Initial project import
This commit is contained in:
128
node_modules/@react-three/drei/core/Decal.js
generated
vendored
Normal file
128
node_modules/@react-three/drei/core/Decal.js
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
import _extends from '@babel/runtime/helpers/esm/extends';
|
||||
import * as React from 'react';
|
||||
import * as THREE from 'three';
|
||||
import { applyProps } from '@react-three/fiber';
|
||||
import { DecalGeometry } from 'three-stdlib';
|
||||
|
||||
function isArray(vec) {
|
||||
return Array.isArray(vec);
|
||||
}
|
||||
function vecToArray(vec = [0, 0, 0]) {
|
||||
if (isArray(vec)) {
|
||||
return vec;
|
||||
} else if (vec instanceof THREE.Vector3 || vec instanceof THREE.Euler) {
|
||||
return [vec.x, vec.y, vec.z];
|
||||
} else {
|
||||
return [vec, vec, vec];
|
||||
}
|
||||
}
|
||||
const Decal = /* @__PURE__ */React.forwardRef(function Decal({
|
||||
debug,
|
||||
depthTest = false,
|
||||
polygonOffsetFactor = -10,
|
||||
map,
|
||||
mesh,
|
||||
children,
|
||||
position,
|
||||
rotation,
|
||||
scale,
|
||||
...props
|
||||
}, forwardRef) {
|
||||
const ref = React.useRef(null);
|
||||
React.useImperativeHandle(forwardRef, () => ref.current);
|
||||
const helper = React.useRef(null);
|
||||
const state = React.useRef({
|
||||
position: new THREE.Vector3(),
|
||||
rotation: new THREE.Euler(),
|
||||
scale: new THREE.Vector3(1, 1, 1)
|
||||
});
|
||||
React.useLayoutEffect(() => {
|
||||
const parent = (mesh == null ? void 0 : mesh.current) || ref.current.parent;
|
||||
const target = ref.current;
|
||||
if (!(parent instanceof THREE.Mesh)) {
|
||||
throw new Error('Decal must have a Mesh as parent or specify its "mesh" prop');
|
||||
}
|
||||
if (parent) {
|
||||
applyProps(state.current, {
|
||||
position,
|
||||
scale
|
||||
});
|
||||
|
||||
// Zero out the parents matrix world for this operation
|
||||
const matrixWorld = parent.matrixWorld.clone();
|
||||
parent.matrixWorld.identity();
|
||||
if (!rotation || typeof rotation === 'number') {
|
||||
const o = new THREE.Object3D();
|
||||
o.position.copy(state.current.position);
|
||||
|
||||
// Thanks https://x.com/N8Programs !
|
||||
const vertices = parent.geometry.attributes.position.array;
|
||||
if (parent.geometry.attributes.normal === undefined) parent.geometry.computeVertexNormals();
|
||||
const normal = parent.geometry.attributes.normal.array;
|
||||
let distance = Infinity;
|
||||
let closestNormal = new THREE.Vector3();
|
||||
const ox = o.position.x;
|
||||
const oy = o.position.y;
|
||||
const oz = o.position.z;
|
||||
const vLength = vertices.length;
|
||||
let chosenIdx = -1;
|
||||
for (let i = 0; i < vLength; i += 3) {
|
||||
const x = vertices[i];
|
||||
const y = vertices[i + 1];
|
||||
const z = vertices[i + 2];
|
||||
const xDiff = x - ox;
|
||||
const yDiff = y - oy;
|
||||
const zDiff = z - oz;
|
||||
const distSquared = xDiff * xDiff + yDiff * yDiff + zDiff * zDiff;
|
||||
if (distSquared < distance) {
|
||||
distance = distSquared;
|
||||
chosenIdx = i;
|
||||
}
|
||||
}
|
||||
closestNormal.fromArray(normal, chosenIdx);
|
||||
|
||||
// Get vector tangent to normal
|
||||
o.lookAt(o.position.clone().add(closestNormal));
|
||||
o.rotateZ(Math.PI);
|
||||
o.rotateY(Math.PI);
|
||||
if (typeof rotation === 'number') o.rotateZ(rotation);
|
||||
applyProps(state.current, {
|
||||
rotation: o.rotation
|
||||
});
|
||||
} else {
|
||||
applyProps(state.current, {
|
||||
rotation
|
||||
});
|
||||
}
|
||||
if (helper.current) {
|
||||
applyProps(helper.current, state.current);
|
||||
}
|
||||
target.geometry = new DecalGeometry(parent, state.current.position, state.current.rotation, state.current.scale);
|
||||
// Reset parents matix-world
|
||||
parent.matrixWorld = matrixWorld;
|
||||
return () => {
|
||||
target.geometry.dispose();
|
||||
};
|
||||
}
|
||||
}, [mesh, ...vecToArray(position), ...vecToArray(scale), ...vecToArray(rotation)]);
|
||||
React.useLayoutEffect(() => {
|
||||
if (helper.current) {
|
||||
// Prevent the helpers from blocking rays
|
||||
helper.current.traverse(child => child.raycast = () => null);
|
||||
}
|
||||
}, [debug]);
|
||||
return /*#__PURE__*/React.createElement("mesh", _extends({
|
||||
ref: ref,
|
||||
"material-transparent": true,
|
||||
"material-polygonOffset": true,
|
||||
"material-polygonOffsetFactor": polygonOffsetFactor,
|
||||
"material-depthTest": depthTest,
|
||||
"material-map": map
|
||||
}, props), children, debug && /*#__PURE__*/React.createElement("mesh", {
|
||||
ref: helper
|
||||
}, /*#__PURE__*/React.createElement("boxGeometry", null), /*#__PURE__*/React.createElement("meshNormalMaterial", {
|
||||
wireframe: true
|
||||
}), /*#__PURE__*/React.createElement("axesHelper", null)));
|
||||
});
|
||||
|
||||
export { Decal };
|
||||
Reference in New Issue
Block a user