source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Vector3.h @ 2782

Revision 2782, 13.2 KB checked in by mattausch, 16 years ago (diff)
Line 
1#ifndef _Vector3_h__
2#define _Vector3_h__
3
4#include <iostream>
5#include "common.h"
6#include <math.h>
7
8
9namespace CHCDemoEngine
10{
11
12// Forward-declare some other classes.
13class Matrix4x4;
14
15
16/** Vector class.
17*/
18class Vector3
19{
20public:
21
22        ///////////
23        //-- members;
24
25        float x;
26        float y;
27        float z;
28
29
30        /////////////////////////
31
32        void  SetX(float q) { x = q; }
33        void  SetY(float q) { y = q; }
34        void  SetZ(float q) { z = q; }
35
36        float GetX() const { return x; }
37        float GetY() const { return y; }
38        float GetZ() const { return z; }
39
40
41        //////////////
42        //-- constructors
43
44        Vector3() { }
45
46        Vector3(float x, float y, float z): x(x), y(y), z(z)
47        {}
48
49        Vector3(float v): x(v), y(v), z(v){}
50        /** Copy constructor.
51        */
52        Vector3(const Vector3 &v): x(v.x), y(v.y), z(v.z)
53        {}
54
55        // Functions to get at the std::vector components
56        float& operator[] (const int inx)
57        {
58                return (&x)[inx];
59        }
60
61        operator const float*() const
62        {
63                return (const float*) this;
64        }
65
66        const float &operator[] (const int inx) const
67        {
68                return *(&x + inx);
69        }
70
71        void ExtractVerts(float *px, float *py, int which) const;
72 
73        void SetValue(float a, float b, float c)
74        { 
75                x = a; y = b; z = c;
76        }
77
78        void SetValue(float a)
79        {
80                x = y = z = a;
81        }
82 
83        /** Returns the axis, where the std::vector has the largest value.
84        */
85        int DrivingAxis(void) const;
86        /** returns the axis, where the std::vector has the smallest value
87        */
88        int TinyAxis(void) const;
89        /** Returns largest component in this vector
90        */
91        inline float MaxComponent(void) const
92        {
93                return (x > y) ? ( (x > z) ? x : z) : ( (y > z) ? y : z);
94        }
95        /** Returns copy of this vector where all components are positiv.
96        */
97        inline Vector3 Abs(void) const
98        {
99                return Vector3(fabs(x), fabs(y), fabs(z));
100        }
101        /** normalizes the std::vector of unit size corresponding to given std::vector
102        */
103        inline void Normalize();
104        /** Returns false if this std::vector has a nan component.
105        */
106        bool CheckValidity() const;
107        /**
108        Find a right handed coordinate system with (*this) being
109        the z-axis. For a right-handed system, U x V = (*this) holds.
110        This implementation is here to avoid inconsistence and confusion
111        when construction coordinate systems using ArbitraryNormal():
112        In fact:
113        V = ArbitraryNormal(N);
114        U = CrossProd(V,N);
115        constructs a right-handed coordinate system as well, BUT:
116        1) bugs can be introduced if one mistakenly constructs a
117        left handed sytems e.g. by doing
118        U = ArbitraryNormal(N);
119        V = CrossProd(U,N);
120        2) this implementation gives non-negative base vectors
121        for (*this)==(0,0,1) |  (0,1,0) | (1,0,0), which is
122        good for debugging and is not the case with the implementation
123        using ArbitraryNormal()
124
125        ===> Using ArbitraryNormal() for constructing coord systems
126        is obsoleted by this method (<JK> 12/20/03).   
127        */
128        void RightHandedBase(Vector3& U, Vector3& V) const;
129       
130       
131        // Unary operators
132
133        Vector3 operator+ () const;
134        Vector3 operator- () const;
135
136        // Assignment operators
137       
138        Vector3& operator+= (const Vector3 &A);
139        Vector3& operator-= (const Vector3 &A);
140        Vector3& operator*= (const Vector3 &A);
141        Vector3& operator*= (float A);
142        Vector3& operator/= (float A);
143
144
145        //////////
146        //-- friends
147       
148        /**
149        ===> Using ArbitraryNormal() for constructing coord systems
150        ===> is obsoleted by RightHandedBase() method (<JK> 12/20/03).   
151
152        Return an arbitrary normal to `v'.
153        In fact it tries v x (0,0,1) an if the result is too small,
154        it definitely does v x (0,1,0). It will always work for
155        non-degenareted std::vector and is much faster than to use
156        TangentVectors.
157
158        @param v(in) The std::vector we want to find normal for.
159        @return The normal std::vector to v.
160        */
161        friend inline Vector3 ArbitraryNormal(const Vector3 &v);
162
163        /// Transforms a std::vector to the global coordinate frame.
164        /**
165        Given a local coordinate frame (U,V,N) (i.e. U,V,N are
166        the x,y,z axes of the local coordinate system) and
167        a std::vector 'loc' in the local coordiante system, this
168        function returns a the coordinates of the same std::vector
169        in global frame (i.e. frame (1,0,0), (0,1,0), (0,0,1).
170        */
171        friend inline Vector3 ToGlobalFrame(const Vector3& loc,
172                                                const Vector3& U,
173                                                                                const Vector3& V,
174                                                                                const Vector3& N);
175
176        /// Transforms a std::vector to a local coordinate frame.
177        /**
178        Given a local coordinate frame (U,V,N) (i.e. U,V,N are
179        the x,y,z axes of the local coordinate system) and
180        a std::vector 'loc' in the global coordiante system, this
181        function returns a the coordinates of the same std::vector
182        in the local frame.
183        */
184        friend inline Vector3 ToLocalFrame(const Vector3& loc,
185                                           const Vector3& U,
186                                                                           const Vector3& V,
187                                                                           const Vector3& N);
188
189        /// the magnitude=size of the std::vector
190        friend inline float Magnitude(const Vector3 &v);
191        /// the squared magnitude of the std::vector .. for efficiency in some cases
192        friend inline float SqrMagnitude(const Vector3 &v);
193        /// Magnitude(v1-v2)
194        friend inline float Distance(const Vector3 &v1, const Vector3 &v2);
195        /// SqrMagnitude(v1-v2)
196        friend inline float SqrDistance(const Vector3 &v1, const Vector3 &v2);
197        /// creates the std::vector of unit size corresponding to given std::vector
198        friend inline Vector3 Normalize(const Vector3 &A);
199        /// // Rotate a direction vector
200        friend Vector3 PlaneRotate(const Matrix4x4 &, const Vector3 &);
201
202        // construct view vectors .. DirAt is the main viewing direction
203        // Viewer is the coordinates of viewer location, UpL is the std::vector.
204        friend void ViewVectors(const Vector3 &DirAt,
205                                                        const Vector3 &Viewer,
206                                                        const Vector3 &UpL,
207                                                        Vector3 &ViewV,
208                                                        Vector3 &ViewU,
209                                                        Vector3 &ViewN);
210
211        // Given the intersection point `P', you have available normal `N'
212        // of unit length. Let us suppose the incoming ray has direction `D'.
213        // Then we can construct such two vectors `U' and `V' that
214        // `U',`N', and `D' are coplanar, and `V' is perpendicular
215        // to the vectors `N','D', and `V'. Then 'N', 'U', and 'V' create
216        // the orthonormal base in space R3.
217        friend void TangentVectors(Vector3 &U, Vector3 &V, // output
218                                                           const Vector3 &normal, // input
219                                                           const Vector3 &dirIncoming);
220
221
222        // Binary operators
223       
224        friend inline Vector3 operator+ (const Vector3 &A, const Vector3 &B);
225        friend inline Vector3 operator- (const Vector3 &A, const Vector3 &B);
226        friend inline Vector3 operator* (const Vector3 &A, const Vector3 &B);
227        friend inline Vector3 operator* (const Vector3 &A, float B);
228        friend inline Vector3 operator* (float A, const Vector3 &B);
229        friend Vector3 operator* (const Matrix4x4 &, const Vector3 &);
230        friend inline Vector3 operator/ (const Vector3 &A, const Vector3 &B);
231
232        friend inline int operator< (const Vector3 &A, const Vector3 &B);
233        friend inline int operator<= (const Vector3 &A, const Vector3 &B);
234
235        friend inline Vector3 operator/ (const Vector3 &A, float B);
236        friend inline int operator== (const Vector3 &A, const Vector3 &B);
237        friend inline float DotProd(const Vector3 &A, const Vector3 &B);
238        friend inline Vector3 CrossProd (const Vector3 &A, const Vector3 &B);
239
240        friend std::ostream& operator<< (std::ostream &s, const Vector3 &A);
241        friend std::istream& operator>> (std::istream &s, Vector3 &A);
242
243        friend void Minimize(Vector3 &min, const Vector3 &candidate);
244        friend void Maximize(Vector3 &max, const Vector3 &candidate);
245
246        friend inline int EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2, float thr);
247        friend inline int EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2);
248
249        friend Vector3 CosineRandomVector(const Vector3 &normal);
250        friend Vector3 UniformRandomVector(const Vector3 &normal);
251        friend Vector3 UniformRandomVector();
252
253        friend Vector3 UniformRandomVector(float r1, float r2);
254
255        friend Vector3 CosineRandomVector(float r1, float r2, const Vector3 &normal);
256};
257
258
259
260// forward declaration
261extern Vector3 UniformRandomVector(const Vector3 &normal);
262extern Vector3 UniformRandomVector();
263extern Vector3 UniformRandomVector(const float r1, const float r2);
264
265inline Vector3 ArbitraryNormal(const Vector3 &N)
266{
267        float dist2 = N.x * N.x + N.y * N.y;
268
269        if (dist2 > 0.0001f)
270        {
271                float inv_size = 1.0f / sqrtf(dist2);
272                return Vector3(N.y * inv_size, -N.x * inv_size, 0); // N x (0,0,1)
273        }
274
275        float inv_size = 1.0f / sqrtf(N.z * N.z + N.x * N.x);
276        return Vector3(-N.z * inv_size, 0, N.x * inv_size); // N x (0,1,0)
277}
278
279
280inline void Vector3::RightHandedBase(Vector3& U, Vector3& V) const
281{
282        // HACK
283        V = ArbitraryNormal(*this);
284        U = CrossProd(V, *this);
285}
286
287
288inline Vector3 ToGlobalFrame(const Vector3 &loc,
289                                                         const Vector3 &U,
290                                                         const Vector3 &V,
291                                                         const Vector3 &N)
292{
293        return loc.x * U + loc.y * V + loc.z * N;
294}
295
296
297inline Vector3 ToLocalFrame(const Vector3 &loc,
298                                                        const Vector3 &U,
299                                                        const Vector3 &V,
300                                                        const Vector3 &N)
301{
302        return Vector3(loc.x * U.x + loc.y * U.y + loc.z * U.z,
303                                   loc.x * V.x + loc.y * V.y + loc.z * V.z,
304                                   loc.x * N.x + loc.y * N.y + loc.z * N.z);
305}
306
307
308inline float Magnitude(const Vector3 &v)
309{
310        return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
311}
312
313
314inline float SqrMagnitude(const Vector3 &v)
315{
316  return v.x * v.x + v.y * v.y + v.z * v.z;
317}
318
319
320inline float Distance(const Vector3 &v1, const Vector3 &v2)
321{
322  return sqrtf(sqrt(v1.x - v2.x) + sqrt(v1.y - v2.y) + sqrt(v1.z - v2.z));
323}
324
325
326inline float SqrDistance(const Vector3 &v1, const Vector3 &v2)
327{
328  return sqrt(v1.x - v2.x) + sqrt(v1.y - v2.y) + sqrt(v1.z - v2.z);
329}
330
331
332inline Vector3 Normalize(const Vector3 &A)
333{
334  return A * (1.0f / Magnitude(A));
335}
336
337
338inline float DotProd(const Vector3 &A, const Vector3 &B)
339{
340  return A.x * B.x + A.y * B.y + A.z * B.z;
341}
342
343
344// angle between two vectors with respect to a surface normal in the
345// range [0 .. 2 * pi]
346inline float Angle(const Vector3 &A, const Vector3 &B, const Vector3 &norm)
347{
348        Vector3 cross = CrossProd(A, B);
349
350        float signedAngle;
351
352        if (DotProd(cross, norm) > 0)
353                signedAngle = atan2(-Magnitude(CrossProd(A, B)), DotProd(A, B));
354        else
355                signedAngle = atan2(Magnitude(CrossProd(A, B)), DotProd(A, B));
356
357        if (signedAngle < 0)
358                return 2 * M_PI + signedAngle;
359
360        return signedAngle;
361}
362
363
364inline Vector3 Vector3::operator+() const
365{
366        return *this;
367}
368
369
370inline Vector3 Vector3::operator-() const
371{
372  return Vector3(-x, -y, -z);
373}
374
375
376inline Vector3 &Vector3::operator+=(const Vector3 &A)
377{
378        x += A.x;  y += A.y;  z += A.z;
379        return *this;
380}
381
382
383inline Vector3& Vector3::operator-=(const Vector3 &A)
384{
385        x -= A.x;  y -= A.y;  z -= A.z;
386       
387        return *this;
388}
389
390
391inline Vector3& Vector3::operator*= (float A)
392{
393        x *= A;  y *= A;  z *= A;
394        return *this;
395}
396
397
398inline Vector3& Vector3::operator/=(float A)
399{
400        float a = 1.0f / A;
401       
402        x *= a;  y *= a;  z *= a;
403       
404        return *this;
405}
406
407
408inline Vector3& Vector3::operator*= (const Vector3 &A)
409{
410  x *= A.x;  y *= A.y;  z *= A.z;
411  return *this;
412}
413
414
415inline Vector3 operator+ (const Vector3 &A, const Vector3 &B)
416{
417        return Vector3(A.x + B.x, A.y + B.y, A.z + B.z);
418}
419
420
421inline Vector3 operator- (const Vector3 &A, const Vector3 &B)
422{
423        return Vector3(A.x - B.x, A.y - B.y, A.z - B.z);
424}
425
426
427inline Vector3 operator* (const Vector3 &A, const Vector3 &B)
428{
429        return Vector3(A.x * B.x, A.y * B.y, A.z * B.z);
430}
431
432
433inline Vector3 operator* (const Vector3 &A, float B)
434{
435  return Vector3(A.x * B, A.y * B, A.z * B);
436}
437
438
439inline Vector3 operator* (float A, const Vector3 &B)
440{
441        return Vector3(B.x * A, B.y * A, B.z * A);
442}
443
444
445inline Vector3 operator/ (const Vector3 &A, const Vector3 &B)
446{
447        return Vector3(A.x / B.x, A.y / B.y, A.z / B.z);
448}
449
450
451inline Vector3 operator/ (const Vector3 &A, float B)
452{
453        float b = 1.0f / B;
454        return Vector3(A.x * b, A.y * b, A.z * b);
455}
456
457
458inline int operator< (const Vector3 &A, const Vector3 &B)
459{
460        return A.x < B.x && A.y < B.y && A.z < B.z;
461}
462
463
464inline int operator<= (const Vector3 &A, const Vector3 &B)
465{
466        return A.x <= B.x && A.y <= B.y && A.z <= B.z;
467}
468
469
470// Might replace floating-point == with comparisons of
471// magnitudes, if needed.
472inline int operator== (const Vector3 &A, const Vector3 &B)
473{
474        return (A.x == B.x) && (A.y == B.y) && (A.z == B.z);
475}
476
477
478inline Vector3 CrossProd (const Vector3 &A, const Vector3 &B)
479{
480        return Vector3(A.y * B.z - A.z * B.y,
481                           A.z * B.x - A.x * B.z,
482                                   A.x * B.y - A.y * B.x);
483}
484
485
486inline void Vector3::Normalize()
487{
488        float sqrmag = x * x + y * y + z * z;
489       
490        if (sqrmag > 0.0f)
491                (*this) *= 1.0f / sqrtf(sqrmag);
492}
493
494
495// Overload << operator for C++-style output
496inline std::ostream& operator<< (std::ostream &s, const Vector3 &A)
497{
498        return s << "(" << A.x << ", " << A.y << ", " << A.z << ")";
499}
500
501
502// Overload >> operator for C++-style input
503inline std::istream& operator>> (std::istream &s, Vector3 &A)
504{
505        char a;
506        // read "(x, y, z)"
507        return s >> a >> A.x >> a >> A.y >> a >> A.z >> a;
508}
509
510
511inline int EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2, float thr)
512{
513        if (fabsf(v1.x-v2.x) > thr)
514                return false;
515        if (fabsf(v1.y-v2.y) > thr)
516                return false;
517        if (fabsf(v1.z-v2.z) > thr)
518                return false;
519       
520        return true;
521}
522
523
524inline int EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2)
525{
526        return EpsilonEqualV3(v1, v2, Limits::Small);
527}
528
529
530}
531
532#endif
Note: See TracBrowser for help on using the repository browser.