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

Added HL1 MDL loader tests.

Added new unit test source files.
Added MDL samples for tests.
Updated CMakeLists file to include the new unit tests.
Marc-Antoine Lortie 5 лет назад
Родитель
Сommit
4144a222d3
39 измененных файлов с 973 добавлено и 0 удалено
  1. 5 0
      test/CMakeLists.txt
  2. BIN
      test/models/MDL/MDL (HL1)/alpha_test.mdl
  3. BIN
      test/models/MDL/MDL (HL1)/blend_additive.mdl
  4. BIN
      test/models/MDL/MDL (HL1)/chrome_sphere.mdl
  5. BIN
      test/models/MDL/MDL (HL1)/duplicate_bodyparts.mdl
  6. BIN
      test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups.mdl
  7. BIN
      test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups01.mdl
  8. BIN
      test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups02.mdl
  9. BIN
      test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups03.mdl
  10. BIN
      test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups04.mdl
  11. BIN
      test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups05.mdl
  12. BIN
      test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups06.mdl
  13. BIN
      test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups07.mdl
  14. BIN
      test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups08.mdl
  15. BIN
      test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups09.mdl
  16. BIN
      test/models/MDL/MDL (HL1)/duplicate_sequences.mdl
  17. BIN
      test/models/MDL/MDL (HL1)/duplicate_submodels.mdl
  18. BIN
      test/models/MDL/MDL (HL1)/man.mdl
  19. BIN
      test/models/MDL/MDL (HL1)/man01.mdl
  20. BIN
      test/models/MDL/MDL (HL1)/manT.mdl
  21. BIN
      test/models/MDL/MDL (HL1)/sequence_transitions.mdl
  22. BIN
      test/models/MDL/MDL (HL1)/unnamed_bodyparts.mdl
  23. BIN
      test/models/MDL/MDL (HL1)/unnamed_bones.mdl
  24. BIN
      test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups.mdl
  25. BIN
      test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups01.mdl
  26. BIN
      test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups02.mdl
  27. BIN
      test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups03.mdl
  28. BIN
      test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups04.mdl
  29. BIN
      test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups05.mdl
  30. BIN
      test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups06.mdl
  31. BIN
      test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups07.mdl
  32. BIN
      test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups08.mdl
  33. BIN
      test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups09.mdl
  34. BIN
      test/models/MDL/MDL (HL1)/unnamed_sequences.mdl
  35. 59 0
      test/unit/ImportExport/MDL/MDLHL1TestFiles.h
  36. 244 0
      test/unit/ImportExport/MDL/utMDLImporter_HL1_ImportSettings.cpp
  37. 136 0
      test/unit/ImportExport/MDL/utMDLImporter_HL1_Materials.cpp
  38. 458 0
      test/unit/ImportExport/MDL/utMDLImporter_HL1_Nodes.cpp
  39. 71 0
      test/unit/ImportExport/utMDLImporter.cpp

+ 5 - 0
test/CMakeLists.txt

