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

Posted

技术标签:

【中文标题】有啥方法可以从 three.js Object3D 中获取边界框?【英文标题】:Any way to get a bounding box from a three.js Object3D?有什么方法可以从 three.js Object3D 中获取边界框? 【发布时间】:2013-03-07 17:39:39 【问题描述】:

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

我不知道如何为其获取边界框——这可能吗?

【问题讨论】:

【参考方案1】:

您不需要遍历对象的所有子对象;库中有一种方法可以做到这一点:THREE.Box3#setFromObject:see the docs。例如,您可以这样做:

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

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

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

【讨论】:

这是最好的答案 感谢您提供如此简洁的答案。只是想指出文档的链接更改为see the docs 这个答案很好,但可能效率低下。此函数会遍历整个层次结构以及所有顶点。一个好主意是在所有网格上调用geometry.computeBoundingBox(),并创建一个使用所有场景边界框扩展主边界框的函数。【参考方案2】:

如果您希望边界框的位置和大小与对象出现在场景中一样,请尝试使用 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 已被deprecated 取代,并被BoxHelper 取代。【参考方案3】:

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

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 Object files 加载的形状,默认情况下未定义边界框属性。必须显式计算。

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 + ')' );

【讨论】:

谢谢乔德斯。但是,我仍然不清楚如何/是否可以获得Object3D 类本身的边界框。我是否需要遍历它的所有子元素并查找 Mesh 类型,保存它们的边界框并以这种方式比较和计算最大 x/y/z 值? 如果你想执行例如鼠标选择,您使用来自geometry.boundingBox 的值并创建您自己的类似于此的框:var box = new THREE.Mesh( new THREE.CubeGeometry(width, height, depth), new THREE.MeshLambertMaterial( color : 0xFFF0FF ) ); 我倾向于将此附加到有问题的Object3DMesh。然后,您可以针对该对象进行光线投射或执行碰撞(或其他)。【参考方案4】:

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

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 ) 以外的位置 谢谢,这正是我想要的

以上是关于有啥方法可以从 three.js Object3D 中获取边界框?的主要内容,如果未能解决你的问题,请参考以下文章

Three.js Object3D 缺少 isMesh、Material 和 Geometry 属性?

Three.js源码解读一:Object3D

three.js 在它的中心围绕 Y 轴旋转 Object3d

Three.js Object3d 圆柱体旋转以对齐向量

有啥方法可以使用 three.js 渲染 Uint8ClampedArray imageData?

一些关于three.js的摘抄笔记