OgreVector3.h
Go to the documentation of this file.
1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4  (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org/
6 
7 Copyright (c) 2000-2013 Torus Knot Software Ltd
8 
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
15 
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 THE SOFTWARE.
26 -----------------------------------------------------------------------------
27 */
28 #ifndef __Vector3_H__
29 #define __Vector3_H__
30 
31 #include "OgrePrerequisites.h"
32 #include "OgreMath.h"
33 #include "OgreQuaternion.h"
34 
35 namespace Ogre
36 {
37 
52  {
53  public:
54  Real x, y, z;
55 
56  public:
57  inline Vector3()
58  {
59  }
60 
61  inline Vector3( const Real fX, const Real fY, const Real fZ )
62  : x( fX ), y( fY ), z( fZ )
63  {
64  }
65 
66  inline explicit Vector3( const Real afCoordinate[3] )
67  : x( afCoordinate[0] ),
68  y( afCoordinate[1] ),
69  z( afCoordinate[2] )
70  {
71  }
72 
73  inline explicit Vector3( const int afCoordinate[3] )
74  {
75  x = (Real)afCoordinate[0];
76  y = (Real)afCoordinate[1];
77  z = (Real)afCoordinate[2];
78  }
79 
80  inline explicit Vector3( Real* const r )
81  : x( r[0] ), y( r[1] ), z( r[2] )
82  {
83  }
84 
85  inline explicit Vector3( const Real scaler )
86  : x( scaler )
87  , y( scaler )
88  , z( scaler )
89  {
90  }
91 
92 
95  inline void swap(Vector3& other)
96  {
97  std::swap(x, other.x);
98  std::swap(y, other.y);
99  std::swap(z, other.z);
100  }
101 
102  inline Real operator [] ( const size_t i ) const
103  {
104  assert( i < 3 );
105 
106  return *(&x+i);
107  }
108 
109  inline Real& operator [] ( const size_t i )
110  {
111  assert( i < 3 );
112 
113  return *(&x+i);
114  }
116  inline Real* ptr()
117  {
118  return &x;
119  }
121  inline const Real* ptr() const
122  {
123  return &x;
124  }
125 
130  inline Vector3& operator = ( const Vector3& rkVector )
131  {
132  x = rkVector.x;
133  y = rkVector.y;
134  z = rkVector.z;
135 
136  return *this;
137  }
138 
139  inline Vector3& operator = ( const Real fScaler )
140  {
141  x = fScaler;
142  y = fScaler;
143  z = fScaler;
144 
145  return *this;
146  }
147 
148  inline bool operator == ( const Vector3& rkVector ) const
149  {
150  return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
151  }
152 
153  inline bool operator != ( const Vector3& rkVector ) const
154  {
155  return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
156  }
157 
158  // arithmetic operations
159  inline Vector3 operator + ( const Vector3& rkVector ) const
160  {
161  return Vector3(
162  x + rkVector.x,
163  y + rkVector.y,
164  z + rkVector.z);
165  }
166 
167  inline Vector3 operator - ( const Vector3& rkVector ) const
168  {
169  return Vector3(
170  x - rkVector.x,
171  y - rkVector.y,
172  z - rkVector.z);
173  }
174 
175  inline Vector3 operator * ( const Real fScalar ) const
176  {
177  return Vector3(
178  x * fScalar,
179  y * fScalar,
180  z * fScalar);
181  }
182 
183  inline Vector3 operator * ( const Vector3& rhs) const
184  {
185  return Vector3(
186  x * rhs.x,
187  y * rhs.y,
188  z * rhs.z);
189  }
190 
191  inline Vector3 operator / ( const Real fScalar ) const
192  {
193  assert( fScalar != 0.0 );
194 
195  Real fInv = 1.0f / fScalar;
196 
197  return Vector3(
198  x * fInv,
199  y * fInv,
200  z * fInv);
201  }
202 
203  inline Vector3 operator / ( const Vector3& rhs) const
204  {
205  return Vector3(
206  x / rhs.x,
207  y / rhs.y,
208  z / rhs.z);
209  }
210 
211  inline const Vector3& operator + () const
212  {
213  return *this;
214  }
215 
216  inline Vector3 operator - () const
217  {
218  return Vector3(-x, -y, -z);
219  }
220 
221  // overloaded operators to help Vector3
222  inline friend Vector3 operator * ( const Real fScalar, const Vector3& rkVector )
223  {
224  return Vector3(
225  fScalar * rkVector.x,
226  fScalar * rkVector.y,
227  fScalar * rkVector.z);
228  }
229 
230  inline friend Vector3 operator / ( const Real fScalar, const Vector3& rkVector )
231  {
232  return Vector3(
233  fScalar / rkVector.x,
234  fScalar / rkVector.y,
235  fScalar / rkVector.z);
236  }
237 
238  inline friend Vector3 operator + (const Vector3& lhs, const Real rhs)
239  {
240  return Vector3(
241  lhs.x + rhs,
242  lhs.y + rhs,
243  lhs.z + rhs);
244  }
245 
246  inline friend Vector3 operator + (const Real lhs, const Vector3& rhs)
247  {
248  return Vector3(
249  lhs + rhs.x,
250  lhs + rhs.y,
251  lhs + rhs.z);
252  }
253 
254  inline friend Vector3 operator - (const Vector3& lhs, const Real rhs)
255  {
256  return Vector3(
257  lhs.x - rhs,
258  lhs.y - rhs,
259  lhs.z - rhs);
260  }
261 
262  inline friend Vector3 operator - (const Real lhs, const Vector3& rhs)
263  {
264  return Vector3(
265  lhs - rhs.x,
266  lhs - rhs.y,
267  lhs - rhs.z);
268  }
269 
270  // arithmetic updates
271  inline Vector3& operator += ( const Vector3& rkVector )
272  {
273  x += rkVector.x;
274  y += rkVector.y;
275  z += rkVector.z;
276 
277  return *this;
278  }
279 
280  inline Vector3& operator += ( const Real fScalar )
281  {
282  x += fScalar;
283  y += fScalar;
284  z += fScalar;
285  return *this;
286  }
287 
288  inline Vector3& operator -= ( const Vector3& rkVector )
289  {
290  x -= rkVector.x;
291  y -= rkVector.y;
292  z -= rkVector.z;
293 
294  return *this;
295  }
296 
297  inline Vector3& operator -= ( const Real fScalar )
298  {
299  x -= fScalar;
300  y -= fScalar;
301  z -= fScalar;
302  return *this;
303  }
304 
305  inline Vector3& operator *= ( const Real fScalar )
306  {
307  x *= fScalar;
308  y *= fScalar;
309  z *= fScalar;
310  return *this;
311  }
312 
313  inline Vector3& operator *= ( const Vector3& rkVector )
314  {
315  x *= rkVector.x;
316  y *= rkVector.y;
317  z *= rkVector.z;
318 
319  return *this;
320  }
321 
322  inline Vector3& operator /= ( const Real fScalar )
323  {
324  assert( fScalar != 0.0 );
325 
326  Real fInv = 1.0f / fScalar;
327 
328  x *= fInv;
329  y *= fInv;
330  z *= fInv;
331 
332  return *this;
333  }
334 
335  inline Vector3& operator /= ( const Vector3& rkVector )
336  {
337  x /= rkVector.x;
338  y /= rkVector.y;
339  z /= rkVector.z;
340 
341  return *this;
342  }
343 
344 
352  inline Real length () const
353  {
354  return Math::Sqrt( x * x + y * y + z * z );
355  }
356 
367  inline Real squaredLength () const
368  {
369  return x * x + y * y + z * z;
370  }
371 
379  inline Real distance(const Vector3& rhs) const
380  {
381  return (*this - rhs).length();
382  }
383 
394  inline Real squaredDistance(const Vector3& rhs) const
395  {
396  return (*this - rhs).squaredLength();
397  }
398 
413  inline Real dotProduct(const Vector3& vec) const
414  {
415  return x * vec.x + y * vec.y + z * vec.z;
416  }
417 
428  inline Real absDotProduct(const Vector3& vec) const
429  {
430  return Math::Abs(x * vec.x) + Math::Abs(y * vec.y) + Math::Abs(z * vec.z);
431  }
432 
442  inline Real normalise()
443  {
444  Real fLength = Math::Sqrt( x * x + y * y + z * z );
445 
446  // Will also work for zero-sized vectors, but will change nothing
447  // We're not using epsilons because we don't need to.
448  // Read http://www.ogre3d.org/forums/viewtopic.php?f=4&t=61259
449  if ( fLength > Real(0.0f) )
450  {
451  Real fInvLength = 1.0f / fLength;
452  x *= fInvLength;
453  y *= fInvLength;
454  z *= fInvLength;
455  }
456 
457  return fLength;
458  }
459 
488  inline Vector3 crossProduct( const Vector3& rkVector ) const
489  {
490  return Vector3(
491  y * rkVector.z - z * rkVector.y,
492  z * rkVector.x - x * rkVector.z,
493  x * rkVector.y - y * rkVector.x);
494  }
495 
499  inline Vector3 midPoint( const Vector3& vec ) const
500  {
501  return Vector3(
502  ( x + vec.x ) * 0.5f,
503  ( y + vec.y ) * 0.5f,
504  ( z + vec.z ) * 0.5f );
505  }
506 
510  inline bool operator < ( const Vector3& rhs ) const
511  {
512  if( x < rhs.x && y < rhs.y && z < rhs.z )
513  return true;
514  return false;
515  }
516 
520  inline bool operator > ( const Vector3& rhs ) const
521  {
522  if( x > rhs.x && y > rhs.y && z > rhs.z )
523  return true;
524  return false;
525  }
526 
534  inline void makeFloor( const Vector3& cmp )
535  {
536  if( cmp.x < x ) x = cmp.x;
537  if( cmp.y < y ) y = cmp.y;
538  if( cmp.z < z ) z = cmp.z;
539  }
540 
548  inline void makeCeil( const Vector3& cmp )
549  {
550  if( cmp.x > x ) x = cmp.x;
551  if( cmp.y > y ) y = cmp.y;
552  if( cmp.z > z ) z = cmp.z;
553  }
554 
562  inline Vector3 perpendicular(void) const
563  {
564  static const Real fSquareZero = (Real)(1e-06 * 1e-06);
565 
566  Vector3 perp = this->crossProduct( Vector3::UNIT_X );
567 
568  // Check length
569  if( perp.squaredLength() < fSquareZero )
570  {
571  /* This vector is the Y axis multiplied by a scalar, so we have
572  to use another axis.
573  */
574  perp = this->crossProduct( Vector3::UNIT_Y );
575  }
576  perp.normalise();
577 
578  return perp;
579  }
600  const Radian& angle,
601  const Vector3& up = Vector3::ZERO ) const
602  {
603  Vector3 newUp;
604 
605  if (up == Vector3::ZERO)
606  {
607  // Generate an up vector
608  newUp = this->perpendicular();
609  }
610  else
611  {
612  newUp = up;
613  }
614 
615  // Rotate up vector by random amount around this
616  Quaternion q;
618  newUp = q * newUp;
619 
620  // Finally rotate this by given angle around randomised up
621  q.FromAngleAxis( angle, newUp );
622  return q * (*this);
623  }
624 
629  inline Radian angleBetween(const Vector3& dest) const
630  {
631  Real lenProduct = length() * dest.length();
632 
633  // Divide by zero check
634  if(lenProduct < 1e-6f)
635  lenProduct = 1e-6f;
636 
637  Real f = dotProduct(dest) / lenProduct;
638 
639  f = Math::Clamp(f, (Real)-1.0, (Real)1.0);
640  return Math::ACos(f);
641 
642  }
652  const Vector3& fallbackAxis = Vector3::ZERO) const
653  {
654  // Based on Stan Melax's article in Game Programming Gems
655  Quaternion q;
656  // Copy, since cannot modify local
657  Vector3 v0 = *this;
658  Vector3 v1 = dest;
659  v0.normalise();
660  v1.normalise();
661 
662  Real d = v0.dotProduct(v1);
663  // If dot == 1, vectors are the same
664  if (d >= 1.0f)
665  {
666  return Quaternion::IDENTITY;
667  }
668  if (d < (1e-6f - 1.0f))
669  {
670  if (fallbackAxis != Vector3::ZERO)
671  {
672  // rotate 180 degrees about the fallback axis
673  q.FromAngleAxis(Radian(Math::PI), fallbackAxis);
674  }
675  else
676  {
677  // Generate an axis
678  Vector3 axis = Vector3::UNIT_X.crossProduct(*this);
679  if (axis.isZeroLength()) // pick another if colinear
680  axis = Vector3::UNIT_Y.crossProduct(*this);
681  axis.normalise();
682  q.FromAngleAxis(Radian(Math::PI), axis);
683  }
684  }
685  else
686  {
687  Real s = Math::Sqrt( (1+d)*2 );
688  Real invs = 1 / s;
689 
690  Vector3 c = v0.crossProduct(v1);
691 
692  q.x = c.x * invs;
693  q.y = c.y * invs;
694  q.z = c.z * invs;
695  q.w = s * 0.5f;
696  q.normalise();
697  }
698  return q;
699  }
700 
702  inline bool isZeroLength(void) const
703  {
704  Real sqlen = (x * x) + (y * y) + (z * z);
705  return (sqlen < (1e-06 * 1e-06));
706 
707  }
708 
711  inline Vector3 normalisedCopy(void) const
712  {
713  Vector3 ret = *this;
714  ret.normalise();
715  return ret;
716  }
717 
721  inline Vector3 reflect(const Vector3& normal) const
722  {
723  return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) );
724  }
725 
732  inline bool positionEquals(const Vector3& rhs, Real tolerance = 1e-03) const
733  {
734  return Math::RealEqual(x, rhs.x, tolerance) &&
735  Math::RealEqual(y, rhs.y, tolerance) &&
736  Math::RealEqual(z, rhs.z, tolerance);
737 
738  }
739 
746  inline bool positionCloses(const Vector3& rhs, Real tolerance = 1e-03f) const
747  {
748  return squaredDistance(rhs) <=
749  (squaredLength() + rhs.squaredLength()) * tolerance;
750  }
751 
759  inline bool directionEquals(const Vector3& rhs,
760  const Radian& tolerance) const
761  {
762  Real dot = dotProduct(rhs);
763  Radian angle = Math::ACos(dot);
764 
765  return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians();
766 
767  }
768 
770  inline bool isNaN() const
771  {
772  return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z);
773  }
774 
776  inline Vector3 primaryAxis() const
777  {
778  Real absx = Math::Abs(x);
779  Real absy = Math::Abs(y);
780  Real absz = Math::Abs(z);
781  if (absx > absy)
782  if (absx > absz)
783  return x > 0 ? Vector3::UNIT_X : Vector3::NEGATIVE_UNIT_X;
784  else
785  return z > 0 ? Vector3::UNIT_Z : Vector3::NEGATIVE_UNIT_Z;
786  else // absx <= absy
787  if (absy > absz)
788  return y > 0 ? Vector3::UNIT_Y : Vector3::NEGATIVE_UNIT_Y;
789  else
790  return z > 0 ? Vector3::UNIT_Z : Vector3::NEGATIVE_UNIT_Z;
791 
792 
793  }
794 
795  // special points
796  static const Vector3 ZERO;
797  static const Vector3 UNIT_X;
798  static const Vector3 UNIT_Y;
799  static const Vector3 UNIT_Z;
800  static const Vector3 NEGATIVE_UNIT_X;
801  static const Vector3 NEGATIVE_UNIT_Y;
802  static const Vector3 NEGATIVE_UNIT_Z;
803  static const Vector3 UNIT_SCALE;
804 
807  inline _OgreExport friend std::ostream& operator <<
808  ( std::ostream& o, const Vector3& v )
809  {
810  o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")";
811  return o;
812  }
813  };
817 }
818 #endif

Copyright © 2012 Torus Knot Software Ltd
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Wed Oct 16 2013 14:35:46