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

Revision 2844, 13.3 KB checked in by mattausch, 16 years ago (diff)

lod starting to work

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        return Magnitude(v1 - v2);
324}
325
326
327inline float SqrDistance(const Vector3 &v1, const Vector3 &v2)
328{
329        //return sqrt(v1.x - v2.x) + sqrt(v1.y - v2.y) + sqrt(v1.z - v2.z);
330        return SqrMagnitude(v1 - v2);
331}
332
333
334inline Vector3 Normalize(const Vector3 &A)
335{
336        return A * (1.0f / Magnitude(A));
337}
338
339
340inline float DotProd(const Vector3 &A, const Vector3 &B)
341{
342        return A.x * B.x + A.y * B.y + A.z * B.z;
343}
344
345
346// angle between two vectors with respect to a surface normal in the
347// range [0 .. 2 * pi]
348inline float Angle(const Vector3 &A, const Vector3 &B, const Vector3 &norm)
349{
350        Vector3 cross = CrossProd(A, B);
351
352        float signedAngle;
353
354        if (DotProd(cross, norm) > 0)
355                signedAngle = atan2(-Magnitude(CrossProd(A, B)), DotProd(A, B));
356        else
357                signedAngle = atan2(Magnitude(CrossProd(A, B)), DotProd(A, B));
358
359        if (signedAngle < 0)
360                return 2 * M_PI + signedAngle;
361
362        return signedAngle;
363}
364
365
366inline Vector3 Vector3::operator+() const
367{
368        return *this;
369}
370
371
372inline Vector3 Vector3::operator-() const
373{
374  return Vector3(-x, -y, -z);
375}
376
377
378inline Vector3 &Vector3::operator+=(const Vector3 &A)
379{
380        x += A.x;  y += A.y;  z += A.z;
381        return *this;
382}
383
384
385inline Vector3& Vector3::operator-=(const Vector3 &A)
386{
387        x -= A.x;  y -= A.y;  z -= A.z;
388       
389        return *this;
390}
391
392
393inline Vector3& Vector3::operator*= (float A)
394{
395        x *= A;  y *= A;  z *= A;
396        return *this;
397}
398
399
400inline Vector3& Vector3::operator/=(float A)
401{
402        float a = 1.0f / A;
403       
404        x *= a;  y *= a;  z *= a;
405       
406        return *this;
407}
408
409
410inline Vector3& Vector3::operator*= (const Vector3 &A)
411{
412  x *= A.x;  y *= A.y;  z *= A.z;
413  return *this;
414}
415
416
417inline Vector3 operator+ (const Vector3 &A, const Vector3 &B)
418{
419        return Vector3(A.x + B.x, A.y + B.y, A.z + B.z);
420}
421
422
423inline Vector3 operator- (const Vector3 &A, const Vector3 &B)
424{
425        return Vector3(A.x - B.x, A.y - B.y, A.z - B.z);
426}
427
428
429inline Vector3 operator* (const Vector3 &A, const Vector3 &B)
430{
431        return Vector3(A.x * B.x, A.y * B.y, A.z * B.z);
432}
433
434
435inline Vector3 operator* (const Vector3 &A, float B)
436{
437  return Vector3(A.x * B, A.y * B, A.z * B);
438}
439
440
441inline Vector3 operator* (float A, const Vector3 &B)
442{
443        return Vector3(B.x * A, B.y * A, B.z * A);
444}
445
446
447inline Vector3 operator/ (const Vector3 &A, const Vector3 &B)
448{
449        return Vector3(A.x / B.x, A.y / B.y, A.z / B.z);
450}
451
452
453inline Vector3 operator/ (const Vector3 &A, float B)
454{
455        float b = 1.0f / B;
456        return Vector3(A.x * b, A.y * b, A.z * b);
457}
458
459
460inline int operator< (const Vector3 &A, const Vector3 &B)
461{
462        return A.x < B.x && A.y < B.y && A.z < B.z;
463}
464
465
466inline int operator<= (const Vector3 &A, const Vector3 &B)
467{
468        return A.x <= B.x && A.y <= B.y && A.z <= B.z;
469}
470
471
472// Might replace floating-point == with comparisons of
473// magnitudes, if needed.
474inline int operator== (const Vector3 &A, const Vector3 &B)
475{
476        return (A.x == B.x) && (A.y == B.y) && (A.z == B.z);
477}
478
479
480inline Vector3 CrossProd (const Vector3 &A, const Vector3 &B)
481{
482        return Vector3(A.y * B.z - A.z * B.y,
483                           A.z * B.x - A.x * B.z,
484                                   A.x * B.y - A.y * B.x);
485}
486
487
488inline void Vector3::Normalize()
489{
490        float sqrmag = x * x + y * y + z * z;
491       
492        if (sqrmag > 0.0f)
493                (*this) *= 1.0f / sqrtf(sqrmag);
494}
495
496
497// Overload << operator for C++-style output
498inline std::ostream& operator<< (std::ostream &s, const Vector3 &A)
499{
500        return s << "(" << A.x << ", " << A.y << ", " << A.z << ")";
501}
502
503
504// Overload >> operator for C++-style input
505inline std::istream& operator>> (std::istream &s, Vector3 &A)
506{
507        char a;
508        // read "(x, y, z)"
509        return s >> a >> A.x >> a >> A.y >> a >> A.z >> a;
510}
511
512
513inline int EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2, float thr)
514{
515        if (fabsf(v1.x-v2.x) > thr)
516                return false;
517        if (fabsf(v1.y-v2.y) > thr)
518                return false;
519        if (fabsf(v1.z-v2.z) > thr)
520                return false;
521       
522        return true;
523}
524
525
526inline int EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2)
527{
528        return EpsilonEqualV3(v1, v2, Limits::Small);
529}
530
531
532}
533
534#endif
Note: See TracBrowser for help on using the repository browser.