@woosh/meep-engine 3.44.0 → 3.45.0

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.
Files changed (233) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/package.json +1 -1
  3. package/src/core/collection/array/array_sort_insertion_ascending.d.ts +19 -0
  4. package/src/core/collection/array/array_sort_insertion_ascending.d.ts.map +1 -0
  5. package/src/core/collection/array/array_sort_insertion_ascending.js +31 -0
  6. package/src/core/geom/3d/aabb/aabb3_array_round_outward_f32.d.ts +27 -0
  7. package/src/core/geom/3d/aabb/aabb3_array_round_outward_f32.d.ts.map +1 -0
  8. package/src/core/geom/3d/aabb/aabb3_array_round_outward_f32.js +39 -0
  9. package/src/core/geom/3d/aabb/aabb3_from_v3_array.d.ts.map +1 -1
  10. package/src/core/geom/3d/aabb/aabb3_from_v3_array.js +4 -1
  11. package/src/core/geom/3d/aabb/aabb3_transform_oriented.d.ts +2 -2
  12. package/src/core/geom/3d/aabb/aabb3_transform_oriented.d.ts.map +1 -1
  13. package/src/core/geom/3d/aabb/aabb3_transform_oriented.js +1 -1
  14. package/src/core/geom/3d/pose/pose3_apply_inverse_point_array.d.ts +21 -0
  15. package/src/core/geom/3d/pose/pose3_apply_inverse_point_array.d.ts.map +1 -0
  16. package/src/core/geom/3d/pose/pose3_apply_inverse_point_array.js +36 -0
  17. package/src/core/geom/3d/pose/pose3_apply_point_array.d.ts +25 -0
  18. package/src/core/geom/3d/pose/pose3_apply_point_array.d.ts.map +1 -0
  19. package/src/core/geom/3d/pose/pose3_apply_point_array.js +40 -0
  20. package/src/core/geom/3d/pose/pose3_compose_array.d.ts +28 -0
  21. package/src/core/geom/3d/pose/pose3_compose_array.d.ts.map +1 -0
  22. package/src/core/geom/3d/pose/pose3_compose_array.js +41 -0
  23. package/src/core/geom/3d/pose/pose3_to_local_array.d.ts +29 -0
  24. package/src/core/geom/3d/pose/pose3_to_local_array.d.ts.map +1 -0
  25. package/src/core/geom/3d/pose/pose3_to_local_array.js +42 -0
  26. package/src/core/geom/3d/quaternion/quat3_clamp_angle_array.d.ts +28 -0
  27. package/src/core/geom/3d/quaternion/quat3_clamp_angle_array.d.ts.map +1 -0
  28. package/src/core/geom/3d/quaternion/quat3_clamp_angle_array.js +66 -0
  29. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_left_array.d.ts +22 -0
  30. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_left_array.d.ts.map +1 -0
  31. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_left_array.js +30 -0
  32. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_right_array.d.ts +23 -0
  33. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_right_array.d.ts.map +1 -0
  34. package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_right_array.js +31 -0
  35. package/src/core/geom/3d/triangle/tri3_compute_normal_area_weighted_array.d.ts +26 -0
  36. package/src/core/geom/3d/triangle/tri3_compute_normal_area_weighted_array.d.ts.map +1 -0
  37. package/src/core/geom/3d/triangle/tri3_compute_normal_area_weighted_array.js +46 -0
  38. package/src/core/geom/vec3/v3_distance_array.d.ts +11 -0
  39. package/src/core/geom/vec3/v3_distance_array.d.ts.map +1 -0
  40. package/src/core/geom/vec3/v3_distance_array.js +19 -0
  41. package/src/core/geom/vec3/v3_normalize_array_checked.d.ts +23 -0
  42. package/src/core/geom/vec3/v3_normalize_array_checked.d.ts.map +1 -0
  43. package/src/core/geom/vec3/v3_normalize_array_checked.js +49 -0
  44. package/src/core/geom/vec3/v3_reject_array.d.ts +15 -0
  45. package/src/core/geom/vec3/v3_reject_array.d.ts.map +1 -0
  46. package/src/core/geom/vec3/v3_reject_array.js +32 -0
  47. package/src/core/graph/csr/csr_build_incidence.d.ts +26 -0
  48. package/src/core/graph/csr/csr_build_incidence.d.ts.map +1 -0
  49. package/src/core/graph/csr/csr_build_incidence.js +71 -0
  50. package/src/core/graph/csr/csr_graph_color_greedy.d.ts +25 -0
  51. package/src/core/graph/csr/csr_graph_color_greedy.d.ts.map +1 -0
  52. package/src/core/graph/csr/csr_graph_color_greedy.js +83 -0
  53. package/src/core/graph/csr/csr_graph_validate_coloring.d.ts +15 -0
  54. package/src/core/graph/csr/csr_graph_validate_coloring.d.ts.map +1 -0
  55. package/src/core/graph/csr/csr_graph_validate_coloring.js +33 -0
  56. package/src/core/math/linalg/matrix_symmetric_3x3_solve_ldlt.d.ts +26 -0
  57. package/src/core/math/linalg/matrix_symmetric_3x3_solve_ldlt.d.ts.map +1 -0
  58. package/src/core/math/linalg/matrix_symmetric_3x3_solve_ldlt.js +71 -0
  59. package/src/core/math/max2_exact.d.ts +15 -0
  60. package/src/core/math/max2_exact.d.ts.map +1 -0
  61. package/src/core/math/max2_exact.js +30 -0
  62. package/src/core/math/min2_exact.d.ts +20 -0
  63. package/src/core/math/min2_exact.d.ts.map +1 -0
  64. package/src/core/math/min2_exact.js +35 -0
  65. package/src/engine/ecs/ik/IKGoalSystem.d.ts.map +1 -1
  66. package/src/engine/ecs/ik/IKGoalSystem.js +3 -19
  67. package/src/engine/ecs/parent/parent_entity_model_of.d.ts +17 -0
  68. package/src/engine/ecs/parent/parent_entity_model_of.d.ts.map +1 -0
  69. package/src/engine/ecs/parent/parent_entity_model_of.js +26 -0
  70. package/src/engine/ecs/transform/t64_read_pose_array.d.ts +15 -0
  71. package/src/engine/ecs/transform/t64_read_pose_array.d.ts.map +1 -0
  72. package/src/engine/ecs/transform/t64_read_pose_array.js +24 -0
  73. package/src/engine/graphics/geometry/geometry_construct_triangle_normal_area_weighted.d.ts +2 -0
  74. package/src/engine/graphics/geometry/geometry_construct_triangle_normal_area_weighted.d.ts.map +1 -1
  75. package/src/engine/graphics/geometry/geometry_construct_triangle_normal_area_weighted.js +10 -21
  76. package/src/engine/graphics3/AnimationGraphSystem.d.ts +5 -0
  77. package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
  78. package/src/engine/graphics3/AnimationGraphSystem.js +48 -2
  79. package/src/engine/graphics3/AnimationSystem.d.ts +5 -0
  80. package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
  81. package/src/engine/graphics3/AnimationSystem.js +47 -2
  82. package/src/engine/graphics3/register_clips.d.ts +29 -0
  83. package/src/engine/graphics3/register_clips.d.ts.map +1 -1
  84. package/src/engine/graphics3/register_clips.js +52 -0
  85. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts +9 -0
  86. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts.map +1 -1
  87. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +3 -1
  88. package/src/engine/physics/cloth/PLAN.md +10 -8
  89. package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts +22 -0
  90. package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts.map +1 -1
  91. package/src/engine/physics/cloth/build/cloth_bind_in_frame.js +51 -19
  92. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts.map +1 -1
  93. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.js +16 -2
  94. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.d.ts.map +1 -1
  95. package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.js +19 -24
  96. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +7 -0
  97. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -1
  98. package/src/engine/physics/cloth/collider/ClothColliderIndex.js +85 -67
  99. package/src/engine/physics/cloth/collider/cloth_collider_bounds.d.ts.map +1 -1
  100. package/src/engine/physics/cloth/collider/cloth_collider_bounds.js +19 -101
  101. package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts +2 -5
  102. package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts.map +1 -1
  103. package/src/engine/physics/cloth/collider/cloth_collider_pack.js +7 -15
  104. package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts.map +1 -1
  105. package/src/engine/physics/cloth/collider/cloth_collider_sdf.js +16 -61
  106. package/src/engine/physics/cloth/ecs/ClothColliderFlags.d.ts +0 -1
  107. package/src/engine/physics/cloth/ecs/ClothColliderFlags.js +6 -19
  108. package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts +1 -2
  109. package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts.map +1 -1
  110. package/src/engine/physics/cloth/ecs/ClothColliderSystem.js +3 -12
  111. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
  112. package/src/engine/physics/cloth/ecs/ClothWorld.js +40 -130
  113. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
  114. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +17 -58
  115. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
  116. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +3 -3
  117. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -1
  118. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +44 -104
  119. package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts.map +1 -1
  120. package/src/engine/physics/cloth/ecs/cloth_geodesic.js +6 -13
  121. package/src/engine/physics/cloth/ecs/cloth_holds.d.ts.map +1 -1
  122. package/src/engine/physics/cloth/ecs/cloth_holds.js +15 -40
  123. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts.map +1 -1
  124. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.js +45 -79
  125. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
  126. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +7 -27
  127. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
  128. package/src/engine/physics/cloth/ecs/cloth_write_back.js +30 -62
  129. package/src/engine/physics/cloth/playground/cloth_playground_build.d.ts.map +1 -1
  130. package/src/engine/physics/cloth/playground/cloth_playground_build.js +2 -3
  131. package/src/engine/physics/cloth/playground/collide_main.js +2 -28
  132. package/src/engine/physics/cloth/playground/garment_main.js +4 -19
  133. package/src/engine/physics/cloth/playground/main.js +6 -48
  134. package/src/engine/physics/cloth/playground/rig_main.js +947 -955
  135. package/src/engine/physics/cloth/playground/wind_main.js +8 -7
  136. package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
  137. package/src/engine/physics/cloth/solver/ClothState.js +16 -76
  138. package/src/engine/physics/cloth/solver/cloth_color_particles.d.ts +10 -8
  139. package/src/engine/physics/cloth/solver/cloth_color_particles.d.ts.map +1 -1
  140. package/src/engine/physics/cloth/solver/cloth_color_particles.js +30 -102
  141. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -1
  142. package/src/engine/physics/cloth/solver/cloth_contact_find.js +3 -2
  143. package/src/engine/physics/cloth/solver/cloth_hold_line.d.ts.map +1 -1
  144. package/src/engine/physics/cloth/solver/cloth_hold_line.js +2 -14
  145. package/src/engine/physics/cloth/solver/cloth_kinetic_energy.d.ts +21 -0
  146. package/src/engine/physics/cloth/solver/cloth_kinetic_energy.d.ts.map +1 -0
  147. package/src/engine/physics/cloth/solver/cloth_kinetic_energy.js +45 -0
  148. package/src/engine/physics/cloth/solver/cloth_particle_coupling.d.ts +32 -0
  149. package/src/engine/physics/cloth/solver/cloth_particle_coupling.d.ts.map +1 -0
  150. package/src/engine/physics/cloth/solver/cloth_particle_coupling.js +133 -0
  151. package/src/engine/physics/cloth/solver/cloth_particle_of_source.d.ts +16 -0
  152. package/src/engine/physics/cloth/solver/cloth_particle_of_source.d.ts.map +1 -0
  153. package/src/engine/physics/cloth/solver/cloth_particle_of_source.js +19 -0
  154. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts.map +1 -1
  155. package/src/engine/physics/cloth/solver/cloth_self_find.js +6 -55
  156. package/src/engine/physics/cloth/solver/cloth_solve_vertex.d.ts.map +1 -1
  157. package/src/engine/physics/cloth/solver/cloth_solve_vertex.js +30 -65
  158. package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
  159. package/src/engine/physics/cloth/solver/cloth_step.js +6 -28
  160. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -1
  161. package/src/engine/physics/cloth/solver/cloth_step_instance.js +2 -3
  162. package/src/engine/physics/cloth/solver/cloth_stretch_residual.d.ts +21 -0
  163. package/src/engine/physics/cloth/solver/cloth_stretch_residual.d.ts.map +1 -0
  164. package/src/engine/physics/cloth/solver/cloth_stretch_residual.js +54 -0
  165. package/src/engine/physics/cloth/solver/cloth_vertex_accumulator.d.ts +15 -0
  166. package/src/engine/physics/cloth/solver/cloth_vertex_accumulator.d.ts.map +1 -1
  167. package/src/engine/physics/cloth/solver/cloth_vertex_accumulator.js +28 -0
  168. package/src/engine/physics/cloth/solver/cloth_worst_tether_ratio.d.ts +30 -0
  169. package/src/engine/physics/cloth/solver/cloth_worst_tether_ratio.d.ts.map +1 -0
  170. package/src/engine/physics/cloth/solver/cloth_worst_tether_ratio.js +56 -0
  171. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts.map +1 -1
  172. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.js +3 -17
  173. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts +2 -1
  174. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts.map +1 -1
  175. package/src/engine/physics/cloth/wind/ClothFluidWind.js +7 -25
  176. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +3 -1
  177. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -1
  178. package/src/engine/physics/cloth/wind/cloth_sample_air.js +40 -62
  179. package/src/engine/physics/ecs/ContactProbeSystem.d.ts.map +1 -1
  180. package/src/engine/physics/ecs/ContactProbeSystem.js +2 -18
  181. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  182. package/src/engine/physics/ecs/PhysicsSystem.js +9 -50
  183. package/src/engine/physics/fluid/ecs/fluid_sample_domain_bounds.d.ts +24 -0
  184. package/src/engine/physics/fluid/ecs/fluid_sample_domain_bounds.d.ts.map +1 -0
  185. package/src/engine/physics/fluid/ecs/fluid_sample_domain_bounds.js +42 -0
  186. package/src/engine/physics/fluid/ecs/fluid_sample_velocity_world_mps.d.ts +25 -0
  187. package/src/engine/physics/fluid/ecs/fluid_sample_velocity_world_mps.d.ts.map +1 -0
  188. package/src/engine/physics/fluid/ecs/fluid_sample_velocity_world_mps.js +40 -0
  189. package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.d.ts.map +1 -1
  190. package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.js +40 -90
  191. package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -1
  192. package/src/engine/physics/narrowphase/capsule_contacts.js +3 -5
  193. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.d.ts.map +1 -1
  194. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.js +2 -14
  195. package/src/engine/physics/narrowphase/hull_sphere_contact.d.ts.map +1 -1
  196. package/src/engine/physics/narrowphase/hull_sphere_contact.js +2 -5
  197. package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
  198. package/src/engine/physics/narrowphase/narrowphase_step.js +13 -32
  199. package/src/engine/physics/narrowphase/sphere_box_contact.d.ts.map +1 -1
  200. package/src/engine/physics/narrowphase/sphere_box_contact.js +2 -5
  201. package/src/format/texture/basis/transcode/etc1s_to_astc.d.ts.map +1 -1
  202. package/src/format/texture/basis/transcode/etc1s_to_astc.js +2 -1
  203. package/src/shade/playground/image_decode_bench/main.js +2 -1
  204. package/src/shade/playground/skinned_blas_refit/diff_traced_against_rasterized.d.ts.map +1 -1
  205. package/src/shade/playground/skinned_blas_refit/diff_traced_against_rasterized.js +2 -1
  206. package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.d.ts.map +1 -1
  207. package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.js +2 -1
  208. package/src/shade/playground/ssr_variance/statistics.d.ts.map +1 -1
  209. package/src/shade/playground/ssr_variance/statistics.js +2 -1
  210. package/src/shade/playground/texture_encode/main.d.ts.map +1 -1
  211. package/src/shade/playground/texture_encode/main.js +2 -1
  212. package/src/shade/playground/volumetrics_froxel/measure.d.ts.map +1 -1
  213. package/src/shade/playground/volumetrics_froxel/measure.js +2 -1
  214. package/src/shade/renderer/buffer/table/gpu_database_check_links.d.ts.map +1 -1
  215. package/src/shade/renderer/buffer/table/gpu_database_check_links.js +2 -1
  216. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_group_step.d.ts.map +1 -1
  217. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_group_step.js +3 -2
  218. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_leaf_frontier.d.ts.map +1 -1
  219. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_leaf_frontier.js +2 -1
  220. package/src/shade/renderer/geometry/virtual/build/level/vgeo_partition_into_groups.d.ts.map +1 -1
  221. package/src/shade/renderer/geometry/virtual/build/level/vgeo_partition_into_groups.js +2 -1
  222. package/src/shade/renderer/geometry/virtual/build/level/vgeo_run_round.d.ts.map +1 -1
  223. package/src/shade/renderer/geometry/virtual/build/level/vgeo_run_round.js +2 -1
  224. package/src/shade/renderer/geometry/virtual/build/level/vgeo_try_repack.d.ts.map +1 -1
  225. package/src/shade/renderer/geometry/virtual/build/level/vgeo_try_repack.js +3 -2
  226. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_graph_components.d.ts.map +1 -1
  227. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_graph_components.js +2 -1
  228. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.d.ts.map +1 -1
  229. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.js +2 -1
  230. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
  231. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +3 -2
  232. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts.map +1 -1
  233. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.js +3 -2
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Solve `M·x = b` for a symmetric positive definite 3×3 `M`, by LDLᵀ factorisation.
3
+ *
4
+ * `M` is read as its six distinct entries, diagonal first: `[m00, m11, m22, m01, m02, m12]`.
5
+ *
6
+ * LDLᵀ rather than a cofactor inverse. The two agree in exact arithmetic and do not agree in Float64: an SPD
7
+ * matrix with a condition number in the billions has a cofactor determinant — a sum of triple products that
8
+ * has to cancel down by that ratio squared — that can come out *negative* although every eigenvalue is
9
+ * positive. The factorisation never forms those products, so its pivots stay positive where the determinant
10
+ * does not, and their product is the determinant to full precision.
11
+ *
12
+ * The pivots of an SPD matrix are `M` restricted to nested subspaces, so all three positive *is* positive
13
+ * definiteness: the function checks exactly that, and returns `false` without writing `out` when a pivot is
14
+ * not positive and finite — an indefinite, singular or non-finite `M`. An infinite pivot needs refusing
15
+ * explicitly: it is positive, and dividing by it reads as a finite solution, zero along that axis.
16
+ *
17
+ * @param {Float64Array|Float32Array|number[]} out solution `x`, 3 entries at `out_offset`
18
+ * @param {number} out_offset
19
+ * @param {Float64Array|Float32Array|number[]} m `[m00, m11, m22, m01, m02, m12]` at `m_offset`
20
+ * @param {number} m_offset
21
+ * @param {Float64Array|Float32Array|number[]} b right-hand side, 3 entries at `b_offset`
22
+ * @param {number} b_offset
23
+ * @returns {boolean} true when `M` was positive definite and `out` holds the solution
24
+ */
25
+ export function matrix_symmetric_3x3_solve_ldlt(
26
+ out, out_offset,
27
+ m, m_offset,
28
+ b, b_offset
29
+ ) {
30
+ const m00 = m[m_offset];
31
+ const m11 = m[m_offset + 1];
32
+ const m22 = m[m_offset + 2];
33
+ const m01 = m[m_offset + 3];
34
+ const m02 = m[m_offset + 4];
35
+ const m12 = m[m_offset + 5];
36
+
37
+ const pivot_0 = m00;
38
+ const lower_10 = m01 / pivot_0;
39
+ const lower_20 = m02 / pivot_0;
40
+
41
+ const pivot_1 = m11 - lower_10 * m01;
42
+ const lower_21 = (m12 - lower_20 * m01) / pivot_1;
43
+
44
+ const pivot_2 = m22 - lower_20 * m02 - lower_21 * lower_21 * pivot_1;
45
+
46
+ if (!(
47
+ pivot_0 > 0 && pivot_0 < Infinity
48
+ && pivot_1 > 0 && pivot_1 < Infinity
49
+ && pivot_2 > 0 && pivot_2 < Infinity
50
+ )) {
51
+ return false;
52
+ }
53
+
54
+ const b0 = b[b_offset];
55
+ const b1 = b[b_offset + 1];
56
+ const b2 = b[b_offset + 2];
57
+
58
+ // Forward substitution through L, scale by D, back substitution through Lᵀ.
59
+ const forward_1 = b1 - lower_10 * b0;
60
+ const forward_2 = b2 - lower_20 * b0 - lower_21 * forward_1;
61
+
62
+ const x2 = forward_2 / pivot_2;
63
+ const x1 = forward_1 / pivot_1 - lower_21 * x2;
64
+ const x0 = b0 / pivot_0 - lower_10 * x1 - lower_20 * x2;
65
+
66
+ out[out_offset] = x0;
67
+ out[out_offset + 1] = x1;
68
+ out[out_offset + 2] = x2;
69
+
70
+ return true;
71
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `Math.max(a, b)` without the call, as {@link min2_exact}: the larger, NaN if either is, and `+0`
3
+ * above `-0`.
4
+ *
5
+ * {@link max2} drops a NaN in `b` and lets the first of two zeros win; this does neither.
6
+ *
7
+ * The same as `Math.max` under `Object.is` for every pair of numbers, except that a NaN answer is the
8
+ * canonical NaN.
9
+ *
10
+ * @param {number} a
11
+ * @param {number} b
12
+ * @returns {number}
13
+ */
14
+ export function max2_exact(a: number, b: number): number;
15
+ //# sourceMappingURL=max2_exact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"max2_exact.d.ts","sourceRoot":"","sources":["../../../../src/core/math/max2_exact.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,8BAJW,MAAM,KACN,MAAM,GACJ,MAAM,CAkBlB"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * `Math.max(a, b)` without the call, as {@link min2_exact}: the larger, NaN if either is, and `+0`
3
+ * above `-0`.
4
+ *
5
+ * {@link max2} drops a NaN in `b` and lets the first of two zeros win; this does neither.
6
+ *
7
+ * The same as `Math.max` under `Object.is` for every pair of numbers, except that a NaN answer is the
8
+ * canonical NaN.
9
+ *
10
+ * @param {number} a
11
+ * @param {number} b
12
+ * @returns {number}
13
+ */
14
+ export function max2_exact(a, b) {
15
+ if (a > b) {
16
+ return a;
17
+ }
18
+
19
+ if (b > a) {
20
+ return b;
21
+ }
22
+
23
+ if (a === b) {
24
+ // equal, and of two zeros the positive one if either is
25
+ return a === 0 && 1 / a < 0 ? b : a;
26
+ }
27
+
28
+ // one of them is NaN
29
+ return NaN;
30
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * `Math.min(a, b)` without the call: the smaller, NaN if either is, and `-0` below `+0`.
3
+ *
4
+ * {@link min2} is `a < b ? a : b`, which answers `b` whenever the comparison is false — a NaN in `a`
5
+ * is dropped, and of two zeros the second one wins. That is right for a running minimum over values
6
+ * known to be numbers, and wrong for a bound that has to stay poisoned when its input was.
7
+ *
8
+ * Why not `Math.min` itself: in code V8 has not optimised yet (a function run a few times a step can
9
+ * stay unoptimised for thousands of steps), `Math.min` is a call into a builtin that hands its answer
10
+ * back boxed into a heap object. This is comparisons only.
11
+ *
12
+ * The same as `Math.min` under `Object.is` for every pair of numbers. A NaN answer is the canonical
13
+ * NaN; which NaN `Math.min` answers is the platform's (on x64, the one with the sign bit set).
14
+ *
15
+ * @param {number} a
16
+ * @param {number} b
17
+ * @returns {number}
18
+ */
19
+ export function min2_exact(a: number, b: number): number;
20
+ //# sourceMappingURL=min2_exact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"min2_exact.d.ts","sourceRoot":"","sources":["../../../../src/core/math/min2_exact.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,8BAJW,MAAM,KACN,MAAM,GACJ,MAAM,CAkBlB"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * `Math.min(a, b)` without the call: the smaller, NaN if either is, and `-0` below `+0`.
3
+ *
4
+ * {@link min2} is `a < b ? a : b`, which answers `b` whenever the comparison is false — a NaN in `a`
5
+ * is dropped, and of two zeros the second one wins. That is right for a running minimum over values
6
+ * known to be numbers, and wrong for a bound that has to stay poisoned when its input was.
7
+ *
8
+ * Why not `Math.min` itself: in code V8 has not optimised yet (a function run a few times a step can
9
+ * stay unoptimised for thousands of steps), `Math.min` is a call into a builtin that hands its answer
10
+ * back boxed into a heap object. This is comparisons only.
11
+ *
12
+ * The same as `Math.min` under `Object.is` for every pair of numbers. A NaN answer is the canonical
13
+ * NaN; which NaN `Math.min` answers is the platform's (on x64, the one with the sign bit set).
14
+ *
15
+ * @param {number} a
16
+ * @param {number} b
17
+ * @returns {number}
18
+ */
19
+ export function min2_exact(a, b) {
20
+ if (a < b) {
21
+ return a;
22
+ }
23
+
24
+ if (b < a) {
25
+ return b;
26
+ }
27
+
28
+ if (a === b) {
29
+ // equal, and of two zeros the negative one if either is
30
+ return a === 0 && 1 / a > 0 ? b : a;
31
+ }
32
+
33
+ // one of them is NaN
34
+ return NaN;
35
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"IKGoalSystem.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/ik/IKGoalSystem.js"],"names":[],"mappings":"AAyOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH;;IAEI,6DAA6C;IAE7C,kbASE;IAEF;;;OAGG;IACH,gBAFU,MAAM,CAEI;IAEpB;;;OAGG;IACH,WAFU,MAAM,CAEC;IAkDjB;;;;OAIG;IACH,WAJW,MAAM,cACN,mBAAmB,UACnB,MAAM,QAgChB;IAED;;;;OAIG;IACH,aAJW,MAAM,cACN,mBAAmB,UACnB,MAAM,QAkBhB;IAED,sCA+BC;;CA6nBJ;uBA1hCsB,cAAc;oCAED,gDAAgD;uBAQ7D,aAAa;4BAD7B,6BAA6B;4CA1BQ,oDAAoD;yCAEvD,uDAAuD;0BAQtE,2BAA2B;kCAEnB,6BAA6B;6BAIlC,2BAA2B;sBAPlC,4BAA4B"}
1
+ {"version":3,"file":"IKGoalSystem.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/ik/IKGoalSystem.js"],"names":[],"mappings":"AA0OA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH;;IAEI,6DAA6C;IAE7C,kbASE;IAEF;;;OAGG;IACH,gBAFU,MAAM,CAEI;IAEpB;;;OAGG;IACH,WAFU,MAAM,CAEC;IAkDjB;;;;OAIG;IACH,WAJW,MAAM,cACN,mBAAmB,UACnB,MAAM,QAgChB;IAED;;;;OAIG;IACH,aAJW,MAAM,cACN,mBAAmB,UACnB,MAAM,QAkBhB;IAED,sCA+BC;;CA6nBJ;uBA1hCsB,cAAc;oCAED,gDAAgD;uBAQ7D,aAAa;4BAD7B,6BAA6B;4CA3BQ,oDAAoD;yCAEvD,uDAAuD;0BAQtE,2BAA2B;kCAEnB,6BAA6B;6BAIlC,2BAA2B;sBAPlC,4BAA4B"}
@@ -19,6 +19,7 @@ import { GPUStateAuthorityFlags } from "../gpu/GPUStateAuthorityFlags.js";
19
19
  import { gpu_authority_hold } from "../gpu/gpu_authority_hold.js";
