2017-09-11 17 views
1

私は球のグループをレンダリングするためにThree.js(r86)を使用しています。私は外部のライブラリからcreateSphereGroup関数を呼び出すことにより、これをやっている:子の幅に基づいてTHREE.Groupを中央に揃えるにはどうすればいいですか?

// External library code. 
function createSphereGroup(sphereCount) [ 
    var group = new THREE.Group(); 
    for (var i = 0; i < sphereCount; i++) { 
    var geometry = new THREE.SphereGeometry(50); 
    var material = new THREE.MeshPhongMaterial({ color: 0xFF0000 }); 
    var sphere = new THREE.Mesh(geometry, material); 
    sphere.position.x = i * 150; 
    group.add(sphere); 
    } 
    return group; 
} 

(外部ライブラリが不透明であると私はそれで任意のコードを変更することはできませんと仮定します。)


Screenshot

:次のようになります
// My code. 
var group = createSphereGroup(5); 
scene.add(group); 

...

ご覧のとおり、球のグループは中心から外れています。グループを中心にして、3つ目の球が2つの線が交差する点にあるようにしたい(x=0)。

私はグループを中心にすることができる方法はありますか?多分、グループの幅を計算してから、それをx=-width/2に置くことによって?ジオメトリ上でcomputeBoundingBoxと呼んでその幅を調べることができますが、THREE.Groupにはジオメトリがないので、これを行う方法がわかりません。

答えて

3

、あなたはとてもように、オブジェクトの位置を設定することによって、そうすることができます:良い

var box = new THREE.Box3().setFromObject(object).getCenter(object.position).multiplyScalar(- 1); 

scene.add(object); 

three.js r.87

+0

を!あまりにも遅くハハを見た。 ただし、頂点ごとにボックスの頂点を拡大するので、一度呼び出すほうがよい。 – neeh

1

グループ内のすべてのオブジェクトがむしろのバウンディングボックスを含むバウンディングボックスを作成するために

function computeGroupCenter(count) { 
    var center = new THREE.Vector3(); 
    var children = group.children; 
    var count = children.length; 
    for (var i = 0; i < count; i++) { 
     center.add(children[i].position); 
    } 
    center.divideScalar(count); 
    return center; 
} 

これを行うには、別の(より堅牢)な方法です:同じサイズは、あなたの例のように、あなただけの子供の位置の平均を取ることができますグループのすべての子供。

考慮すべきいくつかの重要な事があります。

  • THREE.Groupしたがって、アルゴリズムは再帰的であるべき
  • バウンディングボックスはローカル空間で計算されている、しかし、オブジェクトが変換することができる、他の人THREE.Groupを含めることができます私たちは世界の空間で働く必要があります。
  • グループ自体が!に翻訳されている可能性があります。だから、私たちは世界の空間からグループのローカルスペースに戻って、グループのスペースにそのセンターを定義する必要があります。

あなたはTHREE.Object3D.traverseTHREE.BufferGeometry.computeBoundingBoxTHREE.Box3.ApplyMatrix4で簡単にこれを達成することができます

/** 
* Compute the center of a THREE.Group by creating a bounding box 
* containing every children's bounding box. 
* @param {THREE.Group} group - the input group 
* @param {THREE.Vector3=} optionalTarget - an optional output point 
* @return {THREE.Vector3} the center of the group 
*/ 
var computeGroupCenter = (function() { 
    var childBox = new THREE.Box3(); 
    var groupBox = new THREE.Box3(); 
    var invMatrixWorld = new THREE.Matrix4(); 

    return function (group, optionalTarget) { 
     if (!optionalTarget) optionalTarget = new THREE.Vector3(); 

     group.traverse(function (child) { 
      if (child instanceof THREE.Mesh) { 
       if (!child.geometry.boundingBox) { 
        child.geometry.computeBoundingBox(); 
        childBox.copy(child.geometry.boundingBox); 
        child.updateMatrixWorld(true); 
        childBox.applyMatrix4(child.matrixWorld); 
        groupBox.min.min(childBox.min); 
        groupBox.max.max(childBox.max); 
       } 
      } 
     }); 

     // All computations are in world space 
     // But the group might not be in world space 
     group.matrixWorld.getInverse(invMatrixWorld); 
     groupBox.applyMatrix4(invMatrixWorld); 

     groupBox.getCenter(optionalTarget); 
     return optionalTarget; 
    } 
})(); 

Here's a fiddleを。あなたがオブジェクト(またはグループ)とその子供たちを中心にしたい場合は

関連する問題