Rewind
Rewind

Reputation: 2814

PIXI.js - Canvas Coordinate to Container Coordinate

I have initiated a PIXI js canvas:

g_App = new PIXI.Application(800, 600, { backgroundColor: 0x1099bb });

Set up a container:

container = new PIXI.Container();
g_App.stage.addChild(container);

Put a background texture (2000x2000) into the container:

var texture = PIXI.Texture.fromImage('picBottom.png');
var back = new PIXI.Sprite(texture);
container.addChild(back);

Set the global:

var g_Container = container;

I do various pivot points and rotations on container and canvas stage element:

// Set the focus point of the container
g_App.stage.x = Math.floor(400);
g_App.stage.y = Math.floor(500); // Note this one is not central
g_Container.pivot.set(1000, 1000);
g_Container.rotation = 1.5; // radians

Now I need to be able to convert a canvas pixel to the pixel on the background texture.

g_Container has an element transform which in turn has several elements localTransform, pivot, position, scale ands skew. Similarly g_App.stage has the same transform element.

In Maths this is simple, you just have vector point and do matix operations on them. Then to go back the other way you just find inverses of those matrices and multiply backwards.

So what do I do here in pixi.js?

How do I convert a pixel on the canvas and see what pixel it is on the background container?

Upvotes: 0

Views: 4645

Answers (1)

Rewind
Rewind

Reputation: 2814

Note: The following is written using the USA convention of using matrices. They have row vectors on the left and multiply them by the matrix on the right. (Us pesky Brits in the UK do the opposite. We have column vectors on the right and multiply it by the matrix on the left. This means UK and USA matrices to do the same job will look slightly different.)

Now I have confused you all, on with the answer.

g_Container.transform.localTransform - this matrix takes the world coords to the scaled/transposed/rotated COORDS

g_App.stage.transform.localTransform - this matrix takes the rotated world coords and outputs screen (or more accurately) html canvas coords

So for example the Container matrix is:

MatContainer = [g_Container.transform.localTransform.a, g_Container.transform.localTransform.b, 0]
               [g_Container.transform.localTransform.c, g_Container.transform.localTransform.d, 0]
               [g_Container.transform.localTransform.tx, g_Container.transform.localTransform.ty, 1]

and the rotated container matrix to screen is:

MatToScreen = [g_App.stage.transform.localTransform.a, g_App.stage.transform.localTransform.b, 0]
              [g_App.stage.transform.localTransform.c, g_App.stage.transform.localTransform.d, 0]
              [g_App.stage.transform.localTransform.tx, g_App.stage.transform.localTransform.ty, 1]

So to get from World Coordinates to Screen Coordinates (noting our vector will be a row on the left, so the first operation matrix that acts first on the World coordinates must also be on the left), we would need to multiply the vector by:

MatAll = MatContainer * MatToScreen

So if you have a world coordinate vector vectWorld = [worldX, worldY, 1.0] (I'll explain the 1.0 at the end), then to get to the screen coords you would do the following:

vectScreen = vectWorld * MatAll

So to get screen coords and to get to world coords we first need to calculate the inverse matrix of MatAll, call it invMatAll. (There are loads of places that tell you how to do this, so I will not do it here.)

So if we have screen (canvas) coordinates screenX and screenY, we need to create a vector vectScreen = [screenX, screenY, 1.0] (again I will explain the 1.0 later), then to get to world coordinates worldX and worldY we do:

vectWorld = vectScreen * invMatAll

And that is it.

So what about the 1.0?

In a 2D system you can do rotations, scaling with 2x2 matrices. Unfortunately you cannot do a 2D translations with a 2x2 matrix. Consequently you need 3x3 matrices to fully describe all 2D scaling, rotations and translations. This means you need to make your vector 3D as well, and you need to put a 1.0 in the third position in order to do the translations properly. This 1.0 will also be 1.0 after any matrix operation as well.

Note: If we were working in a 3D system we would need 4x4 matrices and put a dummy 1.0 in our 4D vectors for exactly the same reasons.

Upvotes: 2

Related Questions