rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 ---------------------------------------------------------------------------
|
nuclear@0
|
3 Open Asset Import Library (assimp)
|
nuclear@0
|
4 ---------------------------------------------------------------------------
|
nuclear@0
|
5
|
nuclear@0
|
6 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
7
|
nuclear@0
|
8 All rights reserved.
|
nuclear@0
|
9
|
nuclear@0
|
10 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
11 with or without modification, are permitted provided that the following
|
nuclear@0
|
12 conditions are met:
|
nuclear@0
|
13
|
nuclear@0
|
14 * Redistributions of source code must retain the above
|
nuclear@0
|
15 copyright notice, this list of conditions and the
|
nuclear@0
|
16 following disclaimer.
|
nuclear@0
|
17
|
nuclear@0
|
18 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
19 copyright notice, this list of conditions and the
|
nuclear@0
|
20 following disclaimer in the documentation and/or other
|
nuclear@0
|
21 materials provided with the distribution.
|
nuclear@0
|
22
|
nuclear@0
|
23 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
24 contributors may be used to endorse or promote products
|
nuclear@0
|
25 derived from this software without specific prior
|
nuclear@0
|
26 written permission of the assimp team.
|
nuclear@0
|
27
|
nuclear@0
|
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
39 ---------------------------------------------------------------------------
|
nuclear@0
|
40 */
|
nuclear@0
|
41
|
nuclear@0
|
42 #include "AssimpPCH.h"
|
nuclear@0
|
43 #ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
|
nuclear@0
|
44
|
nuclear@0
|
45 #include "ObjFileParser.h"
|
nuclear@0
|
46 #include "ObjFileMtlImporter.h"
|
nuclear@0
|
47 #include "ObjTools.h"
|
nuclear@0
|
48 #include "ObjFileData.h"
|
nuclear@0
|
49 #include "ParsingUtils.h"
|
nuclear@0
|
50 #include "assimp/types.h"
|
nuclear@0
|
51 #include "DefaultIOSystem.h"
|
nuclear@0
|
52
|
nuclear@0
|
53 namespace Assimp
|
nuclear@0
|
54 {
|
nuclear@0
|
55
|
nuclear@0
|
56 // -------------------------------------------------------------------
|
nuclear@0
|
57 const std::string ObjFileParser::DEFAULT_MATERIAL = AI_DEFAULT_MATERIAL_NAME;
|
nuclear@0
|
58
|
nuclear@0
|
59 // -------------------------------------------------------------------
|
nuclear@0
|
60 // Constructor with loaded data and directories.
|
nuclear@0
|
61 ObjFileParser::ObjFileParser(std::vector<char> &Data,const std::string &strModelName, IOSystem *io ) :
|
nuclear@0
|
62 m_DataIt(Data.begin()),
|
nuclear@0
|
63 m_DataItEnd(Data.end()),
|
nuclear@0
|
64 m_pModel(NULL),
|
nuclear@0
|
65 m_uiLine(0),
|
nuclear@0
|
66 m_pIO( io )
|
nuclear@0
|
67 {
|
nuclear@0
|
68 std::fill_n(m_buffer,BUFFERSIZE,0);
|
nuclear@0
|
69
|
nuclear@0
|
70 // Create the model instance to store all the data
|
nuclear@0
|
71 m_pModel = new ObjFile::Model();
|
nuclear@0
|
72 m_pModel->m_ModelName = strModelName;
|
nuclear@0
|
73
|
nuclear@0
|
74 m_pModel->m_pDefaultMaterial = new ObjFile::Material();
|
nuclear@0
|
75 m_pModel->m_pDefaultMaterial->MaterialName.Set( DEFAULT_MATERIAL );
|
nuclear@0
|
76 m_pModel->m_MaterialLib.push_back( DEFAULT_MATERIAL );
|
nuclear@0
|
77 m_pModel->m_MaterialMap[ DEFAULT_MATERIAL ] = m_pModel->m_pDefaultMaterial;
|
nuclear@0
|
78
|
nuclear@0
|
79 // Start parsing the file
|
nuclear@0
|
80 parseFile();
|
nuclear@0
|
81 }
|
nuclear@0
|
82
|
nuclear@0
|
83 // -------------------------------------------------------------------
|
nuclear@0
|
84 // Destructor
|
nuclear@0
|
85 ObjFileParser::~ObjFileParser()
|
nuclear@0
|
86 {
|
nuclear@0
|
87 /*delete m_pModel->m_pDefaultMaterial;
|
nuclear@0
|
88 m_pModel->m_pDefaultMaterial = NULL;*/
|
nuclear@0
|
89
|
nuclear@0
|
90 delete m_pModel;
|
nuclear@0
|
91 m_pModel = NULL;
|
nuclear@0
|
92 }
|
nuclear@0
|
93
|
nuclear@0
|
94 // -------------------------------------------------------------------
|
nuclear@0
|
95 // Returns a pointer to the model instance.
|
nuclear@0
|
96 ObjFile::Model *ObjFileParser::GetModel() const
|
nuclear@0
|
97 {
|
nuclear@0
|
98 return m_pModel;
|
nuclear@0
|
99 }
|
nuclear@0
|
100
|
nuclear@0
|
101 // -------------------------------------------------------------------
|
nuclear@0
|
102 // File parsing method.
|
nuclear@0
|
103 void ObjFileParser::parseFile()
|
nuclear@0
|
104 {
|
nuclear@0
|
105 if (m_DataIt == m_DataItEnd)
|
nuclear@0
|
106 return;
|
nuclear@0
|
107
|
nuclear@0
|
108 while (m_DataIt != m_DataItEnd)
|
nuclear@0
|
109 {
|
nuclear@0
|
110 switch (*m_DataIt)
|
nuclear@0
|
111 {
|
nuclear@0
|
112 case 'v': // Parse a vertex texture coordinate
|
nuclear@0
|
113 {
|
nuclear@0
|
114 ++m_DataIt;
|
nuclear@0
|
115 if (*m_DataIt == ' ')
|
nuclear@0
|
116 {
|
nuclear@0
|
117 // Read in vertex definition
|
nuclear@0
|
118 getVector3(m_pModel->m_Vertices);
|
nuclear@0
|
119 }
|
nuclear@0
|
120 else if (*m_DataIt == 't')
|
nuclear@0
|
121 {
|
nuclear@0
|
122 // Read in texture coordinate (2D)
|
nuclear@0
|
123 ++m_DataIt;
|
nuclear@0
|
124 getVector2(m_pModel->m_TextureCoord);
|
nuclear@0
|
125 }
|
nuclear@0
|
126 else if (*m_DataIt == 'n')
|
nuclear@0
|
127 {
|
nuclear@0
|
128 // Read in normal vector definition
|
nuclear@0
|
129 ++m_DataIt;
|
nuclear@0
|
130 getVector3( m_pModel->m_Normals );
|
nuclear@0
|
131 }
|
nuclear@0
|
132 }
|
nuclear@0
|
133 break;
|
nuclear@0
|
134
|
nuclear@0
|
135 case 'p': // Parse a face, line or point statement
|
nuclear@0
|
136 case 'l':
|
nuclear@0
|
137 case 'f':
|
nuclear@0
|
138 {
|
nuclear@0
|
139 getFace(*m_DataIt == 'f' ? aiPrimitiveType_POLYGON : (*m_DataIt == 'l'
|
nuclear@0
|
140 ? aiPrimitiveType_LINE : aiPrimitiveType_POINT));
|
nuclear@0
|
141 }
|
nuclear@0
|
142 break;
|
nuclear@0
|
143
|
nuclear@0
|
144 case '#': // Parse a comment
|
nuclear@0
|
145 {
|
nuclear@0
|
146 getComment();
|
nuclear@0
|
147 }
|
nuclear@0
|
148 break;
|
nuclear@0
|
149
|
nuclear@0
|
150 case 'u': // Parse a material desc. setter
|
nuclear@0
|
151 {
|
nuclear@0
|
152 getMaterialDesc();
|
nuclear@0
|
153 }
|
nuclear@0
|
154 break;
|
nuclear@0
|
155
|
nuclear@0
|
156 case 'm': // Parse a material library
|
nuclear@0
|
157 {
|
nuclear@0
|
158 getMaterialLib();
|
nuclear@0
|
159 }
|
nuclear@0
|
160 break;
|
nuclear@0
|
161
|
nuclear@0
|
162 case 'g': // Parse group name
|
nuclear@0
|
163 {
|
nuclear@0
|
164 getGroupName();
|
nuclear@0
|
165 }
|
nuclear@0
|
166 break;
|
nuclear@0
|
167
|
nuclear@0
|
168 case 's': // Parse group number
|
nuclear@0
|
169 {
|
nuclear@0
|
170 getGroupNumber();
|
nuclear@0
|
171 }
|
nuclear@0
|
172 break;
|
nuclear@0
|
173
|
nuclear@0
|
174 case 'o': // Parse object name
|
nuclear@0
|
175 {
|
nuclear@0
|
176 getObjectName();
|
nuclear@0
|
177 }
|
nuclear@0
|
178 break;
|
nuclear@0
|
179
|
nuclear@0
|
180 default:
|
nuclear@0
|
181 {
|
nuclear@0
|
182 m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
nuclear@0
|
183 }
|
nuclear@0
|
184 break;
|
nuclear@0
|
185 }
|
nuclear@0
|
186 }
|
nuclear@0
|
187 }
|
nuclear@0
|
188
|
nuclear@0
|
189 // -------------------------------------------------------------------
|
nuclear@0
|
190 // Copy the next word in a temporary buffer
|
nuclear@0
|
191 void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
|
nuclear@0
|
192 {
|
nuclear@0
|
193 size_t index = 0;
|
nuclear@0
|
194 m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
|
nuclear@0
|
195 while ( m_DataIt != m_DataItEnd && !isSeparator(*m_DataIt) )
|
nuclear@0
|
196 {
|
nuclear@0
|
197 pBuffer[index] = *m_DataIt;
|
nuclear@0
|
198 index++;
|
nuclear@0
|
199 if (index == length-1)
|
nuclear@0
|
200 break;
|
nuclear@0
|
201 ++m_DataIt;
|
nuclear@0
|
202 }
|
nuclear@0
|
203 pBuffer[index] = '\0';
|
nuclear@0
|
204 }
|
nuclear@0
|
205
|
nuclear@0
|
206 // -------------------------------------------------------------------
|
nuclear@0
|
207 // Copy the next line into a temporary buffer
|
nuclear@0
|
208 void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
|
nuclear@0
|
209 {
|
nuclear@0
|
210 size_t index = 0;
|
nuclear@0
|
211 while (m_DataIt != m_DataItEnd)
|
nuclear@0
|
212 {
|
nuclear@0
|
213 if (*m_DataIt == '\n' || *m_DataIt == '\r' || index == length-1)
|
nuclear@0
|
214 break;
|
nuclear@0
|
215
|
nuclear@0
|
216 pBuffer[ index ] = *m_DataIt;
|
nuclear@0
|
217 ++index;
|
nuclear@0
|
218 ++m_DataIt;
|
nuclear@0
|
219 }
|
nuclear@0
|
220 pBuffer[ index ] = '\0';
|
nuclear@0
|
221 }
|
nuclear@0
|
222
|
nuclear@0
|
223 // -------------------------------------------------------------------
|
nuclear@0
|
224 // Get values for a new 3D vector instance
|
nuclear@0
|
225 void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array)
|
nuclear@0
|
226 {
|
nuclear@0
|
227 float x, y, z;
|
nuclear@0
|
228 copyNextWord(m_buffer, BUFFERSIZE);
|
nuclear@0
|
229 x = (float) fast_atof(m_buffer);
|
nuclear@0
|
230
|
nuclear@0
|
231 copyNextWord(m_buffer, BUFFERSIZE);
|
nuclear@0
|
232 y = (float) fast_atof(m_buffer);
|
nuclear@0
|
233
|
nuclear@0
|
234 copyNextWord(m_buffer, BUFFERSIZE);
|
nuclear@0
|
235 z = (float) fast_atof(m_buffer);
|
nuclear@0
|
236
|
nuclear@0
|
237 point3d_array.push_back( aiVector3D( x, y, z ) );
|
nuclear@0
|
238 //skipLine();
|
nuclear@0
|
239 m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
nuclear@0
|
240 }
|
nuclear@0
|
241
|
nuclear@0
|
242 // -------------------------------------------------------------------
|
nuclear@0
|
243 // Get values for a new 2D vector instance
|
nuclear@0
|
244 void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array )
|
nuclear@0
|
245 {
|
nuclear@0
|
246 float x, y;
|
nuclear@0
|
247 copyNextWord(m_buffer, BUFFERSIZE);
|
nuclear@0
|
248 x = (float) fast_atof(m_buffer);
|
nuclear@0
|
249
|
nuclear@0
|
250 copyNextWord(m_buffer, BUFFERSIZE);
|
nuclear@0
|
251 y = (float) fast_atof(m_buffer);
|
nuclear@0
|
252
|
nuclear@0
|
253 point2d_array.push_back(aiVector2D(x, y));
|
nuclear@0
|
254
|
nuclear@0
|
255 m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
nuclear@0
|
256 }
|
nuclear@0
|
257
|
nuclear@0
|
258 // -------------------------------------------------------------------
|
nuclear@0
|
259 // Get values for a new face instance
|
nuclear@0
|
260 void ObjFileParser::getFace(aiPrimitiveType type)
|
nuclear@0
|
261 {
|
nuclear@0
|
262 copyNextLine(m_buffer, BUFFERSIZE);
|
nuclear@0
|
263 if (m_DataIt == m_DataItEnd)
|
nuclear@0
|
264 return;
|
nuclear@0
|
265
|
nuclear@0
|
266 char *pPtr = m_buffer;
|
nuclear@0
|
267 char *pEnd = &pPtr[BUFFERSIZE];
|
nuclear@0
|
268 pPtr = getNextToken<char*>(pPtr, pEnd);
|
nuclear@0
|
269 if (pPtr == pEnd || *pPtr == '\0')
|
nuclear@0
|
270 return;
|
nuclear@0
|
271
|
nuclear@0
|
272 std::vector<unsigned int> *pIndices = new std::vector<unsigned int>;
|
nuclear@0
|
273 std::vector<unsigned int> *pTexID = new std::vector<unsigned int>;
|
nuclear@0
|
274 std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
|
nuclear@0
|
275 bool hasNormal = false;
|
nuclear@0
|
276
|
nuclear@0
|
277 const bool vt = (!m_pModel->m_TextureCoord.empty());
|
nuclear@0
|
278 const bool vn = (!m_pModel->m_Normals.empty());
|
nuclear@0
|
279 int iStep = 0, iPos = 0;
|
nuclear@0
|
280 while (pPtr != pEnd)
|
nuclear@0
|
281 {
|
nuclear@0
|
282 iStep = 1;
|
nuclear@0
|
283
|
nuclear@0
|
284 if (IsLineEnd(*pPtr))
|
nuclear@0
|
285 break;
|
nuclear@0
|
286
|
nuclear@0
|
287 if (*pPtr=='/' )
|
nuclear@0
|
288 {
|
nuclear@0
|
289 if (type == aiPrimitiveType_POINT) {
|
nuclear@0
|
290 DefaultLogger::get()->error("Obj: Separator unexpected in point statement");
|
nuclear@0
|
291 }
|
nuclear@0
|
292 if (iPos == 0)
|
nuclear@0
|
293 {
|
nuclear@0
|
294 //if there are no texture coordinates in the file, but normals
|
nuclear@0
|
295 if (!vt && vn) {
|
nuclear@0
|
296 iPos = 1;
|
nuclear@0
|
297 iStep++;
|
nuclear@0
|
298 }
|
nuclear@0
|
299 }
|
nuclear@0
|
300 iPos++;
|
nuclear@0
|
301 }
|
nuclear@0
|
302 else if ( isSeparator(*pPtr) )
|
nuclear@0
|
303 {
|
nuclear@0
|
304 iPos = 0;
|
nuclear@0
|
305 }
|
nuclear@0
|
306 else
|
nuclear@0
|
307 {
|
nuclear@0
|
308 //OBJ USES 1 Base ARRAYS!!!!
|
nuclear@0
|
309 const int iVal = atoi( pPtr );
|
nuclear@0
|
310 int tmp = iVal;
|
nuclear@0
|
311 while ( ( tmp = tmp / 10 )!=0 )
|
nuclear@0
|
312 ++iStep;
|
nuclear@0
|
313
|
nuclear@0
|
314 if ( iVal > 0 )
|
nuclear@0
|
315 {
|
nuclear@0
|
316 // Store parsed index
|
nuclear@0
|
317 if ( 0 == iPos )
|
nuclear@0
|
318 {
|
nuclear@0
|
319 pIndices->push_back( iVal-1 );
|
nuclear@0
|
320 }
|
nuclear@0
|
321 else if ( 1 == iPos )
|
nuclear@0
|
322 {
|
nuclear@0
|
323 pTexID->push_back( iVal-1 );
|
nuclear@0
|
324 }
|
nuclear@0
|
325 else if ( 2 == iPos )
|
nuclear@0
|
326 {
|
nuclear@0
|
327 pNormalID->push_back( iVal-1 );
|
nuclear@0
|
328 hasNormal = true;
|
nuclear@0
|
329 }
|
nuclear@0
|
330 else
|
nuclear@0
|
331 {
|
nuclear@0
|
332 reportErrorTokenInFace();
|
nuclear@0
|
333 }
|
nuclear@0
|
334 }
|
nuclear@0
|
335 }
|
nuclear@0
|
336 pPtr += iStep;
|
nuclear@0
|
337 }
|
nuclear@0
|
338
|
nuclear@0
|
339 if ( pIndices->empty() )
|
nuclear@0
|
340 {
|
nuclear@0
|
341 DefaultLogger::get()->error("Obj: Ignoring empty face");
|
nuclear@0
|
342 m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
nuclear@0
|
343 return;
|
nuclear@0
|
344 }
|
nuclear@0
|
345
|
nuclear@0
|
346 ObjFile::Face *face = new ObjFile::Face( pIndices, pNormalID, pTexID, type );
|
nuclear@0
|
347
|
nuclear@0
|
348 // Set active material, if one set
|
nuclear@0
|
349 if (NULL != m_pModel->m_pCurrentMaterial)
|
nuclear@0
|
350 face->m_pMaterial = m_pModel->m_pCurrentMaterial;
|
nuclear@0
|
351 else
|
nuclear@0
|
352 face->m_pMaterial = m_pModel->m_pDefaultMaterial;
|
nuclear@0
|
353
|
nuclear@0
|
354 // Create a default object, if nothing is there
|
nuclear@0
|
355 if ( NULL == m_pModel->m_pCurrent )
|
nuclear@0
|
356 createObject( "defaultobject" );
|
nuclear@0
|
357
|
nuclear@0
|
358 // Assign face to mesh
|
nuclear@0
|
359 if ( NULL == m_pModel->m_pCurrentMesh )
|
nuclear@0
|
360 {
|
nuclear@0
|
361 createMesh();
|
nuclear@0
|
362 }
|
nuclear@0
|
363
|
nuclear@0
|
364 // Store the face
|
nuclear@0
|
365 m_pModel->m_pCurrentMesh->m_Faces.push_back( face );
|
nuclear@0
|
366 m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int)face->m_pVertices->size();
|
nuclear@0
|
367 m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int)face->m_pTexturCoords[0].size();
|
nuclear@0
|
368 if( !m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal )
|
nuclear@0
|
369 {
|
nuclear@0
|
370 m_pModel->m_pCurrentMesh->m_hasNormals = true;
|
nuclear@0
|
371 }
|
nuclear@0
|
372 // Skip the rest of the line
|
nuclear@0
|
373 m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
nuclear@0
|
374 }
|
nuclear@0
|
375
|
nuclear@0
|
376 // -------------------------------------------------------------------
|
nuclear@0
|
377 // Get values for a new material description
|
nuclear@0
|
378 void ObjFileParser::getMaterialDesc()
|
nuclear@0
|
379 {
|
nuclear@0
|
380 // Each material request a new object.
|
nuclear@0
|
381 // Sometimes the object is already created (see 'o' tag by example), but it is not initialized !
|
nuclear@0
|
382 // So, we create a new object only if the current on is already initialized !
|
nuclear@0
|
383 if (m_pModel->m_pCurrent != NULL &&
|
nuclear@0
|
384 ( m_pModel->m_pCurrent->m_Meshes.size() > 1 ||
|
nuclear@0
|
385 (m_pModel->m_pCurrent->m_Meshes.size() == 1 && m_pModel->m_Meshes[m_pModel->m_pCurrent->m_Meshes[0]]->m_Faces.size() != 0) )
|
nuclear@0
|
386 )
|
nuclear@0
|
387 m_pModel->m_pCurrent = NULL;
|
nuclear@0
|
388
|
nuclear@0
|
389 // Get next data for material data
|
nuclear@0
|
390 m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
nuclear@0
|
391 if (m_DataIt == m_DataItEnd)
|
nuclear@0
|
392 return;
|
nuclear@0
|
393
|
nuclear@0
|
394 char *pStart = &(*m_DataIt);
|
nuclear@0
|
395 while ( m_DataIt != m_DataItEnd && !isSeparator(*m_DataIt) )
|
nuclear@0
|
396 ++m_DataIt;
|
nuclear@0
|
397
|
nuclear@0
|
398 // Get name
|
nuclear@0
|
399 std::string strName(pStart, &(*m_DataIt));
|
nuclear@0
|
400 if ( strName.empty())
|
nuclear@0
|
401 return;
|
nuclear@0
|
402
|
nuclear@0
|
403 // Search for material
|
nuclear@0
|
404 std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strName );
|
nuclear@0
|
405 if ( it == m_pModel->m_MaterialMap.end() )
|
nuclear@0
|
406 {
|
nuclear@0
|
407 // Not found, use default material
|
nuclear@0
|
408 m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
|
nuclear@0
|
409 DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping");
|
nuclear@0
|
410 }
|
nuclear@0
|
411 else
|
nuclear@0
|
412 {
|
nuclear@0
|
413 // Found, using detected material
|
nuclear@0
|
414 m_pModel->m_pCurrentMaterial = (*it).second;
|
nuclear@0
|
415 if ( needsNewMesh( strName ))
|
nuclear@0
|
416 {
|
nuclear@0
|
417 createMesh();
|
nuclear@0
|
418 }
|
nuclear@0
|
419 m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strName );
|
nuclear@0
|
420 }
|
nuclear@0
|
421
|
nuclear@0
|
422 // Skip rest of line
|
nuclear@0
|
423 m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
nuclear@0
|
424 }
|
nuclear@0
|
425
|
nuclear@0
|
426 // -------------------------------------------------------------------
|
nuclear@0
|
427 // Get a comment, values will be skipped
|
nuclear@0
|
428 void ObjFileParser::getComment()
|
nuclear@0
|
429 {
|
nuclear@0
|
430 while (m_DataIt != m_DataItEnd)
|
nuclear@0
|
431 {
|
nuclear@0
|
432 if ( '\n' == (*m_DataIt))
|
nuclear@0
|
433 {
|
nuclear@0
|
434 ++m_DataIt;
|
nuclear@0
|
435 break;
|
nuclear@0
|
436 }
|
nuclear@0
|
437 else
|
nuclear@0
|
438 {
|
nuclear@0
|
439 ++m_DataIt;
|
nuclear@0
|
440 }
|
nuclear@0
|
441 }
|
nuclear@0
|
442 }
|
nuclear@0
|
443
|
nuclear@0
|
444 // -------------------------------------------------------------------
|
nuclear@0
|
445 // Get material library from file.
|
nuclear@0
|
446 void ObjFileParser::getMaterialLib()
|
nuclear@0
|
447 {
|
nuclear@0
|
448 // Translate tuple
|
nuclear@0
|
449 m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
nuclear@0
|
450 if (m_DataIt == m_DataItEnd)
|
nuclear@0
|
451 return;
|
nuclear@0
|
452
|
nuclear@0
|
453 char *pStart = &(*m_DataIt);
|
nuclear@0
|
454 while (m_DataIt != m_DataItEnd && !isNewLine(*m_DataIt))
|
nuclear@0
|
455 m_DataIt++;
|
nuclear@0
|
456
|
nuclear@0
|
457 // Check for existence
|
nuclear@0
|
458 const std::string strMatName(pStart, &(*m_DataIt));
|
nuclear@0
|
459 IOStream *pFile = m_pIO->Open(strMatName);
|
nuclear@0
|
460
|
nuclear@0
|
461 if (!pFile )
|
nuclear@0
|
462 {
|
nuclear@0
|
463 DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName);
|
nuclear@0
|
464 m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
nuclear@0
|
465 return;
|
nuclear@0
|
466 }
|
nuclear@0
|
467
|
nuclear@0
|
468 // Import material library data from file
|
nuclear@0
|
469 std::vector<char> buffer;
|
nuclear@0
|
470 BaseImporter::TextFileToBuffer(pFile,buffer);
|
nuclear@0
|
471 m_pIO->Close( pFile );
|
nuclear@0
|
472
|
nuclear@0
|
473 // Importing the material library
|
nuclear@0
|
474 ObjFileMtlImporter mtlImporter( buffer, strMatName, m_pModel );
|
nuclear@0
|
475 }
|
nuclear@0
|
476
|
nuclear@0
|
477 // -------------------------------------------------------------------
|
nuclear@0
|
478 // Set a new material definition as the current material.
|
nuclear@0
|
479 void ObjFileParser::getNewMaterial()
|
nuclear@0
|
480 {
|
nuclear@0
|
481 m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
nuclear@0
|
482 m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
|
nuclear@0
|
483 if ( m_DataIt == m_DataItEnd )
|
nuclear@0
|
484 return;
|
nuclear@0
|
485
|
nuclear@0
|
486 char *pStart = &(*m_DataIt);
|
nuclear@0
|
487 std::string strMat( pStart, *m_DataIt );
|
nuclear@0
|
488 while ( m_DataIt != m_DataItEnd && isSeparator( *m_DataIt ) )
|
nuclear@0
|
489 m_DataIt++;
|
nuclear@0
|
490 std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
|
nuclear@0
|
491 if ( it == m_pModel->m_MaterialMap.end() )
|
nuclear@0
|
492 {
|
nuclear@0
|
493 // Show a warning, if material was not found
|
nuclear@0
|
494 DefaultLogger::get()->warn("OBJ: Unsupported material requested: " + strMat);
|
nuclear@0
|
495 m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
|
nuclear@0
|
496 }
|
nuclear@0
|
497 else
|
nuclear@0
|
498 {
|
nuclear@0
|
499 // Set new material
|
nuclear@0
|
500 if ( needsNewMesh( strMat ) )
|
nuclear@0
|
501 {
|
nuclear@0
|
502 createMesh();
|
nuclear@0
|
503 }
|
nuclear@0
|
504 m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strMat );
|
nuclear@0
|
505 }
|
nuclear@0
|
506
|
nuclear@0
|
507 m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
nuclear@0
|
508 }
|
nuclear@0
|
509
|
nuclear@0
|
510 // -------------------------------------------------------------------
|
nuclear@0
|
511 int ObjFileParser::getMaterialIndex( const std::string &strMaterialName )
|
nuclear@0
|
512 {
|
nuclear@0
|
513 int mat_index = -1;
|
nuclear@0
|
514 if ( strMaterialName.empty() )
|
nuclear@0
|
515 return mat_index;
|
nuclear@0
|
516 for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index)
|
nuclear@0
|
517 {
|
nuclear@0
|
518 if ( strMaterialName == m_pModel->m_MaterialLib[ index ])
|
nuclear@0
|
519 {
|
nuclear@0
|
520 mat_index = (int)index;
|
nuclear@0
|
521 break;
|
nuclear@0
|
522 }
|
nuclear@0
|
523 }
|
nuclear@0
|
524 return mat_index;
|
nuclear@0
|
525 }
|
nuclear@0
|
526
|
nuclear@0
|
527 // -------------------------------------------------------------------
|
nuclear@0
|
528 // Getter for a group name.
|
nuclear@0
|
529 void ObjFileParser::getGroupName()
|
nuclear@0
|
530 {
|
nuclear@0
|
531 std::string strGroupName;
|
nuclear@0
|
532
|
nuclear@0
|
533 m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName);
|
nuclear@0
|
534 if ( isEndOfBuffer( m_DataIt, m_DataItEnd ) )
|
nuclear@0
|
535 return;
|
nuclear@0
|
536
|
nuclear@0
|
537 // Change active group, if necessary
|
nuclear@0
|
538 if ( m_pModel->m_strActiveGroup != strGroupName )
|
nuclear@0
|
539 {
|
nuclear@0
|
540 // Search for already existing entry
|
nuclear@0
|
541 ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(strGroupName);
|
nuclear@0
|
542
|
nuclear@0
|
543 // We are mapping groups into the object structure
|
nuclear@0
|
544 createObject( strGroupName );
|
nuclear@0
|
545
|
nuclear@0
|
546 // New group name, creating a new entry
|
nuclear@0
|
547 if (it == m_pModel->m_Groups.end())
|
nuclear@0
|
548 {
|
nuclear@0
|
549 std::vector<unsigned int> *pFaceIDArray = new std::vector<unsigned int>;
|
nuclear@0
|
550 m_pModel->m_Groups[ strGroupName ] = pFaceIDArray;
|
nuclear@0
|
551 m_pModel->m_pGroupFaceIDs = (pFaceIDArray);
|
nuclear@0
|
552 }
|
nuclear@0
|
553 else
|
nuclear@0
|
554 {
|
nuclear@0
|
555 m_pModel->m_pGroupFaceIDs = (*it).second;
|
nuclear@0
|
556 }
|
nuclear@0
|
557 m_pModel->m_strActiveGroup = strGroupName;
|
nuclear@0
|
558 }
|
nuclear@0
|
559 m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
nuclear@0
|
560 }
|
nuclear@0
|
561
|
nuclear@0
|
562 // -------------------------------------------------------------------
|
nuclear@0
|
563 // Not supported
|
nuclear@0
|
564 void ObjFileParser::getGroupNumber()
|
nuclear@0
|
565 {
|
nuclear@0
|
566 // Not used
|
nuclear@0
|
567
|
nuclear@0
|
568 m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
nuclear@0
|
569 }
|
nuclear@0
|
570
|
nuclear@0
|
571 // -------------------------------------------------------------------
|
nuclear@0
|
572 // Stores values for a new object instance, name will be used to
|
nuclear@0
|
573 // identify it.
|
nuclear@0
|
574 void ObjFileParser::getObjectName()
|
nuclear@0
|
575 {
|
nuclear@0
|
576 m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
nuclear@0
|
577 if (m_DataIt == m_DataItEnd)
|
nuclear@0
|
578 return;
|
nuclear@0
|
579 char *pStart = &(*m_DataIt);
|
nuclear@0
|
580 while ( m_DataIt != m_DataItEnd && !isSeparator( *m_DataIt ) )
|
nuclear@0
|
581 ++m_DataIt;
|
nuclear@0
|
582
|
nuclear@0
|
583 std::string strObjectName(pStart, &(*m_DataIt));
|
nuclear@0
|
584 if (!strObjectName.empty())
|
nuclear@0
|
585 {
|
nuclear@0
|
586 // Reset current object
|
nuclear@0
|
587 m_pModel->m_pCurrent = NULL;
|
nuclear@0
|
588
|
nuclear@0
|
589 // Search for actual object
|
nuclear@0
|
590 for (std::vector<ObjFile::Object*>::const_iterator it = m_pModel->m_Objects.begin();
|
nuclear@0
|
591 it != m_pModel->m_Objects.end();
|
nuclear@0
|
592 ++it)
|
nuclear@0
|
593 {
|
nuclear@0
|
594 if ((*it)->m_strObjName == strObjectName)
|
nuclear@0
|
595 {
|
nuclear@0
|
596 m_pModel->m_pCurrent = *it;
|
nuclear@0
|
597 break;
|
nuclear@0
|
598 }
|
nuclear@0
|
599 }
|
nuclear@0
|
600
|
nuclear@0
|
601 // Allocate a new object, if current one was not found before
|
nuclear@0
|
602 if ( NULL == m_pModel->m_pCurrent )
|
nuclear@0
|
603 createObject(strObjectName);
|
nuclear@0
|
604 }
|
nuclear@0
|
605 m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
nuclear@0
|
606 }
|
nuclear@0
|
607 // -------------------------------------------------------------------
|
nuclear@0
|
608 // Creates a new object instance
|
nuclear@0
|
609 void ObjFileParser::createObject(const std::string &strObjectName)
|
nuclear@0
|
610 {
|
nuclear@0
|
611 ai_assert( NULL != m_pModel );
|
nuclear@0
|
612 //ai_assert( !strObjectName.empty() );
|
nuclear@0
|
613
|
nuclear@0
|
614 m_pModel->m_pCurrent = new ObjFile::Object;
|
nuclear@0
|
615 m_pModel->m_pCurrent->m_strObjName = strObjectName;
|
nuclear@0
|
616 m_pModel->m_Objects.push_back( m_pModel->m_pCurrent );
|
nuclear@0
|
617
|
nuclear@0
|
618
|
nuclear@0
|
619 createMesh();
|
nuclear@0
|
620
|
nuclear@0
|
621 if( m_pModel->m_pCurrentMaterial )
|
nuclear@0
|
622 {
|
nuclear@0
|
623 m_pModel->m_pCurrentMesh->m_uiMaterialIndex =
|
nuclear@0
|
624 getMaterialIndex( m_pModel->m_pCurrentMaterial->MaterialName.data );
|
nuclear@0
|
625 m_pModel->m_pCurrentMesh->m_pMaterial = m_pModel->m_pCurrentMaterial;
|
nuclear@0
|
626 }
|
nuclear@0
|
627 }
|
nuclear@0
|
628 // -------------------------------------------------------------------
|
nuclear@0
|
629 // Creates a new mesh
|
nuclear@0
|
630 void ObjFileParser::createMesh()
|
nuclear@0
|
631 {
|
nuclear@0
|
632 ai_assert( NULL != m_pModel );
|
nuclear@0
|
633 m_pModel->m_pCurrentMesh = new ObjFile::Mesh;
|
nuclear@0
|
634 m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh );
|
nuclear@0
|
635 unsigned int meshId = m_pModel->m_Meshes.size()-1;
|
nuclear@0
|
636 if ( NULL != m_pModel->m_pCurrent )
|
nuclear@0
|
637 {
|
nuclear@0
|
638 m_pModel->m_pCurrent->m_Meshes.push_back( meshId );
|
nuclear@0
|
639 }
|
nuclear@0
|
640 else
|
nuclear@0
|
641 {
|
nuclear@0
|
642 DefaultLogger::get()->error("OBJ: No object detected to attach a new mesh instance.");
|
nuclear@0
|
643 }
|
nuclear@0
|
644 }
|
nuclear@0
|
645
|
nuclear@0
|
646 // -------------------------------------------------------------------
|
nuclear@0
|
647 // Returns true, if a new mesh must be created.
|
nuclear@0
|
648 bool ObjFileParser::needsNewMesh( const std::string &rMaterialName )
|
nuclear@0
|
649 {
|
nuclear@0
|
650 if(m_pModel->m_pCurrentMesh == 0)
|
nuclear@0
|
651 {
|
nuclear@0
|
652 // No mesh data yet
|
nuclear@0
|
653 return true;
|
nuclear@0
|
654 }
|
nuclear@0
|
655 bool newMat = false;
|
nuclear@0
|
656 int matIdx = getMaterialIndex( rMaterialName );
|
nuclear@0
|
657 int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex;
|
nuclear@0
|
658 if ( curMatIdx != int(ObjFile::Mesh::NoMaterial) || curMatIdx != matIdx )
|
nuclear@0
|
659 {
|
nuclear@0
|
660 // New material -> only one material per mesh, so we need to create a new
|
nuclear@0
|
661 // material
|
nuclear@0
|
662 newMat = true;
|
nuclear@0
|
663 }
|
nuclear@0
|
664 return newMat;
|
nuclear@0
|
665 }
|
nuclear@0
|
666
|
nuclear@0
|
667 // -------------------------------------------------------------------
|
nuclear@0
|
668 // Shows an error in parsing process.
|
nuclear@0
|
669 void ObjFileParser::reportErrorTokenInFace()
|
nuclear@0
|
670 {
|
nuclear@0
|
671 m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
nuclear@0
|
672 DefaultLogger::get()->error("OBJ: Not supported token in face description detected");
|
nuclear@0
|
673 }
|
nuclear@0
|
674
|
nuclear@0
|
675 // -------------------------------------------------------------------
|
nuclear@0
|
676
|
nuclear@0
|
677 } // Namespace Assimp
|
nuclear@0
|
678
|
nuclear@0
|
679 #endif // !! ASSIMP_BUILD_NO_OBJ_IMPORTER
|