UNPKG

@react-three/drei

Version:

useful add-ons for react-three-fiber

76 lines (73 loc) 2.87 kB
import _extends from '@babel/runtime/helpers/esm/extends'; import * as React from 'react'; import { MeshSurfaceSampler } from 'three-stdlib'; import { InstancedBufferAttribute, Vector3, Color, Object3D } from 'three'; function useSurfaceSampler(mesh, count = 16, transform, weight, instanceMesh) { const [buffer, setBuffer] = React.useState(() => { const arr = Array.from({ length: count }, () => [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]).flat(); return new InstancedBufferAttribute(Float32Array.from(arr), 16); }); React.useLayoutEffect(() => { if (typeof mesh.current === 'undefined') return; const sampler = new MeshSurfaceSampler(mesh.current); if (weight) { sampler.setWeightAttribute(weight); } sampler.build(); const position = new Vector3(); const normal = new Vector3(); const color = new Color(); const dummy = new Object3D(); mesh.current.updateMatrixWorld(true); for (let i = 0; i < count; i++) { sampler.sample(position, normal, color); if (typeof transform === 'function') { transform({ dummy, sampledMesh: mesh.current, position, normal, color }, i); } else { dummy.position.copy(position); } dummy.updateMatrix(); if (instanceMesh != null && instanceMesh.current) { instanceMesh.current.setMatrixAt(i, dummy.matrix); } dummy.matrix.toArray(buffer.array, i * 16); } if (instanceMesh != null && instanceMesh.current) { instanceMesh.current.instanceMatrix.needsUpdate = true; } buffer.needsUpdate = true; setBuffer(new InstancedBufferAttribute(buffer.array, buffer.itemSize).copy(buffer)); }, [mesh, instanceMesh, weight, count, transform]); return buffer; } function Sampler({ children, weight, transform, instances, mesh, count = 16, ...props }) { const group = React.useRef(null); const instancedRef = React.useRef(null); const meshToSampleRef = React.useRef(null); React.useLayoutEffect(() => { var _instances$current, _mesh$current; instancedRef.current = (_instances$current = instances == null ? void 0 : instances.current) !== null && _instances$current !== void 0 ? _instances$current : group.current.children.find(c => c.hasOwnProperty('instanceMatrix')); meshToSampleRef.current = (_mesh$current = mesh == null ? void 0 : mesh.current) !== null && _mesh$current !== void 0 ? _mesh$current : group.current.children.find(c => c.type === 'Mesh'); }, [children, mesh == null ? void 0 : mesh.current, instances == null ? void 0 : instances.current]); useSurfaceSampler(meshToSampleRef, count, transform, weight, instancedRef); return /*#__PURE__*/React.createElement("group", _extends({ ref: group }, props), children); } export { Sampler, useSurfaceSampler };