|
Blender
V2.59
|
00001 /* 00002 * $Id: IK_Solver.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 "../extern/IK_solver.h" 00036 00037 #include "IK_QJacobianSolver.h" 00038 #include "IK_QSegment.h" 00039 #include "IK_QTask.h" 00040 00041 #include <list> 00042 using namespace std; 00043 00044 class IK_QSolver { 00045 public: 00046 IK_QSolver() : root(NULL) {}; 00047 00048 IK_QJacobianSolver solver; 00049 IK_QSegment *root; 00050 std::list<IK_QTask*> tasks; 00051 }; 00052 00053 // FIXME: locks still result in small "residual" changes to the locked axes... 00054 IK_QSegment *CreateSegment(int flag, bool translate) 00055 { 00056 int ndof = 0; 00057 ndof += (flag & IK_XDOF)? 1: 0; 00058 ndof += (flag & IK_YDOF)? 1: 0; 00059 ndof += (flag & IK_ZDOF)? 1: 0; 00060 00061 IK_QSegment *seg; 00062 00063 if (ndof == 0) 00064 return NULL; 00065 else if (ndof == 1) { 00066 int axis; 00067 00068 if (flag & IK_XDOF) axis = 0; 00069 else if (flag & IK_YDOF) axis = 1; 00070 else axis = 2; 00071 00072 if (translate) 00073 seg = new IK_QTranslateSegment(axis); 00074 else 00075 seg = new IK_QRevoluteSegment(axis); 00076 } 00077 else if (ndof == 2) { 00078 int axis1, axis2; 00079 00080 if (flag & IK_XDOF) { 00081 axis1 = 0; 00082 axis2 = (flag & IK_YDOF)? 1: 2; 00083 } 00084 else { 00085 axis1 = 1; 00086 axis2 = 2; 00087 } 00088 00089 if (translate) 00090 seg = new IK_QTranslateSegment(axis1, axis2); 00091 else { 00092 if (axis1 + axis2 == 2) 00093 seg = new IK_QSwingSegment(); 00094 else 00095 seg = new IK_QElbowSegment((axis1 == 0)? 0: 2); 00096 } 00097 } 00098 else { 00099 if (translate) 00100 seg = new IK_QTranslateSegment(); 00101 else 00102 seg = new IK_QSphericalSegment(); 00103 } 00104 00105 return seg; 00106 } 00107 00108 IK_Segment *IK_CreateSegment(int flag) 00109 { 00110 IK_QSegment *rot = CreateSegment(flag, false); 00111 IK_QSegment *trans = CreateSegment(flag >> 3, true); 00112 00113 IK_QSegment *seg; 00114 00115 if (rot == NULL && trans == NULL) 00116 seg = new IK_QNullSegment(); 00117 else if (rot == NULL) 00118 seg = trans; 00119 else { 00120 seg = rot; 00121 00122 // make it seem from the interface as if the rotation and translation 00123 // segment are one 00124 if (trans) { 00125 seg->SetComposite(trans); 00126 trans->SetParent(seg); 00127 } 00128 } 00129 00130 return seg; 00131 } 00132 00133 void IK_FreeSegment(IK_Segment *seg) 00134 { 00135 IK_QSegment *qseg = (IK_QSegment*)seg; 00136 00137 if (qseg->Composite()) 00138 delete qseg->Composite(); 00139 delete qseg; 00140 } 00141 00142 void IK_SetParent(IK_Segment *seg, IK_Segment *parent) 00143 { 00144 IK_QSegment *qseg = (IK_QSegment*)seg; 00145 IK_QSegment *qparent = (IK_QSegment*)parent; 00146 00147 if (qparent && qparent->Composite()) 00148 qseg->SetParent(qparent->Composite()); 00149 else 00150 qseg->SetParent(qparent); 00151 } 00152 00153 void IK_SetTransform(IK_Segment *seg, float start[3], float rest[][3], float basis[][3], float length) 00154 { 00155 IK_QSegment *qseg = (IK_QSegment*)seg; 00156 00157 MT_Vector3 mstart(start); 00158 // convert from blender column major to moto row major 00159 MT_Matrix3x3 mbasis(basis[0][0], basis[1][0], basis[2][0], 00160 basis[0][1], basis[1][1], basis[2][1], 00161 basis[0][2], basis[1][2], basis[2][2]); 00162 MT_Matrix3x3 mrest(rest[0][0], rest[1][0], rest[2][0], 00163 rest[0][1], rest[1][1], rest[2][1], 00164 rest[0][2], rest[1][2], rest[2][2]); 00165 MT_Scalar mlength(length); 00166 00167 if (qseg->Composite()) { 00168 MT_Vector3 cstart(0, 0, 0); 00169 MT_Matrix3x3 cbasis; 00170 cbasis.setIdentity(); 00171 00172 qseg->SetTransform(mstart, mrest, mbasis, 0.0); 00173 qseg->Composite()->SetTransform(cstart, cbasis, cbasis, mlength); 00174 } 00175 else 00176 qseg->SetTransform(mstart, mrest, mbasis, mlength); 00177 } 00178 00179 void IK_SetLimit(IK_Segment *seg, IK_SegmentAxis axis, float lmin, float lmax) 00180 { 00181 IK_QSegment *qseg = (IK_QSegment*)seg; 00182 00183 if (axis >= IK_TRANS_X) { 00184 if(!qseg->Translational()) { 00185 if(qseg->Composite() && qseg->Composite()->Translational()) 00186 qseg = qseg->Composite(); 00187 else 00188 return; 00189 } 00190 00191 if(axis == IK_TRANS_X) axis = IK_X; 00192 else if(axis == IK_TRANS_Y) axis = IK_Y; 00193 else axis = IK_Z; 00194 } 00195 00196 qseg->SetLimit(axis, lmin, lmax); 00197 } 00198 00199 void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness) 00200 { 00201 if (stiffness < 0.0) 00202 return; 00203 00204 if (stiffness > 0.999) 00205 stiffness = 0.999; 00206 00207 IK_QSegment *qseg = (IK_QSegment*)seg; 00208 MT_Scalar weight = 1.0-stiffness; 00209 00210 if (axis >= IK_TRANS_X) { 00211 if(!qseg->Translational()) { 00212 if(qseg->Composite() && qseg->Composite()->Translational()) 00213 qseg = qseg->Composite(); 00214 else 00215 return; 00216 } 00217 00218 if(axis == IK_TRANS_X) axis = IK_X; 00219 else if(axis == IK_TRANS_Y) axis = IK_Y; 00220 else axis = IK_Z; 00221 } 00222 00223 qseg->SetWeight(axis, weight); 00224 } 00225 00226 void IK_GetBasisChange(IK_Segment *seg, float basis_change[][3]) 00227 { 00228 IK_QSegment *qseg = (IK_QSegment*)seg; 00229 const MT_Matrix3x3& change = qseg->BasisChange(); 00230 00231 if (qseg->Translational() && qseg->Composite()) 00232 qseg = qseg->Composite(); 00233 00234 // convert from moto row major to blender column major 00235 basis_change[0][0] = (float)change[0][0]; 00236 basis_change[1][0] = (float)change[0][1]; 00237 basis_change[2][0] = (float)change[0][2]; 00238 basis_change[0][1] = (float)change[1][0]; 00239 basis_change[1][1] = (float)change[1][1]; 00240 basis_change[2][1] = (float)change[1][2]; 00241 basis_change[0][2] = (float)change[2][0]; 00242 basis_change[1][2] = (float)change[2][1]; 00243 basis_change[2][2] = (float)change[2][2]; 00244 } 00245 00246 void IK_GetTranslationChange(IK_Segment *seg, float *translation_change) 00247 { 00248 IK_QSegment *qseg = (IK_QSegment*)seg; 00249 00250 if (!qseg->Translational() && qseg->Composite()) 00251 qseg = qseg->Composite(); 00252 00253 const MT_Vector3& change = qseg->TranslationChange(); 00254 00255 translation_change[0] = (float)change[0]; 00256 translation_change[1] = (float)change[1]; 00257 translation_change[2] = (float)change[2]; 00258 } 00259 00260 IK_Solver *IK_CreateSolver(IK_Segment *root) 00261 { 00262 if (root == NULL) 00263 return NULL; 00264 00265 IK_QSolver *solver = new IK_QSolver(); 00266 solver->root = (IK_QSegment*)root; 00267 00268 return (IK_Solver*)solver; 00269 } 00270 00271 void IK_FreeSolver(IK_Solver *solver) 00272 { 00273 if (solver == NULL) 00274 return; 00275 00276 IK_QSolver *qsolver = (IK_QSolver*)solver; 00277 std::list<IK_QTask*>& tasks = qsolver->tasks; 00278 std::list<IK_QTask*>::iterator task; 00279 00280 for (task = tasks.begin(); task != tasks.end(); task++) 00281 delete (*task); 00282 00283 delete qsolver; 00284 } 00285 00286 void IK_SolverAddGoal(IK_Solver *solver, IK_Segment *tip, float goal[3], float weight) 00287 { 00288 if (solver == NULL || tip == NULL) 00289 return; 00290 00291 IK_QSolver *qsolver = (IK_QSolver*)solver; 00292 IK_QSegment *qtip = (IK_QSegment*)tip; 00293 00294 if (qtip->Composite()) 00295 qtip = qtip->Composite(); 00296 00297 MT_Vector3 pos(goal); 00298 00299 IK_QTask *ee = new IK_QPositionTask(true, qtip, pos); 00300 ee->SetWeight(weight); 00301 qsolver->tasks.push_back(ee); 00302 } 00303 00304 void IK_SolverAddGoalOrientation(IK_Solver *solver, IK_Segment *tip, float goal[][3], float weight) 00305 { 00306 if (solver == NULL || tip == NULL) 00307 return; 00308 00309 IK_QSolver *qsolver = (IK_QSolver*)solver; 00310 IK_QSegment *qtip = (IK_QSegment*)tip; 00311 00312 if (qtip->Composite()) 00313 qtip = qtip->Composite(); 00314 00315 // convert from blender column major to moto row major 00316 MT_Matrix3x3 rot(goal[0][0], goal[1][0], goal[2][0], 00317 goal[0][1], goal[1][1], goal[2][1], 00318 goal[0][2], goal[1][2], goal[2][2]); 00319 00320 IK_QTask *orient = new IK_QOrientationTask(true, qtip, rot); 00321 orient->SetWeight(weight); 00322 qsolver->tasks.push_back(orient); 00323 } 00324 00325 void IK_SolverSetPoleVectorConstraint(IK_Solver *solver, IK_Segment *tip, float goal[3], float polegoal[3], float poleangle, int getangle) 00326 { 00327 if (solver == NULL || tip == NULL) 00328 return; 00329 00330 IK_QSolver *qsolver = (IK_QSolver*)solver; 00331 IK_QSegment *qtip = (IK_QSegment*)tip; 00332 00333 MT_Vector3 qgoal(goal); 00334 MT_Vector3 qpolegoal(polegoal); 00335 00336 qsolver->solver.SetPoleVectorConstraint( 00337 qtip, qgoal, qpolegoal, poleangle, getangle); 00338 } 00339 00340 float IK_SolverGetPoleAngle(IK_Solver *solver) 00341 { 00342 if (solver == NULL) 00343 return 0.0f; 00344 00345 IK_QSolver *qsolver = (IK_QSolver*)solver; 00346 00347 return qsolver->solver.GetPoleAngle(); 00348 } 00349 00350 void IK_SolverAddCenterOfMass(IK_Solver *solver, IK_Segment *root, float goal[3], float weight) 00351 { 00352 if (solver == NULL || root == NULL) 00353 return; 00354 00355 IK_QSolver *qsolver = (IK_QSolver*)solver; 00356 IK_QSegment *qroot = (IK_QSegment*)root; 00357 00358 // convert from blender column major to moto row major 00359 MT_Vector3 center(goal); 00360 00361 IK_QTask *com = new IK_QCenterOfMassTask(true, qroot, center); 00362 com->SetWeight(weight); 00363 qsolver->tasks.push_back(com); 00364 } 00365 00366 int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations) 00367 { 00368 if (solver == NULL) 00369 return 0; 00370 00371 IK_QSolver *qsolver = (IK_QSolver*)solver; 00372 00373 IK_QSegment *root = qsolver->root; 00374 IK_QJacobianSolver& jacobian = qsolver->solver; 00375 std::list<IK_QTask*>& tasks = qsolver->tasks; 00376 MT_Scalar tol = tolerance; 00377 00378 if(!jacobian.Setup(root, tasks)) 00379 return 0; 00380 00381 bool result = jacobian.Solve(root, tasks, tol, max_iterations); 00382 00383 return ((result)? 1: 0); 00384 } 00385