r3f-vfx 0.1.1 → 0.1.3
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/index.d.ts +4 -7
- package/dist/index.js +89 -112
- package/package.json +2 -2
- package/dist/curveWorker.d.ts +0 -2
- package/dist/curveWorker.js +0 -105
package/dist/index.d.ts
CHANGED
|
@@ -265,15 +265,12 @@ declare const useVFXStore: typeof useVFXStoreImpl & {
|
|
|
265
265
|
};
|
|
266
266
|
|
|
267
267
|
/**
|
|
268
|
-
* Hook for
|
|
268
|
+
* Hook for curve texture loading/baking
|
|
269
269
|
* Returns a STABLE texture reference that updates in place
|
|
270
270
|
*
|
|
271
|
-
* If curveTexturePath is provided, loads pre-baked texture
|
|
272
|
-
* If curves are defined, bakes them
|
|
273
|
-
* If no curves AND no path, returns default texture (no baking
|
|
274
|
-
*
|
|
275
|
-
* The 4KB default texture is always created for shader compatibility,
|
|
276
|
-
* but baking is skipped when not needed (main performance win).
|
|
271
|
+
* If curveTexturePath is provided, loads pre-baked texture from file
|
|
272
|
+
* If curves are defined, bakes them synchronously on the main thread
|
|
273
|
+
* If no curves AND no path, returns default texture (no baking needed)
|
|
277
274
|
*/
|
|
278
275
|
declare const useCurveTextureAsync: (sizeCurve: CurveData | null, opacityCurve: CurveData | null, velocityCurve: CurveData | null, rotationSpeedCurve: CurveData | null, curveTexturePath?: string | null) => THREE.DataTexture;
|
|
279
276
|
|
package/dist/index.js
CHANGED
|
@@ -58,103 +58,80 @@ var init_react_store = __esm({
|
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
// src/useCurveTextureAsync.ts
|
|
61
|
-
import { useRef, useEffect } from "react";
|
|
61
|
+
import { useRef, useEffect, useMemo } from "react";
|
|
62
62
|
import {
|
|
63
63
|
createDefaultCurveTexture,
|
|
64
|
+
createCombinedCurveTexture,
|
|
64
65
|
loadCurveTextureFromPath
|
|
65
66
|
} from "core-vfx";
|
|
66
|
-
var
|
|
67
|
+
var useCurveTextureAsync;
|
|
67
68
|
var init_useCurveTextureAsync = __esm({
|
|
68
69
|
"src/useCurveTextureAsync.ts"() {
|
|
69
70
|
"use strict";
|
|
70
|
-
import_meta = {};
|
|
71
|
-
curveWorker = null;
|
|
72
|
-
curveWorkerCallbacks = /* @__PURE__ */ new Map();
|
|
73
|
-
curveWorkerIdCounter = 0;
|
|
74
|
-
getCurveWorker = () => {
|
|
75
|
-
if (!curveWorker) {
|
|
76
|
-
curveWorker = new Worker(new URL("./curveWorker.js", import_meta.url), {
|
|
77
|
-
type: "module"
|
|
78
|
-
});
|
|
79
|
-
curveWorker.onmessage = (e) => {
|
|
80
|
-
const { id, rgba } = e.data;
|
|
81
|
-
const callback = curveWorkerCallbacks.get(id);
|
|
82
|
-
if (callback) {
|
|
83
|
-
callback(rgba);
|
|
84
|
-
curveWorkerCallbacks.delete(id);
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
return curveWorker;
|
|
89
|
-
};
|
|
90
|
-
bakeCurvesAsync = (sizeCurve, opacityCurve, velocityCurve, rotationSpeedCurve) => {
|
|
91
|
-
return new Promise((resolve) => {
|
|
92
|
-
const worker = getCurveWorker();
|
|
93
|
-
const id = curveWorkerIdCounter++;
|
|
94
|
-
curveWorkerCallbacks.set(id, resolve);
|
|
95
|
-
worker.postMessage({
|
|
96
|
-
id,
|
|
97
|
-
sizeCurve,
|
|
98
|
-
opacityCurve,
|
|
99
|
-
velocityCurve,
|
|
100
|
-
rotationSpeedCurve
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
};
|
|
104
71
|
useCurveTextureAsync = (sizeCurve, opacityCurve, velocityCurve, rotationSpeedCurve, curveTexturePath = null) => {
|
|
72
|
+
const hasAnyCurve = sizeCurve || opacityCurve || velocityCurve || rotationSpeedCurve;
|
|
105
73
|
const textureRef = useRef(null);
|
|
106
|
-
const pendingRef = useRef(null);
|
|
107
74
|
if (!textureRef.current) {
|
|
108
|
-
|
|
75
|
+
if (!curveTexturePath && hasAnyCurve) {
|
|
76
|
+
textureRef.current = createCombinedCurveTexture(
|
|
77
|
+
sizeCurve,
|
|
78
|
+
opacityCurve,
|
|
79
|
+
velocityCurve,
|
|
80
|
+
rotationSpeedCurve
|
|
81
|
+
);
|
|
82
|
+
} else {
|
|
83
|
+
textureRef.current = createDefaultCurveTexture();
|
|
84
|
+
}
|
|
109
85
|
}
|
|
86
|
+
useMemo(() => {
|
|
87
|
+
if (!curveTexturePath && hasAnyCurve && textureRef.current) {
|
|
88
|
+
const bakedTexture = createCombinedCurveTexture(
|
|
89
|
+
sizeCurve,
|
|
90
|
+
opacityCurve,
|
|
91
|
+
velocityCurve,
|
|
92
|
+
rotationSpeedCurve
|
|
93
|
+
);
|
|
94
|
+
const srcData = bakedTexture.image.data;
|
|
95
|
+
const dstData = textureRef.current.image.data;
|
|
96
|
+
if (srcData && dstData) {
|
|
97
|
+
dstData.set(srcData);
|
|
98
|
+
textureRef.current.needsUpdate = true;
|
|
99
|
+
}
|
|
100
|
+
bakedTexture.dispose();
|
|
101
|
+
}
|
|
102
|
+
}, [sizeCurve, opacityCurve, velocityCurve, rotationSpeedCurve]);
|
|
110
103
|
useEffect(() => {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
);
|
|
121
|
-
return bakeCurvesAsync(
|
|
104
|
+
if (!curveTexturePath || !textureRef.current) return;
|
|
105
|
+
loadCurveTextureFromPath(curveTexturePath, textureRef.current).catch(
|
|
106
|
+
(err) => {
|
|
107
|
+
console.warn(
|
|
108
|
+
`Failed to load curve texture: ${curveTexturePath}, falling back to baking`,
|
|
109
|
+
err
|
|
110
|
+
);
|
|
111
|
+
if (hasAnyCurve && textureRef.current) {
|
|
112
|
+
const bakedTexture = createCombinedCurveTexture(
|
|
122
113
|
sizeCurve,
|
|
123
114
|
opacityCurve,
|
|
124
115
|
velocityCurve,
|
|
125
116
|
rotationSpeedCurve
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
);
|
|
135
|
-
} else if (hasAnyCurve) {
|
|
136
|
-
bakeCurvesAsync(
|
|
137
|
-
sizeCurve,
|
|
138
|
-
opacityCurve,
|
|
139
|
-
velocityCurve,
|
|
140
|
-
rotationSpeedCurve
|
|
141
|
-
).then((rgba) => {
|
|
142
|
-
var _a;
|
|
143
|
-
if (pendingRef.current === requestId && ((_a = textureRef.current) == null ? void 0 : _a.image.data)) {
|
|
144
|
-
textureRef.current.image.data.set(rgba);
|
|
145
|
-
textureRef.current.needsUpdate = true;
|
|
117
|
+
);
|
|
118
|
+
const srcData = bakedTexture.image.data;
|
|
119
|
+
const dstData = textureRef.current.image.data;
|
|
120
|
+
if (srcData && dstData) {
|
|
121
|
+
dstData.set(srcData);
|
|
122
|
+
textureRef.current.needsUpdate = true;
|
|
123
|
+
}
|
|
124
|
+
bakedTexture.dispose();
|
|
146
125
|
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return () => {
|
|
150
|
-
pendingRef.current = null;
|
|
151
|
-
};
|
|
126
|
+
}
|
|
127
|
+
);
|
|
152
128
|
}, [
|
|
129
|
+
curveTexturePath,
|
|
153
130
|
sizeCurve,
|
|
154
131
|
opacityCurve,
|
|
155
132
|
velocityCurve,
|
|
156
133
|
rotationSpeedCurve,
|
|
157
|
-
|
|
134
|
+
hasAnyCurve
|
|
158
135
|
]);
|
|
159
136
|
useEffect(() => {
|
|
160
137
|
return () => {
|
|
@@ -3630,7 +3607,7 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
3630
3607
|
flushChanges();
|
|
3631
3608
|
}
|
|
3632
3609
|
const values2 = valuesRef.current;
|
|
3633
|
-
const
|
|
3610
|
+
const CURVE_RESOLUTION = 256;
|
|
3634
3611
|
const evaluateBezierSegment = (t, p0, p1, h0Out, h1In) => {
|
|
3635
3612
|
const cp0 = p0;
|
|
3636
3613
|
const cp1 = [p0[0] + ((h0Out == null ? void 0 : h0Out[0]) || 0), p0[1] + ((h0Out == null ? void 0 : h0Out[1]) || 0)];
|
|
@@ -3687,23 +3664,23 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
3687
3664
|
return Math.max(-0.5, Math.min(1.5, py));
|
|
3688
3665
|
};
|
|
3689
3666
|
const bakeCurveToArray2 = (curveData) => {
|
|
3690
|
-
const data = new Float32Array(
|
|
3667
|
+
const data = new Float32Array(CURVE_RESOLUTION);
|
|
3691
3668
|
if (!(curveData == null ? void 0 : curveData.points) || !Array.isArray(curveData.points) || curveData.points.length < 2) {
|
|
3692
|
-
for (let i = 0; i <
|
|
3693
|
-
data[i] = 1 - i / (
|
|
3669
|
+
for (let i = 0; i < CURVE_RESOLUTION; i++) {
|
|
3670
|
+
data[i] = 1 - i / (CURVE_RESOLUTION - 1);
|
|
3694
3671
|
}
|
|
3695
3672
|
return data;
|
|
3696
3673
|
}
|
|
3697
3674
|
const firstPoint = curveData.points[0];
|
|
3698
3675
|
const lastPoint = curveData.points[curveData.points.length - 1];
|
|
3699
3676
|
if (!(firstPoint == null ? void 0 : firstPoint.pos) || !(lastPoint == null ? void 0 : lastPoint.pos) || !Array.isArray(firstPoint.pos) || !Array.isArray(lastPoint.pos)) {
|
|
3700
|
-
for (let i = 0; i <
|
|
3701
|
-
data[i] = 1 - i / (
|
|
3677
|
+
for (let i = 0; i < CURVE_RESOLUTION; i++) {
|
|
3678
|
+
data[i] = 1 - i / (CURVE_RESOLUTION - 1);
|
|
3702
3679
|
}
|
|
3703
3680
|
return data;
|
|
3704
3681
|
}
|
|
3705
|
-
for (let i = 0; i <
|
|
3706
|
-
const x = i / (
|
|
3682
|
+
for (let i = 0; i < CURVE_RESOLUTION; i++) {
|
|
3683
|
+
const x = i / (CURVE_RESOLUTION - 1);
|
|
3707
3684
|
data[i] = sampleCurveAtX(x, curveData.points);
|
|
3708
3685
|
}
|
|
3709
3686
|
return data;
|
|
@@ -3712,8 +3689,8 @@ ${" ".repeat(indent - 2)}}`;
|
|
|
3712
3689
|
const opacityData = bakeCurveToArray2(values2.fadeOpacityCurve);
|
|
3713
3690
|
const velocityData = bakeCurveToArray2(values2.velocityCurve);
|
|
3714
3691
|
const rotationSpeedData = bakeCurveToArray2(values2.rotationSpeedCurve);
|
|
3715
|
-
const rgba = new Float32Array(
|
|
3716
|
-
for (let i = 0; i <
|
|
3692
|
+
const rgba = new Float32Array(CURVE_RESOLUTION * 4);
|
|
3693
|
+
for (let i = 0; i < CURVE_RESOLUTION; i++) {
|
|
3717
3694
|
rgba[i * 4] = sizeData[i];
|
|
3718
3695
|
rgba[i * 4 + 1] = opacityData[i];
|
|
3719
3696
|
rgba[i * 4 + 2] = velocityData[i];
|
|
@@ -5426,7 +5403,7 @@ import {
|
|
|
5426
5403
|
useImperativeHandle,
|
|
5427
5404
|
useEffect as useEffect3,
|
|
5428
5405
|
useRef as useRef3,
|
|
5429
|
-
useMemo,
|
|
5406
|
+
useMemo as useMemo2,
|
|
5430
5407
|
useCallback as useCallback2,
|
|
5431
5408
|
useState as useState2
|
|
5432
5409
|
} from "react";
|
|
@@ -5458,7 +5435,7 @@ import {
|
|
|
5458
5435
|
Easing as Easing2,
|
|
5459
5436
|
Lighting,
|
|
5460
5437
|
bakeCurveToArray,
|
|
5461
|
-
createCombinedCurveTexture as
|
|
5438
|
+
createCombinedCurveTexture as createCombinedCurveTexture3
|
|
5462
5439
|
} from "core-vfx";
|
|
5463
5440
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
5464
5441
|
var VFXParticles;
|
|
@@ -5673,10 +5650,10 @@ var init_VFXParticles = __esm({
|
|
|
5673
5650
|
attractors,
|
|
5674
5651
|
collision
|
|
5675
5652
|
]);
|
|
5676
|
-
const sizeRange =
|
|
5677
|
-
const speedRange =
|
|
5678
|
-
const fadeSizeRange =
|
|
5679
|
-
const fadeOpacityRange =
|
|
5653
|
+
const sizeRange = useMemo2(() => toRange(size, [0.1, 0.3]), [size]);
|
|
5654
|
+
const speedRange = useMemo2(() => toRange(speed, [0.1, 0.1]), [speed]);
|
|
5655
|
+
const fadeSizeRange = useMemo2(() => toRange(fadeSize, [1, 0]), [fadeSize]);
|
|
5656
|
+
const fadeOpacityRange = useMemo2(
|
|
5680
5657
|
() => toRange(fadeOpacity, [1, 0]),
|
|
5681
5658
|
[fadeOpacity]
|
|
5682
5659
|
);
|
|
@@ -5696,26 +5673,26 @@ var init_VFXParticles = __esm({
|
|
|
5696
5673
|
}
|
|
5697
5674
|
};
|
|
5698
5675
|
}, [curveTexture]);
|
|
5699
|
-
const lifetimeRange =
|
|
5700
|
-
const rotation3D =
|
|
5701
|
-
const rotationSpeed3D =
|
|
5676
|
+
const lifetimeRange = useMemo2(() => toRange(lifetime, [1, 2]), [lifetime]);
|
|
5677
|
+
const rotation3D = useMemo2(() => toRotation3D(rotation), [rotation]);
|
|
5678
|
+
const rotationSpeed3D = useMemo2(
|
|
5702
5679
|
() => toRotation3D(rotationSpeed),
|
|
5703
5680
|
[rotationSpeed]
|
|
5704
5681
|
);
|
|
5705
|
-
const direction3D =
|
|
5706
|
-
const startPosition3D =
|
|
5682
|
+
const direction3D = useMemo2(() => toRotation3D(direction), [direction]);
|
|
5683
|
+
const startPosition3D = useMemo2(
|
|
5707
5684
|
() => toRotation3D(startPosition),
|
|
5708
5685
|
[startPosition]
|
|
5709
5686
|
);
|
|
5710
|
-
const emitterRadiusRange =
|
|
5687
|
+
const emitterRadiusRange = useMemo2(
|
|
5711
5688
|
() => toRange(emitterRadius, [0, 1]),
|
|
5712
5689
|
[emitterRadius]
|
|
5713
5690
|
);
|
|
5714
|
-
const emitterHeightRange =
|
|
5691
|
+
const emitterHeightRange = useMemo2(
|
|
5715
5692
|
() => toRange(emitterHeight, [0, 1]),
|
|
5716
5693
|
[emitterHeight]
|
|
5717
5694
|
);
|
|
5718
|
-
const activeFeatures =
|
|
5695
|
+
const activeFeatures = useMemo2(
|
|
5719
5696
|
() => ({
|
|
5720
5697
|
// Storage array features
|
|
5721
5698
|
needsPerParticleColor: activeNeedsPerParticleColor,
|
|
@@ -5735,33 +5712,33 @@ var init_VFXParticles = __esm({
|
|
|
5735
5712
|
activeCollision
|
|
5736
5713
|
]
|
|
5737
5714
|
);
|
|
5738
|
-
const frictionIntensityRange =
|
|
5715
|
+
const frictionIntensityRange = useMemo2(() => {
|
|
5739
5716
|
if (typeof friction === "object" && friction !== null && "intensity" in friction) {
|
|
5740
5717
|
return toRange(friction.intensity, [0, 0]);
|
|
5741
5718
|
}
|
|
5742
5719
|
return [0, 0];
|
|
5743
5720
|
}, [friction]);
|
|
5744
|
-
const frictionEasingType =
|
|
5721
|
+
const frictionEasingType = useMemo2(() => {
|
|
5745
5722
|
var _a2;
|
|
5746
5723
|
if (typeof friction === "object" && friction !== null && "easing" in friction) {
|
|
5747
5724
|
return easingToType((_a2 = friction.easing) != null ? _a2 : "linear");
|
|
5748
5725
|
}
|
|
5749
5726
|
return 0;
|
|
5750
5727
|
}, [friction]);
|
|
5751
|
-
const startColors =
|
|
5728
|
+
const startColors = useMemo2(() => {
|
|
5752
5729
|
const colors = colorStart.slice(0, 8).map(hexToRgb);
|
|
5753
5730
|
while (colors.length < 8)
|
|
5754
5731
|
colors.push(colors[colors.length - 1] || [1, 1, 1]);
|
|
5755
5732
|
return colors;
|
|
5756
5733
|
}, [colorStart]);
|
|
5757
5734
|
const effectiveColorEnd = colorEnd != null ? colorEnd : colorStart;
|
|
5758
|
-
const endColors =
|
|
5735
|
+
const endColors = useMemo2(() => {
|
|
5759
5736
|
const colors = effectiveColorEnd.slice(0, 8).map(hexToRgb);
|
|
5760
5737
|
while (colors.length < 8)
|
|
5761
5738
|
colors.push(colors[colors.length - 1] || [1, 1, 1]);
|
|
5762
5739
|
return colors;
|
|
5763
5740
|
}, [effectiveColorEnd]);
|
|
5764
|
-
const uniforms =
|
|
5741
|
+
const uniforms = useMemo2(
|
|
5765
5742
|
() => {
|
|
5766
5743
|
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
5767
5744
|
return {
|
|
@@ -6060,7 +6037,7 @@ var init_VFXParticles = __esm({
|
|
|
6060
6037
|
orientAxis,
|
|
6061
6038
|
stretchBySpeed
|
|
6062
6039
|
]);
|
|
6063
|
-
const storage =
|
|
6040
|
+
const storage = useMemo2(() => {
|
|
6064
6041
|
const arrays = {
|
|
6065
6042
|
positions: instancedArray(activeMaxParticles, "vec3"),
|
|
6066
6043
|
velocities: instancedArray(activeMaxParticles, "vec3"),
|
|
@@ -6085,15 +6062,15 @@ var init_VFXParticles = __esm({
|
|
|
6085
6062
|
activeFeatures.needsRotation,
|
|
6086
6063
|
activeFeatures.needsPerParticleColor
|
|
6087
6064
|
]);
|
|
6088
|
-
const computeInit =
|
|
6065
|
+
const computeInit = useMemo2(
|
|
6089
6066
|
() => createInitCompute(storage, activeMaxParticles),
|
|
6090
6067
|
[storage, activeMaxParticles]
|
|
6091
6068
|
);
|
|
6092
|
-
const computeSpawn =
|
|
6069
|
+
const computeSpawn = useMemo2(
|
|
6093
6070
|
() => createSpawnCompute(storage, uniforms, activeMaxParticles),
|
|
6094
6071
|
[storage, uniforms, activeMaxParticles]
|
|
6095
6072
|
);
|
|
6096
|
-
const computeUpdate =
|
|
6073
|
+
const computeUpdate = useMemo2(
|
|
6097
6074
|
() => createUpdateCompute(
|
|
6098
6075
|
storage,
|
|
6099
6076
|
uniforms,
|
|
@@ -6109,7 +6086,7 @@ var init_VFXParticles = __esm({
|
|
|
6109
6086
|
),
|
|
6110
6087
|
[storage, uniforms, curveTexture, activeMaxParticles, activeFeatures]
|
|
6111
6088
|
);
|
|
6112
|
-
const material =
|
|
6089
|
+
const material = useMemo2(
|
|
6113
6090
|
() => createParticleMaterial(storage, uniforms, curveTexture, {
|
|
6114
6091
|
alphaMap,
|
|
6115
6092
|
flipbook,
|
|
@@ -6146,7 +6123,7 @@ var init_VFXParticles = __esm({
|
|
|
6146
6123
|
activeShadow
|
|
6147
6124
|
]
|
|
6148
6125
|
);
|
|
6149
|
-
const renderObject =
|
|
6126
|
+
const renderObject = useMemo2(() => {
|
|
6150
6127
|
if (activeGeometry) {
|
|
6151
6128
|
const mesh = new THREE2.InstancedMesh(
|
|
6152
6129
|
activeGeometry,
|
|
@@ -6358,7 +6335,7 @@ var init_VFXParticles = __esm({
|
|
|
6358
6335
|
nextIndex.current = 0;
|
|
6359
6336
|
};
|
|
6360
6337
|
}, []);
|
|
6361
|
-
const particleAPI =
|
|
6338
|
+
const particleAPI = useMemo2(
|
|
6362
6339
|
() => ({
|
|
6363
6340
|
spawn,
|
|
6364
6341
|
start,
|
|
@@ -7148,7 +7125,7 @@ export {
|
|
|
7148
7125
|
VFXEmitter,
|
|
7149
7126
|
VFXParticles,
|
|
7150
7127
|
bakeCurveToArray,
|
|
7151
|
-
|
|
7128
|
+
createCombinedCurveTexture3 as createCombinedCurveTexture,
|
|
7152
7129
|
useCurveTextureAsync,
|
|
7153
7130
|
useVFXEmitter,
|
|
7154
7131
|
useVFXStore
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "r3f-vfx",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"prepublishOnly": "bun run copy-readme"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"core-vfx": "0.0.
|
|
27
|
+
"core-vfx": "0.0.6",
|
|
28
28
|
"zustand": "5.0.10"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
package/dist/curveWorker.d.ts
DELETED
package/dist/curveWorker.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
// src/curveWorker.js
|
|
2
|
-
var CURVE_RESOLUTION = 256;
|
|
3
|
-
var evaluateBezierSegment = (t, p0, p1, h0Out, h1In) => {
|
|
4
|
-
const cp0 = p0;
|
|
5
|
-
const cp1 = [p0[0] + ((h0Out == null ? void 0 : h0Out[0]) || 0), p0[1] + ((h0Out == null ? void 0 : h0Out[1]) || 0)];
|
|
6
|
-
const cp2 = [p1[0] + ((h1In == null ? void 0 : h1In[0]) || 0), p1[1] + ((h1In == null ? void 0 : h1In[1]) || 0)];
|
|
7
|
-
const cp3 = p1;
|
|
8
|
-
const mt = 1 - t;
|
|
9
|
-
const mt2 = mt * mt;
|
|
10
|
-
const mt3 = mt2 * mt;
|
|
11
|
-
const t2 = t * t;
|
|
12
|
-
const t3 = t2 * t;
|
|
13
|
-
return [
|
|
14
|
-
mt3 * cp0[0] + 3 * mt2 * t * cp1[0] + 3 * mt * t2 * cp2[0] + t3 * cp3[0],
|
|
15
|
-
mt3 * cp0[1] + 3 * mt2 * t * cp1[1] + 3 * mt * t2 * cp2[1] + t3 * cp3[1]
|
|
16
|
-
];
|
|
17
|
-
};
|
|
18
|
-
var sampleCurveAtX = (x, points) => {
|
|
19
|
-
var _a, _b, _c, _d;
|
|
20
|
-
if (!points || points.length < 2) return x;
|
|
21
|
-
if (!((_a = points[0]) == null ? void 0 : _a.pos) || !((_b = points[points.length - 1]) == null ? void 0 : _b.pos)) return x;
|
|
22
|
-
let segmentIdx = 0;
|
|
23
|
-
for (let i = 0; i < points.length - 1; i++) {
|
|
24
|
-
if (((_c = points[i]) == null ? void 0 : _c.pos) && ((_d = points[i + 1]) == null ? void 0 : _d.pos) && x >= points[i].pos[0] && x <= points[i + 1].pos[0]) {
|
|
25
|
-
segmentIdx = i;
|
|
26
|
-
break;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
const p0 = points[segmentIdx];
|
|
30
|
-
const p1 = points[segmentIdx + 1];
|
|
31
|
-
if (!(p0 == null ? void 0 : p0.pos) || !(p1 == null ? void 0 : p1.pos)) return x;
|
|
32
|
-
let tLow = 0;
|
|
33
|
-
let tHigh = 1;
|
|
34
|
-
let t = 0.5;
|
|
35
|
-
for (let iter = 0; iter < 20; iter++) {
|
|
36
|
-
const [px] = evaluateBezierSegment(
|
|
37
|
-
t,
|
|
38
|
-
p0.pos,
|
|
39
|
-
p1.pos,
|
|
40
|
-
p0.handleOut,
|
|
41
|
-
p1.handleIn
|
|
42
|
-
);
|
|
43
|
-
if (Math.abs(px - x) < 1e-4) break;
|
|
44
|
-
if (px < x) {
|
|
45
|
-
tLow = t;
|
|
46
|
-
} else {
|
|
47
|
-
tHigh = t;
|
|
48
|
-
}
|
|
49
|
-
t = (tLow + tHigh) / 2;
|
|
50
|
-
}
|
|
51
|
-
const [, py] = evaluateBezierSegment(
|
|
52
|
-
t,
|
|
53
|
-
p0.pos,
|
|
54
|
-
p1.pos,
|
|
55
|
-
p0.handleOut,
|
|
56
|
-
p1.handleIn
|
|
57
|
-
);
|
|
58
|
-
return Math.max(-0.5, Math.min(1.5, py));
|
|
59
|
-
};
|
|
60
|
-
var bakeCurveToArray = (curveData) => {
|
|
61
|
-
const data = new Float32Array(CURVE_RESOLUTION);
|
|
62
|
-
if (!(curveData == null ? void 0 : curveData.points) || !Array.isArray(curveData.points) || curveData.points.length < 2) {
|
|
63
|
-
for (let i = 0; i < CURVE_RESOLUTION; i++) {
|
|
64
|
-
data[i] = 1 - i / (CURVE_RESOLUTION - 1);
|
|
65
|
-
}
|
|
66
|
-
return data;
|
|
67
|
-
}
|
|
68
|
-
const firstPoint = curveData.points[0];
|
|
69
|
-
const lastPoint = curveData.points[curveData.points.length - 1];
|
|
70
|
-
if (!(firstPoint == null ? void 0 : firstPoint.pos) || !(lastPoint == null ? void 0 : lastPoint.pos) || !Array.isArray(firstPoint.pos) || !Array.isArray(lastPoint.pos)) {
|
|
71
|
-
for (let i = 0; i < CURVE_RESOLUTION; i++) {
|
|
72
|
-
data[i] = 1 - i / (CURVE_RESOLUTION - 1);
|
|
73
|
-
}
|
|
74
|
-
return data;
|
|
75
|
-
}
|
|
76
|
-
for (let i = 0; i < CURVE_RESOLUTION; i++) {
|
|
77
|
-
const x = i / (CURVE_RESOLUTION - 1);
|
|
78
|
-
data[i] = sampleCurveAtX(x, curveData.points);
|
|
79
|
-
}
|
|
80
|
-
return data;
|
|
81
|
-
};
|
|
82
|
-
var bakeCombinedCurves = (sizeCurve, opacityCurve, velocityCurve, rotationSpeedCurve) => {
|
|
83
|
-
const sizeData = bakeCurveToArray(sizeCurve);
|
|
84
|
-
const opacityData = bakeCurveToArray(opacityCurve);
|
|
85
|
-
const velocityData = bakeCurveToArray(velocityCurve);
|
|
86
|
-
const rotationSpeedData = bakeCurveToArray(rotationSpeedCurve);
|
|
87
|
-
const rgba = new Float32Array(CURVE_RESOLUTION * 4);
|
|
88
|
-
for (let i = 0; i < CURVE_RESOLUTION; i++) {
|
|
89
|
-
rgba[i * 4] = sizeData[i];
|
|
90
|
-
rgba[i * 4 + 1] = opacityData[i];
|
|
91
|
-
rgba[i * 4 + 2] = velocityData[i];
|
|
92
|
-
rgba[i * 4 + 3] = rotationSpeedData[i];
|
|
93
|
-
}
|
|
94
|
-
return rgba;
|
|
95
|
-
};
|
|
96
|
-
self.onmessage = (e) => {
|
|
97
|
-
const { id, sizeCurve, opacityCurve, velocityCurve, rotationSpeedCurve } = e.data;
|
|
98
|
-
const rgba = bakeCombinedCurves(
|
|
99
|
-
sizeCurve,
|
|
100
|
-
opacityCurve,
|
|
101
|
-
velocityCurve,
|
|
102
|
-
rotationSpeedCurve
|
|
103
|
-
);
|
|
104
|
-
self.postMessage({ id, rgba }, [rgba.buffer]);
|
|
105
|
-
};
|