在three.js中移动平行于投影平面的对象

时间:2013-10-15 19:53:48

标签: javascript 3d three.js projection perspectivecamera

我想用鼠标沿着与投影平面平行的平面移动物体。这意味着在移动期间,任何拾取的物体和相机投影平面(不是相机位置)之间的距离必须保持不变。有一个类似的问题被问到:Mouse / Canvas X, Y to Three.js World 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())
);

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

2 个答案:

答案 0 :(得分:1)

我已经修改了提问者优秀的工作版本,以便在更新的版本中工作(对我来说更有效率 - 只需回馈,谢谢。 起初我发现自己使用克隆来避免跳跃行为。然后我注意到前后移动物体向前移动所以我使用了初始点击位置(以获得距离)。 在那里还有使用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一起使用。

答案 1 :(得分: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,如果你有旧版本,它可能无法修改。