web-dev-qa-db-fra.com

Comment faire pivoter des lunes autour d'une planète avec THREE.js?

Je pense que cette image explique le mieux mon problème:

hooray for optical illusions

Je traduis d'abord la boîte le long de la ligne rouge. Ensuite, je veux que l'effet de rotation soit la ligne bleue dans a, mais ce qui se passe réellement ressemble plus à la ligne bleue dans b. Il semble que la modification de la rotation soit toujours relative à l'espace objet d'origine, mais la translation (bien qu'elle se produise en premier) est toujours relative au parent, et n'affecte pas vraiment les points de géométrie par rapport à l'espace objet. Je m'excuse si c'est déroutant; clairement, je suis nouveau dans ce domaine.

La partie importante du code qui produit cet effet est ci-dessous. Veuillez garder à l'esprit que l'orientation de l'image est différente de celle produite par ce code; l'image n'est qu'un exemple pour montrer clairement l'effet.

var objectContainer = new THREE.Object3D();

var tubeRadius = 100;
var tubeGeometry = new THREE.CylinderGeometry(tubeRadius, tubeRadius, tubeRadius * 3, 36, 1, false);
var tube = new THREE.Mesh(tubeGeomtry, material);
scene.add( tube );

var boxes = new THREE.Object3D();
var boxEdge = 50;
var boxGeometry = new THREE.CubeGeometry(boxEdge, boxEdge, boxEdge);
var box1 = new THREE.Mesh( boxGeometry, material );
box1.translateX(tubeRadius + boxEdge / 2 + 5);
box1.translateY(boxEdge / 2);
box1.rotation = new THREE.Vector3(0, 2*Math.PI/3*0, 0);
boxes.add(box1);
var box2 = box1.clone();
box2.rotation = new THREE.Vector3(0, 2*Math.PI/3*1, 0);
boxes.add(box2);
var box3 = box1.clone();
box3.rotation = new THREE.Vector3(0, 2*Math.PI/3*2, 0);
boxes.add(box3);
scene.add( boxes );

La seule solution à laquelle je peux penser est d'envelopper chaque boîte dans un autre espace objet et de la faire pivoter, mais cela semble être un travail excessif. Quelle est la méthode préférée pour obtenir le résultat que je recherche?

31
Nick Larsen

Il y a plusieurs façons de faire ce que vous voulez, mais je pense que la plus simple est la suivante:

// parent
parent = new THREE.Object3D();
scene.add( parent );

// pivots
var pivot1 = new THREE.Object3D();
var pivot2 = new THREE.Object3D();
var pivot3 = new THREE.Object3D();

pivot1.rotation.z = 0;
pivot2.rotation.z = 2 * Math.PI / 3;
pivot3.rotation.z = 4 * Math.PI / 3;

parent.add( pivot1 );
parent.add( pivot2 );
parent.add( pivot3 );

// mesh
var mesh1 = new THREE.Mesh( geometry, material );
var mesh2 = new THREE.Mesh( geometry, material );
var mesh3 = new THREE.Mesh( geometry, material );

mesh1.position.y = 5;
mesh2.position.y = 5;
mesh3.position.y = 5;

pivot1.add( mesh1 );
pivot2.add( mesh2 );
pivot3.add( mesh3 );

Puis dans votre boucle de rendu:

parent.rotation.z += 0.01;

EDIT: violon mis à jour: http://jsfiddle.net/hbt9c/317/

three.js r.70

32
WestLangley

Créer un objet composé dont le centre sera le point autour duquel les objets intérieurs tournent est une réponse évidente et serait très rapide à écrire. Créez simplement un Object3D et ajoutez-y votre boîte.

Une approche similaire est couverte par cette question . Il déplace le point des sommets d'un objet, de sorte qu'il a effectivement un nouveau centre.

Alternativement, vous pouvez jouer avec les matrices à la main. Essaye ça:

var boxGeometry = new THREE.CubeGeometry(boxEdge, boxEdge, boxEdge);
var mr = new THREE.Matrix4();
var mt = new THREE.Matrix4();
mt.setPosition(new THREE.Vector3(0,tubeRadius,0));
var box1 = new THREE.Mesh( boxGeometry, material );
box1.applyMatrix(mt);
var box2 = box1.clone();
mr.makeRotationZ(2 * Math.PI /3);
box2.applyMatrix(mr);
boxes.add(box2);
var box3 = box1.clone();
mr.makeRotationZ(4 * Math.PI /3);
box3.applyMatrix(mr);
boxes.add(box3);
boxes.add(box1);
scene.add( boxes );
6
CL22