source: GTP/trunk/Lib/Geom/shared/GTGeometry/include/GeoVector3.h @ 774

Revision 774, 14.5 KB checked in by gumbau, 18 years ago (diff)

GTGeometry and GeoTool? initial imports

Line 
1#ifndef __GEO_VECTOR3__
2#define __GEO_VECTOR3__
3#ifndef DOXYGEN_SHOULD_SKIP_THIS
4
5#include "GeoBase.h"
6#include <cmath>
7#include <cassert>
8#include <ostream>
9
10namespace Geometry
11{
12
13    class Vector3
14    {
15    public:
16        union {
17            struct {
18                Real x, y, z;       
19            };
20            Real val[3];
21        };
22
23    public:
24        inline Vector3()
25        {
26        }
27
28        inline Vector3( Real fX, Real fY, Real fZ )
29            : x( fX ), y( fY ), z( fZ )
30        {
31        }
32
33        inline Vector3( const Real* const r )
34            : x( r[0] ), y( r[1] ), z( r[2] )
35        {
36        }
37
38        inline Vector3( const Vector3& rkVector )
39            : x( rkVector.x ), y( rkVector.y ), z( rkVector.z )
40        {
41        }
42
43                inline Real operator [] ( size_t i ) const
44        {
45            assert( i < 3 );
46            return *(&x+i);
47        }
48
49                inline Real& operator [] ( size_t i )
50        {
51            assert( i < 3 );
52            return *(&x+i);
53        }
54
55        /** Assigns the value of the other vector.
56            @param
57                rkVector The other vector
58        */
59        inline Vector3& operator = ( const Vector3& rkVector )
60        {
61            x = rkVector.x;
62            y = rkVector.y;
63            z = rkVector.z;           
64
65            return *this;
66        }
67
68        inline bool operator == ( const Vector3& rkVector ) const
69        {
70            return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
71        }
72
73        inline bool operator != ( const Vector3& rkVector ) const
74        {
75            return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
76        }
77
78        // arithmetic operations
79        inline Vector3 operator + ( const Vector3& rkVector ) const
80        {
81            Vector3 kSum;
82
83            kSum.x = x + rkVector.x;
84            kSum.y = y + rkVector.y;
85            kSum.z = z + rkVector.z;
86
87            return kSum;
88        }
89
90        inline Vector3 operator - ( const Vector3& rkVector ) const
91        {
92            Vector3 kDiff;
93
94            kDiff.x = x - rkVector.x;
95            kDiff.y = y - rkVector.y;
96            kDiff.z = z - rkVector.z;
97
98            return kDiff;
99        }
100
101        inline Vector3 operator * ( Real fScalar ) const
102        {
103            Vector3 kProd;
104
105            kProd.x = fScalar*x;
106            kProd.y = fScalar*y;
107            kProd.z = fScalar*z;
108
109            return kProd;
110        }
111
112        inline Vector3 operator * ( const Vector3& rhs) const
113        {
114            Vector3 kProd;
115
116            kProd.x = rhs.x * x;
117            kProd.y = rhs.y * y;
118            kProd.z = rhs.z * z;
119
120            return kProd;
121        }
122
123        inline Vector3 operator / ( Real fScalar ) const
124        {
125            assert( fScalar != 0.0f );
126
127            Vector3 kDiv;
128
129            Real fInv = 1.0f / fScalar;
130            kDiv.x = x * fInv;
131            kDiv.y = y * fInv;
132            kDiv.z = z * fInv;
133
134            return kDiv;
135        }
136
137        inline Vector3 operator / ( const Vector3& rhs) const
138        {
139            Vector3 kDiv;
140
141            kDiv.x = x / rhs.x;
142            kDiv.y = y / rhs.y;
143            kDiv.z = z / rhs.z;
144
145            return kDiv;
146        }
147
148
149        inline Vector3 operator - () const
150        {
151            Vector3 kNeg;
152
153            kNeg.x = -x;
154            kNeg.y = -y;
155            kNeg.z = -z;
156
157            return kNeg;
158        }
159
160        inline friend Vector3 operator * ( Real fScalar, const Vector3& rkVector )
161        {
162            Vector3 kProd;
163
164            kProd.x = fScalar * rkVector.x;
165            kProd.y = fScalar * rkVector.y;
166            kProd.z = fScalar * rkVector.z;
167
168            return kProd;
169        }
170
171        // arithmetic updates
172        inline Vector3& operator += ( const Vector3& rkVector )
173        {
174            x += rkVector.x;
175            y += rkVector.y;
176            z += rkVector.z;
177
178            return *this;
179        }
180
181        inline Vector3& operator -= ( const Vector3& rkVector )
182        {
183            x -= rkVector.x;
184            y -= rkVector.y;
185            z -= rkVector.z;
186
187            return *this;
188        }
189
190        inline Vector3& operator *= ( Real fScalar )
191        {
192            x *= fScalar;
193            y *= fScalar;
194            z *= fScalar;
195            return *this;
196        }
197
198        inline Vector3& operator *= ( const Vector3& rkVector )
199        {
200            x *= rkVector.x;
201            y *= rkVector.y;
202            z *= rkVector.z;
203
204            return *this;
205        }
206
207        inline Vector3& operator /= ( Real fScalar )
208        {
209            assert( fScalar != 0.0f );
210
211            Real fInv = 1.0f / fScalar;
212
213            x *= fInv;
214            y *= fInv;
215            z *= fInv;
216
217            return *this;
218        }
219
220        inline Vector3& operator /= ( const Vector3& rkVector )
221        {
222            x /= rkVector.x;
223            y /= rkVector.y;
224            z /= rkVector.z;
225
226            return *this;
227        }
228
229
230        /** Returns the length (magnitude) of the vector.
231            @warning
232                This operation requires a square root and is expensive in
233                terms of CPU operations. If you don't need to know the exact
234                length (e.g. for just comparing lengths) use squaredLength()
235                instead.
236        */
237        inline Real length () const
238        {
239            return sqrt( x * x + y * y + z * z );
240        }
241
242        /** Returns the square of the length(magnitude) of the vector.
243            @remarks
244                This  method is for efficiency - calculating the actual
245                length of a vector requires a square root, which is expensive
246                in terms of the operations required. This method returns the
247                square of the length of the vector, i.e. the same as the
248                length but before the square root is taken. Use this if you
249                want to find the longest / shortest vector without incurring
250                the square root.
251        */
252        inline Real squaredLength () const
253        {
254            return x * x + y * y + z * z;
255        }
256
257        /** Calculates the dot (scalar) product of this vector with another.
258            @remarks
259                The dot product can be used to calculate the angle between 2
260                vectors. If both are unit vectors, the dot product is the
261                cosine of the angle; otherwise the dot product must be
262                divided by the product of the lengths of both vectors to get
263                the cosine of the angle. This result can further be used to
264                calculate the distance of a point from a plane.
265            @param
266                vec Vector with which to calculate the dot product (together
267                with this one).
268            @returns
269                A float representing the dot product value.
270        */
271        inline Real dotProduct(const Vector3& vec) const
272        {
273            return x * vec.x + y * vec.y + z * vec.z;
274        }
275
276        /** Normalises the vector.
277            @remarks
278                This method normalises the vector such that it's
279                length / magnitude is 1. The result is called a unit vector.
280            @note
281                This function will not crash for zero-sized vectors, but there
282                will be no changes made to their components.
283            @returns The previous length of the vector.
284        */
285        inline Real normalise()
286        {
287            Real fLength = sqrt( x * x + y * y + z * z );
288
289            // Will also work for zero-sized vectors, but will change nothing
290            if ( fLength > 1e-08 )
291            {
292                Real fInvLength = 1.0f / fLength;
293                x *= fInvLength;
294                y *= fInvLength;
295                z *= fInvLength;
296            }
297
298            return fLength;
299        }
300
301        /** Calculates the cross-product of 2 vectors, i.e. the vector that
302            lies perpendicular to them both.
303            @remarks
304                The cross-product is normally used to calculate the normal
305                vector of a plane, by calculating the cross-product of 2
306                non-equivalent vectors which lie on the plane (e.g. 2 edges
307                of a triangle).
308            @param
309                vec Vector which, together with this one, will be used to
310                calculate the cross-product.
311            @returns
312                A vector which is the result of the cross-product. This
313                vector will <b>NOT</b> be normalised, to maximise efficiency
314                - call Vector3::normalise on the result if you wish this to
315                be done. As for which side the resultant vector will be on, the
316                returned vector will be on the side from which the arc from 'this'
317                to rkVector is anticlockwise, e.g. UNIT_Y.crossProduct(UNIT_Z)
318                = UNIT_X, whilst UNIT_Z.crossProduct(UNIT_Y) = -UNIT_X.
319            @par
320                For a clearer explanation, look a the left and the bottom edges
321                of your monitor's screen. Assume that the first vector is the
322                left edge and the second vector is the bottom edge, both of
323                them starting from the lower-left corner of the screen. The
324                resulting vector is going to be perpendicular to both of them
325                and will go <i>inside</i> the screen, towards the cathode tube
326                (assuming you're using a CRT monitor, of course).
327        */
328        inline Vector3 crossProduct( const Vector3& rkVector ) const
329        {
330            Vector3 kCross;
331
332            kCross.x = y * rkVector.z - z * rkVector.y;
333            kCross.y = z * rkVector.x - x * rkVector.z;
334            kCross.z = x * rkVector.y - y * rkVector.x;
335
336            return kCross;
337        }
338
339        /** Returns a vector at a point half way between this and the passed
340            in vector.
341        */
342        inline Vector3 midPoint( const Vector3& vec ) const
343        {
344            return Vector3(
345                ( x + vec.x ) * 0.5f,
346                ( y + vec.y ) * 0.5f,
347                ( z + vec.z ) * 0.5f );
348        }
349
350        /** Returns true if the vector's scalar components are all greater
351            that the ones of the vector it is compared against.
352        */
353        inline bool operator < ( const Vector3& rhs ) const
354        {
355            if( x < rhs.x && y < rhs.y && z < rhs.z )
356                return true;
357            return false;
358        }
359
360        /** Returns true if the vector's scalar components are all smaller
361            that the ones of the vector it is compared against.
362        */
363        inline bool operator > ( const Vector3& rhs ) const
364        {
365            if( x > rhs.x && y > rhs.y && z > rhs.z )
366                return true;
367            return false;
368        }
369
370        /** Sets this vector's components to the minimum of its own and the
371            ones of the passed in vector.
372            @remarks
373                'Minimum' in this case means the combination of the lowest
374                value of x, y and z from both vectors. Lowest is taken just
375                numerically, not magnitude, so -1 < 0.
376        */
377        inline void makeFloor( const Vector3& cmp )
378        {
379            if( cmp.x < x ) x = cmp.x;
380            if( cmp.y < y ) y = cmp.y;
381            if( cmp.z < z ) z = cmp.z;
382        }
383
384        /** Sets this vector's components to the maximum of its own and the
385            ones of the passed in vector.
386            @remarks
387                'Maximum' in this case means the combination of the highest
388                value of x, y and z from both vectors. Highest is taken just
389                numerically, not magnitude, so 1 > -3.
390        */
391        inline void makeCeil( const Vector3& cmp )
392        {
393            if( cmp.x > x ) x = cmp.x;
394            if( cmp.y > y ) y = cmp.y;
395            if( cmp.z > z ) z = cmp.z;
396        }
397
398        /** Generates a vector perpendicular to this vector (eg an 'up' vector).
399            @remarks
400                This method will return a vector which is perpendicular to this
401                vector. There are an infinite number of possibilities but this
402                method will guarantee to generate one of them. If you need more
403                control you should use the Quaternion class.
404        */
405        inline Vector3 perpendicular(void) const
406        {
407            static const Real fSquareZero = 1e-06f * 1e-06f;
408
409            Vector3 perp = this->crossProduct( Vector3::UNIT_X );
410
411            // Check length
412            if( perp.squaredLength() < fSquareZero )
413            {
414                /* This vector is the Y axis multiplied by a scalar, so we have
415                   to use another axis.
416                */
417                perp = this->crossProduct( Vector3::UNIT_Y );
418            }
419
420            return perp;
421        }
422               
423        /** Returns true if this vector is zero length. */
424        inline bool isZeroLength(void) const
425        {
426            Real sqlen = (x * x) + (y * y) + (z * z);
427            return (sqlen < (1e-06 * 1e-06));
428
429        }
430
431        /** As normalise, except that this vector is unaffected and the
432            normalised vector is returned as a copy. */
433        inline Vector3 normalisedCopy(void) const
434        {
435            Vector3 ret = *this;
436            ret.normalise();
437            return ret;
438        }
439
440        /** Calculates a reflection vector to the plane with the given normal .
441        @remarks NB assumes 'this' is pointing AWAY FROM the plane, invert if it is not.
442        */
443        inline Vector3 reflect(const Vector3& normal)
444        {
445            return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) );
446        }
447
448        // special points
449        static const Vector3 ZERO;
450        static const Vector3 UNIT_X;
451        static const Vector3 UNIT_Y;
452        static const Vector3 UNIT_Z;
453        static const Vector3 NEGATIVE_UNIT_X;
454        static const Vector3 NEGATIVE_UNIT_Y;
455        static const Vector3 NEGATIVE_UNIT_Z;
456        static const Vector3 UNIT_SCALE;
457
458        /** Function for writing to a stream.
459        */
460        inline friend std::ostream& operator <<
461            ( std::ostream& o, const Vector3& v )
462        {
463            o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")";
464            return o;
465        }
466    };
467
468}
469#endif /* DOXYGEN_SHOULD_SKIP_THIS */
470#endif
Note: See TracBrowser for help on using the repository browser.