If you're looking to determine the 2D HUD position of a 3D object using three.js version r71, you can achieve this by following these steps, which have been adapted from this reference post:
findHUDPosition : function (obj) {
var vector = new THREE.Vector3();
obj.updateMatrixWorld();
vector.setFromMatrixPosition(obj.matrixWorld);
vector.project(this.camera);
vector.x = ( vector.x * this.windowHalfX );
vector.y = ( vector.y * this.windowHalfY );
return {
x: vector.x,
y: vector.y,
z: vector.z
}
}
The input obj
refers to the object for which you are seeking the HUD position.
vector.project(this.camera);
generates a vector from the object to the this.camera
position, passing through the camera's near
plane.
The updated values of vector
's components represent the intersection of the projected vector and the this.camera
's near plane.
Although the coordinates are within three.js' world coordinate system, a conversion to pixel coordinates is necessary to match the canvas size.
vector.x = ( vector.x * this.windowHalfX );
vector.y = ( vector.y * this.windowHalfY );
The mentioned conversion assumes a HUD coordinate system with an origin at the screen's center (0,0) and a maximum value of half the canvas resolution. For instance, on a 1024 x 768 pixel canvas, the upper right corner would be located at (512, 384).
In a conventional screen coordinate system, the bottom right corner would be at (1024, 768), and the screen center at (512, 384). To acquire this setup, utilize the conversion provided in this reference post.
vector.x = ( vector.x * widthHalf ) + widthHalf;
vector.y = - ( vector.y * heightHalf ) + heightHalf;
At this point in 2D space, the z coordinate is inconsequential.
Lastly, ensure that the object being displayed in 2D is visible to the perspective camera by checking if it falls within the frustum of this.camera
. Refer to this source for the code snippet below:
checkFrustrum : function (obj) {
var frustum = new THREE.Frustum();
var projScreenMatrix = new THREE.Matrix4();
this.camera.updateMatrix();
this.camera.updateMatrixWorld();
projScreenMatrix.multiplyMatrices( this.camera.projectionMatrix, this.camera.matrixWorldInverse );
frustum.setFromMatrix( new THREE.Matrix4().multiplyMatrices( this.camera.projectionMatrix,
this.camera.matrixWorldInverse ) );
return frustum.containsPoint ( obj.position );
}
Failing to perform this check may result in an object located behind the camera being mistakenly recognized as visible in the 2D scene, leading to issues with object tracking. It's also recommended to update the matrices and matrix world of the obj
.