From 2b26f841d01e654a527d8b282eaf34482104ea77 Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Sun, 27 Mar 2016 23:31:57 +0100 Subject: [PATCH] Implement models and a sun/moon --- src/gl/mod.rs | 23 +- src/render/mod.rs | 10 +- src/render/model.rs | 320 +++++++++++++++++++++++++++ src/render/shaders.rs | 15 +- src/render/shaders/model_frag.glsl | 21 ++ src/render/shaders/model_vertex.glsl | 34 +++ src/render/shaders/sun_frag.glsl | 17 ++ src/render/shaders/sun_vertex.glsl | 27 +++ src/render/ui.rs | 2 +- src/{server.rs => server/mod.rs} | 16 ++ src/server/sun.rs | 96 ++++++++ 11 files changed, 573 insertions(+), 8 deletions(-) create mode 100644 src/render/shaders/model_frag.glsl create mode 100644 src/render/shaders/model_vertex.glsl create mode 100644 src/render/shaders/sun_frag.glsl create mode 100644 src/render/shaders/sun_vertex.glsl rename src/{server.rs => server/mod.rs} (97%) create mode 100644 src/server/sun.rs diff --git a/src/gl/mod.rs b/src/gl/mod.rs index b2bbeae..60b671a 100644 --- a/src/gl/mod.rs +++ b/src/gl/mod.rs @@ -46,9 +46,15 @@ pub fn draw_arrays(ty: DrawType, offset: usize, count: usize) { } } -pub fn draw_elements(ty: DrawType, count: usize, dty: Type, offset: usize) { +pub fn draw_elements(ty: DrawType, count: i32, dty: Type, offset: usize) { unsafe { - gl::DrawElements(ty, count as i32, dty, offset as *const gl::types::GLvoid); + gl::DrawElements(ty, count, dty, offset as *const gl::types::GLvoid); + } +} + +pub fn multi_draw_elements(ty: DrawType, count: &[i32], dty: Type, offsets: &[usize]) { + unsafe { + gl::MultiDrawElements(ty, count.as_ptr(), dty, offsets.as_ptr() as *const _, count.len() as i32); } } @@ -530,12 +536,25 @@ impl Uniform { } } + pub fn set_float_mutli_raw(&self, data: *const f32, len: usize) { + unsafe { + gl::Uniform4fv(self.0, len as i32, data); + } + } + pub fn set_matrix4(&self, m: &::cgmath::Matrix4) { use cgmath::Matrix; unsafe { gl::UniformMatrix4fv(self.0, 1, false as u8, m.as_ptr()); } } + + pub fn set_matrix4_multi(&self, m: &[::cgmath::Matrix4]) { + use cgmath::Matrix; + unsafe { + gl::UniformMatrix4fv(self.0, m.len() as i32, false as u8, m.as_ptr() as *const _); // TODO: Most likely isn't safe + } + } } pub struct Attribute(i32); diff --git a/src/render/mod.rs b/src/render/mod.rs index 0ee5d41..c7796f7 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -51,6 +51,7 @@ pub struct Renderer { pub resources: Arc>, textures: Arc>, pub ui: ui::UIState, + pub model: model::Manager, gl_texture: gl::Texture, texture_layers: usize, @@ -185,13 +186,13 @@ impl Renderer { // UI // Line Drawer - // Models // Clouds gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); Renderer { resource_version: version, + model: model::Manager::new(&greg), textures: textures, ui: ui, resources: res, @@ -237,6 +238,8 @@ impl Renderer { self.resource_version = rm.version(); trace!("Updating textures to {}", self.resource_version); self.textures.write().unwrap().update_textures(self.resource_version); + + self.model.rebuild_models(self.resource_version, &self.textures); } } @@ -306,13 +309,14 @@ impl Renderer { if solid.count > 0 { self.chunk_shader.offset.set_int3(pos.0, pos.1 * 4096, pos.2); solid.array.bind(); - gl::draw_elements(gl::TRIANGLES, solid.count, self.element_buffer_type, 0); + gl::draw_elements(gl::TRIANGLES, solid.count as i32, self.element_buffer_type, 0); } } } // Line rendering // Model rendering + self.model.draw(&self.frustum, &self.perspective_matrix, &self.camera_matrix, self.light_level, self.sky_offset); // Cloud rendering // Trans chunk rendering @@ -346,7 +350,7 @@ impl Renderer { if trans.count > 0 { self.chunk_shader_alpha.offset.set_int3(pos.0, pos.1 * 4096, pos.2); trans.array.bind(); - gl::draw_elements(gl::TRIANGLES, trans.count, self.element_buffer_type, 0); + gl::draw_elements(gl::TRIANGLES, trans.count as i32, self.element_buffer_type, 0); } } } diff --git a/src/render/model.rs b/src/render/model.rs index e69de29..d7d893c 100644 --- a/src/render/model.rs +++ b/src/render/model.rs @@ -0,0 +1,320 @@ + +use super::glsl; +use super::shaders; +use gl; +use cgmath::{Point3, Matrix4, SquareMatrix}; +use collision::{self, Frustum, Sphere}; +use std::collections::HashMap; +use std::hash::BuildHasherDefault; +use std::sync::{Arc, RwLock}; +use types::hash::FNVHash; +use byteorder::{WriteBytesExt, NativeEndian}; + +pub struct Manager { + collections: Vec, + + index_buffer: gl::Buffer, + index_type: gl::Type, + max_index: usize, +} + +pub const DEFAULT: CollectionKey = CollectionKey(0); +pub const SUN: CollectionKey = CollectionKey(1); + +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct CollectionKey(usize); + +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct ModelKey(CollectionKey, usize); + +impl Manager { + pub fn new(greg: &glsl::Registry) -> Manager { + let mut m = Manager { + collections: vec![], + + index_buffer: gl::Buffer::new(), + index_type: gl::UNSIGNED_SHORT, + max_index: 0, + }; + m.add_collection( + &greg.get("model_vertex"), + &greg.get("model_frag"), + gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA + ); + m.add_collection( + &greg.get("sun_vertex"), + &greg.get("sun_frag"), + gl::SRC_ALPHA, gl::ONE_FACTOR + ); + m + } + + pub fn add_collection(&mut self, vert: &str, frag: &str, blend_s: gl::Factor, blend_d: gl::Factor) -> CollectionKey { + let collection = Collection { + shader: ModelShader::new_manual(vert, frag), + models: HashMap::with_hasher(BuildHasherDefault::default()), + blend_s: blend_s, + blend_d: blend_d, + next_id: 0, + }; + self.collections.push(collection); + CollectionKey(self.collections.len()) + } + + pub fn get_model(&mut self, key: ModelKey) -> Option<&mut Model> { + let collection = &mut self.collections[(key.0).0]; + collection.models.get_mut(&key) + } + + pub fn create_model(&mut self, ckey: CollectionKey, parts: Vec>) -> ModelKey { + let array = gl::VertexArray::new(); + array.bind(); + self.index_buffer.bind(gl::ELEMENT_ARRAY_BUFFER); + let buffer = gl::Buffer::new(); + buffer.bind(gl::ARRAY_BUFFER); + + let mut model = { + let collection = &mut self.collections[ckey.0]; + collection.shader.program.use_program(); + collection.shader.position.enable(); + collection.shader.texture_info.enable(); + collection.shader.texture_offset.enable(); + collection.shader.color.enable(); + collection.shader.id.enable(); + collection.shader.position.vertex_pointer(3, gl::FLOAT, false, 36, 0); + collection.shader.texture_info.vertex_pointer(4, gl::UNSIGNED_SHORT, false, 36, 12); + collection.shader.texture_offset.vertex_pointer_int(3, gl::SHORT, 36, 20); + collection.shader.color.vertex_pointer(4, gl::UNSIGNED_BYTE, true, 36, 28); + collection.shader.id.vertex_pointer_int(4, gl::UNSIGNED_BYTE, 36, 32); + + let mut model = Model { + // For culling only + x: 0.0, + y: 0.0, + z: 0.0, + radius: 0.0, + // Per a part + matrix: Vec::with_capacity(parts.len()), + colors: Vec::with_capacity(parts.len()), + block_light: 15.0, + sky_light: 15.0, + + array: array, + buffer: buffer, + buffer_size: 0, + count: 0, + + counts: Vec::with_capacity(parts.len()), + offsets: Vec::with_capacity(parts.len()), + + verts: vec![], + }; + + for (i, part) in parts.into_iter().enumerate() { + model.matrix.push(Matrix4::identity()); + model.colors.push([1.0, 1.0, 1.0, 1.0]); + model.counts.push(((part.len() / 4) * 6) as i32); + model.offsets.push((model.verts.len() / 4) * 6); + for mut pp in part { + pp.id = i as u8; + model.verts.push(pp); + } + } + model + }; + + Self::rebuild_model(&mut model); + if self.max_index < model.count { + let (data, ty) = super::generate_element_buffer(model.count); + self.index_buffer.bind(gl::ELEMENT_ARRAY_BUFFER); + self.index_buffer.set_data(gl::ELEMENT_ARRAY_BUFFER, &data, gl::DYNAMIC_DRAW); + self.max_index = model.count; + self.index_type = ty; + } + + let collection = &mut self.collections[ckey.0]; + let key = ModelKey(ckey, collection.next_id); + collection.next_id += 1; + collection.models.insert(key, model); + + key + } + + pub fn remove_model(&mut self, key: ModelKey) { + let collection = &mut self.collections[(key.0).0]; + collection.models.remove(&key); + } + + fn rebuild_model(model: &mut Model) { + model.array.bind(); + model.count = (model.verts.len() / 4) * 6; + + let mut buffer = Vec::with_capacity(36 * model.verts.len()); + for vert in &model.verts { + let _ = buffer.write_f32::(vert.x); + let _ = buffer.write_f32::(vert.y); + let _ = buffer.write_f32::(vert.z); + let _ = buffer.write_u16::(vert.texture.get_x() as u16); + let _ = buffer.write_u16::(vert.texture.get_y() as u16); + let _ = buffer.write_u16::(vert.texture.get_width() as u16); + let _ = buffer.write_u16::(vert.texture.get_height() as u16); + let _ = buffer.write_i16::(((vert.texture.get_width() as f64) * 16.0 * vert.texture_x) as i16); + let _ = buffer.write_i16::(((vert.texture.get_height() as f64) * 16.0 * vert.texture_y) as i16); + let _ = buffer.write_i16::(vert.texture.atlas as i16); + let _ = buffer.write_i16::(0); + let _ = buffer.write_u8(vert.r); + let _ = buffer.write_u8(vert.g); + let _ = buffer.write_u8(vert.b); + let _ = buffer.write_u8(vert.a); + let _ = buffer.write_u8(vert.id); + let _ = buffer.write_u8(0); + let _ = buffer.write_u8(0); + let _ = buffer.write_u8(0); + } + + model.buffer.bind(gl::ARRAY_BUFFER); + if buffer.len() < model.buffer_size { + model.buffer.re_set_data(gl::ARRAY_BUFFER, &buffer); + } else { + model.buffer.set_data(gl::ARRAY_BUFFER, &buffer, gl::DYNAMIC_DRAW); + model.buffer_size = buffer.len(); + } + } + + pub fn rebuild_models(&mut self, version: usize, textures: &Arc>) { + for collection in &mut self.collections { + for (_, model) in &mut collection.models { + for vert in &mut model.verts { + vert.texture = if vert.texture.version == version { + vert.texture.clone() + } else { + let mut new = super::Renderer::get_texture(&textures, &vert.texture.name); + new.rel_x = vert.texture.rel_x; + new.rel_y = vert.texture.rel_y; + new.rel_width = vert.texture.rel_width; + new.rel_height = vert.texture.rel_height; + new.is_rel = vert.texture.is_rel; + new + }; + } + Self::rebuild_model(model); + } + } + } + + pub fn draw(&mut self, frustum: &Frustum, perspective_matrix: &Matrix4, camera_matrix: &Matrix4, sky_offset: f32, light_level: f32) { + let m = if self.index_type == gl::UNSIGNED_SHORT { + 2 + } else { + 4 + }; + + gl::enable(gl::BLEND); + for collection in &self.collections { + collection.shader.program.use_program(); + collection.shader.perspective_matrix.set_matrix4(perspective_matrix); + collection.shader.camera_matrix.set_matrix4(camera_matrix); + collection.shader.texture.set_int(0); + collection.shader.sky_offset.set_float(sky_offset); + collection.shader.light_level.set_float(light_level); + gl::blend_func(collection.blend_s, collection.blend_d); + + for (_, model) in &collection.models { + if model.radius > 0.0 && frustum.contains(Sphere { + center: Point3::new(model.x, -model.y, model.z), + radius: model.radius + }) == collision::Relation::Out { + continue; + } + model.array.bind(); + collection.shader.lighting.set_float2(model.block_light, model.sky_light); + if model.counts.len() > 1 { + let mut offsets = model.offsets.clone(); + for offset in &mut offsets { + *offset *= m; + } + collection.shader.model_matrix.set_matrix4_multi(&model.matrix); + collection.shader.color_mul.set_float_mutli_raw(model.colors.as_ptr() as *const _, model.colors.len()); + gl::multi_draw_elements(gl::TRIANGLES, &model.counts, self.index_type, &offsets); + } else { + collection.shader.model_matrix.set_matrix4_multi(&model.matrix); + collection.shader.color_mul.set_float_mutli_raw(model.colors.as_ptr() as *const _, model.colors.len()); + gl::draw_elements(gl::TRIANGLES, model.counts[0], self.index_type, model.offsets[0] * m); + } + } + } + gl::disable(gl::BLEND); + } +} + +struct Collection { + shader: ModelShader, + + models: HashMap>, + blend_s: gl::Factor, + blend_d: gl::Factor, + + next_id: usize, +} + +pub struct Model { + // For culling only + pub x: f32, + pub y: f32, + pub z: f32, + pub radius: f32, + // Per a part + pub matrix: Vec>, + pub colors: Vec<[f32; 4]>, + pub block_light: f32, + pub sky_light: f32, + + array: gl::VertexArray, + buffer: gl::Buffer, + buffer_size: usize, + count: usize, + + counts: Vec, + offsets: Vec, + + pub verts: Vec, +} + +#[derive(Clone)] +pub struct Vertex { + pub x: f32, + pub y: f32, + pub z: f32, + pub texture: super::Texture, + pub texture_x: f64, + pub texture_y: f64, + pub r: u8, + pub g: u8, + pub b: u8, + pub a: u8, + pub id: u8, +} + +init_shader! { + Program ModelShader { + vert = "model_vertex", + frag = "model_frag", + attribute = { + position => "aPosition", + texture_info => "aTextureInfo", + texture_offset => "aTextureOffset", + color => "aColor", + id => "id", + }, + uniform = { + perspective_matrix => "perspectiveMatrix", + camera_matrix => "cameraMatrix", + model_matrix => "modelMatrix[]", + texture => "textures", + light_level => "lightLevel", + sky_offset => "skyOffset", + lighting => "lighting", + color_mul => "colorMul[]", + }, + } +} diff --git a/src/render/shaders.rs b/src/render/shaders.rs index 7075ba1..11f9f8b 100644 --- a/src/render/shaders.rs +++ b/src/render/shaders.rs @@ -16,8 +16,7 @@ use render::glsl; use gl; pub fn add_shaders(reg: &mut glsl::Registry) { - reg.register("lookup_texture", - include_str!("shaders/lookup_texture.glsl")); + reg.register("lookup_texture", include_str!("shaders/lookup_texture.glsl")); reg.register("get_light", include_str!("shaders/get_light.glsl")); reg.register("ui_vertex", include_str!("shaders/ui_vertex.glsl")); @@ -28,6 +27,12 @@ pub fn add_shaders(reg: &mut glsl::Registry) { reg.register("trans_vertex", include_str!("shaders/trans_vertex.glsl")); reg.register("trans_frag", include_str!("shaders/trans_frag.glsl")); + + reg.register("model_vertex", include_str!("shaders/model_vertex.glsl")); + reg.register("model_frag", include_str!("shaders/model_frag.glsl")); + + reg.register("sun_vertex", include_str!("shaders/sun_vertex.glsl")); + reg.register("sun_frag", include_str!("shaders/sun_frag.glsl")); } macro_rules! get_shader { @@ -69,9 +74,15 @@ macro_rules! init_shader { } impl $name { + #[allow(dead_code)] pub fn new(reg: &glsl::Registry) -> $name { let v = get_shader!(reg, $vert $(,stringify!($vdef))*); let f = get_shader!(reg, $frag $(,stringify!($fdef))*); + $name::new_manual(&v, &f) + } + + #[allow(dead_code)] + pub fn new_manual(v: &str, f: &str) -> $name { let shader = shaders::create_program(&v, &f); $name { $( diff --git a/src/render/shaders/model_frag.glsl b/src/render/shaders/model_frag.glsl new file mode 100644 index 0000000..45558e7 --- /dev/null +++ b/src/render/shaders/model_frag.glsl @@ -0,0 +1,21 @@ +uniform sampler2DArray textures; +uniform vec4 colorMul[10]; + +in vec4 vColor; +in vec4 vTextureInfo; +in vec2 vTextureOffset; +in float vAtlas; +in vec3 vLighting; +in float vID; + +out vec4 fragColor; + +#include lookup_texture + +void main() { + vec4 col = atlasTexture(); + if (col.a <= 0.05) discard; + col *= vColor; + col.rgb *= vLighting; + fragColor = col * colorMul[int(vID)]; +} diff --git a/src/render/shaders/model_vertex.glsl b/src/render/shaders/model_vertex.glsl new file mode 100644 index 0000000..54ee19f --- /dev/null +++ b/src/render/shaders/model_vertex.glsl @@ -0,0 +1,34 @@ +in vec3 aPosition; +in vec4 aTextureInfo; +in ivec3 aTextureOffset; +in vec4 aColor; +in int id; + +uniform mat4 perspectiveMatrix; +uniform mat4 cameraMatrix; +uniform mat4 modelMatrix[10]; +uniform float lightLevel; +uniform float skyOffset; +uniform vec2 lighting; + +out vec4 vColor; +out vec4 vTextureInfo; +out vec2 vTextureOffset; +out float vAtlas; +out float vID; +out vec3 vLighting; + +#include get_light + +void main() { + vec3 pos = vec3(aPosition.x, -aPosition.y, aPosition.z); + gl_Position = perspectiveMatrix * cameraMatrix * modelMatrix[id] * vec4(pos, 1.0); + + vColor = aColor; + vTextureInfo = aTextureInfo; + vTextureOffset = aTextureOffset.xy / 16.0; + vAtlas = aTextureOffset.z; + vID = float(id); + + vLighting = getLight(lighting); +} diff --git a/src/render/shaders/sun_frag.glsl b/src/render/shaders/sun_frag.glsl new file mode 100644 index 0000000..8c48866 --- /dev/null +++ b/src/render/shaders/sun_frag.glsl @@ -0,0 +1,17 @@ +uniform sampler2DArray textures; +uniform vec4 colorMul[10]; + +in vec4 vTextureInfo; +in vec2 vTextureOffset; +in float vAtlas; +in float vID; + +out vec4 fragColor; + +#include lookup_texture + +void main() { + vec4 col = atlasTexture(); + if (col.a <= 0.05) discard; + fragColor = col * colorMul[int(vID)]; +} diff --git a/src/render/shaders/sun_vertex.glsl b/src/render/shaders/sun_vertex.glsl new file mode 100644 index 0000000..462a9a6 --- /dev/null +++ b/src/render/shaders/sun_vertex.glsl @@ -0,0 +1,27 @@ +in vec3 aPosition; +in vec4 aTextureInfo; +in ivec3 aTextureOffset; +in vec4 aColor; +in int id; + +uniform mat4 perspectiveMatrix; +uniform mat4 cameraMatrix; +uniform mat4 modelMatrix[10]; +uniform float lightLevel; +uniform float skyOffset; +uniform vec2 lighting; + +out vec4 vTextureInfo; +out vec2 vTextureOffset; +out float vAtlas; +out float vID; + +void main() { + vec3 pos = vec3(aPosition.x, -aPosition.y, aPosition.z); + gl_Position = perspectiveMatrix * cameraMatrix * modelMatrix[id] * vec4(pos, 1.0); + + vTextureInfo = aTextureInfo; + vTextureOffset = aTextureOffset.xy / 16.0; + vAtlas = aTextureOffset.z; + vID = float(id); +} diff --git a/src/render/ui.rs b/src/render/ui.rs index 1273058..72ab0f2 100644 --- a/src/render/ui.rs +++ b/src/render/ui.rs @@ -170,7 +170,7 @@ impl UIState { } else { self.buffer.re_set_data(gl::ARRAY_BUFFER, &self.data); } - gl::draw_elements(gl::TRIANGLES, self.count, self.index_type, 0); + gl::draw_elements(gl::TRIANGLES, self.count as i32, self.index_type, 0); } gl::disable(gl::BLEND); diff --git a/src/server.rs b/src/server/mod.rs similarity index 97% rename from src/server.rs rename to src/server/mod.rs index 449e455..7e1ba3c 100644 --- a/src/server.rs +++ b/src/server/mod.rs @@ -34,6 +34,8 @@ use collision::Aabb; use sdl2::keyboard::Keycode; use types::Gamemode; +mod sun; + pub struct Server { conn: Option, read_queue: Option>>, @@ -64,6 +66,8 @@ pub struct Server { pressed_keys: HashMap>, tick_timer: f64, entity_tick_timer: f64, + + sun_model: Option, } macro_rules! handle_packet { @@ -222,6 +226,7 @@ impl Server { tick_timer: 0.0, entity_tick_timer: 0.0, + sun_model: None, } } @@ -235,6 +240,10 @@ impl Server { self.version = version; self.world.flag_dirty_all(); } + // TODO: Check if the world type actually needs a sun + if self.sun_model.is_none() { + self.sun_model = Some(sun::SunModel::new(renderer)); + } self.entity_tick(renderer, delta); @@ -246,6 +255,10 @@ impl Server { self.update_time(renderer, delta); + if let Some(sun_model) = self.sun_model.as_mut() { + sun_model.tick(renderer, self.world_time, self.world_age); + } + // Copy to camera if let Some(player) = self.player { let position = self.entities.get_component(player, self.position).unwrap(); @@ -295,6 +308,9 @@ impl Server { pub fn remove(&mut self, renderer: &mut render::Renderer) { self.entities.remove_all_entities(&mut self.world, renderer); + if let Some(mut sun_model) = self.sun_model.take() { + sun_model.remove(renderer); + } } fn update_time(&mut self, renderer: &mut render::Renderer, delta: f64) { diff --git a/src/server/sun.rs b/src/server/sun.rs new file mode 100644 index 0000000..b7aa04c --- /dev/null +++ b/src/server/sun.rs @@ -0,0 +1,96 @@ + +use render; +use render::model; +use cgmath::{Vector3, Matrix4, Decomposed, Rotation3, Rad, Angle, Quaternion}; + +pub struct SunModel { + sun: model::ModelKey, + moon: model::ModelKey, + last_phase: i32, +} + +const SIZE: f32 = 50.0; + +impl SunModel { + + pub fn new(renderer: &mut render::Renderer) -> SunModel { + SunModel { + sun: SunModel::generate_sun(renderer), + moon: SunModel::generate_moon(renderer, 0), + last_phase: 0, + } + } + + pub fn tick(&mut self, renderer: &mut render::Renderer, world_time: f64, world_age: i64) { + use std::f64::consts::PI; + let phase = ((world_age / 24000) % 8) as i32; + if phase != self.last_phase { + renderer.model.remove_model(self.moon); + self.moon = SunModel::generate_moon(renderer, phase); + self.last_phase = phase; + } + + let time = world_time / 12000.0; + let ox = (time * PI).cos() * 300.0; + let oy = (time * PI).sin() * 300.0; + + { + let sun = renderer.model.get_model(self.sun).unwrap(); + sun.matrix[0] = Matrix4::from(Decomposed { + scale: 1.0, + rot: Quaternion::from_angle_z(Rad::new(-(time * PI) as f32)), + disp: Vector3::new( + (renderer.camera.pos.x + ox) as f32, + -(renderer.camera.pos.y + oy) as f32, + renderer.camera.pos.z as f32, + ), + }); + } + + { + let moon = renderer.model.get_model(self.moon).unwrap(); + moon.matrix[0] = Matrix4::from(Decomposed { + scale: 1.0, + rot: Quaternion::from_angle_z(Rad::new((PI - (time * PI)) as f32)), + disp: Vector3::new( + (renderer.camera.pos.x - ox) as f32, + -(renderer.camera.pos.y - oy) as f32, + renderer.camera.pos.z as f32, + ), + }); + } + } + + pub fn remove(&mut self, renderer: &mut render::Renderer) { + renderer.model.remove_model(self.sun); + renderer.model.remove_model(self.moon); + } + + pub fn generate_sun(renderer: &mut render::Renderer) -> model::ModelKey { + let tex = render::Renderer::get_texture(renderer.get_textures_ref(), "environment/sun"); + renderer.model.create_model( + model::SUN, + vec![vec![ + model::Vertex{x: 0.0, y: -SIZE, z: -SIZE, texture_x: 0.0, texture_y: 1.0, texture: tex.clone(), r: 255, g: 255, b: 255, a: 0, id: 0}, + model::Vertex{x: 0.0, y: SIZE, z: -SIZE, texture_x: 0.0, texture_y: 0.0, texture: tex.clone(), r: 255, g: 255, b: 255, a: 0, id: 0}, + model::Vertex{x: 0.0, y: -SIZE, z: SIZE, texture_x: 1.0, texture_y: 1.0, texture: tex.clone(), r: 255, g: 255, b: 255, a: 0, id: 0}, + model::Vertex{x: 0.0, y: SIZE, z: SIZE, texture_x: 1.0, texture_y: 0.0, texture: tex.clone(), r: 255, g: 255, b: 255, a: 0, id: 0} + ]] + ) + } + + pub fn generate_moon(renderer: &mut render::Renderer, phase: i32) -> model::ModelKey { + let tex = render::Renderer::get_texture(renderer.get_textures_ref(), "environment/moon_phases"); + let mpx = (phase % 4) as f64 * (1.0 / 4.0); + let mpy = (phase / 4) as f64 * (1.0 / 2.0); + renderer.model.create_model( + model::SUN, + vec![vec![ + model::Vertex{x: 0.0, y: -SIZE, z: -SIZE, texture_x: mpx, texture_y: mpy + (1.0 / 2.0), texture: tex.clone(), r: 255, g: 255, b: 255, a: 0, id: 0}, + model::Vertex{x: 0.0, y: SIZE, z: -SIZE, texture_x: mpx, texture_y: mpy, texture: tex.clone(), r: 255, g: 255, b: 255, a: 0, id: 0}, + model::Vertex{x: 0.0, y: -SIZE, z: SIZE, texture_x: mpx + (1.0 / 4.0), texture_y: mpy + (1.0 / 2.0), texture: tex.clone(), r: 255, g: 255, b: 255, a: 0, id: 0}, + model::Vertex{x: 0.0, y: SIZE, z: SIZE, texture_x: mpx + (1.0 / 4.0), texture_y: mpy, texture: tex.clone(), r: 255, g: 255, b: 255, a: 0, id: 0} + ]] + ) + } +}