92 lines
2.9 KiB
Rust
92 lines
2.9 KiB
Rust
use vecmath::vec3_sub;
|
|
|
|
#[derive(Default, Clone)]
|
|
pub struct Box3 {
|
|
pub min_bd: [f32; 3],
|
|
pub max_bd: [f32; 3],
|
|
}
|
|
|
|
impl Box3 {
|
|
/// Create a new box from the bounding values
|
|
pub fn new_from_bounds(min_bd: [f32; 3], max_bd: [f32; 3]) -> Self {
|
|
Box3 { min_bd, max_bd }
|
|
}
|
|
|
|
/// This function returns the 8 vertices of an axis-aligned bounding box.
|
|
/// These are ordered
|
|
/// 7----6
|
|
/// | /| /|
|
|
/// | 4----5
|
|
/// | | 3--| 2
|
|
/// | |/ |/
|
|
/// | 0----1
|
|
pub fn get_vertices(&self) -> Vec<[f32; 3]> {
|
|
vec![
|
|
self.min_bd,
|
|
[self.max_bd[0], self.min_bd[1], self.min_bd[2]],
|
|
[self.max_bd[0], self.max_bd[1], self.min_bd[2]],
|
|
[self.min_bd[0], self.max_bd[1], self.min_bd[2]],
|
|
[self.max_bd[0], self.min_bd[1], self.max_bd[2]],
|
|
[self.max_bd[0], self.max_bd[1], self.max_bd[2]],
|
|
self.max_bd,
|
|
[self.min_bd[0], self.max_bd[1], self.max_bd[2]],
|
|
]
|
|
}
|
|
|
|
/// Expand a box to fit all primitive inside of it.
|
|
/// NOTE: vertices does not need to include only vertices being considered. Instead only
|
|
/// vertices included as indices in the primitives list are considered
|
|
pub fn shrink_wrap_primitives<T>(&mut self, vertices: &[[f32; 3]], primitives: &[T])
|
|
where
|
|
for<'a> &'a T: IntoIterator<Item = &'a usize>,
|
|
{
|
|
// If the current primitive list is empty, zero bounding box and exit
|
|
if primitives.is_empty() {
|
|
self.min_bd = [0.0; 3];
|
|
self.max_bd = [0.0; 3];
|
|
return;
|
|
}
|
|
|
|
for vertex_idx in primitives.iter().flatten() {
|
|
self.grow(vertices[*vertex_idx]);
|
|
}
|
|
}
|
|
|
|
/// Compute the surface area of a box
|
|
pub fn surface_area(&self) -> f32 {
|
|
let extents = vec3_sub(self.max_bd, self.min_bd);
|
|
extents[0] * extents[1] + extents[1] * extents[2] + extents[2] * extents[0]
|
|
}
|
|
|
|
/// Get the extents of the current box
|
|
#[inline(always)]
|
|
pub fn get_extents(&self) -> [f32; 3] {
|
|
vec3_sub(self.max_bd, self.min_bd)
|
|
}
|
|
|
|
/// Grow the axis aligned bounding box to include a specific vertex
|
|
#[inline(always)]
|
|
pub fn grow(&mut self, vertex: [f32; 3]) {
|
|
for (axis, pos) in vertex.iter().enumerate() {
|
|
self.min_bd[axis] = self.min_bd[axis].min(*pos);
|
|
self.max_bd[axis] = self.max_bd[axis].min(*pos);
|
|
}
|
|
}
|
|
|
|
/// Grow the axis aligned bounding box to include a min and max boundary
|
|
/// This is useful when trying to combine two bounding boxes
|
|
#[inline(always)]
|
|
pub fn grow_by_other_box(&mut self, other: &Self) {
|
|
for axis in 0..3 {
|
|
self.min_bd[axis] = self.min_bd[axis].min(other.min_bd[axis]);
|
|
self.max_bd[axis] = self.max_bd[axis].max(other.max_bd[axis]);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct Triangle {
|
|
pub v1: [f32; 3],
|
|
pub v2: [f32; 3],
|
|
pub v3: [f32; 3],
|
|
}
|