goud_engine/ecs/components/skeleton2d/mesh.rs
1//! Skeletal mesh types for bone-driven vertex deformation.
2//!
3//! A [`SkeletalMesh2D`] holds vertices with bone weight assignments.
4//! The skeletal animation system uses these weights to deform vertex
5//! positions each frame, storing results in `deformed_positions`.
6
7use crate::core::math::Vec2;
8use crate::ecs::Component;
9
10/// Influence of a single bone on a vertex.
11#[repr(C)]
12#[derive(Debug, Clone, Copy)]
13pub struct BoneWeight {
14 /// Index into [`Skeleton2D::bones`](super::Skeleton2D).
15 pub bone_id: u32,
16 /// Blend weight in `[0.0, 1.0]`. Weights for one vertex should sum to 1.
17 pub weight: f32,
18}
19
20/// A vertex in a skeletal mesh with bone weight assignments.
21#[derive(Debug, Clone)]
22pub struct SkeletalVertex {
23 /// Rest-pose (bind-pose) position.
24 pub position: Vec2,
25 /// Texture coordinates.
26 pub uv: Vec2,
27 /// Bone influences (typically up to 4).
28 pub weights: Vec<BoneWeight>,
29}
30
31/// Deformable 2D mesh driven by a [`Skeleton2D`](super::Skeleton2D).
32///
33/// The mesh stores rest-pose vertices and a parallel `deformed_positions`
34/// buffer that the [`deform_skeletal_meshes`](crate::ecs::systems::skeletal_animation)
35/// system fills each frame.
36#[derive(Debug, Clone)]
37pub struct SkeletalMesh2D {
38 /// Rest-pose vertices with bone weights.
39 pub vertices: Vec<SkeletalVertex>,
40 /// Triangle indices into `vertices`.
41 pub indices: Vec<u16>,
42 /// Output buffer: deformed vertex positions (same length as `vertices`).
43 pub deformed_positions: Vec<Vec2>,
44}
45
46impl Component for SkeletalMesh2D {}
47
48impl SkeletalMesh2D {
49 /// Creates a new skeletal mesh, initialising deformed positions from rest pose.
50 pub fn new(vertices: Vec<SkeletalVertex>, indices: Vec<u16>) -> Self {
51 let deformed_positions = vertices.iter().map(|v| v.position).collect();
52 Self {
53 vertices,
54 indices,
55 deformed_positions,
56 }
57 }
58}