00001 #ifndef PHX_QUATERNION_H
00002 #define PHX_QUATERNION_H
00003
00004 #include <Phx/PhxConfig.h>
00005 #include <Phx/PhxTypes.h>
00006 #include <Phx/Util/PhxMatrix.h>
00007 #include <math.h>
00008
00009 namespace Phx {
00010
00011 class Quaternion {
00012 double mData[4];
00013
00014 public:
00015
00016 Quaternion() {
00017 mData[0] = 1;
00018 mData[1] = mData[2] = mData[3] = 0;
00019 }
00020
00021 Quaternion(double w, const Vector3& v) {
00022 mData[0] = w;
00023 mData[1] = v.element(0,0);
00024 mData[2] = v.element(1,0);
00025 mData[3] = v.element(2,0);
00026 }
00027
00028 Quaternion(const double* array) {
00029 if (!array) {
00030 std::clog << "Constructing quaternion from 0 array." << std::endl;
00031 throw RangeException();
00032 }
00033 for (uint32_t i = 0; i < 4; i++) {
00034 mData[i] = array[i];
00035 }
00036 }
00037
00038 Quaternion(double w, double x, double y, double z) {
00039 mData[0] = w;
00040 mData[1] = x;
00041 mData[2] = y;
00042 mData[3] = z;
00043 }
00044
00045 double x() const { return mData[1]; }
00046 double y() const { return mData[2]; }
00047 double z() const { return mData[3]; }
00048 double w() const { return real(); }
00049
00050 Vector3 complex() const { return Vector3(mData+1); }
00051 double real() const { return mData[0]; }
00052
00053 Quaternion conjugate(void) const {
00054 return Quaternion(real(), -complex());
00055 }
00056
00067 Quaternion inverse(void) const {
00068 return conjugate() / norm();
00069 }
00070
00071
00080 Quaternion product(const Quaternion& rhs) const {
00081 return Quaternion(y()*rhs.z() - z()*rhs.y() + x()*rhs.w() + w()*rhs.x(),
00082 z()*rhs.x() - x()*rhs.z() + y()*rhs.w() + w()*rhs.y(),
00083 x()*rhs.y() - y()*rhs.x() + z()*rhs.w() + w()*rhs.z(),
00084 w()*rhs.w() - x()*rhs.x() - y()*rhs.y() - z()*rhs.z());
00085 }
00086
00103 Quaternion operator*(const Quaternion& rhs) const {
00104 return product(rhs);
00105 }
00106
00113 Quaternion operator*(double s) const {
00114 return Quaternion(real()*s, complex()*s);
00115 }
00116
00123 Quaternion operator/(double s) const {
00124 if (s == 0) std::clog << "Dividing quaternion by 0." << std::endl;
00125 return Quaternion(real()/s, complex()/s);
00126 }
00127
00139 Matrix4 matrix() const {
00140 double m[16] = {
00141 x(), w(), -z(), y(),
00142 y(), z(), w(), -x(),
00143 z(), -y(), x(), w(),
00144 w(), -x(), -y(), -z()
00145 };
00146 return Matrix4(m);
00147 }
00148
00154 Vector4 vector() const { return Vector4(mData); }
00155
00160 double norm() const { return sqrt(mData[0]*mData[0]+mData[1]*mData[1]+
00161 mData[2]*mData[2]+mData[3]*mData[3]); }
00162
00171 Matrix3 rotationMatrix() const {
00172 double m[9] = {
00173 1-2*y()*y()-2*z()*z(), 2*x()*y() - 2*z()*w(), 2*x()*z() + 2*y()*w(),
00174 2*x()*y() + 2*z()*w(), 1-2*x()*x()-2*z()*z(), 2*y()*z() - 2*x()*w(),
00175 2*x()*z() - 2*y()*w(), 2*y()*z() + 2*x()*w(), 1-2*x()*x()-2*y()*y()
00176 };
00177 return Matrix3(m);
00178 }
00179
00180 };
00181
00182
00183 };
00184
00185
00186 #endif