【问题标题】:What's the right way to rotate an object around a point in three.js?在three.js中围绕一个点旋转对象的正确方法是什么?
【发布时间】:2017-11-01 09:43:28
【问题描述】:

大多数关于three.js 的教程/问题都建议使用three.js 围绕点旋转对象的方法是在要旋转的位置创建父对象,附加对象,然后移动子对象。然后,当父级旋转时,子级围绕该点旋转。例如;

//Make a pivot
var pivot = new THREE.Object3D();
//Make an object
var object = new THREE.Mesh( new THREE.BoxGeometry(2,2,2), new THREE.MeshBasicMaterial() );
//Add object to pivot
pivot.add(object);

//Move object away from pivot
object.position.set(new THREE.Vector3(5,0,0));

//rotate the object 90 degrees around pivot
pivot.rotation.y = Math.PI / 2;

这是可行的,但它的限制令人难以置信 - 如果你想围绕不同的点旋转一个对象,你就不能这样做,因为一个对象不能有两个父对象。

下一个可行的方法是将旋转矩阵应用于对象的位置,例如;

//Make an object
var object = new THREE.Mesh( new THREE.BoxGeometry(2,2,2), new THREE.MeshBasicMaterial() );
//Move the object
object.position.set(new THREE.Vector3(5,0,0);

//Create a matrix
var matrix = new THREE.Matrix4();
//Rotate the matrix
matrix.makeRotationY(Math.PI / 2);

//rotate the object using the matrix
object.position.applyMatrix4(matrix);

同样,这可行,但似乎没有办法设置旋转点。它永远是世界的起源。

另一个选项是 sceneUtils 中的实用方法,用于将子对象与父对象分离,另一种方法用于附加新父对象,但该文档警告不要使用它,并且从未在任何示例代码中使用过。

最终我希望能够使立方体遵循 S 形路径,但如果没有这个(看似)基本的东西,我会发现它相当困难。

tl;dr 我想围绕一系列不同的点旋转一个three.js 对象。解决这个问题的好方法是什么?

【问题讨论】:

标签: javascript three.js


【解决方案1】:

这个答案可能会有所帮助:Three JS Pivot point

有几种方法可以解决这个问题。正如您所提到的,您可以在育儿方法中交换枢轴点,但需要大量工作,将对象位置转换为不同的坐标系。

相反,你总是可以这样看(伪代码):

  1. 将对象移动到轴心点

    1.1。从对象的原始位置减去轴心点

  2. 应用轮换

  3. 将对象向后移动相同的位置向量

    1.1。将轴心点添加到对象的位置

注意:一切都在世界坐标中,因此您可能需要进行适当的转换。

【讨论】:

  • 这就是我对点进行旋转的方式。我将从我的位置中减去枢轴,通过THREE.Quaternion().setFromAxisAngle() 应用四元数旋转,然后将枢轴添加回来,效果很好。
  • 仅供参考,THREE.Vector3.applyAxisAngle 内部使用四元数,因此您可能不需要创建自己的(除非您需要多次执行相同的操作)。
  • 我使用的是LineSegment,所以我有 2 点需要轮换,但对于未来的读者来说,请记住这一点。
【解决方案2】:

这是可行的,但它的限制令人难以置信——如果你想旋转一个 围绕一个不同点的对象,你不能因为一个对象不能有 两个父母。

这是真的,但我想知道您对拥有 2 个父母的默认行为有何期望。您可以嵌套事物 - 即,汽车中的女性持有的摄像头有 2 层养育方式:摄像头->女性->汽车。但是,如果您想要一些平行的育儿关系(?),可以说女人拿着相机,但您希望男人同时也拿着相机。你如何让男人转身拍摄一些东西而不从女人那里拿走,反之亦然?当您尝试想象默认情况下会发生什么时,多个父母的想法就会崩溃。女人会随着相机移动吗?那么在这种情况下,相机实际上不是她的父母吗?

如果您想在父对象之间进行更改,您可以随时分离对象,然后将其附加到另一个对象。它会警告您不要手动分离,因为对象将从本地空间到其父级进入世界空间/其新父级的本地空间。

Luckily there are some things in the scene utils meant for exactly this: namely attach and detach。因此,当您想在不从本地坐标到世界坐标并将其传送到奇怪的地方的情况下传递对象时,您可以使用附加/分离功能。

请记住,除非 newParent 在切换时与前一个父对象位于完全相同的位置,否则这会做一些奇怪的事情,因为我们不保证我们的对象与父对象的关系,除了它会保持与交接时相同。

【讨论】:

    【解决方案3】:

    简单的解决方案:移动到锚点,旋转,然后向后移动。

    假设您想围绕anchorPoint 旋转cameracameraTHREE.Camera 的实例,anchorPointTHREE.Vector3 的实例):

    /// step 1: calculate move direction and move distance:
    let moveDir = new THREE.Vector3(
        anchorPoint.x - camera.position.x,
        anchorPoint.y - camera.position.y,
        anchorPoint.z - camera.position.z
    );
    moveDir.normalize();
    let moveDist = camera.position.distanceTo(anchorPoint);
    /// step 2: move camera to anchor point
    camera.translateOnAxis(moveDir, moveDist);
    /// step 3: rotate camera
    camera.rotateX(valX);
    camera.rotateY(valY);
    camera.rotateZ(valZ);
    /// step4: move camera along the opposite direction
    moveDir.multiplyScalar(-1);
    camera.translateOnAxis(moveDir, moveDist);
    

    【讨论】:

      猜你喜欢
      • 2017-07-14
      • 1970-01-01
      • 2015-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      • 2013-08-30
      • 2018-02-17
      相关资源
      最近更新 更多