- allow loading Quake3 BSPs directly without needing the zip archive

pull/25/head
Tai Chi Minh Ralph Eastwood 2013-04-05 13:06:42 +01:00
parent 4277413052
commit ad5c05ae47
4 changed files with 31 additions and 102 deletions

View File

@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//#include <windows.h> //#include <windows.h>
#include "DefaultIOSystem.h" #include "DefaultIOSystem.h"
#include "Q3BSPFileImporter.h" #include "Q3BSPFileImporter.h"
#include "Q3BSPZipArchive.h"
#include "Q3BSPFileParser.h" #include "Q3BSPFileParser.h"
#include "Q3BSPFileData.h" #include "Q3BSPFileData.h"
@ -170,10 +169,10 @@ Q3BSPFileImporter::~Q3BSPFileImporter()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns true, if the loader can read this. // Returns true, if the loader can read this.
bool Q3BSPFileImporter::CanRead( const std::string& rFile, IOSystem* /*pIOHandler*/, bool checkSig ) const bool Q3BSPFileImporter::CanRead( const std::string& rFile, IOSystem* pIOHandler, bool checkSig ) const
{ {
if(!checkSig) { if(!checkSig) {
return SimpleExtensionCheck( rFile, "pk3" ); return SimpleExtensionCheck( rFile, "bsp" );
} }
// TODO perhaps add keyword based detection // TODO perhaps add keyword based detection
return false; return false;
@ -188,86 +187,20 @@ const aiImporterDesc* Q3BSPFileImporter::GetInfo () const
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Import method. // Import method.
void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene* pScene, IOSystem* /*pIOHandler*/) void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene* pScene, IOSystem* pIOHandler)
{ {
Q3BSPZipArchive Archive( rFile ); Q3BSPFileParser fileParser( rFile, pIOHandler );
if ( !Archive.isOpen() )
{
throw DeadlyImportError( "Failed to open file " + rFile + "." );
}
std::string archiveName( "" ), mapName( "" );
separateMapName( rFile, archiveName, mapName );
if ( mapName.empty() )
{
if ( !findFirstMapInArchive( Archive, mapName ) )
{
return;
}
}
Q3BSPFileParser fileParser( mapName, &Archive );
Q3BSPModel *pBSPModel = fileParser.getModel(); Q3BSPModel *pBSPModel = fileParser.getModel();
if ( NULL != pBSPModel ) if ( NULL != pBSPModel )
{ {
CreateDataFromImport( pBSPModel, pScene, &Archive ); CreateDataFromImport( pBSPModel, pScene, pIOHandler );
} }
} }
// ------------------------------------------------------------------------------------------------
// Separates the map name from the import name.
void Q3BSPFileImporter::separateMapName( const std::string &rImportName, std::string &rArchiveName,
std::string &rMapName )
{
rArchiveName = "";
rMapName = "";
if ( rImportName.empty() )
return;
std::string::size_type pos = rImportName.rfind( "," );
if ( std::string::npos == pos )
{
rArchiveName = rImportName;
return;
}
rArchiveName = rImportName.substr( 0, pos );
rMapName = rImportName.substr( pos, rImportName.size() - pos - 1 );
}
// ------------------------------------------------------------------------------------------------
// Returns the first map in the map archive.
bool Q3BSPFileImporter::findFirstMapInArchive( Q3BSPZipArchive &rArchive, std::string &rMapName )
{
rMapName = "";
std::vector<std::string> fileList;
rArchive.getFileList( fileList );
if ( fileList.empty() )
return false;
for ( std::vector<std::string>::iterator it = fileList.begin(); it != fileList.end();
++it )
{
std::string::size_type pos = (*it).find( "maps/" );
if ( std::string::npos != pos )
{
std::string::size_type extPos = (*it).find( ".bsp" );
if ( std::string::npos != extPos )
{
rMapName = *it;
return true;
}
}
}
return false;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Creates the assimp specific data. // Creates the assimp specific data.
void Q3BSPFileImporter::CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, void Q3BSPFileImporter::CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
Q3BSPZipArchive *pArchive ) IOSystem* pIOHandler )
{ {
if ( NULL == pModel || NULL == pScene ) if ( NULL == pModel || NULL == pScene )
return; return;
@ -285,7 +218,7 @@ void Q3BSPFileImporter::CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, a
CreateNodes( pModel, pScene, pScene->mRootNode ); CreateNodes( pModel, pScene, pScene->mRootNode );
// Create the assigned materials // Create the assigned materials
createMaterials( pModel, pScene, pArchive ); createMaterials( pModel, pScene, pIOHandler );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -473,7 +406,7 @@ void Q3BSPFileImporter::createTriangleTopology( const Q3BSP::Q3BSPModel *pModel,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Creates all referenced materials. // Creates all referenced materials.
void Q3BSPFileImporter::createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, void Q3BSPFileImporter::createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
Q3BSPZipArchive *pArchive ) IOSystem *pIOHandler )
{ {
if ( m_MaterialLookupMap.empty() ) if ( m_MaterialLookupMap.empty() )
{ {
@ -509,7 +442,7 @@ void Q3BSPFileImporter::createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScen
tmp += ".jpg"; tmp += ".jpg";
normalizePathName( tmp, texName ); normalizePathName( tmp, texName );
if ( !importTextureFromArchive( pModel, pArchive, pScene, pMatHelper, textureId ) ) if ( !importTextureFromArchive( pModel, pIOHandler, pScene, pMatHelper, textureId ) )
{ {
} }
} }
@ -634,14 +567,14 @@ aiFace *Q3BSPFileImporter::getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx )
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports a texture file. // Imports a texture file.
bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel, bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel,
Q3BSP::Q3BSPZipArchive *pArchive, aiScene* /*pScene*/, IOSystem *pIOHandler, aiScene* /*pScene*/,
aiMaterial *pMatHelper, int textureId ) aiMaterial *pMatHelper, int textureId )
{ {
std::vector<std::string> supportedExtensions; std::vector<std::string> supportedExtensions;
supportedExtensions.push_back( ".jpg" ); supportedExtensions.push_back( ".jpg" );
supportedExtensions.push_back( ".png" ); supportedExtensions.push_back( ".png" );
supportedExtensions.push_back( ".tga" ); supportedExtensions.push_back( ".tga" );
if ( NULL == pArchive || NULL == pArchive || NULL == pMatHelper ) if ( NULL == pIOHandler || NULL == pMatHelper )
{ {
return false; return false;
} }
@ -657,9 +590,9 @@ bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pMode
return false; return false;
std::string textureName, ext; std::string textureName, ext;
if ( expandFile( pArchive, pTexture->strName, supportedExtensions, textureName, ext ) ) if ( expandFile( pIOHandler, pTexture->strName, supportedExtensions, textureName, ext ) )
{ {
IOStream *pTextureStream = pArchive->Open( textureName.c_str() ); IOStream *pTextureStream = pIOHandler->Open( textureName.c_str() );
if ( NULL != pTextureStream ) if ( NULL != pTextureStream )
{ {
size_t texSize = pTextureStream->FileSize(); size_t texSize = pTextureStream->FileSize();
@ -681,7 +614,7 @@ bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pMode
name.data[ 0 ] = '*'; name.data[ 0 ] = '*';
name.length = 1 + ASSIMP_itoa10( name.data + 1, MAXLEN-1, mTextures.size() ); name.length = 1 + ASSIMP_itoa10( name.data + 1, MAXLEN-1, mTextures.size() );
pArchive->Close( pTextureStream ); pIOHandler->Close( pTextureStream );
pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) ); pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
mTextures.push_back( pTexture ); mTextures.push_back( pTexture );
@ -750,11 +683,11 @@ bool Q3BSPFileImporter::importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Will search for a supported extension. // Will search for a supported extension.
bool Q3BSPFileImporter::expandFile( Q3BSP::Q3BSPZipArchive *pArchive, const std::string &rFilename, bool Q3BSPFileImporter::expandFile( IOSystem *pIOHandler, const std::string &rFilename,
const std::vector<std::string> &rExtList, std::string &rFile, const std::vector<std::string> &rExtList, std::string &rFile,
std::string &rExt ) std::string &rExt )
{ {
ai_assert( NULL != pArchive ); ai_assert( NULL != pIOHandler );
ai_assert( !rFilename.empty() ); ai_assert( !rFilename.empty() );
if ( rExtList.empty() ) if ( rExtList.empty() )
@ -768,7 +701,7 @@ bool Q3BSPFileImporter::expandFile( Q3BSP::Q3BSPZipArchive *pArchive, const std
for ( std::vector<std::string>::const_iterator it = rExtList.begin(); it != rExtList.end(); ++it ) for ( std::vector<std::string>::const_iterator it = rExtList.begin(); it != rExtList.end(); ++it )
{ {
const std::string textureName = rFilename + *it; const std::string textureName = rFilename + *it;
if ( pArchive->Exists( textureName.c_str() ) ) if ( pIOHandler->Exists( textureName.c_str() ) )
{ {
rExt = *it; rExt = *it;
rFile = textureName; rFile = textureName;

View File

@ -49,7 +49,6 @@ namespace Assimp
namespace Q3BSP namespace Q3BSP
{ {
class Q3BSPZipArchive;
struct Q3BSPModel; struct Q3BSPModel;
struct sQ3BSPFace; struct sQ3BSPFace;
@ -81,24 +80,23 @@ private:
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const;
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 ); void CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, IOSystem *pIOHandler );
void CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, Q3BSP::Q3BSPZipArchive *pArchive );
void CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiNode *pParent ); void CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiNode *pParent );
aiNode *CreateTopology( const Q3BSP::Q3BSPModel *pModel, unsigned int materialIdx, aiNode *CreateTopology( const Q3BSP::Q3BSPModel *pModel, unsigned int materialIdx,
std::vector<Q3BSP::sQ3BSPFace*> &rArray, aiMesh* pMesh ); std::vector<Q3BSP::sQ3BSPFace*> &rArray, aiMesh* pMesh );
void createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, Q3BSP::sQ3BSPFace *pQ3BSPFace, aiMesh* pMesh, unsigned int &rFaceIdx, void createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, Q3BSP::sQ3BSPFace *pQ3BSPFace, aiMesh* pMesh, unsigned int &rFaceIdx,
unsigned int &rVertIdx ); unsigned int &rVertIdx );
void createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, Q3BSP::Q3BSPZipArchive *pArchive ); void createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, IOSystem *pIOHandler );
size_t countData( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const; size_t countData( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
size_t countFaces( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const; size_t countFaces( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
size_t countTriangles( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const; size_t countTriangles( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
void createMaterialMap( const Q3BSP::Q3BSPModel *pModel); void createMaterialMap( const Q3BSP::Q3BSPModel *pModel);
aiFace *getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx ); aiFace *getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx );
bool importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel, Q3BSP::Q3BSPZipArchive *pArchive, aiScene* pScene, bool importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel, IOSystem *pIOHandler, aiScene* pScene,
aiMaterial *pMatHelper, int textureId ); aiMaterial *pMatHelper, int textureId );
bool importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiMaterial *pMatHelper, int lightmapId ); bool importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiMaterial *pMatHelper, int lightmapId );
bool importEntities( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene ); bool importEntities( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene );
bool expandFile( Q3BSP::Q3BSPZipArchive *pArchive, const std::string &rFilename, const std::vector<std::string> &rExtList, bool expandFile( IOSystem *pIOHandler, const std::string &rFilename, const std::vector<std::string> &rExtList,
std::string &rFile, std::string &rExt ); std::string &rFile, std::string &rExt );
private: private:

View File

@ -44,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Q3BSPFileParser.h" #include "Q3BSPFileParser.h"
#include "DefaultIOSystem.h" #include "DefaultIOSystem.h"
#include "Q3BSPFileData.h" #include "Q3BSPFileData.h"
#include "Q3BSPZipArchive.h"
#include <vector> #include <vector>
namespace Assimp namespace Assimp
@ -53,13 +52,13 @@ namespace Assimp
using namespace Q3BSP; using namespace Q3BSP;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Q3BSPFileParser::Q3BSPFileParser( const std::string &rMapName, Q3BSPZipArchive *pZipArchive ) : Q3BSPFileParser::Q3BSPFileParser( const std::string &rMapName, IOSystem *pIOHandler ) :
m_sOffset( 0 ), m_sOffset( 0 ),
m_Data(), m_Data(),
m_pModel( NULL ), m_pModel( NULL ),
m_pZipArchive( pZipArchive ) m_pIOHandler( pIOHandler )
{ {
ai_assert( NULL != m_pZipArchive ); ai_assert( NULL != m_pIOHandler );
ai_assert( !rMapName.empty() ); ai_assert( !rMapName.empty() );
if ( !readData( rMapName ) ) if ( !readData( rMapName ) )
@ -90,10 +89,10 @@ 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_pIOHandler->Exists( rMapName.c_str() ) )
return false; return false;
IOStream *pMapFile = m_pZipArchive->Open( rMapName.c_str() ); IOStream *pMapFile = m_pIOHandler->Open( rMapName.c_str() );
if ( NULL == pMapFile ) if ( NULL == pMapFile )
return false; return false;
@ -106,7 +105,7 @@ bool Q3BSPFileParser::readData( const std::string &rMapName )
m_Data.clear(); m_Data.clear();
return false; return false;
} }
m_pZipArchive->Close( pMapFile ); m_pIOHandler->Close( pMapFile );
return true; return true;
} }

View File

@ -49,7 +49,6 @@ namespace Assimp
namespace Q3BSP namespace Q3BSP
{ {
class Q3BSPZipArchive;
struct Q3BSPModel; struct Q3BSPModel;
class ZipFile; class ZipFile;
@ -60,7 +59,7 @@ class ZipFile;
class Q3BSPFileParser class Q3BSPFileParser
{ {
public: public:
Q3BSPFileParser( const std::string &rMapName, Q3BSP::Q3BSPZipArchive *pZipArchive ); Q3BSPFileParser( const std::string &rMapName, IOSystem *pIOHandler );
~Q3BSPFileParser(); ~Q3BSPFileParser();
Q3BSP::Q3BSPModel *getModel() const; Q3BSP::Q3BSPModel *getModel() const;
@ -81,7 +80,7 @@ private:
size_t m_sOffset; size_t m_sOffset;
std::vector<char> m_Data; std::vector<char> m_Data;
Q3BSP::Q3BSPModel *m_pModel; Q3BSP::Q3BSPModel *m_pModel;
Q3BSP::Q3BSPZipArchive *m_pZipArchive; IOSystem *m_pIOHandler;
}; };
} // Namespace Assimp } // Namespace Assimp