THREE.JS: 从 3D Perspective 场景转换为 2D Orthographic hud 场景
THREE.JS: Conversion from 3D Perspective scene to 2D Orthographic hud scene
我在 3D 场景中有物体(非常远),使用透视相机和使用正交相机设置的 2D HUD:
this.scene = new THREE.Scene();
this.hud = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera( 30, aspect, front, back );
this.camera.position.set(0,0,0);
this.hudCamera = new THREE.OrthographicCamera (-this.windowHalfX,this.windowHalfX, this.windowHalfY, -this.windowHalfY, 1, 10);
this.hudCamera.position.set(0,0,10);
这是我的渲染循环:
updateFrame : function () {
this.renderer.clear();
this.renderer.render( this.scene, this.camera );
this.renderer.clearDepth();
this.renderer.render( this.hud, this.hudCamera );
},
如何使用对象在 3D 场景中的位置找到对象在 HUD 中的位置?
为了找到 3D 对象的 2D HUD 位置(使用 three.js 版本 r71),您可以执行以下操作,我已从 this 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
}
}
参数obj
是您试图在平显中查找位置的对象。
vector.project(this.camera);
通过相机的 near
平面绘制一个从对象到 this.camera
位置的矢量。
vector
的分量的新值是投影向量与this.camera
的近平面的交点。
虽然坐标在 three.js 的世界坐标系中,因此我们必须快速转换为像素坐标,以扩大我们 canvas 的大小。
vector.x = ( vector.x * this.windowHalfX );
vector.y = ( vector.y * this.windowHalfY );
上述转换适用于 HUD 坐标系的原点 (0,0) 在屏幕中心的设置,最大值为 canvas 分辨率的一半。例如,如果您的 canvas 为 1024 x 768 像素,则右上角的位置将为 (512, 384).
对于典型的屏幕坐标系,右下角为 (1024, 768),屏幕中间为 (512, 384)。要进行此设置,您可以使用以下转换,如 this post.
中所示
vector.x = ( vector.x * widthHalf ) + widthHalf;
vector.y = - ( vector.y * heightHalf ) + heightHalf;
注意,现在 z 坐标无关紧要,因为我们处于 2D 中。
您最不想做的事情是确保您在 2D 中显示的对象实际上对透视相机可见。这就像检查对象是否落在 this.camera
的截锥体内一样简单。 source for following code
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 );
}
如果不这样做,您可以将相机后面的对象注册为在 2D 场景中可见(这会给对象跟踪带来问题)。更新 obj
的矩阵和矩阵世界也是一个好习惯。
我在 3D 场景中有物体(非常远),使用透视相机和使用正交相机设置的 2D HUD:
this.scene = new THREE.Scene();
this.hud = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera( 30, aspect, front, back );
this.camera.position.set(0,0,0);
this.hudCamera = new THREE.OrthographicCamera (-this.windowHalfX,this.windowHalfX, this.windowHalfY, -this.windowHalfY, 1, 10);
this.hudCamera.position.set(0,0,10);
这是我的渲染循环:
updateFrame : function () {
this.renderer.clear();
this.renderer.render( this.scene, this.camera );
this.renderer.clearDepth();
this.renderer.render( this.hud, this.hudCamera );
},
如何使用对象在 3D 场景中的位置找到对象在 HUD 中的位置?
为了找到 3D 对象的 2D HUD 位置(使用 three.js 版本 r71),您可以执行以下操作,我已从 this 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
}
}
参数obj
是您试图在平显中查找位置的对象。
vector.project(this.camera);
通过相机的 near
平面绘制一个从对象到 this.camera
位置的矢量。
vector
的分量的新值是投影向量与this.camera
的近平面的交点。
虽然坐标在 three.js 的世界坐标系中,因此我们必须快速转换为像素坐标,以扩大我们 canvas 的大小。
vector.x = ( vector.x * this.windowHalfX );
vector.y = ( vector.y * this.windowHalfY );
上述转换适用于 HUD 坐标系的原点 (0,0) 在屏幕中心的设置,最大值为 canvas 分辨率的一半。例如,如果您的 canvas 为 1024 x 768 像素,则右上角的位置将为 (512, 384).
对于典型的屏幕坐标系,右下角为 (1024, 768),屏幕中间为 (512, 384)。要进行此设置,您可以使用以下转换,如 this post.
中所示 vector.x = ( vector.x * widthHalf ) + widthHalf;
vector.y = - ( vector.y * heightHalf ) + heightHalf;
注意,现在 z 坐标无关紧要,因为我们处于 2D 中。
您最不想做的事情是确保您在 2D 中显示的对象实际上对透视相机可见。这就像检查对象是否落在 this.camera
的截锥体内一样简单。 source for following code
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 );
}
如果不这样做,您可以将相机后面的对象注册为在 2D 场景中可见(这会给对象跟踪带来问题)。更新 obj
的矩阵和矩阵世界也是一个好习惯。