forked from sagnik/Project_Velocity
37713 lines
1.3 MiB
37713 lines
1.3 MiB
import {
|
|
Events
|
|
} from "./chunk-OAEA5FZL.js";
|
|
import {
|
|
addAfterEffect,
|
|
addEffect,
|
|
applyProps,
|
|
clear,
|
|
context,
|
|
createPortal,
|
|
extend,
|
|
preload,
|
|
require_with_selector,
|
|
suspend,
|
|
useFrame,
|
|
useInstanceHandle,
|
|
useLoader,
|
|
useThree
|
|
} from "./chunk-KOYBCGV3.js";
|
|
import {
|
|
ArcballControls,
|
|
AsciiEffect,
|
|
DRACOLoader,
|
|
DecalGeometry,
|
|
DeviceOrientationControls,
|
|
EXRLoader,
|
|
EffectComposer,
|
|
FBXLoader,
|
|
FirstPersonControls,
|
|
Flow,
|
|
FlyControls,
|
|
FontLoader,
|
|
FullScreenQuad,
|
|
GLTFLoader,
|
|
GammaCorrectionShader,
|
|
GroundProjectedEnv,
|
|
HorizontalBlurShader,
|
|
KTX2Loader,
|
|
Line2,
|
|
LineGeometry,
|
|
LineMaterial,
|
|
LineSegments2,
|
|
LineSegmentsGeometry,
|
|
MapControls,
|
|
MarchingCubes,
|
|
MeshSurfaceSampler,
|
|
MeshoptDecoder,
|
|
OrbitControls,
|
|
PointerLockControls,
|
|
RGBELoader,
|
|
RenderPass,
|
|
SVGLoader,
|
|
SelectionBox,
|
|
ShaderPass,
|
|
SimplexNoise,
|
|
SkeletonUtils,
|
|
Sky,
|
|
TextGeometry,
|
|
TrackballControls,
|
|
TransformControls,
|
|
VerticalBlurShader,
|
|
mergeVertices,
|
|
toCreasedNormals
|
|
} from "./chunk-TGAC7IAX.js";
|
|
import {
|
|
AdditiveBlending,
|
|
AlwaysStencilFunc,
|
|
AnimationMixer,
|
|
AudioListener,
|
|
AudioLoader,
|
|
BackSide,
|
|
BatchedMesh,
|
|
Box3,
|
|
BoxGeometry,
|
|
BufferAttribute,
|
|
BufferGeometry,
|
|
ByteType,
|
|
Camera,
|
|
CameraHelper,
|
|
CanvasTexture,
|
|
CatmullRomCurve3,
|
|
ClampToEdgeWrapping,
|
|
Color,
|
|
CubeCamera,
|
|
CubeReflectionMapping,
|
|
CubeTextureLoader,
|
|
CubicBezierCurve3,
|
|
CurvePath,
|
|
CustomBlending,
|
|
CylinderGeometry,
|
|
DataTexture,
|
|
DefaultLoadingManager,
|
|
DepthFormat,
|
|
DepthTexture,
|
|
DoubleSide,
|
|
DynamicDrawUsage,
|
|
EdgesGeometry,
|
|
EqualStencilFunc,
|
|
EquirectangularReflectionMapping,
|
|
Euler,
|
|
EventDispatcher,
|
|
FileLoader,
|
|
Float32BufferAttribute,
|
|
FloatType,
|
|
FrontSide,
|
|
Frustum,
|
|
Group,
|
|
HalfFloatType,
|
|
InstancedBufferAttribute,
|
|
InstancedBufferGeometry,
|
|
InstancedMesh,
|
|
IntType,
|
|
KeepStencilOp,
|
|
Line3,
|
|
LinearFilter,
|
|
LinearMipMapLinearFilter,
|
|
LinearMipmapLinearFilter,
|
|
LinearSRGBColorSpace,
|
|
Loader,
|
|
LoadingManager,
|
|
Material,
|
|
MathUtils,
|
|
Matrix3,
|
|
Matrix4,
|
|
Mesh,
|
|
MeshBasicMaterial,
|
|
MeshDepthMaterial,
|
|
MeshDistanceMaterial,
|
|
MeshLambertMaterial,
|
|
MeshNormalMaterial,
|
|
MeshPhysicalMaterial,
|
|
MeshStandardMaterial,
|
|
NearestFilter,
|
|
NoBlending,
|
|
NoToneMapping,
|
|
NormalBlending,
|
|
NotEqualStencilFunc,
|
|
Object3D,
|
|
OneFactor,
|
|
OrthographicCamera,
|
|
PerspectiveCamera,
|
|
Plane,
|
|
PlaneGeometry,
|
|
PointsMaterial,
|
|
QuadraticBezierCurve3,
|
|
Quaternion,
|
|
REVISION,
|
|
RGBADepthPacking,
|
|
RGBAFormat,
|
|
RGBAIntegerFormat,
|
|
RGFormat,
|
|
RGIntegerFormat,
|
|
Ray,
|
|
Raycaster,
|
|
RedFormat,
|
|
RedIntegerFormat,
|
|
RepeatWrapping,
|
|
ReplaceStencilOp,
|
|
SRGBColorSpace,
|
|
Scene,
|
|
ShaderChunk,
|
|
ShaderMaterial,
|
|
Shape,
|
|
ShortType,
|
|
SkinnedMesh,
|
|
Sphere,
|
|
SphereGeometry,
|
|
Spherical,
|
|
SrcAlphaFactor,
|
|
Texture,
|
|
TextureLoader,
|
|
Triangle,
|
|
UVMapping,
|
|
Uniform,
|
|
UniformsLib,
|
|
UniformsUtils,
|
|
UnsignedByteType,
|
|
UnsignedIntType,
|
|
UnsignedShortType,
|
|
Vector2,
|
|
Vector3,
|
|
Vector4,
|
|
VideoTexture,
|
|
WebGLCubeRenderTarget,
|
|
WebGLRenderTarget,
|
|
WebGLRenderer
|
|
} from "./chunk-L3Z576C2.js";
|
|
import {
|
|
require_client
|
|
} from "./chunk-6MXH2QM6.js";
|
|
import "./chunk-GUQHL3N7.js";
|
|
import {
|
|
_extends
|
|
} from "./chunk-EQCCHGRT.js";
|
|
import {
|
|
subscribeWithSelector
|
|
} from "./chunk-O4L7C4YS.js";
|
|
import {
|
|
create
|
|
} from "./chunk-7GZ4CI6Q.js";
|
|
import "./chunk-NJ4V5H3P.js";
|
|
import "./chunk-TXHHHGR3.js";
|
|
import "./chunk-YF4B4G2L.js";
|
|
import "./chunk-2YVA4HRZ.js";
|
|
import {
|
|
require_react
|
|
} from "./chunk-WUR7D6NS.js";
|
|
import {
|
|
__commonJS,
|
|
__toESM
|
|
} from "./chunk-G3PMV62Z.js";
|
|
|
|
// node_modules/stats.js/build/stats.min.js
|
|
var require_stats_min = __commonJS({
|
|
"node_modules/stats.js/build/stats.min.js"(exports, module) {
|
|
(function(f2, e2) {
|
|
"object" === typeof exports && "undefined" !== typeof module ? module.exports = e2() : "function" === typeof define && define.amd ? define(e2) : f2.Stats = e2();
|
|
})(exports, function() {
|
|
var f2 = function() {
|
|
function e2(a6) {
|
|
c2.appendChild(a6.dom);
|
|
return a6;
|
|
}
|
|
function u(a6) {
|
|
for (var d2 = 0; d2 < c2.children.length; d2++) c2.children[d2].style.display = d2 === a6 ? "block" : "none";
|
|
l2 = a6;
|
|
}
|
|
var l2 = 0, c2 = document.createElement("div");
|
|
c2.style.cssText = "position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000";
|
|
c2.addEventListener("click", function(a6) {
|
|
a6.preventDefault();
|
|
u(++l2 % c2.children.length);
|
|
}, false);
|
|
var k = (performance || Date).now(), g = k, a5 = 0, r2 = e2(new f2.Panel("FPS", "#0ff", "#002")), h = e2(new f2.Panel("MS", "#0f0", "#020"));
|
|
if (self.performance && self.performance.memory) var t2 = e2(new f2.Panel("MB", "#f08", "#201"));
|
|
u(0);
|
|
return { REVISION: 16, dom: c2, addPanel: e2, showPanel: u, begin: function() {
|
|
k = (performance || Date).now();
|
|
}, end: function() {
|
|
a5++;
|
|
var c5 = (performance || Date).now();
|
|
h.update(c5 - k, 200);
|
|
if (c5 > g + 1e3 && (r2.update(1e3 * a5 / (c5 - g), 100), g = c5, a5 = 0, t2)) {
|
|
var d2 = performance.memory;
|
|
t2.update(d2.usedJSHeapSize / 1048576, d2.jsHeapSizeLimit / 1048576);
|
|
}
|
|
return c5;
|
|
}, update: function() {
|
|
k = this.end();
|
|
}, domElement: c2, setMode: u };
|
|
};
|
|
f2.Panel = function(e2, f3, l2) {
|
|
var c2 = Infinity, k = 0, g = Math.round, a5 = g(window.devicePixelRatio || 1), r2 = 80 * a5, h = 48 * a5, t2 = 3 * a5, v5 = 2 * a5, d2 = 3 * a5, m = 15 * a5, n2 = 74 * a5, p2 = 30 * a5, q = document.createElement("canvas");
|
|
q.width = r2;
|
|
q.height = h;
|
|
q.style.cssText = "width:80px;height:48px";
|
|
var b = q.getContext("2d");
|
|
b.font = "bold " + 9 * a5 + "px Helvetica,Arial,sans-serif";
|
|
b.textBaseline = "top";
|
|
b.fillStyle = l2;
|
|
b.fillRect(0, 0, r2, h);
|
|
b.fillStyle = f3;
|
|
b.fillText(e2, t2, v5);
|
|
b.fillRect(d2, m, n2, p2);
|
|
b.fillStyle = l2;
|
|
b.globalAlpha = 0.9;
|
|
b.fillRect(d2, m, n2, p2);
|
|
return { dom: q, update: function(h2, w) {
|
|
c2 = Math.min(c2, h2);
|
|
k = Math.max(k, h2);
|
|
b.fillStyle = l2;
|
|
b.globalAlpha = 1;
|
|
b.fillRect(0, 0, r2, m);
|
|
b.fillStyle = f3;
|
|
b.fillText(g(h2) + " " + e2 + " (" + g(c2) + "-" + g(k) + ")", t2, v5);
|
|
b.drawImage(q, d2 + a5, m, n2 - a5, p2, d2, m, n2 - a5, p2);
|
|
b.fillRect(d2 + n2 - a5, m, a5, p2);
|
|
b.fillStyle = l2;
|
|
b.globalAlpha = 0.9;
|
|
b.fillRect(d2 + n2 - a5, m, a5, g((1 - h2 / w) * p2));
|
|
} };
|
|
};
|
|
return f2;
|
|
});
|
|
}
|
|
});
|
|
|
|
// node_modules/@react-three/drei/web/Html.js
|
|
var React = __toESM(require_react());
|
|
var ReactDOM = __toESM(require_client());
|
|
var v1 = new Vector3();
|
|
var v2 = new Vector3();
|
|
var v3 = new Vector3();
|
|
var v4 = new Vector2();
|
|
function defaultCalculatePosition(el, camera, size) {
|
|
const objectPos = v1.setFromMatrixPosition(el.matrixWorld);
|
|
objectPos.project(camera);
|
|
const widthHalf = size.width / 2;
|
|
const heightHalf = size.height / 2;
|
|
return [objectPos.x * widthHalf + widthHalf, -(objectPos.y * heightHalf) + heightHalf];
|
|
}
|
|
function isObjectBehindCamera(el, camera) {
|
|
const objectPos = v1.setFromMatrixPosition(el.matrixWorld);
|
|
const cameraPos = v2.setFromMatrixPosition(camera.matrixWorld);
|
|
const deltaCamObj = objectPos.sub(cameraPos);
|
|
const camDir = camera.getWorldDirection(v3);
|
|
return deltaCamObj.angleTo(camDir) > Math.PI / 2;
|
|
}
|
|
function isObjectVisible(el, camera, raycaster, occlude) {
|
|
const elPos = v1.setFromMatrixPosition(el.matrixWorld);
|
|
const screenPos = elPos.clone();
|
|
screenPos.project(camera);
|
|
v4.set(screenPos.x, screenPos.y);
|
|
raycaster.setFromCamera(v4, camera);
|
|
const intersects = raycaster.intersectObjects(occlude, true);
|
|
if (intersects.length) {
|
|
const intersectionDistance = intersects[0].distance;
|
|
const pointDistance = elPos.distanceTo(raycaster.ray.origin);
|
|
return pointDistance < intersectionDistance;
|
|
}
|
|
return true;
|
|
}
|
|
function objectScale(el, camera) {
|
|
if (camera instanceof OrthographicCamera) {
|
|
return camera.zoom;
|
|
} else if (camera instanceof PerspectiveCamera) {
|
|
const objectPos = v1.setFromMatrixPosition(el.matrixWorld);
|
|
const cameraPos = v2.setFromMatrixPosition(camera.matrixWorld);
|
|
const vFOV = camera.fov * Math.PI / 180;
|
|
const dist = objectPos.distanceTo(cameraPos);
|
|
const scaleFOV = 2 * Math.tan(vFOV / 2) * dist;
|
|
return 1 / scaleFOV;
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
function objectZIndex(el, camera, zIndexRange) {
|
|
if (camera instanceof PerspectiveCamera || camera instanceof OrthographicCamera) {
|
|
const objectPos = v1.setFromMatrixPosition(el.matrixWorld);
|
|
const cameraPos = v2.setFromMatrixPosition(camera.matrixWorld);
|
|
const dist = objectPos.distanceTo(cameraPos);
|
|
const A = (zIndexRange[1] - zIndexRange[0]) / (camera.far - camera.near);
|
|
const B = zIndexRange[1] - A * camera.far;
|
|
return Math.round(A * dist + B);
|
|
}
|
|
return void 0;
|
|
}
|
|
var epsilon = (value) => Math.abs(value) < 1e-10 ? 0 : value;
|
|
function getCSSMatrix(matrix4, multipliers, prepend = "") {
|
|
let matrix3d = "matrix3d(";
|
|
for (let i3 = 0; i3 !== 16; i3++) {
|
|
matrix3d += epsilon(multipliers[i3] * matrix4.elements[i3]) + (i3 !== 15 ? "," : ")");
|
|
}
|
|
return prepend + matrix3d;
|
|
}
|
|
var getCameraCSSMatrix = /* @__PURE__ */ ((multipliers) => {
|
|
return (matrix4) => getCSSMatrix(matrix4, multipliers);
|
|
})([1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1]);
|
|
var getObjectCSSMatrix = /* @__PURE__ */ ((scaleMultipliers) => {
|
|
return (matrix4, factor) => getCSSMatrix(matrix4, scaleMultipliers(factor), "translate(-50%,-50%)");
|
|
})((f2) => [1 / f2, 1 / f2, 1 / f2, 1, -1 / f2, -1 / f2, -1 / f2, -1, 1 / f2, 1 / f2, 1 / f2, 1, 1, 1, 1, 1]);
|
|
function isRefObject(ref) {
|
|
return ref && typeof ref === "object" && "current" in ref;
|
|
}
|
|
var Html = React.forwardRef(({
|
|
children,
|
|
eps: eps2 = 1e-3,
|
|
style,
|
|
className,
|
|
prepend,
|
|
center: center2,
|
|
fullscreen,
|
|
portal,
|
|
distanceFactor,
|
|
sprite = false,
|
|
transform = false,
|
|
occlude,
|
|
onOcclude,
|
|
castShadow,
|
|
receiveShadow,
|
|
material,
|
|
geometry: geometry3,
|
|
zIndexRange = [16777271, 0],
|
|
calculatePosition = defaultCalculatePosition,
|
|
as = "div",
|
|
wrapperClass,
|
|
pointerEvents = "auto",
|
|
...props
|
|
}, ref) => {
|
|
const {
|
|
gl,
|
|
camera,
|
|
scene,
|
|
size,
|
|
raycaster,
|
|
events,
|
|
viewport
|
|
} = useThree();
|
|
const [el] = React.useState(() => document.createElement(as));
|
|
const root = React.useRef(null);
|
|
const group = React.useRef(null);
|
|
const oldZoom = React.useRef(0);
|
|
const oldPosition = React.useRef([0, 0]);
|
|
const transformOuterRef = React.useRef(null);
|
|
const transformInnerRef = React.useRef(null);
|
|
const target2 = (portal == null ? void 0 : portal.current) || events.connected || gl.domElement.parentNode;
|
|
const occlusionMeshRef = React.useRef(null);
|
|
const isMeshSizeSet = React.useRef(false);
|
|
const isRayCastOcclusion = React.useMemo(() => {
|
|
return occlude && occlude !== "blending" || Array.isArray(occlude) && occlude.length && isRefObject(occlude[0]);
|
|
}, [occlude]);
|
|
React.useLayoutEffect(() => {
|
|
const el2 = gl.domElement;
|
|
if (occlude && occlude === "blending") {
|
|
el2.style.zIndex = `${Math.floor(zIndexRange[0] / 2)}`;
|
|
el2.style.position = "absolute";
|
|
el2.style.pointerEvents = "none";
|
|
} else {
|
|
el2.style.zIndex = null;
|
|
el2.style.position = null;
|
|
el2.style.pointerEvents = null;
|
|
}
|
|
}, [occlude]);
|
|
React.useLayoutEffect(() => {
|
|
if (group.current) {
|
|
const currentRoot = root.current = ReactDOM.createRoot(el);
|
|
scene.updateMatrixWorld();
|
|
if (transform) {
|
|
el.style.cssText = `position:absolute;top:0;left:0;pointer-events:none;overflow:hidden;`;
|
|
} else {
|
|
const vec = calculatePosition(group.current, camera, size);
|
|
el.style.cssText = `position:absolute;top:0;left:0;transform:translate3d(${vec[0]}px,${vec[1]}px,0);transform-origin:0 0;`;
|
|
}
|
|
if (target2) {
|
|
if (prepend) target2.prepend(el);
|
|
else target2.appendChild(el);
|
|
}
|
|
return () => {
|
|
if (target2) target2.removeChild(el);
|
|
currentRoot.unmount();
|
|
};
|
|
}
|
|
}, [target2, transform]);
|
|
React.useLayoutEffect(() => {
|
|
if (wrapperClass) el.className = wrapperClass;
|
|
}, [wrapperClass]);
|
|
const styles2 = React.useMemo(() => {
|
|
if (transform) {
|
|
return {
|
|
position: "absolute",
|
|
top: 0,
|
|
left: 0,
|
|
width: size.width,
|
|
height: size.height,
|
|
transformStyle: "preserve-3d",
|
|
pointerEvents: "none"
|
|
};
|
|
} else {
|
|
return {
|
|
position: "absolute",
|
|
transform: center2 ? "translate3d(-50%,-50%,0)" : "none",
|
|
...fullscreen && {
|
|
top: -size.height / 2,
|
|
left: -size.width / 2,
|
|
width: size.width,
|
|
height: size.height
|
|
},
|
|
...style
|
|
};
|
|
}
|
|
}, [style, center2, fullscreen, size, transform]);
|
|
const transformInnerStyles = React.useMemo(() => ({
|
|
position: "absolute",
|
|
pointerEvents
|
|
}), [pointerEvents]);
|
|
React.useLayoutEffect(() => {
|
|
isMeshSizeSet.current = false;
|
|
if (transform) {
|
|
var _root$current;
|
|
(_root$current = root.current) == null || _root$current.render(React.createElement("div", {
|
|
ref: transformOuterRef,
|
|
style: styles2
|
|
}, React.createElement("div", {
|
|
ref: transformInnerRef,
|
|
style: transformInnerStyles
|
|
}, React.createElement("div", {
|
|
ref,
|
|
className,
|
|
style,
|
|
children
|
|
}))));
|
|
} else {
|
|
var _root$current2;
|
|
(_root$current2 = root.current) == null || _root$current2.render(React.createElement("div", {
|
|
ref,
|
|
style: styles2,
|
|
className,
|
|
children
|
|
}));
|
|
}
|
|
});
|
|
const visible = React.useRef(true);
|
|
useFrame((gl2) => {
|
|
if (group.current) {
|
|
camera.updateMatrixWorld();
|
|
group.current.updateWorldMatrix(true, false);
|
|
const vec = transform ? oldPosition.current : calculatePosition(group.current, camera, size);
|
|
if (transform || Math.abs(oldZoom.current - camera.zoom) > eps2 || Math.abs(oldPosition.current[0] - vec[0]) > eps2 || Math.abs(oldPosition.current[1] - vec[1]) > eps2) {
|
|
const isBehindCamera = isObjectBehindCamera(group.current, camera);
|
|
let raytraceTarget = false;
|
|
if (isRayCastOcclusion) {
|
|
if (Array.isArray(occlude)) {
|
|
raytraceTarget = occlude.map((item) => item.current);
|
|
} else if (occlude !== "blending") {
|
|
raytraceTarget = [scene];
|
|
}
|
|
}
|
|
const previouslyVisible = visible.current;
|
|
if (raytraceTarget) {
|
|
const isvisible = isObjectVisible(group.current, camera, raycaster, raytraceTarget);
|
|
visible.current = isvisible && !isBehindCamera;
|
|
} else {
|
|
visible.current = !isBehindCamera;
|
|
}
|
|
if (previouslyVisible !== visible.current) {
|
|
if (onOcclude) onOcclude(!visible.current);
|
|
else el.style.display = visible.current ? "block" : "none";
|
|
}
|
|
const halfRange = Math.floor(zIndexRange[0] / 2);
|
|
const zRange = occlude ? isRayCastOcclusion ? [zIndexRange[0], halfRange] : [halfRange - 1, 0] : zIndexRange;
|
|
el.style.zIndex = `${objectZIndex(group.current, camera, zRange)}`;
|
|
if (transform) {
|
|
const [widthHalf, heightHalf] = [size.width / 2, size.height / 2];
|
|
const fov = camera.projectionMatrix.elements[5] * heightHalf;
|
|
const {
|
|
isOrthographicCamera: isOrthographicCamera3,
|
|
top,
|
|
left,
|
|
bottom,
|
|
right
|
|
} = camera;
|
|
const cameraMatrix = getCameraCSSMatrix(camera.matrixWorldInverse);
|
|
const cameraTransform = isOrthographicCamera3 ? `scale(${fov})translate(${epsilon(-(right + left) / 2)}px,${epsilon((top + bottom) / 2)}px)` : `translateZ(${fov}px)`;
|
|
let matrix4 = group.current.matrixWorld;
|
|
if (sprite) {
|
|
matrix4 = camera.matrixWorldInverse.clone().transpose().copyPosition(matrix4).scale(group.current.scale);
|
|
matrix4.elements[3] = matrix4.elements[7] = matrix4.elements[11] = 0;
|
|
matrix4.elements[15] = 1;
|
|
}
|
|
el.style.width = size.width + "px";
|
|
el.style.height = size.height + "px";
|
|
el.style.perspective = isOrthographicCamera3 ? "" : `${fov}px`;
|
|
if (transformOuterRef.current && transformInnerRef.current) {
|
|
transformOuterRef.current.style.transform = `${cameraTransform}${cameraMatrix}translate(${widthHalf}px,${heightHalf}px)`;
|
|
transformInnerRef.current.style.transform = getObjectCSSMatrix(matrix4, 1 / ((distanceFactor || 10) / 400));
|
|
}
|
|
} else {
|
|
const scale5 = distanceFactor === void 0 ? 1 : objectScale(group.current, camera) * distanceFactor;
|
|
el.style.transform = `translate3d(${vec[0]}px,${vec[1]}px,0) scale(${scale5})`;
|
|
}
|
|
oldPosition.current = vec;
|
|
oldZoom.current = camera.zoom;
|
|
}
|
|
}
|
|
if (!isRayCastOcclusion && occlusionMeshRef.current && !isMeshSizeSet.current) {
|
|
if (transform) {
|
|
if (transformOuterRef.current) {
|
|
const el2 = transformOuterRef.current.children[0];
|
|
if (el2 != null && el2.clientWidth && el2 != null && el2.clientHeight) {
|
|
const {
|
|
isOrthographicCamera: isOrthographicCamera3
|
|
} = camera;
|
|
if (isOrthographicCamera3 || geometry3) {
|
|
if (props.scale) {
|
|
if (!Array.isArray(props.scale)) {
|
|
occlusionMeshRef.current.scale.setScalar(1 / props.scale);
|
|
} else if (props.scale instanceof Vector3) {
|
|
occlusionMeshRef.current.scale.copy(props.scale.clone().divideScalar(1));
|
|
} else {
|
|
occlusionMeshRef.current.scale.set(1 / props.scale[0], 1 / props.scale[1], 1 / props.scale[2]);
|
|
}
|
|
}
|
|
} else {
|
|
const ratio = (distanceFactor || 10) / 400;
|
|
const w = el2.clientWidth * ratio;
|
|
const h = el2.clientHeight * ratio;
|
|
occlusionMeshRef.current.scale.set(w, h, 1);
|
|
}
|
|
isMeshSizeSet.current = true;
|
|
}
|
|
}
|
|
} else {
|
|
const ele = el.children[0];
|
|
if (ele != null && ele.clientWidth && ele != null && ele.clientHeight) {
|
|
const ratio = 1 / viewport.factor;
|
|
const w = ele.clientWidth * ratio;
|
|
const h = ele.clientHeight * ratio;
|
|
occlusionMeshRef.current.scale.set(w, h, 1);
|
|
isMeshSizeSet.current = true;
|
|
}
|
|
occlusionMeshRef.current.lookAt(gl2.camera.position);
|
|
}
|
|
}
|
|
});
|
|
const shaders = React.useMemo(() => ({
|
|
vertexShader: !transform ? (
|
|
/* glsl */
|
|
`
|
|
/*
|
|
This shader is from the THREE's SpriteMaterial.
|
|
We need to turn the backing plane into a Sprite
|
|
(make it always face the camera) if "transfrom"
|
|
is false.
|
|
*/
|
|
#include <common>
|
|
|
|
void main() {
|
|
vec2 center = vec2(0., 1.);
|
|
float rotation = 0.0;
|
|
|
|
// This is somewhat arbitrary, but it seems to work well
|
|
// Need to figure out how to derive this dynamically if it even matters
|
|
float size = 0.03;
|
|
|
|
vec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );
|
|
vec2 scale;
|
|
scale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );
|
|
scale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );
|
|
|
|
bool isPerspective = isPerspectiveMatrix( projectionMatrix );
|
|
if ( isPerspective ) scale *= - mvPosition.z;
|
|
|
|
vec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale * size;
|
|
vec2 rotatedPosition;
|
|
rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;
|
|
rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;
|
|
mvPosition.xy += rotatedPosition;
|
|
|
|
gl_Position = projectionMatrix * mvPosition;
|
|
}
|
|
`
|
|
) : void 0,
|
|
fragmentShader: (
|
|
/* glsl */
|
|
`
|
|
void main() {
|
|
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
|
|
}
|
|
`
|
|
)
|
|
}), [transform]);
|
|
return React.createElement("group", _extends({}, props, {
|
|
ref: group
|
|
}), occlude && !isRayCastOcclusion && React.createElement("mesh", {
|
|
castShadow,
|
|
receiveShadow,
|
|
ref: occlusionMeshRef
|
|
}, geometry3 || React.createElement("planeGeometry", null), material || React.createElement("shaderMaterial", {
|
|
side: DoubleSide,
|
|
vertexShader: shaders.vertexShader,
|
|
fragmentShader: shaders.fragmentShader
|
|
})));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/web/CycleRaycast.js
|
|
var React2 = __toESM(require_react());
|
|
function CycleRaycast({
|
|
onChanged,
|
|
portal,
|
|
preventDefault = true,
|
|
scroll = true,
|
|
keyCode = 9
|
|
}) {
|
|
const cycle = React2.useRef(0);
|
|
const setEvents = useThree((state) => state.setEvents);
|
|
const get = useThree((state) => state.get);
|
|
const gl = useThree((state) => state.gl);
|
|
React2.useEffect(() => {
|
|
var _portal$current;
|
|
let hits = [];
|
|
let lastEvent = void 0;
|
|
const prev = get().events.filter;
|
|
const target2 = (_portal$current = portal == null ? void 0 : portal.current) !== null && _portal$current !== void 0 ? _portal$current : gl.domElement.parentNode;
|
|
const renderStatus = () => target2 && onChanged && onChanged(hits, Math.round(cycle.current) % hits.length);
|
|
setEvents({
|
|
filter: (intersections, state) => {
|
|
let clone = [...intersections];
|
|
if (clone.length !== hits.length || !hits.every((hit) => clone.map((e2) => e2.object.uuid).includes(hit.object.uuid))) {
|
|
cycle.current = 0;
|
|
hits = clone;
|
|
renderStatus();
|
|
}
|
|
if (prev) clone = prev(clone, state);
|
|
for (let i3 = 0; i3 < Math.round(cycle.current) % clone.length; i3++) {
|
|
const first2 = clone.shift();
|
|
clone = [...clone, first2];
|
|
}
|
|
return clone;
|
|
}
|
|
});
|
|
const refresh = (fn) => {
|
|
var _get$events$handlers, _get$events$handlers2;
|
|
cycle.current = fn(cycle.current);
|
|
(_get$events$handlers = get().events.handlers) == null || _get$events$handlers.onPointerCancel(void 0);
|
|
(_get$events$handlers2 = get().events.handlers) == null || _get$events$handlers2.onPointerMove(lastEvent);
|
|
renderStatus();
|
|
};
|
|
const tabEvent = (event) => {
|
|
if ((event.keyCode || event.which) === keyCode) {
|
|
if (preventDefault) event.preventDefault();
|
|
if (hits.length > 1) refresh((current) => current + 1);
|
|
}
|
|
};
|
|
const wheelEvent = (event) => {
|
|
if (preventDefault) event.preventDefault();
|
|
let delta = 0;
|
|
if (!event) event = window.event;
|
|
if (event.wheelDelta) delta = event.wheelDelta / 120;
|
|
else if (event.detail) delta = -event.detail / 3;
|
|
if (hits.length > 1) refresh((current) => Math.abs(current - delta));
|
|
};
|
|
const moveEvent = (event) => lastEvent = event;
|
|
document.addEventListener("pointermove", moveEvent, {
|
|
passive: true
|
|
});
|
|
if (scroll) document.addEventListener("wheel", wheelEvent);
|
|
if (keyCode !== void 0) document.addEventListener("keydown", tabEvent);
|
|
return () => {
|
|
setEvents({
|
|
filter: prev
|
|
});
|
|
if (keyCode !== void 0) document.removeEventListener("keydown", tabEvent);
|
|
if (scroll) document.removeEventListener("wheel", wheelEvent);
|
|
document.removeEventListener("pointermove", moveEvent);
|
|
};
|
|
}, [gl, get, setEvents, preventDefault, scroll, keyCode]);
|
|
return null;
|
|
}
|
|
|
|
// node_modules/@react-three/drei/web/useCursor.js
|
|
var React3 = __toESM(require_react());
|
|
function useCursor(hovered, onPointerOver = "pointer", onPointerOut = "auto", container = document.body) {
|
|
React3.useEffect(() => {
|
|
if (hovered) {
|
|
container.style.cursor = onPointerOver;
|
|
return () => void (container.style.cursor = onPointerOut);
|
|
}
|
|
}, [hovered]);
|
|
}
|
|
|
|
// node_modules/@react-three/drei/web/Loader.js
|
|
var React5 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/core/Progress.js
|
|
var React4 = __toESM(require_react());
|
|
var saveLastTotalLoaded = 0;
|
|
var useProgress = create((set) => {
|
|
DefaultLoadingManager.onStart = (item, loaded, total) => {
|
|
set({
|
|
active: true,
|
|
item,
|
|
loaded,
|
|
total,
|
|
progress: (loaded - saveLastTotalLoaded) / (total - saveLastTotalLoaded) * 100
|
|
});
|
|
};
|
|
DefaultLoadingManager.onLoad = () => {
|
|
set({
|
|
active: false
|
|
});
|
|
};
|
|
DefaultLoadingManager.onError = (item) => set((state) => ({
|
|
errors: [...state.errors, item]
|
|
}));
|
|
DefaultLoadingManager.onProgress = (item, loaded, total) => {
|
|
if (loaded === total) {
|
|
saveLastTotalLoaded = total;
|
|
}
|
|
set({
|
|
active: true,
|
|
item,
|
|
loaded,
|
|
total,
|
|
progress: (loaded - saveLastTotalLoaded) / (total - saveLastTotalLoaded) * 100 || 100
|
|
});
|
|
};
|
|
return {
|
|
errors: [],
|
|
active: false,
|
|
progress: 0,
|
|
item: "",
|
|
loaded: 0,
|
|
total: 0
|
|
};
|
|
});
|
|
function Progress({
|
|
children
|
|
}) {
|
|
const result = useProgress();
|
|
return React4.createElement(React4.Fragment, null, children == null ? void 0 : children(result));
|
|
}
|
|
|
|
// node_modules/@react-three/drei/web/Loader.js
|
|
var defaultDataInterpolation = (p2) => `Loading ${p2.toFixed(2)}%`;
|
|
function Loader2({
|
|
containerStyles,
|
|
innerStyles,
|
|
barStyles,
|
|
dataStyles,
|
|
dataInterpolation = defaultDataInterpolation,
|
|
initialState = (active) => active
|
|
}) {
|
|
const {
|
|
active,
|
|
progress
|
|
} = useProgress();
|
|
const progressRef = React5.useRef(0);
|
|
const rafRef = React5.useRef(0);
|
|
const progressSpanRef = React5.useRef(null);
|
|
const [shown, setShown] = React5.useState(initialState(active));
|
|
React5.useEffect(() => {
|
|
let t2;
|
|
if (active !== shown) t2 = setTimeout(() => setShown(active), 300);
|
|
return () => clearTimeout(t2);
|
|
}, [shown, active]);
|
|
const updateProgress = React5.useCallback(() => {
|
|
if (!progressSpanRef.current) return;
|
|
progressRef.current += (progress - progressRef.current) / 2;
|
|
if (progressRef.current > 0.95 * progress || progress === 100) progressRef.current = progress;
|
|
progressSpanRef.current.innerText = dataInterpolation(progressRef.current);
|
|
if (progressRef.current < progress) rafRef.current = requestAnimationFrame(updateProgress);
|
|
}, [dataInterpolation, progress]);
|
|
React5.useEffect(() => {
|
|
updateProgress();
|
|
return () => cancelAnimationFrame(rafRef.current);
|
|
}, [updateProgress]);
|
|
return shown ? React5.createElement("div", {
|
|
style: {
|
|
...styles.container,
|
|
opacity: active ? 1 : 0,
|
|
...containerStyles
|
|
}
|
|
}, React5.createElement("div", null, React5.createElement("div", {
|
|
style: {
|
|
...styles.inner,
|
|
...innerStyles
|
|
}
|
|
}, React5.createElement("div", {
|
|
style: {
|
|
...styles.bar,
|
|
transform: `scaleX(${progress / 100})`,
|
|
...barStyles
|
|
}
|
|
}), React5.createElement("span", {
|
|
ref: progressSpanRef,
|
|
style: {
|
|
...styles.data,
|
|
...dataStyles
|
|
}
|
|
})))) : null;
|
|
}
|
|
var styles = {
|
|
container: {
|
|
position: "absolute",
|
|
top: 0,
|
|
left: 0,
|
|
width: "100%",
|
|
height: "100%",
|
|
background: "#171717",
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
transition: "opacity 300ms ease",
|
|
zIndex: 1e3
|
|
},
|
|
inner: {
|
|
width: 100,
|
|
height: 3,
|
|
background: "#272727",
|
|
textAlign: "center"
|
|
},
|
|
bar: {
|
|
height: 3,
|
|
width: "100%",
|
|
background: "white",
|
|
transition: "transform 200ms",
|
|
transformOrigin: "left center"
|
|
},
|
|
data: {
|
|
display: "inline-block",
|
|
position: "relative",
|
|
fontVariantNumeric: "tabular-nums",
|
|
marginTop: "0.8em",
|
|
color: "#f0f0f0",
|
|
fontSize: "0.6em",
|
|
fontFamily: `-apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", "Helvetica Neue", Helvetica, Arial, Roboto, Ubuntu, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"`,
|
|
whiteSpace: "nowrap"
|
|
}
|
|
};
|
|
|
|
// node_modules/@react-three/drei/web/DragControls.js
|
|
var React7 = __toESM(require_react());
|
|
|
|
// node_modules/@use-gesture/core/dist/maths-0ab39ae9.esm.js
|
|
function clamp(v5, min, max) {
|
|
return Math.max(min, Math.min(v5, max));
|
|
}
|
|
var V = {
|
|
toVector(v5, fallback) {
|
|
if (v5 === void 0) v5 = fallback;
|
|
return Array.isArray(v5) ? v5 : [v5, v5];
|
|
},
|
|
add(v12, v22) {
|
|
return [v12[0] + v22[0], v12[1] + v22[1]];
|
|
},
|
|
sub(v12, v22) {
|
|
return [v12[0] - v22[0], v12[1] - v22[1]];
|
|
},
|
|
addTo(v12, v22) {
|
|
v12[0] += v22[0];
|
|
v12[1] += v22[1];
|
|
},
|
|
subTo(v12, v22) {
|
|
v12[0] -= v22[0];
|
|
v12[1] -= v22[1];
|
|
}
|
|
};
|
|
function rubberband(distance3, dimension, constant) {
|
|
if (dimension === 0 || Math.abs(dimension) === Infinity) return Math.pow(distance3, constant * 5);
|
|
return distance3 * dimension * constant / (dimension + constant * distance3);
|
|
}
|
|
function rubberbandIfOutOfBounds(position2, min, max, constant = 0.15) {
|
|
if (constant === 0) return clamp(position2, min, max);
|
|
if (position2 < min) return -rubberband(min - position2, max - min, constant) + min;
|
|
if (position2 > max) return +rubberband(position2 - max, max - min, constant) + max;
|
|
return position2;
|
|
}
|
|
function computeRubberband(bounds, [Vx, Vy], [Rx, Ry]) {
|
|
const [[X0, X1], [Y0, Y1]] = bounds;
|
|
return [rubberbandIfOutOfBounds(Vx, X0, X1, Rx), rubberbandIfOutOfBounds(Vy, Y0, Y1, Ry)];
|
|
}
|
|
|
|
// node_modules/@use-gesture/core/dist/actions-fe213e88.esm.js
|
|
function _toPrimitive(input, hint) {
|
|
if (typeof input !== "object" || input === null) return input;
|
|
var prim = input[Symbol.toPrimitive];
|
|
if (prim !== void 0) {
|
|
var res = prim.call(input, hint || "default");
|
|
if (typeof res !== "object") return res;
|
|
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
}
|
|
return (hint === "string" ? String : Number)(input);
|
|
}
|
|
function _toPropertyKey(arg) {
|
|
var key = _toPrimitive(arg, "string");
|
|
return typeof key === "symbol" ? key : String(key);
|
|
}
|
|
function _defineProperty(obj, key, value) {
|
|
key = _toPropertyKey(key);
|
|
if (key in obj) {
|
|
Object.defineProperty(obj, key, {
|
|
value,
|
|
enumerable: true,
|
|
configurable: true,
|
|
writable: true
|
|
});
|
|
} else {
|
|
obj[key] = value;
|
|
}
|
|
return obj;
|
|
}
|
|
function ownKeys(e2, r2) {
|
|
var t2 = Object.keys(e2);
|
|
if (Object.getOwnPropertySymbols) {
|
|
var o2 = Object.getOwnPropertySymbols(e2);
|
|
r2 && (o2 = o2.filter(function(r3) {
|
|
return Object.getOwnPropertyDescriptor(e2, r3).enumerable;
|
|
})), t2.push.apply(t2, o2);
|
|
}
|
|
return t2;
|
|
}
|
|
function _objectSpread2(e2) {
|
|
for (var r2 = 1; r2 < arguments.length; r2++) {
|
|
var t2 = null != arguments[r2] ? arguments[r2] : {};
|
|
r2 % 2 ? ownKeys(Object(t2), true).forEach(function(r3) {
|
|
_defineProperty(e2, r3, t2[r3]);
|
|
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e2, Object.getOwnPropertyDescriptors(t2)) : ownKeys(Object(t2)).forEach(function(r3) {
|
|
Object.defineProperty(e2, r3, Object.getOwnPropertyDescriptor(t2, r3));
|
|
});
|
|
}
|
|
return e2;
|
|
}
|
|
var EVENT_TYPE_MAP = {
|
|
pointer: {
|
|
start: "down",
|
|
change: "move",
|
|
end: "up"
|
|
},
|
|
mouse: {
|
|
start: "down",
|
|
change: "move",
|
|
end: "up"
|
|
},
|
|
touch: {
|
|
start: "start",
|
|
change: "move",
|
|
end: "end"
|
|
},
|
|
gesture: {
|
|
start: "start",
|
|
change: "change",
|
|
end: "end"
|
|
}
|
|
};
|
|
function capitalize(string) {
|
|
if (!string) return "";
|
|
return string[0].toUpperCase() + string.slice(1);
|
|
}
|
|
var actionsWithoutCaptureSupported = ["enter", "leave"];
|
|
function hasCapture(capture = false, actionKey) {
|
|
return capture && !actionsWithoutCaptureSupported.includes(actionKey);
|
|
}
|
|
function toHandlerProp(device, action = "", capture = false) {
|
|
const deviceProps = EVENT_TYPE_MAP[device];
|
|
const actionKey = deviceProps ? deviceProps[action] || action : action;
|
|
return "on" + capitalize(device) + capitalize(actionKey) + (hasCapture(capture, actionKey) ? "Capture" : "");
|
|
}
|
|
var pointerCaptureEvents = ["gotpointercapture", "lostpointercapture"];
|
|
function parseProp(prop) {
|
|
let eventKey = prop.substring(2).toLowerCase();
|
|
const passive = !!~eventKey.indexOf("passive");
|
|
if (passive) eventKey = eventKey.replace("passive", "");
|
|
const captureKey = pointerCaptureEvents.includes(eventKey) ? "capturecapture" : "capture";
|
|
const capture = !!~eventKey.indexOf(captureKey);
|
|
if (capture) eventKey = eventKey.replace("capture", "");
|
|
return {
|
|
device: eventKey,
|
|
capture,
|
|
passive
|
|
};
|
|
}
|
|
function toDomEventType(device, action = "") {
|
|
const deviceProps = EVENT_TYPE_MAP[device];
|
|
const actionKey = deviceProps ? deviceProps[action] || action : action;
|
|
return device + actionKey;
|
|
}
|
|
function isTouch(event) {
|
|
return "touches" in event;
|
|
}
|
|
function getPointerType(event) {
|
|
if (isTouch(event)) return "touch";
|
|
if ("pointerType" in event) return event.pointerType;
|
|
return "mouse";
|
|
}
|
|
function getCurrentTargetTouchList(event) {
|
|
return Array.from(event.touches).filter((e2) => {
|
|
var _event$currentTarget, _event$currentTarget$;
|
|
return e2.target === event.currentTarget || ((_event$currentTarget = event.currentTarget) === null || _event$currentTarget === void 0 || (_event$currentTarget$ = _event$currentTarget.contains) === null || _event$currentTarget$ === void 0 ? void 0 : _event$currentTarget$.call(_event$currentTarget, e2.target));
|
|
});
|
|
}
|
|
function getTouchList(event) {
|
|
return event.type === "touchend" || event.type === "touchcancel" ? event.changedTouches : event.targetTouches;
|
|
}
|
|
function getValueEvent(event) {
|
|
return isTouch(event) ? getTouchList(event)[0] : event;
|
|
}
|
|
function distanceAngle(P1, P2) {
|
|
try {
|
|
const dx = P2.clientX - P1.clientX;
|
|
const dy = P2.clientY - P1.clientY;
|
|
const cx = (P2.clientX + P1.clientX) / 2;
|
|
const cy = (P2.clientY + P1.clientY) / 2;
|
|
const distance3 = Math.hypot(dx, dy);
|
|
const angle = -(Math.atan2(dx, dy) * 180) / Math.PI;
|
|
const origin2 = [cx, cy];
|
|
return {
|
|
angle,
|
|
distance: distance3,
|
|
origin: origin2
|
|
};
|
|
} catch (_unused) {
|
|
}
|
|
return null;
|
|
}
|
|
function touchIds(event) {
|
|
return getCurrentTargetTouchList(event).map((touch) => touch.identifier);
|
|
}
|
|
function touchDistanceAngle(event, ids) {
|
|
const [P1, P2] = Array.from(event.touches).filter((touch) => ids.includes(touch.identifier));
|
|
return distanceAngle(P1, P2);
|
|
}
|
|
function pointerId(event) {
|
|
const valueEvent = getValueEvent(event);
|
|
return isTouch(event) ? valueEvent.identifier : valueEvent.pointerId;
|
|
}
|
|
function pointerValues(event) {
|
|
const valueEvent = getValueEvent(event);
|
|
return [valueEvent.clientX, valueEvent.clientY];
|
|
}
|
|
var LINE_HEIGHT = 40;
|
|
var PAGE_HEIGHT = 800;
|
|
function wheelValues(event) {
|
|
let {
|
|
deltaX,
|
|
deltaY,
|
|
deltaMode
|
|
} = event;
|
|
if (deltaMode === 1) {
|
|
deltaX *= LINE_HEIGHT;
|
|
deltaY *= LINE_HEIGHT;
|
|
} else if (deltaMode === 2) {
|
|
deltaX *= PAGE_HEIGHT;
|
|
deltaY *= PAGE_HEIGHT;
|
|
}
|
|
return [deltaX, deltaY];
|
|
}
|
|
function scrollValues(event) {
|
|
var _ref, _ref2;
|
|
const {
|
|
scrollX,
|
|
scrollY,
|
|
scrollLeft,
|
|
scrollTop
|
|
} = event.currentTarget;
|
|
return [(_ref = scrollX !== null && scrollX !== void 0 ? scrollX : scrollLeft) !== null && _ref !== void 0 ? _ref : 0, (_ref2 = scrollY !== null && scrollY !== void 0 ? scrollY : scrollTop) !== null && _ref2 !== void 0 ? _ref2 : 0];
|
|
}
|
|
function getEventDetails(event) {
|
|
const payload = {};
|
|
if ("buttons" in event) payload.buttons = event.buttons;
|
|
if ("shiftKey" in event) {
|
|
const {
|
|
shiftKey,
|
|
altKey,
|
|
metaKey,
|
|
ctrlKey
|
|
} = event;
|
|
Object.assign(payload, {
|
|
shiftKey,
|
|
altKey,
|
|
metaKey,
|
|
ctrlKey
|
|
});
|
|
}
|
|
return payload;
|
|
}
|
|
function call(v5, ...args) {
|
|
if (typeof v5 === "function") {
|
|
return v5(...args);
|
|
} else {
|
|
return v5;
|
|
}
|
|
}
|
|
function noop() {
|
|
}
|
|
function chain(...fns) {
|
|
if (fns.length === 0) return noop;
|
|
if (fns.length === 1) return fns[0];
|
|
return function() {
|
|
let result;
|
|
for (const fn of fns) {
|
|
result = fn.apply(this, arguments) || result;
|
|
}
|
|
return result;
|
|
};
|
|
}
|
|
function assignDefault(value, fallback) {
|
|
return Object.assign({}, fallback, value || {});
|
|
}
|
|
var BEFORE_LAST_KINEMATICS_DELAY = 32;
|
|
var Engine = class {
|
|
constructor(ctrl, args, key) {
|
|
this.ctrl = ctrl;
|
|
this.args = args;
|
|
this.key = key;
|
|
if (!this.state) {
|
|
this.state = {};
|
|
this.computeValues([0, 0]);
|
|
this.computeInitial();
|
|
if (this.init) this.init();
|
|
this.reset();
|
|
}
|
|
}
|
|
get state() {
|
|
return this.ctrl.state[this.key];
|
|
}
|
|
set state(state) {
|
|
this.ctrl.state[this.key] = state;
|
|
}
|
|
get shared() {
|
|
return this.ctrl.state.shared;
|
|
}
|
|
get eventStore() {
|
|
return this.ctrl.gestureEventStores[this.key];
|
|
}
|
|
get timeoutStore() {
|
|
return this.ctrl.gestureTimeoutStores[this.key];
|
|
}
|
|
get config() {
|
|
return this.ctrl.config[this.key];
|
|
}
|
|
get sharedConfig() {
|
|
return this.ctrl.config.shared;
|
|
}
|
|
get handler() {
|
|
return this.ctrl.handlers[this.key];
|
|
}
|
|
reset() {
|
|
const {
|
|
state,
|
|
shared,
|
|
ingKey,
|
|
args
|
|
} = this;
|
|
shared[ingKey] = state._active = state.active = state._blocked = state._force = false;
|
|
state._step = [false, false];
|
|
state.intentional = false;
|
|
state._movement = [0, 0];
|
|
state._distance = [0, 0];
|
|
state._direction = [0, 0];
|
|
state._delta = [0, 0];
|
|
state._bounds = [[-Infinity, Infinity], [-Infinity, Infinity]];
|
|
state.args = args;
|
|
state.axis = void 0;
|
|
state.memo = void 0;
|
|
state.elapsedTime = state.timeDelta = 0;
|
|
state.direction = [0, 0];
|
|
state.distance = [0, 0];
|
|
state.overflow = [0, 0];
|
|
state._movementBound = [false, false];
|
|
state.velocity = [0, 0];
|
|
state.movement = [0, 0];
|
|
state.delta = [0, 0];
|
|
state.timeStamp = 0;
|
|
}
|
|
start(event) {
|
|
const state = this.state;
|
|
const config = this.config;
|
|
if (!state._active) {
|
|
this.reset();
|
|
this.computeInitial();
|
|
state._active = true;
|
|
state.target = event.target;
|
|
state.currentTarget = event.currentTarget;
|
|
state.lastOffset = config.from ? call(config.from, state) : state.offset;
|
|
state.offset = state.lastOffset;
|
|
state.startTime = state.timeStamp = event.timeStamp;
|
|
}
|
|
}
|
|
computeValues(values) {
|
|
const state = this.state;
|
|
state._values = values;
|
|
state.values = this.config.transform(values);
|
|
}
|
|
computeInitial() {
|
|
const state = this.state;
|
|
state._initial = state._values;
|
|
state.initial = state.values;
|
|
}
|
|
compute(event) {
|
|
const {
|
|
state,
|
|
config,
|
|
shared
|
|
} = this;
|
|
state.args = this.args;
|
|
let dt = 0;
|
|
if (event) {
|
|
state.event = event;
|
|
if (config.preventDefault && event.cancelable) state.event.preventDefault();
|
|
state.type = event.type;
|
|
shared.touches = this.ctrl.pointerIds.size || this.ctrl.touchIds.size;
|
|
shared.locked = !!document.pointerLockElement;
|
|
Object.assign(shared, getEventDetails(event));
|
|
shared.down = shared.pressed = shared.buttons % 2 === 1 || shared.touches > 0;
|
|
dt = event.timeStamp - state.timeStamp;
|
|
state.timeStamp = event.timeStamp;
|
|
state.elapsedTime = state.timeStamp - state.startTime;
|
|
}
|
|
if (state._active) {
|
|
const _absoluteDelta = state._delta.map(Math.abs);
|
|
V.addTo(state._distance, _absoluteDelta);
|
|
}
|
|
if (this.axisIntent) this.axisIntent(event);
|
|
const [_m0, _m12] = state._movement;
|
|
const [t0, t1] = config.threshold;
|
|
const {
|
|
_step,
|
|
values
|
|
} = state;
|
|
if (config.hasCustomTransform) {
|
|
if (_step[0] === false) _step[0] = Math.abs(_m0) >= t0 && values[0];
|
|
if (_step[1] === false) _step[1] = Math.abs(_m12) >= t1 && values[1];
|
|
} else {
|
|
if (_step[0] === false) _step[0] = Math.abs(_m0) >= t0 && Math.sign(_m0) * t0;
|
|
if (_step[1] === false) _step[1] = Math.abs(_m12) >= t1 && Math.sign(_m12) * t1;
|
|
}
|
|
state.intentional = _step[0] !== false || _step[1] !== false;
|
|
if (!state.intentional) return;
|
|
const movement = [0, 0];
|
|
if (config.hasCustomTransform) {
|
|
const [v0, v12] = values;
|
|
movement[0] = _step[0] !== false ? v0 - _step[0] : 0;
|
|
movement[1] = _step[1] !== false ? v12 - _step[1] : 0;
|
|
} else {
|
|
movement[0] = _step[0] !== false ? _m0 - _step[0] : 0;
|
|
movement[1] = _step[1] !== false ? _m12 - _step[1] : 0;
|
|
}
|
|
if (this.restrictToAxis && !state._blocked) this.restrictToAxis(movement);
|
|
const previousOffset = state.offset;
|
|
const gestureIsActive = state._active && !state._blocked || state.active;
|
|
if (gestureIsActive) {
|
|
state.first = state._active && !state.active;
|
|
state.last = !state._active && state.active;
|
|
state.active = shared[this.ingKey] = state._active;
|
|
if (event) {
|
|
if (state.first) {
|
|
if ("bounds" in config) state._bounds = call(config.bounds, state);
|
|
if (this.setup) this.setup();
|
|
}
|
|
state.movement = movement;
|
|
this.computeOffset();
|
|
}
|
|
}
|
|
const [ox, oy] = state.offset;
|
|
const [[x0, x1], [y0, y1]] = state._bounds;
|
|
state.overflow = [ox < x0 ? -1 : ox > x1 ? 1 : 0, oy < y0 ? -1 : oy > y1 ? 1 : 0];
|
|
state._movementBound[0] = state.overflow[0] ? state._movementBound[0] === false ? state._movement[0] : state._movementBound[0] : false;
|
|
state._movementBound[1] = state.overflow[1] ? state._movementBound[1] === false ? state._movement[1] : state._movementBound[1] : false;
|
|
const rubberband2 = state._active ? config.rubberband || [0, 0] : [0, 0];
|
|
state.offset = computeRubberband(state._bounds, state.offset, rubberband2);
|
|
state.delta = V.sub(state.offset, previousOffset);
|
|
this.computeMovement();
|
|
if (gestureIsActive && (!state.last || dt > BEFORE_LAST_KINEMATICS_DELAY)) {
|
|
state.delta = V.sub(state.offset, previousOffset);
|
|
const absoluteDelta = state.delta.map(Math.abs);
|
|
V.addTo(state.distance, absoluteDelta);
|
|
state.direction = state.delta.map(Math.sign);
|
|
state._direction = state._delta.map(Math.sign);
|
|
if (!state.first && dt > 0) {
|
|
state.velocity = [absoluteDelta[0] / dt, absoluteDelta[1] / dt];
|
|
state.timeDelta = dt;
|
|
}
|
|
}
|
|
}
|
|
emit() {
|
|
const state = this.state;
|
|
const shared = this.shared;
|
|
const config = this.config;
|
|
if (!state._active) this.clean();
|
|
if ((state._blocked || !state.intentional) && !state._force && !config.triggerAllEvents) return;
|
|
const memo = this.handler(_objectSpread2(_objectSpread2(_objectSpread2({}, shared), state), {}, {
|
|
[this.aliasKey]: state.values
|
|
}));
|
|
if (memo !== void 0) state.memo = memo;
|
|
}
|
|
clean() {
|
|
this.eventStore.clean();
|
|
this.timeoutStore.clean();
|
|
}
|
|
};
|
|
function selectAxis([dx, dy], threshold) {
|
|
const absDx = Math.abs(dx);
|
|
const absDy = Math.abs(dy);
|
|
if (absDx > absDy && absDx > threshold) {
|
|
return "x";
|
|
}
|
|
if (absDy > absDx && absDy > threshold) {
|
|
return "y";
|
|
}
|
|
return void 0;
|
|
}
|
|
var CoordinatesEngine = class extends Engine {
|
|
constructor(...args) {
|
|
super(...args);
|
|
_defineProperty(this, "aliasKey", "xy");
|
|
}
|
|
reset() {
|
|
super.reset();
|
|
this.state.axis = void 0;
|
|
}
|
|
init() {
|
|
this.state.offset = [0, 0];
|
|
this.state.lastOffset = [0, 0];
|
|
}
|
|
computeOffset() {
|
|
this.state.offset = V.add(this.state.lastOffset, this.state.movement);
|
|
}
|
|
computeMovement() {
|
|
this.state.movement = V.sub(this.state.offset, this.state.lastOffset);
|
|
}
|
|
axisIntent(event) {
|
|
const state = this.state;
|
|
const config = this.config;
|
|
if (!state.axis && event) {
|
|
const threshold = typeof config.axisThreshold === "object" ? config.axisThreshold[getPointerType(event)] : config.axisThreshold;
|
|
state.axis = selectAxis(state._movement, threshold);
|
|
}
|
|
state._blocked = (config.lockDirection || !!config.axis) && !state.axis || !!config.axis && config.axis !== state.axis;
|
|
}
|
|
restrictToAxis(v5) {
|
|
if (this.config.axis || this.config.lockDirection) {
|
|
switch (this.state.axis) {
|
|
case "x":
|
|
v5[1] = 0;
|
|
break;
|
|
case "y":
|
|
v5[0] = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var identity = (v5) => v5;
|
|
var DEFAULT_RUBBERBAND = 0.15;
|
|
var commonConfigResolver = {
|
|
enabled(value = true) {
|
|
return value;
|
|
},
|
|
eventOptions(value, _k, config) {
|
|
return _objectSpread2(_objectSpread2({}, config.shared.eventOptions), value);
|
|
},
|
|
preventDefault(value = false) {
|
|
return value;
|
|
},
|
|
triggerAllEvents(value = false) {
|
|
return value;
|
|
},
|
|
rubberband(value = 0) {
|
|
switch (value) {
|
|
case true:
|
|
return [DEFAULT_RUBBERBAND, DEFAULT_RUBBERBAND];
|
|
case false:
|
|
return [0, 0];
|
|
default:
|
|
return V.toVector(value);
|
|
}
|
|
},
|
|
from(value) {
|
|
if (typeof value === "function") return value;
|
|
if (value != null) return V.toVector(value);
|
|
},
|
|
transform(value, _k, config) {
|
|
const transform = value || config.shared.transform;
|
|
this.hasCustomTransform = !!transform;
|
|
if (true) {
|
|
const originalTransform = transform || identity;
|
|
return (v5) => {
|
|
const r2 = originalTransform(v5);
|
|
if (!isFinite(r2[0]) || !isFinite(r2[1])) {
|
|
console.warn(`[@use-gesture]: config.transform() must produce a valid result, but it was: [${r2[0]},${[1]}]`);
|
|
}
|
|
return r2;
|
|
};
|
|
}
|
|
return transform || identity;
|
|
},
|
|
threshold(value) {
|
|
return V.toVector(value, 0);
|
|
}
|
|
};
|
|
if (true) {
|
|
Object.assign(commonConfigResolver, {
|
|
domTarget(value) {
|
|
if (value !== void 0) {
|
|
throw Error(`[@use-gesture]: \`domTarget\` option has been renamed to \`target\`.`);
|
|
}
|
|
return NaN;
|
|
},
|
|
lockDirection(value) {
|
|
if (value !== void 0) {
|
|
throw Error(`[@use-gesture]: \`lockDirection\` option has been merged with \`axis\`. Use it as in \`{ axis: 'lock' }\``);
|
|
}
|
|
return NaN;
|
|
},
|
|
initial(value) {
|
|
if (value !== void 0) {
|
|
throw Error(`[@use-gesture]: \`initial\` option has been renamed to \`from\`.`);
|
|
}
|
|
return NaN;
|
|
}
|
|
});
|
|
}
|
|
var DEFAULT_AXIS_THRESHOLD = 0;
|
|
var coordinatesConfigResolver = _objectSpread2(_objectSpread2({}, commonConfigResolver), {}, {
|
|
axis(_v, _k, {
|
|
axis
|
|
}) {
|
|
this.lockDirection = axis === "lock";
|
|
if (!this.lockDirection) return axis;
|
|
},
|
|
axisThreshold(value = DEFAULT_AXIS_THRESHOLD) {
|
|
return value;
|
|
},
|
|
bounds(value = {}) {
|
|
if (typeof value === "function") {
|
|
return (state) => coordinatesConfigResolver.bounds(value(state));
|
|
}
|
|
if ("current" in value) {
|
|
return () => value.current;
|
|
}
|
|
if (typeof HTMLElement === "function" && value instanceof HTMLElement) {
|
|
return value;
|
|
}
|
|
const {
|
|
left = -Infinity,
|
|
right = Infinity,
|
|
top = -Infinity,
|
|
bottom = Infinity
|
|
} = value;
|
|
return [[left, right], [top, bottom]];
|
|
}
|
|
});
|
|
var KEYS_DELTA_MAP = {
|
|
ArrowRight: (displacement, factor = 1) => [displacement * factor, 0],
|
|
ArrowLeft: (displacement, factor = 1) => [-1 * displacement * factor, 0],
|
|
ArrowUp: (displacement, factor = 1) => [0, -1 * displacement * factor],
|
|
ArrowDown: (displacement, factor = 1) => [0, displacement * factor]
|
|
};
|
|
var DragEngine = class extends CoordinatesEngine {
|
|
constructor(...args) {
|
|
super(...args);
|
|
_defineProperty(this, "ingKey", "dragging");
|
|
}
|
|
reset() {
|
|
super.reset();
|
|
const state = this.state;
|
|
state._pointerId = void 0;
|
|
state._pointerActive = false;
|
|
state._keyboardActive = false;
|
|
state._preventScroll = false;
|
|
state._delayed = false;
|
|
state.swipe = [0, 0];
|
|
state.tap = false;
|
|
state.canceled = false;
|
|
state.cancel = this.cancel.bind(this);
|
|
}
|
|
setup() {
|
|
const state = this.state;
|
|
if (state._bounds instanceof HTMLElement) {
|
|
const boundRect = state._bounds.getBoundingClientRect();
|
|
const targetRect = state.currentTarget.getBoundingClientRect();
|
|
const _bounds = {
|
|
left: boundRect.left - targetRect.left + state.offset[0],
|
|
right: boundRect.right - targetRect.right + state.offset[0],
|
|
top: boundRect.top - targetRect.top + state.offset[1],
|
|
bottom: boundRect.bottom - targetRect.bottom + state.offset[1]
|
|
};
|
|
state._bounds = coordinatesConfigResolver.bounds(_bounds);
|
|
}
|
|
}
|
|
cancel() {
|
|
const state = this.state;
|
|
if (state.canceled) return;
|
|
state.canceled = true;
|
|
state._active = false;
|
|
setTimeout(() => {
|
|
this.compute();
|
|
this.emit();
|
|
}, 0);
|
|
}
|
|
setActive() {
|
|
this.state._active = this.state._pointerActive || this.state._keyboardActive;
|
|
}
|
|
clean() {
|
|
this.pointerClean();
|
|
this.state._pointerActive = false;
|
|
this.state._keyboardActive = false;
|
|
super.clean();
|
|
}
|
|
pointerDown(event) {
|
|
const config = this.config;
|
|
const state = this.state;
|
|
if (event.buttons != null && (Array.isArray(config.pointerButtons) ? !config.pointerButtons.includes(event.buttons) : config.pointerButtons !== -1 && config.pointerButtons !== event.buttons)) return;
|
|
const ctrlIds = this.ctrl.setEventIds(event);
|
|
if (config.pointerCapture) {
|
|
event.target.setPointerCapture(event.pointerId);
|
|
}
|
|
if (ctrlIds && ctrlIds.size > 1 && state._pointerActive) return;
|
|
this.start(event);
|
|
this.setupPointer(event);
|
|
state._pointerId = pointerId(event);
|
|
state._pointerActive = true;
|
|
this.computeValues(pointerValues(event));
|
|
this.computeInitial();
|
|
if (config.preventScrollAxis && getPointerType(event) !== "mouse") {
|
|
state._active = false;
|
|
this.setupScrollPrevention(event);
|
|
} else if (config.delay > 0) {
|
|
this.setupDelayTrigger(event);
|
|
if (config.triggerAllEvents) {
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
} else {
|
|
this.startPointerDrag(event);
|
|
}
|
|
}
|
|
startPointerDrag(event) {
|
|
const state = this.state;
|
|
state._active = true;
|
|
state._preventScroll = true;
|
|
state._delayed = false;
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
pointerMove(event) {
|
|
const state = this.state;
|
|
const config = this.config;
|
|
if (!state._pointerActive) return;
|
|
const id = pointerId(event);
|
|
if (state._pointerId !== void 0 && id !== state._pointerId) return;
|
|
const _values = pointerValues(event);
|
|
if (document.pointerLockElement === event.target) {
|
|
state._delta = [event.movementX, event.movementY];
|
|
} else {
|
|
state._delta = V.sub(_values, state._values);
|
|
this.computeValues(_values);
|
|
}
|
|
V.addTo(state._movement, state._delta);
|
|
this.compute(event);
|
|
if (state._delayed && state.intentional) {
|
|
this.timeoutStore.remove("dragDelay");
|
|
state.active = false;
|
|
this.startPointerDrag(event);
|
|
return;
|
|
}
|
|
if (config.preventScrollAxis && !state._preventScroll) {
|
|
if (state.axis) {
|
|
if (state.axis === config.preventScrollAxis || config.preventScrollAxis === "xy") {
|
|
state._active = false;
|
|
this.clean();
|
|
return;
|
|
} else {
|
|
this.timeoutStore.remove("startPointerDrag");
|
|
this.startPointerDrag(event);
|
|
return;
|
|
}
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
this.emit();
|
|
}
|
|
pointerUp(event) {
|
|
this.ctrl.setEventIds(event);
|
|
try {
|
|
if (this.config.pointerCapture && event.target.hasPointerCapture(event.pointerId)) {
|
|
;
|
|
event.target.releasePointerCapture(event.pointerId);
|
|
}
|
|
} catch (_unused) {
|
|
if (true) {
|
|
console.warn(`[@use-gesture]: If you see this message, it's likely that you're using an outdated version of \`@react-three/fiber\`.
|
|
|
|
Please upgrade to the latest version.`);
|
|
}
|
|
}
|
|
const state = this.state;
|
|
const config = this.config;
|
|
if (!state._active || !state._pointerActive) return;
|
|
const id = pointerId(event);
|
|
if (state._pointerId !== void 0 && id !== state._pointerId) return;
|
|
this.state._pointerActive = false;
|
|
this.setActive();
|
|
this.compute(event);
|
|
const [dx, dy] = state._distance;
|
|
state.tap = dx <= config.tapsThreshold && dy <= config.tapsThreshold;
|
|
if (state.tap && config.filterTaps) {
|
|
state._force = true;
|
|
} else {
|
|
const [_dx, _dy] = state._delta;
|
|
const [_mx, _my] = state._movement;
|
|
const [svx, svy] = config.swipe.velocity;
|
|
const [sx, sy] = config.swipe.distance;
|
|
const sdt = config.swipe.duration;
|
|
if (state.elapsedTime < sdt) {
|
|
const _vx = Math.abs(_dx / state.timeDelta);
|
|
const _vy = Math.abs(_dy / state.timeDelta);
|
|
if (_vx > svx && Math.abs(_mx) > sx) state.swipe[0] = Math.sign(_dx);
|
|
if (_vy > svy && Math.abs(_my) > sy) state.swipe[1] = Math.sign(_dy);
|
|
}
|
|
}
|
|
this.emit();
|
|
}
|
|
pointerClick(event) {
|
|
if (!this.state.tap && event.detail > 0) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
}
|
|
}
|
|
setupPointer(event) {
|
|
const config = this.config;
|
|
const device = config.device;
|
|
if (true) {
|
|
try {
|
|
if (device === "pointer" && config.preventScrollDelay === void 0) {
|
|
const currentTarget = "uv" in event ? event.sourceEvent.currentTarget : event.currentTarget;
|
|
const style = window.getComputedStyle(currentTarget);
|
|
if (style.touchAction === "auto") {
|
|
console.warn(`[@use-gesture]: The drag target has its \`touch-action\` style property set to \`auto\`. It is recommended to add \`touch-action: 'none'\` so that the drag gesture behaves correctly on touch-enabled devices. For more information read this: https://use-gesture.netlify.app/docs/extras/#touch-action.
|
|
|
|
This message will only show in development mode. It won't appear in production. If this is intended, you can ignore it.`, currentTarget);
|
|
}
|
|
}
|
|
} catch (_unused2) {
|
|
}
|
|
}
|
|
if (config.pointerLock) {
|
|
event.currentTarget.requestPointerLock();
|
|
}
|
|
if (!config.pointerCapture) {
|
|
this.eventStore.add(this.sharedConfig.window, device, "change", this.pointerMove.bind(this));
|
|
this.eventStore.add(this.sharedConfig.window, device, "end", this.pointerUp.bind(this));
|
|
this.eventStore.add(this.sharedConfig.window, device, "cancel", this.pointerUp.bind(this));
|
|
}
|
|
}
|
|
pointerClean() {
|
|
if (this.config.pointerLock && document.pointerLockElement === this.state.currentTarget) {
|
|
document.exitPointerLock();
|
|
}
|
|
}
|
|
preventScroll(event) {
|
|
if (this.state._preventScroll && event.cancelable) {
|
|
event.preventDefault();
|
|
}
|
|
}
|
|
setupScrollPrevention(event) {
|
|
this.state._preventScroll = false;
|
|
persistEvent(event);
|
|
const remove = this.eventStore.add(this.sharedConfig.window, "touch", "change", this.preventScroll.bind(this), {
|
|
passive: false
|
|
});
|
|
this.eventStore.add(this.sharedConfig.window, "touch", "end", remove);
|
|
this.eventStore.add(this.sharedConfig.window, "touch", "cancel", remove);
|
|
this.timeoutStore.add("startPointerDrag", this.startPointerDrag.bind(this), this.config.preventScrollDelay, event);
|
|
}
|
|
setupDelayTrigger(event) {
|
|
this.state._delayed = true;
|
|
this.timeoutStore.add("dragDelay", () => {
|
|
this.state._step = [0, 0];
|
|
this.startPointerDrag(event);
|
|
}, this.config.delay);
|
|
}
|
|
keyDown(event) {
|
|
const deltaFn = KEYS_DELTA_MAP[event.key];
|
|
if (deltaFn) {
|
|
const state = this.state;
|
|
const factor = event.shiftKey ? 10 : event.altKey ? 0.1 : 1;
|
|
this.start(event);
|
|
state._delta = deltaFn(this.config.keyboardDisplacement, factor);
|
|
state._keyboardActive = true;
|
|
V.addTo(state._movement, state._delta);
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
}
|
|
keyUp(event) {
|
|
if (!(event.key in KEYS_DELTA_MAP)) return;
|
|
this.state._keyboardActive = false;
|
|
this.setActive();
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
bind(bindFunction) {
|
|
const device = this.config.device;
|
|
bindFunction(device, "start", this.pointerDown.bind(this));
|
|
if (this.config.pointerCapture) {
|
|
bindFunction(device, "change", this.pointerMove.bind(this));
|
|
bindFunction(device, "end", this.pointerUp.bind(this));
|
|
bindFunction(device, "cancel", this.pointerUp.bind(this));
|
|
bindFunction("lostPointerCapture", "", this.pointerUp.bind(this));
|
|
}
|
|
if (this.config.keys) {
|
|
bindFunction("key", "down", this.keyDown.bind(this));
|
|
bindFunction("key", "up", this.keyUp.bind(this));
|
|
}
|
|
if (this.config.filterTaps) {
|
|
bindFunction("click", "", this.pointerClick.bind(this), {
|
|
capture: true,
|
|
passive: false
|
|
});
|
|
}
|
|
}
|
|
};
|
|
function persistEvent(event) {
|
|
"persist" in event && typeof event.persist === "function" && event.persist();
|
|
}
|
|
var isBrowser = typeof window !== "undefined" && window.document && window.document.createElement;
|
|
function supportsTouchEvents() {
|
|
return isBrowser && "ontouchstart" in window;
|
|
}
|
|
function isTouchScreen() {
|
|
return supportsTouchEvents() || isBrowser && window.navigator.maxTouchPoints > 1;
|
|
}
|
|
function supportsPointerEvents() {
|
|
return isBrowser && "onpointerdown" in window;
|
|
}
|
|
function supportsPointerLock() {
|
|
return isBrowser && "exitPointerLock" in window.document;
|
|
}
|
|
function supportsGestureEvents() {
|
|
try {
|
|
return "constructor" in GestureEvent;
|
|
} catch (e2) {
|
|
return false;
|
|
}
|
|
}
|
|
var SUPPORT = {
|
|
isBrowser,
|
|
gesture: supportsGestureEvents(),
|
|
touch: supportsTouchEvents(),
|
|
touchscreen: isTouchScreen(),
|
|
pointer: supportsPointerEvents(),
|
|
pointerLock: supportsPointerLock()
|
|
};
|
|
var DEFAULT_PREVENT_SCROLL_DELAY = 250;
|
|
var DEFAULT_DRAG_DELAY = 180;
|
|
var DEFAULT_SWIPE_VELOCITY = 0.5;
|
|
var DEFAULT_SWIPE_DISTANCE = 50;
|
|
var DEFAULT_SWIPE_DURATION = 250;
|
|
var DEFAULT_KEYBOARD_DISPLACEMENT = 10;
|
|
var DEFAULT_DRAG_AXIS_THRESHOLD = {
|
|
mouse: 0,
|
|
touch: 0,
|
|
pen: 8
|
|
};
|
|
var dragConfigResolver = _objectSpread2(_objectSpread2({}, coordinatesConfigResolver), {}, {
|
|
device(_v, _k, {
|
|
pointer: {
|
|
touch = false,
|
|
lock = false,
|
|
mouse = false
|
|
} = {}
|
|
}) {
|
|
this.pointerLock = lock && SUPPORT.pointerLock;
|
|
if (SUPPORT.touch && touch) return "touch";
|
|
if (this.pointerLock) return "mouse";
|
|
if (SUPPORT.pointer && !mouse) return "pointer";
|
|
if (SUPPORT.touch) return "touch";
|
|
return "mouse";
|
|
},
|
|
preventScrollAxis(value, _k, {
|
|
preventScroll
|
|
}) {
|
|
this.preventScrollDelay = typeof preventScroll === "number" ? preventScroll : preventScroll || preventScroll === void 0 && value ? DEFAULT_PREVENT_SCROLL_DELAY : void 0;
|
|
if (!SUPPORT.touchscreen || preventScroll === false) return void 0;
|
|
return value ? value : preventScroll !== void 0 ? "y" : void 0;
|
|
},
|
|
pointerCapture(_v, _k, {
|
|
pointer: {
|
|
capture = true,
|
|
buttons = 1,
|
|
keys = true
|
|
} = {}
|
|
}) {
|
|
this.pointerButtons = buttons;
|
|
this.keys = keys;
|
|
return !this.pointerLock && this.device === "pointer" && capture;
|
|
},
|
|
threshold(value, _k, {
|
|
filterTaps = false,
|
|
tapsThreshold = 3,
|
|
axis = void 0
|
|
}) {
|
|
const threshold = V.toVector(value, filterTaps ? tapsThreshold : axis ? 1 : 0);
|
|
this.filterTaps = filterTaps;
|
|
this.tapsThreshold = tapsThreshold;
|
|
return threshold;
|
|
},
|
|
swipe({
|
|
velocity = DEFAULT_SWIPE_VELOCITY,
|
|
distance: distance3 = DEFAULT_SWIPE_DISTANCE,
|
|
duration = DEFAULT_SWIPE_DURATION
|
|
} = {}) {
|
|
return {
|
|
velocity: this.transform(V.toVector(velocity)),
|
|
distance: this.transform(V.toVector(distance3)),
|
|
duration
|
|
};
|
|
},
|
|
delay(value = 0) {
|
|
switch (value) {
|
|
case true:
|
|
return DEFAULT_DRAG_DELAY;
|
|
case false:
|
|
return 0;
|
|
default:
|
|
return value;
|
|
}
|
|
},
|
|
axisThreshold(value) {
|
|
if (!value) return DEFAULT_DRAG_AXIS_THRESHOLD;
|
|
return _objectSpread2(_objectSpread2({}, DEFAULT_DRAG_AXIS_THRESHOLD), value);
|
|
},
|
|
keyboardDisplacement(value = DEFAULT_KEYBOARD_DISPLACEMENT) {
|
|
return value;
|
|
}
|
|
});
|
|
if (true) {
|
|
Object.assign(dragConfigResolver, {
|
|
useTouch(value) {
|
|
if (value !== void 0) {
|
|
throw Error(`[@use-gesture]: \`useTouch\` option has been renamed to \`pointer.touch\`. Use it as in \`{ pointer: { touch: true } }\`.`);
|
|
}
|
|
return NaN;
|
|
},
|
|
experimental_preventWindowScrollY(value) {
|
|
if (value !== void 0) {
|
|
throw Error(`[@use-gesture]: \`experimental_preventWindowScrollY\` option has been renamed to \`preventScroll\`.`);
|
|
}
|
|
return NaN;
|
|
},
|
|
swipeVelocity(value) {
|
|
if (value !== void 0) {
|
|
throw Error(`[@use-gesture]: \`swipeVelocity\` option has been renamed to \`swipe.velocity\`. Use it as in \`{ swipe: { velocity: 0.5 } }\`.`);
|
|
}
|
|
return NaN;
|
|
},
|
|
swipeDistance(value) {
|
|
if (value !== void 0) {
|
|
throw Error(`[@use-gesture]: \`swipeDistance\` option has been renamed to \`swipe.distance\`. Use it as in \`{ swipe: { distance: 50 } }\`.`);
|
|
}
|
|
return NaN;
|
|
},
|
|
swipeDuration(value) {
|
|
if (value !== void 0) {
|
|
throw Error(`[@use-gesture]: \`swipeDuration\` option has been renamed to \`swipe.duration\`. Use it as in \`{ swipe: { duration: 250 } }\`.`);
|
|
}
|
|
return NaN;
|
|
}
|
|
});
|
|
}
|
|
function clampStateInternalMovementToBounds(state) {
|
|
const [ox, oy] = state.overflow;
|
|
const [dx, dy] = state._delta;
|
|
const [dirx, diry] = state._direction;
|
|
if (ox < 0 && dx > 0 && dirx < 0 || ox > 0 && dx < 0 && dirx > 0) {
|
|
state._movement[0] = state._movementBound[0];
|
|
}
|
|
if (oy < 0 && dy > 0 && diry < 0 || oy > 0 && dy < 0 && diry > 0) {
|
|
state._movement[1] = state._movementBound[1];
|
|
}
|
|
}
|
|
var SCALE_ANGLE_RATIO_INTENT_DEG = 30;
|
|
var PINCH_WHEEL_RATIO = 100;
|
|
var PinchEngine = class extends Engine {
|
|
constructor(...args) {
|
|
super(...args);
|
|
_defineProperty(this, "ingKey", "pinching");
|
|
_defineProperty(this, "aliasKey", "da");
|
|
}
|
|
init() {
|
|
this.state.offset = [1, 0];
|
|
this.state.lastOffset = [1, 0];
|
|
this.state._pointerEvents = /* @__PURE__ */ new Map();
|
|
}
|
|
reset() {
|
|
super.reset();
|
|
const state = this.state;
|
|
state._touchIds = [];
|
|
state.canceled = false;
|
|
state.cancel = this.cancel.bind(this);
|
|
state.turns = 0;
|
|
}
|
|
computeOffset() {
|
|
const {
|
|
type,
|
|
movement,
|
|
lastOffset
|
|
} = this.state;
|
|
if (type === "wheel") {
|
|
this.state.offset = V.add(movement, lastOffset);
|
|
} else {
|
|
this.state.offset = [(1 + movement[0]) * lastOffset[0], movement[1] + lastOffset[1]];
|
|
}
|
|
}
|
|
computeMovement() {
|
|
const {
|
|
offset,
|
|
lastOffset
|
|
} = this.state;
|
|
this.state.movement = [offset[0] / lastOffset[0], offset[1] - lastOffset[1]];
|
|
}
|
|
axisIntent() {
|
|
const state = this.state;
|
|
const [_m0, _m12] = state._movement;
|
|
if (!state.axis) {
|
|
const axisMovementDifference = Math.abs(_m0) * SCALE_ANGLE_RATIO_INTENT_DEG - Math.abs(_m12);
|
|
if (axisMovementDifference < 0) state.axis = "angle";
|
|
else if (axisMovementDifference > 0) state.axis = "scale";
|
|
}
|
|
}
|
|
restrictToAxis(v5) {
|
|
if (this.config.lockDirection) {
|
|
if (this.state.axis === "scale") v5[1] = 0;
|
|
else if (this.state.axis === "angle") v5[0] = 0;
|
|
}
|
|
}
|
|
cancel() {
|
|
const state = this.state;
|
|
if (state.canceled) return;
|
|
setTimeout(() => {
|
|
state.canceled = true;
|
|
state._active = false;
|
|
this.compute();
|
|
this.emit();
|
|
}, 0);
|
|
}
|
|
touchStart(event) {
|
|
this.ctrl.setEventIds(event);
|
|
const state = this.state;
|
|
const ctrlTouchIds = this.ctrl.touchIds;
|
|
if (state._active) {
|
|
if (state._touchIds.every((id) => ctrlTouchIds.has(id))) return;
|
|
}
|
|
if (ctrlTouchIds.size < 2) return;
|
|
this.start(event);
|
|
state._touchIds = Array.from(ctrlTouchIds).slice(0, 2);
|
|
const payload = touchDistanceAngle(event, state._touchIds);
|
|
if (!payload) return;
|
|
this.pinchStart(event, payload);
|
|
}
|
|
pointerStart(event) {
|
|
if (event.buttons != null && event.buttons % 2 !== 1) return;
|
|
this.ctrl.setEventIds(event);
|
|
event.target.setPointerCapture(event.pointerId);
|
|
const state = this.state;
|
|
const _pointerEvents = state._pointerEvents;
|
|
const ctrlPointerIds = this.ctrl.pointerIds;
|
|
if (state._active) {
|
|
if (Array.from(_pointerEvents.keys()).every((id) => ctrlPointerIds.has(id))) return;
|
|
}
|
|
if (_pointerEvents.size < 2) {
|
|
_pointerEvents.set(event.pointerId, event);
|
|
}
|
|
if (state._pointerEvents.size < 2) return;
|
|
this.start(event);
|
|
const payload = distanceAngle(...Array.from(_pointerEvents.values()));
|
|
if (!payload) return;
|
|
this.pinchStart(event, payload);
|
|
}
|
|
pinchStart(event, payload) {
|
|
const state = this.state;
|
|
state.origin = payload.origin;
|
|
this.computeValues([payload.distance, payload.angle]);
|
|
this.computeInitial();
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
touchMove(event) {
|
|
if (!this.state._active) return;
|
|
const payload = touchDistanceAngle(event, this.state._touchIds);
|
|
if (!payload) return;
|
|
this.pinchMove(event, payload);
|
|
}
|
|
pointerMove(event) {
|
|
const _pointerEvents = this.state._pointerEvents;
|
|
if (_pointerEvents.has(event.pointerId)) {
|
|
_pointerEvents.set(event.pointerId, event);
|
|
}
|
|
if (!this.state._active) return;
|
|
const payload = distanceAngle(...Array.from(_pointerEvents.values()));
|
|
if (!payload) return;
|
|
this.pinchMove(event, payload);
|
|
}
|
|
pinchMove(event, payload) {
|
|
const state = this.state;
|
|
const prev_a = state._values[1];
|
|
const delta_a = payload.angle - prev_a;
|
|
let delta_turns = 0;
|
|
if (Math.abs(delta_a) > 270) delta_turns += Math.sign(delta_a);
|
|
this.computeValues([payload.distance, payload.angle - 360 * delta_turns]);
|
|
state.origin = payload.origin;
|
|
state.turns = delta_turns;
|
|
state._movement = [state._values[0] / state._initial[0] - 1, state._values[1] - state._initial[1]];
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
touchEnd(event) {
|
|
this.ctrl.setEventIds(event);
|
|
if (!this.state._active) return;
|
|
if (this.state._touchIds.some((id) => !this.ctrl.touchIds.has(id))) {
|
|
this.state._active = false;
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
}
|
|
pointerEnd(event) {
|
|
const state = this.state;
|
|
this.ctrl.setEventIds(event);
|
|
try {
|
|
event.target.releasePointerCapture(event.pointerId);
|
|
} catch (_unused) {
|
|
}
|
|
if (state._pointerEvents.has(event.pointerId)) {
|
|
state._pointerEvents.delete(event.pointerId);
|
|
}
|
|
if (!state._active) return;
|
|
if (state._pointerEvents.size < 2) {
|
|
state._active = false;
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
}
|
|
gestureStart(event) {
|
|
if (event.cancelable) event.preventDefault();
|
|
const state = this.state;
|
|
if (state._active) return;
|
|
this.start(event);
|
|
this.computeValues([event.scale, event.rotation]);
|
|
state.origin = [event.clientX, event.clientY];
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
gestureMove(event) {
|
|
if (event.cancelable) event.preventDefault();
|
|
if (!this.state._active) return;
|
|
const state = this.state;
|
|
this.computeValues([event.scale, event.rotation]);
|
|
state.origin = [event.clientX, event.clientY];
|
|
const _previousMovement = state._movement;
|
|
state._movement = [event.scale - 1, event.rotation];
|
|
state._delta = V.sub(state._movement, _previousMovement);
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
gestureEnd(event) {
|
|
if (!this.state._active) return;
|
|
this.state._active = false;
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
wheel(event) {
|
|
const modifierKey = this.config.modifierKey;
|
|
if (modifierKey && (Array.isArray(modifierKey) ? !modifierKey.find((k) => event[k]) : !event[modifierKey])) return;
|
|
if (!this.state._active) this.wheelStart(event);
|
|
else this.wheelChange(event);
|
|
this.timeoutStore.add("wheelEnd", this.wheelEnd.bind(this));
|
|
}
|
|
wheelStart(event) {
|
|
this.start(event);
|
|
this.wheelChange(event);
|
|
}
|
|
wheelChange(event) {
|
|
const isR3f = "uv" in event;
|
|
if (!isR3f) {
|
|
if (event.cancelable) {
|
|
event.preventDefault();
|
|
}
|
|
if (!event.defaultPrevented) {
|
|
console.warn(`[@use-gesture]: To properly support zoom on trackpads, try using the \`target\` option.
|
|
|
|
This message will only appear in development mode.`);
|
|
}
|
|
}
|
|
const state = this.state;
|
|
state._delta = [-wheelValues(event)[1] / PINCH_WHEEL_RATIO * state.offset[0], 0];
|
|
V.addTo(state._movement, state._delta);
|
|
clampStateInternalMovementToBounds(state);
|
|
this.state.origin = [event.clientX, event.clientY];
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
wheelEnd() {
|
|
if (!this.state._active) return;
|
|
this.state._active = false;
|
|
this.compute();
|
|
this.emit();
|
|
}
|
|
bind(bindFunction) {
|
|
const device = this.config.device;
|
|
if (!!device) {
|
|
bindFunction(device, "start", this[device + "Start"].bind(this));
|
|
bindFunction(device, "change", this[device + "Move"].bind(this));
|
|
bindFunction(device, "end", this[device + "End"].bind(this));
|
|
bindFunction(device, "cancel", this[device + "End"].bind(this));
|
|
bindFunction("lostPointerCapture", "", this[device + "End"].bind(this));
|
|
}
|
|
if (this.config.pinchOnWheel) {
|
|
bindFunction("wheel", "", this.wheel.bind(this), {
|
|
passive: false
|
|
});
|
|
}
|
|
}
|
|
};
|
|
var pinchConfigResolver = _objectSpread2(_objectSpread2({}, commonConfigResolver), {}, {
|
|
device(_v, _k, {
|
|
shared,
|
|
pointer: {
|
|
touch = false
|
|
} = {}
|
|
}) {
|
|
const sharedConfig = shared;
|
|
if (sharedConfig.target && !SUPPORT.touch && SUPPORT.gesture) return "gesture";
|
|
if (SUPPORT.touch && touch) return "touch";
|
|
if (SUPPORT.touchscreen) {
|
|
if (SUPPORT.pointer) return "pointer";
|
|
if (SUPPORT.touch) return "touch";
|
|
}
|
|
},
|
|
bounds(_v, _k, {
|
|
scaleBounds = {},
|
|
angleBounds = {}
|
|
}) {
|
|
const _scaleBounds = (state) => {
|
|
const D = assignDefault(call(scaleBounds, state), {
|
|
min: -Infinity,
|
|
max: Infinity
|
|
});
|
|
return [D.min, D.max];
|
|
};
|
|
const _angleBounds = (state) => {
|
|
const A = assignDefault(call(angleBounds, state), {
|
|
min: -Infinity,
|
|
max: Infinity
|
|
});
|
|
return [A.min, A.max];
|
|
};
|
|
if (typeof scaleBounds !== "function" && typeof angleBounds !== "function") return [_scaleBounds(), _angleBounds()];
|
|
return (state) => [_scaleBounds(state), _angleBounds(state)];
|
|
},
|
|
threshold(value, _k, config) {
|
|
this.lockDirection = config.axis === "lock";
|
|
const threshold = V.toVector(value, this.lockDirection ? [0.1, 3] : 0);
|
|
return threshold;
|
|
},
|
|
modifierKey(value) {
|
|
if (value === void 0) return "ctrlKey";
|
|
return value;
|
|
},
|
|
pinchOnWheel(value = true) {
|
|
return value;
|
|
}
|
|
});
|
|
var MoveEngine = class extends CoordinatesEngine {
|
|
constructor(...args) {
|
|
super(...args);
|
|
_defineProperty(this, "ingKey", "moving");
|
|
}
|
|
move(event) {
|
|
if (this.config.mouseOnly && event.pointerType !== "mouse") return;
|
|
if (!this.state._active) this.moveStart(event);
|
|
else this.moveChange(event);
|
|
this.timeoutStore.add("moveEnd", this.moveEnd.bind(this));
|
|
}
|
|
moveStart(event) {
|
|
this.start(event);
|
|
this.computeValues(pointerValues(event));
|
|
this.compute(event);
|
|
this.computeInitial();
|
|
this.emit();
|
|
}
|
|
moveChange(event) {
|
|
if (!this.state._active) return;
|
|
const values = pointerValues(event);
|
|
const state = this.state;
|
|
state._delta = V.sub(values, state._values);
|
|
V.addTo(state._movement, state._delta);
|
|
this.computeValues(values);
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
moveEnd(event) {
|
|
if (!this.state._active) return;
|
|
this.state._active = false;
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
bind(bindFunction) {
|
|
bindFunction("pointer", "change", this.move.bind(this));
|
|
bindFunction("pointer", "leave", this.moveEnd.bind(this));
|
|
}
|
|
};
|
|
var moveConfigResolver = _objectSpread2(_objectSpread2({}, coordinatesConfigResolver), {}, {
|
|
mouseOnly: (value = true) => value
|
|
});
|
|
var ScrollEngine = class extends CoordinatesEngine {
|
|
constructor(...args) {
|
|
super(...args);
|
|
_defineProperty(this, "ingKey", "scrolling");
|
|
}
|
|
scroll(event) {
|
|
if (!this.state._active) this.start(event);
|
|
this.scrollChange(event);
|
|
this.timeoutStore.add("scrollEnd", this.scrollEnd.bind(this));
|
|
}
|
|
scrollChange(event) {
|
|
if (event.cancelable) event.preventDefault();
|
|
const state = this.state;
|
|
const values = scrollValues(event);
|
|
state._delta = V.sub(values, state._values);
|
|
V.addTo(state._movement, state._delta);
|
|
this.computeValues(values);
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
scrollEnd() {
|
|
if (!this.state._active) return;
|
|
this.state._active = false;
|
|
this.compute();
|
|
this.emit();
|
|
}
|
|
bind(bindFunction) {
|
|
bindFunction("scroll", "", this.scroll.bind(this));
|
|
}
|
|
};
|
|
var scrollConfigResolver = coordinatesConfigResolver;
|
|
var WheelEngine = class extends CoordinatesEngine {
|
|
constructor(...args) {
|
|
super(...args);
|
|
_defineProperty(this, "ingKey", "wheeling");
|
|
}
|
|
wheel(event) {
|
|
if (!this.state._active) this.start(event);
|
|
this.wheelChange(event);
|
|
this.timeoutStore.add("wheelEnd", this.wheelEnd.bind(this));
|
|
}
|
|
wheelChange(event) {
|
|
const state = this.state;
|
|
state._delta = wheelValues(event);
|
|
V.addTo(state._movement, state._delta);
|
|
clampStateInternalMovementToBounds(state);
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
wheelEnd() {
|
|
if (!this.state._active) return;
|
|
this.state._active = false;
|
|
this.compute();
|
|
this.emit();
|
|
}
|
|
bind(bindFunction) {
|
|
bindFunction("wheel", "", this.wheel.bind(this));
|
|
}
|
|
};
|
|
var wheelConfigResolver = coordinatesConfigResolver;
|
|
var HoverEngine = class extends CoordinatesEngine {
|
|
constructor(...args) {
|
|
super(...args);
|
|
_defineProperty(this, "ingKey", "hovering");
|
|
}
|
|
enter(event) {
|
|
if (this.config.mouseOnly && event.pointerType !== "mouse") return;
|
|
this.start(event);
|
|
this.computeValues(pointerValues(event));
|
|
this.compute(event);
|
|
this.emit();
|
|
}
|
|
leave(event) {
|
|
if (this.config.mouseOnly && event.pointerType !== "mouse") return;
|
|
const state = this.state;
|
|
if (!state._active) return;
|
|
state._active = false;
|
|
const values = pointerValues(event);
|
|
state._movement = state._delta = V.sub(values, state._values);
|
|
this.computeValues(values);
|
|
this.compute(event);
|
|
state.delta = state.movement;
|
|
this.emit();
|
|
}
|
|
bind(bindFunction) {
|
|
bindFunction("pointer", "enter", this.enter.bind(this));
|
|
bindFunction("pointer", "leave", this.leave.bind(this));
|
|
}
|
|
};
|
|
var hoverConfigResolver = _objectSpread2(_objectSpread2({}, coordinatesConfigResolver), {}, {
|
|
mouseOnly: (value = true) => value
|
|
});
|
|
var EngineMap = /* @__PURE__ */ new Map();
|
|
var ConfigResolverMap = /* @__PURE__ */ new Map();
|
|
function registerAction(action) {
|
|
EngineMap.set(action.key, action.engine);
|
|
ConfigResolverMap.set(action.key, action.resolver);
|
|
}
|
|
var dragAction = {
|
|
key: "drag",
|
|
engine: DragEngine,
|
|
resolver: dragConfigResolver
|
|
};
|
|
var hoverAction = {
|
|
key: "hover",
|
|
engine: HoverEngine,
|
|
resolver: hoverConfigResolver
|
|
};
|
|
var moveAction = {
|
|
key: "move",
|
|
engine: MoveEngine,
|
|
resolver: moveConfigResolver
|
|
};
|
|
var pinchAction = {
|
|
key: "pinch",
|
|
engine: PinchEngine,
|
|
resolver: pinchConfigResolver
|
|
};
|
|
var scrollAction = {
|
|
key: "scroll",
|
|
engine: ScrollEngine,
|
|
resolver: scrollConfigResolver
|
|
};
|
|
var wheelAction = {
|
|
key: "wheel",
|
|
engine: WheelEngine,
|
|
resolver: wheelConfigResolver
|
|
};
|
|
|
|
// node_modules/@use-gesture/react/dist/use-gesture-react.esm.js
|
|
var import_react = __toESM(require_react());
|
|
|
|
// node_modules/@use-gesture/core/dist/use-gesture-core.esm.js
|
|
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
if (source == null) return {};
|
|
var target2 = {};
|
|
var sourceKeys = Object.keys(source);
|
|
var key, i3;
|
|
for (i3 = 0; i3 < sourceKeys.length; i3++) {
|
|
key = sourceKeys[i3];
|
|
if (excluded.indexOf(key) >= 0) continue;
|
|
target2[key] = source[key];
|
|
}
|
|
return target2;
|
|
}
|
|
function _objectWithoutProperties(source, excluded) {
|
|
if (source == null) return {};
|
|
var target2 = _objectWithoutPropertiesLoose(source, excluded);
|
|
var key, i3;
|
|
if (Object.getOwnPropertySymbols) {
|
|
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
|
for (i3 = 0; i3 < sourceSymbolKeys.length; i3++) {
|
|
key = sourceSymbolKeys[i3];
|
|
if (excluded.indexOf(key) >= 0) continue;
|
|
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
target2[key] = source[key];
|
|
}
|
|
}
|
|
return target2;
|
|
}
|
|
var sharedConfigResolver = {
|
|
target(value) {
|
|
if (value) {
|
|
return () => "current" in value ? value.current : value;
|
|
}
|
|
return void 0;
|
|
},
|
|
enabled(value = true) {
|
|
return value;
|
|
},
|
|
window(value = SUPPORT.isBrowser ? window : void 0) {
|
|
return value;
|
|
},
|
|
eventOptions({
|
|
passive = true,
|
|
capture = false
|
|
} = {}) {
|
|
return {
|
|
passive,
|
|
capture
|
|
};
|
|
},
|
|
transform(value) {
|
|
return value;
|
|
}
|
|
};
|
|
var _excluded = ["target", "eventOptions", "window", "enabled", "transform"];
|
|
function resolveWith(config = {}, resolvers) {
|
|
const result = {};
|
|
for (const [key, resolver] of Object.entries(resolvers)) {
|
|
switch (typeof resolver) {
|
|
case "function":
|
|
if (true) {
|
|
const r2 = resolver.call(result, config[key], key, config);
|
|
if (!Number.isNaN(r2)) result[key] = r2;
|
|
} else {
|
|
result[key] = resolver.call(result, config[key], key, config);
|
|
}
|
|
break;
|
|
case "object":
|
|
result[key] = resolveWith(config[key], resolver);
|
|
break;
|
|
case "boolean":
|
|
if (resolver) result[key] = config[key];
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
function parse(newConfig, gestureKey, _config = {}) {
|
|
const _ref = newConfig, {
|
|
target: target2,
|
|
eventOptions,
|
|
window: window2,
|
|
enabled,
|
|
transform
|
|
} = _ref, rest = _objectWithoutProperties(_ref, _excluded);
|
|
_config.shared = resolveWith({
|
|
target: target2,
|
|
eventOptions,
|
|
window: window2,
|
|
enabled,
|
|
transform
|
|
}, sharedConfigResolver);
|
|
if (gestureKey) {
|
|
const resolver = ConfigResolverMap.get(gestureKey);
|
|
_config[gestureKey] = resolveWith(_objectSpread2({
|
|
shared: _config.shared
|
|
}, rest), resolver);
|
|
} else {
|
|
for (const key in rest) {
|
|
const resolver = ConfigResolverMap.get(key);
|
|
if (resolver) {
|
|
_config[key] = resolveWith(_objectSpread2({
|
|
shared: _config.shared
|
|
}, rest[key]), resolver);
|
|
} else if (true) {
|
|
if (!["drag", "pinch", "scroll", "wheel", "move", "hover"].includes(key)) {
|
|
if (key === "domTarget") {
|
|
throw Error(`[@use-gesture]: \`domTarget\` option has been renamed to \`target\`.`);
|
|
}
|
|
console.warn(`[@use-gesture]: Unknown config key \`${key}\` was used. Please read the documentation for further information.`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return _config;
|
|
}
|
|
var EventStore = class {
|
|
constructor(ctrl, gestureKey) {
|
|
_defineProperty(this, "_listeners", /* @__PURE__ */ new Set());
|
|
this._ctrl = ctrl;
|
|
this._gestureKey = gestureKey;
|
|
}
|
|
add(element, device, action, handler, options) {
|
|
const listeners = this._listeners;
|
|
const type = toDomEventType(device, action);
|
|
const _options = this._gestureKey ? this._ctrl.config[this._gestureKey].eventOptions : {};
|
|
const eventOptions = _objectSpread2(_objectSpread2({}, _options), options);
|
|
element.addEventListener(type, handler, eventOptions);
|
|
const remove = () => {
|
|
element.removeEventListener(type, handler, eventOptions);
|
|
listeners.delete(remove);
|
|
};
|
|
listeners.add(remove);
|
|
return remove;
|
|
}
|
|
clean() {
|
|
this._listeners.forEach((remove) => remove());
|
|
this._listeners.clear();
|
|
}
|
|
};
|
|
var TimeoutStore = class {
|
|
constructor() {
|
|
_defineProperty(this, "_timeouts", /* @__PURE__ */ new Map());
|
|
}
|
|
add(key, callback, ms = 140, ...args) {
|
|
this.remove(key);
|
|
this._timeouts.set(key, window.setTimeout(callback, ms, ...args));
|
|
}
|
|
remove(key) {
|
|
const timeout = this._timeouts.get(key);
|
|
if (timeout) window.clearTimeout(timeout);
|
|
}
|
|
clean() {
|
|
this._timeouts.forEach((timeout) => void window.clearTimeout(timeout));
|
|
this._timeouts.clear();
|
|
}
|
|
};
|
|
var Controller = class {
|
|
constructor(handlers) {
|
|
_defineProperty(this, "gestures", /* @__PURE__ */ new Set());
|
|
_defineProperty(this, "_targetEventStore", new EventStore(this));
|
|
_defineProperty(this, "gestureEventStores", {});
|
|
_defineProperty(this, "gestureTimeoutStores", {});
|
|
_defineProperty(this, "handlers", {});
|
|
_defineProperty(this, "config", {});
|
|
_defineProperty(this, "pointerIds", /* @__PURE__ */ new Set());
|
|
_defineProperty(this, "touchIds", /* @__PURE__ */ new Set());
|
|
_defineProperty(this, "state", {
|
|
shared: {
|
|
shiftKey: false,
|
|
metaKey: false,
|
|
ctrlKey: false,
|
|
altKey: false
|
|
}
|
|
});
|
|
resolveGestures(this, handlers);
|
|
}
|
|
setEventIds(event) {
|
|
if (isTouch(event)) {
|
|
this.touchIds = new Set(touchIds(event));
|
|
return this.touchIds;
|
|
} else if ("pointerId" in event) {
|
|
if (event.type === "pointerup" || event.type === "pointercancel") this.pointerIds.delete(event.pointerId);
|
|
else if (event.type === "pointerdown") this.pointerIds.add(event.pointerId);
|
|
return this.pointerIds;
|
|
}
|
|
}
|
|
applyHandlers(handlers, nativeHandlers) {
|
|
this.handlers = handlers;
|
|
this.nativeHandlers = nativeHandlers;
|
|
}
|
|
applyConfig(config, gestureKey) {
|
|
this.config = parse(config, gestureKey, this.config);
|
|
}
|
|
clean() {
|
|
this._targetEventStore.clean();
|
|
for (const key of this.gestures) {
|
|
this.gestureEventStores[key].clean();
|
|
this.gestureTimeoutStores[key].clean();
|
|
}
|
|
}
|
|
effect() {
|
|
if (this.config.shared.target) this.bind();
|
|
return () => this._targetEventStore.clean();
|
|
}
|
|
bind(...args) {
|
|
const sharedConfig = this.config.shared;
|
|
const props = {};
|
|
let target2;
|
|
if (sharedConfig.target) {
|
|
target2 = sharedConfig.target();
|
|
if (!target2) return;
|
|
}
|
|
if (sharedConfig.enabled) {
|
|
for (const gestureKey of this.gestures) {
|
|
const gestureConfig = this.config[gestureKey];
|
|
const bindFunction = bindToProps(props, gestureConfig.eventOptions, !!target2);
|
|
if (gestureConfig.enabled) {
|
|
const Engine2 = EngineMap.get(gestureKey);
|
|
new Engine2(this, args, gestureKey).bind(bindFunction);
|
|
}
|
|
}
|
|
const nativeBindFunction = bindToProps(props, sharedConfig.eventOptions, !!target2);
|
|
for (const eventKey in this.nativeHandlers) {
|
|
nativeBindFunction(eventKey, "", (event) => this.nativeHandlers[eventKey](_objectSpread2(_objectSpread2({}, this.state.shared), {}, {
|
|
event,
|
|
args
|
|
})), void 0, true);
|
|
}
|
|
}
|
|
for (const handlerProp in props) {
|
|
props[handlerProp] = chain(...props[handlerProp]);
|
|
}
|
|
if (!target2) return props;
|
|
for (const handlerProp in props) {
|
|
const {
|
|
device,
|
|
capture,
|
|
passive
|
|
} = parseProp(handlerProp);
|
|
this._targetEventStore.add(target2, device, "", props[handlerProp], {
|
|
capture,
|
|
passive
|
|
});
|
|
}
|
|
}
|
|
};
|
|
function setupGesture(ctrl, gestureKey) {
|
|
ctrl.gestures.add(gestureKey);
|
|
ctrl.gestureEventStores[gestureKey] = new EventStore(ctrl, gestureKey);
|
|
ctrl.gestureTimeoutStores[gestureKey] = new TimeoutStore();
|
|
}
|
|
function resolveGestures(ctrl, internalHandlers) {
|
|
if (internalHandlers.drag) setupGesture(ctrl, "drag");
|
|
if (internalHandlers.wheel) setupGesture(ctrl, "wheel");
|
|
if (internalHandlers.scroll) setupGesture(ctrl, "scroll");
|
|
if (internalHandlers.move) setupGesture(ctrl, "move");
|
|
if (internalHandlers.pinch) setupGesture(ctrl, "pinch");
|
|
if (internalHandlers.hover) setupGesture(ctrl, "hover");
|
|
}
|
|
var bindToProps = (props, eventOptions, withPassiveOption) => (device, action, handler, options = {}, isNative = false) => {
|
|
var _options$capture, _options$passive;
|
|
const capture = (_options$capture = options.capture) !== null && _options$capture !== void 0 ? _options$capture : eventOptions.capture;
|
|
const passive = (_options$passive = options.passive) !== null && _options$passive !== void 0 ? _options$passive : eventOptions.passive;
|
|
let handlerProp = isNative ? device : toHandlerProp(device, action, capture);
|
|
if (withPassiveOption && passive) handlerProp += "Passive";
|
|
props[handlerProp] = props[handlerProp] || [];
|
|
props[handlerProp].push(handler);
|
|
};
|
|
var RE_NOT_NATIVE = /^on(Drag|Wheel|Scroll|Move|Pinch|Hover)/;
|
|
function sortHandlers(_handlers) {
|
|
const native = {};
|
|
const handlers = {};
|
|
const actions = /* @__PURE__ */ new Set();
|
|
for (let key in _handlers) {
|
|
if (RE_NOT_NATIVE.test(key)) {
|
|
actions.add(RegExp.lastMatch);
|
|
handlers[key] = _handlers[key];
|
|
} else {
|
|
native[key] = _handlers[key];
|
|
}
|
|
}
|
|
return [handlers, native, actions];
|
|
}
|
|
function registerGesture(actions, handlers, handlerKey, key, internalHandlers, config) {
|
|
if (!actions.has(handlerKey)) return;
|
|
if (!EngineMap.has(key)) {
|
|
if (true) {
|
|
console.warn(`[@use-gesture]: You've created a custom handler that that uses the \`${key}\` gesture but isn't properly configured.
|
|
|
|
Please add \`${key}Action\` when creating your handler.`);
|
|
}
|
|
return;
|
|
}
|
|
const startKey = handlerKey + "Start";
|
|
const endKey = handlerKey + "End";
|
|
const fn = (state) => {
|
|
let memo = void 0;
|
|
if (state.first && startKey in handlers) handlers[startKey](state);
|
|
if (handlerKey in handlers) memo = handlers[handlerKey](state);
|
|
if (state.last && endKey in handlers) handlers[endKey](state);
|
|
return memo;
|
|
};
|
|
internalHandlers[key] = fn;
|
|
config[key] = config[key] || {};
|
|
}
|
|
function parseMergedHandlers(mergedHandlers, mergedConfig) {
|
|
const [handlers, nativeHandlers, actions] = sortHandlers(mergedHandlers);
|
|
const internalHandlers = {};
|
|
registerGesture(actions, handlers, "onDrag", "drag", internalHandlers, mergedConfig);
|
|
registerGesture(actions, handlers, "onWheel", "wheel", internalHandlers, mergedConfig);
|
|
registerGesture(actions, handlers, "onScroll", "scroll", internalHandlers, mergedConfig);
|
|
registerGesture(actions, handlers, "onPinch", "pinch", internalHandlers, mergedConfig);
|
|
registerGesture(actions, handlers, "onMove", "move", internalHandlers, mergedConfig);
|
|
registerGesture(actions, handlers, "onHover", "hover", internalHandlers, mergedConfig);
|
|
return {
|
|
handlers: internalHandlers,
|
|
config: mergedConfig,
|
|
nativeHandlers
|
|
};
|
|
}
|
|
|
|
// node_modules/@use-gesture/react/dist/use-gesture-react.esm.js
|
|
function useRecognizers(handlers, config = {}, gestureKey, nativeHandlers) {
|
|
const ctrl = import_react.default.useMemo(() => new Controller(handlers), []);
|
|
ctrl.applyHandlers(handlers, nativeHandlers);
|
|
ctrl.applyConfig(config, gestureKey);
|
|
import_react.default.useEffect(ctrl.effect.bind(ctrl));
|
|
import_react.default.useEffect(() => {
|
|
return ctrl.clean.bind(ctrl);
|
|
}, []);
|
|
if (config.target === void 0) {
|
|
return ctrl.bind.bind(ctrl);
|
|
}
|
|
return void 0;
|
|
}
|
|
function createUseGesture(actions) {
|
|
actions.forEach(registerAction);
|
|
return function useGesture2(_handlers, _config) {
|
|
const {
|
|
handlers,
|
|
nativeHandlers,
|
|
config
|
|
} = parseMergedHandlers(_handlers, _config || {});
|
|
return useRecognizers(handlers, config, void 0, nativeHandlers);
|
|
};
|
|
}
|
|
function useGesture(handlers, config) {
|
|
const hook = createUseGesture([dragAction, pinchAction, scrollAction, wheelAction, moveAction, hoverAction]);
|
|
return hook(handlers, config || {});
|
|
}
|
|
|
|
// node_modules/@react-three/drei/web/DragControls.js
|
|
var initialModelPosition = new Vector3();
|
|
var mousePosition2D = new Vector2();
|
|
var mousePosition3D = new Vector3();
|
|
var dragOffset = new Vector3();
|
|
var dragPlaneNormal = new Vector3();
|
|
var dragPlane = new Plane();
|
|
var DragControls = React7.forwardRef(({
|
|
autoTransform = true,
|
|
matrix: matrix4,
|
|
axisLock,
|
|
dragLimits,
|
|
onHover,
|
|
onDragStart,
|
|
onDrag,
|
|
onDragEnd,
|
|
children,
|
|
dragConfig,
|
|
...props
|
|
}, fRef) => {
|
|
const defaultControls = useThree((state) => state.controls);
|
|
const {
|
|
camera,
|
|
size,
|
|
raycaster,
|
|
invalidate
|
|
} = useThree();
|
|
const ref = React7.useRef(null);
|
|
const bind = useGesture({
|
|
onHover: ({
|
|
hovering
|
|
}) => onHover && onHover(hovering !== null && hovering !== void 0 ? hovering : false),
|
|
onDragStart: ({
|
|
event
|
|
}) => {
|
|
if (defaultControls) defaultControls.enabled = false;
|
|
const {
|
|
point
|
|
} = event;
|
|
ref.current.matrix.decompose(initialModelPosition, new Quaternion(), new Vector3());
|
|
mousePosition3D.copy(point);
|
|
dragOffset.copy(mousePosition3D).sub(initialModelPosition);
|
|
onDragStart && onDragStart(initialModelPosition);
|
|
invalidate();
|
|
},
|
|
onDrag: ({
|
|
xy: [dragX, dragY],
|
|
intentional
|
|
}) => {
|
|
if (!intentional) return;
|
|
const normalizedMouseX = (dragX - size.left) / size.width * 2 - 1;
|
|
const normalizedMouseY = -((dragY - size.top) / size.height) * 2 + 1;
|
|
mousePosition2D.set(normalizedMouseX, normalizedMouseY);
|
|
raycaster.setFromCamera(mousePosition2D, camera);
|
|
if (!axisLock) {
|
|
camera.getWorldDirection(dragPlaneNormal).negate();
|
|
} else {
|
|
switch (axisLock) {
|
|
case "x":
|
|
dragPlaneNormal.set(1, 0, 0);
|
|
break;
|
|
case "y":
|
|
dragPlaneNormal.set(0, 1, 0);
|
|
break;
|
|
case "z":
|
|
dragPlaneNormal.set(0, 0, 1);
|
|
break;
|
|
}
|
|
}
|
|
dragPlane.setFromNormalAndCoplanarPoint(dragPlaneNormal, mousePosition3D);
|
|
raycaster.ray.intersectPlane(dragPlane, mousePosition3D);
|
|
const previousLocalMatrix = ref.current.matrix.clone();
|
|
const previousWorldMatrix = ref.current.matrixWorld.clone();
|
|
const intendedNewPosition = new Vector3(mousePosition3D.x - dragOffset.x, mousePosition3D.y - dragOffset.y, mousePosition3D.z - dragOffset.z);
|
|
if (dragLimits) {
|
|
intendedNewPosition.x = dragLimits[0] ? Math.max(Math.min(intendedNewPosition.x, dragLimits[0][1]), dragLimits[0][0]) : intendedNewPosition.x;
|
|
intendedNewPosition.y = dragLimits[1] ? Math.max(Math.min(intendedNewPosition.y, dragLimits[1][1]), dragLimits[1][0]) : intendedNewPosition.y;
|
|
intendedNewPosition.z = dragLimits[2] ? Math.max(Math.min(intendedNewPosition.z, dragLimits[2][1]), dragLimits[2][0]) : intendedNewPosition.z;
|
|
}
|
|
if (autoTransform) {
|
|
ref.current.matrix.setPosition(intendedNewPosition);
|
|
const deltaLocalMatrix = ref.current.matrix.clone().multiply(previousLocalMatrix.invert());
|
|
const deltaWorldMatrix = ref.current.matrix.clone().multiply(previousWorldMatrix.invert());
|
|
onDrag && onDrag(ref.current.matrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
|
|
} else {
|
|
const tempMatrix4 = new Matrix4().copy(ref.current.matrix);
|
|
tempMatrix4.setPosition(intendedNewPosition);
|
|
const deltaLocalMatrix = tempMatrix4.clone().multiply(previousLocalMatrix.invert());
|
|
const deltaWorldMatrix = tempMatrix4.clone().multiply(previousWorldMatrix.invert());
|
|
onDrag && onDrag(tempMatrix4, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
|
|
}
|
|
invalidate();
|
|
},
|
|
onDragEnd: () => {
|
|
if (defaultControls) defaultControls.enabled = true;
|
|
onDragEnd && onDragEnd();
|
|
invalidate();
|
|
}
|
|
}, {
|
|
drag: {
|
|
filterTaps: true,
|
|
threshold: 1,
|
|
...typeof dragConfig === "object" ? dragConfig : {}
|
|
}
|
|
});
|
|
React7.useImperativeHandle(fRef, () => ref.current, []);
|
|
React7.useLayoutEffect(() => {
|
|
if (!matrix4) return;
|
|
ref.current.matrix = matrix4;
|
|
}, [matrix4]);
|
|
return React7.createElement("group", _extends({
|
|
ref
|
|
}, bind(), {
|
|
matrix: matrix4,
|
|
matrixAutoUpdate: false
|
|
}, props), children);
|
|
});
|
|
|
|
// node_modules/@react-three/drei/web/ScrollControls.js
|
|
var React8 = __toESM(require_react());
|
|
var ReactDOM2 = __toESM(require_client());
|
|
|
|
// node_modules/maath/dist/objectSpread2-284232a6.esm.js
|
|
function _defineProperty2(obj, key, value) {
|
|
if (key in obj) {
|
|
Object.defineProperty(obj, key, {
|
|
value,
|
|
enumerable: true,
|
|
configurable: true,
|
|
writable: true
|
|
});
|
|
} else {
|
|
obj[key] = value;
|
|
}
|
|
return obj;
|
|
}
|
|
function ownKeys2(object, enumerableOnly) {
|
|
var keys = Object.keys(object);
|
|
if (Object.getOwnPropertySymbols) {
|
|
var symbols = Object.getOwnPropertySymbols(object);
|
|
if (enumerableOnly) {
|
|
symbols = symbols.filter(function(sym) {
|
|
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
});
|
|
}
|
|
keys.push.apply(keys, symbols);
|
|
}
|
|
return keys;
|
|
}
|
|
function _objectSpread22(target2) {
|
|
for (var i3 = 1; i3 < arguments.length; i3++) {
|
|
var source = arguments[i3] != null ? arguments[i3] : {};
|
|
if (i3 % 2) {
|
|
ownKeys2(Object(source), true).forEach(function(key) {
|
|
_defineProperty2(target2, key, source[key]);
|
|
});
|
|
} else if (Object.getOwnPropertyDescriptors) {
|
|
Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source));
|
|
} else {
|
|
ownKeys2(Object(source)).forEach(function(key) {
|
|
Object.defineProperty(target2, key, Object.getOwnPropertyDescriptor(source, key));
|
|
});
|
|
}
|
|
}
|
|
return target2;
|
|
}
|
|
|
|
// node_modules/maath/dist/isNativeReflectConstruct-5594d075.esm.js
|
|
function _setPrototypeOf(o2, p2) {
|
|
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf2(o3, p3) {
|
|
o3.__proto__ = p3;
|
|
return o3;
|
|
};
|
|
return _setPrototypeOf(o2, p2);
|
|
}
|
|
function _isNativeReflectConstruct() {
|
|
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
|
|
if (Reflect.construct.sham) return false;
|
|
if (typeof Proxy === "function") return true;
|
|
try {
|
|
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {
|
|
}));
|
|
return true;
|
|
} catch (e2) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// node_modules/maath/dist/matrix-baa530bf.esm.js
|
|
function determinant2() {
|
|
for (var _len = arguments.length, terms = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
terms[_key] = arguments[_key];
|
|
}
|
|
var a5 = terms[0], b = terms[1], c2 = terms[2], d2 = terms[3];
|
|
return a5 * d2 - b * c2;
|
|
}
|
|
function determinant3() {
|
|
for (var _len2 = arguments.length, terms = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
terms[_key2] = arguments[_key2];
|
|
}
|
|
var a5 = terms[0], b = terms[1], c2 = terms[2], d2 = terms[3], e2 = terms[4], f2 = terms[5], g = terms[6], h = terms[7], i3 = terms[8];
|
|
return a5 * e2 * i3 + b * f2 * g + c2 * d2 * h - c2 * e2 * g - b * d2 * i3 - a5 * f2 * h;
|
|
}
|
|
function determinant4() {
|
|
for (var _len3 = arguments.length, terms = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
|
|
terms[_key3] = arguments[_key3];
|
|
}
|
|
terms[0];
|
|
terms[1];
|
|
terms[2];
|
|
terms[3];
|
|
terms[4];
|
|
terms[5];
|
|
terms[6];
|
|
terms[7];
|
|
terms[8];
|
|
terms[9];
|
|
terms[10];
|
|
terms[11];
|
|
terms[12];
|
|
terms[13];
|
|
terms[14];
|
|
}
|
|
function getMinor(matrix4, r2, c2) {
|
|
var _matrixTranspose = matrix4.clone().transpose();
|
|
var x = [];
|
|
var l2 = _matrixTranspose.elements.length;
|
|
var n2 = Math.sqrt(l2);
|
|
for (var i3 = 0; i3 < l2; i3++) {
|
|
var element = _matrixTranspose.elements[i3];
|
|
var row = Math.floor(i3 / n2);
|
|
var col3 = i3 % n2;
|
|
if (row !== r2 - 1 && col3 !== c2 - 1) {
|
|
x.push(element);
|
|
}
|
|
}
|
|
return determinant3.apply(void 0, x);
|
|
}
|
|
function matrixSum3(m1, m2) {
|
|
var sum = [];
|
|
var m1Array = m1.toArray();
|
|
var m2Array = m2.toArray();
|
|
for (var i3 = 0; i3 < m1Array.length; i3++) {
|
|
sum[i3] = m1Array[i3] + m2Array[i3];
|
|
}
|
|
return new Matrix3().fromArray(sum);
|
|
}
|
|
var matrix = Object.freeze({
|
|
__proto__: null,
|
|
determinant2,
|
|
determinant3,
|
|
determinant4,
|
|
getMinor,
|
|
matrixSum3
|
|
});
|
|
|
|
// node_modules/maath/dist/triangle-b62b9067.esm.js
|
|
function _arrayWithHoles(arr) {
|
|
if (Array.isArray(arr)) return arr;
|
|
}
|
|
function _iterableToArrayLimit(arr, i3) {
|
|
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
if (_i == null) return;
|
|
var _arr = [];
|
|
var _n = true;
|
|
var _d = false;
|
|
var _s, _e;
|
|
try {
|
|
for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
|
|
_arr.push(_s.value);
|
|
if (i3 && _arr.length === i3) break;
|
|
}
|
|
} catch (err) {
|
|
_d = true;
|
|
_e = err;
|
|
} finally {
|
|
try {
|
|
if (!_n && _i["return"] != null) _i["return"]();
|
|
} finally {
|
|
if (_d) throw _e;
|
|
}
|
|
}
|
|
return _arr;
|
|
}
|
|
function _arrayLikeToArray(arr, len) {
|
|
if (len == null || len > arr.length) len = arr.length;
|
|
for (var i3 = 0, arr2 = new Array(len); i3 < len; i3++) arr2[i3] = arr[i3];
|
|
return arr2;
|
|
}
|
|
function _unsupportedIterableToArray(o2, minLen) {
|
|
if (!o2) return;
|
|
if (typeof o2 === "string") return _arrayLikeToArray(o2, minLen);
|
|
var n2 = Object.prototype.toString.call(o2).slice(8, -1);
|
|
if (n2 === "Object" && o2.constructor) n2 = o2.constructor.name;
|
|
if (n2 === "Map" || n2 === "Set") return Array.from(o2);
|
|
if (n2 === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n2)) return _arrayLikeToArray(o2, minLen);
|
|
}
|
|
function _nonIterableRest() {
|
|
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
}
|
|
function _slicedToArray(arr, i3) {
|
|
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i3) || _unsupportedIterableToArray(arr, i3) || _nonIterableRest();
|
|
}
|
|
function _arrayWithoutHoles(arr) {
|
|
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
|
|
}
|
|
function _iterableToArray(iter) {
|
|
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
}
|
|
function _nonIterableSpread() {
|
|
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
}
|
|
function _toConsumableArray(arr) {
|
|
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
|
|
}
|
|
function _construct(Parent, args, Class) {
|
|
if (_isNativeReflectConstruct()) {
|
|
_construct = Reflect.construct;
|
|
} else {
|
|
_construct = function _construct2(Parent2, args2, Class2) {
|
|
var a5 = [null];
|
|
a5.push.apply(a5, args2);
|
|
var Constructor = Function.bind.apply(Parent2, a5);
|
|
var instance = new Constructor();
|
|
if (Class2) _setPrototypeOf(instance, Class2.prototype);
|
|
return instance;
|
|
};
|
|
}
|
|
return _construct.apply(null, arguments);
|
|
}
|
|
function isPointInTriangle(point, triangle4) {
|
|
var _triangle$ = _slicedToArray(triangle4[0], 2), ax = _triangle$[0], ay = _triangle$[1];
|
|
var _triangle$2 = _slicedToArray(triangle4[1], 2), bx = _triangle$2[0], by = _triangle$2[1];
|
|
var _triangle$3 = _slicedToArray(triangle4[2], 2), cx = _triangle$3[0], cy = _triangle$3[1];
|
|
var _point = _slicedToArray(point, 2), px = _point[0], py = _point[1];
|
|
var matrix4 = new Matrix4();
|
|
matrix4.set(ax, ay, ax * ax + ay * ay, 1, bx, by, bx * bx + by * by, 1, cx, cy, cx * cx + cy * cy, 1, px, py, px * px + py * py, 1);
|
|
return matrix4.determinant() <= 0;
|
|
}
|
|
function triangleDeterminant(triangle4) {
|
|
var _triangle$4 = _slicedToArray(triangle4[0], 2), x1 = _triangle$4[0], y1 = _triangle$4[1];
|
|
var _triangle$5 = _slicedToArray(triangle4[1], 2), x2 = _triangle$5[0], y2 = _triangle$5[1];
|
|
var _triangle$6 = _slicedToArray(triangle4[2], 2), x3 = _triangle$6[0], y3 = _triangle$6[1];
|
|
return determinant3(x1, y1, 1, x2, y2, 1, x3, y3, 1);
|
|
}
|
|
function arePointsCollinear(points) {
|
|
return triangleDeterminant(points) === 0;
|
|
}
|
|
function isTriangleClockwise(triangle4) {
|
|
return triangleDeterminant(triangle4) < 0;
|
|
}
|
|
function getCircumcircle(triangle4) {
|
|
var _triangle$7 = _slicedToArray(triangle4[0], 2), ax = _triangle$7[0], ay = _triangle$7[1];
|
|
var _triangle$8 = _slicedToArray(triangle4[1], 2), bx = _triangle$8[0], by = _triangle$8[1];
|
|
var _triangle$9 = _slicedToArray(triangle4[2], 2), cx = _triangle$9[0], cy = _triangle$9[1];
|
|
if (arePointsCollinear(triangle4)) return null;
|
|
var m = new Matrix4();
|
|
m.set(1, 1, 1, 1, ax * ax + ay * ay, ax, ay, 1, bx * bx + by * by, bx, by, 1, cx * cx + cy * cy, cx, cy, 1);
|
|
var m11 = getMinor(m, 1, 1);
|
|
var m13 = getMinor(m, 1, 3);
|
|
var m12 = getMinor(m, 1, 2);
|
|
var m14 = getMinor(m, 1, 4);
|
|
var x0 = 0.5 * (m12 / m11);
|
|
var y0 = 0.5 * (m13 / m11);
|
|
var r2 = x0 * x0 + y0 * y0 + m14 / m11;
|
|
return {
|
|
x: Math.abs(x0) === 0 ? 0 : x0,
|
|
y: Math.abs(y0) === 0 ? 0 : -y0,
|
|
r: Math.sqrt(r2)
|
|
};
|
|
}
|
|
function isPointInCircumcircle(point, triangle4) {
|
|
var _ref = Array.isArray(triangle4[0]) ? triangle4[0] : triangle4[0].toArray(), _ref2 = _slicedToArray(_ref, 2), ax = _ref2[0], ay = _ref2[1];
|
|
var _ref3 = Array.isArray(triangle4[1]) ? triangle4[1] : triangle4[1].toArray(), _ref4 = _slicedToArray(_ref3, 2), bx = _ref4[0], by = _ref4[1];
|
|
var _ref5 = Array.isArray(triangle4[2]) ? triangle4[2] : triangle4[2].toArray(), _ref6 = _slicedToArray(_ref5, 2), cx = _ref6[0], cy = _ref6[1];
|
|
var _point2 = _slicedToArray(point, 2), px = _point2[0], py = _point2[1];
|
|
if (arePointsCollinear(triangle4)) throw new Error("Collinear points don't form a triangle");
|
|
var x1mpx = ax - px;
|
|
var aympy = ay - py;
|
|
var bxmpx = bx - px;
|
|
var bympy = by - py;
|
|
var cxmpx = cx - px;
|
|
var cympy = cy - py;
|
|
var d2 = determinant3(x1mpx, aympy, x1mpx * x1mpx + aympy * aympy, bxmpx, bympy, bxmpx * bxmpx + bympy * bympy, cxmpx, cympy, cxmpx * cxmpx + cympy * cympy);
|
|
if (d2 === 0) {
|
|
return true;
|
|
}
|
|
return !isTriangleClockwise(triangle4) ? d2 > 0 : d2 < 0;
|
|
}
|
|
var mv1 = new Vector2();
|
|
var mv2 = new Vector2();
|
|
function doThreePointsMakeARight(points) {
|
|
var _points$map = points.map(function(p4) {
|
|
if (Array.isArray(p4)) {
|
|
return _construct(Vector2, _toConsumableArray(p4));
|
|
}
|
|
return p4;
|
|
}), _points$map2 = _slicedToArray(_points$map, 3), p1 = _points$map2[0], p2 = _points$map2[1], p3 = _points$map2[2];
|
|
if (arePointsCollinear(points)) return false;
|
|
var p2p1 = mv1.subVectors(p2, p1);
|
|
var p3p1 = mv2.subVectors(p3, p1);
|
|
var cross2 = p3p1.cross(p2p1);
|
|
return cross2 > 0;
|
|
}
|
|
var triangle = Object.freeze({
|
|
__proto__: null,
|
|
isPointInTriangle,
|
|
triangleDeterminant,
|
|
arePointsCollinear,
|
|
isTriangleClockwise,
|
|
getCircumcircle,
|
|
isPointInCircumcircle,
|
|
doThreePointsMakeARight
|
|
});
|
|
|
|
// node_modules/maath/dist/misc-19a3ec46.esm.js
|
|
function clamp2(value, min, max) {
|
|
return Math.max(min, Math.min(max, value));
|
|
}
|
|
function repeat(t2, length3) {
|
|
return clamp2(t2 - Math.floor(t2 / length3) * length3, 0, length3);
|
|
}
|
|
function deltaAngle(current, target2) {
|
|
var delta = repeat(target2 - current, Math.PI * 2);
|
|
if (delta > Math.PI) delta -= Math.PI * 2;
|
|
return delta;
|
|
}
|
|
function degToRad(degrees) {
|
|
return degrees / 180 * Math.PI;
|
|
}
|
|
function radToDeg(radians) {
|
|
return radians * 180 / Math.PI;
|
|
}
|
|
function fibonacciOnSphere(buffer2, _ref) {
|
|
var _ref$radius = _ref.radius, radius = _ref$radius === void 0 ? 1 : _ref$radius;
|
|
var samples = buffer2.length / 3;
|
|
var offset = 2 / samples;
|
|
var increment = Math.PI * (3 - 2.2360679775);
|
|
for (var i3 = 0; i3 < buffer2.length; i3 += 3) {
|
|
var y = i3 * offset - 1 + offset / 2;
|
|
var distance3 = Math.sqrt(1 - Math.pow(y, 2));
|
|
var phi = i3 % samples * increment;
|
|
var x = Math.cos(phi) * distance3;
|
|
var z = Math.sin(phi) * distance3;
|
|
buffer2[i3] = x * radius;
|
|
buffer2[i3 + 1] = y * radius;
|
|
buffer2[i3 + 2] = z * radius;
|
|
}
|
|
}
|
|
function vectorEquals(a5, b) {
|
|
var eps2 = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : Number.EPSILON;
|
|
return Math.abs(a5.x - b.x) < eps2 && Math.abs(a5.y - b.y) < eps2 && Math.abs(a5.z - b.z) < eps2;
|
|
}
|
|
function lexicographic(a5, b) {
|
|
if (a5.x === b.x) {
|
|
if (typeof a5.z !== "undefined") {
|
|
if (a5.y === b.y) {
|
|
return a5.z - b.z;
|
|
}
|
|
}
|
|
return a5.y - b.y;
|
|
}
|
|
return a5.x - b.x;
|
|
}
|
|
function convexHull(_points) {
|
|
var points = _points.sort(lexicographic);
|
|
var lUpper = [points[0], points[1]];
|
|
for (var i3 = 2; i3 < points.length; i3++) {
|
|
lUpper.push(points[i3]);
|
|
while (lUpper.length > 2 && doThreePointsMakeARight(_toConsumableArray(lUpper.slice(-3)))) {
|
|
lUpper.splice(lUpper.length - 2, 1);
|
|
}
|
|
}
|
|
var lLower = [points[points.length - 1], points[points.length - 2]];
|
|
for (var _i = points.length - 3; _i >= 0; _i--) {
|
|
lLower.push(points[_i]);
|
|
while (lLower.length > 2 && doThreePointsMakeARight(_toConsumableArray(lLower.slice(-3)))) {
|
|
lLower.splice(lLower.length - 2, 1);
|
|
}
|
|
}
|
|
lLower.splice(0, 1);
|
|
lLower.splice(lLower.length - 1, 1);
|
|
var c2 = [].concat(lUpper, lLower);
|
|
return c2;
|
|
}
|
|
function remap(x, _ref2, _ref3) {
|
|
var _ref4 = _slicedToArray(_ref2, 2), low1 = _ref4[0], high1 = _ref4[1];
|
|
var _ref5 = _slicedToArray(_ref3, 2), low2 = _ref5[0], high2 = _ref5[1];
|
|
return low2 + (x - low1) * (high2 - low2) / (high1 - low1);
|
|
}
|
|
function fade(t2) {
|
|
return t2 * t2 * t2 * (t2 * (t2 * 6 - 15) + 10);
|
|
}
|
|
function lerp(v0, v12, t2) {
|
|
return v0 * (1 - t2) + v12 * t2;
|
|
}
|
|
function inverseLerp(v0, v12, t2) {
|
|
return (t2 - v0) / (v12 - v0);
|
|
}
|
|
function normalize(x, y, z) {
|
|
var m = Math.sqrt(x * x + y * y + z * z);
|
|
return [x / m, y / m, z / m];
|
|
}
|
|
function pointOnCubeToPointOnSphere(x, y, z) {
|
|
var x2 = x * x;
|
|
var y2 = y * y;
|
|
var z2 = z * z;
|
|
var nx = x * Math.sqrt(1 - (y2 + z2) / 2 + y2 * z2 / 3);
|
|
var ny = y * Math.sqrt(1 - (z2 + x2) / 2 + z2 * x2 / 3);
|
|
var nz = z * Math.sqrt(1 - (x2 + y2) / 2 + x2 * y2 / 3);
|
|
return [nx, ny, nz];
|
|
}
|
|
function rotateVectorOnVector(a5, b) {
|
|
var v5 = new Vector3().crossVectors(a5, b);
|
|
var c2 = a5.dot(b);
|
|
var i3 = new Matrix3().identity();
|
|
var vx = new Matrix3().set(0, -v5.z, v5.y, v5.z, 0, -v5.x, -v5.y, v5.x, 0);
|
|
var vxsquared = new Matrix3().multiplyMatrices(vx, vx).multiplyScalar(1 / (1 + c2));
|
|
var _final = matrixSum3(matrixSum3(i3, vx), vxsquared);
|
|
return _final;
|
|
}
|
|
function pointToCoordinate(x, y, z) {
|
|
var lat = Math.asin(y);
|
|
var lon = Math.atan2(x, -z);
|
|
return [lat, lon];
|
|
}
|
|
function coordinateToPoint(lat, lon) {
|
|
var y = Math.sin(lat);
|
|
var r2 = Math.cos(lat);
|
|
var x = Math.sin(lon) * r2;
|
|
var z = -Math.cos(lon) * r2;
|
|
return [x, y, z];
|
|
}
|
|
function planeSegmentIntersection(plane, segment) {
|
|
var _segment = _slicedToArray(segment, 2), a5 = _segment[0], b = _segment[1];
|
|
var matrix4 = rotateVectorOnVector(plane.normal, new Vector3(0, 1, 0));
|
|
var t2 = inverseLerp(a5.clone().applyMatrix3(matrix4).y, b.clone().applyMatrix3(matrix4).y, 0);
|
|
return new Vector3().lerpVectors(a5, b, t2);
|
|
}
|
|
function pointToPlaneDistance(p2, plane) {
|
|
var d2 = plane.normal.dot(p2);
|
|
return d2;
|
|
}
|
|
function getIndexFrom3D(coords, sides) {
|
|
var _coords = _slicedToArray(coords, 3), ix = _coords[0], iy = _coords[1], iz = _coords[2];
|
|
var _sides = _slicedToArray(sides, 2), rx = _sides[0], ry = _sides[1];
|
|
return iz * rx * ry + iy * rx + ix;
|
|
}
|
|
function get3DFromIndex(index2, size) {
|
|
var _size = _slicedToArray(size, 2), rx = _size[0], ry = _size[1];
|
|
var a5 = rx * ry;
|
|
var z = index2 / a5;
|
|
var b = index2 - a5 * z;
|
|
var y = b / rx;
|
|
var x = b % rx;
|
|
return [x, y, z];
|
|
}
|
|
function getIndexFrom2D(coords, size) {
|
|
return coords[0] + size[0] * coords[1];
|
|
}
|
|
function get2DFromIndex(index2, columns) {
|
|
var x = index2 % columns;
|
|
var y = Math.floor(index2 / columns);
|
|
return [x, y];
|
|
}
|
|
var misc = Object.freeze({
|
|
__proto__: null,
|
|
clamp: clamp2,
|
|
repeat,
|
|
deltaAngle,
|
|
degToRad,
|
|
radToDeg,
|
|
fibonacciOnSphere,
|
|
vectorEquals,
|
|
lexicographic,
|
|
convexHull,
|
|
remap,
|
|
fade,
|
|
lerp,
|
|
inverseLerp,
|
|
normalize,
|
|
pointOnCubeToPointOnSphere,
|
|
rotateVectorOnVector,
|
|
pointToCoordinate,
|
|
coordinateToPoint,
|
|
planeSegmentIntersection,
|
|
pointToPlaneDistance,
|
|
getIndexFrom3D,
|
|
get3DFromIndex,
|
|
getIndexFrom2D,
|
|
get2DFromIndex
|
|
});
|
|
|
|
// node_modules/maath/dist/vector2-d2bf51f1.esm.js
|
|
function zero() {
|
|
return [0, 0];
|
|
}
|
|
function one() {
|
|
return [1, 1];
|
|
}
|
|
function add(a5, b) {
|
|
return [a5[0] + b[0], a5[1] + b[1]];
|
|
}
|
|
function addValue(a5, n2) {
|
|
return [a5[0] + n2, a5[1] + n2];
|
|
}
|
|
function sub(a5, b) {
|
|
return [a5[0] - b[0], a5[1] - b[1]];
|
|
}
|
|
function subValue(a5, n2) {
|
|
return [a5[0] - n2, a5[1] - n2];
|
|
}
|
|
function scale(a5, n2) {
|
|
return [a5[0] * n2, a5[1] * n2];
|
|
}
|
|
function dot(a5, b) {
|
|
return a5[0] * b[0] + a5[1] * b[1];
|
|
}
|
|
function lengthSqr(a5) {
|
|
return a5[0] * a5[0] + a5[1] * a5[1];
|
|
}
|
|
function length(a5) {
|
|
return Math.sqrt(a5[0] * a5[0] + a5[1] * a5[1]);
|
|
}
|
|
function distance(a5, b) {
|
|
return Math.sqrt((a5[0] - b[0]) * (a5[0] - b[0]) + (a5[1] - b[1]) * (a5[1] - b[1]));
|
|
}
|
|
var vector2 = Object.freeze({
|
|
__proto__: null,
|
|
zero,
|
|
one,
|
|
add,
|
|
addValue,
|
|
sub,
|
|
subValue,
|
|
scale,
|
|
dot,
|
|
lengthSqr,
|
|
length,
|
|
distance
|
|
});
|
|
|
|
// node_modules/maath/dist/vector3-0a088b7f.esm.js
|
|
function zero2() {
|
|
return [0, 0, 0];
|
|
}
|
|
function one2() {
|
|
return [1, 1, 1];
|
|
}
|
|
function add2(a5, b) {
|
|
return [a5[0] + b[0], a5[1] + b[1], a5[2] + b[2]];
|
|
}
|
|
function addValue2(a5, n2) {
|
|
return [a5[0] + n2, a5[1] + n2, a5[2] + n2];
|
|
}
|
|
function sub2(a5, b) {
|
|
return [a5[0] - b[0], a5[1] - b[1], a5[2] - b[2]];
|
|
}
|
|
function subValue2(a5, n2) {
|
|
return [a5[0] - n2, a5[1] - n2, a5[2] - n2];
|
|
}
|
|
function scale2(a5, n2) {
|
|
return [a5[0] * n2, a5[1] * n2, a5[2] * n2];
|
|
}
|
|
function dot2(a5, b) {
|
|
return a5[0] * b[0] + a5[1] * b[1] + a5[2] * b[2];
|
|
}
|
|
function cross(a5, b) {
|
|
var x = a5[1] * b[2] - a5[2] * b[1];
|
|
var y = a5[2] * b[0] - a5[0] * b[2];
|
|
var z = a5[0] * b[1] - a5[1] * b[0];
|
|
return [x, y, z];
|
|
}
|
|
function lengthSqr2(a5) {
|
|
return a5[0] * a5[0] + a5[1] * a5[1] + a5[2] * a5[2];
|
|
}
|
|
function length2(a5) {
|
|
return Math.sqrt(a5[0] * a5[0] + a5[1] * a5[1] + a5[2] * a5[2]);
|
|
}
|
|
function distance2(a5, b) {
|
|
return Math.sqrt((a5[0] - b[0]) * (a5[0] - b[0]) + (a5[1] - b[1]) * (a5[1] - b[1]) + (a5[2] - b[2]) * (a5[2] - b[2]));
|
|
}
|
|
var vector3 = Object.freeze({
|
|
__proto__: null,
|
|
zero: zero2,
|
|
one: one2,
|
|
add: add2,
|
|
addValue: addValue2,
|
|
sub: sub2,
|
|
subValue: subValue2,
|
|
scale: scale2,
|
|
dot: dot2,
|
|
cross,
|
|
lengthSqr: lengthSqr2,
|
|
length: length2,
|
|
distance: distance2
|
|
});
|
|
|
|
// node_modules/maath/dist/buffer-59a95d05.esm.js
|
|
function swizzle(buffer2) {
|
|
var stride = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 3;
|
|
var swizzle2 = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "xyz";
|
|
var o2 = {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
};
|
|
for (var _i = 0; _i < buffer2.length; _i += stride) {
|
|
o2.x = buffer2[_i];
|
|
o2.y = buffer2[_i + 1];
|
|
o2.z = buffer2[_i + 2];
|
|
var _swizzle$split = swizzle2.split(""), _swizzle$split2 = _slicedToArray(_swizzle$split, 3), x = _swizzle$split2[0], y = _swizzle$split2[1], z = _swizzle$split2[2];
|
|
buffer2[_i] = o2[x];
|
|
buffer2[_i + 1] = o2[y];
|
|
if (stride === 3) {
|
|
buffer2[_i + 2] = o2[z];
|
|
}
|
|
}
|
|
return buffer2;
|
|
}
|
|
function addAxis(buffer2, size) {
|
|
var valueGenerator = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : function() {
|
|
return Math.random();
|
|
};
|
|
var newSize = size + 1;
|
|
var newBuffer = new Float32Array(buffer2.length / size * newSize);
|
|
for (var _i2 = 0; _i2 < buffer2.length; _i2 += size) {
|
|
var _j = _i2 / size * newSize;
|
|
newBuffer[_j] = buffer2[_i2];
|
|
newBuffer[_j + 1] = buffer2[_i2 + 1];
|
|
if (size === 2) {
|
|
newBuffer[_j + 2] = valueGenerator(_j);
|
|
}
|
|
if (size === 3) {
|
|
newBuffer[_j + 2] = buffer2[_i2 + 2];
|
|
newBuffer[_j + 3] = valueGenerator(_j);
|
|
}
|
|
}
|
|
return newBuffer;
|
|
}
|
|
function lerp2(bufferA, bufferB, _final, t2) {
|
|
for (var _i3 = 0; _i3 < bufferA.length; _i3++) {
|
|
_final[_i3] = lerp(bufferA[_i3], bufferB[_i3], t2);
|
|
}
|
|
}
|
|
function translate(buffer2, translationVector) {
|
|
var stride = translationVector.length;
|
|
for (var _i4 = 0; _i4 < buffer2.length; _i4 += stride) {
|
|
buffer2[_i4] += translationVector[0];
|
|
buffer2[_i4 + 1] += translationVector[1];
|
|
buffer2[_i4 + 2] += translationVector[2];
|
|
}
|
|
return buffer2;
|
|
}
|
|
function rotate(buffer2, rotation3) {
|
|
var defaultRotation = {
|
|
center: [0, 0, 0],
|
|
q: new Quaternion().identity()
|
|
};
|
|
var v5 = new Vector3();
|
|
var _defaultRotation$rota = _objectSpread22(_objectSpread22({}, defaultRotation), rotation3), q = _defaultRotation$rota.q, center2 = _defaultRotation$rota.center;
|
|
for (var _i5 = 0; _i5 < buffer2.length; _i5 += 3) {
|
|
v5.set(buffer2[_i5] - center2[0], buffer2[_i5 + 1] - center2[1], buffer2[_i5 + 2] - center2[2]);
|
|
v5.applyQuaternion(q);
|
|
buffer2[_i5] = v5.x + center2[0];
|
|
buffer2[_i5 + 1] = v5.y + center2[1];
|
|
buffer2[_i5 + 2] = v5.z + center2[1];
|
|
}
|
|
return buffer2;
|
|
}
|
|
function map(buffer2, stride, callback) {
|
|
for (var _i6 = 0, _j2 = 0; _i6 < buffer2.length; _i6 += stride, _j2++) {
|
|
if (stride === 3) {
|
|
var res = callback([buffer2[_i6], buffer2[_i6 + 1], buffer2[_i6 + 2]], _j2);
|
|
buffer2.set(res, _i6);
|
|
} else {
|
|
buffer2.set(callback([buffer2[_i6], buffer2[_i6 + 1]], _j2), _i6);
|
|
}
|
|
}
|
|
return buffer2;
|
|
}
|
|
function reduce(b, stride, callback, acc) {
|
|
for (var _i7 = 0, _j3 = 0; _i7 < b.length; _i7 += stride, _j3++) {
|
|
if (stride === 2) {
|
|
acc = callback(acc, [b[_i7], b[_i7 + 1]], _j3);
|
|
} else {
|
|
acc = callback(acc, [b[_i7], b[_i7 + 1], b[_i7 + 2]], _j3);
|
|
}
|
|
}
|
|
return acc;
|
|
}
|
|
function expand(b, stride, opts) {
|
|
var defaultExpandOptions = {
|
|
center: [0, 0, 0]
|
|
};
|
|
var _defaultExpandOptions = _objectSpread22(_objectSpread22({}, defaultExpandOptions), opts), center2 = _defaultExpandOptions.center, distance3 = _defaultExpandOptions.distance;
|
|
for (var _i8 = 0; _i8 < b.length; _i8 += stride) {
|
|
b[_i8] = (b[_i8] - center2[0]) * (1 + distance3) + center2[0];
|
|
b[_i8 + 1] = (b[_i8 + 1] - center2[1]) * (1 + distance3) + center2[1];
|
|
if (stride === 3) {
|
|
b[_i8 + 2] = (b[_i8 + 2] - center2[1]) * (1 + distance3) + center2[2];
|
|
}
|
|
}
|
|
return b;
|
|
}
|
|
function center(myBuffer, stride) {
|
|
return reduce(myBuffer, stride, function(acc, point) {
|
|
if (stride === 3) {
|
|
acc = add2(acc, point);
|
|
} else {
|
|
acc = add(acc, point);
|
|
}
|
|
return acc;
|
|
}, zero());
|
|
}
|
|
function sort(myBuffer, stride, callback) {
|
|
var indices = Int16Array.from({
|
|
length: myBuffer.length / stride
|
|
}, function(_, i3) {
|
|
return i3;
|
|
});
|
|
indices.sort(function(a5, b) {
|
|
var pa = myBuffer.slice(a5 * stride, a5 * stride + stride);
|
|
var pb = myBuffer.slice(b * stride, b * stride + stride);
|
|
return callback(pa, pb);
|
|
});
|
|
var prevBuffer = myBuffer.slice(0);
|
|
for (var _i9 = 0; _i9 < indices.length; _i9++) {
|
|
var _j4 = indices[_i9];
|
|
myBuffer.set(prevBuffer.slice(_j4 * stride, _j4 * stride + stride), _i9 * 3);
|
|
}
|
|
return myBuffer;
|
|
}
|
|
var buffer = Object.freeze({
|
|
__proto__: null,
|
|
swizzle,
|
|
addAxis,
|
|
lerp: lerp2,
|
|
translate,
|
|
rotate,
|
|
map,
|
|
reduce,
|
|
expand,
|
|
center,
|
|
sort
|
|
});
|
|
|
|
// node_modules/maath/dist/classCallCheck-9098b006.esm.js
|
|
function _classCallCheck(instance, Constructor) {
|
|
if (!(instance instanceof Constructor)) {
|
|
throw new TypeError("Cannot call a class as a function");
|
|
}
|
|
}
|
|
|
|
// node_modules/maath/dist/index-0332b2ed.esm.js
|
|
function _defineProperties(target2, props) {
|
|
for (var i3 = 0; i3 < props.length; i3++) {
|
|
var descriptor = props[i3];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
if ("value" in descriptor) descriptor.writable = true;
|
|
Object.defineProperty(target2, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
var Grad = function Grad2(x, y, z) {
|
|
var _this = this;
|
|
_classCallCheck(this, Grad2);
|
|
_defineProperty2(this, "dot2", function(x2, y2) {
|
|
return _this.x * x2 + _this.y * y2;
|
|
});
|
|
_defineProperty2(this, "dot3", function(x2, y2, z2) {
|
|
return _this.x * x2 + _this.y * y2 + _this.z * z2;
|
|
});
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
};
|
|
var grad3 = [new Grad(1, 1, 0), new Grad(-1, 1, 0), new Grad(1, -1, 0), new Grad(-1, -1, 0), new Grad(1, 0, 1), new Grad(-1, 0, 1), new Grad(1, 0, -1), new Grad(-1, 0, -1), new Grad(0, 1, 1), new Grad(0, -1, 1), new Grad(0, 1, -1), new Grad(0, -1, -1)];
|
|
var p = [151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180];
|
|
var perm = new Array(512);
|
|
var gradP = new Array(512);
|
|
var seed = function seed2(_seed) {
|
|
if (_seed > 0 && _seed < 1) {
|
|
_seed *= 65536;
|
|
}
|
|
_seed = Math.floor(_seed);
|
|
if (_seed < 256) {
|
|
_seed |= _seed << 8;
|
|
}
|
|
for (var i3 = 0; i3 < 256; i3++) {
|
|
var v5;
|
|
if (i3 & 1) {
|
|
v5 = p[i3] ^ _seed & 255;
|
|
} else {
|
|
v5 = p[i3] ^ _seed >> 8 & 255;
|
|
}
|
|
perm[i3] = perm[i3 + 256] = v5;
|
|
gradP[i3] = gradP[i3 + 256] = grad3[v5 % 12];
|
|
}
|
|
};
|
|
seed(0);
|
|
var F2 = 0.5 * (Math.sqrt(3) - 1);
|
|
var G2 = (3 - Math.sqrt(3)) / 6;
|
|
var F3 = 1 / 3;
|
|
var G3 = 1 / 6;
|
|
var simplex2 = function simplex22(xin, yin) {
|
|
var n0, n1, n2;
|
|
var s2 = (xin + yin) * F2;
|
|
var i3 = Math.floor(xin + s2);
|
|
var j = Math.floor(yin + s2);
|
|
var t2 = (i3 + j) * G2;
|
|
var x0 = xin - i3 + t2;
|
|
var y0 = yin - j + t2;
|
|
var i1, j1;
|
|
if (x0 > y0) {
|
|
i1 = 1;
|
|
j1 = 0;
|
|
} else {
|
|
i1 = 0;
|
|
j1 = 1;
|
|
}
|
|
var x1 = x0 - i1 + G2;
|
|
var y1 = y0 - j1 + G2;
|
|
var x2 = x0 - 1 + 2 * G2;
|
|
var y2 = y0 - 1 + 2 * G2;
|
|
i3 &= 255;
|
|
j &= 255;
|
|
var gi0 = gradP[i3 + perm[j]];
|
|
var gi1 = gradP[i3 + i1 + perm[j + j1]];
|
|
var gi2 = gradP[i3 + 1 + perm[j + 1]];
|
|
var t0 = 0.5 - x0 * x0 - y0 * y0;
|
|
if (t0 < 0) {
|
|
n0 = 0;
|
|
} else {
|
|
t0 *= t0;
|
|
n0 = t0 * t0 * gi0.dot2(x0, y0);
|
|
}
|
|
var t1 = 0.5 - x1 * x1 - y1 * y1;
|
|
if (t1 < 0) {
|
|
n1 = 0;
|
|
} else {
|
|
t1 *= t1;
|
|
n1 = t1 * t1 * gi1.dot2(x1, y1);
|
|
}
|
|
var t22 = 0.5 - x2 * x2 - y2 * y2;
|
|
if (t22 < 0) {
|
|
n2 = 0;
|
|
} else {
|
|
t22 *= t22;
|
|
n2 = t22 * t22 * gi2.dot2(x2, y2);
|
|
}
|
|
return 70 * (n0 + n1 + n2);
|
|
};
|
|
var simplex3 = function simplex32(xin, yin, zin) {
|
|
var n0, n1, n2, n3;
|
|
var s2 = (xin + yin + zin) * F3;
|
|
var i3 = Math.floor(xin + s2);
|
|
var j = Math.floor(yin + s2);
|
|
var k = Math.floor(zin + s2);
|
|
var t2 = (i3 + j + k) * G3;
|
|
var x0 = xin - i3 + t2;
|
|
var y0 = yin - j + t2;
|
|
var z0 = zin - k + t2;
|
|
var i1, j1, k1;
|
|
var i22, j2, k2;
|
|
if (x0 >= y0) {
|
|
if (y0 >= z0) {
|
|
i1 = 1;
|
|
j1 = 0;
|
|
k1 = 0;
|
|
i22 = 1;
|
|
j2 = 1;
|
|
k2 = 0;
|
|
} else if (x0 >= z0) {
|
|
i1 = 1;
|
|
j1 = 0;
|
|
k1 = 0;
|
|
i22 = 1;
|
|
j2 = 0;
|
|
k2 = 1;
|
|
} else {
|
|
i1 = 0;
|
|
j1 = 0;
|
|
k1 = 1;
|
|
i22 = 1;
|
|
j2 = 0;
|
|
k2 = 1;
|
|
}
|
|
} else {
|
|
if (y0 < z0) {
|
|
i1 = 0;
|
|
j1 = 0;
|
|
k1 = 1;
|
|
i22 = 0;
|
|
j2 = 1;
|
|
k2 = 1;
|
|
} else if (x0 < z0) {
|
|
i1 = 0;
|
|
j1 = 1;
|
|
k1 = 0;
|
|
i22 = 0;
|
|
j2 = 1;
|
|
k2 = 1;
|
|
} else {
|
|
i1 = 0;
|
|
j1 = 1;
|
|
k1 = 0;
|
|
i22 = 1;
|
|
j2 = 1;
|
|
k2 = 0;
|
|
}
|
|
}
|
|
var x1 = x0 - i1 + G3;
|
|
var y1 = y0 - j1 + G3;
|
|
var z1 = z0 - k1 + G3;
|
|
var x2 = x0 - i22 + 2 * G3;
|
|
var y2 = y0 - j2 + 2 * G3;
|
|
var z2 = z0 - k2 + 2 * G3;
|
|
var x3 = x0 - 1 + 3 * G3;
|
|
var y3 = y0 - 1 + 3 * G3;
|
|
var z3 = z0 - 1 + 3 * G3;
|
|
i3 &= 255;
|
|
j &= 255;
|
|
k &= 255;
|
|
var gi0 = gradP[i3 + perm[j + perm[k]]];
|
|
var gi1 = gradP[i3 + i1 + perm[j + j1 + perm[k + k1]]];
|
|
var gi2 = gradP[i3 + i22 + perm[j + j2 + perm[k + k2]]];
|
|
var gi3 = gradP[i3 + 1 + perm[j + 1 + perm[k + 1]]];
|
|
var t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
|
|
if (t0 < 0) {
|
|
n0 = 0;
|
|
} else {
|
|
t0 *= t0;
|
|
n0 = t0 * t0 * gi0.dot3(x0, y0, z0);
|
|
}
|
|
var t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
|
|
if (t1 < 0) {
|
|
n1 = 0;
|
|
} else {
|
|
t1 *= t1;
|
|
n1 = t1 * t1 * gi1.dot3(x1, y1, z1);
|
|
}
|
|
var t22 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;
|
|
if (t22 < 0) {
|
|
n2 = 0;
|
|
} else {
|
|
t22 *= t22;
|
|
n2 = t22 * t22 * gi2.dot3(x2, y2, z2);
|
|
}
|
|
var t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;
|
|
if (t3 < 0) {
|
|
n3 = 0;
|
|
} else {
|
|
t3 *= t3;
|
|
n3 = t3 * t3 * gi3.dot3(x3, y3, z3);
|
|
}
|
|
return 32 * (n0 + n1 + n2 + n3);
|
|
};
|
|
var perlin2 = function perlin22(x, y) {
|
|
var X = Math.floor(x), Y = Math.floor(y);
|
|
x = x - X;
|
|
y = y - Y;
|
|
X = X & 255;
|
|
Y = Y & 255;
|
|
var n00 = gradP[X + perm[Y]].dot2(x, y);
|
|
var n01 = gradP[X + perm[Y + 1]].dot2(x, y - 1);
|
|
var n10 = gradP[X + 1 + perm[Y]].dot2(x - 1, y);
|
|
var n11 = gradP[X + 1 + perm[Y + 1]].dot2(x - 1, y - 1);
|
|
var u = fade(x);
|
|
return lerp(lerp(n00, n10, u), lerp(n01, n11, u), fade(y));
|
|
};
|
|
var perlin3 = function perlin32(x, y, z) {
|
|
var X = Math.floor(x), Y = Math.floor(y), Z = Math.floor(z);
|
|
x = x - X;
|
|
y = y - Y;
|
|
z = z - Z;
|
|
X = X & 255;
|
|
Y = Y & 255;
|
|
Z = Z & 255;
|
|
var n000 = gradP[X + perm[Y + perm[Z]]].dot3(x, y, z);
|
|
var n001 = gradP[X + perm[Y + perm[Z + 1]]].dot3(x, y, z - 1);
|
|
var n010 = gradP[X + perm[Y + 1 + perm[Z]]].dot3(x, y - 1, z);
|
|
var n011 = gradP[X + perm[Y + 1 + perm[Z + 1]]].dot3(x, y - 1, z - 1);
|
|
var n100 = gradP[X + 1 + perm[Y + perm[Z]]].dot3(x - 1, y, z);
|
|
var n101 = gradP[X + 1 + perm[Y + perm[Z + 1]]].dot3(x - 1, y, z - 1);
|
|
var n110 = gradP[X + 1 + perm[Y + 1 + perm[Z]]].dot3(x - 1, y - 1, z);
|
|
var n111 = gradP[X + 1 + perm[Y + 1 + perm[Z + 1]]].dot3(x - 1, y - 1, z - 1);
|
|
var u = fade(x);
|
|
var v5 = fade(y);
|
|
var w = fade(z);
|
|
return lerp(lerp(lerp(n000, n100, u), lerp(n001, n101, u), w), lerp(lerp(n010, n110, u), lerp(n011, n111, u), w), v5);
|
|
};
|
|
var noise = Object.freeze({
|
|
__proto__: null,
|
|
seed,
|
|
simplex2,
|
|
simplex3,
|
|
perlin2,
|
|
perlin3
|
|
});
|
|
var TAU = Math.PI * 2;
|
|
var FlashGen = (function() {
|
|
function FlashGen2(props) {
|
|
_classCallCheck(this, FlashGen2);
|
|
_defineProperty2(this, "nextBurstTime", 0);
|
|
_defineProperty2(this, "nextFlashEndTime", 0);
|
|
_defineProperty2(this, "flashesDone", 0);
|
|
_defineProperty2(this, "isFlashing", false);
|
|
_defineProperty2(this, "currentCount", 0);
|
|
_defineProperty2(this, "flashIntensity", 0);
|
|
_defineProperty2(this, "isDecaying", false);
|
|
_defineProperty2(this, "autoBurst", true);
|
|
_defineProperty2(this, "decaySpeed", 40);
|
|
_defineProperty2(this, "minInterval", 5e3);
|
|
_defineProperty2(this, "maxInterval", 1e4);
|
|
_defineProperty2(this, "minDuration", 50);
|
|
_defineProperty2(this, "maxDuration", 300);
|
|
_defineProperty2(this, "count", 5);
|
|
Object.assign(this, props);
|
|
}
|
|
_createClass(FlashGen2, [{
|
|
key: "scheduleNextBurst",
|
|
value: function scheduleNextBurst(currentTime) {
|
|
var burstInterval = Math.random() * (this.maxInterval - this.minInterval) + this.minInterval;
|
|
this.nextBurstTime = currentTime + burstInterval / 1e3;
|
|
this.flashesDone = 0;
|
|
this.isFlashing = false;
|
|
}
|
|
}, {
|
|
key: "burst",
|
|
value: function burst() {
|
|
this.nextBurstTime = 0;
|
|
this.flashesDone = 0;
|
|
this.isFlashing = false;
|
|
}
|
|
}, {
|
|
key: "update",
|
|
value: function update2(currentTime, delta) {
|
|
if (currentTime > this.nextBurstTime && this.currentCount === 0) {
|
|
this.currentCount = Math.floor(Math.random() * this.count) + 1;
|
|
}
|
|
if (this.flashesDone < this.currentCount && currentTime > this.nextBurstTime) {
|
|
if (!this.isFlashing) {
|
|
this.isFlashing = true;
|
|
this.flashIntensity = 1;
|
|
var flashDuration = Math.random() * (this.maxDuration - this.minDuration) + this.minDuration;
|
|
this.nextFlashEndTime = currentTime + flashDuration / 1e3;
|
|
} else if (this.isFlashing && currentTime > this.nextFlashEndTime) {
|
|
this.isFlashing = false;
|
|
this.isDecaying = true;
|
|
this.flashesDone++;
|
|
if (this.flashesDone >= this.currentCount) {
|
|
this.currentCount = 0;
|
|
if (this.autoBurst) this.scheduleNextBurst(currentTime);
|
|
}
|
|
}
|
|
}
|
|
if (this.isDecaying) {
|
|
this.flashIntensity -= delta * this.decaySpeed;
|
|
this.flashIntensity = Math.max(0, Math.min(1, this.flashIntensity));
|
|
if (this.flashIntensity <= 0) {
|
|
this.isDecaying = false;
|
|
this.flashIntensity = 0;
|
|
}
|
|
}
|
|
return this.flashIntensity;
|
|
}
|
|
}]);
|
|
return FlashGen2;
|
|
})();
|
|
function normalizeSeed(seed3) {
|
|
if (typeof seed3 === "number") {
|
|
seed3 = Math.abs(seed3);
|
|
} else if (typeof seed3 === "string") {
|
|
var string = seed3;
|
|
seed3 = 0;
|
|
for (var i3 = 0; i3 < string.length; i3++) {
|
|
seed3 = (seed3 + (i3 + 1) * (string.charCodeAt(i3) % 96)) % 2147483647;
|
|
}
|
|
}
|
|
if (seed3 === 0) {
|
|
seed3 = 311;
|
|
}
|
|
return seed3;
|
|
}
|
|
function lcgRandom(seed3) {
|
|
var state = normalizeSeed(seed3);
|
|
return function() {
|
|
var result = state * 48271 % 2147483647;
|
|
state = result;
|
|
return result / 2147483647;
|
|
};
|
|
}
|
|
var Generator = function Generator2(_seed) {
|
|
var _this = this;
|
|
_classCallCheck(this, Generator2);
|
|
_defineProperty2(this, "seed", 0);
|
|
_defineProperty2(this, "init", function(seed3) {
|
|
_this.seed = seed3;
|
|
_this.value = lcgRandom(seed3);
|
|
});
|
|
_defineProperty2(this, "value", lcgRandom(this.seed));
|
|
this.init(_seed);
|
|
};
|
|
var defaultGen = new Generator(Math.random());
|
|
var defaultSphere = {
|
|
radius: 1,
|
|
center: [0, 0, 0]
|
|
};
|
|
function onSphere(buffer2, sphere) {
|
|
var rng = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : defaultGen;
|
|
var _defaultSphere$sphere = _objectSpread22(_objectSpread22({}, defaultSphere), sphere), radius = _defaultSphere$sphere.radius, center2 = _defaultSphere$sphere.center;
|
|
for (var i3 = 0; i3 < buffer2.length; i3 += 3) {
|
|
var u = rng.value();
|
|
var v5 = rng.value();
|
|
var theta = Math.acos(2 * v5 - 1);
|
|
var phi = TAU * u;
|
|
buffer2[i3] = Math.sin(theta) * Math.cos(phi) * radius + center2[0];
|
|
buffer2[i3 + 1] = Math.sin(theta) * Math.sin(phi) * radius + center2[1];
|
|
buffer2[i3 + 2] = Math.cos(theta) * radius + center2[2];
|
|
}
|
|
return buffer2;
|
|
}
|
|
function inSphere(buffer2, sphere) {
|
|
var rng = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : defaultGen;
|
|
var _defaultSphere$sphere2 = _objectSpread22(_objectSpread22({}, defaultSphere), sphere), radius = _defaultSphere$sphere2.radius, center2 = _defaultSphere$sphere2.center;
|
|
for (var i3 = 0; i3 < buffer2.length; i3 += 3) {
|
|
var u = Math.pow(rng.value(), 1 / 3);
|
|
var x = rng.value() * 2 - 1;
|
|
var y = rng.value() * 2 - 1;
|
|
var z = rng.value() * 2 - 1;
|
|
var mag = Math.sqrt(x * x + y * y + z * z);
|
|
x = u * x / mag;
|
|
y = u * y / mag;
|
|
z = u * z / mag;
|
|
buffer2[i3] = x * radius + center2[0];
|
|
buffer2[i3 + 1] = y * radius + center2[1];
|
|
buffer2[i3 + 2] = z * radius + center2[2];
|
|
}
|
|
return buffer2;
|
|
}
|
|
var defaultCircle = {
|
|
radius: 1,
|
|
center: [0, 0]
|
|
};
|
|
function inCircle(buffer2, circle) {
|
|
var rng = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : defaultGen;
|
|
var _defaultCircle$circle = _objectSpread22(_objectSpread22({}, defaultCircle), circle), radius = _defaultCircle$circle.radius, center2 = _defaultCircle$circle.center;
|
|
for (var i3 = 0; i3 < buffer2.length; i3 += 2) {
|
|
var r2 = radius * Math.sqrt(rng.value());
|
|
var theta = rng.value() * TAU;
|
|
buffer2[i3] = Math.sin(theta) * r2 + center2[0];
|
|
buffer2[i3 + 1] = Math.cos(theta) * r2 + center2[1];
|
|
}
|
|
return buffer2;
|
|
}
|
|
function onCircle(buffer2, circle) {
|
|
var rng = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : defaultGen;
|
|
var _defaultCircle$circle2 = _objectSpread22(_objectSpread22({}, defaultCircle), circle), radius = _defaultCircle$circle2.radius, center2 = _defaultCircle$circle2.center;
|
|
for (var i3 = 0; i3 < buffer2.length; i3 += 2) {
|
|
var theta = rng.value() * TAU;
|
|
buffer2[i3] = Math.sin(theta) * radius + center2[0];
|
|
buffer2[i3 + 1] = Math.cos(theta) * radius + center2[1];
|
|
}
|
|
return buffer2;
|
|
}
|
|
var defaultRect = {
|
|
sides: 1,
|
|
center: [0, 0]
|
|
};
|
|
function inRect(buffer2, rect) {
|
|
var rng = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : defaultGen;
|
|
var _defaultRect$rect = _objectSpread22(_objectSpread22({}, defaultRect), rect), sides = _defaultRect$rect.sides, center2 = _defaultRect$rect.center;
|
|
var sideX = typeof sides === "number" ? sides : sides[0];
|
|
var sideY = typeof sides === "number" ? sides : sides[1];
|
|
for (var i3 = 0; i3 < buffer2.length; i3 += 2) {
|
|
buffer2[i3] = (rng.value() - 0.5) * sideX + center2[0];
|
|
buffer2[i3 + 1] = (rng.value() - 0.5) * sideY + center2[1];
|
|
}
|
|
return buffer2;
|
|
}
|
|
function onRect(buffer2, rect) {
|
|
return buffer2;
|
|
}
|
|
function inBox(buffer2, box) {
|
|
var rng = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : defaultGen;
|
|
var _defaultBox$box = _objectSpread22(_objectSpread22({}, defaultBox), box), sides = _defaultBox$box.sides, center2 = _defaultBox$box.center;
|
|
var sideX = typeof sides === "number" ? sides : sides[0];
|
|
var sideY = typeof sides === "number" ? sides : sides[1];
|
|
var sideZ = typeof sides === "number" ? sides : sides[2];
|
|
for (var i3 = 0; i3 < buffer2.length; i3 += 3) {
|
|
buffer2[i3] = (rng.value() - 0.5) * sideX + center2[0];
|
|
buffer2[i3 + 1] = (rng.value() - 0.5) * sideY + center2[1];
|
|
buffer2[i3 + 2] = (rng.value() - 0.5) * sideZ + center2[2];
|
|
}
|
|
return buffer2;
|
|
}
|
|
var defaultBox = {
|
|
sides: 1,
|
|
center: [0, 0, 0]
|
|
};
|
|
function onBox(buffer2, box) {
|
|
var rng = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : defaultGen;
|
|
var _defaultBox$box2 = _objectSpread22(_objectSpread22({}, defaultBox), box), sides = _defaultBox$box2.sides, center2 = _defaultBox$box2.center;
|
|
var sideX = typeof sides === "number" ? sides : sides[0];
|
|
var sideY = typeof sides === "number" ? sides : sides[1];
|
|
var sideZ = typeof sides === "number" ? sides : sides[2];
|
|
for (var i3 = 0; i3 < buffer2.length; i3 += 3) {
|
|
buffer2[i3] = (rng.value() - 0.5) * sideX + center2[0];
|
|
buffer2[i3 + 1] = (rng.value() - 0.5) * sideY + center2[1];
|
|
buffer2[i3 + 2] = (rng.value() - 0.5) * sideZ + center2[2];
|
|
}
|
|
return buffer2;
|
|
}
|
|
var index = Object.freeze({
|
|
__proto__: null,
|
|
FlashGen,
|
|
Generator,
|
|
onSphere,
|
|
inSphere,
|
|
inCircle,
|
|
onCircle,
|
|
inRect,
|
|
onRect,
|
|
inBox,
|
|
onBox,
|
|
noise
|
|
});
|
|
|
|
// node_modules/maath/dist/easing-0f4db1c0.esm.js
|
|
var rsqw = function rsqw2(t2) {
|
|
var delta = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 0.01;
|
|
var a5 = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : 1;
|
|
var f2 = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : 1 / (2 * Math.PI);
|
|
return a5 / Math.atan(1 / delta) * Math.atan(Math.sin(2 * Math.PI * t2 * f2) / delta);
|
|
};
|
|
var exp = function exp2(t2) {
|
|
return 1 / (1 + t2 + 0.48 * t2 * t2 + 0.235 * t2 * t2 * t2);
|
|
};
|
|
var linear = function linear2(t2) {
|
|
return t2;
|
|
};
|
|
var sine = {
|
|
"in": function _in(x) {
|
|
return 1 - Math.cos(x * Math.PI / 2);
|
|
},
|
|
out: function out(x) {
|
|
return Math.sin(x * Math.PI / 2);
|
|
},
|
|
inOut: function inOut(x) {
|
|
return -(Math.cos(Math.PI * x) - 1) / 2;
|
|
}
|
|
};
|
|
var cubic = {
|
|
"in": function _in2(x) {
|
|
return x * x * x;
|
|
},
|
|
out: function out2(x) {
|
|
return 1 - Math.pow(1 - x, 3);
|
|
},
|
|
inOut: function inOut2(x) {
|
|
return x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;
|
|
}
|
|
};
|
|
var quint = {
|
|
"in": function _in3(x) {
|
|
return x * x * x * x * x;
|
|
},
|
|
out: function out3(x) {
|
|
return 1 - Math.pow(1 - x, 5);
|
|
},
|
|
inOut: function inOut3(x) {
|
|
return x < 0.5 ? 16 * x * x * x * x * x : 1 - Math.pow(-2 * x + 2, 5) / 2;
|
|
}
|
|
};
|
|
var circ = {
|
|
"in": function _in4(x) {
|
|
return 1 - Math.sqrt(1 - Math.pow(x, 2));
|
|
},
|
|
out: function out4(x) {
|
|
return Math.sqrt(1 - Math.pow(x - 1, 2));
|
|
},
|
|
inOut: function inOut4(x) {
|
|
return x < 0.5 ? (1 - Math.sqrt(1 - Math.pow(2 * x, 2))) / 2 : (Math.sqrt(1 - Math.pow(-2 * x + 2, 2)) + 1) / 2;
|
|
}
|
|
};
|
|
var quart = {
|
|
"in": function _in5(t2) {
|
|
return t2 * t2 * t2 * t2;
|
|
},
|
|
out: function out5(t2) {
|
|
return 1 - --t2 * t2 * t2 * t2;
|
|
},
|
|
inOut: function inOut5(t2) {
|
|
return t2 < 0.5 ? 8 * t2 * t2 * t2 * t2 : 1 - 8 * --t2 * t2 * t2 * t2;
|
|
}
|
|
};
|
|
var expo = {
|
|
"in": function _in6(x) {
|
|
return x === 0 ? 0 : Math.pow(2, 10 * x - 10);
|
|
},
|
|
out: function out6(x) {
|
|
return x === 1 ? 1 : 1 - Math.pow(2, -10 * x);
|
|
},
|
|
inOut: function inOut6(x) {
|
|
return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? Math.pow(2, 20 * x - 10) / 2 : (2 - Math.pow(2, -20 * x + 10)) / 2;
|
|
}
|
|
};
|
|
function damp(current, prop, target2) {
|
|
var smoothTime = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : 0.25;
|
|
var delta = arguments.length > 4 && arguments[4] !== void 0 ? arguments[4] : 0.01;
|
|
var maxSpeed = arguments.length > 5 && arguments[5] !== void 0 ? arguments[5] : Infinity;
|
|
var easing2 = arguments.length > 6 && arguments[6] !== void 0 ? arguments[6] : exp;
|
|
var eps2 = arguments.length > 7 && arguments[7] !== void 0 ? arguments[7] : 1e-3;
|
|
var vel = "velocity_" + prop;
|
|
if (current.__damp === void 0) current.__damp = {};
|
|
if (current.__damp[vel] === void 0) current.__damp[vel] = 0;
|
|
if (Math.abs(current[prop] - target2) <= eps2) {
|
|
current[prop] = target2;
|
|
return false;
|
|
}
|
|
smoothTime = Math.max(1e-4, smoothTime);
|
|
var omega = 2 / smoothTime;
|
|
var t2 = easing2(omega * delta);
|
|
var change = current[prop] - target2;
|
|
var originalTo = target2;
|
|
var maxChange = maxSpeed * smoothTime;
|
|
change = Math.min(Math.max(change, -maxChange), maxChange);
|
|
target2 = current[prop] - change;
|
|
var temp5 = (current.__damp[vel] + omega * change) * delta;
|
|
current.__damp[vel] = (current.__damp[vel] - omega * temp5) * t2;
|
|
var output = target2 + (change + temp5) * t2;
|
|
if (originalTo - current[prop] > 0 === output > originalTo) {
|
|
output = originalTo;
|
|
current.__damp[vel] = (output - originalTo) / delta;
|
|
}
|
|
current[prop] = output;
|
|
return true;
|
|
}
|
|
var isCamera = function isCamera2(v5) {
|
|
return v5 && v5.isCamera;
|
|
};
|
|
var isLight = function isLight2(v5) {
|
|
return v5 && v5.isLight;
|
|
};
|
|
var vl3d = new Vector3();
|
|
var _q1 = new Quaternion();
|
|
var _q2 = new Quaternion();
|
|
var _m1 = new Matrix4();
|
|
var _position = new Vector3();
|
|
function dampLookAt(current, target2, smoothTime, delta, maxSpeed, easing2, eps2) {
|
|
if (typeof target2 === "number") vl3d.setScalar(target2);
|
|
else if (Array.isArray(target2)) vl3d.set(target2[0], target2[1], target2[2]);
|
|
else vl3d.copy(target2);
|
|
var parent = current.parent;
|
|
current.updateWorldMatrix(true, false);
|
|
_position.setFromMatrixPosition(current.matrixWorld);
|
|
if (isCamera(current) || isLight(current)) _m1.lookAt(_position, vl3d, current.up);
|
|
else _m1.lookAt(vl3d, _position, current.up);
|
|
dampQ(current.quaternion, _q2.setFromRotationMatrix(_m1), smoothTime, delta, maxSpeed, easing2, eps2);
|
|
if (parent) {
|
|
_m1.extractRotation(parent.matrixWorld);
|
|
_q1.setFromRotationMatrix(_m1);
|
|
dampQ(current.quaternion, _q2.copy(current.quaternion).premultiply(_q1.invert()), smoothTime, delta, maxSpeed, easing2, eps2);
|
|
}
|
|
}
|
|
function dampAngle(current, prop, target2, smoothTime, delta, maxSpeed, easing2, eps2) {
|
|
return damp(current, prop, current[prop] + deltaAngle(current[prop], target2), smoothTime, delta, maxSpeed, easing2, eps2);
|
|
}
|
|
var v2d = new Vector2();
|
|
var a2;
|
|
var b2;
|
|
function damp2(current, target2, smoothTime, delta, maxSpeed, easing2, eps2) {
|
|
if (typeof target2 === "number") v2d.setScalar(target2);
|
|
else if (Array.isArray(target2)) v2d.set(target2[0], target2[1]);
|
|
else v2d.copy(target2);
|
|
a2 = damp(current, "x", v2d.x, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
b2 = damp(current, "y", v2d.y, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
return a2 || b2;
|
|
}
|
|
var v3d = new Vector3();
|
|
var a3;
|
|
var b3;
|
|
var c3;
|
|
function damp3(current, target2, smoothTime, delta, maxSpeed, easing2, eps2) {
|
|
if (typeof target2 === "number") v3d.setScalar(target2);
|
|
else if (Array.isArray(target2)) v3d.set(target2[0], target2[1], target2[2]);
|
|
else v3d.copy(target2);
|
|
a3 = damp(current, "x", v3d.x, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
b3 = damp(current, "y", v3d.y, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
c3 = damp(current, "z", v3d.z, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
return a3 || b3 || c3;
|
|
}
|
|
var v4d = new Vector4();
|
|
var a4;
|
|
var b4;
|
|
var c4;
|
|
var d4;
|
|
function damp4(current, target2, smoothTime, delta, maxSpeed, easing2, eps2) {
|
|
if (typeof target2 === "number") v4d.setScalar(target2);
|
|
else if (Array.isArray(target2)) v4d.set(target2[0], target2[1], target2[2], target2[3]);
|
|
else v4d.copy(target2);
|
|
a4 = damp(current, "x", v4d.x, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
b4 = damp(current, "y", v4d.y, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
c4 = damp(current, "z", v4d.z, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
d4 = damp(current, "w", v4d.w, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
return a4 || b4 || c4 || d4;
|
|
}
|
|
var rot = new Euler();
|
|
var aE;
|
|
var bE;
|
|
var cE;
|
|
function dampE(current, target2, smoothTime, delta, maxSpeed, easing2, eps2) {
|
|
if (Array.isArray(target2)) rot.set(target2[0], target2[1], target2[2], target2[3]);
|
|
else rot.copy(target2);
|
|
aE = dampAngle(current, "x", rot.x, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
bE = dampAngle(current, "y", rot.y, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
cE = dampAngle(current, "z", rot.z, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
return aE || bE || cE;
|
|
}
|
|
var col = new Color();
|
|
var aC;
|
|
var bC;
|
|
var cC;
|
|
function dampC(current, target2, smoothTime, delta, maxSpeed, easing2, eps2) {
|
|
if (target2 instanceof Color) col.copy(target2);
|
|
else if (Array.isArray(target2)) col.setRGB(target2[0], target2[1], target2[2]);
|
|
else col.set(target2);
|
|
aC = damp(current, "r", col.r, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
bC = damp(current, "g", col.g, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
cC = damp(current, "b", col.b, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
return aC || bC || cC;
|
|
}
|
|
var qt = new Quaternion();
|
|
var v4result = new Vector4();
|
|
var v4velocity = new Vector4();
|
|
var v4error = new Vector4();
|
|
var aQ;
|
|
var bQ;
|
|
var cQ;
|
|
var dQ;
|
|
function dampQ(current, target2, smoothTime, delta, maxSpeed, easing2, eps2) {
|
|
var cur = current;
|
|
if (Array.isArray(target2)) qt.set(target2[0], target2[1], target2[2], target2[3]);
|
|
else qt.copy(target2);
|
|
var multi = current.dot(qt) > 0 ? 1 : -1;
|
|
qt.x *= multi;
|
|
qt.y *= multi;
|
|
qt.z *= multi;
|
|
qt.w *= multi;
|
|
aQ = damp(current, "x", qt.x, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
bQ = damp(current, "y", qt.y, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
cQ = damp(current, "z", qt.z, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
dQ = damp(current, "w", qt.w, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
v4result.set(current.x, current.y, current.z, current.w).normalize();
|
|
v4velocity.set(cur.__damp.velocity_x, cur.__damp.velocity_y, cur.__damp.velocity_z, cur.__damp.velocity_w);
|
|
v4error.copy(v4result).multiplyScalar(v4velocity.dot(v4result) / v4result.dot(v4result));
|
|
cur.__damp.velocity_x -= v4error.x;
|
|
cur.__damp.velocity_y -= v4error.y;
|
|
cur.__damp.velocity_z -= v4error.z;
|
|
cur.__damp.velocity_w -= v4error.w;
|
|
current.set(v4result.x, v4result.y, v4result.z, v4result.w);
|
|
return aQ || bQ || cQ || dQ;
|
|
}
|
|
var spherical = new Spherical();
|
|
var aS;
|
|
var bS;
|
|
var cS;
|
|
function dampS(current, target2, smoothTime, delta, maxSpeed, easing2, eps2) {
|
|
if (Array.isArray(target2)) spherical.set(target2[0], target2[1], target2[2]);
|
|
else spherical.copy(target2);
|
|
aS = damp(current, "radius", spherical.radius, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
bS = dampAngle(current, "phi", spherical.phi, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
cS = dampAngle(current, "theta", spherical.theta, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
return aS || bS || cS;
|
|
}
|
|
var mat = new Matrix4();
|
|
var mPos = new Vector3();
|
|
var mRot = new Quaternion();
|
|
var mSca = new Vector3();
|
|
var aM;
|
|
var bM;
|
|
var cM;
|
|
function dampM(current, target2, smoothTime, delta, maxSpeed, easing2, eps2) {
|
|
var cur = current;
|
|
if (cur.__damp === void 0) {
|
|
cur.__damp = {
|
|
position: new Vector3(),
|
|
rotation: new Quaternion(),
|
|
scale: new Vector3()
|
|
};
|
|
current.decompose(cur.__damp.position, cur.__damp.rotation, cur.__damp.scale);
|
|
}
|
|
if (Array.isArray(target2)) mat.set.apply(mat, _toConsumableArray(target2));
|
|
else mat.copy(target2);
|
|
mat.decompose(mPos, mRot, mSca);
|
|
aM = damp3(cur.__damp.position, mPos, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
bM = dampQ(cur.__damp.rotation, mRot, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
cM = damp3(cur.__damp.scale, mSca, smoothTime, delta, maxSpeed, easing2, eps2);
|
|
current.compose(cur.__damp.position, cur.__damp.rotation, cur.__damp.scale);
|
|
return aM || bM || cM;
|
|
}
|
|
var easing = Object.freeze({
|
|
__proto__: null,
|
|
rsqw,
|
|
exp,
|
|
linear,
|
|
sine,
|
|
cubic,
|
|
quint,
|
|
circ,
|
|
quart,
|
|
expo,
|
|
damp,
|
|
dampLookAt,
|
|
dampAngle,
|
|
damp2,
|
|
damp3,
|
|
damp4,
|
|
dampE,
|
|
dampC,
|
|
dampQ,
|
|
dampS,
|
|
dampM
|
|
});
|
|
|
|
// node_modules/maath/dist/geometry-0fb11825.esm.js
|
|
function _inherits(subClass, superClass) {
|
|
if (typeof superClass !== "function" && superClass !== null) {
|
|
throw new TypeError("Super expression must either be null or a function");
|
|
}
|
|
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
|
constructor: {
|
|
value: subClass,
|
|
writable: true,
|
|
configurable: true
|
|
}
|
|
});
|
|
if (superClass) _setPrototypeOf(subClass, superClass);
|
|
}
|
|
function _getPrototypeOf(o2) {
|
|
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf2(o3) {
|
|
return o3.__proto__ || Object.getPrototypeOf(o3);
|
|
};
|
|
return _getPrototypeOf(o2);
|
|
}
|
|
function _assertThisInitialized(self2) {
|
|
if (self2 === void 0) {
|
|
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
}
|
|
return self2;
|
|
}
|
|
function _possibleConstructorReturn(self2, call3) {
|
|
if (call3 && (typeof call3 === "object" || typeof call3 === "function")) {
|
|
return call3;
|
|
} else if (call3 !== void 0) {
|
|
throw new TypeError("Derived constructors may only return object or undefined");
|
|
}
|
|
return _assertThisInitialized(self2);
|
|
}
|
|
function _createSuper(Derived) {
|
|
var hasNativeReflectConstruct = _isNativeReflectConstruct();
|
|
return function _createSuperInternal() {
|
|
var Super = _getPrototypeOf(Derived), result;
|
|
if (hasNativeReflectConstruct) {
|
|
var NewTarget = _getPrototypeOf(this).constructor;
|
|
result = Reflect.construct(Super, arguments, NewTarget);
|
|
} else {
|
|
result = Super.apply(this, arguments);
|
|
}
|
|
return _possibleConstructorReturn(this, result);
|
|
};
|
|
}
|
|
var RoundedPlaneGeometry = (function(_THREE$BufferGeometry) {
|
|
_inherits(RoundedPlaneGeometry2, _THREE$BufferGeometry);
|
|
var _super = _createSuper(RoundedPlaneGeometry2);
|
|
function RoundedPlaneGeometry2() {
|
|
var _this;
|
|
var width = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 2;
|
|
var height = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 1;
|
|
var radius = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : 0.2;
|
|
var segments = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : 16;
|
|
_classCallCheck(this, RoundedPlaneGeometry2);
|
|
_this = _super.call(this);
|
|
_this.parameters = {
|
|
width,
|
|
height,
|
|
radius,
|
|
segments
|
|
};
|
|
var wi = width / 2 - radius;
|
|
var hi = height / 2 - radius;
|
|
var ul = radius / width;
|
|
var ur = (width - radius) / width;
|
|
var vl = radius / height;
|
|
var vh = (height - radius) / height;
|
|
var positions = [wi, hi, 0, -wi, hi, 0, -wi, -hi, 0, wi, -hi, 0];
|
|
var uvs = [ur, vh, ul, vh, ul, vl, ur, vl];
|
|
var n2 = [3 * (segments + 1) + 3, 3 * (segments + 1) + 4, segments + 4, segments + 5, 2 * (segments + 1) + 4, 2, 1, 2 * (segments + 1) + 3, 3, 4 * (segments + 1) + 3, 4, 0];
|
|
var indices = [n2[0], n2[1], n2[2], n2[0], n2[2], n2[3], n2[4], n2[5], n2[6], n2[4], n2[6], n2[7], n2[8], n2[9], n2[10], n2[8], n2[10], n2[11]];
|
|
var phi, cos, sin, xc, yc, uc, vc, idx;
|
|
for (var i3 = 0; i3 < 4; i3++) {
|
|
xc = i3 < 1 || i3 > 2 ? wi : -wi;
|
|
yc = i3 < 2 ? hi : -hi;
|
|
uc = i3 < 1 || i3 > 2 ? ur : ul;
|
|
vc = i3 < 2 ? vh : vl;
|
|
for (var j = 0; j <= segments; j++) {
|
|
phi = Math.PI / 2 * (i3 + j / segments);
|
|
cos = Math.cos(phi);
|
|
sin = Math.sin(phi);
|
|
positions.push(xc + radius * cos, yc + radius * sin, 0);
|
|
uvs.push(uc + ul * cos, vc + vl * sin);
|
|
if (j < segments) {
|
|
idx = (segments + 1) * i3 + j + 4;
|
|
indices.push(i3, idx, idx + 1);
|
|
}
|
|
}
|
|
}
|
|
_this.setIndex(new BufferAttribute(new Uint32Array(indices), 1));
|
|
_this.setAttribute("position", new BufferAttribute(new Float32Array(positions), 3));
|
|
_this.setAttribute("uv", new BufferAttribute(new Float32Array(uvs), 2));
|
|
return _this;
|
|
}
|
|
return RoundedPlaneGeometry2;
|
|
})(BufferGeometry);
|
|
function applyCylindricalUV(bufferGeometry) {
|
|
var uvs = [];
|
|
for (var i3 = 0; i3 < bufferGeometry.attributes.position.array.length / 3; i3++) {
|
|
var x = bufferGeometry.attributes.position.array[i3 * 3 + 0];
|
|
var y = bufferGeometry.attributes.position.array[i3 * 3 + 1];
|
|
var z = bufferGeometry.attributes.position.array[i3 * 3 + 2];
|
|
uvs.push(Math.atan2(x, z) / Math.PI * 0.5 + 0.5, y / Math.PI * 0.5 + 0.5);
|
|
}
|
|
if (bufferGeometry.attributes.uv) delete bufferGeometry.attributes.uv;
|
|
bufferGeometry.setAttribute("uv", new Float32BufferAttribute(uvs, 2));
|
|
bufferGeometry.attributes.uv.needsUpdate = true;
|
|
return bufferGeometry;
|
|
}
|
|
function applySphereUV(bufferGeometry) {
|
|
var uvs = [];
|
|
var vertices = [];
|
|
for (var i3 = 0; i3 < bufferGeometry.attributes.position.array.length / 3; i3++) {
|
|
var x = bufferGeometry.attributes.position.array[i3 * 3 + 0];
|
|
var y = bufferGeometry.attributes.position.array[i3 * 3 + 1];
|
|
var z = bufferGeometry.attributes.position.array[i3 * 3 + 2];
|
|
vertices.push(new Vector3(x, y, z));
|
|
}
|
|
var polarVertices = vertices.map(cartesian2polar);
|
|
for (var _i = 0; _i < polarVertices.length / 3; _i++) {
|
|
var tri = new Triangle(vertices[_i * 3 + 0], vertices[_i * 3 + 1], vertices[_i * 3 + 2]);
|
|
var normal2 = tri.getNormal(new Vector3());
|
|
for (var f2 = 0; f2 < 3; f2++) {
|
|
var vertex = polarVertices[_i * 3 + f2];
|
|
if (vertex.theta === 0 && (vertex.phi === 0 || vertex.phi === Math.PI)) {
|
|
var alignedVertice = vertex.phi === 0 ? _i * 3 + 1 : _i * 3 + 0;
|
|
vertex = {
|
|
r: vertex.r,
|
|
phi: vertex.phi,
|
|
theta: polarVertices[alignedVertice].theta
|
|
};
|
|
}
|
|
if (vertex.theta === Math.PI && cartesian2polar(normal2).theta < Math.PI / 2) {
|
|
vertex.theta = -Math.PI;
|
|
}
|
|
var canvasPoint = polar2canvas(vertex);
|
|
uvs.push(1 - canvasPoint.x, 1 - canvasPoint.y);
|
|
}
|
|
}
|
|
if (bufferGeometry.attributes.uv) delete bufferGeometry.attributes.uv;
|
|
bufferGeometry.setAttribute("uv", new Float32BufferAttribute(uvs, 2));
|
|
bufferGeometry.attributes.uv.needsUpdate = true;
|
|
return bufferGeometry;
|
|
}
|
|
function cartesian2polar(position2) {
|
|
var r2 = Math.sqrt(position2.x * position2.x + position2.z * position2.z + position2.y * position2.y);
|
|
return {
|
|
r: r2,
|
|
phi: Math.acos(position2.y / r2),
|
|
theta: Math.atan2(position2.z, position2.x)
|
|
};
|
|
}
|
|
function polar2canvas(polarPoint) {
|
|
return {
|
|
y: polarPoint.phi / Math.PI,
|
|
x: (polarPoint.theta + Math.PI) / (2 * Math.PI)
|
|
};
|
|
}
|
|
function applyBoxUV(bufferGeometry) {
|
|
bufferGeometry.computeBoundingBox();
|
|
var bboxSize = bufferGeometry.boundingBox.getSize(new Vector3());
|
|
var boxSize = Math.min(bboxSize.x, bboxSize.y, bboxSize.z);
|
|
var boxGeometry = new BoxGeometry(boxSize, boxSize, boxSize);
|
|
var cube = new Mesh(boxGeometry);
|
|
cube.rotation.set(0, 0, 0);
|
|
cube.updateWorldMatrix(true, false);
|
|
var transformMatrix = cube.matrix.clone().invert();
|
|
var uvBbox = new Box3(new Vector3(-boxSize / 2, -boxSize / 2, -boxSize / 2), new Vector3(boxSize / 2, boxSize / 2, boxSize / 2));
|
|
_applyBoxUV(bufferGeometry, transformMatrix, uvBbox, boxSize);
|
|
bufferGeometry.attributes.uv.needsUpdate = true;
|
|
return bufferGeometry;
|
|
}
|
|
function _applyBoxUV(geom, transformMatrix, bbox, bbox_max_size) {
|
|
var coords = [];
|
|
coords.length = 2 * geom.attributes.position.array.length / 3;
|
|
var makeUVs = function makeUVs2(v02, v13, v23) {
|
|
v02.applyMatrix4(transformMatrix);
|
|
v13.applyMatrix4(transformMatrix);
|
|
v23.applyMatrix4(transformMatrix);
|
|
var n2 = new Vector3();
|
|
n2.crossVectors(v13.clone().sub(v02), v13.clone().sub(v23)).normalize();
|
|
n2.x = Math.abs(n2.x);
|
|
n2.y = Math.abs(n2.y);
|
|
n2.z = Math.abs(n2.z);
|
|
var uv0 = new Vector2();
|
|
var uv1 = new Vector2();
|
|
var uv2 = new Vector2();
|
|
if (n2.y > n2.x && n2.y > n2.z) {
|
|
uv0.x = (v02.x - bbox.min.x) / bbox_max_size;
|
|
uv0.y = (bbox.max.z - v02.z) / bbox_max_size;
|
|
uv1.x = (v13.x - bbox.min.x) / bbox_max_size;
|
|
uv1.y = (bbox.max.z - v13.z) / bbox_max_size;
|
|
uv2.x = (v23.x - bbox.min.x) / bbox_max_size;
|
|
uv2.y = (bbox.max.z - v23.z) / bbox_max_size;
|
|
} else if (n2.x > n2.y && n2.x > n2.z) {
|
|
uv0.x = (v02.z - bbox.min.z) / bbox_max_size;
|
|
uv0.y = (v02.y - bbox.min.y) / bbox_max_size;
|
|
uv1.x = (v13.z - bbox.min.z) / bbox_max_size;
|
|
uv1.y = (v13.y - bbox.min.y) / bbox_max_size;
|
|
uv2.x = (v23.z - bbox.min.z) / bbox_max_size;
|
|
uv2.y = (v23.y - bbox.min.y) / bbox_max_size;
|
|
} else if (n2.z > n2.y && n2.z > n2.x) {
|
|
uv0.x = (v02.x - bbox.min.x) / bbox_max_size;
|
|
uv0.y = (v02.y - bbox.min.y) / bbox_max_size;
|
|
uv1.x = (v13.x - bbox.min.x) / bbox_max_size;
|
|
uv1.y = (v13.y - bbox.min.y) / bbox_max_size;
|
|
uv2.x = (v23.x - bbox.min.x) / bbox_max_size;
|
|
uv2.y = (v23.y - bbox.min.y) / bbox_max_size;
|
|
}
|
|
return {
|
|
uv0,
|
|
uv1,
|
|
uv2
|
|
};
|
|
};
|
|
if (geom.index) {
|
|
for (var vi = 0; vi < geom.index.array.length; vi += 3) {
|
|
var idx0 = geom.index.array[vi];
|
|
var idx1 = geom.index.array[vi + 1];
|
|
var idx2 = geom.index.array[vi + 2];
|
|
var vx0 = geom.attributes.position.array[3 * idx0];
|
|
var vy0 = geom.attributes.position.array[3 * idx0 + 1];
|
|
var vz0 = geom.attributes.position.array[3 * idx0 + 2];
|
|
var vx1 = geom.attributes.position.array[3 * idx1];
|
|
var vy1 = geom.attributes.position.array[3 * idx1 + 1];
|
|
var vz1 = geom.attributes.position.array[3 * idx1 + 2];
|
|
var vx2 = geom.attributes.position.array[3 * idx2];
|
|
var vy2 = geom.attributes.position.array[3 * idx2 + 1];
|
|
var vz2 = geom.attributes.position.array[3 * idx2 + 2];
|
|
var v0 = new Vector3(vx0, vy0, vz0);
|
|
var v12 = new Vector3(vx1, vy1, vz1);
|
|
var v22 = new Vector3(vx2, vy2, vz2);
|
|
var uvs = makeUVs(v0, v12, v22);
|
|
coords[2 * idx0] = uvs.uv0.x;
|
|
coords[2 * idx0 + 1] = uvs.uv0.y;
|
|
coords[2 * idx1] = uvs.uv1.x;
|
|
coords[2 * idx1 + 1] = uvs.uv1.y;
|
|
coords[2 * idx2] = uvs.uv2.x;
|
|
coords[2 * idx2 + 1] = uvs.uv2.y;
|
|
}
|
|
} else {
|
|
for (var _vi = 0; _vi < geom.attributes.position.array.length; _vi += 9) {
|
|
var _vx = geom.attributes.position.array[_vi];
|
|
var _vy = geom.attributes.position.array[_vi + 1];
|
|
var _vz = geom.attributes.position.array[_vi + 2];
|
|
var _vx2 = geom.attributes.position.array[_vi + 3];
|
|
var _vy2 = geom.attributes.position.array[_vi + 4];
|
|
var _vz2 = geom.attributes.position.array[_vi + 5];
|
|
var _vx3 = geom.attributes.position.array[_vi + 6];
|
|
var _vy3 = geom.attributes.position.array[_vi + 7];
|
|
var _vz3 = geom.attributes.position.array[_vi + 8];
|
|
var _v = new Vector3(_vx, _vy, _vz);
|
|
var _v22 = new Vector3(_vx2, _vy2, _vz2);
|
|
var _v3 = new Vector3(_vx3, _vy3, _vz3);
|
|
var _uvs = makeUVs(_v, _v22, _v3);
|
|
var _idx = _vi / 3;
|
|
var _idx2 = _idx + 1;
|
|
var _idx3 = _idx + 2;
|
|
coords[2 * _idx] = _uvs.uv0.x;
|
|
coords[2 * _idx + 1] = _uvs.uv0.y;
|
|
coords[2 * _idx2] = _uvs.uv1.x;
|
|
coords[2 * _idx2 + 1] = _uvs.uv1.y;
|
|
coords[2 * _idx3] = _uvs.uv2.x;
|
|
coords[2 * _idx3 + 1] = _uvs.uv2.y;
|
|
}
|
|
}
|
|
if (geom.attributes.uv) delete geom.attributes.uv;
|
|
geom.setAttribute("uv", new Float32BufferAttribute(coords, 2));
|
|
}
|
|
var geometry = Object.freeze({
|
|
__proto__: null,
|
|
RoundedPlaneGeometry,
|
|
applyCylindricalUV,
|
|
applySphereUV,
|
|
applyBoxUV
|
|
});
|
|
|
|
// node_modules/maath/dist/three-eb2ad8c0.esm.js
|
|
function bufferToVectors(buffer2) {
|
|
var stride = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 3;
|
|
var p2 = [];
|
|
for (var i3 = 0, j = 0; i3 < buffer2.length; i3 += stride, j++) {
|
|
if (stride === 3) {
|
|
p2[j] = new Vector3(buffer2[i3], buffer2[i3 + 1], buffer2[i3 + 2]);
|
|
} else {
|
|
p2[j] = new Vector2(buffer2[i3], buffer2[i3 + 1]);
|
|
}
|
|
}
|
|
return p2;
|
|
}
|
|
function vectorsToBuffer(vectorArray) {
|
|
var l2 = vectorArray.length;
|
|
var stride = vectorArray[0].hasOwnProperty("z") ? 3 : 2;
|
|
var buffer2 = new Float32Array(l2 * stride);
|
|
for (var i3 = 0; i3 < l2; i3++) {
|
|
var j = i3 * stride;
|
|
buffer2[j] = vectorArray[i3].x;
|
|
buffer2[j + 1] = vectorArray[i3].y;
|
|
if (stride === 3) {
|
|
buffer2[j + 2] = vectorArray[i3].z;
|
|
}
|
|
}
|
|
return buffer2;
|
|
}
|
|
var three = Object.freeze({
|
|
__proto__: null,
|
|
bufferToVectors,
|
|
vectorsToBuffer
|
|
});
|
|
|
|
// node_modules/@react-three/drei/web/ScrollControls.js
|
|
var context2 = React8.createContext(null);
|
|
function useScroll() {
|
|
return React8.useContext(context2);
|
|
}
|
|
function ScrollControls({
|
|
eps: eps2 = 1e-5,
|
|
enabled = true,
|
|
infinite,
|
|
horizontal,
|
|
pages = 1,
|
|
distance: distance3 = 1,
|
|
damping = 0.25,
|
|
maxSpeed = Infinity,
|
|
prepend = false,
|
|
style = {},
|
|
children
|
|
}) {
|
|
const {
|
|
get,
|
|
setEvents,
|
|
gl,
|
|
size,
|
|
invalidate,
|
|
events
|
|
} = useThree();
|
|
const [el] = React8.useState(() => document.createElement("div"));
|
|
const [fill] = React8.useState(() => document.createElement("div"));
|
|
const [fixed] = React8.useState(() => document.createElement("div"));
|
|
const target2 = gl.domElement.parentNode;
|
|
const scroll = React8.useRef(0);
|
|
const state = React8.useMemo(() => {
|
|
const state2 = {
|
|
el,
|
|
eps: eps2,
|
|
fill,
|
|
fixed,
|
|
horizontal,
|
|
damping,
|
|
offset: 0,
|
|
delta: 0,
|
|
scroll,
|
|
pages,
|
|
// 0-1 for a range between from -> from + distance
|
|
range(from, distance4, margin = 0) {
|
|
const start = from - margin;
|
|
const end = start + distance4 + margin * 2;
|
|
return this.offset < start ? 0 : this.offset > end ? 1 : (this.offset - start) / (end - start);
|
|
},
|
|
// 0-1-0 for a range between from -> from + distance
|
|
curve(from, distance4, margin = 0) {
|
|
return Math.sin(this.range(from, distance4, margin) * Math.PI);
|
|
},
|
|
// true/false for a range between from -> from + distance
|
|
visible(from, distance4, margin = 0) {
|
|
const start = from - margin;
|
|
const end = start + distance4 + margin * 2;
|
|
return this.offset >= start && this.offset <= end;
|
|
}
|
|
};
|
|
return state2;
|
|
}, [eps2, damping, horizontal, pages]);
|
|
React8.useEffect(() => {
|
|
el.style.position = "absolute";
|
|
el.style.width = "100%";
|
|
el.style.height = "100%";
|
|
el.style[horizontal ? "overflowX" : "overflowY"] = "auto";
|
|
el.style[horizontal ? "overflowY" : "overflowX"] = "hidden";
|
|
el.style.top = "0px";
|
|
el.style.left = "0px";
|
|
for (const key in style) {
|
|
el.style[key] = style[key];
|
|
}
|
|
fixed.style.position = "sticky";
|
|
fixed.style.top = "0px";
|
|
fixed.style.left = "0px";
|
|
fixed.style.width = "100%";
|
|
fixed.style.height = "100%";
|
|
fixed.style.overflow = "hidden";
|
|
el.appendChild(fixed);
|
|
fill.style.height = horizontal ? "100%" : `${pages * distance3 * 100}%`;
|
|
fill.style.width = horizontal ? `${pages * distance3 * 100}%` : "100%";
|
|
fill.style.pointerEvents = "none";
|
|
el.appendChild(fill);
|
|
if (prepend) target2.prepend(el);
|
|
else target2.appendChild(el);
|
|
el[horizontal ? "scrollLeft" : "scrollTop"] = 1;
|
|
const oldTarget = events.connected || gl.domElement;
|
|
requestAnimationFrame(() => events.connect == null ? void 0 : events.connect(el));
|
|
const oldCompute = get().events.compute;
|
|
setEvents({
|
|
compute(event, state2) {
|
|
const {
|
|
left,
|
|
top
|
|
} = target2.getBoundingClientRect();
|
|
const offsetX = event.clientX - left;
|
|
const offsetY = event.clientY - top;
|
|
state2.pointer.set(offsetX / state2.size.width * 2 - 1, -(offsetY / state2.size.height) * 2 + 1);
|
|
state2.raycaster.setFromCamera(state2.pointer, state2.camera);
|
|
}
|
|
});
|
|
return () => {
|
|
target2.removeChild(el);
|
|
setEvents({
|
|
compute: oldCompute
|
|
});
|
|
events.connect == null || events.connect(oldTarget);
|
|
};
|
|
}, [pages, distance3, horizontal, el, fill, fixed, target2]);
|
|
React8.useEffect(() => {
|
|
if (events.connected === el) {
|
|
const containerLength = size[horizontal ? "width" : "height"];
|
|
const scrollLength = el[horizontal ? "scrollWidth" : "scrollHeight"];
|
|
const scrollThreshold = scrollLength - containerLength;
|
|
let current = 0;
|
|
let disableScroll = true;
|
|
let firstRun = true;
|
|
const onScroll = () => {
|
|
if (!enabled || firstRun) return;
|
|
invalidate();
|
|
current = el[horizontal ? "scrollLeft" : "scrollTop"];
|
|
scroll.current = current / scrollThreshold;
|
|
if (infinite) {
|
|
if (!disableScroll) {
|
|
if (current >= scrollThreshold) {
|
|
const damp5 = 1 - state.offset;
|
|
el[horizontal ? "scrollLeft" : "scrollTop"] = 1;
|
|
scroll.current = state.offset = -damp5;
|
|
disableScroll = true;
|
|
} else if (current <= 0) {
|
|
const damp5 = 1 + state.offset;
|
|
el[horizontal ? "scrollLeft" : "scrollTop"] = scrollLength;
|
|
scroll.current = state.offset = damp5;
|
|
disableScroll = true;
|
|
}
|
|
}
|
|
if (disableScroll) setTimeout(() => disableScroll = false, 40);
|
|
}
|
|
};
|
|
el.addEventListener("scroll", onScroll, {
|
|
passive: true
|
|
});
|
|
requestAnimationFrame(() => firstRun = false);
|
|
const onWheel = (e2) => el.scrollLeft += e2.deltaY / 2;
|
|
if (horizontal) el.addEventListener("wheel", onWheel, {
|
|
passive: true
|
|
});
|
|
return () => {
|
|
el.removeEventListener("scroll", onScroll);
|
|
if (horizontal) el.removeEventListener("wheel", onWheel);
|
|
};
|
|
}
|
|
}, [el, events, size, infinite, state, invalidate, horizontal, enabled]);
|
|
let last = 0;
|
|
useFrame((_, delta) => {
|
|
last = state.offset;
|
|
easing.damp(state, "offset", scroll.current, damping, delta, maxSpeed, void 0, eps2);
|
|
easing.damp(state, "delta", Math.abs(last - state.offset), damping, delta, maxSpeed, void 0, eps2);
|
|
if (state.delta > eps2) invalidate();
|
|
});
|
|
return React8.createElement(context2.Provider, {
|
|
value: state
|
|
}, children);
|
|
}
|
|
var ScrollCanvas = React8.forwardRef(({
|
|
children
|
|
}, ref) => {
|
|
const group = React8.useRef(null);
|
|
React8.useImperativeHandle(ref, () => group.current, []);
|
|
const state = useScroll();
|
|
const {
|
|
width,
|
|
height
|
|
} = useThree((state2) => state2.viewport);
|
|
useFrame(() => {
|
|
group.current.position.x = state.horizontal ? -width * (state.pages - 1) * state.offset : 0;
|
|
group.current.position.y = state.horizontal ? 0 : height * (state.pages - 1) * state.offset;
|
|
});
|
|
return React8.createElement("group", {
|
|
ref: group
|
|
}, children);
|
|
});
|
|
var ScrollHtml = React8.forwardRef(({
|
|
children,
|
|
style,
|
|
...props
|
|
}, ref) => {
|
|
const state = useScroll();
|
|
const group = React8.useRef(null);
|
|
React8.useImperativeHandle(ref, () => group.current, []);
|
|
const {
|
|
width,
|
|
height
|
|
} = useThree((state2) => state2.size);
|
|
const fiberState = React8.useContext(context);
|
|
const root = React8.useMemo(() => ReactDOM2.createRoot(state.fixed), [state.fixed]);
|
|
useFrame(() => {
|
|
if (state.delta > state.eps) {
|
|
group.current.style.transform = `translate3d(${state.horizontal ? -width * (state.pages - 1) * state.offset : 0}px,${state.horizontal ? 0 : height * (state.pages - 1) * -state.offset}px,0)`;
|
|
}
|
|
});
|
|
root.render(React8.createElement("div", _extends({
|
|
ref: group,
|
|
style: {
|
|
...style,
|
|
position: "absolute",
|
|
top: 0,
|
|
left: 0,
|
|
willChange: "transform"
|
|
}
|
|
}, props), React8.createElement(context2.Provider, {
|
|
value: state
|
|
}, React8.createElement(context.Provider, {
|
|
value: fiberState
|
|
}, children))));
|
|
return null;
|
|
});
|
|
var Scroll = React8.forwardRef(({
|
|
html,
|
|
...props
|
|
}, ref) => {
|
|
const El = html ? ScrollHtml : ScrollCanvas;
|
|
return React8.createElement(El, _extends({
|
|
ref
|
|
}, props));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/web/PresentationControls.js
|
|
var React9 = __toESM(require_react());
|
|
function PresentationControls({
|
|
enabled = true,
|
|
snap,
|
|
global,
|
|
domElement,
|
|
cursor = true,
|
|
children,
|
|
speed = 1,
|
|
rotation: rotation3 = [0, 0, 0],
|
|
zoom = 1,
|
|
polar = [0, Math.PI / 2],
|
|
azimuth = [-Infinity, Infinity],
|
|
damping = 0.25
|
|
}) {
|
|
const events = useThree((state) => state.events);
|
|
const gl = useThree((state) => state.gl);
|
|
const explDomElement = domElement || events.connected || gl.domElement;
|
|
const {
|
|
size
|
|
} = useThree();
|
|
const rPolar = React9.useMemo(() => [rotation3[0] + polar[0], rotation3[0] + polar[1]], [rotation3[0], polar[0], polar[1]]);
|
|
const rAzimuth = React9.useMemo(() => [rotation3[1] + azimuth[0], rotation3[1] + azimuth[1]], [rotation3[1], azimuth[0], azimuth[1]]);
|
|
const rInitial = React9.useMemo(() => [MathUtils.clamp(rotation3[0], ...rPolar), MathUtils.clamp(rotation3[1], ...rAzimuth), rotation3[2]], [rotation3[0], rotation3[1], rotation3[2], rPolar, rAzimuth]);
|
|
React9.useEffect(() => {
|
|
if (global && cursor && enabled) {
|
|
explDomElement.style.cursor = "grab";
|
|
gl.domElement.style.cursor = "";
|
|
return () => {
|
|
explDomElement.style.cursor = "default";
|
|
gl.domElement.style.cursor = "default";
|
|
};
|
|
}
|
|
}, [global, cursor, explDomElement, enabled]);
|
|
const [animation] = React9.useState({
|
|
scale: 1,
|
|
rotation: rInitial,
|
|
damping
|
|
});
|
|
const ref = React9.useRef(null);
|
|
useFrame((state, delta) => {
|
|
easing.damp3(ref.current.scale, animation.scale, animation.damping, delta);
|
|
easing.dampE(ref.current.rotation, animation.rotation, animation.damping, delta);
|
|
});
|
|
const bind = useGesture({
|
|
onHover: ({
|
|
last
|
|
}) => {
|
|
if (cursor && !global && enabled) explDomElement.style.cursor = last ? "auto" : "grab";
|
|
},
|
|
onDrag: ({
|
|
down,
|
|
delta: [x, y],
|
|
memo: [oldY, oldX] = animation.rotation || rInitial
|
|
}) => {
|
|
if (!enabled) return [y, x];
|
|
if (cursor) explDomElement.style.cursor = down ? "grabbing" : "grab";
|
|
x = MathUtils.clamp(oldX + x / size.width * Math.PI * speed, ...rAzimuth);
|
|
y = MathUtils.clamp(oldY + y / size.height * Math.PI * speed, ...rPolar);
|
|
animation.scale = down && y > rPolar[1] / 2 ? zoom : 1;
|
|
animation.rotation = snap && !down ? rInitial : [y, x, 0];
|
|
animation.damping = snap && !down && typeof snap !== "boolean" ? snap : damping;
|
|
return [y, x];
|
|
}
|
|
}, {
|
|
target: global ? explDomElement : void 0
|
|
});
|
|
return React9.createElement("group", _extends({
|
|
ref
|
|
}, bind == null ? void 0 : bind()), children);
|
|
}
|
|
|
|
// node_modules/@react-three/drei/web/KeyboardControls.js
|
|
var React10 = __toESM(require_react());
|
|
var context3 = React10.createContext(null);
|
|
function KeyboardControls({
|
|
map: map2,
|
|
children,
|
|
onChange,
|
|
domElement
|
|
}) {
|
|
const key = map2.map((item) => item.name + item.keys).join("-");
|
|
const useControls = React10.useMemo(() => {
|
|
return create(subscribeWithSelector(() => map2.reduce((prev, cur) => ({
|
|
...prev,
|
|
[cur.name]: false
|
|
}), {})));
|
|
}, [key]);
|
|
const api = React10.useMemo(() => [useControls.subscribe, useControls.getState, useControls], [key]);
|
|
const set = useControls.setState;
|
|
React10.useEffect(() => {
|
|
const config = map2.map(({
|
|
name,
|
|
keys,
|
|
up
|
|
}) => ({
|
|
keys,
|
|
up,
|
|
fn: (value) => {
|
|
set({
|
|
[name]: value
|
|
});
|
|
if (onChange) onChange(name, value, api[1]());
|
|
}
|
|
}));
|
|
const keyMap = config.reduce((out7, {
|
|
keys,
|
|
fn,
|
|
up = true
|
|
}) => {
|
|
keys.forEach((key2) => out7[key2] = {
|
|
fn,
|
|
pressed: false,
|
|
up
|
|
});
|
|
return out7;
|
|
}, {});
|
|
const downHandler = ({
|
|
key: key2,
|
|
code
|
|
}) => {
|
|
const obj = keyMap[key2] || keyMap[code];
|
|
if (!obj) return;
|
|
const {
|
|
fn,
|
|
pressed,
|
|
up
|
|
} = obj;
|
|
obj.pressed = true;
|
|
if (up || !pressed) fn(true);
|
|
};
|
|
const upHandler = ({
|
|
key: key2,
|
|
code
|
|
}) => {
|
|
const obj = keyMap[key2] || keyMap[code];
|
|
if (!obj) return;
|
|
const {
|
|
fn,
|
|
up
|
|
} = obj;
|
|
obj.pressed = false;
|
|
if (up) fn(false);
|
|
};
|
|
const source = domElement || window;
|
|
source.addEventListener("keydown", downHandler, {
|
|
passive: true
|
|
});
|
|
source.addEventListener("keyup", upHandler, {
|
|
passive: true
|
|
});
|
|
return () => {
|
|
source.removeEventListener("keydown", downHandler);
|
|
source.removeEventListener("keyup", upHandler);
|
|
};
|
|
}, [domElement, key]);
|
|
return React10.createElement(context3.Provider, {
|
|
value: api,
|
|
children
|
|
});
|
|
}
|
|
function useKeyboardControls(sel) {
|
|
const [sub3, get, store] = React10.useContext(context3);
|
|
if (sel) return store(sel);
|
|
else return [sub3, get];
|
|
}
|
|
|
|
// node_modules/@react-three/drei/web/Select.js
|
|
var React12 = __toESM(require_react());
|
|
|
|
// node_modules/zustand/esm/vanilla/shallow.mjs
|
|
var isIterable = (obj) => Symbol.iterator in obj;
|
|
var hasIterableEntries = (value) => (
|
|
// HACK: avoid checking entries type
|
|
"entries" in value
|
|
);
|
|
var compareEntries = (valueA, valueB) => {
|
|
const mapA = valueA instanceof Map ? valueA : new Map(valueA.entries());
|
|
const mapB = valueB instanceof Map ? valueB : new Map(valueB.entries());
|
|
if (mapA.size !== mapB.size) {
|
|
return false;
|
|
}
|
|
for (const [key, value] of mapA) {
|
|
if (!mapB.has(key) || !Object.is(value, mapB.get(key))) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
var compareIterables = (valueA, valueB) => {
|
|
const iteratorA = valueA[Symbol.iterator]();
|
|
const iteratorB = valueB[Symbol.iterator]();
|
|
let nextA = iteratorA.next();
|
|
let nextB = iteratorB.next();
|
|
while (!nextA.done && !nextB.done) {
|
|
if (!Object.is(nextA.value, nextB.value)) {
|
|
return false;
|
|
}
|
|
nextA = iteratorA.next();
|
|
nextB = iteratorB.next();
|
|
}
|
|
return !!nextA.done && !!nextB.done;
|
|
};
|
|
function shallow(valueA, valueB) {
|
|
if (Object.is(valueA, valueB)) {
|
|
return true;
|
|
}
|
|
if (typeof valueA !== "object" || valueA === null || typeof valueB !== "object" || valueB === null) {
|
|
return false;
|
|
}
|
|
if (Object.getPrototypeOf(valueA) !== Object.getPrototypeOf(valueB)) {
|
|
return false;
|
|
}
|
|
if (isIterable(valueA) && isIterable(valueB)) {
|
|
if (hasIterableEntries(valueA) && hasIterableEntries(valueB)) {
|
|
return compareEntries(valueA, valueB);
|
|
}
|
|
return compareIterables(valueA, valueB);
|
|
}
|
|
return compareEntries(
|
|
{ entries: () => Object.entries(valueA) },
|
|
{ entries: () => Object.entries(valueB) }
|
|
);
|
|
}
|
|
|
|
// node_modules/zustand/esm/react/shallow.mjs
|
|
var import_react4 = __toESM(require_react(), 1);
|
|
|
|
// node_modules/@react-three/drei/web/Select.js
|
|
var context4 = React12.createContext([]);
|
|
function Select({
|
|
box,
|
|
multiple,
|
|
children,
|
|
onChange,
|
|
onChangePointerUp,
|
|
border = "1px solid #55aaff",
|
|
backgroundColor = "rgba(75, 160, 255, 0.1)",
|
|
filter: customFilter = (item) => item,
|
|
...props
|
|
}) {
|
|
const [downed, down] = React12.useState(false);
|
|
const {
|
|
setEvents,
|
|
camera,
|
|
raycaster,
|
|
gl,
|
|
controls,
|
|
size,
|
|
get
|
|
} = useThree();
|
|
const [hovered, hover] = React12.useState(false);
|
|
const [active, dispatch] = React12.useReducer(
|
|
// @ts-expect-error
|
|
(state, {
|
|
object,
|
|
shift
|
|
}) => {
|
|
if (object === void 0) return [];
|
|
else if (Array.isArray(object)) return object;
|
|
else if (!shift) return state[0] === object ? [] : [object];
|
|
else if (state.includes(object)) return state.filter((o2) => o2 !== object);
|
|
else return [object, ...state];
|
|
},
|
|
[]
|
|
);
|
|
React12.useEffect(() => {
|
|
if (downed) onChange == null || onChange(active);
|
|
else onChangePointerUp == null || onChangePointerUp(active);
|
|
}, [active, downed]);
|
|
const onClick = React12.useCallback((e2) => {
|
|
e2.stopPropagation();
|
|
dispatch({
|
|
object: customFilter([e2.object])[0],
|
|
shift: multiple && e2.shiftKey
|
|
});
|
|
}, []);
|
|
const onPointerMissed = React12.useCallback((e2) => !hovered && dispatch({}), [hovered]);
|
|
const ref = React12.useRef(null);
|
|
React12.useEffect(() => {
|
|
if (!box || !multiple) return;
|
|
const selBox = new SelectionBox(camera, ref.current);
|
|
const element = document.createElement("div");
|
|
element.style.pointerEvents = "none";
|
|
element.style.border = border;
|
|
element.style.backgroundColor = backgroundColor;
|
|
element.style.position = "fixed";
|
|
const startPoint = new Vector2();
|
|
const pointTopLeft = new Vector2();
|
|
const pointBottomRight = new Vector2();
|
|
const oldRaycasterEnabled = get().events.enabled;
|
|
const oldControlsEnabled = controls == null ? void 0 : controls.enabled;
|
|
let isDown = false;
|
|
function prepareRay(event, vec) {
|
|
const {
|
|
offsetX,
|
|
offsetY
|
|
} = event;
|
|
const {
|
|
width,
|
|
height
|
|
} = size;
|
|
vec.set(offsetX / width * 2 - 1, -(offsetY / height) * 2 + 1);
|
|
}
|
|
function onSelectStart(event) {
|
|
var _gl$domElement$parent;
|
|
if (controls) controls.enabled = false;
|
|
setEvents({
|
|
enabled: false
|
|
});
|
|
down(isDown = true);
|
|
(_gl$domElement$parent = gl.domElement.parentElement) == null || _gl$domElement$parent.appendChild(element);
|
|
element.style.left = `${event.clientX}px`;
|
|
element.style.top = `${event.clientY}px`;
|
|
element.style.width = "0px";
|
|
element.style.height = "0px";
|
|
startPoint.x = event.clientX;
|
|
startPoint.y = event.clientY;
|
|
}
|
|
function onSelectMove(event) {
|
|
pointBottomRight.x = Math.max(startPoint.x, event.clientX);
|
|
pointBottomRight.y = Math.max(startPoint.y, event.clientY);
|
|
pointTopLeft.x = Math.min(startPoint.x, event.clientX);
|
|
pointTopLeft.y = Math.min(startPoint.y, event.clientY);
|
|
element.style.left = `${pointTopLeft.x}px`;
|
|
element.style.top = `${pointTopLeft.y}px`;
|
|
element.style.width = `${pointBottomRight.x - pointTopLeft.x}px`;
|
|
element.style.height = `${pointBottomRight.y - pointTopLeft.y}px`;
|
|
}
|
|
function onSelectOver() {
|
|
if (isDown) {
|
|
var _element$parentElemen;
|
|
if (controls) controls.enabled = oldControlsEnabled;
|
|
setEvents({
|
|
enabled: oldRaycasterEnabled
|
|
});
|
|
down(isDown = false);
|
|
(_element$parentElemen = element.parentElement) == null || _element$parentElemen.removeChild(element);
|
|
}
|
|
}
|
|
function pointerDown(event) {
|
|
if (event.shiftKey) {
|
|
onSelectStart(event);
|
|
prepareRay(event, selBox.startPoint);
|
|
}
|
|
}
|
|
let previous = [];
|
|
function pointerMove(event) {
|
|
if (isDown) {
|
|
onSelectMove(event);
|
|
prepareRay(event, selBox.endPoint);
|
|
const allSelected = selBox.select().sort((o2) => o2.uuid).filter((o2) => o2.isMesh);
|
|
if (!shallow(allSelected, previous)) {
|
|
previous = allSelected;
|
|
dispatch({
|
|
object: customFilter(allSelected)
|
|
});
|
|
}
|
|
}
|
|
}
|
|
function pointerUp(event) {
|
|
if (isDown) onSelectOver();
|
|
}
|
|
document.addEventListener("pointerdown", pointerDown, {
|
|
passive: true
|
|
});
|
|
document.addEventListener("pointermove", pointerMove, {
|
|
passive: true,
|
|
capture: true
|
|
});
|
|
document.addEventListener("pointerup", pointerUp, {
|
|
passive: true
|
|
});
|
|
return () => {
|
|
document.removeEventListener("pointerdown", pointerDown);
|
|
document.removeEventListener("pointermove", pointerMove, true);
|
|
document.removeEventListener("pointerup", pointerUp);
|
|
};
|
|
}, [size.width, size.height, raycaster, camera, controls, gl]);
|
|
return React12.createElement("group", _extends({
|
|
ref,
|
|
onClick,
|
|
onPointerOver: () => hover(true),
|
|
onPointerOut: () => hover(false),
|
|
onPointerMissed
|
|
}, props), React12.createElement(context4.Provider, {
|
|
value: active
|
|
}, children));
|
|
}
|
|
function useSelect() {
|
|
return React12.useContext(context4);
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/Billboard.js
|
|
var React13 = __toESM(require_react());
|
|
var Billboard = React13.forwardRef(function Billboard2({
|
|
children,
|
|
follow = true,
|
|
lockX = false,
|
|
lockY = false,
|
|
lockZ = false,
|
|
...props
|
|
}, fref) {
|
|
const inner = React13.useRef(null);
|
|
const localRef = React13.useRef(null);
|
|
const q = new Quaternion();
|
|
useFrame(({
|
|
camera
|
|
}) => {
|
|
if (!follow || !localRef.current) return;
|
|
const prevRotation = inner.current.rotation.clone();
|
|
localRef.current.updateMatrix();
|
|
localRef.current.updateWorldMatrix(false, false);
|
|
localRef.current.getWorldQuaternion(q);
|
|
camera.getWorldQuaternion(inner.current.quaternion).premultiply(q.invert());
|
|
if (lockX) inner.current.rotation.x = prevRotation.x;
|
|
if (lockY) inner.current.rotation.y = prevRotation.y;
|
|
if (lockZ) inner.current.rotation.z = prevRotation.z;
|
|
});
|
|
React13.useImperativeHandle(fref, () => localRef.current, []);
|
|
return React13.createElement("group", _extends({
|
|
ref: localRef
|
|
}, props), React13.createElement("group", {
|
|
ref: inner
|
|
}, children));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/ScreenSpace.js
|
|
var React14 = __toESM(require_react());
|
|
var ScreenSpace = React14.forwardRef(({
|
|
children,
|
|
depth = -1,
|
|
...rest
|
|
}, ref) => {
|
|
const localRef = React14.useRef(null);
|
|
React14.useImperativeHandle(ref, () => localRef.current, []);
|
|
useFrame(({
|
|
camera
|
|
}) => {
|
|
localRef.current.quaternion.copy(camera.quaternion);
|
|
localRef.current.position.copy(camera.position);
|
|
});
|
|
return React14.createElement("group", _extends({
|
|
ref: localRef
|
|
}, rest), React14.createElement("group", {
|
|
"position-z": -depth
|
|
}, children));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/ScreenSizer.js
|
|
var React15 = __toESM(require_react());
|
|
var import_react5 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/core/calculateScaleFactor.js
|
|
var tV0 = new Vector3();
|
|
var tV1 = new Vector3();
|
|
var tV2 = new Vector3();
|
|
var getPoint2 = (point3, camera, size) => {
|
|
const widthHalf = size.width / 2;
|
|
const heightHalf = size.height / 2;
|
|
camera.updateMatrixWorld(false);
|
|
const vector = point3.project(camera);
|
|
vector.x = vector.x * widthHalf + widthHalf;
|
|
vector.y = -(vector.y * heightHalf) + heightHalf;
|
|
return vector;
|
|
};
|
|
var getPoint3 = (point2, camera, size, zValue = 1) => {
|
|
const vector = tV0.set(point2.x / size.width * 2 - 1, -(point2.y / size.height) * 2 + 1, zValue);
|
|
vector.unproject(camera);
|
|
return vector;
|
|
};
|
|
var calculateScaleFactor = (point3, radiusPx, camera, size) => {
|
|
const point2 = getPoint2(tV2.copy(point3), camera, size);
|
|
let scale5 = 0;
|
|
for (let i3 = 0; i3 < 2; ++i3) {
|
|
const point2off = tV1.copy(point2).setComponent(i3, point2.getComponent(i3) + radiusPx);
|
|
const point3off = getPoint3(point2off, camera, size, point2off.z);
|
|
scale5 = Math.max(scale5, point3.distanceTo(point3off));
|
|
}
|
|
return scale5;
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/ScreenSizer.js
|
|
var worldPos = new Vector3();
|
|
var ScreenSizer = (0, import_react5.forwardRef)(({
|
|
scale: scale5 = 1,
|
|
...props
|
|
}, ref) => {
|
|
const container = (0, import_react5.useRef)(null);
|
|
React15.useImperativeHandle(ref, () => container.current, []);
|
|
useFrame((state) => {
|
|
const obj = container.current;
|
|
if (!obj) return;
|
|
const sf = calculateScaleFactor(obj.getWorldPosition(worldPos), scale5, state.camera, state.size);
|
|
obj.scale.setScalar(sf * scale5);
|
|
});
|
|
return React15.createElement("object3D", _extends({
|
|
ref: container
|
|
}, props));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/QuadraticBezierLine.js
|
|
var React17 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/core/Line.js
|
|
var React16 = __toESM(require_react());
|
|
var Line = React16.forwardRef(function Line4({
|
|
points,
|
|
color = 16777215,
|
|
vertexColors,
|
|
linewidth,
|
|
lineWidth,
|
|
segments,
|
|
dashed,
|
|
...rest
|
|
}, ref) {
|
|
var _vertexColors$, _ref;
|
|
const size = useThree((state) => state.size);
|
|
const line2 = React16.useMemo(() => segments ? new LineSegments2() : new Line2(), [segments]);
|
|
const [lineMaterial] = React16.useState(() => new LineMaterial());
|
|
const itemSize = (vertexColors == null || (_vertexColors$ = vertexColors[0]) == null ? void 0 : _vertexColors$.length) === 4 ? 4 : 3;
|
|
const lineGeom = React16.useMemo(() => {
|
|
const geom = segments ? new LineSegmentsGeometry() : new LineGeometry();
|
|
const pValues = points.map((p2) => {
|
|
const isArray3 = Array.isArray(p2);
|
|
return p2 instanceof Vector3 || p2 instanceof Vector4 ? [p2.x, p2.y, p2.z] : p2 instanceof Vector2 ? [p2.x, p2.y, 0] : isArray3 && p2.length === 3 ? [p2[0], p2[1], p2[2]] : isArray3 && p2.length === 2 ? [p2[0], p2[1], 0] : p2;
|
|
});
|
|
geom.setPositions(pValues.flat());
|
|
if (vertexColors) {
|
|
color = 16777215;
|
|
const cValues = vertexColors.map((c2) => c2 instanceof Color ? c2.toArray() : c2);
|
|
geom.setColors(cValues.flat(), itemSize);
|
|
}
|
|
return geom;
|
|
}, [points, segments, vertexColors, itemSize]);
|
|
React16.useLayoutEffect(() => {
|
|
line2.computeLineDistances();
|
|
}, [points, line2]);
|
|
React16.useLayoutEffect(() => {
|
|
if (dashed) {
|
|
lineMaterial.defines.USE_DASH = "";
|
|
} else {
|
|
delete lineMaterial.defines.USE_DASH;
|
|
}
|
|
lineMaterial.needsUpdate = true;
|
|
}, [dashed, lineMaterial]);
|
|
React16.useEffect(() => {
|
|
return () => {
|
|
lineGeom.dispose();
|
|
lineMaterial.dispose();
|
|
};
|
|
}, [lineGeom]);
|
|
return React16.createElement("primitive", _extends({
|
|
object: line2,
|
|
ref
|
|
}, rest), React16.createElement("primitive", {
|
|
object: lineGeom,
|
|
attach: "geometry"
|
|
}), React16.createElement("primitive", _extends({
|
|
object: lineMaterial,
|
|
attach: "material",
|
|
color,
|
|
vertexColors: Boolean(vertexColors),
|
|
resolution: [size.width, size.height],
|
|
linewidth: (_ref = linewidth !== null && linewidth !== void 0 ? linewidth : lineWidth) !== null && _ref !== void 0 ? _ref : 1,
|
|
dashed,
|
|
transparent: itemSize === 4
|
|
}, rest)));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/QuadraticBezierLine.js
|
|
var v = new Vector3();
|
|
var QuadraticBezierLine = React17.forwardRef(function QuadraticBezierLine2({
|
|
start = [0, 0, 0],
|
|
end = [0, 0, 0],
|
|
mid,
|
|
segments = 20,
|
|
...rest
|
|
}, forwardref) {
|
|
const ref = React17.useRef(null);
|
|
React17.useImperativeHandle(forwardref, () => ref.current);
|
|
const [curve] = React17.useState(() => new QuadraticBezierCurve3(void 0, void 0, void 0));
|
|
const getPoints = React17.useCallback((start2, end2, mid2, segments2 = 20) => {
|
|
if (start2 instanceof Vector3) curve.v0.copy(start2);
|
|
else curve.v0.set(...start2);
|
|
if (end2 instanceof Vector3) curve.v2.copy(end2);
|
|
else curve.v2.set(...end2);
|
|
if (mid2 instanceof Vector3) {
|
|
curve.v1.copy(mid2);
|
|
} else if (Array.isArray(mid2)) {
|
|
curve.v1.set(...mid2);
|
|
} else {
|
|
curve.v1.copy(curve.v0.clone().add(curve.v2.clone().sub(curve.v0)).add(v.set(0, curve.v0.y - curve.v2.y, 0)));
|
|
}
|
|
return curve.getPoints(segments2);
|
|
}, []);
|
|
React17.useLayoutEffect(() => {
|
|
ref.current.setPoints = (start2, end2, mid2) => {
|
|
const points2 = getPoints(start2, end2, mid2);
|
|
if (ref.current.geometry) ref.current.geometry.setPositions(points2.map((p2) => p2.toArray()).flat());
|
|
};
|
|
}, []);
|
|
const points = React17.useMemo(() => getPoints(start, end, mid, segments), [start, end, mid, segments]);
|
|
return React17.createElement(Line, _extends({
|
|
ref,
|
|
points
|
|
}, rest));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/CubicBezierLine.js
|
|
var React18 = __toESM(require_react());
|
|
var CubicBezierLine = React18.forwardRef(function CubicBezierLine2({
|
|
start,
|
|
end,
|
|
midA,
|
|
midB,
|
|
segments = 20,
|
|
...rest
|
|
}, ref) {
|
|
const points = React18.useMemo(() => {
|
|
const startV = start instanceof Vector3 ? start : new Vector3(...start);
|
|
const endV = end instanceof Vector3 ? end : new Vector3(...end);
|
|
const midAV = midA instanceof Vector3 ? midA : new Vector3(...midA);
|
|
const midBV = midB instanceof Vector3 ? midB : new Vector3(...midB);
|
|
const interpolatedV = new CubicBezierCurve3(startV, midAV, midBV, endV).getPoints(segments);
|
|
return interpolatedV;
|
|
}, [start, end, midA, midB, segments]);
|
|
return React18.createElement(Line, _extends({
|
|
ref,
|
|
points
|
|
}, rest));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/CatmullRomLine.js
|
|
var React19 = __toESM(require_react());
|
|
var CatmullRomLine = React19.forwardRef(function CatmullRomLine2({
|
|
points,
|
|
closed = false,
|
|
curveType = "centripetal",
|
|
tension = 0.5,
|
|
segments = 20,
|
|
vertexColors,
|
|
...rest
|
|
}, ref) {
|
|
const curve = React19.useMemo(() => {
|
|
const mappedPoints = points.map((pt) => pt instanceof Vector3 ? pt : new Vector3(...pt));
|
|
return new CatmullRomCurve3(mappedPoints, closed, curveType, tension);
|
|
}, [points, closed, curveType, tension]);
|
|
const segmentedPoints = React19.useMemo(() => curve.getPoints(segments), [curve, segments]);
|
|
const interpolatedVertexColors = React19.useMemo(() => {
|
|
if (!vertexColors || vertexColors.length < 2) return void 0;
|
|
if (vertexColors.length === segments + 1) return vertexColors;
|
|
const mappedColors = vertexColors.map((color) => color instanceof Color ? color : new Color(...color));
|
|
if (closed) mappedColors.push(mappedColors[0].clone());
|
|
const iColors = [mappedColors[0]];
|
|
const divisions = segments / (mappedColors.length - 1);
|
|
for (let i3 = 1; i3 < segments; i3++) {
|
|
const alpha = i3 % divisions / divisions;
|
|
const colorIndex = Math.floor(i3 / divisions);
|
|
iColors.push(mappedColors[colorIndex].clone().lerp(mappedColors[colorIndex + 1], alpha));
|
|
}
|
|
iColors.push(mappedColors[mappedColors.length - 1]);
|
|
return iColors;
|
|
}, [vertexColors, segments]);
|
|
return React19.createElement(Line, _extends({
|
|
ref,
|
|
points: segmentedPoints,
|
|
vertexColors: interpolatedVertexColors
|
|
}, rest));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/PositionalAudio.js
|
|
var React20 = __toESM(require_react());
|
|
var PositionalAudio = React20.forwardRef(({
|
|
url,
|
|
distance: distance3 = 1,
|
|
loop = true,
|
|
autoplay,
|
|
...props
|
|
}, ref) => {
|
|
const sound = React20.useRef(null);
|
|
React20.useImperativeHandle(ref, () => sound.current, []);
|
|
const camera = useThree(({
|
|
camera: camera2
|
|
}) => camera2);
|
|
const [listener] = React20.useState(() => new AudioListener());
|
|
const buffer2 = useLoader(AudioLoader, url);
|
|
React20.useEffect(() => {
|
|
const _sound = sound.current;
|
|
if (_sound) {
|
|
_sound.setBuffer(buffer2);
|
|
_sound.setRefDistance(distance3);
|
|
_sound.setLoop(loop);
|
|
if (autoplay && !_sound.isPlaying) _sound.play();
|
|
}
|
|
}, [buffer2, camera, distance3, loop]);
|
|
React20.useEffect(() => {
|
|
const _sound = sound.current;
|
|
camera.add(listener);
|
|
return () => {
|
|
camera.remove(listener);
|
|
if (_sound) {
|
|
if (_sound.isPlaying) _sound.stop();
|
|
if (_sound.source && _sound.source._connected) _sound.disconnect();
|
|
}
|
|
};
|
|
}, []);
|
|
return React20.createElement("positionalAudio", _extends({
|
|
ref: sound,
|
|
args: [listener]
|
|
}, props));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Text.js
|
|
var React21 = __toESM(require_react());
|
|
|
|
// node_modules/troika-worker-utils/dist/troika-worker-utils.esm.js
|
|
function workerBootstrap() {
|
|
var modules = /* @__PURE__ */ Object.create(null);
|
|
function registerModule(ref, callback) {
|
|
var id = ref.id;
|
|
var name = ref.name;
|
|
var dependencies = ref.dependencies;
|
|
if (dependencies === void 0) dependencies = [];
|
|
var init = ref.init;
|
|
if (init === void 0) init = function() {
|
|
};
|
|
var getTransferables = ref.getTransferables;
|
|
if (getTransferables === void 0) getTransferables = null;
|
|
if (modules[id]) {
|
|
return;
|
|
}
|
|
try {
|
|
dependencies = dependencies.map(function(dep) {
|
|
if (dep && dep.isWorkerModule) {
|
|
registerModule(dep, function(depResult) {
|
|
if (depResult instanceof Error) {
|
|
throw depResult;
|
|
}
|
|
});
|
|
dep = modules[dep.id].value;
|
|
}
|
|
return dep;
|
|
});
|
|
init = rehydrate("<" + name + ">.init", init);
|
|
if (getTransferables) {
|
|
getTransferables = rehydrate("<" + name + ">.getTransferables", getTransferables);
|
|
}
|
|
var value = null;
|
|
if (typeof init === "function") {
|
|
value = init.apply(void 0, dependencies);
|
|
} else {
|
|
console.error("worker module init function failed to rehydrate");
|
|
}
|
|
modules[id] = {
|
|
id,
|
|
value,
|
|
getTransferables
|
|
};
|
|
callback(value);
|
|
} catch (err) {
|
|
if (!(err && err.noLog)) {
|
|
console.error(err);
|
|
}
|
|
callback(err);
|
|
}
|
|
}
|
|
function callModule(ref, callback) {
|
|
var ref$1;
|
|
var id = ref.id;
|
|
var args = ref.args;
|
|
if (!modules[id] || typeof modules[id].value !== "function") {
|
|
callback(new Error("Worker module " + id + ": not found or its 'init' did not return a function"));
|
|
}
|
|
try {
|
|
var result = (ref$1 = modules[id]).value.apply(ref$1, args);
|
|
if (result && typeof result.then === "function") {
|
|
result.then(handleResult, function(rej) {
|
|
return callback(rej instanceof Error ? rej : new Error("" + rej));
|
|
});
|
|
} else {
|
|
handleResult(result);
|
|
}
|
|
} catch (err) {
|
|
callback(err);
|
|
}
|
|
function handleResult(result2) {
|
|
try {
|
|
var tx = modules[id].getTransferables && modules[id].getTransferables(result2);
|
|
if (!tx || !Array.isArray(tx) || !tx.length) {
|
|
tx = void 0;
|
|
}
|
|
callback(result2, tx);
|
|
} catch (err) {
|
|
console.error(err);
|
|
callback(err);
|
|
}
|
|
}
|
|
}
|
|
function rehydrate(name, str) {
|
|
var result = void 0;
|
|
self.troikaDefine = function(r2) {
|
|
return result = r2;
|
|
};
|
|
var url = URL.createObjectURL(
|
|
new Blob(
|
|
["/** " + name.replace(/\*/g, "") + " **/\n\ntroikaDefine(\n" + str + "\n)"],
|
|
{ type: "application/javascript" }
|
|
)
|
|
);
|
|
try {
|
|
importScripts(url);
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
URL.revokeObjectURL(url);
|
|
delete self.troikaDefine;
|
|
return result;
|
|
}
|
|
self.addEventListener("message", function(e2) {
|
|
var ref = e2.data;
|
|
var messageId = ref.messageId;
|
|
var action = ref.action;
|
|
var data = ref.data;
|
|
try {
|
|
if (action === "registerModule") {
|
|
registerModule(data, function(result) {
|
|
if (result instanceof Error) {
|
|
postMessage({
|
|
messageId,
|
|
success: false,
|
|
error: result.message
|
|
});
|
|
} else {
|
|
postMessage({
|
|
messageId,
|
|
success: true,
|
|
result: { isCallable: typeof result === "function" }
|
|
});
|
|
}
|
|
});
|
|
}
|
|
if (action === "callModule") {
|
|
callModule(data, function(result, transferables) {
|
|
if (result instanceof Error) {
|
|
postMessage({
|
|
messageId,
|
|
success: false,
|
|
error: result.message
|
|
});
|
|
} else {
|
|
postMessage({
|
|
messageId,
|
|
success: true,
|
|
result
|
|
}, transferables || void 0);
|
|
}
|
|
});
|
|
}
|
|
} catch (err) {
|
|
postMessage({
|
|
messageId,
|
|
success: false,
|
|
error: err.stack
|
|
});
|
|
}
|
|
});
|
|
}
|
|
function defineMainThreadModule(options) {
|
|
var moduleFunc = function() {
|
|
var args = [], len = arguments.length;
|
|
while (len--) args[len] = arguments[len];
|
|
return moduleFunc._getInitResult().then(function(initResult) {
|
|
if (typeof initResult === "function") {
|
|
return initResult.apply(void 0, args);
|
|
} else {
|
|
throw new Error("Worker module function was called but `init` did not return a callable function");
|
|
}
|
|
});
|
|
};
|
|
moduleFunc._getInitResult = function() {
|
|
var dependencies = options.dependencies;
|
|
var init = options.init;
|
|
dependencies = Array.isArray(dependencies) ? dependencies.map(function(dep) {
|
|
if (dep) {
|
|
dep = dep.onMainThread || dep;
|
|
if (dep._getInitResult) {
|
|
dep = dep._getInitResult();
|
|
}
|
|
}
|
|
return dep;
|
|
}) : [];
|
|
var initPromise = Promise.all(dependencies).then(function(deps) {
|
|
return init.apply(null, deps);
|
|
});
|
|
moduleFunc._getInitResult = function() {
|
|
return initPromise;
|
|
};
|
|
return initPromise;
|
|
};
|
|
return moduleFunc;
|
|
}
|
|
var supportsWorkers = function() {
|
|
var supported = false;
|
|
if (typeof window !== "undefined" && typeof window.document !== "undefined") {
|
|
try {
|
|
var worker = new Worker(
|
|
URL.createObjectURL(new Blob([""], { type: "application/javascript" }))
|
|
);
|
|
worker.terminate();
|
|
supported = true;
|
|
} catch (err) {
|
|
if (typeof process !== "undefined" && false) ;
|
|
else {
|
|
console.log(
|
|
"Troika createWorkerModule: web workers not allowed; falling back to main thread execution. Cause: [" + err.message + "]"
|
|
);
|
|
}
|
|
}
|
|
}
|
|
supportsWorkers = function() {
|
|
return supported;
|
|
};
|
|
return supported;
|
|
};
|
|
var _workerModuleId = 0;
|
|
var _messageId = 0;
|
|
var _allowInitAsString = false;
|
|
var workers = /* @__PURE__ */ Object.create(null);
|
|
var registeredModules = /* @__PURE__ */ Object.create(null);
|
|
var openRequests = /* @__PURE__ */ Object.create(null);
|
|
function defineWorkerModule(options) {
|
|
if ((!options || typeof options.init !== "function") && !_allowInitAsString) {
|
|
throw new Error("requires `options.init` function");
|
|
}
|
|
var dependencies = options.dependencies;
|
|
var init = options.init;
|
|
var getTransferables = options.getTransferables;
|
|
var workerId = options.workerId;
|
|
var onMainThread = defineMainThreadModule(options);
|
|
if (workerId == null) {
|
|
workerId = "#default";
|
|
}
|
|
var id = "workerModule" + ++_workerModuleId;
|
|
var name = options.name || id;
|
|
var registrationPromise = null;
|
|
dependencies = dependencies && dependencies.map(function(dep) {
|
|
if (typeof dep === "function" && !dep.workerModuleData) {
|
|
_allowInitAsString = true;
|
|
dep = defineWorkerModule({
|
|
workerId,
|
|
name: "<" + name + "> function dependency: " + dep.name,
|
|
init: "function(){return (\n" + stringifyFunction(dep) + "\n)}"
|
|
});
|
|
_allowInitAsString = false;
|
|
}
|
|
if (dep && dep.workerModuleData) {
|
|
dep = dep.workerModuleData;
|
|
}
|
|
return dep;
|
|
});
|
|
function moduleFunc() {
|
|
var args = [], len = arguments.length;
|
|
while (len--) args[len] = arguments[len];
|
|
if (!supportsWorkers()) {
|
|
return onMainThread.apply(void 0, args);
|
|
}
|
|
if (!registrationPromise) {
|
|
registrationPromise = callWorker(workerId, "registerModule", moduleFunc.workerModuleData);
|
|
var unregister = function() {
|
|
registrationPromise = null;
|
|
registeredModules[workerId].delete(unregister);
|
|
};
|
|
(registeredModules[workerId] || (registeredModules[workerId] = /* @__PURE__ */ new Set())).add(unregister);
|
|
}
|
|
return registrationPromise.then(function(ref) {
|
|
var isCallable = ref.isCallable;
|
|
if (isCallable) {
|
|
return callWorker(workerId, "callModule", { id, args });
|
|
} else {
|
|
throw new Error("Worker module function was called but `init` did not return a callable function");
|
|
}
|
|
});
|
|
}
|
|
moduleFunc.workerModuleData = {
|
|
isWorkerModule: true,
|
|
id,
|
|
name,
|
|
dependencies,
|
|
init: stringifyFunction(init),
|
|
getTransferables: getTransferables && stringifyFunction(getTransferables)
|
|
};
|
|
moduleFunc.onMainThread = onMainThread;
|
|
return moduleFunc;
|
|
}
|
|
function terminateWorker(workerId) {
|
|
if (registeredModules[workerId]) {
|
|
registeredModules[workerId].forEach(function(unregister) {
|
|
unregister();
|
|
});
|
|
}
|
|
if (workers[workerId]) {
|
|
workers[workerId].terminate();
|
|
delete workers[workerId];
|
|
}
|
|
}
|
|
function stringifyFunction(fn) {
|
|
var str = fn.toString();
|
|
if (!/^function/.test(str) && /^\w+\s*\(/.test(str)) {
|
|
str = "function " + str;
|
|
}
|
|
return str;
|
|
}
|
|
function getWorker(workerId) {
|
|
var worker = workers[workerId];
|
|
if (!worker) {
|
|
var bootstrap = stringifyFunction(workerBootstrap);
|
|
worker = workers[workerId] = new Worker(
|
|
URL.createObjectURL(
|
|
new Blob(
|
|
["/** Worker Module Bootstrap: " + workerId.replace(/\*/g, "") + " **/\n\n;(" + bootstrap + ")()"],
|
|
{ type: "application/javascript" }
|
|
)
|
|
)
|
|
);
|
|
worker.onmessage = function(e2) {
|
|
var response = e2.data;
|
|
var msgId = response.messageId;
|
|
var callback = openRequests[msgId];
|
|
if (!callback) {
|
|
throw new Error("WorkerModule response with empty or unknown messageId");
|
|
}
|
|
delete openRequests[msgId];
|
|
callback(response);
|
|
};
|
|
}
|
|
return worker;
|
|
}
|
|
function callWorker(workerId, action, data) {
|
|
return new Promise(function(resolve, reject) {
|
|
var messageId = ++_messageId;
|
|
openRequests[messageId] = function(response) {
|
|
if (response.success) {
|
|
resolve(response.result);
|
|
} else {
|
|
reject(new Error("Error in worker " + action + " call: " + response.error));
|
|
}
|
|
};
|
|
getWorker(workerId).postMessage({
|
|
messageId,
|
|
action,
|
|
data
|
|
});
|
|
});
|
|
}
|
|
|
|
// node_modules/webgl-sdf-generator/dist/webgl-sdf-generator.mjs
|
|
function SDFGenerator() {
|
|
var exports = (function(exports2) {
|
|
function pointOnQuadraticBezier(x0, y0, x1, y1, x2, y2, t2, pointOut) {
|
|
var t22 = 1 - t2;
|
|
pointOut.x = t22 * t22 * x0 + 2 * t22 * t2 * x1 + t2 * t2 * x2;
|
|
pointOut.y = t22 * t22 * y0 + 2 * t22 * t2 * y1 + t2 * t2 * y2;
|
|
}
|
|
function pointOnCubicBezier(x0, y0, x1, y1, x2, y2, x3, y3, t2, pointOut) {
|
|
var t22 = 1 - t2;
|
|
pointOut.x = t22 * t22 * t22 * x0 + 3 * t22 * t22 * t2 * x1 + 3 * t22 * t2 * t2 * x2 + t2 * t2 * t2 * x3;
|
|
pointOut.y = t22 * t22 * t22 * y0 + 3 * t22 * t22 * t2 * y1 + 3 * t22 * t2 * t2 * y2 + t2 * t2 * t2 * y3;
|
|
}
|
|
function forEachPathCommand(pathString, commandCallback) {
|
|
var segmentRE = /([MLQCZ])([^MLQCZ]*)/g;
|
|
var match, firstX, firstY, prevX, prevY;
|
|
while (match = segmentRE.exec(pathString)) {
|
|
var args = match[2].replace(/^\s*|\s*$/g, "").split(/[,\s]+/).map(function(v5) {
|
|
return parseFloat(v5);
|
|
});
|
|
switch (match[1]) {
|
|
case "M":
|
|
prevX = firstX = args[0];
|
|
prevY = firstY = args[1];
|
|
break;
|
|
case "L":
|
|
if (args[0] !== prevX || args[1] !== prevY) {
|
|
commandCallback("L", prevX, prevY, prevX = args[0], prevY = args[1]);
|
|
}
|
|
break;
|
|
case "Q": {
|
|
commandCallback("Q", prevX, prevY, prevX = args[2], prevY = args[3], args[0], args[1]);
|
|
break;
|
|
}
|
|
case "C": {
|
|
commandCallback("C", prevX, prevY, prevX = args[4], prevY = args[5], args[0], args[1], args[2], args[3]);
|
|
break;
|
|
}
|
|
case "Z":
|
|
if (prevX !== firstX || prevY !== firstY) {
|
|
commandCallback("L", prevX, prevY, firstX, firstY);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
function pathToLineSegments(pathString, segmentCallback, curvePoints) {
|
|
if (curvePoints === void 0) curvePoints = 16;
|
|
var tempPoint = { x: 0, y: 0 };
|
|
forEachPathCommand(pathString, function(command, startX, startY, endX, endY, ctrl1X, ctrl1Y, ctrl2X, ctrl2Y) {
|
|
switch (command) {
|
|
case "L":
|
|
segmentCallback(startX, startY, endX, endY);
|
|
break;
|
|
case "Q": {
|
|
var prevCurveX = startX;
|
|
var prevCurveY = startY;
|
|
for (var i3 = 1; i3 < curvePoints; i3++) {
|
|
pointOnQuadraticBezier(
|
|
startX,
|
|
startY,
|
|
ctrl1X,
|
|
ctrl1Y,
|
|
endX,
|
|
endY,
|
|
i3 / (curvePoints - 1),
|
|
tempPoint
|
|
);
|
|
segmentCallback(prevCurveX, prevCurveY, tempPoint.x, tempPoint.y);
|
|
prevCurveX = tempPoint.x;
|
|
prevCurveY = tempPoint.y;
|
|
}
|
|
break;
|
|
}
|
|
case "C": {
|
|
var prevCurveX$1 = startX;
|
|
var prevCurveY$1 = startY;
|
|
for (var i$1 = 1; i$1 < curvePoints; i$1++) {
|
|
pointOnCubicBezier(
|
|
startX,
|
|
startY,
|
|
ctrl1X,
|
|
ctrl1Y,
|
|
ctrl2X,
|
|
ctrl2Y,
|
|
endX,
|
|
endY,
|
|
i$1 / (curvePoints - 1),
|
|
tempPoint
|
|
);
|
|
segmentCallback(prevCurveX$1, prevCurveY$1, tempPoint.x, tempPoint.y);
|
|
prevCurveX$1 = tempPoint.x;
|
|
prevCurveY$1 = tempPoint.y;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
var viewportQuadVertex = "precision highp float;attribute vec2 aUV;varying vec2 vUV;void main(){vUV=aUV;gl_Position=vec4(mix(vec2(-1.0),vec2(1.0),aUV),0.0,1.0);}";
|
|
var copyTexFragment = "precision highp float;uniform sampler2D tex;varying vec2 vUV;void main(){gl_FragColor=texture2D(tex,vUV);}";
|
|
var cache = /* @__PURE__ */ new WeakMap();
|
|
var glContextParams = {
|
|
premultipliedAlpha: false,
|
|
preserveDrawingBuffer: true,
|
|
antialias: false,
|
|
depth: false
|
|
};
|
|
function withWebGLContext(glOrCanvas, callback) {
|
|
var gl = glOrCanvas.getContext ? glOrCanvas.getContext("webgl", glContextParams) : glOrCanvas;
|
|
var wrapper = cache.get(gl);
|
|
if (!wrapper) {
|
|
let getExtension2 = function(name) {
|
|
var ext = extensions2[name];
|
|
if (!ext) {
|
|
ext = extensions2[name] = gl.getExtension(name);
|
|
if (!ext) {
|
|
throw new Error(name + " not supported");
|
|
}
|
|
}
|
|
return ext;
|
|
}, compileShader = function(src, type) {
|
|
var shader = gl.createShader(type);
|
|
gl.shaderSource(shader, src);
|
|
gl.compileShader(shader);
|
|
return shader;
|
|
}, withProgram = function(name, vert, frag, func) {
|
|
if (!programs[name]) {
|
|
var attributes = {};
|
|
var uniforms = {};
|
|
var program = gl.createProgram();
|
|
gl.attachShader(program, compileShader(vert, gl.VERTEX_SHADER));
|
|
gl.attachShader(program, compileShader(frag, gl.FRAGMENT_SHADER));
|
|
gl.linkProgram(program);
|
|
programs[name] = {
|
|
program,
|
|
transaction: function transaction(func2) {
|
|
gl.useProgram(program);
|
|
func2({
|
|
setUniform: function setUniform(type, name2) {
|
|
var values = [], len = arguments.length - 2;
|
|
while (len-- > 0) values[len] = arguments[len + 2];
|
|
var uniformLoc = uniforms[name2] || (uniforms[name2] = gl.getUniformLocation(program, name2));
|
|
gl["uniform" + type].apply(gl, [uniformLoc].concat(values));
|
|
},
|
|
setAttribute: function setAttribute(name2, size, usage, instancingDivisor, data) {
|
|
var attr = attributes[name2];
|
|
if (!attr) {
|
|
attr = attributes[name2] = {
|
|
buf: gl.createBuffer(),
|
|
// TODO should we destroy our buffers?
|
|
loc: gl.getAttribLocation(program, name2),
|
|
data: null
|
|
};
|
|
}
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, attr.buf);
|
|
gl.vertexAttribPointer(attr.loc, size, gl.FLOAT, false, 0, 0);
|
|
gl.enableVertexAttribArray(attr.loc);
|
|
if (isWebGL2) {
|
|
gl.vertexAttribDivisor(attr.loc, instancingDivisor);
|
|
} else {
|
|
getExtension2("ANGLE_instanced_arrays").vertexAttribDivisorANGLE(attr.loc, instancingDivisor);
|
|
}
|
|
if (data !== attr.data) {
|
|
gl.bufferData(gl.ARRAY_BUFFER, data, usage);
|
|
attr.data = data;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
};
|
|
}
|
|
programs[name].transaction(func);
|
|
}, withTexture = function(name, func) {
|
|
textureUnit++;
|
|
try {
|
|
gl.activeTexture(gl.TEXTURE0 + textureUnit);
|
|
var texture = textures[name];
|
|
if (!texture) {
|
|
texture = textures[name] = gl.createTexture();
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
}
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
func(texture, textureUnit);
|
|
} finally {
|
|
textureUnit--;
|
|
}
|
|
}, withTextureFramebuffer = function(texture, textureUnit2, func) {
|
|
var framebuffer = gl.createFramebuffer();
|
|
framebufferStack.push(framebuffer);
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
|
gl.activeTexture(gl.TEXTURE0 + textureUnit2);
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
|
|
try {
|
|
func(framebuffer);
|
|
} finally {
|
|
gl.deleteFramebuffer(framebuffer);
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, framebufferStack[--framebufferStack.length - 1] || null);
|
|
}
|
|
}, handleContextLoss = function() {
|
|
extensions2 = {};
|
|
programs = {};
|
|
textures = {};
|
|
textureUnit = -1;
|
|
framebufferStack.length = 0;
|
|
};
|
|
var isWebGL2 = typeof WebGL2RenderingContext !== "undefined" && gl instanceof WebGL2RenderingContext;
|
|
var extensions2 = {};
|
|
var programs = {};
|
|
var textures = {};
|
|
var textureUnit = -1;
|
|
var framebufferStack = [];
|
|
gl.canvas.addEventListener("webglcontextlost", function(e2) {
|
|
handleContextLoss();
|
|
e2.preventDefault();
|
|
}, false);
|
|
cache.set(gl, wrapper = {
|
|
gl,
|
|
isWebGL2,
|
|
getExtension: getExtension2,
|
|
withProgram,
|
|
withTexture,
|
|
withTextureFramebuffer,
|
|
handleContextLoss
|
|
});
|
|
}
|
|
callback(wrapper);
|
|
}
|
|
function renderImageData(glOrCanvas, imageData, x, y, width, height, channels, framebuffer) {
|
|
if (channels === void 0) channels = 15;
|
|
if (framebuffer === void 0) framebuffer = null;
|
|
withWebGLContext(glOrCanvas, function(ref) {
|
|
var gl = ref.gl;
|
|
var withProgram = ref.withProgram;
|
|
var withTexture = ref.withTexture;
|
|
withTexture("copy", function(tex, texUnit) {
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, imageData);
|
|
withProgram("copy", viewportQuadVertex, copyTexFragment, function(ref2) {
|
|
var setUniform = ref2.setUniform;
|
|
var setAttribute = ref2.setAttribute;
|
|
setAttribute("aUV", 2, gl.STATIC_DRAW, 0, new Float32Array([0, 0, 2, 0, 0, 2]));
|
|
setUniform("1i", "image", texUnit);
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer || null);
|
|
gl.disable(gl.BLEND);
|
|
gl.colorMask(channels & 8, channels & 4, channels & 2, channels & 1);
|
|
gl.viewport(x, y, width, height);
|
|
gl.scissor(x, y, width, height);
|
|
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
function resizeWebGLCanvasWithoutClearing2(canvas, newWidth, newHeight) {
|
|
var width = canvas.width;
|
|
var height = canvas.height;
|
|
withWebGLContext(canvas, function(ref) {
|
|
var gl = ref.gl;
|
|
var data = new Uint8Array(width * height * 4);
|
|
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);
|
|
canvas.width = newWidth;
|
|
canvas.height = newHeight;
|
|
renderImageData(gl, data, 0, 0, width, height);
|
|
});
|
|
}
|
|
var webglUtils = Object.freeze({
|
|
__proto__: null,
|
|
withWebGLContext,
|
|
renderImageData,
|
|
resizeWebGLCanvasWithoutClearing: resizeWebGLCanvasWithoutClearing2
|
|
});
|
|
function generate$2(sdfWidth, sdfHeight, path, viewBox, maxDistance, sdfExponent) {
|
|
if (sdfExponent === void 0) sdfExponent = 1;
|
|
var textureData = new Uint8Array(sdfWidth * sdfHeight);
|
|
var viewBoxWidth = viewBox[2] - viewBox[0];
|
|
var viewBoxHeight = viewBox[3] - viewBox[1];
|
|
var segments = [];
|
|
pathToLineSegments(path, function(x1, y1, x2, y2) {
|
|
segments.push({
|
|
x1,
|
|
y1,
|
|
x2,
|
|
y2,
|
|
minX: Math.min(x1, x2),
|
|
minY: Math.min(y1, y2),
|
|
maxX: Math.max(x1, x2),
|
|
maxY: Math.max(y1, y2)
|
|
});
|
|
});
|
|
segments.sort(function(a5, b) {
|
|
return a5.maxX - b.maxX;
|
|
});
|
|
for (var sdfX = 0; sdfX < sdfWidth; sdfX++) {
|
|
for (var sdfY = 0; sdfY < sdfHeight; sdfY++) {
|
|
var signedDist = findNearestSignedDistance(
|
|
viewBox[0] + viewBoxWidth * (sdfX + 0.5) / sdfWidth,
|
|
viewBox[1] + viewBoxHeight * (sdfY + 0.5) / sdfHeight
|
|
);
|
|
var alpha = Math.pow(1 - Math.abs(signedDist) / maxDistance, sdfExponent) / 2;
|
|
if (signedDist < 0) {
|
|
alpha = 1 - alpha;
|
|
}
|
|
alpha = Math.max(0, Math.min(255, Math.round(alpha * 255)));
|
|
textureData[sdfY * sdfWidth + sdfX] = alpha;
|
|
}
|
|
}
|
|
return textureData;
|
|
function findNearestSignedDistance(x, y) {
|
|
var closestDistSq = Infinity;
|
|
var closestDist = Infinity;
|
|
for (var i3 = segments.length; i3--; ) {
|
|
var seg = segments[i3];
|
|
if (seg.maxX + closestDist <= x) {
|
|
break;
|
|
}
|
|
if (x + closestDist > seg.minX && y - closestDist < seg.maxY && y + closestDist > seg.minY) {
|
|
var distSq = absSquareDistanceToLineSegment(x, y, seg.x1, seg.y1, seg.x2, seg.y2);
|
|
if (distSq < closestDistSq) {
|
|
closestDistSq = distSq;
|
|
closestDist = Math.sqrt(closestDistSq);
|
|
}
|
|
}
|
|
}
|
|
if (isPointInPoly(x, y)) {
|
|
closestDist = -closestDist;
|
|
}
|
|
return closestDist;
|
|
}
|
|
function isPointInPoly(x, y) {
|
|
var winding = 0;
|
|
for (var i3 = segments.length; i3--; ) {
|
|
var seg = segments[i3];
|
|
if (seg.maxX <= x) {
|
|
break;
|
|
}
|
|
var intersects = seg.y1 > y !== seg.y2 > y && x < (seg.x2 - seg.x1) * (y - seg.y1) / (seg.y2 - seg.y1) + seg.x1;
|
|
if (intersects) {
|
|
winding += seg.y1 < seg.y2 ? 1 : -1;
|
|
}
|
|
}
|
|
return winding !== 0;
|
|
}
|
|
}
|
|
function generateIntoCanvas$2(sdfWidth, sdfHeight, path, viewBox, maxDistance, sdfExponent, canvas, x, y, channel) {
|
|
if (sdfExponent === void 0) sdfExponent = 1;
|
|
if (x === void 0) x = 0;
|
|
if (y === void 0) y = 0;
|
|
if (channel === void 0) channel = 0;
|
|
generateIntoFramebuffer$1(sdfWidth, sdfHeight, path, viewBox, maxDistance, sdfExponent, canvas, null, x, y, channel);
|
|
}
|
|
function generateIntoFramebuffer$1(sdfWidth, sdfHeight, path, viewBox, maxDistance, sdfExponent, glOrCanvas, framebuffer, x, y, channel) {
|
|
if (sdfExponent === void 0) sdfExponent = 1;
|
|
if (x === void 0) x = 0;
|
|
if (y === void 0) y = 0;
|
|
if (channel === void 0) channel = 0;
|
|
var data = generate$2(sdfWidth, sdfHeight, path, viewBox, maxDistance, sdfExponent);
|
|
var rgbaData = new Uint8Array(data.length * 4);
|
|
for (var i3 = 0; i3 < data.length; i3++) {
|
|
rgbaData[i3 * 4 + channel] = data[i3];
|
|
}
|
|
renderImageData(glOrCanvas, rgbaData, x, y, sdfWidth, sdfHeight, 1 << 3 - channel, framebuffer);
|
|
}
|
|
function absSquareDistanceToLineSegment(x, y, lineX0, lineY0, lineX1, lineY1) {
|
|
var ldx = lineX1 - lineX0;
|
|
var ldy = lineY1 - lineY0;
|
|
var lengthSq = ldx * ldx + ldy * ldy;
|
|
var t2 = lengthSq ? Math.max(0, Math.min(1, ((x - lineX0) * ldx + (y - lineY0) * ldy) / lengthSq)) : 0;
|
|
var dx = x - (lineX0 + t2 * ldx);
|
|
var dy = y - (lineY0 + t2 * ldy);
|
|
return dx * dx + dy * dy;
|
|
}
|
|
var javascript = Object.freeze({
|
|
__proto__: null,
|
|
generate: generate$2,
|
|
generateIntoCanvas: generateIntoCanvas$2,
|
|
generateIntoFramebuffer: generateIntoFramebuffer$1
|
|
});
|
|
var mainVertex = "precision highp float;uniform vec4 uGlyphBounds;attribute vec2 aUV;attribute vec4 aLineSegment;varying vec4 vLineSegment;varying vec2 vGlyphXY;void main(){vLineSegment=aLineSegment;vGlyphXY=mix(uGlyphBounds.xy,uGlyphBounds.zw,aUV);gl_Position=vec4(mix(vec2(-1.0),vec2(1.0),aUV),0.0,1.0);}";
|
|
var mainFragment = "precision highp float;uniform vec4 uGlyphBounds;uniform float uMaxDistance;uniform float uExponent;varying vec4 vLineSegment;varying vec2 vGlyphXY;float absDistToSegment(vec2 point,vec2 lineA,vec2 lineB){vec2 lineDir=lineB-lineA;float lenSq=dot(lineDir,lineDir);float t=lenSq==0.0 ? 0.0 : clamp(dot(point-lineA,lineDir)/lenSq,0.0,1.0);vec2 linePt=lineA+t*lineDir;return distance(point,linePt);}void main(){vec4 seg=vLineSegment;vec2 p=vGlyphXY;float dist=absDistToSegment(p,seg.xy,seg.zw);float val=pow(1.0-clamp(dist/uMaxDistance,0.0,1.0),uExponent)*0.5;bool crossing=(seg.y>p.y!=seg.w>p.y)&&(p.x<(seg.z-seg.x)*(p.y-seg.y)/(seg.w-seg.y)+seg.x);bool crossingUp=crossing&&vLineSegment.y<vLineSegment.w;gl_FragColor=vec4(crossingUp ? 1.0/255.0 : 0.0,crossing&&!crossingUp ? 1.0/255.0 : 0.0,0.0,val);}";
|
|
var postFragment = "precision highp float;uniform sampler2D tex;varying vec2 vUV;void main(){vec4 color=texture2D(tex,vUV);bool inside=color.r!=color.g;float val=inside ? 1.0-color.a : color.a;gl_FragColor=vec4(val);}";
|
|
var viewportUVs = new Float32Array([0, 0, 2, 0, 0, 2]);
|
|
var implicitContext = null;
|
|
var isTestingSupport = false;
|
|
var NULL_OBJECT = {};
|
|
var supportByCanvas = /* @__PURE__ */ new WeakMap();
|
|
function validateSupport(glOrCanvas) {
|
|
if (!isTestingSupport && !isSupported(glOrCanvas)) {
|
|
throw new Error("WebGL generation not supported");
|
|
}
|
|
}
|
|
function generate$1(sdfWidth, sdfHeight, path, viewBox, maxDistance, sdfExponent, glOrCanvas) {
|
|
if (sdfExponent === void 0) sdfExponent = 1;
|
|
if (glOrCanvas === void 0) glOrCanvas = null;
|
|
if (!glOrCanvas) {
|
|
glOrCanvas = implicitContext;
|
|
if (!glOrCanvas) {
|
|
var canvas = typeof OffscreenCanvas === "function" ? new OffscreenCanvas(1, 1) : typeof document !== "undefined" ? document.createElement("canvas") : null;
|
|
if (!canvas) {
|
|
throw new Error("OffscreenCanvas or DOM canvas not supported");
|
|
}
|
|
glOrCanvas = implicitContext = canvas.getContext("webgl", { depth: false });
|
|
}
|
|
}
|
|
validateSupport(glOrCanvas);
|
|
var rgbaData = new Uint8Array(sdfWidth * sdfHeight * 4);
|
|
withWebGLContext(glOrCanvas, function(ref) {
|
|
var gl = ref.gl;
|
|
var withTexture = ref.withTexture;
|
|
var withTextureFramebuffer = ref.withTextureFramebuffer;
|
|
withTexture("readable", function(texture, textureUnit) {
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sdfWidth, sdfHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
|
withTextureFramebuffer(texture, textureUnit, function(framebuffer) {
|
|
generateIntoFramebuffer(
|
|
sdfWidth,
|
|
sdfHeight,
|
|
path,
|
|
viewBox,
|
|
maxDistance,
|
|
sdfExponent,
|
|
gl,
|
|
framebuffer,
|
|
0,
|
|
0,
|
|
0
|
|
// red channel
|
|
);
|
|
gl.readPixels(0, 0, sdfWidth, sdfHeight, gl.RGBA, gl.UNSIGNED_BYTE, rgbaData);
|
|
});
|
|
});
|
|
});
|
|
var data = new Uint8Array(sdfWidth * sdfHeight);
|
|
for (var i3 = 0, j = 0; i3 < rgbaData.length; i3 += 4) {
|
|
data[j++] = rgbaData[i3];
|
|
}
|
|
return data;
|
|
}
|
|
function generateIntoCanvas$1(sdfWidth, sdfHeight, path, viewBox, maxDistance, sdfExponent, canvas, x, y, channel) {
|
|
if (sdfExponent === void 0) sdfExponent = 1;
|
|
if (x === void 0) x = 0;
|
|
if (y === void 0) y = 0;
|
|
if (channel === void 0) channel = 0;
|
|
generateIntoFramebuffer(sdfWidth, sdfHeight, path, viewBox, maxDistance, sdfExponent, canvas, null, x, y, channel);
|
|
}
|
|
function generateIntoFramebuffer(sdfWidth, sdfHeight, path, viewBox, maxDistance, sdfExponent, glOrCanvas, framebuffer, x, y, channel) {
|
|
if (sdfExponent === void 0) sdfExponent = 1;
|
|
if (x === void 0) x = 0;
|
|
if (y === void 0) y = 0;
|
|
if (channel === void 0) channel = 0;
|
|
validateSupport(glOrCanvas);
|
|
var lineSegmentCoords = [];
|
|
pathToLineSegments(path, function(x1, y1, x2, y2) {
|
|
lineSegmentCoords.push(x1, y1, x2, y2);
|
|
});
|
|
lineSegmentCoords = new Float32Array(lineSegmentCoords);
|
|
withWebGLContext(glOrCanvas, function(ref) {
|
|
var gl = ref.gl;
|
|
var isWebGL2 = ref.isWebGL2;
|
|
var getExtension2 = ref.getExtension;
|
|
var withProgram = ref.withProgram;
|
|
var withTexture = ref.withTexture;
|
|
var withTextureFramebuffer = ref.withTextureFramebuffer;
|
|
var handleContextLoss = ref.handleContextLoss;
|
|
withTexture("rawDistances", function(intermediateTexture, intermediateTextureUnit) {
|
|
if (sdfWidth !== intermediateTexture._lastWidth || sdfHeight !== intermediateTexture._lastHeight) {
|
|
gl.texImage2D(
|
|
gl.TEXTURE_2D,
|
|
0,
|
|
gl.RGBA,
|
|
intermediateTexture._lastWidth = sdfWidth,
|
|
intermediateTexture._lastHeight = sdfHeight,
|
|
0,
|
|
gl.RGBA,
|
|
gl.UNSIGNED_BYTE,
|
|
null
|
|
);
|
|
}
|
|
withProgram("main", mainVertex, mainFragment, function(ref2) {
|
|
var setAttribute = ref2.setAttribute;
|
|
var setUniform = ref2.setUniform;
|
|
var instancingExtension = !isWebGL2 && getExtension2("ANGLE_instanced_arrays");
|
|
var blendMinMaxExtension = !isWebGL2 && getExtension2("EXT_blend_minmax");
|
|
setAttribute("aUV", 2, gl.STATIC_DRAW, 0, viewportUVs);
|
|
setAttribute("aLineSegment", 4, gl.DYNAMIC_DRAW, 1, lineSegmentCoords);
|
|
setUniform.apply(void 0, ["4f", "uGlyphBounds"].concat(viewBox));
|
|
setUniform("1f", "uMaxDistance", maxDistance);
|
|
setUniform("1f", "uExponent", sdfExponent);
|
|
withTextureFramebuffer(intermediateTexture, intermediateTextureUnit, function(framebuffer2) {
|
|
gl.enable(gl.BLEND);
|
|
gl.colorMask(true, true, true, true);
|
|
gl.viewport(0, 0, sdfWidth, sdfHeight);
|
|
gl.scissor(0, 0, sdfWidth, sdfHeight);
|
|
gl.blendFunc(gl.ONE, gl.ONE);
|
|
gl.blendEquationSeparate(gl.FUNC_ADD, isWebGL2 ? gl.MAX : blendMinMaxExtension.MAX_EXT);
|
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
if (isWebGL2) {
|
|
gl.drawArraysInstanced(gl.TRIANGLES, 0, 3, lineSegmentCoords.length / 4);
|
|
} else {
|
|
instancingExtension.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 3, lineSegmentCoords.length / 4);
|
|
}
|
|
});
|
|
});
|
|
withProgram("post", viewportQuadVertex, postFragment, function(program) {
|
|
program.setAttribute("aUV", 2, gl.STATIC_DRAW, 0, viewportUVs);
|
|
program.setUniform("1i", "tex", intermediateTextureUnit);
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
|
gl.disable(gl.BLEND);
|
|
gl.colorMask(channel === 0, channel === 1, channel === 2, channel === 3);
|
|
gl.viewport(x, y, sdfWidth, sdfHeight);
|
|
gl.scissor(x, y, sdfWidth, sdfHeight);
|
|
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
});
|
|
});
|
|
if (gl.isContextLost()) {
|
|
handleContextLoss();
|
|
throw new Error("webgl context lost");
|
|
}
|
|
});
|
|
}
|
|
function isSupported(glOrCanvas) {
|
|
var key = !glOrCanvas || glOrCanvas === implicitContext ? NULL_OBJECT : glOrCanvas.canvas || glOrCanvas;
|
|
var supported = supportByCanvas.get(key);
|
|
if (supported === void 0) {
|
|
isTestingSupport = true;
|
|
var failReason = null;
|
|
try {
|
|
var expectedResult = [
|
|
97,
|
|
106,
|
|
97,
|
|
61,
|
|
99,
|
|
137,
|
|
118,
|
|
80,
|
|
80,
|
|
118,
|
|
137,
|
|
99,
|
|
61,
|
|
97,
|
|
106,
|
|
97
|
|
];
|
|
var testResult = generate$1(
|
|
4,
|
|
4,
|
|
"M8,8L16,8L24,24L16,24Z",
|
|
[0, 0, 32, 32],
|
|
24,
|
|
1,
|
|
glOrCanvas
|
|
);
|
|
supported = testResult && expectedResult.length === testResult.length && testResult.every(function(val, i3) {
|
|
return val === expectedResult[i3];
|
|
});
|
|
if (!supported) {
|
|
failReason = "bad trial run results";
|
|
console.info(expectedResult, testResult);
|
|
}
|
|
} catch (err) {
|
|
supported = false;
|
|
failReason = err.message;
|
|
}
|
|
if (failReason) {
|
|
console.warn("WebGL SDF generation not supported:", failReason);
|
|
}
|
|
isTestingSupport = false;
|
|
supportByCanvas.set(key, supported);
|
|
}
|
|
return supported;
|
|
}
|
|
var webgl = Object.freeze({
|
|
__proto__: null,
|
|
generate: generate$1,
|
|
generateIntoCanvas: generateIntoCanvas$1,
|
|
generateIntoFramebuffer,
|
|
isSupported
|
|
});
|
|
function generate(sdfWidth, sdfHeight, path, viewBox, maxDistance, sdfExponent) {
|
|
if (maxDistance === void 0) maxDistance = Math.max(viewBox[2] - viewBox[0], viewBox[3] - viewBox[1]) / 2;
|
|
if (sdfExponent === void 0) sdfExponent = 1;
|
|
try {
|
|
return generate$1.apply(webgl, arguments);
|
|
} catch (e2) {
|
|
console.info("WebGL SDF generation failed, falling back to JS", e2);
|
|
return generate$2.apply(javascript, arguments);
|
|
}
|
|
}
|
|
function generateIntoCanvas(sdfWidth, sdfHeight, path, viewBox, maxDistance, sdfExponent, canvas, x, y, channel) {
|
|
if (maxDistance === void 0) maxDistance = Math.max(viewBox[2] - viewBox[0], viewBox[3] - viewBox[1]) / 2;
|
|
if (sdfExponent === void 0) sdfExponent = 1;
|
|
if (x === void 0) x = 0;
|
|
if (y === void 0) y = 0;
|
|
if (channel === void 0) channel = 0;
|
|
try {
|
|
return generateIntoCanvas$1.apply(webgl, arguments);
|
|
} catch (e2) {
|
|
console.info("WebGL SDF generation failed, falling back to JS", e2);
|
|
return generateIntoCanvas$2.apply(javascript, arguments);
|
|
}
|
|
}
|
|
exports2.forEachPathCommand = forEachPathCommand;
|
|
exports2.generate = generate;
|
|
exports2.generateIntoCanvas = generateIntoCanvas;
|
|
exports2.javascript = javascript;
|
|
exports2.pathToLineSegments = pathToLineSegments;
|
|
exports2.webgl = webgl;
|
|
exports2.webglUtils = webglUtils;
|
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
return exports2;
|
|
})({});
|
|
return exports;
|
|
}
|
|
|
|
// node_modules/bidi-js/dist/bidi.mjs
|
|
function bidiFactory() {
|
|
var bidi = (function(exports) {
|
|
var DATA = {
|
|
"R": "13k,1a,2,3,3,2+1j,ch+16,a+1,5+2,2+n,5,a,4,6+16,4+3,h+1b,4mo,179q,2+9,2+11,2i9+7y,2+68,4,3+4,5+13,4+3,2+4k,3+29,8+cf,1t+7z,w+17,3+3m,1t+3z,16o1+5r,8+30,8+mc,29+1r,29+4v,75+73",
|
|
"EN": "1c+9,3d+1,6,187+9,513,4+5,7+9,sf+j,175h+9,qw+q,161f+1d,4xt+a,25i+9",
|
|
"ES": "17,2,6dp+1,f+1,av,16vr,mx+1,4o,2",
|
|
"ET": "z+2,3h+3,b+1,ym,3e+1,2o,p4+1,8,6u,7c,g6,1wc,1n9+4,30+1b,2n,6d,qhx+1,h0m,a+1,49+2,63+1,4+1,6bb+3,12jj",
|
|
"AN": "16o+5,2j+9,2+1,35,ed,1ff2+9,87+u",
|
|
"CS": "18,2+1,b,2u,12k,55v,l,17v0,2,3,53,2+1,b",
|
|
"B": "a,3,f+2,2v,690",
|
|
"S": "9,2,k",
|
|
"WS": "c,k,4f4,1vk+a,u,1j,335",
|
|
"ON": "x+1,4+4,h+5,r+5,r+3,z,5+3,2+1,2+1,5,2+2,3+4,o,w,ci+1,8+d,3+d,6+8,2+g,39+1,9,6+1,2,33,b8,3+1,3c+1,7+1,5r,b,7h+3,sa+5,2,3i+6,jg+3,ur+9,2v,ij+1,9g+9,7+a,8m,4+1,49+x,14u,2+2,c+2,e+2,e+2,e+1,i+n,e+e,2+p,u+2,e+2,36+1,2+3,2+1,b,2+2,6+5,2,2,2,h+1,5+4,6+3,3+f,16+2,5+3l,3+81,1y+p,2+40,q+a,m+13,2r+ch,2+9e,75+hf,3+v,2+2w,6e+5,f+6,75+2a,1a+p,2+2g,d+5x,r+b,6+3,4+o,g,6+1,6+2,2k+1,4,2j,5h+z,1m+1,1e+f,t+2,1f+e,d+3,4o+3,2s+1,w,535+1r,h3l+1i,93+2,2s,b+1,3l+x,2v,4g+3,21+3,kz+1,g5v+1,5a,j+9,n+v,2,3,2+8,2+1,3+2,2,3,46+1,4+4,h+5,r+5,r+a,3h+2,4+6,b+4,78,1r+24,4+c,4,1hb,ey+6,103+j,16j+c,1ux+7,5+g,fsh,jdq+1t,4,57+2e,p1,1m,1m,1m,1m,4kt+1,7j+17,5+2r,d+e,3+e,2+e,2+10,m+4,w,1n+5,1q,4z+5,4b+rb,9+c,4+c,4+37,d+2g,8+b,l+b,5+1j,9+9,7+13,9+t,3+1,27+3c,2+29,2+3q,d+d,3+4,4+2,6+6,a+o,8+6,a+2,e+6,16+42,2+1i",
|
|
"BN": "0+8,6+d,2s+5,2+p,e,4m9,1kt+2,2b+5,5+5,17q9+v,7k,6p+8,6+1,119d+3,440+7,96s+1,1ekf+1,1ekf+1,1ekf+1,1ekf+1,1ekf+1,1ekf+1,1ekf+1,1ekf+1,1ekf+1,1ekf+1,1ekf+1,1ekf+75,6p+2rz,1ben+1,1ekf+1,1ekf+1",
|
|
"NSM": "lc+33,7o+6,7c+18,2,2+1,2+1,2,21+a,1d+k,h,2u+6,3+5,3+1,2+3,10,v+q,2k+a,1n+8,a,p+3,2+8,2+2,2+4,18+2,3c+e,2+v,1k,2,5+7,5,4+6,b+1,u,1n,5+3,9,l+1,r,3+1,1m,5+1,5+1,3+2,4,v+1,4,c+1,1m,5+4,2+1,5,l+1,n+5,2,1n,3,2+3,9,8+1,c+1,v,1q,d,1f,4,1m+2,6+2,2+3,8+1,c+1,u,1n,g+1,l+1,t+1,1m+1,5+3,9,l+1,u,21,8+2,2,2j,3+6,d+7,2r,3+8,c+5,23+1,s,2,2,1k+d,2+4,2+1,6+a,2+z,a,2v+3,2+5,2+1,3+1,q+1,5+2,h+3,e,3+1,7,g,jk+2,qb+2,u+2,u+1,v+1,1t+1,2+6,9,3+a,a,1a+2,3c+1,z,3b+2,5+1,a,7+2,64+1,3,1n,2+6,2,2,3+7,7+9,3,1d+g,1s+3,1d,2+4,2,6,15+8,d+1,x+3,3+1,2+2,1l,2+1,4,2+2,1n+7,3+1,49+2,2+c,2+6,5,7,4+1,5j+1l,2+4,k1+w,2db+2,3y,2p+v,ff+3,30+1,n9x+3,2+9,x+1,29+1,7l,4,5,q+1,6,48+1,r+h,e,13+7,q+a,1b+2,1d,3+3,3+1,14,1w+5,3+1,3+1,d,9,1c,1g,2+2,3+1,6+1,2,17+1,9,6n,3,5,fn5,ki+f,h+f,r2,6b,46+4,1af+2,2+1,6+3,15+2,5,4m+1,fy+3,as+1,4a+a,4x,1j+e,1l+2,1e+3,3+1,1y+2,11+4,2+7,1r,d+1,1h+8,b+3,3,2o+2,3,2+1,7,4h,4+7,m+1,1m+1,4,12+6,4+4,5g+7,3+2,2,o,2d+5,2,5+1,2+1,6n+3,7+1,2+1,s+1,2e+7,3,2+1,2z,2,3+5,2,2u+2,3+3,2+4,78+8,2+1,75+1,2,5,41+3,3+1,5,x+5,3+1,15+5,3+3,9,a+5,3+2,1b+c,2+1,bb+6,2+5,2d+l,3+6,2+1,2+1,3f+5,4,2+1,2+6,2,21+1,4,2,9o+1,f0c+4,1o+6,t5,1s+3,2a,f5l+1,43t+2,i+7,3+6,v+3,45+2,1j0+1i,5+1d,9,f,n+4,2+e,11t+6,2+g,3+6,2+1,2+4,7a+6,c6+3,15t+6,32+6,gzhy+6n",
|
|
"AL": "16w,3,2,e+1b,z+2,2+2s,g+1,8+1,b+m,2+t,s+2i,c+e,4h+f,1d+1e,1bwe+dp,3+3z,x+c,2+1,35+3y,2rm+z,5+7,b+5,dt+l,c+u,17nl+27,1t+27,4x+6n,3+d",
|
|
"LRO": "6ct",
|
|
"RLO": "6cu",
|
|
"LRE": "6cq",
|
|
"RLE": "6cr",
|
|
"PDF": "6cs",
|
|
"LRI": "6ee",
|
|
"RLI": "6ef",
|
|
"FSI": "6eg",
|
|
"PDI": "6eh"
|
|
};
|
|
var TYPES = {};
|
|
var TYPES_TO_NAMES = {};
|
|
TYPES.L = 1;
|
|
TYPES_TO_NAMES[1] = "L";
|
|
Object.keys(DATA).forEach(function(type, i3) {
|
|
TYPES[type] = 1 << i3 + 1;
|
|
TYPES_TO_NAMES[TYPES[type]] = type;
|
|
});
|
|
Object.freeze(TYPES);
|
|
var ISOLATE_INIT_TYPES = TYPES.LRI | TYPES.RLI | TYPES.FSI;
|
|
var STRONG_TYPES = TYPES.L | TYPES.R | TYPES.AL;
|
|
var NEUTRAL_ISOLATE_TYPES = TYPES.B | TYPES.S | TYPES.WS | TYPES.ON | TYPES.FSI | TYPES.LRI | TYPES.RLI | TYPES.PDI;
|
|
var BN_LIKE_TYPES = TYPES.BN | TYPES.RLE | TYPES.LRE | TYPES.RLO | TYPES.LRO | TYPES.PDF;
|
|
var TRAILING_TYPES = TYPES.S | TYPES.WS | TYPES.B | ISOLATE_INIT_TYPES | TYPES.PDI | BN_LIKE_TYPES;
|
|
var map2 = null;
|
|
function parseData() {
|
|
if (!map2) {
|
|
map2 = /* @__PURE__ */ new Map();
|
|
var loop = function(type2) {
|
|
if (DATA.hasOwnProperty(type2)) {
|
|
var lastCode = 0;
|
|
DATA[type2].split(",").forEach(function(range) {
|
|
var ref = range.split("+");
|
|
var skip = ref[0];
|
|
var step = ref[1];
|
|
skip = parseInt(skip, 36);
|
|
step = step ? parseInt(step, 36) : 0;
|
|
map2.set(lastCode += skip, TYPES[type2]);
|
|
for (var i3 = 0; i3 < step; i3++) {
|
|
map2.set(++lastCode, TYPES[type2]);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
for (var type in DATA) loop(type);
|
|
}
|
|
}
|
|
function getBidiCharType(char) {
|
|
parseData();
|
|
return map2.get(char.codePointAt(0)) || TYPES.L;
|
|
}
|
|
function getBidiCharTypeName(char) {
|
|
return TYPES_TO_NAMES[getBidiCharType(char)];
|
|
}
|
|
var data$1 = {
|
|
"pairs": "14>1,1e>2,u>2,2wt>1,1>1,1ge>1,1wp>1,1j>1,f>1,hm>1,1>1,u>1,u6>1,1>1,+5,28>1,w>1,1>1,+3,b8>1,1>1,+3,1>3,-1>-1,3>1,1>1,+2,1s>1,1>1,x>1,th>1,1>1,+2,db>1,1>1,+3,3>1,1>1,+2,14qm>1,1>1,+1,4q>1,1e>2,u>2,2>1,+1",
|
|
"canonical": "6f1>-6dx,6dy>-6dx,6ec>-6ed,6ee>-6ed,6ww>2jj,-2ji>2jj,14r4>-1e7l,1e7m>-1e7l,1e7m>-1e5c,1e5d>-1e5b,1e5c>-14qx,14qy>-14qx,14vn>-1ecg,1ech>-1ecg,1edu>-1ecg,1eci>-1ecg,1eda>-1ecg,1eci>-1ecg,1eci>-168q,168r>-168q,168s>-14ye,14yf>-14ye"
|
|
};
|
|
function parseCharacterMap(encodedString, includeReverse) {
|
|
var radix = 36;
|
|
var lastCode = 0;
|
|
var map3 = /* @__PURE__ */ new Map();
|
|
var reverseMap = includeReverse && /* @__PURE__ */ new Map();
|
|
var prevPair;
|
|
encodedString.split(",").forEach(function visit(entry) {
|
|
if (entry.indexOf("+") !== -1) {
|
|
for (var i3 = +entry; i3--; ) {
|
|
visit(prevPair);
|
|
}
|
|
} else {
|
|
prevPair = entry;
|
|
var ref = entry.split(">");
|
|
var a5 = ref[0];
|
|
var b = ref[1];
|
|
a5 = String.fromCodePoint(lastCode += parseInt(a5, radix));
|
|
b = String.fromCodePoint(lastCode += parseInt(b, radix));
|
|
map3.set(a5, b);
|
|
includeReverse && reverseMap.set(b, a5);
|
|
}
|
|
});
|
|
return { map: map3, reverseMap };
|
|
}
|
|
var openToClose, closeToOpen, canonical;
|
|
function parse$1() {
|
|
if (!openToClose) {
|
|
var ref = parseCharacterMap(data$1.pairs, true);
|
|
var map3 = ref.map;
|
|
var reverseMap = ref.reverseMap;
|
|
openToClose = map3;
|
|
closeToOpen = reverseMap;
|
|
canonical = parseCharacterMap(data$1.canonical, false).map;
|
|
}
|
|
}
|
|
function openingToClosingBracket(char) {
|
|
parse$1();
|
|
return openToClose.get(char) || null;
|
|
}
|
|
function closingToOpeningBracket(char) {
|
|
parse$1();
|
|
return closeToOpen.get(char) || null;
|
|
}
|
|
function getCanonicalBracket(char) {
|
|
parse$1();
|
|
return canonical.get(char) || null;
|
|
}
|
|
var TYPE_L = TYPES.L;
|
|
var TYPE_R = TYPES.R;
|
|
var TYPE_EN = TYPES.EN;
|
|
var TYPE_ES = TYPES.ES;
|
|
var TYPE_ET = TYPES.ET;
|
|
var TYPE_AN = TYPES.AN;
|
|
var TYPE_CS = TYPES.CS;
|
|
var TYPE_B = TYPES.B;
|
|
var TYPE_S = TYPES.S;
|
|
var TYPE_ON = TYPES.ON;
|
|
var TYPE_BN = TYPES.BN;
|
|
var TYPE_NSM = TYPES.NSM;
|
|
var TYPE_AL = TYPES.AL;
|
|
var TYPE_LRO = TYPES.LRO;
|
|
var TYPE_RLO = TYPES.RLO;
|
|
var TYPE_LRE = TYPES.LRE;
|
|
var TYPE_RLE = TYPES.RLE;
|
|
var TYPE_PDF = TYPES.PDF;
|
|
var TYPE_LRI = TYPES.LRI;
|
|
var TYPE_RLI = TYPES.RLI;
|
|
var TYPE_FSI = TYPES.FSI;
|
|
var TYPE_PDI = TYPES.PDI;
|
|
function getEmbeddingLevels(string, baseDirection) {
|
|
var MAX_DEPTH = 125;
|
|
var charTypes = new Uint32Array(string.length);
|
|
for (var i3 = 0; i3 < string.length; i3++) {
|
|
charTypes[i3] = getBidiCharType(string[i3]);
|
|
}
|
|
var charTypeCounts = /* @__PURE__ */ new Map();
|
|
function changeCharType(i4, type2) {
|
|
var oldType = charTypes[i4];
|
|
charTypes[i4] = type2;
|
|
charTypeCounts.set(oldType, charTypeCounts.get(oldType) - 1);
|
|
if (oldType & NEUTRAL_ISOLATE_TYPES) {
|
|
charTypeCounts.set(NEUTRAL_ISOLATE_TYPES, charTypeCounts.get(NEUTRAL_ISOLATE_TYPES) - 1);
|
|
}
|
|
charTypeCounts.set(type2, (charTypeCounts.get(type2) || 0) + 1);
|
|
if (type2 & NEUTRAL_ISOLATE_TYPES) {
|
|
charTypeCounts.set(NEUTRAL_ISOLATE_TYPES, (charTypeCounts.get(NEUTRAL_ISOLATE_TYPES) || 0) + 1);
|
|
}
|
|
}
|
|
var embedLevels = new Uint8Array(string.length);
|
|
var isolationPairs = /* @__PURE__ */ new Map();
|
|
var paragraphs = [];
|
|
var paragraph = null;
|
|
for (var i$1 = 0; i$1 < string.length; i$1++) {
|
|
if (!paragraph) {
|
|
paragraphs.push(paragraph = {
|
|
start: i$1,
|
|
end: string.length - 1,
|
|
// 3.3.1 P2-P3: Determine the paragraph level
|
|
level: baseDirection === "rtl" ? 1 : baseDirection === "ltr" ? 0 : determineAutoEmbedLevel(i$1, false)
|
|
});
|
|
}
|
|
if (charTypes[i$1] & TYPE_B) {
|
|
paragraph.end = i$1;
|
|
paragraph = null;
|
|
}
|
|
}
|
|
var FORMATTING_TYPES = TYPE_RLE | TYPE_LRE | TYPE_RLO | TYPE_LRO | ISOLATE_INIT_TYPES | TYPE_PDI | TYPE_PDF | TYPE_B;
|
|
var nextEven = function(n2) {
|
|
return n2 + (n2 & 1 ? 1 : 2);
|
|
};
|
|
var nextOdd = function(n2) {
|
|
return n2 + (n2 & 1 ? 2 : 1);
|
|
};
|
|
for (var paraIdx = 0; paraIdx < paragraphs.length; paraIdx++) {
|
|
paragraph = paragraphs[paraIdx];
|
|
var statusStack = [{
|
|
_level: paragraph.level,
|
|
_override: 0,
|
|
//0=neutral, 1=L, 2=R
|
|
_isolate: 0
|
|
//bool
|
|
}];
|
|
var stackTop = void 0;
|
|
var overflowIsolateCount = 0;
|
|
var overflowEmbeddingCount = 0;
|
|
var validIsolateCount = 0;
|
|
charTypeCounts.clear();
|
|
for (var i$2 = paragraph.start; i$2 <= paragraph.end; i$2++) {
|
|
var charType = charTypes[i$2];
|
|
stackTop = statusStack[statusStack.length - 1];
|
|
charTypeCounts.set(charType, (charTypeCounts.get(charType) || 0) + 1);
|
|
if (charType & NEUTRAL_ISOLATE_TYPES) {
|
|
charTypeCounts.set(NEUTRAL_ISOLATE_TYPES, (charTypeCounts.get(NEUTRAL_ISOLATE_TYPES) || 0) + 1);
|
|
}
|
|
if (charType & FORMATTING_TYPES) {
|
|
if (charType & (TYPE_RLE | TYPE_LRE)) {
|
|
embedLevels[i$2] = stackTop._level;
|
|
var level = (charType === TYPE_RLE ? nextOdd : nextEven)(stackTop._level);
|
|
if (level <= MAX_DEPTH && !overflowIsolateCount && !overflowEmbeddingCount) {
|
|
statusStack.push({
|
|
_level: level,
|
|
_override: 0,
|
|
_isolate: 0
|
|
});
|
|
} else if (!overflowIsolateCount) {
|
|
overflowEmbeddingCount++;
|
|
}
|
|
} else if (charType & (TYPE_RLO | TYPE_LRO)) {
|
|
embedLevels[i$2] = stackTop._level;
|
|
var level$1 = (charType === TYPE_RLO ? nextOdd : nextEven)(stackTop._level);
|
|
if (level$1 <= MAX_DEPTH && !overflowIsolateCount && !overflowEmbeddingCount) {
|
|
statusStack.push({
|
|
_level: level$1,
|
|
_override: charType & TYPE_RLO ? TYPE_R : TYPE_L,
|
|
_isolate: 0
|
|
});
|
|
} else if (!overflowIsolateCount) {
|
|
overflowEmbeddingCount++;
|
|
}
|
|
} else if (charType & ISOLATE_INIT_TYPES) {
|
|
if (charType & TYPE_FSI) {
|
|
charType = determineAutoEmbedLevel(i$2 + 1, true) === 1 ? TYPE_RLI : TYPE_LRI;
|
|
}
|
|
embedLevels[i$2] = stackTop._level;
|
|
if (stackTop._override) {
|
|
changeCharType(i$2, stackTop._override);
|
|
}
|
|
var level$2 = (charType === TYPE_RLI ? nextOdd : nextEven)(stackTop._level);
|
|
if (level$2 <= MAX_DEPTH && overflowIsolateCount === 0 && overflowEmbeddingCount === 0) {
|
|
validIsolateCount++;
|
|
statusStack.push({
|
|
_level: level$2,
|
|
_override: 0,
|
|
_isolate: 1,
|
|
_isolInitIndex: i$2
|
|
});
|
|
} else {
|
|
overflowIsolateCount++;
|
|
}
|
|
} else if (charType & TYPE_PDI) {
|
|
if (overflowIsolateCount > 0) {
|
|
overflowIsolateCount--;
|
|
} else if (validIsolateCount > 0) {
|
|
overflowEmbeddingCount = 0;
|
|
while (!statusStack[statusStack.length - 1]._isolate) {
|
|
statusStack.pop();
|
|
}
|
|
var isolInitIndex = statusStack[statusStack.length - 1]._isolInitIndex;
|
|
if (isolInitIndex != null) {
|
|
isolationPairs.set(isolInitIndex, i$2);
|
|
isolationPairs.set(i$2, isolInitIndex);
|
|
}
|
|
statusStack.pop();
|
|
validIsolateCount--;
|
|
}
|
|
stackTop = statusStack[statusStack.length - 1];
|
|
embedLevels[i$2] = stackTop._level;
|
|
if (stackTop._override) {
|
|
changeCharType(i$2, stackTop._override);
|
|
}
|
|
} else if (charType & TYPE_PDF) {
|
|
if (overflowIsolateCount === 0) {
|
|
if (overflowEmbeddingCount > 0) {
|
|
overflowEmbeddingCount--;
|
|
} else if (!stackTop._isolate && statusStack.length > 1) {
|
|
statusStack.pop();
|
|
stackTop = statusStack[statusStack.length - 1];
|
|
}
|
|
}
|
|
embedLevels[i$2] = stackTop._level;
|
|
} else if (charType & TYPE_B) {
|
|
embedLevels[i$2] = paragraph.level;
|
|
}
|
|
} else {
|
|
embedLevels[i$2] = stackTop._level;
|
|
if (stackTop._override && charType !== TYPE_BN) {
|
|
changeCharType(i$2, stackTop._override);
|
|
}
|
|
}
|
|
}
|
|
var levelRuns = [];
|
|
var currentRun = null;
|
|
for (var i$3 = paragraph.start; i$3 <= paragraph.end; i$3++) {
|
|
var charType$1 = charTypes[i$3];
|
|
if (!(charType$1 & BN_LIKE_TYPES)) {
|
|
var lvl = embedLevels[i$3];
|
|
var isIsolInit = charType$1 & ISOLATE_INIT_TYPES;
|
|
var isPDI = charType$1 === TYPE_PDI;
|
|
if (currentRun && lvl === currentRun._level) {
|
|
currentRun._end = i$3;
|
|
currentRun._endsWithIsolInit = isIsolInit;
|
|
} else {
|
|
levelRuns.push(currentRun = {
|
|
_start: i$3,
|
|
_end: i$3,
|
|
_level: lvl,
|
|
_startsWithPDI: isPDI,
|
|
_endsWithIsolInit: isIsolInit
|
|
});
|
|
}
|
|
}
|
|
}
|
|
var isolatingRunSeqs = [];
|
|
for (var runIdx = 0; runIdx < levelRuns.length; runIdx++) {
|
|
var run = levelRuns[runIdx];
|
|
if (!run._startsWithPDI || run._startsWithPDI && !isolationPairs.has(run._start)) {
|
|
var seqRuns = [currentRun = run];
|
|
for (var pdiIndex = void 0; currentRun && currentRun._endsWithIsolInit && (pdiIndex = isolationPairs.get(currentRun._end)) != null; ) {
|
|
for (var i$4 = runIdx + 1; i$4 < levelRuns.length; i$4++) {
|
|
if (levelRuns[i$4]._start === pdiIndex) {
|
|
seqRuns.push(currentRun = levelRuns[i$4]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
var seqIndices = [];
|
|
for (var i$5 = 0; i$5 < seqRuns.length; i$5++) {
|
|
var run$1 = seqRuns[i$5];
|
|
for (var j = run$1._start; j <= run$1._end; j++) {
|
|
seqIndices.push(j);
|
|
}
|
|
}
|
|
var firstLevel = embedLevels[seqIndices[0]];
|
|
var prevLevel = paragraph.level;
|
|
for (var i$6 = seqIndices[0] - 1; i$6 >= 0; i$6--) {
|
|
if (!(charTypes[i$6] & BN_LIKE_TYPES)) {
|
|
prevLevel = embedLevels[i$6];
|
|
break;
|
|
}
|
|
}
|
|
var lastIndex = seqIndices[seqIndices.length - 1];
|
|
var lastLevel = embedLevels[lastIndex];
|
|
var nextLevel = paragraph.level;
|
|
if (!(charTypes[lastIndex] & ISOLATE_INIT_TYPES)) {
|
|
for (var i$7 = lastIndex + 1; i$7 <= paragraph.end; i$7++) {
|
|
if (!(charTypes[i$7] & BN_LIKE_TYPES)) {
|
|
nextLevel = embedLevels[i$7];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
isolatingRunSeqs.push({
|
|
_seqIndices: seqIndices,
|
|
_sosType: Math.max(prevLevel, firstLevel) % 2 ? TYPE_R : TYPE_L,
|
|
_eosType: Math.max(nextLevel, lastLevel) % 2 ? TYPE_R : TYPE_L
|
|
});
|
|
}
|
|
}
|
|
for (var seqIdx = 0; seqIdx < isolatingRunSeqs.length; seqIdx++) {
|
|
var ref = isolatingRunSeqs[seqIdx];
|
|
var seqIndices$1 = ref._seqIndices;
|
|
var sosType = ref._sosType;
|
|
var eosType = ref._eosType;
|
|
var embedDirection = embedLevels[seqIndices$1[0]] & 1 ? TYPE_R : TYPE_L;
|
|
if (charTypeCounts.get(TYPE_NSM)) {
|
|
for (var si = 0; si < seqIndices$1.length; si++) {
|
|
var i$8 = seqIndices$1[si];
|
|
if (charTypes[i$8] & TYPE_NSM) {
|
|
var prevType = sosType;
|
|
for (var sj = si - 1; sj >= 0; sj--) {
|
|
if (!(charTypes[seqIndices$1[sj]] & BN_LIKE_TYPES)) {
|
|
prevType = charTypes[seqIndices$1[sj]];
|
|
break;
|
|
}
|
|
}
|
|
changeCharType(i$8, prevType & (ISOLATE_INIT_TYPES | TYPE_PDI) ? TYPE_ON : prevType);
|
|
}
|
|
}
|
|
}
|
|
if (charTypeCounts.get(TYPE_EN)) {
|
|
for (var si$1 = 0; si$1 < seqIndices$1.length; si$1++) {
|
|
var i$9 = seqIndices$1[si$1];
|
|
if (charTypes[i$9] & TYPE_EN) {
|
|
for (var sj$1 = si$1 - 1; sj$1 >= -1; sj$1--) {
|
|
var prevCharType = sj$1 === -1 ? sosType : charTypes[seqIndices$1[sj$1]];
|
|
if (prevCharType & STRONG_TYPES) {
|
|
if (prevCharType === TYPE_AL) {
|
|
changeCharType(i$9, TYPE_AN);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (charTypeCounts.get(TYPE_AL)) {
|
|
for (var si$2 = 0; si$2 < seqIndices$1.length; si$2++) {
|
|
var i$10 = seqIndices$1[si$2];
|
|
if (charTypes[i$10] & TYPE_AL) {
|
|
changeCharType(i$10, TYPE_R);
|
|
}
|
|
}
|
|
}
|
|
if (charTypeCounts.get(TYPE_ES) || charTypeCounts.get(TYPE_CS)) {
|
|
for (var si$3 = 1; si$3 < seqIndices$1.length - 1; si$3++) {
|
|
var i$11 = seqIndices$1[si$3];
|
|
if (charTypes[i$11] & (TYPE_ES | TYPE_CS)) {
|
|
var prevType$1 = 0, nextType = 0;
|
|
for (var sj$2 = si$3 - 1; sj$2 >= 0; sj$2--) {
|
|
prevType$1 = charTypes[seqIndices$1[sj$2]];
|
|
if (!(prevType$1 & BN_LIKE_TYPES)) {
|
|
break;
|
|
}
|
|
}
|
|
for (var sj$3 = si$3 + 1; sj$3 < seqIndices$1.length; sj$3++) {
|
|
nextType = charTypes[seqIndices$1[sj$3]];
|
|
if (!(nextType & BN_LIKE_TYPES)) {
|
|
break;
|
|
}
|
|
}
|
|
if (prevType$1 === nextType && (charTypes[i$11] === TYPE_ES ? prevType$1 === TYPE_EN : prevType$1 & (TYPE_EN | TYPE_AN))) {
|
|
changeCharType(i$11, prevType$1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (charTypeCounts.get(TYPE_EN)) {
|
|
for (var si$4 = 0; si$4 < seqIndices$1.length; si$4++) {
|
|
var i$12 = seqIndices$1[si$4];
|
|
if (charTypes[i$12] & TYPE_EN) {
|
|
for (var sj$4 = si$4 - 1; sj$4 >= 0 && charTypes[seqIndices$1[sj$4]] & (TYPE_ET | BN_LIKE_TYPES); sj$4--) {
|
|
changeCharType(seqIndices$1[sj$4], TYPE_EN);
|
|
}
|
|
for (si$4++; si$4 < seqIndices$1.length && charTypes[seqIndices$1[si$4]] & (TYPE_ET | BN_LIKE_TYPES | TYPE_EN); si$4++) {
|
|
if (charTypes[seqIndices$1[si$4]] !== TYPE_EN) {
|
|
changeCharType(seqIndices$1[si$4], TYPE_EN);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (charTypeCounts.get(TYPE_ET) || charTypeCounts.get(TYPE_ES) || charTypeCounts.get(TYPE_CS)) {
|
|
for (var si$5 = 0; si$5 < seqIndices$1.length; si$5++) {
|
|
var i$13 = seqIndices$1[si$5];
|
|
if (charTypes[i$13] & (TYPE_ET | TYPE_ES | TYPE_CS)) {
|
|
changeCharType(i$13, TYPE_ON);
|
|
for (var sj$5 = si$5 - 1; sj$5 >= 0 && charTypes[seqIndices$1[sj$5]] & BN_LIKE_TYPES; sj$5--) {
|
|
changeCharType(seqIndices$1[sj$5], TYPE_ON);
|
|
}
|
|
for (var sj$6 = si$5 + 1; sj$6 < seqIndices$1.length && charTypes[seqIndices$1[sj$6]] & BN_LIKE_TYPES; sj$6++) {
|
|
changeCharType(seqIndices$1[sj$6], TYPE_ON);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (charTypeCounts.get(TYPE_EN)) {
|
|
for (var si$6 = 0, prevStrongType = sosType; si$6 < seqIndices$1.length; si$6++) {
|
|
var i$14 = seqIndices$1[si$6];
|
|
var type = charTypes[i$14];
|
|
if (type & TYPE_EN) {
|
|
if (prevStrongType === TYPE_L) {
|
|
changeCharType(i$14, TYPE_L);
|
|
}
|
|
} else if (type & STRONG_TYPES) {
|
|
prevStrongType = type;
|
|
}
|
|
}
|
|
}
|
|
if (charTypeCounts.get(NEUTRAL_ISOLATE_TYPES)) {
|
|
var R_TYPES_FOR_N_STEPS = TYPE_R | TYPE_EN | TYPE_AN;
|
|
var STRONG_TYPES_FOR_N_STEPS = R_TYPES_FOR_N_STEPS | TYPE_L;
|
|
var bracketPairs = [];
|
|
{
|
|
var openerStack = [];
|
|
for (var si$7 = 0; si$7 < seqIndices$1.length; si$7++) {
|
|
if (charTypes[seqIndices$1[si$7]] & NEUTRAL_ISOLATE_TYPES) {
|
|
var char = string[seqIndices$1[si$7]];
|
|
var oppositeBracket = void 0;
|
|
if (openingToClosingBracket(char) !== null) {
|
|
if (openerStack.length < 63) {
|
|
openerStack.push({ char, seqIndex: si$7 });
|
|
} else {
|
|
break;
|
|
}
|
|
} else if ((oppositeBracket = closingToOpeningBracket(char)) !== null) {
|
|
for (var stackIdx = openerStack.length - 1; stackIdx >= 0; stackIdx--) {
|
|
var stackChar = openerStack[stackIdx].char;
|
|
if (stackChar === oppositeBracket || stackChar === closingToOpeningBracket(getCanonicalBracket(char)) || openingToClosingBracket(getCanonicalBracket(stackChar)) === char) {
|
|
bracketPairs.push([openerStack[stackIdx].seqIndex, si$7]);
|
|
openerStack.length = stackIdx;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
bracketPairs.sort(function(a5, b) {
|
|
return a5[0] - b[0];
|
|
});
|
|
}
|
|
for (var pairIdx = 0; pairIdx < bracketPairs.length; pairIdx++) {
|
|
var ref$1 = bracketPairs[pairIdx];
|
|
var openSeqIdx = ref$1[0];
|
|
var closeSeqIdx = ref$1[1];
|
|
var foundStrongType = false;
|
|
var useStrongType = 0;
|
|
for (var si$8 = openSeqIdx + 1; si$8 < closeSeqIdx; si$8++) {
|
|
var i$15 = seqIndices$1[si$8];
|
|
if (charTypes[i$15] & STRONG_TYPES_FOR_N_STEPS) {
|
|
foundStrongType = true;
|
|
var lr = charTypes[i$15] & R_TYPES_FOR_N_STEPS ? TYPE_R : TYPE_L;
|
|
if (lr === embedDirection) {
|
|
useStrongType = lr;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (foundStrongType && !useStrongType) {
|
|
useStrongType = sosType;
|
|
for (var si$9 = openSeqIdx - 1; si$9 >= 0; si$9--) {
|
|
var i$16 = seqIndices$1[si$9];
|
|
if (charTypes[i$16] & STRONG_TYPES_FOR_N_STEPS) {
|
|
var lr$1 = charTypes[i$16] & R_TYPES_FOR_N_STEPS ? TYPE_R : TYPE_L;
|
|
if (lr$1 !== embedDirection) {
|
|
useStrongType = lr$1;
|
|
} else {
|
|
useStrongType = embedDirection;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (useStrongType) {
|
|
charTypes[seqIndices$1[openSeqIdx]] = charTypes[seqIndices$1[closeSeqIdx]] = useStrongType;
|
|
if (useStrongType !== embedDirection) {
|
|
for (var si$10 = openSeqIdx + 1; si$10 < seqIndices$1.length; si$10++) {
|
|
if (!(charTypes[seqIndices$1[si$10]] & BN_LIKE_TYPES)) {
|
|
if (getBidiCharType(string[seqIndices$1[si$10]]) & TYPE_NSM) {
|
|
charTypes[seqIndices$1[si$10]] = useStrongType;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (useStrongType !== embedDirection) {
|
|
for (var si$11 = closeSeqIdx + 1; si$11 < seqIndices$1.length; si$11++) {
|
|
if (!(charTypes[seqIndices$1[si$11]] & BN_LIKE_TYPES)) {
|
|
if (getBidiCharType(string[seqIndices$1[si$11]]) & TYPE_NSM) {
|
|
charTypes[seqIndices$1[si$11]] = useStrongType;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (var si$12 = 0; si$12 < seqIndices$1.length; si$12++) {
|
|
if (charTypes[seqIndices$1[si$12]] & NEUTRAL_ISOLATE_TYPES) {
|
|
var niRunStart = si$12, niRunEnd = si$12;
|
|
var prevType$2 = sosType;
|
|
for (var si2 = si$12 - 1; si2 >= 0; si2--) {
|
|
if (charTypes[seqIndices$1[si2]] & BN_LIKE_TYPES) {
|
|
niRunStart = si2;
|
|
} else {
|
|
prevType$2 = charTypes[seqIndices$1[si2]] & R_TYPES_FOR_N_STEPS ? TYPE_R : TYPE_L;
|
|
break;
|
|
}
|
|
}
|
|
var nextType$1 = eosType;
|
|
for (var si2$1 = si$12 + 1; si2$1 < seqIndices$1.length; si2$1++) {
|
|
if (charTypes[seqIndices$1[si2$1]] & (NEUTRAL_ISOLATE_TYPES | BN_LIKE_TYPES)) {
|
|
niRunEnd = si2$1;
|
|
} else {
|
|
nextType$1 = charTypes[seqIndices$1[si2$1]] & R_TYPES_FOR_N_STEPS ? TYPE_R : TYPE_L;
|
|
break;
|
|
}
|
|
}
|
|
for (var sj$7 = niRunStart; sj$7 <= niRunEnd; sj$7++) {
|
|
charTypes[seqIndices$1[sj$7]] = prevType$2 === nextType$1 ? prevType$2 : embedDirection;
|
|
}
|
|
si$12 = niRunEnd;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (var i$17 = paragraph.start; i$17 <= paragraph.end; i$17++) {
|
|
var level$3 = embedLevels[i$17];
|
|
var type$1 = charTypes[i$17];
|
|
if (level$3 & 1) {
|
|
if (type$1 & (TYPE_L | TYPE_EN | TYPE_AN)) {
|
|
embedLevels[i$17]++;
|
|
}
|
|
} else {
|
|
if (type$1 & TYPE_R) {
|
|
embedLevels[i$17]++;
|
|
} else if (type$1 & (TYPE_AN | TYPE_EN)) {
|
|
embedLevels[i$17] += 2;
|
|
}
|
|
}
|
|
if (type$1 & BN_LIKE_TYPES) {
|
|
embedLevels[i$17] = i$17 === 0 ? paragraph.level : embedLevels[i$17 - 1];
|
|
}
|
|
if (i$17 === paragraph.end || getBidiCharType(string[i$17]) & (TYPE_S | TYPE_B)) {
|
|
for (var j$1 = i$17; j$1 >= 0 && getBidiCharType(string[j$1]) & TRAILING_TYPES; j$1--) {
|
|
embedLevels[j$1] = paragraph.level;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return {
|
|
levels: embedLevels,
|
|
paragraphs
|
|
};
|
|
function determineAutoEmbedLevel(start, isFSI) {
|
|
for (var i4 = start; i4 < string.length; i4++) {
|
|
var charType2 = charTypes[i4];
|
|
if (charType2 & (TYPE_R | TYPE_AL)) {
|
|
return 1;
|
|
}
|
|
if (charType2 & (TYPE_B | TYPE_L) || isFSI && charType2 === TYPE_PDI) {
|
|
return 0;
|
|
}
|
|
if (charType2 & ISOLATE_INIT_TYPES) {
|
|
var pdi = indexOfMatchingPDI(i4);
|
|
i4 = pdi === -1 ? string.length : pdi;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
function indexOfMatchingPDI(isolateStart) {
|
|
var isolationLevel = 1;
|
|
for (var i4 = isolateStart + 1; i4 < string.length; i4++) {
|
|
var charType2 = charTypes[i4];
|
|
if (charType2 & TYPE_B) {
|
|
break;
|
|
}
|
|
if (charType2 & TYPE_PDI) {
|
|
if (--isolationLevel === 0) {
|
|
return i4;
|
|
}
|
|
} else if (charType2 & ISOLATE_INIT_TYPES) {
|
|
isolationLevel++;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
}
|
|
var data = "14>1,j>2,t>2,u>2,1a>g,2v3>1,1>1,1ge>1,1wd>1,b>1,1j>1,f>1,ai>3,-2>3,+1,8>1k0,-1jq>1y7,-1y6>1hf,-1he>1h6,-1h5>1ha,-1h8>1qi,-1pu>1,6>3u,-3s>7,6>1,1>1,f>1,1>1,+2,3>1,1>1,+13,4>1,1>1,6>1eo,-1ee>1,3>1mg,-1me>1mk,-1mj>1mi,-1mg>1mi,-1md>1,1>1,+2,1>10k,-103>1,1>1,4>1,5>1,1>1,+10,3>1,1>8,-7>8,+1,-6>7,+1,a>1,1>1,u>1,u6>1,1>1,+5,26>1,1>1,2>1,2>2,8>1,7>1,4>1,1>1,+5,b8>1,1>1,+3,1>3,-2>1,2>1,1>1,+2,c>1,3>1,1>1,+2,h>1,3>1,a>1,1>1,2>1,3>1,1>1,d>1,f>1,3>1,1a>1,1>1,6>1,7>1,13>1,k>1,1>1,+19,4>1,1>1,+2,2>1,1>1,+18,m>1,a>1,1>1,lk>1,1>1,4>1,2>1,f>1,3>1,1>1,+3,db>1,1>1,+3,3>1,1>1,+2,14qm>1,1>1,+1,6>1,4j>1,j>2,t>2,u>2,2>1,+1";
|
|
var mirrorMap;
|
|
function parse2() {
|
|
if (!mirrorMap) {
|
|
var ref = parseCharacterMap(data, true);
|
|
var map3 = ref.map;
|
|
var reverseMap = ref.reverseMap;
|
|
reverseMap.forEach(function(value, key) {
|
|
map3.set(key, value);
|
|
});
|
|
mirrorMap = map3;
|
|
}
|
|
}
|
|
function getMirroredCharacter(char) {
|
|
parse2();
|
|
return mirrorMap.get(char) || null;
|
|
}
|
|
function getMirroredCharactersMap(string, embeddingLevels, start, end) {
|
|
var strLen = string.length;
|
|
start = Math.max(0, start == null ? 0 : +start);
|
|
end = Math.min(strLen - 1, end == null ? strLen - 1 : +end);
|
|
var map3 = /* @__PURE__ */ new Map();
|
|
for (var i3 = start; i3 <= end; i3++) {
|
|
if (embeddingLevels[i3] & 1) {
|
|
var mirror = getMirroredCharacter(string[i3]);
|
|
if (mirror !== null) {
|
|
map3.set(i3, mirror);
|
|
}
|
|
}
|
|
}
|
|
return map3;
|
|
}
|
|
function getReorderSegments(string, embeddingLevelsResult, start, end) {
|
|
var strLen = string.length;
|
|
start = Math.max(0, start == null ? 0 : +start);
|
|
end = Math.min(strLen - 1, end == null ? strLen - 1 : +end);
|
|
var segments = [];
|
|
embeddingLevelsResult.paragraphs.forEach(function(paragraph) {
|
|
var lineStart = Math.max(start, paragraph.start);
|
|
var lineEnd = Math.min(end, paragraph.end);
|
|
if (lineStart < lineEnd) {
|
|
var lineLevels = embeddingLevelsResult.levels.slice(lineStart, lineEnd + 1);
|
|
for (var i3 = lineEnd; i3 >= lineStart && getBidiCharType(string[i3]) & TRAILING_TYPES; i3--) {
|
|
lineLevels[i3] = paragraph.level;
|
|
}
|
|
var maxLevel = paragraph.level;
|
|
var minOddLevel = Infinity;
|
|
for (var i$1 = 0; i$1 < lineLevels.length; i$1++) {
|
|
var level = lineLevels[i$1];
|
|
if (level > maxLevel) {
|
|
maxLevel = level;
|
|
}
|
|
if (level < minOddLevel) {
|
|
minOddLevel = level | 1;
|
|
}
|
|
}
|
|
for (var lvl = maxLevel; lvl >= minOddLevel; lvl--) {
|
|
for (var i$2 = 0; i$2 < lineLevels.length; i$2++) {
|
|
if (lineLevels[i$2] >= lvl) {
|
|
var segStart = i$2;
|
|
while (i$2 + 1 < lineLevels.length && lineLevels[i$2 + 1] >= lvl) {
|
|
i$2++;
|
|
}
|
|
if (i$2 > segStart) {
|
|
segments.push([segStart + lineStart, i$2 + lineStart]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
return segments;
|
|
}
|
|
function getReorderedString(string, embedLevelsResult, start, end) {
|
|
var indices = getReorderedIndices(string, embedLevelsResult, start, end);
|
|
var chars = [].concat(string);
|
|
indices.forEach(function(charIndex, i3) {
|
|
chars[i3] = (embedLevelsResult.levels[charIndex] & 1 ? getMirroredCharacter(string[charIndex]) : null) || string[charIndex];
|
|
});
|
|
return chars.join("");
|
|
}
|
|
function getReorderedIndices(string, embedLevelsResult, start, end) {
|
|
var segments = getReorderSegments(string, embedLevelsResult, start, end);
|
|
var indices = [];
|
|
for (var i3 = 0; i3 < string.length; i3++) {
|
|
indices[i3] = i3;
|
|
}
|
|
segments.forEach(function(ref) {
|
|
var start2 = ref[0];
|
|
var end2 = ref[1];
|
|
var slice = indices.slice(start2, end2 + 1);
|
|
for (var i4 = slice.length; i4--; ) {
|
|
indices[end2 - i4] = slice[i4];
|
|
}
|
|
});
|
|
return indices;
|
|
}
|
|
exports.closingToOpeningBracket = closingToOpeningBracket;
|
|
exports.getBidiCharType = getBidiCharType;
|
|
exports.getBidiCharTypeName = getBidiCharTypeName;
|
|
exports.getCanonicalBracket = getCanonicalBracket;
|
|
exports.getEmbeddingLevels = getEmbeddingLevels;
|
|
exports.getMirroredCharacter = getMirroredCharacter;
|
|
exports.getMirroredCharactersMap = getMirroredCharactersMap;
|
|
exports.getReorderSegments = getReorderSegments;
|
|
exports.getReorderedIndices = getReorderedIndices;
|
|
exports.getReorderedString = getReorderedString;
|
|
exports.openingToClosingBracket = openingToClosingBracket;
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
return exports;
|
|
})({});
|
|
return bidi;
|
|
}
|
|
var bidi_default = bidiFactory;
|
|
|
|
// node_modules/troika-three-utils/dist/troika-three-utils.esm.js
|
|
var voidMainRegExp = /\bvoid\s+main\s*\(\s*\)\s*{/g;
|
|
function expandShaderIncludes(source) {
|
|
const pattern = /^[ \t]*#include +<([\w\d./]+)>/gm;
|
|
function replace(match, include) {
|
|
let chunk = ShaderChunk[include];
|
|
return chunk ? expandShaderIncludes(chunk) : match;
|
|
}
|
|
return source.replace(pattern, replace);
|
|
}
|
|
var _lut = [];
|
|
for (let i3 = 0; i3 < 256; i3++) {
|
|
_lut[i3] = (i3 < 16 ? "0" : "") + i3.toString(16);
|
|
}
|
|
function generateUUID() {
|
|
const d0 = Math.random() * 4294967295 | 0;
|
|
const d1 = Math.random() * 4294967295 | 0;
|
|
const d2 = Math.random() * 4294967295 | 0;
|
|
const d3 = Math.random() * 4294967295 | 0;
|
|
const uuid = _lut[d0 & 255] + _lut[d0 >> 8 & 255] + _lut[d0 >> 16 & 255] + _lut[d0 >> 24 & 255] + "-" + _lut[d1 & 255] + _lut[d1 >> 8 & 255] + "-" + _lut[d1 >> 16 & 15 | 64] + _lut[d1 >> 24 & 255] + "-" + _lut[d2 & 63 | 128] + _lut[d2 >> 8 & 255] + "-" + _lut[d2 >> 16 & 255] + _lut[d2 >> 24 & 255] + _lut[d3 & 255] + _lut[d3 >> 8 & 255] + _lut[d3 >> 16 & 255] + _lut[d3 >> 24 & 255];
|
|
return uuid.toUpperCase();
|
|
}
|
|
var assign = Object.assign || function() {
|
|
let target2 = arguments[0];
|
|
for (let i3 = 1, len = arguments.length; i3 < len; i3++) {
|
|
let source = arguments[i3];
|
|
if (source) {
|
|
for (let prop in source) {
|
|
if (Object.prototype.hasOwnProperty.call(source, prop)) {
|
|
target2[prop] = source[prop];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return target2;
|
|
};
|
|
var epoch = Date.now();
|
|
var CONSTRUCTOR_CACHE = /* @__PURE__ */ new WeakMap();
|
|
var SHADER_UPGRADE_CACHE = /* @__PURE__ */ new Map();
|
|
var materialInstanceId = 1e10;
|
|
function createDerivedMaterial(baseMaterial, options) {
|
|
const optionsKey = getKeyForOptions(options);
|
|
let ctorsByDerivation = CONSTRUCTOR_CACHE.get(baseMaterial);
|
|
if (!ctorsByDerivation) {
|
|
CONSTRUCTOR_CACHE.set(baseMaterial, ctorsByDerivation = /* @__PURE__ */ Object.create(null));
|
|
}
|
|
if (ctorsByDerivation[optionsKey]) {
|
|
return new ctorsByDerivation[optionsKey]();
|
|
}
|
|
const privateBeforeCompileProp = `_onBeforeCompile${optionsKey}`;
|
|
const onBeforeCompile = function(shaderInfo, renderer) {
|
|
baseMaterial.onBeforeCompile.call(this, shaderInfo, renderer);
|
|
const cacheKey = this.customProgramCacheKey() + "|" + shaderInfo.vertexShader + "|" + shaderInfo.fragmentShader;
|
|
let upgradedShaders = SHADER_UPGRADE_CACHE[cacheKey];
|
|
if (!upgradedShaders) {
|
|
const upgraded = upgradeShaders(this, shaderInfo, options, optionsKey);
|
|
upgradedShaders = SHADER_UPGRADE_CACHE[cacheKey] = upgraded;
|
|
}
|
|
shaderInfo.vertexShader = upgradedShaders.vertexShader;
|
|
shaderInfo.fragmentShader = upgradedShaders.fragmentShader;
|
|
assign(shaderInfo.uniforms, this.uniforms);
|
|
if (options.timeUniform) {
|
|
shaderInfo.uniforms[options.timeUniform] = {
|
|
get value() {
|
|
return Date.now() - epoch;
|
|
}
|
|
};
|
|
}
|
|
if (this[privateBeforeCompileProp]) {
|
|
this[privateBeforeCompileProp](shaderInfo);
|
|
}
|
|
};
|
|
const DerivedMaterial = function DerivedMaterial2() {
|
|
return derive(options.chained ? baseMaterial : baseMaterial.clone());
|
|
};
|
|
const derive = function(base) {
|
|
const derived = Object.create(base, descriptor);
|
|
Object.defineProperty(derived, "baseMaterial", { value: baseMaterial });
|
|
Object.defineProperty(derived, "id", { value: materialInstanceId++ });
|
|
derived.uuid = generateUUID();
|
|
derived.uniforms = assign({}, base.uniforms, options.uniforms);
|
|
derived.defines = assign({}, base.defines, options.defines);
|
|
derived.defines[`TROIKA_DERIVED_MATERIAL_${optionsKey}`] = "";
|
|
derived.extensions = assign({}, base.extensions, options.extensions);
|
|
derived._listeners = void 0;
|
|
return derived;
|
|
};
|
|
const descriptor = {
|
|
constructor: { value: DerivedMaterial },
|
|
isDerivedMaterial: { value: true },
|
|
type: {
|
|
get: () => baseMaterial.type,
|
|
set: (value) => {
|
|
baseMaterial.type = value;
|
|
}
|
|
},
|
|
isDerivedFrom: {
|
|
writable: true,
|
|
configurable: true,
|
|
value: function(testMaterial) {
|
|
const base = this.baseMaterial;
|
|
return testMaterial === base || base.isDerivedMaterial && base.isDerivedFrom(testMaterial) || false;
|
|
}
|
|
},
|
|
customProgramCacheKey: {
|
|
writable: true,
|
|
configurable: true,
|
|
value: function() {
|
|
return baseMaterial.customProgramCacheKey() + "|" + optionsKey;
|
|
}
|
|
},
|
|
onBeforeCompile: {
|
|
get() {
|
|
return onBeforeCompile;
|
|
},
|
|
set(fn) {
|
|
this[privateBeforeCompileProp] = fn;
|
|
}
|
|
},
|
|
copy: {
|
|
writable: true,
|
|
configurable: true,
|
|
value: function(source) {
|
|
baseMaterial.copy.call(this, source);
|
|
if (!baseMaterial.isShaderMaterial && !baseMaterial.isDerivedMaterial) {
|
|
assign(this.extensions, source.extensions);
|
|
assign(this.defines, source.defines);
|
|
assign(this.uniforms, UniformsUtils.clone(source.uniforms));
|
|
}
|
|
return this;
|
|
}
|
|
},
|
|
clone: {
|
|
writable: true,
|
|
configurable: true,
|
|
value: function() {
|
|
const newBase = new baseMaterial.constructor();
|
|
return derive(newBase).copy(this);
|
|
}
|
|
},
|
|
/**
|
|
* Utility to get a MeshDepthMaterial that will honor this derived material's vertex
|
|
* transformations and discarded fragments.
|
|
*/
|
|
getDepthMaterial: {
|
|
writable: true,
|
|
configurable: true,
|
|
value: function() {
|
|
let depthMaterial = this._depthMaterial;
|
|
if (!depthMaterial) {
|
|
depthMaterial = this._depthMaterial = createDerivedMaterial(
|
|
baseMaterial.isDerivedMaterial ? baseMaterial.getDepthMaterial() : new MeshDepthMaterial({ depthPacking: RGBADepthPacking }),
|
|
options
|
|
);
|
|
depthMaterial.defines.IS_DEPTH_MATERIAL = "";
|
|
depthMaterial.uniforms = this.uniforms;
|
|
}
|
|
return depthMaterial;
|
|
}
|
|
},
|
|
/**
|
|
* Utility to get a MeshDistanceMaterial that will honor this derived material's vertex
|
|
* transformations and discarded fragments.
|
|
*/
|
|
getDistanceMaterial: {
|
|
writable: true,
|
|
configurable: true,
|
|
value: function() {
|
|
let distanceMaterial = this._distanceMaterial;
|
|
if (!distanceMaterial) {
|
|
distanceMaterial = this._distanceMaterial = createDerivedMaterial(
|
|
baseMaterial.isDerivedMaterial ? baseMaterial.getDistanceMaterial() : new MeshDistanceMaterial(),
|
|
options
|
|
);
|
|
distanceMaterial.defines.IS_DISTANCE_MATERIAL = "";
|
|
distanceMaterial.uniforms = this.uniforms;
|
|
}
|
|
return distanceMaterial;
|
|
}
|
|
},
|
|
dispose: {
|
|
writable: true,
|
|
configurable: true,
|
|
value() {
|
|
const { _depthMaterial, _distanceMaterial } = this;
|
|
if (_depthMaterial) _depthMaterial.dispose();
|
|
if (_distanceMaterial) _distanceMaterial.dispose();
|
|
baseMaterial.dispose.call(this);
|
|
}
|
|
}
|
|
};
|
|
ctorsByDerivation[optionsKey] = DerivedMaterial;
|
|
return new DerivedMaterial();
|
|
}
|
|
function upgradeShaders(material, { vertexShader: vertexShader3, fragmentShader: fragmentShader3 }, options, key) {
|
|
let {
|
|
vertexDefs,
|
|
vertexMainIntro,
|
|
vertexMainOutro,
|
|
vertexTransform,
|
|
fragmentDefs,
|
|
fragmentMainIntro,
|
|
fragmentMainOutro,
|
|
fragmentColorTransform,
|
|
customRewriter,
|
|
timeUniform
|
|
} = options;
|
|
vertexDefs = vertexDefs || "";
|
|
vertexMainIntro = vertexMainIntro || "";
|
|
vertexMainOutro = vertexMainOutro || "";
|
|
fragmentDefs = fragmentDefs || "";
|
|
fragmentMainIntro = fragmentMainIntro || "";
|
|
fragmentMainOutro = fragmentMainOutro || "";
|
|
if (vertexTransform || customRewriter) {
|
|
vertexShader3 = expandShaderIncludes(vertexShader3);
|
|
}
|
|
if (fragmentColorTransform || customRewriter) {
|
|
fragmentShader3 = fragmentShader3.replace(
|
|
/^[ \t]*#include <((?:tonemapping|encodings|colorspace|fog|premultiplied_alpha|dithering)_fragment)>/gm,
|
|
"\n//!BEGIN_POST_CHUNK $1\n$&\n//!END_POST_CHUNK\n"
|
|
);
|
|
fragmentShader3 = expandShaderIncludes(fragmentShader3);
|
|
}
|
|
if (customRewriter) {
|
|
let res = customRewriter({ vertexShader: vertexShader3, fragmentShader: fragmentShader3 });
|
|
vertexShader3 = res.vertexShader;
|
|
fragmentShader3 = res.fragmentShader;
|
|
}
|
|
if (fragmentColorTransform) {
|
|
let postChunks = [];
|
|
fragmentShader3 = fragmentShader3.replace(
|
|
/^\/\/!BEGIN_POST_CHUNK[^]+?^\/\/!END_POST_CHUNK/gm,
|
|
// [^]+? = non-greedy match of any chars including newlines
|
|
(match) => {
|
|
postChunks.push(match);
|
|
return "";
|
|
}
|
|
);
|
|
fragmentMainOutro = `${fragmentColorTransform}
|
|
${postChunks.join("\n")}
|
|
${fragmentMainOutro}`;
|
|
}
|
|
if (timeUniform) {
|
|
const code = `
|
|
uniform float ${timeUniform};
|
|
`;
|
|
vertexDefs = code + vertexDefs;
|
|
fragmentDefs = code + fragmentDefs;
|
|
}
|
|
if (vertexTransform) {
|
|
vertexShader3 = `vec3 troika_position_${key};
|
|
vec3 troika_normal_${key};
|
|
vec2 troika_uv_${key};
|
|
${vertexShader3}
|
|
`;
|
|
vertexDefs = `${vertexDefs}
|
|
void troikaVertexTransform${key}(inout vec3 position, inout vec3 normal, inout vec2 uv) {
|
|
${vertexTransform}
|
|
}
|
|
`;
|
|
vertexMainIntro = `
|
|
troika_position_${key} = vec3(position);
|
|
troika_normal_${key} = vec3(normal);
|
|
troika_uv_${key} = vec2(uv);
|
|
troikaVertexTransform${key}(troika_position_${key}, troika_normal_${key}, troika_uv_${key});
|
|
${vertexMainIntro}
|
|
`;
|
|
vertexShader3 = vertexShader3.replace(/\b(position|normal|uv)\b/g, (match, match1, index2, fullStr) => {
|
|
return /\battribute\s+vec[23]\s+$/.test(fullStr.substr(0, index2)) ? match1 : `troika_${match1}_${key}`;
|
|
});
|
|
if (!(material.map && material.map.channel > 0)) {
|
|
vertexShader3 = vertexShader3.replace(/\bMAP_UV\b/g, `troika_uv_${key}`);
|
|
}
|
|
}
|
|
vertexShader3 = injectIntoShaderCode(vertexShader3, key, vertexDefs, vertexMainIntro, vertexMainOutro);
|
|
fragmentShader3 = injectIntoShaderCode(fragmentShader3, key, fragmentDefs, fragmentMainIntro, fragmentMainOutro);
|
|
return {
|
|
vertexShader: vertexShader3,
|
|
fragmentShader: fragmentShader3
|
|
};
|
|
}
|
|
function injectIntoShaderCode(shaderCode, id, defs, intro, outro) {
|
|
if (intro || outro || defs) {
|
|
shaderCode = shaderCode.replace(
|
|
voidMainRegExp,
|
|
`
|
|
${defs}
|
|
void troikaOrigMain${id}() {`
|
|
);
|
|
shaderCode += `
|
|
void main() {
|
|
${intro}
|
|
troikaOrigMain${id}();
|
|
${outro}
|
|
}`;
|
|
}
|
|
return shaderCode;
|
|
}
|
|
function optionsJsonReplacer(key, value) {
|
|
return key === "uniforms" ? void 0 : typeof value === "function" ? value.toString() : value;
|
|
}
|
|
var _idCtr = 0;
|
|
var optionsHashesToIds = /* @__PURE__ */ new Map();
|
|
function getKeyForOptions(options) {
|
|
const optionsHash = JSON.stringify(options, optionsJsonReplacer);
|
|
let id = optionsHashesToIds.get(optionsHash);
|
|
if (id == null) {
|
|
optionsHashesToIds.set(optionsHash, id = ++_idCtr);
|
|
}
|
|
return id;
|
|
}
|
|
var defaultBaseMaterial = new MeshStandardMaterial({ color: 16777215, side: DoubleSide });
|
|
|
|
// node_modules/troika-three-text/dist/troika-three-text.esm.js
|
|
function typrFactory() {
|
|
return "undefined" == typeof window && (self.window = self), (function(r2) {
|
|
var e2 = { parse: function(r3) {
|
|
var t3 = e2._bin, a6 = new Uint8Array(r3);
|
|
if ("ttcf" == t3.readASCII(a6, 0, 4)) {
|
|
var n2 = 4;
|
|
t3.readUshort(a6, n2), n2 += 2, t3.readUshort(a6, n2), n2 += 2;
|
|
var o2 = t3.readUint(a6, n2);
|
|
n2 += 4;
|
|
for (var s2 = [], i3 = 0; i3 < o2; i3++) {
|
|
var h = t3.readUint(a6, n2);
|
|
n2 += 4, s2.push(e2._readFont(a6, h));
|
|
}
|
|
return s2;
|
|
}
|
|
return [e2._readFont(a6, 0)];
|
|
}, _readFont: function(r3, t3) {
|
|
var a6 = e2._bin, n2 = t3;
|
|
a6.readFixed(r3, t3), t3 += 4;
|
|
var o2 = a6.readUshort(r3, t3);
|
|
t3 += 2, a6.readUshort(r3, t3), t3 += 2, a6.readUshort(r3, t3), t3 += 2, a6.readUshort(r3, t3), t3 += 2;
|
|
for (var s2 = ["cmap", "head", "hhea", "maxp", "hmtx", "name", "OS/2", "post", "loca", "glyf", "kern", "CFF ", "GDEF", "GPOS", "GSUB", "SVG "], i3 = { _data: r3, _offset: n2 }, h = {}, d2 = 0; d2 < o2; d2++) {
|
|
var f2 = a6.readASCII(r3, t3, 4);
|
|
t3 += 4, a6.readUint(r3, t3), t3 += 4;
|
|
var u = a6.readUint(r3, t3);
|
|
t3 += 4;
|
|
var l2 = a6.readUint(r3, t3);
|
|
t3 += 4, h[f2] = { offset: u, length: l2 };
|
|
}
|
|
for (d2 = 0; d2 < s2.length; d2++) {
|
|
var v5 = s2[d2];
|
|
h[v5] && (i3[v5.trim()] = e2[v5.trim()].parse(r3, h[v5].offset, h[v5].length, i3));
|
|
}
|
|
return i3;
|
|
}, _tabOffset: function(r3, t3, a6) {
|
|
for (var n2 = e2._bin, o2 = n2.readUshort(r3, a6 + 4), s2 = a6 + 12, i3 = 0; i3 < o2; i3++) {
|
|
var h = n2.readASCII(r3, s2, 4);
|
|
s2 += 4, n2.readUint(r3, s2), s2 += 4;
|
|
var d2 = n2.readUint(r3, s2);
|
|
if (s2 += 4, n2.readUint(r3, s2), s2 += 4, h == t3) return d2;
|
|
}
|
|
return 0;
|
|
} };
|
|
e2._bin = { readFixed: function(r3, e3) {
|
|
return (r3[e3] << 8 | r3[e3 + 1]) + (r3[e3 + 2] << 8 | r3[e3 + 3]) / 65540;
|
|
}, readF2dot14: function(r3, t3) {
|
|
return e2._bin.readShort(r3, t3) / 16384;
|
|
}, readInt: function(r3, t3) {
|
|
return e2._bin._view(r3).getInt32(t3);
|
|
}, readInt8: function(r3, t3) {
|
|
return e2._bin._view(r3).getInt8(t3);
|
|
}, readShort: function(r3, t3) {
|
|
return e2._bin._view(r3).getInt16(t3);
|
|
}, readUshort: function(r3, t3) {
|
|
return e2._bin._view(r3).getUint16(t3);
|
|
}, readUshorts: function(r3, t3, a6) {
|
|
for (var n2 = [], o2 = 0; o2 < a6; o2++) n2.push(e2._bin.readUshort(r3, t3 + 2 * o2));
|
|
return n2;
|
|
}, readUint: function(r3, t3) {
|
|
return e2._bin._view(r3).getUint32(t3);
|
|
}, readUint64: function(r3, t3) {
|
|
return 4294967296 * e2._bin.readUint(r3, t3) + e2._bin.readUint(r3, t3 + 4);
|
|
}, readASCII: function(r3, e3, t3) {
|
|
for (var a6 = "", n2 = 0; n2 < t3; n2++) a6 += String.fromCharCode(r3[e3 + n2]);
|
|
return a6;
|
|
}, readUnicode: function(r3, e3, t3) {
|
|
for (var a6 = "", n2 = 0; n2 < t3; n2++) {
|
|
var o2 = r3[e3++] << 8 | r3[e3++];
|
|
a6 += String.fromCharCode(o2);
|
|
}
|
|
return a6;
|
|
}, _tdec: "undefined" != typeof window && window.TextDecoder ? new window.TextDecoder() : null, readUTF8: function(r3, t3, a6) {
|
|
var n2 = e2._bin._tdec;
|
|
return n2 && 0 == t3 && a6 == r3.length ? n2.decode(r3) : e2._bin.readASCII(r3, t3, a6);
|
|
}, readBytes: function(r3, e3, t3) {
|
|
for (var a6 = [], n2 = 0; n2 < t3; n2++) a6.push(r3[e3 + n2]);
|
|
return a6;
|
|
}, readASCIIArray: function(r3, e3, t3) {
|
|
for (var a6 = [], n2 = 0; n2 < t3; n2++) a6.push(String.fromCharCode(r3[e3 + n2]));
|
|
return a6;
|
|
}, _view: function(r3) {
|
|
return r3._dataView || (r3._dataView = r3.buffer ? new DataView(r3.buffer, r3.byteOffset, r3.byteLength) : new DataView(new Uint8Array(r3).buffer));
|
|
} }, e2._lctf = {}, e2._lctf.parse = function(r3, t3, a6, n2, o2) {
|
|
var s2 = e2._bin, i3 = {}, h = t3;
|
|
s2.readFixed(r3, t3), t3 += 4;
|
|
var d2 = s2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var f2 = s2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var u = s2.readUshort(r3, t3);
|
|
return t3 += 2, i3.scriptList = e2._lctf.readScriptList(r3, h + d2), i3.featureList = e2._lctf.readFeatureList(r3, h + f2), i3.lookupList = e2._lctf.readLookupList(r3, h + u, o2), i3;
|
|
}, e2._lctf.readLookupList = function(r3, t3, a6) {
|
|
var n2 = e2._bin, o2 = t3, s2 = [], i3 = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
for (var h = 0; h < i3; h++) {
|
|
var d2 = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var f2 = e2._lctf.readLookupTable(r3, o2 + d2, a6);
|
|
s2.push(f2);
|
|
}
|
|
return s2;
|
|
}, e2._lctf.readLookupTable = function(r3, t3, a6) {
|
|
var n2 = e2._bin, o2 = t3, s2 = { tabs: [] };
|
|
s2.ltype = n2.readUshort(r3, t3), t3 += 2, s2.flag = n2.readUshort(r3, t3), t3 += 2;
|
|
var i3 = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
for (var h = s2.ltype, d2 = 0; d2 < i3; d2++) {
|
|
var f2 = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var u = a6(r3, h, o2 + f2, s2);
|
|
s2.tabs.push(u);
|
|
}
|
|
return s2;
|
|
}, e2._lctf.numOfOnes = function(r3) {
|
|
for (var e3 = 0, t3 = 0; t3 < 32; t3++) 0 != (r3 >>> t3 & 1) && e3++;
|
|
return e3;
|
|
}, e2._lctf.readClassDef = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = [], o2 = a6.readUshort(r3, t3);
|
|
if (t3 += 2, 1 == o2) {
|
|
var s2 = a6.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var i3 = a6.readUshort(r3, t3);
|
|
t3 += 2;
|
|
for (var h = 0; h < i3; h++) n2.push(s2 + h), n2.push(s2 + h), n2.push(a6.readUshort(r3, t3)), t3 += 2;
|
|
}
|
|
if (2 == o2) {
|
|
var d2 = a6.readUshort(r3, t3);
|
|
t3 += 2;
|
|
for (h = 0; h < d2; h++) n2.push(a6.readUshort(r3, t3)), t3 += 2, n2.push(a6.readUshort(r3, t3)), t3 += 2, n2.push(a6.readUshort(r3, t3)), t3 += 2;
|
|
}
|
|
return n2;
|
|
}, e2._lctf.getInterval = function(r3, e3) {
|
|
for (var t3 = 0; t3 < r3.length; t3 += 3) {
|
|
var a6 = r3[t3], n2 = r3[t3 + 1];
|
|
if (r3[t3 + 2], a6 <= e3 && e3 <= n2) return t3;
|
|
}
|
|
return -1;
|
|
}, e2._lctf.readCoverage = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = {};
|
|
n2.fmt = a6.readUshort(r3, t3), t3 += 2;
|
|
var o2 = a6.readUshort(r3, t3);
|
|
return t3 += 2, 1 == n2.fmt && (n2.tab = a6.readUshorts(r3, t3, o2)), 2 == n2.fmt && (n2.tab = a6.readUshorts(r3, t3, 3 * o2)), n2;
|
|
}, e2._lctf.coverageIndex = function(r3, t3) {
|
|
var a6 = r3.tab;
|
|
if (1 == r3.fmt) return a6.indexOf(t3);
|
|
if (2 == r3.fmt) {
|
|
var n2 = e2._lctf.getInterval(a6, t3);
|
|
if (-1 != n2) return a6[n2 + 2] + (t3 - a6[n2]);
|
|
}
|
|
return -1;
|
|
}, e2._lctf.readFeatureList = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = t3, o2 = [], s2 = a6.readUshort(r3, t3);
|
|
t3 += 2;
|
|
for (var i3 = 0; i3 < s2; i3++) {
|
|
var h = a6.readASCII(r3, t3, 4);
|
|
t3 += 4;
|
|
var d2 = a6.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var f2 = e2._lctf.readFeatureTable(r3, n2 + d2);
|
|
f2.tag = h.trim(), o2.push(f2);
|
|
}
|
|
return o2;
|
|
}, e2._lctf.readFeatureTable = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = t3, o2 = {}, s2 = a6.readUshort(r3, t3);
|
|
t3 += 2, s2 > 0 && (o2.featureParams = n2 + s2);
|
|
var i3 = a6.readUshort(r3, t3);
|
|
t3 += 2, o2.tab = [];
|
|
for (var h = 0; h < i3; h++) o2.tab.push(a6.readUshort(r3, t3 + 2 * h));
|
|
return o2;
|
|
}, e2._lctf.readScriptList = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = t3, o2 = {}, s2 = a6.readUshort(r3, t3);
|
|
t3 += 2;
|
|
for (var i3 = 0; i3 < s2; i3++) {
|
|
var h = a6.readASCII(r3, t3, 4);
|
|
t3 += 4;
|
|
var d2 = a6.readUshort(r3, t3);
|
|
t3 += 2, o2[h.trim()] = e2._lctf.readScriptTable(r3, n2 + d2);
|
|
}
|
|
return o2;
|
|
}, e2._lctf.readScriptTable = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = t3, o2 = {}, s2 = a6.readUshort(r3, t3);
|
|
t3 += 2, s2 > 0 && (o2.default = e2._lctf.readLangSysTable(r3, n2 + s2));
|
|
var i3 = a6.readUshort(r3, t3);
|
|
t3 += 2;
|
|
for (var h = 0; h < i3; h++) {
|
|
var d2 = a6.readASCII(r3, t3, 4);
|
|
t3 += 4;
|
|
var f2 = a6.readUshort(r3, t3);
|
|
t3 += 2, o2[d2.trim()] = e2._lctf.readLangSysTable(r3, n2 + f2);
|
|
}
|
|
return o2;
|
|
}, e2._lctf.readLangSysTable = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = {};
|
|
a6.readUshort(r3, t3), t3 += 2, n2.reqFeature = a6.readUshort(r3, t3), t3 += 2;
|
|
var o2 = a6.readUshort(r3, t3);
|
|
return t3 += 2, n2.features = a6.readUshorts(r3, t3, o2), n2;
|
|
}, e2.CFF = {}, e2.CFF.parse = function(r3, t3, a6) {
|
|
var n2 = e2._bin;
|
|
(r3 = new Uint8Array(r3.buffer, t3, a6))[t3 = 0], r3[++t3], r3[++t3], r3[++t3], t3++;
|
|
var o2 = [];
|
|
t3 = e2.CFF.readIndex(r3, t3, o2);
|
|
for (var s2 = [], i3 = 0; i3 < o2.length - 1; i3++) s2.push(n2.readASCII(r3, t3 + o2[i3], o2[i3 + 1] - o2[i3]));
|
|
t3 += o2[o2.length - 1];
|
|
var h = [];
|
|
t3 = e2.CFF.readIndex(r3, t3, h);
|
|
var d2 = [];
|
|
for (i3 = 0; i3 < h.length - 1; i3++) d2.push(e2.CFF.readDict(r3, t3 + h[i3], t3 + h[i3 + 1]));
|
|
t3 += h[h.length - 1];
|
|
var f2 = d2[0], u = [];
|
|
t3 = e2.CFF.readIndex(r3, t3, u);
|
|
var l2 = [];
|
|
for (i3 = 0; i3 < u.length - 1; i3++) l2.push(n2.readASCII(r3, t3 + u[i3], u[i3 + 1] - u[i3]));
|
|
if (t3 += u[u.length - 1], e2.CFF.readSubrs(r3, t3, f2), f2.CharStrings) {
|
|
t3 = f2.CharStrings;
|
|
u = [];
|
|
t3 = e2.CFF.readIndex(r3, t3, u);
|
|
var v5 = [];
|
|
for (i3 = 0; i3 < u.length - 1; i3++) v5.push(n2.readBytes(r3, t3 + u[i3], u[i3 + 1] - u[i3]));
|
|
f2.CharStrings = v5;
|
|
}
|
|
if (f2.ROS) {
|
|
t3 = f2.FDArray;
|
|
var c2 = [];
|
|
t3 = e2.CFF.readIndex(r3, t3, c2), f2.FDArray = [];
|
|
for (i3 = 0; i3 < c2.length - 1; i3++) {
|
|
var p2 = e2.CFF.readDict(r3, t3 + c2[i3], t3 + c2[i3 + 1]);
|
|
e2.CFF._readFDict(r3, p2, l2), f2.FDArray.push(p2);
|
|
}
|
|
t3 += c2[c2.length - 1], t3 = f2.FDSelect, f2.FDSelect = [];
|
|
var U = r3[t3];
|
|
if (t3++, 3 != U) throw U;
|
|
var g = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
for (i3 = 0; i3 < g + 1; i3++) f2.FDSelect.push(n2.readUshort(r3, t3), r3[t3 + 2]), t3 += 3;
|
|
}
|
|
return f2.Encoding && (f2.Encoding = e2.CFF.readEncoding(r3, f2.Encoding, f2.CharStrings.length)), f2.charset && (f2.charset = e2.CFF.readCharset(r3, f2.charset, f2.CharStrings.length)), e2.CFF._readFDict(r3, f2, l2), f2;
|
|
}, e2.CFF._readFDict = function(r3, t3, a6) {
|
|
var n2;
|
|
for (var o2 in t3.Private && (n2 = t3.Private[1], t3.Private = e2.CFF.readDict(r3, n2, n2 + t3.Private[0]), t3.Private.Subrs && e2.CFF.readSubrs(r3, n2 + t3.Private.Subrs, t3.Private)), t3) -1 != ["FamilyName", "FontName", "FullName", "Notice", "version", "Copyright"].indexOf(o2) && (t3[o2] = a6[t3[o2] - 426 + 35]);
|
|
}, e2.CFF.readSubrs = function(r3, t3, a6) {
|
|
var n2 = e2._bin, o2 = [];
|
|
t3 = e2.CFF.readIndex(r3, t3, o2);
|
|
var s2, i3 = o2.length;
|
|
s2 = i3 < 1240 ? 107 : i3 < 33900 ? 1131 : 32768, a6.Bias = s2, a6.Subrs = [];
|
|
for (var h = 0; h < o2.length - 1; h++) a6.Subrs.push(n2.readBytes(r3, t3 + o2[h], o2[h + 1] - o2[h]));
|
|
}, e2.CFF.tableSE = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 0, 111, 112, 113, 114, 0, 115, 116, 117, 118, 119, 120, 121, 122, 0, 123, 0, 124, 125, 126, 127, 128, 129, 130, 131, 0, 132, 133, 0, 134, 135, 136, 137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 0, 139, 0, 0, 0, 0, 140, 141, 142, 143, 0, 0, 0, 0, 0, 144, 0, 0, 0, 145, 0, 0, 146, 147, 148, 149, 0, 0, 0, 0], e2.CFF.glyphByUnicode = function(r3, e3) {
|
|
for (var t3 = 0; t3 < r3.charset.length; t3++) if (r3.charset[t3] == e3) return t3;
|
|
return -1;
|
|
}, e2.CFF.glyphBySE = function(r3, t3) {
|
|
return t3 < 0 || t3 > 255 ? -1 : e2.CFF.glyphByUnicode(r3, e2.CFF.tableSE[t3]);
|
|
}, e2.CFF.readEncoding = function(r3, t3, a6) {
|
|
e2._bin;
|
|
var n2 = [".notdef"], o2 = r3[t3];
|
|
if (t3++, 0 != o2) throw "error: unknown encoding format: " + o2;
|
|
var s2 = r3[t3];
|
|
t3++;
|
|
for (var i3 = 0; i3 < s2; i3++) n2.push(r3[t3 + i3]);
|
|
return n2;
|
|
}, e2.CFF.readCharset = function(r3, t3, a6) {
|
|
var n2 = e2._bin, o2 = [".notdef"], s2 = r3[t3];
|
|
if (t3++, 0 == s2) for (var i3 = 0; i3 < a6; i3++) {
|
|
var h = n2.readUshort(r3, t3);
|
|
t3 += 2, o2.push(h);
|
|
}
|
|
else {
|
|
if (1 != s2 && 2 != s2) throw "error: format: " + s2;
|
|
for (; o2.length < a6; ) {
|
|
h = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var d2 = 0;
|
|
1 == s2 ? (d2 = r3[t3], t3++) : (d2 = n2.readUshort(r3, t3), t3 += 2);
|
|
for (i3 = 0; i3 <= d2; i3++) o2.push(h), h++;
|
|
}
|
|
}
|
|
return o2;
|
|
}, e2.CFF.readIndex = function(r3, t3, a6) {
|
|
var n2 = e2._bin, o2 = n2.readUshort(r3, t3) + 1, s2 = r3[t3 += 2];
|
|
if (t3++, 1 == s2) for (var i3 = 0; i3 < o2; i3++) a6.push(r3[t3 + i3]);
|
|
else if (2 == s2) for (i3 = 0; i3 < o2; i3++) a6.push(n2.readUshort(r3, t3 + 2 * i3));
|
|
else if (3 == s2) for (i3 = 0; i3 < o2; i3++) a6.push(16777215 & n2.readUint(r3, t3 + 3 * i3 - 1));
|
|
else if (1 != o2) throw "unsupported offset size: " + s2 + ", count: " + o2;
|
|
return (t3 += o2 * s2) - 1;
|
|
}, e2.CFF.getCharString = function(r3, t3, a6) {
|
|
var n2 = e2._bin, o2 = r3[t3], s2 = r3[t3 + 1];
|
|
r3[t3 + 2], r3[t3 + 3], r3[t3 + 4];
|
|
var i3 = 1, h = null, d2 = null;
|
|
o2 <= 20 && (h = o2, i3 = 1), 12 == o2 && (h = 100 * o2 + s2, i3 = 2), 21 <= o2 && o2 <= 27 && (h = o2, i3 = 1), 28 == o2 && (d2 = n2.readShort(r3, t3 + 1), i3 = 3), 29 <= o2 && o2 <= 31 && (h = o2, i3 = 1), 32 <= o2 && o2 <= 246 && (d2 = o2 - 139, i3 = 1), 247 <= o2 && o2 <= 250 && (d2 = 256 * (o2 - 247) + s2 + 108, i3 = 2), 251 <= o2 && o2 <= 254 && (d2 = 256 * -(o2 - 251) - s2 - 108, i3 = 2), 255 == o2 && (d2 = n2.readInt(r3, t3 + 1) / 65535, i3 = 5), a6.val = null != d2 ? d2 : "o" + h, a6.size = i3;
|
|
}, e2.CFF.readCharString = function(r3, t3, a6) {
|
|
for (var n2 = t3 + a6, o2 = e2._bin, s2 = []; t3 < n2; ) {
|
|
var i3 = r3[t3], h = r3[t3 + 1];
|
|
r3[t3 + 2], r3[t3 + 3], r3[t3 + 4];
|
|
var d2 = 1, f2 = null, u = null;
|
|
i3 <= 20 && (f2 = i3, d2 = 1), 12 == i3 && (f2 = 100 * i3 + h, d2 = 2), 19 != i3 && 20 != i3 || (f2 = i3, d2 = 2), 21 <= i3 && i3 <= 27 && (f2 = i3, d2 = 1), 28 == i3 && (u = o2.readShort(r3, t3 + 1), d2 = 3), 29 <= i3 && i3 <= 31 && (f2 = i3, d2 = 1), 32 <= i3 && i3 <= 246 && (u = i3 - 139, d2 = 1), 247 <= i3 && i3 <= 250 && (u = 256 * (i3 - 247) + h + 108, d2 = 2), 251 <= i3 && i3 <= 254 && (u = 256 * -(i3 - 251) - h - 108, d2 = 2), 255 == i3 && (u = o2.readInt(r3, t3 + 1) / 65535, d2 = 5), s2.push(null != u ? u : "o" + f2), t3 += d2;
|
|
}
|
|
return s2;
|
|
}, e2.CFF.readDict = function(r3, t3, a6) {
|
|
for (var n2 = e2._bin, o2 = {}, s2 = []; t3 < a6; ) {
|
|
var i3 = r3[t3], h = r3[t3 + 1];
|
|
r3[t3 + 2], r3[t3 + 3], r3[t3 + 4];
|
|
var d2 = 1, f2 = null, u = null;
|
|
if (28 == i3 && (u = n2.readShort(r3, t3 + 1), d2 = 3), 29 == i3 && (u = n2.readInt(r3, t3 + 1), d2 = 5), 32 <= i3 && i3 <= 246 && (u = i3 - 139, d2 = 1), 247 <= i3 && i3 <= 250 && (u = 256 * (i3 - 247) + h + 108, d2 = 2), 251 <= i3 && i3 <= 254 && (u = 256 * -(i3 - 251) - h - 108, d2 = 2), 255 == i3) throw u = n2.readInt(r3, t3 + 1) / 65535, d2 = 5, "unknown number";
|
|
if (30 == i3) {
|
|
var l2 = [];
|
|
for (d2 = 1; ; ) {
|
|
var v5 = r3[t3 + d2];
|
|
d2++;
|
|
var c2 = v5 >> 4, p2 = 15 & v5;
|
|
if (15 != c2 && l2.push(c2), 15 != p2 && l2.push(p2), 15 == p2) break;
|
|
}
|
|
for (var U = "", g = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ".", "e", "e-", "reserved", "-", "endOfNumber"], S = 0; S < l2.length; S++) U += g[l2[S]];
|
|
u = parseFloat(U);
|
|
}
|
|
if (i3 <= 21) {
|
|
if (f2 = ["version", "Notice", "FullName", "FamilyName", "Weight", "FontBBox", "BlueValues", "OtherBlues", "FamilyBlues", "FamilyOtherBlues", "StdHW", "StdVW", "escape", "UniqueID", "XUID", "charset", "Encoding", "CharStrings", "Private", "Subrs", "defaultWidthX", "nominalWidthX"][i3], d2 = 1, 12 == i3) f2 = ["Copyright", "isFixedPitch", "ItalicAngle", "UnderlinePosition", "UnderlineThickness", "PaintType", "CharstringType", "FontMatrix", "StrokeWidth", "BlueScale", "BlueShift", "BlueFuzz", "StemSnapH", "StemSnapV", "ForceBold", 0, 0, "LanguageGroup", "ExpansionFactor", "initialRandomSeed", "SyntheticBase", "PostScript", "BaseFontName", "BaseFontBlend", 0, 0, 0, 0, 0, 0, "ROS", "CIDFontVersion", "CIDFontRevision", "CIDFontType", "CIDCount", "UIDBase", "FDArray", "FDSelect", "FontName"][h], d2 = 2;
|
|
}
|
|
null != f2 ? (o2[f2] = 1 == s2.length ? s2[0] : s2, s2 = []) : s2.push(u), t3 += d2;
|
|
}
|
|
return o2;
|
|
}, e2.cmap = {}, e2.cmap.parse = function(r3, t3, a6) {
|
|
r3 = new Uint8Array(r3.buffer, t3, a6), t3 = 0;
|
|
var n2 = e2._bin, o2 = {};
|
|
n2.readUshort(r3, t3), t3 += 2;
|
|
var s2 = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var i3 = [];
|
|
o2.tables = [];
|
|
for (var h = 0; h < s2; h++) {
|
|
var d2 = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var f2 = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var u = n2.readUint(r3, t3);
|
|
t3 += 4;
|
|
var l2 = "p" + d2 + "e" + f2, v5 = i3.indexOf(u);
|
|
if (-1 == v5) {
|
|
var c2;
|
|
v5 = o2.tables.length, i3.push(u);
|
|
var p2 = n2.readUshort(r3, u);
|
|
0 == p2 ? c2 = e2.cmap.parse0(r3, u) : 4 == p2 ? c2 = e2.cmap.parse4(r3, u) : 6 == p2 ? c2 = e2.cmap.parse6(r3, u) : 12 == p2 ? c2 = e2.cmap.parse12(r3, u) : console.debug("unknown format: " + p2, d2, f2, u), o2.tables.push(c2);
|
|
}
|
|
if (null != o2[l2]) throw "multiple tables for one platform+encoding";
|
|
o2[l2] = v5;
|
|
}
|
|
return o2;
|
|
}, e2.cmap.parse0 = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = {};
|
|
n2.format = a6.readUshort(r3, t3), t3 += 2;
|
|
var o2 = a6.readUshort(r3, t3);
|
|
t3 += 2, a6.readUshort(r3, t3), t3 += 2, n2.map = [];
|
|
for (var s2 = 0; s2 < o2 - 6; s2++) n2.map.push(r3[t3 + s2]);
|
|
return n2;
|
|
}, e2.cmap.parse4 = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = t3, o2 = {};
|
|
o2.format = a6.readUshort(r3, t3), t3 += 2;
|
|
var s2 = a6.readUshort(r3, t3);
|
|
t3 += 2, a6.readUshort(r3, t3), t3 += 2;
|
|
var i3 = a6.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var h = i3 / 2;
|
|
o2.searchRange = a6.readUshort(r3, t3), t3 += 2, o2.entrySelector = a6.readUshort(r3, t3), t3 += 2, o2.rangeShift = a6.readUshort(r3, t3), t3 += 2, o2.endCount = a6.readUshorts(r3, t3, h), t3 += 2 * h, t3 += 2, o2.startCount = a6.readUshorts(r3, t3, h), t3 += 2 * h, o2.idDelta = [];
|
|
for (var d2 = 0; d2 < h; d2++) o2.idDelta.push(a6.readShort(r3, t3)), t3 += 2;
|
|
for (o2.idRangeOffset = a6.readUshorts(r3, t3, h), t3 += 2 * h, o2.glyphIdArray = []; t3 < n2 + s2; ) o2.glyphIdArray.push(a6.readUshort(r3, t3)), t3 += 2;
|
|
return o2;
|
|
}, e2.cmap.parse6 = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = {};
|
|
n2.format = a6.readUshort(r3, t3), t3 += 2, a6.readUshort(r3, t3), t3 += 2, a6.readUshort(r3, t3), t3 += 2, n2.firstCode = a6.readUshort(r3, t3), t3 += 2;
|
|
var o2 = a6.readUshort(r3, t3);
|
|
t3 += 2, n2.glyphIdArray = [];
|
|
for (var s2 = 0; s2 < o2; s2++) n2.glyphIdArray.push(a6.readUshort(r3, t3)), t3 += 2;
|
|
return n2;
|
|
}, e2.cmap.parse12 = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = {};
|
|
n2.format = a6.readUshort(r3, t3), t3 += 2, t3 += 2, a6.readUint(r3, t3), t3 += 4, a6.readUint(r3, t3), t3 += 4;
|
|
var o2 = a6.readUint(r3, t3);
|
|
t3 += 4, n2.groups = [];
|
|
for (var s2 = 0; s2 < o2; s2++) {
|
|
var i3 = t3 + 12 * s2, h = a6.readUint(r3, i3 + 0), d2 = a6.readUint(r3, i3 + 4), f2 = a6.readUint(r3, i3 + 8);
|
|
n2.groups.push([h, d2, f2]);
|
|
}
|
|
return n2;
|
|
}, e2.glyf = {}, e2.glyf.parse = function(r3, e3, t3, a6) {
|
|
for (var n2 = [], o2 = 0; o2 < a6.maxp.numGlyphs; o2++) n2.push(null);
|
|
return n2;
|
|
}, e2.glyf._parseGlyf = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = r3._data, o2 = e2._tabOffset(n2, "glyf", r3._offset) + r3.loca[t3];
|
|
if (r3.loca[t3] == r3.loca[t3 + 1]) return null;
|
|
var s2 = {};
|
|
if (s2.noc = a6.readShort(n2, o2), o2 += 2, s2.xMin = a6.readShort(n2, o2), o2 += 2, s2.yMin = a6.readShort(n2, o2), o2 += 2, s2.xMax = a6.readShort(n2, o2), o2 += 2, s2.yMax = a6.readShort(n2, o2), o2 += 2, s2.xMin >= s2.xMax || s2.yMin >= s2.yMax) return null;
|
|
if (s2.noc > 0) {
|
|
s2.endPts = [];
|
|
for (var i3 = 0; i3 < s2.noc; i3++) s2.endPts.push(a6.readUshort(n2, o2)), o2 += 2;
|
|
var h = a6.readUshort(n2, o2);
|
|
if (o2 += 2, n2.length - o2 < h) return null;
|
|
s2.instructions = a6.readBytes(n2, o2, h), o2 += h;
|
|
var d2 = s2.endPts[s2.noc - 1] + 1;
|
|
s2.flags = [];
|
|
for (i3 = 0; i3 < d2; i3++) {
|
|
var f2 = n2[o2];
|
|
if (o2++, s2.flags.push(f2), 0 != (8 & f2)) {
|
|
var u = n2[o2];
|
|
o2++;
|
|
for (var l2 = 0; l2 < u; l2++) s2.flags.push(f2), i3++;
|
|
}
|
|
}
|
|
s2.xs = [];
|
|
for (i3 = 0; i3 < d2; i3++) {
|
|
var v5 = 0 != (2 & s2.flags[i3]), c2 = 0 != (16 & s2.flags[i3]);
|
|
v5 ? (s2.xs.push(c2 ? n2[o2] : -n2[o2]), o2++) : c2 ? s2.xs.push(0) : (s2.xs.push(a6.readShort(n2, o2)), o2 += 2);
|
|
}
|
|
s2.ys = [];
|
|
for (i3 = 0; i3 < d2; i3++) {
|
|
v5 = 0 != (4 & s2.flags[i3]), c2 = 0 != (32 & s2.flags[i3]);
|
|
v5 ? (s2.ys.push(c2 ? n2[o2] : -n2[o2]), o2++) : c2 ? s2.ys.push(0) : (s2.ys.push(a6.readShort(n2, o2)), o2 += 2);
|
|
}
|
|
var p2 = 0, U = 0;
|
|
for (i3 = 0; i3 < d2; i3++) p2 += s2.xs[i3], U += s2.ys[i3], s2.xs[i3] = p2, s2.ys[i3] = U;
|
|
} else {
|
|
var g;
|
|
s2.parts = [];
|
|
do {
|
|
g = a6.readUshort(n2, o2), o2 += 2;
|
|
var S = { m: { a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 }, p1: -1, p2: -1 };
|
|
if (s2.parts.push(S), S.glyphIndex = a6.readUshort(n2, o2), o2 += 2, 1 & g) {
|
|
var m = a6.readShort(n2, o2);
|
|
o2 += 2;
|
|
var b = a6.readShort(n2, o2);
|
|
o2 += 2;
|
|
} else {
|
|
m = a6.readInt8(n2, o2);
|
|
o2++;
|
|
b = a6.readInt8(n2, o2);
|
|
o2++;
|
|
}
|
|
2 & g ? (S.m.tx = m, S.m.ty = b) : (S.p1 = m, S.p2 = b), 8 & g ? (S.m.a = S.m.d = a6.readF2dot14(n2, o2), o2 += 2) : 64 & g ? (S.m.a = a6.readF2dot14(n2, o2), o2 += 2, S.m.d = a6.readF2dot14(n2, o2), o2 += 2) : 128 & g && (S.m.a = a6.readF2dot14(n2, o2), o2 += 2, S.m.b = a6.readF2dot14(n2, o2), o2 += 2, S.m.c = a6.readF2dot14(n2, o2), o2 += 2, S.m.d = a6.readF2dot14(n2, o2), o2 += 2);
|
|
} while (32 & g);
|
|
if (256 & g) {
|
|
var y = a6.readUshort(n2, o2);
|
|
o2 += 2, s2.instr = [];
|
|
for (i3 = 0; i3 < y; i3++) s2.instr.push(n2[o2]), o2++;
|
|
}
|
|
}
|
|
return s2;
|
|
}, e2.GDEF = {}, e2.GDEF.parse = function(r3, t3, a6, n2) {
|
|
var o2 = t3;
|
|
t3 += 4;
|
|
var s2 = e2._bin.readUshort(r3, t3);
|
|
return { glyphClassDef: 0 === s2 ? null : e2._lctf.readClassDef(r3, o2 + s2) };
|
|
}, e2.GPOS = {}, e2.GPOS.parse = function(r3, t3, a6, n2) {
|
|
return e2._lctf.parse(r3, t3, a6, n2, e2.GPOS.subt);
|
|
}, e2.GPOS.subt = function(r3, t3, a6, n2) {
|
|
var o2 = e2._bin, s2 = a6, i3 = {};
|
|
if (i3.fmt = o2.readUshort(r3, a6), a6 += 2, 1 == t3 || 2 == t3 || 3 == t3 || 7 == t3 || 8 == t3 && i3.fmt <= 2) {
|
|
var h = o2.readUshort(r3, a6);
|
|
a6 += 2, i3.coverage = e2._lctf.readCoverage(r3, h + s2);
|
|
}
|
|
if (1 == t3 && 1 == i3.fmt) {
|
|
var d2 = o2.readUshort(r3, a6);
|
|
a6 += 2, 0 != d2 && (i3.pos = e2.GPOS.readValueRecord(r3, a6, d2));
|
|
} else if (2 == t3 && i3.fmt >= 1 && i3.fmt <= 2) {
|
|
d2 = o2.readUshort(r3, a6);
|
|
a6 += 2;
|
|
var f2 = o2.readUshort(r3, a6);
|
|
a6 += 2;
|
|
var u = e2._lctf.numOfOnes(d2), l2 = e2._lctf.numOfOnes(f2);
|
|
if (1 == i3.fmt) {
|
|
i3.pairsets = [];
|
|
var v5 = o2.readUshort(r3, a6);
|
|
a6 += 2;
|
|
for (var c2 = 0; c2 < v5; c2++) {
|
|
var p2 = s2 + o2.readUshort(r3, a6);
|
|
a6 += 2;
|
|
var U = o2.readUshort(r3, p2);
|
|
p2 += 2;
|
|
for (var g = [], S = 0; S < U; S++) {
|
|
var m = o2.readUshort(r3, p2);
|
|
p2 += 2, 0 != d2 && (P = e2.GPOS.readValueRecord(r3, p2, d2), p2 += 2 * u), 0 != f2 && (x = e2.GPOS.readValueRecord(r3, p2, f2), p2 += 2 * l2), g.push({ gid2: m, val1: P, val2: x });
|
|
}
|
|
i3.pairsets.push(g);
|
|
}
|
|
}
|
|
if (2 == i3.fmt) {
|
|
var b = o2.readUshort(r3, a6);
|
|
a6 += 2;
|
|
var y = o2.readUshort(r3, a6);
|
|
a6 += 2;
|
|
var F = o2.readUshort(r3, a6);
|
|
a6 += 2;
|
|
var C = o2.readUshort(r3, a6);
|
|
a6 += 2, i3.classDef1 = e2._lctf.readClassDef(r3, s2 + b), i3.classDef2 = e2._lctf.readClassDef(r3, s2 + y), i3.matrix = [];
|
|
for (c2 = 0; c2 < F; c2++) {
|
|
var _ = [];
|
|
for (S = 0; S < C; S++) {
|
|
var P = null, x = null;
|
|
0 != d2 && (P = e2.GPOS.readValueRecord(r3, a6, d2), a6 += 2 * u), 0 != f2 && (x = e2.GPOS.readValueRecord(r3, a6, f2), a6 += 2 * l2), _.push({ val1: P, val2: x });
|
|
}
|
|
i3.matrix.push(_);
|
|
}
|
|
}
|
|
} else if (4 == t3 && 1 == i3.fmt) i3.markCoverage = e2._lctf.readCoverage(r3, o2.readUshort(r3, a6) + s2), i3.baseCoverage = e2._lctf.readCoverage(r3, o2.readUshort(r3, a6 + 2) + s2), i3.markClassCount = o2.readUshort(r3, a6 + 4), i3.markArray = e2.GPOS.readMarkArray(r3, o2.readUshort(r3, a6 + 6) + s2), i3.baseArray = e2.GPOS.readBaseArray(r3, o2.readUshort(r3, a6 + 8) + s2, i3.markClassCount);
|
|
else if (6 == t3 && 1 == i3.fmt) i3.mark1Coverage = e2._lctf.readCoverage(r3, o2.readUshort(r3, a6) + s2), i3.mark2Coverage = e2._lctf.readCoverage(r3, o2.readUshort(r3, a6 + 2) + s2), i3.markClassCount = o2.readUshort(r3, a6 + 4), i3.mark1Array = e2.GPOS.readMarkArray(r3, o2.readUshort(r3, a6 + 6) + s2), i3.mark2Array = e2.GPOS.readBaseArray(r3, o2.readUshort(r3, a6 + 8) + s2, i3.markClassCount);
|
|
else {
|
|
if (9 == t3 && 1 == i3.fmt) {
|
|
var I = o2.readUshort(r3, a6);
|
|
a6 += 2;
|
|
var w = o2.readUint(r3, a6);
|
|
if (a6 += 4, 9 == n2.ltype) n2.ltype = I;
|
|
else if (n2.ltype != I) throw "invalid extension substitution";
|
|
return e2.GPOS.subt(r3, n2.ltype, s2 + w);
|
|
}
|
|
console.debug("unsupported GPOS table LookupType", t3, "format", i3.fmt);
|
|
}
|
|
return i3;
|
|
}, e2.GPOS.readValueRecord = function(r3, t3, a6) {
|
|
var n2 = e2._bin, o2 = [];
|
|
return o2.push(1 & a6 ? n2.readShort(r3, t3) : 0), t3 += 1 & a6 ? 2 : 0, o2.push(2 & a6 ? n2.readShort(r3, t3) : 0), t3 += 2 & a6 ? 2 : 0, o2.push(4 & a6 ? n2.readShort(r3, t3) : 0), t3 += 4 & a6 ? 2 : 0, o2.push(8 & a6 ? n2.readShort(r3, t3) : 0), t3 += 8 & a6 ? 2 : 0, o2;
|
|
}, e2.GPOS.readBaseArray = function(r3, t3, a6) {
|
|
var n2 = e2._bin, o2 = [], s2 = t3, i3 = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
for (var h = 0; h < i3; h++) {
|
|
for (var d2 = [], f2 = 0; f2 < a6; f2++) d2.push(e2.GPOS.readAnchorRecord(r3, s2 + n2.readUshort(r3, t3))), t3 += 2;
|
|
o2.push(d2);
|
|
}
|
|
return o2;
|
|
}, e2.GPOS.readMarkArray = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = [], o2 = t3, s2 = a6.readUshort(r3, t3);
|
|
t3 += 2;
|
|
for (var i3 = 0; i3 < s2; i3++) {
|
|
var h = e2.GPOS.readAnchorRecord(r3, a6.readUshort(r3, t3 + 2) + o2);
|
|
h.markClass = a6.readUshort(r3, t3), n2.push(h), t3 += 4;
|
|
}
|
|
return n2;
|
|
}, e2.GPOS.readAnchorRecord = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = {};
|
|
return n2.fmt = a6.readUshort(r3, t3), n2.x = a6.readShort(r3, t3 + 2), n2.y = a6.readShort(r3, t3 + 4), n2;
|
|
}, e2.GSUB = {}, e2.GSUB.parse = function(r3, t3, a6, n2) {
|
|
return e2._lctf.parse(r3, t3, a6, n2, e2.GSUB.subt);
|
|
}, e2.GSUB.subt = function(r3, t3, a6, n2) {
|
|
var o2 = e2._bin, s2 = a6, i3 = {};
|
|
if (i3.fmt = o2.readUshort(r3, a6), a6 += 2, 1 != t3 && 2 != t3 && 4 != t3 && 5 != t3 && 6 != t3) return null;
|
|
if (1 == t3 || 2 == t3 || 4 == t3 || 5 == t3 && i3.fmt <= 2 || 6 == t3 && i3.fmt <= 2) {
|
|
var h = o2.readUshort(r3, a6);
|
|
a6 += 2, i3.coverage = e2._lctf.readCoverage(r3, s2 + h);
|
|
}
|
|
if (1 == t3 && i3.fmt >= 1 && i3.fmt <= 2) {
|
|
if (1 == i3.fmt) i3.delta = o2.readShort(r3, a6), a6 += 2;
|
|
else if (2 == i3.fmt) {
|
|
var d2 = o2.readUshort(r3, a6);
|
|
a6 += 2, i3.newg = o2.readUshorts(r3, a6, d2), a6 += 2 * i3.newg.length;
|
|
}
|
|
} else if (2 == t3 && 1 == i3.fmt) {
|
|
d2 = o2.readUshort(r3, a6);
|
|
a6 += 2, i3.seqs = [];
|
|
for (var f2 = 0; f2 < d2; f2++) {
|
|
var u = o2.readUshort(r3, a6) + s2;
|
|
a6 += 2;
|
|
var l2 = o2.readUshort(r3, u);
|
|
i3.seqs.push(o2.readUshorts(r3, u + 2, l2));
|
|
}
|
|
} else if (4 == t3) {
|
|
i3.vals = [];
|
|
d2 = o2.readUshort(r3, a6);
|
|
a6 += 2;
|
|
for (f2 = 0; f2 < d2; f2++) {
|
|
var v5 = o2.readUshort(r3, a6);
|
|
a6 += 2, i3.vals.push(e2.GSUB.readLigatureSet(r3, s2 + v5));
|
|
}
|
|
} else if (5 == t3 && 2 == i3.fmt) {
|
|
if (2 == i3.fmt) {
|
|
var c2 = o2.readUshort(r3, a6);
|
|
a6 += 2, i3.cDef = e2._lctf.readClassDef(r3, s2 + c2), i3.scset = [];
|
|
var p2 = o2.readUshort(r3, a6);
|
|
a6 += 2;
|
|
for (f2 = 0; f2 < p2; f2++) {
|
|
var U = o2.readUshort(r3, a6);
|
|
a6 += 2, i3.scset.push(0 == U ? null : e2.GSUB.readSubClassSet(r3, s2 + U));
|
|
}
|
|
}
|
|
} else if (6 == t3 && 3 == i3.fmt) {
|
|
if (3 == i3.fmt) {
|
|
for (f2 = 0; f2 < 3; f2++) {
|
|
d2 = o2.readUshort(r3, a6);
|
|
a6 += 2;
|
|
for (var g = [], S = 0; S < d2; S++) g.push(e2._lctf.readCoverage(r3, s2 + o2.readUshort(r3, a6 + 2 * S)));
|
|
a6 += 2 * d2, 0 == f2 && (i3.backCvg = g), 1 == f2 && (i3.inptCvg = g), 2 == f2 && (i3.ahedCvg = g);
|
|
}
|
|
d2 = o2.readUshort(r3, a6);
|
|
a6 += 2, i3.lookupRec = e2.GSUB.readSubstLookupRecords(r3, a6, d2);
|
|
}
|
|
} else {
|
|
if (7 == t3 && 1 == i3.fmt) {
|
|
var m = o2.readUshort(r3, a6);
|
|
a6 += 2;
|
|
var b = o2.readUint(r3, a6);
|
|
if (a6 += 4, 9 == n2.ltype) n2.ltype = m;
|
|
else if (n2.ltype != m) throw "invalid extension substitution";
|
|
return e2.GSUB.subt(r3, n2.ltype, s2 + b);
|
|
}
|
|
console.debug("unsupported GSUB table LookupType", t3, "format", i3.fmt);
|
|
}
|
|
return i3;
|
|
}, e2.GSUB.readSubClassSet = function(r3, t3) {
|
|
var a6 = e2._bin.readUshort, n2 = t3, o2 = [], s2 = a6(r3, t3);
|
|
t3 += 2;
|
|
for (var i3 = 0; i3 < s2; i3++) {
|
|
var h = a6(r3, t3);
|
|
t3 += 2, o2.push(e2.GSUB.readSubClassRule(r3, n2 + h));
|
|
}
|
|
return o2;
|
|
}, e2.GSUB.readSubClassRule = function(r3, t3) {
|
|
var a6 = e2._bin.readUshort, n2 = {}, o2 = a6(r3, t3), s2 = a6(r3, t3 += 2);
|
|
t3 += 2, n2.input = [];
|
|
for (var i3 = 0; i3 < o2 - 1; i3++) n2.input.push(a6(r3, t3)), t3 += 2;
|
|
return n2.substLookupRecords = e2.GSUB.readSubstLookupRecords(r3, t3, s2), n2;
|
|
}, e2.GSUB.readSubstLookupRecords = function(r3, t3, a6) {
|
|
for (var n2 = e2._bin.readUshort, o2 = [], s2 = 0; s2 < a6; s2++) o2.push(n2(r3, t3), n2(r3, t3 + 2)), t3 += 4;
|
|
return o2;
|
|
}, e2.GSUB.readChainSubClassSet = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = t3, o2 = [], s2 = a6.readUshort(r3, t3);
|
|
t3 += 2;
|
|
for (var i3 = 0; i3 < s2; i3++) {
|
|
var h = a6.readUshort(r3, t3);
|
|
t3 += 2, o2.push(e2.GSUB.readChainSubClassRule(r3, n2 + h));
|
|
}
|
|
return o2;
|
|
}, e2.GSUB.readChainSubClassRule = function(r3, t3) {
|
|
for (var a6 = e2._bin, n2 = {}, o2 = ["backtrack", "input", "lookahead"], s2 = 0; s2 < o2.length; s2++) {
|
|
var i3 = a6.readUshort(r3, t3);
|
|
t3 += 2, 1 == s2 && i3--, n2[o2[s2]] = a6.readUshorts(r3, t3, i3), t3 += 2 * n2[o2[s2]].length;
|
|
}
|
|
i3 = a6.readUshort(r3, t3);
|
|
return t3 += 2, n2.subst = a6.readUshorts(r3, t3, 2 * i3), t3 += 2 * n2.subst.length, n2;
|
|
}, e2.GSUB.readLigatureSet = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = t3, o2 = [], s2 = a6.readUshort(r3, t3);
|
|
t3 += 2;
|
|
for (var i3 = 0; i3 < s2; i3++) {
|
|
var h = a6.readUshort(r3, t3);
|
|
t3 += 2, o2.push(e2.GSUB.readLigature(r3, n2 + h));
|
|
}
|
|
return o2;
|
|
}, e2.GSUB.readLigature = function(r3, t3) {
|
|
var a6 = e2._bin, n2 = { chain: [] };
|
|
n2.nglyph = a6.readUshort(r3, t3), t3 += 2;
|
|
var o2 = a6.readUshort(r3, t3);
|
|
t3 += 2;
|
|
for (var s2 = 0; s2 < o2 - 1; s2++) n2.chain.push(a6.readUshort(r3, t3)), t3 += 2;
|
|
return n2;
|
|
}, e2.head = {}, e2.head.parse = function(r3, t3, a6) {
|
|
var n2 = e2._bin, o2 = {};
|
|
return n2.readFixed(r3, t3), t3 += 4, o2.fontRevision = n2.readFixed(r3, t3), t3 += 4, n2.readUint(r3, t3), t3 += 4, n2.readUint(r3, t3), t3 += 4, o2.flags = n2.readUshort(r3, t3), t3 += 2, o2.unitsPerEm = n2.readUshort(r3, t3), t3 += 2, o2.created = n2.readUint64(r3, t3), t3 += 8, o2.modified = n2.readUint64(r3, t3), t3 += 8, o2.xMin = n2.readShort(r3, t3), t3 += 2, o2.yMin = n2.readShort(r3, t3), t3 += 2, o2.xMax = n2.readShort(r3, t3), t3 += 2, o2.yMax = n2.readShort(r3, t3), t3 += 2, o2.macStyle = n2.readUshort(r3, t3), t3 += 2, o2.lowestRecPPEM = n2.readUshort(r3, t3), t3 += 2, o2.fontDirectionHint = n2.readShort(r3, t3), t3 += 2, o2.indexToLocFormat = n2.readShort(r3, t3), t3 += 2, o2.glyphDataFormat = n2.readShort(r3, t3), t3 += 2, o2;
|
|
}, e2.hhea = {}, e2.hhea.parse = function(r3, t3, a6) {
|
|
var n2 = e2._bin, o2 = {};
|
|
return n2.readFixed(r3, t3), t3 += 4, o2.ascender = n2.readShort(r3, t3), t3 += 2, o2.descender = n2.readShort(r3, t3), t3 += 2, o2.lineGap = n2.readShort(r3, t3), t3 += 2, o2.advanceWidthMax = n2.readUshort(r3, t3), t3 += 2, o2.minLeftSideBearing = n2.readShort(r3, t3), t3 += 2, o2.minRightSideBearing = n2.readShort(r3, t3), t3 += 2, o2.xMaxExtent = n2.readShort(r3, t3), t3 += 2, o2.caretSlopeRise = n2.readShort(r3, t3), t3 += 2, o2.caretSlopeRun = n2.readShort(r3, t3), t3 += 2, o2.caretOffset = n2.readShort(r3, t3), t3 += 2, t3 += 8, o2.metricDataFormat = n2.readShort(r3, t3), t3 += 2, o2.numberOfHMetrics = n2.readUshort(r3, t3), t3 += 2, o2;
|
|
}, e2.hmtx = {}, e2.hmtx.parse = function(r3, t3, a6, n2) {
|
|
for (var o2 = e2._bin, s2 = { aWidth: [], lsBearing: [] }, i3 = 0, h = 0, d2 = 0; d2 < n2.maxp.numGlyphs; d2++) d2 < n2.hhea.numberOfHMetrics && (i3 = o2.readUshort(r3, t3), t3 += 2, h = o2.readShort(r3, t3), t3 += 2), s2.aWidth.push(i3), s2.lsBearing.push(h);
|
|
return s2;
|
|
}, e2.kern = {}, e2.kern.parse = function(r3, t3, a6, n2) {
|
|
var o2 = e2._bin, s2 = o2.readUshort(r3, t3);
|
|
if (t3 += 2, 1 == s2) return e2.kern.parseV1(r3, t3 - 2, a6, n2);
|
|
var i3 = o2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
for (var h = { glyph1: [], rval: [] }, d2 = 0; d2 < i3; d2++) {
|
|
t3 += 2;
|
|
a6 = o2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var f2 = o2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var u = f2 >>> 8;
|
|
if (0 != (u &= 15)) throw "unknown kern table format: " + u;
|
|
t3 = e2.kern.readFormat0(r3, t3, h);
|
|
}
|
|
return h;
|
|
}, e2.kern.parseV1 = function(r3, t3, a6, n2) {
|
|
var o2 = e2._bin;
|
|
o2.readFixed(r3, t3), t3 += 4;
|
|
var s2 = o2.readUint(r3, t3);
|
|
t3 += 4;
|
|
for (var i3 = { glyph1: [], rval: [] }, h = 0; h < s2; h++) {
|
|
o2.readUint(r3, t3), t3 += 4;
|
|
var d2 = o2.readUshort(r3, t3);
|
|
t3 += 2, o2.readUshort(r3, t3), t3 += 2;
|
|
var f2 = d2 >>> 8;
|
|
if (0 != (f2 &= 15)) throw "unknown kern table format: " + f2;
|
|
t3 = e2.kern.readFormat0(r3, t3, i3);
|
|
}
|
|
return i3;
|
|
}, e2.kern.readFormat0 = function(r3, t3, a6) {
|
|
var n2 = e2._bin, o2 = -1, s2 = n2.readUshort(r3, t3);
|
|
t3 += 2, n2.readUshort(r3, t3), t3 += 2, n2.readUshort(r3, t3), t3 += 2, n2.readUshort(r3, t3), t3 += 2;
|
|
for (var i3 = 0; i3 < s2; i3++) {
|
|
var h = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var d2 = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var f2 = n2.readShort(r3, t3);
|
|
t3 += 2, h != o2 && (a6.glyph1.push(h), a6.rval.push({ glyph2: [], vals: [] }));
|
|
var u = a6.rval[a6.rval.length - 1];
|
|
u.glyph2.push(d2), u.vals.push(f2), o2 = h;
|
|
}
|
|
return t3;
|
|
}, e2.loca = {}, e2.loca.parse = function(r3, t3, a6, n2) {
|
|
var o2 = e2._bin, s2 = [], i3 = n2.head.indexToLocFormat, h = n2.maxp.numGlyphs + 1;
|
|
if (0 == i3) for (var d2 = 0; d2 < h; d2++) s2.push(o2.readUshort(r3, t3 + (d2 << 1)) << 1);
|
|
if (1 == i3) for (d2 = 0; d2 < h; d2++) s2.push(o2.readUint(r3, t3 + (d2 << 2)));
|
|
return s2;
|
|
}, e2.maxp = {}, e2.maxp.parse = function(r3, t3, a6) {
|
|
var n2 = e2._bin, o2 = {}, s2 = n2.readUint(r3, t3);
|
|
return t3 += 4, o2.numGlyphs = n2.readUshort(r3, t3), t3 += 2, 65536 == s2 && (o2.maxPoints = n2.readUshort(r3, t3), t3 += 2, o2.maxContours = n2.readUshort(r3, t3), t3 += 2, o2.maxCompositePoints = n2.readUshort(r3, t3), t3 += 2, o2.maxCompositeContours = n2.readUshort(r3, t3), t3 += 2, o2.maxZones = n2.readUshort(r3, t3), t3 += 2, o2.maxTwilightPoints = n2.readUshort(r3, t3), t3 += 2, o2.maxStorage = n2.readUshort(r3, t3), t3 += 2, o2.maxFunctionDefs = n2.readUshort(r3, t3), t3 += 2, o2.maxInstructionDefs = n2.readUshort(r3, t3), t3 += 2, o2.maxStackElements = n2.readUshort(r3, t3), t3 += 2, o2.maxSizeOfInstructions = n2.readUshort(r3, t3), t3 += 2, o2.maxComponentElements = n2.readUshort(r3, t3), t3 += 2, o2.maxComponentDepth = n2.readUshort(r3, t3), t3 += 2), o2;
|
|
}, e2.name = {}, e2.name.parse = function(r3, t3, a6) {
|
|
var n2 = e2._bin, o2 = {};
|
|
n2.readUshort(r3, t3), t3 += 2;
|
|
var s2 = n2.readUshort(r3, t3);
|
|
t3 += 2, n2.readUshort(r3, t3);
|
|
for (var i3, h = ["copyright", "fontFamily", "fontSubfamily", "ID", "fullName", "version", "postScriptName", "trademark", "manufacturer", "designer", "description", "urlVendor", "urlDesigner", "licence", "licenceURL", "---", "typoFamilyName", "typoSubfamilyName", "compatibleFull", "sampleText", "postScriptCID", "wwsFamilyName", "wwsSubfamilyName", "lightPalette", "darkPalette"], d2 = t3 += 2, f2 = 0; f2 < s2; f2++) {
|
|
var u = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var l2 = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var v5 = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var c2 = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var p2 = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var U = n2.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var g, S = h[c2], m = d2 + 12 * s2 + U;
|
|
if (0 == u) g = n2.readUnicode(r3, m, p2 / 2);
|
|
else if (3 == u && 0 == l2) g = n2.readUnicode(r3, m, p2 / 2);
|
|
else if (0 == l2) g = n2.readASCII(r3, m, p2);
|
|
else if (1 == l2) g = n2.readUnicode(r3, m, p2 / 2);
|
|
else if (3 == l2) g = n2.readUnicode(r3, m, p2 / 2);
|
|
else {
|
|
if (1 != u) throw "unknown encoding " + l2 + ", platformID: " + u;
|
|
g = n2.readASCII(r3, m, p2), console.debug("reading unknown MAC encoding " + l2 + " as ASCII");
|
|
}
|
|
var b = "p" + u + "," + v5.toString(16);
|
|
null == o2[b] && (o2[b] = {}), o2[b][void 0 !== S ? S : c2] = g, o2[b]._lang = v5;
|
|
}
|
|
for (var y in o2) if (null != o2[y].postScriptName && 1033 == o2[y]._lang) return o2[y];
|
|
for (var y in o2) if (null != o2[y].postScriptName && 0 == o2[y]._lang) return o2[y];
|
|
for (var y in o2) if (null != o2[y].postScriptName && 3084 == o2[y]._lang) return o2[y];
|
|
for (var y in o2) if (null != o2[y].postScriptName) return o2[y];
|
|
for (var y in o2) {
|
|
i3 = y;
|
|
break;
|
|
}
|
|
return console.debug("returning name table with languageID " + o2[i3]._lang), o2[i3];
|
|
}, e2["OS/2"] = {}, e2["OS/2"].parse = function(r3, t3, a6) {
|
|
var n2 = e2._bin.readUshort(r3, t3);
|
|
t3 += 2;
|
|
var o2 = {};
|
|
if (0 == n2) e2["OS/2"].version0(r3, t3, o2);
|
|
else if (1 == n2) e2["OS/2"].version1(r3, t3, o2);
|
|
else if (2 == n2 || 3 == n2 || 4 == n2) e2["OS/2"].version2(r3, t3, o2);
|
|
else {
|
|
if (5 != n2) throw "unknown OS/2 table version: " + n2;
|
|
e2["OS/2"].version5(r3, t3, o2);
|
|
}
|
|
return o2;
|
|
}, e2["OS/2"].version0 = function(r3, t3, a6) {
|
|
var n2 = e2._bin;
|
|
return a6.xAvgCharWidth = n2.readShort(r3, t3), t3 += 2, a6.usWeightClass = n2.readUshort(r3, t3), t3 += 2, a6.usWidthClass = n2.readUshort(r3, t3), t3 += 2, a6.fsType = n2.readUshort(r3, t3), t3 += 2, a6.ySubscriptXSize = n2.readShort(r3, t3), t3 += 2, a6.ySubscriptYSize = n2.readShort(r3, t3), t3 += 2, a6.ySubscriptXOffset = n2.readShort(r3, t3), t3 += 2, a6.ySubscriptYOffset = n2.readShort(r3, t3), t3 += 2, a6.ySuperscriptXSize = n2.readShort(r3, t3), t3 += 2, a6.ySuperscriptYSize = n2.readShort(r3, t3), t3 += 2, a6.ySuperscriptXOffset = n2.readShort(r3, t3), t3 += 2, a6.ySuperscriptYOffset = n2.readShort(r3, t3), t3 += 2, a6.yStrikeoutSize = n2.readShort(r3, t3), t3 += 2, a6.yStrikeoutPosition = n2.readShort(r3, t3), t3 += 2, a6.sFamilyClass = n2.readShort(r3, t3), t3 += 2, a6.panose = n2.readBytes(r3, t3, 10), t3 += 10, a6.ulUnicodeRange1 = n2.readUint(r3, t3), t3 += 4, a6.ulUnicodeRange2 = n2.readUint(r3, t3), t3 += 4, a6.ulUnicodeRange3 = n2.readUint(r3, t3), t3 += 4, a6.ulUnicodeRange4 = n2.readUint(r3, t3), t3 += 4, a6.achVendID = [n2.readInt8(r3, t3), n2.readInt8(r3, t3 + 1), n2.readInt8(r3, t3 + 2), n2.readInt8(r3, t3 + 3)], t3 += 4, a6.fsSelection = n2.readUshort(r3, t3), t3 += 2, a6.usFirstCharIndex = n2.readUshort(r3, t3), t3 += 2, a6.usLastCharIndex = n2.readUshort(r3, t3), t3 += 2, a6.sTypoAscender = n2.readShort(r3, t3), t3 += 2, a6.sTypoDescender = n2.readShort(r3, t3), t3 += 2, a6.sTypoLineGap = n2.readShort(r3, t3), t3 += 2, a6.usWinAscent = n2.readUshort(r3, t3), t3 += 2, a6.usWinDescent = n2.readUshort(r3, t3), t3 += 2;
|
|
}, e2["OS/2"].version1 = function(r3, t3, a6) {
|
|
var n2 = e2._bin;
|
|
return t3 = e2["OS/2"].version0(r3, t3, a6), a6.ulCodePageRange1 = n2.readUint(r3, t3), t3 += 4, a6.ulCodePageRange2 = n2.readUint(r3, t3), t3 += 4;
|
|
}, e2["OS/2"].version2 = function(r3, t3, a6) {
|
|
var n2 = e2._bin;
|
|
return t3 = e2["OS/2"].version1(r3, t3, a6), a6.sxHeight = n2.readShort(r3, t3), t3 += 2, a6.sCapHeight = n2.readShort(r3, t3), t3 += 2, a6.usDefault = n2.readUshort(r3, t3), t3 += 2, a6.usBreak = n2.readUshort(r3, t3), t3 += 2, a6.usMaxContext = n2.readUshort(r3, t3), t3 += 2;
|
|
}, e2["OS/2"].version5 = function(r3, t3, a6) {
|
|
var n2 = e2._bin;
|
|
return t3 = e2["OS/2"].version2(r3, t3, a6), a6.usLowerOpticalPointSize = n2.readUshort(r3, t3), t3 += 2, a6.usUpperOpticalPointSize = n2.readUshort(r3, t3), t3 += 2;
|
|
}, e2.post = {}, e2.post.parse = function(r3, t3, a6) {
|
|
var n2 = e2._bin, o2 = {};
|
|
return o2.version = n2.readFixed(r3, t3), t3 += 4, o2.italicAngle = n2.readFixed(r3, t3), t3 += 4, o2.underlinePosition = n2.readShort(r3, t3), t3 += 2, o2.underlineThickness = n2.readShort(r3, t3), t3 += 2, o2;
|
|
}, null == e2 && (e2 = {}), null == e2.U && (e2.U = {}), e2.U.codeToGlyph = function(r3, e3) {
|
|
var t3 = r3.cmap, a6 = -1;
|
|
if (null != t3.p0e4 ? a6 = t3.p0e4 : null != t3.p3e1 ? a6 = t3.p3e1 : null != t3.p1e0 ? a6 = t3.p1e0 : null != t3.p0e3 && (a6 = t3.p0e3), -1 == a6) throw "no familiar platform and encoding!";
|
|
var n2 = t3.tables[a6];
|
|
if (0 == n2.format) return e3 >= n2.map.length ? 0 : n2.map[e3];
|
|
if (4 == n2.format) {
|
|
for (var o2 = -1, s2 = 0; s2 < n2.endCount.length; s2++) if (e3 <= n2.endCount[s2]) {
|
|
o2 = s2;
|
|
break;
|
|
}
|
|
if (-1 == o2) return 0;
|
|
if (n2.startCount[o2] > e3) return 0;
|
|
return 65535 & (0 != n2.idRangeOffset[o2] ? n2.glyphIdArray[e3 - n2.startCount[o2] + (n2.idRangeOffset[o2] >> 1) - (n2.idRangeOffset.length - o2)] : e3 + n2.idDelta[o2]);
|
|
}
|
|
if (12 == n2.format) {
|
|
if (e3 > n2.groups[n2.groups.length - 1][1]) return 0;
|
|
for (s2 = 0; s2 < n2.groups.length; s2++) {
|
|
var i3 = n2.groups[s2];
|
|
if (i3[0] <= e3 && e3 <= i3[1]) return i3[2] + (e3 - i3[0]);
|
|
}
|
|
return 0;
|
|
}
|
|
throw "unknown cmap table format " + n2.format;
|
|
}, e2.U.glyphToPath = function(r3, t3) {
|
|
var a6 = { cmds: [], crds: [] };
|
|
if (r3.SVG && r3.SVG.entries[t3]) {
|
|
var n2 = r3.SVG.entries[t3];
|
|
return null == n2 ? a6 : ("string" == typeof n2 && (n2 = e2.SVG.toPath(n2), r3.SVG.entries[t3] = n2), n2);
|
|
}
|
|
if (r3.CFF) {
|
|
var o2 = { x: 0, y: 0, stack: [], nStems: 0, haveWidth: false, width: r3.CFF.Private ? r3.CFF.Private.defaultWidthX : 0, open: false }, s2 = r3.CFF, i3 = r3.CFF.Private;
|
|
if (s2.ROS) {
|
|
for (var h = 0; s2.FDSelect[h + 2] <= t3; ) h += 2;
|
|
i3 = s2.FDArray[s2.FDSelect[h + 1]].Private;
|
|
}
|
|
e2.U._drawCFF(r3.CFF.CharStrings[t3], o2, s2, i3, a6);
|
|
} else r3.glyf && e2.U._drawGlyf(t3, r3, a6);
|
|
return a6;
|
|
}, e2.U._drawGlyf = function(r3, t3, a6) {
|
|
var n2 = t3.glyf[r3];
|
|
null == n2 && (n2 = t3.glyf[r3] = e2.glyf._parseGlyf(t3, r3)), null != n2 && (n2.noc > -1 ? e2.U._simpleGlyph(n2, a6) : e2.U._compoGlyph(n2, t3, a6));
|
|
}, e2.U._simpleGlyph = function(r3, t3) {
|
|
for (var a6 = 0; a6 < r3.noc; a6++) {
|
|
for (var n2 = 0 == a6 ? 0 : r3.endPts[a6 - 1] + 1, o2 = r3.endPts[a6], s2 = n2; s2 <= o2; s2++) {
|
|
var i3 = s2 == n2 ? o2 : s2 - 1, h = s2 == o2 ? n2 : s2 + 1, d2 = 1 & r3.flags[s2], f2 = 1 & r3.flags[i3], u = 1 & r3.flags[h], l2 = r3.xs[s2], v5 = r3.ys[s2];
|
|
if (s2 == n2) if (d2) {
|
|
if (!f2) {
|
|
e2.U.P.moveTo(t3, l2, v5);
|
|
continue;
|
|
}
|
|
e2.U.P.moveTo(t3, r3.xs[i3], r3.ys[i3]);
|
|
} else f2 ? e2.U.P.moveTo(t3, r3.xs[i3], r3.ys[i3]) : e2.U.P.moveTo(t3, (r3.xs[i3] + l2) / 2, (r3.ys[i3] + v5) / 2);
|
|
d2 ? f2 && e2.U.P.lineTo(t3, l2, v5) : u ? e2.U.P.qcurveTo(t3, l2, v5, r3.xs[h], r3.ys[h]) : e2.U.P.qcurveTo(t3, l2, v5, (l2 + r3.xs[h]) / 2, (v5 + r3.ys[h]) / 2);
|
|
}
|
|
e2.U.P.closePath(t3);
|
|
}
|
|
}, e2.U._compoGlyph = function(r3, t3, a6) {
|
|
for (var n2 = 0; n2 < r3.parts.length; n2++) {
|
|
var o2 = { cmds: [], crds: [] }, s2 = r3.parts[n2];
|
|
e2.U._drawGlyf(s2.glyphIndex, t3, o2);
|
|
for (var i3 = s2.m, h = 0; h < o2.crds.length; h += 2) {
|
|
var d2 = o2.crds[h], f2 = o2.crds[h + 1];
|
|
a6.crds.push(d2 * i3.a + f2 * i3.b + i3.tx), a6.crds.push(d2 * i3.c + f2 * i3.d + i3.ty);
|
|
}
|
|
for (h = 0; h < o2.cmds.length; h++) a6.cmds.push(o2.cmds[h]);
|
|
}
|
|
}, e2.U._getGlyphClass = function(r3, t3) {
|
|
var a6 = e2._lctf.getInterval(t3, r3);
|
|
return -1 == a6 ? 0 : t3[a6 + 2];
|
|
}, e2.U._applySubs = function(r3, t3, a6, n2) {
|
|
for (var o2 = r3.length - t3 - 1, s2 = 0; s2 < a6.tabs.length; s2++) if (null != a6.tabs[s2]) {
|
|
var i3, h = a6.tabs[s2];
|
|
if (!h.coverage || -1 != (i3 = e2._lctf.coverageIndex(h.coverage, r3[t3]))) {
|
|
if (1 == a6.ltype) r3[t3], 1 == h.fmt ? r3[t3] = r3[t3] + h.delta : r3[t3] = h.newg[i3];
|
|
else if (4 == a6.ltype) for (var d2 = h.vals[i3], f2 = 0; f2 < d2.length; f2++) {
|
|
var u = d2[f2], l2 = u.chain.length;
|
|
if (!(l2 > o2)) {
|
|
for (var v5 = true, c2 = 0, p2 = 0; p2 < l2; p2++) {
|
|
for (; -1 == r3[t3 + c2 + (1 + p2)]; ) c2++;
|
|
u.chain[p2] != r3[t3 + c2 + (1 + p2)] && (v5 = false);
|
|
}
|
|
if (v5) {
|
|
r3[t3] = u.nglyph;
|
|
for (p2 = 0; p2 < l2 + c2; p2++) r3[t3 + p2 + 1] = -1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (5 == a6.ltype && 2 == h.fmt) for (var U = e2._lctf.getInterval(h.cDef, r3[t3]), g = h.cDef[U + 2], S = h.scset[g], m = 0; m < S.length; m++) {
|
|
var b = S[m], y = b.input;
|
|
if (!(y.length > o2)) {
|
|
for (v5 = true, p2 = 0; p2 < y.length; p2++) {
|
|
var F = e2._lctf.getInterval(h.cDef, r3[t3 + 1 + p2]);
|
|
if (-1 == U && h.cDef[F + 2] != y[p2]) {
|
|
v5 = false;
|
|
break;
|
|
}
|
|
}
|
|
if (v5) {
|
|
var C = b.substLookupRecords;
|
|
for (f2 = 0; f2 < C.length; f2 += 2) C[f2], C[f2 + 1];
|
|
}
|
|
}
|
|
}
|
|
else if (6 == a6.ltype && 3 == h.fmt) {
|
|
if (!e2.U._glsCovered(r3, h.backCvg, t3 - h.backCvg.length)) continue;
|
|
if (!e2.U._glsCovered(r3, h.inptCvg, t3)) continue;
|
|
if (!e2.U._glsCovered(r3, h.ahedCvg, t3 + h.inptCvg.length)) continue;
|
|
var _ = h.lookupRec;
|
|
for (m = 0; m < _.length; m += 2) {
|
|
U = _[m];
|
|
var P = n2[_[m + 1]];
|
|
e2.U._applySubs(r3, t3 + U, P, n2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}, e2.U._glsCovered = function(r3, t3, a6) {
|
|
for (var n2 = 0; n2 < t3.length; n2++) {
|
|
if (-1 == e2._lctf.coverageIndex(t3[n2], r3[a6 + n2])) return false;
|
|
}
|
|
return true;
|
|
}, e2.U.glyphsToPath = function(r3, t3, a6) {
|
|
for (var n2 = { cmds: [], crds: [] }, o2 = 0, s2 = 0; s2 < t3.length; s2++) {
|
|
var i3 = t3[s2];
|
|
if (-1 != i3) {
|
|
for (var h = s2 < t3.length - 1 && -1 != t3[s2 + 1] ? t3[s2 + 1] : 0, d2 = e2.U.glyphToPath(r3, i3), f2 = 0; f2 < d2.crds.length; f2 += 2) n2.crds.push(d2.crds[f2] + o2), n2.crds.push(d2.crds[f2 + 1]);
|
|
a6 && n2.cmds.push(a6);
|
|
for (f2 = 0; f2 < d2.cmds.length; f2++) n2.cmds.push(d2.cmds[f2]);
|
|
a6 && n2.cmds.push("X"), o2 += r3.hmtx.aWidth[i3], s2 < t3.length - 1 && (o2 += e2.U.getPairAdjustment(r3, i3, h));
|
|
}
|
|
}
|
|
return n2;
|
|
}, e2.U.P = {}, e2.U.P.moveTo = function(r3, e3, t3) {
|
|
r3.cmds.push("M"), r3.crds.push(e3, t3);
|
|
}, e2.U.P.lineTo = function(r3, e3, t3) {
|
|
r3.cmds.push("L"), r3.crds.push(e3, t3);
|
|
}, e2.U.P.curveTo = function(r3, e3, t3, a6, n2, o2, s2) {
|
|
r3.cmds.push("C"), r3.crds.push(e3, t3, a6, n2, o2, s2);
|
|
}, e2.U.P.qcurveTo = function(r3, e3, t3, a6, n2) {
|
|
r3.cmds.push("Q"), r3.crds.push(e3, t3, a6, n2);
|
|
}, e2.U.P.closePath = function(r3) {
|
|
r3.cmds.push("Z");
|
|
}, e2.U._drawCFF = function(r3, t3, a6, n2, o2) {
|
|
for (var s2 = t3.stack, i3 = t3.nStems, h = t3.haveWidth, d2 = t3.width, f2 = t3.open, u = 0, l2 = t3.x, v5 = t3.y, c2 = 0, p2 = 0, U = 0, g = 0, S = 0, m = 0, b = 0, y = 0, F = 0, C = 0, _ = { val: 0, size: 0 }; u < r3.length; ) {
|
|
e2.CFF.getCharString(r3, u, _);
|
|
var P = _.val;
|
|
if (u += _.size, "o1" == P || "o18" == P) s2.length % 2 != 0 && !h && (d2 = s2.shift() + n2.nominalWidthX), i3 += s2.length >> 1, s2.length = 0, h = true;
|
|
else if ("o3" == P || "o23" == P) {
|
|
s2.length % 2 != 0 && !h && (d2 = s2.shift() + n2.nominalWidthX), i3 += s2.length >> 1, s2.length = 0, h = true;
|
|
} else if ("o4" == P) s2.length > 1 && !h && (d2 = s2.shift() + n2.nominalWidthX, h = true), f2 && e2.U.P.closePath(o2), v5 += s2.pop(), e2.U.P.moveTo(o2, l2, v5), f2 = true;
|
|
else if ("o5" == P) for (; s2.length > 0; ) l2 += s2.shift(), v5 += s2.shift(), e2.U.P.lineTo(o2, l2, v5);
|
|
else if ("o6" == P || "o7" == P) for (var x = s2.length, I = "o6" == P, w = 0; w < x; w++) {
|
|
var k = s2.shift();
|
|
I ? l2 += k : v5 += k, I = !I, e2.U.P.lineTo(o2, l2, v5);
|
|
}
|
|
else if ("o8" == P || "o24" == P) {
|
|
x = s2.length;
|
|
for (var G = 0; G + 6 <= x; ) c2 = l2 + s2.shift(), p2 = v5 + s2.shift(), U = c2 + s2.shift(), g = p2 + s2.shift(), l2 = U + s2.shift(), v5 = g + s2.shift(), e2.U.P.curveTo(o2, c2, p2, U, g, l2, v5), G += 6;
|
|
"o24" == P && (l2 += s2.shift(), v5 += s2.shift(), e2.U.P.lineTo(o2, l2, v5));
|
|
} else {
|
|
if ("o11" == P) break;
|
|
if ("o1234" == P || "o1235" == P || "o1236" == P || "o1237" == P) "o1234" == P && (p2 = v5, U = (c2 = l2 + s2.shift()) + s2.shift(), C = g = p2 + s2.shift(), m = g, y = v5, l2 = (b = (S = (F = U + s2.shift()) + s2.shift()) + s2.shift()) + s2.shift(), e2.U.P.curveTo(o2, c2, p2, U, g, F, C), e2.U.P.curveTo(o2, S, m, b, y, l2, v5)), "o1235" == P && (c2 = l2 + s2.shift(), p2 = v5 + s2.shift(), U = c2 + s2.shift(), g = p2 + s2.shift(), F = U + s2.shift(), C = g + s2.shift(), S = F + s2.shift(), m = C + s2.shift(), b = S + s2.shift(), y = m + s2.shift(), l2 = b + s2.shift(), v5 = y + s2.shift(), s2.shift(), e2.U.P.curveTo(o2, c2, p2, U, g, F, C), e2.U.P.curveTo(o2, S, m, b, y, l2, v5)), "o1236" == P && (c2 = l2 + s2.shift(), p2 = v5 + s2.shift(), U = c2 + s2.shift(), C = g = p2 + s2.shift(), m = g, b = (S = (F = U + s2.shift()) + s2.shift()) + s2.shift(), y = m + s2.shift(), l2 = b + s2.shift(), e2.U.P.curveTo(o2, c2, p2, U, g, F, C), e2.U.P.curveTo(o2, S, m, b, y, l2, v5)), "o1237" == P && (c2 = l2 + s2.shift(), p2 = v5 + s2.shift(), U = c2 + s2.shift(), g = p2 + s2.shift(), F = U + s2.shift(), C = g + s2.shift(), S = F + s2.shift(), m = C + s2.shift(), b = S + s2.shift(), y = m + s2.shift(), Math.abs(b - l2) > Math.abs(y - v5) ? l2 = b + s2.shift() : v5 = y + s2.shift(), e2.U.P.curveTo(o2, c2, p2, U, g, F, C), e2.U.P.curveTo(o2, S, m, b, y, l2, v5));
|
|
else if ("o14" == P) {
|
|
if (s2.length > 0 && !h && (d2 = s2.shift() + a6.nominalWidthX, h = true), 4 == s2.length) {
|
|
var O = s2.shift(), T = s2.shift(), D = s2.shift(), B = s2.shift(), A = e2.CFF.glyphBySE(a6, D), R = e2.CFF.glyphBySE(a6, B);
|
|
e2.U._drawCFF(a6.CharStrings[A], t3, a6, n2, o2), t3.x = O, t3.y = T, e2.U._drawCFF(a6.CharStrings[R], t3, a6, n2, o2);
|
|
}
|
|
f2 && (e2.U.P.closePath(o2), f2 = false);
|
|
} else if ("o19" == P || "o20" == P) {
|
|
s2.length % 2 != 0 && !h && (d2 = s2.shift() + n2.nominalWidthX), i3 += s2.length >> 1, s2.length = 0, h = true, u += i3 + 7 >> 3;
|
|
} else if ("o21" == P) s2.length > 2 && !h && (d2 = s2.shift() + n2.nominalWidthX, h = true), v5 += s2.pop(), l2 += s2.pop(), f2 && e2.U.P.closePath(o2), e2.U.P.moveTo(o2, l2, v5), f2 = true;
|
|
else if ("o22" == P) s2.length > 1 && !h && (d2 = s2.shift() + n2.nominalWidthX, h = true), l2 += s2.pop(), f2 && e2.U.P.closePath(o2), e2.U.P.moveTo(o2, l2, v5), f2 = true;
|
|
else if ("o25" == P) {
|
|
for (; s2.length > 6; ) l2 += s2.shift(), v5 += s2.shift(), e2.U.P.lineTo(o2, l2, v5);
|
|
c2 = l2 + s2.shift(), p2 = v5 + s2.shift(), U = c2 + s2.shift(), g = p2 + s2.shift(), l2 = U + s2.shift(), v5 = g + s2.shift(), e2.U.P.curveTo(o2, c2, p2, U, g, l2, v5);
|
|
} else if ("o26" == P) for (s2.length % 2 && (l2 += s2.shift()); s2.length > 0; ) c2 = l2, p2 = v5 + s2.shift(), l2 = U = c2 + s2.shift(), v5 = (g = p2 + s2.shift()) + s2.shift(), e2.U.P.curveTo(o2, c2, p2, U, g, l2, v5);
|
|
else if ("o27" == P) for (s2.length % 2 && (v5 += s2.shift()); s2.length > 0; ) p2 = v5, U = (c2 = l2 + s2.shift()) + s2.shift(), g = p2 + s2.shift(), l2 = U + s2.shift(), v5 = g, e2.U.P.curveTo(o2, c2, p2, U, g, l2, v5);
|
|
else if ("o10" == P || "o29" == P) {
|
|
var L = "o10" == P ? n2 : a6;
|
|
if (0 == s2.length) console.debug("error: empty stack");
|
|
else {
|
|
var W = s2.pop(), M = L.Subrs[W + L.Bias];
|
|
t3.x = l2, t3.y = v5, t3.nStems = i3, t3.haveWidth = h, t3.width = d2, t3.open = f2, e2.U._drawCFF(M, t3, a6, n2, o2), l2 = t3.x, v5 = t3.y, i3 = t3.nStems, h = t3.haveWidth, d2 = t3.width, f2 = t3.open;
|
|
}
|
|
} else if ("o30" == P || "o31" == P) {
|
|
var V2 = s2.length, E = (G = 0, "o31" == P);
|
|
for (G += V2 - (x = -3 & V2); G < x; ) E ? (p2 = v5, U = (c2 = l2 + s2.shift()) + s2.shift(), v5 = (g = p2 + s2.shift()) + s2.shift(), x - G == 5 ? (l2 = U + s2.shift(), G++) : l2 = U, E = false) : (c2 = l2, p2 = v5 + s2.shift(), U = c2 + s2.shift(), g = p2 + s2.shift(), l2 = U + s2.shift(), x - G == 5 ? (v5 = g + s2.shift(), G++) : v5 = g, E = true), e2.U.P.curveTo(o2, c2, p2, U, g, l2, v5), G += 4;
|
|
} else {
|
|
if ("o" == (P + "").charAt(0)) throw console.debug("Unknown operation: " + P, r3), P;
|
|
s2.push(P);
|
|
}
|
|
}
|
|
}
|
|
t3.x = l2, t3.y = v5, t3.nStems = i3, t3.haveWidth = h, t3.width = d2, t3.open = f2;
|
|
};
|
|
var t2 = e2, a5 = { Typr: t2 };
|
|
return r2.Typr = t2, r2.default = a5, Object.defineProperty(r2, "__esModule", { value: true }), r2;
|
|
})({}).Typr;
|
|
}
|
|
function woff2otfFactory() {
|
|
return (function(r2) {
|
|
var e2 = Uint8Array, n2 = Uint16Array, t2 = Uint32Array, a5 = new e2([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0]), i3 = new e2([0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 0, 0]), o2 = new e2([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]), f2 = function(r3, e3) {
|
|
for (var a6 = new n2(31), i4 = 0; i4 < 31; ++i4) a6[i4] = e3 += 1 << r3[i4 - 1];
|
|
var o3 = new t2(a6[30]);
|
|
for (i4 = 1; i4 < 30; ++i4) for (var f3 = a6[i4]; f3 < a6[i4 + 1]; ++f3) o3[f3] = f3 - a6[i4] << 5 | i4;
|
|
return [a6, o3];
|
|
}, u = f2(a5, 2), v5 = u[0], s2 = u[1];
|
|
v5[28] = 258, s2[258] = 28;
|
|
for (var l2 = f2(i3, 0)[0], c2 = new n2(32768), g = 0; g < 32768; ++g) {
|
|
var h = (43690 & g) >>> 1 | (21845 & g) << 1;
|
|
h = (61680 & (h = (52428 & h) >>> 2 | (13107 & h) << 2)) >>> 4 | (3855 & h) << 4, c2[g] = ((65280 & h) >>> 8 | (255 & h) << 8) >>> 1;
|
|
}
|
|
var w = function(r3, e3, t3) {
|
|
for (var a6 = r3.length, i4 = 0, o3 = new n2(e3); i4 < a6; ++i4) ++o3[r3[i4] - 1];
|
|
var f3, u2 = new n2(e3);
|
|
for (i4 = 0; i4 < e3; ++i4) u2[i4] = u2[i4 - 1] + o3[i4 - 1] << 1;
|
|
if (t3) {
|
|
f3 = new n2(1 << e3);
|
|
var v6 = 15 - e3;
|
|
for (i4 = 0; i4 < a6; ++i4) if (r3[i4]) for (var s3 = i4 << 4 | r3[i4], l3 = e3 - r3[i4], g2 = u2[r3[i4] - 1]++ << l3, h2 = g2 | (1 << l3) - 1; g2 <= h2; ++g2) f3[c2[g2] >>> v6] = s3;
|
|
} else for (f3 = new n2(a6), i4 = 0; i4 < a6; ++i4) r3[i4] && (f3[i4] = c2[u2[r3[i4] - 1]++] >>> 15 - r3[i4]);
|
|
return f3;
|
|
}, d2 = new e2(288);
|
|
for (g = 0; g < 144; ++g) d2[g] = 8;
|
|
for (g = 144; g < 256; ++g) d2[g] = 9;
|
|
for (g = 256; g < 280; ++g) d2[g] = 7;
|
|
for (g = 280; g < 288; ++g) d2[g] = 8;
|
|
var m = new e2(32);
|
|
for (g = 0; g < 32; ++g) m[g] = 5;
|
|
var b = w(d2, 9, 1), p2 = w(m, 5, 1), y = function(r3) {
|
|
for (var e3 = r3[0], n3 = 1; n3 < r3.length; ++n3) r3[n3] > e3 && (e3 = r3[n3]);
|
|
return e3;
|
|
}, L = function(r3, e3, n3) {
|
|
var t3 = e3 / 8 | 0;
|
|
return (r3[t3] | r3[t3 + 1] << 8) >> (7 & e3) & n3;
|
|
}, U = function(r3, e3) {
|
|
var n3 = e3 / 8 | 0;
|
|
return (r3[n3] | r3[n3 + 1] << 8 | r3[n3 + 2] << 16) >> (7 & e3);
|
|
}, k = ["unexpected EOF", "invalid block type", "invalid length/literal", "invalid distance", "stream finished", "no stream handler", , "no callback", "invalid UTF-8 data", "extra field too long", "date not in range 1980-2099", "filename too long", "stream finishing", "invalid zip data"], T = function(r3, e3, n3) {
|
|
var t3 = new Error(e3 || k[r3]);
|
|
if (t3.code = r3, Error.captureStackTrace && Error.captureStackTrace(t3, T), !n3) throw t3;
|
|
return t3;
|
|
}, O = function(r3, f3, u2) {
|
|
var s3 = r3.length;
|
|
if (!s3 || u2 && !u2.l && s3 < 5) return f3 || new e2(0);
|
|
var c5 = !f3 || u2, g2 = !u2 || u2.i;
|
|
u2 || (u2 = {}), f3 || (f3 = new e2(3 * s3));
|
|
var h2, d3 = function(r4) {
|
|
var n3 = f3.length;
|
|
if (r4 > n3) {
|
|
var t3 = new e2(Math.max(2 * n3, r4));
|
|
t3.set(f3), f3 = t3;
|
|
}
|
|
}, m2 = u2.f || 0, k2 = u2.p || 0, O2 = u2.b || 0, A2 = u2.l, x2 = u2.d, E = u2.m, D = u2.n, M = 8 * s3;
|
|
do {
|
|
if (!A2) {
|
|
u2.f = m2 = L(r3, k2, 1);
|
|
var S = L(r3, k2 + 1, 3);
|
|
if (k2 += 3, !S) {
|
|
var V2 = r3[(I = ((h2 = k2) / 8 | 0) + (7 & h2 && 1) + 4) - 4] | r3[I - 3] << 8, _ = I + V2;
|
|
if (_ > s3) {
|
|
g2 && T(0);
|
|
break;
|
|
}
|
|
c5 && d3(O2 + V2), f3.set(r3.subarray(I, _), O2), u2.b = O2 += V2, u2.p = k2 = 8 * _;
|
|
continue;
|
|
}
|
|
if (1 == S) A2 = b, x2 = p2, E = 9, D = 5;
|
|
else if (2 == S) {
|
|
var j = L(r3, k2, 31) + 257, z = L(r3, k2 + 10, 15) + 4, C = j + L(r3, k2 + 5, 31) + 1;
|
|
k2 += 14;
|
|
for (var F = new e2(C), P = new e2(19), q = 0; q < z; ++q) P[o2[q]] = L(r3, k2 + 3 * q, 7);
|
|
k2 += 3 * z;
|
|
var B = y(P), G = (1 << B) - 1, H = w(P, B, 1);
|
|
for (q = 0; q < C; ) {
|
|
var I, J = H[L(r3, k2, G)];
|
|
if (k2 += 15 & J, (I = J >>> 4) < 16) F[q++] = I;
|
|
else {
|
|
var K = 0, N = 0;
|
|
for (16 == I ? (N = 3 + L(r3, k2, 3), k2 += 2, K = F[q - 1]) : 17 == I ? (N = 3 + L(r3, k2, 7), k2 += 3) : 18 == I && (N = 11 + L(r3, k2, 127), k2 += 7); N--; ) F[q++] = K;
|
|
}
|
|
}
|
|
var Q = F.subarray(0, j), R = F.subarray(j);
|
|
E = y(Q), D = y(R), A2 = w(Q, E, 1), x2 = w(R, D, 1);
|
|
} else T(1);
|
|
if (k2 > M) {
|
|
g2 && T(0);
|
|
break;
|
|
}
|
|
}
|
|
c5 && d3(O2 + 131072);
|
|
for (var W = (1 << E) - 1, X = (1 << D) - 1, Y = k2; ; Y = k2) {
|
|
var Z = (K = A2[U(r3, k2) & W]) >>> 4;
|
|
if ((k2 += 15 & K) > M) {
|
|
g2 && T(0);
|
|
break;
|
|
}
|
|
if (K || T(2), Z < 256) f3[O2++] = Z;
|
|
else {
|
|
if (256 == Z) {
|
|
Y = k2, A2 = null;
|
|
break;
|
|
}
|
|
var $ = Z - 254;
|
|
if (Z > 264) {
|
|
var rr = a5[q = Z - 257];
|
|
$ = L(r3, k2, (1 << rr) - 1) + v5[q], k2 += rr;
|
|
}
|
|
var er = x2[U(r3, k2) & X], nr = er >>> 4;
|
|
er || T(3), k2 += 15 & er;
|
|
R = l2[nr];
|
|
if (nr > 3) {
|
|
rr = i3[nr];
|
|
R += U(r3, k2) & (1 << rr) - 1, k2 += rr;
|
|
}
|
|
if (k2 > M) {
|
|
g2 && T(0);
|
|
break;
|
|
}
|
|
c5 && d3(O2 + 131072);
|
|
for (var tr = O2 + $; O2 < tr; O2 += 4) f3[O2] = f3[O2 - R], f3[O2 + 1] = f3[O2 + 1 - R], f3[O2 + 2] = f3[O2 + 2 - R], f3[O2 + 3] = f3[O2 + 3 - R];
|
|
O2 = tr;
|
|
}
|
|
}
|
|
u2.l = A2, u2.p = Y, u2.b = O2, A2 && (m2 = 1, u2.m = E, u2.d = x2, u2.n = D);
|
|
} while (!m2);
|
|
return O2 == f3.length ? f3 : (function(r4, a6, i4) {
|
|
(null == a6 || a6 < 0) && (a6 = 0), (null == i4 || i4 > r4.length) && (i4 = r4.length);
|
|
var o3 = new (r4 instanceof n2 ? n2 : r4 instanceof t2 ? t2 : e2)(i4 - a6);
|
|
return o3.set(r4.subarray(a6, i4)), o3;
|
|
})(f3, 0, O2);
|
|
}, A = new e2(0);
|
|
var x = "undefined" != typeof TextDecoder && new TextDecoder();
|
|
try {
|
|
x.decode(A, { stream: true }), 1;
|
|
} catch (r3) {
|
|
}
|
|
return r2.convert_streams = function(r3) {
|
|
var e3 = new DataView(r3), n3 = 0;
|
|
function t3() {
|
|
var r4 = e3.getUint16(n3);
|
|
return n3 += 2, r4;
|
|
}
|
|
function a6() {
|
|
var r4 = e3.getUint32(n3);
|
|
return n3 += 4, r4;
|
|
}
|
|
function i4(r4) {
|
|
m2.setUint16(b5, r4), b5 += 2;
|
|
}
|
|
function o3(r4) {
|
|
m2.setUint32(b5, r4), b5 += 4;
|
|
}
|
|
for (var f3 = { signature: a6(), flavor: a6(), length: a6(), numTables: t3(), reserved: t3(), totalSfntSize: a6(), majorVersion: t3(), minorVersion: t3(), metaOffset: a6(), metaLength: a6(), metaOrigLength: a6(), privOffset: a6(), privLength: a6() }, u2 = 0; Math.pow(2, u2) <= f3.numTables; ) u2++;
|
|
u2--;
|
|
for (var v6 = 16 * Math.pow(2, u2), s3 = 16 * f3.numTables - v6, l3 = 12, c5 = [], g2 = 0; g2 < f3.numTables; g2++) c5.push({ tag: a6(), offset: a6(), compLength: a6(), origLength: a6(), origChecksum: a6() }), l3 += 16;
|
|
var h2, w2 = new Uint8Array(12 + 16 * c5.length + c5.reduce((function(r4, e4) {
|
|
return r4 + e4.origLength + 4;
|
|
}), 0)), d3 = w2.buffer, m2 = new DataView(d3), b5 = 0;
|
|
return o3(f3.flavor), i4(f3.numTables), i4(v6), i4(u2), i4(s3), c5.forEach((function(r4) {
|
|
o3(r4.tag), o3(r4.origChecksum), o3(l3), o3(r4.origLength), r4.outOffset = l3, (l3 += r4.origLength) % 4 != 0 && (l3 += 4 - l3 % 4);
|
|
})), c5.forEach((function(e4) {
|
|
var n4, t4 = r3.slice(e4.offset, e4.offset + e4.compLength);
|
|
if (e4.compLength != e4.origLength) {
|
|
var a7 = new Uint8Array(e4.origLength);
|
|
n4 = new Uint8Array(t4, 2), O(n4, a7);
|
|
} else a7 = new Uint8Array(t4);
|
|
w2.set(a7, e4.outOffset);
|
|
var i5 = 0;
|
|
(l3 = e4.outOffset + e4.origLength) % 4 != 0 && (i5 = 4 - l3 % 4), w2.set(new Uint8Array(i5).buffer, e4.outOffset + e4.origLength), h2 = l3 + i5;
|
|
})), d3.slice(0, h2);
|
|
}, Object.defineProperty(r2, "__esModule", { value: true }), r2;
|
|
})({}).convert_streams;
|
|
}
|
|
function parserFactory(Typr, woff2otf) {
|
|
const cmdArgLengths = {
|
|
M: 2,
|
|
L: 2,
|
|
Q: 4,
|
|
C: 6,
|
|
Z: 0
|
|
};
|
|
const joiningTypeRawData = { "C": "18g,ca,368,1kz", "D": "17k,6,2,2+4,5+c,2+6,2+1,10+1,9+f,j+11,2+1,a,2,2+1,15+2,3,j+2,6+3,2+8,2,2,2+1,w+a,4+e,3+3,2,3+2,3+5,23+w,2f+4,3,2+9,2,b,2+3,3,1k+9,6+1,3+1,2+2,2+d,30g,p+y,1,1+1g,f+x,2,sd2+1d,jf3+4,f+3,2+4,2+2,b+3,42,2,4+2,2+1,2,3,t+1,9f+w,2,el+2,2+g,d+2,2l,2+1,5,3+1,2+1,2,3,6,16wm+1v", "R": "17m+3,2,2,6+3,m,15+2,2+2,h+h,13,3+8,2,2,3+1,2,p+1,x,5+4,5,a,2,2,3,u,c+2,g+1,5,2+1,4+1,5j,6+1,2,b,2+2,f,2+1,1s+2,2,3+1,7,1ez0,2,2+1,4+4,b,4,3,b,42,2+2,4,3,2+1,2,o+3,ae,ep,x,2o+2,3+1,3,5+1,6", "L": "x9u,jff,a,fd,jv", "T": "4t,gj+33,7o+4,1+1,7c+18,2,2+1,2+1,2,21+a,2,1b+k,h,2u+6,3+5,3+1,2+3,y,2,v+q,2k+a,1n+8,a,p+3,2+8,2+2,2+4,18+2,3c+e,2+v,1k,2,5+7,5,4+6,b+1,u,1n,5+3,9,l+1,r,3+1,1m,5+1,5+1,3+2,4,v+1,4,c+1,1m,5+4,2+1,5,l+1,n+5,2,1n,3,2+3,9,8+1,c+1,v,1q,d,1f,4,1m+2,6+2,2+3,8+1,c+1,u,1n,3,7,6+1,l+1,t+1,1m+1,5+3,9,l+1,u,21,8+2,2,2j,3+6,d+7,2r,3+8,c+5,23+1,s,2,2,1k+d,2+4,2+1,6+a,2+z,a,2v+3,2+5,2+1,3+1,q+1,5+2,h+3,e,3+1,7,g,jk+2,qb+2,u+2,u+1,v+1,1t+1,2+6,9,3+a,a,1a+2,3c+1,z,3b+2,5+1,a,7+2,64+1,3,1n,2+6,2,2,3+7,7+9,3,1d+d,1,1+1,1s+3,1d,2+4,2,6,15+8,d+1,x+3,3+1,2+2,1l,2+1,4,2+2,1n+7,3+1,49+2,2+c,2+6,5,7,4+1,5j+1l,2+4,ek,3+1,r+4,1e+4,6+5,2p+c,1+3,1,1+2,1+b,2db+2,3y,2p+v,ff+3,30+1,n9x,1+2,2+9,x+1,29+1,7l,4,5,q+1,6,48+1,r+h,e,13+7,q+a,1b+2,1d,3+3,3+1,14,1w+5,3+1,3+1,d,9,1c,1g,2+2,3+1,6+1,2,17+1,9,6n,3,5,fn5,ki+f,h+f,5s,6y+2,ea,6b,46+4,1af+2,2+1,6+3,15+2,5,4m+1,fy+3,as+1,4a+a,4x,1j+e,1l+2,1e+3,3+1,1y+2,11+4,2+7,1r,d+1,1h+8,b+3,3,2o+2,3,2+1,7,4h,4+7,m+1,1m+1,4,12+6,4+4,5g+7,3+2,2,o,2d+5,2,5+1,2+1,6n+3,7+1,2+1,s+1,2e+7,3,2+1,2z,2,3+5,2,2u+2,3+3,2+4,78+8,2+1,75+1,2,5,41+3,3+1,5,x+9,15+5,3+3,9,a+5,3+2,1b+c,2+1,bb+6,2+5,2,2b+l,3+6,2+1,2+1,3f+5,4,2+1,2+6,2,21+1,4,2,9o+1,470+8,at4+4,1o+6,t5,1s+3,2a,f5l+1,2+3,43o+2,a+7,1+7,3+6,v+3,45+2,1j0+1i,5+1d,9,f,n+4,2+e,11t+6,2+g,3+6,2+1,2+4,7a+6,c6+3,15t+6,32+6,1,gzau,v+2n,3l+6n" };
|
|
const JT_LEFT = 1, JT_RIGHT = 2, JT_DUAL = 4, JT_TRANSPARENT = 8, JT_JOIN_CAUSING = 16, JT_NON_JOINING = 32;
|
|
let joiningTypeMap;
|
|
function getCharJoiningType(ch) {
|
|
if (!joiningTypeMap) {
|
|
const m = {
|
|
R: JT_RIGHT,
|
|
L: JT_LEFT,
|
|
D: JT_DUAL,
|
|
C: JT_JOIN_CAUSING,
|
|
U: JT_NON_JOINING,
|
|
T: JT_TRANSPARENT
|
|
};
|
|
joiningTypeMap = /* @__PURE__ */ new Map();
|
|
for (let type in joiningTypeRawData) {
|
|
let lastCode = 0;
|
|
joiningTypeRawData[type].split(",").forEach((range) => {
|
|
let [skip, step] = range.split("+");
|
|
skip = parseInt(skip, 36);
|
|
step = step ? parseInt(step, 36) : 0;
|
|
joiningTypeMap.set(lastCode += skip, m[type]);
|
|
for (let i3 = step; i3--; ) {
|
|
joiningTypeMap.set(++lastCode, m[type]);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
return joiningTypeMap.get(ch) || JT_NON_JOINING;
|
|
}
|
|
const ISOL = 1, INIT = 2, FINA = 3, MEDI = 4;
|
|
const formsToFeatures = [null, "isol", "init", "fina", "medi"];
|
|
function detectJoiningForms(str) {
|
|
const joiningForms = new Uint8Array(str.length);
|
|
let prevJoiningType = JT_NON_JOINING;
|
|
let prevForm = ISOL;
|
|
let prevIndex = -1;
|
|
for (let i3 = 0; i3 < str.length; i3++) {
|
|
const code = str.codePointAt(i3);
|
|
let joiningType = getCharJoiningType(code) | 0;
|
|
let form = ISOL;
|
|
if (joiningType & JT_TRANSPARENT) {
|
|
continue;
|
|
}
|
|
if (prevJoiningType & (JT_LEFT | JT_DUAL | JT_JOIN_CAUSING)) {
|
|
if (joiningType & (JT_RIGHT | JT_DUAL | JT_JOIN_CAUSING)) {
|
|
form = FINA;
|
|
if (prevForm === ISOL || prevForm === FINA) {
|
|
joiningForms[prevIndex]++;
|
|
}
|
|
} else if (joiningType & (JT_LEFT | JT_NON_JOINING)) {
|
|
if (prevForm === INIT || prevForm === MEDI) {
|
|
joiningForms[prevIndex]--;
|
|
}
|
|
}
|
|
} else if (prevJoiningType & (JT_RIGHT | JT_NON_JOINING)) {
|
|
if (prevForm === INIT || prevForm === MEDI) {
|
|
joiningForms[prevIndex]--;
|
|
}
|
|
}
|
|
prevForm = joiningForms[i3] = form;
|
|
prevJoiningType = joiningType;
|
|
prevIndex = i3;
|
|
if (code > 65535) i3++;
|
|
}
|
|
return joiningForms;
|
|
}
|
|
function stringToGlyphs(font, str) {
|
|
const glyphIds = [];
|
|
for (let i3 = 0; i3 < str.length; i3++) {
|
|
const cc = str.codePointAt(i3);
|
|
if (cc > 65535) i3++;
|
|
glyphIds.push(Typr.U.codeToGlyph(font, cc));
|
|
}
|
|
const gsub = font["GSUB"];
|
|
if (gsub) {
|
|
const { lookupList, featureList } = gsub;
|
|
let joiningForms;
|
|
const supportedFeatures = /^(rlig|liga|mset|isol|init|fina|medi|half|pres|blws|ccmp)$/;
|
|
const usedLookups = [];
|
|
featureList.forEach((feature) => {
|
|
if (supportedFeatures.test(feature.tag)) {
|
|
for (let ti = 0; ti < feature.tab.length; ti++) {
|
|
if (usedLookups[feature.tab[ti]]) continue;
|
|
usedLookups[feature.tab[ti]] = true;
|
|
const tab = lookupList[feature.tab[ti]];
|
|
const isJoiningFeature = /^(isol|init|fina|medi)$/.test(feature.tag);
|
|
if (isJoiningFeature && !joiningForms) {
|
|
joiningForms = detectJoiningForms(str);
|
|
}
|
|
for (let ci = 0; ci < glyphIds.length; ci++) {
|
|
if (!joiningForms || !isJoiningFeature || formsToFeatures[joiningForms[ci]] === feature.tag) {
|
|
Typr.U._applySubs(glyphIds, ci, tab, lookupList);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
return glyphIds;
|
|
}
|
|
function calcGlyphPositions(font, glyphIds) {
|
|
const positions = new Int16Array(glyphIds.length * 3);
|
|
let glyphIndex = 0;
|
|
for (; glyphIndex < glyphIds.length; glyphIndex++) {
|
|
const glyphId = glyphIds[glyphIndex];
|
|
if (glyphId === -1) continue;
|
|
positions[glyphIndex * 3 + 2] = font.hmtx.aWidth[glyphId];
|
|
const gpos = font.GPOS;
|
|
if (gpos) {
|
|
const llist = gpos.lookupList;
|
|
for (let i3 = 0; i3 < llist.length; i3++) {
|
|
const lookup = llist[i3];
|
|
for (let j = 0; j < lookup.tabs.length; j++) {
|
|
const tab = lookup.tabs[j];
|
|
if (lookup.ltype === 1) {
|
|
const ind = Typr._lctf.coverageIndex(tab.coverage, glyphId);
|
|
if (ind !== -1 && tab.pos) {
|
|
applyValueRecord(tab.pos, glyphIndex);
|
|
break;
|
|
}
|
|
} else if (lookup.ltype === 2) {
|
|
let adj = null;
|
|
let prevGlyphIndex = getPrevGlyphIndex();
|
|
if (prevGlyphIndex !== -1) {
|
|
const coverageIndex = Typr._lctf.coverageIndex(tab.coverage, glyphIds[prevGlyphIndex]);
|
|
if (coverageIndex !== -1) {
|
|
if (tab.fmt === 1) {
|
|
const right = tab.pairsets[coverageIndex];
|
|
for (let k = 0; k < right.length; k++) {
|
|
if (right[k].gid2 === glyphId) adj = right[k];
|
|
}
|
|
} else if (tab.fmt === 2) {
|
|
const c1 = Typr.U._getGlyphClass(glyphIds[prevGlyphIndex], tab.classDef1);
|
|
const c2 = Typr.U._getGlyphClass(glyphId, tab.classDef2);
|
|
adj = tab.matrix[c1][c2];
|
|
}
|
|
if (adj) {
|
|
if (adj.val1) applyValueRecord(adj.val1, prevGlyphIndex);
|
|
if (adj.val2) applyValueRecord(adj.val2, glyphIndex);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else if (lookup.ltype === 4) {
|
|
const markArrIndex = Typr._lctf.coverageIndex(tab.markCoverage, glyphId);
|
|
if (markArrIndex !== -1) {
|
|
const baseGlyphIndex = getPrevGlyphIndex(isBaseGlyph);
|
|
const baseArrIndex = baseGlyphIndex === -1 ? -1 : Typr._lctf.coverageIndex(tab.baseCoverage, glyphIds[baseGlyphIndex]);
|
|
if (baseArrIndex !== -1) {
|
|
const markRecord = tab.markArray[markArrIndex];
|
|
const baseAnchor = tab.baseArray[baseArrIndex][markRecord.markClass];
|
|
positions[glyphIndex * 3] = baseAnchor.x - markRecord.x + positions[baseGlyphIndex * 3] - positions[baseGlyphIndex * 3 + 2];
|
|
positions[glyphIndex * 3 + 1] = baseAnchor.y - markRecord.y + positions[baseGlyphIndex * 3 + 1];
|
|
break;
|
|
}
|
|
}
|
|
} else if (lookup.ltype === 6) {
|
|
const mark1ArrIndex = Typr._lctf.coverageIndex(tab.mark1Coverage, glyphId);
|
|
if (mark1ArrIndex !== -1) {
|
|
const prevGlyphIndex = getPrevGlyphIndex();
|
|
if (prevGlyphIndex !== -1) {
|
|
const prevGlyphId = glyphIds[prevGlyphIndex];
|
|
if (getGlyphClass(font, prevGlyphId) === 3) {
|
|
const mark2ArrIndex = Typr._lctf.coverageIndex(tab.mark2Coverage, prevGlyphId);
|
|
if (mark2ArrIndex !== -1) {
|
|
const mark1Record = tab.mark1Array[mark1ArrIndex];
|
|
const mark2Anchor = tab.mark2Array[mark2ArrIndex][mark1Record.markClass];
|
|
positions[glyphIndex * 3] = mark2Anchor.x - mark1Record.x + positions[prevGlyphIndex * 3] - positions[prevGlyphIndex * 3 + 2];
|
|
positions[glyphIndex * 3 + 1] = mark2Anchor.y - mark1Record.y + positions[prevGlyphIndex * 3 + 1];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (font.kern && !font.cff) {
|
|
const prevGlyphIndex = getPrevGlyphIndex();
|
|
if (prevGlyphIndex !== -1) {
|
|
const ind1 = font.kern.glyph1.indexOf(glyphIds[prevGlyphIndex]);
|
|
if (ind1 !== -1) {
|
|
const ind2 = font.kern.rval[ind1].glyph2.indexOf(glyphId);
|
|
if (ind2 !== -1) {
|
|
positions[prevGlyphIndex * 3 + 2] += font.kern.rval[ind1].vals[ind2];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return positions;
|
|
function getPrevGlyphIndex(filter) {
|
|
for (let i3 = glyphIndex - 1; i3 >= 0; i3--) {
|
|
if (glyphIds[i3] !== -1 && (!filter || filter(glyphIds[i3]))) {
|
|
return i3;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
function isBaseGlyph(glyphId) {
|
|
return getGlyphClass(font, glyphId) === 1;
|
|
}
|
|
function applyValueRecord(source, gi) {
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
positions[gi * 3 + i3] += source[i3] || 0;
|
|
}
|
|
}
|
|
}
|
|
function getGlyphClass(font, glyphId) {
|
|
const classDef = font.GDEF && font.GDEF.glyphClassDef;
|
|
return classDef ? Typr.U._getGlyphClass(glyphId, classDef) : 0;
|
|
}
|
|
function firstNum(...args) {
|
|
for (let i3 = 0; i3 < args.length; i3++) {
|
|
if (typeof args[i3] === "number") {
|
|
return args[i3];
|
|
}
|
|
}
|
|
}
|
|
function wrapFontObj(typrFont) {
|
|
const glyphMap = /* @__PURE__ */ Object.create(null);
|
|
const os2 = typrFont["OS/2"];
|
|
const hhea = typrFont.hhea;
|
|
const unitsPerEm = typrFont.head.unitsPerEm;
|
|
const ascender = firstNum(os2 && os2.sTypoAscender, hhea && hhea.ascender, unitsPerEm);
|
|
const fontObj = {
|
|
unitsPerEm,
|
|
ascender,
|
|
descender: firstNum(os2 && os2.sTypoDescender, hhea && hhea.descender, 0),
|
|
capHeight: firstNum(os2 && os2.sCapHeight, ascender),
|
|
xHeight: firstNum(os2 && os2.sxHeight, ascender),
|
|
lineGap: firstNum(os2 && os2.sTypoLineGap, hhea && hhea.lineGap),
|
|
supportsCodePoint(code) {
|
|
return Typr.U.codeToGlyph(typrFont, code) > 0;
|
|
},
|
|
forEachGlyph(text, fontSize, letterSpacing, callback) {
|
|
let penX = 0;
|
|
const fontScale = 1 / fontObj.unitsPerEm * fontSize;
|
|
const glyphIds = stringToGlyphs(typrFont, text);
|
|
let charIndex = 0;
|
|
const positions = calcGlyphPositions(typrFont, glyphIds);
|
|
glyphIds.forEach((glyphId, i3) => {
|
|
if (glyphId !== -1) {
|
|
let glyphObj = glyphMap[glyphId];
|
|
if (!glyphObj) {
|
|
const { cmds, crds } = Typr.U.glyphToPath(typrFont, glyphId);
|
|
let path = "";
|
|
let crdsIdx = 0;
|
|
for (let i4 = 0, len = cmds.length; i4 < len; i4++) {
|
|
const numArgs = cmdArgLengths[cmds[i4]];
|
|
path += cmds[i4];
|
|
for (let j = 1; j <= numArgs; j++) {
|
|
path += (j > 1 ? "," : "") + crds[crdsIdx++];
|
|
}
|
|
}
|
|
let xMin, yMin, xMax, yMax;
|
|
if (crds.length) {
|
|
xMin = yMin = Infinity;
|
|
xMax = yMax = -Infinity;
|
|
for (let i4 = 0, len = crds.length; i4 < len; i4 += 2) {
|
|
let x = crds[i4];
|
|
let y = crds[i4 + 1];
|
|
if (x < xMin) xMin = x;
|
|
if (y < yMin) yMin = y;
|
|
if (x > xMax) xMax = x;
|
|
if (y > yMax) yMax = y;
|
|
}
|
|
} else {
|
|
xMin = xMax = yMin = yMax = 0;
|
|
}
|
|
glyphObj = glyphMap[glyphId] = {
|
|
index: glyphId,
|
|
advanceWidth: typrFont.hmtx.aWidth[glyphId],
|
|
xMin,
|
|
yMin,
|
|
xMax,
|
|
yMax,
|
|
path
|
|
};
|
|
}
|
|
callback.call(
|
|
null,
|
|
glyphObj,
|
|
penX + positions[i3 * 3] * fontScale,
|
|
positions[i3 * 3 + 1] * fontScale,
|
|
charIndex
|
|
);
|
|
penX += positions[i3 * 3 + 2] * fontScale;
|
|
if (letterSpacing) {
|
|
penX += letterSpacing * fontSize;
|
|
}
|
|
}
|
|
charIndex += text.codePointAt(charIndex) > 65535 ? 2 : 1;
|
|
});
|
|
return penX;
|
|
}
|
|
};
|
|
return fontObj;
|
|
}
|
|
return function parse2(buffer2) {
|
|
const peek = new Uint8Array(buffer2, 0, 4);
|
|
const tag = Typr._bin.readASCII(peek, 0, 4);
|
|
if (tag === "wOFF") {
|
|
buffer2 = woff2otf(buffer2);
|
|
} else if (tag === "wOF2") {
|
|
throw new Error("woff2 fonts not supported");
|
|
}
|
|
return wrapFontObj(Typr.parse(buffer2)[0]);
|
|
};
|
|
}
|
|
var workerModule = defineWorkerModule({
|
|
name: "Typr Font Parser",
|
|
dependencies: [typrFactory, woff2otfFactory, parserFactory],
|
|
init(typrFactory2, woff2otfFactory2, parserFactory2) {
|
|
const Typr = typrFactory2();
|
|
const woff2otf = woff2otfFactory2();
|
|
return parserFactory2(Typr, woff2otf);
|
|
}
|
|
});
|
|
function unicodeFontResolverClientFactory() {
|
|
return (function(t2) {
|
|
var n2 = function() {
|
|
this.buckets = /* @__PURE__ */ new Map();
|
|
};
|
|
n2.prototype.add = function(t3) {
|
|
var n3 = t3 >> 5;
|
|
this.buckets.set(n3, (this.buckets.get(n3) || 0) | 1 << (31 & t3));
|
|
}, n2.prototype.has = function(t3) {
|
|
var n3 = this.buckets.get(t3 >> 5);
|
|
return void 0 !== n3 && 0 != (n3 & 1 << (31 & t3));
|
|
}, n2.prototype.serialize = function() {
|
|
var t3 = [];
|
|
return this.buckets.forEach((function(n3, r3) {
|
|
t3.push((+r3).toString(36) + ":" + n3.toString(36));
|
|
})), t3.join(",");
|
|
}, n2.prototype.deserialize = function(t3) {
|
|
var n3 = this;
|
|
this.buckets.clear(), t3.split(",").forEach((function(t4) {
|
|
var r3 = t4.split(":");
|
|
n3.buckets.set(parseInt(r3[0], 36), parseInt(r3[1], 36));
|
|
}));
|
|
};
|
|
var r2 = Math.pow(2, 8), e2 = r2 - 1, o2 = ~e2;
|
|
function a5(t3) {
|
|
var n3 = (function(t4) {
|
|
return t4 & o2;
|
|
})(t3).toString(16), e3 = (function(t4) {
|
|
return (t4 & o2) + r2 - 1;
|
|
})(t3).toString(16);
|
|
return "codepoint-index/plane" + (t3 >> 16) + "/" + n3 + "-" + e3 + ".json";
|
|
}
|
|
function i3(t3, n3) {
|
|
var r3 = t3 & e2, o3 = n3.codePointAt(r3 / 6 | 0);
|
|
return 0 != ((o3 = (o3 || 48) - 48) & 1 << r3 % 6);
|
|
}
|
|
function u(t3, n3) {
|
|
var r3;
|
|
(r3 = t3, r3.replace(/U\+/gi, "").replace(/^,+|,+$/g, "").split(/,+/).map((function(t4) {
|
|
return t4.split("-").map((function(t5) {
|
|
return parseInt(t5.trim(), 16);
|
|
}));
|
|
}))).forEach((function(t4) {
|
|
var r4 = t4[0], e3 = t4[1];
|
|
void 0 === e3 && (e3 = r4), n3(r4, e3);
|
|
}));
|
|
}
|
|
function c2(t3, n3) {
|
|
u(t3, (function(t4, r3) {
|
|
for (var e3 = t4; e3 <= r3; e3++) n3(e3);
|
|
}));
|
|
}
|
|
var s2 = {}, f2 = {}, l2 = /* @__PURE__ */ new WeakMap(), v5 = "https://cdn.jsdelivr.net/gh/lojjic/unicode-font-resolver@v1.0.1/packages/data";
|
|
function d2(t3) {
|
|
var r3 = l2.get(t3);
|
|
return r3 || (r3 = new n2(), c2(t3.ranges, (function(t4) {
|
|
return r3.add(t4);
|
|
})), l2.set(t3, r3)), r3;
|
|
}
|
|
var h, p2 = /* @__PURE__ */ new Map();
|
|
function g(t3, n3, r3) {
|
|
return t3[n3] ? n3 : t3[r3] ? r3 : (function(t4) {
|
|
for (var n4 in t4) return n4;
|
|
})(t3);
|
|
}
|
|
function w(t3, n3) {
|
|
var r3 = n3;
|
|
if (!t3.includes(r3)) {
|
|
r3 = 1 / 0;
|
|
for (var e3 = 0; e3 < t3.length; e3++) Math.abs(t3[e3] - n3) < Math.abs(r3 - n3) && (r3 = t3[e3]);
|
|
}
|
|
return r3;
|
|
}
|
|
function k(t3) {
|
|
return h || (h = /* @__PURE__ */ new Set(), c2("9-D,20,85,A0,1680,2000-200A,2028-202F,205F,3000", (function(t4) {
|
|
h.add(t4);
|
|
}))), h.has(t3);
|
|
}
|
|
return t2.CodePointSet = n2, t2.clearCache = function() {
|
|
s2 = {}, f2 = {};
|
|
}, t2.getFontsForString = function(t3, n3) {
|
|
void 0 === n3 && (n3 = {});
|
|
var r3, e3 = n3.lang;
|
|
void 0 === e3 && (e3 = new RegExp("\\p{Script=Hangul}", "u").test(r3 = t3) ? "ko" : new RegExp("\\p{Script=Hiragana}|\\p{Script=Katakana}", "u").test(r3) ? "ja" : "en");
|
|
var o3 = n3.category;
|
|
void 0 === o3 && (o3 = "sans-serif");
|
|
var u2 = n3.style;
|
|
void 0 === u2 && (u2 = "normal");
|
|
var c5 = n3.weight;
|
|
void 0 === c5 && (c5 = 400);
|
|
var l3 = (n3.dataUrl || v5).replace(/\/$/g, ""), h2 = /* @__PURE__ */ new Map(), y = new Uint8Array(t3.length), b = {}, m = {}, A = new Array(t3.length), S = /* @__PURE__ */ new Map(), j = false;
|
|
function M(t4) {
|
|
var n4 = p2.get(t4);
|
|
return n4 || (n4 = fetch(l3 + "/" + t4).then((function(t5) {
|
|
if (!t5.ok) throw new Error(t5.statusText);
|
|
return t5.json().then((function(t6) {
|
|
if (!Array.isArray(t6) || 1 !== t6[0]) throw new Error("Incorrect schema version; need 1, got " + t6[0]);
|
|
return t6[1];
|
|
}));
|
|
})).catch((function(n5) {
|
|
if (l3 !== v5) return j || (console.error('unicode-font-resolver: Failed loading from dataUrl "' + l3 + '", trying default CDN. ' + n5.message), j = true), l3 = v5, p2.delete(t4), M(t4);
|
|
throw n5;
|
|
})), p2.set(t4, n4)), n4;
|
|
}
|
|
for (var P = function(n4) {
|
|
var r4 = t3.codePointAt(n4), e4 = a5(r4);
|
|
A[n4] = e4, s2[e4] || S.has(e4) || S.set(e4, M(e4).then((function(t4) {
|
|
s2[e4] = t4;
|
|
}))), r4 > 65535 && (n4++, E = n4);
|
|
}, E = 0; E < t3.length; E++) P(E);
|
|
return Promise.all(S.values()).then((function() {
|
|
S.clear();
|
|
for (var n4 = function(n5) {
|
|
var o4 = t3.codePointAt(n5), a6 = null, u3 = s2[A[n5]], c6 = void 0;
|
|
for (var l4 in u3) {
|
|
var v6 = m[l4];
|
|
if (void 0 === v6 && (v6 = m[l4] = new RegExp(l4).test(e3 || "en")), v6) {
|
|
for (var d3 in c6 = l4, u3[l4]) if (i3(o4, u3[l4][d3])) {
|
|
a6 = d3;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (!a6) {
|
|
t: for (var h3 in u3) if (h3 !== c6) {
|
|
for (var p3 in u3[h3]) if (i3(o4, u3[h3][p3])) {
|
|
a6 = p3;
|
|
break t;
|
|
}
|
|
}
|
|
}
|
|
a6 || (console.debug("No font coverage for U+" + o4.toString(16)), a6 = "latin"), A[n5] = a6, f2[a6] || S.has(a6) || S.set(a6, M("font-meta/" + a6 + ".json").then((function(t4) {
|
|
f2[a6] = t4;
|
|
}))), o4 > 65535 && (n5++, r4 = n5);
|
|
}, r4 = 0; r4 < t3.length; r4++) n4(r4);
|
|
return Promise.all(S.values());
|
|
})).then((function() {
|
|
for (var n4, r4 = null, e4 = 0; e4 < t3.length; e4++) {
|
|
var a6 = t3.codePointAt(e4);
|
|
if (r4 && (k(a6) || d2(r4).has(a6))) y[e4] = y[e4 - 1];
|
|
else {
|
|
r4 = f2[A[e4]];
|
|
var i4 = b[r4.id];
|
|
if (!i4) {
|
|
var s3 = r4.typeforms, v6 = g(s3, o3, "sans-serif"), p3 = g(s3[v6], u2, "normal"), m2 = w(null === (n4 = s3[v6]) || void 0 === n4 ? void 0 : n4[p3], c5);
|
|
i4 = b[r4.id] = l3 + "/font-files/" + r4.id + "/" + v6 + "." + p3 + "." + m2 + ".woff";
|
|
}
|
|
var S2 = h2.get(i4);
|
|
null == S2 && (S2 = h2.size, h2.set(i4, S2)), y[e4] = S2;
|
|
}
|
|
a6 > 65535 && (e4++, y[e4] = y[e4 - 1]);
|
|
}
|
|
return { fontUrls: Array.from(h2.keys()), chars: y };
|
|
}));
|
|
}, Object.defineProperty(t2, "__esModule", { value: true }), t2;
|
|
})({});
|
|
}
|
|
function createFontResolver(fontParser, unicodeFontResolverClient) {
|
|
const parsedFonts = /* @__PURE__ */ Object.create(null);
|
|
const loadingFonts = /* @__PURE__ */ Object.create(null);
|
|
function doLoadFont(url, callback) {
|
|
const onError = (err) => {
|
|
console.error(`Failure loading font ${url}`, err);
|
|
};
|
|
try {
|
|
const request = new XMLHttpRequest();
|
|
request.open("get", url, true);
|
|
request.responseType = "arraybuffer";
|
|
request.onload = function() {
|
|
if (request.status >= 400) {
|
|
onError(new Error(request.statusText));
|
|
} else if (request.status > 0) {
|
|
try {
|
|
const fontObj = fontParser(request.response);
|
|
fontObj.src = url;
|
|
callback(fontObj);
|
|
} catch (e2) {
|
|
onError(e2);
|
|
}
|
|
}
|
|
};
|
|
request.onerror = onError;
|
|
request.send();
|
|
} catch (err) {
|
|
onError(err);
|
|
}
|
|
}
|
|
function loadFont(fontUrl, callback) {
|
|
let font = parsedFonts[fontUrl];
|
|
if (font) {
|
|
callback(font);
|
|
} else if (loadingFonts[fontUrl]) {
|
|
loadingFonts[fontUrl].push(callback);
|
|
} else {
|
|
loadingFonts[fontUrl] = [callback];
|
|
doLoadFont(fontUrl, (fontObj) => {
|
|
fontObj.src = fontUrl;
|
|
parsedFonts[fontUrl] = fontObj;
|
|
loadingFonts[fontUrl].forEach((cb) => cb(fontObj));
|
|
delete loadingFonts[fontUrl];
|
|
});
|
|
}
|
|
}
|
|
return function(text, callback, {
|
|
lang,
|
|
fonts: userFonts = [],
|
|
style = "normal",
|
|
weight = "normal",
|
|
unicodeFontsURL
|
|
} = {}) {
|
|
const charResolutions = new Uint8Array(text.length);
|
|
const fontResolutions = [];
|
|
if (!text.length) {
|
|
allDone();
|
|
}
|
|
const fontIndices = /* @__PURE__ */ new Map();
|
|
const fallbackRanges = [];
|
|
if (style !== "italic") style = "normal";
|
|
if (typeof weight !== "number") {
|
|
weight = weight === "bold" ? 700 : 400;
|
|
}
|
|
if (userFonts && !Array.isArray(userFonts)) {
|
|
userFonts = [userFonts];
|
|
}
|
|
userFonts = userFonts.slice().filter((def) => !def.lang || def.lang.test(lang)).reverse();
|
|
if (userFonts.length) {
|
|
const UNKNOWN = 0;
|
|
const RESOLVED = 1;
|
|
const NEEDS_FALLBACK = 2;
|
|
let prevCharResult = UNKNOWN;
|
|
(function resolveUserFonts(startIndex = 0) {
|
|
for (let i3 = startIndex, iLen = text.length; i3 < iLen; i3++) {
|
|
const codePoint = text.codePointAt(i3);
|
|
if (prevCharResult === RESOLVED && fontResolutions[charResolutions[i3 - 1]].supportsCodePoint(codePoint) || i3 > 0 && /\s/.test(text[i3])) {
|
|
charResolutions[i3] = charResolutions[i3 - 1];
|
|
if (prevCharResult === NEEDS_FALLBACK) {
|
|
fallbackRanges[fallbackRanges.length - 1][1] = i3;
|
|
}
|
|
} else {
|
|
for (let j = charResolutions[i3], jLen = userFonts.length; j <= jLen; j++) {
|
|
if (j === jLen) {
|
|
const range = prevCharResult === NEEDS_FALLBACK ? fallbackRanges[fallbackRanges.length - 1] : fallbackRanges[fallbackRanges.length] = [i3, i3];
|
|
range[1] = i3;
|
|
prevCharResult = NEEDS_FALLBACK;
|
|
} else {
|
|
charResolutions[i3] = j;
|
|
const { src, unicodeRange } = userFonts[j];
|
|
if (!unicodeRange || isCodeInRanges(codePoint, unicodeRange)) {
|
|
const fontObj = parsedFonts[src];
|
|
if (!fontObj) {
|
|
loadFont(src, () => {
|
|
resolveUserFonts(i3);
|
|
});
|
|
return;
|
|
}
|
|
if (fontObj.supportsCodePoint(codePoint)) {
|
|
let fontIndex = fontIndices.get(fontObj);
|
|
if (typeof fontIndex !== "number") {
|
|
fontIndex = fontResolutions.length;
|
|
fontResolutions.push(fontObj);
|
|
fontIndices.set(fontObj, fontIndex);
|
|
}
|
|
charResolutions[i3] = fontIndex;
|
|
prevCharResult = RESOLVED;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (codePoint > 65535 && i3 + 1 < iLen) {
|
|
charResolutions[i3 + 1] = charResolutions[i3];
|
|
i3++;
|
|
if (prevCharResult === NEEDS_FALLBACK) {
|
|
fallbackRanges[fallbackRanges.length - 1][1] = i3;
|
|
}
|
|
}
|
|
}
|
|
resolveFallbacks();
|
|
})();
|
|
} else {
|
|
fallbackRanges.push([0, text.length - 1]);
|
|
resolveFallbacks();
|
|
}
|
|
function resolveFallbacks() {
|
|
if (fallbackRanges.length) {
|
|
const fallbackString = fallbackRanges.map((range) => text.substring(range[0], range[1] + 1)).join("\n");
|
|
unicodeFontResolverClient.getFontsForString(fallbackString, {
|
|
lang: lang || void 0,
|
|
style,
|
|
weight,
|
|
dataUrl: unicodeFontsURL
|
|
}).then(({ fontUrls, chars }) => {
|
|
const fontIndexOffset = fontResolutions.length;
|
|
let charIdx = 0;
|
|
fallbackRanges.forEach((range) => {
|
|
for (let i3 = 0, endIdx = range[1] - range[0]; i3 <= endIdx; i3++) {
|
|
charResolutions[range[0] + i3] = chars[charIdx++] + fontIndexOffset;
|
|
}
|
|
charIdx++;
|
|
});
|
|
let loadedCount = 0;
|
|
fontUrls.forEach((url, i3) => {
|
|
loadFont(url, (fontObj) => {
|
|
fontResolutions[i3 + fontIndexOffset] = fontObj;
|
|
if (++loadedCount === fontUrls.length) {
|
|
allDone();
|
|
}
|
|
});
|
|
});
|
|
});
|
|
} else {
|
|
allDone();
|
|
}
|
|
}
|
|
function allDone() {
|
|
callback({
|
|
chars: charResolutions,
|
|
fonts: fontResolutions
|
|
});
|
|
}
|
|
function isCodeInRanges(code, ranges) {
|
|
for (let k = 0; k < ranges.length; k++) {
|
|
const [start, end = start] = ranges[k];
|
|
if (start <= code && code <= end) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
}
|
|
var fontResolverWorkerModule = defineWorkerModule({
|
|
name: "FontResolver",
|
|
dependencies: [
|
|
createFontResolver,
|
|
workerModule,
|
|
unicodeFontResolverClientFactory
|
|
],
|
|
init(createFontResolver2, fontParser, unicodeFontResolverClientFactory2) {
|
|
return createFontResolver2(fontParser, unicodeFontResolverClientFactory2());
|
|
}
|
|
});
|
|
function createTypesetter(resolveFonts, bidi) {
|
|
const INF = Infinity;
|
|
const DEFAULT_IGNORABLE_CHARS = /[\u00AD\u034F\u061C\u115F-\u1160\u17B4-\u17B5\u180B-\u180E\u200B-\u200F\u202A-\u202E\u2060-\u206F\u3164\uFE00-\uFE0F\uFEFF\uFFA0\uFFF0-\uFFF8]/;
|
|
const lineBreakingWhiteSpace = `[^\\S\\u00A0]`;
|
|
const BREAK_AFTER_CHARS = new RegExp(`${lineBreakingWhiteSpace}|[\\-\\u007C\\u00AD\\u2010\\u2012-\\u2014\\u2027\\u2056\\u2E17\\u2E40]`);
|
|
function calculateFontRuns({ text, lang, fonts, style, weight, preResolvedFonts, unicodeFontsURL }, onDone) {
|
|
const onResolved = ({ chars, fonts: parsedFonts }) => {
|
|
let curRun, prevVal;
|
|
const runs = [];
|
|
for (let i3 = 0; i3 < chars.length; i3++) {
|
|
if (chars[i3] !== prevVal) {
|
|
prevVal = chars[i3];
|
|
runs.push(curRun = { start: i3, end: i3, fontObj: parsedFonts[chars[i3]] });
|
|
} else {
|
|
curRun.end = i3;
|
|
}
|
|
}
|
|
onDone(runs);
|
|
};
|
|
if (preResolvedFonts) {
|
|
onResolved(preResolvedFonts);
|
|
} else {
|
|
resolveFonts(
|
|
text,
|
|
onResolved,
|
|
{ lang, fonts, style, weight, unicodeFontsURL }
|
|
);
|
|
}
|
|
}
|
|
function typeset({
|
|
text = "",
|
|
font,
|
|
lang,
|
|
sdfGlyphSize = 64,
|
|
fontSize = 400,
|
|
fontWeight = 1,
|
|
fontStyle = "normal",
|
|
letterSpacing = 0,
|
|
lineHeight = "normal",
|
|
maxWidth = INF,
|
|
direction: direction2,
|
|
textAlign = "left",
|
|
textIndent = 0,
|
|
whiteSpace = "normal",
|
|
overflowWrap = "normal",
|
|
anchorX = 0,
|
|
anchorY = 0,
|
|
metricsOnly = false,
|
|
unicodeFontsURL,
|
|
preResolvedFonts = null,
|
|
includeCaretPositions = false,
|
|
chunkedBoundsSize = 8192,
|
|
colorRanges = null
|
|
}, callback) {
|
|
const mainStart = now2();
|
|
const timings = { fontLoad: 0, typesetting: 0 };
|
|
if (text.indexOf("\r") > -1) {
|
|
console.info("Typesetter: got text with \\r chars; normalizing to \\n");
|
|
text = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
}
|
|
fontSize = +fontSize;
|
|
letterSpacing = +letterSpacing;
|
|
maxWidth = +maxWidth;
|
|
lineHeight = lineHeight || "normal";
|
|
textIndent = +textIndent;
|
|
calculateFontRuns({
|
|
text,
|
|
lang,
|
|
style: fontStyle,
|
|
weight: fontWeight,
|
|
fonts: typeof font === "string" ? [{ src: font }] : font,
|
|
unicodeFontsURL,
|
|
preResolvedFonts
|
|
}, (runs) => {
|
|
timings.fontLoad = now2() - mainStart;
|
|
const hasMaxWidth = isFinite(maxWidth);
|
|
let glyphIds = null;
|
|
let glyphFontIndices = null;
|
|
let glyphPositions = null;
|
|
let glyphData = null;
|
|
let glyphColors = null;
|
|
let caretPositions = null;
|
|
let visibleBounds = null;
|
|
let chunkedBounds = null;
|
|
let maxLineWidth = 0;
|
|
let renderableGlyphCount = 0;
|
|
let canWrap = whiteSpace !== "nowrap";
|
|
const metricsByFont = /* @__PURE__ */ new Map();
|
|
const typesetStart = now2();
|
|
let lineXOffset = textIndent;
|
|
let prevRunEndX = 0;
|
|
let currentLine = new TextLine();
|
|
const lines = [currentLine];
|
|
runs.forEach((run) => {
|
|
const { fontObj } = run;
|
|
const { ascender, descender, unitsPerEm, lineGap, capHeight, xHeight } = fontObj;
|
|
let fontData2 = metricsByFont.get(fontObj);
|
|
if (!fontData2) {
|
|
const fontSizeMult2 = fontSize / unitsPerEm;
|
|
const calcLineHeight = lineHeight === "normal" ? (ascender - descender + lineGap) * fontSizeMult2 : lineHeight * fontSize;
|
|
const halfLeading = (calcLineHeight - (ascender - descender) * fontSizeMult2) / 2;
|
|
const caretHeight = Math.min(calcLineHeight, (ascender - descender) * fontSizeMult2);
|
|
const caretTop = (ascender + descender) / 2 * fontSizeMult2 + caretHeight / 2;
|
|
fontData2 = {
|
|
index: metricsByFont.size,
|
|
src: fontObj.src,
|
|
fontObj,
|
|
fontSizeMult: fontSizeMult2,
|
|
unitsPerEm,
|
|
ascender: ascender * fontSizeMult2,
|
|
descender: descender * fontSizeMult2,
|
|
capHeight: capHeight * fontSizeMult2,
|
|
xHeight: xHeight * fontSizeMult2,
|
|
lineHeight: calcLineHeight,
|
|
baseline: -halfLeading - ascender * fontSizeMult2,
|
|
// baseline offset from top of line height
|
|
// cap: -halfLeading - capHeight * fontSizeMult, // cap from top of line height
|
|
// ex: -halfLeading - xHeight * fontSizeMult, // ex from top of line height
|
|
caretTop,
|
|
caretBottom: caretTop - caretHeight
|
|
};
|
|
metricsByFont.set(fontObj, fontData2);
|
|
}
|
|
const { fontSizeMult } = fontData2;
|
|
const runText = text.slice(run.start, run.end + 1);
|
|
let prevGlyphX, prevGlyphObj;
|
|
fontObj.forEachGlyph(runText, fontSize, letterSpacing, (glyphObj, glyphX, glyphY, charIndex) => {
|
|
glyphX += prevRunEndX;
|
|
charIndex += run.start;
|
|
prevGlyphX = glyphX;
|
|
prevGlyphObj = glyphObj;
|
|
const char = text.charAt(charIndex);
|
|
const glyphWidth = glyphObj.advanceWidth * fontSizeMult;
|
|
const curLineCount = currentLine.count;
|
|
let nextLine;
|
|
if (!("isEmpty" in glyphObj)) {
|
|
glyphObj.isWhitespace = !!char && new RegExp(lineBreakingWhiteSpace).test(char);
|
|
glyphObj.canBreakAfter = !!char && BREAK_AFTER_CHARS.test(char);
|
|
glyphObj.isEmpty = glyphObj.xMin === glyphObj.xMax || glyphObj.yMin === glyphObj.yMax || DEFAULT_IGNORABLE_CHARS.test(char);
|
|
}
|
|
if (!glyphObj.isWhitespace && !glyphObj.isEmpty) {
|
|
renderableGlyphCount++;
|
|
}
|
|
if (canWrap && hasMaxWidth && !glyphObj.isWhitespace && glyphX + glyphWidth + lineXOffset > maxWidth && curLineCount) {
|
|
if (currentLine.glyphAt(curLineCount - 1).glyphObj.canBreakAfter) {
|
|
nextLine = new TextLine();
|
|
lineXOffset = -glyphX;
|
|
} else {
|
|
for (let i3 = curLineCount; i3--; ) {
|
|
if (i3 === 0 && overflowWrap === "break-word") {
|
|
nextLine = new TextLine();
|
|
lineXOffset = -glyphX;
|
|
break;
|
|
} else if (currentLine.glyphAt(i3).glyphObj.canBreakAfter) {
|
|
nextLine = currentLine.splitAt(i3 + 1);
|
|
const adjustX = nextLine.glyphAt(0).x;
|
|
lineXOffset -= adjustX;
|
|
for (let j = nextLine.count; j--; ) {
|
|
nextLine.glyphAt(j).x -= adjustX;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (nextLine) {
|
|
currentLine.isSoftWrapped = true;
|
|
currentLine = nextLine;
|
|
lines.push(currentLine);
|
|
maxLineWidth = maxWidth;
|
|
}
|
|
}
|
|
let fly = currentLine.glyphAt(currentLine.count);
|
|
fly.glyphObj = glyphObj;
|
|
fly.x = glyphX + lineXOffset;
|
|
fly.y = glyphY;
|
|
fly.width = glyphWidth;
|
|
fly.charIndex = charIndex;
|
|
fly.fontData = fontData2;
|
|
if (char === "\n") {
|
|
currentLine = new TextLine();
|
|
lines.push(currentLine);
|
|
lineXOffset = -(glyphX + glyphWidth + letterSpacing * fontSize) + textIndent;
|
|
}
|
|
});
|
|
prevRunEndX = prevGlyphX + prevGlyphObj.advanceWidth * fontSizeMult + letterSpacing * fontSize;
|
|
});
|
|
let totalHeight = 0;
|
|
lines.forEach((line) => {
|
|
let isTrailingWhitespace = true;
|
|
for (let i3 = line.count; i3--; ) {
|
|
const glyphInfo = line.glyphAt(i3);
|
|
if (isTrailingWhitespace && !glyphInfo.glyphObj.isWhitespace) {
|
|
line.width = glyphInfo.x + glyphInfo.width;
|
|
if (line.width > maxLineWidth) {
|
|
maxLineWidth = line.width;
|
|
}
|
|
isTrailingWhitespace = false;
|
|
}
|
|
let { lineHeight: lineHeight2, capHeight, xHeight, baseline } = glyphInfo.fontData;
|
|
if (lineHeight2 > line.lineHeight) line.lineHeight = lineHeight2;
|
|
const baselineDiff = baseline - line.baseline;
|
|
if (baselineDiff < 0) {
|
|
line.baseline += baselineDiff;
|
|
line.cap += baselineDiff;
|
|
line.ex += baselineDiff;
|
|
}
|
|
line.cap = Math.max(line.cap, line.baseline + capHeight);
|
|
line.ex = Math.max(line.ex, line.baseline + xHeight);
|
|
}
|
|
line.baseline -= totalHeight;
|
|
line.cap -= totalHeight;
|
|
line.ex -= totalHeight;
|
|
totalHeight += line.lineHeight;
|
|
});
|
|
let anchorXOffset = 0;
|
|
let anchorYOffset = 0;
|
|
if (anchorX) {
|
|
if (typeof anchorX === "number") {
|
|
anchorXOffset = -anchorX;
|
|
} else if (typeof anchorX === "string") {
|
|
anchorXOffset = -maxLineWidth * (anchorX === "left" ? 0 : anchorX === "center" ? 0.5 : anchorX === "right" ? 1 : parsePercent(anchorX));
|
|
}
|
|
}
|
|
if (anchorY) {
|
|
if (typeof anchorY === "number") {
|
|
anchorYOffset = -anchorY;
|
|
} else if (typeof anchorY === "string") {
|
|
anchorYOffset = anchorY === "top" ? 0 : anchorY === "top-baseline" ? -lines[0].baseline : anchorY === "top-cap" ? -lines[0].cap : anchorY === "top-ex" ? -lines[0].ex : anchorY === "middle" ? totalHeight / 2 : anchorY === "bottom" ? totalHeight : anchorY === "bottom-baseline" ? -lines[lines.length - 1].baseline : parsePercent(anchorY) * totalHeight;
|
|
}
|
|
}
|
|
if (!metricsOnly) {
|
|
const bidiLevelsResult = bidi.getEmbeddingLevels(text, direction2);
|
|
glyphIds = new Uint16Array(renderableGlyphCount);
|
|
glyphFontIndices = new Uint8Array(renderableGlyphCount);
|
|
glyphPositions = new Float32Array(renderableGlyphCount * 2);
|
|
glyphData = {};
|
|
visibleBounds = [INF, INF, -INF, -INF];
|
|
chunkedBounds = [];
|
|
if (includeCaretPositions) {
|
|
caretPositions = new Float32Array(text.length * 4);
|
|
}
|
|
if (colorRanges) {
|
|
glyphColors = new Uint8Array(renderableGlyphCount * 3);
|
|
}
|
|
let renderableGlyphIndex = 0;
|
|
let prevCharIndex = -1;
|
|
let colorCharIndex = -1;
|
|
let chunk;
|
|
let currentColor;
|
|
lines.forEach((line, lineIndex) => {
|
|
let { count: lineGlyphCount, width: lineWidth } = line;
|
|
if (lineGlyphCount > 0) {
|
|
let trailingWhitespaceCount = 0;
|
|
for (let i3 = lineGlyphCount; i3-- && line.glyphAt(i3).glyphObj.isWhitespace; ) {
|
|
trailingWhitespaceCount++;
|
|
}
|
|
let lineXOffset2 = 0;
|
|
let justifyAdjust = 0;
|
|
if (textAlign === "center") {
|
|
lineXOffset2 = (maxLineWidth - lineWidth) / 2;
|
|
} else if (textAlign === "right") {
|
|
lineXOffset2 = maxLineWidth - lineWidth;
|
|
} else if (textAlign === "justify" && line.isSoftWrapped) {
|
|
let whitespaceCount = 0;
|
|
for (let i3 = lineGlyphCount - trailingWhitespaceCount; i3--; ) {
|
|
if (line.glyphAt(i3).glyphObj.isWhitespace) {
|
|
whitespaceCount++;
|
|
}
|
|
}
|
|
justifyAdjust = (maxLineWidth - lineWidth) / whitespaceCount;
|
|
}
|
|
if (justifyAdjust || lineXOffset2) {
|
|
let justifyOffset = 0;
|
|
for (let i3 = 0; i3 < lineGlyphCount; i3++) {
|
|
let glyphInfo = line.glyphAt(i3);
|
|
const glyphObj2 = glyphInfo.glyphObj;
|
|
glyphInfo.x += lineXOffset2 + justifyOffset;
|
|
if (justifyAdjust !== 0 && glyphObj2.isWhitespace && i3 < lineGlyphCount - trailingWhitespaceCount) {
|
|
justifyOffset += justifyAdjust;
|
|
glyphInfo.width += justifyAdjust;
|
|
}
|
|
}
|
|
}
|
|
const flips = bidi.getReorderSegments(
|
|
text,
|
|
bidiLevelsResult,
|
|
line.glyphAt(0).charIndex,
|
|
line.glyphAt(line.count - 1).charIndex
|
|
);
|
|
for (let fi = 0; fi < flips.length; fi++) {
|
|
const [start, end] = flips[fi];
|
|
let left = Infinity, right = -Infinity;
|
|
for (let i3 = 0; i3 < lineGlyphCount; i3++) {
|
|
if (line.glyphAt(i3).charIndex >= start) {
|
|
let startInLine = i3, endInLine = i3;
|
|
for (; endInLine < lineGlyphCount; endInLine++) {
|
|
let info = line.glyphAt(endInLine);
|
|
if (info.charIndex > end) {
|
|
break;
|
|
}
|
|
if (endInLine < lineGlyphCount - trailingWhitespaceCount) {
|
|
left = Math.min(left, info.x);
|
|
right = Math.max(right, info.x + info.width);
|
|
}
|
|
}
|
|
for (let j = startInLine; j < endInLine; j++) {
|
|
const glyphInfo = line.glyphAt(j);
|
|
glyphInfo.x = right - (glyphInfo.x + glyphInfo.width - left);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
let glyphObj;
|
|
const setGlyphObj = (g) => glyphObj = g;
|
|
for (let i3 = 0; i3 < lineGlyphCount; i3++) {
|
|
const glyphInfo = line.glyphAt(i3);
|
|
glyphObj = glyphInfo.glyphObj;
|
|
const glyphId = glyphObj.index;
|
|
const rtl = bidiLevelsResult.levels[glyphInfo.charIndex] & 1;
|
|
if (rtl) {
|
|
const mirrored = bidi.getMirroredCharacter(text[glyphInfo.charIndex]);
|
|
if (mirrored) {
|
|
glyphInfo.fontData.fontObj.forEachGlyph(mirrored, 0, 0, setGlyphObj);
|
|
}
|
|
}
|
|
if (includeCaretPositions) {
|
|
const { charIndex, fontData: fontData2 } = glyphInfo;
|
|
const caretLeft = glyphInfo.x + anchorXOffset;
|
|
const caretRight = glyphInfo.x + glyphInfo.width + anchorXOffset;
|
|
caretPositions[charIndex * 4] = rtl ? caretRight : caretLeft;
|
|
caretPositions[charIndex * 4 + 1] = rtl ? caretLeft : caretRight;
|
|
caretPositions[charIndex * 4 + 2] = line.baseline + fontData2.caretBottom + anchorYOffset;
|
|
caretPositions[charIndex * 4 + 3] = line.baseline + fontData2.caretTop + anchorYOffset;
|
|
const ligCount = charIndex - prevCharIndex;
|
|
if (ligCount > 1) {
|
|
fillLigatureCaretPositions(caretPositions, prevCharIndex, ligCount);
|
|
}
|
|
prevCharIndex = charIndex;
|
|
}
|
|
if (colorRanges) {
|
|
const { charIndex } = glyphInfo;
|
|
while (charIndex > colorCharIndex) {
|
|
colorCharIndex++;
|
|
if (colorRanges.hasOwnProperty(colorCharIndex)) {
|
|
currentColor = colorRanges[colorCharIndex];
|
|
}
|
|
}
|
|
}
|
|
if (!glyphObj.isWhitespace && !glyphObj.isEmpty) {
|
|
const idx = renderableGlyphIndex++;
|
|
const { fontSizeMult, src: fontSrc, index: fontIndex } = glyphInfo.fontData;
|
|
const fontGlyphData = glyphData[fontSrc] || (glyphData[fontSrc] = {});
|
|
if (!fontGlyphData[glyphId]) {
|
|
fontGlyphData[glyphId] = {
|
|
path: glyphObj.path,
|
|
pathBounds: [glyphObj.xMin, glyphObj.yMin, glyphObj.xMax, glyphObj.yMax]
|
|
};
|
|
}
|
|
const glyphX = glyphInfo.x + anchorXOffset;
|
|
const glyphY = glyphInfo.y + line.baseline + anchorYOffset;
|
|
glyphPositions[idx * 2] = glyphX;
|
|
glyphPositions[idx * 2 + 1] = glyphY;
|
|
const visX0 = glyphX + glyphObj.xMin * fontSizeMult;
|
|
const visY0 = glyphY + glyphObj.yMin * fontSizeMult;
|
|
const visX1 = glyphX + glyphObj.xMax * fontSizeMult;
|
|
const visY1 = glyphY + glyphObj.yMax * fontSizeMult;
|
|
if (visX0 < visibleBounds[0]) visibleBounds[0] = visX0;
|
|
if (visY0 < visibleBounds[1]) visibleBounds[1] = visY0;
|
|
if (visX1 > visibleBounds[2]) visibleBounds[2] = visX1;
|
|
if (visY1 > visibleBounds[3]) visibleBounds[3] = visY1;
|
|
if (idx % chunkedBoundsSize === 0) {
|
|
chunk = { start: idx, end: idx, rect: [INF, INF, -INF, -INF] };
|
|
chunkedBounds.push(chunk);
|
|
}
|
|
chunk.end++;
|
|
const chunkRect = chunk.rect;
|
|
if (visX0 < chunkRect[0]) chunkRect[0] = visX0;
|
|
if (visY0 < chunkRect[1]) chunkRect[1] = visY0;
|
|
if (visX1 > chunkRect[2]) chunkRect[2] = visX1;
|
|
if (visY1 > chunkRect[3]) chunkRect[3] = visY1;
|
|
glyphIds[idx] = glyphId;
|
|
glyphFontIndices[idx] = fontIndex;
|
|
if (colorRanges) {
|
|
const start = idx * 3;
|
|
glyphColors[start] = currentColor >> 16 & 255;
|
|
glyphColors[start + 1] = currentColor >> 8 & 255;
|
|
glyphColors[start + 2] = currentColor & 255;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
if (caretPositions) {
|
|
const ligCount = text.length - prevCharIndex;
|
|
if (ligCount > 1) {
|
|
fillLigatureCaretPositions(caretPositions, prevCharIndex, ligCount);
|
|
}
|
|
}
|
|
}
|
|
const fontData = [];
|
|
metricsByFont.forEach(({ index: index2, src, unitsPerEm, ascender, descender, lineHeight: lineHeight2, capHeight, xHeight }) => {
|
|
fontData[index2] = { src, unitsPerEm, ascender, descender, lineHeight: lineHeight2, capHeight, xHeight };
|
|
});
|
|
timings.typesetting = now2() - typesetStart;
|
|
callback({
|
|
glyphIds,
|
|
//id for each glyph, specific to that glyph's font
|
|
glyphFontIndices,
|
|
//index into fontData for each glyph
|
|
glyphPositions,
|
|
//x,y of each glyph's origin in layout
|
|
glyphData,
|
|
//dict holding data about each glyph appearing in the text
|
|
fontData,
|
|
//data about each font used in the text
|
|
caretPositions,
|
|
//startX,endX,bottomY caret positions for each char
|
|
// caretHeight, //height of cursor from bottom to top - todo per glyph?
|
|
glyphColors,
|
|
//color for each glyph, if color ranges supplied
|
|
chunkedBounds,
|
|
//total rects per (n=chunkedBoundsSize) consecutive glyphs
|
|
fontSize,
|
|
//calculated em height
|
|
topBaseline: anchorYOffset + lines[0].baseline,
|
|
//y coordinate of the top line's baseline
|
|
blockBounds: [
|
|
//bounds for the whole block of text, including vertical padding for lineHeight
|
|
anchorXOffset,
|
|
anchorYOffset - totalHeight,
|
|
anchorXOffset + maxLineWidth,
|
|
anchorYOffset
|
|
],
|
|
visibleBounds,
|
|
//total bounds of visible text paths, may be larger or smaller than blockBounds
|
|
timings
|
|
});
|
|
});
|
|
}
|
|
function measure(args, callback) {
|
|
typeset({ ...args, metricsOnly: true }, (result) => {
|
|
const [x0, y0, x1, y1] = result.blockBounds;
|
|
callback({
|
|
width: x1 - x0,
|
|
height: y1 - y0
|
|
});
|
|
});
|
|
}
|
|
function parsePercent(str) {
|
|
let match = str.match(/^([\d.]+)%$/);
|
|
let pct = match ? parseFloat(match[1]) : NaN;
|
|
return isNaN(pct) ? 0 : pct / 100;
|
|
}
|
|
function fillLigatureCaretPositions(caretPositions, ligStartIndex, ligCount) {
|
|
const ligStartX = caretPositions[ligStartIndex * 4];
|
|
const ligEndX = caretPositions[ligStartIndex * 4 + 1];
|
|
const ligBottom = caretPositions[ligStartIndex * 4 + 2];
|
|
const ligTop = caretPositions[ligStartIndex * 4 + 3];
|
|
const guessedAdvanceX = (ligEndX - ligStartX) / ligCount;
|
|
for (let i3 = 0; i3 < ligCount; i3++) {
|
|
const startIndex = (ligStartIndex + i3) * 4;
|
|
caretPositions[startIndex] = ligStartX + guessedAdvanceX * i3;
|
|
caretPositions[startIndex + 1] = ligStartX + guessedAdvanceX * (i3 + 1);
|
|
caretPositions[startIndex + 2] = ligBottom;
|
|
caretPositions[startIndex + 3] = ligTop;
|
|
}
|
|
}
|
|
function now2() {
|
|
return (self.performance || Date).now();
|
|
}
|
|
function TextLine() {
|
|
this.data = [];
|
|
}
|
|
const textLineProps = ["glyphObj", "x", "y", "width", "charIndex", "fontData"];
|
|
TextLine.prototype = {
|
|
width: 0,
|
|
lineHeight: 0,
|
|
baseline: 0,
|
|
cap: 0,
|
|
ex: 0,
|
|
isSoftWrapped: false,
|
|
get count() {
|
|
return Math.ceil(this.data.length / textLineProps.length);
|
|
},
|
|
glyphAt(i3) {
|
|
let fly = TextLine.flyweight;
|
|
fly.data = this.data;
|
|
fly.index = i3;
|
|
return fly;
|
|
},
|
|
splitAt(i3) {
|
|
let newLine = new TextLine();
|
|
newLine.data = this.data.splice(i3 * textLineProps.length);
|
|
return newLine;
|
|
}
|
|
};
|
|
TextLine.flyweight = textLineProps.reduce((obj, prop, i3, all) => {
|
|
Object.defineProperty(obj, prop, {
|
|
get() {
|
|
return this.data[this.index * textLineProps.length + i3];
|
|
},
|
|
set(val) {
|
|
this.data[this.index * textLineProps.length + i3] = val;
|
|
}
|
|
});
|
|
return obj;
|
|
}, { data: null, index: 0 });
|
|
return {
|
|
typeset,
|
|
measure
|
|
};
|
|
}
|
|
var now = () => (self.performance || Date).now();
|
|
var mainThreadGenerator = SDFGenerator();
|
|
var warned;
|
|
function generateSDF(width, height, path, viewBox, distance3, exponent, canvas, x, y, channel, useWebGL = true) {
|
|
if (!useWebGL) {
|
|
return generateSDF_JS_Worker(width, height, path, viewBox, distance3, exponent, canvas, x, y, channel);
|
|
}
|
|
return generateSDF_GL(width, height, path, viewBox, distance3, exponent, canvas, x, y, channel).then(
|
|
null,
|
|
(err) => {
|
|
if (!warned) {
|
|
console.warn(`WebGL SDF generation failed, falling back to JS`, err);
|
|
warned = true;
|
|
}
|
|
return generateSDF_JS_Worker(width, height, path, viewBox, distance3, exponent, canvas, x, y, channel);
|
|
}
|
|
);
|
|
}
|
|
var queue = [];
|
|
var chunkTimeBudget = 5;
|
|
var timer = 0;
|
|
function nextChunk() {
|
|
const start = now();
|
|
while (queue.length && now() - start < chunkTimeBudget) {
|
|
queue.shift()();
|
|
}
|
|
timer = queue.length ? setTimeout(nextChunk, 0) : 0;
|
|
}
|
|
var generateSDF_GL = (...args) => {
|
|
return new Promise((resolve, reject) => {
|
|
queue.push(() => {
|
|
const start = now();
|
|
try {
|
|
mainThreadGenerator.webgl.generateIntoCanvas(...args);
|
|
resolve({ timing: now() - start });
|
|
} catch (err) {
|
|
reject(err);
|
|
}
|
|
});
|
|
if (!timer) {
|
|
timer = setTimeout(nextChunk, 0);
|
|
}
|
|
});
|
|
};
|
|
var threadCount = 4;
|
|
var idleTimeout = 2e3;
|
|
var threads = {};
|
|
var callNum = 0;
|
|
function generateSDF_JS_Worker(width, height, path, viewBox, distance3, exponent, canvas, x, y, channel) {
|
|
const workerId = "TroikaTextSDFGenerator_JS_" + callNum++ % threadCount;
|
|
let thread = threads[workerId];
|
|
if (!thread) {
|
|
thread = threads[workerId] = {
|
|
workerModule: defineWorkerModule({
|
|
name: workerId,
|
|
workerId,
|
|
dependencies: [
|
|
SDFGenerator,
|
|
now
|
|
],
|
|
init(_createSDFGenerator, now2) {
|
|
const generate = _createSDFGenerator().javascript.generate;
|
|
return function(...args) {
|
|
const start = now2();
|
|
const textureData = generate(...args);
|
|
return {
|
|
textureData,
|
|
timing: now2() - start
|
|
};
|
|
};
|
|
},
|
|
getTransferables(result) {
|
|
return [result.textureData.buffer];
|
|
}
|
|
}),
|
|
requests: 0,
|
|
idleTimer: null
|
|
};
|
|
}
|
|
thread.requests++;
|
|
clearTimeout(thread.idleTimer);
|
|
return thread.workerModule(width, height, path, viewBox, distance3, exponent).then(({ textureData, timing }) => {
|
|
const start = now();
|
|
const imageData = new Uint8Array(textureData.length * 4);
|
|
for (let i3 = 0; i3 < textureData.length; i3++) {
|
|
imageData[i3 * 4 + channel] = textureData[i3];
|
|
}
|
|
mainThreadGenerator.webglUtils.renderImageData(canvas, imageData, x, y, width, height, 1 << 3 - channel);
|
|
timing += now() - start;
|
|
if (--thread.requests === 0) {
|
|
thread.idleTimer = setTimeout(() => {
|
|
terminateWorker(workerId);
|
|
}, idleTimeout);
|
|
}
|
|
return { timing };
|
|
});
|
|
}
|
|
function warmUpSDFCanvas(canvas) {
|
|
if (!canvas._warm) {
|
|
mainThreadGenerator.webgl.isSupported(canvas);
|
|
canvas._warm = true;
|
|
}
|
|
}
|
|
var resizeWebGLCanvasWithoutClearing = mainThreadGenerator.webglUtils.resizeWebGLCanvasWithoutClearing;
|
|
var CONFIG = {
|
|
defaultFontURL: null,
|
|
unicodeFontsURL: null,
|
|
sdfGlyphSize: 64,
|
|
sdfMargin: 1 / 16,
|
|
sdfExponent: 9,
|
|
textureWidth: 2048,
|
|
useWorker: true
|
|
};
|
|
var tempColor = new Color();
|
|
var hasRequested = false;
|
|
function now$1() {
|
|
return (self.performance || Date).now();
|
|
}
|
|
var atlases = /* @__PURE__ */ Object.create(null);
|
|
function getTextRenderInfo(args, callback) {
|
|
hasRequested = true;
|
|
args = assign2({}, args);
|
|
const totalStart = now$1();
|
|
const { defaultFontURL } = CONFIG;
|
|
const fonts = [];
|
|
if (defaultFontURL) {
|
|
fonts.push({ label: "default", src: toAbsoluteURL(defaultFontURL) });
|
|
}
|
|
if (args.font) {
|
|
fonts.push({ label: "user", src: toAbsoluteURL(args.font) });
|
|
}
|
|
args.font = fonts;
|
|
args.text = "" + args.text;
|
|
args.sdfGlyphSize = args.sdfGlyphSize || CONFIG.sdfGlyphSize;
|
|
args.unicodeFontsURL = args.unicodeFontsURL || CONFIG.unicodeFontsURL;
|
|
if (args.colorRanges != null) {
|
|
let colors2 = {};
|
|
for (let key in args.colorRanges) {
|
|
if (args.colorRanges.hasOwnProperty(key)) {
|
|
let val = args.colorRanges[key];
|
|
if (typeof val !== "number") {
|
|
val = tempColor.set(val).getHex();
|
|
}
|
|
colors2[key] = val;
|
|
}
|
|
}
|
|
args.colorRanges = colors2;
|
|
}
|
|
Object.freeze(args);
|
|
const { textureWidth, sdfExponent } = CONFIG;
|
|
const { sdfGlyphSize } = args;
|
|
const glyphsPerRow = textureWidth / sdfGlyphSize * 4;
|
|
let atlas = atlases[sdfGlyphSize];
|
|
if (!atlas) {
|
|
const canvas = document.createElement("canvas");
|
|
canvas.width = textureWidth;
|
|
canvas.height = sdfGlyphSize * 256 / glyphsPerRow;
|
|
atlas = atlases[sdfGlyphSize] = {
|
|
glyphCount: 0,
|
|
sdfGlyphSize,
|
|
sdfCanvas: canvas,
|
|
sdfTexture: new Texture(
|
|
canvas,
|
|
void 0,
|
|
void 0,
|
|
void 0,
|
|
LinearFilter,
|
|
LinearFilter
|
|
),
|
|
contextLost: false,
|
|
glyphsByFont: /* @__PURE__ */ new Map()
|
|
};
|
|
atlas.sdfTexture.generateMipmaps = false;
|
|
initContextLossHandling(atlas);
|
|
}
|
|
const { sdfTexture, sdfCanvas } = atlas;
|
|
const typeset = CONFIG.useWorker ? typesetInWorker : typesetOnMainThread;
|
|
typeset(args).then((result) => {
|
|
const { glyphIds, glyphFontIndices, fontData, glyphPositions, fontSize, timings } = result;
|
|
const neededSDFs = [];
|
|
const glyphBounds = new Float32Array(glyphIds.length * 4);
|
|
let boundsIdx = 0;
|
|
let positionsIdx = 0;
|
|
const quadsStart = now$1();
|
|
const fontGlyphMaps = fontData.map((font) => {
|
|
let map2 = atlas.glyphsByFont.get(font.src);
|
|
if (!map2) {
|
|
atlas.glyphsByFont.set(font.src, map2 = /* @__PURE__ */ new Map());
|
|
}
|
|
return map2;
|
|
});
|
|
glyphIds.forEach((glyphId, i3) => {
|
|
const fontIndex = glyphFontIndices[i3];
|
|
const { src: fontSrc, unitsPerEm } = fontData[fontIndex];
|
|
let glyphInfo = fontGlyphMaps[fontIndex].get(glyphId);
|
|
if (!glyphInfo) {
|
|
const { path, pathBounds } = result.glyphData[fontSrc][glyphId];
|
|
const fontUnitsMargin = Math.max(pathBounds[2] - pathBounds[0], pathBounds[3] - pathBounds[1]) / sdfGlyphSize * (CONFIG.sdfMargin * sdfGlyphSize + 0.5);
|
|
const atlasIndex = atlas.glyphCount++;
|
|
const sdfViewBox2 = [
|
|
pathBounds[0] - fontUnitsMargin,
|
|
pathBounds[1] - fontUnitsMargin,
|
|
pathBounds[2] + fontUnitsMargin,
|
|
pathBounds[3] + fontUnitsMargin
|
|
];
|
|
fontGlyphMaps[fontIndex].set(glyphId, glyphInfo = { path, atlasIndex, sdfViewBox: sdfViewBox2 });
|
|
neededSDFs.push(glyphInfo);
|
|
}
|
|
const { sdfViewBox } = glyphInfo;
|
|
const posX = glyphPositions[positionsIdx++];
|
|
const posY = glyphPositions[positionsIdx++];
|
|
const fontSizeMult = fontSize / unitsPerEm;
|
|
glyphBounds[boundsIdx++] = posX + sdfViewBox[0] * fontSizeMult;
|
|
glyphBounds[boundsIdx++] = posY + sdfViewBox[1] * fontSizeMult;
|
|
glyphBounds[boundsIdx++] = posX + sdfViewBox[2] * fontSizeMult;
|
|
glyphBounds[boundsIdx++] = posY + sdfViewBox[3] * fontSizeMult;
|
|
glyphIds[i3] = glyphInfo.atlasIndex;
|
|
});
|
|
timings.quads = (timings.quads || 0) + (now$1() - quadsStart);
|
|
const sdfStart = now$1();
|
|
timings.sdf = {};
|
|
const currentHeight = sdfCanvas.height;
|
|
const neededRows = Math.ceil(atlas.glyphCount / glyphsPerRow);
|
|
const neededHeight = Math.pow(2, Math.ceil(Math.log2(neededRows * sdfGlyphSize)));
|
|
if (neededHeight > currentHeight) {
|
|
console.info(`Increasing SDF texture size ${currentHeight}->${neededHeight}`);
|
|
resizeWebGLCanvasWithoutClearing(sdfCanvas, textureWidth, neededHeight);
|
|
sdfTexture.dispose();
|
|
}
|
|
Promise.all(neededSDFs.map(
|
|
(glyphInfo) => generateGlyphSDF(glyphInfo, atlas, args.gpuAccelerateSDF).then(({ timing }) => {
|
|
timings.sdf[glyphInfo.atlasIndex] = timing;
|
|
})
|
|
)).then(() => {
|
|
if (neededSDFs.length && !atlas.contextLost) {
|
|
safariPre15Workaround(atlas);
|
|
sdfTexture.needsUpdate = true;
|
|
}
|
|
timings.sdfTotal = now$1() - sdfStart;
|
|
timings.total = now$1() - totalStart;
|
|
callback(Object.freeze({
|
|
parameters: args,
|
|
sdfTexture,
|
|
sdfGlyphSize,
|
|
sdfExponent,
|
|
glyphBounds,
|
|
glyphAtlasIndices: glyphIds,
|
|
glyphColors: result.glyphColors,
|
|
caretPositions: result.caretPositions,
|
|
chunkedBounds: result.chunkedBounds,
|
|
ascender: result.ascender,
|
|
descender: result.descender,
|
|
lineHeight: result.lineHeight,
|
|
capHeight: result.capHeight,
|
|
xHeight: result.xHeight,
|
|
topBaseline: result.topBaseline,
|
|
blockBounds: result.blockBounds,
|
|
visibleBounds: result.visibleBounds,
|
|
timings: result.timings
|
|
}));
|
|
});
|
|
});
|
|
Promise.resolve().then(() => {
|
|
if (!atlas.contextLost) {
|
|
warmUpSDFCanvas(sdfCanvas);
|
|
}
|
|
});
|
|
}
|
|
function generateGlyphSDF({ path, atlasIndex, sdfViewBox }, { sdfGlyphSize, sdfCanvas, contextLost }, useGPU) {
|
|
if (contextLost) {
|
|
return Promise.resolve({ timing: -1 });
|
|
}
|
|
const { textureWidth, sdfExponent } = CONFIG;
|
|
const maxDist = Math.max(sdfViewBox[2] - sdfViewBox[0], sdfViewBox[3] - sdfViewBox[1]);
|
|
const squareIndex = Math.floor(atlasIndex / 4);
|
|
const x = squareIndex % (textureWidth / sdfGlyphSize) * sdfGlyphSize;
|
|
const y = Math.floor(squareIndex / (textureWidth / sdfGlyphSize)) * sdfGlyphSize;
|
|
const channel = atlasIndex % 4;
|
|
return generateSDF(sdfGlyphSize, sdfGlyphSize, path, sdfViewBox, maxDist, sdfExponent, sdfCanvas, x, y, channel, useGPU);
|
|
}
|
|
function initContextLossHandling(atlas) {
|
|
const canvas = atlas.sdfCanvas;
|
|
canvas.addEventListener("webglcontextlost", (event) => {
|
|
console.log("Context Lost", event);
|
|
event.preventDefault();
|
|
atlas.contextLost = true;
|
|
});
|
|
canvas.addEventListener("webglcontextrestored", (event) => {
|
|
console.log("Context Restored", event);
|
|
atlas.contextLost = false;
|
|
const promises = [];
|
|
atlas.glyphsByFont.forEach((glyphMap) => {
|
|
glyphMap.forEach((glyph) => {
|
|
promises.push(generateGlyphSDF(glyph, atlas, true));
|
|
});
|
|
});
|
|
Promise.all(promises).then(() => {
|
|
safariPre15Workaround(atlas);
|
|
atlas.sdfTexture.needsUpdate = true;
|
|
});
|
|
});
|
|
}
|
|
function preloadFont({ font, characters, sdfGlyphSize }, callback) {
|
|
let text = Array.isArray(characters) ? characters.join("\n") : "" + characters;
|
|
getTextRenderInfo({ font, sdfGlyphSize, text }, callback);
|
|
}
|
|
function assign2(toObj, fromObj) {
|
|
for (let key in fromObj) {
|
|
if (fromObj.hasOwnProperty(key)) {
|
|
toObj[key] = fromObj[key];
|
|
}
|
|
}
|
|
return toObj;
|
|
}
|
|
var linkEl;
|
|
function toAbsoluteURL(path) {
|
|
if (!linkEl) {
|
|
linkEl = typeof document === "undefined" ? {} : document.createElement("a");
|
|
}
|
|
linkEl.href = path;
|
|
return linkEl.href;
|
|
}
|
|
function safariPre15Workaround(atlas) {
|
|
if (typeof createImageBitmap !== "function") {
|
|
console.info("Safari<15: applying SDF canvas workaround");
|
|
const { sdfCanvas, sdfTexture } = atlas;
|
|
const { width, height } = sdfCanvas;
|
|
const gl = atlas.sdfCanvas.getContext("webgl");
|
|
let pixels = sdfTexture.image.data;
|
|
if (!pixels || pixels.length !== width * height * 4) {
|
|
pixels = new Uint8Array(width * height * 4);
|
|
sdfTexture.image = { width, height, data: pixels };
|
|
sdfTexture.flipY = false;
|
|
sdfTexture.isDataTexture = true;
|
|
}
|
|
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
|
}
|
|
}
|
|
var typesetterWorkerModule = defineWorkerModule({
|
|
name: "Typesetter",
|
|
dependencies: [
|
|
createTypesetter,
|
|
fontResolverWorkerModule,
|
|
bidi_default
|
|
],
|
|
init(createTypesetter2, fontResolver, bidiFactory2) {
|
|
return createTypesetter2(fontResolver, bidiFactory2());
|
|
}
|
|
});
|
|
var typesetInWorker = defineWorkerModule({
|
|
name: "Typesetter",
|
|
dependencies: [
|
|
typesetterWorkerModule
|
|
],
|
|
init(typesetter) {
|
|
return function(args) {
|
|
return new Promise((resolve) => {
|
|
typesetter.typeset(args, resolve);
|
|
});
|
|
};
|
|
},
|
|
getTransferables(result) {
|
|
const transferables = [];
|
|
for (let p2 in result) {
|
|
if (result[p2] && result[p2].buffer) {
|
|
transferables.push(result[p2].buffer);
|
|
}
|
|
}
|
|
return transferables;
|
|
}
|
|
});
|
|
var typesetOnMainThread = typesetInWorker.onMainThread;
|
|
var templateGeometries = {};
|
|
function getTemplateGeometry(detail) {
|
|
let geom = templateGeometries[detail];
|
|
if (!geom) {
|
|
geom = templateGeometries[detail] = new PlaneGeometry(1, 1, detail, detail).translate(0.5, 0.5, 0);
|
|
}
|
|
return geom;
|
|
}
|
|
var glyphBoundsAttrName = "aTroikaGlyphBounds";
|
|
var glyphIndexAttrName = "aTroikaGlyphIndex";
|
|
var glyphColorAttrName = "aTroikaGlyphColor";
|
|
var GlyphsGeometry = class extends InstancedBufferGeometry {
|
|
constructor() {
|
|
super();
|
|
this.detail = 1;
|
|
this.curveRadius = 0;
|
|
this.groups = [
|
|
{ start: 0, count: Infinity, materialIndex: 0 },
|
|
{ start: 0, count: Infinity, materialIndex: 1 }
|
|
];
|
|
this.boundingSphere = new Sphere();
|
|
this.boundingBox = new Box3();
|
|
}
|
|
computeBoundingSphere() {
|
|
}
|
|
computeBoundingBox() {
|
|
}
|
|
set detail(detail) {
|
|
if (detail !== this._detail) {
|
|
this._detail = detail;
|
|
if (typeof detail !== "number" || detail < 1) {
|
|
detail = 1;
|
|
}
|
|
let tpl = getTemplateGeometry(detail);
|
|
["position", "normal", "uv"].forEach((attr) => {
|
|
this.attributes[attr] = tpl.attributes[attr].clone();
|
|
});
|
|
this.setIndex(tpl.getIndex().clone());
|
|
}
|
|
}
|
|
get detail() {
|
|
return this._detail;
|
|
}
|
|
set curveRadius(r2) {
|
|
if (r2 !== this._curveRadius) {
|
|
this._curveRadius = r2;
|
|
this._updateBounds();
|
|
}
|
|
}
|
|
get curveRadius() {
|
|
return this._curveRadius;
|
|
}
|
|
/**
|
|
* Update the geometry for a new set of glyphs.
|
|
* @param {Float32Array} glyphBounds - An array holding the planar bounds for all glyphs
|
|
* to be rendered, 4 entries for each glyph: x1,x2,y1,y1
|
|
* @param {Float32Array} glyphAtlasIndices - An array holding the index of each glyph within
|
|
* the SDF atlas texture.
|
|
* @param {Array} blockBounds - An array holding the [minX, minY, maxX, maxY] across all glyphs
|
|
* @param {Array} [chunkedBounds] - An array of objects describing bounds for each chunk of N
|
|
* consecutive glyphs: `{start:N, end:N, rect:[minX, minY, maxX, maxY]}`. This can be
|
|
* used with `applyClipRect` to choose an optimized `instanceCount`.
|
|
* @param {Uint8Array} [glyphColors] - An array holding r,g,b values for each glyph.
|
|
*/
|
|
updateGlyphs(glyphBounds, glyphAtlasIndices, blockBounds, chunkedBounds, glyphColors) {
|
|
this.updateAttributeData(glyphBoundsAttrName, glyphBounds, 4);
|
|
this.updateAttributeData(glyphIndexAttrName, glyphAtlasIndices, 1);
|
|
this.updateAttributeData(glyphColorAttrName, glyphColors, 3);
|
|
this._blockBounds = blockBounds;
|
|
this._chunkedBounds = chunkedBounds;
|
|
this.instanceCount = glyphAtlasIndices.length;
|
|
this._updateBounds();
|
|
}
|
|
_updateBounds() {
|
|
const bounds = this._blockBounds;
|
|
if (bounds) {
|
|
const { curveRadius, boundingBox: bbox } = this;
|
|
if (curveRadius) {
|
|
const { PI, floor, min, max, sin, cos } = Math;
|
|
const halfPi = PI / 2;
|
|
const twoPi = PI * 2;
|
|
const absR = Math.abs(curveRadius);
|
|
const leftAngle = bounds[0] / absR;
|
|
const rightAngle = bounds[2] / absR;
|
|
const minX = floor((leftAngle + halfPi) / twoPi) !== floor((rightAngle + halfPi) / twoPi) ? -absR : min(sin(leftAngle) * absR, sin(rightAngle) * absR);
|
|
const maxX = floor((leftAngle - halfPi) / twoPi) !== floor((rightAngle - halfPi) / twoPi) ? absR : max(sin(leftAngle) * absR, sin(rightAngle) * absR);
|
|
const maxZ = floor((leftAngle + PI) / twoPi) !== floor((rightAngle + PI) / twoPi) ? absR * 2 : max(absR - cos(leftAngle) * absR, absR - cos(rightAngle) * absR);
|
|
bbox.min.set(minX, bounds[1], curveRadius < 0 ? -maxZ : 0);
|
|
bbox.max.set(maxX, bounds[3], curveRadius < 0 ? 0 : maxZ);
|
|
} else {
|
|
bbox.min.set(bounds[0], bounds[1], 0);
|
|
bbox.max.set(bounds[2], bounds[3], 0);
|
|
}
|
|
bbox.getBoundingSphere(this.boundingSphere);
|
|
}
|
|
}
|
|
/**
|
|
* Given a clipping rect, and the chunkedBounds from the last updateGlyphs call, choose the lowest
|
|
* `instanceCount` that will show all glyphs within the clipped view. This is an optimization
|
|
* for long blocks of text that are clipped, to skip vertex shader evaluation for glyphs that would
|
|
* be clipped anyway.
|
|
*
|
|
* Note that since `drawElementsInstanced[ANGLE]` only accepts an instance count and not a starting
|
|
* offset, this optimization becomes less effective as the clipRect moves closer to the end of the
|
|
* text block. We could fix that by switching from instancing to a full geometry with a drawRange,
|
|
* but at the expense of much larger attribute buffers (see classdoc above.)
|
|
*
|
|
* @param {Vector4} clipRect
|
|
*/
|
|
applyClipRect(clipRect) {
|
|
let count = this.getAttribute(glyphIndexAttrName).count;
|
|
let chunks = this._chunkedBounds;
|
|
if (chunks) {
|
|
for (let i3 = chunks.length; i3--; ) {
|
|
count = chunks[i3].end;
|
|
let rect = chunks[i3].rect;
|
|
if (rect[1] < clipRect.w && rect[3] > clipRect.y && rect[0] < clipRect.z && rect[2] > clipRect.x) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
this.instanceCount = count;
|
|
}
|
|
/**
|
|
* Utility for updating instance attributes with automatic resizing
|
|
*/
|
|
updateAttributeData(attrName, newArray, itemSize) {
|
|
const attr = this.getAttribute(attrName);
|
|
if (newArray) {
|
|
if (attr && attr.array.length === newArray.length) {
|
|
attr.array.set(newArray);
|
|
attr.needsUpdate = true;
|
|
} else {
|
|
this.setAttribute(attrName, new InstancedBufferAttribute(newArray, itemSize));
|
|
delete this._maxInstanceCount;
|
|
this.dispose();
|
|
}
|
|
} else if (attr) {
|
|
this.deleteAttribute(attrName);
|
|
}
|
|
}
|
|
};
|
|
var VERTEX_DEFS = `
|
|
uniform vec2 uTroikaSDFTextureSize;
|
|
uniform float uTroikaSDFGlyphSize;
|
|
uniform vec4 uTroikaTotalBounds;
|
|
uniform vec4 uTroikaClipRect;
|
|
uniform mat3 uTroikaOrient;
|
|
uniform bool uTroikaUseGlyphColors;
|
|
uniform float uTroikaEdgeOffset;
|
|
uniform float uTroikaBlurRadius;
|
|
uniform vec2 uTroikaPositionOffset;
|
|
uniform float uTroikaCurveRadius;
|
|
attribute vec4 aTroikaGlyphBounds;
|
|
attribute float aTroikaGlyphIndex;
|
|
attribute vec3 aTroikaGlyphColor;
|
|
varying vec2 vTroikaGlyphUV;
|
|
varying vec4 vTroikaTextureUVBounds;
|
|
varying float vTroikaTextureChannel;
|
|
varying vec3 vTroikaGlyphColor;
|
|
varying vec2 vTroikaGlyphDimensions;
|
|
`;
|
|
var VERTEX_TRANSFORM = `
|
|
vec4 bounds = aTroikaGlyphBounds;
|
|
bounds.xz += uTroikaPositionOffset.x;
|
|
bounds.yw -= uTroikaPositionOffset.y;
|
|
|
|
vec4 outlineBounds = vec4(
|
|
bounds.xy - uTroikaEdgeOffset - uTroikaBlurRadius,
|
|
bounds.zw + uTroikaEdgeOffset + uTroikaBlurRadius
|
|
);
|
|
vec4 clippedBounds = vec4(
|
|
clamp(outlineBounds.xy, uTroikaClipRect.xy, uTroikaClipRect.zw),
|
|
clamp(outlineBounds.zw, uTroikaClipRect.xy, uTroikaClipRect.zw)
|
|
);
|
|
|
|
vec2 clippedXY = (mix(clippedBounds.xy, clippedBounds.zw, position.xy) - bounds.xy) / (bounds.zw - bounds.xy);
|
|
|
|
position.xy = mix(bounds.xy, bounds.zw, clippedXY);
|
|
|
|
uv = (position.xy - uTroikaTotalBounds.xy) / (uTroikaTotalBounds.zw - uTroikaTotalBounds.xy);
|
|
|
|
float rad = uTroikaCurveRadius;
|
|
if (rad != 0.0) {
|
|
float angle = position.x / rad;
|
|
position.xz = vec2(sin(angle) * rad, rad - cos(angle) * rad);
|
|
normal.xz = vec2(sin(angle), cos(angle));
|
|
}
|
|
|
|
position = uTroikaOrient * position;
|
|
normal = uTroikaOrient * normal;
|
|
|
|
vTroikaGlyphUV = clippedXY.xy;
|
|
vTroikaGlyphDimensions = vec2(bounds[2] - bounds[0], bounds[3] - bounds[1]);
|
|
|
|
${""}
|
|
float txCols = uTroikaSDFTextureSize.x / uTroikaSDFGlyphSize;
|
|
vec2 txUvPerSquare = uTroikaSDFGlyphSize / uTroikaSDFTextureSize;
|
|
vec2 txStartUV = txUvPerSquare * vec2(
|
|
mod(floor(aTroikaGlyphIndex / 4.0), txCols),
|
|
floor(floor(aTroikaGlyphIndex / 4.0) / txCols)
|
|
);
|
|
vTroikaTextureUVBounds = vec4(txStartUV, vec2(txStartUV) + txUvPerSquare);
|
|
vTroikaTextureChannel = mod(aTroikaGlyphIndex, 4.0);
|
|
`;
|
|
var FRAGMENT_DEFS = `
|
|
uniform sampler2D uTroikaSDFTexture;
|
|
uniform vec2 uTroikaSDFTextureSize;
|
|
uniform float uTroikaSDFGlyphSize;
|
|
uniform float uTroikaSDFExponent;
|
|
uniform float uTroikaEdgeOffset;
|
|
uniform float uTroikaFillOpacity;
|
|
uniform float uTroikaBlurRadius;
|
|
uniform vec3 uTroikaStrokeColor;
|
|
uniform float uTroikaStrokeWidth;
|
|
uniform float uTroikaStrokeOpacity;
|
|
uniform bool uTroikaSDFDebug;
|
|
varying vec2 vTroikaGlyphUV;
|
|
varying vec4 vTroikaTextureUVBounds;
|
|
varying float vTroikaTextureChannel;
|
|
varying vec2 vTroikaGlyphDimensions;
|
|
|
|
float troikaSdfValueToSignedDistance(float alpha) {
|
|
// Inverse of exponential encoding in webgl-sdf-generator
|
|
${""}
|
|
float maxDimension = max(vTroikaGlyphDimensions.x, vTroikaGlyphDimensions.y);
|
|
float absDist = (1.0 - pow(2.0 * (alpha > 0.5 ? 1.0 - alpha : alpha), 1.0 / uTroikaSDFExponent)) * maxDimension;
|
|
float signedDist = absDist * (alpha > 0.5 ? -1.0 : 1.0);
|
|
return signedDist;
|
|
}
|
|
|
|
float troikaGlyphUvToSdfValue(vec2 glyphUV) {
|
|
vec2 textureUV = mix(vTroikaTextureUVBounds.xy, vTroikaTextureUVBounds.zw, glyphUV);
|
|
vec4 rgba = texture2D(uTroikaSDFTexture, textureUV);
|
|
float ch = floor(vTroikaTextureChannel + 0.5); //NOTE: can't use round() in WebGL1
|
|
return ch == 0.0 ? rgba.r : ch == 1.0 ? rgba.g : ch == 2.0 ? rgba.b : rgba.a;
|
|
}
|
|
|
|
float troikaGlyphUvToDistance(vec2 uv) {
|
|
return troikaSdfValueToSignedDistance(troikaGlyphUvToSdfValue(uv));
|
|
}
|
|
|
|
float troikaGetAADist() {
|
|
${""}
|
|
#if defined(GL_OES_standard_derivatives) || __VERSION__ >= 300
|
|
return length(fwidth(vTroikaGlyphUV * vTroikaGlyphDimensions)) * 0.5;
|
|
#else
|
|
return vTroikaGlyphDimensions.x / 64.0;
|
|
#endif
|
|
}
|
|
|
|
float troikaGetFragDistValue() {
|
|
vec2 clampedGlyphUV = clamp(vTroikaGlyphUV, 0.5 / uTroikaSDFGlyphSize, 1.0 - 0.5 / uTroikaSDFGlyphSize);
|
|
float distance = troikaGlyphUvToDistance(clampedGlyphUV);
|
|
|
|
// Extrapolate distance when outside bounds:
|
|
distance += clampedGlyphUV == vTroikaGlyphUV ? 0.0 :
|
|
length((vTroikaGlyphUV - clampedGlyphUV) * vTroikaGlyphDimensions);
|
|
|
|
${""}
|
|
|
|
return distance;
|
|
}
|
|
|
|
float troikaGetEdgeAlpha(float distance, float distanceOffset, float aaDist) {
|
|
#if defined(IS_DEPTH_MATERIAL) || defined(IS_DISTANCE_MATERIAL)
|
|
float alpha = step(-distanceOffset, -distance);
|
|
#else
|
|
|
|
float alpha = smoothstep(
|
|
distanceOffset + aaDist,
|
|
distanceOffset - aaDist,
|
|
distance
|
|
);
|
|
#endif
|
|
|
|
return alpha;
|
|
}
|
|
`;
|
|
var FRAGMENT_TRANSFORM = `
|
|
float aaDist = troikaGetAADist();
|
|
float fragDistance = troikaGetFragDistValue();
|
|
float edgeAlpha = uTroikaSDFDebug ?
|
|
troikaGlyphUvToSdfValue(vTroikaGlyphUV) :
|
|
troikaGetEdgeAlpha(fragDistance, uTroikaEdgeOffset, max(aaDist, uTroikaBlurRadius));
|
|
|
|
#if !defined(IS_DEPTH_MATERIAL) && !defined(IS_DISTANCE_MATERIAL)
|
|
vec4 fillRGBA = gl_FragColor;
|
|
fillRGBA.a *= uTroikaFillOpacity;
|
|
vec4 strokeRGBA = uTroikaStrokeWidth == 0.0 ? fillRGBA : vec4(uTroikaStrokeColor, uTroikaStrokeOpacity);
|
|
if (fillRGBA.a == 0.0) fillRGBA.rgb = strokeRGBA.rgb;
|
|
gl_FragColor = mix(fillRGBA, strokeRGBA, smoothstep(
|
|
-uTroikaStrokeWidth - aaDist,
|
|
-uTroikaStrokeWidth + aaDist,
|
|
fragDistance
|
|
));
|
|
gl_FragColor.a *= edgeAlpha;
|
|
#endif
|
|
|
|
if (edgeAlpha == 0.0) {
|
|
discard;
|
|
}
|
|
`;
|
|
function createTextDerivedMaterial(baseMaterial) {
|
|
const textMaterial = createDerivedMaterial(baseMaterial, {
|
|
chained: true,
|
|
extensions: {
|
|
derivatives: true
|
|
},
|
|
uniforms: {
|
|
uTroikaSDFTexture: { value: null },
|
|
uTroikaSDFTextureSize: { value: new Vector2() },
|
|
uTroikaSDFGlyphSize: { value: 0 },
|
|
uTroikaSDFExponent: { value: 0 },
|
|
uTroikaTotalBounds: { value: new Vector4(0, 0, 0, 0) },
|
|
uTroikaClipRect: { value: new Vector4(0, 0, 0, 0) },
|
|
uTroikaEdgeOffset: { value: 0 },
|
|
uTroikaFillOpacity: { value: 1 },
|
|
uTroikaPositionOffset: { value: new Vector2() },
|
|
uTroikaCurveRadius: { value: 0 },
|
|
uTroikaBlurRadius: { value: 0 },
|
|
uTroikaStrokeWidth: { value: 0 },
|
|
uTroikaStrokeColor: { value: new Color() },
|
|
uTroikaStrokeOpacity: { value: 1 },
|
|
uTroikaOrient: { value: new Matrix3() },
|
|
uTroikaUseGlyphColors: { value: true },
|
|
uTroikaSDFDebug: { value: false }
|
|
},
|
|
vertexDefs: VERTEX_DEFS,
|
|
vertexTransform: VERTEX_TRANSFORM,
|
|
fragmentDefs: FRAGMENT_DEFS,
|
|
fragmentColorTransform: FRAGMENT_TRANSFORM,
|
|
customRewriter({ vertexShader: vertexShader3, fragmentShader: fragmentShader3 }) {
|
|
let uDiffuseRE = /\buniform\s+vec3\s+diffuse\b/;
|
|
if (uDiffuseRE.test(fragmentShader3)) {
|
|
fragmentShader3 = fragmentShader3.replace(uDiffuseRE, "varying vec3 vTroikaGlyphColor").replace(/\bdiffuse\b/g, "vTroikaGlyphColor");
|
|
if (!uDiffuseRE.test(vertexShader3)) {
|
|
vertexShader3 = vertexShader3.replace(
|
|
voidMainRegExp,
|
|
"uniform vec3 diffuse;\n$&\nvTroikaGlyphColor = uTroikaUseGlyphColors ? aTroikaGlyphColor / 255.0 : diffuse;\n"
|
|
);
|
|
}
|
|
}
|
|
return { vertexShader: vertexShader3, fragmentShader: fragmentShader3 };
|
|
}
|
|
});
|
|
textMaterial.transparent = true;
|
|
textMaterial.forceSinglePass = true;
|
|
Object.defineProperties(textMaterial, {
|
|
isTroikaTextMaterial: { value: true },
|
|
// WebGLShadowMap reverses the side of the shadow material by default, which fails
|
|
// for planes, so here we force the `shadowSide` to always match the main side.
|
|
shadowSide: {
|
|
get() {
|
|
return this.side;
|
|
},
|
|
set() {
|
|
}
|
|
}
|
|
});
|
|
return textMaterial;
|
|
}
|
|
var defaultMaterial = new MeshBasicMaterial({
|
|
color: 16777215,
|
|
side: DoubleSide,
|
|
transparent: true
|
|
});
|
|
var defaultStrokeColor = 8421504;
|
|
var tempMat4 = new Matrix4();
|
|
var tempVec3a = new Vector3();
|
|
var tempVec3b = new Vector3();
|
|
var tempArray = [];
|
|
var origin = new Vector3();
|
|
var defaultOrient = "+x+y";
|
|
function first(o2) {
|
|
return Array.isArray(o2) ? o2[0] : o2;
|
|
}
|
|
var getFlatRaycastMesh = () => {
|
|
const mesh = new Mesh(
|
|
new PlaneGeometry(1, 1),
|
|
defaultMaterial
|
|
);
|
|
getFlatRaycastMesh = () => mesh;
|
|
return mesh;
|
|
};
|
|
var getCurvedRaycastMesh = () => {
|
|
const mesh = new Mesh(
|
|
new PlaneGeometry(1, 1, 32, 1),
|
|
defaultMaterial
|
|
);
|
|
getCurvedRaycastMesh = () => mesh;
|
|
return mesh;
|
|
};
|
|
var syncStartEvent = { type: "syncstart" };
|
|
var syncCompleteEvent = { type: "synccomplete" };
|
|
var SYNCABLE_PROPS = [
|
|
"font",
|
|
"fontSize",
|
|
"fontStyle",
|
|
"fontWeight",
|
|
"lang",
|
|
"letterSpacing",
|
|
"lineHeight",
|
|
"maxWidth",
|
|
"overflowWrap",
|
|
"text",
|
|
"direction",
|
|
"textAlign",
|
|
"textIndent",
|
|
"whiteSpace",
|
|
"anchorX",
|
|
"anchorY",
|
|
"colorRanges",
|
|
"sdfGlyphSize"
|
|
];
|
|
var COPYABLE_PROPS = SYNCABLE_PROPS.concat(
|
|
"material",
|
|
"color",
|
|
"depthOffset",
|
|
"clipRect",
|
|
"curveRadius",
|
|
"orientation",
|
|
"glyphGeometryDetail"
|
|
);
|
|
var Text = class extends Mesh {
|
|
constructor() {
|
|
const geometry3 = new GlyphsGeometry();
|
|
super(geometry3, null);
|
|
this.text = "";
|
|
this.anchorX = 0;
|
|
this.anchorY = 0;
|
|
this.curveRadius = 0;
|
|
this.direction = "auto";
|
|
this.font = null;
|
|
this.unicodeFontsURL = null;
|
|
this.fontSize = 0.1;
|
|
this.fontWeight = "normal";
|
|
this.fontStyle = "normal";
|
|
this.lang = null;
|
|
this.letterSpacing = 0;
|
|
this.lineHeight = "normal";
|
|
this.maxWidth = Infinity;
|
|
this.overflowWrap = "normal";
|
|
this.textAlign = "left";
|
|
this.textIndent = 0;
|
|
this.whiteSpace = "normal";
|
|
this.material = null;
|
|
this.color = null;
|
|
this.colorRanges = null;
|
|
this.outlineWidth = 0;
|
|
this.outlineColor = 0;
|
|
this.outlineOpacity = 1;
|
|
this.outlineBlur = 0;
|
|
this.outlineOffsetX = 0;
|
|
this.outlineOffsetY = 0;
|
|
this.strokeWidth = 0;
|
|
this.strokeColor = defaultStrokeColor;
|
|
this.strokeOpacity = 1;
|
|
this.fillOpacity = 1;
|
|
this.depthOffset = 0;
|
|
this.clipRect = null;
|
|
this.orientation = defaultOrient;
|
|
this.glyphGeometryDetail = 1;
|
|
this.sdfGlyphSize = null;
|
|
this.gpuAccelerateSDF = true;
|
|
this.debugSDF = false;
|
|
}
|
|
/**
|
|
* Updates the text rendering according to the current text-related configuration properties.
|
|
* This is an async process, so you can pass in a callback function to be executed when it
|
|
* finishes.
|
|
* @param {function} [callback]
|
|
*/
|
|
sync(callback) {
|
|
if (this._needsSync) {
|
|
this._needsSync = false;
|
|
if (this._isSyncing) {
|
|
(this._queuedSyncs || (this._queuedSyncs = [])).push(callback);
|
|
} else {
|
|
this._isSyncing = true;
|
|
this.dispatchEvent(syncStartEvent);
|
|
getTextRenderInfo({
|
|
text: this.text,
|
|
font: this.font,
|
|
lang: this.lang,
|
|
fontSize: this.fontSize || 0.1,
|
|
fontWeight: this.fontWeight || "normal",
|
|
fontStyle: this.fontStyle || "normal",
|
|
letterSpacing: this.letterSpacing || 0,
|
|
lineHeight: this.lineHeight || "normal",
|
|
maxWidth: this.maxWidth,
|
|
direction: this.direction || "auto",
|
|
textAlign: this.textAlign,
|
|
textIndent: this.textIndent,
|
|
whiteSpace: this.whiteSpace,
|
|
overflowWrap: this.overflowWrap,
|
|
anchorX: this.anchorX,
|
|
anchorY: this.anchorY,
|
|
colorRanges: this.colorRanges,
|
|
includeCaretPositions: true,
|
|
//TODO parameterize
|
|
sdfGlyphSize: this.sdfGlyphSize,
|
|
gpuAccelerateSDF: this.gpuAccelerateSDF,
|
|
unicodeFontsURL: this.unicodeFontsURL
|
|
}, (textRenderInfo) => {
|
|
this._isSyncing = false;
|
|
this._textRenderInfo = textRenderInfo;
|
|
this.geometry.updateGlyphs(
|
|
textRenderInfo.glyphBounds,
|
|
textRenderInfo.glyphAtlasIndices,
|
|
textRenderInfo.blockBounds,
|
|
textRenderInfo.chunkedBounds,
|
|
textRenderInfo.glyphColors
|
|
);
|
|
const queued = this._queuedSyncs;
|
|
if (queued) {
|
|
this._queuedSyncs = null;
|
|
this._needsSync = true;
|
|
this.sync(() => {
|
|
queued.forEach((fn) => fn && fn());
|
|
});
|
|
}
|
|
this.dispatchEvent(syncCompleteEvent);
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Initiate a sync if needed - note it won't complete until next frame at the
|
|
* earliest so if possible it's a good idea to call sync() manually as soon as
|
|
* all the properties have been set.
|
|
* @override
|
|
*/
|
|
onBeforeRender(renderer, scene, camera, geometry3, material, group) {
|
|
this.sync();
|
|
if (material.isTroikaTextMaterial) {
|
|
this._prepareForRender(material);
|
|
}
|
|
}
|
|
/**
|
|
* Shortcut to dispose the geometry specific to this instance.
|
|
* Note: we don't also dispose the derived material here because if anything else is
|
|
* sharing the same base material it will result in a pause next frame as the program
|
|
* is recompiled. Instead users can dispose the base material manually, like normal,
|
|
* and we'll also dispose the derived material at that time.
|
|
*/
|
|
dispose() {
|
|
this.geometry.dispose();
|
|
}
|
|
/**
|
|
* @property {TroikaTextRenderInfo|null} textRenderInfo
|
|
* @readonly
|
|
* The current processed rendering data for this TextMesh, returned by the TextBuilder after
|
|
* a `sync()` call. This will be `null` initially, and may be stale for a short period until
|
|
* the asynchrous `sync()` process completes.
|
|
*/
|
|
get textRenderInfo() {
|
|
return this._textRenderInfo || null;
|
|
}
|
|
/**
|
|
* Create the text derived material from the base material. Can be overridden to use a custom
|
|
* derived material.
|
|
*/
|
|
createDerivedMaterial(baseMaterial) {
|
|
return createTextDerivedMaterial(baseMaterial);
|
|
}
|
|
// Handler for automatically wrapping the base material with our upgrades. We do the wrapping
|
|
// lazily on _read_ rather than write to avoid unnecessary wrapping on transient values.
|
|
get material() {
|
|
let derivedMaterial = this._derivedMaterial;
|
|
const baseMaterial = this._baseMaterial || this._defaultMaterial || (this._defaultMaterial = defaultMaterial.clone());
|
|
if (!derivedMaterial || !derivedMaterial.isDerivedFrom(baseMaterial)) {
|
|
derivedMaterial = this._derivedMaterial = this.createDerivedMaterial(baseMaterial);
|
|
baseMaterial.addEventListener("dispose", function onDispose() {
|
|
baseMaterial.removeEventListener("dispose", onDispose);
|
|
derivedMaterial.dispose();
|
|
});
|
|
}
|
|
if (this.hasOutline()) {
|
|
let outlineMaterial = derivedMaterial._outlineMtl;
|
|
if (!outlineMaterial) {
|
|
outlineMaterial = derivedMaterial._outlineMtl = Object.create(derivedMaterial, {
|
|
id: { value: derivedMaterial.id + 0.1 }
|
|
});
|
|
outlineMaterial.isTextOutlineMaterial = true;
|
|
outlineMaterial.depthWrite = false;
|
|
outlineMaterial.map = null;
|
|
derivedMaterial.addEventListener("dispose", function onDispose() {
|
|
derivedMaterial.removeEventListener("dispose", onDispose);
|
|
outlineMaterial.dispose();
|
|
});
|
|
}
|
|
return [
|
|
outlineMaterial,
|
|
derivedMaterial
|
|
];
|
|
} else {
|
|
return derivedMaterial;
|
|
}
|
|
}
|
|
set material(baseMaterial) {
|
|
if (baseMaterial && baseMaterial.isTroikaTextMaterial) {
|
|
this._derivedMaterial = baseMaterial;
|
|
this._baseMaterial = baseMaterial.baseMaterial;
|
|
} else {
|
|
this._baseMaterial = baseMaterial;
|
|
}
|
|
}
|
|
hasOutline() {
|
|
return !!(this.outlineWidth || this.outlineBlur || this.outlineOffsetX || this.outlineOffsetY);
|
|
}
|
|
get glyphGeometryDetail() {
|
|
return this.geometry.detail;
|
|
}
|
|
set glyphGeometryDetail(detail) {
|
|
this.geometry.detail = detail;
|
|
}
|
|
get curveRadius() {
|
|
return this.geometry.curveRadius;
|
|
}
|
|
set curveRadius(r2) {
|
|
this.geometry.curveRadius = r2;
|
|
}
|
|
// Create and update material for shadows upon request:
|
|
get customDepthMaterial() {
|
|
return first(this.material).getDepthMaterial();
|
|
}
|
|
set customDepthMaterial(m) {
|
|
}
|
|
get customDistanceMaterial() {
|
|
return first(this.material).getDistanceMaterial();
|
|
}
|
|
set customDistanceMaterial(m) {
|
|
}
|
|
_prepareForRender(material) {
|
|
const isOutline = material.isTextOutlineMaterial;
|
|
const uniforms = material.uniforms;
|
|
const textInfo = this.textRenderInfo;
|
|
if (textInfo) {
|
|
const { sdfTexture, blockBounds } = textInfo;
|
|
uniforms.uTroikaSDFTexture.value = sdfTexture;
|
|
uniforms.uTroikaSDFTextureSize.value.set(sdfTexture.image.width, sdfTexture.image.height);
|
|
uniforms.uTroikaSDFGlyphSize.value = textInfo.sdfGlyphSize;
|
|
uniforms.uTroikaSDFExponent.value = textInfo.sdfExponent;
|
|
uniforms.uTroikaTotalBounds.value.fromArray(blockBounds);
|
|
uniforms.uTroikaUseGlyphColors.value = !isOutline && !!textInfo.glyphColors;
|
|
let distanceOffset = 0;
|
|
let blurRadius = 0;
|
|
let strokeWidth = 0;
|
|
let fillOpacity;
|
|
let strokeOpacity;
|
|
let strokeColor;
|
|
let offsetX = 0;
|
|
let offsetY = 0;
|
|
if (isOutline) {
|
|
let { outlineWidth, outlineOffsetX, outlineOffsetY, outlineBlur, outlineOpacity } = this;
|
|
distanceOffset = this._parsePercent(outlineWidth) || 0;
|
|
blurRadius = Math.max(0, this._parsePercent(outlineBlur) || 0);
|
|
fillOpacity = outlineOpacity;
|
|
offsetX = this._parsePercent(outlineOffsetX) || 0;
|
|
offsetY = this._parsePercent(outlineOffsetY) || 0;
|
|
} else {
|
|
strokeWidth = Math.max(0, this._parsePercent(this.strokeWidth) || 0);
|
|
if (strokeWidth) {
|
|
strokeColor = this.strokeColor;
|
|
uniforms.uTroikaStrokeColor.value.set(strokeColor == null ? defaultStrokeColor : strokeColor);
|
|
strokeOpacity = this.strokeOpacity;
|
|
if (strokeOpacity == null) strokeOpacity = 1;
|
|
}
|
|
fillOpacity = this.fillOpacity;
|
|
}
|
|
uniforms.uTroikaEdgeOffset.value = distanceOffset;
|
|
uniforms.uTroikaPositionOffset.value.set(offsetX, offsetY);
|
|
uniforms.uTroikaBlurRadius.value = blurRadius;
|
|
uniforms.uTroikaStrokeWidth.value = strokeWidth;
|
|
uniforms.uTroikaStrokeOpacity.value = strokeOpacity;
|
|
uniforms.uTroikaFillOpacity.value = fillOpacity == null ? 1 : fillOpacity;
|
|
uniforms.uTroikaCurveRadius.value = this.curveRadius || 0;
|
|
let clipRect = this.clipRect;
|
|
if (clipRect && Array.isArray(clipRect) && clipRect.length === 4) {
|
|
uniforms.uTroikaClipRect.value.fromArray(clipRect);
|
|
} else {
|
|
const pad = (this.fontSize || 0.1) * 100;
|
|
uniforms.uTroikaClipRect.value.set(
|
|
blockBounds[0] - pad,
|
|
blockBounds[1] - pad,
|
|
blockBounds[2] + pad,
|
|
blockBounds[3] + pad
|
|
);
|
|
}
|
|
this.geometry.applyClipRect(uniforms.uTroikaClipRect.value);
|
|
}
|
|
uniforms.uTroikaSDFDebug.value = !!this.debugSDF;
|
|
material.polygonOffset = !!this.depthOffset;
|
|
material.polygonOffsetFactor = material.polygonOffsetUnits = this.depthOffset || 0;
|
|
const color = isOutline ? this.outlineColor || 0 : this.color;
|
|
if (color == null) {
|
|
delete material.color;
|
|
} else {
|
|
const colorObj = material.hasOwnProperty("color") ? material.color : material.color = new Color();
|
|
if (color !== colorObj._input || typeof color === "object") {
|
|
colorObj.set(colorObj._input = color);
|
|
}
|
|
}
|
|
let orient = this.orientation || defaultOrient;
|
|
if (orient !== material._orientation) {
|
|
let rotMat = uniforms.uTroikaOrient.value;
|
|
orient = orient.replace(/[^-+xyz]/g, "");
|
|
let match = orient !== defaultOrient && orient.match(/^([-+])([xyz])([-+])([xyz])$/);
|
|
if (match) {
|
|
let [, hSign, hAxis, vSign, vAxis] = match;
|
|
tempVec3a.set(0, 0, 0)[hAxis] = hSign === "-" ? 1 : -1;
|
|
tempVec3b.set(0, 0, 0)[vAxis] = vSign === "-" ? -1 : 1;
|
|
tempMat4.lookAt(origin, tempVec3a.cross(tempVec3b), tempVec3b);
|
|
rotMat.setFromMatrix4(tempMat4);
|
|
} else {
|
|
rotMat.identity();
|
|
}
|
|
material._orientation = orient;
|
|
}
|
|
}
|
|
_parsePercent(value) {
|
|
if (typeof value === "string") {
|
|
let match = value.match(/^(-?[\d.]+)%$/);
|
|
let pct = match ? parseFloat(match[1]) : NaN;
|
|
value = (isNaN(pct) ? 0 : pct / 100) * this.fontSize;
|
|
}
|
|
return value;
|
|
}
|
|
/**
|
|
* Translate a point in local space to an x/y in the text plane.
|
|
*/
|
|
localPositionToTextCoords(position2, target2 = new Vector2()) {
|
|
target2.copy(position2);
|
|
const r2 = this.curveRadius;
|
|
if (r2) {
|
|
target2.x = Math.atan2(position2.x, Math.abs(r2) - Math.abs(position2.z)) * Math.abs(r2);
|
|
}
|
|
return target2;
|
|
}
|
|
/**
|
|
* Translate a point in world space to an x/y in the text plane.
|
|
*/
|
|
worldPositionToTextCoords(position2, target2 = new Vector2()) {
|
|
tempVec3a.copy(position2);
|
|
return this.localPositionToTextCoords(this.worldToLocal(tempVec3a), target2);
|
|
}
|
|
/**
|
|
* @override Custom raycasting to test against the whole text block's max rectangular bounds
|
|
* TODO is there any reason to make this more granular, like within individual line or glyph rects?
|
|
*/
|
|
raycast(raycaster, intersects) {
|
|
const { textRenderInfo, curveRadius } = this;
|
|
if (textRenderInfo) {
|
|
const bounds = textRenderInfo.blockBounds;
|
|
const raycastMesh = curveRadius ? getCurvedRaycastMesh() : getFlatRaycastMesh();
|
|
const geom = raycastMesh.geometry;
|
|
const { position: position2, uv } = geom.attributes;
|
|
for (let i3 = 0; i3 < uv.count; i3++) {
|
|
let x = bounds[0] + uv.getX(i3) * (bounds[2] - bounds[0]);
|
|
const y = bounds[1] + uv.getY(i3) * (bounds[3] - bounds[1]);
|
|
let z = 0;
|
|
if (curveRadius) {
|
|
z = curveRadius - Math.cos(x / curveRadius) * curveRadius;
|
|
x = Math.sin(x / curveRadius) * curveRadius;
|
|
}
|
|
position2.setXYZ(i3, x, y, z);
|
|
}
|
|
geom.boundingSphere = this.geometry.boundingSphere;
|
|
geom.boundingBox = this.geometry.boundingBox;
|
|
raycastMesh.matrixWorld = this.matrixWorld;
|
|
raycastMesh.material.side = this.material.side;
|
|
tempArray.length = 0;
|
|
raycastMesh.raycast(raycaster, tempArray);
|
|
for (let i3 = 0; i3 < tempArray.length; i3++) {
|
|
tempArray[i3].object = this;
|
|
intersects.push(tempArray[i3]);
|
|
}
|
|
}
|
|
}
|
|
copy(source) {
|
|
const geom = this.geometry;
|
|
super.copy(source);
|
|
this.geometry = geom;
|
|
COPYABLE_PROPS.forEach((prop) => {
|
|
this[prop] = source[prop];
|
|
});
|
|
return this;
|
|
}
|
|
clone() {
|
|
return new this.constructor().copy(this);
|
|
}
|
|
};
|
|
SYNCABLE_PROPS.forEach((prop) => {
|
|
const privateKey = "_private_" + prop;
|
|
Object.defineProperty(Text.prototype, prop, {
|
|
get() {
|
|
return this[privateKey];
|
|
},
|
|
set(value) {
|
|
if (value !== this[privateKey]) {
|
|
this[privateKey] = value;
|
|
this._needsSync = true;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
var tempBox3 = new Box3();
|
|
var tempColor$1 = new Color();
|
|
|
|
// node_modules/@react-three/drei/core/Text.js
|
|
var Text2 = React21.forwardRef(({
|
|
sdfGlyphSize = 64,
|
|
anchorX = "center",
|
|
anchorY = "middle",
|
|
font,
|
|
fontSize = 1,
|
|
children,
|
|
characters,
|
|
onSync,
|
|
...props
|
|
}, ref) => {
|
|
const invalidate = useThree(({
|
|
invalidate: invalidate2
|
|
}) => invalidate2);
|
|
const [troikaMesh] = React21.useState(() => new Text());
|
|
const [nodes, text] = React21.useMemo(() => {
|
|
const n2 = [];
|
|
let t2 = "";
|
|
React21.Children.forEach(children, (child) => {
|
|
if (typeof child === "string" || typeof child === "number") {
|
|
t2 += child;
|
|
} else {
|
|
n2.push(child);
|
|
}
|
|
});
|
|
return [n2, t2];
|
|
}, [children]);
|
|
suspend(() => new Promise((res) => preloadFont({
|
|
font,
|
|
characters
|
|
}, res)), ["troika-text", font, characters]);
|
|
React21.useLayoutEffect(() => void troikaMesh.sync(() => {
|
|
invalidate();
|
|
if (onSync) onSync(troikaMesh);
|
|
}));
|
|
React21.useEffect(() => {
|
|
return () => troikaMesh.dispose();
|
|
}, [troikaMesh]);
|
|
return React21.createElement("primitive", _extends({
|
|
object: troikaMesh,
|
|
ref,
|
|
font,
|
|
text,
|
|
anchorX,
|
|
anchorY,
|
|
fontSize,
|
|
sdfGlyphSize
|
|
}, props), nodes);
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Text3D.js
|
|
var React22 = __toESM(require_react());
|
|
var import_react6 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/core/useFont.js
|
|
var fontLoader = null;
|
|
async function loadFontData(font) {
|
|
return typeof font === "string" ? await (await fetch(font)).json() : font;
|
|
}
|
|
function parseFontData(fontData) {
|
|
if (!fontLoader) {
|
|
fontLoader = new FontLoader();
|
|
}
|
|
return fontLoader.parse(fontData);
|
|
}
|
|
async function loader(font) {
|
|
const data = await loadFontData(font);
|
|
return parseFontData(data);
|
|
}
|
|
function useFont(font) {
|
|
return suspend(loader, [font]);
|
|
}
|
|
useFont.preload = (font) => preload(loader, [font]);
|
|
useFont.clear = (font) => clear([font]);
|
|
|
|
// node_modules/@react-three/drei/core/Text3D.js
|
|
var types = ["string", "number"];
|
|
var getTextFromChildren = (children) => {
|
|
let label = "";
|
|
const rest = [];
|
|
React22.Children.forEach(children, (child) => {
|
|
if (types.includes(typeof child)) label += child + "";
|
|
else rest.push(child);
|
|
});
|
|
return [label, ...rest];
|
|
};
|
|
var Text3D = React22.forwardRef(({
|
|
font: _font,
|
|
letterSpacing = 0,
|
|
lineHeight = 1,
|
|
size = 1,
|
|
height = 0.2,
|
|
bevelThickness = 0.1,
|
|
bevelSize = 0.01,
|
|
bevelEnabled = false,
|
|
bevelOffset = 0,
|
|
bevelSegments = 4,
|
|
curveSegments = 8,
|
|
smooth,
|
|
children,
|
|
...props
|
|
}, fref) => {
|
|
React22.useMemo(() => extend({
|
|
RenamedTextGeometry: TextGeometry
|
|
}), []);
|
|
const ref = React22.useRef(null);
|
|
const font = useFont(_font);
|
|
const opts = (0, import_react6.useMemo)(() => {
|
|
return {
|
|
font,
|
|
size,
|
|
height,
|
|
bevelThickness,
|
|
bevelSize,
|
|
bevelEnabled,
|
|
bevelSegments,
|
|
bevelOffset,
|
|
curveSegments,
|
|
letterSpacing,
|
|
lineHeight
|
|
};
|
|
}, [font, size, height, bevelThickness, bevelSize, bevelEnabled, bevelSegments, bevelOffset, curveSegments, letterSpacing, lineHeight]);
|
|
const [label, ...rest] = (0, import_react6.useMemo)(() => getTextFromChildren(children), [children]);
|
|
const args = React22.useMemo(() => [label, opts], [label, opts]);
|
|
React22.useLayoutEffect(() => {
|
|
if (smooth) {
|
|
ref.current.geometry = mergeVertices(ref.current.geometry, smooth);
|
|
ref.current.geometry.computeVertexNormals();
|
|
}
|
|
}, [args, smooth]);
|
|
React22.useImperativeHandle(fref, () => ref.current, []);
|
|
return React22.createElement("mesh", _extends({}, props, {
|
|
ref
|
|
}), React22.createElement("renamedTextGeometry", {
|
|
args
|
|
}), rest);
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Effects.js
|
|
var React23 = __toESM(require_react());
|
|
var isWebGL2Available = () => {
|
|
try {
|
|
var canvas = document.createElement("canvas");
|
|
return !!(window.WebGL2RenderingContext && canvas.getContext("webgl2"));
|
|
} catch (e2) {
|
|
return false;
|
|
}
|
|
};
|
|
var Effects = React23.forwardRef(({
|
|
children,
|
|
multisamping = 8,
|
|
renderIndex = 1,
|
|
disableRender,
|
|
disableGamma,
|
|
disableRenderPass,
|
|
depthBuffer = true,
|
|
stencilBuffer = false,
|
|
anisotropy = 1,
|
|
colorSpace,
|
|
type,
|
|
...props
|
|
}, ref) => {
|
|
React23.useMemo(() => extend({
|
|
EffectComposer,
|
|
RenderPass,
|
|
ShaderPass
|
|
}), []);
|
|
const composer = React23.useRef(null);
|
|
React23.useImperativeHandle(ref, () => composer.current, []);
|
|
const {
|
|
scene,
|
|
camera,
|
|
gl,
|
|
size,
|
|
viewport
|
|
} = useThree();
|
|
const [target2] = React23.useState(() => {
|
|
const t2 = new WebGLRenderTarget(size.width, size.height, {
|
|
type: type || HalfFloatType,
|
|
format: RGBAFormat,
|
|
depthBuffer,
|
|
stencilBuffer,
|
|
anisotropy
|
|
});
|
|
if (type === UnsignedByteType && colorSpace != null) {
|
|
t2.texture.colorSpace = colorSpace;
|
|
}
|
|
t2.samples = multisamping;
|
|
return t2;
|
|
});
|
|
React23.useEffect(() => {
|
|
var _composer$current, _composer$current2;
|
|
(_composer$current = composer.current) == null || _composer$current.setSize(size.width, size.height);
|
|
(_composer$current2 = composer.current) == null || _composer$current2.setPixelRatio(viewport.dpr);
|
|
}, [gl, size, viewport.dpr]);
|
|
useFrame(() => {
|
|
var _composer$current3;
|
|
if (!disableRender) (_composer$current3 = composer.current) == null || _composer$current3.render();
|
|
}, renderIndex);
|
|
const passes = [];
|
|
if (!disableRenderPass) passes.push(React23.createElement("renderPass", {
|
|
key: "renderpass",
|
|
attach: `passes-${passes.length}`,
|
|
args: [scene, camera]
|
|
}));
|
|
if (!disableGamma) passes.push(React23.createElement("shaderPass", {
|
|
attach: `passes-${passes.length}`,
|
|
key: "gammapass",
|
|
args: [GammaCorrectionShader]
|
|
}));
|
|
React23.Children.forEach(children, (el) => {
|
|
el && passes.push(React23.cloneElement(el, {
|
|
key: passes.length,
|
|
attach: `passes-${passes.length}`
|
|
}));
|
|
});
|
|
return React23.createElement("effectComposer", _extends({
|
|
ref: composer,
|
|
args: [gl, target2]
|
|
}, props), passes);
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/GradientTexture.js
|
|
var React24 = __toESM(require_react());
|
|
var GradientType = (function(GradientType2) {
|
|
GradientType2["Linear"] = "linear";
|
|
GradientType2["Radial"] = "radial";
|
|
return GradientType2;
|
|
})({});
|
|
function GradientTexture({
|
|
stops,
|
|
colors: colors2,
|
|
size = 1024,
|
|
width = 16,
|
|
type = GradientType.Linear,
|
|
innerCircleRadius = 0,
|
|
outerCircleRadius = "auto",
|
|
...props
|
|
}) {
|
|
const gl = useThree((state) => state.gl);
|
|
const canvas = React24.useMemo(() => {
|
|
const canvas2 = document.createElement("canvas");
|
|
const context12 = canvas2.getContext("2d");
|
|
canvas2.width = width;
|
|
canvas2.height = size;
|
|
let gradient;
|
|
if (type === GradientType.Linear) {
|
|
gradient = context12.createLinearGradient(0, 0, 0, size);
|
|
} else {
|
|
const canvasCenterX = canvas2.width / 2;
|
|
const canvasCenterY = canvas2.height / 2;
|
|
const radius = outerCircleRadius !== "auto" ? Math.abs(Number(outerCircleRadius)) : Math.sqrt(canvasCenterX ** 2 + canvasCenterY ** 2);
|
|
gradient = context12.createRadialGradient(canvasCenterX, canvasCenterY, Math.abs(innerCircleRadius), canvasCenterX, canvasCenterY, radius);
|
|
}
|
|
const tempColor2 = new Color();
|
|
let i3 = stops.length;
|
|
while (i3--) {
|
|
gradient.addColorStop(stops[i3], tempColor2.set(colors2[i3]).getStyle());
|
|
}
|
|
context12.save();
|
|
context12.fillStyle = gradient;
|
|
context12.fillRect(0, 0, width, size);
|
|
context12.restore();
|
|
return canvas2;
|
|
}, [stops]);
|
|
return React24.createElement("canvasTexture", _extends({
|
|
colorSpace: gl.outputColorSpace,
|
|
args: [canvas],
|
|
attach: "map"
|
|
}, props));
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/Image.js
|
|
var React26 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/core/shaderMaterial.js
|
|
function shaderMaterial(uniforms, vertexShader3, fragmentShader3, onInit) {
|
|
var _Class;
|
|
return _Class = class extends ShaderMaterial {
|
|
constructor(parameters) {
|
|
super({
|
|
vertexShader: vertexShader3,
|
|
fragmentShader: fragmentShader3,
|
|
...parameters
|
|
});
|
|
for (const key in uniforms) {
|
|
this.uniforms[key] = new Uniform(uniforms[key]);
|
|
Object.defineProperty(this, key, {
|
|
get() {
|
|
return this.uniforms[key].value;
|
|
},
|
|
set(value) {
|
|
this.uniforms[key].value = value;
|
|
}
|
|
});
|
|
}
|
|
this.uniforms = UniformsUtils.clone(this.uniforms);
|
|
onInit == null || onInit(this);
|
|
}
|
|
}, _Class.key = MathUtils.generateUUID(), _Class;
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/Texture.js
|
|
var React25 = __toESM(require_react());
|
|
var import_react7 = __toESM(require_react());
|
|
var IsObject = (url) => url === Object(url) && !Array.isArray(url) && typeof url !== "function";
|
|
function useTexture(input, onLoad) {
|
|
const gl = useThree((state) => state.gl);
|
|
const textures = useLoader(TextureLoader, IsObject(input) ? Object.values(input) : input);
|
|
(0, import_react7.useLayoutEffect)(() => {
|
|
onLoad == null || onLoad(textures);
|
|
}, [onLoad]);
|
|
(0, import_react7.useEffect)(() => {
|
|
if ("initTexture" in gl) {
|
|
let textureArray = [];
|
|
if (Array.isArray(textures)) {
|
|
textureArray = textures;
|
|
} else if (textures instanceof Texture) {
|
|
textureArray = [textures];
|
|
} else if (IsObject(textures)) {
|
|
textureArray = Object.values(textures);
|
|
}
|
|
textureArray.forEach((texture) => {
|
|
if (texture instanceof Texture) {
|
|
gl.initTexture(texture);
|
|
}
|
|
});
|
|
}
|
|
}, [gl, textures]);
|
|
const mappedTextures = (0, import_react7.useMemo)(() => {
|
|
if (IsObject(input)) {
|
|
const keyed = {};
|
|
let i3 = 0;
|
|
for (const key in input) keyed[key] = textures[i3++];
|
|
return keyed;
|
|
} else {
|
|
return textures;
|
|
}
|
|
}, [input, textures]);
|
|
return mappedTextures;
|
|
}
|
|
useTexture.preload = (url) => useLoader.preload(TextureLoader, url);
|
|
useTexture.clear = (input) => useLoader.clear(TextureLoader, input);
|
|
var Texture2 = ({
|
|
children,
|
|
input,
|
|
onLoad
|
|
}) => {
|
|
const ret = useTexture(input, onLoad);
|
|
return React25.createElement(React25.Fragment, null, children == null ? void 0 : children(ret));
|
|
};
|
|
|
|
// node_modules/@react-three/drei/helpers/constants.js
|
|
var getVersion = () => parseInt(REVISION.replace(/\D+/g, ""));
|
|
var version = getVersion();
|
|
|
|
// node_modules/@react-three/drei/core/Image.js
|
|
var ImageMaterialImpl = shaderMaterial(
|
|
{
|
|
color: new Color("white"),
|
|
scale: new Vector2(1, 1),
|
|
imageBounds: new Vector2(1, 1),
|
|
resolution: 1024,
|
|
map: null,
|
|
zoom: 1,
|
|
radius: 0,
|
|
grayscale: 0,
|
|
opacity: 1
|
|
},
|
|
/* glsl */
|
|
`
|
|
varying vec2 vUv;
|
|
varying vec2 vPos;
|
|
void main() {
|
|
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.);
|
|
vUv = uv;
|
|
vPos = position.xy;
|
|
}
|
|
`,
|
|
/* glsl */
|
|
`
|
|
// mostly from https://gist.github.com/statico/df64c5d167362ecf7b34fca0b1459a44
|
|
varying vec2 vUv;
|
|
varying vec2 vPos;
|
|
uniform vec2 scale;
|
|
uniform vec2 imageBounds;
|
|
uniform float resolution;
|
|
uniform vec3 color;
|
|
uniform sampler2D map;
|
|
uniform float radius;
|
|
uniform float zoom;
|
|
uniform float grayscale;
|
|
uniform float opacity;
|
|
const vec3 luma = vec3(.299, 0.587, 0.114);
|
|
vec4 toGrayscale(vec4 color, float intensity) {
|
|
return vec4(mix(color.rgb, vec3(dot(color.rgb, luma)), intensity), color.a);
|
|
}
|
|
vec2 aspect(vec2 size) {
|
|
return size / min(size.x, size.y);
|
|
}
|
|
|
|
const float PI = 3.14159265;
|
|
|
|
// from https://iquilezles.org/articles/distfunctions
|
|
float udRoundBox( vec2 p, vec2 b, float r ) {
|
|
return length(max(abs(p)-b+r,0.0))-r;
|
|
}
|
|
|
|
void main() {
|
|
vec2 s = aspect(scale);
|
|
vec2 i = aspect(imageBounds);
|
|
float rs = s.x / s.y;
|
|
float ri = i.x / i.y;
|
|
vec2 new = rs < ri ? vec2(i.x * s.y / i.y, s.y) : vec2(s.x, i.y * s.x / i.x);
|
|
vec2 offset = (rs < ri ? vec2((new.x - s.x) / 2.0, 0.0) : vec2(0.0, (new.y - s.y) / 2.0)) / new;
|
|
vec2 uv = vUv * s / new + offset;
|
|
vec2 zUv = (uv - vec2(0.5, 0.5)) / zoom + vec2(0.5, 0.5);
|
|
|
|
vec2 res = vec2(scale * resolution);
|
|
vec2 halfRes = 0.5 * res;
|
|
float b = udRoundBox(vUv.xy * res - halfRes, halfRes, resolution * radius);
|
|
vec3 a = mix(vec3(1.0,0.0,0.0), vec3(0.0,0.0,0.0), smoothstep(0.0, 1.0, b));
|
|
gl_FragColor = toGrayscale(texture2D(map, zUv) * vec4(color, opacity * a), grayscale);
|
|
|
|
#include <tonemapping_fragment>
|
|
#include <${version >= 154 ? "colorspace_fragment" : "encodings_fragment"}>
|
|
}
|
|
`
|
|
);
|
|
var ImageBase = React26.forwardRef(({
|
|
children,
|
|
color,
|
|
segments = 1,
|
|
scale: scale5 = 1,
|
|
zoom = 1,
|
|
grayscale = 0,
|
|
opacity = 1,
|
|
radius = 0,
|
|
texture,
|
|
toneMapped,
|
|
transparent,
|
|
side,
|
|
...props
|
|
}, fref) => {
|
|
extend({
|
|
ImageMaterial: ImageMaterialImpl
|
|
});
|
|
const ref = React26.useRef(null);
|
|
const size = useThree((state) => state.size);
|
|
const planeBounds = Array.isArray(scale5) ? [scale5[0], scale5[1]] : [scale5, scale5];
|
|
const imageBounds = [texture.image.width, texture.image.height];
|
|
const resolution = Math.max(size.width, size.height);
|
|
React26.useImperativeHandle(fref, () => ref.current, []);
|
|
React26.useLayoutEffect(() => {
|
|
if (ref.current.geometry.parameters) {
|
|
ref.current.material.scale.set(
|
|
// @ts-ignore
|
|
planeBounds[0] * ref.current.geometry.parameters.width,
|
|
// @ts-ignore
|
|
planeBounds[1] * ref.current.geometry.parameters.height
|
|
);
|
|
}
|
|
}, [planeBounds[0], planeBounds[1]]);
|
|
return React26.createElement("mesh", _extends({
|
|
ref,
|
|
scale: Array.isArray(scale5) ? [...scale5, 1] : scale5
|
|
}, props), React26.createElement("planeGeometry", {
|
|
args: [1, 1, segments, segments]
|
|
}), React26.createElement("imageMaterial", {
|
|
color,
|
|
map: texture,
|
|
zoom,
|
|
grayscale,
|
|
opacity,
|
|
scale: planeBounds,
|
|
imageBounds,
|
|
resolution,
|
|
radius,
|
|
toneMapped,
|
|
transparent,
|
|
side,
|
|
key: ImageMaterialImpl.key
|
|
}), children);
|
|
});
|
|
var ImageWithUrl = React26.forwardRef(({
|
|
url,
|
|
...props
|
|
}, ref) => {
|
|
const texture = useTexture(url);
|
|
return React26.createElement(ImageBase, _extends({}, props, {
|
|
texture,
|
|
ref
|
|
}));
|
|
});
|
|
var ImageWithTexture = React26.forwardRef(({
|
|
url: _url,
|
|
...props
|
|
}, ref) => {
|
|
return React26.createElement(ImageBase, _extends({}, props, {
|
|
ref
|
|
}));
|
|
});
|
|
var Image = React26.forwardRef((props, ref) => {
|
|
if (props.url) return React26.createElement(ImageWithUrl, _extends({}, props, {
|
|
ref
|
|
}));
|
|
else if (props.texture) return React26.createElement(ImageWithTexture, _extends({}, props, {
|
|
ref
|
|
}));
|
|
else throw new Error("<Image /> requires a url or texture");
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Edges.js
|
|
var React27 = __toESM(require_react());
|
|
var Edges = React27.forwardRef(({
|
|
threshold = 15,
|
|
geometry: explicitGeometry,
|
|
...props
|
|
}, fref) => {
|
|
const ref = React27.useRef(null);
|
|
React27.useImperativeHandle(fref, () => ref.current, []);
|
|
const tmpPoints = React27.useMemo(() => [0, 0, 0, 1, 0, 0], []);
|
|
const memoizedGeometry = React27.useRef(null);
|
|
const memoizedThreshold = React27.useRef(null);
|
|
React27.useLayoutEffect(() => {
|
|
const parent = ref.current.parent;
|
|
const geometry3 = explicitGeometry !== null && explicitGeometry !== void 0 ? explicitGeometry : parent == null ? void 0 : parent.geometry;
|
|
if (!geometry3) return;
|
|
const cached = memoizedGeometry.current === geometry3 && memoizedThreshold.current === threshold;
|
|
if (cached) return;
|
|
memoizedGeometry.current = geometry3;
|
|
memoizedThreshold.current = threshold;
|
|
const points = new EdgesGeometry(geometry3, threshold).attributes.position.array;
|
|
ref.current.geometry.setPositions(points);
|
|
ref.current.geometry.attributes.instanceStart.needsUpdate = true;
|
|
ref.current.geometry.attributes.instanceEnd.needsUpdate = true;
|
|
ref.current.computeLineDistances();
|
|
});
|
|
return React27.createElement(Line, _extends({
|
|
segments: true,
|
|
points: tmpPoints,
|
|
ref,
|
|
raycast: () => null
|
|
}, props));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Outlines.js
|
|
var React28 = __toESM(require_react());
|
|
var OutlinesMaterial = shaderMaterial({
|
|
screenspace: false,
|
|
color: new Color("black"),
|
|
opacity: 1,
|
|
thickness: 0.05,
|
|
size: new Vector2()
|
|
}, `#include <common>
|
|
#include <morphtarget_pars_vertex>
|
|
#include <skinning_pars_vertex>
|
|
#include <clipping_planes_pars_vertex>
|
|
uniform float thickness;
|
|
uniform bool screenspace;
|
|
uniform vec2 size;
|
|
void main() {
|
|
#if defined (USE_SKINNING)
|
|
#include <beginnormal_vertex>
|
|
#include <morphnormal_vertex>
|
|
#include <skinbase_vertex>
|
|
#include <skinnormal_vertex>
|
|
#include <defaultnormal_vertex>
|
|
#endif
|
|
#include <begin_vertex>
|
|
#include <morphtarget_vertex>
|
|
#include <skinning_vertex>
|
|
#include <project_vertex>
|
|
#include <clipping_planes_vertex>
|
|
vec4 tNormal = vec4(normal, 0.0);
|
|
vec4 tPosition = vec4(transformed, 1.0);
|
|
#ifdef USE_INSTANCING
|
|
tNormal = instanceMatrix * tNormal;
|
|
tPosition = instanceMatrix * tPosition;
|
|
#endif
|
|
if (screenspace) {
|
|
vec3 newPosition = tPosition.xyz + tNormal.xyz * thickness;
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
|
|
} else {
|
|
vec4 clipPosition = projectionMatrix * modelViewMatrix * tPosition;
|
|
vec4 clipNormal = projectionMatrix * modelViewMatrix * tNormal;
|
|
vec2 offset = normalize(clipNormal.xy) * thickness / size * clipPosition.w * 2.0;
|
|
clipPosition.xy += offset;
|
|
gl_Position = clipPosition;
|
|
}
|
|
}`, `uniform vec3 color;
|
|
uniform float opacity;
|
|
#include <clipping_planes_pars_fragment>
|
|
void main(){
|
|
#include <clipping_planes_fragment>
|
|
gl_FragColor = vec4(color, opacity);
|
|
#include <tonemapping_fragment>
|
|
#include <${version >= 154 ? "colorspace_fragment" : "encodings_fragment"}>
|
|
}`);
|
|
function Outlines({
|
|
color = "black",
|
|
opacity = 1,
|
|
transparent = false,
|
|
screenspace = false,
|
|
toneMapped = true,
|
|
polygonOffset = false,
|
|
polygonOffsetFactor = 0,
|
|
renderOrder = 0,
|
|
thickness = 0.05,
|
|
angle = Math.PI,
|
|
clippingPlanes,
|
|
...props
|
|
}) {
|
|
const ref = React28.useRef(null);
|
|
const [material] = React28.useState(() => new OutlinesMaterial({
|
|
side: BackSide
|
|
}));
|
|
const {
|
|
gl
|
|
} = useThree();
|
|
const contextSize = gl.getDrawingBufferSize(new Vector2());
|
|
React28.useMemo(() => extend({
|
|
OutlinesMaterial
|
|
}), []);
|
|
const oldAngle = React28.useRef(0);
|
|
const oldGeometry = React28.useRef(null);
|
|
React28.useLayoutEffect(() => {
|
|
const group = ref.current;
|
|
if (!group) return;
|
|
const parent = group.parent;
|
|
if (parent && parent.geometry) {
|
|
if (oldAngle.current !== angle || oldGeometry.current !== parent.geometry) {
|
|
var _group$children;
|
|
oldAngle.current = angle;
|
|
oldGeometry.current = parent.geometry;
|
|
let mesh = (_group$children = group.children) == null ? void 0 : _group$children[0];
|
|
if (mesh) {
|
|
if (angle) mesh.geometry.dispose();
|
|
group.remove(mesh);
|
|
}
|
|
if (parent.skeleton) {
|
|
mesh = new SkinnedMesh();
|
|
mesh.material = material;
|
|
mesh.bind(parent.skeleton, parent.bindMatrix);
|
|
group.add(mesh);
|
|
} else if (parent.isInstancedMesh) {
|
|
mesh = new InstancedMesh(parent.geometry, material, parent.count);
|
|
mesh.instanceMatrix = parent.instanceMatrix;
|
|
group.add(mesh);
|
|
} else {
|
|
mesh = new Mesh();
|
|
mesh.material = material;
|
|
group.add(mesh);
|
|
}
|
|
mesh.geometry = angle ? toCreasedNormals(parent.geometry, angle) : parent.geometry;
|
|
mesh.morphTargetInfluences = parent.morphTargetInfluences;
|
|
mesh.morphTargetDictionary = parent.morphTargetDictionary;
|
|
}
|
|
}
|
|
});
|
|
React28.useLayoutEffect(() => {
|
|
const group = ref.current;
|
|
if (!group) return;
|
|
const mesh = group.children[0];
|
|
if (mesh) {
|
|
mesh.renderOrder = renderOrder;
|
|
const parent = group.parent;
|
|
applyProps(mesh, {
|
|
morphTargetInfluences: parent.morphTargetInfluences,
|
|
morphTargetDictionary: parent.morphTargetDictionary
|
|
});
|
|
applyProps(mesh.material, {
|
|
transparent,
|
|
thickness,
|
|
color,
|
|
opacity,
|
|
size: contextSize,
|
|
screenspace,
|
|
toneMapped,
|
|
polygonOffset,
|
|
polygonOffsetFactor,
|
|
clippingPlanes,
|
|
clipping: clippingPlanes && clippingPlanes.length > 0
|
|
});
|
|
}
|
|
});
|
|
React28.useEffect(() => {
|
|
return () => {
|
|
const group = ref.current;
|
|
if (!group) return;
|
|
const mesh = group.children[0];
|
|
if (mesh) {
|
|
if (angle) mesh.geometry.dispose();
|
|
group.remove(mesh);
|
|
}
|
|
};
|
|
}, []);
|
|
return React28.createElement("group", _extends({
|
|
ref
|
|
}, props));
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/Trail.js
|
|
var React29 = __toESM(require_react());
|
|
|
|
// node_modules/meshline/dist/index.js
|
|
var __defProp = Object.defineProperty;
|
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
var __publicField = (obj, key, value) => {
|
|
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
return value;
|
|
};
|
|
function memcpy(src, srcOffset, dst, dstOffset, length3) {
|
|
let i3;
|
|
src = src.subarray || src.slice ? src : src.buffer;
|
|
dst = dst.subarray || dst.slice ? dst : dst.buffer;
|
|
src = srcOffset ? src.subarray ? src.subarray(srcOffset, length3 && srcOffset + length3) : src.slice(srcOffset, length3 && srcOffset + length3) : src;
|
|
if (dst.set) {
|
|
dst.set(src, dstOffset);
|
|
} else {
|
|
for (i3 = 0; i3 < src.length; i3++)
|
|
dst[i3 + dstOffset] = src[i3];
|
|
}
|
|
return dst;
|
|
}
|
|
function convertPoints(points) {
|
|
if (points instanceof Float32Array)
|
|
return points;
|
|
if (points instanceof BufferGeometry)
|
|
return points.getAttribute("position").array;
|
|
return points.map((p2) => {
|
|
const isArray3 = Array.isArray(p2);
|
|
return p2 instanceof Vector3 ? [p2.x, p2.y, p2.z] : p2 instanceof Vector2 ? [p2.x, p2.y, 0] : isArray3 && p2.length === 3 ? [p2[0], p2[1], p2[2]] : isArray3 && p2.length === 2 ? [p2[0], p2[1], 0] : p2;
|
|
}).flat();
|
|
}
|
|
var MeshLineGeometry = class extends BufferGeometry {
|
|
constructor() {
|
|
super();
|
|
__publicField(this, "type", "MeshLine");
|
|
__publicField(this, "isMeshLine", true);
|
|
__publicField(this, "positions", []);
|
|
__publicField(this, "previous", []);
|
|
__publicField(this, "next", []);
|
|
__publicField(this, "side", []);
|
|
__publicField(this, "width", []);
|
|
__publicField(this, "indices_array", []);
|
|
__publicField(this, "uvs", []);
|
|
__publicField(this, "counters", []);
|
|
__publicField(this, "widthCallback", null);
|
|
__publicField(this, "_attributes");
|
|
__publicField(this, "_points", []);
|
|
__publicField(this, "points");
|
|
__publicField(this, "matrixWorld", new Matrix4());
|
|
Object.defineProperties(this, {
|
|
points: {
|
|
enumerable: true,
|
|
get() {
|
|
return this._points;
|
|
},
|
|
set(value) {
|
|
this.setPoints(value, this.widthCallback);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
setMatrixWorld(matrixWorld) {
|
|
this.matrixWorld = matrixWorld;
|
|
}
|
|
setPoints(points, wcb) {
|
|
points = convertPoints(points);
|
|
this._points = points;
|
|
this.widthCallback = wcb != null ? wcb : null;
|
|
this.positions = [];
|
|
this.counters = [];
|
|
if (points.length && points[0] instanceof Vector3) {
|
|
for (let j = 0; j < points.length; j++) {
|
|
const p2 = points[j];
|
|
const c2 = j / (points.length - 1);
|
|
this.positions.push(p2.x, p2.y, p2.z);
|
|
this.positions.push(p2.x, p2.y, p2.z);
|
|
this.counters.push(c2);
|
|
this.counters.push(c2);
|
|
}
|
|
} else {
|
|
for (let j = 0; j < points.length; j += 3) {
|
|
const c2 = j / (points.length - 1);
|
|
this.positions.push(points[j], points[j + 1], points[j + 2]);
|
|
this.positions.push(points[j], points[j + 1], points[j + 2]);
|
|
this.counters.push(c2);
|
|
this.counters.push(c2);
|
|
}
|
|
}
|
|
this.process();
|
|
}
|
|
compareV3(a5, b) {
|
|
const aa = a5 * 6;
|
|
const ab = b * 6;
|
|
return this.positions[aa] === this.positions[ab] && this.positions[aa + 1] === this.positions[ab + 1] && this.positions[aa + 2] === this.positions[ab + 2];
|
|
}
|
|
copyV3(a5) {
|
|
const aa = a5 * 6;
|
|
return [this.positions[aa], this.positions[aa + 1], this.positions[aa + 2]];
|
|
}
|
|
process() {
|
|
const l2 = this.positions.length / 6;
|
|
this.previous = [];
|
|
this.next = [];
|
|
this.side = [];
|
|
this.width = [];
|
|
this.indices_array = [];
|
|
this.uvs = [];
|
|
let w;
|
|
let v5;
|
|
if (this.compareV3(0, l2 - 1)) {
|
|
v5 = this.copyV3(l2 - 2);
|
|
} else {
|
|
v5 = this.copyV3(0);
|
|
}
|
|
this.previous.push(v5[0], v5[1], v5[2]);
|
|
this.previous.push(v5[0], v5[1], v5[2]);
|
|
for (let j = 0; j < l2; j++) {
|
|
this.side.push(1);
|
|
this.side.push(-1);
|
|
if (this.widthCallback)
|
|
w = this.widthCallback(j / (l2 - 1));
|
|
else
|
|
w = 1;
|
|
this.width.push(w);
|
|
this.width.push(w);
|
|
this.uvs.push(j / (l2 - 1), 0);
|
|
this.uvs.push(j / (l2 - 1), 1);
|
|
if (j < l2 - 1) {
|
|
v5 = this.copyV3(j);
|
|
this.previous.push(v5[0], v5[1], v5[2]);
|
|
this.previous.push(v5[0], v5[1], v5[2]);
|
|
const n2 = j * 2;
|
|
this.indices_array.push(n2, n2 + 1, n2 + 2);
|
|
this.indices_array.push(n2 + 2, n2 + 1, n2 + 3);
|
|
}
|
|
if (j > 0) {
|
|
v5 = this.copyV3(j);
|
|
this.next.push(v5[0], v5[1], v5[2]);
|
|
this.next.push(v5[0], v5[1], v5[2]);
|
|
}
|
|
}
|
|
if (this.compareV3(l2 - 1, 0)) {
|
|
v5 = this.copyV3(1);
|
|
} else {
|
|
v5 = this.copyV3(l2 - 1);
|
|
}
|
|
this.next.push(v5[0], v5[1], v5[2]);
|
|
this.next.push(v5[0], v5[1], v5[2]);
|
|
if (!this._attributes || this._attributes.position.count !== this.counters.length) {
|
|
this._attributes = {
|
|
position: new BufferAttribute(new Float32Array(this.positions), 3),
|
|
previous: new BufferAttribute(new Float32Array(this.previous), 3),
|
|
next: new BufferAttribute(new Float32Array(this.next), 3),
|
|
side: new BufferAttribute(new Float32Array(this.side), 1),
|
|
width: new BufferAttribute(new Float32Array(this.width), 1),
|
|
uv: new BufferAttribute(new Float32Array(this.uvs), 2),
|
|
index: new BufferAttribute(new Uint16Array(this.indices_array), 1),
|
|
counters: new BufferAttribute(new Float32Array(this.counters), 1)
|
|
};
|
|
} else {
|
|
this._attributes.position.copyArray(new Float32Array(this.positions));
|
|
this._attributes.position.needsUpdate = true;
|
|
this._attributes.previous.copyArray(new Float32Array(this.previous));
|
|
this._attributes.previous.needsUpdate = true;
|
|
this._attributes.next.copyArray(new Float32Array(this.next));
|
|
this._attributes.next.needsUpdate = true;
|
|
this._attributes.side.copyArray(new Float32Array(this.side));
|
|
this._attributes.side.needsUpdate = true;
|
|
this._attributes.width.copyArray(new Float32Array(this.width));
|
|
this._attributes.width.needsUpdate = true;
|
|
this._attributes.uv.copyArray(new Float32Array(this.uvs));
|
|
this._attributes.uv.needsUpdate = true;
|
|
this._attributes.index.copyArray(new Uint16Array(this.indices_array));
|
|
this._attributes.index.needsUpdate = true;
|
|
}
|
|
this.setAttribute("position", this._attributes.position);
|
|
this.setAttribute("previous", this._attributes.previous);
|
|
this.setAttribute("next", this._attributes.next);
|
|
this.setAttribute("side", this._attributes.side);
|
|
this.setAttribute("width", this._attributes.width);
|
|
this.setAttribute("uv", this._attributes.uv);
|
|
this.setAttribute("counters", this._attributes.counters);
|
|
this.setAttribute("position", this._attributes.position);
|
|
this.setAttribute("previous", this._attributes.previous);
|
|
this.setAttribute("next", this._attributes.next);
|
|
this.setAttribute("side", this._attributes.side);
|
|
this.setAttribute("width", this._attributes.width);
|
|
this.setAttribute("uv", this._attributes.uv);
|
|
this.setAttribute("counters", this._attributes.counters);
|
|
this.setIndex(this._attributes.index);
|
|
this.computeBoundingSphere();
|
|
this.computeBoundingBox();
|
|
}
|
|
advance({ x, y, z }) {
|
|
const positions = this._attributes.position.array;
|
|
const previous = this._attributes.previous.array;
|
|
const next = this._attributes.next.array;
|
|
const l2 = positions.length;
|
|
memcpy(positions, 0, previous, 0, l2);
|
|
memcpy(positions, 6, positions, 0, l2 - 6);
|
|
positions[l2 - 6] = x;
|
|
positions[l2 - 5] = y;
|
|
positions[l2 - 4] = z;
|
|
positions[l2 - 3] = x;
|
|
positions[l2 - 2] = y;
|
|
positions[l2 - 1] = z;
|
|
memcpy(positions, 6, next, 0, l2 - 6);
|
|
next[l2 - 6] = x;
|
|
next[l2 - 5] = y;
|
|
next[l2 - 4] = z;
|
|
next[l2 - 3] = x;
|
|
next[l2 - 2] = y;
|
|
next[l2 - 1] = z;
|
|
this._attributes.position.needsUpdate = true;
|
|
this._attributes.previous.needsUpdate = true;
|
|
this._attributes.next.needsUpdate = true;
|
|
}
|
|
};
|
|
var vertexShader = `
|
|
#include <common>
|
|
#include <logdepthbuf_pars_vertex>
|
|
#include <fog_pars_vertex>
|
|
#include <clipping_planes_pars_vertex>
|
|
|
|
attribute vec3 previous;
|
|
attribute vec3 next;
|
|
attribute float side;
|
|
attribute float width;
|
|
attribute float counters;
|
|
|
|
uniform vec2 resolution;
|
|
uniform float lineWidth;
|
|
uniform vec3 color;
|
|
uniform float opacity;
|
|
uniform float sizeAttenuation;
|
|
|
|
varying vec2 vUV;
|
|
varying vec4 vColor;
|
|
varying float vCounters;
|
|
|
|
vec2 fix(vec4 i, float aspect) {
|
|
vec2 res = i.xy / i.w;
|
|
res.x *= aspect;
|
|
return res;
|
|
}
|
|
|
|
void main() {
|
|
float aspect = resolution.x / resolution.y;
|
|
vColor = vec4(color, opacity);
|
|
vUV = uv;
|
|
vCounters = counters;
|
|
|
|
mat4 m = projectionMatrix * modelViewMatrix;
|
|
vec4 finalPosition = m * vec4(position, 1.0) * aspect;
|
|
vec4 prevPos = m * vec4(previous, 1.0);
|
|
vec4 nextPos = m * vec4(next, 1.0);
|
|
|
|
vec2 currentP = fix(finalPosition, aspect);
|
|
vec2 prevP = fix(prevPos, aspect);
|
|
vec2 nextP = fix(nextPos, aspect);
|
|
|
|
float w = lineWidth * width;
|
|
|
|
vec2 dir;
|
|
if (nextP == currentP) dir = normalize(currentP - prevP);
|
|
else if (prevP == currentP) dir = normalize(nextP - currentP);
|
|
else {
|
|
vec2 dir1 = normalize(currentP - prevP);
|
|
vec2 dir2 = normalize(nextP - currentP);
|
|
dir = normalize(dir1 + dir2);
|
|
|
|
vec2 perp = vec2(-dir1.y, dir1.x);
|
|
vec2 miter = vec2(-dir.y, dir.x);
|
|
//w = clamp(w / dot(miter, perp), 0., 4. * lineWidth * width);
|
|
}
|
|
|
|
//vec2 normal = (cross(vec3(dir, 0.), vec3(0., 0., 1.))).xy;
|
|
vec4 normal = vec4(-dir.y, dir.x, 0., 1.);
|
|
normal.xy *= .5 * w;
|
|
//normal *= projectionMatrix;
|
|
if (sizeAttenuation == 0.) {
|
|
normal.xy *= finalPosition.w;
|
|
normal.xy /= (vec4(resolution, 0., 1.) * projectionMatrix).xy * aspect;
|
|
}
|
|
|
|
finalPosition.xy += normal.xy * side;
|
|
gl_Position = finalPosition;
|
|
#include <logdepthbuf_vertex>
|
|
#include <fog_vertex>
|
|
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
|
|
#include <clipping_planes_vertex>
|
|
#include <fog_vertex>
|
|
}
|
|
`;
|
|
var version2 = (() => parseInt(REVISION.replace(/\D+/g, "")))();
|
|
var colorspace_fragment = version2 >= 154 ? "colorspace_fragment" : "encodings_fragment";
|
|
var fragmentShader = `
|
|
#include <fog_pars_fragment>
|
|
#include <logdepthbuf_pars_fragment>
|
|
#include <clipping_planes_pars_fragment>
|
|
|
|
uniform sampler2D map;
|
|
uniform sampler2D alphaMap;
|
|
uniform float useGradient;
|
|
uniform float useMap;
|
|
uniform float useAlphaMap;
|
|
uniform float useDash;
|
|
uniform float dashArray;
|
|
uniform float dashOffset;
|
|
uniform float dashRatio;
|
|
uniform float visibility;
|
|
uniform float alphaTest;
|
|
uniform vec2 repeat;
|
|
uniform vec3 gradient[2];
|
|
|
|
varying vec2 vUV;
|
|
varying vec4 vColor;
|
|
varying float vCounters;
|
|
|
|
void main() {
|
|
#include <logdepthbuf_fragment>
|
|
vec4 diffuseColor = vColor;
|
|
if (useGradient == 1.) diffuseColor = vec4(mix(gradient[0], gradient[1], vCounters), 1.0);
|
|
if (useMap == 1.) diffuseColor *= texture2D(map, vUV * repeat);
|
|
if (useAlphaMap == 1.) diffuseColor.a *= texture2D(alphaMap, vUV * repeat).a;
|
|
if (diffuseColor.a < alphaTest) discard;
|
|
if (useDash == 1.) diffuseColor.a *= ceil(mod(vCounters + dashOffset, dashArray) - (dashArray * dashRatio));
|
|
diffuseColor.a *= step(vCounters, visibility);
|
|
#include <clipping_planes_fragment>
|
|
gl_FragColor = diffuseColor;
|
|
#include <fog_fragment>
|
|
#include <tonemapping_fragment>
|
|
#include <${colorspace_fragment}>
|
|
}
|
|
`;
|
|
var MeshLineMaterial = class extends ShaderMaterial {
|
|
constructor(parameters) {
|
|
super({
|
|
uniforms: {
|
|
...UniformsLib.fog,
|
|
lineWidth: { value: 1 },
|
|
map: { value: null },
|
|
useMap: { value: 0 },
|
|
alphaMap: { value: null },
|
|
useAlphaMap: { value: 0 },
|
|
color: { value: new Color(16777215) },
|
|
gradient: { value: [new Color(16711680), new Color(65280)] },
|
|
opacity: { value: 1 },
|
|
resolution: { value: new Vector2(1, 1) },
|
|
sizeAttenuation: { value: 1 },
|
|
dashArray: { value: 0 },
|
|
dashOffset: { value: 0 },
|
|
dashRatio: { value: 0.5 },
|
|
useDash: { value: 0 },
|
|
useGradient: { value: 0 },
|
|
visibility: { value: 1 },
|
|
alphaTest: { value: 0 },
|
|
repeat: { value: new Vector2(1, 1) }
|
|
},
|
|
vertexShader,
|
|
fragmentShader
|
|
});
|
|
__publicField(this, "lineWidth");
|
|
__publicField(this, "map");
|
|
__publicField(this, "useMap");
|
|
__publicField(this, "alphaMap");
|
|
__publicField(this, "useAlphaMap");
|
|
__publicField(this, "color");
|
|
__publicField(this, "gradient");
|
|
__publicField(this, "resolution");
|
|
__publicField(this, "sizeAttenuation");
|
|
__publicField(this, "dashArray");
|
|
__publicField(this, "dashOffset");
|
|
__publicField(this, "dashRatio");
|
|
__publicField(this, "useDash");
|
|
__publicField(this, "useGradient");
|
|
__publicField(this, "visibility");
|
|
__publicField(this, "repeat");
|
|
this.type = "MeshLineMaterial";
|
|
Object.defineProperties(this, {
|
|
lineWidth: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.lineWidth.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.lineWidth.value = value;
|
|
}
|
|
},
|
|
map: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.map.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.map.value = value;
|
|
}
|
|
},
|
|
useMap: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.useMap.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.useMap.value = value;
|
|
}
|
|
},
|
|
alphaMap: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.alphaMap.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.alphaMap.value = value;
|
|
}
|
|
},
|
|
useAlphaMap: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.useAlphaMap.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.useAlphaMap.value = value;
|
|
}
|
|
},
|
|
color: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.color.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.color.value = value;
|
|
}
|
|
},
|
|
gradient: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.gradient.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.gradient.value = value;
|
|
}
|
|
},
|
|
opacity: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.opacity.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.opacity.value = value;
|
|
}
|
|
},
|
|
resolution: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.resolution.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.resolution.value.copy(value);
|
|
}
|
|
},
|
|
sizeAttenuation: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.sizeAttenuation.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.sizeAttenuation.value = value;
|
|
}
|
|
},
|
|
dashArray: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.dashArray.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.dashArray.value = value;
|
|
this.useDash = value !== 0 ? 1 : 0;
|
|
}
|
|
},
|
|
dashOffset: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.dashOffset.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.dashOffset.value = value;
|
|
}
|
|
},
|
|
dashRatio: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.dashRatio.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.dashRatio.value = value;
|
|
}
|
|
},
|
|
useDash: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.useDash.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.useDash.value = value;
|
|
}
|
|
},
|
|
useGradient: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.useGradient.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.useGradient.value = value;
|
|
}
|
|
},
|
|
visibility: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.visibility.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.visibility.value = value;
|
|
}
|
|
},
|
|
alphaTest: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.alphaTest.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.alphaTest.value = value;
|
|
}
|
|
},
|
|
repeat: {
|
|
enumerable: true,
|
|
get() {
|
|
return this.uniforms.repeat.value;
|
|
},
|
|
set(value) {
|
|
this.uniforms.repeat.value.copy(value);
|
|
}
|
|
}
|
|
});
|
|
this.setValues(parameters);
|
|
}
|
|
copy(source) {
|
|
super.copy(source);
|
|
this.lineWidth = source.lineWidth;
|
|
this.map = source.map;
|
|
this.useMap = source.useMap;
|
|
this.alphaMap = source.alphaMap;
|
|
this.useAlphaMap = source.useAlphaMap;
|
|
this.color.copy(source.color);
|
|
this.gradient = source.gradient;
|
|
this.opacity = source.opacity;
|
|
this.resolution.copy(source.resolution);
|
|
this.sizeAttenuation = source.sizeAttenuation;
|
|
this.dashArray = source.dashArray;
|
|
this.dashOffset = source.dashOffset;
|
|
this.dashRatio = source.dashRatio;
|
|
this.useDash = source.useDash;
|
|
this.useGradient = source.useGradient;
|
|
this.visibility = source.visibility;
|
|
this.alphaTest = source.alphaTest;
|
|
this.repeat.copy(source.repeat);
|
|
return this;
|
|
}
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/Trail.js
|
|
var defaults = {
|
|
width: 0.2,
|
|
length: 1,
|
|
decay: 1,
|
|
local: false,
|
|
stride: 0,
|
|
interval: 1
|
|
};
|
|
var shiftLeft = (collection, steps = 1) => {
|
|
collection.set(collection.subarray(steps));
|
|
collection.fill(-Infinity, -steps);
|
|
return collection;
|
|
};
|
|
function useTrail(target2, settings) {
|
|
const {
|
|
length: length3,
|
|
local,
|
|
decay,
|
|
interval,
|
|
stride
|
|
} = {
|
|
...defaults,
|
|
...settings
|
|
};
|
|
const points = React29.useRef(null);
|
|
const [worldPosition] = React29.useState(() => new Vector3());
|
|
React29.useLayoutEffect(() => {
|
|
if (target2) {
|
|
points.current = Float32Array.from({
|
|
length: length3 * 10 * 3
|
|
}, (_, i3) => target2.position.getComponent(i3 % 3));
|
|
}
|
|
}, [length3, target2]);
|
|
const prevPosition = React29.useRef(new Vector3());
|
|
const frameCount = React29.useRef(0);
|
|
useFrame(() => {
|
|
if (!target2) return;
|
|
if (!points.current) return;
|
|
if (frameCount.current === 0) {
|
|
let newPosition;
|
|
if (local) {
|
|
newPosition = target2.position;
|
|
} else {
|
|
target2.getWorldPosition(worldPosition);
|
|
newPosition = worldPosition;
|
|
}
|
|
const steps = 1 * decay;
|
|
for (let i3 = 0; i3 < steps; i3++) {
|
|
if (newPosition.distanceTo(prevPosition.current) < stride) continue;
|
|
shiftLeft(points.current, 3);
|
|
points.current.set(newPosition.toArray(), points.current.length - 3);
|
|
}
|
|
prevPosition.current.copy(newPosition);
|
|
}
|
|
frameCount.current++;
|
|
frameCount.current = frameCount.current % interval;
|
|
});
|
|
return points;
|
|
}
|
|
var Trail = React29.forwardRef((props, forwardRef82) => {
|
|
const {
|
|
children
|
|
} = props;
|
|
const {
|
|
width,
|
|
length: length3,
|
|
decay,
|
|
local,
|
|
stride,
|
|
interval
|
|
} = {
|
|
...defaults,
|
|
...props
|
|
};
|
|
const {
|
|
color = "hotpink",
|
|
attenuation,
|
|
target: target2
|
|
} = props;
|
|
const size = useThree((s2) => s2.size);
|
|
const scene = useThree((s2) => s2.scene);
|
|
const ref = React29.useRef(null);
|
|
const [anchor, setAnchor] = React29.useState(null);
|
|
const points = useTrail(anchor, {
|
|
length: length3,
|
|
decay,
|
|
local,
|
|
stride,
|
|
interval
|
|
});
|
|
React29.useEffect(() => {
|
|
const t2 = (target2 == null ? void 0 : target2.current) || ref.current.children.find((o2) => {
|
|
return o2 instanceof Object3D;
|
|
});
|
|
if (t2) {
|
|
setAnchor(t2);
|
|
}
|
|
}, [points, target2]);
|
|
const geo = React29.useMemo(() => new MeshLineGeometry(), []);
|
|
const mat2 = React29.useMemo(() => {
|
|
var _matOverride, _matOverride2;
|
|
const m = new MeshLineMaterial({
|
|
lineWidth: 0.1 * width,
|
|
color,
|
|
sizeAttenuation: 1,
|
|
resolution: new Vector2(size.width, size.height)
|
|
});
|
|
let matOverride;
|
|
if (children) {
|
|
if (Array.isArray(children)) {
|
|
matOverride = children.find((child) => {
|
|
const c2 = child;
|
|
return typeof c2.type === "string" && c2.type === "meshLineMaterial";
|
|
});
|
|
} else {
|
|
const c2 = children;
|
|
if (typeof c2.type === "string" && c2.type === "meshLineMaterial") {
|
|
matOverride = c2;
|
|
}
|
|
}
|
|
}
|
|
if (typeof ((_matOverride = matOverride) == null ? void 0 : _matOverride.props) === "object" && ((_matOverride2 = matOverride) == null ? void 0 : _matOverride2.props) !== null) {
|
|
m.setValues(matOverride.props);
|
|
}
|
|
return m;
|
|
}, [width, color, size, children]);
|
|
React29.useEffect(() => {
|
|
mat2.uniforms.resolution.value.set(size.width, size.height);
|
|
}, [size]);
|
|
useFrame(() => {
|
|
if (!points.current) return;
|
|
geo.setPoints(points.current, attenuation);
|
|
});
|
|
return React29.createElement("group", null, createPortal(React29.createElement("mesh", {
|
|
ref: forwardRef82,
|
|
geometry: geo,
|
|
material: mat2
|
|
}), scene), React29.createElement("group", {
|
|
ref
|
|
}, children));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Sampler.js
|
|
var React30 = __toESM(require_react());
|
|
function useSurfaceSampler(mesh, count = 16, transform, weight, instanceMesh) {
|
|
const [buffer2, setBuffer] = React30.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);
|
|
});
|
|
React30.useLayoutEffect(() => {
|
|
if (typeof mesh.current === "undefined") return;
|
|
const sampler = new MeshSurfaceSampler(mesh.current);
|
|
if (weight) {
|
|
sampler.setWeightAttribute(weight);
|
|
}
|
|
sampler.build();
|
|
const position2 = new Vector3();
|
|
const normal2 = new Vector3();
|
|
const color = new Color();
|
|
const dummy2 = new Object3D();
|
|
mesh.current.updateMatrixWorld(true);
|
|
for (let i3 = 0; i3 < count; i3++) {
|
|
sampler.sample(position2, normal2, color);
|
|
if (typeof transform === "function") {
|
|
transform({
|
|
dummy: dummy2,
|
|
sampledMesh: mesh.current,
|
|
position: position2,
|
|
normal: normal2,
|
|
color
|
|
}, i3);
|
|
} else {
|
|
dummy2.position.copy(position2);
|
|
}
|
|
dummy2.updateMatrix();
|
|
if (instanceMesh != null && instanceMesh.current) {
|
|
instanceMesh.current.setMatrixAt(i3, dummy2.matrix);
|
|
}
|
|
dummy2.matrix.toArray(buffer2.array, i3 * 16);
|
|
}
|
|
if (instanceMesh != null && instanceMesh.current) {
|
|
instanceMesh.current.instanceMatrix.needsUpdate = true;
|
|
}
|
|
buffer2.needsUpdate = true;
|
|
setBuffer(new InstancedBufferAttribute(buffer2.array, buffer2.itemSize).copy(buffer2));
|
|
}, [mesh, instanceMesh, weight, count, transform]);
|
|
return buffer2;
|
|
}
|
|
function Sampler({
|
|
children,
|
|
weight,
|
|
transform,
|
|
instances,
|
|
mesh,
|
|
count = 16,
|
|
...props
|
|
}) {
|
|
const group = React30.useRef(null);
|
|
const instancedRef = React30.useRef(null);
|
|
const meshToSampleRef = React30.useRef(null);
|
|
React30.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((c2) => c2.hasOwnProperty("instanceMatrix"));
|
|
meshToSampleRef.current = (_mesh$current = mesh == null ? void 0 : mesh.current) !== null && _mesh$current !== void 0 ? _mesh$current : group.current.children.find((c2) => c2.type === "Mesh");
|
|
}, [children, mesh == null ? void 0 : mesh.current, instances == null ? void 0 : instances.current]);
|
|
useSurfaceSampler(meshToSampleRef, count, transform, weight, instancedRef);
|
|
return React30.createElement("group", _extends({
|
|
ref: group
|
|
}, props), children);
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/ComputedAttribute.js
|
|
var React31 = __toESM(require_react());
|
|
var ComputedAttribute = ({
|
|
compute,
|
|
name,
|
|
...props
|
|
}) => {
|
|
const [bufferAttribute] = React31.useState(() => new BufferAttribute(new Float32Array(0), 1));
|
|
const primitive = React31.useRef(null);
|
|
React31.useLayoutEffect(() => {
|
|
if (primitive.current) {
|
|
var _ref;
|
|
const parent = (_ref = primitive.current.parent) !== null && _ref !== void 0 ? _ref : primitive.current.__r3f.parent.object;
|
|
const attr = compute(parent);
|
|
primitive.current.copy(attr);
|
|
}
|
|
}, [compute]);
|
|
return React31.createElement("primitive", _extends({
|
|
ref: primitive,
|
|
object: bufferAttribute,
|
|
attach: `attributes-${name}`
|
|
}, props));
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/Clone.js
|
|
var React32 = __toESM(require_react());
|
|
function createSpread(child, {
|
|
keys = ["near", "far", "color", "distance", "decay", "penumbra", "angle", "intensity", "skeleton", "visible", "castShadow", "receiveShadow", "morphTargetDictionary", "morphTargetInfluences", "name", "geometry", "material", "position", "rotation", "scale", "up", "userData", "bindMode", "bindMatrix", "bindMatrixInverse", "skeleton"],
|
|
deep,
|
|
inject,
|
|
castShadow,
|
|
receiveShadow
|
|
}) {
|
|
let spread = {};
|
|
for (const key of keys) {
|
|
spread[key] = child[key];
|
|
}
|
|
if (deep) {
|
|
if (spread.geometry && deep !== "materialsOnly") spread.geometry = spread.geometry.clone();
|
|
if (spread.material && deep !== "geometriesOnly") spread.material = spread.material.clone();
|
|
}
|
|
if (inject) {
|
|
if (typeof inject === "function") spread = {
|
|
...spread,
|
|
children: inject(child)
|
|
};
|
|
else if (React32.isValidElement(inject)) spread = {
|
|
...spread,
|
|
children: inject
|
|
};
|
|
else spread = {
|
|
...spread,
|
|
...inject
|
|
};
|
|
}
|
|
if (child instanceof Mesh) {
|
|
if (castShadow) spread.castShadow = true;
|
|
if (receiveShadow) spread.receiveShadow = true;
|
|
}
|
|
return spread;
|
|
}
|
|
var Clone = React32.forwardRef(({
|
|
isChild = false,
|
|
object,
|
|
children,
|
|
deep,
|
|
castShadow,
|
|
receiveShadow,
|
|
inject,
|
|
keys,
|
|
...props
|
|
}, forwardRef82) => {
|
|
const config = {
|
|
keys,
|
|
deep,
|
|
inject,
|
|
castShadow,
|
|
receiveShadow
|
|
};
|
|
object = React32.useMemo(() => {
|
|
if (isChild === false && !Array.isArray(object)) {
|
|
let isSkinned = false;
|
|
object.traverse((object2) => {
|
|
if (object2.isSkinnedMesh) isSkinned = true;
|
|
});
|
|
if (isSkinned) return SkeletonUtils.clone(object);
|
|
}
|
|
return object;
|
|
}, [object, isChild]);
|
|
if (Array.isArray(object)) {
|
|
return React32.createElement("group", _extends({}, props, {
|
|
ref: forwardRef82
|
|
}), object.map((o2) => React32.createElement(Clone, _extends({
|
|
key: o2.uuid,
|
|
object: o2
|
|
}, config))), children);
|
|
}
|
|
const {
|
|
children: injectChildren,
|
|
...spread
|
|
} = createSpread(object, config);
|
|
const Element = object.type[0].toLowerCase() + object.type.slice(1);
|
|
return React32.createElement(Element, _extends({}, spread, props, {
|
|
ref: forwardRef82
|
|
}), object.children.map((child) => {
|
|
if (child.type === "Bone") return React32.createElement("primitive", _extends({
|
|
key: child.uuid,
|
|
object: child
|
|
}, config));
|
|
return React32.createElement(Clone, _extends({
|
|
key: child.uuid,
|
|
object: child
|
|
}, config, {
|
|
isChild: true
|
|
}));
|
|
}), children, injectChildren);
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/MarchingCubes.js
|
|
var React33 = __toESM(require_react());
|
|
var globalContext = React33.createContext(null);
|
|
var MarchingCubes2 = React33.forwardRef(({
|
|
resolution = 28,
|
|
maxPolyCount = 1e4,
|
|
enableUvs = false,
|
|
enableColors = false,
|
|
children,
|
|
...props
|
|
}, ref) => {
|
|
const marchingCubesRef = React33.useRef(null);
|
|
React33.useImperativeHandle(ref, () => marchingCubesRef.current, []);
|
|
const marchingCubes = React33.useMemo(() => new MarchingCubes(resolution, null, enableUvs, enableColors, maxPolyCount), [resolution, maxPolyCount, enableUvs, enableColors]);
|
|
const api = React33.useMemo(() => ({
|
|
getParent: () => marchingCubesRef
|
|
}), []);
|
|
useFrame(() => {
|
|
marchingCubes.update();
|
|
marchingCubes.reset();
|
|
}, -1);
|
|
return React33.createElement(React33.Fragment, null, React33.createElement("primitive", _extends({
|
|
object: marchingCubes,
|
|
ref: marchingCubesRef
|
|
}, props), React33.createElement(globalContext.Provider, {
|
|
value: api
|
|
}, children)));
|
|
});
|
|
var MarchingCube = React33.forwardRef(({
|
|
strength = 0.5,
|
|
subtract = 12,
|
|
color,
|
|
...props
|
|
}, ref) => {
|
|
const {
|
|
getParent
|
|
} = React33.useContext(globalContext);
|
|
const parentRef = React33.useMemo(() => getParent(), [getParent]);
|
|
const cubeRef = React33.useRef(null);
|
|
React33.useImperativeHandle(ref, () => cubeRef.current, []);
|
|
const vec = new Vector3();
|
|
useFrame((state) => {
|
|
if (!parentRef.current || !cubeRef.current) return;
|
|
cubeRef.current.getWorldPosition(vec);
|
|
parentRef.current.addBall(0.5 + vec.x * 0.5, 0.5 + vec.y * 0.5, 0.5 + vec.z * 0.5, strength, subtract, color);
|
|
});
|
|
return React33.createElement("group", _extends({
|
|
ref: cubeRef
|
|
}, props));
|
|
});
|
|
var MarchingPlane = React33.forwardRef(({
|
|
planeType: _planeType = "x",
|
|
strength = 0.5,
|
|
subtract = 12,
|
|
...props
|
|
}, ref) => {
|
|
const {
|
|
getParent
|
|
} = React33.useContext(globalContext);
|
|
const parentRef = React33.useMemo(() => getParent(), [getParent]);
|
|
const wallRef = React33.useRef(null);
|
|
React33.useImperativeHandle(ref, () => wallRef.current, []);
|
|
const planeType = React33.useMemo(() => _planeType === "x" ? "addPlaneX" : _planeType === "y" ? "addPlaneY" : "addPlaneZ", [_planeType]);
|
|
useFrame(() => {
|
|
if (!parentRef.current || !wallRef.current) return;
|
|
parentRef.current[planeType](strength, subtract);
|
|
});
|
|
return React33.createElement("group", _extends({
|
|
ref: wallRef
|
|
}, props));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Decal.js
|
|
var React34 = __toESM(require_react());
|
|
function isArray(vec) {
|
|
return Array.isArray(vec);
|
|
}
|
|
function vecToArray(vec = [0, 0, 0]) {
|
|
if (isArray(vec)) {
|
|
return vec;
|
|
} else if (vec instanceof Vector3 || vec instanceof Euler) {
|
|
return [vec.x, vec.y, vec.z];
|
|
} else {
|
|
return [vec, vec, vec];
|
|
}
|
|
}
|
|
var Decal = React34.forwardRef(function Decal2({
|
|
debug,
|
|
depthTest = false,
|
|
polygonOffsetFactor = -10,
|
|
map: map2,
|
|
mesh,
|
|
children,
|
|
position: position2,
|
|
rotation: rotation3,
|
|
scale: scale5,
|
|
...props
|
|
}, forwardRef82) {
|
|
const ref = React34.useRef(null);
|
|
React34.useImperativeHandle(forwardRef82, () => ref.current);
|
|
const helper = React34.useRef(null);
|
|
const state = React34.useRef({
|
|
position: new Vector3(),
|
|
rotation: new Euler(),
|
|
scale: new Vector3(1, 1, 1)
|
|
});
|
|
React34.useLayoutEffect(() => {
|
|
const parent = (mesh == null ? void 0 : mesh.current) || ref.current.parent;
|
|
const target2 = ref.current;
|
|
if (!(parent instanceof Mesh)) {
|
|
throw new Error('Decal must have a Mesh as parent or specify its "mesh" prop');
|
|
}
|
|
if (parent) {
|
|
applyProps(state.current, {
|
|
position: position2,
|
|
scale: scale5
|
|
});
|
|
const matrixWorld = parent.matrixWorld.clone();
|
|
parent.matrixWorld.identity();
|
|
if (!rotation3 || typeof rotation3 === "number") {
|
|
const o2 = new Object3D();
|
|
o2.position.copy(state.current.position);
|
|
const vertices = parent.geometry.attributes.position.array;
|
|
if (parent.geometry.attributes.normal === void 0) parent.geometry.computeVertexNormals();
|
|
const normal2 = parent.geometry.attributes.normal.array;
|
|
let distance3 = Infinity;
|
|
let closestNormal = new Vector3();
|
|
const ox = o2.position.x;
|
|
const oy = o2.position.y;
|
|
const oz = o2.position.z;
|
|
const vLength = vertices.length;
|
|
let chosenIdx = -1;
|
|
for (let i3 = 0; i3 < vLength; i3 += 3) {
|
|
const x = vertices[i3];
|
|
const y = vertices[i3 + 1];
|
|
const z = vertices[i3 + 2];
|
|
const xDiff = x - ox;
|
|
const yDiff = y - oy;
|
|
const zDiff = z - oz;
|
|
const distSquared = xDiff * xDiff + yDiff * yDiff + zDiff * zDiff;
|
|
if (distSquared < distance3) {
|
|
distance3 = distSquared;
|
|
chosenIdx = i3;
|
|
}
|
|
}
|
|
closestNormal.fromArray(normal2, chosenIdx);
|
|
o2.lookAt(o2.position.clone().add(closestNormal));
|
|
o2.rotateZ(Math.PI);
|
|
o2.rotateY(Math.PI);
|
|
if (typeof rotation3 === "number") o2.rotateZ(rotation3);
|
|
applyProps(state.current, {
|
|
rotation: o2.rotation
|
|
});
|
|
} else {
|
|
applyProps(state.current, {
|
|
rotation: rotation3
|
|
});
|
|
}
|
|
if (helper.current) {
|
|
applyProps(helper.current, state.current);
|
|
}
|
|
target2.geometry = new DecalGeometry(parent, state.current.position, state.current.rotation, state.current.scale);
|
|
parent.matrixWorld = matrixWorld;
|
|
return () => {
|
|
target2.geometry.dispose();
|
|
};
|
|
}
|
|
}, [mesh, ...vecToArray(position2), ...vecToArray(scale5), ...vecToArray(rotation3)]);
|
|
React34.useLayoutEffect(() => {
|
|
if (helper.current) {
|
|
helper.current.traverse((child) => child.raycast = () => null);
|
|
}
|
|
}, [debug]);
|
|
return React34.createElement("mesh", _extends({
|
|
ref,
|
|
"material-transparent": true,
|
|
"material-polygonOffset": true,
|
|
"material-polygonOffsetFactor": polygonOffsetFactor,
|
|
"material-depthTest": depthTest,
|
|
"material-map": map2
|
|
}, props), children, debug && React34.createElement("mesh", {
|
|
ref: helper
|
|
}, React34.createElement("boxGeometry", null), React34.createElement("meshNormalMaterial", {
|
|
wireframe: true
|
|
}), React34.createElement("axesHelper", null)));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Svg.js
|
|
var React35 = __toESM(require_react());
|
|
var import_react8 = __toESM(require_react());
|
|
var Svg = (0, import_react8.forwardRef)(function R3FSvg({
|
|
src,
|
|
skipFill,
|
|
skipStrokes,
|
|
fillMaterial,
|
|
strokeMaterial,
|
|
fillMeshProps,
|
|
strokeMeshProps,
|
|
...props
|
|
}, ref) {
|
|
const svg = useLoader(SVGLoader, !src.startsWith("<svg") ? src : `data:image/svg+xml;utf8,${src}`);
|
|
const strokeGeometries = (0, import_react8.useMemo)(() => skipStrokes ? [] : svg.paths.map((path) => {
|
|
var _path$userData;
|
|
return ((_path$userData = path.userData) == null ? void 0 : _path$userData.style.stroke) === void 0 || path.userData.style.stroke === "none" ? null : path.subPaths.map((subPath) => SVGLoader.pointsToStroke(subPath.getPoints(), path.userData.style));
|
|
}), [svg, skipStrokes]);
|
|
(0, import_react8.useEffect)(() => {
|
|
return () => strokeGeometries.forEach((group) => group && group.map((g) => g.dispose()));
|
|
}, [strokeGeometries]);
|
|
let renderOrder = 0;
|
|
return React35.createElement("object3D", _extends({
|
|
ref
|
|
}, props), React35.createElement("object3D", {
|
|
scale: [1, -1, 1]
|
|
}, svg.paths.map((path, p2) => {
|
|
var _path$userData2, _path$userData3;
|
|
return React35.createElement(import_react8.Fragment, {
|
|
key: p2
|
|
}, !skipFill && ((_path$userData2 = path.userData) == null ? void 0 : _path$userData2.style.fill) !== void 0 && path.userData.style.fill !== "none" && SVGLoader.createShapes(path).map((shape, s2) => React35.createElement("mesh", _extends({
|
|
key: s2
|
|
}, fillMeshProps, {
|
|
renderOrder: renderOrder++
|
|
}), React35.createElement("shapeGeometry", {
|
|
args: [shape]
|
|
}), React35.createElement("meshBasicMaterial", _extends({
|
|
color: path.userData.style.fill,
|
|
opacity: path.userData.style.fillOpacity,
|
|
transparent: true,
|
|
side: DoubleSide,
|
|
depthWrite: false
|
|
}, fillMaterial)))), !skipStrokes && ((_path$userData3 = path.userData) == null ? void 0 : _path$userData3.style.stroke) !== void 0 && path.userData.style.stroke !== "none" && path.subPaths.map((_subPath, s2) => React35.createElement("mesh", _extends({
|
|
key: s2,
|
|
geometry: strokeGeometries[p2][s2]
|
|
}, strokeMeshProps, {
|
|
renderOrder: renderOrder++
|
|
}), React35.createElement("meshBasicMaterial", _extends({
|
|
color: path.userData.style.stroke,
|
|
opacity: path.userData.style.strokeOpacity,
|
|
transparent: true,
|
|
side: DoubleSide,
|
|
depthWrite: false
|
|
}, strokeMaterial)))));
|
|
})));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Gltf.js
|
|
var React36 = __toESM(require_react());
|
|
var dracoLoader = null;
|
|
var decoderPath = "https://www.gstatic.com/draco/versioned/decoders/1.5.5/";
|
|
function extensions(useDraco = true, useMeshopt = true, extendLoader) {
|
|
return (loader2) => {
|
|
if (extendLoader) {
|
|
extendLoader(loader2);
|
|
}
|
|
if (useDraco) {
|
|
if (!dracoLoader) {
|
|
dracoLoader = new DRACOLoader();
|
|
}
|
|
dracoLoader.setDecoderPath(typeof useDraco === "string" ? useDraco : decoderPath);
|
|
loader2.setDRACOLoader(dracoLoader);
|
|
}
|
|
if (useMeshopt) {
|
|
loader2.setMeshoptDecoder(typeof MeshoptDecoder === "function" ? MeshoptDecoder() : MeshoptDecoder);
|
|
}
|
|
};
|
|
}
|
|
var useGLTF = (path, useDraco, useMeshopt, extendLoader) => useLoader(GLTFLoader, path, extensions(useDraco, useMeshopt, extendLoader));
|
|
useGLTF.preload = (path, useDraco, useMeshopt, extendLoader) => useLoader.preload(GLTFLoader, path, extensions(useDraco, useMeshopt, extendLoader));
|
|
useGLTF.clear = (path) => useLoader.clear(GLTFLoader, path);
|
|
useGLTF.setDecoderPath = (path) => {
|
|
decoderPath = path;
|
|
};
|
|
var Gltf = React36.forwardRef(({
|
|
src,
|
|
useDraco,
|
|
useMeshOpt,
|
|
extendLoader,
|
|
...props
|
|
}, ref) => {
|
|
const {
|
|
scene
|
|
} = useGLTF(src, useDraco, useMeshOpt, extendLoader);
|
|
return React36.createElement(Clone, _extends({
|
|
ref
|
|
}, props, {
|
|
object: scene
|
|
}));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/AsciiRenderer.js
|
|
var React37 = __toESM(require_react());
|
|
function AsciiRenderer({
|
|
renderIndex = 1,
|
|
bgColor = "black",
|
|
fgColor = "white",
|
|
characters = " .:-+*=%@#",
|
|
invert = true,
|
|
color = false,
|
|
resolution = 0.15
|
|
}) {
|
|
const {
|
|
size,
|
|
gl,
|
|
scene,
|
|
camera
|
|
} = useThree();
|
|
const effect = React37.useMemo(() => {
|
|
const effect2 = new AsciiEffect(gl, characters, {
|
|
invert,
|
|
color,
|
|
resolution
|
|
});
|
|
effect2.domElement.style.position = "absolute";
|
|
effect2.domElement.style.top = "0px";
|
|
effect2.domElement.style.left = "0px";
|
|
effect2.domElement.style.pointerEvents = "none";
|
|
return effect2;
|
|
}, [characters, invert, color, resolution]);
|
|
React37.useLayoutEffect(() => {
|
|
effect.domElement.style.color = fgColor;
|
|
effect.domElement.style.backgroundColor = bgColor;
|
|
}, [fgColor, bgColor]);
|
|
React37.useEffect(() => {
|
|
gl.domElement.style.opacity = "0";
|
|
gl.domElement.parentNode.appendChild(effect.domElement);
|
|
return () => {
|
|
gl.domElement.style.opacity = "1";
|
|
gl.domElement.parentNode.removeChild(effect.domElement);
|
|
};
|
|
}, [effect]);
|
|
React37.useEffect(() => {
|
|
effect.setSize(size.width, size.height);
|
|
}, [effect, size]);
|
|
useFrame((state) => {
|
|
effect.render(scene, camera);
|
|
}, renderIndex);
|
|
return React37.createElement(React37.Fragment, null);
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/Splat.js
|
|
var React38 = __toESM(require_react());
|
|
var SplatMaterial = shaderMaterial(
|
|
{
|
|
alphaTest: 0,
|
|
viewport: new Vector2(1980, 1080),
|
|
focal: 1e3,
|
|
centerAndScaleTexture: null,
|
|
covAndColorTexture: null
|
|
},
|
|
/*glsl*/
|
|
`
|
|
precision highp sampler2D;
|
|
precision highp usampler2D;
|
|
out vec4 vColor;
|
|
out vec3 vPosition;
|
|
uniform vec2 resolution;
|
|
uniform vec2 viewport;
|
|
uniform float focal;
|
|
attribute uint splatIndex;
|
|
uniform sampler2D centerAndScaleTexture;
|
|
uniform usampler2D covAndColorTexture;
|
|
|
|
vec2 unpackInt16(in uint value) {
|
|
int v = int(value);
|
|
int v0 = v >> 16;
|
|
int v1 = (v & 0xFFFF);
|
|
if((v & 0x8000) != 0)
|
|
v1 |= 0xFFFF0000;
|
|
return vec2(float(v1), float(v0));
|
|
}
|
|
|
|
void main () {
|
|
ivec2 texSize = textureSize(centerAndScaleTexture, 0);
|
|
ivec2 texPos = ivec2(splatIndex%uint(texSize.x), splatIndex/uint(texSize.x));
|
|
vec4 centerAndScaleData = texelFetch(centerAndScaleTexture, texPos, 0);
|
|
vec4 center = vec4(centerAndScaleData.xyz, 1);
|
|
vec4 camspace = modelViewMatrix * center;
|
|
vec4 pos2d = projectionMatrix * camspace;
|
|
|
|
float bounds = 1.2 * pos2d.w;
|
|
if (pos2d.z < -pos2d.w || pos2d.x < -bounds || pos2d.x > bounds
|
|
|| pos2d.y < -bounds || pos2d.y > bounds) {
|
|
gl_Position = vec4(0.0, 0.0, 2.0, 1.0);
|
|
return;
|
|
}
|
|
|
|
uvec4 covAndColorData = texelFetch(covAndColorTexture, texPos, 0);
|
|
vec2 cov3D_M11_M12 = unpackInt16(covAndColorData.x) * centerAndScaleData.w;
|
|
vec2 cov3D_M13_M22 = unpackInt16(covAndColorData.y) * centerAndScaleData.w;
|
|
vec2 cov3D_M23_M33 = unpackInt16(covAndColorData.z) * centerAndScaleData.w;
|
|
mat3 Vrk = mat3(
|
|
cov3D_M11_M12.x, cov3D_M11_M12.y, cov3D_M13_M22.x,
|
|
cov3D_M11_M12.y, cov3D_M13_M22.y, cov3D_M23_M33.x,
|
|
cov3D_M13_M22.x, cov3D_M23_M33.x, cov3D_M23_M33.y
|
|
);
|
|
|
|
mat3 J = mat3(
|
|
focal / camspace.z, 0., -(focal * camspace.x) / (camspace.z * camspace.z),
|
|
0., focal / camspace.z, -(focal * camspace.y) / (camspace.z * camspace.z),
|
|
0., 0., 0.
|
|
);
|
|
|
|
mat3 W = transpose(mat3(modelViewMatrix));
|
|
mat3 T = W * J;
|
|
mat3 cov = transpose(T) * Vrk * T;
|
|
vec2 vCenter = vec2(pos2d) / pos2d.w;
|
|
float diagonal1 = cov[0][0] + 0.3;
|
|
float offDiagonal = cov[0][1];
|
|
float diagonal2 = cov[1][1] + 0.3;
|
|
float mid = 0.5 * (diagonal1 + diagonal2);
|
|
float radius = length(vec2((diagonal1 - diagonal2) / 2.0, offDiagonal));
|
|
float lambda1 = mid + radius;
|
|
float lambda2 = max(mid - radius, 0.1);
|
|
vec2 diagonalVector = normalize(vec2(offDiagonal, lambda1 - diagonal1));
|
|
vec2 v1 = min(sqrt(2.0 * lambda1), 1024.0) * diagonalVector;
|
|
vec2 v2 = min(sqrt(2.0 * lambda2), 1024.0) * vec2(diagonalVector.y, -diagonalVector.x);
|
|
uint colorUint = covAndColorData.w;
|
|
vColor = vec4(
|
|
float(colorUint & uint(0xFF)) / 255.0,
|
|
float((colorUint >> uint(8)) & uint(0xFF)) / 255.0,
|
|
float((colorUint >> uint(16)) & uint(0xFF)) / 255.0,
|
|
float(colorUint >> uint(24)) / 255.0
|
|
);
|
|
vPosition = position;
|
|
|
|
gl_Position = vec4(
|
|
vCenter
|
|
+ position.x * v2 / viewport * 2.0
|
|
+ position.y * v1 / viewport * 2.0, pos2d.z / pos2d.w, 1.0);
|
|
}
|
|
`,
|
|
/*glsl*/
|
|
`
|
|
#include <alphatest_pars_fragment>
|
|
#include <alphahash_pars_fragment>
|
|
in vec4 vColor;
|
|
in vec3 vPosition;
|
|
void main () {
|
|
float A = -dot(vPosition.xy, vPosition.xy);
|
|
if (A < -4.0) discard;
|
|
float B = exp(A) * vColor.a;
|
|
vec4 diffuseColor = vec4(vColor.rgb, B);
|
|
#include <alphatest_fragment>
|
|
#include <alphahash_fragment>
|
|
gl_FragColor = diffuseColor;
|
|
#include <tonemapping_fragment>
|
|
#include <${version >= 154 ? "colorspace_fragment" : "encodings_fragment"}>
|
|
}
|
|
`
|
|
);
|
|
function createWorker(self2) {
|
|
let matrices = null;
|
|
let offset = 0;
|
|
function sortSplats(view, hashed = false) {
|
|
const vertexCount = matrices.length / 16;
|
|
const threshold = -1e-4;
|
|
let maxDepth = -Infinity;
|
|
let minDepth = Infinity;
|
|
const depthList = new Float32Array(vertexCount);
|
|
const sizeList = new Int32Array(depthList.buffer);
|
|
const validIndexList = new Int32Array(vertexCount);
|
|
let validCount = 0;
|
|
for (let i3 = 0; i3 < vertexCount; i3++) {
|
|
const depth = view[0] * matrices[i3 * 16 + 12] + view[1] * matrices[i3 * 16 + 13] + view[2] * matrices[i3 * 16 + 14] + view[3];
|
|
if (hashed || depth < 0 && matrices[i3 * 16 + 15] > threshold * depth) {
|
|
depthList[validCount] = depth;
|
|
validIndexList[validCount] = i3;
|
|
validCount++;
|
|
if (depth > maxDepth) maxDepth = depth;
|
|
if (depth < minDepth) minDepth = depth;
|
|
}
|
|
}
|
|
const depthInv = (256 * 256 - 1) / (maxDepth - minDepth);
|
|
const counts0 = new Uint32Array(256 * 256);
|
|
for (let i3 = 0; i3 < validCount; i3++) {
|
|
sizeList[i3] = (depthList[i3] - minDepth) * depthInv | 0;
|
|
counts0[sizeList[i3]]++;
|
|
}
|
|
const starts0 = new Uint32Array(256 * 256);
|
|
for (let i3 = 1; i3 < 256 * 256; i3++) starts0[i3] = starts0[i3 - 1] + counts0[i3 - 1];
|
|
const depthIndex = new Uint32Array(validCount);
|
|
for (let i3 = 0; i3 < validCount; i3++) depthIndex[starts0[sizeList[i3]]++] = validIndexList[i3];
|
|
return depthIndex;
|
|
}
|
|
self2.onmessage = (e2) => {
|
|
if (e2.data.method == "push") {
|
|
if (offset === 0) matrices = new Float32Array(e2.data.length);
|
|
const new_matrices = new Float32Array(e2.data.matrices);
|
|
matrices.set(new_matrices, offset);
|
|
offset += new_matrices.length;
|
|
} else if (e2.data.method == "sort") {
|
|
if (matrices !== null) {
|
|
const indices = sortSplats(new Float32Array(e2.data.view), e2.data.hashed);
|
|
self2.postMessage({
|
|
indices,
|
|
key: e2.data.key
|
|
}, [indices.buffer]);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
var SplatLoader = class extends Loader {
|
|
constructor(...args) {
|
|
super(...args);
|
|
this.gl = null;
|
|
this.chunkSize = 25e3;
|
|
}
|
|
load(url, onLoad, onProgress, onError) {
|
|
const shared = {
|
|
gl: this.gl,
|
|
url: this.manager.resolveURL(url),
|
|
worker: new Worker(URL.createObjectURL(new Blob(["(", createWorker.toString(), ")(self)"], {
|
|
type: "application/javascript"
|
|
}))),
|
|
manager: this.manager,
|
|
update: (target2, camera, hashed) => update(camera, shared, target2, hashed),
|
|
connect: (target2) => connect(shared, target2),
|
|
loading: false,
|
|
loaded: false,
|
|
loadedVertexCount: 0,
|
|
chunkSize: this.chunkSize,
|
|
totalDownloadBytes: 0,
|
|
numVertices: 0,
|
|
rowLength: 3 * 4 + 3 * 4 + 4 + 4,
|
|
maxVertexes: 0,
|
|
bufferTextureWidth: 0,
|
|
bufferTextureHeight: 0,
|
|
stream: null,
|
|
centerAndScaleData: null,
|
|
covAndColorData: null,
|
|
covAndColorTexture: null,
|
|
centerAndScaleTexture: null,
|
|
onProgress
|
|
};
|
|
load(shared).then(onLoad).catch((e2) => {
|
|
onError == null || onError(e2);
|
|
shared.manager.itemError(shared.url);
|
|
});
|
|
}
|
|
};
|
|
async function load(shared) {
|
|
shared.manager.itemStart(shared.url);
|
|
const data = await fetch(shared.url);
|
|
if (data.body === null) throw "Failed to fetch file";
|
|
let _totalDownloadBytes = data.headers.get("Content-Length");
|
|
const totalDownloadBytes = _totalDownloadBytes ? parseInt(_totalDownloadBytes) : void 0;
|
|
if (totalDownloadBytes == void 0) throw "Failed to get content length";
|
|
shared.stream = data.body.getReader();
|
|
shared.totalDownloadBytes = totalDownloadBytes;
|
|
shared.numVertices = Math.floor(shared.totalDownloadBytes / shared.rowLength);
|
|
const context12 = shared.gl.getContext();
|
|
let maxTextureSize = context12.getParameter(context12.MAX_TEXTURE_SIZE);
|
|
shared.maxVertexes = maxTextureSize * maxTextureSize;
|
|
if (shared.numVertices > shared.maxVertexes) shared.numVertices = shared.maxVertexes;
|
|
shared.bufferTextureWidth = maxTextureSize;
|
|
shared.bufferTextureHeight = Math.floor((shared.numVertices - 1) / maxTextureSize) + 1;
|
|
shared.centerAndScaleData = new Float32Array(shared.bufferTextureWidth * shared.bufferTextureHeight * 4);
|
|
shared.covAndColorData = new Uint32Array(shared.bufferTextureWidth * shared.bufferTextureHeight * 4);
|
|
shared.centerAndScaleTexture = new DataTexture(shared.centerAndScaleData, shared.bufferTextureWidth, shared.bufferTextureHeight, RGBAFormat, FloatType);
|
|
shared.centerAndScaleTexture.needsUpdate = true;
|
|
shared.covAndColorTexture = new DataTexture(shared.covAndColorData, shared.bufferTextureWidth, shared.bufferTextureHeight, RGBAIntegerFormat, UnsignedIntType);
|
|
shared.covAndColorTexture.internalFormat = "RGBA32UI";
|
|
shared.covAndColorTexture.needsUpdate = true;
|
|
return shared;
|
|
}
|
|
async function lazyLoad(shared) {
|
|
shared.loading = true;
|
|
let bytesDownloaded = 0;
|
|
let bytesProcessed = 0;
|
|
const chunks = [];
|
|
let lastReportedProgress = 0;
|
|
const lengthComputable = shared.totalDownloadBytes !== 0;
|
|
while (true) {
|
|
try {
|
|
const {
|
|
value,
|
|
done
|
|
} = await shared.stream.read();
|
|
if (done) break;
|
|
bytesDownloaded += value.length;
|
|
if (shared.totalDownloadBytes != void 0) {
|
|
const percent = bytesDownloaded / shared.totalDownloadBytes * 100;
|
|
if (shared.onProgress && percent - lastReportedProgress > 1) {
|
|
const event = new ProgressEvent("progress", {
|
|
lengthComputable,
|
|
loaded: bytesDownloaded,
|
|
total: shared.totalDownloadBytes
|
|
});
|
|
shared.onProgress(event);
|
|
lastReportedProgress = percent;
|
|
}
|
|
}
|
|
chunks.push(value);
|
|
const bytesRemains = bytesDownloaded - bytesProcessed;
|
|
if (shared.totalDownloadBytes != void 0 && bytesRemains > shared.rowLength * shared.chunkSize) {
|
|
let vertexCount = Math.floor(bytesRemains / shared.rowLength);
|
|
const concatenatedChunksbuffer = new Uint8Array(bytesRemains);
|
|
let offset = 0;
|
|
for (const chunk of chunks) {
|
|
concatenatedChunksbuffer.set(chunk, offset);
|
|
offset += chunk.length;
|
|
}
|
|
chunks.length = 0;
|
|
if (bytesRemains > vertexCount * shared.rowLength) {
|
|
const extra_data = new Uint8Array(bytesRemains - vertexCount * shared.rowLength);
|
|
extra_data.set(concatenatedChunksbuffer.subarray(bytesRemains - extra_data.length, bytesRemains), 0);
|
|
chunks.push(extra_data);
|
|
}
|
|
const buffer2 = new Uint8Array(vertexCount * shared.rowLength);
|
|
buffer2.set(concatenatedChunksbuffer.subarray(0, buffer2.byteLength), 0);
|
|
const matrices = pushDataBuffer(shared, buffer2.buffer, vertexCount);
|
|
shared.worker.postMessage({
|
|
method: "push",
|
|
src: shared.url,
|
|
length: shared.numVertices * 16,
|
|
matrices: matrices.buffer
|
|
}, [matrices.buffer]);
|
|
bytesProcessed += vertexCount * shared.rowLength;
|
|
if (shared.onProgress) {
|
|
const event = new ProgressEvent("progress", {
|
|
lengthComputable,
|
|
loaded: shared.totalDownloadBytes,
|
|
total: shared.totalDownloadBytes
|
|
});
|
|
shared.onProgress(event);
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
break;
|
|
}
|
|
}
|
|
if (bytesDownloaded - bytesProcessed > 0) {
|
|
let concatenatedChunks = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0));
|
|
let offset = 0;
|
|
for (const chunk of chunks) {
|
|
concatenatedChunks.set(chunk, offset);
|
|
offset += chunk.length;
|
|
}
|
|
let numVertices = Math.floor(concatenatedChunks.byteLength / shared.rowLength);
|
|
const matrices = pushDataBuffer(shared, concatenatedChunks.buffer, numVertices);
|
|
shared.worker.postMessage({
|
|
method: "push",
|
|
src: shared.url,
|
|
length: numVertices * 16,
|
|
matrices: matrices.buffer
|
|
}, [matrices.buffer]);
|
|
}
|
|
shared.loaded = true;
|
|
shared.manager.itemEnd(shared.url);
|
|
}
|
|
function update(camera, shared, target2, hashed) {
|
|
camera.updateMatrixWorld();
|
|
shared.gl.getCurrentViewport(target2.viewport);
|
|
target2.material.viewport.x = target2.viewport.z;
|
|
target2.material.viewport.y = target2.viewport.w;
|
|
target2.material.focal = target2.viewport.w / 2 * Math.abs(camera.projectionMatrix.elements[5]);
|
|
if (target2.ready) {
|
|
if (hashed && target2.sorted) return;
|
|
target2.ready = false;
|
|
const view = new Float32Array([target2.modelViewMatrix.elements[2], -target2.modelViewMatrix.elements[6], target2.modelViewMatrix.elements[10], target2.modelViewMatrix.elements[14]]);
|
|
shared.worker.postMessage({
|
|
method: "sort",
|
|
src: shared.url,
|
|
key: target2.uuid,
|
|
view: view.buffer,
|
|
hashed
|
|
}, [view.buffer]);
|
|
if (hashed && shared.loaded) target2.sorted = true;
|
|
}
|
|
}
|
|
function connect(shared, target2) {
|
|
if (!shared.loading) lazyLoad(shared);
|
|
target2.ready = false;
|
|
target2.pm = new Matrix4();
|
|
target2.vm1 = new Matrix4();
|
|
target2.vm2 = new Matrix4();
|
|
target2.viewport = new Vector4();
|
|
let splatIndexArray = new Uint32Array(shared.bufferTextureWidth * shared.bufferTextureHeight);
|
|
const splatIndexes = new InstancedBufferAttribute(splatIndexArray, 1, false);
|
|
splatIndexes.setUsage(DynamicDrawUsage);
|
|
const geometry3 = target2.geometry = new InstancedBufferGeometry();
|
|
const positionsArray = new Float32Array(6 * 3);
|
|
const positions = new BufferAttribute(positionsArray, 3);
|
|
geometry3.setAttribute("position", positions);
|
|
positions.setXYZ(2, -2, 2, 0);
|
|
positions.setXYZ(1, 2, 2, 0);
|
|
positions.setXYZ(0, -2, -2, 0);
|
|
positions.setXYZ(5, -2, -2, 0);
|
|
positions.setXYZ(4, 2, 2, 0);
|
|
positions.setXYZ(3, 2, -2, 0);
|
|
positions.needsUpdate = true;
|
|
geometry3.setAttribute("splatIndex", splatIndexes);
|
|
geometry3.instanceCount = 1;
|
|
function listener(e2) {
|
|
if (target2 && e2.data.key === target2.uuid) {
|
|
let indexes = new Uint32Array(e2.data.indices);
|
|
geometry3.attributes.splatIndex.set(indexes);
|
|
geometry3.attributes.splatIndex.needsUpdate = true;
|
|
geometry3.instanceCount = indexes.length;
|
|
target2.ready = true;
|
|
}
|
|
}
|
|
shared.worker.addEventListener("message", listener);
|
|
async function wait() {
|
|
while (true) {
|
|
const centerAndScaleTextureProperties = shared.gl.properties.get(shared.centerAndScaleTexture);
|
|
const covAndColorTextureProperties = shared.gl.properties.get(shared.covAndColorTexture);
|
|
if (centerAndScaleTextureProperties != null && centerAndScaleTextureProperties.__webglTexture && covAndColorTextureProperties != null && covAndColorTextureProperties.__webglTexture && shared.loadedVertexCount > 0) break;
|
|
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
}
|
|
target2.ready = true;
|
|
}
|
|
wait();
|
|
return () => shared.worker.removeEventListener("message", listener);
|
|
}
|
|
function pushDataBuffer(shared, buffer2, vertexCount) {
|
|
const context12 = shared.gl.getContext();
|
|
if (shared.loadedVertexCount + vertexCount > shared.maxVertexes) vertexCount = shared.maxVertexes - shared.loadedVertexCount;
|
|
if (vertexCount <= 0) throw "Failed to parse file";
|
|
const u_buffer = new Uint8Array(buffer2);
|
|
const f_buffer = new Float32Array(buffer2);
|
|
const matrices = new Float32Array(vertexCount * 16);
|
|
const covAndColorData_uint8 = new Uint8Array(shared.covAndColorData.buffer);
|
|
const covAndColorData_int16 = new Int16Array(shared.covAndColorData.buffer);
|
|
for (let i3 = 0; i3 < vertexCount; i3++) {
|
|
const quat = new Quaternion(-(u_buffer[32 * i3 + 28 + 1] - 128) / 128, (u_buffer[32 * i3 + 28 + 2] - 128) / 128, (u_buffer[32 * i3 + 28 + 3] - 128) / 128, -(u_buffer[32 * i3 + 28 + 0] - 128) / 128);
|
|
quat.invert();
|
|
const center2 = new Vector3(f_buffer[8 * i3 + 0], f_buffer[8 * i3 + 1], -f_buffer[8 * i3 + 2]);
|
|
const scale5 = new Vector3(f_buffer[8 * i3 + 3 + 0], f_buffer[8 * i3 + 3 + 1], f_buffer[8 * i3 + 3 + 2]);
|
|
const mtx = new Matrix4();
|
|
mtx.makeRotationFromQuaternion(quat);
|
|
mtx.transpose();
|
|
mtx.scale(scale5);
|
|
const mtx_t = mtx.clone();
|
|
mtx.transpose();
|
|
mtx.premultiply(mtx_t);
|
|
mtx.setPosition(center2);
|
|
const cov_indexes = [0, 1, 2, 5, 6, 10];
|
|
let max_value = 0;
|
|
for (let j = 0; j < cov_indexes.length; j++) if (Math.abs(mtx.elements[cov_indexes[j]]) > max_value) max_value = Math.abs(mtx.elements[cov_indexes[j]]);
|
|
let destOffset = shared.loadedVertexCount * 4 + i3 * 4;
|
|
shared.centerAndScaleData[destOffset + 0] = center2.x;
|
|
shared.centerAndScaleData[destOffset + 1] = -center2.y;
|
|
shared.centerAndScaleData[destOffset + 2] = center2.z;
|
|
shared.centerAndScaleData[destOffset + 3] = max_value / 32767;
|
|
destOffset = shared.loadedVertexCount * 8 + i3 * 4 * 2;
|
|
for (let j = 0; j < cov_indexes.length; j++) covAndColorData_int16[destOffset + j] = mtx.elements[cov_indexes[j]] * 32767 / max_value;
|
|
destOffset = shared.loadedVertexCount * 16 + (i3 * 4 + 3) * 4;
|
|
const col3 = new Color(u_buffer[32 * i3 + 24 + 0] / 255, u_buffer[32 * i3 + 24 + 1] / 255, u_buffer[32 * i3 + 24 + 2] / 255);
|
|
col3.convertSRGBToLinear();
|
|
covAndColorData_uint8[destOffset + 0] = col3.r * 255;
|
|
covAndColorData_uint8[destOffset + 1] = col3.g * 255;
|
|
covAndColorData_uint8[destOffset + 2] = col3.b * 255;
|
|
covAndColorData_uint8[destOffset + 3] = u_buffer[32 * i3 + 24 + 3];
|
|
mtx.elements[15] = Math.max(scale5.x, scale5.y, scale5.z) * u_buffer[32 * i3 + 24 + 3] / 255;
|
|
for (let j = 0; j < 16; j++) matrices[i3 * 16 + j] = mtx.elements[j];
|
|
}
|
|
while (vertexCount > 0) {
|
|
let width = 0;
|
|
let height = 0;
|
|
const xoffset = shared.loadedVertexCount % shared.bufferTextureWidth;
|
|
const yoffset = Math.floor(shared.loadedVertexCount / shared.bufferTextureWidth);
|
|
if (shared.loadedVertexCount % shared.bufferTextureWidth != 0) {
|
|
width = Math.min(shared.bufferTextureWidth, xoffset + vertexCount) - xoffset;
|
|
height = 1;
|
|
} else if (Math.floor(vertexCount / shared.bufferTextureWidth) > 0) {
|
|
width = shared.bufferTextureWidth;
|
|
height = Math.floor(vertexCount / shared.bufferTextureWidth);
|
|
} else {
|
|
width = vertexCount % shared.bufferTextureWidth;
|
|
height = 1;
|
|
}
|
|
const centerAndScaleTextureProperties = shared.gl.properties.get(shared.centerAndScaleTexture);
|
|
context12.bindTexture(context12.TEXTURE_2D, centerAndScaleTextureProperties.__webglTexture);
|
|
context12.texSubImage2D(context12.TEXTURE_2D, 0, xoffset, yoffset, width, height, context12.RGBA, context12.FLOAT, shared.centerAndScaleData, shared.loadedVertexCount * 4);
|
|
const covAndColorTextureProperties = shared.gl.properties.get(shared.covAndColorTexture);
|
|
context12.bindTexture(context12.TEXTURE_2D, covAndColorTextureProperties.__webglTexture);
|
|
context12.texSubImage2D(
|
|
context12.TEXTURE_2D,
|
|
0,
|
|
xoffset,
|
|
yoffset,
|
|
width,
|
|
height,
|
|
// @ts-ignore
|
|
context12.RGBA_INTEGER,
|
|
context12.UNSIGNED_INT,
|
|
shared.covAndColorData,
|
|
shared.loadedVertexCount * 4
|
|
);
|
|
shared.gl.resetState();
|
|
shared.loadedVertexCount += width * height;
|
|
vertexCount -= width * height;
|
|
}
|
|
return matrices;
|
|
}
|
|
function Splat({
|
|
src,
|
|
toneMapped = false,
|
|
alphaTest = 0,
|
|
alphaHash = false,
|
|
chunkSize = 25e3,
|
|
...props
|
|
}) {
|
|
extend({
|
|
SplatMaterial
|
|
});
|
|
const ref = React38.useRef(null);
|
|
const gl = useThree((state) => state.gl);
|
|
const camera = useThree((state) => state.camera);
|
|
const shared = useLoader(SplatLoader, src, (loader2) => {
|
|
loader2.gl = gl;
|
|
loader2.chunkSize = chunkSize;
|
|
});
|
|
React38.useLayoutEffect(() => shared.connect(ref.current), [src]);
|
|
useFrame(() => shared.update(ref.current, camera, alphaHash));
|
|
return React38.createElement("mesh", _extends({
|
|
ref,
|
|
frustumCulled: false
|
|
}, props), React38.createElement("splatMaterial", {
|
|
key: `${src}/${alphaTest}/${alphaHash}${SplatMaterial.key}`,
|
|
transparent: !alphaHash,
|
|
depthTest: true,
|
|
alphaTest: alphaHash ? 0 : alphaTest,
|
|
centerAndScaleTexture: shared.centerAndScaleTexture,
|
|
covAndColorTexture: shared.covAndColorTexture,
|
|
depthWrite: alphaHash ? true : alphaTest > 0,
|
|
blending: alphaHash ? NormalBlending : CustomBlending,
|
|
blendSrcAlpha: OneFactor,
|
|
alphaHash: !!alphaHash,
|
|
toneMapped
|
|
}));
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/OrthographicCamera.js
|
|
var React40 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/core/Fbo.js
|
|
var React39 = __toESM(require_react());
|
|
var import_react9 = __toESM(require_react());
|
|
function useFBO(width, height, settings) {
|
|
const size = useThree((state) => state.size);
|
|
const viewport = useThree((state) => state.viewport);
|
|
const _width = typeof width === "number" ? width : size.width * viewport.dpr;
|
|
const _height = typeof height === "number" ? height : size.height * viewport.dpr;
|
|
const _settings = (typeof width === "number" ? settings : width) || {};
|
|
const {
|
|
samples = 0,
|
|
depth,
|
|
...targetSettings
|
|
} = _settings;
|
|
const depthBuffer = depth !== null && depth !== void 0 ? depth : _settings.depthBuffer;
|
|
const target2 = React39.useMemo(() => {
|
|
const target3 = new WebGLRenderTarget(_width, _height, {
|
|
minFilter: LinearFilter,
|
|
magFilter: LinearFilter,
|
|
type: HalfFloatType,
|
|
...targetSettings
|
|
});
|
|
if (depthBuffer) {
|
|
target3.depthTexture = new DepthTexture(_width, _height, FloatType);
|
|
}
|
|
target3.samples = samples;
|
|
return target3;
|
|
}, []);
|
|
React39.useLayoutEffect(() => {
|
|
target2.setSize(_width, _height);
|
|
if (samples) target2.samples = samples;
|
|
}, [samples, target2, _width, _height]);
|
|
React39.useEffect(() => {
|
|
return () => target2.dispose();
|
|
}, []);
|
|
return target2;
|
|
}
|
|
var Fbo = (0, import_react9.forwardRef)(({
|
|
children,
|
|
width,
|
|
height,
|
|
...settings
|
|
}, fref) => {
|
|
const target2 = useFBO(width, height, settings);
|
|
(0, import_react9.useImperativeHandle)(fref, () => target2, [target2]);
|
|
return React39.createElement(React39.Fragment, null, children == null ? void 0 : children(target2));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/OrthographicCamera.js
|
|
var isFunction = (node) => typeof node === "function";
|
|
var OrthographicCamera2 = React40.forwardRef(({
|
|
envMap,
|
|
resolution = 256,
|
|
frames = Infinity,
|
|
children,
|
|
makeDefault,
|
|
...props
|
|
}, ref) => {
|
|
const set = useThree(({
|
|
set: set2
|
|
}) => set2);
|
|
const camera = useThree(({
|
|
camera: camera2
|
|
}) => camera2);
|
|
const size = useThree(({
|
|
size: size2
|
|
}) => size2);
|
|
const cameraRef = React40.useRef(null);
|
|
React40.useImperativeHandle(ref, () => cameraRef.current, []);
|
|
const groupRef = React40.useRef(null);
|
|
const fbo = useFBO(resolution);
|
|
React40.useLayoutEffect(() => {
|
|
if (!props.manual) {
|
|
cameraRef.current.updateProjectionMatrix();
|
|
}
|
|
}, [size, props]);
|
|
React40.useLayoutEffect(() => {
|
|
cameraRef.current.updateProjectionMatrix();
|
|
});
|
|
React40.useLayoutEffect(() => {
|
|
if (makeDefault) {
|
|
const oldCam = camera;
|
|
set(() => ({
|
|
camera: cameraRef.current
|
|
}));
|
|
return () => set(() => ({
|
|
camera: oldCam
|
|
}));
|
|
}
|
|
}, [cameraRef, makeDefault, set]);
|
|
let count = 0;
|
|
let oldEnvMap = null;
|
|
const functional = isFunction(children);
|
|
useFrame((state) => {
|
|
if (functional && (frames === Infinity || count < frames)) {
|
|
groupRef.current.visible = false;
|
|
state.gl.setRenderTarget(fbo);
|
|
oldEnvMap = state.scene.background;
|
|
if (envMap) state.scene.background = envMap;
|
|
state.gl.render(state.scene, cameraRef.current);
|
|
state.scene.background = oldEnvMap;
|
|
state.gl.setRenderTarget(null);
|
|
groupRef.current.visible = true;
|
|
count++;
|
|
}
|
|
});
|
|
return React40.createElement(React40.Fragment, null, React40.createElement("orthographicCamera", _extends({
|
|
left: size.width / -2,
|
|
right: size.width / 2,
|
|
top: size.height / 2,
|
|
bottom: size.height / -2,
|
|
ref: cameraRef
|
|
}, props), !functional && children), React40.createElement("group", {
|
|
ref: groupRef
|
|
}, functional && children(fbo.texture)));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/PerspectiveCamera.js
|
|
var React41 = __toESM(require_react());
|
|
var isFunction2 = (node) => typeof node === "function";
|
|
var PerspectiveCamera2 = React41.forwardRef(({
|
|
envMap,
|
|
resolution = 256,
|
|
frames = Infinity,
|
|
makeDefault,
|
|
children,
|
|
...props
|
|
}, ref) => {
|
|
const set = useThree(({
|
|
set: set2
|
|
}) => set2);
|
|
const camera = useThree(({
|
|
camera: camera2
|
|
}) => camera2);
|
|
const size = useThree(({
|
|
size: size2
|
|
}) => size2);
|
|
const cameraRef = React41.useRef(null);
|
|
React41.useImperativeHandle(ref, () => cameraRef.current, []);
|
|
const groupRef = React41.useRef(null);
|
|
const fbo = useFBO(resolution);
|
|
React41.useLayoutEffect(() => {
|
|
if (!props.manual) {
|
|
cameraRef.current.aspect = size.width / size.height;
|
|
}
|
|
}, [size, props]);
|
|
React41.useLayoutEffect(() => {
|
|
cameraRef.current.updateProjectionMatrix();
|
|
});
|
|
let count = 0;
|
|
let oldEnvMap = null;
|
|
const functional = isFunction2(children);
|
|
useFrame((state) => {
|
|
if (functional && (frames === Infinity || count < frames)) {
|
|
groupRef.current.visible = false;
|
|
state.gl.setRenderTarget(fbo);
|
|
oldEnvMap = state.scene.background;
|
|
if (envMap) state.scene.background = envMap;
|
|
state.gl.render(state.scene, cameraRef.current);
|
|
state.scene.background = oldEnvMap;
|
|
state.gl.setRenderTarget(null);
|
|
groupRef.current.visible = true;
|
|
count++;
|
|
}
|
|
});
|
|
React41.useLayoutEffect(() => {
|
|
if (makeDefault) {
|
|
const oldCam = camera;
|
|
set(() => ({
|
|
camera: cameraRef.current
|
|
}));
|
|
return () => set(() => ({
|
|
camera: oldCam
|
|
}));
|
|
}
|
|
}, [cameraRef, makeDefault, set]);
|
|
return React41.createElement(React41.Fragment, null, React41.createElement("perspectiveCamera", _extends({
|
|
ref: cameraRef
|
|
}, props), !functional && children), React41.createElement("group", {
|
|
ref: groupRef
|
|
}, functional && children(fbo.texture)));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/CubeCamera.js
|
|
var React42 = __toESM(require_react());
|
|
var import_react10 = __toESM(require_react());
|
|
function useCubeCamera({
|
|
resolution = 256,
|
|
near = 0.1,
|
|
far = 1e3,
|
|
envMap,
|
|
fog
|
|
} = {}) {
|
|
const gl = useThree(({
|
|
gl: gl2
|
|
}) => gl2);
|
|
const scene = useThree(({
|
|
scene: scene2
|
|
}) => scene2);
|
|
const fbo = (0, import_react10.useMemo)(() => {
|
|
const fbo2 = new WebGLCubeRenderTarget(resolution);
|
|
fbo2.texture.type = HalfFloatType;
|
|
return fbo2;
|
|
}, [resolution]);
|
|
(0, import_react10.useEffect)(() => {
|
|
return () => {
|
|
fbo.dispose();
|
|
};
|
|
}, [fbo]);
|
|
const camera = (0, import_react10.useMemo)(() => new CubeCamera(near, far, fbo), [near, far, fbo]);
|
|
let originalFog;
|
|
let originalBackground;
|
|
const update2 = React42.useCallback(() => {
|
|
originalFog = scene.fog;
|
|
originalBackground = scene.background;
|
|
scene.background = envMap || originalBackground;
|
|
scene.fog = fog || originalFog;
|
|
camera.update(gl, scene);
|
|
scene.fog = originalFog;
|
|
scene.background = originalBackground;
|
|
}, [gl, scene, camera]);
|
|
return {
|
|
fbo,
|
|
camera,
|
|
update: update2
|
|
};
|
|
}
|
|
function CubeCamera2({
|
|
children,
|
|
frames = Infinity,
|
|
resolution,
|
|
near,
|
|
far,
|
|
envMap,
|
|
fog,
|
|
...props
|
|
}) {
|
|
const ref = React42.useRef(null);
|
|
const {
|
|
fbo,
|
|
camera,
|
|
update: update2
|
|
} = useCubeCamera({
|
|
resolution,
|
|
near,
|
|
far,
|
|
envMap,
|
|
fog
|
|
});
|
|
let count = 0;
|
|
useFrame(() => {
|
|
if (ref.current && (frames === Infinity || count < frames)) {
|
|
ref.current.visible = false;
|
|
update2();
|
|
ref.current.visible = true;
|
|
count++;
|
|
}
|
|
});
|
|
return React42.createElement("group", props, React42.createElement("primitive", {
|
|
object: camera
|
|
}), React42.createElement("group", {
|
|
ref
|
|
}, children == null ? void 0 : children(fbo.texture)));
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/DeviceOrientationControls.js
|
|
var React43 = __toESM(require_react());
|
|
var DeviceOrientationControls2 = React43.forwardRef((props, ref) => {
|
|
const {
|
|
camera,
|
|
onChange,
|
|
makeDefault,
|
|
...rest
|
|
} = props;
|
|
const defaultCamera = useThree((state) => state.camera);
|
|
const invalidate = useThree((state) => state.invalidate);
|
|
const get = useThree((state) => state.get);
|
|
const set = useThree((state) => state.set);
|
|
const explCamera = camera || defaultCamera;
|
|
const controls = React43.useMemo(() => new DeviceOrientationControls(explCamera), [explCamera]);
|
|
React43.useEffect(() => {
|
|
const callback = (e2) => {
|
|
invalidate();
|
|
if (onChange) onChange(e2);
|
|
};
|
|
controls == null || controls.addEventListener == null || controls.addEventListener("change", callback);
|
|
return () => controls == null || controls.removeEventListener == null ? void 0 : controls.removeEventListener("change", callback);
|
|
}, [onChange, controls, invalidate]);
|
|
useFrame(() => controls == null ? void 0 : controls.update(), -1);
|
|
React43.useEffect(() => {
|
|
const current = controls;
|
|
current == null || current.connect();
|
|
return () => current == null ? void 0 : current.dispose();
|
|
}, [controls]);
|
|
React43.useEffect(() => {
|
|
if (makeDefault) {
|
|
const old = get().controls;
|
|
set({
|
|
controls
|
|
});
|
|
return () => set({
|
|
controls: old
|
|
});
|
|
}
|
|
}, [makeDefault, controls]);
|
|
return controls ? React43.createElement("primitive", _extends({
|
|
ref,
|
|
object: controls
|
|
}, rest)) : null;
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/FlyControls.js
|
|
var React44 = __toESM(require_react());
|
|
var FlyControls2 = React44.forwardRef(({
|
|
domElement,
|
|
...props
|
|
}, fref) => {
|
|
const {
|
|
onChange,
|
|
makeDefault,
|
|
...rest
|
|
} = props;
|
|
const invalidate = useThree((state) => state.invalidate);
|
|
const camera = useThree((state) => state.camera);
|
|
const gl = useThree((state) => state.gl);
|
|
const events = useThree((state) => state.events);
|
|
const get = useThree((state) => state.get);
|
|
const set = useThree((state) => state.set);
|
|
const explDomElement = domElement || events.connected || gl.domElement;
|
|
const controls = React44.useMemo(() => new FlyControls(camera), [camera]);
|
|
React44.useEffect(() => {
|
|
controls.connect(explDomElement);
|
|
return () => void controls.dispose();
|
|
}, [explDomElement, controls, invalidate]);
|
|
React44.useEffect(() => {
|
|
const callback = (e2) => {
|
|
invalidate();
|
|
if (onChange) onChange(e2);
|
|
};
|
|
controls.addEventListener == null || controls.addEventListener("change", callback);
|
|
return () => controls.removeEventListener == null ? void 0 : controls.removeEventListener("change", callback);
|
|
}, [onChange, invalidate]);
|
|
React44.useEffect(() => {
|
|
if (makeDefault) {
|
|
const old = get().controls;
|
|
set({
|
|
controls
|
|
});
|
|
return () => set({
|
|
controls: old
|
|
});
|
|
}
|
|
}, [makeDefault, controls]);
|
|
useFrame((_, delta) => controls.update(delta));
|
|
return React44.createElement("primitive", _extends({
|
|
ref: fref,
|
|
object: controls,
|
|
args: [camera, explDomElement]
|
|
}, rest));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/MapControls.js
|
|
var React45 = __toESM(require_react());
|
|
var MapControls2 = React45.forwardRef((props = {
|
|
enableDamping: true
|
|
}, ref) => {
|
|
const {
|
|
domElement,
|
|
camera,
|
|
makeDefault,
|
|
onChange,
|
|
onStart,
|
|
onEnd,
|
|
...rest
|
|
} = props;
|
|
const invalidate = useThree((state) => state.invalidate);
|
|
const defaultCamera = useThree((state) => state.camera);
|
|
const gl = useThree((state) => state.gl);
|
|
const events = useThree((state) => state.events);
|
|
const set = useThree((state) => state.set);
|
|
const get = useThree((state) => state.get);
|
|
const explDomElement = domElement || events.connected || gl.domElement;
|
|
const explCamera = camera || defaultCamera;
|
|
const controls = React45.useMemo(() => new MapControls(explCamera), [explCamera]);
|
|
React45.useEffect(() => {
|
|
controls.connect(explDomElement);
|
|
const callback = (e2) => {
|
|
invalidate();
|
|
if (onChange) onChange(e2);
|
|
};
|
|
controls.addEventListener("change", callback);
|
|
if (onStart) controls.addEventListener("start", onStart);
|
|
if (onEnd) controls.addEventListener("end", onEnd);
|
|
return () => {
|
|
controls.dispose();
|
|
controls.removeEventListener("change", callback);
|
|
if (onStart) controls.removeEventListener("start", onStart);
|
|
if (onEnd) controls.removeEventListener("end", onEnd);
|
|
};
|
|
}, [onChange, onStart, onEnd, controls, invalidate, explDomElement]);
|
|
React45.useEffect(() => {
|
|
if (makeDefault) {
|
|
const old = get().controls;
|
|
set({
|
|
controls
|
|
});
|
|
return () => set({
|
|
controls: old
|
|
});
|
|
}
|
|
}, [makeDefault, controls]);
|
|
useFrame(() => controls.update(), -1);
|
|
return React45.createElement("primitive", _extends({
|
|
ref,
|
|
object: controls,
|
|
enableDamping: true
|
|
}, rest));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/OrbitControls.js
|
|
var React46 = __toESM(require_react());
|
|
var OrbitControls2 = React46.forwardRef(({
|
|
makeDefault,
|
|
camera,
|
|
regress,
|
|
domElement,
|
|
enableDamping = true,
|
|
keyEvents = false,
|
|
onChange,
|
|
onStart,
|
|
onEnd,
|
|
...restProps
|
|
}, ref) => {
|
|
const invalidate = useThree((state) => state.invalidate);
|
|
const defaultCamera = useThree((state) => state.camera);
|
|
const gl = useThree((state) => state.gl);
|
|
const events = useThree((state) => state.events);
|
|
const setEvents = useThree((state) => state.setEvents);
|
|
const set = useThree((state) => state.set);
|
|
const get = useThree((state) => state.get);
|
|
const performance2 = useThree((state) => state.performance);
|
|
const explCamera = camera || defaultCamera;
|
|
const explDomElement = domElement || events.connected || gl.domElement;
|
|
const controls = React46.useMemo(() => new OrbitControls(explCamera), [explCamera]);
|
|
useFrame(() => {
|
|
if (controls.enabled) controls.update();
|
|
}, -1);
|
|
React46.useEffect(() => {
|
|
if (keyEvents) {
|
|
controls.connect(keyEvents === true ? explDomElement : keyEvents);
|
|
}
|
|
controls.connect(explDomElement);
|
|
return () => void controls.dispose();
|
|
}, [keyEvents, explDomElement, regress, controls, invalidate]);
|
|
React46.useEffect(() => {
|
|
const callback = (e2) => {
|
|
invalidate();
|
|
if (regress) performance2.regress();
|
|
if (onChange) onChange(e2);
|
|
};
|
|
const onStartCb = (e2) => {
|
|
if (onStart) onStart(e2);
|
|
};
|
|
const onEndCb = (e2) => {
|
|
if (onEnd) onEnd(e2);
|
|
};
|
|
controls.addEventListener("change", callback);
|
|
controls.addEventListener("start", onStartCb);
|
|
controls.addEventListener("end", onEndCb);
|
|
return () => {
|
|
controls.removeEventListener("start", onStartCb);
|
|
controls.removeEventListener("end", onEndCb);
|
|
controls.removeEventListener("change", callback);
|
|
};
|
|
}, [onChange, onStart, onEnd, controls, invalidate, setEvents]);
|
|
React46.useEffect(() => {
|
|
if (makeDefault) {
|
|
const old = get().controls;
|
|
set({
|
|
controls
|
|
});
|
|
return () => set({
|
|
controls: old
|
|
});
|
|
}
|
|
}, [makeDefault, controls]);
|
|
return React46.createElement("primitive", _extends({
|
|
ref,
|
|
object: controls,
|
|
enableDamping
|
|
}, restProps));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/TrackballControls.js
|
|
var React47 = __toESM(require_react());
|
|
var TrackballControls2 = React47.forwardRef(({
|
|
makeDefault,
|
|
camera,
|
|
domElement,
|
|
regress,
|
|
onChange,
|
|
onStart,
|
|
onEnd,
|
|
...restProps
|
|
}, ref) => {
|
|
const {
|
|
invalidate,
|
|
camera: defaultCamera,
|
|
gl,
|
|
events,
|
|
set,
|
|
get,
|
|
performance: performance2,
|
|
viewport
|
|
} = useThree();
|
|
const explCamera = camera || defaultCamera;
|
|
const explDomElement = domElement || events.connected || gl.domElement;
|
|
const controls = React47.useMemo(() => new TrackballControls(explCamera), [explCamera]);
|
|
useFrame(() => {
|
|
if (controls.enabled) controls.update();
|
|
}, -1);
|
|
React47.useEffect(() => {
|
|
controls.connect(explDomElement);
|
|
return () => void controls.dispose();
|
|
}, [explDomElement, regress, controls, invalidate]);
|
|
React47.useEffect(() => {
|
|
const callback = (e2) => {
|
|
invalidate();
|
|
if (regress) performance2.regress();
|
|
if (onChange) onChange(e2);
|
|
};
|
|
controls.addEventListener("change", callback);
|
|
if (onStart) controls.addEventListener("start", onStart);
|
|
if (onEnd) controls.addEventListener("end", onEnd);
|
|
return () => {
|
|
if (onStart) controls.removeEventListener("start", onStart);
|
|
if (onEnd) controls.removeEventListener("end", onEnd);
|
|
controls.removeEventListener("change", callback);
|
|
};
|
|
}, [onChange, onStart, onEnd, controls, invalidate]);
|
|
React47.useEffect(() => {
|
|
controls.handleResize();
|
|
}, [viewport]);
|
|
React47.useEffect(() => {
|
|
if (makeDefault) {
|
|
const old = get().controls;
|
|
set({
|
|
controls
|
|
});
|
|
return () => set({
|
|
controls: old
|
|
});
|
|
}
|
|
}, [makeDefault, controls]);
|
|
return React47.createElement("primitive", _extends({
|
|
ref,
|
|
object: controls
|
|
}, restProps));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/ArcballControls.js
|
|
var React48 = __toESM(require_react());
|
|
var import_react11 = __toESM(require_react());
|
|
var ArcballControls2 = (0, import_react11.forwardRef)(({
|
|
camera,
|
|
makeDefault,
|
|
regress,
|
|
domElement,
|
|
onChange,
|
|
onStart,
|
|
onEnd,
|
|
...restProps
|
|
}, ref) => {
|
|
const invalidate = useThree((state) => state.invalidate);
|
|
const defaultCamera = useThree((state) => state.camera);
|
|
const gl = useThree((state) => state.gl);
|
|
const events = useThree((state) => state.events);
|
|
const set = useThree((state) => state.set);
|
|
const get = useThree((state) => state.get);
|
|
const performance2 = useThree((state) => state.performance);
|
|
const explCamera = camera || defaultCamera;
|
|
const explDomElement = domElement || events.connected || gl.domElement;
|
|
const controls = (0, import_react11.useMemo)(() => new ArcballControls(explCamera), [explCamera]);
|
|
useFrame(() => {
|
|
if (controls.enabled) controls.update();
|
|
}, -1);
|
|
(0, import_react11.useEffect)(() => {
|
|
controls.connect(explDomElement);
|
|
return () => void controls.dispose();
|
|
}, [explDomElement, regress, controls, invalidate]);
|
|
(0, import_react11.useEffect)(() => {
|
|
const callback = (e2) => {
|
|
invalidate();
|
|
if (regress) performance2.regress();
|
|
if (onChange) onChange(e2);
|
|
};
|
|
controls.addEventListener("change", callback);
|
|
if (onStart) controls.addEventListener("start", onStart);
|
|
if (onEnd) controls.addEventListener("end", onEnd);
|
|
return () => {
|
|
controls.removeEventListener("change", callback);
|
|
if (onStart) controls.removeEventListener("start", onStart);
|
|
if (onEnd) controls.removeEventListener("end", onEnd);
|
|
};
|
|
}, [onChange, onStart, onEnd]);
|
|
(0, import_react11.useEffect)(() => {
|
|
if (makeDefault) {
|
|
const old = get().controls;
|
|
set({
|
|
controls
|
|
});
|
|
return () => set({
|
|
controls: old
|
|
});
|
|
}
|
|
}, [makeDefault, controls]);
|
|
return React48.createElement("primitive", _extends({
|
|
ref,
|
|
object: controls
|
|
}, restProps));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/TransformControls.js
|
|
var React49 = __toESM(require_react());
|
|
var TransformControls2 = React49.forwardRef(({
|
|
children,
|
|
domElement,
|
|
onChange,
|
|
onMouseDown,
|
|
onMouseUp,
|
|
onObjectChange,
|
|
object,
|
|
makeDefault,
|
|
camera,
|
|
// Transform
|
|
enabled,
|
|
axis,
|
|
mode,
|
|
translationSnap,
|
|
rotationSnap,
|
|
scaleSnap,
|
|
space,
|
|
size,
|
|
showX,
|
|
showY,
|
|
showZ,
|
|
...props
|
|
}, ref) => {
|
|
const defaultControls = useThree((state) => state.controls);
|
|
const gl = useThree((state) => state.gl);
|
|
const events = useThree((state) => state.events);
|
|
const defaultCamera = useThree((state) => state.camera);
|
|
const invalidate = useThree((state) => state.invalidate);
|
|
const get = useThree((state) => state.get);
|
|
const set = useThree((state) => state.set);
|
|
const explCamera = camera || defaultCamera;
|
|
const explDomElement = domElement || events.connected || gl.domElement;
|
|
const controls = React49.useMemo(() => new TransformControls(explCamera, explDomElement), [explCamera, explDomElement]);
|
|
const group = React49.useRef(null);
|
|
React49.useLayoutEffect(() => {
|
|
if (object) {
|
|
controls.attach(object instanceof Object3D ? object : object.current);
|
|
} else if (group.current instanceof Object3D) {
|
|
controls.attach(group.current);
|
|
}
|
|
return () => void controls.detach();
|
|
}, [object, children, controls]);
|
|
React49.useEffect(() => {
|
|
if (defaultControls) {
|
|
const callback = (event) => defaultControls.enabled = !event.value;
|
|
controls.addEventListener("dragging-changed", callback);
|
|
return () => controls.removeEventListener("dragging-changed", callback);
|
|
}
|
|
}, [controls, defaultControls]);
|
|
const onChangeRef = React49.useRef(void 0);
|
|
const onMouseDownRef = React49.useRef(void 0);
|
|
const onMouseUpRef = React49.useRef(void 0);
|
|
const onObjectChangeRef = React49.useRef(void 0);
|
|
React49.useLayoutEffect(() => void (onChangeRef.current = onChange), [onChange]);
|
|
React49.useLayoutEffect(() => void (onMouseDownRef.current = onMouseDown), [onMouseDown]);
|
|
React49.useLayoutEffect(() => void (onMouseUpRef.current = onMouseUp), [onMouseUp]);
|
|
React49.useLayoutEffect(() => void (onObjectChangeRef.current = onObjectChange), [onObjectChange]);
|
|
React49.useEffect(() => {
|
|
const onChange2 = (e2) => {
|
|
invalidate();
|
|
onChangeRef.current == null || onChangeRef.current(e2);
|
|
};
|
|
const onMouseDown2 = (e2) => onMouseDownRef.current == null ? void 0 : onMouseDownRef.current(e2);
|
|
const onMouseUp2 = (e2) => onMouseUpRef.current == null ? void 0 : onMouseUpRef.current(e2);
|
|
const onObjectChange2 = (e2) => onObjectChangeRef.current == null ? void 0 : onObjectChangeRef.current(e2);
|
|
controls.addEventListener("change", onChange2);
|
|
controls.addEventListener("mouseDown", onMouseDown2);
|
|
controls.addEventListener("mouseUp", onMouseUp2);
|
|
controls.addEventListener("objectChange", onObjectChange2);
|
|
return () => {
|
|
controls.removeEventListener("change", onChange2);
|
|
controls.removeEventListener("mouseDown", onMouseDown2);
|
|
controls.removeEventListener("mouseUp", onMouseUp2);
|
|
controls.removeEventListener("objectChange", onObjectChange2);
|
|
};
|
|
}, [invalidate, controls]);
|
|
React49.useEffect(() => {
|
|
if (makeDefault) {
|
|
const old = get().controls;
|
|
set({
|
|
controls
|
|
});
|
|
return () => set({
|
|
controls: old
|
|
});
|
|
}
|
|
}, [makeDefault, controls]);
|
|
return React49.createElement(React49.Fragment, null, React49.createElement("primitive", {
|
|
ref,
|
|
object: controls,
|
|
enabled,
|
|
axis,
|
|
mode,
|
|
translationSnap,
|
|
rotationSnap,
|
|
scaleSnap,
|
|
space,
|
|
size,
|
|
showX,
|
|
showY,
|
|
showZ
|
|
}), React49.createElement("group", _extends({
|
|
ref: group
|
|
}, props), children));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/PointerLockControls.js
|
|
var React50 = __toESM(require_react());
|
|
var PointerLockControls2 = React50.forwardRef(({
|
|
domElement,
|
|
selector,
|
|
onChange,
|
|
onLock,
|
|
onUnlock,
|
|
enabled = true,
|
|
makeDefault,
|
|
...props
|
|
}, ref) => {
|
|
const {
|
|
camera,
|
|
...rest
|
|
} = props;
|
|
const setEvents = useThree((state) => state.setEvents);
|
|
const gl = useThree((state) => state.gl);
|
|
const defaultCamera = useThree((state) => state.camera);
|
|
const invalidate = useThree((state) => state.invalidate);
|
|
const events = useThree((state) => state.events);
|
|
const get = useThree((state) => state.get);
|
|
const set = useThree((state) => state.set);
|
|
const explCamera = camera || defaultCamera;
|
|
const explDomElement = domElement || events.connected || gl.domElement;
|
|
const controls = React50.useMemo(() => new PointerLockControls(explCamera), [explCamera]);
|
|
React50.useEffect(() => {
|
|
if (enabled) {
|
|
controls.connect(explDomElement);
|
|
const oldComputeOffsets = get().events.compute;
|
|
setEvents({
|
|
compute(event, state) {
|
|
const offsetX = state.size.width / 2;
|
|
const offsetY = state.size.height / 2;
|
|
state.pointer.set(offsetX / state.size.width * 2 - 1, -(offsetY / state.size.height) * 2 + 1);
|
|
state.raycaster.setFromCamera(state.pointer, state.camera);
|
|
}
|
|
});
|
|
return () => {
|
|
controls.disconnect();
|
|
setEvents({
|
|
compute: oldComputeOffsets
|
|
});
|
|
};
|
|
}
|
|
}, [enabled, controls]);
|
|
React50.useEffect(() => {
|
|
const callback = (e2) => {
|
|
invalidate();
|
|
if (onChange) onChange(e2);
|
|
};
|
|
controls.addEventListener("change", callback);
|
|
if (onLock) controls.addEventListener("lock", onLock);
|
|
if (onUnlock) controls.addEventListener("unlock", onUnlock);
|
|
const handler = () => controls.lock();
|
|
const elements = selector ? Array.from(document.querySelectorAll(selector)) : [document];
|
|
elements.forEach((element) => element && element.addEventListener("click", handler));
|
|
return () => {
|
|
controls.removeEventListener("change", callback);
|
|
if (onLock) controls.removeEventListener("lock", onLock);
|
|
if (onUnlock) controls.removeEventListener("unlock", onUnlock);
|
|
elements.forEach((element) => element ? element.removeEventListener("click", handler) : void 0);
|
|
};
|
|
}, [onChange, onLock, onUnlock, selector, controls, invalidate]);
|
|
React50.useEffect(() => {
|
|
if (makeDefault) {
|
|
const old = get().controls;
|
|
set({
|
|
controls
|
|
});
|
|
return () => set({
|
|
controls: old
|
|
});
|
|
}
|
|
}, [makeDefault, controls]);
|
|
return React50.createElement("primitive", _extends({
|
|
ref,
|
|
object: controls
|
|
}, rest));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/FirstPersonControls.js
|
|
var React51 = __toESM(require_react());
|
|
var FirstPersonControls2 = React51.forwardRef(({
|
|
domElement,
|
|
makeDefault,
|
|
...props
|
|
}, ref) => {
|
|
const camera = useThree((state) => state.camera);
|
|
const gl = useThree((state) => state.gl);
|
|
const events = useThree((state) => state.events);
|
|
const get = useThree((state) => state.get);
|
|
const set = useThree((state) => state.set);
|
|
const explDomElement = domElement || events.connected || gl.domElement;
|
|
const [controls] = React51.useState(() => new FirstPersonControls(camera, explDomElement));
|
|
React51.useEffect(() => {
|
|
if (makeDefault) {
|
|
const old = get().controls;
|
|
set({
|
|
controls
|
|
});
|
|
return () => set({
|
|
controls: old
|
|
});
|
|
}
|
|
}, [makeDefault, controls]);
|
|
useFrame((_, delta) => {
|
|
controls.update(delta);
|
|
}, -1);
|
|
return controls ? React51.createElement("primitive", _extends({
|
|
ref,
|
|
object: controls
|
|
}, props)) : null;
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/CameraControls.js
|
|
var React52 = __toESM(require_react());
|
|
var import_react12 = __toESM(require_react());
|
|
|
|
// node_modules/camera-controls/dist/camera-controls.module.js
|
|
var MOUSE_BUTTON = {
|
|
LEFT: 1,
|
|
RIGHT: 2,
|
|
MIDDLE: 4
|
|
};
|
|
var ACTION = Object.freeze({
|
|
NONE: 0,
|
|
ROTATE: 1,
|
|
TRUCK: 2,
|
|
SCREEN_PAN: 4,
|
|
OFFSET: 8,
|
|
DOLLY: 16,
|
|
ZOOM: 32,
|
|
TOUCH_ROTATE: 64,
|
|
TOUCH_TRUCK: 128,
|
|
TOUCH_SCREEN_PAN: 256,
|
|
TOUCH_OFFSET: 512,
|
|
TOUCH_DOLLY: 1024,
|
|
TOUCH_ZOOM: 2048,
|
|
TOUCH_DOLLY_TRUCK: 4096,
|
|
TOUCH_DOLLY_SCREEN_PAN: 8192,
|
|
TOUCH_DOLLY_OFFSET: 16384,
|
|
TOUCH_DOLLY_ROTATE: 32768,
|
|
TOUCH_ZOOM_TRUCK: 65536,
|
|
TOUCH_ZOOM_OFFSET: 131072,
|
|
TOUCH_ZOOM_SCREEN_PAN: 262144,
|
|
TOUCH_ZOOM_ROTATE: 524288
|
|
});
|
|
var DOLLY_DIRECTION = {
|
|
NONE: 0,
|
|
IN: 1,
|
|
OUT: -1
|
|
};
|
|
function isPerspectiveCamera(camera) {
|
|
return camera.isPerspectiveCamera;
|
|
}
|
|
function isOrthographicCamera(camera) {
|
|
return camera.isOrthographicCamera;
|
|
}
|
|
var PI_2 = Math.PI * 2;
|
|
var PI_HALF = Math.PI / 2;
|
|
var EPSILON = 1e-5;
|
|
var DEG2RAD = Math.PI / 180;
|
|
function clamp3(value, min, max) {
|
|
return Math.max(min, Math.min(max, value));
|
|
}
|
|
function approxZero(number, error = EPSILON) {
|
|
return Math.abs(number) < error;
|
|
}
|
|
function approxEquals(a5, b, error = EPSILON) {
|
|
return approxZero(a5 - b, error);
|
|
}
|
|
function roundToStep(value, step) {
|
|
return Math.round(value / step) * step;
|
|
}
|
|
function infinityToMaxNumber(value) {
|
|
if (isFinite(value))
|
|
return value;
|
|
if (value < 0)
|
|
return -Number.MAX_VALUE;
|
|
return Number.MAX_VALUE;
|
|
}
|
|
function maxNumberToInfinity(value) {
|
|
if (Math.abs(value) < Number.MAX_VALUE)
|
|
return value;
|
|
return value * Infinity;
|
|
}
|
|
function smoothDamp(current, target2, currentVelocityRef, smoothTime, maxSpeed = Infinity, deltaTime) {
|
|
smoothTime = Math.max(1e-4, smoothTime);
|
|
const omega = 2 / smoothTime;
|
|
const x = omega * deltaTime;
|
|
const exp3 = 1 / (1 + x + 0.48 * x * x + 0.235 * x * x * x);
|
|
let change = current - target2;
|
|
const originalTo = target2;
|
|
const maxChange = maxSpeed * smoothTime;
|
|
change = clamp3(change, -maxChange, maxChange);
|
|
target2 = current - change;
|
|
const temp5 = (currentVelocityRef.value + omega * change) * deltaTime;
|
|
currentVelocityRef.value = (currentVelocityRef.value - omega * temp5) * exp3;
|
|
let output = target2 + (change + temp5) * exp3;
|
|
if (originalTo - current > 0 === output > originalTo) {
|
|
output = originalTo;
|
|
currentVelocityRef.value = (output - originalTo) / deltaTime;
|
|
}
|
|
return output;
|
|
}
|
|
function smoothDampVec3(current, target2, currentVelocityRef, smoothTime, maxSpeed = Infinity, deltaTime, out7) {
|
|
smoothTime = Math.max(1e-4, smoothTime);
|
|
const omega = 2 / smoothTime;
|
|
const x = omega * deltaTime;
|
|
const exp3 = 1 / (1 + x + 0.48 * x * x + 0.235 * x * x * x);
|
|
let targetX = target2.x;
|
|
let targetY = target2.y;
|
|
let targetZ = target2.z;
|
|
let changeX = current.x - targetX;
|
|
let changeY = current.y - targetY;
|
|
let changeZ = current.z - targetZ;
|
|
const originalToX = targetX;
|
|
const originalToY = targetY;
|
|
const originalToZ = targetZ;
|
|
const maxChange = maxSpeed * smoothTime;
|
|
const maxChangeSq = maxChange * maxChange;
|
|
const magnitudeSq = changeX * changeX + changeY * changeY + changeZ * changeZ;
|
|
if (magnitudeSq > maxChangeSq) {
|
|
const magnitude = Math.sqrt(magnitudeSq);
|
|
changeX = changeX / magnitude * maxChange;
|
|
changeY = changeY / magnitude * maxChange;
|
|
changeZ = changeZ / magnitude * maxChange;
|
|
}
|
|
targetX = current.x - changeX;
|
|
targetY = current.y - changeY;
|
|
targetZ = current.z - changeZ;
|
|
const tempX = (currentVelocityRef.x + omega * changeX) * deltaTime;
|
|
const tempY = (currentVelocityRef.y + omega * changeY) * deltaTime;
|
|
const tempZ = (currentVelocityRef.z + omega * changeZ) * deltaTime;
|
|
currentVelocityRef.x = (currentVelocityRef.x - omega * tempX) * exp3;
|
|
currentVelocityRef.y = (currentVelocityRef.y - omega * tempY) * exp3;
|
|
currentVelocityRef.z = (currentVelocityRef.z - omega * tempZ) * exp3;
|
|
out7.x = targetX + (changeX + tempX) * exp3;
|
|
out7.y = targetY + (changeY + tempY) * exp3;
|
|
out7.z = targetZ + (changeZ + tempZ) * exp3;
|
|
const origMinusCurrentX = originalToX - current.x;
|
|
const origMinusCurrentY = originalToY - current.y;
|
|
const origMinusCurrentZ = originalToZ - current.z;
|
|
const outMinusOrigX = out7.x - originalToX;
|
|
const outMinusOrigY = out7.y - originalToY;
|
|
const outMinusOrigZ = out7.z - originalToZ;
|
|
if (origMinusCurrentX * outMinusOrigX + origMinusCurrentY * outMinusOrigY + origMinusCurrentZ * outMinusOrigZ > 0) {
|
|
out7.x = originalToX;
|
|
out7.y = originalToY;
|
|
out7.z = originalToZ;
|
|
currentVelocityRef.x = (out7.x - originalToX) / deltaTime;
|
|
currentVelocityRef.y = (out7.y - originalToY) / deltaTime;
|
|
currentVelocityRef.z = (out7.z - originalToZ) / deltaTime;
|
|
}
|
|
return out7;
|
|
}
|
|
function extractClientCoordFromEvent(pointers, out7) {
|
|
out7.set(0, 0);
|
|
pointers.forEach((pointer) => {
|
|
out7.x += pointer.clientX;
|
|
out7.y += pointer.clientY;
|
|
});
|
|
out7.x /= pointers.length;
|
|
out7.y /= pointers.length;
|
|
}
|
|
function notSupportedInOrthographicCamera(camera, message) {
|
|
if (isOrthographicCamera(camera)) {
|
|
console.warn(`${message} is not supported in OrthographicCamera`);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
var EventDispatcher2 = class {
|
|
_listeners = {};
|
|
/**
|
|
* Adds the specified event listener.
|
|
* @param type event name
|
|
* @param listener handler function
|
|
* @category Methods
|
|
*/
|
|
addEventListener(type, listener) {
|
|
const listeners = this._listeners;
|
|
if (listeners[type] === void 0)
|
|
listeners[type] = [];
|
|
if (listeners[type].indexOf(listener) === -1)
|
|
listeners[type].push(listener);
|
|
}
|
|
/**
|
|
* Presence of the specified event listener.
|
|
* @param type event name
|
|
* @param listener handler function
|
|
* @category Methods
|
|
*/
|
|
hasEventListener(type, listener) {
|
|
const listeners = this._listeners;
|
|
return listeners[type] !== void 0 && listeners[type].indexOf(listener) !== -1;
|
|
}
|
|
/**
|
|
* Removes the specified event listener
|
|
* @param type event name
|
|
* @param listener handler function
|
|
* @category Methods
|
|
*/
|
|
removeEventListener(type, listener) {
|
|
const listeners = this._listeners;
|
|
const listenerArray = listeners[type];
|
|
if (listenerArray !== void 0) {
|
|
const index2 = listenerArray.indexOf(listener);
|
|
if (index2 !== -1)
|
|
listenerArray.splice(index2, 1);
|
|
}
|
|
}
|
|
/**
|
|
* Removes all event listeners
|
|
* @param type event name
|
|
* @category Methods
|
|
*/
|
|
removeAllEventListeners(type) {
|
|
if (!type) {
|
|
this._listeners = {};
|
|
return;
|
|
}
|
|
if (Array.isArray(this._listeners[type]))
|
|
this._listeners[type].length = 0;
|
|
}
|
|
/**
|
|
* Fire an event type.
|
|
* @param event DispatcherEvent
|
|
* @category Methods
|
|
*/
|
|
dispatchEvent(event) {
|
|
const listeners = this._listeners;
|
|
const listenerArray = listeners[event.type];
|
|
if (listenerArray !== void 0) {
|
|
event.target = this;
|
|
const array = listenerArray.slice(0);
|
|
for (let i3 = 0, l2 = array.length; i3 < l2; i3++) {
|
|
array[i3].call(this, event);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var VERSION = "3.1.2";
|
|
var TOUCH_DOLLY_FACTOR = 1 / 8;
|
|
var isMac = /Mac/.test(globalThis?.navigator?.platform);
|
|
var THREE;
|
|
var _ORIGIN;
|
|
var _AXIS_Y;
|
|
var _AXIS_Z;
|
|
var _v2;
|
|
var _v3A;
|
|
var _v3B;
|
|
var _v3C;
|
|
var _cameraDirection;
|
|
var _xColumn;
|
|
var _yColumn;
|
|
var _zColumn;
|
|
var _deltaTarget;
|
|
var _deltaOffset;
|
|
var _sphericalA;
|
|
var _sphericalB;
|
|
var _box3A;
|
|
var _box3B;
|
|
var _sphere;
|
|
var _quaternionA;
|
|
var _quaternionB;
|
|
var _rotationMatrix;
|
|
var _raycaster;
|
|
var CameraControls = class _CameraControls extends EventDispatcher2 {
|
|
/**
|
|
* Injects THREE as the dependency. You can then proceed to use CameraControls.
|
|
*
|
|
* e.g
|
|
* ```javascript
|
|
* CameraControls.install( { THREE: THREE } );
|
|
* ```
|
|
*
|
|
* Note: If you do not wish to use enter three.js to reduce file size(tree-shaking for example), make a subset to install.
|
|
*
|
|
* ```js
|
|
* import {
|
|
* Vector2,
|
|
* Vector3,
|
|
* Vector4,
|
|
* Quaternion,
|
|
* Matrix4,
|
|
* Spherical,
|
|
* Box3,
|
|
* Sphere,
|
|
* Raycaster,
|
|
* MathUtils,
|
|
* } from 'three';
|
|
*
|
|
* const subsetOfTHREE = {
|
|
* Vector2 : Vector2,
|
|
* Vector3 : Vector3,
|
|
* Vector4 : Vector4,
|
|
* Quaternion: Quaternion,
|
|
* Matrix4 : Matrix4,
|
|
* Spherical : Spherical,
|
|
* Box3 : Box3,
|
|
* Sphere : Sphere,
|
|
* Raycaster : Raycaster,
|
|
* };
|
|
|
|
* CameraControls.install( { THREE: subsetOfTHREE } );
|
|
* ```
|
|
* @category Statics
|
|
*/
|
|
static install(libs) {
|
|
THREE = libs.THREE;
|
|
_ORIGIN = Object.freeze(new THREE.Vector3(0, 0, 0));
|
|
_AXIS_Y = Object.freeze(new THREE.Vector3(0, 1, 0));
|
|
_AXIS_Z = Object.freeze(new THREE.Vector3(0, 0, 1));
|
|
_v2 = new THREE.Vector2();
|
|
_v3A = new THREE.Vector3();
|
|
_v3B = new THREE.Vector3();
|
|
_v3C = new THREE.Vector3();
|
|
_cameraDirection = new THREE.Vector3();
|
|
_xColumn = new THREE.Vector3();
|
|
_yColumn = new THREE.Vector3();
|
|
_zColumn = new THREE.Vector3();
|
|
_deltaTarget = new THREE.Vector3();
|
|
_deltaOffset = new THREE.Vector3();
|
|
_sphericalA = new THREE.Spherical();
|
|
_sphericalB = new THREE.Spherical();
|
|
_box3A = new THREE.Box3();
|
|
_box3B = new THREE.Box3();
|
|
_sphere = new THREE.Sphere();
|
|
_quaternionA = new THREE.Quaternion();
|
|
_quaternionB = new THREE.Quaternion();
|
|
_rotationMatrix = new THREE.Matrix4();
|
|
_raycaster = new THREE.Raycaster();
|
|
}
|
|
/**
|
|
* list all ACTIONs
|
|
* @category Statics
|
|
*/
|
|
static get ACTION() {
|
|
return ACTION;
|
|
}
|
|
/**
|
|
* Minimum vertical angle in radians.
|
|
* The angle has to be between `0` and `.maxPolarAngle` inclusive.
|
|
* The default value is `0`.
|
|
*
|
|
* e.g.
|
|
* ```
|
|
* cameraControls.maxPolarAngle = 0;
|
|
* ```
|
|
* @category Properties
|
|
*/
|
|
minPolarAngle = 0;
|
|
// radians
|
|
/**
|
|
* Maximum vertical angle in radians.
|
|
* The angle has to be between `.maxPolarAngle` and `Math.PI` inclusive.
|
|
* The default value is `Math.PI`.
|
|
*
|
|
* e.g.
|
|
* ```
|
|
* cameraControls.maxPolarAngle = Math.PI;
|
|
* ```
|
|
* @category Properties
|
|
*/
|
|
maxPolarAngle = Math.PI;
|
|
// radians
|
|
/**
|
|
* Minimum horizontal angle in radians.
|
|
* The angle has to be less than `.maxAzimuthAngle`.
|
|
* The default value is `- Infinity`.
|
|
*
|
|
* e.g.
|
|
* ```
|
|
* cameraControls.minAzimuthAngle = - Infinity;
|
|
* ```
|
|
* @category Properties
|
|
*/
|
|
minAzimuthAngle = -Infinity;
|
|
// radians
|
|
/**
|
|
* Maximum horizontal angle in radians.
|
|
* The angle has to be greater than `.minAzimuthAngle`.
|
|
* The default value is `Infinity`.
|
|
*
|
|
* e.g.
|
|
* ```
|
|
* cameraControls.maxAzimuthAngle = Infinity;
|
|
* ```
|
|
* @category Properties
|
|
*/
|
|
maxAzimuthAngle = Infinity;
|
|
// radians
|
|
// How far you can dolly in and out ( PerspectiveCamera only )
|
|
/**
|
|
* Minimum distance for dolly. The value must be higher than `0`. Default is `Number.EPSILON`.
|
|
* PerspectiveCamera only.
|
|
* @category Properties
|
|
*/
|
|
minDistance = Number.EPSILON;
|
|
/**
|
|
* Maximum distance for dolly. The value must be higher than `minDistance`. Default is `Infinity`.
|
|
* PerspectiveCamera only.
|
|
* @category Properties
|
|
*/
|
|
maxDistance = Infinity;
|
|
/**
|
|
* `true` to enable Infinity Dolly for wheel and pinch. Use this with `minDistance` and `maxDistance`
|
|
* If the Dolly distance is less (or over) than the `minDistance` (or `maxDistance`), `infinityDolly` will keep the distance and pushes the target position instead.
|
|
* @category Properties
|
|
*/
|
|
infinityDolly = false;
|
|
/**
|
|
* Minimum camera zoom.
|
|
* @category Properties
|
|
*/
|
|
minZoom = 0.01;
|
|
/**
|
|
* Maximum camera zoom.
|
|
* @category Properties
|
|
*/
|
|
maxZoom = Infinity;
|
|
/**
|
|
* Approximate time in seconds to reach the target. A smaller value will reach the target faster.
|
|
* @category Properties
|
|
*/
|
|
smoothTime = 0.25;
|
|
/**
|
|
* the smoothTime while dragging
|
|
* @category Properties
|
|
*/
|
|
draggingSmoothTime = 0.125;
|
|
/**
|
|
* Max transition speed in unit-per-seconds
|
|
* @category Properties
|
|
*/
|
|
maxSpeed = Infinity;
|
|
/**
|
|
* Speed of azimuth (horizontal) rotation.
|
|
* @category Properties
|
|
*/
|
|
azimuthRotateSpeed = 1;
|
|
/**
|
|
* Speed of polar (vertical) rotation.
|
|
* @category Properties
|
|
*/
|
|
polarRotateSpeed = 1;
|
|
/**
|
|
* Speed of mouse-wheel dollying.
|
|
* @category Properties
|
|
*/
|
|
dollySpeed = 1;
|
|
/**
|
|
* `true` to invert direction when dollying or zooming via drag
|
|
* @category Properties
|
|
*/
|
|
dollyDragInverted = false;
|
|
/**
|
|
* Speed of drag for truck and pedestal.
|
|
* @category Properties
|
|
*/
|
|
truckSpeed = 2;
|
|
/**
|
|
* `true` to enable Dolly-in to the mouse cursor coords.
|
|
* @category Properties
|
|
*/
|
|
dollyToCursor = false;
|
|
/**
|
|
* @category Properties
|
|
*/
|
|
dragToOffset = false;
|
|
/**
|
|
* Friction ratio of the boundary.
|
|
* @category Properties
|
|
*/
|
|
boundaryFriction = 0;
|
|
/**
|
|
* Controls how soon the `rest` event fires as the camera slows.
|
|
* @category Properties
|
|
*/
|
|
restThreshold = 0.01;
|
|
/**
|
|
* An array of Meshes to collide with camera.
|
|
* Be aware colliderMeshes may decrease performance. The collision test uses 4 raycasters from the camera since the near plane has 4 corners.
|
|
* @category Properties
|
|
*/
|
|
colliderMeshes = [];
|
|
// button configs
|
|
/**
|
|
* User's mouse input config.
|
|
*
|
|
* | button to assign | behavior |
|
|
* | --------------------- | -------- |
|
|
* | `mouseButtons.left` | `CameraControls.ACTION.ROTATE`* \| `CameraControls.ACTION.TRUCK` \| `CameraControls.ACTION.OFFSET` \| `CameraControls.ACTION.DOLLY` \| `CameraControls.ACTION.ZOOM` \| `CameraControls.ACTION.NONE` |
|
|
* | `mouseButtons.right` | `CameraControls.ACTION.ROTATE` \| `CameraControls.ACTION.TRUCK`* \| `CameraControls.ACTION.OFFSET` \| `CameraControls.ACTION.DOLLY` \| `CameraControls.ACTION.ZOOM` \| `CameraControls.ACTION.NONE` |
|
|
* | `mouseButtons.wheel` ¹ | `CameraControls.ACTION.ROTATE` \| `CameraControls.ACTION.TRUCK` \| `CameraControls.ACTION.OFFSET` \| `CameraControls.ACTION.DOLLY` \| `CameraControls.ACTION.ZOOM` \| `CameraControls.ACTION.NONE` |
|
|
* | `mouseButtons.middle` ² | `CameraControls.ACTION.ROTATE` \| `CameraControls.ACTION.TRUCK` \| `CameraControls.ACTION.OFFSET` \| `CameraControls.ACTION.DOLLY`* \| `CameraControls.ACTION.ZOOM` \| `CameraControls.ACTION.NONE` |
|
|
*
|
|
* 1. Mouse wheel event for scroll "up/down" on mac "up/down/left/right"
|
|
* 2. Mouse click on wheel event "button"
|
|
* - \* is the default.
|
|
* - The default of `mouseButtons.wheel` is:
|
|
* - `DOLLY` for Perspective camera.
|
|
* - `ZOOM` for Orthographic camera, and can't set `DOLLY`.
|
|
* @category Properties
|
|
*/
|
|
mouseButtons;
|
|
/**
|
|
* User's touch input config.
|
|
*
|
|
* | fingers to assign | behavior |
|
|
* | --------------------- | -------- |
|
|
* | `touches.one` | `CameraControls.ACTION.TOUCH_ROTATE`* \| `CameraControls.ACTION.TOUCH_TRUCK` \| `CameraControls.ACTION.TOUCH_OFFSET` \| `CameraControls.ACTION.DOLLY` | `CameraControls.ACTION.ZOOM` | `CameraControls.ACTION.NONE` |
|
|
* | `touches.two` | `ACTION.TOUCH_DOLLY_TRUCK` \| `ACTION.TOUCH_DOLLY_OFFSET` \| `ACTION.TOUCH_DOLLY_ROTATE` \| `ACTION.TOUCH_ZOOM_TRUCK` \| `ACTION.TOUCH_ZOOM_OFFSET` \| `ACTION.TOUCH_ZOOM_ROTATE` \| `ACTION.TOUCH_DOLLY` \| `ACTION.TOUCH_ZOOM` \| `CameraControls.ACTION.TOUCH_ROTATE` \| `CameraControls.ACTION.TOUCH_TRUCK` \| `CameraControls.ACTION.TOUCH_OFFSET` \| `CameraControls.ACTION.NONE` |
|
|
* | `touches.three` | `ACTION.TOUCH_DOLLY_TRUCK` \| `ACTION.TOUCH_DOLLY_OFFSET` \| `ACTION.TOUCH_DOLLY_ROTATE` \| `ACTION.TOUCH_ZOOM_TRUCK` \| `ACTION.TOUCH_ZOOM_OFFSET` \| `ACTION.TOUCH_ZOOM_ROTATE` \| `CameraControls.ACTION.TOUCH_ROTATE` \| `CameraControls.ACTION.TOUCH_TRUCK` \| `CameraControls.ACTION.TOUCH_OFFSET` \| `CameraControls.ACTION.NONE` |
|
|
*
|
|
* - \* is the default.
|
|
* - The default of `touches.two` and `touches.three` is:
|
|
* - `TOUCH_DOLLY_TRUCK` for Perspective camera.
|
|
* - `TOUCH_ZOOM_TRUCK` for Orthographic camera, and can't set `TOUCH_DOLLY_TRUCK` and `TOUCH_DOLLY`.
|
|
* @category Properties
|
|
*/
|
|
touches;
|
|
/**
|
|
* Force cancel user dragging.
|
|
* @category Methods
|
|
*/
|
|
// cancel will be overwritten in the constructor.
|
|
cancel = () => {
|
|
};
|
|
/**
|
|
* Still an experimental feature.
|
|
* This could change at any time.
|
|
* @category Methods
|
|
*/
|
|
lockPointer;
|
|
/**
|
|
* Still an experimental feature.
|
|
* This could change at any time.
|
|
* @category Methods
|
|
*/
|
|
unlockPointer;
|
|
_enabled = true;
|
|
_camera;
|
|
_yAxisUpSpace;
|
|
_yAxisUpSpaceInverse;
|
|
_state = ACTION.NONE;
|
|
_domElement;
|
|
_viewport = null;
|
|
// the location of focus, where the object orbits around
|
|
_target;
|
|
_targetEnd;
|
|
_focalOffset;
|
|
_focalOffsetEnd;
|
|
// rotation and dolly distance
|
|
_spherical;
|
|
_sphericalEnd;
|
|
_lastDistance;
|
|
_zoom;
|
|
_zoomEnd;
|
|
_lastZoom;
|
|
// reset
|
|
_cameraUp0;
|
|
_target0;
|
|
_position0;
|
|
_zoom0;
|
|
_focalOffset0;
|
|
_dollyControlCoord;
|
|
_changedDolly = 0;
|
|
_changedZoom = 0;
|
|
// collisionTest uses nearPlane. ( PerspectiveCamera only )
|
|
_nearPlaneCorners;
|
|
_hasRested = true;
|
|
_boundary;
|
|
_boundaryEnclosesCamera = false;
|
|
_needsUpdate = true;
|
|
_updatedLastTime = false;
|
|
_elementRect = new DOMRect();
|
|
_isDragging = false;
|
|
_dragNeedsUpdate = true;
|
|
_activePointers = [];
|
|
_lockedPointer = null;
|
|
_interactiveArea = new DOMRect(0, 0, 1, 1);
|
|
// Use draggingSmoothTime over smoothTime while true.
|
|
// set automatically true on user-dragging start.
|
|
// set automatically false on programmable methods call.
|
|
_isUserControllingRotate = false;
|
|
_isUserControllingDolly = false;
|
|
_isUserControllingTruck = false;
|
|
_isUserControllingOffset = false;
|
|
_isUserControllingZoom = false;
|
|
_lastDollyDirection = DOLLY_DIRECTION.NONE;
|
|
// velocities for smoothDamp
|
|
_thetaVelocity = { value: 0 };
|
|
_phiVelocity = { value: 0 };
|
|
_radiusVelocity = { value: 0 };
|
|
_targetVelocity = new THREE.Vector3();
|
|
_focalOffsetVelocity = new THREE.Vector3();
|
|
_zoomVelocity = { value: 0 };
|
|
/**
|
|
* @deprecated Use `cameraControls.mouseButtons.left = CameraControls.ACTION.SCREEN_PAN` instead.
|
|
*/
|
|
set verticalDragToForward(_) {
|
|
console.warn("camera-controls: `verticalDragToForward` was removed. Use `mouseButtons.left = CameraControls.ACTION.SCREEN_PAN` instead.");
|
|
}
|
|
/**
|
|
* Creates a `CameraControls` instance.
|
|
*
|
|
* Note:
|
|
* You **must install** three.js before using camera-controls. see [#install](#install)
|
|
* Not doing so will lead to runtime errors (`undefined` references to THREE).
|
|
*
|
|
* e.g.
|
|
* ```
|
|
* CameraControls.install( { THREE } );
|
|
* const cameraControls = new CameraControls( camera, domElement );
|
|
* ```
|
|
*
|
|
* @param camera A `THREE.PerspectiveCamera` or `THREE.OrthographicCamera` to be controlled.
|
|
* @param domElement A `HTMLElement` for the draggable area, usually `renderer.domElement`.
|
|
* @category Constructor
|
|
*/
|
|
constructor(camera, domElement) {
|
|
super();
|
|
if (typeof THREE === "undefined") {
|
|
console.error("camera-controls: `THREE` is undefined. You must first run `CameraControls.install( { THREE: THREE } )`. Check the docs for further information.");
|
|
}
|
|
this._camera = camera;
|
|
this._yAxisUpSpace = new THREE.Quaternion().setFromUnitVectors(this._camera.up, _AXIS_Y);
|
|
this._yAxisUpSpaceInverse = this._yAxisUpSpace.clone().invert();
|
|
this._state = ACTION.NONE;
|
|
this._target = new THREE.Vector3();
|
|
this._targetEnd = this._target.clone();
|
|
this._focalOffset = new THREE.Vector3();
|
|
this._focalOffsetEnd = this._focalOffset.clone();
|
|
this._spherical = new THREE.Spherical().setFromVector3(_v3A.copy(this._camera.position).applyQuaternion(this._yAxisUpSpace));
|
|
this._sphericalEnd = this._spherical.clone();
|
|
this._lastDistance = this._spherical.radius;
|
|
this._zoom = this._camera.zoom;
|
|
this._zoomEnd = this._zoom;
|
|
this._lastZoom = this._zoom;
|
|
this._nearPlaneCorners = [
|
|
new THREE.Vector3(),
|
|
new THREE.Vector3(),
|
|
new THREE.Vector3(),
|
|
new THREE.Vector3()
|
|
];
|
|
this._updateNearPlaneCorners();
|
|
this._boundary = new THREE.Box3(new THREE.Vector3(-Infinity, -Infinity, -Infinity), new THREE.Vector3(Infinity, Infinity, Infinity));
|
|
this._cameraUp0 = this._camera.up.clone();
|
|
this._target0 = this._target.clone();
|
|
this._position0 = this._camera.position.clone();
|
|
this._zoom0 = this._zoom;
|
|
this._focalOffset0 = this._focalOffset.clone();
|
|
this._dollyControlCoord = new THREE.Vector2();
|
|
this.mouseButtons = {
|
|
left: ACTION.ROTATE,
|
|
middle: ACTION.DOLLY,
|
|
right: ACTION.TRUCK,
|
|
wheel: isPerspectiveCamera(this._camera) ? ACTION.DOLLY : isOrthographicCamera(this._camera) ? ACTION.ZOOM : ACTION.NONE
|
|
};
|
|
this.touches = {
|
|
one: ACTION.TOUCH_ROTATE,
|
|
two: isPerspectiveCamera(this._camera) ? ACTION.TOUCH_DOLLY_TRUCK : isOrthographicCamera(this._camera) ? ACTION.TOUCH_ZOOM_TRUCK : ACTION.NONE,
|
|
three: ACTION.TOUCH_TRUCK
|
|
};
|
|
const dragStartPosition = new THREE.Vector2();
|
|
const lastDragPosition = new THREE.Vector2();
|
|
const dollyStart = new THREE.Vector2();
|
|
const onPointerDown = (event) => {
|
|
if (!this._enabled || !this._domElement)
|
|
return;
|
|
if (this._interactiveArea.left !== 0 || this._interactiveArea.top !== 0 || this._interactiveArea.width !== 1 || this._interactiveArea.height !== 1) {
|
|
const elRect = this._domElement.getBoundingClientRect();
|
|
const left = event.clientX / elRect.width;
|
|
const top = event.clientY / elRect.height;
|
|
if (left < this._interactiveArea.left || left > this._interactiveArea.right || top < this._interactiveArea.top || top > this._interactiveArea.bottom)
|
|
return;
|
|
}
|
|
const mouseButton = event.pointerType !== "mouse" ? null : (event.buttons & MOUSE_BUTTON.LEFT) === MOUSE_BUTTON.LEFT ? MOUSE_BUTTON.LEFT : (event.buttons & MOUSE_BUTTON.MIDDLE) === MOUSE_BUTTON.MIDDLE ? MOUSE_BUTTON.MIDDLE : (event.buttons & MOUSE_BUTTON.RIGHT) === MOUSE_BUTTON.RIGHT ? MOUSE_BUTTON.RIGHT : null;
|
|
if (mouseButton !== null) {
|
|
const zombiePointer = this._findPointerByMouseButton(mouseButton);
|
|
zombiePointer && this._disposePointer(zombiePointer);
|
|
}
|
|
if ((event.buttons & MOUSE_BUTTON.LEFT) === MOUSE_BUTTON.LEFT && this._lockedPointer)
|
|
return;
|
|
const pointer = {
|
|
pointerId: event.pointerId,
|
|
clientX: event.clientX,
|
|
clientY: event.clientY,
|
|
deltaX: 0,
|
|
deltaY: 0,
|
|
mouseButton
|
|
};
|
|
this._activePointers.push(pointer);
|
|
this._domElement.ownerDocument.removeEventListener("pointermove", onPointerMove, { passive: false });
|
|
this._domElement.ownerDocument.removeEventListener("pointerup", onPointerUp);
|
|
this._domElement.ownerDocument.addEventListener("pointermove", onPointerMove, { passive: false });
|
|
this._domElement.ownerDocument.addEventListener("pointerup", onPointerUp);
|
|
this._isDragging = true;
|
|
startDragging(event);
|
|
};
|
|
const onPointerMove = (event) => {
|
|
if (event.cancelable)
|
|
event.preventDefault();
|
|
const pointerId2 = event.pointerId;
|
|
const pointer = this._lockedPointer || this._findPointerById(pointerId2);
|
|
if (!pointer)
|
|
return;
|
|
pointer.clientX = event.clientX;
|
|
pointer.clientY = event.clientY;
|
|
pointer.deltaX = event.movementX;
|
|
pointer.deltaY = event.movementY;
|
|
this._state = 0;
|
|
if (event.pointerType === "touch") {
|
|
switch (this._activePointers.length) {
|
|
case 1:
|
|
this._state = this.touches.one;
|
|
break;
|
|
case 2:
|
|
this._state = this.touches.two;
|
|
break;
|
|
case 3:
|
|
this._state = this.touches.three;
|
|
break;
|
|
}
|
|
} else {
|
|
if (!this._isDragging && this._lockedPointer || this._isDragging && (event.buttons & MOUSE_BUTTON.LEFT) === MOUSE_BUTTON.LEFT) {
|
|
this._state = this._state | this.mouseButtons.left;
|
|
}
|
|
if (this._isDragging && (event.buttons & MOUSE_BUTTON.MIDDLE) === MOUSE_BUTTON.MIDDLE) {
|
|
this._state = this._state | this.mouseButtons.middle;
|
|
}
|
|
if (this._isDragging && (event.buttons & MOUSE_BUTTON.RIGHT) === MOUSE_BUTTON.RIGHT) {
|
|
this._state = this._state | this.mouseButtons.right;
|
|
}
|
|
}
|
|
dragging();
|
|
};
|
|
const onPointerUp = (event) => {
|
|
const pointer = this._findPointerById(event.pointerId);
|
|
if (pointer && pointer === this._lockedPointer)
|
|
return;
|
|
pointer && this._disposePointer(pointer);
|
|
if (event.pointerType === "touch") {
|
|
switch (this._activePointers.length) {
|
|
case 0:
|
|
this._state = ACTION.NONE;
|
|
break;
|
|
case 1:
|
|
this._state = this.touches.one;
|
|
break;
|
|
case 2:
|
|
this._state = this.touches.two;
|
|
break;
|
|
case 3:
|
|
this._state = this.touches.three;
|
|
break;
|
|
}
|
|
} else {
|
|
this._state = ACTION.NONE;
|
|
}
|
|
endDragging();
|
|
};
|
|
let lastScrollTimeStamp = -1;
|
|
const onMouseWheel = (event) => {
|
|
if (!this._domElement)
|
|
return;
|
|
if (!this._enabled || this.mouseButtons.wheel === ACTION.NONE)
|
|
return;
|
|
if (this._interactiveArea.left !== 0 || this._interactiveArea.top !== 0 || this._interactiveArea.width !== 1 || this._interactiveArea.height !== 1) {
|
|
const elRect = this._domElement.getBoundingClientRect();
|
|
const left = event.clientX / elRect.width;
|
|
const top = event.clientY / elRect.height;
|
|
if (left < this._interactiveArea.left || left > this._interactiveArea.right || top < this._interactiveArea.top || top > this._interactiveArea.bottom)
|
|
return;
|
|
}
|
|
event.preventDefault();
|
|
if (this.dollyToCursor || this.mouseButtons.wheel === ACTION.ROTATE || this.mouseButtons.wheel === ACTION.TRUCK) {
|
|
const now2 = performance.now();
|
|
if (lastScrollTimeStamp - now2 < 1e3)
|
|
this._getClientRect(this._elementRect);
|
|
lastScrollTimeStamp = now2;
|
|
}
|
|
const deltaYFactor = isMac ? -1 : -3;
|
|
const delta = event.deltaMode === 1 && !event.ctrlKey ? event.deltaY / deltaYFactor : event.deltaY / (deltaYFactor * 10);
|
|
const x = this.dollyToCursor ? (event.clientX - this._elementRect.x) / this._elementRect.width * 2 - 1 : 0;
|
|
const y = this.dollyToCursor ? (event.clientY - this._elementRect.y) / this._elementRect.height * -2 + 1 : 0;
|
|
const controlMode = event.ctrlKey ? ACTION.ZOOM : this.mouseButtons.wheel;
|
|
switch (controlMode) {
|
|
case ACTION.ROTATE: {
|
|
this._rotateInternal(event.deltaX, event.deltaY);
|
|
this._isUserControllingRotate = true;
|
|
break;
|
|
}
|
|
case ACTION.TRUCK: {
|
|
this._truckInternal(event.deltaX, event.deltaY, false, false);
|
|
this._isUserControllingTruck = true;
|
|
break;
|
|
}
|
|
case ACTION.SCREEN_PAN: {
|
|
this._truckInternal(event.deltaX, event.deltaY, false, true);
|
|
this._isUserControllingTruck = true;
|
|
break;
|
|
}
|
|
case ACTION.OFFSET: {
|
|
this._truckInternal(event.deltaX, event.deltaY, true, false);
|
|
this._isUserControllingOffset = true;
|
|
break;
|
|
}
|
|
case ACTION.DOLLY: {
|
|
this._dollyInternal(-delta, x, y);
|
|
this._isUserControllingDolly = true;
|
|
break;
|
|
}
|
|
case ACTION.ZOOM: {
|
|
this._zoomInternal(-delta, x, y);
|
|
this._isUserControllingZoom = true;
|
|
break;
|
|
}
|
|
}
|
|
this.dispatchEvent({ type: "control" });
|
|
};
|
|
const onContextMenu = (event) => {
|
|
if (!this._domElement || !this._enabled)
|
|
return;
|
|
if (this.mouseButtons.right === _CameraControls.ACTION.NONE) {
|
|
const pointerId2 = event instanceof PointerEvent ? event.pointerId : 0;
|
|
const pointer = this._findPointerById(pointerId2);
|
|
pointer && this._disposePointer(pointer);
|
|
this._domElement.ownerDocument.removeEventListener("pointermove", onPointerMove, { passive: false });
|
|
this._domElement.ownerDocument.removeEventListener("pointerup", onPointerUp);
|
|
return;
|
|
}
|
|
event.preventDefault();
|
|
};
|
|
const startDragging = (event) => {
|
|
if (!this._enabled)
|
|
return;
|
|
extractClientCoordFromEvent(this._activePointers, _v2);
|
|
this._getClientRect(this._elementRect);
|
|
dragStartPosition.copy(_v2);
|
|
lastDragPosition.copy(_v2);
|
|
const isMultiTouch = this._activePointers.length >= 2;
|
|
if (isMultiTouch) {
|
|
const dx = _v2.x - this._activePointers[1].clientX;
|
|
const dy = _v2.y - this._activePointers[1].clientY;
|
|
const distance3 = Math.sqrt(dx * dx + dy * dy);
|
|
dollyStart.set(0, distance3);
|
|
const x = (this._activePointers[0].clientX + this._activePointers[1].clientX) * 0.5;
|
|
const y = (this._activePointers[0].clientY + this._activePointers[1].clientY) * 0.5;
|
|
lastDragPosition.set(x, y);
|
|
}
|
|
this._state = 0;
|
|
if (!event) {
|
|
if (this._lockedPointer)
|
|
this._state = this._state | this.mouseButtons.left;
|
|
} else if ("pointerType" in event && event.pointerType === "touch") {
|
|
switch (this._activePointers.length) {
|
|
case 1:
|
|
this._state = this.touches.one;
|
|
break;
|
|
case 2:
|
|
this._state = this.touches.two;
|
|
break;
|
|
case 3:
|
|
this._state = this.touches.three;
|
|
break;
|
|
}
|
|
} else {
|
|
if (!this._lockedPointer && (event.buttons & MOUSE_BUTTON.LEFT) === MOUSE_BUTTON.LEFT) {
|
|
this._state = this._state | this.mouseButtons.left;
|
|
}
|
|
if ((event.buttons & MOUSE_BUTTON.MIDDLE) === MOUSE_BUTTON.MIDDLE) {
|
|
this._state = this._state | this.mouseButtons.middle;
|
|
}
|
|
if ((event.buttons & MOUSE_BUTTON.RIGHT) === MOUSE_BUTTON.RIGHT) {
|
|
this._state = this._state | this.mouseButtons.right;
|
|
}
|
|
}
|
|
if ((this._state & ACTION.ROTATE) === ACTION.ROTATE || (this._state & ACTION.TOUCH_ROTATE) === ACTION.TOUCH_ROTATE || (this._state & ACTION.TOUCH_DOLLY_ROTATE) === ACTION.TOUCH_DOLLY_ROTATE || (this._state & ACTION.TOUCH_ZOOM_ROTATE) === ACTION.TOUCH_ZOOM_ROTATE) {
|
|
this._sphericalEnd.theta = this._spherical.theta;
|
|
this._sphericalEnd.phi = this._spherical.phi;
|
|
this._thetaVelocity.value = 0;
|
|
this._phiVelocity.value = 0;
|
|
}
|
|
if ((this._state & ACTION.TRUCK) === ACTION.TRUCK || (this._state & ACTION.SCREEN_PAN) === ACTION.SCREEN_PAN || (this._state & ACTION.TOUCH_TRUCK) === ACTION.TOUCH_TRUCK || (this._state & ACTION.TOUCH_SCREEN_PAN) === ACTION.TOUCH_SCREEN_PAN || (this._state & ACTION.TOUCH_DOLLY_TRUCK) === ACTION.TOUCH_DOLLY_TRUCK || (this._state & ACTION.TOUCH_DOLLY_SCREEN_PAN) === ACTION.TOUCH_DOLLY_SCREEN_PAN || (this._state & ACTION.TOUCH_ZOOM_TRUCK) === ACTION.TOUCH_ZOOM_TRUCK || (this._state & ACTION.TOUCH_ZOOM_SCREEN_PAN) === ACTION.TOUCH_DOLLY_SCREEN_PAN) {
|
|
this._targetEnd.copy(this._target);
|
|
this._targetVelocity.set(0, 0, 0);
|
|
}
|
|
if ((this._state & ACTION.DOLLY) === ACTION.DOLLY || (this._state & ACTION.TOUCH_DOLLY) === ACTION.TOUCH_DOLLY || (this._state & ACTION.TOUCH_DOLLY_TRUCK) === ACTION.TOUCH_DOLLY_TRUCK || (this._state & ACTION.TOUCH_DOLLY_SCREEN_PAN) === ACTION.TOUCH_DOLLY_SCREEN_PAN || (this._state & ACTION.TOUCH_DOLLY_OFFSET) === ACTION.TOUCH_DOLLY_OFFSET || (this._state & ACTION.TOUCH_DOLLY_ROTATE) === ACTION.TOUCH_DOLLY_ROTATE) {
|
|
this._sphericalEnd.radius = this._spherical.radius;
|
|
this._radiusVelocity.value = 0;
|
|
}
|
|
if ((this._state & ACTION.ZOOM) === ACTION.ZOOM || (this._state & ACTION.TOUCH_ZOOM) === ACTION.TOUCH_ZOOM || (this._state & ACTION.TOUCH_ZOOM_TRUCK) === ACTION.TOUCH_ZOOM_TRUCK || (this._state & ACTION.TOUCH_ZOOM_SCREEN_PAN) === ACTION.TOUCH_ZOOM_SCREEN_PAN || (this._state & ACTION.TOUCH_ZOOM_OFFSET) === ACTION.TOUCH_ZOOM_OFFSET || (this._state & ACTION.TOUCH_ZOOM_ROTATE) === ACTION.TOUCH_ZOOM_ROTATE) {
|
|
this._zoomEnd = this._zoom;
|
|
this._zoomVelocity.value = 0;
|
|
}
|
|
if ((this._state & ACTION.OFFSET) === ACTION.OFFSET || (this._state & ACTION.TOUCH_OFFSET) === ACTION.TOUCH_OFFSET || (this._state & ACTION.TOUCH_DOLLY_OFFSET) === ACTION.TOUCH_DOLLY_OFFSET || (this._state & ACTION.TOUCH_ZOOM_OFFSET) === ACTION.TOUCH_ZOOM_OFFSET) {
|
|
this._focalOffsetEnd.copy(this._focalOffset);
|
|
this._focalOffsetVelocity.set(0, 0, 0);
|
|
}
|
|
this.dispatchEvent({ type: "controlstart" });
|
|
};
|
|
const dragging = () => {
|
|
if (!this._enabled || !this._dragNeedsUpdate)
|
|
return;
|
|
this._dragNeedsUpdate = false;
|
|
extractClientCoordFromEvent(this._activePointers, _v2);
|
|
const isPointerLockActive = this._domElement && this._domElement.ownerDocument.pointerLockElement === this._domElement;
|
|
const lockedPointer = isPointerLockActive ? this._lockedPointer || this._activePointers[0] : null;
|
|
const deltaX = lockedPointer ? -lockedPointer.deltaX : lastDragPosition.x - _v2.x;
|
|
const deltaY = lockedPointer ? -lockedPointer.deltaY : lastDragPosition.y - _v2.y;
|
|
lastDragPosition.copy(_v2);
|
|
if ((this._state & ACTION.ROTATE) === ACTION.ROTATE || (this._state & ACTION.TOUCH_ROTATE) === ACTION.TOUCH_ROTATE || (this._state & ACTION.TOUCH_DOLLY_ROTATE) === ACTION.TOUCH_DOLLY_ROTATE || (this._state & ACTION.TOUCH_ZOOM_ROTATE) === ACTION.TOUCH_ZOOM_ROTATE) {
|
|
this._rotateInternal(deltaX, deltaY);
|
|
this._isUserControllingRotate = true;
|
|
}
|
|
if ((this._state & ACTION.DOLLY) === ACTION.DOLLY || (this._state & ACTION.ZOOM) === ACTION.ZOOM) {
|
|
const dollyX = this.dollyToCursor ? (dragStartPosition.x - this._elementRect.x) / this._elementRect.width * 2 - 1 : 0;
|
|
const dollyY = this.dollyToCursor ? (dragStartPosition.y - this._elementRect.y) / this._elementRect.height * -2 + 1 : 0;
|
|
const dollyDirection = this.dollyDragInverted ? -1 : 1;
|
|
if ((this._state & ACTION.DOLLY) === ACTION.DOLLY) {
|
|
this._dollyInternal(dollyDirection * deltaY * TOUCH_DOLLY_FACTOR, dollyX, dollyY);
|
|
this._isUserControllingDolly = true;
|
|
} else {
|
|
this._zoomInternal(dollyDirection * deltaY * TOUCH_DOLLY_FACTOR, dollyX, dollyY);
|
|
this._isUserControllingZoom = true;
|
|
}
|
|
}
|
|
if ((this._state & ACTION.TOUCH_DOLLY) === ACTION.TOUCH_DOLLY || (this._state & ACTION.TOUCH_ZOOM) === ACTION.TOUCH_ZOOM || (this._state & ACTION.TOUCH_DOLLY_TRUCK) === ACTION.TOUCH_DOLLY_TRUCK || (this._state & ACTION.TOUCH_ZOOM_TRUCK) === ACTION.TOUCH_ZOOM_TRUCK || (this._state & ACTION.TOUCH_DOLLY_SCREEN_PAN) === ACTION.TOUCH_DOLLY_SCREEN_PAN || (this._state & ACTION.TOUCH_ZOOM_SCREEN_PAN) === ACTION.TOUCH_ZOOM_SCREEN_PAN || (this._state & ACTION.TOUCH_DOLLY_OFFSET) === ACTION.TOUCH_DOLLY_OFFSET || (this._state & ACTION.TOUCH_ZOOM_OFFSET) === ACTION.TOUCH_ZOOM_OFFSET || (this._state & ACTION.TOUCH_DOLLY_ROTATE) === ACTION.TOUCH_DOLLY_ROTATE || (this._state & ACTION.TOUCH_ZOOM_ROTATE) === ACTION.TOUCH_ZOOM_ROTATE) {
|
|
const dx = _v2.x - this._activePointers[1].clientX;
|
|
const dy = _v2.y - this._activePointers[1].clientY;
|
|
const distance3 = Math.sqrt(dx * dx + dy * dy);
|
|
const dollyDelta = dollyStart.y - distance3;
|
|
dollyStart.set(0, distance3);
|
|
const dollyX = this.dollyToCursor ? (lastDragPosition.x - this._elementRect.x) / this._elementRect.width * 2 - 1 : 0;
|
|
const dollyY = this.dollyToCursor ? (lastDragPosition.y - this._elementRect.y) / this._elementRect.height * -2 + 1 : 0;
|
|
if ((this._state & ACTION.TOUCH_DOLLY) === ACTION.TOUCH_DOLLY || (this._state & ACTION.TOUCH_DOLLY_ROTATE) === ACTION.TOUCH_DOLLY_ROTATE || (this._state & ACTION.TOUCH_DOLLY_TRUCK) === ACTION.TOUCH_DOLLY_TRUCK || (this._state & ACTION.TOUCH_DOLLY_SCREEN_PAN) === ACTION.TOUCH_DOLLY_SCREEN_PAN || (this._state & ACTION.TOUCH_DOLLY_OFFSET) === ACTION.TOUCH_DOLLY_OFFSET) {
|
|
this._dollyInternal(dollyDelta * TOUCH_DOLLY_FACTOR, dollyX, dollyY);
|
|
this._isUserControllingDolly = true;
|
|
} else {
|
|
this._zoomInternal(dollyDelta * TOUCH_DOLLY_FACTOR, dollyX, dollyY);
|
|
this._isUserControllingZoom = true;
|
|
}
|
|
}
|
|
if ((this._state & ACTION.TRUCK) === ACTION.TRUCK || (this._state & ACTION.TOUCH_TRUCK) === ACTION.TOUCH_TRUCK || (this._state & ACTION.TOUCH_DOLLY_TRUCK) === ACTION.TOUCH_DOLLY_TRUCK || (this._state & ACTION.TOUCH_ZOOM_TRUCK) === ACTION.TOUCH_ZOOM_TRUCK) {
|
|
this._truckInternal(deltaX, deltaY, false, false);
|
|
this._isUserControllingTruck = true;
|
|
}
|
|
if ((this._state & ACTION.SCREEN_PAN) === ACTION.SCREEN_PAN || (this._state & ACTION.TOUCH_SCREEN_PAN) === ACTION.TOUCH_SCREEN_PAN || (this._state & ACTION.TOUCH_DOLLY_SCREEN_PAN) === ACTION.TOUCH_DOLLY_SCREEN_PAN || (this._state & ACTION.TOUCH_ZOOM_SCREEN_PAN) === ACTION.TOUCH_ZOOM_SCREEN_PAN) {
|
|
this._truckInternal(deltaX, deltaY, false, true);
|
|
this._isUserControllingTruck = true;
|
|
}
|
|
if ((this._state & ACTION.OFFSET) === ACTION.OFFSET || (this._state & ACTION.TOUCH_OFFSET) === ACTION.TOUCH_OFFSET || (this._state & ACTION.TOUCH_DOLLY_OFFSET) === ACTION.TOUCH_DOLLY_OFFSET || (this._state & ACTION.TOUCH_ZOOM_OFFSET) === ACTION.TOUCH_ZOOM_OFFSET) {
|
|
this._truckInternal(deltaX, deltaY, true, false);
|
|
this._isUserControllingOffset = true;
|
|
}
|
|
this.dispatchEvent({ type: "control" });
|
|
};
|
|
const endDragging = () => {
|
|
extractClientCoordFromEvent(this._activePointers, _v2);
|
|
lastDragPosition.copy(_v2);
|
|
this._dragNeedsUpdate = false;
|
|
if (this._activePointers.length === 0 || this._activePointers.length === 1 && this._activePointers[0] === this._lockedPointer) {
|
|
this._isDragging = false;
|
|
}
|
|
if (this._activePointers.length === 0 && this._domElement) {
|
|
this._domElement.ownerDocument.removeEventListener("pointermove", onPointerMove, { passive: false });
|
|
this._domElement.ownerDocument.removeEventListener("pointerup", onPointerUp);
|
|
this.dispatchEvent({ type: "controlend" });
|
|
}
|
|
};
|
|
this.lockPointer = () => {
|
|
if (!this._enabled || !this._domElement)
|
|
return;
|
|
this.cancel();
|
|
this._lockedPointer = {
|
|
pointerId: -1,
|
|
clientX: 0,
|
|
clientY: 0,
|
|
deltaX: 0,
|
|
deltaY: 0,
|
|
mouseButton: null
|
|
};
|
|
this._activePointers.push(this._lockedPointer);
|
|
this._domElement.ownerDocument.removeEventListener("pointermove", onPointerMove, { passive: false });
|
|
this._domElement.ownerDocument.removeEventListener("pointerup", onPointerUp);
|
|
this._domElement.requestPointerLock();
|
|
this._domElement.ownerDocument.addEventListener("pointerlockchange", onPointerLockChange);
|
|
this._domElement.ownerDocument.addEventListener("pointerlockerror", onPointerLockError);
|
|
this._domElement.ownerDocument.addEventListener("pointermove", onPointerMove, { passive: false });
|
|
this._domElement.ownerDocument.addEventListener("pointerup", onPointerUp);
|
|
startDragging();
|
|
};
|
|
this.unlockPointer = () => {
|
|
if (this._lockedPointer !== null) {
|
|
this._disposePointer(this._lockedPointer);
|
|
this._lockedPointer = null;
|
|
}
|
|
this._domElement?.ownerDocument.exitPointerLock();
|
|
this._domElement?.ownerDocument.removeEventListener("pointerlockchange", onPointerLockChange);
|
|
this._domElement?.ownerDocument.removeEventListener("pointerlockerror", onPointerLockError);
|
|
this.cancel();
|
|
};
|
|
const onPointerLockChange = () => {
|
|
const isPointerLockActive = this._domElement && this._domElement.ownerDocument.pointerLockElement === this._domElement;
|
|
if (!isPointerLockActive)
|
|
this.unlockPointer();
|
|
};
|
|
const onPointerLockError = () => {
|
|
this.unlockPointer();
|
|
};
|
|
this._addAllEventListeners = (domElement2) => {
|
|
this._domElement = domElement2;
|
|
this._domElement.style.touchAction = "none";
|
|
this._domElement.style.userSelect = "none";
|
|
this._domElement.style.webkitUserSelect = "none";
|
|
this._domElement.addEventListener("pointerdown", onPointerDown);
|
|
this._domElement.addEventListener("pointercancel", onPointerUp);
|
|
this._domElement.addEventListener("wheel", onMouseWheel, { passive: false });
|
|
this._domElement.addEventListener("contextmenu", onContextMenu);
|
|
};
|
|
this._removeAllEventListeners = () => {
|
|
if (!this._domElement)
|
|
return;
|
|
this._domElement.style.touchAction = "";
|
|
this._domElement.style.userSelect = "";
|
|
this._domElement.style.webkitUserSelect = "";
|
|
this._domElement.removeEventListener("pointerdown", onPointerDown);
|
|
this._domElement.removeEventListener("pointercancel", onPointerUp);
|
|
this._domElement.removeEventListener("wheel", onMouseWheel, { passive: false });
|
|
this._domElement.removeEventListener("contextmenu", onContextMenu);
|
|
this._domElement.ownerDocument.removeEventListener("pointermove", onPointerMove, { passive: false });
|
|
this._domElement.ownerDocument.removeEventListener("pointerup", onPointerUp);
|
|
this._domElement.ownerDocument.removeEventListener("pointerlockchange", onPointerLockChange);
|
|
this._domElement.ownerDocument.removeEventListener("pointerlockerror", onPointerLockError);
|
|
};
|
|
this.cancel = () => {
|
|
if (this._state === ACTION.NONE)
|
|
return;
|
|
this._state = ACTION.NONE;
|
|
this._activePointers.length = 0;
|
|
endDragging();
|
|
};
|
|
if (domElement)
|
|
this.connect(domElement);
|
|
this.update(0);
|
|
}
|
|
/**
|
|
* The camera to be controlled
|
|
* @category Properties
|
|
*/
|
|
get camera() {
|
|
return this._camera;
|
|
}
|
|
set camera(camera) {
|
|
this._camera = camera;
|
|
this.updateCameraUp();
|
|
this._camera.updateProjectionMatrix();
|
|
this._updateNearPlaneCorners();
|
|
this._needsUpdate = true;
|
|
}
|
|
/**
|
|
* Whether or not the controls are enabled.
|
|
* `false` to disable user dragging/touch-move, but all methods works.
|
|
* @category Properties
|
|
*/
|
|
get enabled() {
|
|
return this._enabled;
|
|
}
|
|
set enabled(enabled) {
|
|
this._enabled = enabled;
|
|
if (!this._domElement)
|
|
return;
|
|
if (enabled) {
|
|
this._domElement.style.touchAction = "none";
|
|
this._domElement.style.userSelect = "none";
|
|
this._domElement.style.webkitUserSelect = "none";
|
|
} else {
|
|
this.cancel();
|
|
this._domElement.style.touchAction = "";
|
|
this._domElement.style.userSelect = "";
|
|
this._domElement.style.webkitUserSelect = "";
|
|
}
|
|
}
|
|
/**
|
|
* Returns `true` if the controls are active updating.
|
|
* readonly value.
|
|
* @category Properties
|
|
*/
|
|
get active() {
|
|
return !this._hasRested;
|
|
}
|
|
/**
|
|
* Getter for the current `ACTION`.
|
|
* readonly value.
|
|
* @category Properties
|
|
*/
|
|
get currentAction() {
|
|
return this._state;
|
|
}
|
|
/**
|
|
* get/set Current distance.
|
|
* @category Properties
|
|
*/
|
|
get distance() {
|
|
return this._spherical.radius;
|
|
}
|
|
set distance(distance3) {
|
|
if (this._spherical.radius === distance3 && this._sphericalEnd.radius === distance3)
|
|
return;
|
|
this._spherical.radius = distance3;
|
|
this._sphericalEnd.radius = distance3;
|
|
this._needsUpdate = true;
|
|
}
|
|
// horizontal angle
|
|
/**
|
|
* get/set the azimuth angle (horizontal) in radians.
|
|
* Every 360 degrees turn is added to `.azimuthAngle` value, which is accumulative.
|
|
* @category Properties
|
|
*/
|
|
get azimuthAngle() {
|
|
return this._spherical.theta;
|
|
}
|
|
set azimuthAngle(azimuthAngle) {
|
|
if (this._spherical.theta === azimuthAngle && this._sphericalEnd.theta === azimuthAngle)
|
|
return;
|
|
this._spherical.theta = azimuthAngle;
|
|
this._sphericalEnd.theta = azimuthAngle;
|
|
this._needsUpdate = true;
|
|
}
|
|
// vertical angle
|
|
/**
|
|
* get/set the polar angle (vertical) in radians.
|
|
* @category Properties
|
|
*/
|
|
get polarAngle() {
|
|
return this._spherical.phi;
|
|
}
|
|
set polarAngle(polarAngle) {
|
|
if (this._spherical.phi === polarAngle && this._sphericalEnd.phi === polarAngle)
|
|
return;
|
|
this._spherical.phi = polarAngle;
|
|
this._sphericalEnd.phi = polarAngle;
|
|
this._needsUpdate = true;
|
|
}
|
|
/**
|
|
* Whether camera position should be enclosed in the boundary or not.
|
|
* @category Properties
|
|
*/
|
|
get boundaryEnclosesCamera() {
|
|
return this._boundaryEnclosesCamera;
|
|
}
|
|
set boundaryEnclosesCamera(boundaryEnclosesCamera) {
|
|
this._boundaryEnclosesCamera = boundaryEnclosesCamera;
|
|
this._needsUpdate = true;
|
|
}
|
|
/**
|
|
* Set drag-start, touches and wheel enable area in the domElement.
|
|
* each values are between `0` and `1` inclusive, where `0` is left/top and `1` is right/bottom of the screen.
|
|
* e.g. `{ x: 0, y: 0, width: 1, height: 1 }` for entire area.
|
|
* @category Properties
|
|
*/
|
|
set interactiveArea(interactiveArea) {
|
|
this._interactiveArea.width = clamp3(interactiveArea.width, 0, 1);
|
|
this._interactiveArea.height = clamp3(interactiveArea.height, 0, 1);
|
|
this._interactiveArea.x = clamp3(interactiveArea.x, 0, 1 - this._interactiveArea.width);
|
|
this._interactiveArea.y = clamp3(interactiveArea.y, 0, 1 - this._interactiveArea.height);
|
|
}
|
|
/**
|
|
* Adds the specified event listener.
|
|
* Applicable event types (which is `K`) are:
|
|
* | Event name | Timing |
|
|
* | ------------------- | ------ |
|
|
* | `'controlstart'` | When the user starts to control the camera via mouse / touches. ¹ |
|
|
* | `'control'` | When the user controls the camera (dragging). |
|
|
* | `'controlend'` | When the user ends to control the camera. ¹ |
|
|
* | `'transitionstart'` | When any kind of transition starts, either user control or using a method with `enableTransition = true` |
|
|
* | `'update'` | When the camera position is updated. |
|
|
* | `'wake'` | When the camera starts moving. |
|
|
* | `'rest'` | When the camera movement is below `.restThreshold` ². |
|
|
* | `'sleep'` | When the camera end moving. |
|
|
*
|
|
* 1. `mouseButtons.wheel` (Mouse wheel control) does not emit `'controlstart'` and `'controlend'`. `mouseButtons.wheel` uses scroll-event internally, and scroll-event happens intermittently. That means "start" and "end" cannot be detected.
|
|
* 2. Due to damping, `sleep` will usually fire a few seconds after the camera _appears_ to have stopped moving. If you want to do something (e.g. enable UI, perform another transition) at the point when the camera has stopped, you probably want the `rest` event. This can be fine tuned using the `.restThreshold` parameter. See the [Rest and Sleep Example](https://yomotsu.github.io/camera-controls/examples/rest-and-sleep.html).
|
|
*
|
|
* e.g.
|
|
* ```
|
|
* cameraControl.addEventListener( 'controlstart', myCallbackFunction );
|
|
* ```
|
|
* @param type event name
|
|
* @param listener handler function
|
|
* @category Methods
|
|
*/
|
|
addEventListener(type, listener) {
|
|
super.addEventListener(type, listener);
|
|
}
|
|
/**
|
|
* Removes the specified event listener
|
|
* e.g.
|
|
* ```
|
|
* cameraControl.addEventListener( 'controlstart', myCallbackFunction );
|
|
* ```
|
|
* @param type event name
|
|
* @param listener handler function
|
|
* @category Methods
|
|
*/
|
|
removeEventListener(type, listener) {
|
|
super.removeEventListener(type, listener);
|
|
}
|
|
/**
|
|
* Rotate azimuthal angle(horizontal) and polar angle(vertical).
|
|
* Every value is added to the current value.
|
|
* @param azimuthAngle Azimuth rotate angle. In radian.
|
|
* @param polarAngle Polar rotate angle. In radian.
|
|
* @param enableTransition Whether to move smoothly or immediately
|
|
* @category Methods
|
|
*/
|
|
rotate(azimuthAngle, polarAngle, enableTransition = false) {
|
|
return this.rotateTo(this._sphericalEnd.theta + azimuthAngle, this._sphericalEnd.phi + polarAngle, enableTransition);
|
|
}
|
|
/**
|
|
* Rotate azimuthal angle(horizontal) to the given angle and keep the same polar angle(vertical) target.
|
|
*
|
|
* e.g.
|
|
* ```
|
|
* cameraControls.rotateAzimuthTo( 30 * THREE.MathUtils.DEG2RAD, true );
|
|
* ```
|
|
* @param azimuthAngle Azimuth rotate angle. In radian.
|
|
* @param enableTransition Whether to move smoothly or immediately
|
|
* @category Methods
|
|
*/
|
|
rotateAzimuthTo(azimuthAngle, enableTransition = false) {
|
|
return this.rotateTo(azimuthAngle, this._sphericalEnd.phi, enableTransition);
|
|
}
|
|
/**
|
|
* Rotate polar angle(vertical) to the given angle and keep the same azimuthal angle(horizontal) target.
|
|
*
|
|
* e.g.
|
|
* ```
|
|
* cameraControls.rotatePolarTo( 30 * THREE.MathUtils.DEG2RAD, true );
|
|
* ```
|
|
* @param polarAngle Polar rotate angle. In radian.
|
|
* @param enableTransition Whether to move smoothly or immediately
|
|
* @category Methods
|
|
*/
|
|
rotatePolarTo(polarAngle, enableTransition = false) {
|
|
return this.rotateTo(this._sphericalEnd.theta, polarAngle, enableTransition);
|
|
}
|
|
/**
|
|
* Rotate azimuthal angle(horizontal) and polar angle(vertical) to the given angle.
|
|
* Camera view will rotate over the orbit pivot absolutely:
|
|
*
|
|
* azimuthAngle
|
|
* ```
|
|
* 0º
|
|
* \
|
|
* 90º -----+----- -90º
|
|
* \
|
|
* 180º
|
|
* ```
|
|
* | direction | angle |
|
|
* | --------- | ---------------------- |
|
|
* | front | 0º |
|
|
* | left | 90º (`Math.PI / 2`) |
|
|
* | right | -90º (`- Math.PI / 2`) |
|
|
* | back | 180º (`Math.PI`) |
|
|
*
|
|
* polarAngle
|
|
* ```
|
|
* 180º
|
|
* |
|
|
* 90º
|
|
* |
|
|
* 0º
|
|
* ```
|
|
* | direction | angle |
|
|
* | -------------------- | ---------------------- |
|
|
* | top/sky | 180º (`Math.PI`) |
|
|
* | horizontal from view | 90º (`Math.PI / 2`) |
|
|
* | bottom/floor | 0º |
|
|
*
|
|
* @param azimuthAngle Azimuth rotate angle to. In radian.
|
|
* @param polarAngle Polar rotate angle to. In radian.
|
|
* @param enableTransition Whether to move smoothly or immediately
|
|
* @category Methods
|
|
*/
|
|
rotateTo(azimuthAngle, polarAngle, enableTransition = false) {
|
|
this._isUserControllingRotate = false;
|
|
const theta = clamp3(azimuthAngle, this.minAzimuthAngle, this.maxAzimuthAngle);
|
|
const phi = clamp3(polarAngle, this.minPolarAngle, this.maxPolarAngle);
|
|
this._sphericalEnd.theta = theta;
|
|
this._sphericalEnd.phi = phi;
|
|
this._sphericalEnd.makeSafe();
|
|
this._needsUpdate = true;
|
|
if (!enableTransition) {
|
|
this._spherical.theta = this._sphericalEnd.theta;
|
|
this._spherical.phi = this._sphericalEnd.phi;
|
|
}
|
|
const resolveImmediately = !enableTransition || approxEquals(this._spherical.theta, this._sphericalEnd.theta, this.restThreshold) && approxEquals(this._spherical.phi, this._sphericalEnd.phi, this.restThreshold);
|
|
return this._createOnRestPromise(resolveImmediately);
|
|
}
|
|
/**
|
|
* Dolly in/out camera position.
|
|
* @param distance Distance of dollyIn. Negative number for dollyOut.
|
|
* @param enableTransition Whether to move smoothly or immediately.
|
|
* @category Methods
|
|
*/
|
|
dolly(distance3, enableTransition = false) {
|
|
return this.dollyTo(this._sphericalEnd.radius - distance3, enableTransition);
|
|
}
|
|
/**
|
|
* Dolly in/out camera position to given distance.
|
|
* @param distance Distance of dolly.
|
|
* @param enableTransition Whether to move smoothly or immediately.
|
|
* @category Methods
|
|
*/
|
|
dollyTo(distance3, enableTransition = false) {
|
|
this._isUserControllingDolly = false;
|
|
this._lastDollyDirection = DOLLY_DIRECTION.NONE;
|
|
this._changedDolly = 0;
|
|
return this._dollyToNoClamp(clamp3(distance3, this.minDistance, this.maxDistance), enableTransition);
|
|
}
|
|
_dollyToNoClamp(distance3, enableTransition = false) {
|
|
const lastRadius = this._sphericalEnd.radius;
|
|
const hasCollider = this.colliderMeshes.length >= 1;
|
|
if (hasCollider) {
|
|
const maxDistanceByCollisionTest = this._collisionTest();
|
|
const isCollided = approxEquals(maxDistanceByCollisionTest, this._spherical.radius);
|
|
const isDollyIn = lastRadius > distance3;
|
|
if (!isDollyIn && isCollided)
|
|
return Promise.resolve();
|
|
this._sphericalEnd.radius = Math.min(distance3, maxDistanceByCollisionTest);
|
|
} else {
|
|
this._sphericalEnd.radius = distance3;
|
|
}
|
|
this._needsUpdate = true;
|
|
if (!enableTransition) {
|
|
this._spherical.radius = this._sphericalEnd.radius;
|
|
}
|
|
const resolveImmediately = !enableTransition || approxEquals(this._spherical.radius, this._sphericalEnd.radius, this.restThreshold);
|
|
return this._createOnRestPromise(resolveImmediately);
|
|
}
|
|
/**
|
|
* Dolly in, but does not change the distance between the target and the camera, and moves the target position instead.
|
|
* Specify a negative value for dolly out.
|
|
* @param distance Distance of dolly.
|
|
* @param enableTransition Whether to move smoothly or immediately.
|
|
* @category Methods
|
|
*/
|
|
dollyInFixed(distance3, enableTransition = false) {
|
|
this._targetEnd.add(this._getCameraDirection(_cameraDirection).multiplyScalar(distance3));
|
|
if (!enableTransition) {
|
|
this._target.copy(this._targetEnd);
|
|
}
|
|
const resolveImmediately = !enableTransition || approxEquals(this._target.x, this._targetEnd.x, this.restThreshold) && approxEquals(this._target.y, this._targetEnd.y, this.restThreshold) && approxEquals(this._target.z, this._targetEnd.z, this.restThreshold);
|
|
return this._createOnRestPromise(resolveImmediately);
|
|
}
|
|
/**
|
|
* Zoom in/out camera. The value is added to camera zoom.
|
|
* Limits set with `.minZoom` and `.maxZoom`
|
|
* @param zoomStep zoom scale
|
|
* @param enableTransition Whether to move smoothly or immediately
|
|
* @category Methods
|
|
*/
|
|
zoom(zoomStep, enableTransition = false) {
|
|
return this.zoomTo(this._zoomEnd + zoomStep, enableTransition);
|
|
}
|
|
/**
|
|
* Zoom in/out camera to given scale. The value overwrites camera zoom.
|
|
* Limits set with .minZoom and .maxZoom
|
|
* @param zoom
|
|
* @param enableTransition
|
|
* @category Methods
|
|
*/
|
|
zoomTo(zoom, enableTransition = false) {
|
|
this._isUserControllingZoom = false;
|
|
this._zoomEnd = clamp3(zoom, this.minZoom, this.maxZoom);
|
|
this._needsUpdate = true;
|
|
if (!enableTransition) {
|
|
this._zoom = this._zoomEnd;
|
|
}
|
|
const resolveImmediately = !enableTransition || approxEquals(this._zoom, this._zoomEnd, this.restThreshold);
|
|
this._changedZoom = 0;
|
|
return this._createOnRestPromise(resolveImmediately);
|
|
}
|
|
/**
|
|
* @deprecated `pan()` has been renamed to `truck()`
|
|
* @category Methods
|
|
*/
|
|
pan(x, y, enableTransition = false) {
|
|
console.warn("`pan` has been renamed to `truck`");
|
|
return this.truck(x, y, enableTransition);
|
|
}
|
|
/**
|
|
* Truck and pedestal camera using current azimuthal angle
|
|
* @param x Horizontal translate amount
|
|
* @param y Vertical translate amount
|
|
* @param enableTransition Whether to move smoothly or immediately
|
|
* @category Methods
|
|
*/
|
|
truck(x, y, enableTransition = false) {
|
|
this._camera.updateMatrix();
|
|
_xColumn.setFromMatrixColumn(this._camera.matrix, 0);
|
|
_yColumn.setFromMatrixColumn(this._camera.matrix, 1);
|
|
_xColumn.multiplyScalar(x);
|
|
_yColumn.multiplyScalar(-y);
|
|
const offset = _v3A.copy(_xColumn).add(_yColumn);
|
|
const to = _v3B.copy(this._targetEnd).add(offset);
|
|
return this.moveTo(to.x, to.y, to.z, enableTransition);
|
|
}
|
|
/**
|
|
* Move forward / backward.
|
|
* @param distance Amount to move forward / backward. Negative value to move backward
|
|
* @param enableTransition Whether to move smoothly or immediately
|
|
* @category Methods
|
|
*/
|
|
forward(distance3, enableTransition = false) {
|
|
_v3A.setFromMatrixColumn(this._camera.matrix, 0);
|
|
_v3A.crossVectors(this._camera.up, _v3A);
|
|
_v3A.multiplyScalar(distance3);
|
|
const to = _v3B.copy(this._targetEnd).add(_v3A);
|
|
return this.moveTo(to.x, to.y, to.z, enableTransition);
|
|
}
|
|
/**
|
|
* Move up / down.
|
|
* @param height Amount to move up / down. Negative value to move down
|
|
* @param enableTransition Whether to move smoothly or immediately
|
|
* @category Methods
|
|
*/
|
|
elevate(height, enableTransition = false) {
|
|
_v3A.copy(this._camera.up).multiplyScalar(height);
|
|
return this.moveTo(this._targetEnd.x + _v3A.x, this._targetEnd.y + _v3A.y, this._targetEnd.z + _v3A.z, enableTransition);
|
|
}
|
|
/**
|
|
* Move target position to given point.
|
|
* @param x x coord to move center position
|
|
* @param y y coord to move center position
|
|
* @param z z coord to move center position
|
|
* @param enableTransition Whether to move smoothly or immediately
|
|
* @category Methods
|
|
*/
|
|
moveTo(x, y, z, enableTransition = false) {
|
|
this._isUserControllingTruck = false;
|
|
const offset = _v3A.set(x, y, z).sub(this._targetEnd);
|
|
this._encloseToBoundary(this._targetEnd, offset, this.boundaryFriction);
|
|
this._needsUpdate = true;
|
|
if (!enableTransition) {
|
|
this._target.copy(this._targetEnd);
|
|
}
|
|
const resolveImmediately = !enableTransition || approxEquals(this._target.x, this._targetEnd.x, this.restThreshold) && approxEquals(this._target.y, this._targetEnd.y, this.restThreshold) && approxEquals(this._target.z, this._targetEnd.z, this.restThreshold);
|
|
return this._createOnRestPromise(resolveImmediately);
|
|
}
|
|
/**
|
|
* Look in the given point direction.
|
|
* @param x point x.
|
|
* @param y point y.
|
|
* @param z point z.
|
|
* @param enableTransition Whether to move smoothly or immediately.
|
|
* @returns Transition end promise
|
|
* @category Methods
|
|
*/
|
|
lookInDirectionOf(x, y, z, enableTransition = false) {
|
|
const point = _v3A.set(x, y, z);
|
|
const direction2 = point.sub(this._targetEnd).normalize();
|
|
const position2 = direction2.multiplyScalar(-this._sphericalEnd.radius).add(this._targetEnd);
|
|
return this.setPosition(position2.x, position2.y, position2.z, enableTransition);
|
|
}
|
|
/**
|
|
* Fit the viewport to the box or the bounding box of the object, using the nearest axis. paddings are in unit.
|
|
* set `cover: true` to fill enter screen.
|
|
* e.g.
|
|
* ```
|
|
* cameraControls.fitToBox( myMesh );
|
|
* ```
|
|
* @param box3OrObject Axis aligned bounding box to fit the view.
|
|
* @param enableTransition Whether to move smoothly or immediately.
|
|
* @param options | `<object>` { cover: boolean, paddingTop: number, paddingLeft: number, paddingBottom: number, paddingRight: number }
|
|
* @returns Transition end promise
|
|
* @category Methods
|
|
*/
|
|
fitToBox(box3OrObject, enableTransition, { cover = false, paddingLeft = 0, paddingRight = 0, paddingBottom = 0, paddingTop = 0 } = {}) {
|
|
const promises = [];
|
|
const aabb = box3OrObject.isBox3 ? _box3A.copy(box3OrObject) : _box3A.setFromObject(box3OrObject);
|
|
if (aabb.isEmpty()) {
|
|
console.warn("camera-controls: fitTo() cannot be used with an empty box. Aborting");
|
|
Promise.resolve();
|
|
}
|
|
const theta = roundToStep(this._sphericalEnd.theta, PI_HALF);
|
|
const phi = roundToStep(this._sphericalEnd.phi, PI_HALF);
|
|
promises.push(this.rotateTo(theta, phi, enableTransition));
|
|
const normal2 = _v3A.setFromSpherical(this._sphericalEnd).normalize();
|
|
const rotation3 = _quaternionA.setFromUnitVectors(normal2, _AXIS_Z);
|
|
const viewFromPolar = approxEquals(Math.abs(normal2.y), 1);
|
|
if (viewFromPolar) {
|
|
rotation3.multiply(_quaternionB.setFromAxisAngle(_AXIS_Y, theta));
|
|
}
|
|
rotation3.multiply(this._yAxisUpSpaceInverse);
|
|
const bb2 = _box3B.makeEmpty();
|
|
_v3B.copy(aabb.min).applyQuaternion(rotation3);
|
|
bb2.expandByPoint(_v3B);
|
|
_v3B.copy(aabb.min).setX(aabb.max.x).applyQuaternion(rotation3);
|
|
bb2.expandByPoint(_v3B);
|
|
_v3B.copy(aabb.min).setY(aabb.max.y).applyQuaternion(rotation3);
|
|
bb2.expandByPoint(_v3B);
|
|
_v3B.copy(aabb.max).setZ(aabb.min.z).applyQuaternion(rotation3);
|
|
bb2.expandByPoint(_v3B);
|
|
_v3B.copy(aabb.min).setZ(aabb.max.z).applyQuaternion(rotation3);
|
|
bb2.expandByPoint(_v3B);
|
|
_v3B.copy(aabb.max).setY(aabb.min.y).applyQuaternion(rotation3);
|
|
bb2.expandByPoint(_v3B);
|
|
_v3B.copy(aabb.max).setX(aabb.min.x).applyQuaternion(rotation3);
|
|
bb2.expandByPoint(_v3B);
|
|
_v3B.copy(aabb.max).applyQuaternion(rotation3);
|
|
bb2.expandByPoint(_v3B);
|
|
bb2.min.x -= paddingLeft;
|
|
bb2.min.y -= paddingBottom;
|
|
bb2.max.x += paddingRight;
|
|
bb2.max.y += paddingTop;
|
|
rotation3.setFromUnitVectors(_AXIS_Z, normal2);
|
|
if (viewFromPolar) {
|
|
rotation3.premultiply(_quaternionB.invert());
|
|
}
|
|
rotation3.premultiply(this._yAxisUpSpace);
|
|
const bbSize = bb2.getSize(_v3A);
|
|
const center2 = bb2.getCenter(_v3B).applyQuaternion(rotation3);
|
|
if (isPerspectiveCamera(this._camera)) {
|
|
const distance3 = this.getDistanceToFitBox(bbSize.x, bbSize.y, bbSize.z, cover);
|
|
promises.push(this.moveTo(center2.x, center2.y, center2.z, enableTransition));
|
|
promises.push(this.dollyTo(distance3, enableTransition));
|
|
promises.push(this.setFocalOffset(0, 0, 0, enableTransition));
|
|
} else if (isOrthographicCamera(this._camera)) {
|
|
const camera = this._camera;
|
|
const width = camera.right - camera.left;
|
|
const height = camera.top - camera.bottom;
|
|
const zoom = cover ? Math.max(width / bbSize.x, height / bbSize.y) : Math.min(width / bbSize.x, height / bbSize.y);
|
|
promises.push(this.moveTo(center2.x, center2.y, center2.z, enableTransition));
|
|
promises.push(this.zoomTo(zoom, enableTransition));
|
|
promises.push(this.setFocalOffset(0, 0, 0, enableTransition));
|
|
}
|
|
return Promise.all(promises);
|
|
}
|
|
/**
|
|
* Fit the viewport to the sphere or the bounding sphere of the object.
|
|
* @param sphereOrMesh
|
|
* @param enableTransition
|
|
* @category Methods
|
|
*/
|
|
fitToSphere(sphereOrMesh, enableTransition) {
|
|
const promises = [];
|
|
const isObject3D = "isObject3D" in sphereOrMesh;
|
|
const boundingSphere = isObject3D ? _CameraControls.createBoundingSphere(sphereOrMesh, _sphere) : _sphere.copy(sphereOrMesh);
|
|
promises.push(this.moveTo(boundingSphere.center.x, boundingSphere.center.y, boundingSphere.center.z, enableTransition));
|
|
if (isPerspectiveCamera(this._camera)) {
|
|
const distanceToFit = this.getDistanceToFitSphere(boundingSphere.radius);
|
|
promises.push(this.dollyTo(distanceToFit, enableTransition));
|
|
} else if (isOrthographicCamera(this._camera)) {
|
|
const width = this._camera.right - this._camera.left;
|
|
const height = this._camera.top - this._camera.bottom;
|
|
const diameter = 2 * boundingSphere.radius;
|
|
const zoom = Math.min(width / diameter, height / diameter);
|
|
promises.push(this.zoomTo(zoom, enableTransition));
|
|
}
|
|
promises.push(this.setFocalOffset(0, 0, 0, enableTransition));
|
|
return Promise.all(promises);
|
|
}
|
|
/**
|
|
* Look at the `target` from the `position`.
|
|
* @param positionX
|
|
* @param positionY
|
|
* @param positionZ
|
|
* @param targetX
|
|
* @param targetY
|
|
* @param targetZ
|
|
* @param enableTransition
|
|
* @category Methods
|
|
*/
|
|
setLookAt(positionX, positionY, positionZ, targetX, targetY, targetZ, enableTransition = false) {
|
|
this._isUserControllingRotate = false;
|
|
this._isUserControllingDolly = false;
|
|
this._isUserControllingTruck = false;
|
|
this._lastDollyDirection = DOLLY_DIRECTION.NONE;
|
|
this._changedDolly = 0;
|
|
const target2 = _v3B.set(targetX, targetY, targetZ);
|
|
const position2 = _v3A.set(positionX, positionY, positionZ);
|
|
this._targetEnd.copy(target2);
|
|
this._sphericalEnd.setFromVector3(position2.sub(target2).applyQuaternion(this._yAxisUpSpace));
|
|
this._needsUpdate = true;
|
|
if (!enableTransition) {
|
|
this._target.copy(this._targetEnd);
|
|
this._spherical.copy(this._sphericalEnd);
|
|
}
|
|
const resolveImmediately = !enableTransition || approxEquals(this._target.x, this._targetEnd.x, this.restThreshold) && approxEquals(this._target.y, this._targetEnd.y, this.restThreshold) && approxEquals(this._target.z, this._targetEnd.z, this.restThreshold) && approxEquals(this._spherical.theta, this._sphericalEnd.theta, this.restThreshold) && approxEquals(this._spherical.phi, this._sphericalEnd.phi, this.restThreshold) && approxEquals(this._spherical.radius, this._sphericalEnd.radius, this.restThreshold);
|
|
return this._createOnRestPromise(resolveImmediately);
|
|
}
|
|
/**
|
|
* Interpolates between two states.
|
|
* @param stateA
|
|
* @param stateB
|
|
* @param t
|
|
* @param enableTransition
|
|
* @category Methods
|
|
*/
|
|
lerp(stateA, stateB, t2, enableTransition = false) {
|
|
this._isUserControllingRotate = false;
|
|
this._isUserControllingDolly = false;
|
|
this._isUserControllingTruck = false;
|
|
this._lastDollyDirection = DOLLY_DIRECTION.NONE;
|
|
this._changedDolly = 0;
|
|
const targetA = _v3A.set(...stateA.target);
|
|
if ("spherical" in stateA) {
|
|
_sphericalA.set(...stateA.spherical);
|
|
} else {
|
|
const positionA = _v3B.set(...stateA.position);
|
|
_sphericalA.setFromVector3(positionA.sub(targetA).applyQuaternion(this._yAxisUpSpace));
|
|
}
|
|
const targetB = _v3C.set(...stateB.target);
|
|
if ("spherical" in stateB) {
|
|
_sphericalB.set(...stateB.spherical);
|
|
} else {
|
|
const positionB = _v3B.set(...stateB.position);
|
|
_sphericalB.setFromVector3(positionB.sub(targetB).applyQuaternion(this._yAxisUpSpace));
|
|
}
|
|
this._targetEnd.copy(targetA.lerp(targetB, t2));
|
|
const deltaTheta = _sphericalB.theta - _sphericalA.theta;
|
|
const deltaPhi = _sphericalB.phi - _sphericalA.phi;
|
|
const deltaRadius = _sphericalB.radius - _sphericalA.radius;
|
|
this._sphericalEnd.set(_sphericalA.radius + deltaRadius * t2, _sphericalA.phi + deltaPhi * t2, _sphericalA.theta + deltaTheta * t2);
|
|
this._needsUpdate = true;
|
|
if (!enableTransition) {
|
|
this._target.copy(this._targetEnd);
|
|
this._spherical.copy(this._sphericalEnd);
|
|
}
|
|
const resolveImmediately = !enableTransition || approxEquals(this._target.x, this._targetEnd.x, this.restThreshold) && approxEquals(this._target.y, this._targetEnd.y, this.restThreshold) && approxEquals(this._target.z, this._targetEnd.z, this.restThreshold) && approxEquals(this._spherical.theta, this._sphericalEnd.theta, this.restThreshold) && approxEquals(this._spherical.phi, this._sphericalEnd.phi, this.restThreshold) && approxEquals(this._spherical.radius, this._sphericalEnd.radius, this.restThreshold);
|
|
return this._createOnRestPromise(resolveImmediately);
|
|
}
|
|
/**
|
|
* Similar to setLookAt, but it interpolates between two states.
|
|
* @param positionAX
|
|
* @param positionAY
|
|
* @param positionAZ
|
|
* @param targetAX
|
|
* @param targetAY
|
|
* @param targetAZ
|
|
* @param positionBX
|
|
* @param positionBY
|
|
* @param positionBZ
|
|
* @param targetBX
|
|
* @param targetBY
|
|
* @param targetBZ
|
|
* @param t
|
|
* @param enableTransition
|
|
* @category Methods
|
|
*/
|
|
lerpLookAt(positionAX, positionAY, positionAZ, targetAX, targetAY, targetAZ, positionBX, positionBY, positionBZ, targetBX, targetBY, targetBZ, t2, enableTransition = false) {
|
|
return this.lerp({
|
|
position: [positionAX, positionAY, positionAZ],
|
|
target: [targetAX, targetAY, targetAZ]
|
|
}, {
|
|
position: [positionBX, positionBY, positionBZ],
|
|
target: [targetBX, targetBY, targetBZ]
|
|
}, t2, enableTransition);
|
|
}
|
|
/**
|
|
* Set angle and distance by given position.
|
|
* An alias of `setLookAt()`, without target change. Thus keep gazing at the current target
|
|
* @param positionX
|
|
* @param positionY
|
|
* @param positionZ
|
|
* @param enableTransition
|
|
* @category Methods
|
|
*/
|
|
setPosition(positionX, positionY, positionZ, enableTransition = false) {
|
|
return this.setLookAt(positionX, positionY, positionZ, this._targetEnd.x, this._targetEnd.y, this._targetEnd.z, enableTransition);
|
|
}
|
|
/**
|
|
* Set the target position where gaze at.
|
|
* An alias of `setLookAt()`, without position change. Thus keep the same position.
|
|
* @param targetX
|
|
* @param targetY
|
|
* @param targetZ
|
|
* @param enableTransition
|
|
* @category Methods
|
|
*/
|
|
setTarget(targetX, targetY, targetZ, enableTransition = false) {
|
|
const pos = this.getPosition(_v3A);
|
|
const promise = this.setLookAt(pos.x, pos.y, pos.z, targetX, targetY, targetZ, enableTransition);
|
|
this._sphericalEnd.phi = clamp3(this._sphericalEnd.phi, this.minPolarAngle, this.maxPolarAngle);
|
|
return promise;
|
|
}
|
|
/**
|
|
* Set focal offset using the screen parallel coordinates. z doesn't affect in Orthographic as with Dolly.
|
|
* @param x
|
|
* @param y
|
|
* @param z
|
|
* @param enableTransition
|
|
* @category Methods
|
|
*/
|
|
setFocalOffset(x, y, z, enableTransition = false) {
|
|
this._isUserControllingOffset = false;
|
|
this._focalOffsetEnd.set(x, y, z);
|
|
this._needsUpdate = true;
|
|
if (!enableTransition)
|
|
this._focalOffset.copy(this._focalOffsetEnd);
|
|
const resolveImmediately = !enableTransition || approxEquals(this._focalOffset.x, this._focalOffsetEnd.x, this.restThreshold) && approxEquals(this._focalOffset.y, this._focalOffsetEnd.y, this.restThreshold) && approxEquals(this._focalOffset.z, this._focalOffsetEnd.z, this.restThreshold);
|
|
return this._createOnRestPromise(resolveImmediately);
|
|
}
|
|
/**
|
|
* Set orbit point without moving the camera.
|
|
* SHOULD NOT RUN DURING ANIMATIONS. `setOrbitPoint()` will immediately fix the positions.
|
|
* @param targetX
|
|
* @param targetY
|
|
* @param targetZ
|
|
* @category Methods
|
|
*/
|
|
setOrbitPoint(targetX, targetY, targetZ) {
|
|
this._camera.updateMatrixWorld();
|
|
_xColumn.setFromMatrixColumn(this._camera.matrixWorldInverse, 0);
|
|
_yColumn.setFromMatrixColumn(this._camera.matrixWorldInverse, 1);
|
|
_zColumn.setFromMatrixColumn(this._camera.matrixWorldInverse, 2);
|
|
const position2 = _v3A.set(targetX, targetY, targetZ);
|
|
const distance3 = position2.distanceTo(this._camera.position);
|
|
const cameraToPoint = position2.sub(this._camera.position);
|
|
_xColumn.multiplyScalar(cameraToPoint.x);
|
|
_yColumn.multiplyScalar(cameraToPoint.y);
|
|
_zColumn.multiplyScalar(cameraToPoint.z);
|
|
_v3A.copy(_xColumn).add(_yColumn).add(_zColumn);
|
|
_v3A.z = _v3A.z + distance3;
|
|
this.dollyTo(distance3, false);
|
|
this.setFocalOffset(-_v3A.x, _v3A.y, -_v3A.z, false);
|
|
this.moveTo(targetX, targetY, targetZ, false);
|
|
}
|
|
/**
|
|
* Set the boundary box that encloses the target of the camera. box3 is in THREE.Box3
|
|
* @param box3
|
|
* @category Methods
|
|
*/
|
|
setBoundary(box3) {
|
|
if (!box3) {
|
|
this._boundary.min.set(-Infinity, -Infinity, -Infinity);
|
|
this._boundary.max.set(Infinity, Infinity, Infinity);
|
|
this._needsUpdate = true;
|
|
return;
|
|
}
|
|
this._boundary.copy(box3);
|
|
this._boundary.clampPoint(this._targetEnd, this._targetEnd);
|
|
this._needsUpdate = true;
|
|
}
|
|
/**
|
|
* Set (or unset) the current viewport.
|
|
* Set this when you want to use renderer viewport and .dollyToCursor feature at the same time.
|
|
* @param viewportOrX
|
|
* @param y
|
|
* @param width
|
|
* @param height
|
|
* @category Methods
|
|
*/
|
|
setViewport(viewportOrX, y, width, height) {
|
|
if (viewportOrX === null) {
|
|
this._viewport = null;
|
|
return;
|
|
}
|
|
this._viewport = this._viewport || new THREE.Vector4();
|
|
if (typeof viewportOrX === "number") {
|
|
this._viewport.set(viewportOrX, y, width, height);
|
|
} else {
|
|
this._viewport.copy(viewportOrX);
|
|
}
|
|
}
|
|
/**
|
|
* Calculate the distance to fit the box.
|
|
* @param width box width
|
|
* @param height box height
|
|
* @param depth box depth
|
|
* @returns distance
|
|
* @category Methods
|
|
*/
|
|
getDistanceToFitBox(width, height, depth, cover = false) {
|
|
if (notSupportedInOrthographicCamera(this._camera, "getDistanceToFitBox"))
|
|
return this._spherical.radius;
|
|
const boundingRectAspect = width / height;
|
|
const fov = this._camera.getEffectiveFOV() * DEG2RAD;
|
|
const aspect = this._camera.aspect;
|
|
const heightToFit = (cover ? boundingRectAspect > aspect : boundingRectAspect < aspect) ? height : width / aspect;
|
|
return heightToFit * 0.5 / Math.tan(fov * 0.5) + depth * 0.5;
|
|
}
|
|
/**
|
|
* Calculate the distance to fit the sphere.
|
|
* @param radius sphere radius
|
|
* @returns distance
|
|
* @category Methods
|
|
*/
|
|
getDistanceToFitSphere(radius) {
|
|
if (notSupportedInOrthographicCamera(this._camera, "getDistanceToFitSphere"))
|
|
return this._spherical.radius;
|
|
const vFOV = this._camera.getEffectiveFOV() * DEG2RAD;
|
|
const hFOV = Math.atan(Math.tan(vFOV * 0.5) * this._camera.aspect) * 2;
|
|
const fov = 1 < this._camera.aspect ? vFOV : hFOV;
|
|
return radius / Math.sin(fov * 0.5);
|
|
}
|
|
/**
|
|
* Returns the orbit center position, where the camera looking at.
|
|
* @param out The receiving Vector3 instance to copy the result
|
|
* @param receiveEndValue Whether receive the transition end coords or current. default is `true`
|
|
* @category Methods
|
|
*/
|
|
getTarget(out7, receiveEndValue = true) {
|
|
const _out = !!out7 && out7.isVector3 ? out7 : new THREE.Vector3();
|
|
return _out.copy(receiveEndValue ? this._targetEnd : this._target);
|
|
}
|
|
/**
|
|
* Returns the camera position.
|
|
* @param out The receiving Vector3 instance to copy the result
|
|
* @param receiveEndValue Whether receive the transition end coords or current. default is `true`
|
|
* @category Methods
|
|
*/
|
|
getPosition(out7, receiveEndValue = true) {
|
|
const _out = !!out7 && out7.isVector3 ? out7 : new THREE.Vector3();
|
|
return _out.setFromSpherical(receiveEndValue ? this._sphericalEnd : this._spherical).applyQuaternion(this._yAxisUpSpaceInverse).add(receiveEndValue ? this._targetEnd : this._target);
|
|
}
|
|
/**
|
|
* Returns the spherical coordinates of the orbit.
|
|
* @param out The receiving Spherical instance to copy the result
|
|
* @param receiveEndValue Whether receive the transition end coords or current. default is `true`
|
|
* @category Methods
|
|
*/
|
|
getSpherical(out7, receiveEndValue = true) {
|
|
const _out = out7 || new THREE.Spherical();
|
|
return _out.copy(receiveEndValue ? this._sphericalEnd : this._spherical);
|
|
}
|
|
/**
|
|
* Returns the focal offset, which is how much the camera appears to be translated in screen parallel coordinates.
|
|
* @param out The receiving Vector3 instance to copy the result
|
|
* @param receiveEndValue Whether receive the transition end coords or current. default is `true`
|
|
* @category Methods
|
|
*/
|
|
getFocalOffset(out7, receiveEndValue = true) {
|
|
const _out = !!out7 && out7.isVector3 ? out7 : new THREE.Vector3();
|
|
return _out.copy(receiveEndValue ? this._focalOffsetEnd : this._focalOffset);
|
|
}
|
|
/**
|
|
* Normalize camera azimuth angle (horizontal rotation) between -180 and 180 degrees.
|
|
* @returns This CameraControls instance.
|
|
* @category Methods
|
|
*/
|
|
normalizeRotations() {
|
|
this._sphericalEnd.theta = (this._sphericalEnd.theta % PI_2 + PI_2) % PI_2;
|
|
if (this._sphericalEnd.theta > Math.PI)
|
|
this._sphericalEnd.theta -= PI_2;
|
|
this._spherical.theta += PI_2 * Math.round((this._sphericalEnd.theta - this._spherical.theta) / PI_2);
|
|
return this;
|
|
}
|
|
/**
|
|
* stop all transitions.
|
|
*/
|
|
stop() {
|
|
this._focalOffset.copy(this._focalOffsetEnd);
|
|
this._target.copy(this._targetEnd);
|
|
this._spherical.copy(this._sphericalEnd);
|
|
this._zoom = this._zoomEnd;
|
|
}
|
|
/**
|
|
* Reset all rotation and position to defaults.
|
|
* @param enableTransition
|
|
* @category Methods
|
|
*/
|
|
reset(enableTransition = false) {
|
|
if (!approxEquals(this._camera.up.x, this._cameraUp0.x) || !approxEquals(this._camera.up.y, this._cameraUp0.y) || !approxEquals(this._camera.up.z, this._cameraUp0.z)) {
|
|
this._camera.up.copy(this._cameraUp0);
|
|
const position2 = this.getPosition(_v3A);
|
|
this.updateCameraUp();
|
|
this.setPosition(position2.x, position2.y, position2.z);
|
|
}
|
|
const promises = [
|
|
this.setLookAt(this._position0.x, this._position0.y, this._position0.z, this._target0.x, this._target0.y, this._target0.z, enableTransition),
|
|
this.setFocalOffset(this._focalOffset0.x, this._focalOffset0.y, this._focalOffset0.z, enableTransition),
|
|
this.zoomTo(this._zoom0, enableTransition)
|
|
];
|
|
return Promise.all(promises);
|
|
}
|
|
/**
|
|
* Set current camera position as the default position.
|
|
* @category Methods
|
|
*/
|
|
saveState() {
|
|
this._cameraUp0.copy(this._camera.up);
|
|
this.getTarget(this._target0);
|
|
this.getPosition(this._position0);
|
|
this._zoom0 = this._zoom;
|
|
this._focalOffset0.copy(this._focalOffset);
|
|
}
|
|
/**
|
|
* Sync camera-up direction.
|
|
* When camera-up vector is changed, `.updateCameraUp()` must be called.
|
|
* @category Methods
|
|
*/
|
|
updateCameraUp() {
|
|
this._yAxisUpSpace.setFromUnitVectors(this._camera.up, _AXIS_Y);
|
|
this._yAxisUpSpaceInverse.copy(this._yAxisUpSpace).invert();
|
|
}
|
|
/**
|
|
* Apply current camera-up direction to the camera.
|
|
* The orbit system will be re-initialized with the current position.
|
|
* @category Methods
|
|
*/
|
|
applyCameraUp() {
|
|
const cameraDirection = _v3A.subVectors(this._target, this._camera.position).normalize();
|
|
const side = _v3B.crossVectors(cameraDirection, this._camera.up);
|
|
this._camera.up.crossVectors(side, cameraDirection).normalize();
|
|
this._camera.updateMatrixWorld();
|
|
const position2 = this.getPosition(_v3A);
|
|
this.updateCameraUp();
|
|
this.setPosition(position2.x, position2.y, position2.z);
|
|
}
|
|
/**
|
|
* Update camera position and directions.
|
|
* This should be called in your tick loop every time, and returns true if re-rendering is needed.
|
|
* @param delta
|
|
* @returns updated
|
|
* @category Methods
|
|
*/
|
|
update(delta) {
|
|
const deltaTheta = this._sphericalEnd.theta - this._spherical.theta;
|
|
const deltaPhi = this._sphericalEnd.phi - this._spherical.phi;
|
|
const deltaRadius = this._sphericalEnd.radius - this._spherical.radius;
|
|
const deltaTarget = _deltaTarget.subVectors(this._targetEnd, this._target);
|
|
const deltaOffset = _deltaOffset.subVectors(this._focalOffsetEnd, this._focalOffset);
|
|
const deltaZoom = this._zoomEnd - this._zoom;
|
|
if (approxZero(deltaTheta)) {
|
|
this._thetaVelocity.value = 0;
|
|
this._spherical.theta = this._sphericalEnd.theta;
|
|
} else {
|
|
const smoothTime = this._isUserControllingRotate ? this.draggingSmoothTime : this.smoothTime;
|
|
this._spherical.theta = smoothDamp(this._spherical.theta, this._sphericalEnd.theta, this._thetaVelocity, smoothTime, Infinity, delta);
|
|
this._needsUpdate = true;
|
|
}
|
|
if (approxZero(deltaPhi)) {
|
|
this._phiVelocity.value = 0;
|
|
this._spherical.phi = this._sphericalEnd.phi;
|
|
} else {
|
|
const smoothTime = this._isUserControllingRotate ? this.draggingSmoothTime : this.smoothTime;
|
|
this._spherical.phi = smoothDamp(this._spherical.phi, this._sphericalEnd.phi, this._phiVelocity, smoothTime, Infinity, delta);
|
|
this._needsUpdate = true;
|
|
}
|
|
if (approxZero(deltaRadius)) {
|
|
this._radiusVelocity.value = 0;
|
|
this._spherical.radius = this._sphericalEnd.radius;
|
|
} else {
|
|
const smoothTime = this._isUserControllingDolly ? this.draggingSmoothTime : this.smoothTime;
|
|
this._spherical.radius = smoothDamp(this._spherical.radius, this._sphericalEnd.radius, this._radiusVelocity, smoothTime, this.maxSpeed, delta);
|
|
this._needsUpdate = true;
|
|
}
|
|
if (approxZero(deltaTarget.x) && approxZero(deltaTarget.y) && approxZero(deltaTarget.z)) {
|
|
this._targetVelocity.set(0, 0, 0);
|
|
this._target.copy(this._targetEnd);
|
|
} else {
|
|
const smoothTime = this._isUserControllingTruck ? this.draggingSmoothTime : this.smoothTime;
|
|
smoothDampVec3(this._target, this._targetEnd, this._targetVelocity, smoothTime, this.maxSpeed, delta, this._target);
|
|
this._needsUpdate = true;
|
|
}
|
|
if (approxZero(deltaOffset.x) && approxZero(deltaOffset.y) && approxZero(deltaOffset.z)) {
|
|
this._focalOffsetVelocity.set(0, 0, 0);
|
|
this._focalOffset.copy(this._focalOffsetEnd);
|
|
} else {
|
|
const smoothTime = this._isUserControllingOffset ? this.draggingSmoothTime : this.smoothTime;
|
|
smoothDampVec3(this._focalOffset, this._focalOffsetEnd, this._focalOffsetVelocity, smoothTime, this.maxSpeed, delta, this._focalOffset);
|
|
this._needsUpdate = true;
|
|
}
|
|
if (approxZero(deltaZoom)) {
|
|
this._zoomVelocity.value = 0;
|
|
this._zoom = this._zoomEnd;
|
|
} else {
|
|
const smoothTime = this._isUserControllingZoom ? this.draggingSmoothTime : this.smoothTime;
|
|
this._zoom = smoothDamp(this._zoom, this._zoomEnd, this._zoomVelocity, smoothTime, Infinity, delta);
|
|
}
|
|
if (this.dollyToCursor) {
|
|
if (isPerspectiveCamera(this._camera) && this._changedDolly !== 0) {
|
|
const dollyControlAmount = this._spherical.radius - this._lastDistance;
|
|
const camera = this._camera;
|
|
const cameraDirection = this._getCameraDirection(_cameraDirection);
|
|
const planeX = _v3A.copy(cameraDirection).cross(camera.up).normalize();
|
|
if (planeX.lengthSq() === 0)
|
|
planeX.x = 1;
|
|
const planeY = _v3B.crossVectors(planeX, cameraDirection);
|
|
const worldToScreen = this._sphericalEnd.radius * Math.tan(camera.getEffectiveFOV() * DEG2RAD * 0.5);
|
|
const prevRadius = this._sphericalEnd.radius - dollyControlAmount;
|
|
const lerpRatio = (prevRadius - this._sphericalEnd.radius) / this._sphericalEnd.radius;
|
|
const cursor = _v3C.copy(this._targetEnd).add(planeX.multiplyScalar(this._dollyControlCoord.x * worldToScreen * camera.aspect)).add(planeY.multiplyScalar(this._dollyControlCoord.y * worldToScreen));
|
|
const newTargetEnd = _v3A.copy(this._targetEnd).lerp(cursor, lerpRatio);
|
|
const isMin = this._lastDollyDirection === DOLLY_DIRECTION.IN && this._spherical.radius <= this.minDistance;
|
|
const isMax = this._lastDollyDirection === DOLLY_DIRECTION.OUT && this.maxDistance <= this._spherical.radius;
|
|
if (this.infinityDolly && (isMin || isMax)) {
|
|
this._sphericalEnd.radius -= dollyControlAmount;
|
|
this._spherical.radius -= dollyControlAmount;
|
|
const dollyAmount = _v3B.copy(cameraDirection).multiplyScalar(-dollyControlAmount);
|
|
newTargetEnd.add(dollyAmount);
|
|
}
|
|
this._boundary.clampPoint(newTargetEnd, newTargetEnd);
|
|
const targetEndDiff = _v3B.subVectors(newTargetEnd, this._targetEnd);
|
|
this._targetEnd.copy(newTargetEnd);
|
|
this._target.add(targetEndDiff);
|
|
this._changedDolly -= dollyControlAmount;
|
|
if (approxZero(this._changedDolly))
|
|
this._changedDolly = 0;
|
|
} else if (isOrthographicCamera(this._camera) && this._changedZoom !== 0) {
|
|
const dollyControlAmount = this._zoom - this._lastZoom;
|
|
const camera = this._camera;
|
|
const worldCursorPosition = _v3A.set(this._dollyControlCoord.x, this._dollyControlCoord.y, (camera.near + camera.far) / (camera.near - camera.far)).unproject(camera);
|
|
const quaternion = _v3B.set(0, 0, -1).applyQuaternion(camera.quaternion);
|
|
const cursor = _v3C.copy(worldCursorPosition).add(quaternion.multiplyScalar(-worldCursorPosition.dot(camera.up)));
|
|
const prevZoom = this._zoom - dollyControlAmount;
|
|
const lerpRatio = -(prevZoom - this._zoom) / this._zoom;
|
|
const cameraDirection = this._getCameraDirection(_cameraDirection);
|
|
const prevPlaneConstant = this._targetEnd.dot(cameraDirection);
|
|
const newTargetEnd = _v3A.copy(this._targetEnd).lerp(cursor, lerpRatio);
|
|
const newPlaneConstant = newTargetEnd.dot(cameraDirection);
|
|
const pullBack = cameraDirection.multiplyScalar(newPlaneConstant - prevPlaneConstant);
|
|
newTargetEnd.sub(pullBack);
|
|
this._boundary.clampPoint(newTargetEnd, newTargetEnd);
|
|
const targetEndDiff = _v3B.subVectors(newTargetEnd, this._targetEnd);
|
|
this._targetEnd.copy(newTargetEnd);
|
|
this._target.add(targetEndDiff);
|
|
this._changedZoom -= dollyControlAmount;
|
|
if (approxZero(this._changedZoom))
|
|
this._changedZoom = 0;
|
|
}
|
|
}
|
|
if (this._camera.zoom !== this._zoom) {
|
|
this._camera.zoom = this._zoom;
|
|
this._camera.updateProjectionMatrix();
|
|
this._updateNearPlaneCorners();
|
|
this._needsUpdate = true;
|
|
}
|
|
this._dragNeedsUpdate = true;
|
|
const maxDistance = this._collisionTest();
|
|
this._spherical.radius = Math.min(this._spherical.radius, maxDistance);
|
|
this._spherical.makeSafe();
|
|
this._camera.position.setFromSpherical(this._spherical).applyQuaternion(this._yAxisUpSpaceInverse).add(this._target);
|
|
this._camera.lookAt(this._target);
|
|
const affectOffset = !approxZero(this._focalOffset.x) || !approxZero(this._focalOffset.y) || !approxZero(this._focalOffset.z);
|
|
if (affectOffset) {
|
|
this._camera.matrix.compose(this._camera.position, this._camera.quaternion, this._camera.scale);
|
|
_xColumn.setFromMatrixColumn(this._camera.matrix, 0);
|
|
_yColumn.setFromMatrixColumn(this._camera.matrix, 1);
|
|
_zColumn.setFromMatrixColumn(this._camera.matrix, 2);
|
|
_xColumn.multiplyScalar(this._focalOffset.x);
|
|
_yColumn.multiplyScalar(-this._focalOffset.y);
|
|
_zColumn.multiplyScalar(this._focalOffset.z);
|
|
_v3A.copy(_xColumn).add(_yColumn).add(_zColumn);
|
|
this._camera.position.add(_v3A);
|
|
this._camera.updateMatrixWorld();
|
|
}
|
|
if (this._boundaryEnclosesCamera) {
|
|
this._encloseToBoundary(this._camera.position.copy(this._target), _v3A.setFromSpherical(this._spherical).applyQuaternion(this._yAxisUpSpaceInverse), 1);
|
|
}
|
|
const updated = this._needsUpdate;
|
|
if (updated && !this._updatedLastTime) {
|
|
this._hasRested = false;
|
|
this.dispatchEvent({ type: "wake" });
|
|
this.dispatchEvent({ type: "update" });
|
|
} else if (updated) {
|
|
this.dispatchEvent({ type: "update" });
|
|
if (approxZero(deltaTheta, this.restThreshold) && approxZero(deltaPhi, this.restThreshold) && approxZero(deltaRadius, this.restThreshold) && approxZero(deltaTarget.x, this.restThreshold) && approxZero(deltaTarget.y, this.restThreshold) && approxZero(deltaTarget.z, this.restThreshold) && approxZero(deltaOffset.x, this.restThreshold) && approxZero(deltaOffset.y, this.restThreshold) && approxZero(deltaOffset.z, this.restThreshold) && approxZero(deltaZoom, this.restThreshold) && !this._hasRested) {
|
|
this._hasRested = true;
|
|
this.dispatchEvent({ type: "rest" });
|
|
}
|
|
} else if (!updated && this._updatedLastTime) {
|
|
this.dispatchEvent({ type: "sleep" });
|
|
}
|
|
this._lastDistance = this._spherical.radius;
|
|
this._lastZoom = this._zoom;
|
|
this._updatedLastTime = updated;
|
|
this._needsUpdate = false;
|
|
return updated;
|
|
}
|
|
/**
|
|
* Get all state in JSON string
|
|
* @category Methods
|
|
*/
|
|
toJSON() {
|
|
return JSON.stringify({
|
|
enabled: this._enabled,
|
|
minDistance: this.minDistance,
|
|
maxDistance: infinityToMaxNumber(this.maxDistance),
|
|
minZoom: this.minZoom,
|
|
maxZoom: infinityToMaxNumber(this.maxZoom),
|
|
minPolarAngle: this.minPolarAngle,
|
|
maxPolarAngle: infinityToMaxNumber(this.maxPolarAngle),
|
|
minAzimuthAngle: infinityToMaxNumber(this.minAzimuthAngle),
|
|
maxAzimuthAngle: infinityToMaxNumber(this.maxAzimuthAngle),
|
|
smoothTime: this.smoothTime,
|
|
draggingSmoothTime: this.draggingSmoothTime,
|
|
dollySpeed: this.dollySpeed,
|
|
truckSpeed: this.truckSpeed,
|
|
dollyToCursor: this.dollyToCursor,
|
|
target: this._targetEnd.toArray(),
|
|
position: _v3A.setFromSpherical(this._sphericalEnd).add(this._targetEnd).toArray(),
|
|
zoom: this._zoomEnd,
|
|
focalOffset: this._focalOffsetEnd.toArray(),
|
|
target0: this._target0.toArray(),
|
|
position0: this._position0.toArray(),
|
|
zoom0: this._zoom0,
|
|
focalOffset0: this._focalOffset0.toArray()
|
|
});
|
|
}
|
|
/**
|
|
* Reproduce the control state with JSON. enableTransition is where anim or not in a boolean.
|
|
* @param json
|
|
* @param enableTransition
|
|
* @category Methods
|
|
*/
|
|
fromJSON(json, enableTransition = false) {
|
|
const obj = JSON.parse(json);
|
|
this.enabled = obj.enabled;
|
|
this.minDistance = obj.minDistance;
|
|
this.maxDistance = maxNumberToInfinity(obj.maxDistance);
|
|
this.minZoom = obj.minZoom;
|
|
this.maxZoom = maxNumberToInfinity(obj.maxZoom);
|
|
this.minPolarAngle = obj.minPolarAngle;
|
|
this.maxPolarAngle = maxNumberToInfinity(obj.maxPolarAngle);
|
|
this.minAzimuthAngle = maxNumberToInfinity(obj.minAzimuthAngle);
|
|
this.maxAzimuthAngle = maxNumberToInfinity(obj.maxAzimuthAngle);
|
|
this.smoothTime = obj.smoothTime;
|
|
this.draggingSmoothTime = obj.draggingSmoothTime;
|
|
this.dollySpeed = obj.dollySpeed;
|
|
this.truckSpeed = obj.truckSpeed;
|
|
this.dollyToCursor = obj.dollyToCursor;
|
|
this._target0.fromArray(obj.target0);
|
|
this._position0.fromArray(obj.position0);
|
|
this._zoom0 = obj.zoom0;
|
|
this._focalOffset0.fromArray(obj.focalOffset0);
|
|
this.moveTo(obj.target[0], obj.target[1], obj.target[2], enableTransition);
|
|
_sphericalA.setFromVector3(_v3A.fromArray(obj.position).sub(this._targetEnd).applyQuaternion(this._yAxisUpSpace));
|
|
this.rotateTo(_sphericalA.theta, _sphericalA.phi, enableTransition);
|
|
this.dollyTo(_sphericalA.radius, enableTransition);
|
|
this.zoomTo(obj.zoom, enableTransition);
|
|
this.setFocalOffset(obj.focalOffset[0], obj.focalOffset[1], obj.focalOffset[2], enableTransition);
|
|
this._needsUpdate = true;
|
|
}
|
|
/**
|
|
* Attach all internal event handlers to enable drag control.
|
|
* @category Methods
|
|
*/
|
|
connect(domElement) {
|
|
if (this._domElement) {
|
|
console.warn("camera-controls is already connected.");
|
|
return;
|
|
}
|
|
domElement.setAttribute("data-camera-controls-version", VERSION);
|
|
this._addAllEventListeners(domElement);
|
|
this._getClientRect(this._elementRect);
|
|
}
|
|
/**
|
|
* Detach all internal event handlers to disable drag control.
|
|
*/
|
|
disconnect() {
|
|
this.cancel();
|
|
this._removeAllEventListeners();
|
|
if (this._domElement) {
|
|
this._domElement.removeAttribute("data-camera-controls-version");
|
|
this._domElement = void 0;
|
|
}
|
|
}
|
|
/**
|
|
* Dispose the cameraControls instance itself, remove all eventListeners.
|
|
* @category Methods
|
|
*/
|
|
dispose() {
|
|
this.removeAllEventListeners();
|
|
this.disconnect();
|
|
}
|
|
// it's okay to expose public though
|
|
_getTargetDirection(out7) {
|
|
return out7.setFromSpherical(this._spherical).divideScalar(this._spherical.radius).applyQuaternion(this._yAxisUpSpaceInverse);
|
|
}
|
|
// it's okay to expose public though
|
|
_getCameraDirection(out7) {
|
|
return this._getTargetDirection(out7).negate();
|
|
}
|
|
_findPointerById(pointerId2) {
|
|
return this._activePointers.find((activePointer) => activePointer.pointerId === pointerId2);
|
|
}
|
|
_findPointerByMouseButton(mouseButton) {
|
|
return this._activePointers.find((activePointer) => activePointer.mouseButton === mouseButton);
|
|
}
|
|
_disposePointer(pointer) {
|
|
this._activePointers.splice(this._activePointers.indexOf(pointer), 1);
|
|
}
|
|
_encloseToBoundary(position2, offset, friction) {
|
|
const offsetLength2 = offset.lengthSq();
|
|
if (offsetLength2 === 0) {
|
|
return position2;
|
|
}
|
|
const newTarget = _v3B.copy(offset).add(position2);
|
|
const clampedTarget = this._boundary.clampPoint(newTarget, _v3C);
|
|
const deltaClampedTarget = clampedTarget.sub(newTarget);
|
|
const deltaClampedTargetLength2 = deltaClampedTarget.lengthSq();
|
|
if (deltaClampedTargetLength2 === 0) {
|
|
return position2.add(offset);
|
|
} else if (deltaClampedTargetLength2 === offsetLength2) {
|
|
return position2;
|
|
} else if (friction === 0) {
|
|
return position2.add(offset).add(deltaClampedTarget);
|
|
} else {
|
|
const offsetFactor = 1 + friction * deltaClampedTargetLength2 / offset.dot(deltaClampedTarget);
|
|
return position2.add(_v3B.copy(offset).multiplyScalar(offsetFactor)).add(deltaClampedTarget.multiplyScalar(1 - friction));
|
|
}
|
|
}
|
|
_updateNearPlaneCorners() {
|
|
if (isPerspectiveCamera(this._camera)) {
|
|
const camera = this._camera;
|
|
const near = camera.near;
|
|
const fov = camera.getEffectiveFOV() * DEG2RAD;
|
|
const heightHalf = Math.tan(fov * 0.5) * near;
|
|
const widthHalf = heightHalf * camera.aspect;
|
|
this._nearPlaneCorners[0].set(-widthHalf, -heightHalf, 0);
|
|
this._nearPlaneCorners[1].set(widthHalf, -heightHalf, 0);
|
|
this._nearPlaneCorners[2].set(widthHalf, heightHalf, 0);
|
|
this._nearPlaneCorners[3].set(-widthHalf, heightHalf, 0);
|
|
} else if (isOrthographicCamera(this._camera)) {
|
|
const camera = this._camera;
|
|
const zoomInv = 1 / camera.zoom;
|
|
const left = camera.left * zoomInv;
|
|
const right = camera.right * zoomInv;
|
|
const top = camera.top * zoomInv;
|
|
const bottom = camera.bottom * zoomInv;
|
|
this._nearPlaneCorners[0].set(left, top, 0);
|
|
this._nearPlaneCorners[1].set(right, top, 0);
|
|
this._nearPlaneCorners[2].set(right, bottom, 0);
|
|
this._nearPlaneCorners[3].set(left, bottom, 0);
|
|
}
|
|
}
|
|
_truckInternal = (deltaX, deltaY, dragToOffset, screenSpacePanning) => {
|
|
let truckX;
|
|
let pedestalY;
|
|
if (isPerspectiveCamera(this._camera)) {
|
|
const offset = _v3A.copy(this._camera.position).sub(this._target);
|
|
const fov = this._camera.getEffectiveFOV() * DEG2RAD;
|
|
const targetDistance = offset.length() * Math.tan(fov * 0.5);
|
|
truckX = this.truckSpeed * deltaX * targetDistance / this._elementRect.height;
|
|
pedestalY = this.truckSpeed * deltaY * targetDistance / this._elementRect.height;
|
|
} else if (isOrthographicCamera(this._camera)) {
|
|
const camera = this._camera;
|
|
truckX = this.truckSpeed * deltaX * (camera.right - camera.left) / camera.zoom / this._elementRect.width;
|
|
pedestalY = this.truckSpeed * deltaY * (camera.top - camera.bottom) / camera.zoom / this._elementRect.height;
|
|
} else {
|
|
return;
|
|
}
|
|
if (screenSpacePanning) {
|
|
dragToOffset ? this.setFocalOffset(this._focalOffsetEnd.x + truckX, this._focalOffsetEnd.y, this._focalOffsetEnd.z, true) : this.truck(truckX, 0, true);
|
|
this.forward(-pedestalY, true);
|
|
} else {
|
|
dragToOffset ? this.setFocalOffset(this._focalOffsetEnd.x + truckX, this._focalOffsetEnd.y + pedestalY, this._focalOffsetEnd.z, true) : this.truck(truckX, pedestalY, true);
|
|
}
|
|
};
|
|
_rotateInternal = (deltaX, deltaY) => {
|
|
const theta = PI_2 * this.azimuthRotateSpeed * deltaX / this._elementRect.height;
|
|
const phi = PI_2 * this.polarRotateSpeed * deltaY / this._elementRect.height;
|
|
this.rotate(theta, phi, true);
|
|
};
|
|
_dollyInternal = (delta, x, y) => {
|
|
const dollyScale = Math.pow(0.95, -delta * this.dollySpeed);
|
|
const lastDistance = this._sphericalEnd.radius;
|
|
const distance3 = this._sphericalEnd.radius * dollyScale;
|
|
const clampedDistance = clamp3(distance3, this.minDistance, this.maxDistance);
|
|
const overflowedDistance = clampedDistance - distance3;
|
|
if (this.infinityDolly && this.dollyToCursor) {
|
|
this._dollyToNoClamp(distance3, true);
|
|
} else if (this.infinityDolly && !this.dollyToCursor) {
|
|
this.dollyInFixed(overflowedDistance, true);
|
|
this._dollyToNoClamp(clampedDistance, true);
|
|
} else {
|
|
this._dollyToNoClamp(clampedDistance, true);
|
|
}
|
|
if (this.dollyToCursor) {
|
|
this._changedDolly += (this.infinityDolly ? distance3 : clampedDistance) - lastDistance;
|
|
this._dollyControlCoord.set(x, y);
|
|
}
|
|
this._lastDollyDirection = Math.sign(-delta);
|
|
};
|
|
_zoomInternal = (delta, x, y) => {
|
|
const zoomScale = Math.pow(0.95, delta * this.dollySpeed);
|
|
const lastZoom = this._zoom;
|
|
const zoom = this._zoom * zoomScale;
|
|
this.zoomTo(zoom, true);
|
|
if (this.dollyToCursor) {
|
|
this._changedZoom += zoom - lastZoom;
|
|
this._dollyControlCoord.set(x, y);
|
|
}
|
|
};
|
|
// lateUpdate
|
|
_collisionTest() {
|
|
let distance3 = Infinity;
|
|
const hasCollider = this.colliderMeshes.length >= 1;
|
|
if (!hasCollider)
|
|
return distance3;
|
|
if (notSupportedInOrthographicCamera(this._camera, "_collisionTest"))
|
|
return distance3;
|
|
const rayDirection = this._getTargetDirection(_cameraDirection);
|
|
_rotationMatrix.lookAt(_ORIGIN, rayDirection, this._camera.up);
|
|
for (let i3 = 0; i3 < 4; i3++) {
|
|
const nearPlaneCorner = _v3B.copy(this._nearPlaneCorners[i3]);
|
|
nearPlaneCorner.applyMatrix4(_rotationMatrix);
|
|
const origin2 = _v3C.addVectors(this._target, nearPlaneCorner);
|
|
_raycaster.set(origin2, rayDirection);
|
|
_raycaster.far = this._spherical.radius + 1;
|
|
const intersects = _raycaster.intersectObjects(this.colliderMeshes);
|
|
if (intersects.length !== 0 && intersects[0].distance < distance3) {
|
|
distance3 = intersects[0].distance;
|
|
}
|
|
}
|
|
return distance3;
|
|
}
|
|
/**
|
|
* Get its client rect and package into given `DOMRect` .
|
|
*/
|
|
_getClientRect(target2) {
|
|
if (!this._domElement)
|
|
return;
|
|
const rect = this._domElement.getBoundingClientRect();
|
|
target2.x = rect.left;
|
|
target2.y = rect.top;
|
|
if (this._viewport) {
|
|
target2.x += this._viewport.x;
|
|
target2.y += rect.height - this._viewport.w - this._viewport.y;
|
|
target2.width = this._viewport.z;
|
|
target2.height = this._viewport.w;
|
|
} else {
|
|
target2.width = rect.width;
|
|
target2.height = rect.height;
|
|
}
|
|
return target2;
|
|
}
|
|
_createOnRestPromise(resolveImmediately) {
|
|
if (resolveImmediately)
|
|
return Promise.resolve();
|
|
this._hasRested = false;
|
|
this.dispatchEvent({ type: "transitionstart" });
|
|
return new Promise((resolve) => {
|
|
const onResolve = () => {
|
|
this.removeEventListener("rest", onResolve);
|
|
resolve();
|
|
};
|
|
this.addEventListener("rest", onResolve);
|
|
});
|
|
}
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
_addAllEventListeners(_domElement) {
|
|
}
|
|
_removeAllEventListeners() {
|
|
}
|
|
/**
|
|
* backward compatible
|
|
* @deprecated use smoothTime (in seconds) instead
|
|
* @category Properties
|
|
*/
|
|
get dampingFactor() {
|
|
console.warn(".dampingFactor has been deprecated. use smoothTime (in seconds) instead.");
|
|
return 0;
|
|
}
|
|
/**
|
|
* backward compatible
|
|
* @deprecated use smoothTime (in seconds) instead
|
|
* @category Properties
|
|
*/
|
|
set dampingFactor(_) {
|
|
console.warn(".dampingFactor has been deprecated. use smoothTime (in seconds) instead.");
|
|
}
|
|
/**
|
|
* backward compatible
|
|
* @deprecated use draggingSmoothTime (in seconds) instead
|
|
* @category Properties
|
|
*/
|
|
get draggingDampingFactor() {
|
|
console.warn(".draggingDampingFactor has been deprecated. use draggingSmoothTime (in seconds) instead.");
|
|
return 0;
|
|
}
|
|
/**
|
|
* backward compatible
|
|
* @deprecated use draggingSmoothTime (in seconds) instead
|
|
* @category Properties
|
|
*/
|
|
set draggingDampingFactor(_) {
|
|
console.warn(".draggingDampingFactor has been deprecated. use draggingSmoothTime (in seconds) instead.");
|
|
}
|
|
static createBoundingSphere(object3d, out7 = new THREE.Sphere()) {
|
|
const boundingSphere = out7;
|
|
const center2 = boundingSphere.center;
|
|
_box3A.makeEmpty();
|
|
object3d.traverseVisible((object) => {
|
|
if (!object.isMesh)
|
|
return;
|
|
_box3A.expandByObject(object);
|
|
});
|
|
_box3A.getCenter(center2);
|
|
let maxRadiusSq = 0;
|
|
object3d.traverseVisible((object) => {
|
|
if (!object.isMesh)
|
|
return;
|
|
const mesh = object;
|
|
if (!mesh.geometry)
|
|
return;
|
|
const geometry3 = mesh.geometry.clone();
|
|
geometry3.applyMatrix4(mesh.matrixWorld);
|
|
const bufferGeometry = geometry3;
|
|
const position2 = bufferGeometry.attributes.position;
|
|
for (let i3 = 0, l2 = position2.count; i3 < l2; i3++) {
|
|
_v3A.fromBufferAttribute(position2, i3);
|
|
maxRadiusSq = Math.max(maxRadiusSq, center2.distanceToSquared(_v3A));
|
|
}
|
|
});
|
|
boundingSphere.radius = Math.sqrt(maxRadiusSq);
|
|
return boundingSphere;
|
|
}
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/CameraControls.js
|
|
var CameraControls2 = (0, import_react12.forwardRef)((props, ref) => {
|
|
const {
|
|
impl: SubclassImpl,
|
|
camera,
|
|
domElement,
|
|
makeDefault,
|
|
onControlStart,
|
|
onControl,
|
|
onControlEnd,
|
|
onTransitionStart,
|
|
onUpdate,
|
|
onWake,
|
|
onRest,
|
|
onSleep,
|
|
onStart,
|
|
onEnd,
|
|
onChange,
|
|
regress,
|
|
...restProps
|
|
} = props;
|
|
const Impl = SubclassImpl !== null && SubclassImpl !== void 0 ? SubclassImpl : CameraControls;
|
|
(0, import_react12.useMemo)(() => {
|
|
const subsetOfTHREE = {
|
|
Box3,
|
|
MathUtils: {
|
|
clamp: MathUtils.clamp
|
|
},
|
|
Matrix4,
|
|
Quaternion,
|
|
Raycaster,
|
|
Sphere,
|
|
Spherical,
|
|
Vector2,
|
|
Vector3,
|
|
Vector4
|
|
};
|
|
Impl.install({
|
|
THREE: subsetOfTHREE
|
|
});
|
|
extend({
|
|
CameraControlsImpl: Impl
|
|
});
|
|
}, [Impl]);
|
|
const defaultCamera = useThree((state) => state.camera);
|
|
const gl = useThree((state) => state.gl);
|
|
const invalidate = useThree((state) => state.invalidate);
|
|
const events = useThree((state) => state.events);
|
|
const setEvents = useThree((state) => state.setEvents);
|
|
const set = useThree((state) => state.set);
|
|
const get = useThree((state) => state.get);
|
|
const performance2 = useThree((state) => state.performance);
|
|
const explCamera = camera || defaultCamera;
|
|
const explDomElement = domElement || events.connected || gl.domElement;
|
|
const controls = (0, import_react12.useMemo)(() => new Impl(explCamera), [Impl, explCamera]);
|
|
useFrame((state, delta) => {
|
|
controls.update(delta);
|
|
}, -1);
|
|
(0, import_react12.useEffect)(() => {
|
|
controls.connect(explDomElement);
|
|
return () => void controls.disconnect();
|
|
}, [explDomElement, controls]);
|
|
(0, import_react12.useEffect)(() => {
|
|
function invalidateAndRegress() {
|
|
invalidate();
|
|
if (regress) performance2.regress();
|
|
}
|
|
const handleControlStart = (e2) => {
|
|
invalidateAndRegress();
|
|
onControlStart == null || onControlStart(e2);
|
|
onStart == null || onStart(e2);
|
|
};
|
|
const handleControl = (e2) => {
|
|
invalidateAndRegress();
|
|
onControl == null || onControl(e2);
|
|
onChange == null || onChange(e2);
|
|
};
|
|
const handleControlEnd = (e2) => {
|
|
onControlEnd == null || onControlEnd(e2);
|
|
onEnd == null || onEnd(e2);
|
|
};
|
|
const handleTransitionStart = (e2) => {
|
|
invalidateAndRegress();
|
|
onTransitionStart == null || onTransitionStart(e2);
|
|
onChange == null || onChange(e2);
|
|
};
|
|
const handleUpdate = (e2) => {
|
|
invalidateAndRegress();
|
|
onUpdate == null || onUpdate(e2);
|
|
onChange == null || onChange(e2);
|
|
};
|
|
const handleWake = (e2) => {
|
|
invalidateAndRegress();
|
|
onWake == null || onWake(e2);
|
|
onChange == null || onChange(e2);
|
|
};
|
|
const handleRest = (e2) => {
|
|
onRest == null || onRest(e2);
|
|
};
|
|
const handleSleep = (e2) => {
|
|
onSleep == null || onSleep(e2);
|
|
};
|
|
controls.addEventListener("controlstart", handleControlStart);
|
|
controls.addEventListener("control", handleControl);
|
|
controls.addEventListener("controlend", handleControlEnd);
|
|
controls.addEventListener("transitionstart", handleTransitionStart);
|
|
controls.addEventListener("update", handleUpdate);
|
|
controls.addEventListener("wake", handleWake);
|
|
controls.addEventListener("rest", handleRest);
|
|
controls.addEventListener("sleep", handleSleep);
|
|
return () => {
|
|
controls.removeEventListener("controlstart", handleControlStart);
|
|
controls.removeEventListener("control", handleControl);
|
|
controls.removeEventListener("controlend", handleControlEnd);
|
|
controls.removeEventListener("transitionstart", handleTransitionStart);
|
|
controls.removeEventListener("update", handleUpdate);
|
|
controls.removeEventListener("wake", handleWake);
|
|
controls.removeEventListener("rest", handleRest);
|
|
controls.removeEventListener("sleep", handleSleep);
|
|
};
|
|
}, [controls, invalidate, setEvents, regress, performance2, onControlStart, onControl, onControlEnd, onTransitionStart, onUpdate, onWake, onRest, onSleep, onChange, onStart, onEnd]);
|
|
(0, import_react12.useEffect)(() => {
|
|
if (makeDefault) {
|
|
const old = get().controls;
|
|
set({
|
|
controls
|
|
});
|
|
return () => set({
|
|
controls: old
|
|
});
|
|
}
|
|
}, [makeDefault, controls]);
|
|
return React52.createElement("primitive", _extends({
|
|
ref,
|
|
object: controls
|
|
}, restProps));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/MotionPathControls.js
|
|
var React53 = __toESM(require_react());
|
|
var isObject3DRef = (ref) => (ref == null ? void 0 : ref.current) instanceof Object3D;
|
|
var MotionContext = React53.createContext(null);
|
|
function useMotion() {
|
|
const context12 = React53.useContext(MotionContext);
|
|
if (!context12) throw new Error("useMotion hook must be used in a MotionPathControls component.");
|
|
return context12;
|
|
}
|
|
function Debug({
|
|
points = 50,
|
|
color = "black"
|
|
}) {
|
|
const {
|
|
path
|
|
} = useMotion();
|
|
const [dots, setDots] = React53.useState([]);
|
|
const material = React53.useMemo(() => new MeshBasicMaterial({
|
|
color
|
|
}), [color]);
|
|
const geometry3 = React53.useMemo(() => new SphereGeometry(0.025, 16, 16), []);
|
|
const last = React53.useRef([]);
|
|
React53.useEffect(() => {
|
|
if (path.curves !== last.current) {
|
|
setDots(path.getPoints(points));
|
|
last.current = path.curves;
|
|
}
|
|
});
|
|
return dots.map((item, index2) => React53.createElement("mesh", {
|
|
key: index2,
|
|
material,
|
|
geometry: geometry3,
|
|
position: [item.x, item.y, item.z]
|
|
}));
|
|
}
|
|
var MotionPathControls = React53.forwardRef(({
|
|
children,
|
|
curves = [],
|
|
debug = false,
|
|
debugColor = "black",
|
|
object,
|
|
focus,
|
|
loop = true,
|
|
offset = void 0,
|
|
smooth = false,
|
|
eps: eps2 = 1e-5,
|
|
damping = 0.1,
|
|
focusDamping = 0.1,
|
|
maxSpeed = Infinity,
|
|
...props
|
|
}, fref) => {
|
|
const {
|
|
camera
|
|
} = useThree();
|
|
const ref = React53.useRef(null);
|
|
const pos = React53.useRef(offset !== null && offset !== void 0 ? offset : 0);
|
|
const path = React53.useMemo(() => new CurvePath(), []);
|
|
const state = React53.useMemo(() => ({
|
|
focus,
|
|
object: (object == null ? void 0 : object.current) instanceof Object3D ? object : {
|
|
current: camera
|
|
},
|
|
path,
|
|
current: pos.current,
|
|
offset: pos.current,
|
|
point: new Vector3(),
|
|
tangent: new Vector3(),
|
|
next: new Vector3()
|
|
}), [focus, object]);
|
|
const instanceRef = useInstanceHandle(ref);
|
|
React53.useLayoutEffect(() => {
|
|
const instance = instanceRef.current;
|
|
path.curves = [];
|
|
const _curves = curves.length > 0 ? curves : instance.children.map((instance2) => instance2.object);
|
|
for (let i3 = 0; i3 < _curves.length; i3++) path.add(_curves[i3]);
|
|
if (smooth) {
|
|
const points = path.getPoints(typeof smooth === "number" ? smooth : 1);
|
|
const catmull = new CatmullRomCurve3(points);
|
|
path.curves = [catmull];
|
|
}
|
|
path.updateArcLengths();
|
|
});
|
|
React53.useImperativeHandle(fref, () => Object.assign(ref.current, {
|
|
motion: state
|
|
}), [state]);
|
|
React53.useLayoutEffect(() => {
|
|
pos.current = misc.repeat(pos.current, 1);
|
|
}, [offset]);
|
|
const vec = React53.useMemo(() => new Vector3(), []);
|
|
useFrame((_state, delta) => {
|
|
const lastOffset = state.offset;
|
|
easing.damp(pos, "current", offset !== void 0 ? offset : state.current, damping, delta, maxSpeed, void 0, eps2);
|
|
state.offset = loop ? misc.repeat(pos.current, 1) : misc.clamp(pos.current, 0, 1);
|
|
if (path.getCurveLengths().length > 0) {
|
|
path.getPointAt(state.offset, state.point);
|
|
path.getTangentAt(state.offset, state.tangent).normalize();
|
|
path.getPointAt(misc.repeat(pos.current - (lastOffset - state.offset), 1), state.next);
|
|
const target2 = (object == null ? void 0 : object.current) instanceof Object3D ? object.current : camera;
|
|
target2.position.copy(state.point);
|
|
if (focus) {
|
|
easing.dampLookAt(target2, isObject3DRef(focus) ? focus.current.getWorldPosition(vec) : focus, focusDamping, delta, maxSpeed, void 0, eps2);
|
|
}
|
|
}
|
|
});
|
|
return React53.createElement("group", _extends({
|
|
ref
|
|
}, props), React53.createElement(MotionContext.Provider, {
|
|
value: state
|
|
}, children, debug && React53.createElement(Debug, {
|
|
color: debugColor
|
|
})));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/GizmoHelper.js
|
|
var React55 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/core/Hud.js
|
|
var React54 = __toESM(require_react());
|
|
function RenderHud({
|
|
defaultScene,
|
|
defaultCamera,
|
|
renderPriority = 1
|
|
}) {
|
|
const {
|
|
gl,
|
|
scene,
|
|
camera
|
|
} = useThree();
|
|
let oldCLear;
|
|
useFrame(() => {
|
|
oldCLear = gl.autoClear;
|
|
if (renderPriority === 1) {
|
|
gl.autoClear = true;
|
|
gl.render(defaultScene, defaultCamera);
|
|
}
|
|
gl.autoClear = false;
|
|
gl.clearDepth();
|
|
gl.render(scene, camera);
|
|
gl.autoClear = oldCLear;
|
|
}, renderPriority);
|
|
return React54.createElement("group", {
|
|
onPointerOver: () => null
|
|
});
|
|
}
|
|
function Hud({
|
|
children,
|
|
renderPriority = 1
|
|
}) {
|
|
const {
|
|
scene: defaultScene,
|
|
camera: defaultCamera
|
|
} = useThree();
|
|
const [hudScene] = React54.useState(() => new Scene());
|
|
return React54.createElement(React54.Fragment, null, createPortal(React54.createElement(React54.Fragment, null, children, React54.createElement(RenderHud, {
|
|
defaultScene,
|
|
defaultCamera,
|
|
renderPriority
|
|
})), hudScene, {
|
|
events: {
|
|
priority: renderPriority + 1
|
|
}
|
|
}));
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/GizmoHelper.js
|
|
var Context = React55.createContext({});
|
|
var useGizmoContext = () => {
|
|
return React55.useContext(Context);
|
|
};
|
|
var turnRate = 2 * Math.PI;
|
|
var dummy = new Object3D();
|
|
var matrix2 = new Matrix4();
|
|
var [q1, q2] = [new Quaternion(), new Quaternion()];
|
|
var target = new Vector3();
|
|
var targetPosition = new Vector3();
|
|
var isOrbitControls = (controls) => {
|
|
return "minPolarAngle" in controls;
|
|
};
|
|
var isCameraControls = (controls) => {
|
|
return "getTarget" in controls;
|
|
};
|
|
var GizmoHelper = ({
|
|
alignment = "bottom-right",
|
|
margin = [80, 80],
|
|
renderPriority = 1,
|
|
onUpdate,
|
|
onTarget,
|
|
children
|
|
}) => {
|
|
const size = useThree((state) => state.size);
|
|
const mainCamera = useThree((state) => state.camera);
|
|
const defaultControls = useThree((state) => state.controls);
|
|
const invalidate = useThree((state) => state.invalidate);
|
|
const gizmoRef = React55.useRef(null);
|
|
const virtualCam = React55.useRef(null);
|
|
const animating = React55.useRef(false);
|
|
const radius = React55.useRef(0);
|
|
const focusPoint = React55.useRef(new Vector3(0, 0, 0));
|
|
const defaultUp = React55.useRef(new Vector3(0, 0, 0));
|
|
React55.useEffect(() => {
|
|
defaultUp.current.copy(mainCamera.up);
|
|
dummy.up.copy(mainCamera.up);
|
|
}, [mainCamera]);
|
|
const tweenCamera = React55.useCallback((direction2) => {
|
|
animating.current = true;
|
|
if (defaultControls || onTarget) {
|
|
focusPoint.current = (onTarget == null ? void 0 : onTarget()) || (isCameraControls(defaultControls) ? defaultControls.getTarget(focusPoint.current) : defaultControls == null ? void 0 : defaultControls.target);
|
|
}
|
|
radius.current = mainCamera.position.distanceTo(target);
|
|
q1.copy(mainCamera.quaternion);
|
|
targetPosition.copy(direction2).multiplyScalar(radius.current).add(target);
|
|
dummy.lookAt(targetPosition);
|
|
q2.copy(dummy.quaternion);
|
|
invalidate();
|
|
}, [defaultControls, mainCamera, onTarget, invalidate]);
|
|
useFrame((_, delta) => {
|
|
if (virtualCam.current && gizmoRef.current) {
|
|
var _gizmoRef$current;
|
|
if (animating.current) {
|
|
if (q1.angleTo(q2) < 0.01) {
|
|
animating.current = false;
|
|
if (isOrbitControls(defaultControls)) {
|
|
mainCamera.up.copy(defaultUp.current);
|
|
}
|
|
} else {
|
|
const step = delta * turnRate;
|
|
q1.rotateTowards(q2, step);
|
|
mainCamera.position.set(0, 0, 1).applyQuaternion(q1).multiplyScalar(radius.current).add(focusPoint.current);
|
|
mainCamera.up.set(0, 1, 0).applyQuaternion(q1).normalize();
|
|
mainCamera.quaternion.copy(q1);
|
|
if (isCameraControls(defaultControls)) defaultControls.setPosition(mainCamera.position.x, mainCamera.position.y, mainCamera.position.z);
|
|
if (onUpdate) onUpdate();
|
|
else if (defaultControls) defaultControls.update(delta);
|
|
invalidate();
|
|
}
|
|
}
|
|
matrix2.copy(mainCamera.matrix).invert();
|
|
(_gizmoRef$current = gizmoRef.current) == null || _gizmoRef$current.quaternion.setFromRotationMatrix(matrix2);
|
|
}
|
|
});
|
|
const gizmoHelperContext = React55.useMemo(() => ({
|
|
tweenCamera
|
|
}), [tweenCamera]);
|
|
const [marginX, marginY] = margin;
|
|
const x = alignment.endsWith("-center") ? 0 : alignment.endsWith("-left") ? -size.width / 2 + marginX : size.width / 2 - marginX;
|
|
const y = alignment.startsWith("center-") ? 0 : alignment.startsWith("top-") ? size.height / 2 - marginY : -size.height / 2 + marginY;
|
|
return React55.createElement(Hud, {
|
|
renderPriority
|
|
}, React55.createElement(Context.Provider, {
|
|
value: gizmoHelperContext
|
|
}, React55.createElement(OrthographicCamera2, {
|
|
makeDefault: true,
|
|
ref: virtualCam,
|
|
position: [0, 0, 200]
|
|
}), React55.createElement("group", {
|
|
ref: gizmoRef,
|
|
position: [x, y, 0]
|
|
}, children)));
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/GizmoViewcube.js
|
|
var React56 = __toESM(require_react());
|
|
var colors = {
|
|
bg: "#f0f0f0",
|
|
hover: "#999",
|
|
text: "black",
|
|
stroke: "black"
|
|
};
|
|
var defaultFaces = ["Right", "Left", "Top", "Bottom", "Front", "Back"];
|
|
var makePositionVector = (xyz) => new Vector3(...xyz).multiplyScalar(0.38);
|
|
var corners = [[1, 1, 1], [1, 1, -1], [1, -1, 1], [1, -1, -1], [-1, 1, 1], [-1, 1, -1], [-1, -1, 1], [-1, -1, -1]].map(makePositionVector);
|
|
var cornerDimensions = [0.25, 0.25, 0.25];
|
|
var edges = [[1, 1, 0], [1, 0, 1], [1, 0, -1], [1, -1, 0], [0, 1, 1], [0, 1, -1], [0, -1, 1], [0, -1, -1], [-1, 1, 0], [-1, 0, 1], [-1, 0, -1], [-1, -1, 0]].map(makePositionVector);
|
|
var edgeDimensions = edges.map((edge) => edge.toArray().map((axis) => axis == 0 ? 0.5 : 0.25));
|
|
var FaceMaterial = ({
|
|
hover,
|
|
index: index2,
|
|
font = "20px Inter var, Arial, sans-serif",
|
|
faces = defaultFaces,
|
|
color = colors.bg,
|
|
hoverColor = colors.hover,
|
|
textColor = colors.text,
|
|
strokeColor = colors.stroke,
|
|
opacity = 1
|
|
}) => {
|
|
const gl = useThree((state) => state.gl);
|
|
const texture = React56.useMemo(() => {
|
|
const canvas = document.createElement("canvas");
|
|
canvas.width = 128;
|
|
canvas.height = 128;
|
|
const context12 = canvas.getContext("2d");
|
|
context12.fillStyle = color;
|
|
context12.fillRect(0, 0, canvas.width, canvas.height);
|
|
context12.strokeStyle = strokeColor;
|
|
context12.strokeRect(0, 0, canvas.width, canvas.height);
|
|
context12.font = font;
|
|
context12.textAlign = "center";
|
|
context12.fillStyle = textColor;
|
|
context12.fillText(faces[index2].toUpperCase(), 64, 76);
|
|
return new CanvasTexture(canvas);
|
|
}, [index2, faces, font, color, textColor, strokeColor]);
|
|
return React56.createElement("meshBasicMaterial", {
|
|
map: texture,
|
|
"map-anisotropy": gl.capabilities.getMaxAnisotropy() || 1,
|
|
attach: `material-${index2}`,
|
|
color: hover ? hoverColor : "white",
|
|
transparent: true,
|
|
opacity
|
|
});
|
|
};
|
|
var FaceCube = (props) => {
|
|
const {
|
|
tweenCamera
|
|
} = useGizmoContext();
|
|
const [hover, setHover] = React56.useState(null);
|
|
const handlePointerOut = (e2) => {
|
|
e2.stopPropagation();
|
|
setHover(null);
|
|
};
|
|
const handleClick = (e2) => {
|
|
e2.stopPropagation();
|
|
tweenCamera(e2.face.normal);
|
|
};
|
|
const handlePointerMove = (e2) => {
|
|
e2.stopPropagation();
|
|
setHover(Math.floor(e2.faceIndex / 2));
|
|
};
|
|
return React56.createElement("mesh", {
|
|
onPointerOut: handlePointerOut,
|
|
onPointerMove: handlePointerMove,
|
|
onClick: props.onClick || handleClick
|
|
}, [...Array(6)].map((_, index2) => React56.createElement(FaceMaterial, _extends({
|
|
key: index2,
|
|
index: index2,
|
|
hover: hover === index2
|
|
}, props))), React56.createElement("boxGeometry", null));
|
|
};
|
|
var EdgeCube = ({
|
|
onClick,
|
|
dimensions,
|
|
position: position2,
|
|
hoverColor = colors.hover
|
|
}) => {
|
|
const {
|
|
tweenCamera
|
|
} = useGizmoContext();
|
|
const [hover, setHover] = React56.useState(false);
|
|
const handlePointerOut = (e2) => {
|
|
e2.stopPropagation();
|
|
setHover(false);
|
|
};
|
|
const handlePointerOver = (e2) => {
|
|
e2.stopPropagation();
|
|
setHover(true);
|
|
};
|
|
const handleClick = (e2) => {
|
|
e2.stopPropagation();
|
|
tweenCamera(position2);
|
|
};
|
|
return React56.createElement("mesh", {
|
|
scale: 1.01,
|
|
position: position2,
|
|
onPointerOver: handlePointerOver,
|
|
onPointerOut: handlePointerOut,
|
|
onClick: onClick || handleClick
|
|
}, React56.createElement("meshBasicMaterial", {
|
|
color: hover ? hoverColor : "white",
|
|
transparent: true,
|
|
opacity: 0.6,
|
|
visible: hover
|
|
}), React56.createElement("boxGeometry", {
|
|
args: dimensions
|
|
}));
|
|
};
|
|
var GizmoViewcube = (props) => {
|
|
return React56.createElement("group", {
|
|
scale: [60, 60, 60]
|
|
}, React56.createElement(FaceCube, props), edges.map((edge, index2) => React56.createElement(EdgeCube, _extends({
|
|
key: index2,
|
|
position: edge,
|
|
dimensions: edgeDimensions[index2]
|
|
}, props))), corners.map((corner, index2) => React56.createElement(EdgeCube, _extends({
|
|
key: index2,
|
|
position: corner,
|
|
dimensions: cornerDimensions
|
|
}, props))));
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/GizmoViewport.js
|
|
var React57 = __toESM(require_react());
|
|
function Axis({
|
|
scale: scale5 = [0.8, 0.05, 0.05],
|
|
color,
|
|
rotation: rotation3
|
|
}) {
|
|
return React57.createElement("group", {
|
|
rotation: rotation3
|
|
}, React57.createElement("mesh", {
|
|
position: [0.4, 0, 0]
|
|
}, React57.createElement("boxGeometry", {
|
|
args: scale5
|
|
}), React57.createElement("meshBasicMaterial", {
|
|
color,
|
|
toneMapped: false
|
|
})));
|
|
}
|
|
function AxisHead({
|
|
onClick,
|
|
font,
|
|
disabled,
|
|
arcStyle,
|
|
label,
|
|
labelColor,
|
|
axisHeadScale = 1,
|
|
...props
|
|
}) {
|
|
const gl = useThree((state) => state.gl);
|
|
const texture = React57.useMemo(() => {
|
|
const canvas = document.createElement("canvas");
|
|
canvas.width = 64;
|
|
canvas.height = 64;
|
|
const context12 = canvas.getContext("2d");
|
|
context12.beginPath();
|
|
context12.arc(32, 32, 16, 0, 2 * Math.PI);
|
|
context12.closePath();
|
|
context12.fillStyle = arcStyle;
|
|
context12.fill();
|
|
if (label) {
|
|
context12.font = font;
|
|
context12.textAlign = "center";
|
|
context12.fillStyle = labelColor;
|
|
context12.fillText(label, 32, 41);
|
|
}
|
|
return new CanvasTexture(canvas);
|
|
}, [arcStyle, label, labelColor, font]);
|
|
const [active, setActive] = React57.useState(false);
|
|
const scale5 = (label ? 1 : 0.75) * (active ? 1.2 : 1) * axisHeadScale;
|
|
const handlePointerOver = (e2) => {
|
|
e2.stopPropagation();
|
|
setActive(true);
|
|
};
|
|
const handlePointerOut = (e2) => {
|
|
e2.stopPropagation();
|
|
setActive(false);
|
|
};
|
|
return React57.createElement("sprite", _extends({
|
|
scale: scale5,
|
|
onPointerOver: !disabled ? handlePointerOver : void 0,
|
|
onPointerOut: !disabled ? onClick || handlePointerOut : void 0
|
|
}, props), React57.createElement("spriteMaterial", {
|
|
map: texture,
|
|
"map-anisotropy": gl.capabilities.getMaxAnisotropy() || 1,
|
|
alphaTest: 0.3,
|
|
opacity: label ? 1 : 0.75,
|
|
toneMapped: false
|
|
}));
|
|
}
|
|
var GizmoViewport = ({
|
|
hideNegativeAxes,
|
|
hideAxisHeads,
|
|
disabled,
|
|
font = "18px Inter var, Arial, sans-serif",
|
|
axisColors = ["#ff2060", "#20df80", "#2080ff"],
|
|
axisHeadScale = 1,
|
|
axisScale,
|
|
labels = ["X", "Y", "Z"],
|
|
labelColor = "#000",
|
|
onClick,
|
|
...props
|
|
}) => {
|
|
const [colorX, colorY, colorZ] = axisColors;
|
|
const {
|
|
tweenCamera
|
|
} = useGizmoContext();
|
|
const axisHeadProps = {
|
|
font,
|
|
disabled,
|
|
labelColor,
|
|
onClick,
|
|
axisHeadScale,
|
|
onPointerDown: !disabled ? (e2) => {
|
|
tweenCamera(e2.object.position);
|
|
e2.stopPropagation();
|
|
} : void 0
|
|
};
|
|
return React57.createElement("group", _extends({
|
|
scale: 40
|
|
}, props), React57.createElement(Axis, {
|
|
color: colorX,
|
|
rotation: [0, 0, 0],
|
|
scale: axisScale
|
|
}), React57.createElement(Axis, {
|
|
color: colorY,
|
|
rotation: [0, 0, Math.PI / 2],
|
|
scale: axisScale
|
|
}), React57.createElement(Axis, {
|
|
color: colorZ,
|
|
rotation: [0, -Math.PI / 2, 0],
|
|
scale: axisScale
|
|
}), !hideAxisHeads && React57.createElement(React57.Fragment, null, React57.createElement(AxisHead, _extends({
|
|
arcStyle: colorX,
|
|
position: [1, 0, 0],
|
|
label: labels[0]
|
|
}, axisHeadProps)), React57.createElement(AxisHead, _extends({
|
|
arcStyle: colorY,
|
|
position: [0, 1, 0],
|
|
label: labels[1]
|
|
}, axisHeadProps)), React57.createElement(AxisHead, _extends({
|
|
arcStyle: colorZ,
|
|
position: [0, 0, 1],
|
|
label: labels[2]
|
|
}, axisHeadProps)), !hideNegativeAxes && React57.createElement(React57.Fragment, null, React57.createElement(AxisHead, _extends({
|
|
arcStyle: colorX,
|
|
position: [-1, 0, 0]
|
|
}, axisHeadProps)), React57.createElement(AxisHead, _extends({
|
|
arcStyle: colorY,
|
|
position: [0, -1, 0]
|
|
}, axisHeadProps)), React57.createElement(AxisHead, _extends({
|
|
arcStyle: colorZ,
|
|
position: [0, 0, -1]
|
|
}, axisHeadProps)))));
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/Grid.js
|
|
var React58 = __toESM(require_react());
|
|
var GridMaterial = shaderMaterial(
|
|
{
|
|
cellSize: 0.5,
|
|
sectionSize: 1,
|
|
fadeDistance: 100,
|
|
fadeStrength: 1,
|
|
fadeFrom: 1,
|
|
cellThickness: 0.5,
|
|
sectionThickness: 1,
|
|
cellColor: new Color(),
|
|
sectionColor: new Color(),
|
|
infiniteGrid: false,
|
|
followCamera: false,
|
|
worldCamProjPosition: new Vector3(),
|
|
worldPlanePosition: new Vector3()
|
|
},
|
|
/* glsl */
|
|
`
|
|
varying vec3 localPosition;
|
|
varying vec4 worldPosition;
|
|
|
|
uniform vec3 worldCamProjPosition;
|
|
uniform vec3 worldPlanePosition;
|
|
uniform float fadeDistance;
|
|
uniform bool infiniteGrid;
|
|
uniform bool followCamera;
|
|
|
|
void main() {
|
|
localPosition = position.xzy;
|
|
if (infiniteGrid) localPosition *= 1.0 + fadeDistance;
|
|
|
|
worldPosition = modelMatrix * vec4(localPosition, 1.0);
|
|
if (followCamera) {
|
|
worldPosition.xyz += (worldCamProjPosition - worldPlanePosition);
|
|
localPosition = (inverse(modelMatrix) * worldPosition).xyz;
|
|
}
|
|
|
|
gl_Position = projectionMatrix * viewMatrix * worldPosition;
|
|
}
|
|
`,
|
|
/* glsl */
|
|
`
|
|
varying vec3 localPosition;
|
|
varying vec4 worldPosition;
|
|
|
|
uniform vec3 worldCamProjPosition;
|
|
uniform float cellSize;
|
|
uniform float sectionSize;
|
|
uniform vec3 cellColor;
|
|
uniform vec3 sectionColor;
|
|
uniform float fadeDistance;
|
|
uniform float fadeStrength;
|
|
uniform float fadeFrom;
|
|
uniform float cellThickness;
|
|
uniform float sectionThickness;
|
|
|
|
float getGrid(float size, float thickness) {
|
|
vec2 r = localPosition.xz / size;
|
|
vec2 grid = abs(fract(r - 0.5) - 0.5) / fwidth(r);
|
|
float line = min(grid.x, grid.y) + 1.0 - thickness;
|
|
return 1.0 - min(line, 1.0);
|
|
}
|
|
|
|
void main() {
|
|
float g1 = getGrid(cellSize, cellThickness);
|
|
float g2 = getGrid(sectionSize, sectionThickness);
|
|
|
|
vec3 from = worldCamProjPosition*vec3(fadeFrom);
|
|
float dist = distance(from, worldPosition.xyz);
|
|
float d = 1.0 - min(dist / fadeDistance, 1.0);
|
|
vec3 color = mix(cellColor, sectionColor, min(1.0, sectionThickness * g2));
|
|
|
|
gl_FragColor = vec4(color, (g1 + g2) * pow(d, fadeStrength));
|
|
gl_FragColor.a = mix(0.75 * gl_FragColor.a, gl_FragColor.a, g2);
|
|
if (gl_FragColor.a <= 0.0) discard;
|
|
|
|
#include <tonemapping_fragment>
|
|
#include <${version >= 154 ? "colorspace_fragment" : "encodings_fragment"}>
|
|
}
|
|
`
|
|
);
|
|
var Grid = React58.forwardRef(({
|
|
args,
|
|
cellColor = "#000000",
|
|
sectionColor = "#2080ff",
|
|
cellSize = 0.5,
|
|
sectionSize = 1,
|
|
followCamera = false,
|
|
infiniteGrid = false,
|
|
fadeDistance = 100,
|
|
fadeStrength = 1,
|
|
fadeFrom = 1,
|
|
cellThickness = 0.5,
|
|
sectionThickness = 1,
|
|
side = BackSide,
|
|
...props
|
|
}, fRef) => {
|
|
extend({
|
|
GridMaterial
|
|
});
|
|
const ref = React58.useRef(null);
|
|
React58.useImperativeHandle(fRef, () => ref.current, []);
|
|
const plane = new Plane();
|
|
const upVector = new Vector3(0, 1, 0);
|
|
const zeroVector = new Vector3(0, 0, 0);
|
|
useFrame((state) => {
|
|
plane.setFromNormalAndCoplanarPoint(upVector, zeroVector).applyMatrix4(ref.current.matrixWorld);
|
|
const gridMaterial = ref.current.material;
|
|
const worldCamProjPosition = gridMaterial.uniforms.worldCamProjPosition;
|
|
const worldPlanePosition = gridMaterial.uniforms.worldPlanePosition;
|
|
plane.projectPoint(state.camera.position, worldCamProjPosition.value);
|
|
worldPlanePosition.value.set(0, 0, 0).applyMatrix4(ref.current.matrixWorld);
|
|
});
|
|
const uniforms1 = {
|
|
cellSize,
|
|
sectionSize,
|
|
cellColor,
|
|
sectionColor,
|
|
cellThickness,
|
|
sectionThickness
|
|
};
|
|
const uniforms2 = {
|
|
fadeDistance,
|
|
fadeStrength,
|
|
fadeFrom,
|
|
infiniteGrid,
|
|
followCamera
|
|
};
|
|
return React58.createElement("mesh", _extends({
|
|
ref,
|
|
frustumCulled: false
|
|
}, props), React58.createElement("gridMaterial", _extends({
|
|
transparent: true,
|
|
"extensions-derivatives": true,
|
|
side
|
|
}, uniforms1, uniforms2)), React58.createElement("planeGeometry", {
|
|
args
|
|
}));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/CubeTexture.js
|
|
var React59 = __toESM(require_react());
|
|
function useCubeTexture(files, {
|
|
path
|
|
}) {
|
|
const [cubeTexture] = useLoader(CubeTextureLoader, [files], (loader2) => loader2.setPath(path));
|
|
return cubeTexture;
|
|
}
|
|
useCubeTexture.preload = (files, {
|
|
path
|
|
}) => useLoader.preload(CubeTextureLoader, [files], (loader2) => loader2.setPath(path));
|
|
function CubeTexture({
|
|
children,
|
|
files,
|
|
...options
|
|
}) {
|
|
const texture = useCubeTexture(files, {
|
|
...options
|
|
});
|
|
return React59.createElement(React59.Fragment, null, children == null ? void 0 : children(texture));
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/Fbx.js
|
|
var React60 = __toESM(require_react());
|
|
function useFBX(path) {
|
|
return useLoader(FBXLoader, path);
|
|
}
|
|
useFBX.preload = (path) => useLoader.preload(FBXLoader, path);
|
|
useFBX.clear = (input) => useLoader.clear(FBXLoader, input);
|
|
function Fbx({
|
|
path,
|
|
...props
|
|
}) {
|
|
const fbx = useFBX(path);
|
|
const object = fbx.children[0];
|
|
return React60.createElement(Clone, _extends({}, props, {
|
|
object
|
|
}));
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/Ktx2.js
|
|
var React61 = __toESM(require_react());
|
|
var import_react13 = __toESM(require_react());
|
|
var cdn = "https://cdn.jsdelivr.net/gh/pmndrs/drei-assets@master";
|
|
function useKTX2(input, basisPath = `${cdn}/basis/`) {
|
|
const gl = useThree((state) => state.gl);
|
|
const textures = useLoader(KTX2Loader, IsObject(input) ? Object.values(input) : input, (loader2) => {
|
|
loader2.detectSupport(gl);
|
|
loader2.setTranscoderPath(basisPath);
|
|
});
|
|
(0, import_react13.useEffect)(() => {
|
|
const array = Array.isArray(textures) ? textures : [textures];
|
|
array.forEach(gl.initTexture);
|
|
}, [gl, textures]);
|
|
if (IsObject(input)) {
|
|
const keys = Object.keys(input);
|
|
const keyed = {};
|
|
keys.forEach((key) => Object.assign(keyed, {
|
|
[key]: textures[keys.indexOf(key)]
|
|
}));
|
|
return keyed;
|
|
} else {
|
|
return textures;
|
|
}
|
|
}
|
|
useKTX2.preload = (url, basisPath = `${cdn}/basis/`) => useLoader.preload(KTX2Loader, url, (loader2) => {
|
|
loader2.setTranscoderPath(basisPath);
|
|
});
|
|
useKTX2.clear = (input) => useLoader.clear(KTX2Loader, input);
|
|
var Ktx2 = ({
|
|
children,
|
|
input,
|
|
basisPath
|
|
}) => {
|
|
const texture = useKTX2(input, basisPath);
|
|
return React61.createElement(React61.Fragment, null, children == null ? void 0 : children(texture));
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/VideoTexture.js
|
|
var React62 = __toESM(require_react());
|
|
var import_react14 = __toESM(require_react());
|
|
var IS_BROWSER = ((_window$document2, _window$navigator2) => typeof window !== "undefined" && typeof ((_window$document2 = window.document) == null ? void 0 : _window$document2.createElement) === "function" && typeof ((_window$navigator2 = window.navigator) == null ? void 0 : _window$navigator2.userAgent) === "string")();
|
|
var _HLSModule = null;
|
|
async function getHls(...args) {
|
|
var _HLSModule2;
|
|
(_HLSModule2 = _HLSModule) !== null && _HLSModule2 !== void 0 ? _HLSModule2 : _HLSModule = await import("./hls-Q6LDPZPT.js");
|
|
const Ctor = _HLSModule.default;
|
|
if (Ctor.isSupported()) {
|
|
return new Ctor(...args);
|
|
}
|
|
return null;
|
|
}
|
|
function useVideoTexture(srcOrSrcObject, {
|
|
unsuspend = "loadedmetadata",
|
|
start = true,
|
|
hls: hlsConfig = {},
|
|
crossOrigin = "anonymous",
|
|
muted = true,
|
|
loop = true,
|
|
playsInline = true,
|
|
onVideoFrame,
|
|
...videoProps
|
|
} = {}) {
|
|
const gl = useThree((state) => state.gl);
|
|
const hlsRef = (0, import_react14.useRef)(null);
|
|
const texture = suspend(() => new Promise(async (res) => {
|
|
let src = void 0;
|
|
let srcObject = void 0;
|
|
if (typeof srcOrSrcObject === "string") {
|
|
src = srcOrSrcObject;
|
|
} else {
|
|
srcObject = srcOrSrcObject;
|
|
}
|
|
const video2 = Object.assign(document.createElement("video"), {
|
|
src,
|
|
srcObject,
|
|
crossOrigin,
|
|
loop,
|
|
muted,
|
|
playsInline,
|
|
...videoProps
|
|
});
|
|
if (src && IS_BROWSER && src.endsWith(".m3u8")) {
|
|
const hls = hlsRef.current = await getHls(hlsConfig);
|
|
if (hls) {
|
|
hls.on(Events.MEDIA_ATTACHED, () => void hls.loadSource(src));
|
|
hls.attachMedia(video2);
|
|
}
|
|
}
|
|
const texture2 = new VideoTexture(video2);
|
|
texture2.colorSpace = gl.outputColorSpace;
|
|
video2.addEventListener(unsuspend, () => res(texture2));
|
|
}), [srcOrSrcObject]);
|
|
const video = texture.source.data;
|
|
useVideoFrame(video, onVideoFrame);
|
|
(0, import_react14.useEffect)(() => {
|
|
start && texture.image.play();
|
|
return () => {
|
|
if (hlsRef.current) {
|
|
hlsRef.current.destroy();
|
|
hlsRef.current = null;
|
|
}
|
|
};
|
|
}, [texture, start]);
|
|
return texture;
|
|
}
|
|
var VideoTexture2 = (0, import_react14.forwardRef)(({
|
|
children,
|
|
src,
|
|
...config
|
|
}, fref) => {
|
|
const texture = useVideoTexture(src, config);
|
|
(0, import_react14.useEffect)(() => {
|
|
return () => void texture.dispose();
|
|
}, [texture]);
|
|
(0, import_react14.useImperativeHandle)(fref, () => texture, [texture]);
|
|
return React62.createElement(React62.Fragment, null, children == null ? void 0 : children(texture));
|
|
});
|
|
var useVideoFrame = (video, f2) => {
|
|
(0, import_react14.useEffect)(() => {
|
|
if (!f2) return;
|
|
if (!video.requestVideoFrameCallback) return;
|
|
let handle;
|
|
const callback = (...args) => {
|
|
f2(...args);
|
|
handle = video.requestVideoFrameCallback(callback);
|
|
};
|
|
video.requestVideoFrameCallback(callback);
|
|
return () => video.cancelVideoFrameCallback(handle);
|
|
}, [video, f2]);
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/useSpriteLoader.js
|
|
var React63 = __toESM(require_react());
|
|
var import_react15 = __toESM(require_react());
|
|
var getFirstFrame = (frames, frameName) => {
|
|
if (Array.isArray(frames)) {
|
|
return frames[0];
|
|
} else {
|
|
const k = frameName !== null && frameName !== void 0 ? frameName : Object.keys(frames)[0];
|
|
return frames[k][0];
|
|
}
|
|
};
|
|
var checkIfFrameIsEmpty = (frameData) => {
|
|
for (let i3 = 3; i3 < frameData.length; i3 += 4) {
|
|
if (frameData[i3] !== 0) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
function useSpriteLoader(input, json, animationNames, numberOfFrames, onLoad, canvasRenderingContext2DSettings) {
|
|
const viewportRef = React63.useRef(useThree((state) => state.viewport));
|
|
const spriteDataRef = React63.useRef(null);
|
|
const totalFrames = React63.useRef(0);
|
|
const aspectFactor = 0.1;
|
|
const inputRef = React63.useRef(input);
|
|
const jsonRef = React63.useRef(json);
|
|
const animationFramesRef = React63.useRef(animationNames);
|
|
const [spriteData, setSpriteData] = (0, import_react15.useState)(null);
|
|
const [spriteTexture, setSpriteTexture] = React63.useState(new Texture());
|
|
const textureLoader = React63.useMemo(() => new TextureLoader(), []);
|
|
const [spriteObj, setSpriteObj] = (0, import_react15.useState)(null);
|
|
const calculateAspectRatio = React63.useCallback((width, height, factor) => {
|
|
const adaptedHeight = height * (viewportRef.current.aspect > width / height ? viewportRef.current.width / width : viewportRef.current.height / height);
|
|
const adaptedWidth = width * (viewportRef.current.aspect > width / height ? viewportRef.current.width / width : viewportRef.current.height / height);
|
|
const scaleX = adaptedWidth * factor;
|
|
const scaleY = adaptedHeight * factor;
|
|
const currentMaxScale = 1;
|
|
let finalMaxScaleW = Math.min(currentMaxScale, scaleX);
|
|
let finalMaxScaleH = Math.min(currentMaxScale, scaleY);
|
|
if (scaleX > currentMaxScale) {
|
|
finalMaxScaleW = currentMaxScale;
|
|
finalMaxScaleH = scaleY / scaleX * currentMaxScale;
|
|
}
|
|
return new Vector3(finalMaxScaleW, finalMaxScaleH, 1);
|
|
}, []);
|
|
const getRowsAndColumns = React63.useCallback((texture, totalFrames2) => {
|
|
if (texture.image) {
|
|
const canvas = document.createElement("canvas");
|
|
const ctx = canvas.getContext("2d", canvasRenderingContext2DSettings);
|
|
if (!ctx) {
|
|
throw new Error("Failed to get 2d context");
|
|
}
|
|
canvas.width = texture.image.width;
|
|
canvas.height = texture.image.height;
|
|
ctx.drawImage(texture.image, 0, 0);
|
|
const width = texture.image.width;
|
|
const height = texture.image.height;
|
|
const cols = Math.round(Math.sqrt(totalFrames2 * (width / height)));
|
|
const rows = Math.round(totalFrames2 / cols);
|
|
const frameWidth = width / cols;
|
|
const frameHeight = height / rows;
|
|
const emptyFrames = [];
|
|
for (let row = 0; row < rows; row++) {
|
|
for (let col3 = 0; col3 < cols; col3++) {
|
|
const frameIndex = row * cols + col3;
|
|
if (frameIndex >= totalFrames2) {
|
|
emptyFrames.push({
|
|
row,
|
|
col: col3
|
|
});
|
|
continue;
|
|
}
|
|
const frameData = ctx.getImageData(col3 * frameWidth, row * frameHeight, frameWidth, frameHeight).data;
|
|
const isEmpty = checkIfFrameIsEmpty(frameData);
|
|
if (isEmpty) {
|
|
emptyFrames.push({
|
|
row,
|
|
col: col3
|
|
});
|
|
}
|
|
}
|
|
}
|
|
return {
|
|
rows,
|
|
columns: cols,
|
|
frameWidth,
|
|
frameHeight,
|
|
emptyFrames
|
|
};
|
|
} else {
|
|
return {
|
|
rows: 0,
|
|
columns: 0,
|
|
frameWidth: 0,
|
|
frameHeight: 0,
|
|
emptyFrames: []
|
|
};
|
|
}
|
|
}, [canvasRenderingContext2DSettings]);
|
|
const calculateScaleRatio = React63.useCallback((frames) => {
|
|
const processFrameArray = (frameArray) => {
|
|
let largestFrame = null;
|
|
for (const frame of frameArray) {
|
|
const {
|
|
w,
|
|
h
|
|
} = frame.frame;
|
|
const area = w * h;
|
|
if (!largestFrame || area > largestFrame.area) {
|
|
largestFrame = {
|
|
w,
|
|
h,
|
|
area
|
|
};
|
|
}
|
|
}
|
|
const frameArr = frameArray.map((frame) => {
|
|
const {
|
|
w,
|
|
h
|
|
} = frame.frame;
|
|
const area = w * h;
|
|
const scaleRatio = largestFrame ? area === largestFrame.area ? 1 : Math.sqrt(area / largestFrame.area) : 1;
|
|
return {
|
|
...frame,
|
|
scaleRatio
|
|
};
|
|
});
|
|
return frameArr;
|
|
};
|
|
if (Array.isArray(frames)) {
|
|
return processFrameArray(frames);
|
|
} else {
|
|
const result = {};
|
|
for (const key in frames) {
|
|
result[key] = processFrameArray(frames[key]);
|
|
}
|
|
return result;
|
|
}
|
|
}, []);
|
|
const parseFrames = React63.useCallback(() => {
|
|
const sprites = {};
|
|
const data = spriteDataRef.current;
|
|
const delimiters = animationFramesRef.current;
|
|
if (data) {
|
|
if (delimiters && Array.isArray(data["frames"])) {
|
|
for (let i3 = 0; i3 < delimiters.length; i3++) {
|
|
sprites[delimiters[i3]] = [];
|
|
for (const value of data["frames"]) {
|
|
const frameData = value["frame"];
|
|
const sourceWidth = value["sourceSize"]["w"];
|
|
const sourceHeight = value["sourceSize"]["h"];
|
|
if (typeof value["filename"] === "string" && value["filename"].toLowerCase().indexOf(delimiters[i3].toLowerCase()) !== -1) {
|
|
sprites[delimiters[i3]].push({
|
|
...value,
|
|
frame: frameData,
|
|
sourceSize: {
|
|
w: sourceWidth,
|
|
h: sourceHeight
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
for (const frame in sprites) {
|
|
const scaleRatioData = calculateScaleRatio(sprites[frame]);
|
|
if (Array.isArray(scaleRatioData)) {
|
|
sprites[frame] = scaleRatioData;
|
|
}
|
|
}
|
|
return sprites;
|
|
} else if (delimiters && typeof data["frames"] === "object") {
|
|
for (let i3 = 0; i3 < delimiters.length; i3++) {
|
|
sprites[delimiters[i3]] = [];
|
|
for (const innerKey in data["frames"]) {
|
|
const value = data["frames"][innerKey];
|
|
const frameData = value["frame"];
|
|
const sourceWidth = value["sourceSize"]["w"];
|
|
const sourceHeight = value["sourceSize"]["h"];
|
|
if (typeof innerKey === "string" && innerKey.toLowerCase().indexOf(delimiters[i3].toLowerCase()) !== -1) {
|
|
sprites[delimiters[i3]].push({
|
|
...value,
|
|
frame: frameData,
|
|
sourceSize: {
|
|
w: sourceWidth,
|
|
h: sourceHeight
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
for (const frame in sprites) {
|
|
const scaleRatioData = calculateScaleRatio(sprites[frame]);
|
|
if (Array.isArray(scaleRatioData)) {
|
|
sprites[frame] = scaleRatioData;
|
|
}
|
|
}
|
|
return sprites;
|
|
} else {
|
|
let spritesArr = [];
|
|
if (data != null && data.frames) {
|
|
if (Array.isArray(data.frames)) {
|
|
spritesArr = data.frames.map((frame) => ({
|
|
...frame,
|
|
x: frame.frame.x,
|
|
y: frame.frame.y,
|
|
w: frame.frame.w,
|
|
h: frame.frame.h
|
|
}));
|
|
} else {
|
|
spritesArr = Object.values(data.frames).flat().map((frame) => ({
|
|
...frame,
|
|
x: frame.frame.x,
|
|
y: frame.frame.y,
|
|
w: frame.frame.w,
|
|
h: frame.frame.h
|
|
}));
|
|
}
|
|
}
|
|
return calculateScaleRatio(spritesArr);
|
|
}
|
|
}
|
|
return [];
|
|
}, [calculateScaleRatio, spriteDataRef]);
|
|
const parseSpriteData = React63.useCallback((json2, _spriteTexture) => {
|
|
let aspect = new Vector3(1, 1, 1);
|
|
if (json2 === null) {
|
|
if (_spriteTexture && numberOfFrames) {
|
|
const width = _spriteTexture.image.width;
|
|
const height = _spriteTexture.image.height;
|
|
totalFrames.current = numberOfFrames;
|
|
const {
|
|
rows,
|
|
columns,
|
|
frameWidth,
|
|
frameHeight,
|
|
emptyFrames
|
|
} = getRowsAndColumns(_spriteTexture, numberOfFrames);
|
|
const nonJsonFrames = {
|
|
frames: [],
|
|
meta: {
|
|
version: "1.0",
|
|
size: {
|
|
w: width,
|
|
h: height
|
|
},
|
|
rows,
|
|
columns,
|
|
frameWidth,
|
|
frameHeight,
|
|
scale: "1"
|
|
}
|
|
};
|
|
for (let row = 0; row < rows; row++) {
|
|
for (let col3 = 0; col3 < columns; col3++) {
|
|
const isExcluded = (emptyFrames !== null && emptyFrames !== void 0 ? emptyFrames : []).some((coord) => coord.row === row && coord.col === col3);
|
|
if (isExcluded) {
|
|
continue;
|
|
}
|
|
if (Array.isArray(nonJsonFrames.frames)) {
|
|
nonJsonFrames.frames.push({
|
|
frame: {
|
|
x: col3 * frameWidth,
|
|
y: row * frameHeight,
|
|
w: frameWidth,
|
|
h: frameHeight
|
|
},
|
|
scaleRatio: 1,
|
|
rotated: false,
|
|
trimmed: false,
|
|
spriteSourceSize: {
|
|
x: 0,
|
|
y: 0,
|
|
w: frameWidth,
|
|
h: frameHeight
|
|
},
|
|
sourceSize: {
|
|
w: frameWidth,
|
|
h: frameHeight
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
aspect = calculateAspectRatio(frameWidth, frameHeight, aspectFactor);
|
|
spriteDataRef.current = nonJsonFrames;
|
|
}
|
|
if (spriteDataRef.current && spriteDataRef.current.frames) {
|
|
spriteDataRef.current.frames = calculateScaleRatio(spriteDataRef.current.frames);
|
|
}
|
|
} else if (_spriteTexture) {
|
|
spriteDataRef.current = json2;
|
|
spriteDataRef.current.frames = parseFrames();
|
|
totalFrames.current = Array.isArray(json2.frames) ? json2.frames.length : Object.keys(json2.frames).length;
|
|
const {
|
|
w,
|
|
h
|
|
} = getFirstFrame(json2.frames).sourceSize;
|
|
aspect = calculateAspectRatio(w, h, aspectFactor);
|
|
}
|
|
setSpriteData(spriteDataRef.current);
|
|
if ("encoding" in _spriteTexture) {
|
|
_spriteTexture.encoding = 3001;
|
|
} else if ("colorSpace" in _spriteTexture) {
|
|
_spriteTexture.colorSpace = SRGBColorSpace;
|
|
}
|
|
setSpriteTexture(_spriteTexture);
|
|
setSpriteObj({
|
|
spriteTexture: _spriteTexture,
|
|
spriteData: spriteDataRef.current,
|
|
aspect
|
|
});
|
|
}, [getRowsAndColumns, numberOfFrames, parseFrames, calculateAspectRatio, calculateScaleRatio]);
|
|
const loadJsonAndTextureAndExecuteCallback = React63.useCallback((jsonUrl, textureUrl, callback) => {
|
|
const jsonPromise = fetch(jsonUrl).then((response) => response.json());
|
|
const texturePromise = new Promise((resolve) => {
|
|
textureLoader.load(textureUrl, resolve);
|
|
});
|
|
Promise.all([jsonPromise, texturePromise]).then((response) => {
|
|
callback(response[0], response[1]);
|
|
});
|
|
}, [textureLoader]);
|
|
const loadStandaloneSprite = React63.useCallback((textureUrl) => {
|
|
if (!textureUrl && !inputRef.current) {
|
|
throw new Error("Either textureUrl or input must be provided");
|
|
}
|
|
const validUrl = textureUrl !== null && textureUrl !== void 0 ? textureUrl : inputRef.current;
|
|
if (!validUrl) {
|
|
throw new Error("A valid texture URL must be provided");
|
|
}
|
|
textureLoader.load(validUrl, (texture) => parseSpriteData(null, texture));
|
|
}, [textureLoader, parseSpriteData]);
|
|
const loadJsonAndTexture = React63.useCallback((textureUrl, jsonUrl) => {
|
|
if (jsonUrl && textureUrl) {
|
|
loadJsonAndTextureAndExecuteCallback(jsonUrl, textureUrl, parseSpriteData);
|
|
} else {
|
|
loadStandaloneSprite(textureUrl);
|
|
}
|
|
}, [loadJsonAndTextureAndExecuteCallback, loadStandaloneSprite, parseSpriteData]);
|
|
React63.useLayoutEffect(() => {
|
|
if (jsonRef.current && inputRef.current) {
|
|
loadJsonAndTextureAndExecuteCallback(jsonRef.current, inputRef.current, parseSpriteData);
|
|
} else if (inputRef.current) {
|
|
loadStandaloneSprite();
|
|
}
|
|
const _inputRef = inputRef.current;
|
|
return () => {
|
|
if (_inputRef) {
|
|
useLoader.clear(TextureLoader, _inputRef);
|
|
}
|
|
};
|
|
}, [loadJsonAndTextureAndExecuteCallback, loadStandaloneSprite, parseSpriteData]);
|
|
React63.useLayoutEffect(() => {
|
|
onLoad == null || onLoad(spriteTexture, spriteData !== null && spriteData !== void 0 ? spriteData : null);
|
|
}, [spriteTexture, spriteData, onLoad]);
|
|
return {
|
|
spriteObj,
|
|
loadJsonAndTexture
|
|
};
|
|
}
|
|
useSpriteLoader.preload = (url) => useLoader.preload(TextureLoader, url);
|
|
useSpriteLoader.clear = (input) => useLoader.clear(TextureLoader, input);
|
|
|
|
// node_modules/@react-three/drei/core/Helper.js
|
|
var React64 = __toESM(require_react());
|
|
function useHelper(object3D, helperConstructor, ...args) {
|
|
const helper = React64.useRef(null);
|
|
const scene = useThree((state) => state.scene);
|
|
React64.useLayoutEffect(() => {
|
|
let currentHelper = void 0;
|
|
if (object3D && object3D != null && object3D.current && helperConstructor) {
|
|
helper.current = currentHelper = new helperConstructor(object3D.current, ...args);
|
|
}
|
|
if (currentHelper) {
|
|
currentHelper.traverse((child) => child.raycast = () => null);
|
|
scene.add(currentHelper);
|
|
return () => {
|
|
helper.current = void 0;
|
|
scene.remove(currentHelper);
|
|
currentHelper.dispose == null || currentHelper.dispose();
|
|
};
|
|
}
|
|
}, [scene, helperConstructor, object3D, ...args]);
|
|
useFrame(() => {
|
|
var _helper$current;
|
|
return void ((_helper$current = helper.current) == null || _helper$current.update == null ? void 0 : _helper$current.update());
|
|
});
|
|
return helper;
|
|
}
|
|
var Helper = ({
|
|
type: helperConstructor,
|
|
args = []
|
|
}) => {
|
|
const thisRef = React64.useRef(null);
|
|
const parentRef = React64.useRef(null);
|
|
React64.useLayoutEffect(() => {
|
|
parentRef.current = thisRef.current.parent;
|
|
});
|
|
useHelper(parentRef, helperConstructor, ...args);
|
|
return React64.createElement("object3D", {
|
|
ref: thisRef
|
|
});
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/Stats.js
|
|
var React66 = __toESM(require_react());
|
|
var import_stats = __toESM(require_stats_min());
|
|
|
|
// node_modules/@react-three/drei/helpers/useEffectfulState.js
|
|
var React65 = __toESM(require_react());
|
|
function call2(ref, value) {
|
|
if (typeof ref === "function") ref(value);
|
|
else if (ref != null) ref.current = value;
|
|
}
|
|
function useEffectfulState(fn, deps = [], cb) {
|
|
const [state, set] = React65.useState();
|
|
React65.useLayoutEffect(() => {
|
|
const value = fn();
|
|
set(value);
|
|
call2(cb, value);
|
|
return () => call2(cb, null);
|
|
}, deps);
|
|
return state;
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/Stats.js
|
|
function Stats({
|
|
showPanel = 0,
|
|
className,
|
|
parent
|
|
}) {
|
|
const stats = useEffectfulState(() => new import_stats.default(), []);
|
|
React66.useEffect(() => {
|
|
if (stats) {
|
|
const node = parent && parent.current || document.body;
|
|
stats.showPanel(showPanel);
|
|
node == null || node.appendChild(stats.dom);
|
|
const classNames = (className !== null && className !== void 0 ? className : "").split(" ").filter((cls) => cls);
|
|
if (classNames.length) stats.dom.classList.add(...classNames);
|
|
const begin = addEffect(() => stats.begin());
|
|
const end = addAfterEffect(() => stats.end());
|
|
return () => {
|
|
if (classNames.length) stats.dom.classList.remove(...classNames);
|
|
node == null || node.removeChild(stats.dom);
|
|
begin();
|
|
end();
|
|
};
|
|
}
|
|
}, [parent, stats, className, showPanel]);
|
|
return null;
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/StatsGl.js
|
|
var React67 = __toESM(require_react());
|
|
|
|
// node_modules/stats-gl/dist/panel.js
|
|
var Panel = class {
|
|
constructor(name, fg, bg) {
|
|
this.name = name;
|
|
this.fg = fg;
|
|
this.bg = bg;
|
|
this.gradient = null;
|
|
this.PR = Math.round(window.devicePixelRatio || 1);
|
|
this.WIDTH = 90 * this.PR;
|
|
this.HEIGHT = 48 * this.PR;
|
|
this.TEXT_X = 3 * this.PR;
|
|
this.TEXT_Y = 2 * this.PR;
|
|
this.GRAPH_X = 3 * this.PR;
|
|
this.GRAPH_Y = 15 * this.PR;
|
|
this.GRAPH_WIDTH = 84 * this.PR;
|
|
this.GRAPH_HEIGHT = 30 * this.PR;
|
|
this.canvas = document.createElement("canvas");
|
|
this.canvas.width = this.WIDTH;
|
|
this.canvas.height = this.HEIGHT;
|
|
this.canvas.style.width = "90px";
|
|
this.canvas.style.height = "48px";
|
|
this.canvas.style.position = "absolute";
|
|
this.canvas.style.cssText = "width:90px;height:48px";
|
|
this.context = this.canvas.getContext("2d");
|
|
this.initializeCanvas();
|
|
}
|
|
createGradient() {
|
|
if (!this.context)
|
|
throw new Error("No context");
|
|
const gradient = this.context.createLinearGradient(
|
|
0,
|
|
this.GRAPH_Y,
|
|
0,
|
|
this.GRAPH_Y + this.GRAPH_HEIGHT
|
|
);
|
|
let startColor;
|
|
const endColor = this.fg;
|
|
switch (this.fg.toLowerCase()) {
|
|
case "#0ff":
|
|
startColor = "#006666";
|
|
break;
|
|
case "#0f0":
|
|
startColor = "#006600";
|
|
break;
|
|
case "#ff0":
|
|
startColor = "#666600";
|
|
break;
|
|
case "#e1e1e1":
|
|
startColor = "#666666";
|
|
break;
|
|
default:
|
|
startColor = this.bg;
|
|
break;
|
|
}
|
|
gradient.addColorStop(0, startColor);
|
|
gradient.addColorStop(1, endColor);
|
|
return gradient;
|
|
}
|
|
initializeCanvas() {
|
|
if (!this.context)
|
|
return;
|
|
this.context.font = "bold " + 9 * this.PR + "px Helvetica,Arial,sans-serif";
|
|
this.context.textBaseline = "top";
|
|
this.gradient = this.createGradient();
|
|
this.context.fillStyle = this.bg;
|
|
this.context.fillRect(0, 0, this.WIDTH, this.HEIGHT);
|
|
this.context.fillStyle = this.fg;
|
|
this.context.fillText(this.name, this.TEXT_X, this.TEXT_Y);
|
|
this.context.fillStyle = this.fg;
|
|
this.context.fillRect(this.GRAPH_X, this.GRAPH_Y, this.GRAPH_WIDTH, this.GRAPH_HEIGHT);
|
|
this.context.fillStyle = this.bg;
|
|
this.context.globalAlpha = 0.9;
|
|
this.context.fillRect(this.GRAPH_X, this.GRAPH_Y, this.GRAPH_WIDTH, this.GRAPH_HEIGHT);
|
|
}
|
|
update(value, valueGraph, maxValue, maxGraph, decimals = 0) {
|
|
if (!this.context || !this.gradient)
|
|
return;
|
|
const min = Math.min(Infinity, value);
|
|
const max = Math.max(maxValue, value);
|
|
maxGraph = Math.max(maxGraph, valueGraph);
|
|
this.context.globalAlpha = 1;
|
|
this.context.fillStyle = this.bg;
|
|
this.context.fillRect(0, 0, this.WIDTH, this.GRAPH_Y);
|
|
this.context.fillStyle = this.fg;
|
|
this.context.fillText(
|
|
`${value.toFixed(decimals)} ${this.name} (${min.toFixed(decimals)}-${parseFloat(
|
|
max.toFixed(decimals)
|
|
)})`,
|
|
this.TEXT_X,
|
|
this.TEXT_Y
|
|
);
|
|
this.context.drawImage(
|
|
this.canvas,
|
|
this.GRAPH_X + this.PR,
|
|
this.GRAPH_Y,
|
|
this.GRAPH_WIDTH - this.PR,
|
|
this.GRAPH_HEIGHT,
|
|
this.GRAPH_X,
|
|
this.GRAPH_Y,
|
|
this.GRAPH_WIDTH - this.PR,
|
|
this.GRAPH_HEIGHT
|
|
);
|
|
const columnHeight = this.GRAPH_HEIGHT - (1 - valueGraph / maxGraph) * this.GRAPH_HEIGHT;
|
|
if (columnHeight > 0) {
|
|
this.context.globalAlpha = 1;
|
|
this.context.fillStyle = this.gradient;
|
|
this.context.fillRect(
|
|
this.GRAPH_X + this.GRAPH_WIDTH - this.PR,
|
|
this.GRAPH_Y + this.GRAPH_HEIGHT - columnHeight,
|
|
this.PR,
|
|
columnHeight
|
|
);
|
|
}
|
|
}
|
|
};
|
|
|
|
// node_modules/stats-gl/dist/main.js
|
|
var _Stats = class _Stats2 {
|
|
constructor({
|
|
trackGPU = false,
|
|
logsPerSecond = 30,
|
|
samplesLog = 60,
|
|
samplesGraph = 10,
|
|
precision = 2,
|
|
minimal = false,
|
|
horizontal = true,
|
|
mode = 0
|
|
} = {}) {
|
|
this.gl = null;
|
|
this.ext = null;
|
|
this.activeQuery = null;
|
|
this.gpuQueries = [];
|
|
this.threeRendererPatched = false;
|
|
this.frames = 0;
|
|
this.renderCount = 0;
|
|
this.isRunningCPUProfiling = false;
|
|
this.totalCpuDuration = 0;
|
|
this.totalGpuDuration = 0;
|
|
this.totalGpuDurationCompute = 0;
|
|
this.totalFps = 0;
|
|
this.gpuPanel = null;
|
|
this.gpuPanelCompute = null;
|
|
this.averageFps = { logs: [], graph: [] };
|
|
this.averageCpu = { logs: [], graph: [] };
|
|
this.averageGpu = { logs: [], graph: [] };
|
|
this.averageGpuCompute = { logs: [], graph: [] };
|
|
this.handleClick = (event) => {
|
|
event.preventDefault();
|
|
this.showPanel(++this.mode % this.dom.children.length);
|
|
};
|
|
this.handleResize = () => {
|
|
this.resizePanel(this.fpsPanel, 0);
|
|
this.resizePanel(this.msPanel, 1);
|
|
if (this.gpuPanel)
|
|
this.resizePanel(this.gpuPanel, 2);
|
|
if (this.gpuPanelCompute)
|
|
this.resizePanel(this.gpuPanelCompute, 3);
|
|
};
|
|
this.mode = mode;
|
|
this.horizontal = horizontal;
|
|
this.minimal = minimal;
|
|
this.trackGPU = trackGPU;
|
|
this.samplesLog = samplesLog;
|
|
this.samplesGraph = samplesGraph;
|
|
this.precision = precision;
|
|
this.logsPerSecond = logsPerSecond;
|
|
this.dom = document.createElement("div");
|
|
this.initializeDOM();
|
|
this.beginTime = performance.now();
|
|
this.prevTime = this.beginTime;
|
|
this.prevCpuTime = this.beginTime;
|
|
this.fpsPanel = this.addPanel(new _Stats2.Panel("FPS", "#0ff", "#002"), 0);
|
|
this.msPanel = this.addPanel(new _Stats2.Panel("CPU", "#0f0", "#020"), 1);
|
|
this.setupEventListeners();
|
|
}
|
|
initializeDOM() {
|
|
this.dom.style.cssText = `
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
opacity: 0.9;
|
|
z-index: 10000;
|
|
${this.minimal ? "cursor: pointer;" : ""}
|
|
`;
|
|
}
|
|
setupEventListeners() {
|
|
if (this.minimal) {
|
|
this.dom.addEventListener("click", this.handleClick);
|
|
this.showPanel(this.mode);
|
|
} else {
|
|
window.addEventListener("resize", this.handleResize);
|
|
}
|
|
}
|
|
async init(canvasOrGL) {
|
|
if (!canvasOrGL) {
|
|
console.error('Stats: The "canvas" parameter is undefined.');
|
|
return;
|
|
}
|
|
if (this.handleThreeRenderer(canvasOrGL))
|
|
return;
|
|
if (await this.handleWebGPURenderer(canvasOrGL))
|
|
return;
|
|
if (!this.initializeWebGL(canvasOrGL))
|
|
return;
|
|
}
|
|
handleThreeRenderer(renderer) {
|
|
if (renderer.isWebGLRenderer && !this.threeRendererPatched) {
|
|
this.patchThreeRenderer(renderer);
|
|
this.gl = renderer.getContext();
|
|
if (this.trackGPU) {
|
|
this.initializeGPUTracking();
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
async handleWebGPURenderer(renderer) {
|
|
if (renderer.isWebGPURenderer) {
|
|
if (this.trackGPU) {
|
|
renderer.backend.trackTimestamp = true;
|
|
if (await renderer.hasFeatureAsync("timestamp-query")) {
|
|
this.initializeWebGPUPanels();
|
|
}
|
|
}
|
|
this.info = renderer.info;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
initializeWebGPUPanels() {
|
|
this.gpuPanel = this.addPanel(new _Stats2.Panel("GPU", "#ff0", "#220"), 2);
|
|
this.gpuPanelCompute = this.addPanel(
|
|
new _Stats2.Panel("CPT", "#e1e1e1", "#212121"),
|
|
3
|
|
);
|
|
}
|
|
initializeWebGL(canvasOrGL) {
|
|
if (canvasOrGL instanceof WebGL2RenderingContext) {
|
|
this.gl = canvasOrGL;
|
|
} else if (canvasOrGL instanceof HTMLCanvasElement || canvasOrGL instanceof OffscreenCanvas) {
|
|
this.gl = canvasOrGL.getContext("webgl2");
|
|
if (!this.gl) {
|
|
console.error("Stats: Unable to obtain WebGL2 context.");
|
|
return false;
|
|
}
|
|
} else {
|
|
console.error(
|
|
"Stats: Invalid input type. Expected WebGL2RenderingContext, HTMLCanvasElement, or OffscreenCanvas."
|
|
);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
initializeGPUTracking() {
|
|
if (this.gl) {
|
|
this.ext = this.gl.getExtension("EXT_disjoint_timer_query_webgl2");
|
|
if (this.ext) {
|
|
this.gpuPanel = this.addPanel(new _Stats2.Panel("GPU", "#ff0", "#220"), 2);
|
|
}
|
|
}
|
|
}
|
|
begin() {
|
|
if (!this.isRunningCPUProfiling) {
|
|
this.beginProfiling("cpu-started");
|
|
}
|
|
if (!this.gl || !this.ext)
|
|
return;
|
|
if (this.activeQuery) {
|
|
this.gl.endQuery(this.ext.TIME_ELAPSED_EXT);
|
|
}
|
|
this.activeQuery = this.gl.createQuery();
|
|
if (this.activeQuery) {
|
|
this.gl.beginQuery(this.ext.TIME_ELAPSED_EXT, this.activeQuery);
|
|
}
|
|
}
|
|
end() {
|
|
this.renderCount++;
|
|
if (this.gl && this.ext && this.activeQuery) {
|
|
this.gl.endQuery(this.ext.TIME_ELAPSED_EXT);
|
|
this.gpuQueries.push({ query: this.activeQuery });
|
|
this.activeQuery = null;
|
|
}
|
|
}
|
|
update() {
|
|
if (!this.info) {
|
|
this.processGpuQueries();
|
|
} else {
|
|
this.processWebGPUTimestamps();
|
|
}
|
|
this.endProfiling("cpu-started", "cpu-finished", "cpu-duration");
|
|
this.updateAverages();
|
|
this.resetCounters();
|
|
}
|
|
processWebGPUTimestamps() {
|
|
this.totalGpuDuration = this.info.render.timestamp;
|
|
this.totalGpuDurationCompute = this.info.compute.timestamp;
|
|
this.addToAverage(this.totalGpuDurationCompute, this.averageGpuCompute);
|
|
}
|
|
updateAverages() {
|
|
this.addToAverage(this.totalCpuDuration, this.averageCpu);
|
|
this.addToAverage(this.totalGpuDuration, this.averageGpu);
|
|
}
|
|
resetCounters() {
|
|
this.renderCount = 0;
|
|
if (this.totalCpuDuration === 0) {
|
|
this.beginProfiling("cpu-started");
|
|
}
|
|
this.totalCpuDuration = 0;
|
|
this.totalFps = 0;
|
|
this.beginTime = this.endInternal();
|
|
}
|
|
resizePanel(panel, offset) {
|
|
panel.canvas.style.position = "absolute";
|
|
if (this.minimal) {
|
|
panel.canvas.style.display = "none";
|
|
} else {
|
|
panel.canvas.style.display = "block";
|
|
if (this.horizontal) {
|
|
panel.canvas.style.top = "0px";
|
|
panel.canvas.style.left = offset * panel.WIDTH / panel.PR + "px";
|
|
} else {
|
|
panel.canvas.style.left = "0px";
|
|
panel.canvas.style.top = offset * panel.HEIGHT / panel.PR + "px";
|
|
}
|
|
}
|
|
}
|
|
addPanel(panel, offset) {
|
|
if (panel.canvas) {
|
|
this.dom.appendChild(panel.canvas);
|
|
this.resizePanel(panel, offset);
|
|
}
|
|
return panel;
|
|
}
|
|
showPanel(id) {
|
|
for (let i3 = 0; i3 < this.dom.children.length; i3++) {
|
|
const child = this.dom.children[i3];
|
|
child.style.display = i3 === id ? "block" : "none";
|
|
}
|
|
this.mode = id;
|
|
}
|
|
processGpuQueries() {
|
|
if (!this.gl || !this.ext)
|
|
return;
|
|
this.totalGpuDuration = 0;
|
|
this.gpuQueries.forEach((queryInfo, index2) => {
|
|
if (this.gl) {
|
|
const available = this.gl.getQueryParameter(queryInfo.query, this.gl.QUERY_RESULT_AVAILABLE);
|
|
const disjoint = this.gl.getParameter(this.ext.GPU_DISJOINT_EXT);
|
|
if (available && !disjoint) {
|
|
const elapsed = this.gl.getQueryParameter(queryInfo.query, this.gl.QUERY_RESULT);
|
|
const duration = elapsed * 1e-6;
|
|
this.totalGpuDuration += duration;
|
|
this.gl.deleteQuery(queryInfo.query);
|
|
this.gpuQueries.splice(index2, 1);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
endInternal() {
|
|
this.frames++;
|
|
const time = (performance || Date).now();
|
|
const elapsed = time - this.prevTime;
|
|
if (time >= this.prevCpuTime + 1e3 / this.logsPerSecond) {
|
|
const fps = Math.round(this.frames * 1e3 / elapsed);
|
|
this.addToAverage(fps, this.averageFps);
|
|
this.updatePanel(this.fpsPanel, this.averageFps, 0);
|
|
this.updatePanel(this.msPanel, this.averageCpu, this.precision);
|
|
this.updatePanel(this.gpuPanel, this.averageGpu, this.precision);
|
|
if (this.gpuPanelCompute) {
|
|
this.updatePanel(this.gpuPanelCompute, this.averageGpuCompute);
|
|
}
|
|
this.frames = 0;
|
|
this.prevCpuTime = time;
|
|
this.prevTime = time;
|
|
}
|
|
return time;
|
|
}
|
|
addToAverage(value, averageArray) {
|
|
averageArray.logs.push(value);
|
|
if (averageArray.logs.length > this.samplesLog) {
|
|
averageArray.logs.shift();
|
|
}
|
|
averageArray.graph.push(value);
|
|
if (averageArray.graph.length > this.samplesGraph) {
|
|
averageArray.graph.shift();
|
|
}
|
|
}
|
|
beginProfiling(marker) {
|
|
if (window.performance) {
|
|
window.performance.mark(marker);
|
|
this.isRunningCPUProfiling = true;
|
|
}
|
|
}
|
|
endProfiling(startMarker, endMarker, measureName) {
|
|
if (window.performance && endMarker && this.isRunningCPUProfiling) {
|
|
window.performance.mark(endMarker);
|
|
const cpuMeasure = performance.measure(measureName, startMarker, endMarker);
|
|
this.totalCpuDuration += cpuMeasure.duration;
|
|
this.isRunningCPUProfiling = false;
|
|
}
|
|
}
|
|
updatePanel(panel, averageArray, precision = 2) {
|
|
if (averageArray.logs.length > 0) {
|
|
let sumLog = 0;
|
|
let max = 0.01;
|
|
for (let i3 = 0; i3 < averageArray.logs.length; i3++) {
|
|
sumLog += averageArray.logs[i3];
|
|
if (averageArray.logs[i3] > max) {
|
|
max = averageArray.logs[i3];
|
|
}
|
|
}
|
|
let sumGraph = 0;
|
|
let maxGraph = 0.01;
|
|
for (let i3 = 0; i3 < averageArray.graph.length; i3++) {
|
|
sumGraph += averageArray.graph[i3];
|
|
if (averageArray.graph[i3] > maxGraph) {
|
|
maxGraph = averageArray.graph[i3];
|
|
}
|
|
}
|
|
if (panel) {
|
|
panel.update(sumLog / Math.min(averageArray.logs.length, this.samplesLog), sumGraph / Math.min(averageArray.graph.length, this.samplesGraph), max, maxGraph, precision);
|
|
}
|
|
}
|
|
}
|
|
get domElement() {
|
|
return this.dom;
|
|
}
|
|
patchThreeRenderer(renderer) {
|
|
const originalRenderMethod = renderer.render;
|
|
const statsInstance = this;
|
|
renderer.render = function(scene, camera) {
|
|
statsInstance.begin();
|
|
originalRenderMethod.call(this, scene, camera);
|
|
statsInstance.end();
|
|
};
|
|
this.threeRendererPatched = true;
|
|
}
|
|
};
|
|
_Stats.Panel = Panel;
|
|
var Stats2 = _Stats;
|
|
|
|
// node_modules/@react-three/drei/core/StatsGl.js
|
|
var StatsGl = React67.forwardRef(function StatsGl2({
|
|
className,
|
|
parent,
|
|
id,
|
|
clearStatsGlStyle,
|
|
...props
|
|
}, fref) {
|
|
const gl = useThree((state) => state.gl);
|
|
const stats = React67.useMemo(() => {
|
|
const stats2 = new Stats2({
|
|
...props
|
|
});
|
|
stats2.init(gl);
|
|
return stats2;
|
|
}, [gl]);
|
|
React67.useImperativeHandle(fref, () => stats.domElement, [stats]);
|
|
React67.useEffect(() => {
|
|
if (stats) {
|
|
const node = parent && parent.current || document.body;
|
|
node == null || node.appendChild(stats.domElement);
|
|
stats.domElement.querySelectorAll("canvas").forEach((canvas) => {
|
|
canvas.style.removeProperty("position");
|
|
});
|
|
if (id) stats.domElement.id = id;
|
|
if (clearStatsGlStyle) stats.domElement.removeAttribute("style");
|
|
stats.domElement.removeAttribute("style");
|
|
const classNames = (className !== null && className !== void 0 ? className : "").split(" ").filter((cls) => cls);
|
|
if (classNames.length) stats.domElement.classList.add(...classNames);
|
|
const end = addAfterEffect(() => stats.update());
|
|
return () => {
|
|
if (classNames.length) stats.domElement.classList.remove(...classNames);
|
|
node == null || node.removeChild(stats.domElement);
|
|
end();
|
|
};
|
|
}
|
|
}, [parent, stats, className, id, clearStatsGlStyle]);
|
|
return null;
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/useDepthBuffer.js
|
|
var React68 = __toESM(require_react());
|
|
function useDepthBuffer({
|
|
size = 256,
|
|
frames = Infinity
|
|
} = {}) {
|
|
const dpr = useThree((state) => state.viewport.dpr);
|
|
const {
|
|
width,
|
|
height
|
|
} = useThree((state) => state.size);
|
|
const w = size || width * dpr;
|
|
const h = size || height * dpr;
|
|
const depthConfig = React68.useMemo(() => {
|
|
const depthTexture = new DepthTexture(w, h);
|
|
depthTexture.format = DepthFormat;
|
|
depthTexture.type = UnsignedShortType;
|
|
return {
|
|
depthTexture
|
|
};
|
|
}, [w, h]);
|
|
let count = 0;
|
|
const depthFBO = useFBO(w, h, depthConfig);
|
|
useFrame((state) => {
|
|
if (frames === Infinity || count < frames) {
|
|
state.gl.setRenderTarget(depthFBO);
|
|
state.gl.render(state.scene, state.camera);
|
|
state.gl.setRenderTarget(null);
|
|
count++;
|
|
}
|
|
});
|
|
return depthFBO.depthTexture;
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/useAspect.js
|
|
function useAspect(width, height, factor = 1) {
|
|
const v5 = useThree((state) => state.viewport);
|
|
const adaptedHeight = height * (v5.aspect > width / height ? v5.width / width : v5.height / height);
|
|
const adaptedWidth = width * (v5.aspect > width / height ? v5.width / width : v5.height / height);
|
|
return [adaptedWidth * factor, adaptedHeight * factor, 1];
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/useCamera.js
|
|
var React69 = __toESM(require_react());
|
|
function useCamera(camera, props) {
|
|
const pointer = useThree((state) => state.pointer);
|
|
const [raycast2] = React69.useState(() => {
|
|
const raycaster = new Raycaster();
|
|
if (props) applyProps(raycaster, props);
|
|
return function(_, intersects) {
|
|
raycaster.setFromCamera(pointer, camera instanceof Camera ? camera : camera.current);
|
|
const rc = this.constructor.prototype.raycast.bind(this);
|
|
if (rc) rc(raycaster, intersects);
|
|
};
|
|
});
|
|
return raycast2;
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/DetectGPU.js
|
|
var React70 = __toESM(require_react());
|
|
|
|
// node_modules/detect-gpu/dist/detect-gpu.esm.js
|
|
function e(e2, t2, r2, n2) {
|
|
return new (r2 || (r2 = Promise))((function(o2, a5) {
|
|
function i3(e3) {
|
|
try {
|
|
d2(n2.next(e3));
|
|
} catch (e4) {
|
|
a5(e4);
|
|
}
|
|
}
|
|
function c2(e3) {
|
|
try {
|
|
d2(n2.throw(e3));
|
|
} catch (e4) {
|
|
a5(e4);
|
|
}
|
|
}
|
|
function d2(e3) {
|
|
var t3;
|
|
e3.done ? o2(e3.value) : (t3 = e3.value, t3 instanceof r2 ? t3 : new r2((function(e4) {
|
|
e4(t3);
|
|
}))).then(i3, c2);
|
|
}
|
|
d2((n2 = n2.apply(e2, t2 || [])).next());
|
|
}));
|
|
}
|
|
var t = ["geforce 320m", "geforce 8600", "geforce 8600m gt", "geforce 8800 gs", "geforce 8800 gt", "geforce 9400", "geforce 9400m g", "geforce 9400m", "geforce 9600m gt", "geforce 9600m", "geforce fx go5200", "geforce gt 120", "geforce gt 130", "geforce gt 330m", "geforce gtx 285", "google swiftshader", "intel g41", "intel g45", "intel gma 4500mhd", "intel gma x3100", "intel hd 3000", "intel q45", "legacy", "mali-2", "mali-3", "mali-4", "quadro fx 1500", "quadro fx 4", "quadro fx 5", "radeon hd 2400", "radeon hd 2600", "radeon hd 4670", "radeon hd 4850", "radeon hd 4870", "radeon hd 5670", "radeon hd 5750", "radeon hd 6290", "radeon hd 6300", "radeon hd 6310", "radeon hd 6320", "radeon hd 6490m", "radeon hd 6630m", "radeon hd 6750m", "radeon hd 6770m", "radeon hd 6970m", "sgx 543", "sgx543"];
|
|
function r(e2) {
|
|
return e2 = e2.toLowerCase().replace(/.*angle ?\((.+)\)(?: on vulkan [0-9.]+)?$/i, "$1").replace(/\s(\d{1,2}gb|direct3d.+$)|\(r\)| \([^)]+\)$/g, "").replace(/(?:vulkan|opengl) \d+\.\d+(?:\.\d+)?(?: \((.*)\))?/, "$1");
|
|
}
|
|
var n = "undefined" == typeof window;
|
|
var o = (() => {
|
|
if (n) return;
|
|
const { userAgent: e2, platform: t2, maxTouchPoints: r2 } = window.navigator, o2 = /(iphone|ipod|ipad)/i.test(e2), a5 = "iPad" === t2 || "MacIntel" === t2 && r2 > 0 && !window.MSStream;
|
|
return { isIpad: a5, isMobile: /android/i.test(e2) || o2 || a5, isSafari12: /Version\/12.+Safari/.test(e2), isFirefox: /Firefox/.test(e2) };
|
|
})();
|
|
function a(e2, t2, r2) {
|
|
if (!r2) return [t2];
|
|
const n2 = (function(e3) {
|
|
const t3 = "\n precision highp float;\n attribute vec3 aPosition;\n varying float vvv;\n void main() {\n vvv = 0.31622776601683794;\n gl_Position = vec4(aPosition, 1.0);\n }\n ", r3 = "\n precision highp float;\n varying float vvv;\n void main() {\n vec4 enc = vec4(1.0, 255.0, 65025.0, 16581375.0) * vvv;\n enc = fract(enc);\n enc -= enc.yzww * vec4(1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0, 0.0);\n gl_FragColor = enc;\n }\n ", n3 = e3.createShader(35633), o2 = e3.createShader(35632), a6 = e3.createProgram();
|
|
if (!(o2 && n3 && a6)) return;
|
|
e3.shaderSource(n3, t3), e3.shaderSource(o2, r3), e3.compileShader(n3), e3.compileShader(o2), e3.attachShader(a6, n3), e3.attachShader(a6, o2), e3.linkProgram(a6), e3.detachShader(a6, n3), e3.detachShader(a6, o2), e3.deleteShader(n3), e3.deleteShader(o2), e3.useProgram(a6);
|
|
const i4 = e3.createBuffer();
|
|
e3.bindBuffer(34962, i4), e3.bufferData(34962, new Float32Array([-1, -1, 0, 3, -1, 0, -1, 3, 0]), 35044);
|
|
const c5 = e3.getAttribLocation(a6, "aPosition");
|
|
e3.vertexAttribPointer(c5, 3, 5126, false, 0, 0), e3.enableVertexAttribArray(c5), e3.clearColor(1, 1, 1, 1), e3.clear(16384), e3.viewport(0, 0, 1, 1), e3.drawArrays(4, 0, 3);
|
|
const d3 = new Uint8Array(4);
|
|
return e3.readPixels(0, 0, 1, 1, 6408, 5121, d3), e3.deleteProgram(a6), e3.deleteBuffer(i4), d3.join("");
|
|
})(e2), a5 = "801621810", i3 = "8016218135", c2 = "80162181161", d2 = (null == o ? void 0 : o.isIpad) ? [["a7", c2, 12], ["a8", i3, 15], ["a8x", i3, 15], ["a9", i3, 15], ["a9x", i3, 15], ["a10", i3, 15], ["a10x", i3, 15], ["a12", a5, 15], ["a12x", a5, 15], ["a12z", a5, 15], ["a14", a5, 15], ["a15", a5, 15], ["m1", a5, 15], ["m2", a5, 15]] : [["a7", c2, 12], ["a8", i3, 12], ["a9", i3, 15], ["a10", i3, 15], ["a11", a5, 15], ["a12", a5, 15], ["a13", a5, 15], ["a14", a5, 15], ["a15", a5, 15], ["a16", a5, 15], ["a17", a5, 15]];
|
|
let l2;
|
|
"80162181255" === n2 ? l2 = d2.filter((([, , e3]) => e3 >= 14)) : (l2 = d2.filter((([, e3]) => e3 === n2)), l2.length || (l2 = d2));
|
|
return l2.map((([e3]) => `apple ${e3} gpu`));
|
|
}
|
|
var i = class extends Error {
|
|
constructor(e2) {
|
|
super(e2), Object.setPrototypeOf(this, new.target.prototype);
|
|
}
|
|
};
|
|
var c = [];
|
|
var d = [];
|
|
function l(e2, t2) {
|
|
if (e2 === t2) return 0;
|
|
const r2 = e2;
|
|
e2.length > t2.length && (e2 = t2, t2 = r2);
|
|
let n2 = e2.length, o2 = t2.length;
|
|
for (; n2 > 0 && e2.charCodeAt(~-n2) === t2.charCodeAt(~-o2); ) n2--, o2--;
|
|
let a5, i3 = 0;
|
|
for (; i3 < n2 && e2.charCodeAt(i3) === t2.charCodeAt(i3); ) i3++;
|
|
if (n2 -= i3, o2 -= i3, 0 === n2) return o2;
|
|
let l2, s2, f2 = 0, u = 0, g = 0;
|
|
for (; u < n2; ) d[u] = e2.charCodeAt(i3 + u), c[u] = ++u;
|
|
for (; g < o2; ) for (a5 = t2.charCodeAt(i3 + g), l2 = g++, f2 = g, u = 0; u < n2; u++) s2 = a5 === d[u] ? l2 : l2 + 1, l2 = c[u], f2 = c[u] = l2 > f2 ? s2 > f2 ? f2 + 1 : s2 : s2 > l2 ? l2 + 1 : s2;
|
|
return f2;
|
|
}
|
|
function s(e2) {
|
|
return null != e2;
|
|
}
|
|
var f = ({ mobileTiers: c2 = [0, 15, 30, 60], desktopTiers: d2 = [0, 15, 30, 60], override: f2 = {}, glContext: u, failIfMajorPerformanceCaveat: g = false, benchmarksURL: h = "https://unpkg.com/detect-gpu@5.0.70/dist/benchmarks" } = {}) => e(void 0, void 0, void 0, (function* () {
|
|
const p2 = {};
|
|
if (n) return { tier: 0, type: "SSR" };
|
|
const { isIpad: m = !!(null == o ? void 0 : o.isIpad), isMobile: v5 = !!(null == o ? void 0 : o.isMobile), screenSize: w = window.screen, loadBenchmarks: x = ((t2) => e(void 0, void 0, void 0, (function* () {
|
|
const e2 = yield fetch(`${h}/${t2}`).then(((e3) => e3.json()));
|
|
if (parseInt(e2.shift().split(".")[0], 10) < 4) throw new i("Detect GPU benchmark data is out of date. Please update to version 4x");
|
|
return e2;
|
|
}))) } = f2;
|
|
let { renderer: A } = f2;
|
|
const P = (e2, t2, r2, n2, o2) => ({ device: o2, fps: n2, gpu: r2, isMobile: v5, tier: e2, type: t2 });
|
|
let S, b = "";
|
|
if (A) A = r(A), S = [A];
|
|
else {
|
|
const e2 = u || (function(e3, t3 = false) {
|
|
const r2 = { alpha: false, antialias: false, depth: false, failIfMajorPerformanceCaveat: t3, powerPreference: "high-performance", stencil: false };
|
|
e3 && delete r2.powerPreference;
|
|
const n2 = window.document.createElement("canvas"), o2 = n2.getContext("webgl", r2) || n2.getContext("experimental-webgl", r2);
|
|
return null != o2 ? o2 : void 0;
|
|
})(null == o ? void 0 : o.isSafari12, g);
|
|
if (!e2) return P(0, "WEBGL_UNSUPPORTED");
|
|
const t2 = (null == o ? void 0 : o.isFirefox) ? null : e2.getExtension("WEBGL_debug_renderer_info");
|
|
if (A = t2 ? e2.getParameter(t2.UNMASKED_RENDERER_WEBGL) : e2.getParameter(e2.RENDERER), !A) return P(1, "FALLBACK");
|
|
b = A, A = r(A), S = (function(e3, t3, r2) {
|
|
return "apple gpu" === t3 ? a(e3, t3, r2) : [t3];
|
|
})(e2, A, v5);
|
|
}
|
|
const E = (yield Promise.all(S.map((function(t2) {
|
|
var r2;
|
|
return e(this, void 0, void 0, (function* () {
|
|
const e2 = ((e3) => {
|
|
const t3 = v5 ? ["adreno", "apple", "mali-t", "mali", "nvidia", "powervr", "samsung"] : ["intel", "apple", "amd", "radeon", "nvidia", "geforce", "adreno"];
|
|
for (const r3 of t3) if (e3.includes(r3)) return r3;
|
|
})(t2);
|
|
if (!e2) return;
|
|
const n2 = `${v5 ? "m" : "d"}-${e2}${m ? "-ipad" : ""}.json`, o2 = p2[n2] = null !== (r2 = p2[n2]) && void 0 !== r2 ? r2 : x(n2);
|
|
let a5;
|
|
try {
|
|
a5 = yield o2;
|
|
} catch (e3) {
|
|
if (e3 instanceof i) throw e3;
|
|
return;
|
|
}
|
|
const c5 = (function(e3) {
|
|
var t3;
|
|
const r3 = (e3 = e3.replace(/\([^)]+\)/, "")).match(/\d+/) || e3.match(/(\W|^)([A-Za-z]{1,3})(\W|$)/g);
|
|
return null !== (t3 = null == r3 ? void 0 : r3.join("").replace(/\W|amd/g, "")) && void 0 !== t3 ? t3 : "";
|
|
})(t2);
|
|
let d3 = a5.filter((([, e3]) => e3 === c5));
|
|
d3.length || (d3 = a5.filter((([e3]) => e3.includes(t2))));
|
|
const s2 = d3.length;
|
|
if (0 === s2) return;
|
|
const f3 = t2.split(/[.,()\[\]/\s]/g).sort().filter(((e3, t3, r3) => 0 === t3 || e3 !== r3[t3 - 1])).join(" ");
|
|
let u2, [g2, , , , h2] = s2 > 1 ? d3.map(((e3) => [e3, l(f3, e3[2])])).sort((([, e3], [, t3]) => e3 - t3))[0][0] : d3[0], A2 = Number.MAX_VALUE;
|
|
const { devicePixelRatio: P2 } = window, S2 = w.width * P2 * w.height * P2;
|
|
for (const e3 of h2) {
|
|
const [t3, r3] = e3, n3 = t3 * r3, o3 = Math.abs(S2 - n3);
|
|
o3 < A2 && (A2 = o3, u2 = e3);
|
|
}
|
|
if (!u2) return;
|
|
const [, , b5, E2] = u2;
|
|
return [A2, b5, g2, E2];
|
|
}));
|
|
})))).filter(s).sort((([e2 = Number.MAX_VALUE, t2], [r2 = Number.MAX_VALUE, n2]) => e2 === r2 ? t2 - n2 : e2 - r2));
|
|
if (!E.length) {
|
|
const e2 = t.find(((e3) => A.includes(e3)));
|
|
return e2 ? P(0, "BLOCKLISTED", e2) : P(1, "FALLBACK", `${A} (${b})`);
|
|
}
|
|
const [, y, C, L] = E[0];
|
|
if (-1 === y) return P(0, "BLOCKLISTED", C, y, L);
|
|
const M = v5 ? c2 : d2;
|
|
let $ = 0;
|
|
for (let e2 = 0; e2 < M.length; e2++) y >= M[e2] && ($ = e2);
|
|
return P($, "BENCHMARK", C, y, L);
|
|
}));
|
|
|
|
// node_modules/@react-three/drei/core/DetectGPU.js
|
|
var useDetectGPU = (props) => suspend(() => f(props), ["useDetectGPU"]);
|
|
function DetectGPU({
|
|
children,
|
|
...options
|
|
}) {
|
|
const result = useDetectGPU(options);
|
|
return React70.createElement(React70.Fragment, null, children == null ? void 0 : children(result));
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/Bvh.js
|
|
var React71 = __toESM(require_react());
|
|
|
|
// node_modules/three-mesh-bvh/src/core/Constants.js
|
|
var CENTER = 0;
|
|
var AVERAGE = 1;
|
|
var SAH = 2;
|
|
var CONTAINED = 2;
|
|
var TRIANGLE_INTERSECT_COST = 1.25;
|
|
var TRAVERSAL_COST = 1;
|
|
var BYTES_PER_NODE = 6 * 4 + 4 + 4;
|
|
var IS_LEAFNODE_FLAG = 65535;
|
|
var FLOAT32_EPSILON = Math.pow(2, -24);
|
|
var SKIP_GENERATION = /* @__PURE__ */ Symbol("SKIP_GENERATION");
|
|
|
|
// node_modules/three-mesh-bvh/src/core/build/geometryUtils.js
|
|
function getVertexCount(geo) {
|
|
return geo.index ? geo.index.count : geo.attributes.position.count;
|
|
}
|
|
function getTriCount(geo) {
|
|
return getVertexCount(geo) / 3;
|
|
}
|
|
function getIndexArray(vertexCount, BufferConstructor = ArrayBuffer) {
|
|
if (vertexCount > 65535) {
|
|
return new Uint32Array(new BufferConstructor(4 * vertexCount));
|
|
} else {
|
|
return new Uint16Array(new BufferConstructor(2 * vertexCount));
|
|
}
|
|
}
|
|
function ensureIndex(geo, options) {
|
|
if (!geo.index) {
|
|
const vertexCount = geo.attributes.position.count;
|
|
const BufferConstructor = options.useSharedArrayBuffer ? SharedArrayBuffer : ArrayBuffer;
|
|
const index2 = getIndexArray(vertexCount, BufferConstructor);
|
|
geo.setIndex(new BufferAttribute(index2, 1));
|
|
for (let i3 = 0; i3 < vertexCount; i3++) {
|
|
index2[i3] = i3;
|
|
}
|
|
}
|
|
}
|
|
function getFullGeometryRange(geo, range) {
|
|
const triCount = getTriCount(geo);
|
|
const drawRange = range ? range : geo.drawRange;
|
|
const start = drawRange.start / 3;
|
|
const end = (drawRange.start + drawRange.count) / 3;
|
|
const offset = Math.max(0, start);
|
|
const count = Math.min(triCount, end) - offset;
|
|
return [{
|
|
offset: Math.floor(offset),
|
|
count: Math.floor(count)
|
|
}];
|
|
}
|
|
function getRootIndexRanges(geo, range) {
|
|
if (!geo.groups || !geo.groups.length) {
|
|
return getFullGeometryRange(geo, range);
|
|
}
|
|
const ranges = [];
|
|
const rangeBoundaries = /* @__PURE__ */ new Set();
|
|
const drawRange = range ? range : geo.drawRange;
|
|
const drawRangeStart = drawRange.start / 3;
|
|
const drawRangeEnd = (drawRange.start + drawRange.count) / 3;
|
|
for (const group of geo.groups) {
|
|
const groupStart = group.start / 3;
|
|
const groupEnd = (group.start + group.count) / 3;
|
|
rangeBoundaries.add(Math.max(drawRangeStart, groupStart));
|
|
rangeBoundaries.add(Math.min(drawRangeEnd, groupEnd));
|
|
}
|
|
const sortedBoundaries = Array.from(rangeBoundaries.values()).sort((a5, b) => a5 - b);
|
|
for (let i3 = 0; i3 < sortedBoundaries.length - 1; i3++) {
|
|
const start = sortedBoundaries[i3];
|
|
const end = sortedBoundaries[i3 + 1];
|
|
ranges.push({
|
|
offset: Math.floor(start),
|
|
count: Math.floor(end - start)
|
|
});
|
|
}
|
|
return ranges;
|
|
}
|
|
function hasGroupGaps(geometry3, range) {
|
|
const vertexCount = getTriCount(geometry3);
|
|
const groups = getRootIndexRanges(geometry3, range).sort((a5, b) => a5.offset - b.offset);
|
|
const finalGroup = groups[groups.length - 1];
|
|
finalGroup.count = Math.min(vertexCount - finalGroup.offset, finalGroup.count);
|
|
let total = 0;
|
|
groups.forEach(({ count }) => total += count);
|
|
return vertexCount !== total;
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/build/computeBoundsUtils.js
|
|
function getBounds(triangleBounds, offset, count, target2, centroidTarget) {
|
|
let minx = Infinity;
|
|
let miny = Infinity;
|
|
let minz = Infinity;
|
|
let maxx = -Infinity;
|
|
let maxy = -Infinity;
|
|
let maxz = -Infinity;
|
|
let cminx = Infinity;
|
|
let cminy = Infinity;
|
|
let cminz = Infinity;
|
|
let cmaxx = -Infinity;
|
|
let cmaxy = -Infinity;
|
|
let cmaxz = -Infinity;
|
|
for (let i3 = offset * 6, end = (offset + count) * 6; i3 < end; i3 += 6) {
|
|
const cx = triangleBounds[i3 + 0];
|
|
const hx = triangleBounds[i3 + 1];
|
|
const lx = cx - hx;
|
|
const rx = cx + hx;
|
|
if (lx < minx) minx = lx;
|
|
if (rx > maxx) maxx = rx;
|
|
if (cx < cminx) cminx = cx;
|
|
if (cx > cmaxx) cmaxx = cx;
|
|
const cy = triangleBounds[i3 + 2];
|
|
const hy = triangleBounds[i3 + 3];
|
|
const ly = cy - hy;
|
|
const ry = cy + hy;
|
|
if (ly < miny) miny = ly;
|
|
if (ry > maxy) maxy = ry;
|
|
if (cy < cminy) cminy = cy;
|
|
if (cy > cmaxy) cmaxy = cy;
|
|
const cz = triangleBounds[i3 + 4];
|
|
const hz = triangleBounds[i3 + 5];
|
|
const lz = cz - hz;
|
|
const rz = cz + hz;
|
|
if (lz < minz) minz = lz;
|
|
if (rz > maxz) maxz = rz;
|
|
if (cz < cminz) cminz = cz;
|
|
if (cz > cmaxz) cmaxz = cz;
|
|
}
|
|
target2[0] = minx;
|
|
target2[1] = miny;
|
|
target2[2] = minz;
|
|
target2[3] = maxx;
|
|
target2[4] = maxy;
|
|
target2[5] = maxz;
|
|
centroidTarget[0] = cminx;
|
|
centroidTarget[1] = cminy;
|
|
centroidTarget[2] = cminz;
|
|
centroidTarget[3] = cmaxx;
|
|
centroidTarget[4] = cmaxy;
|
|
centroidTarget[5] = cmaxz;
|
|
}
|
|
function computeTriangleBounds(geo, target2 = null, offset = null, count = null) {
|
|
const posAttr = geo.attributes.position;
|
|
const index2 = geo.index ? geo.index.array : null;
|
|
const triCount = getTriCount(geo);
|
|
const normalized = posAttr.normalized;
|
|
let triangleBounds;
|
|
if (target2 === null) {
|
|
triangleBounds = new Float32Array(triCount * 6);
|
|
offset = 0;
|
|
count = triCount;
|
|
} else {
|
|
triangleBounds = target2;
|
|
offset = offset || 0;
|
|
count = count || triCount;
|
|
}
|
|
const posArr = posAttr.array;
|
|
const bufferOffset = posAttr.offset || 0;
|
|
let stride = 3;
|
|
if (posAttr.isInterleavedBufferAttribute) {
|
|
stride = posAttr.data.stride;
|
|
}
|
|
const getters = ["getX", "getY", "getZ"];
|
|
for (let tri = offset; tri < offset + count; tri++) {
|
|
const tri3 = tri * 3;
|
|
const tri6 = tri * 6;
|
|
let ai = tri3 + 0;
|
|
let bi = tri3 + 1;
|
|
let ci = tri3 + 2;
|
|
if (index2) {
|
|
ai = index2[ai];
|
|
bi = index2[bi];
|
|
ci = index2[ci];
|
|
}
|
|
if (!normalized) {
|
|
ai = ai * stride + bufferOffset;
|
|
bi = bi * stride + bufferOffset;
|
|
ci = ci * stride + bufferOffset;
|
|
}
|
|
for (let el = 0; el < 3; el++) {
|
|
let a5, b, c2;
|
|
if (normalized) {
|
|
a5 = posAttr[getters[el]](ai);
|
|
b = posAttr[getters[el]](bi);
|
|
c2 = posAttr[getters[el]](ci);
|
|
} else {
|
|
a5 = posArr[ai + el];
|
|
b = posArr[bi + el];
|
|
c2 = posArr[ci + el];
|
|
}
|
|
let min = a5;
|
|
if (b < min) min = b;
|
|
if (c2 < min) min = c2;
|
|
let max = a5;
|
|
if (b > max) max = b;
|
|
if (c2 > max) max = c2;
|
|
const halfExtents = (max - min) / 2;
|
|
const el2 = el * 2;
|
|
triangleBounds[tri6 + el2 + 0] = min + halfExtents;
|
|
triangleBounds[tri6 + el2 + 1] = halfExtents + (Math.abs(min) + halfExtents) * FLOAT32_EPSILON;
|
|
}
|
|
}
|
|
return triangleBounds;
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/utils/ArrayBoxUtilities.js
|
|
function arrayToBox(nodeIndex32, array, target2) {
|
|
target2.min.x = array[nodeIndex32];
|
|
target2.min.y = array[nodeIndex32 + 1];
|
|
target2.min.z = array[nodeIndex32 + 2];
|
|
target2.max.x = array[nodeIndex32 + 3];
|
|
target2.max.y = array[nodeIndex32 + 4];
|
|
target2.max.z = array[nodeIndex32 + 5];
|
|
return target2;
|
|
}
|
|
function getLongestEdgeIndex(bounds) {
|
|
let splitDimIdx = -1;
|
|
let splitDist = -Infinity;
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
const dist = bounds[i3 + 3] - bounds[i3];
|
|
if (dist > splitDist) {
|
|
splitDist = dist;
|
|
splitDimIdx = i3;
|
|
}
|
|
}
|
|
return splitDimIdx;
|
|
}
|
|
function copyBounds(source, target2) {
|
|
target2.set(source);
|
|
}
|
|
function unionBounds(a5, b, target2) {
|
|
let aVal, bVal;
|
|
for (let d2 = 0; d2 < 3; d2++) {
|
|
const d3 = d2 + 3;
|
|
aVal = a5[d2];
|
|
bVal = b[d2];
|
|
target2[d2] = aVal < bVal ? aVal : bVal;
|
|
aVal = a5[d3];
|
|
bVal = b[d3];
|
|
target2[d3] = aVal > bVal ? aVal : bVal;
|
|
}
|
|
}
|
|
function expandByTriangleBounds(startIndex, triangleBounds, bounds) {
|
|
for (let d2 = 0; d2 < 3; d2++) {
|
|
const tCenter = triangleBounds[startIndex + 2 * d2];
|
|
const tHalf = triangleBounds[startIndex + 2 * d2 + 1];
|
|
const tMin = tCenter - tHalf;
|
|
const tMax = tCenter + tHalf;
|
|
if (tMin < bounds[d2]) {
|
|
bounds[d2] = tMin;
|
|
}
|
|
if (tMax > bounds[d2 + 3]) {
|
|
bounds[d2 + 3] = tMax;
|
|
}
|
|
}
|
|
}
|
|
function computeSurfaceArea(bounds) {
|
|
const d0 = bounds[3] - bounds[0];
|
|
const d1 = bounds[4] - bounds[1];
|
|
const d2 = bounds[5] - bounds[2];
|
|
return 2 * (d0 * d1 + d1 * d2 + d2 * d0);
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/build/splitUtils.js
|
|
var BIN_COUNT = 32;
|
|
var binsSort = (a5, b) => a5.candidate - b.candidate;
|
|
var sahBins = new Array(BIN_COUNT).fill().map(() => {
|
|
return {
|
|
count: 0,
|
|
bounds: new Float32Array(6),
|
|
rightCacheBounds: new Float32Array(6),
|
|
leftCacheBounds: new Float32Array(6),
|
|
candidate: 0
|
|
};
|
|
});
|
|
var leftBounds = new Float32Array(6);
|
|
function getOptimalSplit(nodeBoundingData, centroidBoundingData, triangleBounds, offset, count, strategy) {
|
|
let axis = -1;
|
|
let pos = 0;
|
|
if (strategy === CENTER) {
|
|
axis = getLongestEdgeIndex(centroidBoundingData);
|
|
if (axis !== -1) {
|
|
pos = (centroidBoundingData[axis] + centroidBoundingData[axis + 3]) / 2;
|
|
}
|
|
} else if (strategy === AVERAGE) {
|
|
axis = getLongestEdgeIndex(nodeBoundingData);
|
|
if (axis !== -1) {
|
|
pos = getAverage(triangleBounds, offset, count, axis);
|
|
}
|
|
} else if (strategy === SAH) {
|
|
const rootSurfaceArea = computeSurfaceArea(nodeBoundingData);
|
|
let bestCost = TRIANGLE_INTERSECT_COST * count;
|
|
const cStart = offset * 6;
|
|
const cEnd = (offset + count) * 6;
|
|
for (let a5 = 0; a5 < 3; a5++) {
|
|
const axisLeft = centroidBoundingData[a5];
|
|
const axisRight = centroidBoundingData[a5 + 3];
|
|
const axisLength = axisRight - axisLeft;
|
|
const binWidth = axisLength / BIN_COUNT;
|
|
if (count < BIN_COUNT / 4) {
|
|
const truncatedBins = [...sahBins];
|
|
truncatedBins.length = count;
|
|
let b = 0;
|
|
for (let c2 = cStart; c2 < cEnd; c2 += 6, b++) {
|
|
const bin = truncatedBins[b];
|
|
bin.candidate = triangleBounds[c2 + 2 * a5];
|
|
bin.count = 0;
|
|
const {
|
|
bounds,
|
|
leftCacheBounds,
|
|
rightCacheBounds
|
|
} = bin;
|
|
for (let d2 = 0; d2 < 3; d2++) {
|
|
rightCacheBounds[d2] = Infinity;
|
|
rightCacheBounds[d2 + 3] = -Infinity;
|
|
leftCacheBounds[d2] = Infinity;
|
|
leftCacheBounds[d2 + 3] = -Infinity;
|
|
bounds[d2] = Infinity;
|
|
bounds[d2 + 3] = -Infinity;
|
|
}
|
|
expandByTriangleBounds(c2, triangleBounds, bounds);
|
|
}
|
|
truncatedBins.sort(binsSort);
|
|
let splitCount = count;
|
|
for (let bi = 0; bi < splitCount; bi++) {
|
|
const bin = truncatedBins[bi];
|
|
while (bi + 1 < splitCount && truncatedBins[bi + 1].candidate === bin.candidate) {
|
|
truncatedBins.splice(bi + 1, 1);
|
|
splitCount--;
|
|
}
|
|
}
|
|
for (let c2 = cStart; c2 < cEnd; c2 += 6) {
|
|
const center2 = triangleBounds[c2 + 2 * a5];
|
|
for (let bi = 0; bi < splitCount; bi++) {
|
|
const bin = truncatedBins[bi];
|
|
if (center2 >= bin.candidate) {
|
|
expandByTriangleBounds(c2, triangleBounds, bin.rightCacheBounds);
|
|
} else {
|
|
expandByTriangleBounds(c2, triangleBounds, bin.leftCacheBounds);
|
|
bin.count++;
|
|
}
|
|
}
|
|
}
|
|
for (let bi = 0; bi < splitCount; bi++) {
|
|
const bin = truncatedBins[bi];
|
|
const leftCount = bin.count;
|
|
const rightCount = count - bin.count;
|
|
const leftBounds2 = bin.leftCacheBounds;
|
|
const rightBounds = bin.rightCacheBounds;
|
|
let leftProb = 0;
|
|
if (leftCount !== 0) {
|
|
leftProb = computeSurfaceArea(leftBounds2) / rootSurfaceArea;
|
|
}
|
|
let rightProb = 0;
|
|
if (rightCount !== 0) {
|
|
rightProb = computeSurfaceArea(rightBounds) / rootSurfaceArea;
|
|
}
|
|
const cost = TRAVERSAL_COST + TRIANGLE_INTERSECT_COST * (leftProb * leftCount + rightProb * rightCount);
|
|
if (cost < bestCost) {
|
|
axis = a5;
|
|
bestCost = cost;
|
|
pos = bin.candidate;
|
|
}
|
|
}
|
|
} else {
|
|
for (let i3 = 0; i3 < BIN_COUNT; i3++) {
|
|
const bin = sahBins[i3];
|
|
bin.count = 0;
|
|
bin.candidate = axisLeft + binWidth + i3 * binWidth;
|
|
const bounds = bin.bounds;
|
|
for (let d2 = 0; d2 < 3; d2++) {
|
|
bounds[d2] = Infinity;
|
|
bounds[d2 + 3] = -Infinity;
|
|
}
|
|
}
|
|
for (let c2 = cStart; c2 < cEnd; c2 += 6) {
|
|
const triCenter = triangleBounds[c2 + 2 * a5];
|
|
const relativeCenter = triCenter - axisLeft;
|
|
let binIndex = ~~(relativeCenter / binWidth);
|
|
if (binIndex >= BIN_COUNT) binIndex = BIN_COUNT - 1;
|
|
const bin = sahBins[binIndex];
|
|
bin.count++;
|
|
expandByTriangleBounds(c2, triangleBounds, bin.bounds);
|
|
}
|
|
const lastBin = sahBins[BIN_COUNT - 1];
|
|
copyBounds(lastBin.bounds, lastBin.rightCacheBounds);
|
|
for (let i3 = BIN_COUNT - 2; i3 >= 0; i3--) {
|
|
const bin = sahBins[i3];
|
|
const nextBin = sahBins[i3 + 1];
|
|
unionBounds(bin.bounds, nextBin.rightCacheBounds, bin.rightCacheBounds);
|
|
}
|
|
let leftCount = 0;
|
|
for (let i3 = 0; i3 < BIN_COUNT - 1; i3++) {
|
|
const bin = sahBins[i3];
|
|
const binCount = bin.count;
|
|
const bounds = bin.bounds;
|
|
const nextBin = sahBins[i3 + 1];
|
|
const rightBounds = nextBin.rightCacheBounds;
|
|
if (binCount !== 0) {
|
|
if (leftCount === 0) {
|
|
copyBounds(bounds, leftBounds);
|
|
} else {
|
|
unionBounds(bounds, leftBounds, leftBounds);
|
|
}
|
|
}
|
|
leftCount += binCount;
|
|
let leftProb = 0;
|
|
let rightProb = 0;
|
|
if (leftCount !== 0) {
|
|
leftProb = computeSurfaceArea(leftBounds) / rootSurfaceArea;
|
|
}
|
|
const rightCount = count - leftCount;
|
|
if (rightCount !== 0) {
|
|
rightProb = computeSurfaceArea(rightBounds) / rootSurfaceArea;
|
|
}
|
|
const cost = TRAVERSAL_COST + TRIANGLE_INTERSECT_COST * (leftProb * leftCount + rightProb * rightCount);
|
|
if (cost < bestCost) {
|
|
axis = a5;
|
|
bestCost = cost;
|
|
pos = bin.candidate;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
console.warn(`MeshBVH: Invalid build strategy value ${strategy} used.`);
|
|
}
|
|
return { axis, pos };
|
|
}
|
|
function getAverage(triangleBounds, offset, count, axis) {
|
|
let avg = 0;
|
|
for (let i3 = offset, end = offset + count; i3 < end; i3++) {
|
|
avg += triangleBounds[i3 * 6 + axis * 2];
|
|
}
|
|
return avg / count;
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/MeshBVHNode.js
|
|
var MeshBVHNode = class {
|
|
constructor() {
|
|
this.boundingData = new Float32Array(6);
|
|
}
|
|
};
|
|
|
|
// node_modules/three-mesh-bvh/src/core/build/sortUtils.generated.js
|
|
function partition(indirectBuffer, index2, triangleBounds, offset, count, split) {
|
|
let left = offset;
|
|
let right = offset + count - 1;
|
|
const pos = split.pos;
|
|
const axisOffset = split.axis * 2;
|
|
while (true) {
|
|
while (left <= right && triangleBounds[left * 6 + axisOffset] < pos) {
|
|
left++;
|
|
}
|
|
while (left <= right && triangleBounds[right * 6 + axisOffset] >= pos) {
|
|
right--;
|
|
}
|
|
if (left < right) {
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
let t0 = index2[left * 3 + i3];
|
|
index2[left * 3 + i3] = index2[right * 3 + i3];
|
|
index2[right * 3 + i3] = t0;
|
|
}
|
|
for (let i3 = 0; i3 < 6; i3++) {
|
|
let tb = triangleBounds[left * 6 + i3];
|
|
triangleBounds[left * 6 + i3] = triangleBounds[right * 6 + i3];
|
|
triangleBounds[right * 6 + i3] = tb;
|
|
}
|
|
left++;
|
|
right--;
|
|
} else {
|
|
return left;
|
|
}
|
|
}
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/build/sortUtils_indirect.generated.js
|
|
function partition_indirect(indirectBuffer, index2, triangleBounds, offset, count, split) {
|
|
let left = offset;
|
|
let right = offset + count - 1;
|
|
const pos = split.pos;
|
|
const axisOffset = split.axis * 2;
|
|
while (true) {
|
|
while (left <= right && triangleBounds[left * 6 + axisOffset] < pos) {
|
|
left++;
|
|
}
|
|
while (left <= right && triangleBounds[right * 6 + axisOffset] >= pos) {
|
|
right--;
|
|
}
|
|
if (left < right) {
|
|
let t2 = indirectBuffer[left];
|
|
indirectBuffer[left] = indirectBuffer[right];
|
|
indirectBuffer[right] = t2;
|
|
for (let i3 = 0; i3 < 6; i3++) {
|
|
let tb = triangleBounds[left * 6 + i3];
|
|
triangleBounds[left * 6 + i3] = triangleBounds[right * 6 + i3];
|
|
triangleBounds[right * 6 + i3] = tb;
|
|
}
|
|
left++;
|
|
right--;
|
|
} else {
|
|
return left;
|
|
}
|
|
}
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/utils/nodeBufferUtils.js
|
|
function IS_LEAF(n16, uint16Array2) {
|
|
return uint16Array2[n16 + 15] === 65535;
|
|
}
|
|
function OFFSET(n32, uint32Array2) {
|
|
return uint32Array2[n32 + 6];
|
|
}
|
|
function COUNT(n16, uint16Array2) {
|
|
return uint16Array2[n16 + 14];
|
|
}
|
|
function LEFT_NODE(n32) {
|
|
return n32 + 8;
|
|
}
|
|
function RIGHT_NODE(n32, uint32Array2) {
|
|
return uint32Array2[n32 + 6];
|
|
}
|
|
function SPLIT_AXIS(n32, uint32Array2) {
|
|
return uint32Array2[n32 + 7];
|
|
}
|
|
function BOUNDING_DATA_INDEX(n32) {
|
|
return n32;
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/build/buildUtils.js
|
|
var float32Array;
|
|
var uint32Array;
|
|
var uint16Array;
|
|
var uint8Array;
|
|
var MAX_POINTER = Math.pow(2, 32);
|
|
function countNodes(node) {
|
|
if ("count" in node) {
|
|
return 1;
|
|
} else {
|
|
return 1 + countNodes(node.left) + countNodes(node.right);
|
|
}
|
|
}
|
|
function populateBuffer(byteOffset, node, buffer2) {
|
|
float32Array = new Float32Array(buffer2);
|
|
uint32Array = new Uint32Array(buffer2);
|
|
uint16Array = new Uint16Array(buffer2);
|
|
uint8Array = new Uint8Array(buffer2);
|
|
return _populateBuffer(byteOffset, node);
|
|
}
|
|
function _populateBuffer(byteOffset, node) {
|
|
const stride4Offset = byteOffset / 4;
|
|
const stride2Offset = byteOffset / 2;
|
|
const isLeaf = "count" in node;
|
|
const boundingData = node.boundingData;
|
|
for (let i3 = 0; i3 < 6; i3++) {
|
|
float32Array[stride4Offset + i3] = boundingData[i3];
|
|
}
|
|
if (isLeaf) {
|
|
if (node.buffer) {
|
|
const buffer2 = node.buffer;
|
|
uint8Array.set(new Uint8Array(buffer2), byteOffset);
|
|
for (let offset = byteOffset, l2 = byteOffset + buffer2.byteLength; offset < l2; offset += BYTES_PER_NODE) {
|
|
const offset2 = offset / 2;
|
|
if (!IS_LEAF(offset2, uint16Array)) {
|
|
uint32Array[offset / 4 + 6] += stride4Offset;
|
|
}
|
|
}
|
|
return byteOffset + buffer2.byteLength;
|
|
} else {
|
|
const offset = node.offset;
|
|
const count = node.count;
|
|
uint32Array[stride4Offset + 6] = offset;
|
|
uint16Array[stride2Offset + 14] = count;
|
|
uint16Array[stride2Offset + 15] = IS_LEAFNODE_FLAG;
|
|
return byteOffset + BYTES_PER_NODE;
|
|
}
|
|
} else {
|
|
const left = node.left;
|
|
const right = node.right;
|
|
const splitAxis = node.splitAxis;
|
|
let nextUnusedPointer;
|
|
nextUnusedPointer = _populateBuffer(byteOffset + BYTES_PER_NODE, left);
|
|
if (nextUnusedPointer / 4 > MAX_POINTER) {
|
|
throw new Error("MeshBVH: Cannot store child pointer greater than 32 bits.");
|
|
}
|
|
uint32Array[stride4Offset + 6] = nextUnusedPointer / 4;
|
|
nextUnusedPointer = _populateBuffer(nextUnusedPointer, right);
|
|
uint32Array[stride4Offset + 7] = splitAxis;
|
|
return nextUnusedPointer;
|
|
}
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/build/buildTree.js
|
|
function generateIndirectBuffer(geometry3, useSharedArrayBuffer) {
|
|
const triCount = (geometry3.index ? geometry3.index.count : geometry3.attributes.position.count) / 3;
|
|
const useUint32 = triCount > 2 ** 16;
|
|
const byteCount = useUint32 ? 4 : 2;
|
|
const buffer2 = useSharedArrayBuffer ? new SharedArrayBuffer(triCount * byteCount) : new ArrayBuffer(triCount * byteCount);
|
|
const indirectBuffer = useUint32 ? new Uint32Array(buffer2) : new Uint16Array(buffer2);
|
|
for (let i3 = 0, l2 = indirectBuffer.length; i3 < l2; i3++) {
|
|
indirectBuffer[i3] = i3;
|
|
}
|
|
return indirectBuffer;
|
|
}
|
|
function buildTree(bvh, triangleBounds, offset, count, options) {
|
|
const {
|
|
maxDepth,
|
|
verbose,
|
|
maxLeafTris,
|
|
strategy,
|
|
onProgress,
|
|
indirect
|
|
} = options;
|
|
const indirectBuffer = bvh._indirectBuffer;
|
|
const geometry3 = bvh.geometry;
|
|
const indexArray = geometry3.index ? geometry3.index.array : null;
|
|
const partionFunc = indirect ? partition_indirect : partition;
|
|
const totalTriangles = getTriCount(geometry3);
|
|
const cacheCentroidBoundingData = new Float32Array(6);
|
|
let reachedMaxDepth = false;
|
|
const root = new MeshBVHNode();
|
|
getBounds(triangleBounds, offset, count, root.boundingData, cacheCentroidBoundingData);
|
|
splitNode(root, offset, count, cacheCentroidBoundingData);
|
|
return root;
|
|
function triggerProgress(trianglesProcessed) {
|
|
if (onProgress) {
|
|
onProgress(trianglesProcessed / totalTriangles);
|
|
}
|
|
}
|
|
function splitNode(node, offset2, count2, centroidBoundingData = null, depth = 0) {
|
|
if (!reachedMaxDepth && depth >= maxDepth) {
|
|
reachedMaxDepth = true;
|
|
if (verbose) {
|
|
console.warn(`MeshBVH: Max depth of ${maxDepth} reached when generating BVH. Consider increasing maxDepth.`);
|
|
console.warn(geometry3);
|
|
}
|
|
}
|
|
if (count2 <= maxLeafTris || depth >= maxDepth) {
|
|
triggerProgress(offset2 + count2);
|
|
node.offset = offset2;
|
|
node.count = count2;
|
|
return node;
|
|
}
|
|
const split = getOptimalSplit(node.boundingData, centroidBoundingData, triangleBounds, offset2, count2, strategy);
|
|
if (split.axis === -1) {
|
|
triggerProgress(offset2 + count2);
|
|
node.offset = offset2;
|
|
node.count = count2;
|
|
return node;
|
|
}
|
|
const splitOffset = partionFunc(indirectBuffer, indexArray, triangleBounds, offset2, count2, split);
|
|
if (splitOffset === offset2 || splitOffset === offset2 + count2) {
|
|
triggerProgress(offset2 + count2);
|
|
node.offset = offset2;
|
|
node.count = count2;
|
|
} else {
|
|
node.splitAxis = split.axis;
|
|
const left = new MeshBVHNode();
|
|
const lstart = offset2;
|
|
const lcount = splitOffset - offset2;
|
|
node.left = left;
|
|
getBounds(triangleBounds, lstart, lcount, left.boundingData, cacheCentroidBoundingData);
|
|
splitNode(left, lstart, lcount, cacheCentroidBoundingData, depth + 1);
|
|
const right = new MeshBVHNode();
|
|
const rstart = splitOffset;
|
|
const rcount = count2 - lcount;
|
|
node.right = right;
|
|
getBounds(triangleBounds, rstart, rcount, right.boundingData, cacheCentroidBoundingData);
|
|
splitNode(right, rstart, rcount, cacheCentroidBoundingData, depth + 1);
|
|
}
|
|
return node;
|
|
}
|
|
}
|
|
function buildPackedTree(bvh, options) {
|
|
const geometry3 = bvh.geometry;
|
|
if (options.indirect) {
|
|
bvh._indirectBuffer = generateIndirectBuffer(geometry3, options.useSharedArrayBuffer);
|
|
if (hasGroupGaps(geometry3, options.range) && !options.verbose) {
|
|
console.warn(
|
|
'MeshBVH: Provided geometry contains groups or a range that do not fully span the vertex contents while using the "indirect" option. BVH may incorrectly report intersections on unrendered portions of the geometry.'
|
|
);
|
|
}
|
|
}
|
|
if (!bvh._indirectBuffer) {
|
|
ensureIndex(geometry3, options);
|
|
}
|
|
const BufferConstructor = options.useSharedArrayBuffer ? SharedArrayBuffer : ArrayBuffer;
|
|
const triangleBounds = computeTriangleBounds(geometry3);
|
|
const geometryRanges = options.indirect ? getFullGeometryRange(geometry3, options.range) : getRootIndexRanges(geometry3, options.range);
|
|
bvh._roots = geometryRanges.map((range) => {
|
|
const root = buildTree(bvh, triangleBounds, range.offset, range.count, options);
|
|
const nodeCount = countNodes(root);
|
|
const buffer2 = new BufferConstructor(BYTES_PER_NODE * nodeCount);
|
|
populateBuffer(0, root, buffer2);
|
|
return buffer2;
|
|
});
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/math/SeparatingAxisBounds.js
|
|
var SeparatingAxisBounds = class {
|
|
constructor() {
|
|
this.min = Infinity;
|
|
this.max = -Infinity;
|
|
}
|
|
setFromPointsField(points, field) {
|
|
let min = Infinity;
|
|
let max = -Infinity;
|
|
for (let i3 = 0, l2 = points.length; i3 < l2; i3++) {
|
|
const p2 = points[i3];
|
|
const val = p2[field];
|
|
min = val < min ? val : min;
|
|
max = val > max ? val : max;
|
|
}
|
|
this.min = min;
|
|
this.max = max;
|
|
}
|
|
setFromPoints(axis, points) {
|
|
let min = Infinity;
|
|
let max = -Infinity;
|
|
for (let i3 = 0, l2 = points.length; i3 < l2; i3++) {
|
|
const p2 = points[i3];
|
|
const val = axis.dot(p2);
|
|
min = val < min ? val : min;
|
|
max = val > max ? val : max;
|
|
}
|
|
this.min = min;
|
|
this.max = max;
|
|
}
|
|
isSeparated(other) {
|
|
return this.min > other.max || other.min > this.max;
|
|
}
|
|
};
|
|
SeparatingAxisBounds.prototype.setFromBox = (function() {
|
|
const p2 = new Vector3();
|
|
return function setFromBox(axis, box) {
|
|
const boxMin = box.min;
|
|
const boxMax = box.max;
|
|
let min = Infinity;
|
|
let max = -Infinity;
|
|
for (let x = 0; x <= 1; x++) {
|
|
for (let y = 0; y <= 1; y++) {
|
|
for (let z = 0; z <= 1; z++) {
|
|
p2.x = boxMin.x * x + boxMax.x * (1 - x);
|
|
p2.y = boxMin.y * y + boxMax.y * (1 - y);
|
|
p2.z = boxMin.z * z + boxMax.z * (1 - z);
|
|
const val = axis.dot(p2);
|
|
min = Math.min(val, min);
|
|
max = Math.max(val, max);
|
|
}
|
|
}
|
|
}
|
|
this.min = min;
|
|
this.max = max;
|
|
};
|
|
})();
|
|
var areIntersecting = (function() {
|
|
const cacheSatBounds = new SeparatingAxisBounds();
|
|
return function areIntersecting2(shape1, shape2) {
|
|
const points1 = shape1.points;
|
|
const satAxes1 = shape1.satAxes;
|
|
const satBounds1 = shape1.satBounds;
|
|
const points2 = shape2.points;
|
|
const satAxes2 = shape2.satAxes;
|
|
const satBounds2 = shape2.satBounds;
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
const sb = satBounds1[i3];
|
|
const sa = satAxes1[i3];
|
|
cacheSatBounds.setFromPoints(sa, points2);
|
|
if (sb.isSeparated(cacheSatBounds)) return false;
|
|
}
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
const sb = satBounds2[i3];
|
|
const sa = satAxes2[i3];
|
|
cacheSatBounds.setFromPoints(sa, points1);
|
|
if (sb.isSeparated(cacheSatBounds)) return false;
|
|
}
|
|
};
|
|
})();
|
|
|
|
// node_modules/three-mesh-bvh/src/math/MathUtilities.js
|
|
var closestPointLineToLine = (function() {
|
|
const dir1 = new Vector3();
|
|
const dir2 = new Vector3();
|
|
const v02 = new Vector3();
|
|
return function closestPointLineToLine2(l1, l2, result) {
|
|
const v0 = l1.start;
|
|
const v10 = dir1;
|
|
const v22 = l2.start;
|
|
const v32 = dir2;
|
|
v02.subVectors(v0, v22);
|
|
dir1.subVectors(l1.end, l1.start);
|
|
dir2.subVectors(l2.end, l2.start);
|
|
const d0232 = v02.dot(v32);
|
|
const d3210 = v32.dot(v10);
|
|
const d3232 = v32.dot(v32);
|
|
const d0210 = v02.dot(v10);
|
|
const d1010 = v10.dot(v10);
|
|
const denom = d1010 * d3232 - d3210 * d3210;
|
|
let d2, d22;
|
|
if (denom !== 0) {
|
|
d2 = (d0232 * d3210 - d0210 * d3232) / denom;
|
|
} else {
|
|
d2 = 0;
|
|
}
|
|
d22 = (d0232 + d2 * d3210) / d3232;
|
|
result.x = d2;
|
|
result.y = d22;
|
|
};
|
|
})();
|
|
var closestPointsSegmentToSegment = (function() {
|
|
const paramResult = new Vector2();
|
|
const temp14 = new Vector3();
|
|
const temp23 = new Vector3();
|
|
return function closestPointsSegmentToSegment2(l1, l2, target1, target2) {
|
|
closestPointLineToLine(l1, l2, paramResult);
|
|
let d2 = paramResult.x;
|
|
let d22 = paramResult.y;
|
|
if (d2 >= 0 && d2 <= 1 && d22 >= 0 && d22 <= 1) {
|
|
l1.at(d2, target1);
|
|
l2.at(d22, target2);
|
|
return;
|
|
} else if (d2 >= 0 && d2 <= 1) {
|
|
if (d22 < 0) {
|
|
l2.at(0, target2);
|
|
} else {
|
|
l2.at(1, target2);
|
|
}
|
|
l1.closestPointToPoint(target2, true, target1);
|
|
return;
|
|
} else if (d22 >= 0 && d22 <= 1) {
|
|
if (d2 < 0) {
|
|
l1.at(0, target1);
|
|
} else {
|
|
l1.at(1, target1);
|
|
}
|
|
l2.closestPointToPoint(target1, true, target2);
|
|
return;
|
|
} else {
|
|
let p2;
|
|
if (d2 < 0) {
|
|
p2 = l1.start;
|
|
} else {
|
|
p2 = l1.end;
|
|
}
|
|
let p22;
|
|
if (d22 < 0) {
|
|
p22 = l2.start;
|
|
} else {
|
|
p22 = l2.end;
|
|
}
|
|
const closestPoint = temp14;
|
|
const closestPoint2 = temp23;
|
|
l1.closestPointToPoint(p22, true, temp14);
|
|
l2.closestPointToPoint(p2, true, temp23);
|
|
if (closestPoint.distanceToSquared(p22) <= closestPoint2.distanceToSquared(p2)) {
|
|
target1.copy(closestPoint);
|
|
target2.copy(p22);
|
|
return;
|
|
} else {
|
|
target1.copy(p2);
|
|
target2.copy(closestPoint2);
|
|
return;
|
|
}
|
|
}
|
|
};
|
|
})();
|
|
var sphereIntersectTriangle = (function() {
|
|
const closestPointTemp = new Vector3();
|
|
const projectedPointTemp = new Vector3();
|
|
const planeTemp = new Plane();
|
|
const lineTemp = new Line3();
|
|
return function sphereIntersectTriangle2(sphere, triangle4) {
|
|
const { radius, center: center2 } = sphere;
|
|
const { a: a5, b, c: c2 } = triangle4;
|
|
lineTemp.start = a5;
|
|
lineTemp.end = b;
|
|
const closestPoint1 = lineTemp.closestPointToPoint(center2, true, closestPointTemp);
|
|
if (closestPoint1.distanceTo(center2) <= radius) return true;
|
|
lineTemp.start = a5;
|
|
lineTemp.end = c2;
|
|
const closestPoint2 = lineTemp.closestPointToPoint(center2, true, closestPointTemp);
|
|
if (closestPoint2.distanceTo(center2) <= radius) return true;
|
|
lineTemp.start = b;
|
|
lineTemp.end = c2;
|
|
const closestPoint3 = lineTemp.closestPointToPoint(center2, true, closestPointTemp);
|
|
if (closestPoint3.distanceTo(center2) <= radius) return true;
|
|
const plane = triangle4.getPlane(planeTemp);
|
|
const dp = Math.abs(plane.distanceToPoint(center2));
|
|
if (dp <= radius) {
|
|
const pp = plane.projectPoint(center2, projectedPointTemp);
|
|
const cp = triangle4.containsPoint(pp);
|
|
if (cp) return true;
|
|
}
|
|
return false;
|
|
};
|
|
})();
|
|
|
|
// node_modules/three-mesh-bvh/src/math/ExtendedTriangle.js
|
|
var ZERO_EPSILON = 1e-15;
|
|
function isNearZero(value) {
|
|
return Math.abs(value) < ZERO_EPSILON;
|
|
}
|
|
var ExtendedTriangle = class extends Triangle {
|
|
constructor(...args) {
|
|
super(...args);
|
|
this.isExtendedTriangle = true;
|
|
this.satAxes = new Array(4).fill().map(() => new Vector3());
|
|
this.satBounds = new Array(4).fill().map(() => new SeparatingAxisBounds());
|
|
this.points = [this.a, this.b, this.c];
|
|
this.sphere = new Sphere();
|
|
this.plane = new Plane();
|
|
this.needsUpdate = true;
|
|
}
|
|
intersectsSphere(sphere) {
|
|
return sphereIntersectTriangle(sphere, this);
|
|
}
|
|
update() {
|
|
const a5 = this.a;
|
|
const b = this.b;
|
|
const c2 = this.c;
|
|
const points = this.points;
|
|
const satAxes = this.satAxes;
|
|
const satBounds = this.satBounds;
|
|
const axis0 = satAxes[0];
|
|
const sab0 = satBounds[0];
|
|
this.getNormal(axis0);
|
|
sab0.setFromPoints(axis0, points);
|
|
const axis1 = satAxes[1];
|
|
const sab1 = satBounds[1];
|
|
axis1.subVectors(a5, b);
|
|
sab1.setFromPoints(axis1, points);
|
|
const axis2 = satAxes[2];
|
|
const sab2 = satBounds[2];
|
|
axis2.subVectors(b, c2);
|
|
sab2.setFromPoints(axis2, points);
|
|
const axis3 = satAxes[3];
|
|
const sab3 = satBounds[3];
|
|
axis3.subVectors(c2, a5);
|
|
sab3.setFromPoints(axis3, points);
|
|
this.sphere.setFromPoints(this.points);
|
|
this.plane.setFromNormalAndCoplanarPoint(axis0, a5);
|
|
this.needsUpdate = false;
|
|
}
|
|
};
|
|
ExtendedTriangle.prototype.closestPointToSegment = (function() {
|
|
const point1 = new Vector3();
|
|
const point2 = new Vector3();
|
|
const edge = new Line3();
|
|
return function distanceToSegment(segment, target1 = null, target2 = null) {
|
|
const { start, end } = segment;
|
|
const points = this.points;
|
|
let distSq;
|
|
let closestDistanceSq = Infinity;
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
const nexti = (i3 + 1) % 3;
|
|
edge.start.copy(points[i3]);
|
|
edge.end.copy(points[nexti]);
|
|
closestPointsSegmentToSegment(edge, segment, point1, point2);
|
|
distSq = point1.distanceToSquared(point2);
|
|
if (distSq < closestDistanceSq) {
|
|
closestDistanceSq = distSq;
|
|
if (target1) target1.copy(point1);
|
|
if (target2) target2.copy(point2);
|
|
}
|
|
}
|
|
this.closestPointToPoint(start, point1);
|
|
distSq = start.distanceToSquared(point1);
|
|
if (distSq < closestDistanceSq) {
|
|
closestDistanceSq = distSq;
|
|
if (target1) target1.copy(point1);
|
|
if (target2) target2.copy(start);
|
|
}
|
|
this.closestPointToPoint(end, point1);
|
|
distSq = end.distanceToSquared(point1);
|
|
if (distSq < closestDistanceSq) {
|
|
closestDistanceSq = distSq;
|
|
if (target1) target1.copy(point1);
|
|
if (target2) target2.copy(end);
|
|
}
|
|
return Math.sqrt(closestDistanceSq);
|
|
};
|
|
})();
|
|
ExtendedTriangle.prototype.intersectsTriangle = (function() {
|
|
const saTri2 = new ExtendedTriangle();
|
|
const arr1 = new Array(3);
|
|
const arr2 = new Array(3);
|
|
const cachedSatBounds = new SeparatingAxisBounds();
|
|
const cachedSatBounds2 = new SeparatingAxisBounds();
|
|
const cachedAxis = new Vector3();
|
|
const dir = new Vector3();
|
|
const dir1 = new Vector3();
|
|
const dir2 = new Vector3();
|
|
const tempDir = new Vector3();
|
|
const edge = new Line3();
|
|
const edge1 = new Line3();
|
|
const edge2 = new Line3();
|
|
const tempPoint = new Vector3();
|
|
function triIntersectPlane(tri, plane, targetEdge) {
|
|
const points = tri.points;
|
|
let count = 0;
|
|
let startPointIntersection = -1;
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
const { start, end } = edge;
|
|
start.copy(points[i3]);
|
|
end.copy(points[(i3 + 1) % 3]);
|
|
edge.delta(dir);
|
|
const startIntersects = isNearZero(plane.distanceToPoint(start));
|
|
if (isNearZero(plane.normal.dot(dir)) && startIntersects) {
|
|
targetEdge.copy(edge);
|
|
count = 2;
|
|
break;
|
|
}
|
|
const doesIntersect = plane.intersectLine(edge, tempPoint);
|
|
if (!doesIntersect && startIntersects) {
|
|
tempPoint.copy(start);
|
|
}
|
|
if ((doesIntersect || startIntersects) && !isNearZero(tempPoint.distanceTo(end))) {
|
|
if (count <= 1) {
|
|
const point = count === 1 ? targetEdge.start : targetEdge.end;
|
|
point.copy(tempPoint);
|
|
if (startIntersects) {
|
|
startPointIntersection = count;
|
|
}
|
|
} else if (count >= 2) {
|
|
const point = startPointIntersection === 1 ? targetEdge.start : targetEdge.end;
|
|
point.copy(tempPoint);
|
|
count = 2;
|
|
break;
|
|
}
|
|
count++;
|
|
if (count === 2 && startPointIntersection === -1) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
return function intersectsTriangle(other, target2 = null, suppressLog = false) {
|
|
if (this.needsUpdate) {
|
|
this.update();
|
|
}
|
|
if (!other.isExtendedTriangle) {
|
|
saTri2.copy(other);
|
|
saTri2.update();
|
|
other = saTri2;
|
|
} else if (other.needsUpdate) {
|
|
other.update();
|
|
}
|
|
const plane1 = this.plane;
|
|
const plane2 = other.plane;
|
|
if (Math.abs(plane1.normal.dot(plane2.normal)) > 1 - 1e-10) {
|
|
const satBounds1 = this.satBounds;
|
|
const satAxes1 = this.satAxes;
|
|
arr2[0] = other.a;
|
|
arr2[1] = other.b;
|
|
arr2[2] = other.c;
|
|
for (let i3 = 0; i3 < 4; i3++) {
|
|
const sb = satBounds1[i3];
|
|
const sa = satAxes1[i3];
|
|
cachedSatBounds.setFromPoints(sa, arr2);
|
|
if (sb.isSeparated(cachedSatBounds)) return false;
|
|
}
|
|
const satBounds2 = other.satBounds;
|
|
const satAxes2 = other.satAxes;
|
|
arr1[0] = this.a;
|
|
arr1[1] = this.b;
|
|
arr1[2] = this.c;
|
|
for (let i3 = 0; i3 < 4; i3++) {
|
|
const sb = satBounds2[i3];
|
|
const sa = satAxes2[i3];
|
|
cachedSatBounds.setFromPoints(sa, arr1);
|
|
if (sb.isSeparated(cachedSatBounds)) return false;
|
|
}
|
|
for (let i3 = 0; i3 < 4; i3++) {
|
|
const sa1 = satAxes1[i3];
|
|
for (let i22 = 0; i22 < 4; i22++) {
|
|
const sa2 = satAxes2[i22];
|
|
cachedAxis.crossVectors(sa1, sa2);
|
|
cachedSatBounds.setFromPoints(cachedAxis, arr1);
|
|
cachedSatBounds2.setFromPoints(cachedAxis, arr2);
|
|
if (cachedSatBounds.isSeparated(cachedSatBounds2)) return false;
|
|
}
|
|
}
|
|
if (target2) {
|
|
if (!suppressLog) {
|
|
console.warn("ExtendedTriangle.intersectsTriangle: Triangles are coplanar which does not support an output edge. Setting edge to 0, 0, 0.");
|
|
}
|
|
target2.start.set(0, 0, 0);
|
|
target2.end.set(0, 0, 0);
|
|
}
|
|
return true;
|
|
} else {
|
|
const count1 = triIntersectPlane(this, plane2, edge1);
|
|
if (count1 === 1 && other.containsPoint(edge1.end)) {
|
|
if (target2) {
|
|
target2.start.copy(edge1.end);
|
|
target2.end.copy(edge1.end);
|
|
}
|
|
return true;
|
|
} else if (count1 !== 2) {
|
|
return false;
|
|
}
|
|
const count2 = triIntersectPlane(other, plane1, edge2);
|
|
if (count2 === 1 && this.containsPoint(edge2.end)) {
|
|
if (target2) {
|
|
target2.start.copy(edge2.end);
|
|
target2.end.copy(edge2.end);
|
|
}
|
|
return true;
|
|
} else if (count2 !== 2) {
|
|
return false;
|
|
}
|
|
edge1.delta(dir1);
|
|
edge2.delta(dir2);
|
|
if (dir1.dot(dir2) < 0) {
|
|
let tmp = edge2.start;
|
|
edge2.start = edge2.end;
|
|
edge2.end = tmp;
|
|
}
|
|
const s1 = edge1.start.dot(dir1);
|
|
const e1 = edge1.end.dot(dir1);
|
|
const s2 = edge2.start.dot(dir1);
|
|
const e2 = edge2.end.dot(dir1);
|
|
const separated1 = e1 < s2;
|
|
const separated2 = s1 < e2;
|
|
if (s1 !== e2 && s2 !== e1 && separated1 === separated2) {
|
|
return false;
|
|
}
|
|
if (target2) {
|
|
tempDir.subVectors(edge1.start, edge2.start);
|
|
if (tempDir.dot(dir1) > 0) {
|
|
target2.start.copy(edge1.start);
|
|
} else {
|
|
target2.start.copy(edge2.start);
|
|
}
|
|
tempDir.subVectors(edge1.end, edge2.end);
|
|
if (tempDir.dot(dir1) < 0) {
|
|
target2.end.copy(edge1.end);
|
|
} else {
|
|
target2.end.copy(edge2.end);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
})();
|
|
ExtendedTriangle.prototype.distanceToPoint = (function() {
|
|
const target2 = new Vector3();
|
|
return function distanceToPoint(point) {
|
|
this.closestPointToPoint(point, target2);
|
|
return point.distanceTo(target2);
|
|
};
|
|
})();
|
|
ExtendedTriangle.prototype.distanceToTriangle = (function() {
|
|
const point = new Vector3();
|
|
const point2 = new Vector3();
|
|
const cornerFields = ["a", "b", "c"];
|
|
const line1 = new Line3();
|
|
const line2 = new Line3();
|
|
return function distanceToTriangle(other, target1 = null, target2 = null) {
|
|
const lineTarget = target1 || target2 ? line1 : null;
|
|
if (this.intersectsTriangle(other, lineTarget)) {
|
|
if (target1 || target2) {
|
|
if (target1) lineTarget.getCenter(target1);
|
|
if (target2) lineTarget.getCenter(target2);
|
|
}
|
|
return 0;
|
|
}
|
|
let closestDistanceSq = Infinity;
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
let dist;
|
|
const field = cornerFields[i3];
|
|
const otherVec = other[field];
|
|
this.closestPointToPoint(otherVec, point);
|
|
dist = otherVec.distanceToSquared(point);
|
|
if (dist < closestDistanceSq) {
|
|
closestDistanceSq = dist;
|
|
if (target1) target1.copy(point);
|
|
if (target2) target2.copy(otherVec);
|
|
}
|
|
const thisVec = this[field];
|
|
other.closestPointToPoint(thisVec, point);
|
|
dist = thisVec.distanceToSquared(point);
|
|
if (dist < closestDistanceSq) {
|
|
closestDistanceSq = dist;
|
|
if (target1) target1.copy(thisVec);
|
|
if (target2) target2.copy(point);
|
|
}
|
|
}
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
const f11 = cornerFields[i3];
|
|
const f12 = cornerFields[(i3 + 1) % 3];
|
|
line1.set(this[f11], this[f12]);
|
|
for (let i22 = 0; i22 < 3; i22++) {
|
|
const f21 = cornerFields[i22];
|
|
const f22 = cornerFields[(i22 + 1) % 3];
|
|
line2.set(other[f21], other[f22]);
|
|
closestPointsSegmentToSegment(line1, line2, point, point2);
|
|
const dist = point.distanceToSquared(point2);
|
|
if (dist < closestDistanceSq) {
|
|
closestDistanceSq = dist;
|
|
if (target1) target1.copy(point);
|
|
if (target2) target2.copy(point2);
|
|
}
|
|
}
|
|
}
|
|
return Math.sqrt(closestDistanceSq);
|
|
};
|
|
})();
|
|
|
|
// node_modules/three-mesh-bvh/src/math/OrientedBox.js
|
|
var OrientedBox = class {
|
|
constructor(min, max, matrix4) {
|
|
this.isOrientedBox = true;
|
|
this.min = new Vector3();
|
|
this.max = new Vector3();
|
|
this.matrix = new Matrix4();
|
|
this.invMatrix = new Matrix4();
|
|
this.points = new Array(8).fill().map(() => new Vector3());
|
|
this.satAxes = new Array(3).fill().map(() => new Vector3());
|
|
this.satBounds = new Array(3).fill().map(() => new SeparatingAxisBounds());
|
|
this.alignedSatBounds = new Array(3).fill().map(() => new SeparatingAxisBounds());
|
|
this.needsUpdate = false;
|
|
if (min) this.min.copy(min);
|
|
if (max) this.max.copy(max);
|
|
if (matrix4) this.matrix.copy(matrix4);
|
|
}
|
|
set(min, max, matrix4) {
|
|
this.min.copy(min);
|
|
this.max.copy(max);
|
|
this.matrix.copy(matrix4);
|
|
this.needsUpdate = true;
|
|
}
|
|
copy(other) {
|
|
this.min.copy(other.min);
|
|
this.max.copy(other.max);
|
|
this.matrix.copy(other.matrix);
|
|
this.needsUpdate = true;
|
|
}
|
|
};
|
|
OrientedBox.prototype.update = /* @__PURE__ */ (function() {
|
|
return function update2() {
|
|
const matrix4 = this.matrix;
|
|
const min = this.min;
|
|
const max = this.max;
|
|
const points = this.points;
|
|
for (let x = 0; x <= 1; x++) {
|
|
for (let y = 0; y <= 1; y++) {
|
|
for (let z = 0; z <= 1; z++) {
|
|
const i3 = (1 << 0) * x | (1 << 1) * y | (1 << 2) * z;
|
|
const v5 = points[i3];
|
|
v5.x = x ? max.x : min.x;
|
|
v5.y = y ? max.y : min.y;
|
|
v5.z = z ? max.z : min.z;
|
|
v5.applyMatrix4(matrix4);
|
|
}
|
|
}
|
|
}
|
|
const satBounds = this.satBounds;
|
|
const satAxes = this.satAxes;
|
|
const minVec = points[0];
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
const axis = satAxes[i3];
|
|
const sb = satBounds[i3];
|
|
const index2 = 1 << i3;
|
|
const pi = points[index2];
|
|
axis.subVectors(minVec, pi);
|
|
sb.setFromPoints(axis, points);
|
|
}
|
|
const alignedSatBounds = this.alignedSatBounds;
|
|
alignedSatBounds[0].setFromPointsField(points, "x");
|
|
alignedSatBounds[1].setFromPointsField(points, "y");
|
|
alignedSatBounds[2].setFromPointsField(points, "z");
|
|
this.invMatrix.copy(this.matrix).invert();
|
|
this.needsUpdate = false;
|
|
};
|
|
})();
|
|
OrientedBox.prototype.intersectsBox = (function() {
|
|
const aabbBounds = new SeparatingAxisBounds();
|
|
return function intersectsBox(box) {
|
|
if (this.needsUpdate) {
|
|
this.update();
|
|
}
|
|
const min = box.min;
|
|
const max = box.max;
|
|
const satBounds = this.satBounds;
|
|
const satAxes = this.satAxes;
|
|
const alignedSatBounds = this.alignedSatBounds;
|
|
aabbBounds.min = min.x;
|
|
aabbBounds.max = max.x;
|
|
if (alignedSatBounds[0].isSeparated(aabbBounds)) return false;
|
|
aabbBounds.min = min.y;
|
|
aabbBounds.max = max.y;
|
|
if (alignedSatBounds[1].isSeparated(aabbBounds)) return false;
|
|
aabbBounds.min = min.z;
|
|
aabbBounds.max = max.z;
|
|
if (alignedSatBounds[2].isSeparated(aabbBounds)) return false;
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
const axis = satAxes[i3];
|
|
const sb = satBounds[i3];
|
|
aabbBounds.setFromBox(axis, box);
|
|
if (sb.isSeparated(aabbBounds)) return false;
|
|
}
|
|
return true;
|
|
};
|
|
})();
|
|
OrientedBox.prototype.intersectsTriangle = (function() {
|
|
const saTri = new ExtendedTriangle();
|
|
const pointsArr = new Array(3);
|
|
const cachedSatBounds = new SeparatingAxisBounds();
|
|
const cachedSatBounds2 = new SeparatingAxisBounds();
|
|
const cachedAxis = new Vector3();
|
|
return function intersectsTriangle(triangle4) {
|
|
if (this.needsUpdate) {
|
|
this.update();
|
|
}
|
|
if (!triangle4.isExtendedTriangle) {
|
|
saTri.copy(triangle4);
|
|
saTri.update();
|
|
triangle4 = saTri;
|
|
} else if (triangle4.needsUpdate) {
|
|
triangle4.update();
|
|
}
|
|
const satBounds = this.satBounds;
|
|
const satAxes = this.satAxes;
|
|
pointsArr[0] = triangle4.a;
|
|
pointsArr[1] = triangle4.b;
|
|
pointsArr[2] = triangle4.c;
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
const sb = satBounds[i3];
|
|
const sa = satAxes[i3];
|
|
cachedSatBounds.setFromPoints(sa, pointsArr);
|
|
if (sb.isSeparated(cachedSatBounds)) return false;
|
|
}
|
|
const triSatBounds = triangle4.satBounds;
|
|
const triSatAxes = triangle4.satAxes;
|
|
const points = this.points;
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
const sb = triSatBounds[i3];
|
|
const sa = triSatAxes[i3];
|
|
cachedSatBounds.setFromPoints(sa, points);
|
|
if (sb.isSeparated(cachedSatBounds)) return false;
|
|
}
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
const sa1 = satAxes[i3];
|
|
for (let i22 = 0; i22 < 4; i22++) {
|
|
const sa2 = triSatAxes[i22];
|
|
cachedAxis.crossVectors(sa1, sa2);
|
|
cachedSatBounds.setFromPoints(cachedAxis, pointsArr);
|
|
cachedSatBounds2.setFromPoints(cachedAxis, points);
|
|
if (cachedSatBounds.isSeparated(cachedSatBounds2)) return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
})();
|
|
OrientedBox.prototype.closestPointToPoint = /* @__PURE__ */ (function() {
|
|
return function closestPointToPoint2(point, target1) {
|
|
if (this.needsUpdate) {
|
|
this.update();
|
|
}
|
|
target1.copy(point).applyMatrix4(this.invMatrix).clamp(this.min, this.max).applyMatrix4(this.matrix);
|
|
return target1;
|
|
};
|
|
})();
|
|
OrientedBox.prototype.distanceToPoint = (function() {
|
|
const target2 = new Vector3();
|
|
return function distanceToPoint(point) {
|
|
this.closestPointToPoint(point, target2);
|
|
return point.distanceTo(target2);
|
|
};
|
|
})();
|
|
OrientedBox.prototype.distanceToBox = (function() {
|
|
const xyzFields = ["x", "y", "z"];
|
|
const segments1 = new Array(12).fill().map(() => new Line3());
|
|
const segments2 = new Array(12).fill().map(() => new Line3());
|
|
const point1 = new Vector3();
|
|
const point2 = new Vector3();
|
|
return function distanceToBox(box, threshold = 0, target1 = null, target2 = null) {
|
|
if (this.needsUpdate) {
|
|
this.update();
|
|
}
|
|
if (this.intersectsBox(box)) {
|
|
if (target1 || target2) {
|
|
box.getCenter(point2);
|
|
this.closestPointToPoint(point2, point1);
|
|
box.closestPointToPoint(point1, point2);
|
|
if (target1) target1.copy(point1);
|
|
if (target2) target2.copy(point2);
|
|
}
|
|
return 0;
|
|
}
|
|
const threshold2 = threshold * threshold;
|
|
const min = box.min;
|
|
const max = box.max;
|
|
const points = this.points;
|
|
let closestDistanceSq = Infinity;
|
|
for (let i3 = 0; i3 < 8; i3++) {
|
|
const p2 = points[i3];
|
|
point2.copy(p2).clamp(min, max);
|
|
const dist = p2.distanceToSquared(point2);
|
|
if (dist < closestDistanceSq) {
|
|
closestDistanceSq = dist;
|
|
if (target1) target1.copy(p2);
|
|
if (target2) target2.copy(point2);
|
|
if (dist < threshold2) return Math.sqrt(dist);
|
|
}
|
|
}
|
|
let count = 0;
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
for (let i1 = 0; i1 <= 1; i1++) {
|
|
for (let i22 = 0; i22 <= 1; i22++) {
|
|
const nextIndex = (i3 + 1) % 3;
|
|
const nextIndex2 = (i3 + 2) % 3;
|
|
const index2 = i1 << nextIndex | i22 << nextIndex2;
|
|
const index22 = 1 << i3 | i1 << nextIndex | i22 << nextIndex2;
|
|
const p1 = points[index2];
|
|
const p2 = points[index22];
|
|
const line1 = segments1[count];
|
|
line1.set(p1, p2);
|
|
const f1 = xyzFields[i3];
|
|
const f2 = xyzFields[nextIndex];
|
|
const f3 = xyzFields[nextIndex2];
|
|
const line2 = segments2[count];
|
|
const start = line2.start;
|
|
const end = line2.end;
|
|
start[f1] = min[f1];
|
|
start[f2] = i1 ? min[f2] : max[f2];
|
|
start[f3] = i22 ? min[f3] : max[f2];
|
|
end[f1] = max[f1];
|
|
end[f2] = i1 ? min[f2] : max[f2];
|
|
end[f3] = i22 ? min[f3] : max[f2];
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
for (let x = 0; x <= 1; x++) {
|
|
for (let y = 0; y <= 1; y++) {
|
|
for (let z = 0; z <= 1; z++) {
|
|
point2.x = x ? max.x : min.x;
|
|
point2.y = y ? max.y : min.y;
|
|
point2.z = z ? max.z : min.z;
|
|
this.closestPointToPoint(point2, point1);
|
|
const dist = point2.distanceToSquared(point1);
|
|
if (dist < closestDistanceSq) {
|
|
closestDistanceSq = dist;
|
|
if (target1) target1.copy(point1);
|
|
if (target2) target2.copy(point2);
|
|
if (dist < threshold2) return Math.sqrt(dist);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (let i3 = 0; i3 < 12; i3++) {
|
|
const l1 = segments1[i3];
|
|
for (let i22 = 0; i22 < 12; i22++) {
|
|
const l2 = segments2[i22];
|
|
closestPointsSegmentToSegment(l1, l2, point1, point2);
|
|
const dist = point1.distanceToSquared(point2);
|
|
if (dist < closestDistanceSq) {
|
|
closestDistanceSq = dist;
|
|
if (target1) target1.copy(point1);
|
|
if (target2) target2.copy(point2);
|
|
if (dist < threshold2) return Math.sqrt(dist);
|
|
}
|
|
}
|
|
}
|
|
return Math.sqrt(closestDistanceSq);
|
|
};
|
|
})();
|
|
|
|
// node_modules/three-mesh-bvh/src/utils/PrimitivePool.js
|
|
var PrimitivePool = class {
|
|
constructor(getNewPrimitive) {
|
|
this._getNewPrimitive = getNewPrimitive;
|
|
this._primitives = [];
|
|
}
|
|
getPrimitive() {
|
|
const primitives = this._primitives;
|
|
if (primitives.length === 0) {
|
|
return this._getNewPrimitive();
|
|
} else {
|
|
return primitives.pop();
|
|
}
|
|
}
|
|
releasePrimitive(primitive) {
|
|
this._primitives.push(primitive);
|
|
}
|
|
};
|
|
|
|
// node_modules/three-mesh-bvh/src/utils/ExtendedTrianglePool.js
|
|
var ExtendedTrianglePoolBase = class extends PrimitivePool {
|
|
constructor() {
|
|
super(() => new ExtendedTriangle());
|
|
}
|
|
};
|
|
var ExtendedTrianglePool = new ExtendedTrianglePoolBase();
|
|
|
|
// node_modules/three-mesh-bvh/src/core/utils/BufferStack.js
|
|
var _BufferStack = class {
|
|
constructor() {
|
|
this.float32Array = null;
|
|
this.uint16Array = null;
|
|
this.uint32Array = null;
|
|
const stack = [];
|
|
let prevBuffer = null;
|
|
this.setBuffer = (buffer2) => {
|
|
if (prevBuffer) {
|
|
stack.push(prevBuffer);
|
|
}
|
|
prevBuffer = buffer2;
|
|
this.float32Array = new Float32Array(buffer2);
|
|
this.uint16Array = new Uint16Array(buffer2);
|
|
this.uint32Array = new Uint32Array(buffer2);
|
|
};
|
|
this.clearBuffer = () => {
|
|
prevBuffer = null;
|
|
this.float32Array = null;
|
|
this.uint16Array = null;
|
|
this.uint32Array = null;
|
|
if (stack.length !== 0) {
|
|
this.setBuffer(stack.pop());
|
|
}
|
|
};
|
|
}
|
|
};
|
|
var BufferStack = new _BufferStack();
|
|
|
|
// node_modules/three-mesh-bvh/src/core/cast/shapecast.js
|
|
var _box1;
|
|
var _box2;
|
|
var boxStack = [];
|
|
var boxPool = new PrimitivePool(() => new Box3());
|
|
function shapecast(bvh, root, intersectsBounds, intersectsRange, boundsTraverseOrder, byteOffset) {
|
|
_box1 = boxPool.getPrimitive();
|
|
_box2 = boxPool.getPrimitive();
|
|
boxStack.push(_box1, _box2);
|
|
BufferStack.setBuffer(bvh._roots[root]);
|
|
const result = shapecastTraverse(0, bvh.geometry, intersectsBounds, intersectsRange, boundsTraverseOrder, byteOffset);
|
|
BufferStack.clearBuffer();
|
|
boxPool.releasePrimitive(_box1);
|
|
boxPool.releasePrimitive(_box2);
|
|
boxStack.pop();
|
|
boxStack.pop();
|
|
const length3 = boxStack.length;
|
|
if (length3 > 0) {
|
|
_box2 = boxStack[length3 - 1];
|
|
_box1 = boxStack[length3 - 2];
|
|
}
|
|
return result;
|
|
}
|
|
function shapecastTraverse(nodeIndex32, geometry3, intersectsBoundsFunc, intersectsRangeFunc, nodeScoreFunc = null, nodeIndexByteOffset = 0, depth = 0) {
|
|
const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
|
|
let nodeIndex16 = nodeIndex32 * 2;
|
|
const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
|
|
if (isLeaf) {
|
|
const offset = OFFSET(nodeIndex32, uint32Array2);
|
|
const count = COUNT(nodeIndex16, uint16Array2);
|
|
arrayToBox(BOUNDING_DATA_INDEX(nodeIndex32), float32Array2, _box1);
|
|
return intersectsRangeFunc(offset, count, false, depth, nodeIndexByteOffset + nodeIndex32, _box1);
|
|
} else {
|
|
let getLeftOffset = function(nodeIndex322) {
|
|
const { uint16Array: uint16Array3, uint32Array: uint32Array3 } = BufferStack;
|
|
let nodeIndex162 = nodeIndex322 * 2;
|
|
while (!IS_LEAF(nodeIndex162, uint16Array3)) {
|
|
nodeIndex322 = LEFT_NODE(nodeIndex322);
|
|
nodeIndex162 = nodeIndex322 * 2;
|
|
}
|
|
return OFFSET(nodeIndex322, uint32Array3);
|
|
}, getRightEndOffset = function(nodeIndex322) {
|
|
const { uint16Array: uint16Array3, uint32Array: uint32Array3 } = BufferStack;
|
|
let nodeIndex162 = nodeIndex322 * 2;
|
|
while (!IS_LEAF(nodeIndex162, uint16Array3)) {
|
|
nodeIndex322 = RIGHT_NODE(nodeIndex322, uint32Array3);
|
|
nodeIndex162 = nodeIndex322 * 2;
|
|
}
|
|
return OFFSET(nodeIndex322, uint32Array3) + COUNT(nodeIndex162, uint16Array3);
|
|
};
|
|
const left = LEFT_NODE(nodeIndex32);
|
|
const right = RIGHT_NODE(nodeIndex32, uint32Array2);
|
|
let c1 = left;
|
|
let c2 = right;
|
|
let score1, score2;
|
|
let box1, box2;
|
|
if (nodeScoreFunc) {
|
|
box1 = _box1;
|
|
box2 = _box2;
|
|
arrayToBox(BOUNDING_DATA_INDEX(c1), float32Array2, box1);
|
|
arrayToBox(BOUNDING_DATA_INDEX(c2), float32Array2, box2);
|
|
score1 = nodeScoreFunc(box1);
|
|
score2 = nodeScoreFunc(box2);
|
|
if (score2 < score1) {
|
|
c1 = right;
|
|
c2 = left;
|
|
const temp5 = score1;
|
|
score1 = score2;
|
|
score2 = temp5;
|
|
box1 = box2;
|
|
}
|
|
}
|
|
if (!box1) {
|
|
box1 = _box1;
|
|
arrayToBox(BOUNDING_DATA_INDEX(c1), float32Array2, box1);
|
|
}
|
|
const isC1Leaf = IS_LEAF(c1 * 2, uint16Array2);
|
|
const c1Intersection = intersectsBoundsFunc(box1, isC1Leaf, score1, depth + 1, nodeIndexByteOffset + c1);
|
|
let c1StopTraversal;
|
|
if (c1Intersection === CONTAINED) {
|
|
const offset = getLeftOffset(c1);
|
|
const end = getRightEndOffset(c1);
|
|
const count = end - offset;
|
|
c1StopTraversal = intersectsRangeFunc(offset, count, true, depth + 1, nodeIndexByteOffset + c1, box1);
|
|
} else {
|
|
c1StopTraversal = c1Intersection && shapecastTraverse(
|
|
c1,
|
|
geometry3,
|
|
intersectsBoundsFunc,
|
|
intersectsRangeFunc,
|
|
nodeScoreFunc,
|
|
nodeIndexByteOffset,
|
|
depth + 1
|
|
);
|
|
}
|
|
if (c1StopTraversal) return true;
|
|
box2 = _box2;
|
|
arrayToBox(BOUNDING_DATA_INDEX(c2), float32Array2, box2);
|
|
const isC2Leaf = IS_LEAF(c2 * 2, uint16Array2);
|
|
const c2Intersection = intersectsBoundsFunc(box2, isC2Leaf, score2, depth + 1, nodeIndexByteOffset + c2);
|
|
let c2StopTraversal;
|
|
if (c2Intersection === CONTAINED) {
|
|
const offset = getLeftOffset(c2);
|
|
const end = getRightEndOffset(c2);
|
|
const count = end - offset;
|
|
c2StopTraversal = intersectsRangeFunc(offset, count, true, depth + 1, nodeIndexByteOffset + c2, box2);
|
|
} else {
|
|
c2StopTraversal = c2Intersection && shapecastTraverse(
|
|
c2,
|
|
geometry3,
|
|
intersectsBoundsFunc,
|
|
intersectsRangeFunc,
|
|
nodeScoreFunc,
|
|
nodeIndexByteOffset,
|
|
depth + 1
|
|
);
|
|
}
|
|
if (c2StopTraversal) return true;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/cast/closestPointToPoint.js
|
|
var temp = new Vector3();
|
|
var temp1 = new Vector3();
|
|
function closestPointToPoint(bvh, point, target2 = {}, minThreshold = 0, maxThreshold = Infinity) {
|
|
const minThresholdSq = minThreshold * minThreshold;
|
|
const maxThresholdSq = maxThreshold * maxThreshold;
|
|
let closestDistanceSq = Infinity;
|
|
let closestDistanceTriIndex = null;
|
|
bvh.shapecast(
|
|
{
|
|
boundsTraverseOrder: (box) => {
|
|
temp.copy(point).clamp(box.min, box.max);
|
|
return temp.distanceToSquared(point);
|
|
},
|
|
intersectsBounds: (box, isLeaf, score) => {
|
|
return score < closestDistanceSq && score < maxThresholdSq;
|
|
},
|
|
intersectsTriangle: (tri, triIndex) => {
|
|
tri.closestPointToPoint(point, temp);
|
|
const distSq = point.distanceToSquared(temp);
|
|
if (distSq < closestDistanceSq) {
|
|
temp1.copy(temp);
|
|
closestDistanceSq = distSq;
|
|
closestDistanceTriIndex = triIndex;
|
|
}
|
|
if (distSq < minThresholdSq) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
);
|
|
if (closestDistanceSq === Infinity) return null;
|
|
const closestDistance = Math.sqrt(closestDistanceSq);
|
|
if (!target2.point) target2.point = temp1.clone();
|
|
else target2.point.copy(temp1);
|
|
target2.distance = closestDistance, target2.faceIndex = closestDistanceTriIndex;
|
|
return target2;
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/utils/ThreeRayIntersectUtilities.js
|
|
var IS_GT_REVISION_169 = parseInt(REVISION) >= 169;
|
|
var _vA = new Vector3();
|
|
var _vB = new Vector3();
|
|
var _vC = new Vector3();
|
|
var _uvA = new Vector2();
|
|
var _uvB = new Vector2();
|
|
var _uvC = new Vector2();
|
|
var _normalA = new Vector3();
|
|
var _normalB = new Vector3();
|
|
var _normalC = new Vector3();
|
|
var _intersectionPoint = new Vector3();
|
|
function checkIntersection(ray4, pA, pB, pC, point, side, near, far) {
|
|
let intersect;
|
|
if (side === BackSide) {
|
|
intersect = ray4.intersectTriangle(pC, pB, pA, true, point);
|
|
} else {
|
|
intersect = ray4.intersectTriangle(pA, pB, pC, side !== DoubleSide, point);
|
|
}
|
|
if (intersect === null) return null;
|
|
const distance3 = ray4.origin.distanceTo(point);
|
|
if (distance3 < near || distance3 > far) return null;
|
|
return {
|
|
distance: distance3,
|
|
point: point.clone()
|
|
};
|
|
}
|
|
function checkBufferGeometryIntersection(ray4, position2, normal2, uv, uv1, a5, b, c2, side, near, far) {
|
|
_vA.fromBufferAttribute(position2, a5);
|
|
_vB.fromBufferAttribute(position2, b);
|
|
_vC.fromBufferAttribute(position2, c2);
|
|
const intersection3 = checkIntersection(ray4, _vA, _vB, _vC, _intersectionPoint, side, near, far);
|
|
if (intersection3) {
|
|
const barycoord = new Vector3();
|
|
Triangle.getBarycoord(_intersectionPoint, _vA, _vB, _vC, barycoord);
|
|
if (uv) {
|
|
_uvA.fromBufferAttribute(uv, a5);
|
|
_uvB.fromBufferAttribute(uv, b);
|
|
_uvC.fromBufferAttribute(uv, c2);
|
|
intersection3.uv = Triangle.getInterpolation(_intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2());
|
|
}
|
|
if (uv1) {
|
|
_uvA.fromBufferAttribute(uv1, a5);
|
|
_uvB.fromBufferAttribute(uv1, b);
|
|
_uvC.fromBufferAttribute(uv1, c2);
|
|
intersection3.uv1 = Triangle.getInterpolation(_intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2());
|
|
}
|
|
if (normal2) {
|
|
_normalA.fromBufferAttribute(normal2, a5);
|
|
_normalB.fromBufferAttribute(normal2, b);
|
|
_normalC.fromBufferAttribute(normal2, c2);
|
|
intersection3.normal = Triangle.getInterpolation(_intersectionPoint, _vA, _vB, _vC, _normalA, _normalB, _normalC, new Vector3());
|
|
if (intersection3.normal.dot(ray4.direction) > 0) {
|
|
intersection3.normal.multiplyScalar(-1);
|
|
}
|
|
}
|
|
const face = {
|
|
a: a5,
|
|
b,
|
|
c: c2,
|
|
normal: new Vector3(),
|
|
materialIndex: 0
|
|
};
|
|
Triangle.getNormal(_vA, _vB, _vC, face.normal);
|
|
intersection3.face = face;
|
|
intersection3.faceIndex = a5;
|
|
if (IS_GT_REVISION_169) {
|
|
intersection3.barycoord = barycoord;
|
|
}
|
|
}
|
|
return intersection3;
|
|
}
|
|
function intersectTri(geo, side, ray4, tri, intersections, near, far) {
|
|
const triOffset = tri * 3;
|
|
let a5 = triOffset + 0;
|
|
let b = triOffset + 1;
|
|
let c2 = triOffset + 2;
|
|
const index2 = geo.index;
|
|
if (geo.index) {
|
|
a5 = index2.getX(a5);
|
|
b = index2.getX(b);
|
|
c2 = index2.getX(c2);
|
|
}
|
|
const { position: position2, normal: normal2, uv, uv1 } = geo.attributes;
|
|
const intersection3 = checkBufferGeometryIntersection(ray4, position2, normal2, uv, uv1, a5, b, c2, side, near, far);
|
|
if (intersection3) {
|
|
intersection3.faceIndex = tri;
|
|
if (intersections) intersections.push(intersection3);
|
|
return intersection3;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/utils/TriangleUtilities.js
|
|
function setTriangle(tri, i3, index2, pos) {
|
|
const ta = tri.a;
|
|
const tb = tri.b;
|
|
const tc = tri.c;
|
|
let i0 = i3;
|
|
let i1 = i3 + 1;
|
|
let i22 = i3 + 2;
|
|
if (index2) {
|
|
i0 = index2.getX(i0);
|
|
i1 = index2.getX(i1);
|
|
i22 = index2.getX(i22);
|
|
}
|
|
ta.x = pos.getX(i0);
|
|
ta.y = pos.getY(i0);
|
|
ta.z = pos.getZ(i0);
|
|
tb.x = pos.getX(i1);
|
|
tb.y = pos.getY(i1);
|
|
tb.z = pos.getZ(i1);
|
|
tc.x = pos.getX(i22);
|
|
tc.y = pos.getY(i22);
|
|
tc.z = pos.getZ(i22);
|
|
}
|
|
var tempV1 = new Vector3();
|
|
var tempV2 = new Vector3();
|
|
var tempV3 = new Vector3();
|
|
var tempUV1 = new Vector2();
|
|
var tempUV2 = new Vector2();
|
|
var tempUV3 = new Vector2();
|
|
|
|
// node_modules/three-mesh-bvh/src/core/utils/iterationUtils.generated.js
|
|
function intersectTris(bvh, side, ray4, offset, count, intersections, near, far) {
|
|
const { geometry: geometry3, _indirectBuffer } = bvh;
|
|
for (let i3 = offset, end = offset + count; i3 < end; i3++) {
|
|
intersectTri(geometry3, side, ray4, i3, intersections, near, far);
|
|
}
|
|
}
|
|
function intersectClosestTri(bvh, side, ray4, offset, count, near, far) {
|
|
const { geometry: geometry3, _indirectBuffer } = bvh;
|
|
let dist = Infinity;
|
|
let res = null;
|
|
for (let i3 = offset, end = offset + count; i3 < end; i3++) {
|
|
let intersection3;
|
|
intersection3 = intersectTri(geometry3, side, ray4, i3, null, near, far);
|
|
if (intersection3 && intersection3.distance < dist) {
|
|
res = intersection3;
|
|
dist = intersection3.distance;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
function iterateOverTriangles(offset, count, bvh, intersectsTriangleFunc, contained, depth, triangle4) {
|
|
const { geometry: geometry3 } = bvh;
|
|
const { index: index2 } = geometry3;
|
|
const pos = geometry3.attributes.position;
|
|
for (let i3 = offset, l2 = count + offset; i3 < l2; i3++) {
|
|
let tri;
|
|
tri = i3;
|
|
setTriangle(triangle4, tri * 3, index2, pos);
|
|
triangle4.needsUpdate = true;
|
|
if (intersectsTriangleFunc(triangle4, tri, contained, depth)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/cast/refit.generated.js
|
|
function refit(bvh, nodeIndices = null) {
|
|
if (nodeIndices && Array.isArray(nodeIndices)) {
|
|
nodeIndices = new Set(nodeIndices);
|
|
}
|
|
const geometry3 = bvh.geometry;
|
|
const indexArr = geometry3.index ? geometry3.index.array : null;
|
|
const posAttr = geometry3.attributes.position;
|
|
let buffer2, uint32Array2, uint16Array2, float32Array2;
|
|
let byteOffset = 0;
|
|
const roots = bvh._roots;
|
|
for (let i3 = 0, l2 = roots.length; i3 < l2; i3++) {
|
|
buffer2 = roots[i3];
|
|
uint32Array2 = new Uint32Array(buffer2);
|
|
uint16Array2 = new Uint16Array(buffer2);
|
|
float32Array2 = new Float32Array(buffer2);
|
|
_traverse2(0, byteOffset);
|
|
byteOffset += buffer2.byteLength;
|
|
}
|
|
function _traverse2(node32Index, byteOffset2, force = false) {
|
|
const node16Index = node32Index * 2;
|
|
const isLeaf = uint16Array2[node16Index + 15] === IS_LEAFNODE_FLAG;
|
|
if (isLeaf) {
|
|
const offset = uint32Array2[node32Index + 6];
|
|
const count = uint16Array2[node16Index + 14];
|
|
let minx = Infinity;
|
|
let miny = Infinity;
|
|
let minz = Infinity;
|
|
let maxx = -Infinity;
|
|
let maxy = -Infinity;
|
|
let maxz = -Infinity;
|
|
for (let i3 = 3 * offset, l2 = 3 * (offset + count); i3 < l2; i3++) {
|
|
let index2 = indexArr[i3];
|
|
const x = posAttr.getX(index2);
|
|
const y = posAttr.getY(index2);
|
|
const z = posAttr.getZ(index2);
|
|
if (x < minx) minx = x;
|
|
if (x > maxx) maxx = x;
|
|
if (y < miny) miny = y;
|
|
if (y > maxy) maxy = y;
|
|
if (z < minz) minz = z;
|
|
if (z > maxz) maxz = z;
|
|
}
|
|
if (float32Array2[node32Index + 0] !== minx || float32Array2[node32Index + 1] !== miny || float32Array2[node32Index + 2] !== minz || float32Array2[node32Index + 3] !== maxx || float32Array2[node32Index + 4] !== maxy || float32Array2[node32Index + 5] !== maxz) {
|
|
float32Array2[node32Index + 0] = minx;
|
|
float32Array2[node32Index + 1] = miny;
|
|
float32Array2[node32Index + 2] = minz;
|
|
float32Array2[node32Index + 3] = maxx;
|
|
float32Array2[node32Index + 4] = maxy;
|
|
float32Array2[node32Index + 5] = maxz;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
const left = node32Index + 8;
|
|
const right = uint32Array2[node32Index + 6];
|
|
const offsetLeft = left + byteOffset2;
|
|
const offsetRight = right + byteOffset2;
|
|
let forceChildren = force;
|
|
let includesLeft = false;
|
|
let includesRight = false;
|
|
if (nodeIndices) {
|
|
if (!forceChildren) {
|
|
includesLeft = nodeIndices.has(offsetLeft);
|
|
includesRight = nodeIndices.has(offsetRight);
|
|
forceChildren = !includesLeft && !includesRight;
|
|
}
|
|
} else {
|
|
includesLeft = true;
|
|
includesRight = true;
|
|
}
|
|
const traverseLeft = forceChildren || includesLeft;
|
|
const traverseRight = forceChildren || includesRight;
|
|
let leftChange = false;
|
|
if (traverseLeft) {
|
|
leftChange = _traverse2(left, byteOffset2, forceChildren);
|
|
}
|
|
let rightChange = false;
|
|
if (traverseRight) {
|
|
rightChange = _traverse2(right, byteOffset2, forceChildren);
|
|
}
|
|
const didChange = leftChange || rightChange;
|
|
if (didChange) {
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
const lefti = left + i3;
|
|
const righti = right + i3;
|
|
const minLeftValue = float32Array2[lefti];
|
|
const maxLeftValue = float32Array2[lefti + 3];
|
|
const minRightValue = float32Array2[righti];
|
|
const maxRightValue = float32Array2[righti + 3];
|
|
float32Array2[node32Index + i3] = minLeftValue < minRightValue ? minLeftValue : minRightValue;
|
|
float32Array2[node32Index + i3 + 3] = maxLeftValue > maxRightValue ? maxLeftValue : maxRightValue;
|
|
}
|
|
}
|
|
return didChange;
|
|
}
|
|
}
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/utils/intersectUtils.js
|
|
function intersectRay(nodeIndex32, array, ray4, near, far) {
|
|
let tmin, tmax, tymin, tymax, tzmin, tzmax;
|
|
const invdirx = 1 / ray4.direction.x, invdiry = 1 / ray4.direction.y, invdirz = 1 / ray4.direction.z;
|
|
const ox = ray4.origin.x;
|
|
const oy = ray4.origin.y;
|
|
const oz = ray4.origin.z;
|
|
let minx = array[nodeIndex32];
|
|
let maxx = array[nodeIndex32 + 3];
|
|
let miny = array[nodeIndex32 + 1];
|
|
let maxy = array[nodeIndex32 + 3 + 1];
|
|
let minz = array[nodeIndex32 + 2];
|
|
let maxz = array[nodeIndex32 + 3 + 2];
|
|
if (invdirx >= 0) {
|
|
tmin = (minx - ox) * invdirx;
|
|
tmax = (maxx - ox) * invdirx;
|
|
} else {
|
|
tmin = (maxx - ox) * invdirx;
|
|
tmax = (minx - ox) * invdirx;
|
|
}
|
|
if (invdiry >= 0) {
|
|
tymin = (miny - oy) * invdiry;
|
|
tymax = (maxy - oy) * invdiry;
|
|
} else {
|
|
tymin = (maxy - oy) * invdiry;
|
|
tymax = (miny - oy) * invdiry;
|
|
}
|
|
if (tmin > tymax || tymin > tmax) return false;
|
|
if (tymin > tmin || isNaN(tmin)) tmin = tymin;
|
|
if (tymax < tmax || isNaN(tmax)) tmax = tymax;
|
|
if (invdirz >= 0) {
|
|
tzmin = (minz - oz) * invdirz;
|
|
tzmax = (maxz - oz) * invdirz;
|
|
} else {
|
|
tzmin = (maxz - oz) * invdirz;
|
|
tzmax = (minz - oz) * invdirz;
|
|
}
|
|
if (tmin > tzmax || tzmin > tmax) return false;
|
|
if (tzmin > tmin || tmin !== tmin) tmin = tzmin;
|
|
if (tzmax < tmax || tmax !== tmax) tmax = tzmax;
|
|
return tmin <= far && tmax >= near;
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/utils/iterationUtils_indirect.generated.js
|
|
function intersectTris_indirect(bvh, side, ray4, offset, count, intersections, near, far) {
|
|
const { geometry: geometry3, _indirectBuffer } = bvh;
|
|
for (let i3 = offset, end = offset + count; i3 < end; i3++) {
|
|
let vi = _indirectBuffer ? _indirectBuffer[i3] : i3;
|
|
intersectTri(geometry3, side, ray4, vi, intersections, near, far);
|
|
}
|
|
}
|
|
function intersectClosestTri_indirect(bvh, side, ray4, offset, count, near, far) {
|
|
const { geometry: geometry3, _indirectBuffer } = bvh;
|
|
let dist = Infinity;
|
|
let res = null;
|
|
for (let i3 = offset, end = offset + count; i3 < end; i3++) {
|
|
let intersection3;
|
|
intersection3 = intersectTri(geometry3, side, ray4, _indirectBuffer ? _indirectBuffer[i3] : i3, null, near, far);
|
|
if (intersection3 && intersection3.distance < dist) {
|
|
res = intersection3;
|
|
dist = intersection3.distance;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
function iterateOverTriangles_indirect(offset, count, bvh, intersectsTriangleFunc, contained, depth, triangle4) {
|
|
const { geometry: geometry3 } = bvh;
|
|
const { index: index2 } = geometry3;
|
|
const pos = geometry3.attributes.position;
|
|
for (let i3 = offset, l2 = count + offset; i3 < l2; i3++) {
|
|
let tri;
|
|
tri = bvh.resolveTriangleIndex(i3);
|
|
setTriangle(triangle4, tri * 3, index2, pos);
|
|
triangle4.needsUpdate = true;
|
|
if (intersectsTriangleFunc(triangle4, tri, contained, depth)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/cast/raycast.generated.js
|
|
function raycast(bvh, root, side, ray4, intersects, near, far) {
|
|
BufferStack.setBuffer(bvh._roots[root]);
|
|
_raycast(0, bvh, side, ray4, intersects, near, far);
|
|
BufferStack.clearBuffer();
|
|
}
|
|
function _raycast(nodeIndex32, bvh, side, ray4, intersects, near, far) {
|
|
const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
|
|
const nodeIndex16 = nodeIndex32 * 2;
|
|
const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
|
|
if (isLeaf) {
|
|
const offset = OFFSET(nodeIndex32, uint32Array2);
|
|
const count = COUNT(nodeIndex16, uint16Array2);
|
|
intersectTris(bvh, side, ray4, offset, count, intersects, near, far);
|
|
} else {
|
|
const leftIndex = LEFT_NODE(nodeIndex32);
|
|
if (intersectRay(leftIndex, float32Array2, ray4, near, far)) {
|
|
_raycast(leftIndex, bvh, side, ray4, intersects, near, far);
|
|
}
|
|
const rightIndex = RIGHT_NODE(nodeIndex32, uint32Array2);
|
|
if (intersectRay(rightIndex, float32Array2, ray4, near, far)) {
|
|
_raycast(rightIndex, bvh, side, ray4, intersects, near, far);
|
|
}
|
|
}
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/cast/raycastFirst.generated.js
|
|
var _xyzFields = ["x", "y", "z"];
|
|
function raycastFirst(bvh, root, side, ray4, near, far) {
|
|
BufferStack.setBuffer(bvh._roots[root]);
|
|
const result = _raycastFirst(0, bvh, side, ray4, near, far);
|
|
BufferStack.clearBuffer();
|
|
return result;
|
|
}
|
|
function _raycastFirst(nodeIndex32, bvh, side, ray4, near, far) {
|
|
const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
|
|
let nodeIndex16 = nodeIndex32 * 2;
|
|
const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
|
|
if (isLeaf) {
|
|
const offset = OFFSET(nodeIndex32, uint32Array2);
|
|
const count = COUNT(nodeIndex16, uint16Array2);
|
|
return intersectClosestTri(bvh, side, ray4, offset, count, near, far);
|
|
} else {
|
|
const splitAxis = SPLIT_AXIS(nodeIndex32, uint32Array2);
|
|
const xyzAxis = _xyzFields[splitAxis];
|
|
const rayDir = ray4.direction[xyzAxis];
|
|
const leftToRight = rayDir >= 0;
|
|
let c1, c2;
|
|
if (leftToRight) {
|
|
c1 = LEFT_NODE(nodeIndex32);
|
|
c2 = RIGHT_NODE(nodeIndex32, uint32Array2);
|
|
} else {
|
|
c1 = RIGHT_NODE(nodeIndex32, uint32Array2);
|
|
c2 = LEFT_NODE(nodeIndex32);
|
|
}
|
|
const c1Intersection = intersectRay(c1, float32Array2, ray4, near, far);
|
|
const c1Result = c1Intersection ? _raycastFirst(c1, bvh, side, ray4, near, far) : null;
|
|
if (c1Result) {
|
|
const point = c1Result.point[xyzAxis];
|
|
const isOutside = leftToRight ? point <= float32Array2[c2 + splitAxis] : (
|
|
// min bounding data
|
|
point >= float32Array2[c2 + splitAxis + 3]
|
|
);
|
|
if (isOutside) {
|
|
return c1Result;
|
|
}
|
|
}
|
|
const c2Intersection = intersectRay(c2, float32Array2, ray4, near, far);
|
|
const c2Result = c2Intersection ? _raycastFirst(c2, bvh, side, ray4, near, far) : null;
|
|
if (c1Result && c2Result) {
|
|
return c1Result.distance <= c2Result.distance ? c1Result : c2Result;
|
|
} else {
|
|
return c1Result || c2Result || null;
|
|
}
|
|
}
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/cast/intersectsGeometry.generated.js
|
|
var boundingBox = new Box3();
|
|
var triangle2 = new ExtendedTriangle();
|
|
var triangle22 = new ExtendedTriangle();
|
|
var invertedMat = new Matrix4();
|
|
var obb = new OrientedBox();
|
|
var obb2 = new OrientedBox();
|
|
function intersectsGeometry(bvh, root, otherGeometry, geometryToBvh) {
|
|
BufferStack.setBuffer(bvh._roots[root]);
|
|
const result = _intersectsGeometry(0, bvh, otherGeometry, geometryToBvh);
|
|
BufferStack.clearBuffer();
|
|
return result;
|
|
}
|
|
function _intersectsGeometry(nodeIndex32, bvh, otherGeometry, geometryToBvh, cachedObb = null) {
|
|
const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
|
|
let nodeIndex16 = nodeIndex32 * 2;
|
|
if (cachedObb === null) {
|
|
if (!otherGeometry.boundingBox) {
|
|
otherGeometry.computeBoundingBox();
|
|
}
|
|
obb.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
|
|
cachedObb = obb;
|
|
}
|
|
const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
|
|
if (isLeaf) {
|
|
const thisGeometry = bvh.geometry;
|
|
const thisIndex = thisGeometry.index;
|
|
const thisPos = thisGeometry.attributes.position;
|
|
const index2 = otherGeometry.index;
|
|
const pos = otherGeometry.attributes.position;
|
|
const offset = OFFSET(nodeIndex32, uint32Array2);
|
|
const count = COUNT(nodeIndex16, uint16Array2);
|
|
invertedMat.copy(geometryToBvh).invert();
|
|
if (otherGeometry.boundsTree) {
|
|
arrayToBox(BOUNDING_DATA_INDEX(nodeIndex32), float32Array2, obb2);
|
|
obb2.matrix.copy(invertedMat);
|
|
obb2.needsUpdate = true;
|
|
const res = otherGeometry.boundsTree.shapecast({
|
|
intersectsBounds: (box) => obb2.intersectsBox(box),
|
|
intersectsTriangle: (tri) => {
|
|
tri.a.applyMatrix4(geometryToBvh);
|
|
tri.b.applyMatrix4(geometryToBvh);
|
|
tri.c.applyMatrix4(geometryToBvh);
|
|
tri.needsUpdate = true;
|
|
for (let i3 = offset * 3, l2 = (count + offset) * 3; i3 < l2; i3 += 3) {
|
|
setTriangle(triangle22, i3, thisIndex, thisPos);
|
|
triangle22.needsUpdate = true;
|
|
if (tri.intersectsTriangle(triangle22)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
return res;
|
|
} else {
|
|
for (let i3 = offset * 3, l2 = (count + offset) * 3; i3 < l2; i3 += 3) {
|
|
setTriangle(triangle2, i3, thisIndex, thisPos);
|
|
triangle2.a.applyMatrix4(invertedMat);
|
|
triangle2.b.applyMatrix4(invertedMat);
|
|
triangle2.c.applyMatrix4(invertedMat);
|
|
triangle2.needsUpdate = true;
|
|
for (let i22 = 0, l22 = index2.count; i22 < l22; i22 += 3) {
|
|
setTriangle(triangle22, i22, index2, pos);
|
|
triangle22.needsUpdate = true;
|
|
if (triangle2.intersectsTriangle(triangle22)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
const left = nodeIndex32 + 8;
|
|
const right = uint32Array2[nodeIndex32 + 6];
|
|
arrayToBox(BOUNDING_DATA_INDEX(left), float32Array2, boundingBox);
|
|
const leftIntersection = cachedObb.intersectsBox(boundingBox) && _intersectsGeometry(left, bvh, otherGeometry, geometryToBvh, cachedObb);
|
|
if (leftIntersection) return true;
|
|
arrayToBox(BOUNDING_DATA_INDEX(right), float32Array2, boundingBox);
|
|
const rightIntersection = cachedObb.intersectsBox(boundingBox) && _intersectsGeometry(right, bvh, otherGeometry, geometryToBvh, cachedObb);
|
|
if (rightIntersection) return true;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/cast/closestPointToGeometry.generated.js
|
|
var tempMatrix = new Matrix4();
|
|
var obb3 = new OrientedBox();
|
|
var obb22 = new OrientedBox();
|
|
var temp12 = new Vector3();
|
|
var temp2 = new Vector3();
|
|
var temp3 = new Vector3();
|
|
var temp4 = new Vector3();
|
|
function closestPointToGeometry(bvh, otherGeometry, geometryToBvh, target1 = {}, target2 = {}, minThreshold = 0, maxThreshold = Infinity) {
|
|
if (!otherGeometry.boundingBox) {
|
|
otherGeometry.computeBoundingBox();
|
|
}
|
|
obb3.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
|
|
obb3.needsUpdate = true;
|
|
const geometry3 = bvh.geometry;
|
|
const pos = geometry3.attributes.position;
|
|
const index2 = geometry3.index;
|
|
const otherPos = otherGeometry.attributes.position;
|
|
const otherIndex = otherGeometry.index;
|
|
const triangle4 = ExtendedTrianglePool.getPrimitive();
|
|
const triangle24 = ExtendedTrianglePool.getPrimitive();
|
|
let tempTarget1 = temp12;
|
|
let tempTargetDest1 = temp2;
|
|
let tempTarget2 = null;
|
|
let tempTargetDest2 = null;
|
|
if (target2) {
|
|
tempTarget2 = temp3;
|
|
tempTargetDest2 = temp4;
|
|
}
|
|
let closestDistance = Infinity;
|
|
let closestDistanceTriIndex = null;
|
|
let closestDistanceOtherTriIndex = null;
|
|
tempMatrix.copy(geometryToBvh).invert();
|
|
obb22.matrix.copy(tempMatrix);
|
|
bvh.shapecast(
|
|
{
|
|
boundsTraverseOrder: (box) => {
|
|
return obb3.distanceToBox(box);
|
|
},
|
|
intersectsBounds: (box, isLeaf, score) => {
|
|
if (score < closestDistance && score < maxThreshold) {
|
|
if (isLeaf) {
|
|
obb22.min.copy(box.min);
|
|
obb22.max.copy(box.max);
|
|
obb22.needsUpdate = true;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
intersectsRange: (offset, count) => {
|
|
if (otherGeometry.boundsTree) {
|
|
const otherBvh = otherGeometry.boundsTree;
|
|
return otherBvh.shapecast({
|
|
boundsTraverseOrder: (box) => {
|
|
return obb22.distanceToBox(box);
|
|
},
|
|
intersectsBounds: (box, isLeaf, score) => {
|
|
return score < closestDistance && score < maxThreshold;
|
|
},
|
|
intersectsRange: (otherOffset, otherCount) => {
|
|
for (let i22 = otherOffset, l2 = otherOffset + otherCount; i22 < l2; i22++) {
|
|
setTriangle(triangle24, 3 * i22, otherIndex, otherPos);
|
|
triangle24.a.applyMatrix4(geometryToBvh);
|
|
triangle24.b.applyMatrix4(geometryToBvh);
|
|
triangle24.c.applyMatrix4(geometryToBvh);
|
|
triangle24.needsUpdate = true;
|
|
for (let i3 = offset, l3 = offset + count; i3 < l3; i3++) {
|
|
setTriangle(triangle4, 3 * i3, index2, pos);
|
|
triangle4.needsUpdate = true;
|
|
const dist = triangle4.distanceToTriangle(triangle24, tempTarget1, tempTarget2);
|
|
if (dist < closestDistance) {
|
|
tempTargetDest1.copy(tempTarget1);
|
|
if (tempTargetDest2) {
|
|
tempTargetDest2.copy(tempTarget2);
|
|
}
|
|
closestDistance = dist;
|
|
closestDistanceTriIndex = i3;
|
|
closestDistanceOtherTriIndex = i22;
|
|
}
|
|
if (dist < minThreshold) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
const triCount = getTriCount(otherGeometry);
|
|
for (let i22 = 0, l2 = triCount; i22 < l2; i22++) {
|
|
setTriangle(triangle24, 3 * i22, otherIndex, otherPos);
|
|
triangle24.a.applyMatrix4(geometryToBvh);
|
|
triangle24.b.applyMatrix4(geometryToBvh);
|
|
triangle24.c.applyMatrix4(geometryToBvh);
|
|
triangle24.needsUpdate = true;
|
|
for (let i3 = offset, l3 = offset + count; i3 < l3; i3++) {
|
|
setTriangle(triangle4, 3 * i3, index2, pos);
|
|
triangle4.needsUpdate = true;
|
|
const dist = triangle4.distanceToTriangle(triangle24, tempTarget1, tempTarget2);
|
|
if (dist < closestDistance) {
|
|
tempTargetDest1.copy(tempTarget1);
|
|
if (tempTargetDest2) {
|
|
tempTargetDest2.copy(tempTarget2);
|
|
}
|
|
closestDistance = dist;
|
|
closestDistanceTriIndex = i3;
|
|
closestDistanceOtherTriIndex = i22;
|
|
}
|
|
if (dist < minThreshold) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
);
|
|
ExtendedTrianglePool.releasePrimitive(triangle4);
|
|
ExtendedTrianglePool.releasePrimitive(triangle24);
|
|
if (closestDistance === Infinity) {
|
|
return null;
|
|
}
|
|
if (!target1.point) {
|
|
target1.point = tempTargetDest1.clone();
|
|
} else {
|
|
target1.point.copy(tempTargetDest1);
|
|
}
|
|
target1.distance = closestDistance, target1.faceIndex = closestDistanceTriIndex;
|
|
if (target2) {
|
|
if (!target2.point) target2.point = tempTargetDest2.clone();
|
|
else target2.point.copy(tempTargetDest2);
|
|
target2.point.applyMatrix4(tempMatrix);
|
|
tempTargetDest1.applyMatrix4(tempMatrix);
|
|
target2.distance = tempTargetDest1.sub(target2.point).length();
|
|
target2.faceIndex = closestDistanceOtherTriIndex;
|
|
}
|
|
return target1;
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/cast/refit_indirect.generated.js
|
|
function refit_indirect(bvh, nodeIndices = null) {
|
|
if (nodeIndices && Array.isArray(nodeIndices)) {
|
|
nodeIndices = new Set(nodeIndices);
|
|
}
|
|
const geometry3 = bvh.geometry;
|
|
const indexArr = geometry3.index ? geometry3.index.array : null;
|
|
const posAttr = geometry3.attributes.position;
|
|
let buffer2, uint32Array2, uint16Array2, float32Array2;
|
|
let byteOffset = 0;
|
|
const roots = bvh._roots;
|
|
for (let i3 = 0, l2 = roots.length; i3 < l2; i3++) {
|
|
buffer2 = roots[i3];
|
|
uint32Array2 = new Uint32Array(buffer2);
|
|
uint16Array2 = new Uint16Array(buffer2);
|
|
float32Array2 = new Float32Array(buffer2);
|
|
_traverse2(0, byteOffset);
|
|
byteOffset += buffer2.byteLength;
|
|
}
|
|
function _traverse2(node32Index, byteOffset2, force = false) {
|
|
const node16Index = node32Index * 2;
|
|
const isLeaf = uint16Array2[node16Index + 15] === IS_LEAFNODE_FLAG;
|
|
if (isLeaf) {
|
|
const offset = uint32Array2[node32Index + 6];
|
|
const count = uint16Array2[node16Index + 14];
|
|
let minx = Infinity;
|
|
let miny = Infinity;
|
|
let minz = Infinity;
|
|
let maxx = -Infinity;
|
|
let maxy = -Infinity;
|
|
let maxz = -Infinity;
|
|
for (let i3 = offset, l2 = offset + count; i3 < l2; i3++) {
|
|
const t2 = 3 * bvh.resolveTriangleIndex(i3);
|
|
for (let j = 0; j < 3; j++) {
|
|
let index2 = t2 + j;
|
|
index2 = indexArr ? indexArr[index2] : index2;
|
|
const x = posAttr.getX(index2);
|
|
const y = posAttr.getY(index2);
|
|
const z = posAttr.getZ(index2);
|
|
if (x < minx) minx = x;
|
|
if (x > maxx) maxx = x;
|
|
if (y < miny) miny = y;
|
|
if (y > maxy) maxy = y;
|
|
if (z < minz) minz = z;
|
|
if (z > maxz) maxz = z;
|
|
}
|
|
}
|
|
if (float32Array2[node32Index + 0] !== minx || float32Array2[node32Index + 1] !== miny || float32Array2[node32Index + 2] !== minz || float32Array2[node32Index + 3] !== maxx || float32Array2[node32Index + 4] !== maxy || float32Array2[node32Index + 5] !== maxz) {
|
|
float32Array2[node32Index + 0] = minx;
|
|
float32Array2[node32Index + 1] = miny;
|
|
float32Array2[node32Index + 2] = minz;
|
|
float32Array2[node32Index + 3] = maxx;
|
|
float32Array2[node32Index + 4] = maxy;
|
|
float32Array2[node32Index + 5] = maxz;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
const left = node32Index + 8;
|
|
const right = uint32Array2[node32Index + 6];
|
|
const offsetLeft = left + byteOffset2;
|
|
const offsetRight = right + byteOffset2;
|
|
let forceChildren = force;
|
|
let includesLeft = false;
|
|
let includesRight = false;
|
|
if (nodeIndices) {
|
|
if (!forceChildren) {
|
|
includesLeft = nodeIndices.has(offsetLeft);
|
|
includesRight = nodeIndices.has(offsetRight);
|
|
forceChildren = !includesLeft && !includesRight;
|
|
}
|
|
} else {
|
|
includesLeft = true;
|
|
includesRight = true;
|
|
}
|
|
const traverseLeft = forceChildren || includesLeft;
|
|
const traverseRight = forceChildren || includesRight;
|
|
let leftChange = false;
|
|
if (traverseLeft) {
|
|
leftChange = _traverse2(left, byteOffset2, forceChildren);
|
|
}
|
|
let rightChange = false;
|
|
if (traverseRight) {
|
|
rightChange = _traverse2(right, byteOffset2, forceChildren);
|
|
}
|
|
const didChange = leftChange || rightChange;
|
|
if (didChange) {
|
|
for (let i3 = 0; i3 < 3; i3++) {
|
|
const lefti = left + i3;
|
|
const righti = right + i3;
|
|
const minLeftValue = float32Array2[lefti];
|
|
const maxLeftValue = float32Array2[lefti + 3];
|
|
const minRightValue = float32Array2[righti];
|
|
const maxRightValue = float32Array2[righti + 3];
|
|
float32Array2[node32Index + i3] = minLeftValue < minRightValue ? minLeftValue : minRightValue;
|
|
float32Array2[node32Index + i3 + 3] = maxLeftValue > maxRightValue ? maxLeftValue : maxRightValue;
|
|
}
|
|
}
|
|
return didChange;
|
|
}
|
|
}
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/cast/raycast_indirect.generated.js
|
|
function raycast_indirect(bvh, root, side, ray4, intersects, near, far) {
|
|
BufferStack.setBuffer(bvh._roots[root]);
|
|
_raycast2(0, bvh, side, ray4, intersects, near, far);
|
|
BufferStack.clearBuffer();
|
|
}
|
|
function _raycast2(nodeIndex32, bvh, side, ray4, intersects, near, far) {
|
|
const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
|
|
const nodeIndex16 = nodeIndex32 * 2;
|
|
const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
|
|
if (isLeaf) {
|
|
const offset = OFFSET(nodeIndex32, uint32Array2);
|
|
const count = COUNT(nodeIndex16, uint16Array2);
|
|
intersectTris_indirect(bvh, side, ray4, offset, count, intersects, near, far);
|
|
} else {
|
|
const leftIndex = LEFT_NODE(nodeIndex32);
|
|
if (intersectRay(leftIndex, float32Array2, ray4, near, far)) {
|
|
_raycast2(leftIndex, bvh, side, ray4, intersects, near, far);
|
|
}
|
|
const rightIndex = RIGHT_NODE(nodeIndex32, uint32Array2);
|
|
if (intersectRay(rightIndex, float32Array2, ray4, near, far)) {
|
|
_raycast2(rightIndex, bvh, side, ray4, intersects, near, far);
|
|
}
|
|
}
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/cast/raycastFirst_indirect.generated.js
|
|
var _xyzFields2 = ["x", "y", "z"];
|
|
function raycastFirst_indirect(bvh, root, side, ray4, near, far) {
|
|
BufferStack.setBuffer(bvh._roots[root]);
|
|
const result = _raycastFirst2(0, bvh, side, ray4, near, far);
|
|
BufferStack.clearBuffer();
|
|
return result;
|
|
}
|
|
function _raycastFirst2(nodeIndex32, bvh, side, ray4, near, far) {
|
|
const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
|
|
let nodeIndex16 = nodeIndex32 * 2;
|
|
const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
|
|
if (isLeaf) {
|
|
const offset = OFFSET(nodeIndex32, uint32Array2);
|
|
const count = COUNT(nodeIndex16, uint16Array2);
|
|
return intersectClosestTri_indirect(bvh, side, ray4, offset, count, near, far);
|
|
} else {
|
|
const splitAxis = SPLIT_AXIS(nodeIndex32, uint32Array2);
|
|
const xyzAxis = _xyzFields2[splitAxis];
|
|
const rayDir = ray4.direction[xyzAxis];
|
|
const leftToRight = rayDir >= 0;
|
|
let c1, c2;
|
|
if (leftToRight) {
|
|
c1 = LEFT_NODE(nodeIndex32);
|
|
c2 = RIGHT_NODE(nodeIndex32, uint32Array2);
|
|
} else {
|
|
c1 = RIGHT_NODE(nodeIndex32, uint32Array2);
|
|
c2 = LEFT_NODE(nodeIndex32);
|
|
}
|
|
const c1Intersection = intersectRay(c1, float32Array2, ray4, near, far);
|
|
const c1Result = c1Intersection ? _raycastFirst2(c1, bvh, side, ray4, near, far) : null;
|
|
if (c1Result) {
|
|
const point = c1Result.point[xyzAxis];
|
|
const isOutside = leftToRight ? point <= float32Array2[c2 + splitAxis] : (
|
|
// min bounding data
|
|
point >= float32Array2[c2 + splitAxis + 3]
|
|
);
|
|
if (isOutside) {
|
|
return c1Result;
|
|
}
|
|
}
|
|
const c2Intersection = intersectRay(c2, float32Array2, ray4, near, far);
|
|
const c2Result = c2Intersection ? _raycastFirst2(c2, bvh, side, ray4, near, far) : null;
|
|
if (c1Result && c2Result) {
|
|
return c1Result.distance <= c2Result.distance ? c1Result : c2Result;
|
|
} else {
|
|
return c1Result || c2Result || null;
|
|
}
|
|
}
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/cast/intersectsGeometry_indirect.generated.js
|
|
var boundingBox2 = new Box3();
|
|
var triangle3 = new ExtendedTriangle();
|
|
var triangle23 = new ExtendedTriangle();
|
|
var invertedMat2 = new Matrix4();
|
|
var obb4 = new OrientedBox();
|
|
var obb23 = new OrientedBox();
|
|
function intersectsGeometry_indirect(bvh, root, otherGeometry, geometryToBvh) {
|
|
BufferStack.setBuffer(bvh._roots[root]);
|
|
const result = _intersectsGeometry2(0, bvh, otherGeometry, geometryToBvh);
|
|
BufferStack.clearBuffer();
|
|
return result;
|
|
}
|
|
function _intersectsGeometry2(nodeIndex32, bvh, otherGeometry, geometryToBvh, cachedObb = null) {
|
|
const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
|
|
let nodeIndex16 = nodeIndex32 * 2;
|
|
if (cachedObb === null) {
|
|
if (!otherGeometry.boundingBox) {
|
|
otherGeometry.computeBoundingBox();
|
|
}
|
|
obb4.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
|
|
cachedObb = obb4;
|
|
}
|
|
const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
|
|
if (isLeaf) {
|
|
const thisGeometry = bvh.geometry;
|
|
const thisIndex = thisGeometry.index;
|
|
const thisPos = thisGeometry.attributes.position;
|
|
const index2 = otherGeometry.index;
|
|
const pos = otherGeometry.attributes.position;
|
|
const offset = OFFSET(nodeIndex32, uint32Array2);
|
|
const count = COUNT(nodeIndex16, uint16Array2);
|
|
invertedMat2.copy(geometryToBvh).invert();
|
|
if (otherGeometry.boundsTree) {
|
|
arrayToBox(BOUNDING_DATA_INDEX(nodeIndex32), float32Array2, obb23);
|
|
obb23.matrix.copy(invertedMat2);
|
|
obb23.needsUpdate = true;
|
|
const res = otherGeometry.boundsTree.shapecast({
|
|
intersectsBounds: (box) => obb23.intersectsBox(box),
|
|
intersectsTriangle: (tri) => {
|
|
tri.a.applyMatrix4(geometryToBvh);
|
|
tri.b.applyMatrix4(geometryToBvh);
|
|
tri.c.applyMatrix4(geometryToBvh);
|
|
tri.needsUpdate = true;
|
|
for (let i3 = offset, l2 = count + offset; i3 < l2; i3++) {
|
|
setTriangle(triangle23, 3 * bvh.resolveTriangleIndex(i3), thisIndex, thisPos);
|
|
triangle23.needsUpdate = true;
|
|
if (tri.intersectsTriangle(triangle23)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
return res;
|
|
} else {
|
|
for (let i3 = offset, l2 = count + offset; i3 < l2; i3++) {
|
|
const ti = bvh.resolveTriangleIndex(i3);
|
|
setTriangle(triangle3, 3 * ti, thisIndex, thisPos);
|
|
triangle3.a.applyMatrix4(invertedMat2);
|
|
triangle3.b.applyMatrix4(invertedMat2);
|
|
triangle3.c.applyMatrix4(invertedMat2);
|
|
triangle3.needsUpdate = true;
|
|
for (let i22 = 0, l22 = index2.count; i22 < l22; i22 += 3) {
|
|
setTriangle(triangle23, i22, index2, pos);
|
|
triangle23.needsUpdate = true;
|
|
if (triangle3.intersectsTriangle(triangle23)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
const left = nodeIndex32 + 8;
|
|
const right = uint32Array2[nodeIndex32 + 6];
|
|
arrayToBox(BOUNDING_DATA_INDEX(left), float32Array2, boundingBox2);
|
|
const leftIntersection = cachedObb.intersectsBox(boundingBox2) && _intersectsGeometry2(left, bvh, otherGeometry, geometryToBvh, cachedObb);
|
|
if (leftIntersection) return true;
|
|
arrayToBox(BOUNDING_DATA_INDEX(right), float32Array2, boundingBox2);
|
|
const rightIntersection = cachedObb.intersectsBox(boundingBox2) && _intersectsGeometry2(right, bvh, otherGeometry, geometryToBvh, cachedObb);
|
|
if (rightIntersection) return true;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/cast/closestPointToGeometry_indirect.generated.js
|
|
var tempMatrix2 = new Matrix4();
|
|
var obb5 = new OrientedBox();
|
|
var obb24 = new OrientedBox();
|
|
var temp13 = new Vector3();
|
|
var temp22 = new Vector3();
|
|
var temp32 = new Vector3();
|
|
var temp42 = new Vector3();
|
|
function closestPointToGeometry_indirect(bvh, otherGeometry, geometryToBvh, target1 = {}, target2 = {}, minThreshold = 0, maxThreshold = Infinity) {
|
|
if (!otherGeometry.boundingBox) {
|
|
otherGeometry.computeBoundingBox();
|
|
}
|
|
obb5.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
|
|
obb5.needsUpdate = true;
|
|
const geometry3 = bvh.geometry;
|
|
const pos = geometry3.attributes.position;
|
|
const index2 = geometry3.index;
|
|
const otherPos = otherGeometry.attributes.position;
|
|
const otherIndex = otherGeometry.index;
|
|
const triangle4 = ExtendedTrianglePool.getPrimitive();
|
|
const triangle24 = ExtendedTrianglePool.getPrimitive();
|
|
let tempTarget1 = temp13;
|
|
let tempTargetDest1 = temp22;
|
|
let tempTarget2 = null;
|
|
let tempTargetDest2 = null;
|
|
if (target2) {
|
|
tempTarget2 = temp32;
|
|
tempTargetDest2 = temp42;
|
|
}
|
|
let closestDistance = Infinity;
|
|
let closestDistanceTriIndex = null;
|
|
let closestDistanceOtherTriIndex = null;
|
|
tempMatrix2.copy(geometryToBvh).invert();
|
|
obb24.matrix.copy(tempMatrix2);
|
|
bvh.shapecast(
|
|
{
|
|
boundsTraverseOrder: (box) => {
|
|
return obb5.distanceToBox(box);
|
|
},
|
|
intersectsBounds: (box, isLeaf, score) => {
|
|
if (score < closestDistance && score < maxThreshold) {
|
|
if (isLeaf) {
|
|
obb24.min.copy(box.min);
|
|
obb24.max.copy(box.max);
|
|
obb24.needsUpdate = true;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
intersectsRange: (offset, count) => {
|
|
if (otherGeometry.boundsTree) {
|
|
const otherBvh = otherGeometry.boundsTree;
|
|
return otherBvh.shapecast({
|
|
boundsTraverseOrder: (box) => {
|
|
return obb24.distanceToBox(box);
|
|
},
|
|
intersectsBounds: (box, isLeaf, score) => {
|
|
return score < closestDistance && score < maxThreshold;
|
|
},
|
|
intersectsRange: (otherOffset, otherCount) => {
|
|
for (let i22 = otherOffset, l2 = otherOffset + otherCount; i22 < l2; i22++) {
|
|
const ti2 = otherBvh.resolveTriangleIndex(i22);
|
|
setTriangle(triangle24, 3 * ti2, otherIndex, otherPos);
|
|
triangle24.a.applyMatrix4(geometryToBvh);
|
|
triangle24.b.applyMatrix4(geometryToBvh);
|
|
triangle24.c.applyMatrix4(geometryToBvh);
|
|
triangle24.needsUpdate = true;
|
|
for (let i3 = offset, l3 = offset + count; i3 < l3; i3++) {
|
|
const ti = bvh.resolveTriangleIndex(i3);
|
|
setTriangle(triangle4, 3 * ti, index2, pos);
|
|
triangle4.needsUpdate = true;
|
|
const dist = triangle4.distanceToTriangle(triangle24, tempTarget1, tempTarget2);
|
|
if (dist < closestDistance) {
|
|
tempTargetDest1.copy(tempTarget1);
|
|
if (tempTargetDest2) {
|
|
tempTargetDest2.copy(tempTarget2);
|
|
}
|
|
closestDistance = dist;
|
|
closestDistanceTriIndex = i3;
|
|
closestDistanceOtherTriIndex = i22;
|
|
}
|
|
if (dist < minThreshold) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
const triCount = getTriCount(otherGeometry);
|
|
for (let i22 = 0, l2 = triCount; i22 < l2; i22++) {
|
|
setTriangle(triangle24, 3 * i22, otherIndex, otherPos);
|
|
triangle24.a.applyMatrix4(geometryToBvh);
|
|
triangle24.b.applyMatrix4(geometryToBvh);
|
|
triangle24.c.applyMatrix4(geometryToBvh);
|
|
triangle24.needsUpdate = true;
|
|
for (let i3 = offset, l3 = offset + count; i3 < l3; i3++) {
|
|
const ti = bvh.resolveTriangleIndex(i3);
|
|
setTriangle(triangle4, 3 * ti, index2, pos);
|
|
triangle4.needsUpdate = true;
|
|
const dist = triangle4.distanceToTriangle(triangle24, tempTarget1, tempTarget2);
|
|
if (dist < closestDistance) {
|
|
tempTargetDest1.copy(tempTarget1);
|
|
if (tempTargetDest2) {
|
|
tempTargetDest2.copy(tempTarget2);
|
|
}
|
|
closestDistance = dist;
|
|
closestDistanceTriIndex = i3;
|
|
closestDistanceOtherTriIndex = i22;
|
|
}
|
|
if (dist < minThreshold) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
);
|
|
ExtendedTrianglePool.releasePrimitive(triangle4);
|
|
ExtendedTrianglePool.releasePrimitive(triangle24);
|
|
if (closestDistance === Infinity) {
|
|
return null;
|
|
}
|
|
if (!target1.point) {
|
|
target1.point = tempTargetDest1.clone();
|
|
} else {
|
|
target1.point.copy(tempTargetDest1);
|
|
}
|
|
target1.distance = closestDistance, target1.faceIndex = closestDistanceTriIndex;
|
|
if (target2) {
|
|
if (!target2.point) target2.point = tempTargetDest2.clone();
|
|
else target2.point.copy(tempTargetDest2);
|
|
target2.point.applyMatrix4(tempMatrix2);
|
|
tempTargetDest1.applyMatrix4(tempMatrix2);
|
|
target2.distance = tempTargetDest1.sub(target2.point).length();
|
|
target2.faceIndex = closestDistanceOtherTriIndex;
|
|
}
|
|
return target1;
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/utils/BufferUtils.js
|
|
function isSharedArrayBufferSupported() {
|
|
return typeof SharedArrayBuffer !== "undefined";
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/cast/bvhcast.js
|
|
var _bufferStack1 = new BufferStack.constructor();
|
|
var _bufferStack2 = new BufferStack.constructor();
|
|
var _boxPool = new PrimitivePool(() => new Box3());
|
|
var _leftBox1 = new Box3();
|
|
var _rightBox1 = new Box3();
|
|
var _leftBox2 = new Box3();
|
|
var _rightBox2 = new Box3();
|
|
var _active = false;
|
|
function bvhcast(bvh, otherBvh, matrixToLocal, intersectsRanges) {
|
|
if (_active) {
|
|
throw new Error("MeshBVH: Recursive calls to bvhcast not supported.");
|
|
}
|
|
_active = true;
|
|
const roots = bvh._roots;
|
|
const otherRoots = otherBvh._roots;
|
|
let result;
|
|
let offset1 = 0;
|
|
let offset2 = 0;
|
|
const invMat = new Matrix4().copy(matrixToLocal).invert();
|
|
for (let i3 = 0, il = roots.length; i3 < il; i3++) {
|
|
_bufferStack1.setBuffer(roots[i3]);
|
|
offset2 = 0;
|
|
const localBox = _boxPool.getPrimitive();
|
|
arrayToBox(BOUNDING_DATA_INDEX(0), _bufferStack1.float32Array, localBox);
|
|
localBox.applyMatrix4(invMat);
|
|
for (let j = 0, jl = otherRoots.length; j < jl; j++) {
|
|
_bufferStack2.setBuffer(otherRoots[j]);
|
|
result = _traverse(
|
|
0,
|
|
0,
|
|
matrixToLocal,
|
|
invMat,
|
|
intersectsRanges,
|
|
offset1,
|
|
offset2,
|
|
0,
|
|
0,
|
|
localBox
|
|
);
|
|
_bufferStack2.clearBuffer();
|
|
offset2 += otherRoots[j].length;
|
|
if (result) {
|
|
break;
|
|
}
|
|
}
|
|
_boxPool.releasePrimitive(localBox);
|
|
_bufferStack1.clearBuffer();
|
|
offset1 += roots[i3].length;
|
|
if (result) {
|
|
break;
|
|
}
|
|
}
|
|
_active = false;
|
|
return result;
|
|
}
|
|
function _traverse(node1Index32, node2Index32, matrix2to1, matrix1to2, intersectsRangesFunc, node1IndexByteOffset = 0, node2IndexByteOffset = 0, depth1 = 0, depth2 = 0, currBox = null, reversed = false) {
|
|
let bufferStack1, bufferStack2;
|
|
if (reversed) {
|
|
bufferStack1 = _bufferStack2;
|
|
bufferStack2 = _bufferStack1;
|
|
} else {
|
|
bufferStack1 = _bufferStack1;
|
|
bufferStack2 = _bufferStack2;
|
|
}
|
|
const float32Array1 = bufferStack1.float32Array, uint32Array1 = bufferStack1.uint32Array, uint16Array1 = bufferStack1.uint16Array, float32Array2 = bufferStack2.float32Array, uint32Array2 = bufferStack2.uint32Array, uint16Array2 = bufferStack2.uint16Array;
|
|
const node1Index16 = node1Index32 * 2;
|
|
const node2Index16 = node2Index32 * 2;
|
|
const isLeaf1 = IS_LEAF(node1Index16, uint16Array1);
|
|
const isLeaf2 = IS_LEAF(node2Index16, uint16Array2);
|
|
let result = false;
|
|
if (isLeaf2 && isLeaf1) {
|
|
if (reversed) {
|
|
result = intersectsRangesFunc(
|
|
OFFSET(node2Index32, uint32Array2),
|
|
COUNT(node2Index32 * 2, uint16Array2),
|
|
OFFSET(node1Index32, uint32Array1),
|
|
COUNT(node1Index32 * 2, uint16Array1),
|
|
depth2,
|
|
node2IndexByteOffset + node2Index32,
|
|
depth1,
|
|
node1IndexByteOffset + node1Index32
|
|
);
|
|
} else {
|
|
result = intersectsRangesFunc(
|
|
OFFSET(node1Index32, uint32Array1),
|
|
COUNT(node1Index32 * 2, uint16Array1),
|
|
OFFSET(node2Index32, uint32Array2),
|
|
COUNT(node2Index32 * 2, uint16Array2),
|
|
depth1,
|
|
node1IndexByteOffset + node1Index32,
|
|
depth2,
|
|
node2IndexByteOffset + node2Index32
|
|
);
|
|
}
|
|
} else if (isLeaf2) {
|
|
const newBox = _boxPool.getPrimitive();
|
|
arrayToBox(BOUNDING_DATA_INDEX(node2Index32), float32Array2, newBox);
|
|
newBox.applyMatrix4(matrix2to1);
|
|
const cl1 = LEFT_NODE(node1Index32);
|
|
const cr1 = RIGHT_NODE(node1Index32, uint32Array1);
|
|
arrayToBox(BOUNDING_DATA_INDEX(cl1), float32Array1, _leftBox1);
|
|
arrayToBox(BOUNDING_DATA_INDEX(cr1), float32Array1, _rightBox1);
|
|
const intersectCl1 = newBox.intersectsBox(_leftBox1);
|
|
const intersectCr1 = newBox.intersectsBox(_rightBox1);
|
|
result = intersectCl1 && _traverse(
|
|
node2Index32,
|
|
cl1,
|
|
matrix1to2,
|
|
matrix2to1,
|
|
intersectsRangesFunc,
|
|
node2IndexByteOffset,
|
|
node1IndexByteOffset,
|
|
depth2,
|
|
depth1 + 1,
|
|
newBox,
|
|
!reversed
|
|
) || intersectCr1 && _traverse(
|
|
node2Index32,
|
|
cr1,
|
|
matrix1to2,
|
|
matrix2to1,
|
|
intersectsRangesFunc,
|
|
node2IndexByteOffset,
|
|
node1IndexByteOffset,
|
|
depth2,
|
|
depth1 + 1,
|
|
newBox,
|
|
!reversed
|
|
);
|
|
_boxPool.releasePrimitive(newBox);
|
|
} else {
|
|
const cl2 = LEFT_NODE(node2Index32);
|
|
const cr2 = RIGHT_NODE(node2Index32, uint32Array2);
|
|
arrayToBox(BOUNDING_DATA_INDEX(cl2), float32Array2, _leftBox2);
|
|
arrayToBox(BOUNDING_DATA_INDEX(cr2), float32Array2, _rightBox2);
|
|
const leftIntersects = currBox.intersectsBox(_leftBox2);
|
|
const rightIntersects = currBox.intersectsBox(_rightBox2);
|
|
if (leftIntersects && rightIntersects) {
|
|
result = _traverse(
|
|
node1Index32,
|
|
cl2,
|
|
matrix2to1,
|
|
matrix1to2,
|
|
intersectsRangesFunc,
|
|
node1IndexByteOffset,
|
|
node2IndexByteOffset,
|
|
depth1,
|
|
depth2 + 1,
|
|
currBox,
|
|
reversed
|
|
) || _traverse(
|
|
node1Index32,
|
|
cr2,
|
|
matrix2to1,
|
|
matrix1to2,
|
|
intersectsRangesFunc,
|
|
node1IndexByteOffset,
|
|
node2IndexByteOffset,
|
|
depth1,
|
|
depth2 + 1,
|
|
currBox,
|
|
reversed
|
|
);
|
|
} else if (leftIntersects) {
|
|
if (isLeaf1) {
|
|
result = _traverse(
|
|
node1Index32,
|
|
cl2,
|
|
matrix2to1,
|
|
matrix1to2,
|
|
intersectsRangesFunc,
|
|
node1IndexByteOffset,
|
|
node2IndexByteOffset,
|
|
depth1,
|
|
depth2 + 1,
|
|
currBox,
|
|
reversed
|
|
);
|
|
} else {
|
|
const newBox = _boxPool.getPrimitive();
|
|
newBox.copy(_leftBox2).applyMatrix4(matrix2to1);
|
|
const cl1 = LEFT_NODE(node1Index32);
|
|
const cr1 = RIGHT_NODE(node1Index32, uint32Array1);
|
|
arrayToBox(BOUNDING_DATA_INDEX(cl1), float32Array1, _leftBox1);
|
|
arrayToBox(BOUNDING_DATA_INDEX(cr1), float32Array1, _rightBox1);
|
|
const intersectCl1 = newBox.intersectsBox(_leftBox1);
|
|
const intersectCr1 = newBox.intersectsBox(_rightBox1);
|
|
result = intersectCl1 && _traverse(
|
|
cl2,
|
|
cl1,
|
|
matrix1to2,
|
|
matrix2to1,
|
|
intersectsRangesFunc,
|
|
node2IndexByteOffset,
|
|
node1IndexByteOffset,
|
|
depth2,
|
|
depth1 + 1,
|
|
newBox,
|
|
!reversed
|
|
) || intersectCr1 && _traverse(
|
|
cl2,
|
|
cr1,
|
|
matrix1to2,
|
|
matrix2to1,
|
|
intersectsRangesFunc,
|
|
node2IndexByteOffset,
|
|
node1IndexByteOffset,
|
|
depth2,
|
|
depth1 + 1,
|
|
newBox,
|
|
!reversed
|
|
);
|
|
_boxPool.releasePrimitive(newBox);
|
|
}
|
|
} else if (rightIntersects) {
|
|
if (isLeaf1) {
|
|
result = _traverse(
|
|
node1Index32,
|
|
cr2,
|
|
matrix2to1,
|
|
matrix1to2,
|
|
intersectsRangesFunc,
|
|
node1IndexByteOffset,
|
|
node2IndexByteOffset,
|
|
depth1,
|
|
depth2 + 1,
|
|
currBox,
|
|
reversed
|
|
);
|
|
} else {
|
|
const newBox = _boxPool.getPrimitive();
|
|
newBox.copy(_rightBox2).applyMatrix4(matrix2to1);
|
|
const cl1 = LEFT_NODE(node1Index32);
|
|
const cr1 = RIGHT_NODE(node1Index32, uint32Array1);
|
|
arrayToBox(BOUNDING_DATA_INDEX(cl1), float32Array1, _leftBox1);
|
|
arrayToBox(BOUNDING_DATA_INDEX(cr1), float32Array1, _rightBox1);
|
|
const intersectCl1 = newBox.intersectsBox(_leftBox1);
|
|
const intersectCr1 = newBox.intersectsBox(_rightBox1);
|
|
result = intersectCl1 && _traverse(
|
|
cr2,
|
|
cl1,
|
|
matrix1to2,
|
|
matrix2to1,
|
|
intersectsRangesFunc,
|
|
node2IndexByteOffset,
|
|
node1IndexByteOffset,
|
|
depth2,
|
|
depth1 + 1,
|
|
newBox,
|
|
!reversed
|
|
) || intersectCr1 && _traverse(
|
|
cr2,
|
|
cr1,
|
|
matrix1to2,
|
|
matrix2to1,
|
|
intersectsRangesFunc,
|
|
node2IndexByteOffset,
|
|
node1IndexByteOffset,
|
|
depth2,
|
|
depth1 + 1,
|
|
newBox,
|
|
!reversed
|
|
);
|
|
_boxPool.releasePrimitive(newBox);
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/core/MeshBVH.js
|
|
var obb6 = new OrientedBox();
|
|
var tempBox = new Box3();
|
|
var DEFAULT_OPTIONS = {
|
|
strategy: CENTER,
|
|
maxDepth: 40,
|
|
maxLeafTris: 10,
|
|
useSharedArrayBuffer: false,
|
|
setBoundingBox: true,
|
|
onProgress: null,
|
|
indirect: false,
|
|
verbose: true,
|
|
range: null
|
|
};
|
|
var MeshBVH = class _MeshBVH {
|
|
static serialize(bvh, options = {}) {
|
|
options = {
|
|
cloneBuffers: true,
|
|
...options
|
|
};
|
|
const geometry3 = bvh.geometry;
|
|
const rootData = bvh._roots;
|
|
const indirectBuffer = bvh._indirectBuffer;
|
|
const indexAttribute = geometry3.getIndex();
|
|
let result;
|
|
if (options.cloneBuffers) {
|
|
result = {
|
|
roots: rootData.map((root) => root.slice()),
|
|
index: indexAttribute ? indexAttribute.array.slice() : null,
|
|
indirectBuffer: indirectBuffer ? indirectBuffer.slice() : null
|
|
};
|
|
} else {
|
|
result = {
|
|
roots: rootData,
|
|
index: indexAttribute ? indexAttribute.array : null,
|
|
indirectBuffer
|
|
};
|
|
}
|
|
return result;
|
|
}
|
|
static deserialize(data, geometry3, options = {}) {
|
|
options = {
|
|
setIndex: true,
|
|
indirect: Boolean(data.indirectBuffer),
|
|
...options
|
|
};
|
|
const { index: index2, roots, indirectBuffer } = data;
|
|
const bvh = new _MeshBVH(geometry3, { ...options, [SKIP_GENERATION]: true });
|
|
bvh._roots = roots;
|
|
bvh._indirectBuffer = indirectBuffer || null;
|
|
if (options.setIndex) {
|
|
const indexAttribute = geometry3.getIndex();
|
|
if (indexAttribute === null) {
|
|
const newIndex = new BufferAttribute(data.index, 1, false);
|
|
geometry3.setIndex(newIndex);
|
|
} else if (indexAttribute.array !== index2) {
|
|
indexAttribute.array.set(index2);
|
|
indexAttribute.needsUpdate = true;
|
|
}
|
|
}
|
|
return bvh;
|
|
}
|
|
get indirect() {
|
|
return !!this._indirectBuffer;
|
|
}
|
|
constructor(geometry3, options = {}) {
|
|
if (!geometry3.isBufferGeometry) {
|
|
throw new Error("MeshBVH: Only BufferGeometries are supported.");
|
|
} else if (geometry3.index && geometry3.index.isInterleavedBufferAttribute) {
|
|
throw new Error("MeshBVH: InterleavedBufferAttribute is not supported for the index attribute.");
|
|
}
|
|
options = Object.assign({
|
|
...DEFAULT_OPTIONS,
|
|
// undocumented options
|
|
// Whether to skip generating the tree. Used for deserialization.
|
|
[SKIP_GENERATION]: false
|
|
}, options);
|
|
if (options.useSharedArrayBuffer && !isSharedArrayBufferSupported()) {
|
|
throw new Error("MeshBVH: SharedArrayBuffer is not available.");
|
|
}
|
|
this.geometry = geometry3;
|
|
this._roots = null;
|
|
this._indirectBuffer = null;
|
|
if (!options[SKIP_GENERATION]) {
|
|
buildPackedTree(this, options);
|
|
if (!geometry3.boundingBox && options.setBoundingBox) {
|
|
geometry3.boundingBox = this.getBoundingBox(new Box3());
|
|
}
|
|
}
|
|
this.resolveTriangleIndex = options.indirect ? (i3) => this._indirectBuffer[i3] : (i3) => i3;
|
|
}
|
|
refit(nodeIndices = null) {
|
|
const refitFunc = this.indirect ? refit_indirect : refit;
|
|
return refitFunc(this, nodeIndices);
|
|
}
|
|
traverse(callback, rootIndex = 0) {
|
|
const buffer2 = this._roots[rootIndex];
|
|
const uint32Array2 = new Uint32Array(buffer2);
|
|
const uint16Array2 = new Uint16Array(buffer2);
|
|
_traverse2(0);
|
|
function _traverse2(node32Index, depth = 0) {
|
|
const node16Index = node32Index * 2;
|
|
const isLeaf = uint16Array2[node16Index + 15] === IS_LEAFNODE_FLAG;
|
|
if (isLeaf) {
|
|
const offset = uint32Array2[node32Index + 6];
|
|
const count = uint16Array2[node16Index + 14];
|
|
callback(depth, isLeaf, new Float32Array(buffer2, node32Index * 4, 6), offset, count);
|
|
} else {
|
|
const left = node32Index + BYTES_PER_NODE / 4;
|
|
const right = uint32Array2[node32Index + 6];
|
|
const splitAxis = uint32Array2[node32Index + 7];
|
|
const stopTraversal = callback(depth, isLeaf, new Float32Array(buffer2, node32Index * 4, 6), splitAxis);
|
|
if (!stopTraversal) {
|
|
_traverse2(left, depth + 1);
|
|
_traverse2(right, depth + 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* Core Cast Functions */
|
|
raycast(ray4, materialOrSide = FrontSide, near = 0, far = Infinity) {
|
|
const roots = this._roots;
|
|
const geometry3 = this.geometry;
|
|
const intersects = [];
|
|
const isMaterial = materialOrSide.isMaterial;
|
|
const isArrayMaterial = Array.isArray(materialOrSide);
|
|
const groups = geometry3.groups;
|
|
const side = isMaterial ? materialOrSide.side : materialOrSide;
|
|
const raycastFunc = this.indirect ? raycast_indirect : raycast;
|
|
for (let i3 = 0, l2 = roots.length; i3 < l2; i3++) {
|
|
const materialSide = isArrayMaterial ? materialOrSide[groups[i3].materialIndex].side : side;
|
|
const startCount = intersects.length;
|
|
raycastFunc(this, i3, materialSide, ray4, intersects, near, far);
|
|
if (isArrayMaterial) {
|
|
const materialIndex = groups[i3].materialIndex;
|
|
for (let j = startCount, jl = intersects.length; j < jl; j++) {
|
|
intersects[j].face.materialIndex = materialIndex;
|
|
}
|
|
}
|
|
}
|
|
return intersects;
|
|
}
|
|
raycastFirst(ray4, materialOrSide = FrontSide, near = 0, far = Infinity) {
|
|
const roots = this._roots;
|
|
const geometry3 = this.geometry;
|
|
const isMaterial = materialOrSide.isMaterial;
|
|
const isArrayMaterial = Array.isArray(materialOrSide);
|
|
let closestResult = null;
|
|
const groups = geometry3.groups;
|
|
const side = isMaterial ? materialOrSide.side : materialOrSide;
|
|
const raycastFirstFunc = this.indirect ? raycastFirst_indirect : raycastFirst;
|
|
for (let i3 = 0, l2 = roots.length; i3 < l2; i3++) {
|
|
const materialSide = isArrayMaterial ? materialOrSide[groups[i3].materialIndex].side : side;
|
|
const result = raycastFirstFunc(this, i3, materialSide, ray4, near, far);
|
|
if (result != null && (closestResult == null || result.distance < closestResult.distance)) {
|
|
closestResult = result;
|
|
if (isArrayMaterial) {
|
|
result.face.materialIndex = groups[i3].materialIndex;
|
|
}
|
|
}
|
|
}
|
|
return closestResult;
|
|
}
|
|
intersectsGeometry(otherGeometry, geomToMesh) {
|
|
let result = false;
|
|
const roots = this._roots;
|
|
const intersectsGeometryFunc = this.indirect ? intersectsGeometry_indirect : intersectsGeometry;
|
|
for (let i3 = 0, l2 = roots.length; i3 < l2; i3++) {
|
|
result = intersectsGeometryFunc(this, i3, otherGeometry, geomToMesh);
|
|
if (result) {
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
shapecast(callbacks) {
|
|
const triangle4 = ExtendedTrianglePool.getPrimitive();
|
|
const iterateFunc = this.indirect ? iterateOverTriangles_indirect : iterateOverTriangles;
|
|
let {
|
|
boundsTraverseOrder,
|
|
intersectsBounds,
|
|
intersectsRange,
|
|
intersectsTriangle
|
|
} = callbacks;
|
|
if (intersectsRange && intersectsTriangle) {
|
|
const originalIntersectsRange = intersectsRange;
|
|
intersectsRange = (offset, count, contained, depth, nodeIndex) => {
|
|
if (!originalIntersectsRange(offset, count, contained, depth, nodeIndex)) {
|
|
return iterateFunc(offset, count, this, intersectsTriangle, contained, depth, triangle4);
|
|
}
|
|
return true;
|
|
};
|
|
} else if (!intersectsRange) {
|
|
if (intersectsTriangle) {
|
|
intersectsRange = (offset, count, contained, depth) => {
|
|
return iterateFunc(offset, count, this, intersectsTriangle, contained, depth, triangle4);
|
|
};
|
|
} else {
|
|
intersectsRange = (offset, count, contained) => {
|
|
return contained;
|
|
};
|
|
}
|
|
}
|
|
let result = false;
|
|
let byteOffset = 0;
|
|
const roots = this._roots;
|
|
for (let i3 = 0, l2 = roots.length; i3 < l2; i3++) {
|
|
const root = roots[i3];
|
|
result = shapecast(this, i3, intersectsBounds, intersectsRange, boundsTraverseOrder, byteOffset);
|
|
if (result) {
|
|
break;
|
|
}
|
|
byteOffset += root.byteLength;
|
|
}
|
|
ExtendedTrianglePool.releasePrimitive(triangle4);
|
|
return result;
|
|
}
|
|
bvhcast(otherBvh, matrixToLocal, callbacks) {
|
|
let {
|
|
intersectsRanges,
|
|
intersectsTriangles
|
|
} = callbacks;
|
|
const triangle1 = ExtendedTrianglePool.getPrimitive();
|
|
const indexAttr1 = this.geometry.index;
|
|
const positionAttr1 = this.geometry.attributes.position;
|
|
const assignTriangle1 = this.indirect ? (i1) => {
|
|
const ti = this.resolveTriangleIndex(i1);
|
|
setTriangle(triangle1, ti * 3, indexAttr1, positionAttr1);
|
|
} : (i1) => {
|
|
setTriangle(triangle1, i1 * 3, indexAttr1, positionAttr1);
|
|
};
|
|
const triangle24 = ExtendedTrianglePool.getPrimitive();
|
|
const indexAttr2 = otherBvh.geometry.index;
|
|
const positionAttr2 = otherBvh.geometry.attributes.position;
|
|
const assignTriangle2 = otherBvh.indirect ? (i22) => {
|
|
const ti2 = otherBvh.resolveTriangleIndex(i22);
|
|
setTriangle(triangle24, ti2 * 3, indexAttr2, positionAttr2);
|
|
} : (i22) => {
|
|
setTriangle(triangle24, i22 * 3, indexAttr2, positionAttr2);
|
|
};
|
|
if (intersectsTriangles) {
|
|
const iterateOverDoubleTriangles = (offset1, count1, offset2, count2, depth1, index1, depth2, index2) => {
|
|
for (let i22 = offset2, l2 = offset2 + count2; i22 < l2; i22++) {
|
|
assignTriangle2(i22);
|
|
triangle24.a.applyMatrix4(matrixToLocal);
|
|
triangle24.b.applyMatrix4(matrixToLocal);
|
|
triangle24.c.applyMatrix4(matrixToLocal);
|
|
triangle24.needsUpdate = true;
|
|
for (let i1 = offset1, l1 = offset1 + count1; i1 < l1; i1++) {
|
|
assignTriangle1(i1);
|
|
triangle1.needsUpdate = true;
|
|
if (intersectsTriangles(triangle1, triangle24, i1, i22, depth1, index1, depth2, index2)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
if (intersectsRanges) {
|
|
const originalIntersectsRanges = intersectsRanges;
|
|
intersectsRanges = function(offset1, count1, offset2, count2, depth1, index1, depth2, index2) {
|
|
if (!originalIntersectsRanges(offset1, count1, offset2, count2, depth1, index1, depth2, index2)) {
|
|
return iterateOverDoubleTriangles(offset1, count1, offset2, count2, depth1, index1, depth2, index2);
|
|
}
|
|
return true;
|
|
};
|
|
} else {
|
|
intersectsRanges = iterateOverDoubleTriangles;
|
|
}
|
|
}
|
|
return bvhcast(this, otherBvh, matrixToLocal, intersectsRanges);
|
|
}
|
|
/* Derived Cast Functions */
|
|
intersectsBox(box, boxToMesh) {
|
|
obb6.set(box.min, box.max, boxToMesh);
|
|
obb6.needsUpdate = true;
|
|
return this.shapecast(
|
|
{
|
|
intersectsBounds: (box2) => obb6.intersectsBox(box2),
|
|
intersectsTriangle: (tri) => obb6.intersectsTriangle(tri)
|
|
}
|
|
);
|
|
}
|
|
intersectsSphere(sphere) {
|
|
return this.shapecast(
|
|
{
|
|
intersectsBounds: (box) => sphere.intersectsBox(box),
|
|
intersectsTriangle: (tri) => tri.intersectsSphere(sphere)
|
|
}
|
|
);
|
|
}
|
|
closestPointToGeometry(otherGeometry, geometryToBvh, target1 = {}, target2 = {}, minThreshold = 0, maxThreshold = Infinity) {
|
|
const closestPointToGeometryFunc = this.indirect ? closestPointToGeometry_indirect : closestPointToGeometry;
|
|
return closestPointToGeometryFunc(
|
|
this,
|
|
otherGeometry,
|
|
geometryToBvh,
|
|
target1,
|
|
target2,
|
|
minThreshold,
|
|
maxThreshold
|
|
);
|
|
}
|
|
closestPointToPoint(point, target2 = {}, minThreshold = 0, maxThreshold = Infinity) {
|
|
return closestPointToPoint(
|
|
this,
|
|
point,
|
|
target2,
|
|
minThreshold,
|
|
maxThreshold
|
|
);
|
|
}
|
|
getBoundingBox(target2) {
|
|
target2.makeEmpty();
|
|
const roots = this._roots;
|
|
roots.forEach((buffer2) => {
|
|
arrayToBox(0, new Float32Array(buffer2), tempBox);
|
|
target2.union(tempBox);
|
|
});
|
|
return target2;
|
|
}
|
|
};
|
|
|
|
// node_modules/three-mesh-bvh/src/objects/MeshBVHHelper.js
|
|
var boundingBox3 = new Box3();
|
|
var matrix3 = new Matrix4();
|
|
|
|
// node_modules/three-mesh-bvh/src/debug/Debug.js
|
|
var _box12 = new Box3();
|
|
var _box22 = new Box3();
|
|
var _vec = new Vector3();
|
|
|
|
// node_modules/three-mesh-bvh/src/utils/GeometryRayIntersectUtilities.js
|
|
function convertRaycastIntersect(hit, object, raycaster) {
|
|
if (hit === null) {
|
|
return null;
|
|
}
|
|
hit.point.applyMatrix4(object.matrixWorld);
|
|
hit.distance = hit.point.distanceTo(raycaster.ray.origin);
|
|
hit.object = object;
|
|
return hit;
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/utils/ExtensionUtilities.js
|
|
var IS_REVISION_166 = parseInt(REVISION) >= 166;
|
|
var ray = new Ray();
|
|
var direction = new Vector3();
|
|
var tmpInverseMatrix = new Matrix4();
|
|
var origMeshRaycastFunc = Mesh.prototype.raycast;
|
|
var origBatchedRaycastFunc = BatchedMesh.prototype.raycast;
|
|
var _worldScale = new Vector3();
|
|
var _mesh = new Mesh();
|
|
var _batchIntersects = [];
|
|
function acceleratedRaycast(raycaster, intersects) {
|
|
if (this.isBatchedMesh) {
|
|
acceleratedBatchedMeshRaycast.call(this, raycaster, intersects);
|
|
} else {
|
|
acceleratedMeshRaycast.call(this, raycaster, intersects);
|
|
}
|
|
}
|
|
function acceleratedBatchedMeshRaycast(raycaster, intersects) {
|
|
if (this.boundsTrees) {
|
|
const boundsTrees = this.boundsTrees;
|
|
const drawInfo = this._drawInfo || this._instanceInfo;
|
|
const drawRanges = this._drawRanges || this._geometryInfo;
|
|
const matrixWorld = this.matrixWorld;
|
|
_mesh.material = this.material;
|
|
_mesh.geometry = this.geometry;
|
|
const oldBoundsTree = _mesh.geometry.boundsTree;
|
|
const oldDrawRange = _mesh.geometry.drawRange;
|
|
if (_mesh.geometry.boundingSphere === null) {
|
|
_mesh.geometry.boundingSphere = new Sphere();
|
|
}
|
|
for (let i3 = 0, l2 = drawInfo.length; i3 < l2; i3++) {
|
|
if (!this.getVisibleAt(i3)) {
|
|
continue;
|
|
}
|
|
const geometryId = drawInfo[i3].geometryIndex;
|
|
_mesh.geometry.boundsTree = boundsTrees[geometryId];
|
|
this.getMatrixAt(i3, _mesh.matrixWorld).premultiply(matrixWorld);
|
|
if (!_mesh.geometry.boundsTree) {
|
|
this.getBoundingBoxAt(geometryId, _mesh.geometry.boundingBox);
|
|
this.getBoundingSphereAt(geometryId, _mesh.geometry.boundingSphere);
|
|
const drawRange = drawRanges[geometryId];
|
|
_mesh.geometry.setDrawRange(drawRange.start, drawRange.count);
|
|
}
|
|
_mesh.raycast(raycaster, _batchIntersects);
|
|
for (let j = 0, l3 = _batchIntersects.length; j < l3; j++) {
|
|
const intersect = _batchIntersects[j];
|
|
intersect.object = this;
|
|
intersect.batchId = i3;
|
|
intersects.push(intersect);
|
|
}
|
|
_batchIntersects.length = 0;
|
|
}
|
|
_mesh.geometry.boundsTree = oldBoundsTree;
|
|
_mesh.geometry.drawRange = oldDrawRange;
|
|
_mesh.material = null;
|
|
_mesh.geometry = null;
|
|
} else {
|
|
origBatchedRaycastFunc.call(this, raycaster, intersects);
|
|
}
|
|
}
|
|
function acceleratedMeshRaycast(raycaster, intersects) {
|
|
if (this.geometry.boundsTree) {
|
|
if (this.material === void 0) return;
|
|
tmpInverseMatrix.copy(this.matrixWorld).invert();
|
|
ray.copy(raycaster.ray).applyMatrix4(tmpInverseMatrix);
|
|
_worldScale.setFromMatrixScale(this.matrixWorld);
|
|
direction.copy(ray.direction).multiply(_worldScale);
|
|
const scaleFactor = direction.length();
|
|
const near = raycaster.near / scaleFactor;
|
|
const far = raycaster.far / scaleFactor;
|
|
const bvh = this.geometry.boundsTree;
|
|
if (raycaster.firstHitOnly === true) {
|
|
const hit = convertRaycastIntersect(bvh.raycastFirst(ray, this.material, near, far), this, raycaster);
|
|
if (hit) {
|
|
intersects.push(hit);
|
|
}
|
|
} else {
|
|
const hits = bvh.raycast(ray, this.material, near, far);
|
|
for (let i3 = 0, l2 = hits.length; i3 < l2; i3++) {
|
|
const hit = convertRaycastIntersect(hits[i3], this, raycaster);
|
|
if (hit) {
|
|
intersects.push(hit);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
origMeshRaycastFunc.call(this, raycaster, intersects);
|
|
}
|
|
}
|
|
function computeBoundsTree(options = {}) {
|
|
this.boundsTree = new MeshBVH(this, options);
|
|
return this.boundsTree;
|
|
}
|
|
function disposeBoundsTree() {
|
|
this.boundsTree = null;
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/gpu/VertexAttributeTexture.js
|
|
function countToStringFormat(count) {
|
|
switch (count) {
|
|
case 1:
|
|
return "R";
|
|
case 2:
|
|
return "RG";
|
|
case 3:
|
|
return "RGBA";
|
|
case 4:
|
|
return "RGBA";
|
|
}
|
|
throw new Error();
|
|
}
|
|
function countToFormat(count) {
|
|
switch (count) {
|
|
case 1:
|
|
return RedFormat;
|
|
case 2:
|
|
return RGFormat;
|
|
case 3:
|
|
return RGBAFormat;
|
|
case 4:
|
|
return RGBAFormat;
|
|
}
|
|
}
|
|
function countToIntFormat(count) {
|
|
switch (count) {
|
|
case 1:
|
|
return RedIntegerFormat;
|
|
case 2:
|
|
return RGIntegerFormat;
|
|
case 3:
|
|
return RGBAIntegerFormat;
|
|
case 4:
|
|
return RGBAIntegerFormat;
|
|
}
|
|
}
|
|
var VertexAttributeTexture = class extends DataTexture {
|
|
constructor() {
|
|
super();
|
|
this.minFilter = NearestFilter;
|
|
this.magFilter = NearestFilter;
|
|
this.generateMipmaps = false;
|
|
this.overrideItemSize = null;
|
|
this._forcedType = null;
|
|
}
|
|
updateFrom(attr) {
|
|
const overrideItemSize = this.overrideItemSize;
|
|
const originalItemSize = attr.itemSize;
|
|
const originalCount = attr.count;
|
|
if (overrideItemSize !== null) {
|
|
if (originalItemSize * originalCount % overrideItemSize !== 0) {
|
|
throw new Error("VertexAttributeTexture: overrideItemSize must divide evenly into buffer length.");
|
|
}
|
|
attr.itemSize = overrideItemSize;
|
|
attr.count = originalCount * originalItemSize / overrideItemSize;
|
|
}
|
|
const itemSize = attr.itemSize;
|
|
const count = attr.count;
|
|
const normalized = attr.normalized;
|
|
const originalBufferCons = attr.array.constructor;
|
|
const byteCount = originalBufferCons.BYTES_PER_ELEMENT;
|
|
let targetType = this._forcedType;
|
|
let finalStride = itemSize;
|
|
if (targetType === null) {
|
|
switch (originalBufferCons) {
|
|
case Float32Array:
|
|
targetType = FloatType;
|
|
break;
|
|
case Uint8Array:
|
|
case Uint16Array:
|
|
case Uint32Array:
|
|
targetType = UnsignedIntType;
|
|
break;
|
|
case Int8Array:
|
|
case Int16Array:
|
|
case Int32Array:
|
|
targetType = IntType;
|
|
break;
|
|
}
|
|
}
|
|
let type, format, normalizeValue, targetBufferCons;
|
|
let internalFormat = countToStringFormat(itemSize);
|
|
switch (targetType) {
|
|
case FloatType:
|
|
normalizeValue = 1;
|
|
format = countToFormat(itemSize);
|
|
if (normalized && byteCount === 1) {
|
|
targetBufferCons = originalBufferCons;
|
|
internalFormat += "8";
|
|
if (originalBufferCons === Uint8Array) {
|
|
type = UnsignedByteType;
|
|
} else {
|
|
type = ByteType;
|
|
internalFormat += "_SNORM";
|
|
}
|
|
} else {
|
|
targetBufferCons = Float32Array;
|
|
internalFormat += "32F";
|
|
type = FloatType;
|
|
}
|
|
break;
|
|
case IntType:
|
|
internalFormat += byteCount * 8 + "I";
|
|
normalizeValue = normalized ? Math.pow(2, originalBufferCons.BYTES_PER_ELEMENT * 8 - 1) : 1;
|
|
format = countToIntFormat(itemSize);
|
|
if (byteCount === 1) {
|
|
targetBufferCons = Int8Array;
|
|
type = ByteType;
|
|
} else if (byteCount === 2) {
|
|
targetBufferCons = Int16Array;
|
|
type = ShortType;
|
|
} else {
|
|
targetBufferCons = Int32Array;
|
|
type = IntType;
|
|
}
|
|
break;
|
|
case UnsignedIntType:
|
|
internalFormat += byteCount * 8 + "UI";
|
|
normalizeValue = normalized ? Math.pow(2, originalBufferCons.BYTES_PER_ELEMENT * 8 - 1) : 1;
|
|
format = countToIntFormat(itemSize);
|
|
if (byteCount === 1) {
|
|
targetBufferCons = Uint8Array;
|
|
type = UnsignedByteType;
|
|
} else if (byteCount === 2) {
|
|
targetBufferCons = Uint16Array;
|
|
type = UnsignedShortType;
|
|
} else {
|
|
targetBufferCons = Uint32Array;
|
|
type = UnsignedIntType;
|
|
}
|
|
break;
|
|
}
|
|
if (finalStride === 3 && (format === RGBAFormat || format === RGBAIntegerFormat)) {
|
|
finalStride = 4;
|
|
}
|
|
const dimension = Math.ceil(Math.sqrt(count)) || 1;
|
|
const length3 = finalStride * dimension * dimension;
|
|
const dataArray = new targetBufferCons(length3);
|
|
const originalNormalized = attr.normalized;
|
|
attr.normalized = false;
|
|
for (let i3 = 0; i3 < count; i3++) {
|
|
const ii = finalStride * i3;
|
|
dataArray[ii] = attr.getX(i3) / normalizeValue;
|
|
if (itemSize >= 2) {
|
|
dataArray[ii + 1] = attr.getY(i3) / normalizeValue;
|
|
}
|
|
if (itemSize >= 3) {
|
|
dataArray[ii + 2] = attr.getZ(i3) / normalizeValue;
|
|
if (finalStride === 4) {
|
|
dataArray[ii + 3] = 1;
|
|
}
|
|
}
|
|
if (itemSize >= 4) {
|
|
dataArray[ii + 3] = attr.getW(i3) / normalizeValue;
|
|
}
|
|
}
|
|
attr.normalized = originalNormalized;
|
|
this.internalFormat = internalFormat;
|
|
this.format = format;
|
|
this.type = type;
|
|
this.image.width = dimension;
|
|
this.image.height = dimension;
|
|
this.image.data = dataArray;
|
|
this.needsUpdate = true;
|
|
this.dispose();
|
|
attr.itemSize = originalItemSize;
|
|
attr.count = originalCount;
|
|
}
|
|
};
|
|
var UIntVertexAttributeTexture = class extends VertexAttributeTexture {
|
|
constructor() {
|
|
super();
|
|
this._forcedType = UnsignedIntType;
|
|
}
|
|
};
|
|
var FloatVertexAttributeTexture = class extends VertexAttributeTexture {
|
|
constructor() {
|
|
super();
|
|
this._forcedType = FloatType;
|
|
}
|
|
};
|
|
|
|
// node_modules/three-mesh-bvh/src/gpu/MeshBVHUniformStruct.js
|
|
var MeshBVHUniformStruct = class {
|
|
constructor() {
|
|
this.index = new UIntVertexAttributeTexture();
|
|
this.position = new FloatVertexAttributeTexture();
|
|
this.bvhBounds = new DataTexture();
|
|
this.bvhContents = new DataTexture();
|
|
this._cachedIndexAttr = null;
|
|
this.index.overrideItemSize = 3;
|
|
}
|
|
updateFrom(bvh) {
|
|
const { geometry: geometry3 } = bvh;
|
|
bvhToTextures(bvh, this.bvhBounds, this.bvhContents);
|
|
this.position.updateFrom(geometry3.attributes.position);
|
|
if (bvh.indirect) {
|
|
const indirectBuffer = bvh._indirectBuffer;
|
|
if (this._cachedIndexAttr === null || this._cachedIndexAttr.count !== indirectBuffer.length) {
|
|
if (geometry3.index) {
|
|
this._cachedIndexAttr = geometry3.index.clone();
|
|
} else {
|
|
const array = getIndexArray(getVertexCount(geometry3));
|
|
this._cachedIndexAttr = new BufferAttribute(array, 1, false);
|
|
}
|
|
}
|
|
dereferenceIndex(geometry3, indirectBuffer, this._cachedIndexAttr);
|
|
this.index.updateFrom(this._cachedIndexAttr);
|
|
} else {
|
|
this.index.updateFrom(geometry3.index);
|
|
}
|
|
}
|
|
dispose() {
|
|
const { index: index2, position: position2, bvhBounds, bvhContents } = this;
|
|
if (index2) index2.dispose();
|
|
if (position2) position2.dispose();
|
|
if (bvhBounds) bvhBounds.dispose();
|
|
if (bvhContents) bvhContents.dispose();
|
|
}
|
|
};
|
|
function dereferenceIndex(geometry3, indirectBuffer, target2) {
|
|
const unpacked = target2.array;
|
|
const indexArray = geometry3.index ? geometry3.index.array : null;
|
|
for (let i3 = 0, l2 = indirectBuffer.length; i3 < l2; i3++) {
|
|
const i32 = 3 * i3;
|
|
const v32 = 3 * indirectBuffer[i3];
|
|
for (let c2 = 0; c2 < 3; c2++) {
|
|
unpacked[i32 + c2] = indexArray ? indexArray[v32 + c2] : v32 + c2;
|
|
}
|
|
}
|
|
}
|
|
function bvhToTextures(bvh, boundsTexture, contentsTexture) {
|
|
const roots = bvh._roots;
|
|
if (roots.length !== 1) {
|
|
throw new Error("MeshBVHUniformStruct: Multi-root BVHs not supported.");
|
|
}
|
|
const root = roots[0];
|
|
const uint16Array2 = new Uint16Array(root);
|
|
const uint32Array2 = new Uint32Array(root);
|
|
const float32Array2 = new Float32Array(root);
|
|
const nodeCount = root.byteLength / BYTES_PER_NODE;
|
|
const boundsDimension = 2 * Math.ceil(Math.sqrt(nodeCount / 2));
|
|
const boundsArray = new Float32Array(4 * boundsDimension * boundsDimension);
|
|
const contentsDimension = Math.ceil(Math.sqrt(nodeCount));
|
|
const contentsArray = new Uint32Array(2 * contentsDimension * contentsDimension);
|
|
for (let i3 = 0; i3 < nodeCount; i3++) {
|
|
const nodeIndex32 = i3 * BYTES_PER_NODE / 4;
|
|
const nodeIndex16 = nodeIndex32 * 2;
|
|
const boundsIndex = BOUNDING_DATA_INDEX(nodeIndex32);
|
|
for (let b = 0; b < 3; b++) {
|
|
boundsArray[8 * i3 + 0 + b] = float32Array2[boundsIndex + 0 + b];
|
|
boundsArray[8 * i3 + 4 + b] = float32Array2[boundsIndex + 3 + b];
|
|
}
|
|
if (IS_LEAF(nodeIndex16, uint16Array2)) {
|
|
const count = COUNT(nodeIndex16, uint16Array2);
|
|
const offset = OFFSET(nodeIndex32, uint32Array2);
|
|
const mergedLeafCount = 4294901760 | count;
|
|
contentsArray[i3 * 2 + 0] = mergedLeafCount;
|
|
contentsArray[i3 * 2 + 1] = offset;
|
|
} else {
|
|
const rightIndex = 4 * RIGHT_NODE(nodeIndex32, uint32Array2) / BYTES_PER_NODE;
|
|
const splitAxis = SPLIT_AXIS(nodeIndex32, uint32Array2);
|
|
contentsArray[i3 * 2 + 0] = splitAxis;
|
|
contentsArray[i3 * 2 + 1] = rightIndex;
|
|
}
|
|
}
|
|
boundsTexture.image.data = boundsArray;
|
|
boundsTexture.image.width = boundsDimension;
|
|
boundsTexture.image.height = boundsDimension;
|
|
boundsTexture.format = RGBAFormat;
|
|
boundsTexture.type = FloatType;
|
|
boundsTexture.internalFormat = "RGBA32F";
|
|
boundsTexture.minFilter = NearestFilter;
|
|
boundsTexture.magFilter = NearestFilter;
|
|
boundsTexture.generateMipmaps = false;
|
|
boundsTexture.needsUpdate = true;
|
|
boundsTexture.dispose();
|
|
contentsTexture.image.data = contentsArray;
|
|
contentsTexture.image.width = contentsDimension;
|
|
contentsTexture.image.height = contentsDimension;
|
|
contentsTexture.format = RGIntegerFormat;
|
|
contentsTexture.type = UnsignedIntType;
|
|
contentsTexture.internalFormat = "RG32UI";
|
|
contentsTexture.minFilter = NearestFilter;
|
|
contentsTexture.magFilter = NearestFilter;
|
|
contentsTexture.generateMipmaps = false;
|
|
contentsTexture.needsUpdate = true;
|
|
contentsTexture.dispose();
|
|
}
|
|
|
|
// node_modules/three-mesh-bvh/src/utils/StaticGeometryGenerator.js
|
|
var _positionVector = new Vector3();
|
|
var _normalVector = new Vector3();
|
|
var _tangentVector = new Vector3();
|
|
var _tangentVector4 = new Vector4();
|
|
var _morphVector = new Vector3();
|
|
var _temp = new Vector3();
|
|
var _skinIndex = new Vector4();
|
|
var _skinWeight = new Vector4();
|
|
var _matrix = new Matrix4();
|
|
var _boneMatrix = new Matrix4();
|
|
|
|
// node_modules/three-mesh-bvh/src/gpu/glsl/common_functions.glsl.js
|
|
var common_functions = (
|
|
/* glsl */
|
|
`
|
|
|
|
// A stack of uint32 indices can can store the indices for
|
|
// a perfectly balanced tree with a depth up to 31. Lower stack
|
|
// depth gets higher performance.
|
|
//
|
|
// However not all trees are balanced. Best value to set this to
|
|
// is the trees max depth.
|
|
#ifndef BVH_STACK_DEPTH
|
|
#define BVH_STACK_DEPTH 60
|
|
#endif
|
|
|
|
#ifndef INFINITY
|
|
#define INFINITY 1e20
|
|
#endif
|
|
|
|
// Utilities
|
|
uvec4 uTexelFetch1D( usampler2D tex, uint index ) {
|
|
|
|
uint width = uint( textureSize( tex, 0 ).x );
|
|
uvec2 uv;
|
|
uv.x = index % width;
|
|
uv.y = index / width;
|
|
|
|
return texelFetch( tex, ivec2( uv ), 0 );
|
|
|
|
}
|
|
|
|
ivec4 iTexelFetch1D( isampler2D tex, uint index ) {
|
|
|
|
uint width = uint( textureSize( tex, 0 ).x );
|
|
uvec2 uv;
|
|
uv.x = index % width;
|
|
uv.y = index / width;
|
|
|
|
return texelFetch( tex, ivec2( uv ), 0 );
|
|
|
|
}
|
|
|
|
vec4 texelFetch1D( sampler2D tex, uint index ) {
|
|
|
|
uint width = uint( textureSize( tex, 0 ).x );
|
|
uvec2 uv;
|
|
uv.x = index % width;
|
|
uv.y = index / width;
|
|
|
|
return texelFetch( tex, ivec2( uv ), 0 );
|
|
|
|
}
|
|
|
|
vec4 textureSampleBarycoord( sampler2D tex, vec3 barycoord, uvec3 faceIndices ) {
|
|
|
|
return
|
|
barycoord.x * texelFetch1D( tex, faceIndices.x ) +
|
|
barycoord.y * texelFetch1D( tex, faceIndices.y ) +
|
|
barycoord.z * texelFetch1D( tex, faceIndices.z );
|
|
|
|
}
|
|
|
|
void ndcToCameraRay(
|
|
vec2 coord, mat4 cameraWorld, mat4 invProjectionMatrix,
|
|
out vec3 rayOrigin, out vec3 rayDirection
|
|
) {
|
|
|
|
// get camera look direction and near plane for camera clipping
|
|
vec4 lookDirection = cameraWorld * vec4( 0.0, 0.0, - 1.0, 0.0 );
|
|
vec4 nearVector = invProjectionMatrix * vec4( 0.0, 0.0, - 1.0, 1.0 );
|
|
float near = abs( nearVector.z / nearVector.w );
|
|
|
|
// get the camera direction and position from camera matrices
|
|
vec4 origin = cameraWorld * vec4( 0.0, 0.0, 0.0, 1.0 );
|
|
vec4 direction = invProjectionMatrix * vec4( coord, 0.5, 1.0 );
|
|
direction /= direction.w;
|
|
direction = cameraWorld * direction - origin;
|
|
|
|
// slide the origin along the ray until it sits at the near clip plane position
|
|
origin.xyz += direction.xyz * near / dot( direction, lookDirection );
|
|
|
|
rayOrigin = origin.xyz;
|
|
rayDirection = direction.xyz;
|
|
|
|
}
|
|
`
|
|
);
|
|
|
|
// node_modules/three-mesh-bvh/src/gpu/glsl/bvh_ray_functions.glsl.js
|
|
var bvh_ray_functions = (
|
|
/* glsl */
|
|
`
|
|
|
|
#ifndef TRI_INTERSECT_EPSILON
|
|
#define TRI_INTERSECT_EPSILON 1e-5
|
|
#endif
|
|
|
|
// Raycasting
|
|
bool intersectsBounds( vec3 rayOrigin, vec3 rayDirection, vec3 boundsMin, vec3 boundsMax, out float dist ) {
|
|
|
|
// https://www.reddit.com/r/opengl/comments/8ntzz5/fast_glsl_ray_box_intersection/
|
|
// https://tavianator.com/2011/ray_box.html
|
|
vec3 invDir = 1.0 / rayDirection;
|
|
|
|
// find intersection distances for each plane
|
|
vec3 tMinPlane = invDir * ( boundsMin - rayOrigin );
|
|
vec3 tMaxPlane = invDir * ( boundsMax - rayOrigin );
|
|
|
|
// get the min and max distances from each intersection
|
|
vec3 tMinHit = min( tMaxPlane, tMinPlane );
|
|
vec3 tMaxHit = max( tMaxPlane, tMinPlane );
|
|
|
|
// get the furthest hit distance
|
|
vec2 t = max( tMinHit.xx, tMinHit.yz );
|
|
float t0 = max( t.x, t.y );
|
|
|
|
// get the minimum hit distance
|
|
t = min( tMaxHit.xx, tMaxHit.yz );
|
|
float t1 = min( t.x, t.y );
|
|
|
|
// set distance to 0.0 if the ray starts inside the box
|
|
dist = max( t0, 0.0 );
|
|
|
|
return t1 >= dist;
|
|
|
|
}
|
|
|
|
bool intersectsTriangle(
|
|
vec3 rayOrigin, vec3 rayDirection, vec3 a, vec3 b, vec3 c,
|
|
out vec3 barycoord, out vec3 norm, out float dist, out float side
|
|
) {
|
|
|
|
// https://stackoverflow.com/questions/42740765/intersection-between-line-and-triangle-in-3d
|
|
vec3 edge1 = b - a;
|
|
vec3 edge2 = c - a;
|
|
norm = cross( edge1, edge2 );
|
|
|
|
float det = - dot( rayDirection, norm );
|
|
float invdet = 1.0 / det;
|
|
|
|
vec3 AO = rayOrigin - a;
|
|
vec3 DAO = cross( AO, rayDirection );
|
|
|
|
vec4 uvt;
|
|
uvt.x = dot( edge2, DAO ) * invdet;
|
|
uvt.y = - dot( edge1, DAO ) * invdet;
|
|
uvt.z = dot( AO, norm ) * invdet;
|
|
uvt.w = 1.0 - uvt.x - uvt.y;
|
|
|
|
// set the hit information
|
|
barycoord = uvt.wxy; // arranged in A, B, C order
|
|
dist = uvt.z;
|
|
side = sign( det );
|
|
norm = side * normalize( norm );
|
|
|
|
// add an epsilon to avoid misses between triangles
|
|
uvt += vec4( TRI_INTERSECT_EPSILON );
|
|
|
|
return all( greaterThanEqual( uvt, vec4( 0.0 ) ) );
|
|
|
|
}
|
|
|
|
bool intersectTriangles(
|
|
// geometry info and triangle range
|
|
sampler2D positionAttr, usampler2D indexAttr, uint offset, uint count,
|
|
|
|
// ray
|
|
vec3 rayOrigin, vec3 rayDirection,
|
|
|
|
// outputs
|
|
inout float minDistance, inout uvec4 faceIndices, inout vec3 faceNormal, inout vec3 barycoord,
|
|
inout float side, inout float dist
|
|
) {
|
|
|
|
bool found = false;
|
|
vec3 localBarycoord, localNormal;
|
|
float localDist, localSide;
|
|
for ( uint i = offset, l = offset + count; i < l; i ++ ) {
|
|
|
|
uvec3 indices = uTexelFetch1D( indexAttr, i ).xyz;
|
|
vec3 a = texelFetch1D( positionAttr, indices.x ).rgb;
|
|
vec3 b = texelFetch1D( positionAttr, indices.y ).rgb;
|
|
vec3 c = texelFetch1D( positionAttr, indices.z ).rgb;
|
|
|
|
if (
|
|
intersectsTriangle( rayOrigin, rayDirection, a, b, c, localBarycoord, localNormal, localDist, localSide )
|
|
&& localDist < minDistance
|
|
) {
|
|
|
|
found = true;
|
|
minDistance = localDist;
|
|
|
|
faceIndices = uvec4( indices.xyz, i );
|
|
faceNormal = localNormal;
|
|
|
|
side = localSide;
|
|
barycoord = localBarycoord;
|
|
dist = localDist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
bool intersectsBVHNodeBounds( vec3 rayOrigin, vec3 rayDirection, sampler2D bvhBounds, uint currNodeIndex, out float dist ) {
|
|
|
|
uint cni2 = currNodeIndex * 2u;
|
|
vec3 boundsMin = texelFetch1D( bvhBounds, cni2 ).xyz;
|
|
vec3 boundsMax = texelFetch1D( bvhBounds, cni2 + 1u ).xyz;
|
|
return intersectsBounds( rayOrigin, rayDirection, boundsMin, boundsMax, dist );
|
|
|
|
}
|
|
|
|
// use a macro to hide the fact that we need to expand the struct into separate fields
|
|
#define bvhIntersectFirstHit( bvh, rayOrigin, rayDirection, faceIndices, faceNormal, barycoord, side, dist ) _bvhIntersectFirstHit( bvh.position, bvh.index, bvh.bvhBounds, bvh.bvhContents, rayOrigin, rayDirection, faceIndices, faceNormal, barycoord, side, dist )
|
|
|
|
bool _bvhIntersectFirstHit(
|
|
// bvh info
|
|
sampler2D bvh_position, usampler2D bvh_index, sampler2D bvh_bvhBounds, usampler2D bvh_bvhContents,
|
|
|
|
// ray
|
|
vec3 rayOrigin, vec3 rayDirection,
|
|
|
|
// output variables split into separate variables due to output precision
|
|
inout uvec4 faceIndices, inout vec3 faceNormal, inout vec3 barycoord,
|
|
inout float side, inout float dist
|
|
) {
|
|
|
|
// stack needs to be twice as long as the deepest tree we expect because
|
|
// we push both the left and right child onto the stack every traversal
|
|
int ptr = 0;
|
|
uint stack[ BVH_STACK_DEPTH ];
|
|
stack[ 0 ] = 0u;
|
|
|
|
float triangleDistance = INFINITY;
|
|
bool found = false;
|
|
while ( ptr > - 1 && ptr < BVH_STACK_DEPTH ) {
|
|
|
|
uint currNodeIndex = stack[ ptr ];
|
|
ptr --;
|
|
|
|
// check if we intersect the current bounds
|
|
float boundsHitDistance;
|
|
if (
|
|
! intersectsBVHNodeBounds( rayOrigin, rayDirection, bvh_bvhBounds, currNodeIndex, boundsHitDistance )
|
|
|| boundsHitDistance > triangleDistance
|
|
) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
uvec2 boundsInfo = uTexelFetch1D( bvh_bvhContents, currNodeIndex ).xy;
|
|
bool isLeaf = bool( boundsInfo.x & 0xffff0000u );
|
|
|
|
if ( isLeaf ) {
|
|
|
|
uint count = boundsInfo.x & 0x0000ffffu;
|
|
uint offset = boundsInfo.y;
|
|
|
|
found = intersectTriangles(
|
|
bvh_position, bvh_index, offset, count,
|
|
rayOrigin, rayDirection, triangleDistance,
|
|
faceIndices, faceNormal, barycoord, side, dist
|
|
) || found;
|
|
|
|
} else {
|
|
|
|
uint leftIndex = currNodeIndex + 1u;
|
|
uint splitAxis = boundsInfo.x & 0x0000ffffu;
|
|
uint rightIndex = boundsInfo.y;
|
|
|
|
bool leftToRight = rayDirection[ splitAxis ] >= 0.0;
|
|
uint c1 = leftToRight ? leftIndex : rightIndex;
|
|
uint c2 = leftToRight ? rightIndex : leftIndex;
|
|
|
|
// set c2 in the stack so we traverse it later. We need to keep track of a pointer in
|
|
// the stack while we traverse. The second pointer added is the one that will be
|
|
// traversed first
|
|
ptr ++;
|
|
stack[ ptr ] = c2;
|
|
|
|
ptr ++;
|
|
stack[ ptr ] = c1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return found;
|
|
|
|
}
|
|
`
|
|
);
|
|
|
|
// node_modules/three-mesh-bvh/src/gpu/glsl/bvh_struct_definitions.glsl.js
|
|
var bvh_struct_definitions = (
|
|
/* glsl */
|
|
`
|
|
struct BVH {
|
|
|
|
usampler2D index;
|
|
sampler2D position;
|
|
|
|
sampler2D bvhBounds;
|
|
usampler2D bvhContents;
|
|
|
|
};
|
|
`
|
|
);
|
|
|
|
// node_modules/three-mesh-bvh/src/index.js
|
|
var shaderStructs = bvh_struct_definitions;
|
|
var shaderIntersectFunction = `
|
|
${common_functions}
|
|
${bvh_ray_functions}
|
|
`;
|
|
|
|
// node_modules/@react-three/drei/core/Bvh.js
|
|
var isMesh = (child) => child.isMesh;
|
|
function useBVH(mesh, options) {
|
|
options = {
|
|
strategy: SAH,
|
|
verbose: false,
|
|
setBoundingBox: true,
|
|
maxDepth: 40,
|
|
maxLeafTris: 10,
|
|
indirect: false,
|
|
...options
|
|
};
|
|
React71.useEffect(() => {
|
|
if (mesh.current) {
|
|
mesh.current.raycast = acceleratedRaycast;
|
|
const geometry3 = mesh.current.geometry;
|
|
geometry3.computeBoundsTree = computeBoundsTree;
|
|
geometry3.disposeBoundsTree = disposeBoundsTree;
|
|
geometry3.computeBoundsTree(options);
|
|
return () => {
|
|
if (geometry3.boundsTree) {
|
|
geometry3.disposeBoundsTree();
|
|
}
|
|
};
|
|
}
|
|
}, [mesh, JSON.stringify(options)]);
|
|
}
|
|
var Bvh = React71.forwardRef(({
|
|
enabled = true,
|
|
firstHitOnly = false,
|
|
children,
|
|
strategy = SAH,
|
|
verbose = false,
|
|
setBoundingBox = true,
|
|
maxDepth = 40,
|
|
maxLeafTris = 10,
|
|
indirect = false,
|
|
...props
|
|
}, fref) => {
|
|
const ref = React71.useRef(null);
|
|
const raycaster = useThree((state) => state.raycaster);
|
|
React71.useImperativeHandle(fref, () => ref.current, []);
|
|
React71.useEffect(() => {
|
|
if (enabled) {
|
|
const options = {
|
|
strategy,
|
|
verbose,
|
|
setBoundingBox,
|
|
maxDepth,
|
|
maxLeafTris,
|
|
indirect
|
|
};
|
|
const group = ref.current;
|
|
raycaster.firstHitOnly = firstHitOnly;
|
|
group.traverse((child) => {
|
|
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 React71.createElement("group", _extends({
|
|
ref
|
|
}, props), children);
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/useContextBridge.js
|
|
var React72 = __toESM(require_react());
|
|
function useContextBridge(...contexts) {
|
|
const cRef = React72.useRef([]);
|
|
cRef.current = contexts.map((context12) => React72.useContext(context12));
|
|
return React72.useMemo(() => ({
|
|
children
|
|
}) => contexts.reduceRight(
|
|
(acc, Context2, i3) => React72.createElement(Context2.Provider, {
|
|
value: cRef.current[i3],
|
|
children: acc
|
|
}),
|
|
children
|
|
/*
|
|
* done this way in reference to:
|
|
* https://github.com/DefinitelyTyped/DefinitelyTyped/issues/44572#issuecomment-625878049
|
|
* https://github.com/microsoft/TypeScript/issues/14729
|
|
*/
|
|
), []);
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/useAnimations.js
|
|
var React73 = __toESM(require_react());
|
|
function useAnimations(clips, root) {
|
|
const ref = React73.useRef(null);
|
|
const [actualRef] = React73.useState(() => root ? root instanceof Object3D ? {
|
|
current: root
|
|
} : root : ref);
|
|
const [mixer] = React73.useState(() => new AnimationMixer(void 0));
|
|
React73.useLayoutEffect(() => {
|
|
if (root) actualRef.current = root instanceof Object3D ? root : root.current;
|
|
mixer._root = actualRef.current;
|
|
});
|
|
const lazyActions = React73.useRef({});
|
|
const api = React73.useMemo(() => {
|
|
const actions = {};
|
|
clips.forEach((clip) => Object.defineProperty(actions, clip.name, {
|
|
enumerable: true,
|
|
get() {
|
|
if (actualRef.current) {
|
|
return lazyActions.current[clip.name] || (lazyActions.current[clip.name] = mixer.clipAction(clip, actualRef.current));
|
|
}
|
|
},
|
|
configurable: true
|
|
}));
|
|
return {
|
|
ref: actualRef,
|
|
clips,
|
|
actions,
|
|
names: clips.map((c2) => c2.name),
|
|
mixer
|
|
};
|
|
}, [clips]);
|
|
useFrame((state, delta) => mixer.update(delta));
|
|
React73.useEffect(() => {
|
|
const currentRoot = actualRef.current;
|
|
return () => {
|
|
lazyActions.current = {};
|
|
mixer.stopAllAction();
|
|
Object.values(api.actions).forEach((action) => {
|
|
if (currentRoot) {
|
|
mixer.uncacheAction(action, currentRoot);
|
|
}
|
|
});
|
|
};
|
|
}, [clips]);
|
|
return api;
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/useIntersect.js
|
|
var React74 = __toESM(require_react());
|
|
function useIntersect(onChange) {
|
|
const ref = React74.useRef(null);
|
|
const check = React74.useRef(false);
|
|
const temp5 = React74.useRef(false);
|
|
const callback = React74.useRef(onChange);
|
|
React74.useLayoutEffect(() => void (callback.current = onChange), [onChange]);
|
|
React74.useEffect(() => {
|
|
const obj = ref.current;
|
|
if (obj) {
|
|
const unsub1 = addEffect(() => {
|
|
check.current = false;
|
|
return true;
|
|
});
|
|
const oldOnRender = obj.onBeforeRender;
|
|
obj.onBeforeRender = () => check.current = true;
|
|
const unsub2 = addAfterEffect(() => {
|
|
if (check.current !== temp5.current) callback.current == null || callback.current(temp5.current = check.current);
|
|
return true;
|
|
});
|
|
return () => {
|
|
obj.onBeforeRender = oldOnRender;
|
|
unsub1();
|
|
unsub2();
|
|
};
|
|
}
|
|
}, []);
|
|
return ref;
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/useBoxProjectedEnv.js
|
|
var React75 = __toESM(require_react());
|
|
var worldposReplace = (
|
|
/* glsl */
|
|
`
|
|
#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )
|
|
vec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );
|
|
#ifdef BOX_PROJECTED_ENV_MAP
|
|
vWorldPosition = worldPosition.xyz;
|
|
#endif
|
|
#endif
|
|
`
|
|
);
|
|
var boxProjectDefinitions = (
|
|
/*glsl */
|
|
`
|
|
#ifdef BOX_PROJECTED_ENV_MAP
|
|
uniform vec3 envMapSize;
|
|
uniform vec3 envMapPosition;
|
|
varying vec3 vWorldPosition;
|
|
|
|
vec3 parallaxCorrectNormal( vec3 v, vec3 cubeSize, vec3 cubePos ) {
|
|
vec3 nDir = normalize( v );
|
|
vec3 rbmax = ( .5 * cubeSize + cubePos - vWorldPosition ) / nDir;
|
|
vec3 rbmin = ( -.5 * cubeSize + cubePos - vWorldPosition ) / nDir;
|
|
vec3 rbminmax;
|
|
rbminmax.x = ( nDir.x > 0. ) ? rbmax.x : rbmin.x;
|
|
rbminmax.y = ( nDir.y > 0. ) ? rbmax.y : rbmin.y;
|
|
rbminmax.z = ( nDir.z > 0. ) ? rbmax.z : rbmin.z;
|
|
float correction = min( min( rbminmax.x, rbminmax.y ), rbminmax.z );
|
|
vec3 boxIntersection = vWorldPosition + nDir * correction;
|
|
return boxIntersection - cubePos;
|
|
}
|
|
#endif
|
|
`
|
|
);
|
|
var getIBLIrradiance_patch = (
|
|
/* glsl */
|
|
`
|
|
#ifdef BOX_PROJECTED_ENV_MAP
|
|
worldNormal = parallaxCorrectNormal( worldNormal, envMapSize, envMapPosition );
|
|
#endif
|
|
`
|
|
);
|
|
var getIBLRadiance_patch = (
|
|
/* glsl */
|
|
`
|
|
#ifdef BOX_PROJECTED_ENV_MAP
|
|
reflectVec = parallaxCorrectNormal( reflectVec, envMapSize, envMapPosition );
|
|
#endif
|
|
`
|
|
);
|
|
function boxProjectedEnvMap(shader, envMapPosition, envMapSize) {
|
|
shader.defines.BOX_PROJECTED_ENV_MAP = true;
|
|
shader.uniforms.envMapPosition = {
|
|
value: envMapPosition
|
|
};
|
|
shader.uniforms.envMapSize = {
|
|
value: envMapSize
|
|
};
|
|
shader.vertexShader = `
|
|
varying vec3 vWorldPosition;
|
|
${shader.vertexShader.replace("#include <worldpos_vertex>", worldposReplace)}`;
|
|
shader.fragmentShader = `
|
|
${boxProjectDefinitions}
|
|
${shader.fragmentShader.replace("#include <envmap_physical_pars_fragment>", ShaderChunk.envmap_physical_pars_fragment).replace("vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );", `vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );
|
|
${getIBLIrradiance_patch}
|
|
`).replace("reflectVec = inverseTransformDirection( reflectVec, viewMatrix );", `reflectVec = inverseTransformDirection( reflectVec, viewMatrix );
|
|
${getIBLRadiance_patch}
|
|
`)}`;
|
|
}
|
|
function useBoxProjectedEnv(position2 = new Vector3(), size = new Vector3()) {
|
|
const [config] = React75.useState(() => ({
|
|
position: new Vector3(),
|
|
size: new Vector3()
|
|
}));
|
|
applyProps(config, {
|
|
position: position2,
|
|
size
|
|
});
|
|
const ref = React75.useRef(null);
|
|
const spread = React75.useMemo(() => ({
|
|
ref,
|
|
onBeforeCompile: (shader) => boxProjectedEnvMap(shader, config.position, config.size),
|
|
customProgramCacheKey: () => JSON.stringify(config.position.toArray()) + JSON.stringify(config.size.toArray())
|
|
}), [...config.position.toArray(), ...config.size.toArray()]);
|
|
React75.useLayoutEffect(() => void (ref.current.needsUpdate = true), [config]);
|
|
return spread;
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/BBAnchor.js
|
|
var React76 = __toESM(require_react());
|
|
var boundingBox4 = new Box3();
|
|
var boundingBoxSize = new Vector3();
|
|
var BBAnchor = ({
|
|
anchor,
|
|
...props
|
|
}) => {
|
|
const ref = React76.useRef(null);
|
|
const parentRef = React76.useRef(null);
|
|
React76.useEffect(() => {
|
|
var _ref$current;
|
|
if ((_ref$current = ref.current) != null && (_ref$current = _ref$current.parent) != null && _ref$current.parent) {
|
|
parentRef.current = ref.current.parent;
|
|
ref.current.parent.parent.add(ref.current);
|
|
}
|
|
}, []);
|
|
useFrame(() => {
|
|
if (parentRef.current) {
|
|
boundingBox4.setFromObject(parentRef.current);
|
|
boundingBox4.getSize(boundingBoxSize);
|
|
ref.current.position.set(parentRef.current.position.x + boundingBoxSize.x * (Array.isArray(anchor) ? anchor[0] : anchor.x) / 2, parentRef.current.position.y + boundingBoxSize.y * (Array.isArray(anchor) ? anchor[1] : anchor.y) / 2, parentRef.current.position.z + boundingBoxSize.z * (Array.isArray(anchor) ? anchor[2] : anchor.z) / 2);
|
|
}
|
|
});
|
|
return React76.createElement("group", _extends({
|
|
ref
|
|
}, props));
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/TrailTexture.js
|
|
var React77 = __toESM(require_react());
|
|
var import_react16 = __toESM(require_react());
|
|
function smoothAverage(current, measurement, smoothing = 0.9) {
|
|
return measurement * smoothing + current * (1 - smoothing);
|
|
}
|
|
var easeCircleOut = (x) => Math.sqrt(1 - Math.pow(x - 1, 2));
|
|
var TrailTextureImpl = class {
|
|
constructor({
|
|
size = 256,
|
|
maxAge = 750,
|
|
radius = 0.3,
|
|
intensity = 0.2,
|
|
interpolate = 0,
|
|
smoothing = 0,
|
|
minForce = 0.3,
|
|
blend = "screen",
|
|
// source-over is canvas default. Others are slower
|
|
ease = easeCircleOut
|
|
} = {}) {
|
|
this.size = size;
|
|
this.maxAge = maxAge;
|
|
this.radius = radius;
|
|
this.intensity = intensity;
|
|
this.ease = ease;
|
|
this.interpolate = interpolate;
|
|
this.smoothing = smoothing;
|
|
this.minForce = minForce;
|
|
this.blend = blend;
|
|
this.trail = [];
|
|
this.force = 0;
|
|
this.initTexture();
|
|
}
|
|
initTexture() {
|
|
this.canvas = document.createElement("canvas");
|
|
this.canvas.width = this.canvas.height = this.size;
|
|
const ctx = this.canvas.getContext("2d");
|
|
if (ctx === null) {
|
|
throw new Error("2D not available");
|
|
}
|
|
this.ctx = ctx;
|
|
this.ctx.fillStyle = "black";
|
|
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
|
this.texture = new Texture(this.canvas);
|
|
this.canvas.id = "touchTexture";
|
|
this.canvas.style.width = this.canvas.style.height = `${this.canvas.width}px`;
|
|
}
|
|
update(delta) {
|
|
this.clear();
|
|
this.trail.forEach((point, i3) => {
|
|
point.age += delta * 1e3;
|
|
if (point.age > this.maxAge) {
|
|
this.trail.splice(i3, 1);
|
|
}
|
|
});
|
|
if (!this.trail.length) this.force = 0;
|
|
this.trail.forEach((point) => {
|
|
this.drawTouch(point);
|
|
});
|
|
this.texture.needsUpdate = true;
|
|
}
|
|
clear() {
|
|
this.ctx.globalCompositeOperation = "source-over";
|
|
this.ctx.fillStyle = "black";
|
|
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
|
}
|
|
addTouch(point) {
|
|
const last = this.trail[this.trail.length - 1];
|
|
if (last) {
|
|
const dx = last.x - point.x;
|
|
const dy = last.y - point.y;
|
|
const dd = dx * dx + dy * dy;
|
|
const force = Math.max(this.minForce, Math.min(dd * 1e4, 1));
|
|
this.force = smoothAverage(force, this.force, this.smoothing);
|
|
if (!!this.interpolate) {
|
|
const lines = Math.ceil(dd / Math.pow(this.radius * 0.5 / this.interpolate, 2));
|
|
if (lines > 1) {
|
|
for (let i3 = 1; i3 < lines; i3++) {
|
|
this.trail.push({
|
|
x: last.x - dx / lines * i3,
|
|
y: last.y - dy / lines * i3,
|
|
age: 0,
|
|
force
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this.trail.push({
|
|
x: point.x,
|
|
y: point.y,
|
|
age: 0,
|
|
force: this.force
|
|
});
|
|
}
|
|
drawTouch(point) {
|
|
const pos = {
|
|
x: point.x * this.size,
|
|
y: (1 - point.y) * this.size
|
|
};
|
|
let intensity = 1;
|
|
if (point.age < this.maxAge * 0.3) {
|
|
intensity = this.ease(point.age / (this.maxAge * 0.3));
|
|
} else {
|
|
intensity = this.ease(1 - (point.age - this.maxAge * 0.3) / (this.maxAge * 0.7));
|
|
}
|
|
intensity *= point.force;
|
|
this.ctx.globalCompositeOperation = this.blend;
|
|
const radius = this.size * this.radius * intensity;
|
|
const grd = this.ctx.createRadialGradient(pos.x, pos.y, Math.max(0, radius * 0.25), pos.x, pos.y, Math.max(0, radius));
|
|
grd.addColorStop(0, `rgba(255, 255, 255, ${this.intensity})`);
|
|
grd.addColorStop(1, `rgba(0, 0, 0, 0.0)`);
|
|
this.ctx.beginPath();
|
|
this.ctx.fillStyle = grd;
|
|
this.ctx.arc(pos.x, pos.y, Math.max(0, radius), 0, Math.PI * 2);
|
|
this.ctx.fill();
|
|
}
|
|
};
|
|
function useTrailTexture(config = {}) {
|
|
const {
|
|
size,
|
|
maxAge,
|
|
radius,
|
|
intensity,
|
|
interpolate,
|
|
smoothing,
|
|
minForce,
|
|
blend,
|
|
ease
|
|
} = config;
|
|
const trail = (0, import_react16.useMemo)(() => new TrailTextureImpl(config), [size, maxAge, radius, intensity, interpolate, smoothing, minForce, blend, ease]);
|
|
useFrame((_, delta) => void trail.update(delta));
|
|
const onMove = (0, import_react16.useCallback)((e2) => trail.addTouch(e2.uv), [trail]);
|
|
return [trail.texture, onMove];
|
|
}
|
|
var TrailTexture = ({
|
|
children,
|
|
...config
|
|
}) => {
|
|
const ret = useTrailTexture(config);
|
|
return React77.createElement(React77.Fragment, null, children == null ? void 0 : children(ret));
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/Example.js
|
|
var React79 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/core/Center.js
|
|
var React78 = __toESM(require_react());
|
|
var Center = React78.forwardRef(function Center2({
|
|
children,
|
|
object,
|
|
disable,
|
|
disableX,
|
|
disableY,
|
|
disableZ,
|
|
left,
|
|
right,
|
|
top,
|
|
bottom,
|
|
front,
|
|
back,
|
|
onCentered,
|
|
precise = true,
|
|
cacheKey = 0,
|
|
...props
|
|
}, fRef) {
|
|
const ref = React78.useRef(null);
|
|
const outer = React78.useRef(null);
|
|
const inner = React78.useRef(null);
|
|
const [box3] = React78.useState(() => new Box3());
|
|
const [center2] = React78.useState(() => new Vector3());
|
|
const [sphere] = React78.useState(() => new Sphere());
|
|
React78.useLayoutEffect(() => {
|
|
outer.current.matrixWorld.identity();
|
|
box3.setFromObject(object !== null && object !== void 0 ? object : inner.current, precise);
|
|
const width = box3.max.x - box3.min.x;
|
|
const height = box3.max.y - box3.min.y;
|
|
const depth = box3.max.z - box3.min.z;
|
|
box3.getCenter(center2);
|
|
box3.getBoundingSphere(sphere);
|
|
const vAlign = top ? height / 2 : bottom ? -height / 2 : 0;
|
|
const hAlign = left ? -width / 2 : right ? width / 2 : 0;
|
|
const dAlign = front ? depth / 2 : back ? -depth / 2 : 0;
|
|
outer.current.position.set(disable || disableX ? 0 : -center2.x + hAlign, disable || disableY ? 0 : -center2.y + vAlign, disable || disableZ ? 0 : -center2.z + dAlign);
|
|
onCentered == null || onCentered({
|
|
parent: ref.current.parent,
|
|
container: ref.current,
|
|
width,
|
|
height,
|
|
depth,
|
|
boundingBox: box3,
|
|
boundingSphere: sphere,
|
|
center: center2,
|
|
verticalAlignment: vAlign,
|
|
horizontalAlignment: hAlign,
|
|
depthAlignment: dAlign
|
|
});
|
|
}, [cacheKey, onCentered, top, left, front, disable, disableX, disableY, disableZ, object, precise, right, bottom, back, box3, center2, sphere]);
|
|
React78.useImperativeHandle(fRef, () => ref.current, []);
|
|
return React78.createElement("group", _extends({
|
|
ref
|
|
}, props), React78.createElement("group", {
|
|
ref: outer
|
|
}, React78.createElement("group", {
|
|
ref: inner
|
|
}, children)));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Example.js
|
|
var Example = React79.forwardRef(({
|
|
font,
|
|
color = "#cbcbcb",
|
|
bevelSize = 0.04,
|
|
debug = false,
|
|
children,
|
|
...props
|
|
}, fref) => {
|
|
const [counter, setCounter] = React79.useState(0);
|
|
const incr = React79.useCallback((x = 1) => setCounter(counter + x), [counter]);
|
|
const decr = React79.useCallback((x = 1) => setCounter(counter - x), [counter]);
|
|
const api = React79.useMemo(() => ({
|
|
incr,
|
|
decr
|
|
}), [incr, decr]);
|
|
React79.useImperativeHandle(fref, () => api, [api]);
|
|
return React79.createElement("group", props, React79.createElement(React79.Suspense, {
|
|
fallback: null
|
|
}, React79.createElement(Center, {
|
|
top: true,
|
|
cacheKey: JSON.stringify({
|
|
counter,
|
|
font
|
|
})
|
|
}, React79.createElement(Text3D, {
|
|
bevelEnabled: true,
|
|
bevelSize,
|
|
font
|
|
}, debug ? React79.createElement("meshNormalMaterial", {
|
|
wireframe: true
|
|
}) : React79.createElement("meshStandardMaterial", {
|
|
color
|
|
}), counter))), children);
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/SpriteAnimator.js
|
|
var React81 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/core/Instances.js
|
|
var React80 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/helpers/deprecated.js
|
|
var setUpdateRange = (attribute, updateRange) => {
|
|
attribute.updateRanges[0] = updateRange;
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/Instances.js
|
|
function isFunctionChild(value) {
|
|
return typeof value === "function";
|
|
}
|
|
var _instanceLocalMatrix = new Matrix4();
|
|
var _instanceWorldMatrix = new Matrix4();
|
|
var _instanceIntersects = [];
|
|
var _mesh2 = new Mesh();
|
|
var PositionMesh = class extends Group {
|
|
constructor() {
|
|
super();
|
|
this.color = new Color("white");
|
|
this.instance = {
|
|
current: void 0
|
|
};
|
|
this.instanceKey = {
|
|
current: void 0
|
|
};
|
|
}
|
|
// This will allow the virtual instance have bounds
|
|
get geometry() {
|
|
var _this$instance$curren;
|
|
return (_this$instance$curren = this.instance.current) == null ? void 0 : _this$instance$curren.geometry;
|
|
}
|
|
// And this will allow the virtual instance to receive events
|
|
raycast(raycaster, intersects) {
|
|
const parent = this.instance.current;
|
|
if (!parent) return;
|
|
if (!parent.geometry || !parent.material) return;
|
|
_mesh2.geometry = parent.geometry;
|
|
const matrixWorld = parent.matrixWorld;
|
|
const instanceId = parent.userData.instances.indexOf(this.instanceKey);
|
|
if (instanceId === -1 || instanceId > parent.count) return;
|
|
parent.getMatrixAt(instanceId, _instanceLocalMatrix);
|
|
_instanceWorldMatrix.multiplyMatrices(matrixWorld, _instanceLocalMatrix);
|
|
_mesh2.matrixWorld = _instanceWorldMatrix;
|
|
if (parent.material instanceof Material) _mesh2.material.side = parent.material.side;
|
|
else _mesh2.material.side = parent.material[0].side;
|
|
_mesh2.raycast(raycaster, _instanceIntersects);
|
|
for (let i3 = 0, l2 = _instanceIntersects.length; i3 < l2; i3++) {
|
|
const intersect = _instanceIntersects[i3];
|
|
intersect.instanceId = instanceId;
|
|
intersect.object = this;
|
|
intersects.push(intersect);
|
|
}
|
|
_instanceIntersects.length = 0;
|
|
}
|
|
};
|
|
var globalContext2 = React80.createContext(null);
|
|
var parentMatrix = new Matrix4();
|
|
var instanceMatrix = new Matrix4();
|
|
var tempMatrix3 = new Matrix4();
|
|
var translation = new Vector3();
|
|
var rotation = new Quaternion();
|
|
var scale3 = new Vector3();
|
|
var isInstancedBufferAttribute = (attr) => attr.isInstancedBufferAttribute;
|
|
var Instance = React80.forwardRef(({
|
|
context: context12,
|
|
children,
|
|
...props
|
|
}, ref) => {
|
|
React80.useMemo(() => extend({
|
|
PositionMesh
|
|
}), []);
|
|
const group = React80.useRef(null);
|
|
React80.useImperativeHandle(ref, () => group.current, []);
|
|
const {
|
|
subscribe,
|
|
getParent
|
|
} = React80.useContext(context12 || globalContext2);
|
|
React80.useLayoutEffect(() => subscribe(group), []);
|
|
return React80.createElement("positionMesh", _extends({
|
|
instance: getParent(),
|
|
instanceKey: group,
|
|
ref: group
|
|
}, props), children);
|
|
});
|
|
var Instances = React80.forwardRef(({
|
|
context: context12,
|
|
children,
|
|
range,
|
|
limit = 1e3,
|
|
frames = Infinity,
|
|
...props
|
|
}, ref) => {
|
|
const [{
|
|
localContext,
|
|
instance
|
|
}] = React80.useState(() => {
|
|
const localContext2 = React80.createContext(null);
|
|
return {
|
|
localContext: localContext2,
|
|
instance: React80.forwardRef((props2, ref2) => React80.createElement(Instance, _extends({
|
|
context: localContext2
|
|
}, props2, {
|
|
ref: ref2
|
|
})))
|
|
};
|
|
});
|
|
const parentRef = React80.useRef(null);
|
|
React80.useImperativeHandle(ref, () => parentRef.current, []);
|
|
const [instances, setInstances] = React80.useState([]);
|
|
const [[matrices, colors2]] = React80.useState(() => {
|
|
const mArray = new Float32Array(limit * 16);
|
|
for (let i3 = 0; i3 < limit; i3++) tempMatrix3.identity().toArray(mArray, i3 * 16);
|
|
return [mArray, new Float32Array([...new Array(limit * 3)].map(() => 1))];
|
|
});
|
|
React80.useEffect(() => {
|
|
parentRef.current.instanceMatrix.needsUpdate = true;
|
|
});
|
|
let iterations = 0;
|
|
let count = 0;
|
|
const attributes = React80.useRef([]);
|
|
React80.useLayoutEffect(() => {
|
|
attributes.current = Object.entries(parentRef.current.geometry.attributes).filter(([_name, value]) => isInstancedBufferAttribute(value));
|
|
});
|
|
useFrame(() => {
|
|
if (frames === Infinity || iterations < frames) {
|
|
parentRef.current.updateMatrix();
|
|
parentRef.current.updateMatrixWorld();
|
|
parentMatrix.copy(parentRef.current.matrixWorld).invert();
|
|
count = Math.min(limit, range !== void 0 ? range : limit, instances.length);
|
|
parentRef.current.count = count;
|
|
setUpdateRange(parentRef.current.instanceMatrix, {
|
|
start: 0,
|
|
count: count * 16
|
|
});
|
|
setUpdateRange(parentRef.current.instanceColor, {
|
|
start: 0,
|
|
count: count * 3
|
|
});
|
|
for (let i3 = 0; i3 < instances.length; i3++) {
|
|
const instance2 = instances[i3].current;
|
|
instance2.matrixWorld.decompose(translation, rotation, scale3);
|
|
instanceMatrix.compose(translation, rotation, scale3).premultiply(parentMatrix);
|
|
instanceMatrix.toArray(matrices, i3 * 16);
|
|
parentRef.current.instanceMatrix.needsUpdate = true;
|
|
instance2.color.toArray(colors2, i3 * 3);
|
|
parentRef.current.instanceColor.needsUpdate = true;
|
|
}
|
|
iterations++;
|
|
}
|
|
});
|
|
const api = React80.useMemo(() => ({
|
|
getParent: () => parentRef,
|
|
subscribe: (ref2) => {
|
|
setInstances((instances2) => [...instances2, ref2]);
|
|
return () => setInstances((instances2) => instances2.filter((item) => item.current !== ref2.current));
|
|
}
|
|
}), []);
|
|
return React80.createElement("instancedMesh", _extends({
|
|
userData: {
|
|
instances,
|
|
limit,
|
|
frames
|
|
},
|
|
matrixAutoUpdate: false,
|
|
ref: parentRef,
|
|
args: [null, null, 0],
|
|
raycast: () => null
|
|
}, props), React80.createElement("instancedBufferAttribute", {
|
|
attach: "instanceMatrix",
|
|
args: [matrices, 16],
|
|
usage: DynamicDrawUsage
|
|
}), React80.createElement("instancedBufferAttribute", {
|
|
attach: "instanceColor",
|
|
args: [colors2, 3],
|
|
usage: DynamicDrawUsage
|
|
}), isFunctionChild(children) ? React80.createElement(localContext.Provider, {
|
|
value: api
|
|
}, children(instance)) : context12 ? React80.createElement(context12.Provider, {
|
|
value: api
|
|
}, children) : React80.createElement(globalContext2.Provider, {
|
|
value: api
|
|
}, children));
|
|
});
|
|
var Merged = React80.forwardRef(function Merged2({
|
|
meshes,
|
|
children,
|
|
...props
|
|
}, ref) {
|
|
const isArray3 = Array.isArray(meshes);
|
|
if (!isArray3) {
|
|
for (const key of Object.keys(meshes)) if (!meshes[key].isMesh) delete meshes[key];
|
|
}
|
|
const render = (args) => isArray3 ? (
|
|
// @ts-expect-error
|
|
children(...args)
|
|
) : children(
|
|
// @ts-expect-error
|
|
Object.keys(meshes).filter((key) => meshes[key].isMesh).reduce((acc, key, i3) => ({
|
|
...acc,
|
|
[key]: args[i3]
|
|
}), {})
|
|
);
|
|
const components = (isArray3 ? meshes : Object.values(meshes)).map(({
|
|
geometry: geometry3,
|
|
material
|
|
}) => React80.createElement(Instances, _extends({
|
|
key: geometry3.uuid,
|
|
geometry: geometry3,
|
|
material
|
|
}, props)));
|
|
return React80.createElement("group", {
|
|
ref
|
|
}, renderRecursive(render, components));
|
|
});
|
|
function renderRecursive(render, components, results = []) {
|
|
if (!components[0]) {
|
|
return render(results);
|
|
}
|
|
function nextRender(value) {
|
|
return renderRecursive(render, components.slice(1), results.concat([value]));
|
|
}
|
|
return typeof components[0] === "function" ? (
|
|
// When it is a function, produce an element by invoking it with "render component values".
|
|
components[0]({
|
|
results,
|
|
render: nextRender
|
|
})
|
|
) : (
|
|
// When it is an element, enhance the element's props with the render prop.
|
|
React80.cloneElement(components[0], {
|
|
children: nextRender
|
|
})
|
|
);
|
|
}
|
|
function createInstances() {
|
|
const context12 = React80.createContext(null);
|
|
return [React80.forwardRef((props, fref) => React80.createElement(Instances, _extends({
|
|
ref: fref,
|
|
context: context12
|
|
}, props))), React80.forwardRef((props, fref) => React80.createElement(Instance, _extends({
|
|
ref: fref,
|
|
context: context12
|
|
}, props)))];
|
|
}
|
|
var InstancedAttribute = React80.forwardRef(({
|
|
name,
|
|
defaultValue,
|
|
normalized,
|
|
usage = DynamicDrawUsage
|
|
}, fref) => {
|
|
const ref = React80.useRef(null);
|
|
React80.useImperativeHandle(fref, () => ref.current, []);
|
|
React80.useLayoutEffect(() => {
|
|
const parent = ref.current.__r3f.parent.object;
|
|
parent.geometry.attributes[name] = ref.current;
|
|
const value = Array.isArray(defaultValue) ? defaultValue : [defaultValue];
|
|
const array = Array.from({
|
|
length: parent.userData.limit
|
|
}, () => value).flat();
|
|
ref.current.array = new Float32Array(array);
|
|
ref.current.itemSize = value.length;
|
|
ref.current.count = array.length / ref.current.itemSize;
|
|
return () => {
|
|
delete parent.geometry.attributes[name];
|
|
};
|
|
}, [name]);
|
|
let iterations = 0;
|
|
useFrame(() => {
|
|
const parent = ref.current.__r3f.parent.object;
|
|
if (parent.userData.frames === Infinity || iterations < parent.userData.frames) {
|
|
for (let i3 = 0; i3 < parent.userData.instances.length; i3++) {
|
|
const instance = parent.userData.instances[i3].current;
|
|
const value = instance[name];
|
|
if (value !== void 0) {
|
|
ref.current.set(Array.isArray(value) ? value : typeof value.toArray === "function" ? value.toArray() : [value], i3 * ref.current.itemSize);
|
|
ref.current.needsUpdate = true;
|
|
}
|
|
}
|
|
iterations++;
|
|
}
|
|
});
|
|
return React80.createElement("instancedBufferAttribute", {
|
|
ref,
|
|
usage,
|
|
normalized
|
|
});
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/SpriteAnimator.js
|
|
var context5 = React81.createContext(null);
|
|
function useSpriteAnimator() {
|
|
return React81.useContext(context5);
|
|
}
|
|
function isSpriteData(data) {
|
|
return data !== null && "meta" in data && "frames" in data;
|
|
}
|
|
var geometry2 = new PlaneGeometry(1, 1);
|
|
var SpriteAnimator = React81.forwardRef(({
|
|
startFrame = 0,
|
|
endFrame,
|
|
fps = 30,
|
|
frameName = "",
|
|
textureDataURL,
|
|
textureImageURL,
|
|
loop = false,
|
|
numberOfFrames = 1,
|
|
autoPlay = true,
|
|
animationNames,
|
|
onStart,
|
|
onEnd,
|
|
onLoopEnd,
|
|
onFrame,
|
|
play,
|
|
pause = false,
|
|
flipX = false,
|
|
alphaTest = 0,
|
|
children,
|
|
asSprite = false,
|
|
offset,
|
|
playBackwards = false,
|
|
resetOnEnd = false,
|
|
maxItems = 1,
|
|
instanceItems = [[0, 0, 0]],
|
|
spriteDataset,
|
|
canvasRenderingContext2DSettings,
|
|
roundFramePosition = false,
|
|
meshProps = {},
|
|
...props
|
|
}, fref) => {
|
|
const ref = React81.useRef(new Group());
|
|
const spriteData = React81.useRef(null);
|
|
const matRef = React81.useRef(null);
|
|
const spriteRef = React81.useRef(null);
|
|
const timerOffset = React81.useRef(window.performance.now());
|
|
const currentFrame = React81.useRef(startFrame);
|
|
const currentFrameName = React81.useRef(frameName);
|
|
const fpsInterval = fps > 0 ? 1e3 / fps : 0;
|
|
const [spriteTexture, setSpriteTexture] = React81.useState(new Texture());
|
|
const totalFrames = React81.useRef(0);
|
|
const [aspect, setAspect] = React81.useState(new Vector3(1, 1, 1));
|
|
const flipOffset = flipX ? -1 : 1;
|
|
const pauseRef = React81.useRef(pause);
|
|
const pos = React81.useRef(offset);
|
|
const softEnd = React81.useRef(false);
|
|
const {
|
|
spriteObj,
|
|
loadJsonAndTexture
|
|
} = useSpriteLoader(null, null, animationNames, numberOfFrames, void 0, canvasRenderingContext2DSettings);
|
|
const frameNameRef = React81.useRef(frameName);
|
|
const parseSpriteDataLite = React81.useCallback((textureData, data) => {
|
|
if (data === null) {
|
|
if (numberOfFrames) {
|
|
totalFrames.current = numberOfFrames;
|
|
if (playBackwards) {
|
|
currentFrame.current = numberOfFrames - 1;
|
|
}
|
|
spriteData.current = data;
|
|
}
|
|
} else {
|
|
var _spriteData$current$f, _spriteData$current;
|
|
spriteData.current = data;
|
|
if (spriteData.current && Array.isArray(spriteData.current.frames)) {
|
|
totalFrames.current = spriteData.current.frames.length;
|
|
} else if (spriteData.current && typeof spriteData.current === "object" && frameNameRef.current) {
|
|
totalFrames.current = spriteData.current.frames[frameNameRef.current].length;
|
|
} else {
|
|
totalFrames.current = 0;
|
|
}
|
|
if (playBackwards) {
|
|
currentFrame.current = totalFrames.current - 1;
|
|
}
|
|
const {
|
|
w,
|
|
h
|
|
} = getFirstFrame((_spriteData$current$f = (_spriteData$current = spriteData.current) == null ? void 0 : _spriteData$current.frames) !== null && _spriteData$current$f !== void 0 ? _spriteData$current$f : [], frameNameRef.current).sourceSize;
|
|
const aspect2 = calculateAspectRatio(w, h);
|
|
setAspect(aspect2);
|
|
if (matRef.current) {
|
|
matRef.current.map = textureData;
|
|
}
|
|
}
|
|
setSpriteTexture(textureData);
|
|
}, [numberOfFrames, playBackwards]);
|
|
const modifySpritePosition = React81.useCallback(() => {
|
|
if (!spriteData.current) return;
|
|
const {
|
|
meta: {
|
|
size: metaInfo
|
|
},
|
|
frames
|
|
} = spriteData.current;
|
|
const {
|
|
w: frameW,
|
|
h: frameH
|
|
} = Array.isArray(frames) ? frames[0].sourceSize : frameName ? frames[frameName] ? frames[frameName][0].sourceSize : {
|
|
w: 0,
|
|
h: 0
|
|
} : {
|
|
w: 0,
|
|
h: 0
|
|
};
|
|
if (matRef.current && matRef.current.map) {
|
|
matRef.current.map.wrapS = matRef.current.map.wrapT = RepeatWrapping;
|
|
matRef.current.map.center.set(0, 0);
|
|
matRef.current.map.repeat.set(1 * flipOffset / (metaInfo.w / frameW), 1 / (metaInfo.h / frameH));
|
|
}
|
|
const framesV = (metaInfo.h - 1) / frameH;
|
|
const frameOffsetY = 1 / framesV;
|
|
if (matRef.current && matRef.current.map) {
|
|
matRef.current.map.offset.x = 0;
|
|
matRef.current.map.offset.y = 1 - frameOffsetY;
|
|
}
|
|
if (onStart) {
|
|
onStart({
|
|
currentFrameName: frameName !== null && frameName !== void 0 ? frameName : "",
|
|
currentFrame: currentFrame.current
|
|
});
|
|
}
|
|
}, [flipOffset, frameName, onStart]);
|
|
const state = React81.useMemo(() => ({
|
|
current: pos.current,
|
|
offset: pos.current,
|
|
imageUrl: textureImageURL,
|
|
hasEnded: false,
|
|
ref: fref
|
|
}), [textureImageURL, fref]);
|
|
React81.useImperativeHandle(fref, () => ref.current, []);
|
|
React81.useLayoutEffect(() => {
|
|
pos.current = offset;
|
|
}, [offset]);
|
|
const calculateAspectRatio = (width, height) => {
|
|
var _spriteRef$current;
|
|
const ret = new Vector3();
|
|
const aspectRatio = height / width;
|
|
ret.set(1, aspectRatio, 1);
|
|
(_spriteRef$current = spriteRef.current) == null || _spriteRef$current.scale.copy(ret);
|
|
return ret;
|
|
};
|
|
React81.useEffect(() => {
|
|
if (spriteDataset) {
|
|
var _spriteDataset$sprite;
|
|
parseSpriteDataLite(spriteDataset == null || (_spriteDataset$sprite = spriteDataset.spriteTexture) == null ? void 0 : _spriteDataset$sprite.clone(), spriteDataset.spriteData);
|
|
} else {
|
|
if (textureImageURL && textureDataURL) {
|
|
loadJsonAndTexture(textureImageURL, textureDataURL);
|
|
}
|
|
}
|
|
}, [loadJsonAndTexture, spriteDataset, textureDataURL, textureImageURL, parseSpriteDataLite]);
|
|
React81.useEffect(() => {
|
|
if (spriteObj) {
|
|
var _spriteObj$spriteText;
|
|
parseSpriteDataLite(spriteObj == null || (_spriteObj$spriteText = spriteObj.spriteTexture) == null ? void 0 : _spriteObj$spriteText.clone(), spriteObj == null ? void 0 : spriteObj.spriteData);
|
|
}
|
|
}, [spriteObj, parseSpriteDataLite]);
|
|
React81.useEffect(() => {
|
|
state.hasEnded = false;
|
|
if (spriteData.current && playBackwards === true) {
|
|
var _ref;
|
|
currentFrame.current = ((_ref = spriteData.current.frames.length) !== null && _ref !== void 0 ? _ref : 0) - 1;
|
|
} else {
|
|
currentFrame.current = 0;
|
|
}
|
|
}, [playBackwards, state]);
|
|
React81.useLayoutEffect(() => {
|
|
modifySpritePosition();
|
|
}, [spriteTexture, flipX, modifySpritePosition]);
|
|
React81.useEffect(() => {
|
|
if (autoPlay) {
|
|
pauseRef.current = false;
|
|
}
|
|
}, [autoPlay]);
|
|
React81.useLayoutEffect(() => {
|
|
if (currentFrameName.current !== frameName && frameName) {
|
|
currentFrame.current = 0;
|
|
currentFrameName.current = frameName;
|
|
state.hasEnded = false;
|
|
if (fpsInterval <= 0) {
|
|
currentFrame.current = endFrame || startFrame || 0;
|
|
}
|
|
if (spriteData.current) {
|
|
const {
|
|
w,
|
|
h
|
|
} = getFirstFrame(spriteData.current.frames, frameName).sourceSize;
|
|
const _aspect = calculateAspectRatio(w, h);
|
|
setAspect(_aspect);
|
|
}
|
|
}
|
|
}, [frameName, fpsInterval, state, endFrame, startFrame]);
|
|
const runAnimation = () => {
|
|
if (!isSpriteData(spriteData.current)) return;
|
|
const {
|
|
meta: {
|
|
size: metaInfo
|
|
},
|
|
frames
|
|
} = spriteData.current;
|
|
const {
|
|
w: frameW,
|
|
h: frameH
|
|
} = getFirstFrame(frames, frameName).sourceSize;
|
|
const spriteFrames = Array.isArray(frames) ? frames : frameName ? frames[frameName] : [];
|
|
const _endFrame = endFrame || spriteFrames.length - 1;
|
|
var _offset = offset === void 0 ? state.current : offset;
|
|
if (fpsInterval <= 0) {
|
|
currentFrame.current = endFrame || startFrame || 0;
|
|
calculateFinalPosition(frameW, frameH, metaInfo, spriteFrames);
|
|
return;
|
|
}
|
|
const now2 = window.performance.now();
|
|
const diff = now2 - timerOffset.current;
|
|
if (diff <= fpsInterval) return;
|
|
var endCondition = playBackwards ? currentFrame.current < 0 : currentFrame.current > _endFrame;
|
|
var onStartCondition = playBackwards ? currentFrame.current === _endFrame : currentFrame.current === 0;
|
|
var manualProgressEndCondition = playBackwards ? currentFrame.current < 0 : currentFrame.current >= _endFrame;
|
|
if (endCondition) {
|
|
currentFrame.current = loop ? startFrame !== null && startFrame !== void 0 ? startFrame : 0 : 0;
|
|
if (playBackwards) {
|
|
currentFrame.current = _endFrame;
|
|
}
|
|
if (loop) {
|
|
onLoopEnd == null || onLoopEnd({
|
|
currentFrameName: frameName !== null && frameName !== void 0 ? frameName : "",
|
|
currentFrame: currentFrame.current
|
|
});
|
|
} else {
|
|
onEnd == null || onEnd({
|
|
currentFrameName: frameName !== null && frameName !== void 0 ? frameName : "",
|
|
currentFrame: currentFrame.current
|
|
});
|
|
state.hasEnded = !resetOnEnd;
|
|
if (resetOnEnd) {
|
|
pauseRef.current = true;
|
|
}
|
|
}
|
|
if (!loop) return;
|
|
} else if (onStartCondition) {
|
|
onStart == null || onStart({
|
|
currentFrameName: frameName !== null && frameName !== void 0 ? frameName : "",
|
|
currentFrame: currentFrame.current
|
|
});
|
|
}
|
|
if (_offset !== void 0 && manualProgressEndCondition) {
|
|
if (softEnd.current === false) {
|
|
onEnd == null || onEnd({
|
|
currentFrameName: frameName !== null && frameName !== void 0 ? frameName : "",
|
|
currentFrame: currentFrame.current
|
|
});
|
|
softEnd.current = true;
|
|
}
|
|
} else {
|
|
softEnd.current = false;
|
|
}
|
|
if (diff <= fpsInterval) return;
|
|
timerOffset.current = now2 - diff % fpsInterval;
|
|
calculateFinalPosition(frameW, frameH, metaInfo, spriteFrames);
|
|
};
|
|
const calculateFinalPosition = (frameW, frameH, metaInfo, spriteFrames) => {
|
|
var _offset = offset === void 0 ? state.current : offset;
|
|
const targetFrame = currentFrame.current;
|
|
let finalValX = 0;
|
|
let finalValY = 0;
|
|
calculateAspectRatio(frameW, frameH);
|
|
const framesH = roundFramePosition ? Math.round((metaInfo.w - 1) / frameW) : (metaInfo.w - 1) / frameW;
|
|
const framesV = roundFramePosition ? Math.round((metaInfo.h - 1) / frameH) : (metaInfo.h - 1) / frameH;
|
|
if (!spriteFrames[targetFrame]) {
|
|
return;
|
|
}
|
|
const {
|
|
frame: {
|
|
x: frameX,
|
|
y: frameY
|
|
},
|
|
sourceSize: {
|
|
w: originalSizeX,
|
|
h: originalSizeY
|
|
}
|
|
} = spriteFrames[targetFrame];
|
|
const frameOffsetX = 1 / framesH;
|
|
const frameOffsetY = 1 / framesV;
|
|
if (matRef.current && matRef.current.map) {
|
|
finalValX = flipOffset > 0 ? frameOffsetX * (frameX / originalSizeX) : frameOffsetX * (frameX / originalSizeX) - matRef.current.map.repeat.x;
|
|
finalValY = Math.abs(1 - frameOffsetY) - frameOffsetY * (frameY / originalSizeY);
|
|
matRef.current.map.offset.x = finalValX;
|
|
matRef.current.map.offset.y = finalValY;
|
|
}
|
|
if (_offset !== void 0 && _offset !== null) {
|
|
let frameIndex = Math.floor(_offset * spriteFrames.length);
|
|
frameIndex = Math.max(0, Math.min(frameIndex, spriteFrames.length - 1));
|
|
if (isNaN(frameIndex)) {
|
|
frameIndex = 0;
|
|
}
|
|
currentFrame.current = frameIndex;
|
|
} else {
|
|
if (playBackwards) {
|
|
currentFrame.current -= 1;
|
|
} else {
|
|
currentFrame.current += 1;
|
|
}
|
|
}
|
|
};
|
|
useFrame((_state, _delta) => {
|
|
var _spriteData$current2, _matRef$current;
|
|
if (!((_spriteData$current2 = spriteData.current) != null && _spriteData$current2.frames) || !((_matRef$current = matRef.current) != null && _matRef$current.map)) {
|
|
return;
|
|
}
|
|
if (pauseRef.current) {
|
|
return;
|
|
}
|
|
if (!state.hasEnded && (autoPlay || play)) {
|
|
runAnimation();
|
|
onFrame == null || onFrame({
|
|
currentFrameName: currentFrameName.current,
|
|
currentFrame: currentFrame.current
|
|
});
|
|
}
|
|
});
|
|
function multiplyScale(initialScale = new Vector3(1, 1, 1), newScale = 1) {
|
|
if (typeof newScale === "number") return initialScale.multiplyScalar(newScale);
|
|
if (Array.isArray(newScale)) return initialScale.multiply(new Vector3(...newScale));
|
|
if (newScale instanceof Vector3) return initialScale.multiply(newScale);
|
|
}
|
|
return React81.createElement("group", _extends({}, props, {
|
|
ref,
|
|
scale: multiplyScale(aspect, props.scale)
|
|
}), React81.createElement(context5.Provider, {
|
|
value: state
|
|
}, asSprite && React81.createElement(Billboard, null, React81.createElement("mesh", _extends({
|
|
ref: spriteRef,
|
|
scale: 1,
|
|
geometry: geometry2
|
|
}, meshProps), React81.createElement("meshBasicMaterial", {
|
|
premultipliedAlpha: false,
|
|
toneMapped: false,
|
|
side: DoubleSide,
|
|
ref: matRef,
|
|
map: spriteTexture,
|
|
transparent: true,
|
|
alphaTest: alphaTest !== null && alphaTest !== void 0 ? alphaTest : 0
|
|
}))), !asSprite && React81.createElement(Instances, _extends({
|
|
geometry: geometry2,
|
|
limit: maxItems !== null && maxItems !== void 0 ? maxItems : 1
|
|
}, meshProps), React81.createElement("meshBasicMaterial", {
|
|
premultipliedAlpha: false,
|
|
toneMapped: false,
|
|
side: DoubleSide,
|
|
ref: matRef,
|
|
map: spriteTexture,
|
|
transparent: true,
|
|
alphaTest: alphaTest !== null && alphaTest !== void 0 ? alphaTest : 0
|
|
}), (instanceItems !== null && instanceItems !== void 0 ? instanceItems : [0]).map((item, index2) => React81.createElement(Instance, _extends({
|
|
key: index2,
|
|
ref: (instanceItems == null ? void 0 : instanceItems.length) === 1 ? spriteRef : null,
|
|
position: item,
|
|
scale: 1
|
|
}, meshProps)))), children));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/CurveModifier.js
|
|
var React82 = __toESM(require_react());
|
|
var CurveModifier = React82.forwardRef(({
|
|
children,
|
|
curve
|
|
}, ref) => {
|
|
const [scene] = React82.useState(() => new Scene());
|
|
const [obj, set] = React82.useState();
|
|
const modifier = React82.useRef(null);
|
|
React82.useLayoutEffect(() => {
|
|
modifier.current = new Flow(scene.children[0]);
|
|
set(modifier.current.object3D);
|
|
}, [children]);
|
|
React82.useEffect(() => {
|
|
var _modifier$current;
|
|
if (curve) (_modifier$current = modifier.current) == null || _modifier$current.updateCurve(0, curve);
|
|
}, [curve]);
|
|
React82.useImperativeHandle(ref, () => modifier.current);
|
|
return React82.createElement(React82.Fragment, null, createPortal(children, scene), obj && React82.createElement("primitive", {
|
|
object: obj
|
|
}));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/MeshDistortMaterial.js
|
|
var React83 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/helpers/glsl/distort.vert.glsl.js
|
|
var distort = "#define GLSLIFY 1\nvec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 permute(vec4 x){return mod289(((x*34.0)+1.0)*x);}vec4 taylorInvSqrt(vec4 r){return 1.79284291400159-0.85373472095314*r;}float snoise(vec3 v){const vec2 C=vec2(1.0/6.0,1.0/3.0);const vec4 D=vec4(0.0,0.5,1.0,2.0);vec3 i=floor(v+dot(v,C.yyy));vec3 x0=v-i+dot(i,C.xxx);vec3 g=step(x0.yzx,x0.xyz);vec3 l=1.0-g;vec3 i1=min(g.xyz,l.zxy);vec3 i2=max(g.xyz,l.zxy);vec3 x1=x0-i1+C.xxx;vec3 x2=x0-i2+C.yyy;vec3 x3=x0-D.yyy;i=mod289(i);vec4 p=permute(permute(permute(i.z+vec4(0.0,i1.z,i2.z,1.0))+i.y+vec4(0.0,i1.y,i2.y,1.0))+i.x+vec4(0.0,i1.x,i2.x,1.0));float n_=0.142857142857;vec3 ns=n_*D.wyz-D.xzx;vec4 j=p-49.0*floor(p*ns.z*ns.z);vec4 x_=floor(j*ns.z);vec4 y_=floor(j-7.0*x_);vec4 x=x_*ns.x+ns.yyyy;vec4 y=y_*ns.x+ns.yyyy;vec4 h=1.0-abs(x)-abs(y);vec4 b0=vec4(x.xy,y.xy);vec4 b1=vec4(x.zw,y.zw);vec4 s0=floor(b0)*2.0+1.0;vec4 s1=floor(b1)*2.0+1.0;vec4 sh=-step(h,vec4(0.0));vec4 a0=b0.xzyw+s0.xzyw*sh.xxyy;vec4 a1=b1.xzyw+s1.xzyw*sh.zzww;vec3 p0=vec3(a0.xy,h.x);vec3 p1=vec3(a0.zw,h.y);vec3 p2=vec3(a1.xy,h.z);vec3 p3=vec3(a1.zw,h.w);vec4 norm=taylorInvSqrt(vec4(dot(p0,p0),dot(p1,p1),dot(p2,p2),dot(p3,p3)));p0*=norm.x;p1*=norm.y;p2*=norm.z;p3*=norm.w;vec4 m=max(0.6-vec4(dot(x0,x0),dot(x1,x1),dot(x2,x2),dot(x3,x3)),0.0);m=m*m;return 42.0*dot(m*m,vec4(dot(p0,x0),dot(p1,x1),dot(p2,x2),dot(p3,x3)));}";
|
|
|
|
// node_modules/@react-three/drei/core/MeshDistortMaterial.js
|
|
var DistortMaterialImpl = class extends MeshPhysicalMaterial {
|
|
constructor(parameters = {}) {
|
|
super(parameters);
|
|
this.setValues(parameters);
|
|
this._time = {
|
|
value: 0
|
|
};
|
|
this._distort = {
|
|
value: 0.4
|
|
};
|
|
this._radius = {
|
|
value: 1
|
|
};
|
|
}
|
|
// FIXME Use `THREE.WebGLProgramParametersWithUniforms` type when able to target @types/three@0.160.0
|
|
onBeforeCompile(shader) {
|
|
shader.uniforms.time = this._time;
|
|
shader.uniforms.radius = this._radius;
|
|
shader.uniforms.distort = this._distort;
|
|
shader.vertexShader = `
|
|
uniform float time;
|
|
uniform float radius;
|
|
uniform float distort;
|
|
${distort}
|
|
${shader.vertexShader}
|
|
`;
|
|
shader.vertexShader = shader.vertexShader.replace("#include <begin_vertex>", `
|
|
float updateTime = time / 50.0;
|
|
float noise = snoise(vec3(position / 2.0 + updateTime * 5.0));
|
|
vec3 transformed = vec3(position * (noise * pow(distort, 2.0) + radius));
|
|
`);
|
|
}
|
|
get time() {
|
|
return this._time.value;
|
|
}
|
|
set time(v5) {
|
|
this._time.value = v5;
|
|
}
|
|
get distort() {
|
|
return this._distort.value;
|
|
}
|
|
set distort(v5) {
|
|
this._distort.value = v5;
|
|
}
|
|
get radius() {
|
|
return this._radius.value;
|
|
}
|
|
set radius(v5) {
|
|
this._radius.value = v5;
|
|
}
|
|
};
|
|
var MeshDistortMaterial = React83.forwardRef(({
|
|
speed = 1,
|
|
...props
|
|
}, ref) => {
|
|
const [material] = React83.useState(() => new DistortMaterialImpl());
|
|
useFrame((state) => material && (material.time = state.clock.elapsedTime * speed));
|
|
return React83.createElement("primitive", _extends({
|
|
object: material,
|
|
ref,
|
|
attach: "material"
|
|
}, props));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/MeshWobbleMaterial.js
|
|
var React84 = __toESM(require_react());
|
|
var WobbleMaterialImpl = class extends MeshStandardMaterial {
|
|
constructor(parameters = {}) {
|
|
super(parameters);
|
|
this.setValues(parameters);
|
|
this._time = {
|
|
value: 0
|
|
};
|
|
this._factor = {
|
|
value: 1
|
|
};
|
|
}
|
|
// FIXME Use `THREE.WebGLProgramParametersWithUniforms` type when able to target @types/three@0.160.0
|
|
onBeforeCompile(shader) {
|
|
shader.uniforms.time = this._time;
|
|
shader.uniforms.factor = this._factor;
|
|
shader.vertexShader = `
|
|
uniform float time;
|
|
uniform float factor;
|
|
${shader.vertexShader}
|
|
`;
|
|
shader.vertexShader = shader.vertexShader.replace("#include <begin_vertex>", `float theta = sin( time + position.y ) / 2.0 * factor;
|
|
float c = cos( theta );
|
|
float s = sin( theta );
|
|
mat3 m = mat3( c, 0, s, 0, 1, 0, -s, 0, c );
|
|
vec3 transformed = vec3( position ) * m;
|
|
vNormal = vNormal * m;`);
|
|
}
|
|
get time() {
|
|
return this._time.value;
|
|
}
|
|
set time(v5) {
|
|
this._time.value = v5;
|
|
}
|
|
get factor() {
|
|
return this._factor.value;
|
|
}
|
|
set factor(v5) {
|
|
this._factor.value = v5;
|
|
}
|
|
};
|
|
var MeshWobbleMaterial = React84.forwardRef(({
|
|
speed = 1,
|
|
...props
|
|
}, ref) => {
|
|
const [material] = React84.useState(() => new WobbleMaterialImpl());
|
|
useFrame((state) => material && (material.time = state.clock.elapsedTime * speed));
|
|
return React84.createElement("primitive", _extends({
|
|
object: material,
|
|
ref,
|
|
attach: "material"
|
|
}, props));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/MeshReflectorMaterial.js
|
|
var React85 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/materials/ConvolutionMaterial.js
|
|
var ConvolutionMaterial = class extends ShaderMaterial {
|
|
constructor(texelSize = new Vector2()) {
|
|
super({
|
|
uniforms: {
|
|
inputBuffer: new Uniform(null),
|
|
depthBuffer: new Uniform(null),
|
|
resolution: new Uniform(new Vector2()),
|
|
texelSize: new Uniform(new Vector2()),
|
|
halfTexelSize: new Uniform(new Vector2()),
|
|
kernel: new Uniform(0),
|
|
scale: new Uniform(1),
|
|
cameraNear: new Uniform(0),
|
|
cameraFar: new Uniform(1),
|
|
minDepthThreshold: new Uniform(0),
|
|
maxDepthThreshold: new Uniform(1),
|
|
depthScale: new Uniform(0),
|
|
depthToBlurRatioBias: new Uniform(0.25)
|
|
},
|
|
fragmentShader: `#include <common>
|
|
#include <dithering_pars_fragment>
|
|
uniform sampler2D inputBuffer;
|
|
uniform sampler2D depthBuffer;
|
|
uniform float cameraNear;
|
|
uniform float cameraFar;
|
|
uniform float minDepthThreshold;
|
|
uniform float maxDepthThreshold;
|
|
uniform float depthScale;
|
|
uniform float depthToBlurRatioBias;
|
|
varying vec2 vUv;
|
|
varying vec2 vUv0;
|
|
varying vec2 vUv1;
|
|
varying vec2 vUv2;
|
|
varying vec2 vUv3;
|
|
|
|
void main() {
|
|
float depthFactor = 0.0;
|
|
|
|
#ifdef USE_DEPTH
|
|
vec4 depth = texture2D(depthBuffer, vUv);
|
|
depthFactor = smoothstep(minDepthThreshold, maxDepthThreshold, 1.0-(depth.r * depth.a));
|
|
depthFactor *= depthScale;
|
|
depthFactor = max(0.0, min(1.0, depthFactor + 0.25));
|
|
#endif
|
|
|
|
vec4 sum = texture2D(inputBuffer, mix(vUv0, vUv, depthFactor));
|
|
sum += texture2D(inputBuffer, mix(vUv1, vUv, depthFactor));
|
|
sum += texture2D(inputBuffer, mix(vUv2, vUv, depthFactor));
|
|
sum += texture2D(inputBuffer, mix(vUv3, vUv, depthFactor));
|
|
gl_FragColor = sum * 0.25 ;
|
|
|
|
#include <dithering_fragment>
|
|
#include <tonemapping_fragment>
|
|
#include <${version >= 154 ? "colorspace_fragment" : "encodings_fragment"}>
|
|
}`,
|
|
vertexShader: `uniform vec2 texelSize;
|
|
uniform vec2 halfTexelSize;
|
|
uniform float kernel;
|
|
uniform float scale;
|
|
varying vec2 vUv;
|
|
varying vec2 vUv0;
|
|
varying vec2 vUv1;
|
|
varying vec2 vUv2;
|
|
varying vec2 vUv3;
|
|
|
|
void main() {
|
|
vec2 uv = position.xy * 0.5 + 0.5;
|
|
vUv = uv;
|
|
|
|
vec2 dUv = (texelSize * vec2(kernel) + halfTexelSize) * scale;
|
|
vUv0 = vec2(uv.x - dUv.x, uv.y + dUv.y);
|
|
vUv1 = vec2(uv.x + dUv.x, uv.y + dUv.y);
|
|
vUv2 = vec2(uv.x + dUv.x, uv.y - dUv.y);
|
|
vUv3 = vec2(uv.x - dUv.x, uv.y - dUv.y);
|
|
|
|
gl_Position = vec4(position.xy, 1.0, 1.0);
|
|
}`,
|
|
blending: NoBlending,
|
|
depthWrite: false,
|
|
depthTest: false
|
|
});
|
|
this.toneMapped = false;
|
|
this.setTexelSize(texelSize.x, texelSize.y);
|
|
this.kernel = new Float32Array([0, 1, 2, 2, 3]);
|
|
}
|
|
setTexelSize(x, y) {
|
|
this.uniforms.texelSize.value.set(x, y);
|
|
this.uniforms.halfTexelSize.value.set(x, y).multiplyScalar(0.5);
|
|
}
|
|
setResolution(resolution) {
|
|
this.uniforms.resolution.value.copy(resolution);
|
|
}
|
|
};
|
|
|
|
// node_modules/@react-three/drei/materials/BlurPass.js
|
|
var BlurPass = class {
|
|
constructor({
|
|
gl,
|
|
resolution,
|
|
width = 500,
|
|
height = 500,
|
|
minDepthThreshold = 0,
|
|
maxDepthThreshold = 1,
|
|
depthScale = 0,
|
|
depthToBlurRatioBias = 0.25
|
|
}) {
|
|
this.renderToScreen = false;
|
|
this.renderTargetA = new WebGLRenderTarget(resolution, resolution, {
|
|
minFilter: LinearFilter,
|
|
magFilter: LinearFilter,
|
|
stencilBuffer: false,
|
|
depthBuffer: false,
|
|
type: HalfFloatType
|
|
});
|
|
this.renderTargetB = this.renderTargetA.clone();
|
|
this.convolutionMaterial = new ConvolutionMaterial();
|
|
this.convolutionMaterial.setTexelSize(1 / width, 1 / height);
|
|
this.convolutionMaterial.setResolution(new Vector2(width, height));
|
|
this.scene = new Scene();
|
|
this.camera = new Camera();
|
|
this.convolutionMaterial.uniforms.minDepthThreshold.value = minDepthThreshold;
|
|
this.convolutionMaterial.uniforms.maxDepthThreshold.value = maxDepthThreshold;
|
|
this.convolutionMaterial.uniforms.depthScale.value = depthScale;
|
|
this.convolutionMaterial.uniforms.depthToBlurRatioBias.value = depthToBlurRatioBias;
|
|
this.convolutionMaterial.defines.USE_DEPTH = depthScale > 0;
|
|
const vertices = new Float32Array([-1, -1, 0, 3, -1, 0, -1, 3, 0]);
|
|
const uvs = new Float32Array([0, 0, 2, 0, 0, 2]);
|
|
const geometry3 = new BufferGeometry();
|
|
geometry3.setAttribute("position", new BufferAttribute(vertices, 3));
|
|
geometry3.setAttribute("uv", new BufferAttribute(uvs, 2));
|
|
this.screen = new Mesh(geometry3, this.convolutionMaterial);
|
|
this.screen.frustumCulled = false;
|
|
this.scene.add(this.screen);
|
|
}
|
|
render(renderer, inputBuffer, outputBuffer) {
|
|
const scene = this.scene;
|
|
const camera = this.camera;
|
|
const renderTargetA = this.renderTargetA;
|
|
const renderTargetB = this.renderTargetB;
|
|
let material = this.convolutionMaterial;
|
|
let uniforms = material.uniforms;
|
|
uniforms.depthBuffer.value = inputBuffer.depthTexture;
|
|
const kernel = material.kernel;
|
|
let lastRT = inputBuffer;
|
|
let destRT;
|
|
let i3, l2;
|
|
for (i3 = 0, l2 = kernel.length - 1; i3 < l2; ++i3) {
|
|
destRT = (i3 & 1) === 0 ? renderTargetA : renderTargetB;
|
|
uniforms.kernel.value = kernel[i3];
|
|
uniforms.inputBuffer.value = lastRT.texture;
|
|
renderer.setRenderTarget(destRT);
|
|
renderer.render(scene, camera);
|
|
lastRT = destRT;
|
|
}
|
|
uniforms.kernel.value = kernel[i3];
|
|
uniforms.inputBuffer.value = lastRT.texture;
|
|
renderer.setRenderTarget(this.renderToScreen ? null : outputBuffer);
|
|
renderer.render(scene, camera);
|
|
}
|
|
};
|
|
|
|
// node_modules/@react-three/drei/materials/MeshReflectorMaterial.js
|
|
var MeshReflectorMaterial = class extends MeshStandardMaterial {
|
|
constructor(parameters = {}) {
|
|
super(parameters);
|
|
this._tDepth = {
|
|
value: null
|
|
};
|
|
this._distortionMap = {
|
|
value: null
|
|
};
|
|
this._tDiffuse = {
|
|
value: null
|
|
};
|
|
this._tDiffuseBlur = {
|
|
value: null
|
|
};
|
|
this._textureMatrix = {
|
|
value: null
|
|
};
|
|
this._hasBlur = {
|
|
value: false
|
|
};
|
|
this._mirror = {
|
|
value: 0
|
|
};
|
|
this._mixBlur = {
|
|
value: 0
|
|
};
|
|
this._blurStrength = {
|
|
value: 0.5
|
|
};
|
|
this._minDepthThreshold = {
|
|
value: 0.9
|
|
};
|
|
this._maxDepthThreshold = {
|
|
value: 1
|
|
};
|
|
this._depthScale = {
|
|
value: 0
|
|
};
|
|
this._depthToBlurRatioBias = {
|
|
value: 0.25
|
|
};
|
|
this._distortion = {
|
|
value: 1
|
|
};
|
|
this._mixContrast = {
|
|
value: 1
|
|
};
|
|
this.setValues(parameters);
|
|
}
|
|
onBeforeCompile(shader) {
|
|
var _shader$defines;
|
|
if (!((_shader$defines = shader.defines) != null && _shader$defines.USE_UV)) {
|
|
shader.defines.USE_UV = "";
|
|
}
|
|
shader.uniforms.hasBlur = this._hasBlur;
|
|
shader.uniforms.tDiffuse = this._tDiffuse;
|
|
shader.uniforms.tDepth = this._tDepth;
|
|
shader.uniforms.distortionMap = this._distortionMap;
|
|
shader.uniforms.tDiffuseBlur = this._tDiffuseBlur;
|
|
shader.uniforms.textureMatrix = this._textureMatrix;
|
|
shader.uniforms.mirror = this._mirror;
|
|
shader.uniforms.mixBlur = this._mixBlur;
|
|
shader.uniforms.mixStrength = this._blurStrength;
|
|
shader.uniforms.minDepthThreshold = this._minDepthThreshold;
|
|
shader.uniforms.maxDepthThreshold = this._maxDepthThreshold;
|
|
shader.uniforms.depthScale = this._depthScale;
|
|
shader.uniforms.depthToBlurRatioBias = this._depthToBlurRatioBias;
|
|
shader.uniforms.distortion = this._distortion;
|
|
shader.uniforms.mixContrast = this._mixContrast;
|
|
shader.vertexShader = `
|
|
uniform mat4 textureMatrix;
|
|
varying vec4 my_vUv;
|
|
${shader.vertexShader}`;
|
|
shader.vertexShader = shader.vertexShader.replace("#include <project_vertex>", `#include <project_vertex>
|
|
my_vUv = textureMatrix * vec4( position, 1.0 );
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );`);
|
|
shader.fragmentShader = `
|
|
uniform sampler2D tDiffuse;
|
|
uniform sampler2D tDiffuseBlur;
|
|
uniform sampler2D tDepth;
|
|
uniform sampler2D distortionMap;
|
|
uniform float distortion;
|
|
uniform float cameraNear;
|
|
uniform float cameraFar;
|
|
uniform bool hasBlur;
|
|
uniform float mixBlur;
|
|
uniform float mirror;
|
|
uniform float mixStrength;
|
|
uniform float minDepthThreshold;
|
|
uniform float maxDepthThreshold;
|
|
uniform float mixContrast;
|
|
uniform float depthScale;
|
|
uniform float depthToBlurRatioBias;
|
|
varying vec4 my_vUv;
|
|
${shader.fragmentShader}`;
|
|
shader.fragmentShader = shader.fragmentShader.replace("#include <emissivemap_fragment>", `#include <emissivemap_fragment>
|
|
|
|
float distortionFactor = 0.0;
|
|
#ifdef USE_DISTORTION
|
|
distortionFactor = texture2D(distortionMap, vUv).r * distortion;
|
|
#endif
|
|
|
|
vec4 new_vUv = my_vUv;
|
|
new_vUv.x += distortionFactor;
|
|
new_vUv.y += distortionFactor;
|
|
|
|
vec4 base = texture2DProj(tDiffuse, new_vUv);
|
|
vec4 blur = texture2DProj(tDiffuseBlur, new_vUv);
|
|
|
|
vec4 merge = base;
|
|
|
|
#ifdef USE_NORMALMAP
|
|
vec2 normal_uv = vec2(0.0);
|
|
vec4 normalColor = texture2D(normalMap, vUv * normalScale);
|
|
vec3 my_normal = normalize( vec3( normalColor.r * 2.0 - 1.0, normalColor.b, normalColor.g * 2.0 - 1.0 ) );
|
|
vec3 coord = new_vUv.xyz / new_vUv.w;
|
|
normal_uv = coord.xy + coord.z * my_normal.xz * 0.05;
|
|
vec4 base_normal = texture2D(tDiffuse, normal_uv);
|
|
vec4 blur_normal = texture2D(tDiffuseBlur, normal_uv);
|
|
merge = base_normal;
|
|
blur = blur_normal;
|
|
#endif
|
|
|
|
float depthFactor = 0.0001;
|
|
float blurFactor = 0.0;
|
|
|
|
#ifdef USE_DEPTH
|
|
vec4 depth = texture2DProj(tDepth, new_vUv);
|
|
depthFactor = smoothstep(minDepthThreshold, maxDepthThreshold, 1.0-(depth.r * depth.a));
|
|
depthFactor *= depthScale;
|
|
depthFactor = max(0.0001, min(1.0, depthFactor));
|
|
|
|
#ifdef USE_BLUR
|
|
blur = blur * min(1.0, depthFactor + depthToBlurRatioBias);
|
|
merge = merge * min(1.0, depthFactor + 0.5);
|
|
#else
|
|
merge = merge * depthFactor;
|
|
#endif
|
|
|
|
#endif
|
|
|
|
float reflectorRoughnessFactor = roughness;
|
|
#ifdef USE_ROUGHNESSMAP
|
|
vec4 reflectorTexelRoughness = texture2D( roughnessMap, vUv );
|
|
reflectorRoughnessFactor *= reflectorTexelRoughness.g;
|
|
#endif
|
|
|
|
#ifdef USE_BLUR
|
|
blurFactor = min(1.0, mixBlur * reflectorRoughnessFactor);
|
|
merge = mix(merge, blur, blurFactor);
|
|
#endif
|
|
|
|
vec4 newMerge = vec4(0.0, 0.0, 0.0, 1.0);
|
|
newMerge.r = (merge.r - 0.5) * mixContrast + 0.5;
|
|
newMerge.g = (merge.g - 0.5) * mixContrast + 0.5;
|
|
newMerge.b = (merge.b - 0.5) * mixContrast + 0.5;
|
|
|
|
diffuseColor.rgb = diffuseColor.rgb * ((1.0 - min(1.0, mirror)) + newMerge.rgb * mixStrength);
|
|
`);
|
|
}
|
|
get tDiffuse() {
|
|
return this._tDiffuse.value;
|
|
}
|
|
set tDiffuse(v5) {
|
|
this._tDiffuse.value = v5;
|
|
}
|
|
get tDepth() {
|
|
return this._tDepth.value;
|
|
}
|
|
set tDepth(v5) {
|
|
this._tDepth.value = v5;
|
|
}
|
|
get distortionMap() {
|
|
return this._distortionMap.value;
|
|
}
|
|
set distortionMap(v5) {
|
|
this._distortionMap.value = v5;
|
|
}
|
|
get tDiffuseBlur() {
|
|
return this._tDiffuseBlur.value;
|
|
}
|
|
set tDiffuseBlur(v5) {
|
|
this._tDiffuseBlur.value = v5;
|
|
}
|
|
get textureMatrix() {
|
|
return this._textureMatrix.value;
|
|
}
|
|
set textureMatrix(v5) {
|
|
this._textureMatrix.value = v5;
|
|
}
|
|
get hasBlur() {
|
|
return this._hasBlur.value;
|
|
}
|
|
set hasBlur(v5) {
|
|
this._hasBlur.value = v5;
|
|
}
|
|
get mirror() {
|
|
return this._mirror.value;
|
|
}
|
|
set mirror(v5) {
|
|
this._mirror.value = v5;
|
|
}
|
|
get mixBlur() {
|
|
return this._mixBlur.value;
|
|
}
|
|
set mixBlur(v5) {
|
|
this._mixBlur.value = v5;
|
|
}
|
|
get mixStrength() {
|
|
return this._blurStrength.value;
|
|
}
|
|
set mixStrength(v5) {
|
|
this._blurStrength.value = v5;
|
|
}
|
|
get minDepthThreshold() {
|
|
return this._minDepthThreshold.value;
|
|
}
|
|
set minDepthThreshold(v5) {
|
|
this._minDepthThreshold.value = v5;
|
|
}
|
|
get maxDepthThreshold() {
|
|
return this._maxDepthThreshold.value;
|
|
}
|
|
set maxDepthThreshold(v5) {
|
|
this._maxDepthThreshold.value = v5;
|
|
}
|
|
get depthScale() {
|
|
return this._depthScale.value;
|
|
}
|
|
set depthScale(v5) {
|
|
this._depthScale.value = v5;
|
|
}
|
|
get depthToBlurRatioBias() {
|
|
return this._depthToBlurRatioBias.value;
|
|
}
|
|
set depthToBlurRatioBias(v5) {
|
|
this._depthToBlurRatioBias.value = v5;
|
|
}
|
|
get distortion() {
|
|
return this._distortion.value;
|
|
}
|
|
set distortion(v5) {
|
|
this._distortion.value = v5;
|
|
}
|
|
get mixContrast() {
|
|
return this._mixContrast.value;
|
|
}
|
|
set mixContrast(v5) {
|
|
this._mixContrast.value = v5;
|
|
}
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/MeshReflectorMaterial.js
|
|
var MeshReflectorMaterial2 = React85.forwardRef(({
|
|
mixBlur = 0,
|
|
mixStrength = 1,
|
|
resolution = 256,
|
|
blur = [0, 0],
|
|
minDepthThreshold = 0.9,
|
|
maxDepthThreshold = 1,
|
|
depthScale = 0,
|
|
depthToBlurRatioBias = 0.25,
|
|
mirror = 0,
|
|
distortion = 1,
|
|
mixContrast = 1,
|
|
distortionMap,
|
|
reflectorOffset = 0,
|
|
...props
|
|
}, ref) => {
|
|
extend({
|
|
MeshReflectorMaterialImpl: MeshReflectorMaterial
|
|
});
|
|
const gl = useThree(({
|
|
gl: gl2
|
|
}) => gl2);
|
|
const camera = useThree(({
|
|
camera: camera2
|
|
}) => camera2);
|
|
const scene = useThree(({
|
|
scene: scene2
|
|
}) => scene2);
|
|
blur = Array.isArray(blur) ? blur : [blur, blur];
|
|
const hasBlur = blur[0] + blur[1] > 0;
|
|
const blurX = blur[0];
|
|
const blurY = blur[1];
|
|
const materialRef = React85.useRef(null);
|
|
React85.useImperativeHandle(ref, () => materialRef.current, []);
|
|
const [reflectorPlane] = React85.useState(() => new Plane());
|
|
const [normal2] = React85.useState(() => new Vector3());
|
|
const [reflectorWorldPosition] = React85.useState(() => new Vector3());
|
|
const [cameraWorldPosition] = React85.useState(() => new Vector3());
|
|
const [rotationMatrix] = React85.useState(() => new Matrix4());
|
|
const [lookAtPosition] = React85.useState(() => new Vector3(0, 0, -1));
|
|
const [clipPlane] = React85.useState(() => new Vector4());
|
|
const [view] = React85.useState(() => new Vector3());
|
|
const [target2] = React85.useState(() => new Vector3());
|
|
const [q] = React85.useState(() => new Vector4());
|
|
const [textureMatrix] = React85.useState(() => new Matrix4());
|
|
const [virtualCamera] = React85.useState(() => new PerspectiveCamera());
|
|
const beforeRender = React85.useCallback(() => {
|
|
var _materialRef$current;
|
|
const parent = materialRef.current.parent || ((_materialRef$current = materialRef.current) == null || (_materialRef$current = _materialRef$current.__r3f.parent) == null ? void 0 : _materialRef$current.object);
|
|
if (!parent) return;
|
|
reflectorWorldPosition.setFromMatrixPosition(parent.matrixWorld);
|
|
cameraWorldPosition.setFromMatrixPosition(camera.matrixWorld);
|
|
rotationMatrix.extractRotation(parent.matrixWorld);
|
|
normal2.set(0, 0, 1);
|
|
normal2.applyMatrix4(rotationMatrix);
|
|
reflectorWorldPosition.addScaledVector(normal2, reflectorOffset);
|
|
view.subVectors(reflectorWorldPosition, cameraWorldPosition);
|
|
if (view.dot(normal2) > 0) return;
|
|
view.reflect(normal2).negate();
|
|
view.add(reflectorWorldPosition);
|
|
rotationMatrix.extractRotation(camera.matrixWorld);
|
|
lookAtPosition.set(0, 0, -1);
|
|
lookAtPosition.applyMatrix4(rotationMatrix);
|
|
lookAtPosition.add(cameraWorldPosition);
|
|
target2.subVectors(reflectorWorldPosition, lookAtPosition);
|
|
target2.reflect(normal2).negate();
|
|
target2.add(reflectorWorldPosition);
|
|
virtualCamera.position.copy(view);
|
|
virtualCamera.up.set(0, 1, 0);
|
|
virtualCamera.up.applyMatrix4(rotationMatrix);
|
|
virtualCamera.up.reflect(normal2);
|
|
virtualCamera.lookAt(target2);
|
|
virtualCamera.far = camera.far;
|
|
virtualCamera.updateMatrixWorld();
|
|
virtualCamera.projectionMatrix.copy(camera.projectionMatrix);
|
|
textureMatrix.set(0.5, 0, 0, 0.5, 0, 0.5, 0, 0.5, 0, 0, 0.5, 0.5, 0, 0, 0, 1);
|
|
textureMatrix.multiply(virtualCamera.projectionMatrix);
|
|
textureMatrix.multiply(virtualCamera.matrixWorldInverse);
|
|
textureMatrix.multiply(parent.matrixWorld);
|
|
reflectorPlane.setFromNormalAndCoplanarPoint(normal2, reflectorWorldPosition);
|
|
reflectorPlane.applyMatrix4(virtualCamera.matrixWorldInverse);
|
|
clipPlane.set(reflectorPlane.normal.x, reflectorPlane.normal.y, reflectorPlane.normal.z, reflectorPlane.constant);
|
|
const projectionMatrix = virtualCamera.projectionMatrix;
|
|
q.x = (Math.sign(clipPlane.x) + projectionMatrix.elements[8]) / projectionMatrix.elements[0];
|
|
q.y = (Math.sign(clipPlane.y) + projectionMatrix.elements[9]) / projectionMatrix.elements[5];
|
|
q.z = -1;
|
|
q.w = (1 + projectionMatrix.elements[10]) / projectionMatrix.elements[14];
|
|
clipPlane.multiplyScalar(2 / clipPlane.dot(q));
|
|
projectionMatrix.elements[2] = clipPlane.x;
|
|
projectionMatrix.elements[6] = clipPlane.y;
|
|
projectionMatrix.elements[10] = clipPlane.z + 1;
|
|
projectionMatrix.elements[14] = clipPlane.w;
|
|
}, [camera, reflectorOffset]);
|
|
const [fbo1, fbo2, blurpass, reflectorProps] = React85.useMemo(() => {
|
|
const parameters = {
|
|
minFilter: LinearFilter,
|
|
magFilter: LinearFilter,
|
|
type: HalfFloatType
|
|
};
|
|
const fbo12 = new WebGLRenderTarget(resolution, resolution, parameters);
|
|
fbo12.depthBuffer = true;
|
|
fbo12.depthTexture = new DepthTexture(resolution, resolution);
|
|
fbo12.depthTexture.format = DepthFormat;
|
|
fbo12.depthTexture.type = UnsignedShortType;
|
|
const fbo22 = new WebGLRenderTarget(resolution, resolution, parameters);
|
|
const blurpass2 = new BlurPass({
|
|
gl,
|
|
resolution,
|
|
width: blurX,
|
|
height: blurY,
|
|
minDepthThreshold,
|
|
maxDepthThreshold,
|
|
depthScale,
|
|
depthToBlurRatioBias
|
|
});
|
|
const reflectorProps2 = {
|
|
mirror,
|
|
textureMatrix,
|
|
mixBlur,
|
|
tDiffuse: fbo12.texture,
|
|
tDepth: fbo12.depthTexture,
|
|
tDiffuseBlur: fbo22.texture,
|
|
hasBlur,
|
|
mixStrength,
|
|
minDepthThreshold,
|
|
maxDepthThreshold,
|
|
depthScale,
|
|
depthToBlurRatioBias,
|
|
distortion,
|
|
distortionMap,
|
|
mixContrast,
|
|
"defines-USE_BLUR": hasBlur ? "" : void 0,
|
|
"defines-USE_DEPTH": depthScale > 0 ? "" : void 0,
|
|
"defines-USE_DISTORTION": distortionMap ? "" : void 0
|
|
};
|
|
return [fbo12, fbo22, blurpass2, reflectorProps2];
|
|
}, [gl, blurX, blurY, textureMatrix, resolution, mirror, hasBlur, mixBlur, mixStrength, minDepthThreshold, maxDepthThreshold, depthScale, depthToBlurRatioBias, distortion, distortionMap, mixContrast]);
|
|
useFrame(() => {
|
|
var _materialRef$current2;
|
|
const parent = materialRef.current.parent || ((_materialRef$current2 = materialRef.current) == null || (_materialRef$current2 = _materialRef$current2.__r3f.parent) == null ? void 0 : _materialRef$current2.object);
|
|
if (!parent) return;
|
|
parent.visible = false;
|
|
const currentXrEnabled = gl.xr.enabled;
|
|
const currentShadowAutoUpdate = gl.shadowMap.autoUpdate;
|
|
beforeRender();
|
|
gl.xr.enabled = false;
|
|
gl.shadowMap.autoUpdate = false;
|
|
gl.setRenderTarget(fbo1);
|
|
gl.state.buffers.depth.setMask(true);
|
|
if (!gl.autoClear) gl.clear();
|
|
gl.render(scene, virtualCamera);
|
|
if (hasBlur) blurpass.render(gl, fbo1, fbo2);
|
|
gl.xr.enabled = currentXrEnabled;
|
|
gl.shadowMap.autoUpdate = currentShadowAutoUpdate;
|
|
parent.visible = true;
|
|
gl.setRenderTarget(null);
|
|
});
|
|
return React85.createElement("meshReflectorMaterialImpl", _extends({
|
|
attach: "material",
|
|
key: "key" + reflectorProps["defines-USE_BLUR"] + reflectorProps["defines-USE_DEPTH"] + reflectorProps["defines-USE_DISTORTION"],
|
|
ref: materialRef
|
|
}, reflectorProps, props));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/MeshRefractionMaterial.js
|
|
var React86 = __toESM(require_react());
|
|
var import_react17 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/materials/MeshRefractionMaterial.js
|
|
var MeshRefractionMaterial = shaderMaterial(
|
|
{
|
|
envMap: null,
|
|
bounces: 3,
|
|
ior: 2.4,
|
|
correctMips: true,
|
|
aberrationStrength: 0.01,
|
|
fresnel: 0,
|
|
bvh: new MeshBVHUniformStruct(),
|
|
color: new Color("white"),
|
|
opacity: 1,
|
|
resolution: new Vector2(),
|
|
viewMatrixInverse: new Matrix4(),
|
|
projectionMatrixInverse: new Matrix4()
|
|
},
|
|
/*glsl*/
|
|
`
|
|
uniform mat4 viewMatrixInverse;
|
|
|
|
varying vec3 vWorldPosition;
|
|
varying vec3 vNormal;
|
|
varying mat4 vModelMatrixInverse;
|
|
|
|
#include <color_pars_vertex>
|
|
|
|
void main() {
|
|
#include <color_vertex>
|
|
|
|
vec4 transformedNormal = vec4(normal, 0.0);
|
|
vec4 transformedPosition = vec4(position, 1.0);
|
|
#ifdef USE_INSTANCING
|
|
transformedNormal = instanceMatrix * transformedNormal;
|
|
transformedPosition = instanceMatrix * transformedPosition;
|
|
#endif
|
|
|
|
#ifdef USE_INSTANCING
|
|
vModelMatrixInverse = inverse(modelMatrix * instanceMatrix);
|
|
#else
|
|
vModelMatrixInverse = inverse(modelMatrix);
|
|
#endif
|
|
|
|
vWorldPosition = (modelMatrix * transformedPosition).xyz;
|
|
vNormal = normalize((viewMatrixInverse * vec4(normalMatrix * transformedNormal.xyz, 0.0)).xyz);
|
|
gl_Position = projectionMatrix * viewMatrix * modelMatrix * transformedPosition;
|
|
}`,
|
|
/*glsl*/
|
|
`
|
|
#define ENVMAP_TYPE_CUBE_UV
|
|
precision highp isampler2D;
|
|
precision highp usampler2D;
|
|
varying vec3 vWorldPosition;
|
|
varying vec3 vNormal;
|
|
varying mat4 vModelMatrixInverse;
|
|
|
|
#include <color_pars_fragment>
|
|
|
|
#ifdef ENVMAP_TYPE_CUBEM
|
|
uniform samplerCube envMap;
|
|
#else
|
|
uniform sampler2D envMap;
|
|
#endif
|
|
|
|
uniform float bounces;
|
|
${shaderStructs}
|
|
${shaderIntersectFunction}
|
|
uniform BVH bvh;
|
|
uniform float ior;
|
|
uniform bool correctMips;
|
|
uniform vec2 resolution;
|
|
uniform float fresnel;
|
|
uniform mat4 modelMatrix;
|
|
uniform mat4 projectionMatrixInverse;
|
|
uniform mat4 viewMatrixInverse;
|
|
uniform float aberrationStrength;
|
|
uniform vec3 color;
|
|
uniform float opacity;
|
|
|
|
float fresnelFunc(vec3 viewDirection, vec3 worldNormal) {
|
|
return pow( 1.0 + dot( viewDirection, worldNormal), 10.0 );
|
|
}
|
|
|
|
vec3 totalInternalReflection(vec3 ro, vec3 rd, vec3 normal, float ior, mat4 modelMatrixInverse) {
|
|
vec3 rayOrigin = ro;
|
|
vec3 rayDirection = rd;
|
|
rayDirection = refract(rayDirection, normal, 1.0 / ior);
|
|
rayOrigin = vWorldPosition + rayDirection * 0.001;
|
|
rayOrigin = (modelMatrixInverse * vec4(rayOrigin, 1.0)).xyz;
|
|
rayDirection = normalize((modelMatrixInverse * vec4(rayDirection, 0.0)).xyz);
|
|
for(float i = 0.0; i < bounces; i++) {
|
|
uvec4 faceIndices = uvec4( 0u );
|
|
vec3 faceNormal = vec3( 0.0, 0.0, 1.0 );
|
|
vec3 barycoord = vec3( 0.0 );
|
|
float side = 1.0;
|
|
float dist = 0.0;
|
|
bvhIntersectFirstHit( bvh, rayOrigin, rayDirection, faceIndices, faceNormal, barycoord, side, dist );
|
|
vec3 hitPos = rayOrigin + rayDirection * max(dist - 0.001, 0.0);
|
|
vec3 tempDir = refract(rayDirection, faceNormal, ior);
|
|
if (length(tempDir) != 0.0) {
|
|
rayDirection = tempDir;
|
|
break;
|
|
}
|
|
rayDirection = reflect(rayDirection, faceNormal);
|
|
rayOrigin = hitPos + rayDirection * 0.01;
|
|
}
|
|
rayDirection = normalize((modelMatrix * vec4(rayDirection, 0.0)).xyz);
|
|
return rayDirection;
|
|
}
|
|
|
|
#include <common>
|
|
#include <cube_uv_reflection_fragment>
|
|
|
|
#ifdef ENVMAP_TYPE_CUBEM
|
|
vec4 textureGradient(samplerCube envMap, vec3 rayDirection, vec3 directionCamPerfect) {
|
|
return textureGrad(envMap, rayDirection, dFdx(correctMips ? directionCamPerfect: rayDirection), dFdy(correctMips ? directionCamPerfect: rayDirection));
|
|
}
|
|
#else
|
|
vec4 textureGradient(sampler2D envMap, vec3 rayDirection, vec3 directionCamPerfect) {
|
|
vec2 uvv = equirectUv( rayDirection );
|
|
vec2 smoothUv = equirectUv( directionCamPerfect );
|
|
return textureGrad(envMap, uvv, dFdx(correctMips ? smoothUv : uvv), dFdy(correctMips ? smoothUv : uvv));
|
|
}
|
|
#endif
|
|
|
|
void main() {
|
|
vec2 uv = gl_FragCoord.xy / resolution;
|
|
vec3 directionCamPerfect = (projectionMatrixInverse * vec4(uv * 2.0 - 1.0, 0.0, 1.0)).xyz;
|
|
directionCamPerfect = (viewMatrixInverse * vec4(directionCamPerfect, 0.0)).xyz;
|
|
directionCamPerfect = normalize(directionCamPerfect);
|
|
vec3 normal = vNormal;
|
|
vec3 rayOrigin = cameraPosition;
|
|
vec3 rayDirection = normalize(vWorldPosition - cameraPosition);
|
|
|
|
vec4 diffuseColor = vec4(color, opacity);
|
|
#include <color_fragment>
|
|
|
|
#ifdef CHROMATIC_ABERRATIONS
|
|
vec3 rayDirectionG = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior, 1.0), vModelMatrixInverse);
|
|
#ifdef FAST_CHROMA
|
|
vec3 rayDirectionR = normalize(rayDirectionG + 1.0 * vec3(aberrationStrength / 2.0));
|
|
vec3 rayDirectionB = normalize(rayDirectionG - 1.0 * vec3(aberrationStrength / 2.0));
|
|
#else
|
|
vec3 rayDirectionR = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior * (1.0 - aberrationStrength), 1.0), vModelMatrixInverse);
|
|
vec3 rayDirectionB = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior * (1.0 + aberrationStrength), 1.0), vModelMatrixInverse);
|
|
#endif
|
|
float finalColorR = textureGradient(envMap, rayDirectionR, directionCamPerfect).r;
|
|
float finalColorG = textureGradient(envMap, rayDirectionG, directionCamPerfect).g;
|
|
float finalColorB = textureGradient(envMap, rayDirectionB, directionCamPerfect).b;
|
|
diffuseColor.rgb *= vec3(finalColorR, finalColorG, finalColorB);
|
|
#else
|
|
rayDirection = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior, 1.0), vModelMatrixInverse);
|
|
diffuseColor.rgb *= textureGradient(envMap, rayDirection, directionCamPerfect).rgb;
|
|
#endif
|
|
|
|
vec3 viewDirection = normalize(vWorldPosition - cameraPosition);
|
|
float nFresnel = fresnelFunc(viewDirection, normal) * fresnel;
|
|
gl_FragColor = vec4(mix(diffuseColor.rgb, vec3(1.0), nFresnel), diffuseColor.a);
|
|
|
|
#include <tonemapping_fragment>
|
|
#include <${version >= 154 ? "colorspace_fragment" : "encodings_fragment"}>
|
|
}`
|
|
);
|
|
|
|
// node_modules/@react-three/drei/core/MeshRefractionMaterial.js
|
|
var isCubeTexture = (def) => def && def.isCubeTexture;
|
|
function MeshRefractionMaterial2({
|
|
aberrationStrength = 0,
|
|
fastChroma = true,
|
|
envMap,
|
|
...props
|
|
}) {
|
|
extend({
|
|
MeshRefractionMaterial
|
|
});
|
|
const material = (0, import_react17.useRef)(null);
|
|
const {
|
|
size
|
|
} = useThree();
|
|
const defines = (0, import_react17.useMemo)(() => {
|
|
var _ref, _envMap$image$;
|
|
const temp5 = {};
|
|
const isCubeMap = isCubeTexture(envMap);
|
|
const w = (_ref = isCubeMap ? (_envMap$image$ = envMap.image[0]) == null ? void 0 : _envMap$image$.width : envMap.image.width) !== null && _ref !== void 0 ? _ref : 1024;
|
|
const cubeSize = w / 4;
|
|
const _lodMax = Math.floor(Math.log2(cubeSize));
|
|
const _cubeSize = Math.pow(2, _lodMax);
|
|
const width = 3 * Math.max(_cubeSize, 16 * 7);
|
|
const height = 4 * _cubeSize;
|
|
if (isCubeMap) temp5.ENVMAP_TYPE_CUBEM = "";
|
|
temp5.CUBEUV_TEXEL_WIDTH = `${1 / width}`;
|
|
temp5.CUBEUV_TEXEL_HEIGHT = `${1 / height}`;
|
|
temp5.CUBEUV_MAX_MIP = `${_lodMax}.0`;
|
|
if (aberrationStrength > 0) temp5.CHROMATIC_ABERRATIONS = "";
|
|
if (fastChroma) temp5.FAST_CHROMA = "";
|
|
return temp5;
|
|
}, [aberrationStrength, fastChroma]);
|
|
(0, import_react17.useLayoutEffect)(() => {
|
|
var _material$current;
|
|
const geometry3 = (_material$current = material.current) == null || (_material$current = _material$current.__r3f) == null || (_material$current = _material$current.parent) == null || (_material$current = _material$current.object) == null ? void 0 : _material$current.geometry;
|
|
if (geometry3) {
|
|
material.current.bvh = new MeshBVHUniformStruct();
|
|
material.current.bvh.updateFrom(new MeshBVH(geometry3.clone().toNonIndexed(), {
|
|
strategy: SAH
|
|
}));
|
|
}
|
|
}, []);
|
|
useFrame(({
|
|
camera
|
|
}) => {
|
|
material.current.viewMatrixInverse = camera.matrixWorld;
|
|
material.current.projectionMatrixInverse = camera.projectionMatrixInverse;
|
|
});
|
|
return React86.createElement("meshRefractionMaterial", _extends({
|
|
// @ts-ignore
|
|
key: JSON.stringify(defines),
|
|
defines,
|
|
ref: material,
|
|
resolution: [size.width, size.height],
|
|
aberrationStrength,
|
|
envMap
|
|
}, props));
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/MeshTransmissionMaterial.js
|
|
var React87 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/materials/DiscardMaterial.js
|
|
var DiscardMaterial = shaderMaterial({}, "void main() { }", "void main() { gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); discard; }");
|
|
|
|
// node_modules/@react-three/drei/core/MeshTransmissionMaterial.js
|
|
var MeshTransmissionMaterialImpl = class extends MeshPhysicalMaterial {
|
|
constructor(samples = 6, transmissionSampler = false) {
|
|
super();
|
|
this.uniforms = {
|
|
chromaticAberration: {
|
|
value: 0.05
|
|
},
|
|
// Transmission must always be 0, unless transmissionSampler is being used
|
|
transmission: {
|
|
value: 0
|
|
},
|
|
// Instead a workaround is used, see below for reasons why
|
|
_transmission: {
|
|
value: 1
|
|
},
|
|
transmissionMap: {
|
|
value: null
|
|
},
|
|
// Roughness is 1 in THREE.MeshPhysicalMaterial but it makes little sense in a transmission material
|
|
roughness: {
|
|
value: 0
|
|
},
|
|
thickness: {
|
|
value: 0
|
|
},
|
|
thicknessMap: {
|
|
value: null
|
|
},
|
|
attenuationDistance: {
|
|
value: Infinity
|
|
},
|
|
attenuationColor: {
|
|
value: new Color("white")
|
|
},
|
|
anisotropicBlur: {
|
|
value: 0.1
|
|
},
|
|
time: {
|
|
value: 0
|
|
},
|
|
distortion: {
|
|
value: 0
|
|
},
|
|
distortionScale: {
|
|
value: 0.5
|
|
},
|
|
temporalDistortion: {
|
|
value: 0
|
|
},
|
|
buffer: {
|
|
value: null
|
|
}
|
|
};
|
|
this.onBeforeCompile = (shader) => {
|
|
shader.uniforms = {
|
|
...shader.uniforms,
|
|
...this.uniforms
|
|
};
|
|
if (this.anisotropy > 0) shader.defines.USE_ANISOTROPY = "";
|
|
if (transmissionSampler) shader.defines.USE_SAMPLER = "";
|
|
else shader.defines.USE_TRANSMISSION = "";
|
|
shader.fragmentShader = /*glsl*/
|
|
`
|
|
uniform float chromaticAberration;
|
|
uniform float anisotropicBlur;
|
|
uniform float time;
|
|
uniform float distortion;
|
|
uniform float distortionScale;
|
|
uniform float temporalDistortion;
|
|
uniform sampler2D buffer;
|
|
|
|
vec3 random3(vec3 c) {
|
|
float j = 4096.0*sin(dot(c,vec3(17.0, 59.4, 15.0)));
|
|
vec3 r;
|
|
r.z = fract(512.0*j);
|
|
j *= .125;
|
|
r.x = fract(512.0*j);
|
|
j *= .125;
|
|
r.y = fract(512.0*j);
|
|
return r-0.5;
|
|
}
|
|
|
|
uint hash( uint x ) {
|
|
x += ( x << 10u );
|
|
x ^= ( x >> 6u );
|
|
x += ( x << 3u );
|
|
x ^= ( x >> 11u );
|
|
x += ( x << 15u );
|
|
return x;
|
|
}
|
|
|
|
// Compound versions of the hashing algorithm I whipped together.
|
|
uint hash( uvec2 v ) { return hash( v.x ^ hash(v.y) ); }
|
|
uint hash( uvec3 v ) { return hash( v.x ^ hash(v.y) ^ hash(v.z) ); }
|
|
uint hash( uvec4 v ) { return hash( v.x ^ hash(v.y) ^ hash(v.z) ^ hash(v.w) ); }
|
|
|
|
// Construct a float with half-open range [0:1] using low 23 bits.
|
|
// All zeroes yields 0.0, all ones yields the next smallest representable value below 1.0.
|
|
float floatConstruct( uint m ) {
|
|
const uint ieeeMantissa = 0x007FFFFFu; // binary32 mantissa bitmask
|
|
const uint ieeeOne = 0x3F800000u; // 1.0 in IEEE binary32
|
|
m &= ieeeMantissa; // Keep only mantissa bits (fractional part)
|
|
m |= ieeeOne; // Add fractional part to 1.0
|
|
float f = uintBitsToFloat( m ); // Range [1:2]
|
|
return f - 1.0; // Range [0:1]
|
|
}
|
|
|
|
// Pseudo-random value in half-open range [0:1].
|
|
float randomBase( float x ) { return floatConstruct(hash(floatBitsToUint(x))); }
|
|
float randomBase( vec2 v ) { return floatConstruct(hash(floatBitsToUint(v))); }
|
|
float randomBase( vec3 v ) { return floatConstruct(hash(floatBitsToUint(v))); }
|
|
float randomBase( vec4 v ) { return floatConstruct(hash(floatBitsToUint(v))); }
|
|
float rand(float seed) {
|
|
float result = randomBase(vec3(gl_FragCoord.xy, seed));
|
|
return result;
|
|
}
|
|
|
|
const float F3 = 0.3333333;
|
|
const float G3 = 0.1666667;
|
|
|
|
float snoise(vec3 p) {
|
|
vec3 s = floor(p + dot(p, vec3(F3)));
|
|
vec3 x = p - s + dot(s, vec3(G3));
|
|
vec3 e = step(vec3(0.0), x - x.yzx);
|
|
vec3 i1 = e*(1.0 - e.zxy);
|
|
vec3 i2 = 1.0 - e.zxy*(1.0 - e);
|
|
vec3 x1 = x - i1 + G3;
|
|
vec3 x2 = x - i2 + 2.0*G3;
|
|
vec3 x3 = x - 1.0 + 3.0*G3;
|
|
vec4 w, d;
|
|
w.x = dot(x, x);
|
|
w.y = dot(x1, x1);
|
|
w.z = dot(x2, x2);
|
|
w.w = dot(x3, x3);
|
|
w = max(0.6 - w, 0.0);
|
|
d.x = dot(random3(s), x);
|
|
d.y = dot(random3(s + i1), x1);
|
|
d.z = dot(random3(s + i2), x2);
|
|
d.w = dot(random3(s + 1.0), x3);
|
|
w *= w;
|
|
w *= w;
|
|
d *= w;
|
|
return dot(d, vec4(52.0));
|
|
}
|
|
|
|
float snoiseFractal(vec3 m) {
|
|
return 0.5333333* snoise(m)
|
|
+0.2666667* snoise(2.0*m)
|
|
+0.1333333* snoise(4.0*m)
|
|
+0.0666667* snoise(8.0*m);
|
|
}
|
|
` + shader.fragmentShader;
|
|
shader.fragmentShader = shader.fragmentShader.replace(
|
|
"#include <transmission_pars_fragment>",
|
|
/*glsl*/
|
|
`
|
|
#ifdef USE_TRANSMISSION
|
|
// Transmission code is based on glTF-Sampler-Viewer
|
|
// https://github.com/KhronosGroup/glTF-Sample-Viewer
|
|
uniform float _transmission;
|
|
uniform float thickness;
|
|
uniform float attenuationDistance;
|
|
uniform vec3 attenuationColor;
|
|
#ifdef USE_TRANSMISSIONMAP
|
|
uniform sampler2D transmissionMap;
|
|
#endif
|
|
#ifdef USE_THICKNESSMAP
|
|
uniform sampler2D thicknessMap;
|
|
#endif
|
|
uniform vec2 transmissionSamplerSize;
|
|
uniform sampler2D transmissionSamplerMap;
|
|
uniform mat4 modelMatrix;
|
|
uniform mat4 projectionMatrix;
|
|
varying vec3 vWorldPosition;
|
|
vec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {
|
|
// Direction of refracted light.
|
|
vec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );
|
|
// Compute rotation-independant scaling of the model matrix.
|
|
vec3 modelScale;
|
|
modelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );
|
|
modelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );
|
|
modelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );
|
|
// The thickness is specified in local space.
|
|
return normalize( refractionVector ) * thickness * modelScale;
|
|
}
|
|
float applyIorToRoughness( const in float roughness, const in float ior ) {
|
|
// Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and
|
|
// an IOR of 1.5 results in the default amount of microfacet refraction.
|
|
return roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );
|
|
}
|
|
vec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {
|
|
float framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );
|
|
#ifdef USE_SAMPLER
|
|
#ifdef texture2DLodEXT
|
|
return texture2DLodEXT(transmissionSamplerMap, fragCoord.xy, framebufferLod);
|
|
#else
|
|
return texture2D(transmissionSamplerMap, fragCoord.xy, framebufferLod);
|
|
#endif
|
|
#else
|
|
return texture2D(buffer, fragCoord.xy);
|
|
#endif
|
|
}
|
|
vec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {
|
|
if ( isinf( attenuationDistance ) ) {
|
|
// Attenuation distance is +∞, i.e. the transmitted color is not attenuated at all.
|
|
return radiance;
|
|
} else {
|
|
// Compute light attenuation using Beer's law.
|
|
vec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;
|
|
vec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); // Beer's law
|
|
return transmittance * radiance;
|
|
}
|
|
}
|
|
vec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,
|
|
const in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,
|
|
const in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,
|
|
const in vec3 attenuationColor, const in float attenuationDistance ) {
|
|
vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );
|
|
vec3 refractedRayExit = position + transmissionRay;
|
|
// Project refracted vector on the framebuffer, while mapping to normalized device coordinates.
|
|
vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );
|
|
vec2 refractionCoords = ndcPos.xy / ndcPos.w;
|
|
refractionCoords += 1.0;
|
|
refractionCoords /= 2.0;
|
|
// Sample framebuffer to get pixel the refracted ray hits.
|
|
vec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );
|
|
vec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );
|
|
// Get the specular component.
|
|
vec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );
|
|
return vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );
|
|
}
|
|
#endif
|
|
`
|
|
);
|
|
shader.fragmentShader = shader.fragmentShader.replace(
|
|
"#include <transmission_fragment>",
|
|
/*glsl*/
|
|
`
|
|
// Improve the refraction to use the world pos
|
|
material.transmission = _transmission;
|
|
material.transmissionAlpha = 1.0;
|
|
material.thickness = thickness;
|
|
material.attenuationDistance = attenuationDistance;
|
|
material.attenuationColor = attenuationColor;
|
|
#ifdef USE_TRANSMISSIONMAP
|
|
material.transmission *= texture2D( transmissionMap, vUv ).r;
|
|
#endif
|
|
#ifdef USE_THICKNESSMAP
|
|
material.thickness *= texture2D( thicknessMap, vUv ).g;
|
|
#endif
|
|
|
|
vec3 pos = vWorldPosition;
|
|
float runningSeed = 0.0;
|
|
vec3 v = normalize( cameraPosition - pos );
|
|
vec3 n = inverseTransformDirection( normal, viewMatrix );
|
|
vec3 transmission = vec3(0.0);
|
|
float transmissionR, transmissionB, transmissionG;
|
|
float randomCoords = rand(runningSeed++);
|
|
float thickness_smear = thickness * max(pow(roughnessFactor, 0.33), anisotropicBlur);
|
|
vec3 distortionNormal = vec3(0.0);
|
|
vec3 temporalOffset = vec3(time, -time, -time) * temporalDistortion;
|
|
if (distortion > 0.0) {
|
|
distortionNormal = distortion * vec3(snoiseFractal(vec3((pos * distortionScale + temporalOffset))), snoiseFractal(vec3(pos.zxy * distortionScale - temporalOffset)), snoiseFractal(vec3(pos.yxz * distortionScale + temporalOffset)));
|
|
}
|
|
for (float i = 0.0; i < ${samples}.0; i ++) {
|
|
vec3 sampleNorm = normalize(n + roughnessFactor * roughnessFactor * 2.0 * normalize(vec3(rand(runningSeed++) - 0.5, rand(runningSeed++) - 0.5, rand(runningSeed++) - 0.5)) * pow(rand(runningSeed++), 0.33) + distortionNormal);
|
|
transmissionR = getIBLVolumeRefraction(
|
|
sampleNorm, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,
|
|
pos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness + thickness_smear * (i + randomCoords) / float(${samples}),
|
|
material.attenuationColor, material.attenuationDistance
|
|
).r;
|
|
transmissionG = getIBLVolumeRefraction(
|
|
sampleNorm, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,
|
|
pos, modelMatrix, viewMatrix, projectionMatrix, material.ior * (1.0 + chromaticAberration * (i + randomCoords) / float(${samples})) , material.thickness + thickness_smear * (i + randomCoords) / float(${samples}),
|
|
material.attenuationColor, material.attenuationDistance
|
|
).g;
|
|
transmissionB = getIBLVolumeRefraction(
|
|
sampleNorm, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,
|
|
pos, modelMatrix, viewMatrix, projectionMatrix, material.ior * (1.0 + 2.0 * chromaticAberration * (i + randomCoords) / float(${samples})), material.thickness + thickness_smear * (i + randomCoords) / float(${samples}),
|
|
material.attenuationColor, material.attenuationDistance
|
|
).b;
|
|
transmission.r += transmissionR;
|
|
transmission.g += transmissionG;
|
|
transmission.b += transmissionB;
|
|
}
|
|
transmission /= ${samples}.0;
|
|
totalDiffuse = mix( totalDiffuse, transmission.rgb, material.transmission );
|
|
`
|
|
);
|
|
};
|
|
Object.keys(this.uniforms).forEach((name) => Object.defineProperty(this, name, {
|
|
get: () => this.uniforms[name].value,
|
|
set: (v5) => this.uniforms[name].value = v5
|
|
}));
|
|
}
|
|
};
|
|
var MeshTransmissionMaterial = React87.forwardRef(({
|
|
buffer: buffer2,
|
|
transmissionSampler = false,
|
|
backside = false,
|
|
side = FrontSide,
|
|
transmission = 1,
|
|
thickness = 0,
|
|
backsideThickness = 0,
|
|
backsideEnvMapIntensity = 1,
|
|
samples = 10,
|
|
resolution,
|
|
backsideResolution,
|
|
background,
|
|
anisotropy,
|
|
anisotropicBlur,
|
|
...props
|
|
}, fref) => {
|
|
extend({
|
|
MeshTransmissionMaterial: MeshTransmissionMaterialImpl
|
|
});
|
|
const ref = React87.useRef(null);
|
|
const [discardMaterial] = React87.useState(() => new DiscardMaterial());
|
|
const fboBack = useFBO(backsideResolution || resolution);
|
|
const fboMain = useFBO(resolution);
|
|
let oldBg;
|
|
let oldEnvMapIntensity;
|
|
let oldTone;
|
|
let parent;
|
|
useFrame((state) => {
|
|
ref.current.time = state.clock.elapsedTime;
|
|
if (ref.current.buffer === fboMain.texture && !transmissionSampler) {
|
|
var _r3f$parent;
|
|
parent = (_r3f$parent = ref.current.__r3f.parent) == null ? void 0 : _r3f$parent.object;
|
|
if (parent) {
|
|
oldTone = state.gl.toneMapping;
|
|
oldBg = state.scene.background;
|
|
oldEnvMapIntensity = ref.current.envMapIntensity;
|
|
state.gl.toneMapping = NoToneMapping;
|
|
if (background) state.scene.background = background;
|
|
parent.material = discardMaterial;
|
|
if (backside) {
|
|
state.gl.setRenderTarget(fboBack);
|
|
state.gl.render(state.scene, state.camera);
|
|
parent.material = ref.current;
|
|
parent.material.buffer = fboBack.texture;
|
|
parent.material.thickness = backsideThickness;
|
|
parent.material.side = BackSide;
|
|
parent.material.envMapIntensity = backsideEnvMapIntensity;
|
|
}
|
|
state.gl.setRenderTarget(fboMain);
|
|
state.gl.render(state.scene, state.camera);
|
|
parent.material = ref.current;
|
|
parent.material.thickness = thickness;
|
|
parent.material.side = side;
|
|
parent.material.buffer = fboMain.texture;
|
|
parent.material.envMapIntensity = oldEnvMapIntensity;
|
|
state.scene.background = oldBg;
|
|
state.gl.setRenderTarget(null);
|
|
state.gl.toneMapping = oldTone;
|
|
}
|
|
}
|
|
});
|
|
React87.useImperativeHandle(fref, () => ref.current, []);
|
|
return React87.createElement("meshTransmissionMaterial", _extends({
|
|
// Samples must re-compile the shader so we memoize it
|
|
args: [samples, transmissionSampler],
|
|
ref
|
|
}, props, {
|
|
buffer: buffer2 || fboMain.texture,
|
|
_transmission: transmission,
|
|
anisotropicBlur: anisotropicBlur !== null && anisotropicBlur !== void 0 ? anisotropicBlur : anisotropy,
|
|
transmission: transmissionSampler ? transmission : 0,
|
|
thickness,
|
|
side
|
|
}));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/MeshDiscardMaterial.js
|
|
var React88 = __toESM(require_react());
|
|
var MeshDiscardMaterial = React88.forwardRef((props, fref) => {
|
|
extend({
|
|
DiscardMaterialImpl: DiscardMaterial
|
|
});
|
|
return React88.createElement("discardMaterialImpl", _extends({
|
|
ref: fref
|
|
}, props));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/MultiMaterial.js
|
|
var React89 = __toESM(require_react());
|
|
function MultiMaterial(props) {
|
|
const group = React89.useRef(null);
|
|
React89.useLayoutEffect(() => {
|
|
const parent = group.current.parent;
|
|
const geometry3 = parent == null ? void 0 : parent.geometry;
|
|
if (geometry3) {
|
|
const oldMaterial = parent.material;
|
|
parent.material = group.current.__r3f.children.map((instance) => instance.object);
|
|
const oldGroups = [...geometry3.groups];
|
|
geometry3.clearGroups();
|
|
parent.material.forEach((material, index2) => {
|
|
if (index2 < parent.material.length - 1) material.depthWrite = false;
|
|
geometry3.addGroup(0, Infinity, index2);
|
|
});
|
|
return () => {
|
|
parent.material = oldMaterial;
|
|
geometry3.groups = oldGroups;
|
|
};
|
|
}
|
|
});
|
|
return React89.createElement("group", _extends({
|
|
ref: group
|
|
}, props));
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/PointMaterial.js
|
|
var React90 = __toESM(require_react());
|
|
var opaque_fragment = version >= 154 ? "opaque_fragment" : "output_fragment";
|
|
var PointMaterialImpl = class extends PointsMaterial {
|
|
constructor(props) {
|
|
super(props);
|
|
this.onBeforeCompile = (shader, renderer) => {
|
|
const {
|
|
isWebGL2
|
|
} = renderer.capabilities;
|
|
shader.fragmentShader = shader.fragmentShader.replace(`#include <${opaque_fragment}>`, `
|
|
${!isWebGL2 ? `#extension GL_OES_standard_derivatives : enable
|
|
#include <${opaque_fragment}>` : `#include <${opaque_fragment}>`}
|
|
vec2 cxy = 2.0 * gl_PointCoord - 1.0;
|
|
float r = dot(cxy, cxy);
|
|
float delta = fwidth(r);
|
|
float mask = 1.0 - smoothstep(1.0 - delta, 1.0 + delta, r);
|
|
gl_FragColor = vec4(gl_FragColor.rgb, mask * gl_FragColor.a );
|
|
#include <tonemapping_fragment>
|
|
#include <${version >= 154 ? "colorspace_fragment" : "encodings_fragment"}>
|
|
`);
|
|
};
|
|
}
|
|
};
|
|
var PointMaterial = React90.forwardRef((props, ref) => {
|
|
const [material] = React90.useState(() => new PointMaterialImpl(null));
|
|
return React90.createElement("primitive", _extends({}, props, {
|
|
object: material,
|
|
ref,
|
|
attach: "material"
|
|
}));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/softShadows.js
|
|
var React91 = __toESM(require_react());
|
|
var pcss = ({
|
|
focus = 0,
|
|
size = 25,
|
|
samples = 10
|
|
} = {}) => `
|
|
#define PENUMBRA_FILTER_SIZE float(${size})
|
|
#define RGB_NOISE_FUNCTION(uv) (randRGB(uv))
|
|
vec3 randRGB(vec2 uv) {
|
|
return vec3(
|
|
fract(sin(dot(uv, vec2(12.75613, 38.12123))) * 13234.76575),
|
|
fract(sin(dot(uv, vec2(19.45531, 58.46547))) * 43678.23431),
|
|
fract(sin(dot(uv, vec2(23.67817, 78.23121))) * 93567.23423)
|
|
);
|
|
}
|
|
|
|
vec3 lowPassRandRGB(vec2 uv) {
|
|
// 3x3 convolution (average)
|
|
// can be implemented as separable with an extra buffer for a total of 6 samples instead of 9
|
|
vec3 result = vec3(0);
|
|
result += RGB_NOISE_FUNCTION(uv + vec2(-1.0, -1.0));
|
|
result += RGB_NOISE_FUNCTION(uv + vec2(-1.0, 0.0));
|
|
result += RGB_NOISE_FUNCTION(uv + vec2(-1.0, +1.0));
|
|
result += RGB_NOISE_FUNCTION(uv + vec2( 0.0, -1.0));
|
|
result += RGB_NOISE_FUNCTION(uv + vec2( 0.0, 0.0));
|
|
result += RGB_NOISE_FUNCTION(uv + vec2( 0.0, +1.0));
|
|
result += RGB_NOISE_FUNCTION(uv + vec2(+1.0, -1.0));
|
|
result += RGB_NOISE_FUNCTION(uv + vec2(+1.0, 0.0));
|
|
result += RGB_NOISE_FUNCTION(uv + vec2(+1.0, +1.0));
|
|
result *= 0.111111111; // 1.0 / 9.0
|
|
return result;
|
|
}
|
|
vec3 highPassRandRGB(vec2 uv) {
|
|
// by subtracting the low-pass signal from the original signal, we're being left with the high-pass signal
|
|
// hp(x) = x - lp(x)
|
|
return RGB_NOISE_FUNCTION(uv) - lowPassRandRGB(uv) + 0.5;
|
|
}
|
|
|
|
|
|
vec2 vogelDiskSample(int sampleIndex, int sampleCount, float angle) {
|
|
const float goldenAngle = 2.399963f; // radians
|
|
float r = sqrt(float(sampleIndex) + 0.5f) / sqrt(float(sampleCount));
|
|
float theta = float(sampleIndex) * goldenAngle + angle;
|
|
float sine = sin(theta);
|
|
float cosine = cos(theta);
|
|
return vec2(cosine, sine) * r;
|
|
}
|
|
float penumbraSize( const in float zReceiver, const in float zBlocker ) { // Parallel plane estimation
|
|
return (zReceiver - zBlocker) / zBlocker;
|
|
}
|
|
float findBlocker(sampler2D shadowMap, vec2 uv, float compare, float angle) {
|
|
float texelSize = 1.0 / float(textureSize(shadowMap, 0).x);
|
|
float blockerDepthSum = float(${focus});
|
|
float blockers = 0.0;
|
|
|
|
int j = 0;
|
|
vec2 offset = vec2(0.);
|
|
float depth = 0.;
|
|
|
|
#pragma unroll_loop_start
|
|
for(int i = 0; i < ${samples}; i ++) {
|
|
offset = (vogelDiskSample(j, ${samples}, angle) * texelSize) * 2.0 * PENUMBRA_FILTER_SIZE;
|
|
depth = unpackRGBAToDepth( texture2D( shadowMap, uv + offset));
|
|
if (depth < compare) {
|
|
blockerDepthSum += depth;
|
|
blockers++;
|
|
}
|
|
j++;
|
|
}
|
|
#pragma unroll_loop_end
|
|
|
|
if (blockers > 0.0) {
|
|
return blockerDepthSum / blockers;
|
|
}
|
|
return -1.0;
|
|
}
|
|
|
|
|
|
float vogelFilter(sampler2D shadowMap, vec2 uv, float zReceiver, float filterRadius, float angle) {
|
|
float texelSize = 1.0 / float(textureSize(shadowMap, 0).x);
|
|
float shadow = 0.0f;
|
|
int j = 0;
|
|
vec2 vogelSample = vec2(0.0);
|
|
vec2 offset = vec2(0.0);
|
|
#pragma unroll_loop_start
|
|
for (int i = 0; i < ${samples}; i++) {
|
|
vogelSample = vogelDiskSample(j, ${samples}, angle) * texelSize;
|
|
offset = vogelSample * (1.0 + filterRadius * float(${size}));
|
|
shadow += step( zReceiver, unpackRGBAToDepth( texture2D( shadowMap, uv + offset ) ) );
|
|
j++;
|
|
}
|
|
#pragma unroll_loop_end
|
|
return shadow * 1.0 / ${samples}.0;
|
|
}
|
|
|
|
float PCSS (sampler2D shadowMap, vec4 coords) {
|
|
vec2 uv = coords.xy;
|
|
float zReceiver = coords.z; // Assumed to be eye-space z in this code
|
|
float angle = highPassRandRGB(gl_FragCoord.xy).r * PI2;
|
|
float avgBlockerDepth = findBlocker(shadowMap, uv, zReceiver, angle);
|
|
if (avgBlockerDepth == -1.0) {
|
|
return 1.0;
|
|
}
|
|
float penumbraRatio = penumbraSize(zReceiver, avgBlockerDepth);
|
|
return vogelFilter(shadowMap, uv, zReceiver, 1.25 * penumbraRatio, angle);
|
|
}`;
|
|
function reset(gl, scene, camera) {
|
|
scene.traverse((object) => {
|
|
if (object.material) {
|
|
gl.properties.remove(object.material);
|
|
object.material.dispose == null || object.material.dispose();
|
|
}
|
|
});
|
|
gl.info.programs.length = 0;
|
|
gl.compile(scene, camera);
|
|
}
|
|
function SoftShadows({
|
|
focus = 0,
|
|
samples = 10,
|
|
size = 25
|
|
}) {
|
|
const gl = useThree((state) => state.gl);
|
|
const scene = useThree((state) => state.scene);
|
|
const camera = useThree((state) => state.camera);
|
|
React91.useEffect(() => {
|
|
const original = ShaderChunk.shadowmap_pars_fragment;
|
|
ShaderChunk.shadowmap_pars_fragment = ShaderChunk.shadowmap_pars_fragment.replace("#ifdef USE_SHADOWMAP", "#ifdef USE_SHADOWMAP\n" + pcss({
|
|
size,
|
|
samples,
|
|
focus
|
|
})).replace("#if defined( SHADOWMAP_TYPE_PCF )", "\nreturn PCSS(shadowMap, shadowCoord);\n#if defined( SHADOWMAP_TYPE_PCF )");
|
|
reset(gl, scene, camera);
|
|
return () => {
|
|
ShaderChunk.shadowmap_pars_fragment = original;
|
|
reset(gl, scene, camera);
|
|
};
|
|
}, [focus, size, samples]);
|
|
return null;
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/shapes.js
|
|
var React92 = __toESM(require_react());
|
|
function create2(type, effect) {
|
|
const El = type + "Geometry";
|
|
return React92.forwardRef(({
|
|
args,
|
|
children,
|
|
...props
|
|
}, fref) => {
|
|
const ref = React92.useRef(null);
|
|
React92.useImperativeHandle(fref, () => ref.current);
|
|
React92.useLayoutEffect(() => void (effect == null ? void 0 : effect(ref.current)));
|
|
return React92.createElement("mesh", _extends({
|
|
ref
|
|
}, props), React92.createElement(El, {
|
|
attach: "geometry",
|
|
args
|
|
}), children);
|
|
});
|
|
}
|
|
var Box = create2("box");
|
|
var Circle = create2("circle");
|
|
var Cone = create2("cone");
|
|
var Cylinder = create2("cylinder");
|
|
var Sphere2 = create2("sphere");
|
|
var Plane2 = create2("plane");
|
|
var Tube = create2("tube");
|
|
var Torus = create2("torus");
|
|
var TorusKnot = create2("torusKnot");
|
|
var Tetrahedron = create2("tetrahedron");
|
|
var Ring = create2("ring");
|
|
var Polyhedron = create2("polyhedron");
|
|
var Icosahedron = create2("icosahedron");
|
|
var Octahedron = create2("octahedron");
|
|
var Dodecahedron = create2("dodecahedron");
|
|
var Extrude = create2("extrude");
|
|
var Lathe = create2("lathe");
|
|
var Capsule = create2("capsule");
|
|
var Shape2 = create2("shape", ({
|
|
geometry: geometry3
|
|
}) => {
|
|
const pos = geometry3.attributes.position;
|
|
const b32 = new Box3().setFromBufferAttribute(pos);
|
|
const b3size = new Vector3();
|
|
b32.getSize(b3size);
|
|
const uv = [];
|
|
let x = 0, y = 0, u = 0, v5 = 0;
|
|
for (let i3 = 0; i3 < pos.count; i3++) {
|
|
x = pos.getX(i3);
|
|
y = pos.getY(i3);
|
|
u = (x - b32.min.x) / b3size.x;
|
|
v5 = (y - b32.min.y) / b3size.y;
|
|
uv.push(u, v5);
|
|
}
|
|
geometry3.setAttribute("uv", new Float32BufferAttribute(uv, 2));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/RoundedBox.js
|
|
var React93 = __toESM(require_react());
|
|
var eps = 1e-5;
|
|
function createShape(width, height, radius0) {
|
|
const shape = new Shape();
|
|
const radius = radius0 - eps;
|
|
shape.absarc(eps, eps, eps, -Math.PI / 2, -Math.PI, true);
|
|
shape.absarc(eps, height - radius * 2, eps, Math.PI, Math.PI / 2, true);
|
|
shape.absarc(width - radius * 2, height - radius * 2, eps, Math.PI / 2, 0, true);
|
|
shape.absarc(width - radius * 2, eps, eps, 0, -Math.PI / 2, true);
|
|
return shape;
|
|
}
|
|
var RoundedBox = React93.forwardRef(function RoundedBox2({
|
|
args: [width = 1, height = 1, depth = 1] = [],
|
|
radius = 0.05,
|
|
steps = 1,
|
|
smoothness = 4,
|
|
bevelSegments = 4,
|
|
creaseAngle = 0.4,
|
|
children,
|
|
...rest
|
|
}, ref) {
|
|
return React93.createElement("mesh", _extends({
|
|
ref
|
|
}, rest), React93.createElement(RoundedBoxGeometry, {
|
|
args: [width, height, depth],
|
|
radius,
|
|
steps,
|
|
smoothness,
|
|
bevelSegments,
|
|
creaseAngle
|
|
}), children);
|
|
});
|
|
var RoundedBoxGeometry = React93.forwardRef(function RoundedBoxGeometry2({
|
|
args: [width = 1, height = 1, depth = 1] = [],
|
|
radius = 0.05,
|
|
steps = 1,
|
|
smoothness = 4,
|
|
bevelSegments = 4,
|
|
creaseAngle = 0.4,
|
|
...rest
|
|
}, ref) {
|
|
const shape = React93.useMemo(() => createShape(width, height, radius), [width, height, radius]);
|
|
const params = React93.useMemo(() => ({
|
|
depth: depth - radius * 2,
|
|
bevelEnabled: true,
|
|
bevelSegments: bevelSegments * 2,
|
|
steps,
|
|
bevelSize: radius - eps,
|
|
bevelThickness: radius,
|
|
curveSegments: smoothness
|
|
}), [depth, radius, smoothness, bevelSegments, steps]);
|
|
const geomRef = React93.useRef(null);
|
|
React93.useLayoutEffect(() => {
|
|
if (geomRef.current) {
|
|
geomRef.current.center();
|
|
toCreasedNormals(geomRef.current, creaseAngle);
|
|
}
|
|
}, [shape, params, creaseAngle]);
|
|
React93.useImperativeHandle(ref, () => geomRef.current);
|
|
return React93.createElement("extrudeGeometry", _extends({
|
|
ref: geomRef,
|
|
args: [shape, params]
|
|
}, rest));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/ScreenQuad.js
|
|
var React94 = __toESM(require_react());
|
|
function createScreenQuadGeometry() {
|
|
const geometry3 = new BufferGeometry();
|
|
const vertices = new Float32Array([-1, -1, 3, -1, -1, 3]);
|
|
geometry3.boundingSphere = new Sphere();
|
|
geometry3.boundingSphere.set(new Vector3(), Infinity);
|
|
geometry3.setAttribute("position", new BufferAttribute(vertices, 2));
|
|
return geometry3;
|
|
}
|
|
var ScreenQuad = React94.forwardRef(function ScreenQuad2({
|
|
children,
|
|
...restProps
|
|
}, ref) {
|
|
const geometry3 = React94.useMemo(createScreenQuadGeometry, []);
|
|
return React94.createElement("mesh", _extends({
|
|
ref,
|
|
geometry: geometry3,
|
|
frustumCulled: false
|
|
}, restProps), children);
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Resize.js
|
|
var React95 = __toESM(require_react());
|
|
var Resize = React95.forwardRef(({
|
|
children,
|
|
width,
|
|
height,
|
|
depth,
|
|
box3,
|
|
precise = true,
|
|
...props
|
|
}, fRef) => {
|
|
const ref = React95.useRef(null);
|
|
const outer = React95.useRef(null);
|
|
const inner = React95.useRef(null);
|
|
React95.useLayoutEffect(() => {
|
|
outer.current.matrixWorld.identity();
|
|
let box = box3 || new Box3().setFromObject(inner.current, precise);
|
|
const w = box.max.x - box.min.x;
|
|
const h = box.max.y - box.min.y;
|
|
const d2 = box.max.z - box.min.z;
|
|
let dimension = Math.max(w, h, d2);
|
|
if (width) dimension = w;
|
|
if (height) dimension = h;
|
|
if (depth) dimension = d2;
|
|
outer.current.scale.setScalar(1 / dimension);
|
|
}, [width, height, depth, box3, precise]);
|
|
React95.useImperativeHandle(fRef, () => ref.current, []);
|
|
return React95.createElement("group", _extends({
|
|
ref
|
|
}, props), React95.createElement("group", {
|
|
ref: outer
|
|
}, React95.createElement("group", {
|
|
ref: inner
|
|
}, children)));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Bounds.js
|
|
var React96 = __toESM(require_react());
|
|
var AnimationState = (function(AnimationState2) {
|
|
AnimationState2[AnimationState2["NONE"] = 0] = "NONE";
|
|
AnimationState2[AnimationState2["START"] = 1] = "START";
|
|
AnimationState2[AnimationState2["ACTIVE"] = 2] = "ACTIVE";
|
|
return AnimationState2;
|
|
})(AnimationState || {});
|
|
var isOrthographic = (def) => def && def.isOrthographicCamera;
|
|
var isBox3 = (def) => def && def.isBox3;
|
|
var interpolateFuncDefault = (t2) => {
|
|
return 1 - Math.exp(-5 * t2) + 7e-3 * t2;
|
|
};
|
|
var context6 = React96.createContext(null);
|
|
function Bounds({
|
|
children,
|
|
maxDuration = 1,
|
|
margin = 1.2,
|
|
observe,
|
|
fit,
|
|
clip,
|
|
interpolateFunc = interpolateFuncDefault,
|
|
onFit
|
|
}) {
|
|
const ref = React96.useRef(null);
|
|
const {
|
|
camera,
|
|
size,
|
|
invalidate
|
|
} = useThree();
|
|
const controls = useThree((state) => state.controls);
|
|
const onFitRef = React96.useRef(onFit);
|
|
onFitRef.current = onFit;
|
|
const origin2 = React96.useRef({
|
|
camPos: new Vector3(),
|
|
camRot: new Quaternion(),
|
|
camZoom: 1
|
|
});
|
|
const goal = React96.useRef({
|
|
camPos: void 0,
|
|
camRot: void 0,
|
|
camZoom: void 0,
|
|
camUp: void 0,
|
|
target: void 0
|
|
});
|
|
const animationState = React96.useRef(AnimationState.NONE);
|
|
const t2 = React96.useRef(0);
|
|
const [box] = React96.useState(() => new Box3());
|
|
const api = React96.useMemo(() => {
|
|
function getSize() {
|
|
const boxSize = box.getSize(new Vector3());
|
|
const center2 = box.getCenter(new Vector3());
|
|
const maxSize = Math.max(boxSize.x, boxSize.y, boxSize.z);
|
|
const fitHeightDistance = isOrthographic(camera) ? maxSize * 4 : maxSize / (2 * Math.atan(Math.PI * camera.fov / 360));
|
|
const fitWidthDistance = isOrthographic(camera) ? maxSize * 4 : fitHeightDistance / camera.aspect;
|
|
const distance3 = margin * Math.max(fitHeightDistance, fitWidthDistance);
|
|
return {
|
|
box,
|
|
size: boxSize,
|
|
center: center2,
|
|
distance: distance3
|
|
};
|
|
}
|
|
return {
|
|
getSize,
|
|
refresh(object) {
|
|
if (isBox3(object)) box.copy(object);
|
|
else {
|
|
const target2 = object || ref.current;
|
|
if (!target2) return this;
|
|
target2.updateWorldMatrix(true, true);
|
|
box.setFromObject(target2);
|
|
}
|
|
if (box.isEmpty()) {
|
|
const max = camera.position.length() || 10;
|
|
box.setFromCenterAndSize(new Vector3(), new Vector3(max, max, max));
|
|
}
|
|
origin2.current.camPos.copy(camera.position);
|
|
origin2.current.camRot.copy(camera.quaternion);
|
|
isOrthographic(camera) && (origin2.current.camZoom = camera.zoom);
|
|
goal.current.camPos = void 0;
|
|
goal.current.camRot = void 0;
|
|
goal.current.camZoom = void 0;
|
|
goal.current.camUp = void 0;
|
|
goal.current.target = void 0;
|
|
return this;
|
|
},
|
|
reset() {
|
|
const {
|
|
center: center2,
|
|
distance: distance3
|
|
} = getSize();
|
|
const direction2 = camera.position.clone().sub(center2).normalize();
|
|
goal.current.camPos = center2.clone().addScaledVector(direction2, distance3);
|
|
goal.current.target = center2.clone();
|
|
const mCamRot = new Matrix4().lookAt(goal.current.camPos, goal.current.target, camera.up);
|
|
goal.current.camRot = new Quaternion().setFromRotationMatrix(mCamRot);
|
|
animationState.current = AnimationState.START;
|
|
t2.current = 0;
|
|
return this;
|
|
},
|
|
moveTo(position2) {
|
|
goal.current.camPos = Array.isArray(position2) ? new Vector3(...position2) : position2.clone();
|
|
animationState.current = AnimationState.START;
|
|
t2.current = 0;
|
|
return this;
|
|
},
|
|
lookAt({
|
|
target: target2,
|
|
up
|
|
}) {
|
|
goal.current.target = Array.isArray(target2) ? new Vector3(...target2) : target2.clone();
|
|
if (up) {
|
|
goal.current.camUp = Array.isArray(up) ? new Vector3(...up) : up.clone();
|
|
} else {
|
|
goal.current.camUp = camera.up.clone();
|
|
}
|
|
const mCamRot = new Matrix4().lookAt(goal.current.camPos || camera.position, goal.current.target, goal.current.camUp);
|
|
goal.current.camRot = new Quaternion().setFromRotationMatrix(mCamRot);
|
|
animationState.current = AnimationState.START;
|
|
t2.current = 0;
|
|
return this;
|
|
},
|
|
/**
|
|
* @deprecated Use moveTo and lookAt instead
|
|
*/
|
|
to({
|
|
position: position2,
|
|
target: target2
|
|
}) {
|
|
return this.moveTo(position2).lookAt({
|
|
target: target2
|
|
});
|
|
},
|
|
fit() {
|
|
if (!isOrthographic(camera)) {
|
|
return this.reset();
|
|
}
|
|
let maxHeight = 0, maxWidth = 0;
|
|
const vertices = [new Vector3(box.min.x, box.min.y, box.min.z), new Vector3(box.min.x, box.max.y, box.min.z), new Vector3(box.min.x, box.min.y, box.max.z), new Vector3(box.min.x, box.max.y, box.max.z), new Vector3(box.max.x, box.max.y, box.max.z), new Vector3(box.max.x, box.max.y, box.min.z), new Vector3(box.max.x, box.min.y, box.max.z), new Vector3(box.max.x, box.min.y, box.min.z)];
|
|
const pos = goal.current.camPos || camera.position;
|
|
const target2 = goal.current.target || (controls == null ? void 0 : controls.target);
|
|
const up = goal.current.camUp || camera.up;
|
|
const mCamWInv = target2 ? new Matrix4().lookAt(pos, target2, up).setPosition(pos).invert() : camera.matrixWorldInverse;
|
|
for (const v5 of vertices) {
|
|
v5.applyMatrix4(mCamWInv);
|
|
maxHeight = Math.max(maxHeight, Math.abs(v5.y));
|
|
maxWidth = Math.max(maxWidth, Math.abs(v5.x));
|
|
}
|
|
maxHeight *= 2;
|
|
maxWidth *= 2;
|
|
const zoomForHeight = (camera.top - camera.bottom) / maxHeight;
|
|
const zoomForWidth = (camera.right - camera.left) / maxWidth;
|
|
goal.current.camZoom = Math.min(zoomForHeight, zoomForWidth) / margin;
|
|
animationState.current = AnimationState.START;
|
|
t2.current = 0;
|
|
onFitRef.current && onFitRef.current(this.getSize());
|
|
return this;
|
|
},
|
|
clip() {
|
|
const {
|
|
distance: distance3
|
|
} = getSize();
|
|
camera.near = distance3 / 100;
|
|
camera.far = distance3 * 100;
|
|
camera.updateProjectionMatrix();
|
|
if (controls) {
|
|
controls.maxDistance = distance3 * 10;
|
|
controls.update();
|
|
}
|
|
invalidate();
|
|
return this;
|
|
}
|
|
};
|
|
}, [box, camera, controls, margin, invalidate]);
|
|
React96.useLayoutEffect(() => {
|
|
if (controls) {
|
|
const callback = () => {
|
|
if (controls && goal.current.target && animationState.current !== AnimationState.NONE) {
|
|
const front = new Vector3().setFromMatrixColumn(camera.matrix, 2);
|
|
const d0 = origin2.current.camPos.distanceTo(controls.target);
|
|
const d1 = (goal.current.camPos || origin2.current.camPos).distanceTo(goal.current.target);
|
|
const d2 = (1 - t2.current) * d0 + t2.current * d1;
|
|
controls.target.copy(camera.position).addScaledVector(front, -d2);
|
|
controls.update();
|
|
}
|
|
animationState.current = AnimationState.NONE;
|
|
};
|
|
controls.addEventListener("start", callback);
|
|
return () => controls.removeEventListener("start", callback);
|
|
}
|
|
}, [controls]);
|
|
const count = React96.useRef(0);
|
|
React96.useLayoutEffect(() => {
|
|
if (observe || count.current++ === 0) {
|
|
api.refresh();
|
|
if (fit) api.reset().fit();
|
|
if (clip) api.clip();
|
|
}
|
|
}, [size, clip, fit, observe, camera, controls]);
|
|
useFrame((state, delta) => {
|
|
if (animationState.current === AnimationState.START) {
|
|
animationState.current = AnimationState.ACTIVE;
|
|
invalidate();
|
|
} else if (animationState.current === AnimationState.ACTIVE) {
|
|
t2.current += delta / maxDuration;
|
|
if (t2.current >= 1) {
|
|
goal.current.camPos && camera.position.copy(goal.current.camPos);
|
|
goal.current.camRot && camera.quaternion.copy(goal.current.camRot);
|
|
goal.current.camUp && camera.up.copy(goal.current.camUp);
|
|
goal.current.camZoom && isOrthographic(camera) && (camera.zoom = goal.current.camZoom);
|
|
camera.updateMatrixWorld();
|
|
camera.updateProjectionMatrix();
|
|
if (controls && goal.current.target) {
|
|
controls.target.copy(goal.current.target);
|
|
controls.update();
|
|
}
|
|
animationState.current = AnimationState.NONE;
|
|
} else {
|
|
const k = interpolateFunc(t2.current);
|
|
goal.current.camPos && camera.position.lerpVectors(origin2.current.camPos, goal.current.camPos, k);
|
|
goal.current.camRot && camera.quaternion.slerpQuaternions(origin2.current.camRot, goal.current.camRot, k);
|
|
goal.current.camUp && camera.up.set(0, 1, 0).applyQuaternion(camera.quaternion);
|
|
goal.current.camZoom && isOrthographic(camera) && (camera.zoom = (1 - k) * origin2.current.camZoom + k * goal.current.camZoom);
|
|
camera.updateMatrixWorld();
|
|
camera.updateProjectionMatrix();
|
|
}
|
|
invalidate();
|
|
}
|
|
});
|
|
return React96.createElement("group", {
|
|
ref
|
|
}, React96.createElement(context6.Provider, {
|
|
value: api
|
|
}, children));
|
|
}
|
|
function useBounds() {
|
|
return React96.useContext(context6);
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/CameraShake.js
|
|
var React97 = __toESM(require_react());
|
|
var CameraShake = React97.forwardRef(({
|
|
intensity = 1,
|
|
decay,
|
|
decayRate = 0.65,
|
|
maxYaw = 0.1,
|
|
maxPitch = 0.1,
|
|
maxRoll = 0.1,
|
|
yawFrequency = 0.1,
|
|
pitchFrequency = 0.1,
|
|
rollFrequency = 0.1
|
|
}, ref) => {
|
|
const camera = useThree((state) => state.camera);
|
|
const defaultControls = useThree((state) => state.controls);
|
|
const intensityRef = React97.useRef(intensity);
|
|
const initialRotation = React97.useRef(camera.rotation.clone());
|
|
const [yawNoise] = React97.useState(() => new SimplexNoise());
|
|
const [pitchNoise] = React97.useState(() => new SimplexNoise());
|
|
const [rollNoise] = React97.useState(() => new SimplexNoise());
|
|
const constrainIntensity = () => {
|
|
if (intensityRef.current < 0 || intensityRef.current > 1) {
|
|
intensityRef.current = intensityRef.current < 0 ? 0 : 1;
|
|
}
|
|
};
|
|
React97.useImperativeHandle(ref, () => ({
|
|
getIntensity: () => intensityRef.current,
|
|
setIntensity: (val) => {
|
|
intensityRef.current = val;
|
|
constrainIntensity();
|
|
}
|
|
}), []);
|
|
React97.useEffect(() => {
|
|
if (defaultControls) {
|
|
const callback = () => void (initialRotation.current = camera.rotation.clone());
|
|
defaultControls.addEventListener("change", callback);
|
|
callback();
|
|
return () => void defaultControls.removeEventListener("change", callback);
|
|
}
|
|
}, [camera, defaultControls]);
|
|
useFrame((state, delta) => {
|
|
const shake = Math.pow(intensityRef.current, 2);
|
|
const yaw = maxYaw * shake * yawNoise.noise(state.clock.elapsedTime * yawFrequency, 1);
|
|
const pitch = maxPitch * shake * pitchNoise.noise(state.clock.elapsedTime * pitchFrequency, 1);
|
|
const roll = maxRoll * shake * rollNoise.noise(state.clock.elapsedTime * rollFrequency, 1);
|
|
camera.rotation.set(initialRotation.current.x + pitch, initialRotation.current.y + yaw, initialRotation.current.z + roll);
|
|
if (decay && intensityRef.current > 0) {
|
|
intensityRef.current -= decayRate * delta;
|
|
constrainIntensity();
|
|
}
|
|
});
|
|
return null;
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Float.js
|
|
var React98 = __toESM(require_react());
|
|
var Float = React98.forwardRef(({
|
|
children,
|
|
enabled = true,
|
|
speed = 1,
|
|
rotationIntensity = 1,
|
|
floatIntensity = 1,
|
|
floatingRange = [-0.1, 0.1],
|
|
autoInvalidate = false,
|
|
...props
|
|
}, forwardRef82) => {
|
|
const ref = React98.useRef(null);
|
|
React98.useImperativeHandle(forwardRef82, () => ref.current, []);
|
|
const offset = React98.useRef(Math.random() * 1e4);
|
|
useFrame((state) => {
|
|
var _floatingRange$, _floatingRange$2;
|
|
if (!enabled || speed === 0) return;
|
|
if (autoInvalidate) state.invalidate();
|
|
const t2 = offset.current + state.clock.elapsedTime;
|
|
ref.current.rotation.x = Math.cos(t2 / 4 * speed) / 8 * rotationIntensity;
|
|
ref.current.rotation.y = Math.sin(t2 / 4 * speed) / 8 * rotationIntensity;
|
|
ref.current.rotation.z = Math.sin(t2 / 4 * speed) / 20 * rotationIntensity;
|
|
let yPosition = Math.sin(t2 / 4 * speed) / 10;
|
|
yPosition = MathUtils.mapLinear(yPosition, -0.1, 0.1, (_floatingRange$ = floatingRange == null ? void 0 : floatingRange[0]) !== null && _floatingRange$ !== void 0 ? _floatingRange$ : -0.1, (_floatingRange$2 = floatingRange == null ? void 0 : floatingRange[1]) !== null && _floatingRange$2 !== void 0 ? _floatingRange$2 : 0.1);
|
|
ref.current.position.y = yPosition * floatIntensity;
|
|
ref.current.updateMatrix();
|
|
});
|
|
return React98.createElement("group", props, React98.createElement("group", {
|
|
ref,
|
|
matrixAutoUpdate: false
|
|
}, children));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Stage.js
|
|
var React102 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/core/Environment.js
|
|
var React99 = __toESM(require_react());
|
|
|
|
// node_modules/@monogrid/gainmap-js/dist/QuadRenderer-Bj1xl_EK.js
|
|
var getBufferForType = (type, width, height) => {
|
|
let out7;
|
|
switch (type) {
|
|
case UnsignedByteType:
|
|
out7 = new Uint8ClampedArray(width * height * 4);
|
|
break;
|
|
case HalfFloatType:
|
|
out7 = new Uint16Array(width * height * 4);
|
|
break;
|
|
case UnsignedIntType:
|
|
out7 = new Uint32Array(width * height * 4);
|
|
break;
|
|
case ByteType:
|
|
out7 = new Int8Array(width * height * 4);
|
|
break;
|
|
case ShortType:
|
|
out7 = new Int16Array(width * height * 4);
|
|
break;
|
|
case IntType:
|
|
out7 = new Int32Array(width * height * 4);
|
|
break;
|
|
case FloatType:
|
|
out7 = new Float32Array(width * height * 4);
|
|
break;
|
|
default:
|
|
throw new Error("Unsupported data type");
|
|
}
|
|
return out7;
|
|
};
|
|
var _canReadPixelsResult;
|
|
var canReadPixels = (type, renderer, camera, renderTargetOptions) => {
|
|
if (_canReadPixelsResult !== void 0)
|
|
return _canReadPixelsResult;
|
|
const testRT = new WebGLRenderTarget(1, 1, renderTargetOptions);
|
|
renderer.setRenderTarget(testRT);
|
|
const mesh = new Mesh(new PlaneGeometry(), new MeshBasicMaterial({ color: 16777215 }));
|
|
renderer.render(mesh, camera);
|
|
renderer.setRenderTarget(null);
|
|
const out7 = getBufferForType(type, testRT.width, testRT.height);
|
|
renderer.readRenderTargetPixels(testRT, 0, 0, testRT.width, testRT.height, out7);
|
|
testRT.dispose();
|
|
mesh.geometry.dispose();
|
|
mesh.material.dispose();
|
|
_canReadPixelsResult = out7[0] !== 0;
|
|
return _canReadPixelsResult;
|
|
};
|
|
var QuadRenderer = class _QuadRenderer {
|
|
_renderer;
|
|
_rendererIsDisposable = false;
|
|
_material;
|
|
_scene;
|
|
_camera;
|
|
_quad;
|
|
_renderTarget;
|
|
_width;
|
|
_height;
|
|
_type;
|
|
_colorSpace;
|
|
_supportsReadPixels = true;
|
|
/**
|
|
* Constructs a new QuadRenderer
|
|
*
|
|
* @param options Parameters for this QuadRenderer
|
|
*/
|
|
constructor(options) {
|
|
this._width = options.width;
|
|
this._height = options.height;
|
|
this._type = options.type;
|
|
this._colorSpace = options.colorSpace;
|
|
const rtOptions = {
|
|
// fixed options
|
|
format: RGBAFormat,
|
|
depthBuffer: false,
|
|
stencilBuffer: false,
|
|
// user options
|
|
type: this._type,
|
|
// set in class property
|
|
colorSpace: this._colorSpace,
|
|
// set in class property
|
|
anisotropy: options.renderTargetOptions?.anisotropy !== void 0 ? options.renderTargetOptions?.anisotropy : 1,
|
|
generateMipmaps: options.renderTargetOptions?.generateMipmaps !== void 0 ? options.renderTargetOptions?.generateMipmaps : false,
|
|
magFilter: options.renderTargetOptions?.magFilter !== void 0 ? options.renderTargetOptions?.magFilter : LinearFilter,
|
|
minFilter: options.renderTargetOptions?.minFilter !== void 0 ? options.renderTargetOptions?.minFilter : LinearFilter,
|
|
samples: options.renderTargetOptions?.samples !== void 0 ? options.renderTargetOptions?.samples : void 0,
|
|
wrapS: options.renderTargetOptions?.wrapS !== void 0 ? options.renderTargetOptions?.wrapS : ClampToEdgeWrapping,
|
|
wrapT: options.renderTargetOptions?.wrapT !== void 0 ? options.renderTargetOptions?.wrapT : ClampToEdgeWrapping
|
|
};
|
|
this._material = options.material;
|
|
if (options.renderer) {
|
|
this._renderer = options.renderer;
|
|
} else {
|
|
this._renderer = _QuadRenderer.instantiateRenderer();
|
|
this._rendererIsDisposable = true;
|
|
}
|
|
this._scene = new Scene();
|
|
this._camera = new OrthographicCamera();
|
|
this._camera.position.set(0, 0, 10);
|
|
this._camera.left = -0.5;
|
|
this._camera.right = 0.5;
|
|
this._camera.top = 0.5;
|
|
this._camera.bottom = -0.5;
|
|
this._camera.updateProjectionMatrix();
|
|
if (!canReadPixels(this._type, this._renderer, this._camera, rtOptions)) {
|
|
let alternativeType;
|
|
switch (this._type) {
|
|
case HalfFloatType:
|
|
alternativeType = this._renderer.extensions.has("EXT_color_buffer_float") ? FloatType : void 0;
|
|
break;
|
|
}
|
|
if (alternativeType !== void 0) {
|
|
console.warn(`This browser does not support reading pixels from ${this._type} RenderTargets, switching to ${FloatType}`);
|
|
this._type = alternativeType;
|
|
} else {
|
|
this._supportsReadPixels = false;
|
|
console.warn("This browser dos not support toArray or toDataTexture, calls to those methods will result in an error thrown");
|
|
}
|
|
}
|
|
this._quad = new Mesh(new PlaneGeometry(), this._material);
|
|
this._quad.geometry.computeBoundingBox();
|
|
this._scene.add(this._quad);
|
|
this._renderTarget = new WebGLRenderTarget(this.width, this.height, rtOptions);
|
|
this._renderTarget.texture.mapping = options.renderTargetOptions?.mapping !== void 0 ? options.renderTargetOptions?.mapping : UVMapping;
|
|
}
|
|
/**
|
|
* Instantiates a temporary renderer
|
|
*
|
|
* @returns
|
|
*/
|
|
static instantiateRenderer() {
|
|
const renderer = new WebGLRenderer();
|
|
renderer.setSize(128, 128);
|
|
return renderer;
|
|
}
|
|
/**
|
|
* Renders the input texture using the specified material
|
|
*/
|
|
render = () => {
|
|
this._renderer.setRenderTarget(this._renderTarget);
|
|
try {
|
|
this._renderer.render(this._scene, this._camera);
|
|
} catch (e2) {
|
|
this._renderer.setRenderTarget(null);
|
|
throw e2;
|
|
}
|
|
this._renderer.setRenderTarget(null);
|
|
};
|
|
/**
|
|
* Obtains a Buffer containing the rendered texture.
|
|
*
|
|
* @throws Error if the browser cannot read pixels from this RenderTarget type.
|
|
* @returns a TypedArray containing RGBA values from this renderer
|
|
*/
|
|
toArray() {
|
|
if (!this._supportsReadPixels)
|
|
throw new Error("Can't read pixels in this browser");
|
|
const out7 = getBufferForType(this._type, this._width, this._height);
|
|
this._renderer.readRenderTargetPixels(this._renderTarget, 0, 0, this._width, this._height, out7);
|
|
return out7;
|
|
}
|
|
/**
|
|
* Performs a readPixel operation in the renderTarget
|
|
* and returns a DataTexture containing the read data
|
|
*
|
|
* @param options options
|
|
* @returns
|
|
*/
|
|
toDataTexture(options) {
|
|
const returnValue = new DataTexture(
|
|
// fixed values
|
|
this.toArray(),
|
|
this.width,
|
|
this.height,
|
|
RGBAFormat,
|
|
this._type,
|
|
// user values
|
|
options?.mapping || UVMapping,
|
|
options?.wrapS || ClampToEdgeWrapping,
|
|
options?.wrapT || ClampToEdgeWrapping,
|
|
options?.magFilter || LinearFilter,
|
|
options?.minFilter || LinearFilter,
|
|
options?.anisotropy || 1,
|
|
// fixed value
|
|
LinearSRGBColorSpace
|
|
);
|
|
returnValue.generateMipmaps = options?.generateMipmaps !== void 0 ? options?.generateMipmaps : false;
|
|
return returnValue;
|
|
}
|
|
/**
|
|
* If using a disposable renderer, it will dispose it.
|
|
*/
|
|
disposeOnDemandRenderer() {
|
|
this._renderer.setRenderTarget(null);
|
|
if (this._rendererIsDisposable) {
|
|
this._renderer.dispose();
|
|
this._renderer.forceContextLoss();
|
|
}
|
|
}
|
|
/**
|
|
* Will dispose of **all** assets used by this renderer.
|
|
*
|
|
*
|
|
* @param disposeRenderTarget will dispose of the renderTarget which will not be usable later
|
|
* set this to true if you passed the `renderTarget.texture` to a `PMREMGenerator`
|
|
* or are otherwise done with it.
|
|
*
|
|
* @example
|
|
* ```js
|
|
* const loader = new HDRJPGLoader(renderer)
|
|
* const result = await loader.loadAsync('gainmap.jpeg')
|
|
* const mesh = new Mesh(geometry, new MeshBasicMaterial({ map: result.renderTarget.texture }) )
|
|
* // DO NOT dispose the renderTarget here,
|
|
* // it is used directly in the material
|
|
* result.dispose()
|
|
* ```
|
|
*
|
|
* @example
|
|
* ```js
|
|
* const loader = new HDRJPGLoader(renderer)
|
|
* const pmremGenerator = new PMREMGenerator( renderer );
|
|
* const result = await loader.loadAsync('gainmap.jpeg')
|
|
* const envMap = pmremGenerator.fromEquirectangular(result.renderTarget.texture)
|
|
* const mesh = new Mesh(geometry, new MeshStandardMaterial({ envMap }) )
|
|
* // renderTarget can be disposed here
|
|
* // because it was used to generate a PMREM texture
|
|
* result.dispose(true)
|
|
* ```
|
|
*/
|
|
dispose(disposeRenderTarget) {
|
|
this.disposeOnDemandRenderer();
|
|
if (disposeRenderTarget) {
|
|
this.renderTarget.dispose();
|
|
}
|
|
if (this.material instanceof ShaderMaterial) {
|
|
Object.values(this.material.uniforms).forEach((v5) => {
|
|
if (v5.value instanceof Texture)
|
|
v5.value.dispose();
|
|
});
|
|
}
|
|
Object.values(this.material).forEach((value) => {
|
|
if (value instanceof Texture)
|
|
value.dispose();
|
|
});
|
|
this.material.dispose();
|
|
this._quad.geometry.dispose();
|
|
}
|
|
/**
|
|
* Width of the texture
|
|
*/
|
|
get width() {
|
|
return this._width;
|
|
}
|
|
set width(value) {
|
|
this._width = value;
|
|
this._renderTarget.setSize(this._width, this._height);
|
|
}
|
|
/**
|
|
* Height of the texture
|
|
*/
|
|
get height() {
|
|
return this._height;
|
|
}
|
|
set height(value) {
|
|
this._height = value;
|
|
this._renderTarget.setSize(this._width, this._height);
|
|
}
|
|
/**
|
|
* The renderer used
|
|
*/
|
|
get renderer() {
|
|
return this._renderer;
|
|
}
|
|
/**
|
|
* The `WebGLRenderTarget` used.
|
|
*/
|
|
get renderTarget() {
|
|
return this._renderTarget;
|
|
}
|
|
set renderTarget(value) {
|
|
this._renderTarget = value;
|
|
this._width = value.width;
|
|
this._height = value.height;
|
|
}
|
|
/**
|
|
* The `Material` used.
|
|
*/
|
|
get material() {
|
|
return this._material;
|
|
}
|
|
/**
|
|
*
|
|
*/
|
|
get type() {
|
|
return this._type;
|
|
}
|
|
get colorSpace() {
|
|
return this._colorSpace;
|
|
}
|
|
};
|
|
|
|
// node_modules/@monogrid/gainmap-js/dist/Loader-DLI-_JDP.js
|
|
function createDecodeFunction(config) {
|
|
return (params) => {
|
|
const { sdr, gainMap, renderer } = params;
|
|
if (sdr.colorSpace !== SRGBColorSpace) {
|
|
console.warn("SDR Colorspace needs to be *SRGBColorSpace*, setting it automatically");
|
|
sdr.colorSpace = SRGBColorSpace;
|
|
}
|
|
sdr.needsUpdate = true;
|
|
if (gainMap.colorSpace !== LinearSRGBColorSpace) {
|
|
console.warn("Gainmap Colorspace needs to be *LinearSRGBColorSpace*, setting it automatically");
|
|
gainMap.colorSpace = LinearSRGBColorSpace;
|
|
}
|
|
gainMap.needsUpdate = true;
|
|
const material = config.createMaterial({
|
|
...params,
|
|
sdr,
|
|
gainMap
|
|
});
|
|
const quadRenderer = config.createQuadRenderer({
|
|
width: sdr.image.width,
|
|
height: sdr.image.height,
|
|
type: HalfFloatType,
|
|
colorSpace: LinearSRGBColorSpace,
|
|
material,
|
|
renderer,
|
|
renderTargetOptions: params.renderTargetOptions
|
|
});
|
|
return quadRenderer;
|
|
};
|
|
}
|
|
var GainMapNotFoundError = class extends Error {
|
|
};
|
|
var XMPMetadataNotFoundError = class extends Error {
|
|
};
|
|
var getXMLValue = (xml, tag, defaultValue) => {
|
|
const attributeMatch = new RegExp(`${tag}="([^"]*)"`, "i").exec(xml);
|
|
if (attributeMatch)
|
|
return attributeMatch[1];
|
|
const tagMatch = new RegExp(`<${tag}[^>]*>([\\s\\S]*?)</${tag}>`, "i").exec(xml);
|
|
if (tagMatch) {
|
|
const liValues = tagMatch[1].match(/<rdf:li>([^<]*)<\/rdf:li>/g);
|
|
if (liValues && liValues.length === 3) {
|
|
return liValues.map((v5) => v5.replace(/<\/?rdf:li>/g, ""));
|
|
}
|
|
return tagMatch[1].trim();
|
|
}
|
|
if (defaultValue !== void 0)
|
|
return defaultValue;
|
|
throw new Error(`Can't find ${tag} in gainmap metadata`);
|
|
};
|
|
var extractXMP = (input) => {
|
|
let str;
|
|
if (typeof TextDecoder !== "undefined")
|
|
str = new TextDecoder().decode(input);
|
|
else
|
|
str = input.toString();
|
|
let start = str.indexOf("<x:xmpmeta");
|
|
while (start !== -1) {
|
|
const end = str.indexOf("x:xmpmeta>", start);
|
|
const xmpBlock = str.slice(start, end + 10);
|
|
try {
|
|
const gainMapMin = getXMLValue(xmpBlock, "hdrgm:GainMapMin", "0");
|
|
const gainMapMax = getXMLValue(xmpBlock, "hdrgm:GainMapMax");
|
|
const gamma = getXMLValue(xmpBlock, "hdrgm:Gamma", "1");
|
|
const offsetSDR = getXMLValue(xmpBlock, "hdrgm:OffsetSDR", "0.015625");
|
|
const offsetHDR = getXMLValue(xmpBlock, "hdrgm:OffsetHDR", "0.015625");
|
|
const hdrCapacityMinMatch = /hdrgm:HDRCapacityMin="([^"]*)"/.exec(xmpBlock);
|
|
const hdrCapacityMin = hdrCapacityMinMatch ? hdrCapacityMinMatch[1] : "0";
|
|
const hdrCapacityMaxMatch = /hdrgm:HDRCapacityMax="([^"]*)"/.exec(xmpBlock);
|
|
if (!hdrCapacityMaxMatch)
|
|
throw new Error("Incomplete gainmap metadata");
|
|
const hdrCapacityMax = hdrCapacityMaxMatch[1];
|
|
return {
|
|
gainMapMin: Array.isArray(gainMapMin) ? gainMapMin.map((v5) => parseFloat(v5)) : [parseFloat(gainMapMin), parseFloat(gainMapMin), parseFloat(gainMapMin)],
|
|
gainMapMax: Array.isArray(gainMapMax) ? gainMapMax.map((v5) => parseFloat(v5)) : [parseFloat(gainMapMax), parseFloat(gainMapMax), parseFloat(gainMapMax)],
|
|
gamma: Array.isArray(gamma) ? gamma.map((v5) => parseFloat(v5)) : [parseFloat(gamma), parseFloat(gamma), parseFloat(gamma)],
|
|
offsetSdr: Array.isArray(offsetSDR) ? offsetSDR.map((v5) => parseFloat(v5)) : [parseFloat(offsetSDR), parseFloat(offsetSDR), parseFloat(offsetSDR)],
|
|
offsetHdr: Array.isArray(offsetHDR) ? offsetHDR.map((v5) => parseFloat(v5)) : [parseFloat(offsetHDR), parseFloat(offsetHDR), parseFloat(offsetHDR)],
|
|
hdrCapacityMin: parseFloat(hdrCapacityMin),
|
|
hdrCapacityMax: parseFloat(hdrCapacityMax)
|
|
};
|
|
} catch (e2) {
|
|
}
|
|
start = str.indexOf("<x:xmpmeta", end);
|
|
}
|
|
};
|
|
var MPFExtractor = class {
|
|
options;
|
|
constructor(options) {
|
|
this.options = {
|
|
debug: options && options.debug !== void 0 ? options.debug : false,
|
|
extractFII: options && options.extractFII !== void 0 ? options.extractFII : true,
|
|
extractNonFII: options && options.extractNonFII !== void 0 ? options.extractNonFII : true
|
|
};
|
|
}
|
|
extract(imageArrayBuffer) {
|
|
return new Promise((resolve, reject) => {
|
|
const debug = this.options.debug;
|
|
const dataView = new DataView(imageArrayBuffer.buffer);
|
|
if (dataView.getUint16(0) !== 65496) {
|
|
reject(new Error("Not a valid jpeg"));
|
|
return;
|
|
}
|
|
const length3 = dataView.byteLength;
|
|
let offset = 2;
|
|
let loops = 0;
|
|
let marker;
|
|
while (offset < length3) {
|
|
if (++loops > 250) {
|
|
reject(new Error(`Found no marker after ${loops} loops 😵`));
|
|
return;
|
|
}
|
|
if (dataView.getUint8(offset) !== 255) {
|
|
reject(new Error(`Not a valid marker at offset 0x${offset.toString(16)}, found: 0x${dataView.getUint8(offset).toString(16)}`));
|
|
return;
|
|
}
|
|
marker = dataView.getUint8(offset + 1);
|
|
if (debug)
|
|
console.log(`Marker: ${marker.toString(16)}`);
|
|
if (marker === 226) {
|
|
if (debug)
|
|
console.log("Found APP2 marker (0xffe2)");
|
|
const formatPt = offset + 4;
|
|
if (dataView.getUint32(formatPt) === 1297106432) {
|
|
const tiffOffset = formatPt + 4;
|
|
let bigEnd;
|
|
if (dataView.getUint16(tiffOffset) === 18761) {
|
|
bigEnd = false;
|
|
} else if (dataView.getUint16(tiffOffset) === 19789) {
|
|
bigEnd = true;
|
|
} else {
|
|
reject(new Error("No valid endianness marker found in TIFF header"));
|
|
return;
|
|
}
|
|
if (dataView.getUint16(tiffOffset + 2, !bigEnd) !== 42) {
|
|
reject(new Error("Not valid TIFF data! (no 0x002A marker)"));
|
|
return;
|
|
}
|
|
const firstIFDOffset = dataView.getUint32(tiffOffset + 4, !bigEnd);
|
|
if (firstIFDOffset < 8) {
|
|
reject(new Error("Not valid TIFF data! (First offset less than 8)"));
|
|
return;
|
|
}
|
|
const dirStart = tiffOffset + firstIFDOffset;
|
|
const count = dataView.getUint16(dirStart, !bigEnd);
|
|
const entriesStart = dirStart + 2;
|
|
let numberOfImages = 0;
|
|
for (let i3 = entriesStart; i3 < entriesStart + 12 * count; i3 += 12) {
|
|
if (dataView.getUint16(i3, !bigEnd) === 45057) {
|
|
numberOfImages = dataView.getUint32(i3 + 8, !bigEnd);
|
|
}
|
|
}
|
|
const nextIFDOffsetLen = 4;
|
|
const MPImageListValPt = dirStart + 2 + count * 12 + nextIFDOffsetLen;
|
|
const images = [];
|
|
for (let i3 = MPImageListValPt; i3 < MPImageListValPt + numberOfImages * 16; i3 += 16) {
|
|
const image = {
|
|
MPType: dataView.getUint32(i3, !bigEnd),
|
|
size: dataView.getUint32(i3 + 4, !bigEnd),
|
|
// This offset is specified relative to the address of the MP Endian
|
|
// field in the MP Header, unless the image is a First Individual Image,
|
|
// in which case the value of the offset shall be NULL (0x00000000).
|
|
dataOffset: dataView.getUint32(i3 + 8, !bigEnd),
|
|
dependantImages: dataView.getUint32(i3 + 12, !bigEnd),
|
|
start: -1,
|
|
end: -1,
|
|
isFII: false
|
|
};
|
|
if (!image.dataOffset) {
|
|
image.start = 0;
|
|
image.isFII = true;
|
|
} else {
|
|
image.start = tiffOffset + image.dataOffset;
|
|
image.isFII = false;
|
|
}
|
|
image.end = image.start + image.size;
|
|
images.push(image);
|
|
}
|
|
if (this.options.extractNonFII && images.length) {
|
|
const bufferBlob = new Blob([dataView]);
|
|
const imgs = [];
|
|
for (const image of images) {
|
|
if (image.isFII && !this.options.extractFII) {
|
|
continue;
|
|
}
|
|
const imageBlob = bufferBlob.slice(image.start, image.end + 1, "image/jpeg");
|
|
imgs.push(imageBlob);
|
|
}
|
|
resolve(imgs);
|
|
}
|
|
}
|
|
}
|
|
offset += 2 + dataView.getUint16(offset + 2);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
var extractGainmapFromJPEG = async (jpegFile) => {
|
|
const metadata = extractXMP(jpegFile);
|
|
if (!metadata)
|
|
throw new XMPMetadataNotFoundError("Gain map XMP metadata not found");
|
|
const mpfExtractor = new MPFExtractor({ extractFII: true, extractNonFII: true });
|
|
const images = await mpfExtractor.extract(jpegFile);
|
|
if (images.length !== 2)
|
|
throw new GainMapNotFoundError("Gain map recovery image not found");
|
|
return {
|
|
sdr: new Uint8Array(await images[0].arrayBuffer()),
|
|
gainMap: new Uint8Array(await images[1].arrayBuffer()),
|
|
metadata
|
|
};
|
|
};
|
|
var getHTMLImageFromBlob = (blob) => {
|
|
return new Promise((resolve, reject) => {
|
|
const img = document.createElement("img");
|
|
img.onload = () => {
|
|
resolve(img);
|
|
};
|
|
img.onerror = (e2) => {
|
|
reject(e2);
|
|
};
|
|
img.src = URL.createObjectURL(blob);
|
|
});
|
|
};
|
|
var LoaderBaseShared = class extends Loader {
|
|
_renderer;
|
|
_renderTargetOptions;
|
|
_internalLoadingManager;
|
|
_config;
|
|
constructor(config, manager) {
|
|
super(manager);
|
|
this._config = config;
|
|
if (config.renderer)
|
|
this._renderer = config.renderer;
|
|
this._internalLoadingManager = new LoadingManager();
|
|
}
|
|
setRenderer(renderer) {
|
|
this._renderer = renderer;
|
|
return this;
|
|
}
|
|
setRenderTargetOptions(options) {
|
|
this._renderTargetOptions = options;
|
|
return this;
|
|
}
|
|
prepareQuadRenderer() {
|
|
if (!this._renderer) {
|
|
console.warn("WARNING: A Renderer was not passed to this Loader constructor or in setRenderer, the result of this Loader will need to be converted to a Data Texture with toDataTexture() before you can use it in your renderer.");
|
|
}
|
|
const material = this._config.createMaterial({
|
|
gainMapMax: [1, 1, 1],
|
|
gainMapMin: [0, 0, 0],
|
|
gamma: [1, 1, 1],
|
|
offsetHdr: [1, 1, 1],
|
|
offsetSdr: [1, 1, 1],
|
|
hdrCapacityMax: 1,
|
|
hdrCapacityMin: 0,
|
|
maxDisplayBoost: 1,
|
|
gainMap: new Texture(),
|
|
sdr: new Texture()
|
|
});
|
|
return this._config.createQuadRenderer({
|
|
width: 16,
|
|
height: 16,
|
|
type: HalfFloatType,
|
|
colorSpace: LinearSRGBColorSpace,
|
|
material,
|
|
renderer: this._renderer,
|
|
renderTargetOptions: this._renderTargetOptions
|
|
});
|
|
}
|
|
async processImages(sdrBuffer, gainMapBuffer, imageOrientation) {
|
|
const gainMapBlob = gainMapBuffer ? new Blob([gainMapBuffer], { type: "image/jpeg" }) : void 0;
|
|
const sdrBlob = new Blob([sdrBuffer], { type: "image/jpeg" });
|
|
let sdrImage;
|
|
let gainMapImage;
|
|
let needsFlip = false;
|
|
if (typeof createImageBitmap === "undefined") {
|
|
const res = await Promise.all([
|
|
gainMapBlob ? getHTMLImageFromBlob(gainMapBlob) : Promise.resolve(void 0),
|
|
getHTMLImageFromBlob(sdrBlob)
|
|
]);
|
|
gainMapImage = res[0];
|
|
sdrImage = res[1];
|
|
needsFlip = imageOrientation === "flipY";
|
|
} else {
|
|
const res = await Promise.all([
|
|
gainMapBlob ? createImageBitmap(gainMapBlob, { imageOrientation: imageOrientation || "flipY" }) : Promise.resolve(void 0),
|
|
createImageBitmap(sdrBlob, { imageOrientation: imageOrientation || "flipY" })
|
|
]);
|
|
gainMapImage = res[0];
|
|
sdrImage = res[1];
|
|
}
|
|
return { sdrImage, gainMapImage, needsFlip };
|
|
}
|
|
createTextures(sdrImage, gainMapImage, needsFlip) {
|
|
const gainMap = new Texture(gainMapImage || new ImageData(2, 2), UVMapping, ClampToEdgeWrapping, ClampToEdgeWrapping, LinearFilter, LinearMipMapLinearFilter, RGBAFormat, UnsignedByteType, 1, LinearSRGBColorSpace);
|
|
gainMap.flipY = needsFlip;
|
|
gainMap.needsUpdate = true;
|
|
const sdr = new Texture(sdrImage, UVMapping, ClampToEdgeWrapping, ClampToEdgeWrapping, LinearFilter, LinearMipMapLinearFilter, RGBAFormat, UnsignedByteType, 1, SRGBColorSpace);
|
|
sdr.flipY = needsFlip;
|
|
sdr.needsUpdate = true;
|
|
return { gainMap, sdr };
|
|
}
|
|
updateQuadRenderer(quadRenderer, sdrImage, gainMap, sdr, metadata) {
|
|
quadRenderer.width = sdrImage.width;
|
|
quadRenderer.height = sdrImage.height;
|
|
quadRenderer.material.gainMap = gainMap;
|
|
quadRenderer.material.sdr = sdr;
|
|
quadRenderer.material.gainMapMin = metadata.gainMapMin;
|
|
quadRenderer.material.gainMapMax = metadata.gainMapMax;
|
|
quadRenderer.material.offsetHdr = metadata.offsetHdr;
|
|
quadRenderer.material.offsetSdr = metadata.offsetSdr;
|
|
quadRenderer.material.gamma = metadata.gamma;
|
|
quadRenderer.material.hdrCapacityMin = metadata.hdrCapacityMin;
|
|
quadRenderer.material.hdrCapacityMax = metadata.hdrCapacityMax;
|
|
quadRenderer.material.maxDisplayBoost = Math.pow(2, metadata.hdrCapacityMax);
|
|
quadRenderer.material.needsUpdate = true;
|
|
}
|
|
};
|
|
|
|
// node_modules/@monogrid/gainmap-js/dist/decode.js
|
|
var vertexShader2 = (
|
|
/* glsl */
|
|
`
|
|
varying vec2 vUv;
|
|
|
|
void main() {
|
|
vUv = uv;
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
}
|
|
`
|
|
);
|
|
var fragmentShader2 = (
|
|
/* glsl */
|
|
`
|
|
// min half float value
|
|
#define HALF_FLOAT_MIN vec3( -65504, -65504, -65504 )
|
|
// max half float value
|
|
#define HALF_FLOAT_MAX vec3( 65504, 65504, 65504 )
|
|
|
|
uniform sampler2D sdr;
|
|
uniform sampler2D gainMap;
|
|
uniform vec3 gamma;
|
|
uniform vec3 offsetHdr;
|
|
uniform vec3 offsetSdr;
|
|
uniform vec3 gainMapMin;
|
|
uniform vec3 gainMapMax;
|
|
uniform float weightFactor;
|
|
|
|
varying vec2 vUv;
|
|
|
|
void main() {
|
|
vec3 rgb = texture2D( sdr, vUv ).rgb;
|
|
vec3 recovery = texture2D( gainMap, vUv ).rgb;
|
|
vec3 logRecovery = pow( recovery, gamma );
|
|
vec3 logBoost = gainMapMin * ( 1.0 - logRecovery ) + gainMapMax * logRecovery;
|
|
vec3 hdrColor = (rgb + offsetSdr) * exp2( logBoost * weightFactor ) - offsetHdr;
|
|
vec3 clampedHdrColor = max( HALF_FLOAT_MIN, min( HALF_FLOAT_MAX, hdrColor ));
|
|
gl_FragColor = vec4( clampedHdrColor , 1.0 );
|
|
}
|
|
`
|
|
);
|
|
var GainMapDecoderMaterial = class extends ShaderMaterial {
|
|
_maxDisplayBoost;
|
|
_hdrCapacityMin;
|
|
_hdrCapacityMax;
|
|
/**
|
|
*
|
|
* @param params
|
|
*/
|
|
constructor({ gamma, offsetHdr, offsetSdr, gainMapMin, gainMapMax, maxDisplayBoost, hdrCapacityMin, hdrCapacityMax, sdr, gainMap }) {
|
|
super({
|
|
name: "GainMapDecoderMaterial",
|
|
vertexShader: vertexShader2,
|
|
fragmentShader: fragmentShader2,
|
|
uniforms: {
|
|
sdr: { value: sdr },
|
|
gainMap: { value: gainMap },
|
|
gamma: { value: new Vector3(1 / gamma[0], 1 / gamma[1], 1 / gamma[2]) },
|
|
offsetHdr: { value: new Vector3().fromArray(offsetHdr) },
|
|
offsetSdr: { value: new Vector3().fromArray(offsetSdr) },
|
|
gainMapMin: { value: new Vector3().fromArray(gainMapMin) },
|
|
gainMapMax: { value: new Vector3().fromArray(gainMapMax) },
|
|
weightFactor: {
|
|
value: (Math.log2(maxDisplayBoost) - hdrCapacityMin) / (hdrCapacityMax - hdrCapacityMin)
|
|
}
|
|
},
|
|
blending: NoBlending,
|
|
depthTest: false,
|
|
depthWrite: false
|
|
});
|
|
this._maxDisplayBoost = maxDisplayBoost;
|
|
this._hdrCapacityMin = hdrCapacityMin;
|
|
this._hdrCapacityMax = hdrCapacityMax;
|
|
this.needsUpdate = true;
|
|
this.uniformsNeedUpdate = true;
|
|
}
|
|
get sdr() {
|
|
return this.uniforms.sdr.value;
|
|
}
|
|
set sdr(value) {
|
|
this.uniforms.sdr.value = value;
|
|
}
|
|
get gainMap() {
|
|
return this.uniforms.gainMap.value;
|
|
}
|
|
set gainMap(value) {
|
|
this.uniforms.gainMap.value = value;
|
|
}
|
|
/**
|
|
* @see {@link GainMapMetadata.offsetHdr}
|
|
*/
|
|
get offsetHdr() {
|
|
return this.uniforms.offsetHdr.value.toArray();
|
|
}
|
|
set offsetHdr(value) {
|
|
this.uniforms.offsetHdr.value.fromArray(value);
|
|
}
|
|
/**
|
|
* @see {@link GainMapMetadata.offsetSdr}
|
|
*/
|
|
get offsetSdr() {
|
|
return this.uniforms.offsetSdr.value.toArray();
|
|
}
|
|
set offsetSdr(value) {
|
|
this.uniforms.offsetSdr.value.fromArray(value);
|
|
}
|
|
/**
|
|
* @see {@link GainMapMetadata.gainMapMin}
|
|
*/
|
|
get gainMapMin() {
|
|
return this.uniforms.gainMapMin.value.toArray();
|
|
}
|
|
set gainMapMin(value) {
|
|
this.uniforms.gainMapMin.value.fromArray(value);
|
|
}
|
|
/**
|
|
* @see {@link GainMapMetadata.gainMapMax}
|
|
*/
|
|
get gainMapMax() {
|
|
return this.uniforms.gainMapMax.value.toArray();
|
|
}
|
|
set gainMapMax(value) {
|
|
this.uniforms.gainMapMax.value.fromArray(value);
|
|
}
|
|
/**
|
|
* @see {@link GainMapMetadata.gamma}
|
|
*/
|
|
get gamma() {
|
|
const g = this.uniforms.gamma.value;
|
|
return [1 / g.x, 1 / g.y, 1 / g.z];
|
|
}
|
|
set gamma(value) {
|
|
const g = this.uniforms.gamma.value;
|
|
g.x = 1 / value[0];
|
|
g.y = 1 / value[1];
|
|
g.z = 1 / value[2];
|
|
}
|
|
/**
|
|
* @see {@link GainMapMetadata.hdrCapacityMin}
|
|
* @remarks Logarithmic space
|
|
*/
|
|
get hdrCapacityMin() {
|
|
return this._hdrCapacityMin;
|
|
}
|
|
set hdrCapacityMin(value) {
|
|
this._hdrCapacityMin = value;
|
|
this.calculateWeight();
|
|
}
|
|
/**
|
|
* @see {@link GainMapMetadata.hdrCapacityMin}
|
|
* @remarks Logarithmic space
|
|
*/
|
|
get hdrCapacityMax() {
|
|
return this._hdrCapacityMax;
|
|
}
|
|
set hdrCapacityMax(value) {
|
|
this._hdrCapacityMax = value;
|
|
this.calculateWeight();
|
|
}
|
|
/**
|
|
* @see {@link GainmapDecodingParameters.maxDisplayBoost}
|
|
* @remarks Non Logarithmic space
|
|
*/
|
|
get maxDisplayBoost() {
|
|
return this._maxDisplayBoost;
|
|
}
|
|
set maxDisplayBoost(value) {
|
|
this._maxDisplayBoost = Math.max(1, Math.min(65504, value));
|
|
this.calculateWeight();
|
|
}
|
|
calculateWeight() {
|
|
const val = (Math.log2(this._maxDisplayBoost) - this._hdrCapacityMin) / (this._hdrCapacityMax - this._hdrCapacityMin);
|
|
this.uniforms.weightFactor.value = Math.max(0, Math.min(1, val));
|
|
}
|
|
};
|
|
var decodeImpl = createDecodeFunction({
|
|
renderer: WebGLRenderer,
|
|
createMaterial: (params) => new GainMapDecoderMaterial(params),
|
|
createQuadRenderer: (params) => new QuadRenderer(params)
|
|
});
|
|
var LoaderBaseWebGL = class extends LoaderBaseShared {
|
|
constructor(renderer, manager) {
|
|
super({
|
|
renderer,
|
|
createMaterial: (params) => new GainMapDecoderMaterial(params),
|
|
createQuadRenderer: (params) => new QuadRenderer(params)
|
|
}, manager);
|
|
}
|
|
/**
|
|
* @private
|
|
* @param quadRenderer
|
|
* @param metadata
|
|
* @param sdrBuffer
|
|
* @param gainMapBuffer
|
|
*/
|
|
async render(quadRenderer, metadata, sdrBuffer, gainMapBuffer) {
|
|
const { sdrImage, gainMapImage, needsFlip } = await this.processImages(sdrBuffer, gainMapBuffer, "flipY");
|
|
const { gainMap, sdr } = this.createTextures(sdrImage, gainMapImage, needsFlip);
|
|
this.updateQuadRenderer(quadRenderer, sdrImage, gainMap, sdr, metadata);
|
|
quadRenderer.render();
|
|
}
|
|
};
|
|
var GainMapLoader = class extends LoaderBaseWebGL {
|
|
/**
|
|
* Loads a gainmap using separate data
|
|
* * sdr image
|
|
* * gain map image
|
|
* * metadata json
|
|
*
|
|
* useful for webp gain maps
|
|
*
|
|
* @param urls An array in the form of [sdr.jpg, gainmap.jpg, metadata.json]
|
|
* @param onLoad Load complete callback, will receive the result
|
|
* @param onProgress Progress callback, will receive a `ProgressEvent`
|
|
* @param onError Error callback
|
|
* @returns
|
|
*/
|
|
load([sdrUrl, gainMapUrl, metadataUrl], onLoad, onProgress, onError) {
|
|
const quadRenderer = this.prepareQuadRenderer();
|
|
let sdr;
|
|
let gainMap;
|
|
let metadata;
|
|
const loadCheck = async () => {
|
|
if (sdr && gainMap && metadata) {
|
|
try {
|
|
await this.render(quadRenderer, metadata, sdr, gainMap);
|
|
} catch (error) {
|
|
this.manager.itemError(sdrUrl);
|
|
this.manager.itemError(gainMapUrl);
|
|
this.manager.itemError(metadataUrl);
|
|
if (typeof onError === "function")
|
|
onError(error);
|
|
quadRenderer.disposeOnDemandRenderer();
|
|
return;
|
|
}
|
|
if (typeof onLoad === "function")
|
|
onLoad(quadRenderer);
|
|
this.manager.itemEnd(sdrUrl);
|
|
this.manager.itemEnd(gainMapUrl);
|
|
this.manager.itemEnd(metadataUrl);
|
|
quadRenderer.disposeOnDemandRenderer();
|
|
}
|
|
};
|
|
let sdrLengthComputable = true;
|
|
let sdrTotal = 0;
|
|
let sdrLoaded = 0;
|
|
let gainMapLengthComputable = true;
|
|
let gainMapTotal = 0;
|
|
let gainMapLoaded = 0;
|
|
let metadataLengthComputable = true;
|
|
let metadataTotal = 0;
|
|
let metadataLoaded = 0;
|
|
const progressHandler = () => {
|
|
if (typeof onProgress === "function") {
|
|
const total = sdrTotal + gainMapTotal + metadataTotal;
|
|
const loaded = sdrLoaded + gainMapLoaded + metadataLoaded;
|
|
const lengthComputable = sdrLengthComputable && gainMapLengthComputable && metadataLengthComputable;
|
|
onProgress(new ProgressEvent("progress", { lengthComputable, loaded, total }));
|
|
}
|
|
};
|
|
this.manager.itemStart(sdrUrl);
|
|
this.manager.itemStart(gainMapUrl);
|
|
this.manager.itemStart(metadataUrl);
|
|
const sdrLoader = new FileLoader(this._internalLoadingManager);
|
|
sdrLoader.setResponseType("arraybuffer");
|
|
sdrLoader.setRequestHeader(this.requestHeader);
|
|
sdrLoader.setPath(this.path);
|
|
sdrLoader.setWithCredentials(this.withCredentials);
|
|
sdrLoader.load(sdrUrl, async (buffer2) => {
|
|
if (typeof buffer2 === "string")
|
|
throw new Error("Invalid sdr buffer");
|
|
sdr = buffer2;
|
|
await loadCheck();
|
|
}, (e2) => {
|
|
sdrLengthComputable = e2.lengthComputable;
|
|
sdrLoaded = e2.loaded;
|
|
sdrTotal = e2.total;
|
|
progressHandler();
|
|
}, (error) => {
|
|
this.manager.itemError(sdrUrl);
|
|
if (typeof onError === "function")
|
|
onError(error);
|
|
});
|
|
const gainMapLoader = new FileLoader(this._internalLoadingManager);
|
|
gainMapLoader.setResponseType("arraybuffer");
|
|
gainMapLoader.setRequestHeader(this.requestHeader);
|
|
gainMapLoader.setPath(this.path);
|
|
gainMapLoader.setWithCredentials(this.withCredentials);
|
|
gainMapLoader.load(gainMapUrl, async (buffer2) => {
|
|
if (typeof buffer2 === "string")
|
|
throw new Error("Invalid gainmap buffer");
|
|
gainMap = buffer2;
|
|
await loadCheck();
|
|
}, (e2) => {
|
|
gainMapLengthComputable = e2.lengthComputable;
|
|
gainMapLoaded = e2.loaded;
|
|
gainMapTotal = e2.total;
|
|
progressHandler();
|
|
}, (error) => {
|
|
this.manager.itemError(gainMapUrl);
|
|
if (typeof onError === "function")
|
|
onError(error);
|
|
});
|
|
const metadataLoader = new FileLoader(this._internalLoadingManager);
|
|
metadataLoader.setRequestHeader(this.requestHeader);
|
|
metadataLoader.setPath(this.path);
|
|
metadataLoader.setWithCredentials(this.withCredentials);
|
|
metadataLoader.load(metadataUrl, async (json) => {
|
|
if (typeof json !== "string")
|
|
throw new Error("Invalid metadata string");
|
|
metadata = JSON.parse(json);
|
|
await loadCheck();
|
|
}, (e2) => {
|
|
metadataLengthComputable = e2.lengthComputable;
|
|
metadataLoaded = e2.loaded;
|
|
metadataTotal = e2.total;
|
|
progressHandler();
|
|
}, (error) => {
|
|
this.manager.itemError(metadataUrl);
|
|
if (typeof onError === "function")
|
|
onError(error);
|
|
});
|
|
return quadRenderer;
|
|
}
|
|
};
|
|
var HDRJPGLoader = class extends LoaderBaseWebGL {
|
|
/**
|
|
* Loads a JPEG containing gain map metadata
|
|
* Renders a normal SDR image if gainmap data is not found
|
|
*
|
|
* @param url Path to a JPEG file containing embedded gain map metadata
|
|
* @param onLoad Load complete callback, will receive the result
|
|
* @param onProgress Progress callback, will receive a `ProgressEvent`
|
|
* @param onError Error callback
|
|
* @returns
|
|
*/
|
|
load(url, onLoad, onProgress, onError) {
|
|
const quadRenderer = this.prepareQuadRenderer();
|
|
const loader2 = new FileLoader(this._internalLoadingManager);
|
|
loader2.setResponseType("arraybuffer");
|
|
loader2.setRequestHeader(this.requestHeader);
|
|
loader2.setPath(this.path);
|
|
loader2.setWithCredentials(this.withCredentials);
|
|
this.manager.itemStart(url);
|
|
loader2.load(url, async (jpeg) => {
|
|
if (typeof jpeg === "string")
|
|
throw new Error("Invalid buffer, received [string], was expecting [ArrayBuffer]");
|
|
const jpegBuffer = new Uint8Array(jpeg);
|
|
let sdrJPEG;
|
|
let gainMapJPEG;
|
|
let metadata;
|
|
try {
|
|
const extractionResult = await extractGainmapFromJPEG(jpegBuffer);
|
|
sdrJPEG = extractionResult.sdr;
|
|
gainMapJPEG = extractionResult.gainMap;
|
|
metadata = extractionResult.metadata;
|
|
} catch (e2) {
|
|
if (e2 instanceof XMPMetadataNotFoundError || e2 instanceof GainMapNotFoundError) {
|
|
console.warn(`Failure to reconstruct an HDR image from ${url}: Gain map metadata not found in the file, HDRJPGLoader will render the SDR jpeg`);
|
|
metadata = {
|
|
gainMapMin: [0, 0, 0],
|
|
gainMapMax: [1, 1, 1],
|
|
gamma: [1, 1, 1],
|
|
hdrCapacityMin: 0,
|
|
hdrCapacityMax: 1,
|
|
offsetHdr: [0, 0, 0],
|
|
offsetSdr: [0, 0, 0]
|
|
};
|
|
sdrJPEG = jpegBuffer;
|
|
} else {
|
|
throw e2;
|
|
}
|
|
}
|
|
try {
|
|
await this.render(quadRenderer, metadata, sdrJPEG.buffer, gainMapJPEG?.buffer);
|
|
} catch (error) {
|
|
this.manager.itemError(url);
|
|
if (typeof onError === "function")
|
|
onError(error);
|
|
quadRenderer.disposeOnDemandRenderer();
|
|
return;
|
|
}
|
|
if (typeof onLoad === "function")
|
|
onLoad(quadRenderer);
|
|
this.manager.itemEnd(url);
|
|
quadRenderer.disposeOnDemandRenderer();
|
|
}, onProgress, (error) => {
|
|
this.manager.itemError(url);
|
|
if (typeof onError === "function")
|
|
onError(error);
|
|
});
|
|
return quadRenderer;
|
|
}
|
|
};
|
|
|
|
// node_modules/@react-three/drei/helpers/environment-assets.js
|
|
var presetsObj = {
|
|
apartment: "lebombo_1k.hdr",
|
|
city: "potsdamer_platz_1k.hdr",
|
|
dawn: "kiara_1_dawn_1k.hdr",
|
|
forest: "forest_slope_1k.hdr",
|
|
lobby: "st_fagans_interior_1k.hdr",
|
|
night: "dikhololo_night_1k.hdr",
|
|
park: "rooitou_park_1k.hdr",
|
|
studio: "studio_small_03_1k.hdr",
|
|
sunset: "venice_sunset_1k.hdr",
|
|
warehouse: "empty_warehouse_01_1k.hdr"
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/useEnvironment.js
|
|
var import_react18 = __toESM(require_react());
|
|
var CUBEMAP_ROOT = "https://raw.githack.com/pmndrs/drei-assets/456060a26bbeb8fdf79326f224b6d99b8bcce736/hdri/";
|
|
var isArray2 = (arr) => Array.isArray(arr);
|
|
var defaultFiles = ["/px.png", "/nx.png", "/py.png", "/ny.png", "/pz.png", "/nz.png"];
|
|
function useEnvironment({
|
|
files = defaultFiles,
|
|
path = "",
|
|
preset = void 0,
|
|
colorSpace = void 0,
|
|
extensions: extensions2
|
|
} = {}) {
|
|
if (preset) {
|
|
validatePreset(preset);
|
|
files = presetsObj[preset];
|
|
path = CUBEMAP_ROOT;
|
|
}
|
|
const multiFile = isArray2(files);
|
|
const {
|
|
extension,
|
|
isCubemap
|
|
} = getExtension(files);
|
|
const loader2 = getLoader(extension);
|
|
if (!loader2) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
const gl = useThree((state) => state.gl);
|
|
(0, import_react18.useLayoutEffect)(() => {
|
|
if (extension !== "webp" && extension !== "jpg" && extension !== "jpeg") return;
|
|
function clearGainmapTexture() {
|
|
useLoader.clear(loader2, multiFile ? [files] : files);
|
|
}
|
|
gl.domElement.addEventListener("webglcontextlost", clearGainmapTexture, {
|
|
once: true
|
|
});
|
|
}, [files, gl.domElement]);
|
|
const loaderResult = useLoader(loader2, multiFile ? [files] : files, (loader3) => {
|
|
if (extension === "webp" || extension === "jpg" || extension === "jpeg") {
|
|
loader3.setRenderer(gl);
|
|
}
|
|
loader3.setPath == null || loader3.setPath(path);
|
|
if (extensions2) extensions2(loader3);
|
|
});
|
|
let texture = multiFile ? (
|
|
// @ts-ignore
|
|
loaderResult[0]
|
|
) : loaderResult;
|
|
if (extension === "jpg" || extension === "jpeg" || extension === "webp") {
|
|
var _renderTarget;
|
|
texture = (_renderTarget = texture.renderTarget) == null ? void 0 : _renderTarget.texture;
|
|
}
|
|
texture.mapping = isCubemap ? CubeReflectionMapping : EquirectangularReflectionMapping;
|
|
texture.colorSpace = colorSpace !== null && colorSpace !== void 0 ? colorSpace : isCubemap ? "srgb" : "srgb-linear";
|
|
return texture;
|
|
}
|
|
var preloadDefaultOptions = {
|
|
files: defaultFiles,
|
|
path: "",
|
|
preset: void 0,
|
|
extensions: void 0
|
|
};
|
|
useEnvironment.preload = (preloadOptions) => {
|
|
const options = {
|
|
...preloadDefaultOptions,
|
|
...preloadOptions
|
|
};
|
|
let {
|
|
files,
|
|
path = ""
|
|
} = options;
|
|
const {
|
|
preset,
|
|
extensions: extensions2
|
|
} = options;
|
|
if (preset) {
|
|
validatePreset(preset);
|
|
files = presetsObj[preset];
|
|
path = CUBEMAP_ROOT;
|
|
}
|
|
const {
|
|
extension
|
|
} = getExtension(files);
|
|
if (extension === "webp" || extension === "jpg" || extension === "jpeg") {
|
|
throw new Error("useEnvironment: Preloading gainmaps is not supported");
|
|
}
|
|
const loader2 = getLoader(extension);
|
|
if (!loader2) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
useLoader.preload(loader2, isArray2(files) ? [files] : files, (loader3) => {
|
|
loader3.setPath == null || loader3.setPath(path);
|
|
if (extensions2) extensions2(loader3);
|
|
});
|
|
};
|
|
var clearDefaultOptins = {
|
|
files: defaultFiles,
|
|
preset: void 0
|
|
};
|
|
useEnvironment.clear = (clearOptions) => {
|
|
const options = {
|
|
...clearDefaultOptins,
|
|
...clearOptions
|
|
};
|
|
let {
|
|
files
|
|
} = options;
|
|
const {
|
|
preset
|
|
} = options;
|
|
if (preset) {
|
|
validatePreset(preset);
|
|
files = presetsObj[preset];
|
|
}
|
|
const {
|
|
extension
|
|
} = getExtension(files);
|
|
const loader2 = getLoader(extension);
|
|
if (!loader2) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
useLoader.clear(loader2, isArray2(files) ? [files] : files);
|
|
};
|
|
function validatePreset(preset) {
|
|
if (!(preset in presetsObj)) throw new Error("Preset must be one of: " + Object.keys(presetsObj).join(", "));
|
|
}
|
|
function getExtension(files) {
|
|
var _firstEntry$split$pop;
|
|
const isCubemap = isArray2(files) && files.length === 6;
|
|
const isGainmap = isArray2(files) && files.length === 3 && files.some((file) => file.endsWith("json"));
|
|
const firstEntry = isArray2(files) ? files[0] : files;
|
|
const extension = isCubemap ? "cube" : isGainmap ? "webp" : firstEntry.startsWith("data:application/exr") ? "exr" : firstEntry.startsWith("data:application/hdr") ? "hdr" : firstEntry.startsWith("data:image/jpeg") ? "jpg" : (_firstEntry$split$pop = firstEntry.split(".").pop()) == null || (_firstEntry$split$pop = _firstEntry$split$pop.split("?")) == null || (_firstEntry$split$pop = _firstEntry$split$pop.shift()) == null ? void 0 : _firstEntry$split$pop.toLowerCase();
|
|
return {
|
|
extension,
|
|
isCubemap,
|
|
isGainmap
|
|
};
|
|
}
|
|
function getLoader(extension) {
|
|
const loader2 = extension === "cube" ? CubeTextureLoader : extension === "hdr" ? RGBELoader : extension === "exr" ? EXRLoader : extension === "jpg" || extension === "jpeg" ? HDRJPGLoader : extension === "webp" ? GainMapLoader : null;
|
|
return loader2;
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/Environment.js
|
|
var isRef = (obj) => obj.current && obj.current.isScene;
|
|
var resolveScene = (scene) => isRef(scene) ? scene.current : scene;
|
|
function setEnvProps(background, scene, defaultScene, texture, sceneProps = {}) {
|
|
var _target$backgroundRot, _target$backgroundRot2, _target$environmentRo, _target$environmentRo2;
|
|
sceneProps = {
|
|
backgroundBlurriness: 0,
|
|
backgroundIntensity: 1,
|
|
backgroundRotation: [0, 0, 0],
|
|
environmentIntensity: 1,
|
|
environmentRotation: [0, 0, 0],
|
|
...sceneProps
|
|
};
|
|
const target2 = resolveScene(scene || defaultScene);
|
|
const oldbg = target2.background;
|
|
const oldenv = target2.environment;
|
|
const oldSceneProps = {
|
|
// @ts-ignore
|
|
backgroundBlurriness: target2.backgroundBlurriness,
|
|
// @ts-ignore
|
|
backgroundIntensity: target2.backgroundIntensity,
|
|
// @ts-ignore
|
|
backgroundRotation: (_target$backgroundRot = (_target$backgroundRot2 = target2.backgroundRotation) == null || _target$backgroundRot2.clone == null ? void 0 : _target$backgroundRot2.clone()) !== null && _target$backgroundRot !== void 0 ? _target$backgroundRot : [0, 0, 0],
|
|
// @ts-ignore
|
|
environmentIntensity: target2.environmentIntensity,
|
|
// @ts-ignore
|
|
environmentRotation: (_target$environmentRo = (_target$environmentRo2 = target2.environmentRotation) == null || _target$environmentRo2.clone == null ? void 0 : _target$environmentRo2.clone()) !== null && _target$environmentRo !== void 0 ? _target$environmentRo : [0, 0, 0]
|
|
};
|
|
if (background !== "only") target2.environment = texture;
|
|
if (background) target2.background = texture;
|
|
applyProps(target2, sceneProps);
|
|
return () => {
|
|
if (background !== "only") target2.environment = oldenv;
|
|
if (background) target2.background = oldbg;
|
|
applyProps(target2, oldSceneProps);
|
|
};
|
|
}
|
|
function EnvironmentMap({
|
|
scene,
|
|
background = false,
|
|
map: map2,
|
|
...config
|
|
}) {
|
|
const defaultScene = useThree((state) => state.scene);
|
|
React99.useLayoutEffect(() => {
|
|
if (map2) return setEnvProps(background, scene, defaultScene, map2, config);
|
|
});
|
|
return null;
|
|
}
|
|
function EnvironmentCube({
|
|
background = false,
|
|
scene,
|
|
blur,
|
|
backgroundBlurriness,
|
|
backgroundIntensity,
|
|
backgroundRotation,
|
|
environmentIntensity,
|
|
environmentRotation,
|
|
...rest
|
|
}) {
|
|
const texture = useEnvironment(rest);
|
|
const defaultScene = useThree((state) => state.scene);
|
|
React99.useLayoutEffect(() => {
|
|
return setEnvProps(background, scene, defaultScene, texture, {
|
|
backgroundBlurriness: blur !== null && blur !== void 0 ? blur : backgroundBlurriness,
|
|
backgroundIntensity,
|
|
backgroundRotation,
|
|
environmentIntensity,
|
|
environmentRotation
|
|
});
|
|
});
|
|
React99.useEffect(() => {
|
|
return () => {
|
|
texture.dispose();
|
|
};
|
|
}, [texture]);
|
|
return null;
|
|
}
|
|
function EnvironmentPortal({
|
|
children,
|
|
near = 0.1,
|
|
far = 1e3,
|
|
resolution = 256,
|
|
frames = 1,
|
|
map: map2,
|
|
background = false,
|
|
blur,
|
|
backgroundBlurriness,
|
|
backgroundIntensity,
|
|
backgroundRotation,
|
|
environmentIntensity,
|
|
environmentRotation,
|
|
scene,
|
|
files,
|
|
path,
|
|
preset = void 0,
|
|
extensions: extensions2
|
|
}) {
|
|
const gl = useThree((state) => state.gl);
|
|
const defaultScene = useThree((state) => state.scene);
|
|
const camera = React99.useRef(null);
|
|
const [virtualScene] = React99.useState(() => new Scene());
|
|
const fbo = React99.useMemo(() => {
|
|
const fbo2 = new WebGLCubeRenderTarget(resolution);
|
|
fbo2.texture.type = HalfFloatType;
|
|
return fbo2;
|
|
}, [resolution]);
|
|
React99.useEffect(() => {
|
|
return () => {
|
|
fbo.dispose();
|
|
};
|
|
}, [fbo]);
|
|
React99.useLayoutEffect(() => {
|
|
if (frames === 1) {
|
|
const autoClear = gl.autoClear;
|
|
gl.autoClear = true;
|
|
camera.current.update(gl, virtualScene);
|
|
gl.autoClear = autoClear;
|
|
}
|
|
return setEnvProps(background, scene, defaultScene, fbo.texture, {
|
|
backgroundBlurriness: blur !== null && blur !== void 0 ? blur : backgroundBlurriness,
|
|
backgroundIntensity,
|
|
backgroundRotation,
|
|
environmentIntensity,
|
|
environmentRotation
|
|
});
|
|
}, [children, virtualScene, fbo.texture, scene, defaultScene, background, frames, gl]);
|
|
let count = 1;
|
|
useFrame(() => {
|
|
if (frames === Infinity || count < frames) {
|
|
const autoClear = gl.autoClear;
|
|
gl.autoClear = true;
|
|
camera.current.update(gl, virtualScene);
|
|
gl.autoClear = autoClear;
|
|
count++;
|
|
}
|
|
});
|
|
return React99.createElement(React99.Fragment, null, createPortal(React99.createElement(React99.Fragment, null, children, React99.createElement("cubeCamera", {
|
|
ref: camera,
|
|
args: [near, far, fbo]
|
|
}), files || preset ? React99.createElement(EnvironmentCube, {
|
|
background: true,
|
|
files,
|
|
preset,
|
|
path,
|
|
extensions: extensions2
|
|
}) : map2 ? React99.createElement(EnvironmentMap, {
|
|
background: true,
|
|
map: map2,
|
|
extensions: extensions2
|
|
}) : null), virtualScene));
|
|
}
|
|
function EnvironmentGround(props) {
|
|
var _props$ground, _props$ground2, _scale, _props$ground3;
|
|
const textureDefault = useEnvironment(props);
|
|
const texture = props.map || textureDefault;
|
|
React99.useMemo(() => extend({
|
|
GroundProjectedEnvImpl: GroundProjectedEnv
|
|
}), []);
|
|
React99.useEffect(() => {
|
|
return () => {
|
|
textureDefault.dispose();
|
|
};
|
|
}, [textureDefault]);
|
|
const args = React99.useMemo(() => [texture], [texture]);
|
|
const height = (_props$ground = props.ground) == null ? void 0 : _props$ground.height;
|
|
const radius = (_props$ground2 = props.ground) == null ? void 0 : _props$ground2.radius;
|
|
const scale5 = (_scale = (_props$ground3 = props.ground) == null ? void 0 : _props$ground3.scale) !== null && _scale !== void 0 ? _scale : 1e3;
|
|
return React99.createElement(React99.Fragment, null, React99.createElement(EnvironmentMap, _extends({}, props, {
|
|
map: texture
|
|
})), React99.createElement("groundProjectedEnvImpl", {
|
|
args,
|
|
scale: scale5,
|
|
height,
|
|
radius
|
|
}));
|
|
}
|
|
function Environment(props) {
|
|
return props.ground ? React99.createElement(EnvironmentGround, props) : props.map ? React99.createElement(EnvironmentMap, props) : props.children ? React99.createElement(EnvironmentPortal, props) : React99.createElement(EnvironmentCube, props);
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/ContactShadows.js
|
|
var React100 = __toESM(require_react());
|
|
var ContactShadows = React100.forwardRef(({
|
|
scale: scale5 = 10,
|
|
frames = Infinity,
|
|
opacity = 1,
|
|
width = 1,
|
|
height = 1,
|
|
blur = 1,
|
|
near = 0,
|
|
far = 10,
|
|
resolution = 512,
|
|
smooth = true,
|
|
color = "#000000",
|
|
depthWrite = false,
|
|
renderOrder,
|
|
...props
|
|
}, fref) => {
|
|
const ref = React100.useRef(null);
|
|
const scene = useThree((state) => state.scene);
|
|
const gl = useThree((state) => state.gl);
|
|
const shadowCamera = React100.useRef(null);
|
|
width = width * (Array.isArray(scale5) ? scale5[0] : scale5 || 1);
|
|
height = height * (Array.isArray(scale5) ? scale5[1] : scale5 || 1);
|
|
const [renderTarget, planeGeometry, depthMaterial, blurPlane, horizontalBlurMaterial, verticalBlurMaterial, renderTargetBlur] = React100.useMemo(() => {
|
|
const renderTarget2 = new WebGLRenderTarget(resolution, resolution);
|
|
const renderTargetBlur2 = new WebGLRenderTarget(resolution, resolution);
|
|
renderTargetBlur2.texture.generateMipmaps = renderTarget2.texture.generateMipmaps = false;
|
|
const planeGeometry2 = new PlaneGeometry(width, height).rotateX(Math.PI / 2);
|
|
const blurPlane2 = new Mesh(planeGeometry2);
|
|
const depthMaterial2 = new MeshDepthMaterial();
|
|
depthMaterial2.depthTest = depthMaterial2.depthWrite = false;
|
|
depthMaterial2.onBeforeCompile = (shader) => {
|
|
shader.uniforms = {
|
|
...shader.uniforms,
|
|
ucolor: {
|
|
value: new Color(color)
|
|
}
|
|
};
|
|
shader.fragmentShader = shader.fragmentShader.replace(
|
|
`void main() {`,
|
|
//
|
|
`uniform vec3 ucolor;
|
|
void main() {
|
|
`
|
|
);
|
|
shader.fragmentShader = shader.fragmentShader.replace(
|
|
"vec4( vec3( 1.0 - fragCoordZ ), opacity );",
|
|
// Colorize the shadow, multiply by the falloff so that the center can remain darker
|
|
"vec4( ucolor * fragCoordZ * 2.0, ( 1.0 - fragCoordZ ) * 1.0 );"
|
|
);
|
|
};
|
|
const horizontalBlurMaterial2 = new ShaderMaterial(HorizontalBlurShader);
|
|
const verticalBlurMaterial2 = new ShaderMaterial(VerticalBlurShader);
|
|
verticalBlurMaterial2.depthTest = horizontalBlurMaterial2.depthTest = false;
|
|
return [renderTarget2, planeGeometry2, depthMaterial2, blurPlane2, horizontalBlurMaterial2, verticalBlurMaterial2, renderTargetBlur2];
|
|
}, [resolution, width, height, scale5, color]);
|
|
const blurShadows = (blur2) => {
|
|
blurPlane.visible = true;
|
|
blurPlane.material = horizontalBlurMaterial;
|
|
horizontalBlurMaterial.uniforms.tDiffuse.value = renderTarget.texture;
|
|
horizontalBlurMaterial.uniforms.h.value = blur2 * 1 / 256;
|
|
gl.setRenderTarget(renderTargetBlur);
|
|
gl.render(blurPlane, shadowCamera.current);
|
|
blurPlane.material = verticalBlurMaterial;
|
|
verticalBlurMaterial.uniforms.tDiffuse.value = renderTargetBlur.texture;
|
|
verticalBlurMaterial.uniforms.v.value = blur2 * 1 / 256;
|
|
gl.setRenderTarget(renderTarget);
|
|
gl.render(blurPlane, shadowCamera.current);
|
|
blurPlane.visible = false;
|
|
};
|
|
let count = 0;
|
|
let initialBackground;
|
|
let initialOverrideMaterial;
|
|
useFrame(() => {
|
|
if (shadowCamera.current && (frames === Infinity || count < frames)) {
|
|
count++;
|
|
initialBackground = scene.background;
|
|
initialOverrideMaterial = scene.overrideMaterial;
|
|
ref.current.visible = false;
|
|
scene.background = null;
|
|
scene.overrideMaterial = depthMaterial;
|
|
gl.setRenderTarget(renderTarget);
|
|
gl.render(scene, shadowCamera.current);
|
|
blurShadows(blur);
|
|
if (smooth) blurShadows(blur * 0.4);
|
|
gl.setRenderTarget(null);
|
|
ref.current.visible = true;
|
|
scene.overrideMaterial = initialOverrideMaterial;
|
|
scene.background = initialBackground;
|
|
}
|
|
});
|
|
React100.useImperativeHandle(fref, () => ref.current, []);
|
|
return React100.createElement("group", _extends({
|
|
"rotation-x": Math.PI / 2
|
|
}, props, {
|
|
ref
|
|
}), React100.createElement("mesh", {
|
|
renderOrder,
|
|
geometry: planeGeometry,
|
|
scale: [1, -1, 1],
|
|
rotation: [-Math.PI / 2, 0, 0]
|
|
}, React100.createElement("meshBasicMaterial", {
|
|
transparent: true,
|
|
map: renderTarget.texture,
|
|
opacity,
|
|
depthWrite
|
|
})), React100.createElement("orthographicCamera", {
|
|
ref: shadowCamera,
|
|
args: [-width / 2, width / 2, height / 2, -height / 2, near, far]
|
|
}));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/AccumulativeShadows.js
|
|
var React101 = __toESM(require_react());
|
|
function isLight3(object) {
|
|
return object.isLight;
|
|
}
|
|
function isGeometry(object) {
|
|
return !!object.geometry;
|
|
}
|
|
var accumulativeContext = React101.createContext(null);
|
|
var SoftShadowMaterial = shaderMaterial({
|
|
color: new Color(),
|
|
blend: 2,
|
|
alphaTest: 0.75,
|
|
opacity: 0,
|
|
map: null
|
|
}, `varying vec2 vUv;
|
|
void main() {
|
|
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.);
|
|
vUv = uv;
|
|
}`, `varying vec2 vUv;
|
|
uniform sampler2D map;
|
|
uniform vec3 color;
|
|
uniform float opacity;
|
|
uniform float alphaTest;
|
|
uniform float blend;
|
|
void main() {
|
|
vec4 sampledDiffuseColor = texture2D(map, vUv);
|
|
gl_FragColor = vec4(color * sampledDiffuseColor.r * blend, max(0.0, (1.0 - (sampledDiffuseColor.r + sampledDiffuseColor.g + sampledDiffuseColor.b) / alphaTest)) * opacity);
|
|
#include <tonemapping_fragment>
|
|
#include <${version >= 154 ? "colorspace_fragment" : "encodings_fragment"}>
|
|
}`);
|
|
var AccumulativeShadows = React101.forwardRef(({
|
|
children,
|
|
temporal,
|
|
frames = 40,
|
|
limit = Infinity,
|
|
blend = 20,
|
|
scale: scale5 = 10,
|
|
opacity = 1,
|
|
alphaTest = 0.75,
|
|
color = "black",
|
|
colorBlend = 2,
|
|
resolution = 1024,
|
|
toneMapped = true,
|
|
...props
|
|
}, forwardRef82) => {
|
|
extend({
|
|
SoftShadowMaterial
|
|
});
|
|
const gl = useThree((state) => state.gl);
|
|
const scene = useThree((state) => state.scene);
|
|
const camera = useThree((state) => state.camera);
|
|
const invalidate = useThree((state) => state.invalidate);
|
|
const gPlane = React101.useRef(null);
|
|
const gLights = React101.useRef(null);
|
|
const [plm] = React101.useState(() => new ProgressiveLightMap(gl, scene, resolution));
|
|
React101.useLayoutEffect(() => {
|
|
plm.configure(gPlane.current);
|
|
}, []);
|
|
const api = React101.useMemo(() => ({
|
|
lights: /* @__PURE__ */ new Map(),
|
|
temporal: !!temporal,
|
|
frames: Math.max(2, frames),
|
|
blend: Math.max(2, frames === Infinity ? blend : frames),
|
|
count: 0,
|
|
getMesh: () => gPlane.current,
|
|
reset: () => {
|
|
plm.clear();
|
|
const material = gPlane.current.material;
|
|
material.opacity = 0;
|
|
material.alphaTest = 0;
|
|
api.count = 0;
|
|
},
|
|
update: (frames2 = 1) => {
|
|
const material = gPlane.current.material;
|
|
if (!api.temporal) {
|
|
material.opacity = opacity;
|
|
material.alphaTest = alphaTest;
|
|
} else {
|
|
material.opacity = Math.min(opacity, material.opacity + opacity / api.blend);
|
|
material.alphaTest = Math.min(alphaTest, material.alphaTest + alphaTest / api.blend);
|
|
}
|
|
gLights.current.visible = true;
|
|
plm.prepare();
|
|
for (let i3 = 0; i3 < frames2; i3++) {
|
|
api.lights.forEach((light) => light.update());
|
|
plm.update(camera, api.blend);
|
|
}
|
|
gLights.current.visible = false;
|
|
plm.finish();
|
|
}
|
|
}), [plm, camera, scene, temporal, frames, blend, opacity, alphaTest]);
|
|
React101.useLayoutEffect(() => {
|
|
api.reset();
|
|
if (!api.temporal && api.frames !== Infinity) api.update(api.blend);
|
|
});
|
|
React101.useImperativeHandle(forwardRef82, () => api, [api]);
|
|
useFrame(() => {
|
|
if ((api.temporal || api.frames === Infinity) && api.count < api.frames && api.count < limit) {
|
|
invalidate();
|
|
api.update();
|
|
api.count++;
|
|
}
|
|
});
|
|
return React101.createElement("group", props, React101.createElement("group", {
|
|
traverse: () => null,
|
|
ref: gLights
|
|
}, React101.createElement(accumulativeContext.Provider, {
|
|
value: api
|
|
}, children)), React101.createElement("mesh", {
|
|
receiveShadow: true,
|
|
ref: gPlane,
|
|
scale: scale5,
|
|
rotation: [-Math.PI / 2, 0, 0]
|
|
}, React101.createElement("planeGeometry", null), React101.createElement("softShadowMaterial", {
|
|
transparent: true,
|
|
depthWrite: false,
|
|
toneMapped,
|
|
color,
|
|
blend: colorBlend,
|
|
map: plm.progressiveLightMap2.texture
|
|
})));
|
|
});
|
|
var RandomizedLight = React101.forwardRef(({
|
|
castShadow = true,
|
|
bias = 1e-3,
|
|
mapSize = 512,
|
|
size = 5,
|
|
near = 0.5,
|
|
far = 500,
|
|
frames = 1,
|
|
position: position2 = [0, 0, 0],
|
|
radius = 1,
|
|
amount = 8,
|
|
intensity = version >= 155 ? Math.PI : 1,
|
|
ambient = 0.5,
|
|
...props
|
|
}, forwardRef82) => {
|
|
const gLights = React101.useRef(null);
|
|
const length3 = new Vector3(...position2).length();
|
|
const parent = React101.useContext(accumulativeContext);
|
|
const update2 = React101.useCallback(() => {
|
|
let light;
|
|
if (gLights.current) {
|
|
for (let l2 = 0; l2 < gLights.current.children.length; l2++) {
|
|
light = gLights.current.children[l2];
|
|
if (Math.random() > ambient) {
|
|
light.position.set(position2[0] + MathUtils.randFloatSpread(radius), position2[1] + MathUtils.randFloatSpread(radius), position2[2] + MathUtils.randFloatSpread(radius));
|
|
} else {
|
|
let lambda = Math.acos(2 * Math.random() - 1) - Math.PI / 2;
|
|
let phi = 2 * Math.PI * Math.random();
|
|
light.position.set(Math.cos(lambda) * Math.cos(phi) * length3, Math.abs(Math.cos(lambda) * Math.sin(phi) * length3), Math.sin(lambda) * length3);
|
|
}
|
|
}
|
|
}
|
|
}, [radius, ambient, length3, ...position2]);
|
|
const api = React101.useMemo(() => ({
|
|
update: update2
|
|
}), [update2]);
|
|
React101.useImperativeHandle(forwardRef82, () => api, [api]);
|
|
React101.useLayoutEffect(() => {
|
|
var _parent$lights;
|
|
const group = gLights.current;
|
|
if (parent) (_parent$lights = parent.lights) == null || _parent$lights.set(group.uuid, api);
|
|
return () => {
|
|
var _parent$lights2;
|
|
return void (parent == null || (_parent$lights2 = parent.lights) == null ? void 0 : _parent$lights2.delete(group.uuid));
|
|
};
|
|
}, [parent, api]);
|
|
return React101.createElement("group", _extends({
|
|
ref: gLights
|
|
}, props), Array.from({
|
|
length: amount
|
|
}, (_, index2) => React101.createElement("directionalLight", {
|
|
key: index2,
|
|
castShadow,
|
|
"shadow-bias": bias,
|
|
"shadow-mapSize": [mapSize, mapSize],
|
|
intensity: intensity / amount
|
|
}, React101.createElement("orthographicCamera", {
|
|
attach: "shadow-camera",
|
|
args: [-size, size, size, -size, near, far]
|
|
}))));
|
|
});
|
|
var ProgressiveLightMap = class {
|
|
constructor(renderer, scene, res = 1024) {
|
|
this.renderer = renderer;
|
|
this.res = res;
|
|
this.scene = scene;
|
|
this.buffer1Active = false;
|
|
this.lights = [];
|
|
this.meshes = [];
|
|
this.object = null;
|
|
this.clearColor = new Color();
|
|
this.clearAlpha = 0;
|
|
const textureParams = {
|
|
type: HalfFloatType,
|
|
magFilter: NearestFilter,
|
|
minFilter: NearestFilter
|
|
};
|
|
this.progressiveLightMap1 = new WebGLRenderTarget(this.res, this.res, textureParams);
|
|
this.progressiveLightMap2 = new WebGLRenderTarget(this.res, this.res, textureParams);
|
|
this.discardMat = new DiscardMaterial();
|
|
this.targetMat = new MeshLambertMaterial({
|
|
fog: false
|
|
});
|
|
this.previousShadowMap = {
|
|
value: this.progressiveLightMap1.texture
|
|
};
|
|
this.averagingWindow = {
|
|
value: 100
|
|
};
|
|
this.targetMat.onBeforeCompile = (shader) => {
|
|
shader.vertexShader = "varying vec2 vUv;\n" + shader.vertexShader.slice(0, -1) + "vUv = uv; gl_Position = vec4((uv - 0.5) * 2.0, 1.0, 1.0); }";
|
|
const bodyStart = shader.fragmentShader.indexOf("void main() {");
|
|
shader.fragmentShader = "varying vec2 vUv;\n" + shader.fragmentShader.slice(0, bodyStart) + "uniform sampler2D previousShadowMap;\n uniform float averagingWindow;\n" + shader.fragmentShader.slice(bodyStart - 1, -1) + `
|
|
vec3 texelOld = texture2D(previousShadowMap, vUv).rgb;
|
|
gl_FragColor.rgb = mix(texelOld, gl_FragColor.rgb, 1.0/ averagingWindow);
|
|
}`;
|
|
shader.uniforms.previousShadowMap = this.previousShadowMap;
|
|
shader.uniforms.averagingWindow = this.averagingWindow;
|
|
};
|
|
}
|
|
clear() {
|
|
this.renderer.getClearColor(this.clearColor);
|
|
this.clearAlpha = this.renderer.getClearAlpha();
|
|
this.renderer.setClearColor("black", 1);
|
|
this.renderer.setRenderTarget(this.progressiveLightMap1);
|
|
this.renderer.clear();
|
|
this.renderer.setRenderTarget(this.progressiveLightMap2);
|
|
this.renderer.clear();
|
|
this.renderer.setRenderTarget(null);
|
|
this.renderer.setClearColor(this.clearColor, this.clearAlpha);
|
|
this.lights = [];
|
|
this.meshes = [];
|
|
this.scene.traverse((object) => {
|
|
if (isGeometry(object)) {
|
|
this.meshes.push({
|
|
object,
|
|
material: object.material
|
|
});
|
|
} else if (isLight3(object)) {
|
|
this.lights.push({
|
|
object,
|
|
intensity: object.intensity
|
|
});
|
|
}
|
|
});
|
|
}
|
|
prepare() {
|
|
this.lights.forEach((light) => light.object.intensity = 0);
|
|
this.meshes.forEach((mesh) => mesh.object.material = this.discardMat);
|
|
}
|
|
finish() {
|
|
this.lights.forEach((light) => light.object.intensity = light.intensity);
|
|
this.meshes.forEach((mesh) => mesh.object.material = mesh.material);
|
|
}
|
|
configure(object) {
|
|
this.object = object;
|
|
}
|
|
update(camera, blendWindow = 100) {
|
|
if (!this.object) return;
|
|
this.averagingWindow.value = blendWindow;
|
|
this.object.material = this.targetMat;
|
|
const activeMap = this.buffer1Active ? this.progressiveLightMap1 : this.progressiveLightMap2;
|
|
const inactiveMap = this.buffer1Active ? this.progressiveLightMap2 : this.progressiveLightMap1;
|
|
const oldBg = this.scene.background;
|
|
this.scene.background = null;
|
|
this.renderer.setRenderTarget(activeMap);
|
|
this.previousShadowMap.value = inactiveMap.texture;
|
|
this.buffer1Active = !this.buffer1Active;
|
|
this.renderer.render(this.scene, camera);
|
|
this.renderer.setRenderTarget(null);
|
|
this.scene.background = oldBg;
|
|
}
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/Stage.js
|
|
var presets = {
|
|
rembrandt: {
|
|
main: [1, 2, 1],
|
|
fill: [-2, -0.5, -2]
|
|
},
|
|
portrait: {
|
|
main: [-1, 2, 0.5],
|
|
fill: [-1, 0.5, -1.5]
|
|
},
|
|
upfront: {
|
|
main: [0, 2, 1],
|
|
fill: [-1, 0.5, -1.5]
|
|
},
|
|
soft: {
|
|
main: [-2, 4, 4],
|
|
fill: [-1, 0.5, -1.5]
|
|
}
|
|
};
|
|
function Refit({
|
|
radius,
|
|
adjustCamera
|
|
}) {
|
|
const api = useBounds();
|
|
React102.useEffect(() => {
|
|
if (adjustCamera) api.refresh().clip().fit();
|
|
}, [radius, adjustCamera]);
|
|
return null;
|
|
}
|
|
function Stage({
|
|
children,
|
|
center: center2,
|
|
adjustCamera = true,
|
|
intensity = 0.5,
|
|
shadows = "contact",
|
|
environment = "city",
|
|
preset = "rembrandt",
|
|
...props
|
|
}) {
|
|
var _bias, _normalBias, _size, _offset, _amount, _radius, _ambient, _intensity;
|
|
const config = typeof preset === "string" ? presets[preset] : preset;
|
|
const [{
|
|
radius,
|
|
height
|
|
}, set] = React102.useState({
|
|
radius: 0,
|
|
width: 0,
|
|
height: 0,
|
|
depth: 0
|
|
});
|
|
const shadowBias = (_bias = shadows == null ? void 0 : shadows.bias) !== null && _bias !== void 0 ? _bias : -1e-4;
|
|
const normalBias = (_normalBias = shadows == null ? void 0 : shadows.normalBias) !== null && _normalBias !== void 0 ? _normalBias : 0;
|
|
const shadowSize = (_size = shadows == null ? void 0 : shadows.size) !== null && _size !== void 0 ? _size : 1024;
|
|
const shadowOffset = (_offset = shadows == null ? void 0 : shadows.offset) !== null && _offset !== void 0 ? _offset : 0;
|
|
const contactShadow = shadows === "contact" || (shadows == null ? void 0 : shadows.type) === "contact";
|
|
const accumulativeShadow = shadows === "accumulative" || (shadows == null ? void 0 : shadows.type) === "accumulative";
|
|
const shadowSpread = {
|
|
...typeof shadows === "object" ? shadows : {}
|
|
};
|
|
const environmentProps = !environment ? null : typeof environment === "string" ? {
|
|
preset: environment
|
|
} : environment;
|
|
const onCentered = React102.useCallback((props2) => {
|
|
const {
|
|
width,
|
|
height: height2,
|
|
depth,
|
|
boundingSphere
|
|
} = props2;
|
|
set({
|
|
radius: boundingSphere.radius,
|
|
width,
|
|
height: height2,
|
|
depth
|
|
});
|
|
if (center2 != null && center2.onCentered) center2.onCentered(props2);
|
|
}, []);
|
|
return React102.createElement(React102.Fragment, null, React102.createElement("ambientLight", {
|
|
intensity: intensity / 3
|
|
}), React102.createElement("spotLight", {
|
|
penumbra: 1,
|
|
position: [config.main[0] * radius, config.main[1] * radius, config.main[2] * radius],
|
|
intensity: intensity * 2,
|
|
castShadow: !!shadows,
|
|
"shadow-bias": shadowBias,
|
|
"shadow-normalBias": normalBias,
|
|
"shadow-mapSize": shadowSize
|
|
}), React102.createElement("pointLight", {
|
|
position: [config.fill[0] * radius, config.fill[1] * radius, config.fill[2] * radius],
|
|
intensity
|
|
}), React102.createElement(Bounds, _extends({
|
|
fit: !!adjustCamera,
|
|
clip: !!adjustCamera,
|
|
margin: Number(adjustCamera),
|
|
observe: true
|
|
}, props), React102.createElement(Refit, {
|
|
radius,
|
|
adjustCamera
|
|
}), React102.createElement(Center, _extends({}, center2, {
|
|
position: [0, shadowOffset / 2, 0],
|
|
onCentered
|
|
}), children)), React102.createElement("group", {
|
|
position: [0, -height / 2 - shadowOffset / 2, 0]
|
|
}, contactShadow && React102.createElement(ContactShadows, _extends({
|
|
scale: radius * 4,
|
|
far: radius,
|
|
blur: 2
|
|
}, shadowSpread)), accumulativeShadow && React102.createElement(AccumulativeShadows, _extends({
|
|
temporal: true,
|
|
frames: 100,
|
|
alphaTest: 0.9,
|
|
toneMapped: true,
|
|
scale: radius * 4
|
|
}, shadowSpread), React102.createElement(RandomizedLight, {
|
|
amount: (_amount = shadowSpread.amount) !== null && _amount !== void 0 ? _amount : 8,
|
|
radius: (_radius = shadowSpread.radius) !== null && _radius !== void 0 ? _radius : radius,
|
|
ambient: (_ambient = shadowSpread.ambient) !== null && _ambient !== void 0 ? _ambient : 0.5,
|
|
intensity: (_intensity = shadowSpread.intensity) !== null && _intensity !== void 0 ? _intensity : 1,
|
|
position: [config.main[0] * radius, config.main[1] * radius, config.main[2] * radius],
|
|
size: radius * 4,
|
|
bias: -shadowBias,
|
|
mapSize: shadowSize
|
|
}))), environment && React102.createElement(Environment, environmentProps));
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/Backdrop.js
|
|
var React103 = __toESM(require_react());
|
|
var easeInExpo = (x) => x === 0 ? 0 : Math.pow(2, 10 * x - 10);
|
|
function Backdrop({
|
|
children,
|
|
floor = 0.25,
|
|
segments = 20,
|
|
receiveShadow,
|
|
...props
|
|
}) {
|
|
const ref = React103.useRef(null);
|
|
React103.useLayoutEffect(() => {
|
|
let i3 = 0;
|
|
const offset = segments / segments / 2;
|
|
const position2 = ref.current.attributes.position;
|
|
for (let x = 0; x < segments + 1; x++) {
|
|
for (let y = 0; y < segments + 1; y++) {
|
|
position2.setXYZ(i3++, x / segments - offset + (x === 0 ? -floor : 0), y / segments - offset, easeInExpo(x / segments));
|
|
}
|
|
}
|
|
position2.needsUpdate = true;
|
|
ref.current.computeVertexNormals();
|
|
}, [segments, floor]);
|
|
return React103.createElement("group", props, React103.createElement("mesh", {
|
|
receiveShadow,
|
|
rotation: [-Math.PI / 2, 0, Math.PI / 2]
|
|
}, React103.createElement("planeGeometry", {
|
|
ref,
|
|
args: [1, 1, segments, segments]
|
|
}), children));
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/Shadow.js
|
|
var React104 = __toESM(require_react());
|
|
var Shadow = React104.forwardRef(({
|
|
fog = false,
|
|
renderOrder,
|
|
depthWrite = false,
|
|
colorStop = 0,
|
|
color = "black",
|
|
opacity = 0.5,
|
|
...props
|
|
}, ref) => {
|
|
const canvas = React104.useMemo(() => {
|
|
const canvas2 = document.createElement("canvas");
|
|
canvas2.width = 128;
|
|
canvas2.height = 128;
|
|
const context12 = canvas2.getContext("2d");
|
|
const gradient = context12.createRadialGradient(canvas2.width / 2, canvas2.height / 2, 0, canvas2.width / 2, canvas2.height / 2, canvas2.width / 2);
|
|
gradient.addColorStop(colorStop, new Color(color).getStyle());
|
|
gradient.addColorStop(1, "rgba(0,0,0,0)");
|
|
context12.fillStyle = gradient;
|
|
context12.fillRect(0, 0, canvas2.width, canvas2.height);
|
|
return canvas2;
|
|
}, [color, colorStop]);
|
|
return React104.createElement("mesh", _extends({
|
|
renderOrder,
|
|
ref,
|
|
"rotation-x": -Math.PI / 2
|
|
}, props), React104.createElement("planeGeometry", null), React104.createElement("meshBasicMaterial", {
|
|
transparent: true,
|
|
opacity,
|
|
fog,
|
|
depthWrite,
|
|
side: DoubleSide
|
|
}, React104.createElement("canvasTexture", {
|
|
attach: "map",
|
|
args: [canvas]
|
|
})));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Caustics.js
|
|
var React105 = __toESM(require_react());
|
|
function createNormalMaterial(side = FrontSide) {
|
|
const viewMatrix = {
|
|
value: new Matrix4()
|
|
};
|
|
return Object.assign(new MeshNormalMaterial({
|
|
side
|
|
}), {
|
|
viewMatrix,
|
|
onBeforeCompile: (shader) => {
|
|
shader.uniforms.viewMatrix = viewMatrix;
|
|
shader.fragmentShader = `vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {
|
|
return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );
|
|
}
|
|
` + shader.fragmentShader.replace("#include <normal_fragment_maps>", `#include <normal_fragment_maps>
|
|
normal = inverseTransformDirection( normal, viewMatrix );
|
|
`);
|
|
}
|
|
});
|
|
}
|
|
var CausticsProjectionMaterial = shaderMaterial({
|
|
causticsTexture: null,
|
|
causticsTextureB: null,
|
|
color: new Color(),
|
|
lightProjMatrix: new Matrix4(),
|
|
lightViewMatrix: new Matrix4()
|
|
}, `varying vec3 vWorldPosition;
|
|
void main() {
|
|
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.);
|
|
vec4 worldPosition = modelMatrix * vec4(position, 1.);
|
|
vWorldPosition = worldPosition.xyz;
|
|
}`, `varying vec3 vWorldPosition;
|
|
uniform vec3 color;
|
|
uniform sampler2D causticsTexture;
|
|
uniform sampler2D causticsTextureB;
|
|
uniform mat4 lightProjMatrix;
|
|
uniform mat4 lightViewMatrix;
|
|
void main() {
|
|
// Apply caustics
|
|
vec4 lightSpacePos = lightProjMatrix * lightViewMatrix * vec4(vWorldPosition, 1.0);
|
|
lightSpacePos.xyz /= lightSpacePos.w;
|
|
lightSpacePos.xyz = lightSpacePos.xyz * 0.5 + 0.5;
|
|
vec3 front = texture2D(causticsTexture, lightSpacePos.xy).rgb;
|
|
vec3 back = texture2D(causticsTextureB, lightSpacePos.xy).rgb;
|
|
gl_FragColor = vec4((front + back) * color, 1.0);
|
|
#include <tonemapping_fragment>
|
|
#include <${version >= 154 ? "colorspace_fragment" : "encodings_fragment"}>
|
|
}`);
|
|
var CausticsMaterial = shaderMaterial(
|
|
{
|
|
cameraMatrixWorld: new Matrix4(),
|
|
cameraProjectionMatrixInv: new Matrix4(),
|
|
normalTexture: null,
|
|
depthTexture: null,
|
|
lightDir: new Vector3(0, 1, 0),
|
|
lightPlaneNormal: new Vector3(0, 1, 0),
|
|
lightPlaneConstant: 0,
|
|
near: 0.1,
|
|
far: 100,
|
|
modelMatrix: new Matrix4(),
|
|
worldRadius: 1 / 40,
|
|
ior: 1.1,
|
|
bounces: 0,
|
|
resolution: 1024,
|
|
size: 10,
|
|
intensity: 0.5
|
|
},
|
|
/* glsl */
|
|
`
|
|
varying vec2 vUv;
|
|
void main() {
|
|
vUv = uv;
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
}`,
|
|
/* glsl */
|
|
`
|
|
uniform mat4 cameraMatrixWorld;
|
|
uniform mat4 cameraProjectionMatrixInv;
|
|
uniform vec3 lightDir;
|
|
uniform vec3 lightPlaneNormal;
|
|
uniform float lightPlaneConstant;
|
|
uniform float near;
|
|
uniform float far;
|
|
uniform float time;
|
|
uniform float worldRadius;
|
|
uniform float resolution;
|
|
uniform float size;
|
|
uniform float intensity;
|
|
uniform float ior;
|
|
precision highp isampler2D;
|
|
precision highp usampler2D;
|
|
uniform sampler2D normalTexture;
|
|
uniform sampler2D depthTexture;
|
|
uniform float bounces;
|
|
varying vec2 vUv;
|
|
vec3 WorldPosFromDepth(float depth, vec2 coord) {
|
|
float z = depth * 2.0 - 1.0;
|
|
vec4 clipSpacePosition = vec4(coord * 2.0 - 1.0, z, 1.0);
|
|
vec4 viewSpacePosition = cameraProjectionMatrixInv * clipSpacePosition;
|
|
// Perspective division
|
|
viewSpacePosition /= viewSpacePosition.w;
|
|
vec4 worldSpacePosition = cameraMatrixWorld * viewSpacePosition;
|
|
return worldSpacePosition.xyz;
|
|
}
|
|
float sdPlane( vec3 p, vec3 n, float h ) {
|
|
// n must be normalized
|
|
return dot(p,n) + h;
|
|
}
|
|
float planeIntersect( vec3 ro, vec3 rd, vec4 p ) {
|
|
return -(dot(ro,p.xyz)+p.w)/dot(rd,p.xyz);
|
|
}
|
|
vec3 totalInternalReflection(vec3 ro, vec3 rd, vec3 pos, vec3 normal, float ior, out vec3 rayOrigin, out vec3 rayDirection) {
|
|
rayOrigin = ro;
|
|
rayDirection = rd;
|
|
rayDirection = refract(rayDirection, normal, 1.0 / ior);
|
|
rayOrigin = pos + rayDirection * 0.1;
|
|
return rayDirection;
|
|
}
|
|
void main() {
|
|
// Each sample consists of random offset in the x and y direction
|
|
float caustic = 0.0;
|
|
float causticTexelSize = (1.0 / resolution) * size * 2.0;
|
|
float texelsNeeded = worldRadius / causticTexelSize;
|
|
float sampleRadius = texelsNeeded / resolution;
|
|
float sum = 0.0;
|
|
if (texture2D(depthTexture, vUv).x == 1.0) {
|
|
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
|
return;
|
|
}
|
|
vec2 offset1 = vec2(-0.5, -0.5);//vec2(rand() - 0.5, rand() - 0.5);
|
|
vec2 offset2 = vec2(-0.5, 0.5);//vec2(rand() - 0.5, rand() - 0.5);
|
|
vec2 offset3 = vec2(0.5, 0.5);//vec2(rand() - 0.5, rand() - 0.5);
|
|
vec2 offset4 = vec2(0.5, -0.5);//vec2(rand() - 0.5, rand() - 0.5);
|
|
vec2 uv1 = vUv + offset1 * sampleRadius;
|
|
vec2 uv2 = vUv + offset2 * sampleRadius;
|
|
vec2 uv3 = vUv + offset3 * sampleRadius;
|
|
vec2 uv4 = vUv + offset4 * sampleRadius;
|
|
vec3 normal1 = texture2D(normalTexture, uv1, -10.0).rgb * 2.0 - 1.0;
|
|
vec3 normal2 = texture2D(normalTexture, uv2, -10.0).rgb * 2.0 - 1.0;
|
|
vec3 normal3 = texture2D(normalTexture, uv3, -10.0).rgb * 2.0 - 1.0;
|
|
vec3 normal4 = texture2D(normalTexture, uv4, -10.0).rgb * 2.0 - 1.0;
|
|
float depth1 = texture2D(depthTexture, uv1, -10.0).x;
|
|
float depth2 = texture2D(depthTexture, uv2, -10.0).x;
|
|
float depth3 = texture2D(depthTexture, uv3, -10.0).x;
|
|
float depth4 = texture2D(depthTexture, uv4, -10.0).x;
|
|
// Sanity check the depths
|
|
if (depth1 == 1.0 || depth2 == 1.0 || depth3 == 1.0 || depth4 == 1.0) {
|
|
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
|
return;
|
|
}
|
|
vec3 pos1 = WorldPosFromDepth(depth1, uv1);
|
|
vec3 pos2 = WorldPosFromDepth(depth2, uv2);
|
|
vec3 pos3 = WorldPosFromDepth(depth3, uv3);
|
|
vec3 pos4 = WorldPosFromDepth(depth4, uv4);
|
|
vec3 originPos1 = WorldPosFromDepth(0.0, uv1);
|
|
vec3 originPos2 = WorldPosFromDepth(0.0, uv2);
|
|
vec3 originPos3 = WorldPosFromDepth(0.0, uv3);
|
|
vec3 originPos4 = WorldPosFromDepth(0.0, uv4);
|
|
vec3 endPos1, endPos2, endPos3, endPos4;
|
|
vec3 endDir1, endDir2, endDir3, endDir4;
|
|
totalInternalReflection(originPos1, lightDir, pos1, normal1, ior, endPos1, endDir1);
|
|
totalInternalReflection(originPos2, lightDir, pos2, normal2, ior, endPos2, endDir2);
|
|
totalInternalReflection(originPos3, lightDir, pos3, normal3, ior, endPos3, endDir3);
|
|
totalInternalReflection(originPos4, lightDir, pos4, normal4, ior, endPos4, endDir4);
|
|
float lightPosArea = length(cross(originPos2 - originPos1, originPos3 - originPos1)) + length(cross(originPos3 - originPos1, originPos4 - originPos1));
|
|
float t1 = planeIntersect(endPos1, endDir1, vec4(lightPlaneNormal, lightPlaneConstant));
|
|
float t2 = planeIntersect(endPos2, endDir2, vec4(lightPlaneNormal, lightPlaneConstant));
|
|
float t3 = planeIntersect(endPos3, endDir3, vec4(lightPlaneNormal, lightPlaneConstant));
|
|
float t4 = planeIntersect(endPos4, endDir4, vec4(lightPlaneNormal, lightPlaneConstant));
|
|
vec3 finalPos1 = endPos1 + endDir1 * t1;
|
|
vec3 finalPos2 = endPos2 + endDir2 * t2;
|
|
vec3 finalPos3 = endPos3 + endDir3 * t3;
|
|
vec3 finalPos4 = endPos4 + endDir4 * t4;
|
|
float finalArea = length(cross(finalPos2 - finalPos1, finalPos3 - finalPos1)) + length(cross(finalPos3 - finalPos1, finalPos4 - finalPos1));
|
|
caustic += intensity * (lightPosArea / finalArea);
|
|
// Calculate the area of the triangle in light spaces
|
|
gl_FragColor = vec4(vec3(max(caustic, 0.0)), 1.0);
|
|
}`
|
|
);
|
|
var NORMALPROPS = {
|
|
depth: true,
|
|
minFilter: LinearFilter,
|
|
magFilter: LinearFilter,
|
|
type: UnsignedByteType
|
|
};
|
|
var CAUSTICPROPS = {
|
|
minFilter: LinearMipmapLinearFilter,
|
|
magFilter: LinearFilter,
|
|
type: FloatType,
|
|
generateMipmaps: true
|
|
};
|
|
var Caustics = React105.forwardRef(({
|
|
debug,
|
|
children,
|
|
frames = 1,
|
|
ior = 1.1,
|
|
color = "white",
|
|
causticsOnly = false,
|
|
backside = false,
|
|
backsideIOR = 1.1,
|
|
worldRadius = 0.3125,
|
|
intensity = 0.05,
|
|
resolution = 2024,
|
|
lightSource = [5, 5, 5],
|
|
...props
|
|
}, fref) => {
|
|
extend({
|
|
CausticsProjectionMaterial
|
|
});
|
|
const ref = React105.useRef(null);
|
|
const camera = React105.useRef(null);
|
|
const scene = React105.useRef(null);
|
|
const plane = React105.useRef(null);
|
|
const gl = useThree((state) => state.gl);
|
|
const helper = useHelper(debug && camera, CameraHelper);
|
|
const normalTarget = useFBO(resolution, resolution, NORMALPROPS);
|
|
const normalTargetB = useFBO(resolution, resolution, NORMALPROPS);
|
|
const causticsTarget = useFBO(resolution, resolution, CAUSTICPROPS);
|
|
const causticsTargetB = useFBO(resolution, resolution, CAUSTICPROPS);
|
|
const [normalMat] = React105.useState(() => createNormalMaterial());
|
|
const [normalMatB] = React105.useState(() => createNormalMaterial(BackSide));
|
|
const [causticsMaterial] = React105.useState(() => new CausticsMaterial());
|
|
const [causticsQuad] = React105.useState(() => new FullScreenQuad(causticsMaterial));
|
|
React105.useLayoutEffect(() => {
|
|
ref.current.updateWorldMatrix(false, true);
|
|
});
|
|
let count = 0;
|
|
const v5 = new Vector3();
|
|
const lpF = new Frustum();
|
|
const lpM = new Matrix4();
|
|
const lpP = new Plane();
|
|
const lightDir = new Vector3();
|
|
const lightDirInv = new Vector3();
|
|
const bounds = new Box3();
|
|
const focusPos = new Vector3();
|
|
const boundsVertices = [];
|
|
const worldVerts = [];
|
|
const projectedVerts = [];
|
|
const lightDirs = [];
|
|
const cameraPos = new Vector3();
|
|
for (let i3 = 0; i3 < 8; i3++) {
|
|
boundsVertices.push(new Vector3());
|
|
worldVerts.push(new Vector3());
|
|
projectedVerts.push(new Vector3());
|
|
lightDirs.push(new Vector3());
|
|
}
|
|
useFrame(() => {
|
|
if (frames === Infinity || count++ < frames) {
|
|
var _scene$current$parent, _helper$current;
|
|
if (Array.isArray(lightSource)) lightDir.fromArray(lightSource).normalize();
|
|
else lightDir.copy(ref.current.worldToLocal(lightSource.current.getWorldPosition(v5)).normalize());
|
|
lightDirInv.copy(lightDir).multiplyScalar(-1);
|
|
(_scene$current$parent = scene.current.parent) == null || _scene$current$parent.matrixWorld.identity();
|
|
bounds.setFromObject(scene.current, true);
|
|
boundsVertices[0].set(bounds.min.x, bounds.min.y, bounds.min.z);
|
|
boundsVertices[1].set(bounds.min.x, bounds.min.y, bounds.max.z);
|
|
boundsVertices[2].set(bounds.min.x, bounds.max.y, bounds.min.z);
|
|
boundsVertices[3].set(bounds.min.x, bounds.max.y, bounds.max.z);
|
|
boundsVertices[4].set(bounds.max.x, bounds.min.y, bounds.min.z);
|
|
boundsVertices[5].set(bounds.max.x, bounds.min.y, bounds.max.z);
|
|
boundsVertices[6].set(bounds.max.x, bounds.max.y, bounds.min.z);
|
|
boundsVertices[7].set(bounds.max.x, bounds.max.y, bounds.max.z);
|
|
for (let i3 = 0; i3 < 8; i3++) {
|
|
worldVerts[i3].copy(boundsVertices[i3]);
|
|
}
|
|
bounds.getCenter(focusPos);
|
|
boundsVertices.map((v6) => v6.sub(focusPos));
|
|
const lightPlane = lpP.set(lightDirInv, 0);
|
|
boundsVertices.map((v6, i3) => lightPlane.projectPoint(v6, projectedVerts[i3]));
|
|
const centralVert = projectedVerts.reduce((a5, b) => a5.add(b), v5.set(0, 0, 0)).divideScalar(projectedVerts.length);
|
|
const radius = projectedVerts.map((v6) => v6.distanceTo(centralVert)).reduce((a5, b) => Math.max(a5, b));
|
|
const dirLength = boundsVertices.map((x) => x.dot(lightDir)).reduce((a5, b) => Math.max(a5, b));
|
|
camera.current.position.copy(cameraPos.copy(lightDir).multiplyScalar(dirLength).add(focusPos));
|
|
camera.current.lookAt(scene.current.localToWorld(focusPos));
|
|
const dirMatrix = lpM.lookAt(camera.current.position, focusPos, v5.set(0, 1, 0));
|
|
camera.current.left = -radius;
|
|
camera.current.right = radius;
|
|
camera.current.top = radius;
|
|
camera.current.bottom = -radius;
|
|
const yOffset = v5.set(0, radius, 0).applyMatrix4(dirMatrix);
|
|
const yTime = (camera.current.position.y + yOffset.y) / lightDir.y;
|
|
camera.current.near = 0.1;
|
|
camera.current.far = yTime;
|
|
camera.current.updateProjectionMatrix();
|
|
camera.current.updateMatrixWorld();
|
|
const groundProjectedCoords = worldVerts.map((v6, i3) => v6.add(lightDirs[i3].copy(lightDir).multiplyScalar(-v6.y / lightDir.y)));
|
|
const centerPos = groundProjectedCoords.reduce((a5, b) => a5.add(b), v5.set(0, 0, 0)).divideScalar(groundProjectedCoords.length);
|
|
const maxSize = 2 * groundProjectedCoords.map((v6) => Math.hypot(v6.x - centerPos.x, v6.z - centerPos.z)).reduce((a5, b) => Math.max(a5, b));
|
|
plane.current.scale.setScalar(maxSize);
|
|
plane.current.position.copy(centerPos);
|
|
if (debug) (_helper$current = helper.current) == null || _helper$current.update();
|
|
normalMatB.viewMatrix.value = normalMat.viewMatrix.value = camera.current.matrixWorldInverse;
|
|
const dirLightNearPlane = lpF.setFromProjectionMatrix(lpM.multiplyMatrices(camera.current.projectionMatrix, camera.current.matrixWorldInverse)).planes[4];
|
|
causticsMaterial.cameraMatrixWorld = camera.current.matrixWorld;
|
|
causticsMaterial.cameraProjectionMatrixInv = camera.current.projectionMatrixInverse;
|
|
causticsMaterial.lightDir = lightDirInv;
|
|
causticsMaterial.lightPlaneNormal = dirLightNearPlane.normal;
|
|
causticsMaterial.lightPlaneConstant = dirLightNearPlane.constant;
|
|
causticsMaterial.near = camera.current.near;
|
|
causticsMaterial.far = camera.current.far;
|
|
causticsMaterial.resolution = resolution;
|
|
causticsMaterial.size = radius;
|
|
causticsMaterial.intensity = intensity;
|
|
causticsMaterial.worldRadius = worldRadius;
|
|
scene.current.visible = true;
|
|
gl.setRenderTarget(normalTarget);
|
|
gl.clear();
|
|
scene.current.overrideMaterial = normalMat;
|
|
gl.render(scene.current, camera.current);
|
|
gl.setRenderTarget(normalTargetB);
|
|
gl.clear();
|
|
if (backside) {
|
|
scene.current.overrideMaterial = normalMatB;
|
|
gl.render(scene.current, camera.current);
|
|
}
|
|
scene.current.overrideMaterial = null;
|
|
causticsMaterial.ior = ior;
|
|
plane.current.material.lightProjMatrix = camera.current.projectionMatrix;
|
|
plane.current.material.lightViewMatrix = camera.current.matrixWorldInverse;
|
|
causticsMaterial.normalTexture = normalTarget.texture;
|
|
causticsMaterial.depthTexture = normalTarget.depthTexture;
|
|
gl.setRenderTarget(causticsTarget);
|
|
gl.clear();
|
|
causticsQuad.render(gl);
|
|
causticsMaterial.ior = backsideIOR;
|
|
causticsMaterial.normalTexture = normalTargetB.texture;
|
|
causticsMaterial.depthTexture = normalTargetB.depthTexture;
|
|
gl.setRenderTarget(causticsTargetB);
|
|
gl.clear();
|
|
if (backside) causticsQuad.render(gl);
|
|
gl.setRenderTarget(null);
|
|
if (causticsOnly) scene.current.visible = false;
|
|
}
|
|
});
|
|
React105.useImperativeHandle(fref, () => ref.current, []);
|
|
return React105.createElement("group", _extends({
|
|
ref
|
|
}, props), React105.createElement("scene", {
|
|
ref: scene
|
|
}, React105.createElement("orthographicCamera", {
|
|
ref: camera,
|
|
up: [0, 1, 0]
|
|
}), children), React105.createElement("mesh", {
|
|
renderOrder: 2,
|
|
ref: plane,
|
|
"rotation-x": -Math.PI / 2
|
|
}, React105.createElement("planeGeometry", null), React105.createElement("causticsProjectionMaterial", {
|
|
transparent: true,
|
|
color,
|
|
causticsTexture: causticsTarget.texture,
|
|
causticsTextureB: causticsTargetB.texture,
|
|
blending: CustomBlending,
|
|
blendSrc: OneFactor,
|
|
blendDst: SrcAlphaFactor,
|
|
depthWrite: false
|
|
}), debug && React105.createElement(Edges, null, React105.createElement("lineBasicMaterial", {
|
|
color: "#ffff00",
|
|
toneMapped: false
|
|
}))));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/SpotLight.js
|
|
var React106 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/materials/SpotLightMaterial.js
|
|
var SpotLightMaterial = class extends ShaderMaterial {
|
|
constructor() {
|
|
super({
|
|
uniforms: {
|
|
depth: {
|
|
value: null
|
|
},
|
|
opacity: {
|
|
value: 1
|
|
},
|
|
attenuation: {
|
|
value: 2.5
|
|
},
|
|
anglePower: {
|
|
value: 12
|
|
},
|
|
spotPosition: {
|
|
value: new Vector3(0, 0, 0)
|
|
},
|
|
lightColor: {
|
|
value: new Color("white")
|
|
},
|
|
cameraNear: {
|
|
value: 0
|
|
},
|
|
cameraFar: {
|
|
value: 1
|
|
},
|
|
resolution: {
|
|
value: new Vector2(0, 0)
|
|
}
|
|
},
|
|
transparent: true,
|
|
depthWrite: false,
|
|
vertexShader: (
|
|
/* glsl */
|
|
`
|
|
varying vec3 vNormal;
|
|
varying float vViewZ;
|
|
varying float vIntensity;
|
|
uniform vec3 spotPosition;
|
|
uniform float attenuation;
|
|
|
|
#include <common>
|
|
#include <logdepthbuf_pars_vertex>
|
|
|
|
void main() {
|
|
// compute intensity
|
|
vNormal = normalize(normalMatrix * normal);
|
|
vec4 worldPosition = modelMatrix * vec4(position, 1);
|
|
vec4 viewPosition = viewMatrix * worldPosition;
|
|
vViewZ = viewPosition.z;
|
|
|
|
vIntensity = 1.0 - saturate(distance(worldPosition.xyz, spotPosition) / attenuation);
|
|
|
|
gl_Position = projectionMatrix * viewPosition;
|
|
|
|
#include <logdepthbuf_vertex>
|
|
}
|
|
`
|
|
),
|
|
fragmentShader: (
|
|
/* glsl */
|
|
`
|
|
varying vec3 vNormal;
|
|
varying float vViewZ;
|
|
varying float vIntensity;
|
|
|
|
uniform vec3 lightColor;
|
|
uniform float anglePower;
|
|
uniform sampler2D depth;
|
|
uniform vec2 resolution;
|
|
uniform float cameraNear;
|
|
uniform float cameraFar;
|
|
uniform float opacity;
|
|
|
|
#include <packing>
|
|
#include <logdepthbuf_pars_fragment>
|
|
|
|
float readDepth(sampler2D depthSampler, vec2 uv) {
|
|
float fragCoordZ = texture(depthSampler, uv).r;
|
|
|
|
// https://github.com/mrdoob/three.js/issues/23072
|
|
#ifdef USE_LOGDEPTHBUF
|
|
float viewZ = 1.0 - exp2(fragCoordZ * log(cameraFar + 1.0) / log(2.0));
|
|
#else
|
|
float viewZ = perspectiveDepthToViewZ(fragCoordZ, cameraNear, cameraFar);
|
|
#endif
|
|
|
|
return viewZ;
|
|
}
|
|
|
|
void main() {
|
|
#include <logdepthbuf_fragment>
|
|
|
|
vec3 normal = vec3(vNormal.x, vNormal.y, abs(vNormal.z));
|
|
float angleIntensity = pow(dot(normal, vec3(0, 0, 1)), anglePower);
|
|
float intensity = vIntensity * angleIntensity;
|
|
|
|
// fades when z is close to sampled depth, meaning the cone is intersecting existing geometry
|
|
bool isSoft = resolution[0] > 0.0 && resolution[1] > 0.0;
|
|
if (isSoft) {
|
|
vec2 uv = gl_FragCoord.xy / resolution;
|
|
intensity *= smoothstep(0.0, 1.0, vViewZ - readDepth(depth, uv));
|
|
}
|
|
|
|
gl_FragColor = vec4(lightColor, intensity * opacity);
|
|
|
|
#include <tonemapping_fragment>
|
|
#include <${version >= 154 ? "colorspace_fragment" : "encodings_fragment"}>
|
|
}
|
|
`
|
|
)
|
|
});
|
|
}
|
|
};
|
|
|
|
// node_modules/@react-three/drei/helpers/glsl/DefaultSpotlightShadowShadows.glsl.js
|
|
var SpotlightShadowShader = "#define GLSLIFY 1\nvarying vec2 vUv;uniform sampler2D uShadowMap;uniform float uTime;void main(){vec3 color=texture2D(uShadowMap,vUv).xyz;gl_FragColor=vec4(color,1.);}";
|
|
|
|
// node_modules/@react-three/drei/core/SpotLight.js
|
|
var isSpotLight = (child) => {
|
|
return child == null ? void 0 : child.isSpotLight;
|
|
};
|
|
function VolumetricMesh({
|
|
opacity = 1,
|
|
radiusTop,
|
|
radiusBottom,
|
|
depthBuffer,
|
|
color = "white",
|
|
distance: distance3 = 5,
|
|
angle = 0.15,
|
|
attenuation = 5,
|
|
anglePower = 5
|
|
}) {
|
|
const mesh = React106.useRef(null);
|
|
const size = useThree((state) => state.size);
|
|
const camera = useThree((state) => state.camera);
|
|
const dpr = useThree((state) => state.viewport.dpr);
|
|
const [material] = React106.useState(() => new SpotLightMaterial());
|
|
const [vec] = React106.useState(() => new Vector3());
|
|
radiusTop = radiusTop === void 0 ? 0.1 : radiusTop;
|
|
radiusBottom = radiusBottom === void 0 ? angle * 7 : radiusBottom;
|
|
useFrame(() => {
|
|
material.uniforms.spotPosition.value.copy(mesh.current.getWorldPosition(vec));
|
|
mesh.current.lookAt(mesh.current.parent.target.getWorldPosition(vec));
|
|
});
|
|
const geom = React106.useMemo(() => {
|
|
const geometry3 = new CylinderGeometry(radiusTop, radiusBottom, distance3, 128, 64, true);
|
|
geometry3.applyMatrix4(new Matrix4().makeTranslation(0, -distance3 / 2, 0));
|
|
geometry3.applyMatrix4(new Matrix4().makeRotationX(-Math.PI / 2));
|
|
return geometry3;
|
|
}, [distance3, radiusTop, radiusBottom]);
|
|
return React106.createElement(React106.Fragment, null, React106.createElement("mesh", {
|
|
ref: mesh,
|
|
geometry: geom,
|
|
raycast: () => null
|
|
}, React106.createElement("primitive", {
|
|
object: material,
|
|
attach: "material",
|
|
"uniforms-opacity-value": opacity,
|
|
"uniforms-lightColor-value": color,
|
|
"uniforms-attenuation-value": attenuation,
|
|
"uniforms-anglePower-value": anglePower,
|
|
"uniforms-depth-value": depthBuffer,
|
|
"uniforms-cameraNear-value": camera.near,
|
|
"uniforms-cameraFar-value": camera.far,
|
|
"uniforms-resolution-value": depthBuffer ? [size.width * dpr, size.height * dpr] : [0, 0]
|
|
})));
|
|
}
|
|
function useCommon(spotlight, mesh, width, height, distance3) {
|
|
const [[pos, dir]] = React106.useState(() => [new Vector3(), new Vector3()]);
|
|
React106.useLayoutEffect(() => {
|
|
if (isSpotLight(spotlight.current)) {
|
|
spotlight.current.shadow.mapSize.set(width, height);
|
|
spotlight.current.shadow.needsUpdate = true;
|
|
} else {
|
|
throw new Error("SpotlightShadow must be a child of a SpotLight");
|
|
}
|
|
}, [spotlight, width, height]);
|
|
useFrame(() => {
|
|
if (!spotlight.current) return;
|
|
const A = spotlight.current.position;
|
|
const B = spotlight.current.target.position;
|
|
dir.copy(B).sub(A);
|
|
var len = dir.length();
|
|
dir.normalize().multiplyScalar(len * distance3);
|
|
pos.copy(A).add(dir);
|
|
mesh.current.position.copy(pos);
|
|
mesh.current.lookAt(spotlight.current.target.position);
|
|
});
|
|
}
|
|
function SpotlightShadowWithShader({
|
|
distance: distance3 = 0.4,
|
|
alphaTest = 0.5,
|
|
map: map2,
|
|
shader = SpotlightShadowShader,
|
|
width = 512,
|
|
height = 512,
|
|
scale: scale5 = 1,
|
|
children,
|
|
...rest
|
|
}) {
|
|
const mesh = React106.useRef(null);
|
|
const spotlight = rest.spotlightRef;
|
|
const debug = rest.debug;
|
|
useCommon(spotlight, mesh, width, height, distance3);
|
|
const renderTarget = React106.useMemo(() => new WebGLRenderTarget(width, height, {
|
|
format: RGBAFormat,
|
|
stencilBuffer: false
|
|
// depthTexture: null!
|
|
}), [width, height]);
|
|
const uniforms = React106.useRef({
|
|
uShadowMap: {
|
|
value: map2
|
|
},
|
|
uTime: {
|
|
value: 0
|
|
}
|
|
});
|
|
React106.useEffect(() => void (uniforms.current.uShadowMap.value = map2), [map2]);
|
|
const fsQuad = React106.useMemo(() => new FullScreenQuad(new ShaderMaterial({
|
|
uniforms: uniforms.current,
|
|
vertexShader: (
|
|
/* glsl */
|
|
`
|
|
varying vec2 vUv;
|
|
|
|
void main() {
|
|
vUv = uv;
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
}
|
|
`
|
|
),
|
|
fragmentShader: shader
|
|
})), [shader]);
|
|
React106.useEffect(() => () => {
|
|
fsQuad.material.dispose();
|
|
fsQuad.dispose();
|
|
}, [fsQuad]);
|
|
React106.useEffect(() => () => renderTarget.dispose(), [renderTarget]);
|
|
useFrame(({
|
|
gl
|
|
}, dt) => {
|
|
uniforms.current.uTime.value += dt;
|
|
gl.setRenderTarget(renderTarget);
|
|
fsQuad.render(gl);
|
|
gl.setRenderTarget(null);
|
|
});
|
|
return React106.createElement(React106.Fragment, null, React106.createElement("mesh", {
|
|
ref: mesh,
|
|
scale: scale5,
|
|
castShadow: true
|
|
}, React106.createElement("planeGeometry", null), React106.createElement("meshBasicMaterial", {
|
|
transparent: true,
|
|
side: DoubleSide,
|
|
alphaTest,
|
|
alphaMap: renderTarget.texture,
|
|
"alphaMap-wrapS": RepeatWrapping,
|
|
"alphaMap-wrapT": RepeatWrapping,
|
|
opacity: debug ? 1 : 0
|
|
}, children)));
|
|
}
|
|
function SpotlightShadowWithoutShader({
|
|
distance: distance3 = 0.4,
|
|
alphaTest = 0.5,
|
|
map: map2,
|
|
width = 512,
|
|
height = 512,
|
|
scale: scale5,
|
|
children,
|
|
...rest
|
|
}) {
|
|
const mesh = React106.useRef(null);
|
|
const spotlight = rest.spotlightRef;
|
|
const debug = rest.debug;
|
|
useCommon(spotlight, mesh, width, height, distance3);
|
|
return React106.createElement(React106.Fragment, null, React106.createElement("mesh", {
|
|
ref: mesh,
|
|
scale: scale5,
|
|
castShadow: true
|
|
}, React106.createElement("planeGeometry", null), React106.createElement("meshBasicMaterial", {
|
|
transparent: true,
|
|
side: DoubleSide,
|
|
alphaTest,
|
|
alphaMap: map2,
|
|
"alphaMap-wrapS": RepeatWrapping,
|
|
"alphaMap-wrapT": RepeatWrapping,
|
|
opacity: debug ? 1 : 0
|
|
}, children)));
|
|
}
|
|
function SpotLightShadow(props) {
|
|
if (props.shader) return React106.createElement(SpotlightShadowWithShader, props);
|
|
return React106.createElement(SpotlightShadowWithoutShader, props);
|
|
}
|
|
var SpotLight = React106.forwardRef(({
|
|
// Volumetric
|
|
opacity = 1,
|
|
radiusTop,
|
|
radiusBottom,
|
|
depthBuffer,
|
|
color = "white",
|
|
distance: distance3 = 5,
|
|
angle = 0.15,
|
|
attenuation = 5,
|
|
anglePower = 5,
|
|
volumetric = true,
|
|
debug = false,
|
|
children,
|
|
...props
|
|
}, ref) => {
|
|
const spotlight = React106.useRef(null);
|
|
React106.useImperativeHandle(ref, () => spotlight.current, []);
|
|
return React106.createElement("group", null, debug && spotlight.current && React106.createElement("spotLightHelper", {
|
|
args: [spotlight.current]
|
|
}), React106.createElement("spotLight", _extends({
|
|
ref: spotlight,
|
|
angle,
|
|
color,
|
|
distance: distance3,
|
|
castShadow: true
|
|
}, props), volumetric && React106.createElement(VolumetricMesh, {
|
|
debug,
|
|
opacity,
|
|
radiusTop,
|
|
radiusBottom,
|
|
depthBuffer,
|
|
color,
|
|
distance: distance3,
|
|
angle,
|
|
attenuation,
|
|
anglePower
|
|
})), children && React106.cloneElement(children, {
|
|
spotlightRef: spotlight,
|
|
debug
|
|
}));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Lightformer.js
|
|
var React107 = __toESM(require_react());
|
|
var Lightformer = React107.forwardRef(({
|
|
light,
|
|
args,
|
|
map: map2,
|
|
toneMapped = false,
|
|
color = "white",
|
|
form: Form = "rect",
|
|
intensity = 1,
|
|
scale: scale5 = 1,
|
|
target: target2 = [0, 0, 0],
|
|
children,
|
|
...props
|
|
}, forwardRef82) => {
|
|
const ref = React107.useRef(null);
|
|
React107.useImperativeHandle(forwardRef82, () => ref.current, []);
|
|
React107.useLayoutEffect(() => {
|
|
if (!children && !props.material) {
|
|
applyProps(ref.current.material, {
|
|
color
|
|
});
|
|
ref.current.material.color.multiplyScalar(intensity);
|
|
}
|
|
}, [color, intensity, children, props.material]);
|
|
React107.useLayoutEffect(() => {
|
|
if (!props.rotation) ref.current.quaternion.identity();
|
|
if (target2 && !props.rotation) {
|
|
"boolean" === typeof target2 ? ref.current.lookAt(0, 0, 0) : ref.current.lookAt(Array.isArray(target2) ? new Vector3(...target2) : target2);
|
|
}
|
|
}, [target2, props.rotation]);
|
|
scale5 = Array.isArray(scale5) && scale5.length === 2 ? [scale5[0], scale5[1], 1] : scale5;
|
|
return React107.createElement("mesh", _extends({
|
|
ref,
|
|
scale: scale5
|
|
}, props), Form === "circle" ? React107.createElement("ringGeometry", {
|
|
args: args ? args : [0, 0.5, 64]
|
|
}) : Form === "ring" ? React107.createElement("ringGeometry", {
|
|
args: args ? args : [0.25, 0.5, 64]
|
|
}) : Form === "rect" || Form === "plane" ? React107.createElement("planeGeometry", {
|
|
args: args ? args : [1, 1]
|
|
}) : Form === "box" ? React107.createElement("boxGeometry", {
|
|
args: args ? args : [1, 1, 1]
|
|
}) : React107.createElement(Form, {
|
|
args
|
|
}), children ? children : React107.createElement("meshBasicMaterial", {
|
|
toneMapped,
|
|
map: map2,
|
|
side: DoubleSide
|
|
}), light && React107.createElement("pointLight", _extends({
|
|
castShadow: true
|
|
}, light)));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Sky.js
|
|
var React108 = __toESM(require_react());
|
|
function calcPosFromAngles(inclination, azimuth, vector = new Vector3()) {
|
|
const theta = Math.PI * (inclination - 0.5);
|
|
const phi = 2 * Math.PI * (azimuth - 0.5);
|
|
vector.x = Math.cos(phi);
|
|
vector.y = Math.sin(theta);
|
|
vector.z = Math.sin(phi);
|
|
return vector;
|
|
}
|
|
var Sky2 = React108.forwardRef(({
|
|
inclination = 0.6,
|
|
azimuth = 0.1,
|
|
distance: distance3 = 1e3,
|
|
mieCoefficient = 5e-3,
|
|
mieDirectionalG = 0.8,
|
|
rayleigh = 0.5,
|
|
turbidity = 10,
|
|
sunPosition = calcPosFromAngles(inclination, azimuth),
|
|
...props
|
|
}, ref) => {
|
|
const scale5 = React108.useMemo(() => new Vector3().setScalar(distance3), [distance3]);
|
|
const [sky] = React108.useState(() => new Sky());
|
|
return React108.createElement("primitive", _extends({
|
|
object: sky,
|
|
ref,
|
|
"material-uniforms-mieCoefficient-value": mieCoefficient,
|
|
"material-uniforms-mieDirectionalG-value": mieDirectionalG,
|
|
"material-uniforms-rayleigh-value": rayleigh,
|
|
"material-uniforms-sunPosition-value": sunPosition,
|
|
"material-uniforms-turbidity-value": turbidity,
|
|
scale: scale5
|
|
}, props));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Stars.js
|
|
var React109 = __toESM(require_react());
|
|
var StarfieldMaterial = class extends ShaderMaterial {
|
|
constructor() {
|
|
super({
|
|
uniforms: {
|
|
time: {
|
|
value: 0
|
|
},
|
|
fade: {
|
|
value: 1
|
|
}
|
|
},
|
|
vertexShader: (
|
|
/* glsl */
|
|
`
|
|
uniform float time;
|
|
attribute float size;
|
|
varying vec3 vColor;
|
|
void main() {
|
|
vColor = color;
|
|
vec4 mvPosition = modelViewMatrix * vec4(position, 0.5);
|
|
gl_PointSize = size * (30.0 / -mvPosition.z) * (3.0 + sin(time + 100.0));
|
|
gl_Position = projectionMatrix * mvPosition;
|
|
}`
|
|
),
|
|
fragmentShader: (
|
|
/* glsl */
|
|
`
|
|
uniform sampler2D pointTexture;
|
|
uniform float fade;
|
|
varying vec3 vColor;
|
|
void main() {
|
|
float opacity = 1.0;
|
|
if (fade == 1.0) {
|
|
float d = distance(gl_PointCoord, vec2(0.5, 0.5));
|
|
opacity = 1.0 / (1.0 + exp(16.0 * (d - 0.25)));
|
|
}
|
|
gl_FragColor = vec4(vColor, opacity);
|
|
|
|
#include <tonemapping_fragment>
|
|
#include <${version >= 154 ? "colorspace_fragment" : "encodings_fragment"}>
|
|
}`
|
|
)
|
|
});
|
|
}
|
|
};
|
|
var genStar = (r2) => {
|
|
return new Vector3().setFromSpherical(new Spherical(r2, Math.acos(1 - Math.random() * 2), Math.random() * 2 * Math.PI));
|
|
};
|
|
var Stars = React109.forwardRef(({
|
|
radius = 100,
|
|
depth = 50,
|
|
count = 5e3,
|
|
saturation = 0,
|
|
factor = 4,
|
|
fade: fade2 = false,
|
|
speed = 1
|
|
}, ref) => {
|
|
const material = React109.useRef(null);
|
|
const [position2, color, size] = React109.useMemo(() => {
|
|
const positions = [];
|
|
const colors2 = [];
|
|
const sizes = Array.from({
|
|
length: count
|
|
}, () => (0.5 + 0.5 * Math.random()) * factor);
|
|
const color2 = new Color();
|
|
let r2 = radius + depth;
|
|
const increment = depth / count;
|
|
for (let i3 = 0; i3 < count; i3++) {
|
|
r2 -= increment * Math.random();
|
|
positions.push(...genStar(r2).toArray());
|
|
color2.setHSL(i3 / count, saturation, 0.9);
|
|
colors2.push(color2.r, color2.g, color2.b);
|
|
}
|
|
return [new Float32Array(positions), new Float32Array(colors2), new Float32Array(sizes)];
|
|
}, [count, depth, factor, radius, saturation]);
|
|
useFrame((state) => material.current && (material.current.uniforms.time.value = state.clock.elapsedTime * speed));
|
|
const [starfieldMaterial] = React109.useState(() => new StarfieldMaterial());
|
|
return React109.createElement("points", {
|
|
ref
|
|
}, React109.createElement("bufferGeometry", null, React109.createElement("bufferAttribute", {
|
|
attach: "attributes-position",
|
|
args: [position2, 3]
|
|
}), React109.createElement("bufferAttribute", {
|
|
attach: "attributes-color",
|
|
args: [color, 3]
|
|
}), React109.createElement("bufferAttribute", {
|
|
attach: "attributes-size",
|
|
args: [size, 1]
|
|
})), React109.createElement("primitive", {
|
|
ref: material,
|
|
object: starfieldMaterial,
|
|
attach: "material",
|
|
blending: AdditiveBlending,
|
|
"uniforms-fade-value": fade2,
|
|
depthWrite: false,
|
|
transparent: true,
|
|
vertexColors: true
|
|
}));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Cloud.js
|
|
var React110 = __toESM(require_react());
|
|
var CLOUD_URL = "https://rawcdn.githack.com/pmndrs/drei-assets/9225a9f1fbd449d9411125c2f419b843d0308c9f/cloud.png";
|
|
var parentMatrix2 = new Matrix4();
|
|
var translation2 = new Vector3();
|
|
var rotation2 = new Quaternion();
|
|
var cpos = new Vector3();
|
|
var cquat = new Quaternion();
|
|
var scale4 = new Vector3();
|
|
var context7 = React110.createContext(null);
|
|
var Clouds = React110.forwardRef(({
|
|
children,
|
|
material = MeshLambertMaterial,
|
|
texture = CLOUD_URL,
|
|
range,
|
|
limit = 200,
|
|
frustumCulled,
|
|
...props
|
|
}, fref) => {
|
|
var _image$width, _image$height;
|
|
const CloudMaterial = React110.useMemo(() => {
|
|
return class extends material {
|
|
constructor() {
|
|
super();
|
|
const opaque_fragment2 = parseInt(REVISION.replace(/\D+/g, "")) >= 154 ? "opaque_fragment" : "output_fragment";
|
|
this.onBeforeCompile = (shader) => {
|
|
shader.vertexShader = `attribute float cloudOpacity;
|
|
varying float vOpacity;
|
|
` + shader.vertexShader.replace("#include <fog_vertex>", `#include <fog_vertex>
|
|
vOpacity = cloudOpacity;
|
|
`);
|
|
shader.fragmentShader = `varying float vOpacity;
|
|
` + shader.fragmentShader.replace(`#include <${opaque_fragment2}>`, `#include <${opaque_fragment2}>
|
|
gl_FragColor = vec4(outgoingLight, diffuseColor.a * vOpacity);
|
|
`);
|
|
};
|
|
}
|
|
};
|
|
}, [material]);
|
|
extend({
|
|
CloudMaterial
|
|
});
|
|
const instance = React110.useRef(null);
|
|
const clouds = React110.useRef([]);
|
|
const opacities = React110.useMemo(() => new Float32Array(Array.from({
|
|
length: limit
|
|
}, () => 1)), [limit]);
|
|
const colors2 = React110.useMemo(() => new Float32Array(Array.from({
|
|
length: limit
|
|
}, () => [1, 1, 1]).flat()), [limit]);
|
|
const cloudTexture = useTexture(texture);
|
|
let t2 = 0;
|
|
let index2 = 0;
|
|
let config;
|
|
const qat = new Quaternion();
|
|
const dir = new Vector3(0, 0, 1);
|
|
const pos = new Vector3();
|
|
useFrame((state, delta) => {
|
|
t2 = state.clock.elapsedTime;
|
|
parentMatrix2.copy(instance.current.matrixWorld).invert();
|
|
state.camera.matrixWorld.decompose(cpos, cquat, scale4);
|
|
for (index2 = 0; index2 < clouds.current.length; index2++) {
|
|
config = clouds.current[index2];
|
|
config.ref.current.matrixWorld.decompose(translation2, rotation2, scale4);
|
|
translation2.add(pos.copy(config.position).applyQuaternion(rotation2).multiply(scale4));
|
|
rotation2.copy(cquat).multiply(qat.setFromAxisAngle(dir, config.rotation += delta * config.rotationFactor));
|
|
scale4.multiplyScalar(config.volume + (1 + Math.sin(t2 * config.density * config.speed)) / 2 * config.growth);
|
|
config.matrix.compose(translation2, rotation2, scale4).premultiply(parentMatrix2);
|
|
config.dist = translation2.distanceTo(cpos);
|
|
}
|
|
clouds.current.sort((a5, b) => b.dist - a5.dist);
|
|
for (index2 = 0; index2 < clouds.current.length; index2++) {
|
|
config = clouds.current[index2];
|
|
opacities[index2] = config.opacity * (config.dist < config.fade - 1 ? config.dist / config.fade : 1);
|
|
instance.current.setMatrixAt(index2, config.matrix);
|
|
instance.current.setColorAt(index2, config.color);
|
|
}
|
|
instance.current.geometry.attributes.cloudOpacity.needsUpdate = true;
|
|
instance.current.instanceMatrix.needsUpdate = true;
|
|
if (instance.current.instanceColor) instance.current.instanceColor.needsUpdate = true;
|
|
});
|
|
React110.useLayoutEffect(() => {
|
|
const count = Math.min(limit, range !== void 0 ? range : limit, clouds.current.length);
|
|
instance.current.count = count;
|
|
setUpdateRange(instance.current.instanceMatrix, {
|
|
start: 0,
|
|
count: count * 16
|
|
});
|
|
if (instance.current.instanceColor) {
|
|
setUpdateRange(instance.current.instanceColor, {
|
|
start: 0,
|
|
count: count * 3
|
|
});
|
|
}
|
|
setUpdateRange(instance.current.geometry.attributes.cloudOpacity, {
|
|
start: 0,
|
|
count
|
|
});
|
|
});
|
|
let imageBounds = [(_image$width = cloudTexture.image.width) !== null && _image$width !== void 0 ? _image$width : 1, (_image$height = cloudTexture.image.height) !== null && _image$height !== void 0 ? _image$height : 1];
|
|
const max = Math.max(imageBounds[0], imageBounds[1]);
|
|
imageBounds = [imageBounds[0] / max, imageBounds[1] / max];
|
|
return React110.createElement("group", _extends({
|
|
ref: fref
|
|
}, props), React110.createElement(context7.Provider, {
|
|
value: clouds
|
|
}, children, React110.createElement("instancedMesh", {
|
|
matrixAutoUpdate: false,
|
|
ref: instance,
|
|
args: [null, null, limit],
|
|
frustumCulled
|
|
}, React110.createElement("instancedBufferAttribute", {
|
|
usage: DynamicDrawUsage,
|
|
attach: "instanceColor",
|
|
args: [colors2, 3]
|
|
}), React110.createElement("planeGeometry", {
|
|
args: [...imageBounds]
|
|
}, React110.createElement("instancedBufferAttribute", {
|
|
usage: DynamicDrawUsage,
|
|
attach: "attributes-cloudOpacity",
|
|
args: [opacities, 1]
|
|
})), React110.createElement("cloudMaterial", {
|
|
key: material.name,
|
|
map: cloudTexture,
|
|
transparent: true,
|
|
depthWrite: false
|
|
}))));
|
|
});
|
|
var CloudInstance = React110.forwardRef(({
|
|
opacity = 1,
|
|
speed = 0,
|
|
bounds = [5, 1, 1],
|
|
segments = 20,
|
|
color = "#ffffff",
|
|
fade: fade2 = 10,
|
|
volume = 6,
|
|
smallestVolume = 0.25,
|
|
distribute = null,
|
|
growth = 4,
|
|
concentrate = "inside",
|
|
seed: seed3 = Math.random(),
|
|
...props
|
|
}, fref) => {
|
|
function random() {
|
|
const x = Math.sin(seed3++) * 1e4;
|
|
return x - Math.floor(x);
|
|
}
|
|
const parent = React110.useContext(context7);
|
|
const ref = React110.useRef(null);
|
|
const uuid = React110.useId();
|
|
const clouds = React110.useMemo(() => {
|
|
return [...new Array(segments)].map((_, index2) => ({
|
|
segments,
|
|
bounds: new Vector3(1, 1, 1),
|
|
position: new Vector3(),
|
|
uuid,
|
|
index: index2,
|
|
ref,
|
|
dist: 0,
|
|
matrix: new Matrix4(),
|
|
color: new Color(),
|
|
rotation: index2 * (Math.PI / segments)
|
|
}));
|
|
}, [segments, uuid]);
|
|
React110.useLayoutEffect(() => {
|
|
clouds.forEach((cloud, index2) => {
|
|
applyProps(cloud, {
|
|
volume,
|
|
color,
|
|
speed,
|
|
growth,
|
|
opacity,
|
|
fade: fade2,
|
|
bounds,
|
|
density: Math.max(0.5, random()),
|
|
rotationFactor: Math.max(0.2, 0.5 * random()) * speed
|
|
});
|
|
const distributed = distribute == null ? void 0 : distribute(cloud, index2);
|
|
if (distributed || segments > 1) {
|
|
var _distributed$point;
|
|
cloud.position.copy(cloud.bounds).multiply((_distributed$point = distributed == null ? void 0 : distributed.point) !== null && _distributed$point !== void 0 ? _distributed$point : {
|
|
x: random() * 2 - 1,
|
|
y: random() * 2 - 1,
|
|
z: random() * 2 - 1
|
|
});
|
|
}
|
|
const xDiff = Math.abs(cloud.position.x);
|
|
const yDiff = Math.abs(cloud.position.y);
|
|
const zDiff = Math.abs(cloud.position.z);
|
|
const max = Math.max(xDiff, yDiff, zDiff);
|
|
cloud.length = 1;
|
|
if (xDiff === max) cloud.length -= xDiff / cloud.bounds.x;
|
|
if (yDiff === max) cloud.length -= yDiff / cloud.bounds.y;
|
|
if (zDiff === max) cloud.length -= zDiff / cloud.bounds.z;
|
|
cloud.volume = ((distributed == null ? void 0 : distributed.volume) !== void 0 ? distributed.volume : Math.max(Math.max(0, smallestVolume), concentrate === "random" ? random() : concentrate === "inside" ? cloud.length : 1 - cloud.length)) * volume;
|
|
});
|
|
}, [concentrate, bounds, fade2, color, opacity, growth, volume, seed3, segments, speed]);
|
|
React110.useLayoutEffect(() => {
|
|
const temp5 = clouds;
|
|
parent.current = [...parent.current, ...temp5];
|
|
return () => {
|
|
parent.current = parent.current.filter((item) => item.uuid !== uuid);
|
|
};
|
|
}, [clouds]);
|
|
React110.useImperativeHandle(fref, () => ref.current, []);
|
|
return React110.createElement("group", _extends({
|
|
ref
|
|
}, props));
|
|
});
|
|
var Cloud = React110.forwardRef((props, fref) => {
|
|
const parent = React110.useContext(context7);
|
|
if (parent) return React110.createElement(CloudInstance, _extends({
|
|
ref: fref
|
|
}, props));
|
|
return React110.createElement(Clouds, null, React110.createElement(CloudInstance, _extends({
|
|
ref: fref
|
|
}, props)));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Sparkles.js
|
|
var React111 = __toESM(require_react());
|
|
var SparklesImplMaterial = class extends ShaderMaterial {
|
|
constructor() {
|
|
super({
|
|
uniforms: {
|
|
time: {
|
|
value: 0
|
|
},
|
|
pixelRatio: {
|
|
value: 1
|
|
}
|
|
},
|
|
vertexShader: (
|
|
/* glsl */
|
|
`
|
|
uniform float pixelRatio;
|
|
uniform float time;
|
|
attribute float size;
|
|
attribute float speed;
|
|
attribute float opacity;
|
|
attribute vec3 noise;
|
|
attribute vec3 color;
|
|
varying vec3 vColor;
|
|
varying float vOpacity;
|
|
|
|
void main() {
|
|
vec4 modelPosition = modelMatrix * vec4(position, 1.0);
|
|
modelPosition.y += sin(time * speed + modelPosition.x * noise.x * 100.0) * 0.2;
|
|
modelPosition.z += cos(time * speed + modelPosition.x * noise.y * 100.0) * 0.2;
|
|
modelPosition.x += cos(time * speed + modelPosition.x * noise.z * 100.0) * 0.2;
|
|
vec4 viewPosition = viewMatrix * modelPosition;
|
|
vec4 projectionPostion = projectionMatrix * viewPosition;
|
|
gl_Position = projectionPostion;
|
|
gl_PointSize = size * 25. * pixelRatio;
|
|
gl_PointSize *= (1.0 / - viewPosition.z);
|
|
vColor = color;
|
|
vOpacity = opacity;
|
|
}
|
|
`
|
|
),
|
|
fragmentShader: (
|
|
/* glsl */
|
|
`
|
|
varying vec3 vColor;
|
|
varying float vOpacity;
|
|
void main() {
|
|
float distanceToCenter = distance(gl_PointCoord, vec2(0.5));
|
|
float strength = 0.05 / distanceToCenter - 0.1;
|
|
gl_FragColor = vec4(vColor, strength * vOpacity);
|
|
#include <tonemapping_fragment>
|
|
#include <${version >= 154 ? "colorspace_fragment" : "encodings_fragment"}>
|
|
}
|
|
`
|
|
)
|
|
});
|
|
}
|
|
get time() {
|
|
return this.uniforms.time.value;
|
|
}
|
|
set time(value) {
|
|
this.uniforms.time.value = value;
|
|
}
|
|
get pixelRatio() {
|
|
return this.uniforms.pixelRatio.value;
|
|
}
|
|
set pixelRatio(value) {
|
|
this.uniforms.pixelRatio.value = value;
|
|
}
|
|
};
|
|
var isFloat32Array = (def) => def && def.constructor === Float32Array;
|
|
var expandColor = (v5) => [v5.r, v5.g, v5.b];
|
|
var isVector = (v5) => v5 instanceof Vector2 || v5 instanceof Vector3 || v5 instanceof Vector4;
|
|
var normalizeVector = (v5) => {
|
|
if (Array.isArray(v5)) return v5;
|
|
else if (isVector(v5)) return v5.toArray();
|
|
return [v5, v5, v5];
|
|
};
|
|
function usePropAsIsOrAsAttribute(count, prop, setDefault) {
|
|
return React111.useMemo(() => {
|
|
if (prop !== void 0) {
|
|
if (isFloat32Array(prop)) {
|
|
return prop;
|
|
} else {
|
|
if (prop instanceof Color) {
|
|
const a5 = Array.from({
|
|
length: count * 3
|
|
}, () => expandColor(prop)).flat();
|
|
return Float32Array.from(a5);
|
|
} else if (isVector(prop) || Array.isArray(prop)) {
|
|
const a5 = Array.from({
|
|
length: count * 3
|
|
}, () => normalizeVector(prop)).flat();
|
|
return Float32Array.from(a5);
|
|
}
|
|
return Float32Array.from({
|
|
length: count
|
|
}, () => prop);
|
|
}
|
|
}
|
|
return Float32Array.from({
|
|
length: count
|
|
}, setDefault);
|
|
}, [prop]);
|
|
}
|
|
var Sparkles = React111.forwardRef(({
|
|
noise: noise2 = 1,
|
|
count = 100,
|
|
speed = 1,
|
|
opacity = 1,
|
|
scale: scale5 = 1,
|
|
size,
|
|
color,
|
|
children,
|
|
...props
|
|
}, forwardRef82) => {
|
|
React111.useMemo(() => extend({
|
|
SparklesImplMaterial
|
|
}), []);
|
|
const ref = React111.useRef(null);
|
|
const dpr = useThree((state) => state.viewport.dpr);
|
|
const _scale = normalizeVector(scale5);
|
|
const positions = React111.useMemo(() => Float32Array.from(Array.from({
|
|
length: count
|
|
}, () => _scale.map(MathUtils.randFloatSpread)).flat()), [count, ..._scale]);
|
|
const sizes = usePropAsIsOrAsAttribute(count, size, Math.random);
|
|
const opacities = usePropAsIsOrAsAttribute(count, opacity);
|
|
const speeds = usePropAsIsOrAsAttribute(count, speed);
|
|
const noises = usePropAsIsOrAsAttribute(count * 3, noise2);
|
|
const colors2 = usePropAsIsOrAsAttribute(color === void 0 ? count * 3 : count, !isFloat32Array(color) ? new Color(color) : color, () => 1);
|
|
useFrame((state) => {
|
|
if (ref.current && ref.current.material) ref.current.material.time = state.clock.elapsedTime;
|
|
});
|
|
React111.useImperativeHandle(forwardRef82, () => ref.current, []);
|
|
return React111.createElement("points", _extends({
|
|
key: `particle-${count}-${JSON.stringify(scale5)}`
|
|
}, props, {
|
|
ref
|
|
}), React111.createElement("bufferGeometry", null, React111.createElement("bufferAttribute", {
|
|
attach: "attributes-position",
|
|
args: [positions, 3]
|
|
}), React111.createElement("bufferAttribute", {
|
|
attach: "attributes-size",
|
|
args: [sizes, 1]
|
|
}), React111.createElement("bufferAttribute", {
|
|
attach: "attributes-opacity",
|
|
args: [opacities, 1]
|
|
}), React111.createElement("bufferAttribute", {
|
|
attach: "attributes-speed",
|
|
args: [speeds, 1]
|
|
}), React111.createElement("bufferAttribute", {
|
|
attach: "attributes-color",
|
|
args: [colors2, 3]
|
|
}), React111.createElement("bufferAttribute", {
|
|
attach: "attributes-noise",
|
|
args: [noises, 3]
|
|
})), children ? children : React111.createElement("sparklesImplMaterial", {
|
|
transparent: true,
|
|
pixelRatio: dpr,
|
|
depthWrite: false
|
|
}));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/MatcapTexture.js
|
|
var React112 = __toESM(require_react());
|
|
function getFormatString(format) {
|
|
switch (format) {
|
|
case 64:
|
|
return "-64px";
|
|
case 128:
|
|
return "-128px";
|
|
case 256:
|
|
return "-256px";
|
|
case 512:
|
|
return "-512px";
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
var LIST_URL = "https://cdn.jsdelivr.net/gh/pmndrs/drei-assets@master/matcaps.json";
|
|
var MATCAP_ROOT = "https://rawcdn.githack.com/emmelleppi/matcaps/9b36ccaaf0a24881a39062d05566c9e92be4aa0d";
|
|
function useMatcapTexture(id = 0, format = 1024, onLoad) {
|
|
const matcapList = suspend(() => fetch(LIST_URL).then((res) => res.json()), ["matcapList"]);
|
|
const DEFAULT_MATCAP = matcapList[0];
|
|
const numTot = React112.useMemo(() => Object.keys(matcapList).length, []);
|
|
const fileHash = React112.useMemo(() => {
|
|
if (typeof id === "string") {
|
|
return id;
|
|
} else if (typeof id === "number") {
|
|
return matcapList[id];
|
|
}
|
|
return null;
|
|
}, [id]);
|
|
const fileName = `${fileHash || DEFAULT_MATCAP}${getFormatString(format)}.png`;
|
|
const url = `${MATCAP_ROOT}/${format}/${fileName}`;
|
|
const matcapTexture = useTexture(url, onLoad);
|
|
return [matcapTexture, url, numTot];
|
|
}
|
|
var MatcapTexture = ({
|
|
children,
|
|
id,
|
|
format,
|
|
onLoad
|
|
}) => {
|
|
const texture = useMatcapTexture(id, format, onLoad);
|
|
return React112.createElement(React112.Fragment, null, children == null ? void 0 : children(texture));
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/NormalTexture.js
|
|
var React113 = __toESM(require_react());
|
|
var NORMAL_ROOT = "https://rawcdn.githack.com/pmndrs/drei-assets/7a3104997e1576f83472829815b00880d88b32fb";
|
|
var LIST_URL2 = "https://cdn.jsdelivr.net/gh/pmndrs/drei-assets@master/normals/normals.json";
|
|
function useNormalTexture(id = 0, settings = {}, onLoad) {
|
|
const {
|
|
repeat: repeat2 = [1, 1],
|
|
anisotropy = 1,
|
|
offset = [0, 0]
|
|
} = settings;
|
|
const normalsList = suspend(() => fetch(LIST_URL2).then((res) => res.json()), ["normalsList"]);
|
|
const numTot = React113.useMemo(() => Object.keys(normalsList).length, []);
|
|
const DEFAULT_NORMAL = normalsList[0];
|
|
const imageName = normalsList[id] || DEFAULT_NORMAL;
|
|
const url = `${NORMAL_ROOT}/normals/${imageName}`;
|
|
const normalTexture = useTexture(url, onLoad);
|
|
React113.useLayoutEffect(() => {
|
|
if (!normalTexture) return;
|
|
normalTexture.wrapS = normalTexture.wrapT = RepeatWrapping;
|
|
normalTexture.repeat = new Vector2(repeat2[0], repeat2[1]);
|
|
normalTexture.offset = new Vector2(offset[0], offset[1]);
|
|
normalTexture.anisotropy = anisotropy;
|
|
}, [normalTexture, anisotropy, repeat2, offset]);
|
|
return [normalTexture, url, numTot];
|
|
}
|
|
var NormalTexture = ({
|
|
children,
|
|
id,
|
|
onLoad,
|
|
...settings
|
|
}) => {
|
|
const ret = useNormalTexture(id, settings, onLoad);
|
|
return React113.createElement(React113.Fragment, null, children == null ? void 0 : children(ret));
|
|
};
|
|
|
|
// node_modules/@react-three/drei/core/Wireframe.js
|
|
var React115 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/materials/WireframeMaterial.js
|
|
var React114 = __toESM(require_react());
|
|
var WireframeMaterialShaders = {
|
|
uniforms: {
|
|
strokeOpacity: 1,
|
|
fillOpacity: 0.25,
|
|
fillMix: 0,
|
|
thickness: 0.05,
|
|
colorBackfaces: false,
|
|
dashInvert: true,
|
|
dash: false,
|
|
dashRepeats: 4,
|
|
dashLength: 0.5,
|
|
squeeze: false,
|
|
squeezeMin: 0.2,
|
|
squeezeMax: 1,
|
|
stroke: new Color("#ff0000"),
|
|
backfaceStroke: new Color("#0000ff"),
|
|
fill: new Color("#00ff00")
|
|
},
|
|
vertex: (
|
|
/* glsl */
|
|
`
|
|
attribute vec3 barycentric;
|
|
|
|
varying vec3 v_edges_Barycentric;
|
|
varying vec3 v_edges_Position;
|
|
|
|
void initWireframe() {
|
|
v_edges_Barycentric = barycentric;
|
|
v_edges_Position = position.xyz;
|
|
}
|
|
`
|
|
),
|
|
fragment: (
|
|
/* glsl */
|
|
`
|
|
#ifndef PI
|
|
#define PI 3.1415926535897932384626433832795
|
|
#endif
|
|
|
|
varying vec3 v_edges_Barycentric;
|
|
varying vec3 v_edges_Position;
|
|
|
|
uniform float strokeOpacity;
|
|
uniform float fillOpacity;
|
|
uniform float fillMix;
|
|
uniform float thickness;
|
|
uniform bool colorBackfaces;
|
|
|
|
// Dash
|
|
uniform bool dashInvert;
|
|
uniform bool dash;
|
|
uniform bool dashOnly;
|
|
uniform float dashRepeats;
|
|
uniform float dashLength;
|
|
|
|
// Squeeze
|
|
uniform bool squeeze;
|
|
uniform float squeezeMin;
|
|
uniform float squeezeMax;
|
|
|
|
// Colors
|
|
uniform vec3 stroke;
|
|
uniform vec3 backfaceStroke;
|
|
uniform vec3 fill;
|
|
|
|
// This is like
|
|
float wireframe_aastep(float threshold, float dist) {
|
|
float afwidth = fwidth(dist) * 0.5;
|
|
return smoothstep(threshold - afwidth, threshold + afwidth, dist);
|
|
}
|
|
|
|
float wireframe_map(float value, float min1, float max1, float min2, float max2) {
|
|
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
|
|
}
|
|
|
|
float getWireframe() {
|
|
vec3 barycentric = v_edges_Barycentric;
|
|
|
|
// Distance from center of each triangle to its edges.
|
|
float d = min(min(barycentric.x, barycentric.y), barycentric.z);
|
|
|
|
// for dashed rendering, we can use this to get the 0 .. 1 value of the line length
|
|
float positionAlong = max(barycentric.x, barycentric.y);
|
|
if (barycentric.y < barycentric.x && barycentric.y < barycentric.z) {
|
|
positionAlong = 1.0 - positionAlong;
|
|
}
|
|
|
|
// the thickness of the stroke
|
|
float computedThickness = wireframe_map(thickness, 0.0, 1.0, 0.0, 0.34);
|
|
|
|
// if we want to shrink the thickness toward the center of the line segment
|
|
if (squeeze) {
|
|
computedThickness *= mix(squeezeMin, squeezeMax, (1.0 - sin(positionAlong * PI)));
|
|
}
|
|
|
|
// Create dash pattern
|
|
if (dash) {
|
|
// here we offset the stroke position depending on whether it
|
|
// should overlap or not
|
|
float offset = 1.0 / dashRepeats * dashLength / 2.0;
|
|
if (!dashInvert) {
|
|
offset += 1.0 / dashRepeats / 2.0;
|
|
}
|
|
|
|
// if we should animate the dash or not
|
|
// if (dashAnimate) {
|
|
// offset += time * 0.22;
|
|
// }
|
|
|
|
// create the repeating dash pattern
|
|
float pattern = fract((positionAlong + offset) * dashRepeats);
|
|
computedThickness *= 1.0 - wireframe_aastep(dashLength, pattern);
|
|
}
|
|
|
|
// compute the anti-aliased stroke edge
|
|
float edge = 1.0 - wireframe_aastep(computedThickness, d);
|
|
|
|
return edge;
|
|
}
|
|
`
|
|
)
|
|
};
|
|
var WireframeMaterial = shaderMaterial(WireframeMaterialShaders.uniforms, WireframeMaterialShaders.vertex + /* glsl */
|
|
`
|
|
void main() {
|
|
initWireframe();
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
}
|
|
`, WireframeMaterialShaders.fragment + /* glsl */
|
|
`
|
|
void main () {
|
|
// Compute color
|
|
|
|
float edge = getWireframe();
|
|
vec4 colorStroke = vec4(stroke, edge);
|
|
|
|
#ifdef FLIP_SIDED
|
|
colorStroke.rgb = backfaceStroke;
|
|
#endif
|
|
|
|
vec4 colorFill = vec4(fill, fillOpacity);
|
|
vec4 outColor = mix(colorFill, colorStroke, edge * strokeOpacity);
|
|
|
|
gl_FragColor = outColor;
|
|
}
|
|
`);
|
|
function setWireframeOverride(material, uniforms) {
|
|
material.onBeforeCompile = (shader) => {
|
|
shader.uniforms = {
|
|
...shader.uniforms,
|
|
...uniforms
|
|
};
|
|
shader.vertexShader = shader.vertexShader.replace("void main() {", `
|
|
${WireframeMaterialShaders.vertex}
|
|
void main() {
|
|
initWireframe();
|
|
`);
|
|
shader.fragmentShader = shader.fragmentShader.replace("void main() {", `
|
|
${WireframeMaterialShaders.fragment}
|
|
void main() {
|
|
`);
|
|
shader.fragmentShader = shader.fragmentShader.replace(
|
|
"#include <color_fragment>",
|
|
/* glsl */
|
|
`
|
|
#include <color_fragment>
|
|
float edge = getWireframe();
|
|
vec4 colorStroke = vec4(stroke, edge);
|
|
#ifdef FLIP_SIDED
|
|
colorStroke.rgb = backfaceStroke;
|
|
#endif
|
|
vec4 colorFill = vec4(mix(diffuseColor.rgb, fill, fillMix), mix(diffuseColor.a, fillOpacity, fillMix));
|
|
vec4 outColor = mix(colorFill, colorStroke, edge * strokeOpacity);
|
|
|
|
diffuseColor.rgb = outColor.rgb;
|
|
diffuseColor.a *= outColor.a;
|
|
`
|
|
);
|
|
};
|
|
material.side = DoubleSide;
|
|
material.transparent = true;
|
|
}
|
|
function useWireframeUniforms(uniforms, props) {
|
|
React114.useEffect(() => {
|
|
var _props$fillOpacity;
|
|
return void (uniforms.fillOpacity.value = (_props$fillOpacity = props.fillOpacity) !== null && _props$fillOpacity !== void 0 ? _props$fillOpacity : uniforms.fillOpacity.value);
|
|
}, [props.fillOpacity]);
|
|
React114.useEffect(() => {
|
|
var _props$fillMix;
|
|
return void (uniforms.fillMix.value = (_props$fillMix = props.fillMix) !== null && _props$fillMix !== void 0 ? _props$fillMix : uniforms.fillMix.value);
|
|
}, [props.fillMix]);
|
|
React114.useEffect(() => {
|
|
var _props$strokeOpacity;
|
|
return void (uniforms.strokeOpacity.value = (_props$strokeOpacity = props.strokeOpacity) !== null && _props$strokeOpacity !== void 0 ? _props$strokeOpacity : uniforms.strokeOpacity.value);
|
|
}, [props.strokeOpacity]);
|
|
React114.useEffect(() => {
|
|
var _props$thickness;
|
|
return void (uniforms.thickness.value = (_props$thickness = props.thickness) !== null && _props$thickness !== void 0 ? _props$thickness : uniforms.thickness.value);
|
|
}, [props.thickness]);
|
|
React114.useEffect(() => void (uniforms.colorBackfaces.value = !!props.colorBackfaces), [props.colorBackfaces]);
|
|
React114.useEffect(() => void (uniforms.dash.value = !!props.dash), [props.dash]);
|
|
React114.useEffect(() => void (uniforms.dashInvert.value = !!props.dashInvert), [props.dashInvert]);
|
|
React114.useEffect(() => {
|
|
var _props$dashRepeats;
|
|
return void (uniforms.dashRepeats.value = (_props$dashRepeats = props.dashRepeats) !== null && _props$dashRepeats !== void 0 ? _props$dashRepeats : uniforms.dashRepeats.value);
|
|
}, [props.dashRepeats]);
|
|
React114.useEffect(() => {
|
|
var _props$dashLength;
|
|
return void (uniforms.dashLength.value = (_props$dashLength = props.dashLength) !== null && _props$dashLength !== void 0 ? _props$dashLength : uniforms.dashLength.value);
|
|
}, [props.dashLength]);
|
|
React114.useEffect(() => void (uniforms.squeeze.value = !!props.squeeze), [props.squeeze]);
|
|
React114.useEffect(() => {
|
|
var _props$squeezeMin;
|
|
return void (uniforms.squeezeMin.value = (_props$squeezeMin = props.squeezeMin) !== null && _props$squeezeMin !== void 0 ? _props$squeezeMin : uniforms.squeezeMin.value);
|
|
}, [props.squeezeMin]);
|
|
React114.useEffect(() => {
|
|
var _props$squeezeMax;
|
|
return void (uniforms.squeezeMax.value = (_props$squeezeMax = props.squeezeMax) !== null && _props$squeezeMax !== void 0 ? _props$squeezeMax : uniforms.squeezeMax.value);
|
|
}, [props.squeezeMax]);
|
|
React114.useEffect(() => void (uniforms.stroke.value = props.stroke ? new Color(props.stroke) : uniforms.stroke.value), [props.stroke]);
|
|
React114.useEffect(() => void (uniforms.fill.value = props.fill ? new Color(props.fill) : uniforms.fill.value), [props.fill]);
|
|
React114.useEffect(() => void (uniforms.backfaceStroke.value = props.backfaceStroke ? new Color(props.backfaceStroke) : uniforms.backfaceStroke.value), [props.backfaceStroke]);
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/Wireframe.js
|
|
function isWithGeometry(object) {
|
|
return !!(object != null && object.geometry);
|
|
}
|
|
function isGeometry2(object) {
|
|
return !!(object != null && object.isBufferGeometry);
|
|
}
|
|
function isRefObject2(object) {
|
|
return !!(object != null && object.current);
|
|
}
|
|
function isRef2(object) {
|
|
return (object == null ? void 0 : object.current) !== void 0;
|
|
}
|
|
function isWireframeGeometry(geometry3) {
|
|
return geometry3.type === "WireframeGeometry";
|
|
}
|
|
function getUniforms() {
|
|
const u = {};
|
|
for (const key in WireframeMaterialShaders.uniforms) {
|
|
u[key] = {
|
|
value: WireframeMaterialShaders.uniforms[key]
|
|
};
|
|
}
|
|
return u;
|
|
}
|
|
function getBarycentricCoordinates(geometry3, removeEdge) {
|
|
const position2 = geometry3.getAttribute("position");
|
|
const count = position2.count;
|
|
const barycentric = [];
|
|
for (let i3 = 0; i3 < count; i3++) {
|
|
const even = i3 % 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 BufferAttribute(Float32Array.from(barycentric), 3);
|
|
}
|
|
function getInputGeometry(inputGeometry) {
|
|
const geo = isRefObject2(inputGeometry) ? inputGeometry.current : inputGeometry;
|
|
if (!isGeometry2(geo)) {
|
|
if (isWireframeGeometry(geo)) {
|
|
throw new Error("Wireframe: WireframeGeometry is not supported.");
|
|
}
|
|
const parent = geo.parent;
|
|
if (isWithGeometry(parent)) {
|
|
if (isWireframeGeometry(parent.geometry)) {
|
|
throw new Error("Wireframe: WireframeGeometry is not supported.");
|
|
}
|
|
return parent.geometry;
|
|
}
|
|
} else {
|
|
return geo;
|
|
}
|
|
}
|
|
function setBarycentricCoordinates(geometry3, simplify) {
|
|
if (geometry3.index) {
|
|
console.warn("Wireframe: Requires non-indexed geometry, converting to non-indexed geometry.");
|
|
const nonIndexedGeo = geometry3.toNonIndexed();
|
|
geometry3.copy(nonIndexedGeo);
|
|
geometry3.setIndex(null);
|
|
}
|
|
const newBarycentric = getBarycentricCoordinates(geometry3, simplify);
|
|
geometry3.setAttribute("barycentric", newBarycentric);
|
|
}
|
|
function WireframeWithCustomGeo({
|
|
geometry: customGeometry,
|
|
simplify = false,
|
|
...props
|
|
}) {
|
|
extend({
|
|
MeshWireframeMaterial: WireframeMaterial
|
|
});
|
|
const [geometry3, setGeometry] = React115.useState(null);
|
|
React115.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 (isRef2(customGeometry)) {
|
|
setGeometry(geom);
|
|
}
|
|
}, [simplify, customGeometry]);
|
|
const drawnGeo = isRef2(customGeometry) ? geometry3 : customGeometry;
|
|
return React115.createElement(React115.Fragment, null, drawnGeo && React115.createElement("mesh", {
|
|
geometry: drawnGeo
|
|
}, React115.createElement("meshWireframeMaterial", _extends({
|
|
attach: "material",
|
|
transparent: true,
|
|
side: DoubleSide,
|
|
polygonOffset: true,
|
|
polygonOffsetFactor: -4
|
|
}, props, {
|
|
extensions: {
|
|
derivatives: true,
|
|
fragDepth: false,
|
|
drawBuffers: false,
|
|
shaderTextureLOD: false
|
|
}
|
|
}))));
|
|
}
|
|
function WireframeWithoutCustomGeo({
|
|
simplify = false,
|
|
...props
|
|
}) {
|
|
const objectRef = React115.useRef(null);
|
|
const uniforms = React115.useMemo(() => getUniforms(), [WireframeMaterialShaders.uniforms]);
|
|
useWireframeUniforms(uniforms, props);
|
|
React115.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]);
|
|
React115.useLayoutEffect(() => {
|
|
const parentMesh = objectRef.current.parent;
|
|
const og = parentMesh.material.clone();
|
|
setWireframeOverride(parentMesh.material, uniforms);
|
|
return () => {
|
|
parentMesh.material.dispose();
|
|
parentMesh.material = og;
|
|
};
|
|
}, []);
|
|
return React115.createElement("object3D", {
|
|
ref: objectRef
|
|
});
|
|
}
|
|
function Wireframe({
|
|
geometry: customGeometry,
|
|
...props
|
|
}) {
|
|
if (customGeometry) {
|
|
return React115.createElement(WireframeWithCustomGeo, _extends({
|
|
geometry: customGeometry
|
|
}, props));
|
|
}
|
|
return React115.createElement(WireframeWithoutCustomGeo, props);
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/ShadowAlpha.js
|
|
var React116 = __toESM(require_react());
|
|
function ShadowAlpha({
|
|
opacity,
|
|
alphaMap
|
|
}) {
|
|
const depthMaterialRef = React116.useRef(null);
|
|
const distanceMaterialRef = React116.useRef(null);
|
|
const uShadowOpacity = React116.useRef({
|
|
value: 1
|
|
});
|
|
const uAlphaMap = React116.useRef({
|
|
value: null
|
|
});
|
|
const uHasAlphaMap = React116.useRef({
|
|
value: false
|
|
});
|
|
React116.useLayoutEffect(() => {
|
|
depthMaterialRef.current.onBeforeCompile = distanceMaterialRef.current.onBeforeCompile = (shader) => {
|
|
const mainLineStart = shader.fragmentShader.indexOf("void main");
|
|
let mainLine = "";
|
|
let ch;
|
|
let i3 = mainLineStart;
|
|
while (ch !== "\n" && i3 < mainLineStart + 100) {
|
|
ch = shader.fragmentShader.charAt(i3);
|
|
mainLine += ch;
|
|
i3++;
|
|
}
|
|
mainLine = mainLine.trim();
|
|
shader.vertexShader = shader.vertexShader.replace("void main() {", `
|
|
varying vec2 custom_vUv;
|
|
|
|
void main() {
|
|
custom_vUv = uv;
|
|
|
|
`);
|
|
shader.fragmentShader = shader.fragmentShader.replace(mainLine, `
|
|
uniform float uShadowOpacity;
|
|
uniform sampler2D uAlphaMap;
|
|
uniform bool uHasAlphaMap;
|
|
|
|
varying vec2 custom_vUv;
|
|
|
|
float bayerDither2x2( vec2 v ) {
|
|
return mod( 3.0 * v.y + 2.0 * v.x, 4.0 );
|
|
}
|
|
|
|
float bayerDither4x4( vec2 v ) {
|
|
vec2 P1 = mod( v, 2.0 );
|
|
vec2 P2 = mod( floor( 0.5 * v ), 2.0 );
|
|
return 4.0 * bayerDither2x2( P1 ) + bayerDither2x2( P2 );
|
|
}
|
|
|
|
void main() {
|
|
float alpha =
|
|
uHasAlphaMap ?
|
|
uShadowOpacity * texture2D(uAlphaMap, custom_vUv).x
|
|
: uShadowOpacity;
|
|
|
|
if( ( bayerDither4x4( floor( mod( gl_FragCoord.xy, 4.0 ) ) ) ) / 16.0 >= alpha ) discard;
|
|
|
|
`);
|
|
shader.uniforms["uShadowOpacity"] = uShadowOpacity.current;
|
|
shader.uniforms["uAlphaMap"] = uAlphaMap.current;
|
|
shader.uniforms["uHasAlphaMap"] = uHasAlphaMap.current;
|
|
};
|
|
}, []);
|
|
useFrame(() => {
|
|
var _r3f;
|
|
const parent = (_r3f = depthMaterialRef.current.__r3f) == null || (_r3f = _r3f.parent) == null ? void 0 : _r3f.object;
|
|
if (parent) {
|
|
const parentMainMaterial = parent.material;
|
|
if (parentMainMaterial) {
|
|
uShadowOpacity.current.value = opacity !== null && opacity !== void 0 ? opacity : parentMainMaterial.opacity;
|
|
if (alphaMap === false) {
|
|
uAlphaMap.current.value = null;
|
|
uHasAlphaMap.current.value = false;
|
|
} else {
|
|
uAlphaMap.current.value = alphaMap || parentMainMaterial.alphaMap;
|
|
uHasAlphaMap.current.value = !!uAlphaMap.current.value;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
return React116.createElement(React116.Fragment, null, React116.createElement("meshDepthMaterial", {
|
|
ref: depthMaterialRef,
|
|
attach: "customDepthMaterial",
|
|
depthPacking: RGBADepthPacking
|
|
}), React116.createElement("meshDistanceMaterial", {
|
|
ref: distanceMaterialRef,
|
|
attach: "customDistanceMaterial"
|
|
}));
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/Points.js
|
|
var React117 = __toESM(require_react());
|
|
var _inverseMatrix = new Matrix4();
|
|
var _ray = new Ray();
|
|
var _sphere2 = new Sphere();
|
|
var _position2 = new Vector3();
|
|
var PositionPoint = class extends Group {
|
|
constructor() {
|
|
super();
|
|
this.size = 0;
|
|
this.color = new Color("white");
|
|
this.instance = {
|
|
current: void 0
|
|
};
|
|
this.instanceKey = {
|
|
current: void 0
|
|
};
|
|
}
|
|
// This will allow the virtual instance have bounds
|
|
get geometry() {
|
|
var _this$instance$curren;
|
|
return (_this$instance$curren = this.instance.current) == null ? void 0 : _this$instance$curren.geometry;
|
|
}
|
|
raycast(raycaster, intersects) {
|
|
var _raycaster$params$Poi, _raycaster$params$Poi2;
|
|
const parent = this.instance.current;
|
|
if (!parent || !parent.geometry) return;
|
|
const instanceId = parent.userData.instances.indexOf(this.instanceKey);
|
|
if (instanceId === -1 || instanceId > parent.geometry.drawRange.count) return;
|
|
const threshold = (_raycaster$params$Poi = (_raycaster$params$Poi2 = raycaster.params.Points) == null ? void 0 : _raycaster$params$Poi2.threshold) !== null && _raycaster$params$Poi !== void 0 ? _raycaster$params$Poi : 1;
|
|
_sphere2.set(this.getWorldPosition(_position2), threshold);
|
|
if (raycaster.ray.intersectsSphere(_sphere2) === false) return;
|
|
_inverseMatrix.copy(parent.matrixWorld).invert();
|
|
_ray.copy(raycaster.ray).applyMatrix4(_inverseMatrix);
|
|
const localThreshold = threshold / ((this.scale.x + this.scale.y + this.scale.z) / 3);
|
|
const localThresholdSq = localThreshold * localThreshold;
|
|
const rayPointDistanceSq = _ray.distanceSqToPoint(this.position);
|
|
if (rayPointDistanceSq < localThresholdSq) {
|
|
const intersectPoint = new Vector3();
|
|
_ray.closestPointToPoint(this.position, intersectPoint);
|
|
intersectPoint.applyMatrix4(this.matrixWorld);
|
|
const distance3 = raycaster.ray.origin.distanceTo(intersectPoint);
|
|
if (distance3 < raycaster.near || distance3 > raycaster.far) return;
|
|
intersects.push({
|
|
distance: distance3,
|
|
distanceToRay: Math.sqrt(rayPointDistanceSq),
|
|
point: intersectPoint,
|
|
index: instanceId,
|
|
face: null,
|
|
object: this
|
|
});
|
|
}
|
|
}
|
|
};
|
|
var i2;
|
|
var positionRef;
|
|
var context8 = React117.createContext(null);
|
|
var parentMatrix3 = new Matrix4();
|
|
var position = new Vector3();
|
|
var PointsInstances = React117.forwardRef(({
|
|
children,
|
|
range,
|
|
limit = 1e3,
|
|
...props
|
|
}, ref) => {
|
|
const parentRef = React117.useRef(null);
|
|
React117.useImperativeHandle(ref, () => parentRef.current, []);
|
|
const [refs, setRefs] = React117.useState([]);
|
|
const [[positions, colors2, sizes]] = React117.useState(() => [new Float32Array(limit * 3), Float32Array.from({
|
|
length: limit * 3
|
|
}, () => 1), Float32Array.from({
|
|
length: limit
|
|
}, () => 1)]);
|
|
React117.useEffect(() => {
|
|
parentRef.current.geometry.attributes.position.needsUpdate = true;
|
|
});
|
|
useFrame(() => {
|
|
parentRef.current.updateMatrix();
|
|
parentRef.current.updateMatrixWorld();
|
|
parentMatrix3.copy(parentRef.current.matrixWorld).invert();
|
|
parentRef.current.geometry.drawRange.count = Math.min(limit, range !== void 0 ? range : limit, refs.length);
|
|
for (i2 = 0; i2 < refs.length; i2++) {
|
|
positionRef = refs[i2].current;
|
|
positionRef.getWorldPosition(position).applyMatrix4(parentMatrix3);
|
|
position.toArray(positions, i2 * 3);
|
|
parentRef.current.geometry.attributes.position.needsUpdate = true;
|
|
positionRef.matrixWorldNeedsUpdate = true;
|
|
positionRef.color.toArray(colors2, i2 * 3);
|
|
parentRef.current.geometry.attributes.color.needsUpdate = true;
|
|
sizes.set([positionRef.size], i2);
|
|
parentRef.current.geometry.attributes.size.needsUpdate = true;
|
|
}
|
|
});
|
|
const api = React117.useMemo(() => ({
|
|
getParent: () => parentRef,
|
|
subscribe: (ref2) => {
|
|
setRefs((refs2) => [...refs2, ref2]);
|
|
return () => setRefs((refs2) => refs2.filter((item) => item.current !== ref2.current));
|
|
}
|
|
}), []);
|
|
return React117.createElement("points", _extends({
|
|
userData: {
|
|
instances: refs
|
|
},
|
|
matrixAutoUpdate: false,
|
|
ref: parentRef,
|
|
raycast: () => null
|
|
}, props), React117.createElement("bufferGeometry", null, React117.createElement("bufferAttribute", {
|
|
attach: "attributes-position",
|
|
args: [positions, 3],
|
|
usage: DynamicDrawUsage
|
|
}), React117.createElement("bufferAttribute", {
|
|
attach: "attributes-color",
|
|
args: [colors2, 3],
|
|
usage: DynamicDrawUsage
|
|
}), React117.createElement("bufferAttribute", {
|
|
attach: "attributes-size",
|
|
args: [sizes, 1],
|
|
usage: DynamicDrawUsage
|
|
})), React117.createElement(context8.Provider, {
|
|
value: api
|
|
}, children));
|
|
});
|
|
var Point = React117.forwardRef(({
|
|
children,
|
|
...props
|
|
}, ref) => {
|
|
React117.useMemo(() => extend({
|
|
PositionPoint
|
|
}), []);
|
|
const group = React117.useRef(null);
|
|
React117.useImperativeHandle(ref, () => group.current, []);
|
|
const {
|
|
subscribe,
|
|
getParent
|
|
} = React117.useContext(context8);
|
|
React117.useLayoutEffect(() => subscribe(group), []);
|
|
return React117.createElement("positionPoint", _extends({
|
|
instance: getParent(),
|
|
instanceKey: group,
|
|
ref: group
|
|
}, props), children);
|
|
});
|
|
var PointsBuffer = React117.forwardRef(({
|
|
children,
|
|
positions,
|
|
colors: colors2,
|
|
sizes,
|
|
stride = 3,
|
|
...props
|
|
}, forwardedRef) => {
|
|
const pointsRef = React117.useRef(null);
|
|
React117.useImperativeHandle(forwardedRef, () => pointsRef.current, []);
|
|
useFrame(() => {
|
|
const attr = pointsRef.current.geometry.attributes;
|
|
attr.position.needsUpdate = true;
|
|
if (colors2) attr.color.needsUpdate = true;
|
|
if (sizes) attr.size.needsUpdate = true;
|
|
});
|
|
return React117.createElement("points", _extends({
|
|
ref: pointsRef
|
|
}, props), React117.createElement("bufferGeometry", null, React117.createElement("bufferAttribute", {
|
|
attach: "attributes-position",
|
|
args: [positions, stride],
|
|
usage: DynamicDrawUsage
|
|
}), colors2 && React117.createElement("bufferAttribute", {
|
|
attach: "attributes-color",
|
|
args: [colors2, stride],
|
|
count: colors2.length / stride,
|
|
usage: DynamicDrawUsage
|
|
}), sizes && React117.createElement("bufferAttribute", {
|
|
attach: "attributes-size",
|
|
args: [sizes, 1],
|
|
count: sizes.length / stride,
|
|
usage: DynamicDrawUsage
|
|
})), children);
|
|
});
|
|
var Points = React117.forwardRef((props, forwardedRef) => {
|
|
if (props.positions instanceof Float32Array) {
|
|
return React117.createElement(PointsBuffer, _extends({}, props, {
|
|
ref: forwardedRef
|
|
}));
|
|
} else return React117.createElement(PointsInstances, _extends({}, props, {
|
|
ref: forwardedRef
|
|
}));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Segments.js
|
|
var React118 = __toESM(require_react());
|
|
var context9 = React118.createContext(null);
|
|
var Segments = React118.forwardRef((props, forwardedRef) => {
|
|
React118.useMemo(() => extend({
|
|
SegmentObject
|
|
}), []);
|
|
const {
|
|
limit = 1e3,
|
|
lineWidth = 1,
|
|
children,
|
|
...rest
|
|
} = props;
|
|
const [segments, setSegments] = React118.useState([]);
|
|
const [line] = React118.useState(() => new Line2());
|
|
const [material] = React118.useState(() => new LineMaterial());
|
|
const [geometry3] = React118.useState(() => new LineSegmentsGeometry());
|
|
const [resolution] = React118.useState(() => new Vector2(512, 512));
|
|
const [positions] = React118.useState(() => Array(limit * 6).fill(0));
|
|
const [colors2] = React118.useState(() => Array(limit * 6).fill(0));
|
|
const api = React118.useMemo(() => ({
|
|
subscribe: (ref) => {
|
|
setSegments((segments2) => [...segments2, ref]);
|
|
return () => setSegments((segments2) => segments2.filter((item) => item.current !== ref.current));
|
|
}
|
|
}), []);
|
|
useFrame(() => {
|
|
for (let i3 = 0; i3 < limit; i3++) {
|
|
var _segments$i;
|
|
const segment = (_segments$i = segments[i3]) == null ? void 0 : _segments$i.current;
|
|
if (segment) {
|
|
positions[i3 * 6 + 0] = segment.start.x;
|
|
positions[i3 * 6 + 1] = segment.start.y;
|
|
positions[i3 * 6 + 2] = segment.start.z;
|
|
positions[i3 * 6 + 3] = segment.end.x;
|
|
positions[i3 * 6 + 4] = segment.end.y;
|
|
positions[i3 * 6 + 5] = segment.end.z;
|
|
colors2[i3 * 6 + 0] = segment.color.r;
|
|
colors2[i3 * 6 + 1] = segment.color.g;
|
|
colors2[i3 * 6 + 2] = segment.color.b;
|
|
colors2[i3 * 6 + 3] = segment.color.r;
|
|
colors2[i3 * 6 + 4] = segment.color.g;
|
|
colors2[i3 * 6 + 5] = segment.color.b;
|
|
}
|
|
}
|
|
geometry3.setColors(colors2);
|
|
geometry3.setPositions(positions);
|
|
line.computeLineDistances();
|
|
});
|
|
return React118.createElement("primitive", {
|
|
object: line,
|
|
ref: forwardedRef
|
|
}, React118.createElement("primitive", {
|
|
object: geometry3,
|
|
attach: "geometry"
|
|
}), React118.createElement("primitive", _extends({
|
|
object: material,
|
|
attach: "material",
|
|
vertexColors: true,
|
|
resolution,
|
|
linewidth: lineWidth
|
|
}, rest)), React118.createElement(context9.Provider, {
|
|
value: api
|
|
}, children));
|
|
});
|
|
var SegmentObject = class {
|
|
constructor() {
|
|
this.color = new Color("white");
|
|
this.start = new Vector3(0, 0, 0);
|
|
this.end = new Vector3(0, 0, 0);
|
|
}
|
|
};
|
|
var normPos = (pos) => pos instanceof Vector3 ? pos : new Vector3(...typeof pos === "number" ? [pos, pos, pos] : pos);
|
|
var Segment = React118.forwardRef(({
|
|
color,
|
|
start,
|
|
end
|
|
}, forwardedRef) => {
|
|
const api = React118.useContext(context9);
|
|
if (!api) throw "Segment must used inside Segments component.";
|
|
const ref = React118.useRef(null);
|
|
React118.useImperativeHandle(forwardedRef, () => ref.current, []);
|
|
React118.useLayoutEffect(() => api.subscribe(ref), []);
|
|
return React118.createElement("segmentObject", {
|
|
ref,
|
|
color,
|
|
start: normPos(start),
|
|
end: normPos(end)
|
|
});
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Detailed.js
|
|
var React119 = __toESM(require_react());
|
|
var Detailed = React119.forwardRef(({
|
|
children,
|
|
hysteresis = 0,
|
|
distances,
|
|
...props
|
|
}, ref) => {
|
|
const lodRef = React119.useRef(null);
|
|
React119.useImperativeHandle(ref, () => lodRef.current, []);
|
|
React119.useLayoutEffect(() => {
|
|
const {
|
|
current: lod
|
|
} = lodRef;
|
|
lod.levels.length = 0;
|
|
lod.children.forEach((object, index2) => lod.levels.push({
|
|
object,
|
|
hysteresis,
|
|
distance: distances[index2]
|
|
}));
|
|
});
|
|
useFrame((state) => {
|
|
var _lodRef$current;
|
|
return (_lodRef$current = lodRef.current) == null ? void 0 : _lodRef$current.update(state.camera);
|
|
});
|
|
return React119.createElement("lOD", _extends({
|
|
ref: lodRef
|
|
}, props), children);
|
|
});
|
|
|
|
// node_modules/@react-three/drei/core/Preload.js
|
|
var React120 = __toESM(require_react());
|
|
function Preload({
|
|
all,
|
|
scene,
|
|
camera
|
|
}) {
|
|
const gl = useThree(({
|
|
gl: gl2
|
|
}) => gl2);
|
|
const dCamera = useThree(({
|
|
camera: camera2
|
|
}) => camera2);
|
|
const dScene = useThree(({
|
|
scene: scene2
|
|
}) => scene2);
|
|
React120.useLayoutEffect(() => {
|
|
const invisible = [];
|
|
if (all) {
|
|
(scene || dScene).traverse((object) => {
|
|
if (object.visible === false) {
|
|
invisible.push(object);
|
|
object.visible = true;
|
|
}
|
|
});
|
|
}
|
|
gl.compile(scene || dScene, camera || dCamera);
|
|
const cubeRenderTarget = new WebGLCubeRenderTarget(128);
|
|
const cubeCamera = new CubeCamera(0.01, 1e5, cubeRenderTarget);
|
|
cubeCamera.update(gl, scene || dScene);
|
|
cubeRenderTarget.dispose();
|
|
invisible.forEach((object) => object.visible = false);
|
|
}, []);
|
|
return null;
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/BakeShadows.js
|
|
var import_react19 = __toESM(require_react());
|
|
function BakeShadows() {
|
|
const gl = useThree((state) => state.gl);
|
|
(0, import_react19.useEffect)(() => {
|
|
gl.shadowMap.autoUpdate = false;
|
|
gl.shadowMap.needsUpdate = true;
|
|
return () => {
|
|
gl.shadowMap.autoUpdate = gl.shadowMap.needsUpdate = true;
|
|
};
|
|
}, [gl.shadowMap]);
|
|
return null;
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/meshBounds.js
|
|
var _inverseMatrix2 = new Matrix4();
|
|
var _ray2 = new Ray();
|
|
var _sphere3 = new Sphere();
|
|
var _vA2 = new Vector3();
|
|
function meshBounds(raycaster, intersects) {
|
|
const geometry3 = this.geometry;
|
|
const material = this.material;
|
|
const matrixWorld = this.matrixWorld;
|
|
if (material === void 0) return;
|
|
if (geometry3.boundingSphere === null) geometry3.computeBoundingSphere();
|
|
_sphere3.copy(geometry3.boundingSphere);
|
|
_sphere3.applyMatrix4(matrixWorld);
|
|
if (raycaster.ray.intersectsSphere(_sphere3) === false) return;
|
|
_inverseMatrix2.copy(matrixWorld).invert();
|
|
_ray2.copy(raycaster.ray).applyMatrix4(_inverseMatrix2);
|
|
if (geometry3.boundingBox !== null && _ray2.intersectBox(geometry3.boundingBox, _vA2) === null) return;
|
|
intersects.push({
|
|
distance: _vA2.distanceTo(raycaster.ray.origin),
|
|
point: _vA2.clone(),
|
|
object: this
|
|
});
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/AdaptiveDpr.js
|
|
var React121 = __toESM(require_react());
|
|
function AdaptiveDpr({
|
|
pixelated
|
|
}) {
|
|
const gl = useThree((state) => state.gl);
|
|
const active = useThree((state) => state.internal.active);
|
|
const current = useThree((state) => state.performance.current);
|
|
const initialDpr = useThree((state) => state.viewport.initialDpr);
|
|
const setDpr = useThree((state) => state.setDpr);
|
|
React121.useEffect(() => {
|
|
const domElement = gl.domElement;
|
|
return () => {
|
|
if (active) setDpr(initialDpr);
|
|
if (pixelated && domElement) domElement.style.imageRendering = "auto";
|
|
};
|
|
}, []);
|
|
React121.useEffect(() => {
|
|
setDpr(current * initialDpr);
|
|
if (pixelated && gl.domElement) gl.domElement.style.imageRendering = current === 1 ? "auto" : "pixelated";
|
|
}, [current]);
|
|
return null;
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/AdaptiveEvents.js
|
|
var React122 = __toESM(require_react());
|
|
function AdaptiveEvents() {
|
|
const get = useThree((state) => state.get);
|
|
const setEvents = useThree((state) => state.setEvents);
|
|
const current = useThree((state) => state.performance.current);
|
|
React122.useEffect(() => {
|
|
const enabled = get().events.enabled;
|
|
return () => setEvents({
|
|
enabled
|
|
});
|
|
}, []);
|
|
React122.useEffect(() => setEvents({
|
|
enabled: current === 1
|
|
}), [current]);
|
|
return null;
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/PerformanceMonitor.js
|
|
var React123 = __toESM(require_react());
|
|
var import_react20 = __toESM(require_react());
|
|
var context10 = (0, import_react20.createContext)(null);
|
|
function PerformanceMonitor({
|
|
iterations = 10,
|
|
ms = 250,
|
|
threshold = 0.75,
|
|
step = 0.1,
|
|
factor: _factor = 0.5,
|
|
flipflops = Infinity,
|
|
bounds = (refreshrate) => refreshrate > 100 ? [60, 100] : [40, 60],
|
|
onIncline,
|
|
onDecline,
|
|
onChange,
|
|
onFallback,
|
|
children
|
|
}) {
|
|
const decimalPlacesRatio = Math.pow(10, 0);
|
|
const [api, _] = (0, import_react20.useState)(() => ({
|
|
fps: 0,
|
|
index: 0,
|
|
factor: _factor,
|
|
flipped: 0,
|
|
refreshrate: 0,
|
|
fallback: false,
|
|
frames: [],
|
|
averages: [],
|
|
subscriptions: /* @__PURE__ */ new Map(),
|
|
subscribe: (ref) => {
|
|
const key = /* @__PURE__ */ Symbol();
|
|
api.subscriptions.set(key, ref.current);
|
|
return () => void api.subscriptions.delete(key);
|
|
}
|
|
}));
|
|
let lastFactor = 0;
|
|
useFrame(() => {
|
|
const {
|
|
frames,
|
|
averages
|
|
} = api;
|
|
if (api.fallback) return;
|
|
if (averages.length < iterations) {
|
|
frames.push(performance.now());
|
|
const msPassed = frames[frames.length - 1] - frames[0];
|
|
if (msPassed >= ms) {
|
|
api.fps = Math.round(frames.length / msPassed * 1e3 * decimalPlacesRatio) / decimalPlacesRatio;
|
|
api.refreshrate = Math.max(api.refreshrate, api.fps);
|
|
averages[api.index++ % iterations] = api.fps;
|
|
if (averages.length === iterations) {
|
|
const [lower, upper] = bounds(api.refreshrate);
|
|
const upperBounds = averages.filter((value) => value >= upper);
|
|
const lowerBounds = averages.filter((value) => value < lower);
|
|
if (upperBounds.length > iterations * threshold) {
|
|
api.factor = Math.min(1, api.factor + step);
|
|
api.flipped++;
|
|
if (onIncline) onIncline(api);
|
|
api.subscriptions.forEach((value) => value.onIncline && value.onIncline(api));
|
|
}
|
|
if (lowerBounds.length > iterations * threshold) {
|
|
api.factor = Math.max(0, api.factor - step);
|
|
api.flipped++;
|
|
if (onDecline) onDecline(api);
|
|
api.subscriptions.forEach((value) => value.onDecline && value.onDecline(api));
|
|
}
|
|
if (lastFactor !== api.factor) {
|
|
lastFactor = api.factor;
|
|
if (onChange) onChange(api);
|
|
api.subscriptions.forEach((value) => value.onChange && value.onChange(api));
|
|
}
|
|
if (api.flipped > flipflops && !api.fallback) {
|
|
api.fallback = true;
|
|
if (onFallback) onFallback(api);
|
|
api.subscriptions.forEach((value) => value.onFallback && value.onFallback(api));
|
|
}
|
|
api.averages = [];
|
|
}
|
|
api.frames = [];
|
|
}
|
|
}
|
|
});
|
|
return React123.createElement(context10.Provider, {
|
|
value: api
|
|
}, children);
|
|
}
|
|
function usePerformanceMonitor({
|
|
onIncline,
|
|
onDecline,
|
|
onChange,
|
|
onFallback
|
|
}) {
|
|
const api = (0, import_react20.useContext)(context10);
|
|
const ref = (0, import_react20.useRef)({
|
|
onIncline,
|
|
onDecline,
|
|
onChange,
|
|
onFallback
|
|
});
|
|
(0, import_react20.useLayoutEffect)(() => {
|
|
ref.current.onIncline = onIncline;
|
|
ref.current.onDecline = onDecline;
|
|
ref.current.onChange = onChange;
|
|
ref.current.onFallback = onFallback;
|
|
}, [onIncline, onDecline, onChange, onFallback]);
|
|
(0, import_react20.useLayoutEffect)(() => api.subscribe(ref), [api]);
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/RenderTexture.js
|
|
var React124 = __toESM(require_react());
|
|
var RenderTexture = React124.forwardRef(({
|
|
children,
|
|
compute,
|
|
width,
|
|
height,
|
|
samples = 8,
|
|
renderPriority = 0,
|
|
eventPriority = 0,
|
|
frames = Infinity,
|
|
stencilBuffer = false,
|
|
depthBuffer = true,
|
|
generateMipmaps = false,
|
|
...props
|
|
}, forwardRef82) => {
|
|
const {
|
|
size,
|
|
viewport
|
|
} = useThree();
|
|
const fbo = useFBO((width || size.width) * viewport.dpr, (height || size.height) * viewport.dpr, {
|
|
samples,
|
|
stencilBuffer,
|
|
depthBuffer,
|
|
generateMipmaps
|
|
});
|
|
const [vScene] = React124.useState(() => new Scene());
|
|
const uvCompute = React124.useCallback((event, state, previous) => {
|
|
var _fbo$texture, _previous$previousRoo;
|
|
let parent = (_fbo$texture = fbo.texture) == null || (_fbo$texture = _fbo$texture.__r3f.parent) == null ? void 0 : _fbo$texture.object;
|
|
while (parent && !(parent instanceof Object3D)) {
|
|
var _parent$__r3f$parent;
|
|
parent = (_parent$__r3f$parent = parent.__r3f.parent) == null ? void 0 : _parent$__r3f$parent.object;
|
|
}
|
|
if (!parent) return false;
|
|
if (!previous.raycaster.camera) previous.events.compute(event, previous, (_previous$previousRoo = previous.previousRoot) == null ? void 0 : _previous$previousRoo.getState());
|
|
const [intersection3] = previous.raycaster.intersectObject(parent);
|
|
if (!intersection3) return false;
|
|
const uv = intersection3.uv;
|
|
if (!uv) return false;
|
|
state.raycaster.setFromCamera(state.pointer.set(uv.x * 2 - 1, uv.y * 2 - 1), state.camera);
|
|
}, []);
|
|
React124.useImperativeHandle(forwardRef82, () => fbo.texture, [fbo]);
|
|
return React124.createElement(React124.Fragment, null, createPortal(React124.createElement(Container, {
|
|
renderPriority,
|
|
frames,
|
|
fbo
|
|
}, children, React124.createElement("group", {
|
|
onPointerOver: () => null
|
|
})), vScene, {
|
|
events: {
|
|
compute: compute || uvCompute,
|
|
priority: eventPriority
|
|
}
|
|
}), React124.createElement("primitive", _extends({
|
|
object: fbo.texture
|
|
}, props)));
|
|
});
|
|
function Container({
|
|
frames,
|
|
renderPriority,
|
|
children,
|
|
fbo
|
|
}) {
|
|
let count = 0;
|
|
let oldAutoClear;
|
|
let oldXrEnabled;
|
|
let oldRenderTarget;
|
|
let oldIsPresenting;
|
|
useFrame((state) => {
|
|
if (frames === Infinity || count < frames) {
|
|
oldAutoClear = state.gl.autoClear;
|
|
oldXrEnabled = state.gl.xr.enabled;
|
|
oldRenderTarget = state.gl.getRenderTarget();
|
|
oldIsPresenting = state.gl.xr.isPresenting;
|
|
state.gl.autoClear = true;
|
|
state.gl.xr.enabled = false;
|
|
state.gl.xr.isPresenting = false;
|
|
state.gl.setRenderTarget(fbo);
|
|
state.gl.render(state.scene, state.camera);
|
|
state.gl.setRenderTarget(oldRenderTarget);
|
|
state.gl.autoClear = oldAutoClear;
|
|
state.gl.xr.enabled = oldXrEnabled;
|
|
state.gl.xr.isPresenting = oldIsPresenting;
|
|
count++;
|
|
}
|
|
}, renderPriority);
|
|
return React124.createElement(React124.Fragment, null, children);
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/RenderCubeTexture.js
|
|
var React125 = __toESM(require_react());
|
|
var RenderCubeTexture = React125.forwardRef(({
|
|
children,
|
|
compute,
|
|
renderPriority = -1,
|
|
eventPriority = 0,
|
|
frames = Infinity,
|
|
stencilBuffer = false,
|
|
depthBuffer = true,
|
|
generateMipmaps = false,
|
|
resolution = 896,
|
|
near = 0.1,
|
|
far = 1e3,
|
|
flip = false,
|
|
position: position2,
|
|
rotation: rotation3,
|
|
scale: scale5,
|
|
quaternion,
|
|
matrix: matrix4,
|
|
matrixAutoUpdate,
|
|
...props
|
|
}, forwardRef82) => {
|
|
const {
|
|
size,
|
|
viewport
|
|
} = useThree();
|
|
const camera = React125.useRef(null);
|
|
const fbo = React125.useMemo(() => {
|
|
const fbo2 = new WebGLCubeRenderTarget(Math.max((resolution || size.width) * viewport.dpr, (resolution || size.height) * viewport.dpr), {
|
|
stencilBuffer,
|
|
depthBuffer,
|
|
generateMipmaps
|
|
});
|
|
fbo2.texture.isRenderTargetTexture = !flip;
|
|
fbo2.texture.flipY = true;
|
|
fbo2.texture.type = HalfFloatType;
|
|
return fbo2;
|
|
}, [resolution, flip]);
|
|
React125.useEffect(() => {
|
|
return () => fbo.dispose();
|
|
}, [fbo]);
|
|
const [vScene] = React125.useState(() => new Scene());
|
|
React125.useImperativeHandle(forwardRef82, () => ({
|
|
scene: vScene,
|
|
fbo,
|
|
camera: camera.current
|
|
}), [fbo]);
|
|
return React125.createElement(React125.Fragment, null, createPortal(React125.createElement(Container2, {
|
|
renderPriority,
|
|
frames,
|
|
camera
|
|
}, children, React125.createElement("group", {
|
|
onPointerOver: () => null
|
|
})), vScene, {
|
|
events: {
|
|
compute,
|
|
priority: eventPriority
|
|
}
|
|
}), React125.createElement("primitive", _extends({
|
|
object: fbo.texture
|
|
}, props)), React125.createElement("cubeCamera", {
|
|
ref: camera,
|
|
args: [near, far, fbo],
|
|
position: position2,
|
|
rotation: rotation3,
|
|
scale: scale5,
|
|
quaternion,
|
|
matrix: matrix4,
|
|
matrixAutoUpdate
|
|
}));
|
|
});
|
|
function Container2({
|
|
frames,
|
|
renderPriority,
|
|
children,
|
|
camera
|
|
}) {
|
|
let count = 0;
|
|
useFrame((state) => {
|
|
if (frames === Infinity || count < frames) {
|
|
camera.current.update(state.gl, state.scene);
|
|
count++;
|
|
}
|
|
}, renderPriority);
|
|
return React125.createElement(React125.Fragment, null, children);
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/Mask.js
|
|
var React126 = __toESM(require_react());
|
|
var Mask = React126.forwardRef(({
|
|
id = 1,
|
|
colorWrite = false,
|
|
depthWrite = false,
|
|
...props
|
|
}, fref) => {
|
|
const ref = React126.useRef(null);
|
|
const spread = React126.useMemo(() => ({
|
|
colorWrite,
|
|
depthWrite,
|
|
stencilWrite: true,
|
|
stencilRef: id,
|
|
stencilFunc: AlwaysStencilFunc,
|
|
stencilFail: ReplaceStencilOp,
|
|
stencilZFail: ReplaceStencilOp,
|
|
stencilZPass: ReplaceStencilOp
|
|
}), [id, colorWrite, depthWrite]);
|
|
React126.useLayoutEffect(() => {
|
|
Object.assign(ref.current.material, spread);
|
|
});
|
|
React126.useImperativeHandle(fref, () => ref.current, []);
|
|
return React126.createElement("mesh", _extends({
|
|
ref,
|
|
renderOrder: -id
|
|
}, props));
|
|
});
|
|
function useMask(id, inverse = false) {
|
|
return {
|
|
stencilWrite: true,
|
|
stencilRef: id,
|
|
stencilFunc: inverse ? NotEqualStencilFunc : EqualStencilFunc,
|
|
stencilFail: KeepStencilOp,
|
|
stencilZFail: KeepStencilOp,
|
|
stencilZPass: KeepStencilOp
|
|
};
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/Fisheye.js
|
|
var React127 = __toESM(require_react());
|
|
function Fisheye({
|
|
renderPriority = 1,
|
|
zoom = 0,
|
|
segments = 64,
|
|
children,
|
|
resolution = 896,
|
|
...props
|
|
}) {
|
|
const sphere = React127.useRef(null);
|
|
const cubeApi = React127.useRef(null);
|
|
const {
|
|
width,
|
|
height
|
|
} = useThree((state) => state.size);
|
|
const [orthoC] = React127.useState(() => new OrthographicCamera());
|
|
React127.useLayoutEffect(() => {
|
|
orthoC.position.set(0, 0, 100);
|
|
orthoC.zoom = 100;
|
|
orthoC.left = width / -2;
|
|
orthoC.right = width / 2;
|
|
orthoC.top = height / 2;
|
|
orthoC.bottom = height / -2;
|
|
orthoC.updateProjectionMatrix();
|
|
}, [width, height]);
|
|
const radius = Math.sqrt(width * width + height * height) / 100 * (0.5 + zoom / 2);
|
|
const normal2 = new Vector3();
|
|
const sph = new Sphere(new Vector3(), radius);
|
|
const normalMatrix = new Matrix3();
|
|
const compute = React127.useCallback((event, state, prev) => {
|
|
state.pointer.set(event.offsetX / state.size.width * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
|
|
state.raycaster.setFromCamera(state.pointer, orthoC);
|
|
if (!state.raycaster.ray.intersectSphere(sph, normal2)) return;
|
|
else normal2.normalize();
|
|
normalMatrix.getNormalMatrix(cubeApi.current.camera.matrixWorld);
|
|
cubeApi.current.camera.getWorldPosition(state.raycaster.ray.origin);
|
|
state.raycaster.ray.direction.set(0, 0, 1).reflect(normal2);
|
|
state.raycaster.ray.direction.x *= -1;
|
|
state.raycaster.ray.direction.applyNormalMatrix(normalMatrix).multiplyScalar(-1);
|
|
return void 0;
|
|
}, []);
|
|
useFrame((state) => {
|
|
if (renderPriority) state.gl.render(sphere.current, orthoC);
|
|
}, renderPriority);
|
|
return React127.createElement(React127.Fragment, null, React127.createElement("mesh", _extends({
|
|
ref: sphere
|
|
}, props, {
|
|
scale: radius
|
|
}), React127.createElement("sphereGeometry", {
|
|
args: [1, segments, segments]
|
|
}), React127.createElement("meshBasicMaterial", null, React127.createElement(RenderCubeTexture, {
|
|
compute,
|
|
attach: "envMap",
|
|
flip: true,
|
|
resolution,
|
|
ref: cubeApi
|
|
}, children, React127.createElement(UpdateCubeCamera, {
|
|
api: cubeApi
|
|
})))));
|
|
}
|
|
function UpdateCubeCamera({
|
|
api
|
|
}) {
|
|
const t2 = new Vector3();
|
|
const r2 = new Quaternion();
|
|
const s2 = new Vector3();
|
|
const e2 = new Euler(0, Math.PI, 0);
|
|
useFrame((state) => {
|
|
state.camera.matrixWorld.decompose(t2, r2, s2);
|
|
api.current.camera.position.copy(t2);
|
|
api.current.camera.quaternion.setFromEuler(e2).premultiply(r2);
|
|
});
|
|
return null;
|
|
}
|
|
|
|
// node_modules/@react-three/drei/core/MeshPortalMaterial.js
|
|
var React128 = __toESM(require_react());
|
|
var PortalMaterialImpl = shaderMaterial({
|
|
blur: 0,
|
|
map: null,
|
|
sdf: null,
|
|
blend: 0,
|
|
size: 0,
|
|
resolution: new Vector2()
|
|
}, `varying vec2 vUv;
|
|
void main() {
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
vUv = uv;
|
|
}`, `uniform sampler2D sdf;
|
|
uniform sampler2D map;
|
|
uniform float blur;
|
|
uniform float size;
|
|
uniform float time;
|
|
uniform vec2 resolution;
|
|
varying vec2 vUv;
|
|
#include <packing>
|
|
void main() {
|
|
vec2 uv = gl_FragCoord.xy / resolution.xy;
|
|
vec4 t = texture2D(map, uv);
|
|
float k = blur;
|
|
float d = texture2D(sdf, vUv).r/size;
|
|
float alpha = 1.0 - smoothstep(0.0, 1.0, clamp(d/k + 1.0, 0.0, 1.0));
|
|
gl_FragColor = vec4(t.rgb, blur == 0.0 ? t.a : t.a * alpha);
|
|
#include <tonemapping_fragment>
|
|
#include <${version >= 154 ? "colorspace_fragment" : "encodings_fragment"}>
|
|
}`);
|
|
var MeshPortalMaterial = React128.forwardRef(({
|
|
children,
|
|
events = void 0,
|
|
blur = 0,
|
|
eventPriority = 0,
|
|
renderPriority = 0,
|
|
worldUnits = false,
|
|
resolution = 512,
|
|
...props
|
|
}, fref) => {
|
|
extend({
|
|
PortalMaterialImpl
|
|
});
|
|
const ref = React128.useRef(null);
|
|
const {
|
|
scene,
|
|
gl,
|
|
size,
|
|
viewport,
|
|
setEvents
|
|
} = useThree();
|
|
const maskRenderTarget = useFBO(resolution, resolution);
|
|
const [priority, setPriority] = React128.useState(0);
|
|
useFrame(() => {
|
|
const p2 = ref.current.blend > 0 ? Math.max(1, renderPriority) : 0;
|
|
if (priority !== p2) setPriority(p2);
|
|
});
|
|
React128.useEffect(() => {
|
|
if (events !== void 0) setEvents({
|
|
enabled: !events
|
|
});
|
|
}, [events]);
|
|
const [visible, setVisible] = React128.useState(true);
|
|
const parent = useIntersect(setVisible);
|
|
React128.useLayoutEffect(() => {
|
|
var _ref$current;
|
|
parent.current = (_ref$current = ref.current) == null || (_ref$current = _ref$current.__r3f.parent) == null ? void 0 : _ref$current.object;
|
|
}, []);
|
|
React128.useLayoutEffect(() => {
|
|
if (!parent.current) return;
|
|
if (blur && ref.current.sdf === null) {
|
|
const tempMesh = new Mesh(parent.current.geometry, new MeshBasicMaterial());
|
|
const boundingBox5 = new Box3().setFromBufferAttribute(tempMesh.geometry.attributes.position);
|
|
const orthoCam = new OrthographicCamera(boundingBox5.min.x * (1 + 2 / resolution), boundingBox5.max.x * (1 + 2 / resolution), boundingBox5.max.y * (1 + 2 / resolution), boundingBox5.min.y * (1 + 2 / resolution), 0.1, 1e3);
|
|
orthoCam.position.set(0, 0, 1);
|
|
orthoCam.lookAt(0, 0, 0);
|
|
gl.setRenderTarget(maskRenderTarget);
|
|
gl.render(tempMesh, orthoCam);
|
|
const sg = makeSDFGenerator(resolution, resolution, gl);
|
|
const sdf = sg(maskRenderTarget.texture);
|
|
const readSdf = new Float32Array(resolution * resolution);
|
|
gl.readRenderTargetPixels(sdf, 0, 0, resolution, resolution, readSdf);
|
|
let min = Infinity;
|
|
for (let i3 = 0; i3 < readSdf.length; i3++) {
|
|
if (readSdf[i3] < min) min = readSdf[i3];
|
|
}
|
|
min = -min;
|
|
ref.current.size = min;
|
|
ref.current.sdf = sdf.texture;
|
|
gl.setRenderTarget(null);
|
|
}
|
|
}, [resolution, blur]);
|
|
React128.useImperativeHandle(fref, () => ref.current);
|
|
const compute = React128.useCallback((event, state, previous) => {
|
|
var _ref$current2;
|
|
if (!parent.current) return false;
|
|
state.pointer.set(event.offsetX / state.size.width * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
|
|
state.raycaster.setFromCamera(state.pointer, state.camera);
|
|
if (((_ref$current2 = ref.current) == null ? void 0 : _ref$current2.blend) === 0) {
|
|
const [intersection3] = state.raycaster.intersectObject(parent.current);
|
|
if (!intersection3) {
|
|
state.raycaster.camera = void 0;
|
|
return false;
|
|
}
|
|
}
|
|
}, []);
|
|
return React128.createElement("portalMaterialImpl", _extends({
|
|
ref,
|
|
blur,
|
|
blend: 0,
|
|
resolution: [size.width * viewport.dpr, size.height * viewport.dpr],
|
|
attach: "material"
|
|
}, props), React128.createElement(RenderTexture, {
|
|
attach: "map",
|
|
frames: visible ? Infinity : 0,
|
|
eventPriority,
|
|
renderPriority,
|
|
compute
|
|
}, children, React128.createElement(ManagePortalScene, {
|
|
events,
|
|
rootScene: scene,
|
|
priority,
|
|
material: ref,
|
|
worldUnits
|
|
})));
|
|
});
|
|
function ManagePortalScene({
|
|
events = void 0,
|
|
rootScene,
|
|
material,
|
|
priority,
|
|
worldUnits
|
|
}) {
|
|
const scene = useThree((state) => state.scene);
|
|
const setEvents = useThree((state) => state.setEvents);
|
|
const buffer1 = useFBO();
|
|
const buffer2 = useFBO();
|
|
React128.useLayoutEffect(() => {
|
|
scene.matrixAutoUpdate = false;
|
|
}, []);
|
|
React128.useEffect(() => {
|
|
if (events !== void 0) setEvents({
|
|
enabled: events
|
|
});
|
|
}, [events]);
|
|
const [quad, blend] = React128.useMemo(() => {
|
|
const blend2 = {
|
|
value: 0
|
|
};
|
|
const quad2 = new FullScreenQuad(new ShaderMaterial({
|
|
uniforms: {
|
|
a: {
|
|
value: buffer1.texture
|
|
},
|
|
b: {
|
|
value: buffer2.texture
|
|
},
|
|
blend: blend2
|
|
},
|
|
vertexShader: (
|
|
/*glsl*/
|
|
`
|
|
varying vec2 vUv;
|
|
void main() {
|
|
vUv = uv;
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
}`
|
|
),
|
|
fragmentShader: (
|
|
/*glsl*/
|
|
`
|
|
uniform sampler2D a;
|
|
uniform sampler2D b;
|
|
uniform float blend;
|
|
varying vec2 vUv;
|
|
#include <packing>
|
|
void main() {
|
|
vec4 ta = texture2D(a, vUv);
|
|
vec4 tb = texture2D(b, vUv);
|
|
gl_FragColor = mix(tb, ta, blend);
|
|
#include <tonemapping_fragment>
|
|
#include <${version >= 154 ? "colorspace_fragment" : "encodings_fragment"}>
|
|
}`
|
|
)
|
|
}));
|
|
return [quad2, blend2];
|
|
}, []);
|
|
useFrame((state) => {
|
|
var _material$current;
|
|
let parent = material == null || (_material$current = material.current) == null || (_material$current = _material$current.__r3f.parent) == null ? void 0 : _material$current.object;
|
|
if (parent) {
|
|
if (!worldUnits) {
|
|
var _material$current2;
|
|
if (priority && ((_material$current2 = material.current) == null ? void 0 : _material$current2.blend) === 1) parent.updateWorldMatrix(true, false);
|
|
scene.matrixWorld.copy(parent.matrixWorld);
|
|
} else scene.matrixWorld.identity();
|
|
if (priority) {
|
|
var _material$current3, _material$current4, _material$current5;
|
|
if (((_material$current3 = material.current) == null ? void 0 : _material$current3.blend) > 0 && ((_material$current4 = material.current) == null ? void 0 : _material$current4.blend) < 1) {
|
|
blend.value = material.current.blend;
|
|
state.gl.setRenderTarget(buffer1);
|
|
state.gl.render(scene, state.camera);
|
|
state.gl.setRenderTarget(buffer2);
|
|
state.gl.render(rootScene, state.camera);
|
|
state.gl.setRenderTarget(null);
|
|
quad.render(state.gl);
|
|
} else if (((_material$current5 = material.current) == null ? void 0 : _material$current5.blend) === 1) {
|
|
state.gl.render(scene, state.camera);
|
|
}
|
|
}
|
|
}
|
|
}, priority);
|
|
return React128.createElement(React128.Fragment, null);
|
|
}
|
|
var makeSDFGenerator = (clientWidth, clientHeight, renderer) => {
|
|
let finalTarget = new WebGLRenderTarget(clientWidth, clientHeight, {
|
|
minFilter: LinearMipmapLinearFilter,
|
|
magFilter: LinearFilter,
|
|
type: FloatType,
|
|
format: RedFormat,
|
|
generateMipmaps: true
|
|
});
|
|
let outsideRenderTarget = new WebGLRenderTarget(clientWidth, clientHeight, {
|
|
minFilter: NearestFilter,
|
|
magFilter: NearestFilter
|
|
});
|
|
let insideRenderTarget = new WebGLRenderTarget(clientWidth, clientHeight, {
|
|
minFilter: NearestFilter,
|
|
magFilter: NearestFilter
|
|
});
|
|
let outsideRenderTarget2 = new WebGLRenderTarget(clientWidth, clientHeight, {
|
|
minFilter: NearestFilter,
|
|
magFilter: NearestFilter
|
|
});
|
|
let insideRenderTarget2 = new WebGLRenderTarget(clientWidth, clientHeight, {
|
|
minFilter: NearestFilter,
|
|
magFilter: NearestFilter
|
|
});
|
|
let outsideRenderTargetFinal = new WebGLRenderTarget(clientWidth, clientHeight, {
|
|
minFilter: NearestFilter,
|
|
magFilter: NearestFilter,
|
|
type: FloatType,
|
|
format: RedFormat
|
|
});
|
|
let insideRenderTargetFinal = new WebGLRenderTarget(clientWidth, clientHeight, {
|
|
minFilter: NearestFilter,
|
|
magFilter: NearestFilter,
|
|
type: FloatType,
|
|
format: RedFormat
|
|
});
|
|
const uvRender = new FullScreenQuad(new ShaderMaterial({
|
|
uniforms: {
|
|
tex: {
|
|
value: null
|
|
}
|
|
},
|
|
vertexShader: (
|
|
/*glsl*/
|
|
`
|
|
varying vec2 vUv;
|
|
void main() {
|
|
vUv = uv;
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
}`
|
|
),
|
|
fragmentShader: (
|
|
/*glsl*/
|
|
`
|
|
uniform sampler2D tex;
|
|
varying vec2 vUv;
|
|
#include <packing>
|
|
void main() {
|
|
gl_FragColor = pack2HalfToRGBA(vUv * (round(texture2D(tex, vUv).x)));
|
|
}`
|
|
)
|
|
}));
|
|
const uvRenderInside = new FullScreenQuad(new ShaderMaterial({
|
|
uniforms: {
|
|
tex: {
|
|
value: null
|
|
}
|
|
},
|
|
vertexShader: (
|
|
/*glsl*/
|
|
`
|
|
varying vec2 vUv;
|
|
void main() {
|
|
vUv = uv;
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
}`
|
|
),
|
|
fragmentShader: (
|
|
/*glsl*/
|
|
`
|
|
uniform sampler2D tex;
|
|
varying vec2 vUv;
|
|
#include <packing>
|
|
void main() {
|
|
gl_FragColor = pack2HalfToRGBA(vUv * (1.0 - round(texture2D(tex, vUv).x)));
|
|
}`
|
|
)
|
|
}));
|
|
const jumpFloodRender = new FullScreenQuad(new ShaderMaterial({
|
|
uniforms: {
|
|
tex: {
|
|
value: null
|
|
},
|
|
offset: {
|
|
value: 0
|
|
},
|
|
level: {
|
|
value: 0
|
|
},
|
|
maxSteps: {
|
|
value: 0
|
|
}
|
|
},
|
|
vertexShader: (
|
|
/*glsl*/
|
|
`
|
|
varying vec2 vUv;
|
|
void main() {
|
|
vUv = uv;
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
}`
|
|
),
|
|
fragmentShader: (
|
|
/*glsl*/
|
|
`
|
|
varying vec2 vUv;
|
|
uniform sampler2D tex;
|
|
uniform float offset;
|
|
uniform float level;
|
|
uniform float maxSteps;
|
|
#include <packing>
|
|
void main() {
|
|
float closestDist = 9999999.9;
|
|
vec2 closestPos = vec2(0.0);
|
|
for (float x = -1.0; x <= 1.0; x += 1.0) {
|
|
for (float y = -1.0; y <= 1.0; y += 1.0) {
|
|
vec2 voffset = vUv;
|
|
voffset += vec2(x, y) * vec2(${1 / clientWidth}, ${1 / clientHeight}) * offset;
|
|
vec2 pos = unpackRGBATo2Half(texture2D(tex, voffset));
|
|
float dist = distance(pos.xy, vUv);
|
|
if(pos.x != 0.0 && pos.y != 0.0 && dist < closestDist) {
|
|
closestDist = dist;
|
|
closestPos = pos;
|
|
}
|
|
}
|
|
}
|
|
gl_FragColor = pack2HalfToRGBA(closestPos);
|
|
}`
|
|
)
|
|
}));
|
|
const distanceFieldRender = new FullScreenQuad(new ShaderMaterial({
|
|
uniforms: {
|
|
tex: {
|
|
value: null
|
|
},
|
|
size: {
|
|
value: new Vector2(clientWidth, clientHeight)
|
|
}
|
|
},
|
|
vertexShader: (
|
|
/*glsl*/
|
|
`
|
|
varying vec2 vUv;
|
|
void main() {
|
|
vUv = uv;
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
}`
|
|
),
|
|
fragmentShader: (
|
|
/*glsl*/
|
|
`
|
|
varying vec2 vUv;
|
|
uniform sampler2D tex;
|
|
uniform vec2 size;
|
|
#include <packing>
|
|
void main() {
|
|
gl_FragColor = vec4(distance(size * unpackRGBATo2Half(texture2D(tex, vUv)), size * vUv), 0.0, 0.0, 0.0);
|
|
}`
|
|
)
|
|
}));
|
|
const compositeRender = new FullScreenQuad(new ShaderMaterial({
|
|
uniforms: {
|
|
inside: {
|
|
value: insideRenderTargetFinal.texture
|
|
},
|
|
outside: {
|
|
value: outsideRenderTargetFinal.texture
|
|
},
|
|
tex: {
|
|
value: null
|
|
}
|
|
},
|
|
vertexShader: (
|
|
/*glsl*/
|
|
`
|
|
varying vec2 vUv;
|
|
void main() {
|
|
vUv = uv;
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
}`
|
|
),
|
|
fragmentShader: (
|
|
/*glsl*/
|
|
`
|
|
varying vec2 vUv;
|
|
uniform sampler2D inside;
|
|
uniform sampler2D outside;
|
|
uniform sampler2D tex;
|
|
#include <packing>
|
|
void main() {
|
|
float i = texture2D(inside, vUv).x;
|
|
float o =texture2D(outside, vUv).x;
|
|
if (texture2D(tex, vUv).x == 0.0) {
|
|
gl_FragColor = vec4(o, 0.0, 0.0, 0.0);
|
|
} else {
|
|
gl_FragColor = vec4(-i, 0.0, 0.0, 0.0);
|
|
}
|
|
}`
|
|
)
|
|
}));
|
|
return (image) => {
|
|
let ft = finalTarget;
|
|
image.minFilter = NearestFilter;
|
|
image.magFilter = NearestFilter;
|
|
uvRender.material.uniforms.tex.value = image;
|
|
renderer.setRenderTarget(outsideRenderTarget);
|
|
uvRender.render(renderer);
|
|
const passes = Math.ceil(Math.log(Math.max(clientWidth, clientHeight)) / Math.log(2));
|
|
let lastTarget = outsideRenderTarget;
|
|
let target2 = null;
|
|
for (let i3 = 0; i3 < passes; i3++) {
|
|
const offset = Math.pow(2, passes - i3 - 1);
|
|
target2 = lastTarget === outsideRenderTarget ? outsideRenderTarget2 : outsideRenderTarget;
|
|
jumpFloodRender.material.uniforms.level.value = i3;
|
|
jumpFloodRender.material.uniforms.maxSteps.value = passes;
|
|
jumpFloodRender.material.uniforms.offset.value = offset;
|
|
jumpFloodRender.material.uniforms.tex.value = lastTarget.texture;
|
|
renderer.setRenderTarget(target2);
|
|
jumpFloodRender.render(renderer);
|
|
lastTarget = target2;
|
|
}
|
|
renderer.setRenderTarget(outsideRenderTargetFinal);
|
|
distanceFieldRender.material.uniforms.tex.value = target2.texture;
|
|
distanceFieldRender.render(renderer);
|
|
uvRenderInside.material.uniforms.tex.value = image;
|
|
renderer.setRenderTarget(insideRenderTarget);
|
|
uvRenderInside.render(renderer);
|
|
lastTarget = insideRenderTarget;
|
|
for (let i3 = 0; i3 < passes; i3++) {
|
|
const offset = Math.pow(2, passes - i3 - 1);
|
|
target2 = lastTarget === insideRenderTarget ? insideRenderTarget2 : insideRenderTarget;
|
|
jumpFloodRender.material.uniforms.level.value = i3;
|
|
jumpFloodRender.material.uniforms.maxSteps.value = passes;
|
|
jumpFloodRender.material.uniforms.offset.value = offset;
|
|
jumpFloodRender.material.uniforms.tex.value = lastTarget.texture;
|
|
renderer.setRenderTarget(target2);
|
|
jumpFloodRender.render(renderer);
|
|
lastTarget = target2;
|
|
}
|
|
renderer.setRenderTarget(insideRenderTargetFinal);
|
|
distanceFieldRender.material.uniforms.tex.value = target2.texture;
|
|
distanceFieldRender.render(renderer);
|
|
renderer.setRenderTarget(ft);
|
|
compositeRender.material.uniforms.tex.value = image;
|
|
compositeRender.render(renderer);
|
|
renderer.setRenderTarget(null);
|
|
return ft;
|
|
};
|
|
};
|
|
|
|
// node_modules/@react-three/drei/web/View.js
|
|
var React130 = __toESM(require_react());
|
|
|
|
// node_modules/tunnel-rat/dist/index.js
|
|
var import_react22 = __toESM(require_react());
|
|
|
|
// node_modules/tunnel-rat/node_modules/zustand/esm/vanilla.mjs
|
|
var createStoreImpl = (createState) => {
|
|
let state;
|
|
const listeners = /* @__PURE__ */ new Set();
|
|
const setState = (partial, replace) => {
|
|
const nextState = typeof partial === "function" ? partial(state) : partial;
|
|
if (!Object.is(nextState, state)) {
|
|
const previousState = state;
|
|
state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
|
|
listeners.forEach((listener) => listener(state, previousState));
|
|
}
|
|
};
|
|
const getState = () => state;
|
|
const getInitialState = () => initialState;
|
|
const subscribe = (listener) => {
|
|
listeners.add(listener);
|
|
return () => listeners.delete(listener);
|
|
};
|
|
const destroy = () => {
|
|
if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production") {
|
|
console.warn(
|
|
"[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."
|
|
);
|
|
}
|
|
listeners.clear();
|
|
};
|
|
const api = { setState, getState, getInitialState, subscribe, destroy };
|
|
const initialState = state = createState(setState, getState, api);
|
|
return api;
|
|
};
|
|
var createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
|
|
|
|
// node_modules/tunnel-rat/node_modules/zustand/esm/index.mjs
|
|
var import_react21 = __toESM(require_react(), 1);
|
|
var import_with_selector = __toESM(require_with_selector(), 1);
|
|
var { useDebugValue } = import_react21.default;
|
|
var { useSyncExternalStoreWithSelector } = import_with_selector.default;
|
|
var didWarnAboutEqualityFn = false;
|
|
var identity2 = (arg) => arg;
|
|
function useStore(api, selector = identity2, equalityFn) {
|
|
if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production" && equalityFn && !didWarnAboutEqualityFn) {
|
|
console.warn(
|
|
"[DEPRECATED] Use `createWithEqualityFn` instead of `create` or use `useStoreWithEqualityFn` instead of `useStore`. They can be imported from 'zustand/traditional'. https://github.com/pmndrs/zustand/discussions/1937"
|
|
);
|
|
didWarnAboutEqualityFn = true;
|
|
}
|
|
const slice = useSyncExternalStoreWithSelector(
|
|
api.subscribe,
|
|
api.getState,
|
|
api.getServerState || api.getInitialState,
|
|
selector,
|
|
equalityFn
|
|
);
|
|
useDebugValue(slice);
|
|
return slice;
|
|
}
|
|
var createImpl = (createState) => {
|
|
if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production" && typeof createState !== "function") {
|
|
console.warn(
|
|
"[DEPRECATED] Passing a vanilla store will be unsupported in a future version. Instead use `import { useStore } from 'zustand'`."
|
|
);
|
|
}
|
|
const api = typeof createState === "function" ? createStore(createState) : createState;
|
|
const useBoundStore = (selector, equalityFn) => useStore(api, selector, equalityFn);
|
|
Object.assign(useBoundStore, api);
|
|
return useBoundStore;
|
|
};
|
|
var create3 = (createState) => createState ? createImpl(createState) : createImpl;
|
|
|
|
// node_modules/tunnel-rat/dist/index.js
|
|
var _window$document;
|
|
var _window$navigator;
|
|
var useIsomorphicLayoutEffect = typeof window !== "undefined" && ((_window$document = window.document) != null && _window$document.createElement || ((_window$navigator = window.navigator) == null ? void 0 : _window$navigator.product) === "ReactNative") ? import_react22.default.useLayoutEffect : import_react22.default.useEffect;
|
|
function tunnel() {
|
|
const useStore2 = create3((set) => ({
|
|
current: new Array(),
|
|
version: 0,
|
|
set
|
|
}));
|
|
return {
|
|
In: ({
|
|
children
|
|
}) => {
|
|
const set = useStore2((state) => state.set);
|
|
const version3 = useStore2((state) => state.version);
|
|
useIsomorphicLayoutEffect(() => {
|
|
set((state) => ({
|
|
version: state.version + 1
|
|
}));
|
|
}, []);
|
|
useIsomorphicLayoutEffect(() => {
|
|
set(({
|
|
current
|
|
}) => ({
|
|
current: [...current, children]
|
|
}));
|
|
return () => set(({
|
|
current
|
|
}) => ({
|
|
current: current.filter((c2) => c2 !== children)
|
|
}));
|
|
}, [children, version3]);
|
|
return null;
|
|
},
|
|
Out: () => {
|
|
const current = useStore2((state) => state.current);
|
|
return import_react22.default.createElement(import_react22.default.Fragment, null, current);
|
|
}
|
|
};
|
|
}
|
|
|
|
// node_modules/@react-three/drei/web/View.js
|
|
var isOrthographicCamera2 = (def) => def && def.isOrthographicCamera;
|
|
var col2 = new Color();
|
|
var tracked = tunnel();
|
|
function computeContainerPosition(canvasSize, trackRect) {
|
|
const {
|
|
right,
|
|
top,
|
|
left: trackLeft,
|
|
bottom: trackBottom,
|
|
width,
|
|
height
|
|
} = trackRect;
|
|
const isOffscreen = trackRect.bottom < 0 || top > canvasSize.height || right < 0 || trackRect.left > canvasSize.width;
|
|
const canvasBottom = canvasSize.top + canvasSize.height;
|
|
const bottom = canvasBottom - trackBottom;
|
|
const left = trackLeft - canvasSize.left;
|
|
return {
|
|
position: {
|
|
width,
|
|
height,
|
|
left,
|
|
top,
|
|
bottom,
|
|
right
|
|
},
|
|
isOffscreen
|
|
};
|
|
}
|
|
function prepareSkissor(state, {
|
|
left,
|
|
bottom,
|
|
width,
|
|
height
|
|
}) {
|
|
let autoClear;
|
|
const aspect = width / height;
|
|
if (isOrthographicCamera2(state.camera)) {
|
|
if (!state.camera.manual) {
|
|
if (state.camera.left !== width / -2 || state.camera.right !== width / 2 || state.camera.top !== height / 2 || state.camera.bottom !== height / -2) {
|
|
Object.assign(state.camera, {
|
|
left: width / -2,
|
|
right: width / 2,
|
|
top: height / 2,
|
|
bottom: height / -2
|
|
});
|
|
state.camera.updateProjectionMatrix();
|
|
}
|
|
} else {
|
|
state.camera.updateProjectionMatrix();
|
|
}
|
|
} else if (state.camera.aspect !== aspect) {
|
|
state.camera.aspect = aspect;
|
|
state.camera.updateProjectionMatrix();
|
|
}
|
|
autoClear = state.gl.autoClear;
|
|
state.gl.autoClear = false;
|
|
state.gl.setViewport(left, bottom, width, height);
|
|
state.gl.setScissor(left, bottom, width, height);
|
|
state.gl.setScissorTest(true);
|
|
return autoClear;
|
|
}
|
|
function finishSkissor(state, autoClear) {
|
|
state.gl.setScissorTest(false);
|
|
state.gl.autoClear = autoClear;
|
|
}
|
|
function clear2(state) {
|
|
state.gl.getClearColor(col2);
|
|
state.gl.setClearColor(col2, state.gl.getClearAlpha());
|
|
state.gl.clear(true, true);
|
|
}
|
|
function Container3({
|
|
visible = true,
|
|
canvasSize,
|
|
scene,
|
|
index: index2,
|
|
children,
|
|
frames,
|
|
rect,
|
|
track
|
|
}) {
|
|
const rootState = useThree();
|
|
const [isOffscreen, setOffscreen] = React130.useState(false);
|
|
let frameCount = 0;
|
|
useFrame((state) => {
|
|
if (frames === Infinity || frameCount <= frames) {
|
|
var _track$current;
|
|
if (track) rect.current = (_track$current = track.current) == null ? void 0 : _track$current.getBoundingClientRect();
|
|
frameCount++;
|
|
}
|
|
if (rect.current) {
|
|
const {
|
|
position: position2,
|
|
isOffscreen: _isOffscreen
|
|
} = computeContainerPosition(canvasSize, rect.current);
|
|
if (isOffscreen !== _isOffscreen) setOffscreen(_isOffscreen);
|
|
if (visible && !isOffscreen && rect.current) {
|
|
const autoClear = prepareSkissor(state, position2);
|
|
state.gl.render(children ? state.scene : scene, state.camera);
|
|
finishSkissor(state, autoClear);
|
|
}
|
|
}
|
|
}, index2);
|
|
React130.useLayoutEffect(() => {
|
|
const curRect = rect.current;
|
|
if (curRect && (!visible || !isOffscreen)) {
|
|
const {
|
|
position: position2
|
|
} = computeContainerPosition(canvasSize, curRect);
|
|
const autoClear = prepareSkissor(rootState, position2);
|
|
clear2(rootState);
|
|
finishSkissor(rootState, autoClear);
|
|
}
|
|
}, [visible, isOffscreen]);
|
|
React130.useEffect(() => {
|
|
if (!track) return;
|
|
const curRect = rect.current;
|
|
const old = rootState.get().events.connected;
|
|
rootState.setEvents({
|
|
connected: track.current
|
|
});
|
|
return () => {
|
|
if (curRect) {
|
|
const {
|
|
position: position2
|
|
} = computeContainerPosition(canvasSize, curRect);
|
|
const autoClear = prepareSkissor(rootState, position2);
|
|
clear2(rootState);
|
|
finishSkissor(rootState, autoClear);
|
|
}
|
|
rootState.setEvents({
|
|
connected: old
|
|
});
|
|
};
|
|
}, [track]);
|
|
return React130.createElement(React130.Fragment, null, children, React130.createElement("group", {
|
|
onPointerOver: () => null
|
|
}));
|
|
}
|
|
var CanvasView = React130.forwardRef(({
|
|
track,
|
|
visible = true,
|
|
index: index2 = 1,
|
|
id,
|
|
style,
|
|
className,
|
|
frames = Infinity,
|
|
children,
|
|
...props
|
|
}, fref) => {
|
|
var _rect$current, _rect$current2, _rect$current3, _rect$current4;
|
|
const rect = React130.useRef(null);
|
|
const {
|
|
size,
|
|
scene
|
|
} = useThree();
|
|
const [virtualScene] = React130.useState(() => new Scene());
|
|
const [ready, toggle] = React130.useReducer(() => true, false);
|
|
const compute = React130.useCallback((event, state) => {
|
|
if (rect.current && track && track.current && event.target === track.current) {
|
|
const {
|
|
width,
|
|
height,
|
|
left,
|
|
top
|
|
} = rect.current;
|
|
const x = event.clientX - left;
|
|
const y = event.clientY - top;
|
|
state.pointer.set(x / width * 2 - 1, -(y / height) * 2 + 1);
|
|
state.raycaster.setFromCamera(state.pointer, state.camera);
|
|
}
|
|
}, [rect, track]);
|
|
React130.useEffect(() => {
|
|
var _track$current2;
|
|
if (track) rect.current = (_track$current2 = track.current) == null ? void 0 : _track$current2.getBoundingClientRect();
|
|
toggle();
|
|
}, [track]);
|
|
return React130.createElement("group", _extends({
|
|
ref: fref
|
|
}, props), ready && createPortal(React130.createElement(Container3, {
|
|
visible,
|
|
canvasSize: size,
|
|
frames,
|
|
scene,
|
|
track,
|
|
rect,
|
|
index: index2
|
|
}, children), virtualScene, {
|
|
events: {
|
|
compute,
|
|
priority: index2
|
|
},
|
|
size: {
|
|
width: (_rect$current = rect.current) == null ? void 0 : _rect$current.width,
|
|
height: (_rect$current2 = rect.current) == null ? void 0 : _rect$current2.height,
|
|
// @ts-ignore
|
|
top: (_rect$current3 = rect.current) == null ? void 0 : _rect$current3.top,
|
|
// @ts-ignore
|
|
left: (_rect$current4 = rect.current) == null ? void 0 : _rect$current4.left
|
|
}
|
|
}));
|
|
});
|
|
var HtmlView = React130.forwardRef(({
|
|
as: El = "div",
|
|
id,
|
|
visible,
|
|
className,
|
|
style,
|
|
index: index2 = 1,
|
|
track,
|
|
frames = Infinity,
|
|
children,
|
|
...props
|
|
}, fref) => {
|
|
const uuid = React130.useId();
|
|
const ref = React130.useRef(null);
|
|
React130.useImperativeHandle(fref, () => ref.current);
|
|
return React130.createElement(React130.Fragment, null, React130.createElement(El, _extends({
|
|
ref,
|
|
id,
|
|
className,
|
|
style
|
|
}, props)), React130.createElement(tracked.In, null, React130.createElement(CanvasView, {
|
|
visible,
|
|
key: uuid,
|
|
track: ref,
|
|
frames,
|
|
index: index2
|
|
}, children)));
|
|
});
|
|
var View = (() => {
|
|
const _View = React130.forwardRef((props, fref) => {
|
|
const store = React130.useContext(context);
|
|
if (!store) return React130.createElement(HtmlView, _extends({
|
|
ref: fref
|
|
}, props));
|
|
else return React130.createElement(CanvasView, _extends({
|
|
ref: fref
|
|
}, props));
|
|
});
|
|
_View.Port = () => React130.createElement(tracked.Out, null);
|
|
return _View;
|
|
})();
|
|
|
|
// node_modules/@react-three/drei/web/pivotControls/index.js
|
|
var React136 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/web/pivotControls/AxisArrow.js
|
|
var React132 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/web/pivotControls/context.js
|
|
var React131 = __toESM(require_react());
|
|
var context11 = React131.createContext(null);
|
|
|
|
// node_modules/@react-three/drei/web/pivotControls/AxisArrow.js
|
|
var vec1 = new Vector3();
|
|
var vec2 = new Vector3();
|
|
var calculateOffset = (clickPoint, normal2, rayStart, rayDir) => {
|
|
const e1 = normal2.dot(normal2);
|
|
const e2 = normal2.dot(clickPoint) - normal2.dot(rayStart);
|
|
const e3 = normal2.dot(rayDir);
|
|
if (e3 === 0) {
|
|
return -e2 / e1;
|
|
}
|
|
vec1.copy(rayDir).multiplyScalar(e1 / e3).sub(normal2);
|
|
vec2.copy(rayDir).multiplyScalar(e2 / e3).add(rayStart).sub(clickPoint);
|
|
const offset = -vec1.dot(vec2) / vec1.dot(vec1);
|
|
return offset;
|
|
};
|
|
var upV = new Vector3(0, 1, 0);
|
|
var offsetMatrix = new Matrix4();
|
|
var AxisArrow = ({
|
|
direction: direction2,
|
|
axis
|
|
}) => {
|
|
const {
|
|
translation: translation3,
|
|
translationLimits,
|
|
annotations,
|
|
annotationsClass,
|
|
depthTest,
|
|
scale: scale5,
|
|
lineWidth,
|
|
fixed,
|
|
axisColors,
|
|
hoveredColor,
|
|
opacity,
|
|
renderOrder,
|
|
onDragStart,
|
|
onDrag,
|
|
onDragEnd,
|
|
userData
|
|
} = React132.useContext(context11);
|
|
const camControls = useThree((state) => state.controls);
|
|
const divRef = React132.useRef(null);
|
|
const objRef = React132.useRef(null);
|
|
const clickInfo = React132.useRef(null);
|
|
const offset0 = React132.useRef(0);
|
|
const [isHovered, setIsHovered] = React132.useState(false);
|
|
const onPointerDown = React132.useCallback((e2) => {
|
|
if (annotations) {
|
|
divRef.current.innerText = `${translation3.current[axis].toFixed(2)}`;
|
|
divRef.current.style.display = "block";
|
|
}
|
|
e2.stopPropagation();
|
|
const rotation3 = new Matrix4().extractRotation(objRef.current.matrixWorld);
|
|
const clickPoint = e2.point.clone();
|
|
const origin2 = new Vector3().setFromMatrixPosition(objRef.current.matrixWorld);
|
|
const dir = direction2.clone().applyMatrix4(rotation3).normalize();
|
|
clickInfo.current = {
|
|
clickPoint,
|
|
dir
|
|
};
|
|
offset0.current = translation3.current[axis];
|
|
onDragStart({
|
|
component: "Arrow",
|
|
axis,
|
|
origin: origin2,
|
|
directions: [dir]
|
|
});
|
|
camControls && (camControls.enabled = false);
|
|
e2.target.setPointerCapture(e2.pointerId);
|
|
}, [annotations, direction2, camControls, onDragStart, translation3, axis]);
|
|
const onPointerMove = React132.useCallback((e2) => {
|
|
e2.stopPropagation();
|
|
if (!isHovered) setIsHovered(true);
|
|
if (clickInfo.current) {
|
|
const {
|
|
clickPoint,
|
|
dir
|
|
} = clickInfo.current;
|
|
const [min, max] = (translationLimits == null ? void 0 : translationLimits[axis]) || [void 0, void 0];
|
|
let offset = calculateOffset(clickPoint, dir, e2.ray.origin, e2.ray.direction);
|
|
if (min !== void 0) {
|
|
offset = Math.max(offset, min - offset0.current);
|
|
}
|
|
if (max !== void 0) {
|
|
offset = Math.min(offset, max - offset0.current);
|
|
}
|
|
translation3.current[axis] = offset0.current + offset;
|
|
if (annotations) {
|
|
divRef.current.innerText = `${translation3.current[axis].toFixed(2)}`;
|
|
}
|
|
offsetMatrix.makeTranslation(dir.x * offset, dir.y * offset, dir.z * offset);
|
|
onDrag(offsetMatrix);
|
|
}
|
|
}, [annotations, onDrag, isHovered, translation3, translationLimits, axis]);
|
|
const onPointerUp = React132.useCallback((e2) => {
|
|
if (annotations) {
|
|
divRef.current.style.display = "none";
|
|
}
|
|
e2.stopPropagation();
|
|
clickInfo.current = null;
|
|
onDragEnd();
|
|
camControls && (camControls.enabled = true);
|
|
e2.target.releasePointerCapture(e2.pointerId);
|
|
}, [annotations, camControls, onDragEnd]);
|
|
const onPointerOut = React132.useCallback((e2) => {
|
|
e2.stopPropagation();
|
|
setIsHovered(false);
|
|
}, []);
|
|
const {
|
|
cylinderLength,
|
|
coneWidth,
|
|
coneLength,
|
|
matrixL
|
|
} = React132.useMemo(() => {
|
|
const coneWidth2 = fixed ? lineWidth / scale5 * 1.6 : scale5 / 20;
|
|
const coneLength2 = fixed ? 0.2 : scale5 / 5;
|
|
const cylinderLength2 = fixed ? 1 - coneLength2 : scale5 - coneLength2;
|
|
const quaternion = new Quaternion().setFromUnitVectors(upV, direction2.clone().normalize());
|
|
const matrixL2 = new Matrix4().makeRotationFromQuaternion(quaternion);
|
|
return {
|
|
cylinderLength: cylinderLength2,
|
|
coneWidth: coneWidth2,
|
|
coneLength: coneLength2,
|
|
matrixL: matrixL2
|
|
};
|
|
}, [direction2, scale5, lineWidth, fixed]);
|
|
const color_ = isHovered ? hoveredColor : axisColors[axis];
|
|
return React132.createElement("group", {
|
|
ref: objRef
|
|
}, React132.createElement("group", {
|
|
matrix: matrixL,
|
|
matrixAutoUpdate: false,
|
|
onPointerDown,
|
|
onPointerMove,
|
|
onPointerUp,
|
|
onPointerOut
|
|
}, annotations && React132.createElement(Html, {
|
|
position: [0, -coneLength, 0]
|
|
}, React132.createElement("div", {
|
|
style: {
|
|
display: "none",
|
|
background: "#151520",
|
|
color: "white",
|
|
padding: "6px 8px",
|
|
borderRadius: 7,
|
|
whiteSpace: "nowrap"
|
|
},
|
|
className: annotationsClass,
|
|
ref: divRef
|
|
})), React132.createElement("mesh", {
|
|
visible: false,
|
|
position: [0, (cylinderLength + coneLength) / 2, 0],
|
|
userData
|
|
}, React132.createElement("cylinderGeometry", {
|
|
args: [coneWidth * 1.4, coneWidth * 1.4, cylinderLength + coneLength, 8, 1]
|
|
})), React132.createElement(Line, {
|
|
transparent: true,
|
|
raycast: () => null,
|
|
depthTest,
|
|
points: [0, 0, 0, 0, cylinderLength, 0],
|
|
lineWidth,
|
|
side: DoubleSide,
|
|
color: color_,
|
|
opacity,
|
|
polygonOffset: true,
|
|
renderOrder,
|
|
polygonOffsetFactor: -10,
|
|
fog: false
|
|
}), React132.createElement("mesh", {
|
|
raycast: () => null,
|
|
position: [0, cylinderLength + coneLength / 2, 0],
|
|
renderOrder
|
|
}, React132.createElement("coneGeometry", {
|
|
args: [coneWidth, coneLength, 24, 1]
|
|
}), React132.createElement("meshBasicMaterial", {
|
|
transparent: true,
|
|
depthTest,
|
|
color: color_,
|
|
opacity,
|
|
polygonOffset: true,
|
|
polygonOffsetFactor: -10,
|
|
fog: false
|
|
}))));
|
|
};
|
|
|
|
// node_modules/@react-three/drei/web/pivotControls/AxisRotator.js
|
|
var React133 = __toESM(require_react());
|
|
var clickDir = new Vector3();
|
|
var intersectionDir = new Vector3();
|
|
var toDegrees = (radians) => radians * 180 / Math.PI;
|
|
var toRadians = (degrees) => degrees * Math.PI / 180;
|
|
var calculateAngle = (clickPoint, intersectionPoint, origin2, e1, e2) => {
|
|
clickDir.copy(clickPoint).sub(origin2);
|
|
intersectionDir.copy(intersectionPoint).sub(origin2);
|
|
const dote1e1 = e1.dot(e1);
|
|
const dote2e2 = e2.dot(e2);
|
|
const uClick = clickDir.dot(e1) / dote1e1;
|
|
const vClick = clickDir.dot(e2) / dote2e2;
|
|
const uIntersection = intersectionDir.dot(e1) / dote1e1;
|
|
const vIntersection = intersectionDir.dot(e2) / dote2e2;
|
|
const angleClick = Math.atan2(vClick, uClick);
|
|
const angleIntersection = Math.atan2(vIntersection, uIntersection);
|
|
return angleIntersection - angleClick;
|
|
};
|
|
var fmod = (num, denom) => {
|
|
let k = Math.floor(num / denom);
|
|
k = k < 0 ? k + 1 : k;
|
|
return num - k * denom;
|
|
};
|
|
var minimizeAngle = (angle) => {
|
|
let result = fmod(angle, 2 * Math.PI);
|
|
if (Math.abs(result) < 1e-6) {
|
|
return 0;
|
|
}
|
|
if (result < 0) {
|
|
result += 2 * Math.PI;
|
|
}
|
|
return result;
|
|
};
|
|
var rotMatrix = new Matrix4();
|
|
var posNew = new Vector3();
|
|
var ray2 = new Ray();
|
|
var intersection = new Vector3();
|
|
var AxisRotator = ({
|
|
dir1,
|
|
dir2,
|
|
axis
|
|
}) => {
|
|
const {
|
|
rotationLimits,
|
|
annotations,
|
|
annotationsClass,
|
|
depthTest,
|
|
scale: scale5,
|
|
lineWidth,
|
|
fixed,
|
|
axisColors,
|
|
hoveredColor,
|
|
renderOrder,
|
|
opacity,
|
|
onDragStart,
|
|
onDrag,
|
|
onDragEnd,
|
|
userData
|
|
} = React133.useContext(context11);
|
|
const camControls = useThree((state) => state.controls);
|
|
const divRef = React133.useRef(null);
|
|
const objRef = React133.useRef(null);
|
|
const angle0 = React133.useRef(0);
|
|
const angle = React133.useRef(0);
|
|
const clickInfo = React133.useRef(null);
|
|
const [isHovered, setIsHovered] = React133.useState(false);
|
|
const onPointerDown = React133.useCallback((e2) => {
|
|
if (annotations) {
|
|
divRef.current.innerText = `${toDegrees(angle.current).toFixed(0)}º`;
|
|
divRef.current.style.display = "block";
|
|
}
|
|
e2.stopPropagation();
|
|
const clickPoint = e2.point.clone();
|
|
const origin2 = new Vector3().setFromMatrixPosition(objRef.current.matrixWorld);
|
|
const e1 = new Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 0).normalize();
|
|
const e22 = new Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 1).normalize();
|
|
const normal2 = new Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 2).normalize();
|
|
const plane = new Plane().setFromNormalAndCoplanarPoint(normal2, origin2);
|
|
clickInfo.current = {
|
|
clickPoint,
|
|
origin: origin2,
|
|
e1,
|
|
e2: e22,
|
|
normal: normal2,
|
|
plane
|
|
};
|
|
onDragStart({
|
|
component: "Rotator",
|
|
axis,
|
|
origin: origin2,
|
|
directions: [e1, e22, normal2]
|
|
});
|
|
camControls && (camControls.enabled = false);
|
|
e2.target.setPointerCapture(e2.pointerId);
|
|
}, [annotations, camControls, onDragStart, axis]);
|
|
const onPointerMove = React133.useCallback((e2) => {
|
|
e2.stopPropagation();
|
|
if (!isHovered) setIsHovered(true);
|
|
if (clickInfo.current) {
|
|
const {
|
|
clickPoint,
|
|
origin: origin2,
|
|
e1,
|
|
e2: e22,
|
|
normal: normal2,
|
|
plane
|
|
} = clickInfo.current;
|
|
const [min, max] = (rotationLimits == null ? void 0 : rotationLimits[axis]) || [void 0, void 0];
|
|
ray2.copy(e2.ray);
|
|
ray2.intersectPlane(plane, intersection);
|
|
ray2.direction.negate();
|
|
ray2.intersectPlane(plane, intersection);
|
|
let deltaAngle2 = calculateAngle(clickPoint, intersection, origin2, e1, e22);
|
|
let degrees = toDegrees(deltaAngle2);
|
|
if (e2.shiftKey) {
|
|
degrees = Math.round(degrees / 10) * 10;
|
|
deltaAngle2 = toRadians(degrees);
|
|
}
|
|
if (min !== void 0 && max !== void 0 && max - min < 2 * Math.PI) {
|
|
deltaAngle2 = minimizeAngle(deltaAngle2);
|
|
deltaAngle2 = deltaAngle2 > Math.PI ? deltaAngle2 - 2 * Math.PI : deltaAngle2;
|
|
deltaAngle2 = MathUtils.clamp(deltaAngle2, min - angle0.current, max - angle0.current);
|
|
angle.current = angle0.current + deltaAngle2;
|
|
} else {
|
|
angle.current = minimizeAngle(angle0.current + deltaAngle2);
|
|
angle.current = angle.current > Math.PI ? angle.current - 2 * Math.PI : angle.current;
|
|
}
|
|
if (annotations) {
|
|
degrees = toDegrees(angle.current);
|
|
divRef.current.innerText = `${degrees.toFixed(0)}º`;
|
|
}
|
|
rotMatrix.makeRotationAxis(normal2, deltaAngle2);
|
|
posNew.copy(origin2).applyMatrix4(rotMatrix).sub(origin2).negate();
|
|
rotMatrix.setPosition(posNew);
|
|
onDrag(rotMatrix);
|
|
}
|
|
}, [annotations, onDrag, isHovered, rotationLimits, axis]);
|
|
const onPointerUp = React133.useCallback((e2) => {
|
|
if (annotations) {
|
|
divRef.current.style.display = "none";
|
|
}
|
|
e2.stopPropagation();
|
|
angle0.current = angle.current;
|
|
clickInfo.current = null;
|
|
onDragEnd();
|
|
camControls && (camControls.enabled = true);
|
|
e2.target.releasePointerCapture(e2.pointerId);
|
|
}, [annotations, camControls, onDragEnd]);
|
|
const onPointerOut = React133.useCallback((e2) => {
|
|
e2.stopPropagation();
|
|
setIsHovered(false);
|
|
}, []);
|
|
const matrixL = React133.useMemo(() => {
|
|
const dir1N = dir1.clone().normalize();
|
|
const dir2N = dir2.clone().normalize();
|
|
return new Matrix4().makeBasis(dir1N, dir2N, dir1N.clone().cross(dir2N));
|
|
}, [dir1, dir2]);
|
|
const r2 = fixed ? 0.65 : scale5 * 0.65;
|
|
const arc = React133.useMemo(() => {
|
|
const segments = 32;
|
|
const points = [];
|
|
for (let j = 0; j <= segments; j++) {
|
|
const angle2 = j * (Math.PI / 2) / segments;
|
|
points.push(new Vector3(Math.cos(angle2) * r2, Math.sin(angle2) * r2, 0));
|
|
}
|
|
return points;
|
|
}, [r2]);
|
|
return React133.createElement("group", {
|
|
ref: objRef,
|
|
onPointerDown,
|
|
onPointerMove,
|
|
onPointerUp,
|
|
onPointerOut,
|
|
matrix: matrixL,
|
|
matrixAutoUpdate: false
|
|
}, annotations && React133.createElement(Html, {
|
|
position: [r2, r2, 0]
|
|
}, React133.createElement("div", {
|
|
style: {
|
|
display: "none",
|
|
background: "#151520",
|
|
color: "white",
|
|
padding: "6px 8px",
|
|
borderRadius: 7,
|
|
whiteSpace: "nowrap"
|
|
},
|
|
className: annotationsClass,
|
|
ref: divRef
|
|
})), React133.createElement(Line, {
|
|
points: arc,
|
|
lineWidth: lineWidth * 4,
|
|
visible: false,
|
|
userData
|
|
}), React133.createElement(Line, {
|
|
transparent: true,
|
|
raycast: () => null,
|
|
depthTest,
|
|
points: arc,
|
|
lineWidth,
|
|
side: DoubleSide,
|
|
color: isHovered ? hoveredColor : axisColors[axis],
|
|
opacity,
|
|
polygonOffset: true,
|
|
polygonOffsetFactor: -10,
|
|
renderOrder,
|
|
fog: false
|
|
}));
|
|
};
|
|
|
|
// node_modules/@react-three/drei/web/pivotControls/PlaneSlider.js
|
|
var React134 = __toESM(require_react());
|
|
var decomposeIntoBasis = (e1, e2, offset) => {
|
|
const i1 = Math.abs(e1.x) >= Math.abs(e1.y) && Math.abs(e1.x) >= Math.abs(e1.z) ? 0 : Math.abs(e1.y) >= Math.abs(e1.x) && Math.abs(e1.y) >= Math.abs(e1.z) ? 1 : 2;
|
|
const e2DegrowthOrder = [0, 1, 2].sort((a5, b) => Math.abs(e2.getComponent(b)) - Math.abs(e2.getComponent(a5)));
|
|
const i22 = i1 === e2DegrowthOrder[0] ? e2DegrowthOrder[1] : e2DegrowthOrder[0];
|
|
const a1 = e1.getComponent(i1);
|
|
const a22 = e1.getComponent(i22);
|
|
const b1 = e2.getComponent(i1);
|
|
const b22 = e2.getComponent(i22);
|
|
const c1 = offset.getComponent(i1);
|
|
const c2 = offset.getComponent(i22);
|
|
const y = (c2 - c1 * (a22 / a1)) / (b22 - b1 * (a22 / a1));
|
|
const x = (c1 - y * b1) / a1;
|
|
return [x, y];
|
|
};
|
|
var ray3 = new Ray();
|
|
var intersection2 = new Vector3();
|
|
var offsetMatrix2 = new Matrix4();
|
|
var PlaneSlider = ({
|
|
dir1,
|
|
dir2,
|
|
axis
|
|
}) => {
|
|
const {
|
|
translation: translation3,
|
|
translationLimits,
|
|
annotations,
|
|
annotationsClass,
|
|
depthTest,
|
|
scale: scale5,
|
|
lineWidth,
|
|
fixed,
|
|
axisColors,
|
|
hoveredColor,
|
|
opacity,
|
|
renderOrder,
|
|
onDragStart,
|
|
onDrag,
|
|
onDragEnd,
|
|
userData
|
|
} = React134.useContext(context11);
|
|
const camControls = useThree((state) => state.controls);
|
|
const divRef = React134.useRef(null);
|
|
const objRef = React134.useRef(null);
|
|
const clickInfo = React134.useRef(null);
|
|
const offsetX0 = React134.useRef(0);
|
|
const offsetY0 = React134.useRef(0);
|
|
const [isHovered, setIsHovered] = React134.useState(false);
|
|
const onPointerDown = React134.useCallback((e2) => {
|
|
if (annotations) {
|
|
divRef.current.innerText = `${translation3.current[(axis + 1) % 3].toFixed(2)}, ${translation3.current[(axis + 2) % 3].toFixed(2)}`;
|
|
divRef.current.style.display = "block";
|
|
}
|
|
e2.stopPropagation();
|
|
const clickPoint = e2.point.clone();
|
|
const origin2 = new Vector3().setFromMatrixPosition(objRef.current.matrixWorld);
|
|
const e1 = new Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 0).normalize();
|
|
const e22 = new Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 1).normalize();
|
|
const normal2 = new Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 2).normalize();
|
|
const plane = new Plane().setFromNormalAndCoplanarPoint(normal2, origin2);
|
|
clickInfo.current = {
|
|
clickPoint,
|
|
e1,
|
|
e2: e22,
|
|
plane
|
|
};
|
|
offsetX0.current = translation3.current[(axis + 1) % 3];
|
|
offsetY0.current = translation3.current[(axis + 2) % 3];
|
|
onDragStart({
|
|
component: "Slider",
|
|
axis,
|
|
origin: origin2,
|
|
directions: [e1, e22, normal2]
|
|
});
|
|
camControls && (camControls.enabled = false);
|
|
e2.target.setPointerCapture(e2.pointerId);
|
|
}, [annotations, camControls, onDragStart, axis]);
|
|
const onPointerMove = React134.useCallback((e2) => {
|
|
e2.stopPropagation();
|
|
if (!isHovered) setIsHovered(true);
|
|
if (clickInfo.current) {
|
|
const {
|
|
clickPoint,
|
|
e1,
|
|
e2: e22,
|
|
plane
|
|
} = clickInfo.current;
|
|
const [minX, maxX] = (translationLimits == null ? void 0 : translationLimits[(axis + 1) % 3]) || [void 0, void 0];
|
|
const [minY, maxY] = (translationLimits == null ? void 0 : translationLimits[(axis + 2) % 3]) || [void 0, void 0];
|
|
ray3.copy(e2.ray);
|
|
ray3.intersectPlane(plane, intersection2);
|
|
ray3.direction.negate();
|
|
ray3.intersectPlane(plane, intersection2);
|
|
intersection2.sub(clickPoint);
|
|
let [offsetX, offsetY] = decomposeIntoBasis(e1, e22, intersection2);
|
|
if (minX !== void 0) {
|
|
offsetX = Math.max(offsetX, minX - offsetX0.current);
|
|
}
|
|
if (maxX !== void 0) {
|
|
offsetX = Math.min(offsetX, maxX - offsetX0.current);
|
|
}
|
|
if (minY !== void 0) {
|
|
offsetY = Math.max(offsetY, minY - offsetY0.current);
|
|
}
|
|
if (maxY !== void 0) {
|
|
offsetY = Math.min(offsetY, maxY - offsetY0.current);
|
|
}
|
|
translation3.current[(axis + 1) % 3] = offsetX0.current + offsetX;
|
|
translation3.current[(axis + 2) % 3] = offsetY0.current + offsetY;
|
|
if (annotations) {
|
|
divRef.current.innerText = `${translation3.current[(axis + 1) % 3].toFixed(2)}, ${translation3.current[(axis + 2) % 3].toFixed(2)}`;
|
|
}
|
|
offsetMatrix2.makeTranslation(offsetX * e1.x + offsetY * e22.x, offsetX * e1.y + offsetY * e22.y, offsetX * e1.z + offsetY * e22.z);
|
|
onDrag(offsetMatrix2);
|
|
}
|
|
}, [annotations, onDrag, isHovered, translation3, translationLimits, axis]);
|
|
const onPointerUp = React134.useCallback((e2) => {
|
|
if (annotations) {
|
|
divRef.current.style.display = "none";
|
|
}
|
|
e2.stopPropagation();
|
|
clickInfo.current = null;
|
|
onDragEnd();
|
|
camControls && (camControls.enabled = true);
|
|
e2.target.releasePointerCapture(e2.pointerId);
|
|
}, [annotations, camControls, onDragEnd]);
|
|
const onPointerOut = React134.useCallback((e2) => {
|
|
e2.stopPropagation();
|
|
setIsHovered(false);
|
|
}, []);
|
|
const matrixL = React134.useMemo(() => {
|
|
const dir1N = dir1.clone().normalize();
|
|
const dir2N = dir2.clone().normalize();
|
|
return new Matrix4().makeBasis(dir1N, dir2N, dir1N.clone().cross(dir2N));
|
|
}, [dir1, dir2]);
|
|
const pos1 = fixed ? 1 / 7 : scale5 / 7;
|
|
const length3 = fixed ? 0.225 : scale5 * 0.225;
|
|
const color = isHovered ? hoveredColor : axisColors[axis];
|
|
const points = React134.useMemo(() => [new Vector3(0, 0, 0), new Vector3(0, length3, 0), new Vector3(length3, length3, 0), new Vector3(length3, 0, 0), new Vector3(0, 0, 0)], [length3]);
|
|
return React134.createElement("group", {
|
|
ref: objRef,
|
|
matrix: matrixL,
|
|
matrixAutoUpdate: false
|
|
}, annotations && React134.createElement(Html, {
|
|
position: [0, 0, 0]
|
|
}, React134.createElement("div", {
|
|
style: {
|
|
display: "none",
|
|
background: "#151520",
|
|
color: "white",
|
|
padding: "6px 8px",
|
|
borderRadius: 7,
|
|
whiteSpace: "nowrap"
|
|
},
|
|
className: annotationsClass,
|
|
ref: divRef
|
|
})), React134.createElement("group", {
|
|
position: [pos1 * 1.7, pos1 * 1.7, 0]
|
|
}, React134.createElement("mesh", {
|
|
visible: true,
|
|
onPointerDown,
|
|
onPointerMove,
|
|
onPointerUp,
|
|
onPointerOut,
|
|
scale: length3,
|
|
userData,
|
|
renderOrder
|
|
}, React134.createElement("planeGeometry", null), React134.createElement("meshBasicMaterial", {
|
|
transparent: true,
|
|
depthTest,
|
|
color,
|
|
polygonOffset: true,
|
|
polygonOffsetFactor: -10,
|
|
side: DoubleSide,
|
|
fog: false
|
|
})), React134.createElement(Line, {
|
|
position: [-length3 / 2, -length3 / 2, 0],
|
|
transparent: true,
|
|
depthTest,
|
|
points,
|
|
lineWidth,
|
|
color,
|
|
opacity,
|
|
polygonOffset: true,
|
|
polygonOffsetFactor: -10,
|
|
userData,
|
|
fog: false,
|
|
renderOrder
|
|
})));
|
|
};
|
|
|
|
// node_modules/@react-three/drei/web/pivotControls/ScalingSphere.js
|
|
var React135 = __toESM(require_react());
|
|
var vec12 = new Vector3();
|
|
var vec22 = new Vector3();
|
|
var calculateOffset2 = (clickPoint, normal2, rayStart, rayDir) => {
|
|
const e1 = normal2.dot(normal2);
|
|
const e2 = normal2.dot(clickPoint) - normal2.dot(rayStart);
|
|
const e3 = normal2.dot(rayDir);
|
|
if (e3 === 0) {
|
|
return -e2 / e1;
|
|
}
|
|
vec12.copy(rayDir).multiplyScalar(e1 / e3).sub(normal2);
|
|
vec22.copy(rayDir).multiplyScalar(e2 / e3).add(rayStart).sub(clickPoint);
|
|
const offset = -vec12.dot(vec22) / vec12.dot(vec12);
|
|
return offset;
|
|
};
|
|
var upV2 = new Vector3(0, 1, 0);
|
|
var scaleV = new Vector3();
|
|
var scaleMatrix = new Matrix4();
|
|
var ScalingSphere = ({
|
|
direction: direction2,
|
|
axis
|
|
}) => {
|
|
const {
|
|
scaleLimits,
|
|
annotations,
|
|
annotationsClass,
|
|
depthTest,
|
|
scale: scale5,
|
|
lineWidth,
|
|
fixed,
|
|
axisColors,
|
|
hoveredColor,
|
|
opacity,
|
|
renderOrder,
|
|
onDragStart,
|
|
onDrag,
|
|
onDragEnd,
|
|
userData
|
|
} = React135.useContext(context11);
|
|
const size = useThree((state) => state.size);
|
|
const camControls = useThree((state) => state.controls);
|
|
const divRef = React135.useRef(null);
|
|
const objRef = React135.useRef(null);
|
|
const meshRef = React135.useRef(null);
|
|
const scale0 = React135.useRef(1);
|
|
const scaleCur = React135.useRef(1);
|
|
const clickInfo = React135.useRef(null);
|
|
const [isHovered, setIsHovered] = React135.useState(false);
|
|
const position2 = fixed ? 1.2 : 1.2 * scale5;
|
|
const onPointerDown = React135.useCallback((e2) => {
|
|
if (annotations) {
|
|
divRef.current.innerText = `${scaleCur.current.toFixed(2)}`;
|
|
divRef.current.style.display = "block";
|
|
}
|
|
e2.stopPropagation();
|
|
const rotation3 = new Matrix4().extractRotation(objRef.current.matrixWorld);
|
|
const clickPoint = e2.point.clone();
|
|
const origin2 = new Vector3().setFromMatrixPosition(objRef.current.matrixWorld);
|
|
const dir = direction2.clone().applyMatrix4(rotation3).normalize();
|
|
const mPLG = objRef.current.matrixWorld.clone();
|
|
const mPLGInv = mPLG.clone().invert();
|
|
const offsetMultiplier = fixed ? 1 / calculateScaleFactor(objRef.current.getWorldPosition(vec12), scale5, e2.camera, size) : 1;
|
|
clickInfo.current = {
|
|
clickPoint,
|
|
dir,
|
|
mPLG,
|
|
mPLGInv,
|
|
offsetMultiplier
|
|
};
|
|
onDragStart({
|
|
component: "Sphere",
|
|
axis,
|
|
origin: origin2,
|
|
directions: [dir]
|
|
});
|
|
camControls && (camControls.enabled = false);
|
|
e2.target.setPointerCapture(e2.pointerId);
|
|
}, [annotations, camControls, direction2, onDragStart, axis, fixed, scale5, size]);
|
|
const onPointerMove = React135.useCallback((e2) => {
|
|
e2.stopPropagation();
|
|
if (!isHovered) setIsHovered(true);
|
|
if (clickInfo.current) {
|
|
const {
|
|
clickPoint,
|
|
dir,
|
|
mPLG,
|
|
mPLGInv,
|
|
offsetMultiplier
|
|
} = clickInfo.current;
|
|
const [min, max] = (scaleLimits == null ? void 0 : scaleLimits[axis]) || [1e-5, void 0];
|
|
const offsetW = calculateOffset2(clickPoint, dir, e2.ray.origin, e2.ray.direction);
|
|
const offsetL = offsetW * offsetMultiplier;
|
|
const offsetH = fixed ? offsetL : offsetL / scale5;
|
|
let upscale = Math.pow(2, offsetH * 0.2);
|
|
if (e2.shiftKey) {
|
|
upscale = Math.round(upscale * 10) / 10;
|
|
}
|
|
upscale = Math.max(upscale, min / scale0.current);
|
|
if (max !== void 0) {
|
|
upscale = Math.min(upscale, max / scale0.current);
|
|
}
|
|
scaleCur.current = scale0.current * upscale;
|
|
meshRef.current.position.set(0, position2 + offsetL, 0);
|
|
if (annotations) {
|
|
divRef.current.innerText = `${scaleCur.current.toFixed(2)}`;
|
|
}
|
|
scaleV.set(1, 1, 1);
|
|
scaleV.setComponent(axis, upscale);
|
|
scaleMatrix.makeScale(scaleV.x, scaleV.y, scaleV.z).premultiply(mPLG).multiply(mPLGInv);
|
|
onDrag(scaleMatrix);
|
|
}
|
|
}, [annotations, position2, onDrag, isHovered, scaleLimits, axis]);
|
|
const onPointerUp = React135.useCallback((e2) => {
|
|
if (annotations) {
|
|
divRef.current.style.display = "none";
|
|
}
|
|
e2.stopPropagation();
|
|
scale0.current = scaleCur.current;
|
|
clickInfo.current = null;
|
|
meshRef.current.position.set(0, position2, 0);
|
|
onDragEnd();
|
|
camControls && (camControls.enabled = true);
|
|
e2.target.releasePointerCapture(e2.pointerId);
|
|
}, [annotations, camControls, onDragEnd, position2]);
|
|
const onPointerOut = React135.useCallback((e2) => {
|
|
e2.stopPropagation();
|
|
setIsHovered(false);
|
|
}, []);
|
|
const {
|
|
radius,
|
|
matrixL
|
|
} = React135.useMemo(() => {
|
|
const radius2 = fixed ? lineWidth / scale5 * 1.8 : scale5 / 22.5;
|
|
const quaternion = new Quaternion().setFromUnitVectors(upV2, direction2.clone().normalize());
|
|
const matrixL2 = new Matrix4().makeRotationFromQuaternion(quaternion);
|
|
return {
|
|
radius: radius2,
|
|
matrixL: matrixL2
|
|
};
|
|
}, [direction2, scale5, lineWidth, fixed]);
|
|
const color = isHovered ? hoveredColor : axisColors[axis];
|
|
return React135.createElement("group", {
|
|
ref: objRef
|
|
}, React135.createElement("group", {
|
|
matrix: matrixL,
|
|
matrixAutoUpdate: false,
|
|
onPointerDown,
|
|
onPointerMove,
|
|
onPointerUp,
|
|
onPointerOut
|
|
}, annotations && React135.createElement(Html, {
|
|
position: [0, position2 / 2, 0]
|
|
}, React135.createElement("div", {
|
|
style: {
|
|
display: "none",
|
|
background: "#151520",
|
|
color: "white",
|
|
padding: "6px 8px",
|
|
borderRadius: 7,
|
|
whiteSpace: "nowrap"
|
|
},
|
|
className: annotationsClass,
|
|
ref: divRef
|
|
})), React135.createElement("mesh", {
|
|
ref: meshRef,
|
|
position: [0, position2, 0],
|
|
renderOrder,
|
|
userData
|
|
}, React135.createElement("sphereGeometry", {
|
|
args: [radius, 12, 12]
|
|
}), React135.createElement("meshBasicMaterial", {
|
|
transparent: true,
|
|
depthTest,
|
|
color,
|
|
opacity,
|
|
polygonOffset: true,
|
|
polygonOffsetFactor: -10
|
|
}))));
|
|
};
|
|
|
|
// node_modules/@react-three/drei/web/pivotControls/index.js
|
|
var mL0 = new Matrix4();
|
|
var mW0 = new Matrix4();
|
|
var mP = new Matrix4();
|
|
var mPInv = new Matrix4();
|
|
var mW = new Matrix4();
|
|
var mL = new Matrix4();
|
|
var mL0Inv = new Matrix4();
|
|
var mdL = new Matrix4();
|
|
var mG = new Matrix4();
|
|
var bb = new Box3();
|
|
var bbObj = new Box3();
|
|
var vCenter = new Vector3();
|
|
var vSize = new Vector3();
|
|
var vAnchorOffset = new Vector3();
|
|
var vPosition = new Vector3();
|
|
var vScale = new Vector3();
|
|
var xDir = new Vector3(1, 0, 0);
|
|
var yDir = new Vector3(0, 1, 0);
|
|
var zDir = new Vector3(0, 0, 1);
|
|
var PivotControls = React136.forwardRef(({
|
|
enabled = true,
|
|
matrix: matrix4,
|
|
onDragStart,
|
|
onDrag,
|
|
onDragEnd,
|
|
autoTransform = true,
|
|
anchor,
|
|
disableAxes = false,
|
|
disableSliders = false,
|
|
disableRotations = false,
|
|
disableScaling = false,
|
|
activeAxes = [true, true, true],
|
|
offset = [0, 0, 0],
|
|
rotation: rotation3 = [0, 0, 0],
|
|
scale: scale5 = 1,
|
|
lineWidth = 4,
|
|
fixed = false,
|
|
translationLimits,
|
|
rotationLimits,
|
|
scaleLimits,
|
|
depthTest = true,
|
|
renderOrder = 500,
|
|
axisColors = ["#ff2060", "#20df80", "#2080ff"],
|
|
hoveredColor = "#ffff40",
|
|
annotations = false,
|
|
annotationsClass,
|
|
opacity = 1,
|
|
visible = true,
|
|
userData,
|
|
children,
|
|
...props
|
|
}, fRef) => {
|
|
const invalidate = useThree((state) => state.invalidate);
|
|
const parentRef = React136.useRef(null);
|
|
const ref = React136.useRef(null);
|
|
const gizmoRef = React136.useRef(null);
|
|
const childrenRef = React136.useRef(null);
|
|
const translation3 = React136.useRef([0, 0, 0]);
|
|
const cameraScale = React136.useRef(new Vector3(1, 1, 1));
|
|
const gizmoScale = React136.useRef(new Vector3(1, 1, 1));
|
|
React136.useLayoutEffect(() => {
|
|
if (!anchor) return;
|
|
childrenRef.current.updateWorldMatrix(true, true);
|
|
mPInv.copy(childrenRef.current.matrixWorld).invert();
|
|
bb.makeEmpty();
|
|
childrenRef.current.traverse((obj) => {
|
|
if (!obj.geometry) return;
|
|
if (!obj.geometry.boundingBox) obj.geometry.computeBoundingBox();
|
|
mL.copy(obj.matrixWorld).premultiply(mPInv);
|
|
bbObj.copy(obj.geometry.boundingBox);
|
|
bbObj.applyMatrix4(mL);
|
|
bb.union(bbObj);
|
|
});
|
|
vCenter.copy(bb.max).add(bb.min).multiplyScalar(0.5);
|
|
vSize.copy(bb.max).sub(bb.min).multiplyScalar(0.5);
|
|
vAnchorOffset.copy(vSize).multiply(new Vector3(...anchor)).add(vCenter);
|
|
vPosition.set(...offset).add(vAnchorOffset);
|
|
gizmoRef.current.position.copy(vPosition);
|
|
invalidate();
|
|
});
|
|
const config = React136.useMemo(() => ({
|
|
onDragStart: (props2) => {
|
|
mL0.copy(ref.current.matrix);
|
|
mW0.copy(ref.current.matrixWorld);
|
|
onDragStart && onDragStart(props2);
|
|
invalidate();
|
|
},
|
|
onDrag: (mdW) => {
|
|
mP.copy(parentRef.current.matrixWorld);
|
|
mPInv.copy(mP).invert();
|
|
mW.copy(mW0).premultiply(mdW);
|
|
mL.copy(mW).premultiply(mPInv);
|
|
mL0Inv.copy(mL0).invert();
|
|
mdL.copy(mL).multiply(mL0Inv);
|
|
if (autoTransform) {
|
|
ref.current.matrix.copy(mL);
|
|
}
|
|
onDrag && onDrag(mL, mdL, mW, mdW);
|
|
invalidate();
|
|
},
|
|
onDragEnd: () => {
|
|
if (onDragEnd) onDragEnd();
|
|
invalidate();
|
|
},
|
|
translation: translation3,
|
|
translationLimits,
|
|
rotationLimits,
|
|
axisColors,
|
|
hoveredColor,
|
|
opacity,
|
|
scale: scale5,
|
|
lineWidth,
|
|
fixed,
|
|
depthTest,
|
|
renderOrder,
|
|
userData,
|
|
annotations,
|
|
annotationsClass
|
|
}), [onDragStart, onDrag, onDragEnd, translation3, translationLimits, rotationLimits, scaleLimits, depthTest, scale5, lineWidth, fixed, ...axisColors, hoveredColor, opacity, userData, autoTransform, annotations, annotationsClass]);
|
|
const vec = new Vector3();
|
|
useFrame((state) => {
|
|
if (fixed) {
|
|
const sf = calculateScaleFactor(gizmoRef.current.getWorldPosition(vec), scale5, state.camera, state.size);
|
|
cameraScale.current.setScalar(sf);
|
|
}
|
|
if (matrix4 && matrix4 instanceof Matrix4) {
|
|
ref.current.matrix = matrix4;
|
|
}
|
|
ref.current.updateWorldMatrix(true, true);
|
|
mG.makeRotationFromEuler(gizmoRef.current.rotation).setPosition(gizmoRef.current.position).premultiply(ref.current.matrixWorld);
|
|
gizmoScale.current.setFromMatrixScale(mG);
|
|
vScale.copy(cameraScale.current).divide(gizmoScale.current);
|
|
if (Math.abs(gizmoRef.current.scale.x - vScale.x) > 1e-4 || Math.abs(gizmoRef.current.scale.y - vScale.y) > 1e-4 || Math.abs(gizmoRef.current.scale.z - vScale.z) > 1e-4) {
|
|
gizmoRef.current.scale.copy(vScale);
|
|
state.invalidate();
|
|
}
|
|
});
|
|
React136.useImperativeHandle(fRef, () => ref.current, []);
|
|
return React136.createElement(context11.Provider, {
|
|
value: config
|
|
}, React136.createElement("group", {
|
|
ref: parentRef
|
|
}, React136.createElement("group", _extends({
|
|
ref,
|
|
matrix: matrix4,
|
|
matrixAutoUpdate: false
|
|
}, props), React136.createElement("group", {
|
|
visible,
|
|
ref: gizmoRef,
|
|
position: offset,
|
|
rotation: rotation3
|
|
}, enabled && React136.createElement(React136.Fragment, null, !disableAxes && activeAxes[0] && React136.createElement(AxisArrow, {
|
|
axis: 0,
|
|
direction: xDir
|
|
}), !disableAxes && activeAxes[1] && React136.createElement(AxisArrow, {
|
|
axis: 1,
|
|
direction: yDir
|
|
}), !disableAxes && activeAxes[2] && React136.createElement(AxisArrow, {
|
|
axis: 2,
|
|
direction: zDir
|
|
}), !disableSliders && activeAxes[0] && activeAxes[1] && React136.createElement(PlaneSlider, {
|
|
axis: 2,
|
|
dir1: xDir,
|
|
dir2: yDir
|
|
}), !disableSliders && activeAxes[0] && activeAxes[2] && React136.createElement(PlaneSlider, {
|
|
axis: 1,
|
|
dir1: zDir,
|
|
dir2: xDir
|
|
}), !disableSliders && activeAxes[2] && activeAxes[1] && React136.createElement(PlaneSlider, {
|
|
axis: 0,
|
|
dir1: yDir,
|
|
dir2: zDir
|
|
}), !disableRotations && activeAxes[0] && activeAxes[1] && React136.createElement(AxisRotator, {
|
|
axis: 2,
|
|
dir1: xDir,
|
|
dir2: yDir
|
|
}), !disableRotations && activeAxes[0] && activeAxes[2] && React136.createElement(AxisRotator, {
|
|
axis: 1,
|
|
dir1: zDir,
|
|
dir2: xDir
|
|
}), !disableRotations && activeAxes[2] && activeAxes[1] && React136.createElement(AxisRotator, {
|
|
axis: 0,
|
|
dir1: yDir,
|
|
dir2: zDir
|
|
}), !disableScaling && activeAxes[0] && React136.createElement(ScalingSphere, {
|
|
axis: 0,
|
|
direction: xDir
|
|
}), !disableScaling && activeAxes[1] && React136.createElement(ScalingSphere, {
|
|
axis: 1,
|
|
direction: yDir
|
|
}), !disableScaling && activeAxes[2] && React136.createElement(ScalingSphere, {
|
|
axis: 2,
|
|
direction: zDir
|
|
}))), React136.createElement("group", {
|
|
ref: childrenRef
|
|
}, children))));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/web/ScreenVideoTexture.js
|
|
var React137 = __toESM(require_react());
|
|
var import_react23 = __toESM(require_react());
|
|
var ScreenVideoTexture = (0, import_react23.forwardRef)(({
|
|
options = {
|
|
video: true
|
|
},
|
|
...props
|
|
}, fref) => {
|
|
const mediaStream = suspend(() => navigator.mediaDevices.getDisplayMedia(options), []);
|
|
(0, import_react23.useEffect)(() => {
|
|
return () => {
|
|
mediaStream == null || mediaStream.getTracks().forEach((track) => track.stop());
|
|
clear([]);
|
|
};
|
|
}, [mediaStream]);
|
|
return React137.createElement(VideoTexture2, _extends({
|
|
ref: fref
|
|
}, props, {
|
|
src: mediaStream
|
|
}));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/web/WebcamVideoTexture.js
|
|
var React138 = __toESM(require_react());
|
|
var import_react24 = __toESM(require_react());
|
|
var WebcamVideoTexture = (0, import_react24.forwardRef)(({
|
|
constraints = {
|
|
audio: false,
|
|
video: {
|
|
facingMode: "user"
|
|
}
|
|
},
|
|
...props
|
|
}, fref) => {
|
|
const mediaStream = suspend(() => navigator.mediaDevices.getUserMedia(constraints), []);
|
|
(0, import_react24.useEffect)(() => {
|
|
return () => {
|
|
mediaStream == null || mediaStream.getTracks().forEach((track) => track.stop());
|
|
clear([]);
|
|
};
|
|
}, [mediaStream]);
|
|
return React138.createElement(VideoTexture2, _extends({
|
|
ref: fref
|
|
}, props, {
|
|
src: mediaStream
|
|
}));
|
|
});
|
|
|
|
// node_modules/@react-three/drei/web/FaceControls.js
|
|
var React141 = __toESM(require_react());
|
|
var import_react26 = __toESM(require_react());
|
|
|
|
// node_modules/@react-three/drei/web/Facemesh.js
|
|
var React139 = __toESM(require_react());
|
|
var defaultLookAt = new Vector3(0, 0, -1);
|
|
var normal = (function() {
|
|
const a5 = new Vector3();
|
|
const b = new Vector3();
|
|
const c2 = new Vector3();
|
|
const ab = new Vector3();
|
|
const ac = new Vector3();
|
|
return function(v12, v22, v32, v5) {
|
|
a5.copy(v12);
|
|
b.copy(v22);
|
|
c2.copy(v32);
|
|
ab.copy(b).sub(a5);
|
|
ac.copy(c2).sub(a5);
|
|
return v5.crossVectors(ac, ab).normalize();
|
|
};
|
|
})();
|
|
function mean(v12, v22) {
|
|
return v12.clone().add(v22).multiplyScalar(0.5);
|
|
}
|
|
var Facemesh = React139.forwardRef(({
|
|
points = FacemeshDatas.SAMPLE_FACELANDMARKER_RESULT.faceLandmarks[0],
|
|
face,
|
|
facialTransformationMatrix,
|
|
faceBlendshapes,
|
|
offset,
|
|
offsetScalar = 80,
|
|
width,
|
|
height,
|
|
depth = 1,
|
|
verticalTri = [159, 386, 152],
|
|
origin: origin2,
|
|
eyes = true,
|
|
eyesAsOrigin = false,
|
|
debug = false,
|
|
children,
|
|
...props
|
|
}, fref) => {
|
|
var _meshRef$current3;
|
|
if (face) {
|
|
points = face.keypoints;
|
|
console.warn("Facemesh `face` prop is deprecated: use `points` instead");
|
|
}
|
|
const offsetRef = React139.useRef(null);
|
|
const scaleRef = React139.useRef(null);
|
|
const originRef = React139.useRef(null);
|
|
const outerRef = React139.useRef(null);
|
|
const meshRef = React139.useRef(null);
|
|
const eyeRightRef = React139.useRef(null);
|
|
const eyeLeftRef = React139.useRef(null);
|
|
const [sightDir] = React139.useState(() => new Vector3());
|
|
const [transform] = React139.useState(() => new Object3D());
|
|
const [sightDirQuaternion] = React139.useState(() => new Quaternion());
|
|
const [_origin] = React139.useState(() => new Vector3());
|
|
const {
|
|
invalidate
|
|
} = useThree();
|
|
React139.useEffect(() => {
|
|
var _meshRef$current;
|
|
(_meshRef$current = meshRef.current) == null || _meshRef$current.geometry.setIndex(FacemeshDatas.TRIANGULATION);
|
|
}, []);
|
|
const [bboxSize] = React139.useState(() => new Vector3());
|
|
React139.useEffect(() => {
|
|
var _meshRef$current2, _outerRef$current;
|
|
const faceGeometry = (_meshRef$current2 = meshRef.current) == null ? void 0 : _meshRef$current2.geometry;
|
|
if (!faceGeometry) return;
|
|
faceGeometry.setFromPoints(points);
|
|
faceGeometry.setDrawRange(0, FacemeshDatas.TRIANGULATION.length);
|
|
if (facialTransformationMatrix) {
|
|
transform.matrix.fromArray(facialTransformationMatrix.data);
|
|
transform.matrix.decompose(transform.position, transform.quaternion, transform.scale);
|
|
transform.rotation.y *= -1;
|
|
transform.rotation.z *= -1;
|
|
sightDirQuaternion.setFromEuler(transform.rotation);
|
|
if (offset) {
|
|
var _offsetRef$current;
|
|
transform.position.y *= -1;
|
|
transform.position.z *= -1;
|
|
(_offsetRef$current = offsetRef.current) == null || _offsetRef$current.position.copy(transform.position.divideScalar(offsetScalar));
|
|
} else {
|
|
var _offsetRef$current2;
|
|
(_offsetRef$current2 = offsetRef.current) == null || _offsetRef$current2.position.set(0, 0, 0);
|
|
}
|
|
} else {
|
|
normal(points[verticalTri[0]], points[verticalTri[1]], points[verticalTri[2]], sightDir);
|
|
sightDirQuaternion.setFromUnitVectors(defaultLookAt, sightDir);
|
|
}
|
|
const sightDirQuaternionInverse = sightDirQuaternion.clone().invert();
|
|
faceGeometry.computeBoundingBox();
|
|
if (debug) invalidate();
|
|
faceGeometry.center();
|
|
faceGeometry.applyQuaternion(sightDirQuaternionInverse);
|
|
(_outerRef$current = outerRef.current) == null || _outerRef$current.setRotationFromQuaternion(sightDirQuaternion);
|
|
if (eyes) {
|
|
if (!faceBlendshapes) {
|
|
console.warn("Facemesh `eyes` option only works if `faceBlendshapes` is provided: skipping.");
|
|
} else {
|
|
if (eyeRightRef.current && eyeLeftRef.current && originRef.current) {
|
|
if (eyesAsOrigin) {
|
|
const eyeRightSphere = eyeRightRef.current._computeSphere(faceGeometry);
|
|
const eyeLeftSphere = eyeLeftRef.current._computeSphere(faceGeometry);
|
|
const eyesCenter = mean(eyeRightSphere.center, eyeLeftSphere.center);
|
|
origin2 = eyesCenter.negate();
|
|
eyeRightRef.current._update(faceGeometry, faceBlendshapes, eyeRightSphere);
|
|
eyeLeftRef.current._update(faceGeometry, faceBlendshapes, eyeLeftSphere);
|
|
} else {
|
|
eyeRightRef.current._update(faceGeometry, faceBlendshapes);
|
|
eyeLeftRef.current._update(faceGeometry, faceBlendshapes);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (originRef.current) {
|
|
if (origin2 !== void 0) {
|
|
if (typeof origin2 === "number") {
|
|
const position2 = faceGeometry.getAttribute("position");
|
|
_origin.set(-position2.getX(origin2), -position2.getY(origin2), -position2.getZ(origin2));
|
|
} else if (origin2.isVector3) {
|
|
_origin.copy(origin2);
|
|
}
|
|
} else {
|
|
_origin.setScalar(0);
|
|
}
|
|
originRef.current.position.copy(_origin);
|
|
}
|
|
if (scaleRef.current) {
|
|
let scale5 = 1;
|
|
if (width || height || depth) {
|
|
faceGeometry.boundingBox.getSize(bboxSize);
|
|
if (width) scale5 = width / bboxSize.x;
|
|
if (height) scale5 = height / bboxSize.y;
|
|
if (depth) scale5 = depth / bboxSize.z;
|
|
}
|
|
scaleRef.current.scale.setScalar(scale5 !== 1 ? scale5 : 1);
|
|
}
|
|
faceGeometry.computeVertexNormals();
|
|
faceGeometry.attributes.position.needsUpdate = true;
|
|
}, [points, facialTransformationMatrix, faceBlendshapes, transform, offset, offsetScalar, width, height, depth, verticalTri, origin2, eyes, debug, invalidate, sightDir, sightDirQuaternion, bboxSize, _origin]);
|
|
const api = React139.useMemo(() => ({
|
|
outerRef,
|
|
meshRef,
|
|
eyeRightRef,
|
|
eyeLeftRef
|
|
}), []);
|
|
React139.useImperativeHandle(fref, () => api, [api]);
|
|
const [meshBboxSize] = React139.useState(() => new Vector3());
|
|
const bbox = (_meshRef$current3 = meshRef.current) == null ? void 0 : _meshRef$current3.geometry.boundingBox;
|
|
const one3 = (bbox == null ? void 0 : bbox.getSize(meshBboxSize).z) || 1;
|
|
return React139.createElement("group", props, React139.createElement("group", {
|
|
ref: offsetRef
|
|
}, React139.createElement("group", {
|
|
ref: outerRef
|
|
}, React139.createElement("group", {
|
|
ref: scaleRef
|
|
}, debug ? React139.createElement(React139.Fragment, null, React139.createElement("axesHelper", {
|
|
args: [one3]
|
|
}), React139.createElement(Line, {
|
|
points: [[0, 0, 0], [0, 0, -one3]],
|
|
color: 65535
|
|
})) : null, React139.createElement("group", {
|
|
ref: originRef
|
|
}, eyes && faceBlendshapes && React139.createElement("group", {
|
|
name: "eyes"
|
|
}, React139.createElement(FacemeshEye, {
|
|
side: "left",
|
|
ref: eyeRightRef,
|
|
debug
|
|
}), React139.createElement(FacemeshEye, {
|
|
side: "right",
|
|
ref: eyeLeftRef,
|
|
debug
|
|
})), React139.createElement("mesh", {
|
|
ref: meshRef,
|
|
name: "face"
|
|
}, children, debug ? React139.createElement(React139.Fragment, null, bbox && React139.createElement("box3Helper", {
|
|
args: [bbox]
|
|
})) : null))))));
|
|
});
|
|
var FacemeshEyeDefaults = {
|
|
contourLandmarks: {
|
|
right: [33, 133, 159, 145, 153],
|
|
left: [263, 362, 386, 374, 380]
|
|
},
|
|
blendshapes: {
|
|
right: [14, 16, 18, 12],
|
|
// lookIn,lookOut, lookUp,lookDown
|
|
left: [13, 15, 17, 11]
|
|
// lookIn,lookOut, lookUp,lookDown
|
|
},
|
|
color: {
|
|
right: "red",
|
|
left: "#00ff00"
|
|
},
|
|
fov: {
|
|
horizontal: 100,
|
|
vertical: 90
|
|
}
|
|
};
|
|
var FacemeshEye = React139.forwardRef(({
|
|
side,
|
|
debug = true
|
|
}, fref) => {
|
|
const eyeMeshRef = React139.useRef(null);
|
|
const irisDirRef = React139.useRef(null);
|
|
const [sphere] = React139.useState(() => new Sphere());
|
|
const _computeSphere = React139.useCallback((faceGeometry) => {
|
|
const position2 = faceGeometry.getAttribute("position");
|
|
const eyeContourLandmarks = FacemeshEyeDefaults.contourLandmarks[side];
|
|
const eyeContourPoints = eyeContourLandmarks.map((i3) => new Vector3(position2.getX(i3), position2.getY(i3), position2.getZ(i3)));
|
|
sphere.center.set(0, 0, 0);
|
|
eyeContourPoints.forEach((v5) => sphere.center.add(v5));
|
|
sphere.center.divideScalar(eyeContourPoints.length);
|
|
sphere.radius = eyeContourPoints[0].sub(eyeContourPoints[1]).length() / 2;
|
|
return sphere;
|
|
}, [sphere, side]);
|
|
const [rotation3] = React139.useState(() => new Euler());
|
|
const _update = React139.useCallback((faceGeometry, faceBlendshapes, sphere2) => {
|
|
if (eyeMeshRef.current) {
|
|
var _sphere4;
|
|
(_sphere4 = sphere2) !== null && _sphere4 !== void 0 ? _sphere4 : sphere2 = _computeSphere(faceGeometry);
|
|
eyeMeshRef.current.position.copy(sphere2.center);
|
|
eyeMeshRef.current.scale.setScalar(sphere2.radius);
|
|
}
|
|
if (faceBlendshapes && irisDirRef.current) {
|
|
const blendshapes = FacemeshEyeDefaults.blendshapes[side];
|
|
const lookIn = faceBlendshapes.categories[blendshapes[0]].score;
|
|
const lookOut = faceBlendshapes.categories[blendshapes[1]].score;
|
|
const lookUp = faceBlendshapes.categories[blendshapes[2]].score;
|
|
const lookDown = faceBlendshapes.categories[blendshapes[3]].score;
|
|
const hfov = FacemeshEyeDefaults.fov.horizontal * MathUtils.DEG2RAD;
|
|
const vfov = FacemeshEyeDefaults.fov.vertical * MathUtils.DEG2RAD;
|
|
const rx = hfov * 0.5 * (lookDown - lookUp);
|
|
const ry = vfov * 0.5 * (lookIn - lookOut) * (side === "left" ? 1 : -1);
|
|
rotation3.set(rx, ry, 0);
|
|
irisDirRef.current.setRotationFromEuler(rotation3);
|
|
}
|
|
}, [_computeSphere, side, rotation3]);
|
|
const api = React139.useMemo(() => ({
|
|
eyeMeshRef,
|
|
irisDirRef,
|
|
_computeSphere,
|
|
_update
|
|
}), [_computeSphere, _update]);
|
|
React139.useImperativeHandle(fref, () => api, [api]);
|
|
const color = FacemeshEyeDefaults.color[side];
|
|
return React139.createElement("group", null, React139.createElement("group", {
|
|
ref: eyeMeshRef
|
|
}, debug && React139.createElement("axesHelper", null), React139.createElement("group", {
|
|
ref: irisDirRef
|
|
}, React139.createElement(React139.Fragment, null, debug && React139.createElement(Line, {
|
|
points: [[0, 0, 0], [0, 0, -2]],
|
|
lineWidth: 1,
|
|
color
|
|
})))));
|
|
});
|
|
var FacemeshDatas = {
|
|
// Extracted from: https://github.com/tensorflow/tfjs-models/blob/a8f500809f5afe38feea27870c77e7ba03a6ece4/face-landmarks-detection/demos/shared/triangulation.js
|
|
// prettier-ignore
|
|
TRIANGULATION: [127, 34, 139, 11, 0, 37, 232, 231, 120, 72, 37, 39, 128, 121, 47, 232, 121, 128, 104, 69, 67, 175, 171, 148, 157, 154, 155, 118, 50, 101, 73, 39, 40, 9, 151, 108, 48, 115, 131, 194, 204, 211, 74, 40, 185, 80, 42, 183, 40, 92, 186, 230, 229, 118, 202, 212, 214, 83, 18, 17, 76, 61, 146, 160, 29, 30, 56, 157, 173, 106, 204, 194, 135, 214, 192, 203, 165, 98, 21, 71, 68, 51, 45, 4, 144, 24, 23, 77, 146, 91, 205, 50, 187, 201, 200, 18, 91, 106, 182, 90, 91, 181, 85, 84, 17, 206, 203, 36, 148, 171, 140, 92, 40, 39, 193, 189, 244, 159, 158, 28, 247, 246, 161, 236, 3, 196, 54, 68, 104, 193, 168, 8, 117, 228, 31, 189, 193, 55, 98, 97, 99, 126, 47, 100, 166, 79, 218, 155, 154, 26, 209, 49, 131, 135, 136, 150, 47, 126, 217, 223, 52, 53, 45, 51, 134, 211, 170, 140, 67, 69, 108, 43, 106, 91, 230, 119, 120, 226, 130, 247, 63, 53, 52, 238, 20, 242, 46, 70, 156, 78, 62, 96, 46, 53, 63, 143, 34, 227, 173, 155, 133, 123, 117, 111, 44, 125, 19, 236, 134, 51, 216, 206, 205, 154, 153, 22, 39, 37, 167, 200, 201, 208, 36, 142, 100, 57, 212, 202, 20, 60, 99, 28, 158, 157, 35, 226, 113, 160, 159, 27, 204, 202, 210, 113, 225, 46, 43, 202, 204, 62, 76, 77, 137, 123, 116, 41, 38, 72, 203, 129, 142, 64, 98, 240, 49, 102, 64, 41, 73, 74, 212, 216, 207, 42, 74, 184, 169, 170, 211, 170, 149, 176, 105, 66, 69, 122, 6, 168, 123, 147, 187, 96, 77, 90, 65, 55, 107, 89, 90, 180, 101, 100, 120, 63, 105, 104, 93, 137, 227, 15, 86, 85, 129, 102, 49, 14, 87, 86, 55, 8, 9, 100, 47, 121, 145, 23, 22, 88, 89, 179, 6, 122, 196, 88, 95, 96, 138, 172, 136, 215, 58, 172, 115, 48, 219, 42, 80, 81, 195, 3, 51, 43, 146, 61, 171, 175, 199, 81, 82, 38, 53, 46, 225, 144, 163, 110, 246, 33, 7, 52, 65, 66, 229, 228, 117, 34, 127, 234, 107, 108, 69, 109, 108, 151, 48, 64, 235, 62, 78, 191, 129, 209, 126, 111, 35, 143, 163, 161, 246, 117, 123, 50, 222, 65, 52, 19, 125, 141, 221, 55, 65, 3, 195, 197, 25, 7, 33, 220, 237, 44, 70, 71, 139, 122, 193, 245, 247, 130, 33, 71, 21, 162, 153, 158, 159, 170, 169, 150, 188, 174, 196, 216, 186, 92, 144, 160, 161, 2, 97, 167, 141, 125, 241, 164, 167, 37, 72, 38, 12, 145, 159, 160, 38, 82, 13, 63, 68, 71, 226, 35, 111, 158, 153, 154, 101, 50, 205, 206, 92, 165, 209, 198, 217, 165, 167, 97, 220, 115, 218, 133, 112, 243, 239, 238, 241, 214, 135, 169, 190, 173, 133, 171, 208, 32, 125, 44, 237, 86, 87, 178, 85, 86, 179, 84, 85, 180, 83, 84, 181, 201, 83, 182, 137, 93, 132, 76, 62, 183, 61, 76, 184, 57, 61, 185, 212, 57, 186, 214, 207, 187, 34, 143, 156, 79, 239, 237, 123, 137, 177, 44, 1, 4, 201, 194, 32, 64, 102, 129, 213, 215, 138, 59, 166, 219, 242, 99, 97, 2, 94, 141, 75, 59, 235, 24, 110, 228, 25, 130, 226, 23, 24, 229, 22, 23, 230, 26, 22, 231, 112, 26, 232, 189, 190, 243, 221, 56, 190, 28, 56, 221, 27, 28, 222, 29, 27, 223, 30, 29, 224, 247, 30, 225, 238, 79, 20, 166, 59, 75, 60, 75, 240, 147, 177, 215, 20, 79, 166, 187, 147, 213, 112, 233, 244, 233, 128, 245, 128, 114, 188, 114, 217, 174, 131, 115, 220, 217, 198, 236, 198, 131, 134, 177, 132, 58, 143, 35, 124, 110, 163, 7, 228, 110, 25, 356, 389, 368, 11, 302, 267, 452, 350, 349, 302, 303, 269, 357, 343, 277, 452, 453, 357, 333, 332, 297, 175, 152, 377, 384, 398, 382, 347, 348, 330, 303, 304, 270, 9, 336, 337, 278, 279, 360, 418, 262, 431, 304, 408, 409, 310, 415, 407, 270, 409, 410, 450, 348, 347, 422, 430, 434, 313, 314, 17, 306, 307, 375, 387, 388, 260, 286, 414, 398, 335, 406, 418, 364, 367, 416, 423, 358, 327, 251, 284, 298, 281, 5, 4, 373, 374, 253, 307, 320, 321, 425, 427, 411, 421, 313, 18, 321, 405, 406, 320, 404, 405, 315, 16, 17, 426, 425, 266, 377, 400, 369, 322, 391, 269, 417, 465, 464, 386, 257, 258, 466, 260, 388, 456, 399, 419, 284, 332, 333, 417, 285, 8, 346, 340, 261, 413, 441, 285, 327, 460, 328, 355, 371, 329, 392, 439, 438, 382, 341, 256, 429, 420, 360, 364, 394, 379, 277, 343, 437, 443, 444, 283, 275, 440, 363, 431, 262, 369, 297, 338, 337, 273, 375, 321, 450, 451, 349, 446, 342, 467, 293, 334, 282, 458, 461, 462, 276, 353, 383, 308, 324, 325, 276, 300, 293, 372, 345, 447, 382, 398, 362, 352, 345, 340, 274, 1, 19, 456, 248, 281, 436, 427, 425, 381, 256, 252, 269, 391, 393, 200, 199, 428, 266, 330, 329, 287, 273, 422, 250, 462, 328, 258, 286, 384, 265, 353, 342, 387, 259, 257, 424, 431, 430, 342, 353, 276, 273, 335, 424, 292, 325, 307, 366, 447, 345, 271, 303, 302, 423, 266, 371, 294, 455, 460, 279, 278, 294, 271, 272, 304, 432, 434, 427, 272, 407, 408, 394, 430, 431, 395, 369, 400, 334, 333, 299, 351, 417, 168, 352, 280, 411, 325, 319, 320, 295, 296, 336, 319, 403, 404, 330, 348, 349, 293, 298, 333, 323, 454, 447, 15, 16, 315, 358, 429, 279, 14, 15, 316, 285, 336, 9, 329, 349, 350, 374, 380, 252, 318, 402, 403, 6, 197, 419, 318, 319, 325, 367, 364, 365, 435, 367, 397, 344, 438, 439, 272, 271, 311, 195, 5, 281, 273, 287, 291, 396, 428, 199, 311, 271, 268, 283, 444, 445, 373, 254, 339, 263, 466, 249, 282, 334, 296, 449, 347, 346, 264, 447, 454, 336, 296, 299, 338, 10, 151, 278, 439, 455, 292, 407, 415, 358, 371, 355, 340, 345, 372, 390, 249, 466, 346, 347, 280, 442, 443, 282, 19, 94, 370, 441, 442, 295, 248, 419, 197, 263, 255, 359, 440, 275, 274, 300, 383, 368, 351, 412, 465, 263, 467, 466, 301, 368, 389, 380, 374, 386, 395, 378, 379, 412, 351, 419, 436, 426, 322, 373, 390, 388, 2, 164, 393, 370, 462, 461, 164, 0, 267, 302, 11, 12, 374, 373, 387, 268, 12, 13, 293, 300, 301, 446, 261, 340, 385, 384, 381, 330, 266, 425, 426, 423, 391, 429, 355, 437, 391, 327, 326, 440, 457, 438, 341, 382, 362, 459, 457, 461, 434, 430, 394, 414, 463, 362, 396, 369, 262, 354, 461, 457, 316, 403, 402, 315, 404, 403, 314, 405, 404, 313, 406, 405, 421, 418, 406, 366, 401, 361, 306, 408, 407, 291, 409, 408, 287, 410, 409, 432, 436, 410, 434, 416, 411, 264, 368, 383, 309, 438, 457, 352, 376, 401, 274, 275, 4, 421, 428, 262, 294, 327, 358, 433, 416, 367, 289, 455, 439, 462, 370, 326, 2, 326, 370, 305, 460, 455, 254, 449, 448, 255, 261, 446, 253, 450, 449, 252, 451, 450, 256, 452, 451, 341, 453, 452, 413, 464, 463, 441, 413, 414, 258, 442, 441, 257, 443, 442, 259, 444, 443, 260, 445, 444, 467, 342, 445, 459, 458, 250, 289, 392, 290, 290, 328, 460, 376, 433, 435, 250, 290, 392, 411, 416, 433, 341, 463, 464, 453, 464, 465, 357, 465, 412, 343, 412, 399, 360, 363, 440, 437, 399, 456, 420, 456, 363, 401, 435, 288, 372, 383, 353, 339, 255, 249, 448, 261, 255, 133, 243, 190, 133, 155, 112, 33, 246, 247, 33, 130, 25, 398, 384, 286, 362, 398, 414, 362, 463, 341, 263, 359, 467, 263, 249, 255, 466, 467, 260, 75, 60, 166, 238, 239, 79, 162, 127, 139, 72, 11, 37, 121, 232, 120, 73, 72, 39, 114, 128, 47, 233, 232, 128, 103, 104, 67, 152, 175, 148, 173, 157, 155, 119, 118, 101, 74, 73, 40, 107, 9, 108, 49, 48, 131, 32, 194, 211, 184, 74, 185, 191, 80, 183, 185, 40, 186, 119, 230, 118, 210, 202, 214, 84, 83, 17, 77, 76, 146, 161, 160, 30, 190, 56, 173, 182, 106, 194, 138, 135, 192, 129, 203, 98, 54, 21, 68, 5, 51, 4, 145, 144, 23, 90, 77, 91, 207, 205, 187, 83, 201, 18, 181, 91, 182, 180, 90, 181, 16, 85, 17, 205, 206, 36, 176, 148, 140, 165, 92, 39, 245, 193, 244, 27, 159, 28, 30, 247, 161, 174, 236, 196, 103, 54, 104, 55, 193, 8, 111, 117, 31, 221, 189, 55, 240, 98, 99, 142, 126, 100, 219, 166, 218, 112, 155, 26, 198, 209, 131, 169, 135, 150, 114, 47, 217, 224, 223, 53, 220, 45, 134, 32, 211, 140, 109, 67, 108, 146, 43, 91, 231, 230, 120, 113, 226, 247, 105, 63, 52, 241, 238, 242, 124, 46, 156, 95, 78, 96, 70, 46, 63, 116, 143, 227, 116, 123, 111, 1, 44, 19, 3, 236, 51, 207, 216, 205, 26, 154, 22, 165, 39, 167, 199, 200, 208, 101, 36, 100, 43, 57, 202, 242, 20, 99, 56, 28, 157, 124, 35, 113, 29, 160, 27, 211, 204, 210, 124, 113, 46, 106, 43, 204, 96, 62, 77, 227, 137, 116, 73, 41, 72, 36, 203, 142, 235, 64, 240, 48, 49, 64, 42, 41, 74, 214, 212, 207, 183, 42, 184, 210, 169, 211, 140, 170, 176, 104, 105, 69, 193, 122, 168, 50, 123, 187, 89, 96, 90, 66, 65, 107, 179, 89, 180, 119, 101, 120, 68, 63, 104, 234, 93, 227, 16, 15, 85, 209, 129, 49, 15, 14, 86, 107, 55, 9, 120, 100, 121, 153, 145, 22, 178, 88, 179, 197, 6, 196, 89, 88, 96, 135, 138, 136, 138, 215, 172, 218, 115, 219, 41, 42, 81, 5, 195, 51, 57, 43, 61, 208, 171, 199, 41, 81, 38, 224, 53, 225, 24, 144, 110, 105, 52, 66, 118, 229, 117, 227, 34, 234, 66, 107, 69, 10, 109, 151, 219, 48, 235, 183, 62, 191, 142, 129, 126, 116, 111, 143, 7, 163, 246, 118, 117, 50, 223, 222, 52, 94, 19, 141, 222, 221, 65, 196, 3, 197, 45, 220, 44, 156, 70, 139, 188, 122, 245, 139, 71, 162, 145, 153, 159, 149, 170, 150, 122, 188, 196, 206, 216, 92, 163, 144, 161, 164, 2, 167, 242, 141, 241, 0, 164, 37, 11, 72, 12, 144, 145, 160, 12, 38, 13, 70, 63, 71, 31, 226, 111, 157, 158, 154, 36, 101, 205, 203, 206, 165, 126, 209, 217, 98, 165, 97, 237, 220, 218, 237, 239, 241, 210, 214, 169, 140, 171, 32, 241, 125, 237, 179, 86, 178, 180, 85, 179, 181, 84, 180, 182, 83, 181, 194, 201, 182, 177, 137, 132, 184, 76, 183, 185, 61, 184, 186, 57, 185, 216, 212, 186, 192, 214, 187, 139, 34, 156, 218, 79, 237, 147, 123, 177, 45, 44, 4, 208, 201, 32, 98, 64, 129, 192, 213, 138, 235, 59, 219, 141, 242, 97, 97, 2, 141, 240, 75, 235, 229, 24, 228, 31, 25, 226, 230, 23, 229, 231, 22, 230, 232, 26, 231, 233, 112, 232, 244, 189, 243, 189, 221, 190, 222, 28, 221, 223, 27, 222, 224, 29, 223, 225, 30, 224, 113, 247, 225, 99, 60, 240, 213, 147, 215, 60, 20, 166, 192, 187, 213, 243, 112, 244, 244, 233, 245, 245, 128, 188, 188, 114, 174, 134, 131, 220, 174, 217, 236, 236, 198, 134, 215, 177, 58, 156, 143, 124, 25, 110, 7, 31, 228, 25, 264, 356, 368, 0, 11, 267, 451, 452, 349, 267, 302, 269, 350, 357, 277, 350, 452, 357, 299, 333, 297, 396, 175, 377, 381, 384, 382, 280, 347, 330, 269, 303, 270, 151, 9, 337, 344, 278, 360, 424, 418, 431, 270, 304, 409, 272, 310, 407, 322, 270, 410, 449, 450, 347, 432, 422, 434, 18, 313, 17, 291, 306, 375, 259, 387, 260, 424, 335, 418, 434, 364, 416, 391, 423, 327, 301, 251, 298, 275, 281, 4, 254, 373, 253, 375, 307, 321, 280, 425, 411, 200, 421, 18, 335, 321, 406, 321, 320, 405, 314, 315, 17, 423, 426, 266, 396, 377, 369, 270, 322, 269, 413, 417, 464, 385, 386, 258, 248, 456, 419, 298, 284, 333, 168, 417, 8, 448, 346, 261, 417, 413, 285, 326, 327, 328, 277, 355, 329, 309, 392, 438, 381, 382, 256, 279, 429, 360, 365, 364, 379, 355, 277, 437, 282, 443, 283, 281, 275, 363, 395, 431, 369, 299, 297, 337, 335, 273, 321, 348, 450, 349, 359, 446, 467, 283, 293, 282, 250, 458, 462, 300, 276, 383, 292, 308, 325, 283, 276, 293, 264, 372, 447, 346, 352, 340, 354, 274, 19, 363, 456, 281, 426, 436, 425, 380, 381, 252, 267, 269, 393, 421, 200, 428, 371, 266, 329, 432, 287, 422, 290, 250, 328, 385, 258, 384, 446, 265, 342, 386, 387, 257, 422, 424, 430, 445, 342, 276, 422, 273, 424, 306, 292, 307, 352, 366, 345, 268, 271, 302, 358, 423, 371, 327, 294, 460, 331, 279, 294, 303, 271, 304, 436, 432, 427, 304, 272, 408, 395, 394, 431, 378, 395, 400, 296, 334, 299, 6, 351, 168, 376, 352, 411, 307, 325, 320, 285, 295, 336, 320, 319, 404, 329, 330, 349, 334, 293, 333, 366, 323, 447, 316, 15, 315, 331, 358, 279, 317, 14, 316, 8, 285, 9, 277, 329, 350, 253, 374, 252, 319, 318, 403, 351, 6, 419, 324, 318, 325, 397, 367, 365, 288, 435, 397, 278, 344, 439, 310, 272, 311, 248, 195, 281, 375, 273, 291, 175, 396, 199, 312, 311, 268, 276, 283, 445, 390, 373, 339, 295, 282, 296, 448, 449, 346, 356, 264, 454, 337, 336, 299, 337, 338, 151, 294, 278, 455, 308, 292, 415, 429, 358, 355, 265, 340, 372, 388, 390, 466, 352, 346, 280, 295, 442, 282, 354, 19, 370, 285, 441, 295, 195, 248, 197, 457, 440, 274, 301, 300, 368, 417, 351, 465, 251, 301, 389, 385, 380, 386, 394, 395, 379, 399, 412, 419, 410, 436, 322, 387, 373, 388, 326, 2, 393, 354, 370, 461, 393, 164, 267, 268, 302, 12, 386, 374, 387, 312, 268, 13, 298, 293, 301, 265, 446, 340, 380, 385, 381, 280, 330, 425, 322, 426, 391, 420, 429, 437, 393, 391, 326, 344, 440, 438, 458, 459, 461, 364, 434, 394, 428, 396, 262, 274, 354, 457, 317, 316, 402, 316, 315, 403, 315, 314, 404, 314, 313, 405, 313, 421, 406, 323, 366, 361, 292, 306, 407, 306, 291, 408, 291, 287, 409, 287, 432, 410, 427, 434, 411, 372, 264, 383, 459, 309, 457, 366, 352, 401, 1, 274, 4, 418, 421, 262, 331, 294, 358, 435, 433, 367, 392, 289, 439, 328, 462, 326, 94, 2, 370, 289, 305, 455, 339, 254, 448, 359, 255, 446, 254, 253, 449, 253, 252, 450, 252, 256, 451, 256, 341, 452, 414, 413, 463, 286, 441, 414, 286, 258, 441, 258, 257, 442, 257, 259, 443, 259, 260, 444, 260, 467, 445, 309, 459, 250, 305, 289, 290, 305, 290, 460, 401, 376, 435, 309, 250, 392, 376, 411, 433, 453, 341, 464, 357, 453, 465, 343, 357, 412, 437, 343, 399, 344, 360, 440, 420, 437, 456, 360, 420, 363, 361, 401, 288, 265, 372, 353, 390, 339, 249, 339, 448, 255],
|
|
// My face as default (captured with a 640x480 webcam)
|
|
// prettier-ignore
|
|
SAMPLE_FACE: {
|
|
"keypoints": [{
|
|
"x": 356.2804412841797,
|
|
"y": 295.1960563659668,
|
|
"z": -23.786449432373047,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 354.8859405517578,
|
|
"y": 264.69520568847656,
|
|
"z": -36.718435287475586
|
|
}, {
|
|
"x": 355.2180862426758,
|
|
"y": 275.3360366821289,
|
|
"z": -21.183712482452393
|
|
}, {
|
|
"x": 347.349853515625,
|
|
"y": 242.4400234222412,
|
|
"z": -25.093655586242676
|
|
}, {
|
|
"x": 354.40135955810547,
|
|
"y": 256.67933464050293,
|
|
"z": -38.23572635650635
|
|
}, {
|
|
"x": 353.7689971923828,
|
|
"y": 247.54886627197266,
|
|
"z": -34.5475435256958
|
|
}, {
|
|
"x": 352.1288299560547,
|
|
"y": 227.34312057495117,
|
|
"z": -13.095386028289795
|
|
}, {
|
|
"x": 303.5013198852539,
|
|
"y": 234.67002868652344,
|
|
"z": 12.500141859054565,
|
|
"name": "rightEye"
|
|
}, {
|
|
"x": 351.09378814697266,
|
|
"y": 211.87547206878662,
|
|
"z": -6.413471698760986
|
|
}, {
|
|
"x": 350.7115936279297,
|
|
"y": 202.1251630783081,
|
|
"z": -6.413471698760986
|
|
}, {
|
|
"x": 348.33667755126953,
|
|
"y": 168.7741756439209,
|
|
"z": 6.483500003814697,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 356.4806365966797,
|
|
"y": 299.2995357513428,
|
|
"z": -23.144519329071045
|
|
}, {
|
|
"x": 356.5511703491211,
|
|
"y": 302.66146659851074,
|
|
"z": -21.020312309265137
|
|
}, {
|
|
"x": 356.6239547729492,
|
|
"y": 304.1536331176758,
|
|
"z": -18.137459754943848,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 356.5807342529297,
|
|
"y": 305.1840591430664,
|
|
"z": -18.767719268798828,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 356.8241500854492,
|
|
"y": 308.25711250305176,
|
|
"z": -20.16829490661621
|
|
}, {
|
|
"x": 357.113037109375,
|
|
"y": 312.26277351379395,
|
|
"z": -22.10575819015503
|
|
}, {
|
|
"x": 357.34962463378906,
|
|
"y": 317.1123218536377,
|
|
"z": -21.837315559387207,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 357.6658630371094,
|
|
"y": 325.51036834716797,
|
|
"z": -16.27002477645874
|
|
}, {
|
|
"x": 355.0201416015625,
|
|
"y": 269.36279296875,
|
|
"z": -33.73054027557373
|
|
}, {
|
|
"x": 348.5237503051758,
|
|
"y": 270.33411026000977,
|
|
"z": -24.93025302886963
|
|
}, {
|
|
"x": 279.97331619262695,
|
|
"y": 213.24176788330078,
|
|
"z": 47.759642601013184,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 322.66529083251953,
|
|
"y": 238.5027265548706,
|
|
"z": 5.535193085670471
|
|
}, {
|
|
"x": 316.0983657836914,
|
|
"y": 239.94489669799805,
|
|
"z": 5.777376294136047
|
|
}, {
|
|
"x": 309.9431610107422,
|
|
"y": 240.24518966674805,
|
|
"z": 7.510589361190796
|
|
}, {
|
|
"x": 301.31994247436523,
|
|
"y": 237.86138534545898,
|
|
"z": 13.118728399276733
|
|
}, {
|
|
"x": 328.14266204833984,
|
|
"y": 235.80496788024902,
|
|
"z": 6.646900177001953
|
|
}, {
|
|
"x": 313.7326431274414,
|
|
"y": 222.11161136627197,
|
|
"z": 3.9887237548828125
|
|
}, {
|
|
"x": 320.45196533203125,
|
|
"y": 221.87729358673096,
|
|
"z": 4.601476192474365
|
|
}, {
|
|
"x": 307.35679626464844,
|
|
"y": 223.63793849945068,
|
|
"z": 5.932023525238037
|
|
}, {
|
|
"x": 303.0031204223633,
|
|
"y": 226.3743782043457,
|
|
"z": 8.479321002960205
|
|
}, {
|
|
"x": 296.80023193359375,
|
|
"y": 242.94299125671387,
|
|
"z": 15.931552648544312
|
|
}, {
|
|
"x": 332.2352981567383,
|
|
"y": 340.77341079711914,
|
|
"z": -10.165848731994629
|
|
}, {
|
|
"x": 301.38587951660156,
|
|
"y": 233.46447944641113,
|
|
"z": 14.764405488967896,
|
|
"name": "rightEye"
|
|
}, {
|
|
"x": 279.0147018432617,
|
|
"y": 244.37155723571777,
|
|
"z": 45.77549457550049
|
|
}, {
|
|
"x": 289.60548400878906,
|
|
"y": 239.1807460784912,
|
|
"z": 23.191204071044922
|
|
}, {
|
|
"x": 320.32257080078125,
|
|
"y": 267.1292781829834,
|
|
"z": -4.954537749290466
|
|
}, {
|
|
"x": 347.64583587646484,
|
|
"y": 294.4955062866211,
|
|
"z": -23.062820434570312,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 349.28138732910156,
|
|
"y": 303.1095886230469,
|
|
"z": -20.238323211669922
|
|
}, {
|
|
"x": 338.9453125,
|
|
"y": 298.19186210632324,
|
|
"z": -19.456336498260498,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 333.36788177490234,
|
|
"y": 302.6706790924072,
|
|
"z": -14.776077270507812,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 342.89188385009766,
|
|
"y": 304.3561363220215,
|
|
"z": -17.752301692962646
|
|
}, {
|
|
"x": 337.7375030517578,
|
|
"y": 306.0098361968994,
|
|
"z": -13.410515785217285
|
|
}, {
|
|
"x": 325.6159210205078,
|
|
"y": 316.22995376586914,
|
|
"z": -6.681914925575256
|
|
}, {
|
|
"x": 349.0104675292969,
|
|
"y": 264.9818515777588,
|
|
"z": -36.274919509887695
|
|
}, {
|
|
"x": 347.7138900756836,
|
|
"y": 257.5664806365967,
|
|
"z": -37.67549514770508
|
|
}, {
|
|
"x": 291.79357528686523,
|
|
"y": 218.88171672821045,
|
|
"z": 11.578094959259033,
|
|
"name": "rightEyebrow"
|
|
}, {
|
|
"x": 332.2689437866211,
|
|
"y": 247.56946563720703,
|
|
"z": -3.3730539679527283
|
|
}, {
|
|
"x": 332.0074462890625,
|
|
"y": 267.1201229095459,
|
|
"z": -19.969879388809204
|
|
}, {
|
|
"x": 331.27952575683594,
|
|
"y": 263.6967658996582,
|
|
"z": -17.47218608856201
|
|
}, {
|
|
"x": 301.04373931884766,
|
|
"y": 269.56552505493164,
|
|
"z": 3.61815482378006
|
|
}, {
|
|
"x": 347.4863815307617,
|
|
"y": 249.0706443786621,
|
|
"z": -32.633421421051025
|
|
}, {
|
|
"x": 307.26118087768555,
|
|
"y": 208.2646894454956,
|
|
"z": 1.1591226607561111,
|
|
"name": "rightEyebrow"
|
|
}, {
|
|
"x": 297.91919708251953,
|
|
"y": 212.22604751586914,
|
|
"z": 5.914516448974609,
|
|
"name": "rightEyebrow"
|
|
}, {
|
|
"x": 285.1651382446289,
|
|
"y": 197.98450469970703,
|
|
"z": 36.391637325286865,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 337.04097747802734,
|
|
"y": 211.25229835510254,
|
|
"z": -4.548954665660858
|
|
}, {
|
|
"x": 326.5912628173828,
|
|
"y": 223.16698551177979,
|
|
"z": 6.670243740081787
|
|
}, {
|
|
"x": 320.05664825439453,
|
|
"y": 309.5834255218506,
|
|
"z": -4.055835008621216
|
|
}, {
|
|
"x": 289.6866226196289,
|
|
"y": 314.617395401001,
|
|
"z": 53.875489234924316,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 337.4256896972656,
|
|
"y": 270.8755302429199,
|
|
"z": -17.67060160636902
|
|
}, {
|
|
"x": 343.69922637939453,
|
|
"y": 273.0000400543213,
|
|
"z": -18.756048679351807
|
|
}, {
|
|
"x": 327.4242401123047,
|
|
"y": 309.22399520874023,
|
|
"z": -4.703601002693176,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 330.37220001220703,
|
|
"y": 308.3323001861572,
|
|
"z": -6.442649960517883
|
|
}, {
|
|
"x": 293.87027740478516,
|
|
"y": 207.7961826324463,
|
|
"z": 9.821539521217346,
|
|
"name": "rightEyebrow"
|
|
}, {
|
|
"x": 332.11437225341797,
|
|
"y": 271.22812271118164,
|
|
"z": -16.64351224899292
|
|
}, {
|
|
"x": 320.1197814941406,
|
|
"y": 207.40366458892822,
|
|
"z": -2.48164564371109,
|
|
"name": "rightEyebrow"
|
|
}, {
|
|
"x": 318.59575271606445,
|
|
"y": 201.07443809509277,
|
|
"z": -3.110446035861969,
|
|
"name": "rightEyebrow"
|
|
}, {
|
|
"x": 310.72303771972656,
|
|
"y": 175.75075149536133,
|
|
"z": 13.328815698623657,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 289.67578887939453,
|
|
"y": 202.29835510253906,
|
|
"z": 21.370456218719482
|
|
}, {
|
|
"x": 315.30879974365234,
|
|
"y": 187.35260009765625,
|
|
"z": 5.0304025411605835
|
|
}, {
|
|
"x": 287.8936767578125,
|
|
"y": 216.54793739318848,
|
|
"z": 17.81065821647644,
|
|
"name": "rightEyebrow"
|
|
}, {
|
|
"x": 283.9391899108887,
|
|
"y": 215.01142501831055,
|
|
"z": 32.04984903335571
|
|
}, {
|
|
"x": 348.35330963134766,
|
|
"y": 299.4155788421631,
|
|
"z": -22.47924566268921
|
|
}, {
|
|
"x": 341.1790466308594,
|
|
"y": 301.8221855163574,
|
|
"z": -18.977805376052856
|
|
}, {
|
|
"x": 335.69713592529297,
|
|
"y": 304.4266891479492,
|
|
"z": -14.682706594467163
|
|
}, {
|
|
"x": 339.4615173339844,
|
|
"y": 272.3654365539551,
|
|
"z": -16.38674020767212
|
|
}, {
|
|
"x": 328.99600982666016,
|
|
"y": 308.86685371398926,
|
|
"z": -5.616893768310547
|
|
}, {
|
|
"x": 332.00313568115234,
|
|
"y": 309.1875743865967,
|
|
"z": -10.335084199905396
|
|
}, {
|
|
"x": 331.0068130493164,
|
|
"y": 307.9274368286133,
|
|
"z": -6.681914925575256,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 341.13792419433594,
|
|
"y": 266.4876937866211,
|
|
"z": -26.56425952911377
|
|
}, {
|
|
"x": 339.02950286865234,
|
|
"y": 305.6663703918457,
|
|
"z": -12.33674168586731,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 344.22935485839844,
|
|
"y": 304.9452781677246,
|
|
"z": -15.161235332489014,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 350.1844024658203,
|
|
"y": 304.374303817749,
|
|
"z": -17.5305438041687,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 348.52630615234375,
|
|
"y": 325.9562301635742,
|
|
"z": -16.164982318878174
|
|
}, {
|
|
"x": 348.6581802368164,
|
|
"y": 317.1624183654785,
|
|
"z": -21.510512828826904,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 348.9766311645508,
|
|
"y": 312.1923065185547,
|
|
"z": -21.708929538726807
|
|
}, {
|
|
"x": 349.2427444458008,
|
|
"y": 308.0660820007324,
|
|
"z": -19.643079042434692
|
|
}, {
|
|
"x": 349.67491149902344,
|
|
"y": 305.42747497558594,
|
|
"z": -18.16080331802368,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 337.95589447021484,
|
|
"y": 306.6535949707031,
|
|
"z": -12.803598642349243,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 337.06878662109375,
|
|
"y": 307.63169288635254,
|
|
"z": -14.274203777313232
|
|
}, {
|
|
"x": 335.77449798583984,
|
|
"y": 309.8449516296387,
|
|
"z": -15.698124170303345
|
|
}, {
|
|
"x": 334.6099090576172,
|
|
"y": 312.7997016906738,
|
|
"z": -14.764405488967896,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 327.2330856323242,
|
|
"y": 293.80866050720215,
|
|
"z": -11.864047050476074
|
|
}, {
|
|
"x": 280.97679138183594,
|
|
"y": 279.79928970336914,
|
|
"z": 68.90834331512451,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 355.13843536376953,
|
|
"y": 271.7875671386719,
|
|
"z": -25.350427627563477
|
|
}, {
|
|
"x": 334.7235870361328,
|
|
"y": 307.4656391143799,
|
|
"z": -9.302158951759338,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 333.5293960571289,
|
|
"y": 307.89782524108887,
|
|
"z": -10.200862884521484
|
|
}, {
|
|
"x": 346.29688262939453,
|
|
"y": 276.4256286621094,
|
|
"z": -19.748122692108154
|
|
}, {
|
|
"x": 335.16246795654297,
|
|
"y": 276.22097969055176,
|
|
"z": -12.313398122787476
|
|
}, {
|
|
"x": 345.09132385253906,
|
|
"y": 274.7082996368408,
|
|
"z": -19.304605722427368
|
|
}, {
|
|
"x": 325.4267883300781,
|
|
"y": 252.95130729675293,
|
|
"z": -1.6661019623279572
|
|
}, {
|
|
"x": 315.347843170166,
|
|
"y": 259.05200958251953,
|
|
"z": -0.25604281574487686
|
|
}, {
|
|
"x": 330.44933319091797,
|
|
"y": 267.7570152282715,
|
|
"z": -14.017432928085327
|
|
}, {
|
|
"x": 294.96768951416016,
|
|
"y": 185.26001930236816,
|
|
"z": 23.903164863586426,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 299.63531494140625,
|
|
"y": 192.7913761138916,
|
|
"z": 12.640198469161987
|
|
}, {
|
|
"x": 304.5452117919922,
|
|
"y": 202.4142837524414,
|
|
"z": 3.244667649269104,
|
|
"name": "rightEyebrow"
|
|
}, {
|
|
"x": 331.6915512084961,
|
|
"y": 320.0467872619629,
|
|
"z": -10.632705688476562
|
|
}, {
|
|
"x": 334.5911407470703,
|
|
"y": 201.27566814422607,
|
|
"z": -6.133356094360352,
|
|
"name": "rightEyebrow"
|
|
}, {
|
|
"x": 331.4815902709961,
|
|
"y": 185.44180870056152,
|
|
"z": 0.6627205014228821
|
|
}, {
|
|
"x": 328.05816650390625,
|
|
"y": 170.8385467529297,
|
|
"z": 7.358860373497009,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 304.49764251708984,
|
|
"y": 239.76297855377197,
|
|
"z": 10.387605428695679
|
|
}, {
|
|
"x": 290.6382179260254,
|
|
"y": 248.85257720947266,
|
|
"z": 19.03616428375244
|
|
}, {
|
|
"x": 331.5682601928711,
|
|
"y": 233.20727348327637,
|
|
"z": 7.837390303611755
|
|
}, {
|
|
"x": 295.5115509033203,
|
|
"y": 228.9834451675415,
|
|
"z": 14.41426157951355
|
|
}, {
|
|
"x": 336.94332122802734,
|
|
"y": 241.8259334564209,
|
|
"z": -5.27842104434967
|
|
}, {
|
|
"x": 336.2792205810547,
|
|
"y": 262.7049922943115,
|
|
"z": -26.12074375152588
|
|
}, {
|
|
"x": 284.4102478027344,
|
|
"y": 255.3262710571289,
|
|
"z": 25.467140674591064
|
|
}, {
|
|
"x": 295.1420593261719,
|
|
"y": 253.02655220031738,
|
|
"z": 12.430112361907959
|
|
}, {
|
|
"x": 303.5196113586426,
|
|
"y": 254.20703887939453,
|
|
"z": 6.139191389083862
|
|
}, {
|
|
"x": 315.73450088500977,
|
|
"y": 251.64799690246582,
|
|
"z": 3.3788898587226868
|
|
}, {
|
|
"x": 324.69661712646484,
|
|
"y": 247.56494522094727,
|
|
"z": 2.3328344523906708
|
|
}, {
|
|
"x": 331.57970428466797,
|
|
"y": 243.02241325378418,
|
|
"z": 1.1423448473215103
|
|
}, {
|
|
"x": 345.6210708618164,
|
|
"y": 229.9976634979248,
|
|
"z": -10.825285911560059
|
|
}, {
|
|
"x": 286.26644134521484,
|
|
"y": 270.37991523742676,
|
|
"z": 21.708929538726807
|
|
}, {
|
|
"x": 290.2525520324707,
|
|
"y": 228.4921360015869,
|
|
"z": 17.71728754043579
|
|
}, {
|
|
"x": 351.65367126464844,
|
|
"y": 269.3400764465332,
|
|
"z": -33.450424671173096
|
|
}, {
|
|
"x": 333.1378936767578,
|
|
"y": 253.88388633728027,
|
|
"z": -7.230473756790161
|
|
}, {
|
|
"x": 277.8318977355957,
|
|
"y": 246.95331573486328,
|
|
"z": 68.20805549621582,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 336.6680908203125,
|
|
"y": 238.10003757476807,
|
|
"z": 0.7688578963279724
|
|
}, {
|
|
"x": 329.95800018310547,
|
|
"y": 269.18323516845703,
|
|
"z": -7.207130789756775
|
|
}, {
|
|
"x": 299.17491912841797,
|
|
"y": 234.13324356079102,
|
|
"z": 15.95489501953125
|
|
}, {
|
|
"x": 335.61729431152344,
|
|
"y": 258.71752738952637,
|
|
"z": -23.016133308410645
|
|
}, {
|
|
"x": 284.1079330444336,
|
|
"y": 297.0343494415283,
|
|
"z": 63.25934886932373,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 331.44542694091797,
|
|
"y": 230.6892442703247,
|
|
"z": 9.92658257484436,
|
|
"name": "rightEye"
|
|
}, {
|
|
"x": 341.41536712646484,
|
|
"y": 253.01264762878418,
|
|
"z": -29.038610458374023
|
|
}, {
|
|
"x": 303.5472869873047,
|
|
"y": 327.5896739959717,
|
|
"z": 16.725212335586548
|
|
}, {
|
|
"x": 304.7756576538086,
|
|
"y": 337.4389457702637,
|
|
"z": 27.38126277923584,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 280.80501556396484,
|
|
"y": 275.32050132751465,
|
|
"z": 45.0752067565918
|
|
}, {
|
|
"x": 295.43582916259766,
|
|
"y": 318.4501647949219,
|
|
"z": 26.2608003616333
|
|
}, {
|
|
"x": 281.4303207397461,
|
|
"y": 228.7355661392212,
|
|
"z": 40.94350814819336
|
|
}, {
|
|
"x": 331.2549591064453,
|
|
"y": 349.4216537475586,
|
|
"z": -7.376367449760437
|
|
}, {
|
|
"x": 352.4247741699219,
|
|
"y": 271.7330074310303,
|
|
"z": -24.953596591949463
|
|
}, {
|
|
"x": 327.5672912597656,
|
|
"y": 260.41900634765625,
|
|
"z": -5.456410646438599
|
|
}, {
|
|
"x": 284.5432472229004,
|
|
"y": 241.7647933959961,
|
|
"z": 29.668869972229004
|
|
}, {
|
|
"x": 310,
|
|
"y": 235.66174507141113,
|
|
"z": 8.502663969993591,
|
|
"name": "rightEye"
|
|
}, {
|
|
"x": 315.7071113586426,
|
|
"y": 235.7572603225708,
|
|
"z": 6.938687562942505,
|
|
"name": "rightEye"
|
|
}, {
|
|
"x": 330.41088104248047,
|
|
"y": 311.04143142700195,
|
|
"z": -9.325502514839172,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 288.5377502441406,
|
|
"y": 285.31983375549316,
|
|
"z": 21.837315559387207
|
|
}, {
|
|
"x": 344.55039978027344,
|
|
"y": 359.4300842285156,
|
|
"z": -6.705257892608643,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 323.41880798339844,
|
|
"y": 351.67362213134766,
|
|
"z": 7.802375555038452,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 314.64088439941406,
|
|
"y": 346.11894607543945,
|
|
"z": 16.36339783668518,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 349.4945526123047,
|
|
"y": 184.8434829711914,
|
|
"z": -0.21847527474164963
|
|
}, {
|
|
"x": 359.24694061279297,
|
|
"y": 359.8348903656006,
|
|
"z": -8.403456211090088,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 321.26182556152344,
|
|
"y": 234.64492321014404,
|
|
"z": 6.90950870513916,
|
|
"name": "rightEye"
|
|
}, {
|
|
"x": 326.318359375,
|
|
"y": 232.90250301361084,
|
|
"z": 8.029969334602356,
|
|
"name": "rightEye"
|
|
}, {
|
|
"x": 329.6211624145508,
|
|
"y": 231.6195774078369,
|
|
"z": 9.722331762313843,
|
|
"name": "rightEye"
|
|
}, {
|
|
"x": 285.9398078918457,
|
|
"y": 228.2351303100586,
|
|
"z": 24.650139808654785
|
|
}, {
|
|
"x": 325.79288482666016,
|
|
"y": 227.88007736206055,
|
|
"z": 7.469738721847534,
|
|
"name": "rightEye"
|
|
}, {
|
|
"x": 320.1699447631836,
|
|
"y": 227.5934886932373,
|
|
"z": 6.168370842933655,
|
|
"name": "rightEye"
|
|
}, {
|
|
"x": 314.85408782958984,
|
|
"y": 227.85282611846924,
|
|
"z": 6.2675780057907104,
|
|
"name": "rightEye"
|
|
}, {
|
|
"x": 309.3084907531738,
|
|
"y": 229.1516876220703,
|
|
"z": 7.7031683921813965,
|
|
"name": "rightEye"
|
|
}, {
|
|
"x": 305.5621337890625,
|
|
"y": 230.92366218566895,
|
|
"z": 9.722331762313843,
|
|
"name": "rightEye"
|
|
}, {
|
|
"x": 277.8681945800781,
|
|
"y": 228.5354232788086,
|
|
"z": 59.71122741699219,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 306.1444664001465,
|
|
"y": 235.1954698562622,
|
|
"z": 10.603528022766113,
|
|
"name": "rightEye"
|
|
}, {
|
|
"x": 355.4478454589844,
|
|
"y": 281.96210861206055,
|
|
"z": -20.565123558044434
|
|
}, {
|
|
"x": 333.02661895751953,
|
|
"y": 288.0105400085449,
|
|
"z": -14.72939133644104
|
|
}, {
|
|
"x": 337.15728759765625,
|
|
"y": 269.2059516906738,
|
|
"z": -19.8414945602417
|
|
}, {
|
|
"x": 345.9898376464844,
|
|
"y": 283.5453128814697,
|
|
"z": -20.4834246635437
|
|
}, {
|
|
"x": 351.48963928222656,
|
|
"y": 219.98916149139404,
|
|
"z": -7.0378947257995605
|
|
}, {
|
|
"x": 312.39574432373047,
|
|
"y": 336.50628089904785,
|
|
"z": 8.671900033950806
|
|
}, {
|
|
"x": 321.32152557373047,
|
|
"y": 343.1755256652832,
|
|
"z": 0.9067271649837494
|
|
}, {
|
|
"x": 343.78379821777344,
|
|
"y": 353.2975959777832,
|
|
"z": -14.355905055999756
|
|
}, {
|
|
"x": 296.8791389465332,
|
|
"y": 327.91497230529785,
|
|
"z": 41.01353645324707,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 329.6939468383789,
|
|
"y": 229.27897453308105,
|
|
"z": 8.934508562088013,
|
|
"name": "rightEye"
|
|
}, {
|
|
"x": 341.6905212402344,
|
|
"y": 241.4073657989502,
|
|
"z": -14.589333534240723
|
|
}, {
|
|
"x": 359.03079986572266,
|
|
"y": 353.48859786987305,
|
|
"z": -15.803166627883911
|
|
}, {
|
|
"x": 333.1861877441406,
|
|
"y": 356.43213272094727,
|
|
"z": -1.0234417766332626,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 283.97483825683594,
|
|
"y": 291.4318656921387,
|
|
"z": 41.94725513458252
|
|
}, {
|
|
"x": 343.33770751953125,
|
|
"y": 305.830135345459,
|
|
"z": -15.756480693817139,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 342.40283966064453,
|
|
"y": 307.7453899383545,
|
|
"z": -17.4021577835083
|
|
}, {
|
|
"x": 341.53621673583984,
|
|
"y": 311.0595703125,
|
|
"z": -19.047834873199463
|
|
}, {
|
|
"x": 340.9107208251953,
|
|
"y": 315.4837703704834,
|
|
"z": -18.5576331615448,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 339.1478729248047,
|
|
"y": 323.42233657836914,
|
|
"z": -14.367576837539673
|
|
}, {
|
|
"x": 333.3201599121094,
|
|
"y": 307.4406337738037,
|
|
"z": -9.617288708686829
|
|
}, {
|
|
"x": 331.2411117553711,
|
|
"y": 306.9811820983887,
|
|
"z": -9.669809937477112
|
|
}, {
|
|
"x": 329.23255920410156,
|
|
"y": 306.0508346557617,
|
|
"z": -9.582273960113525,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 322.4586486816406,
|
|
"y": 301.33323669433594,
|
|
"z": -7.720675468444824
|
|
}, {
|
|
"x": 297.1712112426758,
|
|
"y": 286.9552803039551,
|
|
"z": 8.240055441856384
|
|
}, {
|
|
"x": 341.3060760498047,
|
|
"y": 235.4432201385498,
|
|
"z": -7.504753470420837
|
|
}, {
|
|
"x": 336.9318389892578,
|
|
"y": 224.3451976776123,
|
|
"z": 5.829898118972778
|
|
}, {
|
|
"x": 332.65323638916016,
|
|
"y": 226.70403957366943,
|
|
"z": 8.105834126472473
|
|
}, {
|
|
"x": 334.67357635498047,
|
|
"y": 306.4397621154785,
|
|
"z": -8.981193900108337,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 297.4601936340332,
|
|
"y": 306.29210472106934,
|
|
"z": 15.476365089416504
|
|
}, {
|
|
"x": 342.9119110107422,
|
|
"y": 222.37077713012695,
|
|
"z": -2.754466235637665
|
|
}, {
|
|
"x": 335.4629898071289,
|
|
"y": 332.20250129699707,
|
|
"z": -11.823196411132812
|
|
}, {
|
|
"x": 353.2412338256836,
|
|
"y": 240.56339263916016,
|
|
"z": -27.147831916809082
|
|
}, {
|
|
"x": 346.3080596923828,
|
|
"y": 236.41446590423584,
|
|
"z": -18.452589511871338
|
|
}, {
|
|
"x": 352.6475143432617,
|
|
"y": 234.1420555114746,
|
|
"z": -19.748122692108154
|
|
}, {
|
|
"x": 337.3209762573242,
|
|
"y": 253.39937210083008,
|
|
"z": -16.024924516677856
|
|
}, {
|
|
"x": 358.6122131347656,
|
|
"y": 344.90861892700195,
|
|
"z": -18.592647314071655
|
|
}, {
|
|
"x": 358.1117248535156,
|
|
"y": 334.64990615844727,
|
|
"z": -17.49552845954895
|
|
}, {
|
|
"x": 346.4450454711914,
|
|
"y": 335.0321102142334,
|
|
"z": -16.32838249206543
|
|
}, {
|
|
"x": 319.17640686035156,
|
|
"y": 320.2833938598633,
|
|
"z": -3.276764452457428
|
|
}, {
|
|
"x": 325.2540588378906,
|
|
"y": 276.2369728088379,
|
|
"z": -6.460157036781311
|
|
}, {
|
|
"x": 326.7214584350586,
|
|
"y": 327.3939514160156,
|
|
"z": -7.417217493057251
|
|
}, {
|
|
"x": 310.7190132141113,
|
|
"y": 277.2265148162842,
|
|
"z": -3.5452082753181458
|
|
}, {
|
|
"x": 319.78355407714844,
|
|
"y": 284.8238182067871,
|
|
"z": -6.4543211460113525
|
|
}, {
|
|
"x": 305.773983001709,
|
|
"y": 290.83580017089844,
|
|
"z": 0.06907138042151928
|
|
}, {
|
|
"x": 344.4001770019531,
|
|
"y": 344.85408782958984,
|
|
"z": -16.946970224380493
|
|
}, {
|
|
"x": 333.1879425048828,
|
|
"y": 258.74256134033203,
|
|
"z": -11.90489649772644
|
|
}, {
|
|
"x": 313.80598068237305,
|
|
"y": 327.08919525146484,
|
|
"z": 2.2277912497520447
|
|
}, {
|
|
"x": 322.9637908935547,
|
|
"y": 334.6819496154785,
|
|
"z": -3.3643004298210144
|
|
}, {
|
|
"x": 313.4055519104004,
|
|
"y": 311.2166690826416,
|
|
"z": -1.1175429821014404
|
|
}, {
|
|
"x": 291.0865783691406,
|
|
"y": 298.2831001281738,
|
|
"z": 22.467575073242188
|
|
}, {
|
|
"x": 305.6580924987793,
|
|
"y": 313.3707904815674,
|
|
"z": 5.561453700065613
|
|
}, {
|
|
"x": 288.23760986328125,
|
|
"y": 305.9941864013672,
|
|
"z": 36.765122413635254
|
|
}, {
|
|
"x": 315.10692596435547,
|
|
"y": 296.26991271972656,
|
|
"z": -4.604393839836121
|
|
}, {
|
|
"x": 337.50518798828125,
|
|
"y": 247.5944423675537,
|
|
"z": -10.597691535949707
|
|
}, {
|
|
"x": 338.8450622558594,
|
|
"y": 265.47778129577637,
|
|
"z": -27.778091430664062
|
|
}, {
|
|
"x": 334.25254821777344,
|
|
"y": 269.0671920776367,
|
|
"z": -20.938611030578613
|
|
}, {
|
|
"x": 341.64512634277344,
|
|
"y": 259.6387195587158,
|
|
"z": -32.189905643463135
|
|
}, {
|
|
"x": 331.44081115722656,
|
|
"y": 219.0976095199585,
|
|
"z": 4.207563698291779
|
|
}, {
|
|
"x": 320.56339263916016,
|
|
"y": 216.49658203125,
|
|
"z": 2.930997312068939
|
|
}, {
|
|
"x": 311.21912002563477,
|
|
"y": 216.57853603363037,
|
|
"z": 2.9674705862998962
|
|
}, {
|
|
"x": 303.46256256103516,
|
|
"y": 218.54614734649658,
|
|
"z": 5.357203483581543
|
|
}, {
|
|
"x": 297.99999237060547,
|
|
"y": 222.505202293396,
|
|
"z": 9.325502514839172
|
|
}, {
|
|
"x": 294.93839263916016,
|
|
"y": 236.39654159545898,
|
|
"z": 18.534289598464966
|
|
}, {
|
|
"x": 278.87489318847656,
|
|
"y": 259.7095584869385,
|
|
"z": 45.68212032318115
|
|
}, {
|
|
"x": 300.3782653808594,
|
|
"y": 245.38593292236328,
|
|
"z": 12.278382778167725
|
|
}, {
|
|
"x": 307.06348419189453,
|
|
"y": 246.36857986450195,
|
|
"z": 8.164191246032715
|
|
}, {
|
|
"x": 315.5229187011719,
|
|
"y": 245.3949737548828,
|
|
"z": 5.503097176551819
|
|
}, {
|
|
"x": 323.71395111083984,
|
|
"y": 242.75178909301758,
|
|
"z": 4.6335723996162415
|
|
}, {
|
|
"x": 330.2785873413086,
|
|
"y": 239.34658527374268,
|
|
"z": 4.937030673027039
|
|
}, {
|
|
"x": 334.6982192993164,
|
|
"y": 236.0460376739502,
|
|
"z": 4.823233783245087
|
|
}, {
|
|
"x": 279.3412208557129,
|
|
"y": 263.5196113586426,
|
|
"z": 70.91583728790283,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 334.65972900390625,
|
|
"y": 271.6648578643799,
|
|
"z": -17.775644063949585
|
|
}, {
|
|
"x": 342.05677032470703,
|
|
"y": 246.99846267700195,
|
|
"z": -20.84523916244507
|
|
}, {
|
|
"x": 344.0357971191406,
|
|
"y": 264.5701503753662,
|
|
"z": -32.936880588531494
|
|
}, {
|
|
"x": 348.25531005859375,
|
|
"y": 268.6645030975342,
|
|
"z": -30.695960521697998
|
|
}, {
|
|
"x": 344.12227630615234,
|
|
"y": 266.34212493896484,
|
|
"z": -29.808926582336426
|
|
}, {
|
|
"x": 337.12318420410156,
|
|
"y": 274.2556858062744,
|
|
"z": -15.768152475357056
|
|
}, {
|
|
"x": 349.49047088623047,
|
|
"y": 269.071683883667,
|
|
"z": -32.51670837402344
|
|
}, {
|
|
"x": 350.1683044433594,
|
|
"y": 271.4691352844238,
|
|
"z": -24.93025302886963
|
|
}, {
|
|
"x": 333.9634704589844,
|
|
"y": 230.56639194488525,
|
|
"z": 8.89949381351471
|
|
}, {
|
|
"x": 338.2147979736328,
|
|
"y": 231.4807891845703,
|
|
"z": 4.6715047955513
|
|
}, {
|
|
"x": 340.4712677001953,
|
|
"y": 231.74463272094727,
|
|
"z": -0.34996166825294495
|
|
}, {
|
|
"x": 303.28975677490234,
|
|
"y": 232.24980354309082,
|
|
"z": 11.916568279266357,
|
|
"name": "rightEye"
|
|
}, {
|
|
"x": 299.4649124145508,
|
|
"y": 229.53842639923096,
|
|
"z": 12.325069904327393
|
|
}, {
|
|
"x": 359.09618377685547,
|
|
"y": 241.77349090576172,
|
|
"z": -24.650139808654785
|
|
}, {
|
|
"x": 399.46216583251953,
|
|
"y": 229.89503860473633,
|
|
"z": 15.919880867004395,
|
|
"name": "leftEye"
|
|
}, {
|
|
"x": 361.38919830322266,
|
|
"y": 269.6129894256592,
|
|
"z": -24.510080814361572
|
|
}, {
|
|
"x": 416.9973373413086,
|
|
"y": 206.0895538330078,
|
|
"z": 53.26857566833496,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 381.32179260253906,
|
|
"y": 235.5476474761963,
|
|
"z": 7.6214683055877686
|
|
}, {
|
|
"x": 387.8068542480469,
|
|
"y": 236.25958442687988,
|
|
"z": 8.345099091529846
|
|
}, {
|
|
"x": 393.95751953125,
|
|
"y": 235.8660364151001,
|
|
"z": 10.475142002105713
|
|
}, {
|
|
"x": 401.84600830078125,
|
|
"y": 232.77019500732422,
|
|
"z": 16.760226488113403
|
|
}, {
|
|
"x": 375.70568084716797,
|
|
"y": 233.48456382751465,
|
|
"z": 8.234220147132874
|
|
}, {
|
|
"x": 388.17752838134766,
|
|
"y": 218.94717693328857,
|
|
"z": 6.810300946235657
|
|
}, {
|
|
"x": 381.64928436279297,
|
|
"y": 219.2656660079956,
|
|
"z": 6.711093783378601
|
|
}, {
|
|
"x": 394.4760513305664,
|
|
"y": 219.66821193695068,
|
|
"z": 9.173773527145386
|
|
}, {
|
|
"x": 398.8843536376953,
|
|
"y": 221.8837022781372,
|
|
"z": 12.03328251838684
|
|
}, {
|
|
"x": 406.5454864501953,
|
|
"y": 237.12156772613525,
|
|
"z": 19.7131085395813
|
|
}, {
|
|
"x": 383.87447357177734,
|
|
"y": 337.6932907104492,
|
|
"z": -8.631049990653992
|
|
}, {
|
|
"x": 401.2682342529297,
|
|
"y": 228.5916566848755,
|
|
"z": 18.359217643737793,
|
|
"name": "leftEye"
|
|
}, {
|
|
"x": 422.0449447631836,
|
|
"y": 236.73934936523438,
|
|
"z": 51.16771221160889
|
|
}, {
|
|
"x": 412.69153594970703,
|
|
"y": 232.80198097229004,
|
|
"z": 27.52131938934326
|
|
}, {
|
|
"x": 387.3497772216797,
|
|
"y": 263.298397064209,
|
|
"z": -2.8609684109687805
|
|
}, {
|
|
"x": 364.5124053955078,
|
|
"y": 293.39221000671387,
|
|
"z": -22.397546768188477,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 363.62987518310547,
|
|
"y": 302.1291446685791,
|
|
"z": -19.643079042434692
|
|
}, {
|
|
"x": 373.2334518432617,
|
|
"y": 295.8647060394287,
|
|
"z": -18.125789165496826,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 378.83365631103516,
|
|
"y": 299.5177745819092,
|
|
"z": -13.153743743896484,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 369.91477966308594,
|
|
"y": 302.5704002380371,
|
|
"z": -16.65518283843994
|
|
}, {
|
|
"x": 374.9167251586914,
|
|
"y": 303.5416603088379,
|
|
"z": -11.963253021240234
|
|
}, {
|
|
"x": 387.58888244628906,
|
|
"y": 312.2716999053955,
|
|
"z": -4.680258631706238
|
|
}, {
|
|
"x": 360.6635284423828,
|
|
"y": 264.31986808776855,
|
|
"z": -35.94811677932739
|
|
}, {
|
|
"x": 361.04564666748047,
|
|
"y": 256.8225860595703,
|
|
"z": -37.278664112091064
|
|
}, {
|
|
"x": 408.3855438232422,
|
|
"y": 213.52088928222656,
|
|
"z": 15.756480693817139,
|
|
"name": "leftEyebrow"
|
|
}, {
|
|
"x": 373.2946014404297,
|
|
"y": 245.38101196289062,
|
|
"z": -1.9316278398036957
|
|
}, {
|
|
"x": 376.83860778808594,
|
|
"y": 264.3721103668213,
|
|
"z": -18.510947227478027
|
|
}, {
|
|
"x": 376.9546127319336,
|
|
"y": 261.0010528564453,
|
|
"z": -15.989909172058105
|
|
}, {
|
|
"x": 406.1498260498047,
|
|
"y": 263.5030174255371,
|
|
"z": 7.072908878326416
|
|
}, {
|
|
"x": 360.07205963134766,
|
|
"y": 248.3631706237793,
|
|
"z": -32.16656446456909
|
|
}, {
|
|
"x": 393.11119079589844,
|
|
"y": 205.10473251342773,
|
|
"z": 3.7786373496055603,
|
|
"name": "leftEyebrow"
|
|
}, {
|
|
"x": 402.12791442871094,
|
|
"y": 207.89000988006592,
|
|
"z": 9.383859634399414,
|
|
"name": "leftEyebrow"
|
|
}, {
|
|
"x": 410.8693313598633,
|
|
"y": 191.6182279586792,
|
|
"z": 41.27030849456787,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 364.9509811401367,
|
|
"y": 210.40483474731445,
|
|
"z": -3.758212625980377
|
|
}, {
|
|
"x": 375.94444274902344,
|
|
"y": 221.1331844329834,
|
|
"z": 8.368442058563232
|
|
}, {
|
|
"x": 392.1904754638672,
|
|
"y": 305.0360298156738,
|
|
"z": -1.752179116010666
|
|
}, {
|
|
"x": 419.50225830078125,
|
|
"y": 307.25592613220215,
|
|
"z": 58.96425247192383,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 372.0027160644531,
|
|
"y": 268.7212657928467,
|
|
"z": -16.631840467453003
|
|
}, {
|
|
"x": 366.1614227294922,
|
|
"y": 271.6237449645996,
|
|
"z": -18.219159841537476
|
|
}, {
|
|
"x": 385.00938415527344,
|
|
"y": 305.3863334655762,
|
|
"z": -2.567722797393799
|
|
}, {
|
|
"x": 381.99771881103516,
|
|
"y": 304.9723720550537,
|
|
"z": -4.575215280056
|
|
}, {
|
|
"x": 405.078125,
|
|
"y": 203.21216583251953,
|
|
"z": 13.713973760604858,
|
|
"name": "leftEyebrow"
|
|
}, {
|
|
"x": 377.13207244873047,
|
|
"y": 268.4710121154785,
|
|
"z": -15.266278982162476
|
|
}, {
|
|
"x": 380.9713363647461,
|
|
"y": 205.36980628967285,
|
|
"z": -0.7250899076461792,
|
|
"name": "leftEyebrow"
|
|
}, {
|
|
"x": 381.7788314819336,
|
|
"y": 198.9268398284912,
|
|
"z": -1.184653863310814,
|
|
"name": "leftEyebrow"
|
|
}, {
|
|
"x": 385.5204772949219,
|
|
"y": 172.1484375,
|
|
"z": 16.04826807975769,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 407.94189453125,
|
|
"y": 196.76236152648926,
|
|
"z": 25.723915100097656
|
|
}, {
|
|
"x": 383.03890228271484,
|
|
"y": 184.5157527923584,
|
|
"z": 7.393874526023865
|
|
}, {
|
|
"x": 411.61781311035156,
|
|
"y": 210.79241752624512,
|
|
"z": 22.315845489501953,
|
|
"name": "leftEyebrow"
|
|
}, {
|
|
"x": 414.30870056152344,
|
|
"y": 208.4643030166626,
|
|
"z": 37.021894454956055
|
|
}, {
|
|
"x": 364.28722381591797,
|
|
"y": 298.35777282714844,
|
|
"z": -21.86065673828125
|
|
}, {
|
|
"x": 371.3682556152344,
|
|
"y": 299.78848457336426,
|
|
"z": -17.834001779556274
|
|
}, {
|
|
"x": 376.88201904296875,
|
|
"y": 301.6696071624756,
|
|
"z": -13.153743743896484
|
|
}, {
|
|
"x": 370.2193832397461,
|
|
"y": 270.49095153808594,
|
|
"z": -15.569736957550049
|
|
}, {
|
|
"x": 383.5081100463867,
|
|
"y": 305.2726364135742,
|
|
"z": -3.673594295978546
|
|
}, {
|
|
"x": 380.73760986328125,
|
|
"y": 305.96869468688965,
|
|
"z": -8.660228252410889
|
|
}, {
|
|
"x": 381.2334442138672,
|
|
"y": 304.63574409484863,
|
|
"z": -4.820316135883331,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 368.1698989868164,
|
|
"y": 264.8884963989258,
|
|
"z": -25.653886795043945
|
|
}, {
|
|
"x": 373.5087203979492,
|
|
"y": 303.4233856201172,
|
|
"z": -10.95950722694397,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 368.4544372558594,
|
|
"y": 303.29601287841797,
|
|
"z": -14.169161319732666,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 362.76554107666016,
|
|
"y": 303.5735607147217,
|
|
"z": -16.911956071853638,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 366.60980224609375,
|
|
"y": 324.8870658874512,
|
|
"z": -15.616422891616821
|
|
}, {
|
|
"x": 365.7067108154297,
|
|
"y": 315.95678329467773,
|
|
"z": -20.903596878051758,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 365.0083923339844,
|
|
"y": 311.2232208251953,
|
|
"z": -21.066999435424805
|
|
}, {
|
|
"x": 364.1508102416992,
|
|
"y": 307.0583438873291,
|
|
"z": -18.907777070999146
|
|
}, {
|
|
"x": 363.37512969970703,
|
|
"y": 304.5721435546875,
|
|
"z": -17.42550015449524,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 374.580078125,
|
|
"y": 304.3059539794922,
|
|
"z": -11.40302300453186,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 375.55362701416016,
|
|
"y": 305.0998020172119,
|
|
"z": -12.861957550048828
|
|
}, {
|
|
"x": 377.2437286376953,
|
|
"y": 307.1674346923828,
|
|
"z": -14.215847253799438
|
|
}, {
|
|
"x": 378.68587493896484,
|
|
"y": 309.9015712738037,
|
|
"z": -13.223772048950195,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 383.8992691040039,
|
|
"y": 290.29629707336426,
|
|
"z": -9.97326910495758
|
|
}, {
|
|
"x": 423.3871841430664,
|
|
"y": 271.91688537597656,
|
|
"z": 74.37058925628662,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 377.68043518066406,
|
|
"y": 304.62209701538086,
|
|
"z": -7.603961229324341,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 379.00428771972656,
|
|
"y": 304.9314594268799,
|
|
"z": -8.57852816581726
|
|
}, {
|
|
"x": 364.00279998779297,
|
|
"y": 275.2813911437988,
|
|
"z": -19.25792098045349
|
|
}, {
|
|
"x": 374.68231201171875,
|
|
"y": 273.82555961608887,
|
|
"z": -11.28047227859497
|
|
}, {
|
|
"x": 365.0354766845703,
|
|
"y": 273.4548568725586,
|
|
"z": -18.791062831878662
|
|
}, {
|
|
"x": 380.61901092529297,
|
|
"y": 249.8848056793213,
|
|
"z": 0.15501167625188828
|
|
}, {
|
|
"x": 391.14158630371094,
|
|
"y": 254.7934627532959,
|
|
"z": 2.0906515419483185
|
|
}, {
|
|
"x": 378.1761169433594,
|
|
"y": 264.9612236022949,
|
|
"z": -12.605184316635132
|
|
}, {
|
|
"x": 400.9540557861328,
|
|
"y": 179.99592304229736,
|
|
"z": 27.82477855682373,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 398.0038833618164,
|
|
"y": 188.50656509399414,
|
|
"z": 16.094952821731567
|
|
}, {
|
|
"x": 394.8717498779297,
|
|
"y": 199.0359592437744,
|
|
"z": 6.226727366447449,
|
|
"name": "leftEyebrow"
|
|
}, {
|
|
"x": 382.10926055908203,
|
|
"y": 316.83926582336426,
|
|
"z": -8.946179747581482
|
|
}, {
|
|
"x": 366.51588439941406,
|
|
"y": 200.32583713531494,
|
|
"z": -5.24632453918457,
|
|
"name": "leftEyebrow"
|
|
}, {
|
|
"x": 367.4893569946289,
|
|
"y": 183.87210845947266,
|
|
"z": 1.9039081037044525
|
|
}, {
|
|
"x": 368.6243438720703,
|
|
"y": 168.8127565383911,
|
|
"z": 8.736093044281006,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 398.96175384521484,
|
|
"y": 234.9675178527832,
|
|
"z": 13.713973760604858
|
|
}, {
|
|
"x": 412.9645538330078,
|
|
"y": 242.23042488098145,
|
|
"z": 23.272905349731445
|
|
}, {
|
|
"x": 372.05257415771484,
|
|
"y": 231.41919136047363,
|
|
"z": 9.226294755935669
|
|
}, {
|
|
"x": 406.0722351074219,
|
|
"y": 223.58965873718262,
|
|
"z": 18.370890617370605
|
|
}, {
|
|
"x": 368.27442169189453,
|
|
"y": 240.2039337158203,
|
|
"z": -4.166713654994965
|
|
}, {
|
|
"x": 372.3575210571289,
|
|
"y": 260.66442489624023,
|
|
"z": -24.976940155029297
|
|
}, {
|
|
"x": 419.2244338989258,
|
|
"y": 247.9079246520996,
|
|
"z": 30.299127101898193
|
|
}, {
|
|
"x": 409.43885803222656,
|
|
"y": 246.60913467407227,
|
|
"z": 16.398411989212036
|
|
}, {
|
|
"x": 401.69139862060547,
|
|
"y": 248.76328468322754,
|
|
"z": 9.395531415939331
|
|
}, {
|
|
"x": 389.7608184814453,
|
|
"y": 247.56915092468262,
|
|
"z": 5.841569304466248
|
|
}, {
|
|
"x": 380.5461883544922,
|
|
"y": 244.55984115600586,
|
|
"z": 4.263003468513489
|
|
}, {
|
|
"x": 373.25817108154297,
|
|
"y": 240.80214500427246,
|
|
"z": 2.5356262922286987
|
|
}, {
|
|
"x": 358.77086639404297,
|
|
"y": 229.35615062713623,
|
|
"z": -10.387605428695679
|
|
}, {
|
|
"x": 419.5793914794922,
|
|
"y": 262.8478717803955,
|
|
"z": 26.5175724029541
|
|
}, {
|
|
"x": 410.8808898925781,
|
|
"y": 222.51372814178467,
|
|
"z": 22.199130058288574
|
|
}, {
|
|
"x": 358.45714569091797,
|
|
"y": 268.91467094421387,
|
|
"z": -33.17030906677246
|
|
}, {
|
|
"x": 373.4129333496094,
|
|
"y": 251.6385841369629,
|
|
"z": -5.771540403366089
|
|
}, {
|
|
"x": 422.5408172607422,
|
|
"y": 239.23919677734375,
|
|
"z": 74.04378890991211,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 367.8171920776367,
|
|
"y": 236.58040523529053,
|
|
"z": 1.820748895406723
|
|
}, {
|
|
"x": 378.51959228515625,
|
|
"y": 266.2532329559326,
|
|
"z": -5.74819803237915
|
|
}, {
|
|
"x": 403.3472442626953,
|
|
"y": 229.05112266540527,
|
|
"z": 19.689764976501465
|
|
}, {
|
|
"x": 372.34840393066406,
|
|
"y": 256.6451168060303,
|
|
"z": -21.872329711914062
|
|
}, {
|
|
"x": 422.54566192626953,
|
|
"y": 289.1587829589844,
|
|
"z": 68.67491245269775,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 371.9297409057617,
|
|
"y": 228.90116214752197,
|
|
"z": 11.432201862335205,
|
|
"name": "leftEye"
|
|
}, {
|
|
"x": 366.21360778808594,
|
|
"y": 251.6158962249756,
|
|
"z": -28.19826364517212
|
|
}, {
|
|
"x": 409.1571807861328,
|
|
"y": 321.3156223297119,
|
|
"z": 20.2266526222229
|
|
}, {
|
|
"x": 408.52943420410156,
|
|
"y": 331.44238471984863,
|
|
"z": 31.09278917312622,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 424.2788314819336,
|
|
"y": 267.1992301940918,
|
|
"z": 50.467424392700195
|
|
}, {
|
|
"x": 415.60352325439453,
|
|
"y": 311.6528606414795,
|
|
"z": 30.579242706298828
|
|
}, {
|
|
"x": 418.12793731689453,
|
|
"y": 221.59927368164062,
|
|
"z": 46.26569747924805
|
|
}, {
|
|
"x": 385.68286895751953,
|
|
"y": 346.0184955596924,
|
|
"z": -5.70151150226593
|
|
}, {
|
|
"x": 357.82936096191406,
|
|
"y": 271.3758373260498,
|
|
"z": -24.836881160736084
|
|
}, {
|
|
"x": 379.588623046875,
|
|
"y": 257.5071716308594,
|
|
"z": -3.755294680595398
|
|
}, {
|
|
"x": 417.4592590332031,
|
|
"y": 234.71948146820068,
|
|
"z": 34.5475435256958
|
|
}, {
|
|
"x": 393.4684371948242,
|
|
"y": 231.58967971801758,
|
|
"z": 11.408859491348267,
|
|
"name": "leftEye"
|
|
}, {
|
|
"x": 387.8864288330078,
|
|
"y": 232.14245796203613,
|
|
"z": 9.51808214187622,
|
|
"name": "leftEye"
|
|
}, {
|
|
"x": 382.4981689453125,
|
|
"y": 307.5654888153076,
|
|
"z": -7.522260546684265,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 419.00169372558594,
|
|
"y": 277.8332805633545,
|
|
"z": 26.424202919006348
|
|
}, {
|
|
"x": 373.62953186035156,
|
|
"y": 357.6375102996826,
|
|
"z": -5.75986921787262,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 392.8708267211914,
|
|
"y": 347.72446632385254,
|
|
"z": 10.154176950454712,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 400.3953552246094,
|
|
"y": 341.0005187988281,
|
|
"z": 19.39797878265381,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 382.25440979003906,
|
|
"y": 231.66935920715332,
|
|
"z": 8.998700976371765,
|
|
"name": "leftEye"
|
|
}, {
|
|
"x": 377.14550018310547,
|
|
"y": 230.4228687286377,
|
|
"z": 9.804032444953918,
|
|
"name": "leftEye"
|
|
}, {
|
|
"x": 373.8358688354492,
|
|
"y": 229.64950561523438,
|
|
"z": 11.292144060134888,
|
|
"name": "leftEye"
|
|
}, {
|
|
"x": 414.5794677734375,
|
|
"y": 221.67891025543213,
|
|
"z": 29.412097930908203
|
|
}, {
|
|
"x": 377.00672149658203,
|
|
"y": 225.66201210021973,
|
|
"z": 9.360517263412476,
|
|
"name": "leftEye"
|
|
}, {
|
|
"x": 382.29530334472656,
|
|
"y": 224.8431158065796,
|
|
"z": 8.32175612449646,
|
|
"name": "leftEye"
|
|
}, {
|
|
"x": 387.5133514404297,
|
|
"y": 224.49507236480713,
|
|
"z": 8.917000889778137,
|
|
"name": "leftEye"
|
|
}, {
|
|
"x": 393.15906524658203,
|
|
"y": 225.24795055389404,
|
|
"z": 10.737749338150024,
|
|
"name": "leftEye"
|
|
}, {
|
|
"x": 397.05554962158203,
|
|
"y": 226.55359268188477,
|
|
"z": 13.002015352249146,
|
|
"name": "leftEye"
|
|
}, {
|
|
"x": 420.5299377441406,
|
|
"y": 221.014666557312,
|
|
"z": 65.40690422058105,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 397.06920623779297,
|
|
"y": 230.6661558151245,
|
|
"z": 13.807345628738403,
|
|
"name": "leftEye"
|
|
}, {
|
|
"x": 377.94647216796875,
|
|
"y": 285.1647090911865,
|
|
"z": -13.305472135543823
|
|
}, {
|
|
"x": 372.1118927001953,
|
|
"y": 267.1267318725586,
|
|
"z": -18.83774757385254
|
|
}, {
|
|
"x": 364.9968719482422,
|
|
"y": 282.24411964416504,
|
|
"z": -19.818150997161865
|
|
}, {
|
|
"x": 401.973876953125,
|
|
"y": 331.20131492614746,
|
|
"z": 11.566424369812012
|
|
}, {
|
|
"x": 394.3083190917969,
|
|
"y": 338.86693954467773,
|
|
"z": 3.142542541027069
|
|
}, {
|
|
"x": 373.9820861816406,
|
|
"y": 351.4504623413086,
|
|
"z": -13.50388765335083
|
|
}, {
|
|
"x": 414.3888854980469,
|
|
"y": 321.24735832214355,
|
|
"z": 45.51872253417969,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 373.44234466552734,
|
|
"y": 227.33163356781006,
|
|
"z": 10.626870393753052,
|
|
"name": "leftEye"
|
|
}, {
|
|
"x": 364.0731430053711,
|
|
"y": 240.31539916992188,
|
|
"z": -13.807345628738403
|
|
}, {
|
|
"x": 384.2658233642578,
|
|
"y": 353.3793067932129,
|
|
"z": 0.7385850697755814,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 423.20526123046875,
|
|
"y": 283.5176181793213,
|
|
"z": 47.152724266052246
|
|
}, {
|
|
"x": 369.42798614501953,
|
|
"y": 304.0898895263672,
|
|
"z": -14.647691249847412,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 370.63812255859375,
|
|
"y": 305.90051651000977,
|
|
"z": -16.211668252944946
|
|
}, {
|
|
"x": 371.91192626953125,
|
|
"y": 309.0167713165283,
|
|
"z": -17.84567356109619
|
|
}, {
|
|
"x": 373.0583953857422,
|
|
"y": 313.3545398712158,
|
|
"z": -17.378815412521362,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 375.39905548095703,
|
|
"y": 321.09289169311523,
|
|
"z": -13.118728399276733
|
|
}, {
|
|
"x": 379.2567825317383,
|
|
"y": 304.3582534790039,
|
|
"z": -7.924926280975342
|
|
}, {
|
|
"x": 381.18797302246094,
|
|
"y": 303.7031364440918,
|
|
"z": -7.843226194381714
|
|
}, {
|
|
"x": 383.0918502807617,
|
|
"y": 302.4884605407715,
|
|
"z": -7.6506465673446655,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 389.09461975097656,
|
|
"y": 297.1475315093994,
|
|
"z": -5.5497825145721436
|
|
}, {
|
|
"x": 411.6408920288086,
|
|
"y": 280.24898529052734,
|
|
"z": 12.02161192893982
|
|
}, {
|
|
"x": 363.3110809326172,
|
|
"y": 234.27620887756348,
|
|
"z": -6.775286793708801
|
|
}, {
|
|
"x": 366.0474395751953,
|
|
"y": 223.29872131347656,
|
|
"z": 6.827808618545532
|
|
}, {
|
|
"x": 370.34427642822266,
|
|
"y": 225.1457118988037,
|
|
"z": 9.558931589126587
|
|
}, {
|
|
"x": 377.5371551513672,
|
|
"y": 303.60079765319824,
|
|
"z": -7.358860373497009,
|
|
"name": "lips"
|
|
}, {
|
|
"x": 412.9557800292969,
|
|
"y": 299.53579902648926,
|
|
"z": 19.39797878265381
|
|
}, {
|
|
"x": 360.0810241699219,
|
|
"y": 221.72012329101562,
|
|
"z": -2.153385728597641
|
|
}, {
|
|
"x": 379.82784271240234,
|
|
"y": 329.47723388671875,
|
|
"z": -10.48097848892212
|
|
}, {
|
|
"x": 359.08477783203125,
|
|
"y": 235.7911491394043,
|
|
"z": -18.079102039337158
|
|
}, {
|
|
"x": 369.6688461303711,
|
|
"y": 251.5407943725586,
|
|
"z": -14.962821006774902
|
|
}, {
|
|
"x": 369.5555114746094,
|
|
"y": 333.5307312011719,
|
|
"z": -15.67478060722351
|
|
}, {
|
|
"x": 394.0193176269531,
|
|
"y": 315.6973171234131,
|
|
"z": -0.9920747578144073
|
|
}, {
|
|
"x": 383.78997802734375,
|
|
"y": 272.7268695831299,
|
|
"z": -4.689012169837952
|
|
}, {
|
|
"x": 387.67765045166016,
|
|
"y": 323.6722755432129,
|
|
"z": -5.640236139297485
|
|
}, {
|
|
"x": 397.8769302368164,
|
|
"y": 272.1331214904785,
|
|
"z": -0.9395531564950943
|
|
}, {
|
|
"x": 389.87476348876953,
|
|
"y": 280.5630111694336,
|
|
"z": -4.29218202829361
|
|
}, {
|
|
"x": 403.83888244628906,
|
|
"y": 285.1167869567871,
|
|
"z": 3.0229100584983826
|
|
}, {
|
|
"x": 372.5467300415039,
|
|
"y": 343.1070327758789,
|
|
"z": -16.153310537338257
|
|
}, {
|
|
"x": 374.1112518310547,
|
|
"y": 256.3721466064453,
|
|
"z": -10.574349164962769
|
|
}, {
|
|
"x": 399.73785400390625,
|
|
"y": 321.77515983581543,
|
|
"z": 4.849494695663452
|
|
}, {
|
|
"x": 392.03365325927734,
|
|
"y": 330.56447982788086,
|
|
"z": -1.3407598435878754
|
|
}, {
|
|
"x": 398.59134674072266,
|
|
"y": 305.93902587890625,
|
|
"z": 1.517290621995926
|
|
}, {
|
|
"x": 417.95997619628906,
|
|
"y": 290.9716987609863,
|
|
"z": 26.89105987548828
|
|
}, {
|
|
"x": 406.04541778564453,
|
|
"y": 307.35154151916504,
|
|
"z": 8.666064143180847
|
|
}, {
|
|
"x": 420.75328826904297,
|
|
"y": 298.40752601623535,
|
|
"z": 41.78385257720947
|
|
}, {
|
|
"x": 395.4522705078125,
|
|
"y": 291.4153575897217,
|
|
"z": -2.1752697229385376
|
|
}, {
|
|
"x": 368.6452102661133,
|
|
"y": 245.8882999420166,
|
|
"z": -9.453888535499573
|
|
}, {
|
|
"x": 370.34900665283203,
|
|
"y": 263.56690406799316,
|
|
"z": -26.75100326538086
|
|
}, {
|
|
"x": 374.98477935791016,
|
|
"y": 266.6126346588135,
|
|
"z": -19.77146625518799
|
|
}, {
|
|
"x": 366.99840545654297,
|
|
"y": 258.12140464782715,
|
|
"z": -31.372904777526855
|
|
}, {
|
|
"x": 371.00616455078125,
|
|
"y": 217.63479709625244,
|
|
"z": 5.60522198677063
|
|
}, {
|
|
"x": 381.30577087402344,
|
|
"y": 214.14087295532227,
|
|
"z": 4.983716309070587
|
|
}, {
|
|
"x": 390.1496124267578,
|
|
"y": 213.38221549987793,
|
|
"z": 5.593550801277161
|
|
}, {
|
|
"x": 397.7696990966797,
|
|
"y": 214.3659782409668,
|
|
"z": 8.57852816581726
|
|
}, {
|
|
"x": 403.1652069091797,
|
|
"y": 217.65509605407715,
|
|
"z": 13.013685941696167
|
|
}, {
|
|
"x": 407.3551940917969,
|
|
"y": 230.72525024414062,
|
|
"z": 22.444231510162354
|
|
}, {
|
|
"x": 424.0876770019531,
|
|
"y": 251.7839241027832,
|
|
"z": 51.16771221160889
|
|
}, {
|
|
"x": 403.50196838378906,
|
|
"y": 239.88757610321045,
|
|
"z": 15.803166627883911
|
|
}, {
|
|
"x": 397.31719970703125,
|
|
"y": 241.49806022644043,
|
|
"z": 11.233787536621094
|
|
}, {
|
|
"x": 388.99425506591797,
|
|
"y": 241.4366912841797,
|
|
"z": 7.948269248008728
|
|
}, {
|
|
"x": 380.7804489135742,
|
|
"y": 239.78078842163086,
|
|
"z": 6.600214838981628
|
|
}, {
|
|
"x": 374.01336669921875,
|
|
"y": 237.11946487426758,
|
|
"z": 6.349278092384338
|
|
}, {
|
|
"x": 369.39125061035156,
|
|
"y": 234.35351371765137,
|
|
"z": 5.987462401390076
|
|
}, {
|
|
"x": 422.9730987548828,
|
|
"y": 255.76455116271973,
|
|
"z": 76.61150932312012,
|
|
"name": "faceOval"
|
|
}, {
|
|
"x": 374.73915100097656,
|
|
"y": 269.24214363098145,
|
|
"z": -16.608498096466064
|
|
}, {
|
|
"x": 364.61681365966797,
|
|
"y": 245.71088790893555,
|
|
"z": -20.02823829650879
|
|
}, {
|
|
"x": 365.3834533691406,
|
|
"y": 263.34174156188965,
|
|
"z": -32.32996463775635
|
|
}, {
|
|
"x": 361.58252716064453,
|
|
"y": 267.8273677825928,
|
|
"z": -30.345816612243652
|
|
}, {
|
|
"x": 365.37208557128906,
|
|
"y": 265.0249671936035,
|
|
"z": -29.178667068481445
|
|
}, {
|
|
"x": 372.72605895996094,
|
|
"y": 272.05135345458984,
|
|
"z": -14.834434986114502
|
|
}, {
|
|
"x": 360.48614501953125,
|
|
"y": 268.34827423095703,
|
|
"z": -32.189905643463135
|
|
}, {
|
|
"x": 359.9516296386719,
|
|
"y": 270.8049201965332,
|
|
"z": -24.650139808654785
|
|
}, {
|
|
"x": 369.5049285888672,
|
|
"y": 229.01945114135742,
|
|
"z": 10.107489824295044
|
|
}, {
|
|
"x": 365.5447769165039,
|
|
"y": 230.24096488952637,
|
|
"z": 5.593550801277161
|
|
}, {
|
|
"x": 363.50669860839844,
|
|
"y": 230.6208372116089,
|
|
"z": 0.43622106313705444
|
|
}, {
|
|
"x": 399.3529510498047,
|
|
"y": 227.65677452087402,
|
|
"z": 15.35965085029602,
|
|
"name": "leftEye"
|
|
}, {
|
|
"x": 402.5693130493164,
|
|
"y": 224.60190296173096,
|
|
"z": 15.931552648544312
|
|
}],
|
|
"box": {
|
|
"xMin": 277.8318977355957,
|
|
"yMin": 168.7741756439209,
|
|
"xMax": 424.2788314819336,
|
|
"yMax": 359.8348903656006,
|
|
"width": 146.4469337463379,
|
|
"height": 191.0607147216797
|
|
}
|
|
},
|
|
// Tasks-vision: https://developers.google.com/mediapipe/solutions/vision/face_landmarker/web_js
|
|
// prettier-ignore
|
|
SAMPLE_FACELANDMARKER_RESULT: {
|
|
"faceLandmarks": [[{
|
|
"x": 0.5760777592658997,
|
|
"y": 0.8639070391654968,
|
|
"z": -0.030997956171631813
|
|
}, {
|
|
"x": 0.572094738483429,
|
|
"y": 0.7886289358139038,
|
|
"z": -0.07189624011516571
|
|
}, {
|
|
"x": 0.5723551511764526,
|
|
"y": 0.8075382709503174,
|
|
"z": -0.03578168898820877
|
|
}, {
|
|
"x": 0.5548420548439026,
|
|
"y": 0.7188365459442139,
|
|
"z": -0.057787876576185226
|
|
}, {
|
|
"x": 0.5706077814102173,
|
|
"y": 0.7674974799156189,
|
|
"z": -0.07740399986505508
|
|
}, {
|
|
"x": 0.5681378245353699,
|
|
"y": 0.7387768030166626,
|
|
"z": -0.07356284558773041
|
|
}, {
|
|
"x": 0.5621535181999207,
|
|
"y": 0.6681165099143982,
|
|
"z": -0.04189874976873398
|
|
}, {
|
|
"x": 0.46613582968711853,
|
|
"y": 0.6679812073707581,
|
|
"z": 0.011289681307971478
|
|
}, {
|
|
"x": 0.5579932928085327,
|
|
"y": 0.6174106597900391,
|
|
"z": -0.03502821549773216
|
|
}, {
|
|
"x": 0.5563451647758484,
|
|
"y": 0.5905600190162659,
|
|
"z": -0.03928658738732338
|
|
}, {
|
|
"x": 0.5487832427024841,
|
|
"y": 0.4900572597980499,
|
|
"z": -0.029898937791585922
|
|
}, {
|
|
"x": 0.5765544176101685,
|
|
"y": 0.8692144751548767,
|
|
"z": -0.02831427752971649
|
|
}, {
|
|
"x": 0.5771114230155945,
|
|
"y": 0.873644232749939,
|
|
"z": -0.02345779910683632
|
|
}, {
|
|
"x": 0.5771905779838562,
|
|
"y": 0.877016007900238,
|
|
"z": -0.016658689826726913
|
|
}, {
|
|
"x": 0.5778058767318726,
|
|
"y": 0.8770116567611694,
|
|
"z": -0.014505492523312569
|
|
}, {
|
|
"x": 0.5783766508102417,
|
|
"y": 0.8835000991821289,
|
|
"z": -0.015996402129530907
|
|
}, {
|
|
"x": 0.5792440176010132,
|
|
"y": 0.8913810849189758,
|
|
"z": -0.01924579218029976
|
|
}, {
|
|
"x": 0.5796768069267273,
|
|
"y": 0.8996334671974182,
|
|
"z": -0.018261712044477463
|
|
}, {
|
|
"x": 0.5817288160324097,
|
|
"y": 0.9255813956260681,
|
|
"z": -0.007126849144697189
|
|
}, {
|
|
"x": 0.5726592540740967,
|
|
"y": 0.7992473244667053,
|
|
"z": -0.0643521398305893
|
|
}, {
|
|
"x": 0.5579419136047363,
|
|
"y": 0.7996989488601685,
|
|
"z": -0.04566684365272522
|
|
}, {
|
|
"x": 0.4216199815273285,
|
|
"y": 0.5958762764930725,
|
|
"z": 0.06776496022939682
|
|
}, {
|
|
"x": 0.5052269697189331,
|
|
"y": 0.6796539425849915,
|
|
"z": -0.0010737782577052712
|
|
}, {
|
|
"x": 0.49243026971817017,
|
|
"y": 0.6838865876197815,
|
|
"z": -5227324436418712e-19
|
|
}, {
|
|
"x": 0.4796970784664154,
|
|
"y": 0.6856290102005005,
|
|
"z": 0.002684245817363262
|
|
}, {
|
|
"x": 0.4618356227874756,
|
|
"y": 0.6764569878578186,
|
|
"z": 0.013439622707664967
|
|
}, {
|
|
"x": 0.5160380601882935,
|
|
"y": 0.6737282276153564,
|
|
"z": -17607348127057776e-21
|
|
}, {
|
|
"x": 0.48070961236953735,
|
|
"y": 0.6255870461463928,
|
|
"z": -0.008339674212038517
|
|
}, {
|
|
"x": 0.49719780683517456,
|
|
"y": 0.6256808042526245,
|
|
"z": -0.008027955889701843
|
|
}, {
|
|
"x": 0.46674346923828125,
|
|
"y": 0.6317623853683472,
|
|
"z": -0.004460199736058712
|
|
}, {
|
|
"x": 0.4582492709159851,
|
|
"y": 0.641118049621582,
|
|
"z": 0.0011905613355338573
|
|
}, {
|
|
"x": 0.45408669114112854,
|
|
"y": 0.6911458969116211,
|
|
"z": 0.020514748990535736
|
|
}, {
|
|
"x": 0.535312294960022,
|
|
"y": 0.9619986414909363,
|
|
"z": 0.012499462813138962
|
|
}, {
|
|
"x": 0.4608460068702698,
|
|
"y": 0.6628725528717041,
|
|
"z": 0.01517564244568348
|
|
}, {
|
|
"x": 0.4206731915473938,
|
|
"y": 0.6828458309173584,
|
|
"z": 0.07848648726940155
|
|
}, {
|
|
"x": 0.4390624463558197,
|
|
"y": 0.6796106696128845,
|
|
"z": 0.03283142298460007
|
|
}, {
|
|
"x": 0.5029968619346619,
|
|
"y": 0.7701570391654968,
|
|
"z": -0.009734481573104858
|
|
}, {
|
|
"x": 0.5595027208328247,
|
|
"y": 0.8607323169708252,
|
|
"z": -0.030043255537748337
|
|
}, {
|
|
"x": 0.5621269941329956,
|
|
"y": 0.8738374710083008,
|
|
"z": -0.021709579974412918
|
|
}, {
|
|
"x": 0.5451499819755554,
|
|
"y": 0.865527331829071,
|
|
"z": -0.022014077752828598
|
|
}, {
|
|
"x": 0.5351184010505676,
|
|
"y": 0.8705098032951355,
|
|
"z": -0.011602800339460373
|
|
}, {
|
|
"x": 0.5495014190673828,
|
|
"y": 0.8744956254959106,
|
|
"z": -0.016490943729877472
|
|
}, {
|
|
"x": 0.5395170450210571,
|
|
"y": 0.8759440779685974,
|
|
"z": -0.007333362940698862
|
|
}, {
|
|
"x": 0.5183624029159546,
|
|
"y": 0.8959754705429077,
|
|
"z": 0.010520773939788342
|
|
}, {
|
|
"x": 0.5604349374771118,
|
|
"y": 0.7895449995994568,
|
|
"z": -0.07082037627696991
|
|
}, {
|
|
"x": 0.557381272315979,
|
|
"y": 0.7687489986419678,
|
|
"z": -0.07590588927268982
|
|
}, {
|
|
"x": 0.4432901442050934,
|
|
"y": 0.6308897733688354,
|
|
"z": 0.0027153254486620426
|
|
}, {
|
|
"x": 0.5258325338363647,
|
|
"y": 0.7151225805282593,
|
|
"z": -0.014676518738269806
|
|
}, {
|
|
"x": 0.5271827578544617,
|
|
"y": 0.7833116054534912,
|
|
"z": -0.037643320858478546
|
|
}, {
|
|
"x": 0.5257382988929749,
|
|
"y": 0.7717816233634949,
|
|
"z": -0.03401920944452286
|
|
}, {
|
|
"x": 0.46516409516334534,
|
|
"y": 0.7705106735229492,
|
|
"z": 0.0065747760236263275
|
|
}, {
|
|
"x": 0.5558893084526062,
|
|
"y": 0.7420997619628906,
|
|
"z": -0.0694495290517807
|
|
}, {
|
|
"x": 0.4720408320426941,
|
|
"y": 0.6066038608551025,
|
|
"z": -0.021204356104135513
|
|
}, {
|
|
"x": 0.45432573556900024,
|
|
"y": 0.6158540844917297,
|
|
"z": -0.011054684408009052
|
|
}, {
|
|
"x": 0.4305151402950287,
|
|
"y": 0.5608053803443909,
|
|
"z": 0.0396830290555954
|
|
}, {
|
|
"x": 0.5310865640640259,
|
|
"y": 0.6157484650611877,
|
|
"z": -0.03081176057457924
|
|
}, {
|
|
"x": 0.5114666223526001,
|
|
"y": 0.6329749226570129,
|
|
"z": -0.00335998204536736
|
|
}, {
|
|
"x": 0.506435751914978,
|
|
"y": 0.8786543607711792,
|
|
"z": 0.012980876490473747
|
|
}, {
|
|
"x": 0.4480472207069397,
|
|
"y": 0.8640613555908203,
|
|
"z": 0.12569651007652283
|
|
}, {
|
|
"x": 0.5372058153152466,
|
|
"y": 0.7942581176757812,
|
|
"z": -0.03168361634016037
|
|
}, {
|
|
"x": 0.5488379597663879,
|
|
"y": 0.8001630306243896,
|
|
"z": -0.03280917927622795
|
|
}, {
|
|
"x": 0.5213388204574585,
|
|
"y": 0.8794381618499756,
|
|
"z": 0.011892606504261494
|
|
}, {
|
|
"x": 0.5242055654525757,
|
|
"y": 0.8789222240447998,
|
|
"z": 0.008370225317776203
|
|
}, {
|
|
"x": 0.4477175176143646,
|
|
"y": 0.6039950251579285,
|
|
"z": -0.0050799972377717495
|
|
}, {
|
|
"x": 0.526964008808136,
|
|
"y": 0.7916748523712158,
|
|
"z": -0.02968614175915718
|
|
}, {
|
|
"x": 0.4971255660057068,
|
|
"y": 0.6050706505775452,
|
|
"z": -0.028175678104162216
|
|
}, {
|
|
"x": 0.4938119053840637,
|
|
"y": 0.5882453918457031,
|
|
"z": -0.03210941329598427
|
|
}, {
|
|
"x": 0.4757143557071686,
|
|
"y": 0.5094879865646362,
|
|
"z": -0.01300730835646391
|
|
}, {
|
|
"x": 0.43947282433509827,
|
|
"y": 0.5816648006439209,
|
|
"z": 0.01415177434682846
|
|
}, {
|
|
"x": 0.485664039850235,
|
|
"y": 0.5477864146232605,
|
|
"z": -0.023685332387685776
|
|
}, {
|
|
"x": 0.43635931611061096,
|
|
"y": 0.6226438283920288,
|
|
"z": 0.013606148771941662
|
|
}, {
|
|
"x": 0.42910251021385193,
|
|
"y": 0.6102726459503174,
|
|
"z": 0.03926564007997513
|
|
}, {
|
|
"x": 0.5605402588844299,
|
|
"y": 0.8680099248886108,
|
|
"z": -0.027318159118294716
|
|
}, {
|
|
"x": 0.5474816560745239,
|
|
"y": 0.8702861070632935,
|
|
"z": -0.019686367362737656
|
|
}, {
|
|
"x": 0.5373021364212036,
|
|
"y": 0.8728838562965393,
|
|
"z": -0.010484928265213966
|
|
}, {
|
|
"x": 0.540735125541687,
|
|
"y": 0.7979167103767395,
|
|
"z": -0.029073253273963928
|
|
}, {
|
|
"x": 0.5228585004806519,
|
|
"y": 0.87913578748703,
|
|
"z": 0.009915109723806381
|
|
}, {
|
|
"x": 0.530497670173645,
|
|
"y": 0.8815253973007202,
|
|
"z": 0.0020524784922599792
|
|
}, {
|
|
"x": 0.5259912610054016,
|
|
"y": 0.8790552616119385,
|
|
"z": 0.007895970717072487
|
|
}, {
|
|
"x": 0.5433906316757202,
|
|
"y": 0.7882310748100281,
|
|
"z": -0.05121905356645584
|
|
}, {
|
|
"x": 0.541388213634491,
|
|
"y": 0.8777219653129578,
|
|
"z": -0.00466804439201951
|
|
}, {
|
|
"x": 0.5515822172164917,
|
|
"y": 0.8767023086547852,
|
|
"z": -0.010475946590304375
|
|
}, {
|
|
"x": 0.5637003779411316,
|
|
"y": 0.877059817314148,
|
|
"z": -0.015273625031113625
|
|
}, {
|
|
"x": 0.5640299320220947,
|
|
"y": 0.9263423085212708,
|
|
"z": -0.00658724969252944
|
|
}, {
|
|
"x": 0.5642300248146057,
|
|
"y": 0.8993074893951416,
|
|
"z": -0.017653480172157288
|
|
}, {
|
|
"x": 0.5637336373329163,
|
|
"y": 0.8910360932350159,
|
|
"z": -0.01852807030081749
|
|
}, {
|
|
"x": 0.5637134313583374,
|
|
"y": 0.8837276697158813,
|
|
"z": -0.01482592523097992
|
|
}, {
|
|
"x": 0.564205527305603,
|
|
"y": 0.8768964409828186,
|
|
"z": -0.01331155002117157
|
|
}, {
|
|
"x": 0.5419867634773254,
|
|
"y": 0.8778373599052429,
|
|
"z": -0.0037720394320786
|
|
}, {
|
|
"x": 0.5404468774795532,
|
|
"y": 0.880696177482605,
|
|
"z": -0.005610354244709015
|
|
}, {
|
|
"x": 0.5392338633537292,
|
|
"y": 0.8845721483230591,
|
|
"z": -0.007352025713771582
|
|
}, {
|
|
"x": 0.538469672203064,
|
|
"y": 0.8891173601150513,
|
|
"z": -0.005154991988092661
|
|
}, {
|
|
"x": 0.5189250111579895,
|
|
"y": 0.8452741503715515,
|
|
"z": -0.009755070321261883
|
|
}, {
|
|
"x": 0.4258975088596344,
|
|
"y": 0.7662280797958374,
|
|
"z": 0.1387351155281067
|
|
}, {
|
|
"x": 0.5725725293159485,
|
|
"y": 0.8041572570800781,
|
|
"z": -0.04583907872438431
|
|
}, {
|
|
"x": 0.5342061519622803,
|
|
"y": 0.8785833120346069,
|
|
"z": 0.002659974154084921
|
|
}, {
|
|
"x": 0.5324031114578247,
|
|
"y": 0.8804071545600891,
|
|
"z": 0.0017832003068178892
|
|
}, {
|
|
"x": 0.5538818836212158,
|
|
"y": 0.8078407645225525,
|
|
"z": -0.03254539892077446
|
|
}, {
|
|
"x": 0.5325431823730469,
|
|
"y": 0.8026832938194275,
|
|
"z": -0.019140373915433884
|
|
}, {
|
|
"x": 0.5514076948165894,
|
|
"y": 0.8043903112411499,
|
|
"z": -0.03313535451889038
|
|
}, {
|
|
"x": 0.5131856203079224,
|
|
"y": 0.7284771800041199,
|
|
"z": -0.009399853646755219
|
|
}, {
|
|
"x": 0.49331504106521606,
|
|
"y": 0.7443980574607849,
|
|
"z": -0.005225230939686298
|
|
}, {
|
|
"x": 0.5239617824554443,
|
|
"y": 0.7807451486587524,
|
|
"z": -0.025881027802824974
|
|
}, {
|
|
"x": 0.4473606050014496,
|
|
"y": 0.5315827131271362,
|
|
"z": 0.011164786294102669
|
|
}, {
|
|
"x": 0.45718759298324585,
|
|
"y": 0.5604941248893738,
|
|
"z": -0.005943301599472761
|
|
}, {
|
|
"x": 0.4670005738735199,
|
|
"y": 0.5909327268600464,
|
|
"z": -0.019681761041283607
|
|
}, {
|
|
"x": 0.5311570167541504,
|
|
"y": 0.9076261520385742,
|
|
"z": 0.00389476353302598
|
|
}, {
|
|
"x": 0.5249923467636108,
|
|
"y": 0.5893563628196716,
|
|
"z": -0.037981919944286346
|
|
}, {
|
|
"x": 0.5166932344436646,
|
|
"y": 0.5429551005363464,
|
|
"z": -0.03319704160094261
|
|
}, {
|
|
"x": 0.5085030198097229,
|
|
"y": 0.49676206707954407,
|
|
"z": -0.02691275253891945
|
|
}, {
|
|
"x": 0.4687720239162445,
|
|
"y": 0.6834565997123718,
|
|
"z": 0.008113506250083447
|
|
}, {
|
|
"x": 0.4426414966583252,
|
|
"y": 0.7069531679153442,
|
|
"z": 0.028577271848917007
|
|
}, {
|
|
"x": 0.5230373740196228,
|
|
"y": 0.6675713658332825,
|
|
"z": 0.001773772411979735
|
|
}, {
|
|
"x": 0.4481240212917328,
|
|
"y": 0.6527872085571289,
|
|
"z": 0.012414850294589996
|
|
}, {
|
|
"x": 0.5339856743812561,
|
|
"y": 0.7012367844581604,
|
|
"z": -0.020220188423991203
|
|
}, {
|
|
"x": 0.5347223281860352,
|
|
"y": 0.7761190533638,
|
|
"z": -0.05141595005989075
|
|
}, {
|
|
"x": 0.4315067231655121,
|
|
"y": 0.7211957573890686,
|
|
"z": 0.04381405934691429
|
|
}, {
|
|
"x": 0.45203351974487305,
|
|
"y": 0.7206180095672607,
|
|
"z": 0.017288070172071457
|
|
}, {
|
|
"x": 0.46892452239990234,
|
|
"y": 0.7265436053276062,
|
|
"z": 0.005602988880127668
|
|
}, {
|
|
"x": 0.49314674735069275,
|
|
"y": 0.7202282547950745,
|
|
"z": -6408205372281373e-19
|
|
}, {
|
|
"x": 0.5104925632476807,
|
|
"y": 0.7091827392578125,
|
|
"z": -0.00362918758764863
|
|
}, {
|
|
"x": 0.5232142210006714,
|
|
"y": 0.698553740978241,
|
|
"z": -0.00787867046892643
|
|
}, {
|
|
"x": 0.5497883558273315,
|
|
"y": 0.6743605136871338,
|
|
"z": -0.036349106580019
|
|
}, {
|
|
"x": 0.43658503890037537,
|
|
"y": 0.7627100348472595,
|
|
"z": 0.042555369436740875
|
|
}, {
|
|
"x": 0.4397648870944977,
|
|
"y": 0.6528646349906921,
|
|
"z": 0.017956094816327095
|
|
}, {
|
|
"x": 0.5653332471847534,
|
|
"y": 0.7992802858352661,
|
|
"z": -0.06365057826042175
|
|
}, {
|
|
"x": 0.5285563468933105,
|
|
"y": 0.736810564994812,
|
|
"z": -0.018836988136172295
|
|
}, {
|
|
"x": 0.4180678725242615,
|
|
"y": 0.6792560815811157,
|
|
"z": 0.12284679710865021
|
|
}, {
|
|
"x": 0.5328429937362671,
|
|
"y": 0.6865872144699097,
|
|
"z": -0.010484723374247551
|
|
}, {
|
|
"x": 0.5230283141136169,
|
|
"y": 0.7809416055679321,
|
|
"z": -0.011922398582100868
|
|
}, {
|
|
"x": 0.4551771283149719,
|
|
"y": 0.6650775074958801,
|
|
"z": 0.01774493046104908
|
|
}, {
|
|
"x": 0.5337203741073608,
|
|
"y": 0.7618928551673889,
|
|
"z": -0.04697106033563614
|
|
}, {
|
|
"x": 0.43463975191116333,
|
|
"y": 0.8133478164672852,
|
|
"z": 0.1354849934577942
|
|
}, {
|
|
"x": 0.5225707292556763,
|
|
"y": 0.6605283617973328,
|
|
"z": 0.004980515688657761
|
|
}, {
|
|
"x": 0.5441933870315552,
|
|
"y": 0.7497199773788452,
|
|
"z": -0.06091512367129326
|
|
}, {
|
|
"x": 0.4774007797241211,
|
|
"y": 0.9159183502197266,
|
|
"z": 0.059622734785079956
|
|
}, {
|
|
"x": 0.48068761825561523,
|
|
"y": 0.9364941716194153,
|
|
"z": 0.08404944837093353
|
|
}, {
|
|
"x": 0.4268292486667633,
|
|
"y": 0.7657528519630432,
|
|
"z": 0.09051097184419632
|
|
}, {
|
|
"x": 0.46051913499832153,
|
|
"y": 0.8880485892295837,
|
|
"z": 0.0738474428653717
|
|
}, {
|
|
"x": 0.4243420660495758,
|
|
"y": 0.6434382200241089,
|
|
"z": 0.06230505183339119
|
|
}, {
|
|
"x": 0.5342157483100891,
|
|
"y": 0.9835634231567383,
|
|
"z": 0.021662971004843712
|
|
}, {
|
|
"x": 0.5668109655380249,
|
|
"y": 0.8042187094688416,
|
|
"z": -0.044937074184417725
|
|
}, {
|
|
"x": 0.5176341533660889,
|
|
"y": 0.7530587315559387,
|
|
"z": -0.012967454269528389
|
|
}, {
|
|
"x": 0.430206298828125,
|
|
"y": 0.6835605502128601,
|
|
"z": 0.04612284153699875
|
|
}, {
|
|
"x": 0.4794231951236725,
|
|
"y": 0.6732114553451538,
|
|
"z": 0.003970044665038586
|
|
}, {
|
|
"x": 0.49073347449302673,
|
|
"y": 0.6722435355186462,
|
|
"z": 8692514384165406e-19
|
|
}, {
|
|
"x": 0.5294116139411926,
|
|
"y": 0.884677529335022,
|
|
"z": 0.004413890186697245
|
|
}, {
|
|
"x": 0.4430122375488281,
|
|
"y": 0.80235356092453,
|
|
"z": 0.04987282305955887
|
|
}, {
|
|
"x": 0.5603825449943542,
|
|
"y": 1.0092442035675049,
|
|
"z": 0.026417359709739685
|
|
}, {
|
|
"x": 0.5186598300933838,
|
|
"y": 0.9828659892082214,
|
|
"z": 0.0513598807156086
|
|
}, {
|
|
"x": 0.5010536909103394,
|
|
"y": 0.9640932679176331,
|
|
"z": 0.06591596454381943
|
|
}, {
|
|
"x": 0.5524769425392151,
|
|
"y": 0.539441704750061,
|
|
"z": -0.035816047340631485
|
|
}, {
|
|
"x": 0.5879997611045837,
|
|
"y": 1.0091472864151,
|
|
"z": 0.02285068854689598
|
|
}, {
|
|
"x": 0.5016193985939026,
|
|
"y": 0.6684437990188599,
|
|
"z": 28415941051207483e-20
|
|
}, {
|
|
"x": 0.511952817440033,
|
|
"y": 0.6642197370529175,
|
|
"z": 0.0021144719794392586
|
|
}, {
|
|
"x": 0.5194343328475952,
|
|
"y": 0.6623469591140747,
|
|
"z": 0.004674181342124939
|
|
}, {
|
|
"x": 0.4321230351924896,
|
|
"y": 0.6496355533599854,
|
|
"z": 0.03124697133898735
|
|
}, {
|
|
"x": 0.508686363697052,
|
|
"y": 0.6479565501213074,
|
|
"z": -44765998609364033e-20
|
|
}, {
|
|
"x": 0.4963986277580261,
|
|
"y": 0.6431032419204712,
|
|
"z": -0.0032507688738405704
|
|
}, {
|
|
"x": 0.4845542013645172,
|
|
"y": 0.6430778503417969,
|
|
"z": -0.002903624437749386
|
|
}, {
|
|
"x": 0.4733612537384033,
|
|
"y": 0.647506833076477,
|
|
"z": 23347247042693198e-20
|
|
}, {
|
|
"x": 0.4668654501438141,
|
|
"y": 0.653346598148346,
|
|
"z": 0.004762572236359119
|
|
}, {
|
|
"x": 0.41815051436424255,
|
|
"y": 0.633708119392395,
|
|
"z": 0.09809435904026031
|
|
}, {
|
|
"x": 0.47159942984580994,
|
|
"y": 0.6711485385894775,
|
|
"z": 0.007849935442209244
|
|
}, {
|
|
"x": 0.5734396576881409,
|
|
"y": 0.8256140351295471,
|
|
"z": -0.03155219927430153
|
|
}, {
|
|
"x": 0.5306524038314819,
|
|
"y": 0.8337990641593933,
|
|
"z": -0.018351426348090172
|
|
}, {
|
|
"x": 0.5371729135513306,
|
|
"y": 0.7910830974578857,
|
|
"z": -0.037286680191755295
|
|
}, {
|
|
"x": 0.5549534559249878,
|
|
"y": 0.8275275826454163,
|
|
"z": -0.030664825811982155
|
|
}, {
|
|
"x": 0.5597432255744934,
|
|
"y": 0.6418541669845581,
|
|
"z": -0.03318847343325615
|
|
}, {
|
|
"x": 0.4958484172821045,
|
|
"y": 0.9429569244384766,
|
|
"z": 0.048340678215026855
|
|
}, {
|
|
"x": 0.5140507817268372,
|
|
"y": 0.9634028077125549,
|
|
"z": 0.03589847311377525
|
|
}, {
|
|
"x": 0.5587693452835083,
|
|
"y": 0.9951097369194031,
|
|
"z": 0.00908728688955307
|
|
}, {
|
|
"x": 0.46411189436912537,
|
|
"y": 0.9051855206489563,
|
|
"z": 0.10601935535669327
|
|
}, {
|
|
"x": 0.5181609392166138,
|
|
"y": 0.6554316878318787,
|
|
"z": 0.002546071307733655
|
|
}, {
|
|
"x": 0.5436590909957886,
|
|
"y": 0.7085841298103333,
|
|
"z": -0.03844436630606651
|
|
}, {
|
|
"x": 0.5872187614440918,
|
|
"y": 0.9960382580757141,
|
|
"z": 0.0063423276878893375
|
|
}, {
|
|
"x": 0.5379653573036194,
|
|
"y": 0.9989125728607178,
|
|
"z": 0.03636329993605614
|
|
}, {
|
|
"x": 0.4350326955318451,
|
|
"y": 0.8088565468788147,
|
|
"z": 0.09147704392671585
|
|
}, {
|
|
"x": 0.5523084998130798,
|
|
"y": 0.8773422837257385,
|
|
"z": -0.009068487212061882
|
|
}, {
|
|
"x": 0.5510149598121643,
|
|
"y": 0.8816931843757629,
|
|
"z": -0.011043853126466274
|
|
}, {
|
|
"x": 0.5503793954849243,
|
|
"y": 0.88776695728302,
|
|
"z": -0.01348799467086792
|
|
}, {
|
|
"x": 0.5501549243927002,
|
|
"y": 0.8954370617866516,
|
|
"z": -0.012142189778387547
|
|
}, {
|
|
"x": 0.546072781085968,
|
|
"y": 0.9192524552345276,
|
|
"z": -0.003157563041895628
|
|
}, {
|
|
"x": 0.5314661860466003,
|
|
"y": 0.8771666884422302,
|
|
"z": 5075141089037061e-19
|
|
}, {
|
|
"x": 0.5293324589729309,
|
|
"y": 0.8762547969818115,
|
|
"z": 39177737198770046e-20
|
|
}, {
|
|
"x": 0.5275698900222778,
|
|
"y": 0.8750609755516052,
|
|
"z": 47732755774632096e-21
|
|
}, {
|
|
"x": 0.5104271173477173,
|
|
"y": 0.8607332110404968,
|
|
"z": 0.0012934643309563398
|
|
}, {
|
|
"x": 0.45938700437545776,
|
|
"y": 0.8134918212890625,
|
|
"z": 0.023569690063595772
|
|
}, {
|
|
"x": 0.5418947339057922,
|
|
"y": 0.6864100694656372,
|
|
"z": -0.027333909645676613
|
|
}, {
|
|
"x": 0.531914234161377,
|
|
"y": 0.6456130743026733,
|
|
"z": -0.005434140563011169
|
|
}, {
|
|
"x": 0.523697018623352,
|
|
"y": 0.647885262966156,
|
|
"z": -2466466394253075e-19
|
|
}, {
|
|
"x": 0.5338191390037537,
|
|
"y": 0.8783687353134155,
|
|
"z": 0.002268768846988678
|
|
}, {
|
|
"x": 0.46226605772972107,
|
|
"y": 0.8610277771949768,
|
|
"z": 0.04718952998518944
|
|
}, {
|
|
"x": 0.5434442758560181,
|
|
"y": 0.6456181406974792,
|
|
"z": -0.02327350154519081
|
|
}, {
|
|
"x": 0.5399754643440247,
|
|
"y": 0.940219521522522,
|
|
"z": 0.005075343884527683
|
|
}, {
|
|
"x": 0.5661457777023315,
|
|
"y": 0.71457839012146,
|
|
"z": -0.06242101639509201
|
|
}, {
|
|
"x": 0.5523148775100708,
|
|
"y": 0.6974870562553406,
|
|
"z": -0.04863070324063301
|
|
}, {
|
|
"x": 0.5639959573745728,
|
|
"y": 0.6923378109931946,
|
|
"z": -0.05180761218070984
|
|
}, {
|
|
"x": 0.5367592573165894,
|
|
"y": 0.7423217296600342,
|
|
"z": -0.03623027727007866
|
|
}, {
|
|
"x": 0.5853689908981323,
|
|
"y": 0.9752064943313599,
|
|
"z": -0.002361974213272333
|
|
}, {
|
|
"x": 0.5835235118865967,
|
|
"y": 0.9493685960769653,
|
|
"z": -0.003941743168979883
|
|
}, {
|
|
"x": 0.5615018606185913,
|
|
"y": 0.949194610118866,
|
|
"z": -0.0015953965485095978
|
|
}, {
|
|
"x": 0.5068561434745789,
|
|
"y": 0.9048219323158264,
|
|
"z": 0.01862684078514576
|
|
}, {
|
|
"x": 0.5134067535400391,
|
|
"y": 0.7971825003623962,
|
|
"z": -0.008485661819577217
|
|
}, {
|
|
"x": 0.5223897099494934,
|
|
"y": 0.925589919090271,
|
|
"z": 0.01249657291918993
|
|
}, {
|
|
"x": 0.48500555753707886,
|
|
"y": 0.7959478497505188,
|
|
"z": -0.0032065745908766985
|
|
}, {
|
|
"x": 0.5037734508514404,
|
|
"y": 0.8184596300125122,
|
|
"z": -0.004932103678584099
|
|
}, {
|
|
"x": 0.4766361117362976,
|
|
"y": 0.828806459903717,
|
|
"z": 0.01027688942849636
|
|
}, {
|
|
"x": 0.5589827299118042,
|
|
"y": 0.974656343460083,
|
|
"z": 9666886180639267e-19
|
|
}, {
|
|
"x": 0.5294582843780518,
|
|
"y": 0.7541216611862183,
|
|
"z": -0.025603046640753746
|
|
}, {
|
|
"x": 0.4973002076148987,
|
|
"y": 0.9208990931510925,
|
|
"z": 0.031931452453136444
|
|
}, {
|
|
"x": 0.5163551568984985,
|
|
"y": 0.9432790875434875,
|
|
"z": 0.024321340024471283
|
|
}, {
|
|
"x": 0.49399662017822266,
|
|
"y": 0.8814862370491028,
|
|
"z": 0.018687399104237556
|
|
}, {
|
|
"x": 0.44948166608810425,
|
|
"y": 0.836137592792511,
|
|
"z": 0.05702034756541252
|
|
}, {
|
|
"x": 0.47898444533348083,
|
|
"y": 0.8836610913276672,
|
|
"z": 0.03150695189833641
|
|
}, {
|
|
"x": 0.4454479217529297,
|
|
"y": 0.8499438166618347,
|
|
"z": 0.08868525922298431
|
|
}, {
|
|
"x": 0.49572959542274475,
|
|
"y": 0.8452823758125305,
|
|
"z": 0.0036111653316766024
|
|
}, {
|
|
"x": 0.5362502336502075,
|
|
"y": 0.7222585678100586,
|
|
"z": -0.027912352234125137
|
|
}, {
|
|
"x": 0.5393770337104797,
|
|
"y": 0.7850722074508667,
|
|
"z": -0.05415399745106697
|
|
}, {
|
|
"x": 0.531399667263031,
|
|
"y": 0.7898418307304382,
|
|
"z": -0.03883346915245056
|
|
}, {
|
|
"x": 0.5451627373695374,
|
|
"y": 0.7717036604881287,
|
|
"z": -0.06480253487825394
|
|
}, {
|
|
"x": 0.5206395983695984,
|
|
"y": 0.6287745833396912,
|
|
"z": -0.010521138086915016
|
|
}, {
|
|
"x": 0.4974782466888428,
|
|
"y": 0.6191938519477844,
|
|
"z": -0.014098240062594414
|
|
}, {
|
|
"x": 0.4774145185947418,
|
|
"y": 0.6193130612373352,
|
|
"z": -0.013643337413668633
|
|
}, {
|
|
"x": 0.4616098403930664,
|
|
"y": 0.6259890198707581,
|
|
"z": -0.008448202162981033
|
|
}, {
|
|
"x": 0.4516478478908539,
|
|
"y": 0.6368461847305298,
|
|
"z": 9050309745362028e-20
|
|
}, {
|
|
"x": 0.4485096037387848,
|
|
"y": 0.6719120740890503,
|
|
"z": 0.022984720766544342
|
|
}, {
|
|
"x": 0.42177659273147583,
|
|
"y": 0.7240667343139648,
|
|
"z": 0.08511673659086227
|
|
}, {
|
|
"x": 0.4616215229034424,
|
|
"y": 0.6988231539726257,
|
|
"z": 0.014238474890589714
|
|
}, {
|
|
"x": 0.4755798876285553,
|
|
"y": 0.7034608721733093,
|
|
"z": 0.00625590980052948
|
|
}, {
|
|
"x": 0.4924992024898529,
|
|
"y": 0.7005885243415833,
|
|
"z": 9391739731654525e-19
|
|
}, {
|
|
"x": 0.5082254409790039,
|
|
"y": 0.693384051322937,
|
|
"z": -9464038303121924e-19
|
|
}, {
|
|
"x": 0.5203112959861755,
|
|
"y": 0.6849707961082458,
|
|
"z": -0.0022114769089967012
|
|
}, {
|
|
"x": 0.52867591381073,
|
|
"y": 0.6779075860977173,
|
|
"z": -0.002962538506835699
|
|
}, {
|
|
"x": 0.4213953912258148,
|
|
"y": 0.7219811677932739,
|
|
"z": 0.1350894570350647
|
|
}, {
|
|
"x": 0.5320829749107361,
|
|
"y": 0.794858992099762,
|
|
"z": -0.03181503340601921
|
|
}, {
|
|
"x": 0.5452795028686523,
|
|
"y": 0.7286570072174072,
|
|
"z": -0.04771539941430092
|
|
}, {
|
|
"x": 0.5496407747268677,
|
|
"y": 0.7866933345794678,
|
|
"z": -0.06452003121376038
|
|
}, {
|
|
"x": 0.557040274143219,
|
|
"y": 0.7962084412574768,
|
|
"z": -0.05837344378232956
|
|
}, {
|
|
"x": 0.549176812171936,
|
|
"y": 0.7895247936248779,
|
|
"z": -0.057761140167713165
|
|
}, {
|
|
"x": 0.5362890362739563,
|
|
"y": 0.8005836606025696,
|
|
"z": -0.026903774589300156
|
|
}, {
|
|
"x": 0.560200035572052,
|
|
"y": 0.7983731031417847,
|
|
"z": -0.06172555685043335
|
|
}, {
|
|
"x": 0.5616944432258606,
|
|
"y": 0.8022753596305847,
|
|
"z": -0.045200999826192856
|
|
}, {
|
|
"x": 0.5273328423500061,
|
|
"y": 0.6611284017562866,
|
|
"z": 0.0029021520167589188
|
|
}, {
|
|
"x": 0.534850537776947,
|
|
"y": 0.6660012006759644,
|
|
"z": -0.005215510260313749
|
|
}, {
|
|
"x": 0.5394860506057739,
|
|
"y": 0.6701375246047974,
|
|
"z": -0.014931917190551758
|
|
}, {
|
|
"x": 0.4634307324886322,
|
|
"y": 0.658291757106781,
|
|
"z": 0.009295716881752014
|
|
}, {
|
|
"x": 0.4538393020629883,
|
|
"y": 0.6519932150840759,
|
|
"z": 0.00930330716073513
|
|
}, {
|
|
"x": 0.5776031613349915,
|
|
"y": 0.7159298658370972,
|
|
"z": -0.057365912944078445
|
|
}, {
|
|
"x": 0.6504855155944824,
|
|
"y": 0.6461779475212097,
|
|
"z": 0.014184834435582161
|
|
}, {
|
|
"x": 0.5860154032707214,
|
|
"y": 0.7962266206741333,
|
|
"z": -0.04522843658924103
|
|
}, {
|
|
"x": 0.6842049360275269,
|
|
"y": 0.5631637573242188,
|
|
"z": 0.07207967340946198
|
|
}, {
|
|
"x": 0.6152560710906982,
|
|
"y": 0.6674962639808655,
|
|
"z": 7529259892180562e-19
|
|
}, {
|
|
"x": 0.6280948519706726,
|
|
"y": 0.6684326529502869,
|
|
"z": 0.0016892586136236787
|
|
}, {
|
|
"x": 0.6408625245094299,
|
|
"y": 0.6663892269134521,
|
|
"z": 0.005331226624548435
|
|
}, {
|
|
"x": 0.6557814478874207,
|
|
"y": 0.6534678936004639,
|
|
"z": 0.01646413467824459
|
|
}, {
|
|
"x": 0.6035663485527039,
|
|
"y": 0.6639701724052429,
|
|
"z": 0.0013799630105495453
|
|
}, {
|
|
"x": 0.6329053044319153,
|
|
"y": 0.608010470867157,
|
|
"z": -0.006195899099111557
|
|
}, {
|
|
"x": 0.6167260408401489,
|
|
"y": 0.6117533445358276,
|
|
"z": -0.006319951266050339
|
|
}, {
|
|
"x": 0.6471013426780701,
|
|
"y": 0.6112449765205383,
|
|
"z": -0.0017843559617176652
|
|
}, {
|
|
"x": 0.6560901999473572,
|
|
"y": 0.6185776591300964,
|
|
"z": 0.004047257360070944
|
|
}, {
|
|
"x": 0.6666946411132812,
|
|
"y": 0.6651176810264587,
|
|
"z": 0.023647578433156013
|
|
}, {
|
|
"x": 0.6311345100402832,
|
|
"y": 0.9495396018028259,
|
|
"z": 0.014004078693687916
|
|
}, {
|
|
"x": 0.6544655561447144,
|
|
"y": 0.6397901773452759,
|
|
"z": 0.01809609681367874
|
|
}, {
|
|
"x": 0.6965808868408203,
|
|
"y": 0.6482675075531006,
|
|
"z": 0.08304904401302338
|
|
}, {
|
|
"x": 0.679817259311676,
|
|
"y": 0.650188148021698,
|
|
"z": 0.03632688894867897
|
|
}, {
|
|
"x": 0.6336516737937927,
|
|
"y": 0.7541458010673523,
|
|
"z": -0.007742783520370722
|
|
}, {
|
|
"x": 0.5921701192855835,
|
|
"y": 0.8567668199539185,
|
|
"z": -0.029399123042821884
|
|
}, {
|
|
"x": 0.591663658618927,
|
|
"y": 0.870215654373169,
|
|
"z": -0.02103729173541069
|
|
}, {
|
|
"x": 0.6068367958068848,
|
|
"y": 0.8584195375442505,
|
|
"z": -0.020668085664510727
|
|
}, {
|
|
"x": 0.6176617741584778,
|
|
"y": 0.860965371131897,
|
|
"z": -0.009790095500648022
|
|
}, {
|
|
"x": 0.6040634512901306,
|
|
"y": 0.8686612844467163,
|
|
"z": -0.015289564616978168
|
|
}, {
|
|
"x": 0.6143736839294434,
|
|
"y": 0.8671170473098755,
|
|
"z": -0.005712216719985008
|
|
}, {
|
|
"x": 0.6373105049133301,
|
|
"y": 0.8815656900405884,
|
|
"z": 0.012672550976276398
|
|
}, {
|
|
"x": 0.5832505822181702,
|
|
"y": 0.7866312861442566,
|
|
"z": -0.07051534950733185
|
|
}, {
|
|
"x": 0.5836675763130188,
|
|
"y": 0.7658692598342896,
|
|
"z": -0.07566110789775848
|
|
}, {
|
|
"x": 0.6709531545639038,
|
|
"y": 0.604898989200592,
|
|
"z": 0.005951565690338612
|
|
}, {
|
|
"x": 0.6029891967773438,
|
|
"y": 0.705652117729187,
|
|
"z": -0.013388276100158691
|
|
}, {
|
|
"x": 0.6131622195243835,
|
|
"y": 0.7728396058082581,
|
|
"z": -0.036248479038476944
|
|
}, {
|
|
"x": 0.6123163104057312,
|
|
"y": 0.7612020373344421,
|
|
"z": -0.03264721855521202
|
|
}, {
|
|
"x": 0.6696187853813171,
|
|
"y": 0.744706928730011,
|
|
"z": 0.009673702530562878
|
|
}, {
|
|
"x": 0.5803102254867554,
|
|
"y": 0.7385968565940857,
|
|
"z": -0.0689152330160141
|
|
}, {
|
|
"x": 0.6404349207878113,
|
|
"y": 0.5877999663352966,
|
|
"z": -0.01929756999015808
|
|
}, {
|
|
"x": 0.6588467955589294,
|
|
"y": 0.5929454565048218,
|
|
"z": -0.008487257175147533
|
|
}, {
|
|
"x": 0.6720337867736816,
|
|
"y": 0.530631422996521,
|
|
"z": 0.043437421321868896
|
|
}, {
|
|
"x": 0.584305465221405,
|
|
"y": 0.6099005341529846,
|
|
"z": -0.030301367864012718
|
|
}, {
|
|
"x": 0.6034283638000488,
|
|
"y": 0.6217452883720398,
|
|
"z": -0.001970183802768588
|
|
}, {
|
|
"x": 0.6460927724838257,
|
|
"y": 0.8608663082122803,
|
|
"z": 0.015541625209152699
|
|
}, {
|
|
"x": 0.6957815289497375,
|
|
"y": 0.8326103091239929,
|
|
"z": 0.13015234470367432
|
|
}, {
|
|
"x": 0.6043362617492676,
|
|
"y": 0.7861682772636414,
|
|
"z": -0.030476901680231094
|
|
}, {
|
|
"x": 0.594293475151062,
|
|
"y": 0.7942103147506714,
|
|
"z": -0.032218821346759796
|
|
}, {
|
|
"x": 0.6324057579040527,
|
|
"y": 0.8665139675140381,
|
|
"z": 0.014255806803703308
|
|
}, {
|
|
"x": 0.6296147704124451,
|
|
"y": 0.8667733669281006,
|
|
"z": 0.010388285852968693
|
|
}, {
|
|
"x": 0.663644552230835,
|
|
"y": 0.5798642635345459,
|
|
"z": -0.0022301070857793093
|
|
}, {
|
|
"x": 0.6140630841255188,
|
|
"y": 0.7809288501739502,
|
|
"z": -0.02835679054260254
|
|
}, {
|
|
"x": 0.615908145904541,
|
|
"y": 0.5921698212623596,
|
|
"z": -0.026804860681295395
|
|
}, {
|
|
"x": 0.617181122303009,
|
|
"y": 0.5748661756515503,
|
|
"z": -0.03060605563223362
|
|
}, {
|
|
"x": 0.6222207546234131,
|
|
"y": 0.49137672781944275,
|
|
"z": -0.011151673272252083
|
|
}, {
|
|
"x": 0.6669357419013977,
|
|
"y": 0.5541607141494751,
|
|
"z": 0.017466170713305473
|
|
}, {
|
|
"x": 0.6182981729507446,
|
|
"y": 0.5320425629615784,
|
|
"z": -0.021793590858578682
|
|
}, {
|
|
"x": 0.6760554313659668,
|
|
"y": 0.595052182674408,
|
|
"z": 0.017115700989961624
|
|
}, {
|
|
"x": 0.6801463961601257,
|
|
"y": 0.5800720453262329,
|
|
"z": 0.043127160519361496
|
|
}, {
|
|
"x": 0.5922210812568665,
|
|
"y": 0.8644017577171326,
|
|
"z": -0.02662893570959568
|
|
}, {
|
|
"x": 0.6054555177688599,
|
|
"y": 0.8637874722480774,
|
|
"z": -0.018363753333687782
|
|
}, {
|
|
"x": 0.6161889433860779,
|
|
"y": 0.8641164898872375,
|
|
"z": -0.008808949030935764
|
|
}, {
|
|
"x": 0.6017249822616577,
|
|
"y": 0.7901403307914734,
|
|
"z": -0.028126630932092667
|
|
}, {
|
|
"x": 0.631446123123169,
|
|
"y": 0.8664817810058594,
|
|
"z": 0.012112865224480629
|
|
}, {
|
|
"x": 0.6249198913574219,
|
|
"y": 0.8716511130332947,
|
|
"z": 0.003882825840264559
|
|
}, {
|
|
"x": 0.6281915903091431,
|
|
"y": 0.867301881313324,
|
|
"z": 0.009891441091895103
|
|
}, {
|
|
"x": 0.5986843109130859,
|
|
"y": 0.7813931703567505,
|
|
"z": -0.050227612257003784
|
|
}, {
|
|
"x": 0.6126407384872437,
|
|
"y": 0.869275689125061,
|
|
"z": -0.0031255714129656553
|
|
}, {
|
|
"x": 0.6027271151542664,
|
|
"y": 0.8711842894554138,
|
|
"z": -0.009324162267148495
|
|
}, {
|
|
"x": 0.59088134765625,
|
|
"y": 0.8742044568061829,
|
|
"z": -0.014608660712838173
|
|
}, {
|
|
"x": 0.5984604358673096,
|
|
"y": 0.9216185212135315,
|
|
"z": -0.005981989670544863
|
|
}, {
|
|
"x": 0.5950398445129395,
|
|
"y": 0.8964707255363464,
|
|
"z": -0.01703473925590515
|
|
}, {
|
|
"x": 0.5941568613052368,
|
|
"y": 0.8882410526275635,
|
|
"z": -0.017784785479307175
|
|
}, {
|
|
"x": 0.5928806662559509,
|
|
"y": 0.8803883194923401,
|
|
"z": -0.014153128489851952
|
|
}, {
|
|
"x": 0.5909661054611206,
|
|
"y": 0.8748103976249695,
|
|
"z": -0.012609979137778282
|
|
}, {
|
|
"x": 0.6128016710281372,
|
|
"y": 0.8702545762062073,
|
|
"z": -0.0022550546564161777
|
|
}, {
|
|
"x": 0.6150846481323242,
|
|
"y": 0.8726804256439209,
|
|
"z": -0.00414019962772727
|
|
}, {
|
|
"x": 0.6173093914985657,
|
|
"y": 0.8770190477371216,
|
|
"z": -0.005970994010567665
|
|
}, {
|
|
"x": 0.619335412979126,
|
|
"y": 0.8814800977706909,
|
|
"z": -0.0036864024586975574
|
|
}, {
|
|
"x": 0.6292637586593628,
|
|
"y": 0.8314558267593384,
|
|
"z": -0.007714875973761082
|
|
}, {
|
|
"x": 0.702275276184082,
|
|
"y": 0.7320667505264282,
|
|
"z": 0.1433621346950531
|
|
}, {
|
|
"x": 0.6204835176467896,
|
|
"y": 0.8689177632331848,
|
|
"z": 0.0044869170524179935
|
|
}, {
|
|
"x": 0.6223508715629578,
|
|
"y": 0.8704851269721985,
|
|
"z": 0.00352082890458405
|
|
}, {
|
|
"x": 0.590448260307312,
|
|
"y": 0.8029727935791016,
|
|
"z": -0.03200828656554222
|
|
}, {
|
|
"x": 0.6097423434257507,
|
|
"y": 0.7933741211891174,
|
|
"z": -0.018042555078864098
|
|
}, {
|
|
"x": 0.59229576587677,
|
|
"y": 0.7993767261505127,
|
|
"z": -0.032564569264650345
|
|
}, {
|
|
"x": 0.6171364188194275,
|
|
"y": 0.7153720259666443,
|
|
"z": -0.007672437466681004
|
|
}, {
|
|
"x": 0.6389747858047485,
|
|
"y": 0.726390540599823,
|
|
"z": -0.002999067772179842
|
|
}, {
|
|
"x": 0.6151940226554871,
|
|
"y": 0.769412100315094,
|
|
"z": -0.024427521973848343
|
|
}, {
|
|
"x": 0.6526776552200317,
|
|
"y": 0.505868136882782,
|
|
"z": 0.01412637997418642
|
|
}, {
|
|
"x": 0.6475822329521179,
|
|
"y": 0.5375454425811768,
|
|
"z": -0.0033899128902703524
|
|
}, {
|
|
"x": 0.6433356404304504,
|
|
"y": 0.5714520215988159,
|
|
"z": -0.017428796738386154
|
|
}, {
|
|
"x": 0.626949667930603,
|
|
"y": 0.8962116837501526,
|
|
"z": 0.005602736957371235
|
|
}, {
|
|
"x": 0.5868416428565979,
|
|
"y": 0.5829002261161804,
|
|
"z": -0.03727729618549347
|
|
}, {
|
|
"x": 0.5877229571342468,
|
|
"y": 0.5345035791397095,
|
|
"z": -0.032396964728832245
|
|
}, {
|
|
"x": 0.5887066125869751,
|
|
"y": 0.48655083775520325,
|
|
"z": -0.025856535881757736
|
|
}, {
|
|
"x": 0.6507197618484497,
|
|
"y": 0.6612282991409302,
|
|
"z": 0.011114613153040409
|
|
}, {
|
|
"x": 0.6803066730499268,
|
|
"y": 0.677992045879364,
|
|
"z": 0.032125361263751984
|
|
}, {
|
|
"x": 0.5963194370269775,
|
|
"y": 0.6598632335662842,
|
|
"z": 0.002976928371936083
|
|
}, {
|
|
"x": 0.667536199092865,
|
|
"y": 0.6274255514144897,
|
|
"z": 0.015618261881172657
|
|
}, {
|
|
"x": 0.5930740833282471,
|
|
"y": 0.6940041780471802,
|
|
"z": -0.019217798486351967
|
|
}, {
|
|
"x": 0.6053346395492554,
|
|
"y": 0.7676517963409424,
|
|
"z": -0.050308309495449066
|
|
}, {
|
|
"x": 0.6934473514556885,
|
|
"y": 0.6884298920631409,
|
|
"z": 0.04794462397694588
|
|
}, {
|
|
"x": 0.6738007664680481,
|
|
"y": 0.6934011578559875,
|
|
"z": 0.020697161555290222
|
|
}, {
|
|
"x": 0.6588084697723389,
|
|
"y": 0.7033141851425171,
|
|
"z": 0.008462334051728249
|
|
}, {
|
|
"x": 0.6346072554588318,
|
|
"y": 0.7029502391815186,
|
|
"z": 0.001542167621664703
|
|
}, {
|
|
"x": 0.6157816648483276,
|
|
"y": 0.6966525912284851,
|
|
"z": -0.002009218093007803
|
|
}, {
|
|
"x": 0.6015574336051941,
|
|
"y": 0.688928484916687,
|
|
"z": -0.006588225718587637
|
|
}, {
|
|
"x": 0.5746836066246033,
|
|
"y": 0.6711069345474243,
|
|
"z": -0.03597589209675789
|
|
}, {
|
|
"x": 0.6947521567344666,
|
|
"y": 0.7309479117393494,
|
|
"z": 0.046707939356565475
|
|
}, {
|
|
"x": 0.6759101152420044,
|
|
"y": 0.6249120831489563,
|
|
"z": 0.021654341369867325
|
|
}, {
|
|
"x": 0.5794773101806641,
|
|
"y": 0.7971615195274353,
|
|
"z": -0.06339326500892639
|
|
}, {
|
|
"x": 0.6041849851608276,
|
|
"y": 0.727514922618866,
|
|
"z": -0.017512541264295578
|
|
}, {
|
|
"x": 0.6968844532966614,
|
|
"y": 0.6440950036048889,
|
|
"z": 0.12727996706962585
|
|
}, {
|
|
"x": 0.5910853147506714,
|
|
"y": 0.679325520992279,
|
|
"z": -0.009497715160250664
|
|
}, {
|
|
"x": 0.6157375574111938,
|
|
"y": 0.7695677280426025,
|
|
"z": -0.010624290443956852
|
|
}, {
|
|
"x": 0.6606494784355164,
|
|
"y": 0.6410489678382874,
|
|
"z": 0.0208158977329731
|
|
}, {
|
|
"x": 0.6040687561035156,
|
|
"y": 0.7531470656394958,
|
|
"z": -0.045887019485235214
|
|
}, {
|
|
"x": 0.7012156248092651,
|
|
"y": 0.780247151851654,
|
|
"z": 0.14028730988502502
|
|
}, {
|
|
"x": 0.595149576663971,
|
|
"y": 0.6527782678604126,
|
|
"z": 0.006308757700026035
|
|
}, {
|
|
"x": 0.5925500392913818,
|
|
"y": 0.7436665892601013,
|
|
"z": -0.060151755809783936
|
|
}, {
|
|
"x": 0.6780198812484741,
|
|
"y": 0.8905693888664246,
|
|
"z": 0.0626060739159584
|
|
}, {
|
|
"x": 0.676746666431427,
|
|
"y": 0.9113880395889282,
|
|
"z": 0.08726003766059875
|
|
}, {
|
|
"x": 0.7030686140060425,
|
|
"y": 0.7312687635421753,
|
|
"z": 0.09529774636030197
|
|
}, {
|
|
"x": 0.688987135887146,
|
|
"y": 0.8588417172431946,
|
|
"z": 0.07752864807844162
|
|
}, {
|
|
"x": 0.6883691549301147,
|
|
"y": 0.6109960675239563,
|
|
"z": 0.06669612973928452
|
|
}, {
|
|
"x": 0.6358906030654907,
|
|
"y": 0.9702065587043762,
|
|
"z": 0.023120900616049767
|
|
}, {
|
|
"x": 0.5781539678573608,
|
|
"y": 0.8023634552955627,
|
|
"z": -0.044763918966054916
|
|
}, {
|
|
"x": 0.6170316934585571,
|
|
"y": 0.7408350706100464,
|
|
"z": -0.011375460773706436
|
|
}, {
|
|
"x": 0.688542366027832,
|
|
"y": 0.6516284346580505,
|
|
"z": 0.050206027925014496
|
|
}, {
|
|
"x": 0.6385149359703064,
|
|
"y": 0.6540714502334595,
|
|
"z": 0.006462941411882639
|
|
}, {
|
|
"x": 0.6279382109642029,
|
|
"y": 0.6563615798950195,
|
|
"z": 0.003062846139073372
|
|
}, {
|
|
"x": 0.6268895268440247,
|
|
"y": 0.8736732006072998,
|
|
"z": 0.00627936702221632
|
|
}, {
|
|
"x": 0.6944946050643921,
|
|
"y": 0.7709181308746338,
|
|
"z": 0.053824134171009064
|
|
}, {
|
|
"x": 0.614617109298706,
|
|
"y": 1.0022112131118774,
|
|
"z": 0.02719894051551819
|
|
}, {
|
|
"x": 0.6493719220161438,
|
|
"y": 0.9665167927742004,
|
|
"z": 0.053563784807920456
|
|
}, {
|
|
"x": 0.6624587178230286,
|
|
"y": 0.943530797958374,
|
|
"z": 0.068605437874794
|
|
}, {
|
|
"x": 0.6162528991699219,
|
|
"y": 0.6558693051338196,
|
|
"z": 0.002187855076044798
|
|
}, {
|
|
"x": 0.6058168411254883,
|
|
"y": 0.654328465461731,
|
|
"z": 0.0036193584091961384
|
|
}, {
|
|
"x": 0.5987918972969055,
|
|
"y": 0.6536934971809387,
|
|
"z": 0.006134530063718557
|
|
}, {
|
|
"x": 0.6831037402153015,
|
|
"y": 0.6195642948150635,
|
|
"z": 0.03511790186166763
|
|
}, {
|
|
"x": 0.6062582731246948,
|
|
"y": 0.6356398463249207,
|
|
"z": 0.001280312892049551
|
|
}, {
|
|
"x": 0.6174948811531067,
|
|
"y": 0.62776118516922,
|
|
"z": -0.0013642468256875873
|
|
}, {
|
|
"x": 0.6297246217727661,
|
|
"y": 0.6253792643547058,
|
|
"z": -7034156005829573e-19
|
|
}, {
|
|
"x": 0.6407091617584229,
|
|
"y": 0.627578616142273,
|
|
"z": 0.0028144705574959517
|
|
}, {
|
|
"x": 0.6479622721672058,
|
|
"y": 0.6322650909423828,
|
|
"z": 0.00750273372977972
|
|
}, {
|
|
"x": 0.6915091276168823,
|
|
"y": 0.5990704298019409,
|
|
"z": 0.10270945727825165
|
|
}, {
|
|
"x": 0.6457163095474243,
|
|
"y": 0.6504453420639038,
|
|
"z": 0.010696077719330788
|
|
}, {
|
|
"x": 0.6164222955703735,
|
|
"y": 0.8231936097145081,
|
|
"z": -0.016772059723734856
|
|
}, {
|
|
"x": 0.6042401194572449,
|
|
"y": 0.7830976843833923,
|
|
"z": -0.03630910441279411
|
|
}, {
|
|
"x": 0.5922216773033142,
|
|
"y": 0.8228387236595154,
|
|
"z": -0.029992375522851944
|
|
}, {
|
|
"x": 0.6646111011505127,
|
|
"y": 0.92097008228302,
|
|
"z": 0.050967294722795486
|
|
}, {
|
|
"x": 0.651232898235321,
|
|
"y": 0.9460107088088989,
|
|
"z": 0.038000158965587616
|
|
}, {
|
|
"x": 0.6140977144241333,
|
|
"y": 0.9882472157478333,
|
|
"z": 0.009882091544568539
|
|
}, {
|
|
"x": 0.6870781183242798,
|
|
"y": 0.8768675327301025,
|
|
"z": 0.10980932414531708
|
|
}, {
|
|
"x": 0.5986856818199158,
|
|
"y": 0.6456438899040222,
|
|
"z": 0.003999010659754276
|
|
}, {
|
|
"x": 0.585981547832489,
|
|
"y": 0.7034481763839722,
|
|
"z": -0.0377722829580307
|
|
}, {
|
|
"x": 0.6342031359672546,
|
|
"y": 0.9867448806762695,
|
|
"z": 0.03786521404981613
|
|
}, {
|
|
"x": 0.7013950943946838,
|
|
"y": 0.776049017906189,
|
|
"z": 0.09598205983638763
|
|
}, {
|
|
"x": 0.6030206680297852,
|
|
"y": 0.8719133138656616,
|
|
"z": -0.007931148633360863
|
|
}, {
|
|
"x": 0.6050592064857483,
|
|
"y": 0.8767156004905701,
|
|
"z": -0.009791925549507141
|
|
}, {
|
|
"x": 0.6073468923568726,
|
|
"y": 0.8831382393836975,
|
|
"z": -0.012361008673906326
|
|
}, {
|
|
"x": 0.6087977290153503,
|
|
"y": 0.890143632888794,
|
|
"z": -0.01098148338496685
|
|
}, {
|
|
"x": 0.6147705316543579,
|
|
"y": 0.9110084772109985,
|
|
"z": -0.0018823575228452682
|
|
}, {
|
|
"x": 0.622577965259552,
|
|
"y": 0.8670604825019836,
|
|
"z": 0.002609190298244357
|
|
}, {
|
|
"x": 0.6241236329078674,
|
|
"y": 0.8651344180107117,
|
|
"z": 0.0025534380692988634
|
|
}, {
|
|
"x": 0.6257084608078003,
|
|
"y": 0.8638408184051514,
|
|
"z": 0.0023300074972212315
|
|
}, {
|
|
"x": 0.639931321144104,
|
|
"y": 0.8449671268463135,
|
|
"z": 0.0038123116828501225
|
|
}, {
|
|
"x": 0.6810906529426575,
|
|
"y": 0.7856625318527222,
|
|
"z": 0.02717764675617218
|
|
}, {
|
|
"x": 0.583532452583313,
|
|
"y": 0.6811994910240173,
|
|
"z": -0.026588857173919678
|
|
}, {
|
|
"x": 0.5855660438537598,
|
|
"y": 0.6393819451332092,
|
|
"z": -0.004512844607234001
|
|
}, {
|
|
"x": 0.5932201743125916,
|
|
"y": 0.6398029327392578,
|
|
"z": 8020466193556786e-19
|
|
}, {
|
|
"x": 0.6200879812240601,
|
|
"y": 0.8683351874351501,
|
|
"z": 0.00417016725987196
|
|
}, {
|
|
"x": 0.6842559576034546,
|
|
"y": 0.8330534100532532,
|
|
"z": 0.050836317241191864
|
|
}, {
|
|
"x": 0.5754412412643433,
|
|
"y": 0.6418221592903137,
|
|
"z": -0.022838059812784195
|
|
}, {
|
|
"x": 0.6232790350914001,
|
|
"y": 0.9295297265052795,
|
|
"z": 0.006339520215988159
|
|
}, {
|
|
"x": 0.5764067769050598,
|
|
"y": 0.694546639919281,
|
|
"z": -0.04825803264975548
|
|
}, {
|
|
"x": 0.59778892993927,
|
|
"y": 0.7343927621841431,
|
|
"z": -0.035004377365112305
|
|
}, {
|
|
"x": 0.6042810678482056,
|
|
"y": 0.9441440105438232,
|
|
"z": -0.0010970570147037506
|
|
}, {
|
|
"x": 0.6496372222900391,
|
|
"y": 0.8869078159332275,
|
|
"z": 0.021036235615611076
|
|
}, {
|
|
"x": 0.6274012327194214,
|
|
"y": 0.7830310463905334,
|
|
"z": -0.006658440921455622
|
|
}, {
|
|
"x": 0.637792706489563,
|
|
"y": 0.9104999899864197,
|
|
"z": 0.014290250837802887
|
|
}, {
|
|
"x": 0.6549934148788452,
|
|
"y": 0.7748609185218811,
|
|
"z": -6672973395325243e-19
|
|
}, {
|
|
"x": 0.6404005289077759,
|
|
"y": 0.801220715045929,
|
|
"z": -0.0026642554439604282
|
|
}, {
|
|
"x": 0.6671456694602966,
|
|
"y": 0.8045546412467957,
|
|
"z": 0.013180811889469624
|
|
}, {
|
|
"x": 0.6107483506202698,
|
|
"y": 0.9680658578872681,
|
|
"z": 0.001778992242179811
|
|
}, {
|
|
"x": 0.6060343980789185,
|
|
"y": 0.744587242603302,
|
|
"z": -0.024382334202528
|
|
}, {
|
|
"x": 0.6602751612663269,
|
|
"y": 0.8998945355415344,
|
|
"z": 0.0344940721988678
|
|
}, {
|
|
"x": 0.6463775038719177,
|
|
"y": 0.9262562394142151,
|
|
"z": 0.02617623284459114
|
|
}, {
|
|
"x": 0.6579852104187012,
|
|
"y": 0.8602304458618164,
|
|
"z": 0.021586716175079346
|
|
}, {
|
|
"x": 0.6926165223121643,
|
|
"y": 0.8053340315818787,
|
|
"z": 0.061075080186128616
|
|
}, {
|
|
"x": 0.6724731922149658,
|
|
"y": 0.8594399690628052,
|
|
"z": 0.03457934781908989
|
|
}, {
|
|
"x": 0.6975721716880798,
|
|
"y": 0.8183245062828064,
|
|
"z": 0.09300774335861206
|
|
}, {
|
|
"x": 0.6512877941131592,
|
|
"y": 0.8258221745491028,
|
|
"z": 0.006324059329926968
|
|
}, {
|
|
"x": 0.594887375831604,
|
|
"y": 0.7148372530937195,
|
|
"z": -0.026898479089140892
|
|
}, {
|
|
"x": 0.6017440557479858,
|
|
"y": 0.7773507833480835,
|
|
"z": -0.05312420800328255
|
|
}, {
|
|
"x": 0.6096571683883667,
|
|
"y": 0.7806998491287231,
|
|
"z": -0.037646256387233734
|
|
}, {
|
|
"x": 0.5952993035316467,
|
|
"y": 0.7654367685317993,
|
|
"z": -0.06398405134677887
|
|
}, {
|
|
"x": 0.5950021147727966,
|
|
"y": 0.6201304793357849,
|
|
"z": -0.009297547861933708
|
|
}, {
|
|
"x": 0.6165438890457153,
|
|
"y": 0.6052900552749634,
|
|
"z": -0.012455573305487633
|
|
}, {
|
|
"x": 0.6362661719322205,
|
|
"y": 0.6015968918800354,
|
|
"z": -0.011649220250546932
|
|
}, {
|
|
"x": 0.6522727608680725,
|
|
"y": 0.6046400666236877,
|
|
"z": -0.005903332494199276
|
|
}, {
|
|
"x": 0.6625409722328186,
|
|
"y": 0.6128141283988953,
|
|
"z": 0.0030042496509850025
|
|
}, {
|
|
"x": 0.6688099503517151,
|
|
"y": 0.6457712054252625,
|
|
"z": 0.026322703808546066
|
|
}, {
|
|
"x": 0.7013440728187561,
|
|
"y": 0.6893666386604309,
|
|
"z": 0.08984331786632538
|
|
}, {
|
|
"x": 0.6608623266220093,
|
|
"y": 0.6749406456947327,
|
|
"z": 0.0172116681933403
|
|
}, {
|
|
"x": 0.6482325196266174,
|
|
"y": 0.6823726296424866,
|
|
"z": 0.008881398476660252
|
|
}, {
|
|
"x": 0.6313265562057495,
|
|
"y": 0.6842025518417358,
|
|
"z": 0.0031308617908507586
|
|
}, {
|
|
"x": 0.6147016286849976,
|
|
"y": 0.6809731721878052,
|
|
"z": 7630771724507213e-19
|
|
}, {
|
|
"x": 0.6018834114074707,
|
|
"y": 0.6755372285842896,
|
|
"z": -8834321051836014e-19
|
|
}, {
|
|
"x": 0.5925027132034302,
|
|
"y": 0.670681357383728,
|
|
"z": -0.001968748401850462
|
|
}, {
|
|
"x": 0.700127363204956,
|
|
"y": 0.6871103644371033,
|
|
"z": 0.13980500400066376
|
|
}, {
|
|
"x": 0.6095665693283081,
|
|
"y": 0.7853189706802368,
|
|
"z": -0.03074747882783413
|
|
}, {
|
|
"x": 0.5880423784255981,
|
|
"y": 0.7229287028312683,
|
|
"z": -0.04691500961780548
|
|
}, {
|
|
"x": 0.5930182337760925,
|
|
"y": 0.7811514139175415,
|
|
"z": -0.06398335844278336
|
|
}, {
|
|
"x": 0.5867722034454346,
|
|
"y": 0.7922660112380981,
|
|
"z": -0.05794971063733101
|
|
}, {
|
|
"x": 0.5933279991149902,
|
|
"y": 0.7842848896980286,
|
|
"z": -0.05714067071676254
|
|
}, {
|
|
"x": 0.6063535809516907,
|
|
"y": 0.7920218706130981,
|
|
"z": -0.02590685710310936
|
|
}, {
|
|
"x": 0.5839452743530273,
|
|
"y": 0.794978141784668,
|
|
"z": -0.0615212507545948
|
|
}, {
|
|
"x": 0.5828126072883606,
|
|
"y": 0.8000800013542175,
|
|
"z": -0.0449722595512867
|
|
}, {
|
|
"x": 0.5909603834152222,
|
|
"y": 0.6541213393211365,
|
|
"z": 0.003991890233010054
|
|
}, {
|
|
"x": 0.5852181911468506,
|
|
"y": 0.6602938771247864,
|
|
"z": -0.004428438376635313
|
|
}, {
|
|
"x": 0.5825737714767456,
|
|
"y": 0.6651063561439514,
|
|
"z": -0.014345290139317513
|
|
}, {
|
|
"x": 0.6517343521118164,
|
|
"y": 0.6362385153770447,
|
|
"z": 0.012151890434324741
|
|
}, {
|
|
"x": 0.6615052819252014,
|
|
"y": 0.6281577944755554,
|
|
"z": 0.0123682152479887
|
|
}, {
|
|
"x": 0.4856873154640198,
|
|
"y": 0.6568945646286011,
|
|
"z": 720038078725338e-18
|
|
}, {
|
|
"x": 0.49988406896591187,
|
|
"y": 0.6547410488128662,
|
|
"z": 6949726957827806e-19
|
|
}, {
|
|
"x": 0.48438939452171326,
|
|
"y": 0.6392973065376282,
|
|
"z": 705525919329375e-18
|
|
}, {
|
|
"x": 0.47143134474754333,
|
|
"y": 0.6589511632919312,
|
|
"z": 6980331381782889e-19
|
|
}, {
|
|
"x": 0.48704618215560913,
|
|
"y": 0.6752797961235046,
|
|
"z": 6921177846379578e-19
|
|
}, {
|
|
"x": 0.6243702173233032,
|
|
"y": 0.640461802482605,
|
|
"z": -6592126737814397e-20
|
|
}, {
|
|
"x": 0.6390967965126038,
|
|
"y": 0.6385173797607422,
|
|
"z": -16105435497593135e-20
|
|
}, {
|
|
"x": 0.6230536699295044,
|
|
"y": 0.6224825382232666,
|
|
"z": -16136496560648084e-20
|
|
}, {
|
|
"x": 0.6095397472381592,
|
|
"y": 0.641917884349823,
|
|
"z": -1803556369850412e-19
|
|
}, {
|
|
"x": 0.6250996589660645,
|
|
"y": 0.6586247682571411,
|
|
"z": -1785515050869435e-19
|
|
}]],
|
|
"faceBlendshapes": [{
|
|
"categories": [{
|
|
"index": 0,
|
|
"score": 5187174338061595e-21,
|
|
"categoryName": "_neutral",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 1,
|
|
"score": 0.24521504342556,
|
|
"categoryName": "browDownLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 2,
|
|
"score": 0.1987743377685547,
|
|
"categoryName": "browDownRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 3,
|
|
"score": 0.013400448486208916,
|
|
"categoryName": "browInnerUp",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 4,
|
|
"score": 0.012361560948193073,
|
|
"categoryName": "browOuterUpLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 5,
|
|
"score": 0.019305096939206123,
|
|
"categoryName": "browOuterUpRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 6,
|
|
"score": 28426356948330067e-21,
|
|
"categoryName": "cheekPuff",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 7,
|
|
"score": 34500112633395474e-23,
|
|
"categoryName": "cheekSquintLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 8,
|
|
"score": 483789051486383e-21,
|
|
"categoryName": "cheekSquintRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 9,
|
|
"score": 0.07650448381900787,
|
|
"categoryName": "eyeBlinkLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 10,
|
|
"score": 0.05070012807846069,
|
|
"categoryName": "eyeBlinkRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 11,
|
|
"score": 0.13978900015354156,
|
|
"categoryName": "eyeLookDownLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 12,
|
|
"score": 0.14198613166809082,
|
|
"categoryName": "eyeLookDownRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 13,
|
|
"score": 0.2177766114473343,
|
|
"categoryName": "eyeLookInLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 14,
|
|
"score": 0.014739357866346836,
|
|
"categoryName": "eyeLookInRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 15,
|
|
"score": 0.02361512929201126,
|
|
"categoryName": "eyeLookOutLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 16,
|
|
"score": 0.19679604470729828,
|
|
"categoryName": "eyeLookOutRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 17,
|
|
"score": 0.04874616861343384,
|
|
"categoryName": "eyeLookUpLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 18,
|
|
"score": 0.049392376095056534,
|
|
"categoryName": "eyeLookUpRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 19,
|
|
"score": 0.34944331645965576,
|
|
"categoryName": "eyeSquintLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 20,
|
|
"score": 0.2939716875553131,
|
|
"categoryName": "eyeSquintRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 21,
|
|
"score": 0.005955042317509651,
|
|
"categoryName": "eyeWideLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 22,
|
|
"score": 0.006776117719709873,
|
|
"categoryName": "eyeWideRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 23,
|
|
"score": 16942436559475027e-21,
|
|
"categoryName": "jawForward",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 24,
|
|
"score": 0.0045165494084358215,
|
|
"categoryName": "jawLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 25,
|
|
"score": 0.07803940027952194,
|
|
"categoryName": "jawOpen",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 26,
|
|
"score": 2090057751047425e-20,
|
|
"categoryName": "jawRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 27,
|
|
"score": 0.06032035872340202,
|
|
"categoryName": "mouthClose",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 28,
|
|
"score": 0.00228882092051208,
|
|
"categoryName": "mouthDimpleLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 29,
|
|
"score": 0.00781762320548296,
|
|
"categoryName": "mouthDimpleRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 30,
|
|
"score": 0.0017093931091949344,
|
|
"categoryName": "mouthFrownLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 31,
|
|
"score": 0.0019319106359034777,
|
|
"categoryName": "mouthFrownRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 32,
|
|
"score": 8485237776767462e-20,
|
|
"categoryName": "mouthFunnel",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 33,
|
|
"score": 9051355300471187e-19,
|
|
"categoryName": "mouthLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 34,
|
|
"score": 3630454302765429e-19,
|
|
"categoryName": "mouthLowerDownLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 35,
|
|
"score": 17601238505449146e-20,
|
|
"categoryName": "mouthLowerDownRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 36,
|
|
"score": 0.12865161895751953,
|
|
"categoryName": "mouthPressLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 37,
|
|
"score": 0.20137207210063934,
|
|
"categoryName": "mouthPressRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 38,
|
|
"score": 0.0022203284315764904,
|
|
"categoryName": "mouthPucker",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 39,
|
|
"score": 9096377179957926e-19,
|
|
"categoryName": "mouthRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 40,
|
|
"score": 0.34189721941947937,
|
|
"categoryName": "mouthRollLower",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 41,
|
|
"score": 0.11409689486026764,
|
|
"categoryName": "mouthRollUpper",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 42,
|
|
"score": 0.17172536253929138,
|
|
"categoryName": "mouthShrugLower",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 43,
|
|
"score": 0.004038424696773291,
|
|
"categoryName": "mouthShrugUpper",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 44,
|
|
"score": 23205230536404997e-20,
|
|
"categoryName": "mouthSmileLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 45,
|
|
"score": 19313619122840464e-20,
|
|
"categoryName": "mouthSmileRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 46,
|
|
"score": 0.0018571305554360151,
|
|
"categoryName": "mouthStretchLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 47,
|
|
"score": 0.0023813238367438316,
|
|
"categoryName": "mouthStretchRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 48,
|
|
"score": 24323100660694763e-21,
|
|
"categoryName": "mouthUpperUpLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 49,
|
|
"score": 3161552012898028e-20,
|
|
"categoryName": "mouthUpperUpRight",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 50,
|
|
"score": 108198406678639e-21,
|
|
"categoryName": "noseSneerLeft",
|
|
"displayName": ""
|
|
}, {
|
|
"index": 51,
|
|
"score": 12652527630052646e-22,
|
|
"categoryName": "noseSneerRight",
|
|
"displayName": ""
|
|
}],
|
|
"headIndex": -1,
|
|
"headName": ""
|
|
}],
|
|
"facialTransformationMatrixes": [{
|
|
"rows": 4,
|
|
"columns": 4,
|
|
"data": [0.9947517514228821, 0.10230544209480286, 0.0013679931871592999, 0, -0.10230997204780579, 0.9947447776794434, 0.003816320328041911, 0, -970348424743861e-18, -0.0039362297393381596, 0.9999914169311523, 0, 2.8888821601867676, -7.808934211730957, -30.52109146118164, 1]
|
|
}]
|
|
}
|
|
};
|
|
|
|
// node_modules/@react-three/drei/web/FaceLandmarker.js
|
|
var React140 = __toESM(require_react());
|
|
var import_react25 = __toESM(require_react());
|
|
var FaceLandmarkerContext = (0, import_react25.createContext)({});
|
|
var FaceLandmarkerDefaults = {
|
|
basePath: "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.17/wasm",
|
|
options: {
|
|
baseOptions: {
|
|
modelAssetPath: "https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task",
|
|
delegate: "GPU"
|
|
},
|
|
runningMode: "VIDEO",
|
|
outputFaceBlendshapes: true,
|
|
outputFacialTransformationMatrixes: true
|
|
}
|
|
};
|
|
var FaceLandmarker = (0, import_react25.forwardRef)(({
|
|
basePath = FaceLandmarkerDefaults.basePath,
|
|
options = FaceLandmarkerDefaults.options,
|
|
children
|
|
}, fref) => {
|
|
const opts = JSON.stringify(options);
|
|
const faceLandmarker = suspend(async () => {
|
|
const {
|
|
FilesetResolver,
|
|
FaceLandmarker: FaceLandmarker2
|
|
} = await import("./vision_bundle-CRIBZNUI.js");
|
|
const vision = await FilesetResolver.forVisionTasks(basePath);
|
|
return FaceLandmarker2.createFromOptions(vision, options);
|
|
}, [basePath, opts]);
|
|
(0, import_react25.useEffect)(() => {
|
|
return () => {
|
|
faceLandmarker == null || faceLandmarker.close();
|
|
clear([basePath, opts]);
|
|
};
|
|
}, [faceLandmarker, basePath, opts]);
|
|
(0, import_react25.useImperativeHandle)(fref, () => faceLandmarker, [faceLandmarker]);
|
|
return React140.createElement(FaceLandmarkerContext.Provider, {
|
|
value: faceLandmarker
|
|
}, children);
|
|
});
|
|
function useFaceLandmarker() {
|
|
return (0, import_react25.useContext)(FaceLandmarkerContext);
|
|
}
|
|
|
|
// node_modules/@react-three/drei/web/FaceControls.js
|
|
function mean2(v12, v22) {
|
|
return v12.clone().add(v22).multiplyScalar(0.5);
|
|
}
|
|
function localToLocal(objSrc, v5, objDst) {
|
|
const v_world = objSrc.localToWorld(v5);
|
|
return objDst.worldToLocal(v_world);
|
|
}
|
|
var FaceControlsContext = (0, import_react26.createContext)({});
|
|
var FaceControls = (0, import_react26.forwardRef)(({
|
|
camera,
|
|
videoTexture = {
|
|
start: true
|
|
},
|
|
manualDetect = false,
|
|
faceLandmarkerResult,
|
|
manualUpdate = false,
|
|
makeDefault,
|
|
smoothTime = 0.25,
|
|
offset = true,
|
|
offsetScalar = 80,
|
|
eyes = false,
|
|
eyesAsOrigin = true,
|
|
depth = 0.15,
|
|
debug = false,
|
|
facemesh
|
|
}, fref) => {
|
|
var _result$facialTransfo, _result$faceBlendshap;
|
|
const scene = useThree((state) => state.scene);
|
|
const defaultCamera = useThree((state) => state.camera);
|
|
const set = useThree((state) => state.set);
|
|
const get = useThree((state) => state.get);
|
|
const explCamera = camera || defaultCamera;
|
|
const facemeshApiRef = (0, import_react26.useRef)(null);
|
|
const [target2] = (0, import_react26.useState)(() => new Object3D());
|
|
const [irisRightDirPos] = (0, import_react26.useState)(() => new Vector3());
|
|
const [irisLeftDirPos] = (0, import_react26.useState)(() => new Vector3());
|
|
const [irisRightLookAt] = (0, import_react26.useState)(() => new Vector3());
|
|
const [irisLeftLookAt] = (0, import_react26.useState)(() => new Vector3());
|
|
const computeTarget = (0, import_react26.useCallback)(() => {
|
|
target2.parent = explCamera.parent;
|
|
const facemeshApi = facemeshApiRef.current;
|
|
if (facemeshApi) {
|
|
const {
|
|
outerRef,
|
|
eyeRightRef,
|
|
eyeLeftRef
|
|
} = facemeshApi;
|
|
if (eyeRightRef.current && eyeLeftRef.current) {
|
|
const {
|
|
irisDirRef: irisRightDirRef
|
|
} = eyeRightRef.current;
|
|
const {
|
|
irisDirRef: irisLeftDirRef
|
|
} = eyeLeftRef.current;
|
|
if (irisRightDirRef.current && irisLeftDirRef.current && outerRef.current) {
|
|
irisRightDirPos.copy(localToLocal(irisRightDirRef.current, new Vector3(0, 0, 0), outerRef.current));
|
|
irisLeftDirPos.copy(localToLocal(irisLeftDirRef.current, new Vector3(0, 0, 0), outerRef.current));
|
|
target2.position.copy(localToLocal(outerRef.current, mean2(irisRightDirPos, irisLeftDirPos), explCamera.parent || scene));
|
|
irisRightLookAt.copy(localToLocal(irisRightDirRef.current, new Vector3(0, 0, 1), outerRef.current));
|
|
irisLeftLookAt.copy(localToLocal(irisLeftDirRef.current, new Vector3(0, 0, 1), outerRef.current));
|
|
target2.lookAt(outerRef.current.localToWorld(mean2(irisRightLookAt, irisLeftLookAt)));
|
|
}
|
|
} else {
|
|
if (outerRef.current) {
|
|
target2.position.copy(localToLocal(outerRef.current, new Vector3(0, 0, 0), explCamera.parent || scene));
|
|
target2.lookAt(outerRef.current.localToWorld(new Vector3(0, 0, 1)));
|
|
}
|
|
}
|
|
}
|
|
return target2;
|
|
}, [explCamera, irisLeftDirPos, irisLeftLookAt, irisRightDirPos, irisRightLookAt, scene, target2]);
|
|
const [current] = (0, import_react26.useState)(() => new Object3D());
|
|
const update2 = (0, import_react26.useCallback)(function(delta, target3) {
|
|
if (explCamera) {
|
|
var _target;
|
|
(_target = target3) !== null && _target !== void 0 ? _target : target3 = computeTarget();
|
|
if (smoothTime > 0) {
|
|
const eps2 = 1e-9;
|
|
easing.damp3(current.position, target3.position, smoothTime, delta, void 0, void 0, eps2);
|
|
easing.dampE(current.rotation, target3.rotation, smoothTime, delta, void 0, void 0, eps2);
|
|
} else {
|
|
current.position.copy(target3.position);
|
|
current.rotation.copy(target3.rotation);
|
|
}
|
|
explCamera.position.copy(current.position);
|
|
explCamera.rotation.copy(current.rotation);
|
|
}
|
|
}, [explCamera, computeTarget, smoothTime, current.position, current.rotation]);
|
|
useFrame((_, delta) => {
|
|
if (manualUpdate) return;
|
|
update2(delta);
|
|
});
|
|
const videoTextureRef = (0, import_react26.useRef)(null);
|
|
const [_faceLandmarkerResult, setFaceLandmarkerResult] = (0, import_react26.useState)();
|
|
const faceLandmarker = useFaceLandmarker();
|
|
const onVideoFrame = (0, import_react26.useCallback)((now2, metadata) => {
|
|
const texture = videoTextureRef.current;
|
|
if (!texture) return;
|
|
const videoFrame = texture.source.data;
|
|
const result2 = faceLandmarker == null ? void 0 : faceLandmarker.detectForVideo(videoFrame, now2);
|
|
setFaceLandmarkerResult(result2);
|
|
}, [faceLandmarker]);
|
|
const api = (0, import_react26.useMemo)(() => Object.assign(Object.create(EventDispatcher.prototype), {
|
|
computeTarget,
|
|
update: update2,
|
|
facemeshApiRef
|
|
}), [computeTarget, update2]);
|
|
(0, import_react26.useImperativeHandle)(fref, () => api, [api]);
|
|
(0, import_react26.useEffect)(() => {
|
|
if (makeDefault) {
|
|
const old = get().controls;
|
|
set({
|
|
controls: api
|
|
});
|
|
return () => set({
|
|
controls: old
|
|
});
|
|
}
|
|
}, [makeDefault, api, get, set]);
|
|
const result = faceLandmarkerResult !== null && faceLandmarkerResult !== void 0 ? faceLandmarkerResult : _faceLandmarkerResult;
|
|
const points = result == null ? void 0 : result.faceLandmarks[0];
|
|
const facialTransformationMatrix = result == null || (_result$facialTransfo = result.facialTransformationMatrixes) == null ? void 0 : _result$facialTransfo[0];
|
|
const faceBlendshapes = result == null || (_result$faceBlendshap = result.faceBlendshapes) == null ? void 0 : _result$faceBlendshap[0];
|
|
const videoTextureProps = {
|
|
onVideoFrame,
|
|
...videoTexture
|
|
};
|
|
return React141.createElement(FaceControlsContext.Provider, {
|
|
value: api
|
|
}, !manualDetect && React141.createElement(import_react26.Suspense, {
|
|
fallback: null
|
|
}, "src" in videoTextureProps ? React141.createElement(VideoTexture2, _extends({
|
|
ref: videoTextureRef
|
|
}, videoTextureProps)) : React141.createElement(WebcamVideoTexture, _extends({
|
|
ref: videoTextureRef
|
|
}, videoTextureProps))), React141.createElement(Facemesh, _extends({
|
|
ref: facemeshApiRef,
|
|
children: React141.createElement("meshNormalMaterial", {
|
|
side: DoubleSide
|
|
})
|
|
}, facemesh, {
|
|
points,
|
|
depth,
|
|
facialTransformationMatrix,
|
|
faceBlendshapes,
|
|
eyes,
|
|
eyesAsOrigin,
|
|
offset,
|
|
offsetScalar,
|
|
debug,
|
|
"rotation-z": Math.PI,
|
|
visible: debug
|
|
})));
|
|
});
|
|
var useFaceControls = () => (0, import_react26.useContext)(FaceControlsContext);
|
|
export {
|
|
AccumulativeShadows,
|
|
AdaptiveDpr,
|
|
AdaptiveEvents,
|
|
ArcballControls2 as ArcballControls,
|
|
AsciiRenderer,
|
|
BBAnchor,
|
|
Backdrop,
|
|
BakeShadows,
|
|
Billboard,
|
|
Bounds,
|
|
Box,
|
|
Bvh,
|
|
CameraControls2 as CameraControls,
|
|
CameraControls as CameraControlsImpl,
|
|
CameraShake,
|
|
Capsule,
|
|
CatmullRomLine,
|
|
Caustics,
|
|
Center,
|
|
Circle,
|
|
Clone,
|
|
Cloud,
|
|
CloudInstance,
|
|
Clouds,
|
|
ComputedAttribute,
|
|
Cone,
|
|
ContactShadows,
|
|
CubeCamera2 as CubeCamera,
|
|
CubeTexture,
|
|
CubicBezierLine,
|
|
CurveModifier,
|
|
CycleRaycast,
|
|
Cylinder,
|
|
Decal,
|
|
Detailed,
|
|
DetectGPU,
|
|
DeviceOrientationControls2 as DeviceOrientationControls,
|
|
Dodecahedron,
|
|
DragControls,
|
|
Edges,
|
|
Effects,
|
|
Environment,
|
|
EnvironmentCube,
|
|
EnvironmentMap,
|
|
EnvironmentPortal,
|
|
Example,
|
|
Extrude,
|
|
FaceControls,
|
|
FaceLandmarker,
|
|
FaceLandmarkerDefaults,
|
|
Facemesh,
|
|
FacemeshDatas,
|
|
FacemeshEye,
|
|
FacemeshEyeDefaults,
|
|
Fbo,
|
|
Fbx,
|
|
FirstPersonControls2 as FirstPersonControls,
|
|
Fisheye,
|
|
Float,
|
|
FlyControls2 as FlyControls,
|
|
GizmoHelper,
|
|
GizmoViewcube,
|
|
GizmoViewport,
|
|
Gltf,
|
|
GradientTexture,
|
|
GradientType,
|
|
Grid,
|
|
Helper,
|
|
Html,
|
|
Hud,
|
|
Icosahedron,
|
|
Image,
|
|
Instance,
|
|
InstancedAttribute,
|
|
Instances,
|
|
IsObject,
|
|
KeyboardControls,
|
|
Ktx2,
|
|
Lathe,
|
|
Lightformer,
|
|
Line,
|
|
Loader2 as Loader,
|
|
MapControls2 as MapControls,
|
|
MarchingCube,
|
|
MarchingCubes2 as MarchingCubes,
|
|
MarchingPlane,
|
|
Mask,
|
|
MatcapTexture,
|
|
Merged,
|
|
MeshDiscardMaterial,
|
|
MeshDistortMaterial,
|
|
MeshPortalMaterial,
|
|
MeshReflectorMaterial2 as MeshReflectorMaterial,
|
|
MeshRefractionMaterial2 as MeshRefractionMaterial,
|
|
MeshTransmissionMaterial,
|
|
MeshWobbleMaterial,
|
|
MotionPathControls,
|
|
MultiMaterial,
|
|
NormalTexture,
|
|
Octahedron,
|
|
OrbitControls2 as OrbitControls,
|
|
OrthographicCamera2 as OrthographicCamera,
|
|
Outlines,
|
|
PerformanceMonitor,
|
|
PerspectiveCamera2 as PerspectiveCamera,
|
|
PivotControls,
|
|
Plane2 as Plane,
|
|
Point,
|
|
PointMaterial,
|
|
PointMaterialImpl,
|
|
PointerLockControls2 as PointerLockControls,
|
|
Points,
|
|
PointsBuffer,
|
|
Polyhedron,
|
|
PositionMesh,
|
|
PositionPoint,
|
|
PositionalAudio,
|
|
Preload,
|
|
PresentationControls,
|
|
Progress,
|
|
QuadraticBezierLine,
|
|
RandomizedLight,
|
|
RenderCubeTexture,
|
|
RenderTexture,
|
|
Resize,
|
|
Ring,
|
|
RoundedBox,
|
|
RoundedBoxGeometry,
|
|
Sampler,
|
|
ScreenQuad,
|
|
ScreenSizer,
|
|
ScreenSpace,
|
|
ScreenVideoTexture,
|
|
Scroll,
|
|
ScrollControls,
|
|
Segment,
|
|
SegmentObject,
|
|
Segments,
|
|
Select,
|
|
Shadow,
|
|
ShadowAlpha,
|
|
Shape2 as Shape,
|
|
Sky2 as Sky,
|
|
SoftShadows,
|
|
Sparkles,
|
|
Sphere2 as Sphere,
|
|
Splat,
|
|
SpotLight,
|
|
SpotLightShadow,
|
|
SpriteAnimator,
|
|
Stage,
|
|
Stars,
|
|
Stats,
|
|
StatsGl,
|
|
Svg,
|
|
Tetrahedron,
|
|
Text2 as Text,
|
|
Text3D,
|
|
Texture2 as Texture,
|
|
Torus,
|
|
TorusKnot,
|
|
TrackballControls2 as TrackballControls,
|
|
Trail,
|
|
TrailTexture,
|
|
TransformControls2 as TransformControls,
|
|
Tube,
|
|
VideoTexture2 as VideoTexture,
|
|
View,
|
|
WebcamVideoTexture,
|
|
Wireframe,
|
|
accumulativeContext,
|
|
calcPosFromAngles,
|
|
calculateScaleFactor,
|
|
checkIfFrameIsEmpty,
|
|
createInstances,
|
|
getFirstFrame,
|
|
isWebGL2Available,
|
|
meshBounds,
|
|
shaderMaterial,
|
|
useAnimations,
|
|
useAspect,
|
|
useBVH,
|
|
useBounds,
|
|
useBoxProjectedEnv,
|
|
useCamera,
|
|
useContextBridge,
|
|
useCubeCamera,
|
|
useCubeTexture,
|
|
useCursor,
|
|
useDepthBuffer,
|
|
useDetectGPU,
|
|
useEnvironment,
|
|
useFBO,
|
|
useFBX,
|
|
useFaceControls,
|
|
useFaceLandmarker,
|
|
useFont,
|
|
useGLTF,
|
|
useGizmoContext,
|
|
useHelper,
|
|
useIntersect,
|
|
useKTX2,
|
|
useKeyboardControls,
|
|
useMask,
|
|
useMatcapTexture,
|
|
useMotion,
|
|
useNormalTexture,
|
|
usePerformanceMonitor,
|
|
useProgress,
|
|
useScroll,
|
|
useSelect,
|
|
useSpriteAnimator,
|
|
useSpriteLoader,
|
|
useSurfaceSampler,
|
|
useTexture,
|
|
useTrail,
|
|
useTrailTexture,
|
|
useVideoTexture
|
|
};
|
|
//# sourceMappingURL=@react-three_drei.js.map
|