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}