Browse Source

Improve model import error handling

Josh Engebretson 10 years ago
parent
commit
4eac481831

+ 1 - 1
Script/TypeScript/ToolCore.d.ts

@@ -227,7 +227,7 @@ declare module ToolCore {
 
       load(assetPath: string): boolean;
       getErrorMessage(): string;
-      exportModel(outName: string, animName?: string, animationOnly?: boolean): void;
+      exportModel(outName: string, animName?: string, animationOnly?: boolean): boolean;
       setImportNode(node: Atomic.Node): void;
       setStartTime(startTime: number): void;
       setEndTime(endTime: number): void;

+ 74 - 21
Source/ToolCore/Import/OpenAssetImporter.cpp

@@ -202,26 +202,34 @@ void OpenAssetImporter::ApplyScale()
 
 }
 
-void OpenAssetImporter::ExportModel(const String& outName, const String &animName, bool animationOnly)
+bool OpenAssetImporter::ExportModel(const String& outName, const String &animName, bool animationOnly)
 {
     if (outName.Empty())
-        ErrorExit("No output file defined");
+    {
+        errorMessage_ = "No output file defined";
+        return false;
+    }
 
     OutModel model;
     model.rootNode_ = rootNode_;
     model.outName_ = outName + ".mdl";
 
     CollectMeshes(scene_, model, model.rootNode_);
-    CollectBones(model, animationOnly);
+    if (!CollectBones(model, animationOnly))
+        return false;
     BuildBoneCollisionInfo(model);
 
     if (!animationOnly)
-        BuildAndSaveModel(model);
+    {
+        if (!BuildAndSaveModel(model))
+            return false;
+    }
 
     if (!noAnimations_)
     {
         CollectAnimations(&model);
-        BuildAndSaveAnimations(&model, animName);
+        if (!BuildAndSaveAnimations(&model, animName))
+            return false;
 
         // Save scene-global animations
         // CollectAnimations();
@@ -235,7 +243,10 @@ void OpenAssetImporter::ExportModel(const String& outName, const String &animNam
     }
 
     if (importNode_.Null())
-        return;
+    {
+        errorMessage_ = "NULL importNode_";
+        return false;
+    }
 
     ResourceCache* cache = GetSubsystem<ResourceCache>();    
     Model* mdl = cache->GetResource<Model>( model.outName_);
@@ -244,7 +255,10 @@ void OpenAssetImporter::ExportModel(const String& outName, const String &animNam
     cache->ReloadResource(mdl);
 
     if (!mdl)
-        return;
+    {
+        errorMessage_ = "Unable to load " + model.outName_ + " from Cache";
+        return false;
+    }
 
     StaticModel* modelComponent = 0;
 
@@ -273,15 +287,24 @@ void OpenAssetImporter::ExportModel(const String& outName, const String &animNam
         }
 
     }
+
+    return true;
 }
 
-void OpenAssetImporter::BuildAndSaveModel(OutModel& model)
+bool OpenAssetImporter::BuildAndSaveModel(OutModel& model)
 {
     if (!model.rootNode_)
-        ErrorExit("Null root node for model");
+    {
+        errorMessage_ = "Null root node for model";
+        return false;
+    }
+
     String rootNodeName = FromAIString(model.rootNode_->mName);
     if (!model.meshes_.Size())
-        ErrorExit("No geometries found starting from node " + rootNodeName);
+    {
+        errorMessage_ = "No geometries found starting from node " + rootNodeName;
+        return false;
+    }
 
     //PrintLine("Writing model " + rootNodeName);
 
@@ -409,7 +432,10 @@ void OpenAssetImporter::BuildAndSaveModel(OutModel& model)
         Vector<PODVector<float> > blendWeights;
         PODVector<unsigned> boneMappings;
         if (model.bones_.Size())
-            GetBlendData(model, mesh, boneMappings, blendIndices, blendWeights, maxBones_);
+        {
+            if (!GetBlendData(model, mesh, boneMappings, blendIndices, blendWeights, errorMessage_, maxBones_))
+                return false;
+        }
 
         float* dest = (float*)((unsigned char*)vertexData + startVertexOffset * vb->GetVertexSize());
         for (unsigned j = 0; j < mesh->mNumVertices; ++j)
@@ -506,7 +532,11 @@ void OpenAssetImporter::BuildAndSaveModel(OutModel& model)
 
     File outFile(context_);
     if (!outFile.Open(model.outName_, FILE_WRITE))
-        ErrorExit("Could not open output file " + model.outName_);
+    {
+        errorMessage_ = "Could not open output file " + model.outName_;
+        return false;
+    }
+
     outModel->Save(outFile);
 
     // If exporting materials, also save material list for use by the editor
@@ -524,6 +554,8 @@ void OpenAssetImporter::BuildAndSaveModel(OutModel& model)
             PrintLine("Warning: could not write material list file " + materialListName);
         }
     }
+
+    return true;
 }
 
 String OpenAssetImporter::GetMeshMaterialName(aiMesh* mesh)
