sparcoon 0.5.0 → 0.6.1
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/README.md +6 -6
- package/dist/emitter/FXEmitter.Internal.d.ts +50 -2
- package/dist/emitter/FXEmitter.Internal.js +1 -2
- package/dist/emitter/FXEmitter.d.ts +48 -1
- package/dist/emitter/FXEmitter.js +74 -11
- package/dist/emitter/behavior/FXBehavior.d.ts +12 -2
- package/dist/emitter/behavior/FXBehavior.js +3 -2
- package/dist/emitter/behavior/FXBehaviorDirectionalForce.d.ts +25 -0
- package/dist/emitter/behavior/FXBehaviorDirectionalForce.js +74 -0
- package/dist/emitter/behavior/FXBehaviorPointForce.d.ts +40 -0
- package/dist/emitter/behavior/FXBehaviorPointForce.js +98 -0
- package/dist/emitter/behavior/FXBehaviorScaleOverLife.d.ts +9 -8
- package/dist/emitter/behavior/FXBehaviorScaleOverLife.js +12 -29
- package/dist/emitter/behavior/FXBehaviorTorqueDamping.d.ts +4 -3
- package/dist/emitter/behavior/FXBehaviorTorqueDamping.js +3 -2
- package/dist/emitter/behavior/FXBehaviorTorqueNoise.d.ts +4 -3
- package/dist/emitter/behavior/FXBehaviorTorqueNoise.js +3 -2
- package/dist/emitter/behavior/FXBehaviorTorqueOverLife.d.ts +17 -0
- package/dist/emitter/behavior/FXBehaviorTorqueOverLife.js +34 -0
- package/dist/emitter/behavior/FXBehaviorVelocityDamping.d.ts +3 -2
- package/dist/emitter/behavior/FXBehaviorVelocityDamping.js +3 -2
- package/dist/emitter/behavior/FXBehaviorVelocityNoise.d.ts +6 -5
- package/dist/emitter/behavior/FXBehaviorVelocityNoise.js +6 -5
- package/dist/emitter/behavior/FXBehaviorVelocityOverLife.d.ts +20 -0
- package/dist/emitter/behavior/FXBehaviorVelocityOverLife.js +48 -0
- package/dist/emitter/spawn/FXSpawn.d.ts +4 -2
- package/dist/emitter/spawn/FXSpawn.js +3 -2
- package/dist/emitter/spawn/FXSpawnBox.d.ts +8 -16
- package/dist/emitter/spawn/FXSpawnBox.js +23 -39
- package/dist/emitter/spawn/{FXSpawnRandomLifetime.d.ts → FXSpawnLifetime.d.ts} +3 -5
- package/dist/emitter/spawn/{FXSpawnRandomLifetime.js → FXSpawnLifetime.js} +8 -10
- package/dist/emitter/spawn/FXSpawnOffset.d.ts +9 -0
- package/dist/emitter/spawn/FXSpawnOffset.js +9 -0
- package/dist/emitter/spawn/FXSpawnPoint.d.ts +8 -0
- package/dist/emitter/spawn/FXSpawnPoint.js +8 -0
- package/dist/emitter/spawn/{FXSpawnRandomRotation.d.ts → FXSpawnRotation.d.ts} +3 -5
- package/dist/emitter/spawn/{FXSpawnRandomRotation.js → FXSpawnRotation.js} +8 -10
- package/dist/emitter/spawn/{FXSpawnRandomScale.d.ts → FXSpawnScale.d.ts} +4 -6
- package/dist/emitter/spawn/{FXSpawnRandomScale.js → FXSpawnScale.js} +12 -14
- package/dist/emitter/spawn/FXSpawnSphere.d.ts +11 -6
- package/dist/emitter/spawn/FXSpawnSphere.js +11 -6
- package/dist/emitter/spawn/{FXSpawnRandomTorque.d.ts → FXSpawnTorque.d.ts} +3 -5
- package/dist/emitter/spawn/{FXSpawnRandomTorque.js → FXSpawnTorque.js} +8 -10
- package/dist/emitter/spawn/FXSpawnVelocity.d.ts +32 -0
- package/dist/emitter/spawn/{FXSpawnRandomVelocity.js → FXSpawnVelocity.js} +26 -11
- package/dist/index.d.ts +23 -16
- package/dist/index.js +20 -16
- package/dist/materials/FXDiffuseMaterial/FXDiffuseMaterial.Internal.d.ts +4 -4
- package/dist/materials/FXDiffuseMaterial/FXDiffuseMaterial.Internal.js +2 -2
- package/dist/materials/FXDiffuseMaterial/FXDiffuseMaterial.d.ts +55 -5
- package/dist/materials/FXDiffuseMaterial/FXDiffuseMaterial.js +9 -2
- package/dist/materials/FXMaterial/FXDepthMaterial.Internal.d.ts +3 -3
- package/dist/materials/FXMaterial/FXDistanceMaterial.Internal.d.ts +3 -3
- package/dist/materials/FXMaterial/FXMaterial.d.ts +51 -5
- package/dist/materials/FXMaterial/FXMaterial.js +5 -0
- package/dist/materials/FXUnlitMaterial/FXUnlitMaterial.Internal.d.ts +3 -3
- package/dist/materials/FXUnlitMaterial/FXUnlitMaterial.d.ts +3 -3
- package/dist/materials/FXUnlitMaterial/FXUnlitMaterial.js +3 -3
- package/dist/miscellaneous/curve/FXCurve1D.Internal.d.ts +20 -0
- package/dist/miscellaneous/curve/FXCurve1D.d.ts +17 -0
- package/dist/miscellaneous/curve/FXCurve1D.js +94 -0
- package/dist/miscellaneous/miscellaneous.d.ts +3 -1
- package/dist/miscellaneous/miscellaneous.js +8 -4
- package/dist/miscellaneous/texture/FXTextureView.Internal.js +6 -0
- package/dist/miscellaneous/texture/FXTextureView.js +234 -0
- package/dist/nodes/color/FXNodeColor.d.ts +7 -0
- package/dist/nodes/color/FXNodeColor.js +11 -0
- package/dist/nodes/color/FXNodeColorOverLife.d.ts +25 -0
- package/dist/nodes/color/FXNodeColorOverLife.js +60 -0
- package/dist/nodes/color/FXNodeSphericalClip.d.ts +18 -0
- package/dist/nodes/color/FXNodeSphericalClip.js +45 -0
- package/dist/nodes/normal/FXNodeFlatNormal.d.ts +7 -0
- package/dist/nodes/normal/FXNodeFlatNormal.js +17 -0
- package/dist/nodes/normal/FXNodeNormal.d.ts +7 -0
- package/dist/nodes/normal/FXNodeNormal.js +7 -0
- package/dist/nodes/normal/FXNodeSphericalNormal.d.ts +7 -0
- package/dist/nodes/normal/{FXSphericalNormalNode.js → FXNodeSphericalNormal.js} +7 -4
- package/dist/nodes/texture/FXNodeAnimatedTexture.d.ts +47 -0
- package/dist/nodes/texture/FXNodeAnimatedTexture.js +137 -0
- package/dist/nodes/texture/FXNodeStaticTexture.d.ts +18 -0
- package/dist/nodes/texture/FXNodeStaticTexture.js +60 -0
- package/dist/nodes/texture/FXNodeTexture.d.ts +7 -0
- package/dist/nodes/texture/FXNodeTexture.js +11 -0
- package/package.json +2 -4
- package/dist/emitter/behavior/FXBehaviorDirectionalGravity.d.ts +0 -21
- package/dist/emitter/behavior/FXBehaviorDirectionalGravity.js +0 -51
- package/dist/emitter/behavior/FXBehaviorPointGravity.d.ts +0 -39
- package/dist/emitter/behavior/FXBehaviorPointGravity.js +0 -116
- package/dist/emitter/spawn/FXSpawnRandomVelocity.d.ts +0 -17
- package/dist/nodes/color/FXColorNode.d.ts +0 -3
- package/dist/nodes/color/FXColorNode.js +0 -8
- package/dist/nodes/color/FXColorOverLifeNode.d.ts +0 -6
- package/dist/nodes/color/FXColorOverLifeNode.js +0 -44
- package/dist/nodes/color/FXSphericalClipNode.d.ts +0 -5
- package/dist/nodes/color/FXSphericalClipNode.js +0 -30
- package/dist/nodes/normal/FXFlatNormalNode.d.ts +0 -4
- package/dist/nodes/normal/FXFlatNormalNode.js +0 -14
- package/dist/nodes/normal/FXNormalNode.d.ts +0 -3
- package/dist/nodes/normal/FXNormalNode.js +0 -4
- package/dist/nodes/normal/FXSphericalNormalNode.d.ts +0 -4
- package/dist/nodes/texture/FXAnimatedTextureNode.d.ts +0 -12
- package/dist/nodes/texture/FXAnimatedTextureNode.js +0 -88
- package/dist/nodes/texture/FXStaticTextureNode.d.ts +0 -6
- package/dist/nodes/texture/FXStaticTextureNode.js +0 -34
- package/dist/nodes/texture/FXTextureNode.d.ts +0 -3
- package/dist/nodes/texture/FXTextureNode.js +0 -8
|
@@ -1,24 +1,74 @@
|
|
|
1
1
|
import type { ColorRepresentation } from "three";
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
2
|
+
import type { FXNodeColor } from "../../nodes/color/FXNodeColor";
|
|
3
|
+
import type { FXNodeNormal } from "../../nodes/normal/FXNodeNormal";
|
|
4
|
+
import type { FXNodeTexture } from "../../nodes/texture/FXNodeTexture";
|
|
5
5
|
import type { FXMaterialOptions } from "../FXMaterial/FXMaterial";
|
|
6
6
|
import { FXMaterial } from "../FXMaterial/FXMaterial";
|
|
7
|
+
/**
|
|
8
|
+
* Configuration options for {@link FXDiffuseMaterial}
|
|
9
|
+
*/
|
|
7
10
|
export interface FXDiffuseMaterialOptions extends FXMaterialOptions {
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Normal nodes for lighting; multiple nodes are blended together
|
|
13
|
+
*
|
|
14
|
+
* @defaultValue `[new FXNodeSphericalNormal()]`
|
|
15
|
+
*/
|
|
16
|
+
normalNodes: (FXNodeTexture | FXNodeNormal)[];
|
|
17
|
+
/**
|
|
18
|
+
* Emission color nodes composited for emissive output
|
|
19
|
+
*
|
|
20
|
+
* @defaultValue `[]`
|
|
21
|
+
*/
|
|
22
|
+
emissionNodes: (FXNodeColor | FXNodeTexture)[];
|
|
23
|
+
/**
|
|
24
|
+
* Enable subsurface scattering approximation
|
|
25
|
+
*
|
|
26
|
+
* @defaultValue `false`
|
|
27
|
+
*/
|
|
10
28
|
enableScatter: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Tint color applied to the scatter contribution
|
|
31
|
+
*
|
|
32
|
+
* @defaultValue `0xffd999`
|
|
33
|
+
*/
|
|
11
34
|
scatterTint: ColorRepresentation;
|
|
35
|
+
/**
|
|
36
|
+
* Scatter lobe sharpness; higher values produce a tighter highlight
|
|
37
|
+
*
|
|
38
|
+
* @defaultValue `10`
|
|
39
|
+
*/
|
|
12
40
|
scatterPower: number;
|
|
41
|
+
/**
|
|
42
|
+
* Forward scatter intensity (light-facing side)
|
|
43
|
+
*
|
|
44
|
+
* @defaultValue `1`
|
|
45
|
+
*/
|
|
13
46
|
forwardScatterStrength: number;
|
|
47
|
+
/**
|
|
48
|
+
* Back scatter intensity (back-lit side)
|
|
49
|
+
*
|
|
50
|
+
* @defaultValue `1`
|
|
51
|
+
*/
|
|
14
52
|
backScatterStrength: number;
|
|
53
|
+
/**
|
|
54
|
+
* Shadow influence (`0` = no shadows, `1` = full shadows)
|
|
55
|
+
*
|
|
56
|
+
* @defaultValue `1`
|
|
57
|
+
*/
|
|
15
58
|
shadowSensitivity: number;
|
|
16
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Diffuse particle material with lighting, normals, emission, and optional subsurface scattering
|
|
62
|
+
*/
|
|
17
63
|
export declare class FXDiffuseMaterial extends FXMaterial {
|
|
18
64
|
private readonly normalNodes;
|
|
19
65
|
private readonly emissionNodes;
|
|
20
66
|
private readonly scatterUniforms;
|
|
21
67
|
private readonly shadowSensitivity;
|
|
68
|
+
/**
|
|
69
|
+
* @param options - Material configuration
|
|
70
|
+
*/
|
|
22
71
|
constructor(options?: Partial<FXDiffuseMaterialOptions>);
|
|
72
|
+
/** Releases resources held by all albedo, normal, and emission nodes */
|
|
23
73
|
destroy(): void;
|
|
24
74
|
}
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import { FXColor } from '../../miscellaneous/color/FXColor.js';
|
|
2
|
-
import {
|
|
2
|
+
import { FXNodeSphericalNormal } from '../../nodes/normal/FXNodeSphericalNormal.js';
|
|
3
3
|
import { FXMaterial } from '../FXMaterial/FXMaterial.js';
|
|
4
4
|
import { buildFXDiffuseMaterial } from './FXDiffuseMaterial.Internal.js';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Diffuse particle material with lighting, normals, emission, and optional subsurface scattering
|
|
8
|
+
*/
|
|
6
9
|
class FXDiffuseMaterial extends FXMaterial {
|
|
10
|
+
/**
|
|
11
|
+
* @param options - Material configuration
|
|
12
|
+
*/
|
|
7
13
|
constructor(options = {}) {
|
|
8
14
|
super(options);
|
|
9
|
-
this._private_normalNodes = options.normalNodes ?? [new
|
|
15
|
+
this._private_normalNodes = options.normalNodes ?? [new FXNodeSphericalNormal()];
|
|
10
16
|
this._private_emissionNodes = options.emissionNodes ?? [];
|
|
11
17
|
this._private_scatterUniforms =
|
|
12
18
|
options.enableScatter === true
|
|
@@ -23,6 +29,7 @@ class FXDiffuseMaterial extends FXMaterial {
|
|
|
23
29
|
: undefined;
|
|
24
30
|
this._private_shadowSensitivity = { value: options.shadowSensitivity ?? 1 };
|
|
25
31
|
}
|
|
32
|
+
/** Releases resources held by all albedo, normal, and emission nodes */
|
|
26
33
|
destroy() {
|
|
27
34
|
super.destroy();
|
|
28
35
|
for (const node of this._private_normalNodes) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { MeshDepthMaterial } from "three";
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
export declare function buildDepthMaterial(albedoNodes: readonly (
|
|
2
|
+
import type { FXNodeColor } from "../../nodes/color/FXNodeColor";
|
|
3
|
+
import type { FXNodeTexture } from "../../nodes/texture/FXNodeTexture";
|
|
4
|
+
export declare function buildDepthMaterial(albedoNodes: readonly (FXNodeColor | FXNodeTexture)[], depthAlphaTest: number, useDepthAlphaHash: boolean, useSphericalDepth: boolean): MeshDepthMaterial;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { MeshDistanceMaterial } from "three";
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
export declare function buildDistanceMaterial(albedoNodes: readonly (
|
|
2
|
+
import type { FXNodeColor } from "../../nodes/color/FXNodeColor";
|
|
3
|
+
import type { FXNodeTexture } from "../../nodes/texture/FXNodeTexture";
|
|
4
|
+
export declare function buildDistanceMaterial(albedoNodes: readonly (FXNodeColor | FXNodeTexture)[], distanceAlphaTest: number, useDistanceAlphaHash: boolean, useSphericalDepth: boolean): MeshDistanceMaterial;
|
|
@@ -1,21 +1,67 @@
|
|
|
1
|
-
import type { Blending
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
1
|
+
import type { Blending } from "three";
|
|
2
|
+
import type { FXNodeColor } from "../../nodes/color/FXNodeColor";
|
|
3
|
+
import type { FXNodeTexture } from "../../nodes/texture/FXNodeTexture";
|
|
4
|
+
/**
|
|
5
|
+
* Configuration options shared by all {@link FXMaterial} subclasses
|
|
6
|
+
*/
|
|
4
7
|
export interface FXMaterialOptions {
|
|
5
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Color and texture nodes composited for particle color
|
|
10
|
+
*
|
|
11
|
+
* @defaultValue `[]`
|
|
12
|
+
*/
|
|
13
|
+
albedoNodes: (FXNodeColor | FXNodeTexture)[];
|
|
14
|
+
/**
|
|
15
|
+
* Three.js blending mode
|
|
16
|
+
*
|
|
17
|
+
* @defaultValue `NormalBlending`
|
|
18
|
+
*/
|
|
6
19
|
blending: Blending;
|
|
20
|
+
/**
|
|
21
|
+
* Use alpha hashing instead of standard transparency
|
|
22
|
+
*
|
|
23
|
+
* @defaultValue `false`
|
|
24
|
+
*/
|
|
7
25
|
useAlphaHashing: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Alpha cutoff threshold for color passes
|
|
28
|
+
*
|
|
29
|
+
* @defaultValue `0.0075`
|
|
30
|
+
*/
|
|
8
31
|
alphaTest: number;
|
|
32
|
+
/**
|
|
33
|
+
* Alpha cutoff threshold for depth and shadow passes
|
|
34
|
+
*
|
|
35
|
+
* @defaultValue `0.5`
|
|
36
|
+
*/
|
|
9
37
|
depthAlphaTest: number;
|
|
38
|
+
/**
|
|
39
|
+
* Use alpha hashing in depth and shadow passes
|
|
40
|
+
*
|
|
41
|
+
* @defaultValue `false`
|
|
42
|
+
*/
|
|
10
43
|
useDepthAlphaHash: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Approximate spherical depth for shadow maps
|
|
46
|
+
*
|
|
47
|
+
* @defaultValue `true`
|
|
48
|
+
*/
|
|
11
49
|
useSphericalDepth: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Use premultiplied alpha blending
|
|
52
|
+
*
|
|
53
|
+
* @defaultValue `true`
|
|
54
|
+
*/
|
|
12
55
|
premultipliedAlpha: boolean;
|
|
13
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Abstract base class for particle materials
|
|
59
|
+
*/
|
|
14
60
|
export declare abstract class FXMaterial {
|
|
15
61
|
private readonly depthAlphaTest;
|
|
16
62
|
private readonly useDepthAlphaHash;
|
|
17
63
|
private readonly useSphericalDepth;
|
|
18
64
|
constructor(options?: Partial<FXMaterialOptions>);
|
|
65
|
+
/** Releases resources held by all albedo nodes */
|
|
19
66
|
destroy(): void;
|
|
20
|
-
buildDistanceMaterial(): MeshDistanceMaterial;
|
|
21
67
|
}
|
|
@@ -2,6 +2,9 @@ import { NormalBlending } from 'three';
|
|
|
2
2
|
import { buildDepthMaterial } from './FXDepthMaterial.Internal.js';
|
|
3
3
|
import { buildDistanceMaterial } from './FXDistanceMaterial.Internal.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Abstract base class for particle materials
|
|
7
|
+
*/
|
|
5
8
|
class FXMaterial {
|
|
6
9
|
constructor(options = {}) {
|
|
7
10
|
this.albedoNodes = options.albedoNodes ?? [];
|
|
@@ -14,6 +17,7 @@ class FXMaterial {
|
|
|
14
17
|
this._private_useDepthAlphaHash = options.useDepthAlphaHash ?? false;
|
|
15
18
|
this._private_useSphericalDepth = options.useSphericalDepth ?? true;
|
|
16
19
|
}
|
|
20
|
+
/** Releases resources held by all albedo nodes */
|
|
17
21
|
destroy() {
|
|
18
22
|
for (const node of this.albedoNodes) {
|
|
19
23
|
node.destroy?.();
|
|
@@ -23,6 +27,7 @@ class FXMaterial {
|
|
|
23
27
|
buildDepthMaterial() {
|
|
24
28
|
return buildDepthMaterial(this.albedoNodes, this._private_depthAlphaTest, this._private_useDepthAlphaHash, this._private_useSphericalDepth);
|
|
25
29
|
}
|
|
30
|
+
/** @internal */
|
|
26
31
|
buildDistanceMaterial() {
|
|
27
32
|
return buildDistanceMaterial(this.albedoNodes, this._private_depthAlphaTest, this._private_useDepthAlphaHash, this._private_useSphericalDepth);
|
|
28
33
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Blending } from "three";
|
|
2
2
|
import { MeshBasicMaterial } from "three";
|
|
3
3
|
import type { GLTypeInfo } from "../../instancedParticle/shared";
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
6
|
-
export declare function buildFXUnlitMaterial(varyings: Record<string, GLTypeInfo>, blending: Blending, useAlphaHashing: boolean, alphaTest: number, premultipliedAlpha: boolean, albedoNodes: readonly (
|
|
4
|
+
import type { FXNodeColor } from "../../nodes/color/FXNodeColor";
|
|
5
|
+
import type { FXNodeTexture } from "../../nodes/texture/FXNodeTexture";
|
|
6
|
+
export declare function buildFXUnlitMaterial(varyings: Record<string, GLTypeInfo>, blending: Blending, useAlphaHashing: boolean, alphaTest: number, premultipliedAlpha: boolean, albedoNodes: readonly (FXNodeColor | FXNodeTexture)[]): MeshBasicMaterial;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { FXMaterialOptions } from "../FXMaterial/FXMaterial";
|
|
2
1
|
import { FXMaterial } from "../FXMaterial/FXMaterial";
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Unlit particle material - renders particles without lighting or shadows
|
|
4
|
+
*/
|
|
4
5
|
export declare class FXUnlitMaterial extends FXMaterial {
|
|
5
|
-
constructor(options?: Partial<FXUnlitMaterialOptions>);
|
|
6
6
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { FXMaterial } from '../FXMaterial/FXMaterial.js';
|
|
2
2
|
import { buildFXUnlitMaterial } from './FXUnlitMaterial.Internal.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Unlit particle material - renders particles without lighting or shadows
|
|
6
|
+
*/
|
|
4
7
|
class FXUnlitMaterial extends FXMaterial {
|
|
5
|
-
constructor(options = {}) {
|
|
6
|
-
super(options);
|
|
7
|
-
}
|
|
8
8
|
/** @internal */
|
|
9
9
|
buildThreeMaterial(varyings) {
|
|
10
10
|
return buildFXUnlitMaterial(varyings, this.blending, this.useAlphaHashing, this.alphaTest, this.premultipliedAlpha, this.albedoNodes);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { FXCurve1D } from "./FXCurve1D";
|
|
2
|
+
/** Input point for {@link FXCurve1D}. */
|
|
3
|
+
export interface FXCurve1DPoint<T> {
|
|
4
|
+
/** Output value at this position. */
|
|
5
|
+
value: T;
|
|
6
|
+
/** Normalized position in [0, 1]. */
|
|
7
|
+
position: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Accepts either:
|
|
11
|
+
* - Explicit anchor points ({@link FXCurve1DPoint}\<T>[])
|
|
12
|
+
* - A uniform shorthand (`T[]`) where anchors are distributed evenly across [0, 1]
|
|
13
|
+
* - Another {@link FXCurve1D}\<T> instance to copy anchors from
|
|
14
|
+
*/
|
|
15
|
+
export type FXCurve1DConfig<T> = FXCurve1DPoint<T>[] | T[] | FXCurve1D<T>;
|
|
16
|
+
/** Resolved anchor stored internally by {@link FXCurve1D}. */
|
|
17
|
+
export interface FXCurve1DAnchor<T> {
|
|
18
|
+
readonly value: T;
|
|
19
|
+
readonly position: number;
|
|
20
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FXCurve1DAnchor, FXCurve1DConfig, FXCurve1DPoint } from "./FXCurve1D.Internal";
|
|
2
|
+
export type { FXCurve1DAnchor, FXCurve1DConfig, FXCurve1DPoint };
|
|
3
|
+
/**
|
|
4
|
+
* 1D curve defined by anchor points at explicit normalized positions.
|
|
5
|
+
*
|
|
6
|
+
* Anchors must be strictly ascending by `value`, first must be `0`, last must be `1`.
|
|
7
|
+
* Output at each anchor is a value of type `T` - interpolation is left to the caller.
|
|
8
|
+
*/
|
|
9
|
+
export declare class FXCurve1D<T> {
|
|
10
|
+
private readonly anchorsInternal;
|
|
11
|
+
/**
|
|
12
|
+
* @param config - Explicit anchor points, a uniform shorthand array, or another {@link FXCurve1D} to copy
|
|
13
|
+
*/
|
|
14
|
+
constructor(config: FXCurve1DConfig<T>);
|
|
15
|
+
/** Resolved anchor points ordered ascending by `value`. */
|
|
16
|
+
get anchors(): readonly FXCurve1DAnchor<T>[];
|
|
17
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { assertValidNumber } from '../asserts.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 1D curve defined by anchor points at explicit normalized positions.
|
|
5
|
+
*
|
|
6
|
+
* Anchors must be strictly ascending by `value`, first must be `0`, last must be `1`.
|
|
7
|
+
* Output at each anchor is a value of type `T` - interpolation is left to the caller.
|
|
8
|
+
*/
|
|
9
|
+
class FXCurve1D {
|
|
10
|
+
/**
|
|
11
|
+
* @param config - Explicit anchor points, a uniform shorthand array, or another {@link FXCurve1D} to copy
|
|
12
|
+
*/
|
|
13
|
+
constructor(config) {
|
|
14
|
+
if (config instanceof FXCurve1D) {
|
|
15
|
+
this._private_anchorsInternal = config._private_anchorsInternal.map((anchor) => ({ ...anchor }));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const isPointArray = config.length > 0 &&
|
|
19
|
+
typeof config[0] === "object" &&
|
|
20
|
+
!Array.isArray(config[0]) &&
|
|
21
|
+
"value" in config[0];
|
|
22
|
+
const points = isPointArray
|
|
23
|
+
? config
|
|
24
|
+
: config.map((value, index) => ({
|
|
25
|
+
value,
|
|
26
|
+
position: index / (config.length - 1),
|
|
27
|
+
}));
|
|
28
|
+
if (points.length < 2) {
|
|
29
|
+
throw new Error("FXCurve1D: at least 2 anchor points are required");
|
|
30
|
+
}
|
|
31
|
+
if (points[0].position !== 0) {
|
|
32
|
+
throw new Error(`FXCurve1D: first anchor value must be 0, got ${points[0].position}`);
|
|
33
|
+
}
|
|
34
|
+
if (points[points.length - 1].position !== 1) {
|
|
35
|
+
throw new Error(`FXCurve1D: last anchor value must be 1, got ${points[points.length - 1].position}`);
|
|
36
|
+
}
|
|
37
|
+
this._private_anchorsInternal = [];
|
|
38
|
+
for (let index = 0; index < points.length; index++) {
|
|
39
|
+
const { value, position } = points[index];
|
|
40
|
+
if (position < 0 || position > 1) {
|
|
41
|
+
throw new Error(`FXCurve1D: anchor[${index}].value must be in [0, 1], got ${position}`);
|
|
42
|
+
}
|
|
43
|
+
if (index > 0 && position <= points[index - 1].position) {
|
|
44
|
+
throw new Error(`FXCurve1D: anchor[${index}].value (${position}) must be strictly greater than anchor[${index - 1}].value (${points[index - 1].position})`);
|
|
45
|
+
}
|
|
46
|
+
this._private_anchorsInternal.push({ value, position });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** Resolved anchor points ordered ascending by `value`. */
|
|
50
|
+
get anchors() {
|
|
51
|
+
return this._private_anchorsInternal;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Samples the curve at normalized position `t`.
|
|
55
|
+
*
|
|
56
|
+
* Returns the two bracketing anchor values and the local interpolation factor `t` in [0, 1].
|
|
57
|
+
* The caller is responsible for interpolating between `a` and `b` using `t`.
|
|
58
|
+
*
|
|
59
|
+
* @param t - Normalized position in [0, 1]
|
|
60
|
+
* @internal
|
|
61
|
+
*/
|
|
62
|
+
sample(t) {
|
|
63
|
+
assertValidNumber(t, "FXCurve1D.sample.t");
|
|
64
|
+
const anchors = this._private_anchorsInternal;
|
|
65
|
+
const anchorCount = anchors.length;
|
|
66
|
+
let segmentIndex;
|
|
67
|
+
if (anchorCount < 10) {
|
|
68
|
+
segmentIndex = 0;
|
|
69
|
+
while (segmentIndex < anchorCount - 2 && anchors[segmentIndex + 1].position <= t) {
|
|
70
|
+
segmentIndex++;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
let low = 0;
|
|
75
|
+
let high = anchorCount - 2;
|
|
76
|
+
while (low < high) {
|
|
77
|
+
const mid = (low + high + 1) >> 1;
|
|
78
|
+
if (anchors[mid].position <= t) {
|
|
79
|
+
low = mid;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
high = mid - 1;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
segmentIndex = low;
|
|
86
|
+
}
|
|
87
|
+
const anchorA = anchors[segmentIndex];
|
|
88
|
+
const anchorB = anchors[segmentIndex + 1];
|
|
89
|
+
const localT = (t - anchorA.position) / (anchorB.position - anchorA.position);
|
|
90
|
+
return { a: anchorA.value, b: anchorB.value, t: localT };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export { FXCurve1D };
|
|
@@ -3,6 +3,8 @@ import { DataTexture } from "three";
|
|
|
3
3
|
import type { Vector3Like } from "../miscellaneous/math";
|
|
4
4
|
import type { FXTextureConfig } from "../miscellaneous/texture/FXTextureView.Internal";
|
|
5
5
|
import type { FXColor } from "./color/FXColor";
|
|
6
|
+
import type { FXCurve1D } from "./curve/FXCurve1D";
|
|
7
|
+
export declare function getNextInstanceId(): number;
|
|
6
8
|
export interface FXRange {
|
|
7
9
|
min: number;
|
|
8
10
|
max: number;
|
|
@@ -13,7 +15,7 @@ export type FXAspectConfig = number | FXTextureConfig;
|
|
|
13
15
|
export declare function resolveFXRangeConfig(config: FXRangeConfig): FXRange;
|
|
14
16
|
export declare function resolveFXVector3Config(config: FXVector3Config): Vector3Like;
|
|
15
17
|
export declare function resolveAspect(config: number | FXTextureConfig): number;
|
|
16
|
-
export declare function buildGradientTexture(
|
|
18
|
+
export declare function buildGradientTexture(curve: FXCurve1D<FXColor>): DataTexture;
|
|
17
19
|
export declare const BUILTIN_OFFSET_POSITION_X = 0;
|
|
18
20
|
export declare const BUILTIN_OFFSET_POSITION_Y = 1;
|
|
19
21
|
export declare const BUILTIN_OFFSET_POSITION_Z = 2;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { Texture, DataTexture, RGBAFormat, UnsignedByteType, UVMapping, ClampToEdgeWrapping, LinearFilter, SRGBColorSpace } from 'three';
|
|
2
2
|
|
|
3
|
+
let nextInstanceId = 0;
|
|
4
|
+
function getNextInstanceId() {
|
|
5
|
+
return nextInstanceId++;
|
|
6
|
+
}
|
|
3
7
|
function resolveFXRangeConfig(config) {
|
|
4
8
|
if (typeof config === "number") {
|
|
5
9
|
return { min: config, max: config };
|
|
@@ -27,12 +31,12 @@ function resolveAspect(config) {
|
|
|
27
31
|
}
|
|
28
32
|
return config.sourceSize.w / config.sourceSize.h;
|
|
29
33
|
}
|
|
30
|
-
function buildGradientTexture(
|
|
31
|
-
const width =
|
|
34
|
+
function buildGradientTexture(curve) {
|
|
35
|
+
const width = curve.anchors.length;
|
|
32
36
|
const height = 1;
|
|
33
37
|
const data = new Uint8Array(width * height * 4);
|
|
34
38
|
for (let i = 0; i < width; i++) {
|
|
35
|
-
const color =
|
|
39
|
+
const color = curve.anchors[i].value;
|
|
36
40
|
const index = i * 4;
|
|
37
41
|
data[index] = Math.round(color.r * 255);
|
|
38
42
|
data[index + 1] = Math.round(color.g * 255);
|
|
@@ -82,4 +86,4 @@ const PARTICLE_DEFINES = `
|
|
|
82
86
|
#define PARTICLE_RANDOM_C p_builtin[3][3]
|
|
83
87
|
`;
|
|
84
88
|
|
|
85
|
-
export { BUILTIN_OFFSET_AGE, BUILTIN_OFFSET_LIFETIME, BUILTIN_OFFSET_POSITION_X, BUILTIN_OFFSET_POSITION_Y, BUILTIN_OFFSET_POSITION_Z, BUILTIN_OFFSET_RANDOM_A, BUILTIN_OFFSET_RANDOM_B, BUILTIN_OFFSET_RANDOM_C, BUILTIN_OFFSET_ROTATION, BUILTIN_OFFSET_SCALE_X, BUILTIN_OFFSET_SCALE_Y, BUILTIN_OFFSET_TORQUE, BUILTIN_OFFSET_VELOCITY_X, BUILTIN_OFFSET_VELOCITY_Y, BUILTIN_OFFSET_VELOCITY_Z, PARTICLE_DEFINES, buildGradientTexture, resolveAspect, resolveFXRangeConfig, resolveFXVector3Config };
|
|
89
|
+
export { BUILTIN_OFFSET_AGE, BUILTIN_OFFSET_LIFETIME, BUILTIN_OFFSET_POSITION_X, BUILTIN_OFFSET_POSITION_Y, BUILTIN_OFFSET_POSITION_Z, BUILTIN_OFFSET_RANDOM_A, BUILTIN_OFFSET_RANDOM_B, BUILTIN_OFFSET_RANDOM_C, BUILTIN_OFFSET_ROTATION, BUILTIN_OFFSET_SCALE_X, BUILTIN_OFFSET_SCALE_Y, BUILTIN_OFFSET_TORQUE, BUILTIN_OFFSET_VELOCITY_X, BUILTIN_OFFSET_VELOCITY_Y, BUILTIN_OFFSET_VELOCITY_Z, PARTICLE_DEFINES, buildGradientTexture, getNextInstanceId, resolveAspect, resolveFXRangeConfig, resolveFXVector3Config };
|