rtiow: AABB add hit_distance to return Option<f32> instead of bool.
This commit is contained in:
parent
cd149755cb
commit
f73a471cb6
@ -33,10 +33,11 @@ impl fmt::Debug for AABB {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"AABB: <{} - {}> Vol: {}",
|
"AABB: <{} - {}> Vol: {} Area: {}",
|
||||||
self.bounds[0],
|
self.bounds[0],
|
||||||
self.bounds[1],
|
self.bounds[1],
|
||||||
self.volume()
|
self.volume(),
|
||||||
|
self.area()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,10 +103,14 @@ impl AABB {
|
|||||||
// TODO(wathiede): implement branchless https://tavianator.com/cgit/dimension.git/tree/libdimension/bvh/bvh.c#n194
|
// TODO(wathiede): implement branchless https://tavianator.com/cgit/dimension.git/tree/libdimension/bvh/bvh.c#n194
|
||||||
|
|
||||||
pub fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> bool {
|
pub fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> bool {
|
||||||
|
self.hit_simd(r, t_min, t_max).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hit_distance(&self, r: Ray, t_min: f32, t_max: f32) -> Option<f32> {
|
||||||
self.hit_simd(r, t_min, t_max)
|
self.hit_simd(r, t_min, t_max)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hit_naive(&self, r: Ray, t_min: f32, t_max: f32) -> bool {
|
pub fn hit_naive(&self, r: Ray, t_min: f32, t_max: f32) -> Option<f32> {
|
||||||
let mut t_min = t_min;
|
let mut t_min = t_min;
|
||||||
let mut t_max = t_max;
|
let mut t_max = t_max;
|
||||||
for axis in 0..3 {
|
for axis in 0..3 {
|
||||||
@ -116,13 +121,13 @@ impl AABB {
|
|||||||
t_min = t0.max(t_min);
|
t_min = t0.max(t_min);
|
||||||
t_max = t1.min(t_max);
|
t_max = t1.min(t_max);
|
||||||
if t_max <= t_min {
|
if t_max <= t_min {
|
||||||
return false;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
Some(t_min)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hit2(&self, r: Ray, t_min: f32, t_max: f32) -> bool {
|
pub fn hit2(&self, r: Ray, t_min: f32, t_max: f32) -> Option<f32> {
|
||||||
let mut t_min = t_min;
|
let mut t_min = t_min;
|
||||||
let mut t_max = t_max;
|
let mut t_max = t_max;
|
||||||
for axis in 0..3 {
|
for axis in 0..3 {
|
||||||
@ -138,13 +143,13 @@ impl AABB {
|
|||||||
t_min = max(t0, t_min);
|
t_min = max(t0, t_min);
|
||||||
t_max = min(t1, t_max);
|
t_max = min(t1, t_max);
|
||||||
if t_max <= t_min {
|
if t_max <= t_min {
|
||||||
return false;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
Some(t_min)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hit_precompute(&self, r: Ray, t0: f32, t1: f32) -> bool {
|
pub fn hit_precompute(&self, r: Ray, t0: f32, t1: f32) -> Option<f32> {
|
||||||
// TODO(wathiede): this has bugs.
|
// TODO(wathiede): this has bugs.
|
||||||
let mut t_min = (self.bounds[r.sign[0]].x - r.origin.x) * r.inv_direction.x;
|
let mut t_min = (self.bounds[r.sign[0]].x - r.origin.x) * r.inv_direction.x;
|
||||||
let mut t_max = (self.bounds[1 - r.sign[0]].x - r.origin.x) * r.inv_direction.x;
|
let mut t_max = (self.bounds[1 - r.sign[0]].x - r.origin.x) * r.inv_direction.x;
|
||||||
@ -152,7 +157,7 @@ impl AABB {
|
|||||||
let t_y_max = (self.bounds[1 - r.sign[0]].y - r.origin.y) * r.inv_direction.y;
|
let t_y_max = (self.bounds[1 - r.sign[0]].y - r.origin.y) * r.inv_direction.y;
|
||||||
|
|
||||||
if t_min > t_y_max || t_y_min > t_max {
|
if t_min > t_y_max || t_y_min > t_max {
|
||||||
return false;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if t_y_min > t_min {
|
if t_y_min > t_min {
|
||||||
@ -165,7 +170,7 @@ impl AABB {
|
|||||||
let t_z_min = (self.bounds[r.sign[2]].z - r.origin.z) * r.inv_direction.z;
|
let t_z_min = (self.bounds[r.sign[2]].z - r.origin.z) * r.inv_direction.z;
|
||||||
let t_z_max = (self.bounds[1 - r.sign[2]].z - r.origin.z) * r.inv_direction.z;
|
let t_z_max = (self.bounds[1 - r.sign[2]].z - r.origin.z) * r.inv_direction.z;
|
||||||
if t_min > t_z_max || t_z_min > t_max {
|
if t_min > t_z_max || t_z_min > t_max {
|
||||||
return false;
|
return None;
|
||||||
}
|
}
|
||||||
if t_z_min > t_min {
|
if t_z_min > t_min {
|
||||||
t_min = t_z_min;
|
t_min = t_z_min;
|
||||||
@ -173,10 +178,14 @@ impl AABB {
|
|||||||
if t_z_max < t_max {
|
if t_z_max < t_max {
|
||||||
t_max = t_z_max;
|
t_max = t_z_max;
|
||||||
}
|
}
|
||||||
t_min < t1 && t_max > t0
|
if t_min < t1 && t_max > t0 {
|
||||||
|
Some(t_min)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hit_simd(&self, r: Ray, t_min: f32, t_max: f32) -> bool {
|
pub fn hit_simd(&self, r: Ray, t_min: f32, t_max: f32) -> Option<f32> {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
unsafe {
|
unsafe {
|
||||||
use std::arch::x86_64::*;
|
use std::arch::x86_64::*;
|
||||||
@ -193,14 +202,18 @@ impl AABB {
|
|||||||
let vmin4: (f32, f32, f32, f32) = std::mem::transmute(vmin4);
|
let vmin4: (f32, f32, f32, f32) = std::mem::transmute(vmin4);
|
||||||
let tmax = min(min(vmax4.0, min(vmax4.1, vmax4.2)), t_max);
|
let tmax = min(min(vmax4.0, min(vmax4.1, vmax4.2)), t_max);
|
||||||
let tmin = max(max(vmin4.0, max(vmin4.1, vmin4.2)), t_min);
|
let tmin = max(max(vmin4.0, max(vmin4.1, vmin4.2)), t_min);
|
||||||
tmin <= tmax
|
if tmin <= tmax {
|
||||||
|
Some(tmin)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
// TODO(wathiede): add NEON implementation.
|
// TODO(wathiede): add NEON implementation.
|
||||||
self.hit2(r, t_min, t_max)
|
self.hit2(r, t_min, t_max)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hit_fast(&self, r: Ray, _t_min: f32, _t_max: f32) -> bool {
|
pub fn hit_fast(&self, r: Ray, _t_min: f32, _t_max: f32) -> Option<f32> {
|
||||||
let b = self;
|
let b = self;
|
||||||
let mut t1 = (b.min()[0] - r.origin[0]) * 1. / r.direction[0];
|
let mut t1 = (b.min()[0] - r.origin[0]) * 1. / r.direction[0];
|
||||||
let mut t2 = (b.max()[0] - r.origin[0]) * 1. / r.direction[0];
|
let mut t2 = (b.max()[0] - r.origin[0]) * 1. / r.direction[0];
|
||||||
@ -216,7 +229,11 @@ impl AABB {
|
|||||||
tmax = tmax.min(t1.max(t2));
|
tmax = tmax.min(t1.max(t2));
|
||||||
}
|
}
|
||||||
|
|
||||||
tmax > tmin.max(0.0)
|
if tmax > tmin.max(0.0) {
|
||||||
|
Some(tmin)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,74 +271,74 @@ mod tests {
|
|||||||
fn hit_front() {
|
fn hit_front() {
|
||||||
let bb = test_bb();
|
let bb = test_bb();
|
||||||
let r = Ray::new([-2., 0., 0.], [1., 0., 0.], 0.5);
|
let r = Ray::new([-2., 0., 0.], [1., 0., 0.], 0.5);
|
||||||
assert!(bb.$name(r, T_MIN, T_MAX));
|
assert!(bb.$name(r, T_MIN, T_MAX).is_some());
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn hit_back() {
|
fn hit_back() {
|
||||||
let bb = test_bb();
|
let bb = test_bb();
|
||||||
let r = Ray::new([2., 0., 0.], [-1., 0., 0.], 0.5);
|
let r = Ray::new([2., 0., 0.], [-1., 0., 0.], 0.5);
|
||||||
assert!(bb.$name(r, T_MIN, T_MAX));
|
assert!(bb.$name(r, T_MIN, T_MAX).is_some());
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn hit_top() {
|
fn hit_top() {
|
||||||
let bb = test_bb();
|
let bb = test_bb();
|
||||||
let r = Ray::new([0., 2., 0.], [0., -1., 0.], 0.5);
|
let r = Ray::new([0., 2., 0.], [0., -1., 0.], 0.5);
|
||||||
assert!(bb.$name(r, T_MIN, T_MAX));
|
assert!(bb.$name(r, T_MIN, T_MAX).is_some());
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn hit_bottom() {
|
fn hit_bottom() {
|
||||||
let bb = test_bb();
|
let bb = test_bb();
|
||||||
let r = Ray::new([0., -2., 0.], [0., 1., 0.], 0.5);
|
let r = Ray::new([0., -2., 0.], [0., 1., 0.], 0.5);
|
||||||
assert!(bb.$name(r, T_MIN, T_MAX));
|
assert!(bb.$name(r, T_MIN, T_MAX).is_some());
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn hit_left() {
|
fn hit_left() {
|
||||||
let bb = test_bb();
|
let bb = test_bb();
|
||||||
let r = Ray::new([0., 0., -2.], [0., 0., 1.], 0.5);
|
let r = Ray::new([0., 0., -2.], [0., 0., 1.], 0.5);
|
||||||
assert!(bb.$name(r, T_MIN, T_MAX));
|
assert!(bb.$name(r, T_MIN, T_MAX).is_some());
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn hit_right() {
|
fn hit_right() {
|
||||||
let bb = test_bb();
|
let bb = test_bb();
|
||||||
let r = Ray::new([0., 0., 2.], [0., 0., -1.], 0.5);
|
let r = Ray::new([0., 0., 2.], [0., 0., -1.], 0.5);
|
||||||
assert!(bb.$name(r, T_MIN, T_MAX));
|
assert!(bb.$name(r, T_MIN, T_MAX).is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn miss_front() {
|
fn miss_front() {
|
||||||
let bb = test_bb();
|
let bb = test_bb();
|
||||||
let r = Ray::new([0., 1.1, -1.1], [0., -1., 0.], 0.5);
|
let r = Ray::new([0., 1.1, -1.1], [0., -1., 0.], 0.5);
|
||||||
assert!(!bb.$name(r, T_MIN, T_MAX));
|
assert_eq!(bb.$name(r, T_MIN, T_MAX), None);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn miss_back() {
|
fn miss_back() {
|
||||||
let bb = test_bb();
|
let bb = test_bb();
|
||||||
let r = Ray::new([0., 1.1, 1.1], [0., -1., 0.], 0.5);
|
let r = Ray::new([0., 1.1, 1.1], [0., -1., 0.], 0.5);
|
||||||
assert!(!bb.$name(r, T_MIN, T_MAX));
|
assert_eq!(bb.$name(r, T_MIN, T_MAX), None);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn miss_top() {
|
fn miss_top() {
|
||||||
let bb = test_bb();
|
let bb = test_bb();
|
||||||
let r = Ray::new([0., 1.1, -1.1], [0., 0., 1.], 0.5);
|
let r = Ray::new([0., 1.1, -1.1], [0., 0., 1.], 0.5);
|
||||||
assert!(!bb.$name(r, T_MIN, T_MAX));
|
assert_eq!(bb.$name(r, T_MIN, T_MAX), None);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn miss_bottom() {
|
fn miss_bottom() {
|
||||||
let bb = test_bb();
|
let bb = test_bb();
|
||||||
let r = Ray::new([0., -1.1, -1.1], [0., 0., 1.], 0.5);
|
let r = Ray::new([0., -1.1, -1.1], [0., 0., 1.], 0.5);
|
||||||
assert!(!bb.$name(r, T_MIN, T_MAX));
|
assert_eq!(bb.$name(r, T_MIN, T_MAX), None);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn miss_left() {
|
fn miss_left() {
|
||||||
let bb = test_bb();
|
let bb = test_bb();
|
||||||
let r = Ray::new([-1.1, 0., -1.1], [0., 0., 1.], 0.5);
|
let r = Ray::new([-1.1, 0., -1.1], [0., 0., 1.], 0.5);
|
||||||
assert!(!bb.$name(r, T_MIN, T_MAX));
|
assert_eq!(bb.$name(r, T_MIN, T_MAX), None);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn miss_right() {
|
fn miss_right() {
|
||||||
let bb = test_bb();
|
let bb = test_bb();
|
||||||
let r = Ray::new([1.1, 0., -1.1], [0., 0., 1.], 0.5);
|
let r = Ray::new([1.1, 0., -1.1], [0., 0., 1.], 0.5);
|
||||||
assert!(!bb.$name(r, T_MIN, T_MAX));
|
assert_eq!(bb.$name(r, T_MIN, T_MAX), None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
@ -330,8 +347,8 @@ mod tests {
|
|||||||
|
|
||||||
hit_test! {
|
hit_test! {
|
||||||
hit_naive,
|
hit_naive,
|
||||||
hit2,
|
|
||||||
hit_fast,
|
|
||||||
hit_simd,
|
hit_simd,
|
||||||
|
hit_fast,
|
||||||
|
hit2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user