Просмотр исходного кода

Merge pull request #4977 from turol/lwo-fixes

LWO fixes
Kim Kulling 2 лет назад
Родитель
Сommit
90333340d6
2 измененных файлов с 378 добавлено и 42 удалено
  1. 66 42
      code/AssetLib/LWO/LWOLoader.cpp
  2. 312 0
      test/unit/utLWOImportExport.cpp

+ 66 - 42
code/AssetLib/LWO/LWOLoader.cpp

@@ -178,7 +178,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
     mLayers->push_back(Layer());
     mCurLayer = &mLayers->back();
     mCurLayer->mName = "<LWODefault>";
-    mCurLayer->mIndex = (uint16_t) -1;
+    mCurLayer->mIndex = 1;
 
     // old lightwave file format (prior to v6)
     mIsLWO2 = false;
@@ -398,14 +398,6 @@ void LWOImporter::InternReadFile(const std::string &pFile,
                             pvVC[w]++;
                         }
 
-#if 0
-                        // process vertex weights. We can't properly reconstruct the whole skeleton for now,
-                        // but we can create dummy bones for all weight channels which we have.
-                        for (unsigned int w = 0; w < layer.mWeightChannels.size();++w)
-                        {
-                        }
-#endif
-
                         face.mIndices[q] = vert;
                     }
                     pf->mIndices = face.mIndices;
@@ -429,7 +421,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
         // Generate nodes to render the mesh. Store the source layer in the mParent member of the nodes
         unsigned int num = static_cast<unsigned int>(apcMeshes.size() - meshStart);
         if (layer.mName != "<LWODefault>" || num > 0) {
-            aiNode *pcNode = new aiNode();
+            std::unique_ptr<aiNode> pcNode(new aiNode());
             pcNode->mName.Set(layer.mName);
             pcNode->mParent = (aiNode *)&layer;
             pcNode->mNumMeshes = num;
@@ -439,7 +431,8 @@ void LWOImporter::InternReadFile(const std::string &pFile,
                 for (unsigned int p = 0; p < pcNode->mNumMeshes; ++p)
                     pcNode->mMeshes[p] = p + meshStart;
             }
-            apcNodes[layer.mIndex] = pcNode;
+            ASSIMP_LOG_DEBUG("insert apcNode for layer ", layer.mIndex, " \"", layer.mName, "\"");
+            apcNodes[layer.mIndex] = pcNode.release();
         }
     }
 
