diff options
Diffstat (limited to 'NvCloth/samples/external/assimp-4.1.0/code/Q3BSPFileImporter.cpp')
| -rw-r--r-- | NvCloth/samples/external/assimp-4.1.0/code/Q3BSPFileImporter.cpp | 771 |
1 files changed, 771 insertions, 0 deletions
diff --git a/NvCloth/samples/external/assimp-4.1.0/code/Q3BSPFileImporter.cpp b/NvCloth/samples/external/assimp-4.1.0/code/Q3BSPFileImporter.cpp new file mode 100644 index 0000000..9d6d8e8 --- /dev/null +++ b/NvCloth/samples/external/assimp-4.1.0/code/Q3BSPFileImporter.cpp @@ -0,0 +1,771 @@ +/* +Open Asset Import Library (assimp) +--------------------------------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +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. + +--------------------------------------------------------------------------------------------------- +*/ + +#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER + +#include "Q3BSPFileImporter.h" +#include "Q3BSPZipArchive.h" +#include "Q3BSPFileParser.h" +#include "Q3BSPFileData.h" + +#ifdef ASSIMP_BUILD_NO_OWN_ZLIB +# include <zlib.h> +#else +# include "../contrib/zlib/zlib.h" +#endif + +#include <assimp/types.h> +#include <assimp/mesh.h> +#include <assimp/scene.h> +#include <assimp/ai_assert.h> +#include <assimp/DefaultIOSystem.h> +#include <assimp/importerdesc.h> +#include <vector> +#include <sstream> +#include "StringComparison.h" + +static const aiImporterDesc desc = { + "Quake III BSP Importer", + "", + "", + "", + aiImporterFlags_SupportBinaryFlavour, + 0, + 0, + 0, + 0, + "pk3" +}; + +namespace Assimp { + +using namespace Q3BSP; + +// ------------------------------------------------------------------------------------------------ +// Local function to create a material key name. +static void createKey( int id1, int id2, std::string &rKey ) +{ + std::ostringstream str; + str << id1 << "." << id2; + rKey = str.str(); +} + +// ------------------------------------------------------------------------------------------------ +// Local function to extract the texture ids from a material key-name. +static void extractIds( const std::string &rKey, int &rId1, int &rId2 ) +{ + rId1 = -1; + rId2 = -1; + if ( rKey.empty() ) + return; + + std::string::size_type pos = rKey.find( "." ); + if ( std::string::npos == pos ) + return; + + std::string tmp1 = rKey.substr( 0, pos ); + std::string tmp2 = rKey.substr( pos + 1, rKey.size() - pos - 1 ); + rId1 = atoi( tmp1.c_str() ); + rId2 = atoi( tmp2.c_str() ); +} + +// ------------------------------------------------------------------------------------------------ +// Local helper function to normalize filenames. +static void normalizePathName( const std::string &rPath, std::string &rNormalizedPath ) +{ + rNormalizedPath = ""; + if ( rPath.empty() ) + return; + +#ifdef _WIN32 + std::string sep = "\\"; +#else + std::string sep = "/"; +#endif + + static const unsigned int numDelimiters = 2; + const char delimiters[ numDelimiters ] = { '/', '\\' }; + rNormalizedPath = rPath; + for (const char delimiter : delimiters) + { + for ( size_t j=0; j<rNormalizedPath.size(); j++ ) + { + if ( rNormalizedPath[j] == delimiter ) + { + rNormalizedPath[ j ] = sep[ 0 ]; + } + } + } +} + +// ------------------------------------------------------------------------------------------------ +// Constructor. +Q3BSPFileImporter::Q3BSPFileImporter() : + m_pCurrentMesh( NULL ), + m_pCurrentFace( NULL ), + m_MaterialLookupMap(), + mTextures() +{ + // empty +} + +// ------------------------------------------------------------------------------------------------ +// Destructor. +Q3BSPFileImporter::~Q3BSPFileImporter() { + m_pCurrentMesh = NULL; + m_pCurrentFace = NULL; + + // Clear face-to-material map + for ( FaceMap::iterator it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it ) { + const std::string &matName = it->first; + if ( !matName.empty() ) { + delete it->second; + } + } + m_MaterialLookupMap.clear(); +} + +// ------------------------------------------------------------------------------------------------ +// Returns true, if the loader can read this. +bool Q3BSPFileImporter::CanRead( const std::string& rFile, IOSystem* /*pIOHandler*/, bool checkSig ) const +{ + if(!checkSig) { + return SimpleExtensionCheck( rFile, "pk3", "bsp" ); + } + // TODO perhaps add keyword based detection + return false; +} + +// ------------------------------------------------------------------------------------------------ +// Adds extensions. +const aiImporterDesc* Q3BSPFileImporter::GetInfo () const +{ + return &desc; +} + +// ------------------------------------------------------------------------------------------------ +// Import method. +void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene* pScene, IOSystem* pIOHandler) +{ + Q3BSPZipArchive Archive( pIOHandler, rFile ); + 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(); + if ( NULL != pBSPModel ) + { + CreateDataFromImport( pBSPModel, pScene, &Archive ); + } +} + +// ------------------------------------------------------------------------------------------------ +// 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. +void Q3BSPFileImporter::CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, + Q3BSPZipArchive *pArchive ) +{ + if ( NULL == pModel || NULL == pScene ) + return; + + pScene->mRootNode = new aiNode; + if ( !pModel->m_ModelName.empty() ) + { + pScene->mRootNode->mName.Set( pModel->m_ModelName ); + } + + // Create the face to material relation map + createMaterialMap( pModel ); + + // Create all nodes + CreateNodes( pModel, pScene, pScene->mRootNode ); + + // Create the assigned materials + createMaterials( pModel, pScene, pArchive ); +} + +// ------------------------------------------------------------------------------------------------ +// Creates all assimp nodes. +void Q3BSPFileImporter::CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, + aiNode *pParent ) +{ + ai_assert( NULL != pModel ); + if ( NULL == pModel ) + { + return; + } + + unsigned int matIdx = 0; + std::vector<aiMesh*> MeshArray; + std::vector<aiNode*> NodeArray; + for ( FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.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, matIdx, *pArray, pMesh ); + if ( NULL != pNode ) + { + NodeArray.push_back( pNode ); + MeshArray.push_back( pMesh ); + } + else + { + delete pMesh; + } + } + matIdx++; + } + + pScene->mNumMeshes = static_cast<unsigned int>( MeshArray.size() ); + if ( pScene->mNumMeshes > 0 ) + { + pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ]; + for ( size_t i = 0; i < MeshArray.size(); i++ ) + { + aiMesh *pMesh = MeshArray[ i ]; + if ( NULL != pMesh ) + { + pScene->mMeshes[ i ] = pMesh; + } + } + } + + pParent->mNumChildren = static_cast<unsigned int>(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 ] = static_cast<unsigned int>(i); + } +} + +// ------------------------------------------------------------------------------------------------ +// Creates the topology. +aiNode *Q3BSPFileImporter::CreateTopology( const Q3BSP::Q3BSPModel *pModel, + unsigned int materialIdx, + 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; + } + + size_t numTriangles = countTriangles( rArray ); + pMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + + pMesh->mFaces = new aiFace[ numTriangles ]; + pMesh->mNumFaces = static_cast<unsigned int>(numTriangles); + + pMesh->mNumVertices = static_cast<unsigned int>(numVerts); + pMesh->mVertices = new aiVector3D[ numVerts ]; + pMesh->mNormals = new aiVector3D[ numVerts ]; + pMesh->mTextureCoords[ 0 ] = new aiVector3D[ numVerts ]; + pMesh->mTextureCoords[ 1 ] = new aiVector3D[ numVerts ]; + pMesh->mMaterialIndex = materialIdx; + + unsigned int faceIdx = 0; + unsigned int vertIdx = 0; + pMesh->mNumUVComponents[ 0 ] = 2; + pMesh->mNumUVComponents[ 1 ] = 2; + for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); ++it ) + { + Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; + ai_assert( NULL != pQ3BSPFace ); + if ( NULL == pQ3BSPFace ) + { + continue; + } + + if ( pQ3BSPFace->iNumOfFaceVerts > 0 ) + { + if ( pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh ) + { + createTriangleTopology( pModel, pQ3BSPFace, pMesh, faceIdx, vertIdx ); + } + } + } + + aiNode *pNode = new aiNode; + pNode->mNumMeshes = 1; + pNode->mMeshes = new unsigned int[ 1 ]; + + return pNode; +} + +// ------------------------------------------------------------------------------------------------ +// Creates the triangle topology from a face array. +void Q3BSPFileImporter::createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, + Q3BSP::sQ3BSPFace *pQ3BSPFace, + aiMesh* pMesh, + unsigned int &rFaceIdx, + unsigned int &rVertIdx ) +{ + ai_assert( rFaceIdx < pMesh->mNumFaces ); + + m_pCurrentFace = getNextFace( pMesh, rFaceIdx ); + ai_assert( NULL != m_pCurrentFace ); + if ( NULL == m_pCurrentFace ) + { + return; + } + + m_pCurrentFace->mNumIndices = 3; + m_pCurrentFace->mIndices = new unsigned int[ m_pCurrentFace->mNumIndices ]; + + size_t idx = 0; + for ( size_t i = 0; i < (size_t) pQ3BSPFace->iNumOfFaceVerts; i++ ) + { + const size_t index = pQ3BSPFace->iVertexIndex + pModel->m_Indices[ pQ3BSPFace->iFaceVertexIndex + i ]; + ai_assert( index < pModel->m_Vertices.size() ); + if ( index >= pModel->m_Vertices.size() ) + { + continue; + } + + sQ3BSPVertex *pVertex = pModel->m_Vertices[ index ]; + ai_assert( NULL != pVertex ); + if ( NULL == pVertex ) + { + continue; + } + + pMesh->mVertices[ rVertIdx ].Set( pVertex->vPosition.x, pVertex->vPosition.y, pVertex->vPosition.z ); + pMesh->mNormals[ rVertIdx ].Set( pVertex->vNormal.x, pVertex->vNormal.y, pVertex->vNormal.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 ); + + m_pCurrentFace->mIndices[ idx ] = rVertIdx; + rVertIdx++; + + idx++; + if ( idx > 2 ) + { + idx = 0; + m_pCurrentFace = getNextFace( pMesh, rFaceIdx ); + if ( NULL != m_pCurrentFace ) + { + m_pCurrentFace->mNumIndices = 3; + m_pCurrentFace->mIndices = new unsigned int[ 3 ]; + } + } + } + rFaceIdx--; +} + +// ------------------------------------------------------------------------------------------------ +// Creates all referenced materials. +void Q3BSPFileImporter::createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, + Q3BSPZipArchive *pArchive ) +{ + if ( m_MaterialLookupMap.empty() ) + { + return; + } + + pScene->mMaterials = new aiMaterial*[ m_MaterialLookupMap.size() ]; + aiString aiMatName; + int textureId( -1 ), lightmapId( -1 ); + for ( FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); + ++it ) + { + const std::string matName = (*it).first; + if ( matName.empty() ) + { + continue; + } + + aiMatName.Set( matName ); + aiMaterial *pMatHelper = new aiMaterial; + pMatHelper->AddProperty( &aiMatName, AI_MATKEY_NAME ); + + extractIds( matName, textureId, lightmapId ); + + // Adding the texture + if ( -1 != textureId ) + { + sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ]; + if ( NULL != pTexture ) + { + std::string tmp( "*" ), texName( "" ); + tmp += pTexture->strName; + tmp += ".jpg"; + normalizePathName( tmp, texName ); + + if ( !importTextureFromArchive( pModel, pArchive, pScene, pMatHelper, textureId ) ) + { + } + } + + } + if ( -1 != lightmapId ) + { + importLightmap( pModel, pScene, pMatHelper, lightmapId ); + } + pScene->mMaterials[ pScene->mNumMaterials ] = pMatHelper; + pScene->mNumMaterials++; + } + pScene->mNumTextures = static_cast<unsigned int>(mTextures.size()); + pScene->mTextures = new aiTexture*[ pScene->mNumTextures ]; + std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures ); +} + +// ------------------------------------------------------------------------------------------------ +// Counts the number of referenced vertices. +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 == Polygon || pQ3BSPFace->iType == TriangleMesh ) + { + Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; + ai_assert( NULL != pQ3BSPFace ); + numVerts += pQ3BSPFace->iNumOfFaceVerts; + } + } + + return numVerts; +} + +// ------------------------------------------------------------------------------------------------ +// Counts the faces with vertices. +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->iNumOfFaceVerts > 0 ) + { + numFaces++; + } + } + + return numFaces; +} + +// ------------------------------------------------------------------------------------------------ +// Counts the number of triangles in a Q3-face-array. +size_t Q3BSPFileImporter::countTriangles( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const +{ + size_t numTriangles = 0; + for ( std::vector<Q3BSP::sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); + ++it ) + { + const Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; + if ( NULL != pQ3BSPFace ) + { + numTriangles += pQ3BSPFace->iNumOfFaceVerts / 3; + } + } + + return numTriangles; +} + +// ------------------------------------------------------------------------------------------------ +// Creates the faces-to-material map. +void Q3BSPFileImporter::createMaterialMap( const Q3BSP::Q3BSPModel *pModel ) +{ + std::string key( "" ); + std::vector<sQ3BSPFace*> *pCurFaceArray = NULL; + for ( size_t idx = 0; idx < pModel->m_Faces.size(); idx++ ) + { + Q3BSP::sQ3BSPFace *pQ3BSPFace = pModel->m_Faces[ idx ]; + const int texId = pQ3BSPFace->iTextureID; + const int lightMapId = pQ3BSPFace->iLightmapID; + createKey( texId, lightMapId, key ); + FaceMapIt it = m_MaterialLookupMap.find( key ); + if ( m_MaterialLookupMap.end() == it ) + { + pCurFaceArray = new std::vector<Q3BSP::sQ3BSPFace*>; + m_MaterialLookupMap[ key ] = pCurFaceArray; + } + else + { + pCurFaceArray = (*it).second; + } + ai_assert( NULL != pCurFaceArray ); + if ( NULL != pCurFaceArray ) + { + pCurFaceArray->push_back( pQ3BSPFace ); + } + } +} + +// ------------------------------------------------------------------------------------------------ +// Returns the next face. +aiFace *Q3BSPFileImporter::getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx ) +{ + aiFace *pFace( NULL ); + if ( rFaceIdx < pMesh->mNumFaces ) { + pFace = &pMesh->mFaces[ rFaceIdx ]; + rFaceIdx++; + } + + return pFace; +} + +// ------------------------------------------------------------------------------------------------ +// Imports a texture file. +bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel, + Q3BSP::Q3BSPZipArchive *pArchive, aiScene*, + aiMaterial *pMatHelper, int textureId ) { + if ( NULL == pArchive || NULL == pMatHelper ) { + return false; + } + + if ( textureId < 0 || textureId >= static_cast<int>( pModel->m_Textures.size() ) ) { + return false; + } + + bool res = true; + sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ]; + if ( !pTexture ) { + return false; + } + + std::vector<std::string> supportedExtensions; + supportedExtensions.push_back( ".jpg" ); + supportedExtensions.push_back( ".png" ); + supportedExtensions.push_back( ".tga" ); + std::string textureName, ext; + if ( expandFile( pArchive, pTexture->strName, supportedExtensions, textureName, ext ) ) { + IOStream *pTextureStream = pArchive->Open( textureName.c_str() ); + if ( pTextureStream ) { + size_t texSize = pTextureStream->FileSize(); + aiTexture *pTexture = new aiTexture; + pTexture->mHeight = 0; + pTexture->mWidth = static_cast<unsigned int>(texSize); + unsigned char *pData = new unsigned char[ pTexture->mWidth ]; + size_t readSize = pTextureStream->Read( pData, sizeof( unsigned char ), pTexture->mWidth ); + (void)readSize; + ai_assert( readSize == pTexture->mWidth ); + pTexture->pcData = reinterpret_cast<aiTexel*>( pData ); + pTexture->achFormatHint[ 0 ] = ext[ 1 ]; + pTexture->achFormatHint[ 1 ] = ext[ 2 ]; + pTexture->achFormatHint[ 2 ] = ext[ 3 ]; + pTexture->achFormatHint[ 3 ] = '\0'; + res = true; + + aiString name; + name.data[ 0 ] = '*'; + name.length = 1 + ASSIMP_itoa10( name.data + 1, static_cast<unsigned int>(MAXLEN-1), static_cast<int32_t>(mTextures.size()) ); + + pArchive->Close( pTextureStream ); + + pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) ); + mTextures.push_back( pTexture ); + } else { + // If it doesn't exist in the archive, it is probably just a reference to an external file. + // We'll leave it up to the user to figure out which extension the file has. + aiString name; + strncpy( name.data, pTexture->strName, sizeof name.data ); + name.length = strlen( name.data ); + pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) ); + } + } + + return res; +} + +// ------------------------------------------------------------------------------------------------ +// Imports a light map file. +bool Q3BSPFileImporter::importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, + aiMaterial *pMatHelper, int lightmapId ) +{ + if ( NULL == pModel || NULL == pScene || NULL == pMatHelper ) + { + return false; + } + + if ( lightmapId < 0 || lightmapId >= static_cast<int>( pModel->m_Lightmaps.size() ) ) + { + return false; + } + + sQ3BSPLightmap *pLightMap = pModel->m_Lightmaps[ lightmapId ]; + if ( NULL == pLightMap ) + { + return false; + } + + aiTexture *pTexture = new aiTexture; + + pTexture->mWidth = CE_BSP_LIGHTMAPWIDTH; + pTexture->mHeight = CE_BSP_LIGHTMAPHEIGHT; + pTexture->pcData = new aiTexel[CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT]; + + ::memcpy( pTexture->pcData, pLightMap->bLMapData, pTexture->mWidth ); + size_t p = 0; + for ( size_t i = 0; i < CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT; ++i ) + { + pTexture->pcData[ i ].r = pLightMap->bLMapData[ p++ ]; + pTexture->pcData[ i ].g = pLightMap->bLMapData[ p++ ]; + pTexture->pcData[ i ].b = pLightMap->bLMapData[ p++ ]; + pTexture->pcData[ i ].a = 0xFF; + } + + aiString name; + name.data[ 0 ] = '*'; + name.length = 1 + ASSIMP_itoa10( name.data + 1, static_cast<unsigned int>(MAXLEN-1), static_cast<int32_t>(mTextures.size()) ); + + pMatHelper->AddProperty( &name,AI_MATKEY_TEXTURE_LIGHTMAP( 1 ) ); + mTextures.push_back( pTexture ); + + return true; +} + + +// ------------------------------------------------------------------------------------------------ +// Will search for a supported extension. +bool Q3BSPFileImporter::expandFile( Q3BSP::Q3BSPZipArchive *pArchive, const std::string &rFilename, + const std::vector<std::string> &rExtList, std::string &rFile, + std::string &rExt ) +{ + ai_assert( NULL != pArchive ); + ai_assert( !rFilename.empty() ); + + if ( rExtList.empty() ) + { + rFile = rFilename; + rExt = ""; + return true; + } + + bool found = false; + for ( std::vector<std::string>::const_iterator it = rExtList.begin(); it != rExtList.end(); ++it ) + { + const std::string textureName = rFilename + *it; + if ( pArchive->Exists( textureName.c_str() ) ) + { + rExt = *it; + rFile = textureName; + found = true; + break; + } + } + + return found; +} + +// ------------------------------------------------------------------------------------------------ + +} // Namespace Assimp + +#endif // ASSIMP_BUILD_NO_Q3BSP_IMPORTER |