11#include <pxr/usd/usdGeom/primvarsAPI.h>
12#include <pxr/usd/usdSkel/animation.h>
13#include <pxr/usd/usdSkel/bindingAPI.h>
14#include <pxr/usd/usdSkel/blendShape.h>
15#include <pxr/usd/usdSkel/cache.h>
16#include <pxr/usd/usdSkel/skeletonQuery.h>
17#include <pxr/usd/usdSkel/utils.h>
57inline float max_mag_component(
const pxr::GfVec3d &vec)
59 return pxr::GfMax(pxr::GfAbs(vec[0]), pxr::GfAbs(vec[1]), pxr::GfAbs(vec[2]));
63FCurve *create_fcurve(
const int array_index,
const std::string &rna_path)
76 const int array_index,
77 const std::string &rna_path,
80 FCurve *fcu = create_fcurve(array_index, rna_path);
94 bez.
vec[1][0] = frame;
95 bez.
vec[1][1] = value;
113void import_skeleton_curves(
Main *bmain,
115 const pxr::UsdSkelSkeletonQuery &skel_query,
120 if (!(bmain && arm_obj && skel_query)) {
128 const pxr::UsdSkelAnimQuery &anim_query = skel_query.GetAnimQuery();
135 std::vector<double> samples;
136 anim_query.GetJointTransformTimeSamples(&samples);
138 if (samples.empty()) {
142 const size_t num_samples = samples.size();
150 pxr::VtTokenArray joint_order = skel_query.GetJointOrder();
157 for (
const pxr::TfToken &joint : joint_order) {
158 const std::string *name = joint_to_bone_map.
lookup_ptr(joint);
160 if (name ==
nullptr) {
163 loc_curves.
append(
nullptr);
164 loc_curves.
append(
nullptr);
165 loc_curves.
append(
nullptr);
166 rot_curves.
append(
nullptr);
167 rot_curves.
append(
nullptr);
168 rot_curves.
append(
nullptr);
169 rot_curves.
append(
nullptr);
170 scale_curves.
append(
nullptr);
171 scale_curves.
append(
nullptr);
172 scale_curves.
append(
nullptr);
179 std::string rna_path =
"pose.bones[\"" + *name +
"\"].location";
180 loc_curves.
append(create_chan_fcurve(act, grp, 0, rna_path, num_samples));
181 loc_curves.
append(create_chan_fcurve(act, grp, 1, rna_path, num_samples));
182 loc_curves.
append(create_chan_fcurve(act, grp, 2, rna_path, num_samples));
185 rna_path =
"pose.bones[\"" + *name +
"\"].rotation_quaternion";
186 rot_curves.
append(create_chan_fcurve(act, grp, 0, rna_path, num_samples));
187 rot_curves.
append(create_chan_fcurve(act, grp, 1, rna_path, num_samples));
188 rot_curves.
append(create_chan_fcurve(act, grp, 2, rna_path, num_samples));
189 rot_curves.
append(create_chan_fcurve(act, grp, 3, rna_path, num_samples));
192 rna_path =
"pose.bones[\"" + *name +
"\"].scale";
193 scale_curves.
append(create_chan_fcurve(act, grp, 0, rna_path, num_samples));
194 scale_curves.
append(create_chan_fcurve(act, grp, 1, rna_path, num_samples));
195 scale_curves.
append(create_chan_fcurve(act, grp, 2, rna_path, num_samples));
199 if (loc_curves.
size() != joint_order.size() * 3) {
204 if (rot_curves.
size() != joint_order.size() * 4) {
209 if (scale_curves.
size() != joint_order.size() * 3) {
226 pxr::VtMatrix4dArray bind_xforms;
227 if (!skel_query.GetJointWorldBindTransforms(&bind_xforms)) {
230 "%s: Couldn't get world bind transforms for skeleton %s",
232 skel_query.GetSkeleton().GetPrim().GetPath().GetAsString().c_str());
236 if (bind_xforms.size() != joint_order.size()) {
239 "%s: Number of bind transforms doesn't match the number of joints for skeleton %s",
241 skel_query.GetSkeleton().GetPrim().GetPath().GetAsString().c_str());
245 const pxr::UsdSkelTopology &skel_topology = skel_query.GetTopology();
247 pxr::VtMatrix4dArray joint_local_bind_xforms(bind_xforms.size());
248 for (
int i = 0; i < bind_xforms.size(); ++i) {
249 const int parent_id = skel_topology.GetParent(i);
251 if (parent_id >= 0) {
254 joint_local_bind_xforms[i] = bind_xforms[i] * bind_xforms[parent_id].GetInverse();
258 joint_local_bind_xforms[i] = bind_xforms[i];
263 for (
const double frame : samples) {
264 pxr::VtMatrix4dArray joint_local_xforms;
265 if (!skel_query.ComputeJointLocalTransforms(&joint_local_xforms, frame)) {
266 CLOG_WARN(&
LOG,
"Couldn't compute joint local transforms on frame %f", frame);
270 if (joint_local_xforms.size() != joint_order.size()) {
273 "Number of joint local transform entries %zu doesn't match the number of joints %zu",
274 joint_local_xforms.size(),
279 for (
int i = 0; i < joint_local_xforms.size(); ++i) {
280 pxr::GfMatrix4d bone_xform = joint_local_xforms[i] * joint_local_bind_xforms[i].GetInverse();
286 if (!pxr::UsdSkelDecomposeTransform(bone_xform, &t, &qrot, &s)) {
287 CLOG_WARN(&
LOG,
"Error decomposing matrix on frame %f", frame);
291 const float re = qrot.GetReal();
292 const pxr::GfVec3f &im = qrot.GetImaginary();
294 for (
int j = 0; j < 3; ++j) {
295 const int k = 3 * i + j;
296 if (k >= loc_curves.
size()) {
297 CLOG_ERROR(&
LOG,
"Out of bounds translation curve index %d", k);
300 if (
FCurve *fcu = loc_curves[k]) {
301 add_bezt(fcu, frame, t[j]);
305 for (
int j = 0; j < 4; ++j) {
306 const int k = 4 * i + j;
307 if (k >= rot_curves.
size()) {
308 CLOG_ERROR(&
LOG,
"Out of bounds rotation curve index %d", k);
311 if (
FCurve *fcu = rot_curves[k]) {
313 add_bezt(fcu, frame, re);
316 add_bezt(fcu, frame, im[j - 1]);
321 for (
int j = 0; j < 3; ++j) {
322 const int k = 3 * i + j;
323 if (k >= scale_curves.
size()) {
327 if (
FCurve *fcu = scale_curves[k]) {
328 add_bezt(fcu, frame, s[j]);
336 std::for_each(loc_curves.
begin(), loc_curves.
end(), recalc_handles);
337 std::for_each(rot_curves.
begin(), rot_curves.
end(), recalc_handles);
338 std::for_each(scale_curves.
begin(), scale_curves.
end(), recalc_handles);
342void add_skinned_mesh_bindings(
const pxr::UsdSkelSkeleton &skel,
343 const pxr::UsdPrim &mesh_prim,
344 pxr::UsdGeomXformCache &xf_cache)
346 pxr::UsdSkelBindingAPI skel_api = pxr::UsdSkelBindingAPI::Apply(mesh_prim);
350 "Couldn't apply UsdSkelBindingAPI to skinned mesh prim %s",
351 mesh_prim.GetPath().GetAsString().c_str());
356 pxr::SdfPath skel_path = skel.GetPath();
357 skel_api.CreateSkeletonRel().SetTargets(pxr::SdfPathVector({skel_path}));
360 if (pxr::UsdAttribute geom_bind_attr = skel_api.CreateGeomBindTransformAttr()) {
362 pxr::GfMatrix4d mesh_xf = xf_cache.GetLocalToWorldTransform(mesh_prim);
363 pxr::GfMatrix4d skel_xf = xf_cache.GetLocalToWorldTransform(skel.GetPrim());
364 pxr::GfMatrix4d bind_xf = mesh_xf * skel_xf.GetInverse();
365 geom_bind_attr.Set(bind_xf);
369 "Couldn't create geom bind transform attribute for skinned mesh %s",
370 mesh_prim.GetPath().GetAsString().c_str());
380 const pxr::UsdPrim &prim,
382 const bool import_anim)
384 if (!(mesh_obj && mesh_obj->
data && mesh_obj->
type ==
OB_MESH && prim)) {
388 if (prim.IsInstanceProxy()) {
394 pxr::UsdSkelBindingAPI skel_api(prim);
399 if (!skel_api.GetBlendShapeTargetsRel().HasAuthoredTargets()) {
404 pxr::SdfPathVector targets;
405 if (!skel_api.GetBlendShapeTargetsRel().GetTargets(&targets)) {
408 "%s: Couldn't get blendshape targets for prim %s",
410 prim.GetPath().GetAsString().c_str());
414 if (targets.empty()) {
418 if (!skel_api.GetBlendShapesAttr().HasAuthoredValue()) {
423 pxr::VtTokenArray blendshapes;
424 if (!skel_api.GetBlendShapesAttr().Get(&blendshapes)) {
428 if (blendshapes.empty()) {
433 if (targets.size() != blendshapes.size()) {
436 "%s: Number of blendshapes doesn't match number of blendshape targets for prim %s",
438 prim.GetPath().GetAsString().c_str());
442 pxr::UsdStageRefPtr
stage = prim.GetStage();
447 "%s: Couldn't get stage for prim %s",
449 prim.GetPath().GetAsString().c_str());
469 for (
int i = 0; i < targets.size(); ++i) {
471 const pxr::SdfPath &path = targets[i];
472 pxr::UsdSkelBlendShape blendshape(
stage->GetPrimAtPath(path));
479 if (!blendshape.GetOffsetsAttr().HasAuthoredValue()) {
484 pxr::VtVec3fArray offsets;
485 if (!blendshape.GetOffsetsAttr().Get(&offsets)) {
488 "%s: Couldn't get offsets for blend shape %s",
490 path.GetAsString().c_str());
494 if (offsets.empty()) {
497 "%s: No offsets for blend shape %s",
499 path.GetAsString().c_str());
503 shapekey_names.
add(blendshapes[i]);
511 pxr::VtArray<int> point_indices;
512 if (blendshape.GetPointIndicesAttr().HasAuthoredValue()) {
513 blendshape.GetPointIndicesAttr().Get(&point_indices);
516 float *fp =
static_cast<float *
>(kb->
data);
518 if (point_indices.empty()) {
521 for (
int a = 0; a < kb->
totelem; ++a, fp += 3) {
522 if (a >= offsets.size()) {
526 "%s: Number of offsets greater than number of mesh vertices for blend shape %s",
528 path.GetAsString().c_str());
538 for (
const int point : point_indices) {
541 "Out of bounds point index %d for blendshape %s",
543 path.GetAsString().c_str());
547 if (a >= offsets.size()) {
551 "%s: Number of offsets greater than number of mesh vertices for blend shape %s",
553 path.GetAsString().c_str());
569 pxr::UsdSkelSkeleton skel_prim = skel_api.GetInheritedSkeleton();
575 skel_api = pxr::UsdSkelBindingAPI(skel_prim.GetPrim());
577 pxr::UsdPrim anim_prim = skel_api.GetInheritedAnimationSource();
582 skel_api.GetAnimationSource(&anim_prim);
589 pxr::UsdSkelAnimation skel_anim(anim_prim);
596 if (!skel_anim.GetBlendShapesAttr().HasAuthoredValue()) {
600 pxr::UsdAttribute weights_attr = skel_anim.GetBlendShapeWeightsAttr();
602 if (!(weights_attr && weights_attr.HasAuthoredValue())) {
607 std::vector<double> times;
608 if (!weights_attr.GetTimeSamples(×)) {
617 if (!skel_anim.GetBlendShapesAttr().Get(&blendshapes)) {
621 if (blendshapes.empty()) {
625 const size_t num_samples = times.size();
631 for (
auto blendshape_name : blendshapes) {
632 if (!shapekey_names.
contains(blendshape_name)) {
640 std::string rna_path =
"key_blocks[\"" + blendshape_name.GetString() +
"\"].value";
641 FCurve *fcu = create_fcurve(0, rna_path);
648 for (
double frame : times) {
649 pxr::VtFloatArray weights;
650 if (!weights_attr.Get(&weights, frame)) {
651 CLOG_WARN(&
LOG,
"Couldn't get blendshape weights for time %f", frame);
655 if (weights.size() != curves.size()) {
658 "Number of weight samples doesn't match number of shapekey curve entries for frame %f",
663 for (
int wi = 0; wi < weights.size(); ++wi) {
664 if (curves[wi] !=
nullptr) {
665 add_bezt(curves[wi], frame, weights[wi]);
672 std::for_each(curves.begin(), curves.end(), recalc_handles);
677 const pxr::UsdSkelSkeleton &skel,
679 const bool import_anim)
685 pxr::UsdSkelCache skel_cache;
686 pxr::UsdSkelSkeletonQuery skel_query = skel_cache.GetSkelQuery(skel);
688 if (!skel_query.IsValid()) {
691 "%s: Couldn't query skeleton %s",
693 skel.GetPath().GetAsString().c_str());
697 const pxr::UsdSkelTopology &skel_topology = skel_query.GetTopology();
699 pxr::VtTokenArray joint_order = skel_query.GetJointOrder();
701 if (joint_order.size() != skel_topology.size()) {
704 "%s: Topology and joint order size mismatch for skeleton %s",
706 skel.GetPath().GetAsString().c_str());
724 for (
const pxr::TfToken &joint : joint_order) {
725 std::string name = pxr::SdfPath(joint).GetName();
730 "%s: Couldn't add bone for joint %s",
732 joint.GetString().c_str());
733 edit_bones.
append(
nullptr);
736 joint_to_bone_map.
add(joint, bone->
name);
741 const size_t num_joints = skel_topology.GetNumJoints();
742 if (edit_bones.
size() != num_joints) {
745 "%s: Mismatch in bone and joint counts for skeleton %s",
747 skel.GetPath().GetAsString().c_str());
752 pxr::VtMatrix4dArray bind_xforms;
753 if (!skel_query.GetJointWorldBindTransforms(&bind_xforms)) {
756 "%s: Couldn't get world bind transforms for skeleton %s",
758 skel.GetPath().GetAsString().c_str());
762 if (bind_xforms.size() != num_joints) {
765 "%s: Mismatch in bind xforms and joint counts for skeleton %s",
767 skel.GetPath().GetAsString().c_str());
781 bool negative_determinant =
false;
784 for (
size_t i = 0; i < num_joints; ++i) {
791 pxr::GfMatrix4f mat(bind_xforms[i]);
796 pxr::GfVec3f head(0.0f, 0.0f, 0.0f);
797 pxr::GfVec3f tail(0.0f, 1.0f, 0.0f);
804 if (mat.GetDeterminant() < 0.0) {
805 negative_determinant =
true;
809 bool valid_skeleton =
true;
810 if (negative_determinant) {
811 valid_skeleton =
false;
815 "USD Skeleton Import: bone matrices with negative determinants detected in prim %s. "
816 "Such matrices may indicate negative scales, possibly due to mirroring operations, "
817 "and can't currently be converted to Blender's bone representation. "
818 "The skeletal animation won't be imported",
819 skel.GetPath().GetAsString().c_str());
832 for (
size_t i = 0; i < num_joints; ++i) {
833 const int parent_idx = skel_topology.GetParent(i);
834 if (parent_idx < 0) {
837 if (parent_idx >= edit_bones.
size()) {
839 "Out of bounds parent index for bone %s on skeleton %s",
840 pxr::SdfPath(joint_order[i]).GetAsString().c_str(),
841 skel.GetPath().GetAsString().c_str());
845 child_bones[parent_idx].
append(i);
846 if (edit_bones[i] && edit_bones[parent_idx]) {
847 edit_bones[i]->parent = edit_bones[parent_idx];
852 const pxr::UsdGeomPrimvarsAPI pv_api = pxr::UsdGeomPrimvarsAPI(skel.GetPrim());
854 if (pv_lengths.HasValue()) {
855 pxr::VtArray<float> bone_lengths;
856 pv_lengths.ComputeFlattened(&bone_lengths);
858 for (
size_t i = 0; i < num_joints; ++i) {
860 pxr::GfVec3f head(bone->
head);
861 pxr::GfVec3f tail(bone->
tail);
863 tail = head + (tail - head).GetNormalized() * bone_lengths[i];
868 float avg_len_scale = 0;
869 for (
size_t i = 0; i < num_joints; ++i) {
875 if (child_bones[i].is_empty()) {
884 pxr::GfVec3f avg_child_head(0);
885 for (
int j : child_bones[i]) {
890 pxr::GfVec3f child_head(child->
head);
891 avg_child_head += child_head;
894 avg_child_head /= child_bones[i].
size();
896 pxr::GfVec3f parent_head(parent->
head);
897 pxr::GfVec3f parent_tail(parent->
tail);
899 const float new_len = (avg_child_head - parent_head).GetLength();
902 if (new_len > .00001 * max_mag_component(parent_head)) {
903 parent_tail = parent_head + (parent_tail - parent_head).GetNormalized() * new_len;
905 avg_len_scale += new_len;
910 avg_len_scale /= num_joints;
912 for (
size_t i = 0; i < num_joints; ++i) {
913 if (!child_bones[i].is_empty()) {
921 pxr::GfVec3f head(bone->
head);
924 if (avg_len_scale > .00001 * max_mag_component(head)) {
925 pxr::GfVec3f tail(bone->
tail);
926 tail = head + (tail - head).GetNormalized() * avg_len_scale;
936 if (import_anim && valid_skeleton) {
937 import_skeleton_curves(bmain, arm_obj, skel_query, joint_to_bone_map, reports);
943 const pxr::UsdPrim &prim,
946 if (!(bmain && mesh_obj && mesh_obj->
type ==
OB_MESH && prim)) {
950 if (prim.IsInstanceProxy()) {
956 pxr::UsdSkelBindingAPI skel_api(prim);
958 pxr::UsdSkelSkeleton skel = skel_api.GetInheritedSkeleton();
966 pxr::VtArray<pxr::TfToken> joints;
968 if (skel_api.GetJointsAttr().HasAuthoredValue()) {
969 skel_api.GetJointsAttr().Get(&joints);
971 else if (skel.GetJointsAttr().HasAuthoredValue()) {
972 skel.GetJointsAttr().Get(&joints);
975 if (joints.empty()) {
980 pxr::UsdGeomPrimvar joint_indices_primvar = skel_api.GetJointIndicesPrimvar();
981 if (!(joint_indices_primvar && joint_indices_primvar.HasAuthoredValue())) {
986 pxr::UsdGeomPrimvar joint_weights_primvar = skel_api.GetJointWeightsPrimvar();
987 if (!(joint_weights_primvar && joint_weights_primvar.HasAuthoredValue())) {
993 int joint_indices_elem_size = joint_indices_primvar.GetElementSize();
994 int joint_weights_elem_size = joint_weights_primvar.GetElementSize();
997 if (joint_indices_elem_size != joint_weights_elem_size) {
1000 "%s: Joint weights and joint indices element size mismatch for prim %s",
1002 prim.GetPath().GetAsString().c_str());
1007 pxr::VtIntArray joint_indices;
1008 joint_indices_primvar.ComputeFlattened(&joint_indices);
1010 pxr::VtFloatArray joint_weights;
1011 joint_weights_primvar.ComputeFlattened(&joint_weights);
1013 if (joint_indices.empty() || joint_weights.empty()) {
1017 if (joint_indices.size() != joint_weights.size()) {
1020 "%s: Joint weights and joint indices size mismatch for prim %s",
1022 prim.GetPath().GetAsString().c_str());
1028 const pxr::TfToken
interp = joint_weights_primvar.GetInterpolation();
1031 if (!
ELEM(
interp, pxr::UsdGeomTokens->vertex, pxr::UsdGeomTokens->constant)) {
1034 "%s: Unexpected joint weights interpolation type %s for prim %s",
1036 interp.GetString().c_str(),
1037 prim.GetPath().GetAsString().c_str());
1042 if (
interp == pxr::UsdGeomTokens->vertex &&
1043 joint_weights.size() != mesh->verts_num * joint_weights_elem_size)
1047 "%s: Joint weights of unexpected size for vertex interpolation for prim %s",
1049 prim.GetPath().GetAsString().c_str());
1053 if (
interp == pxr::UsdGeomTokens->constant && joint_weights.size() != joint_weights_elem_size) {
1056 "%s: Joint weights of unexpected size for constant interpolation for prim %s",
1058 prim.GetPath().GetAsString().c_str());
1064 for (
int index : joint_indices) {
1065 if (std::find(used_indices.
begin(), used_indices.
end(), index) == used_indices.
end()) {
1067 if (index < 0 || index >= joints.size()) {
1071 used_indices.
append(index);
1082 "%s: Error creating deform group data for mesh %s",
1098 for (
int idx : used_indices) {
1099 std::string joint_name = pxr::SdfPath(joints[idx]).GetName();
1102 joint_def_grps[idx] = def_grp;
1107 for (
int i = 0; i < mesh->verts_num; ++i) {
1111 if (
interp == pxr::UsdGeomTokens->vertex) {
1112 offset = i * joint_weights_elem_size;
1114 for (
int j = 0; j < joint_weights_elem_size; ++j) {
1115 const int k = offset + j;
1116 const float w = joint_weights[k];
1121 const int joint_idx = joint_indices[k];
1122 if (
bDeformGroup *def_grp = joint_def_grps[joint_idx]) {
1138 pxr::UsdGeomXformCache xf_cache(1.0);
1140 stage, armature_export_map, skinned_mesh_export_map, xf_cache,
depsgraph);
1147 pxr::UsdGeomXformCache &xf_cache,
1151 for (
const auto &item : skinned_mesh_export_map.
items()) {
1152 const Object *mesh_obj = item.key;
1153 const pxr::SdfPath &mesh_path = item.value;
1156 pxr::UsdPrim mesh_prim =
stage->GetPrimAtPath(mesh_path);
1159 "Invalid export map prim path %s for mesh object %s",
1160 mesh_path.GetAsString().c_str(),
1168 CLOG_WARN(&
LOG,
"Invalid armature modifier for skinned mesh %s", mesh_obj->
id.
name + 2);
1172 const pxr::SdfPath *path = armature_export_map.
lookup_ptr(arm_obj);
1174 CLOG_WARN(&
LOG,
"No export map entry for armature object %s", mesh_obj->
id.
name + 2);
1178 pxr::UsdPrim skel_prim =
stage->GetPrimAtPath(*path);
1179 pxr::UsdSkelSkeleton skel(skel_prim);
1181 CLOG_WARN(&
LOG,
"Invalid USD skeleton for armature object %s", arm_obj->
id.
name + 2);
1185 add_skinned_mesh_bindings(skel, mesh_prim, xf_cache);
1199 for (
const auto &item : shape_key_mesh_export_map.
items()) {
1200 const Object *mesh_obj = item.key;
1201 const pxr::SdfPath &mesh_path = item.value;
1204 pxr::UsdPrim mesh_prim =
stage->GetPrimAtPath(mesh_path);
1207 "Invalid export map prim path %s for mesh object %s",
1208 mesh_path.GetAsString().c_str(),
1214 mesh_prims.
append(mesh_prim);
1216 pxr::UsdSkelBindingAPI skel_api = pxr::UsdSkelBindingAPI::Apply(mesh_prim);
1220 "Couldn't apply UsdSkelBindingAPI to prim %s",
1221 mesh_prim.GetPath().GetAsString().c_str());
1225 pxr::UsdSkelSkeleton skel;
1226 if (skel_api.GetSkeleton(&skel)) {
1228 pxr::SdfPathSet *mesh_paths = skel_to_mesh.
lookup_ptr(skel.GetPath());
1230 skel_to_mesh.
add_new(skel.GetPath(), pxr::SdfPathSet());
1231 mesh_paths = skel_to_mesh.
lookup_ptr(skel.GetPath());
1234 mesh_paths->insert(mesh_prim.GetPath());
1247 for (
const auto &item : skel_to_mesh.
items()) {
1252 for (
const pxr::UsdPrim &prim : mesh_prims) {
1258 const pxr::UsdSkelBindingAPI &skel_api,
1274 for (
int i = 0; i < bone_names.
size(); ++i) {
1275 if (bone_names[i] == def->name) {
1281 joint_index.
append(bone_idx);
1290 int max_totweight = 1;
1300 const int element_size = max_totweight;
1301 int num_points = mesh->verts_num;
1303 pxr::VtArray<int> joint_indices(num_points * element_size, 0);
1304 pxr::VtArray<float> joint_weights(num_points * element_size, 0.0f);
1312 for (
int j = 0; j < element_size; ++j, ++offset) {
1314 if (offset >= joint_indices.size()) {
1325 if (def_nr >= joint_index.
size()) {
1330 if (joint_index[def_nr] == -1) {
1334 joint_indices[offset] = joint_index[def_nr];
1335 joint_weights[offset] = vert.
dw[j].
weight;
1339 pxr::UsdSkelNormalizeWeights(joint_weights, element_size);
1341 skel_api.CreateJointIndicesPrimvar(
false, element_size).GetAttr().Set(joint_indices);
1342 skel_api.CreateJointWeightsPrimvar(
false, element_size).GetAttr().Set(joint_weights);
Functions to work with AnimData.
Functions to modify FCurves.
Blender kernel action and pose functionality.
void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve)
bActionGroup * action_groups_add_new(bAction *act, const char name[])
void BKE_fcurve_handles_recalc(FCurve *fcu)
FCurve * BKE_fcurve_create(void)
Key * BKE_key_add(Main *bmain, ID *id)
KeyBlock * BKE_keyblock_add(Key *key, const char *name)
void BKE_keyblock_convert_from_mesh(const Mesh *mesh, const Key *key, KeyBlock *kb)
ModifierData * BKE_modifiers_findby_type(const Object *ob, ModifierType type)
void BKE_modifiers_persistent_uid_init(const Object &object, ModifierData &md)
ModifierData * BKE_modifier_new(int type)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert_unreachable()
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
#define CLOG_ERROR(clg_ref,...)
#define CLOG_WARN(clg_ref,...)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
EditBone * ED_armature_ebone_add(bArmature *arm, const char *name)
void ED_armature_edit_free(bArmature *arm)
void ED_armature_from_edit(Main *bmain, bArmature *arm)
void ED_armature_ebone_from_mat4(EditBone *ebone, const float mat[4][4])
void ED_armature_to_edit(bArmature *arm)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
const Value * lookup_ptr(const Key &key) const
bool add(const Key &key, const Value &value)
void add_new(const Key &key, const Value &value)
ItemIterator items() const
bool contains(const Key &key) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
void append(const T &value)
const Depsgraph * depsgraph
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
ccl_device_inline float2 interp(const float2 a, const float2 b, float t)
bAction * id_action_ensure(Main *bmain, ID *id)
int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag)
Lesser Key-framing API call.
void vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, int assignmode)
void shape_key_export_chaser(pxr::UsdStageRefPtr stage, const ObjExportMap &shape_key_mesh_export_map)
void skel_export_chaser(pxr::UsdStageRefPtr stage, const ObjExportMap &armature_export_map, const ObjExportMap &skinned_mesh_export_map, const ObjExportMap &shape_key_mesh_export_map, const Depsgraph *depsgraph)
void remap_blend_shape_anim(pxr::UsdStageRefPtr stage, const pxr::SdfPath &skel_path, const pxr::SdfPathSet &mesh_paths)
void export_deform_verts(const Mesh *mesh, const pxr::UsdSkelBindingAPI &skel_api, const Span< std::string > bone_names)
const pxr::TfToken BlenderBoneLengths("blender:bone_lengths", pxr::TfToken::Immortal)
void import_blendshapes(Main *bmain, Object *mesh_obj, const pxr::UsdPrim &prim, ReportList *reports, const bool import_anim)
void skinned_mesh_export_chaser(pxr::UsdStageRefPtr stage, const ObjExportMap &armature_export_map, const ObjExportMap &skinned_mesh_export_map, pxr::UsdGeomXformCache &xf_cache, const Depsgraph *depsgraph)
void ensure_blend_shape_skeleton(pxr::UsdStageRefPtr stage, pxr::UsdPrim &mesh_prim)
pxr::TfToken TempBlendShapeWeightsPrimvarName
void import_skeleton(Main *bmain, Object *arm_obj, const pxr::UsdSkelSkeleton &skel, ReportList *reports, const bool import_anim)
const Object * get_armature_modifier_obj(const Object &obj, const Depsgraph *depsgraph)
void import_mesh_skel_bindings(Main *bmain, Object *mesh_obj, const pxr::UsdPrim &prim, ReportList *reports)