Initial Patch of Auction House bot rev. 135
[auctionmangos.git] / dep / src / g3dlite / Vector3.cpp
blob57ee76d1eb17e48a1b81b2fbc25e1fbc1dd22ca2
1 /**
2 @file Vector3.cpp
4 3D vector class
6 @maintainer Morgan McGuire, matrix@graphics3d.com
8 @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com
10 @created 2001-06-02
11 @edited 2006-01-30
14 #include <limits>
15 #include <stdlib.h>
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"
24 namespace G3D {
26 Vector3 Vector3::dummy;
28 // Deprecated.
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 {
42 Axis a = X_AXIS;
44 double nx = abs(x);
45 double ny = abs(y);
46 double nz = abs(z);
48 if (nx > ny) {
49 if (nx > nz) {
50 a = X_AXIS;
51 } else {
52 a = Z_AXIS;
54 } else {
55 if (ny > nz) {
56 a = Y_AXIS;
57 } else {
58 a = Z_AXIS;
62 return a;
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 //----------------------------------------------------------------------------
81 double frand() {
82 return rand() / (double) RAND_MAX;
86 Vector3::Vector3(const class Vector3int16& v) {
87 x = v.x;
88 y = v.y;
89 z = v.z;
93 Vector3 Vector3::random() {
94 Vector3 result;
96 do {
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);
102 result.unitize();
104 return result;
107 //----------------------------------------------------------------------------
108 Vector3 Vector3::operator/ (float fScalar) const {
109 Vector3 kQuot;
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;
116 return kQuot;
117 } else {
118 return Vector3::inf();
122 //----------------------------------------------------------------------------
123 Vector3& Vector3::operator/= (float fScalar) {
124 if (fScalar != 0.0) {
125 float fInvScalar = 1.0f / fScalar;
126 x *= fInvScalar;
127 y *= fInvScalar;
128 z *= fInvScalar;
129 } else {
130 x = (float)G3D::inf();
131 y = (float)G3D::inf();
132 z = (float)G3D::inf();
135 return *this;
138 //----------------------------------------------------------------------------
139 float Vector3::unitize (float fTolerance) {
140 float fMagnitude = magnitude();
142 if (fMagnitude > fTolerance) {
143 float fInvMagnitude = 1.0f / fMagnitude;
144 x *= fInvMagnitude;
145 y *= fInvMagnitude;
146 z *= fInvMagnitude;
147 } else {
148 fMagnitude = 0.0f;
151 return fMagnitude;
154 //----------------------------------------------------------------------------
156 Vector3 Vector3::reflectAbout(const Vector3& normal) const {
158 Vector3 out;
160 Vector3 N = normal.direction();
162 // 2 * normal.dot(this) * normal - this
163 return N * 2 * this->dot(N) - *this;
166 //----------------------------------------------------------------------------
167 #if 0
168 Vector3 Vector3::cosRandom(const Vector3& normal) {
169 double e1 = G3D::random(0, 1);
170 double e2 = G3D::random(0, 1);
172 // Angle from normal
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();
187 V = W.cross(U);
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) {
198 return -V;
199 } else {
200 return V;
203 #endif
204 //----------------------------------------------------------------------------
206 Vector3 Vector3::reflectionDirection(const Vector3& normal) const {
207 return -reflectAbout(normal).direction();
210 //----------------------------------------------------------------------------
212 Vector3 Vector3::refractionDirection(
213 const Vector3& normal,
214 float iInside,
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();
225 float h1 = iOutside;
226 float h2 = iInside;
228 if (normal.dot(*this) > 0.0f) {
229 h1 = iInside;
230 h2 = iOutside;
231 N = -N;
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));
239 if (det < 0) {
240 // Total internal reflection
241 return Vector3::zero();
242 } else {
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,
252 // u0 = v0/|v0|
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.
259 // compute u0
260 akVector[0].unitize();
262 // compute u1
263 float fDot0 = akVector[0].dot(akVector[1]);
264 akVector[1] -= akVector[0] * fDot0;
265 akVector[1].unitize();
267 // compute u2
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) {
277 if ( !bUnitLengthW )
278 rkW.unitize();
280 if ( G3D::abs(rkW.x) >= G3D::abs(rkW.y)
281 && G3D::abs(rkW.x) >= G3D::abs(rkW.z) ) {
282 rkU.x = -rkW.y;
283 rkU.y = + rkW.x;
284 rkU.z = 0.0;
285 } else {
286 rkU.x = 0.0;
287 rkU.y = + rkW.z;
288 rkU.z = -rkW.y;
291 rkU.unitize();
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,
306 z, 0, -x,
307 -y, x, 0);
311 //----------------------------------------------------------------------------
312 // 2-char swizzles
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); }
324 // 3-char swizzles
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); }
354 // 4-char swizzles
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); }
443 } // namespace