diff --git a/src/app.rs b/src/app.rs index 0fb8a80..0907c8e 100644 --- a/src/app.rs +++ b/src/app.rs @@ -40,7 +40,7 @@ pub struct AppState { clients: Vec, } -const BLOCKS: i32 = 4; +const BLOCKS: i32 = 1; impl AppState { // We don't need this to be async right now, @@ -54,24 +54,17 @@ impl AppState { .renderer .as_mut() .unwrap() - .load_from_gltf(include_bytes!("assets/sphere.glb")); + .load_from_gltf(include_bytes!("assets/cube.glb")); let block = file.first_object().unwrap(); let skybox = world.renderer.as_mut().unwrap().load_texture_from_bytes( - include_bytes!("assets/skybox2.png"), + include_bytes!("assets/skybox1.png"), Some(image::ImageFormat::Png), ); - world.renderer().set_skybox(skybox); - let color = world - .renderer() - .load_texture_from_bytes(include_bytes!("assets/plank/color.png"), None); - let normal = world - .renderer() - .load_texture_from_bytes(include_bytes!("assets/plank/normal.png"), None); - let roughness = world - .renderer() - .load_texture_from_bytes(include_bytes!("assets/plank/roughness.png"), None); - let mat = world.renderer().new_material(&color, &normal, &roughness); - block.0.borrow_mut().model.as_mut().unwrap().material = mat; + world.renderer.as_mut().unwrap().set_skybox(skybox); + //let color = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/color.png")); + //let normal = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/normal.png")); + //let roughness = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/roughness.png")); + //let mat = renderer.new_material(color,normal,roughness); for x in -BLOCKS..BLOCKS { for y in -BLOCKS..BLOCKS { let block = block.hard_clone(); @@ -79,7 +72,7 @@ impl AppState { { let mut model = block.0.borrow_mut(); model.model.as_mut().unwrap().instance.transform = Mat4::from_translation( - Vec3::new(-x as f32 * 3.0, -2.0, -y as f32 * 3.0), + Vec3::new(-x as f32 * 3.0, -8.0, -y as f32 * 3.0), ) * Mat4::from_rotation_z((x * y) as f32 / 1.23); model.model.as_mut().unwrap().instance.color = Vec4::new( diff --git a/src/assets/SimpleShader.wgsl b/src/assets/SimpleShader.wgsl index f8c7b12..7a9a592 100644 --- a/src/assets/SimpleShader.wgsl +++ b/src/assets/SimpleShader.wgsl @@ -88,9 +88,9 @@ var t_rough: texture_2d; fn sky_aspect(look: vec3) -> vec4 { var pi = 3.14159; let u_angle = atan2(look.x,look.z); - let u = (u_angle/pi) * 0.5 + 0.5; // from -pi/2 -> pi/2 into 0 -> 1 + let u = (u_angle/pi) + 0.5; // from -pi/2 -> pi/2 into 0 -> 1 let v_angle = atan2(-look.y,sqrt(look.x * look.x + look.z * look.z)); - let v = (v_angle/pi) - 0.5;//(v_angle/pi) + 0.5; // from -pi/2 -> pi/2 into 0 -> 1 + let v = (v_angle/pi) + 0.5;//(v_angle/pi) + 0.5; // from -pi/2 -> pi/2 into 0 -> 1 let uv = vec2(u,v); // Get UV on skybox return textureSample(sky_texture, sky_sampler, uv); } @@ -112,9 +112,7 @@ fn translation(mat: mat4x4) -> vec4 { fn fs_main(in: VertexOutput) -> @location(0) vec4 { let object_color: vec4 = textureSample(t_diffuse, s_diffuse, in.tex_coords); let object_normal: vec4 = textureSample(t_normal, s_diffuse, in.tex_coords); - let object_rough: vec4 = textureSample(t_rough, s_diffuse, in.tex_coords); - let diffuse_result = object_color.xyz * environment.ambient.xyz; let diffuse_color = object_color.xyz; let specular_color = vec3(0.0,0.0,0.0); let reflection = sky_aspect(reflect(normalize(in.world_position-translation(eye.frame).xyz),normalize(in.world_normal))); @@ -131,15 +129,9 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4 { //let specular_strength = pow(max(dot(tangent_normal, half_dir), 0.0), 32.0); //let specular_color = specular_strength * environment.light.xyz; - let reflect_factor = max(object_rough.x * 0.5,object_rough.y); + let result = (environment.ambient.xyz + diffuse_color.xyz + specular_color.xyz) * object_color.xyz; - let diffuse_brightness = length(diffuse_color); - - let diffuse_effect = (diffuse_result * (1 - reflect_factor)) + reflection.xyz * reflect_factor * diffuse_brightness; - - let result = (diffuse_effect.xyz + specular_color.xyz); - - return vec4(result.xyz,object_color.a); + return vec4(reflection.xyz,object_color.a); } struct SkyOutput { diff --git a/src/assets/skybox2.png b/src/assets/skybox2.png deleted file mode 100644 index e828de1..0000000 Binary files a/src/assets/skybox2.png and /dev/null differ diff --git a/src/render/eye.rs b/src/render/eye.rs index 21fd621..11b7112 100644 --- a/src/render/eye.rs +++ b/src/render/eye.rs @@ -63,7 +63,7 @@ impl Eye { let dir = Vec3::new(1.0, 0.5, 1.0).normalize(); let environment = Environment { - ambient: Vec4::new(0.1, 0.1, 0.1, 0.0), + ambient: Vec4::new(0.15, 0.15, 0.15, 0.0), light: Vec4::new(1.0, 1.0, 1.0, 0.0), dir: Vec4::new(dir.x, dir.y, dir.z, 0.0), }; diff --git a/src/render/mod.rs b/src/render/mod.rs index f6d2761..68977e7 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -826,6 +826,7 @@ impl Renderer { collider: SimpleColliderData { transform: Mat4::default(), shape: Shape::None, + radius: 0.0, }, }))); if len == 1 { diff --git a/src/world/mod.rs b/src/world/mod.rs index 0cdfdad..3802219 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -1,7 +1,8 @@ use crate::render::{Renderer, SimpleLightData, SimpleModelData}; -use glam::{IVec3, Mat4, Vec3}; +use glam::{DVec3, IVec3, Mat4, UVec3, Vec3, Vec4Swizzles}; use std::cell::RefCell; use std::hash::{BuildHasherDefault, Hash, Hasher}; +use std::ops::{Div, Mul}; use std::rc::Rc; use wgpu::naga::{FastHashMap, FastHashSet}; @@ -16,29 +17,7 @@ pub enum Shape { pub struct SimpleColliderData { pub transform: Mat4, pub shape: Shape, -} - -impl SimpleColliderData { - fn aabb(&self) -> Option { - let (_scale, _rotation, translation) = self.transform.to_scale_rotation_translation(); - match self.shape { - Shape::Block(size) => { - let radius_offset = Vec3::splat(size.length()); - Some(AABB( - translation - radius_offset, - translation + radius_offset, - )) - } - Shape::Sphere(radius) => { - let radius_offset = Vec3::splat(radius); - Some(AABB( - translation - radius_offset, - translation + radius_offset, - )) - } - Shape::None => None, - } - } + pub radius: f32, } #[derive(Clone)] @@ -93,220 +72,157 @@ impl Hash for SimpleObject { } #[derive(Eq, Hash, PartialEq, Clone)] -pub enum Interest { +enum Interest { Light(SimpleLight), Object(SimpleObject), } -impl Interest { - fn aabb(&self) -> Option { - match self { - Interest::Light(light) => { - let data = light.0.borrow(); - Some(AABB::new( - data.transform.to_scale_rotation_translation().2, - Vec3::splat(data.instance.color.length()), - )) - } - Interest::Object(object) => object.0.borrow().collider.aabb(), - } - } -} - -#[derive(Copy, Clone)] -struct Material { +struct Block { + debug: Option, volume: u8, velocity: Vec3, material: u8, + interests: FastHashSet, + blocks: [Option>; 64], } -impl Material { - const fn new() -> Material { - Material { +const TREE_ATTACK: usize = 4; +const TREE_FLOOR: usize = 4; +impl Block { + fn new() -> Block { + Block { + debug: None, volume: 0, velocity: Vec3::ZERO, material: 0, + interests: FastHashSet::with_hasher(BuildHasherDefault::default()), + blocks: [const { None }; const { TREE_ATTACK * TREE_ATTACK * TREE_ATTACK }], } } -} - -#[derive(Clone, Copy)] -struct AABB(Vec3, Vec3); - -impl AABB { - fn new(translation: Vec3, size: Vec3) -> AABB { - AABB(translation - size, translation + size) + fn place_pos(&mut self, interest: Interest, pos: Vec3, rad: f32, block_size: f32) { + let cs = block_size / const { TREE_ATTACK as f32 }; + if rad < cs || block_size >= TREE_FLOOR as f32 { + let rel = ((pos + block_size / 2.0) / cs).round().as_uvec3(); + let new_pos = pos - (rel.as_vec3() + cs / 2.0); + let index = (rel.x + rel.y * 4 + rel.z * 16) as usize; + match self.blocks[index] { + Some(ref mut block) => { + block.place_pos(interest, new_pos, rad, cs); + } + None => { + let mut block = Box::new(Block::new()); + block.place_pos(interest, new_pos, rad, cs); + self.blocks[index] = Some(block); + } + } + } else { + self.interests.insert(interest); + } } - fn bounded_by(&self, aabb: AABB) -> AABB { - AABB(self.0.max(aabb.0), self.1.min(aabb.1)) - } - fn offset(&self) -> Vec3 { - self.1 - self.0 + fn debug_step(&mut self, value: bool) { + match self.debug { + Some(ref mut debug) => { + if value { + } else { + } + } + None => { + if value { + } else { + } + } + } + for maybe_block in self.blocks.iter_mut() { + if let Some(block) = maybe_block { + block.debug_step(value) + } + } } } pub struct World { - map: HashedMap, + chunk_size: u32, + map: FastHashMap, pub renderer: Option, + debug_world_map: bool, + debug_world_map_object: Option, } impl World { pub fn new() -> World { World { - map: HashedMap::new(), + chunk_size: 512, + map: FastHashMap::with_hasher(BuildHasherDefault::default()), renderer: None, + debug_world_map: false, + debug_world_map_object: None, } } - pub fn renderer(&mut self) -> &mut Renderer { - self.renderer.as_mut().unwrap() - } pub fn add_renderer(&mut self, renderer: Renderer) { self.renderer = Some(renderer); + self.debug_world_map_object = self + .renderer + .as_mut() + .unwrap() + .load_from_gltf(include_bytes!("../assets/cube.glb")) + .first_object() } pub fn add_object(&mut self, object: SimpleObject) { - if let Some(aabb) = object.0.borrow().collider.aabb() { - self.map - .place_with_aabb(Interest::Object(object.clone()), aabb); - } - if let Some(ref mut renderer) = self.renderer - && object.0.borrow().model.is_some() - { - renderer.instances.add_object(object.clone()) + self.place(Interest::Object(object.clone())); + if let Some(ref mut renderer) = self.renderer { + renderer.instances.add_object(object) } } - pub fn remove_object(&mut self, object: SimpleObject) {} - pub fn set_debug(&mut self, value: Option) { - for (index, item) in self.map.it.iter_mut() {} + pub fn set_debug(&mut self, value: bool) { + self.debug_world_map = value; } - fn step(&mut self) {} - fn sync(&mut self) {} -} - -type VecMap = FastHashMap; - -struct Level { - sub_level: - entries: T -} - -struct MatterLevel { - blocks: Option> -} - -struct InterestLevel { - blocks: Option> -} - -struct HashedMap { - matter: -} - -impl HashedMap { - fn new() -> HashedMap { - HashedMap { - it: FastHashMap::default() + pub fn light_step(&mut self) {} + pub fn object_step(&mut self) {} + pub fn debug_step(&mut self) { + self.light_step(); + self.object_step(); + for (index, item) in self.map.iter_mut() { + item.debug_step(self.debug_world_map); } } -} - -/*impl Block { - const FLOOR: i32 = 4; - const CHUNK_SIZE: i32 = Block::FLOOR * 64; - const MAX_IDEAL_INTEREST: usize = 4; - fn new() -> Block { - Block { - debug: None, - material: Material::new(), - interests: FastHashSet::default(), - blocks: None, - } - } -} - -type Blocks = Box<[Block; 8]>; - -struct Block { - debug: Option, - interests: FastHashSet, - material: Material, - blocks: Option, -} - -impl Block { - pub fn set_debug(&mut self, value: Option, pos: Vec3, size: f32) {} -} - -pub trait WorldMap { - fn new() -> Self; - fn place_with_aabb(&mut self, interest: Interest, aabb: AABB); -} - -struct OctreeMap { - it: FastHashMap, -} - -impl OctreeMap { - fn place_with_index(&mut self, interest: Interest, mut index: IVec3) { - let chunk_index = (index + IVec3::splat(Block::CHUNK_SIZE / 2)) / Block::CHUNK_SIZE; - let mut block = self.it.entry(chunk_index).or_insert_with(|| Block::new()); - let mut offset_size = Block::CHUNK_SIZE / 4; - index = index - chunk_index * Block::CHUNK_SIZE; - while index != IVec3::ZERO { - let blocks = if let Some(ref mut blocks) = block.blocks { - blocks - } else if block.interests.len() < Block::MAX_IDEAL_INTEREST { - block.interests.insert(interest.clone()); - return; - } else { - block.blocks = Some(Box::new(core::array::from_fn(|_| Block::new()))); - block.blocks.as_mut().unwrap() - }; - let mut block_index = 0; - if index.x < 0 { - index.x += offset_size; - } else { - index.x -= offset_size; - block_index += 1; - } - if index.y < 0 { - index.y += offset_size; - } else { - index.y -= offset_size; - block_index += 2; - } - if index.z < 0 { - index.z += offset_size; - } else { - index.z -= offset_size; - block_index += 4; - } - block = &mut blocks[block_index]; - offset_size /= 2; - } - block.interests.insert(interest.clone()); - } -} - -impl WorldMap for OctreeMap { - fn place_with_aabb(&mut self, interest: Interest, aabb: AABB) { - let mut d = 4; - let offset = aabb.1 - aabb.0; - while offset.element_sum() > (d * 2) as f32 { - d *= 2 - } - let iaabb0 = (aabb.0 / d as f32).floor().as_ivec3(); - let iaabb1 = (aabb.1 / d as f32).ceil().as_ivec3(); - for x in iaabb0.x..iaabb1.x { - for y in iaabb0.y..iaabb1.y { - for z in iaabb0.z..iaabb1.z { - self.place_with_index(interest.clone(), IVec3::new(x, y, z) * d as i32); + fn place_pos(&mut self, interest: Interest, pos: Vec3, rad: f32) { + let cs = self.chunk_size as f32; + let c_rad = ((cs / 2.0) * (cs / 2.0)) * 3.0; + for x in (pos.x - rad).div(cs) as i32..=(pos.x + rad).div(cs).ceil() as i32 { + for y in (pos.y - rad).div(cs) as i32..=(pos.y + rad).div(cs).ceil() as i32 { + for z in (pos.z - rad).div(cs) as i32..=(pos.z + rad).div(cs).ceil() as i32 { + let block_pos = IVec3::new(x, y, z); + let block_pos_f32 = block_pos.as_vec3(); + if block_pos_f32.distance_squared(pos) < rad + c_rad { + self.map.entry(block_pos).or_insert_with(|| { + let mut block = Block::new(); + block.place_pos( + interest.clone(), + pos - block_pos_f32, + rad, + self.chunk_size as f32, + ); + block + }); + } } } } } - fn new() -> OctreeMap { - OctreeMap { - it: FastHashMap::with_hasher(BuildHasherDefault::default()), - } + fn place(&mut self, interest: Interest) { + let (pos, rad) = match &interest { + Interest::Light(light) => { + let light = light.0.borrow(); + (light.instance.location.xyz(), light.instance.color.length()) + } + Interest::Object(object) => { + let collider = &object.0.borrow().collider; + ( + collider.transform.to_scale_rotation_translation().2, + collider.radius, + ) + } + }; + self.place_pos(interest, pos, rad); } -}*/ +}