82 if (!
stage || !mesh_prim) {
86 pxr::UsdSkelBindingAPI skel_api = pxr::UsdSkelBindingAPI::Apply(mesh_prim);
90 "Couldn't apply UsdSkelBindingAPI to mesh prim %s",
91 mesh_prim.GetPath().GetAsString().c_str());
95 pxr::UsdSkelSkeleton skel;
96 if (!skel_api.GetSkeleton(&skel)) {
97 pxr::SdfPath skel_path = mesh_prim.GetParent().GetPath().AppendChild(
usdtokens::Skel);
98 skel = pxr::UsdSkelSkeleton::Define(
stage, skel_path);
102 "Couldn't find or create skeleton bound to mesh prim %s",
103 mesh_prim.GetPath().GetAsString().c_str());
107 skel_api.CreateSkeletonRel().AddTarget(skel.GetPath());
110 pxr::VtMatrix4dArray bind_transforms(1, pxr::GfMatrix4d(1.0));
111 pxr::VtMatrix4dArray rest_transforms(1, pxr::GfMatrix4d(1.0));
112 skel.CreateBindTransformsAttr().Set(bind_transforms);
113 skel.GetRestTransformsAttr().Set(rest_transforms);
118 skel.CreateJointsAttr().Set(joints);
121 pxr::UsdAttribute temp_weights_attr = pxr::UsdGeomPrimvarsAPI(mesh_prim).GetPrimvar(
124 if (!temp_weights_attr) {
130 pxr::UsdSkelAnimation anim = pxr::UsdSkelAnimation::Define(
stage, anim_path);
133 CLOG_WARN(&
LOG,
"Couldn't define animation at path %s", anim_path.GetAsString().c_str());
137 pxr::VtTokenArray blendshape_names;
138 skel_api.GetBlendShapesAttr().Get(&blendshape_names);
139 anim.CreateBlendShapesAttr().Set(blendshape_names);
141 std::vector<double> times;
142 temp_weights_attr.GetTimeSamples(×);
144 pxr::UsdAttribute anim_weights_attr = anim.CreateBlendShapeWeightsAttr();
146 pxr::VtFloatArray weights;
147 for (
const double time : times) {
148 if (temp_weights_attr.Get(&weights, time)) {
149 anim_weights_attr.Set(weights, time);
155 skel_api = pxr::UsdSkelBindingAPI::Apply(skel.GetPrim());
159 "Couldn't apply UsdSkelBindingAPI to skeleton prim %s",
160 skel.GetPath().GetAsString().c_str());
164 if (!skel_api.CreateAnimationSourceRel().AddTarget(pxr::SdfPath(
usdtokens::Anim))) {
166 "Couldn't set animation source on skeleton %s",
167 skel.GetPath().GetAsString().c_str());
194 const pxr::UsdPrim &mesh_prim,
199 if (!(key && mesh_prim)) {
203 pxr::UsdSkelBindingAPI skel_api = pxr::UsdSkelBindingAPI::Apply(mesh_prim);
207 "Couldn't apply UsdSkelBindingAPI to mesh prim %s",
208 mesh_prim.GetPath().GetAsString().c_str());
212 pxr::VtTokenArray blendshape_names;
213 std::vector<pxr::SdfPath> blendshape_paths;
222 int basis_totelem = basis_key->
totelem;
229 if (kb == basis_key) {
235 blendshape_names.push_back(name);
237 pxr::SdfPath path = mesh_prim.GetPath().AppendChild(name);
238 blendshape_paths.push_back(path);
240 pxr::UsdSkelBlendShape blendshape = pxr::UsdSkelBlendShape::Define(
stage, path);
242 pxr::UsdAttribute offsets_attr = blendshape.CreateOffsetsAttr();
247 pxr::UsdAttribute point_indices_attr = blendshape.CreatePointIndicesAttr();
249 pxr::VtVec3fArray offsets(kb->totelem);
250 pxr::VtIntArray
indices(kb->totelem);
251 std::iota(indices.begin(), indices.end(), 0);
253 const float(*fp)[3] =
static_cast<float(*)[3]
>(kb->data);
255 const float(*basis_fp)[3] =
static_cast<float(*)[3]
>(basis_key->
data);
257 for (
int i = 0; i < kb->totelem; ++i) {
263 offsets_attr.Set(offsets);
264 point_indices_attr.Set(indices);
268 pxr::UsdAttribute blendshape_attr = skel_api.CreateBlendShapesAttr();
269 blendshape_attr.Set(blendshape_names);
270 skel_api.CreateBlendShapeTargetsRel().SetTargets(blendshape_paths);
275 if (!skel_api.GetJointIndicesAttr().HasAuthoredValue()) {
276 pxr::VtArray<int> joint_indices(basis_totelem, 0);
277 skel_api.CreateJointIndicesPrimvar(
false, 1).GetAttr().Set(joint_indices);
280 if (!skel_api.GetJointWeightsAttr().HasAuthoredValue()) {
281 pxr::VtArray<float> joint_weights(basis_totelem, 1.0f);
282 skel_api.CreateJointWeightsPrimvar(
false, 1).GetAttr().Set(joint_weights);
304 const pxr::SdfPath &skel_path,
305 const pxr::SdfPathSet &mesh_paths)
307 pxr::UsdSkelSkeleton skel = pxr::UsdSkelSkeleton::Get(
stage, skel_path);
310 CLOG_WARN(&
LOG,
"Couldn't get skeleton from path %s", skel_path.GetAsString().c_str());
316 const pxr::UsdSkelAnimation anim = pxr::UsdSkelAnimation::Define(
stage, anim_path);
319 CLOG_WARN(&
LOG,
"Couldn't define animation at path %s", anim_path.GetAsString().c_str());
334 for (
const pxr::SdfPath &mesh_path : mesh_paths) {
336 pxr::UsdPrim mesh_prim =
stage->GetPrimAtPath(mesh_path);
337 pxr::UsdSkelBindingAPI skel_api = pxr::UsdSkelBindingAPI::Apply(mesh_prim);
340 "Couldn't apply UsdSkelBindingAPI to mesh prim %s",
341 mesh_path.GetAsString().c_str());
346 pxr::UsdAttribute blend_shapes_attr = skel_api.GetBlendShapesAttr();
348 if (!blend_shapes_attr) {
352 pxr::VtTokenArray names;
353 if (!skel_api.GetBlendShapesAttr().Get(&names)) {
358 pxr::VtTokenArray unique_names;
360 for (pxr::TfToken &name : names) {
361 std::string unique = add_unique_name(merged_names, name.GetString());
362 unique_names.push_back(pxr::TfToken(unique));
366 skel_api.GetBlendShapesAttr().Set(unique_names);
369 pxr::UsdAttribute temp_weights_attr = pxr::UsdGeomPrimvarsAPI(mesh_prim).GetPrimvar(
372 if (!temp_weights_attr) {
378 merge_info.
append(BlendShapeMergeInfo());
379 merge_info.
last().src_blend_shapes = unique_names;
380 merge_info.
last().src_weights_attr = temp_weights_attr;
389 pxr::VtTokenArray skel_blend_shape_names;
390 for (
const std::string &name : merged_names) {
391 skel_blend_shape_names.push_back(pxr::TfToken(name));
395 for (BlendShapeMergeInfo &info : merge_info) {
396 info.init_anim_map(skel_blend_shape_names);
400 anim.CreateBlendShapesAttr().Set(skel_blend_shape_names);
402 pxr::UsdAttribute dst_weights_attr = anim.CreateBlendShapeWeightsAttr();
405 std::vector<double> times;
406 merge_info.
first().src_weights_attr.GetTimeSamples(×);
411 times.push_back(pxr::UsdTimeCode::Default().GetValue());
414 pxr::VtFloatArray dst_weights;
416 for (
const double time : times) {
417 for (
const BlendShapeMergeInfo &info : merge_info) {
418 pxr::VtFloatArray src_weights;
419 if (info.src_weights_attr.Get(&src_weights, time)) {
420 if (!info.anim_map.Remap(src_weights, &dst_weights)) {
421 CLOG_WARN(&
LOG,
"Failed remapping blend shape weights");
426 dst_weights_attr.Set(dst_weights, time);
static void unique_name(bNode *node)