vrshoot

diff libs/assimp/Q3BSPFileImporter.cpp @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libs/assimp/Q3BSPFileImporter.cpp	Sat Feb 01 19:58:19 2014 +0200
     1.3 @@ -0,0 +1,787 @@
     1.4 +/*
     1.5 +Open Asset Import Library (assimp)
     1.6 +---------------------------------------------------------------------------------------------------
     1.7 +
     1.8 +Copyright (c) 2006-2008, assimp team
     1.9 +All rights reserved.
    1.10 +
    1.11 +Redistribution and use of this software in source and binary forms, 
    1.12 +with or without modification, are permitted provided that the 
    1.13 +following conditions are met:
    1.14 +
    1.15 +* Redistributions of source code must retain the above
    1.16 +  copyright notice, this list of conditions and the
    1.17 +  following disclaimer.
    1.18 +
    1.19 +* Redistributions in binary form must reproduce the above
    1.20 +  copyright notice, this list of conditions and the
    1.21 +  following disclaimer in the documentation and/or other
    1.22 +  materials provided with the distribution.
    1.23 +
    1.24 +* Neither the name of the assimp team, nor the names of its
    1.25 +  contributors may be used to endorse or promote products
    1.26 +  derived from this software without specific prior
    1.27 +  written permission of the assimp team.
    1.28 +
    1.29 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    1.30 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    1.31 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.32 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    1.33 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.34 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    1.35 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.36 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
    1.37 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    1.38 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    1.39 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.40 +
    1.41 +---------------------------------------------------------------------------------------------------
    1.42 +*/
    1.43 +#include "AssimpPCH.h"
    1.44 +#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
    1.45 +
    1.46 +//#include <windows.h> 
    1.47 +#include "DefaultIOSystem.h"
    1.48 +#include "Q3BSPFileImporter.h"
    1.49 +#include "Q3BSPZipArchive.h"
    1.50 +#include "Q3BSPFileParser.h"
    1.51 +#include "Q3BSPFileData.h"
    1.52 +
    1.53 +#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
    1.54 +#	include <zlib.h>
    1.55 +#else
    1.56 +#	include "../contrib/zlib/zlib.h"
    1.57 +#endif
    1.58 +
    1.59 +#include "assimp/types.h"
    1.60 +#include "assimp/mesh.h"
    1.61 +#include <vector>
    1.62 +
    1.63 +
    1.64 +static const aiImporterDesc desc = {
    1.65 +	"Quake III BSP Importer",
    1.66 +	"",
    1.67 +	"",
    1.68 +	"",
    1.69 +	aiImporterFlags_SupportBinaryFlavour,
    1.70 +	0,
    1.71 +	0,
    1.72 +	0,
    1.73 +	0,
    1.74 +	"pk3"
    1.75 +};
    1.76 +
    1.77 +namespace Assimp
    1.78 +{
    1.79 +
    1.80 +using namespace Q3BSP;
    1.81 +
    1.82 +// ------------------------------------------------------------------------------------------------
    1.83 +//	Local function to create a material key name.
    1.84 +static void createKey( int id1, int id2, std::string &rKey )
    1.85 +{
    1.86 +	std::ostringstream str;
    1.87 +	str << id1 << "." << id2;
    1.88 +	rKey = str.str();
    1.89 +}
    1.90 +
    1.91 +// ------------------------------------------------------------------------------------------------
    1.92 +//	Local function to extract the texture ids from a material keyname.
    1.93 +static void extractIds( const std::string &rKey, int &rId1, int &rId2 )
    1.94 +{
    1.95 +	rId1 = -1;
    1.96 +	rId2 = -1;
    1.97 +	if ( rKey.empty() )
    1.98 +		return;
    1.99 +
   1.100 +	std::string::size_type pos = rKey.find( "." );
   1.101 +	if ( std::string::npos == pos )
   1.102 +		return;
   1.103 +
   1.104 +	std::string tmp1 = rKey.substr( 0, pos );
   1.105 +	std::string tmp2 = rKey.substr( pos + 1, rKey.size() - pos - 1 );
   1.106 +	rId1 = atoi( tmp1.c_str() );
   1.107 +	rId2 = atoi( tmp2.c_str() );
   1.108 +}
   1.109 +
   1.110 +// ------------------------------------------------------------------------------------------------
   1.111 +//	Local helper function to normalize filenames.
   1.112 +static void normalizePathName( const std::string &rPath, std::string &rNormalizedPath )
   1.113 +{
   1.114 +	rNormalizedPath = "";
   1.115 +	if ( rPath.empty() )
   1.116 +		return;
   1.117 +
   1.118 +#ifdef _WIN32
   1.119 +	std::string sep = "\\";
   1.120 +#else
   1.121 +	std::string sep = "/";
   1.122 +#endif
   1.123 +
   1.124 +	static const unsigned int numDelimiters = 2;
   1.125 +	const char delimiters[ numDelimiters ] = { '/', '\\' };
   1.126 +	rNormalizedPath = rPath;
   1.127 +	for ( unsigned int i=0; i<numDelimiters; i++ )
   1.128 +	{
   1.129 +		for ( size_t j=0; j<rNormalizedPath.size(); j++ )
   1.130 +		{
   1.131 +			if ( rNormalizedPath[j] == delimiters[ i ] )
   1.132 +			{
   1.133 +				rNormalizedPath[ j ] = sep[ 0 ];
   1.134 +			}
   1.135 +		}
   1.136 +	}
   1.137 +}
   1.138 +
   1.139 +// ------------------------------------------------------------------------------------------------
   1.140 +//	Constructor.
   1.141 +Q3BSPFileImporter::Q3BSPFileImporter() :
   1.142 +	m_pCurrentMesh( NULL ),
   1.143 +	m_pCurrentFace( NULL ),
   1.144 +	m_MaterialLookupMap(),
   1.145 +	mTextures()
   1.146 +{
   1.147 +	// empty
   1.148 +}
   1.149 +
   1.150 +// ------------------------------------------------------------------------------------------------
   1.151 +//	Destructor.
   1.152 +Q3BSPFileImporter::~Q3BSPFileImporter()
   1.153 +{
   1.154 +	// For lint
   1.155 +	m_pCurrentMesh = NULL;
   1.156 +	m_pCurrentFace = NULL;
   1.157 +	
   1.158 +	// Clear face-to-material map
   1.159 +	for ( FaceMap::iterator it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end();
   1.160 +		++it )
   1.161 +	{
   1.162 +		const std::string matName = (*it).first;
   1.163 +		if ( matName.empty() )
   1.164 +		{
   1.165 +			continue;
   1.166 +		}
   1.167 +
   1.168 +		std::vector<Q3BSP::sQ3BSPFace*> *pCurFaceArray = (*it).second;
   1.169 +		delete pCurFaceArray;
   1.170 +	}
   1.171 +	m_MaterialLookupMap.clear();
   1.172 +}
   1.173 +
   1.174 +// ------------------------------------------------------------------------------------------------
   1.175 +//	Returns true, if the loader can read this.
   1.176 +bool Q3BSPFileImporter::CanRead( const std::string& rFile, IOSystem* /*pIOHandler*/, bool checkSig ) const
   1.177 +{
   1.178 +	if(!checkSig) {
   1.179 +		return SimpleExtensionCheck( rFile, "pk3" );
   1.180 +	}
   1.181 +	// TODO perhaps add keyword based detection
   1.182 +	return false;
   1.183 +}
   1.184 +
   1.185 +// ------------------------------------------------------------------------------------------------
   1.186 +//	Adds extensions.
   1.187 +const aiImporterDesc* Q3BSPFileImporter::GetInfo () const
   1.188 +{
   1.189 +	return &desc;
   1.190 +}
   1.191 +
   1.192 +// ------------------------------------------------------------------------------------------------
   1.193 +//	Import method.
   1.194 +void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene* pScene, IOSystem* /*pIOHandler*/)
   1.195 +{
   1.196 +	Q3BSPZipArchive Archive( rFile );
   1.197 +	if ( !Archive.isOpen() )
   1.198 +	{
   1.199 +		throw DeadlyImportError( "Failed to open file " + rFile + "." );
   1.200 +	}
   1.201 +
   1.202 +	std::string archiveName( "" ), mapName( "" );
   1.203 +	separateMapName( rFile, archiveName, mapName );
   1.204 +
   1.205 +	if ( mapName.empty() )
   1.206 +	{
   1.207 +		if ( !findFirstMapInArchive( Archive, mapName ) )
   1.208 +		{
   1.209 +			return;
   1.210 +		}
   1.211 +	}
   1.212 +
   1.213 +	Q3BSPFileParser fileParser( mapName, &Archive );
   1.214 +	Q3BSPModel *pBSPModel = fileParser.getModel();
   1.215 +	if ( NULL != pBSPModel )
   1.216 +	{
   1.217 +		CreateDataFromImport( pBSPModel, pScene, &Archive );
   1.218 +	}
   1.219 +}
   1.220 +
   1.221 +// ------------------------------------------------------------------------------------------------
   1.222 +//	Separates the map name from the import name.
   1.223 +void Q3BSPFileImporter::separateMapName( const std::string &rImportName, std::string &rArchiveName, 
   1.224 +										std::string &rMapName )
   1.225 +{
   1.226 +	rArchiveName = "";
   1.227 +	rMapName = "";
   1.228 +	if ( rImportName.empty() )
   1.229 +		return;
   1.230 +
   1.231 +	std::string::size_type pos = rImportName.rfind( "," );
   1.232 +	if ( std::string::npos == pos )
   1.233 +	{
   1.234 +		rArchiveName = rImportName;
   1.235 +		return;
   1.236 +	}
   1.237 +
   1.238 +	rArchiveName = rImportName.substr( 0, pos );
   1.239 +	rMapName = rImportName.substr( pos, rImportName.size() - pos - 1 );
   1.240 +}
   1.241 +
   1.242 +// ------------------------------------------------------------------------------------------------
   1.243 +//	Returns the first map in the map archive.
   1.244 +bool Q3BSPFileImporter::findFirstMapInArchive( Q3BSPZipArchive &rArchive, std::string &rMapName )
   1.245 +{
   1.246 +	rMapName = "";
   1.247 +	std::vector<std::string> fileList;
   1.248 +	rArchive.getFileList( fileList );
   1.249 +	if ( fileList.empty() )  
   1.250 +		return false;
   1.251 +
   1.252 +	for ( std::vector<std::string>::iterator it = fileList.begin(); it != fileList.end();
   1.253 +		++it )
   1.254 +	{
   1.255 +		std::string::size_type pos = (*it).find( "maps/" );
   1.256 +		if ( std::string::npos != pos )
   1.257 +		{
   1.258 +			std::string::size_type extPos = (*it).find( ".bsp" );
   1.259 +			if ( std::string::npos != extPos )
   1.260 +			{
   1.261 +				rMapName = *it;
   1.262 +				return true;
   1.263 +			}
   1.264 +		}
   1.265 +	}
   1.266 +	
   1.267 +	return false;
   1.268 +}
   1.269 +
   1.270 +// ------------------------------------------------------------------------------------------------
   1.271 +//	Creates the assimp specific data.
   1.272 +void Q3BSPFileImporter::CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, 
   1.273 +											 Q3BSPZipArchive *pArchive )
   1.274 +{
   1.275 +	if ( NULL == pModel || NULL == pScene )
   1.276 +		return;
   1.277 +
   1.278 +	pScene->mRootNode = new aiNode;
   1.279 +	if ( !pModel->m_ModelName.empty() )
   1.280 +	{
   1.281 +		pScene->mRootNode->mName.Set( pModel->m_ModelName );
   1.282 +	}
   1.283 +
   1.284 +	// Create the face to material relation map 
   1.285 +	createMaterialMap( pModel );
   1.286 +
   1.287 +	// Create all nodes
   1.288 +	CreateNodes( pModel, pScene, pScene->mRootNode );
   1.289 +	
   1.290 +	// Create the assigned materials
   1.291 +	createMaterials( pModel, pScene, pArchive );
   1.292 +}
   1.293 +
   1.294 +// ------------------------------------------------------------------------------------------------
   1.295 +//	Creates all assimp nodes.
   1.296 +void Q3BSPFileImporter::CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, 
   1.297 +									aiNode *pParent )
   1.298 +{
   1.299 +	ai_assert( NULL != pModel );
   1.300 +	if ( NULL == pModel )
   1.301 +	{
   1.302 +		return;
   1.303 +	}
   1.304 +
   1.305 +	unsigned int matIdx = 0;
   1.306 +	std::vector<aiMesh*> MeshArray;
   1.307 +	std::vector<aiNode*> NodeArray;
   1.308 +	for ( FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it )
   1.309 +	{
   1.310 +		std::vector<Q3BSP::sQ3BSPFace*> *pArray = (*it).second;
   1.311 +		size_t numVerts = countData( *pArray );
   1.312 +		if ( 0 != numVerts )
   1.313 +		{
   1.314 +			aiMesh* pMesh = new aiMesh;
   1.315 +			aiNode *pNode = CreateTopology( pModel, matIdx, *pArray, pMesh );
   1.316 +			if ( NULL != pNode )
   1.317 +			{
   1.318 +				NodeArray.push_back( pNode );
   1.319 +				MeshArray.push_back( pMesh );
   1.320 +			}
   1.321 +			else
   1.322 +			{
   1.323 +				delete pMesh;
   1.324 +			}
   1.325 +		}
   1.326 +		matIdx++;
   1.327 +	}
   1.328 +
   1.329 +	pScene->mNumMeshes = MeshArray.size();
   1.330 +	if ( pScene->mNumMeshes > 0 )
   1.331 +	{
   1.332 +		pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ];
   1.333 +		for ( size_t i = 0; i < MeshArray.size(); i++ )
   1.334 +		{
   1.335 +			aiMesh *pMesh = MeshArray[ i ];
   1.336 +			if ( NULL != pMesh )
   1.337 +			{
   1.338 +				pScene->mMeshes[ i ] = pMesh;
   1.339 +			}
   1.340 +		}
   1.341 +	}
   1.342 +
   1.343 +	pParent->mNumChildren = MeshArray.size();
   1.344 +	pParent->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren ];
   1.345 +	for ( size_t i=0; i<NodeArray.size(); i++ )
   1.346 +	{
   1.347 +		aiNode *pNode = NodeArray[ i ];
   1.348 +		pNode->mParent = pParent;
   1.349 +		pParent->mChildren[ i ] = pNode;
   1.350 +		pParent->mChildren[ i ]->mMeshes[ 0 ] = i;
   1.351 +	}
   1.352 +}
   1.353 +
   1.354 +// ------------------------------------------------------------------------------------------------
   1.355 +//	Creates the topology.
   1.356 +aiNode *Q3BSPFileImporter::CreateTopology( const Q3BSP::Q3BSPModel *pModel,
   1.357 +										  unsigned int materialIdx,
   1.358 +										  std::vector<sQ3BSPFace*> &rArray, 
   1.359 +										  aiMesh* pMesh )
   1.360 +{
   1.361 +	size_t numVerts = countData( rArray );
   1.362 +	if ( 0 == numVerts )
   1.363 +	{
   1.364 +		return NULL;
   1.365 +	}
   1.366 +	
   1.367 +	size_t numFaces = countFaces( rArray );
   1.368 +	if ( 0 == numFaces )
   1.369 +	{
   1.370 +		return NULL;
   1.371 +	}
   1.372 +
   1.373 +	size_t numTriangles = countTriangles( rArray );
   1.374 +	pMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
   1.375 +
   1.376 +	pMesh->mFaces = new aiFace[ numTriangles ];
   1.377 +	pMesh->mNumFaces = numTriangles;
   1.378 +	
   1.379 +	pMesh->mNumVertices = numVerts;
   1.380 +	pMesh->mVertices = new aiVector3D[ numVerts ];
   1.381 +	pMesh->mNormals =  new aiVector3D[ numVerts ];
   1.382 +	pMesh->mTextureCoords[ 0 ] = new aiVector3D[ numVerts ];
   1.383 +	pMesh->mTextureCoords[ 1 ] = new aiVector3D[ numVerts ];
   1.384 +	pMesh->mMaterialIndex = materialIdx;
   1.385 +
   1.386 +	unsigned int faceIdx = 0;
   1.387 +	unsigned int vertIdx = 0;
   1.388 +	pMesh->mNumUVComponents[ 0 ] = 2;
   1.389 +	pMesh->mNumUVComponents[ 1 ] = 2;
   1.390 +	for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); ++it )
   1.391 +	{
   1.392 +		Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
   1.393 +		ai_assert( NULL != pQ3BSPFace );
   1.394 +		if ( NULL == pQ3BSPFace )
   1.395 +		{
   1.396 +			continue;
   1.397 +		}
   1.398 +
   1.399 +		if ( pQ3BSPFace->iNumOfFaceVerts > 0 )
   1.400 +		{
   1.401 +			if ( pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh )
   1.402 +			{
   1.403 +				createTriangleTopology( pModel, pQ3BSPFace, pMesh, faceIdx, vertIdx );
   1.404 +			}		
   1.405 +		}
   1.406 +	}
   1.407 +
   1.408 +	aiNode *pNode = new aiNode;
   1.409 +	pNode->mNumMeshes = 1;
   1.410 +	pNode->mMeshes = new unsigned int[ 1 ];
   1.411 +
   1.412 +	return pNode;
   1.413 +}
   1.414 +
   1.415 +// ------------------------------------------------------------------------------------------------
   1.416 +//	Creates the triangle topology from a face array.
   1.417 +void Q3BSPFileImporter::createTriangleTopology( const Q3BSP::Q3BSPModel *pModel,
   1.418 +											  Q3BSP::sQ3BSPFace *pQ3BSPFace, 
   1.419 +											  aiMesh* pMesh,
   1.420 +											  unsigned int &rFaceIdx, 
   1.421 +											  unsigned int &rVertIdx )
   1.422 +{
   1.423 +	ai_assert( rFaceIdx < pMesh->mNumFaces );
   1.424 +	
   1.425 +	m_pCurrentFace = getNextFace( pMesh, rFaceIdx );
   1.426 +	ai_assert( NULL != m_pCurrentFace );
   1.427 +	if ( NULL == m_pCurrentFace )
   1.428 +	{
   1.429 +		return;
   1.430 +	}
   1.431 +
   1.432 +	m_pCurrentFace->mNumIndices = 3;
   1.433 +	m_pCurrentFace->mIndices = new unsigned int[ m_pCurrentFace->mNumIndices ];
   1.434 +	
   1.435 +	size_t idx = 0;
   1.436 +	for ( size_t i = 0; i < (size_t) pQ3BSPFace->iNumOfFaceVerts; i++ )
   1.437 +	{
   1.438 +		const size_t index = pQ3BSPFace->iVertexIndex + pModel->m_Indices[ pQ3BSPFace->iFaceVertexIndex + i ];
   1.439 +		ai_assert( index < pModel->m_Vertices.size() );
   1.440 +		if ( index >= pModel->m_Vertices.size() )
   1.441 +		{
   1.442 +			continue;
   1.443 +		}
   1.444 +
   1.445 +		sQ3BSPVertex *pVertex = pModel->m_Vertices[ index ];
   1.446 +		ai_assert( NULL != pVertex );
   1.447 +		if ( NULL == pVertex )
   1.448 +		{
   1.449 +			continue;
   1.450 +		}
   1.451 +
   1.452 +		pMesh->mVertices[ rVertIdx ].Set( pVertex->vPosition.x, pVertex->vPosition.y, pVertex->vPosition.z );
   1.453 +		pMesh->mNormals[ rVertIdx ].Set( pVertex->vNormal.x, pVertex->vNormal.y, pVertex->vNormal.z );
   1.454 +				
   1.455 +		pMesh->mTextureCoords[ 0 ][ rVertIdx ].Set( pVertex->vTexCoord.x, pVertex->vTexCoord.y, 0.0f );
   1.456 +		pMesh->mTextureCoords[ 1 ][ rVertIdx ].Set( pVertex->vLightmap.x, pVertex->vLightmap.y, 0.0f );
   1.457 +		
   1.458 +		m_pCurrentFace->mIndices[ idx ] = rVertIdx;
   1.459 +		rVertIdx++;
   1.460 +		
   1.461 +		idx++;
   1.462 +		if ( idx > 2 )
   1.463 +		{
   1.464 +			idx = 0;
   1.465 +			m_pCurrentFace = getNextFace( pMesh, rFaceIdx );
   1.466 +			if ( NULL != m_pCurrentFace )
   1.467 +			{
   1.468 +				m_pCurrentFace->mNumIndices = 3;
   1.469 +				m_pCurrentFace->mIndices = new unsigned int[ 3 ];
   1.470 +			}
   1.471 +		}
   1.472 +	}
   1.473 +	rFaceIdx--;
   1.474 +}
   1.475 +
   1.476 +// ------------------------------------------------------------------------------------------------
   1.477 +//	Creates all referenced materials.
   1.478 +void Q3BSPFileImporter::createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
   1.479 +										Q3BSPZipArchive *pArchive )
   1.480 +{
   1.481 +	if ( m_MaterialLookupMap.empty() )
   1.482 +	{
   1.483 +		return;
   1.484 +	}
   1.485 +
   1.486 +	pScene->mMaterials = new aiMaterial*[ m_MaterialLookupMap.size() ];
   1.487 +	aiString aiMatName;
   1.488 +	int textureId( -1 ), lightmapId( -1 );
   1.489 +	for ( FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end();
   1.490 +		++it )
   1.491 +	{
   1.492 +		const std::string matName = (*it).first;
   1.493 +		if ( matName.empty() )
   1.494 +		{
   1.495 +			continue;
   1.496 +		}
   1.497 +
   1.498 +		aiMatName.Set( matName );
   1.499 +		aiMaterial *pMatHelper = new aiMaterial;
   1.500 +		pMatHelper->AddProperty( &aiMatName, AI_MATKEY_NAME );
   1.501 +
   1.502 +		extractIds( matName, textureId, lightmapId );
   1.503 +		
   1.504 +		// Adding the texture
   1.505 +		if ( -1 != textureId )
   1.506 +		{
   1.507 +			sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ];
   1.508 +			if ( NULL != pTexture )
   1.509 +			{
   1.510 +				std::string tmp( "*" ), texName( "" );
   1.511 +				tmp += pTexture->strName;
   1.512 +				tmp += ".jpg";
   1.513 +				normalizePathName( tmp, texName );
   1.514 +				
   1.515 +				if ( !importTextureFromArchive( pModel, pArchive, pScene, pMatHelper, textureId ) )
   1.516 +				{
   1.517 +				}
   1.518 +			}
   1.519 +
   1.520 +		}
   1.521 +		if ( -1 != lightmapId )
   1.522 +		{
   1.523 +			importLightmap( pModel, pScene, pMatHelper, lightmapId );
   1.524 +		}
   1.525 +		pScene->mMaterials[ pScene->mNumMaterials ] = pMatHelper;
   1.526 +		pScene->mNumMaterials++;
   1.527 +	}
   1.528 +	pScene->mNumTextures = mTextures.size();
   1.529 +	pScene->mTextures = new aiTexture*[ pScene->mNumTextures ];
   1.530 +	std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures );
   1.531 +}
   1.532 +
   1.533 +// ------------------------------------------------------------------------------------------------
   1.534 +//	Counts the number of referenced vertices.
   1.535 +size_t Q3BSPFileImporter::countData( const std::vector<sQ3BSPFace*> &rArray ) const
   1.536 +{
   1.537 +	size_t numVerts = 0;
   1.538 +	for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); 
   1.539 +		++it )
   1.540 +	{
   1.541 +		sQ3BSPFace *pQ3BSPFace = *it;
   1.542 +		if ( pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh )
   1.543 +		{
   1.544 +			Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
   1.545 +			ai_assert( NULL != pQ3BSPFace );
   1.546 +			numVerts += pQ3BSPFace->iNumOfFaceVerts;
   1.547 +		}
   1.548 +	}
   1.549 +
   1.550 +	return numVerts;
   1.551 +}
   1.552 +
   1.553 +// ------------------------------------------------------------------------------------------------
   1.554 +//	Counts the faces with vertices.
   1.555 +size_t Q3BSPFileImporter::countFaces( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const
   1.556 +{
   1.557 +	size_t numFaces = 0;
   1.558 +	for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); 
   1.559 +		++it )
   1.560 +	{
   1.561 +		Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
   1.562 +		if ( pQ3BSPFace->iNumOfFaceVerts > 0 )
   1.563 +		{
   1.564 +			numFaces++;
   1.565 +		}
   1.566 +	}
   1.567 +
   1.568 +	return numFaces;
   1.569 +}
   1.570 +
   1.571 +// ------------------------------------------------------------------------------------------------
   1.572 +//	Counts the number of triangles in a Q3-facearray.
   1.573 +size_t Q3BSPFileImporter::countTriangles( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const
   1.574 +{
   1.575 +	size_t numTriangles = 0;
   1.576 +	for ( std::vector<Q3BSP::sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); 
   1.577 +		++it )
   1.578 +	{
   1.579 +		const Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
   1.580 +		if ( NULL != pQ3BSPFace )
   1.581 +		{
   1.582 +			numTriangles += pQ3BSPFace->iNumOfFaceVerts / 3;
   1.583 +		}
   1.584 +	}
   1.585 +
   1.586 +	return numTriangles;
   1.587 +}
   1.588 +
   1.589 +// ------------------------------------------------------------------------------------------------
   1.590 +//	Creates the faces-to-material map.
   1.591 +void Q3BSPFileImporter::createMaterialMap( const Q3BSP::Q3BSPModel *pModel )
   1.592 +{
   1.593 +	std::string key( "" );
   1.594 +	std::vector<sQ3BSPFace*> *pCurFaceArray = NULL;
   1.595 +	for ( size_t idx = 0; idx < pModel->m_Faces.size(); idx++ )
   1.596 +	{
   1.597 +		Q3BSP::sQ3BSPFace *pQ3BSPFace = pModel->m_Faces[ idx ];
   1.598 +		const int texId = pQ3BSPFace->iTextureID;
   1.599 +		const int lightMapId = pQ3BSPFace->iLightmapID;
   1.600 +		createKey( texId, lightMapId, key );
   1.601 +		FaceMapIt it = m_MaterialLookupMap.find( key );
   1.602 +		if ( m_MaterialLookupMap.end() == it )
   1.603 +		{
   1.604 +			pCurFaceArray = new std::vector<Q3BSP::sQ3BSPFace*>;
   1.605 +			m_MaterialLookupMap[ key ] = pCurFaceArray;
   1.606 +		}
   1.607 +		else
   1.608 +		{
   1.609 +			pCurFaceArray = (*it).second;
   1.610 +		}
   1.611 +		ai_assert( NULL != pCurFaceArray );
   1.612 +		if ( NULL != pCurFaceArray )
   1.613 +		{
   1.614 +			pCurFaceArray->push_back( pQ3BSPFace );
   1.615 +		}
   1.616 +	}
   1.617 +}
   1.618 +
   1.619 +// ------------------------------------------------------------------------------------------------
   1.620 +//	Returns the next face.
   1.621 +aiFace *Q3BSPFileImporter::getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx )
   1.622 +{
   1.623 +	aiFace *pFace = NULL;
   1.624 +	if ( rFaceIdx < pMesh->mNumFaces )
   1.625 +	{
   1.626 +		pFace = &pMesh->mFaces[ rFaceIdx ];
   1.627 +		rFaceIdx++;
   1.628 +	}
   1.629 +	else
   1.630 +	{
   1.631 +		pFace = NULL;
   1.632 +	}
   1.633 +
   1.634 +	return pFace;
   1.635 +}
   1.636 +
   1.637 +// ------------------------------------------------------------------------------------------------
   1.638 +//	Imports a texture file.
   1.639 +bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel,
   1.640 +												 Q3BSP::Q3BSPZipArchive *pArchive, aiScene* /*pScene*/,
   1.641 +												 aiMaterial *pMatHelper, int textureId )
   1.642 +{
   1.643 +	std::vector<std::string> supportedExtensions;
   1.644 +	supportedExtensions.push_back( ".jpg" );
   1.645 +	supportedExtensions.push_back( ".png" );
   1.646 +  supportedExtensions.push_back( ".tga" );
   1.647 +	if ( NULL == pArchive || NULL == pArchive || NULL == pMatHelper )
   1.648 +	{
   1.649 +		return false;
   1.650 +	}
   1.651 +
   1.652 +	if ( textureId < 0 || textureId >= static_cast<int>( pModel->m_Textures.size() ) )
   1.653 +	{
   1.654 +		return false;
   1.655 +	}
   1.656 +
   1.657 +	bool res = true;
   1.658 +	sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ];
   1.659 +	if ( NULL == pTexture )
   1.660 +		return false;
   1.661 +
   1.662 +	std::string textureName, ext;
   1.663 +	if ( expandFile( pArchive, pTexture->strName, supportedExtensions, textureName, ext ) )
   1.664 +	{
   1.665 +		IOStream *pTextureStream = pArchive->Open( textureName.c_str() );
   1.666 +		if ( NULL != pTextureStream )
   1.667 +		{
   1.668 +			size_t texSize = pTextureStream->FileSize();
   1.669 +			aiTexture *pTexture = new aiTexture;
   1.670 +			pTexture->mHeight = 0;
   1.671 +			pTexture->mWidth = texSize;
   1.672 +			unsigned char *pData = new unsigned char[ pTexture->mWidth ];
   1.673 +			size_t readSize = pTextureStream->Read( pData, sizeof( unsigned char ), pTexture->mWidth );
   1.674 +			(void)readSize;
   1.675 +			ai_assert( readSize == pTexture->mWidth );
   1.676 +			pTexture->pcData = reinterpret_cast<aiTexel*>( pData );
   1.677 +			pTexture->achFormatHint[ 0 ] = ext[ 1 ];
   1.678 +			pTexture->achFormatHint[ 1 ] = ext[ 2 ];
   1.679 +			pTexture->achFormatHint[ 2 ] = ext[ 3 ];
   1.680 +			pTexture->achFormatHint[ 3 ] = '\0';
   1.681 +			res = true;
   1.682 +
   1.683 +			aiString name;
   1.684 +			name.data[ 0 ] = '*';
   1.685 +			name.length = 1 + ASSIMP_itoa10( name.data + 1, MAXLEN-1, mTextures.size() );
   1.686 +
   1.687 +			pArchive->Close( pTextureStream );
   1.688 +
   1.689 +			pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
   1.690 +			mTextures.push_back( pTexture );
   1.691 +		}
   1.692 +		else
   1.693 +		{
   1.694 +			// If it doesn't exist in the archive, it is probably just a reference to an external file.
   1.695 +			// We'll leave it up to the user to figure out which extension the file has.
   1.696 +			aiString name;
   1.697 +			strncpy( name.data, pTexture->strName, sizeof name.data );
   1.698 +			name.length = strlen( name.data );
   1.699 +			pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
   1.700 +		}
   1.701 +	}
   1.702 +
   1.703 +	return res;
   1.704 +}
   1.705 +
   1.706 +// ------------------------------------------------------------------------------------------------
   1.707 +//	Imports a light map file.
   1.708 +bool Q3BSPFileImporter::importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, 
   1.709 +									   aiMaterial *pMatHelper, int lightmapId )
   1.710 +{
   1.711 +	if ( NULL == pModel || NULL == pScene || NULL == pMatHelper )
   1.712 +	{
   1.713 +		return false;
   1.714 +	}
   1.715 +
   1.716 +	if ( lightmapId < 0 || lightmapId >= static_cast<int>( pModel->m_Lightmaps.size() ) )
   1.717 +	{
   1.718 +		return false;
   1.719 +	}
   1.720 +
   1.721 +	sQ3BSPLightmap *pLightMap = pModel->m_Lightmaps[ lightmapId ];
   1.722 +	if ( NULL == pLightMap )
   1.723 +	{
   1.724 +		return false;
   1.725 +	}
   1.726 +
   1.727 +	aiTexture *pTexture = new aiTexture;
   1.728 +	
   1.729 +	pTexture->mWidth = CE_BSP_LIGHTMAPWIDTH;
   1.730 +	pTexture->mHeight = CE_BSP_LIGHTMAPHEIGHT;
   1.731 +	pTexture->pcData = new aiTexel[CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT];
   1.732 +
   1.733 +	::memcpy( pTexture->pcData, pLightMap->bLMapData, pTexture->mWidth );
   1.734 +	size_t p = 0;
   1.735 +	for ( size_t i = 0; i < CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT; ++i )
   1.736 +	{
   1.737 +		pTexture->pcData[ i ].r = pLightMap->bLMapData[ p++ ];
   1.738 +		pTexture->pcData[ i ].g = pLightMap->bLMapData[ p++ ];
   1.739 +		pTexture->pcData[ i ].b = pLightMap->bLMapData[ p++ ];
   1.740 +		pTexture->pcData[ i ].a = 0xFF;
   1.741 +	}
   1.742 +	
   1.743 +	aiString name;
   1.744 +	name.data[ 0 ] = '*';
   1.745 +	name.length = 1 + ASSIMP_itoa10( name.data + 1, MAXLEN-1,  mTextures.size() );
   1.746 +
   1.747 +	pMatHelper->AddProperty( &name,AI_MATKEY_TEXTURE_LIGHTMAP( 1 ) );
   1.748 +	mTextures.push_back( pTexture );
   1.749 +
   1.750 +	return true;
   1.751 +}
   1.752 +
   1.753 +
   1.754 +// ------------------------------------------------------------------------------------------------
   1.755 +//	Will search for a supported extension.
   1.756 +bool Q3BSPFileImporter::expandFile(  Q3BSP::Q3BSPZipArchive *pArchive, const std::string &rFilename, 
   1.757 +								   const std::vector<std::string> &rExtList, std::string &rFile,
   1.758 +								   std::string &rExt )
   1.759 +{
   1.760 +	ai_assert( NULL != pArchive );
   1.761 +	ai_assert( !rFilename.empty() );
   1.762 +
   1.763 +	if ( rExtList.empty() )
   1.764 +	{
   1.765 +		rFile =  rFilename;
   1.766 +		rExt = "";
   1.767 +		return true;
   1.768 +	}
   1.769 +
   1.770 +	bool found = false;
   1.771 +	for ( std::vector<std::string>::const_iterator it = rExtList.begin(); it != rExtList.end(); ++it )
   1.772 +	{
   1.773 +		const std::string textureName = rFilename + *it;
   1.774 +		if ( pArchive->Exists( textureName.c_str() ) )
   1.775 +		{
   1.776 +			rExt = *it;
   1.777 +			rFile = textureName;
   1.778 +			found = true;
   1.779 +			break;
   1.780 +		}
   1.781 +	}
   1.782 +
   1.783 +	return found;
   1.784 +}
   1.785 +
   1.786 +// ------------------------------------------------------------------------------------------------
   1.787 +
   1.788 +} // Namespace Assimp
   1.789 +
   1.790 +#endif // ASSIMP_BUILD_NO_Q3BSP_IMPORTER