Prevent scaling when resizing the canvas - Pixel to unit conversion

I’ve been trying to create a function that can convert pixels to units so that i can put 3D objects in a layer under a html page. I need this so that i can have the camera position.y linked with the page scroll y. 3d objects need to be placeable at exact pixel position and sizes of html objects. These html objects change size on resize so the objects will need to check the html object size and resize and reposition accordingly.

What would be the best way to do this in BabylonJS? I have tried the following:
create a box of 10, resize box to fit view, divide box size by screen size: now we know how much units 1 pixel is. This gives sort of what i need, but does not work well when the aspect ratio goes above 1.5.

cam = new UniversalCamera(
‘Camera’,
new Vector3(0, 0, 50),
scene
);
cam.setTarget(new Vector3(0, 0, 0));
cam.fovMode = 0; // FOVMODE_VERTICAL_FIXED
cam.fov = Math.radians(45);
cam.minZ = 0.1;
cam.maxZ = 10000;

const cardMesh = BoxBuilder.CreateBox(
boxMesh,
{
width: 10,
height: 10,
depth: 0.05,
},
scene
);

cardMesh.computeWorldMatrix(true);
const size = cardMesh.getBoundingInfo().boundingBox.extendSizeWorld;
const maxSize = size.x;
const ratio = engine.getAspectRatio(cam);
const h = maxSize / (Math.tan(cam.fov / 2) * ratio);
cam.position.z = h;
cam.getProjectionMatrix(true);

Does anyone know how this could be done better with more precision?
I think it might be related to the way Babylon scales the content when resizing the canvas. Is there a way to link this to canvas size like you can in three js, like in this example?

  • camera.aspect = canvas.clientWidth / canvas.clientHeight;
  • camera.updateProjectionMatrix();

I know you can set fov fixed vertical or horizontal but i think i need both fixed.

Thank you!

1 Like

Hi Ivo_Metz,

I’m not 100% sure I understand your use case correctly. However, if you just want the FOV to remain fixed, I think you can do that by calling freezeProjectionMatrix (you might need to force the system to compute the projection matrix before freezing it if you call the method right at the beginning). You can also go the route of unprojecting the regions you want the geometry to render to and calculating where it should be based on that; but depending on what exactly your use case is, you might not need to do something that elaborate.