@react-three/drei
Version:
useful add-ons for react-three-fiber
158 lines (155 loc) • 4.92 kB
JavaScript
import _extends from '@babel/runtime/helpers/esm/extends';
import * as React from 'react';
import * as THREE from 'three';
import { extend } from '@react-three/fiber';
import { WireframeMaterial, WireframeMaterialShaders, useWireframeUniforms, setWireframeOverride } from '../materials/WireframeMaterial.js';
function isWithGeometry(object) {
return !!(object != null && object.geometry);
}
function isGeometry(object) {
return !!(object != null && object.isBufferGeometry);
}
function isRefObject(object) {
return !!(object != null && object.current);
}
function isRef(object) {
return (object == null ? void 0 : object.current) !== undefined;
}
function isWireframeGeometry(geometry) {
return geometry.type === 'WireframeGeometry';
}
function getUniforms() {
const u = {};
for (const key in WireframeMaterialShaders.uniforms) {
u[key] = {
value: WireframeMaterialShaders.uniforms[key]
};
}
return u;
}
function getBarycentricCoordinates(geometry, removeEdge) {
const position = geometry.getAttribute('position');
const count = position.count;
const barycentric = [];
for (let i = 0; i < count; i++) {
const even = i % 2 === 0;
const Q = removeEdge ? 1 : 0;
if (even) {
barycentric.push(0, 0, 1, 0, 1, 0, 1, 0, Q);
} else {
barycentric.push(0, 1, 0, 0, 0, 1, 1, 0, Q);
}
}
return new THREE.BufferAttribute(Float32Array.from(barycentric), 3);
}
function getInputGeometry(inputGeometry) {
const geo = isRefObject(inputGeometry) ? inputGeometry.current : inputGeometry;
if (!isGeometry(geo)) {
// Disallow WireframeGeometry
if (isWireframeGeometry(geo)) {
throw new Error('Wireframe: WireframeGeometry is not supported.');
}
const parent = geo.parent;
if (isWithGeometry(parent)) {
// Disallow WireframeGeometry
if (isWireframeGeometry(parent.geometry)) {
throw new Error('Wireframe: WireframeGeometry is not supported.');
}
return parent.geometry;
}
} else {
return geo;
}
}
function setBarycentricCoordinates(geometry, simplify) {
if (geometry.index) {
console.warn('Wireframe: Requires non-indexed geometry, converting to non-indexed geometry.');
const nonIndexedGeo = geometry.toNonIndexed();
geometry.copy(nonIndexedGeo);
geometry.setIndex(null);
}
const newBarycentric = getBarycentricCoordinates(geometry, simplify);
geometry.setAttribute('barycentric', newBarycentric);
}
function WireframeWithCustomGeo({
geometry: customGeometry,
simplify = false,
...props
}) {
extend({
MeshWireframeMaterial: WireframeMaterial
});
const [geometry, setGeometry] = React.useState(null);
React.useLayoutEffect(() => {
const geom = getInputGeometry(customGeometry);
if (!geom) {
throw new Error('Wireframe: geometry prop must be a BufferGeometry or a ref to a BufferGeometry.');
}
setBarycentricCoordinates(geom, simplify);
if (isRef(customGeometry)) {
setGeometry(geom);
}
}, [simplify, customGeometry]);
const drawnGeo = isRef(customGeometry) ? geometry : customGeometry;
return /*#__PURE__*/React.createElement(React.Fragment, null, drawnGeo && /*#__PURE__*/React.createElement("mesh", {
geometry: drawnGeo
}, /*#__PURE__*/React.createElement("meshWireframeMaterial", _extends({
attach: "material",
transparent: true,
side: THREE.DoubleSide,
polygonOffset: true //
,
polygonOffsetFactor: -4
}, props, {
extensions: {
derivatives: true,
fragDepth: false,
drawBuffers: false,
shaderTextureLOD: false
}
}))));
}
function WireframeWithoutCustomGeo({
simplify = false,
...props
}) {
const objectRef = React.useRef(null);
const uniforms = React.useMemo(() => getUniforms(), [WireframeMaterialShaders.uniforms]);
useWireframeUniforms(uniforms, props);
React.useLayoutEffect(() => {
const geom = getInputGeometry(objectRef);
if (!geom) {
throw new Error('Wireframe: Must be a child of a Mesh, Line or Points object or specify a geometry prop.');
}
const og = geom.clone();
setBarycentricCoordinates(geom, simplify);
return () => {
geom.copy(og);
og.dispose();
};
}, [simplify]);
React.useLayoutEffect(() => {
const parentMesh = objectRef.current.parent;
const og = parentMesh.material.clone();
setWireframeOverride(parentMesh.material, uniforms);
return () => {
parentMesh.material.dispose();
parentMesh.material = og;
};
}, []);
return /*#__PURE__*/React.createElement("object3D", {
ref: objectRef
});
}
function Wireframe({
geometry: customGeometry,
...props
}) {
if (customGeometry) {
return /*#__PURE__*/React.createElement(WireframeWithCustomGeo, _extends({
geometry: customGeometry
}, props));
}
return /*#__PURE__*/React.createElement(WireframeWithoutCustomGeo, props);
}
export { Wireframe };