@react-three/drei
Version:
useful add-ons for react-three-fiber
93 lines (89 loc) • 2.81 kB
JavaScript
import _extends from '@babel/runtime/helpers/esm/extends';
import { useThree } from '@react-three/fiber';
import * as React from 'react';
import { Mesh } from 'three';
import { SAH, acceleratedRaycast, computeBoundsTree, disposeBoundsTree } from 'three-mesh-bvh';
const isMesh = child => child.isMesh;
/**
* @deprecated Use the Bvh component instead
*/
function useBVH(mesh, options) {
options = {
strategy: SAH,
verbose: false,
setBoundingBox: true,
maxDepth: 40,
maxLeafTris: 10,
indirect: false,
...options
};
React.useEffect(() => {
if (mesh.current) {
mesh.current.raycast = acceleratedRaycast;
const geometry = mesh.current.geometry;
geometry.computeBoundsTree = computeBoundsTree;
geometry.disposeBoundsTree = disposeBoundsTree;
geometry.computeBoundsTree(options);
return () => {
if (geometry.boundsTree) {
geometry.disposeBoundsTree();
}
};
}
}, [mesh, JSON.stringify(options)]);
}
const Bvh = /* @__PURE__ */React.forwardRef(({
enabled = true,
firstHitOnly = false,
children,
strategy = SAH,
verbose = false,
setBoundingBox = true,
maxDepth = 40,
maxLeafTris = 10,
indirect = false,
...props
}, fref) => {
const ref = React.useRef(null);
const raycaster = useThree(state => state.raycaster);
React.useImperativeHandle(fref, () => ref.current, []);
React.useEffect(() => {
if (enabled) {
const options = {
strategy,
verbose,
setBoundingBox,
maxDepth,
maxLeafTris,
indirect
};
const group = ref.current;
// This can only safely work if the component is used once, but there is no alternative.
// Hijacking the raycast method to do it for individual meshes is not an option as it would
// cost too much memory ...
raycaster.firstHitOnly = firstHitOnly;
group.traverse(child => {
// Only include meshes that do not yet have a boundsTree and whose raycast is standard issue
if (isMesh(child) && !child.geometry.boundsTree && child.raycast === Mesh.prototype.raycast) {
child.raycast = acceleratedRaycast;
child.geometry.computeBoundsTree = computeBoundsTree;
child.geometry.disposeBoundsTree = disposeBoundsTree;
child.geometry.computeBoundsTree(options);
}
});
return () => {
delete raycaster.firstHitOnly;
group.traverse(child => {
if (isMesh(child) && child.geometry.boundsTree) {
child.geometry.disposeBoundsTree();
child.raycast = Mesh.prototype.raycast;
}
});
};
}
}, []);
return /*#__PURE__*/React.createElement("group", _extends({
ref: ref
}, props), children);
});
export { Bvh, useBVH };