-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVector3D.cpp
242 lines (224 loc) · 5.62 KB
/
Vector3D.cpp
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#include <math.h>
#include "precomp.h"
#include "Vector3D.h"
// Defult Constructor
inline Vector3D::Vector3D() : x(0.0f), y(0.0f), z(0.0f)
{}
// Construct with one float
inline Vector3D::Vector3D(float value) : x(value), y(value), z(value)
{}
// Construct with three floats
inline Vector3D::Vector3D(float x_value, float y_value, float z_value)
: x(x_value), y(y_value), z(z_value)
{}
// Copy Construct from a vector
inline Vector3D::Vector3D(const Vector3D& vec3)
: x(vec3.x), y(vec3.y), z(vec3.z)
{}
// Construct from a Point3D
inline Vector3D::Vector3D(const Point3D& p3d)
: x(p3d.x), y(p3d.y), z(p3d.z)
{}
// Construct from a normal
Vector3D::Vector3D(const Normal& nrml)
: x(nrml.x), y(nrml.y), z(nrml.z)
{}
// Destructor
inline Vector3D::~Vector3D()
{}
// Assignment operator, from a Vector3D
Vector3D& Vector3D::operator=(const Vector3D& vec3)
{
if (this == &vec3)
return *this;
x = vec3.x;
y = vec3.y;
z = vec3.z;
return *this;
}
// Assignment operator, from a Normal
Vector3D& Vector3D::operator=(const Normal& nrml)
{
x = nrml.x;
y = nrml.y;
z = nrml.z;
return *this;
}
// Assignment operator, from a Point3D
Vector3D& Vector3D::operator=(const Point3D& p3d)
{
x = p3d.x;
y = p3d.y;
z = p3d.z;
return *this;
}
// Unary minus
Point3D Vector3D::operator- () const
{
return Point3D(-x, -y, -z);
}
// Get length / norm of the Vector3D
float Vector3D::length()
{
return sqrtf(len_squared());
}
// Get the squared length / norm of the Vector3D
float Vector3D::len_squared()
{
return (x*x + y*y + z*z);
}
// Multiplication by a float on the right
Vector3D Vector3D::operator* (const float value) const
{
return Vector3D(x*value, y*value, z*value);
}
// Division by a float
Vector3D Vector3D::operator/ (const float value) const
{
float valueInv = float(1.0f / value);
return Vector3D(x*valueInv, y*valueInv, z*valueInv);
}
// Addition by another Vector3D
Vector3D Vector3D::operator+ (const Vector3D& vec3) const
{
return Vector3D(x + vec3.x, y + vec3.y, z + vec3.z);
}
// Compound Addition
Vector3D& Vector3D::operator+= (const Vector3D& vec3)
{
x += vec3.x;
y += vec3.y;
z += vec3.z;
return *this;
}
// Subtract a Vector3D
Vector3D Vector3D::operator- (const Vector3D& vec3) const
{
return Vector3D(x - vec3.x, y - vec3.y, z - vec3.z);
}
// Dot product
float Vector3D::operator* (const Vector3D& vec3) const
{
return (x * vec3.x + y * vec3.y + z * vec3.z);
}
// Cross product
Vector3D Vector3D::operator^ (const Vector3D& vec3) const
{
return (Vector3D(y * vec3.z - z * vec3.y,
z * vec3.x - x * vec3.z,
x * vec3.y - y * vec3.x));
}
// Return a unit Vector3D, and normalize the Vector3D
Vector3D& Vector3D::hat()
{
float vecLengthInv = float(1.0 / length());
x *= vecLengthInv;
y *= vecLengthInv;
z *= vecLengthInv;
return *this;
}
/// Class ONB
// Build ONB using input Normal
void ONB::build_onb(const Normal& n)
{
this->w_axis = n; this->w_axis.normalize();
Vector3D a = (fabs(n.x) > 0.99f) ? Vector3D(0, 1, 0) : Vector3D(1, 0, 0);
this->u_axis = this->w_axis^a;
this->v_axis = this->u_axis^this->w_axis;
this->u_axis.normalize(); this->v_axis.normalize();
}
Vector3D ONB::de_local(const Vector3D& vec)
{
return Vector3D(this->u_axis * vec, this->v_axis * vec, this->w_axis * vec);
}
// Non-member functions
// Multiplication by a float on the left
Vector3D operator* (const float value, const Vector3D& vec3)
{
return Vector3D(vec3.x * value, vec3.y * value, vec3.z * value);
}
// Multiplication by a matrix on the left
Vector3D operator* (const Matrix& mat, const Vector3D& vec3)
{
return (Vector3D(mat.m[0][0] * vec3.x + mat.m[0][1] * vec3.y + mat.m[0][2] * vec3.z,
mat.m[1][0] * vec3.x + mat.m[1][1] * vec3.y + mat.m[1][2] * vec3.z,
mat.m[2][0] * vec3.x + mat.m[2][1] * vec3.y + mat.m[2][2] * vec3.z));
}
// Get a random Vector3D within a unit sphere
Vector3D random_in_unit_sphere()
{
Vector3D vec;
do
{
vec = 2.0f * Vector3D(drand48(), drand48(), drand48()) - Vector3D(1.0f, 1.0f, 1.0f);
} while (vec.len_squared() >= 1.0f);
vec.normalize();
return vec;
}
// Get a Point2D within a unit disc
Point2D random_in_unit_disc()
{
float x, y;
do
{
x = 2.0f * drand48() - 1.0f; y = 2.0f * drand48() - 1.0f;
} while (x*x + y*y >= 1.0f);
return Point2D(x, y);
}
// Get a random Vector3D according to cosine(with z-axis) distribution
// PDF for this distribution is: pdf = cosine / PI
Vector3D random_cosine_direction()
{
float r1, r2;
do
{
r1 = drand48(); r2 = drand48();
} while (r1 == 1.0f || r2 == 1.0f);
float z = (float)sqrtf(1.0f - r2);
float phi = TWO_PI * r1;
float rt = (float)sqrtf(r2);
float x = cosf(phi)*rt;
float y = sinf(phi)*rt;
return Vector3D(x, y, z);
}
Vector3D random_cosine_direction(float angleInput)
{
// This is expensive! That's why there is no sphere lights!
float theta = (float)acosf(angleInput);
float r1, r2;
do
{
r1 = drand48(); r2 = drand48();
} while (r1 == 1.0f || r2 == 1.0f);
float z = (float)cosf(theta * r2);
float phi = TWO_PI * r1;
float sine = (float)sinf(theta * r2);
float x = cosf(phi)*sine;
float y = sinf(phi)*sine;
return Vector3D(x, y, z);
}
Vector3D random_phong_direction(float a)
{
float r1 = drand48(), r2 = drand48();
float z = pow(r2, 1.0f / (a + 1.0f));
float t = pow(r2, 2.0f / (a + 1.0f));
float phi = TWO_PI * r1;
float rt = (float)sqrtf(1.0f - t);
float x = cosf(phi)*rt;
float y = sinf(phi)*rt;
return Vector3D(x, y, z);
}
Vector3D random_microfacet_direction(float alpha)
{
float r1, r2;
do
{
r1 = drand48(); r2 = drand48();
} while (r1 == 0.0f || r2 == 1.0f);
float cosTheta = pow(r1, (1.0f / (alpha + 1)));
float sinTheta = sqrtf(1.0f - cosTheta*cosTheta);
float Phi = TWO_PI * r2;
return Vector3D(sinTheta * cosf(Phi),
sinTheta * sinf(Phi),
cosTheta);
}