如何在轴 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点围绕世界轴旋转?
我已经尝试使用 matrixRotationWorld 作为
@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 对象?的主要内容,如果未能解决你的问题,请参考以下文章