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