@@ -634,7 +666,7 @@ void OpenAssetImporter::CollectSceneModels(OutScene& scene, aiNode* node)
         CollectSceneModels(scene, node->mChildren[i]);
 }
 
-void OpenAssetImporter::CollectBones(OutModel& model, bool animationOnly)
+bool OpenAssetImporter::CollectBones(OutModel& model, bool animationOnly)
 {
     HashSet<aiNode*> necessary;
     HashSet<aiNode*> rootNodes;
@@ -687,7 +719,11 @@ void OpenAssetImporter::CollectBones(OutModel& model, bool animationOnly)
                 String boneName(FromAIString(bone->mName));
                 aiNode* boneNode = GetNode(boneName, scene_->mRootNode, true);
                 if (!boneNode)
-                    ErrorExit("Could not find scene node for bone " + boneName);
+                {
+                    errorMessage_ = "Could not find scene node for bone " + boneName;
+                    return false;
+                }
+
                 necessary.Insert(boneNode);
                 rootNode = boneNode;
 
@@ -715,7 +751,10 @@ void OpenAssetImporter::CollectBones(OutModel& model, bool animationOnly)
             if (*i != commonParent)
             {
                 if (!commonParent || (*i)->mParent != commonParent)
-                    ErrorExit("Skeleton with multiple root nodes found, not supported");
+                {
+                    errorMessage_ = "Skeleton with multiple root nodes found, not supported";
+                    return false;
+                }
             }
         }
         rootNodes.Clear();
@@ -724,7 +763,7 @@ void OpenAssetImporter::CollectBones(OutModel& model, bool animationOnly)
     }
 
     if (rootNodes.Empty())
-        return;
+        return true;
 
     model.rootBone_ = *rootNodes.Begin();
     CollectBonesFinal(model.bones_, necessary, model.rootBone_);
@@ -736,6 +775,8 @@ void OpenAssetImporter::CollectBones(OutModel& model, bool animationOnly)
         model.boneRadii_[i] = 0.0f;
         model.boneHitboxes_[i] = BoundingBox(0.0f, 0.0f);
     }
+
+    return true;
 }
 
 void OpenAssetImporter::CollectBonesFinal(PODVector<aiNode*>& dest, const HashSet<aiNode*>& necessary, aiNode* node)
@@ -849,7 +890,7 @@ void OpenAssetImporter::BuildBoneCollisionInfo(OutModel& model)
     }
 }
 
-void OpenAssetImporter::BuildAndSaveAnimations(OutModel* model, const String &animNameOverride)
+bool OpenAssetImporter::BuildAndSaveAnimations(OutModel* model, const String &animNameOverride)
 {
     const PODVector<aiAnimation*>& animations = model ? model->animations_ : sceneAnimations_;
 
@@ -1066,7 +1107,11 @@ void OpenAssetImporter::BuildAndSaveAnimations(OutModel* model, const String &an
 
         File outFile(context_);
         if (!outFile.Open(animOutName, FILE_WRITE))
-            ErrorExit("Could not open output file " + animOutName);
+        {
+            errorMessage_ = "Could not open output file " + animOutName;
+            return false;
+        }
+
         outAnim->Save(outFile);
 
         AnimationInfo info;
@@ -1074,6 +1119,8 @@ void OpenAssetImporter::BuildAndSaveAnimations(OutModel* model, const String &an
         info.cacheFilename_ = animOutName;
         animationInfos_.Push(info);
     }
+
+    return true;
 }
 
 // Materials
@@ -1088,7 +1135,7 @@ void OpenAssetImporter::ExportMaterials(HashSet<String>& usedTextures)
         BuildAndSaveMaterial(scene_->mMaterials[i], usedTextures);
 }
 