@@ -128,6 +128,11 @@ SET( IMPORTERS
   unit/ImportExport/utOFFImportExport.cpp
   unit/ImportExport/utNFFImportExport.cpp
   unit/ImportExport/utXGLImportExport.cpp
+  unit/ImportExport/utMDLImporter.cpp
+  unit/ImportExport/MDL/MDLHL1TestFiles.h
+  unit/ImportExport/MDL/utMDLImporter_HL1_ImportSettings.cpp
+  unit/ImportExport/MDL/utMDLImporter_HL1_Materials.cpp
+  unit/ImportExport/MDL/utMDLImporter_HL1_Nodes.cpp
 )
 
 SET( MATERIAL

BIN
test/models/MDL/MDL (HL1)/alpha_test.mdl


BIN
test/models/MDL/MDL (HL1)/blend_additive.mdl


BIN
test/models/MDL/MDL (HL1)/chrome_sphere.mdl


BIN
test/models/MDL/MDL (HL1)/duplicate_bodyparts.mdl


BIN
test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups.mdl


BIN
test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups01.mdl


BIN
test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups02.mdl


BIN
test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups03.mdl


BIN
test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups04.mdl


BIN
test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups05.mdl


BIN
test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups06.mdl


BIN
test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups07.mdl


BIN
test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups08.mdl


BIN
test/models/MDL/MDL (HL1)/duplicate_sequence_groups/duplicate_sequence_groups09.mdl


BIN
test/models/MDL/MDL (HL1)/duplicate_sequences.mdl


BIN
test/models/MDL/MDL (HL1)/duplicate_submodels.mdl


BIN
test/models/MDL/MDL (HL1)/man.mdl


BIN
test/models/MDL/MDL (HL1)/man01.mdl


BIN
test/models/MDL/MDL (HL1)/manT.mdl


BIN
test/models/MDL/MDL (HL1)/sequence_transitions.mdl


BIN
test/models/MDL/MDL (HL1)/unnamed_bodyparts.mdl


BIN
test/models/MDL/MDL (HL1)/unnamed_bones.mdl


BIN
test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups.mdl


BIN
test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups01.mdl


BIN
test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups02.mdl


BIN
test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups03.mdl


BIN
test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups04.mdl


BIN
test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups05.mdl


BIN
test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups06.mdl


BIN
test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups07.mdl


BIN
test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups08.mdl


BIN
test/models/MDL/MDL (HL1)/unnamed_sequence_groups/unnamed_sequence_groups09.mdl


BIN
test/models/MDL/MDL (HL1)/unnamed_sequences.mdl


+ 59 - 0
test/unit/ImportExport/MDL/MDLHL1TestFiles.h

@@ -0,0 +1,59 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file MDLHL1TestFiles.h
+ *  @brief Definitions for Half-Life 1 MDL loader tests.
+ */
+
+#ifndef AI_MDLHL1TESTFILES_INCLUDED
+#define AI_MDLHL1TESTFILES_INCLUDED
+
+#ifndef ASSIMP_TEST_MDL_HL1_MODELS_DIR
+#define ASSIMP_TEST_MDL_HL1_MODELS_DIR ASSIMP_TEST_MODELS_DIR"/MDL/MDL (HL1)/"
+#endif
+
+#ifndef MDL_HL1_FILE_MAN
+#define MDL_HL1_FILE_MAN ASSIMP_TEST_MDL_HL1_MODELS_DIR "man.mdl"
+#endif
+
+#endif // AI_MDLHL1TESTFILES_INCLUDED

+ 244 - 0
test/unit/ImportExport/MDL/utMDLImporter_HL1_ImportSettings.cpp

@@ -0,0 +1,244 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file utMDLImporter_HL1_ImportSettings.cpp
+ *  @brief Half-Life 1 MDL loader import settings tests.
+ */
+
+#include "AbstractImportExportBase.h"
+#include "MDL/HalfLife/HL1ImportDefinitions.h"
+#include "MDLHL1TestFiles.h"
+#include "UnitTestPCH.h"
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+#include <assimp/Importer.hpp>
+#include <functional>
+#include <initializer_list>
+
+using namespace Assimp;
+
+class utMDLImporter_HL1_ImportSettings : public ::testing::Test {
+
+public:
+    // Test various import settings scenarios.
+
+    void importSettings() {
+        
+        /* Verify that animations are *NOT* imported when
+           'Read animations' is disabled. */
+        load_with_import_setting_bool(
+            MDL_HL1_FILE_MAN,
+            AI_CONFIG_IMPORT_MDL_HL1_READ_ANIMATIONS,
+            false, // Set config value to false.
+            [&](const aiScene *scene) {
+                EXPECT_EQ(0, scene->mNumAnimations);
+                EXPECT_EQ(nullptr, scene->mRootNode->FindNode(AI_MDL_HL1_NODE_SEQUENCE_INFOS));
+                EXPECT_EQ(nullptr, scene->mRootNode->FindNode(AI_MDL_HL1_NODE_SEQUENCE_GROUPS));
+                EXPECT_EQ(nullptr, scene->mRootNode->FindNode(AI_MDL_HL1_NODE_SEQUENCE_TRANSITION_GRAPH));
+
+                expect_global_info_eq<int>(scene, {
+                    { 0, "NumSequences" },
+                    { 0, "NumTransitionNodes" }
+                });
+            });
+
+        /* Verify that blend controllers info is *NOT* imported when
+           'Read blend controllers' is disabled. */
+        load_with_import_setting_bool(
+            MDL_HL1_FILE_MAN,
+            AI_CONFIG_IMPORT_MDL_HL1_READ_BLEND_CONTROLLERS,
+            false, // Set config value to false.
+            [&](const aiScene *scene) {
+                EXPECT_NE(0, scene->mNumAnimations);
+
+                const aiNode *sequence_infos = scene->mRootNode->FindNode(AI_MDL_HL1_NODE_SEQUENCE_INFOS);
+                EXPECT_NE(nullptr, sequence_infos);
+
+                for (unsigned int i = 0; i < sequence_infos->mNumChildren; ++i)
+                    EXPECT_EQ(nullptr, sequence_infos->mChildren[i]->FindNode(AI_MDL_HL1_NODE_BLEND_CONTROLLERS));
+                
+                expect_global_info_eq(scene, 0, "NumBlendControllers");
+            });
+
+        /* Verify that animation events are *NOT* imported when
+           'Read animation events' is disabled. */
+        load_with_import_setting_bool(
+            MDL_HL1_FILE_MAN,
+            AI_CONFIG_IMPORT_MDL_HL1_READ_ANIMATION_EVENTS,
+            false, // Set config value to false.
+            [&](const aiScene *scene) {
+                EXPECT_NE(0, scene->mNumAnimations);
+
+                const aiNode *sequence_infos = scene->mRootNode->FindNode(AI_MDL_HL1_NODE_SEQUENCE_INFOS);
+                EXPECT_NE(nullptr, sequence_infos);
+
+                for (unsigned int i = 0; i < sequence_infos->mNumChildren; ++i)
+                    EXPECT_EQ(nullptr, sequence_infos->mChildren[i]->FindNode(AI_MDL_HL1_NODE_ANIMATION_EVENTS));
+            });
+
+        /* Verify that sequence transitions info is read when
+           'Read sequence transitions' is enabled. */
+        load_with_import_setting_bool(
+            ASSIMP_TEST_MDL_HL1_MODELS_DIR "sequence_transitions.mdl",
+            AI_CONFIG_IMPORT_MDL_HL1_READ_SEQUENCE_TRANSITIONS,
+            true, // Set config value to true.
+            [&](const aiScene *scene) {
+                EXPECT_NE(nullptr, scene->mRootNode->FindNode(AI_MDL_HL1_NODE_SEQUENCE_TRANSITION_GRAPH));
+                expect_global_info_eq(scene, 4, "NumTransitionNodes");
+            });
+
+        /* Verify that sequence transitions info is *NOT* read when
+           'Read sequence transitions' is disabled. */
+        load_with_import_setting_bool(
+            ASSIMP_TEST_MDL_HL1_MODELS_DIR "sequence_transitions.mdl",
+            AI_CONFIG_IMPORT_MDL_HL1_READ_SEQUENCE_TRANSITIONS,
+            false, // Set config value to false.
+            [&](const aiScene *scene) {
+                EXPECT_EQ(nullptr, scene->mRootNode->FindNode(AI_MDL_HL1_NODE_SEQUENCE_TRANSITION_GRAPH));
+                expect_global_info_eq(scene, 0, "NumTransitionNodes");
+            });
+
+        /* Verify that bone controllers info is *NOT* read when
+           'Read bone controllers' is disabled. */
+        load_with_import_setting_bool(
+            MDL_HL1_FILE_MAN,
+            AI_CONFIG_IMPORT_MDL_HL1_READ_BONE_CONTROLLERS,
+            false, // Set config value to false.
+            [&](const aiScene *scene) {
+                EXPECT_EQ(nullptr, scene->mRootNode->FindNode(AI_MDL_HL1_NODE_BONE_CONTROLLERS));
+                expect_global_info_eq(scene, 0, "NumBoneControllers");
+            });
+
+        /* Verify that attachments info is *NOT* read when
+           'Read attachments' is disabled. */
+        load_with_import_setting_bool(
+            MDL_HL1_FILE_MAN,
+            AI_CONFIG_IMPORT_MDL_HL1_READ_ATTACHMENTS,
+            false, // Set config value to false.
+            [&](const aiScene *scene) {
+                EXPECT_EQ(nullptr, scene->mRootNode->FindNode(AI_MDL_HL1_NODE_ATTACHMENTS));
+                expect_global_info_eq(scene, 0, "NumAttachments");
+            });
+
+        /* Verify that hitboxes info is *NOT* read when
+           'Read hitboxes' is disabled. */
+        load_with_import_setting_bool(
+            MDL_HL1_FILE_MAN,
+            AI_CONFIG_IMPORT_MDL_HL1_READ_HITBOXES,
+            false, // Set config value to false.
+            [&](const aiScene *scene) {
+                EXPECT_EQ(nullptr, scene->mRootNode->FindNode(AI_MDL_HL1_NODE_HITBOXES));
+                expect_global_info_eq(scene, 0, "NumHitboxes");
+            });
+
+        /* Verify that misc global info is *NOT* read when
+           'Read misc global info' is disabled. */
+        load_with_import_setting_bool(
+            MDL_HL1_FILE_MAN,
+            AI_CONFIG_IMPORT_MDL_HL1_READ_MISC_GLOBAL_INFO,
+            false, // Set config value to false.
+            [&](const aiScene *scene) {
+                aiNode *global_info = get_global_info(scene);
+                EXPECT_NE(nullptr, global_info);
+                aiVector3D temp;
+                EXPECT_FALSE(global_info->mMetaData->Get("EyePosition", temp));
+            });
+    }
+
+private:
+    void load_with_import_setting_bool(
+        const char *file_path,
+        const char *setting_key,
+        bool setting_value,
+        std::function<void(const aiScene *)> &&func) {
+        Assimp::Importer importer;
+        importer.SetPropertyBool(setting_key, setting_value);
+        const aiScene *scene = importer.ReadFile(file_path, aiProcess_ValidateDataStructure);
+        EXPECT_NE(nullptr, scene);
+        func(scene);
+    }
+
+    void load_with_import_setting_string(
+        const char *file_path,
+        const char *setting_key,
+        const char *setting_value,
+        std::function<void(const aiScene *)> &&func) {
+        Assimp::Importer importer;
+        importer.SetPropertyString(setting_key, setting_value);
+        const aiScene *scene = importer.ReadFile(file_path, aiProcess_ValidateDataStructure);
+        EXPECT_NE(nullptr, scene);
+        func(scene);
+    }
+
+    inline static aiNode *get_global_info(const aiScene *scene) {
+        return scene->mRootNode->FindNode(AI_MDL_HL1_NODE_GLOBAL_INFO);
+    }
+
+    template <typename T>
+    static void expect_global_info_eq(
+        const aiScene *scene, 
+        T expected_value, 
+        const char *key_name) {
+        aiNode *global_info = get_global_info(scene);
+        EXPECT_NE(nullptr, global_info);
+        T temp;
+        EXPECT_TRUE(global_info->mMetaData->Get(key_name, temp));
+        EXPECT_EQ(expected_value, temp);
+    }
+
+    template <typename T>
+    static void expect_global_info_eq(const aiScene *scene,
+        std::initializer_list<std::pair<T, const char *>> p_kv) {
+        aiNode *global_info = get_global_info(scene);
+        EXPECT_NE(nullptr, global_info);
+        for (auto it = p_kv.begin(); it != p_kv.end(); ++it) {
+            T temp;
+            EXPECT_TRUE(global_info->mMetaData->Get(it->second, temp));
+            EXPECT_EQ(it->first, temp);
+        }
+    }
+};
+
+TEST_F(utMDLImporter_HL1_ImportSettings, importSettings) {
+    importSettings();
+}

+ 136 - 0
test/unit/ImportExport/MDL/utMDLImporter_HL1_Materials.cpp

@@ -0,0 +1,136 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file utMDLImporter_HL1_Materials.cpp
+ *  @brief Half-Life 1 MDL loader materials tests.
+ */
+
+#include "UnitTestPCH.h"
+#include "AbstractImportExportBase.h"
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+#include <assimp/Importer.hpp>
+#include "MDLHL1TestFiles.h"
+#include "MDL/HalfLife/HL1ImportDefinitions.h"
+
+using namespace Assimp;
+
+class utMDLImporter_HL1_Materials : public ::testing::Test {
+
+public:
+    /* Given an MDL model with a texture flagged as flatshade,
+       verify that the imported model has a flat shading model. */
+    void flatShadeTexture() {
+        Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MDL_HL1_MODELS_DIR "chrome_sphere.mdl", aiProcess_ValidateDataStructure);
+        EXPECT_NE(nullptr, scene);
+        EXPECT_NE(nullptr, scene->mMaterials);
+
+        aiShadingMode shading_mode;
+        scene->mMaterials[0]->Get(AI_MATKEY_SHADING_MODEL, shading_mode);
+        EXPECT_EQ(aiShadingMode_Flat, shading_mode);
+    }
+
+    /* Given an MDL model with a chrome texture, verify that
+       the imported model has a chrome material. */
+    void chromeTexture() {
+        Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MDL_HL1_MODELS_DIR "chrome_sphere.mdl", aiProcess_ValidateDataStructure);
+        EXPECT_NE(nullptr, scene);
+        EXPECT_NE(nullptr, scene->mMaterials);
+
+        int chrome;
+        scene->mMaterials[0]->Get(AI_MDL_HL1_MATKEY_CHROME(aiTextureType_DIFFUSE, 0), chrome);
+        EXPECT_EQ(1, chrome);
+    }
+
+    /* Given an MDL model with an additive texture, verify that
+       the imported model has an additive material. */
+    void additiveBlendTexture() {
+        Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MDL_HL1_MODELS_DIR "blend_additive.mdl", aiProcess_ValidateDataStructure);
+        EXPECT_NE(nullptr, scene);
+        EXPECT_NE(nullptr, scene->mMaterials);
+
+        aiBlendMode blend_mode;
+        scene->mMaterials[0]->Get(AI_MATKEY_BLEND_FUNC, blend_mode);
+        EXPECT_EQ(aiBlendMode_Additive, blend_mode);
+    }
+
+    /* Given an MDL model with a color masked texture, verify that
+       the imported model has a color masked material. Ensure too
+       that the transparency color is the correct one. */
+    void textureWithColorMask() {
+        Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MDL_HL1_MODELS_DIR "alpha_test.mdl", aiProcess_ValidateDataStructure);
+        EXPECT_NE(nullptr, scene);
+        EXPECT_NE(nullptr, scene->mMaterials);
+
+        int texture_flags;
+        scene->mMaterials[0]->Get(AI_MATKEY_TEXFLAGS_DIFFUSE(0), texture_flags);
+        EXPECT_EQ(aiTextureFlags_UseAlpha, texture_flags);
+
+        // The model has only one texture, a 256 color bitmap with
+        // a palette. Pure blue is the last color in the palette,
+        // and should be the transparency color.
+        aiColor3D transparency_color;
+        scene->mMaterials[0]->Get(AI_MATKEY_COLOR_TRANSPARENT, transparency_color);
+        EXPECT_EQ(aiColor3D(0, 0, 255), transparency_color);
+    }
+};
+
+TEST_F(utMDLImporter_HL1_Materials, flatShadeTexture) {
+    flatShadeTexture();
+}
+
+TEST_F(utMDLImporter_HL1_Materials, chromeTexture) {
+    chromeTexture();
+}
+
+TEST_F(utMDLImporter_HL1_Materials, additiveBlendTexture) {
+    additiveBlendTexture();
+}
+
+TEST_F(utMDLImporter_HL1_Materials, textureWithColorMask) {
+    textureWithColorMask();
+}

