diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 710035a6d..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 @@ -974,7 +996,7 @@ void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref &meshRef, Ref buf = vertexJointAccessor->bufferView->buffer; uint8_t *arrys = new uint8_t[bytesLen]; unsigned int i = 0; - for (unsigned int j = 0; j <= bytesLen; j += bytesPerComp) { + for (unsigned int j = 0; j < bytesLen; j += bytesPerComp) { size_t len_p = offset + j; float f_value = *(float *)&buf->GetPointer()[len_p]; unsigned short c = static_cast(f_value); diff --git a/code/PostProcessing/MakeVerboseFormat.cpp b/code/PostProcessing/MakeVerboseFormat.cpp index 8410cc9d4..71c1cc439 100644 --- a/code/PostProcessing/MakeVerboseFormat.cpp +++ b/code/PostProcessing/MakeVerboseFormat.cpp @@ -161,6 +161,7 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh *pcMesh) { delete[] pcMesh->mBones[i]->mWeights; if (!newWeights[i].empty()) { pcMesh->mBones[i]->mWeights = new aiVertexWeight[newWeights[i].size()]; + pcMesh->mBones[i]->mNumWeights = static_cast(newWeights[i].size()); aiVertexWeight *weightToCopy = &(newWeights[i][0]); memcpy(pcMesh->mBones[i]->mWeights, weightToCopy, sizeof(aiVertexWeight) * newWeights[i].size());