2
0
Эх сурвалжийг харах

Merge branch 'master' into master

Kim Kulling 2 жил өмнө
parent
commit
a259277498
52 өөрчлөгдсөн 507 нэмэгдсэн , 95 устгасан
  1. 128 0
      CODE_OF_CONDUCT.md
  2. 18 22
      Readme.md
  3. 1 1
      code/AssetLib/FBX/FBXConverter.cpp
  4. 14 13
      code/AssetLib/glTF/glTFAsset.h
  5. 1 1
      code/AssetLib/glTF2/glTF2Asset.h
  6. 25 11
      code/AssetLib/glTF2/glTF2Asset.inl
  7. 77 36
      code/AssetLib/glTF2/glTF2Importer.cpp
  8. 63 1
      code/CMakeLists.txt
  9. 2 1
      contrib/unzip/crypt.c
  10. 9 1
      contrib/zlib/CMakeLists.txt
  11. BIN
      test/models-nonbsd/BLEND/guard1_body.png
  12. BIN
      test/models-nonbsd/BLEND/guard1_face.png
  13. BIN
      test/models-nonbsd/BLEND/guard1_helmet.png
  14. BIN
      test/models-nonbsd/BLEND/iron_grill.png
  15. BIN
      test/models-nonbsd/BLEND/round_grill.png
  16. BIN
      test/models-nonbsd/IRR/skybox.xml
  17. BIN
      test/models-nonbsd/IRR/skybox_UTF16LE.xml
  18. BIN
      test/models/COB/axe.jpg
  19. BIN
      test/models/COB/dwarf.jpg
  20. BIN
      test/models/COB/dwarf2.jpg
  21. BIN
      test/models/IRR/1.png
  22. BIN
      test/models/IRR/EpisodeII_TheDwarfesStrikeBack.irr
  23. BIN
      test/models/IRR/EpisodeII_TheDwarfesStrikeBack_UTF16LE.irr
  24. BIN
      test/models/IRR/EpisodeI_ANewDwarf.irr
  25. BIN
      test/models/IRR/EpisodeI_ANewDwarf_UTF16LE.irr
  26. BIN
      test/models/IRR/animMesh.irr
  27. BIN
      test/models/IRR/animMesh_UTF16LE.irr
  28. BIN
      test/models/IRR/box.irr
  29. BIN
      test/models/IRR/box_UTF16LE.irr
  30. BIN
      test/models/IRR/brownground_1-1.jpg
  31. BIN
      test/models/IRR/crackedground_1-6.jpg
  32. BIN
      test/models/IRR/dawfInCellar_ChildOfCellar.irr
  33. BIN
      test/models/IRR/dawfInCellar_ChildOfCellar_UTF16LE.irr
  34. BIN
      test/models/IRR/dawfInCellar_SameHierarchy.irr
  35. BIN
      test/models/IRR/dawfInCellar_SameHierarchy_UTF16LE.irr
  36. BIN
      test/models/IRR/multipleAnimators.irr
  37. BIN
      test/models/IRR/multipleAnimators_UTF16LE.irr
  38. BIN
      test/models/IRR/scenegraphAnim.irr
  39. BIN
      test/models/IRR/scenegraphAnim_UTF16LE.irr
  40. BIN
      test/models/IRR/sphere.irr
  41. BIN
      test/models/IRR/sphere_UTF16LE.irr
  42. BIN
      test/models/IRRMesh/cellar.irrmesh
  43. BIN
      test/models/IRRMesh/cellar_UTF16LE.irrmesh
  44. BIN
      test/models/IRRMesh/spider.irrmesh
  45. BIN
      test/models/IRRMesh/spider_UTF16LE.irrmesh
  46. BIN
      test/models/IRRMesh/testFormatDetection.xml
  47. BIN
      test/models/IRRMesh/testFormatDetection_UTF16LE.xml
  48. 21 0
      test/unit/ut3DImportExport.cpp
  49. 112 0
      test/unit/ut3DSImportExport.cpp
  50. 15 1
      test/unit/utBVHImportExport.cpp
  51. 14 0
      test/unit/utDXFImporterExporter.cpp
  52. 7 7
      test/unit/utglTF2ImportExport.cpp

+ 128 - 0
CODE_OF_CONDUCT.md

