FP3.0 DebugViewXNA Quastion

Topics: Developer Forum, Project Management Forum, User Forum
Jul 29, 2010 at 7:43 PM
i cant figure out how to use the new debug view. could i get a sample code of how its used. physicsSimulatorView was very helpful in 2.0
Jul 29, 2010 at 11:01 PM
Edited Jul 29, 2010 at 11:04 PM
  public void LoadContent()
        {
            if (_debugViewOn)
            {
                _gamescreen.DebugViewEnabled = true;
                _gamescreen.DebugView.AppendFlags(DebugViewFlags.Shape);
                _gamescreen.DebugView.AppendFlags(DebugViewFlags.AABB);
                _gamescreen.DebugView.AppendFlags(DebugViewFlags.CenterOfMass);
                _gamescreen.DebugView.AppendFlags(DebugViewFlags.Joint);
                _gamescreen.DebugView.AppendFlags(DebugViewFlags.Pair);
            }

            if (_gamescreen.DebugViewEnabled)
                DebugViewXNA.LoadContent(ScreenManager.GraphicsDevice, _content);

            _border = new Border(_world, _size.X, _size.Y, 0.64f);
        }
Then in your Draw():
           if (DebugViewEnabled)
            {
                DebugView.DrawDebugData();
                DebugView.RenderDebugData(ref this.Projection, ref this.View);
            }
You will need to figure out what your View and Projection Matrices are, which depends on your camera/game.
Jul 30, 2010 at 1:47 AM

Thank you it works greate

