Rendering bodys xna/farseer physics

Topics: Developer Forum, Project Management Forum, User Forum
Jan 21, 2011 at 6:09 PM

I use farseer physics 3.2 and xna 4.0.

If i draw simple rectangular body i draw my rectangular texture on body.Position.X, body.Position.Y.

But if I have custom shape, for example:

body2 = BodyFactory.CreateBody(world, new Vector2(0.0f, -150.0f));
Shape[] shape = new Shape[6];
shape[0] = new EdgeShape(Vector2.Zero, new Vector2(100, 100));
shape[1] = new EdgeShape(new Vector2(100, 100), new Vector2(50, 100));
shape[2] = new EdgeShape(new Vector2(50, 100), new Vector2(50, 160));
shape[3] = new EdgeShape(new Vector2(50, 160), new Vector2(0, 160));
shape[4] = new EdgeShape(new Vector2(0, 160), new Vector2(-10, 100));
shape[5] = new EdgeShape(new Vector2(-10, 100), new Vector2(0, 0));
for (int i = 0; i < 6; i++)
{
       body2.CreateFixture(shape[i]);
}



How render this body?
Or what if shape is generated by program, and i need render it?

Jan 21, 2011 at 10:37 PM
Edited Jan 21, 2011 at 10:41 PM

I found that drawing was easiest with an orthographic projection and drawing the shapes with 3d primitives. 

http://msdn.microsoft.com/en-us/library/bb196414.aspx

This site was where I found the most usefull information.

Then when you draw you can just loop over all of the bodies in the world object, then all the fixtures on the body, and then finaly add all of the vertices into the graphics device to draw. The only important thing that you have to worry about is whether or not you wind clockwise, because other wise the xna system does backface culling and your shapes dont show up at all. Also, the translation from the imaginary farseer world to pixels is somewhat tricky because the center of the farseer world is 0,0 while the center of the phone or screen pixels is like 400,240 or whatever. I could post some sample code if you like later if this does not help enough...

If you want to draw a texture, then you can just call an overload on the draw primitive method that maps points of the texture to the points in 3d space. Then it will draw with the vertices at the correct position in your image, and you can cut out parts of the image to fit the farseer body.

Hope this answers your questions!

Jan 22, 2011 at 8:38 AM

Oragamster, thanks a lot.

But I have a couple of questions:

What method draw primitive that maps points of the texture to the points? Is it DrawUserIndexedPrimitives<VertexPositionTexture>(...) ?

And sample code would not prevent.

Developer
Jan 22, 2011 at 2:12 PM

At the moment we draw our objects in the samples in exactly the same way as described by Oragamster. Just have a look at the DebugView and see how rendering is done there. For another approach which uses textures/sprites and the spritebatch just have a look at the HelloWorld Sample in the source control. It demonstrates how to align sprites to physical objects.

Some remarks:

@Dimir: You could just use a loop shape created from a (custom) polygon and add that to your body. It creates edge shapes for each edge of a polygon and links them together automatically. This would yield the same results while at the samte time using fewer fixtures... which is always a good thing ;)

@Oragamster: As the Farseer world does not have any graphical representation per se you can put your center wherever you like. Spritebatch has the point (0,0) in the top left of the screen with y-axis pointing downwards. Internally spritebatch does nothing else than using CreateOrthographicOffCenter(0, [Screen width in pixels], [Screen height in pixels], 0,...). By creating a custom projection matrix via CreateOrthographicOffCenter() you can put your "center" anywhere on the screen.

Regarding the winding order: Culling backfaces may be the default behaviour, but it is easy to change. Just set 

GraphicsDevice.RasterizerState = RasterizerState.CullNone;

and you won't have to bother with the winding order anymore.


Jan 23, 2011 at 5:33 PM

Very cool, I had been working on that system for a while and was beginning to just be frustrated with the many weird things that happened. Also, I did not realise that the system that I used was the same... I found the code in the samples to be confusing, so I just came up with my own. Thanks for the tips!