pbrt_r3/core/geometry/
misc.rs

1use 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}