Search code examples
c#xnaphysicsxna-4.0farseer

Farseer Meter/Pixel Ratio


I've done a lot with box2d in c++, and am giving C# a try. It looks like Farseer is generally used in place of Box2D (I'm aware of Box2DXNA, but it seems a little outdated.) So, Farseer is what I've been using. When I was using C++ and Box2D, everyone always advised against using a 1pixel/meter ratio (For what reason, I don't know,) and usually suggested using somewhere around 30pixels/meter. As I've been researching Farseer, I've seen a lot of conflicting statements. Some say to use 1pixel/meter, others say to use a scale, others say to use ConvertUnits.ToSimUnits and ConvertUnits.ToDisplayUnits, etc.

So what should I use? Right now, I'm using ConvertUnits, but everything renders in weird places. Is there a de-facto standard or anything that I should go by? Thanks in advance.


Solution

  • Farseer 3.x is based on Box2D. And the Box2D FAQ says:

    Box2D is tuned for meters-kilograms-seconds (MKS). Your moving objects should be between 0.1 - 10 meters. Do not use pixels as units! You will get a jittery simulation.

    In other words, assuming a "normal" physics world, you should probably have 1 physics unit = 1m. But any scale that causes the majority of your moving objects to be in the 0.1 to 10 unit range should be ok.

    So, say you're making a model of a car. A really, really simple model that happens to be a rectangle. You'd create it using something like:

    float width = 4.1f; // average car length in meters
    float height = 1.4f; // average car height in meters
    // Note: this method takes half-sizes:
    var carVertices = PolygonTools.CreateRectangle(width / 2f, height / 2f);
    // Then pass carVertices into PolygonShape, etc...
    

    The separate problem is how to then render your world at the correct size.

    The way this is generally done is at render time using a camera or view matrix (in the standard world/view/projection system). The two places you could do this are BasicEffect.View (MSDN), or the transformation matrix parameter to SpriteBatch.Begin (MSDN, see also).

    IMO, the Farseer ConvertUnits class is a very ugly way of handling the conversion.