UNPKG

three-mesh-bvh

Version:

A BVH implementation to speed up raycasting against three.js meshes.

173 lines (108 loc) 4.8 kB
import { Box3, Matrix4 } from 'three'; import { OrientedBox } from '../../math/OrientedBox.js'; import { ExtendedTriangle } from '../../math/ExtendedTriangle.js'; import { setTriangle } from '../../utils/TriangleUtilities.js'; import { arrayToBox } from '../../utils/ArrayBoxUtilities.js'; import { IS_LEAF, OFFSET, COUNT, BOUNDING_DATA_INDEX, LEFT_NODE, RIGHT_NODE } from '../utils/nodeBufferUtils.js'; import { BufferStack } from '../utils/BufferStack.js'; import { getTriCount } from '../build/geometryUtils.js'; /*****************************************************************/ /* This file is generated from "intersectsGeometry.template.js". */ /*****************************************************************/ /* eslint-disable indent */ const boundingBox = /* @__PURE__ */ new Box3(); const triangle = /* @__PURE__ */ new ExtendedTriangle(); const triangle2 = /* @__PURE__ */ new ExtendedTriangle(); const invertedMat = /* @__PURE__ */ new Matrix4(); const obb = /* @__PURE__ */ new OrientedBox(); const obb2 = /* @__PURE__ */ new OrientedBox(); function intersectsGeometry( bvh, root, otherGeometry, geometryToBvh ) { BufferStack.setBuffer( bvh._roots[ root ] ); const result = _intersectsGeometry( 0, bvh, otherGeometry, geometryToBvh ); BufferStack.clearBuffer(); return result; } function _intersectsGeometry( nodeIndex32, bvh, otherGeometry, geometryToBvh, cachedObb = null ) { const { float32Array, uint16Array, uint32Array } = BufferStack; let nodeIndex16 = nodeIndex32 * 2; if ( cachedObb === null ) { if ( ! otherGeometry.boundingBox ) { otherGeometry.computeBoundingBox(); } obb.set( otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh ); cachedObb = obb; } const isLeaf = IS_LEAF( nodeIndex16, uint16Array ); if ( isLeaf ) { const thisGeometry = bvh.geometry; const thisIndex = thisGeometry.index; const thisPos = thisGeometry.attributes.position; const otherIndex = otherGeometry.index; const otherPos = otherGeometry.attributes.position; const offset = OFFSET( nodeIndex32, uint32Array ); const count = COUNT( nodeIndex16, uint16Array ); // get the inverse of the geometry matrix so we can transform our triangles into the // geometry space we're trying to test. We assume there are fewer triangles being checked // here. invertedMat.copy( geometryToBvh ).invert(); if ( otherGeometry.boundsTree ) { // if there's a bounds tree arrayToBox( BOUNDING_DATA_INDEX( nodeIndex32 ), float32Array, obb2 ); obb2.matrix.copy( invertedMat ); obb2.needsUpdate = true; // TODO: use a triangle iteration function here const res = otherGeometry.boundsTree.shapecast( { intersectsBounds: box => obb2.intersectsBox( box ), intersectsTriangle: tri => { tri.a.applyMatrix4( geometryToBvh ); tri.b.applyMatrix4( geometryToBvh ); tri.c.applyMatrix4( geometryToBvh ); tri.needsUpdate = true; for ( let i = offset * 3, l = ( count + offset ) * 3; i < l; i += 3 ) { // this triangle needs to be transformed into the current BVH coordinate frame setTriangle( triangle2, i, thisIndex, thisPos ); triangle2.needsUpdate = true; if ( tri.intersectsTriangle( triangle2 ) ) { return true; } } return false; } } ); return res; } else { // if we're just dealing with raw geometry const otherTriangleCount = getTriCount( otherGeometry ); for ( let i = offset * 3, l = ( count + offset ) * 3; i < l; i += 3 ) { // this triangle needs to be transformed into the current BVH coordinate frame setTriangle( triangle, i, thisIndex, thisPos ); triangle.a.applyMatrix4( invertedMat ); triangle.b.applyMatrix4( invertedMat ); triangle.c.applyMatrix4( invertedMat ); triangle.needsUpdate = true; for ( let i2 = 0, l2 = otherTriangleCount * 3; i2 < l2; i2 += 3 ) { setTriangle( triangle2, i2, otherIndex, otherPos ); triangle2.needsUpdate = true; if ( triangle.intersectsTriangle( triangle2 ) ) { return true; } } } } } else { const left = LEFT_NODE( nodeIndex32 ); const right = RIGHT_NODE( nodeIndex32, uint32Array ); arrayToBox( BOUNDING_DATA_INDEX( left ), float32Array, boundingBox ); const leftIntersection = cachedObb.intersectsBox( boundingBox ) && _intersectsGeometry( left, bvh, otherGeometry, geometryToBvh, cachedObb ); if ( leftIntersection ) return true; arrayToBox( BOUNDING_DATA_INDEX( right ), float32Array, boundingBox ); const rightIntersection = cachedObb.intersectsBox( boundingBox ) && _intersectsGeometry( right, bvh, otherGeometry, geometryToBvh, cachedObb ); if ( rightIntersection ) return true; return false; } } export { intersectsGeometry };