MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
quaternion.cpp
1 // © Copyright 2010 - 2014 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 #ifndef _quaternion_cpp
41 #define _quaternion_cpp
42 
43 #include "stringtool.h"
44 #include "quaternion.h"
45 #include "mathtool.h"
46 #include "serialization.h"
47 #include "vector3.h"
48 #include "matrix3x3.h"
49 #include "exception.h"
50 
51 #include <Ogre.h>
52 #include "btBulletDynamicsCommon.h"
53 
54 #include <cmath>
55 #include <memory>
56 
57 namespace Mezzanine
58 {
59  ///////////////////////////////////////////////////////////////////////////////
60  // Constructors
62  { SetIdentity(); }
63 
64  Quaternion::Quaternion(const Real& X, const Real& Y, const Real& Z, const Real& W)
65  { SetValues(X,Y,Z,W); }
66 
67  Quaternion::Quaternion(const Real& Angle, const Vector3& Axis)
68  { SetFromAxisAngle(Angle,Axis); }
69 
71  { SetFromMatrix3x3(Mat); }
72 
73  Quaternion::Quaternion(const Vector3& AxisX, const Vector3& AxisY, const Vector3& AxisZ)
74  { SetFromAxes(AxisX,AxisY,AxisZ); }
75 
76  Quaternion::Quaternion(const btQuaternion& Other)
77  { ExtractBulletQuaternion(Other); }
78 
79  Quaternion::Quaternion(const Ogre::Quaternion& Other)
80  { ExtractOgreQuaternion(Other); }
81 
83  {
84  this->X = Other.X;
85  this->Y = Other.Y;
86  this->Z = Other.Z;
87  this->W = Other.W;
88  }
89 
91  { this->ProtoDeSerialize(OneNode); }
92 
93  ///////////////////////////////////////////////////////////////////////////////
94  // Fancy Math and Utilities
95 
97  {
98  this->X = 0;
99  this->Y = 0;
100  this->Z = 0;
101  this->W = 1;
102  }
103 
104  void Quaternion::SetValues(const Real& X, const Real& Y, const Real& Z, const Real& W)
105  {
106  this->X = X;
107  this->Y = Y;
108  this->Z = Z;
109  this->W = W;
110  }
111 
112  void Quaternion::SetFromAxisAngle(const Real& Angle, const Vector3& Axis)
113  {
114  Real HalfAngle ( 0.5*Angle );
115  Real AngleSin = MathTools::Sin(HalfAngle);
116  this->W = MathTools::Cos(HalfAngle);
117  this->X = AngleSin * Axis.X;
118  this->Y = AngleSin * Axis.Y;
119  this->Z = AngleSin * Axis.Z;
120  }
121 
123  {
124  Real Trace = Mat.Matrix[0][0]+Mat.Matrix[1][1]+Mat.Matrix[2][2];
125  Real Root;
126 
127  if(Trace > 0.0)
128  {
129  Root = MathTools::Sqrt(Trace + 1.0);
130  this->W = Root * 0.5;
131  Root = 0.5/Root;
132  this->X = (Mat.Matrix[2][1] - Mat.Matrix[1][2]) * Root;
133  this->Y = (Mat.Matrix[0][2] - Mat.Matrix[2][0]) * Root;
134  this->Z = (Mat.Matrix[1][0] - Mat.Matrix[0][1]) * Root;
135  }else{
136  static size_t s_iNext[3] = { 1, 2, 0 };
137  size_t I = 0;
138  if ( Mat.Matrix[1][1] > Mat.Matrix[0][0] )
139  I = 1;
140  if ( Mat.Matrix[2][2] > Mat.Matrix[I][I] )
141  I = 2;
142  size_t J = s_iNext[I];
143  size_t K = s_iNext[J];
144 
145  Root = MathTools::Sqrt(Mat.Matrix[I][I] - Mat.Matrix[J][J] - Mat.Matrix[K][K] + 1.0);
146  Real* QuatMem[3] = { &X, &Y, &Z };
147  *QuatMem[I] = 0.5 * Root;
148  Root = 0.5 / Root;
149  this->W = (Mat.Matrix[K][J] - Mat.Matrix[J][K]) * Root;
150  *QuatMem[J] = (Mat.Matrix[J][I] + Mat.Matrix[I][J]) * Root;
151  *QuatMem[K] = (Mat.Matrix[K][I] + Mat.Matrix[I][K]) * Root;
152  }
153  }
154 
155  void Quaternion::SetFromAxes(const Vector3& AxisX, const Vector3& AxisY, const Vector3& AxisZ)
156  {
157  Matrix3x3 Mat3;
158 
159  Mat3.Matrix[0][0] = AxisX.X;
160  Mat3.Matrix[1][0] = AxisX.Y;
161  Mat3.Matrix[2][0] = AxisX.Z;
162  Mat3.Matrix[0][1] = AxisY.X;
163  Mat3.Matrix[1][1] = AxisY.Y;
164  Mat3.Matrix[2][1] = AxisY.Z;
165  Mat3.Matrix[0][2] = AxisZ.X;
166  Mat3.Matrix[1][2] = AxisZ.Y;
167  Mat3.Matrix[2][2] = AxisZ.Z;
168 
169  SetFromMatrix3x3(Mat3);
170  }
171 
173  {
174  return this->X * Other.X + this->Y * Other.Y + this->Z * Other.Z + this->W * Other.W;
175  }
176 
178  {
179  return sqrt(LengthSqrd());
180  }
181 
183  {
184  return DotProduct(*this);
185  }
186 
188  {
189  *this = *this / Length();
190  return *this;
191  }
192 
194  { return *this / Length(); }
195 
196 
198  {
199  Real Norm = W*W+X*X+Y*Y+Z*Z;
200  if ( Norm > 0.0 )
201  {
202  Real InvNorm = 1.f/Norm;
203  return Quaternion(W*InvNorm,-X*InvNorm,-Y*InvNorm,-Z*InvNorm);
204  }else{
205  return Quaternion(0,0,0,0);
206  }
207  }
208 
209  ///////////////////////////////////////////////////////////////////////////////
210  // Explicit Conversion
211 
212  btQuaternion Quaternion::GetBulletQuaternion(bool normalize) const
213  {
214  btQuaternion Other;
215  Other.setX(this->X);
216  Other.setY(this->Y);
217  Other.setZ(this->Z);
218  Other.setW(this->W);
219  if(normalize)
220  { Other.normalize(); }
221  return Other;
222  }
223 
224  void Quaternion::ExtractBulletQuaternion(const btQuaternion &Other)
225  {
226  this->X=Other.x();
227  this->Y=Other.y();
228  this->Z=Other.z();
229  this->W=Other.w();
230  }
231 
232  Ogre::Quaternion Quaternion::GetOgreQuaternion(bool normalize) const
233  {
234  Ogre::Quaternion Other;
235  Other.x=this->X;
236  Other.y=this->Y;
237  Other.z=this->Z;
238  Other.w=this->W;
239  if(normalize)
240  { Other.normalise(); }
241  return Other;
242  }
243 
244  void Quaternion::ExtractOgreQuaternion(const Ogre::Quaternion &Other)
245  {
246  this->X=Other.x;
247  this->Y=Other.y;
248  this->Z=Other.z;
249  this->W=Other.w;
250  }
251 
252  ///////////////////////////////////////////////////////////////////////////////
253  // Access Operators
254 
255  Real Quaternion::operator[](const Whole& Index) const
256  {
257  switch(Index)
258  {
259  case 0: return X;
260  case 1: return Y;
261  case 2: return Z;
262  case 3: return W;
263  default:
264  { MEZZ_EXCEPTION(Exception::MM_OUT_OF_BOUNDS_EXCEPTION,"Attempting to get invalid index."); }
265  }
266  }
267 
269  {
270  switch(Index)
271  {
272  case 0: return X;
273  case 1: return Y;
274  case 2: return Z;
275  case 3: return W;
276  default:
277  { MEZZ_EXCEPTION(Exception::MM_OUT_OF_BOUNDS_EXCEPTION,"Attempting to get invalid index."); }
278  }
279  }
280 
281  ///////////////////////////////////////////////////////////////////////////////
282  // Arithmetic By Real Operators
283 
285  {
286  return Quaternion(this->X * Scalar,this->Y * Scalar,this->Z * Scalar,this->W * Scalar);
287  }
288 
290  {
291  if( 0 == Scalar )
292  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Dividing by zero in 'Quaternion::operator/', Quit it."); }
293  return *this * ( 1.0 / Scalar );
294  }
295 
296  ///////////////////////////////////////////////////////////////////////////////
297  // Left Hand Basic Arithmetic Operators
298 
300  { return Quaternion(this->X+Other.X, this->Y+Other.Y, this->Z+Other.Z, this->W+Other.W); }
301 
302  Quaternion Quaternion::operator+ (const Ogre::Quaternion& Other) const
303  { return Quaternion(this->X+Other.x, this->Y+Other.y, this->Z+Other.z, this->W+Other.w); }
304 
305  Quaternion Quaternion::operator+ (const btQuaternion& Other) const
306  { return Quaternion(this->X+Other.x(), this->Y+Other.y(), this->Z+Other.z(), this->W+Other.w()); }
307 
309  { return Quaternion(this->X-Other.X, this->Y-Other.Y, this->Z-Other.Z, this->W-Other.W); }
310 
311  Quaternion Quaternion::operator- (const Ogre::Quaternion& Other) const
312  { return Quaternion(this->X-Other.x, this->Y-Other.y, this->Z-Other.z, this->W-Other.w); }
313 
314  Quaternion Quaternion::operator- (const btQuaternion& Other) const
315  { return Quaternion(this->X-Other.x(), this->Y-Other.y(), this->Z-Other.z(), this->W-Other.w()); }
316 
318  {
319  return Quaternion
320  (
321  this->W * Other.X + this->X * Other.W + this->Y * Other.Z - this->Z * Other.Y,
322  this->W * Other.Y + this->Y * Other.W + this->Z * Other.X - this->X * Other.Z,
323  this->W * Other.Z + this->Z * Other.W + this->X * Other.Y - this->Y * Other.X,
324  this->W * Other.W - this->X * Other.X + this->Y * Other.Y - this->Z * Other.Z
325  );
326  }
327 
328  Quaternion Quaternion::operator* (const Ogre::Quaternion& Other) const
329  {
330  return Quaternion
331  (
332  this->W * Other.x + this->X * Other.w + this->Y * Other.z - this->Z * Other.y,
333  this->W * Other.y + this->Y * Other.w + this->Z * Other.x - this->X * Other.z,
334  this->W * Other.z + this->Z * Other.w + this->X * Other.y - this->Y * Other.x,
335  this->W * Other.w - this->X * Other.x + this->Y * Other.y - this->Z * Other.z
336  );
337  }
338 
339  Quaternion Quaternion::operator* (const btQuaternion& Other) const
340  {
341  return Quaternion
342  (
343  this->W * Other.x() + this->X * Other.w() + this->Y * Other.z() - this->Z * Other.y(),
344  this->W * Other.y() + this->Y * Other.w() + this->Z * Other.x() - this->X * Other.z(),
345  this->W * Other.z() + this->Z * Other.w() + this->X * Other.y() - this->Y * Other.x(),
346  this->W * Other.w() - this->X * Other.x() + this->Y * Other.y() - this->Z * Other.z()
347  );
348  }
349 
350  ///////////////////////////////////////////////////////////////////////////////
351  // Vector Rotation Operators
352 
354  {
355  Vector3 UV, UUV;
356  Vector3 QuatVec(X,Y,Z);
357  UV = QuatVec.CrossProduct(Other);
358  UUV = QuatVec.CrossProduct(UV);
359  UV *= (2.f * W);
360  UUV *= 2.f;
361  return Other + UV + UUV;
362  }
363 
364  ///////////////////////////////////////////////////////////////////////////////
365  // Increment and Decrement Operators
366 
368  {
369  this->X=this->X+Other.X;
370  this->Y=this->Y+Other.Y;
371  this->Z=this->Z+Other.Z;
372  this->W=this->W+Other.W;
373  return *this;
374  }
375 
376  Quaternion& Quaternion::operator+= (const Ogre::Quaternion& Other)
377  {
378  this->X=this->X+Other.x;
379  this->Y=this->Y+Other.y;
380  this->Z=this->Z+Other.z;
381  this->W=this->W+Other.w;
382  return *this;
383  }
384 
385  Quaternion& Quaternion::operator+= (const btQuaternion& Other)
386  {
387  this->X=this->X+Other.x();
388  this->Y=this->Y+Other.y();
389  this->Z=this->Z+Other.z();
390  this->W=this->W+Other.w();
391  return *this;
392  }
393 
395  {
396  this->X=this->X-Other.X;
397  this->Y=this->Y-Other.Y;
398  this->Z=this->Z-Other.Z;
399  this->W=this->W-Other.W;
400  return *this;
401  }
402 
403  Quaternion& Quaternion::operator-= (const Ogre::Quaternion& Other)
404  {
405  this->X=this->X-Other.x;
406  this->Y=this->Y-Other.y;
407  this->Z=this->Z-Other.z;
408  this->W=this->W-Other.w;
409  return *this;
410  }
411 
412  Quaternion& Quaternion::operator-= (const btQuaternion& Other)
413  {
414  this->X=this->X-Other.x();
415  this->Y=this->Y-Other.y();
416  this->Z=this->Z-Other.z();
417  this->W=this->W-Other.w();
418  return *this;
419  }
420 
421  ///////////////////////////////////////////////////////////////////////////////
422  // Assignment Operators
424  {
425  this->X=Other.X;
426  this->Y=Other.Y;
427  this->Z=Other.Z;
428  this->W=Other.W;
429  return *this;
430  }
431 
432  Quaternion& Quaternion::operator= (const btQuaternion& Other)
433  {
435  return *this;
436  }
437 
438  Quaternion& Quaternion::operator= (const Ogre::Quaternion& Other)
439  {
440  ExtractOgreQuaternion(Other);
441  return *this;
442  }
443 
444  ///////////////////////////////////////////////////////////////////////////////
445  // Equality Comparison Operators
446 
448  { return (this->X==Other.X && this->Y==Other.Y && this->Z==Other.Z && this->W==Other.W); }
449 
450  bool Quaternion::operator==(const Ogre::Quaternion& Other) const
451  { return (this->X==Other.x && this->Y==Other.y && this->Z==Other.z && this->W==Other.w); }
452 
453  bool Quaternion::operator==(const btQuaternion& Other) const
454  { return (this->X==Other.getX() && this->Y==Other.getY() && this->Z==Other.getZ() && this->W==Other.getW()); }
455 
457  { return (this->X!=Other.X || this->Y!=Other.Y || this->Z!=Other.Z || this->W!=Other.W); }
458 
459  bool Quaternion::operator!=(const Ogre::Quaternion& Other) const
460  { return (this->X!=Other.x || this->Y!=Other.y || this->Z!=Other.z || this->W!=Other.w); }
461 
462  bool Quaternion::operator!=(const btQuaternion& Other) const
463  { return (this->X!=Other.getX() || this->Y!=Other.getY() || this->Z!=Other.getZ() || this->W!=Other.getW()); }
464 
466  { return (this->X<=Other.X && this->Y<=Other.Y && this->Z<=Other.Z && this->W<=Other.W); }
468  { return (this->X>=Other.X && this->Y>=Other.Y && this->Z>=Other.Z && this->W>=Other.W); }
469 
470  // Serializable
471  void Quaternion::ProtoSerialize(XML::Node& CurrentRoot) const
472  {
473  Mezzanine::XML::Node VecNode = CurrentRoot.AppendChild(SerializableName());
474  VecNode.SetName(SerializableName());
475 
476  Mezzanine::XML::Attribute VersionAttr = VecNode.AppendAttribute("Version");
477  Mezzanine::XML::Attribute XAttr = VecNode.AppendAttribute("X");
478  Mezzanine::XML::Attribute YAttr = VecNode.AppendAttribute("Y");
479  Mezzanine::XML::Attribute ZAttr = VecNode.AppendAttribute("Z");
480  Mezzanine::XML::Attribute WAttr = VecNode.AppendAttribute("W");
481  if( VersionAttr && XAttr && YAttr && ZAttr && WAttr)
482  {
483  if( VersionAttr.SetValue("1") && XAttr.SetValue(this->X) && YAttr.SetValue(this->Y) && ZAttr.SetValue(this->Z) && WAttr.SetValue(this->W))
484  {
485  return;
486  }else{
487  SerializeError("Create XML Attribute Values", SerializableName(),true);
488  }
489  }else{
490  SerializeError("Create XML Attributes", SerializableName(),true);
491  }
492  }
493 
494  // DeSerializable
496  {
498  {
499  if(OneNode.GetAttribute("Version").AsInt() == 1)
500  {
501  this->X=OneNode.GetAttribute("X").AsReal();
502  this->Y=OneNode.GetAttribute("Y").AsReal();
503  this->Z=OneNode.GetAttribute("Z").AsReal();
504  this->W=OneNode.GetAttribute("W").AsReal();
505  }else{
506  MEZZ_EXCEPTION(Mezzanine::Exception::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + SerializableName() + ": Not Version 1.");
507  }
508  }else{
509  MEZZ_EXCEPTION(Mezzanine::Exception::II_IDENTITY_INVALID_EXCEPTION,"Attempting to deserialize a " + SerializableName() + ", found a " + Mezzanine::String(OneNode.Name()));
510  }
511  }
512 
514  { return String("Quaternion"); }
515 
516 }
517 
518 ///////////////////////////////////////////////////////////////////////////////
519 // Right Hand Addition Operators
520 
521 Mezzanine::Quaternion operator+ (const Ogre::Quaternion& Other, const Mezzanine::Quaternion& Other2)
522  { return Other2+Other; }
523 
524 Mezzanine::Quaternion operator+ (const btQuaternion& Other, const Mezzanine::Quaternion& Other2)
525  { return Other2+Other; }
526 
527 Mezzanine::Quaternion operator- (const Ogre::Quaternion& Other, const Mezzanine::Quaternion& Other2)
528  { return Mezzanine::Quaternion(Other.x-Other2.X, Other.y-Other2.Y, Other.z-Other2.Z, Other.w-Other2.W); }
529 
530 Mezzanine::Quaternion operator- (const btQuaternion& Other, const Mezzanine::Quaternion& Other2)
531  { return Mezzanine::Quaternion(Other.getX()-Other2.X, Other.getY()-Other2.Y, Other.getZ()-Other2.Z, Other.getW()-Other2.W); }
532 
533 ///////////////////////////////////////////////////////////////////////////////
534 // Class External << Operators for streaming or assignment
535 
536 btQuaternion& operator<< ( btQuaternion& Other, const Mezzanine::Quaternion& Other2)
537 {
538  Other=Other2.GetBulletQuaternion();
539  return Other;
540 }
541 
542 btQuaternion& operator<< ( btQuaternion& Other, const Ogre::Quaternion& Other2)
543 {
544  Other.setX(Other2.x);
545  Other.setY(Other2.y);
546  Other.setZ(Other2.z);
547  Other.setW(Other2.w);
548  return Other;
549 }
550 
551 Mezzanine::Quaternion& operator<< ( Mezzanine::Quaternion& Other, const Ogre::Quaternion& Other2)
552 {
553  Other=Other2;
554  return Other;
555 }
556 
557 Mezzanine::Quaternion& operator<< ( Mezzanine::Quaternion& Other, const btQuaternion& Other2)
558 {
559  Other=Other2;
560  return Other;
561 }
562 
563 Ogre::Quaternion& operator<< ( Ogre::Quaternion& Other, const Mezzanine::Quaternion& Other2)
564 {
565  Other=Other2.GetOgreQuaternion();
566  return Other;
567 }
568 
569 Ogre::Quaternion& operator<< ( Ogre::Quaternion& Other, const btQuaternion& Other2)
570 {
571  Other.x=Other2.getX();
572  Other.y=Other2.getY();
573  Other.z=Other2.getZ();
574  Other.w=Other2.getW();
575  return Other;
576 }
577 
578 std::ostream& operator << (std::ostream& stream, const Mezzanine::Quaternion& x)
579 {
580 
581  Serialize(stream, x);
582  // '"<Quaternion Version=\"1\" X=\"" << x.X << "\" Y=\"" << x.Y << "\" Z=\"" << x.Z << "\" W=\"" << x.W << "\" />";
583 
584  return stream;
585 }
586 
587 std::istream& operator >> (std::istream& stream, Mezzanine::Quaternion& Ev)
588  { return DeSerialize(stream,Ev); }
589 
590 void operator >> (const Mezzanine::XML::Node& OneNode, Mezzanine::Quaternion& Ev)
591  { Ev.ProtoDeSerialize(OneNode); }
592 
593 
594 
595 #endif // \_quaternion_cpp