Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/include/OgreVector3.h @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

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