web-dev-qa-db-fra.com

trois js comment faire pivoter autour du centre de l'objet, au lieu du centre du monde

enter image description here

deux objets dans la scène. l'axe de rotation du cube devrait être le centre du cube, c'est mon attente.

mais l'axe de rotation du modèle de chaussure est l'axe y du monde.

mon code d'origine est.

cube.rotation.y += 0.01;
shoe.rotation.y += 0.01;

J'ai trouvé une solution dans stackoverflow, comme ceci:

cube.rotation.y += 0.01;
var pivot = new THREE.Object3D();
pivot.add(shoe);
pivot.rotation.y += 0.01;

Mais ça ne marche pas. Et puis, je change la position de la chaussure.

cube.rotation.y += 0.01;
var pivot = new THREE.Object3D();
shoe.position.set(-5,0,0);
pivot.add(shoe);
pivot.rotation.y += 0.01;

Le résultat est meilleur maintenant, mais il n'est toujours pas parfait. Et comme il y a beaucoup de modèles de chaussures, je ne peux pas déterminer de position différente pour chaque modèle de chaussure.

40
Jinceon

Si votre maillage ne tourne pas autour de son centre, c'est parce que les sommets de la géométrie sont décalés par rapport à l'origine.

Vous pouvez automatiser le repositionnement en utilisant une boîte englobante pour définir un centre raisonnable, puis décaler la position du maillage comme suit:

var box = new THREE.Box3().setFromObject( mesh );
box.center( mesh.position ); // this re-sets the mesh position
mesh.position.multiplyScalar( - 1 );

Ajoutez ensuite le maillage à un objet pivot:

var pivot = new THREE.Group();
scene.add( pivot );
pivot.add( mesh );

Dans votre boucle d'animation, faites pivoter le pivot;

pivot.rotation.y += 0.01;

EDIT: ne solution différente consiste à traduire les sommets de la géométrie afin que la géométrie soit centrée autour ou près de l'origine:

geometry.translate( distX, distY, distZ );

Ou, vous pouvez également appeler:

geometry.center();

qui centre pour vous les sommets de la géométrie en fonction du cadre de délimitation de la géométrie.

three.js r.97

38
WestLangley

Utilisez THREE.Geometry.prototype.center comme suit:

myGeometry.center();

C'est comme utiliser myGeometery.translate (x, y, z) avec centrage automatique (x, y, z).

21
Samuel Danielson

La solution pivot ne fonctionnait pas pour moi.

Avec OBJLoader.js (pour charger des objets .obj), vous devez obtenir le BoundingBox de l'objet, obtenir son centre, multiplier le scalaire par -1 et l'utiliser pour traduire la géométrie de la géométrie de CHAQUE enfant. Ensuite, vous devez mettre à jour le boundingBox si vous souhaitez l'utiliser à des fins.

Voici une fonction qui charge un obj et "normalise" ses sommets de géométrie, étant donné le répertoire et le nom des fichiers OBJ et MTL (texture) (par exemple, si les fichiers OBJ et MTL sont dir1/myObject.obj et dir1/myObject .mtl, alors vous appelez loadObj ('dir1', 'myObject')).

 function loadObj(dir, objName) {
        var onProgress = function(xhr) {
            if (xhr.lengthComputable) {
                var percentComplete = xhr.loaded / xhr.total * 100;
                console.log(Math.round(percentComplete, 2) + '% downloaded');
            }
        };

        var onError = function(xhr) {};

        // Manager
        var manager = new THREE.LoadingManager();
        manager.onProgress = function(item, loaded, total) {
            console.log( 'Started loading file: ' + item + '.\nLoaded ' + loaded + ' of ' + total + ' files.' );
        };

        var mtlLoader = new THREE.MTLLoader();
        mtlLoader.setPath(dir);
        mtlLoader.load(objName + '.mtl', function(materials) {
            materials.preload();

            // Model
            var loader = new THREE.OBJLoader(manager);
            loader.setMaterials(materials);
            loader.setPath(dir);
            loader.load(objName + '.obj', function (object) {

            var objBbox = new THREE.Box3().setFromObject(object);

            // Geometry vertices centering to world axis
            var bboxCenter = objBbox.getCenter().clone();
            bboxCenter.multiplyScalar(-1);

            object.traverse(function (child) {
                if (child instanceof THREE.Mesh) {
                    child.geometry.translate(bboxCenter.x, bboxCenter.y, bboxCenter.z);
                }
            });

            objBbox.setFromObject(object); // Update the bounding box

            scene.add(object);
            }, onProgress, onError);
        });
    }
5
Manuel Dipre

Voici comment j'ai fait fonctionner les choses sur R86

// Store original position
let box = new THREE.Box3().setFromObject(this.mesh);
let offset = box.getCenter();

// Center geometry faces
this.geometry.center();

// Add to pivot group
this.group = new THREE.Object3D();
this.group.add(this.mesh);

// Offset pivot group by original position
this.group.position.set(offset.x, offset.y, offset.z);
1
Dustin Silk