{"id":13401878,"url":"https://github.com/gkjohnson/three-mesh-bvh","last_synced_at":"2026-01-08T11:07:37.932Z","repository":{"id":39534179,"uuid":"118064695","full_name":"gkjohnson/three-mesh-bvh","owner":"gkjohnson","description":"A BVH implementation to speed up raycasting and enable spatial queries against three.js meshes.","archived":false,"fork":false,"pushed_at":"2025-10-16T06:27:25.000Z","size":155919,"stargazers_count":3037,"open_issues_count":78,"forks_count":294,"subscribers_count":40,"default_branch":"master","last_synced_at":"2025-10-17T09:03:10.526Z","etag":null,"topics":["acceleration","bounds","bounds-hierarchy","bvh","distance","geometry","graphics","intersection","mesh","pathtracing","performance","point-cloud","pointcloud","raycast","raytracing","three-js","three-mesh-bvh","threejs","tree","webvr"],"latest_commit_sha":null,"homepage":"https://gkjohnson.github.io/three-mesh-bvh/example/bundle/raycast.html","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gkjohnson.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"gkjohnson","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2018-01-19T02:17:11.000Z","updated_at":"2025-10-16T06:26:52.000Z","dependencies_parsed_at":"2024-01-03T04:06:44.105Z","dependency_job_id":"1d50a646-d28a-4b07-b1a7-cd0533d7c8d3","html_url":"https://github.com/gkjohnson/three-mesh-bvh","commit_stats":{"total_commits":2421,"total_committers":48,"mean_commits":50.4375,"dds":"0.10945890128046265","last_synced_commit":"84d382bf8cf1a433e105f6abbc97b39efb5c8d26"},"previous_names":[],"tags_count":71,"template":false,"template_full_name":null,"purl":"pkg:github/gkjohnson/three-mesh-bvh","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkjohnson%2Fthree-mesh-bvh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkjohnson%2Fthree-mesh-bvh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkjohnson%2Fthree-mesh-bvh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkjohnson%2Fthree-mesh-bvh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gkjohnson","download_url":"https://codeload.github.com/gkjohnson/three-mesh-bvh/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkjohnson%2Fthree-mesh-bvh/sbom","scorecard":{"id":428948,"data":{"date":"2025-08-11","repo":{"name":"github.com/gkjohnson/three-mesh-bvh","commit":"f592faa0a7f3f71a6b681a53205d6f35a59b4251"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.5,"checks":[{"name":"Maintained","score":10,"reason":"30 commit(s) and 8 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 1/11 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql.yml:17","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:18","Warn: no topLevel permission defined: .github/workflows/codeql.yml:1","Warn: no topLevel permission defined: .github/workflows/examples-build.yml:1","Warn: no topLevel permission defined: .github/workflows/node.js.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Pinned-Dependencies","score":4,"reason":"dependency not pinned by hash detected -- score normalized to 4","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/gkjohnson/three-mesh-bvh/codeql.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:33: update your workflow using https://app.stepsecurity.io/secureworkflow/gkjohnson/three-mesh-bvh/codeql.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/gkjohnson/three-mesh-bvh/codeql.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/gkjohnson/three-mesh-bvh/codeql.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/examples-build.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/gkjohnson/three-mesh-bvh/examples-build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/examples-build.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/gkjohnson/three-mesh-bvh/examples-build.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/examples-build.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/gkjohnson/three-mesh-bvh/examples-build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node.js.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/gkjohnson/three-mesh-bvh/node.js.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node.js.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/gkjohnson/three-mesh-bvh/node.js.yml/master?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/node.js.yml:31","Info:   0 out of   8 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   3 out of   4 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"SAST","score":10,"reason":"SAST tool is run on all commits","details":["Info: SAST configuration detected: CodeQL","Info: all commits (20) are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":2,"reason":"8 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-67mh-4wv8-2f99","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-v834-rhv4-65m3","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T02:52:31.016Z","repository_id":39534179,"created_at":"2025-08-19T02:52:31.016Z","updated_at":"2025-08-19T02:52:31.016Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":284304462,"owners_count":26982161,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-13T02:00:06.582Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["acceleration","bounds","bounds-hierarchy","bvh","distance","geometry","graphics","intersection","mesh","pathtracing","performance","point-cloud","pointcloud","raycast","raytracing","three-js","three-mesh-bvh","threejs","tree","webvr"],"created_at":"2024-07-30T19:01:08.419Z","updated_at":"2026-01-08T11:07:37.925Z","avatar_url":"https://github.com/gkjohnson.png","language":"JavaScript","funding_links":["https://github.com/sponsors/gkjohnson","https://github.com/sponsors/gkjohnson/"],"categories":["JavaScript","4. 高级功能插件","Graphics","Spatial querying \u0026 Raycasting","Libraries"],"sub_categories":["Svelte","Visual Animation Editor","JavaScript"],"readme":"# three-mesh-bvh\n\n[![npm version](https://img.shields.io/npm/v/three-mesh-bvh.svg?style=flat-square)](https://www.npmjs.com/package/three-mesh-bvh)\n[![build](https://img.shields.io/github/actions/workflow/status/gkjohnson/three-mesh-bvh/node.js.yml?style=flat-square\u0026label=build\u0026branch=master)](https://github.com/gkjohnson/three-mesh-bvh/actions)\n[![github](https://flat.badgen.net/badge/icon/github?icon=github\u0026label)](https://github.com/gkjohnson/three-mesh-bvh/)\n[![twitter](https://flat.badgen.net/badge/twitter/@garrettkjohnson/?icon\u0026label)](https://twitter.com/garrettkjohnson)\n[![sponsors](https://img.shields.io/github/sponsors/gkjohnson?style=flat-square\u0026color=1da1f2)](https://github.com/sponsors/gkjohnson/)\n\nA Bounding Volume Hierarchy (BVH) implementation to speed up raycasting and enable spatial queries against three.js meshes. See the associated [Wikipedia article](https://en.wikipedia.org/wiki/Bounding_volume_hierarchy) for more information on bounding volume hierarchies and how they work.\n\n![screenshot](./docs/example-sm.gif)\n\nCasting 500 rays against an 80,000 polygon model at 60fps!\n\n# Examples\n\n[Raycasting](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/raycast.html)\n\n[Skinned geometry](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/skinnedMesh.html)\n\n[Point cloud intersection](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/pointCloudIntersection.html)\n\n[Line intersection](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/lineIntersection.html)\n\n[Shape intersection](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/shapecast.html)\n\n[Geometry edge intersection](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/edgeIntersect.html)\n\n[SDF generation](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/sdfGeneration.html)\n\n[WebWorker generation](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/asyncGenerate.html)\n\n[BVH options inspector](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/inspector.html)\n\n[BatchedMesh Raycasting](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/batchedMesh.html)\n\n**Tools**\n\n[Sculpting](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/sculpt.html)\n\n[Distance comparison](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/distancecast.html)\n\n[Triangle painting](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/collectTriangles.html)\n\n[Lasso selection](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/selection.html)\n\n[Clipped edges](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/clippedEdges.html)\n\n[Geometry voxelization](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/voxelize.html)\n\n**Games**\n\n[Sphere physics collision](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/physics.html)\n\n[Player movement](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/characterMovement.html)\n\n**Path Tracing**\n\n[Simple GPU Path Tracing](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/gpuPathTracingSimple.html)\n\n[Lambert GPU Path Tracing](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/gpuPathTracing.html)\n\n[CPU Path Tracing](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/cpuPathTracing.html)\n\n[Gem Refraction Path Tracing](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/diamond.html)\n\n\u003c!--\n**WebGPU Compute Shaders**\n\n[Simple Path Tracing](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/webgpu_gpuPathTracingSimple.html)\n--\u003e\n\n**External Projects**\n\n[three-gpu-pathtracer](https://github.com/gkjohnson/three-gpu-pathtracer)\n\n[three-bvh-csg](https://github.com/gkjohnson/three-bvh-csg)\n\n[three-edge-projection](https://github.com/gkjohnson/three-edge-projection/)\n\n# Use\n\nUsing pre-made functions\n\n```js\nimport * as THREE from 'three';\nimport {\n\tcomputeBoundsTree, disposeBoundsTree,\n\tcomputeBatchedBoundsTree, disposeBatchedBoundsTree, acceleratedRaycast,\n} from 'three-mesh-bvh';\n\n// Add the extension functions\nTHREE.BufferGeometry.prototype.computeBoundsTree = computeBoundsTree;\nTHREE.BufferGeometry.prototype.disposeBoundsTree = disposeBoundsTree;\nTHREE.Mesh.prototype.raycast = acceleratedRaycast;\n\nTHREE.BatchedMesh.prototype.computeBoundsTree = computeBatchedBoundsTree;\nTHREE.BatchedMesh.prototype.disposeBoundsTree = disposeBatchedBoundsTree;\nTHREE.BatchedMesh.prototype.raycast = acceleratedRaycast;\n\n// Generate geometry and associated BVH\nconst geom = new THREE.TorusKnotGeometry( 10, 3, 400, 100 );\nconst mesh = new THREE.Mesh( geom, material );\ngeom.computeBoundsTree();\n\n// Or generate BatchedMesh and associated BVHs\nconst batchedMesh = new THREE.BatchedMesh( ... );\nconst geomId = batchedMesh.addGeometry( geom );\nconst instId = batchedMesh.addGeometry( geom );\n\n// Generate bounds tree for sub geometry\nbatchedMesh.computeBoundsTree( geomId );\n```\n\nOr manually building the BVH\n\n```js\nimport * as THREE from 'three';\nimport { MeshBVH, acceleratedRaycast } from 'three-mesh-bvh';\n\n// Add the raycast function. Assumes the BVH is available on\n// the `boundsTree` variable\nTHREE.Mesh.prototype.raycast = acceleratedRaycast;\n\n// ...\n\n// Generate the BVH and use the newly generated index\ngeom.boundsTree = new MeshBVH( geom );\n```\n\nAnd then raycasting\n\n```js\n// Setting \"firstHitOnly\" to true means the Mesh.raycast function will use the\n// bvh \"raycastFirst\" function to return a result more quickly.\nconst raycaster = new THREE.Raycaster();\nraycaster.firstHitOnly = true;\nraycaster.intersectObjects( [ mesh ] );\n```\n\n## Other BVH Types\n\nIn addition to `MeshBVH` for triangle meshes, the library provides specialized BVH implementations for other primitive types:\n\n- **PointsBVH** - For `THREE.Points` geometries\n- **LineBVH** - For `THREE.Line` geometries\n- **LineLoopBVH** - For `THREE.LineLoop` geometries\n- **LineSegmentsBVH** - For `THREE.LineSegments` geometries\n\nThese can be used with the extension functions by passing a `type` option into \"computeBoundsTree\" or constructing them explicitly:\n\n```js\nimport { PointsBVH } from 'three-mesh-bvh';\n\n// For point clouds\nTHREE.Points.prototype.raycast = acceleratedRaycast;\n\nconst points = new THREE.Points( geometry, material );\ngeometry.computeBoundsTree( { type: PointsBVH } );\n\n// Or create directly\ngeometry.boundsTree = new PointsBVH( geometry );\n```\n\nEach BVH type implements a core API including shapecast \u0026 raycastObject3D for its specific primitive type. See the [point cloud intersection](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/pointCloudIntersection.html) \u0026 [line intersection](https://gkjohnson.github.io/three-mesh-bvh/example/bundle/lineIntersection.html) examples for a working demonstration. Some features like webworker-generation and serialization are not supported at the moment.\n\n## Querying the BVH Directly\n\n```js\nimport * as THREE from 'three';\nimport { MeshBVH, acceleratedRaycast } from 'three-mesh-bvh';\n\nlet mesh, geometry;\nconst invMat = new THREE.Matrix4();\n\n// instantiate the geometry\n\n// ...\n\nconst bvh = new MeshBVH( geometry );\ninvMat.copy( mesh.matrixWorld ).invert();\n\n// raycasting\n// ensure the ray is in the local space of the geometry being cast against\nraycaster.ray.applyMatrix4( invMat );\nconst hit = bvh.raycastFirst( raycaster.ray );\n\n// results are returned in local spac, as well, so they must be transformed into\n// world space if needed.\nhit.point.applyMatrixWorld( mesh.matrixWorld );\n\n// spherecasting\n// ensure the sphere is in the local space of the geometry being cast against\nsphere.applyMatrix4( invMat );\nconst intersects = bvh.intersectsSphere( sphere );\n```\n\n## With Skinned and Morph Target Meshes\n\n```js\nimport { StaticGeometryGenerator } from 'three-mesh-bvh';\n\nconst generator = new StaticGeometryGenerator( [ ...skinnedMeshes ] );\nconst geometry = generator.generate();\ngeometry.computeBoundsTree();\n\n// ...\n\n// update the geometry in place\ngenerator.generate( geometry );\ngeometry.boundsTree.refit();\n```\n\n## Serialization and Deserialization\n\n```js\nconst geometry = new KnotGeometry( 1, 0.5, 40, 10 );\nconst bvh = new MeshBVH( geometry );\nconst serialized = MeshBVH.serialize( bvh );\n\n// ...\n\nconst deserializedBVH = MeshBVH.deserialize( serialized, geometry );\ngeometry.boundsTree = deserializedBVH;\n```\n\n## Asynchronous Generation\n\n_NOTE WebWorker syntax is inconsistently supported across bundlers and sometimes not supported at all so the GenerateMeshBVHWorker class is exported separately via `three-mesh-bvh/worker` subpath. If needed the code from `src/worker` can be copied and modified to accommodate a particular build process._\n\n```js\nimport { GenerateMeshBVHWorker } from 'three-mesh-bvh/worker';\n\n// ...\n\nconst geometry = new KnotGeometry( 1, 0.5, 40, 10 );\nconst worker = new GenerateMeshBVHWorker();\nworker.generate( geometry ).then( bvh =\u003e {\n\n    geometry.boundsTree = bvh;\n\n} );\n```\n\n_Parallel BVH generation is also supported using \"ParallelMeshBVHWorker\", which requires support for SharedArrayBuffer. If SharedArrayBuffer is not available it falls back to \"GenerateMeshBVHWorker\". It is recommended that geometry passed to this function have `position` and `index` with SharedArrayBuffer arrays, otherwise buffer copies must be made._\n\n```js\nimport { ParallelMeshBVHWorker } from 'three-mesh-bvh/worker';\n\n// ...\n\nconst geometry = new KnotGeometry( 1, 0.5, 40, 10 );\nconst worker = new ParallelMeshBVHWorker();\nworker.generate( geometry ).then( bvh =\u003e {\n\n    geometry.boundsTree = bvh;\n\n} );\n```\n\n## BVH Queries in a Shader\n\nSee the shader implementation in the [simple GPU Path Tracing example](https://github.com/gkjohnson/three-mesh-bvh/blob/master/example/gpuPathTracingSimple.js) for an example on how to perform BVH ray queries in a shader. Or the [GPU SDF Generation example](https://github.com/gkjohnson/three-mesh-bvh/blob/master/example/sdfGeneration.js) for how to perform distance and closest point to point queries in a shader.\n\n# Exports\n\n## Split Strategy Constants\n\n#### CENTER\n\nOption for splitting each BVH node down the center of the longest axis of the bounds.\n\nThis is the fastest construction option and will yield a good, performant bounds.\n\n#### AVERAGE\n\nOption for splitting each BVH node at the average point along the longest axis for all triangle centroids in the bounds.\n\nThis strategy may be better than `CENTER` with some geometry.\n\n#### SAH\n\nOption to use a Surface Area Heuristic to split the bounds more optimally. This SAH implementation tests 32 discrete splits in each node along each axis to determine which split is the lowest cost.\n\nThis is the slowest construction option but will yield the best bounds of the three options and use the least memory.\n\n## Shapecast Intersection Constants\n\n#### NOT_INTERSECTED\n\nIndicates the shape did not intersect the given bounding box.\n\n#### INTERSECTED\n\nIndicates the shape did intersect the given bounding box.\n\n#### CONTAINED\n\nIndicate the shape entirely contains the given bounding box.\n\n## MeshBVH\n\nThe MeshBVH generation process modifies the geometry's index bufferAttribute in place to save memory. The BVH construction will use the geometry's boundingBox if it exists or set it if it does not. The BVH will no longer work correctly if the index buffer is modified.\n\nOnly triangles within the geometry's draw range (or provided `range` option) are included in the BVH. When a geometry has multiple groups, only triangles within the defined group ranges are included. Triangles in gaps between groups are excluded.\n\nNote that all query functions expect arguments in local space of the BVH and return results in local space, as well. If world space results are needed they must be transformed into world space using `object.matrixWorld`.\n\n### static .serialize\n\n```js\nstatic serialize( bvh : MeshBVH, options : Object = null ) : SerializedBVH\n```\n\nGenerates a representation of the complete bounds tree and the geometry index buffer which can be used to recreate a bounds tree using the [deserialize](#static-deserialize) function. The `serialize` and `deserialize` functions can be used to generate a MeshBVH asynchronously in a background web worker to prevent the main thread from stuttering. The BVH roots buffer stored in the serialized representation are the same as the ones used by the original BVH so they should not be modified. If `SharedArrayBuffers` are used then the same BVH memory can be used for multiple BVH in multiple WebWorkers.\n\n`bvh` is the MeshBVH to be serialized. The `options` object can have the following fields:\n\n```js\n{\n\n\t// if true then a clone of the `geometry.index.array` and MeshBVH buffers are made which slightly slower but\n\t// ensures modifications do not affect the serialized content. Can be set to \"false\" if it is guaranteed that\n\t// no modifications will be made, to save memory, or transfer and share them across WebWorkers if SharedArrayBuffers\n\t// are being used.\n\tcloneBuffers: true\n\n}\n```\n\n### static .deserialize\n\n```js\nstatic deserialize( data : SerializedBVH, geometry : BufferGeometry, options : Object = null ) : MeshBVH\n```\n\nReturns a new MeshBVH instance from the serialized data. `geometry` is the geometry used to generate the original BVH `data` was derived from. The root buffers stored in `data` are set directly on the new BVH so the memory is shared.\n\nThe `options` object can have the following fields:\n\n```js\n{\n\t// If true then the buffer for the `geometry.index` attribute is set from the serialized\n\t// data attribute or created if an index does not exist.\n\tsetIndex: true,\n\n}\n```\n\n_NOTE: In order for the bounds tree to be used for casts the geometry index attribute must be replaced by the data in the SeralizedMeshBVH object._\n\n### .constructor\n\n```js\nconstructor( geometry : BufferGeometry, options : Object )\n```\n\nConstructs the bounds tree for the given geometry and produces a new index attribute buffer. A reference to the passed geometry is retained. The available options are\n\n```js\n{\n    // Which split strategy to use when constructing the BVH.\n    strategy: CENTER,\n\n    // The maximum depth to allow the tree to build to.\n    // Setting this to a smaller trades raycast speed for better construction\n    // time and less memory allocation.\n    maxDepth: 40,\n\n    // The number of triangles to aim for in a leaf node. Setting this to a lower\n    // number can improve raycast performance but increase construction time and\n    // memory footprint.\n    maxLeafTris: 10,\n\n    // If true then the bounding box for the geometry is set once the BVH\n    // has been constructed.\n    setBoundingBox: true,\n\n    // If true then the MeshBVH will use SharedArrayBuffer rather than ArrayBuffer when\n    // initializing the BVH buffers. Geometry index data will be created as a\n    // SharedArrayBuffer only if it needs to be created. Otherwise it is used as-is.\n    useSharedArrayBuffer: false,\n\n    // An optional function that takes a \"progress\" argument in the range [0, 1]\n    // indicating the progress along BVH generation. Useful primarily when generating\n    // the BVH asynchronously with the GenerateMeshBVHWorker class.\n    onProgress: null,\n\n    // If false then an index buffer is created if it does not exist and is rearranged\n    // to hold the bvh structure. If true then a separate buffer is created to store the\n    // structure and the index buffer (or lack thereof) is retained. This can be used\n    // when the existing index layout is important or groups are being used so a\n    // single BVH hierarchy can be created to improve performance.\n    indirect: false,\n\n    // Print out warnings encountered during tree construction.\n    verbose: true,\n\n    // If given, the MeshBVH will be computed for the given range on the geometry.\n    // If not specified, geometry.drawRange is used.\n    range: { start: number, count: number }\n\n}\n```\n\n*NOTE: The geometry's index attribute array is modified in order to build the bounds tree unless `indirect` is set to `true`. If the geometry has no index then one is added if `indirect` is set to `false`.*\n\n### .resolveTriangleIndex\n\n```js\nresolveTriangleIndex( index : Number ) : Number\n```\n\nHelper function for use when `indirect` is set to true. This function takes a triangle index in the BVH layout and returns the associated triangle index in the geometry index buffer or position attribute.\n\n### .raycast\n\n```js\nraycast( ray : Ray, side : FrontSide | BackSide | DoubleSide = FrontSide, near : Number = 0, far : Number = Infinity ) : Array\u003cRaycastHit\u003e\n```\n```js\nraycast( ray : Ray, material? : Array\u003cMaterial\u003e | Material, near : Number = 0, far : Number = Infinity ) : Array\u003cRaycastHit\u003e\n```\n\nReturns all raycast triangle hits in unsorted order. It is expected that `ray` is in the frame of the BVH already. Likewise the returned results are also provided in the local frame of the BVH. The `side` identifier is used to determine the side to check when raycasting or a material with the given side field can be passed. If an array of materials is provided then it is expected that the geometry has groups and the appropriate material side is used per group.\n\nNote that unlike three.js' Raycaster results the points and distances in the intersections returned from this function are relative to the local frame of the MeshBVH. When using the [acceleratedRaycast](#acceleratedRaycast) function as an override for `Mesh.raycast` they are transformed into world space to be consistent with three's results.\n\n### .raycastFirst\n\n```js\nraycastFirst( ray : Ray, side : FrontSide | BackSide | DoubleSide = FrontSide, near : Number = 0, far : Number = Infinity ) : RaycastHit\n```\n```js\nraycastFirst( ray : Ray, material : Array\u003cMaterial\u003e | Material, near : Number = 0, far : Number = Infinity ) : RaycastHit\n```\n\nReturns the first raycast hit in the model. This is typically much faster than returning all hits. See [raycast](#raycast) for information on the side and material options as well as the frame of the returned intersections.\n\n### .raycastObject3D\n\n```js\nraycastObject3D( mesh: Mesh, raycaster: Raycaster, intersects = []: Array\u003cRaycastHit\u003e ): Array\u003cRaycastHit\u003e\n```\n\nA convenience function for performing a raycast based on a mesh. Results are formed like three.js raycast results in world frame.\n\n### .intersectsSphere\n\n```js\nintersectsSphere( sphere : Sphere ) : Boolean\n```\n\nReturns whether or not the mesh intersects the given sphere.\n\n### .intersectsBox\n\n```js\nintersectsBox( box : Box3, boxToBvh : Matrix4 ) : Boolean\n```\n\nReturns whether or not the mesh intersects the given box.\n\nThe `boxToBvh` parameter is the transform of the box in the meshes frame.\n\n### .intersectsGeometry\n\n```js\nintersectsGeometry( geometry : BufferGeometry, geometryToBvh : Matrix4 ) : Boolean\n```\n\nReturns whether or not the mesh intersects the given geometry.\n\nThe `geometryToBvh` parameter is the transform of the geometry in the BVH's local frame.\n\nPerformance improves considerably if the provided geometry _also_ has a `boundsTree`.\n\n### .closestPointToPoint\n\n```js\nclosestPointToPoint(\n\tpoint : Vector3,\n\ttarget : Object = {},\n\tminThreshold : Number = 0,\n\tmaxThreshold : Number = Infinity\n) : target\n```\n\nComputes the closest distance from the point to the mesh and gives additional information in `target`. The target can be left undefined to default to a new object which is ultimately returned by the function.\n\nIf a point is found that is closer than `minThreshold` then the function will return that result early. Any triangles or points outside of `maxThreshold` are ignored. If no point is found within the min / max thresholds then `null` is returned and the `target` object is not modified.\n\n```js\ntarget : {\n\tpoint : Vector3,\n\tdistance : Number,\n\tfaceIndex : Number\n}\n```\n\nThe returned faceIndex can be used with the standalone function [getTriangleHitPointInfo](#getTriangleHitPointInfo) to obtain more information like UV coordinates, triangle normal and materialIndex.\n\n### .closestPointToGeometry\n\n```js\nclosestPointToGeometry(\n\tgeometry : BufferGeometry,\n\tgeometryToBvh : Matrix4,\n\ttarget1 : Object = {},\n\ttarget2 : Object = {},\n\tminThreshold : Number = 0,\n\tmaxThreshold : Number = Infinity\n) : target1\n```\n\nComputes the closest distance from the geometry to the mesh and puts the closest point on the mesh in `target1` (in the frame of the BVH) and the closest point on the other geometry in `target2` (in the geometry frame). If `target1` is not provided a new Object is created and returned from the function.\n\nThe `geometryToBvh` parameter is the transform of the geometry in the BVH's local frame.\n\nIf a point is found that is closer than `minThreshold` then the function will return that result early. Any triangles or points outside of `maxThreshold` are ignored. If no point is found within the min / max thresholds then `null` is returned and the target objects are not modified.\n\n`target1` and `target2` are optional objects that similar to the `target` parameter in [closestPointPoint](#closestPointToPoint) and set with the same fields as that function.\n\nThe returned in `target1` and `target2` can be used with the standalone function [getTriangleHitPointInfo](#getTriangleHitPointInfo) to obtain more information like UV coordinates, triangle normal and materialIndex.\n\n_Note that this function can be very slow if `geometry` does not have a `geometry.boundsTree` computed._\n\n### .shapecast\n\n```js\nshapecast(\n\tcallbacks : {\n\n\t\tboundsTraverseOrder : (\n\t\t\tbox: Box3\n\t\t) =\u003e Number = null,\n\n\t\tintersectsBounds : (\n\t\t\tbox : Box3,\n\t\t\tisLeaf : Boolean,\n\t\t\tscore : Number | undefined,\n\t\t\tdepth : Number,\n\t\t\tnodeIndex : Number\n\t\t) =\u003e NOT_INTERSECTED | INTERSECTED | CONTAINED,\n\n\t\tintersectsRange : (\n\t\t\ttriangleOffset : Number,\n\t\t\ttriangleCount : Number\n\t\t\tcontained : Boolean,\n\t\t\tdepth : Number,\n\t\t\tnodeIndex : Number,\n\t\t\tbox: Box3\n\t\t) =\u003e Boolean = null,\n\n\t\tintersectsTriangle : (\n\t\t\ttriangle : ExtendedTriangle,\n\t\t\ttriangleIndex : Number,\n\t\t\tcontained : Boolean,\n\t\t\tdepth : Number\n\t\t) =\u003e Boolean = null,\n\n\t}\n\n) : Boolean\n```\n\nA generalized cast function that can be used to implement intersection logic for custom shapes. This is used internally for [intersectsBox](#intersectsBox), [intersectsSphere](#intersectsSphere), and more. The function returns as soon as a triangle has been reported as intersected and returns `true` if a triangle has been intersected. The bounds are traversed in depth first order calling `boundsTraverseOrder`, `intersectsBoundsFunc`, `intersectsRange`, and `intersectsTriangle` for each node and using the results to determine when to end traversal. The `depth` value passed to callbacks indicates the depth of the bounds the provided box or triangle range belongs to unless the triangles are indicated to be `CONTAINED`, in which case depth is the depth of the parent bounds that were contained. The depth field can be used to precompute, cache to an array, and then read information about a parent bound to improve performance while traversing because nodes are traversed in a dpeth first order. The `triangleIndex` parameter specifies the index of the triangle in the index buffer. The three vertex indices can be computed as `triangleIndex * 3 + 0`, `triangleIndex * 3 + 1`, `triangleIndex * 3 + 2`.\n\n`boundsTraverseOrder` takes as an argument the axis aligned bounding box representing an internal node local to the BVH and returns a score (often distance) used to determine whether the left or right node should be traversed first. The shape with the lowest score is traversed first.\n\n`intersectsBounds` takes the axis aligned bounding box representing an internal node local to the bvh, whether or not the node is a leaf, the score calculated by `boundsTraverseOrder`, the node depth, and the node index (for use with the [refit](#refit) function) and returns a constant indicating whether or not the bounds is intersected or contained meaning traversal should continue. If `CONTAINED` is returned (meaning the bounds is entirely encapsulated by the shape) then an optimization is triggered allowing the range and / or triangle intersection callbacks to be run immediately rather than traversing the rest of the child bounds.\n\n`intersectsRange` takes a triangle offset and count representing the number of triangles to be iterated over. 1 triangle from this range represents 3 values in the geometry's index buffer. If this function returns true then traversal is stopped and `intersectsTriangle` is not called if provided.\n\n\u003e [!NOTE]\n\u003e The triangle range provided in `intersectsRange` is for the indirect bvh storage buffer if the option has been set so it is necessary to transform to geometry triangle indices using `resolveTriangleIndex`.\n\n`intersectsTriangle` takes a triangle and the triangle index and returns whether or not the triangle has been intersected. If the triangle is reported to be intersected the traversal ends and the `shapecast` function completes. If multiple triangles need to be collected or intersected return false here and push results onto an array. `contained` is set to `true` if one of the parent bounds was marked as entirely contained (returned `CONTAINED`) in the `intersectsBoundsFunc` function.\n\n### .bvhcast\n\n```js\nbvhcast(\n\totherBvh : MeshBVH,\n\tmatrixToLocal : Matrix4,\n\tcallbacks : {\n\n\t\tintersectsRanges : (\n\t\t\toffset1 : Number,\n\t\t\tcount1 : Number,\n\t\t\toffset2 : Number,\n\t\t\tcount2 : Number,\n\t\t\tdepth1 : Number,\n\t\t\tnodeIndex1 : Number,\n\t\t\tdepth2 : Number,\n\t\t\tnodeIndex2 : Number\n\t\t) =\u003e Boolean = null,\n\n\t\tintersectsTriangles : (\n\t\t\ttriangle1 : ExtendedTriangle,\n\t\t\ttriangle2 : ExtendedTriangle,\n\t\t\ttriangleIndex1 : Number,\n\t\t\ttriangleIndex2 : Number,\n\t\t\tdepth1 : Number,\n\t\t\tnodeIndex1 : Number,\n\t\t\tdepth2 : Number,\n\t\t\tnodeIndex2 : Number\n\t\t) =\u003e Boolean = null\n\n\t}\n\n) : Boolean\n```\n\nA generalized cast function that traverses two BVH structures simultaneously to perform intersection tests between them. This is used internally by [intersectsGeometry](#intersectsGeometry). The function returns `true` as soon as a triangle pair has been reported as intersected by the callbacks. Both BVH trees are traversed in depth-first order, alternating descent.\n\n`matrixToLocal` is a Matrix4 that transforms `otherBvh` into the local space of this BVH. The other BVH's triangles are transformed by this matrix before intersection tests.\n\n`intersectsRanges` is called when both trees have reached leaf nodes, providing triangle ranges from both BVHs. The `offset` and `count` parameters represent ranges in each BVH's triangle storage. If this function returns `true`, traversal stops immediately. If not provided, traversal continues to `intersectsTriangles`.\n\n`intersectsTriangles` is called for each pair of triangles from the two BVHs when leaf nodes are reached. Both triangles are provided as `ExtendedTriangle` objects, with `triangle2` already transformed into the local space of the first BVH. If this callback returns `true`, traversal stops immediately and the function returns `true`. If multiple triangle pairs need to be collected, return `false` and push results onto an array.\n\nThe `triangleIndex1` and `triangleIndex2` parameters specify the indices of the triangles in their respective geometries. These indices are automatically resolved if either BVH was built with the `indirect` option, so they always represent the actual triangle indices in the geometry (not BVH storage indices).\n\nThe `offset1`, `count1`, `offset2`, and `count2` parameters in `intersectsRanges` represent triangle ranges in the BVH storage buffers. If a BVH was built with the `indirect` option, these offsets refer to the indirect buffer indices and must be resolved using `resolveTriangleIndex` if you need the actual geometry triangle indices.\n\n\u003e [!NOTE]\n\u003e Triangle indices provided to `intersectsTriangles` are already resolved to geometry indices, but range offsets provided to `intersectsRanges` are BVH storage indices and require manual resolution if needed.\n\n### .refit\n\n```js\nrefit( nodeIndices : Array\u003cNumber\u003e | Set\u003cNumber\u003e = null ) : void\n```\n\nRefit the node bounds to the current triangle positions. This is quicker than regenerating a new BVH but will not be optimal after significant changes to the vertices. `nodeIndices` is a set of node indices (provided by the [shapecast](#shapecast) function, see example snippet below) that need to be refit including all internal nodes. If one of a nodes children is also included in the set of node indices then only the included child bounds are traversed. If neither child index is included in the `nodeIndices` set, though, then it is assumed that every child below that node needs to be updated.\n\nHere's how to get the set of indices that need to be refit:\n\n```js\nconst nodeIndices = new Set();\nbvh.shapecast(\n\n\t{\n\n\t\tintersectsBounds: ( box, isLeaf, score, depth, nodeIndex ) =\u003e {\n\n\t\t\tif ( /* intersects shape */ ) {\n\n\t\t\t\tnodeIndices.add( nodeIndex );\n\t\t\t\treturn INTERSECTED;\n\n\t\t\t}\n\n\t\t\treturn NOT_INTERSECTED;\n\n\t\t},\n\n\t\tintersectsRange: ( offset, count, contained, depth, nodeIndex ) =\u003e {\n\n\t\t\t/* collect triangles / vertices to move */\n\n\t\t\t// the nodeIndex here will have always already been added to the set in the\n\t\t\t// `intersectsBounds` callback.\n\t\t\tnodeIndices.add( nodeIndex );\n\n\t\t}\n\n\t}\n\n);\n\n/* update the positions of the triangle vertices */\n\n// update the BVH bounds of just the bounds that need to be updated\nbvh.refit( nodeIndices );\n```\n\n### .shiftTriangleOffsets\n\n```js\nshiftTriangleOffsets( offset : Number ) : void\n```\n\nAdjusts all triangle offsets stored in the BVH by the given offset. This is useful when the triangle data has been compacted or shifted in the geometry buffers (e.g. in `BatchedMesh` when geometries are compacted using the \"optimize\" function or constructing a \"merged\" BVH).\n\nThis function only adjusts the BVH to point to different triangles in the geometry. The geometry's index buffer and/or position attributes must be updated separately to match.\n\n**Example use case with merged geometry:**\n\n```js\nconst boxGeometry = new BoxGeometry();\nconst sphereGeometry = new SphereGeometry();\n\n// construct the BVH\nconst sphereBvh = new MeshBVH( sphereGeometry );\n\n// ...\n\n// adjust the bvh so it points to the new geometry and adjust the BVH triangle offsets\n// by the amount in the box geometry\nconst mergedGeometry = mergeGeometries( [ boxGeometry, sphereGeometry ] );\nsphereBvh.geometry = mergedGeometry;\nsphereBvh.shiftTriangleOffsets( boxGeometry.index.count / 3 );\n```\n\n### .getBoundingBox\n\n```js\ngetBoundingBox( target : Box3 ) : Box3\n```\n\nGet the bounding box of the geometry computed from the root node bounds of the BVH. Significantly faster than `BufferGeometry.computeBoundingBox`.\n\n## SerializedBVH\n\n### .roots\n\n```js\nroots : Array\u003cArrayBuffer\u003e\n```\n\n### .index\n\n```js\nindex : TypedArray\n```\n\n## MeshBVHHelper\n\n_extends THREE.Group_\n\nDisplays a view of the bounds tree up to the given depth of the tree. Update() must be called after any fields that affect visualization geometry are changed.\n\n_Note: The visualizer is expected to be a sibling of the mesh being visualized._\n\n### .depth\n\n```js\ndepth : Number\n```\n\nThe depth to traverse and visualize the tree to.\n\n### .color\n\n```js\ncolor = 0x00FF88 : THREE.Color\n```\n\nThe color to render the bounding volume with.\n\n### .opacity\n\n```js\nopacity = 0.3 : Number\n```\n\nThe opacity to render the bounding volume with.\n\n### .displayParents\n\n```js\ndisplayParents = false : Boolean\n```\n\nWhether or not to display the parent bounds.\n\n### .displayEdges\n\n```js\ndisplayEdges = true : Boolean\n```\n\nIf true displays the bounds as edges other displays the bounds as solid meshes.\n\n### .objectIndex\n\n```js\nobjectIndex = 0 : Number\n```\n\nWhen using an `InstancedMesh` or a `BatchedMesh` this refers to the item index to use for the BVH and / or matrix transformation to use.\n\n### .edgeMaterial\n\n```js\nedgeMaterial : LineBasicMaterial\n```\n\nThe material to use when rendering edges.\n\n### .meshMaterial\n\n```js\nmeshMaterial : MeshBasicMaterial\n```\n\nThe material to use when rendering as a sold meshes.\n\n### .constructor\n\n```js\nconstructor(\n\tmeshOrBvh: THREE.Mesh | MeshBVH,\n\tdepth = 10 : Number\n)\n\nconstructor(\n\tmesh = null : THREE.Mesh,\n\tbvh = null : MeshBVH,\n\tdepth = 10 : Number\n)\n```\n\nInstantiates the helper to visualize a MeshBVH.\n\nIf a `mesh` and no `bvh` is provided then the `mesh.geometry.boundsTree` is displayed. Otherwise the provided bvh is displayed. Additionally, if `mesh` is provided then the helper world transform is automatically synchronized with the Mesh. Otherwise if not `mesh` is provided then the user can manage the transform.\n\n### .update\n\n```js\nupdate() : void\n```\n\nUpdates the display of the bounds tree in the case that the bounds tree has changed or the depth parameter has changed.\n\n### .dispose\n\n```js\ndispose() : void\n```\n\nDisposes of the material used.\n\n## ExtendedTriangle\n\n_extends THREE.Triangle_\n\nAn extended version of three.js' Triangle class. A variety of derivative values are cached on the object to accelerate the intersection functions. `.needsUpdate` must be set to true when modifying the triangle parameters.\n\n### .needsUpdate\n\n```js\nneedsUpdate : Boolean\n```\n\nIndicates that the triangle fields have changed so cached variables to accelerate other function execution can be updated. Must be set to true after modifying the triangle `a`, `b`, `c` fields.\n\n### .intersectsTriangle\n\n```js\nintersectsTriangle( other : Triangle, target? : Line3  ) : Boolean;\n```\n\nReturns whether the triangles intersect. `target` is set to the line segment representing the intersection.\n\n### .intersectsSphere\n\n```js\nintersectsSphere( sphere : Sphere ) : Boolean\n```\n\nReturns whether the triangle intersects the given sphere.\n\n### .closestPointToSegment\n\n```js\nclosestPointToSegment( segment : Line3, target1? : Vector3, target2? : Vector3 ) : Number\n```\n\nReturns the distance to the provided line segment. `target1` and `target2` are set to the closest points on the triangle and segment respectively.\n\n### .distanceToPoint\n\n```js\ndistanceToPoint( point : Vector3 ) : Number\n```\n\nReturns the distance to the provided point.\n\n### .distanceToTriangle\n\n```js\ndistanceToTriangle( tri : Triangle ) : Number\n```\n\nReturns the distance to the provided triangle.\n\n## OrientedBox\n\n_extends THREE.Box3_\n\nAn oriented version of three.js' Box3 class. A variety of derivative values are cached on the object to accelerate the intersection functions. `.needsUpdate` must be set to true when modifying the box parameters.\n\n### .matrix\n\n```js\nmatrix : Matrix4\n```\n\nMatrix transformation applied to the box.\n\n### .needsUpdate\n\n```js\nupdateUpdate : Boolean\n```\n\nIndicates that the bounding box fields have changed so cached variables to accelerate other function execution can be updated. Must be set to true after modifying the oriented box `min`, `max`, `matrix` fields.\n\n### .set\n\n```js\nset( min : Vector3, max : Vector3, matrix : Matrix4 ) : this\n```\n\nSets the oriented box parameters.\n\n### .intersectsBox\n\n```js\nintersectsBox( box : Box3 ) : Boolean\n```\n\nReturns true if intersecting with the provided box.\n\n### .intersectsTriangle\n\n```js\nintersectsTriangle( tri : Triangle ) : Boolean\n```\n\nReturns true if intersecting with the provided triangle.\n\n### .closestPointToPoint\n\n```js\nclosestPointToPoint( point : Vector3, target = null : Vector3 ) : Number\n```\n\nReturns the distance to the provided point. Sets `target` to the closest point on the surface of the box if provided.\n\n\n### .distanceToPoint\n\n```js\ndistanceToPoint( point : Vector3 ) : Number\n```\n\nReturns the distance to the provided point.\n\n### .distanceToBox\n\n```js\ndistanceToBox( box : Box3, threshold = 0 : Number, target1 = null : Vector3, target2 = null : Vector3 ) : Number\n```\n\nReturns the distance to the provided box. `threshold` is an optional distance to return early if the distance is found to be within it. `target1` and `target2` are set to the points on the surface of this box and the `box` argument respectively.\n\n## Extensions\n\n### Raycaster.firstHitOnly\n\n```js\nfirstHitOnly = false : Boolean\n```\n\nIf the `Raycaster` member `firstHitOnly` is set to true then the [.acceleratedRaycast](#acceleratedRaycast) function will call the [.raycastFirst](#raycastFirst) function to retrieve hits which is generally faster.\n\n### .computeBoundsTree\n\n```js\ncomputeBoundsTree( options? : Object ) : void\n```\n\nA pre-made BufferGeometry extension function that builds a new BVH, assigns it to `boundsTree` for BufferGeometry, and applies the new index buffer to the geometry. Comparable to `computeBoundingBox` and `computeBoundingSphere`.\n\n```js\nTHREE.BufferGeometry.prototype.computeBoundsTree = computeBoundsTree;\n```\n\n### .disposeBoundsTree\n\n```js\ndisposeBoundsTree() : void\n```\n\nA BufferGeometry extension function that disposes of the BVH.\n\n```js\nTHREE.BufferGeometry.prototype.disposeBoundsTree = disposeBoundsTree;\n```\n\n### .computeBatchedBoundsTree\n\n```js\ncomputeBatchedBoundsTree( index = - 1 : Number, options? : Object ) : void\n```\n\nEquivalent of `computeBoundsTree` for BatchedMesh. Calling this generates a `BatchedMesh.boundsTrees` array if it doesn't exist and assigns the newly generated BVHs. If `index` is -1 then BVHs for all available geometry are generated. Otherwise only the BVH for the geometry at the given index is generated.\n\n```js\nTHREE.BatchedMesh.prototype.computeBoundsTree = computeBatchedBoundsTree;\n```\n\n### .disposeBatchedBoundsTree\n\n```js\ndisposeBatchedBoundsTree( index = - 1 : Number, options? : Object ) : void\n```\n\nEquivalent of `disposeBoundsTree` for BatchedMesh. Calling this sets entries in `BatchedMesh.boundsTrees` array to null. If `index` is -1 then BVHs are disposed. Otherwise only the BVH for the geometry at the given index is disposed.\n\n```js\nTHREE.BatchedMesh.prototype.disposeBoundsTree = disposeBatchedBoundsTree;\n```\n\n### .acceleratedRaycast\n\n```js\nacceleratedRaycast( ... )\n```\n\nAn accelerated raycast function with the same signature as `THREE.Mesh.raycast`. Uses the BVH for raycasting if it's available otherwise it falls back to the built-in approach. The results of the function are designed to be identical to the results of the conventional `THREE.Mesh.raycast` results.\n\nIf the raycaster object being used has a property `firstHitOnly` set to `true`, then the raycasting will terminate as soon as it finds the closest intersection to the ray's origin and return only that intersection. This is typically several times faster than searching for all intersections.\n\n```js\nTHREE.Mesh.prototype.raycast = acceleratedRaycast;\n```\n\n## StaticGeometryGenerator\n\nA utility class for taking a set of SkinnedMeshes or morph target geometry and baking it into a single, static geometry that a BVH can be generated for.\n\n### .useGroups\n\n```js\nuseGroups = true : Boolean\n```\n\nIf true then groups are used to support an array of materials on the mesh.\n\n### .attributes\n\n```js\nattributes = [ 'position', 'normal', 'tangent', 'uv', 'uv2' ] : Array\u003cString\u003e\n```\n\nThe set of attributes to copy onto the static geometry.\n\n### .applyWorldTransforms\n\n```js\napplyWorldTransforms = true : Boolean\n```\n\nWhether to transform the vertices of the geometry by the world transforms of each mesh when generating.\n\n### constructor\n\n```js\nconstructor( object : Array\u003cObject3D\u003e )\n```\n\nTakes an array of object hierarchies to bake into a single static geometry.\n\n### .getMaterials\n\n```js\ngetMaterials() : Array\u003cMaterial\u003e\n```\n\nReturns an array of materials for the meshes to be merged. These can be used alongside the generated geometry when creating a mesh: `new Mesh( geometry, generator.getMaterials() )`.\n\n### .generate\n\n```js\ngenerate( target = new BufferGeometry() : BufferGeometry ) : BufferGeometry\n```\n\nGenerates a single, static geometry for the passed meshes. When generating for the first time an empty target geometry is expected. The same generated geometry can be passed into the function on subsequent calls to update the geometry in place to save memory. An error will be thrown if the attributes or geometry on the meshes to bake has been changed and are incompatible lengths, types, etc.\n\nOn subsequent calls the \"index\" buffer will not be modified so any BVH generated for the geometry is unaffected. Once the geometry is updated the `MeshBVH.refit` function can be called to update the BVH.\n\n## GenerateMeshBVHWorker\n\nHelper class for generating a MeshBVH for a given geometry in asynchronously in a worker. The geometry position and index buffer attribute `ArrayBuffers` are transferred to the Worker while the BVH is being generated meaning the geometry will be unavailable to use while the BVH is being processed unless `SharedArrayBuffers` are used. They will be automatically replaced when the MeshBVH is finished generating.\n\n_NOTE It's best to reuse a single instance of this class to avoid the overhead of instantiating a new Worker._\n\n_See note in [Asynchronous Generation](#asynchronous-generation) use snippet._\n\n### .running\n\n```js\nrunning : Boolean;\n```\n\nFlag indicating whether or not a BVH is already being generated in the worker.\n\n### .generate\n\n```js\ngenerate( geometry : BufferGeometry, options : Object ) : Promise\u003c MeshBVH \u003e;\n```\n\nGenerates a MeshBVH instance for the given geometry with the given options in a WebWorker. Returns a promise that resolves with the generated MeshBVH. This function will throw an error if it is already running.\n\n### .dispose\n\n```js\ndispose() : void;\n```\n\nTerminates the worker.\n\n## Debug Functions\n\n### estimateMemoryInBytes\n\n```js\nestimateMemoryInBytes( bvh : MeshBVH ) : Number\n```\n\nRoughly estimates the amount of memory in bytes a BVH is using.\n\n### getBVHExtremes\n\n```js\ngetBVHExtremes( bvh : MeshBVH ) : Array\u003c Object \u003e\n```\n\nMeasures the min and max extremes of the tree including node depth, leaf triangle count, and number of splits on different axes to show how well a tree is structured. Returns an array of extremes for each group root for the bvh. The objects are structured like so:\n\n```js\n{\n\t// The total number of nodes in the tree including leaf nodes.\n\tnodeCount: Number,\n\n\t// The total number of leaf nodes in the tree.\n\tleafNodeCount: Number,\n\n\t// A total tree score based on the surface area heuristic score\n\t// useful for comparing the quality and performance capability\n\t// of the bounds tree. Lower score is better and based on the surface\n\t// area of bounds and how many triangles are stored within.\n\tsurfaceAreaScore: Number,\n\n\t// The min and max of leaf nodes in the tree.\n\tdepth: { min: Number, max: Number },\n\n\t// The min and max number of triangles contained within the\n\t// bounds the leaf nodes.\n\ttris: { min: Number, max: Number },\n\n\t// The number of splits on any given axis.\n\tsplits: [ Number, Number, Number ]\n}\n```\n\n_NOTE The when using the [refit](#refit) function the `surfaceAreaScore` can be used to check how significantly the structure of the BVH has degraded and rebuild it if it has changed beyond some threshold ratio._\n\n## Individual Functions\n\nFunctions exported individually not part of a class.\n\n### getTriangleHitPointInfo\n\n```js\ngetTriangleHitPointInfo(\n\tpoint: Vector3,\n\tgeometry : BufferGeometry,\n\ttriangleIndex: Number\n\ttarget: Object\n) : Object\n```\n\nThis function returns information of a point related to a geometry. It returns the `target` object or a new one if passed `undefined`:\n\n```js\ntarget : {\n\tface: {\n\t\ta: Number,\n\t\tb: Number,\n\t\tc: Number,\n\t\tmaterialIndex: Number,\n\t\tnormal: Vector3\n\t},\n\tuv: Vector2\n}\n```\n\n- `a`, `b`, `c`: Triangle indices\n- `materialIndex`: Face material index or 0 if not available.\n- `normal`: Face normal\n- `uv`: UV coordinates.\n\nThis function can be used after a call to [closestPointPoint](#closestPointToPoint) or [closestPointToGeometry](#closestPointToGeometry) to retrieve more detailed result information.\n\n# Shader and Texture Packing API\n\nIn addition to queries in Javascript the BVH can be packed into a series of textures so raycast queries can be performed in a shader using provided WebGL shader functions. See the shader implementation in the [simple GPU Path Tracing example](https://github.com/gkjohnson/three-mesh-bvh/blob/master/example/gpuPathTracingSimple.js) for an example on how to use the functionality.\n\n## *VertexAttributeTexture\n\n### FloatVertexAttributeTexture\n\n### UIntVertexAttributeTexture\n\n### IntVertexAttributeTexture\n\n_extends THREE.DataTexture_\n\nFloat, Uint, and Int VertexAttributeTexture implementations are designed to simplify the efficient packing of a three.js BufferAttribute into a texture. An instance can be treated as a texture and when passing as a uniform to a shader they should be used as a `sampler2d`, `usampler2d`, and `isampler2d` when using the Float, Uint, and Int texture types respectively.\n\n### .overrideItemSize\n\n```js\noverrideItemSize : Number = null\n```\n\nTreats `BufferAttribute.itemSize` as though it were set to this value when packing the buffer attribute texture. Throws an error if the value does not divide evenly into the length of the BufferAttribute buffer (`count * itemSize % overrideItemSize`).\n\nSpecifically used to pack geometry indices into an RGB texture rather than an Red texture.\n\n### .updateFrom\n\n```js\nupdateFrom( attribute : THREE.BufferAttribute ) : void\n```\n\nUpdates the texture to have the data contained in the passed BufferAttribute using the BufferAttribute `itemSize` field, `normalized` field, and TypedArray layout to determine the appropriate texture layout, format, and type. The texture dimensions will always be square. Because these are intended to be sampled as 1D arrays the width of the texture msut be taken into account to derive a sampling uv. See `texelFetch1D` in [shaderFunctions](#shaderFunctions).\n\n## MeshBVHUniformStruct\n\nA shader uniform object corresponding to the `BVH` shader struct defined in [shaderStructs](#shaderStructs). The object contains four textures containing information about the BVH and geometry so it can be queried in a shader using the bvh intersection functions defined in [shaderFunctions](#shaderFunctions). This object is intended to be used as a shader uniform and read in the shader as a `BVH` struct.\n\n### .updateFrom\n\n```js\nupdateFrom( bvh : MeshBVH ) : void\n```\n\nUpdates the object and associated textures with data from the provided BVH.\n\n### .dispose\n\n```js\ndispose() : void\n```\n\nDispose of the associated textures.\n\n## WebGL Shader Function and Struct Exports\n\n### shaderStructs\n\n```js\nBVHShaderGLSL.bvh_struct_definitions : string\n```\n\nSet of shaders structs and defined constants used for interacting with the packed BVH in a shader. See [src/webgl/glsl/bvh_struct_definitions.glsl.js](https://github.com/gkjohnson/three-mesh-bvh/blob/master/src/webgl/glsl/bvh_struct_definitions.glsl.js) for full implementations and declarations.\n\n### shaderFunctions\n\n```js\nBVHShaderGLSL.bvh_distance_functions : string\nBVHShaderGLSL.bvh_ray_functions : string\nBVHShaderGLSL.common_functions : string\n```\n\nSet of shader functions used for interacting with the packed BVH in a shader and sampling [VertexAttributeTextures](#VertexAttributeTexture). See [src/webgl/glsl](https://github.com/gkjohnson/three-mesh-bvh/tree/master/src/webgl/glsl) for full implementations and declarations.\n\n## Gotchas\n\n- When querying the MeshBVH directly all shapes and geometry are expected to be specified in the local frame of the BVH. When using three.js' built in raycasting system all results are implicitly transformed into world coordinates.\n- A bounds tree can be generated for either an indexed or non-indexed `BufferGeometry`, but an index will\n  be produced and retained as a side effect of the construction unless the \"indirect\" option is used.\n- The bounds hierarchy is _not_ dynamic, so geometry that uses morph targets or skinning cannot be used. Though if vertex positions are modified directly the [refit](#refit) function can be used to adjust the bounds tree.\n- If the geometry is changed then a new bounds tree will need to be generated or refit.\n- [InterleavedBufferAttributes](https://threejs.org/docs/#api/en/core/InterleavedBufferAttribute) are not supported with the geometry index buffer attribute.\n- A separate bounds tree root is generated for each [geometry group](https://threejs.org/docs/#api/en/objects/Group), which could result in less than optimal raycast performance on geometry with lots of groups. Triangles excluded from these groups are not included in the BVH.\n- Due to errors related to floating point precision it is recommended that geometry be centered using `BufferGeometry.center()` before creating the BVH if the geometry is sufficiently large or off center so bounds tightly contain the geometry as much as possible.\n\n# Running Examples Locally\n\nTo run the examples locally:\n- Run `npm start`\n- Then visit `localhost:5173/\u003cdemo-name\u003e.html`\n\nWhere `\u003cdemo-name\u003e` is the name of the HTML file from `example` folder.\n\n\n# Used and Supported by\n\n\u003ca href=\"https://www.threekit.com/\" title=\"threekit\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/734200/162633617-aad48fd1-931e-4e5e-8811-c29e799ee95a.png\" width=\"20%\"/\u003e\u003c/a\u003e\u003ca href=\"https://matterport.com/\" title=\"matterport\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/734200/162633614-27f7f1e5-7f3c-4c55-99da-de0e7636dbcf.png\" width=\"20%\"/\u003e\u003c/a\u003e\u003ca href=\"https://www.flux.ai/\" title=\"flux\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/734200/162633622-ed1e80b2-ee3b-4998-872c-a690d7b86eaf.png\" width=\"20%\"/\u003e\u003c/a\u003e\u003ca href=\"https://www.resonai.com/\" title=\"resonai\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/734200/162694304-57be0ef3-a2d4-4af7-b3e0-6626cbef97a0.png\" width=\"20%\"/\u003e\u003c/a\u003e\u003ca href=\"https://www.sitescape.ai/\" title=\"sitescape\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/734200/162633616-2649b441-dca8-490c-891f-f433aad24172.png\" width=\"20%\"/\u003e\u003c/a\u003e\u003ca href=\"https://ifcjs.github.io/info/\" title=\"ifc.js\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/734200/162633613-1fa05098-0610-4e93-936a-ea12bcdc62e3.png\" width=\"20%\"/\u003e\u003c/a\u003e\u003ca href=\"https://utsubo.co/\" title=\"utsubo\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/734200/162633619-fb6404c0-3a7d-40b2-8e9a-2014d904146c.png\" width=\"20%\"/\u003e\u003c/a\u003e\u003ca href=\"https://github.com/phoenixbf/aton\" title=\"aton\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/734200/162633621-d0b49f47-5520-48da-a1fd-1d1fa88459a6.png\" width=\"20%\"/\u003e\u003c/a\u003e\u003ca href=\"https://polygonjs.com/\" title=\"polygonjs\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/734200/162633615-b6d136e1-1580-4230-a3e9-2dfbcf8923d1.png\" width=\"20%\"/\u003e\u003c/a\u003e\u003ca href=\"https://vartiste.xyz/\" title=\"vartiste\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/734200/162633620-e95f446f-af5d-4579-8ab5-2eeaf00b37ad.png\" width=\"20%\"/\u003e\u003c/a\u003e\n\n...and more!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgkjohnson%2Fthree-mesh-bvh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgkjohnson%2Fthree-mesh-bvh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgkjohnson%2Fthree-mesh-bvh/lists"}