3 * ***** BEGIN GPL LICENSE BLOCK *****
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20 * All rights reserved.
22 * The Original Code is: all of this file.
24 * Original Author: Laurence
25 * Contributor(s): Brecht
27 * ***** END GPL LICENSE BLOCK *****
30 #include "../extern/IK_solver.h"
32 #include "IK_QJacobianSolver.h"
33 #include "IK_QSegment.h"
41 IK_QSolver() : root(NULL) {};
43 IK_QJacobianSolver solver;
45 std::list<IK_QTask*> tasks;
48 // FIXME: locks still result in small "residual" changes to the locked axes...
49 IK_QSegment *CreateSegment(int flag, bool translate)
52 ndof += (flag & IK_XDOF)? 1: 0;
53 ndof += (flag & IK_YDOF)? 1: 0;
54 ndof += (flag & IK_ZDOF)? 1: 0;
63 if (flag & IK_XDOF) axis = 0;
64 else if (flag & IK_YDOF) axis = 1;
68 seg = new IK_QTranslateSegment(axis);
70 seg = new IK_QRevoluteSegment(axis);
77 axis2 = (flag & IK_YDOF)? 1: 2;
85 seg = new IK_QTranslateSegment(axis1, axis2);
87 if (axis1 + axis2 == 2)
88 seg = new IK_QSwingSegment();
90 seg = new IK_QElbowSegment((axis1 == 0)? 0: 2);
95 seg = new IK_QTranslateSegment();
97 seg = new IK_QSphericalSegment();
103 IK_Segment *IK_CreateSegment(int flag)
105 IK_QSegment *rot = CreateSegment(flag, false);
106 IK_QSegment *trans = CreateSegment(flag >> 3, true);
110 if (rot == NULL && trans == NULL)
111 seg = new IK_QNullSegment();
112 else if (rot == NULL)
117 // make it seem from the interface as if the rotation and translation
120 seg->SetComposite(trans);
121 trans->SetParent(seg);
128 void IK_FreeSegment(IK_Segment *seg)
130 IK_QSegment *qseg = (IK_QSegment*)seg;
132 if (qseg->Composite())
133 delete qseg->Composite();
137 void IK_SetParent(IK_Segment *seg, IK_Segment *parent)
139 IK_QSegment *qseg = (IK_QSegment*)seg;
140 IK_QSegment *qparent = (IK_QSegment*)parent;
142 if (qparent && qparent->Composite())
143 qseg->SetParent(qparent->Composite());
145 qseg->SetParent(qparent);
148 void IK_SetTransform(IK_Segment *seg, float start[3], float rest[][3], float basis[][3], float length)
150 IK_QSegment *qseg = (IK_QSegment*)seg;
152 MT_Vector3 mstart(start);
153 // convert from blender column major to moto row major
154 MT_Matrix3x3 mbasis(basis[0][0], basis[1][0], basis[2][0],
155 basis[0][1], basis[1][1], basis[2][1],
156 basis[0][2], basis[1][2], basis[2][2]);
157 MT_Matrix3x3 mrest(rest[0][0], rest[1][0], rest[2][0],
158 rest[0][1], rest[1][1], rest[2][1],
159 rest[0][2], rest[1][2], rest[2][2]);
160 MT_Scalar mlength(length);
162 if (qseg->Composite()) {
163 MT_Vector3 cstart(0, 0, 0);
165 cbasis.setIdentity();
167 qseg->SetTransform(mstart, mrest, mbasis, 0.0);
168 qseg->Composite()->SetTransform(cstart, cbasis, cbasis, mlength);
171 qseg->SetTransform(mstart, mrest, mbasis, mlength);
174 void IK_SetLimit(IK_Segment *seg, IK_SegmentAxis axis, float lmin, float lmax)
176 IK_QSegment *qseg = (IK_QSegment*)seg;
178 if (axis >= IK_TRANS_X) {
179 if(!qseg->Translational()) {
180 if(qseg->Composite() && qseg->Composite()->Translational())
181 qseg = qseg->Composite();
186 if(axis == IK_TRANS_X) axis = IK_X;
187 else if(axis == IK_TRANS_Y) axis = IK_Y;
191 qseg->SetLimit(axis, lmin, lmax);
194 void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness)
199 if (stiffness > 0.999)
202 IK_QSegment *qseg = (IK_QSegment*)seg;
203 MT_Scalar weight = 1.0-stiffness;
205 if (axis >= IK_TRANS_X) {
206 if(!qseg->Translational()) {
207 if(qseg->Composite() && qseg->Composite()->Translational())
208 qseg = qseg->Composite();
213 if(axis == IK_TRANS_X) axis = IK_X;
214 else if(axis == IK_TRANS_Y) axis = IK_Y;
218 qseg->SetWeight(axis, weight);
221 void IK_GetBasisChange(IK_Segment *seg, float basis_change[][3])
223 IK_QSegment *qseg = (IK_QSegment*)seg;
224 const MT_Matrix3x3& change = qseg->BasisChange();
226 if (qseg->Translational() && qseg->Composite())
227 qseg = qseg->Composite();
229 // convert from moto row major to blender column major
230 basis_change[0][0] = (float)change[0][0];
231 basis_change[1][0] = (float)change[0][1];
232 basis_change[2][0] = (float)change[0][2];
233 basis_change[0][1] = (float)change[1][0];
234 basis_change[1][1] = (float)change[1][1];
235 basis_change[2][1] = (float)change[1][2];
236 basis_change[0][2] = (float)change[2][0];
237 basis_change[1][2] = (float)change[2][1];
238 basis_change[2][2] = (float)change[2][2];
241 void IK_GetTranslationChange(IK_Segment *seg, float *translation_change)
243 IK_QSegment *qseg = (IK_QSegment*)seg;
245 if (!qseg->Translational() && qseg->Composite())
246 qseg = qseg->Composite();
248 const MT_Vector3& change = qseg->TranslationChange();
250 translation_change[0] = (float)change[0];
251 translation_change[1] = (float)change[1];
252 translation_change[2] = (float)change[2];
255 IK_Solver *IK_CreateSolver(IK_Segment *root)
260 IK_QSolver *solver = new IK_QSolver();
261 solver->root = (IK_QSegment*)root;
263 return (IK_Solver*)solver;
266 void IK_FreeSolver(IK_Solver *solver)
271 IK_QSolver *qsolver = (IK_QSolver*)solver;
272 std::list<IK_QTask*>& tasks = qsolver->tasks;
273 std::list<IK_QTask*>::iterator task;
275 for (task = tasks.begin(); task != tasks.end(); task++)
281 void IK_SolverAddGoal(IK_Solver *solver, IK_Segment *tip, float goal[3], float weight)
283 if (solver == NULL || tip == NULL)
286 IK_QSolver *qsolver = (IK_QSolver*)solver;
287 IK_QSegment *qtip = (IK_QSegment*)tip;
289 if (qtip->Composite())
290 qtip = qtip->Composite();
292 MT_Vector3 pos(goal);
294 IK_QTask *ee = new IK_QPositionTask(true, qtip, pos);
295 ee->SetWeight(weight);
296 qsolver->tasks.push_back(ee);
299 void IK_SolverAddGoalOrientation(IK_Solver *solver, IK_Segment *tip, float goal[][3], float weight)
301 if (solver == NULL || tip == NULL)
304 IK_QSolver *qsolver = (IK_QSolver*)solver;
305 IK_QSegment *qtip = (IK_QSegment*)tip;
307 if (qtip->Composite())
308 qtip = qtip->Composite();
310 // convert from blender column major to moto row major
311 MT_Matrix3x3 rot(goal[0][0], goal[1][0], goal[2][0],
312 goal[0][1], goal[1][1], goal[2][1],
313 goal[0][2], goal[1][2], goal[2][2]);
315 IK_QTask *orient = new IK_QOrientationTask(true, qtip, rot);
316 orient->SetWeight(weight);
317 qsolver->tasks.push_back(orient);
320 void IK_SolverSetPoleVectorConstraint(IK_Solver *solver, IK_Segment *tip, float goal[3], float polegoal[3], float poleangle, int getangle)
322 if (solver == NULL || tip == NULL)
325 IK_QSolver *qsolver = (IK_QSolver*)solver;
326 IK_QSegment *qtip = (IK_QSegment*)tip;
328 MT_Vector3 qgoal(goal);
329 MT_Vector3 qpolegoal(polegoal);
331 qsolver->solver.SetPoleVectorConstraint(
332 qtip, qgoal, qpolegoal, poleangle, getangle);
335 float IK_SolverGetPoleAngle(IK_Solver *solver)
340 IK_QSolver *qsolver = (IK_QSolver*)solver;
342 return qsolver->solver.GetPoleAngle();
345 void IK_SolverAddCenterOfMass(IK_Solver *solver, IK_Segment *root, float goal[3], float weight)
347 if (solver == NULL || root == NULL)
350 IK_QSolver *qsolver = (IK_QSolver*)solver;
351 IK_QSegment *qroot = (IK_QSegment*)root;
353 // convert from blender column major to moto row major
354 MT_Vector3 center(goal);
356 IK_QTask *com = new IK_QCenterOfMassTask(true, qroot, center);
357 com->SetWeight(weight);
358 qsolver->tasks.push_back(com);
361 int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations)
366 IK_QSolver *qsolver = (IK_QSolver*)solver;
368 IK_QSegment *root = qsolver->root;
369 IK_QJacobianSolver& jacobian = qsolver->solver;
370 std::list<IK_QTask*>& tasks = qsolver->tasks;
371 MT_Scalar tol = tolerance;
373 if(!jacobian.Setup(root, tasks))
376 bool result = jacobian.Solve(root, tasks, tol, max_iterations);
378 return ((result)? 1: 0);