Three.js: 复合的Object3D对象的BoundingBox?

创建于 2011-09-26  ·  15评论  ·  资料来源: mrdoob/three.js

大家好,

我有一个Object3D实例,其中包括CubeGeometry和TextGeometry。 我的问题:有可能获得
这种复合几何的边界框? 我问这个问题,因为我看到Object3D类没有boundingBox-Method
而且我没有办法为包括在Object3D容器中的所有对象计算它。

我的想法是根据Object3D容器的中心类来使相机居中,因此我必须知道boundingBox。

问候roundrobin

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

有了这种方式,您只需要遵循此步骤即可

到目前为止,谢谢。 也许我问错了,我的目的是要得到两个对象的边界框。 我知道如何计算一个几何的边界框,但是当我有一个复合3D对象时,如何计算边界框,例如两个立方体。 还是必须先将对象合并为一个几何体?

我希望你明白我的意思:)这很难解释。

我懂了。 我想现在唯一的方法是比较所有边界框,并用所有值做一些max()min() s。

好的谢谢。 如果成功,我会发布解决方案

这是我的解决方案。 只需将对象传递给此函数,它就会查看其子元素以计算对象的高度/宽度,并为该对象分配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看起来不错!

我有两年前与roundrobin完全相同的问题和相同的想法。 @NickLarsen的解决方案看起来非常好,就像@mrdoob所说的那样,但是有一个大问题……我将尽力解释。

在我的场景中,总是有一个包含所有几何图形的Object3D。 例如,我有8个球体,它们具有不同的半径和不同的y坐标。 它们都位于x = 0和z = 0。
然后,我尝试使用NickLarsen的函数计算整个边界框,但结果非常奇怪。 为了找到错误,我将所有单个边界框都记录到控制台:

({min:{x:-10,y:-10,z:-10},max:{x:10,y:10,z:10}})
({min:{x:-20,y:-20,z:-20},max:{x:20,y:20,z:20}})
({最小:{x:-7,y:-7,z:-7},最大:{x:7,y:7,z:7}})
({min:{x:-18,y:-18,z:-18},max:{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}})
({min:{x:-10,y:-10,z:-10},max:{x:10,y:10,z:10}})
({min:{x:-25,y:-25,z:-25},max:{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 等级