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