在Three.js中将物体平行移动到投影平面

4
我想用鼠标沿着与投影平面平行的平面移动物体。这意味着在移动过程中,任何被选中的物体与相机投影平面(而不是相机位置)之间的距离必须保持不变。有一个类似的问题被问到:鼠标/画布X,Y到Three.js世界坐标系X,Y,Z的转换,但与此不同的是,我需要解决方案适用于任意相机角度和相机/物体位置,而不仅仅是Z=0的平面。它还必须适用于正交投影。现在我创建了一个示例:

http://jsfiddle.net/nmrNR/

以下是mousemove事件处理程序中的代码:

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())
);

圆圈跟随鼠标的位置移动,但它到相机的距离保持不变,因此实际上是在进行球形运动。当切换到正交相机时(点击),它也没有按预期跟随鼠标位置移动。
2个回答

1
我已将提问者优秀的工作版本修改为更适用于当前版本(对我来说更有效率 - 只是回报而已,谢谢)。起初,我发现使用clone可以避免跳跃行为。然后我注意到将对象前后移动会使其向前爬,所以我使用了初始点击位置(以获取距离)。还有警告问题,提示使用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版本。

0

这是一个旧问题,你可能已经解决了,但我还是给你一个答案。

你没有使用像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版本,如果您使用的是旧版本,则可能需要进行修改才能正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接