Переглянути джерело

Merge branch 'master' into static-lib-export

Kim Kulling 6 роки тому
батько
коміт
e8a4d60b6f

+ 7 - 0
.gitignore

@@ -7,6 +7,12 @@ build
 *.sln
 *.ncb
 *.vcproj
+*.vcxproj.user
+*.VC.db
+*.VC.db-shm
+*.VC.db-wal
+*.VC.opendb
+*.ipch
 
 # Output
 bin/
@@ -32,6 +38,7 @@ cmake_uninstall.cmake
 *.dir/
 assimp-config.cmake
 assimp-config-version.cmake
+assimpTargets*.cmake
 
 # MakeFile
 Makefile

+ 55 - 46
code/FBXConverter.cpp

@@ -86,7 +86,6 @@ namespace Assimp {
         , textures_converted()
         , meshes_converted()
         , node_anim_chain_bits()
-        , mNodeNameInstances()
         , mNodeNames()
         , anim_fps()
         , out(out)
@@ -142,12 +141,46 @@ namespace Assimp {
 
         void FBXConverter::ConvertRootNode() {
             out->mRootNode = new aiNode();
-            out->mRootNode->mName.Set("RootNode");
+            std::string unique_name;
+            GetUniqueName("RootNode", unique_name);
+            out->mRootNode->mName.Set(unique_name);
 
             // root has ID 0
             ConvertNodes(0L, *out->mRootNode);
         }
 
+        static std::string getAncestorBaseName(const aiNode* node)
+        {
+            const char* nodeName = nullptr;
+            size_t length = 0;
+            while (node && (!nodeName || length == 0))
+            {
+                nodeName = node->mName.C_Str();
+                length = node->mName.length;
+                node = node->mParent;
+            }
+
+            if (!nodeName || length == 0)
+            {
+                return {};
+            }
+            // could be std::string_view if c++17 available
+            return std::string(nodeName, length);
+        }
+
+        // Make unique name
+        std::string FBXConverter::MakeUniqueNodeName(const Model* const model, const aiNode& parent)
+        {
+            std::string original_name = FixNodeName(model->Name());
+            if (original_name.empty())
+            {
+                original_name = getAncestorBaseName(&parent);
+            }
+            std::string unique_name;
+            GetUniqueName(original_name, unique_name);
+            return unique_name;
+        }
+
         void FBXConverter::ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform) {
             const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(id, "Model");
 
@@ -179,35 +212,18 @@ namespace Assimp {
 
                         aiMatrix4x4 new_abs_transform = parent_transform;
 
+                        std::string unique_name = MakeUniqueNodeName(model, parent);
+
                         // even though there is only a single input node, the design of
                         // assimp (or rather: the complicated transformation chain that
                         // is employed by fbx) means that we may need multiple aiNode's
                         // to represent a fbx node's transformation.
-                        GenerateTransformationNodeChain(*model, nodes_chain, post_nodes_chain);
+                        const bool need_additional_node = GenerateTransformationNodeChain(*model, unique_name, nodes_chain, post_nodes_chain);
 
                         ai_assert(nodes_chain.size());
 
-                        std::string original_name = FixNodeName(model->Name());
-
-                        // check if any of the nodes in the chain has the name the fbx node
-                        // is supposed to have. If there is none, add another node to
-                        // preserve the name - people might have scripts etc. that rely
-                        // on specific node names.
-                        aiNode* name_carrier = NULL;
-                        for (aiNode* prenode : nodes_chain) {
-                            if (!strcmp(prenode->mName.C_Str(), original_name.c_str())) {
-                                name_carrier = prenode;
-                                break;
-                            }
-                        }
-
-                        if (!name_carrier) {
-                            std::string old_original_name = original_name;
-                            GetUniqueName(old_original_name, original_name);
-                            nodes_chain.push_back(new aiNode(original_name));
-                        }
-                        else {
-                            original_name = nodes_chain.back()->mName.C_Str();
+                        if (need_additional_node) {
+                            nodes_chain.push_back(new aiNode(unique_name));
                         }
 
                         //setup metadata on newest node
@@ -269,11 +285,11 @@ namespace Assimp {
                         ConvertNodes(model->ID(), *last_parent, new_abs_transform);
 
                         if (doc.Settings().readLights) {
-                            ConvertLights(*model, original_name);
+                            ConvertLights(*model, unique_name);
                         }
 
                         if (doc.Settings().readCameras) {
-                            ConvertCameras(*model, original_name);
+                            ConvertCameras(*model, unique_name);
                         }
 
                         nodes.push_back(nodes_chain.front());
@@ -426,21 +442,16 @@ namespace Assimp {
         void FBXConverter::GetUniqueName(const std::string &name, std::string &uniqueName)
         {
             uniqueName = name;
-            int i = 0;
-            auto it = mNodeNameInstances.find(name); // duplicate node name instance count
-            if (it != mNodeNameInstances.end())
+            auto it_pair = mNodeNames.insert({ name, 0 }); // duplicate node name instance count
+            unsigned int& i = it_pair.first->second;
+            while (!it_pair.second)
             {
-                i = it->second;
-                while (mNodeNames.find(uniqueName) != mNodeNames.end())
-                {
-                    i++;
-                    std::stringstream ext;
-                    ext << name << std::setfill('0') << std::setw(3) << i;
-                    uniqueName = ext.str();
-                }
+                i++;
+                std::ostringstream ext;
+                ext << name << std::setfill('0') << std::setw(3) << i;
+                uniqueName = ext.str();
+                it_pair = mNodeNames.insert({ uniqueName, 0 });
             }
-            mNodeNameInstances[name] = i;
-            mNodeNames.insert(uniqueName);
         }
 
         const char* FBXConverter::NameTransformationComp(TransformationComp comp) {
@@ -672,7 +683,7 @@ namespace Assimp {
             return name + std::string(MAGIC_NODE_TAG) + "_" + NameTransformationComp(comp);
         }
 
-        void FBXConverter::GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes,
+        bool FBXConverter::GenerateTransformationNodeChain(const Model& model, const std::string& name, std::vector<aiNode*>& output_nodes,
             std::vector<aiNode*>& post_output_nodes) {
             const PropertyTable& props = model.Props();
             const Model::RotOrder rot = model.RotationOrder();
@@ -787,8 +798,6 @@ namespace Assimp {
             // not be guaranteed.
             ai_assert(NeedsComplexTransformationChain(model) == is_complex);
 
-            std::string name = FixNodeName(model.Name());
-
             // now, if we have more than just Translation, Scaling and Rotation,
             // we need to generate a full node chain to accommodate for assimp's
             // lack to express pivots and offsets.
@@ -830,20 +839,20 @@ namespace Assimp {
                 }
 
                 ai_assert(output_nodes.size());
-                return;
+                return true;
             }
 
             // else, we can just multiply the matrices together
             aiNode* nd = new aiNode();
             output_nodes.push_back(nd);
-            std::string uniqueName;
-            GetUniqueName(name, uniqueName);
 
-            nd->mName.Set(uniqueName);
+            // name passed to the method is already unique
+            nd->mName.Set(name);
 
             for (const auto &transform : chain) {
                 nd->mTransformation = nd->mTransformation * transform;
             }
+            return false;
         }
 
         void FBXConverter::SetupNodeMetadata(const Model& model, aiNode& nd)

+ 7 - 5
code/FBXConverter.h

@@ -154,6 +154,11 @@ private:
     // while these would be allowed, they are a potential trouble spot so better not use them).
     const char* NameTransformationComp(TransformationComp comp);
 
+    // ------------------------------------------------------------------------------------------------
+    // Returns an unique name for a node or traverses up a hierarchy until a non-empty name is found and
+    // then makes this name unique
+    std::string MakeUniqueNodeName(const Model* const model, const aiNode& parent);
+
     // ------------------------------------------------------------------------------------------------
     // note: this returns the REAL fbx property names
     const char* NameTransformationCompProperty(TransformationComp comp);
@@ -177,7 +182,7 @@ private:
     /**
     *  note: memory for output_nodes will be managed by the caller
     */
-    void GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes);
+    bool GenerateTransformationNodeChain(const Model& model, const std::string& name, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes);
 
     // ------------------------------------------------------------------------------------------------
     void SetupNodeMetadata(const Model& model, aiNode& nd);
@@ -457,10 +462,7 @@ private:
     NodeAnimBitMap node_anim_chain_bits;
 
     // number of nodes with the same name
-    using NodeAnimNameMap = std::unordered_map<std::string, unsigned int>;
-    NodeAnimNameMap mNodeNameInstances;
-
-    using NodeNameCache = std::unordered_set<std::string>;
+    using NodeNameCache = std::unordered_map<std::string, unsigned int>;
     NodeNameCache mNodeNames;
 
     double anim_fps;

+ 3 - 3
code/FBXParser.cpp

@@ -643,9 +643,9 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
         if (type == 'd') {
             const double* d = reinterpret_cast<const double*>(&buff[0]);
             for (unsigned int i = 0; i < count3; ++i, d += 3) {
-                out.push_back(aiVector3D(static_cast<float>(d[0]),
-                    static_cast<float>(d[1]),
-                    static_cast<float>(d[2])));
+                out.push_back(aiVector3D(static_cast<ai_real>(d[0]),
+                    static_cast<ai_real>(d[1]),
+                    static_cast<ai_real>(d[2])));
             }
             // for debugging
             /*for ( size_t i = 0; i < out.size(); i++ ) {

+ 6 - 6
code/FindInstancesProcess.cpp

@@ -137,6 +137,11 @@ void FindInstancesProcess::Execute( aiScene* pScene)
             aiMesh* inst = pScene->mMeshes[i];
             hashes[i] = GetMeshHash(inst);
 
+            // Find an appropriate epsilon 
+            // to compare position differences against
+            float epsilon = ComputePositionEpsilon(inst);
+            epsilon *= epsilon;
+
             for (int a = i-1; a >= 0; --a) {
                 if (hashes[i] == hashes[a])
                 {
@@ -154,12 +159,7 @@ void FindInstancesProcess::Execute( aiScene* pScene)
                         orig->mPrimitiveTypes != inst->mPrimitiveTypes)
                         continue;
 
-                    // up to now the meshes are equal. find an appropriate
-                    // epsilon to compare position differences against
-                    float epsilon = ComputePositionEpsilon(inst);
-                    epsilon *= epsilon;
-
-                    // now compare vertex positions, normals,
+                    // up to now the meshes are equal. Now compare vertex positions, normals,
                     // tangents and bitangents using this epsilon.
                     if (orig->HasPositions()) {
                         if(!CompareArrays(orig->mVertices,inst->mVertices,orig->mNumVertices,epsilon))

+ 1 - 1
code/Importer/IFC/IFCBoolean.cpp

@@ -256,7 +256,7 @@ bool IntersectsBoundaryProfile(const IfcVector3& e0, const IfcVector3& e1, const
     for( size_t i = 0, bcount = boundary.size(); i < bcount; ++i ) {
         IfcVector3 b01 = boundary[(i + 1) % bcount] - boundary[i];
         IfcVector3 b12 = boundary[(i + 2) % bcount] - boundary[(i + 1) % bcount];
-        IfcVector3 b1_side = IfcVector3(b01.y, -b01.x, 0.0); // rotated 90° clockwise in Z plane
+        IfcVector3 b1_side = IfcVector3(b01.y, -b01.x, 0.0); // rotated 90° clockwise in Z plane
         // Warning: rough estimate only. A concave poly with lots of small segments each featuring a small counter rotation
         // could fool the accumulation. Correct implementation would be sum( acos( b01 * b2) * sign( b12 * b1_side))
         windingOrder += (b1_side.x*b12.x + b1_side.y*b12.y);

+ 1 - 0
code/STLLoader.cpp

@@ -278,6 +278,7 @@ void STLImporter::LoadASCIIFile( aiNode *root ) {
             }
             std::string name( szMe, temp );
             node->mName.Set( name.c_str() );
+            pMesh->mName.Set( name.c_str() );
             //pScene->mRootNode->mName.length = temp;
             //memcpy(pScene->mRootNode->mName.data,szMe,temp);
             //pScene->mRootNode->mName.data[temp] = '\0';

+ 2 - 2
code/res/resource.h

@@ -2,8 +2,8 @@
 // Microsoft Visual C++ generated include file.
 // Used by assimp.rc
 
-// Nächste Standardwerte für neue Objekte
-// 
+// Next standard values for new objects
+//
 #ifdef APSTUDIO_INVOKED
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_NEXT_RESOURCE_VALUE        101

+ 1 - 1
contrib/irrXML/irrString.h

@@ -19,7 +19,7 @@ so you can assign unicode to string<c8> and ascii to string<wchar_t>
 Note that the conversation between both is not done using an encoding.
 
 Known bugs:
-Special characters like 'Ä', 'Ü' and 'Ö' are ignored in the
+Special characters like 'Ä', 'Ü' and 'Ö' are ignored in the
 methods make_upper, make_lower and equals_ignore_case.
 */
 template <class T>

+ 1 - 1
contrib/poly2tri/AUTHORS

@@ -1,7 +1,7 @@
 Primary Contributors:
 
   Mason Green <[email protected]> (C++, Python)
-  Thomas Åhlén <[email protected]>    (Java)
+  Thomas Ã…hlén <[email protected]>    (Java)
 
 Other Contributors:
 

+ 2 - 2
contrib/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs

@@ -1,5 +1,5 @@
 //
-// © Copyright Henrik Ravn 2004
+// © Copyright Henrik Ravn 2004
 //
 // Use, modification and distribution are subject to the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -199,4 +199,4 @@ namespace DotZLib
     }
     #endregion
 
-}
+}

+ 1 - 1
contrib/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs

@@ -1,5 +1,5 @@
 //
-// © Copyright Henrik Ravn 2004
+// © Copyright Henrik Ravn 2004
 //
 // Use, modification and distribution are subject to the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

+ 1 - 1
contrib/zlib/contrib/dotzlib/DotZLib/CodecBase.cs

@@ -1,5 +1,5 @@
 //
-// © Copyright Henrik Ravn 2004
+// © Copyright Henrik Ravn 2004
 //
 // Use, modification and distribution are subject to the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

+ 1 - 1
contrib/zlib/contrib/dotzlib/DotZLib/Deflater.cs

@@ -1,5 +1,5 @@
 //
-// © Copyright Henrik Ravn 2004
+// © Copyright Henrik Ravn 2004
 //
 // Use, modification and distribution are subject to the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

+ 1 - 1
contrib/zlib/contrib/dotzlib/DotZLib/DotZLib.cs

@@ -1,5 +1,5 @@
 //
-// © Copyright Henrik Ravn 2004
+// © Copyright Henrik Ravn 2004
 //
 // Use, modification and distribution are subject to the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

+ 1 - 1
contrib/zlib/contrib/dotzlib/DotZLib/GZipStream.cs

@@ -1,5 +1,5 @@
 //
-// © Copyright Henrik Ravn 2004
+// © Copyright Henrik Ravn 2004
 //
 // Use, modification and distribution are subject to the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

+ 1 - 1
contrib/zlib/contrib/dotzlib/DotZLib/Inflater.cs

@@ -1,5 +1,5 @@
 //
-// © Copyright Henrik Ravn 2004
+// © Copyright Henrik Ravn 2004
 //
 // Use, modification and distribution are subject to the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

+ 1 - 1
include/assimp/defs.h

@@ -293,7 +293,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef _MSC_VER
 #  define AI_NO_EXCEPT noexcept
 #else
-#  if (_MSC_VER == 1915 )
+#  if (_MSC_VER >= 1915 )
 #    define AI_NO_EXCEPT noexcept
 #  else
 #    define AI_NO_EXCEPT

+ 8 - 7
include/assimp/irrXMLWrapper.h

@@ -91,14 +91,15 @@ public:
         stream->Read(&data[0],data.size(),1);
 
         // Remove null characters from the input sequence otherwise the parsing will utterly fail
-        unsigned int size = 0;
-        unsigned int size_max = static_cast<unsigned int>(data.size());
-        for(unsigned int i = 0; i < size_max; i++) {
-            if(data[i] != '\0') {
-                data[size++] = data[i];
-            }
+        // std::find is usually much faster than manually iterating
+        // It is very unlikely that there will be any null characters
+        auto null_char_iter = std::find(data.begin(), data.end(), '\0');
+
+        while (null_char_iter != data.end())
+        {
+            null_char_iter = data.erase(null_char_iter);
+            null_char_iter = std::find(null_char_iter, data.end(), '\0');
         }
-        data.resize(size);
 
         BaseImporter::ConvertToUTF8(data);
     }

+ 2 - 1
port/PyAssimp/pyassimp/core.py

@@ -82,7 +82,8 @@ def call_init(obj, caller = None):
         _init(obj,parent=caller)
 
 def _is_init_type(obj):
-    if helper.hasattr_silent(obj,'contents'): #pointer
+
+    if obj and helper.hasattr_silent(obj,'contents'): #pointer
         return _is_init_type(obj[0])
     # null-pointer case that arises when we reach a mesh attribute
     # like mBitangents which use mNumVertices rather than mNumBitangents

Різницю між файлами не показано, бо вона завелика
+ 571 - 0
test/models/FBX/cubes_nonames.fbx


Різницю між файлами не показано, бо вона завелика
+ 571 - 0
test/models/FBX/cubes_with_mirroring_and_pivot.fbx


Різницю між файлами не показано, бо вона завелика
+ 571 - 0
test/models/FBX/cubes_with_names.fbx


+ 113 - 0
test/unit/utFBXImporterExporter.cpp

@@ -76,6 +76,119 @@ TEST_F( utFBXImporterExporter, importBareBoxWithoutColorsAndTextureCoords ) {
     EXPECT_EQ(mesh->mNumVertices, 36);
 }
 
+TEST_F(utFBXImporterExporter, importCubesWithNoNames) {
+    Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/cubes_nonames.fbx", aiProcess_ValidateDataStructure);
+    ASSERT_TRUE(scene);
+
+    ASSERT_TRUE(scene->mRootNode);
+    const auto root = scene->mRootNode;
+    ASSERT_STREQ(root->mName.C_Str(), "RootNode");
+    ASSERT_TRUE(root->mChildren);
+    ASSERT_EQ(root->mNumChildren, 2);
+
+    const auto child0 = root->mChildren[0];
+    ASSERT_TRUE(child0);
+    ASSERT_STREQ(child0->mName.C_Str(), "RootNode001");
+    ASSERT_TRUE(child0->mChildren);
+    ASSERT_EQ(child0->mNumChildren, 1);
+
+    const auto child00 = child0->mChildren[0];
+    ASSERT_TRUE(child00);
+    ASSERT_STREQ(child00->mName.C_Str(), "RootNode001001");
+
+    const auto child1 = root->mChildren[1];
+    ASSERT_TRUE(child1);
+    ASSERT_STREQ(child1->mName.C_Str(), "RootNode002");
+    ASSERT_TRUE(child1->mChildren);
+    ASSERT_EQ(child1->mNumChildren, 1);
+
+    const auto child10 = child1->mChildren[0];
+    ASSERT_TRUE(child10);
+    ASSERT_STREQ(child10->mName.C_Str(), "RootNode002001");
+}
+
+TEST_F(utFBXImporterExporter, importCubesWithUnicodeDuplicatedNames) {
+    Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/cubes_with_names.fbx", aiProcess_ValidateDataStructure);
+    ASSERT_TRUE(scene);
+
+    ASSERT_TRUE(scene->mRootNode);
+    const auto root = scene->mRootNode;
+    ASSERT_STREQ(root->mName.C_Str(), "RootNode");
+    ASSERT_TRUE(root->mChildren);
+    ASSERT_EQ(root->mNumChildren, 2);
+
+    const auto child0 = root->mChildren[0];
+    ASSERT_TRUE(child0);
+    ASSERT_STREQ(child0->mName.C_Str(), "Cube2");
+    ASSERT_TRUE(child0->mChildren);
+    ASSERT_EQ(child0->mNumChildren, 1);
+
+    const auto child00 = child0->mChildren[0];
+    ASSERT_TRUE(child00);
+    ASSERT_STREQ(child00->mName.C_Str(), "\xd0\x9a\xd1\x83\xd0\xb1\x31");
+
+    const auto child1 = root->mChildren[1];
+    ASSERT_TRUE(child1);
+    ASSERT_STREQ(child1->mName.C_Str(), "Cube3");
+    ASSERT_TRUE(child1->mChildren);
+    ASSERT_EQ(child1->mNumChildren, 1);
+
+    const auto child10 = child1->mChildren[0];
+    ASSERT_TRUE(child10);
+    ASSERT_STREQ(child10->mName.C_Str(), "\xd0\x9a\xd1\x83\xd0\xb1\x31""001");
+}
+
+TEST_F(utFBXImporterExporter, importCubesComplexTransform) {
+    Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/cubes_with_mirroring_and_pivot.fbx", aiProcess_ValidateDataStructure);
+    ASSERT_TRUE(scene);
+
+    ASSERT_TRUE(scene->mRootNode);
+    const auto root = scene->mRootNode;
+    ASSERT_STREQ(root->mName.C_Str(), "RootNode");
+    ASSERT_TRUE(root->mChildren);
+    ASSERT_EQ(root->mNumChildren, 2);
+
+    const auto child0 = root->mChildren[0];
+    ASSERT_TRUE(child0);
+    ASSERT_STREQ(child0->mName.C_Str(), "Cube2");
+    ASSERT_TRUE(child0->mChildren);
+    ASSERT_EQ(child0->mNumChildren, 1);
+
+    const auto child00 = child0->mChildren[0];
+    ASSERT_TRUE(child00);
+    ASSERT_STREQ(child00->mName.C_Str(), "Cube1");
+
+    const auto child1 = root->mChildren[1];
+    ASSERT_TRUE(child1);
+    ASSERT_STREQ(child1->mName.C_Str(), "Cube3");
+
+    auto parent = child1;
+    const size_t chain_length = 8u;
+    const char* chainStr[chain_length] = {
+        "Cube1001_$AssimpFbx$_Translation",
+        "Cube1001_$AssimpFbx$_RotationPivot",
+        "Cube1001_$AssimpFbx$_RotationPivotInverse",
+        "Cube1001_$AssimpFbx$_ScalingOffset",
+        "Cube1001_$AssimpFbx$_ScalingPivot",
+        "Cube1001_$AssimpFbx$_Scaling",
+        "Cube1001_$AssimpFbx$_ScalingPivotInverse",
+        "Cube1001"
+    };
+    for (size_t i = 0; i < chain_length; ++i)
+    {
+        ASSERT_TRUE(parent->mChildren);
+        ASSERT_EQ(parent->mNumChildren, 1);
+        auto node = parent->mChildren[0];
+        ASSERT_TRUE(node);
+        ASSERT_STREQ(node->mName.C_Str(), chainStr[i]);
+        parent = node;
+    }
+    ASSERT_EQ(0, parent->mNumChildren) << "Leaf node";
+}
+
 TEST_F( utFBXImporterExporter, importPhongMaterial ) {
     Assimp::Importer importer;
     const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/phong_cube.fbx", aiProcess_ValidateDataStructure );

+ 7 - 2
tools/assimp_cmd/Info.cpp

@@ -317,10 +317,15 @@ int Assimp_Info (const char* const* params, unsigned int num) {
 		return 1;
 	}
 	
-	// do maximum post-processing unless -r was specified
+	// Parse post-processing flags unless -r was specified
 	ImportData import;
 	if (!raw) {
-		import.ppFlags = aiProcessPreset_TargetRealtime_MaxQuality;
+		// get import flags
+		ProcessStandardArguments(import, params + 1, num - 1);
+
+		//No custom post process flags defined, we set all the post process flags active
+		if(import.ppFlags == 0)
+			import.ppFlags |= aiProcessPreset_TargetRealtime_MaxQuality;
 	}
 
 	// import the main model

+ 2 - 2
tools/assimp_view/stdafx.cpp

@@ -1,8 +1,8 @@
 // stdafx.cpp : Quelldatei, die nur die Standard-Includes einbindet.
 // assimp_view.pch ist der vorkompilierte Header.
-// stdafx.obj enthält die vorkompilierten Typinformationen.
+// stdafx.obj enthält die vorkompilierten Typinformationen.
 
 #include "stdafx.h"
 
-// TODO: Auf zusätzliche Header verweisen, die in STDAFX.H
+// TODO: Auf zusätzliche Header verweisen, die in STDAFX.H
 // und nicht in dieser Datei erforderlich sind.

+ 13 - 13
tools/assimp_view/stdafx.h

@@ -1,26 +1,26 @@
-// stdafx.h : Includedatei für Standardsystem-Includedateien
-// oder häufig verwendete projektspezifische Includedateien,
-// die nur in unregelmäßigen Abständen geändert werden.
+// stdafx.h : Includedatei für Standardsystem-Includedateien
+// oder häufig verwendete projektspezifische Includedateien,
+// die nur in unregelmäßigen Abständen geändert werden.
 //
 
 #pragma once
 
-// Ändern Sie folgende Definitionen für Plattformen, die älter als die unten angegebenen sind.
-// In MSDN finden Sie die neuesten Informationen über die entsprechenden Werte für die unterschiedlichen Plattformen.
-#ifndef WINVER              // Lassen Sie die Verwendung spezifischer Features von Windows XP oder später zu.
-#   define WINVER 0x0501        // Ändern Sie dies in den geeigneten Wert für andere Versionen von Windows.
+// Ändern Sie folgende Definitionen für Plattformen, die älter als die unten angegebenen sind.
+// In MSDN finden Sie die neuesten Informationen über die entsprechenden Werte für die unterschiedlichen Plattformen.
+#ifndef WINVER              // Lassen Sie die Verwendung spezifischer Features von Windows XP oder später zu.
+#   define WINVER 0x0501        // Ändern Sie dies in den geeigneten Wert für andere Versionen von Windows.
 #endif
 
-#ifndef _WIN32_WINNT        // Lassen Sie die Verwendung spezifischer Features von Windows XP oder später zu.
-#   define _WIN32_WINNT 0x0501  // Ändern Sie dies in den geeigneten Wert für andere Versionen von Windows.
+#ifndef _WIN32_WINNT        // Lassen Sie die Verwendung spezifischer Features von Windows XP oder später zu.
+#   define _WIN32_WINNT 0x0501  // Ändern Sie dies in den geeigneten Wert für andere Versionen von Windows.
 #endif
 
-#ifndef _WIN32_WINDOWS      // Lassen Sie die Verwendung spezifischer Features von Windows 98 oder später zu.
-#   define _WIN32_WINDOWS 0x0410 // Ändern Sie dies in den geeigneten Wert für Windows Me oder höher.
+#ifndef _WIN32_WINDOWS      // Lassen Sie die Verwendung spezifischer Features von Windows 98 oder später zu.
+#   define _WIN32_WINDOWS 0x0410 // Ändern Sie dies in den geeigneten Wert für Windows Me oder höher.
 #endif
 
-#ifndef _WIN32_IE           // Lassen Sie die Verwendung spezifischer Features von IE 6.0 oder später zu.
-#define _WIN32_IE 0x0600    // Ändern Sie dies in den geeigneten Wert für andere Versionen von IE.
+#ifndef _WIN32_IE           // Lassen Sie die Verwendung spezifischer Features von IE 6.0 oder später zu.
+#define _WIN32_IE 0x0600    // Ändern Sie dies in den geeigneten Wert für andere Versionen von IE.
 #endif
 
 // Windows-Headerdateien:

Деякі файли не було показано, через те що забагато файлів було змінено