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