diff --git a/Cargo.toml b/Cargo.toml index 70930e72e1..3730694b99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "client", "server", "voxygen", + "world", ] [profile.dev] diff --git a/client/Cargo.toml b/client/Cargo.toml index dd73327af8..04e8d4ae16 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -6,5 +6,7 @@ edition = "2018" [dependencies] common = { package = "veloren-common", path = "../common" } +world = { package = "veloren-world", path = "../world" } specs = "0.14" +vek = "0.9" diff --git a/client/src/lib.rs b/client/src/lib.rs index ebcc79fe15..eafda2d0b1 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -1,8 +1,16 @@ // Standard use std::time::Duration; -// Internal -use common::state::State; +// Library +use specs::Entity as EcsEntity; +use vek::*; + +// Project +use common::{ + state::State, + terrain::TerrainChunk, +}; +use world::World; #[derive(Debug)] pub enum Error { @@ -17,7 +25,11 @@ pub struct Input { pub struct Client { state: State, - // TODO: Add "meta" state here + player: Option, + + // Testing + world: World, + pub chunk: Option, } impl Client { @@ -25,9 +37,21 @@ impl Client { pub fn new() -> Self { Self { state: State::new(), + + player: None, + + // Testing + world: World::new(), + chunk: None, } } + /// 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. pub fn state(&self) -> &State { &self.state } diff --git a/common/src/terrain/biome.rs b/common/src/terrain/biome.rs index 53632d139c..81bd29967d 100644 --- a/common/src/terrain/biome.rs +++ b/common/src/terrain/biome.rs @@ -1,4 +1,5 @@ pub enum BiomeKind { + Void, Grassland, Ocean, Mountain, diff --git a/common/src/terrain/mod.rs b/common/src/terrain/mod.rs index e54f6d508f..f860e14bcb 100644 --- a/common/src/terrain/mod.rs +++ b/common/src/terrain/mod.rs @@ -1,35 +1,47 @@ pub mod block; pub mod biome; +// Reexports +pub use self::{ + block::Block, + biome::BiomeKind, +}; + // Library use vek::*; // Crate use crate::{ vol::VolSize, - volumes::vol_map::VolMap, + volumes::{ + vol_map::VolMap, + chunk::Chunk, + }, }; -// Local -use self::{ - block::Block, - biome::BiomeKind, -}; +// TerrainChunkSize -// ChunkSize +pub struct TerrainChunkSize; -pub struct ChunkSize; - -impl VolSize for ChunkSize { +impl VolSize for TerrainChunkSize { const SIZE: Vec3 = Vec3 { x: 32, y: 32, z: 32 }; } -// ChunkMeta +// TerrainChunkMeta -pub struct ChunkMeta { +pub struct TerrainChunkMeta { biome: BiomeKind, } -// TerrainMap +impl TerrainChunkMeta { + pub fn void() -> Self { + Self { + biome: BiomeKind::Void, + } + } +} -pub type TerrainMap = VolMap; +// Terrain type aliases + +pub type TerrainChunk = Chunk; +pub type TerrainMap = VolMap; diff --git a/common/src/volumes/vol_map.rs b/common/src/volumes/vol_map.rs index 33674d4e33..dd0ab1569b 100644 --- a/common/src/volumes/vol_map.rs +++ b/common/src/volumes/vol_map.rs @@ -105,4 +105,12 @@ impl VolMap { chunks: HashMap::new(), } } + + pub fn insert(&mut self, key: Vec3, chunk: Chunk) -> Option> { + self.chunks.insert(key, chunk) + } + + pub fn remove(&mut self, key: &Vec3) -> Option> { + self.chunks.remove(key) + } } diff --git a/server/Cargo.toml b/server/Cargo.toml index 9c48fce6ae..a5950b0420 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -6,5 +6,6 @@ edition = "2018" [dependencies] common = { package = "veloren-common", path = "../common" } +world = { package = "veloren-world", path = "../world" } specs = "0.14" diff --git a/server/src/lib.rs b/server/src/lib.rs index 9c6302efc4..3e202b9482 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -3,6 +3,7 @@ use std::time::Duration; // Internal use common::state::State; +use world::World; #[derive(Debug)] pub enum Error { @@ -15,6 +16,7 @@ pub struct Input { pub struct Server { state: State, + world: World, // TODO: Add "meta" state here } @@ -24,15 +26,20 @@ impl Server { pub fn new() -> Self { Self { state: State::new(), + world: World::new(), } } - /// Get a reference to the client's game state. + /// Get a reference to the server's game state. pub fn state(&self) -> &State { &self.state } - - /// Get a mutable reference to the client's game state. + /// Get a mutable reference to the server's game state. pub fn state_mut(&mut self) -> &mut State { &mut self.state } + /// Get a reference to the server's world. + pub fn world(&self) -> &World { &self.world } + /// Get a mutable reference to the server's world. + pub fn world_mut(&mut self) -> &mut World { &mut self.world } + /// Execute a single server tick, handle input and update the game state by the given duration pub fn tick(&mut self, input: Input, dt: Duration) -> Result<(), Error> { // This tick function is the centre of the Veloren universe. Most server-side things are diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index 92411ebc94..b5b5639fb9 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -19,6 +19,7 @@ impl Animation for RunAnimation { ) { let wave = (time as f32 * 12.0).sin(); let wave_fast = (time as f32 * 6.0).sin(); + let wave_dip = (wave_fast.abs() - 0.5).abs(); skeleton.head.offset = Vec3::unit_z() * 13.0; skeleton.head.ori = Quaternion::rotation_z(wave * 0.3); @@ -32,15 +33,15 @@ impl Animation for RunAnimation { skeleton.shorts.offset = Vec3::unit_z() * 4.0; skeleton.shorts.ori = Quaternion::rotation_z(wave * 0.1); - skeleton.l_hand.offset = Vec3::new(-7.5, wave * 5.0, 9.0); - skeleton.r_hand.offset = Vec3::new(7.5, -wave * 5.0, 9.0); + skeleton.l_hand.offset = Vec3::new(-6.0 - wave_dip * 6.0, wave * 5.0, 11.0 - wave_dip * 6.0); + skeleton.r_hand.offset = Vec3::new(6.0 + wave_dip * 6.0, -wave * 5.0, 11.0 - wave_dip * 6.0); - skeleton.l_foot.offset = Vec3::new(-3.5, 2.0 - wave * 8.0, 3.5 - (wave_fast.abs() - 0.5).abs() * 4.0); + skeleton.l_foot.offset = Vec3::new(-3.5, 1.0 - wave * 8.0, 3.5 - wave_dip * 4.0); skeleton.l_foot.ori = Quaternion::rotation_x(-wave + 1.0); - skeleton.r_foot.offset = Vec3::new(3.5, 2.0 + wave * 8.0, 3.5 - (wave_fast.abs() - 0.5).abs() * 4.0); + skeleton.r_foot.offset = Vec3::new(3.5, 1.0 + wave * 8.0, 3.5 - wave_dip * 4.0); skeleton.r_foot.ori = Quaternion::rotation_x(wave + 1.0); - skeleton.back.offset = Vec3::new(-8.0, 5.0, 16.0); + skeleton.back.offset = Vec3::new(-9.0, 5.0, 18.0); skeleton.back.ori = Quaternion::rotation_y(2.5); } } diff --git a/voxygen/src/scene/camera.rs b/voxygen/src/scene/camera.rs index aad5e5591d..d17b0aac15 100644 --- a/voxygen/src/scene/camera.rs +++ b/voxygen/src/scene/camera.rs @@ -27,7 +27,8 @@ impl Camera { } } - /// Compute the transformation matrices (view matrix and projection matrix) for the camera. + /// Compute the transformation matrices (view matrix and projection matrix) and position of the + /// camera. pub fn compute_dependents(&self) -> (Mat4, Mat4, Vec3) { let view_mat = Mat4::::identity() * Mat4::translation_3d(-Vec3::unit_z() * self.dist) diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index beb8de6fa5..cfb1b510f1 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -1,5 +1,6 @@ pub mod camera; pub mod figure; +pub mod terrain; // Library use vek::*; @@ -33,6 +34,7 @@ use crate::{ use self::{ camera::Camera, figure::Figure, + terrain::Terrain, }; // TODO: Don't hard-code this @@ -44,9 +46,11 @@ struct Skybox { } pub struct Scene { - camera: Camera, globals: Consts, + camera: Camera, + skybox: Skybox, + terrain: Terrain, test_figure: Figure, } @@ -58,12 +62,13 @@ fn load_segment(filename: &'static str) -> Segment { impl Scene { /// Create a new `Scene` with default parameters. - pub fn new(renderer: &mut Renderer) -> Self { + pub fn new(renderer: &mut Renderer, client: &Client) -> Self { Self { - camera: Camera::new(), globals: renderer .create_consts(&[Globals::default()]) .unwrap(), + camera: Camera::new(), + skybox: Skybox { model: renderer .create_model(&create_skybox_mesh()) @@ -72,6 +77,7 @@ impl Scene { .create_consts(&[SkyboxLocals::default()]) .unwrap(), }, + terrain: Terrain::new(), test_figure: Figure::new( renderer, @@ -129,6 +135,9 @@ impl Scene { )]) .expect("Failed to update global constants"); + // Maintain terrain GPU data + self.terrain.maintain_gpu_data(renderer); + // TODO: Don't do this here RunAnimation::update_skeleton( &mut self.test_figure.skeleton, @@ -147,6 +156,9 @@ impl Scene { &self.skybox.locals, ); + // Render terrain + self.terrain.render(renderer, &self.globals); + // Render the test figure self.test_figure.render(renderer, &self.globals); } diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs new file mode 100644 index 0000000000..f7a97703cf --- /dev/null +++ b/voxygen/src/scene/terrain.rs @@ -0,0 +1,52 @@ +// Standard +use std::collections::HashMap; + +// Library +use vek::*; + +// Crate +use crate::{ + Error, + render::{ + Consts, + Globals, + Mesh, + Model, + Renderer, + TerrainPipeline, + TerrainLocals, + }, +}; + +struct TerrainChunk { + // GPU data + model: Model, + locals: Consts, +} + +pub struct Terrain { + chunks: HashMap, TerrainChunk>, +} + +impl Terrain { + pub fn new() -> Self { + Self { + chunks: HashMap::new(), + } + } + + pub fn maintain_gpu_data(&mut self, renderer: &mut Renderer) { + // TODO + } + + pub fn render(&self, renderer: &mut Renderer, globals: &Consts) { + /* + renderer.render_terrain_chunk( + &self.model, + globals, + &self.locals, + &self.bone_consts, + ); + */ + } +} diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index ac8393664b..2dfe231832 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -33,10 +33,11 @@ pub struct SessionState { impl SessionState { /// Create a new `SessionState` pub fn new(renderer: &mut Renderer) -> Self { + let client = Client::new().with_test_state(); // <--- TODO: Remove this Self { // Create a scene for this session. The scene handles visible elements of the game world - scene: Scene::new(renderer), - client: Client::new(), + scene: Scene::new(renderer, &client), + client, } } } diff --git a/world/.gitignore b/world/.gitignore new file mode 100644 index 0000000000..693699042b --- /dev/null +++ b/world/.gitignore @@ -0,0 +1,3 @@ +/target +**/*.rs.bk +Cargo.lock diff --git a/world/Cargo.toml b/world/Cargo.toml new file mode 100644 index 0000000000..b7f42a9601 --- /dev/null +++ b/world/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "veloren-world" +version = "0.1.0" +authors = ["Joshua Barretto "] +edition = "2018" + +[dependencies] +common = { package = "veloren-common", path = "../common" } +vek = "0.9" diff --git a/world/src/lib.rs b/world/src/lib.rs new file mode 100644 index 0000000000..2caaff9df4 --- /dev/null +++ b/world/src/lib.rs @@ -0,0 +1,29 @@ +// Library +use vek::*; + +// Project +use common::{ + vol::Vox, + terrain::{ + Block, + TerrainChunk, + TerrainChunkMeta, + }, +}; + +#[derive(Debug)] +pub enum Error { + Other(String), +} + +pub struct World; + +impl World { + pub fn new() -> Self { + Self + } + + pub fn generate_chunk(&self, pos: Vec3) -> TerrainChunk { + TerrainChunk::filled(Block::empty(), TerrainChunkMeta::void()) + } +}