source: GTP/trunk/App/Demos/Geom/include/OgreVector3.h @ 1030

Revision 1030, 20.5 KB checked in by gumbau, 18 years ago (diff)

Ogre Stuff initial import

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#ifndef __Vector3_H__
26#define __Vector3_H__
27
28#include "OgrePrerequisites.h"
29#include "OgreMath.h"
30#include "OgreQuaternion.h"
31
32namespace Ogre
33{
34
35    /** Standard 3-dimensional vector.
36        @remarks
37            A direction in 3D space represented as distances along the 3
38            orthoganal axes (x, y, z). Note that positions, directions and
39            scaling factors can be represented by a vector, depending on how
40            you interpret the values.
41    */
42    class _OgreExport Vector3
43    {
44    public:
45        union {
46            struct {
47                Real x, y, z;       
48            };
49            Real val[3];
50        };
51
52    public:
53        inline Vector3()
54        {
55        }
56
57        inline Vector3( Real fX, Real fY, Real fZ )
58            : x( fX ), y( fY ), z( fZ )
59        {
60        }
61
62        inline Vector3( Real afCoordinate[3] )
63            : x( afCoordinate[0] ),
64              y( afCoordinate[1] ),
65              z( afCoordinate[2] )
66        {
67        }
68
69        inline Vector3( int afCoordinate[3] )
70        {
71            x = (Real)afCoordinate[0];
72            y = (Real)afCoordinate[1];
73            z = (Real)afCoordinate[2];
74        }
75
76        inline Vector3( const Real* const r )
77            : x( r[0] ), y( r[1] ), z( r[2] )
78        {
79        }
80
81        inline Vector3( const Vector3& rkVector )
82            : x( rkVector.x ), y( rkVector.y ), z( rkVector.z )
83        {
84        }
85
86                inline Real operator [] ( size_t i ) const
87        {
88            assert( i < 3 );
89
90            return *(&x+i);
91        }
92
93                inline Real& operator [] ( size_t i )
94        {
95            assert( i < 3 );
96
97            return *(&x+i);
98        }
99
100        /** Assigns the value of the other vector.
101            @param
102                rkVector The other vector
103        */
104        inline Vector3& operator = ( const Vector3& rkVector )
105        {
106            x = rkVector.x;
107            y = rkVector.y;
108            z = rkVector.z;           
109
110            return *this;
111        }
112
113        inline bool operator == ( const Vector3& rkVector ) const
114        {
115            return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
116        }
117
118        inline bool operator != ( const Vector3& rkVector ) const
119        {
120            return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
121        }
122
123        // arithmetic operations
124        inline Vector3 operator + ( const Vector3& rkVector ) const
125        {
126            Vector3 kSum;
127
128            kSum.x = x + rkVector.x;
129            kSum.y = y + rkVector.y;
130            kSum.z = z + rkVector.z;
131
132            return kSum;
133        }
134
135        inline Vector3 operator - ( const Vector3& rkVector ) const
136        {
137            Vector3 kDiff;
138
139            kDiff.x = x - rkVector.x;
140            kDiff.y = y - rkVector.y;
141            kDiff.z = z - rkVector.z;
142
143            return kDiff;
144        }
145
146        inline Vector3 operator * ( Real fScalar ) const
147        {
148            Vector3 kProd;
149
150            kProd.x = fScalar*x;
151            kProd.y = fScalar*y;
152            kProd.z = fScalar*z;
153
154            return kProd;
155        }
156
157        inline Vector3 operator * ( const Vector3& rhs) const
158        {
159            Vector3 kProd;
160
161            kProd.x = rhs.x * x;
162            kProd.y = rhs.y * y;
163            kProd.z = rhs.z * z;
164
165            return kProd;
166        }
167
168        inline Vector3 operator / ( Real fScalar ) const
169        {
170            assert( fScalar != 0.0 );
171
172            Vector3 kDiv;
173
174            Real fInv = 1.0 / fScalar;
175            kDiv.x = x * fInv;
176            kDiv.y = y * fInv;
177            kDiv.z = z * fInv;
178
179            return kDiv;
180        }
181
182        inline Vector3 operator / ( const Vector3& rhs) const
183        {
184            Vector3 kDiv;
185
186            kDiv.x = x / rhs.x;
187            kDiv.y = y / rhs.y;
188            kDiv.z = z / rhs.z;
189
190            return kDiv;
191        }
192
193
194        inline Vector3 operator - () const
195        {
196            Vector3 kNeg;
197
198            kNeg.x = -x;
199            kNeg.y = -y;
200            kNeg.z = -z;
201
202            return kNeg;
203        }
204
205        inline friend Vector3 operator * ( Real fScalar, const Vector3& rkVector )
206        {
207            Vector3 kProd;
208
209            kProd.x = fScalar * rkVector.x;
210            kProd.y = fScalar * rkVector.y;
211            kProd.z = fScalar * rkVector.z;
212
213            return kProd;
214        }
215
216        // arithmetic updates
217        inline Vector3& operator += ( const Vector3& rkVector )
218        {
219            x += rkVector.x;
220            y += rkVector.y;
221            z += rkVector.z;
222
223            return *this;
224        }
225
226        inline Vector3& operator -= ( const Vector3& rkVector )
227        {
228            x -= rkVector.x;
229            y -= rkVector.y;
230            z -= rkVector.z;
231
232            return *this;
233        }
234
235        inline Vector3& operator *= ( Real fScalar )
236        {
237            x *= fScalar;
238            y *= fScalar;
239            z *= fScalar;
240            return *this;
241        }
242
243        inline Vector3& operator *= ( const Vector3& rkVector )
244        {
245            x *= rkVector.x;
246            y *= rkVector.y;
247            z *= rkVector.z;
248
249            return *this;
250        }
251
252        inline Vector3& operator /= ( Real fScalar )
253        {
254            assert( fScalar != 0.0 );
255
256            Real fInv = 1.0 / fScalar;
257
258            x *= fInv;
259            y *= fInv;
260            z *= fInv;
261
262            return *this;
263        }
264
265        inline Vector3& operator /= ( const Vector3& rkVector )
266        {
267            x /= rkVector.x;
268            y /= rkVector.y;
269            z /= rkVector.z;
270
271            return *this;
272        }
273
274
275        /** Returns the length (magnitude) of the vector.
276            @warning
277                This operation requires a square root and is expensive in
278                terms of CPU operations. If you don't need to know the exact
279                length (e.g. for just comparing lengths) use squaredLength()
280                instead.
281        */
282        inline Real length () const
283        {
284            return Math::Sqrt( x * x + y * y + z * z );
285        }
286
287        /** Returns the square of the length(magnitude) of the vector.
288            @remarks
289                This  method is for efficiency - calculating the actual
290                length of a vector requires a square root, which is expensive
291                in terms of the operations required. This method returns the
292                square of the length of the vector, i.e. the same as the
293                length but before the square root is taken. Use this if you
294                want to find the longest / shortest vector without incurring
295                the square root.
296        */
297        inline Real squaredLength () const
298        {
299            return x * x + y * y + z * z;
300        }
301
302        /** Calculates the dot (scalar) product of this vector with another.
303            @remarks
304                The dot product can be used to calculate the angle between 2
305                vectors. If both are unit vectors, the dot product is the
306                cosine of the angle; otherwise the dot product must be
307                divided by the product of the lengths of both vectors to get
308                the cosine of the angle. This result can further be used to
309                calculate the distance of a point from a plane.
310            @param
311                vec Vector with which to calculate the dot product (together
312                with this one).
313            @returns
314                A float representing the dot product value.
315        */
316        inline Real dotProduct(const Vector3& vec) const
317        {
318            return x * vec.x + y * vec.y + z * vec.z;
319        }
320
321        /** Normalises the vector.
322            @remarks
323                This method normalises the vector such that it's
324                length / magnitude is 1. The result is called a unit vector.
325            @note
326                This function will not crash for zero-sized vectors, but there
327                will be no changes made to their components.
328            @returns The previous length of the vector.
329        */
330        inline Real normalise()
331        {
332            Real fLength = Math::Sqrt( x * x + y * y + z * z );
333
334            // Will also work for zero-sized vectors, but will change nothing
335            if ( fLength > 1e-08 )
336            {
337                Real fInvLength = 1.0 / fLength;
338                x *= fInvLength;
339                y *= fInvLength;
340                z *= fInvLength;
341            }
342
343            return fLength;
344        }
345
346        /** Calculates the cross-product of 2 vectors, i.e. the vector that
347            lies perpendicular to them both.
348            @remarks
349                The cross-product is normally used to calculate the normal
350                vector of a plane, by calculating the cross-product of 2
351                non-equivalent vectors which lie on the plane (e.g. 2 edges
352                of a triangle).
353            @param
354                vec Vector which, together with this one, will be used to
355                calculate the cross-product.
356            @returns
357                A vector which is the result of the cross-product. This
358                vector will <b>NOT</b> be normalised, to maximise efficiency
359                - call Vector3::normalise on the result if you wish this to
360                be done. As for which side the resultant vector will be on, the
361                returned vector will be on the side from which the arc from 'this'
362                to rkVector is anticlockwise, e.g. UNIT_Y.crossProduct(UNIT_Z)
363                = UNIT_X, whilst UNIT_Z.crossProduct(UNIT_Y) = -UNIT_X.
364            @par
365                For a clearer explanation, look a the left and the bottom edges
366                of your monitor's screen. Assume that the first vector is the
367                left edge and the second vector is the bottom edge, both of
368                them starting from the lower-left corner of the screen. The
369                resulting vector is going to be perpendicular to both of them
370                and will go <i>inside</i> the screen, towards the cathode tube
371                (assuming you're using a CRT monitor, of course).
372        */
373        inline Vector3 crossProduct( const Vector3& rkVector ) const
374        {
375            Vector3 kCross;
376
377            kCross.x = y * rkVector.z - z * rkVector.y;
378            kCross.y = z * rkVector.x - x * rkVector.z;
379            kCross.z = x * rkVector.y - y * rkVector.x;
380
381            return kCross;
382        }
383
384        /** Returns a vector at a point half way between this and the passed
385            in vector.
386        */
387        inline Vector3 midPoint( const Vector3& vec ) const
388        {
389            return Vector3(
390                ( x + vec.x ) * 0.5,
391                ( y + vec.y ) * 0.5,
392                ( z + vec.z ) * 0.5 );
393        }
394
395        /** Returns true if the vector's scalar components are all greater
396            that the ones of the vector it is compared against.
397        */
398        inline bool operator < ( const Vector3& rhs ) const
399        {
400            if( x < rhs.x && y < rhs.y && z < rhs.z )
401                return true;
402            return false;
403        }
404
405        /** Returns true if the vector's scalar components are all smaller
406            that the ones of the vector it is compared against.
407        */
408        inline bool operator > ( const Vector3& rhs ) const
409        {
410            if( x > rhs.x && y > rhs.y && z > rhs.z )
411                return true;
412            return false;
413        }
414
415        /** Sets this vector's components to the minimum of its own and the
416            ones of the passed in vector.
417            @remarks
418                'Minimum' in this case means the combination of the lowest
419                value of x, y and z from both vectors. Lowest is taken just
420                numerically, not magnitude, so -1 < 0.
421        */
422        inline void makeFloor( const Vector3& cmp )
423        {
424            if( cmp.x < x ) x = cmp.x;
425            if( cmp.y < y ) y = cmp.y;
426            if( cmp.z < z ) z = cmp.z;
427        }
428
429        /** Sets this vector's components to the maximum of its own and the
430            ones of the passed in vector.
431            @remarks
432                'Maximum' in this case means the combination of the highest
433                value of x, y and z from both vectors. Highest is taken just
434                numerically, not magnitude, so 1 > -3.
435        */
436        inline void makeCeil( const Vector3& cmp )
437        {
438            if( cmp.x > x ) x = cmp.x;
439            if( cmp.y > y ) y = cmp.y;
440            if( cmp.z > z ) z = cmp.z;
441        }
442
443        /** Generates a vector perpendicular to this vector (eg an 'up' vector).
444            @remarks
445                This method will return a vector which is perpendicular to this
446                vector. There are an infinite number of possibilities but this
447                method will guarantee to generate one of them. If you need more
448                control you should use the Quaternion class.
449        */
450        inline Vector3 perpendicular(void) const
451        {
452            static const Real fSquareZero = 1e-06 * 1e-06;
453
454            Vector3 perp = this->crossProduct( Vector3::UNIT_X );
455
456            // Check length
457            if( perp.squaredLength() < fSquareZero )
458            {
459                /* This vector is the Y axis multiplied by a scalar, so we have
460                   to use another axis.
461                */
462                perp = this->crossProduct( Vector3::UNIT_Y );
463            }
464
465            return perp;
466        }
467        /** Generates a new random vector which deviates from this vector by a
468            given angle in a random direction.
469            @remarks
470                This method assumes that the random number generator has already
471                been seeded appropriately.
472            @param
473                angle The angle at which to deviate
474            @param
475                up Any vector perpendicular to this one (which could generated
476                by cross-product of this vector and any other non-colinear
477                vector). If you choose not to provide this the function will
478                derive one on it's own, however if you provide one yourself the
479                function will be faster (this allows you to reuse up vectors if
480                you call this method more than once)
481            @returns
482                A random vector which deviates from this vector by angle. This
483                vector will not be normalised, normalise it if you wish
484                afterwards.
485        */
486        inline Vector3 randomDeviant(
487            const Radian& angle,
488            const Vector3& up = Vector3::ZERO ) const
489        {
490            Vector3 newUp;
491
492            if (up == Vector3::ZERO)
493            {
494                // Generate an up vector
495                newUp = this->perpendicular();
496            }
497            else
498            {
499                newUp = up;
500            }
501
502            // Rotate up vector by random amount around this
503            Quaternion q;
504            q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this );
505            newUp = q * newUp;
506
507            // Finally rotate this by given angle around randomised up
508            q.FromAngleAxis( angle, newUp );
509            return q * (*this);
510        }
511#ifndef OGRE_FORCE_ANGLE_TYPES
512        inline Vector3 randomDeviant(
513            Real angle,
514            const Vector3& up = Vector3::ZERO ) const
515        {
516            return randomDeviant ( Radian(angle), up );
517        }
518#endif//OGRE_FORCE_ANGLE_TYPES
519
520        /** Gets the shortest arc quaternion to rotate this vector to the destination
521            vector.
522        @remarks
523            Don't call this if you think the dest vector can be close to the inverse
524            of this vector, since then ANY axis of rotation is ok.
525        */
526        Quaternion getRotationTo(const Vector3& dest) const
527        {
528            // Based on Stan Melax's article in Game Programming Gems
529            Quaternion q;
530            // Copy, since cannot modify local
531            Vector3 v0 = *this;
532            Vector3 v1 = dest;
533            v0.normalise();
534            v1.normalise();
535
536            Vector3 c = v0.crossProduct(v1);
537
538            // NB if the crossProduct approaches zero, we get unstable because ANY axis will do
539            // when v0 == -v1
540            Real d = v0.dotProduct(v1);
541            // If dot == 1, vectors are the same
542            if (d >= 1.0f)
543            {
544                return Quaternion::IDENTITY;
545            }
546            Real s = Math::Sqrt( (1+d)*2 );
547            assert (s != 0 && "Divide by zero!");
548            Real invs = 1 / s;
549
550
551            q.x = c.x * invs;
552            q.y = c.y * invs;
553            q.z = c.z * invs;
554            q.w = s * 0.5;
555            return q;
556        }
557
558        /** Returns true if this vector is zero length. */
559        inline bool isZeroLength(void) const
560        {
561            Real sqlen = (x * x) + (y * y) + (z * z);
562            return (sqlen < (1e-06 * 1e-06));
563
564        }
565
566        /** As normalise, except that this vector is unaffected and the
567            normalised vector is returned as a copy. */
568        inline Vector3 normalisedCopy(void) const
569        {
570            Vector3 ret = *this;
571            ret.normalise();
572            return ret;
573        }
574
575        /** Calculates a reflection vector to the plane with the given normal .
576        @remarks NB assumes 'this' is pointing AWAY FROM the plane, invert if it is not.
577        */
578        inline Vector3 reflect(const Vector3& normal) const
579        {
580            return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) );
581        }
582
583                /** Returns whether this vector is within a positional tolerance
584                        of another vector.
585                @param rhs The vector to compare with
586                @param tolerance The amount that each element of the vector may vary by
587                        and still be considered equal
588                */
589                inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const
590                {
591                        return Math::RealEqual(x, rhs.x, tolerance) &&
592                                Math::RealEqual(y, rhs.y, tolerance) &&
593                                Math::RealEqual(z, rhs.z, tolerance);
594                       
595                }
596                /** Returns whether this vector is within a directional tolerance
597                        of another vector.
598                @param rhs The vector to compare with
599                @param tolerance The maximum angle by which the vectors may vary and
600                        still be considered equal
601                */
602                inline bool directionEquals(const Vector3& rhs,
603                        const Radian& tolerance) const
604                {
605                        Real dot = dotProduct(rhs);
606                        Radian angle = Math::ACos(dot);
607
608                        return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians();
609                       
610                }
611
612        // special points
613        static const Vector3 ZERO;
614        static const Vector3 UNIT_X;
615        static const Vector3 UNIT_Y;
616        static const Vector3 UNIT_Z;
617        static const Vector3 NEGATIVE_UNIT_X;
618        static const Vector3 NEGATIVE_UNIT_Y;
619        static const Vector3 NEGATIVE_UNIT_Z;
620        static const Vector3 UNIT_SCALE;
621
622        /** Function for writing to a stream.
623        */
624        inline _OgreExport friend std::ostream& operator <<
625            ( std::ostream& o, const Vector3& v )
626        {
627            o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")";
628            return o;
629        }
630    };
631
632}
633#endif
Note: See TracBrowser for help on using the repository browser.