@@ -572,40 +565,64 @@ void LWOImporter::GenerateNodeGraph(std::map<uint16_t, aiNode *> &apcNodes) {
     aiNode *root = mScene->mRootNode = new aiNode();
     root->mName.Set("<LWORoot>");
 
-    //Set parent of all children, inserting pivots
-    std::map<uint16_t, aiNode *> mapPivot;
-    for (auto itapcNodes = apcNodes.begin(); itapcNodes != apcNodes.end(); ++itapcNodes) {
-
-        //Get the parent index
-        LWO::Layer *nodeLayer = (LWO::Layer *)(itapcNodes->second->mParent);
-        uint16_t parentIndex = nodeLayer->mParent;
+    ASSIMP_LOG_DEBUG("apcNodes initial size: ", apcNodes.size());
+    if (!apcNodes.empty()) {
+        ASSIMP_LOG_DEBUG("first apcNode is: ", apcNodes.begin()->first, " \"", apcNodes.begin()->second->mName.C_Str(), "\"");
+    }
 
-        //Create pivot node, store it into the pivot map, and set the parent as the pivot
-        aiNode *pivotNode = new aiNode();
-        pivotNode->mName.Set("Pivot-" + std::string(itapcNodes->second->mName.data));
-        itapcNodes->second->mParent = pivotNode;
+    //Set parent of all children, inserting pivots
+    {
+        std::map<uint16_t, aiNode *> mapPivot;
+        for (auto itapcNodes = apcNodes.begin(); itapcNodes != apcNodes.end(); ++itapcNodes) {
+
+            //Get the parent index
+            LWO::Layer *nodeLayer = (LWO::Layer *)(itapcNodes->second->mParent);
+            uint16_t parentIndex = nodeLayer->mParent;
+
+            //Create pivot node, store it into the pivot map, and set the parent as the pivot
+            std::unique_ptr<aiNode> pivotNode(new aiNode());
+            pivotNode->mName.Set("Pivot-" + std::string(itapcNodes->second->mName.data));
+            itapcNodes->second->mParent = pivotNode.get();
+
+            //Look for the parent node to attach the pivot to
+            if (apcNodes.find(parentIndex) != apcNodes.end()) {
+                pivotNode->mParent = apcNodes[parentIndex];
+            } else {
+                //If not, attach to the root node
+                pivotNode->mParent = root;
+            }
 
-        //Look for the parent node to attach the pivot to
-        if (apcNodes.find(parentIndex) != apcNodes.end()) {
-            pivotNode->mParent = apcNodes[parentIndex];
-        } else {
-            //If not, attach to the root node
-            pivotNode->mParent = root;
+            //Set the node and the pivot node transformation
+            itapcNodes->second->mTransformation.a4 = -nodeLayer->mPivot.x;
+            itapcNodes->second->mTransformation.b4 = -nodeLayer->mPivot.y;
+            itapcNodes->second->mTransformation.c4 = -nodeLayer->mPivot.z;
+            pivotNode->mTransformation.a4 = nodeLayer->mPivot.x;
+            pivotNode->mTransformation.b4 = nodeLayer->mPivot.y;
+            pivotNode->mTransformation.c4 = nodeLayer->mPivot.z;
+            uint16_t pivotNodeId = static_cast<uint16_t>(-(itapcNodes->first + 2));
+            ASSIMP_LOG_DEBUG("insert pivot node: ", pivotNodeId);
+            auto oldNodeIt = mapPivot.find(pivotNodeId);
+            if (oldNodeIt != mapPivot.end()) {
+                ASSIMP_LOG_ERROR("attempted to insert pivot node which already exists in pivot map ", pivotNodeId, " \"", pivotNode->mName.C_Str(), "\"");
+            } else {
+                mapPivot.emplace(pivotNodeId, pivotNode.release());
+            }
         }
 
-        //Set the node and the pivot node transformation
-        itapcNodes->second->mTransformation.a4 = -nodeLayer->mPivot.x;
-        itapcNodes->second->mTransformation.b4 = -nodeLayer->mPivot.y;
-        itapcNodes->second->mTransformation.c4 = -nodeLayer->mPivot.z;
-        pivotNode->mTransformation.a4 = nodeLayer->mPivot.x;
-        pivotNode->mTransformation.b4 = nodeLayer->mPivot.y;
-        pivotNode->mTransformation.c4 = nodeLayer->mPivot.z;
-        mapPivot[-(itapcNodes->first + 2)] = pivotNode;
-    }
-
-    //Merge pivot map into node map
-    for (auto itMapPivot = mapPivot.begin(); itMapPivot != mapPivot.end(); ++itMapPivot) {
-        apcNodes[itMapPivot->first] = itMapPivot->second;
+        ASSIMP_LOG_DEBUG("pivot nodes: ", mapPivot.size());
+        //Merge pivot map into node map
+        for (auto itMapPivot = mapPivot.begin(); itMapPivot != mapPivot.end();) {
+            uint16_t pivotNodeId = itMapPivot->first;
+            auto oldApcNodeIt = apcNodes.find(pivotNodeId);
+            if (oldApcNodeIt != apcNodes.end()) {
+                ASSIMP_LOG_ERROR("attempted to insert pivot node which already exists in apc nodes ", pivotNodeId, " \"", itMapPivot->second->mName.C_Str(), "\"");
+            } else {
+                apcNodes.emplace(pivotNodeId, itMapPivot->second);
+            }
+            itMapPivot->second = nullptr;
+            itMapPivot = mapPivot.erase(itMapPivot);
+        }
+        ASSIMP_LOG_DEBUG("total nodes: ", apcNodes.size());
     }
 
     //Set children of all parents
@@ -627,8 +644,15 @@ void LWOImporter::GenerateNodeGraph(std::map<uint16_t, aiNode *> &apcNodes) {
         }
     }
 
-    if (!mScene->mRootNode->mNumChildren)
+    if (!mScene->mRootNode->mNumChildren) {
+        ASSIMP_LOG_DEBUG("All apcNodes:");
+        for (auto nodeIt = apcNodes.begin(); nodeIt != apcNodes.end(); ) {
+            ASSIMP_LOG_DEBUG("Node ", nodeIt->first, " \"", nodeIt->second->mName.C_Str(), "\"");
+            nodeIt->second = nullptr;
+            nodeIt = apcNodes.erase(nodeIt);
+        }
         throw DeadlyImportError("LWO: Unable to build a valid node graph");
+    }
 
     // Remove a single root node with no meshes assigned to it ...
     if (1 == mScene->mRootNode->mNumChildren) {

+ 312 - 0
test/unit/utLWOImportExport.cpp

@@ -75,3 +75,315 @@ TEST_F(utLWOImportExport, importLWOformatdetection) {
 
     EXPECT_NE(nullptr, scene);
 }
+
+
+TEST_F(utLWOImportExport, importLWOempty) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/invalid/empty.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_EQ(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWObox_2uv_1unused) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/box_2uv_1unused.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWObox_2vc_1unused) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/box_2vc_1unused.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOconcave_polygon) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/concave_polygon.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOconcave_self_intersecting) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/concave_self_intersecting.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOhierarchy) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/hierarchy.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOhierarchy_smoothed) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/hierarchy_smoothed.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOearth_cylindrical_x) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/MappingModes/earth_cylindrical_x.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOearth_cylindrical_x_scale_222_wrap_21) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/MappingModes/earth_cylindrical_x_scale_222_wrap_21.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOearth_cylindrical_y) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/MappingModes/earth_cylindrical_y.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOearth_cylindrical_y_scale_111) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/MappingModes/earth_cylindrical_y_scale_111.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOearth_cylindrical_y_scale_111_wrap_21) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/MappingModes/earth_cylindrical_y_scale_111_wrap_21.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOearth_cylindrical_z) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/MappingModes/earth_cylindrical_z.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOearth_planar_x) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/MappingModes/earth_planar_x.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOearth_planar_y) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/MappingModes/earth_planar_y.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOearth_planar_z) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/MappingModes/earth_planar_z.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOearth_planar_z_scale_111) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/MappingModes/earth_planar_z_scale_111.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOearth_spherical_x) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/MappingModes/earth_spherical_x.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOearth_spherical_x_scale_222_wrap_22) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/MappingModes/earth_spherical_x_scale_222_wrap_22.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOearth_spherical_y) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/MappingModes/earth_spherical_y.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOearth_spherical_) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/MappingModes/earth_spherical_z.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOearth_spherical_z_wrap_22) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/MappingModes/earth_spherical_z_wrap_22.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOearth_uv_cylindrical_y) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/MappingModes/earth_uv_cylindrical_y.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOModoExport_vertNormals) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/ModoExport_vertNormals.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOnonplanar_polygon) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/nonplanar_polygon.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOCellShader) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/shader_test/CellShader.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOfastFresne) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/shader_test/fastFresnel.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOrealFresnel) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/shader_test/realFresnel.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOSuperCellShader) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/shader_test/SuperCellShader.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOsphere_with_gradient) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/sphere_with_gradient.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOsphere_with_mat_gloss_10pc) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/sphere_with_mat_gloss_10pc.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOSubdivision) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/Subdivision.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOtransparency) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/transparency.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOUglyVertexColors) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/UglyVertexColors.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOuvtest) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/uvtest.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOBConcavePolygon) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWOB/ConcavePolygon.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOBbluewithcylindrictex) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWOB/MappingModes/bluewithcylindrictexz.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOBsphere_with_mat_gloss_10pc) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWOB/sphere_with_mat_gloss_10pc.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utLWOImportExport, importLWOBsphere_with_mat_gloss_50pc) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWOB/sphere_with_mat_gloss_50pc.lwo", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}