Skip to content

Commit

Permalink
Prevent hard crashes on incorrect assimp files (the mesh named object…
Browse files Browse the repository at this point in the history
… is missing in the nodes hierarchy). Instead look for a likely replacemetn (the first level child of Scene object that has no childrens). Throw content error exception instead of crashing too.
  • Loading branch information
lhog committed Sep 13, 2023
1 parent 3f34c43 commit b0494c9
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 7 deletions.
31 changes: 25 additions & 6 deletions rts/Rendering/Models/AssParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,12 +313,20 @@ void CAssParser::Load(S3DModel& model, const std::string& modelFilePath)
std::vector<SPseudoAssPiece> meshPseudoPieces(meshNames.size());
auto mppIt = meshPseudoPieces.begin();
for (const auto& meshName : meshNames) {
aiNode* meshNode = nullptr;
meshNode = FindNode(scene, scene->mRootNode, meshName);
mppIt->name = meshName;
if (!meshNode) {
LOG_SL(LOG_SECTION_MODEL, L_ERROR, "An assimp model has invalid pieces hierarchy. Missing a mesh named: \"%s\" in model[\"%s\"] path: %s. Looking for a likely candidate", meshName.c_str(), modelName.c_str(), modelPath.c_str());

meshNode = FindFallbackNode(scene);
if (meshNode && meshNode->mParent)
LOG_SL(LOG_SECTION_MODEL, L_WARNING, "Found a likely replacement candidate for mesh \"%s\" - node \"%s\". It might be incorrect!", meshName.c_str(), meshNode->mName.data);
else
throw content_error("An assimp model has invalid pieces hierarchy. Failed to find suitable replacement.");
}

const auto* meshNode = FindNode(scene, scene->mRootNode, meshName);
assert(meshNode && meshNode->mParent);

std::string parentName(meshNode->mParent->mName.C_Str());
std::string const parentName(meshNode->mParent->mName.C_Str());
auto* parentPiece = model.FindPiece(parentName);
assert(parentPiece);
mppIt->parent = parentPiece;
Expand Down Expand Up @@ -726,20 +734,31 @@ const std::vector<std::string> CAssParser::GetMeshNames(const aiScene* scene)
return meshNames;
}

const aiNode* CAssParser::FindNode(const aiScene* scene, const aiNode* node, const std::string& name)
aiNode* CAssParser::FindNode(const aiScene* scene, aiNode* node, const std::string& name)
{
if (std::string(node->mName.C_Str()) == name)
return node;

for (uint32_t ci = 0; ci < node->mNumChildren; ++ci) {
const auto* childTargetNode = FindNode(scene, node->mChildren[ci], name);
auto* childTargetNode = FindNode(scene, node->mChildren[ci], name);
if (childTargetNode)
return childTargetNode;
}

return nullptr;
}

aiNode* CAssParser::FindFallbackNode(const aiScene* scene)
{
for (uint32_t ci = 0; ci < scene->mRootNode->mNumChildren; ++ci) {
if (scene->mRootNode->mChildren[ci]->mNumChildren == 0) {
return scene->mRootNode->mChildren[ci];
}
}

return nullptr;
}

const std::vector<CMatrix44f> CAssParser::GetMeshBoneMatrices(const aiScene* scene, const S3DModel* model, std::vector<SPseudoAssPiece>& meshPPs)
{
std::vector<CMatrix44f> meshBoneMatrices;
Expand Down
3 changes: 2 additions & 1 deletion rts/Rendering/Models/AssParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ class CAssParser: public IModelParser

static const std::vector<std::string> GetBoneNames(const aiScene* scene);
static const std::vector<std::string> GetMeshNames(const aiScene* scene);
static const aiNode* FindNode(const aiScene* scene, const aiNode* node, const std::string& name);
static aiNode* FindNode(const aiScene* scene, aiNode* node, const std::string& name);
static aiNode* FindFallbackNode(const aiScene* scene);
static const std::vector<CMatrix44f> GetMeshBoneMatrices(
const aiScene* scene,
const S3DModel* model,
Expand Down

0 comments on commit b0494c9

Please sign in to comment.