123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875 |
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Linq;
- using FarseerPhysics.Collision;
- using FarseerPhysics.Collision.Shapes;
- using FarseerPhysics.Common;
- using FarseerPhysics.Controllers;
- using FarseerPhysics.Dynamics;
- using FarseerPhysics.Dynamics.Contacts;
- using FarseerPhysics.Dynamics.Joints;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Content;
- using Microsoft.Xna.Framework.Graphics;
- namespace FarseerPhysics.DebugViews
- {
- /// <summary>
- /// A debug view that works in XNA.
- /// A debug view shows you what happens inside the physics engine. You can view
- /// bodies, joints, fixtures and more.
- /// </summary>
- public class DebugViewXNA : DebugView, IDisposable
- {
- //Drawing
- private PrimitiveBatch _primitiveBatch;
- private SpriteBatch _batch;
- private SpriteFont _font;
- private GraphicsDevice _device;
- private Vector2[] _tempVertices = new Vector2[Settings.MaxPolygonVertices];
- private List<StringData> _stringData;
- private Matrix _localProjection;
- private Matrix _localView;
- //Shapes
- public Color DefaultShapeColor = new Color(0.9f, 0.7f, 0.7f);
- public Color InactiveShapeColor = new Color(0.5f, 0.5f, 0.3f);
- public Color KinematicShapeColor = new Color(0.5f, 0.5f, 0.9f);
- public Color SleepingShapeColor = new Color(0.6f, 0.6f, 0.6f);
- public Color StaticShapeColor = new Color(0.5f, 0.9f, 0.5f);
- public Color TextColor = Color.White;
- //Contacts
- private int _pointCount;
- private const int MaxContactPoints = 2048;
- private ContactPoint[] _points = new ContactPoint[MaxContactPoints];
- //Debug panel
- #if XBOX
- public Vector2 DebugPanelPosition = new Vector2(55, 100);
- #else
- public Vector2 DebugPanelPosition = new Vector2(40, 100);
- #endif
- private int _max;
- private int _avg;
- private int _min;
- //Performance graph
- public bool AdaptiveLimits = true;
- public int ValuesToGraph = 500;
- public int MinimumValue;
- public int MaximumValue = 1000;
- private List<float> _graphValues = new List<float>();
- #if XBOX
- public Rectangle PerformancePanelBounds = new Rectangle(265, 100, 200, 100);
- #else
- public Rectangle PerformancePanelBounds = new Rectangle(250, 100, 200, 100);
- #endif
- private Vector2[] _background = new Vector2[4];
- public bool Enabled = true;
- #if XBOX || WINDOWS_PHONE
- public const int CircleSegments = 16;
- #else
- public const int CircleSegments = 32;
- #endif
- public DebugViewXNA(World world)
- : base(world)
- {
- world.ContactManager.PreSolve += PreSolve;
- //Default flags
- AppendFlags(DebugViewFlags.Shape);
- AppendFlags(DebugViewFlags.Controllers);
- AppendFlags(DebugViewFlags.Joint);
- }
- public void BeginCustomDraw(ref Matrix projection, ref Matrix view)
- {
- _primitiveBatch.Begin(ref projection, ref view);
- }
- public void EndCustomDraw()
- {
- _primitiveBatch.End();
- }
- #region IDisposable Members
- public void Dispose()
- {
- World.ContactManager.PreSolve -= PreSolve;
- }
- #endregion
- private void PreSolve(Contact contact, ref Manifold oldManifold)
- {
- if ((Flags & DebugViewFlags.ContactPoints) == DebugViewFlags.ContactPoints)
- {
- Manifold manifold = contact.Manifold;
- if (manifold.PointCount == 0)
- {
- return;
- }
- Fixture fixtureA = contact.FixtureA;
- FixedArray2<PointState> state1, state2;
- Collision.Collision.GetPointStates(out state1, out state2, ref oldManifold, ref manifold);
- FixedArray2<Vector2> points;
- Vector2 normal;
- contact.GetWorldManifold(out normal, out points);
- for (int i = 0; i < manifold.PointCount && _pointCount < MaxContactPoints; ++i)
- {
- if (fixtureA == null)
- {
- _points[i] = new ContactPoint();
- }
- ContactPoint cp = _points[_pointCount];
- cp.Position = points[i];
- cp.Normal = normal;
- cp.State = state2[i];
- _points[_pointCount] = cp;
- ++_pointCount;
- }
- }
- }
- /// <summary>
- /// Call this to draw shapes and other debug draw data.
- /// </summary>
- private void DrawDebugData()
- {
- if ((Flags & DebugViewFlags.Shape) == DebugViewFlags.Shape)
- {
- foreach (Body b in World.BodyList)
- {
- Transform xf;
- b.GetTransform(out xf);
- foreach (Fixture f in b.FixtureList)
- {
- if (b.Enabled == false)
- {
- DrawShape(f, xf, InactiveShapeColor);
- }
- else if (b.BodyType == BodyType.Static)
- {
- DrawShape(f, xf, StaticShapeColor);
- }
- else if (b.BodyType == BodyType.Kinematic)
- {
- DrawShape(f, xf, KinematicShapeColor);
- }
- else if (b.Awake == false)
- {
- DrawShape(f, xf, SleepingShapeColor);
- }
- else
- {
- DrawShape(f, xf, DefaultShapeColor);
- }
- }
- }
- }
- if ((Flags & DebugViewFlags.ContactPoints) == DebugViewFlags.ContactPoints)
- {
- const float axisScale = 0.3f;
- for (int i = 0; i < _pointCount; ++i)
- {
- ContactPoint point = _points[i];
- if (point.State == PointState.Add)
- {
- // Add
- DrawPoint(point.Position, 0.1f, new Color(0.3f, 0.95f, 0.3f));
- }
- else if (point.State == PointState.Persist)
- {
- // Persist
- DrawPoint(point.Position, 0.1f, new Color(0.3f, 0.3f, 0.95f));
- }
- if ((Flags & DebugViewFlags.ContactNormals) == DebugViewFlags.ContactNormals)
- {
- Vector2 p1 = point.Position;
- Vector2 p2 = p1 + axisScale * point.Normal;
- DrawSegment(p1, p2, new Color(0.4f, 0.9f, 0.4f));
- }
- }
- _pointCount = 0;
- }
- if ((Flags & DebugViewFlags.PolygonPoints) == DebugViewFlags.PolygonPoints)
- {
- foreach (Body body in World.BodyList)
- {
- foreach (Fixture f in body.FixtureList)
- {
- PolygonShape polygon = f.Shape as PolygonShape;
- if (polygon != null)
- {
- Transform xf;
- body.GetTransform(out xf);
- for (int i = 0; i < polygon.Vertices.Count; i++)
- {
- Vector2 tmp = MathUtils.Multiply(ref xf, polygon.Vertices[i]);
- DrawPoint(tmp, 0.1f, Color.Red);
- }
- }
- }
- }
- }
- if ((Flags & DebugViewFlags.Joint) == DebugViewFlags.Joint)
- {
- foreach (Joint j in World.JointList)
- {
- DrawJoint(j);
- }
- }
- if ((Flags & DebugViewFlags.Pair) == DebugViewFlags.Pair)
- {
- Color color = new Color(0.3f, 0.9f, 0.9f);
- for (int i = 0; i < World.ContactManager.ContactList.Count; i++)
- {
- Contact c = World.ContactManager.ContactList[i];
- Fixture fixtureA = c.FixtureA;
- Fixture fixtureB = c.FixtureB;
- AABB aabbA;
- fixtureA.GetAABB(out aabbA, 0);
- AABB aabbB;
- fixtureB.GetAABB(out aabbB, 0);
- Vector2 cA = aabbA.Center;
- Vector2 cB = aabbB.Center;
- DrawSegment(cA, cB, color);
- }
- }
- if ((Flags & DebugViewFlags.AABB) == DebugViewFlags.AABB)
- {
- Color color = new Color(0.9f, 0.3f, 0.9f);
- IBroadPhase bp = World.ContactManager.BroadPhase;
- foreach (Body b in World.BodyList)
- {
- if (b.Enabled == false)
- {
- continue;
- }
- foreach (Fixture f in b.FixtureList)
- {
- for (int t = 0; t < f.ProxyCount; ++t)
- {
- FixtureProxy proxy = f.Proxies[t];
- AABB aabb;
- bp.GetFatAABB(proxy.ProxyId, out aabb);
- DrawAABB(ref aabb, color);
- }
- }
- }
- }
- if ((Flags & DebugViewFlags.CenterOfMass) == DebugViewFlags.CenterOfMass)
- {
- foreach (Body b in World.BodyList)
- {
- Transform xf;
- b.GetTransform(out xf);
- xf.Position = b.WorldCenter;
- DrawTransform(ref xf);
- }
- }
- if ((Flags & DebugViewFlags.Controllers) == DebugViewFlags.Controllers)
- {
- for (int i = 0; i < World.ControllerList.Count; i++)
- {
- Controller controller = World.ControllerList[i];
- BuoyancyController buoyancy = controller as BuoyancyController;
- if (buoyancy != null)
- {
- AABB container = buoyancy.Container;
- DrawAABB(ref container, Color.LightBlue);
- }
- }
- }
- if ((Flags & DebugViewFlags.DebugPanel) == DebugViewFlags.DebugPanel)
- {
- DrawDebugPanel();
- }
- }
- private void DrawPerformanceGraph()
- {
- _graphValues.Add(World.UpdateTime);
- if (_graphValues.Count > ValuesToGraph + 1)
- _graphValues.RemoveAt(0);
- float x = PerformancePanelBounds.X;
- float deltaX = PerformancePanelBounds.Width / (float)ValuesToGraph;
- float yScale = PerformancePanelBounds.Bottom - (float)PerformancePanelBounds.Top;
- // we must have at least 2 values to start rendering
- if (_graphValues.Count > 2)
- {
- _max = (int)_graphValues.Max();
- _avg = (int)_graphValues.Average();
- _min = (int)_graphValues.Min();
- if (AdaptiveLimits)
- {
- MaximumValue = _max;
- MinimumValue = 0;
- }
- // start at last value (newest value added)
- // continue until no values are left
- for (int i = _graphValues.Count - 1; i > 0; i--)
- {
- float y1 = PerformancePanelBounds.Bottom -
- ((_graphValues[i] / (MaximumValue - MinimumValue)) * yScale);
- float y2 = PerformancePanelBounds.Bottom -
- ((_graphValues[i - 1] / (MaximumValue - MinimumValue)) * yScale);
- Vector2 x1 =
- new Vector2(MathHelper.Clamp(x, PerformancePanelBounds.Left, PerformancePanelBounds.Right),
- MathHelper.Clamp(y1, PerformancePanelBounds.Top, PerformancePanelBounds.Bottom));
- Vector2 x2 =
- new Vector2(
- MathHelper.Clamp(x + deltaX, PerformancePanelBounds.Left, PerformancePanelBounds.Right),
- MathHelper.Clamp(y2, PerformancePanelBounds.Top, PerformancePanelBounds.Bottom));
- DrawSegment(x1, x2, Color.LightGreen);
- x += deltaX;
- }
- }
- DrawString(PerformancePanelBounds.Right + 10, PerformancePanelBounds.Top, "Max: " + _max);
- DrawString(PerformancePanelBounds.Right + 10, PerformancePanelBounds.Center.Y - 7, "Avg: " + _avg);
- DrawString(PerformancePanelBounds.Right + 10, PerformancePanelBounds.Bottom - 15, "Min: " + _min);
- //Draw background.
- _background[0] = new Vector2(PerformancePanelBounds.X, PerformancePanelBounds.Y);
- _background[1] = new Vector2(PerformancePanelBounds.X,
- PerformancePanelBounds.Y + PerformancePanelBounds.Height);
- _background[2] = new Vector2(PerformancePanelBounds.X + PerformancePanelBounds.Width,
- PerformancePanelBounds.Y + PerformancePanelBounds.Height);
- _background[3] = new Vector2(PerformancePanelBounds.X + PerformancePanelBounds.Width,
- PerformancePanelBounds.Y);
- DrawSolidPolygon(_background, 4, Color.DarkGray, true);
- }
- private void DrawDebugPanel()
- {
- int fixtures = 0;
- for (int i = 0; i < World.BodyList.Count; i++)
- {
- fixtures += World.BodyList[i].FixtureList.Count;
- }
- int x = (int)DebugPanelPosition.X;
- int y = (int)DebugPanelPosition.Y;
- DrawString(x, y, "Objects:" +
- "\n- Bodies: " + World.BodyList.Count +
- "\n- Fixtures: " + fixtures +
- "\n- Contacts: " + World.ContactList.Count +
- "\n- Joints: " + World.JointList.Count +
- "\n- Controllers: " + World.ControllerList.Count +
- "\n- Proxies: " + World.ProxyCount);
- DrawString(x + 110, y, "Update time:" +
- "\n- Body: " + World.SolveUpdateTime +
- "\n- Contact: " + World.ContactsUpdateTime +
- "\n- CCD: " + World.ContinuousPhysicsTime +
- "\n- Joint: " + World.Island.JointUpdateTime +
- "\n- Controller: " + World.ControllersUpdateTime +
- "\n- Total: " + World.UpdateTime);
- }
- public void DrawAABB(ref AABB aabb, Color color)
- {
- Vector2[] verts = new Vector2[4];
- verts[0] = new Vector2(aabb.LowerBound.X, aabb.LowerBound.Y);
- verts[1] = new Vector2(aabb.UpperBound.X, aabb.LowerBound.Y);
- verts[2] = new Vector2(aabb.UpperBound.X, aabb.UpperBound.Y);
- verts[3] = new Vector2(aabb.LowerBound.X, aabb.UpperBound.Y);
- DrawPolygon(verts, 4, color);
- }
- private void DrawJoint(Joint joint)
- {
- if (!joint.Enabled)
- return;
- Body b1 = joint.BodyA;
- Body b2 = joint.BodyB;
- Transform xf1, xf2;
- b1.GetTransform(out xf1);
- Vector2 x2 = Vector2.Zero;
- // WIP David
- if (!joint.IsFixedType())
- {
- b2.GetTransform(out xf2);
- x2 = xf2.Position;
- }
- Vector2 p1 = joint.WorldAnchorA;
- Vector2 p2 = joint.WorldAnchorB;
- Vector2 x1 = xf1.Position;
- Color color = new Color(0.5f, 0.8f, 0.8f);
- switch (joint.JointType)
- {
- case JointType.Distance:
- DrawSegment(p1, p2, color);
- break;
- case JointType.Pulley:
- PulleyJoint pulley = (PulleyJoint)joint;
- Vector2 s1 = pulley.GroundAnchorA;
- Vector2 s2 = pulley.GroundAnchorB;
- DrawSegment(s1, p1, color);
- DrawSegment(s2, p2, color);
- DrawSegment(s1, s2, color);
- break;
- case JointType.FixedMouse:
- DrawPoint(p1, 0.5f, new Color(0.0f, 1.0f, 0.0f));
- DrawSegment(p1, p2, new Color(0.8f, 0.8f, 0.8f));
- break;
- case JointType.Revolute:
- //DrawSegment(x2, p1, color);
- DrawSegment(p2, p1, color);
- DrawSolidCircle(p2, 0.1f, Vector2.Zero, Color.Red);
- DrawSolidCircle(p1, 0.1f, Vector2.Zero, Color.Blue);
- break;
- case JointType.FixedAngle:
- //Should not draw anything.
- break;
- case JointType.FixedRevolute:
- DrawSegment(x1, p1, color);
- DrawSolidCircle(p1, 0.1f, Vector2.Zero, Color.Pink);
- break;
- case JointType.FixedLine:
- DrawSegment(x1, p1, color);
- DrawSegment(p1, p2, color);
- break;
- case JointType.FixedDistance:
- DrawSegment(x1, p1, color);
- DrawSegment(p1, p2, color);
- break;
- case JointType.FixedPrismatic:
- DrawSegment(x1, p1, color);
- DrawSegment(p1, p2, color);
- break;
- case JointType.Gear:
- DrawSegment(x1, x2, color);
- break;
- //case JointType.Weld:
- // break;
- default:
- DrawSegment(x1, p1, color);
- DrawSegment(p1, p2, color);
- DrawSegment(x2, p2, color);
- break;
- }
- }
- public void DrawShape(Fixture fixture, Transform xf, Color color)
- {
- switch (fixture.ShapeType)
- {
- case ShapeType.Circle:
- {
- CircleShape circle = (CircleShape)fixture.Shape;
- Vector2 center = MathUtils.Multiply(ref xf, circle.Position);
- float radius = circle.Radius;
- Vector2 axis = xf.R.Col1;
- DrawSolidCircle(center, radius, axis, color);
- }
- break;
- case ShapeType.Polygon:
- {
- PolygonShape poly = (PolygonShape)fixture.Shape;
- int vertexCount = poly.Vertices.Count;
- Debug.Assert(vertexCount <= Settings.MaxPolygonVertices);
- for (int i = 0; i < vertexCount; ++i)
- {
- _tempVertices[i] = MathUtils.Multiply(ref xf, poly.Vertices[i]);
- }
- DrawSolidPolygon(_tempVertices, vertexCount, color);
- }
- break;
- case ShapeType.Edge:
- {
- EdgeShape edge = (EdgeShape)fixture.Shape;
- Vector2 v1 = MathUtils.Multiply(ref xf, edge.Vertex1);
- Vector2 v2 = MathUtils.Multiply(ref xf, edge.Vertex2);
- DrawSegment(v1, v2, color);
- }
- break;
- case ShapeType.Loop:
- {
- LoopShape loop = (LoopShape)fixture.Shape;
- int count = loop.Vertices.Count;
- Vector2 v1 = MathUtils.Multiply(ref xf, loop.Vertices[count - 1]);
- DrawCircle(v1, 0.05f, color);
- for (int i = 0; i < count; ++i)
- {
- Vector2 v2 = MathUtils.Multiply(ref xf, loop.Vertices[i]);
- DrawSegment(v1, v2, color);
- v1 = v2;
- }
- }
- break;
- }
- }
- public override void DrawPolygon(Vector2[] vertices, int count, float red, float green, float blue)
- {
- DrawPolygon(vertices, count, new Color(red, green, blue));
- }
- public void DrawPolygon(Vector2[] vertices, int count, Color color)
- {
- if (!_primitiveBatch.IsReady())
- {
- throw new InvalidOperationException("BeginCustomDraw must be called before drawing anything.");
- }
- for (int i = 0; i < count - 1; i++)
- {
- _primitiveBatch.AddVertex(vertices[i], color, PrimitiveType.LineList);
- _primitiveBatch.AddVertex(vertices[i + 1], color, PrimitiveType.LineList);
- }
- _primitiveBatch.AddVertex(vertices[count - 1], color, PrimitiveType.LineList);
- _primitiveBatch.AddVertex(vertices[0], color, PrimitiveType.LineList);
- }
- public override void DrawSolidPolygon(Vector2[] vertices, int count, float red, float green, float blue)
- {
- DrawSolidPolygon(vertices, count, new Color(red, green, blue), true);
- }
- public void DrawSolidPolygon(Vector2[] vertices, int count, Color color)
- {
- DrawSolidPolygon(vertices, count, color, true);
- }
- public void DrawSolidPolygon(Vector2[] vertices, int count, Color color, bool outline)
- {
- if (!_primitiveBatch.IsReady())
- {
- throw new InvalidOperationException("BeginCustomDraw must be called before drawing anything.");
- }
- if (count == 2)
- {
- DrawPolygon(vertices, count, color);
- return;
- }
- Color colorFill = color * (outline ? 0.5f : 1.0f);
- for (int i = 1; i < count - 1; i++)
- {
- _primitiveBatch.AddVertex(vertices[0], colorFill, PrimitiveType.TriangleList);
- _primitiveBatch.AddVertex(vertices[i], colorFill, PrimitiveType.TriangleList);
- _primitiveBatch.AddVertex(vertices[i + 1], colorFill, PrimitiveType.TriangleList);
- }
- if (outline)
- {
- DrawPolygon(vertices, count, color);
- }
- }
- public override void DrawCircle(Vector2 center, float radius, float red, float green, float blue)
- {
- DrawCircle(center, radius, new Color(red, green, blue));
- }
- public void DrawCircle(Vector2 center, float radius, Color color)
- {
- if (!_primitiveBatch.IsReady())
- {
- throw new InvalidOperationException("BeginCustomDraw must be called before drawing anything.");
- }
- const double increment = Math.PI * 2.0 / CircleSegments;
- double theta = 0.0;
- for (int i = 0; i < CircleSegments; i++)
- {
- Vector2 v1 = center + radius * new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta));
- Vector2 v2 = center +
- radius *
- new Vector2((float)Math.Cos(theta + increment), (float)Math.Sin(theta + increment));
- _primitiveBatch.AddVertex(v1, color, PrimitiveType.LineList);
- _primitiveBatch.AddVertex(v2, color, PrimitiveType.LineList);
- theta += increment;
- }
- }
- public override void DrawSolidCircle(Vector2 center, float radius, Vector2 axis, float red, float green,
- float blue)
- {
- DrawSolidCircle(center, radius, axis, new Color(red, green, blue));
- }
- public void DrawSolidCircle(Vector2 center, float radius, Vector2 axis, Color color)
- {
- if (!_primitiveBatch.IsReady())
- {
- throw new InvalidOperationException("BeginCustomDraw must be called before drawing anything.");
- }
- const double increment = Math.PI * 2.0 / CircleSegments;
- double theta = 0.0;
- Color colorFill = color * 0.5f;
- Vector2 v0 = center + radius * new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta));
- theta += increment;
- for (int i = 1; i < CircleSegments - 1; i++)
- {
- Vector2 v1 = center + radius * new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta));
- Vector2 v2 = center +
- radius *
- new Vector2((float)Math.Cos(theta + increment), (float)Math.Sin(theta + increment));
- _primitiveBatch.AddVertex(v0, colorFill, PrimitiveType.TriangleList);
- _primitiveBatch.AddVertex(v1, colorFill, PrimitiveType.TriangleList);
- _primitiveBatch.AddVertex(v2, colorFill, PrimitiveType.TriangleList);
- theta += increment;
- }
- DrawCircle(center, radius, color);
- DrawSegment(center, center + axis * radius, color);
- }
- public override void DrawSegment(Vector2 start, Vector2 end, float red, float green, float blue)
- {
- DrawSegment(start, end, new Color(red, green, blue));
- }
- public void DrawSegment(Vector2 start, Vector2 end, Color color)
- {
- if (!_primitiveBatch.IsReady())
- {
- throw new InvalidOperationException("BeginCustomDraw must be called before drawing anything.");
- }
- _primitiveBatch.AddVertex(start, color, PrimitiveType.LineList);
- _primitiveBatch.AddVertex(end, color, PrimitiveType.LineList);
- }
- public override void DrawTransform(ref Transform transform)
- {
- const float axisScale = 0.4f;
- Vector2 p1 = transform.Position;
- Vector2 p2 = p1 + axisScale * transform.R.Col1;
- DrawSegment(p1, p2, Color.Red);
- p2 = p1 + axisScale * transform.R.Col2;
- DrawSegment(p1, p2, Color.Green);
- }
- public void DrawPoint(Vector2 p, float size, Color color)
- {
- Vector2[] verts = new Vector2[4];
- float hs = size / 2.0f;
- verts[0] = p + new Vector2(-hs, -hs);
- verts[1] = p + new Vector2(hs, -hs);
- verts[2] = p + new Vector2(hs, hs);
- verts[3] = p + new Vector2(-hs, hs);
- DrawSolidPolygon(verts, 4, color, true);
- }
- public void DrawString(int x, int y, string s, params object[] args)
- {
- _stringData.Add(new StringData(x, y, s, args, TextColor));
- }
- public void DrawArrow(Vector2 start, Vector2 end, float length, float width, bool drawStartIndicator,
- Color color)
- {
- // Draw connection segment between start- and end-point
- DrawSegment(start, end, color);
- // Precalculate halfwidth
- float halfWidth = width / 2;
- // Create directional reference
- Vector2 rotation = (start - end);
- rotation.Normalize();
- // Calculate angle of directional vector
- float angle = (float)Math.Atan2(rotation.X, -rotation.Y);
- // Create matrix for rotation
- Matrix rotMatrix = Matrix.CreateRotationZ(angle);
- // Create translation matrix for end-point
- Matrix endMatrix = Matrix.CreateTranslation(end.X, end.Y, 0);
- // Setup arrow end shape
- Vector2[] verts = new Vector2[3];
- verts[0] = new Vector2(0, 0);
- verts[1] = new Vector2(-halfWidth, -length);
- verts[2] = new Vector2(halfWidth, -length);
- // Rotate end shape
- Vector2.Transform(verts, ref rotMatrix, verts);
- // Translate end shape
- Vector2.Transform(verts, ref endMatrix, verts);
- // Draw arrow end shape
- DrawSolidPolygon(verts, 3, color, false);
- if (drawStartIndicator)
- {
- // Create translation matrix for start
- Matrix startMatrix = Matrix.CreateTranslation(start.X, start.Y, 0);
- // Setup arrow start shape
- Vector2[] baseVerts = new Vector2[4];
- baseVerts[0] = new Vector2(-halfWidth, length / 4);
- baseVerts[1] = new Vector2(halfWidth, length / 4);
- baseVerts[2] = new Vector2(halfWidth, 0);
- baseVerts[3] = new Vector2(-halfWidth, 0);
- // Rotate start shape
- Vector2.Transform(baseVerts, ref rotMatrix, baseVerts);
- // Translate start shape
- Vector2.Transform(baseVerts, ref startMatrix, baseVerts);
- // Draw start shape
- DrawSolidPolygon(baseVerts, 4, color, false);
- }
- }
- public void RenderDebugData(ref Matrix projection, ref Matrix view)
- {
- if (!Enabled)
- {
- return;
- }
- //Nothing is enabled - don't draw the debug view.
- if (Flags == 0)
- return;
- _device.RasterizerState = RasterizerState.CullNone;
- _device.DepthStencilState = DepthStencilState.Default;
- _primitiveBatch.Begin(ref projection, ref view);
- DrawDebugData();
- _primitiveBatch.End();
- if ((Flags & DebugViewFlags.PerformanceGraph) == DebugViewFlags.PerformanceGraph)
- {
- _primitiveBatch.Begin(ref _localProjection, ref _localView);
- DrawPerformanceGraph();
- _primitiveBatch.End();
- }
- // begin the sprite batch effect
- _batch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
- // draw any strings we have
- for (int i = 0; i < _stringData.Count; i++)
- {
- _batch.DrawString(_font, string.Format(_stringData[i].S, _stringData[i].Args),
- new Vector2(_stringData[i].X + 1f, _stringData[i].Y + 1f), Color.Black);
- _batch.DrawString(_font, string.Format(_stringData[i].S, _stringData[i].Args),
- new Vector2(_stringData[i].X, _stringData[i].Y), _stringData[i].Color);
- }
- // end the sprite batch effect
- _batch.End();
- _stringData.Clear();
- }
- public void RenderDebugData(ref Matrix projection)
- {
- if (!Enabled)
- {
- return;
- }
- Matrix view = Matrix.Identity;
- RenderDebugData(ref projection, ref view);
- }
- public void LoadContent(GraphicsDevice device, ContentManager content)
- {
- // Create a new SpriteBatch, which can be used to draw textures.
- _device = device;
- _batch = new SpriteBatch(_device);
- _primitiveBatch = new PrimitiveBatch(_device, 1000);
- _font = content.Load<SpriteFont>("font");
- _stringData = new List<StringData>();
- _localProjection = Matrix.CreateOrthographicOffCenter(0f, _device.Viewport.Width, _device.Viewport.Height,
- 0f, 0f, 1f);
- _localView = Matrix.Identity;
- }
- #region Nested type: ContactPoint
- private struct ContactPoint
- {
- public Vector2 Normal;
- public Vector2 Position;
- public PointState State;
- }
- #endregion
- #region Nested type: StringData
- private struct StringData
- {
- public object[] Args;
- public Color Color;
- public string S;
- public int X, Y;
- public StringData(int x, int y, string s, object[] args, Color color)
- {
- X = x;
- Y = y;
- S = s;
- Args = args;
- Color = color;
- }
- }
- #endregion
- }
- }
|