@@ -0,0 +1,128 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, religion, or sexual identity
+and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+  and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the
+  overall community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or
+  advances of any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email
+  address, without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+  professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
+.
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series
+of actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or
+permanent ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior,  harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within
+the community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.0, available at
+https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
+
+Community Impact Guidelines were inspired by [Mozilla's code of conduct
+enforcement ladder](https://github.com/mozilla/diversity).
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see the FAQ at
+https://www.contributor-covenant.org/faq. Translations are available at
+https://www.contributor-covenant.org/translations.

+ 18 - 22
Readme.md

@@ -1,6 +1,8 @@
 Open Asset Import Library (assimp)
 ==================================
-A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data.
+
+Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
+
 ### Current project status ###
 [![Financial Contributors on Open Collective](https://opencollective.com/assimp/all/badge.svg?label=financial+contributors)](https://opencollective.com/assimp) 
 ![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg)
@@ -22,15 +24,19 @@ Additionally, assimp features various __mesh post processing tools__: normals an
 ### Latest Doc's ###
 Please check the latest documents at [Asset-Importer-Lib-Doc](https://assimp-docs.readthedocs.io/en/latest/). 
 
-### Get involved ###
-This is the development repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases).
-<br>
-You find a bug in the docs? Use [Doc-Repo](https://github.com/assimp/assimp-docs).
-<br>
-Please check our Wiki as well: https://github.com/assimp/assimp/wiki
+### Prebuild binaries ###
+Please check our [Itchi Projectspace](https://kimkulling.itch.io/the-asset-importer-lib)
 
 If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb
 
+### Communities ###
+- Ask a question at [The Assimp-Discussion Board](https://github.com/assimp/assimp/discussions)
+- Ask on [Assimp-Community on Reddit](https://www.reddit.com/r/Assimp/)
+- Ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). 
+- Nothing has worked? File a question or an issue-report at [The Assimp-Issue Tracker](https://github.com/assimp/assimp/issues)
+
+And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
+
 #### Supported file formats ####
 You can find the complete list of supported file-formats [here](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md)
 
@@ -65,28 +71,18 @@ Open Asset Import Library is implemented in C++. The directory structure looks l
 	/port		Ports to other languages and scripts to maintain those.
 	/test		Unit- and regression tests, test suite of models
 	/tools		Tools (old assimp viewer, command line `assimp`)
-	/samples	A small number of samples to illustrate possible
-                        use cases for Assimp
+	/samples	A small number of samples to illustrate possible use-cases for Assimp
 
 The source code is organized in the following way:
 
 	code/Common			The base implementation for importers and the infrastructure
+	code/CApi                       Special implementations which are only used for the C-API
+	code/Geometry                   A collection of geometry tools
+	code/Material                   The material system
+	code/PBR                        An exporter for physical based models
 	code/PostProcessing		The post-processing steps
 	code/AssetLib/<FormatName>	Implementation for import and export for the format
 
-### Where to get help ###
-To find our documentation, visit [our website](https://assimp.org/) or check out [Wiki](https://github.com/assimp/assimp/wiki)
-
-If the docs don't solve your problem, you can:
-- Ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). 
-- Ask on [Assimp-Community on Reddit](https://www.reddit.com/r/Assimp/)
-- Ask a question at [The Assimp-Discussion Board](https://github.com/assimp/assimp/discussions)
-- Nothing has worked? File a question or an issue-report at [The Assimp-Issue Tracker](https://github.com/assimp/assimp/issues)
-
-Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
-
-And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
-
 ### Contributing ###
 Contributions to assimp are highly appreciated. The easiest way to get involved is to submit
 a pull request with your changes against the main repository's `master` branch.

+ 1 - 1
code/AssetLib/FBX/FBXConverter.cpp

@@ -652,7 +652,7 @@ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rot
 bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
     const PropertyTable &props = model.Props();
 
-    const auto zero_epsilon = ai_epsilon;
+    const auto zero_epsilon = Math::getEpsilon<ai_real>();
     const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
     for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
         const TransformationComp comp = static_cast<TransformationComp>(i);

+ 14 - 13
code/AssetLib/glTF/glTFAsset.h

@@ -513,21 +513,22 @@ struct Camera : public Object {
     };
 
     Type type;
+    struct Perspective {
+        float aspectRatio; //!<The floating - point aspect ratio of the field of view. (0 = undefined = use the canvas one)
+        float yfov; //!<The floating - point vertical field of view in radians. (required)
+        float zfar; //!<The floating - point distance to the far clipping plane. (required)
+        float znear; //!< The floating - point distance to the near clipping plane. (required)
+    };
 
+    struct Ortographic {
+        float xmag; //! The floating-point horizontal magnification of the view. (required)
+        float ymag; //! The floating-point vertical magnification of the view. (required)
+        float zfar; //! The floating-point distance to the far clipping plane. (required)
+        float znear; //! The floating-point distance to the near clipping plane. (required)
+    };
     union {
-        struct {
-            float aspectRatio; //!<The floating - point aspect ratio of the field of view. (0 = undefined = use the canvas one)
-            float yfov; //!<The floating - point vertical field of view in radians. (required)
-            float zfar; //!<The floating - point distance to the far clipping plane. (required)
-            float znear; //!< The floating - point distance to the near clipping plane. (required)
-        } perspective;
-
-        struct {
-            float xmag; //! The floating-point horizontal magnification of the view. (required)
-            float ymag; //! The floating-point vertical magnification of the view. (required)
-            float zfar; //! The floating-point distance to the far clipping plane. (required)
-            float znear; //! The floating-point distance to the near clipping plane. (required)
-        } ortographic;
+        struct Perspective perspective;
+        struct Ortographic ortographic;
     };
 
     Camera() = default;

+ 1 - 1
code/AssetLib/glTF2/glTF2Asset.h

@@ -565,7 +565,7 @@ struct Accessor : public Object {
     inline size_t GetMaxByteSize();
 
     template <class T>
-    void ExtractData(T *&outData);
+    size_t ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices = nullptr);
 
     void WriteData(size_t count, const void *src_buffer, size_t src_stride);
     void WriteSparseValues(size_t count, const void *src_data, size_t src_dataStride);

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

@@ -962,14 +962,15 @@ inline size_t Accessor::GetMaxByteSize() {
 }
 
 template <class T>
-void Accessor::ExtractData(T *&outData) {
+size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) {
     uint8_t *data = GetPointer();
     if (!data) {
         throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name));
     }
 
+    const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count;
     const size_t elemSize = GetElementSize();
-    const size_t totalSize = elemSize * count;
+    const size_t totalSize = elemSize * usedCount;
 
     const size_t stride = GetStride();
 
@@ -980,18 +981,31 @@ void Accessor::ExtractData(T *&outData) {
     }
 
     const size_t maxSize = GetMaxByteSize();
-    if (count * stride > maxSize) {
-        throw DeadlyImportError("GLTF: count*stride ", (count * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
-    }
 
-    outData = new T[count];
-    if (stride == elemSize && targetElemSize == elemSize) {
-        memcpy(outData, data, totalSize);
-    } else {
-        for (size_t i = 0; i < count; ++i) {
-            memcpy(outData + i, data + i * stride, elemSize);
+    outData = new T[usedCount];
+
+    if (remappingIndices != nullptr) {
+        const unsigned int maxIndex = static_cast<unsigned int>(maxSize / stride - 1);
+        for (size_t i = 0; i < usedCount; ++i) {
+            size_t srcIdx = (*remappingIndices)[i];
+            if (srcIdx > maxIndex) {
+                throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
+            }
+            memcpy(outData + i, data + srcIdx * stride, elemSize);
+        }
+    } else { // non-indexed cases
+        if (usedCount * stride > maxSize) {
+            throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
+        }
+        if (stride == elemSize && targetElemSize == elemSize) {
+            memcpy(outData, data, totalSize);
+        } else {
+            for (size_t i = 0; i < usedCount; ++i) {
+                memcpy(outData + i, data + i * stride, elemSize);
+            }
         }
     }
+    return usedCount;
 }
 
 inline void Accessor::WriteData(size_t _count, const void *src_buffer, size_t src_stride) {

+ 77 - 36
code/AssetLib/glTF2/glTF2Importer.cpp

@@ -453,6 +453,11 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
     unsigned int k = 0;
     meshOffsets.clear();
 
+
+    std::vector<unsigned int> usedVertexIndices;
+    std::vector<unsigned int> reverseMappingIndices;
+    std::vector<unsigned int> indexBuffer;
+
     for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
         Mesh &mesh = r.meshes[m];
 
@@ -462,6 +467,50 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
         for (unsigned int p = 0; p < mesh.primitives.size(); ++p) {
             Mesh::Primitive &prim = mesh.primitives[p];
 
+            Mesh::Primitive::Attributes &attr = prim.attributes;
+
+            // Find out the maximum number of vertices:
+            size_t numAllVertices = 0;
+            if (!attr.position.empty() && attr.position[0]) {
+                numAllVertices = attr.position[0]->count;
+            }
+
+            // Extract used vertices:
+            bool useIndexBuffer = prim.indices;
+            std::vector<unsigned int>* vertexRemappingTable = nullptr;
+            if (useIndexBuffer) {
+                size_t count = prim.indices->count;
+                indexBuffer.resize(count);
+                usedVertexIndices.clear();
+                reverseMappingIndices.clear();
+                usedVertexIndices.reserve(count / 3); // this is a very rough heuristic to reduce re-allocations
+                vertexRemappingTable = &usedVertexIndices;
+                Accessor::Indexer data = prim.indices->GetIndexer();
+                if (!data.IsValid()) {
+                    throw DeadlyImportError("GLTF: Invalid accessor without data in mesh ", getContextForErrorMessages(mesh.id, mesh.name));
+                }
+
+                // Build the vertex remapping table and the modified index buffer (used later instead of the original one)
+                // In case no index buffer is used, the original vertex arrays are being used so no remapping is required in the first place.
+                const unsigned int unusedIndex = ~0u;
+                for (unsigned int i = 0; i < count; ++i) {
+                    unsigned int index = data.GetUInt(i);
+                    if (index >= numAllVertices) {
+                        // Out-of-range indices will be filtered out when adding the faces and then lead to a warning. At this stage, we just keep them.
+                        indexBuffer[i] = index;
+                        continue; 
+                    }
+                    if (index >= reverseMappingIndices.size()) {
+                        reverseMappingIndices.resize(index + 1, unusedIndex);
+                    }
+                    if (reverseMappingIndices[index] == unusedIndex) {
+                        reverseMappingIndices[index] = static_cast<unsigned int>(usedVertexIndices.size());
+                        usedVertexIndices.push_back(index);
+                    }
+                    indexBuffer[i] = reverseMappingIndices[index];
+                }
+            }
+
             aiMesh *aim = new aiMesh();
             meshes.push_back(std::unique_ptr<aiMesh>(aim));
 
@@ -491,28 +540,25 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
                 break;
             }
 
-            Mesh::Primitive::Attributes &attr = prim.attributes;
-
             if (!attr.position.empty() && attr.position[0]) {
-                aim->mNumVertices = static_cast<unsigned int>(attr.position[0]->count);
-                attr.position[0]->ExtractData(aim->mVertices);
+                aim->mNumVertices = static_cast<unsigned int>(attr.position[0]->ExtractData(aim->mVertices, vertexRemappingTable));
             }
 
             if (!attr.normal.empty() && attr.normal[0]) {
-                if (attr.normal[0]->count != aim->mNumVertices) {
+                    if (attr.normal[0]->count != numAllVertices) {
                     DefaultLogger::get()->warn("Normal count in mesh \"", mesh.name, "\" does not match the vertex count, normals ignored.");
                 } else {
-                    attr.normal[0]->ExtractData(aim->mNormals);
+                    attr.normal[0]->ExtractData(aim->mNormals, vertexRemappingTable);
 
                     // only extract tangents if normals are present
                     if (!attr.tangent.empty() && attr.tangent[0]) {
-                        if (attr.tangent[0]->count != aim->mNumVertices) {
+                        if (attr.tangent[0]->count != numAllVertices) {
                             DefaultLogger::get()->warn("Tangent count in mesh \"", mesh.name, "\" does not match the vertex count, tangents ignored.");
                         } else {
                             // generate bitangents from normals and tangents according to spec
                             Tangent *tangents = nullptr;
 
-                            attr.tangent[0]->ExtractData(tangents);
+                            attr.tangent[0]->ExtractData(tangents, vertexRemappingTable);
 
                             aim->mTangents = new aiVector3D[aim->mNumVertices];
                             aim->mBitangents = new aiVector3D[aim->mNumVertices];
@@ -529,7 +575,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
             }
 
             for (size_t c = 0; c < attr.color.size() && c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) {
-                if (attr.color[c]->count != aim->mNumVertices) {
+                if (attr.color[c]->count != numAllVertices) {
                     DefaultLogger::get()->warn("Color stream size in mesh \"", mesh.name,
                             "\" does not match the vertex count");
                     continue;
@@ -537,7 +583,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
 
                 auto componentType = attr.color[c]->componentType;
                 if (componentType == glTF2::ComponentType_FLOAT) {
-                    attr.color[c]->ExtractData(aim->mColors[c]);
+                    attr.color[c]->ExtractData(aim->mColors[c], vertexRemappingTable);
                 } else {
                     if (componentType == glTF2::ComponentType_UNSIGNED_BYTE) {
                         aim->mColors[c] = GetVertexColorsForType<unsigned char>(attr.color[c]);
@@ -552,13 +598,13 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
                     continue;
                 }
 
-                if (attr.texcoord[tc]->count != aim->mNumVertices) {
+                if (attr.texcoord[tc]->count != numAllVertices) {
                     DefaultLogger::get()->warn("Texcoord stream size in mesh \"", mesh.name,
                             "\" does not match the vertex count");
                     continue;
                 }
 
-                attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]);
+                attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc], vertexRemappingTable);
                 aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents();
 
                 aiVector3D *values = aim->mTextureCoords[tc];
@@ -583,11 +629,11 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
                     Mesh::Primitive::Target &target = targets[i];
 
                     if (needPositions) {
-                        if (target.position[0]->count != aim->mNumVertices) {
+                        if (target.position[0]->count != numAllVertices) {
                             ASSIMP_LOG_WARN("Positions of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count");
                         } else {
                             aiVector3D *positionDiff = nullptr;
-                            target.position[0]->ExtractData(positionDiff);
+                            target.position[0]->ExtractData(positionDiff, vertexRemappingTable);
                             for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
                                 aiAnimMesh.mVertices[vertexId] += positionDiff[vertexId];
                             }
@@ -595,11 +641,11 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
                         }
                     }
                     if (needNormals) {
-                        if (target.normal[0]->count != aim->mNumVertices) {
+                        if (target.normal[0]->count != numAllVertices) {
                             ASSIMP_LOG_WARN("Normals of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count");
                         } else {
                             aiVector3D *normalDiff = nullptr;
-                            target.normal[0]->ExtractData(normalDiff);
+                            target.normal[0]->ExtractData(normalDiff, vertexRemappingTable);
                             for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
                                 aiAnimMesh.mNormals[vertexId] += normalDiff[vertexId];
                             }
@@ -610,14 +656,14 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
                         if (!aiAnimMesh.HasNormals()) {
                             // prevent nullptr access to aiAnimMesh.mNormals below when no normals are available
                             ASSIMP_LOG_WARN("Bitangents of target ", i, " in mesh \"", mesh.name, "\" can't be computed, because mesh has no normals.");
-                        } else if (target.tangent[0]->count != aim->mNumVertices) {
+                        } else if (target.tangent[0]->count != numAllVertices) {
                             ASSIMP_LOG_WARN("Tangents of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count");
                         } else {
                             Tangent *tangent = nullptr;
-                            attr.tangent[0]->ExtractData(tangent);
+                            attr.tangent[0]->ExtractData(tangent, vertexRemappingTable);
 
                             aiVector3D *tangentDiff = nullptr;
-                            target.tangent[0]->ExtractData(tangentDiff);
+                            target.tangent[0]->ExtractData(tangentDiff, vertexRemappingTable);
 
                             for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; ++vertexId) {
                                 tangent[vertexId].xyz += tangentDiff[vertexId];
@@ -641,20 +687,15 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
             aiFace *facePtr = nullptr;
             size_t nFaces = 0;
 
-            if (prim.indices) {
-                size_t count = prim.indices->count;
-
-                Accessor::Indexer data = prim.indices->GetIndexer();
-                if (!data.IsValid()) {
-                    throw DeadlyImportError("GLTF: Invalid accessor without data in mesh ", getContextForErrorMessages(mesh.id, mesh.name));
-                }
+            if (useIndexBuffer) {
+                size_t count = indexBuffer.size();
 
                 switch (prim.mode) {
                 case PrimitiveMode_POINTS: {
                     nFaces = count;
                     facePtr = faces = new aiFace[nFaces];
                     for (unsigned int i = 0; i < count; ++i) {
-                        SetFaceAndAdvance1(facePtr, aim->mNumVertices, data.GetUInt(i));
+                        SetFaceAndAdvance1(facePtr, aim->mNumVertices, indexBuffer[i]);
                     }
                     break;
                 }
@@ -667,7 +708,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
                     }
                     facePtr = faces = new aiFace[nFaces];
                     for (unsigned int i = 0; i < count; i += 2) {
-                        SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1));
+                        SetFaceAndAdvance2(facePtr, aim->mNumVertices, indexBuffer[i], indexBuffer[i + 1]);
                     }
                     break;
                 }
@@ -676,12 +717,12 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
                 case PrimitiveMode_LINE_STRIP: {
                     nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
                     facePtr = faces = new aiFace[nFaces];
-                    SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1));
+                    SetFaceAndAdvance2(facePtr, aim->mNumVertices, indexBuffer[0], indexBuffer[1]);
                     for (unsigned int i = 2; i < count; ++i) {
-                        SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(i - 1), data.GetUInt(i));
+                        SetFaceAndAdvance2(facePtr, aim->mNumVertices, indexBuffer[i - 1], indexBuffer[i]);
                     }
                     if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop
-                        SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(static_cast<int>(count) - 1), faces[0].mIndices[0]);
+                        SetFaceAndAdvance2(facePtr, aim->mNumVertices, indexBuffer[static_cast<int>(count) - 1], faces[0].mIndices[0]);
                     }
                     break;
                 }
@@ -694,7 +735,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
                     }
                     facePtr = faces = new aiFace[nFaces];
                     for (unsigned int i = 0; i < count; i += 3) {
-                        SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
+                        SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[i], indexBuffer[i + 1], indexBuffer[i + 2]);
                     }
                     break;
                 }
@@ -705,10 +746,10 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
                         // The ordering is to ensure that the triangles are all drawn with the same orientation
                         if ((i + 1) % 2 == 0) {
                             // For even n, vertices n + 1, n, and n + 2 define triangle n
-                            SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2));
+                            SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[i + 1], indexBuffer[i], indexBuffer[i + 2]);
                         } else {
                             // For odd n, vertices n, n+1, and n+2 define triangle n
-                            SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
+                            SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[i], indexBuffer[i + 1], indexBuffer[i + 2]);
                         }
                     }
                     break;
@@ -716,9 +757,9 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
                 case PrimitiveMode_TRIANGLE_FAN:
                     nFaces = count - 2;
                     facePtr = faces = new aiFace[nFaces];
-                    SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
+                    SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[0], indexBuffer[1], indexBuffer[2]);
                     for (unsigned int i = 1; i < nFaces; ++i) {
-                        SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(i + 1), data.GetUInt(i + 2));
+                        SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[0], indexBuffer[i + 1], indexBuffer[i + 2]);
                     }
                     break;
                 }

+ 63 - 1
code/CMakeLists.txt

@@ -1195,7 +1195,69 @@ TARGET_USE_COMMON_OUTPUT_DIRECTORY(assimp)
 IF (ASSIMP_WARNINGS_AS_ERRORS)
   MESSAGE(STATUS "Treating all warnings as errors (for assimp library only)")
   IF (MSVC)
-    TARGET_COMPILE_OPTIONS(assimp PRIVATE /W4 /WX)
+
+    IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) # clang-cl
+      TARGET_COMPILE_OPTIONS(assimp PRIVATE -Wall -Werror
+        -Wno-unused-function
+        -Wno-microsoft-enum-value
+        -Wno-switch-enum
+        -Wno-covered-switch-default
+        -Wno-reserved-identifier
+        -Wno-c++98-compat-pedantic
+        -Wno-c++98-compat
+        -Wno-documentation
+        -Wno-documentation-unknown-command
+        -Wno-deprecated-dynamic-exception-spec
+        -Wno-undef
+        -Wno-suggest-destructor-override
+        -Wno-suggest-override
+        -Wno-inconsistent-missing-destructor-override
+        -Wno-zero-as-null-pointer-constant
+        -Wno-global-constructors
+        -Wno-exit-time-destructors
+        -Wno-extra-semi-stmt
+        -Wno-missing-prototypes
+        -Wno-old-style-cast
+        -Wno-cast-align
+        -Wno-cast-qual
+        -Wno-float-equal
+        -Wno-implicit-int-float-conversion
+        -Wno-sign-conversion
+        -Wno-implicit-float-conversion
+        -Wno-implicit-int-conversion
+        -Wno-float-conversion
+        -Wno-double-promotion
+        -Wno-unused-macros
+        -Wno-disabled-macro-expansion
+        -Wno-shadow-field
+        -Wno-shadow
+        -Wno-language-extension-token
+        -Wno-header-hygiene
+        -Wno-tautological-value-range-compare
+        -Wno-tautological-type-limit-compare
+        -Wno-missing-noreturn
+        -Wno-missing-variable-declarations
+        -Wno-extra-semi
+        -Wno-nonportable-system-include-path
+        -Wno-undefined-reinterpret-cast
+        -Wno-shift-sign-overflow
+        -Wno-deprecated-copy-with-user-provided-dtor
+        -Wno-deprecated-copy-with-dtor
+        -Wno-deprecated
+        -Wno-format-nonliteral
+        -Wno-format-non-iso
+        -Wno-comma
+        -Wno-unreachable-code-break
+        -Wno-unreachable-code-return
+        -Wno-unreachable-code
+        -Wno-implicit-fallthrough
+        -Wno-unused-template
+        -Wno-undefined-func-template
+        -Wno-declaration-after-statement
+      )
+    ELSE()
+      TARGET_COMPILE_OPTIONS(assimp PRIVATE /W4 /WX)
+    ENDIF()
   ELSE()
     TARGET_COMPILE_OPTIONS(assimp PRIVATE -Wall -Werror)
   ENDIF()

+ 2 - 1
contrib/unzip/crypt.c

@@ -103,7 +103,7 @@ int cryptrand(unsigned char *buf, unsigned int len)
     unsigned __int64 pentium_tsc[1];
     int result = 0;
 
-
+    #if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP
     if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
     {
         result = CryptGenRandom(provider, len, buf);
@@ -111,6 +111,7 @@ int cryptrand(unsigned char *buf, unsigned int len)
         if (result)
             return len;
     }
+    #endif
 
     for (rlen = 0; rlen < (int)len; ++rlen)
     {

+ 9 - 1
contrib/zlib/CMakeLists.txt

@@ -76,7 +76,15 @@ if(MSVC)
     set(CMAKE_DEBUG_POSTFIX "d")
     add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
     add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
+    if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) # clang-cl
+        SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-non-prototype")
+    endif()
+
     include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+else()
+    if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) # clang-cl
+        SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-non-prototype")
+    endif()
 endif()
 
 if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
@@ -88,7 +96,7 @@ if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
         message(STATUS "to 'zconf.h.included' because this file is included with zlib")
         message(STATUS "but CMake generates it automatically in the build directory.")
         file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included)
-  endif()
+    endif()
 endif()
 
 set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc)

