将 Point3D 转换为 Screen2D 在 three.js 中得到错误的结果

convert Point3D To Screen2D get wrong result in three.js

我在 three.js 69

中使用了这样的函数
  function Point3DToScreen2D(point3D,camera){
    var p = point3D.clone();
    var vector = p.project(camera);

    vector.x = (vector.x + 1) / 2 * window.innerWidth;
    vector.y = -(vector.y - 1) / 2 * window.innerHeight;

    return vector;

  }

当我保持场景静止时效果很好。 但是当我旋转场景时它犯了一个错误并且 return 在屏幕中的位置错误。 当我旋转大约 180 度时会发生这种情况 degrees.It 在屏幕中应该没有位置但是它显示。

我在update中设置了一个位置var tmpV=Point3DToScreen2D(new THREE.Vector3(-67,1033,-2500),camera);并用css3d.And显示,当我旋转180度但小于360度时,该点显示在屏幕上again.Obviously 从现场可以看出位置不对,我没有旋转360度

我对 Matrix 知之甚少,所以我不知道 project 是如何工作的。

这里是 three.js 中 project 的来源:

project: function () {

        var matrix;

        return function ( camera ) {

            if ( matrix === undefined ) matrix = new THREE.Matrix4();

            matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) );
            return this.applyProjection( matrix );

        };

    }()

matrix.getInverse( camera.matrixWorld ) 是多余的吗?我试图删除它,但没有用。 谁能帮帮我?谢谢。

您正在使用如下模式将 3D 点从世界 space 投影到屏幕 space:

var vector = new THREE.Vector3();
var canvas = renderer.domElement;

vector.set( 1, 2, 3 );

// map to normalized device coordinate (NDC) space
vector.project( camera );

// map to 2D screen space
vector.x = Math.round( (   vector.x + 1 ) * canvas.width  / 2 ),
vector.y = Math.round( ( - vector.y + 1 ) * canvas.height / 2 );
vector.z = 0;

但是,使用这种方法,相机后面的点也会投影到屏幕上 space。

你说你想过滤掉相机后面的点。为此,您可以先使用此模式:

var matrix = new THREE.Matrix4(); // create once and reuse

...

// get the matrix that maps from world space to camera space
matrix.getInverse( camera.matrixWorld );

// transform your point from world space to camera space
p.applyMatrix( matrix );

由于摄像机位于摄像机 space 的原点,并且由于摄像机始终向下看摄像机 space 的负 z 轴,摄像机后面的点将具有 z -坐标大于零。

// check if point is behind the camera
if ( p.z > 0 ) ...

three.js r.71

和上面的例子一样,但是你可以检查vector.z来确定它是否在前面。

var vector = new THREE.Vector3();
var canvas = renderer.domElement;

vector.set( 1, 2, 3 );

// map to normalized device coordinate (NDC) space
vector.project( camera );

// map to 2D screen space
vector.x = Math.round( (   vector.x + 1 ) * canvas.width  / 2 ),
vector.y = Math.round( ( - vector.y + 1 ) * canvas.height / 2 );

//behind the camera if z isn't in 0..1 [frustrum range]
if(vector.z > 1){
   vector = null;
}

要更深入地研究这个答案:

// behind the camera if z isn't in 0..1 [frustrum range]
if(vector.z > 1){
   vector = null;
}

This is not true. The mapping is not continuous. Points beyond the far plane also map to z-values greater than 1

投影矢量的 z 值究竟代表什么? X 和 Y 在归一化裁剪空间 [-1,1] 中,那么 z?

这是真的吗?

projectVector.project(camera);

var inFrontOfCamera = projectVector.z < 1;

由于摄像机位于摄像机 space 的原点,并且由于摄像机始终向下看摄像机 space 的负 z 轴,摄像机后面的点将具有 z -坐标大于1.

//check if point is behind the camera
if ( p.z > 1 ) ...

注意:如果满足此条件,则投影坐标需要中心对称

{x: 0.233, y: -0.566, z: 1.388}
// after transform
{x: -0.233, y: 0.566, z: 1.388}