@3driseai/3drise-viewer 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/CustomPrimitive.js +1 -1
- package/dist/components/GeometryShape.d.ts.map +1 -1
- package/dist/components/GeometryShape.js +19 -3
- package/dist/components/ObjectNode.d.ts.map +1 -1
- package/dist/components/ObjectNode.js +1 -9
- package/dist/components/ParticlesR3f.d.ts.map +1 -1
- package/dist/components/ParticlesR3f.js +63 -12
- package/dist/components/PointCloud.d.ts.map +1 -1
- package/dist/components/PointCloud.js +50 -10
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +6 -0
- package/dist/hooks/useMaterialApplication.d.ts.map +1 -1
- package/dist/hooks/useMaterialApplication.js +2 -3
- package/dist/hooks/useMaterialOptions.d.ts +2 -2
- package/dist/hooks/useMaterialOptions.d.ts.map +1 -1
- package/dist/hooks/useMaterialOptions.js +13 -31
- package/dist/hooks/useObjectEdges.d.ts.map +1 -1
- package/dist/hooks/useObjectEdges.js +3 -49
- package/dist/utils/pointsMaterialOwnership.d.ts +9 -0
- package/dist/utils/pointsMaterialOwnership.d.ts.map +1 -0
- package/dist/utils/pointsMaterialOwnership.js +14 -0
- package/package.json +2 -2
|
@@ -76,7 +76,7 @@ const CustomPrimitive = memo(({ createdObject, onObjectReady, onObjectDispose, h
|
|
|
76
76
|
// mode = 'outline';
|
|
77
77
|
// }
|
|
78
78
|
if (createdObject.type === 'mesh')
|
|
79
|
-
return _jsx("mesh", { ref: meshRef, name: createdObject.name, children: _jsx(GeometryMesh, { config: createdObject.config, materialSettings: createdObject.materialSettings, animations: createdObject.animations, onObjectReady: (_object, ref) => onObjectReady && onObjectReady(createdObject, ref), onObjectDispose: (_object, ref) => onObjectDispose && onObjectDispose(createdObject, ref), modeConfig: createdObject.modeConfig || { mode: 'solid', count: 1000, symmetry: 3, spacing: 0.1, slices: 8, linkRadius: 0.05, angle: 18, lineWidth: 1 } }) }, createdObject.id);
|
|
79
|
+
return _jsx("mesh", { ref: meshRef, name: createdObject.name, children: _jsx(GeometryMesh, { config: createdObject.config, materialSettings: createdObject.materialSettings, animations: createdObject.animations, onObjectReady: (_object, ref) => onObjectReady && onObjectReady(createdObject, ref), onObjectDispose: (_object, ref) => onObjectDispose && onObjectDispose(createdObject, ref), modeConfig: createdObject.modeConfig || { mode: 'solid', count: 1000, symmetry: 3, spacing: 0.1, slices: 8, linkRadius: 0.05, angle: 18, lineWidth: 1 }, children: useDreiMaterials && createdObject.meshSettings.visible && (_jsx(MaterialLibrary, { materialSettings: createdObject.materialSettings })) }) }, createdObject.id);
|
|
80
80
|
if (!resolvedObject) {
|
|
81
81
|
return null;
|
|
82
82
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GeometryShape.d.ts","sourceRoot":"","sources":["../../src/components/GeometryShape.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAI5C,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"GeometryShape.d.ts","sourceRoot":"","sources":["../../src/components/GeometryShape.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAI5C,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAQjH,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEnC,KAAK,QAAQ,GAAG;IACZ,IAAI,EAAE,MAAM,CAAC;CAChB,GAAG;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,YAAY,CAAC;CAC3B,GAAG;IACA,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,EAAE,EAAE,CAAC;CAChB,GAAG;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,YAAY,CAAC;IACxB,QAAQ,EAAE,EAAE,EAAE,CAAC;CAClB,CAAC;AAEF,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACvD,MAAM,EAAE,mBAAmB,CAAC;IAC5B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,QAAQ,CAAC,EAAE,SAAS,CAAC;CACxB;AA4BD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,GAAG,SAAS,GAAG,cAAc,CAShG;AA4BD,wBAAgB,UAAU,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,GAAE,MAAW,GAAG,YAAY,CAyBpG;AACD,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAiC/E;AACD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAiB9F;AACD,wBAAgB,WAAW,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,CAgC7F;AACD,wBAAgB,YAAY,CAAC,GAAG,EAAE,cAAc,GAAG,YAAY,CAS9D;AACD,wBAAgB,OAAO,CAAC,GAAG,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,EAAE,EAAE,CAKnE;AACD,wBAAgB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,EAAE,EAAE,CAkBnD;AACD,wBAAgB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,EAAE,EAAE,CAKnD;AACD,+FAA+F;AAC/F,wBAAgB,aAAa,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,MAAU,GAAG,EAAE,EAAE,CAuBzF;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAU,GAAG;IAC7F,SAAS,EAAE,YAAY,CAAC;IACxB,QAAQ,EAAE,EAAE,EAAE,CAAC;CAClB,CAoCJ;AACD,wBAAgB,WAAW,CAAC,GAAG,EAAE,cAAc,EAAE,CAAC,EAAE,UAAU,GAAG,QAAQ,CAkBxE;AAMD,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,UAAU,EAAE,UAA8B,EAAE,KAAiB,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,EAAE,iBAAiB,+BA2BpL;AAED,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,MAAY,EAAE,QAAQ,EAAE,EAAE;IACnD,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACxB,GAQ2E,GAAG,CACtF"}
|
|
@@ -2,9 +2,16 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useEffect, useMemo, useRef } from 'react';
|
|
3
3
|
import { useObjectReady } from '../hooks/useObjectReady.js';
|
|
4
4
|
import { EdgesGeometry, WireframeGeometry, Mesh, MeshBasicMaterial, Raycaster, Vector3, DoubleSide, } from 'three';
|
|
5
|
-
import {
|
|
5
|
+
import { buildSegmentQuadGeometry } from '@3driseai/3drise-core';
|
|
6
6
|
import { shapeGenerators } from '../utils/shapes.js';
|
|
7
7
|
import PointCloud from './PointCloud.js';
|
|
8
|
+
/**
|
|
9
|
+
* World-space half-thickness of a line ribbon at `lineWidth: 1`. Line modes are
|
|
10
|
+
* built as quad meshes rather than line primitives so that materials apply to
|
|
11
|
+
* them — see buildSegmentQuadGeometry — which means width is a world unit here,
|
|
12
|
+
* not a screen-space pixel count. Matches the edges builder's default.
|
|
13
|
+
*/
|
|
14
|
+
const LINE_THICKNESS_UNIT = 0.008;
|
|
8
15
|
const defaultModeConfig = {
|
|
9
16
|
mode: 'solid',
|
|
10
17
|
count: 1000,
|
|
@@ -312,13 +319,22 @@ export function GeometryMesh({ config, materialSettings, animations, modeConfig
|
|
|
312
319
|
const geometry = useShapeGeometry(config);
|
|
313
320
|
const safeModeConfig = normalizeModeConfig(modeConfig);
|
|
314
321
|
const data = useModeData(geometry, safeModeConfig);
|
|
322
|
+
// Line modes are ribbons of quads, not line primitives, so the material
|
|
323
|
+
// system reaches them the same way it reaches edges. Built before the
|
|
324
|
+
// branches below because hooks cannot run conditionally.
|
|
325
|
+
const lineSegments = data.kind === 'lines' ? data.points : data.kind === 'plexus' ? data.segments : null;
|
|
326
|
+
const lineThickness = (safeModeConfig.lineWidth ?? 1) * LINE_THICKNESS_UNIT;
|
|
327
|
+
const lineGeometry = useMemo(() => (lineSegments && lineSegments.length
|
|
328
|
+
? buildSegmentQuadGeometry(lineSegments, lineThickness)
|
|
329
|
+
: null), [lineSegments, lineThickness]);
|
|
330
|
+
useEffect(() => () => { lineGeometry?.dispose(); }, [lineGeometry]);
|
|
315
331
|
// if (data.kind === 'points') return <PointCloud positions={data.positions} color={color} size={modeConfig.mode === 'vertices' ? 0.035 : 0.02} />;
|
|
316
332
|
if (data.kind === 'points')
|
|
317
333
|
return _jsx(PointCloud, { positions: data.positions, animations: animations, materialSettings: materialSettings, onObjectReady: reportReady, onObjectDispose: reportDispose });
|
|
318
334
|
if (data.kind === 'lines')
|
|
319
|
-
return
|
|
335
|
+
return lineGeometry ? (_jsx("mesh", { ref: rootRef, geometry: lineGeometry, children: children ?? _jsx("meshBasicMaterial", { color: color, side: DoubleSide }) })) : null;
|
|
320
336
|
if (data.kind === 'plexus')
|
|
321
|
-
return (_jsxs("group", { ref: rootRef, children: [_jsx(PointCloud, { positions: data.positions, animations: animations, materialSettings: materialSettings }),
|
|
337
|
+
return (_jsxs("group", { ref: rootRef, children: [_jsx(PointCloud, { positions: data.positions, animations: animations, materialSettings: materialSettings }), lineGeometry && (_jsx("mesh", { geometry: lineGeometry, children: children ?? _jsx("meshBasicMaterial", { color: color, side: DoubleSide, transparent: true, opacity: 0.45 }) }))] }));
|
|
322
338
|
return (_jsx("mesh", { ref: rootRef, geometry: geometry, children: children ?? _jsx("meshPhongMaterial", { color: color, side: DoubleSide }) }));
|
|
323
339
|
}
|
|
324
340
|
export function FitGroup({ geometry, radius = 1.7, children }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ObjectNode.d.ts","sourceRoot":"","sources":["../../src/components/ObjectNode.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAe,qBAAqB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAChG,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"ObjectNode.d.ts","sourceRoot":"","sources":["../../src/components/ObjectNode.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAe,qBAAqB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAChG,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,KAAK,eAAe,GAAG,gBAAgB,GAAG;IACtC,IAAI,EAAE,cAAc,CAAC;IACrB,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CAC7G,CAAC;AAgBF,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAyGzC,CAAC;AACF,eAAe,UAAU,CAAC"}
|
|
@@ -13,15 +13,7 @@ import LightObject from "./LightObject.js";
|
|
|
13
13
|
import EnvironmentObject from "./EnvironmentObject.js";
|
|
14
14
|
import Galaxy from "./Galaxy.js";
|
|
15
15
|
import GridGenerator from "./GridsGenerator.js";
|
|
16
|
-
|
|
17
|
-
'effect',
|
|
18
|
-
// 'gallery',
|
|
19
|
-
'earth',
|
|
20
|
-
'space',
|
|
21
|
-
'shootingStars',
|
|
22
|
-
'grid',
|
|
23
|
-
// 'moon'
|
|
24
|
-
]);
|
|
16
|
+
import { SELF_MANAGED_MATERIAL } from "../constants.js";
|
|
25
17
|
// const EffectsLayer: React.FC<{ effects: CreatedObjectSettings['effects'] }> = ({ effects }) =>
|
|
26
18
|
// effects?.length ? (
|
|
27
19
|
// <>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ParticlesR3f.d.ts","sourceRoot":"","sources":["../../src/components/ParticlesR3f.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAO7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"ParticlesR3f.d.ts","sourceRoot":"","sources":["../../src/components/ParticlesR3f.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAO7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG/D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,UAAU,iBAAkB,SAAQ,gBAAgB;IAChD,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChD;AAMD,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAoJ7C,CAAC;AACF,eAAe,YAAY,CAAC"}
|
|
@@ -5,8 +5,9 @@ import { useFrame } from '@react-three/fiber';
|
|
|
5
5
|
import { useParticlePositions } from '../hooks/useParticlePositions.js';
|
|
6
6
|
import { useParticlesColors } from '../hooks/useParticlesColors.js';
|
|
7
7
|
import { useParticlesTextures } from '../hooks/useParticlesTextures.js';
|
|
8
|
-
import { handleShapeAnimation, buildShaderEffectsMaterial, structureKey } from '@3driseai/3drise-core';
|
|
8
|
+
import { handleShapeAnimation, buildShaderEffectsMaterial, structureKey, SELF_OWNED_MATERIAL_KEY, applyVertexEffects, partitionShaderEffects, LOCAL_POINTER_SCALE } from '@3driseai/3drise-core';
|
|
9
9
|
import { update3driseShaderUniforms } from '../hooks/use3driseShader.js';
|
|
10
|
+
import { ownsShaderEffectsMaterial } from '../utils/pointsMaterialOwnership.js';
|
|
10
11
|
function normalizeEffects(raw) {
|
|
11
12
|
return Array.isArray(raw) ? raw : [];
|
|
12
13
|
}
|
|
@@ -71,42 +72,92 @@ const ParticlesR3f = ({ particlesSettings, duration = 1, transitionSettings, onO
|
|
|
71
72
|
const activeEffects = useMemo(() => normalizeEffects(particlesSettings.animations?.material?.shaderEffects), [particlesSettings.animations?.material?.shaderEffects]);
|
|
72
73
|
const pointerRadius = particlesSettings.animations?.material
|
|
73
74
|
?.shaderEffectsPointerRadius ?? 0.4;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
// Position effects displace the geometry from the CPU and leave `.material`
|
|
76
|
+
// alone, so they compose with any material. Only the rest still need the
|
|
77
|
+
// shader shell — and only the shell takes ownership of `.material`.
|
|
78
|
+
const { position: positionEffects, shell: shellEffects } = useMemo(() => partitionShaderEffects(activeEffects), [activeEffects]);
|
|
79
|
+
const hasPositionEffects = positionEffects.some(effect => effect.enabled);
|
|
80
|
+
const effectsKey = useMemo(() => structureKey(shellEffects), [shellEffects]);
|
|
81
|
+
const ownsMaterial = ownsShaderEffectsMaterial(particlesSettings.materialSettings, shellEffects);
|
|
82
|
+
const material = useMemo(() => ownsMaterial ? buildShaderEffectsMaterial({
|
|
83
|
+
effects: shellEffects,
|
|
77
84
|
initialColor: color,
|
|
78
85
|
initialOpacity: opacity,
|
|
79
86
|
initialPointSize: pointSize,
|
|
80
87
|
initialParticleUVScale: particleUVScale,
|
|
81
88
|
initialPointerEffectRadius: pointerRadius,
|
|
82
|
-
}),
|
|
89
|
+
}) : null,
|
|
83
90
|
// Rebuild when the structural set of effects changes; not on parameter tweaks.
|
|
84
91
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
85
|
-
[effectsKey]);
|
|
92
|
+
[effectsKey, ownsMaterial]);
|
|
93
|
+
// With position effects on, the attribute gets its own buffer: the shape
|
|
94
|
+
// animation writes this frame's morph into it, and the effects displace from
|
|
95
|
+
// a snapshot of that into the same buffer. Without a separate buffer the
|
|
96
|
+
// shape animation would read back its own displaced output next frame.
|
|
97
|
+
const displayPositions = useMemo(() => (hasPositionEffects && basePositions.current
|
|
98
|
+
? new Float32Array(basePositions.current)
|
|
99
|
+
: basePositions.current), [hasPositionEffects, basePositions.current]);
|
|
100
|
+
const frameBaseRef = useRef(null);
|
|
86
101
|
useEffect(() => {
|
|
87
102
|
materialRef.current = material;
|
|
88
103
|
return () => {
|
|
89
|
-
material
|
|
104
|
+
material?.dispose();
|
|
90
105
|
};
|
|
91
106
|
}, [material]);
|
|
107
|
+
// Tell useMaterialApplication's traversal to leave this object alone while we
|
|
108
|
+
// own its material. Set imperatively rather than through a `userData` prop:
|
|
109
|
+
// R3F replaces the whole object on every render, which would wipe the
|
|
110
|
+
// applyTexture handle stashed above.
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
const points = pointsRef.current;
|
|
113
|
+
if (!points)
|
|
114
|
+
return;
|
|
115
|
+
points.userData[SELF_OWNED_MATERIAL_KEY] = ownsMaterial;
|
|
116
|
+
return () => {
|
|
117
|
+
if (points.userData)
|
|
118
|
+
delete points.userData[SELF_OWNED_MATERIAL_KEY];
|
|
119
|
+
};
|
|
120
|
+
}, [ownsMaterial]);
|
|
92
121
|
useFrame((state, delta) => {
|
|
93
|
-
|
|
94
|
-
if (!mat || !pointsRef.current || !basePositions.current)
|
|
122
|
+
if (!pointsRef.current || !basePositions.current)
|
|
95
123
|
return;
|
|
124
|
+
const mat = materialRef.current;
|
|
96
125
|
if (meshSettings.visible) {
|
|
126
|
+
// Geometry animation is independent of who owns the material.
|
|
97
127
|
handleShapeAnimation(delta, speed, animationProgress, pointsRef, basePositions, targetPositions);
|
|
98
|
-
|
|
128
|
+
if (mat)
|
|
129
|
+
handleColorsAnimation(materialRef, delta, speed);
|
|
99
130
|
}
|
|
131
|
+
if (hasPositionEffects && displayPositions && displayPositions !== basePositions.current) {
|
|
132
|
+
if (!frameBaseRef.current || frameBaseRef.current.length !== displayPositions.length)
|
|
133
|
+
frameBaseRef.current = new Float32Array(displayPositions.length);
|
|
134
|
+
// Snapshot the shape-animated positions as this frame's baseline so
|
|
135
|
+
// the effects do not compound over time.
|
|
136
|
+
frameBaseRef.current.set(displayPositions);
|
|
137
|
+
const moved = applyVertexEffects(frameBaseRef.current, displayPositions, positionEffects, {
|
|
138
|
+
time: state.clock.getElapsedTime(),
|
|
139
|
+
pointerX: state.pointer.x * LOCAL_POINTER_SCALE,
|
|
140
|
+
pointerY: state.pointer.y * LOCAL_POINTER_SCALE,
|
|
141
|
+
pointerRadius: pointerRadius * LOCAL_POINTER_SCALE,
|
|
142
|
+
});
|
|
143
|
+
if (moved) {
|
|
144
|
+
const attribute = pointsRef.current.geometry?.attributes?.position;
|
|
145
|
+
if (attribute)
|
|
146
|
+
attribute.needsUpdate = true;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (!mat)
|
|
150
|
+
return;
|
|
100
151
|
if (prevTexture.current)
|
|
101
152
|
mat.uniforms.uTexture.value = prevTexture.current;
|
|
102
153
|
if (currentTexture.current)
|
|
103
154
|
mat.uniforms.uTargetTexture.value = currentTexture.current;
|
|
104
155
|
mat.uniforms.uHasTexture.value = !!currentTexture.current;
|
|
105
156
|
handleTextureAnimation(materialRef, delta, speed);
|
|
106
|
-
update3driseShaderUniforms(mat.uniforms,
|
|
157
|
+
update3driseShaderUniforms(mat.uniforms, shellEffects, state.clock.getElapsedTime(), { x: state.pointer.x, y: state.pointer.y }, { pointerRadius });
|
|
107
158
|
});
|
|
108
159
|
if (!basePositions.current)
|
|
109
160
|
return null;
|
|
110
|
-
return (_jsxs("points", { name: name, ref: pointsRef, raycast: () => null, position: [0, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1], children: [_jsxs("bufferGeometry", { children: [_jsx("bufferAttribute", { attach: "attributes-position", count: basePositions.current.length / 3, array: basePositions.current, itemSize: 3, args: [basePositions.current, 3] }), uvs && (_jsx("bufferAttribute", { attach: "attributes-aUV", count: uvs.length / 2, array: uvs, itemSize: 2, args: [uvs, 2] }))] }), _jsx("primitive", { object: material, attach: "material" })] }));
|
|
161
|
+
return (_jsxs("points", { name: name, ref: pointsRef, raycast: () => null, position: [0, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1], children: [_jsxs("bufferGeometry", { children: [_jsx("bufferAttribute", { attach: "attributes-position", count: (displayPositions ?? basePositions.current).length / 3, array: displayPositions ?? basePositions.current, itemSize: 3, args: [displayPositions ?? basePositions.current, 3] }), uvs && (_jsx("bufferAttribute", { attach: "attributes-aUV", count: uvs.length / 2, array: uvs, itemSize: 2, args: [uvs, 2] }))] }), material && _jsx("primitive", { object: material, attach: "material" })] }));
|
|
111
162
|
};
|
|
112
163
|
export default ParticlesR3f;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PointCloud.d.ts","sourceRoot":"","sources":["../../src/components/PointCloud.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"PointCloud.d.ts","sourceRoot":"","sources":["../../src/components/PointCloud.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAO7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEhF,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,UAAU,eAAgB,SAAQ,gBAAgB;IAC9C,SAAS,EAAE,YAAY,CAAC;IACxB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,UAAU,CAAC,EAAE,gBAAgB,CAAC;CACjC;AAyBD,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA0HzC,CAAC;AACF,eAAe,UAAU,CAAC"}
|
|
@@ -4,7 +4,8 @@ import { useEffect, useMemo, useRef } from 'react';
|
|
|
4
4
|
import { useFrame } from '@react-three/fiber';
|
|
5
5
|
import { useParticlesColors } from '../hooks/useParticlesColors.js';
|
|
6
6
|
import { useParticlesTextures } from '../hooks/useParticlesTextures.js';
|
|
7
|
-
import { buildShaderEffectsMaterial, structureKey } from '@3driseai/3drise-core';
|
|
7
|
+
import { buildShaderEffectsMaterial, structureKey, SELF_OWNED_MATERIAL_KEY, applyVertexEffects, partitionShaderEffects, LOCAL_POINTER_SCALE } from '@3driseai/3drise-core';
|
|
8
|
+
import { ownsShaderEffectsMaterial } from '../utils/pointsMaterialOwnership.js';
|
|
8
9
|
import { update3driseShaderUniforms } from '../hooks/use3driseShader.js';
|
|
9
10
|
function normalizeEffects(raw) {
|
|
10
11
|
return Array.isArray(raw) ? raw : [];
|
|
@@ -77,27 +78,66 @@ const PointCloud = ({ positions, materialSettings, animations, onObjectReady, on
|
|
|
77
78
|
const activeEffects = useMemo(() => normalizeEffects(animations?.material?.shaderEffects), [animations?.material?.shaderEffects]);
|
|
78
79
|
const pointerRadius = animations?.material
|
|
79
80
|
?.shaderEffectsPointerRadius ?? 0.4;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
// Position effects displace the geometry from the CPU and leave `.material`
|
|
82
|
+
// alone, so they compose with any material. Only the rest still need the
|
|
83
|
+
// shader shell — and only the shell takes ownership of `.material`.
|
|
84
|
+
const { position: positionEffects, shell: shellEffects } = useMemo(() => partitionShaderEffects(activeEffects), [activeEffects]);
|
|
85
|
+
const hasPositionEffects = positionEffects.some(effect => effect.enabled);
|
|
86
|
+
const effectsKey = useMemo(() => structureKey(shellEffects), [shellEffects]);
|
|
87
|
+
const ownsMaterial = ownsShaderEffectsMaterial(materialSettings, shellEffects);
|
|
88
|
+
// A separate buffer to displace into, so `positions` stays the authored
|
|
89
|
+
// baseline and effects never accumulate frame over frame.
|
|
90
|
+
const displayPositions = useMemo(() => (hasPositionEffects && positions ? new Float32Array(positions) : positions), [positions, hasPositionEffects]);
|
|
91
|
+
const material = useMemo(() => ownsMaterial ? buildShaderEffectsMaterial({
|
|
92
|
+
effects: shellEffects,
|
|
83
93
|
initialColor: color,
|
|
84
94
|
initialOpacity: opacity,
|
|
85
95
|
initialPointSize: pointSize,
|
|
86
96
|
initialParticleUVScale: particleUVScale,
|
|
87
97
|
initialPointerEffectRadius: pointerRadius,
|
|
88
|
-
}),
|
|
98
|
+
}) : null,
|
|
89
99
|
// Rebuild when the structural set of effects changes; not on parameter tweaks.
|
|
90
100
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
91
|
-
[effectsKey]);
|
|
101
|
+
[effectsKey, ownsMaterial]);
|
|
92
102
|
useEffect(() => {
|
|
93
103
|
materialRef.current = material;
|
|
94
104
|
return () => {
|
|
95
|
-
material
|
|
105
|
+
material?.dispose();
|
|
96
106
|
};
|
|
97
107
|
}, [material]);
|
|
108
|
+
// Tell useMaterialApplication's traversal to leave this object alone while we
|
|
109
|
+
// own its material. Set imperatively rather than through a `userData` prop:
|
|
110
|
+
// R3F replaces the whole object on every render, which would wipe the
|
|
111
|
+
// applyTexture handle stashed above.
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
const points = pointsRef.current;
|
|
114
|
+
if (!points)
|
|
115
|
+
return;
|
|
116
|
+
points.userData[SELF_OWNED_MATERIAL_KEY] = ownsMaterial;
|
|
117
|
+
return () => {
|
|
118
|
+
if (points.userData)
|
|
119
|
+
delete points.userData[SELF_OWNED_MATERIAL_KEY];
|
|
120
|
+
};
|
|
121
|
+
}, [ownsMaterial]);
|
|
98
122
|
useFrame((state, delta) => {
|
|
123
|
+
const points = pointsRef.current;
|
|
124
|
+
if (!points)
|
|
125
|
+
return;
|
|
126
|
+
if (hasPositionEffects && displayPositions !== positions) {
|
|
127
|
+
const moved = applyVertexEffects(positions, displayPositions, positionEffects, {
|
|
128
|
+
time: state.clock.getElapsedTime(),
|
|
129
|
+
pointerX: state.pointer.x * LOCAL_POINTER_SCALE,
|
|
130
|
+
pointerY: state.pointer.y * LOCAL_POINTER_SCALE,
|
|
131
|
+
pointerRadius: pointerRadius * LOCAL_POINTER_SCALE,
|
|
132
|
+
});
|
|
133
|
+
if (moved) {
|
|
134
|
+
const attribute = points.geometry?.attributes?.position;
|
|
135
|
+
if (attribute)
|
|
136
|
+
attribute.needsUpdate = true;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
99
139
|
const mat = materialRef.current;
|
|
100
|
-
if (!mat
|
|
140
|
+
if (!mat)
|
|
101
141
|
return;
|
|
102
142
|
handleColorsAnimation(materialRef, delta, speed);
|
|
103
143
|
if (prevTexture.current)
|
|
@@ -106,10 +146,10 @@ const PointCloud = ({ positions, materialSettings, animations, onObjectReady, on
|
|
|
106
146
|
mat.uniforms.uTargetTexture.value = currentTexture.current;
|
|
107
147
|
mat.uniforms.uHasTexture.value = !!currentTexture.current;
|
|
108
148
|
handleTextureAnimation(materialRef, delta, speed);
|
|
109
|
-
update3driseShaderUniforms(mat.uniforms,
|
|
149
|
+
update3driseShaderUniforms(mat.uniforms, shellEffects, state.clock.getElapsedTime(), { x: state.pointer.x, y: state.pointer.y }, { pointerRadius });
|
|
110
150
|
});
|
|
111
151
|
if (!positions)
|
|
112
152
|
return null;
|
|
113
|
-
return (_jsxs("points", { ref: pointsRef, raycast: () => null, position: [0, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1], children: [_jsxs("bufferGeometry", { children: [_jsx("bufferAttribute", { attach: "attributes-position", count:
|
|
153
|
+
return (_jsxs("points", { ref: pointsRef, raycast: () => null, position: [0, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1], children: [_jsxs("bufferGeometry", { children: [_jsx("bufferAttribute", { attach: "attributes-position", count: displayPositions.length / 3, array: displayPositions, itemSize: 3, args: [displayPositions, 3] }), uvs && (_jsx("bufferAttribute", { attach: "attributes-aUV", count: uvs.length / 2, array: uvs, itemSize: 2, args: [uvs, 2] }))] }), material && _jsx("primitive", { object: material, attach: "material" })] }));
|
|
114
154
|
};
|
|
115
155
|
export default PointCloud;
|
package/dist/constants.d.ts
CHANGED
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,gBAAgB,gCAAgC,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,gBAAgB,gCAAgC,CAAC;AAC9D,eAAO,MAAM,qBAAqB,aAKhC,CAAC"}
|
package/dist/constants.js
CHANGED
|
@@ -4,3 +4,9 @@ const isLocalHostRuntime = typeof window !== 'undefined' &&
|
|
|
4
4
|
(window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1');
|
|
5
5
|
// export const dataCenterServer = isLocalHostRuntime ? LOCAL_DATA_CENTER_SERVER : PRODUCTION_DATA_CENTER_SERVER;
|
|
6
6
|
export const dataCenterServer = PRODUCTION_DATA_CENTER_SERVER;
|
|
7
|
+
export const SELF_MANAGED_MATERIAL = new Set([
|
|
8
|
+
'effect',
|
|
9
|
+
'space',
|
|
10
|
+
'grid',
|
|
11
|
+
// 'moon'
|
|
12
|
+
]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMaterialApplication.d.ts","sourceRoot":"","sources":["../../src/hooks/useMaterialApplication.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"useMaterialApplication.d.ts","sourceRoot":"","sources":["../../src/hooks/useMaterialApplication.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG/D,eAAO,MAAM,sBAAsB,GAAI,QAAQ,cAAc,EAAE,kBAAkB,gBAAgB,EAAE,4BAA4B,OAAO,EAAE,YAAY,MAAM,IAAI,KAAG,IAuIhK,CAAC"}
|
|
@@ -8,8 +8,6 @@
|
|
|
8
8
|
import { useEffect, useRef } from 'react';
|
|
9
9
|
import { createAndApplyMaterial, MATERIAL_INSTANCE_KEY, MaterialRegistryAPI, ObjectManager, resolveTextures, traverseSkippingEdgesAndEffects } from '@3driseai/3drise-core';
|
|
10
10
|
import { resolveObject3D } from "../utils/resolveObject3D.js";
|
|
11
|
-
// TEST: 0=raw defaults, 1=+DoubleSide, 2=+transparent, 3=+metalness/roughness
|
|
12
|
-
const TEST_MATERIAL_MODE = 1;
|
|
13
11
|
export const useMaterialApplication = (source, materialSettings, shouldApply3driseMaterial, onApplied) => {
|
|
14
12
|
// Track all material instances we've created so we can release them on change/unmount
|
|
15
13
|
// const { getTypeByName } = useObjectTypes();
|
|
@@ -29,7 +27,8 @@ export const useMaterialApplication = (source, materialSettings, shouldApply3dri
|
|
|
29
27
|
// attached refs, so this is the first point the object reliably exists.
|
|
30
28
|
const obj = resolveObject3D(source);
|
|
31
29
|
if (!obj || !materialSettings || materialSettings.materialType === 'advanced' ||
|
|
32
|
-
materialSettings.materialVariant === '3dRiseShader'
|
|
30
|
+
materialSettings.materialVariant === '3dRiseShader'
|
|
31
|
+
|| (shouldApply3driseMaterial === false))
|
|
33
32
|
return;
|
|
34
33
|
handleSettingsChange(obj, materialSettings);
|
|
35
34
|
return () => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MaterialRegistryAPI } from '@3driseai/3drise-core';
|
|
2
|
-
import type { CreatedObjectType,
|
|
2
|
+
import type { CreatedObjectType, MaterialSettings, ModeGroup, SelectOptions } from '@3driseai/3drise-core';
|
|
3
3
|
type RegistryMaterialType = Exclude<Parameters<typeof MaterialRegistryAPI.getVariants>[0], undefined>;
|
|
4
4
|
export interface UseMaterialOptionsReturn {
|
|
5
5
|
selectedType: RegistryMaterialType;
|
|
@@ -9,6 +9,6 @@ export interface UseMaterialOptionsReturn {
|
|
|
9
9
|
handleTypeChange: (type: RegistryMaterialType) => void;
|
|
10
10
|
handleVariantChange: (variant: string) => void;
|
|
11
11
|
}
|
|
12
|
-
export declare const useMaterialOptions: (initialSettings: MaterialSettings, onSettingsChange?: (newSettings: MaterialSettings) => void, objectType?: CreatedObjectType,
|
|
12
|
+
export declare const useMaterialOptions: (initialSettings: MaterialSettings, onSettingsChange?: (newSettings: MaterialSettings) => void, objectType?: CreatedObjectType, surface?: ModeGroup) => UseMaterialOptionsReturn;
|
|
13
13
|
export {};
|
|
14
14
|
//# sourceMappingURL=useMaterialOptions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMaterialOptions.d.ts","sourceRoot":"","sources":["../../src/hooks/useMaterialOptions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"useMaterialOptions.d.ts","sourceRoot":"","sources":["../../src/hooks/useMaterialOptions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAA2B,MAAM,uBAAuB,CAAC;AACrF,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3G,KAAK,oBAAoB,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,mBAAmB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AAEtG,MAAM,WAAW,wBAAwB;IACrC,YAAY,EAAE,oBAAoB,CAAC;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,aAAa,CAAC;IACnC,cAAc,EAAE,aAAa,CAAC;IAC9B,gBAAgB,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACvD,mBAAmB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD;AAED,eAAO,MAAM,kBAAkB,GAAI,iBAAiB,gBAAgB,EAAE,mBAAmB,CAAC,WAAW,EAAE,gBAAgB,KAAK,IAAI,EAAE,aAAY,iBAA0B,EAAE,UAAS,SAAkB,KAAG,wBA0FvM,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useState, useEffect } from 'react';
|
|
2
|
-
import { MaterialRegistryAPI } from '@3driseai/3drise-core';
|
|
2
|
+
import { MaterialRegistryAPI, materialTypeFitsSurface } from '@3driseai/3drise-core';
|
|
3
3
|
import { FrontSide } from 'three';
|
|
4
|
-
export const useMaterialOptions = (initialSettings, onSettingsChange, objectType = 'mesh',
|
|
4
|
+
export const useMaterialOptions = (initialSettings, onSettingsChange, objectType = 'mesh', surface = 'mesh') => {
|
|
5
5
|
// Ensure we always have a valid material type
|
|
6
6
|
const validType = (initialSettings.materialType || 'basic');
|
|
7
7
|
const [selectedType, setSelectedType] = useState(validType);
|
|
@@ -18,35 +18,17 @@ export const useMaterialOptions = (initialSettings, onSettingsChange, objectType
|
|
|
18
18
|
setSelectedVariant(initialSettings.materialVariant || variants[0] || '');
|
|
19
19
|
}, [initialSettings.materialType, initialSettings.materialVariant]);
|
|
20
20
|
const allmaterialTypes = MaterialRegistryAPI.getTypes();
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const materialTypeOptions = () =>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
if (is3dRiseShaderMaterial) {
|
|
34
|
-
return dRiseShaderMaterialTypes.map((type) => ({
|
|
35
|
-
value: type,
|
|
36
|
-
label: type.charAt(0).toUpperCase() + type.slice(1)
|
|
37
|
-
}));
|
|
38
|
-
}
|
|
39
|
-
if (isLineMaterial) {
|
|
40
|
-
return lineMaterialTypes.map((type) => ({
|
|
41
|
-
value: type,
|
|
42
|
-
label: type.charAt(0).toUpperCase() + type.slice(1)
|
|
43
|
-
}));
|
|
44
|
-
}
|
|
45
|
-
return meshMaterialTypes.map((type) => ({
|
|
46
|
-
value: type,
|
|
47
|
-
label: type.charAt(0).toUpperCase() + type.slice(1)
|
|
48
|
-
}));
|
|
49
|
-
};
|
|
21
|
+
// Offer only the families that can actually draw on this object's surface.
|
|
22
|
+
// A <points> takes the `particles` family and nothing else; every other
|
|
23
|
+
// surface takes everything except it. Note this keys off the surface, never
|
|
24
|
+
// off the currently selected material — the previous version did the latter,
|
|
25
|
+
// which meant an object could never get back to a family once it left it.
|
|
26
|
+
const materialTypeOptions = () => allmaterialTypes
|
|
27
|
+
.filter((type) => materialTypeFitsSurface(type, surface))
|
|
28
|
+
.map((type) => ({
|
|
29
|
+
value: type,
|
|
30
|
+
label: type.charAt(0).toUpperCase() + type.slice(1)
|
|
31
|
+
}));
|
|
50
32
|
// is3dRiseShaderMaterial ?
|
|
51
33
|
// dRiseShaderMaterialTypes.map((type: string) => ({
|
|
52
34
|
// value: type,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useObjectEdges.d.ts","sourceRoot":"","sources":["../../src/hooks/useObjectEdges.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"useObjectEdges.d.ts","sourceRoot":"","sources":["../../src/hooks/useObjectEdges.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAmH/D,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,CAAC,EAAE,cAAc,GAAG,IAAI,CA6ChH"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import { BoxGeometry,
|
|
2
|
+
import { BoxGeometry, CylinderGeometry, EdgesGeometry, Group, LineSegments, Mesh, MeshBasicMaterial, Points, PointsMaterial, Quaternion, Vector3, } from 'three';
|
|
3
3
|
import { useFrame } from '@react-three/fiber';
|
|
4
|
-
import { collectMeshes, computeThreshold, buildSubdividedEdgeGeometry, EDGES_GROUP_KEY, animateUniforms, cacheChildrenWithMaterials, findById } from '@3driseai/3drise-core';
|
|
4
|
+
import { collectMeshes, computeThreshold, buildSubdividedEdgeGeometry, buildSegmentQuadGeometry, EDGES_GROUP_KEY, animateUniforms, cacheChildrenWithMaterials, findById } from '@3driseai/3drise-core';
|
|
5
5
|
import { useMaterialApplication } from './useMaterialApplication.js';
|
|
6
6
|
import { resolveObject3D } from '../utils/resolveObject3D.js';
|
|
7
7
|
;
|
|
@@ -9,52 +9,6 @@ import { resolveObject3D } from '../utils/resolveObject3D.js';
|
|
|
9
9
|
const DEFAULT_TUBE_RADIUS = 0.01;
|
|
10
10
|
const DEFAULT_CUBE_SIZE = 0.02;
|
|
11
11
|
// ─── Builders ────────────────────────────────────────────────────────────────
|
|
12
|
-
function edgesGeoToQuadMesh(edgesGeo, thickness = 0.008) {
|
|
13
|
-
const src = edgesGeo.attributes.position;
|
|
14
|
-
const segCount = src.count / 2; // each segment = 2 vertices
|
|
15
|
-
const positions = [];
|
|
16
|
-
const uvs = [];
|
|
17
|
-
const indices = [];
|
|
18
|
-
const start = new Vector3();
|
|
19
|
-
const end = new Vector3();
|
|
20
|
-
const dir = new Vector3();
|
|
21
|
-
const up = new Vector3(0, 1, 0);
|
|
22
|
-
const right = new Vector3();
|
|
23
|
-
for (let i = 0; i < segCount; i++) {
|
|
24
|
-
start.fromBufferAttribute(src, i * 2);
|
|
25
|
-
end.fromBufferAttribute(src, i * 2 + 1);
|
|
26
|
-
dir.subVectors(end, start).normalize();
|
|
27
|
-
// Perpendicular axis — fallback to X if segment is vertical
|
|
28
|
-
right.crossVectors(dir, up).normalize();
|
|
29
|
-
if (right.lengthSq() < 0.0001) {
|
|
30
|
-
right.set(1, 0, 0);
|
|
31
|
-
}
|
|
32
|
-
const rx = right.x * thickness;
|
|
33
|
-
const ry = right.y * thickness;
|
|
34
|
-
const rz = right.z * thickness;
|
|
35
|
-
const base = i * 4;
|
|
36
|
-
// v0 start-bottom uv(0,0)
|
|
37
|
-
positions.push(start.x - rx, start.y - ry, start.z - rz);
|
|
38
|
-
uvs.push(0, 0);
|
|
39
|
-
// v1 end-bottom uv(1,0)
|
|
40
|
-
positions.push(end.x - rx, end.y - ry, end.z - rz);
|
|
41
|
-
uvs.push(1, 0);
|
|
42
|
-
// v2 start-top uv(0,1)
|
|
43
|
-
positions.push(start.x + rx, start.y + ry, start.z + rz);
|
|
44
|
-
uvs.push(0, 1);
|
|
45
|
-
// v3 end-top uv(1,1)
|
|
46
|
-
positions.push(end.x + rx, end.y + ry, end.z + rz);
|
|
47
|
-
uvs.push(1, 1);
|
|
48
|
-
indices.push(base, base + 1, base + 2);
|
|
49
|
-
indices.push(base + 1, base + 3, base + 2);
|
|
50
|
-
}
|
|
51
|
-
const geo = new BufferGeometry();
|
|
52
|
-
geo.setAttribute("position", new Float32BufferAttribute(positions, 3));
|
|
53
|
-
geo.setAttribute("uv", new Float32BufferAttribute(uvs, 2));
|
|
54
|
-
geo.setIndex(indices);
|
|
55
|
-
geo.computeVertexNormals();
|
|
56
|
-
return new Mesh(geo);
|
|
57
|
-
}
|
|
58
12
|
function buildLineGroup(object, localParent) {
|
|
59
13
|
const g = new Group();
|
|
60
14
|
for (const { mesh, matrixRelativeToRoot } of collectMeshes(object, localParent)) {
|
|
@@ -64,7 +18,7 @@ function buildLineGroup(object, localParent) {
|
|
|
64
18
|
const quaternion = new Quaternion();
|
|
65
19
|
const scale = new Vector3();
|
|
66
20
|
matrixRelativeToRoot.decompose(position, quaternion, scale);
|
|
67
|
-
const quadMesh =
|
|
21
|
+
const quadMesh = new Mesh(buildSegmentQuadGeometry(edgesGeo.attributes.position));
|
|
68
22
|
quadMesh.position.copy(position);
|
|
69
23
|
quadMesh.quaternion.copy(quaternion);
|
|
70
24
|
quadMesh.scale.copy(scale);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { MaterialSettings } from '@3driseai/3drise-core';
|
|
2
|
+
import type { ShaderEffect } from '@3driseai/3drise-core';
|
|
3
|
+
/** The one particles variant that is built dynamically rather than by the registry. */
|
|
4
|
+
export declare const SHADER_EFFECTS_VARIANT = "3dRiseShader";
|
|
5
|
+
/** True when at least one shader effect is switched on. */
|
|
6
|
+
export declare function hasActiveShaderEffects(effects?: ShaderEffect[] | null): boolean;
|
|
7
|
+
export declare function ownsShaderEffectsMaterial(materialSettings?: MaterialSettings | null, effects?: ShaderEffect[] | null): boolean;
|
|
8
|
+
export default ownsShaderEffectsMaterial;
|
|
9
|
+
//# sourceMappingURL=pointsMaterialOwnership.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointsMaterialOwnership.d.ts","sourceRoot":"","sources":["../../src/utils/pointsMaterialOwnership.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,uFAAuF;AACvF,eAAO,MAAM,sBAAsB,iBAAiB,CAAC;AAErD,2DAA2D;AAC3D,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,YAAY,EAAE,GAAG,IAAI,GAAG,OAAO,CAE/E;AAED,wBAAgB,yBAAyB,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,YAAY,EAAE,GAAG,IAAI,GAAG,OAAO,CAM9H;AAED,eAAe,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** The one particles variant that is built dynamically rather than by the registry. */
|
|
2
|
+
export const SHADER_EFFECTS_VARIANT = '3dRiseShader';
|
|
3
|
+
/** True when at least one shader effect is switched on. */
|
|
4
|
+
export function hasActiveShaderEffects(effects) {
|
|
5
|
+
return Array.isArray(effects) && effects.some((effect) => effect?.enabled);
|
|
6
|
+
}
|
|
7
|
+
export function ownsShaderEffectsMaterial(materialSettings, effects) {
|
|
8
|
+
// Effects only exist inside the shell, so their presence decides ownership.
|
|
9
|
+
if (hasActiveShaderEffects(effects))
|
|
10
|
+
return true;
|
|
11
|
+
const variant = materialSettings?.materialVariant;
|
|
12
|
+
return !variant || variant === SHADER_EFFECTS_VARIANT;
|
|
13
|
+
}
|
|
14
|
+
export default ownsShaderEffectsMaterial;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@3driseai/3drise-viewer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -39,6 +39,6 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@3driseai/3drise-common": "^1.0.1",
|
|
42
|
-
"@3driseai/3drise-core": "^1.0.
|
|
42
|
+
"@3driseai/3drise-core": "^1.0.4"
|
|
43
43
|
}
|
|
44
44
|
}
|