18#include <pxr/base/gf/matrix4d.h>
19#include <pxr/base/gf/matrix4f.h>
20#include <pxr/usd/usdGeom/primvarsAPI.h>
21#include <pxr/usd/usdSkel/animation.h>
22#include <pxr/usd/usdSkel/bindingAPI.h>
23#include <pxr/usd/usdSkel/skeleton.h>
24#include <pxr/usd/usdSkel/utils.h>
38 const pxr::GfMatrix4f pose_mat(pchan->
pose_mat);
42 const pxr::GfMatrix4f xf = pose_mat * parent_pose_mat.GetInverse();
43 return pxr::GfMatrix4d(xf);
47 return pxr::GfMatrix4d(pose_mat);
53 pxr::UsdSkelSkeleton &skel,
54 pxr::UsdSkelAnimation &skel_anim,
60 pxr::VtTokenArray joints;
61 pxr::VtArray<float> bone_lengths;
62 pxr::VtArray<pxr::GfMatrix4d> bind_xforms;
63 pxr::VtArray<pxr::GfMatrix4d> rest_xforms;
66 auto visitor = [&](
const Bone *bone) {
71 if (deform_bones && !deform_bones->
contains(bone->name)) {
78 bone_lengths.push_back(bone->length);
81 const pxr::GfMatrix4f arm_mat(bone->arm_mat);
82 bind_xforms.push_back(pxr::GfMatrix4d(arm_mat));
89 else if (bone->parent) {
90 pxr::GfMatrix4f parent_arm_mat(bone->parent->arm_mat);
91 const pxr::GfMatrix4f rest_mat = arm_mat * parent_arm_mat.GetInverse();
92 rest_xforms.push_back(pxr::GfMatrix4d(rest_mat));
95 rest_xforms.push_back(pxr::GfMatrix4d(arm_mat));
100 skel.GetJointsAttr().Set(joints);
101 skel.GetBindTransformsAttr().Set(bind_xforms);
102 skel.GetRestTransformsAttr().Set(rest_xforms);
104 const pxr::UsdPrim skel_prim = skel.GetPrim();
107 const pxr::UsdGeomPrimvarsAPI pv_api = pxr::UsdGeomPrimvarsAPI(skel_prim);
108 pxr::UsdGeomPrimvar pv_lengths = pv_api.CreatePrimvar(
110 pv_lengths.Set(bone_lengths);
112 pxr::UsdSkelBindingAPI usd_skel_api = pxr::UsdSkelBindingAPI::Apply(skel_prim);
115 usd_skel_api.CreateAnimationSourceRel().SetTargets(
116 pxr::SdfPathVector({pxr::SdfPath(skel_anim.GetPath().GetName())}));
126 const pxr::UsdTimeCode time,
128 pxr::UsdUtilsSparseValueWriter &value_writer)
130 if (!(skel_anim &&
obj &&
obj->pose)) {
134 pxr::VtArray<pxr::GfMatrix4d> xforms;
142 if (deform_map && !deform_map->
contains(pchan->bone->name)) {
152 pxr::VtArray<pxr::GfVec3f> translations;
153 pxr::VtArray<pxr::GfQuatf> rotations;
154 pxr::VtArray<pxr::GfVec3h> scales;
155 if (pxr::UsdSkelDecomposeTransforms(xforms, &translations, &rotations, &scales)) {
156 set_attribute(skel_anim.GetTranslationsAttr(), translations, time, value_writer);
157 set_attribute(skel_anim.GetRotationsAttr(), rotations, time, value_writer);
158 set_attribute(skel_anim.GetScalesAttr(), scales, time, value_writer);
161 CLOG_WARN(&
LOG,
"Could not decompose skeleton transforms for frame time %f", time.GetValue());
169 if (!(context.object && context.object->type ==
OB_ARMATURE && context.object->data)) {
180 "Couldn't define UsdSkelSkeleton %s",
185 pxr::UsdSkelAnimation skel_anim;
197 skel_anim = pxr::UsdSkelAnimation::Define(stage, anim_path);
200 CLOG_WARN(&
LOG,
"Couldn't define UsdSkelAnimation %s", anim_path.GetString().c_str());
211 initialize(context.object, skel, skel_anim, deform_map, allow_unicode);
228 return obj->adt !=
nullptr;
Functions and classes to work with Actions.
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
#define BLI_assert_unreachable()
#define LISTBASE_FOREACH(type, var, list)
#define CLOG_WARN(clg_ref,...)
bool contains(const Key &key) const
bool frame_has_been_written_
pxr::UsdTimeCode get_export_time_code() const
pxr::UsdUtilsSparseValueWriter usd_value_writer_
USDAbstractWriter(const USDExporterContext &usd_export_context)
const USDExporterContext usd_export_context_
bool check_is_animated(const HierarchyContext &context) const override
USDArmatureWriter(const USDExporterContext &ctx)
void do_write(HierarchyContext &context) override
Action * get_action(ID &animated_id)
void init_deform_bones_map(const Object *obj, Map< StringRef, const Bone * > *deform_map)
static void add_anim_sample(pxr::UsdSkelAnimation &skel_anim, const Object *obj, const pxr::UsdTimeCode time, const blender::Map< blender::StringRef, const Bone * > *deform_map, pxr::UsdUtilsSparseValueWriter &value_writer)
void set_attribute(const pxr::UsdAttribute &attr, const USDT value, pxr::UsdTimeCode timecode, pxr::UsdUtilsSparseValueWriter &value_writer)
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)
const pxr::TfToken BlenderBoneLengths("blender:bone_lengths", pxr::TfToken::Immortal)
pxr::TfToken build_usd_joint_path(const Bone *bone, bool allow_unicode)
static void visit_bones(const Bone *bone, FunctionRef< void(const Bone *)> visitor)
struct bPoseChannel * parent
const USDExportParams & export_params
const pxr::SdfPath usd_path
const pxr::UsdStageRefPtr stage
static void initialize(const Object *obj, pxr::UsdSkelSkeleton &skel, pxr::UsdSkelAnimation &skel_anim, const blender::Map< blender::StringRef, const Bone * > *deform_bones, bool allow_unicode)
static pxr::GfMatrix4d parent_relative_pose_mat(const bPoseChannel *pchan)