Polygon Centering Problem

Topics: Developer Forum, User Forum
May 30, 2008 at 8:03 PM
Hi,
I've been having problems getting polygon collision to work.  Here's the problem.

I've got a bitmap of a sprite I want to use in a game.  The sprite is best represented as a polygon.  The dimensions are 56x40, so when defined the coordinates, I subtracted 28x20 from them so the center is at 0,0.  I know the center of the polygon and the center of mass are different things.

When I run the game, the geometry is a bit off center.  It would penetrate a few pixels into other objects before colliding.  Sure enough, when I checked the geometry's LocalVertices property, Farseer went ahead and repositioned the vertices so that the center of mass is at 0,0.  In fact, even if I hadn't subtracted 28x20 from each vertex, Farseer automatically calculates the new positions for me.

Is there a way to prevent this behavior and force Farseer to use the vertices I've provided?

Here is some relevant code.  Thanks!

Vertices vertices = new Vertices(new Vector2[] { 
    new Vector2(27f, 20f),
    new Vector2(27f, 6f),
    new Vector2(19f, -10f),
    new Vector2(-5f, -10f),
    new Vector2(-8f, -20f),
    new Vector2(-16f, -20f),
    new Vector2(-19f, -11f),
    new Vector2(-25f, -11f),
    new Vector2(-28f, -6f),
    new Vector2(-28f, 20f)
});

//game.Physics is a PhysicsSimulator
Body body = BodyFactory.Instance.CreateBody(game.Physics, 100f, vertices.GetMomentOfInertia());
Geom geom = GeomFactory.Instance.CreatePolygonGeom(game.Physics, body, vertices, 0f);

May 31, 2008 at 12:04 AM
Ok, now, I'm not sure if this problem is related to Farseer automatically calculating the center of mass for me.  I get these values for geom.LocalVertices:

+  [0] {X:29.20031 Y:15.93663} FarseerGames.FarseerPhysics.Mathematics.Vector2
+  [1] {X:29.20031 Y:1.936629} FarseerGames.FarseerPhysics.Mathematics.Vector2
+  [2] {X:21.20031 Y:-14.06337} FarseerGames.FarseerPhysics.Mathematics.Vector2
+  [3] {X:-2.799686 Y:-14.06337} FarseerGames.FarseerPhysics.Mathematics.Vector2
+  [4] {X:-5.799686 Y:-24.06337} FarseerGames.FarseerPhysics.Mathematics.Vector2
+  [5] {X:-13.79969 Y:-24.06337} FarseerGames.FarseerPhysics.Mathematics.Vector2
+  [6] {X:-16.79969 Y:-15.06337} FarseerGames.FarseerPhysics.Mathematics.Vector2
+  [7] {X:-22.79969 Y:-15.06337} FarseerGames.FarseerPhysics.Mathematics.Vector2
+  [8] {X:-25.79969 Y:-10.06337} FarseerGames.FarseerPhysics.Mathematics.Vector2
+  [9] {X:-25.79969 Y:15.93663} FarseerGames.FarseerPhysics.Mathematics.Vector2

That's roughly (+2.2, -4.1) off center.  If I evaluate vertices.GetCentroid() and geom.LocalVertices.GetCentroid(), I get (0,0).

Why is this offset happening?

May 31, 2008 at 12:43 AM
Edited May 31, 2008 at 12:44 AM
... edit... double post.

Jun 2, 2008 at 4:48 PM
I had a terrible time getting my sprites to line up with my bodies at the beginning.  What I was doing was:
1) Create Vertices collection
2) CreatePolygonBody with Verts
3) CreatePolygonGeom with Verts
4) Create Sprite, and use Verts.GetCentroid to offset since my sprite draws from 0,0 and the Body is positioned by the axis.

This would cause everything to get crazy.  I also kept getting Verts.GetCentroid = 0.  What happened was when you create a new polygon Geom, the Vertices collection gets translated by the result of GetCentroid which will always results in 0,0.  So I just changed my steps so that after I created my Vertices Collection I computed the GetCentroid immediately and used that value when I created my sprite.

1) Create Vertices collection
2) Create Sprite, and use Verts.GetCentroid to offset since my sprite draws from 0,0 and the Body is positioned by the axis.
3) CreatePolygonBody with Verts
4) CreatePolygonGeom with Verts
Hope that helps.
Jun 2, 2008 at 10:59 PM
Edited Jun 3, 2008 at 1:26 AM
Thanks DDtMM for the suggestion.

I didn't realize that Farseer was actually modifying my Vertices collection when I supply it as an argument to create a new Geom (doesn't really make sense).

I think I might have solved the offsetting problem, but it turns out I might have other problems with polygon collision.  My shape above is basically a rectangle, but one of the edges has lots of jagged parts.  That edge seems to be causing Farseer a lot of problems.  I've tried experimenting with the collision cell size but without much luck.  The edge seems to protrude several pixels more than it should, and sometimes does not collide with other non-static objects.

Perhaps Farseer has problems with concave polygons.  I've tried simplifying the shape and it does look like concave polygons (even simple ones with 5 edges) have problems.

Has anyone had any success with concave polygons?
Jun 3, 2008 at 3:01 PM
I've had some issues as well. I created two concave semi-circles to act as circular bounds, and with a low vertex count I got a lot of interpenetration and strange/unreliable behavior. After bumping up the number of vertices in the concave region things became acceptable. While some of this is to be expected, I think there might be an underlying cause we are missing.
Jun 3, 2008 at 5:28 PM
Try doing Vertices.SubDivideVerts(smallNumber).  I'm pretty new to Farseer, but it seems to be a bit of an artform getting settings right.  In the game that I am writing now I have mostly funky objects that the space between verts is large.  But, for my main objects, like the player object, I do a subdivideverts with a parameter of 2.  This seems to work well with the collision detection.
Jun 7, 2008 at 3:06 AM
Thanks everyone for their responses.  I'm really loving this engine (when I'm not trying to wrestle with these issues).

I think most of my problems in this thread have been resolved following DDtMM's suggestion.  Unfortunately, it did mess up my code a fair bit as I never expected to have to add a little hack to counter-act what Farseer was doing when I supplied my own vertices.  Originally, I used a rectangle to display the sprite while Farseer would treat the same entity as a polygon.  I couldn't for the life of me figure out how to offset the rectangle without resulting in some bizarre WPF behavior.  So I ended up creating a 4 sided WPF polygon to replace the rectangle.  For some reason, that seemed to work, and I can control exactly where the points go.

I also ended up resolving the issue with the concave polygons too - but I have no idea how.  Maybe the mispositioned sprite was messing with me.  Once I had the position spot-on, I could see Farseer doing the collisions correctly.

This is a really great engine.  However, it woud be great if there was some more documentation.  The next thing I'm going to mess with is collision callbacks and how I can determine certain properties of the collision (like the impact velocity, impulse etc...).  Looks like I'll be spending a bit of time searching through these forums.