Initial work on player models
This commit is contained in:
parent
7fbbdf7686
commit
ed5fb8c93d
|
@ -390,7 +390,7 @@ impl Manager {
|
|||
fn trigger_remove_for_render_systems(&mut self, e: Entity, old_set: &BSet, new_set: &BSet, world: &mut world::World, renderer: &mut render::Renderer) {
|
||||
let mut systems = mem::replace(&mut self.render_systems, unsafe { mem::uninitialized() });
|
||||
for sys in &mut systems {
|
||||
if new_set.includes_set(&sys.filter().bits) && !old_set.includes_set(&sys.filter().bits) {
|
||||
if !new_set.includes_set(&sys.filter().bits) && old_set.includes_set(&sys.filter().bits) {
|
||||
sys.entity_removed(self, e, world, renderer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ pub fn add_systems(m: &mut ecs::Manager) {
|
|||
pub struct Position {
|
||||
pub position: Vector3<f64>,
|
||||
pub last_position: Vector3<f64>,
|
||||
pub moved: bool,
|
||||
}
|
||||
|
||||
impl Position {
|
||||
|
@ -31,6 +32,7 @@ impl Position {
|
|||
Position {
|
||||
position: Vector3::new(x, y, z),
|
||||
last_position: Vector3::new(x, y, z),
|
||||
moved: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,9 +10,10 @@ use super::{
|
|||
};
|
||||
use world;
|
||||
use render;
|
||||
use render::model;
|
||||
use types::Gamemode;
|
||||
use collision::{Aabb, Aabb3};
|
||||
use cgmath::{self, Point3};
|
||||
use cgmath::{self, Point3, Vector3, Matrix4, Decomposed, Rotation3, Rad, Angle, Quaternion};
|
||||
use std::collections::HashMap;
|
||||
use std::hash::BuildHasherDefault;
|
||||
use types::hash::FNVHash;
|
||||
|
@ -23,6 +24,8 @@ pub fn add_systems(m: &mut ecs::Manager) {
|
|||
// we can handle input the better.
|
||||
let sys = MovementHandler::new(m);
|
||||
m.add_render_system(sys);
|
||||
let sys = PlayerRenderer::new(m);
|
||||
m.add_render_system(sys);
|
||||
}
|
||||
|
||||
pub fn create_local(m: &mut ecs::Manager) -> ecs::Entity {
|
||||
|
@ -37,9 +40,305 @@ pub fn create_local(m: &mut ecs::Manager) -> ecs::Entity {
|
|||
Point3::new(-0.3, 0.0, -0.3),
|
||||
Point3::new(0.3, 1.8, 0.3)
|
||||
)));
|
||||
m.add_component_direct(entity, PlayerModel::new(false, false, true));
|
||||
entity
|
||||
}
|
||||
|
||||
|
||||
pub struct PlayerModel {
|
||||
model: Option<model::ModelKey>,
|
||||
|
||||
has_head: bool,
|
||||
has_name_tag: bool,
|
||||
first_person: bool,
|
||||
|
||||
dir: i32,
|
||||
time: f64,
|
||||
still_time: f64,
|
||||
idle_time: f64,
|
||||
arm_time: f64,
|
||||
}
|
||||
|
||||
impl PlayerModel {
|
||||
pub fn new(has_head: bool, has_name_tag: bool, first_person: bool) -> PlayerModel {
|
||||
PlayerModel {
|
||||
model: None,
|
||||
|
||||
has_head: has_head,
|
||||
has_name_tag: has_name_tag,
|
||||
first_person: first_person,
|
||||
|
||||
dir: 0,
|
||||
time: 0.0,
|
||||
still_time: 0.0,
|
||||
idle_time: 0.0,
|
||||
arm_time: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct PlayerRenderer {
|
||||
filter: ecs::Filter,
|
||||
player_model: ecs::Key<PlayerModel>,
|
||||
position: ecs::Key<Position>,
|
||||
rotation: ecs::Key<Rotation>,
|
||||
game_info: ecs::Key<GameInfo>,
|
||||
}
|
||||
|
||||
impl PlayerRenderer {
|
||||
fn new(m: &mut ecs::Manager) -> PlayerRenderer {
|
||||
let player_model = m.get_key();
|
||||
let position = m.get_key();
|
||||
let rotation = m.get_key();
|
||||
PlayerRenderer {
|
||||
filter: ecs::Filter::new()
|
||||
.with(player_model)
|
||||
.with(position)
|
||||
.with(rotation),
|
||||
player_model: player_model,
|
||||
position: position,
|
||||
rotation: rotation,
|
||||
game_info: m.get_key(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum PlayerModelPart {
|
||||
Head = 0,
|
||||
Body = 1,
|
||||
LegLeft = 2,
|
||||
LegRight = 3,
|
||||
ArmLeft = 4,
|
||||
ArmRight = 5,
|
||||
Cape = 6,
|
||||
NameTag = 7
|
||||
}
|
||||
|
||||
// TODO: Setup culling
|
||||
impl ecs::System for PlayerRenderer {
|
||||
|
||||
fn filter(&self) -> &ecs::Filter {
|
||||
&self.filter
|
||||
}
|
||||
|
||||
fn update(&mut self, m: &mut ecs::Manager, _: &mut world::World, renderer: &mut render::Renderer) {
|
||||
use std::f32::consts::PI;
|
||||
use std::f64::consts::PI as PI64;
|
||||
let world_entity = m.get_world();
|
||||
let delta = m.get_component_mut(world_entity, self.game_info).unwrap().delta;
|
||||
for e in m.find(&self.filter) {
|
||||
let player_model = m.get_component_mut(e, self.player_model).unwrap();
|
||||
let position = m.get_component_mut(e, self.position).unwrap();
|
||||
let rotation = m.get_component_mut(e, self.rotation).unwrap();
|
||||
|
||||
if let Some(pmodel) = player_model.model {
|
||||
let mdl = renderer.model.get_model(pmodel).unwrap();
|
||||
let offset = if player_model.first_person {
|
||||
let ox = (rotation.yaw - PI64/2.0).cos() * 0.25;
|
||||
let oz = -(rotation.yaw - PI64/2.0).sin() * 0.25;
|
||||
Vector3::new(
|
||||
position.position.x as f32 - ox as f32,
|
||||
-position.position.y as f32,
|
||||
position.position.z as f32 - oz as f32,
|
||||
)
|
||||
} else {
|
||||
Vector3::new(
|
||||
position.position.x as f32,
|
||||
-position.position.y as f32,
|
||||
position.position.z as f32,
|
||||
)
|
||||
};
|
||||
let offset_matrix = Matrix4::from(Decomposed {
|
||||
scale: 1.0,
|
||||
rot: Quaternion::from_angle_y(Rad::new((PI + rotation.yaw as f32))),
|
||||
disp: offset,
|
||||
});
|
||||
|
||||
mdl.matrix[PlayerModelPart::Head as usize] = offset_matrix * Matrix4::from(Decomposed {
|
||||
scale: 1.0,
|
||||
rot: Quaternion::from_angle_x(Rad::new(-rotation.pitch as f32)),
|
||||
disp: Vector3::new(0.0, -12.0/16.0 - 12.0/16.0, 0.0),
|
||||
});
|
||||
mdl.matrix[PlayerModelPart::Body as usize] = offset_matrix * Matrix4::from(Decomposed {
|
||||
scale: 1.0,
|
||||
rot: Quaternion::from_angle_x(Rad::new(0.0)),
|
||||
disp: Vector3::new(0.0, -12.0/16.0 - 6.0/16.0, 0.0),
|
||||
});
|
||||
|
||||
let mut time = player_model.time;
|
||||
let mut dir = player_model.dir;
|
||||
if dir == 0 {
|
||||
dir = 1;
|
||||
time = 15.0;
|
||||
}
|
||||
let ang = ((time / 15.0) - 1.0) * (PI64 / 4.0);
|
||||
|
||||
mdl.matrix[PlayerModelPart::LegRight as usize] = offset_matrix * Matrix4::from(Decomposed {
|
||||
scale: 1.0,
|
||||
rot: Quaternion::from_angle_x(Rad::new(ang as f32)),
|
||||
disp: Vector3::new(2.0/16.0, -12.0/16.0, 0.0),
|
||||
});
|
||||
mdl.matrix[PlayerModelPart::LegLeft as usize] = offset_matrix * Matrix4::from(Decomposed {
|
||||
scale: 1.0,
|
||||
rot: Quaternion::from_angle_x(Rad::new(-ang as f32)),
|
||||
disp: Vector3::new(-2.0/16.0, -12.0/16.0, 0.0),
|
||||
});
|
||||
|
||||
let mut i_time = player_model.idle_time;
|
||||
i_time += delta * 0.02;
|
||||
if i_time > PI64 * 2.0 {
|
||||
i_time -= PI64 * 2.0;
|
||||
}
|
||||
player_model.idle_time = i_time;
|
||||
|
||||
if player_model.arm_time <= 0.0 {
|
||||
player_model.arm_time = 0.0;
|
||||
} else {
|
||||
player_model.arm_time -= delta;
|
||||
}
|
||||
|
||||
mdl.matrix[PlayerModelPart::ArmRight as usize] = offset_matrix * Matrix4::from_translation(
|
||||
Vector3::new(6.0/16.0, -12.0/16.0-12.0/16.0, 0.0)
|
||||
) * Matrix4::from(Quaternion::from_angle_x(Rad::new(-(ang * 0.75) as f32)))
|
||||
* Matrix4::from(Quaternion::from_angle_z(Rad::new((i_time.cos() * 0.06 - 0.06) as f32)))
|
||||
* Matrix4::from(Quaternion::from_angle_x(Rad::new((i_time.sin() * 0.06 - ((7.5 - (player_model.arm_time-7.5).abs()) / 7.5)) as f32)));
|
||||
|
||||
mdl.matrix[PlayerModelPart::ArmLeft as usize] = offset_matrix * Matrix4::from_translation(
|
||||
Vector3::new(-6.0/16.0, -12.0/16.0-12.0/16.0, 0.0)
|
||||
) * Matrix4::from(Quaternion::from_angle_x(Rad::new((ang * 0.75) as f32)))
|
||||
* Matrix4::from(Quaternion::from_angle_z(Rad::new(-(i_time.cos() * 0.06 - 0.06) as f32)))
|
||||
* Matrix4::from(Quaternion::from_angle_x(Rad::new(-(i_time.sin() * 0.06) as f32)));
|
||||
|
||||
let mut update = true;
|
||||
if !position.moved {
|
||||
if player_model.still_time > 5.0 {
|
||||
if (time - 15.0).abs() <= 1.5 * delta {
|
||||
time = 15.0;
|
||||
update = false;
|
||||
}
|
||||
dir = (15.0 - time).signum() as i32;
|
||||
} else {
|
||||
player_model.still_time += delta;
|
||||
}
|
||||
} else {
|
||||
player_model.still_time = 0.0;
|
||||
}
|
||||
|
||||
if update {
|
||||
time += delta * 1.5 * (dir as f64);
|
||||
if time > 30.0 {
|
||||
time = 30.0;
|
||||
dir = -1;
|
||||
} else if time < 0.0 {
|
||||
time = 0.0;
|
||||
dir = 1;
|
||||
}
|
||||
}
|
||||
player_model.time = time;
|
||||
player_model.dir = dir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn entity_added(&mut self, m: &mut ecs::Manager, e: ecs::Entity, _: &mut world::World, renderer: &mut render::Renderer) {
|
||||
let player_model = m.get_component_mut(e, self.player_model).unwrap();
|
||||
|
||||
let skin = render::Renderer::get_texture(renderer.get_textures_ref(), "entity/steve");
|
||||
|
||||
macro_rules! srel {
|
||||
($x:expr, $y:expr, $w:expr, $h:expr) => (
|
||||
Some(skin.relative(($x) / 64.0, ($y) / 64.0, ($w) / 64.0, ($h) / 64.0))
|
||||
);
|
||||
}
|
||||
|
||||
let mut head_verts = vec![];
|
||||
if player_model.has_head {
|
||||
model::append_box(&mut head_verts, -4.0/16.0, 0.0, -4.0/16.0, 8.0/16.0, 8.0/16.0, 8.0/16.0, [
|
||||
srel!(8.0, 0.0, 8.0, 8.0), // Up
|
||||
srel!(16.0, 0.0, 8.0, 8.0), // Down
|
||||
srel!(8.0, 8.0, 8.0, 8.0), // North
|
||||
srel!(24.0, 8.0, 8.0, 8.0), // South
|
||||
srel!(16.0, 8.0, 8.0, 8.0), // West
|
||||
srel!(0.0, 8.0, 8.0, 8.0), // East
|
||||
]);
|
||||
model::append_box(&mut head_verts, -4.2/16.0, -0.2, -4.2/16.0, 8.4/16.0, 8.4/16.0, 8.4/16.0, [
|
||||
srel!((8.0 + 32.0), 0.0, 8.0, 8.0), // Up
|
||||
srel!((16.0 + 32.0), 0.0, 8.0, 8.0), // Down
|
||||
srel!((8.0 + 32.0), 8.0, 8.0, 8.0), // North
|
||||
srel!((24.0 + 32.0), 8.0, 8.0, 8.0), // South
|
||||
srel!((16.0 + 32.0), 8.0, 8.0, 8.0), // West
|
||||
srel!((0.0 + 32.0), 8.0, 8.0, 8.0), // East
|
||||
]);
|
||||
}
|
||||
|
||||
// TODO: Cape
|
||||
let mut body_verts = vec![];
|
||||
model::append_box(&mut body_verts, -4.0/16.0, -6.0/16.0, -2.0/16.0, 8.0/16.0, 12.0/16.0, 4.0/16.0, [
|
||||
srel!(20.0, 16.0, 8.0, 4.0), // Up
|
||||
srel!(28.0, 16.0, 8.0, 4.0), // Down
|
||||
srel!(20.0, 20.0, 8.0, 12.0), // North
|
||||
srel!(32.0, 20.0, 8.0, 12.0), // South
|
||||
srel!(16.0, 20.0, 4.0, 12.0), // West
|
||||
srel!(28.0, 20.0, 4.0, 12.0), // East
|
||||
]);
|
||||
model::append_box(&mut body_verts, -4.2/16.0, -6.2/16.0, -2.2/16.0, 8.4/16.0, 12.4/16.0, 4.4/16.0, [
|
||||
srel!(20.0, 16.0 + 16.0, 8.0, 4.0), // Up
|
||||
srel!(28.0, 16.0 + 16.0, 8.0, 4.0), // Down
|
||||
srel!(20.0, 20.0 + 16.0, 8.0, 12.0), // North
|
||||
srel!(32.0, 20.0 + 16.0, 8.0, 12.0), // South
|
||||
srel!(16.0, 20.0 + 16.0, 4.0, 12.0), // West
|
||||
srel!(28.0, 20.0 + 16.0, 4.0, 12.0), // East
|
||||
]);
|
||||
|
||||
let mut part_verts = vec![vec![]; 4];
|
||||
|
||||
for (i, offsets) in [
|
||||
[16.0, 48.0, 0.0, 48.0],
|
||||
[0.0, 16.0, 0.0, 32.0],
|
||||
[40.0, 16.0, 40.0, 32.0],
|
||||
[32.0, 48.0, 48.0, 48.0],
|
||||
].into_iter().enumerate() {
|
||||
let (ox, oy) = (offsets[0], offsets[1]);
|
||||
model::append_box(&mut part_verts[i], -2.0/16.0, -12.0/16.0, -2.0/16.0, 4.0/16.0, 12.0/16.0, 4.0/16.0, [
|
||||
srel!(ox + 4.0, oy + 0.0, 4.0, 4.0), // Up
|
||||
srel!(ox + 8.0, oy + 0.0, 4.0, 4.0), // Down
|
||||
srel!(ox + 4.0, oy + 4.0, 4.0, 12.0), // North
|
||||
srel!(ox + 12.0, oy + 4.0, 4.0, 12.0), // South
|
||||
srel!(ox + 0.0, oy + 4.0, 4.0, 12.0), // West
|
||||
srel!(ox + 8.0, oy + 4.0, 4.0, 12.0), // East
|
||||
]);
|
||||
let (ox, oy) = (offsets[2], offsets[3]);
|
||||
model::append_box(&mut part_verts[i], -2.2/16.0, -12.2/16.0, -2.2/16.0, 4.4/16.0, 12.4/16.0, 4.4/16.0, [
|
||||
srel!(ox + 4.0, oy + 0.0, 4.0, 4.0), // Up
|
||||
srel!(ox + 8.0, oy + 0.0, 4.0, 4.0), // Down
|
||||
srel!(ox + 4.0, oy + 4.0, 4.0, 12.0), // North
|
||||
srel!(ox + 12.0, oy + 4.0, 4.0, 12.0), // South
|
||||
srel!(ox + 0.0, oy + 4.0, 4.0, 12.0), // West
|
||||
srel!(ox + 8.0, oy + 4.0, 4.0, 12.0), // East
|
||||
]);
|
||||
}
|
||||
|
||||
player_model.model = Some(renderer.model.create_model(
|
||||
model::DEFAULT,
|
||||
vec![
|
||||
head_verts,
|
||||
body_verts,
|
||||
part_verts[0].clone(),
|
||||
part_verts[1].clone(),
|
||||
part_verts[2].clone(),
|
||||
part_verts[3].clone(),
|
||||
]
|
||||
));
|
||||
}
|
||||
|
||||
fn entity_removed(&mut self, m: &mut ecs::Manager, e: ecs::Entity, _: &mut world::World, renderer: &mut render::Renderer) {
|
||||
let player_model = m.get_component_mut(e, self.player_model).unwrap();
|
||||
if let Some(model) = player_model.model.take() {
|
||||
renderer.model.remove_model(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PlayerMovement {
|
||||
pub flying: bool,
|
||||
pub did_touch_ground: bool,
|
||||
|
@ -153,6 +452,8 @@ impl ecs::System for MovementHandler {
|
|||
|
||||
let player_bounds = m.get_component(e, self.bounds).unwrap().bounds;
|
||||
|
||||
let prev_position = position.last_position;
|
||||
|
||||
if world.is_chunk_loaded((position.position.x as i32) >> 4, (position.position.z as i32) >> 4) {
|
||||
let (forward, yaw) = movement.calculate_movement(rotation.yaw);
|
||||
let mut speed = 4.317 / 60.0;
|
||||
|
@ -248,6 +549,8 @@ impl ecs::System for MovementHandler {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
position.moved = position.position != prev_position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,6 +113,7 @@ impl ecs::System for UpdateLastPosition {
|
|||
for e in m.find(&self.filter) {
|
||||
let pos = m.get_component_mut(e, self.position).unwrap();
|
||||
|
||||
pos.moved = pos.position != pos.last_position;
|
||||
pos.last_position = pos.position;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use std::collections::HashMap;
|
|||
use std::hash::BuildHasherDefault;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use types::hash::FNVHash;
|
||||
use types::Direction;
|
||||
use byteorder::{WriteBytesExt, NativeEndian};
|
||||
|
||||
pub struct Manager {
|
||||
|
@ -318,3 +319,52 @@ init_shader! {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
pub fn append_box(
|
||||
verts: &mut Vec<Vertex>,
|
||||
x: f32, y: f32, z: f32,
|
||||
w: f32, h: f32, d: f32, textures: [Option<super::Texture>; 6]
|
||||
) {
|
||||
append_box_texture_scale(verts, x, y, z, w, h, d, textures, [
|
||||
[1.0, 1.0],
|
||||
[1.0, 1.0],
|
||||
[1.0, 1.0],
|
||||
[1.0, 1.0],
|
||||
[1.0, 1.0],
|
||||
[1.0, 1.0]
|
||||
]);
|
||||
}
|
||||
pub fn append_box_texture_scale(
|
||||
verts: &mut Vec<Vertex>,
|
||||
x: f32, y: f32, z: f32,
|
||||
w: f32, h: f32, d: f32,
|
||||
textures: [Option<super::Texture>; 6], texture_scale: [[f64; 2]; 6]) {
|
||||
for dir in Direction::all() {
|
||||
let tex = textures[dir.index()].clone();
|
||||
if tex.is_none() {
|
||||
continue;
|
||||
}
|
||||
let tex = tex.unwrap();
|
||||
for vert in dir.get_verts() {
|
||||
let (rr, gg, bb) = if dir == Direction::West || dir == Direction::East {
|
||||
((255.0 * 0.8) as u8, (255.0 * 0.8) as u8, (255.0 * 0.8) as u8)
|
||||
} else {
|
||||
(255, 255, 255)
|
||||
};
|
||||
verts.push(Vertex {
|
||||
x: vert.x * w + x,
|
||||
y: vert.y * h + y,
|
||||
z: vert.z * d + z,
|
||||
texture: tex.clone(),
|
||||
texture_x: (vert.toffsetx as f64) * texture_scale[dir.index()][0],
|
||||
texture_y: (vert.toffsety as f64) * texture_scale[dir.index()][0],
|
||||
r: rr,
|
||||
g: gg,
|
||||
b: bb,
|
||||
a: 255,
|
||||
id: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue