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