vox_geometry_rust/
samplers.rs

1/*
2 * // Copyright (c) 2021 Feng Yang
3 * //
4 * // I am making my contributions/submissions to this project solely in my
5 * // personal capacity and am not conveying any rights to any intellectual
6 * // property of any third parties.
7 */
8
9use crate::vector3::Vector3D;
10use crate::vector2::Vector2D;
11
12/// Returns randomly sampled direction within a cone.
13///
14/// For a given cone, defined by axis and angle, this function returns a sampled
15/// direction vector within the cone.
16/// - Parameters:
17///   - u1: First random sample.
18///   - u2: Second random sample.
19///   - axis: The axis of the cone.
20///   - angle: The angle of the cone.
21/// - Returns: Sampled direction vector.
22pub fn uniform_sample_cone(u1: f64, u2: f64,
23                           axis: &Vector3D,
24                           angle: f64) -> Vector3D {
25    let cos_angle_2 = f64::cos(angle / 2.0);
26    let y: f64 = 1.0 - (1.0 - cos_angle_2) * u1;
27    let r = f64::sqrt(f64::max(0.0, 1.0 - y * y));
28    let phi = crate::constants::K_TWO_PI_D * u2;
29    let x = r * f64::cos(phi);
30    let z = r * f64::sin(phi);
31    let ts = axis.tangential();
32
33    let result = ts.0 * x + *axis * y;
34    return result + ts.1 * z;
35}
36
37/// Returns randomly sampled point within a unit hemisphere.
38///
39/// For a given unit hemisphere, defined by center normal vector, this function
40/// returns a point within the hemisphere.
41/// - Parameters:
42///   - u1: First random sample.
43///   - u2: Second random sample.
44///   - normal: The center normal of the hemisphere.
45/// - Returns: Sampled point.
46pub fn uniform_sample_hemisphere(u1: f64, u2: f64,
47                                 normal: &Vector3D) -> Vector3D {
48    let y = u1;
49    let r = f64::sqrt(f64::max(0.0, 1.0 - y * y));
50    let phi = crate::constants::K_TWO_PI_D * u2;
51    let x = r * f64::cos(phi);
52    let z = r * f64::sin(phi);
53    let ts = normal.tangential();
54
55    let result = ts.0 * x + *normal * y;
56    return result + ts.1 * z;
57}
58
59/// Returns weighted sampled point on a hemisphere.
60///
61/// For a given hemisphere, defined by center normal vector, this function
62/// returns a point on the hemisphere, where the probability is
63/// cosine-weighted.
64/// - Parameters:
65///   - u1: First random sample.
66///   - u2: Second random sample.
67///   - normal: The center normal of the hemisphere.
68/// - Returns: Sampled point.
69pub fn cosine_weighted_sample_hemisphere(u1: f64, u2: f64,
70                                         normal: &Vector3D) -> Vector3D {
71    let phi = crate::constants::K_TWO_PI_D * u1;
72    let y = f64::sqrt(u2);
73    let theta = f64::acos(y);
74    let x = f64::cos(phi) * f64::sin(theta);
75    let z = f64::sin(phi) * f64::sin(theta);
76    let ts = normal.tangential();
77
78    let result = ts.0 * x + *normal * y;
79    return result + ts.1 * z;
80}
81
82/// Returns randomly a point on a sphere.
83///
84/// For a given sphere, defined by center normal vector, this function returns a
85/// point on the sphere.
86/// - Parameters:
87///   - u1: First random sample.
88///   - u2: Second random sample.
89/// - Returns: Sampled point.
90pub fn uniform_sample_sphere(u1: f64, u2: f64) -> Vector3D {
91    let y = 1.0 - 2.0 * u1;
92    let r = f64::sqrt(f64::max(0.0, 1.0 - y * y));
93    let phi = crate::constants::K_TWO_PI_D * u2;
94    let x = r * f64::cos(phi);
95    let z = r * f64::sin(phi);
96    return Vector3D::new(x, y, z);
97}
98
99/// Returns randomly a point on a disk.
100///
101/// For a given disk, this function returns a point on the disk.
102/// - Parameters:
103///   - u1: First random sample.
104///   - u2: Second random sample.
105/// - Returns: Sampled point.
106pub fn uniform_sample_disk(u1: f64, u2: f64) -> Vector2D {
107    let r = f64::sqrt(u1);
108    let theta = crate::constants::K_TWO_PI_D * u2;
109
110    return Vector2D::new(r * f64::cos(theta), r * f64::sin(theta));
111}