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