-void OpenAssetImporter::BuildAndSaveMaterial(aiMaterial* material, HashSet<String>& usedTextures)
+bool OpenAssetImporter::BuildAndSaveMaterial(aiMaterial* material, HashSet<String>& usedTextures)
 {
     aiString matNameStr;
     material->Get(AI_MATKEY_NAME, matNameStr);
@@ -1233,15 +1280,21 @@ void OpenAssetImporter::BuildAndSaveMaterial(aiMaterial* material, HashSet<Strin
     if (noOverwriteMaterial_ && fileSystem->FileExists(outFileName))
     {
         PrintLine("Skipping save of existing material " + matName);
-        return;
+        return true;
     }
 
     PrintLine("Writing material " + matName);
 
     File outFile(context_);
     if (!outFile.Open(outFileName, FILE_WRITE))
-        ErrorExit("Could not open output file " + outFileName);
+    {
+        errorMessage_ = "Could not open output file " + outFileName;
+        return false;
+    }
+
     outMaterial.Save(outFile);
+
+    return true;
 }
 
 void OpenAssetImporter::DumpNodes(aiNode* rootNode, unsigned level)

+ 5 - 5
Source/ToolCore/Import/OpenAssetImporter.h

@@ -55,7 +55,7 @@ public:
 
     const String& GetErrorMessage() { return errorMessage_; }
 
-    void ExportModel(const String& outName, const String& animName = String::EMPTY, bool animationOnly = false);
+    bool ExportModel(const String& outName, const String& animName = String::EMPTY, bool animationOnly = false);
 
     void SetImportNode(Node* node) { importNode_ = node; }
     void SetStartTime(float startTime) { startTime_ = startTime; }
@@ -72,14 +72,14 @@ private:
     void ApplyScale();
     void ApplyScale(aiNode* node);
 
-    void BuildAndSaveModel(OutModel& model);
-    void BuildAndSaveAnimations(OutModel* model = 0, const String& animNameOverride = String::EMPTY);
+    bool BuildAndSaveModel(OutModel& model);
+    bool BuildAndSaveAnimations(OutModel* model = 0, const String& animNameOverride = String::EMPTY);
 
     void ExportMaterials(HashSet<String>& usedTextures);
-    void BuildAndSaveMaterial(aiMaterial* material, HashSet<String>& usedTextures);
+    bool BuildAndSaveMaterial(aiMaterial* material, HashSet<String>& usedTextures);
 
     void CollectSceneModels(OutScene& scene, aiNode* node);
-    void CollectBones(OutModel& model, bool animationOnly = false);
+    bool CollectBones(OutModel& model, bool animationOnly = false);
     void CollectBonesFinal(PODVector<aiNode*>& dest, const HashSet<aiNode*>& necessary, aiNode* node);
     void BuildBoneCollisionInfo(OutModel& model);
     void CollectAnimations(OutModel* model = 0);

+ 16 - 7
Source/ToolCore/Import/OpenAssetUtils.cpp

@@ -303,8 +303,8 @@ void GetPosRotScale(const aiMatrix4x4& transform, Vector3& pos, Quaternion& rot,
     scale = ToVector3(aiScale);
 }
 
-void GetBlendData(OutModel& model, aiMesh* mesh, PODVector<unsigned>& boneMappings, Vector<PODVector<unsigned char> >&
-    blendIndices, Vector<PODVector<float> >& blendWeights, unsigned maxBones)
+bool GetBlendData(OutModel& model, aiMesh* mesh, PODVector<unsigned>& boneMappings, Vector<PODVector<unsigned char> >&
+    blendIndices, Vector<PODVector<float> >& blendWeights, String& errorMessage, unsigned maxBones)
 {
     blendIndices.Resize(mesh->mNumVertices);
     blendWeights.Resize(mesh->mNumVertices);
@@ -315,10 +315,11 @@ void GetBlendData(OutModel& model, aiMesh* mesh, PODVector<unsigned>& boneMappin
     {
         if (mesh->mNumBones > maxBones)
         {
-            ErrorExit(
+            errorMessage =
                 "Geometry (submesh) has over " + String(maxBones) + " bone influences. Try splitting to more submeshes\n"
-                "that each stay at " + String(maxBones) + " bones or below."
-            );
+                "that each stay at " + String(maxBones) + " bones or below.";
+
+             return false;
         }
         boneMappings.Resize(mesh->mNumBones);
         for (unsigned i = 0; i < mesh->mNumBones; ++i)
@@ -347,17 +348,25 @@ void GetBlendData(OutModel& model, aiMesh* mesh, PODVector<unsigned>& boneMappin
             String boneName = FromAIString(bone->mName);
             unsigned globalIndex = GetBoneIndex(model, boneName);
             if (globalIndex == M_MAX_UNSIGNED)
-                ErrorExit("Bone " + boneName + " not found");
+            {
+                errorMessage = "Bone " + boneName + " not found";
+                return false;
+            }
             for (unsigned j = 0; j < bone->mNumWeights; ++j)
             {
                 unsigned vertex = bone->mWeights[j].mVertexId;
                 blendIndices[vertex].Push(globalIndex);
                 blendWeights[vertex].Push(bone->mWeights[j].mWeight);
                 if (blendWeights[vertex].Size() > 4)
-                    ErrorExit("More than 4 bone influences on vertex");
+                {
+                    errorMessage = "More than 4 bone influences on vertex";
+                    return false;
+                }
             }
         }
     }
+
+    return true;
 }
 
 String FromAIString(const aiString& str)

+ 2 - 2
Source/ToolCore/Import/OpenAssetUtils.h

@@ -105,8 +105,8 @@ aiBone* GetMeshBone(OutModel& model, const String& boneName);
 Matrix3x4 GetOffsetMatrix(OutModel& model, const String& boneName);
 unsigned GetNumValidFaces(aiMesh* mesh);
 
-void GetBlendData(OutModel& model, aiMesh* mesh, PODVector<unsigned>& boneMappings, Vector<PODVector<unsigned char> >&
-    blendIndices, Vector<PODVector<float> >& blendWeights, unsigned maxBones = 64);
+bool GetBlendData(OutModel& model, aiMesh* mesh, PODVector<unsigned>& boneMappings, Vector<PODVector<unsigned char> >&
+    blendIndices, Vector<PODVector<float> >& blendWeights, String &errorMessage, unsigned maxBones = 64);
 
 void CollectMeshes(const aiScene* scene, OutModel& model, aiNode* node);