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
|
||||
let (state, player) = match postbox.next_message() {
|
||||
Some(ServerMsg::Handshake { ecs_state, player_entity }) => {
|
||||
println!("STATE PACKAGE! {:?}", ecs_state);
|
||||
let mut state = State::from_state_package(ecs_state);
|
||||
let player_entity = state.ecs().entity_from_uid(player_entity);
|
||||
(state, player_entity)
|
||||
@ -99,12 +98,6 @@ impl Client {
|
||||
#[allow(dead_code)]
|
||||
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.
|
||||
#[allow(dead_code)]
|
||||
pub fn state(&self) -> &State { &self.state }
|
||||
@ -158,6 +151,9 @@ impl Client {
|
||||
const PLAYER_VELOCITY: f32 = 100.0;
|
||||
// TODO: Set acceleration instead
|
||||
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)
|
||||
@ -207,10 +203,7 @@ impl Client {
|
||||
ServerMsg::Pong => {},
|
||||
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::EcsSync(sync_package) => {
|
||||
println!("SYNC PACKAGE! {:?}", sync_package);
|
||||
self.state.ecs_mut().sync_with_package(sync_package)
|
||||
},
|
||||
ServerMsg::EcsSync(sync_package) => self.state.ecs_mut().sync_with_package(sync_package),
|
||||
}
|
||||
}
|
||||
} else if let Some(err) = self.postbox.error() {
|
||||
|
@ -182,6 +182,9 @@ impl Server {
|
||||
|
||||
// Write client components
|
||||
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 {
|
||||
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];
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,14 @@
|
||||
use specs::{Component, VecStorage};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
f32,
|
||||
};
|
||||
use specs::{Entity as EcsEntity, Component, VecStorage, Join};
|
||||
use vek::*;
|
||||
use client::Client;
|
||||
use common::{
|
||||
comp,
|
||||
figure::Segment,
|
||||
};
|
||||
use crate::{
|
||||
Error,
|
||||
render::{
|
||||
@ -12,42 +21,50 @@ use crate::{
|
||||
FigureBoneData,
|
||||
FigureLocals,
|
||||
},
|
||||
anim::Skeleton,
|
||||
anim::{
|
||||
Animation,
|
||||
Skeleton,
|
||||
character::{
|
||||
CharacterSkeleton,
|
||||
RunAnimation,
|
||||
},
|
||||
},
|
||||
mesh::Meshable,
|
||||
};
|
||||
|
||||
pub struct Figure<S: Skeleton> {
|
||||
// GPU data
|
||||
model: Model<FigurePipeline>,
|
||||
bone_consts: Consts<FigureBoneData>,
|
||||
locals: Consts<FigureLocals>,
|
||||
|
||||
// CPU data
|
||||
bone_meshes: [Option<Mesh<FigurePipeline>>; 16],
|
||||
pub skeleton: S,
|
||||
pub struct Figures {
|
||||
test_model: Model<FigurePipeline>,
|
||||
states: HashMap<EcsEntity, FigureState<CharacterSkeleton>>,
|
||||
}
|
||||
|
||||
impl<S: Skeleton> Figure<S> {
|
||||
pub fn new(
|
||||
renderer: &mut Renderer,
|
||||
bone_meshes: [Option<Mesh<FigurePipeline>>; 16],
|
||||
skeleton: S,
|
||||
) -> 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()])?,
|
||||
impl Figures {
|
||||
pub fn new(renderer: &mut Renderer) -> Self {
|
||||
// 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())
|
||||
}
|
||||
|
||||
bone_meshes,
|
||||
skeleton,
|
||||
};
|
||||
this.update_model(renderer)?;
|
||||
Ok(this)
|
||||
}
|
||||
let bone_meshes = [
|
||||
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,
|
||||
];
|
||||
|
||||
pub fn update_model(&mut self, renderer: &mut Renderer) -> Result<(), Error> {
|
||||
let mut mesh = Mesh::new();
|
||||
|
||||
self.bone_meshes
|
||||
bone_meshes
|
||||
.iter()
|
||||
.enumerate()
|
||||
.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))
|
||||
});
|
||||
|
||||
self.model = renderer.create_model(&mesh)?;
|
||||
Ok(())
|
||||
Self {
|
||||
test_model: renderer.create_model(&mesh).unwrap(),
|
||||
states: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_skeleton(&mut self, renderer: &mut Renderer) -> Result<(), Error> {
|
||||
renderer.update_consts(&mut self.bone_consts, &self.skeleton.compute_matrices())?;
|
||||
Ok(())
|
||||
pub fn maintain(&mut self, renderer: &mut Renderer, client: &mut Client) {
|
||||
let time = client.state().get_time();
|
||||
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);
|
||||
}
|
||||
|
||||
self.states.retain(|entity, _| ecs.entities().is_alive(*entity));
|
||||
}
|
||||
|
||||
pub fn update_locals(&mut self, renderer: &mut Renderer, locals: FigureLocals) -> Result<(), Error> {
|
||||
renderer.update_consts(&mut self.locals, &[locals])?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn render(&self, renderer: &mut Renderer, globals: &Consts<Globals>) {
|
||||
renderer.render_figure(
|
||||
&self.model,
|
||||
globals,
|
||||
&self.locals,
|
||||
&self.bone_consts,
|
||||
);
|
||||
pub fn render(&self, renderer: &mut Renderer, client: &Client, globals: &Consts<Globals>) {
|
||||
for state in self.states.values() {
|
||||
renderer.render_figure(
|
||||
&self.test_model,
|
||||
globals,
|
||||
&state.locals,
|
||||
&state.bone_consts,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Figure<S: Skeleton> {
|
||||
pub struct FigureState<S: Skeleton> {
|
||||
bone_consts: Consts<FigureBoneData>,
|
||||
locals: Consts<FigureLocals>,
|
||||
skeleton: S,
|
||||
}
|
||||
|
||||
impl<S: Skeleton> Component for Figure<S> {
|
||||
type Storage = VecStorage<Self>;
|
||||
impl<S: Skeleton> FigureState<S> {
|
||||
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::{
|
||||
camera::Camera,
|
||||
figure::Figure,
|
||||
figure::Figures,
|
||||
terrain::Terrain,
|
||||
};
|
||||
|
||||
@ -47,13 +47,7 @@ pub struct Scene {
|
||||
|
||||
skybox: Skybox,
|
||||
terrain: Terrain,
|
||||
|
||||
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())
|
||||
figures: Figures,
|
||||
}
|
||||
|
||||
impl Scene {
|
||||
@ -74,30 +68,7 @@ impl Scene {
|
||||
.unwrap(),
|
||||
},
|
||||
terrain: Terrain::new(),
|
||||
|
||||
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(),
|
||||
figures: Figures::new(renderer),
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,7 +104,7 @@ impl Scene {
|
||||
}
|
||||
|
||||
/// 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
|
||||
let player_pos = client
|
||||
.player()
|
||||
@ -165,24 +136,13 @@ impl Scene {
|
||||
)])
|
||||
.expect("Failed to update global constants");
|
||||
|
||||
// Maintain the terrain
|
||||
// Maintain the terrain and figures
|
||||
self.terrain.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();
|
||||
self.figures.maintain(renderer, client);
|
||||
}
|
||||
|
||||
/// 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)
|
||||
renderer.render_skybox(
|
||||
&self.skybox.model,
|
||||
@ -190,10 +150,8 @@ impl Scene {
|
||||
&self.skybox.locals,
|
||||
);
|
||||
|
||||
// Render terrain
|
||||
// Render terrain and figures
|
||||
self.terrain.render(renderer, &self.globals);
|
||||
|
||||
// Render the test figure
|
||||
self.test_figure.render(renderer, &self.globals);
|
||||
self.figures.render(renderer, client, &self.globals);
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ impl SessionState {
|
||||
renderer.clear(BG_COLOR);
|
||||
|
||||
// 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
|
||||
self.hud.render(renderer);
|
||||
|
||||
@ -157,7 +157,7 @@ impl PlayState for SessionState {
|
||||
.expect("Failed to tick 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
|
||||
for event in self.hud.maintain(global_state.window.renderer_mut()) {
|
||||
match event {
|
||||
|
Loading…
Reference in New Issue
Block a user