如何在轴three.js上旋转3D对象?

IT技术 javascript coffeescript three.js
2021-01-30 19:53:12

我有一个关于 Three.js 旋转的大问题 我想在我的一个游戏中旋转我的 3D 立方体。

//init
geometry = new THREE.CubeGeometry grid, grid, grid
material = new THREE.MeshLambertMaterial {color:0xFFFFFF * Math.random(), shading:THREE.FlatShading, overdraw:true, transparent: true, opacity:0.8}
for i in [1...@shape.length]
    othergeo = new THREE.Mesh new THREE.CubeGeometry(grid, grid, grid)
    othergeo.position.x = grid * @shape[i][0]
    othergeo.position.y = grid * @shape[i][1]
    THREE.GeometryUtils.merge geometry, othergeo
@mesh = new THREE.Mesh geometry, material

//rotate
@mesh.rotation.y += y * Math.PI / 180
@mesh.rotation.x += x * Math.PI / 180
@mesh.rotation.z += z * Math.PI / 180

并且 (x, y, z) 可以是 (1, 0, 0)

然后立方体可以旋转,但问题是立方体在自己的轴上旋转,所以旋转后,它不能按预期旋转。

我找到页面如何围绕轴旋转 Three.js Vector3?,但它只是让 Vector3 点绕世界轴旋转?

我曾尝试使用matrixRotationWorld作为

@mesh.matrixRotationWorld.x += x * Math.PI / 180
@mesh.matrixRotationWorld.y += y * Math.PI / 180
@mesh.matrixRotationWorld.z += z * Math.PI / 180

但它不起作用,我不知道是我以错误的方式使用它还是有其他方式..

那么,如何让 3D 立方体绕世界轴旋转???

6个回答

从 r59 版本开始,three.js 提供了这三个函数来围绕对象轴旋转对象。

object.rotateX(angle);
object.rotateY(angle);
object.rotateZ(angle);
谢谢。这应该是最重要的答案,大多数其他答案要么已弃用,要么效率更低。很好!
2021-03-13 19:53:12
这不应该用于动画!取自Three.js 文档This is typically done as a one time operation, and not during a loop Use Object3D.rotation for typical real-time mesh rotation.
2021-03-13 19:53:12
@Hetong 我自己仍在寻找正确的解决方案。
2021-03-18 19:53:12
@MatthewCliatt 你是对的。你能为动画提供更好或更有效的解决方案吗?
2021-04-03 19:53:12

这是我使用的两个函数。它们基于矩阵旋转。并且可以绕任意轴旋转。要使用世界坐标轴旋转,您需要使用第二个函数 rotateAroundWorldAxis()。

// Rotate an object around an arbitrary axis in object space
var rotObjectMatrix;
function rotateAroundObjectAxis(object, axis, radians) {
    rotObjectMatrix = new THREE.Matrix4();
    rotObjectMatrix.makeRotationAxis(axis.normalize(), radians);

    // old code for Three.JS pre r54:
    // object.matrix.multiplySelf(rotObjectMatrix);      // post-multiply
    // new code for Three.JS r55+:
    object.matrix.multiply(rotObjectMatrix);

    // old code for Three.js pre r49:
    // object.rotation.getRotationFromMatrix(object.matrix, object.scale);
    // old code for Three.js r50-r58:
    // object.rotation.setEulerFromRotationMatrix(object.matrix);
    // new code for Three.js r59+:
    object.rotation.setFromRotationMatrix(object.matrix);
}

var rotWorldMatrix;
// Rotate an object around an arbitrary axis in world space       
function rotateAroundWorldAxis(object, axis, radians) {
    rotWorldMatrix = new THREE.Matrix4();
    rotWorldMatrix.makeRotationAxis(axis.normalize(), radians);

    // old code for Three.JS pre r54:
    //  rotWorldMatrix.multiply(object.matrix);
    // new code for Three.JS r55+:
    rotWorldMatrix.multiply(object.matrix);                // pre-multiply

    object.matrix = rotWorldMatrix;

    // old code for Three.js pre r49:
    // object.rotation.getRotationFromMatrix(object.matrix, object.scale);
    // old code for Three.js pre r59:
    // object.rotation.setEulerFromRotationMatrix(object.matrix);
    // code for r59+:
    object.rotation.setFromRotationMatrix(object.matrix);
}

所以你应该在你的anim函数中调用这些函数(requestAnimFrame 回调),导致在 x 轴上旋转 90 度:

var xAxis = new THREE.Vector3(1,0,0);
rotateAroundWorldAxis(mesh, xAxis, Math.PI / 180);
我认为为每次调用继续创建一个新的 THREE.Matrix4 会很昂贵,如果它用于每帧动画,你会不会重用它?
2021-03-21 19:53:12
当我尝试更改函数以重用相同的矩阵时,我无法让我的任何演示工作。如果有人设法在不创建这样的新矩阵的情况下实现这一点,请发布。
2021-03-30 19:53:12
小心这种方法!在 Three.js 中,应该对 Object3D 进行直接矩阵操作(使用 object.matrixAutoUpdate = false)或操作旋转、位置等属性。three.js docs进一步rotateAroundWorldAxis不适用于应用于对象的非均匀缩放。您必须从结果中提取旋转object.matrix,乘以rotWorldMatrix并设置 的分量object.rotation
2021-04-02 19:53:12
我如何使用它来围绕其边缘旋转平面?
2021-04-09 19:53:12
我得到了有人在github上发布的这两个函数。我必须编辑它们以使用新的函数名称等对于 Threejs 的最新版本开发版本。我自己也想过这个。垃圾收集器每隔一段时间就会清除这些对象。我已经在 Chrome 中查看了内存使用图,它会在创建和销毁对象的地方上下移动,但是到目前为止我使用的所有动画看起来都很好。
2021-04-11 19:53:12

我需要该rotateAroundWorldAxis功能,但上述代码不适用于最新版本 (r52)。好像getRotationFromMatrix()被替换了setEulerFromRotationMatrix()

function rotateAroundWorldAxis( object, axis, radians ) {

    var rotationMatrix = new THREE.Matrix4();

    rotationMatrix.makeRotationAxis( axis.normalize(), radians );
    rotationMatrix.multiplySelf( object.matrix );                       // pre-multiply
    object.matrix = rotationMatrix;
    object.rotation.setEulerFromRotationMatrix( object.matrix );
}

使用 r55 你必须改变
rotationMatrix.multiplySelf( object.matrix );

rotationMatrix.multiply(object.matrix);

在 Three.js R59 中,object.rotation.setEulerFromRotationMatrix(object.matrix);已改为object.rotation.setFromRotationMatrix(object.matrix);

3js 变化如此之快 :D