From 0e125c2255a775a6a0ae55879850ac09f9fb6cbe Mon Sep 17 00:00:00 2001 From: kimmi Date: Wed, 2 Jul 2008 18:12:54 +0000 Subject: [PATCH] CHANGE: Prototype for correct material loading, now the meshes have correct references to the used material. BUGFIX: Parsing of normals and texture coordinates fixed. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@61 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- code/3DSGenNormals.cpp | 2 +- code/ObjFileData.h | 29 ++++-- code/ObjFileImporter.cpp | 174 +++++++++++++++++++++------------- code/ObjFileImporter.h | 9 +- code/ObjFileParser.cpp | 34 +++++-- code/ObjFileParser.h | 1 + tools/assimp_view/Display.cpp | 27 ++++-- 7 files changed, 185 insertions(+), 91 deletions(-) diff --git a/code/3DSGenNormals.cpp b/code/3DSGenNormals.cpp index 995d5315e..51550c951 100644 --- a/code/3DSGenNormals.cpp +++ b/code/3DSGenNormals.cpp @@ -133,4 +133,4 @@ void Dot3DSImporter::GenNormals(Dot3DS::Mesh* sMesh) } sMesh->mNormals = avNormals; return; -} \ No newline at end of file +} diff --git a/code/ObjFileData.h b/code/ObjFileData.h index 701952070..4f4200f22 100644 --- a/code/ObjFileData.h +++ b/code/ObjFileData.h @@ -80,11 +80,11 @@ struct Face Face(std::vector *pVertices, std::vector *pNormals, std::vector *pTexCoords) : - m_PrimitiveType(2), - m_pVertices(pVertices), - m_pNormals(pNormals), - m_pTexturCoords(pTexCoords), - m_pMaterial(0L) + m_PrimitiveType( 2 ), + m_pVertices( pVertices ), + m_pNormals( pNormals ), + m_pTexturCoords( pTexCoords ), + m_pMaterial( 0L ) { // empty } @@ -150,6 +150,14 @@ struct Material float shineness; //! Illumination model int illumination_model; + + Material() + { + } + + ~Material() + { + } }; // ------------------------------------------------------------------------------------------------ @@ -159,9 +167,18 @@ struct Mesh { std::vector m_Faces; Material *m_pMaterial; + unsigned int m_uiNumIndices; + unsigned int m_uiMaterialIndex; Mesh() : - m_pMaterial(NULL) + m_pMaterial(NULL), + m_uiNumIndices(0), + m_uiMaterialIndex(0) + { + // empty + } + + ~Mesh() { // empty } diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index d7d2b0389..8b2af5fd8 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -129,8 +129,8 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene // Create mesh pointer buffer for this scene if (pScene->mNumMeshes > 0) { - pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ]; - for (size_t index =0; index < pScene->mNumMeshes; index++) + pScene->mMeshes = new aiMesh*[ MeshArray.size() ]; + for (size_t index =0; index < MeshArray.size(); index++) { pScene->mMeshes [ index ] = MeshArray[ index ]; } @@ -139,7 +139,7 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene // Create all materials for (size_t index = 0; index < pModel->m_Objects.size(); index++) { - createMaterial(pModel, pModel->m_Objects[ index ], pScene); + createMaterial( pModel, pModel->m_Objects[ index ], pScene ); } } @@ -159,13 +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 = NULL; + for (unsigned int meshIndex = 0; meshIndex < pModel->m_Meshes.size(); meshIndex++) { - + pMesh = new aiMesh(); + MeshArray.push_back( pMesh ); + createTopology( pModel, pData, meshIndex, pMesh ); } - aiMesh *pMesh = new aiMesh(); - 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,27 +175,29 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile pNode->mNumMeshes = 1; pNode->mMeshes = new unsigned int[1]; - // Loop over all child objects - for (size_t index = 0; index < pData->m_SubObjects.size(); index++) + // Loop over all child objects, TODO + /*for (size_t index = 0; index < pData->m_SubObjects.size(); index++) { // Create all child nodes pNode->mChildren[ index ] = createNodes( pModel, pData, pNode, pScene, MeshArray ); - - pMesh = new aiMesh(); - MeshArray.push_back( pMesh ); - createTopology( pModel, pData, pMesh ); + for (unsigned int meshIndex = 0; meshIndex < pData->m_SubObjects[ index ]->m_Meshes.size(); meshIndex++) + { + pMesh = new aiMesh(); + MeshArray.push_back( pMesh ); + createTopology( pModel, pData, meshIndex, pMesh ); + } // Create material of this object createMaterial(pModel, pData->m_SubObjects[ index ], pScene); - } + }*/ } // Set mesh instances into scene- and node-instances const size_t meshSizeDiff = MeshArray.size()- oldMeshSize; - if (meshSizeDiff > 0 ) + if ( meshSizeDiff > 0 ) { pNode->mMeshes = new unsigned int[ meshSizeDiff ]; - pNode->mNumMeshes++; + pNode->mNumMeshes = meshSizeDiff; size_t index = 0; for (size_t i = oldMeshSize; i < MeshArray.size(); i++) { @@ -210,88 +212,121 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile // ------------------------------------------------------------------------------------------------ // Create topology data -void ObjFileImporter::createTopology(const ObjFile::Model* pModel, const ObjFile::Object* pData, +void ObjFileImporter::createTopology(const ObjFile::Model* pModel, + const ObjFile::Object* pData, + unsigned int uiMeshIndex, aiMesh* pMesh ) { + // Checking preconditions + ai_assert( NULL != pModel ); if (NULL == pData) return; - - // Create mesh vertices - createVertexArray(pModel, pData, pMesh); // Create faces - pMesh->mNumFaces = (unsigned int)pData->m_Faces.size(); + ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ]; + pMesh->mNumFaces = (unsigned int) pObjMesh->m_Faces.size(); pMesh->mFaces = new aiFace[ pMesh->mNumFaces ]; - //pMesh->mMaterialIndex = pMode; - for (size_t index = 0; index < pMesh->mNumFaces; index++) + pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex; + + // Copy all data from all stored meshes + for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) { aiFace *pFace = &pMesh->mFaces[ index ]; - pFace->mNumIndices = (unsigned int)pData->m_Faces[index]->m_pVertices->size(); + const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_pVertices->size(); + pFace->mNumIndices = (unsigned int) uiNumIndices; if (pFace->mNumIndices > 0) { - 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 - //memcpy(pFace->mIndices, &pData->m_Faces[index]->m_pVertices[0], pFace->mNumIndices * sizeof(unsigned int)); - if (pArray != NULL) + pFace->mIndices = new unsigned int[ uiNumIndices ]; + ObjFile::Face::IndexArray *pIndexArray = pObjMesh->m_Faces[ index ]->m_pVertices; + ai_assert ( NULL != pIndexArray ); + for ( size_t a=0; amNumIndices; a++ ) { - for (size_t a=0; amNumIndices; a++) - { - pFace->mIndices[a] = pArray->at( a ); - } - } - else - { - ai_assert (false); + pFace->mIndices[ a ] = pIndexArray->at( a ); } } + else + { + pFace->mIndices = NULL; + } } + + // Create mesh vertices + createVertexArray(pModel, pData, uiMeshIndex, pMesh); } // ------------------------------------------------------------------------------------------------ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject, + unsigned int uiMeshIndex, aiMesh* pMesh) { + // Checking preconditions + ai_assert ( NULL != pCurrentObject ); + // Break, if no faces are stored in object if (pCurrentObject->m_Faces.empty()) return; - + + // Get current mesh + ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ]; + if ( NULL == pObjMesh ) + return; + // Copy vertices of this mesh instance - pMesh->mNumVertices = (unsigned int)pModel->m_Vertices.size(); + pMesh->mNumVertices = (unsigned int) pObjMesh->m_uiNumIndices; pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ]; - for ( size_t index=0; index < pModel->m_Vertices.size(); index++ ) + + // Allocate buffer for normal vectors + if ( !pModel->m_Normals.empty() ) + pMesh->mNormals = new aiVector3D[ pMesh->mNumVertices ]; + + // Allocate buffer for texture coordinates + if ( !pModel->m_TextureCoord.empty() ) { - pMesh->mVertices[ index ] = *pModel->m_Vertices[ index ]; + for ( size_t i=0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) + pMesh->mTextureCoords[ i ] = new aiVector3D[ pModel->m_TextureCoord.size() ]; } - // Copy normals for this mesh - if ( !pModel->m_Normals.empty() ) + // Copy vertices, normals and textures into aiMesh instance + unsigned int newIndex = 0; + for ( size_t index=0; index < pObjMesh->m_Faces.size(); index++ ) { - pMesh->mNormals = new aiVector3D[pModel->m_Normals.size()]; - for ( size_t index = 0; index < pModel->m_Normals.size(); index++ ) - { - pMesh->mNormals[ index ] = *pModel->m_Normals[ index ]; - } - } + // get destination face + aiFace *pDestFace = &pMesh->mFaces[ index ]; + + // get source face + ObjFile::Face *pSourceFace = pObjMesh->m_Faces[ index ]; - if (!pModel->m_TextureCoord.empty()) - { - pMesh->mTextureCoords[ 0 ] = new aiVector3D[ pModel->m_TextureCoord.size() ]; - - for( unsigned int e = 0; e < AI_MAX_NUMBER_OF_TEXTURECOORDS; e++) + // Copy all index arrays + for ( size_t vertexIndex = 0; vertexIndex < pSourceFace->m_pVertices->size(); vertexIndex++ ) { - if( pMesh->HasTextureCoords( e )) + unsigned int vertex = pSourceFace->m_pVertices->at( vertexIndex ); + assert ( vertex < pModel->m_Vertices.size() ); + pMesh->mVertices[ newIndex ] = *pModel->m_Vertices[ vertex ]; + + if ( !pModel->m_Normals.empty() ) { - for (unsigned int index = 0; index < pModel->m_TextureCoord.size(); index++ ) + const unsigned int normal = pSourceFace->m_pNormals->at( vertexIndex ); + assert( normal < pModel->m_Normals.size() ); + pMesh->mNormals[ newIndex ] = *pModel->m_Normals[ normal ]; + } + + if ( !pModel->m_TextureCoord.empty() ) + { + const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex ); + ai_assert ( tex < pModel->m_TextureCoord.size() ); + for ( size_t i=0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) { - aiVector2D *tex = pModel->m_TextureCoord[ index ]; - pMesh->mTextureCoords[ e ][ index ] = aiVector3D( tex->x, tex->y, 0.0f); + aiVector2D coord2d = *pModel->m_TextureCoord[ tex ]; + pMesh->mTextureCoords[ i ][ newIndex ] = aiVector3D( coord2d.x, coord2d.y, 0.0 ); } } + + assert( pMesh->mNumVertices > newIndex ); + pDestFace->mIndices[ vertexIndex ] = newIndex; + newIndex++; } - } + } } // ------------------------------------------------------------------------------------------------ @@ -333,16 +368,20 @@ void ObjFileImporter::createMaterial(const ObjFile::Model* pModel, const ObjFile // Store material name std::map::const_iterator it = pModel->m_MaterialMap.find( pModel->m_MaterialLib[ matIndex ] ); + + // No material found, use the default material if ( pModel->m_MaterialMap.end() == it) continue; + ObjFile::Material *pCurrentMaterial = (*it).second; mat->AddProperty( &pCurrentMaterial->MaterialName, AI_MATKEY_NAME ); - + mat->AddProperty( &pCurrentMaterial->illumination_model, 1, AI_MATKEY_SHADING_MODEL); + // 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); + 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 ) @@ -352,6 +391,9 @@ void ObjFileImporter::createMaterial(const ObjFile::Model* pModel, const ObjFile pScene->mMaterials[ pScene->mNumMaterials ] = mat; pScene->mNumMaterials++; } + + // Test number of created materials. + ai_assert( pScene->mNumMaterials == numMaterials ); } // ------------------------------------------------------------------------------------------------ diff --git a/code/ObjFileImporter.h b/code/ObjFileImporter.h index 99f97375f..6f40498e0 100644 --- a/code/ObjFileImporter.h +++ b/code/ObjFileImporter.h @@ -96,11 +96,11 @@ private: //! \brief Creates topology data like faces and meshes for the geometry. void createTopology(const ObjFile::Model* pModel, const ObjFile::Object* pData, - aiMesh* pMesh); + unsigned int uiMeshIndex, aiMesh* pMesh); //! \brief Creates vertices from model. - void createVertexArray(const ObjFile::Model* pModel, - const ObjFile::Object* pCurrentObject, aiMesh* pMesh); + void createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject, + unsigned int uiMeshIndex, aiMesh* pMesh); //! \brief Object counter helper method. void countObjects(const std::vector &rObjects, int &iNumMeshes); @@ -112,6 +112,9 @@ private: //! \brief Appends a child node to a parentnode and updates the datastructures. void appendChildToParentNode(aiNode *pParent, aiNode *pChild); + //! \brief + void createAnimations(); + private: //! Data buffer std::vector m_Buffer; diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index d5386fe59..a13a82e0d 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -71,11 +71,13 @@ void ObjFileParser::parseFile() else if (*m_DataIt == 't') { // Read in texture coordinate (2D) + ++m_DataIt; getVector2(m_pModel->m_TextureCoord); } else if (*m_DataIt == 'n') { // Read in normal vector definition + ++m_DataIt; getVector3(m_pModel->m_Normals); } } @@ -286,7 +288,7 @@ void ObjFileParser::getFace() face->m_pMaterial = m_pModel->m_pDefaultMaterial; // Create a default object, if nothing there - if (NULL == m_pModel->m_pCurrent) + if ( NULL == m_pModel->m_pCurrent ) createObject("defaultobject"); // Store the new instance @@ -299,6 +301,8 @@ void ObjFileParser::getFace() m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh ); } m_pModel->m_pCurrentMesh->m_Faces.push_back( face ); + if ( !face->m_pVertices->empty() ) + m_pModel->m_pCurrentMesh->m_uiNumIndices += face->m_pVertices->size(); // Skip the rest of the line m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); @@ -338,6 +342,7 @@ void ObjFileParser::getMaterialDesc() // 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 ); + m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strName ); } // Skip rest of line @@ -387,24 +392,23 @@ void ObjFileParser::getMaterialLib() // Extract the extention std::string strExt(""); - extractExtension(strMatName, strExt); - std::string mat = "mtl"; + extractExtension( strMatName, strExt ); + static const std::string mat = "mtl"; // Load the material library DefaultIOSystem FileSystem; IOStream *pFile = FileSystem.Open(absName); if (0L != pFile) { + // Import material library data from file size_t size = pFile->FileSize(); std::vector buffer; buffer.resize( size ); - size_t read_size = pFile->Read( &buffer[ 0 ], sizeof( char ), size ); FileSystem.Close( pFile ); // Importing the material library ObjFileMtlImporter mtlImporter( buffer, absName, m_pModel ); - m_pModel->m_MaterialLib.push_back( strMatName ); } // Skip rest of line @@ -422,7 +426,7 @@ void ObjFileParser::getNewMaterial() std::string strMat(pStart, *m_DataIt); while (isSpace(*m_DataIt)) m_DataIt++; - std::map::iterator it = m_pModel->m_MaterialMap.find(strMat); + std::map::iterator it = m_pModel->m_MaterialMap.find( strMat ); if (it == m_pModel->m_MaterialMap.end()) { // Show a warning, if material was not found @@ -435,11 +439,29 @@ void ObjFileParser::getNewMaterial() { // Set new material m_pModel->m_pCurrentMaterial = (*it).second; + m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strMat ); } m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } +// ------------------------------------------------------------------- +int ObjFileParser::getMaterialIndex( const std::string &strMaterialName ) +{ + int mat_index = -1; + if ( strMaterialName.empty() ) + return mat_index; + for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index) + { + if ( strMaterialName == m_pModel->m_MaterialLib[ index ]) + { + mat_index = index; + break; + } + } + return mat_index; +} + // ------------------------------------------------------------------- // Getter for a group name. void ObjFileParser::getGroupName() diff --git a/code/ObjFileParser.h b/code/ObjFileParser.h index 6e79dde03..4ddf384ff 100644 --- a/code/ObjFileParser.h +++ b/code/ObjFileParser.h @@ -91,6 +91,7 @@ private: void getNewMaterial(); void getGroupName(); void getGroupNumber(); + int getMaterialIndex( const std::string &strMaterialName ); void getObjectName(); void createObject(const std::string &strObjectName); void reportErrorTokenInFace(); diff --git a/tools/assimp_view/Display.cpp b/tools/assimp_view/Display.cpp index da1980582..b1533196d 100644 --- a/tools/assimp_view/Display.cpp +++ b/tools/assimp_view/Display.cpp @@ -428,34 +428,43 @@ int CDisplay::AddTextureToDisplayList(unsigned int iType, { case AI_TEXTYPE_DIFFUSE: piTexture = &g_pcAsset->apcMeshes[iMesh]->piDiffuseTexture; - szType = "Diffuse";break; + szType = "Diffuse"; + break; case AI_TEXTYPE_SPECULAR: piTexture = &g_pcAsset->apcMeshes[iMesh]->piSpecularTexture; - szType = "Specular";break; + szType = "Specular"; + break; case AI_TEXTYPE_AMBIENT: piTexture = &g_pcAsset->apcMeshes[iMesh]->piAmbientTexture; - szType = "Ambient";break; + szType = "Ambient"; + break; case AI_TEXTYPE_EMISSIVE: piTexture = &g_pcAsset->apcMeshes[iMesh]->piEmissiveTexture; - szType = "Emissive";break; + szType = "Emissive"; + break; case AI_TEXTYPE_HEIGHT: piTexture = &g_pcAsset->apcMeshes[iMesh]->piNormalTexture; - szType = "HeightMap";break; + szType = "HeightMap"; + break; case AI_TEXTYPE_NORMALS: piTexture = &g_pcAsset->apcMeshes[iMesh]->piNormalTexture; - szType = "NormalMap";break; + szType = "NormalMap"; + break; case AI_TEXTYPE_SHININESS: piTexture = &g_pcAsset->apcMeshes[iMesh]->piShininessTexture; - szType = "Shininess";break; + szType = "Shininess"; + break; default: // opacity + opacity | mask piTexture = &g_pcAsset->apcMeshes[iMesh]->piOpacityTexture; - szType = "Opacity";break; + szType = "Opacity"; + break; }; if (bIsExtraOpacity) { sprintf(chTemp,"%s %i ()",szType,iIndex+1); } - else sprintf(chTemp,"%s %i (%s)",szType,iIndex+1,sz); + else + sprintf(chTemp,"%s %i (%s)",szType,iIndex+1,sz); TVITEMEX tvi; TVINSERTSTRUCT sNew;