平行于投影平面移动物体,.js

Moving objects parallel to projection plane in three.js

本文关键字:js 移动 投影平面      更新时间:2023-09-26

我想用鼠标沿着平行于投影平面的平面移动对象。这意味着在移动过程中,任何拾取对象与摄像机投影平面(而不是摄像机位置)之间的距离必须保持不变。已经提出了类似的问题:鼠标/画布 X,Y 到三个.js世界 X、Y、Z ,但与那里不同的是,我需要一种适用于任意相机角度和相机/物体位置的解决方案,而不仅仅是适用于 z=0 的平面。它还必须适用于正交投影。现在我创建了一个小提琴

http://jsfiddle.net/nmrNR/

鼠标移动事件处理程序中的代码:

var v = new THREE.Vector3(
    (event.clientX/window.innerWidth)*2-1,
    -(event.clientY/window.innerHeight)*2+1,
    1
);
projector.unprojectVector(v,camera);
var dist = circle.position.sub(camera.position,circle.position),
    pos = camera.position.clone();
pos = pos.add(pos,
    v.sub(v,camera.position).normalize().multiplyScalar(dist.length())
);

圆圈跟随鼠标位置,但它与相机位置的距离是恒定的,因此它实际上是在执行球形运动。切换到地形相机(单击)时,它也不会按预期跟随鼠标位置。

我已经修改了提问者的优秀工作版本,使其在更新的版本中工作(对我来说更有效率 - 只是回馈,谢谢。起初,我发现自己使用克隆来避免跳跃行为。然后我注意到来回移动对象会让它向前爬行,所以我使用初始单击位置(以获得距离)。那里也有警告说使用addVectors和subVectors的问题,但这也没有必要。

camPos = cam.position;
var mv = new THREE.Vector3((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY/window.innerHeight) * 2 + 1, 1).unproject(cam);
var pos = camPos.clone(); 
pos.add(mv.sub(camPos).normalize().multiplyScalar(initalClickPos.distanceTo(camPos)));

将要移动的目标对象的位置设置为 pos 会将其从当前相机平面中的鼠标移动位置移动,但随着透视视图中对象的摄像机距离保持不变,它确实会以某种方式旋转。

对我来说,它看起来仍然有点时髦,所以我想也许可以通过添加和订阅更干净来进一步改进。可能如其他答案所示。

我最初单击的位置仍然有偏移问题,因此位置中心不会弹出,也许暂时设置对象枢轴值得探索。这适用于 r71。

一个你现在可能早就解决了的老问题,无论如何,这是一个答案。

您没有使用像OrbitControls这样的控件,这可能会使这稍微容易一些,即使只是为了在您的脑海中可视化它。 OrbitControls不仅有相机,还有一个引导相机的目标对象(它总是在看它,y 轴总是向上)。你想要实现的运动垂直于从相机到target的矢量,而不是垂直于对象的矢量,后者随着对象的移动而变化,其变化解释了圆周运动。方便的是,OrbitControls提供了您需要的数学。

从 https://github.com/mrdoob/three.js/blob/master/examples/js/controls/OrbitControls.js#L147-L171 开始,这些函数计算一个矢量,用于移动相机和目标(这应该同样适用于您的对象,尽管您可能需要反转移动)。请注意,this.object是相机。

// pass in distance in world space to move left
this.panLeft = function ( distance ) {
    var te = this.object.matrix.elements;
    // get X column of matrix
    panOffset.set( te[ 0 ], te[ 1 ], te[ 2 ] );
    panOffset.multiplyScalar( - distance );
    pan.add( panOffset );
};
// pass in distance in world space to move up
this.panUp = function ( distance ) {
    var te = this.object.matrix.elements;
    // get Y column of matrix
    panOffset.set( te[ 4 ], te[ 5 ], te[ 6 ] );
    panOffset.multiplyScalar( distance );
    pan.add( panOffset );
};

代码来自 r.68,如果您有旧版本,如果不修改它可能无法工作。