javascript - Cómo rotar un objeto 3D en el eje three.js?
coffeescript (9)
Tengo un gran problema con la rotación en three.js. Quiero rotar mi cubo 3D en uno de mis juegos.
//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 [[email protected]]
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
y (x, y, z) puede ser (1, 0, 0)
entonces el cubo puede rotar, pero el problema es que el cubo gira sobre su propio eje, por lo que una vez que ha girado, no puede girar como se espera.
Encuentro la página ¿Cómo rotar un Three.js Vector3 alrededor de un eje? , pero solo deja que un punto Vector3 gire alrededor del eje del mundo?
y he intentado usar matrixRotationWorld como
@mesh.matrixRotationWorld.x += x * Math.PI / 180
@mesh.matrixRotationWorld.y += y * Math.PI / 180
@mesh.matrixRotationWorld.z += z * Math.PI / 180
pero no funciona, no sé si lo usé de manera incorrecta o si hay otras formas ...
Entonces, ¿cómo dejar que el cubo 3D gire alrededor del eje del mundo?
Desde la versión r59, three.js proporciona esas tres funciones para rotar un objeto alrededor del eje del objeto.
object.rotateX(angle);
object.rotateY(angle);
object.rotateZ(angle);
En Three.js R59, object.rotation.setEulerFromRotationMatrix(object.matrix);
ha sido cambiado a object.rotation.setFromRotationMatrix(object.matrix);
3js está cambiando tan rápidamente: D
En Three.js R66, esto es lo que uso (versión 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
En algún lugar alrededor de r59 esto se vuelve más fácil (rotar alrededor de x):
bb.GraphicsEngine.prototype.calcRotation = function ( obj, rotationX)
{
var euler = new THREE.Euler( rotationX, 0, 0, ''XYZ'' );
obj.position.applyEuler(euler);
}
Estas son las dos funciones que uso. Se basan en rotaciones de matriz. y puede rotar alrededor de ejes arbitrarios. Para rotar usando los ejes del mundo, querrá usar la segunda función, 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);
}
Por lo tanto, debe llamar a estas funciones dentro de su función anim
(requestAnimFrame callback), lo que da como resultado una rotación de 90 grados en el eje x:
var xAxis = new THREE.Vector3(1,0,0);
rotateAroundWorldAxis(mesh, xAxis, Math.PI / 180);
Necesitaba la función rotateAroundWorldAxis
, pero el código anterior no funciona con la versión más reciente (r52). Parece que getRotationFromMatrix()
fue reemplazado por 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 );
}
Por si acaso ... en r52 el método se llama setEulerFromRotationMatrix
lugar de getRotationFromMatrix
Resolví este problema de esta manera:
Creé el módulo ''ObjectControls'' para ThreeJS que le permite rotar un único OBJECT (o un grupo), y no SCENE.
Incluye la biblioteca
<script src="ObjectControls.js"></script>
Uso:
var controls = new THREE.ObjectControls(camera, renderer.domElement, yourMesh);
Aquí puede encontrar una demostración en vivo: https://albertopiras.github.io/threeJS-object-controls/
Aquí está el repositorio: https://github.com/albertopiras/threeJS-object-controls .
con r55 tienes que cambiar
rotationMatrix.multiplySelf (object.matrix);
a
rotationMatrix.multiply (object.matrix);