Moved to Skeleton and Animation traits

This commit is contained in:
Joshua Barretto 2019-01-14 14:18:58 +00:00
parent 8184bc6fc0
commit 86e70751e0
7 changed files with 149 additions and 66 deletions

View File

@ -1,6 +1,7 @@
#version 330 core #version 330 core
in vec3 f_pos; in vec3 f_pos;
in vec3 f_norm;
in vec3 f_col; in vec3 f_col;
layout (std140) layout (std140)
@ -22,5 +23,13 @@ uniform u_globals {
out vec4 tgt_color; out vec4 tgt_color;
void main() { void main() {
tgt_color = vec4(f_col, 1.0); vec3 world_norm = (model_mat * vec4(f_norm, 0.0)).xyz;
float ambient = 0.5;
vec3 sun_dir = normalize(vec3(1.3, 1.7, 1.1));
float sun_diffuse = dot(sun_dir, world_norm) * 0.5;
tgt_color = vec4(f_col * (ambient + sun_diffuse), 1.0);
} }

View File

@ -1,6 +1,7 @@
#version 330 core #version 330 core
in vec3 v_pos; in vec3 v_pos;
in vec3 v_norm;
in vec3 v_col; in vec3 v_col;
in uint v_bone_idx; in uint v_bone_idx;
@ -30,10 +31,12 @@ uniform u_bones {
}; };
out vec3 f_pos; out vec3 f_pos;
out vec3 f_norm;
out vec3 f_col; out vec3 f_col;
void main() { void main() {
f_pos = v_pos; f_pos = v_pos;
f_norm = v_norm;
f_col = v_col; f_col = v_col;
gl_Position = gl_Position =

View File

@ -6,7 +6,7 @@ use crate::render::FigureBoneData;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct Bone { pub struct Bone {
parent: Option<u8>, // MUST be less than the current bone index parent_idx: Option<u8>, // MUST be less than the current bone index
pub offset: Vec3<f32>, pub offset: Vec3<f32>,
pub ori: Quaternion<f32>, pub ori: Quaternion<f32>,
} }
@ -14,50 +14,122 @@ pub struct Bone {
impl Bone { impl Bone {
pub fn default() -> Self { pub fn default() -> Self {
Self { Self {
parent: None, parent_idx: None,
offset: Vec3::zero(), offset: Vec3::zero(),
ori: Quaternion::identity(), ori: Quaternion::identity(),
} }
} }
pub fn get_parent_idx(&self) -> Option<u8> { self.parent_idx }
pub fn set_parent_idx(&mut self, parent_idx: u8) {
self.parent_idx = Some(parent_idx);
}
pub fn compute_base_matrix(&self) -> Mat4<f32> { pub fn compute_base_matrix(&self) -> Mat4<f32> {
Mat4::<f32>::translation_3d(self.offset) * Mat4::from(self.ori) Mat4::<f32>::translation_3d(self.offset) * Mat4::from(self.ori)
} }
} }
#[derive(Copy, Clone)] pub trait Skeleton {
pub struct Skeleton { fn compute_matrices(&self) -> [FigureBoneData; 16];
bones: [Bone; 16],
} }
impl Skeleton { pub struct CharacterSkeleton {
pub fn default() -> Self { head: Bone,
chest: Bone,
belt: Bone,
leggings: Bone,
l_hand: Bone,
r_hand: Bone,
l_foot: Bone,
r_foot: Bone,
back: Bone,
}
impl CharacterSkeleton {
pub fn new() -> Self {
Self { Self {
bones: [Bone::default(); 16], head: Bone::default(),
chest: Bone::default(),
belt: Bone::default(),
leggings: Bone::default(),
l_hand: Bone::default(),
r_hand: Bone::default(),
l_foot: Bone::default(),
r_foot: Bone::default(),
back: Bone::default(),
}
} }
} }
pub fn with_bone(mut self, bone_idx: u8, bone: Bone) -> Self { impl Skeleton for CharacterSkeleton {
self.bones[bone_idx as usize] = bone; fn compute_matrices(&self) -> [FigureBoneData; 16] {
self let chest_mat = self.chest.compute_base_matrix();
[
FigureBoneData::new(self.head.compute_base_matrix()),
FigureBoneData::new(chest_mat),
FigureBoneData::new(self.belt.compute_base_matrix()),
FigureBoneData::new(self.leggings.compute_base_matrix()),
FigureBoneData::new(self.l_hand.compute_base_matrix()),
FigureBoneData::new(self.r_hand.compute_base_matrix()),
FigureBoneData::new(self.l_foot.compute_base_matrix()),
FigureBoneData::new(self.r_foot.compute_base_matrix()),
FigureBoneData::new(chest_mat * self.back.compute_base_matrix()),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
]
}
} }
pub fn bone(&self, bone_idx: u8) -> &Bone { &self.bones[bone_idx as usize] } pub trait Animation {
pub fn bone_mut(&mut self, bone_idx: u8) -> &mut Bone { &mut self.bones[bone_idx as usize] } type Skeleton;
type Dependency;
pub fn compute_matrices(&self) -> [FigureBoneData; 16] { fn update_skeleton(
let mut bone_data = [FigureBoneData::default(); 16]; skeleton: &mut Self::Skeleton,
for i in 0..16 { dependency: Self::Dependency,
bone_data[i] = FigureBoneData::new(
self.bones[i].compute_base_matrix()
// *
//if let Some(parent_idx) = self.bones[i].parent {
// bone_data[parent_idx as usize]
//} else {
// Mat4::identity()
//}
); );
} }
bone_data
pub struct RunAnimation;
impl Animation for RunAnimation {
type Skeleton = CharacterSkeleton;
type Dependency = f64;
fn update_skeleton(
skeleton: &mut Self::Skeleton,
time: f64,
) {
let wave = (time as f32 * 10.0).sin();
let wave_fast = (time as f32 * 5.0).sin();
skeleton.head.offset = Vec3::unit_z() * 13.0;
skeleton.head.ori = Quaternion::rotation_z(wave * 0.3);
skeleton.chest.offset = Vec3::unit_z() * 9.0;
skeleton.chest.ori = Quaternion::rotation_z(wave * 0.3);
skeleton.belt.offset = Vec3::unit_z() * 7.0;
skeleton.belt.ori = Quaternion::rotation_z(wave * 0.3);
skeleton.leggings.offset = Vec3::unit_z() * 4.0;
skeleton.leggings.ori = Quaternion::rotation_z(wave * 0.3);
skeleton.l_hand.offset = Vec3::new(-8.0, wave * 4.0, 9.0);
skeleton.r_hand.offset = Vec3::new(8.0, -wave * 4.0, 9.0);
skeleton.l_foot.offset = Vec3::new(-3.0, -wave * 4.0, -(wave_fast.abs() - 0.5) * 3.0);
skeleton.r_foot.offset = Vec3::new(3.0, wave * 4.0, (wave_fast.abs() - 0.5) * 3.0);
skeleton.back.offset = Vec3::new(-8.0, 5.0, 16.0);
skeleton.back.ori = Quaternion::rotation_y(2.5);
} }
} }

View File

@ -29,14 +29,15 @@ fn create_quad(
origin: Vec3<f32>, origin: Vec3<f32>,
unit_x: Vec3<f32>, unit_x: Vec3<f32>,
unit_y: Vec3<f32>, unit_y: Vec3<f32>,
norm: Vec3<f32>,
col: Rgb<f32>, col: Rgb<f32>,
bone: u8, bone: u8,
) -> Quad<FigurePipeline> { ) -> Quad<FigurePipeline> {
Quad::new( Quad::new(
FigureVertex::new(origin, col, bone), FigureVertex::new(origin, norm, col, bone),
FigureVertex::new(origin + unit_x, col, bone), FigureVertex::new(origin + unit_x, norm, col, bone),
FigureVertex::new(origin + unit_x + unit_y, col, bone), FigureVertex::new(origin + unit_x + unit_y, norm, col, bone),
FigureVertex::new(origin + unit_y, col, bone), FigureVertex::new(origin + unit_y, norm, col, bone),
) )
} }
@ -61,6 +62,7 @@ impl Meshable for Segment {
offs + pos.map(|e| e as f32) + Vec3::unit_y(), offs + pos.map(|e| e as f32) + Vec3::unit_y(),
-Vec3::unit_y(), -Vec3::unit_y(),
Vec3::unit_z(), Vec3::unit_z(),
-Vec3::unit_x(),
col, col,
0, 0,
)); ));
@ -69,6 +71,7 @@ impl Meshable for Segment {
offs + pos.map(|e| e as f32) + Vec3::unit_x(), offs + pos.map(|e| e as f32) + Vec3::unit_x(),
Vec3::unit_y(), Vec3::unit_y(),
Vec3::unit_z(), Vec3::unit_z(),
Vec3::unit_x(),
col, col,
0, 0,
)); ));
@ -77,6 +80,7 @@ impl Meshable for Segment {
offs + pos.map(|e| e as f32), offs + pos.map(|e| e as f32),
Vec3::unit_x(), Vec3::unit_x(),
Vec3::unit_z(), Vec3::unit_z(),
-Vec3::unit_y(),
col, col,
0, 0,
)); ));
@ -85,6 +89,7 @@ impl Meshable for Segment {
offs + pos.map(|e| e as f32) + Vec3::unit_y(), offs + pos.map(|e| e as f32) + Vec3::unit_y(),
Vec3::unit_z(), Vec3::unit_z(),
Vec3::unit_x(), Vec3::unit_x(),
Vec3::unit_y(),
col, col,
0, 0,
)); ));
@ -93,6 +98,7 @@ impl Meshable for Segment {
offs + pos.map(|e| e as f32), offs + pos.map(|e| e as f32),
Vec3::unit_y(), Vec3::unit_y(),
Vec3::unit_x(), Vec3::unit_x(),
-Vec3::unit_z(),
col, col,
0, 0,
)); ));
@ -101,6 +107,7 @@ impl Meshable for Segment {
offs + pos.map(|e| e as f32) + Vec3::unit_z(), offs + pos.map(|e| e as f32) + Vec3::unit_z(),
Vec3::unit_x(), Vec3::unit_x(),
Vec3::unit_y(), Vec3::unit_y(),
Vec3::unit_z(),
col, col,
0, 0,
)); ));

