Răsfoiți Sursa

3MF: fix working test for 3MF-export.

Kim Kulling 7 ani în urmă
părinte
comite
95e9cd75fa

+ 51 - 9
code/D3MFExporter.cpp

@@ -63,6 +63,11 @@ void ExportScene3MF( const char* pFile, IOSystem* pIOSystem, const aiScene* pSce
     }
     D3MF::D3MFExporter myExporter( pFile, pScene );
     if ( myExporter.validate() ) {
+        if ( pIOSystem->Exists( pFile ) ) {
+            if ( !pIOSystem->DeleteFile( pFile ) ) {
+                throw DeadlyExportError( "File exists, cannot override : " + std::string( pFile ) );
+            }
+        }
         bool ok = myExporter.exportArchive(pFile);
         if ( !ok ) {
             throw DeadlyExportError( "Could not export 3MP archive: " + std::string( pFile ) );
@@ -76,6 +81,9 @@ D3MFExporter::D3MFExporter( const char* pFile, const aiScene* pScene )
 : mArchiveName( pFile )
 , m_zipArchive( nullptr )
 , mScene( pScene )
+, mModelOutput()
+, mRelOutput()
+, mContentOutput()
 , mBuildItems()
 , mRelations() {
     // empty
@@ -107,6 +115,7 @@ bool D3MFExporter::exportArchive( const char *file ) {
     if ( nullptr == m_zipArchive ) {
         return false;
     }
+    ok |= exportContentTypes();
     ok |= export3DModel();
     ok |= exportRelations();
 
@@ -116,16 +125,36 @@ bool D3MFExporter::exportArchive( const char *file ) {
     return ok;
 }
 
+
+bool D3MFExporter::exportContentTypes() {
+    mContentOutput.clear();
+
+    mContentOutput << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+    mContentOutput << std::endl;
+    mContentOutput << "<Types xmlns = \"http://schemas.openxmlformats.org/package/2006/content-types\">";
+    mContentOutput << std::endl;
+    mContentOutput << "<Default Extension = \"rels\" ContentType = \"application/vnd.openxmlformats-package.relationships+xml\" />";
+    mContentOutput << std::endl;
+    mContentOutput << "<Default Extension = \"model\" ContentType = \"application/vnd.ms-package.3dmanufacturing-3dmodel+xml\" />";
+    mContentOutput << std::endl;
+    mContentOutput << "</Types>";
+    mContentOutput << std::endl;
+    exportContentTyp( XmlTag::CONTENT_TYPES_ARCHIVE );
+
+    return true;
+}
+
 bool D3MFExporter::exportRelations() {
     mRelOutput.clear();
 
-    mRelOutput << "<?xml version = \"1.0\" encoding = \"UTF-8\"?>\n";
-    mRelOutput << "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n";
+    mRelOutput << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+    mRelOutput << std::endl;
+    mRelOutput << "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">";
 
     for ( size_t i = 0; i < mRelations.size(); ++i ) {
-        mRelOutput << "<Relationship Target =\"/3D/" << mRelations[ i ]->target << "\" ";
-        mRelOutput << "id=\"" << mRelations[i]->id << "\" ";
-        mRelOutput << "Type=\"" << mRelations[ i ]->type << "/>";
+        mRelOutput << "<Relationship Target=\"/" << mRelations[ i ]->target << "\" ";
+        mRelOutput << "Id=\"" << mRelations[i]->id << "\" ";
+        mRelOutput << "Type=\"" << mRelations[ i ]->type << "\" />";
         mRelOutput << std::endl;
     }
     mRelOutput << "</Relationships>";
@@ -157,12 +186,12 @@ bool D3MFExporter::export3DModel() {
     mModelOutput << "</" << XmlTag::model << ">\n";
 
     OpcPackageRelationship *info = new OpcPackageRelationship;
-    info->id = mArchiveName;
-    info->target = "rel0";
-    info->type = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
+    info->id = "rel0";
+    info->target = "/3D/3DModel.model";
+    info->type = XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
     mRelations.push_back( info );
 
-    writeModelToArchive( "3D", "3DModel.model" );
+    writeModelToArchive( "/3D", "3DModel.model" );
     mModelOutput.flush();
 
     return true;
@@ -251,6 +280,19 @@ void D3MFExporter::writeBuild() {
     mModelOutput << std::endl;
 }
 
+void D3MFExporter::exportContentTyp( const std::string &filename ) {
+    if ( nullptr == m_zipArchive ) {
+        throw DeadlyExportError( "3MF-Export: Zip archive not valid, nullptr." );
+    }
+    const std::string entry = filename;
+    zip_entry_open( m_zipArchive, entry.c_str() );
+
+    const std::string &exportTxt( mContentOutput.str() );
+    zip_entry_write( m_zipArchive, exportTxt.c_str(), exportTxt.size() );
+
+    zip_entry_close( m_zipArchive );
+}
+
 void D3MFExporter::writeModelToArchive( const std::string &folder, const std::string &modelName ) {
     if ( nullptr == m_zipArchive ) {
         throw DeadlyExportError( "3MF-Export: Zip archive not valid, nullptr." );

+ 3 - 0
code/D3MFExporter.h

@@ -69,6 +69,7 @@ public:
     ~D3MFExporter();
     bool validate();
     bool exportArchive( const char *file );
+    bool exportContentTypes();
     bool exportRelations();
     bool export3DModel();
 
@@ -79,6 +80,7 @@ protected:
     void writeVertex( const aiVector3D &pos );
     void writeFaces( aiMesh *mesh );
     void writeBuild();
+    void exportContentTyp( const std::string &filename );
     void writeModelToArchive( const std::string &folder, const std::string &modelName );
     void writeRelInfoToFile( const std::string &folder, const std::string &relName );
 
@@ -88,6 +90,7 @@ private:
     const aiScene *mScene;
     std::ostringstream mModelOutput;
     std::ostringstream mRelOutput;
+    std::ostringstream mContentOutput;
     std::vector<unsigned int> mBuildItems;
     std::vector<OpcPackageRelationship*> mRelations;
 };

+ 0 - 1
code/D3MFImporter.cpp

@@ -100,7 +100,6 @@ public:
         scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren]();
 
         std::copy(children.begin(), children.end(), scene->mRootNode->mChildren);
-
     }
 
 private:

+ 4 - 4
code/D3MFOpcPackage.cpp

@@ -416,9 +416,9 @@ public:
     void ParseChildNode(XmlReader* xmlReader) {        
         OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
 
-        relPtr->id = xmlReader->getAttributeValue(XmlTag::RELS_ATTRIB_ID.c_str());
-        relPtr->type = xmlReader->getAttributeValue(XmlTag::RELS_ATTRIB_TYPE.c_str());
-        relPtr->target = xmlReader->getAttributeValue(XmlTag::RELS_ATTRIB_TARGET.c_str());
+        relPtr->id = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_ID.c_str());
+        relPtr->type = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TYPE.c_str());
+        relPtr->target = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TARGET.c_str());
 
         m_relationShips.push_back(relPtr);
     }
@@ -494,7 +494,7 @@ std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) {
     });
 
     if(itr == reader.m_relationShips.end())
