From 69742670dd55b256923bed0feb52d45146af97c8 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 9 Mar 2018 11:40:45 +0100 Subject: [PATCH 01/13] 3mf: use correct material assignment in case of multi-materials. --- code/3MFXmlTags.h | 1 + code/BaseImporter.cpp | 16 ++++----- code/D3MFExporter.cpp | 7 +++- code/D3MFExporter.h | 1 + code/D3MFImporter.cpp | 78 +++++++++++++++++++++++++++++++---------- code/D3MFOpcPackage.cpp | 59 ++++++++++++++++--------------- code/D3MFOpcPackage.h | 9 ++--- 7 files changed, 110 insertions(+), 61 deletions(-) diff --git a/code/3MFXmlTags.h b/code/3MFXmlTags.h index c4da2970d..feedf4538 100644 --- a/code/3MFXmlTags.h +++ b/code/3MFXmlTags.h @@ -74,6 +74,7 @@ namespace XmlTag { // 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"; diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index e7736d8a4..67c743285 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -115,13 +115,12 @@ void BaseImporter::SetupProperties(const Importer* /*pImp*/) } // ------------------------------------------------------------------------------------------------ -void BaseImporter::GetExtensionList(std::set& extensions) -{ +void BaseImporter::GetExtensionList(std::set& extensions) { const aiImporterDesc* desc = GetInfo(); - ai_assert(desc != NULL); + ai_assert(desc != nullptr); const char* ext = desc->mFileExtensions; - ai_assert(ext != NULL); + ai_assert(ext != nullptr ); const char* last = ext; do { @@ -145,12 +144,13 @@ void BaseImporter::GetExtensionList(std::set& extensions) unsigned int searchBytes /* = 200 */, bool tokensSol /* false */) { - ai_assert( NULL != tokens ); + ai_assert( nullptr != tokens ); ai_assert( 0 != numTokens ); ai_assert( 0 != searchBytes); - if (!pIOHandler) + if ( nullptr == pIOHandler ) { return false; + } std::unique_ptr pStream (pIOHandler->Open(pFile)); if (pStream.get() ) { @@ -179,9 +179,9 @@ void BaseImporter::GetExtensionList(std::set& extensions) *cur2 = '\0'; std::string token; - for (unsigned int i = 0; i < numTokens;++i) { + for (unsigned int i = 0; i < numTokens; ++i ) { ai_assert( nullptr != tokens[i] ); - size_t len( strlen( tokens[ i ] ) ); + const size_t len( strlen( tokens[ i ] ) ); token.clear(); const char *ptr( tokens[ i ] ); for ( size_t tokIdx = 0; tokIdx < len; ++tokIdx ) { diff --git a/code/D3MFExporter.cpp b/code/D3MFExporter.cpp index 91f06fc87..a74280af7 100644 --- a/code/D3MFExporter.cpp +++ b/code/D3MFExporter.cpp @@ -126,7 +126,6 @@ bool D3MFExporter::exportArchive( const char *file ) { return ok; } - bool D3MFExporter::exportContentTypes() { mContentOutput.clear(); @@ -177,6 +176,8 @@ bool D3MFExporter::export3DModel() { mModelOutput << "<" << XmlTag::resources << ">"; mModelOutput << std::endl; + writeBaseMaterials(); + writeObjects(); @@ -203,6 +204,10 @@ void D3MFExporter::writeHeader() { mModelOutput << std::endl; } +void D3MFExporter::writeBaseMaterials() { + +} + void D3MFExporter::writeObjects() { if ( nullptr == mScene->mRootNode ) { return; diff --git a/code/D3MFExporter.h b/code/D3MFExporter.h index 64967f68b..7e6e44e6e 100644 --- a/code/D3MFExporter.h +++ b/code/D3MFExporter.h @@ -76,6 +76,7 @@ public: protected: void writeHeader(); + void writeBaseMaterials(); void writeObjects(); void writeMesh( aiMesh *mesh ); void writeVertex( const aiVector3D &pos ); diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index fe5e260a4..7c0954524 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -70,9 +70,14 @@ namespace D3MF { class XmlSerializer { public: + using MatArray = std::vector; + using MatId2MatArray = std::map>; + XmlSerializer(XmlReader* xmlReader) : mMeshes() - , mMaterials() + , mMatArray() + , mActiveMatGroup( 99999999 ) + , mMatId2MatArray() , xmlReader(xmlReader){ // empty } @@ -109,10 +114,10 @@ public: std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes); - scene->mNumMaterials = mMaterials.size(); + scene->mNumMaterials = mMatArray.size(); if ( 0 != scene->mNumMaterials ) { scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ]; - std::copy( mMaterials.begin(), mMaterials.end(), scene->mMaterials ); + std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials ); } scene->mRootNode->mNumChildren = static_cast(children.size()); scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren](); @@ -162,7 +167,7 @@ private: return node.release(); } - aiMesh* ReadMesh() { + aiMesh *ReadMesh() { aiMesh* mesh = new aiMesh(); while(ReadToEndElement(D3MF::XmlTag::mesh)) { if(xmlReader->getNodeName() == D3MF::XmlTag::vertices) { @@ -177,7 +182,6 @@ private: void ImportVertices(aiMesh* mesh) { std::vector vertices; - while(ReadToEndElement(D3MF::XmlTag::vertices)) { if(xmlReader->getNodeName() == D3MF::XmlTag::vertex) { vertices.push_back(ReadVertex()); @@ -234,8 +238,27 @@ private: } void ReadBaseMaterials() { + std::vector MatIdArray; + const char *baseMaterialId( xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_id.c_str() ) ); + if ( nullptr != baseMaterialId ) { + unsigned int id = std::atoi( baseMaterialId ); + const size_t newMatIdx( mMatArray.size() ); + if ( id != mActiveMatGroup ) { + mActiveMatGroup = id; + MatId2MatArray::const_iterator it( mMatId2MatArray.find( id ) ); + if ( mMatId2MatArray.end() == it ) { + MatIdArray.clear(); + mMatId2MatArray[ id ] = MatIdArray; + } else { + MatIdArray = it->second; + } + } + MatIdArray.push_back( newMatIdx ); + mMatId2MatArray[ mActiveMatGroup ] = MatIdArray; + } + while ( ReadToEndElement( D3MF::XmlTag::basematerials ) ) { - mMaterials.push_back( readMaterialDef() ); + mMatArray.push_back( readMaterialDef() ); xmlReader->read(); } } @@ -285,24 +308,37 @@ private: return true; } + void assignDiffuseColor( aiMaterial *mat ) { + const char *color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() ); + aiColor4D diffuse; + if ( parseColor( color, diffuse ) ) { + mat->AddProperty( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE ); + } + + } aiMaterial *readMaterialDef() { aiMaterial *mat( nullptr ); const char *name( nullptr ); - const char *color( nullptr ); const std::string nodeName( xmlReader->getNodeName() ); if ( nodeName == D3MF::XmlTag::basematerials_base ) { name = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_name.c_str() ); - + std::string stdMatName; aiString matName; - matName.Set( name ); + std::string strId( to_string( mActiveMatGroup ) ); + stdMatName += "id"; + stdMatName += strId; + stdMatName += "_"; + if ( nullptr != name ) { + stdMatName += std::string( name ); + } else { + stdMatName += "basemat"; + } + matName.Set( stdMatName ); + mat = new aiMaterial; mat->AddProperty( &matName, AI_MATKEY_NAME ); - color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() ); - aiColor4D diffuse; - if ( parseColor( color, diffuse ) ) { - mat->AddProperty( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE ); - } + assignDiffuseColor( mat ); } return mat; @@ -339,7 +375,9 @@ private: private: std::vector mMeshes; - std::vector mMaterials; + MatArray mMatArray; + unsigned int mActiveMatGroup; + MatId2MatArray mMatId2MatArray; XmlReader* xmlReader; }; @@ -370,14 +408,16 @@ D3MFImporter::~D3MFImporter() { // empty } -bool D3MFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { - const std::string extension = GetExtension(pFile); +bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const { + const std::string extension( GetExtension( filename ) ); if(extension == Extension ) { return true; } else if ( !extension.length() || checkSig ) { - if (nullptr == pIOHandler ) { - return true; + if ( nullptr == pIOHandler ) { + return false; } + D3MF::D3MFOpcPackage opcPackage( pIOHandler, filename ); + return opcPackage.validate(); } return false; diff --git a/code/D3MFOpcPackage.cpp b/code/D3MFOpcPackage.cpp index a7039d34e..81d610e15 100644 --- a/code/D3MFOpcPackage.cpp +++ b/code/D3MFOpcPackage.cpp @@ -247,13 +247,13 @@ private: // ------------------------------------------------------------------------------------------------ // Constructor. D3MFZipArchive::D3MFZipArchive(IOSystem* pIOHandler, const std::string& rFile) -: m_ZipFileHandle(NULL) +: m_ZipFileHandle( nullptr ) , m_ArchiveMap() { if (! rFile.empty()) { zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler); m_ZipFileHandle = unzOpen2(rFile.c_str(), &mapping); - if(m_ZipFileHandle != NULL) { + if(m_ZipFileHandle != nullptr ) { mapArchive(); } } @@ -267,32 +267,32 @@ D3MFZipArchive::~D3MFZipArchive() { } m_ArchiveMap.clear(); - if(m_ZipFileHandle != NULL) { + if(m_ZipFileHandle != nullptr) { unzClose(m_ZipFileHandle); - m_ZipFileHandle = NULL; + m_ZipFileHandle = nullptr; } } // ------------------------------------------------------------------------------------------------ // Returns true, if the archive is already open. bool D3MFZipArchive::isOpen() const { - return (m_ZipFileHandle != NULL); + return (m_ZipFileHandle != nullptr ); } // ------------------------------------------------------------------------------------------------ // Returns true, if the filename is part of the archive. bool D3MFZipArchive::Exists(const char* pFile) const { - ai_assert(pFile != NULL); + ai_assert(pFile != nullptr ); - bool exist = false; + if ( pFile == nullptr ) { + return false; + } - if (pFile != NULL) { - std::string rFile(pFile); - std::map::const_iterator it = m_ArchiveMap.find(rFile); - - if(it != m_ArchiveMap.end()) { - exist = true; - } + std::string rFile(pFile); + std::map::const_iterator it = m_ArchiveMap.find(rFile); + bool exist( false ); + if(it != m_ArchiveMap.end()) { + exist = true; } return exist; @@ -434,8 +434,8 @@ public: std::vector m_relationShips; }; -// ------------------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------------------ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile) : mRootStream(nullptr) , mZipArchive() { @@ -460,7 +460,7 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile) if ( rootFile.size() > 0 && rootFile[ 0 ] == '/' ) { rootFile = rootFile.substr( 1 ); if ( rootFile[ 0 ] == '/' ) { - // deal with zipbug + // deal with zip-bug rootFile = rootFile.substr( 1 ); } } @@ -470,18 +470,9 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile) mRootStream = mZipArchive->Open(rootFile.c_str()); ai_assert( mRootStream != nullptr ); if ( nullptr == mRootStream ) { - throw DeadlyExportError( "Cannot open rootfile in archive : " + rootFile ); + throw DeadlyExportError( "Cannot open root-file in archive : " + rootFile ); } - // const size_t size = zipArchive->FileSize(); - // m_Data.resize( size ); - - // const size_t readSize = pMapFile->Read( &m_Data[0], sizeof( char ), size ); - // if ( readSize != size ) - // { - // m_Data.clear(); - // return false; - // } mZipArchive->Close( fileStream ); } else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) { @@ -498,6 +489,16 @@ IOStream* D3MFOpcPackage::RootStream() const { return mRootStream; } +static const std::string ModelRef = "3D/3dmodel.model"; + +bool D3MFOpcPackage::validate() { + if ( nullptr == mRootStream || nullptr == mZipArchive ) { + return false; + } + + return mZipArchive->Exists( ModelRef.c_str() ); +} + std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) { std::unique_ptr xmlStream(new CIrrXML_IOStreamReader(stream)); std::unique_ptr xml(irr::io::createIrrXMLReader(xmlStream.get())); @@ -508,14 +509,14 @@ std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) { return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE; }); - if(itr == reader.m_relationShips.end()) - throw DeadlyImportError("Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE); + if ( itr == reader.m_relationShips.end() ) { + throw DeadlyImportError( "Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE ); + } return (*itr)->target; } } // Namespace D3MF - } // Namespace Assimp #endif //ASSIMP_BUILD_NO_3MF_IMPORTER diff --git a/code/D3MFOpcPackage.h b/code/D3MFOpcPackage.h index 8cf08d092..b49740eff 100644 --- a/code/D3MFOpcPackage.h +++ b/code/D3MFOpcPackage.h @@ -51,8 +51,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace D3MF { -typedef irr::io::IrrXMLReader XmlReader; -typedef std::shared_ptr XmlReaderPtr; +using XmlReader = irr::io::IrrXMLReader ; +using XmlReaderPtr = std::shared_ptr ; struct OpcPackageRelationship { std::string id; @@ -67,6 +67,7 @@ public: D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile); ~D3MFOpcPackage(); IOStream* RootStream() const; + bool validate(); protected: std::string ReadPackageRootRelationship(IOStream* stream); @@ -76,7 +77,7 @@ private: std::unique_ptr mZipArchive; }; -} -} +} // Namespace D3MF +} // Namespace Assimp #endif // D3MFOPCPACKAGE_H From 6668eeb68eaeeff2b0686d07d7ec6e1cdf88c882 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 9 Mar 2018 19:03:05 +0100 Subject: [PATCH 02/13] Fix possible nullptr dereferencing. --- code/D3MFExporter.cpp | 42 ++++++++++++++++++++++++++++++++++++-- include/assimp/fast_atof.h | 2 -- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/code/D3MFExporter.cpp b/code/D3MFExporter.cpp index a74280af7..98b15b10b 100644 --- a/code/D3MFExporter.cpp +++ b/code/D3MFExporter.cpp @@ -49,8 +49,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include - +#include #include + #include "3MFXmlTags.h" #include "D3MFOpcPackage.h" @@ -204,8 +205,45 @@ void D3MFExporter::writeHeader() { mModelOutput << std::endl; } -void D3MFExporter::writeBaseMaterials() { +static std::string to_hex( int to_convert ) { + std::string result; + std::stringstream ss; + ss << std::hex << to_convert; + ss >> result; + return result; +} +void D3MFExporter::writeBaseMaterials() { + mModelOutput << "\n"; + for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) { + aiMaterial *mat = mScene->mMaterials[ i ]; + std::string strName; + aiString name; + if ( mat->Get( AI_MATKEY_NAME, name ) != aiReturn_SUCCESS ) { + strName = "basemat_" + to_string( i ); + } else { + strName = name.C_Str(); + } + std::string hexDiffuseColor; + aiColor4D color; + if ( mat->Get( AI_MATKEY_COLOR_DIFFUSE, color ) == aiReturn_SUCCESS ) { + hexDiffuseColor = "#"; + std::string tmp; + tmp = to_hex( color.r ); + hexDiffuseColor += tmp; + tmp = to_hex( color.g ); + hexDiffuseColor += tmp; + tmp = to_hex( color.b ); + hexDiffuseColor += tmp; + tmp = to_hex( color.a ); + hexDiffuseColor += tmp; + } else { + hexDiffuseColor = "#FFFFFFFF"; + } + + mModelOutput << "\n"; + } + mModelOutput << "\n"; } void D3MFExporter::writeObjects() { diff --git a/include/assimp/fast_atof.h b/include/assimp/fast_atof.h index fced5307a..e66f1b37d 100644 --- a/include/assimp/fast_atof.h +++ b/include/assimp/fast_atof.h @@ -146,7 +146,6 @@ uint8_t HexOctetToDecimal(const char* in) { return ((uint8_t)HexDigitToDecimal(in[0])<<4)+(uint8_t)HexDigitToDecimal(in[1]); } - // ------------------------------------------------------------------------------------ // signed variant of strtoul10 // ------------------------------------------------------------------------------------ @@ -353,7 +352,6 @@ ai_real fast_atof(const char* c) { return ret; } - inline ai_real fast_atof( const char* c, const char** cout) { ai_real ret(0.0); From 336a09ee0e47f5520eb3032d7b377982176fbe6d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 9 Mar 2018 23:35:12 +0100 Subject: [PATCH 03/13] add material reference to faces. --- code/ConvertToLHProcess.cpp | 26 +++++++++++++++++--------- code/D3MFExporter.cpp | 9 ++++++--- code/D3MFExporter.h | 2 +- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/code/ConvertToLHProcess.cpp b/code/ConvertToLHProcess.cpp index 47e2fb949..ba8371439 100644 --- a/code/ConvertToLHProcess.cpp +++ b/code/ConvertToLHProcess.cpp @@ -91,12 +91,14 @@ void MakeLeftHandedProcess::Execute( aiScene* pScene) ProcessNode( pScene->mRootNode, aiMatrix4x4()); // process the meshes accordingly - for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) - ProcessMesh( pScene->mMeshes[a]); + for ( unsigned int a = 0; a < pScene->mNumMeshes; ++a ) { + ProcessMesh( pScene->mMeshes[ a ] ); + } // process the materials accordingly - for( unsigned int a = 0; a < pScene->mNumMaterials; ++a) - ProcessMaterial( pScene->mMaterials[a]); + for ( unsigned int a = 0; a < pScene->mNumMaterials; ++a ) { + ProcessMaterial( pScene->mMaterials[ a ] ); + } // transform all animation channels as well for( unsigned int a = 0; a < pScene->mNumAnimations; a++) @@ -136,8 +138,11 @@ void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pPare // ------------------------------------------------------------------------------------------------ // Converts a single mesh to left handed coordinates. -void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) -{ +void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) { + if ( nullptr == pMesh ) { + DefaultLogger::get()->error( "Nullptr to mesh found." ); + return; + } // mirror positions, normals and stuff along the Z axis for( size_t a = 0; a < pMesh->mNumVertices; ++a) { @@ -173,8 +178,12 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) // ------------------------------------------------------------------------------------------------ // Converts a single material to left handed coordinates. -void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) -{ +void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) { + if ( nullptr == _mat ) { + DefaultLogger::get()->error( "Nullptr to aiMaterial found." ); + return; + } + aiMaterial* mat = (aiMaterial*)_mat; for (unsigned int a = 0; a < mat->mNumProperties;++a) { aiMaterialProperty* prop = mat->mProperties[a]; @@ -183,7 +192,6 @@ void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) if (!::strcmp( prop->mKey.data, "$tex.mapaxis")) { ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */ aiVector3D* pff = (aiVector3D*)prop->mData; - pff->z *= -1.f; } } diff --git a/code/D3MFExporter.cpp b/code/D3MFExporter.cpp index 98b15b10b..7c75178e6 100644 --- a/code/D3MFExporter.cpp +++ b/code/D3MFExporter.cpp @@ -285,7 +285,9 @@ void D3MFExporter::writeMesh( aiMesh *mesh ) { } mModelOutput << "" << std::endl; - writeFaces( mesh ); + const unsigned int matIdx( mesh->mMaterialIndex ); + + writeFaces( mesh, matIdx ); mModelOutput << "" << std::endl; } @@ -295,7 +297,7 @@ void D3MFExporter::writeVertex( const aiVector3D &pos ) { mModelOutput << std::endl; } -void D3MFExporter::writeFaces( aiMesh *mesh ) { +void D3MFExporter::writeFaces( aiMesh *mesh, unsigned int matIdx ) { if ( nullptr == mesh ) { return; } @@ -307,7 +309,8 @@ void D3MFExporter::writeFaces( aiMesh *mesh ) { for ( unsigned int i = 0; i < mesh->mNumFaces; ++i ) { aiFace ¤tFace = mesh->mFaces[ i ]; mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[ 0 ] << "\" v2=\"" - << currentFace.mIndices[ 1 ] << "\" v3=\"" << currentFace.mIndices[ 2 ] << "\"/>"; + << currentFace.mIndices[ 1 ] << "\" v3=\"" << currentFace.mIndices[ 2 ] + << "\" pid=\"1\" p1=\""+to_string(matIdx)+"\" />"; mModelOutput << std::endl; } mModelOutput << ""; diff --git a/code/D3MFExporter.h b/code/D3MFExporter.h index 7e6e44e6e..b553e0ab5 100644 --- a/code/D3MFExporter.h +++ b/code/D3MFExporter.h @@ -80,7 +80,7 @@ protected: void writeObjects(); void writeMesh( aiMesh *mesh ); void writeVertex( const aiVector3D &pos ); - void writeFaces( aiMesh *mesh ); + void writeFaces( aiMesh *mesh, unsigned int matIdx ); void writeBuild(); void exportContentTyp( const std::string &filename ); void writeModelToArchive( const std::string &folder, const std::string &modelName ); From 017b7d1a2f51a4f62047c98f987704fc9fabebe4 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 11 Mar 2018 20:15:25 +0100 Subject: [PATCH 04/13] 3MF: add missig tags for meta data. --- code/3MFXmlTags.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/3MFXmlTags.h b/code/3MFXmlTags.h index feedf4538..e869c33c1 100644 --- a/code/3MFXmlTags.h +++ b/code/3MFXmlTags.h @@ -45,6 +45,10 @@ namespace Assimp { namespace D3MF { namespace XmlTag { + // Meta-data + static const std::string meta = "metadata"; + static const std::string meta_name = "name"; + // Model-data specific tags static const std::string model = "model"; static const std::string model_unit = "unit"; From c8ae0bbb3d43384fde27c28c93343b0f885dc5e8 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 11 Mar 2018 20:15:49 +0100 Subject: [PATCH 05/13] 3MF: fix model folder desc. --- code/D3MFExporter.cpp | 25 +++++++++++-------------- code/D3MFImporter.cpp | 6 ++---- include/assimp/StringUtils.h | 36 +++++++++++++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/code/D3MFExporter.cpp b/code/D3MFExporter.cpp index 7c75178e6..b89e81ce6 100644 --- a/code/D3MFExporter.cpp +++ b/code/D3MFExporter.cpp @@ -153,7 +153,11 @@ bool D3MFExporter::exportRelations() { mRelOutput << ""; for ( size_t i = 0; i < mRelations.size(); ++i ) { - mRelOutput << "target << "\" "; + if ( mRelations[ i ]->target[ 0 ] == '/' ) { + mRelOutput << "target << "\" "; + } else { + mRelOutput << "target << "\" "; + } mRelOutput << "Id=\"" << mRelations[i]->id << "\" "; mRelOutput << "Type=\"" << mRelations[ i ]->type << "\" />"; mRelOutput << std::endl; @@ -205,14 +209,6 @@ void D3MFExporter::writeHeader() { mModelOutput << std::endl; } -static std::string to_hex( int to_convert ) { - std::string result; - std::stringstream ss; - ss << std::hex << to_convert; - ss >> result; - return result; -} - void D3MFExporter::writeBaseMaterials() { mModelOutput << "\n"; for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) { @@ -229,19 +225,20 @@ void D3MFExporter::writeBaseMaterials() { if ( mat->Get( AI_MATKEY_COLOR_DIFFUSE, color ) == aiReturn_SUCCESS ) { hexDiffuseColor = "#"; std::string tmp; - tmp = to_hex( color.r ); + + tmp = DecimalToHexa( color.r ); hexDiffuseColor += tmp; - tmp = to_hex( color.g ); + tmp = DecimalToHexa( color.g ); hexDiffuseColor += tmp; - tmp = to_hex( color.b ); + tmp = DecimalToHexa( color.b ); hexDiffuseColor += tmp; - tmp = to_hex( color.a ); + tmp = DecimalToHexa( color.a ); hexDiffuseColor += tmp; } else { hexDiffuseColor = "#FFFFFFFF"; } - mModelOutput << "\n"; + mModelOutput << "\n"; } mModelOutput << "\n"; } diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 7c0954524..1732a5a8a 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -259,7 +259,6 @@ private: while ( ReadToEndElement( D3MF::XmlTag::basematerials ) ) { mMatArray.push_back( readMaterialDef() ); - xmlReader->read(); } } @@ -398,7 +397,6 @@ static const aiImporterDesc desc = { Extension.c_str() }; - D3MFImporter::D3MFImporter() : BaseImporter() { // empty @@ -431,8 +429,8 @@ const aiImporterDesc *D3MFImporter::GetInfo() const { return &desc; } -void D3MFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { - D3MF::D3MFOpcPackage opcPackage(pIOHandler, pFile); +void D3MFImporter::InternReadFile( const std::string &filename, aiScene *pScene, IOSystem *pIOHandler ) { + D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename); std::unique_ptr xmlStream(new CIrrXML_IOStreamReader(opcPackage.RootStream())); std::unique_ptr xmlReader(irr::io::createIrrXMLReader(xmlStream.get())); diff --git a/include/assimp/StringUtils.h b/include/assimp/StringUtils.h index 3c3afd264..157454126 100644 --- a/include/assimp/StringUtils.h +++ b/include/assimp/StringUtils.h @@ -55,7 +55,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /// @return The number of written characters if the buffer size was big enough. If an encoding error occurs, a negative number is returned. #if defined(_MSC_VER) && _MSC_VER < 1900 - inline int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) { + inline + int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) { int count(-1); if (0 != size) { count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); @@ -67,7 +68,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return count; } - inline int ai_snprintf(char *outBuf, size_t size, const char *format, ...) { + inline + int ai_snprintf(char *outBuf, size_t size, const char *format, ...) { int count; va_list ap; @@ -82,14 +84,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # define ai_snprintf snprintf #endif +/// @fn to_string +/// @brief The portable version of to_string ( some gcc-versions on embedded devices are not supporting this). +/// @param value The value to write into the std::string. +/// @return The value as a std::string template inline std::string to_string( T value ) { std::ostringstream os; os << value; + return os.str(); } +/// @fn ai_strtof +/// @brief The portable version of strtof. +/// @param begin The first character of the string. +/// @param end The last character +/// @return The float value, 0.0f in cas of an error. inline float ai_strtof( const char *begin, const char *end ) { if ( nullptr == begin ) { @@ -107,5 +119,23 @@ float ai_strtof( const char *begin, const char *end ) { return val; } -#endif // INCLUDED_AI_STRINGUTILS_H +/// @fn DecimalToHexa +/// @brief The portable to convert a decimal value into a hexadecimal string. +/// @param toConvert Value to convert +/// @return The hexadecimal string, is empty in case of an error. +template +inline +std::string DecimalToHexa( T toConvert ) { + std::string result; + std::stringstream ss; + ss << std::hex << toConvert; + ss >> result; + for ( size_t i = 0; i < result.size(); ++i ) { + result[ i ] = toupper( result[ i ] ); + } + + return result; +} + +#endif // INCLUDED_AI_STRINGUTILS_H From c7ac32f891a16cc49fcca9b656feec75c116de76 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 12 Mar 2018 22:28:00 +0100 Subject: [PATCH 06/13] fix naming readout + export. --- code/D3MFImporter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 1732a5a8a..fce2743fe 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -133,11 +133,11 @@ private: const char *attrib( nullptr ); std::string name, type; - attrib = xmlReader->getAttributeValue( D3MF::XmlTag::name.c_str() ); + attrib = xmlReader->getAttributeValue( D3MF::XmlTag::id.c_str() ); if ( nullptr != attrib ) { name = attrib; } - attrib = xmlReader->getAttributeValue( D3MF::XmlTag::name.c_str() ); + attrib = xmlReader->getAttributeValue( D3MF::XmlTag::type.c_str() ); if ( nullptr != attrib ) { type = attrib; } From f11d4902c626e08a949f83eefcb38483c3edc5e9 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Mar 2018 17:50:34 +0100 Subject: [PATCH 07/13] fix CanRead-method for the 3MF-Importer. --- code/D3MFImporter.cpp | 3 +++ code/D3MFOpcPackage.cpp | 9 +++++++++ code/D3MFOpcPackage.h | 3 ++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index fce2743fe..c5b4a8c91 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -414,6 +414,9 @@ bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bo if ( nullptr == pIOHandler ) { return false; } + if ( !D3MF::D3MFOpcPackage::isZipArchive( pIOHandler, filename ) ) { + return false; + } D3MF::D3MFOpcPackage opcPackage( pIOHandler, filename ); return opcPackage.validate(); } diff --git a/code/D3MFOpcPackage.cpp b/code/D3MFOpcPackage.cpp index 81d610e15..2f7c8a25e 100644 --- a/code/D3MFOpcPackage.cpp +++ b/code/D3MFOpcPackage.cpp @@ -499,6 +499,15 @@ bool D3MFOpcPackage::validate() { return mZipArchive->Exists( ModelRef.c_str() ); } +bool D3MFOpcPackage::isZipArchive( IOSystem* pIOHandler, const std::string& rFile ) { + D3MF::D3MFZipArchive ar( pIOHandler, rFile ); + if ( !ar.isOpen() ) { + return false; + } + + return true; +} + std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) { std::unique_ptr xmlStream(new CIrrXML_IOStreamReader(stream)); std::unique_ptr xml(irr::io::createIrrXMLReader(xmlStream.get())); diff --git a/code/D3MFOpcPackage.h b/code/D3MFOpcPackage.h index b49740eff..6d7b3d478 100644 --- a/code/D3MFOpcPackage.h +++ b/code/D3MFOpcPackage.h @@ -64,10 +64,11 @@ class D3MFZipArchive; class D3MFOpcPackage { public: - D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile); + D3MFOpcPackage( IOSystem* pIOHandler, const std::string& rFile ); ~D3MFOpcPackage(); IOStream* RootStream() const; bool validate(); + static bool isZipArchive( IOSystem* pIOHandler, const std::string& rFile ); protected: std::string ReadPackageRootRelationship(IOStream* stream); From 6b9add5594185afdc90f58c385bb78cf7699fa70 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Mar 2018 18:19:10 +0100 Subject: [PATCH 08/13] fix compiler warning fr 64 bit --- code/D3MFImporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index c5b4a8c91..3fffa5aeb 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -114,7 +114,7 @@ public: std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes); - scene->mNumMaterials = mMatArray.size(); + scene->mNumMaterials = static_cast( mMatArray.size() ); if ( 0 != scene->mNumMaterials ) { scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ]; std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials ); From f857d72dbbb07177e80f80af639f1c7e685f7ddd Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Mar 2018 18:56:47 +0100 Subject: [PATCH 09/13] add roundtrip test for 3mf. --- test/unit/utD3MFImportExport.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/unit/utD3MFImportExport.cpp b/test/unit/utD3MFImportExport.cpp index 3aefeba84..dd54b3042 100644 --- a/test/unit/utD3MFImportExport.cpp +++ b/test/unit/utD3MFImportExport.cpp @@ -86,4 +86,11 @@ TEST_F( utD3MFImporterExporter, export3MFtoMemTest ) { EXPECT_TRUE( exporterTest() ); } +TEST_F( utD3MFImporterExporter, roundtrip3MFtoMemTest ) { + EXPECT_TRUE( exporterTest() ); + + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "test.3mf", 0 ); +} + #endif // ASSIMP_BUILD_NO_EXPORT From 18e9aa13d6a603983e25675bb7a376caf45c3c02 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Mar 2018 19:15:56 +0100 Subject: [PATCH 10/13] fix vs2017-compiler-warning c4002: tr1 is deprecated. --- test/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a9dfaf83f..049dbcdd2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -45,7 +45,9 @@ INCLUDE_DIRECTORIES( ${Assimp_SOURCE_DIR}/include ${Assimp_SOURCE_DIR}/code ) - +if (MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING") +endif() # Add the temporary output directories to the library path to make sure the # Assimp library can be found, even if it is not installed system-wide yet. LINK_DIRECTORIES( ${Assimp_BINARY_DIR} ${AssetImporter_BINARY_DIR}/lib ) From 20c817bc36e9f7cc16abbba8a0b613de910faf43 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Mar 2018 19:42:06 +0100 Subject: [PATCH 11/13] Update utD3MFImportExport.cpp Fix compiler warning: unused var. --- test/unit/utD3MFImportExport.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/utD3MFImportExport.cpp b/test/unit/utD3MFImportExport.cpp index dd54b3042..e8797d74d 100644 --- a/test/unit/utD3MFImportExport.cpp +++ b/test/unit/utD3MFImportExport.cpp @@ -91,6 +91,7 @@ TEST_F( utD3MFImporterExporter, roundtrip3MFtoMemTest ) { Assimp::Importer importer; const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "test.3mf", 0 ); + EXPECT_NE( nullptr, scene ); } #endif // ASSIMP_BUILD_NO_EXPORT From 4c023c3818252c1102c5dc2bca200d0a9fff9d8b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Mar 2018 21:40:23 +0100 Subject: [PATCH 12/13] fix unittest folder for roundtriptest. --- code/IRRLoader.cpp | 20 ++++++++------------ test/unit/utD3MFImportExport.cpp | 2 +- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/code/IRRLoader.cpp b/code/IRRLoader.cpp index fbec3da00..66d15c5c4 100644 --- a/code/IRRLoader.cpp +++ b/code/IRRLoader.cpp @@ -100,26 +100,22 @@ IRRImporter::~IRRImporter() // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool IRRImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - /* NOTE: A simple check for the file extension is not enough - * here. Irrmesh and irr are easy, but xml is too generic - * and could be collada, too. So we need to open the file and - * search for typical tokens. - */ +bool IRRImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { const std::string extension = GetExtension(pFile); - - if (extension == "irr")return true; - else if (extension == "xml" || checkSig) - { + if ( extension == "irr" ) { + return true; + } else if (extension == "xml" || checkSig) { /* If CanRead() is called in order to check whether we * support a specific file extension in general pIOHandler * might be NULL and it's our duty to return true here. */ - if (!pIOHandler)return true; + if ( nullptr == pIOHandler ) { + return true; + } const char* tokens[] = {"irr_scene"}; return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); } + return false; } diff --git a/test/unit/utD3MFImportExport.cpp b/test/unit/utD3MFImportExport.cpp index e8797d74d..c5fdd003b 100644 --- a/test/unit/utD3MFImportExport.cpp +++ b/test/unit/utD3MFImportExport.cpp @@ -90,7 +90,7 @@ TEST_F( utD3MFImporterExporter, roundtrip3MFtoMemTest ) { EXPECT_TRUE( exporterTest() ); Assimp::Importer importer; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "test.3mf", 0 ); + const aiScene *scene = importer.ReadFile( "test.3mf", 0 ); EXPECT_NE( nullptr, scene ); } From 5cf6509fb51c648a2c155ed82920a7ae2947ea2d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 14 Mar 2018 20:42:42 +0100 Subject: [PATCH 13/13] closes https://github.com/assimp/assimp/issues/1120: use euler angles for pre- and post-rotation. --- code/FBXConverter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 5d732c7b2..9bb023b4e 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -643,14 +643,14 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector if ( ok && PreRotation.SquareLength() > zero_epsilon ) { is_complex = true; - GetRotationMatrix( rot, PreRotation, chain[ TransformationComp_PreRotation ] ); + GetRotationMatrix( Model::RotOrder::RotOrder_EulerXYZ, PreRotation, chain[ TransformationComp_PreRotation ] ); } const aiVector3D& PostRotation = PropertyGet( props, "PostRotation", ok ); if ( ok && PostRotation.SquareLength() > zero_epsilon ) { is_complex = true; - GetRotationMatrix( rot, PostRotation, chain[ TransformationComp_PostRotation ] ); + GetRotationMatrix( Model::RotOrder::RotOrder_EulerXYZ, PostRotation, chain[ TransformationComp_PostRotation ] ); } const aiVector3D& RotationPivot = PropertyGet( props, "RotationPivot", ok );