@woosh/meep-engine 3.43.0 → 3.44.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.
- package/editor/prototypeEditorShell.d.ts.map +1 -1
- package/editor/prototypeEditorShell.js +4 -2
- package/package.json +1 -1
- package/src/engine/Clock.d.ts +15 -0
- package/src/engine/Clock.d.ts.map +1 -1
- package/src/engine/Clock.js +29 -5
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +11 -19
- package/src/engine/graphics/ecs/mesh-v2/MeshSkin.d.ts +57 -0
- package/src/engine/graphics/ecs/mesh-v2/MeshSkin.d.ts.map +1 -0
- package/src/engine/graphics/ecs/mesh-v2/MeshSkin.js +84 -0
- package/src/engine/graphics3/AnimationGraphSystem.d.ts +23 -13
- package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationGraphSystem.js +61 -64
- package/src/engine/graphics3/AnimationSystem.d.ts +24 -15
- package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationSystem.js +67 -61
- package/src/engine/graphics3/MeshSkinSystem.d.ts +56 -0
- package/src/engine/graphics3/MeshSkinSystem.d.ts.map +1 -0
- package/src/engine/graphics3/MeshSkinSystem.js +317 -0
- package/src/engine/graphics3/MeshSystem.d.ts +15 -35
- package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
- package/src/engine/graphics3/MeshSystem.js +21 -298
- package/src/engine/graphics3/RowChains.d.ts +76 -0
- package/src/engine/graphics3/RowChains.d.ts.map +1 -0
- package/src/engine/graphics3/RowChains.js +347 -0
- package/src/engine/graphics3/ShadedGeometrySystem.d.ts +6 -0
- package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
- package/src/engine/graphics3/ShadedGeometrySystem.js +329 -309
- package/src/engine/graphics3/animation/AnimationClips.d.ts +56 -0
- package/src/engine/graphics3/animation/AnimationClips.d.ts.map +1 -0
- package/src/engine/graphics3/animation/AnimationClips.js +79 -0
- package/src/engine/graphics3/animation/ClipListPlayer.d.ts +13 -14
- package/src/engine/graphics3/animation/ClipListPlayer.d.ts.map +1 -1
- package/src/engine/graphics3/animation/ClipListPlayer.js +262 -263
- package/src/engine/graphics3/animation/write_clip_playback.d.ts +3 -3
- package/src/engine/graphics3/animation/write_clip_playback.js +4 -4
- package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts +5 -0
- package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts.map +1 -1
- package/src/engine/graphics3/pose/query_entity_node_world_pose.js +80 -75
- package/src/engine/graphics3/prefab/PrefabInstance.d.ts +4 -24
- package/src/engine/graphics3/prefab/PrefabInstance.d.ts.map +1 -1
- package/src/engine/graphics3/prefab/PrefabInstance.js +60 -80
- package/src/engine/graphics3/prefab/prefab_instantiate.d.ts +16 -3
- package/src/engine/graphics3/prefab/prefab_instantiate.d.ts.map +1 -1
- package/src/engine/graphics3/prefab/prefab_instantiate.js +49 -12
- package/src/engine/graphics3/prefab/prefab_place.d.ts +31 -17
- package/src/engine/graphics3/prefab/prefab_place.d.ts.map +1 -1
- package/src/engine/graphics3/prefab/prefab_place.js +175 -130
- package/src/engine/graphics3/register_clips.d.ts +64 -0
- package/src/engine/graphics3/register_clips.d.ts.map +1 -0
- package/src/engine/graphics3/register_clips.js +114 -0
- package/src/engine/physics/cloth/MEASUREMENTS.md +795 -0
- package/src/engine/physics/cloth/PLAN.md +339 -9
- package/src/engine/physics/cloth/build/ClothProxy.d.ts +113 -61
- package/src/engine/physics/cloth/build/ClothProxy.d.ts.map +1 -1
- package/src/engine/physics/cloth/build/ClothProxy.js +142 -77
- package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts +22 -0
- package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts.map +1 -0
- package/src/engine/physics/cloth/build/cloth_bind_in_frame.js +75 -0
- package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts +43 -30
- package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts.map +1 -1
- package/src/engine/physics/cloth/build/cloth_proxy_from_joints.js +357 -284
- package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.d.ts +62 -0
- package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.d.ts.map +1 -0
- package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.js +280 -0
- package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts +1 -1
- package/src/engine/physics/cloth/collider/cloth_collider_sdf.js +1 -1
- package/src/engine/physics/cloth/ecs/Cloth.d.ts +17 -9
- package/src/engine/physics/cloth/ecs/Cloth.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/Cloth.js +220 -212
- package/src/engine/physics/cloth/ecs/ClothDynamicsFlags.js +6 -0
- package/src/engine/physics/cloth/ecs/ClothHold.d.ts +91 -0
- package/src/engine/physics/cloth/ecs/ClothHold.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothHold.js +103 -0
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +254 -48
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothInstance.js +277 -47
- package/src/engine/physics/cloth/ecs/ClothPin.d.ts +73 -0
- package/src/engine/physics/cloth/ecs/ClothPin.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothPin.js +92 -0
- package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.d.ts +36 -0
- package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.js +61 -0
- package/src/engine/physics/cloth/ecs/ClothRig.d.ts +23 -17
- package/src/engine/physics/cloth/ecs/ClothRig.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothRig.js +29 -27
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +12 -14
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothSystem.js +20 -15
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +57 -36
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothWorld.js +816 -179
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +12 -13
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +20 -14
- package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts +63 -11
- package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_build_rows.js +321 -84
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +9 -7
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +9 -7
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +3 -3
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +30 -30
- package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts +37 -0
- package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/cloth_geodesic.js +142 -0
- package/src/engine/physics/cloth/ecs/cloth_holds.d.ts +97 -0
- package/src/engine/physics/cloth/ecs/cloth_holds.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/cloth_holds.js +608 -0
- package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts +2 -2
- package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.js +160 -9
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +17 -22
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +55 -117
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +21 -6
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +44 -15
- package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts +5 -0
- package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_write_back.js +60 -16
- package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_write_back_rig.js +65 -58
- package/src/engine/physics/cloth/playground/collide_main.js +1 -1
- package/src/engine/physics/cloth/playground/garment_build.d.ts.map +1 -1
- package/src/engine/physics/cloth/playground/garment_build.js +17 -5
- package/src/engine/physics/cloth/playground/garment_main.js +1 -1
- package/src/engine/physics/cloth/playground/rig_build.d.ts.map +1 -1
- package/src/engine/physics/cloth/playground/rig_build.js +302 -296
- package/src/engine/physics/cloth/solver/ClothState.d.ts +45 -7
- package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/ClothState.js +63 -7
- package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +6 -1
- package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_contact_find.js +7 -2
- package/src/engine/physics/cloth/solver/cloth_hold_line.d.ts +114 -0
- package/src/engine/physics/cloth/solver/cloth_hold_line.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/cloth_hold_line.js +362 -0
- package/src/engine/physics/cloth/solver/cloth_self_find.d.ts +6 -2
- package/src/engine/physics/cloth/solver/cloth_self_find.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_self_find.js +13 -13
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +24 -12
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_solver_constants.js +24 -12
- package/src/engine/physics/cloth/solver/cloth_step.d.ts +16 -0
- package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_step.js +183 -20
- package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +1 -0
- package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_step_instance.js +10 -3
- package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.d.ts +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.js +353 -346
- package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts +7 -5
- package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_self_row.js +7 -5
- package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +9 -9
- package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -1
- package/src/engine/physics/cloth/wind/cloth_sample_air.js +26 -26
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/simulation/Ticker.d.ts +13 -0
- package/src/engine/simulation/Ticker.d.ts.map +1 -1
- package/src/engine/simulation/Ticker.js +43 -8
- package/src/shade/RENDERER_CONTRACT.md +8 -2
- package/src/shade/playground/mesh_row_ceiling/main.js +2 -1
- package/src/shade/playground/skinned_blas_refit/main.d.ts.map +1 -1
- package/src/shade/playground/skinned_blas_refit/main.js +11 -19
- package/src/shade/playground/skinned_blas_refit/place_character.d.ts +6 -3
- package/src/shade/playground/skinned_blas_refit/place_character.d.ts.map +1 -1
- package/src/shade/playground/skinned_blas_refit/place_character.js +90 -90
- package/src/shade/playground/skinned_mesh_soup/main.d.ts.map +1 -1
- package/src/shade/playground/skinned_mesh_soup/main.js +502 -509
- package/src/shade/playground/texture_encode/README.md +129 -109
- package/src/shade/playground/texture_encode/main.js +1430 -1430
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts +45 -14
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
- package/src/shade/renderer/animation/GPUAnimationManager.js +316 -64
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts +5 -0
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +11 -1
- package/src/shade/renderer/geometry/BoxGeometry.d.ts +1 -11
- package/src/shade/renderer/geometry/BoxGeometry.d.ts.map +1 -1
- package/src/shade/renderer/geometry/BoxGeometry.js +6 -13
- package/src/shade/renderer/geometry/CapsuleGeometry.d.ts +19 -0
- package/src/shade/renderer/geometry/CapsuleGeometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/CapsuleGeometry.js +24 -0
- package/src/shade/renderer/geometry/ConeGeometry.d.ts +20 -0
- package/src/shade/renderer/geometry/ConeGeometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/ConeGeometry.js +33 -0
- package/src/shade/renderer/geometry/CylinderGeometry.d.ts +21 -0
- package/src/shade/renderer/geometry/CylinderGeometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/CylinderGeometry.js +35 -0
- package/src/shade/renderer/geometry/PlaneGeometry.d.ts +17 -0
- package/src/shade/renderer/geometry/PlaneGeometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/PlaneGeometry.js +22 -0
- package/src/shade/renderer/geometry/TorusGeometry.d.ts +18 -0
- package/src/shade/renderer/geometry/TorusGeometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/TorusGeometry.js +23 -0
- package/src/shade/renderer/geometry/UVSphereGeometry.d.ts +21 -0
- package/src/shade/renderer/geometry/UVSphereGeometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/UVSphereGeometry.js +34 -0
- package/src/shade/renderer/geometry/primitives/make_capsule_geometry.d.ts +19 -0
- package/src/shade/renderer/geometry/primitives/make_capsule_geometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/primitives/make_capsule_geometry.js +205 -0
- package/src/shade/renderer/geometry/primitives/make_cone_geometry.d.ts +21 -0
- package/src/shade/renderer/geometry/primitives/make_cone_geometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/primitives/make_cone_geometry.js +36 -0
- package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.d.ts +1 -1
- package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.d.ts.map +1 -1
- package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.js +44 -9
- package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.d.ts +20 -0
- package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.js +190 -0
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +7 -2
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts +26 -8
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.js +56 -39
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.d.ts +7 -0
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.js +46 -4
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/test_prefix_sum.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/test_prefix_sum.js +4 -2
- package/src/shade/renderer/gpu_primitive/sort/defs.d.ts +2 -2
- package/src/shade/renderer/gpu_primitive/sort/defs.js +79 -79
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts +1 -1
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +7 -3
- package/src/shade/renderer/particles/GPUParticleSystem.js +1 -1
- package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts +4 -3
- package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts.map +1 -1
- package/src/shade/renderer/particles/coherence/graph_particle_bucket.js +200 -194
- package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph_particles.js +6 -2
- package/src/shade/renderer/particles/warmup/graph_particle_warmup.d.ts.map +1 -1
- package/src/shade/renderer/particles/warmup/graph_particle_warmup.js +334 -329
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +7 -2
- package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.js +16 -4
- package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +2444 -2345
- package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.d.ts.map +1 -1
- package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.js +312 -310
- package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.d.ts +3 -3
- package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.d.ts.map +1 -1
- package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.js +383 -375
- package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.d.ts.map +1 -1
- package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.js +349 -346
- package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.d.ts +58 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.js +536 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.d.ts +21 -7
- package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.d.ts.map +1 -1
- package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.js +291 -327
- package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.d.ts +25 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.js +99 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.d.ts +5 -3
- package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.d.ts.map +1 -1
- package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.js +47 -71
- package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.d.ts +10 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.js +50 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.d.ts +4 -5
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.d.ts.map +1 -1
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.js +7 -8
- package/src/shade/renderer/water/chunk_water_transport.d.ts.map +1 -1
- package/src/shade/renderer/water/chunk_water_transport.js +7 -5
- package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +1 -1
- package/src/shade/renderer/water/medium/GPUWaterBodies.js +8 -2
- package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts +3 -2
- package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts.map +1 -1
- package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.js +3 -2
- package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
- package/src/shade/renderer/water/shader_water.js +3 -1
- package/src/shade/renderer/water/surface/GPUWaterSurface.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/GPUWaterSurface.js +3 -1
- package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/graph_water_tessellation.js +11 -4
- package/src/shade/renderer/water/surface/particles/GPUWaterParticles.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/particles/GPUWaterParticles.js +37 -20
- package/src/shade/wgsl/validate_wgsl_source.d.ts.map +1 -1
- package/src/shade/wgsl/validate_wgsl_source.js +74 -3
- package/src/engine/graphics3/register_instance_animation.d.ts +0 -114
- package/src/engine/graphics3/register_instance_animation.d.ts.map +0 -1
- package/src/engine/graphics3/register_instance_animation.js +0 -201
|
@@ -4,13 +4,10 @@ import { ResourceAccessSpecification } from "../../core/model/ResourceAccessSpec
|
|
|
4
4
|
import { PosePlayback } from "../../shade/renderer/animation/pose/PosePlayback.js";
|
|
5
5
|
import { Animation } from "../ecs/animation/Animation.js";
|
|
6
6
|
import { System } from "../ecs/System.js";
|
|
7
|
-
import {
|
|
7
|
+
import { AnimationClips } from "./animation/AnimationClips.js";
|
|
8
8
|
import { ClipListPlayer } from "./animation/ClipListPlayer.js";
|
|
9
9
|
import { write_clip_playback } from "./animation/write_clip_playback.js";
|
|
10
|
-
import {
|
|
11
|
-
register_instance_clips,
|
|
12
|
-
unregister_instance_clips
|
|
13
|
-
} from "./register_instance_animation.js";
|
|
10
|
+
import { register_clips, unregister_clips } from "./register_clips.js";
|
|
14
11
|
|
|
15
12
|
/**
|
|
16
13
|
* @type {ClipPlayback[]}
|
|
@@ -23,9 +20,13 @@ const NOTHING = Object.freeze([]);
|
|
|
23
20
|
*
|
|
24
21
|
* The list path is what the game uses wherever there is no state machine — buildings, critters and
|
|
25
22
|
* the strategy map's groups — and {@link ClipListPlayer} is what plays it. This is the ECS half:
|
|
26
|
-
* which entity has
|
|
23
|
+
* which clips each entity has, and when the ids the renderer issued for them stopped meaning
|
|
27
24
|
* anything.
|
|
28
25
|
*
|
|
26
|
+
* **The clips are the entity's {@link AnimationClips}.** An entity is driven while it carries both
|
|
27
|
+
* components, whoever put them there — a model `MeshSystem` loaded, or a rig built in code. New
|
|
28
|
+
* clips are a new component, which this system sees as the entity leaving and coming back.
|
|
29
|
+
*
|
|
29
30
|
* **It is the CPU that plays the animation and the GPU that draws it.** Shade can advance a clip
|
|
30
31
|
* itself, and this never asks it to — `AnimationClipFlags.Playing` is left clear and every audible
|
|
31
32
|
* clip's time is written down each frame from the player's own clock. That is I-4: the pose
|
|
@@ -43,32 +44,31 @@ export class AnimationSystem extends System {
|
|
|
43
44
|
#graphics;
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
|
-
* The
|
|
47
|
-
* for them.
|
|
47
|
+
* The scene whose GPU context issues the clip ids.
|
|
48
48
|
*
|
|
49
|
-
* @type {
|
|
49
|
+
* @type {Scene}
|
|
50
50
|
*/
|
|
51
|
-
#
|
|
51
|
+
#scene;
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
|
-
* @type {Map<number, {player: ClipListPlayer,
|
|
54
|
+
* @type {Map<number, {player: ClipListPlayer, clips: ShadeAnimationClip[], bound: boolean, clip_registration: ClipRegistration|null, played_slots: Int32Array, written: Float32Array, poses: PosePlayback[]}>}
|
|
55
55
|
*/
|
|
56
56
|
#entries = new Map();
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
59
|
* @param {GraphicsEngine} graphics
|
|
60
|
-
* @param {
|
|
60
|
+
* @param {Scene} scene
|
|
61
61
|
*/
|
|
62
|
-
constructor(graphics,
|
|
62
|
+
constructor(graphics, scene) {
|
|
63
63
|
super();
|
|
64
64
|
|
|
65
65
|
assert.defined(graphics, 'graphics');
|
|
66
|
-
assert.
|
|
66
|
+
assert.equal(scene?.isScene, true, 'scene.isScene !== true');
|
|
67
67
|
|
|
68
68
|
this.#graphics = graphics;
|
|
69
|
-
this.#
|
|
69
|
+
this.#scene = scene;
|
|
70
70
|
|
|
71
|
-
this.dependencies = [Animation,
|
|
71
|
+
this.dependencies = [Animation, AnimationClips];
|
|
72
72
|
|
|
73
73
|
// this tick's clip times are this system's to set: whatever evaluates a pose from them
|
|
74
74
|
// (exact queries, IK's base pose) reads Animation and so runs after it
|
|
@@ -81,8 +81,7 @@ export class AnimationSystem extends System {
|
|
|
81
81
|
* What an entity is playing, and where each of them is.
|
|
82
82
|
*
|
|
83
83
|
* One entry per clip in the component's list, in the list's own order. Empty for an entity this
|
|
84
|
-
* system is not driving — one that has left, or one whose
|
|
85
|
-
* same wait the clip durations are on.
|
|
84
|
+
* system is not driving — one that has left, or one whose clips arrived since the last update.
|
|
86
85
|
*
|
|
87
86
|
* @param {number} entity
|
|
88
87
|
* @returns {ClipPlayback[]}
|
|
@@ -98,14 +97,15 @@ export class AnimationSystem extends System {
|
|
|
98
97
|
}
|
|
99
98
|
|
|
100
99
|
/**
|
|
101
|
-
* What the entity
|
|
102
|
-
*
|
|
100
|
+
* What the entity is playing, in the form the CPU pose evaluator takes: one entry per clip of its
|
|
101
|
+
* {@link AnimationClips} that the list names, at the weight and the time the renderer has been
|
|
102
|
+
* given.
|
|
103
103
|
*
|
|
104
104
|
* **Only the clips the list names are here, because they are the only ones registered** (D37).
|
|
105
105
|
* The GPU's accumulator marks a joint dirty for every bound clip that writes to it, weight and
|
|
106
106
|
* all — so a bound clip at weight zero resolves the joints only it drives to zero rather than
|
|
107
107
|
* leaving them at rest. The answer is not to hand the surplus to the evaluator so it agrees with
|
|
108
|
-
* a mistake; it is not to bind them, and then a clip
|
|
108
|
+
* a mistake; it is not to bind them, and then a clip nothing names moves nothing.
|
|
109
109
|
*
|
|
110
110
|
* The entries are this system's own and are rewritten by the next call, which is what keeps a
|
|
111
111
|
* query on a per-frame path from allocating.
|
|
@@ -113,16 +113,17 @@ export class AnimationSystem extends System {
|
|
|
113
113
|
* @param {PosePlayback[]} target appended to
|
|
114
114
|
* @param {number} entity
|
|
115
115
|
* @returns {boolean} whether this system is driving the entity — `false` for one with no
|
|
116
|
-
* {@link Animation}, and for one whose
|
|
116
|
+
* {@link Animation} or no {@link AnimationClips}, and for one whose clips arrived since the last
|
|
117
|
+
* update
|
|
117
118
|
*/
|
|
118
119
|
write_pose_playbacks(target, entity) {
|
|
119
120
|
const entry = this.#entries.get(entity);
|
|
120
121
|
|
|
121
|
-
if (entry === undefined || entry.
|
|
122
|
+
if (entry === undefined || !entry.bound) {
|
|
122
123
|
return false;
|
|
123
124
|
}
|
|
124
125
|
|
|
125
|
-
const clips = entry.
|
|
126
|
+
const clips = entry.clips;
|
|
126
127
|
const weights = entry.player.weights;
|
|
127
128
|
const poses = entry.poses;
|
|
128
129
|
const played = entry.played_slots;
|
|
@@ -155,14 +156,19 @@ export class AnimationSystem extends System {
|
|
|
155
156
|
}
|
|
156
157
|
|
|
157
158
|
/**
|
|
159
|
+
* Only noted here: the clips are taken up by the next {@link update}. A link can happen anywhere
|
|
160
|
+
* the components are added — inside a model's spawn, for one `MeshSystem` loads — and binding is
|
|
161
|
+
* this system's work, on its own tick.
|
|
162
|
+
*
|
|
158
163
|
* @param {Animation} component
|
|
159
|
-
* @param {
|
|
164
|
+
* @param {AnimationClips} clips
|
|
160
165
|
* @param {number} entity
|
|
161
166
|
*/
|
|
162
|
-
link(component,
|
|
167
|
+
link(component, clips, entity) {
|
|
163
168
|
this.#entries.set(entity, {
|
|
164
169
|
player: ClipListPlayer.from(component),
|
|
165
|
-
|
|
170
|
+
clips: clips.clips,
|
|
171
|
+
bound: false,
|
|
166
172
|
clip_registration: null,
|
|
167
173
|
played_slots: new Int32Array(0),
|
|
168
174
|
written: new Float32Array(0),
|
|
@@ -172,10 +178,10 @@ export class AnimationSystem extends System {
|
|
|
172
178
|
|
|
173
179
|
/**
|
|
174
180
|
* @param {Animation} component
|
|
175
|
-
* @param {
|
|
181
|
+
* @param {AnimationClips} clips
|
|
176
182
|
* @param {number} entity
|
|
177
183
|
*/
|
|
178
|
-
unlink(component,
|
|
184
|
+
unlink(component, clips, entity) {
|
|
179
185
|
const entry = this.#entries.get(entity);
|
|
180
186
|
|
|
181
187
|
if (entry !== undefined) {
|
|
@@ -221,23 +227,23 @@ export class AnimationSystem extends System {
|
|
|
221
227
|
return;
|
|
222
228
|
}
|
|
223
229
|
|
|
224
|
-
if (registration.context === this.#graphics.scene_context(this.#
|
|
225
|
-
|
|
230
|
+
if (registration.context === this.#graphics.scene_context(this.#scene)) {
|
|
231
|
+
unregister_clips(registration);
|
|
226
232
|
}
|
|
227
233
|
|
|
228
234
|
entry.clip_registration = null;
|
|
229
235
|
}
|
|
230
236
|
|
|
231
237
|
/**
|
|
232
|
-
* Which of the
|
|
238
|
+
* Which of the entity's clips the list currently names, kept up to date.
|
|
233
239
|
*
|
|
234
240
|
* **The list is edited while the game runs** — `ClipListPlayer` reconciles its playbacks against
|
|
235
241
|
* it every tick, and `StopAnimationBehavior` empties it outright — so which clips are playable
|
|
236
242
|
* is not settled once at bind.
|
|
237
243
|
*
|
|
238
244
|
* Maintained here rather than alongside the registration because **the pose evaluator needs it
|
|
239
|
-
* whether or not there is a device**: `
|
|
240
|
-
*
|
|
245
|
+
* whether or not there is a device**: `collect_entity_playbacks` answers on the CPU, from the
|
|
246
|
+
* clips this driver plays, and a game with rendering disabled still asks (I-4).
|
|
241
247
|
*
|
|
242
248
|
* @param {object} entry
|
|
243
249
|
* @returns {boolean} whether the set changed
|
|
@@ -247,10 +253,9 @@ export class AnimationSystem extends System {
|
|
|
247
253
|
const played = entry.played_slots;
|
|
248
254
|
|
|
249
255
|
/*
|
|
250
|
-
The distinct slots, and distinct is the point: two entries of the list can name one clip
|
|
251
|
-
the
|
|
252
|
-
|
|
253
|
-
re-registration.
|
|
256
|
+
The distinct slots, and distinct is the point: two entries of the list can name one clip, so
|
|
257
|
+
the number of playbacks is not the number of clips. Comparing the two would report a change
|
|
258
|
+
on every frame for a list that had not moved, and a change here is a re-registration.
|
|
254
259
|
*/
|
|
255
260
|
const wanted = [];
|
|
256
261
|
|
|
@@ -289,12 +294,11 @@ export class AnimationSystem extends System {
|
|
|
289
294
|
* the joints only it drives down to zero with it.
|
|
290
295
|
*
|
|
291
296
|
* @param {object} entry
|
|
292
|
-
* @param {PrefabInstance} instance
|
|
293
297
|
* @param {GPUSceneContext} context
|
|
294
298
|
* @param {boolean} set_changed whether {@link #refresh_played_slots} just moved
|
|
295
299
|
* @returns {boolean} whether the registration was replaced
|
|
296
300
|
*/
|
|
297
|
-
#refresh_clips(entry,
|
|
301
|
+
#refresh_clips(entry, context, set_changed) {
|
|
298
302
|
const registration = entry.clip_registration;
|
|
299
303
|
|
|
300
304
|
if (!set_changed && registration !== null && registration.context === context) {
|
|
@@ -303,42 +307,44 @@ export class AnimationSystem extends System {
|
|
|
303
307
|
|
|
304
308
|
this.#release_clips_only(entry);
|
|
305
309
|
|
|
306
|
-
entry.clip_registration =
|
|
310
|
+
entry.clip_registration = register_clips(context, entry.clips, entry.played_slots);
|
|
307
311
|
|
|
308
312
|
return true;
|
|
309
313
|
}
|
|
310
314
|
|
|
315
|
+
/**
|
|
316
|
+
* Take up the entity's clips: the list is played against them from here on.
|
|
317
|
+
*
|
|
318
|
+
* @param {object} entry
|
|
319
|
+
* @param {number} entity
|
|
320
|
+
* @param {EntityComponentDataset} ecd
|
|
321
|
+
*/
|
|
322
|
+
#bind(entry, entity, ecd) {
|
|
323
|
+
const clips = entry.clips;
|
|
324
|
+
|
|
325
|
+
entry.player.bind(entity, ecd, clips);
|
|
326
|
+
|
|
327
|
+
entry.written = new Float32Array(clips.length).fill(-1);
|
|
328
|
+
entry.poses = clips.map(() => new PosePlayback());
|
|
329
|
+
|
|
330
|
+
entry.bound = true;
|
|
331
|
+
}
|
|
332
|
+
|
|
311
333
|
/**
|
|
312
334
|
* @param {number} time_delta_seconds
|
|
313
335
|
*/
|
|
314
336
|
update(time_delta_seconds) {
|
|
315
337
|
const ecd = this.entityManager.dataset;
|
|
316
338
|
|
|
317
|
-
const context = this.#graphics.scene_context(this.#
|
|
339
|
+
const context = this.#graphics.scene_context(this.#scene);
|
|
318
340
|
|
|
319
341
|
// No device — before the first start, and again after a stop. The clocks still run: a clip
|
|
320
342
|
// that ends while the renderer is being replaced still says so.
|
|
321
343
|
const manager = context === null ? null : context.animation_manager;
|
|
322
344
|
|
|
323
345
|
for (const [entity, entry] of this.#entries) {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
if (instance === null) {
|
|
327
|
-
// the model has not arrived, and its clips are what say how long they run
|
|
328
|
-
continue;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
if (instance !== entry.instance) {
|
|
332
|
-
entry.instance = instance;
|
|
333
|
-
|
|
334
|
-
entry.player.bind(entity, ecd, instance);
|
|
335
|
-
|
|
336
|
-
entry.written = new Float32Array(instance.clips.length).fill(-1);
|
|
337
|
-
entry.poses = instance.clips.map(() => new PosePlayback());
|
|
338
|
-
|
|
339
|
-
// ids the manager issued for the model that was here before name clips this one
|
|
340
|
-
// does not have
|
|
341
|
-
this.#release_clips(entry);
|
|
346
|
+
if (!entry.bound) {
|
|
347
|
+
this.#bind(entry, entity, ecd);
|
|
342
348
|
}
|
|
343
349
|
|
|
344
350
|
entry.player.tick(time_delta_seconds);
|
|
@@ -349,7 +355,7 @@ export class AnimationSystem extends System {
|
|
|
349
355
|
continue;
|
|
350
356
|
}
|
|
351
357
|
|
|
352
|
-
if (this.#refresh_clips(entry,
|
|
358
|
+
if (this.#refresh_clips(entry, context, set_changed)) {
|
|
353
359
|
// whatever the last registration was told is not what this one knows
|
|
354
360
|
entry.written.fill(-1);
|
|
355
361
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deforms every primitive that carries a {@link MeshSkin}: registers its skin with the animation
|
|
3
|
+
* manager, binds the primitive to it, and holds a row for each joint and everything above it.
|
|
4
|
+
*
|
|
5
|
+
* **It does not care where the skin came from.** `MeshSystem` puts one on each skinned primitive of
|
|
6
|
+
* a model it loads; code building a skinned mesh puts one there itself. Both are the same
|
|
7
|
+
* components on the same kinds of entities, and this is the whole of what makes them deform —
|
|
8
|
+
* `ShadedGeometrySystem` draws the clone, this binds it.
|
|
9
|
+
*
|
|
10
|
+
* **One skeleton, one registration.** A body and its hair carry a skin each, with the same joints
|
|
11
|
+
* bound the same way; the manager answers both registrations with one skin, so the skeleton's
|
|
12
|
+
* matrices are made once a frame.
|
|
13
|
+
*
|
|
14
|
+
* **Joint rows are chains** ({@link RowChains}). A joint composes on the GPU under its parent's row;
|
|
15
|
+
* under a clip-driven ancestor that is the only place its world is right, and a clip keying the
|
|
16
|
+
* ancestor binds only once the ancestor holds a row.
|
|
17
|
+
*
|
|
18
|
+
* **Registration waits for {@link update}**, never happening at link. A spawn adds components node
|
|
19
|
+
* by node, so a joint later in the file is not complete when the primitive links; and there may be
|
|
20
|
+
* no device to register with. A restart replaces the context and voids every id it issued: they are
|
|
21
|
+
* forgotten rather than handed back, and every skin registers again in the new one.
|
|
22
|
+
*/
|
|
23
|
+
export class MeshSkinSystem extends System<any> {
|
|
24
|
+
/**
|
|
25
|
+
* @param {GraphicsEngine} graphics
|
|
26
|
+
* @param {Scene} scene
|
|
27
|
+
*/
|
|
28
|
+
constructor(graphics: GraphicsEngine, scene: Scene);
|
|
29
|
+
dependencies: (typeof ShadedGeometry | typeof MeshSkin)[];
|
|
30
|
+
/**
|
|
31
|
+
* @returns {Scene}
|
|
32
|
+
*/
|
|
33
|
+
get scene(): import("../../shade/renderer/scene/Scene.js").Scene;
|
|
34
|
+
startup(entityManager: any): Promise<void>;
|
|
35
|
+
shutdown(entityManager: any): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* @param {MeshSkin} skin
|
|
38
|
+
* @param {ShadedGeometry} geometry
|
|
39
|
+
* @param {number} entity
|
|
40
|
+
*/
|
|
41
|
+
link(skin: MeshSkin, geometry: ShadedGeometry, entity: number): void;
|
|
42
|
+
/**
|
|
43
|
+
* @param {MeshSkin} skin
|
|
44
|
+
* @param {ShadedGeometry} geometry
|
|
45
|
+
* @param {number} entity
|
|
46
|
+
*/
|
|
47
|
+
unlink(skin: MeshSkin, geometry: ShadedGeometry, entity: number): void;
|
|
48
|
+
#private;
|
|
49
|
+
}
|
|
50
|
+
export type GPUSceneContext = import("../../shade/renderer/scene/GPUSceneContext.js").GPUSceneContext;
|
|
51
|
+
export type GraphicsEngine = import("./GraphicsEngine.js").GraphicsEngine;
|
|
52
|
+
export type Scene = import("../../shade/renderer/scene/Scene.js").Scene;
|
|
53
|
+
import { System } from "../ecs/System.js";
|
|
54
|
+
import { ShadedGeometry } from "../graphics/ecs/mesh-v2/ShadedGeometry.js";
|
|
55
|
+
import { MeshSkin } from "../graphics/ecs/mesh-v2/MeshSkin.js";
|
|
56
|
+
//# sourceMappingURL=MeshSkinSystem.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MeshSkinSystem.d.ts","sourceRoot":"","sources":["../../../../src/engine/graphics3/MeshSkinSystem.js"],"names":[],"mappings":"AAmDA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH;IAsCI;;;OAGG;IACH,sBAHW,cAAc,SACd,KAAK,EAYf;IADG,0DAA8C;IAGlD;;OAEG;IACH,iEAEC;IAED,2CAeC;IAED,4CAUC;IAED;;;;OAIG;IACH,WAJW,QAAQ,YACR,cAAc,UACd,MAAM,QAehB;IAED;;;;OAIG;IACH,aAJW,QAAQ,YACR,cAAc,UACd,MAAM,QAIhB;;CA8HJ;8BApTY,OAAO,+CAA+C,EAAE,eAAe;6BACvE,OAAO,qBAAqB,EAAE,cAAc;oBAC5C,OAAO,qCAAqC,EAAE,KAAK;uBATzC,kBAAkB;+BAEV,2CAA2C;yBADjD,qCAAqC"}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { assert } from "../../core/assert.js";
|
|
2
|
+
import { System } from "../ecs/System.js";
|
|
3
|
+
import { MeshSkin } from "../graphics/ecs/mesh-v2/MeshSkin.js";
|
|
4
|
+
import { ShadedGeometry } from "../graphics/ecs/mesh-v2/ShadedGeometry.js";
|
|
5
|
+
import { ShadedGeometryFlags } from "../graphics/ecs/mesh-v2/ShadedGeometryFlags.js";
|
|
6
|
+
import { RowChains } from "./RowChains.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {import("../../shade/renderer/scene/GPUSceneContext.js").GPUSceneContext} GPUSceneContext
|
|
10
|
+
* @typedef {import("./GraphicsEngine.js").GraphicsEngine} GraphicsEngine
|
|
11
|
+
* @typedef {import("../../shade/renderer/scene/Scene.js").Scene} Scene
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* What the GPU gave one skinned primitive, and in which context.
|
|
16
|
+
*/
|
|
17
|
+
class Entry {
|
|
18
|
+
/**
|
|
19
|
+
* @type {number}
|
|
20
|
+
*/
|
|
21
|
+
entity = -1;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @type {MeshSkin}
|
|
25
|
+
*/
|
|
26
|
+
skin = null;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The id the animation manager issued for the skin, or -1 while nothing is registered: not yet,
|
|
30
|
+
* no device, or a restart not yet drained.
|
|
31
|
+
*
|
|
32
|
+
* @type {number}
|
|
33
|
+
*/
|
|
34
|
+
skin_id = -1;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The context {@link skin_id} belongs to, or null while there is none.
|
|
38
|
+
*
|
|
39
|
+
* @type {GPUSceneContext|null}
|
|
40
|
+
*/
|
|
41
|
+
context = null;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Whether the joints' chains are held. They are held from the first registration until the
|
|
45
|
+
* entity leaves, across restarts: the chains re-acquire in a new context on their own.
|
|
46
|
+
*
|
|
47
|
+
* @type {boolean}
|
|
48
|
+
*/
|
|
49
|
+
held = false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Deforms every primitive that carries a {@link MeshSkin}: registers its skin with the animation
|
|
54
|
+
* manager, binds the primitive to it, and holds a row for each joint and everything above it.
|
|
55
|
+
*
|
|
56
|
+
* **It does not care where the skin came from.** `MeshSystem` puts one on each skinned primitive of
|
|
57
|
+
* a model it loads; code building a skinned mesh puts one there itself. Both are the same
|
|
58
|
+
* components on the same kinds of entities, and this is the whole of what makes them deform —
|
|
59
|
+
* `ShadedGeometrySystem` draws the clone, this binds it.
|
|
60
|
+
*
|
|
61
|
+
* **One skeleton, one registration.** A body and its hair carry a skin each, with the same joints
|
|
62
|
+
* bound the same way; the manager answers both registrations with one skin, so the skeleton's
|
|
63
|
+
* matrices are made once a frame.
|
|
64
|
+
*
|
|
65
|
+
* **Joint rows are chains** ({@link RowChains}). A joint composes on the GPU under its parent's row;
|
|
66
|
+
* under a clip-driven ancestor that is the only place its world is right, and a clip keying the
|
|
67
|
+
* ancestor binds only once the ancestor holds a row.
|
|
68
|
+
*
|
|
69
|
+
* **Registration waits for {@link update}**, never happening at link. A spawn adds components node
|
|
70
|
+
* by node, so a joint later in the file is not complete when the primitive links; and there may be
|
|
71
|
+
* no device to register with. A restart replaces the context and voids every id it issued: they are
|
|
72
|
+
* forgotten rather than handed back, and every skin registers again in the new one.
|
|
73
|
+
*/
|
|
74
|
+
export class MeshSkinSystem extends System {
|
|
75
|
+
/**
|
|
76
|
+
* @type {GraphicsEngine}
|
|
77
|
+
*/
|
|
78
|
+
#graphics;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @type {Scene}
|
|
82
|
+
*/
|
|
83
|
+
#scene;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @type {Map<number, Entry>}
|
|
87
|
+
*/
|
|
88
|
+
#entries = new Map();
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The scene's GPU context as of the last {@link update}. A different one is a restart.
|
|
92
|
+
*
|
|
93
|
+
* @type {GPUSceneContext|null}
|
|
94
|
+
*/
|
|
95
|
+
#context = null;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Entries not registered with {@link #context}: linked since the last frame, or voided by a
|
|
99
|
+
* restart. A queue rather than a scan, because the answer is almost always "nothing to do".
|
|
100
|
+
*
|
|
101
|
+
* @type {Entry[]}
|
|
102
|
+
*/
|
|
103
|
+
#unregistered = [];
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* The joints' chains. Null until the system has a dataset.
|
|
107
|
+
*
|
|
108
|
+
* @type {RowChains|null}
|
|
109
|
+
*/
|
|
110
|
+
#chains = null;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @param {GraphicsEngine} graphics
|
|
114
|
+
* @param {Scene} scene
|
|
115
|
+
*/
|
|
116
|
+
constructor(graphics, scene) {
|
|
117
|
+
super();
|
|
118
|
+
|
|
119
|
+
assert.defined(graphics, 'graphics');
|
|
120
|
+
assert.defined(scene, 'scene');
|
|
121
|
+
|
|
122
|
+
this.#graphics = graphics;
|
|
123
|
+
this.#scene = scene;
|
|
124
|
+
|
|
125
|
+
this.dependencies = [MeshSkin, ShadedGeometry];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @returns {Scene}
|
|
130
|
+
*/
|
|
131
|
+
get scene() {
|
|
132
|
+
return this.#scene;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async startup(entityManager) {
|
|
136
|
+
this.entityManager = entityManager;
|
|
137
|
+
|
|
138
|
+
// the scene's rows are this dataset's entities; the first system to place one says so
|
|
139
|
+
const dataset = entityManager.dataset;
|
|
140
|
+
const scene = this.#scene;
|
|
141
|
+
|
|
142
|
+
assert.ok(
|
|
143
|
+
scene.dataset === null || scene.dataset === undefined || scene.dataset === dataset,
|
|
144
|
+
'the scene is bound to another dataset'
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
scene.dataset = dataset;
|
|
148
|
+
|
|
149
|
+
this.#chains = new RowChains(dataset);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async shutdown(entityManager) {
|
|
153
|
+
for (const entity of Array.from(this.#entries.keys())) {
|
|
154
|
+
this.#drop(entity);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
this.#chains.destroy();
|
|
158
|
+
this.#chains = null;
|
|
159
|
+
|
|
160
|
+
this.#context = null;
|
|
161
|
+
this.#unregistered.length = 0;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* @param {MeshSkin} skin
|
|
166
|
+
* @param {ShadedGeometry} geometry
|
|
167
|
+
* @param {number} entity
|
|
168
|
+
*/
|
|
169
|
+
link(skin, geometry, entity) {
|
|
170
|
+
assert.equal(
|
|
171
|
+
geometry.getFlag(ShadedGeometryFlags.Skinned), true,
|
|
172
|
+
'a MeshSkin deforms a geometry that draws a clone: set ShadedGeometryFlags.Skinned'
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
const entry = new Entry();
|
|
176
|
+
|
|
177
|
+
entry.entity = entity;
|
|
178
|
+
entry.skin = skin;
|
|
179
|
+
|
|
180
|
+
this.#entries.set(entity, entry);
|
|
181
|
+
this.#unregistered.push(entry);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* @param {MeshSkin} skin
|
|
186
|
+
* @param {ShadedGeometry} geometry
|
|
187
|
+
* @param {number} entity
|
|
188
|
+
*/
|
|
189
|
+
unlink(skin, geometry, entity) {
|
|
190
|
+
this.#drop(entity);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Register what arrived since the last frame, and everything again after a restart.
|
|
195
|
+
*
|
|
196
|
+
* @param {number} time_delta_seconds
|
|
197
|
+
*/
|
|
198
|
+
update(time_delta_seconds) {
|
|
199
|
+
const context = this.#graphics.scene_context(this.#scene);
|
|
200
|
+
|
|
201
|
+
if (context === null) {
|
|
202
|
+
// No device — before the first start, or after a stop. The next context to arrive is a
|
|
203
|
+
// change like any other.
|
|
204
|
+
this.#chains.bind(null);
|
|
205
|
+
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (context !== this.#context) {
|
|
210
|
+
this.#context = context;
|
|
211
|
+
|
|
212
|
+
this.#chains.bind(context.rows);
|
|
213
|
+
|
|
214
|
+
const waiting = this.#unregistered;
|
|
215
|
+
|
|
216
|
+
waiting.length = 0;
|
|
217
|
+
|
|
218
|
+
for (const entry of this.#entries.values()) {
|
|
219
|
+
// the old context's ids are void, and only forgotten
|
|
220
|
+
entry.skin_id = -1;
|
|
221
|
+
entry.context = null;
|
|
222
|
+
|
|
223
|
+
waiting.push(entry);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const waiting = this.#unregistered;
|
|
228
|
+
|
|
229
|
+
if (waiting.length === 0) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/*
|
|
234
|
+
An entry comes off the list before it is registered, so a registration that throws
|
|
235
|
+
cannot leave the ones before it queued for a second time — a mesh registered twice is
|
|
236
|
+
refused as a rebind, once a frame, for as long as the game runs. One that cannot be
|
|
237
|
+
registered is dropped with a message, and every other one goes ahead.
|
|
238
|
+
*/
|
|
239
|
+
const entries = waiting.slice();
|
|
240
|
+
|
|
241
|
+
waiting.length = 0;
|
|
242
|
+
|
|
243
|
+
for (let i = 0; i < entries.length; i++) {
|
|
244
|
+
const entry = entries[i];
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
this.#register(entry, context);
|
|
248
|
+
} catch (e) {
|
|
249
|
+
console.error(`MeshSkinSystem: failed to register the skin of entity ${entry.entity}, dropping it`, e);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* @param {Entry} entry
|
|
256
|
+
* @param {GPUSceneContext} context
|
|
257
|
+
*/
|
|
258
|
+
#register(entry, context) {
|
|
259
|
+
const skin = entry.skin;
|
|
260
|
+
const joints = skin.joints;
|
|
261
|
+
|
|
262
|
+
if (!entry.held) {
|
|
263
|
+
for (let i = 0; i < joints.length; i++) {
|
|
264
|
+
this.#chains.hold(joints[i]);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
entry.held = true;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const manager = context.animation_manager;
|
|
271
|
+
|
|
272
|
+
entry.skin_id = manager.register_skin(joints, skin.inverse_bind_matrices);
|
|
273
|
+
entry.context = context;
|
|
274
|
+
|
|
275
|
+
manager.bind_skin_mesh(entry.entity, entry.skin_id);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* @param {number} entity
|
|
280
|
+
*/
|
|
281
|
+
#drop(entity) {
|
|
282
|
+
const entry = this.#entries.get(entity);
|
|
283
|
+
|
|
284
|
+
if (entry === undefined) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
this.#entries.delete(entity);
|
|
289
|
+
|
|
290
|
+
const waiting = this.#unregistered.indexOf(entry);
|
|
291
|
+
|
|
292
|
+
if (waiting !== -1) {
|
|
293
|
+
this.#unregistered.splice(waiting, 1);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// A context replaced by a restart took its ids with it; only the running one gets any back.
|
|
297
|
+
if (entry.context !== null && entry.context === this.#graphics.scene_context(this.#scene)) {
|
|
298
|
+
const manager = entry.context.animation_manager;
|
|
299
|
+
|
|
300
|
+
manager.unbind_skin_mesh(entity);
|
|
301
|
+
manager.unregister_skin(entry.skin_id);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
entry.skin_id = -1;
|
|
305
|
+
entry.context = null;
|
|
306
|
+
|
|
307
|
+
if (entry.held) {
|
|
308
|
+
const joints = entry.skin.joints;
|
|
309
|
+
|
|
310
|
+
for (let i = 0; i < joints.length; i++) {
|
|
311
|
+
this.#chains.release(joints[i]);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
entry.held = false;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|