-        throw DeadlyImportError("Cannot find" + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE);
+        throw DeadlyImportError("Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE);
 
     return (*itr)->target;
 }

+ 12 - 0
include/assimp/IOSystem.hpp

@@ -224,6 +224,8 @@ public:
      */
     virtual bool ChangeDirectory( const std::string &path );
 
+    virtual bool DeleteFile( const std::string &file );
+
 private:
     std::vector<std::string> m_pathStack;
 };
@@ -342,6 +344,16 @@ bool IOSystem::ChangeDirectory( const std::string &path ) {
 #endif // _WIN32
 }
 
+
+// ----------------------------------------------------------------------------
+AI_FORCE_INLINE
+bool IOSystem::DeleteFile( const std::string &file ) {
+    if ( file.empty() ) {
+        return false;
+    }
+    const int retCode( ::remove( file.c_str() ) );
+    return ( 0 == retCode );
+}
 } //!ns Assimp
 
 #endif //AI_IOSYSTEM_H_INC

+ 3 - 0
test/unit/utIOSystem.cpp

@@ -73,3 +73,6 @@ TEST_F( IOSystemTest, accessDirectoryStackTest ) {
     EXPECT_EQ( 0U, pImp->StackSize() );
 }
 
+TEST_F( IOSystemTest, delFileTest ) {
+    EXPECT_FALSE( pImp->DeleteFile( "none" ) );
+}