web-dev-qa-db-ja.com

3つのjs世界の中心ではなく、オブジェクトの中心を中心に回転する方法

enter image description here

シーン内の2つのオブジェクト。キューブ回転軸はキューブの中心である必要があります、それは私の期待です。

しかし、靴モデルの回転軸は世界の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;

結果は改善されましたが、まだ完全ではありません。靴のモデルはたくさんあるので、靴のモデルごとに異なる位置を決定することはできません。

40
Jinceon

メッシュがその中心の周りを回転していない場合、ジオメトリの頂点が原点からオフセットされているためです。

バウンディングボックスを使用して適切な中心を定義し、メッシュの位置を次のようにオフセットすることにより、再配置を自動化できます。

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

38
WestLangley

THREE.Geometry.prototype.centerを次のように使用します。

myGeometry.center();

これは、myGeometery.translate(x、y、z)と自動センタリング(x、y、z)を使用するようなものです。

21

ピボットソリューションはうまくいきませんでした。

OBJLoader.js(.objオブジェクトの読み込み用)では、オブジェクトのboundingBoxを取得し、その中心を取得し、スカラーに-1を乗算し、これを使用してすべての子のジオメトリのジオメトリを変換する必要があります。次に、目的に使用する場合は、boundingBoxを再更新する必要があります。

以下は、OBJおよびMTL(テクスチャ)ファイルのディレクトリと名前を指定して、objをロードし、ジオメトリ頂点を「正規化」する関数です(たとえば、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);
        });
    }
5
Manuel Dipre

私が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