Browse Source

Merge branch 'master' into patch-3

Jason C 4 years ago
parent
commit
f5a31b70f5

+ 3 - 2
code/AssetLib/3DS/3DSExporter.cpp

@@ -102,13 +102,14 @@ private:
 // preserves the mesh's given name if it has one. |index| is the index
 // of the mesh in |aiScene::mMeshes|.
 std::string GetMeshName(const aiMesh &mesh, unsigned int index, const aiNode &node) {
-    static const std::string underscore = "_";
+    static const char underscore = '_';
     char postfix[10] = { 0 };
     ASSIMP_itoa10(postfix, index);
 
     std::string result = node.mName.C_Str();
     if (mesh.mName.length > 0) {
-        result += underscore + mesh.mName.C_Str();
+        result += underscore;
+        result += mesh.mName.C_Str();
     }
     return result + underscore + postfix;
 }

+ 3 - 13
code/AssetLib/3DS/3DSHelper.h

@@ -61,20 +61,10 @@ namespace D3DS {
 #include <assimp/Compiler/pushpack1.h>
 
 // ---------------------------------------------------------------------------
-/** Discreet3DS class: Helper class for loading 3ds files. Defines chunks
-*  and data structures.
+/** Defines chunks and data structures.
 */
-class Discreet3DS {
-private:
-    Discreet3DS() AI_NO_EXCEPT {
-        // empty
-    }
-
-    ~Discreet3DS() {
-        // empty
-    }
+namespace Discreet3DS {
 
-public:
     //! data structure for a single chunk in a .3ds file
     struct Chunk {
         uint16_t Flag;
@@ -314,7 +304,7 @@ public:
         // camera sub-chunks
         CHUNK_CAM_RANGES = 0x4720
     };
-};
+}
 
 // ---------------------------------------------------------------------------
 /** Helper structure representing a 3ds mesh face */

+ 53 - 50
code/AssetLib/3MF/3MFXmlTags.h

@@ -44,63 +44,66 @@ namespace Assimp {
 namespace D3MF {
 
 namespace XmlTag {
+    // Root tag
+    const char* const RootTag = "3MF";
+
     // Meta-data
-    static const std::string meta = "metadata";
-    static const std::string meta_name = "name";
+    const char* const meta = "metadata";
+    const char* const meta_name = "name";
 
     // Model-data specific tags
-    static const std::string model = "model";
-    static const std::string model_unit = "unit";
-    static const std::string metadata = "metadata";
-    static const std::string resources = "resources";
-    static const std::string object = "object";
-    static const std::string mesh = "mesh";
-    static const std::string components = "components";
-    static const std::string component = "component";
-    static const std::string vertices = "vertices";
-    static const std::string vertex = "vertex";
-    static const std::string triangles = "triangles";
-    static const std::string triangle = "triangle";
-    static const std::string x = "x";
-    static const std::string y = "y";
-    static const std::string z = "z";
-    static const std::string v1 = "v1";
-    static const std::string v2 = "v2";
-    static const std::string v3 = "v3";
-    static const std::string id = "id";
-    static const std::string pid = "pid";
-    static const std::string pindex = "pindex";
-    static const std::string p1 = "p1";
-    static const std::string name = "name";
-    static const std::string type = "type";
-    static const std::string build = "build";
-    static const std::string item = "item";
-    static const std::string objectid = "objectid";
-    static const std::string transform = "transform";
+    const char* const model = "model";
+    const char* const model_unit = "unit";
+    const char* const metadata = "metadata";
+    const char* const resources = "resources";
+    const char* const object = "object";
+    const char* const mesh = "mesh";
+    const char* const components = "components";
+    const char* const component = "component";
+    const char* const vertices = "vertices";
+    const char* const vertex = "vertex";
+    const char* const triangles = "triangles";
+    const char* const triangle = "triangle";
+    const char* const x = "x";
+    const char* const y = "y";
+    const char* const z = "z";
+    const char* const v1 = "v1";
+    const char* const v2 = "v2";
+    const char* const v3 = "v3";
+    const char* const id = "id";
+    const char* const pid = "pid";
+    const char* const pindex = "pindex";
+    const char* const p1 = "p1";
+    const char* const name = "name";
+    const char* const type = "type";
+    const char* const build = "build";
+    const char* const item = "item";
+    const char* const objectid = "objectid";
+    const char* const transform = "transform";
 
     // Material definitions
-    static const std::string basematerials = "basematerials";
-    static const std::string basematerials_id = "id";
-    static const std::string basematerials_base = "base";
-    static const std::string basematerials_name = "name";
-    static const std::string basematerials_displaycolor = "displaycolor";
+    const char* const basematerials = "basematerials";
+    const char* const basematerials_id = "id";
+    const char* const basematerials_base = "base";
+    const char* const basematerials_name = "name";
+    const char* const basematerials_displaycolor = "displaycolor";
 
     // Meta info tags
-    static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
-    static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
-    static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
-    static const std::string SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
-    static const std::string RELS_RELATIONSHIP_CONTAINER = "Relationships";
-    static const std::string RELS_RELATIONSHIP_NODE = "Relationship";
-    static const std::string RELS_ATTRIB_TARGET = "Target";
-    static const std::string RELS_ATTRIB_TYPE = "Type";
-    static const std::string RELS_ATTRIB_ID = "Id";
-    static const std::string PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
-    static const std::string PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
-    static const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
-    static const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
-    static const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
-}
+    const char* const CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
+    const char* const ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
+    const char* const SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
+    const char* const SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
+    const char* const RELS_RELATIONSHIP_CONTAINER = "Relationships";
+    const char* const RELS_RELATIONSHIP_NODE = "Relationship";
+    const char* const RELS_ATTRIB_TARGET = "Target";
+    const char* const RELS_ATTRIB_TYPE = "Type";
+    const char* const RELS_ATTRIB_ID = "Id";
+    const char* const PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
+    const char* const PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
+    const char* const PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
+    const char* const PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
+    const char* const PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
+    }
 
 } // Namespace D3MF
 } // Namespace Assimp

