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