Blender V4.3
iksolver_plugin.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <algorithm>
10
11#include "MEM_guardedalloc.h"
12
13#include "BIK_api.h"
14#include "BLI_blenlib.h"
15#include "BLI_math_matrix.h"
16#include "BLI_math_rotation.h"
17#include "BLI_math_vector.h"
18#include "BLI_utildefines.h"
19#include "BLI_vector.hh"
20
21#include "BKE_armature.hh"
22#include "BKE_constraint.h"
23
24#include "DNA_action_types.h"
25#include "DNA_armature_types.h"
27#include "DNA_object_types.h"
28
29#include "IK_solver.h"
30#include "iksolver_plugin.h"
31
32#include <cstring> /* memcpy */
33
34#define USE_NONUNIFORM_SCALE
35
36/* ********************** THE IK SOLVER ******************* */
37
39 blender::Vector<bConstraint *> &ik_constraints)
40{
42 if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
43 bKinematicConstraint *data = (bKinematicConstraint *)con->data;
44 if (data->flag & CONSTRAINT_IK_AUTO) {
45 ik_constraints.append(con);
46 continue;
47 }
48 if (data->tar == nullptr) {
49 continue;
50 }
51 if (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0) {
52 continue;
53 }
54 if (con->flag & CONSTRAINT_DISABLE) {
55 continue;
56 }
57 ik_constraints.append(con);
58 }
59 }
60}
61
62/* allocates PoseTree, and links that to root bone/channel */
63/* NOTE: detecting the IK chain is duplicate code...
64 * in drawarmature.c and in transform_conversions.c */
65static void initialize_posetree(Object * /*ob*/, bPoseChannel *pchan_tip)
66{
67 blender::Vector<bConstraint *> ik_constraints;
68 find_ik_constraints(&pchan_tip->constraints, ik_constraints);
69
70 if (ik_constraints.is_empty()) {
71 return;
72 }
73
74 for (bConstraint *constraint : ik_constraints) {
75 bPoseChannel *curchan, *pchan_root = nullptr, *chanlist[256], **oldchan;
76 int segcount = 0;
77 PoseTarget *target;
79 bKinematicConstraint *data = (bKinematicConstraint *)constraint->data;
80 /* exclude tip from chain? */
81 if (!(data->flag & CONSTRAINT_IK_TIP) && pchan_tip->parent != nullptr) {
82 pchan_tip = pchan_tip->parent;
83 }
84
85 /* Find the chain's root & count the segments needed */
86 for (curchan = pchan_tip; curchan; curchan = curchan->parent) {
87 pchan_root = curchan;
88
89 curchan->flag |= POSE_CHAIN; /* don't forget to clear this */
90 chanlist[segcount] = curchan;
91 segcount++;
92
93 if (segcount == data->rootbone || segcount > 255) {
94 break; /* 255 is weak */
95 }
96 }
97 if (!segcount) {
98 continue;
99 }
100
101 /* setup the chain data */
102 /* we make tree-IK, unless all existing targets are in this chain */
103 for (tree = static_cast<PoseTree *>(pchan_root->iktree.first); tree; tree = tree->next) {
104 for (target = static_cast<PoseTarget *>(tree->targets.first); target; target = target->next)
105 {
106 curchan = tree->pchan[target->tip];
107 if (curchan->flag & POSE_CHAIN) {
108 curchan->flag &= ~POSE_CHAIN;
109 }
110 else {
111 break;
112 }
113 }
114 if (target) {
115 break;
116 }
117 }
118
119 /* create a target */
120 target = static_cast<PoseTarget *>(MEM_callocN(sizeof(PoseTarget), "posetarget"));
121 target->con = constraint;
122 pchan_tip->flag &= ~POSE_CHAIN;
123
124 if (tree == nullptr) {
125 /* make new tree */
126 tree = static_cast<PoseTree *>(MEM_callocN(sizeof(PoseTree), "posetree"));
127
129
130 tree->iterations = data->iterations;
131 tree->totchannel = segcount;
132 tree->stretch = (data->flag & CONSTRAINT_IK_STRETCH);
133
134 tree->pchan = static_cast<bPoseChannel **>(
135 MEM_callocN(segcount * sizeof(void *), "ik tree pchan"));
136 tree->parent = static_cast<int *>(MEM_callocN(segcount * sizeof(int), "ik tree parent"));
137 for (int a = 0; a < segcount; a++) {
138 tree->pchan[a] = chanlist[segcount - a - 1];
139 tree->parent[a] = a - 1;
140 }
141 target->tip = segcount - 1;
142
143 /* AND! link the tree to the root */
144 BLI_addtail(&pchan_root->iktree, tree);
145 }
146 else {
147 tree->iterations = std::max<int>(data->iterations, tree->iterations);
148 tree->stretch = tree->stretch && !(data->flag & CONSTRAINT_IK_STRETCH);
149
150 /* Skip common pose channels and add remaining. */
151 const int size = std::min(segcount, tree->totchannel);
152 int a, t;
153 a = t = 0;
154 while (a < size && t < tree->totchannel) {
155 /* locate first matching channel */
156 for (; t < tree->totchannel && tree->pchan[t] != chanlist[segcount - a - 1]; t++) {
157 /* pass */
158 }
159 if (t >= tree->totchannel) {
160 break;
161 }
162 for (; a < size && t < tree->totchannel && tree->pchan[t] == chanlist[segcount - a - 1];
163 a++, t++)
164 {
165 /* pass */
166 }
167 }
168
169 segcount = segcount - a;
170 target->tip = tree->totchannel + segcount - 1;
171
172 if (segcount > 0) {
173 int parent;
174 for (parent = a - 1; parent < tree->totchannel; parent++) {
175 if (tree->pchan[parent] == chanlist[segcount - 1]->parent) {
176 break;
177 }
178 }
179
180 /* shouldn't happen, but could with dependency cycles */
181 if (parent == tree->totchannel) {
182 parent = a - 1;
183 }
184
185 /* resize array */
186 const int newsize = tree->totchannel + segcount;
187 oldchan = tree->pchan;
188 int *oldparent = tree->parent;
189
190 tree->pchan = static_cast<bPoseChannel **>(
191 MEM_callocN(newsize * sizeof(void *), "ik tree pchan"));
192 tree->parent = static_cast<int *>(MEM_callocN(newsize * sizeof(int), "ik tree parent"));
193 memcpy(tree->pchan, oldchan, sizeof(void *) * tree->totchannel);
194 memcpy(tree->parent, oldparent, sizeof(int) * tree->totchannel);
195 MEM_freeN(oldchan);
196 MEM_freeN(oldparent);
197
198 /* add new pose channels at the end, in reverse order */
199 for (a = 0; a < segcount; a++) {
200 tree->pchan[tree->totchannel + a] = chanlist[segcount - a - 1];
201 tree->parent[tree->totchannel + a] = tree->totchannel + a - 1;
202 }
203 tree->parent[tree->totchannel] = parent;
204
205 tree->totchannel = newsize;
206 }
207
208 /* move tree to end of list, for correct evaluation order */
209 BLI_remlink(&pchan_root->iktree, tree);
210 BLI_addtail(&pchan_root->iktree, tree);
211 }
212
213 /* add target to the tree */
214 BLI_addtail(&tree->targets, target);
215 /* mark root channel having an IK tree */
216 pchan_root->flag |= POSE_IKTREE;
217
218 /* Per bone only one active IK constraint is supported. Inactive constraints still need to be
219 * added for the depsgraph to evaluate properly. */
220 if (constraint->enforce != 0.0 && !(constraint->flag & CONSTRAINT_OFF)) {
221 break;
222 }
223 }
224}
225
226/* transform from bone(b) to bone(b+1), store in chan_mat */
227static void make_dmats(bPoseChannel *pchan)
228{
229 if (pchan->parent) {
230 float iR_parmat[4][4];
231 invert_m4_m4(iR_parmat, pchan->parent->pose_mat);
232 mul_m4_m4m4(pchan->chan_mat, iR_parmat, pchan->pose_mat); /* delta mat */
233 }
234 else {
235 copy_m4_m4(pchan->chan_mat, pchan->pose_mat);
236 }
237}
238
239/* applies IK matrix to pchan, IK is done separated */
240/* formula: pose_mat(b) = pose_mat(b-1) * diffmat(b-1, b) * ik_mat(b) */
241/* to make this work, the diffmats have to be precalculated! Stored in chan_mat */
243 float ik_mat[3][3]) /* nr = to detect if this is first bone */
244{
245 float vec[3], ikmat[4][4];
246
247 copy_m4_m3(ikmat, ik_mat);
248
249 if (pchan->parent) {
250 mul_m4_m4m4(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat);
251 }
252 else {
253 copy_m4_m4(pchan->pose_mat, pchan->chan_mat);
254 }
255
256#ifdef USE_NONUNIFORM_SCALE
257 /* apply IK mat, but as if the bones have uniform scale since the IK solver
258 * is not aware of non-uniform scale */
259 float scale[3];
260 mat4_to_size(scale, pchan->pose_mat);
261 normalize_v3_length(pchan->pose_mat[0], scale[1]);
262 normalize_v3_length(pchan->pose_mat[2], scale[1]);
263#endif
264
265 mul_m4_m4m4(pchan->pose_mat, pchan->pose_mat, ikmat);
266
267#ifdef USE_NONUNIFORM_SCALE
268 float ik_scale[3];
269 mat3_to_size(ik_scale, ik_mat);
270 normalize_v3_length(pchan->pose_mat[0], scale[0] * ik_scale[0]);
271 normalize_v3_length(pchan->pose_mat[2], scale[2] * ik_scale[2]);
272#endif
273
274 /* calculate head */
275 copy_v3_v3(pchan->pose_head, pchan->pose_mat[3]);
276 /* calculate tail */
277 copy_v3_v3(vec, pchan->pose_mat[1]);
278 mul_v3_fl(vec, pchan->bone->length);
279 add_v3_v3v3(pchan->pose_tail, pchan->pose_head, vec);
280
281 pchan->flag |= POSE_DONE;
282}
283
288static void execute_posetree(Depsgraph *depsgraph, Scene *scene, Object *ob, PoseTree *tree)
289{
290 float R_parmat[3][3], identity[3][3];
291 float iR_parmat[3][3];
292 float R_bonemat[3][3];
293 float goalrot[3][3], goalpos[3];
294 float rootmat[4][4], imat[4][4];
295 float goal[4][4], goalinv[4][4];
296 float irest_basis[3][3], full_basis[3][3];
297 float end_pose[4][4], world_pose[4][4];
298 float basis[3][3], rest_basis[3][3], start[3], *ikstretch = nullptr;
299 float resultinf = 0.0f;
300 int a, flag, hasstretch = 0, resultblend = 0;
301 bPoseChannel *pchan;
302 IK_Segment *seg, *parent, **iktree, *iktarget;
303 IK_Solver *solver;
304 bKinematicConstraint *data, *poleangledata = nullptr;
305 Bone *bone;
306
307 if (tree->totchannel == 0) {
308 return;
309 }
310
311 iktree = static_cast<IK_Segment **>(MEM_mallocN(sizeof(void *) * tree->totchannel, "ik tree"));
312
313 for (a = 0; a < tree->totchannel; a++) {
314 float length;
315 pchan = tree->pchan[a];
316 bone = pchan->bone;
317
318 /* set DoF flag */
319 flag = 0;
320 if (!(pchan->ikflag & BONE_IK_NO_XDOF) && !(pchan->ikflag & BONE_IK_NO_XDOF_TEMP)) {
321 flag |= IK_XDOF;
322 }
323 if (!(pchan->ikflag & BONE_IK_NO_YDOF) && !(pchan->ikflag & BONE_IK_NO_YDOF_TEMP)) {
324 flag |= IK_YDOF;
325 }
326 if (!(pchan->ikflag & BONE_IK_NO_ZDOF) && !(pchan->ikflag & BONE_IK_NO_ZDOF_TEMP)) {
327 flag |= IK_ZDOF;
328 }
329
330 if (tree->stretch && (pchan->ikstretch > 0.0f)) {
332 hasstretch = 1;
333 }
334
335 seg = iktree[a] = IK_CreateSegment(flag);
336
337 /* find parent */
338 if (a == 0) {
339 parent = nullptr;
340 }
341 else {
342 parent = iktree[tree->parent[a]];
343 }
344
345 IK_SetParent(seg, parent);
346
347 /* get the matrix that transforms from prevbone into this bone */
348 copy_m3_m4(R_bonemat, pchan->pose_mat);
349
350 /* gather transformations for this IK segment */
351
352 if (pchan->parent) {
353 copy_m3_m4(R_parmat, pchan->parent->pose_mat);
354 }
355 else {
356 unit_m3(R_parmat);
357 }
358
359 /* bone offset */
360 if (pchan->parent && (a > 0)) {
361 sub_v3_v3v3(start, pchan->pose_head, pchan->parent->pose_tail);
362 }
363 else {
364 /* only root bone (a = 0) has no parent */
365 start[0] = start[1] = start[2] = 0.0f;
366 }
367
368 /* change length based on bone size */
369 length = bone->length * len_v3(R_bonemat[1]);
370
371 /* basis must be pure rotation */
372 normalize_m3(R_bonemat);
373 normalize_m3(R_parmat);
374
375 /* compute rest basis and its inverse */
376 copy_m3_m3(rest_basis, bone->bone_mat);
377 transpose_m3_m3(irest_basis, bone->bone_mat);
378
379 /* compute basis with rest_basis removed */
380 invert_m3_m3(iR_parmat, R_parmat);
381 mul_m3_m3m3(full_basis, iR_parmat, R_bonemat);
382 mul_m3_m3m3(basis, irest_basis, full_basis);
383
384 /* transform offset into local bone space */
385 mul_m3_v3(iR_parmat, start);
386
387 IK_SetTransform(seg, start, rest_basis, basis, length);
388
389 if (pchan->ikflag & BONE_IK_XLIMIT) {
390 IK_SetLimit(seg, IK_X, pchan->limitmin[0], pchan->limitmax[0]);
391 }
392 if (pchan->ikflag & BONE_IK_YLIMIT) {
393 IK_SetLimit(seg, IK_Y, pchan->limitmin[1], pchan->limitmax[1]);
394 }
395 if (pchan->ikflag & BONE_IK_ZLIMIT) {
396 IK_SetLimit(seg, IK_Z, pchan->limitmin[2], pchan->limitmax[2]);
397 }
398
399 IK_SetStiffness(seg, IK_X, pchan->stiffness[0]);
400 IK_SetStiffness(seg, IK_Y, pchan->stiffness[1]);
401 IK_SetStiffness(seg, IK_Z, pchan->stiffness[2]);
402
403 if (tree->stretch && (pchan->ikstretch > 0.0f)) {
404 const float ikstretch_sq = square_f(pchan->ikstretch);
405 /* this function does its own clamping */
406 IK_SetStiffness(seg, IK_TRANS_Y, 1.0f - ikstretch_sq);
408 }
409 }
410
411 solver = IK_CreateSolver(iktree[0]);
412
413 /* set solver goals */
414
415 /* first set the goal inverse transform, assuming the root of tree was done ok! */
416 pchan = tree->pchan[0];
417 if (pchan->parent) {
418 /* transform goal by parent mat, so this rotation is not part of the
419 * segment's basis. otherwise rotation limits do not work on the
420 * local transform of the segment itself. */
421 copy_m4_m4(rootmat, pchan->parent->pose_mat);
422 /* However, we do not want to get (i.e. reverse) parent's scale,
423 * as it generates #31008 kind of nasty bugs. */
424 normalize_m4(rootmat);
425 }
426 else {
427 unit_m4(rootmat);
428 }
429 copy_v3_v3(rootmat[3], pchan->pose_head);
430
431 mul_m4_m4m4(imat, ob->object_to_world().ptr(), rootmat);
432 invert_m4_m4(goalinv, imat);
433
434 LISTBASE_FOREACH (PoseTarget *, target, &tree->targets) {
435 float polepos[3];
436 int poleconstrain = 0;
437
438 data = (bKinematicConstraint *)target->con->data;
439
440 /* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though
441 * strictly speaking, it is a posechannel)
442 */
444 depsgraph, scene, target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
445
446 /* and set and transform goal */
447 mul_m4_m4m4(goal, goalinv, rootmat);
448
449 copy_v3_v3(goalpos, goal[3]);
450 copy_m3_m4(goalrot, goal);
451 normalize_m3(goalrot);
452
453 /* same for pole vector target */
454 if (data->poletar) {
456 depsgraph, scene, target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
457
458 if (data->flag & CONSTRAINT_IK_SETANGLE) {
459 /* don't solve IK when we are setting the pole angle */
460 break;
461 }
462
463 mul_m4_m4m4(goal, goalinv, rootmat);
464 copy_v3_v3(polepos, goal[3]);
465 poleconstrain = 1;
466
467 /* for pole targets, we blend the result of the ik solver
468 * instead of the target position, otherwise we can't get
469 * a smooth transition */
470 resultblend = 1;
471 resultinf = (target->con->flag & CONSTRAINT_OFF) ? 0.0f : target->con->enforce;
472
473 if (data->flag & CONSTRAINT_IK_GETANGLE) {
474 poleangledata = data;
475 data->flag &= ~CONSTRAINT_IK_GETANGLE;
476 }
477 }
478
479 /* do we need blending? */
480 if (!resultblend && ((target->con->flag & CONSTRAINT_OFF) || target->con->enforce != 1.0f)) {
481 float q1[4], q2[4], q[4];
482 float fac = (target->con->flag & CONSTRAINT_OFF) ? 0.0f : target->con->enforce;
483 float mfac = 1.0f - fac;
484
485 pchan = tree->pchan[target->tip];
486
487 /* end effector in world space */
488 copy_m4_m4(end_pose, pchan->pose_mat);
489 copy_v3_v3(end_pose[3], pchan->pose_tail);
490 mul_m4_series(world_pose, goalinv, ob->object_to_world().ptr(), end_pose);
491
492 /* blend position */
493 goalpos[0] = fac * goalpos[0] + mfac * world_pose[3][0];
494 goalpos[1] = fac * goalpos[1] + mfac * world_pose[3][1];
495 goalpos[2] = fac * goalpos[2] + mfac * world_pose[3][2];
496
497 /* blend rotation */
498 mat3_to_quat(q1, goalrot);
499 mat4_to_quat(q2, world_pose);
500 interp_qt_qtqt(q, q1, q2, mfac);
501 quat_to_mat3(goalrot, q);
502 }
503
504 iktarget = iktree[target->tip];
505
506 if ((data->flag & CONSTRAINT_IK_POS) && data->weight != 0.0f) {
507 if (poleconstrain) {
509 solver, iktarget, goalpos, polepos, data->poleangle, (poleangledata == data));
510 }
511 IK_SolverAddGoal(solver, iktarget, goalpos, data->weight);
512 }
513 if ((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0f)) {
514 if ((data->flag & CONSTRAINT_IK_AUTO) == 0) {
515 IK_SolverAddGoalOrientation(solver, iktarget, goalrot, data->orientweight);
516 }
517 }
518 }
519
520 /* solve */
521 IK_Solve(solver, 0.0f, tree->iterations);
522
523 if (poleangledata) {
524 poleangledata->poleangle = IK_SolverGetPoleAngle(solver);
525 }
526
527 IK_FreeSolver(solver);
528
529 /* gather basis changes */
530 tree->basis_change = static_cast<float(*)[3][3]>(
531 MEM_mallocN(sizeof(float[3][3]) * tree->totchannel, "ik basis change"));
532 if (hasstretch) {
533 ikstretch = static_cast<float *>(MEM_mallocN(sizeof(float) * tree->totchannel, "ik stretch"));
534 }
535
536 for (a = 0; a < tree->totchannel; a++) {
537 IK_GetBasisChange(iktree[a], tree->basis_change[a]);
538
539 if (hasstretch) {
540 /* have to compensate for scaling received from parent */
541 float parentstretch, stretch;
542
543 pchan = tree->pchan[a];
544 parentstretch = (tree->parent[a] >= 0) ? ikstretch[tree->parent[a]] : 1.0f;
545
546 if (tree->stretch && (pchan->ikstretch > 0.0f)) {
547 float trans[3], length;
548
549 IK_GetTranslationChange(iktree[a], trans);
550 length = pchan->bone->length * len_v3(pchan->pose_mat[1]);
551
552 ikstretch[a] = (length == 0.0f) ? 1.0f : (trans[1] + length) / length;
553 }
554 else {
555 ikstretch[a] = 1.0;
556 }
557
558 stretch = (parentstretch == 0.0f) ? 1.0f : ikstretch[a] / parentstretch;
559
560 mul_v3_fl(tree->basis_change[a][0], stretch);
561 mul_v3_fl(tree->basis_change[a][1], stretch);
562 mul_v3_fl(tree->basis_change[a][2], stretch);
563 }
564
565 if (resultblend && resultinf != 1.0f) {
566 unit_m3(identity);
567 blend_m3_m3m3(tree->basis_change[a], identity, tree->basis_change[a], resultinf);
568 }
569
570 IK_FreeSegment(iktree[a]);
571 }
572
573 MEM_freeN(iktree);
574 if (ikstretch) {
575 MEM_freeN(ikstretch);
576 }
577}
578
580{
581 BLI_freelistN(&tree->targets);
582 if (tree->pchan) {
583 MEM_freeN(tree->pchan);
584 }
585 if (tree->parent) {
586 MEM_freeN(tree->parent);
587 }
588 if (tree->basis_change) {
589 MEM_freeN(tree->basis_change);
590 }
592}
593
594/* ------------------------------
595 * Plugin API for legacy iksolver */
596
597void iksolver_initialize_tree(Depsgraph * /*depsgraph*/,
598 Scene * /*scene*/,
599 Object *ob,
600 float /*ctime*/)
601{
602 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
603 if (pchan->constflag & PCHAN_HAS_IK) { /* flag is set on editing constraints */
604 initialize_posetree(ob, pchan); /* will attach it to root! */
605 }
606 }
607 ob->pose->flag &= ~POSE_WAS_REBUILT;
608}
609
611 Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
612{
613 while (pchan_root->iktree.first) {
614 PoseTree *tree = static_cast<PoseTree *>(pchan_root->iktree.first);
615 int a;
616
617 /* stop on the first tree that isn't a standard IK chain */
618 if (tree->type != CONSTRAINT_TYPE_KINEMATIC) {
619 return;
620 }
621
622 /* Test if this IK tree has any influence, so we can skip computations. */
623 bool has_influence = false;
624 LISTBASE_FOREACH (PoseTarget *, target, &tree->targets) {
625 if (!(target->con->flag & CONSTRAINT_OFF) && target->con->enforce != 0.0f) {
626 has_influence = true;
627 break;
628 }
629 }
630
631 /* 4. walk over the tree for regular solving */
632 for (a = 0; a < tree->totchannel; a++) {
633 if (!(tree->pchan[a]->flag & POSE_DONE)) { /* successive trees can set the flag */
634 BKE_pose_where_is_bone(depsgraph, scene, ob, tree->pchan[a], ctime, true);
635 }
636 /* Tell blender that this channel was controlled by IK,
637 * it's cleared on each BKE_pose_where_is(). */
638 tree->pchan[a]->flag |= POSE_CHAIN;
639
640 /* Immediately done if IK solving gets skipped. */
641 if (!has_influence) {
642 tree->pchan[a]->flag |= POSE_DONE;
643 }
644 }
645
646 if (has_influence) {
647 /* 5. execute the IK solver */
648 execute_posetree(depsgraph, scene, ob, tree);
649
650 /* 6. apply the differences to the channels,
651 * we need to calculate the original differences first */
652 for (a = 0; a < tree->totchannel; a++) {
653 make_dmats(tree->pchan[a]);
654 }
655
656 for (a = 0; a < tree->totchannel; a++) {
657 /* sets POSE_DONE */
658 where_is_ik_bone(tree->pchan[a], tree->basis_change[a]);
659 }
660 }
661
662 /* 7. and free */
663 BLI_remlink(&pchan_root->iktree, tree);
665 }
666}
667
668void iksolver_release_tree(Scene * /*scene*/, Object *ob, float /*ctime*/)
669{
671}
672
674{
675 LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
676 if ((pchan->flag & POSE_IKTREE) == 0) {
677 continue;
678 }
679
680 while (pchan->iktree.first) {
681 PoseTree *tree = static_cast<PoseTree *>(pchan->iktree.first);
682
683 /* stop on the first tree that isn't a standard IK chain */
684 if (tree->type != CONSTRAINT_TYPE_KINEMATIC) {
685 break;
686 }
687
688 BLI_remlink(&pchan->iktree, tree);
690 }
691 }
692}
void BKE_pose_where_is_bone(Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan, float ctime, bool do_extra)
Definition armature.cc:2877
void BKE_constraint_target_matrix_get(struct Depsgraph *depsgraph, struct Scene *scene, struct bConstraint *con, int index, short ownertype, void *ownerdata, float mat[4][4], float ctime)
#define LISTBASE_FOREACH(type, var, list)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
MINLINE float square_f(float a)
void mul_m3_v3(const float M[3][3], float r[3])
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void copy_m3_m3(float m1[3][3], const float m2[3][3])
void unit_m3(float m[3][3])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
void unit_m4(float m[4][4])
Definition rct.c:1127
void copy_m4_m3(float m1[4][4], const float m2[3][3])
void normalize_m3(float R[3][3]) ATTR_NONNULL()
#define mul_m4_series(...)
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void mat4_to_size(float size[3], const float M[4][4])
void transpose_m3_m3(float R[3][3], const float M[3][3])
void blend_m3_m3m3(float out[3][3], const float dst[3][3], const float src[3][3], float srcweight)
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
void mat3_to_size(float size[3], const float M[3][3])
void normalize_m4(float R[4][4]) ATTR_NONNULL()
void interp_qt_qtqt(float q[4], const float a[4], const float b[4], float t)
void quat_to_mat3(float m[3][3], const float q[4])
void mat3_to_quat(float q[4], const float mat[3][3])
void mat4_to_quat(float q[4], const float mat[4][4])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float normalize_v3_length(float n[3], float unit_length)
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
@ BONE_IK_ZLIMIT
@ BONE_IK_NO_YDOF_TEMP
@ BONE_IK_XLIMIT
@ BONE_IK_NO_XDOF_TEMP
@ BONE_IK_NO_ZDOF
@ BONE_IK_NO_ZDOF_TEMP
@ BONE_IK_YLIMIT
@ BONE_IK_NO_YDOF
@ BONE_IK_NO_XDOF
@ PCHAN_HAS_IK
@ POSE_DONE
@ POSE_IKTREE
@ POSE_CHAIN
@ CONSTRAINT_OFF
@ CONSTRAINT_DISABLE
@ CONSTRAINT_IK_ROT
@ CONSTRAINT_IK_GETANGLE
@ CONSTRAINT_IK_SETANGLE
@ CONSTRAINT_IK_POS
@ CONSTRAINT_IK_AUTO
@ CONSTRAINT_IK_STRETCH
@ CONSTRAINT_IK_TIP
@ CONSTRAINT_TYPE_KINEMATIC
@ CONSTRAINT_OBTYPE_OBJECT
Object is a sort of wrapper for general info.
@ OB_ARMATURE
IK_Solver * IK_CreateSolver(IK_Segment *root)
float IK_SolverGetPoleAngle(IK_Solver *solver)
#define IK_STRETCH_STIFF_MAX
Definition IK_solver.h:147
void IK_SolverSetPoleVectorConstraint(IK_Solver *solver, IK_Segment *tip, float goal[3], float polegoal[3], float poleangle, int getangle)
void IK_Segment
Definition IK_solver.h:80
void IK_SetParent(IK_Segment *seg, IK_Segment *parent)
void IK_FreeSolver(IK_Solver *solver)
#define IK_STRETCH_STIFF_MIN
Definition IK_solver.h:146
IK_Segment * IK_CreateSegment(int flag)
Definition IK_Solver.cpp:97
void IK_FreeSegment(IK_Segment *seg)
@ IK_TRANS_YDOF
Definition IK_solver.h:87
void IK_SolverAddGoalOrientation(IK_Solver *solver, IK_Segment *tip, float goal[][3], float weight)
void IK_SetLimit(IK_Segment *seg, IK_SegmentAxis axis, float lmin, float lmax)
void IK_SolverAddGoal(IK_Solver *solver, IK_Segment *tip, float goal[3], float weight)
int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations)
void IK_SetTransform(IK_Segment *seg, float start[3], float rest_basis[][3], float basis[][3], float length)
void IK_GetBasisChange(IK_Segment *seg, float basis_change[][3])
void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness)
void IK_GetTranslationChange(IK_Segment *seg, float *translation_change)
void IK_Solver
Definition IK_solver.h:125
Read Guarded memory(de)allocation.
btSequentialImpulseConstraintSolverMt int btPersistentManifold int btTypedConstraint ** constraints
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
void append(const T &value)
bool is_empty() const
const Depsgraph * depsgraph
KDTree_3d * tree
void iksolver_release_tree(Scene *, Object *ob, float)
static void initialize_posetree(Object *, bPoseChannel *pchan_tip)
static void find_ik_constraints(ListBase *constraints, blender::Vector< bConstraint * > &ik_constraints)
static void free_posetree(PoseTree *tree)
static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[3][3])
void iksolver_execute_tree(Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
void iksolver_clear_data(bPose *pose)
void iksolver_initialize_tree(Depsgraph *, Scene *, Object *ob, float)
static void make_dmats(bPoseChannel *pchan)
static void execute_posetree(Depsgraph *depsgraph, Scene *scene, Object *ob, PoseTree *tree)
@ IK_ZDOF
@ IK_XDOF
@ IK_YDOF
@ IK_X
@ IK_Y
@ IK_TRANS_Y
@ IK_Z
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
float bone_mat[3][3]
void * first
struct bPose * pose
PoseTarget * next
bConstraint * con
struct Bone * bone
struct bPoseChannel * parent
struct ListBase iktree
float chan_mat[4][4]
float pose_mat[4][4]
ListBase chanbase
uint8_t flag
Definition wm_window.cc:138