diff --git a/code/ObjFileData.h b/code/ObjFileData.h index d5052a50a..701952070 100644 --- a/code/ObjFileData.h +++ b/code/ObjFileData.h @@ -50,7 +50,7 @@ namespace Assimp namespace ObjFile { - +// ------------------------------------------------------------------------------------------------ struct Object; struct Face; struct Material; @@ -134,16 +134,39 @@ struct Object //! \brief Data structure to store all material specific data struct Material { + //! NAme of material description aiString MaterialName; + //! Name of used texture aiString texture; + //! Ambient color aiColor3D ambient; + //! Diffuse color aiColor3D diffuse; + //! Speculao color aiColor3D specular; + //! Alpha value float alpha; + //! Shineness factor float shineness; + //! Illumination model int illumination_model; }; +// ------------------------------------------------------------------------------------------------ +//! \struct Mesh +//! \brief Data structure to store a mesh +struct Mesh +{ + std::vector m_Faces; + Material *m_pMaterial; + + Mesh() : + m_pMaterial(NULL) + { + // empty + } +}; + // ------------------------------------------------------------------------------------------------ //! \struct Model //! \brief Data structure to store all obj-specific model datas @@ -179,29 +202,44 @@ struct Model std::string m_strActiveGroup; //! Vector with generated texture coordinates std::vector m_TextureCoord; + //! Current mesh instance + Mesh *m_pCurrentMesh; + //! Vector with stored meshes + std::vector m_Meshes; //! Material map std::map m_MaterialMap; + //! \brief Default constructor Model() : m_ModelName(""), m_pCurrent(NULL), m_pCurrentMaterial(NULL), m_pDefaultMaterial(NULL), - m_strActiveGroup("") + m_strActiveGroup(""), + m_pCurrentMesh(NULL) { // empty } - //! \brief DEstructor + //! \brief Destructor ~Model() { + // Clear all stored object instances for (std::vector::iterator it = m_Objects.begin(); - it != m_Objects.end(); ++it) + it != m_Objects.end(); ++it) { delete *it; } m_Objects.clear(); + + // Clear all stored mesh instances + for (std::vector::iterator it = m_Meshes.begin(); + it != m_Meshes.end(); ++it) + { + delete *it; + } + m_Meshes.clear(); } }; diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index 014603322..d7d2b0389 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -159,9 +159,13 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile if (pParent != NULL) this->appendChildToParentNode(pParent, pNode); + for (int meshIndex = 0; meshIndex < pModel->m_Meshes.size(); meshIndex++) + { + + } aiMesh *pMesh = new aiMesh(); - MeshArray.push_back(pMesh); - createTopology(pModel, pData, pMesh); + MeshArray.push_back( pMesh ); + createTopology( pModel, pData, pMesh ); // Create all nodes from the subobjects stored in the current object if (!pData->m_SubObjects.empty()) @@ -175,13 +179,12 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile for (size_t index = 0; index < pData->m_SubObjects.size(); index++) { // Create all child nodes - pNode->mChildren[index] = createNodes(pModel, pData, pNode, pScene, MeshArray); + pNode->mChildren[ index ] = createNodes( pModel, pData, pNode, pScene, MeshArray ); - // Create meshes of this object pMesh = new aiMesh(); - MeshArray.push_back(pMesh); - createTopology(pModel, pData->m_SubObjects[ index ], pMesh); - + MeshArray.push_back( pMesh ); + createTopology( pModel, pData, pMesh ); + // Create material of this object createMaterial(pModel, pData->m_SubObjects[ index ], pScene); } @@ -208,7 +211,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile // ------------------------------------------------------------------------------------------------ // Create topology data void ObjFileImporter::createTopology(const ObjFile::Model* pModel, const ObjFile::Object* pData, - aiMesh* pMesh) + aiMesh* pMesh ) { if (NULL == pData) return; @@ -218,14 +221,15 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel, const ObjFile // Create faces pMesh->mNumFaces = (unsigned int)pData->m_Faces.size(); - pMesh->mFaces = new aiFace[pMesh->mNumFaces]; + pMesh->mFaces = new aiFace[ pMesh->mNumFaces ]; + //pMesh->mMaterialIndex = pMode; for (size_t index = 0; index < pMesh->mNumFaces; index++) { aiFace *pFace = &pMesh->mFaces[ index ]; pFace->mNumIndices = (unsigned int)pData->m_Faces[index]->m_pVertices->size(); if (pFace->mNumIndices > 0) { - pFace->mIndices = new unsigned int[pMesh->mFaces[index].mNumIndices]; + pFace->mIndices = new unsigned int[ pMesh->mFaces[ index ].mNumIndices ]; ObjFile::Face::IndexArray *pArray = pData->m_Faces[index]->m_pVertices; // TODO: Should be implement much better @@ -254,18 +258,19 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, if (pCurrentObject->m_Faces.empty()) return; - // Copy all stored vertices, normals and so on + // Copy vertices of this mesh instance pMesh->mNumVertices = (unsigned int)pModel->m_Vertices.size(); - pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; - for (size_t index=0; index < pModel->m_Vertices.size(); index++) + pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ]; + for ( size_t index=0; index < pModel->m_Vertices.size(); index++ ) { pMesh->mVertices[ index ] = *pModel->m_Vertices[ index ]; } - if (!pModel->m_Normals.empty()) + // Copy normals for this mesh + if ( !pModel->m_Normals.empty() ) { pMesh->mNormals = new aiVector3D[pModel->m_Normals.size()]; - for (size_t index = 0; index < pModel->m_Normals.size(); index++) + for ( size_t index = 0; index < pModel->m_Normals.size(); index++ ) { pMesh->mNormals[ index ] = *pModel->m_Normals[ index ]; } @@ -273,7 +278,19 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, if (!pModel->m_TextureCoord.empty()) { - // TODO: Implement texture coodinates + pMesh->mTextureCoords[ 0 ] = new aiVector3D[ pModel->m_TextureCoord.size() ]; + + for( unsigned int e = 0; e < AI_MAX_NUMBER_OF_TEXTURECOORDS; e++) + { + if( pMesh->HasTextureCoords( e )) + { + for (unsigned int index = 0; index < pModel->m_TextureCoord.size(); index++ ) + { + aiVector2D *tex = pModel->m_TextureCoord[ index ]; + pMesh->mTextureCoords[ e ][ index ] = aiVector3D( tex->x, tex->y, 0.0f); + } + } + } } } @@ -304,13 +321,37 @@ void ObjFileImporter::createMaterial(const ObjFile::Model* pModel, const ObjFile if (NULL == pData) return; - // Create only a dumy material to enshure a running viewer - pScene->mNumMaterials = 1; - Assimp::MaterialHelper* mat = new Assimp::MaterialHelper; + const unsigned int numMaterials = (unsigned int) pModel->m_MaterialLib.size(); + pScene->mNumMaterials = 0; + if ( pModel->m_MaterialLib.empty() ) + return; - // Create a new material - pScene->mMaterials = new aiMaterial*[1]; - pScene->mMaterials[0] = mat; + pScene->mMaterials = new aiMaterial*[ numMaterials ]; + for ( unsigned int matIndex = 0; matIndex < numMaterials; matIndex++ ) + { + Assimp::MaterialHelper* mat = new Assimp::MaterialHelper(); + + // Store material name + std::map::const_iterator it = pModel->m_MaterialMap.find( pModel->m_MaterialLib[ matIndex ] ); + if ( pModel->m_MaterialMap.end() == it) + continue; + ObjFile::Material *pCurrentMaterial = (*it).second; + mat->AddProperty( &pCurrentMaterial->MaterialName, AI_MATKEY_NAME ); + + // Adding material colors + mat->AddProperty( &pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT); + mat->AddProperty( &pCurrentMaterial->diffuse, 1, AI_MATKEY_COLOR_DIFFUSE); + mat->AddProperty( &pCurrentMaterial->specular, 1, AI_MATKEY_COLOR_SPECULAR); + mat->AddProperty( &pCurrentMaterial->shineness, 1, AI_MATKEY_SHININESS); + + // Adding textures + if ( 0 != pCurrentMaterial->texture.length ) + mat->AddProperty( &pCurrentMaterial->texture, AI_MATKEY_TEXTURE_DIFFUSE(0)); + + // Store material property info in material array in scene + pScene->mMaterials[ pScene->mNumMaterials ] = mat; + pScene->mNumMaterials++; + } } // ------------------------------------------------------------------------------------------------ @@ -346,7 +387,6 @@ void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild) pParent->mChildren[ index ] = temp [ index ]; } pParent->mChildren[ pParent->mNumChildren-1 ] = pChild; - } // ------------------------------------------------------------------------------------------------ diff --git a/code/ObjFileImporter.h b/code/ObjFileImporter.h index 19401a579..99f97375f 100644 --- a/code/ObjFileImporter.h +++ b/code/ObjFileImporter.h @@ -58,7 +58,7 @@ struct Model; } /// \class ObjFileImporter -/// \brief IMports a waveform obj file +/// \brief Imports a waveform obj file class ObjFileImporter : BaseImporter { @@ -81,46 +81,51 @@ public: private: - //! brief - void GetExtensionList(std::string& append) - { - append.append("*.obj"); - } + //! \brief Appends the supported extention. + void GetExtensionList(std::string& append); - //! \brief + //! \brief File import implementation. void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); - //! \brief + //! \brief Create the data from imported content. void CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene); - //! \brief + //! \brief Creates all nodes stored in imported content. aiNode *createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pData, aiNode *pParent, aiScene* pScene, std::vector &MeshArray); - //! \brief + //! \brief Creates topology data like faces and meshes for the geometry. void createTopology(const ObjFile::Model* pModel, const ObjFile::Object* pData, aiMesh* pMesh); - //! \brief + //! \brief Creates vertices from model. void createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject, aiMesh* pMesh); - //! \brief + //! \brief Object counter helper method. void countObjects(const std::vector &rObjects, int &iNumMeshes); - //! \brief + //! \brief Material creation. void createMaterial(const ObjFile::Model* pModel, const ObjFile::Object* pData, aiScene* pScene); - //! \brief + //! \brief Appends a child node to a parentnode and updates the datastructures. void appendChildToParentNode(aiNode *pParent, aiNode *pChild); private: + //! Data buffer std::vector m_Buffer; + //! Pointer to root object instance ObjFile::Object *m_pRootObject; + //! Absolute pathname of model in filesystem std::string m_strAbsPath; }; +inline void ObjFileImporter::GetExtensionList(std::string& append) +{ + append.append("*.obj"); +} + } // Namespace Assimp #endif diff --git a/code/ObjFileMtlImporter.cpp b/code/ObjFileMtlImporter.cpp index 27cfecce0..7b8b28a5d 100644 --- a/code/ObjFileMtlImporter.cpp +++ b/code/ObjFileMtlImporter.cpp @@ -16,14 +16,13 @@ ObjFileMtlImporter::ObjFileMtlImporter( std::vector &buffer, m_DataIt( buffer.begin() ), m_DataItEnd( buffer.end() ), m_uiLine( 0 ), - m_pModel( NULL ) + m_pModel( pModel ) { ai_assert ( NULL != m_pModel ); if ( NULL == m_pModel->m_pDefaultMaterial ) { m_pModel->m_pDefaultMaterial = new ObjFile::Material(); - - //m_pModel->m_pDefaultMaterial-> + m_pModel->m_pDefaultMaterial->MaterialName.Set( "default" ); } load(); } @@ -155,29 +154,26 @@ void ObjFileMtlImporter::getFloatValue( float &value ) // ------------------------------------------------------------------- void ObjFileMtlImporter::createMaterial() -{ - m_pModel->m_pCurrentMaterial = new ObjFile::Material(); - - /*m_DataIt = getNextToken( m_DataIt, m_DataItEnd ); - if (m_DataIt == m_DataItEnd) - return; - - char *pStart = &(*m_DataIt); - while ( !isSpace(*m_DataIt) && m_DataIt != m_DataItEnd ) - ++m_DataIt; - - // Get name - std::string strName(pStart, &(*m_DataIt)); - if ( strName.empty() ) - return;*/ +{ std::string strName; m_DataIt = getName( m_DataIt, m_DataItEnd, strName ); if ( m_DataItEnd == m_DataIt ) return; - m_pModel->m_pCurrentMaterial->MaterialName.Set( strName ); - m_pModel->m_MaterialLib.push_back( strName ); - m_pModel->m_MaterialMap[ strName ] = m_pModel->m_pCurrentMaterial; + std::map::iterator it = m_pModel->m_MaterialMap.find( strName ); + if ( m_pModel->m_MaterialMap.end() == it) + { + // New Material created + m_pModel->m_pCurrentMaterial = new ObjFile::Material(); + m_pModel->m_pCurrentMaterial->MaterialName.Set( strName ); + m_pModel->m_MaterialLib.push_back( strName ); + m_pModel->m_MaterialMap[ strName ] = m_pModel->m_pCurrentMaterial; + } + else + { + // Use older material + m_pModel->m_pCurrentMaterial = (*it).second; + } } // ------------------------------------------------------------------- diff --git a/code/ObjFileMtlImporter.h b/code/ObjFileMtlImporter.h index 29d4aaf3d..2e37f0ec0 100644 --- a/code/ObjFileMtlImporter.h +++ b/code/ObjFileMtlImporter.h @@ -82,7 +82,10 @@ private: //! \brief Assignment operator, returns only a reference of this instance. ObjFileMtlImporter &operator = (const ObjFileMtlImporter &rOther); + //! \brief Load the whole material description void load(); + + //! void getColorRGBA( aiColor3D *pColor); void getIlluminationModel( int &illum_model ); void getFloatValue( float &value ); @@ -90,11 +93,17 @@ private: void getTexture(); private: + //! Absolute pathname std::string m_strAbsPath; + //! Data iterator showing to the current position in data buffer DataArrayIt m_DataIt; + //! Data iterator to end of buffer DataArrayIt m_DataItEnd; + //! USed model instance ObjFile::Model *m_pModel; + //! Current line in file unsigned int m_uiLine; + //! Helper buffer char m_buffer[BUFFERSIZE]; }; diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index 88e7d9135..b583e04df 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -1,4 +1,5 @@ #include "ObjFileParser.h" +#include "ObjFileMtlImporter.h" #include "ObjTools.h" #include "ObjFileData.h" #include "DefaultIOSystem.h" @@ -15,7 +16,9 @@ namespace Assimp { // ------------------------------------------------------------------- -ObjFileParser::ObjFileParser(std::vector &Data, const std::string &strAbsPath, const std::string &strModelName) : +ObjFileParser::ObjFileParser(std::vector &Data, + const std::string &strAbsPath, + const std::string &strModelName) : m_strAbsPath(strAbsPath), m_DataIt(Data.begin()), m_DataItEnd(Data.end()), @@ -284,6 +287,9 @@ void ObjFileParser::getFace() // Store the new instance m_pModel->m_pCurrent->m_Faces.push_back(face); + // Assign face to mesh + m_pModel->m_pCurrentMesh->m_Faces.push_back( face ); + // Skip the rest of the line m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } @@ -298,23 +304,33 @@ void ObjFileParser::getMaterialDesc() return; char *pStart = &(*m_DataIt); - while (!isSpace(*m_DataIt) && m_DataIt != m_DataItEnd) - m_DataIt++; + while ( !isSpace(*m_DataIt) && m_DataIt != m_DataItEnd ) + ++m_DataIt; // Get name std::string strName(pStart, &(*m_DataIt)); - if (strName.empty()) + if ( strName.empty() ) return; // Search for material - std::string strFile; std::map::iterator it = m_pModel->m_MaterialMap.find( strName ); - if (it == m_pModel->m_MaterialMap.end()) + if ( it == m_pModel->m_MaterialMap.end() ) { - m_pModel->m_pCurrentMaterial = new ObjFile::Material(); - m_pModel->m_MaterialMap[ strName ] = m_pModel->m_pCurrentMaterial; + // Not found, use default material + m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial; + m_pModel->m_MaterialMap[ strName ] = m_pModel->m_pCurrentMaterial; + } + else + { + // Found, using detected material + m_pModel->m_pCurrentMaterial = (*it).second; + + // Create a new mesh for a new material + m_pModel->m_pCurrentMesh = new ObjFile::Mesh(); + m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh ); } + // Skip rest of line m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } @@ -337,7 +353,7 @@ void ObjFileParser::getComment() } // ------------------------------------------------------------------- -// +// Get material library from file. void ObjFileParser::getMaterialLib() { // Translate tuple @@ -353,16 +369,18 @@ void ObjFileParser::getMaterialLib() DefaultIOSystem IOSystem; std::string strMatName(pStart, &(*m_DataIt)); std::string absName = m_strAbsPath + IOSystem.getOsSeparator() + strMatName; - if (!IOSystem.Exists(absName)) + if ( !IOSystem.Exists(absName) ) { m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); return; } + // Extract the extention std::string strExt(""); extractExtension(strMatName, strExt); std::string mat = "mtl"; + // Load the material library DefaultIOSystem FileSystem; IOStream *pFile = FileSystem.Open(absName); if (0L != pFile) @@ -371,21 +389,20 @@ void ObjFileParser::getMaterialLib() std::vector buffer; buffer.resize( size ); - size_t read_size = pFile->Read( &buffer[ 0 ], sizeof(char), size ); + size_t read_size = pFile->Read( &buffer[ 0 ], sizeof( char ), size ); FileSystem.Close( pFile ); - // TODO: Load mtl file - + // Importing the material library + ObjFileMtlImporter mtlImporter( buffer, absName, m_pModel ); + m_pModel->m_MaterialLib.push_back( strMatName ); } - - // Load material library (all materials will be created) - m_pModel->m_MaterialLib.push_back(strMatName); + // Skip rest of line m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } // ------------------------------------------------------------------- -// +// Set a new material definition as the current material. void ObjFileParser::getNewMaterial() { m_DataIt = getNextToken(m_DataIt, m_DataItEnd); @@ -414,7 +431,7 @@ void ObjFileParser::getNewMaterial() } // ------------------------------------------------------------------- -// +// Getter for a group name. void ObjFileParser::getGroupName() { // Get next word from data buffer diff --git a/code/ObjFileParser.h b/code/ObjFileParser.h index 9ca3f5756..6e79dde03 100644 --- a/code/ObjFileParser.h +++ b/code/ObjFileParser.h @@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include "../include/aiTypes.h" /*struct aiVector2D_t; @@ -62,6 +63,8 @@ struct Point2; } class ObjFileImporter; +/// \class ObjFileParser +/// \brief Parser for a obj waveform file class ObjFileParser { public: @@ -94,13 +97,18 @@ private: void extractExtension(const std::string strFile, std::string &strExt); private: + //! Absolute filepath to model std::string m_strAbsPath; + //! Iterator to current position in buffer DataArrayIt m_DataIt; + //! Iterator to end position of buffer DataArrayIt m_DataItEnd; + //! Pointer to model instance ObjFile::Model *m_pModel; + //! Current line (for debugging) unsigned int m_uiLine; + //! Helper buffer char m_buffer[BUFFERSIZE]; - }; } // Namespace Assimp