source: OGRE/trunk/ogrenew/OgreMain/include/OgreVector3.h @ 692

Revision 692, 22.5 KB checked in by mattausch, 19 years ago (diff)

adding ogre 1.2 and dependencies

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( const Real fX, const Real fY, const Real fZ )
58            : x( fX ), y( fY ), z( fZ )
59        {
60        }
61
62        inline explicit Vector3( const Real afCoordinate[3] )
63            : x( afCoordinate[0] ),
64              y( afCoordinate[1] ),
65              z( afCoordinate[2] )
66        {
67        }
68
69        inline explicit Vector3( const int afCoordinate[3] )
70        {
71            x = (Real)afCoordinate[0];
72            y = (Real)afCoordinate[1];
73            z = (Real)afCoordinate[2];
74        }
75
76        inline explicit Vector3( Real* const r )
77            : x( r[0] ), y( r[1] ), z( r[2] )
78        {
79        }
80
81        inline explicit Vector3( const Real scaler )
82            : x( scaler )
83            , y( scaler )
84            , z( scaler )
85        {
86        }
87
88
89        inline Vector3( const Vector3& rkVector )
90            : x( rkVector.x ), y( rkVector.y ), z( rkVector.z )
91        {
92        }
93
94                inline Real operator [] ( const size_t i ) const
95        {
96            assert( i < 3 );
97
98            return *(&x+i);
99        }
100
101                inline Real& operator [] ( const size_t i )
102        {
103            assert( i < 3 );
104
105            return *(&x+i);
106        }
107
108        /** Assigns the value of the other vector.
109            @param
110                rkVector The other vector
111        */
112        inline Vector3& operator = ( const Vector3& rkVector )
113        {
114            x = rkVector.x;
115            y = rkVector.y;
116            z = rkVector.z;
117
118            return *this;
119        }
120
121        inline Vector3& operator = ( const Real fScaler )
122        {
123            x = fScaler;
124            y = fScaler;
125            z = fScaler;
126
127            return *this;
128        }
129
130        inline bool operator == ( const Vector3& rkVector ) const
131        {
132            return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
133        }
134
135        inline bool operator != ( const Vector3& rkVector ) const
136        {
137            return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
138        }
139
140        // arithmetic operations
141        inline Vector3 operator + ( const Vector3& rkVector ) const
142        {
143            Vector3 kSum;
144
145            kSum.x = x + rkVector.x;
146            kSum.y = y + rkVector.y;
147            kSum.z = z + rkVector.z;
148
149            return kSum;
150        }
151
152        inline Vector3 operator - ( const Vector3& rkVector ) const
153        {
154            Vector3 kDiff;
155
156            kDiff.x = x - rkVector.x;
157            kDiff.y = y - rkVector.y;
158            kDiff.z = z - rkVector.z;
159
160            return kDiff;
161        }
162
163        inline Vector3 operator * ( const Real fScalar ) const
164        {
165            Vector3 kProd;
166
167            kProd.x = fScalar*x;
168            kProd.y = fScalar*y;
169            kProd.z = fScalar*z;
170
171            return kProd;
172        }
173
174        inline Vector3 operator * ( const Vector3& rhs) const
175        {
176            Vector3 kProd;
177
178            kProd.x = rhs.x * x;
179            kProd.y = rhs.y * y;
180            kProd.z = rhs.z * z;
181
182            return kProd;
183        }
184
185        inline Vector3 operator / ( const Real fScalar ) const
186        {
187            assert( fScalar != 0.0 );
188
189            Vector3 kDiv;
190
191            Real fInv = 1.0 / fScalar;
192            kDiv.x = x * fInv;
193            kDiv.y = y * fInv;
194            kDiv.z = z * fInv;
195
196            return kDiv;
197        }
198
199        inline Vector3 operator / ( const Vector3& rhs) const
200        {
201            Vector3 kDiv;
202
203            kDiv.x = x / rhs.x;
204            kDiv.y = y / rhs.y;
205            kDiv.z = z / rhs.z;
206
207            return kDiv;
208        }
209
210
211        inline Vector3 operator - () const
212        {
213            Vector3 kNeg;
214
215            kNeg.x = -x;
216            kNeg.y = -y;
217            kNeg.z = -z;
218
219            return kNeg;
220        }
221
222        // overloaded operators to help Vector3
223        inline friend Vector3 operator * ( const Real fScalar, const Vector3& rkVector )
224        {
225            Vector3 kProd;
226
227            kProd.x = fScalar * rkVector.x;
228            kProd.y = fScalar * rkVector.y;
229            kProd.z = fScalar * rkVector.z;
230
231            return kProd;
232        }
233
234        inline friend Vector3 operator + (const Vector3& lhs, const Real rhs)
235        {
236            Vector3 ret(rhs);
237            return ret += lhs;
238        }
239
240        inline friend Vector3 operator + (const Real lhs, const Vector3& rhs)
241        {
242            Vector3 ret(lhs);
243            return ret += rhs;
244        }
245
246        inline friend Vector3 operator - (const Vector3& lhs, const Real rhs)
247        {
248            return lhs - Vector3(rhs);
249        }
250
251        inline friend Vector3 operator - (const Real lhs, const Vector3& rhs)
252        {
253            Vector3 ret(lhs);
254            return ret -= rhs;
255        }
256
257        // arithmetic updates
258        inline Vector3& operator += ( const Vector3& rkVector )
259        {
260            x += rkVector.x;
261            y += rkVector.y;
262            z += rkVector.z;
263
264            return *this;
265        }
266
267        inline Vector3& operator += ( const Real fScalar )
268        {
269            x += fScalar;
270            y += fScalar;
271            z += fScalar;
272            return *this;
273        }
274
275        inline Vector3& operator -= ( const Vector3& rkVector )
276        {
277            x -= rkVector.x;
278            y -= rkVector.y;
279            z -= rkVector.z;
280
281            return *this;
282        }
283
284        inline Vector3& operator -= ( const Real fScalar )
285        {
286            x -= fScalar;
287            y -= fScalar;
288            z -= fScalar;
289            return *this;
290        }
291
292        inline Vector3& operator *= ( const Real fScalar )
293        {
294            x *= fScalar;
295            y *= fScalar;
296            z *= fScalar;
297            return *this;
298        }
299
300        inline Vector3& operator *= ( const Vector3& rkVector )
301        {
302            x *= rkVector.x;
303            y *= rkVector.y;
304            z *= rkVector.z;
305
306            return *this;
307        }
308
309        inline Vector3& operator /= ( const Real fScalar )
310        {
311            assert( fScalar != 0.0 );
312
313            Real fInv = 1.0 / fScalar;
314
315            x *= fInv;
316            y *= fInv;
317            z *= fInv;
318
319            return *this;
320        }
321
322        inline Vector3& operator /= ( const Vector3& rkVector )
323        {
324            x /= rkVector.x;
325            y /= rkVector.y;
326            z /= rkVector.z;
327
328            return *this;
329        }
330
331
332        /** Returns the length (magnitude) of the vector.
333            @warning
334                This operation requires a square root and is expensive in
335                terms of CPU operations. If you don't need to know the exact
336                length (e.g. for just comparing lengths) use squaredLength()
337                instead.
338        */
339        inline Real length () const
340        {
341            return Math::Sqrt( x * x + y * y + z * z );
342        }
343
344        /** Returns the square of the length(magnitude) of the vector.
345            @remarks
346                This  method is for efficiency - calculating the actual
347                length of a vector requires a square root, which is expensive
348                in terms of the operations required. This method returns the
349                square of the length of the vector, i.e. the same as the
350                length but before the square root is taken. Use this if you
351                want to find the longest / shortest vector without incurring
352                the square root.
353        */
354        inline Real squaredLength () const
355        {
356            return x * x + y * y + z * z;
357        }
358
359        /** Calculates the dot (scalar) product of this vector with another.
360            @remarks
361                The dot product can be used to calculate the angle between 2
362                vectors. If both are unit vectors, the dot product is the
363                cosine of the angle; otherwise the dot product must be
364                divided by the product of the lengths of both vectors to get
365                the cosine of the angle. This result can further be used to
366                calculate the distance of a point from a plane.
367            @param
368                vec Vector with which to calculate the dot product (together
369                with this one).
370            @returns
371                A float representing the dot product value.
372        */
373        inline Real dotProduct(const Vector3& vec) const
374        {
375            return x * vec.x + y * vec.y + z * vec.z;
376        }
377
378        /** Normalises the vector.
379            @remarks
380                This method normalises the vector such that it's
381                length / magnitude is 1. The result is called a unit vector.
382            @note
383                This function will not crash for zero-sized vectors, but there
384                will be no changes made to their components.
385            @returns The previous length of the vector.
386        */
387        inline Real normalise()
388        {
389            Real fLength = Math::Sqrt( x * x + y * y + z * z );
390
391            // Will also work for zero-sized vectors, but will change nothing
392            if ( fLength > 1e-08 )
393            {
394                Real fInvLength = 1.0 / fLength;
395                x *= fInvLength;
396                y *= fInvLength;
397                z *= fInvLength;
398            }
399
400            return fLength;
401        }
402
403        /** Calculates the cross-product of 2 vectors, i.e. the vector that
404            lies perpendicular to them both.
405            @remarks
406                The cross-product is normally used to calculate the normal
407                vector of a plane, by calculating the cross-product of 2
408                non-equivalent vectors which lie on the plane (e.g. 2 edges
409                of a triangle).
410            @param
411                vec Vector which, together with this one, will be used to
412                calculate the cross-product.
413            @returns
414                A vector which is the result of the cross-product. This
415                vector will <b>NOT</b> be normalised, to maximise efficiency
416                - call Vector3::normalise on the result if you wish this to
417                be done. As for which side the resultant vector will be on, the
418                returned vector will be on the side from which the arc from 'this'
419                to rkVector is anticlockwise, e.g. UNIT_Y.crossProduct(UNIT_Z)
420                = UNIT_X, whilst UNIT_Z.crossProduct(UNIT_Y) = -UNIT_X.
421                                This is because OGRE uses a right-handed coordinate system.
422            @par
423                For a clearer explanation, look a the left and the bottom edges
424                of your monitor's screen. Assume that the first vector is the
425                left edge and the second vector is the bottom edge, both of
426                them starting from the lower-left corner of the screen. The
427                resulting vector is going to be perpendicular to both of them
428                and will go <i>inside</i> the screen, towards the cathode tube
429                (assuming you're using a CRT monitor, of course).
430        */
431        inline Vector3 crossProduct( const Vector3& rkVector ) const
432        {
433            Vector3 kCross;
434
435            kCross.x = y * rkVector.z - z * rkVector.y;
436            kCross.y = z * rkVector.x - x * rkVector.z;
437            kCross.z = x * rkVector.y - y * rkVector.x;
438
439            return kCross;
440        }
441
442        /** Returns a vector at a point half way between this and the passed
443            in vector.
444        */
445        inline Vector3 midPoint( const Vector3& vec ) const
446        {
447            return Vector3(
448                ( x + vec.x ) * 0.5,
449                ( y + vec.y ) * 0.5,
450                ( z + vec.z ) * 0.5 );
451        }
452
453        /** Returns true if the vector's scalar components are all greater
454            that the ones of the vector it is compared against.
455        */
456        inline bool operator < ( const Vector3& rhs ) const
457        {
458            if( x < rhs.x && y < rhs.y && z < rhs.z )
459                return true;
460            return false;
461        }
462
463        /** Returns true if the vector's scalar components are all smaller
464            that the ones of the vector it is compared against.
465        */
466        inline bool operator > ( const Vector3& rhs ) const
467        {
468            if( x > rhs.x && y > rhs.y && z > rhs.z )
469                return true;
470            return false;
471        }
472
473        /** Sets this vector's components to the minimum of its own and the
474            ones of the passed in vector.
475            @remarks
476                'Minimum' in this case means the combination of the lowest
477                value of x, y and z from both vectors. Lowest is taken just
478                numerically, not magnitude, so -1 < 0.
479        */
480        inline void makeFloor( const Vector3& cmp )
481        {
482            if( cmp.x < x ) x = cmp.x;
483            if( cmp.y < y ) y = cmp.y;
484            if( cmp.z < z ) z = cmp.z;
485        }
486
487        /** Sets this vector's components to the maximum of its own and the
488            ones of the passed in vector.
489            @remarks
490                'Maximum' in this case means the combination of the highest
491                value of x, y and z from both vectors. Highest is taken just
492                numerically, not magnitude, so 1 > -3.
493        */
494        inline void makeCeil( const Vector3& cmp )
495        {
496            if( cmp.x > x ) x = cmp.x;
497            if( cmp.y > y ) y = cmp.y;
498            if( cmp.z > z ) z = cmp.z;
499        }
500
501        /** Generates a vector perpendicular to this vector (eg an 'up' vector).
502            @remarks
503                This method will return a vector which is perpendicular to this
504                vector. There are an infinite number of possibilities but this
505                method will guarantee to generate one of them. If you need more
506                control you should use the Quaternion class.
507        */
508        inline Vector3 perpendicular(void) const
509        {
510            static const Real fSquareZero = 1e-06 * 1e-06;
511
512            Vector3 perp = this->crossProduct( Vector3::UNIT_X );
513
514            // Check length
515            if( perp.squaredLength() < fSquareZero )
516            {
517                /* This vector is the Y axis multiplied by a scalar, so we have
518                   to use another axis.
519                */
520                perp = this->crossProduct( Vector3::UNIT_Y );
521            }
522
523            return perp;
524        }
525        /** Generates a new random vector which deviates from this vector by a
526            given angle in a random direction.
527            @remarks
528                This method assumes that the random number generator has already
529                been seeded appropriately.
530            @param
531                angle The angle at which to deviate
532            @param
533                up Any vector perpendicular to this one (which could generated
534                by cross-product of this vector and any other non-colinear
535                vector). If you choose not to provide this the function will
536                derive one on it's own, however if you provide one yourself the
537                function will be faster (this allows you to reuse up vectors if
538                you call this method more than once)
539            @returns
540                A random vector which deviates from this vector by angle. This
541                vector will not be normalised, normalise it if you wish
542                afterwards.
543        */
544        inline Vector3 randomDeviant(
545            const Radian& angle,
546            const Vector3& up = Vector3::ZERO ) const
547        {
548            Vector3 newUp;
549
550            if (up == Vector3::ZERO)
551            {
552                // Generate an up vector
553                newUp = this->perpendicular();
554            }
555            else
556            {
557                newUp = up;
558            }
559
560            // Rotate up vector by random amount around this
561            Quaternion q;
562            q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this );
563            newUp = q * newUp;
564
565            // Finally rotate this by given angle around randomised up
566            q.FromAngleAxis( angle, newUp );
567            return q * (*this);
568        }
569#ifndef OGRE_FORCE_ANGLE_TYPES
570        inline Vector3 randomDeviant(
571            Real angle,
572            const Vector3& up = Vector3::ZERO ) const
573        {
574            return randomDeviant ( Radian(angle), up );
575        }
576#endif//OGRE_FORCE_ANGLE_TYPES
577
578        /** Gets the shortest arc quaternion to rotate this vector to the destination
579            vector.
580        @remarks
581            If you call this with a dest vector that is close to the inverse
582            of this vector, we will rotate 180 degrees around the 'fallbackAxis'
583                        (if specified, or a generated axis if not) since in this case
584                        ANY axis of rotation is valid.
585        */
586        Quaternion getRotationTo(const Vector3& dest,
587                        const Vector3& fallbackAxis = Vector3::ZERO) const
588        {
589            // Based on Stan Melax's article in Game Programming Gems
590            Quaternion q;
591            // Copy, since cannot modify local
592            Vector3 v0 = *this;
593            Vector3 v1 = dest;
594            v0.normalise();
595            v1.normalise();
596
597            Vector3 c = v0.crossProduct(v1);
598
599            Real d = v0.dotProduct(v1);
600            // If dot == 1, vectors are the same
601            if (d >= 1.0f)
602            {
603                return Quaternion::IDENTITY;
604            }
605            Real s = Math::Sqrt( (1+d)*2 );
606                        if (s < 1e-6f)
607                        {
608                                if (fallbackAxis != Vector3::ZERO)
609                                {
610                                        // rotate 180 degrees about the fallback axis
611                                        q.FromAngleAxis(Radian(Math::PI), fallbackAxis);
612                                }
613                                else
614                                {
615                                        // Generate an axis
616                                        Vector3 axis = Vector3::UNIT_X.crossProduct(*this);
617                                        if (axis.isZeroLength()) // pick another if colinear
618                                                axis = Vector3::UNIT_Y.crossProduct(*this);
619                                        axis.normalise();
620                                        q.FromAngleAxis(Radian(Math::PI), axis);
621                                }
622                        }
623                        else
624                        {
625                    Real invs = 1 / s;
626
627                q.x = c.x * invs;
628                    q.y = c.y * invs;
629                q.z = c.z * invs;
630                q.w = s * 0.5;
631                        }
632            return q;
633        }
634
635        /** Returns true if this vector is zero length. */
636        inline bool isZeroLength(void) const
637        {
638            Real sqlen = (x * x) + (y * y) + (z * z);
639            return (sqlen < (1e-06 * 1e-06));
640
641        }
642
643        /** As normalise, except that this vector is unaffected and the
644            normalised vector is returned as a copy. */
645        inline Vector3 normalisedCopy(void) const
646        {
647            Vector3 ret = *this;
648            ret.normalise();
649            return ret;
650        }
651
652        /** Calculates a reflection vector to the plane with the given normal .
653        @remarks NB assumes 'this' is pointing AWAY FROM the plane, invert if it is not.
654        */
655        inline Vector3 reflect(const Vector3& normal) const
656        {
657            return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) );
658        }
659
660                /** Returns whether this vector is within a positional tolerance
661                        of another vector.
662                @param rhs The vector to compare with
663                @param tolerance The amount that each element of the vector may vary by
664                        and still be considered equal
665                */
666                inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const
667                {
668                        return Math::RealEqual(x, rhs.x, tolerance) &&
669                                Math::RealEqual(y, rhs.y, tolerance) &&
670                                Math::RealEqual(z, rhs.z, tolerance);
671
672                }
673                /** Returns whether this vector is within a directional tolerance
674                        of another vector.
675                @param rhs The vector to compare with
676                @param tolerance The maximum angle by which the vectors may vary and
677                        still be considered equal
678                */
679                inline bool directionEquals(const Vector3& rhs,
680                        const Radian& tolerance) const
681                {
682                        Real dot = dotProduct(rhs);
683                        Radian angle = Math::ACos(dot);
684
685                        return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians();
686
687                }
688
689        // special points
690        static const Vector3 ZERO;
691        static const Vector3 UNIT_X;
692        static const Vector3 UNIT_Y;
693        static const Vector3 UNIT_Z;
694        static const Vector3 NEGATIVE_UNIT_X;
695        static const Vector3 NEGATIVE_UNIT_Y;
696        static const Vector3 NEGATIVE_UNIT_Z;
697        static const Vector3 UNIT_SCALE;
698
699        /** Function for writing to a stream.
700        */
701        inline _OgreExport friend std::ostream& operator <<
702            ( std::ostream& o, const Vector3& v )
703        {
704            o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")";
705            return o;
706        }
707    };
708
709}
710#endif
Note: See TracBrowser for help on using the repository browser.