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 "IK_QTask.h" 00035 00036 // IK_QTask 00037 00038 IK_QTask::IK_QTask( 00039 int size, 00040 bool primary, 00041 bool active, 00042 const IK_QSegment *segment 00043 ) : 00044 m_size(size), m_primary(primary), m_active(active), m_segment(segment), 00045 m_weight(1.0) 00046 { 00047 } 00048 00049 // IK_QPositionTask 00050 00051 IK_QPositionTask::IK_QPositionTask( 00052 bool primary, 00053 const IK_QSegment *segment, 00054 const MT_Vector3& goal 00055 ) : 00056 IK_QTask(3, primary, true, segment), m_goal(goal) 00057 { 00058 // computing clamping length 00059 int num; 00060 const IK_QSegment *seg; 00061 00062 m_clamp_length = 0.0; 00063 num = 0; 00064 00065 for (seg = m_segment; seg; seg = seg->Parent()) { 00066 m_clamp_length += seg->MaxExtension(); 00067 num++; 00068 } 00069 00070 m_clamp_length /= 2*num; 00071 } 00072 00073 void IK_QPositionTask::ComputeJacobian(IK_QJacobian& jacobian) 00074 { 00075 // compute beta 00076 const MT_Vector3& pos = m_segment->GlobalEnd(); 00077 00078 MT_Vector3 d_pos = m_goal - pos; 00079 MT_Scalar length = d_pos.length(); 00080 00081 if (length > m_clamp_length) 00082 d_pos = (m_clamp_length/length)*d_pos; 00083 00084 jacobian.SetBetas(m_id, m_size, m_weight*d_pos); 00085 00086 // compute derivatives 00087 int i; 00088 const IK_QSegment *seg; 00089 00090 for (seg = m_segment; seg; seg = seg->Parent()) { 00091 MT_Vector3 p = seg->GlobalStart() - pos; 00092 00093 for (i = 0; i < seg->NumberOfDoF(); i++) { 00094 MT_Vector3 axis = seg->Axis(i)*m_weight; 00095 00096 if (seg->Translational()) 00097 jacobian.SetDerivatives(m_id, seg->DoFId()+i, axis, 1e2); 00098 else { 00099 MT_Vector3 pa = p.cross(axis); 00100 jacobian.SetDerivatives(m_id, seg->DoFId()+i, pa, 1e0); 00101 } 00102 } 00103 } 00104 } 00105 00106 MT_Scalar IK_QPositionTask::Distance() const 00107 { 00108 const MT_Vector3& pos = m_segment->GlobalEnd(); 00109 MT_Vector3 d_pos = m_goal - pos; 00110 return d_pos.length(); 00111 } 00112 00113 // IK_QOrientationTask 00114 00115 IK_QOrientationTask::IK_QOrientationTask( 00116 bool primary, 00117 const IK_QSegment *segment, 00118 const MT_Matrix3x3& goal 00119 ) : 00120 IK_QTask(3, primary, true, segment), m_goal(goal), m_distance(0.0) 00121 { 00122 } 00123 00124 void IK_QOrientationTask::ComputeJacobian(IK_QJacobian& jacobian) 00125 { 00126 // compute betas 00127 const MT_Matrix3x3& rot = m_segment->GlobalTransform().getBasis(); 00128 00129 MT_Matrix3x3 d_rotm = m_goal*rot.transposed(); 00130 d_rotm.transpose(); 00131 00132 MT_Vector3 d_rot; 00133 d_rot = -0.5*MT_Vector3(d_rotm[2][1] - d_rotm[1][2], 00134 d_rotm[0][2] - d_rotm[2][0], 00135 d_rotm[1][0] - d_rotm[0][1]); 00136 00137 m_distance = d_rot.length(); 00138 00139 jacobian.SetBetas(m_id, m_size, m_weight*d_rot); 00140 00141 // compute derivatives 00142 int i; 00143 const IK_QSegment *seg; 00144 00145 for (seg = m_segment; seg; seg = seg->Parent()) 00146 for (i = 0; i < seg->NumberOfDoF(); i++) { 00147 00148 if (seg->Translational()) 00149 jacobian.SetDerivatives(m_id, seg->DoFId()+i, MT_Vector3(0, 0, 0), 1e2); 00150 else { 00151 MT_Vector3 axis = seg->Axis(i)*m_weight; 00152 jacobian.SetDerivatives(m_id, seg->DoFId()+i, axis, 1e0); 00153 } 00154 } 00155 } 00156 00157 // IK_QCenterOfMassTask 00158 // Note: implementation not finished! 00159 00160 IK_QCenterOfMassTask::IK_QCenterOfMassTask( 00161 bool primary, 00162 const IK_QSegment *segment, 00163 const MT_Vector3& goal_center 00164 ) : 00165 IK_QTask(3, primary, true, segment), m_goal_center(goal_center) 00166 { 00167 m_total_mass_inv = ComputeTotalMass(m_segment); 00168 if (!MT_fuzzyZero(m_total_mass_inv)) 00169 m_total_mass_inv = 1.0/m_total_mass_inv; 00170 } 00171 00172 MT_Scalar IK_QCenterOfMassTask::ComputeTotalMass(const IK_QSegment *segment) 00173 { 00174 MT_Scalar mass = /*seg->Mass()*/ 1.0; 00175 00176 const IK_QSegment *seg; 00177 for (seg = segment->Child(); seg; seg = seg->Sibling()) 00178 mass += ComputeTotalMass(seg); 00179 00180 return mass; 00181 } 00182 00183 MT_Vector3 IK_QCenterOfMassTask::ComputeCenter(const IK_QSegment *segment) 00184 { 00185 MT_Vector3 center = /*seg->Mass()**/segment->GlobalStart(); 00186 00187 const IK_QSegment *seg; 00188 for (seg = segment->Child(); seg; seg = seg->Sibling()) 00189 center += ComputeCenter(seg); 00190 00191 return center; 00192 } 00193 00194 void IK_QCenterOfMassTask::JacobianSegment(IK_QJacobian& jacobian, MT_Vector3& center, const IK_QSegment *segment) 00195 { 00196 int i; 00197 MT_Vector3 p = center - segment->GlobalStart(); 00198 00199 for (i = 0; i < segment->NumberOfDoF(); i++) { 00200 MT_Vector3 axis = segment->Axis(i)*m_weight; 00201 axis *= /*segment->Mass()**/m_total_mass_inv; 00202 00203 if (segment->Translational()) 00204 jacobian.SetDerivatives(m_id, segment->DoFId()+i, axis, 1e2); 00205 else { 00206 MT_Vector3 pa = axis.cross(p); 00207 jacobian.SetDerivatives(m_id, segment->DoFId()+i, pa, 1e0); 00208 } 00209 } 00210 00211 const IK_QSegment *seg; 00212 for (seg = segment->Child(); seg; seg = seg->Sibling()) 00213 JacobianSegment(jacobian, center, seg); 00214 } 00215 00216 void IK_QCenterOfMassTask::ComputeJacobian(IK_QJacobian& jacobian) 00217 { 00218 MT_Vector3 center = ComputeCenter(m_segment)*m_total_mass_inv; 00219 00220 // compute beta 00221 MT_Vector3 d_pos = m_goal_center - center; 00222 00223 m_distance = d_pos.length(); 00224 00225 #if 0 00226 if (m_distance > m_clamp_length) 00227 d_pos = (m_clamp_length/m_distance)*d_pos; 00228 #endif 00229 00230 jacobian.SetBetas(m_id, m_size, m_weight*d_pos); 00231 00232 // compute derivatives 00233 JacobianSegment(jacobian, center, m_segment); 00234 } 00235 00236 MT_Scalar IK_QCenterOfMassTask::Distance() const 00237 { 00238 return m_distance; 00239 } 00240