Use cache to significantly reduce vert count

This commit is contained in:
Tyler Hallada 2019-04-07 02:11:23 -04:00
parent ebc9fdfdb2
commit c5044a3a4f
8 changed files with 50 additions and 62 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -10,6 +10,8 @@ use cgmath::Vector3;
use serde::ser::{SerializeSeq, Serializer}; use serde::ser::{SerializeSeq, Serializer};
use serde::Serialize; use serde::Serialize;
const VERT_CACHE_PRECISION: f32 = 10000_f32;
#[derive(Debug)] #[derive(Debug)]
struct Triangle { struct Triangle {
a: usize, a: usize,
@ -44,6 +46,8 @@ struct ArraySerializedVector(Vector3<f32>);
struct Polyhedron { struct Polyhedron {
positions: Vec<ArraySerializedVector>, positions: Vec<ArraySerializedVector>,
cells: Vec<Triangle>, cells: Vec<Triangle>,
#[serde(skip)]
added_vert_cache: HashMap<(i32, i32, i32), usize>,
} }
impl Serialize for ArraySerializedVector { impl Serialize for ArraySerializedVector {
@ -65,26 +69,14 @@ impl Polyhedron {
Polyhedron { Polyhedron {
positions: vec![], positions: vec![],
cells: vec![], cells: vec![],
added_vert_cache: HashMap::new(),
} }
} }
fn new_isocahedron(radius: f32, detail: usize) -> Polyhedron { fn new_isocahedron(radius: f32, detail: usize) -> Polyhedron {
let t = (1.0 + (5.0 as f32).sqrt()) / 2.0; let t = (1.0 + (5.0 as f32).sqrt()) / 2.0;
let base_isocahedron = Polyhedron { let mut base_isocahedron = Polyhedron {
positions: vec![ positions: vec![],
ArraySerializedVector(Vector3::new(-1.0, t, 0.0)),
ArraySerializedVector(Vector3::new(1.0, t, 0.0)),
ArraySerializedVector(Vector3::new(-1.0, -t, 0.0)),
ArraySerializedVector(Vector3::new(1.0, -t, 0.0)),
ArraySerializedVector(Vector3::new(0.0, -1.0, t)),
ArraySerializedVector(Vector3::new(0.0, 1.0, t)),
ArraySerializedVector(Vector3::new(0.0, -1.0, -t)),
ArraySerializedVector(Vector3::new(0.0, 1.0, -t)),
ArraySerializedVector(Vector3::new(t, 0.0, -1.0)),
ArraySerializedVector(Vector3::new(t, 0.0, 1.0)),
ArraySerializedVector(Vector3::new(-t, 0.0, -1.0)),
ArraySerializedVector(Vector3::new(-t, 0.0, 1.0)),
],
cells: vec![ cells: vec![
Triangle::new(0, 11, 5), Triangle::new(0, 11, 5),
Triangle::new(0, 5, 1), Triangle::new(0, 5, 1),
@ -107,7 +99,21 @@ impl Polyhedron {
Triangle::new(8, 6, 7), Triangle::new(8, 6, 7),
Triangle::new(9, 8, 1), Triangle::new(9, 8, 1),
], ],
added_vert_cache: HashMap::new(),
}; };
base_isocahedron.add_position(Vector3::new(-1.0, t, 0.0));
base_isocahedron.add_position(Vector3::new(1.0, t, 0.0));
base_isocahedron.add_position(Vector3::new(-1.0, -t, 0.0));
base_isocahedron.add_position(Vector3::new(1.0, -t, 0.0));
base_isocahedron.add_position(Vector3::new(0.0, -1.0, t));
base_isocahedron.add_position(Vector3::new(0.0, 1.0, t));
base_isocahedron.add_position(Vector3::new(0.0, -1.0, -t));
base_isocahedron.add_position(Vector3::new(0.0, 1.0, -t));
base_isocahedron.add_position(Vector3::new(t, 0.0, -1.0));
base_isocahedron.add_position(Vector3::new(t, 0.0, 1.0));
base_isocahedron.add_position(Vector3::new(-t, 0.0, -1.0));
base_isocahedron.add_position(Vector3::new(-t, 0.0, 1.0));
let mut subdivided = Polyhedron::new(); let mut subdivided = Polyhedron::new();
subdivided.subdivide(base_isocahedron, radius, detail); subdivided.subdivide(base_isocahedron, radius, detail);
subdivided subdivided
@ -121,14 +127,11 @@ impl Polyhedron {
} }
fn subdivide(&mut self, other: Polyhedron, radius: f32, detail: usize) { fn subdivide(&mut self, other: Polyhedron, radius: f32, detail: usize) {
// TODO: maybe make this part of the polygon stuct to avoid having to pass it around
let mut added_vert_cache: HashMap<(i32, i32, i32), usize> = HashMap::new();
let precision = 10_f32.powi(4);
for triangle in other.cells { for triangle in other.cells {
let a = other.positions[triangle.a].0; let a = other.positions[triangle.a].0;
let b = other.positions[triangle.b].0; let b = other.positions[triangle.b].0;
let c = other.positions[triangle.c].0; let c = other.positions[triangle.c].0;
self.subdivide_triangle(a, b, c, radius, detail, precision, &mut added_vert_cache); self.subdivide_triangle(a, b, c, radius, detail);
} }
} }
@ -139,8 +142,6 @@ impl Polyhedron {
c: Vector3<f32>, c: Vector3<f32>,
radius: f32, radius: f32,
detail: usize, detail: usize,
precision: f32,
added_vert_cache: &mut HashMap<(i32, i32, i32), usize>,
) { ) {
let cols = 2usize.pow(detail as u32); let cols = 2usize.pow(detail as u32);
let mut new_vertices: Vec<Vec<Vector3<f32>>> = vec![]; let mut new_vertices: Vec<Vec<Vector3<f32>>> = vec![];
@ -167,18 +168,13 @@ impl Polyhedron {
let mut triangle = Triangle { a: 0, b: 0, c: 0 }; let mut triangle = Triangle { a: 0, b: 0, c: 0 };
if j % 2 == 0 { if j % 2 == 0 {
triangle.a = triangle.a = self.add_position(new_vertices[i][k + 1]);
self.add_position(new_vertices[i][k + 1], precision, added_vert_cache); triangle.b = self.add_position(new_vertices[i + 1][k]);
triangle.b = triangle.c = self.add_position(new_vertices[i][k]);
self.add_position(new_vertices[i + 1][k], precision, added_vert_cache);
triangle.c = self.add_position(new_vertices[i][k], precision, added_vert_cache);
} else { } else {
triangle.a = triangle.a = self.add_position(new_vertices[i][k + 1]);
self.add_position(new_vertices[i][k + 1], precision, added_vert_cache); triangle.b = self.add_position(new_vertices[i + 1][k + 1]);
triangle.b = triangle.c = self.add_position(new_vertices[i + 1][k]);
self.add_position(new_vertices[i + 1][k + 1], precision, added_vert_cache);
triangle.c =
self.add_position(new_vertices[i + 1][k], precision, added_vert_cache);
} }
self.cells.push(triangle); self.cells.push(triangle);
@ -189,20 +185,18 @@ impl Polyhedron {
fn add_position( fn add_position(
&mut self, &mut self,
vertex: Vector3<f32>, vertex: Vector3<f32>,
precision: f32,
added_vert_cache: &mut HashMap<(i32, i32, i32), usize>,
) -> usize { ) -> usize {
let vertex_key = ( let vertex_key = (
(vertex.x * precision).round() as i32, (vertex.x * VERT_CACHE_PRECISION).round() as i32,
(vertex.y * precision).round() as i32, (vertex.y * VERT_CACHE_PRECISION).round() as i32,
(vertex.z * precision).round() as i32, (vertex.z * VERT_CACHE_PRECISION).round() as i32,
); );
if let Some(added_vert_index) = added_vert_cache.get(&vertex_key) { if let Some(added_vert_index) = self.added_vert_cache.get(&vertex_key) {
return *added_vert_index; return *added_vert_index;
} else { } else {
self.positions.push(ArraySerializedVector(vertex)); self.positions.push(ArraySerializedVector(vertex));
let added_index = self.positions.len() - 1; let added_index = self.positions.len() - 1;
added_vert_cache.insert(vertex_key, added_index); self.added_vert_cache.insert(vertex_key, added_index);
return added_index; return added_index;
} }
} }
@ -248,26 +242,20 @@ impl Polyhedron {
&mut mid_centroid_cache, &mut mid_centroid_cache,
); );
let positions_start = self.positions.len(); let center_point_index = self.add_position(center_point);
// TODO: remove duplication here: let centroid_index = self.add_position(centroid);
// push all triangle_centroids at beginning, same index as face_index let mid_b_centroid_index = self.add_position(mid_b_centroid);
// push center_point once in outer loop and save index let mid_c_centroid_index = self.add_position(mid_c_centroid);
// (is it okay if vertices show up in positions out of order like that?)
// -- yes, I think it is okay
self.positions.push(ArraySerializedVector(center_point));
self.positions.push(ArraySerializedVector(centroid));
self.positions.push(ArraySerializedVector(mid_b_centroid));
self.positions.push(ArraySerializedVector(mid_c_centroid));
self.cells.push(Triangle::new( self.cells.push(Triangle::new(
positions_start, center_point_index,
positions_start + 1, centroid_index,
positions_start + 2, mid_b_centroid_index,
)); ));
self.cells.push(Triangle::new( self.cells.push(Triangle::new(
positions_start, center_point_index,
positions_start + 1, centroid_index,
positions_start + 3, mid_c_centroid_index,
)); ));
} }
} }