BIN
test/models-nonbsd/BLEND/guard1_body.png


BIN
test/models-nonbsd/BLEND/guard1_face.png


BIN
test/models-nonbsd/BLEND/guard1_helmet.png


BIN
test/models-nonbsd/BLEND/iron_grill.png


BIN
test/models-nonbsd/BLEND/round_grill.png


BIN
test/models-nonbsd/IRR/skybox.xml


BIN
test/models-nonbsd/IRR/skybox_UTF16LE.xml


BIN
test/models/COB/axe.jpg


BIN
test/models/COB/dwarf.jpg


BIN
test/models/COB/dwarf2.jpg


BIN
test/models/IRR/1.png


BIN
test/models/IRR/EpisodeII_TheDwarfesStrikeBack.irr


BIN
test/models/IRR/EpisodeII_TheDwarfesStrikeBack_UTF16LE.irr


BIN
test/models/IRR/EpisodeI_ANewDwarf.irr


BIN
test/models/IRR/EpisodeI_ANewDwarf_UTF16LE.irr


BIN
test/models/IRR/animMesh.irr


BIN
test/models/IRR/animMesh_UTF16LE.irr


BIN
test/models/IRR/box.irr


BIN
test/models/IRR/box_UTF16LE.irr


BIN
test/models/IRR/brownground_1-1.jpg


