Skip to content

Commit bba7814

Browse files
committed
Cap number of bones exported to 192
1 parent eca1e47 commit bba7814

File tree

2 files changed

+44
-22
lines changed

2 files changed

+44
-22
lines changed

ViroFBX/VROFBXExporter.cpp

+32-21
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ FbxScene *VROFBXExporter::loadFBX(std::string fbxPath) {
102102
//
103103
// NOTE: This apparently stopped working after FBX SDK 2015 (tried in versions 2016 and 2018)
104104
// https://forums.autodesk.com/t5/fbx-forum/issue-with-convertpivotanimationrecursive-and-default-transform/td-p/6887073
105+
pinfo("Baking pivots...");
105106
scene->GetRootNode()->ResetPivotSetAndConvertAnimation(kAnimationFPS);
106107

107108
return scene;
@@ -566,14 +567,12 @@ bool SortByBoneWeight(const VROBoneIndexWeight &i, const VROBoneIndexWeight &j)
566567

567568
void VROFBXExporter::exportSkin(FbxNode *node, const viro::Node::Skeleton &skeleton, viro::Node::Geometry::Skin *outSkin) {
568569
FbxMesh *mesh = node->GetMesh();
569-
unsigned int numDeformers = mesh->GetDeformerCount();
570-
571-
// Not understood, typically identity matrix
572-
// FbxAMatrix geometryTransform = Utilities::GetGeometryTransformation(node);
573-
574-
// Each FBX deformer contains clusters. Clusters each contain a link (which is a
575-
// bone). Normally only one deformer per mesh.
576570

571+
/*
572+
Each FBX deformer contains clusters. Clusters each contain a link (which is a
573+
bone). Normally only one deformer per mesh.
574+
*/
575+
unsigned int numDeformers = mesh->GetDeformerCount();
577576
std::map<int, std::vector<VROBoneIndexWeight>> bones;
578577

579578
for (unsigned int deformerIndex = 0; deformerIndex < numDeformers; ++deformerIndex) {
@@ -616,6 +615,16 @@ void VROFBXExporter::exportSkin(FbxNode *node, const viro::Node::Skeleton &skele
616615
*/
617616
std::string boneName = cluster->GetLink()->GetName();
618617
unsigned int boneIndex = findBoneIndexUsingName(boneName, skeleton);
618+
619+
/*
620+
If a model has more bones that we support, we ignore the bones that are beyond
621+
our max bone index. This will likely ruin the animation, so log a warning.
622+
*/
623+
if (boneIndex >= kMaxBones) {
624+
pinfo("Warning: Viro only supports %d bones: bone %d will be discarded, animations may be skewed",
625+
kMaxBones, boneIndex);
626+
continue;
627+
}
619628

620629
/*
621630
Sanity check: the transform matrix for each cluster's parent node should
@@ -652,8 +661,10 @@ void VROFBXExporter::exportSkin(FbxNode *node, const viro::Node::Skeleton &skele
652661
int controlPointIndex = cluster->GetControlPointIndices()[i];
653662
float boneWeight = cluster->GetControlPointWeights()[i];
654663

655-
// Associates a control point (vertex) with a bone, and gives
656-
// the bone a weight on that control point
664+
/*
665+
Associates a control point (vertex) with a bone, and gives
666+
the bone a weight on that control point.
667+
*/
657668
VROBoneIndexWeight bone(boneIndex, boneWeight);
658669
bones[controlPointIndex].push_back(bone);
659670
}
@@ -663,11 +674,11 @@ void VROFBXExporter::exportSkin(FbxNode *node, const viro::Node::Skeleton &skele
663674
for (auto &kv : bones) {
664675
std::vector<VROBoneIndexWeight> &bones = kv.second;
665676

666-
// If there are more than kMaxBones bones, use only those with greatest
677+
// If there are more than kMaxBoneInfluences bones, use only those with greatest
667678
// weight, and renormalize
668-
if (bones.size() > kMaxBones) {
679+
if (bones.size() > kMaxBoneInfluences) {
669680
std::sort(bones.begin(), bones.end(), SortByBoneWeight);
670-
bones.erase(bones.begin() + kMaxBones, bones.end());
681+
bones.erase(bones.begin() + kMaxBoneInfluences, bones.end());
671682

672683
float total = 0;
673684
for (VROBoneIndexWeight &bone : bones) {
@@ -679,8 +690,8 @@ void VROFBXExporter::exportSkin(FbxNode *node, const viro::Node::Skeleton &skele
679690
}
680691

681692
// Add extra dummy bones to each control point that has fewer than
682-
// kMaxBones
683-
for (size_t i = bones.size(); i < kMaxBones; ++i) {
693+
// kMaxBoneInfluences
694+
for (size_t i = bones.size(); i < kMaxBoneInfluences; ++i) {
684695
bones.push_back({0, 0});
685696
}
686697
}
@@ -713,14 +724,14 @@ void VROFBXExporter::exportSkin(FbxNode *node, const viro::Node::Skeleton &skele
713724
pinfo(" No bones found for control point %d", controlPointIndex);
714725
}
715726

716-
for (int b = 0; b < kMaxBones; b++) {
727+
for (int b = 0; b < kMaxBoneInfluences; b++) {
717728
boneIndicesData.push_back(0);
718729
boneWeightsData.push_back(0);
719730
}
720731
}
721732
else {
722733
std::vector<VROBoneIndexWeight> &boneData = it->second;
723-
passert (boneData.size() == kMaxBones);
734+
passert (boneData.size() == kMaxBoneInfluences);
724735

725736
if (kDebugGeometrySource) {
726737
pinfo(" Control point %d", controlPointIndex);
@@ -738,27 +749,27 @@ void VROFBXExporter::exportSkin(FbxNode *node, const viro::Node::Skeleton &skele
738749
}
739750
}
740751

741-
int intsPerVertex = kMaxBones;
752+
int intsPerVertex = kMaxBoneInfluences;
742753
int numVertices = (uint32_t)boneIndicesData.size() / intsPerVertex;
743754

744755
viro::Node::Geometry::Source *boneIndices = outSkin->mutable_bone_indices();
745756
boneIndices->set_semantic(viro::Node_Geometry_Source_Semantic_BoneIndices);
746757
boneIndices->set_vertex_count(numVertices);
747758
boneIndices->set_float_components(false);
748-
boneIndices->set_components_per_vertex(kMaxBones);
759+
boneIndices->set_components_per_vertex(kMaxBoneInfluences);
749760
boneIndices->set_bytes_per_component(sizeof(int));
750761
boneIndices->set_data_offset(0);
751-
boneIndices->set_data_stride(sizeof(int) * kMaxBones);
762+
boneIndices->set_data_stride(sizeof(int) * kMaxBoneInfluences);
752763
boneIndices->set_data(boneIndicesData.data(), boneIndicesData.size() * sizeof(int));
753764

754765
viro::Node::Geometry::Source *boneWeights = outSkin->mutable_bone_weights();
755766
boneWeights->set_semantic(viro::Node_Geometry_Source_Semantic_BoneWeights);
756767
boneWeights->set_vertex_count(numVertices);
757768
boneWeights->set_float_components(true);
758-
boneWeights->set_components_per_vertex(kMaxBones);
769+
boneWeights->set_components_per_vertex(kMaxBoneInfluences);
759770
boneWeights->set_bytes_per_component(sizeof(float));
760771
boneWeights->set_data_offset(0);
761-
boneWeights->set_data_stride(sizeof(float) * kMaxBones);
772+
boneWeights->set_data_stride(sizeof(float) * kMaxBoneInfluences);
762773
boneWeights->set_data(boneWeightsData.data(), boneWeightsData.size() * sizeof(float));
763774
}
764775

ViroFBX/VROFBXExporter.h

+12-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,18 @@
1515
#include <map>
1616
#include "Nodes.pb.h"
1717

18-
static const int kMaxBones = 4;
18+
/*
19+
Maximum number of bones that can influence each vertex.
20+
*/
21+
static const int kMaxBoneInfluences = 4;
22+
23+
/*
24+
Maximum number of bones in a node. Keep in sync with:
25+
26+
ViroRenderer::VROBoneUBO.h and
27+
ViroRenderer::skinning_vsh.glsl
28+
*/
29+
static const int kMaxBones = 192;
1930

2031
class VROBoneIndexWeight {
2132
public:

0 commit comments

Comments
 (0)