Browse Source

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

kimmi 17 years ago
parent
commit
0e125c2255

+ 1 - 1
code/3DSGenNormals.cpp

@@ -133,4 +133,4 @@ void Dot3DSImporter::GenNormals(Dot3DS::Mesh* sMesh)
 	}
 	sMesh->mNormals = avNormals;
 	return;
-}
+}

+ 23 - 6
code/ObjFileData.h

@@ -80,11 +80,11 @@ struct Face
 	Face(std::vector<unsigned int> *pVertices, 
 			std::vector<unsigned int> *pNormals, 
 			std::vector<unsigned int> *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<Face*> 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
 	}

+ 107 - 65
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; a<pFace->mNumIndices; a++ )
 			{
-				for (size_t a=0; a<pFace->mNumIndices; 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++ )
-	{
-		pMesh->mVertices[ index ] = *pModel->m_Vertices[ index ];
-	}
 	
-	// Copy normals for this mesh
+	// 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->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 ];
-		}
+		for ( size_t i=0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++)
+			pMesh->mTextureCoords[ i ] = new aiVector3D[ pModel->m_TextureCoord.size() ];
 	}
-
-	if (!pModel->m_TextureCoord.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->mTextureCoords[ 0 ] = new aiVector3D[ pModel->m_TextureCoord.size() ];
+		// get destination face
+		aiFace *pDestFace = &pMesh->mFaces[ index ];
+		
+		// get source face
+		ObjFile::Face *pSourceFace = pObjMesh->m_Faces[ index ]; 
 
-		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<std::string, ObjFile::Material*>::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<int>( &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 );
 }
 
 // ------------------------------------------------------------------------------------------------

+ 6 - 3
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<ObjFile::Object*> &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<char> m_Buffer;

+ 28 - 6
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<DataArrayIt>( 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<char> 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<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find(strMat);
+	std::map<std::string, ObjFile::Material*>::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<DataArrayIt>( 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()

+ 1 - 0
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();

+ 18 - 9
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 (<copy of diffuse #1>)",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;