Browse Source

Merge pull request #3787 from ms-maxvollmer/ms-maxvollmer/importer_fixes

Importer improvements
Kim Kulling 4 năm trước cách đây
mục cha
commit
96d0524fab

+ 25 - 2
code/AssetLib/glTF2/glTF2Asset.inl

@@ -162,6 +162,9 @@ inline static bool ReadValue(Value &val, T &out) {
 
 template <class T>
 inline static bool ReadMember(Value &obj, const char *id, T &out) {
+    if (!obj.IsObject()) {
+        return false;
+    }
     Value::MemberIterator it = obj.FindMember(id);
     if (it != obj.MemberEnd()) {
         return ReadHelper<T>::Read(it->value, out);
@@ -176,6 +179,9 @@ inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
 }
 
 inline Value *FindMember(Value &val, const char *id) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
     Value::MemberIterator it = val.FindMember(id);
     return (it != val.MemberEnd()) ? &it->value : nullptr;
 }
@@ -193,6 +199,9 @@ inline void throwUnexpectedTypeError(const char (&expectedTypeName)[N], const ch
 // Look-up functions with type checks. Context and extra context help the user identify the problem if there's an error.
 
 inline Value *FindStringInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
     Value::MemberIterator it = val.FindMember(memberId);
     if (it == val.MemberEnd()) {
         return nullptr;
@@ -204,6 +213,9 @@ inline Value *FindStringInContext(Value &val, const char *memberId, const char*
 }
 
 inline Value *FindNumberInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
     Value::MemberIterator it = val.FindMember(memberId);
     if (it == val.MemberEnd()) {
         return nullptr;
@@ -215,6 +227,9 @@ inline Value *FindNumberInContext(Value &val, const char *memberId, const char*
 }
 
 inline Value *FindUIntInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
     Value::MemberIterator it = val.FindMember(memberId);
     if (it == val.MemberEnd()) {
         return nullptr;
@@ -226,6 +241,9 @@ inline Value *FindUIntInContext(Value &val, const char *memberId, const char* co
 }
 
 inline Value *FindArrayInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
     Value::MemberIterator it = val.FindMember(memberId);
     if (it == val.MemberEnd()) {
         return nullptr;
@@ -237,6 +255,9 @@ inline Value *FindArrayInContext(Value &val, const char *memberId, const char* c
 }
 
 inline Value *FindObjectInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
     Value::MemberIterator it = val.FindMember(memberId);
     if (it == val.MemberEnd()) {
         return nullptr;
@@ -886,7 +907,7 @@ inline void Accessor::Read(Value &obj, Asset &r) {
     componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE);
     {
         const Value* countValue = FindUInt(obj, "count");
-        if (!countValue || countValue->GetInt() < 1)
+        if (!countValue || countValue->GetUint() < 1)
         {
             throw DeadlyImportError("A strictly positive count value is required, when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")");
         }
@@ -1105,7 +1126,9 @@ inline Accessor::Indexer::Indexer(Accessor &acc) :
 template <class T>
 T Accessor::Indexer::GetValue(int i) {
     ai_assert(data);
-    ai_assert(i * stride < accessor.GetMaxByteSize());
+    if (i * stride >= accessor.GetMaxByteSize()) {
+        throw DeadlyImportError("GLTF: Invalid index ", i, ", count out of range for buffer with stride ", stride, " and size ", accessor.GetMaxByteSize(), ".");
+    }
     // Ensure that the memcpy doesn't overwrite the local.
     const size_t sizeToCopy = std::min(elemSize, sizeof(T));
     T value = T();

+ 3 - 3
code/AssetLib/glTF2/glTF2Importer.cpp

@@ -1172,7 +1172,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
 
         static const float kMillisecondsFromSeconds = 1000.f;
 
-        if (samplers.translation) {
+        if (samplers.translation && samplers.translation->input && samplers.translation->output) {
             float *times = nullptr;
             samplers.translation->input->ExtractData(times);
             aiVector3D *values = nullptr;
@@ -1196,7 +1196,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
             anim->mPositionKeys->mValue.z = node.translation.value[2];
         }
 
-        if (samplers.rotation) {
+        if (samplers.rotation && samplers.rotation->input && samplers.rotation->output) {
             float *times = nullptr;
             samplers.rotation->input->ExtractData(times);
             aiQuaternion *values = nullptr;
@@ -1224,7 +1224,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
             anim->mRotationKeys->mValue.w = node.rotation.value[3];
         }
 
-        if (samplers.scale) {
+        if (samplers.scale && samplers.scale->input && samplers.scale->output) {
             float *times = nullptr;
             samplers.scale->input->ExtractData(times);
             aiVector3D *values = nullptr;

+ 3 - 1
code/PostProcessing/SortByPTypeProcess.cpp

@@ -135,7 +135,9 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
     std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin();
     for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
         aiMesh *const mesh = pScene->mMeshes[i];
-        ai_assert(0 != mesh->mPrimitiveTypes);
+        if (mesh->mPrimitiveTypes == 0) {
+            throw DeadlyImportError("Mesh with invalid primitive type: ", mesh->mName.C_Str());
+        }
 
         // if there's just one primitive type in the mesh there's nothing to do for us
         unsigned int num = 0;