vrshoot

view 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 source
1 /*
2 Open Asset Import Library (assimp)
3 ---------------------------------------------------------------------------------------------------
5 Copyright (c) 2006-2008, assimp team
6 All rights reserved.
8 Redistribution and use of this software in source and binary forms,
9 with or without modification, are permitted provided that the
10 following conditions are met:
12 * Redistributions of source code must retain the above
13 copyright notice, this list of conditions and the
14 following disclaimer.
16 * Redistributions in binary form must reproduce the above
17 copyright notice, this list of conditions and the
18 following disclaimer in the documentation and/or other
19 materials provided with the distribution.
21 * Neither the name of the assimp team, nor the names of its
22 contributors may be used to endorse or promote products
23 derived from this software without specific prior
24 written permission of the assimp team.
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 ---------------------------------------------------------------------------------------------------
39 */
40 #include "AssimpPCH.h"
41 #ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
43 //#include <windows.h>
44 #include "DefaultIOSystem.h"
45 #include "Q3BSPFileImporter.h"
46 #include "Q3BSPZipArchive.h"
47 #include "Q3BSPFileParser.h"
48 #include "Q3BSPFileData.h"
50 #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
51 # include <zlib.h>
52 #else
53 # include "../contrib/zlib/zlib.h"
54 #endif
56 #include "assimp/types.h"
57 #include "assimp/mesh.h"
58 #include <vector>
61 static const aiImporterDesc desc = {
62 "Quake III BSP Importer",
63 "",
64 "",
65 "",
66 aiImporterFlags_SupportBinaryFlavour,
67 0,
68 0,
69 0,
70 0,
71 "pk3"
72 };
74 namespace Assimp
75 {
77 using namespace Q3BSP;
79 // ------------------------------------------------------------------------------------------------
80 // Local function to create a material key name.
81 static void createKey( int id1, int id2, std::string &rKey )
82 {
83 std::ostringstream str;
84 str << id1 << "." << id2;
85 rKey = str.str();
86 }
88 // ------------------------------------------------------------------------------------------------
89 // Local function to extract the texture ids from a material keyname.
90 static void extractIds( const std::string &rKey, int &rId1, int &rId2 )
91 {
92 rId1 = -1;
93 rId2 = -1;
94 if ( rKey.empty() )
95 return;
97 std::string::size_type pos = rKey.find( "." );
98 if ( std::string::npos == pos )
99 return;
101 std::string tmp1 = rKey.substr( 0, pos );
102 std::string tmp2 = rKey.substr( pos + 1, rKey.size() - pos - 1 );
103 rId1 = atoi( tmp1.c_str() );
104 rId2 = atoi( tmp2.c_str() );
105 }
107 // ------------------------------------------------------------------------------------------------
108 // Local helper function to normalize filenames.
109 static void normalizePathName( const std::string &rPath, std::string &rNormalizedPath )
110 {
111 rNormalizedPath = "";
112 if ( rPath.empty() )
113 return;
115 #ifdef _WIN32
116 std::string sep = "\\";
117 #else
118 std::string sep = "/";
119 #endif
121 static const unsigned int numDelimiters = 2;
122 const char delimiters[ numDelimiters ] = { '/', '\\' };
123 rNormalizedPath = rPath;
124 for ( unsigned int i=0; i<numDelimiters; i++ )
125 {
126 for ( size_t j=0; j<rNormalizedPath.size(); j++ )
127 {
128 if ( rNormalizedPath[j] == delimiters[ i ] )
129 {
130 rNormalizedPath[ j ] = sep[ 0 ];
131 }
132 }
133 }
134 }
136 // ------------------------------------------------------------------------------------------------
137 // Constructor.
138 Q3BSPFileImporter::Q3BSPFileImporter() :
139 m_pCurrentMesh( NULL ),
140 m_pCurrentFace( NULL ),
141 m_MaterialLookupMap(),
142 mTextures()
143 {
144 // empty
145 }
147 // ------------------------------------------------------------------------------------------------
148 // Destructor.
149 Q3BSPFileImporter::~Q3BSPFileImporter()
150 {
151 // For lint
152 m_pCurrentMesh = NULL;
153 m_pCurrentFace = NULL;
155 // Clear face-to-material map
156 for ( FaceMap::iterator it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end();
157 ++it )
158 {
159 const std::string matName = (*it).first;
160 if ( matName.empty() )
161 {
162 continue;
163 }
165 std::vector<Q3BSP::sQ3BSPFace*> *pCurFaceArray = (*it).second;
166 delete pCurFaceArray;
167 }
168 m_MaterialLookupMap.clear();
169 }
171 // ------------------------------------------------------------------------------------------------
172 // Returns true, if the loader can read this.
173 bool Q3BSPFileImporter::CanRead( const std::string& rFile, IOSystem* /*pIOHandler*/, bool checkSig ) const
174 {
175 if(!checkSig) {
176 return SimpleExtensionCheck( rFile, "pk3" );
177 }
178 // TODO perhaps add keyword based detection
179 return false;
180 }
182 // ------------------------------------------------------------------------------------------------
183 // Adds extensions.
184 const aiImporterDesc* Q3BSPFileImporter::GetInfo () const
185 {
186 return &desc;
187 }
189 // ------------------------------------------------------------------------------------------------
190 // Import method.
191 void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene* pScene, IOSystem* /*pIOHandler*/)
192 {
193 Q3BSPZipArchive Archive( rFile );
194 if ( !Archive.isOpen() )
195 {
196 throw DeadlyImportError( "Failed to open file " + rFile + "." );
197 }
199 std::string archiveName( "" ), mapName( "" );
200 separateMapName( rFile, archiveName, mapName );
202 if ( mapName.empty() )
203 {
204 if ( !findFirstMapInArchive( Archive, mapName ) )
205 {
206 return;
207 }
208 }
210 Q3BSPFileParser fileParser( mapName, &Archive );
211 Q3BSPModel *pBSPModel = fileParser.getModel();
212 if ( NULL != pBSPModel )
213 {
214 CreateDataFromImport( pBSPModel, pScene, &Archive );
215 }
216 }
218 // ------------------------------------------------------------------------------------------------
219 // Separates the map name from the import name.
220 void Q3BSPFileImporter::separateMapName( const std::string &rImportName, std::string &rArchiveName,
221 std::string &rMapName )
222 {
223 rArchiveName = "";
224 rMapName = "";
225 if ( rImportName.empty() )
226 return;
228 std::string::size_type pos = rImportName.rfind( "," );
229 if ( std::string::npos == pos )
230 {
231 rArchiveName = rImportName;
232 return;
233 }
235 rArchiveName = rImportName.substr( 0, pos );
236 rMapName = rImportName.substr( pos, rImportName.size() - pos - 1 );
237 }
239 // ------------------------------------------------------------------------------------------------
240 // Returns the first map in the map archive.
241 bool Q3BSPFileImporter::findFirstMapInArchive( Q3BSPZipArchive &rArchive, std::string &rMapName )
242 {
243 rMapName = "";
244 std::vector<std::string> fileList;
245 rArchive.getFileList( fileList );
246 if ( fileList.empty() )
247 return false;
249 for ( std::vector<std::string>::iterator it = fileList.begin(); it != fileList.end();
250 ++it )
251 {
252 std::string::size_type pos = (*it).find( "maps/" );
253 if ( std::string::npos != pos )
254 {
255 std::string::size_type extPos = (*it).find( ".bsp" );
256 if ( std::string::npos != extPos )
257 {
258 rMapName = *it;
259 return true;
260 }
261 }
262 }
264 return false;
265 }
267 // ------------------------------------------------------------------------------------------------
268 // Creates the assimp specific data.
269 void Q3BSPFileImporter::CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
270 Q3BSPZipArchive *pArchive )
271 {
272 if ( NULL == pModel || NULL == pScene )
273 return;
275 pScene->mRootNode = new aiNode;
276 if ( !pModel->m_ModelName.empty() )
277 {
278 pScene->mRootNode->mName.Set( pModel->m_ModelName );
279 }
281 // Create the face to material relation map
282 createMaterialMap( pModel );
284 // Create all nodes
285 CreateNodes( pModel, pScene, pScene->mRootNode );
287 // Create the assigned materials
288 createMaterials( pModel, pScene, pArchive );
289 }
291 // ------------------------------------------------------------------------------------------------
292 // Creates all assimp nodes.
293 void Q3BSPFileImporter::CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
294 aiNode *pParent )
295 {
296 ai_assert( NULL != pModel );
297 if ( NULL == pModel )
298 {
299 return;
300 }
302 unsigned int matIdx = 0;
303 std::vector<aiMesh*> MeshArray;
304 std::vector<aiNode*> NodeArray;
305 for ( FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it )
306 {
307 std::vector<Q3BSP::sQ3BSPFace*> *pArray = (*it).second;
308 size_t numVerts = countData( *pArray );
309 if ( 0 != numVerts )
310 {
311 aiMesh* pMesh = new aiMesh;
312 aiNode *pNode = CreateTopology( pModel, matIdx, *pArray, pMesh );
313 if ( NULL != pNode )
314 {
315 NodeArray.push_back( pNode );
316 MeshArray.push_back( pMesh );
317 }
318 else
319 {
320 delete pMesh;
321 }
322 }
323 matIdx++;
324 }
326 pScene->mNumMeshes = MeshArray.size();
327 if ( pScene->mNumMeshes > 0 )
328 {
329 pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ];
330 for ( size_t i = 0; i < MeshArray.size(); i++ )
331 {
332 aiMesh *pMesh = MeshArray[ i ];
333 if ( NULL != pMesh )
334 {
335 pScene->mMeshes[ i ] = pMesh;
336 }
337 }
338 }
340 pParent->mNumChildren = MeshArray.size();
341 pParent->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren ];
342 for ( size_t i=0; i<NodeArray.size(); i++ )
343 {
344 aiNode *pNode = NodeArray[ i ];
345 pNode->mParent = pParent;
346 pParent->mChildren[ i ] = pNode;
347 pParent->mChildren[ i ]->mMeshes[ 0 ] = i;
348 }
349 }
351 // ------------------------------------------------------------------------------------------------
352 // Creates the topology.
353 aiNode *Q3BSPFileImporter::CreateTopology( const Q3BSP::Q3BSPModel *pModel,
354 unsigned int materialIdx,
355 std::vector<sQ3BSPFace*> &rArray,
356 aiMesh* pMesh )
357 {
358 size_t numVerts = countData( rArray );
359 if ( 0 == numVerts )
360 {
361 return NULL;
362 }
364 size_t numFaces = countFaces( rArray );
365 if ( 0 == numFaces )
366 {
367 return NULL;
368 }
370 size_t numTriangles = countTriangles( rArray );
371 pMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
373 pMesh->mFaces = new aiFace[ numTriangles ];
374 pMesh->mNumFaces = numTriangles;
376 pMesh->mNumVertices = numVerts;
377 pMesh->mVertices = new aiVector3D[ numVerts ];
378 pMesh->mNormals = new aiVector3D[ numVerts ];
379 pMesh->mTextureCoords[ 0 ] = new aiVector3D[ numVerts ];
380 pMesh->mTextureCoords[ 1 ] = new aiVector3D[ numVerts ];
381 pMesh->mMaterialIndex = materialIdx;
383 unsigned int faceIdx = 0;
384 unsigned int vertIdx = 0;
385 pMesh->mNumUVComponents[ 0 ] = 2;
386 pMesh->mNumUVComponents[ 1 ] = 2;
387 for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); ++it )
388 {
389 Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
390 ai_assert( NULL != pQ3BSPFace );
391 if ( NULL == pQ3BSPFace )
392 {
393 continue;
394 }
396 if ( pQ3BSPFace->iNumOfFaceVerts > 0 )
397 {
398 if ( pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh )
399 {
400 createTriangleTopology( pModel, pQ3BSPFace, pMesh, faceIdx, vertIdx );
401 }
402 }
403 }
405 aiNode *pNode = new aiNode;
406 pNode->mNumMeshes = 1;
407 pNode->mMeshes = new unsigned int[ 1 ];
409 return pNode;
410 }
412 // ------------------------------------------------------------------------------------------------
413 // Creates the triangle topology from a face array.
414 void Q3BSPFileImporter::createTriangleTopology( const Q3BSP::Q3BSPModel *pModel,
415 Q3BSP::sQ3BSPFace *pQ3BSPFace,
416 aiMesh* pMesh,
417 unsigned int &rFaceIdx,
418 unsigned int &rVertIdx )
419 {
420 ai_assert( rFaceIdx < pMesh->mNumFaces );
422 m_pCurrentFace = getNextFace( pMesh, rFaceIdx );
423 ai_assert( NULL != m_pCurrentFace );
424 if ( NULL == m_pCurrentFace )
425 {
426 return;
427 }
429 m_pCurrentFace->mNumIndices = 3;
430 m_pCurrentFace->mIndices = new unsigned int[ m_pCurrentFace->mNumIndices ];
432 size_t idx = 0;
433 for ( size_t i = 0; i < (size_t) pQ3BSPFace->iNumOfFaceVerts; i++ )
434 {
435 const size_t index = pQ3BSPFace->iVertexIndex + pModel->m_Indices[ pQ3BSPFace->iFaceVertexIndex + i ];
436 ai_assert( index < pModel->m_Vertices.size() );
437 if ( index >= pModel->m_Vertices.size() )
438 {
439 continue;
440 }
442 sQ3BSPVertex *pVertex = pModel->m_Vertices[ index ];
443 ai_assert( NULL != pVertex );
444 if ( NULL == pVertex )
445 {
446 continue;
447 }
449 pMesh->mVertices[ rVertIdx ].Set( pVertex->vPosition.x, pVertex->vPosition.y, pVertex->vPosition.z );
450 pMesh->mNormals[ rVertIdx ].Set( pVertex->vNormal.x, pVertex->vNormal.y, pVertex->vNormal.z );
452 pMesh->mTextureCoords[ 0 ][ rVertIdx ].Set( pVertex->vTexCoord.x, pVertex->vTexCoord.y, 0.0f );
453 pMesh->mTextureCoords[ 1 ][ rVertIdx ].Set( pVertex->vLightmap.x, pVertex->vLightmap.y, 0.0f );
455 m_pCurrentFace->mIndices[ idx ] = rVertIdx;
456 rVertIdx++;
458 idx++;
459 if ( idx > 2 )
460 {
461 idx = 0;
462 m_pCurrentFace = getNextFace( pMesh, rFaceIdx );
463 if ( NULL != m_pCurrentFace )
464 {
465 m_pCurrentFace->mNumIndices = 3;
466 m_pCurrentFace->mIndices = new unsigned int[ 3 ];
467 }
468 }
469 }
470 rFaceIdx--;
471 }
473 // ------------------------------------------------------------------------------------------------
474 // Creates all referenced materials.
475 void Q3BSPFileImporter::createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
476 Q3BSPZipArchive *pArchive )
477 {
478 if ( m_MaterialLookupMap.empty() )
479 {
480 return;
481 }
483 pScene->mMaterials = new aiMaterial*[ m_MaterialLookupMap.size() ];
484 aiString aiMatName;
485 int textureId( -1 ), lightmapId( -1 );
486 for ( FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end();
487 ++it )
488 {
489 const std::string matName = (*it).first;
490 if ( matName.empty() )
491 {
492 continue;
493 }
495 aiMatName.Set( matName );
496 aiMaterial *pMatHelper = new aiMaterial;
497 pMatHelper->AddProperty( &aiMatName, AI_MATKEY_NAME );
499 extractIds( matName, textureId, lightmapId );
501 // Adding the texture
502 if ( -1 != textureId )
503 {
504 sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ];
505 if ( NULL != pTexture )
506 {
507 std::string tmp( "*" ), texName( "" );
508 tmp += pTexture->strName;
509 tmp += ".jpg";
510 normalizePathName( tmp, texName );
512 if ( !importTextureFromArchive( pModel, pArchive, pScene, pMatHelper, textureId ) )
513 {
514 }
515 }
517 }
518 if ( -1 != lightmapId )
519 {
520 importLightmap( pModel, pScene, pMatHelper, lightmapId );
521 }
522 pScene->mMaterials[ pScene->mNumMaterials ] = pMatHelper;
523 pScene->mNumMaterials++;
524 }
525 pScene->mNumTextures = mTextures.size();
526 pScene->mTextures = new aiTexture*[ pScene->mNumTextures ];
527 std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures );
528 }
530 // ------------------------------------------------------------------------------------------------
531 // Counts the number of referenced vertices.
532 size_t Q3BSPFileImporter::countData( const std::vector<sQ3BSPFace*> &rArray ) const
533 {
534 size_t numVerts = 0;
535 for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end();
536 ++it )
537 {
538 sQ3BSPFace *pQ3BSPFace = *it;
539 if ( pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh )
540 {
541 Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
542 ai_assert( NULL != pQ3BSPFace );
543 numVerts += pQ3BSPFace->iNumOfFaceVerts;
544 }
545 }
547 return numVerts;
548 }
550 // ------------------------------------------------------------------------------------------------
551 // Counts the faces with vertices.
552 size_t Q3BSPFileImporter::countFaces( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const
553 {
554 size_t numFaces = 0;
555 for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end();
556 ++it )
557 {
558 Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
559 if ( pQ3BSPFace->iNumOfFaceVerts > 0 )
560 {
561 numFaces++;
562 }
563 }
565 return numFaces;
566 }
568 // ------------------------------------------------------------------------------------------------
569 // Counts the number of triangles in a Q3-facearray.
570 size_t Q3BSPFileImporter::countTriangles( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const
571 {
572 size_t numTriangles = 0;
573 for ( std::vector<Q3BSP::sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end();
574 ++it )
575 {
576 const Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
577 if ( NULL != pQ3BSPFace )
578 {
579 numTriangles += pQ3BSPFace->iNumOfFaceVerts / 3;
580 }
581 }
583 return numTriangles;
584 }
586 // ------------------------------------------------------------------------------------------------
587 // Creates the faces-to-material map.
588 void Q3BSPFileImporter::createMaterialMap( const Q3BSP::Q3BSPModel *pModel )
589 {
590 std::string key( "" );
591 std::vector<sQ3BSPFace*> *pCurFaceArray = NULL;
592 for ( size_t idx = 0; idx < pModel->m_Faces.size(); idx++ )
593 {
594 Q3BSP::sQ3BSPFace *pQ3BSPFace = pModel->m_Faces[ idx ];
595 const int texId = pQ3BSPFace->iTextureID;
596 const int lightMapId = pQ3BSPFace->iLightmapID;
597 createKey( texId, lightMapId, key );
598 FaceMapIt it = m_MaterialLookupMap.find( key );
599 if ( m_MaterialLookupMap.end() == it )
600 {
601 pCurFaceArray = new std::vector<Q3BSP::sQ3BSPFace*>;
602 m_MaterialLookupMap[ key ] = pCurFaceArray;
603 }
604 else
605 {
606 pCurFaceArray = (*it).second;
607 }
608 ai_assert( NULL != pCurFaceArray );
609 if ( NULL != pCurFaceArray )
610 {
611 pCurFaceArray->push_back( pQ3BSPFace );
612 }
613 }
614 }
616 // ------------------------------------------------------------------------------------------------
617 // Returns the next face.
618 aiFace *Q3BSPFileImporter::getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx )
619 {
620 aiFace *pFace = NULL;
621 if ( rFaceIdx < pMesh->mNumFaces )
622 {
623 pFace = &pMesh->mFaces[ rFaceIdx ];
624 rFaceIdx++;
625 }
626 else
627 {
628 pFace = NULL;
629 }
631 return pFace;
632 }
634 // ------------------------------------------------------------------------------------------------
635 // Imports a texture file.
636 bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel,
637 Q3BSP::Q3BSPZipArchive *pArchive, aiScene* /*pScene*/,
638 aiMaterial *pMatHelper, int textureId )
639 {
640 std::vector<std::string> supportedExtensions;
641 supportedExtensions.push_back( ".jpg" );
642 supportedExtensions.push_back( ".png" );
643 supportedExtensions.push_back( ".tga" );
644 if ( NULL == pArchive || NULL == pArchive || NULL == pMatHelper )
645 {
646 return false;
647 }
649 if ( textureId < 0 || textureId >= static_cast<int>( pModel->m_Textures.size() ) )
650 {
651 return false;
652 }
654 bool res = true;
655 sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ];
656 if ( NULL == pTexture )
657 return false;
659 std::string textureName, ext;
660 if ( expandFile( pArchive, pTexture->strName, supportedExtensions, textureName, ext ) )
661 {
662 IOStream *pTextureStream = pArchive->Open( textureName.c_str() );
663 if ( NULL != pTextureStream )
664 {
665 size_t texSize = pTextureStream->FileSize();
666 aiTexture *pTexture = new aiTexture;
667 pTexture->mHeight = 0;
668 pTexture->mWidth = texSize;
669 unsigned char *pData = new unsigned char[ pTexture->mWidth ];
670 size_t readSize = pTextureStream->Read( pData, sizeof( unsigned char ), pTexture->mWidth );
671 (void)readSize;
672 ai_assert( readSize == pTexture->mWidth );
673 pTexture->pcData = reinterpret_cast<aiTexel*>( pData );
674 pTexture->achFormatHint[ 0 ] = ext[ 1 ];
675 pTexture->achFormatHint[ 1 ] = ext[ 2 ];
676 pTexture->achFormatHint[ 2 ] = ext[ 3 ];
677 pTexture->achFormatHint[ 3 ] = '\0';
678 res = true;
680 aiString name;
681 name.data[ 0 ] = '*';
682 name.length = 1 + ASSIMP_itoa10( name.data + 1, MAXLEN-1, mTextures.size() );
684 pArchive->Close( pTextureStream );
686 pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
687 mTextures.push_back( pTexture );
688 }
689 else
690 {
691 // If it doesn't exist in the archive, it is probably just a reference to an external file.
692 // We'll leave it up to the user to figure out which extension the file has.
693 aiString name;
694 strncpy( name.data, pTexture->strName, sizeof name.data );
695 name.length = strlen( name.data );
696 pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
697 }
698 }
700 return res;
701 }
703 // ------------------------------------------------------------------------------------------------
704 // Imports a light map file.
705 bool Q3BSPFileImporter::importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
706 aiMaterial *pMatHelper, int lightmapId )
707 {
708 if ( NULL == pModel || NULL == pScene || NULL == pMatHelper )
709 {
710 return false;
711 }
713 if ( lightmapId < 0 || lightmapId >= static_cast<int>( pModel->m_Lightmaps.size() ) )
714 {
715 return false;
716 }
718 sQ3BSPLightmap *pLightMap = pModel->m_Lightmaps[ lightmapId ];
719 if ( NULL == pLightMap )
720 {
721 return false;
722 }
724 aiTexture *pTexture = new aiTexture;
726 pTexture->mWidth = CE_BSP_LIGHTMAPWIDTH;
727 pTexture->mHeight = CE_BSP_LIGHTMAPHEIGHT;
728 pTexture->pcData = new aiTexel[CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT];
730 ::memcpy( pTexture->pcData, pLightMap->bLMapData, pTexture->mWidth );
731 size_t p = 0;
732 for ( size_t i = 0; i < CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT; ++i )
733 {
734 pTexture->pcData[ i ].r = pLightMap->bLMapData[ p++ ];
735 pTexture->pcData[ i ].g = pLightMap->bLMapData[ p++ ];
736 pTexture->pcData[ i ].b = pLightMap->bLMapData[ p++ ];
737 pTexture->pcData[ i ].a = 0xFF;
738 }
740 aiString name;
741 name.data[ 0 ] = '*';
742 name.length = 1 + ASSIMP_itoa10( name.data + 1, MAXLEN-1, mTextures.size() );
744 pMatHelper->AddProperty( &name,AI_MATKEY_TEXTURE_LIGHTMAP( 1 ) );
745 mTextures.push_back( pTexture );
747 return true;
748 }
751 // ------------------------------------------------------------------------------------------------
752 // Will search for a supported extension.
753 bool Q3BSPFileImporter::expandFile( Q3BSP::Q3BSPZipArchive *pArchive, const std::string &rFilename,
754 const std::vector<std::string> &rExtList, std::string &rFile,
755 std::string &rExt )
756 {
757 ai_assert( NULL != pArchive );
758 ai_assert( !rFilename.empty() );
760 if ( rExtList.empty() )
761 {
762 rFile = rFilename;
763 rExt = "";
764 return true;
765 }
767 bool found = false;
768 for ( std::vector<std::string>::const_iterator it = rExtList.begin(); it != rExtList.end(); ++it )
769 {
770 const std::string textureName = rFilename + *it;
771 if ( pArchive->Exists( textureName.c_str() ) )
772 {
773 rExt = *it;
774 rFile = textureName;
775 found = true;
776 break;
777 }
778 }
780 return found;
781 }
783 // ------------------------------------------------------------------------------------------------
785 } // Namespace Assimp
787 #endif // ASSIMP_BUILD_NO_Q3BSP_IMPORTER