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

Posted

技术标签:

【中文标题】如何在轴 three.js 上旋转 3D 对象?【英文标题】:How to rotate a 3D object on axis three.js? 【发布时间】:2012-06-19 02:49:11 【问题描述】:

我对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)

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

我找到了页面How to rotate a Three.js Vector3 around an axis?,但它只是让一个Vector3点围绕世界轴旋转?

我已经尝试使用 ma​​trixRotationWorld 作为

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

但它不起作用,我不知道是我用错了还是有其他方法..

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

【问题讨论】:

@ 表示法是什么? '@' 在 CoffeeScript 中的意思是 'this'。在 javascript 中。这是一个简写。 【参考方案1】:

自 r59 版本以来,three.js 提供了这三个 functions 来围绕对象轴旋转对象。

object.rotateX(angle);
object.rotateY(angle);
object.rotateZ(angle);

【讨论】:

谢谢。这应该是最佳答案,大多数其他答案要么已弃用,要么效率低下。干得好! 这不应该用于动画!取自Three.js documentation:This is typically done as a one time operation, and not during a loop Use Object3D.rotation for typical real-time mesh rotation. @MatthewCliatt 你是对的。您能否为动画提供更好或更有效的解决方案? @Hetong 我自己还在寻找正确的解决方案。【参考方案2】:

我是这样解决的:

我为 ThreeJS 创建了“ObjectControls”模块,它允许您旋转单个 OBJECT(或组),而不是 SCENE。

包含库:

<script src="ObjectControls.js"></script>

用法:

var controls = new ObjectControls(camera, renderer.domElement, yourMesh);

您可以在这里找到现场演示:https://albertopiras.github.io/threeJS-object-controls/

这里是回购:https://github.com/albertopiras/threeJS-object-controls。

【讨论】:

链接死的快得惊人,这将使这个答案变得不那么有用。您能否将解决方案的相关部分提炼成答案正文中的文本或代码?【参考方案3】:

这是我使用的两个函数。它们基于矩阵旋转。并且可以绕任意轴旋转。要使用世界坐标轴旋转,您需要使用第二个函数 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 成本很高,如果它用于每一帧动画,你会不会重复使用它? 我得到了有人在github上发布的这两个函数。我不得不编辑它们以使用新的函数名称,例如最新版本的threejs 开发版本。我自己也想知道这一点。垃圾收集器会不时地清除对象。我在 Chrome 中查看了内存使用图,它在创建和销毁对象的位置上下波动,但动画对于我迄今为止使用的所有内容都很好。 当我尝试更改函数以重用相同的矩阵时,我的任何演示都无法运行。如果有人设法在不创建这样的新矩阵的情况下实现这一点,请发帖。 如何使用它来围绕其边缘旋转平面? 谨慎使用这种方法!在 Three.js 中,应该对 Object3D 进行直接矩阵操作(使用 object.matrixAutoUpdate = false)或对旋转、位置等属性进行操作。three.js docs 此外,rotateAroundWorldAxis 不适用于应用于对象。您必须从object.matrix 中提取旋转,乘以rotWorldMatrix 并从结果中设置object.rotation 的组件。【参考方案4】:

在 r59 附近的某个地方,这变得更容易(围绕 x 旋转):

bb.GraphicsEngine.prototype.calcRotation = function ( obj, rotationX)

    var euler = new THREE.Euler( rotationX, 0, 0, 'XYZ' );
    obj.position.applyEuler(euler);

【讨论】:

【参考方案5】:

在 Three.js R66 中,这是我使用的(CoffeeScript 版本):

THREE.Object3D.prototype.rotateAroundWorldAxis = (axis, radians) ->
  rotWorldMatrix = new THREE.Matrix4()
  rotWorldMatrix.makeRotationAxis axis.normalize(), radians
  rotWorldMatrix.multiply this.matrix
  this.matrix = rotWorldMatrix
  this.rotation.setFromRotationMatrix this.matrix

【讨论】:

【参考方案6】:

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

3js 变化如此之快 :D

【讨论】:

【参考方案7】:

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

【讨论】:

【参考方案8】:

以防万一...在 r52 中,该方法被称为 setEulerFromRotationMatrix 而不是 getRotationFromMatrix

【讨论】:

【参考方案9】:

我需要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 );

【讨论】:

以上是关于如何在轴 three.js 上旋转 3D 对象?的主要内容,如果未能解决你的问题,请参考以下文章

如何在旋转场景中查找对象的全局位置 THREE.JS

three.js 在它的中心围绕 Y 轴旋转 Object3d

Three.js 飞机的 3D 旋转

Three.js在函数中平滑旋转一个对象

Three.js源码解读一:Object3D

THREE.js - 旋转移动3D球