source: GTP/trunk/App/Demos/Vis/FriendlyCulling/Converter/SimpleVec.h @ 3012

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