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