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