6 @maintainer Morgan McGuire, matrix@graphics3d.com
8 @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com
16 #include "G3D/Vector3.h"
17 #include "G3D/g3dmath.h"
18 #include "G3D/format.h"
19 #include "G3D/stringutils.h"
20 #include "G3D/Vector3int16.h"
21 #include "G3D/Matrix3.h"
22 #include "G3D/Vector2.h"
26 Vector3
Vector3::dummy
;
29 const Vector3
Vector3::ZERO(0, 0, 0);
30 const Vector3
Vector3::ZERO3(0, 0, 0);
31 const Vector3
Vector3::UNIT_X(1, 0, 0);
32 const Vector3
Vector3::UNIT_Y(0, 1, 0);
33 const Vector3
Vector3::UNIT_Z(0, 0, 1);
34 const Vector3
Vector3::INF3((float)G3D::inf(), (float)G3D::inf(), (float)G3D::inf());
35 const Vector3
Vector3::NAN3((float)G3D::nan(), (float)G3D::nan(), (float)G3D::nan());
37 Vector3::Vector3(const class Vector2
& v
, float _z
) : x(v
.x
), y(v
.y
), z(_z
) {
40 Vector3::Axis
Vector3::primaryAxis() const {
66 unsigned int Vector3::hashCode() const {
67 unsigned int xhash
= (*(int*)(void*)(&x
));
68 unsigned int yhash
= (*(int*)(void*)(&y
));
69 unsigned int zhash
= (*(int*)(void*)(&z
));
71 return xhash
+ (yhash
* 37) + (zhash
* 101);
74 std::ostream
& operator<<(std::ostream
& os
, const Vector3
& v
) {
75 return os
<< v
.toString();
79 //----------------------------------------------------------------------------
82 return rand() / (double) RAND_MAX
;
86 Vector3::Vector3(const class Vector3int16
& v
) {
93 Vector3
Vector3::random() {
97 result
= Vector3(uniformRandom(-1.0, 1.0),
98 uniformRandom(-1.0, 1.0),
99 uniformRandom(-1.0, 1.0));
100 } while (result
.squaredMagnitude() >= 1.0f
);
107 //----------------------------------------------------------------------------
108 Vector3
Vector3::operator/ (float fScalar
) const {
111 if ( fScalar
!= 0.0 ) {
112 float fInvScalar
= 1.0f
/ fScalar
;
113 kQuot
.x
= fInvScalar
* x
;
114 kQuot
.y
= fInvScalar
* y
;
115 kQuot
.z
= fInvScalar
* z
;
118 return Vector3::inf();
122 //----------------------------------------------------------------------------
123 Vector3
& Vector3::operator/= (float fScalar
) {
124 if (fScalar
!= 0.0) {
125 float fInvScalar
= 1.0f
/ fScalar
;
130 x
= (float)G3D::inf();
131 y
= (float)G3D::inf();
132 z
= (float)G3D::inf();
138 //----------------------------------------------------------------------------
139 float Vector3::unitize (float fTolerance
) {
140 float fMagnitude
= magnitude();
142 if (fMagnitude
> fTolerance
) {
143 float fInvMagnitude
= 1.0f
/ fMagnitude
;
154 //----------------------------------------------------------------------------
156 Vector3
Vector3::reflectAbout(const Vector3
& normal
) const {
160 Vector3 N
= normal
.direction();
162 // 2 * normal.dot(this) * normal - this
163 return N
* 2 * this->dot(N
) - *this;
166 //----------------------------------------------------------------------------
168 Vector3
Vector3::cosRandom(const Vector3
& normal
) {
169 double e1
= G3D::random(0, 1);
170 double e2
= G3D::random(0, 1);
173 double theta
= acos(sqrt(e1
));
175 // Angle about normal
176 double phi
= 2 * G3D_PI
* e2
;
178 // Make a coordinate system
179 Vector3 U
= normal
.direction();
180 Vector3 V
= Vector3::unitX();
182 if (abs(U
.dot(V
)) > .9) {
183 V
= Vector3::unitY();
186 Vector3 W
= U
.cross(V
).direction();
189 // Convert to rectangular form
190 return cos(theta
) * U
+ sin(theta
) * (cos(phi
) * V
+ sin(phi
) * W
);
192 //----------------------------------------------------------------------------
194 Vector3
Vector3::hemiRandom(const Vector3
& normal
) {
195 Vector3 V
= Vector3::random();
197 if (V
.dot(normal
) < 0) {
204 //----------------------------------------------------------------------------
206 Vector3
Vector3::reflectionDirection(const Vector3
& normal
) const {
207 return -reflectAbout(normal
).direction();
210 //----------------------------------------------------------------------------
212 Vector3
Vector3::refractionDirection(
213 const Vector3
& normal
,
215 float iOutside
) const {
217 // From pg. 24 of Henrik Wann Jensen. Realistic Image Synthesis
218 // Using Photon Mapping. AK Peters. ISBN: 1568811470. July 2001.
220 // Invert the directions from Wann Jensen's formulation
221 // and normalize the vectors.
222 const Vector3 W
= -direction();
223 Vector3 N
= normal
.direction();
228 if (normal
.dot(*this) > 0.0f
) {
234 const float hRatio
= h1
/ h2
;
235 const float WdotN
= W
.dot(N
);
237 float det
= 1.0f
- (float)square(hRatio
) * (1.0f
- (float)square(WdotN
));
240 // Total internal reflection
241 return Vector3::zero();
243 return -hRatio
* (W
- WdotN
* N
) - N
* sqrt(det
);
247 //----------------------------------------------------------------------------
248 void Vector3::orthonormalize (Vector3 akVector
[3]) {
249 // If the input vectors are v0, v1, and v2, then the Gram-Schmidt
250 // orthonormalization produces vectors u0, u1, and u2 as follows,
253 // u1 = (v1-(u0*v1)u0)/|v1-(u0*v1)u0|
254 // u2 = (v2-(u0*v2)u0-(u1*v2)u1)/|v2-(u0*v2)u0-(u1*v2)u1|
256 // where |A| indicates length of vector A and A*B indicates dot
257 // product of vectors A and B.
260 akVector
[0].unitize();
263 float fDot0
= akVector
[0].dot(akVector
[1]);
264 akVector
[1] -= akVector
[0] * fDot0
;
265 akVector
[1].unitize();
268 float fDot1
= akVector
[1].dot(akVector
[2]);
269 fDot0
= akVector
[0].dot(akVector
[2]);
270 akVector
[2] -= akVector
[0] * fDot0
+ akVector
[1] * fDot1
;
271 akVector
[2].unitize();
274 //----------------------------------------------------------------------------
275 void Vector3::generateOrthonormalBasis (Vector3
& rkU
, Vector3
& rkV
,
276 Vector3
& rkW
, bool bUnitLengthW
) {
280 if ( G3D::abs(rkW
.x
) >= G3D::abs(rkW
.y
)
281 && G3D::abs(rkW
.x
) >= G3D::abs(rkW
.z
) ) {
292 rkV
= rkW
.cross(rkU
);
295 //----------------------------------------------------------------------------
297 std::string
Vector3::toString() const {
298 return G3D::format("(%g, %g, %g)", x
, y
, z
);
302 //----------------------------------------------------------------------------
304 Matrix3
Vector3::cross() const {
305 return Matrix3( 0, -z
, y
,
311 //----------------------------------------------------------------------------
314 Vector2
Vector3::xx() const { return Vector2 (x
, x
); }
315 Vector2
Vector3::yx() const { return Vector2 (y
, x
); }
316 Vector2
Vector3::zx() const { return Vector2 (z
, x
); }
317 Vector2
Vector3::xy() const { return Vector2 (x
, y
); }
318 Vector2
Vector3::yy() const { return Vector2 (y
, y
); }
319 Vector2
Vector3::zy() const { return Vector2 (z
, y
); }
320 Vector2
Vector3::xz() const { return Vector2 (x
, z
); }
321 Vector2
Vector3::yz() const { return Vector2 (y
, z
); }
322 Vector2
Vector3::zz() const { return Vector2 (z
, z
); }
326 Vector3
Vector3::xxx() const { return Vector3 (x
, x
, x
); }
327 Vector3
Vector3::yxx() const { return Vector3 (y
, x
, x
); }
328 Vector3
Vector3::zxx() const { return Vector3 (z
, x
, x
); }
329 Vector3
Vector3::xyx() const { return Vector3 (x
, y
, x
); }
330 Vector3
Vector3::yyx() const { return Vector3 (y
, y
, x
); }
331 Vector3
Vector3::zyx() const { return Vector3 (z
, y
, x
); }
332 Vector3
Vector3::xzx() const { return Vector3 (x
, z
, x
); }
333 Vector3
Vector3::yzx() const { return Vector3 (y
, z
, x
); }
334 Vector3
Vector3::zzx() const { return Vector3 (z
, z
, x
); }
335 Vector3
Vector3::xxy() const { return Vector3 (x
, x
, y
); }
336 Vector3
Vector3::yxy() const { return Vector3 (y
, x
, y
); }
337 Vector3
Vector3::zxy() const { return Vector3 (z
, x
, y
); }
338 Vector3
Vector3::xyy() const { return Vector3 (x
, y
, y
); }
339 Vector3
Vector3::yyy() const { return Vector3 (y
, y
, y
); }
340 Vector3
Vector3::zyy() const { return Vector3 (z
, y
, y
); }
341 Vector3
Vector3::xzy() const { return Vector3 (x
, z
, y
); }
342 Vector3
Vector3::yzy() const { return Vector3 (y
, z
, y
); }
343 Vector3
Vector3::zzy() const { return Vector3 (z
, z
, y
); }
344 Vector3
Vector3::xxz() const { return Vector3 (x
, x
, z
); }
345 Vector3
Vector3::yxz() const { return Vector3 (y
, x
, z
); }
346 Vector3
Vector3::zxz() const { return Vector3 (z
, x
, z
); }
347 Vector3
Vector3::xyz() const { return Vector3 (x
, y
, z
); }
348 Vector3
Vector3::yyz() const { return Vector3 (y
, y
, z
); }
349 Vector3
Vector3::zyz() const { return Vector3 (z
, y
, z
); }
350 Vector3
Vector3::xzz() const { return Vector3 (x
, z
, z
); }
351 Vector3
Vector3::yzz() const { return Vector3 (y
, z
, z
); }
352 Vector3
Vector3::zzz() const { return Vector3 (z
, z
, z
); }
356 Vector4
Vector3::xxxx() const { return Vector4 (x
, x
, x
, x
); }
357 Vector4
Vector3::yxxx() const { return Vector4 (y
, x
, x
, x
); }
358 Vector4
Vector3::zxxx() const { return Vector4 (z
, x
, x
, x
); }
359 Vector4
Vector3::xyxx() const { return Vector4 (x
, y
, x
, x
); }
360 Vector4
Vector3::yyxx() const { return Vector4 (y
, y
, x
, x
); }
361 Vector4
Vector3::zyxx() const { return Vector4 (z
, y
, x
, x
); }
362 Vector4
Vector3::xzxx() const { return Vector4 (x
, z
, x
, x
); }
363 Vector4
Vector3::yzxx() const { return Vector4 (y
, z
, x
, x
); }
364 Vector4
Vector3::zzxx() const { return Vector4 (z
, z
, x
, x
); }
365 Vector4
Vector3::xxyx() const { return Vector4 (x
, x
, y
, x
); }
366 Vector4
Vector3::yxyx() const { return Vector4 (y
, x
, y
, x
); }
367 Vector4
Vector3::zxyx() const { return Vector4 (z
, x
, y
, x
); }
368 Vector4
Vector3::xyyx() const { return Vector4 (x
, y
, y
, x
); }
369 Vector4
Vector3::yyyx() const { return Vector4 (y
, y
, y
, x
); }
370 Vector4
Vector3::zyyx() const { return Vector4 (z
, y
, y
, x
); }
371 Vector4
Vector3::xzyx() const { return Vector4 (x
, z
, y
, x
); }
372 Vector4
Vector3::yzyx() const { return Vector4 (y
, z
, y
, x
); }
373 Vector4
Vector3::zzyx() const { return Vector4 (z
, z
, y
, x
); }
374 Vector4
Vector3::xxzx() const { return Vector4 (x
, x
, z
, x
); }
375 Vector4
Vector3::yxzx() const { return Vector4 (y
, x
, z
, x
); }
376 Vector4
Vector3::zxzx() const { return Vector4 (z
, x
, z
, x
); }
377 Vector4
Vector3::xyzx() const { return Vector4 (x
, y
, z
, x
); }
378 Vector4
Vector3::yyzx() const { return Vector4 (y
, y
, z
, x
); }
379 Vector4
Vector3::zyzx() const { return Vector4 (z
, y
, z
, x
); }
380 Vector4
Vector3::xzzx() const { return Vector4 (x
, z
, z
, x
); }
381 Vector4
Vector3::yzzx() const { return Vector4 (y
, z
, z
, x
); }
382 Vector4
Vector3::zzzx() const { return Vector4 (z
, z
, z
, x
); }
383 Vector4
Vector3::xxxy() const { return Vector4 (x
, x
, x
, y
); }
384 Vector4
Vector3::yxxy() const { return Vector4 (y
, x
, x
, y
); }
385 Vector4
Vector3::zxxy() const { return Vector4 (z
, x
, x
, y
); }
386 Vector4
Vector3::xyxy() const { return Vector4 (x
, y
, x
, y
); }
387 Vector4
Vector3::yyxy() const { return Vector4 (y
, y
, x
, y
); }
388 Vector4
Vector3::zyxy() const { return Vector4 (z
, y
, x
, y
); }
389 Vector4
Vector3::xzxy() const { return Vector4 (x
, z
, x
, y
); }
390 Vector4
Vector3::yzxy() const { return Vector4 (y
, z
, x
, y
); }
391 Vector4
Vector3::zzxy() const { return Vector4 (z
, z
, x
, y
); }
392 Vector4
Vector3::xxyy() const { return Vector4 (x
, x
, y
, y
); }
393 Vector4
Vector3::yxyy() const { return Vector4 (y
, x
, y
, y
); }
394 Vector4
Vector3::zxyy() const { return Vector4 (z
, x
, y
, y
); }
395 Vector4
Vector3::xyyy() const { return Vector4 (x
, y
, y
, y
); }
396 Vector4
Vector3::yyyy() const { return Vector4 (y
, y
, y
, y
); }
397 Vector4
Vector3::zyyy() const { return Vector4 (z
, y
, y
, y
); }
398 Vector4
Vector3::xzyy() const { return Vector4 (x
, z
, y
, y
); }
399 Vector4
Vector3::yzyy() const { return Vector4 (y
, z
, y
, y
); }
400 Vector4
Vector3::zzyy() const { return Vector4 (z
, z
, y
, y
); }
401 Vector4
Vector3::xxzy() const { return Vector4 (x
, x
, z
, y
); }
402 Vector4
Vector3::yxzy() const { return Vector4 (y
, x
, z
, y
); }
403 Vector4
Vector3::zxzy() const { return Vector4 (z
, x
, z
, y
); }
404 Vector4
Vector3::xyzy() const { return Vector4 (x
, y
, z
, y
); }
405 Vector4
Vector3::yyzy() const { return Vector4 (y
, y
, z
, y
); }
406 Vector4
Vector3::zyzy() const { return Vector4 (z
, y
, z
, y
); }
407 Vector4
Vector3::xzzy() const { return Vector4 (x
, z
, z
, y
); }
408 Vector4
Vector3::yzzy() const { return Vector4 (y
, z
, z
, y
); }
409 Vector4
Vector3::zzzy() const { return Vector4 (z
, z
, z
, y
); }
410 Vector4
Vector3::xxxz() const { return Vector4 (x
, x
, x
, z
); }
411 Vector4
Vector3::yxxz() const { return Vector4 (y
, x
, x
, z
); }
412 Vector4
Vector3::zxxz() const { return Vector4 (z
, x
, x
, z
); }
413 Vector4
Vector3::xyxz() const { return Vector4 (x
, y
, x
, z
); }
414 Vector4
Vector3::yyxz() const { return Vector4 (y
, y
, x
, z
); }
415 Vector4
Vector3::zyxz() const { return Vector4 (z
, y
, x
, z
); }
416 Vector4
Vector3::xzxz() const { return Vector4 (x
, z
, x
, z
); }
417 Vector4
Vector3::yzxz() const { return Vector4 (y
, z
, x
, z
); }
418 Vector4
Vector3::zzxz() const { return Vector4 (z
, z
, x
, z
); }
419 Vector4
Vector3::xxyz() const { return Vector4 (x
, x
, y
, z
); }
420 Vector4
Vector3::yxyz() const { return Vector4 (y
, x
, y
, z
); }
421 Vector4
Vector3::zxyz() const { return Vector4 (z
, x
, y
, z
); }
422 Vector4
Vector3::xyyz() const { return Vector4 (x
, y
, y
, z
); }
423 Vector4
Vector3::yyyz() const { return Vector4 (y
, y
, y
, z
); }
424 Vector4
Vector3::zyyz() const { return Vector4 (z
, y
, y
, z
); }
425 Vector4
Vector3::xzyz() const { return Vector4 (x
, z
, y
, z
); }
426 Vector4
Vector3::yzyz() const { return Vector4 (y
, z
, y
, z
); }
427 Vector4
Vector3::zzyz() const { return Vector4 (z
, z
, y
, z
); }
428 Vector4
Vector3::xxzz() const { return Vector4 (x
, x
, z
, z
); }
429 Vector4
Vector3::yxzz() const { return Vector4 (y
, x
, z
, z
); }
430 Vector4
Vector3::zxzz() const { return Vector4 (z
, x
, z
, z
); }
431 Vector4
Vector3::xyzz() const { return Vector4 (x
, y
, z
, z
); }
432 Vector4
Vector3::yyzz() const { return Vector4 (y
, y
, z
, z
); }
433 Vector4
Vector3::zyzz() const { return Vector4 (z
, y
, z
, z
); }
434 Vector4
Vector3::xzzz() const { return Vector4 (x
, z
, z
, z
); }
435 Vector4
Vector3::yzzz() const { return Vector4 (y
, z
, z
, z
); }
436 Vector4
Vector3::zzzz() const { return Vector4 (z
, z
, z
, z
); }