BIN
test/models/IRR/crackedground_1-6.jpg


BIN
test/models/IRR/dawfInCellar_ChildOfCellar.irr


BIN
test/models/IRR/dawfInCellar_ChildOfCellar_UTF16LE.irr


BIN
test/models/IRR/dawfInCellar_SameHierarchy.irr


BIN
test/models/IRR/dawfInCellar_SameHierarchy_UTF16LE.irr


BIN
test/models/IRR/multipleAnimators.irr


BIN
test/models/IRR/multipleAnimators_UTF16LE.irr


BIN
test/models/IRR/scenegraphAnim.irr


BIN
test/models/IRR/scenegraphAnim_UTF16LE.irr


BIN
test/models/IRR/sphere.irr


BIN
test/models/IRR/sphere_UTF16LE.irr


BIN
test/models/IRRMesh/cellar.irrmesh


BIN
test/models/IRRMesh/cellar_UTF16LE.irrmesh


BIN
test/models/IRRMesh/spider.irrmesh


BIN
test/models/IRRMesh/spider_UTF16LE.irrmesh


BIN
test/models/IRRMesh/testFormatDetection.xml


BIN
test/models/IRRMesh/testFormatDetection_UTF16LE.xml


+ 21 - 0
test/unit/ut3DImportExport.cpp