+ 26 - 11
code/AssetLib/3MF/D3MFExporter.cpp

@@ -307,18 +307,26 @@ void D3MFExporter::writeMesh(aiMesh *mesh) {
         return;
     }
 
-    mModelOutput << "<" << XmlTag::mesh << ">" << std::endl;
-    mModelOutput << "<" << XmlTag::vertices << ">" << std::endl;
+    mModelOutput << "<"
+                 << XmlTag::mesh
+                 << ">" << "\n";
+    mModelOutput << "<"
+                 << XmlTag::vertices
+                 << ">" << "\n";
     for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
         writeVertex(mesh->mVertices[i]);
     }
-    mModelOutput << "</" << XmlTag::vertices << ">" << std::endl;
+    mModelOutput << "</"
+                 << XmlTag::vertices << ">"
+                 << "\n";
 
     const unsigned int matIdx(mesh->mMaterialIndex);
 
     writeFaces(mesh, matIdx);
 
-    mModelOutput << "</" << XmlTag::mesh << ">" << std::endl;
+    mModelOutput << "</"
+                 << XmlTag::mesh << ">"
+                 << "\n";
 }
 
 void D3MFExporter::writeVertex(const aiVector3D &pos) {
@@ -334,27 +342,34 @@ void D3MFExporter::writeFaces(aiMesh *mesh, unsigned int matIdx) {
     if (!mesh->HasFaces()) {
         return;
     }
-    mModelOutput << "<" << XmlTag::triangles << ">" << std::endl;
+    mModelOutput << "<"
+                 << XmlTag::triangles << ">"
+                 << "\n";
     for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
         aiFace &currentFace = mesh->mFaces[i];
         mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[0] << "\" v2=\""
                      << currentFace.mIndices[1] << "\" v3=\"" << currentFace.mIndices[2]
                      << "\" pid=\"1\" p1=\"" + ai_to_string(matIdx) + "\" />";
-        mModelOutput << std::endl;
+        mModelOutput << "\n";
     }
-    mModelOutput << "</" << XmlTag::triangles << ">";
-    mModelOutput << std::endl;
+    mModelOutput << "</"
+                 << XmlTag::triangles
+                 << ">";
+    mModelOutput << "\n";
 }
 
 void D3MFExporter::writeBuild() {
-    mModelOutput << "<" << XmlTag::build << ">" << std::endl;
+    mModelOutput << "<"
+                 << XmlTag::build
+                 << ">"
+                 << "\n";
 
     for (size_t i = 0; i < mBuildItems.size(); ++i) {
         mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 2 << "\"/>";
-        mModelOutput << std::endl;
+        mModelOutput << "\n";
     }
     mModelOutput << "</" << XmlTag::build << ">";
-    mModelOutput << std::endl;
+    mModelOutput << "\n";
 }
 
 void D3MFExporter::zipContentType(const std::string &filename) {

+ 107 - 99
code/AssetLib/3MF/D3MFImporter.cpp

@@ -42,6 +42,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
 
 #include "D3MFImporter.h"
+#include "3MFXmlTags.h"
+#include "D3MFOpcPackage.h"
 
 #include <assimp/StringComparison.h>
 #include <assimp/StringUtils.h>
@@ -51,17 +53,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/scene.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/IOSystem.hpp>
+#include <assimp/fast_atof.h>
+
 #include <cassert>
 #include <map>
 #include <memory>
 #include <string>
 #include <vector>
-
-#include "3MFXmlTags.h"
-#include "D3MFOpcPackage.h"
-#include <assimp/fast_atof.h>
-
 #include <iomanip>
+#include <string.h>
 
 namespace Assimp {
 namespace D3MF {
@@ -72,32 +72,39 @@ enum class ResourceType {
     RT_Unknown
 }; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...)
 
-class Resource
-{
+class Resource {
 public:
-    Resource(int id) :
-            mId(id) {}
+    int mId;
 
-    virtual ~Resource() {}
+    Resource(int id) :
+            mId(id) {
+        // empty
+    }
 
-    int mId;
+    virtual ~Resource() {
+        // empty
+    }
 
-    virtual ResourceType getType() {
+    virtual ResourceType getType() const {
         return ResourceType::RT_Unknown;
     }
 };
 
 class BaseMaterials : public Resource {
 public:
+    std::vector<aiMaterial *> mMaterials;
+    std::vector<unsigned int> mMaterialIndex;
+
     BaseMaterials(int id) :
             Resource(id),
             mMaterials(),
-            mMaterialIndex() {}
+            mMaterialIndex() {
+        // empty
+    }
 
-    std::vector<aiMaterial *> mMaterials;
-    std::vector<unsigned int> mMaterialIndex;
+    ~BaseMaterials() = default;
 
-    virtual ResourceType getType() {
+    ResourceType getType() const override {
         return ResourceType::RT_BaseMaterials;
     }
 };
@@ -109,24 +116,26 @@ struct Component {
 
 class Object : public Resource {
 public:
-    std::vector<aiMesh*> mMeshes;
+    std::vector<aiMesh *> mMeshes;
     std::vector<unsigned int> mMeshIndex;
     std::vector<Component> mComponents;
     std::string mName;
 
     Object(int id) :
             Resource(id),
-            mName(std::string("Object_") + ai_to_string(id)) {}
+            mName(std::string("Object_") + ai_to_string(id)) {
+        // empty
+    }
+
+    ~Object() = default;
 
-    virtual ResourceType getType() {
+    ResourceType getType() const override {
         return ResourceType::RT_Object;
     }
 };
 
-
 class XmlSerializer {
 public:
-
     XmlSerializer(XmlParser *xmlParser) :
             mResourcesDictionnary(),
             mMaterialCount(0),
@@ -136,7 +145,7 @@ public:
     }
 
     ~XmlSerializer() {
-        for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) {
+        for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it ) {
             delete it->second;
         }
     }
@@ -146,28 +155,28 @@ public:
             return;
         }
 
-        scene->mRootNode = new aiNode("3MF");
+        scene->mRootNode = new aiNode(XmlTag::RootTag);
 
-        XmlNode node = mXmlParser->getRootNode().child("model");
+        XmlNode node = mXmlParser->getRootNode().child(XmlTag::model);
         if (node.empty()) {
             return;
         }
-        XmlNode resNode = node.child("resources");
-        for (XmlNode currentNode = resNode.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-            const std::string &currentNodeName = currentNode.name();
-            if (currentNodeName == D3MF::XmlTag::object) {
-                ReadObject(currentNode);;
-            } else if (currentNodeName == D3MF::XmlTag::basematerials) {
+        XmlNode resNode = node.child(XmlTag::resources);
+        for (auto &currentNode : resNode.children()) {
+            const std::string currentNodeName = currentNode.name();
+            if (currentNodeName == XmlTag::object) {
+                ReadObject(currentNode);
+            } else if (currentNodeName == XmlTag::basematerials) {
                 ReadBaseMaterials(currentNode);
-            } else if (currentNodeName == D3MF::XmlTag::meta) {
+            } else if (currentNodeName == XmlTag::meta) {
                 ReadMetadata(currentNode);
             }
         }
 
-        XmlNode buildNode = node.child("build");
-        for (XmlNode currentNode = buildNode.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-            const std::string &currentNodeName = currentNode.name();
-            if (currentNodeName == D3MF::XmlTag::item) {
+        XmlNode buildNode = node.child(XmlTag::build);
+        for (auto &currentNode : buildNode.children()) {
+            const std::string currentNodeName = currentNode.name();
+            if (currentNodeName == XmlTag::item) {
                 int objectId = -1;
                 std::string transformationMatrixStr;
                 aiMatrix4x4 transformationMatrix;
@@ -186,10 +195,9 @@ public:
             }
         }
 
-
         // import the metadata
         if (!mMetaData.empty()) {
-            const size_t numMeta(mMetaData.size());
+            const size_t numMeta = mMetaData.size();
             scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
             for (size_t i = 0; i < numMeta; ++i) {
                 aiString val(mMetaData[i].value);
@@ -201,22 +209,22 @@ public:
         scene->mNumMeshes = static_cast<unsigned int>(mMeshCount);
         if (scene->mNumMeshes != 0) {
             scene->mMeshes = new aiMesh *[scene->mNumMeshes]();
-            for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) {
+            for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
                 if (it->second->getType() == ResourceType::RT_Object) {
-                    Object *obj = static_cast<Object*>(it->second);
+                    Object *obj = static_cast<Object *>(it->second);
+                    ai_assert(nullptr != obj);
                     for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) {
                         scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i];
                     }
                 }
             }
         }
-        
 
         // import the materials
-        scene->mNumMaterials = static_cast<unsigned int>(mMaterialCount);
+        scene->mNumMaterials = mMaterialCount;
         if (scene->mNumMaterials != 0) {
             scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
-            for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) {
+            for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
                 if (it->second->getType() == ResourceType::RT_BaseMaterials) {
                     BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
                     for (unsigned int i = 0; i < baseMaterials->mMaterials.size(); ++i) {
@@ -228,35 +236,36 @@ public:
     }
 
 private:
+    void addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform) {
+        ai_assert(nullptr != obj);
 
-    void addObjectToNode(aiNode* parent, Object* obj, aiMatrix4x4 nodeTransform) {
         aiNode *sceneNode = new aiNode(obj->mName);
         sceneNode->mNumMeshes = static_cast<unsigned int>(obj->mMeshes.size());
         sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes];
         std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes);
 
         sceneNode->mTransformation = nodeTransform;
-
-        parent->addChildren(1, &sceneNode);
+        if (nullptr != parent) {
+            parent->addChildren(1, &sceneNode);
+        }
 
         for (size_t i = 0; i < obj->mComponents.size(); ++i) {
             Component c = obj->mComponents[i];
             auto it = mResourcesDictionnary.find(c.mObjectId);
             if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
-                addObjectToNode(sceneNode, static_cast<Object*>(it->second), c.mTransformation);
+                addObjectToNode(sceneNode, static_cast<Object *>(it->second), c.mTransformation);
             }
-            
         }
     }
 
-    bool getNodeAttribute(const XmlNode& node, const std::string& attribute, std::string& value) {
+    bool getNodeAttribute(const XmlNode &node, const std::string &attribute, std::string &value) {
         pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str());
         if (!objectAttribute.empty()) {
             value = objectAttribute.as_string();
             return true;
-        } else {
-            return false;
         }
+
+        return false;
     }
 
     bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) {
@@ -265,9 +274,9 @@ private:
         if (ret) {
             value = std::atoi(strValue.c_str());
             return true;
-        } else {
-            return false;
-        }
+        } 
+
+        return false;
     }
 
     aiMatrix4x4 parseTransformMatrix(std::string matrixStr) {
@@ -287,7 +296,7 @@ private:
             }
         }
         if (currentNumber.size() > 0) {
-            float f = std::stof(currentNumber);
+            const float f = std::stof(currentNumber);
             numbers.push_back(f);
         }
 
@@ -311,29 +320,26 @@ private:
         transformMatrix.b4 = numbers[10];
         transformMatrix.c4 = numbers[11];
         transformMatrix.d4 = 1;
+
         return transformMatrix;
     }
 
     void ReadObject(XmlNode &node) {
         int id = -1, pid = -1, pindex = -1;
-        bool hasId = getNodeAttribute(node, D3MF::XmlTag::id, id);
-        //bool hasType = getNodeAttribute(node, D3MF::XmlTag::type, type); not used currently
-        bool hasPid = getNodeAttribute(node, D3MF::XmlTag::pid, pid);
-        bool hasPindex = getNodeAttribute(node, D3MF::XmlTag::pindex, pindex);
-
-        std::string idStr = ai_to_string(id);
-
+        bool hasId = getNodeAttribute(node, XmlTag::id, id);
+        bool hasPid = getNodeAttribute(node, XmlTag::pid, pid);
+        bool hasPindex = getNodeAttribute(node, XmlTag::pindex, pindex);
         if (!hasId) {
             return;
         }
 
         Object *obj = new Object(id);
 
-        for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+        for (XmlNode &currentNode : node.children()) {
             const std::string &currentName = currentNode.name();
             if (currentName == D3MF::XmlTag::mesh) {
                 auto mesh = ReadMesh(currentNode);
-                mesh->mName.Set(idStr);
+                mesh->mName.Set(ai_to_string(id));
 
                 if (hasPid) {
                     auto it = mResourcesDictionnary.find(pid);
@@ -347,8 +353,9 @@ private:
                 obj->mMeshIndex.push_back(mMeshCount);
                 mMeshCount++;
             } else if (currentName == D3MF::XmlTag::components) {
-                for (XmlNode currentSubNode = currentNode.first_child(); currentSubNode; currentSubNode = currentSubNode.next_sibling()) {
-                    if (currentSubNode.name() == D3MF::XmlTag::component) {
+                for (XmlNode &currentSubNode : currentNode.children()) {
+                    const std::string subNodeName = currentSubNode.name();
+                    if (subNodeName == D3MF::XmlTag::component) {
                         int objectId = -1;
                         std::string componentTransformStr;
                         aiMatrix4x4 componentTransform;
@@ -356,8 +363,9 @@ private:
                             componentTransform = parseTransformMatrix(componentTransformStr);
                         }
 
-                        if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId))
+                        if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId)) {
                             obj->mComponents.push_back({ objectId, componentTransform });
+                        }
                     }
                 }
             }
@@ -369,21 +377,20 @@ private:
     aiMesh *ReadMesh(XmlNode &node) {
         aiMesh *mesh = new aiMesh();
 
-        for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-            const std::string &currentName = currentNode.name();
-            if (currentName == D3MF::XmlTag::vertices) {
+        for (XmlNode &currentNode : node.children()) {
+            const std::string currentName = currentNode.name();
+            if (currentName == XmlTag::vertices) {
                 ImportVertices(currentNode, mesh);
-            } else if (currentName == D3MF::XmlTag::triangles) {
+            } else if (currentName == XmlTag::triangles) {
                 ImportTriangles(currentNode, mesh);
             }
-
         }
 
         return mesh;
     }
 
     void ReadMetadata(XmlNode &node) {
-        pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name.c_str());
+        pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name);
         const std::string name = attribute.as_string();
         const std::string value = node.value();
         if (name.empty()) {
@@ -398,9 +405,9 @@ private:
 
     void ImportVertices(XmlNode &node, aiMesh *mesh) {
         std::vector<aiVector3D> vertices;
-        for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-            const std::string &currentName = currentNode.name();
-            if (currentName == D3MF::XmlTag::vertex) {
+        for (XmlNode &currentNode : node.children()) {
+            const std::string currentName = currentNode.name();
+            if (currentName == XmlTag::vertex) {
                 vertices.push_back(ReadVertex(currentNode));
             }
         }
@@ -412,29 +419,28 @@ private:
 
     aiVector3D ReadVertex(XmlNode &node) {
         aiVector3D vertex;
-        vertex.x = ai_strtof(node.attribute(D3MF::XmlTag::x.c_str()).as_string(), nullptr);
-        vertex.y = ai_strtof(node.attribute(D3MF::XmlTag::y.c_str()).as_string(), nullptr);
-        vertex.z = ai_strtof(node.attribute(D3MF::XmlTag::z.c_str()).as_string(), nullptr);
+        vertex.x = ai_strtof(node.attribute(XmlTag::x).as_string(), nullptr);
+        vertex.y = ai_strtof(node.attribute(XmlTag::y).as_string(), nullptr);
+        vertex.z = ai_strtof(node.attribute(XmlTag::z).as_string(), nullptr);
 
         return vertex;
     }
 
     void ImportTriangles(XmlNode &node, aiMesh *mesh) {
         std::vector<aiFace> faces;
-        for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-            const std::string &currentName = currentNode.name();
-            if (currentName == D3MF::XmlTag::triangle) {
+        for (XmlNode &currentNode : node.children()) {
+            const std::string currentName = currentNode.name();
+            if (currentName == XmlTag::triangle) {
                 aiFace face = ReadTriangle(currentNode);
                 faces.push_back(face);
 
-                int pid = 0, p1;
+                int pid = 0, p1 = 0;
                 bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
                 bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
 
                 if (hasPid && hasP1) {
                     auto it = mResourcesDictionnary.find(pid);
-                    if (it != mResourcesDictionnary.end())
-                    {
+                    if (it != mResourcesDictionnary.end()) {
                         if (it->second->getType() == ResourceType::RT_BaseMaterials) {
                             BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
                             mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
@@ -457,9 +463,9 @@ private:
 
         face.mNumIndices = 3;
         face.mIndices = new unsigned int[face.mNumIndices];
-        face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v1.c_str()).as_string()));
-        face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v2.c_str()).as_string()));
-        face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v3.c_str()).as_string()));
+        face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v1).as_string()));
+        face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
+        face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
 
         return face;
     }
@@ -467,14 +473,14 @@ private:
     void ReadBaseMaterials(XmlNode &node) {
         int id = -1;
         if (getNodeAttribute(node, D3MF::XmlTag::basematerials_id, id)) {
-            BaseMaterials* baseMaterials = new BaseMaterials(id);
+            BaseMaterials *baseMaterials = new BaseMaterials(id);
 
-            for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling())
-            {
-                if (currentNode.name() == D3MF::XmlTag::basematerials_base) {
+            for (XmlNode &currentNode : node.children()) {
+                const std::string currentName = currentNode.name();
+                if (currentName == XmlTag::basematerials_base) {
                     baseMaterials->mMaterialIndex.push_back(mMaterialCount);
                     baseMaterials->mMaterials.push_back(readMaterialDef(currentNode, id));
-                    mMaterialCount++;
+                    ++mMaterialCount;
                 }
             }
 
@@ -488,7 +494,7 @@ private:
         }
 
         //format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
-        const size_t len(strlen(color));
+        const size_t len = strlen(color);
         if (9 != len && 7 != len) {
             return false;
         }
@@ -517,7 +523,7 @@ private:
     }
 
     void assignDiffuseColor(XmlNode &node, aiMaterial *mat) {
-        const char *color = node.attribute(D3MF::XmlTag::basematerials_displaycolor.c_str()).as_string();
+        const char *color = node.attribute(XmlTag::basematerials_displaycolor).as_string();
         aiColor4D diffuse;
         if (parseColor(color, diffuse)) {
             mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
@@ -531,7 +537,7 @@ private:
         bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name);
 
         std::string stdMaterialName;
-        std::string strId(ai_to_string(basematerialsId));
+        const std::string strId(ai_to_string(basematerialsId));
         stdMaterialName += "id";
         stdMaterialName += strId;
         stdMaterialName += "_";
@@ -556,13 +562,15 @@ private:
         std::string value;
     };
     std::vector<MetaEntry> mMetaData;
-    std::map<unsigned int, Resource*> mResourcesDictionnary;
+    std::map<unsigned int, Resource *> mResourcesDictionnary;
     unsigned int mMaterialCount, mMeshCount;
     XmlParser *mXmlParser;
 };
 
 } //namespace D3MF
 
