Three.js: 複合Object3DオブジェクトのBoundingBox?

作成日 2011年09月26日  ·  15コメント  ·  ソース: mrdoob/three.js

こんにちはみんな、

CubeGeometryとTextGeometryを含むObject3Dインスタンスがあります。 私の質問:取得することは可能です
この複合ジオメトリのバウンディングボックス? Object3DクラスにboundingBox-Methodがないことがわかったので、これを尋ねます
Object3Dコンテナに含まれるすべてのオブジェクトについて計算する方法がありません。

私の考えは、Object3D-コンテナの重心に応じてカメラを中央に配置することでした。したがって、boundingBoxを知る必要があります。

ラウンドロビンのご挨拶

Question

最も参考になるコメント

私は同じことを探してこれに出くわし、これに落ち着きました:

function getCompoundBoundingBox(object3D) {
    var box = null;
    object3D.traverse(function (obj3D) {
        var geometry = obj3D.geometry;
        if (geometry === undefined) return;
        geometry.computeBoundingBox();
        if (box === null) {
            box = geometry.boundingBox;
        } else {
            box.union(geometry.boundingBox);
        }
    });
    return box;
}

全てのコメント15件

Object3Dはバウンディングボックスを計算する方法がありませんが、 Geometryはあります。

それが邪魔にならないように、あなたはこれに従う必要があります。

これまでのところありがとう。 多分私は間違って尋ねます、私の意図は2つのオブジェクトのバウンディングボックスを取得することでした。 1つのジオメトリの境界ボックスを計算する方法は知っていますが、複合3Dオブジェクトがある場合、たとえば2つの立方体の境界ボックスを計算する方法を知っています。 または、前のオブジェクトを1つのジオメトリにマージする必要がありますか?

私の主張を理解していただければ幸いです:)説明するのは難しいです。

そうですか。 今のところ唯一の方法は、すべてのバウンディングボックスを比較し、すべての値を使用してmax()min()を実行することだと思います。

大丈夫ありがとう。 成功したらソリューションを投稿します

これが私の解決策です。 オブジェクトをこの関数に渡すだけで、子を調べてオブジェクトの高さ/幅を計算し、heightとwidthのプロパティをオブジェクトに割り当てます。


calculateDimensions(myObject);

...

/*
* Get the size of the compound object by computing the bounding box and getting the max/min of each of its children
*/
function calculateDimensions(_object) {

    var absoluteMinX = 0, absoluteMaxX = 0, absoluteMinY = 0, absoluteMaxY = 0, absoluteMinZ = 0, absoluteMaxZ = 0;

    for (var i = 0; i < _object.children.length; i++) {
        _object.children[i].geometry.computeBoundingBox();
        absoluteMinX = Math.min(absoluteMinX,_object.children[i].geometry.boundingBox.min.x);
        absoluteMaxX = Math.max(absoluteMaxX,_object.children[i].geometry.boundingBox.max.x);
        absoluteMinY = Math.min(absoluteMinY,_object.children[i].geometry.boundingBox.min.y);
        absoluteMaxY = Math.max(absoluteMaxY,_object.children[i].geometry.boundingBox.max.y);
        absoluteMinZ = Math.min(absoluteMinZ,_object.children[i].geometry.boundingBox.min.z);
        absoluteMaxZ = Math.max(absoluteMaxZ,_object.children[i].geometry.boundingBox.max.z);
    }

    // set generic height and width values
    _object.depth = (absoluteMaxX - absoluteMinX) * _object.scale.x;
    _object.height = (absoluteMaxY - absoluteMinY) * _object.scale.y;
    _object.width = (absoluteMaxZ - absoluteMinZ) * _object.scale.z;

    // remember the original dimensions
    if (_object.originalDepth === undefined) _object.originalDepth = _object.depth;
    if (_object.originalHeight === undefined) _object.originalHeight = _object.height;
    if (_object.originalWidth === undefined) _object.originalWidth = _object.width;

    console.log("Depth: " + _object.depth + ", Height: " + _object.height + ", Width: " + _object.width);
}


私は同じことを探してこれに出くわし、これに落ち着きました:

function getCompoundBoundingBox(object3D) {
    var box = null;
    object3D.traverse(function (obj3D) {
        var geometry = obj3D.geometry;
        if (geometry === undefined) return;
        geometry.computeBoundingBox();
        if (box === null) {
            box = geometry.boundingBox;
        } else {
            box.union(geometry.boundingBox);
        }
    });
    return box;
}

