Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Original Author: Laurence 00024 * Contributor(s): Brecht 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00034 #include "MT_ExpMap.h" 00035 00040 void 00041 MT_ExpMap:: 00042 setRotation( 00043 const MT_Quaternion &q 00044 ) { 00045 // ok first normalize the quaternion 00046 // then compute theta the axis-angle and the normalized axis v 00047 // scale v by theta and that's it hopefully! 00048 00049 m_q = q.normalized(); 00050 m_v = MT_Vector3(m_q.x(), m_q.y(), m_q.z()); 00051 00052 MT_Scalar cosp = m_q.w(); 00053 m_sinp = m_v.length(); 00054 m_v /= m_sinp; 00055 00056 m_theta = atan2(double(m_sinp),double(cosp)); 00057 m_v *= m_theta; 00058 } 00059 00065 const MT_Quaternion& 00066 MT_ExpMap:: 00067 getRotation( 00068 ) const { 00069 return m_q; 00070 } 00071 00076 MT_Matrix3x3 00077 MT_ExpMap:: 00078 getMatrix( 00079 ) const { 00080 return MT_Matrix3x3(m_q); 00081 } 00082 00087 void 00088 MT_ExpMap:: 00089 update( 00090 const MT_Vector3& dv 00091 ){ 00092 m_v += dv; 00093 00094 angleUpdated(); 00095 } 00096 00103 void 00104 MT_ExpMap:: 00105 partialDerivatives( 00106 MT_Matrix3x3& dRdx, 00107 MT_Matrix3x3& dRdy, 00108 MT_Matrix3x3& dRdz 00109 ) const { 00110 00111 MT_Quaternion dQdx[3]; 00112 00113 compute_dQdVi(dQdx); 00114 00115 compute_dRdVi(dQdx[0], dRdx); 00116 compute_dRdVi(dQdx[1], dRdy); 00117 compute_dRdVi(dQdx[2], dRdz); 00118 } 00119 00120 void 00121 MT_ExpMap:: 00122 compute_dRdVi( 00123 const MT_Quaternion &dQdvi, 00124 MT_Matrix3x3 & dRdvi 00125 ) const { 00126 00127 MT_Scalar prod[9]; 00128 00129 /* This efficient formulation is arrived at by writing out the 00130 * entire chain rule product dRdq * dqdv in terms of 'q' and 00131 * noticing that all the entries are formed from sums of just 00132 * nine products of 'q' and 'dqdv' */ 00133 00134 prod[0] = -MT_Scalar(4)*m_q.x()*dQdvi.x(); 00135 prod[1] = -MT_Scalar(4)*m_q.y()*dQdvi.y(); 00136 prod[2] = -MT_Scalar(4)*m_q.z()*dQdvi.z(); 00137 prod[3] = MT_Scalar(2)*(m_q.y()*dQdvi.x() + m_q.x()*dQdvi.y()); 00138 prod[4] = MT_Scalar(2)*(m_q.w()*dQdvi.z() + m_q.z()*dQdvi.w()); 00139 prod[5] = MT_Scalar(2)*(m_q.z()*dQdvi.x() + m_q.x()*dQdvi.z()); 00140 prod[6] = MT_Scalar(2)*(m_q.w()*dQdvi.y() + m_q.y()*dQdvi.w()); 00141 prod[7] = MT_Scalar(2)*(m_q.z()*dQdvi.y() + m_q.y()*dQdvi.z()); 00142 prod[8] = MT_Scalar(2)*(m_q.w()*dQdvi.x() + m_q.x()*dQdvi.w()); 00143 00144 /* first row, followed by second and third */ 00145 dRdvi[0][0] = prod[1] + prod[2]; 00146 dRdvi[0][1] = prod[3] - prod[4]; 00147 dRdvi[0][2] = prod[5] + prod[6]; 00148 00149 dRdvi[1][0] = prod[3] + prod[4]; 00150 dRdvi[1][1] = prod[0] + prod[2]; 00151 dRdvi[1][2] = prod[7] - prod[8]; 00152 00153 dRdvi[2][0] = prod[5] - prod[6]; 00154 dRdvi[2][1] = prod[7] + prod[8]; 00155 dRdvi[2][2] = prod[0] + prod[1]; 00156 } 00157 00158 // compute partial derivatives dQ/dVi 00159 00160 void 00161 MT_ExpMap:: 00162 compute_dQdVi( 00163 MT_Quaternion *dQdX 00164 ) const { 00165 00166 /* This is an efficient implementation of the derivatives given 00167 * in Appendix A of the paper with common subexpressions factored out */ 00168 00169 MT_Scalar sinc, termCoeff; 00170 00171 if (m_theta < MT_EXPMAP_MINANGLE) { 00172 sinc = 0.5 - m_theta*m_theta/48.0; 00173 termCoeff = (m_theta*m_theta/40.0 - 1.0)/24.0; 00174 } 00175 else { 00176 MT_Scalar cosp = m_q.w(); 00177 MT_Scalar ang = 1.0/m_theta; 00178 00179 sinc = m_sinp*ang; 00180 termCoeff = ang*ang*(0.5*cosp - sinc); 00181 } 00182 00183 for (int i = 0; i < 3; i++) { 00184 MT_Quaternion& dQdx = dQdX[i]; 00185 int i2 = (i+1)%3; 00186 int i3 = (i+2)%3; 00187 00188 MT_Scalar term = m_v[i]*termCoeff; 00189 00190 dQdx[i] = term*m_v[i] + sinc; 00191 dQdx[i2] = term*m_v[i2]; 00192 dQdx[i3] = term*m_v[i3]; 00193 dQdx.w() = -0.5*m_v[i]*sinc; 00194 } 00195 } 00196 00197 // reParametize away from singularity, updating 00198 // m_v and m_theta 00199 00200 void 00201 MT_ExpMap:: 00202 reParametrize( 00203 ){ 00204 if (m_theta > MT_PI) { 00205 MT_Scalar scl = m_theta; 00206 if (m_theta > MT_2_PI){ /* first get theta into range 0..2PI */ 00207 m_theta = MT_Scalar(fmod(m_theta, MT_2_PI)); 00208 scl = m_theta/scl; 00209 m_v *= scl; 00210 } 00211 if (m_theta > MT_PI){ 00212 scl = m_theta; 00213 m_theta = MT_2_PI - m_theta; 00214 scl = MT_Scalar(1.0) - MT_2_PI/scl; 00215 m_v *= scl; 00216 } 00217 } 00218 } 00219 00220 // compute cached variables 00221 00222 void 00223 MT_ExpMap:: 00224 angleUpdated( 00225 ){ 00226 m_theta = m_v.length(); 00227 00228 reParametrize(); 00229 00230 // compute quaternion, sinp and cosp 00231 00232 if (m_theta < MT_EXPMAP_MINANGLE) { 00233 m_sinp = MT_Scalar(0.0); 00234 00235 /* Taylor Series for sinc */ 00236 MT_Vector3 temp = m_v * MT_Scalar(MT_Scalar(.5) - m_theta*m_theta/MT_Scalar(48.0)); 00237 m_q.x() = temp.x(); 00238 m_q.y() = temp.y(); 00239 m_q.z() = temp.z(); 00240 m_q.w() = MT_Scalar(1.0); 00241 } else { 00242 m_sinp = MT_Scalar(sin(.5*m_theta)); 00243 00244 /* Taylor Series for sinc */ 00245 MT_Vector3 temp = m_v * (m_sinp/m_theta); 00246 m_q.x() = temp.x(); 00247 m_q.y() = temp.y(); 00248 m_q.z() = temp.z(); 00249 m_q.w() = MT_Scalar(cos(.5*m_theta)); 00250 } 00251 } 00252