diff --git a/code/ObjFileData.h b/code/ObjFileData.h index 676004646..b8248bbf1 100644 --- a/code/ObjFileData.h +++ b/code/ObjFileData.h @@ -107,14 +107,20 @@ struct Face //! \brief Stores all objects of an objfile object definition struct Object { + enum ObjectType + { + ObjType, + GroupType + }; + //! Object name std::string m_strObjName; - //! Assigend face instances - std::vector m_Faces; //! Transformation matrix, stored in OpenGL format aiMatrix4x4 m_Transformation; //! All sub-objects referenced by this object std::vector m_SubObjects; + /// Assigned meshes + std::vector m_Meshes; //! \brief Default constructor Object() : @@ -189,6 +195,8 @@ struct Material //! \brief Data structure to store a mesh struct Mesh { + static const unsigned int NoMaterial = 999999999; + /// Array with pointer to all stored faces std::vector m_Faces; /// Assigned material @@ -205,7 +213,7 @@ struct Mesh Mesh() : m_pMaterial(NULL), m_uiNumIndices(0), - m_uiMaterialIndex(0), + m_uiMaterialIndex( NoMaterial ), m_hasNormals(false) { memset(m_uiUVCoordinates, 0, sizeof( unsigned int ) * AI_MAX_NUMBER_OF_TEXTURECOORDS); @@ -305,7 +313,6 @@ struct Model } m_Groups.clear(); - } }; diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index d42c899d5..8952438bf 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER #include "DefaultIOSystem.h" - #include "ObjFileImporter.h" #include "ObjFileParser.h" #include "ObjFileData.h" @@ -140,8 +139,8 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene return; // Create the root node of the scene - pScene->mRootNode = new aiNode(); - if (!pModel->m_ModelName.empty()) + pScene->mRootNode = new aiNode; + if ( !pModel->m_ModelName.empty() ) { // Set the name of the scene pScene->mRootNode->mName.Set(pModel->m_ModelName); @@ -175,40 +174,46 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene // ------------------------------------------------------------------------------------------------ // Creates all nodes of the model -aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pData, +aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pObject, unsigned int uiMeshIndex, aiNode *pParent, aiScene* pScene, - std::vector &MeshArray) + std::vector &MeshArray ) { ai_assert( NULL != pModel ); - if (NULL == pData) + if ( NULL == pObject ) return NULL; // Store older mesh size to be able to computate mesh offsets for new mesh instances const size_t oldMeshSize = MeshArray.size(); - aiNode *pNode = new aiNode(); + aiNode *pNode = new aiNode; if (pParent != NULL) - this->appendChildToParentNode(pParent, pNode); + appendChildToParentNode(pParent, pNode); - aiMesh *pMesh = new aiMesh; - createTopology( pModel, pData, uiMeshIndex, pMesh ); - if ( pMesh->mNumVertices > 0 ) + + for ( unsigned int i=0; i< pObject->m_Meshes.size(); i++ ) { - MeshArray.push_back( pMesh ); - } - else - { - delete pMesh; + unsigned int meshId = pObject->m_Meshes[ i ]; + aiMesh *pMesh = new aiMesh; + createTopology( pModel, pObject, meshId, pMesh ); + if ( pMesh->mNumVertices > 0 ) + { + MeshArray.push_back( pMesh ); + } + else + { + delete pMesh; + } } - // Create all nodes from the subobjects stored in the current object - if ( !pData->m_SubObjects.empty() ) + // Create all nodes from the sub-objects stored in the current object + if ( !pObject->m_SubObjects.empty() ) { - pNode->mNumChildren = (unsigned int)pData->m_SubObjects.size(); - pNode->mChildren = new aiNode*[pData->m_SubObjects.size()]; + size_t numChilds = pObject->m_SubObjects.size(); + pNode->mNumChildren = static_cast( numChilds ); + pNode->mChildren = new aiNode*[ numChilds ]; pNode->mNumMeshes = 1; - pNode->mMeshes = new unsigned int[1]; + pNode->mMeshes = new unsigned int[ 1 ]; } // Set mesh instances into scene- and node-instances @@ -216,7 +221,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile if ( meshSizeDiff > 0 ) { pNode->mMeshes = new unsigned int[ meshSizeDiff ]; - pNode->mNumMeshes = (unsigned int)meshSizeDiff; + pNode->mNumMeshes = static_cast( meshSizeDiff ); size_t index = 0; for (size_t i = oldMeshSize; i < MeshArray.size(); i++) { @@ -248,7 +253,10 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel, if ( pMesh->mNumFaces > 0 ) { pMesh->mFaces = new aiFace[ pMesh->mNumFaces ]; - pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex; + if ( pObjMesh->m_uiMaterialIndex != ObjFile::Mesh::NoMaterial ) + { + pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex; + } // Copy all data from all stored meshes for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) @@ -278,7 +286,7 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel, } // ------------------------------------------------------------------------------------------------ -// Creates a vretex array +// Creates a vertex array void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject, unsigned int uiMeshIndex, @@ -288,7 +296,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, ai_assert( NULL != pCurrentObject ); // Break, if no faces are stored in object - if (pCurrentObject->m_Faces.empty()) + if ( pCurrentObject->m_Meshes.empty() ) return; // Get current mesh @@ -366,10 +374,10 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, void ObjFileImporter::countObjects(const std::vector &rObjects, int &iNumMeshes) { iNumMeshes = 0; - if (rObjects.empty()) + if ( rObjects.empty() ) return; - iNumMeshes += (unsigned int)rObjects.size(); + iNumMeshes += static_cast( rObjects.size() ); for (std::vector::const_iterator it = rObjects.begin(); it != rObjects.end(); ++it) @@ -400,17 +408,18 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc Assimp::MaterialHelper* mat = new Assimp::MaterialHelper(); // Store material name - std::map::const_iterator it = pModel->m_MaterialMap.find( pModel->m_MaterialLib[ matIndex ] ); + std::map::const_iterator it; + it = pModel->m_MaterialMap.find( pModel->m_MaterialLib[ matIndex ] ); // No material found, use the default material - if ( pModel->m_MaterialMap.end() == it) + if ( pModel->m_MaterialMap.end() == it ) continue; ObjFile::Material *pCurrentMaterial = (*it).second; mat->AddProperty( &pCurrentMaterial->MaterialName, AI_MATKEY_NAME ); // convert illumination model - int sm; + int sm = 0; switch (pCurrentMaterial->illumination_model) { case 0: @@ -474,8 +483,8 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild) { // Checking preconditions - ai_assert (NULL != pParent); - ai_assert (NULL != pChild); + ai_assert( NULL != pParent ); + ai_assert( NULL != pChild ); // Assign parent to child pChild->mParent = pParent; @@ -486,7 +495,7 @@ void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild) if (pParent->mChildren != NULL) { sNumChildren = pParent->mNumChildren; - ai_assert (0 != sNumChildren); + ai_assert( 0 != sNumChildren ); for (size_t index = 0; index < pParent->mNumChildren; index++) { temp.push_back(pParent->mChildren [ index ] ); diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index b30e4fd1b..6609abe75 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -50,7 +50,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../include/aiTypes.h" #include "DefaultIOSystem.h" -namespace Assimp { +namespace Assimp +{ + // ------------------------------------------------------------------- const std::string ObjFileParser::DEFAULT_MATERIAL = AI_DEFAULT_MATERIAL_NAME; // fix: changed that to our standard default name @@ -78,6 +80,7 @@ ObjFileParser::ObjFileParser(std::vector &Data,const std::string &strModel } // ------------------------------------------------------------------- +// Destrcutor. ObjFileParser::~ObjFileParser() { delete m_pModel->m_pDefaultMaterial; @@ -88,12 +91,14 @@ ObjFileParser::~ObjFileParser() } // ------------------------------------------------------------------- +// Returns a pointer to the model instance. ObjFile::Model *ObjFileParser::GetModel() const { return m_pModel; } // ------------------------------------------------------------------- +// File parsing method. void ObjFileParser::parseFile() { if (m_DataIt == m_DataItEnd) @@ -201,7 +206,6 @@ void ObjFileParser::copyNextLine(char *pBuffer, size_t length) size_t index = 0; while (m_DataIt != m_DataItEnd) { - // (Aramis) removed assertion (index *pTexID = new std::vector; std::vector *pNormalID = new std::vector; bool hasNormal = false; - bool vt = (!m_pModel->m_TextureCoord.empty()); bool vn = (!m_pModel->m_Normals.empty()); @@ -329,7 +332,7 @@ void ObjFileParser::getFace() ++pPtr; } - ObjFile::Face *face = new ObjFile::Face(pIndices, pNormalID, pTexID); + ObjFile::Face *face = new ObjFile::Face( pIndices, pNormalID, pTexID ); // Set active material, if one set if (NULL != m_pModel->m_pCurrentMaterial) @@ -339,23 +342,20 @@ void ObjFileParser::getFace() // Create a default object, if nothing there if ( NULL == m_pModel->m_pCurrent ) - createObject("defaultobject"); - - // Store the new instance - m_pModel->m_pCurrent->m_Faces.push_back(face); + createObject( "defaultobject" ); // Assign face to mesh if ( NULL == m_pModel->m_pCurrentMesh ) { - m_pModel->m_pCurrentMesh = new ObjFile::Mesh(); - m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh ); + createMesh(); } // Store the face m_pModel->m_pCurrentMesh->m_Faces.push_back( face ); m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int)face->m_pVertices->size(); m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int)face->m_pTexturCoords[0].size(); - if(!m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal) { + if( !m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal ) + { m_pModel->m_pCurrentMesh->m_hasNormals = true; } // Skip the rest of the line @@ -391,6 +391,10 @@ void ObjFileParser::getMaterialDesc() { // Found, using detected material m_pModel->m_pCurrentMaterial = (*it).second; + if ( needsNewMesh( strName )) + { + createMesh(); + } m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strName ); } @@ -460,11 +464,11 @@ void ObjFileParser::getNewMaterial() return; char *pStart = &(*m_DataIt); - std::string strMat(pStart, *m_DataIt); + std::string strMat( pStart, *m_DataIt ); while ( isSeparator( *m_DataIt ) ) m_DataIt++; std::map::iterator it = m_pModel->m_MaterialMap.find( strMat ); - if (it == m_pModel->m_MaterialMap.end()) + if ( it == m_pModel->m_MaterialMap.end() ) { // Show a warning, if material was not found DefaultLogger::get()->warn("OBJ: Unsupported material requested: " + strMat); @@ -473,7 +477,10 @@ void ObjFileParser::getNewMaterial() else { // Set new material - m_pModel->m_pCurrentMaterial = (*it).second; + if ( needsNewMesh( strMat ) ) + { + createMesh(); + } m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strMat ); } @@ -514,13 +521,12 @@ void ObjFileParser::getGroupName() std::string strGroupName(pStart, &(*m_DataIt)); // Change active group, if necessary - if (m_pModel->m_strActiveGroup != strGroupName) + if ( m_pModel->m_strActiveGroup != strGroupName ) { // Search for already existing entry ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(&strGroupName); // We are mapping groups into the object structure - /// TODO: Is this the right way to do it???? createObject( strGroupName ); // New group name, creating a new entry @@ -557,8 +563,8 @@ void ObjFileParser::getObjectName() if (m_DataIt == m_DataItEnd) return; char *pStart = &(*m_DataIt); - while (!isSeparator(*m_DataIt)) - m_DataIt++; + while ( !isSeparator( *m_DataIt ) ) + ++m_DataIt; std::string strObjectName(pStart, &(*m_DataIt)); if (!strObjectName.empty()) @@ -588,15 +594,15 @@ void ObjFileParser::getObjectName() // Creates a new object instance void ObjFileParser::createObject(const std::string &strObjectName) { - ai_assert (NULL != m_pModel); - ai_assert (!strObjectName.empty()); + ai_assert( NULL != m_pModel ); + ai_assert( !strObjectName.empty() ); - m_pModel->m_pCurrent = new ObjFile::Object(); + m_pModel->m_pCurrent = new ObjFile::Object; m_pModel->m_pCurrent->m_strObjName = strObjectName; m_pModel->m_Objects.push_back( m_pModel->m_pCurrent ); - m_pModel->m_pCurrentMesh = new ObjFile::Mesh(); - m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh ); + + createMesh(); if( m_pModel->m_pCurrentMaterial ) { @@ -605,6 +611,39 @@ void ObjFileParser::createObject(const std::string &strObjectName) m_pModel->m_pCurrentMesh->m_pMaterial = m_pModel->m_pCurrentMaterial; } } +// ------------------------------------------------------------------- +// Creates a new mesh +void ObjFileParser::createMesh() +{ + ai_assert( NULL != m_pModel ); + m_pModel->m_pCurrentMesh = new ObjFile::Mesh; + m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh ); + unsigned int meshId = m_pModel->m_Meshes.size()-1; + if ( NULL != m_pModel->m_pCurrent ) + { + m_pModel->m_pCurrent->m_Meshes.push_back( meshId ); + } + else + { + DefaultLogger::get()->error("OBJ: No object detected to attach a new mesh instance."); + } +} + +// ------------------------------------------------------------------- +// Returns true, if a new mesh must be created. +bool ObjFileParser::needsNewMesh( const std::string &rMaterialName ) +{ + bool newMat = false; + int matIdx = getMaterialIndex( rMaterialName ); + int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex; + if ( curMatIdx != ObjFile::Mesh::NoMaterial || curMatIdx != matIdx ) + { + // New material -> only one material per mesh, so we need to create a new + // material + newMat = true; + } + return newMat; +} // ------------------------------------------------------------------- // Shows an error in parsing process. @@ -613,6 +652,7 @@ void ObjFileParser::reportErrorTokenInFace() m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); DefaultLogger::get()->error("OBJ: Not supported token in face description detected"); } + // ------------------------------------------------------------------- } // Namespace Assimp diff --git a/code/ObjFileParser.h b/code/ObjFileParser.h index 94a953e13..60ce9a475 100644 --- a/code/ObjFileParser.h +++ b/code/ObjFileParser.h @@ -108,6 +108,10 @@ private: void getObjectName(); /// Creates a new object. void createObject(const std::string &strObjectName); + /// Creates a new mesh. + void createMesh(); + /// Returns true, if a new mesh instance must be created. + bool needsNewMesh( const std::string &rMaterialName ); /// Error report in token void reportErrorTokenInFace();