Bounding box bigger than concave object (ExtrudeGeometry)

I create a rectangle with cut or rounded corners using ExtrudeGeometry and after rotating its mesh I get a bounding box larger than this geometry. If I rotate the geometry itself, the problem disappears, but when I group several of these geometries and rotate this group, the problem occurs again. I tried updating matrix and matrixWorld of mesh, but this does not solve the problem. Is it even possible to solve this problem? Thanks



3

I found a solution. You should modify “expandByObject” method of Box3 class like this:

expandByObject(object) {
	object.updateWorldMatrix(false, false);
	const geometry = object.geometry;

	if (geometry !== undefined) {
		object.updateWorldMatrix(true, false);
		geometry.computeBoundingBox(object.matrixWorld);

		_box$3.copy(geometry.boundingBox);

		let m = new Matrix4();
		let v = new Vector3();
		m.setPosition(v.setFromMatrixPosition(object.matrixWorld));
		_box$3.applyMatrix4(m);

		this.union(_box$3);
	}

	const children = object.children;

	for (let i = 0, l = children.length; i < l; i++) {
		this.expandByObject(children[i]);
	}

	return this;
}

and modify “computeBoundingBox” method of BufferGeometry class like this:

computeBoundingBox: function (matrix) {
	if (this.boundingBox === null) {
		this.boundingBox = new Box3();
	}

	const position = this.attributes.position.clone();
	
	if (matrix !== undefined) {
		let m = new Matrix4();
		position.applyMatrix4(m.extractRotation(matrix));
	}

	const morphAttributesPosition = this.morphAttributes.position;

	if (position && position.isGLBufferAttribute) {
		console.error('THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".', this);
		this.boundingBox.set(new Vector3(-Infinity, -Infinity, -Infinity), new Vector3(+Infinity, +Infinity, +Infinity));
		return;
	}

	if (position !== undefined) {
		this.boundingBox.setFromBufferAttribute(position); // process morph attributes if present
		
		if (morphAttributesPosition) {
			for (let i = 0, il = morphAttributesPosition.length; i < il; i++) {
				const morphAttribute = morphAttributesPosition[i];

				_box$1.setFromBufferAttribute(morphAttribute);

				if (this.morphTargetsRelative) {
					_vector$8.addVectors(this.boundingBox.min, _box$1.min);

					this.boundingBox.expandByPoint(_vector$8);

					_vector$8.addVectors(this.boundingBox.max, _box$1.max);

					this.boundingBox.expandByPoint(_vector$8);
				} else {
					this.boundingBox.expandByPoint(_box$1.min);
					this.boundingBox.expandByPoint(_box$1.max);
				}
			}
		}
	} else {
		this.boundingBox.makeEmpty();
	}

	if (isNaN(this.boundingBox.min.x) || isNaN(this.boundingBox.min.y) || isNaN(this.boundingBox.min.z)) {
		console.error('THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this);
	}
}

Now it computes bounding box of concave objects and its groups fine

1 Like

is this available as a patch? being considered for inclusion?

is this an accurate summary of the patch?

  • for expandByObject(), it’s extracting only position from object.matrixWorld
  • for computeBoundingBox(), adds optional matrix parameter to morph position

I patched my source to use this workaround and:

  • it does fix bounding box computation
  • but it also breaks ray intersections

I was looking for the suggestions like this i am trying something like this can anyone tell me with some extra suggestions i had several issues.

Here is a simplified implementation that works without modifying THREE core libs. Provided an empty THREE.Box3 and an object, this function will compute the proper bounding box in world coordinates. It’s more expensive than the core implementation because it requires cloning geometries and applying matrices to them. But it works.

    // bounding box workaround adapted from:
    // https://discourse.threejs.org/t/bounding-box-bigger-than-concave-object-extrudegeometry/26073/2
    // https://discourse.threejs.org/t/invalid-bounds-generated-for-some-orientations/33205
    box3expand(box3, object) {
        let geometry = object.geometry;
        object.updateWorldMatrix(geometry ? true : false, false);

        if (geometry) {
            let matrix = object.matrixWorld;
            let position = geometry.attributes.position.clone();
            position.applyMatrix4(new THREE.Matrix4().extractRotation(matrix));
            let bounds = new THREE.Box3().setFromBufferAttribute(position);
            let bt = new THREE.Box3().copy(bounds);
            let m4 = new THREE.Matrix4();
            m4.setPosition(new THREE.Vector3().setFromMatrixPosition(object.matrixWorld));
            bt.applyMatrix4(m4);
            box3.union(bt);
        }

        let children = object.children;
        for (let i = 0, l = children.length; i < l; i++) {
            box3expand(box3, children[i]);
        }
    }

Thank you so much!

Your function does the trick for me.
I spent half a day trying to figure out why the bounding box is calculated incorrectly.

I appreciate it!