Box2D-for-Processing icon indicating copy to clipboard operation
Box2D-for-Processing copied to clipboard

converting between Box2D world coordinates and screen coordinates

Open aaarbk opened this issue 12 years ago • 3 comments

According to "The Nature of Code", the coordinate system for Box2D is a standard cartesian one, whereas for Processing it's one with the origin at the top left of the window, with y-coordinate increasing downward and x-coordinate to the right.

However, testing the coordinate conversion functions in pbox2d gives a different picture:


import pbox2d.*;
import org.jbox2d.common.*;

boolean once = false;
PBox2D box2d;

void setup()
{
  box2d = new PBox2D(this);
  box2d.createWorld();
  size(500, 500);
}

void draw()
{
  if (!once)
  {

    Vec2[] screenPositions = new Vec2[3];
    screenPositions[0] = new Vec2(250, 250); // center of screen
    screenPositions[1] = new Vec2(0, 0); // upper left corner
    screenPositions[2] = new Vec2(500, 500); // lower right corner

    for ( int i = 0; i < 3; i++ )
    {
      Vec2 worldPos = box2d.coordPixelsToWorld(screenPositions[i]);
      print("screenPos.x = " + screenPositions[i].x + " screenPos.y = " + screenPositions[i].y);
      println();
      print("worldPos.x = " + worldPos.x + " worldPos.y = " + worldPos.y);
      println();
      println();

    }
    once = true;
  }
}


gives the following output in the message area:

screenPos.x = 250.0 screenPos.y = 250.0
worldPos.x = 20.0 worldPos.y = 20.0

screenPos.x = 0.0 screenPos.y = 0.0
worldPos.x = -5.0 worldPos.y = 45.0

screenPos.x = 500.0 screenPos.y = 500.0
worldPos.x = 45.0 worldPos.y = -5.0

So it seems that a screen coordinate with x = 0 corresponds to a world Position with x coordinate = -5, and a screen coordinate with y = 500 (or, generally speaking, the width of the window, as I've confirmed by testing with different sizes of the window) results in a world position with y coordinate = -5.0. The scaling factor is always 1/10.

Is there a reason why the origin of the Box2D world coordinate system doesn't correspond to the center of the screen? I don't have much familiarity with either box2d or Processing, and I jumped directly into chapter 5 of "The Nature of Code", so apologies if I'm missing something that ought to be common knowledge.

aaarbk avatar Sep 07 '13 10:09 aaarbk

Here's example of the implementation of the coordPixelsToWorld(x, y):

public Vec2 coordPixelsToWorld(float pixelX, float pixelY) {
        float worldX = PApplet.map(pixelX, transX, transX+scaleFactor, 0f, 1f);
        float worldY = pixelY;
        if (yFlip == -1.0f) worldY = PApplet.map(pixelY,parent.height,0f,0f,parent.height);
        worldY = PApplet.map(worldY, transY, transY+scaleFactor, 0f, 1f);
        return new Vec2(worldX,worldY);
    }

At the initialization stage of PBox2d transX is set to half screen width (width/2), so in your case it will be 500/2 = 250. Variable transY is initialized as well with half-height, which is 250 in your case.

The scaleFactor is by default initialized with 10. And obviously parent.height is equal to the height of the sketch, in your case 500.

So if I replace variables with literal values in the above code, it will look like this:

public Vec2 coordPixelsToWorld(float pixelX, float pixelY) {
        float worldX = PApplet.map(pixelX, 250, 250+10, 0f, 1f);
        float worldY = pixelY;
        if (yFlip == -1.0f) worldY = PApplet.map(pixelY,500,  0f,  0f,  500);
        worldY = PApplet.map(worldY, 250, 250 + 10,   0f,   1f);
        return new Vec2(worldX,worldY);
    }

dimkir avatar Sep 15 '13 13:09 dimkir

Actually the example above is just FYI, you have bug in your implemntation (which I noticed only now), the call to size() should be the first call in your setup(), otherwise you initialize PBox2D with incorrect dimensions of the sketch (before you call size() your actual dimensions are something like 150x150: the default sketch size for processing), so this is why your coordinates get calcualted incorrectly.

void setup()
{
  size(500, 500);   // this is correct way: always call to size as first call in your setup()
  box2d = new PBox2D(this); // now PBox2D will fetch correct size of the sketch which would allow
                                           // to make correct coordinate conversions
  box2d.createWorld();

}

After putting call to size() as first line I get correct coordinates:


screenPos.x = 250.0 screenPos.y = 250.0
worldPos.x = 0.0 worldPos.y = 0.0

screenPos.x = 0.0 screenPos.y = 0.0
worldPos.x = -25.0 worldPos.y = 25.0

screenPos.x = 500.0 screenPos.y = 500.0
worldPos.x = 25.0 worldPos.y = -25.0


dimkir avatar Sep 15 '13 14:09 dimkir

@dimkir

In the literal example above:

float worldX = PApplet.map(pixelX, 250, 250+10, 0f, 1f);

Why is pixelX considered to be in the range of 250 and 260?

Subedy avatar Mar 02 '14 23:03 Subedy