mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Moved figure rendering to a better place
Former-commit-id: 51ca948e131c20151c97f9f8454c80c47a9154b0
This commit is contained in:
parent
62b91eb01b
commit
11630877e3
@ -67,7 +67,6 @@ impl Client {
|
|||||||
// Wait for handshake from server
|
// Wait for handshake from server
|
||||||
let (state, player) = match postbox.next_message() {
|
let (state, player) = match postbox.next_message() {
|
||||||
Some(ServerMsg::Handshake { ecs_state, player_entity }) => {
|
Some(ServerMsg::Handshake { ecs_state, player_entity }) => {
|
||||||
println!("STATE PACKAGE! {:?}", ecs_state);
|
|
||||||
let mut state = State::from_state_package(ecs_state);
|
let mut state = State::from_state_package(ecs_state);
|
||||||
let player_entity = state.ecs().entity_from_uid(player_entity);
|
let player_entity = state.ecs().entity_from_uid(player_entity);
|
||||||
(state, player_entity)
|
(state, player_entity)
|
||||||
@ -99,12 +98,6 @@ impl Client {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn thread_pool(&self) -> &threadpool::ThreadPool { &self.thread_pool }
|
pub fn thread_pool(&self) -> &threadpool::ThreadPool { &self.thread_pool }
|
||||||
|
|
||||||
// TODO: Get rid of this
|
|
||||||
pub fn with_test_state(mut self) -> Self {
|
|
||||||
self.chunk = Some(self.world.generate_chunk(Vec3::zero()));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a reference to the client's game state.
|
/// Get a reference to the client's game state.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn state(&self) -> &State { &self.state }
|
pub fn state(&self) -> &State { &self.state }
|
||||||
@ -158,6 +151,9 @@ impl Client {
|
|||||||
const PLAYER_VELOCITY: f32 = 100.0;
|
const PLAYER_VELOCITY: f32 = 100.0;
|
||||||
// TODO: Set acceleration instead
|
// TODO: Set acceleration instead
|
||||||
self.state.write_component(ecs_entity, comp::phys::Vel(Vec3::from(input.move_dir * PLAYER_VELOCITY)));
|
self.state.write_component(ecs_entity, comp::phys::Vel(Vec3::from(input.move_dir * PLAYER_VELOCITY)));
|
||||||
|
if input.move_dir.magnitude() > 0.01 {
|
||||||
|
self.state.write_component(ecs_entity, comp::phys::Dir(input.move_dir.normalized().into()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tick the client's LocalState (step 3)
|
// Tick the client's LocalState (step 3)
|
||||||
@ -207,10 +203,7 @@ impl Client {
|
|||||||
ServerMsg::Pong => {},
|
ServerMsg::Pong => {},
|
||||||
ServerMsg::Chat(msg) => frontend_events.push(Event::Chat(msg)),
|
ServerMsg::Chat(msg) => frontend_events.push(Event::Chat(msg)),
|
||||||
ServerMsg::SetPlayerEntity(uid) => self.player = Some(self.state.ecs().entity_from_uid(uid).unwrap()), // TODO: Don't unwrap here!
|
ServerMsg::SetPlayerEntity(uid) => self.player = Some(self.state.ecs().entity_from_uid(uid).unwrap()), // TODO: Don't unwrap here!
|
||||||
ServerMsg::EcsSync(sync_package) => {
|
ServerMsg::EcsSync(sync_package) => self.state.ecs_mut().sync_with_package(sync_package),
|
||||||
println!("SYNC PACKAGE! {:?}", sync_package);
|
|
||||||
self.state.ecs_mut().sync_with_package(sync_package)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let Some(err) = self.postbox.error() {
|
} else if let Some(err) = self.postbox.error() {
|
||||||
|
@ -182,6 +182,9 @@ impl Server {
|
|||||||
|
|
||||||
// Write client components
|
// Write client components
|
||||||
state.write_component(client.entity, player);
|
state.write_component(client.entity, player);
|
||||||
|
state.write_component(client.entity, comp::phys::Pos(Vec3::zero()));
|
||||||
|
state.write_component(client.entity, comp::phys::Vel(Vec3::zero()));
|
||||||
|
state.write_component(client.entity, comp::phys::Dir(Vec3::unit_y()));
|
||||||
if let Some(character) = character {
|
if let Some(character) = character {
|
||||||
state.write_component(client.entity, character);
|
state.write_component(client.entity, character);
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ impl Bone {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Skeleton {
|
pub trait Skeleton: Send + Sync + 'static {
|
||||||
fn compute_matrices(&self) -> [FigureBoneData; 16];
|
fn compute_matrices(&self) -> [FigureBoneData; 16];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
use specs::{Component, VecStorage};
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
f32,
|
||||||
|
};
|
||||||
|
use specs::{Entity as EcsEntity, Component, VecStorage, Join};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
use client::Client;
|
||||||
|
use common::{
|
||||||
|
comp,
|
||||||
|
figure::Segment,
|
||||||
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
Error,
|
Error,
|
||||||
render::{
|
render::{
|
||||||
@ -12,42 +21,50 @@ use crate::{
|
|||||||
FigureBoneData,
|
FigureBoneData,
|
||||||
FigureLocals,
|
FigureLocals,
|
||||||
},
|
},
|
||||||
anim::Skeleton,
|
anim::{
|
||||||
|
Animation,
|
||||||
|
Skeleton,
|
||||||
|
character::{
|
||||||
|
CharacterSkeleton,
|
||||||
|
RunAnimation,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mesh::Meshable,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Figure<S: Skeleton> {
|
pub struct Figures {
|
||||||
// GPU data
|
test_model: Model<FigurePipeline>,
|
||||||
model: Model<FigurePipeline>,
|
states: HashMap<EcsEntity, FigureState<CharacterSkeleton>>,
|
||||||
bone_consts: Consts<FigureBoneData>,
|
|
||||||
locals: Consts<FigureLocals>,
|
|
||||||
|
|
||||||
// CPU data
|
|
||||||
bone_meshes: [Option<Mesh<FigurePipeline>>; 16],
|
|
||||||
pub skeleton: S,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Skeleton> Figure<S> {
|
impl Figures {
|
||||||
pub fn new(
|
pub fn new(renderer: &mut Renderer) -> Self {
|
||||||
renderer: &mut Renderer,
|
// TODO: Make a proper asset loading system
|
||||||
bone_meshes: [Option<Mesh<FigurePipeline>>; 16],
|
fn load_segment(filename: &'static str) -> Segment {
|
||||||
skeleton: S,
|
Segment::from(dot_vox::load(&(concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/voxygen/voxel/").to_string() + filename)).unwrap())
|
||||||
) -> Result<Self, Error> {
|
|
||||||
let mut this = Self {
|
|
||||||
model: renderer.create_model(&Mesh::new())?,
|
|
||||||
bone_consts: renderer.create_consts(&skeleton.compute_matrices())?,
|
|
||||||
locals: renderer.create_consts(&[FigureLocals::default()])?,
|
|
||||||
|
|
||||||
bone_meshes,
|
|
||||||
skeleton,
|
|
||||||
};
|
|
||||||
this.update_model(renderer)?;
|
|
||||||
Ok(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_model(&mut self, renderer: &mut Renderer) -> Result<(), Error> {
|
let bone_meshes = [
|
||||||
let mut mesh = Mesh::new();
|
Some(load_segment("head.vox").generate_mesh(Vec3::new(-7.0, -6.5, -6.0))),
|
||||||
|
Some(load_segment("chest.vox").generate_mesh(Vec3::new(-6.0, -3.0, 0.0))),
|
||||||
|
Some(load_segment("belt.vox").generate_mesh(Vec3::new(-5.0, -3.0, 0.0))),
|
||||||
|
Some(load_segment("pants.vox").generate_mesh(Vec3::new(-5.0, -3.0, 0.0))),
|
||||||
|
Some(load_segment("hand.vox").generate_mesh(Vec3::new(-2.0, -2.0, -1.0))),
|
||||||
|
Some(load_segment("hand.vox").generate_mesh(Vec3::new(-2.0, -2.0, -1.0))),
|
||||||
|
Some(load_segment("foot.vox").generate_mesh(Vec3::new(-2.5, -3.0, -2.0))),
|
||||||
|
Some(load_segment("foot.vox").generate_mesh(Vec3::new(-2.5, -3.0, -2.0))),
|
||||||
|
Some(load_segment("sword.vox").generate_mesh(Vec3::new(-6.5, -1.0, 0.0))),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
];
|
||||||
|
|
||||||
self.bone_meshes
|
let mut mesh = Mesh::new();
|
||||||
|
bone_meshes
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|(i, bm)| bm.as_ref().map(|bm| (i, bm)))
|
.filter_map(|(i, bm)| bm.as_ref().map(|bm| (i, bm)))
|
||||||
@ -55,39 +72,69 @@ impl<S: Skeleton> Figure<S> {
|
|||||||
mesh.push_mesh_map(bone_mesh, |vert| vert.with_bone_idx(i as u8))
|
mesh.push_mesh_map(bone_mesh, |vert| vert.with_bone_idx(i as u8))
|
||||||
});
|
});
|
||||||
|
|
||||||
self.model = renderer.create_model(&mesh)?;
|
Self {
|
||||||
Ok(())
|
test_model: renderer.create_model(&mesh).unwrap(),
|
||||||
|
states: HashMap::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_skeleton(&mut self, renderer: &mut Renderer) -> Result<(), Error> {
|
pub fn maintain(&mut self, renderer: &mut Renderer, client: &mut Client) {
|
||||||
renderer.update_consts(&mut self.bone_consts, &self.skeleton.compute_matrices())?;
|
let time = client.state().get_time();
|
||||||
Ok(())
|
let ecs = client.state_mut().ecs_mut().internal_mut();
|
||||||
|
for (entity, pos, dir, character) in (
|
||||||
|
&ecs.entities(),
|
||||||
|
&ecs.read_storage::<comp::phys::Pos>(),
|
||||||
|
&ecs.read_storage::<comp::phys::Dir>(),
|
||||||
|
&ecs.read_storage::<comp::Character>(),
|
||||||
|
).join() {
|
||||||
|
let state = self.states
|
||||||
|
.entry(entity)
|
||||||
|
.or_insert_with(|| FigureState::new(renderer, CharacterSkeleton::new()));
|
||||||
|
|
||||||
|
state.update(renderer, pos.0, dir.0);
|
||||||
|
|
||||||
|
RunAnimation::update_skeleton(&mut state.skeleton, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_locals(&mut self, renderer: &mut Renderer, locals: FigureLocals) -> Result<(), Error> {
|
self.states.retain(|entity, _| ecs.entities().is_alive(*entity));
|
||||||
renderer.update_consts(&mut self.locals, &[locals])?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&self, renderer: &mut Renderer, globals: &Consts<Globals>) {
|
pub fn render(&self, renderer: &mut Renderer, client: &Client, globals: &Consts<Globals>) {
|
||||||
|
for state in self.states.values() {
|
||||||
renderer.render_figure(
|
renderer.render_figure(
|
||||||
&self.model,
|
&self.test_model,
|
||||||
globals,
|
globals,
|
||||||
&self.locals,
|
&state.locals,
|
||||||
&self.bone_consts,
|
&state.bone_consts,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
pub struct FigureState<S: Skeleton> {
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
pub struct Figure<S: Skeleton> {
|
|
||||||
bone_consts: Consts<FigureBoneData>,
|
bone_consts: Consts<FigureBoneData>,
|
||||||
locals: Consts<FigureLocals>,
|
locals: Consts<FigureLocals>,
|
||||||
skeleton: S,
|
skeleton: S,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Skeleton> Component for Figure<S> {
|
impl<S: Skeleton> FigureState<S> {
|
||||||
type Storage = VecStorage<Self>;
|
pub fn new(renderer: &mut Renderer, skeleton: S) -> Self {
|
||||||
|
Self {
|
||||||
|
bone_consts: renderer.create_consts(&skeleton.compute_matrices()).unwrap(),
|
||||||
|
locals: renderer.create_consts(&[FigureLocals::default()]).unwrap(),
|
||||||
|
skeleton,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, renderer: &mut Renderer, pos: Vec3<f32>, dir: Vec3<f32>) {
|
||||||
|
let mat =
|
||||||
|
Mat4::<f32>::identity() *
|
||||||
|
Mat4::translation_3d(pos) *
|
||||||
|
Mat4::rotation_z(dir.y.atan2(dir.x) + f32::consts::PI / 2.0);
|
||||||
|
|
||||||
|
let locals = FigureLocals::new(mat);
|
||||||
|
renderer.update_consts(&mut self.locals, &[locals]).unwrap();
|
||||||
|
|
||||||
|
renderer.update_consts(&mut self.bone_consts, &self.skeleton.compute_matrices()).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
@ -29,7 +29,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use self::{
|
use self::{
|
||||||
camera::Camera,
|
camera::Camera,
|
||||||
figure::Figure,
|
figure::Figures,
|
||||||
terrain::Terrain,
|
terrain::Terrain,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -47,13 +47,7 @@ pub struct Scene {
|
|||||||
|
|
||||||
skybox: Skybox,
|
skybox: Skybox,
|
||||||
terrain: Terrain,
|
terrain: Terrain,
|
||||||
|
figures: Figures,
|
||||||
test_figure: Figure<CharacterSkeleton>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Make a proper asset loading system
|
|
||||||
fn load_segment(filename: &'static str) -> Segment {
|
|
||||||
Segment::from(dot_vox::load(&(concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/voxygen/voxel/").to_string() + filename)).unwrap())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scene {
|
impl Scene {
|
||||||
@ -74,30 +68,7 @@ impl Scene {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
},
|
},
|
||||||
terrain: Terrain::new(),
|
terrain: Terrain::new(),
|
||||||
|
figures: Figures::new(renderer),
|
||||||
test_figure: Figure::new(
|
|
||||||
renderer,
|
|
||||||
[
|
|
||||||
Some(load_segment("head.vox").generate_mesh(Vec3::new(-7.0, -6.5, -6.0))),
|
|
||||||
Some(load_segment("chest.vox").generate_mesh(Vec3::new(-6.0, -3.0, 0.0))),
|
|
||||||
Some(load_segment("belt.vox").generate_mesh(Vec3::new(-5.0, -3.0, 0.0))),
|
|
||||||
Some(load_segment("pants.vox").generate_mesh(Vec3::new(-5.0, -3.0, 0.0))),
|
|
||||||
Some(load_segment("hand.vox").generate_mesh(Vec3::new(-2.0, -2.0, -1.0))),
|
|
||||||
Some(load_segment("hand.vox").generate_mesh(Vec3::new(-2.0, -2.0, -1.0))),
|
|
||||||
Some(load_segment("foot.vox").generate_mesh(Vec3::new(-2.5, -3.0, -2.0))),
|
|
||||||
Some(load_segment("foot.vox").generate_mesh(Vec3::new(-2.5, -3.0, -2.0))),
|
|
||||||
Some(load_segment("sword.vox").generate_mesh(Vec3::new(-6.5, -1.0, 0.0))),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
],
|
|
||||||
CharacterSkeleton::new(),
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +104,7 @@ impl Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Maintain data such as GPU constant buffers, models, etc. To be called once per tick.
|
/// Maintain data such as GPU constant buffers, models, etc. To be called once per tick.
|
||||||
pub fn maintain(&mut self, renderer: &mut Renderer, client: &Client) {
|
pub fn maintain(&mut self, renderer: &mut Renderer, client: &mut Client) {
|
||||||
// Get player position
|
// Get player position
|
||||||
let player_pos = client
|
let player_pos = client
|
||||||
.player()
|
.player()
|
||||||
@ -165,24 +136,13 @@ impl Scene {
|
|||||||
)])
|
)])
|
||||||
.expect("Failed to update global constants");
|
.expect("Failed to update global constants");
|
||||||
|
|
||||||
// Maintain the terrain
|
// Maintain the terrain and figures
|
||||||
self.terrain.maintain(renderer, client);
|
self.terrain.maintain(renderer, client);
|
||||||
|
self.figures.maintain(renderer, client);
|
||||||
// TODO: Don't do this here
|
|
||||||
RunAnimation::update_skeleton(
|
|
||||||
&mut self.test_figure.skeleton,
|
|
||||||
client.state().get_time(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Calculate player model matrix
|
|
||||||
let model_mat = Mat4::<f32>::translation_3d(player_pos);
|
|
||||||
|
|
||||||
self.test_figure.update_locals(renderer, FigureLocals::new(model_mat)).unwrap();
|
|
||||||
self.test_figure.update_skeleton(renderer).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render the scene using the provided `Renderer`
|
/// Render the scene using the provided `Renderer`
|
||||||
pub fn render_to(&self, renderer: &mut Renderer) {
|
pub fn render(&self, renderer: &mut Renderer, client: &Client) {
|
||||||
// Render the skybox first (it appears over everything else so must be rendered first)
|
// Render the skybox first (it appears over everything else so must be rendered first)
|
||||||
renderer.render_skybox(
|
renderer.render_skybox(
|
||||||
&self.skybox.model,
|
&self.skybox.model,
|
||||||
@ -190,10 +150,8 @@ impl Scene {
|
|||||||
&self.skybox.locals,
|
&self.skybox.locals,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Render terrain
|
// Render terrain and figures
|
||||||
self.terrain.render(renderer, &self.globals);
|
self.terrain.render(renderer, &self.globals);
|
||||||
|
self.figures.render(renderer, client, &self.globals);
|
||||||
// Render the test figure
|
|
||||||
self.test_figure.render(renderer, &self.globals);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ impl SessionState {
|
|||||||
renderer.clear(BG_COLOR);
|
renderer.clear(BG_COLOR);
|
||||||
|
|
||||||
// Render the screen using the global renderer
|
// Render the screen using the global renderer
|
||||||
self.scene.render_to(renderer);
|
self.scene.render(renderer, &self.client.borrow());
|
||||||
// Draw the UI to the screen
|
// Draw the UI to the screen
|
||||||
self.hud.render(renderer);
|
self.hud.render(renderer);
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ impl PlayState for SessionState {
|
|||||||
.expect("Failed to tick the scene");
|
.expect("Failed to tick the scene");
|
||||||
|
|
||||||
// Maintain the scene
|
// Maintain the scene
|
||||||
self.scene.maintain(global_state.window.renderer_mut(), &self.client.borrow());
|
self.scene.maintain(global_state.window.renderer_mut(), &mut self.client.borrow_mut());
|
||||||
// Maintain the UI
|
// Maintain the UI
|
||||||
for event in self.hud.maintain(global_state.window.renderer_mut()) {
|
for event in self.hud.maintain(global_state.window.renderer_mut()) {
|
||||||
match event {
|
match event {
|
||||||
|
Loading…
Reference in New Issue
Block a user