WFMath
1.0.1
|
00001 // quaternion.h (based on the Quaternion class from eris) 00002 // 00003 // The WorldForge Project 00004 // Copyright (C) 2002 The WorldForge Project 00005 // 00006 // This program is free software; you can redistribute it and/or modify 00007 // it under the terms of the GNU General Public License as published by 00008 // the Free Software Foundation; either version 2 of the License, or 00009 // (at your option) any later version. 00010 // 00011 // This program is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU General Public License 00017 // along with this program; if not, write to the Free Software 00018 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 // 00020 // For information about WorldForge and its authors, please contact 00021 // the Worldforge Web Site at http://www.worldforge.org. 00022 // 00023 00024 // Author: Ron Steinke 00025 00026 #ifndef WFMATH_QUATERNION_H 00027 #define WFMATH_QUATERNION_H 00028 00029 #include <wfmath/vector.h> 00030 #include <wfmath/rotmatrix.h> 00031 00032 namespace WFMath { 00033 00035 class Quaternion 00036 { 00037 public: 00038 class Identity {}; 00040 Quaternion(const Identity &) : m_w(1), m_vec(), m_valid(true), m_age(0) { 00041 m_vec.zero(); 00042 } 00044 Quaternion () : m_w(0), m_vec(), m_valid(false), m_age(0) {} 00046 00049 Quaternion (CoordType w_in, CoordType x_in, CoordType y_in, CoordType z_in); 00051 Quaternion (int axis, CoordType angle) : m_w(0), m_vec(), m_valid(false), 00052 m_age(0) 00053 {rotation(axis, angle);} 00055 Quaternion (const Vector<3>& axis, CoordType angle) : m_w(0), m_vec(), 00056 m_valid(false), 00057 m_age(0) 00058 {rotation(axis, angle);} 00060 00063 explicit Quaternion (const Vector<3>& axis) : m_w(0), m_vec(), 00064 m_valid(false), m_age(0) 00065 {rotation(axis);} // angle == axis.mag() 00067 Quaternion (const Quaternion& p) : m_w(p.m_w), m_vec(p.m_vec), 00068 m_valid(p.m_valid), m_age(p.m_age) {} 00070 explicit Quaternion (const AtlasInType& a) : m_w(0), m_vec(), 00071 m_valid(false), m_age(0) 00072 {fromAtlas(a);} 00073 00074 ~Quaternion() {} 00075 00076 friend std::ostream& operator<<(std::ostream& os, const Quaternion& p); 00077 friend std::istream& operator>>(std::istream& is, Quaternion& p); 00078 00080 AtlasOutType toAtlas() const; 00082 void fromAtlas(const AtlasInType& a); 00083 00084 Quaternion& operator= (const Quaternion& rhs) 00085 {m_w = rhs.m_w; m_vec = rhs.m_vec; m_valid = rhs.m_valid; m_age = rhs.m_age; return *this;} 00086 00087 // This regards q and -1*q as equal, since they give the 00088 // same RotMatrix<3> 00089 bool isEqualTo(const Quaternion &q, CoordType epsilon = numeric_constants<CoordType>::epsilon()) const; 00090 00091 bool operator== (const Quaternion& rhs) const {return isEqualTo(rhs);} 00092 bool operator!= (const Quaternion& rhs) const {return !isEqualTo(rhs);} 00093 00094 bool isValid() const {return m_valid;} 00095 00097 Quaternion& identity() {m_w = 1; m_vec.zero(); m_valid = true; m_age = 0; return *this;} // Set to null rotation 00098 00099 // Operators 00100 00102 Quaternion& operator*= (const Quaternion& rhs); 00104 Quaternion& operator/= (const Quaternion& rhs); 00106 Quaternion operator* (const Quaternion& rhs) const { 00107 Quaternion out(*this); 00108 out *= rhs; 00109 return out; 00110 } 00112 Quaternion operator/ (const Quaternion& rhs) const { 00113 Quaternion out(*this); 00114 out /= rhs; 00115 return out; 00116 } 00117 00118 // Functions 00119 00120 // Returns "not_flip", similar to RotMatrix<>.toEuler() 00122 00131 bool fromRotMatrix(const RotMatrix<3>& m); 00132 00134 Quaternion inverse() const; 00135 00137 Quaternion& rotate(const RotMatrix<3>&); 00138 00140 Quaternion& rotate(const Quaternion& q) {return operator*=(q);} 00141 00143 Quaternion& rotation(int axis, CoordType angle); 00145 Quaternion& rotation(const Vector<3>& axis, CoordType angle); 00147 00150 Quaternion& rotation(const Vector<3>& axis); // angle == axis.mag() 00151 00153 Quaternion& rotation(const Vector<3>& from, const Vector<3>& to); 00154 00156 CoordType scalar() const {return m_w;} 00158 const Vector<3>& vector() const {return m_vec;} 00159 00161 void normalize(); 00163 unsigned age() const {return m_age;} 00164 00165 private: 00166 Quaternion(bool valid) : m_w(0), m_vec(), m_valid(valid), m_age(1) {} 00167 void checkNormalization() {if(m_age >= WFMATH_MAX_NORM_AGE && m_valid) normalize();} 00168 CoordType m_w; 00169 Vector<3> m_vec; 00170 bool m_valid; 00171 unsigned m_age; 00172 }; 00173 00174 } // namespace WFMath 00175 00176 #endif // WFMATH_QUATERNION_H