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
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/* -------------------------------------------------------------------- */
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
85/* -------------------------------------------------------------------- */
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{
231 data, IDP_foreach_property(bone->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
232 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
233 }));
234
235 LISTBASE_FOREACH (Bone *, curbone, &bone->childbase) {
237 }
238}
239
241{
243 data, IDP_foreach_property(edit_bone->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
244 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
245 }));
246}
247
249{
251 data, IDP_foreach_property(bcoll->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
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. */
440 bcoll->flags &= ~BONE_COLLECTION_OVERRIDE_LIBRARY_LOCAL;
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
510/* -------------------------------------------------------------------- */
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
619/* -------------------------------------------------------------------- */
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
654/* -------------------------------------------------------------------- */
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
757/* -------------------------------------------------------------------- */
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
831/* -------------------------------------------------------------------- */
836{
837 if (bone->flag & flag) {
838 return true;
839 }
840 if (bone->parent) {
842 }
843 return false;
844}
845
848/* -------------------------------------------------------------------- */
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
981/* -------------------------------------------------------------------- */
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
1985/* -------------------------------------------------------------------- */
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
2021/* -------------------------------------------------------------------- */
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,
2229 BoneParentTransform *result)
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
2286/* -------------------------------------------------------------------- */
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
2377/* -------------------------------------------------------------------- */
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
2432/* -------------------------------------------------------------------- */
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{
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
2621/* -------------------------------------------------------------------- */
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
2673/* -------------------------------------------------------------------- */
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
2833/* -------------------------------------------------------------------- */
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
3020/* -------------------------------------------------------------------- */
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) &&
3055 BKE_object_minmax_empty_drawtype(ob_custom, min, max))
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
3128/* -------------------------------------------------------------------- */
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
3154 bSplineIKConstraint *data)
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
3172/* -------------------------------------------------------------------- */
3176blender::Span<const BoneCollection *> bArmature::collections_span() const
3177{
3179}
3180
3181blender::Span<BoneCollection *> bArmature::collections_span()
3182{
3184}
3185
3186blender::Span<const BoneCollection *> bArmature::collections_roots() const
3187{
3189}
3190blender::Span<BoneCollection *> bArmature::collections_roots()
3191{
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
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition BKE_idtype.hh:39
@ LIB_ID_CREATE_NO_USER_REFCOUNT
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1482
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
#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
struct bArmature bArmature
@ 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
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
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
IDTypeInfo IDType_ID_AR
Definition armature.cc:477
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
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
static T sum(const btAlignedObjectArray< T > &items)
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
const Depsgraph * depsgraph
#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)
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