Reputation: 5005
I am facing the challenge of figuring out the visible view width and height of a ThreeJS mesh object in pixel units.
In the screenshot below you can see objects floating in 3D space, on mouse click I need to be able to figure out what view width and height they are occupying in pixels
As I am rather new to ThreeJS it is taking me rather long to find a solution, so I would welcome any kind of assistance.
The below function shows what kind of approaches I have been trying.
getObjectSizeInViewSpace(object){
const size = new THREE.Vector3()
const box = new THREE.Box3().setFromObject(object).getSize(size)
size.project(this.camera)
let halfWidth = window.innerWidth / 2;
let halfHeight = window.innerHeight / 2;
size.x = (size.x*halfWidth)
size.y = (size.y*halfHeight)
return new THREE.Vector2(size.x,size.y)
}
Upvotes: 5
Views: 2799
Reputation: 28472
You're looking for Vector3.project()
. This basically takes world-space (3D) coordinates, and uses the camera's viewport to convert into normalized device coordinates, which range from [-1, 1]
. For example x: -1
is the left side of the screen, and x: 1
is the right side. So you'll have to take the 4 vectors (top left, top right, bottom left, bottom right)` of your plane to calculate their pixel dimensions in your browser:
// Get 3D positions of top left corner (assuming they're not rotated)
vec3 topLeft = new Vector3(
plane.position.x - planeWidth / 2,
plane.position.y - planeHeight / 2,
plane.positon.z
);
// This converts x, y, z to the [-1, 1] range
topLeft.project(camera);
// This converts from [-1, 1] to [0, windowWidth]
const topLeftX = (1 + topLeft.x) / 2 * window.innerWidth;
const topLeftY = (1 - topLeft.y) / 2 * window.innerHeight;
Notice the topLeftY
value is inverted, since -y
in 3D space goes +y
in pixel coordinates. Do this 4 times (once for each corner), and then you can subtract (right - left) to get the width, and the same for the height.
Upvotes: 6