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
in vec3 f_pos;
in vec3 f_norm;
in vec3 f_col;
layout (std140)
@ -22,5 +23,13 @@ uniform u_globals {
out vec4 tgt_color;
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
in vec3 v_pos;
in vec3 v_norm;
in vec3 v_col;
in uint v_bone_idx;
@ -30,10 +31,12 @@ uniform u_bones {
};
out vec3 f_pos;
out vec3 f_norm;
out vec3 f_col;
void main() {
f_pos = v_pos;
f_norm = v_norm;
f_col = v_col;
gl_Position =

View File

@ -6,7 +6,7 @@ use crate::render::FigureBoneData;
#[derive(Copy, Clone)]
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 ori: Quaternion<f32>,
}
@ -14,50 +14,122 @@ pub struct Bone {
impl Bone {
pub fn default() -> Self {
Self {
parent: None,
parent_idx: None,
offset: Vec3::zero(),
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> {
Mat4::<f32>::translation_3d(self.offset) * Mat4::from(self.ori)
}
}
#[derive(Copy, Clone)]
pub struct Skeleton {
bones: [Bone; 16],
pub trait Skeleton {
fn compute_matrices(&self) -> [FigureBoneData; 16];
}
impl Skeleton {
pub fn default() -> Self {
pub struct CharacterSkeleton {
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 {
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 {
self.bones[bone_idx as usize] = bone;
self
impl Skeleton for CharacterSkeleton {
fn compute_matrices(&self) -> [FigureBoneData; 16] {
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 fn bone_mut(&mut self, bone_idx: u8) -> &mut Bone { &mut self.bones[bone_idx as usize] }
pub trait Animation {
type Skeleton;
type Dependency;
pub fn compute_matrices(&self) -> [FigureBoneData; 16] {
let mut bone_data = [FigureBoneData::default(); 16];
for i in 0..16 {
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()
//}
fn update_skeleton(
skeleton: &mut Self::Skeleton,
dependency: Self::Dependency,
);
}
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>,
unit_x: Vec3<f32>,
unit_y: Vec3<f32>,
norm: Vec3<f32>,
col: Rgb<f32>,
bone: u8,
) -> Quad<FigurePipeline> {
Quad::new(
FigureVertex::new(origin, col, bone),
FigureVertex::new(origin + unit_x, col, bone),
FigureVertex::new(origin + unit_x + unit_y, col, bone),
FigureVertex::new(origin + unit_y, col, bone),
FigureVertex::new(origin, norm, col, bone),
FigureVertex::new(origin + unit_x, norm, col, bone),
FigureVertex::new(origin + unit_x + unit_y, norm, 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(),
-Vec3::unit_y(),
Vec3::unit_z(),
-Vec3::unit_x(),
col,
0,
));
@ -69,6 +71,7 @@ impl Meshable for Segment {
offs + pos.map(|e| e as f32) + Vec3::unit_x(),
Vec3::unit_y(),
Vec3::unit_z(),
Vec3::unit_x(),
col,
0,
));
@ -77,6 +80,7 @@ impl Meshable for Segment {
offs + pos.map(|e| e as f32),
Vec3::unit_x(),
Vec3::unit_z(),
-Vec3::unit_y(),
col,
0,
));
@ -85,6 +89,7 @@ impl Meshable for Segment {
offs + pos.map(|e| e as f32) + Vec3::unit_y(),
Vec3::unit_z(),
Vec3::unit_x(),
Vec3::unit_y(),
col,
0,
));
@ -93,6 +98,7 @@ impl Meshable for Segment {
offs + pos.map(|e| e as f32),
Vec3::unit_y(),
Vec3::unit_x(),
-Vec3::unit_z(),
col,
0,
));
@ -101,6 +107,7 @@ impl Meshable for Segment {
offs + pos.map(|e| e as f32) + Vec3::unit_z(),
Vec3::unit_x(),
Vec3::unit_y(),
Vec3::unit_z(),
col,
0,
));

View File

@ -25,6 +25,7 @@ use super::{
gfx_defines! {
vertex Vertex {
pos: [f32; 3] = "v_pos",
norm: [f32; 3] = "v_norm",
col: [f32; 3] = "v_col",
bone_idx: u8 = "v_bone_idx",
}
@ -50,10 +51,11 @@ gfx_defines! {
}
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 {
pos: pos.into_array(),
col: col.into_array(),
norm: norm.into_array(),
bone_idx,
}
}

View File

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

View File

@ -30,6 +30,11 @@ use crate::{
},
window::Event,
mesh::Meshable,
anim::{
Animation,
CharacterSkeleton,
RunAnimation,
},
};
// Local
@ -51,7 +56,7 @@ pub struct Scene {
globals: Consts<Globals>,
skybox: Skybox,
test_figure: Figure,
test_figure: Figure<CharacterSkeleton>,
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("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("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("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))),
None,
None,
@ -98,6 +103,7 @@ impl Scene {
None,
None,
],
CharacterSkeleton::new(),
)
.unwrap(),
@ -142,26 +148,10 @@ impl Scene {
.expect("Failed to update global constants");
// TODO: Don't do this here
let offs = (self.client.state().get_tick() as f32 * 10.0).sin();
self.test_figure.skeleton.bone_mut(0).offset = Vec3::new(0.0, 0.0, 13.0);
self.test_figure.skeleton.bone_mut(0).ori = Quaternion::rotation_z(offs * 0.3);
// 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);
RunAnimation::update_skeleton(
&mut self.test_figure.skeleton,
self.client.state().get_tick(),
);
self.test_figure.update_locals(renderer, FigureLocals::default());
self.test_figure.update_skeleton(renderer);
}