Merge pull request #1793 from assimp/3mf_basematerial_support

3mf: introduce first prototype for basematerial support.
pull/1803/head^2
Kim Kulling 2018-02-23 21:13:04 +01:00 committed by GitHub
commit f11f35d157
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 177 additions and 97 deletions

View File

@ -45,6 +45,7 @@ namespace Assimp {
namespace D3MF {
namespace XmlTag {
// Model-data specific tags
static const std::string model = "model";
static const std::string model_unit = "unit";
static const std::string metadata = "metadata";
@ -62,6 +63,8 @@ namespace XmlTag {
static const std::string v2 = "v2";
static const std::string v3 = "v3";
static const std::string id = "id";
static const std::string pid = "pid";
static const std::string p1 = "p1";
static const std::string name = "name";
static const std::string type = "type";
static const std::string build = "build";
@ -69,6 +72,13 @@ 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";
// Meta info tags
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 +93,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

View File

@ -61,6 +61,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <unzip.h>
#include <assimp/irrXMLWrapper.h>
#include "3MFXmlTags.h"
#include <assimp/fast_atof.h>
#include <iomanip>
namespace Assimp {
namespace D3MF {
@ -68,7 +71,9 @@ namespace D3MF {
class XmlSerializer {
public:
XmlSerializer(XmlReader* xmlReader)
: xmlReader(xmlReader) {
: mMeshes()
, mMaterials()
, xmlReader(xmlReader){
// empty
}
@ -77,14 +82,21 @@ public:
}
void ImportXml(aiScene* scene) {
if ( nullptr == scene ) {
return;
}
scene->mRootNode = new aiNode();
std::vector<aiNode*> children;
while(ReadToEndElement(D3MF::XmlTag::model)) {
if(xmlReader->getNodeName() == D3MF::XmlTag::object) {
const std::string nodeName( xmlReader->getNodeName() );
if( nodeName == D3MF::XmlTag::object) {
children.push_back(ReadObject(scene));
} else if(xmlReader->getNodeName() == D3MF::XmlTag::build) {
} else if( nodeName == D3MF::XmlTag::build) {
//
} else if ( nodeName == D3MF::XmlTag::basematerials ) {
ReadBaseMaterials();
}
}
@ -92,11 +104,16 @@ public:
scene->mRootNode->mName.Set( "3MF" );
}
scene->mNumMeshes = static_cast<unsigned int>(meshes.size());
scene->mNumMeshes = static_cast<unsigned int>( 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->mNumMaterials = mMaterials.size();
if ( 0 != scene->mNumMaterials ) {
scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ];
std::copy( mMaterials.begin(), mMaterials.end(), scene->mMaterials );
}
scene->mRootNode->mNumChildren = static_cast<unsigned int>(children.size());
scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren]();
@ -104,8 +121,7 @@ public:
}
private:
aiNode* ReadObject(aiScene* scene)
{
aiNode* ReadObject(aiScene* scene) {
std::unique_ptr<aiNode> node(new aiNode());
std::vector<unsigned long> meshIds;
@ -124,19 +140,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<unsigned long>(meshIdx));
meshIdx++;
++meshIdx;
}
}
@ -147,19 +160,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,14 +175,11 @@ private:
return mesh;
}
void ImportVertices(aiMesh* mesh)
{
void ImportVertices(aiMesh* mesh) {
std::vector<aiVector3D> vertices;
while(ReadToEndElement(D3MF::XmlTag::vertices))
{
if(xmlReader->getNodeName() == D3MF::XmlTag::vertex)
{
while(ReadToEndElement(D3MF::XmlTag::vertices)) {
if(xmlReader->getNodeName() == D3MF::XmlTag::vertex) {
vertices.push_back(ReadVertex());
}
}
@ -182,11 +187,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,16 +199,18 @@ private:
return vertex;
}
void ImportTriangles(aiMesh* mesh)
{
void ImportTriangles(aiMesh* mesh) {
std::vector<aiFace> faces;
while(ReadToEndElement(D3MF::XmlTag::triangles))
{
if(xmlReader->getNodeName() == D3MF::XmlTag::triangle)
{
while(ReadToEndElement(D3MF::XmlTag::triangles)) {
const std::string nodeName( xmlReader->getNodeName() );
if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) {
faces.push_back(ReadTriangle());
const char *pidToken( xmlReader->getAttributeValue( D3MF::XmlTag::p1.c_str() ) );
if ( nullptr != pidToken ) {
int matIdx( std::atoi( pidToken ) );
mesh->mMaterialIndex = matIdx;
}
}
}
@ -216,8 +221,7 @@ private:
std::copy(faces.begin(), faces.end(), mesh->mFaces);
}
aiFace ReadTriangle()
{
aiFace ReadTriangle() {
aiFace face;
face.mNumIndices = 3;
@ -229,45 +233,113 @@ private:
return face;
}
private:
bool ReadToStartElement(const std::string& startTag)
{
while(xmlReader->read())
{
if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && xmlReader->getNodeName() == startTag)
{
return true;
void ReadBaseMaterials() {
while ( ReadToEndElement( D3MF::XmlTag::basematerials ) ) {
mMaterials.push_back( readMaterialDef() );
xmlReader->read();
}
}
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;
}
++buf;
char comp[ 3 ] = { 0,0,'\0' };
comp[ 0 ] = *buf;
++buf;
comp[ 1 ] = *buf;
++buf;
diffuse.r = static_cast<ai_real>( strtol( comp, NULL, 16 ) );
comp[ 0 ] = *buf;
++buf;
comp[ 1 ] = *buf;
++buf;
diffuse.g = static_cast< ai_real >( strtol( comp, NULL, 16 ) );
comp[ 0 ] = *buf;
++buf;
comp[ 1 ] = *buf;
++buf;
diffuse.b = static_cast< ai_real >( strtol( comp, NULL, 16 ) );
comp[ 0 ] = *buf;
++buf;
comp[ 1 ] = *buf;
++buf;
diffuse.a = static_cast< ai_real >( strtol( comp, NULL, 16 ) );
return true;
}
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() );
aiString matName;
matName.Set( name );
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 );
}
else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END &&
xmlReader->getNodeName() == startTag)
{
}
return mat;
}
private:
bool ReadToStartElement(const std::string& startTag) {
while(xmlReader->read()) {
const std::string &nodeName( xmlReader->getNodeName() );
if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && nodeName == startTag) {
return true;
} else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == startTag) {
return false;
}
}
//DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag");
return false;
}
bool ReadToEndElement(const std::string& closeTag)
{
while(xmlReader->read())
{
bool ReadToEndElement(const std::string& closeTag) {
while(xmlReader->read()) {
const std::string &nodeName( xmlReader->getNodeName() );
if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT) {
return true;
}
else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END
&& xmlReader->getNodeName() == closeTag)
{
} else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == closeTag) {
return false;
}
}
DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag");
return false;
}
private:
std::vector<aiMesh*> meshes;
std::vector<aiMesh*> mMeshes;
std::vector<aiMaterial*> mMaterials;
XmlReader* xmlReader;
};

View File

@ -66,49 +66,50 @@ static const unsigned int BufferSize = 4096;
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE char_t ToLower( char_t in)
{
AI_FORCE_INLINE
char_t ToLower( char_t in ) {
return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in+0x20) : in;
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE char_t ToUpper( char_t in) {
AI_FORCE_INLINE
char_t ToUpper( char_t in) {
return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in;
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsUpper( char_t in)
{
AI_FORCE_INLINE
bool IsUpper( char_t in) {
return (in >= (char_t)'A' && in <= (char_t)'Z');
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsLower( char_t in)
{
AI_FORCE_INLINE
bool IsLower( char_t in) {
return (in >= (char_t)'a' && in <= (char_t)'z');
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsSpace( char_t in)
{
AI_FORCE_INLINE
bool IsSpace( char_t in) {
return (in == (char_t)' ' || in == (char_t)'\t');
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsLineEnd( char_t in)
{
AI_FORCE_INLINE
bool IsLineEnd( char_t in) {
return (in==(char_t)'\r'||in==(char_t)'\n'||in==(char_t)'\0'||in==(char_t)'\f');
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsSpaceOrNewLine( char_t in)
{
AI_FORCE_INLINE
bool IsSpaceOrNewLine( char_t in) {
return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
}

View File

@ -14,8 +14,8 @@
// ------------------------------------------------------------------------------------
#ifndef __FAST_A_TO_F_H_INCLUDED__
#define __FAST_A_TO_F_H_INCLUDED__
#ifndef FAST_A_TO_F_H_INCLUDED
#define FAST_A_TO_F_H_INCLUDED
#include <cmath>
#include <limits>
@ -26,15 +26,13 @@
#include "StringComparison.h"
#include <assimp/DefaultLogger.hpp>
#ifdef _MSC_VER
# include <stdint.h>
#else
# include <assimp/Compiler/pstdint.h>
#endif
namespace Assimp
{
namespace Assimp {
const double fast_atof_table[16] = { // we write [16] here instead of [] to work around a swig bug
0.0,
@ -64,8 +62,9 @@ unsigned int strtoul10( const char* in, const char** out=0) {
unsigned int value = 0;
for ( ;; ) {
if ( *in < '0' || *in > '9' )
if ( *in < '0' || *in > '9' ) {
break;
}
value = ( value * 10 ) + ( *in - '0' );
++in;
@ -109,8 +108,7 @@ unsigned int strtoul16( const char* in, const char** out=0) {
value = ( value << 4u ) + ( *in - 'A' ) + 10;
} else if (*in >= 'a' && *in <= 'f') {
value = ( value << 4u ) + ( *in - 'a' ) + 10;
}
else {
} else {
break;
}
++in;
@ -205,7 +203,6 @@ uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_ino
DefaultLogger::get()->warn( std::string( "Converting the string \"" ) + in + "\" into a value resulted in overflow." );
return 0;
}
//throw std::overflow_error();
value = new_value;
@ -213,21 +210,23 @@ uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_ino
++cur;
if (max_inout && *max_inout == cur) {
if (out) { /* skip to end */
while (*in >= '0' && *in <= '9')
while ( *in >= '0' && *in <= '9' ) {
++in;
}
*out = in;
}
return value;
}
}
if (out)
if ( out ) {
*out = in;
}
if (max_inout)
if ( max_inout ) {
*max_inout = cur;
}
return value;
}
@ -238,7 +237,7 @@ uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_ino
inline
int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inout = 0) {
bool inv = (*in == '-');
if (inv || *in == '+') {
if ( inv || *in == '+' ) {
++in;
}
@ -249,7 +248,6 @@ int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inou
return value;
}
// Number of relevant decimals for floating-point parsing.
#define AI_FAST_ATOF_RELAVANT_DECIMALS 15
@ -258,7 +256,7 @@ int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inou
//! about 6 times faster than atof in win32.
// If you find any bugs, please send them to me, niko (at) irrlicht3d.org.
// ------------------------------------------------------------------------------------
template <typename Real>
template<typename Real>
inline
const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) {
Real f = 0;
@ -284,10 +282,10 @@ const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true)
c += 5;
}
return c;
}
}
if (!(c[0] >= '0' && c[0] <= '9') &&
!((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')) {
!((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')) {
throw std::invalid_argument("Cannot parse string "
"as real number: does not start with digit "
"or decimal point followed by digit.");
@ -322,7 +320,6 @@ const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true)
// A major 'E' must be allowed. Necessary for proper reading of some DXF files.
// Thanks to Zhao Lei to point out that this if() must be outside the if (*c == '.' ..)
if (*c == 'e' || *c == 'E') {
++c;
const bool einv = (*c=='-');
if (einv || *c=='+') {
@ -352,6 +349,7 @@ inline
ai_real fast_atof(const char* c) {
ai_real ret(0.0);
fast_atoreal_move<ai_real>(c, ret);
return ret;
}
@ -374,4 +372,4 @@ ai_real fast_atof( const char** inout) {
} //! namespace Assimp
#endif // __FAST_A_TO_F_H_INCLUDED__
#endif // FAST_A_TO_F_H_INCLUDED