1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
//! Implements 3d axis aligned bounding box
use crate::{Number, Float};
use super::vector3::{Vector3, Vector3f};
use crate::core::{min, max};
use crate::core::Ray;
#[derive(Clone)]
pub struct Bound3<T: Number> {
pub min: Vector3<T>,
pub max: Vector3<T>
}
pub type Bound3f = Bound3<Float>;
impl<T: Number> Bound3<T> {
/// Creates a bound from two points
pub fn new(p0: Vector3<T>, p1: Vector3<T>) -> Self {
// Elliminate some code duplication here
let min = Vector3::new_xyz(
min(p0.x, p1.x),
min(p0.y, p1.y),
min(p0.z, p1.z)
);
let max = Vector3::new_xyz(
max(p0.x, p1.x),
max(p0.y, p1.y),
max(p0.z, p1.z)
);
Self {min, max}
}
pub fn combine(&self, op: &Self) -> Self {
let min = Vector3::new_xyz(
min(self.min.x, op.min.x),
min(self.min.y, op.min.y),
min(self.min.z, op.min.z)
);
let max = Vector3::new_xyz(
max(self.max.x, op.max.x),
max(self.max.y, op.max.y),
max(self.max.z, op.max.z)
);
Self {min, max}
}
pub fn and(&self, op: &Self) -> Self {
let min_b = Vector3::new_xyz(
max(self.min.x, op.min.x),
max(self.min.y, op.min.y),
max(self.min.z, op.min.z)
);
let max_b = Vector3::new_xyz(
min(self.max.x, op.max.x),
min(self.max.y, op.max.y),
min(self.max.z, op.max.z)
);
Self {min: min_b, max: max_b}
}
pub fn area(&self) -> T {
let diag = self.max - self.min;
diag.x * diag.y * diag.z
}
pub fn offset(&self, offset: Vector3<T>) -> Self {
Self {
min: self.min + offset,
max: self.max + offset,
}
}
}
impl Bound3f {
pub const EMPTY: Bound3f = Bound3f{min: Vector3f::ZERO, max: Vector3f::ZERO};
/// Calculate whether there is a intersect between a bounding box and a ray
///
/// # Examples:
///
/// ```
/// use rendering::core::{Bound3f, Vector3f, Ray};
/// use rendering::INFTY;
/// let b = Bound3f::new(Vector3f::new(7.0), Vector3f::new(10.0));
/// let r1 = Ray::new_to(Vector3f::new(0.0), Vector3f::new(5.0));
/// let r2 = Ray::new_to(Vector3f::new(-0.0), Vector3f::new(-5.0));
/// let r3 = Ray::new(Vector3f::new_xyz(-1.0, 0.0, 0.0), Vector3f::new_xyz(1.0, 0.0, 0.0));
///
/// assert!(b.intersect(&r1, 0.0, INFTY));
/// assert!(!b.intersect(&r2, 0.0, INFTY));
/// assert!(!b.intersect(&r3, 0.0, INFTY));
/// ```
pub fn intersect(&self, ray: &Ray, t_min: Float, t_max: Float) -> bool {
// Method stolen from Ray tracing the next week.
// They mention its from pixar
for i in 0..3 {
let inv = 1.0 / ray.direction[i];
let mut t0 = (self.min[i] - ray.origin[i]) * inv;
let mut t1 = (self.max[i] - ray.origin[i]) * inv;
if inv < 0.0 {
let tmp = t0;
t0 = t1;
t1 = tmp;
}
let t_min = max(t0, t_min);
let t_max = min(t1, t_max);
if t_max <= t_min {
return false;
}
}
return true;
}
}
|