+ 458 - 0
test/unit/ImportExport/MDL/utMDLImporter_HL1_Nodes.cpp

@@ -0,0 +1,458 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file utMDLImporter_HL1_Nodes.cpp
+ *  @brief Half-Life 1 MDL loader nodes tests.
+ */
+
+#include "UnitTestPCH.h"
+#include "AbstractImportExportBase.h"
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+#include <assimp/Importer.hpp>
+#include "MDLHL1TestFiles.h"
+#include "MDL/HalfLife/HL1ImportDefinitions.h"
+
+using namespace Assimp;
+
+class utMDLImporter_HL1_Nodes : public ::testing::Test {
+
+public:
+    /**
+    * @note The following tests require a basic understanding
+    * of the SMD format. For more information about SMD format,
+    * please refer to the SMD importer or go to VDC
+    * (Valve Developer Community).
+    */
+
+    /*  Given a model with bones that have empty names,
+        verify that all the bones of the imported model
+        have unique and no empty names.
+
+        ""        <----+---- empty names
+        ""        <----+
+        ""        <----+
+        "Bone_3"       |
+        ""        <----+
+        "Bone_2"       |
+        "Bone_5"       | 
+        ""        <----+
+        ""        <----+
+    */
+    void emptyBonesNames() {
+        Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MDL_HL1_MODELS_DIR "unnamed_bones.mdl", aiProcess_ValidateDataStructure);
+        EXPECT_NE(nullptr, scene);
+
+        const std::vector<std::string> expected_bones_names = {
+            "Bone",
+            "Bone_0",
+            "Bone_1",
+            "Bone_3",
+            "Bone_4",
+            "Bone_2",
+            "Bone_5",
+            "Bone_6",
+            "Bone_7"
+        };
+
+        expect_named_children(scene, AI_MDL_HL1_NODE_BONES, expected_bones_names);
+    }
+
+    /*  Given a model with bodyparts that have empty names,
+        verify that the imported model contains bodyparts with
+        unique and no empty names.
+
+        $body ""           <----+---- empty names
+        $body "Bodypart_1"      |
+        $body "Bodypart_5"      |
+        $body "Bodypart_6"      |
+        $body ""           <----+
+        $body "Bodypart_2"      |
+        $body ""           <----+
+        $body "Bodypart_3"      |
+        $body ""           <----+
+    */
+    void emptyBodypartsNames() {
+        Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MDL_HL1_MODELS_DIR "unnamed_bodyparts.mdl", aiProcess_ValidateDataStructure);
+        EXPECT_NE(nullptr, scene);
+        
+        const std::vector<std::string> expected_bodyparts_names = {
+            "Bodypart",
+            "Bodypart_1",
+            "Bodypart_5",
+            "Bodypart_6",
+            "Bodypart_0",
+            "Bodypart_2",
+            "Bodypart_4",
+            "Bodypart_3",
+            "Bodypart_7"
+        };
+
+        expect_named_children(scene, AI_MDL_HL1_NODE_BODYPARTS, expected_bodyparts_names);
+    }
+
+    /*  Given a model with bodyparts that have duplicate names,
+        verify that the imported model contains bodyparts with
+        unique and no duplicate names.
+
+        $body "Bodypart"   <-----+
+        $body "Bodypart_1" <--+  |
+        $body "Bodypart_2"    |  |
+        $body "Bodypart1"     |  |
+        $body "Bodypart"   ---|--+ 
+        $body "Bodypart_1" ---+  |
+        $body "Bodypart2"        |
+        $body "Bodypart"   ------+
+        $body "Bodypart_4"
+    */
+    void duplicateBodypartsNames() {
+        Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MDL_HL1_MODELS_DIR "duplicate_bodyparts.mdl", aiProcess_ValidateDataStructure);
+        EXPECT_NE(nullptr, scene);
+
+        const std::vector<std::string> expected_bodyparts_names = {
+            "Bodypart",
+            "Bodypart_1",
+            "Bodypart_2",
+            "Bodypart1",
+            "Bodypart_0",
+            "Bodypart_1_0",
+            "Bodypart2",
+            "Bodypart_3",
+            "Bodypart_4"
+        };
+
+        expect_named_children(scene, AI_MDL_HL1_NODE_BODYPARTS, expected_bodyparts_names);
+    }
+
+    /*  Given a model with several bodyparts that contains multiple
+        sub models with the same file name, verify for each bodypart
+        sub model of the imported model that they have a unique name.
+
+        $bodygroup "first_bodypart"
+        {
+            studio "triangle"   <------+ duplicate file names.
+            studio "triangle"   -------+
+        }                              |
+                                       |
+        $bodygroup "second_bodypart"   |
+        {                              |
+            studio "triangle"   -------+ same as first bodypart, but with same file.
+            studio "triangle"   -------+
+        }
+
+        $bodygroup "last_bodypart"
+        {
+            studio "triangle2"  <------+ duplicate names.
+            studio "triangle2"  -------+
+        }
+    */
+    void duplicateSubModelsNames() {
+        Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MDL_HL1_MODELS_DIR "duplicate_submodels.mdl", aiProcess_ValidateDataStructure);
+        EXPECT_NE(nullptr, scene);
+
+        const std::vector<std::vector<std::string>> expected_bodypart_sub_models_names = {
+            {
+                "triangle",
+                "triangle_0",
+            },
+            {
+                "triangle_1",
+                "triangle_2",
+            },
+            {
+                "triangle2",
+                "triangle2_0",
+            }
+        };
+
+        const aiNode *bodyparts_node = scene->mRootNode->FindNode(AI_MDL_HL1_NODE_BODYPARTS);
+        EXPECT_NE(nullptr, bodyparts_node);
+        EXPECT_EQ(3, bodyparts_node->mNumChildren);
+        for (unsigned int i = 0; i < bodyparts_node->mNumChildren; ++i) {
+            expect_named_children(bodyparts_node->mChildren[i],
+                    expected_bodypart_sub_models_names[i]);
+        }
+    }
+
+    /*  Given a model with sequences that have duplicate names, verify
+        that each sequence from the imported model has a unique
+        name.
+
+        $sequence "idle_1" <-------+
+        $sequence "idle"   <----+  |
+        $sequence "idle_2"      |  |
+        $sequence "idle"   -----+  |
+        $sequence "idle_0"      |  |
+        $sequence "idle_1" -----|--+
+        $sequence "idle_3"      |
+        $sequence "idle"   -----+
+        $sequence "idle_7"
+    */
+    void duplicateSequenceNames() {
+        Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MDL_HL1_MODELS_DIR "duplicate_sequences.mdl", aiProcess_ValidateDataStructure);
+        EXPECT_NE(nullptr, scene);
+
+        const std::vector<std::string> expected_sequence_names = {
+            "idle_1",
+            "idle",
+            "idle_2",
+            "idle_4",
+            "idle_0",
+            "idle_1_0",
+            "idle_3",
+            "idle_5",
+            "idle_7"
+        };
+
+        expect_named_children(scene, AI_MDL_HL1_NODE_SEQUENCE_INFOS, expected_sequence_names);
+    }
+
+    /*  Given a model with sequences that have empty names, verify
+        that each sequence from the imported model has a unique
+        name.
+
+        $sequence ""            <----+---- empty names
+        $sequence "Sequence_1"       |
+        $sequence ""            <----+
+        $sequence "Sequence_4"       |
+        $sequence ""            <----+
+        $sequence "Sequence_8"       |
+        $sequence ""            <----+
+        $sequence "Sequence_2"       |
+        $sequence ""            <----+
+    */
+    void emptySequenceNames() {
+        Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MDL_HL1_MODELS_DIR "unnamed_sequences.mdl", aiProcess_ValidateDataStructure);
+        EXPECT_NE(nullptr, scene);
+
+        const std::vector<std::string> expected_sequence_names = {
+            "Sequence",
+            "Sequence_1",
+            "Sequence_0",
+            "Sequence_4",
+            "Sequence_3",
+            "Sequence_8",
+            "Sequence_5",
+            "Sequence_2",
+            "Sequence_6"
+        };
+
+        expect_named_children(scene, AI_MDL_HL1_NODE_SEQUENCE_INFOS, expected_sequence_names);
+    }
+
+    /*  Given a model with sequence groups that have duplicate names,
+        verify that each sequence group from the imported model has
+        a unique name.
+
+        "default"
+        $sequencegroup "SequenceGroup"    <----+
+        $sequencegroup "SequenceGroup_1"       |
+        $sequencegroup "SequenceGroup_5"  <----|--+
+        $sequencegroup "SequenceGroup"    -----+  |
+        $sequencegroup "SequenceGroup_0"       |  |
+        $sequencegroup "SequenceGroup"    -----+  |
+        $sequencegroup "SequenceGroup_5"  --------+
+        $sequencegroup "SequenceGroup_6"
+        $sequencegroup "SequenceGroup_2"
+    */
+    void duplicateSequenceGroupNames() {
+        Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MDL_HL1_MODELS_DIR "duplicate_sequence_groups/duplicate_sequence_groups.mdl", aiProcess_ValidateDataStructure);
+        EXPECT_NE(nullptr, scene);
+
+        const std::vector<std::string> expected_sequence_names = {
+            "default",
+            "SequenceGroup",
+            "SequenceGroup_1",
+            "SequenceGroup_5",
+            "SequenceGroup_3",
+            "SequenceGroup_0",
+            "SequenceGroup_4",
+            "SequenceGroup_5_0",
+            "SequenceGroup_6",
+            "SequenceGroup_2"
+        };
+
+        expect_named_children(scene, AI_MDL_HL1_NODE_SEQUENCE_GROUPS, expected_sequence_names);
+    }
+
+    /*  Given a model with sequence groups that have empty names,
+        verify that each sequence group from the imported model has
+        a unique name.
+
+        "default"
+        $sequencegroup ""                 <----+---- empty names
+        $sequencegroup "SequenceGroup_2"       |
+        $sequencegroup "SequenceGroup_6"       |
+        $sequencegroup ""                 <----+
+        $sequencegroup ""                 <----+
+        $sequencegroup "SequenceGroup_1"       |
+        $sequencegroup "SequenceGroup_5"       |
+        $sequencegroup ""                 <----+
+        $sequencegroup "SequenceGroup_4"
+    */
+    void emptySequenceGroupNames() {
+        Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MDL_HL1_MODELS_DIR "unnamed_sequence_groups/unnamed_sequence_groups.mdl", aiProcess_ValidateDataStructure);
+        EXPECT_NE(nullptr, scene);
+
+        const std::vector<std::string> expected_sequence_names = {
+            "default",
+            "SequenceGroup",
+            "SequenceGroup_2",
+            "SequenceGroup_6",
+            "SequenceGroup_0",
+            "SequenceGroup_3",
+            "SequenceGroup_1",
+            "SequenceGroup_5",
+            "SequenceGroup_7",
+            "SequenceGroup_4"
+        };
+
+        expect_named_children(scene, AI_MDL_HL1_NODE_SEQUENCE_GROUPS, expected_sequence_names);
+    }
+
+    /*  Verify that mOffsetMatrix applies the correct
+        inverse bind pose transform. */
+    void offsetMatrixUnappliesTransformations() {
+
+        const float TOLERANCE = 0.01f;
+
+        Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile(MDL_HL1_FILE_MAN, aiProcess_ValidateDataStructure);
+        EXPECT_NE(nullptr, scene);
+
+        aiNode *scene_bones_node = scene->mRootNode->FindNode(AI_MDL_HL1_NODE_BONES);
+
+        const aiMatrix4x4 identity_matrix;
+
+        for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
+            aiMesh *scene_mesh = scene->mMeshes[i];
+            for (unsigned int j = 0; j < scene_mesh->mNumBones; ++j) {
+                aiBone *scene_mesh_bone = scene_mesh->mBones[j];
+
+                // Store local node transforms.
+                aiNode *n = scene_bones_node->FindNode(scene_mesh_bone->mName);
+                std::vector<aiMatrix4x4> bone_matrices = { n->mTransformation };
+                while (n->mParent != scene->mRootNode) {
+                    n = n->mParent;
+                    bone_matrices.push_back(n->mTransformation);
+                }
+
+                // Compute absolute node transform.
+                aiMatrix4x4 transform;
+                for (auto it = bone_matrices.rbegin(); it != bone_matrices.rend(); ++it)
+                    transform *= *it;
+
+                // Unapply the transformation using the offset matrix.
+                aiMatrix4x4 unapplied_transform = scene_mesh_bone->mOffsetMatrix * transform;
+
+                // Ensure that we have, approximatively, the identity matrix.
+                expect_equal_matrices(identity_matrix, unapplied_transform, TOLERANCE);
+            }
+        }
+    }
+
+private:
+    void expect_named_children(const aiNode *parent_node, const std::vector<std::string> &expected_names) {
+        EXPECT_NE(nullptr, parent_node);
+        EXPECT_EQ(expected_names.size(), parent_node->mNumChildren);
+
+        for (unsigned int i = 0; i < parent_node->mNumChildren; ++i)
+            EXPECT_EQ(expected_names[i], parent_node->mChildren[i]->mName.C_Str());
+    }
+
+    void expect_named_children(const aiScene *scene, const char *node_name, const std::vector<std::string> &expected_names) {
+        const aiNode *node = scene->mRootNode->FindNode(node_name);
+        expect_named_children(scene->mRootNode->FindNode(node_name), expected_names);
+    }
+
+    void expect_equal_matrices(const aiMatrix4x4 &expected, const aiMatrix4x4 &actual, float abs_error) {
+        for (int i = 0; i < 4; ++i) {
+            for (int j = 0; j < 4; ++j)
+                EXPECT_NEAR(expected[i][j], actual[i][j], abs_error);
+        }
+    }
+};
+
+TEST_F(utMDLImporter_HL1_Nodes, emptyBonesNames) {
+    emptyBonesNames();
+}
+
+TEST_F(utMDLImporter_HL1_Nodes, emptyBodypartsNames) {
+    emptyBodypartsNames();
+}
+
+TEST_F(utMDLImporter_HL1_Nodes, duplicateBodypartsNames) {
+    duplicateBodypartsNames();
+}
+
+TEST_F(utMDLImporter_HL1_Nodes, duplicateSubModelsNames) {
+    duplicateSubModelsNames();
+}
+
+TEST_F(utMDLImporter_HL1_Nodes, emptySequenceNames) {
+    emptySequenceNames();
+}
+
+TEST_F(utMDLImporter_HL1_Nodes, duplicateSequenceNames) {
+    duplicateSequenceNames();
+}
+
+TEST_F(utMDLImporter_HL1_Nodes, emptySequenceGroupNames) {
+    emptySequenceGroupNames();
+}
+
+TEST_F(utMDLImporter_HL1_Nodes, duplicateSequenceGroupNames) {
+    duplicateSequenceGroupNames();
+}
+
+TEST_F(utMDLImporter_HL1_Nodes, offsetMatrixUnappliesTransformations) {
+    offsetMatrixUnappliesTransformations();
+}

+ 71 - 0
test/unit/ImportExport/utMDLImporter.cpp

@@ -0,0 +1,71 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#include "UnitTestPCH.h"
+
+#include "AbstractImportExportBase.h"
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+#include <assimp/Importer.hpp>
+
+#include "MDL/MDLHL1TestFiles.h"
+
+using namespace Assimp;
+
+class utMDLImporter : public AbstractImportExportBase {
+public:
+    virtual bool importerTest() {
+
+        Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile(MDL_HL1_FILE_MAN, 0);
+        EXPECT_NE(nullptr, scene);
+
+        // Add further MDL tests...
+
+        return true;
+    }
+};
+
+TEST_F(utMDLImporter, importMDLFromFileTest) {
+    EXPECT_TRUE(importerTest());
+}