Merge pull request #4895 from assimp/kimkulling/make_remove_empty_bones_optional_issue-4840

Update LimitBoneWeightsProcess.cpp
pull/4896/head
Kim Kulling 2023-01-20 19:33:41 +01:00 committed by GitHub
commit 288d49b721
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 38 additions and 50 deletions

View File

@ -2,8 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2022, assimp team Copyright (c) 2006-2023, assimp team
All rights reserved. All rights reserved.
@ -36,13 +35,7 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- */
----------------------------------------------------------------------
*/
/** Implementation of the LimitBoneWeightsProcess post processing step */
#include "LimitBoneWeightsProcess.h" #include "LimitBoneWeightsProcess.h"
#include <assimp/SmallVector.h> #include <assimp/SmallVector.h>
#include <assimp/StringUtils.h> #include <assimp/StringUtils.h>
@ -51,14 +44,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h> #include <assimp/scene.h>
#include <stdio.h> #include <stdio.h>
using namespace Assimp; namespace Assimp {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
LimitBoneWeightsProcess::LimitBoneWeightsProcess() LimitBoneWeightsProcess::LimitBoneWeightsProcess() : mMaxWeights(AI_LMW_MAX_WEIGHTS) {}
{
mMaxWeights = AI_LMW_MAX_WEIGHTS;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
@ -66,15 +56,15 @@ LimitBoneWeightsProcess::~LimitBoneWeightsProcess() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool LimitBoneWeightsProcess::IsActive( unsigned int pFlags) const bool LimitBoneWeightsProcess::IsActive( unsigned int pFlags) const {
{
return (pFlags & aiProcess_LimitBoneWeights) != 0; return (pFlags & aiProcess_LimitBoneWeights) != 0;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void LimitBoneWeightsProcess::Execute( aiScene* pScene) void LimitBoneWeightsProcess::Execute( aiScene* pScene) {
{ ai_assert(pScene != nullptr);
ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess begin"); ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess begin");
for (unsigned int m = 0; m < pScene->mNumMeshes; ++m) { for (unsigned int m = 0; m < pScene->mNumMeshes; ++m) {
@ -86,16 +76,30 @@ void LimitBoneWeightsProcess::Execute( aiScene* pScene)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp) void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp) {
{
// get the current value of the property
this->mMaxWeights = pImp->GetPropertyInteger(AI_CONFIG_PP_LBW_MAX_WEIGHTS,AI_LMW_MAX_WEIGHTS); this->mMaxWeights = pImp->GetPropertyInteger(AI_CONFIG_PP_LBW_MAX_WEIGHTS,AI_LMW_MAX_WEIGHTS);
} }
// ------------------------------------------------------------------------------------------------
static unsigned int removeEmptyBones(aiMesh *pMesh) {
ai_assert(pMesh != nullptr);
unsigned int writeBone = 0;
for (unsigned int readBone = 0; readBone< pMesh->mNumBones; ++readBone) {
aiBone* bone = pMesh->mBones[readBone];
if (bone->mNumWeights > 0) {
pMesh->mBones[writeBone++] = bone;
} else {
delete bone;
}
}
return writeBone;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Unites identical vertices in the given mesh // Unites identical vertices in the given mesh
void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh) void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh) {
{
if (!pMesh->HasBones()) if (!pMesh->HasBones())
return; return;
@ -105,11 +109,9 @@ void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh)
WeightsPerVertex vertexWeights(pMesh->mNumVertices); WeightsPerVertex vertexWeights(pMesh->mNumVertices);
size_t maxVertexWeights = 0; size_t maxVertexWeights = 0;
for (unsigned int b = 0; b < pMesh->mNumBones; ++b) for (unsigned int b = 0; b < pMesh->mNumBones; ++b) {
{
const aiBone* bone = pMesh->mBones[b]; const aiBone* bone = pMesh->mBones[b];
for (unsigned int w = 0; w < bone->mNumWeights; ++w) for (unsigned int w = 0; w < bone->mNumWeights; ++w) {
{
const aiVertexWeight& vw = bone->mWeights[w]; const aiVertexWeight& vw = bone->mWeights[w];
if (vertexWeights.size() <= vw.mVertexId) if (vertexWeights.size() <= vw.mVertexId)
@ -126,8 +128,7 @@ void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh)
unsigned int removed = 0, old_bones = pMesh->mNumBones; unsigned int removed = 0, old_bones = pMesh->mNumBones;
// now cut the weight count if it exceeds the maximum // now cut the weight count if it exceeds the maximum
for (WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit) for (WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit) {
{
if (vit->size() <= mMaxWeights) if (vit->size() <= mMaxWeights)
continue; continue;
@ -154,40 +155,27 @@ void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh)
} }
// clear weight count for all bone // clear weight count for all bone
for (unsigned int a = 0; a < pMesh->mNumBones; ++a) for (unsigned int a = 0; a < pMesh->mNumBones; ++a) {
{
pMesh->mBones[a]->mNumWeights = 0; pMesh->mBones[a]->mNumWeights = 0;
} }
// rebuild the vertex weight array for all bones // rebuild the vertex weight array for all bones
for (unsigned int a = 0; a < vertexWeights.size(); ++a) for (unsigned int a = 0; a < vertexWeights.size(); ++a) {
{
const VertexWeightArray& vw = vertexWeights[a]; const VertexWeightArray& vw = vertexWeights[a];
for (const Weight* it = vw.begin(); it != vw.end(); ++it) for (const Weight* it = vw.begin(); it != vw.end(); ++it) {
{
aiBone* bone = pMesh->mBones[it->mBone]; aiBone* bone = pMesh->mBones[it->mBone];
bone->mWeights[bone->mNumWeights++] = aiVertexWeight(a, it->mWeight); bone->mWeights[bone->mNumWeights++] = aiVertexWeight(a, it->mWeight);
} }
} }
// remove empty bones // remove empty bones
unsigned int writeBone = 0; #ifdef AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES
pMesh->mNumBones = removeEmptyBones(pMesh);
for (unsigned int readBone = 0; readBone< pMesh->mNumBones; ++readBone) #endif // AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES
{
aiBone* bone = pMesh->mBones[readBone];
if (bone->mNumWeights > 0)
{
pMesh->mBones[writeBone++] = bone;
}
else
{
delete bone;
}
}
pMesh->mNumBones = writeBone;
if (!DefaultLogger::isNullLogger()) { if (!DefaultLogger::isNullLogger()) {
ASSIMP_LOG_INFO("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones); ASSIMP_LOG_INFO("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones);
} }
} }
} // namespace Assimp