Bounding box calculation not correct based on Blender glb export

I have a problem when exporting a box from Blender to *.glb and calculate it’s BBOX in ThreeJs.

When using the exported box in ThreeJs the boundingbox seems to keep the world zero point in its calculation. Not sure why.

The Blender setup:

The result in ThreeJs for the BBOX:
threeJs

The code in ThreeJs:

        const boundingBox = new THREE.Box3();
        scene.traverse(function (object)
        {
            if (object.isMesh) 
                boundingBox.expandByObject(object, true);
        });



        //Make mesh from box3 to show in box helper
        // make a BoxGeometry of the same size as Box3
        const dimensions = new THREE.Vector3().subVectors( boundingBox.max, boundingBox.min );
        const boxGeo = new THREE.BoxGeometry(dimensions.x, dimensions.y, dimensions.z);
        // move new mesh center so it's aligned with the original object
        const matrix = new THREE.Matrix4().setPosition(dimensions.addVectors(boundingBox.min, boundingBox.max).multiplyScalar( 0.5 ));
        boxGeo.applyMatrix4(matrix);
        // make a mesh
        const mesh = new THREE.Mesh(boxGeo);


        let helper = new THREE.BoxHelper(mesh, 0xff0000);
        helper.update();
        scene.add(helper);

This code:

        const boundingBox = new THREE.Box3();
        scene.traverse(function (object)
        {
            if (object.isMesh) 
                boundingBox.expandByObject(object, true);
        });

Will expand the empty bounding box starting from 0,0,0. You don’t want this.

instead you want:

const boundingBox = new THREE.Box3();
boundingBox.setFromObject(scene);
3 Likes

I see.

I need to filter for meshes only. That’s why I couldn’t use the scene as feed for the BBOX calculation. Unless there is another way to do this?

I understand my problem now.
Because the Vector3 is initialized as a zero vector and I expand from there with expandByObject for other bounding boxes it keeps track of the world zero point.

I fixed this by doeing setFromObject(object) for the first encounter and expand starting from the second encounter.

Thanks for the insight.

Revised code:

        //Find all the meshes to set BBOX
        let boundingBox = null;
        scene.traverse(function (object)
        {
            if (object.isMesh) 
            {
                console.log(object);

                if(object.name == "")
                    return;

                if(boundingBox == null)
                    boundingBox = new THREE.Box3().setFromObject(object);
                else
                    boundingBox.expandByObject(object, true);
            }
        });


        //Make mesh from box3 to show in box helper
        // make a BoxGeometry of the same size as Box3
        const dimensions = new THREE.Vector3().subVectors( boundingBox.max, boundingBox.min );
        const boxGeo = new THREE.BoxGeometry(dimensions.x, dimensions.y, dimensions.z);
        // move new mesh center so it's aligned with the original object
        const matrix = new THREE.Matrix4().setPosition(dimensions.addVectors(boundingBox.min, boundingBox.max).multiplyScalar( 0.5 ));
        boxGeo.applyMatrix4(matrix);
        // make a mesh
        const mesh = new THREE.Mesh(boxGeo);


        let helper = new THREE.BoxHelper(mesh, 0xff0000);
        helper.update();
        scene.add(helper);

You probably don’t need to traverse. You can just call it on the scene. It traverses for you. iirc it only looks at meshes anyway. i.e. objects that have a .geometry

https://threejs.org/docs/#api/en/math/Box3.setFromObject

edit: Oh i see you are filtering unnamed meshes… ok. then ya… you should be good to go with your traversal. :slight_smile:

1 Like