00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <base/consts>
00026 #include <base/Quat4>
00027 #include <base/Matrix4>
00028 #include <base/Math>
00029 #include <base/Serializer>
00030
00031
00032 using base::Quat4;
00033 using base::Matrix4;
00034 using base::Vector3;
00035 using base::Point4;
00036 using base::Math;
00037
00038
00039
00040 Quat4& Quat4::operator*=(const Quat4& qr)
00041 {
00042 Quat4 ql(*this);
00043
00044 w = ql.w*qr.w - ql.v.x*qr.v.x - ql.v.y*qr.v.y - ql.v.z*qr.v.z;
00045 v.x = ql.w*qr.v.x + ql.v.x*qr.w + ql.v.y*qr.v.z - ql.v.z*qr.v.y;
00046 v.y = ql.w*qr.v.y + ql.v.y*qr.w + ql.v.z*qr.v.x - ql.v.x*qr.v.z;
00047 v.z = ql.w*qr.v.z + ql.v.z*qr.w + ql.v.x*qr.v.y - ql.v.y*qr.v.x;
00048
00049 return *this;
00050 }
00051
00052 void Quat4::setRotation(const Vector3& axis, Real angle)
00053 {
00054 Vector3 a(axis);
00055 a.normalize();
00056 v=a*sin(angle/2.0);
00057 w=cos(angle/2.0);
00058 }
00059
00060
00061 void Quat4::setRotation(const Matrix4& rotation)
00062 {
00063
00064
00065 const Matrix4& m = rotation;
00066 Quat4& q = *this;
00067
00068 Real tr = 1 + m.e(1,1) + m.e(2,2) + m.e(3,3);
00069 if (tr > consts::epsilon) {
00070 Real s = sqrt(tr)*2.0;
00071 q.v.x = (m.e(3,2) - m.e(2,3))/s;
00072 q.v.y = (m.e(1,3) - m.e(3,1))/s;
00073 q.v.z = (m.e(2,1) - m.e(1,2))/s;
00074 q.w = 0.25*s;
00075 }
00076 else {
00077
00078 if ((m.e(1,1) > m.e(2,2)) && (m.e(1,1) > m.e(3,3))) {
00079 Real s = sqrt(1+m.e(1,1)-m.e(2,2)-m.e(3,3))*2.0;
00080 q.v.x = 0.25*s;
00081 q.v.y = (m.e(2,1)+m.e(1,2))/s;
00082 q.v.z = (m.e(1,3)+m.e(3,1))/s;
00083 q.w = (m.e(3,2)-m.e(2,3))/s;
00084 }
00085 else if (m.e(2,2) > m.e(3,3)) {
00086 Real s = sqrt(1+m.e(2,2)-m.e(1,1)-m.e(3,3))*2.0;
00087 q.v.x = (m.e(2,1)+m.e(1,2))/s;
00088 q.v.y = 0.25*s;
00089 q.v.z = (m.e(3,2)+m.e(2,3))/s;
00090 q.w = (m.e(1,3)-m.e(3,1))/s;
00091 }
00092 else {
00093 Real s = sqrt(1+m.e(3,3)-m.e(1,1)-m.e(2,2))*2.0;
00094 q.v.x = (m.e(1,3)+m.e(3,1))/s;
00095 q.v.y = (m.e(3,2)+m.e(2,3))/s;
00096 q.v.z = 0.25*s;
00097 q.w = (m.e(2,1)-m.e(1,2))/s;
00098 }
00099 }
00100
00101
00102 }
00103
00104
00105 void Quat4::getRotation(Vector3& axis, Real& angle) const
00106 {
00107 angle = 2.0*acos(w);
00108 if (!base::equals(angle,0))
00109 axis = v / sin(angle/2.0);
00110 else
00111 axis = Vector3(0,0,1);
00112
00113 if (base::equals(axis.norm(),0))
00114 angle = 0;
00115 }
00116
00117
00118 void Quat4::rotatePoint(Point4& p) const
00119 {
00120 const Quat4& q = *this;
00121 Quat4 r( (q * Quat4(p)) * inverse(q) );
00122 p=Point4(r.v.x,r.v.y,r.v.z,r.w);
00123 }
00124
00125
00126
00127
00128
00129
00130
00131 Quat4 Quat4::interpolate(const Quat4& from, const Quat4& to, Real t)
00132 {
00133 const Real linearTolerance = 1e-3;
00134
00135
00136 Real omega, cosomega, sinomega, scale_from, scale_to;
00137
00138 Quat4 quatTo(to);
00139
00140
00141 cosomega = from.v.dot(to.v)+(from.w*to.w);
00142
00143 if ( cosomega <0.0 ) {
00144 cosomega = -cosomega;
00145 quatTo.negate();
00146 }
00147
00148 if( (1.0 - cosomega) > linearTolerance ) {
00149 omega= Math::acos(cosomega) ;
00150 sinomega = Math::sin(omega) ;
00151
00152 scale_from = Math::sin((1.0-t)*omega)/sinomega ;
00153 scale_to = Math::sin(t*omega)/sinomega ;
00154 }
00155 else {
00156
00157
00158
00159 scale_from = 1.0 - t ;
00160 scale_to = t ;
00161 }
00162
00163 Quat4 ret;
00164 ret.v = (from.v*scale_from) + (quatTo.v*scale_to);
00165 ret.w = (from.w*scale_from) + (quatTo.w*scale_to);
00166 return ret;
00167 }
00168
00169
00170 Real Quat4::angleBetween(const Quat4& q1, const Quat4& q2)
00171 {
00172
00173
00174
00175
00176 Vector3 xaxis(Vector3(1,0,0));
00177 Vector3 vector1(q1.rotate(xaxis));
00178 Vector3 vector2(q2.rotate(xaxis));
00179 return Math::acos(dot(vector1,vector2));
00180 }
00181
00182
00183
00184 Quat4::operator Matrix4() const
00185 {
00186 Real nq = norm();
00187 Real s = (nq> Real(0))? (Real(2)/base::sqrt(nq)):Real(0);
00188
00189 Real xs = v.x*s, ys = v.y*s, zs = v.z*s;
00190 Real wx = w*xs, wy = w*ys, wz = w*zs;
00191 Real xx = v.x*xs,xy = v.x*ys,xz = v.x*zs;
00192 Real yy = v.y*ys,yz = v.y*zs,zz = v.z*zs;
00193
00194 Matrix4 m;
00195
00196 m.e(1,1) = Real(1) - (yy+zz); m.e(2,1) = xy+wz; m.e(3,1) = xz-wy;
00197 m.e(1,2) = xy - wz; m.e(2,2) = Real(1) - (xx+zz); m.e(3,2) = yz+wx;
00198 m.e(1,3) = xz+wy; m.e(2,3) = yz-wx; m.e(3,3) = Real(1) - (xx+yy);
00199
00200 return m;
00201 }
00202
00203
00204 void Quat4::serialize(Serializer& s)
00205 {
00206 s(v,"v"); s(w,"w");
00207 }
00208
00209
00210
00211
00212 std::ostream& base::operator<<(std::ostream& out, const Quat4& q)
00213 {
00214 return out << "([" << q.v.x << "," << q.v.y << "," << q.v.z << "]," << q.w << ")";
00215 }