web-dev-qa-db-fra.com

Comment faire pivoter un objet 3D sur l'axe trois.js?

J'ai un gros problème avec la rotation en trois. Je veux faire pivoter mon cube 3D dans un de mes jeux.

//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

et (x, y, z) peuvent être (1, 0, 0)

le cube peut alors pivoter, mais le problème est que le cube pivote sur son propre axe. Par conséquent, une fois pivoté, il ne peut pas pivoter comme prévu.

Je trouve la page Comment faire pivoter un vecteur Three.js autour d'un axe? , mais laisse-t-il simplement tourner un point Vector3 autour de l'axe du monde?

et j'ai essayé d'utiliser matrixRotationWorld comme

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

mais cela ne fonctionne pas, je ne sais pas si je l'ai utilisé de manière erronée ou par d'autres moyens ..

oui, comment laisser le cube 3D tourner autour de l'axe du monde ???

34
Tony Han

Voici les deux fonctions que j'utilise. Ils sont basés sur les rotations de la matrice. et peut tourner autour d'axes arbitraires. Pour faire pivoter en utilisant les axes du monde, vous voudriez utiliser la deuxième fonction 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);
}

Vous devez donc appeler ces fonctions dans votre fonction anim (callback requestAnimFrame), ce qui entraîne une rotation de 90 degrés sur l'axe des x:

var xAxis = new THREE.Vector3(1,0,0);
rotateAroundWorldAxis(mesh, xAxis, Math.PI / 180);
48
Cory Gross

Depuis la version r59, three.js fournit ces trois fonctions pour faire pivoter un objet autour de son axe.

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

J'avais besoin de la fonction rotateAroundWorldAxis mais le code ci-dessus ne fonctionne pas avec la dernière version (r52). Il semble que getRotationFromMatrix() ait été remplacé par 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 );
}
13
guntrumm

avec r55 vous devez changer
rotationMatrix.multiplySelf (object.matrix);
à
rotationMatrix.multiply (object.matrix);

10
block23

Dans Three.js R59, object.rotation.setEulerFromRotationMatrix(object.matrix); a été remplacé par object.rotation.setFromRotationMatrix(object.matrix);

3js change si rapidement: D

7
mind1n

Juste au cas où ... en r52, la méthode s'appelle setEulerFromRotationMatrix au lieu de getRotationFromMatrix

6
Leprosy

Cela devient plus facile quelque part autour de r59 (rotation autour de x):

bb.GraphicsEngine.prototype.calcRotation = function ( obj, rotationX)
{
    var euler = new THREE.Euler( rotationX, 0, 0, 'XYZ' );
    obj.position.applyEuler(euler);
}
3
acarlon

Dans Three.js R66, voici ce que j'utilise (version 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
2
aymericbeaumet

J'ai résolu ce problème de cette façon:

J'ai créé le module 'ObjectControls' pour ThreeJS qui vous permet de faire pivoter un seul objet (ou un groupe), et non la scène.

Inclure la librairie:

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

Usage:

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

Vous pouvez trouver ici une démonstration en direct ici: https://albertopiras.github.io/threeJS-object-controls/

Voici le référentiel: https://github.com/albertopiras/threeJS-object-controls .

1
Alberto Piras