@@ -65,3 +65,24 @@ TEST(ut3DImportExport, importBoxUC) {
     const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3D/box.uc", aiProcess_ValidateDataStructure);
     ASSERT_NE(nullptr, scene);
 }
+
+
+TEST(ut3DImportExport, importMarRifle) {
+    Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3D/mar_rifle.uc", aiProcess_ValidateDataStructure);
+    ASSERT_NE(nullptr, scene);
+}
+
+
+TEST(ut3DImportExport, importMarRifleA) {
+    Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3D/mar_rifle_a.3d", aiProcess_ValidateDataStructure);
+    ASSERT_NE(nullptr, scene);
+}
+
+
+TEST(ut3DImportExport, importMarRifleD) {
+    Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3D/mar_rifle_d.3d", aiProcess_ValidateDataStructure);
+    ASSERT_NE(nullptr, scene);
+}

+ 112 - 0
test/unit/ut3DSImportExport.cpp

@@ -70,3 +70,115 @@ TEST_F(ut3DSImportExport, import3DSformatdetection) {
 
     EXPECT_NE(nullptr, scene);
 }
+
+
+TEST_F(ut3DSImportExport, importCameraRollAnim) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/CameraRollAnim.3ds", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(ut3DSImportExport, importCameraRollAnimWithChildObject) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/CameraRollAnimWithChildObject.3ds", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(ut3DSImportExport, importCubesWithAlpha) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/cubes_with_alpha.3DS", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(ut3DSImportExport, importCubeWithDiffuseTexture) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/cube_with_diffuse_texture.3DS", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(ut3DSImportExport, importCubeWithSpecularTexture) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/cube_with_specular_texture.3DS", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(ut3DSImportExport, importRotatingCube) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/RotatingCube.3DS", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(ut3DSImportExport, importTargetCameraAnim) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/TargetCameraAnim.3ds", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(ut3DSImportExport, importTest1) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/test1.3ds", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(ut3DSImportExport, importCartWheel) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3DS/cart_wheel.3DS", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(ut3DSImportExport, importGranate) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3DS/Granate.3DS", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(ut3DSImportExport, importJeep1) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3DS/jeep1.3ds", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(ut3DSImportExport, importMarRifle) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3DS/mar_rifle.3ds", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(ut3DSImportExport, importMp5Sil) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3DS/mp5_sil.3ds", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(ut3DSImportExport, importPyramob) {
+    ::Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3DS/pyramob.3DS", aiProcess_ValidateDataStructure);
+
+    EXPECT_NE(nullptr, scene);
+}

