Kreshnik Hasanaj
Kreshnik Hasanaj

Reputation: 5005

How to get the visible width and height of a ThreeJS mesh object in pixel unit

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 enter image description here

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

Answers (1)

M -
M -

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

Related Questions