1 | /* |
2 | Open Asset Import Library (assimp) |
3 | ---------------------------------------------------------------------- |
4 | |
5 | Copyright (c) 2006-2017, assimp team |
6 | |
7 | All rights reserved. |
8 | |
9 | Redistribution and use of this software in source and binary forms, |
10 | with or without modification, are permitted provided that the |
11 | following conditions are met: |
12 | |
13 | * Redistributions of source code must retain the above |
14 | copyright notice, this list of conditions and the |
15 | following disclaimer. |
16 | |
17 | * Redistributions in binary form must reproduce the above |
18 | copyright notice, this list of conditions and the |
19 | following disclaimer in the documentation and/or other |
20 | materials provided with the distribution. |
21 | |
22 | * Neither the name of the assimp team, nor the names of its |
23 | contributors may be used to endorse or promote products |
24 | derived from this software without specific prior |
25 | written permission of the assimp team. |
26 | |
27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
28 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
29 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
30 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
31 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
32 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
33 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
34 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
35 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
36 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
37 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
38 | |
39 | ---------------------------------------------------------------------- |
40 | */ |
41 | |
42 | |
43 | #ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER |
44 | |
45 | #include "Q3BSPFileParser.h" |
46 | #include "Q3BSPFileData.h" |
47 | #include "Q3BSPZipArchive.h" |
48 | #include <vector> |
49 | #include <assimp/DefaultIOSystem.h> |
50 | #include <assimp/ai_assert.h> |
51 | |
52 | namespace Assimp { |
53 | |
54 | using namespace Q3BSP; |
55 | |
56 | // ------------------------------------------------------------------------------------------------ |
57 | Q3BSPFileParser::Q3BSPFileParser( const std::string &rMapName, Q3BSPZipArchive *pZipArchive ) : |
58 | m_sOffset( 0 ), |
59 | m_Data(), |
60 | m_pModel( NULL ), |
61 | m_pZipArchive( pZipArchive ) |
62 | { |
63 | ai_assert( NULL != m_pZipArchive ); |
64 | ai_assert( !rMapName.empty() ); |
65 | |
66 | if ( !readData( rMapName ) ) |
67 | return; |
68 | |
69 | m_pModel = new Q3BSPModel; |
70 | m_pModel->m_ModelName = rMapName; |
71 | if ( !parseFile() ) |
72 | { |
73 | delete m_pModel; |
74 | m_pModel = NULL; |
75 | } |
76 | } |
77 | |
78 | // ------------------------------------------------------------------------------------------------ |
79 | Q3BSPFileParser::~Q3BSPFileParser() |
80 | { |
81 | delete m_pModel; |
82 | m_pModel = NULL; |
83 | } |
84 | |
85 | // ------------------------------------------------------------------------------------------------ |
86 | Q3BSP::Q3BSPModel *Q3BSPFileParser::getModel() const |
87 | { |
88 | return m_pModel; |
89 | } |
90 | |
91 | // ------------------------------------------------------------------------------------------------ |
92 | bool Q3BSPFileParser::readData( const std::string &rMapName ) |
93 | { |
94 | if ( !m_pZipArchive->Exists( rMapName.c_str() ) ) |
95 | return false; |
96 | |
97 | IOStream *pMapFile = m_pZipArchive->Open( rMapName.c_str() ); |
98 | if ( NULL == pMapFile ) |
99 | return false; |
100 | |
101 | const size_t size = pMapFile->FileSize(); |
102 | m_Data.resize( size ); |
103 | |
104 | const size_t readSize = pMapFile->Read( &m_Data[0], sizeof( char ), size ); |
105 | if ( readSize != size ) |
106 | { |
107 | m_Data.clear(); |
108 | return false; |
109 | } |
110 | m_pZipArchive->Close( pMapFile ); |
111 | |
112 | return true; |
113 | } |
114 | |
115 | // ------------------------------------------------------------------------------------------------ |
116 | bool Q3BSPFileParser::parseFile() |
117 | { |
118 | if ( m_Data.empty() ) |
119 | { |
120 | return false; |
121 | } |
122 | |
123 | if ( !validateFormat() ) |
124 | { |
125 | return false; |
126 | } |
127 | |
128 | // Imports the dictionary of the level |
129 | getLumps(); |
130 | |
131 | // Conunt data and prepare model data |
132 | countLumps(); |
133 | |
134 | // Read in Vertices |
135 | getVertices(); |
136 | |
137 | // Read in Indices |
138 | getIndices(); |
139 | |
140 | // Read Faces |
141 | getFaces(); |
142 | |
143 | // Read Textures |
144 | getTextures(); |
145 | |
146 | // Read Lightmaps |
147 | getLightMaps(); |
148 | |
149 | // Load the entities |
150 | getEntities(); |
151 | |
152 | return true; |
153 | } |
154 | |
155 | // ------------------------------------------------------------------------------------------------ |
156 | bool Q3BSPFileParser::validateFormat() |
157 | { |
158 | sQ3BSPHeader *pHeader = (sQ3BSPHeader*) &m_Data[ 0 ]; |
159 | m_sOffset += sizeof( sQ3BSPHeader ); |
160 | |
161 | // Version and identify string validation |
162 | if (pHeader->strID[ 0 ] != 'I' || pHeader->strID[ 1 ] != 'B' || pHeader->strID[ 2 ] != 'S' |
163 | || pHeader->strID[ 3 ] != 'P') |
164 | { |
165 | return false; |
166 | } |
167 | |
168 | return true; |
169 | } |
170 | |
171 | // ------------------------------------------------------------------------------------------------ |
172 | void Q3BSPFileParser::getLumps() |
173 | { |
174 | size_t Offset = m_sOffset; |
175 | m_pModel->m_Lumps.resize( kMaxLumps ); |
176 | for ( size_t idx=0; idx < kMaxLumps; idx++ ) |
177 | { |
178 | sQ3BSPLump *pLump = new sQ3BSPLump; |
179 | memcpy( pLump, &m_Data[ Offset ], sizeof( sQ3BSPLump ) ); |
180 | Offset += sizeof( sQ3BSPLump ); |
181 | m_pModel->m_Lumps[ idx ] = pLump; |
182 | } |
183 | } |
184 | |
185 | // ------------------------------------------------------------------------------------------------ |
186 | void Q3BSPFileParser::countLumps() |
187 | { |
188 | m_pModel->m_Vertices.resize( m_pModel->m_Lumps[ kVertices ]->iSize / sizeof( sQ3BSPVertex ) ); |
189 | m_pModel->m_Indices.resize( m_pModel->m_Lumps[ kMeshVerts ]->iSize / sizeof( int ) ); |
190 | m_pModel->m_Faces.resize( m_pModel->m_Lumps[ kFaces ]->iSize / sizeof( sQ3BSPFace ) ); |
191 | m_pModel->m_Textures.resize( m_pModel->m_Lumps[ kTextures ]->iSize / sizeof( sQ3BSPTexture ) ); |
192 | m_pModel->m_Lightmaps.resize( m_pModel->m_Lumps[ kLightmaps ]->iSize / sizeof( sQ3BSPLightmap ) ); |
193 | } |
194 | |
195 | // ------------------------------------------------------------------------------------------------ |
196 | void Q3BSPFileParser::getVertices() |
197 | { |
198 | size_t Offset = m_pModel->m_Lumps[ kVertices ]->iOffset; |
199 | for ( size_t idx = 0; idx < m_pModel->m_Vertices.size(); idx++ ) |
200 | { |
201 | sQ3BSPVertex *pVertex = new sQ3BSPVertex; |
202 | memcpy( pVertex, &m_Data[ Offset ], sizeof( sQ3BSPVertex ) ); |
203 | Offset += sizeof( sQ3BSPVertex ); |
204 | m_pModel->m_Vertices[ idx ] = pVertex; |
205 | } |
206 | } |
207 | |
208 | // ------------------------------------------------------------------------------------------------ |
209 | void Q3BSPFileParser::getIndices() |
210 | { |
211 | ai_assert( NULL != m_pModel ); |
212 | |
213 | sQ3BSPLump *lump = m_pModel->m_Lumps[ kMeshVerts ]; |
214 | size_t Offset = (size_t) lump->iOffset; |
215 | const size_t nIndices = lump->iSize / sizeof( int ); |
216 | m_pModel->m_Indices.resize( nIndices ); |
217 | memcpy( &m_pModel->m_Indices[ 0 ], &m_Data[ Offset ], lump->iSize ); |
218 | } |
219 | |
220 | // ------------------------------------------------------------------------------------------------ |
221 | void Q3BSPFileParser::getFaces() |
222 | { |
223 | ai_assert( NULL != m_pModel ); |
224 | |
225 | size_t Offset = m_pModel->m_Lumps[ kFaces ]->iOffset; |
226 | for ( size_t idx = 0; idx < m_pModel->m_Faces.size(); idx++ ) |
227 | { |
228 | sQ3BSPFace *pFace = new sQ3BSPFace; |
229 | memcpy( pFace, &m_Data[ Offset ], sizeof( sQ3BSPFace ) ); |
230 | m_pModel->m_Faces[ idx ] = pFace; |
231 | Offset += sizeof( sQ3BSPFace ); |
232 | } |
233 | } |
234 | |
235 | // ------------------------------------------------------------------------------------------------ |
236 | void Q3BSPFileParser::getTextures() |
237 | { |
238 | ai_assert( NULL != m_pModel ); |
239 | |
240 | size_t Offset = m_pModel->m_Lumps[ kTextures ]->iOffset; |
241 | for ( size_t idx=0; idx < m_pModel->m_Textures.size(); idx++ ) |
242 | { |
243 | sQ3BSPTexture *pTexture = new sQ3BSPTexture; |
244 | memcpy( pTexture, &m_Data[ Offset ], sizeof(sQ3BSPTexture) ); |
245 | m_pModel->m_Textures[ idx ] = pTexture; |
246 | Offset += sizeof(sQ3BSPTexture); |
247 | } |
248 | } |
249 | |
250 | // ------------------------------------------------------------------------------------------------ |
251 | void Q3BSPFileParser::getLightMaps() |
252 | { |
253 | ai_assert( NULL != m_pModel ); |
254 | |
255 | size_t Offset = m_pModel->m_Lumps[kLightmaps]->iOffset; |
256 | for ( size_t idx=0; idx < m_pModel->m_Lightmaps.size(); idx++ ) |
257 | { |
258 | sQ3BSPLightmap *pLightmap = new sQ3BSPLightmap; |
259 | memcpy( pLightmap, &m_Data[ Offset ], sizeof( sQ3BSPLightmap ) ); |
260 | Offset += sizeof( sQ3BSPLightmap ); |
261 | m_pModel->m_Lightmaps[ idx ] = pLightmap; |
262 | } |
263 | } |
264 | |
265 | // ------------------------------------------------------------------------------------------------ |
266 | void Q3BSPFileParser::getEntities() |
267 | { |
268 | int size = m_pModel->m_Lumps[ kEntities ]->iSize; |
269 | m_pModel->m_EntityData.resize( size ); |
270 | if ( size > 0 ) |
271 | { |
272 | size_t Offset = m_pModel->m_Lumps[ kEntities ]->iOffset; |
273 | memcpy( &m_pModel->m_EntityData[ 0 ], &m_Data[ Offset ], sizeof( char ) * size ); |
274 | } |
275 | } |
276 | |
277 | // ------------------------------------------------------------------------------------------------ |
278 | |
279 | } // Namespace Assimp |
280 | |
281 | #endif // ASSIMP_BUILD_NO_Q3BSP_IMPORTER |
282 | |