Skip to content

Commit

Permalink
feat test: use Vec3.mul(SCALE).as_ivec3() as Hash Key for compute_smo…
Browse files Browse the repository at this point in the history
…oth_normals
  • Loading branch information
Dreamtowards committed Jan 20, 2024
1 parent 4865144 commit 3ef6db1
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 64 deletions.
158 changes: 102 additions & 56 deletions src/voxel/meshgen.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{hash::Hash, num};
use std::{hash::Hash, num, ops::Mul};

use bevy::{
math::{ivec3, vec2, vec3},
Expand Down Expand Up @@ -34,12 +34,42 @@ impl Hash for HashVec3 {
impl Eq for HashVec3 {
}



#[derive(Clone, Copy)]
pub struct Vertex {
pub pos: Vec3,
pub uv: Vec2,
pub norm: Vec3,
}

impl Hash for Vertex {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.pos.mul(100.).as_ivec3().hash(state);
self.norm.mul(100.).as_ivec3().hash(state);
self.uv.mul(100.).as_ivec2().hash(state);
// self.pos.x.to_bits().hash(state);
// self.pos.y.to_bits().hash(state);
// self.pos.z.to_bits().hash(state);
// self.norm.x.to_bits().hash(state);
// self.norm.y.to_bits().hash(state);
// self.norm.z.to_bits().hash(state);
// self.uv.x.to_bits().hash(state);
// self.uv.y.to_bits().hash(state);
}
}
impl PartialEq for Vertex {
fn eq(&self, other: &Self) -> bool {
self.pos.mul(100.).as_ivec3() == other.pos.mul(100.).as_ivec3() &&
self.norm.mul(100.).as_ivec3() == other.norm.mul(100.).as_ivec3() &&
self.uv.mul(100.).as_ivec2() == other.uv.mul(100.).as_ivec2()
}
}

impl Eq for Vertex {
}


#[derive(Default)]
pub struct VertexBuffer {
pub vertices: Vec<Vertex>,
Expand Down Expand Up @@ -74,8 +104,16 @@ impl VertexBuffer {
}
}

fn triangles_count(&self) -> usize {
self.vertex_count() / 3
fn triangle_count(&self) -> u32 {
(self.vertex_count() / 3) as u32
}

fn vert(&self, idx: u32) -> &Vertex {
if self.is_indexed() {
&self.vertices[self.indices[idx as usize] as usize]
} else {
&self.vertices[idx as usize]
}
}

pub fn clear(&mut self) {
Expand All @@ -86,8 +124,8 @@ impl VertexBuffer {
pub fn compute_flat_normals(&mut self) {
assert!(!self.is_indexed());

for tri_i in 0..self.triangles_count() {
let v = &mut self.vertices[tri_i*3..];
for tri_i in 0..self.triangle_count() {
let v = &mut self.vertices[tri_i as usize * 3 ..];
let p0 = v[0].pos;
let p1 = v[1].pos;
let p2 = v[2].pos;
Expand All @@ -101,80 +139,88 @@ impl VertexBuffer {
}

pub fn compute_smooth_normals(&mut self) {
// assert!(!self.is_indexed());
assert!(!self.is_indexed()); // todo: could support indexed
const SCALE: f32 = 100.;

// let mut pos2norm = HashMap::<HashVec3, Vec3>::new();

// let pos = &self.pos;
// for tri_i in 0..self.triangles_count() {
// let p0 = pos[tri_i*3];
// let p1 = pos[tri_i*3+1];
// let p2 = pos[tri_i*3+2];
let mut pos2norm = HashMap::<IVec3, Vec3>::new();

// let n = (p1 - p0).cross(p2 - p0);
for tri_i in 0..self.triangle_count() {
let p0 = self.vert(tri_i*3).pos;
let p1 = self.vert(tri_i*3+1).pos;
let p2 = self.vert(tri_i*3+2).pos;

// let a0 = (p1 - p0).angle_between(p2 - p0);
// let a1 = (p2 - p1).angle_between(p0 - p1);
// let a2 = (p0 - p2).angle_between(p1 - p2);
let n = (p1 - p0).cross(p2 - p0);

// *pos2norm.entry(HashVec3(p0)).or_default() += n * a0;
// *pos2norm.entry(HashVec3(p1)).or_default() += n * a1;
// *pos2norm.entry(HashVec3(p2)).or_default() += n * a2;
// }
let a0 = (p1 - p0).angle_between(p2 - p0);
let a1 = (p2 - p1).angle_between(p0 - p1);
let a2 = (p0 - p2).angle_between(p1 - p2);

// for norm in pos2norm.values_mut() {
// *norm = norm.normalize();
// }
*pos2norm.entry(p0.mul(SCALE).as_ivec3()).or_default() += n * a0;
*pos2norm.entry(p1.mul(SCALE).as_ivec3()).or_default() += n * a1;
*pos2norm.entry(p2.mul(SCALE).as_ivec3()).or_default() += n * a2;
}

// self.norm.clear();
// self.norm.reserve(self.pos.len());
// for pos in self.pos.iter() {
// self.norm.push(*pos2norm.get(&HashVec3(*pos)).unwrap());
// }
for norm in pos2norm.values_mut() {
*norm = norm.normalize();
}

for v in &mut self.vertices {
v.norm = *pos2norm.get(&v.pos.mul(SCALE).as_ivec3()).unwrap();
}
}

pub fn compute_indexed(&mut self) {
pub fn compute_indexed_naive(&mut self) {
assert!(!self.is_indexed());
self.indices.clear();
self.indices.reserve(self.vertex_count());

for i in 0..self.vertex_count() {
self.indices.push(i as u32);
}
}

pub fn compute_indexed(&mut self) {
assert!(!self.is_indexed());
self.indices.clear();
self.indices.reserve(self.vertex_count());

// let mut vert2idx = HashMap::<HashVec3, u32>::new();
// let mut verts = Vec::new();
let mut vert2idx = HashMap::<Vertex, u32>::new();

let mut vertices = Vec::new();

for vert in self.vertices.iter() {

// for vert in self.pos.iter() {
self.indices.push(vertices.len() as u32);
vertices.push(*vert);

// match vert2idx.entry(HashVec3(*vert)) {
// Entry::Occupied(e) => {
// let idx = *e.get();
// self.indices.push(idx);
// },
// Entry::Vacant(e) => {
// let idx = verts.len() as u32;
// e.insert(idx);
// verts.push(vert);
// self.indices.push(idx);
// }
// }
// todo!("Sth");
// if let Some(idx) = vert2idx.get(vert) {
// self.indices.push(*idx);
// } else {
// let idx = vertices.len() as u32;
// vert2idx.insert(*vert, idx);
// vertices.push(*vert);
// self.indices.push(idx);
// }

// match vert2idx.entry(*vert) {
// Entry::Occupied(e) => {
// let idx = *e.get();
// self.indices.push(idx);
// },
// Entry::Vacant(e) => {
// let idx = vertices.len() as u32;
// e.insert(idx);
// vertices.push(*vert);
// self.indices.push(idx);
// }
// }
}

// }
self.vertices.clear();
self.vertices = vertices;
}

pub fn to_mesh(&self, mesh: &mut Mesh) {
// let (pos, uv, norm) = self.vertices.iter()
// .fold((vec![], vec![], vec![]),
// |(mut a, mut b, mut c), vertex| {
// a.push(vertex.pos);
// b.push(vertex.uv);
// c.push(vertex.norm);
// (a, b, c)
// });

let pos: Vec<Vec3> = self.vertices.iter().map(|v| v.pos).collect();
mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, pos);

Expand Down
20 changes: 12 additions & 8 deletions src/voxel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ fn chunks_detect_load_and_unload(
WorldGen::generate_chunk(&mut chunk);
}

info!("Load Chunk: {:?}", chunkpos);
// info!("Load Chunk: {:?}", chunkpos);

chunkptr
});
Expand Down Expand Up @@ -207,7 +207,7 @@ fn chunks_detect_load_and_unload(
|| (vp.z - chunkpos.z).abs() > vd.x * Chunk::SIZE
|| (vp.y - chunkpos.y).abs() > vd.y * Chunk::SIZE
{
info!("Unload Chunk: {:?}", chunkpos);
// info!("Unload Chunk: {:?}", chunkpos);
commands.entity(entity).despawn_recursive();
chunk_sys.despawn_chunk(chunkpos);
} else if chunk_sys.dbg_remesh_all_chunks {
Expand All @@ -223,7 +223,7 @@ static THREAD_LOCAL_VERTEX_BUFFERS: Lazy<ThreadLocal<RefCell<VertexBuffer>>> =
fn chunks_remesh(
mut commands: Commands,

mut query_cam: Query<&Transform, With<CharacterControllerCamera>>,
query_cam: Query<&Transform, With<CharacterControllerCamera>>,
mut chunk_sys: ResMut<ChunkSystem>,
mut meshes: ResMut<Assets<Mesh>>,
// mut query: Query<(Entity, &Handle<Mesh>, &mut ChunkMeshingTask, &ChunkComponent, &mut Visibility)>,
Expand Down Expand Up @@ -260,12 +260,17 @@ fn chunks_remesh(
mesh_handle = chunk.mesh_handle.clone();
}

info!("Generated ReMesh {}", vbuf.vertex_count());

// vbuf.compute_flat_normals();
// vbuf.compute_smooth_normals();
vbuf.compute_smooth_normals();

let nv = vbuf.vertices.len();
vbuf.compute_indexed();

if nv != 0 {
info!("Generated ReMesh verts: {} before: {} after {}, saved: {}%",
vbuf.vertex_count(), nv, vbuf.vertices.len(), (1.0 - vbuf.vertices.len() as f32/nv as f32) * 100.0);
}

let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
vbuf.to_mesh(&mut mesh);
vbuf.clear();
Expand All @@ -276,7 +281,7 @@ fn chunks_remesh(
(mesh, collider, entity, mesh_handle)
});

info!("Queued ReMesh");
// info!("Queued ReMesh");
chunk_sys.chunks_meshing.insert(chunkpos, task);
}
chunk_sys.chunks_remesh.remove(&chunkpos);
Expand All @@ -297,7 +302,6 @@ fn chunks_remesh(
}
}

info!("Applied ReMesh");
return false;
}
true
Expand Down

0 comments on commit 3ef6db1

Please sign in to comment.