|
@@ -4,6 +4,7 @@
|
|
|
|
|
|
|
|
|
use crate::geometry::Vec3;
|
|
|
+use crate::geometry::Axis;
|
|
|
use crate::mesh::Face;
|
|
|
use crate::mesh::Mesh;
|
|
|
|
|
@@ -16,21 +17,6 @@ pub struct AABB {
|
|
|
pub max: Vec3
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * Bounding Volume Hierarchy
|
|
|
- */
|
|
|
-pub struct FaceReference<'a> {
|
|
|
- m: &'a Mesh,
|
|
|
- f: &'a Face
|
|
|
-}
|
|
|
-
|
|
|
-pub enum BVH<'a> {
|
|
|
- Node(&'a BVH<'a>, &'a BVH<'a>),
|
|
|
- Leaf(&'a BVH<'a>, Vec<FaceReference<'a>>)
|
|
|
-
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
fn f32_min(a: f32, b: f32) -> f32 {
|
|
|
return if a < b { a } else { b };
|
|
|
}
|
|
@@ -52,16 +38,103 @@ impl AABB {
|
|
|
self.max.z = f32::max(self.max.z, coords.iter().map(|c| c.z).reduce(f32_max).unwrap());
|
|
|
}
|
|
|
|
|
|
- pub fn from(m: &Mesh, f: &Face) -> AABB {
|
|
|
+ pub fn from(fr: &[FaceReference]) -> AABB {
|
|
|
let mut aabb = AABB {
|
|
|
min: Vec3::new(f32::INFINITY, f32::INFINITY, f32::INFINITY),
|
|
|
max: Vec3::new(-f32::INFINITY, -f32::INFINITY, -f32::INFINITY),
|
|
|
};
|
|
|
|
|
|
- aabb.extend(m, f);
|
|
|
-
|
|
|
+ for face_reference in fr {
|
|
|
+ aabb.extend(face_reference.m, face_reference.f);
|
|
|
+ }
|
|
|
+
|
|
|
return aabb;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
+
|
|
|
+/**
|
|
|
+ * Bounding Volume Hierarchy
|
|
|
+ */
|
|
|
+pub enum BVH<'a> {
|
|
|
+ Node(AABB, Box<BVH<'a>>, Box<BVH<'a>>),
|
|
|
+ Leaf(AABB, Vec<FaceReference<'a>>)
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+#[derive(Clone)]
|
|
|
+pub struct FaceReference<'a> {
|
|
|
+ m: &'a Mesh,
|
|
|
+ f: &'a Face
|
|
|
+}
|
|
|
+
|
|
|
+impl BVH<'_> {
|
|
|
+ fn build_recursive<'a, 'b>(frs: &'b mut [FaceReference<'a>], recursion_limit: u16, split_axis: Axis) -> BVH<'a> {
|
|
|
+ let aabb = AABB::from(frs);
|
|
|
+ let frs_count = frs.len();
|
|
|
+
|
|
|
+ if recursion_limit == 0 || frs_count <= 3 {
|
|
|
+ // We have reached the maximum of recursions necessary.
|
|
|
+ return BVH::Leaf(aabb, Vec::from(frs));
|
|
|
+ }
|
|
|
+
|
|
|
+ // Sort along the current axis
|
|
|
+ frs.sort_by(|a,b| a.f.center.select(split_axis).partial_cmp(
|
|
|
+ &b.f.center.select(split_axis)).unwrap());
|
|
|
+
|
|
|
+ // Select using surface area heuristic
|
|
|
+ let total_surface: f32= frs.iter().map(|fr| fr.f.area).sum();
|
|
|
+
|
|
|
+ let mut split_index : usize = 0;
|
|
|
+ let mut surface_area = 0.0;
|
|
|
+ while surface_area < total_surface / 2.0 {
|
|
|
+ surface_area += frs[split_index].f.area;
|
|
|
+ split_index += 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Recurse
|
|
|
+ let (frs1, frs2) = frs.split_at_mut(split_index);
|
|
|
+ let left = Self::build_recursive(frs1, recursion_limit - 1, split_axis.next());
|
|
|
+ let right = Self::build_recursive(frs2, recursion_limit - 1, split_axis.next());
|
|
|
+
|
|
|
+ return BVH::Node(aabb, Box::new(left), Box::new(right));
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn from<'a>(meshes: &'a Vec<Mesh>, recursion_depth: u16) -> BVH {
|
|
|
+ // Create references for each triangle
|
|
|
+ let mut references = vec!();
|
|
|
+
|
|
|
+ for m in meshes {
|
|
|
+ for f in &m.faces {
|
|
|
+ references.push(FaceReference {
|
|
|
+ m: &m,
|
|
|
+ f: &f
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ let bvh = Self::build_recursive(&mut references, recursion_depth, Axis::x);
|
|
|
+
|
|
|
+ return bvh;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl std::fmt::Display for AABB {
|
|
|
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
|
+ return write!(f, "{} -> {}", self.min, self.max);
|
|
|
+ }
|
|
|
+}
|
|
|
+impl std::fmt::Display for BVH<'_> {
|
|
|
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
|
+ match self {
|
|
|
+ BVH::Leaf(aabb,_) => {
|
|
|
+ return write!(f, "(Leaf {})", aabb);
|
|
|
+ }
|
|
|
+ BVH::Node(aabb, left, right) => {
|
|
|
+ return write!(f, "(Node {}; {} {})", aabb, left, right);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|