使用Projection将World坐标转换为Three.js中的Screen坐标

Bis*_*opZ 31 javascript 3d three.js

有几个优秀的堆栈问题(1,2)关于three.js所unprojecting,那就是如何转换(X,Y)鼠标在浏览器中的(X,Y,Z)坐标three.js所帆布空间坐标.他们大多遵循这种模式:

    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 );
Run Code Online (Sandbox Code Playgroud)

我一直试图反过来 - 而不是从"屏幕到世界"空间,从"世界到屏幕"空间.如果我知道Three.js中对象的位置,我该如何确定它在屏幕上的位置?

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

在Github上也有这个问题.

任何帮助表示赞赏.

mrd*_*oob 34

试试这个:

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;
Run Code Online (Sandbox Code Playgroud)

  • getPosition()已被弃用.改为使用:var vector = projector.projectVector(new THREE.Vector3().getPositionFromMatrix(object.matrixWorld),camera); (2认同)

dko*_*zev 9

对于现代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;
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果对象是组的一部分,则`object.position`可能不是您所需要的,因为`object.position`是组中的本地位置.使用`object.getWorldPosition()`(或`pos.setFromMatrixPosition()`,与其他答案一样)将考虑组内的相对位置. (3认同)
  • 这个答案假设画布与窗口大小相同。实际上应该使用一半画布宽度和一半画布高度...... (3认同)
  • 如果您想要准确地获取位置,无论包含画布(可能不是整个窗口)的位置和大小如何,您都需要基于“canvas.getBoundingClientRect()”而不是“window”进行这些计算 (3认同)

mar*_*tin 8

对于每个人deprecated或获取warnings日志,接受的答案是针对较旧的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);
Run Code Online (Sandbox Code Playgroud)