aboutsummaryrefslogtreecommitdiff
path: root/NvCloth/samples/external/assimp-4.1.0/code/Q3BSPFileImporter.cpp
diff options
context:
space:
mode:
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.cpp771
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