enter image description here

Два объекта в сцене. ось вращения куба должна быть центром куба, это я и ожидал.

Но ось вращения модели обуви - это мировая ось y.

Мой исходный код.

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

Я нашел решение в stackoverflow, например:

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

Но не работает. Затем я меняю положение обуви.

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

Результат сейчас лучше, но все еще не идеален. А поскольку моделей обуви много, я не могу определить разное положение для каждой модели обуви.

62
Jinceon 4 Мар 2015 в 10:35

5 ответов

Лучший ответ

Если ваша сетка не вращается вокруг своего центра, это потому, что вершины геометрии смещены от начала координат.

Вы можете автоматизировать изменение положения, используя ограничивающую рамку, чтобы определить разумный центр, а затем сместить положение сетки следующим образом:

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

Затем добавьте сетку к объекту сводки:

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

В цикле анимации поверните стержень;

pivot.rotation.y += 0.01;

РЕДАКТИРОВАТЬ: Другое решение - перевести геометрию вершины, чтобы геометрия центрировалась вокруг или около начала координат:

geometry.translate( distX, distY, distZ );

Или, как вариант, вы можете просто позвонить:

geometry.center();

Который центрирует вершины геометрии для вас на основе ограничивающей рамки геометрии.

Three.js r.97

47
WestLangley 2 Окт 2018 в 17:40

Если имеется несколько сеток (что является наиболее распространенным), установите положение родительского узла в графе сцены, чтобы достичь цели центрирования модели. Если граф сцены похож на этот gltfObject -> childObject -> .. -> массив мешей

const bbox = new THREE.Box3().setFromObject( gltfObject );
const offset = new THREE.Vector3();
bbox.getCenter(offset).negate();
childObject.position.set(offset.x, offset.y, offset.z);
1
Ajay 5 Янв 2020 в 19:17

Вот как я получил работу на 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 7 Май 2017 в 21:47

Сводное решение у меня не сработало.

С помощью OBJLoader.js (для загрузки объектов .obj) вам необходимо получить ограничивающий блок объекта, получить его центр, умножить скаляр на -1 и использовать это для преобразования геометрии КАЖДОЙ дочерней геометрии. Затем вам нужно обновить boundingBox, если вы хотите использовать его для определенной цели.

Вот функция, которая загружает объект и «нормализует» его геометрические вершины, учитывая каталог и имя файлов OBJ и MTL (текстуры) (например, если файлы OBJ и MTL - это dir1 / myObject.obj и dir1 / myObject .mtl, затем вы вызываете 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);
        });
    }
9
Manuel Dipre 3 Фев 2017 в 12:14

Используйте THREE.Geometry.prototype.center следующим образом:

myGeometry.center();

Это похоже на использование myGeometery.translate (x, y, z) с автоматическим центрированием (x, y, z).

27
Samuel Danielson 24 Май 2016 в 11:38