@NickLarsenよさそうだ!

私は2年前のラウンドロビンとまったく同じ問題と同じ考えを持っています。 @mrdoobが言ったように、 @ NickLarsenの解決策は本当に良さそうですが、大きな問題があります...それを説明しようと思います。

私のシーンでは、すべてのジオメトリを含むObject3Dが常に1つあります。 たとえば、半径とy座標が異なる8つの球があります。 それらはすべてx = 0とz = 0にあります。
次に、NickLarsenの関数を使用して境界ボックス全体を計算しようとしましたが、結果は非常に奇妙でした。 エラーを見つけるために、すべての単一の境界ボックスをコンソールに記録しました。

({最小:{x:-10、y:-10、z:-10}、最大:{x:10、y:10、z:10}})
({最小:{x:-20、y:-20、z:-20}、最大:{x:20、y:20、z:20}})
({最小:{x:-7、y:-7、z:-7}、最大:{x:7、y:7、z:7}})
({最小:{x:-18、y:-18、z:-18}、最大:{x:18、y:18、z:18}})
({最小:{x:-15、y:-15、z:-15}、最大:{x:15、y:15、z:15}})
({最小:{x:-3、y:-3、z:-3}、最大:{x:3、y:3、z:3}})
({最小:{x:-10、y:-10、z:-10}、最大:{x:10、y:10、z:10}})
({最小:{x:-25、y:-25、z:-25}、最大:{x:25、y:25、z:25}})

ご覧のとおり、境界ボックスは常に単一の球のローカル座標系で計算されます。 そして、あなたがそれらを結合するとき、それは意味がありません! Object3Dの実際のバウンディングボックスを取得するために、ワールド座標でバウンディングボックスを取得するにはどうすればよいですか?

r.59devブランチで、 Box3.setFromObject( object )参照してください。

@PanChanこれを実行する前に変換をパーコレーションする必要があり、意図したとおりに機能します。 これを実際に使用する場合、バウンディングボックスを計算する前に、各オブジェクトのジオメトリを複製し、それに変換を適用します。 ここで私の実際の実装を見ることができ

@NickLarsenうまくいくように見える別の解決策を見つけました。 バウンディングボックスを計算した後、それをワールドシステムに変換します。

var bb = geometry.boundingBox;
bb.translate(obj3D.localToWorld( new THREE.Vector3()));

それが良い解決策かどうかはわかりませんが、今のところは機能します。 私はプロのソリューションで新しい改訂を待っていると思います;)説明をありがとう!

私のプロジェクトで@NickLarsenソリューションを使用すると、オブジェクトのバウンディングボックスがすでに存在する場合に少し最適化された計算であるため、再度計算する必要はありません。

function getComplexBoundingBox(object3D) {
    var box = null;
    object3D.traverse(function(obj3D) {
        if (obj3D.matrixWorldNeedsUpdate) obj3D.updateMatrixWorld();
        var geometry = obj3D.geometry;
        // If current is not a geometry (THREE.Geometry), proceed to the next one
        if (geometry === undefined) return null;
        // If this object is already bounding box, then use it
        if (geometry.boundingBox) { 
            var workableBox = geometry.boundingBox.clone();
            // Move the resulting bounding box to the position of the object itself
            workableBox.applyMatrix4(obj3D.matrixWorld);
            if (box === null) {
                box = workableBox;
            } else {
                box.union(workableBox);
            }
        // If there is no bounding box for current object - creating
        } else {
            var workableGeometry = geometry.clone();
            // Move the resulting geometry in the position of the object itself
            workableGeometry.applyMatrix(obj3D.matrixWorld);
            // Calculate the bounding box for the resulting geometry
            workableGeometry.computeBoundingBox();
            if (box === null) {
                box = workableGeometry.boundingBox;
            } else {
                box.union(workableGeometry.boundingBox);
            }
        }
    });
    return box;
}

5 IF条件-それは確かに良いコードの例ではありませんが、何をすべきか、それでも私はうまくいきませんでしたか? :)

これは本当に古いスレッドです。 今日では、新しいnew THREE.Box3().setFromObject(object3d)ができます

この方法を試してみます、ありがとう!

問題ない。 私は数ヶ月前にこの認識を自分で経験しました: https

このページは役に立ちましたか?
0 / 5 - 0 評価