ソースを参照

- UPDATE : Q3BSPLoader now imports topology of a quake-level. Known issues: It seems, that faces a still missing.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@771 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
kimmi 15 年 前
コミット
7f2f5e7555

+ 5 - 5
code/ObjFileImporter.cpp

@@ -48,22 +48,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ObjFileData.h"
 
 namespace Assimp	{
-// ------------------------------------------------------------------------------------------------
 
 using namespace std;
 
 // ------------------------------------------------------------------------------------------------
 //	Default constructor
 ObjFileImporter::ObjFileImporter() :
-	m_pRootObject(NULL)
+	m_Buffer(),	
+	m_pRootObject( NULL ),
+	m_strAbsPath( "" )
 {
     DefaultIOSystem io;
 	m_strAbsPath = io.getOsSeparator();
-    
 }
 
 // ------------------------------------------------------------------------------------------------
-//	Destructor
+//	Destructor.
 ObjFileImporter::~ObjFileImporter()
 {
 	// Release root object instance
@@ -75,7 +75,7 @@ ObjFileImporter::~ObjFileImporter()
 }
 
 // ------------------------------------------------------------------------------------------------
-//	Returns true, fi file is an obj file
+//	Returns true, if file is an obj file.
 bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem*  pIOHandler , bool checkSig ) const
 {
 	if(!checkSig) //Check File Extension

+ 9 - 8
code/Q3BSPFileData.h

@@ -37,8 +37,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ----------------------------------------------------------------------
 */
-#ifndef ASSIMP_Q§BSPFILEDATA_H_INC
-#define ASSIMP_Q§BSPFILEDATA_H_INC
+#ifndef ASSIMP_Q3BSPFILEDATA_H_INC
+#define ASSIMP_Q3BSPFILEDATA_H_INC
 
 #include <vector>
 
@@ -102,7 +102,7 @@ struct sQ3BSPFace
 	int iNumOfVerts;				///< Number of vertices
 	int	iMeshVertexIndex;			///< Index of first mesh vertex
 	int iNumOfMeshVerts;			///< Anzahl der Meshvertices
-	int iLightmapID;				///< Index in das Lightmaparray
+	int iLightmapID;				///< Index in das Lightmap array
 	int iLMapCorner[ 2 ];			///< Die Ecke der Lightmap in der Textur
 	int iLMapSize[ 2 ];				///< Size of the lightmap stored on the texture
 	vec3f vLMapPos;					///< 3D-Ursprung der Lightmap
@@ -114,12 +114,12 @@ struct sQ3BSPFace
 /// A quake3 texture name.
 struct sQ3BSPTexture 
 {
-	char strName[ 64 ];		//!< Name of the texture without extention
-	int iFlags;			//!< Not used
-	int iContents;		//!< Not used
+	char strName[ 64 ];		///< Name of the texture without extention
+	int iFlags;				///< Not used
+	int iContents;			///< Not used
 };
 
-//! A lightmap of the level, size 128 x 128, RGB components
+///	A lightmap of the level, size 128 x 128, RGB components.
 struct sQ3BSPLightmap 
 {
 	unsigned char bLMapData[CE_BSP_LIGHTMAPSIZE];
@@ -173,6 +173,7 @@ struct Q3BSPModel
 	std::vector<sQ3BSPTexture*> m_Textures;
 	std::vector<sQ3BSPLightmap*> m_Lightmaps;
 	std::vector<char> m_EntityData;
+	std::string m_ModelName;
 
 	Q3BSPModel() :
 		m_Data(),
@@ -191,4 +192,4 @@ struct Q3BSPModel
 }
 }
 
-#endif // ASSIMP_Q§BSPFILEDATA_H_INC
+#endif // ASSIMP_Q3BSPFILEDATA_H_INC

+ 239 - 4
code/Q3BSPFileImporter.cpp

@@ -1,6 +1,6 @@
 /*
 Open Asset Import Library (ASSIMP)
-----------------------------------------------------------------------
+---------------------------------------------------------------------------------------------------
 
 Copyright (c) 2006-2008, ASSIMP Development Team
 All rights reserved.
@@ -35,7 +35,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-----------------------------------------------------------------------
+---------------------------------------------------------------------------------------------------
 */
 #include "AssimpPCH.h"
 #ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
@@ -44,7 +44,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "Q3BSPFileImporter.h"
 #include "Q3BSPZipArchive.h"
 #include "Q3BSPFileParser.h"