20
20
  import { gpu_authority_unhold } from "../gpu/gpu_authority_unhold.js";
21
21
  import { ParentEntity } from "../parent/ParentEntity.js";
22
+ import { parent_entity_model_of } from "../parent/parent_entity_model_of.js";
22
23
  import { System } from "../System.js";
23
24
  import { TRANSFORM_ATTACHMENT_EVENT_CHANGE } from "../transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.js";
24
25
  import { TransformAttachment } from "../transform-attachment/TransformAttachment.js";
@@ -354,8 +355,8 @@ export class IKGoalSystem extends System {
354
355
  record.entity = entity;
355
356
  record.goal = goal;
356
357
  record.system = this;
357
- record.model = model_of(dataset, entity);
358
- record.target_model = dataset.entityExists(goal.target) ? model_of(dataset, goal.target) : -1;
358
+ record.model = parent_entity_model_of(dataset, entity);
359
+ record.target_model = dataset.entityExists(goal.target) ? parent_entity_model_of(dataset, goal.target) : -1;
359
360
 
360
361
  this.#records.set(entity, record);
361
362
 
@@ -1071,23 +1072,6 @@ export class IKGoalSystem extends System {
1071
1072
  }
1072
1073
  }
1073
1074
 
1074
- /**
1075
- * The entity whose clips drive `entity`: the model its lifetime belongs to, or itself.
1076
- *
1077
- * @param {EntityComponentDataset} dataset
1078
- * @param {number} entity
1079
- * @returns {number}
1080
- */
1081
- function model_of(dataset, entity) {
1082
- const owner = dataset.getComponent(entity, ParentEntity);
1083
-
1084
- if (owner === undefined || owner === null) {
1085
- return entity;
1086
- }
1087
-
1088
- return owner.entity;
1089
- }
1090
-
1091
1075
  /**
1092
1076
  * Goals grouped by connected paths: two goals whose paths share a bone are solved together.
1093
1077
  *
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The entity whose clips drive `entity`: the model its lifetime belongs to, or itself.
3
+ *
4
+ * A placed model's bones each carry a {@link ParentEntity} naming the model's root, and the root is
5
+ * where the model's clips and animation drivers live. So the model of a bone is one step up the
6
+ * lifetime edge, and an entity without one — a root, a prop, a hand-made rig — is its own model.
7
+ *
8
+ * One step, not a walk to the top: a model placed under another model is still its own model, with
9
+ * its own clips.
10
+ *
11
+ * @param {EntityComponentDataset} dataset
12
+ * @param {number} entity
13
+ * @returns {number} the model entity; `entity` itself when it has no {@link ParentEntity}, or one
14
+ * naming no entity yet (`-1`)
15
+ */
16
+ export function parent_entity_model_of(dataset: EntityComponentDataset, entity: number): number;
17
+ //# sourceMappingURL=parent_entity_model_of.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parent_entity_model_of.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/parent/parent_entity_model_of.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,gFAJW,MAAM,GACJ,MAAM,CAWlB"}
@@ -0,0 +1,26 @@
1
+ import { ParentEntity } from "./ParentEntity.js";
2
+
3
+ /**
4
+ * The entity whose clips drive `entity`: the model its lifetime belongs to, or itself.
5
+ *
6
+ * A placed model's bones each carry a {@link ParentEntity} naming the model's root, and the root is
7
+ * where the model's clips and animation drivers live. So the model of a bone is one step up the
8
+ * lifetime edge, and an entity without one — a root, a prop, a hand-made rig — is its own model.
9
+ *
10
+ * One step, not a walk to the top: a model placed under another model is still its own model, with
11
+ * its own clips.
12
+ *
13
+ * @param {EntityComponentDataset} dataset
14
+ * @param {number} entity
15
+ * @returns {number} the model entity; `entity` itself when it has no {@link ParentEntity}, or one
16
+ * naming no entity yet (`-1`)
17
+ */
18
+ export function parent_entity_model_of(dataset, entity) {
19
+ const owner = dataset.getComponent(entity, ParentEntity);
20
+
21
+ if (owner === undefined || owner === null || owner.entity < 0) {
22
+ return entity;
23
+ }
24
+
25
+ return owner.entity;
26
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Pack a transform's rigid pose, `[tx, ty, tz, qx, qy, qz, qw]`, into an array: the translation and
3
+ * the rotation, without the scale or the matrix.
4
+ *
5
+ * Seven floats is the shape a contact kernel, an oriented box transform or a cloth holder takes a
6
+ * pose in. Read off the transform's lanes (a {@link Transform64} is a `Float64Array`) rather than
7
+ * through `translation_x` and the rest: a hot caller that does not inline those accessor calls gets
8
+ * each number back boxed, and the vector getters allocate outright.
9
+ *
10
+ * @param {number[]|Float32Array|Float64Array} out
11
+ * @param {number} out_offset receives 7 floats
12
+ * @param {Transform64|Float64Array} transform a `Transform64`, or an array in its layout
13
+ */
14
+ export function t64_read_pose_array(out: number[] | Float32Array | Float64Array, out_offset: number, transform: Transform64 | Float64Array): void;
15
+ //# sourceMappingURL=t64_read_pose_array.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"t64_read_pose_array.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/transform/t64_read_pose_array.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,yCAJW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,cAClC,MAAM,aACN,cAAY,YAAY,QAUlC"}
@@ -0,0 +1,24 @@
1
+ import { TRANSFORM64_ROTATION_OFFSET, TRANSFORM64_TRANSLATION_OFFSET } from "./Transform64.js";
2
+
3
+ /**
4
+ * Pack a transform's rigid pose, `[tx, ty, tz, qx, qy, qz, qw]`, into an array: the translation and
5
+ * the rotation, without the scale or the matrix.
6
+ *
7
+ * Seven floats is the shape a contact kernel, an oriented box transform or a cloth holder takes a
8
+ * pose in. Read off the transform's lanes (a {@link Transform64} is a `Float64Array`) rather than
9
+ * through `translation_x` and the rest: a hot caller that does not inline those accessor calls gets
10
+ * each number back boxed, and the vector getters allocate outright.
11
+ *
12
+ * @param {number[]|Float32Array|Float64Array} out
13
+ * @param {number} out_offset receives 7 floats
14
+ * @param {Transform64|Float64Array} transform a `Transform64`, or an array in its layout
15
+ */
16
+ export function t64_read_pose_array(out, out_offset, transform) {
17
+ out[out_offset] = transform[TRANSFORM64_TRANSLATION_OFFSET];
18
+ out[out_offset + 1] = transform[TRANSFORM64_TRANSLATION_OFFSET + 1];
19
+ out[out_offset + 2] = transform[TRANSFORM64_TRANSLATION_OFFSET + 2];
20
+ out[out_offset + 3] = transform[TRANSFORM64_ROTATION_OFFSET];
21
+ out[out_offset + 4] = transform[TRANSFORM64_ROTATION_OFFSET + 1];
22
+ out[out_offset + 5] = transform[TRANSFORM64_ROTATION_OFFSET + 2];
23
+ out[out_offset + 6] = transform[TRANSFORM64_ROTATION_OFFSET + 3];
24
+ }
@@ -17,6 +17,8 @@
17
17
  * to synthesise some arbitrary unit vector and hand it over as though it were a
18
18
  * measurement.
19
19
  *
20
+ * An indexed form of {@link tri3_compute_normal_area_weighted_array}, which holds the arithmetic.
21
+ *
20
22
  * Single-face callers — a raycast normal, a plane side test — want
21
23
  * {@link geometry_construct_triangle_normal} instead.
22
24
  *
@@ -1 +1 @@
1
- {"version":3,"file":"geometry_construct_triangle_normal_area_weighted.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics/geometry/geometry_construct_triangle_normal_area_weighted.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,sEARW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,cAClC,MAAM,KACN,MAAM,KACN,MAAM,KACN,MAAM,aACN,MAAM,EAAE,GAAC,YAAY,GACnB,IAAI,CAwBhB"}
1
+ {"version":3,"file":"geometry_construct_triangle_normal_area_weighted.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics/geometry/geometry_construct_triangle_normal_area_weighted.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,sEARW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,cAClC,MAAM,KACN,MAAM,KACN,MAAM,KACN,MAAM,aACN,MAAM,EAAE,GAAC,YAAY,GACnB,IAAI,CAShB"}
@@ -1,3 +1,5 @@
1
+ import { tri3_compute_normal_area_weighted_array } from "../../../core/geom/3d/triangle/tri3_compute_normal_area_weighted_array.js";
2
+
1
3
  /**
2
4
  * The face normal of an indexed triangle, NOT normalised — the raw
3
5
  * `(c - b) × (a - b)`, whose magnitude is twice the triangle's area.
@@ -17,6 +19,8 @@
17
19
  * to synthesise some arbitrary unit vector and hand it over as though it were a
18
20
  * measurement.
19
21
  *
22
+ * An indexed form of {@link tri3_compute_normal_area_weighted_array}, which holds the arithmetic.
23
+ *
20
24
  * Single-face callers — a raycast normal, a plane side test — want
21
25
  * {@link geometry_construct_triangle_normal} instead.
22
26
  *
@@ -29,25 +33,10 @@
29
33
  * @returns {void}
30
34
  */
31
35
  export function geometry_construct_triangle_normal_area_weighted(out, out_offset, a, b, c, positions) {
32
-
33
- const a_address = a * 3;
34
- const b_address = b * 3;
35
- const c_address = c * 3;
36
-
37
- const bx = positions[b_address];
38
- const by = positions[b_address + 1];
39
- const bz = positions[b_address + 2];
40
-
41
- const cb_x = positions[c_address] - bx;
42
- const cb_y = positions[c_address + 1] - by;
43
- const cb_z = positions[c_address + 2] - bz;
44
-
45
- const ab_x = positions[a_address] - bx;
46
- const ab_y = positions[a_address + 1] - by;
47
- const ab_z = positions[a_address + 2] - bz;
48
-
49
- // the same winding `tri3_compute_normal` uses, so the direction agrees
50
- out[out_offset] = cb_y * ab_z - cb_z * ab_y;
51
- out[out_offset + 1] = cb_z * ab_x - cb_x * ab_z;
52
- out[out_offset + 2] = cb_x * ab_y - cb_y * ab_x;
36
+ tri3_compute_normal_area_weighted_array(
37
+ out, out_offset,
38
+ positions, a * 3,
39
+ positions, b * 3,
40
+ positions, c * 3
41
+ );
53
42
  }
@@ -6,6 +6,10 @@
6
6
  * components, whoever put them there — a model `MeshSystem` loaded, or a rig built in code. New
7
7
  * clips are a new component, which this system sees as the entity leaving and coming back.
8
8
  *
9
+ * **Every node the clips key holds a row here** ({@link hold_clip_targets}), from the graph being
10
+ * bound to the clips until they go. A clip binds only once all of them do, and a keyed node outside
11
+ * every skin with nothing drawn under it — a socket, say — is held by no other system.
12
+ *
9
13
  * **It is the CPU that plays the animation and the GPU that draws it.** Shade can advance a clip
10
14
  * itself, and this never asks it to — `AnimationClipFlags.Playing` is left clear and every audible
11
15
  * clip's time is written down each frame from the controller's own clock. That is I-4: the pose
@@ -66,6 +70,7 @@ export class AnimationGraphSystem extends System<any> {
66
70
  * @param {number} entity
67
71
  */
68
72
  unlink(controller: AnimationGraphController, clips: AnimationClips, entity: number): void;
73
+ startup(entityManager: any): Promise<void>;
69
74
  shutdown(entityManager: any): Promise<void>;
70
75
  #private;
71
76
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AnimationGraphSystem.d.ts","sourceRoot":"","sources":["../../../../src/engine/graphics3/AnimationGraphSystem.js"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;GAkBG;AACH;IAkBI;;;OAGG;IACH,oDAgBC;IAPG,0EAA8D;IAI9D,gFAEC;IAGL;;;;;;;;;OASG;IACH,iBAJW,wBAAwB,SACxB,cAAc,UACd,MAAM,QAchB;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,6BANW,YAAY,EAAE,UACd,MAAM,GACJ,OAAO,CAgDnB;IAED;;;;OAIG;IACH,mBAJW,wBAAwB,SACxB,cAAc,UACd,MAAM,QAYhB;IAED,4CAQC;;CAkJJ;uBAzUsB,kBAAkB;yCAEA,yCAAyC;+BADnD,+BAA+B;4CAHlB,iDAAiD;6BAChE,qDAAqD"}
1
+ {"version":3,"file":"AnimationGraphSystem.d.ts","sourceRoot":"","sources":["../../../../src/engine/graphics3/AnimationGraphSystem.js"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IAyBI;;;OAGG;IACH,oDAgBC;IAPG,0EAA8D;IAI9D,gFAEC;IAGL;;;;;;;;;OASG;IACH,iBAJW,wBAAwB,SACxB,cAAc,UACd,MAAM,QAehB;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,6BANW,YAAY,EAAE,UACd,MAAM,GACJ,OAAO,CAgDnB;IAED;;;;OAIG;IACH,mBAJW,wBAAwB,SACxB,cAAc,UACd,MAAM,QAkBhB;IAED,2CAaC;IAED,4CAWC;;CA2JJ;uBAvXsB,kBAAkB;yCAEA,yCAAyC;+BADnD,+BAA+B;4CAHlB,iDAAiD;6BAChE,qDAAqD"}
@@ -6,7 +6,8 @@ import { System } from "../ecs/System.js";
6
6
  import { AnimationClips } from "./animation/AnimationClips.js";
7
7
  import { AnimationGraphController } from "./animation/AnimationGraphController.js";
8
8
  import { write_graph_playback } from "./animation/write_graph_playback.js";
9
- import { register_clips, unregister_clips } from "./register_clips.js";
9
+ import { hold_clip_targets, register_clips, release_clip_targets, unregister_clips } from "./register_clips.js";
10
+ import { RowChains } from "./RowChains.js";
10
11
 
11
12
  /**
12
13
  * Drives every entity's {@link AnimationGraphController}: runs its clock, and tells the renderer
@@ -16,6 +17,10 @@ import { register_clips, unregister_clips } from "./register_clips.js";
16
17
  * components, whoever put them there — a model `MeshSystem` loaded, or a rig built in code. New
17
18
  * clips are a new component, which this system sees as the entity leaving and coming back.
18
19
  *
20
+ * **Every node the clips key holds a row here** ({@link hold_clip_targets}), from the graph being
21
+ * bound to the clips until they go. A clip binds only once all of them do, and a keyed node outside
22
+ * every skin with nothing drawn under it — a socket, say — is held by no other system.
23
+ *
19
24
  * **It is the CPU that plays the animation and the GPU that draws it.** Shade can advance a clip
20
25
  * itself, and this never asks it to — `AnimationClipFlags.Playing` is left clear and every audible
21
26
  * clip's time is written down each frame from the controller's own clock. That is I-4: the pose
@@ -41,10 +46,17 @@ export class AnimationGraphSystem extends System {
41
46
  #scene;
42
47
 
43
48
  /**
44
- * @type {Map<number, {controller: AnimationGraphController, clips: ShadeAnimationClip[], bound: boolean, clip_registration: ClipRegistration|null, slots: Int32Array, played_slots: Int32Array, clip_ids: Int32Array, weights: Float32Array, poses: PosePlayback[]}>}
49
+ * @type {Map<number, {controller: AnimationGraphController, clips: ShadeAnimationClip[], bound: boolean, held: boolean, clip_registration: ClipRegistration|null, slots: Int32Array, played_slots: Int32Array, clip_ids: Int32Array, weights: Float32Array, poses: PosePlayback[]}>}
45
50
  */
46
51
  #entries = new Map();
47
52
 
53
+ /**
54
+ * The chains of the nodes the clips key. Null until the system has a dataset.
55
+ *
56
+ * @type {RowChains|null}
57
+ */
58
+ #chains = null;
59
+
48
60
  /**
49
61
  * @param {GraphicsEngine} graphics
50
62
  * @param {Scene} scene
@@ -82,6 +94,7 @@ export class AnimationGraphSystem extends System {
82
94
  controller,
83
95
  clips: clips.clips,
84
96
  bound: false,
97
+ held: false,
85
98
  clip_registration: null,
86
99
  slots: new Int32Array(0),
87
100
  played_slots: new Int32Array(0),
@@ -172,11 +185,32 @@ export class AnimationGraphSystem extends System {
172
185
 
173
186
  if (entry !== undefined) {
174
187
  this.#release_clips(entry);
188
+
189
+ if (entry.held) {
190
+ release_clip_targets(this.#chains, entry.clips);
191
+
192
+ entry.held = false;
193
+ }
175
194
  }
176
195
 
177
196
  this.#entries.delete(entity);
178
197
  }
179
198
 
199
+ async startup(entityManager) {
200
+ // the scene's rows are this dataset's entities; the first system to place one says so
201
+ const dataset = entityManager.dataset;
202
+ const scene = this.#scene;
203
+
204
+ assert.ok(
205
+ scene.dataset === null || scene.dataset === undefined || scene.dataset === dataset,
206
+ 'the scene is bound to another dataset'
207
+ );
208
+
209
+ scene.dataset = dataset;
210
+
211
+ this.#chains = new RowChains(dataset);
212
+ }
213
+
180
214
  async shutdown(entityManager) {
181
215
  for (const entry of this.#entries.values()) {
182
216
  entry.controller.unlink();
@@ -185,6 +219,9 @@ export class AnimationGraphSystem extends System {
185
219
  }
186
220
 
187
221
  this.#entries.clear();
222
+
223
+ this.#chains.destroy();
224
+ this.#chains = null;
188
225
  }
189
226
 
190
227
  /**
@@ -223,6 +260,9 @@ export class AnimationGraphSystem extends System {
223
260
  // that fires an ability while the renderer is being replaced still fires it.
224
261
  const manager = context === null ? null : context.animation_manager;
225
262
 
263
+ // a new context after a restart is acquired in whole; until there is one, holds are recorded
264
+ this.#chains.bind(context === null ? null : context.rows);
265
+
226
266
  for (const [entity, entry] of this.#entries) {
227
267
  if (!entry.bound) {
228
268
  this.#bind_clips(entry, entity, ecd);
@@ -302,6 +342,12 @@ export class AnimationGraphSystem extends System {
302
342
  entry.poses = clips.map(() => new PosePlayback());
303
343
 
304
344
  entry.bound = true;
345
+
346
+ // past the throw above, so a graph that cannot be bound holds nothing; and before anything
347
+ // registers, so the clips bind in the update that registers them
348
+ hold_clip_targets(this.#chains, clips);
349
+
350
+ entry.held = true;
305
351
  }
306
352
 
307
353
  /**
@@ -11,6 +11,10 @@
11
11
  * components, whoever put them there — a model `MeshSystem` loaded, or a rig built in code. New
12
12
  * clips are a new component, which this system sees as the entity leaving and coming back.
13
13
  *
14
+ * **Every node the clips key holds a row here** ({@link hold_clip_targets}), from the clips being
15
+ * taken up until they go. A clip binds only once all of them do, and a keyed node outside every skin
16
+ * with nothing drawn under it is held by no other system.
17
+ *
14
18
  * **It is the CPU that plays the animation and the GPU that draws it.** Shade can advance a clip
15
19
  * itself, and this never asks it to — `AnimationClipFlags.Playing` is left clear and every audible
16
20
  * clip's time is written down each frame from the player's own clock. That is I-4: the pose
@@ -76,6 +80,7 @@ export class AnimationSystem extends System<any> {
76
80
  * @param {number} entity
77
81
  */
78
82
  unlink(component: Animation, clips: AnimationClips, entity: number): void;
83
+ startup(entityManager: any): Promise<void>;
79
84
  shutdown(entityManager: any): Promise<void>;
80
85
  #private;
81
86
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AnimationSystem.d.ts","sourceRoot":"","sources":["../../../../src/engine/graphics3/AnimationSystem.js"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IAkBI;;;OAGG;IACH,oDAgBC;IAPG,2DAA+C;IAI/C,iEAEC;IAGL;;;;;;;;OAQG;IACH,qBAHW,MAAM,GACJ,cAAc,CAU1B;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,6BANW,YAAY,EAAE,UACd,MAAM,GACJ,OAAO,CAyCnB;IAED;;;;;;;;OAQG;IACH,gBAJW,SAAS,SACT,cAAc,UACd,MAAM,QAYhB;IAED;;;;OAIG;IACH,kBAJW,SAAS,SACT,cAAc,UACd,MAAM,QAUhB;IAED,4CAMC;;CAsKJ;uBAxWsB,kBAAkB;0BADf,+BAA+B;+BAE1B,+BAA+B;4CAJlB,iDAAiD;6BAChE,qDAAqD"}
1
+ {"version":3,"file":"AnimationSystem.d.ts","sourceRoot":"","sources":["../../../../src/engine/graphics3/AnimationSystem.js"],"names":[],"mappings":"AAiBA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH;IAyBI;;;OAGG;IACH,oDAgBC;IAPG,2DAA+C;IAI/C,iEAEC;IAGL;;;;;;;;OAQG;IACH,qBAHW,MAAM,GACJ,cAAc,CAU1B;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,6BANW,YAAY,EAAE,UACd,MAAM,GACJ,OAAO,CAyCnB;IAED;;;;;;;;OAQG;IACH,gBAJW,SAAS,SACT,cAAc,UACd,MAAM,QAahB;IAED;;;;OAIG;IACH,kBAJW,SAAS,SACT,cAAc,UACd,MAAM,QAgBhB;IAED,2CAaC;IAED,4CASC;;CA8KJ;uBArZsB,kBAAkB;0BADf,+BAA+B;+BAE1B,+BAA+B;4CAJlB,iDAAiD;6BAChE,qDAAqD"}