nuclear@0: /* nuclear@0: Open Asset Import Library (assimp) nuclear@0: ---------------------------------------------------------------------- nuclear@0: nuclear@0: Copyright (c) 2006-2008, assimp team nuclear@0: All rights reserved. nuclear@0: nuclear@0: Redistribution and use of this software in source and binary forms, nuclear@0: with or without modification, are permitted provided that the nuclear@0: following conditions are met: nuclear@0: nuclear@0: * Redistributions of source code must retain the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer. nuclear@0: nuclear@0: * Redistributions in binary form must reproduce the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer in the documentation and/or other nuclear@0: materials provided with the distribution. nuclear@0: nuclear@0: * Neither the name of the assimp team, nor the names of its nuclear@0: contributors may be used to endorse or promote products nuclear@0: derived from this software without specific prior nuclear@0: written permission of the assimp team. nuclear@0: nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nuclear@0: nuclear@0: ---------------------------------------------------------------------- nuclear@0: */ nuclear@0: #include "AssimpPCH.h" nuclear@0: nuclear@0: #ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER nuclear@0: nuclear@0: #include "Q3BSPFileParser.h" nuclear@0: #include "DefaultIOSystem.h" nuclear@0: #include "Q3BSPFileData.h" nuclear@0: #include "Q3BSPZipArchive.h" nuclear@0: #include nuclear@0: nuclear@0: namespace Assimp nuclear@0: { nuclear@0: nuclear@0: using namespace Q3BSP; nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: Q3BSPFileParser::Q3BSPFileParser( const std::string &rMapName, Q3BSPZipArchive *pZipArchive ) : nuclear@0: m_sOffset( 0 ), nuclear@0: m_Data(), nuclear@0: m_pModel( NULL ), nuclear@0: m_pZipArchive( pZipArchive ) nuclear@0: { nuclear@0: ai_assert( NULL != m_pZipArchive ); nuclear@0: ai_assert( !rMapName.empty() ); nuclear@0: nuclear@0: if ( !readData( rMapName ) ) nuclear@0: return; nuclear@0: nuclear@0: m_pModel = new Q3BSPModel; nuclear@0: m_pModel->m_ModelName = rMapName; nuclear@0: if ( !parseFile() ) nuclear@0: { nuclear@0: delete m_pModel; nuclear@0: m_pModel = NULL; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: Q3BSPFileParser::~Q3BSPFileParser() nuclear@0: { nuclear@0: delete m_pModel; nuclear@0: m_pModel = NULL; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: Q3BSP::Q3BSPModel *Q3BSPFileParser::getModel() const nuclear@0: { nuclear@0: return m_pModel; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: bool Q3BSPFileParser::readData( const std::string &rMapName ) nuclear@0: { nuclear@0: if ( !m_pZipArchive->Exists( rMapName.c_str() ) ) nuclear@0: return false; nuclear@0: nuclear@0: IOStream *pMapFile = m_pZipArchive->Open( rMapName.c_str() ); nuclear@0: if ( NULL == pMapFile ) nuclear@0: return false; nuclear@0: nuclear@0: const size_t size = pMapFile->FileSize(); nuclear@0: m_Data.resize( size ); nuclear@0: nuclear@0: const size_t readSize = pMapFile->Read( &m_Data[0], sizeof( char ), size ); nuclear@0: if ( readSize != size ) nuclear@0: { nuclear@0: m_Data.clear(); nuclear@0: return false; nuclear@0: } nuclear@0: m_pZipArchive->Close( pMapFile ); nuclear@0: nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: bool Q3BSPFileParser::parseFile() nuclear@0: { nuclear@0: if ( m_Data.empty() ) nuclear@0: { nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: if ( !validateFormat() ) nuclear@0: { nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: // Imports the dictionary of the level nuclear@0: getLumps(); nuclear@0: nuclear@0: // Conunt data and prepare model data nuclear@0: countLumps(); nuclear@0: nuclear@0: // Read in Vertices nuclear@0: getVertices(); nuclear@0: nuclear@0: // Read in Indices nuclear@0: getIndices(); nuclear@0: nuclear@0: // Read Faces nuclear@0: getFaces(); nuclear@0: nuclear@0: // Read Textures nuclear@0: getTextures(); nuclear@0: nuclear@0: // Read Lightmaps nuclear@0: getLightMaps(); nuclear@0: nuclear@0: // Load the entities nuclear@0: getEntities(); nuclear@0: nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: bool Q3BSPFileParser::validateFormat() nuclear@0: { nuclear@0: sQ3BSPHeader *pHeader = (sQ3BSPHeader*) &m_Data[ 0 ]; nuclear@0: m_sOffset += sizeof( sQ3BSPHeader ); nuclear@0: nuclear@0: // Version and identify string validation nuclear@0: if (pHeader->strID[ 0 ] != 'I' || pHeader->strID[ 1 ] != 'B' || pHeader->strID[ 2 ] != 'S' nuclear@0: || pHeader->strID[ 3 ] != 'P') nuclear@0: { nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: void Q3BSPFileParser::getLumps() nuclear@0: { nuclear@0: size_t Offset = m_sOffset; nuclear@0: m_pModel->m_Lumps.resize( kMaxLumps ); nuclear@0: for ( size_t idx=0; idx < kMaxLumps; idx++ ) nuclear@0: { nuclear@0: sQ3BSPLump *pLump = new sQ3BSPLump; nuclear@0: memcpy( pLump, &m_Data[ Offset ], sizeof( sQ3BSPLump ) ); nuclear@0: Offset += sizeof( sQ3BSPLump ); nuclear@0: m_pModel->m_Lumps[ idx ] = pLump; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: void Q3BSPFileParser::countLumps() nuclear@0: { nuclear@0: m_pModel->m_Vertices.resize( m_pModel->m_Lumps[ kVertices ]->iSize / sizeof( sQ3BSPVertex ) ); nuclear@0: m_pModel->m_Indices.resize( m_pModel->m_Lumps[ kMeshVerts ]->iSize / sizeof( int ) ); nuclear@0: m_pModel->m_Faces.resize( m_pModel->m_Lumps[ kFaces ]->iSize / sizeof( sQ3BSPFace ) ); nuclear@0: m_pModel->m_Textures.resize( m_pModel->m_Lumps[ kTextures ]->iSize / sizeof( sQ3BSPTexture ) ); nuclear@0: m_pModel->m_Lightmaps.resize( m_pModel->m_Lumps[ kLightmaps ]->iSize / sizeof( sQ3BSPLightmap ) ); nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: void Q3BSPFileParser::getVertices() nuclear@0: { nuclear@0: size_t Offset = m_pModel->m_Lumps[ kVertices ]->iOffset; nuclear@0: for ( size_t idx = 0; idx < m_pModel->m_Vertices.size(); idx++ ) nuclear@0: { nuclear@0: sQ3BSPVertex *pVertex = new sQ3BSPVertex; nuclear@0: memcpy( pVertex, &m_Data[ Offset ], sizeof( sQ3BSPVertex ) ); nuclear@0: Offset += sizeof( sQ3BSPVertex ); nuclear@0: m_pModel->m_Vertices[ idx ] = pVertex; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: void Q3BSPFileParser::getIndices() nuclear@0: { nuclear@0: ai_assert( NULL != m_pModel ); nuclear@0: nuclear@0: sQ3BSPLump *lump = m_pModel->m_Lumps[ kMeshVerts ]; nuclear@0: size_t Offset = (size_t) lump->iOffset; nuclear@0: const size_t nIndices = lump->iSize / sizeof( int ); nuclear@0: m_pModel->m_Indices.resize( nIndices ); nuclear@0: memcpy( &m_pModel->m_Indices[ 0 ], &m_Data[ Offset ], lump->iSize ); nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: void Q3BSPFileParser::getFaces() nuclear@0: { nuclear@0: ai_assert( NULL != m_pModel ); nuclear@0: nuclear@0: size_t Offset = m_pModel->m_Lumps[ kFaces ]->iOffset; nuclear@0: for ( size_t idx = 0; idx < m_pModel->m_Faces.size(); idx++ ) nuclear@0: { nuclear@0: sQ3BSPFace *pFace = new sQ3BSPFace; nuclear@0: memcpy( pFace, &m_Data[ Offset ], sizeof( sQ3BSPFace ) ); nuclear@0: m_pModel->m_Faces[ idx ] = pFace; nuclear@0: Offset += sizeof( sQ3BSPFace ); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: void Q3BSPFileParser::getTextures() nuclear@0: { nuclear@0: ai_assert( NULL != m_pModel ); nuclear@0: nuclear@0: size_t Offset = m_pModel->m_Lumps[ kTextures ]->iOffset; nuclear@0: for ( size_t idx=0; idx < m_pModel->m_Textures.size(); idx++ ) nuclear@0: { nuclear@0: sQ3BSPTexture *pTexture = new sQ3BSPTexture; nuclear@0: memcpy( pTexture, &m_Data[ Offset ], sizeof(sQ3BSPTexture) ); nuclear@0: m_pModel->m_Textures[ idx ] = pTexture; nuclear@0: Offset += sizeof(sQ3BSPTexture); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: void Q3BSPFileParser::getLightMaps() nuclear@0: { nuclear@0: ai_assert( NULL != m_pModel ); nuclear@0: nuclear@0: size_t Offset = m_pModel->m_Lumps[kLightmaps]->iOffset; nuclear@0: for ( size_t idx=0; idx < m_pModel->m_Lightmaps.size(); idx++ ) nuclear@0: { nuclear@0: sQ3BSPLightmap *pLightmap = new sQ3BSPLightmap; nuclear@0: memcpy( pLightmap, &m_Data[ Offset ], sizeof( sQ3BSPLightmap ) ); nuclear@0: Offset += sizeof( sQ3BSPLightmap ); nuclear@0: m_pModel->m_Lightmaps[ idx ] = pLightmap; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: void Q3BSPFileParser::getEntities() nuclear@0: { nuclear@0: int size = m_pModel->m_Lumps[ kEntities ]->iSize; nuclear@0: m_pModel->m_EntityData.resize( size ); nuclear@0: if ( size > 0 ) nuclear@0: { nuclear@0: size_t Offset = m_pModel->m_Lumps[ kEntities ]->iOffset; nuclear@0: memcpy( &m_pModel->m_EntityData[ 0 ], &m_Data[ Offset ], sizeof( char ) * size ); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: nuclear@0: } // Namespace Assimp nuclear@0: nuclear@0: #endif // ASSIMP_BUILD_NO_Q3BSP_IMPORTER