From 331e67c32d7b1e685c704d552ed08f25bb03e7ba Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 12 Feb 2018 22:07:12 +0100 Subject: [PATCH] 3mf: introduce first prototype for basematerial support. --- code/3MFXmlTags.h | 7 ++- code/D3MFImporter.cpp | 137 ++++++++++++++++++++++++++++++------------ 2 files changed, 106 insertions(+), 38 deletions(-) diff --git a/code/3MFXmlTags.h b/code/3MFXmlTags.h index 30aed0e95..20971a38f 100644 --- a/code/3MFXmlTags.h +++ b/code/3MFXmlTags.h @@ -69,6 +69,12 @@ namespace XmlTag { static const std::string objectid = "objectid"; static const std::string transform = "transform"; + // Material definitions + static const std::string basematerials = "basematerials"; + static const std::string basematerials_base = "base"; + static const std::string basematerials_name = "name"; + static const std::string basematerials_displaycolor = "displaycolor"; + static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml"; static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels"; static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types"; @@ -83,7 +89,6 @@ namespace XmlTag { static const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture"; static const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; static const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; - } } // Namespace D3MF diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 0777a55fa..823fae74c 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -68,7 +68,9 @@ namespace D3MF { class XmlSerializer { public: XmlSerializer(XmlReader* xmlReader) - : xmlReader(xmlReader) { + : xmlReader(xmlReader) + , mMeshes() + , mMaterials() { // empty } @@ -77,6 +79,10 @@ public: } void ImportXml(aiScene* scene) { + if ( nullptr != scene ) { + return; + } + scene->mRootNode = new aiNode(); std::vector children; @@ -84,7 +90,9 @@ public: if(xmlReader->getNodeName() == D3MF::XmlTag::object) { children.push_back(ReadObject(scene)); } else if(xmlReader->getNodeName() == D3MF::XmlTag::build) { - + // + } else if ( xmlReader->getNodeName() == D3MF::XmlTag::basematerials ) { + ReadBaseMaterials(); } } @@ -92,10 +100,10 @@ public: scene->mRootNode->mName.Set( "3MF" ); } - scene->mNumMeshes = static_cast(meshes.size()); + scene->mNumMeshes = static_cast( mMeshes.size()); scene->mMeshes = new aiMesh*[scene->mNumMeshes](); - std::copy(meshes.begin(), meshes.end(), scene->mMeshes); + std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes); scene->mRootNode->mNumChildren = static_cast(children.size()); scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren](); @@ -104,8 +112,7 @@ public: } private: - aiNode* ReadObject(aiScene* scene) - { + aiNode* ReadObject(aiScene* scene) { std::unique_ptr node(new aiNode()); std::vector meshIds; @@ -124,19 +131,16 @@ private: node->mParent = scene->mRootNode; node->mName.Set(name); - size_t meshIdx = meshes.size(); + size_t meshIdx = mMeshes.size(); - while(ReadToEndElement(D3MF::XmlTag::object)) - { - if(xmlReader->getNodeName() == D3MF::XmlTag::mesh) - { + while(ReadToEndElement(D3MF::XmlTag::object)) { + if(xmlReader->getNodeName() == D3MF::XmlTag::mesh) { auto mesh = ReadMesh(); mesh->mName.Set(name); - meshes.push_back(mesh); + mMeshes.push_back(mesh); meshIds.push_back(static_cast(meshIdx)); - meshIdx++; - + ++meshIdx; } } @@ -147,19 +151,14 @@ private: std::copy(meshIds.begin(), meshIds.end(), node->mMeshes); return node.release(); - } aiMesh* ReadMesh() { aiMesh* mesh = new aiMesh(); - while(ReadToEndElement(D3MF::XmlTag::mesh)) - { - if(xmlReader->getNodeName() == D3MF::XmlTag::vertices) - { + while(ReadToEndElement(D3MF::XmlTag::mesh)) { + if(xmlReader->getNodeName() == D3MF::XmlTag::vertices) { ImportVertices(mesh); - } - else if(xmlReader->getNodeName() == D3MF::XmlTag::triangles) - { + } else if(xmlReader->getNodeName() == D3MF::XmlTag::triangles) { ImportTriangles(mesh); } } @@ -167,8 +166,7 @@ private: return mesh; } - void ImportVertices(aiMesh* mesh) - { + void ImportVertices(aiMesh* mesh) { std::vector vertices; while(ReadToEndElement(D3MF::XmlTag::vertices)) @@ -182,11 +180,9 @@ private: mesh->mVertices = new aiVector3D[mesh->mNumVertices]; std::copy(vertices.begin(), vertices.end(), mesh->mVertices); - } - aiVector3D ReadVertex() - { + aiVector3D ReadVertex() { aiVector3D vertex; vertex.x = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::x.c_str()), nullptr); @@ -196,15 +192,11 @@ private: return vertex; } - void ImportTriangles(aiMesh* mesh) - { + void ImportTriangles(aiMesh* mesh) { std::vector faces; - - while(ReadToEndElement(D3MF::XmlTag::triangles)) - { - if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) - { + while(ReadToEndElement(D3MF::XmlTag::triangles)) { + if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) { faces.push_back(ReadTriangle()); } } @@ -216,8 +208,7 @@ private: std::copy(faces.begin(), faces.end(), mesh->mFaces); } - aiFace ReadTriangle() - { + aiFace ReadTriangle() { aiFace face; face.mNumIndices = 3; @@ -229,6 +220,77 @@ private: return face; } + void ReadBaseMaterials() { + while ( ReadToEndElement( D3MF::XmlTag::basematerials ) ) { + mMaterials.push_back( readMaterialDef() ); + } + } + + bool parseColor( const char *color, aiColor4D &diffuse ) { + if ( nullptr == color ) { + return false; + } + + const size_t len( strlen( color ) ); + if ( 9 != len ) { + return false; + } + + const char *buf( color ); + if ( '#' != *buf ) { + return false; + } + + char comp[ 2 ] = { 0,0 }; + comp[ 0 ] = *buf; + ++buf; + comp[ 1 ] = *buf; + ++buf; + diffuse.r = static_cast( std::atoi( comp ) ); + + comp[ 0 ] = *buf; + ++buf; + comp[ 1 ] = *buf; + ++buf; + diffuse.g = static_cast( std::atoi( comp ) ); + + comp[ 0 ] = *buf; + ++buf; + comp[ 1 ] = *buf; + ++buf; + diffuse.b = static_cast( std::atoi( comp ) ); + + comp[ 0 ] = *buf; + ++buf; + comp[ 1 ] = *buf; + ++buf; + diffuse.a = static_cast( std::atoi( comp ) ); + + return true; + } + + aiMaterial *readMaterialDef() { + while ( ReadToEndElement( D3MF::XmlTag::basematerials_base ) ) { + const char *name( nullptr ); + const char *color( nullptr ); + if ( xmlReader->getNodeName() == D3MF::XmlTag::basematerials_name ) { + name = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_name.c_str() ); + + aiString matName; + matName.Set( name ); + aiMaterial *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 ); + } + } + } + + } + private: bool ReadToStartElement(const std::string& startTag) { @@ -267,7 +329,8 @@ private: private: - std::vector meshes; + std::vector mMeshes; + std::vector mMaterials; XmlReader* xmlReader; };