From 7f2f5e75552db3cc21250ce748a594499817df91 Mon Sep 17 00:00:00 2001 From: kimmi Date: Thu, 8 Jul 2010 21:25:48 +0000 Subject: [PATCH] - 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 --- code/ObjFileImporter.cpp | 10 +- code/Q3BSPFileData.h | 17 +-- code/Q3BSPFileImporter.cpp | 243 ++++++++++++++++++++++++++++++++++++- code/Q3BSPFileImporter.h | 26 +++- code/Q3BSPFileParser.cpp | 3 +- 5 files changed, 278 insertions(+), 21 deletions(-) diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index 8952438bf..99d79ba09 100644 --- a/code/ObjFileImporter.cpp +++ b/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 diff --git a/code/Q3BSPFileData.h b/code/Q3BSPFileData.h index faa1a6c05..49212b4cd 100644 --- a/code/Q3BSPFileData.h +++ b/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 @@ -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 m_Textures; std::vector m_Lightmaps; std::vector 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 diff --git a/code/Q3BSPFileImporter.cpp b/code/Q3BSPFileImporter.cpp index 3ffd144a5..ee54e6ddd 100644 --- a/code/Q3BSPFileImporter.cpp +++ b/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 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& 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 *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 *pArray = new std::vector; + pArray->push_back( pQ3BSPFace ); + lookupMap[ key ] = pArray; + } + else + { + std::vector *pArray = (*it).second; + ai_assert( NULL != pArray ); + if ( NULL != pArray ) + { + pArray->push_back( pQ3BSPFace ); + } + } + } + + std::vector MeshArray; + std::vector NodeArray; + for ( FaceMapIt it = lookupMap.begin(); it != lookupMap.end(); ++it ) + { + std::vector *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; imNumFaces; 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; imParent = pParent; + pParent->mChildren[ i ] = pNode; + pParent->mChildren[ i ]->mMeshes[ 0 ] = i; + } +} + +// ------------------------------------------------------------------------------------------------ +aiNode *Q3BSPFileImporter::CreateTopology( const Q3BSP::Q3BSPModel *pModel, + std::vector &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::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 &rArray ) const +{ + size_t numVerts = 0; + for ( std::vector::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 &rArray ) const +{ + size_t numFaces = 0; + for ( std::vector::const_iterator it = rArray.begin(); it != rArray.end(); + ++it ) + { + Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; + if ( pQ3BSPFace->iNumOfMeshVerts > 0) + { + numFaces++; + } + } + + return numFaces; +} + // ------------------------------------------------------------------------------------------------ } // Namespace Assimp diff --git a/code/Q3BSPFileImporter.h b/code/Q3BSPFileImporter.h index 7be01e251..996b23c2f 100644 --- a/code/Q3BSPFileImporter.h +++ b/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*> FaceMap; + typedef std::map* >::iterator FaceMapIt; + typedef std::map*>::const_iterator FaceMapConstIt; + void GetExtensionList(std::set& 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 &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 &rArray ) const; + size_t countFaces( const std::vector &rArray ) const; + +private: + aiMesh *m_pCurrentMesh; }; } // Namespace Assimp diff --git a/code/Q3BSPFileParser.cpp b/code/Q3BSPFileParser.cpp index c39882dbc..ece2df4bc 100644 --- a/code/Q3BSPFileParser.cpp +++ b/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;