فهرست منبع

Merge pull request #2820 from RichardTea/collada_modeller_metadata

Collada and glTF modeller metadata
Kim Kulling 5 سال پیش
والد
کامیت
a01d7c4048

+ 2 - 0
code/CMakeLists.txt

@@ -66,6 +66,7 @@ SET( PUBLIC_HEADERS
   ${HEADER_PATH}/color4.h
   ${HEADER_PATH}/color4.inl
   ${CMAKE_CURRENT_BINARY_DIR}/../include/assimp/config.h
+  ${HEADER_PATH}/commonMetaData.h
   ${HEADER_PATH}/defs.h
   ${HEADER_PATH}/Defines.h
   ${HEADER_PATH}/cfileio.h
@@ -348,6 +349,7 @@ ADD_ASSIMP_IMPORTER( BVH
 )
 
 ADD_ASSIMP_IMPORTER( COLLADA
+  Collada/ColladaHelper.cpp
   Collada/ColladaHelper.h
   Collada/ColladaLoader.cpp
   Collada/ColladaLoader.h

+ 3 - 2
code/Collada/ColladaExporter.cpp

@@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "ColladaExporter.h"
 #include <assimp/Bitmap.h>
+#include <assimp/commonMetaData.h>
 #include <assimp/MathFunctions.h>
 #include <assimp/fast_atof.h>
 #include <assimp/SceneCombiner.h>
@@ -277,7 +278,7 @@ void ColladaExporter::WriteHeader() {
         mOutput << startstr << "<author>" << XMLEscape(value.C_Str()) << "</author>" << endstr;
     }
 
-    if (nullptr == meta || !meta->Get("AuthoringTool", value)) {
+    if (nullptr == meta || !meta->Get(AI_METADATA_SOURCE_GENERATOR, value)) {
         mOutput << startstr << "<authoring_tool>" << "Assimp Exporter" << "</authoring_tool>" << endstr;
     } else {
         mOutput << startstr << "<authoring_tool>" << XMLEscape(value.C_Str()) << "</authoring_tool>" << endstr;
@@ -287,7 +288,7 @@ void ColladaExporter::WriteHeader() {
         if (meta->Get("Comments", value)) {
             mOutput << startstr << "<comments>" << XMLEscape(value.C_Str()) << "</comments>" << endstr;
         }
-        if (meta->Get("Copyright", value)) {
+        if (meta->Get(AI_METADATA_SOURCE_COPYRIGHT, value)) {
             mOutput << startstr << "<copyright>" << XMLEscape(value.C_Str()) << "</copyright>" << endstr;
         }
         if (meta->Get("SourceData", value)) {

+ 107 - 0
code/Collada/ColladaHelper.cpp

@@ -0,0 +1,107 @@
+/** Helper structures for the Collada loader */
+
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#include "ColladaHelper.h"
+
+#include <assimp/commonMetaData.h>
+#include <assimp/ParsingUtils.h>
+
+namespace Assimp {
+namespace Collada {
+
+const MetaKeyPairVector MakeColladaAssimpMetaKeys() {
+    MetaKeyPairVector result;
+    result.emplace_back("authoring_tool", AI_METADATA_SOURCE_GENERATOR);
+    result.emplace_back("copyright", AI_METADATA_SOURCE_COPYRIGHT);
+    return result;
+};
+
+const MetaKeyPairVector &GetColladaAssimpMetaKeys() {
+    static const MetaKeyPairVector result = MakeColladaAssimpMetaKeys();
+    return result;
+}
+
+const MetaKeyPairVector MakeColladaAssimpMetaKeysCamelCase() {
+    MetaKeyPairVector result = MakeColladaAssimpMetaKeys();
+    for (auto &val : result)
+    {
+        ToCamelCase(val.first);
+    }
+    return result;
+};
+
+const MetaKeyPairVector &GetColladaAssimpMetaKeysCamelCase()
+{
+    static const MetaKeyPairVector result = MakeColladaAssimpMetaKeysCamelCase();
+    return result;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Convert underscore_separated to CamelCase: "authoring_tool" becomes "AuthoringTool"
+void ToCamelCase(std::string &text)
+{
+    if (text.empty())
+        return;
+    // Capitalise first character
+    auto it = text.begin();
+    (*it) = ToUpper(*it);
+    ++it;
+    for (/*started above*/ ; it != text.end(); /*iterated below*/)
+    {
+        if ((*it) == '_')
+        {
+            it = text.erase(it);
+            if (it != text.end())
+                (*it) = ToUpper(*it);
+        }
+        else
+        {
+            // Make lower case
+            (*it) = ToLower(*it);
+            ++it;               
+        }
+    }
+}
+
+} // namespace Collada
+} // namespace Assimp

+ 11 - 0
code/Collada/ColladaHelper.h

@@ -104,6 +104,17 @@ enum MorphMethod
     Relative
 };
 
+/** Common metadata keys as <Collada, Assimp> */
+typedef std::pair<std::string, std::string> MetaKeyPair;
+typedef std::vector<MetaKeyPair> MetaKeyPairVector;
+
+// Collada as lower_case (native)
+const MetaKeyPairVector &GetColladaAssimpMetaKeys();
+// Collada as CamelCase (used by Assimp for consistency)
+const MetaKeyPairVector &GetColladaAssimpMetaKeysCamelCase();
+
+/** Convert underscore_separated to CamelCase "authoring_tool" becomes "AuthoringTool" */
+void ToCamelCase(std::string &text);
 
 /** Contains all data for one of the different transformation types */
 struct Transform

+ 41 - 34
code/Collada/ColladaParser.cpp

@@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <sstream>
 #include <stdarg.h>
 #include "ColladaParser.h"
+#include <assimp/commonMetaData.h>
 #include <assimp/fast_atof.h>
 #include <assimp/ParsingUtils.h>
 #include <assimp/StringUtils.h>
@@ -249,6 +250,9 @@ void ColladaParser::UriDecodePath(aiString& ss)
 bool ColladaParser::ReadBoolFromTextContent()
 {
     const char* cur = GetTextContent();
+    if ( nullptr == cur) {
+        return false;
+    }
     return (!ASSIMP_strincmp(cur, "true", 4) || '0' != *cur);
 }
 
@@ -257,6 +261,9 @@ bool ColladaParser::ReadBoolFromTextContent()
 ai_real ColladaParser::ReadFloatFromTextContent()
 {
     const char* cur = GetTextContent();
+    if ( nullptr == cur ) {
+        return 0.0;
+    }
     return fast_atof(cur);
 }
 
@@ -276,6 +283,11 @@ void ColladaParser::ReadContents()
                 if (attrib != -1) {
                     const char* version = mReader->getAttributeValue(attrib);
 
+                    // Store declared format version string
+                    aiString v;
+                    v.Set(version);
+                    mAssetMetaData.emplace(AI_METADATA_SOURCE_FORMAT_VERSION, v );
+
                     if (!::strncmp(version, "1.5", 3)) {
                         mFormat = FV_1_5_n;
                         ASSIMP_LOG_DEBUG("Collada schema version is 1.5.n");
@@ -434,23 +446,39 @@ void ColladaParser::ReadContributorInfo()
     }
 }
 
+static bool FindCommonKey(const std::string &collada_key, const MetaKeyPairVector &key_renaming, size_t &found_index) {
+    for (size_t i = 0; i < key_renaming.size(); ++i) {
+		if (key_renaming[i].first == collada_key) {
+            found_index = i;
+            return true;
+		}
+	}
+    found_index = std::numeric_limits<size_t>::max();
+    return false;
+}
+
 // ------------------------------------------------------------------------------------------------
 // Reads a single string metadata item
-void ColladaParser::ReadMetaDataItem(StringMetaData &metadata)
-{
-    // Metadata such as created, keywords, subject etc
-    const char* key_char = mReader->getNodeName();
-    if (key_char != nullptr)
-    {
+void ColladaParser::ReadMetaDataItem(StringMetaData &metadata) {
+    const Collada::MetaKeyPairVector &key_renaming = GetColladaAssimpMetaKeysCamelCase();
+	// Metadata such as created, keywords, subject etc
+	const char *key_char = mReader->getNodeName();
+	if (key_char != nullptr) {
         const std::string key_str(key_char);
-        const char* value_char = TestTextContent();
-        if (value_char != nullptr)
-        {
-            std::string camel_key_str = key_str;
-            ToCamelCase(camel_key_str);
+		const char *value_char = TestTextContent();
+		if (value_char != nullptr) {
             aiString aistr;
-            aistr.Set(value_char);
-            metadata.emplace(camel_key_str, aistr);
+			aistr.Set(value_char);
+
+            std::string camel_key_str(key_str);
+			ToCamelCase(camel_key_str);
+
+			size_t found_index;
+			if (FindCommonKey(camel_key_str, key_renaming, found_index)) {
+                metadata.emplace(key_renaming[found_index].second, aistr);
+            } else {
+				metadata.emplace(camel_key_str, aistr);
+			}
         }
         TestClosing(key_str.c_str());
     }
@@ -458,27 +486,6 @@ void ColladaParser::ReadMetaDataItem(StringMetaData &metadata)
         SkipElement();
 }
 
-// ------------------------------------------------------------------------------------------------
-// Convert underscore_seperated to CamelCase: "authoring_tool" becomes "AuthoringTool"
-void ColladaParser::ToCamelCase(std::string &text)
-{
-    if (text.empty())
-        return;
-    // Capitalise first character
-    text[0] = ToUpper(text[0]);
-    for (auto it = text.begin(); it != text.end(); /*iterated below*/)
-    {
-        if ((*it) == '_')
-        {
-            it = text.erase(it);
-            if (it != text.end())
-                (*it) = ToUpper(*it);
-        }
-        else
-            ++it;
-    }
-}
-
 // ------------------------------------------------------------------------------------------------
 // Reads the animation clips
 void ColladaParser::ReadAnimationClipLibrary()

+ 1 - 4
code/Collada/ColladaParser.h

@@ -94,12 +94,9 @@ namespace Assimp
         /** Reads contributor information such as author and legal blah */
         void ReadContributorInfo();
 
-        /** Reads generic metadata into provided map */
+        /** Reads generic metadata into provided map and renames keys for Assimp */
         void ReadMetaDataItem(StringMetaData &metadata);
 
-        /** Convert underscore_seperated to CamelCase "authoring_tool" becomes "AuthoringTool" */
-        static void ToCamelCase(std::string &text);
-
         /** Reads the animation library */
         void ReadAnimationLibrary();
 

+ 3 - 0
code/glTF/glTFAssetWriter.inl

@@ -627,6 +627,9 @@ namespace glTF {
         asset.SetObject();
         asset.AddMember("version", Value(mAsset.asset.version, mAl).Move(), mAl);
         asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
+        if (!mAsset.asset.copyright.empty())
+            asset.AddMember("copyright", Value(mAsset.asset.copyright, mAl).Move(), mAl);
+
         mDoc.AddMember("asset", asset, mAl);
     }
 

+ 7 - 0
code/glTF/glTFExporter.cpp

@@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "glTF/glTFAssetWriter.h"
 #include "PostProcessing/SplitLargeMeshes.h"
 
+#include <assimp/commonMetaData.h>
 #include <assimp/Exceptional.h>
 #include <assimp/StringComparison.h>
 #include <assimp/ByteSwapper.h>
@@ -873,6 +874,12 @@ void glTFExporter::ExportMetadata()
         aiGetVersionMajor(), aiGetVersionMinor(), aiGetVersionRevision());
 
     asset.generator = buffer;
+
+	// Copyright
+	aiString copyright_str;
+	if (mScene->mMetaData->Get(AI_METADATA_SOURCE_COPYRIGHT, copyright_str)) {
+		asset.copyright = copyright_str.C_Str();
+	}
 }
 
 inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animation>& animRef, Ref<Buffer>& buffer, const aiNodeAnim* nodeChannel, float ticksPerSecond)

+ 6 - 1
code/glTF/glTFImporter.cpp

@@ -703,7 +703,8 @@ void glTFImporter::ImportCommonMetadata(glTF::Asset& a)
     ai_assert(mScene->mMetaData == nullptr);
     const bool hasVersion = !a.asset.version.empty();
     const bool hasGenerator = !a.asset.generator.empty();
-    if (hasVersion || hasGenerator)
+    const bool hasCopyright = !a.asset.copyright.empty();
+    if (hasVersion || hasGenerator || hasCopyright)
     {
         mScene->mMetaData = new aiMetadata;
         if (hasVersion)
@@ -714,6 +715,10 @@ void glTFImporter::ImportCommonMetadata(glTF::Asset& a)
         {
             mScene->mMetaData->Add(AI_METADATA_SOURCE_GENERATOR, aiString(a.asset.generator));
         }
+        if (hasCopyright)
+        {
+            mScene->mMetaData->Add(AI_METADATA_SOURCE_COPYRIGHT, aiString(a.asset.copyright));
+        }
     }
 }
 

+ 2 - 0
code/glTF2/glTF2AssetWriter.inl

@@ -720,6 +720,8 @@ namespace glTF2 {
         asset.SetObject();
         asset.AddMember("version", Value(mAsset.asset.version, mAl).Move(), mAl);
         asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
+        if (!mAsset.asset.copyright.empty())
+            asset.AddMember("copyright", Value(mAsset.asset.copyright, mAl).Move(), mAl);
         mDoc.AddMember("asset", asset, mAl);
     }
 

+ 7 - 0
code/glTF2/glTF2Exporter.cpp

@@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "glTF2/glTF2AssetWriter.h"
 #include "PostProcessing/SplitLargeMeshes.h"
 
+#include <assimp/commonMetaData.h>
 #include <assimp/Exceptional.h>
 #include <assimp/StringComparison.h>
 #include <assimp/ByteSwapper.h>
@@ -996,6 +997,12 @@ void glTF2Exporter::ExportMetadata()
         aiGetVersionMajor(), aiGetVersionMinor(), aiGetVersionRevision());
 
     asset.generator = buffer;
+
+    // Copyright
+	aiString copyright_str;
+	if (mScene->mMetaData->Get(AI_METADATA_SOURCE_COPYRIGHT, copyright_str)) {
+        asset.copyright = copyright_str.C_Str();
+	}
 }
 
 inline Ref<Accessor> GetSamplerInputRef(Asset& asset, std::string& animId, Ref<Buffer>& buffer, std::vector<float>& times)

+ 6 - 1
code/glTF2/glTF2Importer.cpp

@@ -1307,7 +1307,8 @@ void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) {
     ai_assert(mScene->mMetaData == nullptr);
     const bool hasVersion = !a.asset.version.empty();
     const bool hasGenerator = !a.asset.generator.empty();
-    if (hasVersion || hasGenerator)
+    const bool hasCopyright = !a.asset.copyright.empty();
+    if (hasVersion || hasGenerator || hasCopyright)
     {
         mScene->mMetaData = new aiMetadata;
         if (hasVersion)
@@ -1318,6 +1319,10 @@ void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) {
         {
             mScene->mMetaData->Add(AI_METADATA_SOURCE_GENERATOR, aiString(a.asset.generator));
         }
+        if (hasCopyright)
+        {
+            mScene->mMetaData->Add(AI_METADATA_SOURCE_COPYRIGHT, aiString(a.asset.copyright));
+        }
     }
 }
 

+ 4 - 0
include/assimp/commonMetaData.h

@@ -60,4 +60,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /// Not all formats add this metadata.
 #define AI_METADATA_SOURCE_GENERATOR "SourceAsset_Generator"
 
+/// Scene metadata holding the source asset copyright statement, if available.
+/// Not all formats add this metadata.
+#define AI_METADATA_SOURCE_COPYRIGHT "SourceAsset_Copyright"
+
 #endif

+ 1 - 0
test/models/Collada/lights.dae

@@ -4,6 +4,7 @@
     <contributor>
       <author>Blender User</author>
       <authoring_tool>Blender 2.74.0 commit date:2015-03-31, commit time:13:39, hash:000dfc0</authoring_tool>
+      <copyright>BSD</copyright>
     </contributor>
     <created>2015-05-17T21:55:44</created>
     <modified>2015-05-17T21:55:44</modified>

+ 54 - 5
test/unit/utColladaExportLight.cpp

@@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "UnitTestPCH.h"
 
 #include <assimp/cexport.h>
+#include <assimp/commonMetaData.h>
 #include <assimp/Exporter.hpp>
 #include <assimp/Importer.hpp>
 #include <assimp/scene.h>
@@ -75,7 +76,7 @@ TEST_F(ColladaExportLight, testExportLight)
     const char* file = "lightsExp.dae";
 
     const aiScene* pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/lights.dae", aiProcess_ValidateDataStructure);
-    ASSERT_TRUE(pTest!=NULL);
+    ASSERT_NE(pTest, nullptr);
     ASSERT_TRUE(pTest->HasLights());
 
     const unsigned int origNumLights( pTest->mNumLights );
@@ -86,15 +87,63 @@ TEST_F(ColladaExportLight, testExportLight)
         origLights[ i ] = *(pTest->mLights[ i ]);
     }
 
-    EXPECT_EQ(AI_SUCCESS,ex->Export(pTest,"collada",file));
+    // Common metadata
+    // Confirm was loaded by the Collada importer
+    aiString origImporter;
+    EXPECT_TRUE(pTest->mMetaData->Get(AI_METADATA_SOURCE_FORMAT, origImporter)) << "No importer format metadata";
+	EXPECT_STREQ("Collada Importer", origImporter.C_Str());
+
+    aiString origGenerator;
+	EXPECT_TRUE(pTest->mMetaData->Get(AI_METADATA_SOURCE_GENERATOR, origGenerator)) << "No generator metadata";
+	EXPECT_EQ(strncmp(origGenerator.C_Str(), "Blender", 7), 0) << "AI_METADATA_SOURCE_GENERATOR was: " << origGenerator.C_Str();
+
+    aiString origCopyright;
+	EXPECT_TRUE(pTest->mMetaData->Get(AI_METADATA_SOURCE_COPYRIGHT, origCopyright)) << "No copyright metadata";
+    EXPECT_STREQ("BSD", origCopyright.C_Str());
+
+    aiString origCreated;
+	EXPECT_TRUE(pTest->mMetaData->Get("Created", origCreated)) << "No created metadata";
+    EXPECT_STREQ("2015-05-17T21:55:44", origCreated.C_Str());
+
+    aiString origModified;
+	EXPECT_TRUE(pTest->mMetaData->Get("Modified", origModified)) << "No modified metadata";
+    EXPECT_STREQ("2015-05-17T21:55:44", origModified.C_Str());
+
+    EXPECT_EQ(AI_SUCCESS, ex->Export(pTest, "collada", file));
+
+    // Drop the pointer as about to become invalid
+    pTest = nullptr;
 
     const aiScene* imported = im->ReadFile(file, aiProcess_ValidateDataStructure);
 
-    ASSERT_TRUE(imported!=NULL);
+    ASSERT_TRUE(imported != NULL);
+
+    // Check common metadata survived roundtrip
+    aiString readImporter;
+    EXPECT_TRUE(imported->mMetaData->Get(AI_METADATA_SOURCE_FORMAT, readImporter)) << "No importer format metadata after export";
+    EXPECT_STREQ(origImporter.C_Str(), readImporter.C_Str()) << "Assimp Importer Format changed";
+
+    aiString readGenerator;
+	EXPECT_TRUE(imported->mMetaData->Get(AI_METADATA_SOURCE_GENERATOR, readGenerator)) << "No generator metadata";
+	EXPECT_STREQ(origGenerator.C_Str(), readGenerator.C_Str()) << "Generator changed";
+
+    aiString readCopyright;
+	EXPECT_TRUE(imported->mMetaData->Get(AI_METADATA_SOURCE_COPYRIGHT, readCopyright)) << "No copyright metadata";
+    EXPECT_STREQ(origCopyright.C_Str(), readCopyright.C_Str()) << "Copyright changed";
+
+    aiString readCreated;
+	EXPECT_TRUE(imported->mMetaData->Get("Created", readCreated)) << "No created metadata";
+    EXPECT_STREQ(origCreated.C_Str(), readCreated.C_Str()) << "Created date changed";
+
+    aiString readModified;
+	EXPECT_TRUE(imported->mMetaData->Get("Modified", readModified)) << "No modified metadata";
+    EXPECT_STRNE(origModified.C_Str(), readModified.C_Str()) << "Modified date did not change";
+    EXPECT_GT(readModified.length, ai_uint32(18)) << "Modified date too short";
 
+    // Lights
     EXPECT_TRUE(imported->HasLights());
-    EXPECT_EQ( origNumLights,imported->mNumLights );
-    for(size_t i=0; i< origNumLights; i++) {
+    EXPECT_EQ(origNumLights, imported->mNumLights);
+    for(size_t i=0; i < origNumLights; i++) {
         const aiLight *orig = &origLights[ i ];
         const aiLight *read = imported->mLights[i];
         EXPECT_EQ( 0,strncmp(origNames[ i ].c_str(),read->mName.C_Str(), origNames[ i ].size() ) );

+ 69 - 54
test/unit/utColladaImportExport.cpp

@@ -40,76 +40,91 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ---------------------------------------------------------------------------
 */
-#include "UnitTestPCH.h"
 #include "AbstractImportExportBase.h"
+#include "UnitTestPCH.h"
 
-#include <assimp/Importer.hpp>
-#include <assimp/scene.h>
+#include <assimp/commonMetaData.h>
 #include <assimp/postprocess.h>
+#include <assimp/scene.h>
+#include <assimp/Importer.hpp>
 
 using namespace Assimp;
 
 class utColladaImportExport : public AbstractImportExportBase {
 public:
-    virtual bool importerTest() {
-        Assimp::Importer importer;
-        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.dae", aiProcess_ValidateDataStructure);
-        if (scene == nullptr)
-            return false;
-
-        // Expected number of items
-        EXPECT_EQ(scene->mNumMeshes, 1u);
-        EXPECT_EQ(scene->mNumMaterials, 1u);
-        EXPECT_EQ(scene->mNumAnimations, 0u);
-        EXPECT_EQ(scene->mNumTextures, 0u);
-        EXPECT_EQ(scene->mNumLights, 1u);
-        EXPECT_EQ(scene->mNumCameras, 1u);
-
-        return true;
-    }
+	virtual bool importerTest() {
+		Assimp::Importer importer;
+		const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.dae", aiProcess_ValidateDataStructure);
+		if (scene == nullptr)
+			return false;
+
+		// Expected number of items
+		EXPECT_EQ(scene->mNumMeshes, 1u);
+		EXPECT_EQ(scene->mNumMaterials, 1u);
+		EXPECT_EQ(scene->mNumAnimations, 0u);
+		EXPECT_EQ(scene->mNumTextures, 0u);
+		EXPECT_EQ(scene->mNumLights, 1u);
+		EXPECT_EQ(scene->mNumCameras, 1u);
+
+		// Expected common metadata
+		aiString value;
+		EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT, value)) << "No importer format metadata";
+		EXPECT_STREQ("Collada Importer", value.C_Str());
+
+		EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT_VERSION, value)) << "No format version metadata";
+		EXPECT_STREQ("1.4.1", value.C_Str());
+
+		EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_GENERATOR, value)) << "No generator metadata";
+		EXPECT_EQ(strncmp(value.C_Str(), "Maya 8.0", 8), 0) << "AI_METADATA_SOURCE_GENERATOR was: " << value.C_Str();
+
+		EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_COPYRIGHT, value)) << "No copyright metadata";
+		EXPECT_EQ(strncmp(value.C_Str(), "Copyright 2006", 14), 0) << "AI_METADATA_SOURCE_COPYRIGHT was: " << value.C_Str();
+
+		return true;
+	}
 };
 
 TEST_F(utColladaImportExport, importBlenFromFileTest) {
-    EXPECT_TRUE(importerTest());
+	EXPECT_TRUE(importerTest());
 }
 
 class utColladaZaeImportExport : public AbstractImportExportBase {
 public:
-    virtual bool importerTest() {
-        {
-            Assimp::Importer importer;
-            const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.zae", aiProcess_ValidateDataStructure);
-            if (scene == nullptr)
-                return false;
-
-            // Expected number of items
-            EXPECT_EQ(scene->mNumMeshes, 1u);
-            EXPECT_EQ(scene->mNumMaterials, 1u);
-            EXPECT_EQ(scene->mNumAnimations, 0u);
-            EXPECT_EQ(scene->mNumTextures, 1u);
-            EXPECT_EQ(scene->mNumLights, 1u);
-            EXPECT_EQ(scene->mNumCameras, 1u);
-        }
-
-        {
-            Assimp::Importer importer;
-            const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck_nomanifest.zae", aiProcess_ValidateDataStructure);
-            if (scene == nullptr)
-                return false;
-
-            // Expected number of items
-            EXPECT_EQ(scene->mNumMeshes, 1u);
-            EXPECT_EQ(scene->mNumMaterials, 1u);
-            EXPECT_EQ(scene->mNumAnimations, 0u);
-            EXPECT_EQ(scene->mNumTextures, 1u);
-            EXPECT_EQ(scene->mNumLights, 1u);
-            EXPECT_EQ(scene->mNumCameras, 1u);
-        }
-
-        return true;
-    }
+	virtual bool importerTest() {
+		{
+			Assimp::Importer importer;
+			const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.zae", aiProcess_ValidateDataStructure);
+			if (scene == nullptr)
+				return false;
+
+			// Expected number of items
+			EXPECT_EQ(scene->mNumMeshes, 1u);
+			EXPECT_EQ(scene->mNumMaterials, 1u);
+			EXPECT_EQ(scene->mNumAnimations, 0u);
+			EXPECT_EQ(scene->mNumTextures, 1u);
+			EXPECT_EQ(scene->mNumLights, 1u);
+			EXPECT_EQ(scene->mNumCameras, 1u);
+		}
+
+		{
+			Assimp::Importer importer;
+			const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck_nomanifest.zae", aiProcess_ValidateDataStructure);
+			if (scene == nullptr)
+				return false;
+
+			// Expected number of items
+			EXPECT_EQ(scene->mNumMeshes, 1u);
+			EXPECT_EQ(scene->mNumMaterials, 1u);
+			EXPECT_EQ(scene->mNumAnimations, 0u);
+			EXPECT_EQ(scene->mNumTextures, 1u);
+			EXPECT_EQ(scene->mNumLights, 1u);
+			EXPECT_EQ(scene->mNumCameras, 1u);
+		}
+
+		return true;
+	}
 };
 
 TEST_F(utColladaZaeImportExport, importBlenFromFileTest) {
-    EXPECT_TRUE(importerTest());
+	EXPECT_TRUE(importerTest());
 }