From b9937994ca0b16d9117eeb78eb91a761b4c5de2e Mon Sep 17 00:00:00 2001 From: freizhang Date: Sat, 13 Nov 2021 12:07:29 +0800 Subject: [PATCH] Fix glTF2 skinning bone weight exporting issue --- code/AssetLib/glTF2/glTF2Exporter.cpp | 34 ++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 94d82cbe8..e5c8b4530 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -174,6 +174,22 @@ static void IdentityMatrix4(mat4 &o) { o[15] = 1; } +static bool IsBoneWeightFitted(vec4 &weight) { + return weight[0] + weight[1] + weight[2] + weight[3] >= 1.f; +} + +static int FitBoneWeight(vec4 &weight, float value) { + int i = 0; + for (; i < 4; ++i) { + if (weight[i] < value) { + weight[i] = value; + return i; + } + } + + return -1; +} + template void SetAccessorRange(Ref acc, void *data, size_t count, unsigned int numCompsIn, unsigned int numCompsOut) { @@ -950,15 +966,21 @@ void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref &meshRef, RefmWeights[idx_weights].mVertexId; float vertWeight = aib->mWeights[idx_weights].mWeight; - // A vertex can only have at most four joint weights. Ignore all others. - if (jointsPerVertex[vertexId] > 3) { + // A vertex can only have at most four joint weights, which ideally sum up to 1 + if (IsBoneWeightFitted(vertexWeightData[vertexId])) { continue; } + if (jointsPerVertex[vertexId] > 3) { + int boneIndexFitted = FitBoneWeight(vertexWeightData[vertexId], vertWeight); + if (boneIndexFitted) { + vertexJointData[vertexId][boneIndexFitted] = static_cast(jointNamesIndex); + } + }else { + vertexJointData[vertexId][jointsPerVertex[vertexId]] = static_cast(jointNamesIndex); + vertexWeightData[vertexId][jointsPerVertex[vertexId]] = vertWeight; - vertexJointData[vertexId][jointsPerVertex[vertexId]] = static_cast(jointNamesIndex); - vertexWeightData[vertexId][jointsPerVertex[vertexId]] = vertWeight; - - jointsPerVertex[vertexId] += 1; + jointsPerVertex[vertexId] += 1; + } } } // End: for-loop mNumMeshes