38

关于 Three.js 中的非投影有几个很好的堆栈问题(1、2 ,即如何将浏览器中的 (x,y) 鼠标坐标转换为 Three.js 画布空间中的 (x,y,z) 坐标。他们大多遵循这种模式:

    var elem = renderer.domElement, 
        boundingRect = elem.getBoundingClientRect(),
        x = (event.clientX - boundingRect.left) * (elem.width / boundingRect.width),
        y = (event.clientY - boundingRect.top) * (elem.height / boundingRect.height);

    var vector = new THREE.Vector3( 
        ( x / WIDTH ) * 2 - 1, 
        - ( y / HEIGHT ) * 2 + 1, 
        0.5 
    );

    projector.unprojectVector( vector, camera );
    var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() );
    var intersects = ray.intersectObjects( scene.children );

我一直试图做相反的事情——而不是从“屏幕到世界”空间,而是从“世界到屏幕”空间。如果我知道 Three.js 中对象的位置,我如何确定它在屏幕上的位置?

这个问题似乎没有任何已发布的解决方案。关于这个的另一个问题刚刚出现在 Stack 上,但作者声称已经用一个对我不起作用的函数解决了这个问题。他们的解决方案不使用投影射线,我很确定由于 2D 到 3D 使用 unprojectVector(),3D 到 2D 解决方案将需要 projectVector()。

Github 上也有这个问题。

任何帮助表示赞赏。

4

3 回答 3

37

试试这个:

var width = 640, height = 480;
var widthHalf = width / 2, heightHalf = height / 2;

var vector = new THREE.Vector3();
var projector = new THREE.Projector();
projector.projectVector( vector.setFromMatrixPosition( object.matrixWorld ), camera );

vector.x = ( vector.x * widthHalf ) + widthHalf;
vector.y = - ( vector.y * heightHalf ) + heightHalf;
于 2012-07-23T00:00:50.680 回答
28

对于现代 Three.js (r75),可以将矢量投影到屏幕上:

var width = window.innerWidth, height = window.innerHeight;
var widthHalf = width / 2, heightHalf = height / 2;

var pos = object.position.clone();
pos.project(camera);
pos.x = ( pos.x * widthHalf ) + widthHalf;
pos.y = - ( pos.y * heightHalf ) + heightHalf;
于 2016-04-19T01:26:17.870 回答
16

对于每个获取deprecatedwarnings记录的人,可接受的答案是针对较旧的 Three.js 版本。现在更容易了:

let pos = new THREE.Vector3();
pos = pos.setFromMatrixPosition(object.matrixWorld);
pos.project(camera);

let widthHalf = canvasWidth / 2;
let heightHalf = canvasHeight / 2;

pos.x = (pos.x * widthHalf) + widthHalf;
pos.y = - (pos.y * heightHalf) + heightHalf;
pos.z = 0;

console.log(pos);
于 2016-10-31T18:31:08.600 回答