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.5k stars 261 forks source link

Pass down triangle point indices in intersectsTriangle #535

Closed Tirzono closed 1 year ago

Tirzono commented 1 year ago

Is your feature request related to a problem? Please describe.

I would like to intersect a geometry with a plane and would like to get an outline of that intersection, but I would also like to get the color from the material of the geometry along that line. I am using this example:

https://github.com/gkjohnson/three-mesh-bvh/blob/master/example/clippedEdges.js

And am able to get the outline. However, in order to get the color from the material of the geometry, I need to know the indices of points in the ExtendedTriangle.

Describe the solution you'd like

Pass the indices of the intersection to the user in the intersectsTriangle function. Maybe this can be done in setTriangle by adding a property indices?

export class ExtendedTriangle extends Triangle {

    constructor( ...args ) {

        super( ...args );

        this.isExtendedTriangle = true;
        this.satAxes = new Array( 4 ).fill().map( () => new Vector3() );
        this.satBounds = new Array( 4 ).fill().map( () => new SeparatingAxisBounds() );
        this.points = [ this.a, this.b, this.c ];
        this.indices = [-1, -1, -1];
        this.sphere = new Sphere();
        this.plane = new Plane();
        this.needsUpdate = true;

    }

And in setTriangle:

export function setTriangle( tri, i, index, pos ) {

    const ta = tri.a;
    const tb = tri.b;
    const tc = tri.c;

    let i0 = i;
    let i1 = i + 1;
    let i2 = i + 2;
    if ( index ) {

        i0 = index.getX( i );
        i1 = index.getX( i + 1 );
        i2 = index.getX( i + 2 );

    }

        tri.indices = [i0, i1, i2];

Describe alternatives you've considered

N/A

Additional context

N/A

gkjohnson commented 1 year ago

If you look at the documentation for shapecast you'll see that the triangle index is already being passed into the intersectsTriangle function:

        intersectsTriangle : (
            triangle : ExtendedTriangle,
            triangleIndex : Number,
            contained : Boolean,
            depth : Number
        ) => Boolean = null,
Tirzono commented 1 year ago

Apologies, that's something I should've known.

For anyone else with the same question who then wants to translate triangleIndex to the indices of the points of the triangle:

        const indices = mesh.geometry.getIndex().array;

        mesh.geometry.boundsTree.shapecast({
            intersectsTriangle: (triangle, triangleIndex) => {
                const a = indices[triangleIndex * 3]; // Matches triangle.a
                const b = indices[triangleIndex * 3 + 1]; // Matches triangle.b
                const c = indices[triangleIndex * 3 + 2]; // Matches triangle.c
gkjohnson commented 1 year ago

It's best to do the following to account for different buffer attribute types:

const index = mesh.geometry.getIndex();

// ...
const a = index.getX( triangleIndex * 3 ); // Matches triangle.a
const b = index.getX( triangleIndex * 3 + 1 ); // Matches triangle.b
const c = index.getX( triangleIndex * 3 + 2 ); // Matches triangle.c