Accurate GLTF bounding box

I am trying to calculate the bounding box of a GLTF model I load but the simple approach:

const bbox = new THREE.BoxHelper( gltf.scene, 0xffff00 );

is inaccurate for this model - works for the models included in the Three.js distribution:

That suggested to me that the model is authored incorrectly and would need to be redone but if I load it into a 3rd party GLTF Viewer that supports display of a bounding box, it appears to be correct so I think that means there is a way to update the bounds.

I’ve tried lots of ways (from posts here) to fix this without success - can anyone point me at the right solution?

1 Like

The usual cause here is that a skinnedmesh’s bounds are derived from the influence of its skeleton on the vertices. THREE.BoxHelper does not compute all of that, just the size of the base geometry before any skinning deformation.

The SkinnedMesh.boneTransform method could be compute updated vertex positions with skinning included, do that for every vertex and you’ll get the accurate bounding box. This would be fairly expensive to do on every frame, though.

Understood and thank you. I only have to do this once - the ultimate goal once I have an accurate bounding box is to fit the model to the viewport and save off the result as a PNG. This is the last piece of the puzzle I have to solve.

could you go into more detail with this one? i have the same problem, this is for instance the reason for why on pmndrs market some models have the shadow piercing the model, like this one pmndrs market - this happens when they’re skinned. how can we use boneTransform in combination with box3? i would also need it just once.

Here’s code for accurately fitting a THREE.Box3 to a THREE.SkinnedMesh —

const vector = new THREE.Vector3();
const box = new THREE.Box3().makeEmpty();
const position = mesh.geometry.attributes.position;

for ( let i = 0, il = position.count; i < il; i ++ ) {

	vector.fromBufferAttribute( position, i );
	mesh.boneTransform( i, vector );
	mesh.localToWorld( vector );
	box.expandByPoint( vector );

}

The code above computes the bounding box in world space; omit localToWorld if you prefer local space.

Preview:

NOTE: Only some portions of this character are skinned. I included only the skinned portions in this capture, which is why the legs do not display a bbox, but that’s an unusual situation.

2 Likes

incredible, thank you! i will try to add this to drei/stage.

btw what is this game or website in your preview? it is beautiful …

2 Likes

New IK example :slight_smile:

1 Like