+ 15 - 1
test/unit/utBVHImportExport.cpp

@@ -55,6 +55,20 @@ public:
     }
 };
 
-TEST_F(utBVHImportExport, importBlenFromFileTest) {
+TEST_F(utBVHImportExport, import01_01) {
     EXPECT_TRUE(importerTest());
 }
+
+
+TEST_F(utBVHImportExport, import01_03) {
+    Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/BVH/01_03.bvh", aiProcess_ValidateDataStructure);
+    ASSERT_NE(nullptr, scene);
+}
+
+
+TEST_F(utBVHImportExport, importBoxingToes) {
+    Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/BVH/Boxing_Toes.bvh", aiProcess_ValidateDataStructure);
+    ASSERT_NE(nullptr, scene);
+}

+ 14 - 0
test/unit/utDXFImporterExporter.cpp

@@ -71,3 +71,17 @@ TEST_F(utDXFImporterExporter, issue2229) {
     const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/DXF/issue_2229.dxf", aiProcess_ValidateDataStructure);
     EXPECT_NE(nullptr, scene);
 }
+
+
+TEST_F(utDXFImporterExporter, importWuson) {
+    Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/DXF/wuson.dxf", aiProcess_ValidateDataStructure);
+    EXPECT_NE(nullptr, scene);
+}
+
+
+TEST_F(utDXFImporterExporter, importRifle) {
+    Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/DXF/rifle.dxf", aiProcess_ValidateDataStructure);
+    EXPECT_NE(nullptr, scene);
+}

+ 7 - 7
test/unit/utglTF2ImportExport.cpp

@@ -380,7 +380,7 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLines) {
     const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_08.gltf", aiProcess_ValidateDataStructure);
     EXPECT_NE(nullptr, scene);
     EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
-    std::array<unsigned int, 5> l1 = { { 0u, 3u, 2u, 1u, 0u } };
+    std::array<unsigned int, 5> l1 = { { 0u, 1u, 2u, 3u, 0u } };
     EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
     for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
         EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
@@ -394,7 +394,7 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLineLoop) {
     const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_09.gltf", aiProcess_ValidateDataStructure);
     EXPECT_NE(nullptr, scene);
     EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
-    std::array<unsigned int, 5> l1 = { { 0, 3u, 2u, 1u, 0u } };
+    std::array<unsigned int, 5> l1 = { { 0, 1u, 2u, 3u, 0u } };
     EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
     for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
         EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
@@ -408,7 +408,7 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLineStrip) {
     const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_10.gltf", aiProcess_ValidateDataStructure);
     EXPECT_NE(nullptr, scene);
     EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
-    std::array<unsigned int, 5> l1 = { { 0u, 3u, 2u, 1u, 0u } };
+    std::array<unsigned int, 5> l1 = { { 0u, 1u, 2u, 3u, 0u } };
     EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
     for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
         EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
@@ -423,13 +423,13 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesStrip) {
     EXPECT_NE(nullptr, scene);
     EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
     EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
-    std::array<unsigned int, 3> f1 = { { 0u, 3u, 1u } };
+    std::array<unsigned int, 3> f1 = { { 0u, 1u, 2u } };
     EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
     for (size_t i = 0; i < 3; ++i) {
         EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
     }
 
-    std::array<unsigned int, 3> f2 = { { 1u, 3u, 2u } };
+    std::array<unsigned int, 3> f2 = { { 2u, 1u, 3u } };
     EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
     for (size_t i = 0; i < 3; ++i) {
         EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
@@ -443,13 +443,13 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesFan) {
     EXPECT_NE(nullptr, scene);
     EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
     EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
-    std::array<unsigned int, 3> f1 = { { 0u, 3u, 2u } };
+    std::array<unsigned int, 3> f1 = { { 0u, 1u, 2u } };
     EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
     for (size_t i = 0; i < 3; ++i) {
         EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
     }
 
-    std::array<unsigned int, 3> f2 = { { 0u, 2u, 1u } };
+    std::array<unsigned int, 3> f2 = { { 0u, 2u, 3u } };
     EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
     for (size_t i = 0; i < 3; ++i) {
         EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);