@woosh/meep-engine 3.14.3 → 3.14.5
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/package.json +1 -1
- package/src/core/geom/3d/mat4/m4_rigidity_defect.d.ts +30 -0
- package/src/core/geom/3d/mat4/m4_rigidity_defect.d.ts.map +1 -0
- package/src/core/geom/3d/mat4/m4_rigidity_defect.js +71 -0
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +733 -726
- package/src/engine/network/NetworkSession.d.ts +24 -4
- package/src/engine/network/NetworkSession.d.ts.map +1 -1
- package/src/engine/network/NetworkSession.js +28 -4
- package/src/engine/network/orchestrator/NetworkPeer.d.ts +96 -7
- package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/NetworkPeer.js +392 -68
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts +6 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +6 -0
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts +105 -13
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +306 -59
- package/src/engine/network/replication/Replicator.d.ts +43 -7
- package/src/engine/network/replication/Replicator.d.ts.map +1 -1
- package/src/engine/network/replication/Replicator.js +309 -111
- package/src/engine/network/sim/ActionLog.d.ts +23 -3
- package/src/engine/network/sim/ActionLog.d.ts.map +1 -1
- package/src/engine/network/sim/ActionLog.js +26 -3
- package/src/engine/network/sim/ActionRecordCursor.d.ts +82 -0
- package/src/engine/network/sim/ActionRecordCursor.d.ts.map +1 -0
- package/src/engine/network/sim/ActionRecordCursor.js +120 -0
- package/src/engine/network/sim/RewindEngine.d.ts.map +1 -1
- package/src/engine/network/sim/RewindEngine.js +13 -29
- package/src/engine/network/sim/SimAction.d.ts +15 -0
- package/src/engine/network/sim/SimAction.d.ts.map +1 -1
- package/src/engine/network/sim/SimAction.js +15 -0
- package/src/engine/network/sim/SimActionExecutor.d.ts +51 -2
- package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
- package/src/engine/network/sim/SimActionExecutor.js +74 -7
- package/src/engine/network/transport/Channel.d.ts +1 -1
- package/src/engine/network/transport/Channel.js +1 -1
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/simulation/Ticker.d.ts.map +1 -1
- package/src/engine/simulation/Ticker.js +4 -1
- package/src/engine/ui/GUIEngine.d.ts.map +1 -1
- package/src/engine/ui/GUIEngine.js +6 -0
- package/src/shade/playground/particle_system/README.md +98 -0
- package/src/shade/playground/particle_system/index.html +124 -0
- package/src/shade/playground/particle_system/main.d.ts +2 -0
- package/src/shade/playground/particle_system/main.d.ts.map +1 -0
- package/src/shade/playground/particle_system/main.js +180 -0
- package/src/shade/playground/particle_system/particle_scene.d.ts +52 -0
- package/src/shade/playground/particle_system/particle_scene.d.ts.map +1 -0
- package/src/shade/playground/particle_system/particle_scene.js +553 -0
- package/src/shade/playground/skinned_mesh_soup/README.md +143 -0
- package/src/shade/playground/skinned_mesh_soup/index.html +202 -0
- package/src/shade/playground/skinned_mesh_soup/main.d.ts +7 -0
- package/src/shade/playground/skinned_mesh_soup/main.d.ts.map +1 -0
- package/src/shade/playground/skinned_mesh_soup/main.js +567 -0
- package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.d.ts +29 -0
- package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.d.ts.map +1 -0
- package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.js +428 -0
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
- package/src/shade/renderer/animation/GPUAnimationManager.js +1958 -1796
- package/src/shade/renderer/animation/SKINNING_FRAME_PLAN.md +357 -0
- package/src/shade/renderer/animation/skin_bind_transform.d.ts +25 -0
- package/src/shade/renderer/animation/skin_bind_transform.d.ts.map +1 -0
- package/src/shade/renderer/animation/skin_bind_transform.js +33 -0
- package/src/shade/renderer/animation/skin_clip_scale_conflicts.d.ts +67 -0
- package/src/shade/renderer/animation/skin_clip_scale_conflicts.d.ts.map +1 -0
- package/src/shade/renderer/animation/skin_clip_scale_conflicts.js +199 -0
- package/src/shade/renderer/animation/skin_frame_defect.d.ts +34 -0
- package/src/shade/renderer/animation/skin_frame_defect.d.ts.map +1 -0
- package/src/shade/renderer/animation/skin_frame_defect.js +132 -0
- package/src/shade/renderer/animation/skin_joint_matrix.d.ts +24 -0
- package/src/shade/renderer/animation/skin_joint_matrix.d.ts.map +1 -0
- package/src/shade/renderer/animation/skin_joint_matrix.js +46 -0
- package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts +70 -0
- package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts.map +1 -0
- package/src/shade/renderer/animation/skin_normalize_mesh_frame.js +216 -0
- package/src/shade/renderer/animation/skin_test_fixtures.d.ts +86 -0
- package/src/shade/renderer/animation/skin_test_fixtures.d.ts.map +1 -0
- package/src/shade/renderer/animation/skin_test_fixtures.js +250 -0
- package/src/shade/renderer/animation/skinning/chunk_skin_blend_mesh_local.d.ts +18 -4
- package/src/shade/renderer/animation/skinning/chunk_skin_blend_mesh_local.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/chunk_skin_blend_mesh_local.js +18 -4
- package/src/shade/renderer/particles/DESIGN.md +5 -5
- package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts.map +1 -1
- package/src/shade/renderer/particles/cull/chunk_particle_cull.js +3 -1
- package/src/shade/renderer/particles/data/chunk_particle_emitter.js +1 -1
- package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts +43 -0
- package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts.map +1 -0
- package/src/shade/renderer/particles/graph/ParticleNodeDescription.js +44 -0
- package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts +33 -59
- package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/ParticleNodeRegistry.js +185 -118
- package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts +15 -10
- package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/compile_particle_graph.js +205 -170
- package/src/shade/renderer/particles/graph/particle_graph_authoring.d.ts +44 -0
- package/src/shade/renderer/particles/graph/particle_graph_authoring.d.ts.map +1 -0
- package/src/shade/renderer/particles/graph/particle_graph_authoring.js +108 -0
- package/src/shade/renderer/particles/isa/InstructionStream.d.ts +89 -0
- package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -0
- package/src/shade/renderer/particles/isa/InstructionStream.js +162 -0
- package/src/shade/renderer/particles/isa/ParticleAssembler.d.ts +1 -48
- package/src/shade/renderer/particles/isa/ParticleAssembler.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/ParticleAssembler.js +25 -114
- package/src/shade/renderer/particles/particle_prototype.d.ts.map +1 -1
- package/src/shade/renderer/particles/particle_prototype.js +181 -180
- package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts +4 -4
- package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts.map +1 -1
- package/src/shade/renderer/particles/runtime/create_particle_effect.js +19 -19
- package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.js +4 -2
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts +4 -4
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.js +7 -5
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.js +3 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.js +3 -1
- package/src/shade/renderer/particles/shaders/shader_particle_finalize.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_finalize.js +5 -2
- package/src/shade/renderer/particles/shaders/shader_particle_render.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_render.js +9 -2
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +3 -1
- package/src/shade/renderer/particles/vm/chunk_particle_vm.js +1 -1
- package/src/shade/renderer/scene/SkinnedMesh.d.ts +11 -0
- package/src/shade/renderer/scene/SkinnedMesh.d.ts.map +1 -1
- package/src/shade/renderer/scene/SkinnedMesh.js +11 -0
- package/src/shade/renderer/shader/chunk/geometry/quaternion/dual/chunk_dual_quat_from_m4.d.ts +33 -3
- package/src/shade/renderer/shader/chunk/geometry/quaternion/dual/chunk_dual_quat_from_m4.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/quaternion/dual/chunk_dual_quat_from_m4.js +58 -37
- package/src/shade/renderer/particles/graph/ParticleGraph.d.ts +0 -54
- package/src/shade/renderer/particles/graph/ParticleGraph.d.ts.map +0 -1
- package/src/shade/renderer/particles/graph/ParticleGraph.js +0 -99
- package/src/shade/renderer/particles/prototypeParticleSystem.d.ts +0 -2
- package/src/shade/renderer/particles/prototypeParticleSystem.d.ts.map +0 -1
- package/src/shade/renderer/particles/prototypeParticleSystem.js +0 -448
|
@@ -52,7 +52,8 @@ resources.createGroup()
|
|
|
52
52
|
// Only textureLoad-ed (soft depth), so it can be unfilterable — matches an r32float scene depth.
|
|
53
53
|
.addTexture("scene_depth", "unfilterable-float");
|
|
54
54
|
|
|
55
|
-
const body = CodeChunk.from(
|
|
55
|
+
const body = CodeChunk.from(
|
|
56
|
+
/* language=wgsl */ `
|
|
56
57
|
const PARTICLE_RECORD_WORDS : u32 = ${PARTICLE_RECORD_WORD_COUNT}u;
|
|
57
58
|
const PARTICLE_HEADER_EMITTER : u32 = ${PARTICLE_RECORD_HEADER_EMITTER}u;
|
|
58
59
|
const PARTICLE_ATTRIBUTE_ABSENT : u32 = ${EMITTER_ATTRIBUTE_ABSENT}u;
|
|
@@ -165,7 +166,12 @@ const descriptor = ShaderDescriptor.from({ label: "Particle Billboard", body, re
|
|
|
165
166
|
* reverse-Z scenes (the engine convention), "less"/"less-equal" for a standard-Z scene
|
|
166
167
|
* @returns {RenderPipelineDescriptor}
|
|
167
168
|
*/
|
|
168
|
-
export function create_particle_billboard_pipeline({
|
|
169
|
+
export function create_particle_billboard_pipeline({
|
|
170
|
+
color_format = "rgba16float",
|
|
171
|
+
depth_format = "depth32float",
|
|
172
|
+
depth_compare = "greater"
|
|
173
|
+
} = {}) {
|
|
174
|
+
|
|
169
175
|
const code = descriptor.source;
|
|
170
176
|
|
|
171
177
|
return RenderPipelineDescriptor.from({
|
|
@@ -184,6 +190,7 @@ export function create_particle_billboard_pipeline({ color_format = "rgba16float
|
|
|
184
190
|
: DepthStencilState.from({ format: depth_format, depthWriteEnabled: false, depthCompare: depth_compare }),
|
|
185
191
|
primitive: { topology: "triangle-list", cullMode: "none" },
|
|
186
192
|
});
|
|
193
|
+
|
|
187
194
|
}
|
|
188
195
|
|
|
189
196
|
/** The billboard shader's resource set (for building bind groups + the draw command). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shader_particle_simulate.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_simulate.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,+CAHU,aAAa,CAG4B;
|
|
1
|
+
{"version":3,"file":"shader_particle_simulate.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_simulate.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,+CAHU,aAAa,CAG4B;AAuEnD,qDAIG;8BA7G2B,+BAA+B"}
|
|
@@ -62,7 +62,9 @@ resources.createGroup()
|
|
|
62
62
|
.addStorageBuffer("alive_out", WebGPUArray.u32, true)
|
|
63
63
|
.addStorageBuffer("dead", WebGPUArray.u32, true)
|
|
64
64
|
.addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true);
|
|
65
|
-
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
const body = CodeChunk.from(/* language=wgsl */ `
|
|
66
68
|
const PARTICLE_RECORD_WORDS : u32 = ${PARTICLE_RECORD_WORD_COUNT}u;
|
|
67
69
|
const PARTICLE_HEADER_EMITTER : u32 = ${PARTICLE_RECORD_HEADER_EMITTER}u;
|
|
68
70
|
const PARTICLE_INSTRUCTION_WORDS : u32 = ${PARTICLE_VM_INSTRUCTION_WORDS}u;
|
|
@@ -33,7 +33,7 @@ import { VM_BUILTIN, VM_OP, VM_RANDOM_MODE } from "../isa/ParticleVMISA.js";
|
|
|
33
33
|
|
|
34
34
|
const R = PARTICLE_VM_REGISTER_COUNT;
|
|
35
35
|
|
|
36
|
-
const source = /* wgsl */ `
|
|
36
|
+
const source = /* language=wgsl */ `
|
|
37
37
|
const PARTICLE_VM_REGISTER_COUNT : u32 = ${R}u;
|
|
38
38
|
const PARTICLE_VM_MAX_INSTRUCTIONS : u32 = ${PARTICLE_VM_MAX_INSTRUCTIONS}u;
|
|
39
39
|
const PARTICLE_VM_TWO_PI : f32 = 6.28318530717958647692;
|
|
@@ -28,6 +28,17 @@
|
|
|
28
28
|
* see {@link chunk_skin_blend_mesh_local} for why it goes into each
|
|
29
29
|
* matrix rather than onto the blended position.
|
|
30
30
|
*
|
|
31
|
+
* **`transform_global` on a skinned mesh is the engine's, not the
|
|
32
|
+
* asset's.** It cancels out of the rendered position, so glTF declares
|
|
33
|
+
* it meaningless — and the one meaning it does have is the frame the
|
|
34
|
+
* clone's vertices are written in, which the fold above requires to be
|
|
35
|
+
* rigid against the skin. {@link GPUAnimationManager#register_skin}
|
|
36
|
+
* therefore overwrites it, by way of
|
|
37
|
+
* {@link skin_normalize_mesh_frame}, with the skin's own bind
|
|
38
|
+
* transform. Whatever the file put there is discarded, and anything
|
|
39
|
+
* reading this expecting the file's value is reading the wrong thing.
|
|
40
|
+
* See `renderer/animation/SKINNING_FRAME_PLAN.md`.
|
|
41
|
+
*
|
|
31
42
|
* The mesh's **skin id** — a row in a GPU table — lives in
|
|
32
43
|
* {@link GPUMeshSkinningContext} and nowhere else. The CPU-side
|
|
33
44
|
* {@link Skin} it was registered with is a different thing, pure data
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SkinnedMesh.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/scene/SkinnedMesh.js"],"names":[],"mappings":"AAGA
|
|
1
|
+
{"version":3,"file":"SkinnedMesh.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/scene/SkinnedMesh.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AACH;IAEI;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAFU,OAAK,IAAI,CAEP;IAEZ;;OAEG;IACH,SAFa,WAAW,CAMvB;IAED;;OAEG;IACH,YAFW,WAAW,QAYrB;IA4CL;;;OAGG;IACH,wBAFU,OAAO,CAEkB;CANlC;qBA9JoB,WAAW"}
|
|
@@ -31,6 +31,17 @@ import { Mesh } from "./Mesh.js";
|
|
|
31
31
|
* see {@link chunk_skin_blend_mesh_local} for why it goes into each
|
|
32
32
|
* matrix rather than onto the blended position.
|
|
33
33
|
*
|
|
34
|
+
* **`transform_global` on a skinned mesh is the engine's, not the
|
|
35
|
+
* asset's.** It cancels out of the rendered position, so glTF declares
|
|
36
|
+
* it meaningless — and the one meaning it does have is the frame the
|
|
37
|
+
* clone's vertices are written in, which the fold above requires to be
|
|
38
|
+
* rigid against the skin. {@link GPUAnimationManager#register_skin}
|
|
39
|
+
* therefore overwrites it, by way of
|
|
40
|
+
* {@link skin_normalize_mesh_frame}, with the skin's own bind
|
|
41
|
+
* transform. Whatever the file put there is discarded, and anything
|
|
42
|
+
* reading this expecting the file's value is reading the wrong thing.
|
|
43
|
+
* See `renderer/animation/SKINNING_FRAME_PLAN.md`.
|
|
44
|
+
*
|
|
34
45
|
* The mesh's **skin id** — a row in a GPU table — lives in
|
|
35
46
|
* {@link GPUMeshSkinningContext} and nowhere else. The CPU-side
|
|
36
47
|
* {@link Skin} it was registered with is a different thing, pure data
|
package/src/shade/renderer/shader/chunk/geometry/quaternion/dual/chunk_dual_quat_from_m4.d.ts
CHANGED
|
@@ -1,7 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* A rigid transform as a dual quaternion: the rotation in the real part, the translation carried in
|
|
3
|
+
* the dual part as `0.5 · t · real`.
|
|
4
|
+
*
|
|
5
|
+
* The matrix's upper 3×3 is read as a rotation and its fourth column as a translation. Anything else
|
|
6
|
+
* in the matrix — a scale, a shear — has nowhere to go, and comes back as neither itself nor a
|
|
7
|
+
* warning: see {@link m4_rigidity_defect} for the number that says so and
|
|
8
|
+
* `renderer/animation/SKINNING_FRAME_PLAN.md` for the frame arrangement that keeps a skinning
|
|
9
|
+
* matrix rigid in the first place.
|
|
10
|
+
*
|
|
11
|
+
* ## Why the rotation goes through `quat_from_m3`
|
|
12
|
+
*
|
|
13
|
+
* This used to take all four quaternion components as `sqrt(max(0, 1 ± m00 ± m11 ± m22)) · 0.5` and
|
|
14
|
+
* recover their signs from the off-diagonal differences. That is exact in exact arithmetic and
|
|
15
|
+
* badly conditioned in floating point: near the identity three of those radicands are near zero, and
|
|
16
|
+
* a square root turns an input error of `e` into an output error of `sqrt(e)`. A matrix that is the
|
|
17
|
+
* identity to `1e-6` — which is what a skin's folded joint matrices are at bind pose — yielded
|
|
18
|
+
* quaternion components off by `9e-4`, an angular error of `1.8e-3` radians, and a millimetre and a
|
|
19
|
+
* half of vertex displacement on a 1.66 m character. Measured, on `Michelle.glb`.
|
|
20
|
+
*
|
|
21
|
+
* {@link chunk_quat_from_m3} is Shoemake's branch-picking form: it computes whichever component the
|
|
22
|
+
* matrix's diagonal says is largest, and derives the other three from it by division. Every branch
|
|
23
|
+
* divides by at least 2, so the components come out **linear** in the input error rather than as its
|
|
24
|
+
* square root — the same `1e-6` matrix now gives `2.5e-7`, three and a half orders better — and the
|
|
25
|
+
* near-180° case, where the trace form is ill-conditioned for the opposite reason, is a branch of its
|
|
26
|
+
* own. One `sqrt` and a reciprocal where there were four `sqrt`s.
|
|
27
|
+
*
|
|
28
|
+
* The normalize stays, on top of that. It is a no-op for the orthonormal input this is meant to be
|
|
29
|
+
* given; what it earns its rsqrt for is the input that is not — a degenerate 3×3 leaves
|
|
30
|
+
* `quat_from_m3` on a branch whose answer has length 0.5, and this is what keeps the documented
|
|
31
|
+
* postcondition, a unit real part, true anyway.
|
|
32
|
+
*
|
|
33
|
+
* @see https://gitlab.com/libeigen/eigen/-/blob/master/Eigen/src/Geometry/Quaternion.h#L813
|
|
34
|
+
* @type {CodeChunk}
|
|
5
35
|
*/
|
|
6
36
|
export const chunk_dual_quat_from_m4: CodeChunk;
|
|
7
37
|
import { CodeChunk } from "../../../../compiler/CodeChunk.js";
|
package/src/shade/renderer/shader/chunk/geometry/quaternion/dual/chunk_dual_quat_from_m4.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk_dual_quat_from_m4.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/shade/renderer/shader/chunk/geometry/quaternion/dual/chunk_dual_quat_from_m4.js"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"chunk_dual_quat_from_m4.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/shade/renderer/shader/chunk/geometry/quaternion/dual/chunk_dual_quat_from_m4.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,sCAFU,SAAS,CAoBlB;0BAzDyB,mCAAmC"}
|
|
@@ -1,37 +1,58 @@
|
|
|
1
|
-
import { CodeChunk } from "../../../../compiler/CodeChunk.js";
|
|
2
|
-
import {
|
|
3
|
-
import { chunk_quat_multiply } from "../chunk_quat_multiply.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
1
|
+
import { CodeChunk } from "../../../../compiler/CodeChunk.js";
|
|
2
|
+
import { chunk_quat_from_m3 } from "../chunk_quat_from_m3.js";
|
|
3
|
+
import { chunk_quat_multiply } from "../chunk_quat_multiply.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A rigid transform as a dual quaternion: the rotation in the real part, the translation carried in
|
|
7
|
+
* the dual part as `0.5 · t · real`.
|
|
8
|
+
*
|
|
9
|
+
* The matrix's upper 3×3 is read as a rotation and its fourth column as a translation. Anything else
|
|
10
|
+
* in the matrix — a scale, a shear — has nowhere to go, and comes back as neither itself nor a
|
|
11
|
+
* warning: see {@link m4_rigidity_defect} for the number that says so and
|
|
12
|
+
* `renderer/animation/SKINNING_FRAME_PLAN.md` for the frame arrangement that keeps a skinning
|
|
13
|
+
* matrix rigid in the first place.
|
|
14
|
+
*
|
|
15
|
+
* ## Why the rotation goes through `quat_from_m3`
|
|
16
|
+
*
|
|
17
|
+
* This used to take all four quaternion components as `sqrt(max(0, 1 ± m00 ± m11 ± m22)) · 0.5` and
|
|
18
|
+
* recover their signs from the off-diagonal differences. That is exact in exact arithmetic and
|
|
19
|
+
* badly conditioned in floating point: near the identity three of those radicands are near zero, and
|
|
20
|
+
* a square root turns an input error of `e` into an output error of `sqrt(e)`. A matrix that is the
|
|
21
|
+
* identity to `1e-6` — which is what a skin's folded joint matrices are at bind pose — yielded
|
|
22
|
+
* quaternion components off by `9e-4`, an angular error of `1.8e-3` radians, and a millimetre and a
|
|
23
|
+
* half of vertex displacement on a 1.66 m character. Measured, on `Michelle.glb`.
|
|
24
|
+
*
|
|
25
|
+
* {@link chunk_quat_from_m3} is Shoemake's branch-picking form: it computes whichever component the
|
|
26
|
+
* matrix's diagonal says is largest, and derives the other three from it by division. Every branch
|
|
27
|
+
* divides by at least 2, so the components come out **linear** in the input error rather than as its
|
|
28
|
+
* square root — the same `1e-6` matrix now gives `2.5e-7`, three and a half orders better — and the
|
|
29
|
+
* near-180° case, where the trace form is ill-conditioned for the opposite reason, is a branch of its
|
|
30
|
+
* own. One `sqrt` and a reciprocal where there were four `sqrt`s.
|
|
31
|
+
*
|
|
32
|
+
* The normalize stays, on top of that. It is a no-op for the orthonormal input this is meant to be
|
|
33
|
+
* given; what it earns its rsqrt for is the input that is not — a degenerate 3×3 leaves
|
|
34
|
+
* `quat_from_m3` on a branch whose answer has length 0.5, and this is what keeps the documented
|
|
35
|
+
* postcondition, a unit real part, true anyway.
|
|
36
|
+
*
|
|
37
|
+
* @see https://gitlab.com/libeigen/eigen/-/blob/master/Eigen/src/Geometry/Quaternion.h#L813
|
|
38
|
+
* @type {CodeChunk}
|
|
39
|
+
*/
|
|
40
|
+
export const chunk_dual_quat_from_m4 = CodeChunk.from(
|
|
41
|
+
//language=WGSL
|
|
42
|
+
`
|
|
43
|
+
fn dual_quat_from_m4(m: mat4x4<f32>) -> mat2x4<f32> {
|
|
44
|
+
|
|
45
|
+
var dq: mat2x4<f32>;
|
|
46
|
+
|
|
47
|
+
dq[0] = normalize(quat_from_m3(mat3x3<f32>(m[0].xyz, m[1].xyz, m[2].xyz)));
|
|
48
|
+
|
|
49
|
+
dq[1] = vec4(m[3][0], m[3][1], m[3][2], 0);
|
|
50
|
+
dq[1] = quat_multiply(dq[1], dq[0]) * 0.5;
|
|
51
|
+
|
|
52
|
+
return dq;
|
|
53
|
+
}
|
|
54
|
+
`, [
|
|
55
|
+
chunk_quat_from_m3,
|
|
56
|
+
chunk_quat_multiply,
|
|
57
|
+
]
|
|
58
|
+
)
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Wrap a scalar or vector as a literal source (so it is unambiguous vs. a node id).
|
|
3
|
-
* @param {...number} components
|
|
4
|
-
* @returns {number[]}
|
|
5
|
-
*/
|
|
6
|
-
export function literal(...components: number[]): number[];
|
|
7
|
-
/**
|
|
8
|
-
* A directed acyclic graph describing one lifecycle phase (SPAWN or UPDATE) of a particle effect.
|
|
9
|
-
*
|
|
10
|
-
* Nodes are value-producing operations (constants, builtins, attribute reads, math, curves, random)
|
|
11
|
-
* or sinks (attribute writes, kill). Edges wire a producing node's single `out` port to a consuming
|
|
12
|
-
* node's named input port. Inputs may also be literal `vec4` values, which the compiler lowers to
|
|
13
|
-
* constant loads.
|
|
14
|
-
*
|
|
15
|
-
* The graph is pure data + a small builder; {@link ../graph/compile_particle_graph.js} lowers it to
|
|
16
|
-
* VM bytecode.
|
|
17
|
-
*/
|
|
18
|
-
export class ParticleGraph {
|
|
19
|
-
/** @type {Map<number, {id: number, type: string, params: object, inputs: Map<string, object>}>} */
|
|
20
|
-
nodes: Map<number, {
|
|
21
|
-
id: number;
|
|
22
|
-
type: string;
|
|
23
|
-
params: object;
|
|
24
|
-
inputs: Map<string, object>;
|
|
25
|
-
}>;
|
|
26
|
-
/** @type {number} */
|
|
27
|
-
next_id: number;
|
|
28
|
-
/**
|
|
29
|
-
* Add a node.
|
|
30
|
-
* @param {string} type a key in {@link PARTICLE_NODE_TYPES}
|
|
31
|
-
* @param {object} [params] static parameters (attribute name, builtin id, constant value, …)
|
|
32
|
-
* @returns {number} the new node id
|
|
33
|
-
*/
|
|
34
|
-
add(type: string, params?: object): number;
|
|
35
|
-
/**
|
|
36
|
-
* Bind an input port of a node to a source.
|
|
37
|
-
*
|
|
38
|
-
* The source may be:
|
|
39
|
-
* - a node id (number) → that node's `out` port,
|
|
40
|
-
* - `{ node, port }` → an explicit port,
|
|
41
|
-
* - a number or array → a literal `vec4` (scalars broadcast is NOT applied; `5` means `[5,0,0,0]`).
|
|
42
|
-
*
|
|
43
|
-
* @param {number} node_id
|
|
44
|
-
* @param {string} port
|
|
45
|
-
* @param {number|number[]|{node: number, port?: string}} source
|
|
46
|
-
* @returns {ParticleGraph} this, for chaining
|
|
47
|
-
*/
|
|
48
|
-
wire(node_id: number, port: string, source: number | number[] | {
|
|
49
|
-
node: number;
|
|
50
|
-
port?: string;
|
|
51
|
-
}): ParticleGraph;
|
|
52
|
-
#private;
|
|
53
|
-
}
|
|
54
|
-
//# sourceMappingURL=ParticleGraph.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ParticleGraph.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/graph/ParticleGraph.js"],"names":[],"mappings":"AA2FA;;;;GAIG;AACH,uCAHc,MAAM,KACP,MAAM,EAAE,CAIpB;AA/FD;;;;;;;;;;GAUG;AACH;IAEQ,mGAAmG;IACnG,OADW,IAAI,MAAM,EAAE;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,IAAI,MAAM,EAAE,MAAM,CAAC,CAAA;KAAC,CAAC,CACzE;IACtB,qBAAqB;IACrB,SADW,MAAM,CACD;IAGpB;;;;;OAKG;IACH,UAJW,MAAM,WACN,MAAM,GACJ,MAAM,CAWlB;IAED;;;;;;;;;;;;OAYG;IACH,cALW,MAAM,QACN,MAAM;cACiB,MAAM;eAAS,MAAM;QAC1C,aAAa,CAYzB;;CAQJ"}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { assert } from "../../../../core/assert.js";
|
|
2
|
-
import { PARTICLE_NODE_TYPES } from "./ParticleNodeRegistry.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* A directed acyclic graph describing one lifecycle phase (SPAWN or UPDATE) of a particle effect.
|
|
6
|
-
*
|
|
7
|
-
* Nodes are value-producing operations (constants, builtins, attribute reads, math, curves, random)
|
|
8
|
-
* or sinks (attribute writes, kill). Edges wire a producing node's single `out` port to a consuming
|
|
9
|
-
* node's named input port. Inputs may also be literal `vec4` values, which the compiler lowers to
|
|
10
|
-
* constant loads.
|
|
11
|
-
*
|
|
12
|
-
* The graph is pure data + a small builder; {@link ../graph/compile_particle_graph.js} lowers it to
|
|
13
|
-
* VM bytecode.
|
|
14
|
-
*/
|
|
15
|
-
export class ParticleGraph {
|
|
16
|
-
constructor() {
|
|
17
|
-
/** @type {Map<number, {id: number, type: string, params: object, inputs: Map<string, object>}>} */
|
|
18
|
-
this.nodes = new Map();
|
|
19
|
-
/** @type {number} */
|
|
20
|
-
this.next_id = 0;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Add a node.
|
|
25
|
-
* @param {string} type a key in {@link PARTICLE_NODE_TYPES}
|
|
26
|
-
* @param {object} [params] static parameters (attribute name, builtin id, constant value, …)
|
|
27
|
-
* @returns {number} the new node id
|
|
28
|
-
*/
|
|
29
|
-
add(type, params = {}) {
|
|
30
|
-
const definition = PARTICLE_NODE_TYPES[type];
|
|
31
|
-
if (definition === undefined) {
|
|
32
|
-
throw new Error(`Unknown particle node type '${type}'`);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const id = this.next_id++;
|
|
36
|
-
this.nodes.set(id, { id, type, params, inputs: new Map() });
|
|
37
|
-
return id;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Bind an input port of a node to a source.
|
|
42
|
-
*
|
|
43
|
-
* The source may be:
|
|
44
|
-
* - a node id (number) → that node's `out` port,
|
|
45
|
-
* - `{ node, port }` → an explicit port,
|
|
46
|
-
* - a number or array → a literal `vec4` (scalars broadcast is NOT applied; `5` means `[5,0,0,0]`).
|
|
47
|
-
*
|
|
48
|
-
* @param {number} node_id
|
|
49
|
-
* @param {string} port
|
|
50
|
-
* @param {number|number[]|{node: number, port?: string}} source
|
|
51
|
-
* @returns {ParticleGraph} this, for chaining
|
|
52
|
-
*/
|
|
53
|
-
wire(node_id, port, source) {
|
|
54
|
-
const node = this.#require(node_id);
|
|
55
|
-
|
|
56
|
-
const definition = PARTICLE_NODE_TYPES[node.type];
|
|
57
|
-
if (!definition.inputs.includes(port)) {
|
|
58
|
-
throw new Error(`Node '${node.type}' has no input port '${port}'`);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
node.inputs.set(port, normalize_source(source));
|
|
62
|
-
return this;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** @param {number} id @returns {{id, type, params, inputs}} */
|
|
66
|
-
#require(id) {
|
|
67
|
-
const node = this.nodes.get(id);
|
|
68
|
-
assert.defined(node, `node ${id}`);
|
|
69
|
-
return node;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* @param {number|number[]|{node:number,port?:string}} source
|
|
75
|
-
* @returns {{kind: "node", node: number, port: string} | {kind: "literal", value: number[]}}
|
|
76
|
-
*/
|
|
77
|
-
function normalize_source(source) {
|
|
78
|
-
if (typeof source === "number") {
|
|
79
|
-
// Could be a node id or a scalar literal — ambiguous, so require explicit forms for literals.
|
|
80
|
-
return { kind: "node", node: source, port: "out" };
|
|
81
|
-
}
|
|
82
|
-
if (Array.isArray(source)) {
|
|
83
|
-
const value = [source[0] ?? 0, source[1] ?? 0, source[2] ?? 0, source[3] ?? 0];
|
|
84
|
-
return { kind: "literal", value };
|
|
85
|
-
}
|
|
86
|
-
if (source !== null && typeof source === "object" && typeof source.node === "number") {
|
|
87
|
-
return { kind: "node", node: source.node, port: source.port ?? "out" };
|
|
88
|
-
}
|
|
89
|
-
throw new Error(`Invalid input source: ${JSON.stringify(source)}`);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Wrap a scalar or vector as a literal source (so it is unambiguous vs. a node id).
|
|
94
|
-
* @param {...number} components
|
|
95
|
-
* @returns {number[]}
|
|
96
|
-
*/
|
|
97
|
-
export function literal(...components) {
|
|
98
|
-
return components;
|
|
99
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prototypeParticleSystem.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/particles/prototypeParticleSystem.js"],"names":[],"mappings":""}
|