Blender V5.0
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 "ANIM_action.hh"
9#include "ANIM_fcurve.hh"
10
11#include "BKE_armature.hh"
12#include "BKE_fcurve.hh"
13#include "BKE_modifier.hh"
14
15#include "BLI_listbase.h"
16#include "BLI_string_ref.hh"
17#include "BLI_vector.hh"
18
19#include "DEG_depsgraph.hh"
21#include "DNA_action_types.h"
22#include "DNA_armature_types.h"
23
25
26/* Utility: create new fcurve and add it as a channel to a group. */
28 const blender::animrig::FCurveDescriptor &fcurve_descriptor,
29 const int sample_count)
30{
31 FCurve *fcurve = channelbag.fcurve_create_unique(nullptr, fcurve_descriptor);
32 BLI_assert_msg(fcurve, "The same F-Curve is being created twice, this is unexpected.");
33 BKE_fcurve_bezt_resize(fcurve, sample_count);
34 return fcurve;
35}
36
37/* Utility: fill in a single fcurve sample at the provided index. */
38void set_fcurve_sample(FCurve *fcu, int64_t sample_index, const float frame, const float value)
39{
40 BLI_assert(sample_index >= 0 && sample_index < fcu->totvert);
41 BezTriple &bez = fcu->bezt[sample_index];
42 bez.vec[1][0] = frame;
43 bez.vec[1][1] = value;
44 bez.ipo = BEZT_IPO_LIN;
45 bez.f1 = bez.f2 = bez.f3 = SELECT;
46 bez.h1 = bez.h2 = HD_AUTO;
47}
48
49/* Recursively invoke the 'visitor' function on the given bone and its children. */
50static void visit_bones(const Bone *bone, FunctionRef<void(const Bone *)> visitor)
51{
52 if (!(bone && visitor)) {
53 return;
54 }
55
56 visitor(bone);
57
58 LISTBASE_FOREACH (const Bone *, child, &bone->childbase) {
59 visit_bones(child, visitor);
60 }
61}
62
64 ModifierType type,
65 const Depsgraph *depsgraph)
66{
68
69 const Scene *scene = DEG_get_input_scene(depsgraph);
71
72 LISTBASE_FOREACH (ModifierData *, md, &obj.modifiers) {
73
74 if (!BKE_modifier_is_enabled(scene, md, mode)) {
75 continue;
76 }
77
78 if (md->type == type) {
79 return md;
80 }
81 }
82
83 return nullptr;
84}
85
86/* Return the armature modifier on the given object. Return null if no armature modifier
87 * can be found. */
89 const Depsgraph *depsgraph)
90{
91 const ArmatureModifierData *mod = reinterpret_cast<const ArmatureModifierData *>(
93 return mod;
94}
95
96void visit_bones(const Object *ob_arm, FunctionRef<void(const Bone *)> visitor)
97{
98 if (!(ob_arm && ob_arm->type == OB_ARMATURE && ob_arm->data)) {
99 return;
100 }
101
102 const bArmature *armature = (bArmature *)ob_arm->data;
103 LISTBASE_FOREACH (const Bone *, bone, &armature->bonebase) {
104 visit_bones(bone, visitor);
105 }
106}
107
109 const bool use_deform,
110 Vector<StringRef> &r_names)
111{
113 if (use_deform) {
114 init_deform_bones_map(ob_arm, &deform_map);
115 }
116
117 auto visitor = [&](const Bone *bone) {
118 const StringRef bone_name(bone->name);
119 if (use_deform && !deform_map.contains(bone_name)) {
120 return;
121 }
122
123 r_names.append(bone_name);
124 };
125
126 visit_bones(ob_arm, visitor);
127}
128
129pxr::TfToken build_usd_joint_path(const Bone *bone, bool allow_unicode)
130{
131 std::string path(make_safe_name(bone->name, allow_unicode));
132
133 const Bone *parent = bone->parent;
134 while (parent) {
135 path = make_safe_name(parent->name, allow_unicode) + '/' + path;
136 parent = parent->parent;
137 }
138
139 return pxr::TfToken(path);
140}
141
142void create_pose_joints(pxr::UsdSkelAnimation &skel_anim,
143 const Object &obj,
144 const Map<StringRef, const Bone *> *deform_map,
145 bool allow_unicode)
146{
147 BLI_assert(obj.pose);
148
149 pxr::VtTokenArray joints;
150
151 const bPose *pose = obj.pose;
152
153 LISTBASE_FOREACH (const bPoseChannel *, pchan, &pose->chanbase) {
154 if (pchan->bone) {
155 if (deform_map && !deform_map->contains(pchan->bone->name)) {
156 /* If deform_map is passed in, assume we're going deform-only.
157 * Bones not found in the map should be skipped. */
158 continue;
159 }
160
161 joints.push_back(build_usd_joint_path(pchan->bone, allow_unicode));
162 }
163 }
164
165 skel_anim.GetJointsAttr().Set(joints);
166}
167
168const Object *get_armature_modifier_obj(const Object &obj, const Depsgraph *depsgraph)
169{
171 return mod ? mod->object : nullptr;
172}
173
175 const StringRefNull name,
176 const Depsgraph *depsgraph)
177{
179
180 if (!arm_mod || !arm_mod->object || !arm_mod->object->data) {
181 return false;
182 }
183
184 bArmature *arm = static_cast<bArmature *>(arm_mod->object->data);
185
186 return BKE_armature_find_bone_name(arm, name.c_str());
187}
188
189bool can_export_skinned_mesh(const Object &obj, const Depsgraph *depsgraph)
190{
192}
193
195{
196 if (!deform_map) {
197 return;
198 }
199
200 deform_map->clear();
201
202 auto deform_visitor = [&](const Bone *bone) {
203 if (!bone) {
204 return;
205 }
206
207 const bool deform = !(bone->flag & BONE_NO_DEFORM);
208 if (deform) {
209 deform_map->add(bone->name, bone);
210 }
211 };
212
213 visit_bones(obj, deform_visitor);
214
215 /* Get deform parents */
216 for (const auto &item : deform_map->items()) {
217 BLI_assert(item.value);
218 for (const Bone *parent = item.value->parent; parent; parent = parent->parent) {
219 deform_map->add(parent->name, parent);
220 }
221 }
222}
223
224} // namespace blender::io::usd
Functions and classes to work with Actions.
Functions to modify FCurves.
Bone * BKE_armature_find_bone_name(bArmature *arm, const char *name)
void BKE_fcurve_bezt_resize(FCurve *fcu, int new_totvert)
bool BKE_modifier_is_enabled(const Scene *scene, ModifierData *md, int required_mode)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#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
@ HD_AUTO
@ BEZT_IPO_LIN
@ eModifierType_Armature
@ OB_ARMATURE
BPy_StructRNA * depsgraph
long long int int64_t
void clear()
Definition BLI_map.hh:1038
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:295
bool contains(const Key &key) const
Definition BLI_map.hh:353
ItemIterator items() const &
Definition BLI_map.hh:902
void append(const T &value)
FCurve * fcurve_create_unique(Main *bmain, const FCurveDescriptor &fcurve_descriptor)
#define SELECT
VecBase< float, D > constexpr mod(VecOp< float, D >, VecOp< float, D >) RET
void init_deform_bones_map(const Object *obj, Map< StringRef, const Bone * > *deform_map)
void set_fcurve_sample(FCurve *fcu, int64_t sample_index, const float frame, const float value)
void get_armature_bone_names(const Object *ob_arm, const bool use_deform, Vector< StringRef > &r_names)
FCurve * create_fcurve(blender::animrig::Channelbag &channelbag, const blender::animrig::FCurveDescriptor &fcurve_descriptor, const int sample_count)
static const ArmatureModifierData * get_armature_modifier(const Object &obj, const Depsgraph *depsgraph)
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)
std::string make_safe_name(const StringRef name, bool allow_unicode)
Definition usd_utils.cc:18
pxr::TfToken build_usd_joint_path(const Bone *bone, bool allow_unicode)
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)
const char * name
float vec[3][3]
struct Bone * parent
char name[64]
ListBase childbase
BezTriple * bezt
ListBase chanbase