Use cache to significantly reduce vert count
This commit is contained in:
parent
ebc9fdfdb2
commit
c5044a3a4f
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
98
src/main.rs
98
src/main.rs
@ -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,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user