瀏覽代碼

CHANGE: Bugfixes for ObjFile material import

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@53 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
kimmi 17 年之前
父節點
當前提交
a3d2ff5f26
共有 7 個文件被更改,包括 194 次插入81 次删除
  1. 42 4
      code/ObjFileData.h
  2. 63 23
      code/ObjFileImporter.cpp
  3. 19 14
      code/ObjFileImporter.h
  4. 17 21
      code/ObjFileMtlImporter.cpp
  5. 9 0
      code/ObjFileMtlImporter.h
  6. 35 18
      code/ObjFileParser.cpp
  7. 9 1
      code/ObjFileParser.h

+ 42 - 4
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<Face*> 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<aiVector2D*> m_TextureCoord;
+	//!	Current mesh instance
+	Mesh *m_pCurrentMesh;
+	//!	Vector with stored meshes
+	std::vector<Mesh*> m_Meshes;
 	//!	Material map
 	std::map<std::string, Material*> 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<Object*>::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<Mesh*>::iterator it = m_Meshes.begin();
+			it != m_Meshes.end(); ++it)
+		{
+			delete *it;
+		}
+		m_Meshes.clear();
 	}
 };
 

+ 63 - 23
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<std::string, ObjFile::Material*>::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;
-
 }
 
 // ------------------------------------------------------------------------------------------------

+ 19 - 14
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<aiMesh*> &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<ObjFile::Object*> &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<char> 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

+ 17 - 21
code/ObjFileMtlImporter.cpp

@@ -16,14 +16,13 @@ ObjFileMtlImporter::ObjFileMtlImporter( std::vector<char> &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<DataArrayIt>( 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<DataArrayIt>( 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<std::string, ObjFile::Material*>::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;
+	}
 }
 
 // -------------------------------------------------------------------

+ 9 - 0
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];
 };
 

+ 35 - 18
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<char> &Data, const std::string &strAbsPath, const std::string &strModelName) :
+ObjFileParser::ObjFileParser(std::vector<char> &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<DataArrayIt>( 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<std::string, ObjFile::Material*>::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<DataArrayIt>( 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<DataArrayIt>( 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<char> 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<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 
 // -------------------------------------------------------------------
-//	
+//	Set a new material definition as the current material.
 void ObjFileParser::getNewMaterial()
 {
 	m_DataIt = getNextToken<DataArrayIt>(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

+ 9 - 1
code/ObjFileParser.h

@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <vector>
 #include <string>
+#include <map>
 #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