pbrt_r3/core/geometry/
misc.rs1use crate::core::base::*;
2use crate::core::misc::*;
3
4#[inline]
5pub fn offset_ray_origin(p: &Point3f, p_error: &Vector3f, n: &Normal3f, w: &Vector3f) -> Point3f {
6 let d = Vector3f::dot(&n.abs(), p_error);
7
8 let mut offset = d * n.clone();
9 if Vector3f::dot(w, n) < 0.0 {
10 offset = -offset;
11 }
12 let po = *p + offset;
13 let mut a = [po.x, po.y, po.z];
14
15 for i in 0..3 {
16 if offset[i] > 0.0 {
17 a[i] = next_float_up(a[i]);
18 } else if offset[i] < 0.0 {
19 a[i] = next_float_down(a[i]);
20 }
21 }
22 return Point3f::new(a[0], a[1], a[2]);
23}
24
25#[inline]
26pub fn face_forward(n: &Vector3f, v: &Vector3f) -> Vector3f {
27 if Vector3f::dot(n, v) < 0.0 {
28 return *n * -1.0;
29 } else {
30 return *n;
31 }
32}
33
34#[inline]
35pub fn max_dimension(v: &Vector3f) -> i32 {
36 if v.x > v.y {
37 if v.x > v.z {
38 return 0;
39 } else {
40 return 2;
41 }
42 } else {
43 if v.y > v.z {
44 return 1;
45 } else {
46 return 2;
47 }
48 }
49}
50
51#[inline]
52pub fn permute(v: &Vector3f, x: usize, y: usize, z: usize) -> Vector3f {
53 return Vector3f::new(v[x], v[y], v[z]);
54}
55
56#[inline]
57pub fn max_component(v: &Vector3f) -> Float {
58 return Float::max(v.x, Float::max(v.y, v.z));
59}
60
61#[inline]
62pub fn coordinate_system(v1: &Vector3f) -> (Vector3f, Vector3f) {
63 let v2 = if Float::abs(v1.x) > Float::abs(v1.y) {
64 Vector3f::new(-v1.z, 0.0, v1.x) / Float::sqrt(v1.x * v1.x + v1.z * v1.z)
65 } else {
66 Vector3f::new(0.0, v1.z, -v1.y) / Float::sqrt(v1.y * v1.y + v1.z * v1.z)
67 };
68 let v3 = Vector3f::cross(v1, &v2).normalize();
69 return (v2, v3);
70}
71
72#[inline]
73pub fn spherical_direction(sin_theta: Float, cos_theta: Float, phi: Float) -> Vector3f {
74 return Vector3f::new(
75 sin_theta * Float::cos(phi),
76 sin_theta * Float::sin(phi),
77 cos_theta,
78 );
79}
80
81#[inline]
82pub fn spherical_direction_axes(
83 sin_theta: Float,
84 cos_theta: Float,
85 phi: Float,
86 x: &Vector3f,
87 y: &Vector3f,
88 z: &Vector3f,
89) -> Vector3f {
90 return (sin_theta * Float::cos(phi) * *x)
91 + (sin_theta * Float::sin(phi) * *y)
92 + (cos_theta * *z);
93}
94
95#[inline]
96pub fn spherical_theta(v: &Vector3f) -> Float {
97 return Float::acos(Float::clamp(v.z, -1.0, 1.0));
98}
99
100#[inline]
101pub fn spherical_phi(v: &Vector3f) -> Float {
102 let p = Float::atan2(v.y, v.x);
103 return if p < 0.0 { p + 2.0 * PI } else { p };
104}