I’m trying to calculate an OBB manually from an unknown rotated Cube-BufferGeometry mesh.
Since there is no setFromObject method for OBB, it must be done manually.
My findings so far:
For building an OBB, 3 parameters are needed: center, halfSize and rotation.
I’ve already calculated the center of the BufferGeometry, which was pretty straight forward:
Got all local positions of the corners of the mesh from the BufferGeometryAttribute (8 corners in total) and added them together (Obviously separeted by X, Y, Z)
Divided these sums by 8, so I get the exact center of the rotated box.
But I’m getting confused on how to get the halfSize and rotation out of this, and it’s not just calculating the distance from the center to any vertex, since everything is rotated.
This is an example of how the cube-geometry looks. It’s important to mention that the rotation of the object is (0, 0, 0), the vertices positions are the ones that make it look rotated.
Just working with cube geometries won’t help much. Implementing OBB.setFromObject() is tricky since the related algorithms for computing the minimum enclosing OBB are complicated and do not always produce expected results. I’ve implemented such a method for Yuka based on Collision Queries using Oriented Bounding Boxes. However, since this approach has problems with certain edge cases (it does not compute good OBBs for certain symmetric shapes), I doubt the implementation will be accepted in the three.js repo.
You can see Yuks’s OBB implementation in the following example that compares different types of bounding volumes for a typical game asset: Yuka | Bounding Volumes
Ive done this before for one job using Principal component analysis - Wikipedia this basically finds ordered set of axes that vertices are distributed along the most to the least, which form the basis of transformation matrix for the box you are looking for. The method always works, but the axes might flip around wildly if you move the vertices even by tiny bit.
The code I used as a reference could be borrowed here, btw. I think. It looks similar.
let box3 = mesh.geometry.boundingBox;
if (!box3) {
mesh.geometry.computeBoundingBox();
box3 = mesh.geometry.boundingBox;
}
if (box3) {
this._obb.fromBox3(box3)
this._obb.halfSize.copy(box3.getSize(new Vector3())).multiplyScalar(0.5);
// now rotate the OBB object to mesh rotation
this._obb.applyMatrix4(mesh.matrixWorld);
this._obb.intersectXXX(); // perform intersection test
}
This would only work if the mesh was axis-oriented, which is not the case. And I cannot force it to be axis-oriented to calculate the bounding box, cause orientation is not even assigned at mesh-level, but more like a result of how the vertex are positioned
This really helped! I got it working with the Yuka example, plus it’s amazing it has ConvexHull calculation as well. I’ll keep playing around with it to see how far it can go for my use-case.