diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 85aa620d9..8bad9365d 100644 --- a/code/CMakeLists.txt +++ b/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 diff --git a/code/Collada/ColladaExporter.cpp b/code/Collada/ColladaExporter.cpp index a93dfa59a..3e63990b8 100644 --- a/code/Collada/ColladaExporter.cpp +++ b/code/Collada/ColladaExporter.cpp @@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ColladaExporter.h" #include +#include #include #include #include @@ -277,7 +278,7 @@ void ColladaExporter::WriteHeader() { mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; } - if (nullptr == meta || !meta->Get("AuthoringTool", value)) { + if (nullptr == meta || !meta->Get(AI_METADATA_SOURCE_GENERATOR, value)) { mOutput << startstr << "" << "Assimp Exporter" << "" << endstr; } else { mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; @@ -287,7 +288,7 @@ void ColladaExporter::WriteHeader() { if (meta->Get("Comments", value)) { mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; } - if (meta->Get("Copyright", value)) { + if (meta->Get(AI_METADATA_SOURCE_COPYRIGHT, value)) { mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; } if (meta->Get("SourceData", value)) { diff --git a/code/Collada/ColladaHelper.cpp b/code/Collada/ColladaHelper.cpp new file mode 100644 index 000000000..3a22d4db3 --- /dev/null +++ b/code/Collada/ColladaHelper.cpp @@ -0,0 +1,65 @@ +/** 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 + +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; +} + +} // namespace Collada +} // namespace Assimp diff --git a/code/Collada/ColladaHelper.h b/code/Collada/ColladaHelper.h index b7d47da15..f9968f162 100644 --- a/code/Collada/ColladaHelper.h +++ b/code/Collada/ColladaHelper.h @@ -104,6 +104,11 @@ enum MorphMethod Relative }; +/** Common metadata keys as */ +typedef std::pair MetaKeyPair; +typedef std::vector MetaKeyPairVector; + +const MetaKeyPairVector &GetColladaAssimpMetaKeys(); /** Contains all data for one of the different transformation types */ struct Transform diff --git a/code/Collada/ColladaParser.cpp b/code/Collada/ColladaParser.cpp index e2e6626c3..1b5b3b4d6 100644 --- a/code/Collada/ColladaParser.cpp +++ b/code/Collada/ColladaParser.cpp @@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "ColladaParser.h" +#include #include #include #include @@ -276,6 +277,9 @@ void ColladaParser::ReadContents() if (attrib != -1) { const char* version = mReader->getAttributeValue(attrib); + // Store declared format version string + mAssetMetaData.emplace(AI_METADATA_SOURCE_FORMAT_VERSION, version); + if (!::strncmp(version, "1.5", 3)) { mFormat = FV_1_5_n; ASSIMP_LOG_DEBUG("Collada schema version is 1.5.n"); @@ -399,7 +403,7 @@ void ColladaParser::ReadAssetInfo() } else { - ReadMetaDataItem(mAssetMetaData); + ReadMetaDataItem(mAssetMetaData, GetColladaAssimpMetaKeys()); } } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) @@ -423,7 +427,7 @@ void ColladaParser::ReadContributorInfo() { if (mReader->getNodeType() == irr::io::EXN_ELEMENT) { - ReadMetaDataItem(mAssetMetaData); + ReadMetaDataItem(mAssetMetaData, GetColladaAssimpMetaKeys()); } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { @@ -434,23 +438,36 @@ void ColladaParser::ReadContributorInfo() } } +bool FindCommonKey(const char *collada_key, const MetaKeyPairVector &key_renaming, size_t &found_index) { + for (size_t i = 0; i < key_renaming.size(); ++i) { + if (strcmp(key_renaming[i].first, collada_key) == 0) { + found_index = i; + return true; + } + } + 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 MetaKeyPairVector &key_renaming) { + // 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); + + size_t found_index; + if (FindCommonKey(key_str.c_str(), key_renaming, found_index)) { + metadata.emplace(key_renaming[found_index].second, aistr); + } else { + std::string camel_key_str(key_str); + ToCamelCase(camel_key_str); + metadata.emplace(camel_key_str, aistr); + } } TestClosing(key_str.c_str()); } diff --git a/code/Collada/ColladaParser.h b/code/Collada/ColladaParser.h index 4e8c8fccf..57d644aef 100644 --- a/code/Collada/ColladaParser.h +++ b/code/Collada/ColladaParser.h @@ -94,8 +94,8 @@ namespace Assimp /** Reads contributor information such as author and legal blah */ void ReadContributorInfo(); - /** Reads generic metadata into provided map */ - void ReadMetaDataItem(StringMetaData &metadata); + /** Reads generic metadata into provided map and renames keys for Assimp */ + void ReadMetaDataItem(StringMetaData &metadata, const Collada::MetaKeyPairVector &key_renaming); /** Convert underscore_seperated to CamelCase "authoring_tool" becomes "AuthoringTool" */ static void ToCamelCase(std::string &text); diff --git a/include/assimp/commonMetaData.h b/include/assimp/commonMetaData.h index 1e176725e..cca21ed2a 100644 --- a/include/assimp/commonMetaData.h +++ b/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 diff --git a/test/unit/utColladaImportExport.cpp b/test/unit/utColladaImportExport.cpp index 8bce3a3dd..1350d3607 100644 --- a/test/unit/utColladaImportExport.cpp +++ b/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 -#include +#include #include +#include +#include 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; + 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 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; - } + // 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)); + 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; + 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); - } + // 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; + { + 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); - } + // 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; - } + return true; + } }; TEST_F(utColladaZaeImportExport, importBlenFromFileTest) { - EXPECT_TRUE(importerTest()); + EXPECT_TRUE(importerTest()); }