Explorar el Código

3mf: use correct material assignment in case of multi-materials.

Kim Kulling hace 7 años
padre
commit
69742670dd
Se han modificado 7 ficheros con 110 adiciones y 61 borrados
  1. 1 0
      code/3MFXmlTags.h
  2. 8 8
      code/BaseImporter.cpp
  3. 6 1
      code/D3MFExporter.cpp
  4. 1 0
      code/D3MFExporter.h
  5. 59 19
      code/D3MFImporter.cpp
  6. 30 29
      code/D3MFOpcPackage.cpp
  7. 5 4
      code/D3MFOpcPackage.h

+ 1 - 0
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";

+ 8 - 8
code/BaseImporter.cpp

@@ -115,13 +115,12 @@ void BaseImporter::SetupProperties(const Importer* /*pImp*/)
 }
 
 // ------------------------------------------------------------------------------------------------
-void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
-{
+void BaseImporter::GetExtensionList(std::set<std::string>& 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<std::string>& 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<IOStream> pStream (pIOHandler->Open(pFile));
     if (pStream.get() ) {
@@ -179,9 +179,9 @@ void BaseImporter::GetExtensionList(std::set<std::string>& 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 ) {

+ 6 - 1
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;

+ 1 - 0
code/D3MFExporter.h

@@ -76,6 +76,7 @@ public:
 
 protected:
     void writeHeader();
+    void writeBaseMaterials();
     void writeObjects();
     void writeMesh( aiMesh *mesh );
     void writeVertex( const aiVector3D &pos );

+ 59 - 19
code/D3MFImporter.cpp

@@ -70,9 +70,14 @@ namespace D3MF {
 
 class XmlSerializer {
 public:
+    using MatArray = std::vector<aiMaterial*>;
+    using MatId2MatArray = std::map<unsigned int, std::vector<unsigned int>>;
+
     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<unsigned int>(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<aiVector3D> 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<unsigned int> 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<aiColor4D>( &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<aiColor4D>( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE );
-            }
+            assignDiffuseColor( mat );
         }
 
         return mat;
@@ -339,7 +375,9 @@ private:
 
 private:
     std::vector<aiMesh*> mMeshes;
-    std::vector<aiMaterial*> 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;

+ 30 - 29
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 != NULL) {
-        std::string rFile(pFile);
-        std::map<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(rFile);
+    if ( pFile == nullptr ) {
+        return false;
+    }
 
-        if(it != m_ArchiveMap.end()) {
-            exist = true;
-        }
+    std::string rFile(pFile);
+    std::map<std::string, ZipFile*>::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<OpcPackageRelationshipPtr> 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<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(stream));
     std::unique_ptr<XmlReader> 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

+ 5 - 4
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<XmlReader> XmlReaderPtr;
+using XmlReader = irr::io::IrrXMLReader ;
+using XmlReaderPtr = std::shared_ptr<XmlReader> ;
 
 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<D3MFZipArchive> mZipArchive;
 };
 
-}
-}
+} // Namespace D3MF
+} // Namespace Assimp
 
 #endif // D3MFOPCPACKAGE_H