+using namespace D3MF;
+
 static const aiImporterDesc desc = {
     "3mf Importer",
     "",
@@ -596,7 +604,7 @@ bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bo
         if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {
             return false;
         }
-        D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename);
+        D3MFOpcPackage opcPackage(pIOHandler, filename);
         return opcPackage.validate();
     }
 
@@ -612,11 +620,11 @@ const aiImporterDesc *D3MFImporter::GetInfo() const {
 }
 
 void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene, IOSystem *pIOHandler) {
-    D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename);
+    D3MFOpcPackage opcPackage(pIOHandler, filename);
 
     XmlParser xmlParser;
     if (xmlParser.parse(opcPackage.RootStream())) {
-        D3MF::XmlSerializer xmlSerializer(&xmlParser);
+        XmlSerializer xmlSerializer(&xmlParser);
         xmlSerializer.ImportXml(pScene);
     }
 }

+ 1 - 1
code/AssetLib/3MF/D3MFImporter.h

@@ -47,9 +47,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 namespace Assimp {
 
+/// @brief  The 3MF-importer class.
 class D3MFImporter : public BaseImporter {
 public:
-    // BaseImporter interface
     D3MFImporter();
     ~D3MFImporter();
     bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;

+ 3 - 3
code/AssetLib/3MF/D3MFOpcPackage.cpp

@@ -103,9 +103,9 @@ public:
             std::string name = currentNode.name();
             if (name == "Relationship") {
                 OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
-                relPtr->id = currentNode.attribute(XmlTag::RELS_ATTRIB_ID.c_str()).as_string();
-                relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE.c_str()).as_string();
-                relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET.c_str()).as_string();
+                relPtr->id = currentNode.attribute(XmlTag::RELS_ATTRIB_ID).as_string();
+                relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE).as_string();
+                relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET).as_string();
                 if (validateRels(relPtr)) {
                     m_relationShips.push_back(relPtr);
                 }

