Blender V5.0
blenkernel/intern/armature.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 <cctype>
10#include <cfloat>
11#include <cmath>
12#include <cstdlib>
13#include <cstring>
14#include <limits>
15#include <optional>
16
17#include "MEM_guardedalloc.h"
18
19#include "BLI_alloca.h"
20#include "BLI_bounds.hh"
21#include "BLI_ghash.h"
22#include "BLI_listbase.h"
23#include "BLI_math_geom.h"
24#include "BLI_math_matrix.h"
25#include "BLI_math_matrix.hh"
26#include "BLI_math_rotation.h"
27#include "BLI_math_vector.h"
28#include "BLI_span.hh"
29#include "BLI_string_utf8.h"
30#include "BLI_utildefines.h"
31#include "BLT_translation.hh"
32
33#include "DNA_defaults.h"
34
35#include "DNA_armature_types.h"
37#include "DNA_listBase.h"
38#include "DNA_object_types.h"
39#include "DNA_scene_types.h"
40
41#include "BKE_action.hh"
42#include "BKE_anim_data.hh"
44#include "BKE_armature.hh"
45#include "BKE_constraint.h"
46#include "BKE_curve.hh"
47#include "BKE_idprop.hh"
48#include "BKE_idtype.hh"
49#include "BKE_lib_id.hh"
50#include "BKE_lib_query.hh"
51#include "BKE_main.hh"
52#include "BKE_object.hh"
53#include "BKE_scene.hh"
54
55#include "ANIM_armature.hh"
57
60
61#include "BIK_api.h"
62
63#include "BLO_read_write.hh"
64
65using namespace blender;
66
67/* -------------------------------------------------------------------- */
70
71static void copy_bonechildren(Bone *bone_dst,
72 const Bone *bone_src,
73 const Bone *bone_src_act,
74 Bone **r_bone_dst_act,
75 const int flag);
76
77static void copy_bonechildren_custom_handles(Bone *bone_dst, bArmature *arm_dst);
78
80
81/* -------------------------------------------------------------------- */
84
85static void armature_init_data(ID *id)
86{
87 bArmature *armature = (bArmature *)id;
89
91}
92
102static void copy_bone_collection(bArmature *armature_dst,
103 BoneCollection *&bcoll_dst,
104 const BoneCollection *bcoll_src,
105 const int lib_id_flag)
106{
107 bcoll_dst = static_cast<BoneCollection *>(MEM_dupallocN(bcoll_src));
108
109 /* ID properties. */
110 if (bcoll_dst->prop) {
111 bcoll_dst->prop = IDP_CopyProperty_ex(bcoll_dst->prop, lib_id_flag);
112 }
113 if (bcoll_dst->system_properties) {
114 bcoll_dst->system_properties = IDP_CopyProperty_ex(bcoll_dst->system_properties, lib_id_flag);
115 }
116
117 /* Bone references. */
118 BLI_duplicatelist(&bcoll_dst->bones, &bcoll_dst->bones);
119 LISTBASE_FOREACH (BoneCollectionMember *, member, &bcoll_dst->bones) {
120 member->bone = BKE_armature_find_bone_name(armature_dst, member->bone->name);
121 }
122}
123
134static void armature_copy_data(Main * /*bmain*/,
135 std::optional<Library *> /*owner_library*/,
136 ID *id_dst,
137 const ID *id_src,
138 const int flag)
139{
140 bArmature *armature_dst = (bArmature *)id_dst;
141 const bArmature *armature_src = (const bArmature *)id_src;
142
143 Bone *bone_src, *bone_dst;
144 Bone *bone_dst_act = nullptr;
145
146 /* We never handle user-count here for own data. */
147 const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
148
149 armature_dst->bonehash = nullptr;
150
151 BLI_duplicatelist(&armature_dst->bonebase, &armature_src->bonebase);
152
153 /* Duplicate the children's lists. */
154 bone_dst = static_cast<Bone *>(armature_dst->bonebase.first);
155 for (bone_src = static_cast<Bone *>(armature_src->bonebase.first); bone_src;
156 bone_src = bone_src->next)
157 {
158 bone_dst->parent = nullptr;
159 copy_bonechildren(bone_dst, bone_src, armature_src->act_bone, &bone_dst_act, flag_subdata);
160 bone_dst = bone_dst->next;
161 }
162
163 armature_dst->act_bone = bone_dst_act;
164
165 BKE_armature_bone_hash_make(armature_dst);
166
167 /* Fix custom handle references. */
168 for (bone_dst = static_cast<Bone *>(armature_dst->bonebase.first); bone_dst;
169 bone_dst = bone_dst->next)
170 {
171 copy_bonechildren_custom_handles(bone_dst, armature_dst);
172 }
173
174 armature_dst->edbo = nullptr;
175 armature_dst->act_edbone = nullptr;
176
177 /* Duplicate bone collections & assignments. */
178 if (armature_src->collection_array) {
179 armature_dst->collection_array = static_cast<BoneCollection **>(
180 MEM_dupallocN(armature_src->collection_array));
181 armature_dst->collection_array_num = armature_src->collection_array_num;
182 for (int i = 0; i < armature_src->collection_array_num; i++) {
183 copy_bone_collection(armature_dst,
184 armature_dst->collection_array[i],
185 armature_src->collection_array[i],
186 flag);
187 }
188 }
189 else {
190 armature_dst->collection_array = nullptr;
191 armature_dst->collection_array_num = 0;
192 }
193
195 armature_src->runtime.active_collection_index);
196 ANIM_armature_runtime_refresh(armature_dst);
197}
198
200static void armature_free_data(ID *id)
201{
202 bArmature *armature = (bArmature *)id;
204
205 /* Free all BoneCollectionMembership objects. */
206 if (armature->collection_array) {
207 for (BoneCollection *bcoll : armature->collections_span()) {
208 BLI_freelistN(&bcoll->bones);
209 ANIM_bonecoll_free(bcoll, false);
210 }
211 MEM_freeN(armature->collection_array);
212 }
213 armature->collection_array = nullptr;
214 armature->collection_array_num = 0;
215
217 BKE_armature_bonelist_free(&armature->bonebase, false);
218
219 /* free editmode data */
220 if (armature->edbo) {
221 BKE_armature_editbonelist_free(armature->edbo, false);
222 MEM_freeN(armature->edbo);
223 armature->edbo = nullptr;
224 }
225}
226
228{
231 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
232 }));
234 data,
236 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
237 }));
238
239 LISTBASE_FOREACH (Bone *, curbone, &bone->childbase) {
241 }
242}
243
245{
248 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
249 }));
251 data,
253 edit_bone->system_properties, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
254 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
255 }));
256}
257
259{
262 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
263 }));
265 data,
267 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
268 }));
269}
270
272{
273 bArmature *arm = (bArmature *)id;
274 LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) {
276 }
277
278 if (arm->edbo != nullptr) {
279 LISTBASE_FOREACH (EditBone *, edit_bone, arm->edbo) {
281 }
282 }
283
284 for (BoneCollection *bcoll : arm->collections_span()) {
287 }
288}
289
290static void write_bone(BlendWriter *writer, Bone *bone)
291{
292 /* PATCH for upward compatibility after 2.37+ armature recode */
293 bone->size[0] = bone->size[1] = bone->size[2] = 1.0f;
294
295 /* Write this bone, except for its runtime data. */
296 const Bone_Runtime runtime_backup = bone->runtime;
297 bone->runtime = Bone_Runtime{};
298 BLO_write_struct(writer, Bone, bone);
299 bone->runtime = runtime_backup;
300
301 /* Write ID Properties -- and copy this comment EXACTLY for easy finding
302 * of library blocks that implement this. */
303 if (bone->prop) {
304 IDP_BlendWrite(writer, bone->prop);
305 }
306 if (bone->system_properties) {
307 IDP_BlendWrite(writer, bone->system_properties);
308 }
309
310 /* Write Children */
311 LISTBASE_FOREACH (Bone *, cbone, &bone->childbase) {
312 write_bone(writer, cbone);
313 }
314}
315
317{
318 /* Write this bone collection. */
319 BLO_write_struct(writer, BoneCollection, bcoll);
320
321 /* Write ID Properties -- and copy this comment EXACTLY for easy finding
322 * of library blocks that implement this. */
323 if (bcoll->prop) {
324 IDP_BlendWrite(writer, bcoll->prop);
325 }
326 if (bcoll->system_properties) {
327 IDP_BlendWrite(writer, bcoll->system_properties);
328 }
329
331}
332
333static void armature_blend_write(BlendWriter *writer, ID *id, const void *id_address)
334{
335 bArmature *arm = (bArmature *)id;
336
337 /* Clean up, important in undo case to reduce false detection of changed datablocks. */
338 arm->bonehash = nullptr;
339 arm->edbo = nullptr;
340 /* Must always be cleared (armatures don't have their own edit-data). */
341 arm->needs_flush_to_id = 0;
342 arm->act_edbone = nullptr;
343
344 const bArmature_Runtime runtime_backup = arm->runtime;
345 arm->runtime = bArmature_Runtime{};
346
347 /* Convert BoneCollections over to a listbase for writing. */
348 BoneCollection **collection_array_backup = arm->collection_array;
349 if (arm->collection_array_num > 0) {
350 for (int i = 0; i < arm->collection_array_num - 1; i++) {
351 arm->collection_array[i]->next = arm->collection_array[i + 1];
352 arm->collection_array[i + 1]->prev = arm->collection_array[i];
353 }
356 arm->collection_array = nullptr;
357 }
358
359 BLO_write_id_struct(writer, bArmature, id_address, &arm->id);
360 BKE_id_blend_write(writer, &arm->id);
361
362 /* Direct data */
363 LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) {
364 write_bone(writer, bone);
365 }
366
368 write_bone_collection(writer, bcoll);
369 }
370
371 /* Restore the BoneCollection array and clear the listbase. */
372 arm->collection_array = collection_array_backup;
373 for (int i = 0; i < arm->collection_array_num - 1; i++) {
374 arm->collection_array[i]->next = nullptr;
375 arm->collection_array[i + 1]->prev = nullptr;
376 }
378
379 arm->runtime = runtime_backup;
380}
381
382static void direct_link_bones(BlendDataReader *reader, Bone *bone)
383{
384 BLO_read_struct(reader, Bone, &bone->parent);
385
386 BLO_read_struct(reader, IDProperty, &bone->prop);
387 IDP_BlendDataRead(reader, &bone->prop);
389 IDP_BlendDataRead(reader, &bone->system_properties);
390
391 BLO_read_struct(reader, Bone, &bone->bbone_next);
392 BLO_read_struct(reader, Bone, &bone->bbone_prev);
393
395
396 BLO_read_struct_list(reader, Bone, &bone->childbase);
397
398 LISTBASE_FOREACH (Bone *, child, &bone->childbase) {
399 direct_link_bones(reader, child);
400 }
401
402 bone->runtime = Bone_Runtime{};
403}
404
406{
407 BLO_read_struct(reader, IDProperty, &bcoll->prop);
408 IDP_BlendDataRead(reader, &bcoll->prop);
410 IDP_BlendDataRead(reader, &bcoll->system_properties);
411
413 LISTBASE_FOREACH (BoneCollectionMember *, member, &bcoll->bones) {
414 BLO_read_struct(reader, Bone, &member->bone);
415 }
416}
417
419{
420 /* Read as listbase, but convert to an array on the armature. */
424 __func__);
425 {
426 int i;
427 int min_child_index = 0;
429 arm->collection_array[i] = bcoll;
430
431 if (bcoll->child_index > 0) {
432 min_child_index = min_ii(min_child_index, bcoll->child_index);
433 }
434 }
435
436 if (arm->collection_root_count == 0 && arm->collection_array_num > 0) {
437 /* There cannot be zero roots when there are any bone collections. This means the root count
438 * likely got lost for some reason, and should be reconstructed to avoid data corruption when
439 * modifying the array. */
440 if (min_child_index == 0) {
441 /* None of the bone collections had any children, so all are roots. */
443 }
444 else {
445 arm->collection_root_count = min_child_index;
446 }
447 }
448 }
449
450 /* We don't need the listbase or prev/next pointers because the
451 * collections are stored in an array. */
452 for (int i = 0; i < arm->collection_array_num - 1; i++) {
453 arm->collection_array[i]->next = nullptr;
454 arm->collection_array[i + 1]->prev = nullptr;
455 }
457
458 /* Bone collections added via an override can be edited, but ones that already exist in another
459 * blend file (so on the linked Armature) should not be touched. */
460 const bool reset_bcoll_override_flag = ID_IS_LINKED(&arm->id);
461 for (BoneCollection *bcoll : arm->collections_span()) {
462 direct_link_bone_collection(reader, bcoll);
463 if (reset_bcoll_override_flag) {
464 /* The linked Armature may have overrides in the library file already, and
465 * those should *not* be editable here. */
467 }
468 }
469}
470
472{
473 bArmature *arm = (bArmature *)id;
474 BLO_read_struct_list(reader, Bone, &arm->bonebase);
475 arm->bonehash = nullptr;
476 arm->edbo = nullptr;
477 /* Must always be cleared (armatures don't have their own edit-data). */
478 arm->needs_flush_to_id = 0;
479
480 LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) {
481 direct_link_bones(reader, bone);
482 }
483
484 read_bone_collections(reader, arm);
485
486 BLO_read_struct(reader, Bone, &arm->act_bone);
487 arm->act_edbone = nullptr;
488
490
491 arm->runtime = bArmature_Runtime{};
493}
494
495static void armature_undo_preserve(BlendLibReader * /*reader*/, ID *id_new, ID *id_old)
496{
497 bArmature *arm_new = (bArmature *)id_new;
498 bArmature *arm_old = (bArmature *)id_old;
499
500 animrig::bonecolls_copy_expanded_flag(arm_new->collections_span(), arm_old->collections_span());
501}
502
504 /*id_code*/ bArmature::id_type,
505 /*id_filter*/ FILTER_ID_AR,
506 /* IDProps of armature bones can use any type of ID. */
507 /*dependencies_id_types*/ FILTER_ID_ALL,
508 /*main_listbase_index*/ INDEX_ID_AR,
509 /*struct_size*/ sizeof(bArmature),
510 /*name*/ "Armature",
511 /*name_plural*/ N_("armatures"),
512 /*translation_context*/ BLT_I18NCONTEXT_ID_ARMATURE,
514 /*asset_type_info*/ nullptr,
515
516 /*init_data*/ armature_init_data,
517 /*copy_data*/ armature_copy_data,
518 /*free_data*/ armature_free_data,
519 /*make_local*/ nullptr,
520 /*foreach_id*/ armature_foreach_id,
521 /*foreach_cache*/ nullptr,
522 /*foreach_path*/ nullptr,
523 /*foreach_working_space_color*/ nullptr,
524 /*owner_pointer_get*/ nullptr,
525
526 /*blend_write*/ armature_blend_write,
527 /*blend_read_data*/ armature_blend_read_data,
528 /*blend_read_after_liblink*/ nullptr,
529
530 /*blend_read_undo_preserve*/ armature_undo_preserve,
531
532 /*lib_override_apply_post*/ nullptr,
533};
534
536
537/* -------------------------------------------------------------------- */
540
541bArmature *BKE_armature_add(Main *bmain, const char *name)
542{
543 bArmature *arm;
544
545 arm = BKE_id_new<bArmature>(bmain, name);
546 return arm;
547}
548
550{
551 if (ob->type == OB_ARMATURE) {
552 return (bArmature *)ob->data;
553 }
554 return nullptr;
555}
556
558{
559 int i = 0;
560 LISTBASE_FOREACH (Bone *, bone, lb) {
561 i += 1 + BKE_armature_bonelist_count(&bone->childbase);
562 }
563
564 return i;
565}
566
567void BKE_armature_bonelist_free(ListBase *lb, const bool do_id_user)
568{
569 LISTBASE_FOREACH (Bone *, bone, lb) {
570 if (bone->prop) {
571 IDP_FreeProperty_ex(bone->prop, do_id_user);
572 }
573 if (bone->system_properties) {
574 IDP_FreeProperty_ex(bone->system_properties, do_id_user);
575 }
576 BLI_freelistN(&bone->runtime.collections);
577 BKE_armature_bonelist_free(&bone->childbase, do_id_user);
578 }
579
580 BLI_freelistN(lb);
581}
582
583void BKE_armature_editbonelist_free(ListBase *lb, const bool do_id_user)
584{
585 LISTBASE_FOREACH_MUTABLE (EditBone *, edit_bone, lb) {
586 if (edit_bone->prop) {
587 IDP_FreeProperty_ex(edit_bone->prop, do_id_user);
588 }
589 if (edit_bone->system_properties) {
590 IDP_FreeProperty_ex(edit_bone->system_properties, do_id_user);
591 }
592 BLI_remlink_safe(lb, edit_bone);
593 MEM_freeN(edit_bone);
594 }
595}
596
597static void copy_bonechildren(Bone *bone_dst,
598 const Bone *bone_src,
599 const Bone *bone_src_act,
600 Bone **r_bone_dst_act,
601 const int flag)
602{
603 Bone *bone_src_child, *bone_dst_child;
604
605 if (bone_src == bone_src_act) {
606 *r_bone_dst_act = bone_dst;
607 }
608
609 if (bone_src->prop) {
610 bone_dst->prop = IDP_CopyProperty_ex(bone_src->prop, flag);
611 }
612 if (bone_src->system_properties) {
614 }
615
616 /* Clear the runtime cache of the collection relations, these will be
617 * reconstructed after the entire armature duplication is done. Don't free,
618 * just clear, as these pointers refer to the original and not the copy. */
620
621 /* Copy this bone's list */
622 BLI_duplicatelist(&bone_dst->childbase, &bone_src->childbase);
623
624 /* For each child in the list, update its children */
625 for (bone_src_child = static_cast<Bone *>(bone_src->childbase.first),
626 bone_dst_child = static_cast<Bone *>(bone_dst->childbase.first);
627 bone_src_child;
628 bone_src_child = bone_src_child->next, bone_dst_child = bone_dst_child->next)
629 {
630 bone_dst_child->parent = bone_dst;
631 copy_bonechildren(bone_dst_child, bone_src_child, bone_src_act, r_bone_dst_act, flag);
632 }
633}
634
635static void copy_bonechildren_custom_handles(Bone *bone_dst, bArmature *arm_dst)
636{
637 Bone *bone_dst_child;
638
639 if (bone_dst->bbone_prev) {
640 bone_dst->bbone_prev = BKE_armature_find_bone_name(arm_dst, bone_dst->bbone_prev->name);
641 }
642 if (bone_dst->bbone_next) {
643 bone_dst->bbone_next = BKE_armature_find_bone_name(arm_dst, bone_dst->bbone_next->name);
644 }
645
646 for (bone_dst_child = static_cast<Bone *>(bone_dst->childbase.first); bone_dst_child;
647 bone_dst_child = bone_dst_child->next)
648 {
649 copy_bonechildren_custom_handles(bone_dst_child, arm_dst);
650 }
651}
652
654
655/* -------------------------------------------------------------------- */
658
659static void copy_bone_transform(Bone *bone_dst, const Bone *bone_src)
660{
661 bone_dst->roll = bone_src->roll;
662
663 copy_v3_v3(bone_dst->head, bone_src->head);
664 copy_v3_v3(bone_dst->tail, bone_src->tail);
665
666 copy_m3_m3(bone_dst->bone_mat, bone_src->bone_mat);
667
668 copy_v3_v3(bone_dst->arm_head, bone_src->arm_head);
669 copy_v3_v3(bone_dst->arm_tail, bone_src->arm_tail);
670
671 copy_m4_m4(bone_dst->arm_mat, bone_src->arm_mat);
672
673 bone_dst->arm_roll = bone_src->arm_roll;
674}
675
676void BKE_armature_copy_bone_transforms(bArmature *armature_dst, const bArmature *armature_src)
677{
678 Bone *bone_dst = static_cast<Bone *>(armature_dst->bonebase.first);
679 const Bone *bone_src = static_cast<const Bone *>(armature_src->bonebase.first);
680 while (bone_dst != nullptr) {
681 BLI_assert(bone_src != nullptr);
682 copy_bone_transform(bone_dst, bone_src);
683 bone_dst = bone_dst->next;
684 bone_src = bone_src->next;
685 }
686}
687
689
690/* -------------------------------------------------------------------- */
695
698 const float mat[4][4],
699 const bool do_props,
700 /* Cached from 'mat'. */
701 const float mat3[3][3],
702 const float scale,
703 /* Child bones. */
704 const Bone *bone_parent,
705 const float arm_mat_parent_inv[4][4])
706{
707 LISTBASE_FOREACH (Bone *, bone, bonebase) {
708
709 /* Store the initial bone roll in a matrix, this is needed even for child bones
710 * so any change in head/tail doesn't cause the roll to change.
711 *
712 * Logic here is different to edit-mode because
713 * this is calculated in relative to the parent. */
714 float roll_mat3_pre[3][3];
715 {
716 float delta[3];
717 sub_v3_v3v3(delta, bone->tail, bone->head);
718 vec_roll_to_mat3(delta, bone->roll, roll_mat3_pre);
719 if (bone->parent == nullptr) {
720 mul_m3_m3m3(roll_mat3_pre, mat3, roll_mat3_pre);
721 }
722 }
723 /* Optional, use this for predictable results since the roll is re-calculated below anyway. */
724 bone->roll = 0.0f;
725
726 mul_m4_v3(mat, bone->arm_head);
727 mul_m4_v3(mat, bone->arm_tail);
728
729 /* Get the new head and tail */
730 if (bone_parent) {
731 sub_v3_v3v3(bone->head, bone->arm_head, bone_parent->arm_tail);
732 sub_v3_v3v3(bone->tail, bone->arm_tail, bone_parent->arm_tail);
733
734 mul_mat3_m4_v3(arm_mat_parent_inv, bone->head);
735 mul_mat3_m4_v3(arm_mat_parent_inv, bone->tail);
736 }
737 else {
738 copy_v3_v3(bone->head, bone->arm_head);
739 copy_v3_v3(bone->tail, bone->arm_tail);
740 }
741
742 /* Now the head/tail have been updated, set the roll back, matching 'roll_mat3_pre'. */
743 {
744 float roll_mat3_post[3][3], delta_mat3[3][3];
745 float delta[3];
746 sub_v3_v3v3(delta, bone->tail, bone->head);
747 vec_roll_to_mat3(delta, 0.0f, roll_mat3_post);
748 invert_m3(roll_mat3_post);
749 mul_m3_m3m3(delta_mat3, roll_mat3_post, roll_mat3_pre);
750 bone->roll = atan2f(delta_mat3[2][0], delta_mat3[2][2]);
751 }
752
753 BKE_armature_where_is_bone(bone, bone_parent, false);
754
755 {
756 float arm_mat3[3][3];
757 copy_m3_m4(arm_mat3, bone->arm_mat);
758 mat3_to_vec_roll(arm_mat3, nullptr, &bone->arm_roll);
759 }
760
761 if (do_props) {
762 bone->rad_head *= scale;
763 bone->rad_tail *= scale;
764 bone->dist *= scale;
765
766 /* we could be smarter and scale by the matrix along the x & z axis */
767 bone->xwidth *= scale;
768 bone->zwidth *= scale;
769 }
770
771 if (!BLI_listbase_is_empty(&bone->childbase)) {
772 float arm_mat_inv[4][4];
773 invert_m4_m4(arm_mat_inv, bone->arm_mat);
774 armature_transform_recurse(&bone->childbase, mat, do_props, mat3, scale, bone, arm_mat_inv);
775 }
776 }
777}
778
779void BKE_armature_transform(bArmature *arm, const float mat[4][4], const bool do_props)
780{
781 /* Store the scale of the matrix here to use on envelopes. */
782 float scale = mat4_to_scale(mat);
783 float mat3[3][3];
784
785 copy_m3_m4(mat3, mat);
786 normalize_m3(mat3);
787
788 armature_transform_recurse(&arm->bonebase, mat, do_props, mat3, scale, nullptr, nullptr);
789}
790
792
793/* -------------------------------------------------------------------- */
798
800{
801 LISTBASE_FOREACH (Bone *, curBone, lb) {
802 if (STREQ(curBone->name, name)) {
803 return curBone;
804 }
805
806 Bone *rbone = get_named_bone_bonechildren(&curBone->childbase, name);
807 if (rbone) {
808 return rbone;
809 }
810 }
811
812 return nullptr;
813}
814
816{
817 if (!arm) {
818 return nullptr;
819 }
820
821 if (arm->bonehash) {
822 return static_cast<Bone *>(BLI_ghash_lookup(arm->bonehash, name));
823 }
824
826}
827
829{
830 LISTBASE_FOREACH (Bone *, bone, lb) {
831 BLI_ghash_insert(bone_hash, bone->name, bone);
832 armature_bone_from_name_insert_recursive(bone_hash, &bone->childbase);
833 }
834}
835
843{
844 const int bones_count = BKE_armature_bonelist_count(&arm->bonebase);
845 GHash *bone_hash = BLI_ghash_str_new_ex(__func__, bones_count);
847 return bone_hash;
848}
849
851{
852 if (!arm->bonehash) {
854 }
855}
856
858{
859 if (arm->bonehash) {
860 BLI_ghash_free(arm->bonehash, nullptr, nullptr);
861 arm->bonehash = nullptr;
862 }
863}
864
866
867/* -------------------------------------------------------------------- */
870
872{
873 if (bone->flag & flag) {
874 return true;
875 }
876 if (bone->parent) {
878 }
879 return false;
880}
881
883
884/* -------------------------------------------------------------------- */
887
889 char name[MAXBONENAME], int /*strip_number*/, short axis, float head, float tail)
890{
891 char basename[MAXBONENAME];
892 uint len = STRNCPY_UTF8_RLEN(basename, name);
893 if (len == 0) {
894 return false;
895 }
896
897 /* Figure out extension to append:
898 * - The extension to append is based upon the axis that we are working on.
899 * - If head happens to be on 0, then we must consider the tail position as well to decide
900 * which side the bone is on
901 * -> If tail is 0, then its bone is considered to be on axis, so no extension should be added
902 * -> Otherwise, extension is added from perspective of object based on which side tail goes to
903 * - If head is non-zero, extension is added from perspective of object based on side head is on
904 */
905 const char *extension = nullptr;
906 if (axis == 2) {
907 /* z-axis - vertical (top/bottom) */
908 if (IS_EQF(head, 0.0f)) {
909 if (tail < 0) {
910 extension = "Bot";
911 }
912 else if (tail > 0) {
913 extension = "Top";
914 }
915 }
916 else {
917 if (head < 0) {
918 extension = "Bot";
919 }
920 else {
921 extension = "Top";
922 }
923 }
924 }
925 else if (axis == 1) {
926 /* y-axis - depth (front/back) */
927 if (IS_EQF(head, 0.0f)) {
928 if (tail < 0) {
929 extension = "Fr";
930 }
931 else if (tail > 0) {
932 extension = "Bk";
933 }
934 }
935 else {
936 if (head < 0) {
937 extension = "Fr";
938 }
939 else {
940 extension = "Bk";
941 }
942 }
943 }
944 else {
945 /* x-axis - horizontal (left/right) */
946 if (IS_EQF(head, 0.0f)) {
947 if (tail < 0) {
948 extension = "R";
949 }
950 else if (tail > 0) {
951 extension = "L";
952 }
953 }
954 else {
955 if (head < 0) {
956 extension = "R";
957 /* XXX Shouldn't this be simple else, as for z and y axes? */
958 }
959 else if (head > 0) {
960 extension = "L";
961 }
962 }
963 }
964
965 /* Simple name truncation
966 * - truncate if there is an extension and it wouldn't be able to fit
967 * - otherwise, just append to end
968 */
969 if (extension) {
970 bool changed = true;
971
972 while (changed) { /* remove extensions */
973 changed = false;
974 if (len > 2 && basename[len - 2] == '.') {
975 if (ELEM(basename[len - 1], 'L', 'R')) { /* L R */
976 basename[len - 2] = '\0';
977 len -= 2;
978 changed = true;
979 }
980 }
981 else if (len > 3 && basename[len - 3] == '.') {
982 if ((basename[len - 2] == 'F' && basename[len - 1] == 'r') || /* Fr */
983 (basename[len - 2] == 'B' && basename[len - 1] == 'k')) /* Bk */
984 {
985 basename[len - 3] = '\0';
986 len -= 3;
987 changed = true;
988 }
989 }
990 else if (len > 4 && basename[len - 4] == '.') {
991 if ((basename[len - 3] == 'T' && basename[len - 2] == 'o' &&
992 basename[len - 1] == 'p') || /* Top */
993 (basename[len - 3] == 'B' && basename[len - 2] == 'o' &&
994 basename[len - 1] == 't')) /* Bot */
995 {
996 basename[len - 4] = '\0';
997 len -= 4;
998 changed = true;
999 }
1000 }
1001 }
1002
1003 /* Subtract 1 from #MAXBONENAME for the null byte. Add 1 to the extension for the '.' */
1004 const int basename_maxncpy = (MAXBONENAME - 1) - (1 + strlen(extension));
1005 BLI_str_utf8_truncate_at_size(basename, basename_maxncpy);
1006 BLI_snprintf_utf8(name, MAXBONENAME, "%s.%s", basename, extension);
1007
1008 return true;
1009 }
1010 return false;
1011}
1012
1014
1015/* -------------------------------------------------------------------- */
1018
1019/* Compute a set of bezier parameter values that produce approximately equally spaced points. */
1020static void equalize_cubic_bezier(const float control[4][3],
1021 int temp_segments,
1022 int final_segments,
1023 const float *segment_scales,
1024 float *r_t_points)
1025{
1026 float (*coords)[3] = static_cast<float (*)[3]>(BLI_array_alloca(coords, temp_segments + 1));
1027 float *pdist = static_cast<float *>(BLI_array_alloca(pdist, temp_segments + 1));
1028
1029 /* Compute the first pass of bezier point coordinates. */
1030 for (int i = 0; i < 3; i++) {
1031 BKE_curve_forward_diff_bezier(control[0][i],
1032 control[1][i],
1033 control[2][i],
1034 control[3][i],
1035 &coords[0][i],
1036 temp_segments,
1037 sizeof(*coords));
1038 }
1039
1040 /* Calculate the length of the polyline at each point. */
1041 pdist[0] = 0.0f;
1042
1043 for (int i = 0; i < temp_segments; i++) {
1044 pdist[i + 1] = pdist[i] + len_v3v3(coords[i], coords[i + 1]);
1045 }
1046
1047 /* Go over distances and calculate new parameter values. */
1048 float dist_step = pdist[temp_segments];
1049 float dist = 0, sum = 0;
1050
1051 for (int i = 0; i < final_segments; i++) {
1052 sum += segment_scales[i];
1053 }
1054
1055 dist_step /= sum;
1056
1057 r_t_points[0] = 0.0f;
1058
1059 for (int i = 1, nr = 1; i <= final_segments; i++) {
1060 dist += segment_scales[i - 1] * dist_step;
1061
1062 /* We're looking for location (distance) 'dist' in the array. */
1063 while ((nr < temp_segments) && (dist >= pdist[nr])) {
1064 nr++;
1065 }
1066
1067 float fac = (pdist[nr] - dist) / (pdist[nr] - pdist[nr - 1]);
1068
1069 r_t_points[i] = (nr - fac) / temp_segments;
1070 }
1071
1072 r_t_points[final_segments] = 1.0f;
1073}
1074
1075/* Evaluate bezier position and tangent at a specific parameter value
1076 * using the De Casteljau algorithm. */
1077static void evaluate_cubic_bezier(const float control[4][3],
1078 float t,
1079 float r_pos[3],
1080 float r_tangent[3])
1081{
1082 float layer1[3][3];
1083 interp_v3_v3v3(layer1[0], control[0], control[1], t);
1084 interp_v3_v3v3(layer1[1], control[1], control[2], t);
1085 interp_v3_v3v3(layer1[2], control[2], control[3], t);
1086
1087 float layer2[2][3];
1088 interp_v3_v3v3(layer2[0], layer1[0], layer1[1], t);
1089 interp_v3_v3v3(layer2[1], layer1[1], layer1[2], t);
1090
1091 sub_v3_v3v3(r_tangent, layer2[1], layer2[0]);
1092 madd_v3_v3v3fl(r_pos, layer2[0], r_tangent, t);
1093}
1094
1096{
1097 if (pchan->bone->bbone_prev_type == BBONE_HANDLE_AUTO) {
1098 /* Use connected parent. */
1099 if (pchan->bone->flag & BONE_CONNECTED) {
1100 *r_prev = pchan->parent;
1101 }
1102 else {
1103 *r_prev = nullptr;
1104 }
1105 }
1106 else {
1107 /* Use the provided bone as prev - leave blank to eliminate this effect altogether. */
1108 *r_prev = pchan->bbone_prev;
1109 }
1110
1111 if (pchan->bone->bbone_next_type == BBONE_HANDLE_AUTO) {
1112 /* Use connected child. */
1113 *r_next = pchan->child;
1114 }
1115 else {
1116 /* Use the provided bone as next - leave blank to eliminate this effect altogether. */
1117 *r_next = pchan->bbone_next;
1118 }
1119}
1120
1122 const bool rest,
1123 BBoneSplineParameters *param)
1124{
1125 bPoseChannel *next, *prev;
1126 Bone *bone = pchan->bone;
1127 float imat[4][4], posemat[4][4], tmpmat[4][4];
1128 float delta[3];
1129
1130 memset(param, 0, sizeof(*param));
1131
1132 param->segments = bone->segments;
1133 param->length = bone->length;
1134
1135 if (!rest) {
1136 float scale[3];
1137
1138 /* Check if we need to take non-uniform bone scaling into account. */
1139 mat4_to_size(scale, pchan->pose_mat);
1140
1141 if (fabsf(scale[0] - scale[1]) > 1e-6f || fabsf(scale[1] - scale[2]) > 1e-6f) {
1142 param->do_scale = true;
1143 copy_v3_v3(param->scale, scale);
1144 }
1145 }
1146
1147 BKE_pchan_bbone_handles_get(pchan, &prev, &next);
1148
1149 /* Find the handle points, since this is inside bone space, the
1150 * first point = (0, 0, 0)
1151 * last point = (0, length, 0) */
1152 if (rest) {
1153 invert_m4_m4(imat, pchan->bone->arm_mat);
1154 }
1155 else if (param->do_scale) {
1156 copy_m4_m4(posemat, pchan->pose_mat);
1157 normalize_m4(posemat);
1158 invert_m4_m4(imat, posemat);
1159 }
1160 else {
1161 invert_m4_m4(imat, pchan->pose_mat);
1162 }
1163
1164 float prev_scale[3], next_scale[3];
1165
1166 copy_v3_fl(prev_scale, 1.0f);
1167 copy_v3_fl(next_scale, 1.0f);
1168
1169 if (prev) {
1170 float h1[3];
1171 bool done = false;
1172
1173 param->use_prev = true;
1174
1175 /* Transform previous point inside this bone space. */
1177 /* Use delta movement (from rest-pose),
1178 * and apply this relative to the current bone's head. */
1179 if (rest) {
1180 /* In rest-pose, arm_head == pose_head */
1181 zero_v3(param->prev_h);
1182 done = true;
1183 }
1184 else {
1185 sub_v3_v3v3(delta, prev->pose_head, prev->bone->arm_head);
1186 sub_v3_v3v3(h1, pchan->pose_head, delta);
1187 }
1188 }
1189 else if (bone->bbone_prev_type == BBONE_HANDLE_TANGENT) {
1190 /* Use bone direction by offsetting so that its tail meets current bone's head */
1191 if (rest) {
1192 sub_v3_v3v3(delta, prev->bone->arm_tail, prev->bone->arm_head);
1193 sub_v3_v3v3(h1, bone->arm_head, delta);
1194 }
1195 else {
1196 sub_v3_v3v3(delta, prev->pose_tail, prev->pose_head);
1197 sub_v3_v3v3(h1, pchan->pose_head, delta);
1198 }
1199 }
1200 else {
1201 /* Apply special handling for smoothly joining B-Bone chains */
1202 param->prev_bbone = (prev->bone->segments > 1);
1203
1204 /* Use bone head as absolute position. */
1205 copy_v3_v3(h1, rest ? prev->bone->arm_head : prev->pose_head);
1206 }
1207
1208 if (!done) {
1209 mul_v3_m4v3(param->prev_h, imat, h1);
1210 }
1211
1212 if (!param->prev_bbone) {
1213 /* Find the previous roll to interpolate. */
1214 mul_m4_m4m4(param->prev_mat, imat, rest ? prev->bone->arm_mat : prev->pose_mat);
1215
1216 /* Retrieve the local scale of the bone if necessary. */
1217 if ((bone->bbone_prev_flag & BBONE_HANDLE_SCALE_ANY) && !rest) {
1218 BKE_armature_mat_pose_to_bone(prev, prev->pose_mat, tmpmat);
1219 mat4_to_size(prev_scale, tmpmat);
1220 }
1221 }
1222 }
1223
1224 if (next) {
1225 float h2[3];
1226 bool done = false;
1227
1228 param->use_next = true;
1229
1230 /* Transform next point inside this bone space. */
1232 /* Use delta movement (from rest-pose),
1233 * and apply this relative to the current bone's tail. */
1234 if (rest) {
1235 /* In rest-pose, arm_head == pose_head */
1236 copy_v3_fl3(param->next_h, 0.0f, param->length, 0.0);
1237 done = true;
1238 }
1239 else {
1240 sub_v3_v3v3(delta, next->pose_head, next->bone->arm_head);
1241 add_v3_v3v3(h2, pchan->pose_tail, delta);
1242 }
1243 }
1244 else if (bone->bbone_next_type == BBONE_HANDLE_TANGENT) {
1245 /* Use bone direction by offsetting so that its head meets current bone's tail */
1246 if (rest) {
1247 sub_v3_v3v3(delta, next->bone->arm_tail, next->bone->arm_head);
1248 add_v3_v3v3(h2, bone->arm_tail, delta);
1249 }
1250 else {
1251 sub_v3_v3v3(delta, next->pose_tail, next->pose_head);
1252 add_v3_v3v3(h2, pchan->pose_tail, delta);
1253 }
1254 }
1255 else {
1256 /* Apply special handling for smoothly joining B-Bone chains */
1257 param->next_bbone = (next->bone->segments > 1);
1258
1259 /* Use bone tail as absolute position. */
1260 copy_v3_v3(h2, rest ? next->bone->arm_tail : next->pose_tail);
1261 }
1262
1263 if (!done) {
1264 mul_v3_m4v3(param->next_h, imat, h2);
1265 }
1266
1267 /* Find the next roll to interpolate as well. */
1268 mul_m4_m4m4(param->next_mat, imat, rest ? next->bone->arm_mat : next->pose_mat);
1269
1270 /* Retrieve the local scale of the bone if necessary. */
1271 if ((bone->bbone_next_flag & BBONE_HANDLE_SCALE_ANY) && !rest) {
1272 BKE_armature_mat_pose_to_bone(next, next->pose_mat, tmpmat);
1273 mat4_to_size(next_scale, tmpmat);
1274 }
1275 }
1276
1277 /* Add effects from bbone properties over the top
1278 * - These properties allow users to hand-animate the
1279 * bone curve/shape, without having to resort to using
1280 * extra bones
1281 * - The "bone" level offsets are for defining the rest-pose
1282 * shape of the bone (e.g. for curved eyebrows for example).
1283 * -> In the viewport, it's needed to define what the rest pose
1284 * looks like
1285 * -> For "rest == 0", we also still need to have it present
1286 * so that we can "cancel out" this rest-pose when it comes
1287 * time to deform some geometry, it won't cause double transforms.
1288 * - The "pchan" level offsets are the ones that animators actually
1289 * end up animating
1290 */
1291 {
1292 param->ease1 = bone->ease1 + (!rest ? pchan->ease1 : 0.0f);
1293 param->ease2 = bone->ease2 + (!rest ? pchan->ease2 : 0.0f);
1294
1295 param->roll1 = bone->roll1 + (!rest ? pchan->roll1 : 0.0f);
1296 param->roll2 = bone->roll2 + (!rest ? pchan->roll2 : 0.0f);
1297
1299 if (prev) {
1300 if (prev->bone) {
1301 param->roll1 += prev->bone->roll2;
1302 }
1303
1304 if (!rest) {
1305 param->roll1 += prev->roll2;
1306 }
1307 }
1308 }
1309
1310 copy_v3_v3(param->scale_in, bone->scale_in);
1311 copy_v3_v3(param->scale_out, bone->scale_out);
1312
1313 if (!rest) {
1314 mul_v3_v3(param->scale_in, pchan->scale_in);
1315 mul_v3_v3(param->scale_out, pchan->scale_out);
1316 }
1317
1318 /* Extra curve x / z */
1319 param->curve_in_x = bone->curve_in_x + (!rest ? pchan->curve_in_x : 0.0f);
1320 param->curve_in_z = bone->curve_in_z + (!rest ? pchan->curve_in_z : 0.0f);
1321
1322 param->curve_out_x = bone->curve_out_x + (!rest ? pchan->curve_out_x : 0.0f);
1323 param->curve_out_z = bone->curve_out_z + (!rest ? pchan->curve_out_z : 0.0f);
1324
1325 if (bone->bbone_flag & BBONE_SCALE_EASING) {
1326 param->ease1 *= param->scale_in[1];
1327 param->curve_in_x *= param->scale_in[1];
1328 param->curve_in_z *= param->scale_in[1];
1329
1330 param->ease2 *= param->scale_out[1];
1331 param->curve_out_x *= param->scale_out[1];
1332 param->curve_out_z *= param->scale_out[1];
1333 }
1334
1335 /* Custom handle scale. */
1337 param->scale_in[0] *= prev_scale[0];
1338 }
1340 param->scale_in[1] *= prev_scale[1];
1341 }
1343 param->scale_in[2] *= prev_scale[2];
1344 }
1346 param->ease1 *= prev_scale[1];
1347 param->curve_in_x *= prev_scale[1];
1348 param->curve_in_z *= prev_scale[1];
1349 }
1350
1352 param->scale_out[0] *= next_scale[0];
1353 }
1355 param->scale_out[1] *= next_scale[1];
1356 }
1358 param->scale_out[2] *= next_scale[2];
1359 }
1361 param->ease2 *= next_scale[1];
1362 param->curve_out_x *= next_scale[1];
1363 param->curve_out_z *= next_scale[1];
1364 }
1365 }
1366}
1367
1369 const bool rest,
1370 const bool for_deform,
1371 Mat4 *result_array)
1372{
1374
1375 BKE_pchan_bbone_spline_params_get(pchan, rest, &param);
1376
1377 pchan->bone->segments = BKE_pchan_bbone_spline_compute(&param, for_deform, result_array);
1378}
1379
1381 float h1[3],
1382 float *r_roll1,
1383 float h2[3],
1384 float *r_roll2,
1385 bool ease,
1386 bool offsets)
1387{
1388 float mat3[3][3];
1389 float length = param->length;
1390 float epsilon = 1e-5 * length;
1391
1392 if (param->do_scale) {
1393 length *= param->scale[1];
1394 }
1395
1396 *r_roll1 = *r_roll2 = 0.0f;
1397
1398 if (param->use_prev) {
1399 copy_v3_v3(h1, param->prev_h);
1400
1401 if (param->prev_bbone) {
1402 /* If previous bone is B-bone too, use average handle direction. */
1403 h1[1] -= length;
1404 }
1405
1406 if (normalize_v3(h1) < epsilon) {
1407 copy_v3_fl3(h1, 0.0f, -1.0f, 0.0f);
1408 }
1409
1410 negate_v3(h1);
1411
1412 if (!param->prev_bbone) {
1413 /* Find the previous roll to interpolate. */
1414 copy_m3_m4(mat3, param->prev_mat);
1415 mat3_vec_to_roll(mat3, h1, r_roll1);
1416 }
1417 }
1418 else {
1419 h1[0] = 0.0f;
1420 h1[1] = 1.0;
1421 h1[2] = 0.0f;
1422 }
1423
1424 if (param->use_next) {
1425 copy_v3_v3(h2, param->next_h);
1426
1427 /* If next bone is B-bone too, use average handle direction. */
1428 if (param->next_bbone) {
1429 /* pass */
1430 }
1431 else {
1432 h2[1] -= length;
1433 }
1434
1435 if (normalize_v3(h2) < epsilon) {
1436 copy_v3_fl3(h2, 0.0f, 1.0f, 0.0f);
1437 }
1438
1439 /* Find the next roll to interpolate as well. */
1440 copy_m3_m4(mat3, param->next_mat);
1441 mat3_vec_to_roll(mat3, h2, r_roll2);
1442 }
1443 else {
1444 h2[0] = 0.0f;
1445 h2[1] = 1.0f;
1446 h2[2] = 0.0f;
1447 }
1448
1449 if (ease) {
1450 const float circle_factor = length * (cubic_tangent_factor_circle_v3(h1, h2) / 0.75f);
1451
1452 const float hlength1 = param->ease1 * circle_factor;
1453 const float hlength2 = param->ease2 * circle_factor;
1454
1455 /* and only now negate h2 */
1456 mul_v3_fl(h1, hlength1);
1457 mul_v3_fl(h2, -hlength2);
1458 }
1459
1460 /* Add effects from bbone properties over the top
1461 * - These properties allow users to hand-animate the
1462 * bone curve/shape, without having to resort to using
1463 * extra bones
1464 * - The "bone" level offsets are for defining the rest-pose
1465 * shape of the bone (e.g. for curved eyebrows for example).
1466 * -> In the viewport, it's needed to define what the rest pose
1467 * looks like
1468 * -> For "rest == 0", we also still need to have it present
1469 * so that we can "cancel out" this rest-pose when it comes
1470 * time to deform some geometry, it won't cause double transforms.
1471 * - The "pchan" level offsets are the ones that animators actually
1472 * end up animating
1473 */
1474 if (offsets) {
1475 /* Add extra rolls. */
1476 *r_roll1 += param->roll1;
1477 *r_roll2 += param->roll2;
1478
1479 /* Extra curve x / y */
1480 /* NOTE:
1481 * Scale correction factors here are to compensate for some random floating-point glitches
1482 * when scaling up the bone or its parent by a factor of approximately 8.15/6, which results
1483 * in the bone length getting scaled up too (from 1 to 8), causing the curve to flatten out.
1484 */
1485 const float xscale_correction = (param->do_scale) ? param->scale[0] : 1.0f;
1486 const float zscale_correction = (param->do_scale) ? param->scale[2] : 1.0f;
1487
1488 h1[0] += param->curve_in_x * xscale_correction;
1489 h1[2] += param->curve_in_z * zscale_correction;
1490
1491 h2[0] += param->curve_out_x * xscale_correction;
1492 h2[2] += param->curve_out_z * zscale_correction;
1493 }
1494}
1495
1497 const float scalemats[2][4][4],
1498 const float pos[3],
1499 const float axis[3],
1500 float roll,
1501 float scalex,
1502 float scalez,
1503 float result[4][4])
1504{
1505 float mat3[3][3];
1506
1507 vec_roll_to_mat3(axis, roll, mat3);
1508
1509 copy_m4_m3(result, mat3);
1510 copy_v3_v3(result[3], pos);
1511
1512 if (param->do_scale) {
1513 /* Correct for scaling when this matrix is used in scaled space. */
1514 mul_m4_series(result, scalemats[0], result, scalemats[1]);
1515 }
1516
1517 /* BBone scale... */
1518 mul_v3_fl(result[0], scalex);
1519 mul_v3_fl(result[2], scalez);
1520}
1521
1522/* Fade from first to second derivative when the handle is very short. */
1523static void ease_handle_axis(const float deriv1[3], const float deriv2[3], float r_axis[3])
1524{
1525 const float gap = 0.1f;
1526
1527 copy_v3_v3(r_axis, deriv1);
1528
1529 const float len2 = len_squared_v3(deriv2);
1530 if (UNLIKELY(len2 == 0.0f)) {
1531 return;
1532 }
1533 const float len1 = len_squared_v3(deriv1);
1534 const float ratio = len1 / len2;
1535 if (ratio < gap * gap) {
1536 madd_v3_v3fl(r_axis, deriv2, gap - sqrtf(ratio));
1537 }
1538}
1539
1541 const bool for_deform,
1542 Mat4 *result_array)
1543{
1544 float scalemats[2][4][4];
1545 float bezt_controls[4][3];
1546 float h1[3], roll1, h2[3], roll2, prev[3], cur[3], axis[3];
1547 float length = param->length;
1548
1549 if (param->do_scale) {
1550 size_to_mat4(scalemats[1], param->scale);
1551 invert_m4_m4(scalemats[0], scalemats[1]);
1552
1553 length *= param->scale[1];
1554 }
1555
1556 BKE_pchan_bbone_handles_compute(param, h1, &roll1, h2, &roll2, true, true);
1557
1558 /* Make curve. */
1560
1561 copy_v3_fl3(bezt_controls[3], 0.0f, length, 0.0f);
1562 add_v3_v3v3(bezt_controls[2], bezt_controls[3], h2);
1563 copy_v3_v3(bezt_controls[1], h1);
1564 zero_v3(bezt_controls[0]);
1565
1566 /* Compute lengthwise segment scale. */
1567 float segment_scales[MAX_BBONE_SUBDIV];
1568
1569 CLAMP_MIN(param->scale_in[1], 0.0001f);
1570 CLAMP_MIN(param->scale_out[1], 0.0001f);
1571
1572 const float log_scale_in_len = logf(param->scale_in[1]);
1573 const float log_scale_out_len = logf(param->scale_out[1]);
1574
1575 for (int i = 0; i < param->segments; i++) {
1576 const float fac = float(i) / (param->segments - 1);
1577 segment_scales[i] = expf(interpf(log_scale_out_len, log_scale_in_len, fac));
1578 }
1579
1580 /* Compute segment vertex offsets along the curve length. */
1581 float bezt_points[MAX_BBONE_SUBDIV + 1];
1582
1584 bezt_controls, MAX_BBONE_SUBDIV, param->segments, segment_scales, bezt_points);
1585
1586 /* Deformation uses N+1 matrices computed at points between the segments. */
1587 if (for_deform) {
1588 /* Bezier derivatives. */
1589 float bezt_deriv1[3][3], bezt_deriv2[2][3];
1590
1591 for (int i = 0; i < 3; i++) {
1592 sub_v3_v3v3(bezt_deriv1[i], bezt_controls[i + 1], bezt_controls[i]);
1593 }
1594 for (int i = 0; i < 2; i++) {
1595 sub_v3_v3v3(bezt_deriv2[i], bezt_deriv1[i + 1], bezt_deriv1[i]);
1596 }
1597
1598 /* End points require special handling to fix zero length handles. */
1599 ease_handle_axis(bezt_deriv1[0], bezt_deriv2[0], axis);
1601 scalemats,
1602 bezt_controls[0],
1603 axis,
1604 roll1,
1605 param->scale_in[0],
1606 param->scale_in[2],
1607 result_array[0].mat);
1608
1609 for (int a = 1; a < param->segments; a++) {
1610 evaluate_cubic_bezier(bezt_controls, bezt_points[a], cur, axis);
1611
1612 float fac = float(a) / param->segments;
1613 float roll = interpf(roll2, roll1, fac);
1614 float scalex = interpf(param->scale_out[0], param->scale_in[0], fac);
1615 float scalez = interpf(param->scale_out[2], param->scale_in[2], fac);
1616
1618 param, scalemats, cur, axis, roll, scalex, scalez, result_array[a].mat);
1619 }
1620
1621 negate_v3(bezt_deriv2[1]);
1622 ease_handle_axis(bezt_deriv1[2], bezt_deriv2[1], axis);
1624 scalemats,
1625 bezt_controls[3],
1626 axis,
1627 roll2,
1628 param->scale_out[0],
1629 param->scale_out[2],
1630 result_array[param->segments].mat);
1631 }
1632 /* Other code (e.g. display) uses matrices for the segments themselves. */
1633 else {
1634 zero_v3(prev);
1635
1636 for (int a = 0; a < param->segments; a++) {
1637 evaluate_cubic_bezier(bezt_controls, bezt_points[a + 1], cur, axis);
1638
1639 sub_v3_v3v3(axis, cur, prev);
1640
1641 float fac = (a + 0.5f) / param->segments;
1642 float roll = interpf(roll2, roll1, fac);
1643 float scalex = interpf(param->scale_out[0], param->scale_in[0], fac);
1644 float scalez = interpf(param->scale_out[2], param->scale_in[2], fac);
1645
1647 param, scalemats, prev, axis, roll, scalex, scalez, result_array[a].mat);
1648 copy_v3_v3(prev, cur);
1649 }
1650 }
1651
1652 return param->segments;
1653}
1654
1656 const int segments,
1657 const bool use_boundaries)
1658{
1659 bPoseChannel_Runtime *runtime = &pchan->runtime;
1660
1661 if (runtime->bbone_segments != segments) {
1663
1664 runtime->bbone_segments = segments;
1665 runtime->bbone_rest_mats = MEM_malloc_arrayN<Mat4>(1 + uint(segments),
1666 "bPoseChannel_Runtime::bbone_rest_mats");
1667 runtime->bbone_pose_mats = MEM_malloc_arrayN<Mat4>(1 + uint(segments),
1668 "bPoseChannel_Runtime::bbone_pose_mats");
1670 2 + uint(segments), "bPoseChannel_Runtime::bbone_deform_mats");
1672 1 + uint(segments), "bPoseChannel_Runtime::bbone_dual_quats");
1673 }
1674
1675 /* If the segment count changed, the array was deallocated and nulled above. */
1676 if (use_boundaries && !runtime->bbone_segment_boundaries) {
1678 1 + uint(segments), "bPoseChannel_Runtime::bbone_segment_boundaries");
1679 }
1680 else if (!use_boundaries) {
1682 }
1683}
1684
1687{
1688 const Bone *bone = pchan->bone;
1689 bPoseChannel_Runtime *runtime = &pchan->runtime;
1690 const Mat4 *b_bone_rest = runtime->bbone_rest_mats;
1692
1693 /* Convert joints to pose space. */
1694 for (int i = 0; i <= bone->segments; i++) {
1695 mul_v3_m4v3(boundaries[i].point, bone->arm_mat, b_bone_rest[i].mat[3]);
1696 mul_v3_mat3_m4v3(boundaries[i].plane_normal, bone->arm_mat, b_bone_rest[i].mat[1]);
1697 normalize_v3(boundaries[i].plane_normal);
1698 }
1699
1700 /* Precompute coefficients for the mapping calculations. */
1701 for (int i = 0; i <= bone->segments; i++) {
1702 boundaries[i].plane_offset = dot_v3v3(boundaries[i].point, boundaries[i].plane_normal);
1703 }
1704
1705 /* Precompute the inverted length of the curve. */
1706 float arc_length = 0.0f;
1707
1708 for (int i = 0; i < bone->segments; i++) {
1709 arc_length += len_v3v3(boundaries[i + 1].point, boundaries[i].point);
1710 }
1711
1712 runtime->bbone_arc_length_reciprocal = 1.0f / arc_length;
1713
1714 /* Precompute the BSP depth based widening coefficients.
1715 * The actual space partitioning includes two extra virtual segments for the ends. */
1716 const int bsp_depth = int(ceilf(log2f(bone->segments + 2)));
1717
1718 BLI_assert(bsp_depth <= bone->segments);
1719
1720 /* Maximum half-width of the smoothing band at the bsp tree root plane, in segments.
1721 * The tuning coefficient was chosen by trial and error (see PR #110758). */
1722 const float tuning_factor = 0.222f;
1723 const float straight_length = len_v3v3(boundaries[0].point, boundaries[bone->segments].point);
1724 const float max_depth_scale = bone->segments * (straight_length / arc_length) * tuning_factor;
1725
1726 /* Per tree layer scaling factor, aiming to reduce the radius to 1 segment at the leaf level.
1727 * Since depth_scale is actually a reciprocal of the width, this factor is >= 1. */
1728 const float scale_factor = powf(max_ff(max_depth_scale, 1.0f), 1.0f / (bsp_depth - 1));
1729
1730 boundaries[0].depth_scale = bone->segments / max_depth_scale;
1731
1732 for (int i = 1; i < bsp_depth; i++) {
1733 boundaries[i].depth_scale = boundaries[i - 1].depth_scale * scale_factor;
1734 }
1735}
1736
1738{
1739 bPoseChannel_Runtime *runtime = &pchan->runtime;
1740 Bone *bone = pchan->bone;
1741 int segments = bone->segments;
1742
1743 BLI_assert(segments > 1);
1744
1745 /* Allocate the cache if needed. */
1746 const bool use_curved_mapping = bone->bbone_mapping_mode == BBONE_MAPPING_CURVED;
1747
1748 allocate_bbone_cache(pchan, segments, use_curved_mapping);
1749
1750 /* Compute the shape. */
1751 Mat4 *b_bone = runtime->bbone_pose_mats;
1752 Mat4 *b_bone_rest = runtime->bbone_rest_mats;
1753 Mat4 *b_bone_mats = runtime->bbone_deform_mats;
1754 DualQuat *b_bone_dual_quats = runtime->bbone_dual_quats;
1755 int a;
1756
1757 BKE_pchan_bbone_spline_setup(pchan, false, true, b_bone);
1758 BKE_pchan_bbone_spline_setup(pchan, true, true, b_bone_rest);
1759
1760 /* Compute segment boundaries. */
1761 if (runtime->bbone_segment_boundaries) {
1762 BLI_assert(use_curved_mapping);
1764 }
1765
1766 /* Compute deform matrices. */
1767 /* first matrix is the inverse arm_mat, to bring points in local bone space
1768 * for finding out which segment it belongs to */
1769 invert_m4_m4(b_bone_mats[0].mat, bone->arm_mat);
1770
1771 /* then we make the b_bone_mats:
1772 * - first transform to local bone space
1773 * - translate over the curve to the bbone mat space
1774 * - transform with b_bone matrix
1775 * - transform back into global space */
1776
1777 for (a = 0; a <= bone->segments; a++) {
1778 float tmat[4][4];
1779
1780 invert_m4_m4(tmat, b_bone_rest[a].mat);
1781 mul_m4_series(b_bone_mats[a + 1].mat,
1782 pchan->chan_mat,
1783 bone->arm_mat,
1784 b_bone[a].mat,
1785 tmat,
1786 b_bone_mats[0].mat);
1787
1788 /* Compute the orthonormal object space rest matrix of the segment. */
1789 mul_m4_m4m4(tmat, bone->arm_mat, b_bone_rest[a].mat);
1790 normalize_m4(tmat);
1791
1792 mat4_to_dquat(&b_bone_dual_quats[a], tmat, b_bone_mats[a + 1].mat);
1793 }
1794}
1795
1797{
1798 bPoseChannel_Runtime *runtime = &pchan->runtime;
1799 bPoseChannel_Runtime *runtime_from = &pchan_from->runtime;
1800 int segments = runtime_from->bbone_segments;
1801
1802 if (segments <= 1) {
1804 }
1805 else {
1806 const bool use_curved_mapping = runtime_from->bbone_segment_boundaries != nullptr;
1807
1808 allocate_bbone_cache(pchan, segments, use_curved_mapping);
1809
1810 memcpy(runtime->bbone_rest_mats, runtime_from->bbone_rest_mats, sizeof(Mat4) * (1 + segments));
1811 memcpy(runtime->bbone_pose_mats, runtime_from->bbone_pose_mats, sizeof(Mat4) * (1 + segments));
1812 memcpy(runtime->bbone_deform_mats,
1813 runtime_from->bbone_deform_mats,
1814 sizeof(Mat4) * (2 + segments));
1815 memcpy(runtime->bbone_dual_quats,
1816 runtime_from->bbone_dual_quats,
1817 sizeof(DualQuat) * (1 + segments));
1818
1819 if (use_curved_mapping) {
1821
1822 memcpy(runtime->bbone_segment_boundaries,
1823 runtime_from->bbone_segment_boundaries,
1824 sizeof(bPoseChannel_BBoneSegmentBoundary) * (1 + segments));
1825 }
1826 else {
1827 BLI_assert(runtime->bbone_segment_boundaries == nullptr);
1828 }
1829 }
1830}
1831
1833 float head_tail,
1834 int *r_index,
1835 float *r_blend_next)
1836{
1837 int segments = pchan->bone->segments;
1838
1839 CLAMP(head_tail, 0.0f, 1.0f);
1840
1841 /* Calculate the indices of the 2 affecting b_bone segments.
1842 * Integer part is the first segment's index.
1843 * Integer part plus 1 is the second segment's index.
1844 * Fractional part is the blend factor. */
1845 float pre_blend = head_tail * float(segments);
1846
1847 int index = int(floorf(pre_blend));
1848 CLAMP(index, 0, segments - 1);
1849
1850 float blend = pre_blend - index;
1851 CLAMP(blend, 0.0f, 1.0f);
1852
1853 *r_index = index;
1854 *r_blend_next = blend;
1855}
1856
1859 const float *co,
1860 int *r_index,
1861 float *r_blend_next)
1862{
1863 const Mat4 *mats = pchan->runtime.bbone_deform_mats;
1864 const float (*mat)[4] = mats[0].mat;
1865
1866 /* Transform co to bone space and get its y component. */
1867 const float y = mat[0][1] * co[0] + mat[1][1] * co[1] + mat[2][1] * co[2] + mat[3][1];
1868
1869 /* Calculate the indices of the 2 affecting b_bone segments. */
1871 pchan, y / pchan->bone->length, r_index, r_blend_next);
1872}
1873
1876 const float *co)
1877{
1878 return dot_v3v3(co, boundary.plane_normal) - boundary.plane_offset;
1879}
1880
1883 const float *co,
1884 int *r_index,
1885 float *r_blend_next)
1886{
1888 const int segments = pchan->runtime.bbone_segments;
1889
1890 /* Saved signed distances from co to each checked boundary plane. */
1891 float boundary_dist[MAX_BBONE_SUBDIV + 1];
1892
1893 /* Stack of BSP plane indices that were checked in the binary search. */
1894 int boundary_idx_stack[MAX_BBONE_SUBDIV];
1895 int stack_top = -1;
1896
1897 /* Perform a BSP binary search to narrow things down to one segment.
1898 * Checked BSP planes are stored for the smoothing pass later. */
1899 int start = -1, end = segments + 1, bias = 0;
1900
1901 while (end - start > 1) {
1902 const int mid = (start + end + bias) / 2;
1903
1904 BLI_assert(start < mid && mid < end);
1905
1906 const float dist = bbone_segment_bsp_signed_distance(boundaries[mid], co);
1907
1908 boundary_idx_stack[++stack_top] = mid;
1909 boundary_dist[mid] = dist;
1910
1911 if (dist < 0) {
1912 end = mid;
1913 /* Bias division of odd numbers toward the previous split. This should produce
1914 * a slightly smoother and more symmetrical evolute boundary near the ends. */
1915 bias = 1;
1916 }
1917 else {
1918 start = mid;
1919 bias = 0;
1920 }
1921 }
1922
1923 /* Compute the mapping from the individual segment, or the curve ends. */
1924 const float segment_size = 1.0f / segments;
1925 float head_tail;
1926
1927 if (end <= 0) {
1928 head_tail = 0;
1929 }
1930 else if (start >= segments) {
1931 head_tail = 1;
1932 }
1933 else {
1934 /* Linear interpolation between the innermost two planes. */
1935 const float d1 = fabsf(boundary_dist[start]);
1936 const float d2 = fabsf(boundary_dist[end]);
1937 const float t = d1 / (d1 + d2);
1938
1939 head_tail = segment_size * (start + t);
1940 }
1941
1942 /* Smooth the mapping to suppress discontinuities by using BSP boundaries up the stack.
1943 *
1944 * This works basically by pulling the mapped position towards the boundary in order to
1945 * reduce the gradient slope to the ideal value (the one you get for points directly on
1946 * the curve), using heuristic blend strength falloff coefficients based on the distances
1947 * to the boundary plane before and after mapping. See PR #110758 for more details, or
1948 * https://developer.blender.org/docs/features/animation/b-bone_vertex_mapping/#curved-mapping */
1949 const float segment_scale = pchan->runtime.bbone_arc_length_reciprocal;
1950
1951 for (int i = stack_top; i >= 0; --i) {
1952 const int boundary_idx = boundary_idx_stack[i];
1953
1954 /* Boundary in the head-tail space. */
1955 const float boundary_pos = boundary_idx * segment_size;
1956
1957 /* Distance of the original 3d point (co) from the boundary plane,
1958 * mapped to the head-tail space using the ideal slope ratio. */
1959 const float point_dist = boundary_dist[boundary_idx] * segment_scale;
1960 const float point_dist_abs = fabsf(point_dist);
1961
1962 /* Distance of the current mapped position from the boundary in the head-tail space. */
1963 const float mapped_dist = fabsf(head_tail - boundary_pos);
1964
1965 /* Only reduce the local gradient slope, don't increase it. This basically limits
1966 * smoothing to the inside of the curve, leaving outside as is. */
1967 const float slope_gap = mapped_dist - point_dist_abs;
1968
1969 if (slope_gap <= 0) {
1970 continue;
1971 }
1972
1973 /* Only affect points close to the split line; the radius depends on the depth
1974 * in the stack using precomputed coefficients. */
1975 const float dist_coeff = 1.0f - point_dist_abs * boundaries[i].depth_scale;
1976
1977 if (dist_coeff <= 0) {
1978 continue;
1979 }
1980
1981 /* Asymptotically clamp the slope coefficient to 1. The tune coefficients here and
1982 * below control the sharpness of the transition and were chosen by trial and error. */
1983 const float slope_tune_coeff = 3.0f;
1984 const float scaled_gap = slope_gap * slope_tune_coeff;
1985 const float slope_coeff = scaled_gap / (scaled_gap + point_dist_abs);
1986
1987 /* Smooth the distance based coefficient around zero. */
1988 const float dist_tune_coeff = 7.0f;
1989 const float dist_coeff_smooth = dist_coeff * dist_coeff * (dist_tune_coeff + 1.0f) /
1990 (dist_tune_coeff * dist_coeff + 1.0f);
1991
1992 /* Blend towards the point on the ideal slope. */
1993 const float target_pos = boundary_pos + point_dist;
1994
1995 head_tail = interpf(target_pos, head_tail, slope_coeff * dist_coeff_smooth);
1996 }
1997
1998 /* Calculate the indices of the 2 affecting b_bone segments. */
1999 BKE_pchan_bbone_deform_clamp_segment_index(pchan, head_tail, r_index, r_blend_next);
2000}
2001
2003 const float *co,
2004 int *r_index,
2005 float *r_blend_next)
2006{
2007 if (pchan->runtime.bbone_segment_boundaries) {
2008 find_bbone_segment_index_curved(pchan, co, r_index, r_blend_next);
2009 }
2010 else {
2011 find_bbone_segment_index_straight(pchan, co, r_index, r_blend_next);
2012 }
2013}
2014
2016
2017/* -------------------------------------------------------------------- */
2020
2021void BKE_armature_mat_world_to_pose(Object *ob, const float inmat[4][4], float outmat[4][4])
2022{
2023 float obmat[4][4];
2024
2025 /* prevent crashes */
2026 if (ob == nullptr) {
2027 return;
2028 }
2029
2030 /* Get inverse of (armature) object's matrix. */
2031 invert_m4_m4(obmat, ob->object_to_world().ptr());
2032
2033 /* multiply given matrix by object's-inverse to find pose-space matrix */
2034 mul_m4_m4m4(outmat, inmat, obmat);
2035}
2036
2037void BKE_armature_loc_world_to_pose(Object *ob, const float inloc[3], float outloc[3])
2038{
2039 float xLocMat[4][4];
2040 float nLocMat[4][4];
2041
2042 /* build matrix for location */
2043 unit_m4(xLocMat);
2044 copy_v3_v3(xLocMat[3], inloc);
2045
2046 /* get bone-space cursor matrix and extract location */
2047 BKE_armature_mat_world_to_pose(ob, xLocMat, nLocMat);
2048 copy_v3_v3(outloc, nLocMat[3]);
2049}
2050
2052
2053/* -------------------------------------------------------------------- */
2056
2057void BKE_bone_offset_matrix_get(const Bone *bone, float offs_bone[4][4])
2058{
2059 BLI_assert(bone->parent != nullptr);
2060
2061 /* Bone transform itself. */
2062 copy_m4_m3(offs_bone, bone->bone_mat);
2063
2064 /* The bone's root offset (is in the parent's coordinate system). */
2065 copy_v3_v3(offs_bone[3], bone->head);
2066
2067 /* Get the length translation of parent (length along y axis). */
2068 offs_bone[3][1] += bone->parent->length;
2069}
2070
2072 BoneParentTransform *r_bpt)
2073{
2074 const Bone *bone, *parbone;
2075 const bPoseChannel *parchan;
2076
2077 /* set up variables for quicker access below */
2078 bone = pchan->bone;
2079 parbone = bone->parent;
2080 parchan = pchan->parent;
2081
2082 if (parchan) {
2083 float offs_bone[4][4];
2084 /* yoffs(b-1) + root(b) + bonemat(b). */
2085 BKE_bone_offset_matrix_get(bone, offs_bone);
2086
2088 bone->inherit_scale_mode,
2089 offs_bone,
2090 parbone->arm_mat,
2091 parchan->pose_mat,
2092 r_bpt);
2093 }
2094 else {
2096 bone->flag, bone->inherit_scale_mode, bone->arm_mat, nullptr, nullptr, r_bpt);
2097 }
2098}
2099
2101 int inherit_scale_mode,
2102 const float offs_bone[4][4],
2103 const float parent_arm_mat[4][4],
2104 const float parent_pose_mat[4][4],
2105 BoneParentTransform *r_bpt)
2106{
2107 copy_v3_fl(r_bpt->post_scale, 1.0f);
2108
2109 if (parent_pose_mat) {
2110 const bool use_rotation = (bone_flag & BONE_HINGE) == 0;
2111 const bool full_transform = use_rotation && inherit_scale_mode == BONE_INHERIT_SCALE_FULL;
2112
2113 /* Compose the rotscale matrix for this bone. */
2114 if (full_transform) {
2115 /* Parent pose rotation and scale. */
2116 mul_m4_m4m4(r_bpt->rotscale_mat, parent_pose_mat, offs_bone);
2117 }
2118 else {
2119 float tmat[4][4], tscale[3];
2120
2121 /* If using parent pose rotation: */
2122 if (use_rotation) {
2123 copy_m4_m4(tmat, parent_pose_mat);
2124
2125 /* Normalize the matrix when needed. */
2126 switch (inherit_scale_mode) {
2129 /* Keep scale and shear. */
2130 break;
2131
2134 /* Remove scale and shear from parent. */
2135 orthogonalize_m4_stable(tmat, 1, true);
2136 break;
2137
2139 /* Remove shear and extract scale. */
2140 orthogonalize_m4_stable(tmat, 1, false);
2141 normalize_m4_ex(tmat, r_bpt->post_scale);
2142 break;
2143
2145 /* Remove only scale - bad legacy way. */
2146 normalize_m4(tmat);
2147 break;
2148
2149 default:
2151 }
2152 }
2153 /* If removing parent pose rotation: */
2154 else {
2155 copy_m4_m4(tmat, parent_arm_mat);
2156
2157 /* Copy the parent scale when needed. */
2158 switch (inherit_scale_mode) {
2160 /* Ignore effects of shear. */
2161 mat4_to_size(tscale, parent_pose_mat);
2162 rescale_m4(tmat, tscale);
2163 break;
2164
2166 /* Take the effects of parent shear into account to get exact volume. */
2167 mat4_to_size_fix_shear(tscale, parent_pose_mat);
2168 rescale_m4(tmat, tscale);
2169 break;
2170
2172 mat4_to_size_fix_shear(r_bpt->post_scale, parent_pose_mat);
2173 break;
2174
2178 /* Keep unscaled. */
2179 break;
2180
2181 default:
2183 }
2184 }
2185
2186 /* Apply the average parent scale when needed. */
2187 if (inherit_scale_mode == BONE_INHERIT_SCALE_AVERAGE) {
2188 mul_mat3_m4_fl(tmat, cbrtf(fabsf(mat4_to_volume_scale(parent_pose_mat))));
2189 }
2190
2191 mul_m4_m4m4(r_bpt->rotscale_mat, tmat, offs_bone);
2192
2193 /* Remove remaining shear when needed, preserving volume. */
2194 if (inherit_scale_mode == BONE_INHERIT_SCALE_FIX_SHEAR) {
2195 orthogonalize_m4_stable(r_bpt->rotscale_mat, 1, false);
2196 }
2197 }
2198
2199 /* Compose the loc matrix for this bone. */
2200 /* NOTE: That version does not modify bone's loc when HINGE/NO_SCALE options are set. */
2201
2202 /* In this case, use the object's space *orientation*. */
2203 if (bone_flag & BONE_NO_LOCAL_LOCATION) {
2204 /* XXX I'm sure that code can be simplified! */
2205 float bone_loc[4][4], bone_rotscale[3][3], tmat4[4][4], tmat3[3][3];
2206 unit_m4(bone_loc);
2207 unit_m4(r_bpt->loc_mat);
2208 unit_m4(tmat4);
2209
2210 mul_v3_m4v3(bone_loc[3], parent_pose_mat, offs_bone[3]);
2211
2212 unit_m3(bone_rotscale);
2213 copy_m3_m4(tmat3, parent_pose_mat);
2214 mul_m3_m3m3(bone_rotscale, tmat3, bone_rotscale);
2215
2216 copy_m4_m3(tmat4, bone_rotscale);
2217 mul_m4_m4m4(r_bpt->loc_mat, bone_loc, tmat4);
2218 }
2219 /* Those flags do not affect position, use plain parent transform space! */
2220 else if (!full_transform) {
2221 mul_m4_m4m4(r_bpt->loc_mat, parent_pose_mat, offs_bone);
2222 }
2223 /* Else (i.e. default, usual case),
2224 * just use the same matrix for rotation/scaling, and location. */
2225 else {
2226 copy_m4_m4(r_bpt->loc_mat, r_bpt->rotscale_mat);
2227 }
2228 }
2229 /* Root bones. */
2230 else {
2231 /* Rotation/scaling. */
2232 copy_m4_m4(r_bpt->rotscale_mat, offs_bone);
2233 /* Translation. */
2234 if (bone_flag & BONE_NO_LOCAL_LOCATION) {
2235 /* Translation of arm_mat, without the rotation. */
2236 unit_m4(r_bpt->loc_mat);
2237 copy_v3_v3(r_bpt->loc_mat[3], offs_bone[3]);
2238 }
2239 else {
2240 copy_m4_m4(r_bpt->loc_mat, r_bpt->rotscale_mat);
2241 }
2242 }
2243}
2244
2246{
2247 unit_m4(bpt->rotscale_mat);
2248 unit_m4(bpt->loc_mat);
2249 copy_v3_fl(bpt->post_scale, 1.0f);
2250}
2251
2258
2260 const BoneParentTransform *in2,
2262{
2263 mul_m4_m4m4(result->rotscale_mat, in1->rotscale_mat, in2->rotscale_mat);
2264 mul_m4_m4m4(result->loc_mat, in1->loc_mat, in2->loc_mat);
2265 mul_v3_v3v3(result->post_scale, in1->post_scale, in2->post_scale);
2266}
2267
2269 const float inmat[4][4],
2270 float outmat[4][4])
2271{
2272 /* in case inmat == outmat */
2273 float tmploc[3];
2274 copy_v3_v3(tmploc, inmat[3]);
2275
2276 mul_m4_m4m4(outmat, bpt->rotscale_mat, inmat);
2277 mul_v3_m4v3(outmat[3], bpt->loc_mat, tmploc);
2278 rescale_m4(outmat, bpt->post_scale);
2279}
2280
2282 const float inmat[4][4],
2283 float outmat[4][4])
2284{
2286
2289 BKE_bone_parent_transform_apply(&bpt, inmat, outmat);
2290}
2291
2293 const float inmat[4][4],
2294 float outmat[4][4])
2295{
2297
2299 BKE_bone_parent_transform_apply(&bpt, inmat, outmat);
2300}
2301
2303 const float inloc[3],
2304 float outloc[3])
2305{
2306 float xLocMat[4][4];
2307 float nLocMat[4][4];
2308
2309 /* build matrix for location */
2310 unit_m4(xLocMat);
2311 copy_v3_v3(xLocMat[3], inloc);
2312
2313 /* get bone-space cursor matrix and extract location */
2314 BKE_armature_mat_pose_to_bone(pchan, xLocMat, nLocMat);
2315 copy_v3_v3(outloc, nLocMat[3]);
2316}
2317
2319
2320/* -------------------------------------------------------------------- */
2325
2327 Object *ob,
2328 const bPoseChannel *pchan,
2329 const float inmat[4][4],
2330 float outmat[4][4])
2331{
2332 bPoseChannel work_pchan = blender::dna::shallow_copy(*pchan);
2333
2334 /* Recalculate pose matrix with only parent transformations,
2335 * bone location/scale/rotation is ignored, scene and frame are not used. */
2336 BKE_pose_where_is_bone(depsgraph, nullptr, ob, &work_pchan, 0.0f, false);
2337
2338 /* Find the matrix, need to remove the bone transforms first so this is calculated
2339 * as a matrix to set rather than a difference on top of what's already there. */
2340 unit_m4(outmat);
2341 BKE_pchan_apply_mat4(&work_pchan, outmat, false);
2342
2343 BKE_armature_mat_pose_to_bone(&work_pchan, inmat, outmat);
2344}
2345
2346void BKE_pchan_mat3_to_rot(bPoseChannel *pchan, const float mat[3][3], bool use_compat)
2347{
2348 BLI_ASSERT_UNIT_M3(mat);
2349
2350 switch (pchan->rotmode) {
2351 case ROT_MODE_QUAT:
2352 mat3_normalized_to_quat(pchan->quat, mat);
2353 break;
2354 case ROT_MODE_AXISANGLE:
2355 mat3_normalized_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, mat);
2356 break;
2357 default: /* euler */
2358 if (use_compat) {
2359 mat3_normalized_to_compatible_eulO(pchan->eul, pchan->eul, pchan->rotmode, mat);
2360 }
2361 else {
2362 mat3_normalized_to_eulO(pchan->eul, pchan->rotmode, mat);
2363 }
2364 break;
2365 }
2366}
2367
2368void BKE_pchan_rot_to_mat3(const bPoseChannel *pchan, float r_mat[3][3])
2369{
2370 /* rotations may either be quats, eulers (with various rotation orders), or axis-angle */
2371 if (pchan->rotmode > 0) {
2372 /* Euler rotations (will cause gimbal lock,
2373 * but this can be alleviated a bit with rotation orders) */
2374 eulO_to_mat3(r_mat, pchan->eul, pchan->rotmode);
2375 }
2376 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
2377 /* axis-angle - not really that great for 3D-changing orientations */
2378 axis_angle_to_mat3(r_mat, pchan->rotAxis, pchan->rotAngle);
2379 }
2380 else {
2381 /* quats are normalized before use to eliminate scaling issues */
2382 float quat[4];
2383
2384 /* NOTE: we now don't normalize the stored values anymore,
2385 * since this was kind of evil in some cases but if this proves to be too problematic,
2386 * switch back to the old system of operating directly on the stored copy. */
2387 normalize_qt_qt(quat, pchan->quat);
2388 quat_to_mat3(r_mat, quat);
2389 }
2390}
2391
2392void BKE_pchan_apply_mat4(bPoseChannel *pchan, const float mat[4][4], bool use_compat)
2393{
2394 float rot[3][3];
2395 mat4_to_loc_rot_size(pchan->loc, rot, pchan->scale, mat);
2396 BKE_pchan_mat3_to_rot(pchan, rot, use_compat);
2397}
2398
2399void BKE_armature_mat_pose_to_delta(float delta_mat[4][4],
2400 float pose_mat[4][4],
2401 float arm_mat[4][4])
2402{
2403 float imat[4][4];
2404
2405 invert_m4_m4(imat, arm_mat);
2406 mul_m4_m4m4(delta_mat, imat, pose_mat);
2407}
2408
2410
2411/* -------------------------------------------------------------------- */
2416
2418 float quat[4], float eul[3], float axis[3], float *angle, short oldMode, short newMode)
2419{
2420 /* check if any change - if so, need to convert data */
2421 if (newMode > 0) { /* to euler */
2422 if (oldMode == ROT_MODE_AXISANGLE) {
2423 /* axis-angle to euler */
2424 axis_angle_to_eulO(eul, newMode, axis, *angle);
2425 }
2426 else if (oldMode == ROT_MODE_QUAT) {
2427 /* quat to euler */
2428 normalize_qt(quat);
2429 quat_to_eulO(eul, newMode, quat);
2430 }
2431 /* else { no conversion needed } */
2432 }
2433 else if (newMode == ROT_MODE_QUAT) { /* to quat */
2434 if (oldMode == ROT_MODE_AXISANGLE) {
2435 /* axis angle to quat */
2436 axis_angle_to_quat(quat, axis, *angle);
2437 }
2438 else if (oldMode > 0) {
2439 /* euler to quat */
2440 eulO_to_quat(quat, eul, oldMode);
2441 }
2442 /* else { no conversion needed } */
2443 }
2444 else if (newMode == ROT_MODE_AXISANGLE) { /* to axis-angle */
2445 if (oldMode > 0) {
2446 /* euler to axis angle */
2447 eulO_to_axis_angle(axis, angle, eul, oldMode);
2448 }
2449 else if (oldMode == ROT_MODE_QUAT) {
2450 /* quat to axis angle */
2451 normalize_qt(quat);
2452 quat_to_axis_angle(axis, angle, quat);
2453 }
2454
2455 /* When converting to axis-angle,
2456 * we need a special exception for the case when there is no axis. */
2457 if (IS_EQF(axis[0], axis[1]) && IS_EQF(axis[1], axis[2])) {
2458 /* for now, rotate around y-axis then (so that it simply becomes the roll) */
2459 axis[1] = 1.0f;
2460 }
2461 }
2462}
2463
2465
2466/* -------------------------------------------------------------------- */
2469
2470void BKE_pchan_protected_location_set(bPoseChannel *pchan, const float location[3])
2471{
2472 if ((pchan->protectflag & OB_LOCK_LOCX) == 0) {
2473 pchan->loc[0] = location[0];
2474 }
2475 if ((pchan->protectflag & OB_LOCK_LOCY) == 0) {
2476 pchan->loc[1] = location[1];
2477 }
2478 if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) {
2479 pchan->loc[2] = location[2];
2480 }
2481}
2482
2483void BKE_pchan_protected_scale_set(bPoseChannel *pchan, const float scale[3])
2484{
2485 if ((pchan->protectflag & OB_LOCK_SCALEX) == 0) {
2486 pchan->scale[0] = scale[0];
2487 }
2488 if ((pchan->protectflag & OB_LOCK_SCALEY) == 0) {
2489 pchan->scale[1] = scale[1];
2490 }
2491 if ((pchan->protectflag & OB_LOCK_SCALEZ) == 0) {
2492 pchan->scale[2] = scale[2];
2493 }
2494}
2495
2497{
2498 if ((pchan->protectflag & OB_LOCK_ROTX) == 0) {
2499 pchan->quat[0] = quat[0];
2500 }
2501 if ((pchan->protectflag & OB_LOCK_ROTY) == 0) {
2502 pchan->quat[1] = quat[1];
2503 }
2504 if ((pchan->protectflag & OB_LOCK_ROTZ) == 0) {
2505 pchan->quat[2] = quat[2];
2506 }
2507 if ((pchan->protectflag & OB_LOCK_ROTW) == 0) {
2508 pchan->quat[3] = quat[3];
2509 }
2510}
2511
2513{
2514 if ((pchan->protectflag & OB_LOCK_ROTX) == 0) {
2515 pchan->eul[0] = euler[0];
2516 }
2517 if ((pchan->protectflag & OB_LOCK_ROTY) == 0) {
2518 pchan->eul[1] = euler[1];
2519 }
2520 if ((pchan->protectflag & OB_LOCK_ROTZ) == 0) {
2521 pchan->eul[2] = euler[2];
2522 }
2523}
2524
2526 const float axis[3],
2527 float angle)
2528{
2529 if ((pchan->protectflag & OB_LOCK_ROTX) == 0) {
2530 pchan->rotAxis[0] = axis[0];
2531 }
2532 if ((pchan->protectflag & OB_LOCK_ROTY) == 0) {
2533 pchan->rotAxis[1] = axis[1];
2534 }
2535 if ((pchan->protectflag & OB_LOCK_ROTZ) == 0) {
2536 pchan->rotAxis[2] = axis[2];
2537 }
2538 if ((pchan->protectflag & OB_LOCK_ROTW) == 0) {
2539 pchan->rotAngle = angle;
2540 }
2541}
2542
2544
2545/* -------------------------------------------------------------------- */
2568
2569void mat3_to_vec_roll(const float mat[3][3], float r_vec[3], float *r_roll)
2570{
2571 if (r_vec) {
2572 copy_v3_v3(r_vec, mat[1]);
2573 }
2574
2575 if (r_roll) {
2576 mat3_vec_to_roll(mat, mat[1], r_roll);
2577 }
2578}
2579
2580void mat3_vec_to_roll(const float mat[3][3], const float vec[3], float *r_roll)
2581{
2582 float vecmat[3][3], vecmatinv[3][3], rollmat[3][3], q[4];
2583
2584 /* Compute the orientation relative to the vector with zero roll. */
2585 vec_roll_to_mat3(vec, 0.0f, vecmat);
2586 invert_m3_m3(vecmatinv, vecmat);
2587 mul_m3_m3m3(rollmat, vecmatinv, mat);
2588
2589 /* Extract the twist angle as the roll value. */
2590 mat3_to_quat(q, rollmat);
2591
2592 *r_roll = quat_split_swing_and_twist(q, 1, nullptr, nullptr);
2593}
2594
2595void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float r_mat[3][3])
2596{
2669
2670 const float SAFE_THRESHOLD = 6.1e-3f; /* Theta above this value has good enough precision. */
2671 const float CRITICAL_THRESHOLD = 2.5e-4f; /* True singularity if XZ distance is below this. */
2672 const float THRESHOLD_SQUARED = CRITICAL_THRESHOLD * CRITICAL_THRESHOLD;
2673
2674 const float x = nor[0];
2675 const float y = nor[1];
2676 const float z = nor[2];
2677
2678 float theta = 1.0f + y; /* Remapping Y from [-1,+1] to [0,2]. */
2679 const float theta_alt = x * x + z * z; /* Squared distance from origin in x,z plane. */
2680 float rMatrix[3][3], bMatrix[3][3];
2681
2683
2684 /* Determine if the input is far enough from the true singularity of this type of
2685 * transformation at (0,-1,0), where roll becomes 0/0 undefined without a limit.
2686 *
2687 * When theta is close to zero (nor is aligned close to negative Y Axis),
2688 * we have to check we do have non-null X/Z components as well.
2689 * Also, due to float precision errors, nor can be (0.0, -0.99999994, 0.0) which results
2690 * in theta being close to zero. This will cause problems when theta is used as divisor.
2691 */
2692 if (theta > SAFE_THRESHOLD || theta_alt > THRESHOLD_SQUARED) {
2693 /* nor is *not* aligned to negative Y-axis (0,-1,0). */
2694
2695 bMatrix[0][1] = -x;
2696 bMatrix[1][0] = x;
2697 bMatrix[1][1] = y;
2698 bMatrix[1][2] = z;
2699 bMatrix[2][1] = -z;
2700
2701 if (theta <= SAFE_THRESHOLD) {
2702 /* When nor is close to negative Y axis (0,-1,0) the theta precision is very bad,
2703 * so recompute it from x and z instead, using the series expansion for `sqrt`. */
2704 theta = theta_alt * 0.5f + theta_alt * theta_alt * 0.125f;
2705 }
2706
2707 bMatrix[0][0] = 1 - x * x / theta;
2708 bMatrix[2][2] = 1 - z * z / theta;
2709 bMatrix[2][0] = bMatrix[0][2] = -x * z / theta;
2710 }
2711 else {
2712 /* nor is very close to negative Y axis (0,-1,0): use simple symmetry by Z axis. */
2713 unit_m3(bMatrix);
2714 bMatrix[0][0] = bMatrix[1][1] = -1.0;
2715 }
2716
2717 /* Make Roll matrix */
2718 axis_angle_normalized_to_mat3(rMatrix, nor, roll);
2719
2720 /* Combine and output result */
2721 mul_m3_m3m3(r_mat, rMatrix, bMatrix);
2722}
2723
2724void vec_roll_to_mat3(const float vec[3], const float roll, float r_mat[3][3])
2725{
2726 float nor[3];
2727
2728 normalize_v3_v3(nor, vec);
2729 vec_roll_to_mat3_normalized(nor, roll, r_mat);
2730}
2731
2733
2734/* -------------------------------------------------------------------- */
2737
2738void BKE_armature_where_is_bone(Bone *bone, const Bone *bone_parent, const bool use_recursion)
2739{
2740 float vec[3];
2741
2742 /* Bone Space */
2743 sub_v3_v3v3(vec, bone->tail, bone->head);
2744 bone->length = len_v3(vec);
2745 vec_roll_to_mat3(vec, bone->roll, bone->bone_mat);
2746
2747 /* this is called on old file reading too... */
2748 if (bone->xwidth == 0.0f) {
2749 bone->xwidth = 0.1f;
2750 bone->zwidth = 0.1f;
2751 bone->segments = 1;
2752 }
2753
2754 if (bone_parent) {
2755 float offs_bone[4][4];
2756 /* yoffs(b-1) + root(b) + bonemat(b) */
2757 BKE_bone_offset_matrix_get(bone, offs_bone);
2758
2759 /* Compose the matrix for this bone. */
2760 mul_m4_m4m4(bone->arm_mat, bone_parent->arm_mat, offs_bone);
2761 }
2762 else {
2763 copy_m4_m3(bone->arm_mat, bone->bone_mat);
2764 copy_v3_v3(bone->arm_mat[3], bone->head);
2765 }
2766
2767 /* and the kiddies */
2768 if (use_recursion) {
2769 bone_parent = bone;
2770 for (bone = static_cast<Bone *>(bone->childbase.first); bone; bone = bone->next) {
2771 BKE_armature_where_is_bone(bone, bone_parent, use_recursion);
2772 }
2773 }
2774}
2775
2777{
2778 /* hierarchical from root to children */
2779 LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) {
2780 BKE_armature_where_is_bone(bone, nullptr, true);
2781 }
2782}
2783
2785
2786/* -------------------------------------------------------------------- */
2789
2794 bPose *pose, Bone *bone, bPoseChannel *parchan, int counter, Bone **r_last_visited_bone_p)
2795{
2796 bPoseChannel *pchan = BKE_pose_channel_ensure(pose, bone->name); /* verify checks and/or adds */
2797
2798 pchan->bone = bone;
2799 pchan->parent = parchan;
2800
2801 /* Prevent custom bone colors from having alpha zero.
2802 * Part of the fix for issue #115434. */
2803 pchan->color.custom.solid[3] = 255;
2804 pchan->color.custom.select[3] = 255;
2805 pchan->color.custom.active[3] = 255;
2806
2807 /* We ensure the current pchan is immediately after the one we just generated/updated in the
2808 * previous call to `rebuild_pose_bone`.
2809 *
2810 * It may be either the parent, the previous sibling, or the last
2811 * (grand-(grand-(...)))-child (as processed by the recursive, depth-first nature of this
2812 * function) of the previous sibling.
2813 *
2814 * NOTE: In most cases there is nothing to do here, but pose list may get out of order when some
2815 * bones are added, removed or moved in the armature data. */
2816 bPoseChannel *pchan_prev = pchan->prev;
2817 const Bone *last_visited_bone = *r_last_visited_bone_p;
2818 if ((pchan_prev == nullptr && last_visited_bone != nullptr) ||
2819 (pchan_prev != nullptr && pchan_prev->bone != last_visited_bone))
2820 {
2821 pchan_prev = last_visited_bone != nullptr ?
2822 BKE_pose_channel_find_name(pose, last_visited_bone->name) :
2823 nullptr;
2824 BLI_remlink(&pose->chanbase, pchan);
2825 BLI_insertlinkafter(&pose->chanbase, pchan_prev, pchan);
2826 }
2827
2828 *r_last_visited_bone_p = pchan->bone;
2829 counter++;
2830
2831 for (bone = static_cast<Bone *>(bone->childbase.first); bone; bone = bone->next) {
2832 counter = rebuild_pose_bone(pose, bone, pchan, counter, r_last_visited_bone_p);
2833 /* for quick detecting of next bone in chain, only b-bone uses it now */
2834 if (bone->flag & BONE_CONNECTED) {
2835 pchan->child = BKE_pose_channel_find_name(pose, bone->name);
2836 }
2837 }
2838
2839 return counter;
2840}
2841
2843{
2844 LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
2845 pchan->bone = nullptr;
2846 pchan->child = nullptr;
2847 }
2848}
2849
2851{
2852 LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
2853 pchan->bone = BKE_armature_find_bone_name(armature, pchan->name);
2854 }
2855}
2856
2859{
2860 return (bone != nullptr) ? BKE_pose_channel_find_name(pose, bone->name) : nullptr;
2861}
2862
2864{
2865 pchan->bbone_prev = pose_channel_find_bone(pose, pchan->bone->bbone_prev);
2866 pchan->bbone_next = pose_channel_find_bone(pose, pchan->bone->bbone_next);
2867}
2868
2869void BKE_pose_channels_clear_with_null_bone(bPose *pose, const bool do_id_user)
2870{
2872 if (pchan->bone == nullptr) {
2873 BKE_pose_channel_free_ex(pchan, do_id_user);
2875 BLI_freelinkN(&pose->chanbase, pchan);
2876 }
2877 }
2878}
2879
2880void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_user)
2881{
2882 bPose *pose;
2883 int counter = 0;
2884
2885 /* only done here */
2886 if (ob->pose == nullptr) {
2887 /* create new pose */
2888 ob->pose = MEM_callocN<bPose>("new pose");
2889
2890 /* set default settings for animviz */
2892 }
2893 pose = ob->pose;
2894
2895 /* clear */
2897
2898 /* first step, check if all channels are there */
2899 Bone *prev_bone = nullptr;
2900 LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) {
2901 counter = rebuild_pose_bone(pose, bone, nullptr, counter, &prev_bone);
2902 }
2903
2904 /* and a check for garbage */
2906
2908
2909 LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
2910 /* Find the custom B-Bone handles. */
2912 /* Re-validate that we are still using a valid pchan form custom transform. */
2913 /* Note that we could store pointers of freed pchan in a GSet to speed this up, however this is
2914 * supposed to be a rarely used feature, so for now assuming that always building that GSet
2915 * would be less optimal. */
2916 if (pchan->custom_tx != nullptr && BLI_findindex(&pose->chanbase, pchan->custom_tx) == -1) {
2917 pchan->custom_tx = nullptr;
2918 }
2919 }
2920
2921 // printf("rebuild pose %s, %d bones\n", ob->id.name, counter);
2922
2923 BKE_pose_update_constraint_flags(pose); /* for IK detection for example */
2924
2925 pose->flag &= ~POSE_RECALC;
2926 pose->flag |= POSE_WAS_REBUILT;
2927
2928 /* Rebuilding poses forces us to also rebuild the dependency graph,
2929 * since there is one node per pose/bone. */
2930 if (bmain != nullptr) {
2932 }
2933}
2934
2935void BKE_pose_ensure(Main *bmain, Object *ob, bArmature *arm, const bool do_id_user)
2936{
2937 BLI_assert(!ELEM(nullptr, arm, ob));
2938 if (ob->type == OB_ARMATURE && ((ob->pose == nullptr) || (ob->pose->flag & POSE_RECALC))) {
2939 BLI_assert(GS(arm->id.name) == ID_AR);
2940 BKE_pose_rebuild(bmain, ob, arm, do_id_user);
2941 }
2942}
2943
2945
2946/* -------------------------------------------------------------------- */
2949
2950void BKE_pchan_to_mat4(const bPoseChannel *pchan, float r_chanmat[4][4])
2951{
2952 float smat[3][3];
2953 float rmat[3][3];
2954 float tmat[3][3];
2955
2956 /* get scaling matrix */
2957 size_to_mat3(smat, pchan->scale);
2958
2959 /* get rotation matrix */
2960 BKE_pchan_rot_to_mat3(pchan, rmat);
2961
2962 /* calculate matrix of bone (as 3x3 matrix, but then copy the 4x4) */
2963 mul_m3_m3m3(tmat, rmat, smat);
2964 copy_m4_m3(r_chanmat, tmat);
2965
2966 /* prevent action channels breaking chains */
2967 /* need to check for bone here, CONSTRAINT_TYPE_ACTION uses this call */
2968 if ((pchan->bone == nullptr) || !(pchan->bone->flag & BONE_CONNECTED)) {
2969 copy_v3_v3(r_chanmat[3], pchan->loc);
2970 }
2971}
2972
2974{
2975 /* this is just a wrapper around the copy of this function which calculates the matrix
2976 * and stores the result in any given channel
2977 */
2978 BKE_pchan_to_mat4(pchan, pchan->chan_mat);
2979}
2980
2982{
2983 float vec[3];
2984
2985 copy_v3_v3(vec, pchan->pose_mat[1]);
2986 mul_v3_fl(vec, pchan->bone->length);
2987 add_v3_v3v3(pchan->pose_tail, pchan->pose_head, vec);
2988}
2989
2991 Scene *scene,
2992 Object *ob,
2993 bPoseChannel *pchan,
2994 float ctime,
2995 bool do_extra)
2996{
2997 /* This gives a chan_mat with actions (F-Curve) results. */
2998 if (do_extra) {
2999 BKE_pchan_calc_mat(pchan);
3000 }
3001 else {
3002 unit_m4(pchan->chan_mat);
3003 }
3004
3005 /* Construct the posemat based on PoseChannels, that we do before applying constraints. */
3006 /* pose_mat(b) = pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) * chan_mat(b) */
3007 BKE_armature_mat_bone_to_pose(pchan, pchan->chan_mat, pchan->pose_mat);
3008
3009 /* Only root-bones get the cyclic offset (unless user doesn't want that). */
3010 /* XXX That could be a problem for snapping and other "reverse transform" features... */
3011 if (!pchan->parent) {
3012 if ((pchan->bone->flag & BONE_NO_CYCLICOFFSET) == 0) {
3013 add_v3_v3(pchan->pose_mat[3], ob->pose->cyclic_offset);
3014 }
3015 }
3016
3017 if (do_extra) {
3018 /* Do constraints */
3019 if (pchan->constraints.first) {
3020 bConstraintOb *cob;
3021 float vec[3];
3022
3023 /* make a copy of location of PoseChannel for later */
3024 copy_v3_v3(vec, pchan->pose_mat[3]);
3025
3026 /* prepare PoseChannel for Constraint solving
3027 * - makes a copy of matrix, and creates temporary struct to use
3028 */
3030
3031 /* Solve PoseChannel's Constraints */
3032
3033 /* ctime doesn't alter objects. */
3034 BKE_constraints_solve(depsgraph, &pchan->constraints, cob, ctime);
3035
3036 /* cleanup after Constraint Solving
3037 * - applies matrix back to pchan, and frees temporary struct used
3038 */
3040
3041 /* prevent constraints breaking a chain */
3042 if (pchan->bone->flag & BONE_CONNECTED) {
3043 copy_v3_v3(pchan->pose_mat[3], vec);
3044 }
3045 }
3046 }
3047
3048 /* calculate head */
3049 copy_v3_v3(pchan->pose_head, pchan->pose_mat[3]);
3050 /* calculate tail */
3052}
3053
3054void BKE_pose_where_is(Depsgraph *depsgraph, Scene *scene, Object *ob)
3055{
3056 bArmature *arm;
3057 Bone *bone;
3058 float imat[4][4];
3059 float ctime;
3060
3061 if (ob->type != OB_ARMATURE) {
3062 return;
3063 }
3064 arm = static_cast<bArmature *>(ob->data);
3065
3066 if (ELEM(nullptr, arm, scene)) {
3067 return;
3068 }
3069 /* WARNING! passing nullptr bmain here means we won't tag depsgraph's as dirty -
3070 * hopefully this is OK. */
3071 BKE_pose_ensure(nullptr, ob, arm, true);
3072
3073 ctime = BKE_scene_ctime_get(scene); /* not accurate... */
3074
3075 /* In edit-mode or rest-position we read the data from the bones. */
3076 if (arm->edbo || (arm->flag & ARM_RESTPOS)) {
3077 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
3078 bone = pchan->bone;
3079 if (bone) {
3080 copy_m4_m4(pchan->pose_mat, bone->arm_mat);
3081 copy_v3_v3(pchan->pose_head, bone->arm_head);
3082 copy_v3_v3(pchan->pose_tail, bone->arm_tail);
3083 }
3084 }
3085 }
3086 else {
3087 invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
3088
3089 /* 1. clear flags */
3090 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
3091 pchan->flag &= ~(POSE_DONE | POSE_CHAIN | POSE_IKTREE | POSE_IKSPLINE);
3092 }
3093
3094 /* 2a. construct the IK tree (standard IK) */
3095 BIK_init_tree(depsgraph, scene, ob, ctime);
3096
3097 /* 2b. construct the Spline IK trees
3098 * - this is not integrated as an IK plugin, since it should be able
3099 * to function in conjunction with standard IK
3100 */
3101 BKE_pose_splineik_init_tree(scene, ob, ctime);
3102
3103 /* 3. the main loop, channels are already hierarchical sorted from root to children */
3104 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
3105 /* 4a. if we find an IK root, we handle it separated */
3106 if (pchan->flag & POSE_IKTREE) {
3107 BIK_execute_tree(depsgraph, scene, ob, pchan, ctime);
3108 }
3109 /* 4b. if we find a Spline IK root, we handle it separated too */
3110 else if (pchan->flag & POSE_IKSPLINE) {
3111 BKE_splineik_execute_tree(depsgraph, scene, ob, pchan, ctime);
3112 }
3113 /* 5. otherwise just call the normal solver */
3114 else if (!(pchan->flag & POSE_DONE)) {
3115 BKE_pose_where_is_bone(depsgraph, scene, ob, pchan, ctime, true);
3116 }
3117 }
3118 /* 6. release the IK tree */
3119 BIK_release_tree(scene, ob, ctime);
3120 }
3121
3122 /* calculating deform matrices */
3123 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
3124 if (pchan->bone) {
3125 invert_m4_m4(imat, pchan->bone->arm_mat);
3126 mul_m4_m4m4(pchan->chan_mat, pchan->pose_mat, imat);
3127 }
3128 }
3129}
3130
3132
3133/* -------------------------------------------------------------------- */
3136
3137std::optional<blender::Bounds<blender::float3>> BKE_armature_min_max(const Object *ob)
3138{
3139 return BKE_pose_minmax(ob, false);
3140}
3141
3143 const bPoseChannel *pchan,
3144 const bool use_empty_drawtype,
3145 blender::float3 &r_min,
3146 blender::float3 &r_max)
3147{
3148 using namespace blender;
3149 const bArmature *arm = static_cast<const bArmature *>(ob->data);
3150
3151 Object *ob_custom = nullptr;
3152 if (!(arm->flag & ARM_NO_CUSTOM) && pchan->custom) {
3153 /* This should not be possible, protected against in RNA code and
3154 * BKE_pose_blend_read_after_liblink(). Just for safety do another check
3155 * here, as otherwise this code can end in an infinite loop. */
3156 BLI_assert(pchan->custom->type != OB_ARMATURE);
3157
3158 if (pchan->custom->type != OB_ARMATURE) {
3159 ob_custom = pchan->custom;
3160 }
3161 }
3162
3163 const bPoseChannel *pchan_tx = (ob_custom && pchan->custom_tx) ? pchan->custom_tx : pchan;
3164
3165 std::optional<Bounds<float3>> bb_custom;
3166 if (ob_custom) {
3167 float3 min, max;
3168 if (use_empty_drawtype && (ob_custom->type == OB_EMPTY) &&
3170 {
3171 bb_custom.emplace(Bounds<float3>{min, max});
3172 }
3173 else {
3174 bb_custom = BKE_object_boundbox_get(ob_custom);
3175 }
3176 }
3177
3178 if (bb_custom) {
3179 float4x4 mat, smat, rmat, tmp;
3181 rescale_m4(smat.ptr(), pchan->custom_scale_xyz);
3183 copy_m4_m4(tmp.ptr(), pchan_tx->pose_mat);
3184 translate_m4(tmp.ptr(),
3185 pchan->custom_translation[0],
3186 pchan->custom_translation[1],
3187 pchan->custom_translation[2]);
3188 mul_m4_series(mat.ptr(), tmp.ptr(), rmat.ptr(), smat.ptr());
3189 const Bounds tranformed_bounds = bounds::transform_bounds(mat, *bb_custom);
3190 r_min = math::min(tranformed_bounds.min, r_min);
3191 r_max = math::max(tranformed_bounds.max, r_max);
3192 }
3193 else {
3194 minmax_v3v3_v3(r_min, r_max, pchan_tx->pose_head);
3195 minmax_v3v3_v3(r_min, r_max, pchan_tx->pose_tail);
3196 }
3197}
3198
3199std::optional<blender::Bounds<blender::float3>> BKE_pose_minmax(const Object *ob,
3200 const bool use_select)
3201{
3202 if (!ob->pose) {
3203 return std::nullopt;
3204 }
3205
3206 blender::float3 min(std::numeric_limits<float>::max());
3207 blender::float3 max(std::numeric_limits<float>::lowest());
3208
3209 BLI_assert(ob->type == OB_ARMATURE);
3210 const bArmature *arm = static_cast<const bArmature *>(ob->data);
3211
3212 bool found_pchan = false;
3213 LISTBASE_FOREACH (const bPoseChannel *, pchan, &ob->pose->chanbase) {
3214 /* XXX pchan->bone may be nullptr for duplicated bones, see duplicateEditBoneObjects()
3215 * comment (editarmature.c:2592)... Skip in this case too! */
3216 if (!pchan->bone) {
3217 continue;
3218 }
3219 /* Despite `bone_is_selected` also checking for visibility we need to check visibility
3220 * manually due to `use_select` potentially ignoring selection state. */
3221 if (!blender::animrig::bone_is_visible(arm, pchan)) {
3222 continue;
3223 }
3224 if (use_select && !blender::animrig::bone_is_selected(arm, pchan)) {
3225 continue;
3226 }
3227
3228 BKE_pchan_minmax(ob, pchan, false, min, max);
3229 found_pchan = true;
3230 }
3231
3232 if (!found_pchan) {
3233 return std::nullopt;
3234 }
3235
3237}
3238
3240
3241/* -------------------------------------------------------------------- */
3244
3246{
3247 bPoseChannel *rootchan = pchan;
3248 if (!(data->flag & CONSTRAINT_IK_TIP)) {
3249 /* Exclude tip from chain. */
3250 rootchan = rootchan->parent;
3251 }
3252 if (rootchan != nullptr) {
3253 int segcount = 0;
3254 while (rootchan->parent) {
3255 /* Continue up chain, until we reach target number of items. */
3256 segcount++;
3257 if (segcount == data->rootbone) {
3258 break;
3259 }
3260 rootchan = rootchan->parent;
3261 }
3262 }
3263 return rootchan;
3264}
3265
3268{
3269 bPoseChannel *rootchan = pchan;
3270 int segcount = 0;
3271 BLI_assert(rootchan != nullptr);
3272 while (rootchan->parent) {
3273 /* Continue up chain, until we reach target number of items. */
3274 segcount++;
3275 if (segcount == data->chainlen) {
3276 break;
3277 }
3278 rootchan = rootchan->parent;
3279 }
3280 return rootchan;
3281}
3282
3284
3285/* -------------------------------------------------------------------- */
3288
3289blender::Span<const BoneCollection *> bArmature::collections_span() const
3290{
3291 return blender::Span(collection_array, collection_array_num);
3292}
3293
3294blender::Span<BoneCollection *> bArmature::collections_span()
3295{
3296 return blender::Span(collection_array, collection_array_num);
3297}
3298
3299blender::Span<const BoneCollection *> bArmature::collections_roots() const
3300{
3301 return blender::Span(collection_array, collection_root_count);
3302}
3303blender::Span<BoneCollection *> bArmature::collections_roots()
3304{
3305 return blender::Span(collection_array, collection_root_count);
3306}
3307
3308blender::Span<const BoneCollection *> bArmature::collection_children(
3309 const BoneCollection *parent) const
3310{
3311 return blender::Span(&collection_array[parent->child_index], parent->child_count);
3312}
3313
3314blender::Span<BoneCollection *> bArmature::collection_children(BoneCollection *parent)
3315{
3316 return blender::Span(&collection_array[parent->child_index], parent->child_count);
3317}
3318
3319bool BoneCollection::is_visible() const
3320{
3321 return this->flags & BONE_COLLECTION_VISIBLE;
3322}
3323bool BoneCollection::is_visible_ancestors() const
3324{
3326}
3327bool BoneCollection::is_visible_with_ancestors() const
3328{
3329 return this->is_visible() && this->is_visible_ancestors();
3330}
3331bool BoneCollection::is_solo() const
3332{
3333 return this->flags & BONE_COLLECTION_SOLO;
3334}
3335bool BoneCollection::is_expanded() const
3336{
3337 return this->flags & BONE_COLLECTION_EXPANDED;
3338}
3339
Functions to deal with Armatures.
C++ functions to deal with Armature collections (i.e. the successor of bone layers).
void ANIM_armature_runtime_free(bArmature *armature)
void ANIM_armature_runtime_refresh(bArmature *armature)
void ANIM_bonecoll_free(BoneCollection *bcoll, bool do_id_user_count=true)
void ANIM_armature_bonecoll_active_index_set(bArmature *armature, int bone_collection_index)
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_channels_hash_free(bPose *pose) ATTR_NONNULL(1)
void BKE_pose_update_constraint_flags(bPose *pose) ATTR_NONNULL(1)
void BKE_pose_channels_hash_ensure(bPose *pose) ATTR_NONNULL(1)
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
bPoseChannel * BKE_pose_channel_ensure(bPose *pose, const char *name) ATTR_NONNULL(2)
void BKE_pose_channel_free_ex(bPoseChannel *pchan, bool do_id_user) ATTR_NONNULL(1)
void BKE_pose_channel_free_bbone_cache(bPoseChannel_Runtime *runtime) ATTR_NONNULL(1)
void animviz_settings_init(struct bAnimVizSettings *avs)
void BKE_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)
#define MAX_BBONE_SUBDIV
void BKE_constraints_solve(struct Depsgraph *depsgraph, struct ListBase *conlist, struct bConstraintOb *cob, float ctime)
void BKE_constraints_clear_evalob(struct bConstraintOb *cob)
struct bConstraintOb * BKE_constraints_make_evalob(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, void *subdata, short datatype)
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
Definition curve.cc:1669
void IDP_foreach_property(IDProperty *id_property_root, int type_filter, blender::FunctionRef< void(IDProperty *id_property)> callback)
#define IDP_BlendDataRead(reader, prop)
IDProperty * IDP_CopyProperty_ex(const IDProperty *prop, int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:845
void IDP_BlendWrite(BlendWriter *writer, const IDProperty *prop)
Definition idprop.cc:1461
void IDP_FreeProperty_ex(IDProperty *prop, bool do_id_user)
Definition idprop.cc:1245
IDTypeInfo IDType_ID_AR
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition BKE_idtype.hh:47
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1514
@ LIB_ID_CREATE_NO_USER_REFCOUNT
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2631
#define BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data_, func_call_)
General operations, lookup, etc. for blender objects.
bool BKE_object_minmax_empty_drawtype(const Object *ob, float r_min[3], float r_max[3])
std::optional< blender::Bounds< blender::float3 > > BKE_object_boundbox_get(const Object *ob)
float BKE_scene_ctime_get(const Scene *scene)
Definition scene.cc:2370
#define BLI_array_alloca(arr, realsize)
Definition BLI_alloca.h:18
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
GHash * BLI_ghash_str_new_ex(const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:731
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.cc:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:860
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_freelinkN(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:270
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:332
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
bool BLI_remlink_safe(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:154
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
void void void void void void BLI_duplicatelist(ListBase *dst, const ListBase *src) ATTR_NONNULL(1
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
#define BLI_ASSERT_UNIT_M3(m)
MINLINE float interpf(float target, float origin, float t)
#define BLI_ASSERT_UNIT_V3(v)
float cubic_tangent_factor_circle_v3(const float tan_l[3], const float tan_r[3])
float mat4_to_volume_scale(const float mat[4][4])
float mat4_to_scale(const float mat[4][4])
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void mul_mat3_m4_fl(float R[4][4], float f)
void size_to_mat3(float R[3][3], const float size[3])
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 mat4_to_size_fix_shear(float size[3], const float M[4][4])
void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], const float wmat[4][4])
void translate_m4(float mat[4][4], float Tx, float Ty, float Tz)
void normalize_m3(float R[3][3]) ATTR_NONNULL()
void rescale_m4(float mat[4][4], const float scale[3])
void size_to_mat4(float R[4][4], const float size[3])
void mul_m4_v3(const float M[4][4], float r[3])
void orthogonalize_m4_stable(float R[4][4], int axis, bool normalize)
#define mul_m4_series(...)
void scale_m4_fl(float R[4][4], float scale)
void normalize_m4_ex(float R[4][4], float r_scale[3]) ATTR_NONNULL()
void copy_m4_m4(float m1[4][4], const float m2[4][4])
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])
bool invert_m4(float mat[4][4])
void mat4_to_size(float size[3], const float M[4][4])
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
void mul_v3_mat3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool invert_m3(float mat[3][3])
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
void normalize_m4(float R[4][4]) ATTR_NONNULL()
void unit_m4(float m[4][4])
void axis_angle_to_quat(float r[4], const float axis[3], float angle)
void quat_to_mat3(float m[3][3], const float q[4])
void axis_angle_normalized_to_mat3(float R[3][3], const float axis[3], float angle)
void mat3_to_quat(float q[4], const float mat[3][3])
void quat_to_eulO(float e[3], short order, const float q[4])
float normalize_qt(float q[4])
void eulO_to_axis_angle(float axis[3], float *angle, const float eul[3], short order)
void eulO_to_quat(float q[4], const float e[3], short order)
void eulO_to_mat4(float mat[4][4], const float e[3], short order)
float normalize_qt_qt(float r[4], const float q[4])
float quat_split_swing_and_twist(const float q_in[4], int axis, float r_swing[4], float r_twist[4])
void quat_to_axis_angle(float axis[3], float *angle, const float q[4])
void mat4_to_dquat(DualQuat *dq, const float basemat[4][4], const float mat[4][4])
void axis_angle_to_eulO(float eul[3], short order, const float axis[3], float angle)
void eulO_to_mat3(float M[3][3], const float e[3], short order)
void mat3_normalized_to_eulO(float eul[3], short order, const float m[3][3])
void axis_angle_to_mat3(float R[3][3], const float axis[3], float angle)
void mat3_normalized_to_compatible_eulO(float eul[3], const float oldrot[3], short order, const float mat[3][3])
void mat3_normalized_to_quat(float q[4], const float mat[3][3])
void mat3_normalized_to_axis_angle(float axis[3], float *angle, const float mat[3][3])
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void mul_v3_v3(float r[3], const float a[3])
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 copy_v3_fl3(float v[3], float x, float y, float z)
MINLINE void invert_v3_safe(float r[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 add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
MINLINE void mul_v3_v3v3(float r[3], const float v1[3], const float v2[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
size_t size_t size_t BLI_snprintf_utf8(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
size_t size_t size_t bool BLI_str_utf8_truncate_at_size(char *str, const size_t str_size)
#define STRNCPY_UTF8_RLEN(dst, src)
unsigned int uint
#define CLAMP(a, b, c)
#define CLAMP_MAX(a, c)
#define UNLIKELY(x)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define IS_EQF(a, b)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define STREQ(a, b)
#define CLAMP_MIN(a, b)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_write_struct_list(writer, struct_name, list_ptr)
#define BLO_read_struct(reader, struct_name, ptr_p)
#define BLT_I18NCONTEXT_ID_ARMATURE
void DEG_relations_tag_update(Main *bmain)
#define FILTER_ID_ALL
Definition DNA_ID.h:1239
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:694
#define FILTER_ID_AR
Definition DNA_ID.h:1198
@ INDEX_ID_AR
Definition DNA_ID.h:1324
@ ID_AR
@ IDP_TYPE_FILTER_ID
#define PCHAN_CUSTOM_BONE_LENGTH(pchan)
@ ROT_MODE_QUAT
@ ROT_MODE_AXISANGLE
@ ROT_MODE_XYZ
@ POSE_DONE
@ POSE_IKTREE
@ POSE_IKSPLINE
@ POSE_CHAIN
@ POSE_WAS_REBUILT
@ POSE_RECALC
@ BONE_COLLECTION_VISIBLE
@ BONE_COLLECTION_ANCESTORS_VISIBLE
@ BONE_COLLECTION_SOLO
@ BONE_COLLECTION_EXPANDED
@ BONE_COLLECTION_OVERRIDE_LIBRARY_LOCAL
#define MAXBONENAME
@ BBONE_MAPPING_CURVED
@ BBONE_HANDLE_AUTO
@ BBONE_HANDLE_TANGENT
@ BBONE_HANDLE_RELATIVE
@ BONE_DRAW_LOCKED_WEIGHT
@ BONE_NO_CYCLICOFFSET
@ BONE_NO_LOCAL_LOCATION
@ BONE_DRAW_ACTIVE
@ BONE_CONNECTED
@ BONE_HINGE
@ ARM_NO_CUSTOM
@ ARM_RESTPOS
@ BBONE_ADD_PARENT_END_ROLL
@ BBONE_SCALE_EASING
@ BBONE_HANDLE_SCALE_EASE
@ BBONE_HANDLE_SCALE_Y
@ BBONE_HANDLE_SCALE_X
@ BBONE_HANDLE_SCALE_ANY
@ BBONE_HANDLE_SCALE_Z
@ BONE_INHERIT_SCALE_FULL
@ BONE_INHERIT_SCALE_NONE
@ BONE_INHERIT_SCALE_FIX_SHEAR
@ BONE_INHERIT_SCALE_NONE_LEGACY
@ BONE_INHERIT_SCALE_ALIGNED
@ BONE_INHERIT_SCALE_AVERAGE
@ CONSTRAINT_IK_TIP
@ CONSTRAINT_OBTYPE_BONE
#define DNA_struct_default_get(struct_name)
These structs are the foundation for all linked lists in the library system.
Object is a sort of wrapper for general info.
@ OB_EMPTY
@ OB_ARMATURE
@ OB_LOCK_ROTZ
@ OB_LOCK_SCALEZ
@ OB_LOCK_ROTX
@ OB_LOCK_SCALEX
@ OB_LOCK_ROTW
@ OB_LOCK_LOCY
@ OB_LOCK_LOCZ
@ OB_LOCK_ROTY
@ OB_LOCK_SCALEY
@ OB_LOCK_LOCX
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
void BKE_pchan_rot_to_mat3(const bPoseChannel *pchan, float r_mat[3][3])
void BKE_pchan_protected_rotation_axisangle_set(bPoseChannel *pchan, const float axis[3], float angle)
void BKE_armature_bone_hash_make(bArmature *arm)
static GHash * armature_bone_from_name_map(bArmature *arm)
static void copy_bone_transform(Bone *bone_dst, const Bone *bone_src)
void vec_roll_to_mat3(const float vec[3], const float roll, float r_mat[3][3])
static void write_bone_collection(BlendWriter *writer, BoneCollection *bcoll)
static void compute_bbone_segment_boundaries(bPoseChannel *pchan)
bArmature * BKE_armature_from_object(Object *ob)
bPoseChannel * BKE_armature_ik_solver_find_root(bPoseChannel *pchan, bKinematicConstraint *data)
void BKE_bone_parent_transform_clear(BoneParentTransform *bpt)
static void ease_handle_axis(const float deriv1[3], const float deriv2[3], float r_axis[3])
void BKE_pchan_bbone_deform_segment_index(const bPoseChannel *pchan, const float *co, int *r_index, float *r_blend_next)
void BKE_bone_parent_transform_combine(const BoneParentTransform *in1, const BoneParentTransform *in2, BoneParentTransform *result)
void BKE_pose_where_is_bone(Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan, float ctime, bool do_extra)
int BKE_armature_bonelist_count(const ListBase *lb)
void BKE_armature_bonelist_free(ListBase *lb, const bool do_id_user)
void BKE_pose_channels_clear_with_null_bone(bPose *pose, const bool do_id_user)
void BKE_pchan_protected_rotation_euler_set(bPoseChannel *pchan, const float euler[3])
void BKE_pose_ensure(Main *bmain, Object *ob, bArmature *arm, const bool do_id_user)
static void armature_foreach_id_bone_collection(BoneCollection *bcoll, LibraryForeachIDData *data)
static void copy_bone_collection(bArmature *armature_dst, BoneCollection *&bcoll_dst, const BoneCollection *bcoll_src, const int lib_id_flag)
void BKE_armature_mat_pose_to_bone_ex(Depsgraph *depsgraph, Object *ob, const bPoseChannel *pchan, const float inmat[4][4], float outmat[4][4])
void BKE_bone_parent_transform_invert(BoneParentTransform *bpt)
void BKE_armature_where_is_bone(Bone *bone, const Bone *bone_parent, const bool use_recursion)
void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_user)
void mat3_vec_to_roll(const float mat[3][3], const float vec[3], float *r_roll)
static void read_bone_collections(BlendDataReader *reader, bArmature *arm)
static void write_bone(BlendWriter *writer, Bone *bone)
static void direct_link_bone_collection(BlendDataReader *reader, BoneCollection *bcoll)
void BKE_pchan_protected_location_set(bPoseChannel *pchan, const float location[3])
static void armature_transform_recurse(ListBase *bonebase, const float mat[4][4], const bool do_props, const float mat3[3][3], const float scale, const Bone *bone_parent, const float arm_mat_parent_inv[4][4])
void BKE_pchan_calc_mat(bPoseChannel *pchan)
void BKE_pose_where_is_bone_tail(bPoseChannel *pchan)
void BKE_pchan_apply_mat4(bPoseChannel *pchan, const float mat[4][4], bool use_compat)
void BKE_armature_mat_bone_to_pose(const bPoseChannel *pchan, const float inmat[4][4], float outmat[4][4])
void BKE_pchan_minmax(const Object *ob, const bPoseChannel *pchan, const bool use_empty_drawtype, blender::float3 &r_min, blender::float3 &r_max)
static void armature_foreach_id_bone(Bone *bone, LibraryForeachIDData *data)
static void equalize_cubic_bezier(const float control[4][3], int temp_segments, int final_segments, const float *segment_scales, float *r_t_points)
static void allocate_bbone_cache(bPoseChannel *pchan, const int segments, const bool use_boundaries)
float bbone_segment_bsp_signed_distance(const bPoseChannel_BBoneSegmentBoundary &boundary, const float *co)
void BKE_armature_loc_pose_to_bone(const bPoseChannel *pchan, const float inloc[3], float outloc[3])
void BKE_pchan_rebuild_bbone_handles(bPose *pose, bPoseChannel *pchan)
static bPoseChannel * pose_channel_find_bone(bPose *pose, Bone *bone)
void BKE_pose_clear_pointers(bPose *pose)
bool BKE_armature_bone_flag_test_recursive(const Bone *bone, int flag)
void BKE_pchan_to_mat4(const bPoseChannel *pchan, float r_chanmat[4][4])
static void armature_undo_preserve(BlendLibReader *, ID *id_new, ID *id_old)
static void armature_copy_data(Main *, std::optional< Library * >, ID *id_dst, const ID *id_src, const int flag)
static void copy_bonechildren(Bone *bone_dst, const Bone *bone_src, const Bone *bone_src_act, Bone **r_bone_dst_act, const int flag)
void BKE_armature_copy_bone_transforms(bArmature *armature_dst, const bArmature *armature_src)
static void make_bbone_spline_matrix(BBoneSplineParameters *param, const float scalemats[2][4][4], const float pos[3], const float axis[3], float roll, float scalex, float scalez, float result[4][4])
static void armature_blend_write(BlendWriter *writer, ID *id, const void *id_address)
static void armature_foreach_id_editbone(EditBone *edit_bone, LibraryForeachIDData *data)
static int rebuild_pose_bone(bPose *pose, Bone *bone, bPoseChannel *parchan, int counter, Bone **r_last_visited_bone_p)
void BKE_rotMode_change_values(float quat[4], float eul[3], float axis[3], float *angle, short oldMode, short newMode)
static void copy_bonechildren_custom_handles(Bone *bone_dst, bArmature *arm_dst)
void BKE_bone_parent_transform_apply(const BoneParentTransform *bpt, const float inmat[4][4], float outmat[4][4])
void BKE_pchan_bbone_segments_cache_copy(bPoseChannel *pchan, bPoseChannel *pchan_from)
void BKE_armature_mat_pose_to_delta(float delta_mat[4][4], float pose_mat[4][4], float arm_mat[4][4])
void BKE_pose_where_is(Depsgraph *depsgraph, Scene *scene, Object *ob)
void BKE_pchan_bbone_spline_params_get(bPoseChannel *pchan, const bool rest, BBoneSplineParameters *param)
void BKE_bone_parent_transform_calc_from_pchan(const bPoseChannel *pchan, BoneParentTransform *r_bpt)
std::optional< blender::Bounds< blender::float3 > > BKE_pose_minmax(const Object *ob, const bool use_select)
static void armature_free_data(ID *id)
int BKE_pchan_bbone_spline_compute(BBoneSplineParameters *param, const bool for_deform, Mat4 *result_array)
void BKE_pchan_protected_scale_set(bPoseChannel *pchan, const float scale[3])
void BKE_pchan_mat3_to_rot(bPoseChannel *pchan, const float mat[3][3], bool use_compat)
void mat3_to_vec_roll(const float mat[3][3], float r_vec[3], float *r_roll)
static void armature_bone_from_name_insert_recursive(GHash *bone_hash, ListBase *lb)
void BKE_armature_transform(bArmature *arm, const float mat[4][4], const bool do_props)
void BKE_pchan_bbone_segments_cache_compute(bPoseChannel *pchan)
void BKE_armature_editbonelist_free(ListBase *lb, const bool do_id_user)
void BKE_bone_parent_transform_calc_from_matrices(int bone_flag, int inherit_scale_mode, const float offs_bone[4][4], const float parent_arm_mat[4][4], const float parent_pose_mat[4][4], BoneParentTransform *r_bpt)
void BKE_pchan_bbone_handles_get(bPoseChannel *pchan, bPoseChannel **r_prev, bPoseChannel **r_next)
static void armature_foreach_id(ID *id, LibraryForeachIDData *data)
void BKE_armature_mat_pose_to_bone(const bPoseChannel *pchan, const float inmat[4][4], float outmat[4][4])
void BKE_bone_offset_matrix_get(const Bone *bone, float offs_bone[4][4])
static void armature_init_data(ID *id)
std::optional< blender::Bounds< blender::float3 > > BKE_armature_min_max(const Object *ob)
Bone * BKE_armature_find_bone_name(bArmature *arm, const char *name)
static Bone * get_named_bone_bonechildren(ListBase *lb, const char *name)
void BKE_armature_bone_hash_free(bArmature *arm)
void BKE_armature_where_is(bArmature *arm)
static void direct_link_bones(BlendDataReader *reader, Bone *bone)
void BKE_pchan_bbone_deform_clamp_segment_index(const bPoseChannel *pchan, float head_tail, int *r_index, float *r_blend_next)
void BKE_pchan_protected_rotation_quaternion_set(bPoseChannel *pchan, const float quat[4])
void BKE_armature_mat_world_to_pose(Object *ob, const float inmat[4][4], float outmat[4][4])
void BKE_pchan_bbone_spline_setup(bPoseChannel *pchan, const bool rest, const bool for_deform, Mat4 *result_array)
bool bone_autoside_name(char name[MAXBONENAME], int, short axis, float head, float tail)
static void armature_blend_read_data(BlendDataReader *reader, ID *id)
bPoseChannel * BKE_armature_splineik_solver_find_root(bPoseChannel *pchan, bSplineIKConstraint *data)
static void evaluate_cubic_bezier(const float control[4][3], float t, float r_pos[3], float r_tangent[3])
void BKE_pose_remap_bone_pointers(bArmature *armature, bPose *pose)
void BKE_armature_loc_world_to_pose(Object *ob, const float inloc[3], float outloc[3])
static void find_bbone_segment_index_curved(const bPoseChannel *pchan, const float *co, int *r_index, float *r_blend_next)
void BKE_pchan_bbone_handles_compute(const BBoneSplineParameters *param, float h1[3], float *r_roll1, float h2[3], float *r_roll2, bool ease, bool offsets)
void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float r_mat[3][3])
static void find_bbone_segment_index_straight(const bPoseChannel *pchan, const float *co, int *r_index, float *r_blend_next)
bArmature * BKE_armature_add(Main *bmain, const char *name)
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
BPy_StructRNA * depsgraph
ccl_device_inline float arc_length(const float e2, const float gamma)
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
static T sum(const btAlignedObjectArray< T > &items)
nullptr float
#define logf(x)
#define expf(x)
#define powf(x, y)
#define rot(x, k)
#define GS(x)
uint pos
uint nor
float length(VecOp< float, D >) RET
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_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static ulong * next
bool bone_is_visible(const bArmature *armature, const Bone *bone)
void bonecolls_copy_expanded_flag(Span< BoneCollection * > bcolls_dest, Span< const BoneCollection * > bcolls_source)
bool bone_is_selected(const bArmature *armature, const Bone *bone)
Bounds< VecBase< T, 3 > > transform_bounds(const MatBase< T, D, D > &matrix, const Bounds< VecBase< T, 3 > > &bounds)
T min(const T &a, const T &b)
T max(const T &a, const T &b)
MatBase< float, 4, 4 > float4x4
VecBase< float, 3 > float3
const char * name
#define floorf
#define fabsf
#define sqrtf
#define ceilf
#define atan2f
#define min(a, b)
Definition sort.cc:36
struct IDProperty * system_properties
struct IDProperty * prop
struct BoneCollection * next
struct BoneCollection * prev
ThemeWireColor custom
float rotscale_mat[4][4]
float curve_in_z
short bbone_next_flag
short bbone_prev_flag
Bone_Runtime runtime
struct Bone * parent
struct Bone * bbone_prev
float arm_head[3]
char name[64]
float tail[3]
float arm_tail[3]
struct Bone * bbone_next
char inherit_scale_mode
char bbone_prev_type
float curve_in_x
float scale_out[3]
float size[3]
IDProperty * prop
float curve_out_z
char bbone_mapping_mode
float arm_mat[4][4]
float bone_mat[3][3]
float scale_in[3]
float head[3]
char bbone_next_type
struct Bone * next
float curve_out_x
ListBase childbase
IDProperty * system_properties
IDProperty * prop
IDProperty * system_properties
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
void * last
void * first
float mat[4][4]
struct bPose * pose
ObjectRuntimeHandle * runtime
unsigned char select[4]
unsigned char solid[4]
unsigned char active[4]
struct BoneCollection ** collection_array
struct GHash * bonehash
struct EditBone * act_edbone
ListBase collections_legacy
ListBase * edbo
struct bArmature_Runtime runtime
struct Mat4 * bbone_deform_mats
struct bPoseChannel_BBoneSegmentBoundary * bbone_segment_boundaries
struct DualQuat * bbone_dual_quats
struct Mat4 * bbone_pose_mats
struct Mat4 * bbone_rest_mats
float custom_scale_xyz[3]
float custom_rotation_euler[3]
struct Bone * bone
struct bPoseChannel * parent
struct bPoseChannel * custom_tx
float chan_mat[4][4]
struct bPoseChannel * bbone_next
struct Object * custom
struct bPoseChannel * prev
float custom_translation[3]
struct bPoseChannel_Runtime runtime
struct bPoseChannel * bbone_prev
float pose_mat[4][4]
struct bPoseChannel * child
ListBase chanbase
bAnimVizSettings avs
float cyclic_offset[3]
const c_style_mat & ptr() const
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
static int blend(const Tex *tex, const float texvec[3], TexResult *texres)
uint len
#define N_(msgid)
uint8_t flag
Definition wm_window.cc:145