gkjohnson / three-mesh-bvh

A BVH implementation to speed up raycasting and enable spatial queries against three.js meshes.
https://gkjohnson.github.io/three-mesh-bvh/example/bundle/raycast.html
MIT License
2.53k stars 267 forks source link

closestPointToGeometry unexpected behaviour #386

Closed cpind closed 2 years ago

cpind commented 2 years ago

Hi,

I'm running into an unexpected behaviour with the bvh.closestPointToGeometry. Below is a failing test case created to replicate the issue.

Test uses the bvh.closestPointToGeometry to compute distance between 2 sphere of radius 1, where one sphere is positioned at origin new Vector3(0, 0, 0) and the other at new Vector3(3, 0, 0). Hence the distance is expected to be closed to 1. Problem is that sometimes distance is way greater than that.

The issue only arise for sphere with a greater number of triangles. In test below the 2 first test case passes, ie for new SphereBufferGeometry(1, 8, 4); and new SphereBufferGeometry(1, 16, 8) but fails for new SphereBufferGeometry(1, 32, 16).

        for (let n of [4, 8, 16]) {

            it(`should handle case, n: ${n}`, () => {
                const geom = new SphereBufferGeometry(1, n * 2, n);
                geom.boundsTree = new MeshBVH(geom);
                const matrix = new Matrix4()
                            .compose(
                                new Vector3(3, 0, 0),
                                new Quaternion(),
                                new Vector3(1, 1, 1)
                            );

                const bvh1 = geom.boundsTree;

                const target1 = {};
                const target2 = {};
                bvh1.closestPointToGeometry(geom, matrix, target1, target2);
                const point1 = target1.point;
                const point2 = target2.point.applyMatrix4(matrix); // moves target2 to world coordinate
                const dist = point1.distanceTo(point2);
                expect(dist).toBeCloseTo(1, 1);
            });
    }

Result:

   ✓ should handle case, n: 4 (10 ms)
    ✓ should handle case, n: 8 (13 ms)
    ✕ should handle case, n: 16 (18 ms) // Received: 1.1592849569923525
gkjohnson commented 2 years ago

Thanks for the report and the fix! Our of curiosity are you able to share how you're using the library? It's always helpful to understand how the project is being used.

cpind commented 2 years ago

I'm building a tool to generate automatic exploded views of CAD models. The viewer is built with Three.js and it relies on an explosion graph for the CAD model. To compute the explosion graph I need to know the distance between each parts or which one are in contact. This is where I use your lib. How it integrate smoothly with Three.js was what got me to use it.

I have couple more fixes to issues that I've run into, I'll submit, just need a bit of a cleaning first.

Thank you for the lib ;-)

gkjohnson commented 2 years ago

Just merged! Let me know what other issues you're looking in to.

Thanks for the fix! And if you can share the work you're doing at some point I'd love to see it.