+ 0 - 4
code/AssetLib/AMF/AMFImporter.cpp

@@ -517,10 +517,6 @@ bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool p
     return false;
 }
 
-void AMFImporter::GetExtensionList(std::set<std::string> &pExtensionList) {
-    pExtensionList.insert("amf");
-}
-
 const aiImporterDesc *AMFImporter::GetInfo() const {
     return &Description;
 }

+ 0 - 1
code/AssetLib/AMF/AMFImporter.hpp

@@ -277,7 +277,6 @@ public:
     void ParseHelper_Node_Enter(AMFNodeElementBase *child);
     void ParseHelper_Node_Exit();
     bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const;
-    void GetExtensionList(std::set<std::string> &pExtensionList);
     void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
     const aiImporterDesc *GetInfo() const;
     bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const;

+ 2 - 2
code/AssetLib/AMF/AMFImporter_Postprocess.cpp

@@ -428,10 +428,10 @@ void AMFImporter::Postprocess_BuildMeshSet(const AMFMesh &pNodeElement, const st
 
                     if (pBiggerThan != nullptr) {
                         bool found = false;
-
+                        const size_t biggerThan = *pBiggerThan;
                         for (const SComplexFace &face : pFaceList) {
                             for (size_t idx_vert = 0; idx_vert < face.Face.mNumIndices; idx_vert++) {
-                                if (face.Face.mIndices[idx_vert] > *pBiggerThan) {
+                                if (face.Face.mIndices[idx_vert] > biggerThan) {
                                     rv = face.Face.mIndices[idx_vert];
                                     found = true;
                                     break;

+ 0 - 6
code/AssetLib/Blender/BlenderLoader.cpp

@@ -132,12 +132,6 @@ bool BlenderImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bo
     return false;
 }
 
-// ------------------------------------------------------------------------------------------------
-// List all extensions handled by this loader
-void BlenderImporter::GetExtensionList(std::set<std::string> &app) {
-    app.insert("blend");
-}
-
 // ------------------------------------------------------------------------------------------------
 // Loader registry entry
 const aiImporterDesc *BlenderImporter::GetInfo() const {

+ 0 - 1
code/AssetLib/Blender/BlenderLoader.h

@@ -110,7 +110,6 @@ public:
 
 protected:
     const aiImporterDesc* GetInfo () const;
-    void GetExtensionList(std::set<std::string>& app);
     void SetupProperties(const Importer* pImp);
     void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
     void ParseBlendFile(Blender::FileDatabase& out, std::shared_ptr<IOStream> stream);

+ 1 - 1
code/AssetLib/Collada/ColladaLoader.cpp

@@ -75,7 +75,7 @@ static const aiImporterDesc desc = {
     3,
     1,
     5,
-    "dae zae"
+    "dae xml zae"
 };
 
 static const float kMillisecondsFromSeconds = 1000.f;

+ 3 - 3
code/AssetLib/FBX/FBXExporter.cpp

@@ -1789,13 +1789,13 @@ void FBXExporter::WriteObjects ()
             blendchannel_uid, blendshape_name + FBX::SEPARATOR + "SubDeformer", "BlendShapeChannel"
         );
         sdnode.AddChild("Version", int32_t(100));
-        sdnode.AddChild("DeformPercent", int32_t(100));
+        sdnode.AddChild("DeformPercent", float_t(0.0));
         FBX::Node p("Properties70");
-        p.AddP70numberA("DeformPercent", 100.);
+        p.AddP70numberA("DeformPercent", 0.0);
         sdnode.AddChild(p);
         // TODO: Normally just one weight per channel, adding stub for later development
         std::vector<float>fFullWeights;
-        fFullWeights.push_back(0.);
+        fFullWeights.push_back(100.);
         sdnode.AddChild("FullWeights", fFullWeights);
         sdnode.Dump(outstream, binary, indent);
 

+ 2 - 3
code/AssetLib/M3D/M3DImporter.cpp

@@ -95,10 +95,9 @@ static const aiImporterDesc desc = {
     0,
     0,
     0,
-#ifdef M3D_ASCII
-    "m3d a3d"
-#else
     "m3d"
+#ifdef M3D_ASCII
+    " a3d"
 #endif
 };
 

+ 1 - 1
code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp

@@ -75,7 +75,7 @@ static const aiImporterDesc desc = {
     0,
     0,
     0,
-    "pk3"
+    "bsp pk3"
 };
 
 namespace Assimp {

+ 0 - 4
code/AssetLib/X3D/X3DImporter.cpp

@@ -167,10 +167,6 @@ bool X3DImporter::CanRead( const std::string &pFile, IOSystem * /*pIOHandler*/,
     return false;
 }
 
-void X3DImporter::GetExtensionList( std::set<std::string> &extensionList ) {
-    extensionList.insert("x3d");
-}
-
 void X3DImporter::InternReadFile( const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler ) {
     std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
     if (!stream) {

+ 0 - 1
code/AssetLib/X3D/X3DImporter.hpp

@@ -307,7 +307,6 @@ public:
     /// \param [in] pIOHandler - pointer to IO helper object.
     void ParseFile(const std::string &pFile, IOSystem *pIOHandler);
     bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const;
-    void GetExtensionList(std::set<std::string> &pExtensionList);
     void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
     const aiImporterDesc *GetInfo() const;
     void Clear();

+ 2 - 2
code/CApi/CInterfaceIOWrapper.cpp

@@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 namespace Assimp {
 
-CIOStreamWrapper::~CIOStreamWrapper(void) {
+CIOStreamWrapper::~CIOStreamWrapper() {
     /* Various places depend on this destructor to close the file */
     if (mFile) {
         mIO->mFileSystem->CloseProc(mIO->mFileSystem, mFile);
@@ -78,7 +78,7 @@ aiReturn CIOStreamWrapper::Seek(size_t pOffset,
 }
 
 // ...................................................................
-size_t CIOStreamWrapper::Tell(void) const {
+size_t CIOStreamWrapper::Tell() const {
     return mFile->TellProc(mFile);
 }
 

+ 1 - 1
code/Common/BaseImporter.cpp

@@ -97,7 +97,7 @@ void BaseImporter::UpdateImporterScale(Importer *pImp) {
     // Set active scaling
     pImp->SetPropertyFloat(AI_CONFIG_APP_SCALE_KEY, static_cast<float>(activeScale));
 
-    ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: %f", activeScale);
+    ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: ", activeScale);
 }
 
 // ------------------------------------------------------------------------------------------------

+ 15 - 2
code/Common/ImporterRegistry.cpp

@@ -48,6 +48,7 @@ corresponding preprocessor flag to selectively disable formats.
 
 #include <assimp/BaseImporter.h>
 #include <vector>
+#include <cstdlib>
 
 // ------------------------------------------------------------------------------------------------
 // Importers
@@ -204,7 +205,17 @@ corresponding preprocessor flag to selectively disable formats.
 namespace Assimp {
 
 // ------------------------------------------------------------------------------------------------
-void GetImporterInstanceList(std::vector<BaseImporter *> &out) {
+void GetImporterInstanceList(std::vector<BaseImporter *> &out) {    
+    
+    // Some importers may be unimplemented or otherwise unsuitable for general use
+    // in their current state. Devs can set ASSIMP_ENABLE_DEV_IMPORTERS in their
+    // local environment to enable them, otherwise they're left out of the registry.
+    const char *envStr = std::getenv("ASSIMP_ENABLE_DEV_IMPORTERS");
+    bool devImportersEnabled = envStr && strcmp(envStr, "0");
+
+    // Ensure no unused var warnings if all uses are #ifndef'd away below:
+    (void)devImportersEnabled;
+
     // ----------------------------------------------------------------------------
     // Add an instance of each worker class here
     // (register_new_importers_here)
@@ -354,7 +365,9 @@ void GetImporterInstanceList(std::vector<BaseImporter *> &out) {
     out.push_back(new D3MFImporter());
 #endif
 #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-    out.push_back(new X3DImporter());
+    if (devImportersEnabled) { // https://github.com/assimp/assimp/issues/3647
+        out.push_back(new X3DImporter());
+    }
 #endif
 #ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
     out.push_back(new MMDImporter());

+ 1 - 1
contrib/zip/src/zip.c

@@ -44,7 +44,7 @@
 
 #ifdef _MSC_VER
 #include <io.h>
-#pragma warning(disable : 4706)
+#pragma warning(disable : 4706 4244 4028)
 
 #define ftruncate(fd, sz) (-(_chsize_s((fd), (sz)) != 0))
 #define fileno _fileno

+ 3 - 3
include/assimp/StringUtils.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2021, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -55,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <cstdlib>
 #include <locale>
 #include <sstream>
+#include <iomanip>
 
 #ifdef _MSC_VER
 #define AI_SIZEFMT "%Iu"
@@ -177,7 +177,7 @@ AI_FORCE_INLINE std::string ai_rgba2hex(int r, int g, int b, int a, bool with_he
     if (with_head) {
         ss << "#";
     }
-    ss << std::hex << (r << 24 | g << 16 | b << 8 | a);
+    ss << std::hex << std::setfill('0') << std::setw(8) << (r << 24 | g << 16 | b << 8 | a);
 
     return ss.str();
 }
@@ -249,4 +249,4 @@ AI_FORCE_INLINE std::string ai_str_toupper(const std::string &in) {
     return out;
 }
 
-#endif
+#endif // INCLUDED_AI_STRINGUTILS_H

+ 2 - 2
port/PyAssimp/pyassimp/structs.py

@@ -1,6 +1,6 @@
 #-*- coding: utf-8 -*-
 
-from ctypes import POINTER, c_void_p, c_uint, c_char, c_float, Structure, c_char_p, c_double, c_ubyte, c_size_t, c_uint32
+from ctypes import POINTER, c_void_p, c_uint, c_char, c_float, Structure, c_double, c_ubyte, c_size_t, c_uint32
 
 
 class Vector2D(Structure):
@@ -1121,7 +1121,7 @@ class Scene(Structure):
             ("mMetadata", POINTER(Metadata)),
 
             # Internal data, do not touch
-            ("mPrivate", c_char_p),
+            ("mPrivate", POINTER(c_char)),
         ]
 
 assimp_structs_as_tuple = (Matrix4x4,

BIN
test/test.3mf


+ 11 - 2
test/unit/utStringUtils.cpp

@@ -42,9 +42,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/StringUtils.h>
 
 class utStringUtils : public ::testing::Test {
+    // empty
 };
 
-TEST_F( utStringUtils, to_string_Test ) {
+TEST_F(utStringUtils, to_string_Test ) {
     std::string res = ai_to_string( 1 );
     EXPECT_EQ( res, "1" );
 
@@ -52,7 +53,7 @@ TEST_F( utStringUtils, to_string_Test ) {
     EXPECT_EQ( res, "1" );
 }
 
-TEST_F( utStringUtils, ai_strtofTest ) {
+TEST_F(utStringUtils, ai_strtofTest ) {
     float res = ai_strtof( nullptr, nullptr );
     EXPECT_FLOAT_EQ( res, 0.0f );
 
@@ -66,3 +67,11 @@ TEST_F( utStringUtils, ai_strtofTest ) {
     res = ai_strtof( begin, end );
     EXPECT_FLOAT_EQ( res, 200.0f );
 }
+
+TEST_F(utStringUtils, ai_rgba2hexTest) {
+    std::string result;
+    result = ai_rgba2hex(255, 255, 255, 255, true);
+    EXPECT_EQ(result, "#ffffffff");
+    result = ai_rgba2hex(0, 0, 0, 0, false);
+    EXPECT_EQ(result, "00000000");
+}

+ 5 - 4
tools/assimp_cmd/ImageExtractor.cpp

@@ -130,8 +130,9 @@ int SaveAsBMP(FILE *file, const aiTexel *data, unsigned int width, unsigned int
             s[0] = t->b;
             s[1] = t->g;
             s[2] = t->r;
-            if (4 == numc)
+            if (4 == numc) {
                 s[3] = t->a;
+            }
         }
     }
 
@@ -296,7 +297,7 @@ int Assimp_Extract(const char *const *params, unsigned int num) {
 
         // check whether the requested texture is existing
         if (texIdx >= scene->mNumTextures) {
-            ::printf("assimp extract: Texture %i requested, but there are just %i textures\n",
+            ::printf("assimp extract: Texture %u requested, but there are just %i textures\n",
                     texIdx, scene->mNumTextures);
             return AssimpCmdExtractError::TextureIndexIsOutOfRange;
         }
@@ -325,7 +326,7 @@ int Assimp_Extract(const char *const *params, unsigned int num) {
         // if the texture is a compressed one, we'll export
         // it to its native file format
         if (!tex->mHeight) {
-            printf("assimp extract: Texture %i is compressed (%s). Writing native file format.\n",
+            printf("assimp extract: Texture %u is compressed (%s). Writing native file format.\n",
                     i, tex->achFormatHint);
 
             // modify file extension
@@ -350,7 +351,7 @@ int Assimp_Extract(const char *const *params, unsigned int num) {
         }
         ::fclose(p);
 
-        printf("assimp extract: Wrote texture %i to %s\n", i, out_cpy.c_str());
+        printf("assimp extract: Wrote texture %u to %s\n", i, out_cpy.c_str());
         if (texIdx != 0xffffffff) {
             return m;
         }