Problems positioning FixtureFactory.CreatePolygon fixture

Oct 24, 2010 at 10:51 PM
Edited Oct 25, 2010 at 12:18 AM

Hey folks,

I am creating my fixtures based on a randomly generated platformer level.  They are static squares and ramps that are grouped into larger fixtures to increase efficiency.  I was having no difficulties creating and placing the rectangles in my world using FixtureFactory.CreateRectangle. 

I am getting positioning errors while when making my ramps with FixtureFactory.CreatePolygon.  My ramps are at a 45 degree angle and so I have a uniform grid system with all my squares and ramps (they all have the same width and height).  The problem is that when I position my ramp into the world they are off to the right a few pixels and as I go further away from the world origin they get increasingly further away from where they should be located. 

I had read that createpolygon doesn't set the center correctly and in a recent post it was suggested to translate the vertices by half the width and height of the object.  This makes the fixture positioned even more incorrectly.  (this may also not matter but...) When setting the center of mass on in debug view the center is in the top left corner instead of the center of the polygon.

Hopefully this screenshot works.

As you can see the rectangles are all aligned on the grid but any polygon with a ramp is offset.  What things could I look at to remedy this?  Posting code isn't really an option due to the complexities of integrating farseer code with my generator.  If desired I could write up some mock code that would be doing the same approximate thing.


Edit: I'm using farseer 3.0

Oct 25, 2010 at 10:06 AM

Rectangles are polygons too. Might be a problem with the calculation of centroid. Could you code up a quick test for the Testbed?

Oct 25, 2010 at 5:08 PM
Edited Oct 25, 2010 at 10:49 PM

After creating my implementation in the testbed everything is lining up and looks good.

I'll have to scour my code much deeper it seems.  I'm starting to suspect a precision error rather than a miscalculation.  This will be lots of fun...


I located the issue after a some more debugging. My calculation was incorrect, I was positioning my vertices in world space instead of in local space. This explains why as the polygons got further from the origin, they got more off.  Bla....


As I mentioned above, the center of mass appears to be set incorrectly (or not at all). Even in the test bed it was wrong.  It seems that it is always at the polygons origin rather then at the center like the polygons from CreateRectangle.  Maybe it isn't supposed to be set, I had just assumed it would be since the other Create calls do this.

Here is the test that I wrote, its a repeating pattern of rectangles and ramps.  When you run it and turn on the center of mass debug, you'll see what I'm talking about.  


using System;
using FarseerPhysics.Collision;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using FarseerPhysics.Common;
using FarseerPhysics.TestBed.Framework;

using Microsoft.Xna.Framework;

namespace FarseerPhysics.TestBed.Tests
    public class RampTest : Test
        public const int TILE_SIZE = 2;
        public const int TILE_HALF_SIZE = TILE_SIZE / 2;

        private Vector2 GlobalPos = new Vector2(-20, 0);
        private int Iterations = 10;

        private RampTest()

            int[] map = new int[6];

            /*      Demo Block
             *   _________________________
             *   |___|___|___|___|___|___|     no slopes ( 6 x 1 ) Tiles
             *   |___|___|__\|___|___|___|     a right slope (3 x 1) and (3 x 1) Tiles
             *   |___|___|___|___|/__|___|     a left slope (4 x 1) and (2 x 1) Tiles
            Fixture fixture;
            int sizeOfDemoBlockX = 6 * TILE_SIZE;
            int sizeOfDemoBlockY = 3 * TILE_SIZE;
            for (int repeaterY = 0; repeaterY < Iterations; ++repeaterY)
                for (int repeaterX = 0; repeaterX < Iterations; ++repeaterX)
                    Vector2 repeaterPosition = new Vector2(repeaterX * sizeOfDemoBlockX, repeaterY * sizeOfDemoBlockY);

                    //The 1st row
                    MakeRectangle(0, 2, 6, 1, repeaterPosition);

                    //The right slope
                    int x = 0;
                    int y = 1;
                    int width = 3;
                    int height = 1;
                    Vertices verts = new Vertices(4);
                    verts.Add(new Vector2(width * TILE_SIZE, 0));
                    verts.Add(new Vector2((width - 1) * TILE_SIZE, height * TILE_SIZE));
                    verts.Add(new Vector2(0, height * TILE_SIZE));
                    verts.Add(new Vector2(0, 0));
                    Vector2 pos = new Vector2(x * TILE_SIZE, y * TILE_SIZE);
                    fixture = FixtureFactory.CreatePolygon(World, verts, 5, GlobalPos + repeaterPosition + pos);
                    fixture.Body.BodyType = BodyType.Static;

                    MakeRectangle(3, 1, 3, 1, repeaterPosition);

                    //The 3rd row
                    MakeRectangle(0, 0, 4, 1, repeaterPosition);

                    //The left slope
                    x = 4;
                    y = 0;
                    width = 2;
                    height = 1;
                    verts = new Vertices(4);
                    verts.Add(new Vector2(0, 0));
                    verts.Add(new Vector2(width * TILE_SIZE, 0));
                    verts.Add(new Vector2(width * TILE_SIZE, height * TILE_SIZE));
                    verts.Add(new Vector2((width - 1) * TILE_SIZE, height * TILE_SIZE));
                    pos = new Vector2(x * TILE_SIZE, y * TILE_SIZE);
                    fixture = FixtureFactory.CreatePolygon(World, verts, 5, GlobalPos + repeaterPosition + pos);
                    fixture.Body.BodyType = BodyType.Static;

        private void MakeRectangle(int x, int y, int width, int height, Vector2 repeaterPosition)
            Vector2 dimension = new Vector2(width * TILE_SIZE, height * TILE_SIZE);
            Vector2 pos = new Vector2(x * TILE_SIZE + (width * TILE_HALF_SIZE),
                              y * TILE_SIZE + (height * TILE_HALF_SIZE));
            Fixture fixture = FixtureFactory.CreateRectangle(World, dimension.X, dimension.Y, 5, GlobalPos + repeaterPosition + pos);
            fixture.Body.BodyType = BodyType.Static;

        public override void Update(GameSettings settings, GameTime gameTime)
            base.Update(settings, gameTime);

        internal static Test Create()
            return new RampTest();