@3driseai/3drise-core 1.0.3 → 1.0.4
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/presets/coronaPresets.d.ts.map +1 -1
- package/dist/presets/coronaPresets.js +14 -7
- package/dist/shaders/effects/index.d.ts +2 -0
- package/dist/shaders/effects/index.d.ts.map +1 -1
- package/dist/shaders/effects/index.js +2 -0
- package/dist/shaders/effects/noiseLib.d.ts +12 -0
- package/dist/shaders/effects/noiseLib.d.ts.map +1 -0
- package/dist/shaders/effects/noiseLib.js +215 -0
- package/dist/shaders/effects/vertexEffectsCpu.d.ts +52 -0
- package/dist/shaders/effects/vertexEffectsCpu.d.ts.map +1 -0
- package/dist/shaders/effects/vertexEffectsCpu.js +240 -0
- package/dist/utils/edgeUtils.d.ts +2 -1
- package/dist/utils/edgeUtils.d.ts.map +1 -1
- package/dist/utils/edgeUtils.js +70 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/materialApplicationUtils.d.ts +11 -2
- package/dist/utils/materialApplicationUtils.d.ts.map +1 -1
- package/dist/utils/materialApplicationUtils.js +12 -3
- package/dist/utils/surfaceUtils.d.ts +21 -0
- package/dist/utils/surfaceUtils.d.ts.map +1 -0
- package/dist/utils/surfaceUtils.js +50 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coronaPresets.d.ts","sourceRoot":"","sources":["../../src/presets/coronaPresets.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACjC;AAED,eAAO,MAAM,aAAa,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"coronaPresets.d.ts","sourceRoot":"","sources":["../../src/presets/coronaPresets.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACjC;AAED,eAAO,MAAM,aAAa,EAAE,YAAY,EAyJvC,CAAC"}
|
|
@@ -34,7 +34,8 @@ export const coronaPresets = [
|
|
|
34
34
|
u_pulseAmount: 0.45,
|
|
35
35
|
u_shellScale: 1.30,
|
|
36
36
|
u_innerColor: [1.0, 0.18, 0.02],
|
|
37
|
-
u_outerColor: [1.0, 0.85, 0.40]
|
|
37
|
+
u_outerColor: [1.0, 0.85, 0.40],
|
|
38
|
+
side: BackSide
|
|
38
39
|
}
|
|
39
40
|
},
|
|
40
41
|
{
|
|
@@ -52,7 +53,8 @@ export const coronaPresets = [
|
|
|
52
53
|
u_pulseAmount: 0.15,
|
|
53
54
|
u_shellScale: 1.35,
|
|
54
55
|
u_innerColor: [0.95, 0.85, 0.65],
|
|
55
|
-
u_outerColor: [1.0, 0.95, 0.80]
|
|
56
|
+
u_outerColor: [1.0, 0.95, 0.80],
|
|
57
|
+
side: BackSide
|
|
56
58
|
}
|
|
57
59
|
},
|
|
58
60
|
{
|
|
@@ -70,7 +72,8 @@ export const coronaPresets = [
|
|
|
70
72
|
u_pulseAmount: 0.2,
|
|
71
73
|
u_shellScale: 1.28,
|
|
72
74
|
u_innerColor: [0.10, 0.30, 0.85],
|
|
73
|
-
u_outerColor: [0.75, 0.92, 1.0]
|
|
75
|
+
u_outerColor: [0.75, 0.92, 1.0],
|
|
76
|
+
side: BackSide
|
|
74
77
|
}
|
|
75
78
|
},
|
|
76
79
|
{
|
|
@@ -88,7 +91,8 @@ export const coronaPresets = [
|
|
|
88
91
|
u_pulseAmount: 0.40,
|
|
89
92
|
u_shellScale: 1.22,
|
|
90
93
|
u_innerColor: [0.55, 0.02, 0.0],
|
|
91
|
-
u_outerColor: [1.0, 0.22, 0.08]
|
|
94
|
+
u_outerColor: [1.0, 0.22, 0.08],
|
|
95
|
+
side: BackSide
|
|
92
96
|
}
|
|
93
97
|
},
|
|
94
98
|
{
|
|
@@ -106,7 +110,8 @@ export const coronaPresets = [
|
|
|
106
110
|
u_pulseAmount: 0.50,
|
|
107
111
|
u_shellScale: 1.30,
|
|
108
112
|
u_innerColor: [0.40, 0.08, 0.80],
|
|
109
|
-
u_outerColor: [1.0, 0.35, 0.95]
|
|
113
|
+
u_outerColor: [1.0, 0.35, 0.95],
|
|
114
|
+
side: BackSide
|
|
110
115
|
}
|
|
111
116
|
},
|
|
112
117
|
{
|
|
@@ -124,7 +129,8 @@ export const coronaPresets = [
|
|
|
124
129
|
u_pulseAmount: 0.30,
|
|
125
130
|
u_shellScale: 1.35,
|
|
126
131
|
u_innerColor: [0.10, 0.55, 0.40],
|
|
127
|
-
u_outerColor: [0.65, 1.0, 0.75]
|
|
132
|
+
u_outerColor: [0.65, 1.0, 0.75],
|
|
133
|
+
side: BackSide
|
|
128
134
|
}
|
|
129
135
|
},
|
|
130
136
|
{
|
|
@@ -142,7 +148,8 @@ export const coronaPresets = [
|
|
|
142
148
|
u_pulseAmount: 0.15,
|
|
143
149
|
u_shellScale: 1.25,
|
|
144
150
|
u_innerColor: [0.20, 0.45, 0.85],
|
|
145
|
-
u_outerColor: [0.92, 0.97, 1.0]
|
|
151
|
+
u_outerColor: [0.92, 0.97, 1.0],
|
|
152
|
+
side: BackSide
|
|
146
153
|
}
|
|
147
154
|
}
|
|
148
155
|
];
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export * from './presets';
|
|
2
2
|
export * from './types';
|
|
3
|
+
export * from './noiseLib';
|
|
4
|
+
export * from './vertexEffectsCpu';
|
|
3
5
|
export * from './EffectsFragmentFunctions.glsl';
|
|
4
6
|
export * from './EffectsVertexFunctions.glsl';
|
|
5
7
|
export * from './buildShaderEffectsMaterial';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shaders/effects/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shaders/effects/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,YAAY,CAAC"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export * from './presets.js';
|
|
2
2
|
export * from './types.js';
|
|
3
|
+
export * from './noiseLib.js';
|
|
4
|
+
export * from './vertexEffectsCpu.js';
|
|
3
5
|
export * from './EffectsFragmentFunctions.glsl.js';
|
|
4
6
|
export * from './EffectsVertexFunctions.glsl.js';
|
|
5
7
|
export * from './buildShaderEffectsMaterial.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function whiteNoise2D(x: number, y: number): number;
|
|
2
|
+
export declare function valueNoise2D(x: number, y: number): number;
|
|
3
|
+
export declare function perlinNoise2D(px: number, py: number): number;
|
|
4
|
+
export declare function simplexNoise2D(vx: number, vy: number): number;
|
|
5
|
+
export declare function worleyNoise2D(px: number, py: number): number;
|
|
6
|
+
export declare function fractalNoise2D(px: number, py: number): number;
|
|
7
|
+
export declare function turbulenceNoise2D(px: number, py: number): number;
|
|
8
|
+
export declare function ridgedNoise2D(px: number, py: number): number;
|
|
9
|
+
export declare function domainWarpedNoise2D(px: number, py: number): number;
|
|
10
|
+
/** Mirrors the GLSL `sampleNoise(float type, vec2 p)` dispatch, ranges included. */
|
|
11
|
+
export declare function sampleNoise(type: number, px: number, py: number): number;
|
|
12
|
+
//# sourceMappingURL=noiseLib.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noiseLib.d.ts","sourceRoot":"","sources":["../../../src/shaders/effects/noiseLib.ts"],"names":[],"mappings":"AAmCA,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAUzD;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CA6C5D;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAyC7D;AAID,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAiB5D;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAO7D;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAOhE;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAQ5D;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAIlE;AAED,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAUxE"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// noiseLib.ts — CPU port of noiseLib.glsl
|
|
3
|
+
// =============================================================================
|
|
4
|
+
//
|
|
5
|
+
// A faithful scalar transcription of the GLSL noise library, so a position
|
|
6
|
+
// effect evaluated on the CPU produces the same shape as the shader did. Keep
|
|
7
|
+
// the two in step: if a function changes in `noiseLib.glsl.ts`, change it here.
|
|
8
|
+
//
|
|
9
|
+
// Type dispatch matches `sampleNoise` exactly:
|
|
10
|
+
// 0=perlin 1=simplex 2=worley 3=value 4=white
|
|
11
|
+
// 5=fractal 6=ridged 7=turbulence 8=domainWarped
|
|
12
|
+
//
|
|
13
|
+
const fract = (x) => x - Math.floor(x);
|
|
14
|
+
/** GLSL mod(), which differs from JS % for negative operands. */
|
|
15
|
+
const glslMod = (x, y) => x - y * Math.floor(x / y);
|
|
16
|
+
const mix = (a, b, t) => a + (b - a) * t;
|
|
17
|
+
const mod289 = (x) => x - Math.floor(x * (1.0 / 289.0)) * 289.0;
|
|
18
|
+
const permute = (x) => mod289(((x * 34.0) + 1.0) * x);
|
|
19
|
+
const hash21 = (x, y) => fract(Math.sin(x * 127.1 + y * 311.7) * 43758.5453123);
|
|
20
|
+
/** nl_hash22 — returns a 2-vector in roughly [-1, 1]. */
|
|
21
|
+
function hash22(x, y, out) {
|
|
22
|
+
const dx = x * 127.1 + y * 311.7;
|
|
23
|
+
const dy = x * 269.5 + y * 183.3;
|
|
24
|
+
out[0] = -1.0 + 2.0 * fract(Math.sin(dx) * 43758.5453123);
|
|
25
|
+
out[1] = -1.0 + 2.0 * fract(Math.sin(dy) * 43758.5453123);
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
const fade = (t) => t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
|
|
29
|
+
export function whiteNoise2D(x, y) {
|
|
30
|
+
return hash21(x, y);
|
|
31
|
+
}
|
|
32
|
+
export function valueNoise2D(x, y) {
|
|
33
|
+
const ix = Math.floor(x), iy = Math.floor(y);
|
|
34
|
+
const fx = fract(x), fy = fract(y);
|
|
35
|
+
const a = hash21(ix, iy);
|
|
36
|
+
const b = hash21(ix + 1.0, iy);
|
|
37
|
+
const c = hash21(ix, iy + 1.0);
|
|
38
|
+
const d = hash21(ix + 1.0, iy + 1.0);
|
|
39
|
+
const ux = fx * fx * (3.0 - 2.0 * fx);
|
|
40
|
+
const uy = fy * fy * (3.0 - 2.0 * fy);
|
|
41
|
+
return mix(a, b, ux) + (c - a) * uy * (1.0 - ux) + (d - b) * ux * uy;
|
|
42
|
+
}
|
|
43
|
+
export function perlinNoise2D(px, py) {
|
|
44
|
+
// Pi = floor(P.xyxy) + (0,0,1,1); Pf = fract(P.xyxy) - (0,0,1,1)
|
|
45
|
+
let pi0 = Math.floor(px), pi1 = Math.floor(py);
|
|
46
|
+
let pi2 = pi0 + 1.0, pi3 = pi1 + 1.0;
|
|
47
|
+
const pf0 = fract(px), pf1 = fract(py);
|
|
48
|
+
const pf2 = pf0 - 1.0, pf3 = pf1 - 1.0;
|
|
49
|
+
pi0 = glslMod(pi0, 289.0);
|
|
50
|
+
pi1 = glslMod(pi1, 289.0);
|
|
51
|
+
pi2 = glslMod(pi2, 289.0);
|
|
52
|
+
pi3 = glslMod(pi3, 289.0);
|
|
53
|
+
// ix = Pi.xzxz, iy = Pi.yyww, fx = Pf.xzxz, fy = Pf.yyww
|
|
54
|
+
const ix = [pi0, pi2, pi0, pi2];
|
|
55
|
+
const iy = [pi1, pi1, pi3, pi3];
|
|
56
|
+
const fx = [pf0, pf2, pf0, pf2];
|
|
57
|
+
const fy = [pf1, pf1, pf3, pf3];
|
|
58
|
+
const gxv = [0, 0, 0, 0];
|
|
59
|
+
const gyv = [0, 0, 0, 0];
|
|
60
|
+
for (let k = 0; k < 4; k++) {
|
|
61
|
+
const i = permute(permute(ix[k]) + iy[k]);
|
|
62
|
+
let gx = 2.0 * fract(i * 0.0243902439) - 1.0;
|
|
63
|
+
const gy = Math.abs(gx) - 0.5;
|
|
64
|
+
gx = gx - Math.floor(gx + 0.5);
|
|
65
|
+
gxv[k] = gx;
|
|
66
|
+
gyv[k] = gy;
|
|
67
|
+
}
|
|
68
|
+
// g00=(gx.x,gy.x) g10=(gx.y,gy.y) g01=(gx.z,gy.z) g11=(gx.w,gy.w)
|
|
69
|
+
let g00x = gxv[0], g00y = gyv[0];
|
|
70
|
+
let g10x = gxv[1], g10y = gyv[1];
|
|
71
|
+
let g01x = gxv[2], g01y = gyv[2];
|
|
72
|
+
let g11x = gxv[3], g11y = gyv[3];
|
|
73
|
+
const N = 1.79284291400159, M = 0.85373472095314;
|
|
74
|
+
const n00norm = N - M * (g00x * g00x + g00y * g00y);
|
|
75
|
+
const n01norm = N - M * (g01x * g01x + g01y * g01y);
|
|
76
|
+
const n10norm = N - M * (g10x * g10x + g10y * g10y);
|
|
77
|
+
const n11norm = N - M * (g11x * g11x + g11y * g11y);
|
|
78
|
+
g00x *= n00norm;
|
|
79
|
+
g00y *= n00norm;
|
|
80
|
+
g01x *= n01norm;
|
|
81
|
+
g01y *= n01norm;
|
|
82
|
+
g10x *= n10norm;
|
|
83
|
+
g10y *= n10norm;
|
|
84
|
+
g11x *= n11norm;
|
|
85
|
+
g11y *= n11norm;
|
|
86
|
+
const n00 = g00x * fx[0] + g00y * fy[0];
|
|
87
|
+
const n10 = g10x * fx[1] + g10y * fy[1];
|
|
88
|
+
const n01 = g01x * fx[2] + g01y * fy[2];
|
|
89
|
+
const n11 = g11x * fx[3] + g11y * fy[3];
|
|
90
|
+
const fadeX = fade(pf0), fadeY = fade(pf1);
|
|
91
|
+
const nx0 = mix(n00, n10, fadeX);
|
|
92
|
+
const nx1 = mix(n01, n11, fadeX);
|
|
93
|
+
return 2.3 * mix(nx0, nx1, fadeY);
|
|
94
|
+
}
|
|
95
|
+
export function simplexNoise2D(vx, vy) {
|
|
96
|
+
const C0 = 0.211324865405187, C1 = 0.366025403784439;
|
|
97
|
+
const C2 = -0.577350269189626, C3 = 0.024390243902439;
|
|
98
|
+
const dotVC = vx * C1 + vy * C1;
|
|
99
|
+
let ix = Math.floor(vx + dotVC);
|
|
100
|
+
let iy = Math.floor(vy + dotVC);
|
|
101
|
+
const dotIC = ix * C0 + iy * C0;
|
|
102
|
+
const x0x = vx - ix + dotIC;
|
|
103
|
+
const x0y = vy - iy + dotIC;
|
|
104
|
+
const i1x = x0x > x0y ? 1.0 : 0.0;
|
|
105
|
+
const i1y = x0x > x0y ? 0.0 : 1.0;
|
|
106
|
+
// x12 = x0.xyxy + C.xxzz; x12.xy -= i1
|
|
107
|
+
const x12x = x0x + C0 - i1x;
|
|
108
|
+
const x12y = x0y + C0 - i1y;
|
|
109
|
+
const x12z = x0x + C2;
|
|
110
|
+
const x12w = x0y + C2;
|
|
111
|
+
ix = mod289(ix);
|
|
112
|
+
iy = mod289(iy);
|
|
113
|
+
const p0 = permute(permute(iy + 0.0) + ix + 0.0);
|
|
114
|
+
const p1 = permute(permute(iy + i1y) + ix + i1x);
|
|
115
|
+
const p2 = permute(permute(iy + 1.0) + ix + 1.0);
|
|
116
|
+
let m0 = Math.max(0.5 - (x0x * x0x + x0y * x0y), 0.0);
|
|
117
|
+
let m1 = Math.max(0.5 - (x12x * x12x + x12y * x12y), 0.0);
|
|
118
|
+
let m2 = Math.max(0.5 - (x12z * x12z + x12w * x12w), 0.0);
|
|
119
|
+
m0 = m0 * m0;
|
|
120
|
+
m0 = m0 * m0;
|
|
121
|
+
m1 = m1 * m1;
|
|
122
|
+
m1 = m1 * m1;
|
|
123
|
+
m2 = m2 * m2;
|
|
124
|
+
m2 = m2 * m2;
|
|
125
|
+
const xa = 2.0 * fract(p0 * C3) - 1.0;
|
|
126
|
+
const xb = 2.0 * fract(p1 * C3) - 1.0;
|
|
127
|
+
const xc = 2.0 * fract(p2 * C3) - 1.0;
|
|
128
|
+
const ha = Math.abs(xa) - 0.5, hb = Math.abs(xb) - 0.5, hc = Math.abs(xc) - 0.5;
|
|
129
|
+
const a0a = xa - Math.floor(xa + 0.5);
|
|
130
|
+
const a0b = xb - Math.floor(xb + 0.5);
|
|
131
|
+
const a0c = xc - Math.floor(xc + 0.5);
|
|
132
|
+
const N = 1.79284291400159, M = 0.85373472095314;
|
|
133
|
+
m0 *= N - M * (a0a * a0a + ha * ha);
|
|
134
|
+
m1 *= N - M * (a0b * a0b + hb * hb);
|
|
135
|
+
m2 *= N - M * (a0c * a0c + hc * hc);
|
|
136
|
+
const gx = a0a * x0x + ha * x0y;
|
|
137
|
+
const gy = a0b * x12x + hb * x12y;
|
|
138
|
+
const gz = a0c * x12z + hc * x12w;
|
|
139
|
+
return 130.0 * (m0 * gx + m1 * gy + m2 * gz);
|
|
140
|
+
}
|
|
141
|
+
const worleyScratch = [0, 0];
|
|
142
|
+
export function worleyNoise2D(px, py) {
|
|
143
|
+
const ix = Math.floor(px), iy = Math.floor(py);
|
|
144
|
+
const fx = fract(px), fy = fract(py);
|
|
145
|
+
let minDist = 1.5;
|
|
146
|
+
for (let y = -1; y <= 1; y++) {
|
|
147
|
+
for (let x = -1; x <= 1; x++) {
|
|
148
|
+
const h = hash22(ix + x, iy + y, worleyScratch);
|
|
149
|
+
const pointX = 0.5 + 0.5 * h[0];
|
|
150
|
+
const pointY = 0.5 + 0.5 * h[1];
|
|
151
|
+
const dx = x + pointX - fx;
|
|
152
|
+
const dy = y + pointY - fy;
|
|
153
|
+
const d = Math.sqrt(dx * dx + dy * dy);
|
|
154
|
+
if (d < minDist)
|
|
155
|
+
minDist = d;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return minDist;
|
|
159
|
+
}
|
|
160
|
+
export function fractalNoise2D(px, py) {
|
|
161
|
+
let v = 0.0, amp = 0.5, qx = px, qy = py;
|
|
162
|
+
for (let i = 0; i < 4; i++) {
|
|
163
|
+
v += amp * perlinNoise2D(qx, qy);
|
|
164
|
+
qx *= 2.0;
|
|
165
|
+
qy *= 2.0;
|
|
166
|
+
amp *= 0.5;
|
|
167
|
+
}
|
|
168
|
+
return v;
|
|
169
|
+
}
|
|
170
|
+
export function turbulenceNoise2D(px, py) {
|
|
171
|
+
let v = 0.0, amp = 0.5, qx = px, qy = py;
|
|
172
|
+
for (let i = 0; i < 4; i++) {
|
|
173
|
+
v += amp * Math.abs(perlinNoise2D(qx, qy));
|
|
174
|
+
qx *= 2.0;
|
|
175
|
+
qy *= 2.0;
|
|
176
|
+
amp *= 0.5;
|
|
177
|
+
}
|
|
178
|
+
return v;
|
|
179
|
+
}
|
|
180
|
+
export function ridgedNoise2D(px, py) {
|
|
181
|
+
let v = 0.0, amp = 0.5, qx = px, qy = py;
|
|
182
|
+
for (let i = 0; i < 4; i++) {
|
|
183
|
+
const n = 1.0 - Math.abs(perlinNoise2D(qx, qy));
|
|
184
|
+
v += amp * n * n;
|
|
185
|
+
qx *= 2.0;
|
|
186
|
+
qy *= 2.0;
|
|
187
|
+
amp *= 0.5;
|
|
188
|
+
}
|
|
189
|
+
return v;
|
|
190
|
+
}
|
|
191
|
+
export function domainWarpedNoise2D(px, py) {
|
|
192
|
+
const wx = perlinNoise2D(px, py);
|
|
193
|
+
const wy = perlinNoise2D(px + 5.2, py + 1.3);
|
|
194
|
+
return perlinNoise2D(px + wx * 0.5, py + wy * 0.5);
|
|
195
|
+
}
|
|
196
|
+
/** Mirrors the GLSL `sampleNoise(float type, vec2 p)` dispatch, ranges included. */
|
|
197
|
+
export function sampleNoise(type, px, py) {
|
|
198
|
+
if (type < 0.5)
|
|
199
|
+
return perlinNoise2D(px, py);
|
|
200
|
+
if (type < 1.5)
|
|
201
|
+
return simplexNoise2D(px, py);
|
|
202
|
+
if (type < 2.5)
|
|
203
|
+
return worleyNoise2D(px, py) * 2.0 - 1.0;
|
|
204
|
+
if (type < 3.5)
|
|
205
|
+
return valueNoise2D(px, py) * 2.0 - 1.0;
|
|
206
|
+
if (type < 4.5)
|
|
207
|
+
return whiteNoise2D(px, py) * 2.0 - 1.0;
|
|
208
|
+
if (type < 5.5)
|
|
209
|
+
return fractalNoise2D(px, py);
|
|
210
|
+
if (type < 6.5)
|
|
211
|
+
return ridgedNoise2D(px, py);
|
|
212
|
+
if (type < 7.5)
|
|
213
|
+
return turbulenceNoise2D(px, py);
|
|
214
|
+
return domainWarpedNoise2D(px, py);
|
|
215
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ShaderEffect } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* The shader approximated a local-space pointer as `u_pointer * 5.0` — a legacy
|
|
4
|
+
* constant, but the one the effects were tuned against. The CPU path reuses it
|
|
5
|
+
* so pointer-scoped effects keep the reach they had.
|
|
6
|
+
*/
|
|
7
|
+
export declare const LOCAL_POINTER_SCALE = 5;
|
|
8
|
+
export interface VertexEffectContext {
|
|
9
|
+
/** Seconds, matching the shader's `u_time`. */
|
|
10
|
+
time: number;
|
|
11
|
+
/**
|
|
12
|
+
* Pointer position in the same space as the positions being displaced.
|
|
13
|
+
* The shader computed pointer falloff in screen NDC per vertex; doing that
|
|
14
|
+
* on the CPU would mean projecting every point every frame, so this uses
|
|
15
|
+
* object-local distance instead. Pointer-scoped effects therefore have a
|
|
16
|
+
* slightly different falloff shape than they did in the shader.
|
|
17
|
+
*/
|
|
18
|
+
pointerX: number;
|
|
19
|
+
pointerY: number;
|
|
20
|
+
/** Falloff radius for `pointer`-scoped effects, in local units. */
|
|
21
|
+
pointerRadius: number;
|
|
22
|
+
}
|
|
23
|
+
/** Working position, reused across points so the loop allocates nothing. */
|
|
24
|
+
interface Pos {
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
z: number;
|
|
28
|
+
}
|
|
29
|
+
type VertexEffectImpl = (p: Pos, values: Record<string, number>, time: number, scope: number, baseX: number, baseY: number, baseZ: number) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Position effects that run on the CPU. Anything vertex-stage but absent here
|
|
32
|
+
* still needs the shader shell — `scale` writes gl_PointSize, which has no
|
|
33
|
+
* per-point CPU equivalent.
|
|
34
|
+
*/
|
|
35
|
+
export declare const CPU_VERTEX_EFFECTS: Record<string, VertexEffectImpl>;
|
|
36
|
+
/** True when this effect type displaces positions on the CPU. */
|
|
37
|
+
export declare function hasCpuVertexEffect(type: string): boolean;
|
|
38
|
+
/** Split a mixed list into the CPU-displaced ones and everything else. */
|
|
39
|
+
export declare function partitionShaderEffects(effects: ShaderEffect[] | null | undefined): {
|
|
40
|
+
position: ShaderEffect[];
|
|
41
|
+
shell: ShaderEffect[];
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Displace `base` into `out` by every enabled position effect.
|
|
45
|
+
*
|
|
46
|
+
* `base` is never modified, so effects always compose from the authored
|
|
47
|
+
* positions rather than accumulating frame over frame. Returns false when
|
|
48
|
+
* nothing was applied, so the caller can skip the attribute upload.
|
|
49
|
+
*/
|
|
50
|
+
export declare function applyVertexEffects(base: Float32Array, out: Float32Array, effects: ShaderEffect[] | null | undefined, ctx: VertexEffectContext): boolean;
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=vertexEffectsCpu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vertexEffectsCpu.d.ts","sourceRoot":"","sources":["../../../src/shaders/effects/vertexEffectsCpu.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,IAAM,CAAC;AAEvC,MAAM,WAAW,mBAAmB;IAChC,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;OAMG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,4EAA4E;AAC5E,UAAU,GAAG;IACT,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACb;AAED,KAAK,gBAAgB,GAAG,CACpB,CAAC,EAAE,GAAG,EACN,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,KACZ,IAAI,CAAC;AA+HV;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAE/D,CAAC;AAEF,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,0EAA0E;AAC1E,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG;IAChF,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,KAAK,EAAE,YAAY,EAAE,CAAC;CACzB,CAOA;AAoBD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAC9B,IAAI,EAAE,YAAY,EAClB,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,GAAG,SAAS,EAC1C,GAAG,EAAE,mBAAmB,GACzB,OAAO,CAsCT"}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// vertexEffectsCpu — position effects, evaluated on the CPU
|
|
3
|
+
// =============================================================================
|
|
4
|
+
//
|
|
5
|
+
// Why this exists: the GLSL versions of these effects only run inside
|
|
6
|
+
// `buildShaderEffectsMaterial`'s standalone shell, and that shell *replaces*
|
|
7
|
+
// whatever material the object was given. Evaluating position effects here
|
|
8
|
+
// instead means they displace the geometry and leave `.material` alone, so they
|
|
9
|
+
// compose with any material — the registry's, a custom ShaderMaterial, anything.
|
|
10
|
+
//
|
|
11
|
+
// Colour effects cannot move: there is no per-pixel hook on the CPU. They stay
|
|
12
|
+
// in the shell until they are injected into the chosen material (onBeforeCompile).
|
|
13
|
+
//
|
|
14
|
+
// Each implementation is a transcription of the matching `vertexBody` in
|
|
15
|
+
// `registry/*.ts`. Keep them in step. The GLSL bodies remain the reference for
|
|
16
|
+
// anything still rendered through the shell.
|
|
17
|
+
//
|
|
18
|
+
// Deliberately allocation-free in the hot loop: positions are read from a base
|
|
19
|
+
// array and written to an output array, no vectors constructed per point.
|
|
20
|
+
//
|
|
21
|
+
import { getDescriptor } from './registry/index.js';
|
|
22
|
+
import { sampleNoise } from './noiseLib.js';
|
|
23
|
+
/**
|
|
24
|
+
* The shader approximated a local-space pointer as `u_pointer * 5.0` — a legacy
|
|
25
|
+
* constant, but the one the effects were tuned against. The CPU path reuses it
|
|
26
|
+
* so pointer-scoped effects keep the reach they had.
|
|
27
|
+
*/
|
|
28
|
+
export const LOCAL_POINTER_SCALE = 5.0;
|
|
29
|
+
const smoothstep = (edge0, edge1, x) => {
|
|
30
|
+
const t = Math.min(Math.max((x - edge0) / (edge1 - edge0), 0), 1);
|
|
31
|
+
return t * t * (3 - 2 * t);
|
|
32
|
+
};
|
|
33
|
+
const fract = (x) => x - Math.floor(x);
|
|
34
|
+
// ─── Implementations ─────────────────────────────────────────────────────────
|
|
35
|
+
const wave = (p, v, t, s) => {
|
|
36
|
+
const input = v.direction < 0.5 ? p.x : v.direction < 1.5 ? p.y : p.x + p.y;
|
|
37
|
+
p.z += Math.sin(input * v.frequency + t * v.speed) * v.intensity * s;
|
|
38
|
+
};
|
|
39
|
+
const ripple = (p, v, t, s) => {
|
|
40
|
+
const dx = p.x - v.centerX;
|
|
41
|
+
const dy = p.y - v.centerY;
|
|
42
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
43
|
+
p.z += Math.sin(dist * v.frequency - t * v.speed) * v.intensity * s;
|
|
44
|
+
};
|
|
45
|
+
const vortex = (p, v, t, s) => {
|
|
46
|
+
const toX = p.x - v.centerX;
|
|
47
|
+
const toY = p.y - v.centerY;
|
|
48
|
+
const angle = v.intensity * t * v.speed * s;
|
|
49
|
+
const c = Math.cos(angle), sn = Math.sin(angle);
|
|
50
|
+
p.x = v.centerX + (c * toX - sn * toY);
|
|
51
|
+
p.y = v.centerY + (sn * toX + c * toY);
|
|
52
|
+
};
|
|
53
|
+
const spiral = (p, v, t, s) => {
|
|
54
|
+
const toX = p.x - v.centerX;
|
|
55
|
+
const toY = p.y - v.centerY;
|
|
56
|
+
let r = Math.sqrt(toX * toX + toY * toY);
|
|
57
|
+
let a = Math.atan2(toY, toX);
|
|
58
|
+
a += t * v.speed * v.intensity * s;
|
|
59
|
+
r = Math.max(0, r + t * v.radialSpeed * s);
|
|
60
|
+
p.x = v.centerX + r * Math.cos(a);
|
|
61
|
+
p.y = v.centerY + r * Math.sin(a);
|
|
62
|
+
};
|
|
63
|
+
const twist = (p, v, t, s) => {
|
|
64
|
+
const coord = v.axis < 0.5 ? p.x : v.axis < 1.5 ? p.y : p.z;
|
|
65
|
+
const angle = (coord * v.intensity + t * v.speed) * s;
|
|
66
|
+
const sn = Math.sin(angle), c = Math.cos(angle);
|
|
67
|
+
if (v.axis < 0.5) {
|
|
68
|
+
const y = c * p.y - sn * p.z;
|
|
69
|
+
const z = sn * p.y + c * p.z;
|
|
70
|
+
p.y = y;
|
|
71
|
+
p.z = z;
|
|
72
|
+
}
|
|
73
|
+
else if (v.axis < 1.5) {
|
|
74
|
+
const x = c * p.x + sn * p.z;
|
|
75
|
+
const z = -sn * p.x + c * p.z;
|
|
76
|
+
p.x = x;
|
|
77
|
+
p.z = z;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const x = c * p.x - sn * p.y;
|
|
81
|
+
const y = sn * p.x + c * p.y;
|
|
82
|
+
p.x = x;
|
|
83
|
+
p.y = y;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const explode = (p, v, t, s) => {
|
|
87
|
+
const fx = p.x - v.centerX;
|
|
88
|
+
const fy = p.y - v.centerY;
|
|
89
|
+
const fz = p.z - v.centerZ;
|
|
90
|
+
const dist = Math.sqrt(fx * fx + fy * fy + fz * fz);
|
|
91
|
+
let dx = 0, dy = 1, dz = 0;
|
|
92
|
+
if (dist > 0.0001) {
|
|
93
|
+
dx = fx / dist;
|
|
94
|
+
dy = fy / dist;
|
|
95
|
+
dz = fz / dist;
|
|
96
|
+
}
|
|
97
|
+
const wave01 = Math.sin(t * v.speed) * 0.5 + 0.5;
|
|
98
|
+
const push = v.intensity * wave01 * s;
|
|
99
|
+
p.x += dx * push;
|
|
100
|
+
p.y += dy * push;
|
|
101
|
+
p.z += dz * push;
|
|
102
|
+
};
|
|
103
|
+
const magnet = (p, v, t, s) => {
|
|
104
|
+
const toX = v.centerX - p.x;
|
|
105
|
+
const toY = v.centerY - p.y;
|
|
106
|
+
const toZ = v.centerZ - p.z;
|
|
107
|
+
const dist = Math.max(Math.sqrt(toX * toX + toY * toY + toZ * toZ), 0.001);
|
|
108
|
+
const strength = Math.min(v.intensity * s / Math.pow(dist, v.falloffPower), dist);
|
|
109
|
+
p.x += (toX / dist) * strength;
|
|
110
|
+
p.y += (toY / dist) * strength;
|
|
111
|
+
p.z += (toZ / dist) * strength;
|
|
112
|
+
};
|
|
113
|
+
const jitter = (p, v, t, s, bx, by, bz) => {
|
|
114
|
+
// Seeded from the untouched base position, exactly as the shader seeds from
|
|
115
|
+
// the `position` attribute, so each point keeps its own stable direction.
|
|
116
|
+
const step = Math.floor(t * v.speed) * 0.137;
|
|
117
|
+
const sx = bx + step, sy = by + step, sz = bz + step;
|
|
118
|
+
const ox = fract(Math.sin(sx * 12.9898 + sy * 78.233 + sz * 37.719) * 43758.5453) - 0.5;
|
|
119
|
+
const oy = fract(Math.sin(sx * 93.9898 + sy * 47.233 + sz * 12.719) * 43758.5453) - 0.5;
|
|
120
|
+
const oz = fract(Math.sin(sx * 54.9898 + sy * 31.233 + sz * 89.719) * 43758.5453) - 0.5;
|
|
121
|
+
const k = v.intensity * 2.0 * s;
|
|
122
|
+
p.x += ox * k;
|
|
123
|
+
p.y += oy * k;
|
|
124
|
+
p.z += oz * k;
|
|
125
|
+
};
|
|
126
|
+
const noise = (p, v, t, s) => {
|
|
127
|
+
const nx = p.x * v.frequency + t * v.speed;
|
|
128
|
+
const ny = p.y * v.frequency + t * v.speed;
|
|
129
|
+
const k = v.intensity * s;
|
|
130
|
+
if (v.axis < 2.5) {
|
|
131
|
+
const push = sampleNoise(v.noiseType, nx, ny) * k;
|
|
132
|
+
if (v.axis < 0.5)
|
|
133
|
+
p.x += push;
|
|
134
|
+
else if (v.axis < 1.5)
|
|
135
|
+
p.y += push;
|
|
136
|
+
else
|
|
137
|
+
p.z += push;
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
p.x += sampleNoise(v.noiseType, nx, ny) * k;
|
|
141
|
+
p.y += sampleNoise(v.noiseType, nx + 31.7, ny + 5.2) * k;
|
|
142
|
+
p.z += sampleNoise(v.noiseType, nx + 11.3, ny + 27.1) * k;
|
|
143
|
+
};
|
|
144
|
+
const displacement = (p, v, t, s, _bx, _by, _bz) => {
|
|
145
|
+
// Pushed away from the pointer. `ctx` supplies the pointer in local space;
|
|
146
|
+
// it is folded into `values` by applyVertexEffects before the loop.
|
|
147
|
+
const dx = p.x - v.__pointerX;
|
|
148
|
+
const dy = p.y - v.__pointerY;
|
|
149
|
+
const len = Math.sqrt(dx * dx + dy * dy);
|
|
150
|
+
if (len < 1e-6)
|
|
151
|
+
return;
|
|
152
|
+
const k = v.intensity * s * 2.0;
|
|
153
|
+
p.x += (dx / len) * k;
|
|
154
|
+
p.y += (dy / len) * k;
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* Position effects that run on the CPU. Anything vertex-stage but absent here
|
|
158
|
+
* still needs the shader shell — `scale` writes gl_PointSize, which has no
|
|
159
|
+
* per-point CPU equivalent.
|
|
160
|
+
*/
|
|
161
|
+
export const CPU_VERTEX_EFFECTS = {
|
|
162
|
+
wave, ripple, vortex, spiral, twist, explode, magnet, jitter, noise, displacement,
|
|
163
|
+
};
|
|
164
|
+
/** True when this effect type displaces positions on the CPU. */
|
|
165
|
+
export function hasCpuVertexEffect(type) {
|
|
166
|
+
return Object.prototype.hasOwnProperty.call(CPU_VERTEX_EFFECTS, type);
|
|
167
|
+
}
|
|
168
|
+
/** Split a mixed list into the CPU-displaced ones and everything else. */
|
|
169
|
+
export function partitionShaderEffects(effects) {
|
|
170
|
+
const position = [];
|
|
171
|
+
const shell = [];
|
|
172
|
+
for (const effect of effects ?? []) {
|
|
173
|
+
(hasCpuVertexEffect(effect.type) ? position : shell).push(effect);
|
|
174
|
+
}
|
|
175
|
+
return { position, shell };
|
|
176
|
+
}
|
|
177
|
+
/** Resolve an effect's values against its descriptor defaults, once per frame. */
|
|
178
|
+
function resolveValues(effect, ctx) {
|
|
179
|
+
const descriptor = getDescriptor(effect.type);
|
|
180
|
+
if (!descriptor)
|
|
181
|
+
return null;
|
|
182
|
+
const values = {};
|
|
183
|
+
for (const [key, def] of Object.entries(descriptor.uniforms)) {
|
|
184
|
+
const raw = effect.values?.[key];
|
|
185
|
+
const value = raw === undefined ? def.default : raw;
|
|
186
|
+
values[key] = typeof value === 'number' ? value : Number(value) || 0;
|
|
187
|
+
}
|
|
188
|
+
values.__pointerX = ctx.pointerX;
|
|
189
|
+
values.__pointerY = ctx.pointerY;
|
|
190
|
+
return values;
|
|
191
|
+
}
|
|
192
|
+
const scratch = { x: 0, y: 0, z: 0 };
|
|
193
|
+
/**
|
|
194
|
+
* Displace `base` into `out` by every enabled position effect.
|
|
195
|
+
*
|
|
196
|
+
* `base` is never modified, so effects always compose from the authored
|
|
197
|
+
* positions rather than accumulating frame over frame. Returns false when
|
|
198
|
+
* nothing was applied, so the caller can skip the attribute upload.
|
|
199
|
+
*/
|
|
200
|
+
export function applyVertexEffects(base, out, effects, ctx) {
|
|
201
|
+
const active = (effects ?? []).filter(e => e?.enabled && hasCpuVertexEffect(e.type));
|
|
202
|
+
if (active.length === 0)
|
|
203
|
+
return false;
|
|
204
|
+
const resolved = [];
|
|
205
|
+
for (const effect of active) {
|
|
206
|
+
const values = resolveValues(effect, ctx);
|
|
207
|
+
if (!values)
|
|
208
|
+
continue;
|
|
209
|
+
resolved.push({
|
|
210
|
+
impl: CPU_VERTEX_EFFECTS[effect.type],
|
|
211
|
+
values,
|
|
212
|
+
pointerScoped: effect.scope === 'pointer',
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
if (resolved.length === 0)
|
|
216
|
+
return false;
|
|
217
|
+
const radius = ctx.pointerRadius > 0 ? ctx.pointerRadius : 1;
|
|
218
|
+
const count = Math.min(base.length, out.length);
|
|
219
|
+
for (let i = 0; i < count; i += 3) {
|
|
220
|
+
const bx = base[i], by = base[i + 1], bz = base[i + 2];
|
|
221
|
+
scratch.x = bx;
|
|
222
|
+
scratch.y = by;
|
|
223
|
+
scratch.z = bz;
|
|
224
|
+
// Falloff is measured from the untouched position so that one effect
|
|
225
|
+
// moving a point cannot change how strongly the next one grips it.
|
|
226
|
+
const dx = bx - ctx.pointerX;
|
|
227
|
+
const dy = by - ctx.pointerY;
|
|
228
|
+
const pointerFalloff = smoothstep(radius, 0, Math.sqrt(dx * dx + dy * dy));
|
|
229
|
+
for (const { impl, values, pointerScoped } of resolved) {
|
|
230
|
+
const scope = pointerScoped ? pointerFalloff : 1;
|
|
231
|
+
if (scope <= 0)
|
|
232
|
+
continue;
|
|
233
|
+
impl(scratch, values, ctx.time, scope, bx, by, bz);
|
|
234
|
+
}
|
|
235
|
+
out[i] = scratch.x;
|
|
236
|
+
out[i + 1] = scratch.y;
|
|
237
|
+
out[i + 2] = scratch.z;
|
|
238
|
+
}
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BufferGeometry, Matrix4, Mesh, Vector3 } from "three";
|
|
1
|
+
import { BufferAttribute, BufferGeometry, Matrix4, Mesh, Vector3 } from "three";
|
|
2
2
|
import type { Object3D } from 'three';
|
|
3
3
|
export interface MeshEntry {
|
|
4
4
|
mesh: Mesh;
|
|
@@ -34,4 +34,5 @@ export declare function sampleEdgePoints(segments: EdgeSegment[], countPerEdge:
|
|
|
34
34
|
* Indices form connected pairs so LineSegments renders them as solid continuous lines per edge.
|
|
35
35
|
*/
|
|
36
36
|
export declare function buildSubdividedEdgeGeometry(object: Object3D, subdivisions?: number, parentMatrix?: Matrix4): BufferGeometry;
|
|
37
|
+
export declare function buildSegmentQuadGeometry(source: BufferAttribute | ArrayLike<[number, number, number]>, thickness?: number): BufferGeometry;
|
|
37
38
|
//# sourceMappingURL=edgeUtils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edgeUtils.d.ts","sourceRoot":"","sources":["../../src/utils/edgeUtils.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"edgeUtils.d.ts","sourceRoot":"","sources":["../../src/utils/edgeUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAyC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACvH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEtC,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,IAAI,CAAC;IACX,4CAA4C;IAC5C,oBAAoB,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,WAAW;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;CAChB;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,GAAG,EAAE,QAAQ,EAAE,YAAY,GAAE,OAAuB,GAAG,SAAS,EAAE,CAY/F;AACD,uDAAuD;AACvD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAQjE;AACD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,QAAQ,GAAG,WAAW,EAAE,CAiBnE;AACD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG;IACzE,SAAS,EAAE,YAAY,CAAC;IACxB,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,YAAY,CAAC;CAC3B,CAsBJ;AACD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAE,MAAW,EAAE,YAAY,CAAC,EAAE,OAAO,GAAG,cAAc,CA8C/H;AAmBD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,SAAS,GAAE,MAAc,GAAG,cAAc,CAmDjJ"}
|
package/dist/utils/edgeUtils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BufferAttribute, BufferGeometry, EdgesGeometry, Matrix4, Mesh, Vector3 } from "three";
|
|
1
|
+
import { BufferAttribute, BufferGeometry, EdgesGeometry, Float32BufferAttribute, Matrix4, Mesh, Vector3 } from "three";
|
|
2
2
|
import { EDGES_GROUP_KEY } from "./materialApplicationUtils.js";
|
|
3
3
|
/** Recursively collect all meshes with geometries, accumulating local matrices. */
|
|
4
4
|
export function collectMeshes(obj, parentMatrix = new Matrix4()) {
|
|
@@ -126,3 +126,72 @@ export function buildSubdividedEdgeGeometry(object, subdivisions = 60, parentMat
|
|
|
126
126
|
geo.setIndex(indices);
|
|
127
127
|
return geo;
|
|
128
128
|
}
|
|
129
|
+
// =============================================================================
|
|
130
|
+
// SEGMENT QUADS
|
|
131
|
+
// =============================================================================
|
|
132
|
+
//
|
|
133
|
+
// Turn a list of line segments into a ribbon of camera-agnostic quads — two
|
|
134
|
+
// triangles per segment, with UVs running (0,0)-(1,1) along and across it.
|
|
135
|
+
//
|
|
136
|
+
// This is what makes edges materialisable: the result is an ordinary Mesh with
|
|
137
|
+
// real UVs, so every registry material (the `line` shader family included)
|
|
138
|
+
// applies to it exactly as it would to any other mesh. Line primitives cannot
|
|
139
|
+
// do that — Line2 needs its own LineMaterial and carries no UVs — which is why
|
|
140
|
+
// both the edges builder and the `lines` display modes go through here instead.
|
|
141
|
+
//
|
|
142
|
+
// `source` is a flat sequence of vertex positions, two consecutive vertices per
|
|
143
|
+
// segment: either a BufferAttribute (e.g. EdgesGeometry.attributes.position) or
|
|
144
|
+
// an array of [x, y, z] triples.
|
|
145
|
+
//
|
|
146
|
+
export function buildSegmentQuadGeometry(source, thickness = 0.008) {
|
|
147
|
+
const isAttribute = typeof source.getX === 'function';
|
|
148
|
+
const attr = source;
|
|
149
|
+
const list = source;
|
|
150
|
+
const vertexCount = isAttribute ? attr.count : list.length;
|
|
151
|
+
const segCount = Math.floor(vertexCount / 2);
|
|
152
|
+
const readVertex = (i, out) => (isAttribute
|
|
153
|
+
? out.fromBufferAttribute(attr, i)
|
|
154
|
+
: out.set(list[i][0], list[i][1], list[i][2]));
|
|
155
|
+
const positions = [];
|
|
156
|
+
const uvs = [];
|
|
157
|
+
const indices = [];
|
|
158
|
+
const start = new Vector3();
|
|
159
|
+
const end = new Vector3();
|
|
160
|
+
const dir = new Vector3();
|
|
161
|
+
const up = new Vector3(0, 1, 0);
|
|
162
|
+
const right = new Vector3();
|
|
163
|
+
for (let i = 0; i < segCount; i++) {
|
|
164
|
+
readVertex(i * 2, start);
|
|
165
|
+
readVertex(i * 2 + 1, end);
|
|
166
|
+
dir.subVectors(end, start).normalize();
|
|
167
|
+
// Perpendicular axis — fallback to X if the segment is vertical
|
|
168
|
+
right.crossVectors(dir, up).normalize();
|
|
169
|
+
if (right.lengthSq() < 0.0001) {
|
|
170
|
+
right.set(1, 0, 0);
|
|
171
|
+
}
|
|
172
|
+
const rx = right.x * thickness;
|
|
173
|
+
const ry = right.y * thickness;
|
|
174
|
+
const rz = right.z * thickness;
|
|
175
|
+
const base = i * 4;
|
|
176
|
+
// v0 start-bottom uv(0,0)
|
|
177
|
+
positions.push(start.x - rx, start.y - ry, start.z - rz);
|
|
178
|
+
uvs.push(0, 0);
|
|
179
|
+
// v1 end-bottom uv(1,0)
|
|
180
|
+
positions.push(end.x - rx, end.y - ry, end.z - rz);
|
|
181
|
+
uvs.push(1, 0);
|
|
182
|
+
// v2 start-top uv(0,1)
|
|
183
|
+
positions.push(start.x + rx, start.y + ry, start.z + rz);
|
|
184
|
+
uvs.push(0, 1);
|
|
185
|
+
// v3 end-top uv(1,1)
|
|
186
|
+
positions.push(end.x + rx, end.y + ry, end.z + rz);
|
|
187
|
+
uvs.push(1, 1);
|
|
188
|
+
indices.push(base, base + 1, base + 2);
|
|
189
|
+
indices.push(base + 1, base + 3, base + 2);
|
|
190
|
+
}
|
|
191
|
+
const geo = new BufferGeometry();
|
|
192
|
+
geo.setAttribute('position', new Float32BufferAttribute(positions, 3));
|
|
193
|
+
geo.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
|
|
194
|
+
geo.setIndex(indices);
|
|
195
|
+
geo.computeVertexNormals();
|
|
196
|
+
return geo;
|
|
197
|
+
}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export * from './positionsCreatorUtils';
|
|
|
16
16
|
export * from './sunUtils';
|
|
17
17
|
export * from './utils';
|
|
18
18
|
export * from './edgeUtils';
|
|
19
|
+
export * from './surfaceUtils';
|
|
19
20
|
export * from './objectTreeUtils';
|
|
20
21
|
export * from './handleTransformEffects';
|
|
21
22
|
export * from './handleEdgesAnimations';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC"}
|
package/dist/utils/index.js
CHANGED
|
@@ -16,6 +16,7 @@ export * from './positionsCreatorUtils.js';
|
|
|
16
16
|
export * from './sunUtils.js';
|
|
17
17
|
export * from './utils.js';
|
|
18
18
|
export * from './edgeUtils.js';
|
|
19
|
+
export * from './surfaceUtils.js';
|
|
19
20
|
export * from './objectTreeUtils.js';
|
|
20
21
|
export * from './handleTransformEffects.js';
|
|
21
22
|
export * from './handleEdgesAnimations.js';
|
|
@@ -3,10 +3,19 @@ import { MaterialInstance } from '../services/MaterialRegistry';
|
|
|
3
3
|
export declare const MATERIAL_INSTANCE_KEY = "_3driseMaterialInstance";
|
|
4
4
|
export declare const EDGES_GROUP_KEY = "__isEdgesGroup";
|
|
5
5
|
export declare const GEREATIVE_EFFECTS_KEY = "__isGenerativeEffectsGroup";
|
|
6
|
+
/**
|
|
7
|
+
* Set by a renderer that builds and owns its object's material itself — today the
|
|
8
|
+
* points renderers, while shader effects are active. Two writers on one
|
|
9
|
+
* `.material` is the bug this prevents: whichever loses keeps animating a
|
|
10
|
+
* material that is no longer on the mesh, and the object renders as whatever the
|
|
11
|
+
* winner left behind.
|
|
12
|
+
*/
|
|
13
|
+
export declare const SELF_OWNED_MATERIAL_KEY = "__ownsItsMaterial";
|
|
6
14
|
/**
|
|
7
15
|
* Traverses obj and its descendants, skipping subtrees whose root is marked
|
|
8
|
-
* with EDGES_GROUP_KEY or
|
|
9
|
-
* or generative effects group can still
|
|
16
|
+
* with EDGES_GROUP_KEY, GEREATIVE_EFFECTS_KEY or SELF_OWNED_MATERIAL_KEY — unless obj itself
|
|
17
|
+
* carries that mark (so an edges group or generative effects group can still
|
|
18
|
+
* apply its own material via useMaterialApplication).
|
|
10
19
|
*/
|
|
11
20
|
export declare function traverseSkippingEdgesAndEffects(obj: Object3D, isRoot: boolean, callback: (node: Object3D) => void): void;
|
|
12
21
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"materialApplicationUtils.d.ts","sourceRoot":"","sources":["../../src/utils/materialApplicationUtils.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAChD,OAA4B,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAKrF,eAAO,MAAM,qBAAqB,4BAA4B,CAAC;AAE/D,eAAO,MAAM,eAAe,mBAAmB,CAAC;AAChD,eAAO,MAAM,qBAAqB,+BAA+B,CAAC;AAClE
|
|
1
|
+
{"version":3,"file":"materialApplicationUtils.d.ts","sourceRoot":"","sources":["../../src/utils/materialApplicationUtils.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAChD,OAA4B,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAKrF,eAAO,MAAM,qBAAqB,4BAA4B,CAAC;AAE/D,eAAO,MAAM,eAAe,mBAAmB,CAAC;AAChD,eAAO,MAAM,qBAAqB,+BAA+B,CAAC;AAClE;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,sBAAsB,CAAC;AAC3D;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,GAAG,IAAI,CAOxH;AAKD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,gBAAgB,CAI/G;AACD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAQlH;AACD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI,CAsCrF;AACD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAE1F;AACD;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEpD;AACD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGtD;AACD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAElE;AACD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAElE;AACD;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,GAAG,CAAC,MAAM,CAGtC,CAAC;AACH;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG;IAC3D,OAAO,EAAE,KAAK,CAAC;QACX,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IACH,MAAM,EAAE,KAAK,CAAC;QACV,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IACH,QAAQ,EAAE,KAAK,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,GAAG,CAAC;KACd,CAAC,CAAC;IACH,QAAQ,EAAE,KAAK,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,OAAO,CAAC;KAClB,CAAC,CAAC;IACH,KAAK,EAAE,KAAK,CAAC;QACT,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,GAAG,CAAC;KACd,CAAC,CAAC;CACN,CA6BJ"}
|
|
@@ -18,13 +18,22 @@ export const MATERIAL_INSTANCE_KEY = '_3driseMaterialInstance';
|
|
|
18
18
|
// Key placed on edges group userData to prevent material bleed-through
|
|
19
19
|
export const EDGES_GROUP_KEY = '__isEdgesGroup';
|
|
20
20
|
export const GEREATIVE_EFFECTS_KEY = '__isGenerativeEffectsGroup';
|
|
21
|
+
/**
|
|
22
|
+
* Set by a renderer that builds and owns its object's material itself — today the
|
|
23
|
+
* points renderers, while shader effects are active. Two writers on one
|
|
24
|
+
* `.material` is the bug this prevents: whichever loses keeps animating a
|
|
25
|
+
* material that is no longer on the mesh, and the object renders as whatever the
|
|
26
|
+
* winner left behind.
|
|
27
|
+
*/
|
|
28
|
+
export const SELF_OWNED_MATERIAL_KEY = '__ownsItsMaterial';
|
|
21
29
|
/**
|
|
22
30
|
* Traverses obj and its descendants, skipping subtrees whose root is marked
|
|
23
|
-
* with EDGES_GROUP_KEY or
|
|
24
|
-
* or generative effects group can still
|
|
31
|
+
* with EDGES_GROUP_KEY, GEREATIVE_EFFECTS_KEY or SELF_OWNED_MATERIAL_KEY — unless obj itself
|
|
32
|
+
* carries that mark (so an edges group or generative effects group can still
|
|
33
|
+
* apply its own material via useMaterialApplication).
|
|
25
34
|
*/
|
|
26
35
|
export function traverseSkippingEdgesAndEffects(obj, isRoot, callback) {
|
|
27
|
-
if (!isRoot && (obj.userData[EDGES_GROUP_KEY] || obj.userData[GEREATIVE_EFFECTS_KEY]))
|
|
36
|
+
if (!isRoot && (obj.userData[EDGES_GROUP_KEY] || obj.userData[GEREATIVE_EFFECTS_KEY] || obj.userData[SELF_OWNED_MATERIAL_KEY]))
|
|
28
37
|
return;
|
|
29
38
|
callback(obj);
|
|
30
39
|
for (const child of obj.children) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CreatedObjectSettings, DisplayMode, EdgesType, ModeGroup } from '../types/scene3d';
|
|
2
|
+
/** Display mode → the kind of object it draws. */
|
|
3
|
+
export declare const DISPLAY_MODE_GROUPS: Record<DisplayMode, ModeGroup>;
|
|
4
|
+
export declare function modeGroupOf(mode?: DisplayMode | null): ModeGroup;
|
|
5
|
+
/**
|
|
6
|
+
* Edge decorations follow the same rule: `particles` edges are a Points object,
|
|
7
|
+
* every other edge type is built from meshes.
|
|
8
|
+
*/
|
|
9
|
+
export declare function edgesTypeGroupOf(type?: EdgesType | null): ModeGroup;
|
|
10
|
+
/** The surface a created object draws, for material-compatibility purposes. */
|
|
11
|
+
export declare function surfaceOf(settings?: Pick<CreatedObjectSettings, 'type' | 'modeConfig'> | null): ModeGroup;
|
|
12
|
+
/**
|
|
13
|
+
* The one hard constraint: a Points object can only take the `particles`
|
|
14
|
+
* family, and that family only renders on a Points object. Everything else is
|
|
15
|
+
* an ordinary mesh material — the `line` family included, which is a material
|
|
16
|
+
* with line-like effects rather than a material for line primitives.
|
|
17
|
+
*/
|
|
18
|
+
export declare function materialTypeFitsSurface(materialType: string, surface: ModeGroup): boolean;
|
|
19
|
+
/** The family to fall back to when the current one cannot draw on a surface. */
|
|
20
|
+
export declare function defaultMaterialTypeForSurface(surface: ModeGroup): string;
|
|
21
|
+
//# sourceMappingURL=surfaceUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surfaceUtils.d.ts","sourceRoot":"","sources":["../../src/utils/surfaceUtils.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEjG,kDAAkD;AAClD,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,SAAS,CAa9D,CAAC;AAEF,wBAAgB,WAAW,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAEhE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,CAEnE;AAED,+EAA+E;AAC/E,wBAAgB,SAAS,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,qBAAqB,EAAE,MAAM,GAAG,YAAY,CAAC,GAAG,IAAI,GAAG,SAAS,CAQzG;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,GAAG,OAAO,CAIzF;AAED,gFAAgF;AAChF,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,SAAS,GAAG,MAAM,CAExE"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** Display mode → the kind of object it draws. */
|
|
2
|
+
export const DISPLAY_MODE_GROUPS = {
|
|
3
|
+
solid: 'mesh',
|
|
4
|
+
volume: 'points',
|
|
5
|
+
surface: 'points',
|
|
6
|
+
symmetric: 'points',
|
|
7
|
+
evenScatter: 'points',
|
|
8
|
+
vertices: 'points',
|
|
9
|
+
// plexus draws a point cloud plus connecting ribbons; the points dominate.
|
|
10
|
+
plexus: 'points',
|
|
11
|
+
edges3d: 'lines',
|
|
12
|
+
profile2d: 'lines',
|
|
13
|
+
wireframe: 'lines',
|
|
14
|
+
contourSlices: 'lines',
|
|
15
|
+
};
|
|
16
|
+
export function modeGroupOf(mode) {
|
|
17
|
+
return (mode && DISPLAY_MODE_GROUPS[mode]) || 'mesh';
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Edge decorations follow the same rule: `particles` edges are a Points object,
|
|
21
|
+
* every other edge type is built from meshes.
|
|
22
|
+
*/
|
|
23
|
+
export function edgesTypeGroupOf(type) {
|
|
24
|
+
return type === 'particles' ? 'points' : 'lines';
|
|
25
|
+
}
|
|
26
|
+
/** The surface a created object draws, for material-compatibility purposes. */
|
|
27
|
+
export function surfaceOf(settings) {
|
|
28
|
+
if (!settings)
|
|
29
|
+
return 'mesh';
|
|
30
|
+
if (settings.type === 'particles')
|
|
31
|
+
return 'points';
|
|
32
|
+
if (settings.type === 'mesh')
|
|
33
|
+
return modeGroupOf(settings.modeConfig?.mode);
|
|
34
|
+
return 'mesh';
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The one hard constraint: a Points object can only take the `particles`
|
|
38
|
+
* family, and that family only renders on a Points object. Everything else is
|
|
39
|
+
* an ordinary mesh material — the `line` family included, which is a material
|
|
40
|
+
* with line-like effects rather than a material for line primitives.
|
|
41
|
+
*/
|
|
42
|
+
export function materialTypeFitsSurface(materialType, surface) {
|
|
43
|
+
return surface === 'points'
|
|
44
|
+
? materialType === 'particles'
|
|
45
|
+
: materialType !== 'particles';
|
|
46
|
+
}
|
|
47
|
+
/** The family to fall back to when the current one cannot draw on a surface. */
|
|
48
|
+
export function defaultMaterialTypeForSurface(surface) {
|
|
49
|
+
return surface === 'points' ? 'particles' : 'basic';
|
|
50
|
+
}
|