UNPKG

three-mesh-bvh

Version:

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

465 lines (357 loc) 10.9 kB
import { BufferGeometry, Vector3, Side, Material, Ray, Sphere, Matrix4, Color, Intersection, Box3, Triangle, Vector2, Raycaster, MeshBasicMaterial, Group, LineBasicMaterial, Mesh, DataTexture, BufferAttribute, Line3, Object3D, SkinnedMesh, } from 'three'; // Contants export enum SplitStrategy {} export const CENTER: SplitStrategy; export const AVERAGE: SplitStrategy; export const SAH: SplitStrategy; export enum ShapecastIntersection {} export const NOT_INTERSECTED: ShapecastIntersection; export const INTERSECTED: ShapecastIntersection; export const CONTAINED: ShapecastIntersection; export interface HitPointInfo { point: Vector3; distance: number; faceIndex: number; } export interface BVHOptions { strategy?: SplitStrategy; maxDepth?: number; /** @deprecated Use maxLeafSize instead */ maxLeafTris?: number; maxLeafSize?: number; setBoundingBox?: boolean; useSharedArrayBuffer?: boolean; indirect?: boolean; verbose?: boolean; onProgress?: ( progress: number ) => void; range?: { start: number; count: number }; } /** @deprecated Use BVHOptions instead */ export interface MeshBVHOptions extends BVHOptions {} // eslint-disable-line export interface ComputeBVHOptions extends BVHOptions { type?: typeof GeometryBVH; } export interface MeshBVHSerializeOptions { cloneBuffers?: boolean; } export interface MeshBVHDeserializeOptions { setIndex?: boolean; } export interface ShapecastCallbacks { intersectsBounds: ( box: Box3, isLeaf: boolean, score: number | undefined, depth: number, nodeIndex: number ) => ShapecastIntersection|boolean; boundsTraverseOrder?: ( box: Box3 ) => number; intersectsRange?: ( offset: number, count: number, contained: boolean, depth: number, nodeIndex: number, box: Box3 ) => boolean; /** @deprecated geometry.boundsTree must be cast to "MeshBVH" in order to use "intersectsTriangle" callback. */ intersectsTriangle?: ( triangle: ExtendedTriangle, triangleIndex: number, contained: boolean, depth: number ) => boolean|void } export interface BVHCastCallbacks { intersectsRanges: ( offset1: number, count1: number, offset2: number, count2: number, depth1: number, index1: number, depth2: number, index2: number ) => boolean } export class BVH { shiftPrimitiveOffsets( offset: number ): void; refit( nodeIndices?: Array<number> | Set<number> ): void; traverse( callback: ( depth: number, isLeaf: boolean, boundingData: ArrayBuffer, offsetOrSplit: number, count: number ) => void, rootIndex?: number ): void; getBoundingBox( target: Box3 ): Box3; shapecast( callbacks: ShapecastCallbacks ): boolean; bvhcast( otherBVH: MeshBVH, matrixToLocal: Matrix4, callbacks: BVHCastCallbacks ): boolean; } export class GeometryBVH extends BVH { readonly geometry: BufferGeometry; constructor( geometry: BufferGeometry, options?: BVHOptions ); raycastObject3D( object: Object3D, raycaster: Raycaster, intersects: Array<Intersection> ): void; } // MeshBVH export class MeshBVH extends GeometryBVH { readonly resolveTriangleIndex: ( i: number ) => number; static serialize( bvh: MeshBVH, options?: MeshBVHSerializeOptions ): SerializedBVH; static deserialize( data: SerializedBVH, geometry: BufferGeometry, options?: MeshBVHDeserializeOptions ): MeshBVH; constructor( geometry: BufferGeometry, options?: BVHOptions ); shiftTriangleOffsets( offset: number ): void; raycast( ray: Ray, materialOrSide?: Side | Array<Material> | Material, near?: number, far?: number ): Array<Intersection> raycastFirst( ray: Ray, materialOrSide?: Side | Array<Material> | Material, near?: number, far?: number ): Intersection | null; intersectsSphere( sphere: Sphere ): boolean; intersectsBox( box: Box3, boxToMesh: Matrix4 ): boolean; intersectsGeometry( geometry: BufferGeometry, geometryToBvh: Matrix4 ): boolean; closestPointToPoint( point: Vector3, target?: HitPointInfo, minThreshold?: number, maxThreshold?: number ): HitPointInfo | null; closestPointToGeometry( geometry: BufferGeometry, geometryToBvh: Matrix4, target1?: HitPointInfo, target2?: HitPointInfo, minThreshold?: number, maxThreshold?: number ): HitPointInfo | null; shapecast( callbacks: ShapecastCallbacks & { intersectsTriangle?: ( triangle: ExtendedTriangle, triangleIndex: number, contained: boolean, depth: number ) => boolean|void } ): boolean; // union types to enable at least one of two functions: // https://stackoverflow.com/a/60617060/9838891 bvhcast( otherBVH: MeshBVH, matrixToLocal: Matrix4, callbacks: ( BVHCastCallbacks | { intersectsTriangles: ( triangle1: ExtendedTriangle, triangle2: ExtendedTriangle, i1: number, i2: number, depth1: number, index1: number, depth2: number, index2: number, ) => boolean, } ) ): boolean; } export class SkinnedMeshBVH extends GeometryBVH { constructor( mesh: SkinnedMesh, options?: BVHOptions ); shapecast( callbacks: ShapecastCallbacks & { intersectsTriangle?: ( triangle: ExtendedTriangle, triangleIndex: number, contained: boolean, depth: number ) => boolean|void } ): boolean; } // other BVHs export class PointsBVH extends GeometryBVH { shapecast( callbacks: ShapecastCallbacks & { intersectsPoint?: ( pointIndex: number, contained: boolean, depth: number ) => boolean|void } ): boolean; } export class LineSegmentsBVH extends GeometryBVH { shapecast( callbacks: ShapecastCallbacks & { intersectsLine?: ( lineIndex: number, contained: boolean, depth: number ) => boolean|void } ): boolean; } export class LineLoopBVH extends LineSegmentsBVH {} export class LineBVH extends LineLoopBVH {} export class ObjectBVH extends BVH { constructor( root: Array<Object3D> | Object3D, options?: BVHOptions ); getObjectFromId( compositeId: number ): Object3D; getInstanceFromId( compositeId: number ): number; shapecast( callbacks: ShapecastCallbacks & { intersectsObject?: ( object: Object3D, instanceId: number, contained: boolean, depth: number ) => boolean|void } ): boolean; raycast( raycaster: Raycaster, intersects?: Array<Intersection> ): Array<Intersection>; } // SerializedBVH export class SerializedBVH { roots: Array<ArrayBuffer>; index: ArrayBufferView; } // BVHHelper export class BVHHelper extends Group { opacity: number; depth: number; instanceId: number; displayParents: boolean; displayEdges: boolean; edgeMaterial: LineBasicMaterial; meshMaterial: MeshBasicMaterial; constructor( meshOrBVH: Object3D | GeometryBVH, depth?: number ); constructor( mesh?: Object3D | null, bvh?: GeometryBVH | null, depth?: number ); update(): void; get color(): Color; } /** @deprecated Use BVHHelper instead */ export class MeshBVHHelper extends BVHHelper {} // THREE.js Extensions export function computeBoundsTree( options?: ComputeBVHOptions ): GeometryBVH; export function disposeBoundsTree(): void; export function computeBatchedBoundsTree( index?: number, options?: BVHOptions ): GeometryBVH | GeometryBVH[]; export function disposeBatchedBoundsTree( index?: number ): void; export function acceleratedRaycast( raycaster: Raycaster, intersects: Array<Intersection> ): void; declare module 'three' { export interface BufferGeometry { boundsTree?: GeometryBVH; computeBoundsTree: typeof computeBoundsTree; disposeBoundsTree: typeof disposeBoundsTree; } export interface BatchedMesh { boundsTrees?: Array<GeometryBVH | null>; computeBoundsTree: typeof computeBatchedBoundsTree; disposeBoundsTree: typeof disposeBatchedBoundsTree; } export interface Raycaster { firstHitOnly?: boolean; } } // GenerateMeshBVHWorker // export class GenerateMeshBVHWorker { // running: boolean; // generate( geometry: BufferGeometry, options?: MeshBVHOptions ): Promise<MeshBVH>; // terminate(): boolean; // } // Debug functions export function estimateMemoryInBytes( bvh: BVH ): number; export interface ExtremeInfo { nodeCount: number; leafNodeCount: number; surfaceAreaScore: number; depth: {min: number, max: number}; primitives: {min: number, max: number}; splits: [number, number, number]; } export function getBVHExtremes( bvh: BVH ): Array<ExtremeInfo>; export function validateBounds( bvh: MeshBVH ): boolean; export interface TreeNode { bounds: Box3; count: number; offset: number; left?: TreeNode; right?: TreeNode; } export function getJSONStructure( bvh: BVH ): TreeNode; // Triangle Utilities export interface HitTriangleInfo { face: { a: number, b: number, c: number, materialIndex: number, normal: Vector3 }, uv: Vector2 } export function getTriangleHitPointInfo( point: Vector3, geometry : BufferGeometry, triangleIndex: number, target?: HitTriangleInfo ): HitTriangleInfo // Shader Utilities declare class VertexAttributeTexture extends DataTexture { overrideItemSize: number | null; updateFrom( attribute: BufferAttribute ): void; } export class FloatVertexAttributeTexture extends VertexAttributeTexture {} export class UIntVertexAttributeTexture extends VertexAttributeTexture {} export class IntVertexAttributeTexture extends VertexAttributeTexture {} export class MeshBVHUniformStruct { updateFrom( bvh: MeshBVH ): void; dispose(): void; } export const BVHShaderGLSL: { bvh_distance_functions: string; bvh_ray_functions: string; bvh_struct_definitions: string; common_functions: string; }; // backwards compatibility export const shaderStructs: string; export const shaderDistanceFunction: string; export const shaderIntersectFunction: string; // Math classes export class ExtendedTriangle extends Triangle { needsUpdate : boolean; intersectsTriangle( other : Triangle, target? : Line3 ) : boolean; intersectsSphere( sphere : Sphere ) : boolean; closestPointToSegment( segment : Line3, target1? : Vector3, target2? : Vector3 ) : number; distanceToPoint( point : Vector3 ) : number; distanceToTriangle( tri : Triangle ) : number; } export class OrientedBox { min: Vector3; max: Vector3; matrix : Matrix4; needsUpdate : boolean; constructor( min : Vector3, max : Vector3 ); set( min : Vector3, max : Vector3, matrix : Matrix4 ) : OrientedBox; intersectsBox( box : Box3 ) : boolean; intersectsTriangle( tri : Triangle ) : boolean; closestPointToPoint( point : Vector3, target? : Vector3 ) : number; distanceToPoint( point : Vector3 ) : number; distanceToBox( box : Box3, threshold? : number, target1? : Vector3, target2? : Vector3 ) : number; } export class StaticGeometryGenerator { useGroups : boolean; attributes : Array<string>; applyWorldTransforms : boolean; constructor( objects : Array<Object3D> | Object3D ); getMaterials() : Array<Material>; generate( target? : BufferGeometry ) : BufferGeometry; }