Blender V5.0
armature_update.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2015 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10
11#include "MEM_guardedalloc.h"
12
13#include "BLI_listbase.h"
14#include "BLI_math_matrix.h"
15#include "BLI_math_rotation.h"
16#include "BLI_math_vector.h"
17#include "BLI_utildefines.h"
18
19#include "DNA_armature_types.h"
21#include "DNA_curve_types.h"
22#include "DNA_object_types.h"
23
24#include "BKE_action.hh"
25#include "BKE_anim_path.h"
26#include "BKE_armature.hh"
27#include "BKE_curve.hh"
28#include "BKE_object_types.hh"
29#include "BKE_scene.hh"
30
31#include "BIK_api.h"
32
33#include "DEG_depsgraph.hh"
34
35/* ********************** SPLINE IK SOLVER ******************* */
36
37/* Temporary evaluation tree data used for Spline IK */
40
41 int type; /* type of IK that this serves (CONSTRAINT_TYPE_KINEMATIC or ..._SPLINEIK) */
42
43 short chainlen; /* number of bones in the chain */
44 float totlength; /* total length of bones in the chain */
45
46 const float *points; /* parametric positions for the joints along the curve */
47 bPoseChannel **chain; /* chain of bones to affect using Spline IK (ordered from the tip) */
48
49 bPoseChannel *root; /* bone that is the root node of the chain */
50
51 bConstraint *con; /* constraint for this chain */
52 bSplineIKConstraint *ik_data; /* constraint settings for this chain */
53};
54
55/* ----------- */
56
57/* Tag the bones in the chain formed by the given bone for IK. */
58static void splineik_init_tree_from_pchan(Scene * /*scene*/,
59 Object * /*ob*/,
60 bPoseChannel *pchan_tip)
61{
62 bPoseChannel *pchan, *pchan_root = nullptr;
63 bPoseChannel *pchan_chain[255];
64 bConstraint *con = nullptr;
65 bSplineIKConstraint *ik_data = nullptr;
66 float bone_lengths[255];
67 float totlength = 0.0f;
68 int segcount = 0;
69
70 /* Find the SplineIK constraint. */
71 for (con = static_cast<bConstraint *>(pchan_tip->constraints.first); con; con = con->next) {
72 if (con->type == CONSTRAINT_TYPE_SPLINEIK) {
73 ik_data = static_cast<bSplineIKConstraint *>(con->data);
74
75 /* Target can only be a curve. */
76 if ((ik_data->tar == nullptr) || (ik_data->tar->type != OB_CURVES_LEGACY)) {
77 continue;
78 }
79 /* Skip if disabled. */
80 if ((con->enforce == 0.0f) || (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF))) {
81 continue;
82 }
83
84 /* Otherwise, constraint is ok... */
85 break;
86 }
87 }
88 if (con == nullptr) {
89 return;
90 }
91
92 /* Find the root bone and the chain of bones from the root to the tip.
93 * NOTE: this assumes that the bones are connected, but that may not be true... */
94 for (pchan = pchan_tip; pchan && (segcount < ik_data->chainlen);
95 pchan = pchan->parent, segcount++)
96 {
97 /* Store this segment in the chain. */
98 pchan_chain[segcount] = pchan;
99
100 /* If performing rebinding, calculate the length of the bone. */
101 bone_lengths[segcount] = pchan->bone->length;
102 totlength += bone_lengths[segcount];
103 }
104
105 if (segcount == 0) {
106 return;
107 }
108
109 pchan_root = pchan_chain[segcount - 1];
110
111 /* Perform binding step if required. */
112 if ((ik_data->flag & CONSTRAINT_SPLINEIK_BOUND) == 0) {
113 float segmentLen = (1.0f / float(segcount));
114
115 /* Setup new empty array for the points list. */
116 if (ik_data->points) {
117 MEM_freeN(ik_data->points);
118 }
119 ik_data->numpoints = ik_data->chainlen + 1;
120 ik_data->points = MEM_malloc_arrayN<float>(size_t(ik_data->numpoints), "Spline IK Binding");
121
122 /* Bind 'tip' of chain (i.e. first joint = tip of bone with the Spline IK Constraint). */
123 ik_data->points[0] = 1.0f;
124
125 /* Perform binding of the joints to parametric positions along the curve based
126 * proportion of the total length that each bone occupies.
127 */
128 for (int i = 0; i < segcount; i++) {
129 /* 'head' joints, traveling towards the root of the chain.
130 * - 2 methods; the one chosen depends on whether we've got usable lengths.
131 */
132 if ((ik_data->flag & CONSTRAINT_SPLINEIK_EVENSPLITS) || (totlength == 0.0f)) {
133 /* 1) Equi-spaced joints. */
134 ik_data->points[i + 1] = ik_data->points[i] - segmentLen;
135 }
136 else {
137 /* 2) To find this point on the curve, we take a step from the previous joint
138 * a distance given by the proportion that this bone takes.
139 */
140 ik_data->points[i + 1] = ik_data->points[i] - (bone_lengths[i] / totlength);
141 }
142 }
143
144 /* Spline has now been bound. */
146 }
147
148 /* Disallow negative values (happens with float precision). */
149 CLAMP_MIN(ik_data->points[segcount], 0.0f);
150
151 /* Make a new Spline-IK chain, and store it in the IK chains. */
152 /* TODO: we should check if there is already an IK chain on this,
153 * since that would take precedence... */
154 {
155 /* Make a new tree. */
158
159 tree->chainlen = segcount;
160 tree->totlength = totlength;
161
162 /* Copy over the array of links to bones in the chain (from tip to root). */
163 tree->chain = MEM_malloc_arrayN<bPoseChannel *>(size_t(segcount), "SplineIK Chain");
164 memcpy(tree->chain, pchan_chain, sizeof(bPoseChannel *) * segcount);
165
166 /* Store reference to joint position array. */
167 tree->points = ik_data->points;
168
169 /* Store references to different parts of the chain. */
170 tree->root = pchan_root;
171 tree->con = con;
172 tree->ik_data = ik_data;
173
174 /* AND! Link the tree to the root. */
175 BLI_addtail(&pchan_root->siktree, tree);
176 }
177
178 /* Mark root channel having an IK tree. */
179 pchan_root->flag |= POSE_IKSPLINE;
180}
181
182/* Tag which bones are members of Spline IK chains. */
183static void splineik_init_tree(Scene *scene, Object *ob, float /*ctime*/)
184{
185 /* Find the tips of Spline IK chains,
186 * which are simply the bones which have been tagged as such. */
187 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
188 if (pchan->constflag & PCHAN_HAS_SPLINEIK) {
189 splineik_init_tree_from_pchan(scene, ob, pchan);
190 }
191 }
192}
193
194/* ----------- */
195
197 float curve_position; /* Current position along the curve. */
198 float curve_scale; /* Global scale to apply to curve positions. */
199 float locrot_offset[4][4]; /* Bone rotation and location offset inherited from parent. */
200 float prev_tail_loc[3]; /* Tail location of the previous bone. */
201 float prev_tail_radius; /* Tail curve radius of the previous bone. */
202 int prev_tail_seg_idx; /* Curve segment the previous tail bone belongs to. */
203};
204
205/* Prepare data to evaluate spline IK. */
207{
208 bSplineIKConstraint *ik_data = tree->ik_data;
209
210 /* Make sure that the constraint targets are ok, to avoid crashes
211 * in case of a depsgraph bug or dependency cycle.
212 */
213 if (ik_data->tar == nullptr) {
214 return false;
215 }
216
217 CurveCache *cache = ik_data->tar->runtime->curve_cache;
218
219 if (ELEM(nullptr, cache, cache->anim_path_accum_length)) {
220 return false;
221 }
222
223 /* Initialize the evaluation state. */
224 state->curve_position = 0.0f;
225 state->curve_scale = 1.0f;
226 unit_m4(state->locrot_offset);
227 zero_v3(state->prev_tail_loc);
228 state->prev_tail_radius = 1.0f;
229 state->prev_tail_seg_idx = 0;
230
231 /* Apply corrections for sensitivity to scaling. */
232 if ((ik_data->yScaleMode != CONSTRAINT_SPLINEIK_YS_FIT_CURVE) && (tree->totlength != 0.0f)) {
233 /* Get the current length of the curve. */
234 /* NOTE: This is assumed to be correct even after the curve was resized. */
235 const float spline_len = BKE_anim_path_get_length(cache);
236
237 /* Calculate the scale factor to multiply all the path values by so that the
238 * bone chain retains its current length, such that:
239 * maxScale * splineLen = totLength
240 */
241 state->curve_scale = tree->totlength / spline_len;
242 }
243
244 return true;
245}
246
248 bSplineIKConstraint *ik_data, Object *ob, float radius, float r_vec[3], float *r_radius)
249{
250 /* Apply the curve's object-mode transforms to the position
251 * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root).
252 */
253 if ((ik_data->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) {
254 mul_m4_v3(ik_data->tar->object_to_world().ptr(), r_vec);
255 }
256
257 /* Convert the position to pose-space. */
258 mul_m4_v3(ob->world_to_object().ptr(), r_vec);
259
260 /* Set the new radius (it should be the average value). */
261 *r_radius = (radius + *r_radius) / 2;
262}
263
264static float dist_to_sphere_shell(const float sphere_origin[3],
265 const float sphere_radius,
266 const float point[3])
267{
268 float vec[3];
269 sub_v3_v3v3(vec, sphere_origin, point);
270 return sphere_radius - len_v3(vec);
271}
272
273/* This function positions the tail of the bone so that it preserves the length of it.
274 * The length of the bone can be seen as a sphere radius.
275 */
277 const float head_pos[3],
278 const float sphere_radius,
279 int prev_seg_idx,
280 float r_tail_pos[3],
281 float *r_new_curve_pos,
282 float *r_radius)
283{
284 /* This is using the tessellated curve data.
285 * So we are working with piece-wise linear curve segments.
286 * The same method is used in #BKE_where_on_path to get curve location data. */
287 const CurveCache *cache = ik_data->tar->runtime->curve_cache;
288 const float *seg_accum_len = cache->anim_path_accum_length;
289
290 int max_seg_idx = BKE_anim_path_get_array_size(cache) - 1;
291
292 /* Make an initial guess of where our intersection point will be.
293 * If the curve was a straight line, then the fraction passed in r_new_curve_pos
294 * would be the correct location.
295 * So make it our first initial guess.
296 */
297 const float spline_len = BKE_anim_path_get_length(cache);
298 const float guessed_len = *r_new_curve_pos * spline_len;
299
300 BLI_assert(prev_seg_idx >= 0);
301 int cur_seg_idx = prev_seg_idx;
302 while (cur_seg_idx < max_seg_idx && guessed_len > seg_accum_len[cur_seg_idx]) {
303 cur_seg_idx++;
304 }
305
306 /* Convert the segment to bev points.
307 * For example, the segment with index 0 will have bev points 0 and 1.
308 */
309 int bp_idx = cur_seg_idx + 1;
310
311 const BevList *bl = static_cast<const BevList *>(cache->bev.first);
312 bool is_cyclic = bl->poly >= 0;
313 BevPoint *bp = bl->bevpoints;
314 BevPoint *prev_bp;
315 bp = bp + bp_idx;
316 prev_bp = bp - 1;
317
318 /* Go to the next tessellated curve point until we cross to outside of the sphere. */
319 while (len_v3v3(head_pos, bp->vec) < sphere_radius) {
320 if (bp_idx > max_seg_idx) {
321 /* We are outside the defined curve. We will now extrapolate the intersection point. */
322 break;
323 }
324 prev_bp = bp;
325 if (is_cyclic && bp_idx == max_seg_idx) {
326 /* Wrap around to the start point.
327 * Don't set the bp_idx to zero here as we use it to get the segment index later.
328 */
329 bp = bl->bevpoints;
330 }
331 else {
332 bp++;
333 }
334 bp_idx++;
335 }
336
337 /* Calculate the intersection point using the secant root finding method */
338 float x0 = 0.0f, x1 = 1.0f;
339 float x0_point[3], x1_point[3], start_p[3];
340 float epsilon = max_fff(1.0f, len_v3(head_pos), len_v3(bp->vec)) * FLT_EPSILON;
341
342 if (prev_seg_idx == bp_idx - 1) {
343 /* The intersection lies inside the same segment as the last point.
344 * Set the last point to be the start search point so we minimize the risks of going backwards
345 * on the curve.
346 */
347 copy_v3_v3(start_p, head_pos);
348 }
349 else {
350 copy_v3_v3(start_p, prev_bp->vec);
351 }
352
353 for (int i = 0; i < 10; i++) {
354 interp_v3_v3v3(x0_point, start_p, bp->vec, x0);
355 interp_v3_v3v3(x1_point, start_p, bp->vec, x1);
356
357 float f_x0 = dist_to_sphere_shell(head_pos, sphere_radius, x0_point);
358 float f_x1 = dist_to_sphere_shell(head_pos, sphere_radius, x1_point);
359
360 if (fabsf(f_x1) <= epsilon || f_x0 == f_x1) {
361 break;
362 }
363
364 const float x2 = x1 - f_x1 * (x1 - x0) / (f_x1 - f_x0);
365 x0 = x1;
366 x1 = x2;
367 }
368 /* Found the bone tail position! */
369 copy_v3_v3(r_tail_pos, x1_point);
370
371 /* Because our intersection point lies inside the current segment,
372 * Convert our bevpoint index back to the previous segment index (-2 instead of -1).
373 * This is because our actual location is prev_seg_len + isect_seg_len.
374 */
375 prev_seg_idx = bp_idx - 2;
376 float prev_seg_len = 0;
377
378 if (prev_seg_idx < 0) {
379 prev_seg_idx = 0;
380 prev_seg_len = 0;
381 }
382 else {
383 prev_seg_len = seg_accum_len[prev_seg_idx];
384 }
385
386 /* Convert the point back into the 0-1 interpolation range. */
387 const float isect_seg_len = len_v3v3(prev_bp->vec, r_tail_pos);
388 const float frac = isect_seg_len / len_v3v3(prev_bp->vec, bp->vec);
389 *r_new_curve_pos = (prev_seg_len + isect_seg_len) / spline_len;
390
391 if (*r_new_curve_pos > 1.0f) {
392 *r_radius = bp->radius;
393 }
394 else {
395 *r_radius = (1.0f - frac) * prev_bp->radius + frac * bp->radius;
396 }
397
398 /* Return the current segment. */
399 return bp_idx - 1;
400}
401
402/* Evaluate spline IK for a given bone. */
405{
406 bSplineIKConstraint *ik_data = tree->ik_data;
407
408 if (pchan->bone->length < FLT_EPSILON) {
409 /* Only move the bone position with zero length bones. */
410 float bone_pos[4], rad;
412 ik_data->tar, state->curve_position, bone_pos, nullptr, nullptr, &rad, nullptr);
413
414 apply_curve_transform(ik_data, ob, rad, bone_pos, &rad);
415
416 copy_v3_v3(pchan->pose_mat[3], bone_pos);
417 copy_v3_v3(pchan->pose_head, bone_pos);
418 copy_v3_v3(pchan->pose_tail, bone_pos);
419 pchan->flag |= POSE_DONE;
420 return;
421 }
422
423 float orig_head[3], orig_tail[3], pose_head[3], pose_tail[3];
424 float base_pose_mat[3][3], pose_mat[3][3];
425 float spline_vec[3], scale_fac, radius = 1.0f;
426 float tail_blend_fac = 0.0f;
427
428 mul_v3_m4v3(pose_head, state->locrot_offset, pchan->pose_head);
429 mul_v3_m4v3(pose_tail, state->locrot_offset, pchan->pose_tail);
430
431 copy_v3_v3(orig_head, pose_head);
432
433 /* First, adjust the point positions on the curve. */
434 float curveLen = tree->points[index] - tree->points[index + 1];
435 float bone_len = len_v3v3(pose_head, pose_tail);
436 float point_start = state->curve_position;
437 float pose_scale = bone_len / pchan->bone->length;
438 float base_scale = 1.0f;
439
441 /* Carry over the bone Y scale to the curve range. */
442 base_scale = pose_scale;
443 }
444
445 float point_end = point_start + curveLen * base_scale * state->curve_scale;
446
447 state->curve_position = point_end;
448
449 /* Step 1: determine the positions for the endpoints of the bone. */
450 if (point_start < 1.0f) {
451 float vec[4], rad;
452 radius = 0.0f;
453
454 /* Calculate head position. */
455 if (point_start == 0.0f) {
456 /* Start of the path. We have no previous tail position to copy. */
457 BKE_where_on_path(ik_data->tar, point_start, vec, nullptr, nullptr, &rad, nullptr);
458 }
459 else {
460 copy_v3_v3(vec, state->prev_tail_loc);
461 rad = state->prev_tail_radius;
462 }
463
464 radius = rad;
465 copy_v3_v3(pose_head, vec);
466 apply_curve_transform(ik_data, ob, rad, pose_head, &radius);
467
468 /* Calculate tail position. */
470 float sphere_radius;
471
473 sphere_radius = bone_len;
474 }
475 else {
476 /* Don't take bone scale into account. */
477 sphere_radius = pchan->bone->length;
478 }
479
480 /* Calculate the tail position with sphere curve intersection. */
481 state->prev_tail_seg_idx = position_tail_on_spline(
482 ik_data, vec, sphere_radius, state->prev_tail_seg_idx, pose_tail, &point_end, &rad);
483
484 state->prev_tail_radius = rad;
485 copy_v3_v3(state->prev_tail_loc, pose_tail);
486
487 apply_curve_transform(ik_data, ob, rad, pose_tail, &radius);
488 state->curve_position = point_end;
489 }
490 else {
491 /* Scale to fit curve end position. */
492 if (BKE_where_on_path(ik_data->tar, point_end, vec, nullptr, nullptr, &rad, nullptr)) {
493 state->prev_tail_radius = rad;
494 copy_v3_v3(state->prev_tail_loc, vec);
495 copy_v3_v3(pose_tail, vec);
496 apply_curve_transform(ik_data, ob, rad, pose_tail, &radius);
497 }
498 }
499
500 /* Determine if the bone should still be affected by SplineIK.
501 * This makes it so that the bone slowly becomes poseable again the further it rolls off the
502 * curve. When the whole bone has rolled off the curve, the IK constraint will not influence it
503 * anymore.
504 */
505 if (point_end >= 1.0f) {
506 /* Blending factor depends on the amount of the bone still left on the chain. */
507 tail_blend_fac = (1.0f - point_start) / (point_end - point_start);
508 }
509 else {
510 tail_blend_fac = 1.0f;
511 }
512 }
513
514 /* Step 2: determine the implied transform from these endpoints.
515 * - splineVec: the vector direction that the spline applies on the bone.
516 * - scaleFac: the factor that the bone length is scaled by to get the desired amount.
517 */
518 sub_v3_v3v3(spline_vec, pose_tail, pose_head);
519 scale_fac = len_v3(spline_vec) / pchan->bone->length;
520
521 /* Step 3: compute the shortest rotation needed
522 * to map from the bone rotation to the current axis.
523 * - this uses the same method as is used for the Damped Track Constraint
524 * (see the code there for details).
525 */
526 {
527 float dmat[3][3], rmat[3][3];
528 float raxis[3], rangle;
529
530 /* Compute the raw rotation matrix from the bone's current matrix by extracting only the
531 * orientation-relevant axes, and normalizing them.
532 */
533 mul_m3_m4m4(base_pose_mat, state->locrot_offset, pchan->pose_mat);
534 normalize_m3_m3(rmat, base_pose_mat);
535
536 /* Also, normalize the orientation imposed by the bone,
537 * now that we've extracted the scale factor. */
538 normalize_v3(spline_vec);
539
540 /* Calculate smallest axis-angle rotation necessary for getting from the
541 * current orientation of the bone, to the spline-imposed direction.
542 */
543 cross_v3_v3v3(raxis, rmat[1], spline_vec);
544
545 /* Check if the old and new bone direction is parallel to each other.
546 * If they are, then 'raxis' should be near zero and we will have to get the rotation axis in
547 * some other way.
548 */
549 float norm = normalize_v3(raxis);
550
551 if (norm < FLT_EPSILON) {
552 /* Can't use cross product! */
553 int order[3] = {0, 1, 2};
554 float tmp_axis[3];
555 zero_v3(tmp_axis);
556
557 axis_sort_v3(spline_vec, order);
558
559 /* Use the second largest axis as the basis for the rotation axis. */
560 tmp_axis[order[1]] = 1.0f;
561 cross_v3_v3v3(raxis, tmp_axis, spline_vec);
562 }
563
564 rangle = dot_v3v3(rmat[1], spline_vec);
565 CLAMP(rangle, -1.0f, 1.0f);
566 rangle = acosf(rangle);
567
568 /* Multiply the magnitude of the angle by the influence of the constraint to
569 * control the influence of the SplineIK effect.
570 */
571 rangle *= tree->con->enforce * tail_blend_fac;
572
573 /* Construct rotation matrix from the axis-angle rotation found above.
574 * - This call takes care to make sure that the axis provided is a unit vector first.
575 */
576 axis_angle_to_mat3(dmat, raxis, rangle);
577
578 /* Combine these rotations so that the y-axis of the bone is now aligned as the
579 * spline dictates, while still maintaining roll control from the existing bone animation. */
580 mul_m3_m3m3(pose_mat, dmat, rmat);
581
582 /* Attempt to reduce shearing, though I doubt this will really help too much now. */
583 normalize_m3(pose_mat);
584
585 mul_m3_m3m3(base_pose_mat, dmat, base_pose_mat);
586
587 /* Apply rotation to the accumulated parent transform. */
588 mul_m4_m3m4(state->locrot_offset, dmat, state->locrot_offset);
589 }
590
591 /* Step 4: Set the scaling factors for the axes. */
592
593 /* Always multiply the y-axis by the scaling factor to get the correct length. */
594 mul_v3_fl(pose_mat[1], scale_fac);
595
596 /* After that, apply x/z scaling modes. */
598 /* First, apply the original scale if enabled. */
601 {
602 float scale;
603
604 /* X-axis scale. */
605 scale = len_v3(pchan->pose_mat[0]);
606 mul_v3_fl(pose_mat[0], scale);
607 /* Z-axis scale. */
608 scale = len_v3(pchan->pose_mat[2]);
609 mul_v3_fl(pose_mat[2], scale);
610
611 /* Adjust the scale factor used for volume preservation
612 * to consider the pre-IK scaling as the initial volume. */
613 scale_fac /= pose_scale;
614 }
615
616 /* Apply volume preservation. */
617 switch (ik_data->xzScaleMode) {
619 /* Old 'volume preservation' method using the inverse scale. */
620 float scale;
621
622 /* Calculate volume preservation factor which is
623 * basically the inverse of the y-scaling factor.
624 */
625 if (fabsf(scale_fac) != 0.0f) {
626 scale = 1.0f / fabsf(scale_fac);
627
628 /* We need to clamp this within sensible values. */
629 /* NOTE: these should be fine for now, but should get sanitized in future. */
630 CLAMP(scale, 0.0001f, 100000.0f);
631 }
632 else {
633 scale = 1.0f;
634 }
635
636 /* Apply the scaling. */
637 mul_v3_fl(pose_mat[0], scale);
638 mul_v3_fl(pose_mat[2], scale);
639 break;
640 }
642 /* Improved volume preservation based on the Stretch To constraint. */
643 float final_scale;
644
645 /* As the basis for volume preservation, we use the inverse scale factor... */
646 if (fabsf(scale_fac) != 0.0f) {
647 /* NOTE: The method here is taken wholesale from the Stretch To constraint. */
648 float bulge = powf(1.0f / fabsf(scale_fac), ik_data->bulge);
649
650 if (bulge > 1.0f) {
652 float bulge_max = max_ff(ik_data->bulge_max, 1.0f);
653 float hard = min_ff(bulge, bulge_max);
654
655 float range = bulge_max - 1.0f;
656 float scale = (range > 0.0f) ? 1.0f / range : 0.0f;
657 float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / float(M_PI_2);
658
659 bulge = interpf(soft, hard, ik_data->bulge_smooth);
660 }
661 }
662 if (bulge < 1.0f) {
664 float bulge_min = std::clamp(ik_data->bulge_min, 0.0f, 1.0f);
665 float hard = max_ff(bulge, bulge_min);
666
667 float range = 1.0f - bulge_min;
668 float scale = (range > 0.0f) ? 1.0f / range : 0.0f;
669 float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / float(M_PI_2);
670
671 bulge = interpf(soft, hard, ik_data->bulge_smooth);
672 }
673 }
674
675 /* Compute scale factor for XZ axes from this value. */
676 final_scale = sqrtf(bulge);
677 }
678 else {
679 /* No scaling, so scale factor is simple. */
680 final_scale = 1.0f;
681 }
682
683 /* Apply the scaling (assuming normalized scale). */
684 mul_v3_fl(pose_mat[0], final_scale);
685 mul_v3_fl(pose_mat[2], final_scale);
686 break;
687 }
688 }
689 }
690
691 /* Finally, multiply the x and z scaling by the radius of the curve too,
692 * to allow automatic scales to get tweaked still.
693 */
694 if ((ik_data->flag & CONSTRAINT_SPLINEIK_NO_CURVERAD) == 0) {
695 mul_v3_fl(pose_mat[0], radius);
696 mul_v3_fl(pose_mat[2], radius);
697 }
698
699 /* Blend the scaling of the matrix according to the influence. */
700 sub_m3_m3m3(pose_mat, pose_mat, base_pose_mat);
701 madd_m3_m3m3fl(pose_mat, base_pose_mat, pose_mat, tree->con->enforce * tail_blend_fac);
702
703 /* Step 5: Set the location of the bone in the matrix. */
704 if (ik_data->flag & CONSTRAINT_SPLINEIK_NO_ROOT) {
705 /* When the 'no-root' option is affected, the chain can retain
706 * the shape but be moved elsewhere.
707 */
708 copy_v3_v3(pose_head, orig_head);
709 }
710 else if (tree->con->enforce < 1.0f) {
711 /* When the influence is too low:
712 * - Blend the positions for the 'root' bone.
713 * - Stick to the parent for any other.
714 */
715 if (index < tree->chainlen - 1) {
716 copy_v3_v3(pose_head, orig_head);
717 }
718 else {
719 interp_v3_v3v3(pose_head, orig_head, pose_head, tree->con->enforce);
720 }
721 }
722
723 /* Finally, store the new transform. */
724 copy_m4_m3(pchan->pose_mat, pose_mat);
725 copy_v3_v3(pchan->pose_mat[3], pose_head);
726 copy_v3_v3(pchan->pose_head, pose_head);
727
728 mul_v3_mat3_m4v3(orig_tail, state->locrot_offset, pchan->pose_tail);
729
730 /* Recalculate tail, as it's now outdated after the head gets adjusted above! */
732
733 /* Update the offset in the accumulated parent transform. */
734 sub_v3_v3v3(state->locrot_offset[3], pchan->pose_tail, orig_tail);
735
736 /* Done! */
737 pchan->flag |= POSE_DONE;
738}
739
740/* Evaluate the chain starting from the nominated bone */
742 Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
743{
745
746 /* for each pose-tree, execute it if it is spline, otherwise just free it */
747 while ((tree = static_cast<tSplineIK_Tree *>(pchan_root->siktree.first)) != nullptr) {
748 /* Firstly, calculate the bone matrix the standard way,
749 * since this is needed for roll control. */
750 for (int i = tree->chainlen - 1; i >= 0; i--) {
751 BKE_pose_where_is_bone(depsgraph, scene, ob, tree->chain[i], ctime, true);
752 }
753
754 /* After that, evaluate the actual Spline IK, unless there are missing dependencies. */
756
758 /* Walk over each bone in the chain, calculating the effects of spline IK
759 * - the chain is traversed in the opposite order to storage order
760 * (i.e. parent to children) so that dependencies are correct
761 */
762 for (int i = tree->chainlen - 1; i >= 0; i--) {
763 bPoseChannel *pchan = tree->chain[i];
764 splineik_evaluate_bone(tree, ob, pchan, i, &state);
765 }
766 }
767
768 /* free the tree info specific to SplineIK trees now */
769 if (tree->chain) {
770 MEM_freeN(tree->chain);
771 }
772
773 /* free this tree */
774 BLI_freelinkN(&pchan_root->siktree, tree);
775 }
776}
777
778void BKE_pose_splineik_init_tree(Scene *scene, Object *ob, float ctime)
779{
780 splineik_init_tree(scene, ob, ctime);
781}
782
784 Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
785{
786 splineik_execute_tree(depsgraph, scene, ob, pchan_root, ctime);
787}
788
789/* *************** Depsgraph evaluation callbacks ************ */
790
792{
794 const int num_channels = BLI_listbase_count(&pose->chanbase);
795 pose->chan_array = MEM_malloc_arrayN<bPoseChannel *>(size_t(num_channels), "pose->chan_array");
796 int pchan_index = 0;
797 for (bPoseChannel *pchan = static_cast<bPoseChannel *>(pose->chanbase.first); pchan != nullptr;
798 pchan = pchan->next)
799 {
800 pose->chan_array[pchan_index++] = pchan;
801 }
802}
803
805{
806 bPose *pose = ob->pose;
807 BLI_assert(pose != nullptr);
808 BLI_assert(pose->chan_array != nullptr);
809 BLI_assert(pchan_index >= 0);
810 BLI_assert(pchan_index < MEM_allocN_len(pose->chan_array) / sizeof(bPoseChannel *));
811 return pose->chan_array[pchan_index];
812}
813
814void BKE_pose_eval_init(Depsgraph *depsgraph, Scene * /*scene*/, Object *object)
815{
816 bPose *pose = object->pose;
817 BLI_assert(pose != nullptr);
818
819 DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
820
821 BLI_assert(object->type == OB_ARMATURE);
822
823 /* We demand having proper pose. */
824 BLI_assert(object->pose != nullptr);
825 BLI_assert((object->pose->flag & POSE_RECALC) == 0);
826
827 /* world_to_object is needed for solvers. */
828 invert_m4_m4(object->runtime->world_to_object.ptr(), object->object_to_world().ptr());
829
830 /* clear flags */
831 for (bPoseChannel *pchan = static_cast<bPoseChannel *>(pose->chanbase.first); pchan != nullptr;
832 pchan = pchan->next)
833 {
834 pchan->flag &= ~(POSE_DONE | POSE_CHAIN | POSE_IKTREE | POSE_IKSPLINE);
835
836 /* Free B-Bone shape data cache if it's not a B-Bone. */
837 if (pchan->bone == nullptr || pchan->bone->segments <= 1) {
838 BKE_pose_channel_free_bbone_cache(&pchan->runtime);
839 }
840 }
841
842 BLI_assert(pose->chan_array != nullptr || BLI_listbase_is_empty(&pose->chanbase));
843}
844
845void BKE_pose_eval_init_ik(Depsgraph *depsgraph, Scene *scene, Object *object)
846{
847 DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
848 BLI_assert(object->type == OB_ARMATURE);
849 const float ctime = BKE_scene_ctime_get(scene); /* not accurate... */
850 bArmature *armature = (bArmature *)object->data;
851 if (armature->flag & ARM_RESTPOS) {
852 return;
853 }
854 /* construct the IK tree (standard IK) */
855 BIK_init_tree(depsgraph, scene, object, ctime);
856 /* construct the Spline IK trees
857 * - this is not integrated as an IK plugin, since it should be able
858 * to function in conjunction with standard IK. */
859 BKE_pose_splineik_init_tree(scene, object, ctime);
860}
861
862void BKE_pose_eval_bone(Depsgraph *depsgraph, Scene *scene, Object *object, int pchan_index)
863{
864 const bArmature *armature = (bArmature *)object->data;
865 if (armature->edbo != nullptr) {
866 return;
867 }
868 bPoseChannel *pchan = pose_pchan_get_indexed(object, pchan_index);
870 depsgraph, __func__, object->id.name, object, "pchan", pchan->name, pchan);
871 BLI_assert(object->type == OB_ARMATURE);
872 if (armature->flag & ARM_RESTPOS) {
873 Bone *bone = pchan->bone;
874 if (bone) {
875 copy_m4_m4(pchan->pose_mat, bone->arm_mat);
876 copy_v3_v3(pchan->pose_head, bone->arm_head);
877 copy_v3_v3(pchan->pose_tail, bone->arm_tail);
878 }
879 }
880 else {
881 /* TODO(sergey): Currently if there are constraints full transform is
882 * being evaluated in BKE_pose_constraints_evaluate. */
883 if (pchan->constraints.first == nullptr) {
884 if (pchan->flag & POSE_IKTREE || pchan->flag & POSE_IKSPLINE) {
885 /* pass */
886 }
887 else {
888 if ((pchan->flag & POSE_DONE) == 0) {
889 /* TODO(sergey): Use time source node for time. */
890 float ctime = BKE_scene_ctime_get(scene); /* not accurate... */
891 BKE_pose_where_is_bone(depsgraph, scene, object, pchan, ctime, true);
892 }
893 }
894 }
895 }
896}
897
899 Scene *scene,
900 Object *object,
901 int pchan_index)
902{
903 const bArmature *armature = (bArmature *)object->data;
904 if (armature->edbo != nullptr) {
905 return;
906 }
907 bPoseChannel *pchan = pose_pchan_get_indexed(object, pchan_index);
909 depsgraph, __func__, object->id.name, object, "pchan", pchan->name, pchan);
910 if (armature->flag & ARM_RESTPOS) {
911 return;
912 }
913 if (pchan->flag & POSE_IKTREE || pchan->flag & POSE_IKSPLINE) {
914 /* IK are being solved separately/ */
915 }
916 else {
917 if ((pchan->flag & POSE_DONE) == 0) {
918 float ctime = BKE_scene_ctime_get(scene); /* not accurate... */
919 BKE_pose_where_is_bone(depsgraph, scene, object, pchan, ctime, true);
920 }
921 }
922}
923
925 Object *object,
926 bPoseChannel *pchan)
927{
928 if (!DEG_is_active(depsgraph)) {
929 return;
930 }
931 const bArmature *armature = (bArmature *)object->data;
932 if (armature->edbo != nullptr) {
933 return;
934 }
935 bPoseChannel *pchan_orig = pchan->orig_pchan;
936 /* TODO(sergey): Using BKE_pose_copy_pchan_result() introduces #70901, but why? */
937 copy_m4_m4(pchan_orig->pose_mat, pchan->pose_mat);
938 copy_m4_m4(pchan_orig->chan_mat, pchan->chan_mat);
939 copy_v3_v3(pchan_orig->pose_head, pchan->pose_mat[3]);
940 copy_m4_m4(pchan_orig->constinv, pchan->constinv);
941 copy_v3_v3(pchan_orig->pose_tail, pchan->pose_tail);
942 pchan_orig->constflag = pchan->constflag;
943}
944
945void BKE_pose_bone_done(Depsgraph *depsgraph, Object *object, int pchan_index)
946{
947 /* Note: tests in `armature_deform_test.cc` update pose matrices locally to avoid creating a full
948 * depsgraph. Keep these in sync if this function is changed! */
949
950 const bArmature *armature = (bArmature *)object->data;
951 if (armature->edbo != nullptr) {
952 return;
953 }
954 bPoseChannel *pchan = pose_pchan_get_indexed(object, pchan_index);
955 float imat[4][4];
957 depsgraph, __func__, object->id.name, object, "pchan", pchan->name, pchan);
958 if (pchan->bone) {
959 invert_m4_m4(imat, pchan->bone->arm_mat);
960 mul_m4_m4m4(pchan->chan_mat, pchan->pose_mat, imat);
961 if (!(pchan->bone->flag & BONE_NO_DEFORM)) {
962 mat4_to_dquat(&pchan->runtime.deform_dual_quat, pchan->bone->arm_mat, pchan->chan_mat);
963 }
964 }
967 bPoseChannel *pchan_orig = pchan->orig_pchan;
968 if (pchan->bone == nullptr || pchan->bone->segments <= 1) {
970 }
971 }
972}
973
974void BKE_pose_eval_bbone_segments(Depsgraph *depsgraph, Object *object, int pchan_index)
975{
976 const bArmature *armature = (bArmature *)object->data;
977 if (armature->edbo != nullptr) {
978 return;
979 }
980 bPoseChannel *pchan = pose_pchan_get_indexed(object, pchan_index);
982 depsgraph, __func__, object->id.name, object, "pchan", pchan->name, pchan);
983 if (pchan->bone != nullptr && pchan->bone->segments > 1) {
987 }
988 }
989}
990
992 Scene *scene,
993 Object *object,
994 int rootchan_index)
995{
996 const bArmature *armature = (bArmature *)object->data;
997 if (armature->edbo != nullptr) {
998 return;
999 }
1000 bPoseChannel *rootchan = pose_pchan_get_indexed(object, rootchan_index);
1002 depsgraph, __func__, object->id.name, object, "rootchan", rootchan->name, rootchan);
1003 BLI_assert(object->type == OB_ARMATURE);
1004 const float ctime = BKE_scene_ctime_get(scene); /* not accurate... */
1005 if (armature->flag & ARM_RESTPOS) {
1006 return;
1007 }
1008 BIK_execute_tree(depsgraph, scene, object, rootchan, ctime);
1009}
1010
1012 Scene *scene,
1013 Object *object,
1014 int rootchan_index)
1015
1016{
1017 const bArmature *armature = (bArmature *)object->data;
1018 if (armature->edbo != nullptr) {
1019 return;
1020 }
1021 bPoseChannel *rootchan = pose_pchan_get_indexed(object, rootchan_index);
1023 depsgraph, __func__, object->id.name, object, "rootchan", rootchan->name, rootchan);
1024 BLI_assert(object->type == OB_ARMATURE);
1025 const float ctime = BKE_scene_ctime_get(scene); /* not accurate... */
1026 if (armature->flag & ARM_RESTPOS) {
1027 return;
1028 }
1029 BKE_splineik_execute_tree(depsgraph, scene, object, rootchan, ctime);
1030}
1031
1033{
1034 bPose *pose = object->pose;
1035 BLI_assert(pose != nullptr);
1036 BLI_assert(pose->chan_array != nullptr || BLI_listbase_is_empty(&pose->chanbase));
1037 UNUSED_VARS_NDEBUG(pose);
1038}
1039
1040void BKE_pose_eval_done(Depsgraph *depsgraph, Object *object)
1041{
1042 bPose *pose = object->pose;
1043 BLI_assert(pose != nullptr);
1044 UNUSED_VARS_NDEBUG(pose);
1045 DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
1046 BLI_assert(object->type == OB_ARMATURE);
1047}
1048
1049void BKE_pose_eval_cleanup(Depsgraph *depsgraph, Scene *scene, Object *object)
1050{
1051 bPose *pose = object->pose;
1052 BLI_assert(pose != nullptr);
1053 UNUSED_VARS_NDEBUG(pose);
1054 const float ctime = BKE_scene_ctime_get(scene); /* not accurate... */
1055 DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
1056 BLI_assert(object->type == OB_ARMATURE);
1057 /* Release the IK tree. */
1058 BIK_release_tree(scene, object, ctime);
1060}
void BIK_init_tree(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, float ctime)
void BIK_release_tree(struct Scene *scene, struct Object *ob, float ctime)
void BIK_execute_tree(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime)
Blender kernel action and pose functionality.
void BKE_pose_channel_free_bbone_cache(bPoseChannel_Runtime *runtime) ATTR_NONNULL(1)
bool BKE_where_on_path(const struct Object *ob, float ctime, float r_vec[4], float r_dir[3], float r_quat[4], float *r_radius, float *r_weight)
int BKE_anim_path_get_array_size(const struct CurveCache *curve_cache)
float BKE_anim_path_get_length(const struct CurveCache *curve_cache)
void BKE_pose_where_is_bone(Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan, float ctime, bool do_extra)
void BKE_pose_where_is_bone_tail(bPoseChannel *pchan)
void BKE_pchan_bbone_segments_cache_copy(bPoseChannel *pchan, bPoseChannel *pchan_from)
void BKE_pchan_bbone_segments_cache_compute(bPoseChannel *pchan)
float BKE_scene_ctime_get(const Scene *scene)
Definition scene.cc:2370
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_INLINE
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_freelinkN(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:270
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
MINLINE float max_fff(float a, float b, float c)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
MINLINE float interpf(float target, float origin, float t)
#define M_PI_2
void sub_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void normalize_m3_m3(float R[3][3], const float M[3][3]) ATTR_NONNULL()
void copy_m4_m3(float m1[4][4], const float m2[3][3])
void normalize_m3(float R[3][3]) ATTR_NONNULL()
void mul_m4_v3(const float M[4][4], float r[3])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
void madd_m3_m3m3fl(float R[3][3], const float A[3][3], const float B[3][3], float f)
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
void mul_m4_m3m4(float R[4][4], const float A[3][3], const float B[4][4])
void mul_v3_mat3_m4v3(float r[3], const float mat[4][4], const float vec[3])
void mul_m3_m4m4(float R[3][3], const float A[4][4], const float B[4][4])
void unit_m4(float m[4][4])
void mat4_to_dquat(DualQuat *dq, const float basemat[4][4], const float mat[4][4])
void axis_angle_to_mat3(float R[3][3], const float axis[3], float angle)
void axis_sort_v3(const float axis_values[3], int r_axis_order[3])
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
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 float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void zero_v3(float r[3])
MINLINE float normalize_v3(float n[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
#define CLAMP(a, b, c)
#define UNUSED_VARS_NDEBUG(...)
#define ELEM(...)
#define CLAMP_MIN(a, b)
void DEG_debug_print_eval_subdata(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address, const char *subdata_comment, const char *subdata_name, const void *subdata_address)
bool DEG_is_active(const Depsgraph *depsgraph)
Definition depsgraph.cc:323
void DEG_debug_print_eval(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address)
@ PCHAN_HAS_SPLINEIK
@ POSE_DONE
@ POSE_IKTREE
@ POSE_IKSPLINE
@ POSE_CHAIN
@ POSE_RECALC
@ BONE_NO_DEFORM
@ ARM_RESTPOS
@ CONSTRAINT_OFF
@ CONSTRAINT_DISABLE
@ CONSTRAINT_TYPE_SPLINEIK
@ CONSTRAINT_SPLINEIK_YS_FIT_CURVE
@ CONSTRAINT_SPLINEIK_YS_ORIGINAL
@ CONSTRAINT_SPLINEIK_EVENSPLITS
@ CONSTRAINT_SPLINEIK_USE_BULGE_MAX
@ CONSTRAINT_SPLINEIK_USE_ORIGINAL_SCALE
@ CONSTRAINT_SPLINEIK_USE_BULGE_MIN
@ CONSTRAINT_SPLINEIK_BOUND
@ CONSTRAINT_SPLINEIK_NO_CURVERAD
@ CONSTRAINT_SPLINEIK_NO_ROOT
@ CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC
@ CONSTRAINT_SPLINEIK_XZS_ORIGINAL
@ CONSTRAINT_SPLINEIK_XZS_NONE
@ CONSTRAINT_SPLINEIK_XZS_INVERSE
Object is a sort of wrapper for general info.
@ OB_ARMATURE
@ OB_CURVES_LEGACY
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
void BKE_splineik_execute_tree(Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
void BKE_pose_eval_init_ik(Depsgraph *depsgraph, Scene *scene, Object *object)
void BKE_pose_splineik_evaluate(Depsgraph *depsgraph, Scene *scene, Object *object, int rootchan_index)
static void splineik_init_tree_from_pchan(Scene *, Object *, bPoseChannel *pchan_tip)
static void splineik_init_tree(Scene *scene, Object *ob, float)
static bool splineik_evaluate_init(tSplineIK_Tree *tree, tSplineIk_EvalState *state)
void BKE_pose_pchan_index_rebuild(bPose *pose)
static void apply_curve_transform(bSplineIKConstraint *ik_data, Object *ob, float radius, float r_vec[3], float *r_radius)
static void splineik_execute_tree(Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
void BKE_pose_splineik_init_tree(Scene *scene, Object *ob, float ctime)
static void splineik_evaluate_bone(tSplineIK_Tree *tree, Object *ob, bPoseChannel *pchan, int index, tSplineIk_EvalState *state)
void BKE_pose_eval_init(Depsgraph *depsgraph, Scene *, Object *object)
static int position_tail_on_spline(bSplineIKConstraint *ik_data, const float head_pos[3], const float sphere_radius, int prev_seg_idx, float r_tail_pos[3], float *r_new_curve_pos, float *r_radius)
void BKE_pose_iktree_evaluate(Depsgraph *depsgraph, Scene *scene, Object *object, int rootchan_index)
void BKE_pose_eval_cleanup(Depsgraph *depsgraph, Scene *scene, Object *object)
static void pose_channel_flush_to_orig_if_needed(Depsgraph *depsgraph, Object *object, bPoseChannel *pchan)
static float dist_to_sphere_shell(const float sphere_origin[3], const float sphere_radius, const float point[3])
void BKE_pose_eval_bbone_segments(Depsgraph *depsgraph, Object *object, int pchan_index)
BLI_INLINE bPoseChannel * pose_pchan_get_indexed(Object *ob, int pchan_index)
void BKE_pose_bone_done(Depsgraph *depsgraph, Object *object, int pchan_index)
static void pose_eval_cleanup_common(Object *object)
void BKE_pose_constraints_evaluate(Depsgraph *depsgraph, Scene *scene, Object *object, int pchan_index)
void BKE_pose_eval_done(Depsgraph *depsgraph, Object *object)
void BKE_pose_eval_bone(Depsgraph *depsgraph, Scene *scene, Object *object, int pchan_index)
BPy_StructRNA * depsgraph
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition btVector3.h:263
nullptr float
CCL_NAMESPACE_BEGIN ccl_device_inline float frac(const float x, ccl_private int *ix)
#define powf(x, y)
#define acosf(x)
static bool is_cyclic(const Nurb *nu)
KDTree_3d * tree
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
size_t(* MEM_allocN_len)(const void *vmemh)
Definition mallocn.cc:36
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static ulong state[N]
#define fabsf
#define sqrtf
#define atanf
BevPoint * bevpoints
float vec[3]
float arm_head[3]
float arm_tail[3]
float arm_mat[4][4]
ListBase bev
Definition BKE_curve.hh:41
const float * anim_path_accum_length
Definition BKE_curve.hh:49
char name[258]
Definition DNA_ID.h:432
void * first
struct bPose * pose
ObjectRuntimeHandle * runtime
ListBase * edbo
struct bConstraint * next
struct DualQuat deform_dual_quat
struct Bone * bone
struct bPoseChannel * parent
float chan_mat[4][4]
struct bPoseChannel * next
float constinv[4][4]
struct bPoseChannel_Runtime runtime
struct bPoseChannel * orig_pchan
float pose_mat[4][4]
struct ListBase siktree
ListBase chanbase
bPoseChannel ** chan_array
tSplineIK_Tree * next
bPoseChannel ** chain
bPoseChannel * root
bSplineIKConstraint * ik_data
const float * points
tSplineIK_Tree * prev
bConstraint * con
i
Definition text_draw.cc:230