Blender V4.3
usd_armature_utils.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6#include "usd_utils.hh"
7
8#include "BKE_armature.hh"
9#include "BKE_modifier.hh"
10#include "BLI_listbase.h"
11#include "BLI_vector.hh"
12#include "DEG_depsgraph.hh"
14#include "DNA_action_types.h"
15#include "DNA_armature_types.h"
16
18
19/* Recursively invoke the 'visitor' function on the given bone and its children. */
20static void visit_bones(const Bone *bone, FunctionRef<void(const Bone *)> visitor)
21{
22 if (!(bone && visitor)) {
23 return;
24 }
25
26 visitor(bone);
27
28 LISTBASE_FOREACH (const Bone *, child, &bone->childbase) {
29 visit_bones(child, visitor);
30 }
31}
32
34 ModifierType type,
35 const Depsgraph *depsgraph)
36{
38
39 const Scene *scene = DEG_get_input_scene(depsgraph);
41
43
44 if (!BKE_modifier_is_enabled(scene, md, mode)) {
45 continue;
46 }
47
48 if (md->type == type) {
49 return md;
50 }
51 }
52
53 return nullptr;
54}
55
56/* Return the armature modifier on the given object. Return null if no armature modifier
57 * can be found. */
59 const Depsgraph *depsgraph)
60{
61 const ArmatureModifierData *mod = reinterpret_cast<const ArmatureModifierData *>(
63 return mod;
64}
65
66void visit_bones(const Object *ob_arm, FunctionRef<void(const Bone *)> visitor)
67{
68 if (!(ob_arm && ob_arm->type == OB_ARMATURE && ob_arm->data)) {
69 return;
70 }
71
72 bArmature *armature = (bArmature *)ob_arm->data;
73
74 LISTBASE_FOREACH (const Bone *, bone, &armature->bonebase) {
75 visit_bones(bone, visitor);
76 }
77}
78
80 const bool use_deform,
81 Vector<std::string> &r_names)
82{
84 if (use_deform) {
85 init_deform_bones_map(ob_arm, &deform_map);
86 }
87
88 auto visitor = [&](const Bone *bone) {
89 if (use_deform && !deform_map.contains(bone->name)) {
90 return;
91 }
92
93 r_names.append(bone->name);
94 };
95
96 visit_bones(ob_arm, visitor);
97}
98
99pxr::TfToken build_usd_joint_path(const Bone *bone, bool allow_unicode)
100{
101 std::string path(make_safe_name(bone->name, allow_unicode));
102
103 const Bone *parent = bone->parent;
104 while (parent) {
105 path = make_safe_name(parent->name, allow_unicode) + std::string("/") + path;
106 parent = parent->parent;
107 }
108
109 return pxr::TfToken(path);
110}
111
112void create_pose_joints(pxr::UsdSkelAnimation &skel_anim,
113 const Object &obj,
114 const Map<StringRef, const Bone *> *deform_map,
115 bool allow_unicode)
116{
117 BLI_assert(obj.pose);
118
119 pxr::VtTokenArray joints;
120
121 const bPose *pose = obj.pose;
122
123 LISTBASE_FOREACH (const bPoseChannel *, pchan, &pose->chanbase) {
124 if (pchan->bone) {
125 if (deform_map && !deform_map->contains(pchan->bone->name)) {
126 /* If deform_map is passed in, assume we're going deform-only.
127 * Bones not found in the map should be skipped. */
128 continue;
129 }
130
131 joints.push_back(build_usd_joint_path(pchan->bone, allow_unicode));
132 }
133 }
134
135 skel_anim.GetJointsAttr().Set(joints);
136}
137
138const Object *get_armature_modifier_obj(const Object &obj, const Depsgraph *depsgraph)
139{
141 return mod ? mod->object : nullptr;
142}
143
145 const StringRefNull name,
146 const Depsgraph *depsgraph)
147{
149
150 if (!arm_mod || !arm_mod->object || !arm_mod->object->data) {
151 return false;
152 }
153
154 bArmature *arm = static_cast<bArmature *>(arm_mod->object->data);
155
156 return BKE_armature_find_bone_name(arm, name.c_str());
157}
158
159bool can_export_skinned_mesh(const Object &obj, const Depsgraph *depsgraph)
160{
162}
163
165{
166 if (!deform_map) {
167 return;
168 }
169
170 deform_map->clear();
171
172 auto deform_visitor = [&](const Bone *bone) {
173 if (!bone) {
174 return;
175 }
176
177 const bool deform = !(bone->flag & BONE_NO_DEFORM);
178 if (deform) {
179 deform_map->add(bone->name, bone);
180 }
181 };
182
183 visit_bones(obj, deform_visitor);
184
185 /* Get deform parents */
186 for (const auto &item : deform_map->items()) {
187 BLI_assert(item.value);
188 for (const Bone *parent = item.value->parent; parent; parent = parent->parent) {
189 deform_map->add(parent->name, parent);
190 }
191 }
192}
193
194} // namespace blender::io::usd
Bone * BKE_armature_find_bone_name(bArmature *arm, const char *name)
Definition armature.cc:779
bool BKE_modifier_is_enabled(const Scene *scene, ModifierData *md, int required_mode)
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
eEvaluationMode
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
Scene * DEG_get_input_scene(const Depsgraph *graph)
@ BONE_NO_DEFORM
@ eModifierType_Armature
@ OB_ARMATURE
void clear()
Definition BLI_map.hh:989
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:271
ItemIterator items() const
Definition BLI_map.hh:864
bool contains(const Key &key) const
Definition BLI_map.hh:329
void append(const T &value)
const Depsgraph * depsgraph
void init_deform_bones_map(const Object *obj, Map< StringRef, const Bone * > *deform_map)
static const ArmatureModifierData * get_armature_modifier(const Object &obj, const Depsgraph *depsgraph)
std::string make_safe_name(const std::string &name, bool allow_unicode)
Definition usd_utils.cc:16
bool is_armature_modifier_bone_name(const Object &obj, const StringRefNull name, const Depsgraph *depsgraph)
void create_pose_joints(pxr::UsdSkelAnimation &skel_anim, const Object &obj, const Map< StringRef, const Bone * > *deform_map, bool allow_unicode)
pxr::TfToken build_usd_joint_path(const Bone *bone, bool allow_unicode)
void get_armature_bone_names(const Object *ob_arm, const bool use_deform, Vector< std::string > &r_names)
const ModifierData * get_enabled_modifier(const Object &obj, ModifierType type, const Depsgraph *depsgraph)
const Object * get_armature_modifier_obj(const Object &obj, const Depsgraph *depsgraph)
static void visit_bones(const Bone *bone, FunctionRef< void(const Bone *)> visitor)
bool can_export_skinned_mesh(const Object &obj, const Depsgraph *depsgraph)
struct Bone * parent
char name[64]
ListBase childbase
struct bPose * pose
ListBase modifiers
ListBase chanbase
ccl_device_inline int mod(int x, int m)
Definition util/math.h:520