Aug 17, 2010 at 8:56 PM
I'm trying to get started with FP3.0 and XNA 4.0 (Beta), but DebugViewXNA seems to be broken in XNA 4.0(?) =/
Aug 18, 2010 at 5:11 AM
I haven't played with xna 4 yet. What are the problems? The problem I had with the new DebugView was getting the projection and View matricies in line with what my game camera was doing. Can you describe what you see? If not, we'll have to see is someone else here who has xna 4 experience can chime in.
Aug 18, 2010 at 1:44 PM
He/She means it doesn't compile for XNA 4.0 due to various breaking changes in XNA. Several things changed in XNA 4.0, including various SpriteBatch.Begin() overloads are gone or changed, and I think I heard someone say that blend-state semantics are different. I haven't been able to find solid documentation on the new changes yet, so I'm not sure how to update the debug view to compile/work in XNA 4.0. I need it in a Windows Phone 7 project I'm working on, so if anyone is able to get the FP3 debug view to work in XNA 4.0, please pass the code along (even if it's in rough shape). Currently just running the FP3 base library with my own basic sprite drawing code, but I'm having trouble without the debug view heh.
Aug 18, 2010 at 8:00 PM
Edited Aug 19, 2010 at 8:46 PM

Exactly...

'Microsoft.Xna.Framework.Color' does not contain a constructor that takes 2 arguments

'Microsoft.Xna.Framework.Graphics.GraphicsDevice' does not contain a definition for 'RenderState' and no extension method 'RenderState' accepting a first argument of type 'Microsoft.Xna.Framework.Graphics.GraphicsDevice' could be found (are you missing a using directive or an assembly reference?)

'Microsoft.Xna.Framework.Graphics.GraphicsDevice' does not contain a definition for 'VertexDeclaration' and no extension method 'VertexDeclaration' accepting a first argument of type 'Microsoft.Xna.Framework.Graphics.GraphicsDevice' could be found (are you missing a using directive or an assembly reference?)

'Microsoft.Xna.Framework.Graphics.BasicEffect' does not contain a definition for 'Begin' and no extension method 'Begin' accepting a first argument of type 'Microsoft.Xna.Framework.Graphics.BasicEffect' could be found (are you missing a using directive or an assembly reference?)

'Microsoft.Xna.Framework.Graphics.EffectPass' does not contain a definition for 'End' and no extension method 'End' accepting a first argument of type 'Microsoft.Xna.Framework.Graphics.EffectPass' could be found (are you missing a using directive or an assembly reference?)

The name 'SpriteBlendMode' does not exist in the current context

The name 'SaveStateMode' does not exist in the current context

'Microsoft.Xna.Framework.Graphics.VertexPositionColor' does not contain a definition for 'VertexElements'

'Microsoft.Xna.Framework.Graphics.BasicEffect' does not contain a constructor that takes 2 arguments

http://blogs.msdn.com/b/shawnhar/archive/2010/03/16/breaking-changes-in-xna-game-studio-4-0.aspx

Aug 18, 2010 at 8:12 PM
Also... What's with the missing line breaks?
Aug 18, 2010 at 9:02 PM
Edited Aug 18, 2010 at 9:49 PM

Looks like the lack of line breaks is due to CodePlex not liking FireFox?

Anyway, thanks for the link to the new article. It doesn't necessarily tell you specifics, but it might be enough to figure out where to go:

  • Vertex buffers are now strongly typed, each one having an associated VertexDeclaration. You no longer need to specify a VertexDeclaration before drawing, because this is implicit in your choice of vertex buffer. Vertex buffer sizes are now specified as number of vertices rather than bytes. Replaced GraphicsDevice.Vertices with a new SetVertexBuffer API
    • Looks like this is the source of the these errors:
      • 'Microsoft.Xna.Framework.Graphics.GraphicsDevice' does not contain a definition for 'VertexDeclaration' and no extension method 'VertexDeclaration' accepting a first argument of type 'Microsoft.Xna.Framework.Graphics.GraphicsDevice' could be found (are you missing a using directive or an assembly reference?)
      • 'Microsoft.Xna.Framework.Graphics.VertexPositionColor' does not contain a definition for 'VertexElements'
    • Looks like here is an article about this change:http://blogs.msdn.com/b/shawnhar/archive/2010/04/19/vertex-data-in-xna-game-studio-4-0.aspx
  • Replaced individual graphics renderstates with a new state objects API.
    • Looks like this is the source of these errors:
      • 'Microsoft.Xna.Framework.Graphics.GraphicsDevice' does not contain a definition for 'RenderState' and no extension method 'RenderState' accepting a first argument of type
      • 'Microsoft.Xna.Framework.Graphics.GraphicsDevice' could be found (are you missing a using directive or an assembly reference?)
    • Here is the article describing this change: http://blogs.msdn.com/b/shawnhar/archive/2010/04/02/state-objects-in-xna-game-studio-4-0.aspx
  • Replaced Effect.Begin and End with a new EffectPass.Apply method
    • Looks like this is the source of these errors:
      • 'Microsoft.Xna.Framework.Graphics.BasicEffect' does not contain a definition for 'Begin' and no extension method 'Begin' accepting a first argument of type 'Microsoft.Xna.Framework.Graphics.BasicEffect' could be found (are you missing a using directive or an assembly reference?)
      • 'Microsoft.Xna.Framework.Graphics.EffectPass' does not contain a definition for 'End' and no extension method 'End' accepting a first argument of type 'Microsoft.Xna.Framework.Graphics.EffectPass' could be found (are you missing a using directive or an assembly reference?)
    • Here is an article specifically about this change: http://blogs.msdn.com/b/shawnhar/archive/2010/04/22/effect-api-changes-in-xna-game-studio-4-0.aspx

 

For the Color constructor error, they removed the (Color rgb, float alpha) constructor. Just use the (float r, float g, float b, float alpha) constructor instead, passing the RGB values from the existing color through.

Aug 19, 2010 at 4:36 AM
Edited Aug 19, 2010 at 4:38 AM
Surround your code with the html "pre" tag to get your line breaks back. < pre > code here </ pre> (Without the spaces of course) And yes, Codeplex only plays nice with IE. You get a nice WYSIWYG editor in IE. It's a javascript issue I think.
Aug 19, 2010 at 8:49 PM

Strange...

Now it works fine with Firefox, including the WYSIWYG editor.

Aug 19, 2010 at 9:49 PM

I got a version of DebugViewXNA running. It seems to fill in everything in white instead of gray like the TestBed, so something might be off with the DrawUserPrimitives calls, but it's good enough to use for now.

 

using System;
using System.Collections.Generic;
using System.Diagnostics;
using FarseerPhysics.Collision;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Common;
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.DebugViewXNA
{
	/// <summary>
	/// A debug view that works in XNA.
	/// A debug view shows you what happens inside the physics engine. You can view
	/// bodies, 
	/// </summary>
	public class DebugViewXNA : DebugView, IDisposable
	{
		private static VertexPositionColor[] _vertsLines;
		private static VertexPositionColor[] _vertsFill;
		private static int _lineCount;
		private static int _fillCount;
		private static SpriteBatch _batch;
		private static SpriteFont _font;
		private static GraphicsDevice _device;

		private static List<StringData> _stringData;
		private static VertexDeclaration _vertexDeclaration;
		private static BasicEffect _effect;
		private const int MaxContactPoints = 2048;
		private ContactPoint[] _points = new ContactPoint[MaxContactPoints];
		private int _pointCount;

		public Color InactiveShapeColor = new Color(0.5f, 0.5f, 0.3f);
		public Color StaticShapeColor = new Color(0.5f, 0.9f, 0.5f);
		public Color SleepingShapeColor = new Color(0.6f, 0.6f, 0.6f);
		public Color KinematicShapeColor = new Color(0.5f, 0.5f, 0.9f);
		public Color DefaultShapeColor = new Color(0.9f, 0.7f, 0.7f);
		public Color TextColor = Color.White;

		public struct ContactPoint
		{
			public Vector2 Normal;
			public Vector2 Position;
			public PointState State;
		}

		public DebugViewXNA(World world)
			: base(world)
		{
			_vertsLines = new VertexPositionColor[1000000];
			_vertsFill = new VertexPositionColor[1000000];

			world.ContactManager.PreSolve += PreSolve;

			//Default flags
			AppendFlags(DebugViewFlags.Shape);
			AppendFlags(DebugViewFlags.Joint);
		}

		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);

				WorldManifold worldManifold;
				contact.GetWorldManifold(out worldManifold);

				for (int i = 0; i < manifold.PointCount && _pointCount < MaxContactPoints; ++i)
				{
					if (fixtureA == null)
					{
						_points[i] = new ContactPoint();
					}
					ContactPoint cp = _points[_pointCount];
					cp.Position = worldManifold.Points[i];
					cp.Normal = worldManifold.Normal;
					cp.State = state2[i];
					_points[_pointCount] = cp;
					++_pointCount;
				}
			}
		}

		/// <summary>
		/// Call this to draw shapes and other debug draw data.
		/// </summary>
		public void DrawDebugData()
		{
			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.65f, new Color(0.3f, 0.95f, 0.3f));
					}
					else if (point.State == PointState.Persist)
					{
						// Persist
						DrawPoint(point.Position, 0.65f, 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.DebugPanel) == DebugViewFlags.DebugPanel)
			{
				DrawDebugPanel();
			}

			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.Active == 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.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 (Contact c = World.ContactManager.ContactList; c != null; c = c.Next)
				{
					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.GetCenter();
					Vector2 cB = aabbB.GetCenter();

					DrawSegment(cA, cB, color);
				}
			}

			if ((Flags & DebugViewFlags.AABB) == DebugViewFlags.AABB)
			{
				Color color = new Color(0.9f, 0.3f, 0.9f);
				BroadPhase bp = World.ContactManager.BroadPhase;

				foreach (Body b in World.BodyList)
				{
					if (b.Active == 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);
							Vector2[] vs = new Vector2[4];
							vs[0] = new Vector2(aabb.LowerBound.X, aabb.LowerBound.Y);
							vs[1] = new Vector2(aabb.UpperBound.X, aabb.LowerBound.Y);
							vs[2] = new Vector2(aabb.UpperBound.X, aabb.UpperBound.Y);
							vs[3] = new Vector2(aabb.LowerBound.X, aabb.UpperBound.Y);

							DrawPolygon(ref vs, 4, 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);
				}
			}
		}

		private void DrawDebugPanel()
		{
			DrawString(50, 100, "Bodies: " + World.BodyList.Count);

			//TODO: Is the number of contacts reliable?
			DrawString(50, 115, "Contacts: " + World.ContactCount);
			DrawString(50, 130, "Joints: " + World.JointList.Count);
			DrawString(50, 145, "Proxies: " + World.ProxyCount);
			DrawString(50, 160, "Breakable: " + World.BreakableBodyList.Count);
			DrawString(50, 175, "Controllers: " + World.Controllers.Count);

			DrawString(160, 100, "New contacts: " + World.NewContactsTime);
			DrawString(160, 115, "Controllers: " + World.ControllersUpdateTime);
			DrawString(160, 130, "Contacts: " + World.ContactsUpdateTime);
			DrawString(160, 145, "Solve: " + World.SolveUpdateTime);
			DrawString(160, 160, "CCD: " + World.ContinuousPhysicsTime);
			DrawString(160, 175, "Total: " + World.UpdateTime);
		}

		private void DrawJoint(Joint joint)
		{
			Body b1 = joint.BodyA;
			Body b2 = joint.BodyB;
			Transform xf1, xf2;
			b1.GetTransform(out xf1);

			Vector2 x2 = new Vector2();

			// WIP David
			if (!joint.IsFixedType())
			{
				b2.GetTransform(out xf2);
				x2 = xf2.Position;
			}
			Vector2 p2 = joint.WorldAnchorB;

			Vector2 x1 = xf1.Position;

			Vector2 p1 = joint.WorldAnchorA;

			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:

					FixedMouseJoint fixedMouseJoint = (FixedMouseJoint)joint;
					p1 = fixedMouseJoint.Target;

					DrawPoint(p2, 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, new Vector2(), Color.Red);
					DrawSolidCircle(p1, 0.1f, new Vector2(), Color.Blue);
					break;
				case JointType.FixedRevolute:
					DrawSegment(x1, p1, color);
					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);
					//DrawSegment(x1, p1, color);
					//DrawSegment(p1, p2, color);
					break;
				default:
					DrawSegment(x1, p1, color);
					DrawSegment(p1, p2, color);
					DrawSegment(x2, p2, color);
					break;
			}
		}

		private 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);
						Vector2[] vertices = new Vector2[Settings.MaxPolygonVertices];

						for (int i = 0; i < vertexCount; ++i)
						{
							vertices[i] = MathUtils.Multiply(ref xf, poly.Vertices[i]);
						}

						DrawSolidPolygon(ref vertices, 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.Count;

						Vector2 v1 = MathUtils.Multiply(ref xf, loop.Vertices[count - 1]);
						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(ref Vector2[] vertices, int count, float red, float green, float blue)
		{
			DrawPolygon(ref vertices, count, new Color(red, green, blue));
		}

		public void DrawPolygon(ref Vector2[] vertices, int count, Color color)
		{
			for (int i = 0; i < count - 1; i++)
			{
				_vertsLines[_lineCount * 2].Position = new Vector3(vertices[i], 0.0f);
				_vertsLines[_lineCount * 2].Color = color;
				_vertsLines[_lineCount * 2 + 1].Position = new Vector3(vertices[i + 1], 0.0f);
				_vertsLines[_lineCount * 2 + 1].Color = color;
				_lineCount++;
			}

			_vertsLines[_lineCount * 2].Position = new Vector3(vertices[count - 1], 0.0f);
			_vertsLines[_lineCount * 2].Color = color;
			_vertsLines[_lineCount * 2 + 1].Position = new Vector3(vertices[0], 0.0f);
			_vertsLines[_lineCount * 2 + 1].Color = color;
			_lineCount++;
		}

		public override void DrawSolidPolygon(ref Vector2[] vertices, int count, float red, float green, float blue)
		{
			DrawSolidPolygon(ref vertices, count, new Color(red, green, blue), true);
		}

		public void DrawSolidPolygon(ref Vector2[] vertices, int count, Color color)
		{
			DrawSolidPolygon(ref vertices, count, color, true);
		}

		public void DrawSolidPolygon(ref Vector2[] vertices, int count, Color color, bool outline)
		{
			if (count == 2)
			{
				DrawPolygon(ref vertices, count, color);
				return;
			}

			Color colorFill = new Color(color.R, color.G, color.B, outline ? 0.5f : 1.0f);

			for (int i = 1; i < count - 1; i++)
			{
				_vertsFill[_fillCount * 3].Position = new Vector3(vertices[0], 0.0f);
				_vertsFill[_fillCount * 3].Color = colorFill;

				_vertsFill[_fillCount * 3 + 1].Position = new Vector3(vertices[i], 0.0f);
				_vertsFill[_fillCount * 3 + 1].Color = colorFill;

				_vertsFill[_fillCount * 3 + 2].Position = new Vector3(vertices[i + 1], 0.0f);
				_vertsFill[_fillCount * 3 + 2].Color = colorFill;

				_fillCount++;
			}

			if (outline)
			{
				DrawPolygon(ref 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)
		{
			const int segments = 32;
			const double increment = Math.PI * 2.0 / segments;
			double theta = 0.0;

			for (int i = 0; i < segments; 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));

				_vertsLines[_lineCount * 2].Position = new Vector3(v1, 0.0f);
				_vertsLines[_lineCount * 2].Color = color;
				_vertsLines[_lineCount * 2 + 1].Position = new Vector3(v2, 0.0f);
				_vertsLines[_lineCount * 2 + 1].Color = color;
				_lineCount++;

				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)
		{
			const int segments = 32;
			const double increment = Math.PI * 2.0 / segments;
			double theta = 0.0;

			Color colorFill = new Color(color.R, color.G, color.B, 0.5f);

			Vector2 v0 = center + radius * new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta));
			theta += increment;

			for (int i = 1; i < segments - 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));

				_vertsFill[_fillCount * 3].Position = new Vector3(v0, 0.0f);
				_vertsFill[_fillCount * 3].Color = colorFill;

				_vertsFill[_fillCount * 3 + 1].Position = new Vector3(v1, 0.0f);
				_vertsFill[_fillCount * 3 + 1].Color = colorFill;

				_vertsFill[_fillCount * 3 + 2].Position = new Vector3(v2, 0.0f);
				_vertsFill[_fillCount * 3 + 2].Color = colorFill;

				_fillCount++;

				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)
		{
			_vertsLines[_lineCount * 2].Position = new Vector3(start, 0.0f);
			_vertsLines[_lineCount * 2 + 1].Position = new Vector3(end, 0.0f);
			_vertsLines[_lineCount * 2].Color = _vertsLines[_lineCount * 2 + 1].Color = color;
			_lineCount++;
		}

		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(ref 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 RenderDebugData(ref Matrix projection)
		{
			// set the cull mode? should be unnecessary
			//_device.RenderState.CullMode = CullMode.None;
			_device.RasterizerState = RasterizerState.CullNone;

			// turn alpha blending on
			//_device.RenderState.AlphaBlendEnable = true;
			_device.BlendState = BlendState.AlphaBlend;

			// set the vertex declaration...this ensures if window resizes occur...rendering continues ;)
			//_device.VertexDeclaration = _vertexDeclaration;

			// set the effects projection matrix
			_effect.Projection = projection;

			// begin the effect
			//_effect.Begin();

			// we should have only 1 technique and 1 pass
			_effect.Techniques[0].Passes[0].Apply();

			// make sure we have stuff to draw
			if (_fillCount > 0)
				_device.DrawUserPrimitives(PrimitiveType.TriangleList, _vertsFill, 0, _fillCount);

			// make sure we have lines to draw
			if (_lineCount > 0)
				_device.DrawUserPrimitives(PrimitiveType.LineList, _vertsLines, 0, _lineCount);

			// end the pass and effect
			//_effect.Techniques[0].Passes[0].End();
			//_effect.End();

			// begin the sprite batch effect
			//_batch.Begin(SpriteBlendMode.AlphaBlend, 
			//  SpriteSortMode.Deferred, 
			//  SaveStateMode.None, 
			//  Matrix.Identity);
			_batch.Begin(SpriteSortMode.Deferred,
				BlendState.AlphaBlend,
				null, null, null, null,
				Matrix.Identity);

			// 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, _stringData[i].Y), _stringData[i].Color);
			}
			// end the sprite batch effect
			_batch.End();

			_stringData.Clear();
			_lineCount = _fillCount = 0;
		}

		public void RenderDebugData(ref Matrix projection, ref Matrix view)
		{
			_effect.View = view;
			RenderDebugData(ref projection);
		}

		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(ref verts, 4, color);
		}

		public static void LoadContent(GraphicsDevice device, ContentManager content)
		{
			// Create a new SpriteBatch, which can be used to draw textures.
			_batch = new SpriteBatch(device);
			_font = content.Load<SpriteFont>("font");
			//_vertexDeclaration = new VertexDeclaration(device, VertexPositionColor.VertexElements);
			_device = device;
			_effect = new BasicEffect(device);
			_effect.VertexColorEnabled = true;
			_stringData = new List<StringData>();
		}

		public void Dispose()
		{
			World.ContactManager.PreSolve -= PreSolve;
		}

		#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)
			{
				X = x;
				Y = y;
				S = s;
				Args = args;
				Color = new Color(0.9f, 0.6f, 0.6f);
			}

			public StringData(int x, int y, string s, object[] args, Color color)
			{
				X = x;
				Y = y;
				S = s;
				Args = args;
				Color = color;
			}
		}

		#endregion
	}
}
Aug 20, 2010 at 11:47 AM

Thanks JeroMiya! =)

Aug 20, 2010 at 12:33 PM

I think the Effect isn't working somehow - thus the white. I'll take a look at it and see if I can figure out a fix.