1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//! Skeletal animation skinning for mesh deformation.
//!
//! Bind meshes to skeletons for GPU-accelerated vertex skinning:
//!
//! - [`Skin`]: Binding between a mesh and its skeleton joints
//! - [`Joint`]: Individual bone in the skeleton hierarchy
//!
//! Skinning is handled automatically when loading glTF models with skeletons.
//! The animation system updates joint transforms, and the GPU computes
//! final vertex positions using inverse bind matrices.
//!
//! # How Skinning Works
//!
//! ```text
//! ┌─────────────────────────────────────────────────────────────────┐
//! │ 1. Skeleton hierarchy defines bone relationships │
//! │ Root → Spine → Chest → Head │
//! │ └→ LeftArm → LeftHand │
//! │ └→ RightArm → RightHand │
//! │ │
//! │ 2. Each vertex has up to 4 joint influences + weights │
//! │ vertex[i].joints = [spine, chest, 0, 0] │
//! │ vertex[i].weights = [0.3, 0.7, 0.0, 0.0] │
//! │ │
//! │ 3. GPU computes: final_pos = Σ (weight[j] × joint_matrix[j]) │
//! └─────────────────────────────────────────────────────────────────┘
//! ```
//!
//! # Automatic Setup (glTF)
//!
//! glTF models with skins are automatically configured:
//!
//! ```ignore
//! // Load skinned model
//! let prefab = import_gltf_from_bytes(world, character_bytes, "character")?;
//! let entity = spawn_prefab_with_animations(world, &prefab, Vec3::zeros());
//!
//! // Skin component is already attached and configured
//! // Just play animations - skinning happens automatically
//! if let Some(player) = world.core.get_animation_player_mut(entity) {
//! player.play(WALK_ANIMATION);
//! }
//! ```
//!
//! # Manual Skin Setup
//!
//! For procedural skeletons:
//!
//! ```ignore
//! // Create joint entities
//! let root = world.spawn_entities(JOINT | LOCAL_TRANSFORM | GLOBAL_TRANSFORM, 1)[0];
//! let spine = world.spawn_entities(JOINT | LOCAL_TRANSFORM | GLOBAL_TRANSFORM | PARENT, 1)[0];
//! let head = world.spawn_entities(JOINT | LOCAL_TRANSFORM | GLOBAL_TRANSFORM | PARENT, 1)[0];
//!
//! // Set up hierarchy
//! world.core.set_parent(spine, Parent(root));
//! world.core.set_parent(head, Parent(spine));
//!
//! // Configure joints
//! world.core.set_joint(root, Joint::new(0).with_name("root"));
//! world.core.set_joint(spine, Joint::new(1).with_name("spine"));
//! world.core.set_joint(head, Joint::new(2).with_name("head"));
//!
//! // Create skin with inverse bind matrices
//! let skin = Skin::new(
//! vec![root, spine, head],
//! vec![
//! Mat4::identity(), // root inverse bind
//! Mat4::new_translation(&Vec3::new(0.0, -1.0, 0.0)), // spine
//! Mat4::new_translation(&Vec3::new(0.0, -2.0, 0.0)), // head
//! ],
//! ).with_name("character_skin");
//!
//! // Attach skin to mesh entity
//! world.core.set_skin(mesh_entity, skin);
//! ```
//!
//! # Skin Properties
//!
//! | Field | Description |
//! |-------|-------------|
//! | `joints` | Ordered list of joint entities |
//! | `inverse_bind_matrices` | Transform from mesh space to bone space |
//! | `name` | Optional identifier |
//!
//! # Joint Properties
//!
//! | Field | Description |
//! |-------|-------------|
//! | `index_in_skin` | Index into the skin's joint array |
//! | `name` | Optional bone name (for animation targeting) |
//!
//! # GPU Skinning Pipeline
//!
//! 1. Animation system updates joint `LocalTransform` components
//! 2. Transform propagation computes `GlobalTransform` for each joint
//! 3. Compute shader calculates joint matrices: `global × inverse_bind`
//! 4. Vertex shader applies weighted joint influences to each vertex
//!
//! # Performance Notes
//!
//! - Skinning runs entirely on GPU via compute shaders
//! - Up to 4 joint influences per vertex (glTF standard)
//! - Joint matrices uploaded once per frame per skin
//! - Multiple meshes can share a single skin
pub use *;
pub use *;