+#include "Q3BSPFileData.h"
 #include "../contrib/zlib/zlib.h"
+#include "../include/aiTypes.h"
+#include "../include/aiMesh.h"
 #include <vector>
 
 namespace Assimp
@@ -53,7 +56,16 @@ namespace Assimp
 using namespace Q3BSP;
 
 // ------------------------------------------------------------------------------------------------
-Q3BSPFileImporter::Q3BSPFileImporter()
+static void createKey( int id1, int id2, std::string &rKey )
+{
+	std::stringstream str;
+	str << id1 << "." << id2;
+	rKey = str.str();
+}
+
+// ------------------------------------------------------------------------------------------------
+Q3BSPFileImporter::Q3BSPFileImporter() :
+	m_pCurrentMesh( NULL )
 {
 }
 
@@ -75,7 +87,7 @@ bool Q3BSPFileImporter::CanRead( const std::string& rFile, IOSystem* pIOHandler,
 // ------------------------------------------------------------------------------------------------
 void Q3BSPFileImporter::GetExtensionList(std::set<std::string>& extensions)
 {
-	extensions.insert("pk3");
+	extensions.insert( "pk3" );
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -102,6 +114,7 @@ void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene* pScene
 	Q3BSPModel *pBSPModel = fileParser.getModel();
 	if ( NULL != pBSPModel )
 	{
+		CreateDataFromImport( pBSPModel, pScene );
 	}
 }
 
@@ -151,6 +164,228 @@ bool Q3BSPFileImporter::findFirstMapInArchive( Q3BSPZipArchive &rArchive, std::s
 	return false;
 }
 
+// ------------------------------------------------------------------------------------------------
+void Q3BSPFileImporter::CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene )
+{
+	if ( NULL == pModel || NULL == pScene )
+		return;
+
+	pScene->mRootNode = new aiNode;
+	if ( !pModel->m_ModelName.empty() )
+	{
+		pScene->mRootNode->mName.Set( pModel->m_ModelName );
+	}
+
+	CreateNodes( pModel, pScene, pScene->mRootNode );
+}
+
+// ------------------------------------------------------------------------------------------------
+void Q3BSPFileImporter::CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiNode *pParent )
+{
+	ai_assert( NULL != pModel );
+	if ( NULL == pModel )
+		return;
+
+	FaceMap matLookupTable;
+	std::string key( "" );
+	std::vector<sQ3BSPFace*> *pCurFaceArray = NULL;
+	FaceMap lookupMap;
+	for ( size_t idx=0; idx < pModel->m_Faces.size(); idx++ )
+	{
+		Q3BSP::sQ3BSPFace *pQ3BSPFace = pModel->m_Faces[ idx ];
+		int texId = pQ3BSPFace->iTextureID;
+		int lightMapId = pQ3BSPFace->iLightmapID;
+		createKey( texId, lightMapId, key );
+		FaceMapIt it = lookupMap.find( key );
+		if ( lookupMap.end() == it)
+		{
+			std::vector<Q3BSP::sQ3BSPFace*> *pArray = new std::vector<Q3BSP::sQ3BSPFace*>;
+			pArray->push_back( pQ3BSPFace );
+			lookupMap[ key ] = pArray;
+		}
+		else
+		{
+			std::vector<Q3BSP::sQ3BSPFace*> *pArray = (*it).second;
+			ai_assert( NULL != pArray );
+			if ( NULL != pArray )
+			{
+				pArray->push_back( pQ3BSPFace );
+			}
+		}
+	}
+	
+	std::vector<aiMesh*> MeshArray;
+	std::vector<aiNode*> NodeArray;
+	for ( FaceMapIt it = lookupMap.begin(); it != lookupMap.end(); ++it )
+	{
+		std::vector<Q3BSP::sQ3BSPFace*> *pArray = (*it).second;
+		size_t numVerts = countData( *pArray );
+		if ( 0 != numVerts )
+		{
+			aiMesh* pMesh = new aiMesh;
+			aiNode *pNode = CreateTopology( pModel, *pArray, pMesh );
+			if ( NULL != pNode )
+			{
+				NodeArray.push_back( pNode );
+				MeshArray.push_back( pMesh );
+			}
+			else
+			{
+				delete pMesh;
+			}
+		}
+	}
+
+	pScene->mNumMeshes = MeshArray.size();
+	pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ];
+	for ( size_t i=0; i<MeshArray.size(); ++i )
+	{
+		aiMesh *pMesh = MeshArray[ i ];
+		for ( size_t j=0; j<pMesh->mNumFaces; j++ )
+		{
+			aiFace *face = &pMesh->mFaces[j];
+			if ( NULL == face->mIndices )
+			{
+				printf("error\n");
+			}
+			ai_assert( NULL != face->mIndices );
+		}
+		pScene->mMeshes[ i ] = pMesh;
+	}
+
+	pParent->mNumChildren = MeshArray.size();
+	pParent->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren ];
+	for ( size_t i=0; i<NodeArray.size(); i++ )
+	{
+		aiNode *pNode = NodeArray[ i ];
+		pNode->mParent = pParent;
+		pParent->mChildren[ i ] = pNode;
+		pParent->mChildren[ i ]->mMeshes[ 0 ] = i;
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+aiNode *Q3BSPFileImporter::CreateTopology( const Q3BSP::Q3BSPModel *pModel,
+										  std::vector<sQ3BSPFace*> &rArray, aiMesh* pMesh )
+{
+	size_t numVerts = countData( rArray );
+	if ( 0 == numVerts )
+		return NULL;
+	
+	size_t numFaces = countFaces( rArray );
+	if ( 0 == numFaces )
+		return NULL;
+
+	pMesh->mFaces = new aiFace[ numFaces ];
+	pMesh->mNumFaces = numFaces;
+	pMesh->mNumVertices = numVerts;
+	pMesh->mVertices = new aiVector3D[ numVerts ];
+	pMesh->mNormals =  new aiVector3D[ numVerts ];
+	pMesh->mTextureCoords[ 0 ] = new aiVector3D[ numVerts ];
+	pMesh->mTextureCoords[ 1 ] = new aiVector3D[ numVerts ];
+
+	unsigned int faceIdx = 0;
+	unsigned int vertIdx = 0;
+	aiVector3D *pVec3( NULL );
+	aiVector3D normal;
+	for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); 
+		++it )
+	{
+		Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
+		ai_assert( NULL != pQ3BSPFace );
+		if ( pQ3BSPFace->iNumOfMeshVerts == 0 )
+		{
+			continue;
+		}
+
+		if ( pQ3BSPFace->iType == 1 || pQ3BSPFace->iType == 3 )
+		{
+			createTriangleTopology( pModel, pQ3BSPFace, pMesh, faceIdx, vertIdx );
+		}		
+	}
+
+	aiNode *pNode = new aiNode;
+	pNode->mNumMeshes = 1;
+	pNode->mMeshes = new unsigned int[ 1 ];
+
+	return pNode;
+}
+// ------------------------------------------------------------------------------------------------
+void Q3BSPFileImporter::createTriangleTopology( const Q3BSP::Q3BSPModel *pModel,
+											  Q3BSP::sQ3BSPFace *pQ3BSPFace, 
+											  aiMesh* pMesh, unsigned int &rFaceIdx, 
+											  unsigned int &rVertIdx )
+{
+	ai_assert( faceIdx < pMesh->mNumFaces );
+	aiFace *pFace = &pMesh->mFaces[ rFaceIdx ];
+	ai_assert( NULL != pFace );
+	rFaceIdx++;
+
+	pFace->mNumIndices = pQ3BSPFace->iNumOfMeshVerts;
+	pFace->mIndices = new unsigned int[ pFace->mNumIndices ];
+	aiVector3D normal;
+	normal.Set( pQ3BSPFace->vNormal.x, pQ3BSPFace->vNormal.y, pQ3BSPFace->vNormal.z );
+
+	for ( int i = 0; i < pQ3BSPFace->iNumOfMeshVerts; ++i )
+	{
+		size_t idx =  pModel->m_Indices[ pQ3BSPFace->iMeshVertexIndex + i ];;
+		const unsigned int index = pQ3BSPFace->iVertexIndex + pModel->m_Indices[idx];
+		ai_assert( index < pModel->m_Vertices.size() );
+		sQ3BSPVertex *pVertex = pModel->m_Vertices[ index ];
+		ai_assert( NULL != pVertex );
+
+		pMesh->mVertices[ rVertIdx ].Set( pVertex->vPosition.x, pVertex->vPosition.y, pVertex->vPosition.z );
+		pMesh->mNormals[ rVertIdx ].Set( normal.x, normal.y, normal.z );
+				
+		pMesh->mTextureCoords[ 0 ][ rVertIdx ].Set( pVertex->vTexCoord.x, pVertex->vTexCoord.y, 0.0f );
+		pMesh->mTextureCoords[ 1 ][ rVertIdx ].Set( pVertex->vLightmap.x, pVertex->vLightmap.y, 0.0f );
+		pFace->mIndices[ i ] = rVertIdx;
+		rVertIdx++;
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+void Q3BSPFileImporter::createMaterials()
+{
+	// TODO
+}
+
+// ------------------------------------------------------------------------------------------------
+size_t Q3BSPFileImporter::countData( const std::vector<sQ3BSPFace*> &rArray ) const
+{
+	size_t numVerts = 0;
+	for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); 
+		++it )
+	{
+		sQ3BSPFace *pQ3BSPFace = *it;
+		if ( pQ3BSPFace->iType == 1 || pQ3BSPFace->iType == 3 )
+		{
+			Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
+			ai_assert( NULL != pQ3BSPFace );
+			numVerts += pQ3BSPFace->iNumOfMeshVerts;
+		}
+	}
+
+	return numVerts;
+}
+
+// ------------------------------------------------------------------------------------------------
+size_t Q3BSPFileImporter::countFaces( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const
+{
+	size_t numFaces = 0;
+	for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); 
+		++it )
+	{
+		Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
+		if ( pQ3BSPFace->iNumOfMeshVerts > 0)
+		{
+			numFaces++;
+		}
+	}
+
+	return numFaces;
+}
+
 // ------------------------------------------------------------------------------------------------
 
 } // Namespace Assimp

