- 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
pull/1/head
kimmi 2010-07-08 21:25:48 +00:00
parent edb2fca8d6
commit 7f2f5e7555
5 changed files with 278 additions and 21 deletions

View File

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

View File

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

View File

@ -1,6 +1,6 @@
/* /*
Open Asset Import Library (ASSIMP) Open Asset Import Library (ASSIMP)
---------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------
Copyright (c) 2006-2008, ASSIMP Development Team Copyright (c) 2006-2008, ASSIMP Development Team
All rights reserved. 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 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------
*/ */
#include "AssimpPCH.h" #include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER #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 "Q3BSPFileImporter.h"
#include "Q3BSPZipArchive.h" #include "Q3BSPZipArchive.h"
#include "Q3BSPFileParser.h" #include "Q3BSPFileParser.h"
#include "Q3BSPFileData.h"
#include "../contrib/zlib/zlib.h" #include "../contrib/zlib/zlib.h"
#include "../include/aiTypes.h"
#include "../include/aiMesh.h"
#include <vector> #include <vector>
namespace Assimp namespace Assimp
@ -53,7 +56,16 @@ namespace Assimp
using namespace Q3BSP; 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) 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(); Q3BSPModel *pBSPModel = fileParser.getModel();
if ( NULL != pBSPModel ) if ( NULL != pBSPModel )
{ {
CreateDataFromImport( pBSPModel, pScene );
} }
} }
@ -151,6 +164,228 @@ bool Q3BSPFileImporter::findFirstMapInArchive( Q3BSPZipArchive &rArchive, std::s
return false; 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 } // Namespace Assimp

View File

@ -42,12 +42,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h" #include "BaseImporter.h"
struct aiMesh;
namespace Assimp namespace Assimp
{ {
namespace Q3BSP namespace Q3BSP
{ {
class Q3BSPZipArchive;
class Q3BSPZipArchive;
struct Q3BSPModel;
struct sQ3BSPFace;
} }
class Q3BSPFileImporter : BaseImporter class Q3BSPFileImporter : BaseImporter
@ -55,7 +60,7 @@ class Q3BSPFileImporter : BaseImporter
friend class Importer; friend class Importer;
protected: protected:
/// \brief Default constructor, /// \brief Default constructor.
Q3BSPFileImporter(); Q3BSPFileImporter();
/// \brief Destructor. /// \brief Destructor.
@ -67,10 +72,25 @@ public:
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const; bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const;
private: 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 GetExtensionList(std::set<std::string>& extensions);
void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
void separateMapName( const std::string &rImportName, std::string &rArchiveName, std::string &rMapName ); void separateMapName( const std::string &rImportName, std::string &rArchiveName, std::string &rMapName );
bool findFirstMapInArchive( Q3BSP::Q3BSPZipArchive &rArchive, 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 } // Namespace Assimp

View File

@ -63,6 +63,7 @@ Q3BSPFileParser::Q3BSPFileParser( const std::string &rMapName, Q3BSPZipArchive *
return; return;
m_pModel = new Q3BSPModel; m_pModel = new Q3BSPModel;
m_pModel->m_ModelName = rMapName;
if ( !parseFile() ) if ( !parseFile() )
{ {
delete m_pModel; 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() ) ) if ( !m_pZipArchive->Exists( rMapName.c_str() ) )
return false; return false;