From 317f3e2a59059fe689e9182cd922ba185c1a48b6 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Mar 2018 14:10:08 +0100 Subject: [PATCH] 3MF: Export metadata. --- code/D3MFExporter.cpp | 26 +++++++++++ code/D3MFExporter.h | 1 + code/D3MFImporter.cpp | 9 ++-- code/Exporter.cpp | 3 +- include/assimp/metadata.h | 98 ++++++++++++++++++++++++++++++++------- 5 files changed, 116 insertions(+), 21 deletions(-) diff --git a/code/D3MFExporter.cpp b/code/D3MFExporter.cpp index b89e81ce6..950793f44 100644 --- a/code/D3MFExporter.cpp +++ b/code/D3MFExporter.cpp @@ -117,6 +117,7 @@ bool D3MFExporter::exportArchive( const char *file ) { if ( nullptr == m_zipArchive ) { return false; } + ok |= exportContentTypes(); ok |= export3DModel(); ok |= exportRelations(); @@ -181,6 +182,8 @@ bool D3MFExporter::export3DModel() { mModelOutput << "<" << XmlTag::resources << ">"; mModelOutput << std::endl; + writeMetaData(); + writeBaseMaterials(); writeObjects(); @@ -209,6 +212,29 @@ void D3MFExporter::writeHeader() { mModelOutput << std::endl; } +void D3MFExporter::writeMetaData() { + if ( nullptr == mScene->mMetaData ) { + return; + } + + const unsigned int numMetaEntries( mScene->mMetaData->mNumProperties ); + if ( 0 == numMetaEntries ) { + return; + } + + const aiString *key; + const aiMetadataEntry *entry(nullptr); + for ( size_t i = 0; i < numMetaEntries; ++i ) { + mScene->mMetaData->Get( i, key, entry ); + std::string k( key->C_Str() ); + aiString value; + mScene->mMetaData->Get( k, value ); + mModelOutput << "<" << XmlTag::meta << " " << XmlTag::meta_name << "=\"" << key->C_Str() << "\">"; + mModelOutput << value.C_Str(); + mModelOutput << "" << std::endl; + } +} + void D3MFExporter::writeBaseMaterials() { mModelOutput << "\n"; for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) { diff --git a/code/D3MFExporter.h b/code/D3MFExporter.h index b553e0ab5..110862b99 100644 --- a/code/D3MFExporter.h +++ b/code/D3MFExporter.h @@ -76,6 +76,7 @@ public: protected: void writeHeader(); + void writeMetaData(); void writeBaseMaterials(); void writeObjects(); void writeMesh( aiMesh *mesh ); diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 9153b1790..d9f498ebf 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -111,28 +111,31 @@ public: scene->mRootNode->mName.Set( "3MF" ); } + // import the metadata if ( !mMetaData.empty() ) { const size_t numMeta( mMetaData.size() ); scene->mMetaData = aiMetadata::Alloc( numMeta ); for ( size_t i = 0; i < numMeta; ++i ) { aiString val( mMetaData[ i ].value ); - scene->mMetaData->Add( mMetaData[ i ].name, val ); + scene->mMetaData->Set( i, mMetaData[ i ].name, val ); } } + // import the meshes scene->mNumMeshes = static_cast( mMeshes.size()); scene->mMeshes = new aiMesh*[scene->mNumMeshes](); - std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes); + // import the materials scene->mNumMaterials = static_cast( mMatArray.size() ); if ( 0 != scene->mNumMaterials ) { scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ]; std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials ); } + + // create the scenegraph scene->mRootNode->mNumChildren = static_cast(children.size()); scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren](); - std::copy(children.begin(), children.end(), scene->mRootNode->mChildren); } diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 4951c70ef..49523e658 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -308,7 +308,8 @@ bool IsVerboseFormat(const aiScene* pScene) { } // ------------------------------------------------------------------------------------------------ -aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties) { +aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath, + unsigned int pPreprocessing, const ExportProperties* pProperties) { ASSIMP_BEGIN_EXCEPTION_REGION(); // when they create scenes from scratch, users will likely create them not in verbose diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 2dba61abc..70a604de9 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -67,6 +67,7 @@ typedef enum aiMetadataType { AI_DOUBLE = 4, AI_AISTRING = 5, AI_AIVECTOR3D = 6, + AI_META_MAX = 7, #ifndef SWIG FORCE_32BIT = INT_MAX @@ -130,42 +131,103 @@ struct aiMetadata { */ aiMetadata() : mNumProperties(0) - , mKeys(NULL) - , mValues(NULL) { + , mKeys(nullptr) + , mValues(nullptr) { // empty } + aiMetadata( const aiMetadata &rhs ) + : mNumProperties( rhs.mNumProperties ) + , mKeys( nullptr ) + , mValues( nullptr ) { + mKeys = new aiString[ mNumProperties ]; + for ( unsigned int i = 0; i < mNumProperties; ++i ) { + mKeys[ i ] = rhs.mKeys[ i ]; + } + mValues = new aiMetadataEntry[ mNumProperties ]; + for ( unsigned int i = 0; i < mNumProperties; ++i ) { + mValues[ i ].mType = rhs.mValues[ i ].mType; + switch ( rhs.mValues[ i ].mType ) { + case AI_BOOL: + mValues[ i ].mData = new bool( rhs.mValues[i].mData ); + break; + case AI_INT32: { + int32_t v; + ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( int32_t ) ); + mValues[ i ].mData = new int32_t( v ); + } + break; + case AI_UINT64: { + uint64_t v; + ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( uint64_t ) ); + mValues[ i ].mData = new uint64_t( v ); + } + break; + case AI_FLOAT: { + float v; + ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( float ) ); + mValues[ i ].mData = new float( v ); + } + break; + case AI_DOUBLE: { + double v; + ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( double ) ); + mValues[ i ].mData = new double( v ); + } + break; + case AI_AISTRING: { + aiString v; + rhs.Get( mKeys[ i ], v ); + mValues[ i ].mData = new aiString( v ); + } + break; + case AI_AIVECTOR3D: { + aiVector3D v; + rhs.Get( mKeys[ i ], v ); + mValues[ i ].mData = new aiVector3D( v ); + } + break; +#ifndef SWIG + case FORCE_32BIT: +#endif + default: + break; + } + + } + } + /** * @brief The destructor. */ ~aiMetadata() { delete [] mKeys; - mKeys = NULL; + mKeys = nullptr; if (mValues) { // Delete each metadata entry for (unsigned i=0; i(data); + delete static_cast< bool* >( data ); break; case AI_INT32: - delete static_cast(data); + delete static_cast< int32_t* >( data ); break; case AI_UINT64: - delete static_cast(data); + delete static_cast< uint64_t* >( data ); break; case AI_FLOAT: - delete static_cast(data); + delete static_cast< float* >( data ); break; case AI_DOUBLE: - delete static_cast(data); + delete static_cast< double* >( data ); break; case AI_AISTRING: - delete static_cast(data); + delete static_cast< aiString* >( data ); break; case AI_AIVECTOR3D: - delete static_cast(data); + delete static_cast< aiVector3D* >( data ); break; #ifndef SWIG case FORCE_32BIT: @@ -177,7 +239,7 @@ struct aiMetadata { // Delete the metadata array delete [] mValues; - mValues = NULL; + mValues = nullptr; } } @@ -208,8 +270,8 @@ struct aiMetadata { } template - inline void Add(const std::string& key, const T& value) - { + inline + void Add(const std::string& key, const T& value) { aiString* new_keys = new aiString[mNumProperties + 1]; aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1]; @@ -256,7 +318,7 @@ struct aiMetadata { template inline - bool Get( unsigned index, T& value ) { + bool Get( unsigned index, T& value ) const { // In range assertion if ( index >= mNumProperties ) { return false; @@ -277,7 +339,7 @@ struct aiMetadata { template inline - bool Get( const aiString& key, T& value ) { + bool Get( const aiString& key, T& value ) const { // Search for the given key for ( unsigned int i = 0; i < mNumProperties; ++i ) { if ( mKeys[ i ] == key ) { @@ -288,7 +350,8 @@ struct aiMetadata { } template - inline bool Get( const std::string& key, T& value ) { + inline + bool Get( const std::string& key, T& value ) const { return Get(aiString(key), value); } @@ -297,7 +360,8 @@ struct aiMetadata { /// \param [out] pKey - pointer to the key value. /// \param [out] pEntry - pointer to the entry: type and value. /// \return false - if pIndex is out of range, else - true. - inline bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) { + inline + bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) const { if ( index >= mNumProperties ) { return false; }