+ 23 - 3
code/Q3BSPFileImporter.h

@@ -42,12 +42,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "BaseImporter.h"
 
+struct aiMesh;
+
 namespace Assimp
 {
-
 namespace Q3BSP
 {
-	class Q3BSPZipArchive;
+
+class Q3BSPZipArchive;
+struct Q3BSPModel;
+struct sQ3BSPFace;
+
 }
 
 class Q3BSPFileImporter : BaseImporter
@@ -55,7 +60,7 @@ class Q3BSPFileImporter : BaseImporter
 	friend class Importer;
 
 protected:
-	///	\brief	Default constructor,
+	///	\brief	Default constructor.
 	Q3BSPFileImporter();
 
 	///	\brief	Destructor.
@@ -67,10 +72,25 @@ public:
 	bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const;
 
 private:
+	typedef std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>*> FaceMap;
+	typedef std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>* >::iterator FaceMapIt;
+	typedef std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>*>::const_iterator FaceMapConstIt;
+
 	void GetExtensionList(std::set<std::string>& extensions);
 	void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
 	void separateMapName( const std::string &rImportName, std::string &rArchiveName, std::string &rMapName );
 	bool findFirstMapInArchive( Q3BSP::Q3BSPZipArchive &rArchive, std::string &rMapName );
+	void CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene );
+	void CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiNode *pParent );
+	aiNode *CreateTopology( const Q3BSP::Q3BSPModel *pModel, std::vector<Q3BSP::sQ3BSPFace*> &rArray, aiMesh* pMesh );
+	void createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, Q3BSP::sQ3BSPFace *pQ3BSPFace, aiMesh* pMesh, unsigned int &rFaceIdx, 
+		unsigned int &rVertIdx  );
+	void createMaterials();
+	size_t countData( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
+	size_t countFaces( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
+
+private:
+	aiMesh *m_pCurrentMesh;
 };
 
 } // Namespace Assimp

+ 2 - 1
code/Q3BSPFileParser.cpp

@@ -63,6 +63,7 @@ Q3BSPFileParser::Q3BSPFileParser( const std::string &rMapName, Q3BSPZipArchive *
 		return;
 
 	m_pModel = new Q3BSPModel;
+	m_pModel->m_ModelName = rMapName;
 	if ( !parseFile() )
 	{
 		delete m_pModel;
@@ -84,7 +85,7 @@ Q3BSP::Q3BSPModel *Q3BSPFileParser::getModel() const
 }
 
 // ------------------------------------------------------------------------------------------------
-bool Q3BSPFileParser::readData(const std::string &rMapName)
+bool Q3BSPFileParser::readData( const std::string &rMapName )
 {
 	if ( !m_pZipArchive->Exists( rMapName.c_str() ) )
 		return false;