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