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 "../extern/IK_solver.h" 00035 00036 #include "IK_QJacobianSolver.h" 00037 #include "IK_QSegment.h" 00038 #include "IK_QTask.h" 00039 00040 #include <list> 00041 using namespace std; 00042 00043 class IK_QSolver { 00044 public: 00045 IK_QSolver() : root(NULL) {}; 00046 00047 IK_QJacobianSolver solver; 00048 IK_QSegment *root; 00049 std::list<IK_QTask*> tasks; 00050 }; 00051 00052 // FIXME: locks still result in small "residual" changes to the locked axes... 00053 IK_QSegment *CreateSegment(int flag, bool translate) 00054 { 00055 int ndof = 0; 00056 ndof += (flag & IK_XDOF)? 1: 0; 00057 ndof += (flag & IK_YDOF)? 1: 0; 00058 ndof += (flag & IK_ZDOF)? 1: 0; 00059 00060 IK_QSegment *seg; 00061 00062 if (ndof == 0) 00063 return NULL; 00064 else if (ndof == 1) { 00065 int axis; 00066 00067 if (flag & IK_XDOF) axis = 0; 00068 else if (flag & IK_YDOF) axis = 1; 00069 else axis = 2; 00070 00071 if (translate) 00072 seg = new IK_QTranslateSegment(axis); 00073 else 00074 seg = new IK_QRevoluteSegment(axis); 00075 } 00076 else if (ndof == 2) { 00077 int axis1, axis2; 00078 00079 if (flag & IK_XDOF) { 00080 axis1 = 0; 00081 axis2 = (flag & IK_YDOF)? 1: 2; 00082 } 00083 else { 00084 axis1 = 1; 00085 axis2 = 2; 00086 } 00087 00088 if (translate) 00089 seg = new IK_QTranslateSegment(axis1, axis2); 00090 else { 00091 if (axis1 + axis2 == 2) 00092 seg = new IK_QSwingSegment(); 00093 else 00094 seg = new IK_QElbowSegment((axis1 == 0)? 0: 2); 00095 } 00096 } 00097 else { 00098 if (translate) 00099 seg = new IK_QTranslateSegment(); 00100 else 00101 seg = new IK_QSphericalSegment(); 00102 } 00103 00104 return seg; 00105 } 00106 00107 IK_Segment *IK_CreateSegment(int flag) 00108 { 00109 IK_QSegment *rot = CreateSegment(flag, false); 00110 IK_QSegment *trans = CreateSegment(flag >> 3, true); 00111 00112 IK_QSegment *seg; 00113 00114 if (rot == NULL && trans == NULL) 00115 seg = new IK_QNullSegment(); 00116 else if (rot == NULL) 00117 seg = trans; 00118 else { 00119 seg = rot; 00120 00121 // make it seem from the interface as if the rotation and translation 00122 // segment are one 00123 if (trans) { 00124 seg->SetComposite(trans); 00125 trans->SetParent(seg); 00126 } 00127 } 00128 00129 return seg; 00130 } 00131 00132 void IK_FreeSegment(IK_Segment *seg) 00133 { 00134 IK_QSegment *qseg = (IK_QSegment*)seg; 00135 00136 if (qseg->Composite()) 00137 delete qseg->Composite(); 00138 delete qseg; 00139 } 00140 00141 void IK_SetParent(IK_Segment *seg, IK_Segment *parent) 00142 { 00143 IK_QSegment *qseg = (IK_QSegment*)seg; 00144 IK_QSegment *qparent = (IK_QSegment*)parent; 00145 00146 if (qparent && qparent->Composite()) 00147 qseg->SetParent(qparent->Composite()); 00148 else 00149 qseg->SetParent(qparent); 00150 } 00151 00152 void IK_SetTransform(IK_Segment *seg, float start[3], float rest[][3], float basis[][3], float length) 00153 { 00154 IK_QSegment *qseg = (IK_QSegment*)seg; 00155 00156 MT_Vector3 mstart(start); 00157 // convert from blender column major to moto row major 00158 MT_Matrix3x3 mbasis(basis[0][0], basis[1][0], basis[2][0], 00159 basis[0][1], basis[1][1], basis[2][1], 00160 basis[0][2], basis[1][2], basis[2][2]); 00161 MT_Matrix3x3 mrest(rest[0][0], rest[1][0], rest[2][0], 00162 rest[0][1], rest[1][1], rest[2][1], 00163 rest[0][2], rest[1][2], rest[2][2]); 00164 MT_Scalar mlength(length); 00165 00166 if (qseg->Composite()) { 00167 MT_Vector3 cstart(0, 0, 0); 00168 MT_Matrix3x3 cbasis; 00169 cbasis.setIdentity(); 00170 00171 qseg->SetTransform(mstart, mrest, mbasis, 0.0); 00172 qseg->Composite()->SetTransform(cstart, cbasis, cbasis, mlength); 00173 } 00174 else 00175 qseg->SetTransform(mstart, mrest, mbasis, mlength); 00176 } 00177 00178 void IK_SetLimit(IK_Segment *seg, IK_SegmentAxis axis, float lmin, float lmax) 00179 { 00180 IK_QSegment *qseg = (IK_QSegment*)seg; 00181 00182 if (axis >= IK_TRANS_X) { 00183 if(!qseg->Translational()) { 00184 if(qseg->Composite() && qseg->Composite()->Translational()) 00185 qseg = qseg->Composite(); 00186 else 00187 return; 00188 } 00189 00190 if(axis == IK_TRANS_X) axis = IK_X; 00191 else if(axis == IK_TRANS_Y) axis = IK_Y; 00192 else axis = IK_Z; 00193 } 00194 00195 qseg->SetLimit(axis, lmin, lmax); 00196 } 00197 00198 void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness) 00199 { 00200 if (stiffness < 0.0) 00201 return; 00202 00203 if (stiffness > 0.999) 00204 stiffness = 0.999; 00205 00206 IK_QSegment *qseg = (IK_QSegment*)seg; 00207 MT_Scalar weight = 1.0-stiffness; 00208 00209 if (axis >= IK_TRANS_X) { 00210 if(!qseg->Translational()) { 00211 if(qseg->Composite() && qseg->Composite()->Translational()) 00212 qseg = qseg->Composite(); 00213 else 00214 return; 00215 } 00216 00217 if(axis == IK_TRANS_X) axis = IK_X; 00218 else if(axis == IK_TRANS_Y) axis = IK_Y; 00219 else axis = IK_Z; 00220 } 00221 00222 qseg->SetWeight(axis, weight); 00223 } 00224 00225 void IK_GetBasisChange(IK_Segment *seg, float basis_change[][3]) 00226 { 00227 IK_QSegment *qseg = (IK_QSegment*)seg; 00228 00229 if (qseg->Translational() && qseg->Composite()) 00230 qseg = qseg->Composite(); 00231 00232 const MT_Matrix3x3& change = qseg->BasisChange(); 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