有什么方法可以从three.js Object3D 中获取边界框?

IT技术 javascript three.js
2021-02-23 13:23:01

我正在使用 Three.js 和 OBJLoader.js 加载 OBJ 文件。这将返回一个 Three.Object3D 对象,它具有您对 3D 模型的期望(位置向量、向上向量...)

我想不通的是如何为它获得一个边界框——这可能吗?

4个回答

您不需要遍历对象的所有子项;库中有一种方法可以执行此操作THREE.Box3#setFromObject::请参阅文档例如,您可以执行以下操作:

var bbox = new THREE.Box3().setFromObject(obj);

获取 的边界框obj,包括其所有子项,并考虑任何平移、旋转等。

请注意,BoundingBox助手旨在在场景中绘制边界框,而不仅仅是计算某个对象的边界框。

这个答案很好,但可能效率低下。此函数将遍历整个层次结构以及所有顶点。一个好主意是调用geometry.computeBoundingBox()所有网格,并创建一个使用所有场景边界框扩展主边界框的函数。
2021-04-19 13:23:01
感谢这个伟大而简洁的答案。只是想指出的是链接到文档改为看到的文档虽然
2021-04-23 13:23:01
这是这里最好的答案
2021-05-03 13:23:01

如果您想要对象出现在场景中时的边界框位置和大小,请尝试使用 BoundingBoxHelper:

var helper = new THREE.BoundingBoxHelper(someObject3D, 0xff0000);
helper.update();
// If you want a visible bounding box
scene.add(helper);
// If you just want the numbers
console.log(helper.box.min);
console.log(helper.box.max);

.boundingBox对几何形状不占平移,旋转或缩放可以应用于父网等,我发现它非常难以调整为手动,但助手会为你。

请注意,BoundingBoxHelper已被弃用,并被BoxHelper取代
2021-04-26 13:23:01

对于任何形状,在其几何对象上都有一个boundingBox属性。这个属性持有一个THREE.Box3对象。这个Box3对象由两个对象组成THREE.Vector3minmax

var geometry = new THREE.CylinderGeometry(...);
var material = new THREE.LineBasicMaterial(...);
var mesh = new THREE.Mesh(geometry, material);

var boundingBox = mesh.geometry.boundingBox.clone();
alert('bounding box coordinates: ' + 
    '(' + boundingBox.min.x + ', ' + boundingBox.min.y + ', ' + boundingBox.min.z + '), ' + 
    '(' + boundingBox.max.x + ', ' + boundingBox.max.y + ', ' + boundingBox.max.z + ')' );

对于更复杂的形状,例如从JSON 对象文件加载的形状,默认情况下未定义边界框属性。它必须明确计算。

var loader = new THREE.ObjectLoader();
loader.load(imagePath, function(object){

    geometry = object.children[0].children[0].geometry;  // substitute the path to your geometry

    geometry.computeBoundingBox();  // otherwise geometry.boundingBox will be undefined

    var boundingBox = geometry.boundingBox.clone();
    alert('bounding box coordinates: ' + 
        '(' + boundingBox.min.x + ', ' + boundingBox.min.y + ', ' + boundingBox.min.z + '), ' + 
        '(' + boundingBox.max.x + ', ' + boundingBox.max.y + ', ' + boundingBox.max.z + ')' );
}
如果您想执行例如鼠标选择,您可以使用来自的值geometry.boundingBox并创建您自己的与此类似的框:var box = new THREE.Mesh( new THREE.CubeGeometry(width, height, depth), new THREE.MeshLambertMaterial({ color : 0xFFF0FF }) );我倾向于将其附加到Object3DMesh有问题。然后,您可以对该对象进行光线投射或执行碰撞(或其他)。
2021-04-18 13:23:01
谢谢乔德斯。但是,我仍然不清楚如何/是否可以获得Object3D类本身的边界框我是否需要遍历它的所有子项并查找Mesh类型、保存它们的边界框并以这种方式比较和计算最大 x/y/z 值?
2021-05-02 13:23:01

是的,你需要这样的东西:

if (object instanceof THREE.Object3D)
{
    object.traverse (function (mesh)
    {
        if (mesh instanceof THREE.Mesh)
        {
            mesh.geometry.computeBoundingBox ();
            var bBox = mesh.geometry.boundingBox;

            // compute overall bbox
            minX = Math.min (minX, bBox.min.x);
            minY = Math.min (minY, bBox.min.y);
            minZ = Math.min (minZ, bBox.min.z);
            maxX = Math.max (maxX, bBox.max.x);
            maxY = Math.max (maxY, bBox.max.y);
            maxZ = Math.max (maxZ, bBox.max.z);
        }
    });

    var bBox_min = new THREE.Vector3 (minX, minY, minZ);
    var bBox_max = new THREE.Vector3 (maxX, maxY, maxZ);
    var bBox_new = new THREE.Box3 (bBox_min, bBox_max);

    scene.add (object);
}

编辑:

此方法在BoundingBoxHelper()BoxHelper()可用之前

我只想补充一点,您可能想要做类似 minX = Math.min (minX, bBox.min.x + mesh.position.x ); 用于计算整个框,以防万一对象的某些子项已放置在 ( 0 , 0 , 0 ) 以外的位置
2021-04-22 13:23:01
谢谢,这正是我要找的
2021-05-16 13:23:01