Got rid of indexing into Float4 and 3d vector elements.
This assures correct semantics for SIMD usage.
This commit is contained in:
parent
378f69dd57
commit
7ef5846c89
22
src/bbox.rs
22
src/bbox.rs
|
@ -58,14 +58,14 @@ impl BBox {
|
||||||
// Creates a new BBox transformed into a different space.
|
// Creates a new BBox transformed into a different space.
|
||||||
pub fn transformed(&self, xform: Matrix4x4) -> BBox {
|
pub fn transformed(&self, xform: Matrix4x4) -> BBox {
|
||||||
// BBox corners
|
// BBox corners
|
||||||
let vs = [Point::new(self.min[0], self.min[1], self.min[2]),
|
let vs = [Point::new(self.min.x(), self.min.y(), self.min.z()),
|
||||||
Point::new(self.min[0], self.min[1], self.max[2]),
|
Point::new(self.min.x(), self.min.y(), self.max.z()),
|
||||||
Point::new(self.min[0], self.max[1], self.min[2]),
|
Point::new(self.min.x(), self.max.y(), self.min.z()),
|
||||||
Point::new(self.min[0], self.max[1], self.max[2]),
|
Point::new(self.min.x(), self.max.y(), self.max.z()),
|
||||||
Point::new(self.max[0], self.min[1], self.min[2]),
|
Point::new(self.max.x(), self.min.y(), self.min.z()),
|
||||||
Point::new(self.max[0], self.min[1], self.max[2]),
|
Point::new(self.max.x(), self.min.y(), self.max.z()),
|
||||||
Point::new(self.max[0], self.max[1], self.min[2]),
|
Point::new(self.max.x(), self.max.y(), self.min.z()),
|
||||||
Point::new(self.max[0], self.max[1], self.max[2])];
|
Point::new(self.max.x(), self.max.y(), self.max.z())];
|
||||||
|
|
||||||
// Transform BBox corners and make new bbox
|
// Transform BBox corners and make new bbox
|
||||||
let mut b = BBox::new();
|
let mut b = BBox::new();
|
||||||
|
@ -79,9 +79,9 @@ impl BBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn surface_area(&self) -> f32 {
|
pub fn surface_area(&self) -> f32 {
|
||||||
let x = self.max[0] - self.min[0];
|
let x = self.max.x() - self.min.x();
|
||||||
let y = self.max[1] - self.min[1];
|
let y = self.max.y() - self.min.y();
|
||||||
let z = self.max[2] - self.min[2];
|
let z = self.max.z() - self.min.z();
|
||||||
|
|
||||||
((x * y) + (y * z) + (z * x)) * 2.0
|
((x * y) + (y * z) + (z * x)) * 2.0
|
||||||
}
|
}
|
||||||
|
|
18
src/bvh.rs
18
src/bvh.rs
|
@ -145,10 +145,10 @@ impl BVH {
|
||||||
let sah_divs = {
|
let sah_divs = {
|
||||||
let mut sah_divs = [[0.0f32; SAH_BIN_COUNT - 1]; 3];
|
let mut sah_divs = [[0.0f32; SAH_BIN_COUNT - 1]; 3];
|
||||||
for d in 0..3 {
|
for d in 0..3 {
|
||||||
let extent = bounds.max[d] - bounds.min[d];
|
let extent = bounds.max.get_n(d) - bounds.min.get_n(d);
|
||||||
for div in 0..(SAH_BIN_COUNT - 1) {
|
for div in 0..(SAH_BIN_COUNT - 1) {
|
||||||
let part = extent * ((div + 1) as f32 / SAH_BIN_COUNT as f32);
|
let part = extent * ((div + 1) as f32 / SAH_BIN_COUNT as f32);
|
||||||
sah_divs[d][div] = bounds.min[d] + part;
|
sah_divs[d][div] = bounds.min.get_n(d) + part;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sah_divs
|
sah_divs
|
||||||
|
@ -163,7 +163,7 @@ impl BVH {
|
||||||
|
|
||||||
for d in 0..3 {
|
for d in 0..3 {
|
||||||
for div in 0..(SAH_BIN_COUNT - 1) {
|
for div in 0..(SAH_BIN_COUNT - 1) {
|
||||||
if centroid[d] <= sah_divs[d][div] {
|
if centroid.get_n(d) <= sah_divs[d][div] {
|
||||||
sah_bins[d][div].0 |= tb;
|
sah_bins[d][div].0 |= tb;
|
||||||
sah_bins[d][div].2 += 1;
|
sah_bins[d][div].2 += 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -203,7 +203,7 @@ impl BVH {
|
||||||
// Partition
|
// Partition
|
||||||
let mut split_i = partition(&mut objects[..], |obj| {
|
let mut split_i = partition(&mut objects[..], |obj| {
|
||||||
let tb = lerp_slice(bounder(obj), 0.5);
|
let tb = lerp_slice(bounder(obj), 0.5);
|
||||||
let centroid = (tb.min[split_axis] + tb.max[split_axis]) * 0.5;
|
let centroid = (tb.min.get_n(split_axis) + tb.max.get_n(split_axis)) * 0.5;
|
||||||
centroid < div
|
centroid < div
|
||||||
});
|
});
|
||||||
if split_i < 1 {
|
if split_i < 1 {
|
||||||
|
@ -219,7 +219,7 @@ impl BVH {
|
||||||
let mut axis = 0;
|
let mut axis = 0;
|
||||||
let mut largest = std::f32::NEG_INFINITY;
|
let mut largest = std::f32::NEG_INFINITY;
|
||||||
for i in 0..3 {
|
for i in 0..3 {
|
||||||
let extent = bounds.max[i] - bounds.min[i];
|
let extent = bounds.max.get_n(i) - bounds.min.get_n(i);
|
||||||
if extent > largest {
|
if extent > largest {
|
||||||
largest = extent;
|
largest = extent;
|
||||||
axis = i;
|
axis = i;
|
||||||
|
@ -234,8 +234,10 @@ impl BVH {
|
||||||
&|a, b| {
|
&|a, b| {
|
||||||
let tb_a = lerp_slice(bounder(a), 0.5);
|
let tb_a = lerp_slice(bounder(a), 0.5);
|
||||||
let tb_b = lerp_slice(bounder(b), 0.5);
|
let tb_b = lerp_slice(bounder(b), 0.5);
|
||||||
let centroid_a = (tb_a.min[split_axis] + tb_a.max[split_axis]) * 0.5;
|
let centroid_a = (tb_a.min.get_n(split_axis) + tb_a.max.get_n(split_axis)) *
|
||||||
let centroid_b = (tb_b.min[split_axis] + tb_b.max[split_axis]) * 0.5;
|
0.5;
|
||||||
|
let centroid_b = (tb_b.min.get_n(split_axis) + tb_b.max.get_n(split_axis)) *
|
||||||
|
0.5;
|
||||||
|
|
||||||
if centroid_a < centroid_b {
|
if centroid_a < centroid_b {
|
||||||
Ordering::Less
|
Ordering::Less
|
||||||
|
@ -307,7 +309,7 @@ impl BVH {
|
||||||
i_stack[stack_ptr + 1] = second_child_index;
|
i_stack[stack_ptr + 1] = second_child_index;
|
||||||
ray_i_stack[stack_ptr] = part;
|
ray_i_stack[stack_ptr] = part;
|
||||||
ray_i_stack[stack_ptr + 1] = part;
|
ray_i_stack[stack_ptr + 1] = part;
|
||||||
if rays[0].dir_inv[split_axis as usize].is_sign_positive() {
|
if rays[0].dir_inv.get_n(split_axis as usize).is_sign_positive() {
|
||||||
i_stack.swap(stack_ptr, stack_ptr + 1);
|
i_stack.swap(stack_ptr, stack_ptr + 1);
|
||||||
}
|
}
|
||||||
stack_ptr += 1;
|
stack_ptr += 1;
|
||||||
|
|
|
@ -70,8 +70,8 @@ impl Camera {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ray direction
|
// Ray direction
|
||||||
let dir = Vector::new((x * tfov) - (orig[0] / focus_distance),
|
let dir = Vector::new((x * tfov) - (orig.x() / focus_distance),
|
||||||
(y * tfov) - (orig[1] / focus_distance),
|
(y * tfov) - (orig.y() / focus_distance),
|
||||||
1.0)
|
1.0)
|
||||||
.normalized();
|
.normalized();
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ impl SpectralSample {
|
||||||
pub fn new(wavelength: f32) -> SpectralSample {
|
pub fn new(wavelength: f32) -> SpectralSample {
|
||||||
debug_assert!(wavelength >= WL_MIN && wavelength <= WL_MAX);
|
debug_assert!(wavelength >= WL_MIN && wavelength <= WL_MAX);
|
||||||
SpectralSample {
|
SpectralSample {
|
||||||
e: Float4::new(0.0, 0.0, 0.0, 0.0),
|
e: Float4::splat(0.0),
|
||||||
hero_wavelength: wavelength,
|
hero_wavelength: wavelength,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ impl SpectralSample {
|
||||||
pub fn from_value(value: f32, wavelength: f32) -> SpectralSample {
|
pub fn from_value(value: f32, wavelength: f32) -> SpectralSample {
|
||||||
debug_assert!(wavelength >= WL_MIN && wavelength <= WL_MAX);
|
debug_assert!(wavelength >= WL_MIN && wavelength <= WL_MAX);
|
||||||
SpectralSample {
|
SpectralSample {
|
||||||
e: Float4::new(value, value, value, value),
|
e: Float4::splat(value),
|
||||||
hero_wavelength: wavelength,
|
hero_wavelength: wavelength,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,10 +174,10 @@ impl XYZ {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_spectral_sample(ss: &SpectralSample) -> XYZ {
|
pub fn from_spectral_sample(ss: &SpectralSample) -> XYZ {
|
||||||
let xyz0 = XYZ::from_wavelength(ss.wl_n(0), ss.e[0]);
|
let xyz0 = XYZ::from_wavelength(ss.wl_n(0), ss.e.get_0());
|
||||||
let xyz1 = XYZ::from_wavelength(ss.wl_n(1), ss.e[1]);
|
let xyz1 = XYZ::from_wavelength(ss.wl_n(1), ss.e.get_1());
|
||||||
let xyz2 = XYZ::from_wavelength(ss.wl_n(2), ss.e[2]);
|
let xyz2 = XYZ::from_wavelength(ss.wl_n(2), ss.e.get_2());
|
||||||
let xyz3 = XYZ::from_wavelength(ss.wl_n(3), ss.e[3]);
|
let xyz3 = XYZ::from_wavelength(ss.wl_n(3), ss.e.get_3());
|
||||||
(xyz0 + xyz1 + xyz2 + xyz3) * 0.75
|
(xyz0 + xyz1 + xyz2 + xyz3) * 0.75
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
130
src/float4.rs
130
src/float4.rs
|
@ -1,6 +1,6 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::ops::{Index, IndexMut, Add, Sub, Mul, Div};
|
use std::ops::{Add, Sub, Mul, Div};
|
||||||
use std::cmp::PartialEq;
|
use std::cmp::PartialEq;
|
||||||
|
|
||||||
#[cfg(feature = "simd_perf")]
|
#[cfg(feature = "simd_perf")]
|
||||||
|
@ -140,11 +140,25 @@ impl Float4 {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the nth element to the given value.
|
||||||
|
#[inline]
|
||||||
|
pub fn set_n(&mut self, n: usize, v: f32) {
|
||||||
|
match n {
|
||||||
|
0 => self.set_0(v),
|
||||||
|
1 => self.set_1(v),
|
||||||
|
2 => self.set_2(v),
|
||||||
|
3 => self.set_3(v),
|
||||||
|
_ => panic!("Attempted to set element of Float4 outside of bounds."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the 0th element to the given value.
|
/// Set the 0th element to the given value.
|
||||||
#[cfg(feature = "simd_perf")]
|
#[cfg(feature = "simd_perf")]
|
||||||
|
#[inline(always)]
|
||||||
pub fn set_0(&mut self, n: f32) {
|
pub fn set_0(&mut self, n: f32) {
|
||||||
self.data = self.data.replace(0, n);
|
self.data = self.data.replace(0, n);
|
||||||
}
|
}
|
||||||
|
#[inline(always)]
|
||||||
#[cfg(not(feature = "simd_perf"))]
|
#[cfg(not(feature = "simd_perf"))]
|
||||||
pub fn set_0(&mut self, n: f32) {
|
pub fn set_0(&mut self, n: f32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -154,10 +168,12 @@ impl Float4 {
|
||||||
|
|
||||||
/// Set the 1th element to the given value.
|
/// Set the 1th element to the given value.
|
||||||
#[cfg(feature = "simd_perf")]
|
#[cfg(feature = "simd_perf")]
|
||||||
|
#[inline(always)]
|
||||||
pub fn set_1(&mut self, n: f32) {
|
pub fn set_1(&mut self, n: f32) {
|
||||||
self.data = self.data.replace(1, n);
|
self.data = self.data.replace(1, n);
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "simd_perf"))]
|
#[cfg(not(feature = "simd_perf"))]
|
||||||
|
#[inline(always)]
|
||||||
pub fn set_1(&mut self, n: f32) {
|
pub fn set_1(&mut self, n: f32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
*self.data.get_unchecked_mut(1) = n;
|
*self.data.get_unchecked_mut(1) = n;
|
||||||
|
@ -166,10 +182,12 @@ impl Float4 {
|
||||||
|
|
||||||
/// Set the 2th element to the given value.
|
/// Set the 2th element to the given value.
|
||||||
#[cfg(feature = "simd_perf")]
|
#[cfg(feature = "simd_perf")]
|
||||||
|
#[inline(always)]
|
||||||
pub fn set_2(&mut self, n: f32) {
|
pub fn set_2(&mut self, n: f32) {
|
||||||
self.data = self.data.replace(2, n);
|
self.data = self.data.replace(2, n);
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "simd_perf"))]
|
#[cfg(not(feature = "simd_perf"))]
|
||||||
|
#[inline(always)]
|
||||||
pub fn set_2(&mut self, n: f32) {
|
pub fn set_2(&mut self, n: f32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
*self.data.get_unchecked_mut(2) = n;
|
*self.data.get_unchecked_mut(2) = n;
|
||||||
|
@ -178,92 +196,80 @@ impl Float4 {
|
||||||
|
|
||||||
/// Set the 3th element to the given value.
|
/// Set the 3th element to the given value.
|
||||||
#[cfg(feature = "simd_perf")]
|
#[cfg(feature = "simd_perf")]
|
||||||
|
#[inline(always)]
|
||||||
pub fn set_3(&mut self, n: f32) {
|
pub fn set_3(&mut self, n: f32) {
|
||||||
self.data = self.data.replace(3, n);
|
self.data = self.data.replace(3, n);
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "simd_perf"))]
|
#[cfg(not(feature = "simd_perf"))]
|
||||||
|
#[inline(always)]
|
||||||
pub fn set_3(&mut self, n: f32) {
|
pub fn set_3(&mut self, n: f32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
*self.data.get_unchecked_mut(3) = n;
|
*self.data.get_unchecked_mut(3) = n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the value of the nth element.
|
||||||
|
#[inline]
|
||||||
|
pub fn get_n(&self, n: usize) -> f32 {
|
||||||
|
match n {
|
||||||
|
0 => self.get_0(),
|
||||||
|
1 => self.get_1(),
|
||||||
|
2 => self.get_2(),
|
||||||
|
3 => self.get_3(),
|
||||||
|
_ => panic!("Attempted to access element of Float4 outside of bounds."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the value of the 0th element.
|
/// Returns the value of the 0th element.
|
||||||
#[cfg(feature = "simd_perf")]
|
#[cfg(feature = "simd_perf")]
|
||||||
|
#[inline(always)]
|
||||||
pub fn get_0(&self) -> f32 {
|
pub fn get_0(&self) -> f32 {
|
||||||
self.data.extract(0)
|
self.data.extract(0)
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "simd_perf"))]
|
#[cfg(not(feature = "simd_perf"))]
|
||||||
|
#[inline(always)]
|
||||||
pub fn get_0(&self) -> f32 {
|
pub fn get_0(&self) -> f32 {
|
||||||
unsafe { *self.data.get_unchecked(0) }
|
unsafe { *self.data.get_unchecked(0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the value of the 1th element.
|
/// Returns the value of the 1th element.
|
||||||
#[cfg(feature = "simd_perf")]
|
#[cfg(feature = "simd_perf")]
|
||||||
|
#[inline(always)]
|
||||||
pub fn get_1(&self) -> f32 {
|
pub fn get_1(&self) -> f32 {
|
||||||
self.data.extract(1)
|
self.data.extract(1)
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "simd_perf"))]
|
#[cfg(not(feature = "simd_perf"))]
|
||||||
|
#[inline(always)]
|
||||||
pub fn get_1(&self) -> f32 {
|
pub fn get_1(&self) -> f32 {
|
||||||
unsafe { *self.data.get_unchecked(1) }
|
unsafe { *self.data.get_unchecked(1) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the value of the 2th element.
|
/// Returns the value of the 2th element.
|
||||||
#[cfg(feature = "simd_perf")]
|
#[cfg(feature = "simd_perf")]
|
||||||
|
#[inline(always)]
|
||||||
pub fn get_2(&self) -> f32 {
|
pub fn get_2(&self) -> f32 {
|
||||||
self.data.extract(2)
|
self.data.extract(2)
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "simd_perf"))]
|
#[cfg(not(feature = "simd_perf"))]
|
||||||
|
#[inline(always)]
|
||||||
pub fn get_2(&self) -> f32 {
|
pub fn get_2(&self) -> f32 {
|
||||||
unsafe { *self.data.get_unchecked(2) }
|
unsafe { *self.data.get_unchecked(2) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the value of the 3th element.
|
/// Returns the value of the 3th element.
|
||||||
#[cfg(feature = "simd_perf")]
|
#[cfg(feature = "simd_perf")]
|
||||||
|
#[inline(always)]
|
||||||
pub fn get_3(&self) -> f32 {
|
pub fn get_3(&self) -> f32 {
|
||||||
self.data.extract(3)
|
self.data.extract(3)
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "simd_perf"))]
|
#[cfg(not(feature = "simd_perf"))]
|
||||||
|
#[inline(always)]
|
||||||
pub fn get_3(&self) -> f32 {
|
pub fn get_3(&self) -> f32 {
|
||||||
unsafe { *self.data.get_unchecked(3) }
|
unsafe { *self.data.get_unchecked(3) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Index<usize> for Float4 {
|
|
||||||
type Output = f32;
|
|
||||||
|
|
||||||
#[cfg(feature = "simd_perf")]
|
|
||||||
fn index(&self, index: usize) -> &f32 {
|
|
||||||
// TODO: this might not be correct! It works, but need to make sure
|
|
||||||
// to do this in a way with proper defined behavior.
|
|
||||||
use std::mem::transmute;
|
|
||||||
let vs: &[f32; 4] = unsafe { transmute(&self.data) };
|
|
||||||
&vs[index]
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "simd_perf"))]
|
|
||||||
fn index(&self, index: usize) -> &f32 {
|
|
||||||
&self.data[index]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl IndexMut<usize> for Float4 {
|
|
||||||
#[cfg(feature = "simd_perf")]
|
|
||||||
fn index_mut(&mut self, index: usize) -> &mut f32 {
|
|
||||||
// TODO: this might not be correct! It works, but need to make sure
|
|
||||||
// to do this in a way with proper defined behavior.
|
|
||||||
use std::mem::transmute;
|
|
||||||
let vs: &mut [f32; 4] = unsafe { transmute(&mut self.data) };
|
|
||||||
&mut vs[index]
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "simd_perf"))]
|
|
||||||
fn index_mut(&mut self, index: usize) -> &mut f32 {
|
|
||||||
&mut self.data[index]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl PartialEq for Float4 {
|
impl PartialEq for Float4 {
|
||||||
fn eq(&self, other: &Float4) -> bool {
|
fn eq(&self, other: &Float4) -> bool {
|
||||||
self.get_0() == other.get_0() && self.get_1() == other.get_1() &&
|
self.get_0() == other.get_0() && self.get_1() == other.get_1() &&
|
||||||
|
@ -389,27 +395,51 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn index() {
|
fn get() {
|
||||||
let f = Float4::new(1.0, 2.0, 3.0, 4.0);
|
let f = Float4::new(1.0, 2.0, 3.0, 4.0);
|
||||||
|
|
||||||
assert_eq!(f[0], 1.0);
|
assert_eq!(f.get_0(), 1.0);
|
||||||
assert_eq!(f[1], 2.0);
|
assert_eq!(f.get_1(), 2.0);
|
||||||
assert_eq!(f[2], 3.0);
|
assert_eq!(f.get_2(), 3.0);
|
||||||
assert_eq!(f[3], 4.0);
|
assert_eq!(f.get_3(), 4.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn index_mut() {
|
fn get_n() {
|
||||||
let mut f = Float4::new(1.0, 2.0, 3.0, 4.0);
|
let f = Float4::new(1.0, 2.0, 3.0, 4.0);
|
||||||
f[0] = 5.0;
|
|
||||||
f[1] = 6.0;
|
|
||||||
f[2] = 7.0;
|
|
||||||
f[3] = 8.0;
|
|
||||||
|
|
||||||
assert_eq!(f[0], 5.0);
|
assert_eq!(f.get_n(0), 1.0);
|
||||||
assert_eq!(f[1], 6.0);
|
assert_eq!(f.get_n(1), 2.0);
|
||||||
assert_eq!(f[2], 7.0);
|
assert_eq!(f.get_n(2), 3.0);
|
||||||
assert_eq!(f[3], 8.0);
|
assert_eq!(f.get_n(3), 4.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn set() {
|
||||||
|
let mut f = Float4::new(1.0, 2.0, 3.0, 4.0);
|
||||||
|
f.set_0(5.0);
|
||||||
|
f.set_1(6.0);
|
||||||
|
f.set_2(7.0);
|
||||||
|
f.set_3(8.0);
|
||||||
|
|
||||||
|
assert_eq!(f.get_0(), 5.0);
|
||||||
|
assert_eq!(f.get_1(), 6.0);
|
||||||
|
assert_eq!(f.get_2(), 7.0);
|
||||||
|
assert_eq!(f.get_3(), 8.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn set_n() {
|
||||||
|
let mut f = Float4::new(1.0, 2.0, 3.0, 4.0);
|
||||||
|
f.set_n(0, 5.0);
|
||||||
|
f.set_n(1, 6.0);
|
||||||
|
f.set_n(2, 7.0);
|
||||||
|
f.set_n(3, 8.0);
|
||||||
|
|
||||||
|
assert_eq!(f.get_0(), 5.0);
|
||||||
|
assert_eq!(f.get_1(), 6.0);
|
||||||
|
assert_eq!(f.get_2(), 7.0);
|
||||||
|
assert_eq!(f.get_3(), 8.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -79,11 +79,15 @@ impl LightSource for RectangleLight {
|
||||||
// Project shadow_vec back onto the light's surface
|
// Project shadow_vec back onto the light's surface
|
||||||
let arr_local = arr * *space;
|
let arr_local = arr * *space;
|
||||||
let shadow_vec_local = shadow_vec * *space;
|
let shadow_vec_local = shadow_vec * *space;
|
||||||
let shadow_vec_local = shadow_vec_local * (-arr_local[2] / shadow_vec_local[2]);
|
let shadow_vec_local = shadow_vec_local * (-arr_local.z() / shadow_vec_local.z());
|
||||||
let mut sample_point_local = arr_local + shadow_vec_local;
|
let mut sample_point_local = arr_local + shadow_vec_local;
|
||||||
sample_point_local[0] = sample_point_local[0].max(dim.0 * -0.5).min(dim.0 * 0.5);
|
{
|
||||||
sample_point_local[1] = sample_point_local[1].max(dim.1 * -0.5).min(dim.1 * 0.5);
|
let x = sample_point_local.x().max(dim.0 * -0.5).min(dim.0 * 0.5);
|
||||||
sample_point_local[2] = 0.0;
|
let y = sample_point_local.y().max(dim.1 * -0.5).min(dim.1 * 0.5);
|
||||||
|
sample_point_local.set_x(x);
|
||||||
|
sample_point_local.set_y(y);
|
||||||
|
sample_point_local.set_z(0.0);
|
||||||
|
}
|
||||||
let sample_point = sample_point_local * space_inv;
|
let sample_point = sample_point_local * space_inv;
|
||||||
let shadow_vec = sample_point - arr;
|
let shadow_vec = sample_point - arr;
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ impl LightSource for SphereLight {
|
||||||
// Sample the cone subtended by the sphere and calculate
|
// Sample the cone subtended by the sphere and calculate
|
||||||
// useful data from that.
|
// useful data from that.
|
||||||
let sample = uniform_sample_cone(u, v, cos_theta_max).normalized();
|
let sample = uniform_sample_cone(u, v, cos_theta_max).normalized();
|
||||||
let cos_theta: f64 = sample[2] as f64;
|
let cos_theta: f64 = sample.z() as f64;
|
||||||
let cos_theta2: f64 = cos_theta * cos_theta;
|
let cos_theta2: f64 = cos_theta * cos_theta;
|
||||||
let sin_theta2: f64 = (1.0 - cos_theta2).max(0.0);
|
let sin_theta2: f64 = (1.0 - cos_theta2).max(0.0);
|
||||||
let sin_theta: f64 = sin_theta2.sqrt();
|
let sin_theta: f64 = sin_theta2.sqrt();
|
||||||
|
@ -90,7 +90,7 @@ impl LightSource for SphereLight {
|
||||||
(d - (cos_a * radius)) as f32);
|
(d - (cos_a * radius)) as f32);
|
||||||
|
|
||||||
// Calculate the final values and return everything.
|
// Calculate the final values and return everything.
|
||||||
let shadow_vec = (x * sample[0]) + (y * sample[1]) + (z * sample[2]);
|
let shadow_vec = (x * sample.x()) + (y * sample.y()) + (z * sample.z());
|
||||||
let pdf = uniform_sample_cone_pdf(cos_theta_max);
|
let pdf = uniform_sample_cone_pdf(cos_theta_max);
|
||||||
let spectral_sample = (col * surface_area_inv as f32).to_spectral_sample(wavelength);
|
let spectral_sample = (col * surface_area_inv as f32).to_spectral_sample(wavelength);
|
||||||
return (spectral_sample, shadow_vec, pdf as f32);
|
return (spectral_sample, shadow_vec, pdf as f32);
|
||||||
|
|
|
@ -59,9 +59,9 @@ impl Matrix4x4 {
|
||||||
|
|
||||||
pub fn from_location(loc: Point) -> Matrix4x4 {
|
pub fn from_location(loc: Point) -> Matrix4x4 {
|
||||||
Matrix4x4 {
|
Matrix4x4 {
|
||||||
values: [Float4::new(1.0, 0.0, 0.0, loc[0]),
|
values: [Float4::new(1.0, 0.0, 0.0, loc.x()),
|
||||||
Float4::new(0.0, 1.0, 0.0, loc[1]),
|
Float4::new(0.0, 1.0, 0.0, loc.y()),
|
||||||
Float4::new(0.0, 0.0, 1.0, loc[2]),
|
Float4::new(0.0, 0.0, 1.0, loc.z()),
|
||||||
Float4::new(0.0, 0.0, 0.0, 1.0)],
|
Float4::new(0.0, 0.0, 0.0, 1.0)],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,8 +79,8 @@ impl Matrix4x4 {
|
||||||
// http://floating-point-gui.de/errors/comparison/
|
// http://floating-point-gui.de/errors/comparison/
|
||||||
// It might be worth breaking this out into a separate funcion,
|
// It might be worth breaking this out into a separate funcion,
|
||||||
// but I'm not entirely sure where to put it.
|
// but I'm not entirely sure where to put it.
|
||||||
let a = self[y][x];
|
let a = self[y].get_n(x);
|
||||||
let b = other[y][x];
|
let b = other[y].get_n(x);
|
||||||
let aabs = a.abs();
|
let aabs = a.abs();
|
||||||
let babs = b.abs();
|
let babs = b.abs();
|
||||||
let diff = (a - b).abs();
|
let diff = (a - b).abs();
|
||||||
|
@ -102,10 +102,22 @@ impl Matrix4x4 {
|
||||||
pub fn transposed(&self) -> Matrix4x4 {
|
pub fn transposed(&self) -> Matrix4x4 {
|
||||||
Matrix4x4 {
|
Matrix4x4 {
|
||||||
values: {
|
values: {
|
||||||
[Float4::new(self[0][0], self[1][0], self[2][0], self[3][0]),
|
[Float4::new(self[0].get_0(),
|
||||||
Float4::new(self[0][1], self[1][1], self[2][1], self[3][1]),
|
self[1].get_0(),
|
||||||
Float4::new(self[0][2], self[1][2], self[2][2], self[3][2]),
|
self[2].get_0(),
|
||||||
Float4::new(self[0][3], self[1][3], self[2][3], self[3][3])]
|
self[3].get_0()),
|
||||||
|
Float4::new(self[0].get_1(),
|
||||||
|
self[1].get_1(),
|
||||||
|
self[2].get_1(),
|
||||||
|
self[3].get_1()),
|
||||||
|
Float4::new(self[0].get_2(),
|
||||||
|
self[1].get_2(),
|
||||||
|
self[2].get_2(),
|
||||||
|
self[3].get_2()),
|
||||||
|
Float4::new(self[0].get_3(),
|
||||||
|
self[1].get_3(),
|
||||||
|
self[2].get_3(),
|
||||||
|
self[3].get_3())]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,19 +125,19 @@ impl Matrix4x4 {
|
||||||
|
|
||||||
/// Returns the inverse of the Matrix
|
/// Returns the inverse of the Matrix
|
||||||
pub fn inverse(&self) -> Matrix4x4 {
|
pub fn inverse(&self) -> Matrix4x4 {
|
||||||
let s0 = (self[0][0] * self[1][1]) - (self[1][0] * self[0][1]);
|
let s0 = (self[0].get_0() * self[1].get_1()) - (self[1].get_0() * self[0].get_1());
|
||||||
let s1 = (self[0][0] * self[1][2]) - (self[1][0] * self[0][2]);
|
let s1 = (self[0].get_0() * self[1].get_2()) - (self[1].get_0() * self[0].get_2());
|
||||||
let s2 = (self[0][0] * self[1][3]) - (self[1][0] * self[0][3]);
|
let s2 = (self[0].get_0() * self[1].get_3()) - (self[1].get_0() * self[0].get_3());
|
||||||
let s3 = (self[0][1] * self[1][2]) - (self[1][1] * self[0][2]);
|
let s3 = (self[0].get_1() * self[1].get_2()) - (self[1].get_1() * self[0].get_2());
|
||||||
let s4 = (self[0][1] * self[1][3]) - (self[1][1] * self[0][3]);
|
let s4 = (self[0].get_1() * self[1].get_3()) - (self[1].get_1() * self[0].get_3());
|
||||||
let s5 = (self[0][2] * self[1][3]) - (self[1][2] * self[0][3]);
|
let s5 = (self[0].get_2() * self[1].get_3()) - (self[1].get_2() * self[0].get_3());
|
||||||
|
|
||||||
let c5 = (self[2][2] * self[3][3]) - (self[3][2] * self[2][3]);
|
let c5 = (self[2].get_2() * self[3].get_3()) - (self[3].get_2() * self[2].get_3());
|
||||||
let c4 = (self[2][1] * self[3][3]) - (self[3][1] * self[2][3]);
|
let c4 = (self[2].get_1() * self[3].get_3()) - (self[3].get_1() * self[2].get_3());
|
||||||
let c3 = (self[2][1] * self[3][2]) - (self[3][1] * self[2][2]);
|
let c3 = (self[2].get_1() * self[3].get_2()) - (self[3].get_1() * self[2].get_2());
|
||||||
let c2 = (self[2][0] * self[3][3]) - (self[3][0] * self[2][3]);
|
let c2 = (self[2].get_0() * self[3].get_3()) - (self[3].get_0() * self[2].get_3());
|
||||||
let c1 = (self[2][0] * self[3][2]) - (self[3][0] * self[2][2]);
|
let c1 = (self[2].get_0() * self[3].get_2()) - (self[3].get_0() * self[2].get_2());
|
||||||
let c0 = (self[2][0] * self[3][1]) - (self[3][0] * self[2][1]);
|
let c0 = (self[2].get_0() * self[3].get_1()) - (self[3].get_0() * self[2].get_1());
|
||||||
|
|
||||||
// TODO: handle 0.0 determinant
|
// TODO: handle 0.0 determinant
|
||||||
let det = (s0 * c5) - (s1 * c4) + (s2 * c3) + (s3 * c2) - (s4 * c1) + (s5 * c0);
|
let det = (s0 * c5) - (s1 * c4) + (s2 * c3) + (s3 * c2) - (s4 * c1) + (s5 * c0);
|
||||||
|
@ -133,25 +145,41 @@ impl Matrix4x4 {
|
||||||
|
|
||||||
Matrix4x4 {
|
Matrix4x4 {
|
||||||
values: {
|
values: {
|
||||||
[Float4::new(((self[1][1] * c5) - (self[1][2] * c4) + (self[1][3] * c3)) * invdet,
|
[Float4::new(((self[1].get_1() * c5) - (self[1].get_2() * c4) +
|
||||||
((-self[0][1] * c5) + (self[0][2] * c4) - (self[0][3] * c3)) * invdet,
|
(self[1].get_3() * c3)) * invdet,
|
||||||
((self[3][1] * s5) - (self[3][2] * s4) + (self[3][3] * s3)) * invdet,
|
((-self[0].get_1() * c5) + (self[0].get_2() * c4) -
|
||||||
((-self[2][1] * s5) + (self[2][2] * s4) - (self[2][3] * s3)) * invdet),
|
(self[0].get_3() * c3)) * invdet,
|
||||||
|
((self[3].get_1() * s5) - (self[3].get_2() * s4) +
|
||||||
|
(self[3].get_3() * s3)) * invdet,
|
||||||
|
((-self[2].get_1() * s5) + (self[2].get_2() * s4) -
|
||||||
|
(self[2].get_3() * s3)) * invdet),
|
||||||
|
|
||||||
Float4::new(((-self[1][0] * c5) + (self[1][2] * c2) - (self[1][3] * c1)) * invdet,
|
Float4::new(((-self[1].get_0() * c5) + (self[1].get_2() * c2) -
|
||||||
((self[0][0] * c5) - (self[0][2] * c2) + (self[0][3] * c1)) * invdet,
|
(self[1].get_3() * c1)) * invdet,
|
||||||
((-self[3][0] * s5) + (self[3][2] * s2) - (self[3][3] * s1)) * invdet,
|
((self[0].get_0() * c5) - (self[0].get_2() * c2) +
|
||||||
((self[2][0] * s5) - (self[2][2] * s2) + (self[2][3] * s1)) * invdet),
|
(self[0].get_3() * c1)) * invdet,
|
||||||
|
((-self[3].get_0() * s5) + (self[3].get_2() * s2) -
|
||||||
|
(self[3].get_3() * s1)) * invdet,
|
||||||
|
((self[2].get_0() * s5) - (self[2].get_2() * s2) +
|
||||||
|
(self[2].get_3() * s1)) * invdet),
|
||||||
|
|
||||||
Float4::new(((self[1][0] * c4) - (self[1][1] * c2) + (self[1][3] * c0)) * invdet,
|
Float4::new(((self[1].get_0() * c4) - (self[1].get_1() * c2) +
|
||||||
((-self[0][0] * c4) + (self[0][1] * c2) - (self[0][3] * c0)) * invdet,
|
(self[1].get_3() * c0)) * invdet,
|
||||||
((self[3][0] * s4) - (self[3][1] * s2) + (self[3][3] * s0)) * invdet,
|
((-self[0].get_0() * c4) + (self[0].get_1() * c2) -
|
||||||
((-self[2][0] * s4) + (self[2][1] * s2) - (self[2][3] * s0)) * invdet),
|
(self[0].get_3() * c0)) * invdet,
|
||||||
|
((self[3].get_0() * s4) - (self[3].get_1() * s2) +
|
||||||
|
(self[3].get_3() * s0)) * invdet,
|
||||||
|
((-self[2].get_0() * s4) + (self[2].get_1() * s2) -
|
||||||
|
(self[2].get_3() * s0)) * invdet),
|
||||||
|
|
||||||
Float4::new(((-self[1][0] * c3) + (self[1][1] * c1) - (self[1][2] * c0)) * invdet,
|
Float4::new(((-self[1].get_0() * c3) + (self[1].get_1() * c1) -
|
||||||
((self[0][0] * c3) - (self[0][1] * c1) + (self[0][2] * c0)) * invdet,
|
(self[1].get_2() * c0)) * invdet,
|
||||||
((-self[3][0] * s3) + (self[3][1] * s1) - (self[3][2] * s0)) * invdet,
|
((self[0].get_0() * c3) - (self[0].get_1() * c1) +
|
||||||
((self[2][0] * s3) - (self[2][1] * s1) + (self[2][2] * s0)) * invdet)]
|
(self[0].get_2() * c0)) * invdet,
|
||||||
|
((-self[3].get_0() * s3) + (self[3].get_1() * s1) -
|
||||||
|
(self[3].get_2() * s0)) * invdet,
|
||||||
|
((self[2].get_0() * s3) - (self[2].get_1() * s1) +
|
||||||
|
(self[2].get_2() * s0)) * invdet)]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,7 +208,7 @@ impl PartialEq for Matrix4x4 {
|
||||||
|
|
||||||
for y in 0..4 {
|
for y in 0..4 {
|
||||||
for x in 0..4 {
|
for x in 0..4 {
|
||||||
result = result && (self[y][x] == other[y][x]);
|
result = result && (self[y].get_n(x) == other[y].get_n(x));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,25 +252,10 @@ impl Lerp for Matrix4x4 {
|
||||||
fn lerp(self, other: Matrix4x4, alpha: f32) -> Matrix4x4 {
|
fn lerp(self, other: Matrix4x4, alpha: f32) -> Matrix4x4 {
|
||||||
let alpha_minus = 1.0 - alpha;
|
let alpha_minus = 1.0 - alpha;
|
||||||
Matrix4x4 {
|
Matrix4x4 {
|
||||||
values: [Float4::new((self[0][0] * alpha_minus) + (other[0][0] * alpha),
|
values: [(self[0] * alpha_minus) + (other[0] * alpha),
|
||||||
(self[0][1] * alpha_minus) + (other[0][1] * alpha),
|
(self[1] * alpha_minus) + (other[1] * alpha),
|
||||||
(self[0][2] * alpha_minus) + (other[0][2] * alpha),
|
(self[2] * alpha_minus) + (other[2] * alpha),
|
||||||
(self[0][3] * alpha_minus) + (other[0][3] * alpha)),
|
(self[3] * alpha_minus) + (other[3] * alpha)],
|
||||||
|
|
||||||
Float4::new((self[1][0] * alpha_minus) + (other[1][0] * alpha),
|
|
||||||
(self[1][1] * alpha_minus) + (other[1][1] * alpha),
|
|
||||||
(self[1][2] * alpha_minus) + (other[1][2] * alpha),
|
|
||||||
(self[1][3] * alpha_minus) + (other[1][3] * alpha)),
|
|
||||||
|
|
||||||
Float4::new((self[2][0] * alpha_minus) + (other[2][0] * alpha),
|
|
||||||
(self[2][1] * alpha_minus) + (other[2][1] * alpha),
|
|
||||||
(self[2][2] * alpha_minus) + (other[2][2] * alpha),
|
|
||||||
(self[2][3] * alpha_minus) + (other[2][3] * alpha)),
|
|
||||||
|
|
||||||
Float4::new((self[3][0] * alpha_minus) + (other[3][0] * alpha),
|
|
||||||
(self[3][1] * alpha_minus) + (other[3][1] * alpha),
|
|
||||||
(self[3][2] * alpha_minus) + (other[3][2] * alpha),
|
|
||||||
(self[3][3] * alpha_minus) + (other[3][3] * alpha))],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,12 +134,12 @@ pub fn log2_64(value: u64) -> u64 {
|
||||||
|
|
||||||
/// Creates a coordinate system from a single vector.
|
/// Creates a coordinate system from a single vector.
|
||||||
pub fn coordinate_system_from_vector(v: Vector) -> (Vector, Vector, Vector) {
|
pub fn coordinate_system_from_vector(v: Vector) -> (Vector, Vector, Vector) {
|
||||||
let v2 = if v[0].abs() > v[1].abs() {
|
let v2 = if v.x().abs() > v.y().abs() {
|
||||||
let invlen = 1.0 / ((v[0] * v[0]) + (v[2] * v[2])).sqrt();
|
let invlen = 1.0 / ((v.x() * v.x()) + (v.z() * v.z())).sqrt();
|
||||||
Vector::new(-v[2] * invlen, 0.0, v[0] * invlen)
|
Vector::new(-v.z() * invlen, 0.0, v.x() * invlen)
|
||||||
} else {
|
} else {
|
||||||
let invlen = 1.0 / ((v[1] * v[1]) + (v[2] * v[2])).sqrt();
|
let invlen = 1.0 / ((v.y() * v.y()) + (v.z() * v.z())).sqrt();
|
||||||
Vector::new(0.0, v[2] * invlen, -v[1] * invlen)
|
Vector::new(0.0, v.z() * invlen, -v.y() * invlen)
|
||||||
};
|
};
|
||||||
|
|
||||||
let v3 = cross(v, v2);
|
let v3 = cross(v, v2);
|
||||||
|
@ -164,7 +164,7 @@ pub fn zup_to_vec(from: Vector, toz: Vector) -> Vector {
|
||||||
// Use simple linear algebra to convert the "from"
|
// Use simple linear algebra to convert the "from"
|
||||||
// vector to a space composed of tox, toy, and toz
|
// vector to a space composed of tox, toy, and toz
|
||||||
// as the x, y, and z axes.
|
// as the x, y, and z axes.
|
||||||
(tox * from[0]) + (toy * from[1]) + (toz * from[2])
|
(tox * from.x()) + (toy * from.y()) + (toz * from.z())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The logit function, scaled to approximate the probit function.
|
/// The logit function, scaled to approximate the probit function.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::ops::{Index, IndexMut, Add, Sub, Mul, Div, Neg};
|
use std::ops::{Add, Sub, Mul, Div, Neg};
|
||||||
use std::cmp::PartialEq;
|
use std::cmp::PartialEq;
|
||||||
|
|
||||||
use lerp::Lerp;
|
use lerp::Lerp;
|
||||||
|
@ -33,26 +33,40 @@ impl Normal {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_vector(self) -> Vector {
|
pub fn into_vector(self) -> Vector {
|
||||||
Vector::new(self.co[0], self.co[1], self.co[2])
|
Vector::new(self.co.get_0(), self.co.get_1(), self.co.get_2())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_n(&self, n: usize) -> f32 {
|
||||||
|
match n {
|
||||||
|
0 => self.x(),
|
||||||
|
1 => self.y(),
|
||||||
|
2 => self.z(),
|
||||||
|
_ => panic!("Attempt to access dimension beyond z."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn x(&self) -> f32 {
|
||||||
impl Index<usize> for Normal {
|
self.co.get_0()
|
||||||
type Output = f32;
|
|
||||||
|
|
||||||
fn index(&self, index: usize) -> &f32 {
|
|
||||||
debug_assert!(index < 3);
|
|
||||||
|
|
||||||
&self.co[index]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndexMut<usize> for Normal {
|
pub fn y(&self) -> f32 {
|
||||||
fn index_mut(&mut self, index: usize) -> &mut f32 {
|
self.co.get_1()
|
||||||
debug_assert!(index < 3);
|
}
|
||||||
|
|
||||||
&mut self.co[index]
|
pub fn z(&self) -> f32 {
|
||||||
|
self.co.get_2()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_x(&mut self, x: f32) {
|
||||||
|
self.co.set_0(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_y(&mut self, y: f32) {
|
||||||
|
self.co.set_1(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_z(&mut self, z: f32) {
|
||||||
|
self.co.set_2(z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,9 +110,9 @@ impl Mul<Matrix4x4> for Normal {
|
||||||
fn mul(self, other: Matrix4x4) -> Normal {
|
fn mul(self, other: Matrix4x4) -> Normal {
|
||||||
let mat = other.inverse().transposed();
|
let mat = other.inverse().transposed();
|
||||||
Normal {
|
Normal {
|
||||||
co: Float4::new((self[0] * mat[0][0]) + (self[1] * mat[0][1]) + (self[2] * mat[0][2]),
|
co: Float4::new((self.co * mat[0]).h_sum(),
|
||||||
(self[0] * mat[1][0]) + (self[1] * mat[1][1]) + (self[2] * mat[1][2]),
|
(self.co * mat[1]).h_sum(),
|
||||||
(self[0] * mat[2][0]) + (self[1] * mat[2][1]) + (self[2] * mat[2][2]),
|
(self.co * mat[2]).h_sum(),
|
||||||
0.0),
|
0.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,9 +154,12 @@ impl DotProduct for Normal {
|
||||||
impl CrossProduct for Normal {
|
impl CrossProduct for Normal {
|
||||||
fn cross(self, other: Normal) -> Normal {
|
fn cross(self, other: Normal) -> Normal {
|
||||||
Normal {
|
Normal {
|
||||||
co: Float4::new((self[1] * other[2]) - (self[2] * other[1]),
|
co: Float4::new((self.co.get_1() * other.co.get_2()) -
|
||||||
(self[2] * other[0]) - (self[0] * other[2]),
|
(self.co.get_2() * other.co.get_1()),
|
||||||
(self[0] * other[1]) - (self[1] * other[0]),
|
(self.co.get_2() * other.co.get_0()) -
|
||||||
|
(self.co.get_0() * other.co.get_2()),
|
||||||
|
(self.co.get_0() * other.co.get_1()) -
|
||||||
|
(self.co.get_1() * other.co.get_0()),
|
||||||
0.0),
|
0.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -231,9 +248,9 @@ mod tests {
|
||||||
let n1 = Normal::new(1.0, 2.0, 3.0);
|
let n1 = Normal::new(1.0, 2.0, 3.0);
|
||||||
let n2 = Normal::new(0.2672612419124244, 0.5345224838248488, 0.8017837257372732);
|
let n2 = Normal::new(0.2672612419124244, 0.5345224838248488, 0.8017837257372732);
|
||||||
let n3 = n1.normalized();
|
let n3 = n1.normalized();
|
||||||
assert!((n3[0] - n2[0]).abs() < 0.000001);
|
assert!((n3.x() - n2.x()).abs() < 0.000001);
|
||||||
assert!((n3[1] - n2[1]).abs() < 0.000001);
|
assert!((n3.y() - n2.y()).abs() < 0.000001);
|
||||||
assert!((n3[2] - n2[2]).abs() < 0.000001);
|
assert!((n3.z() - n2.z()).abs() < 0.000001);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::ops::{Index, IndexMut, Add, Sub, Mul};
|
use std::ops::{Add, Sub, Mul};
|
||||||
use std::cmp::PartialEq;
|
use std::cmp::PartialEq;
|
||||||
|
|
||||||
use lerp::Lerp;
|
use lerp::Lerp;
|
||||||
|
@ -23,7 +23,7 @@ impl Point {
|
||||||
/// Returns the point in standardized coordinates, where the
|
/// Returns the point in standardized coordinates, where the
|
||||||
/// fourth homogeneous component has been normalized to 1.0.
|
/// fourth homogeneous component has been normalized to 1.0.
|
||||||
pub fn norm(&self) -> Point {
|
pub fn norm(&self) -> Point {
|
||||||
Point { co: self.co / self.co[3] }
|
Point { co: self.co / self.co.get_3() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn min(&self, other: Point) -> Point {
|
pub fn min(&self, other: Point) -> Point {
|
||||||
|
@ -41,26 +41,40 @@ impl Point {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_vector(self) -> Vector {
|
pub fn into_vector(self) -> Vector {
|
||||||
Vector::new(self[0], self[1], self[2])
|
Vector::new(self.co.get_0(), self.co.get_1(), self.co.get_2())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_n(&self, n: usize) -> f32 {
|
||||||
|
match n {
|
||||||
|
0 => self.x(),
|
||||||
|
1 => self.y(),
|
||||||
|
2 => self.z(),
|
||||||
|
_ => panic!("Attempt to access dimension beyond z."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn x(&self) -> f32 {
|
||||||
impl Index<usize> for Point {
|
self.co.get_0()
|
||||||
type Output = f32;
|
|
||||||
|
|
||||||
fn index(&self, index: usize) -> &f32 {
|
|
||||||
debug_assert!(index < 3);
|
|
||||||
|
|
||||||
&self.co[index]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndexMut<usize> for Point {
|
pub fn y(&self) -> f32 {
|
||||||
fn index_mut(&mut self, index: usize) -> &mut f32 {
|
self.co.get_1()
|
||||||
debug_assert!(index < 3);
|
}
|
||||||
|
|
||||||
&mut self.co[index]
|
pub fn z(&self) -> f32 {
|
||||||
|
self.co.get_2()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_x(&mut self, x: f32) {
|
||||||
|
self.co.set_0(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_y(&mut self, y: f32) {
|
||||||
|
self.co.set_1(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_z(&mut self, z: f32) {
|
||||||
|
self.co.set_2(z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +144,7 @@ mod tests {
|
||||||
fn norm() {
|
fn norm() {
|
||||||
let mut p1 = Point::new(1.0, 2.0, 3.0);
|
let mut p1 = Point::new(1.0, 2.0, 3.0);
|
||||||
let p2 = Point::new(2.0, 4.0, 6.0);
|
let p2 = Point::new(2.0, 4.0, 6.0);
|
||||||
p1.co[3] = 0.5;
|
p1.co.set_3(0.5);
|
||||||
|
|
||||||
assert_eq!(p2, p1.norm());
|
assert_eq!(p2, p1.norm());
|
||||||
}
|
}
|
||||||
|
@ -196,7 +210,7 @@ mod tests {
|
||||||
1.0,
|
1.0,
|
||||||
5.0);
|
5.0);
|
||||||
let mut pm = Point::new(15.5, 54.0, 70.0);
|
let mut pm = Point::new(15.5, 54.0, 70.0);
|
||||||
pm.co[3] = 18.5;
|
pm.co.set_3(18.5);
|
||||||
assert_eq!(p * m, pm);
|
assert_eq!(p * m, pm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::ops::{Index, IndexMut, Add, Sub, Mul, Div, Neg};
|
use std::ops::{Add, Sub, Mul, Div, Neg};
|
||||||
use std::cmp::PartialEq;
|
use std::cmp::PartialEq;
|
||||||
|
|
||||||
use lerp::Lerp;
|
use lerp::Lerp;
|
||||||
|
@ -33,26 +33,40 @@ impl Vector {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_normal(self) -> Normal {
|
pub fn into_normal(self) -> Normal {
|
||||||
Normal::new(self.co[0], self.co[1], self.co[2])
|
Normal::new(self.x(), self.y(), self.z())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_n(&self, n: usize) -> f32 {
|
||||||
|
match n {
|
||||||
|
0 => self.x(),
|
||||||
|
1 => self.y(),
|
||||||
|
2 => self.z(),
|
||||||
|
_ => panic!("Attempt to access dimension beyond z."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn x(&self) -> f32 {
|
||||||
impl Index<usize> for Vector {
|
self.co.get_0()
|
||||||
type Output = f32;
|
|
||||||
|
|
||||||
fn index(&self, index: usize) -> &f32 {
|
|
||||||
debug_assert!(index < 3);
|
|
||||||
|
|
||||||
&self.co[index]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndexMut<usize> for Vector {
|
pub fn y(&self) -> f32 {
|
||||||
fn index_mut(&mut self, index: usize) -> &mut f32 {
|
self.co.get_1()
|
||||||
debug_assert!(index < 3);
|
}
|
||||||
|
|
||||||
&mut self.co[index]
|
pub fn z(&self) -> f32 {
|
||||||
|
self.co.get_2()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_x(&mut self, x: f32) {
|
||||||
|
self.co.set_0(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_y(&mut self, y: f32) {
|
||||||
|
self.co.set_1(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_z(&mut self, z: f32) {
|
||||||
|
self.co.set_2(z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,9 +154,12 @@ impl DotProduct for Vector {
|
||||||
impl CrossProduct for Vector {
|
impl CrossProduct for Vector {
|
||||||
fn cross(self, other: Vector) -> Vector {
|
fn cross(self, other: Vector) -> Vector {
|
||||||
Vector {
|
Vector {
|
||||||
co: Float4::new((self[1] * other[2]) - (self[2] * other[1]),
|
co: Float4::new((self.co.get_1() * other.co.get_2()) -
|
||||||
(self[2] * other[0]) - (self[0] * other[2]),
|
(self.co.get_2() * other.co.get_1()),
|
||||||
(self[0] * other[1]) - (self[1] * other[0]),
|
(self.co.get_2() * other.co.get_0()) -
|
||||||
|
(self.co.get_0() * other.co.get_2()),
|
||||||
|
(self.co.get_0() * other.co.get_1()) -
|
||||||
|
(self.co.get_1() * other.co.get_0()),
|
||||||
0.0),
|
0.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,7 +219,7 @@ mod tests {
|
||||||
15.0,
|
15.0,
|
||||||
3.0);
|
3.0);
|
||||||
let mut vm = Vector::new(14.0, 46.0, 58.0);
|
let mut vm = Vector::new(14.0, 46.0, 58.0);
|
||||||
vm.co[3] = 90.5;
|
vm.co.set_3(90.5);
|
||||||
assert_eq!(v * m, vm);
|
assert_eq!(v * m, vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,9 +272,9 @@ mod tests {
|
||||||
let v1 = Vector::new(1.0, 2.0, 3.0);
|
let v1 = Vector::new(1.0, 2.0, 3.0);
|
||||||
let v2 = Vector::new(0.2672612419124244, 0.5345224838248488, 0.8017837257372732);
|
let v2 = Vector::new(0.2672612419124244, 0.5345224838248488, 0.8017837257372732);
|
||||||
let v3 = v1.normalized();
|
let v3 = v1.normalized();
|
||||||
assert!((v3[0] - v2[0]).abs() < 0.000001);
|
assert!((v3.x() - v2.x()).abs() < 0.000001);
|
||||||
assert!((v3[1] - v2[1]).abs() < 0.000001);
|
assert!((v3.y() - v2.y()).abs() < 0.000001);
|
||||||
assert!((v3[2] - v2[2]).abs() < 0.000001);
|
assert!((v3.z() - v2.z()).abs() < 0.000001);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -138,7 +138,6 @@ fn take_decimal_real(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use nom::IResult;
|
|
||||||
use nom::IResult::*;
|
use nom::IResult::*;
|
||||||
use super::take_decimal_real;
|
use super::take_decimal_real;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -650,7 +650,7 @@ mod tests {
|
||||||
"#)
|
"#)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut i = dt.iter_children_with_type("A");
|
let i = dt.iter_children_with_type("A");
|
||||||
assert_eq!(i.count(), 3);
|
assert_eq!(i.count(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,7 +665,7 @@ mod tests {
|
||||||
"#)
|
"#)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut i = dt.iter_internal_children_with_type("A");
|
let i = dt.iter_internal_children_with_type("A");
|
||||||
assert_eq!(i.count(), 2);
|
assert_eq!(i.count(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -680,7 +680,7 @@ mod tests {
|
||||||
"#)
|
"#)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut i = dt.iter_leaf_children_with_type("A");
|
let i = dt.iter_leaf_children_with_type("A");
|
||||||
assert_eq!(i.count(), 2);
|
assert_eq!(i.count(), 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,7 +210,7 @@ impl SurfaceClosure for LambertClosure {
|
||||||
// Generate a random ray direction in the hemisphere
|
// Generate a random ray direction in the hemisphere
|
||||||
// of the surface.
|
// of the surface.
|
||||||
let dir = cosine_sample_hemisphere(uv.0, uv.1);
|
let dir = cosine_sample_hemisphere(uv.0, uv.1);
|
||||||
let pdf = dir[2] * INV_PI;
|
let pdf = dir.z() * INV_PI;
|
||||||
let out = zup_to_vec(dir, nn);
|
let out = zup_to_vec(dir, nn);
|
||||||
let filter = self.evaluate(inc, out, nor, wavelength);
|
let filter = self.evaluate(inc, out, nor, wavelength);
|
||||||
|
|
||||||
|
|
|
@ -154,15 +154,15 @@ impl<'a> TracerInner<'a> {
|
||||||
fn split_rays_by_direction(rays: &mut [AccelRay]) -> [&mut [AccelRay]; 8] {
|
fn split_rays_by_direction(rays: &mut [AccelRay]) -> [&mut [AccelRay]; 8] {
|
||||||
// | | | | | | | | |
|
// | | | | | | | | |
|
||||||
// s1 s2 s3 s4 s5 s6 s7
|
// s1 s2 s3 s4 s5 s6 s7
|
||||||
let s4 = partition(&mut rays[..], |r| r.dir_inv[0].is_sign_positive());
|
let s4 = partition(&mut rays[..], |r| r.dir_inv.x().is_sign_positive());
|
||||||
|
|
||||||
let s2 = partition(&mut rays[..s4], |r| r.dir_inv[1].is_sign_positive());
|
let s2 = partition(&mut rays[..s4], |r| r.dir_inv.y().is_sign_positive());
|
||||||
let s6 = s4 + partition(&mut rays[s4..], |r| r.dir_inv[1].is_sign_positive());
|
let s6 = s4 + partition(&mut rays[s4..], |r| r.dir_inv.y().is_sign_positive());
|
||||||
|
|
||||||
let s1 = partition(&mut rays[..s2], |r| r.dir_inv[2].is_sign_positive());
|
let s1 = partition(&mut rays[..s2], |r| r.dir_inv.z().is_sign_positive());
|
||||||
let s3 = s2 + partition(&mut rays[s2..s4], |r| r.dir_inv[2].is_sign_positive());
|
let s3 = s2 + partition(&mut rays[s2..s4], |r| r.dir_inv.z().is_sign_positive());
|
||||||
let s5 = s4 + partition(&mut rays[s4..s6], |r| r.dir_inv[2].is_sign_positive());
|
let s5 = s4 + partition(&mut rays[s4..s6], |r| r.dir_inv.z().is_sign_positive());
|
||||||
let s7 = s6 + partition(&mut rays[s6..], |r| r.dir_inv[2].is_sign_positive());
|
let s7 = s6 + partition(&mut rays[s6..], |r| r.dir_inv.z().is_sign_positive());
|
||||||
|
|
||||||
let (rest, rs7) = rays.split_at_mut(s7);
|
let (rest, rs7) = rays.split_at_mut(s7);
|
||||||
let (rest, rs6) = rest.split_at_mut(s6);
|
let (rest, rs6) = rest.split_at_mut(s6);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user