Object Position to Canvas Pixel Position

Assuming I have some arbitrary game object, is there a way to transform object’s position to canvas pixel space? In otherwords, how would I get the x,y pixel I would need to click on to click on the origin of the object?

Hi @HyPeRbLaH,
If the size of the viewport of your camera is the same as the size of the canvas, this would be a way:

// this === scene
var gameObjectCanvasX = gameObject.x - this.cameras.main.scrollX * gameObject.scrollFactorX;
var gameObjectCanvasY = gameObject.y - this.cameras.main.scrollY * gameObject.scrollFactorY;

Regards.

Thanks @jjcapellan. Unfortunately my camera viewport will not be the same size as the viewport.

Then, you need to add the camera position:

// this === scene 
var cam = this.cameras.main;
var gameObjectCanvasX = gameObject.x - cam.scrollX * gameObject.scrollFactorX + cam.x;
var gameObjectCanvasY = gameObject.y - cam.scrollY * gameObject.scrollFactorY + cam.y;

What ended up working for me is as follows:

// obj is our game object
var mat = obj.getWorldTransformMatrix();

// Get world position;
var x = mat.getX(0, 0);
var y = mat.getY(0, 0);

// Convert world position into canvas pixel space
var cam = this.scene.scene.cameras.main;
var displayScale = cam.scaleManager.displayScale;
mat = cam.matrix;
let tx = mat.getX(x - camera.scrollX, y - camera.scrollY) / displayScale.x;
let ty = mat.getY(x - camera.scrollX, y - camera.scrollY) / displayScale.y;
x = Math.round(tx);
y = Math.round(ty);

This seems to handle a bunch of cases like deep hierarchies, rotations, scaled and rotated cameras, scale manager scaling, etc…

Probably this can be a more accurate solution:

function GetCanvasPoint(camera: Camera, x: number, y: number, output?: Vector2) {

    if (output === undefined) {
        output = new Vector2();
    }

    const cameraMatrix = (camera as any).matrix.matrix;

    const mva = cameraMatrix[0];
    const mvb = cameraMatrix[1];
    const mvc = cameraMatrix[2];
    const mvd = cameraMatrix[3];
    const mve = cameraMatrix[4];
    const mvf = cameraMatrix[5];

    const determinant = (mva * mvd) - (mvb * mvc);

    if (!determinant) {
        output.x = x;
        output.y = y;

        return output;
    }

    const res = camera.resolution;

    const sx = (mva * x + mvc * y + mve) / res;
    const sy = (mvb * x + mvd * y + mvf) / res;

    const c = Math.cos((camera as any).rotation);
    const s = Math.sin((camera as any).rotation);

    const zoom = camera.zoom;

    const scrollX = camera.scrollX;
    const scrollY = camera.scrollY;

    output.x = sx - (scrollX * c - scrollY * s) * zoom;
    output.y = sy - (scrollX * s + scrollY * c) * zoom;

    return output;
}

Thanks for this. However I found that the displayScale. bit was throwing my result out. I don’t understand how it works, but when I took out /displayScale.x and /displayScale.y the result i got was correct.

Cheers
Martin