View File

@ -25,6 +25,7 @@ use super::{
gfx_defines! { gfx_defines! {
vertex Vertex { vertex Vertex {
pos: [f32; 3] = "v_pos", pos: [f32; 3] = "v_pos",
norm: [f32; 3] = "v_norm",
col: [f32; 3] = "v_col", col: [f32; 3] = "v_col",
bone_idx: u8 = "v_bone_idx", bone_idx: u8 = "v_bone_idx",
} }
@ -50,10 +51,11 @@ gfx_defines! {
} }
impl Vertex { impl Vertex {
pub fn new(pos: Vec3<f32>, col: Rgb<f32>, bone_idx: u8) -> Self { pub fn new(pos: Vec3<f32>, norm: Vec3<f32>, col: Rgb<f32>, bone_idx: u8) -> Self {
Self { Self {
pos: pos.into_array(), pos: pos.into_array(),
col: col.into_array(), col: col.into_array(),
norm: norm.into_array(),
bone_idx, bone_idx,
} }
} }

View File

@ -14,7 +14,7 @@ use crate::{
anim::Skeleton, anim::Skeleton,
}; };
pub struct Figure { pub struct Figure<S: Skeleton> {
// GPU data // GPU data
model: Model<FigurePipeline>, model: Model<FigurePipeline>,
bone_consts: Consts<FigureBoneData>, bone_consts: Consts<FigureBoneData>,
@ -22,15 +22,15 @@ pub struct Figure {
// CPU data // CPU data
bone_meshes: [Option<Mesh<FigurePipeline>>; 16], bone_meshes: [Option<Mesh<FigurePipeline>>; 16],
pub skeleton: Skeleton, pub skeleton: S,
} }
impl Figure { impl<S: Skeleton> Figure<S> {
pub fn new( pub fn new(
renderer: &mut Renderer, renderer: &mut Renderer,
bone_meshes: [Option<Mesh<FigurePipeline>>; 16] bone_meshes: [Option<Mesh<FigurePipeline>>; 16],
skeleton: S,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let skeleton = Skeleton::default();
let mut this = Self { let mut this = Self {
model: renderer.create_model(&Mesh::new())?, model: renderer.create_model(&Mesh::new())?,
bone_consts: renderer.create_consts(&skeleton.compute_matrices())?, bone_consts: renderer.create_consts(&skeleton.compute_matrices())?,

View File

@ -30,6 +30,11 @@ use crate::{
}, },
window::Event, window::Event,
mesh::Meshable, mesh::Meshable,
anim::{
Animation,
CharacterSkeleton,
RunAnimation,
},
}; };
// Local // Local
@ -51,7 +56,7 @@ pub struct Scene {
globals: Consts<Globals>, globals: Consts<Globals>,
skybox: Skybox, skybox: Skybox,
test_figure: Figure, test_figure: Figure<CharacterSkeleton>,
client: Client, client: Client,
} }
@ -85,10 +90,10 @@ impl Scene {
Some(load_segment("chest.vox").generate_mesh_with_offset(Vec3::new(-6.0, -3.0, 0.0))), Some(load_segment("chest.vox").generate_mesh_with_offset(Vec3::new(-6.0, -3.0, 0.0))),
Some(load_segment("belt.vox").generate_mesh_with_offset(Vec3::new(-5.0, -3.0, 0.0))), Some(load_segment("belt.vox").generate_mesh_with_offset(Vec3::new(-5.0, -3.0, 0.0))),
Some(load_segment("pants.vox").generate_mesh_with_offset(Vec3::new(-5.0, -3.0, 0.0))), Some(load_segment("pants.vox").generate_mesh_with_offset(Vec3::new(-5.0, -3.0, 0.0))),
Some(load_segment("foot.vox").generate_mesh_with_offset(Vec3::new(-2.5, -3.0, 0.0))),
Some(load_segment("foot.vox").generate_mesh_with_offset(Vec3::new(-2.5, -3.0, 0.0))),
Some(load_segment("hand.vox").generate_mesh_with_offset(Vec3::new(-2.0, -2.0, -1.0))), Some(load_segment("hand.vox").generate_mesh_with_offset(Vec3::new(-2.0, -2.0, -1.0))),
Some(load_segment("hand.vox").generate_mesh_with_offset(Vec3::new(-2.0, -2.0, -1.0))), Some(load_segment("hand.vox").generate_mesh_with_offset(Vec3::new(-2.0, -2.0, -1.0))),
Some(load_segment("foot.vox").generate_mesh_with_offset(Vec3::new(-2.5, -3.0, 0.0))),
Some(load_segment("foot.vox").generate_mesh_with_offset(Vec3::new(-2.5, -3.0, 0.0))),
Some(load_segment("sword.vox").generate_mesh_with_offset(Vec3::new(-6.5, -1.0, 0.0))), Some(load_segment("sword.vox").generate_mesh_with_offset(Vec3::new(-6.5, -1.0, 0.0))),
None, None,
None, None,
@ -98,6 +103,7 @@ impl Scene {
None, None,
None, None,
], ],
CharacterSkeleton::new(),
) )
.unwrap(), .unwrap(),
@ -142,26 +148,10 @@ impl Scene {
.expect("Failed to update global constants"); .expect("Failed to update global constants");
// TODO: Don't do this here // TODO: Don't do this here
let offs = (self.client.state().get_tick() as f32 * 10.0).sin(); RunAnimation::update_skeleton(
self.test_figure.skeleton.bone_mut(0).offset = Vec3::new(0.0, 0.0, 13.0); &mut self.test_figure.skeleton,
self.test_figure.skeleton.bone_mut(0).ori = Quaternion::rotation_z(offs * 0.3); self.client.state().get_tick(),
// Chest );
self.test_figure.skeleton.bone_mut(1).offset = Vec3::new(0.0, 0.0, 9.0);
self.test_figure.skeleton.bone_mut(2).offset = Vec3::new(0.0, 0.0, 7.0);
self.test_figure.skeleton.bone_mut(3).offset = Vec3::new(0.0, 0.0, 4.0);
self.test_figure.skeleton.bone_mut(1).ori = Quaternion::rotation_z(offs * 0.15);
self.test_figure.skeleton.bone_mut(2).ori = Quaternion::rotation_z(offs * 0.15);
self.test_figure.skeleton.bone_mut(3).ori = Quaternion::rotation_z(offs * 0.15);
//Feet
self.test_figure.skeleton.bone_mut(4).offset = Vec3::new(-3.0, -offs * 4.0, 0.0);
self.test_figure.skeleton.bone_mut(5).offset = Vec3::new(3.0, offs * 4.0, 0.0);
// Hands
self.test_figure.skeleton.bone_mut(6).offset = Vec3::new(-8.0, offs * 4.0, 9.0);
self.test_figure.skeleton.bone_mut(7).offset = Vec3::new(8.0, -offs * 4.0, 9.0);
// Sword
self.test_figure.skeleton.bone_mut(8).offset = Vec3::new(-8.0, 5.0, 24.0);
self.test_figure.skeleton.bone_mut(8).ori = Quaternion::rotation_y(2.5);
self.test_figure.update_locals(renderer, FigureLocals::default()); self.test_figure.update_locals(renderer, FigureLocals::default());
self.test_figure.update_skeleton(renderer); self.test_figure.update_skeleton(renderer);
} }