49

I'm loading an OBJ file using Three.js and OBJLoader.js. This returns a Three.Object3D object, which has what you'd expect from a 3D model (position vector, up vector...)

What I can't figure out is how to get a bounding box for it-- is this possible?

Share a link to this question
CC BY-SA 3.0
90

You don't need to iterate over all children of the object; there's a method in the library to do this: THREE.Box3#setFromObject: see the docs. For example, you can do:

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

to get the bounding box of obj, including all of its children, and accounting for any translations, rotations, etc.

Note that the BoundingBox helper is intended to draw a bounding box in the scene, not for just calculating the bounding box of some object.

Share a link to this answer
CC BY-SA 3.0
3
  • 5
    this the best answer here – Jared Nov 24 '14 at 20:20
  • thanks for this great and concise answer. Just wanted to point out that the link to the docs changed to see the docs though – burnedikt Sep 6 '17 at 16:21
  • 2
    This answer is good, but can be inefficient. This function retraverse the whole hierarchy, as well as all the vertices. A good idea would be to call geometry.computeBoundingBox() on all meshes, and create a function that expand the main bounding box using all the scene bounding boxes. – David Peicho Jul 5 '18 at 14:38
30

If you want the bounding box position and size as the object appears in the scene, try the 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);

The .boundingBox on the geometry doesn't account for translations, rotations, or scaling that may be applied to the parent mesh and etc. and I found it very difficult to adjust for that manually, but the helper does it for you.

Share a link to this answer
CC BY-SA 3.0
1
18

For any shape, on its geometry object, there is a boundingBox property. This property holds a THREE.Box3 object. This Box3 object consists of two THREE.Vector3 objects, min and max.

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

For more complex shapes, like those loaded from JSON Object files, the bounding box property is undefined by default. It must be computed explicitly.

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 + ')' );
}
Share a link to this answer
CC BY-SA 3.0
2
  • 1
    Thank you Jodes. However I'm still not clear how/if I can get a bounding box for the Object3D class itself. Do I need to walk through all its children and look for Mesh types, save their bounding boxes and compare and compute the maximum x/y/z values that way? – larryq Mar 19 '13 at 15:06
  • If you want to perform e.g. mouse-picking, you use the values from geometry.boundingBox and create your own box similar to this: var box = new THREE.Mesh( new THREE.CubeGeometry(width, height, depth), new THREE.MeshLambertMaterial({ color : 0xFFF0FF }) ); I tend to attach this to the Object3D or Mesh in question. You can then raycast against that object or perform collisions (or whatever). – Engineer Feb 20 '14 at 1:01
12

Yes you would need something like this:

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);
}

EDIT:

This method is before the BoundingBoxHelper() or BoxHelper() were available

Share a link to this answer
CC BY-SA 3.0
1
  • I would just like to add that you may want to do something like minX = Math.min (minX, bBox.min.x + mesh.position.x ); for computing the overall box, just in case some of the children of the object have been placed at locations other than ( 0 , 0 , 0 ) – Cabbibo Jun 4 '14 at 20:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.