4

我想用鼠标沿着与投影平面平行的平面移动对象。这意味着在移动过程中,任何拾取的对象与相机投影平面(不是相机位置)之间的距离必须保持不变。有人问了一个类似的问题: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())
);

圆圈跟随鼠标位置,但它与相机位置的距离是恒定的,因此它实际上是在执行球面运动。当切换到正交相机(点击)时,它也不会像预期的那样跟随鼠标位置。

4

2 回答 2

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 会将其从当前相机平面中的鼠标移动位置移动,但它会以某种方式旋转,因为在透视图中保持对象的相机距离。

它对我来说仍然看起来有点时髦,所以我想也许可以通过 add 和 sub 更清洁来进一步改进。可能在发布的其他答案中可以看到。

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

于 2015-04-22T22:47:11.810 回答
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,如果您有旧版本,它可能无法在不修改的情况下运行。

于 2014-07-19T15:20:24.597 回答