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 /** @file ASEParser.cpp
|
nuclear@0
|
43 * @brief Implementation of the ASE parser class
|
nuclear@0
|
44 */
|
nuclear@0
|
45
|
nuclear@0
|
46 #include "AssimpPCH.h"
|
nuclear@0
|
47 #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
|
nuclear@0
|
48
|
nuclear@0
|
49 // internal headers
|
nuclear@0
|
50 #include "TextureTransform.h"
|
nuclear@0
|
51 #include "ASELoader.h"
|
nuclear@0
|
52 #include "MaterialSystem.h"
|
nuclear@0
|
53 #include "fast_atof.h"
|
nuclear@0
|
54
|
nuclear@0
|
55 using namespace Assimp;
|
nuclear@0
|
56 using namespace Assimp::ASE;
|
nuclear@0
|
57
|
nuclear@0
|
58
|
nuclear@0
|
59 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
60 // Begin an ASE parsing function
|
nuclear@0
|
61
|
nuclear@0
|
62 #define AI_ASE_PARSER_INIT() \
|
nuclear@0
|
63 int iDepth = 0;
|
nuclear@0
|
64
|
nuclear@0
|
65 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
66 // Handle a "top-level" section in the file. EOF is no error in this case.
|
nuclear@0
|
67
|
nuclear@0
|
68 #define AI_ASE_HANDLE_TOP_LEVEL_SECTION() \
|
nuclear@0
|
69 else if ('{' == *filePtr)iDepth++; \
|
nuclear@0
|
70 else if ('}' == *filePtr) \
|
nuclear@0
|
71 { \
|
nuclear@0
|
72 if (0 == --iDepth) \
|
nuclear@0
|
73 { \
|
nuclear@0
|
74 ++filePtr; \
|
nuclear@0
|
75 SkipToNextToken(); \
|
nuclear@0
|
76 return; \
|
nuclear@0
|
77 } \
|
nuclear@0
|
78 } \
|
nuclear@0
|
79 else if ('\0' == *filePtr) \
|
nuclear@0
|
80 { \
|
nuclear@0
|
81 return; \
|
nuclear@0
|
82 } \
|
nuclear@0
|
83 if(IsLineEnd(*filePtr) && !bLastWasEndLine) \
|
nuclear@0
|
84 { \
|
nuclear@0
|
85 ++iLineNumber; \
|
nuclear@0
|
86 bLastWasEndLine = true; \
|
nuclear@0
|
87 } else bLastWasEndLine = false; \
|
nuclear@0
|
88 ++filePtr;
|
nuclear@0
|
89
|
nuclear@0
|
90 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
91 // Handle a nested section in the file. EOF is an error in this case
|
nuclear@0
|
92 // @param level "Depth" of the section
|
nuclear@0
|
93 // @param msg Full name of the section (including the asterisk)
|
nuclear@0
|
94
|
nuclear@0
|
95 #define AI_ASE_HANDLE_SECTION(level, msg) \
|
nuclear@0
|
96 if ('{' == *filePtr)iDepth++; \
|
nuclear@0
|
97 else if ('}' == *filePtr) \
|
nuclear@0
|
98 { \
|
nuclear@0
|
99 if (0 == --iDepth) \
|
nuclear@0
|
100 { \
|
nuclear@0
|
101 ++filePtr; \
|
nuclear@0
|
102 SkipToNextToken(); \
|
nuclear@0
|
103 return; \
|
nuclear@0
|
104 } \
|
nuclear@0
|
105 } \
|
nuclear@0
|
106 else if ('\0' == *filePtr) \
|
nuclear@0
|
107 { \
|
nuclear@0
|
108 LogError("Encountered unexpected EOL while parsing a " msg \
|
nuclear@0
|
109 " chunk (Level " level ")"); \
|
nuclear@0
|
110 } \
|
nuclear@0
|
111 if(IsLineEnd(*filePtr) && !bLastWasEndLine) \
|
nuclear@0
|
112 { \
|
nuclear@0
|
113 ++iLineNumber; \
|
nuclear@0
|
114 bLastWasEndLine = true; \
|
nuclear@0
|
115 } else bLastWasEndLine = false; \
|
nuclear@0
|
116 ++filePtr;
|
nuclear@0
|
117
|
nuclear@0
|
118 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
119 Parser::Parser (const char* szFile, unsigned int fileFormatDefault)
|
nuclear@0
|
120 {
|
nuclear@0
|
121 ai_assert(NULL != szFile);
|
nuclear@0
|
122 filePtr = szFile;
|
nuclear@0
|
123 iFileFormat = fileFormatDefault;
|
nuclear@0
|
124
|
nuclear@0
|
125 // make sure that the color values are invalid
|
nuclear@0
|
126 m_clrBackground.r = get_qnan();
|
nuclear@0
|
127 m_clrAmbient.r = get_qnan();
|
nuclear@0
|
128
|
nuclear@0
|
129 // setup some default values
|
nuclear@0
|
130 iLineNumber = 0;
|
nuclear@0
|
131 iFirstFrame = 0;
|
nuclear@0
|
132 iLastFrame = 0;
|
nuclear@0
|
133 iFrameSpeed = 30; // use 30 as default value for this property
|
nuclear@0
|
134 iTicksPerFrame = 1; // use 1 as default value for this property
|
nuclear@0
|
135 bLastWasEndLine = false; // need to handle \r\n seqs due to binary file mapping
|
nuclear@0
|
136 }
|
nuclear@0
|
137
|
nuclear@0
|
138 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
139 void Parser::LogWarning(const char* szWarn)
|
nuclear@0
|
140 {
|
nuclear@0
|
141 ai_assert(NULL != szWarn);
|
nuclear@0
|
142
|
nuclear@0
|
143 char szTemp[1024];
|
nuclear@0
|
144 #if _MSC_VER >= 1400
|
nuclear@0
|
145 sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn);
|
nuclear@0
|
146 #else
|
nuclear@0
|
147 snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn);
|
nuclear@0
|
148 #endif
|
nuclear@0
|
149
|
nuclear@0
|
150 // output the warning to the logger ...
|
nuclear@0
|
151 DefaultLogger::get()->warn(szTemp);
|
nuclear@0
|
152 }
|
nuclear@0
|
153
|
nuclear@0
|
154 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
155 void Parser::LogInfo(const char* szWarn)
|
nuclear@0
|
156 {
|
nuclear@0
|
157 ai_assert(NULL != szWarn);
|
nuclear@0
|
158
|
nuclear@0
|
159 char szTemp[1024];
|
nuclear@0
|
160 #if _MSC_VER >= 1400
|
nuclear@0
|
161 sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn);
|
nuclear@0
|
162 #else
|
nuclear@0
|
163 snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn);
|
nuclear@0
|
164 #endif
|
nuclear@0
|
165
|
nuclear@0
|
166 // output the information to the logger ...
|
nuclear@0
|
167 DefaultLogger::get()->info(szTemp);
|
nuclear@0
|
168 }
|
nuclear@0
|
169
|
nuclear@0
|
170 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
171 void Parser::LogError(const char* szWarn)
|
nuclear@0
|
172 {
|
nuclear@0
|
173 ai_assert(NULL != szWarn);
|
nuclear@0
|
174
|
nuclear@0
|
175 char szTemp[1024];
|
nuclear@0
|
176 #if _MSC_VER >= 1400
|
nuclear@0
|
177 sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn);
|
nuclear@0
|
178 #else
|
nuclear@0
|
179 snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn);
|
nuclear@0
|
180 #endif
|
nuclear@0
|
181
|
nuclear@0
|
182 // throw an exception
|
nuclear@0
|
183 throw DeadlyImportError(szTemp);
|
nuclear@0
|
184 }
|
nuclear@0
|
185
|
nuclear@0
|
186 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
187 bool Parser::SkipToNextToken()
|
nuclear@0
|
188 {
|
nuclear@0
|
189 while (true)
|
nuclear@0
|
190 {
|
nuclear@0
|
191 char me = *filePtr;
|
nuclear@0
|
192
|
nuclear@0
|
193 // increase the line number counter if necessary
|
nuclear@0
|
194 if (IsLineEnd(me) && !bLastWasEndLine)
|
nuclear@0
|
195 {
|
nuclear@0
|
196 ++iLineNumber;
|
nuclear@0
|
197 bLastWasEndLine = true;
|
nuclear@0
|
198 }
|
nuclear@0
|
199 else bLastWasEndLine = false;
|
nuclear@0
|
200 if ('*' == me || '}' == me || '{' == me)return true;
|
nuclear@0
|
201 if ('\0' == me)return false;
|
nuclear@0
|
202
|
nuclear@0
|
203 ++filePtr;
|
nuclear@0
|
204 }
|
nuclear@0
|
205 }
|
nuclear@0
|
206
|
nuclear@0
|
207 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
208 bool Parser::SkipSection()
|
nuclear@0
|
209 {
|
nuclear@0
|
210 // must handle subsections ...
|
nuclear@0
|
211 int iCnt = 0;
|
nuclear@0
|
212 while (true)
|
nuclear@0
|
213 {
|
nuclear@0
|
214 if ('}' == *filePtr)
|
nuclear@0
|
215 {
|
nuclear@0
|
216 --iCnt;
|
nuclear@0
|
217 if (0 == iCnt)
|
nuclear@0
|
218 {
|
nuclear@0
|
219 // go to the next valid token ...
|
nuclear@0
|
220 ++filePtr;
|
nuclear@0
|
221 SkipToNextToken();
|
nuclear@0
|
222 return true;
|
nuclear@0
|
223 }
|
nuclear@0
|
224 }
|
nuclear@0
|
225 else if ('{' == *filePtr)
|
nuclear@0
|
226 {
|
nuclear@0
|
227 ++iCnt;
|
nuclear@0
|
228 }
|
nuclear@0
|
229 else if ('\0' == *filePtr)
|
nuclear@0
|
230 {
|
nuclear@0
|
231 LogWarning("Unable to parse block: Unexpected EOF, closing bracket \'}\' was expected [#1]");
|
nuclear@0
|
232 return false;
|
nuclear@0
|
233 }
|
nuclear@0
|
234 else if(IsLineEnd(*filePtr))++iLineNumber;
|
nuclear@0
|
235 ++filePtr;
|
nuclear@0
|
236 }
|
nuclear@0
|
237 }
|
nuclear@0
|
238
|
nuclear@0
|
239 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
240 void Parser::Parse()
|
nuclear@0
|
241 {
|
nuclear@0
|
242 AI_ASE_PARSER_INIT();
|
nuclear@0
|
243 while (true)
|
nuclear@0
|
244 {
|
nuclear@0
|
245 if ('*' == *filePtr)
|
nuclear@0
|
246 {
|
nuclear@0
|
247 ++filePtr;
|
nuclear@0
|
248
|
nuclear@0
|
249 // Version should be 200. Validate this ...
|
nuclear@0
|
250 if (TokenMatch(filePtr,"3DSMAX_ASCIIEXPORT",18))
|
nuclear@0
|
251 {
|
nuclear@0
|
252 unsigned int fmt;
|
nuclear@0
|
253 ParseLV4MeshLong(fmt);
|
nuclear@0
|
254
|
nuclear@0
|
255 if (fmt > 200)
|
nuclear@0
|
256 {
|
nuclear@0
|
257 LogWarning("Unknown file format version: *3DSMAX_ASCIIEXPORT should \
|
nuclear@0
|
258 be <= 200");
|
nuclear@0
|
259 }
|
nuclear@0
|
260 // *************************************************************
|
nuclear@0
|
261 // - fmt will be 0 if we're unable to read the version number
|
nuclear@0
|
262 // there are some faulty files without a version number ...
|
nuclear@0
|
263 // in this case we'll guess the exact file format by looking
|
nuclear@0
|
264 // at the file extension (ASE, ASK, ASC)
|
nuclear@0
|
265 // *************************************************************
|
nuclear@0
|
266
|
nuclear@0
|
267 if (fmt)iFileFormat = fmt;
|
nuclear@0
|
268 continue;
|
nuclear@0
|
269 }
|
nuclear@0
|
270 // main scene information
|
nuclear@0
|
271 if (TokenMatch(filePtr,"SCENE",5))
|
nuclear@0
|
272 {
|
nuclear@0
|
273 ParseLV1SceneBlock();
|
nuclear@0
|
274 continue;
|
nuclear@0
|
275 }
|
nuclear@0
|
276 // "group" - no implementation yet, in facte
|
nuclear@0
|
277 // we're just ignoring them for the moment
|
nuclear@0
|
278 if (TokenMatch(filePtr,"GROUP",5))
|
nuclear@0
|
279 {
|
nuclear@0
|
280 Parse();
|
nuclear@0
|
281 continue;
|
nuclear@0
|
282 }
|
nuclear@0
|
283 // material list
|
nuclear@0
|
284 if (TokenMatch(filePtr,"MATERIAL_LIST",13))
|
nuclear@0
|
285 {
|
nuclear@0
|
286 ParseLV1MaterialListBlock();
|
nuclear@0
|
287 continue;
|
nuclear@0
|
288 }
|
nuclear@0
|
289 // geometric object (mesh)
|
nuclear@0
|
290 if (TokenMatch(filePtr,"GEOMOBJECT",10))
|
nuclear@0
|
291
|
nuclear@0
|
292 {
|
nuclear@0
|
293 m_vMeshes.push_back(Mesh());
|
nuclear@0
|
294 ParseLV1ObjectBlock(m_vMeshes.back());
|
nuclear@0
|
295 continue;
|
nuclear@0
|
296 }
|
nuclear@0
|
297 // helper object = dummy in the hierarchy
|
nuclear@0
|
298 if (TokenMatch(filePtr,"HELPEROBJECT",12))
|
nuclear@0
|
299
|
nuclear@0
|
300 {
|
nuclear@0
|
301 m_vDummies.push_back(Dummy());
|
nuclear@0
|
302 ParseLV1ObjectBlock(m_vDummies.back());
|
nuclear@0
|
303 continue;
|
nuclear@0
|
304 }
|
nuclear@0
|
305 // light object
|
nuclear@0
|
306 if (TokenMatch(filePtr,"LIGHTOBJECT",11))
|
nuclear@0
|
307
|
nuclear@0
|
308 {
|
nuclear@0
|
309 m_vLights.push_back(Light());
|
nuclear@0
|
310 ParseLV1ObjectBlock(m_vLights.back());
|
nuclear@0
|
311 continue;
|
nuclear@0
|
312 }
|
nuclear@0
|
313 // camera object
|
nuclear@0
|
314 if (TokenMatch(filePtr,"CAMERAOBJECT",12))
|
nuclear@0
|
315 {
|
nuclear@0
|
316 m_vCameras.push_back(Camera());
|
nuclear@0
|
317 ParseLV1ObjectBlock(m_vCameras.back());
|
nuclear@0
|
318 continue;
|
nuclear@0
|
319 }
|
nuclear@0
|
320 // comment - print it on the console
|
nuclear@0
|
321 if (TokenMatch(filePtr,"COMMENT",7))
|
nuclear@0
|
322 {
|
nuclear@0
|
323 std::string out = "<unknown>";
|
nuclear@0
|
324 ParseString(out,"*COMMENT");
|
nuclear@0
|
325 LogInfo(("Comment: " + out).c_str());
|
nuclear@0
|
326 continue;
|
nuclear@0
|
327 }
|
nuclear@0
|
328 // ASC bone weights
|
nuclear@0
|
329 if (AI_ASE_IS_OLD_FILE_FORMAT() && TokenMatch(filePtr,"MESH_SOFTSKINVERTS",18))
|
nuclear@0
|
330 {
|
nuclear@0
|
331 ParseLV1SoftSkinBlock();
|
nuclear@0
|
332 }
|
nuclear@0
|
333 }
|
nuclear@0
|
334 AI_ASE_HANDLE_TOP_LEVEL_SECTION();
|
nuclear@0
|
335 }
|
nuclear@0
|
336 return;
|
nuclear@0
|
337 }
|
nuclear@0
|
338
|
nuclear@0
|
339 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
340 void Parser::ParseLV1SoftSkinBlock()
|
nuclear@0
|
341 {
|
nuclear@0
|
342 // TODO: fix line counting here
|
nuclear@0
|
343
|
nuclear@0
|
344 // **************************************************************
|
nuclear@0
|
345 // The soft skin block is formatted differently. There are no
|
nuclear@0
|
346 // nested sections supported and the single elements aren't
|
nuclear@0
|
347 // marked by keywords starting with an asterisk.
|
nuclear@0
|
348
|
nuclear@0
|
349 /**
|
nuclear@0
|
350 FORMAT BEGIN
|
nuclear@0
|
351
|
nuclear@0
|
352 *MESH_SOFTSKINVERTS {
|
nuclear@0
|
353 <nodename>
|
nuclear@0
|
354 <number of vertices>
|
nuclear@0
|
355
|
nuclear@0
|
356 [for <number of vertices> times:]
|
nuclear@0
|
357 <number of weights> [for <number of weights> times:] <bone name> <weight>
|
nuclear@0
|
358 }
|
nuclear@0
|
359
|
nuclear@0
|
360 FORMAT END
|
nuclear@0
|
361 */
|
nuclear@0
|
362 // **************************************************************
|
nuclear@0
|
363 while (true)
|
nuclear@0
|
364 {
|
nuclear@0
|
365 if (*filePtr == '}' ) {++filePtr;return;}
|
nuclear@0
|
366 else if (*filePtr == '\0') return;
|
nuclear@0
|
367 else if (*filePtr == '{' ) ++filePtr;
|
nuclear@0
|
368
|
nuclear@0
|
369 else // if (!IsSpace(*filePtr) && !IsLineEnd(*filePtr))
|
nuclear@0
|
370 {
|
nuclear@0
|
371 ASE::Mesh* curMesh = NULL;
|
nuclear@0
|
372 unsigned int numVerts = 0;
|
nuclear@0
|
373
|
nuclear@0
|
374 const char* sz = filePtr;
|
nuclear@0
|
375 while (!IsSpaceOrNewLine(*filePtr))++filePtr;
|
nuclear@0
|
376
|
nuclear@0
|
377 const unsigned int diff = (unsigned int)(filePtr-sz);
|
nuclear@0
|
378 if (diff)
|
nuclear@0
|
379 {
|
nuclear@0
|
380 std::string name = std::string(sz,diff);
|
nuclear@0
|
381 for (std::vector<ASE::Mesh>::iterator it = m_vMeshes.begin();
|
nuclear@0
|
382 it != m_vMeshes.end(); ++it)
|
nuclear@0
|
383 {
|
nuclear@0
|
384 if ((*it).mName == name)
|
nuclear@0
|
385 {
|
nuclear@0
|
386 curMesh = & (*it);
|
nuclear@0
|
387 break;
|
nuclear@0
|
388 }
|
nuclear@0
|
389 }
|
nuclear@0
|
390 if (!curMesh)
|
nuclear@0
|
391 {
|
nuclear@0
|
392 LogWarning("Encountered unknown mesh in *MESH_SOFTSKINVERTS section");
|
nuclear@0
|
393
|
nuclear@0
|
394 // Skip the mesh data - until we find a new mesh
|
nuclear@0
|
395 // or the end of the *MESH_SOFTSKINVERTS section
|
nuclear@0
|
396 while (true)
|
nuclear@0
|
397 {
|
nuclear@0
|
398 SkipSpacesAndLineEnd(&filePtr);
|
nuclear@0
|
399 if (*filePtr == '}')
|
nuclear@0
|
400 {++filePtr;return;}
|
nuclear@0
|
401 else if (!IsNumeric(*filePtr))
|
nuclear@0
|
402 break;
|
nuclear@0
|
403
|
nuclear@0
|
404 SkipLine(&filePtr);
|
nuclear@0
|
405 }
|
nuclear@0
|
406 }
|
nuclear@0
|
407 else
|
nuclear@0
|
408 {
|
nuclear@0
|
409 SkipSpacesAndLineEnd(&filePtr);
|
nuclear@0
|
410 ParseLV4MeshLong(numVerts);
|
nuclear@0
|
411
|
nuclear@0
|
412 // Reserve enough storage
|
nuclear@0
|
413 curMesh->mBoneVertices.reserve(numVerts);
|
nuclear@0
|
414
|
nuclear@0
|
415 for (unsigned int i = 0; i < numVerts;++i)
|
nuclear@0
|
416 {
|
nuclear@0
|
417 SkipSpacesAndLineEnd(&filePtr);
|
nuclear@0
|
418 unsigned int numWeights;
|
nuclear@0
|
419 ParseLV4MeshLong(numWeights);
|
nuclear@0
|
420
|
nuclear@0
|
421 curMesh->mBoneVertices.push_back(ASE::BoneVertex());
|
nuclear@0
|
422 ASE::BoneVertex& vert = curMesh->mBoneVertices.back();
|
nuclear@0
|
423
|
nuclear@0
|
424 // Reserve enough storage
|
nuclear@0
|
425 vert.mBoneWeights.reserve(numWeights);
|
nuclear@0
|
426
|
nuclear@0
|
427 for (unsigned int w = 0; w < numWeights;++w)
|
nuclear@0
|
428 {
|
nuclear@0
|
429 std::string bone;
|
nuclear@0
|
430 ParseString(bone,"*MESH_SOFTSKINVERTS.Bone");
|
nuclear@0
|
431
|
nuclear@0
|
432 // Find the bone in the mesh's list
|
nuclear@0
|
433 std::pair<int,float> me;
|
nuclear@0
|
434 me.first = -1;
|
nuclear@0
|
435
|
nuclear@0
|
436 for (unsigned int n = 0; n < curMesh->mBones.size();++n)
|
nuclear@0
|
437 {
|
nuclear@0
|
438 if (curMesh->mBones[n].mName == bone)
|
nuclear@0
|
439 {
|
nuclear@0
|
440 me.first = n;
|
nuclear@0
|
441 break;
|
nuclear@0
|
442 }
|
nuclear@0
|
443 }
|
nuclear@0
|
444 if (-1 == me.first)
|
nuclear@0
|
445 {
|
nuclear@0
|
446 // We don't have this bone yet, so add it to the list
|
nuclear@0
|
447 me.first = (int)curMesh->mBones.size();
|
nuclear@0
|
448 curMesh->mBones.push_back(ASE::Bone(bone));
|
nuclear@0
|
449 }
|
nuclear@0
|
450 ParseLV4MeshFloat( me.second );
|
nuclear@0
|
451
|
nuclear@0
|
452 // Add the new bone weight to list
|
nuclear@0
|
453 vert.mBoneWeights.push_back(me);
|
nuclear@0
|
454 }
|
nuclear@0
|
455 }
|
nuclear@0
|
456 }
|
nuclear@0
|
457 }
|
nuclear@0
|
458 }
|
nuclear@0
|
459 ++filePtr;
|
nuclear@0
|
460 SkipSpacesAndLineEnd(&filePtr);
|
nuclear@0
|
461 }
|
nuclear@0
|
462 }
|
nuclear@0
|
463
|
nuclear@0
|
464 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
465 void Parser::ParseLV1SceneBlock()
|
nuclear@0
|
466 {
|
nuclear@0
|
467 AI_ASE_PARSER_INIT();
|
nuclear@0
|
468 while (true)
|
nuclear@0
|
469 {
|
nuclear@0
|
470 if ('*' == *filePtr)
|
nuclear@0
|
471 {
|
nuclear@0
|
472 ++filePtr;
|
nuclear@0
|
473 if (TokenMatch(filePtr,"SCENE_BACKGROUND_STATIC",23))
|
nuclear@0
|
474
|
nuclear@0
|
475 {
|
nuclear@0
|
476 // parse a color triple and assume it is really the bg color
|
nuclear@0
|
477 ParseLV4MeshFloatTriple( &m_clrBackground.r );
|
nuclear@0
|
478 continue;
|
nuclear@0
|
479 }
|
nuclear@0
|
480 if (TokenMatch(filePtr,"SCENE_AMBIENT_STATIC",20))
|
nuclear@0
|
481
|
nuclear@0
|
482 {
|
nuclear@0
|
483 // parse a color triple and assume it is really the bg color
|
nuclear@0
|
484 ParseLV4MeshFloatTriple( &m_clrAmbient.r );
|
nuclear@0
|
485 continue;
|
nuclear@0
|
486 }
|
nuclear@0
|
487 if (TokenMatch(filePtr,"SCENE_FIRSTFRAME",16))
|
nuclear@0
|
488 {
|
nuclear@0
|
489 ParseLV4MeshLong(iFirstFrame);
|
nuclear@0
|
490 continue;
|
nuclear@0
|
491 }
|
nuclear@0
|
492 if (TokenMatch(filePtr,"SCENE_LASTFRAME",15))
|
nuclear@0
|
493 {
|
nuclear@0
|
494 ParseLV4MeshLong(iLastFrame);
|
nuclear@0
|
495 continue;
|
nuclear@0
|
496 }
|
nuclear@0
|
497 if (TokenMatch(filePtr,"SCENE_FRAMESPEED",16))
|
nuclear@0
|
498 {
|
nuclear@0
|
499 ParseLV4MeshLong(iFrameSpeed);
|
nuclear@0
|
500 continue;
|
nuclear@0
|
501 }
|
nuclear@0
|
502 if (TokenMatch(filePtr,"SCENE_TICKSPERFRAME",19))
|
nuclear@0
|
503 {
|
nuclear@0
|
504 ParseLV4MeshLong(iTicksPerFrame);
|
nuclear@0
|
505 continue;
|
nuclear@0
|
506 }
|
nuclear@0
|
507 }
|
nuclear@0
|
508 AI_ASE_HANDLE_TOP_LEVEL_SECTION();
|
nuclear@0
|
509 }
|
nuclear@0
|
510 }
|
nuclear@0
|
511
|
nuclear@0
|
512 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
513 void Parser::ParseLV1MaterialListBlock()
|
nuclear@0
|
514 {
|
nuclear@0
|
515 AI_ASE_PARSER_INIT();
|
nuclear@0
|
516
|
nuclear@0
|
517 unsigned int iMaterialCount = 0;
|
nuclear@0
|
518 unsigned int iOldMaterialCount = (unsigned int)m_vMaterials.size();
|
nuclear@0
|
519 while (true)
|
nuclear@0
|
520 {
|
nuclear@0
|
521 if ('*' == *filePtr)
|
nuclear@0
|
522 {
|
nuclear@0
|
523 ++filePtr;
|
nuclear@0
|
524 if (TokenMatch(filePtr,"MATERIAL_COUNT",14))
|
nuclear@0
|
525 {
|
nuclear@0
|
526 ParseLV4MeshLong(iMaterialCount);
|
nuclear@0
|
527
|
nuclear@0
|
528 // now allocate enough storage to hold all materials
|
nuclear@0
|
529 m_vMaterials.resize(iOldMaterialCount+iMaterialCount);
|
nuclear@0
|
530 continue;
|
nuclear@0
|
531 }
|
nuclear@0
|
532 if (TokenMatch(filePtr,"MATERIAL",8))
|
nuclear@0
|
533 {
|
nuclear@0
|
534 unsigned int iIndex = 0;
|
nuclear@0
|
535 ParseLV4MeshLong(iIndex);
|
nuclear@0
|
536
|
nuclear@0
|
537 if (iIndex >= iMaterialCount)
|
nuclear@0
|
538 {
|
nuclear@0
|
539 LogWarning("Out of range: material index is too large");
|
nuclear@0
|
540 iIndex = iMaterialCount-1;
|
nuclear@0
|
541 }
|
nuclear@0
|
542
|
nuclear@0
|
543 // get a reference to the material
|
nuclear@0
|
544 Material& sMat = m_vMaterials[iIndex+iOldMaterialCount];
|
nuclear@0
|
545 // parse the material block
|
nuclear@0
|
546 ParseLV2MaterialBlock(sMat);
|
nuclear@0
|
547 continue;
|
nuclear@0
|
548 }
|
nuclear@0
|
549 }
|
nuclear@0
|
550 AI_ASE_HANDLE_TOP_LEVEL_SECTION();
|
nuclear@0
|
551 }
|
nuclear@0
|
552 }
|
nuclear@0
|
553
|
nuclear@0
|
554 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
555 void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
|
nuclear@0
|
556 {
|
nuclear@0
|
557 AI_ASE_PARSER_INIT();
|
nuclear@0
|
558
|
nuclear@0
|
559 unsigned int iNumSubMaterials = 0;
|
nuclear@0
|
560 while (true)
|
nuclear@0
|
561 {
|
nuclear@0
|
562 if ('*' == *filePtr)
|
nuclear@0
|
563 {
|
nuclear@0
|
564 ++filePtr;
|
nuclear@0
|
565 if (TokenMatch(filePtr,"MATERIAL_NAME",13))
|
nuclear@0
|
566 {
|
nuclear@0
|
567 if (!ParseString(mat.mName,"*MATERIAL_NAME"))
|
nuclear@0
|
568 SkipToNextToken();
|
nuclear@0
|
569 continue;
|
nuclear@0
|
570 }
|
nuclear@0
|
571 // ambient material color
|
nuclear@0
|
572 if (TokenMatch(filePtr,"MATERIAL_AMBIENT",16))
|
nuclear@0
|
573 {
|
nuclear@0
|
574 ParseLV4MeshFloatTriple(&mat.mAmbient.r);
|
nuclear@0
|
575 continue;
|
nuclear@0
|
576 }
|
nuclear@0
|
577 // diffuse material color
|
nuclear@0
|
578 if (TokenMatch(filePtr,"MATERIAL_DIFFUSE",16) )
|
nuclear@0
|
579 {
|
nuclear@0
|
580 ParseLV4MeshFloatTriple(&mat.mDiffuse.r);
|
nuclear@0
|
581 continue;
|
nuclear@0
|
582 }
|
nuclear@0
|
583 // specular material color
|
nuclear@0
|
584 if (TokenMatch(filePtr,"MATERIAL_SPECULAR",17))
|
nuclear@0
|
585 {
|
nuclear@0
|
586 ParseLV4MeshFloatTriple(&mat.mSpecular.r);
|
nuclear@0
|
587 continue;
|
nuclear@0
|
588 }
|
nuclear@0
|
589 // material shading type
|
nuclear@0
|
590 if (TokenMatch(filePtr,"MATERIAL_SHADING",16))
|
nuclear@0
|
591 {
|
nuclear@0
|
592 if (TokenMatch(filePtr,"Blinn",5))
|
nuclear@0
|
593 {
|
nuclear@0
|
594 mat.mShading = Discreet3DS::Blinn;
|
nuclear@0
|
595 }
|
nuclear@0
|
596 else if (TokenMatch(filePtr,"Phong",5))
|
nuclear@0
|
597 {
|
nuclear@0
|
598 mat.mShading = Discreet3DS::Phong;
|
nuclear@0
|
599 }
|
nuclear@0
|
600 else if (TokenMatch(filePtr,"Flat",4))
|
nuclear@0
|
601 {
|
nuclear@0
|
602 mat.mShading = Discreet3DS::Flat;
|
nuclear@0
|
603 }
|
nuclear@0
|
604 else if (TokenMatch(filePtr,"Wire",4))
|
nuclear@0
|
605 {
|
nuclear@0
|
606 mat.mShading = Discreet3DS::Wire;
|
nuclear@0
|
607 }
|
nuclear@0
|
608 else
|
nuclear@0
|
609 {
|
nuclear@0
|
610 // assume gouraud shading
|
nuclear@0
|
611 mat.mShading = Discreet3DS::Gouraud;
|
nuclear@0
|
612 SkipToNextToken();
|
nuclear@0
|
613 }
|
nuclear@0
|
614 continue;
|
nuclear@0
|
615 }
|
nuclear@0
|
616 // material transparency
|
nuclear@0
|
617 if (TokenMatch(filePtr,"MATERIAL_TRANSPARENCY",21))
|
nuclear@0
|
618 {
|
nuclear@0
|
619 ParseLV4MeshFloat(mat.mTransparency);
|
nuclear@0
|
620 mat.mTransparency = 1.0f - mat.mTransparency;continue;
|
nuclear@0
|
621 }
|
nuclear@0
|
622 // material self illumination
|
nuclear@0
|
623 if (TokenMatch(filePtr,"MATERIAL_SELFILLUM",18))
|
nuclear@0
|
624 {
|
nuclear@0
|
625 float f = 0.0f;
|
nuclear@0
|
626 ParseLV4MeshFloat(f);
|
nuclear@0
|
627
|
nuclear@0
|
628 mat.mEmissive.r = f;
|
nuclear@0
|
629 mat.mEmissive.g = f;
|
nuclear@0
|
630 mat.mEmissive.b = f;
|
nuclear@0
|
631 continue;
|
nuclear@0
|
632 }
|
nuclear@0
|
633 // material shininess
|
nuclear@0
|
634 if (TokenMatch(filePtr,"MATERIAL_SHINE",14) )
|
nuclear@0
|
635 {
|
nuclear@0
|
636 ParseLV4MeshFloat(mat.mSpecularExponent);
|
nuclear@0
|
637 mat.mSpecularExponent *= 15;
|
nuclear@0
|
638 continue;
|
nuclear@0
|
639 }
|
nuclear@0
|
640 // two-sided material
|
nuclear@0
|
641 if (TokenMatch(filePtr,"MATERIAL_TWOSIDED",17) )
|
nuclear@0
|
642 {
|
nuclear@0
|
643 mat.mTwoSided = true;
|
nuclear@0
|
644 continue;
|
nuclear@0
|
645 }
|
nuclear@0
|
646 // material shininess strength
|
nuclear@0
|
647 if (TokenMatch(filePtr,"MATERIAL_SHINESTRENGTH",22))
|
nuclear@0
|
648 {
|
nuclear@0
|
649 ParseLV4MeshFloat(mat.mShininessStrength);
|
nuclear@0
|
650 continue;
|
nuclear@0
|
651 }
|
nuclear@0
|
652 // diffuse color map
|
nuclear@0
|
653 if (TokenMatch(filePtr,"MAP_DIFFUSE",11))
|
nuclear@0
|
654 {
|
nuclear@0
|
655 // parse the texture block
|
nuclear@0
|
656 ParseLV3MapBlock(mat.sTexDiffuse);
|
nuclear@0
|
657 continue;
|
nuclear@0
|
658 }
|
nuclear@0
|
659 // ambient color map
|
nuclear@0
|
660 if (TokenMatch(filePtr,"MAP_AMBIENT",11))
|
nuclear@0
|
661 {
|
nuclear@0
|
662 // parse the texture block
|
nuclear@0
|
663 ParseLV3MapBlock(mat.sTexAmbient);
|
nuclear@0
|
664 continue;
|
nuclear@0
|
665 }
|
nuclear@0
|
666 // specular color map
|
nuclear@0
|
667 if (TokenMatch(filePtr,"MAP_SPECULAR",12))
|
nuclear@0
|
668 {
|
nuclear@0
|
669 // parse the texture block
|
nuclear@0
|
670 ParseLV3MapBlock(mat.sTexSpecular);
|
nuclear@0
|
671 continue;
|
nuclear@0
|
672 }
|
nuclear@0
|
673 // opacity map
|
nuclear@0
|
674 if (TokenMatch(filePtr,"MAP_OPACITY",11))
|
nuclear@0
|
675 {
|
nuclear@0
|
676 // parse the texture block
|
nuclear@0
|
677 ParseLV3MapBlock(mat.sTexOpacity);
|
nuclear@0
|
678 continue;
|
nuclear@0
|
679 }
|
nuclear@0
|
680 // emissive map
|
nuclear@0
|
681 if (TokenMatch(filePtr,"MAP_SELFILLUM",13))
|
nuclear@0
|
682 {
|
nuclear@0
|
683 // parse the texture block
|
nuclear@0
|
684 ParseLV3MapBlock(mat.sTexEmissive);
|
nuclear@0
|
685 continue;
|
nuclear@0
|
686 }
|
nuclear@0
|
687 // bump map
|
nuclear@0
|
688 if (TokenMatch(filePtr,"MAP_BUMP",8))
|
nuclear@0
|
689 {
|
nuclear@0
|
690 // parse the texture block
|
nuclear@0
|
691 ParseLV3MapBlock(mat.sTexBump);
|
nuclear@0
|
692 }
|
nuclear@0
|
693 // specular/shininess map
|
nuclear@0
|
694 if (TokenMatch(filePtr,"MAP_SHINESTRENGTH",17))
|
nuclear@0
|
695 {
|
nuclear@0
|
696 // parse the texture block
|
nuclear@0
|
697 ParseLV3MapBlock(mat.sTexShininess);
|
nuclear@0
|
698 continue;
|
nuclear@0
|
699 }
|
nuclear@0
|
700 // number of submaterials
|
nuclear@0
|
701 if (TokenMatch(filePtr,"NUMSUBMTLS",10))
|
nuclear@0
|
702 {
|
nuclear@0
|
703 ParseLV4MeshLong(iNumSubMaterials);
|
nuclear@0
|
704
|
nuclear@0
|
705 // allocate enough storage
|
nuclear@0
|
706 mat.avSubMaterials.resize(iNumSubMaterials);
|
nuclear@0
|
707 }
|
nuclear@0
|
708 // submaterial chunks
|
nuclear@0
|
709 if (TokenMatch(filePtr,"SUBMATERIAL",11))
|
nuclear@0
|
710 {
|
nuclear@0
|
711
|
nuclear@0
|
712 unsigned int iIndex = 0;
|
nuclear@0
|
713 ParseLV4MeshLong(iIndex);
|
nuclear@0
|
714
|
nuclear@0
|
715 if (iIndex >= iNumSubMaterials)
|
nuclear@0
|
716 {
|
nuclear@0
|
717 LogWarning("Out of range: submaterial index is too large");
|
nuclear@0
|
718 iIndex = iNumSubMaterials-1;
|
nuclear@0
|
719 }
|
nuclear@0
|
720
|
nuclear@0
|
721 // get a reference to the material
|
nuclear@0
|
722 Material& sMat = mat.avSubMaterials[iIndex];
|
nuclear@0
|
723
|
nuclear@0
|
724 // parse the material block
|
nuclear@0
|
725 ParseLV2MaterialBlock(sMat);
|
nuclear@0
|
726 continue;
|
nuclear@0
|
727 }
|
nuclear@0
|
728 }
|
nuclear@0
|
729 AI_ASE_HANDLE_SECTION("2","*MATERIAL");
|
nuclear@0
|
730 }
|
nuclear@0
|
731 }
|
nuclear@0
|
732
|
nuclear@0
|
733 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
734 void Parser::ParseLV3MapBlock(Texture& map)
|
nuclear@0
|
735 {
|
nuclear@0
|
736 AI_ASE_PARSER_INIT();
|
nuclear@0
|
737
|
nuclear@0
|
738 // ***********************************************************
|
nuclear@0
|
739 // *BITMAP should not be there if *MAP_CLASS is not BITMAP,
|
nuclear@0
|
740 // but we need to expect that case ... if the path is
|
nuclear@0
|
741 // empty the texture won't be used later.
|
nuclear@0
|
742 // ***********************************************************
|
nuclear@0
|
743 bool parsePath = true;
|
nuclear@0
|
744 while (true)
|
nuclear@0
|
745 {
|
nuclear@0
|
746 if ('*' == *filePtr)
|
nuclear@0
|
747 {
|
nuclear@0
|
748 ++filePtr;
|
nuclear@0
|
749 // type of map
|
nuclear@0
|
750 if (TokenMatch(filePtr,"MAP_CLASS" ,9))
|
nuclear@0
|
751 {
|
nuclear@0
|
752 std::string temp;
|
nuclear@0
|
753 if(!ParseString(temp,"*MAP_CLASS"))
|
nuclear@0
|
754 SkipToNextToken();
|
nuclear@0
|
755 if (temp != "Bitmap" && temp != "Normal Bump")
|
nuclear@0
|
756 {
|
nuclear@0
|
757 DefaultLogger::get()->warn("ASE: Skipping unknown map type: " + temp);
|
nuclear@0
|
758 parsePath = false;
|
nuclear@0
|
759 }
|
nuclear@0
|
760 continue;
|
nuclear@0
|
761 }
|
nuclear@0
|
762 // path to the texture
|
nuclear@0
|
763 if (parsePath && TokenMatch(filePtr,"BITMAP" ,6))
|
nuclear@0
|
764 {
|
nuclear@0
|
765 if(!ParseString(map.mMapName,"*BITMAP"))
|
nuclear@0
|
766 SkipToNextToken();
|
nuclear@0
|
767
|
nuclear@0
|
768 if (map.mMapName == "None")
|
nuclear@0
|
769 {
|
nuclear@0
|
770 // Files with 'None' as map name are produced by
|
nuclear@0
|
771 // an Maja to ASE exporter which name I forgot ..
|
nuclear@0
|
772 DefaultLogger::get()->warn("ASE: Skipping invalid map entry");
|
nuclear@0
|
773 map.mMapName = "";
|
nuclear@0
|
774 }
|
nuclear@0
|
775
|
nuclear@0
|
776 continue;
|
nuclear@0
|
777 }
|
nuclear@0
|
778 // offset on the u axis
|
nuclear@0
|
779 if (TokenMatch(filePtr,"UVW_U_OFFSET" ,12))
|
nuclear@0
|
780 {
|
nuclear@0
|
781 ParseLV4MeshFloat(map.mOffsetU);
|
nuclear@0
|
782 continue;
|
nuclear@0
|
783 }
|
nuclear@0
|
784 // offset on the v axis
|
nuclear@0
|
785 if (TokenMatch(filePtr,"UVW_V_OFFSET" ,12))
|
nuclear@0
|
786 {
|
nuclear@0
|
787 ParseLV4MeshFloat(map.mOffsetV);
|
nuclear@0
|
788 continue;
|
nuclear@0
|
789 }
|
nuclear@0
|
790 // tiling on the u axis
|
nuclear@0
|
791 if (TokenMatch(filePtr,"UVW_U_TILING" ,12))
|
nuclear@0
|
792 {
|
nuclear@0
|
793 ParseLV4MeshFloat(map.mScaleU);
|
nuclear@0
|
794 continue;
|
nuclear@0
|
795 }
|
nuclear@0
|
796 // tiling on the v axis
|
nuclear@0
|
797 if (TokenMatch(filePtr,"UVW_V_TILING" ,12))
|
nuclear@0
|
798 {
|
nuclear@0
|
799 ParseLV4MeshFloat(map.mScaleV);
|
nuclear@0
|
800 continue;
|
nuclear@0
|
801 }
|
nuclear@0
|
802 // rotation around the z-axis
|
nuclear@0
|
803 if (TokenMatch(filePtr,"UVW_ANGLE" ,9))
|
nuclear@0
|
804 {
|
nuclear@0
|
805 ParseLV4MeshFloat(map.mRotation);
|
nuclear@0
|
806 continue;
|
nuclear@0
|
807 }
|
nuclear@0
|
808 // map blending factor
|
nuclear@0
|
809 if (TokenMatch(filePtr,"MAP_AMOUNT" ,10))
|
nuclear@0
|
810 {
|
nuclear@0
|
811 ParseLV4MeshFloat(map.mTextureBlend);
|
nuclear@0
|
812 continue;
|
nuclear@0
|
813 }
|
nuclear@0
|
814 }
|
nuclear@0
|
815 AI_ASE_HANDLE_SECTION("3","*MAP_XXXXXX");
|
nuclear@0
|
816 }
|
nuclear@0
|
817 return;
|
nuclear@0
|
818 }
|
nuclear@0
|
819
|
nuclear@0
|
820 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
821 bool Parser::ParseString(std::string& out,const char* szName)
|
nuclear@0
|
822 {
|
nuclear@0
|
823 char szBuffer[1024];
|
nuclear@0
|
824 if (!SkipSpaces(&filePtr))
|
nuclear@0
|
825 {
|
nuclear@0
|
826
|
nuclear@0
|
827 sprintf(szBuffer,"Unable to parse %s block: Unexpected EOL",szName);
|
nuclear@0
|
828 LogWarning(szBuffer);
|
nuclear@0
|
829 return false;
|
nuclear@0
|
830 }
|
nuclear@0
|
831 // there must be '"'
|
nuclear@0
|
832 if ('\"' != *filePtr)
|
nuclear@0
|
833 {
|
nuclear@0
|
834
|
nuclear@0
|
835 sprintf(szBuffer,"Unable to parse %s block: Strings are expected "
|
nuclear@0
|
836 "to be enclosed in double quotation marks",szName);
|
nuclear@0
|
837 LogWarning(szBuffer);
|
nuclear@0
|
838 return false;
|
nuclear@0
|
839 }
|
nuclear@0
|
840 ++filePtr;
|
nuclear@0
|
841 const char* sz = filePtr;
|
nuclear@0
|
842 while (true)
|
nuclear@0
|
843 {
|
nuclear@0
|
844 if ('\"' == *sz)break;
|
nuclear@0
|
845 else if ('\0' == *sz)
|
nuclear@0
|
846 {
|
nuclear@0
|
847 sprintf(szBuffer,"Unable to parse %s block: Strings are expected to "
|
nuclear@0
|
848 "be enclosed in double quotation marks but EOF was reached before "
|
nuclear@0
|
849 "a closing quotation mark was encountered",szName);
|
nuclear@0
|
850 LogWarning(szBuffer);
|
nuclear@0
|
851 return false;
|
nuclear@0
|
852 }
|
nuclear@0
|
853 sz++;
|
nuclear@0
|
854 }
|
nuclear@0
|
855 out = std::string(filePtr,(uintptr_t)sz-(uintptr_t)filePtr);
|
nuclear@0
|
856 filePtr = sz+1;
|
nuclear@0
|
857 return true;
|
nuclear@0
|
858 }
|
nuclear@0
|
859
|
nuclear@0
|
860 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
861 void Parser::ParseLV1ObjectBlock(ASE::BaseNode& node)
|
nuclear@0
|
862 {
|
nuclear@0
|
863 AI_ASE_PARSER_INIT();
|
nuclear@0
|
864 while (true)
|
nuclear@0
|
865 {
|
nuclear@0
|
866 if ('*' == *filePtr)
|
nuclear@0
|
867 {
|
nuclear@0
|
868 ++filePtr;
|
nuclear@0
|
869
|
nuclear@0
|
870 // first process common tokens such as node name and transform
|
nuclear@0
|
871 // name of the mesh/node
|
nuclear@0
|
872 if (TokenMatch(filePtr,"NODE_NAME" ,9))
|
nuclear@0
|
873 {
|
nuclear@0
|
874 if(!ParseString(node.mName,"*NODE_NAME"))
|
nuclear@0
|
875 SkipToNextToken();
|
nuclear@0
|
876 continue;
|
nuclear@0
|
877 }
|
nuclear@0
|
878 // name of the parent of the node
|
nuclear@0
|
879 if (TokenMatch(filePtr,"NODE_PARENT" ,11) )
|
nuclear@0
|
880 {
|
nuclear@0
|
881 if(!ParseString(node.mParent,"*NODE_PARENT"))
|
nuclear@0
|
882 SkipToNextToken();
|
nuclear@0
|
883 continue;
|
nuclear@0
|
884 }
|
nuclear@0
|
885 // transformation matrix of the node
|
nuclear@0
|
886 if (TokenMatch(filePtr,"NODE_TM" ,7))
|
nuclear@0
|
887 {
|
nuclear@0
|
888 ParseLV2NodeTransformBlock(node);
|
nuclear@0
|
889 continue;
|
nuclear@0
|
890 }
|
nuclear@0
|
891 // animation data of the node
|
nuclear@0
|
892 if (TokenMatch(filePtr,"TM_ANIMATION" ,12))
|
nuclear@0
|
893 {
|
nuclear@0
|
894 ParseLV2AnimationBlock(node);
|
nuclear@0
|
895 continue;
|
nuclear@0
|
896 }
|
nuclear@0
|
897
|
nuclear@0
|
898 if (node.mType == BaseNode::Light)
|
nuclear@0
|
899 {
|
nuclear@0
|
900 // light settings
|
nuclear@0
|
901 if (TokenMatch(filePtr,"LIGHT_SETTINGS" ,14))
|
nuclear@0
|
902 {
|
nuclear@0
|
903 ParseLV2LightSettingsBlock((ASE::Light&)node);
|
nuclear@0
|
904 continue;
|
nuclear@0
|
905 }
|
nuclear@0
|
906 // type of the light source
|
nuclear@0
|
907 if (TokenMatch(filePtr,"LIGHT_TYPE" ,10))
|
nuclear@0
|
908 {
|
nuclear@0
|
909 if (!ASSIMP_strincmp("omni",filePtr,4))
|
nuclear@0
|
910 {
|
nuclear@0
|
911 ((ASE::Light&)node).mLightType = ASE::Light::OMNI;
|
nuclear@0
|
912 }
|
nuclear@0
|
913 else if (!ASSIMP_strincmp("target",filePtr,6))
|
nuclear@0
|
914 {
|
nuclear@0
|
915 ((ASE::Light&)node).mLightType = ASE::Light::TARGET;
|
nuclear@0
|
916 }
|
nuclear@0
|
917 else if (!ASSIMP_strincmp("free",filePtr,4))
|
nuclear@0
|
918 {
|
nuclear@0
|
919 ((ASE::Light&)node).mLightType = ASE::Light::FREE;
|
nuclear@0
|
920 }
|
nuclear@0
|
921 else if (!ASSIMP_strincmp("directional",filePtr,11))
|
nuclear@0
|
922 {
|
nuclear@0
|
923 ((ASE::Light&)node).mLightType = ASE::Light::DIRECTIONAL;
|
nuclear@0
|
924 }
|
nuclear@0
|
925 else
|
nuclear@0
|
926 {
|
nuclear@0
|
927 LogWarning("Unknown kind of light source");
|
nuclear@0
|
928 }
|
nuclear@0
|
929 continue;
|
nuclear@0
|
930 }
|
nuclear@0
|
931 }
|
nuclear@0
|
932 else if (node.mType == BaseNode::Camera)
|
nuclear@0
|
933 {
|
nuclear@0
|
934 // Camera settings
|
nuclear@0
|
935 if (TokenMatch(filePtr,"CAMERA_SETTINGS" ,15))
|
nuclear@0
|
936 {
|
nuclear@0
|
937 ParseLV2CameraSettingsBlock((ASE::Camera&)node);
|
nuclear@0
|
938 continue;
|
nuclear@0
|
939 }
|
nuclear@0
|
940 else if (TokenMatch(filePtr,"CAMERA_TYPE" ,11))
|
nuclear@0
|
941 {
|
nuclear@0
|
942 if (!ASSIMP_strincmp("target",filePtr,6))
|
nuclear@0
|
943 {
|
nuclear@0
|
944 ((ASE::Camera&)node).mCameraType = ASE::Camera::TARGET;
|
nuclear@0
|
945 }
|
nuclear@0
|
946 else if (!ASSIMP_strincmp("free",filePtr,4))
|
nuclear@0
|
947 {
|
nuclear@0
|
948 ((ASE::Camera&)node).mCameraType = ASE::Camera::FREE;
|
nuclear@0
|
949 }
|
nuclear@0
|
950 else
|
nuclear@0
|
951 {
|
nuclear@0
|
952 LogWarning("Unknown kind of camera");
|
nuclear@0
|
953 }
|
nuclear@0
|
954 continue;
|
nuclear@0
|
955 }
|
nuclear@0
|
956 }
|
nuclear@0
|
957 else if (node.mType == BaseNode::Mesh)
|
nuclear@0
|
958 {
|
nuclear@0
|
959 // mesh data
|
nuclear@0
|
960 // FIX: Older files use MESH_SOFTSKIN
|
nuclear@0
|
961 if (TokenMatch(filePtr,"MESH" ,4) ||
|
nuclear@0
|
962 TokenMatch(filePtr,"MESH_SOFTSKIN",13))
|
nuclear@0
|
963 {
|
nuclear@0
|
964 ParseLV2MeshBlock((ASE::Mesh&)node);
|
nuclear@0
|
965 continue;
|
nuclear@0
|
966 }
|
nuclear@0
|
967 // mesh material index
|
nuclear@0
|
968 if (TokenMatch(filePtr,"MATERIAL_REF" ,12))
|
nuclear@0
|
969 {
|
nuclear@0
|
970 ParseLV4MeshLong(((ASE::Mesh&)node).iMaterialIndex);
|
nuclear@0
|
971 continue;
|
nuclear@0
|
972 }
|
nuclear@0
|
973 }
|
nuclear@0
|
974 }
|
nuclear@0
|
975 AI_ASE_HANDLE_TOP_LEVEL_SECTION();
|
nuclear@0
|
976 }
|
nuclear@0
|
977 return;
|
nuclear@0
|
978 }
|
nuclear@0
|
979
|
nuclear@0
|
980 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
981 void Parser::ParseLV2CameraSettingsBlock(ASE::Camera& camera)
|
nuclear@0
|
982 {
|
nuclear@0
|
983 AI_ASE_PARSER_INIT();
|
nuclear@0
|
984 while (true)
|
nuclear@0
|
985 {
|
nuclear@0
|
986 if ('*' == *filePtr)
|
nuclear@0
|
987 {
|
nuclear@0
|
988 ++filePtr;
|
nuclear@0
|
989 if (TokenMatch(filePtr,"CAMERA_NEAR" ,11))
|
nuclear@0
|
990 {
|
nuclear@0
|
991 ParseLV4MeshFloat(camera.mNear);
|
nuclear@0
|
992 continue;
|
nuclear@0
|
993 }
|
nuclear@0
|
994 if (TokenMatch(filePtr,"CAMERA_FAR" ,10))
|
nuclear@0
|
995 {
|
nuclear@0
|
996 ParseLV4MeshFloat(camera.mFar);
|
nuclear@0
|
997 continue;
|
nuclear@0
|
998 }
|
nuclear@0
|
999 if (TokenMatch(filePtr,"CAMERA_FOV" ,10))
|
nuclear@0
|
1000 {
|
nuclear@0
|
1001 ParseLV4MeshFloat(camera.mFOV);
|
nuclear@0
|
1002 continue;
|
nuclear@0
|
1003 }
|
nuclear@0
|
1004 }
|
nuclear@0
|
1005 AI_ASE_HANDLE_SECTION("2","CAMERA_SETTINGS");
|
nuclear@0
|
1006 }
|
nuclear@0
|
1007 return;
|
nuclear@0
|
1008 }
|
nuclear@0
|
1009
|
nuclear@0
|
1010 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1011 void Parser::ParseLV2LightSettingsBlock(ASE::Light& light)
|
nuclear@0
|
1012 {
|
nuclear@0
|
1013 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1014 while (true)
|
nuclear@0
|
1015 {
|
nuclear@0
|
1016 if ('*' == *filePtr)
|
nuclear@0
|
1017 {
|
nuclear@0
|
1018 ++filePtr;
|
nuclear@0
|
1019 if (TokenMatch(filePtr,"LIGHT_COLOR" ,11))
|
nuclear@0
|
1020 {
|
nuclear@0
|
1021 ParseLV4MeshFloatTriple(&light.mColor.r);
|
nuclear@0
|
1022 continue;
|
nuclear@0
|
1023 }
|
nuclear@0
|
1024 if (TokenMatch(filePtr,"LIGHT_INTENS" ,12))
|
nuclear@0
|
1025 {
|
nuclear@0
|
1026 ParseLV4MeshFloat(light.mIntensity);
|
nuclear@0
|
1027 continue;
|
nuclear@0
|
1028 }
|
nuclear@0
|
1029 if (TokenMatch(filePtr,"LIGHT_HOTSPOT" ,13))
|
nuclear@0
|
1030 {
|
nuclear@0
|
1031 ParseLV4MeshFloat(light.mAngle);
|
nuclear@0
|
1032 continue;
|
nuclear@0
|
1033 }
|
nuclear@0
|
1034 if (TokenMatch(filePtr,"LIGHT_FALLOFF" ,13))
|
nuclear@0
|
1035 {
|
nuclear@0
|
1036 ParseLV4MeshFloat(light.mFalloff);
|
nuclear@0
|
1037 continue;
|
nuclear@0
|
1038 }
|
nuclear@0
|
1039 }
|
nuclear@0
|
1040 AI_ASE_HANDLE_SECTION("2","LIGHT_SETTINGS");
|
nuclear@0
|
1041 }
|
nuclear@0
|
1042 return;
|
nuclear@0
|
1043 }
|
nuclear@0
|
1044
|
nuclear@0
|
1045 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1046 void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh)
|
nuclear@0
|
1047 {
|
nuclear@0
|
1048 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1049
|
nuclear@0
|
1050 ASE::Animation* anim = &mesh.mAnim;
|
nuclear@0
|
1051 while (true)
|
nuclear@0
|
1052 {
|
nuclear@0
|
1053 if ('*' == *filePtr)
|
nuclear@0
|
1054 {
|
nuclear@0
|
1055 ++filePtr;
|
nuclear@0
|
1056 if (TokenMatch(filePtr,"NODE_NAME" ,9))
|
nuclear@0
|
1057 {
|
nuclear@0
|
1058 std::string temp;
|
nuclear@0
|
1059 if(!ParseString(temp,"*NODE_NAME"))
|
nuclear@0
|
1060 SkipToNextToken();
|
nuclear@0
|
1061
|
nuclear@0
|
1062 // If the name of the node contains .target it
|
nuclear@0
|
1063 // represents an animated camera or spot light
|
nuclear@0
|
1064 // target.
|
nuclear@0
|
1065 if (std::string::npos != temp.find(".Target"))
|
nuclear@0
|
1066 {
|
nuclear@0
|
1067 if ((mesh.mType != BaseNode::Camera || ((ASE::Camera&)mesh).mCameraType != ASE::Camera::TARGET) &&
|
nuclear@0
|
1068 ( mesh.mType != BaseNode::Light || ((ASE::Light&)mesh).mLightType != ASE::Light::TARGET))
|
nuclear@0
|
1069 {
|
nuclear@0
|
1070
|
nuclear@0
|
1071 DefaultLogger::get()->error("ASE: Found target animation channel "
|
nuclear@0
|
1072 "but the node is neither a camera nor a spot light");
|
nuclear@0
|
1073 anim = NULL;
|
nuclear@0
|
1074 }
|
nuclear@0
|
1075 else anim = &mesh.mTargetAnim;
|
nuclear@0
|
1076 }
|
nuclear@0
|
1077 continue;
|
nuclear@0
|
1078 }
|
nuclear@0
|
1079
|
nuclear@0
|
1080 // position keyframes
|
nuclear@0
|
1081 if (TokenMatch(filePtr,"CONTROL_POS_TRACK" ,17) ||
|
nuclear@0
|
1082 TokenMatch(filePtr,"CONTROL_POS_BEZIER" ,18) ||
|
nuclear@0
|
1083 TokenMatch(filePtr,"CONTROL_POS_TCB" ,15))
|
nuclear@0
|
1084 {
|
nuclear@0
|
1085 if (!anim)SkipSection();
|
nuclear@0
|
1086 else ParseLV3PosAnimationBlock(*anim);
|
nuclear@0
|
1087 continue;
|
nuclear@0
|
1088 }
|
nuclear@0
|
1089 // scaling keyframes
|
nuclear@0
|
1090 if (TokenMatch(filePtr,"CONTROL_SCALE_TRACK" ,19) ||
|
nuclear@0
|
1091 TokenMatch(filePtr,"CONTROL_SCALE_BEZIER" ,20) ||
|
nuclear@0
|
1092 TokenMatch(filePtr,"CONTROL_SCALE_TCB" ,17))
|
nuclear@0
|
1093 {
|
nuclear@0
|
1094 if (!anim || anim == &mesh.mTargetAnim)
|
nuclear@0
|
1095 {
|
nuclear@0
|
1096 // Target animation channels may have no rotation channels
|
nuclear@0
|
1097 DefaultLogger::get()->error("ASE: Ignoring scaling channel in target animation");
|
nuclear@0
|
1098 SkipSection();
|
nuclear@0
|
1099 }
|
nuclear@0
|
1100 else ParseLV3ScaleAnimationBlock(*anim);
|
nuclear@0
|
1101 continue;
|
nuclear@0
|
1102 }
|
nuclear@0
|
1103 // rotation keyframes
|
nuclear@0
|
1104 if (TokenMatch(filePtr,"CONTROL_ROT_TRACK" ,17) ||
|
nuclear@0
|
1105 TokenMatch(filePtr,"CONTROL_ROT_BEZIER" ,18) ||
|
nuclear@0
|
1106 TokenMatch(filePtr,"CONTROL_ROT_TCB" ,15))
|
nuclear@0
|
1107 {
|
nuclear@0
|
1108 if (!anim || anim == &mesh.mTargetAnim)
|
nuclear@0
|
1109 {
|
nuclear@0
|
1110 // Target animation channels may have no rotation channels
|
nuclear@0
|
1111 DefaultLogger::get()->error("ASE: Ignoring rotation channel in target animation");
|
nuclear@0
|
1112 SkipSection();
|
nuclear@0
|
1113 }
|
nuclear@0
|
1114 else ParseLV3RotAnimationBlock(*anim);
|
nuclear@0
|
1115 continue;
|
nuclear@0
|
1116 }
|
nuclear@0
|
1117 }
|
nuclear@0
|
1118 AI_ASE_HANDLE_SECTION("2","TM_ANIMATION");
|
nuclear@0
|
1119 }
|
nuclear@0
|
1120 }
|
nuclear@0
|
1121 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1122 void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation& anim)
|
nuclear@0
|
1123 {
|
nuclear@0
|
1124 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1125 unsigned int iIndex;
|
nuclear@0
|
1126
|
nuclear@0
|
1127 while (true)
|
nuclear@0
|
1128 {
|
nuclear@0
|
1129 if ('*' == *filePtr)
|
nuclear@0
|
1130 {
|
nuclear@0
|
1131 ++filePtr;
|
nuclear@0
|
1132
|
nuclear@0
|
1133 bool b = false;
|
nuclear@0
|
1134
|
nuclear@0
|
1135 // For the moment we're just reading the three floats -
|
nuclear@0
|
1136 // we ignore the ádditional information for bezier's and TCBs
|
nuclear@0
|
1137
|
nuclear@0
|
1138 // simple scaling keyframe
|
nuclear@0
|
1139 if (TokenMatch(filePtr,"CONTROL_SCALE_SAMPLE" ,20))
|
nuclear@0
|
1140 {
|
nuclear@0
|
1141 b = true;
|
nuclear@0
|
1142 anim.mScalingType = ASE::Animation::TRACK;
|
nuclear@0
|
1143 }
|
nuclear@0
|
1144
|
nuclear@0
|
1145 // Bezier scaling keyframe
|
nuclear@0
|
1146 if (TokenMatch(filePtr,"CONTROL_BEZIER_SCALE_KEY" ,24))
|
nuclear@0
|
1147 {
|
nuclear@0
|
1148 b = true;
|
nuclear@0
|
1149 anim.mScalingType = ASE::Animation::BEZIER;
|
nuclear@0
|
1150 }
|
nuclear@0
|
1151 // TCB scaling keyframe
|
nuclear@0
|
1152 if (TokenMatch(filePtr,"CONTROL_TCB_SCALE_KEY" ,21))
|
nuclear@0
|
1153 {
|
nuclear@0
|
1154 b = true;
|
nuclear@0
|
1155 anim.mScalingType = ASE::Animation::TCB;
|
nuclear@0
|
1156 }
|
nuclear@0
|
1157 if (b)
|
nuclear@0
|
1158 {
|
nuclear@0
|
1159 anim.akeyScaling.push_back(aiVectorKey());
|
nuclear@0
|
1160 aiVectorKey& key = anim.akeyScaling.back();
|
nuclear@0
|
1161 ParseLV4MeshFloatTriple(&key.mValue.x,iIndex);
|
nuclear@0
|
1162 key.mTime = (double)iIndex;
|
nuclear@0
|
1163 }
|
nuclear@0
|
1164 }
|
nuclear@0
|
1165 AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK");
|
nuclear@0
|
1166 }
|
nuclear@0
|
1167 }
|
nuclear@0
|
1168 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1169 void Parser::ParseLV3PosAnimationBlock(ASE::Animation& anim)
|
nuclear@0
|
1170 {
|
nuclear@0
|
1171 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1172 unsigned int iIndex;
|
nuclear@0
|
1173 while (true)
|
nuclear@0
|
1174 {
|
nuclear@0
|
1175 if ('*' == *filePtr)
|
nuclear@0
|
1176 {
|
nuclear@0
|
1177 ++filePtr;
|
nuclear@0
|
1178
|
nuclear@0
|
1179 bool b = false;
|
nuclear@0
|
1180
|
nuclear@0
|
1181 // For the moment we're just reading the three floats -
|
nuclear@0
|
1182 // we ignore the ádditional information for bezier's and TCBs
|
nuclear@0
|
1183
|
nuclear@0
|
1184 // simple scaling keyframe
|
nuclear@0
|
1185 if (TokenMatch(filePtr,"CONTROL_POS_SAMPLE" ,18))
|
nuclear@0
|
1186 {
|
nuclear@0
|
1187 b = true;
|
nuclear@0
|
1188 anim.mPositionType = ASE::Animation::TRACK;
|
nuclear@0
|
1189 }
|
nuclear@0
|
1190
|
nuclear@0
|
1191 // Bezier scaling keyframe
|
nuclear@0
|
1192 if (TokenMatch(filePtr,"CONTROL_BEZIER_POS_KEY" ,22))
|
nuclear@0
|
1193 {
|
nuclear@0
|
1194 b = true;
|
nuclear@0
|
1195 anim.mPositionType = ASE::Animation::BEZIER;
|
nuclear@0
|
1196 }
|
nuclear@0
|
1197 // TCB scaling keyframe
|
nuclear@0
|
1198 if (TokenMatch(filePtr,"CONTROL_TCB_POS_KEY" ,19))
|
nuclear@0
|
1199 {
|
nuclear@0
|
1200 b = true;
|
nuclear@0
|
1201 anim.mPositionType = ASE::Animation::TCB;
|
nuclear@0
|
1202 }
|
nuclear@0
|
1203 if (b)
|
nuclear@0
|
1204 {
|
nuclear@0
|
1205 anim.akeyPositions.push_back(aiVectorKey());
|
nuclear@0
|
1206 aiVectorKey& key = anim.akeyPositions.back();
|
nuclear@0
|
1207 ParseLV4MeshFloatTriple(&key.mValue.x,iIndex);
|
nuclear@0
|
1208 key.mTime = (double)iIndex;
|
nuclear@0
|
1209 }
|
nuclear@0
|
1210 }
|
nuclear@0
|
1211 AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK");
|
nuclear@0
|
1212 }
|
nuclear@0
|
1213 }
|
nuclear@0
|
1214 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1215 void Parser::ParseLV3RotAnimationBlock(ASE::Animation& anim)
|
nuclear@0
|
1216 {
|
nuclear@0
|
1217 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1218 unsigned int iIndex;
|
nuclear@0
|
1219 while (true)
|
nuclear@0
|
1220 {
|
nuclear@0
|
1221 if ('*' == *filePtr)
|
nuclear@0
|
1222 {
|
nuclear@0
|
1223 ++filePtr;
|
nuclear@0
|
1224
|
nuclear@0
|
1225 bool b = false;
|
nuclear@0
|
1226
|
nuclear@0
|
1227 // For the moment we're just reading the floats -
|
nuclear@0
|
1228 // we ignore the ádditional information for bezier's and TCBs
|
nuclear@0
|
1229
|
nuclear@0
|
1230 // simple scaling keyframe
|
nuclear@0
|
1231 if (TokenMatch(filePtr,"CONTROL_ROT_SAMPLE" ,18))
|
nuclear@0
|
1232 {
|
nuclear@0
|
1233 b = true;
|
nuclear@0
|
1234 anim.mRotationType = ASE::Animation::TRACK;
|
nuclear@0
|
1235 }
|
nuclear@0
|
1236
|
nuclear@0
|
1237 // Bezier scaling keyframe
|
nuclear@0
|
1238 if (TokenMatch(filePtr,"CONTROL_BEZIER_ROT_KEY" ,22))
|
nuclear@0
|
1239 {
|
nuclear@0
|
1240 b = true;
|
nuclear@0
|
1241 anim.mRotationType = ASE::Animation::BEZIER;
|
nuclear@0
|
1242 }
|
nuclear@0
|
1243 // TCB scaling keyframe
|
nuclear@0
|
1244 if (TokenMatch(filePtr,"CONTROL_TCB_ROT_KEY" ,19))
|
nuclear@0
|
1245 {
|
nuclear@0
|
1246 b = true;
|
nuclear@0
|
1247 anim.mRotationType = ASE::Animation::TCB;
|
nuclear@0
|
1248 }
|
nuclear@0
|
1249 if (b)
|
nuclear@0
|
1250 {
|
nuclear@0
|
1251 anim.akeyRotations.push_back(aiQuatKey());
|
nuclear@0
|
1252 aiQuatKey& key = anim.akeyRotations.back();
|
nuclear@0
|
1253 aiVector3D v;float f;
|
nuclear@0
|
1254 ParseLV4MeshFloatTriple(&v.x,iIndex);
|
nuclear@0
|
1255 ParseLV4MeshFloat(f);
|
nuclear@0
|
1256 key.mTime = (double)iIndex;
|
nuclear@0
|
1257 key.mValue = aiQuaternion(v,f);
|
nuclear@0
|
1258 }
|
nuclear@0
|
1259 }
|
nuclear@0
|
1260 AI_ASE_HANDLE_SECTION("3","*CONTROL_ROT_TRACK");
|
nuclear@0
|
1261 }
|
nuclear@0
|
1262 }
|
nuclear@0
|
1263 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1264 void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode& mesh)
|
nuclear@0
|
1265 {
|
nuclear@0
|
1266 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1267 int mode = 0;
|
nuclear@0
|
1268 while (true)
|
nuclear@0
|
1269 {
|
nuclear@0
|
1270 if ('*' == *filePtr)
|
nuclear@0
|
1271 {
|
nuclear@0
|
1272 ++filePtr;
|
nuclear@0
|
1273 // name of the node
|
nuclear@0
|
1274 if (TokenMatch(filePtr,"NODE_NAME" ,9))
|
nuclear@0
|
1275 {
|
nuclear@0
|
1276 std::string temp;
|
nuclear@0
|
1277 if(!ParseString(temp,"*NODE_NAME"))
|
nuclear@0
|
1278 SkipToNextToken();
|
nuclear@0
|
1279
|
nuclear@0
|
1280 std::string::size_type s;
|
nuclear@0
|
1281 if (temp == mesh.mName)
|
nuclear@0
|
1282 {
|
nuclear@0
|
1283 mode = 1;
|
nuclear@0
|
1284 }
|
nuclear@0
|
1285 else if (std::string::npos != (s = temp.find(".Target")) &&
|
nuclear@0
|
1286 mesh.mName == temp.substr(0,s))
|
nuclear@0
|
1287 {
|
nuclear@0
|
1288 // This should be either a target light or a target camera
|
nuclear@0
|
1289 if ( (mesh.mType == BaseNode::Light && ((ASE::Light&)mesh) .mLightType == ASE::Light::TARGET) ||
|
nuclear@0
|
1290 (mesh.mType == BaseNode::Camera && ((ASE::Camera&)mesh).mCameraType == ASE::Camera::TARGET))
|
nuclear@0
|
1291 {
|
nuclear@0
|
1292 mode = 2;
|
nuclear@0
|
1293 }
|
nuclear@0
|
1294 else DefaultLogger::get()->error("ASE: Ignoring target transform, "
|
nuclear@0
|
1295 "this is no spot light or target camera");
|
nuclear@0
|
1296 }
|
nuclear@0
|
1297 else
|
nuclear@0
|
1298 {
|
nuclear@0
|
1299 DefaultLogger::get()->error("ASE: Unknown node transformation: " + temp);
|
nuclear@0
|
1300 // mode = 0
|
nuclear@0
|
1301 }
|
nuclear@0
|
1302 continue;
|
nuclear@0
|
1303 }
|
nuclear@0
|
1304 if (mode)
|
nuclear@0
|
1305 {
|
nuclear@0
|
1306 // fourth row of the transformation matrix - and also the
|
nuclear@0
|
1307 // only information here that is interesting for targets
|
nuclear@0
|
1308 if (TokenMatch(filePtr,"TM_ROW3" ,7))
|
nuclear@0
|
1309 {
|
nuclear@0
|
1310 ParseLV4MeshFloatTriple((mode == 1 ? mesh.mTransform[3] : &mesh.mTargetPosition.x));
|
nuclear@0
|
1311 continue;
|
nuclear@0
|
1312 }
|
nuclear@0
|
1313 if (mode == 1)
|
nuclear@0
|
1314 {
|
nuclear@0
|
1315 // first row of the transformation matrix
|
nuclear@0
|
1316 if (TokenMatch(filePtr,"TM_ROW0" ,7))
|
nuclear@0
|
1317 {
|
nuclear@0
|
1318 ParseLV4MeshFloatTriple(mesh.mTransform[0]);
|
nuclear@0
|
1319 continue;
|
nuclear@0
|
1320 }
|
nuclear@0
|
1321 // second row of the transformation matrix
|
nuclear@0
|
1322 if (TokenMatch(filePtr,"TM_ROW1" ,7))
|
nuclear@0
|
1323 {
|
nuclear@0
|
1324 ParseLV4MeshFloatTriple(mesh.mTransform[1]);
|
nuclear@0
|
1325 continue;
|
nuclear@0
|
1326 }
|
nuclear@0
|
1327 // third row of the transformation matrix
|
nuclear@0
|
1328 if (TokenMatch(filePtr,"TM_ROW2" ,7))
|
nuclear@0
|
1329 {
|
nuclear@0
|
1330 ParseLV4MeshFloatTriple(mesh.mTransform[2]);
|
nuclear@0
|
1331 continue;
|
nuclear@0
|
1332 }
|
nuclear@0
|
1333 // inherited position axes
|
nuclear@0
|
1334 if (TokenMatch(filePtr,"INHERIT_POS" ,11))
|
nuclear@0
|
1335 {
|
nuclear@0
|
1336 unsigned int aiVal[3];
|
nuclear@0
|
1337 ParseLV4MeshLongTriple(aiVal);
|
nuclear@0
|
1338
|
nuclear@0
|
1339 for (unsigned int i = 0; i < 3;++i)
|
nuclear@0
|
1340 mesh.inherit.abInheritPosition[i] = aiVal[i] != 0;
|
nuclear@0
|
1341 continue;
|
nuclear@0
|
1342 }
|
nuclear@0
|
1343 // inherited rotation axes
|
nuclear@0
|
1344 if (TokenMatch(filePtr,"INHERIT_ROT" ,11))
|
nuclear@0
|
1345 {
|
nuclear@0
|
1346 unsigned int aiVal[3];
|
nuclear@0
|
1347 ParseLV4MeshLongTriple(aiVal);
|
nuclear@0
|
1348
|
nuclear@0
|
1349 for (unsigned int i = 0; i < 3;++i)
|
nuclear@0
|
1350 mesh.inherit.abInheritRotation[i] = aiVal[i] != 0;
|
nuclear@0
|
1351 continue;
|
nuclear@0
|
1352 }
|
nuclear@0
|
1353 // inherited scaling axes
|
nuclear@0
|
1354 if (TokenMatch(filePtr,"INHERIT_SCL" ,11))
|
nuclear@0
|
1355 {
|
nuclear@0
|
1356 unsigned int aiVal[3];
|
nuclear@0
|
1357 ParseLV4MeshLongTriple(aiVal);
|
nuclear@0
|
1358
|
nuclear@0
|
1359 for (unsigned int i = 0; i < 3;++i)
|
nuclear@0
|
1360 mesh.inherit.abInheritScaling[i] = aiVal[i] != 0;
|
nuclear@0
|
1361 continue;
|
nuclear@0
|
1362 }
|
nuclear@0
|
1363 }
|
nuclear@0
|
1364 }
|
nuclear@0
|
1365 }
|
nuclear@0
|
1366 AI_ASE_HANDLE_SECTION("2","*NODE_TM");
|
nuclear@0
|
1367 }
|
nuclear@0
|
1368 return;
|
nuclear@0
|
1369 }
|
nuclear@0
|
1370 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1371 void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
|
nuclear@0
|
1372 {
|
nuclear@0
|
1373 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1374
|
nuclear@0
|
1375 unsigned int iNumVertices = 0;
|
nuclear@0
|
1376 unsigned int iNumFaces = 0;
|
nuclear@0
|
1377 unsigned int iNumTVertices = 0;
|
nuclear@0
|
1378 unsigned int iNumTFaces = 0;
|
nuclear@0
|
1379 unsigned int iNumCVertices = 0;
|
nuclear@0
|
1380 unsigned int iNumCFaces = 0;
|
nuclear@0
|
1381 while (true)
|
nuclear@0
|
1382 {
|
nuclear@0
|
1383 if ('*' == *filePtr)
|
nuclear@0
|
1384 {
|
nuclear@0
|
1385 ++filePtr;
|
nuclear@0
|
1386 // Number of vertices in the mesh
|
nuclear@0
|
1387 if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14))
|
nuclear@0
|
1388 {
|
nuclear@0
|
1389 ParseLV4MeshLong(iNumVertices);
|
nuclear@0
|
1390 continue;
|
nuclear@0
|
1391 }
|
nuclear@0
|
1392 // Number of texture coordinates in the mesh
|
nuclear@0
|
1393 if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15))
|
nuclear@0
|
1394 {
|
nuclear@0
|
1395 ParseLV4MeshLong(iNumTVertices);
|
nuclear@0
|
1396 continue;
|
nuclear@0
|
1397 }
|
nuclear@0
|
1398 // Number of vertex colors in the mesh
|
nuclear@0
|
1399 if (TokenMatch(filePtr,"MESH_NUMCVERTEX" ,15))
|
nuclear@0
|
1400 {
|
nuclear@0
|
1401 ParseLV4MeshLong(iNumCVertices);
|
nuclear@0
|
1402 continue;
|
nuclear@0
|
1403 }
|
nuclear@0
|
1404 // Number of regular faces in the mesh
|
nuclear@0
|
1405 if (TokenMatch(filePtr,"MESH_NUMFACES" ,13))
|
nuclear@0
|
1406 {
|
nuclear@0
|
1407 ParseLV4MeshLong(iNumFaces);
|
nuclear@0
|
1408 continue;
|
nuclear@0
|
1409 }
|
nuclear@0
|
1410 // Number of UVWed faces in the mesh
|
nuclear@0
|
1411 if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15))
|
nuclear@0
|
1412 {
|
nuclear@0
|
1413 ParseLV4MeshLong(iNumTFaces);
|
nuclear@0
|
1414 continue;
|
nuclear@0
|
1415 }
|
nuclear@0
|
1416 // Number of colored faces in the mesh
|
nuclear@0
|
1417 if (TokenMatch(filePtr,"MESH_NUMCVFACES" ,15))
|
nuclear@0
|
1418 {
|
nuclear@0
|
1419 ParseLV4MeshLong(iNumCFaces);
|
nuclear@0
|
1420 continue;
|
nuclear@0
|
1421 }
|
nuclear@0
|
1422 // mesh vertex list block
|
nuclear@0
|
1423 if (TokenMatch(filePtr,"MESH_VERTEX_LIST" ,16))
|
nuclear@0
|
1424 {
|
nuclear@0
|
1425 ParseLV3MeshVertexListBlock(iNumVertices,mesh);
|
nuclear@0
|
1426 continue;
|
nuclear@0
|
1427 }
|
nuclear@0
|
1428 // mesh face list block
|
nuclear@0
|
1429 if (TokenMatch(filePtr,"MESH_FACE_LIST" ,14))
|
nuclear@0
|
1430 {
|
nuclear@0
|
1431 ParseLV3MeshFaceListBlock(iNumFaces,mesh);
|
nuclear@0
|
1432 continue;
|
nuclear@0
|
1433 }
|
nuclear@0
|
1434 // mesh texture vertex list block
|
nuclear@0
|
1435 if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14))
|
nuclear@0
|
1436 {
|
nuclear@0
|
1437 ParseLV3MeshTListBlock(iNumTVertices,mesh);
|
nuclear@0
|
1438 continue;
|
nuclear@0
|
1439 }
|
nuclear@0
|
1440 // mesh texture face block
|
nuclear@0
|
1441 if (TokenMatch(filePtr,"MESH_TFACELIST" ,14))
|
nuclear@0
|
1442 {
|
nuclear@0
|
1443 ParseLV3MeshTFaceListBlock(iNumTFaces,mesh);
|
nuclear@0
|
1444 continue;
|
nuclear@0
|
1445 }
|
nuclear@0
|
1446 // mesh color vertex list block
|
nuclear@0
|
1447 if (TokenMatch(filePtr,"MESH_CVERTLIST" ,14))
|
nuclear@0
|
1448 {
|
nuclear@0
|
1449 ParseLV3MeshCListBlock(iNumCVertices,mesh);
|
nuclear@0
|
1450 continue;
|
nuclear@0
|
1451 }
|
nuclear@0
|
1452 // mesh color face block
|
nuclear@0
|
1453 if (TokenMatch(filePtr,"MESH_CFACELIST" ,14))
|
nuclear@0
|
1454 {
|
nuclear@0
|
1455 ParseLV3MeshCFaceListBlock(iNumCFaces,mesh);
|
nuclear@0
|
1456 continue;
|
nuclear@0
|
1457 }
|
nuclear@0
|
1458 // mesh normals
|
nuclear@0
|
1459 if (TokenMatch(filePtr,"MESH_NORMALS" ,12))
|
nuclear@0
|
1460 {
|
nuclear@0
|
1461 ParseLV3MeshNormalListBlock(mesh);
|
nuclear@0
|
1462 continue;
|
nuclear@0
|
1463 }
|
nuclear@0
|
1464 // another mesh UV channel ...
|
nuclear@0
|
1465 if (TokenMatch(filePtr,"MESH_MAPPINGCHANNEL" ,19))
|
nuclear@0
|
1466 {
|
nuclear@0
|
1467
|
nuclear@0
|
1468 unsigned int iIndex = 0;
|
nuclear@0
|
1469 ParseLV4MeshLong(iIndex);
|
nuclear@0
|
1470
|
nuclear@0
|
1471 if (iIndex < 2)
|
nuclear@0
|
1472 {
|
nuclear@0
|
1473 LogWarning("Mapping channel has an invalid index. Skipping UV channel");
|
nuclear@0
|
1474 // skip it ...
|
nuclear@0
|
1475 SkipSection();
|
nuclear@0
|
1476 }
|
nuclear@0
|
1477 if (iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS)
|
nuclear@0
|
1478 {
|
nuclear@0
|
1479 LogWarning("Too many UV channels specified. Skipping channel ..");
|
nuclear@0
|
1480 // skip it ...
|
nuclear@0
|
1481 SkipSection();
|
nuclear@0
|
1482 }
|
nuclear@0
|
1483 else
|
nuclear@0
|
1484 {
|
nuclear@0
|
1485 // parse the mapping channel
|
nuclear@0
|
1486 ParseLV3MappingChannel(iIndex-1,mesh);
|
nuclear@0
|
1487 }
|
nuclear@0
|
1488 continue;
|
nuclear@0
|
1489 }
|
nuclear@0
|
1490 // mesh animation keyframe. Not supported
|
nuclear@0
|
1491 if (TokenMatch(filePtr,"MESH_ANIMATION" ,14))
|
nuclear@0
|
1492 {
|
nuclear@0
|
1493
|
nuclear@0
|
1494 LogWarning("Found *MESH_ANIMATION element in ASE/ASK file. "
|
nuclear@0
|
1495 "Keyframe animation is not supported by Assimp, this element "
|
nuclear@0
|
1496 "will be ignored");
|
nuclear@0
|
1497 //SkipSection();
|
nuclear@0
|
1498 continue;
|
nuclear@0
|
1499 }
|
nuclear@0
|
1500 if (TokenMatch(filePtr,"MESH_WEIGHTS" ,12))
|
nuclear@0
|
1501 {
|
nuclear@0
|
1502 ParseLV3MeshWeightsBlock(mesh);continue;
|
nuclear@0
|
1503 }
|
nuclear@0
|
1504 }
|
nuclear@0
|
1505 AI_ASE_HANDLE_SECTION("2","*MESH");
|
nuclear@0
|
1506 }
|
nuclear@0
|
1507 return;
|
nuclear@0
|
1508 }
|
nuclear@0
|
1509 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1510 void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh)
|
nuclear@0
|
1511 {
|
nuclear@0
|
1512 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1513
|
nuclear@0
|
1514 unsigned int iNumVertices = 0, iNumBones = 0;
|
nuclear@0
|
1515 while (true)
|
nuclear@0
|
1516 {
|
nuclear@0
|
1517 if ('*' == *filePtr)
|
nuclear@0
|
1518 {
|
nuclear@0
|
1519 ++filePtr;
|
nuclear@0
|
1520
|
nuclear@0
|
1521 // Number of bone vertices ...
|
nuclear@0
|
1522 if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14))
|
nuclear@0
|
1523 {
|
nuclear@0
|
1524 ParseLV4MeshLong(iNumVertices);
|
nuclear@0
|
1525 continue;
|
nuclear@0
|
1526 }
|
nuclear@0
|
1527 // Number of bones
|
nuclear@0
|
1528 if (TokenMatch(filePtr,"MESH_NUMBONE" ,11))
|
nuclear@0
|
1529 {
|
nuclear@0
|
1530 ParseLV4MeshLong(iNumBones);
|
nuclear@0
|
1531 continue;
|
nuclear@0
|
1532 }
|
nuclear@0
|
1533 // parse the list of bones
|
nuclear@0
|
1534 if (TokenMatch(filePtr,"MESH_BONE_LIST" ,14))
|
nuclear@0
|
1535 {
|
nuclear@0
|
1536 ParseLV4MeshBones(iNumBones,mesh);
|
nuclear@0
|
1537 continue;
|
nuclear@0
|
1538 }
|
nuclear@0
|
1539 // parse the list of bones vertices
|
nuclear@0
|
1540 if (TokenMatch(filePtr,"MESH_BONE_VERTEX_LIST" ,21) )
|
nuclear@0
|
1541 {
|
nuclear@0
|
1542 ParseLV4MeshBonesVertices(iNumVertices,mesh);
|
nuclear@0
|
1543 continue;
|
nuclear@0
|
1544 }
|
nuclear@0
|
1545 }
|
nuclear@0
|
1546 AI_ASE_HANDLE_SECTION("3","*MESH_WEIGHTS");
|
nuclear@0
|
1547 }
|
nuclear@0
|
1548 return;
|
nuclear@0
|
1549 }
|
nuclear@0
|
1550 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1551 void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh)
|
nuclear@0
|
1552 {
|
nuclear@0
|
1553 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1554 mesh.mBones.resize(iNumBones);
|
nuclear@0
|
1555 while (true)
|
nuclear@0
|
1556 {
|
nuclear@0
|
1557 if ('*' == *filePtr)
|
nuclear@0
|
1558 {
|
nuclear@0
|
1559 ++filePtr;
|
nuclear@0
|
1560
|
nuclear@0
|
1561 // Mesh bone with name ...
|
nuclear@0
|
1562 if (TokenMatch(filePtr,"MESH_BONE_NAME" ,16))
|
nuclear@0
|
1563 {
|
nuclear@0
|
1564 // parse an index ...
|
nuclear@0
|
1565 if(SkipSpaces(&filePtr))
|
nuclear@0
|
1566 {
|
nuclear@0
|
1567 unsigned int iIndex = strtoul10(filePtr,&filePtr);
|
nuclear@0
|
1568 if (iIndex >= iNumBones)
|
nuclear@0
|
1569 {
|
nuclear@0
|
1570 LogWarning("Bone index is out of bounds");
|
nuclear@0
|
1571 continue;
|
nuclear@0
|
1572 }
|
nuclear@0
|
1573 if (!ParseString(mesh.mBones[iIndex].mName,"*MESH_BONE_NAME"))
|
nuclear@0
|
1574 SkipToNextToken();
|
nuclear@0
|
1575 continue;
|
nuclear@0
|
1576 }
|
nuclear@0
|
1577 }
|
nuclear@0
|
1578 }
|
nuclear@0
|
1579 AI_ASE_HANDLE_SECTION("3","*MESH_BONE_LIST");
|
nuclear@0
|
1580 }
|
nuclear@0
|
1581 }
|
nuclear@0
|
1582 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1583 void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices,ASE::Mesh& mesh)
|
nuclear@0
|
1584 {
|
nuclear@0
|
1585 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1586 mesh.mBoneVertices.resize(iNumVertices);
|
nuclear@0
|
1587 while (true)
|
nuclear@0
|
1588 {
|
nuclear@0
|
1589 if ('*' == *filePtr)
|
nuclear@0
|
1590 {
|
nuclear@0
|
1591 ++filePtr;
|
nuclear@0
|
1592
|
nuclear@0
|
1593 // Mesh bone vertex
|
nuclear@0
|
1594 if (TokenMatch(filePtr,"MESH_BONE_VERTEX" ,16))
|
nuclear@0
|
1595 {
|
nuclear@0
|
1596 // read the vertex index
|
nuclear@0
|
1597 unsigned int iIndex = strtoul10(filePtr,&filePtr);
|
nuclear@0
|
1598 if (iIndex >= mesh.mPositions.size())
|
nuclear@0
|
1599 {
|
nuclear@0
|
1600 iIndex = (unsigned int)mesh.mPositions.size()-1;
|
nuclear@0
|
1601 LogWarning("Bone vertex index is out of bounds. Using the largest valid "
|
nuclear@0
|
1602 "bone vertex index instead");
|
nuclear@0
|
1603 }
|
nuclear@0
|
1604
|
nuclear@0
|
1605 // --- ignored
|
nuclear@0
|
1606 float afVert[3];
|
nuclear@0
|
1607 ParseLV4MeshFloatTriple(afVert);
|
nuclear@0
|
1608
|
nuclear@0
|
1609 std::pair<int,float> pairOut;
|
nuclear@0
|
1610 while (true)
|
nuclear@0
|
1611 {
|
nuclear@0
|
1612 // first parse the bone index ...
|
nuclear@0
|
1613 if (!SkipSpaces(&filePtr))break;
|
nuclear@0
|
1614 pairOut.first = strtoul10(filePtr,&filePtr);
|
nuclear@0
|
1615
|
nuclear@0
|
1616 // then parse the vertex weight
|
nuclear@0
|
1617 if (!SkipSpaces(&filePtr))break;
|
nuclear@0
|
1618 filePtr = fast_atoreal_move<float>(filePtr,pairOut.second);
|
nuclear@0
|
1619
|
nuclear@0
|
1620 // -1 marks unused entries
|
nuclear@0
|
1621 if (-1 != pairOut.first)
|
nuclear@0
|
1622 {
|
nuclear@0
|
1623 mesh.mBoneVertices[iIndex].mBoneWeights.push_back(pairOut);
|
nuclear@0
|
1624 }
|
nuclear@0
|
1625 }
|
nuclear@0
|
1626 continue;
|
nuclear@0
|
1627 }
|
nuclear@0
|
1628 }
|
nuclear@0
|
1629 AI_ASE_HANDLE_SECTION("4","*MESH_BONE_VERTEX");
|
nuclear@0
|
1630 }
|
nuclear@0
|
1631 return;
|
nuclear@0
|
1632 }
|
nuclear@0
|
1633 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1634 void Parser::ParseLV3MeshVertexListBlock(
|
nuclear@0
|
1635 unsigned int iNumVertices, ASE::Mesh& mesh)
|
nuclear@0
|
1636 {
|
nuclear@0
|
1637 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1638
|
nuclear@0
|
1639 // allocate enough storage in the array
|
nuclear@0
|
1640 mesh.mPositions.resize(iNumVertices);
|
nuclear@0
|
1641 while (true)
|
nuclear@0
|
1642 {
|
nuclear@0
|
1643 if ('*' == *filePtr)
|
nuclear@0
|
1644 {
|
nuclear@0
|
1645 ++filePtr;
|
nuclear@0
|
1646
|
nuclear@0
|
1647 // Vertex entry
|
nuclear@0
|
1648 if (TokenMatch(filePtr,"MESH_VERTEX" ,11))
|
nuclear@0
|
1649 {
|
nuclear@0
|
1650
|
nuclear@0
|
1651 aiVector3D vTemp;
|
nuclear@0
|
1652 unsigned int iIndex;
|
nuclear@0
|
1653 ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
|
nuclear@0
|
1654
|
nuclear@0
|
1655 if (iIndex >= iNumVertices)
|
nuclear@0
|
1656 {
|
nuclear@0
|
1657 LogWarning("Invalid vertex index. It will be ignored");
|
nuclear@0
|
1658 }
|
nuclear@0
|
1659 else mesh.mPositions[iIndex] = vTemp;
|
nuclear@0
|
1660 continue;
|
nuclear@0
|
1661 }
|
nuclear@0
|
1662 }
|
nuclear@0
|
1663 AI_ASE_HANDLE_SECTION("3","*MESH_VERTEX_LIST");
|
nuclear@0
|
1664 }
|
nuclear@0
|
1665 return;
|
nuclear@0
|
1666 }
|
nuclear@0
|
1667 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1668 void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
|
nuclear@0
|
1669 {
|
nuclear@0
|
1670 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1671
|
nuclear@0
|
1672 // allocate enough storage in the face array
|
nuclear@0
|
1673 mesh.mFaces.resize(iNumFaces);
|
nuclear@0
|
1674 while (true)
|
nuclear@0
|
1675 {
|
nuclear@0
|
1676 if ('*' == *filePtr)
|
nuclear@0
|
1677 {
|
nuclear@0
|
1678 ++filePtr;
|
nuclear@0
|
1679
|
nuclear@0
|
1680 // Face entry
|
nuclear@0
|
1681 if (TokenMatch(filePtr,"MESH_FACE" ,9))
|
nuclear@0
|
1682 {
|
nuclear@0
|
1683
|
nuclear@0
|
1684 ASE::Face mFace;
|
nuclear@0
|
1685 ParseLV4MeshFace(mFace);
|
nuclear@0
|
1686
|
nuclear@0
|
1687 if (mFace.iFace >= iNumFaces)
|
nuclear@0
|
1688 {
|
nuclear@0
|
1689 LogWarning("Face has an invalid index. It will be ignored");
|
nuclear@0
|
1690 }
|
nuclear@0
|
1691 else mesh.mFaces[mFace.iFace] = mFace;
|
nuclear@0
|
1692 continue;
|
nuclear@0
|
1693 }
|
nuclear@0
|
1694 }
|
nuclear@0
|
1695 AI_ASE_HANDLE_SECTION("3","*MESH_FACE_LIST");
|
nuclear@0
|
1696 }
|
nuclear@0
|
1697 return;
|
nuclear@0
|
1698 }
|
nuclear@0
|
1699 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1700 void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
|
nuclear@0
|
1701 ASE::Mesh& mesh, unsigned int iChannel)
|
nuclear@0
|
1702 {
|
nuclear@0
|
1703 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1704
|
nuclear@0
|
1705 // allocate enough storage in the array
|
nuclear@0
|
1706 mesh.amTexCoords[iChannel].resize(iNumVertices);
|
nuclear@0
|
1707 while (true)
|
nuclear@0
|
1708 {
|
nuclear@0
|
1709 if ('*' == *filePtr)
|
nuclear@0
|
1710 {
|
nuclear@0
|
1711 ++filePtr;
|
nuclear@0
|
1712
|
nuclear@0
|
1713 // Vertex entry
|
nuclear@0
|
1714 if (TokenMatch(filePtr,"MESH_TVERT" ,10))
|
nuclear@0
|
1715 {
|
nuclear@0
|
1716 aiVector3D vTemp;
|
nuclear@0
|
1717 unsigned int iIndex;
|
nuclear@0
|
1718 ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
|
nuclear@0
|
1719
|
nuclear@0
|
1720 if (iIndex >= iNumVertices)
|
nuclear@0
|
1721 {
|
nuclear@0
|
1722 LogWarning("Tvertex has an invalid index. It will be ignored");
|
nuclear@0
|
1723 }
|
nuclear@0
|
1724 else mesh.amTexCoords[iChannel][iIndex] = vTemp;
|
nuclear@0
|
1725
|
nuclear@0
|
1726 if (0.0f != vTemp.z)
|
nuclear@0
|
1727 {
|
nuclear@0
|
1728 // we need 3 coordinate channels
|
nuclear@0
|
1729 mesh.mNumUVComponents[iChannel] = 3;
|
nuclear@0
|
1730 }
|
nuclear@0
|
1731 continue;
|
nuclear@0
|
1732 }
|
nuclear@0
|
1733 }
|
nuclear@0
|
1734 AI_ASE_HANDLE_SECTION("3","*MESH_TVERT_LIST");
|
nuclear@0
|
1735 }
|
nuclear@0
|
1736 return;
|
nuclear@0
|
1737 }
|
nuclear@0
|
1738 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1739 void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
|
nuclear@0
|
1740 ASE::Mesh& mesh, unsigned int iChannel)
|
nuclear@0
|
1741 {
|
nuclear@0
|
1742 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1743 while (true)
|
nuclear@0
|
1744 {
|
nuclear@0
|
1745 if ('*' == *filePtr)
|
nuclear@0
|
1746 {
|
nuclear@0
|
1747 ++filePtr;
|
nuclear@0
|
1748
|
nuclear@0
|
1749 // Face entry
|
nuclear@0
|
1750 if (TokenMatch(filePtr,"MESH_TFACE" ,10))
|
nuclear@0
|
1751 {
|
nuclear@0
|
1752 unsigned int aiValues[3];
|
nuclear@0
|
1753 unsigned int iIndex = 0;
|
nuclear@0
|
1754
|
nuclear@0
|
1755 ParseLV4MeshLongTriple(aiValues,iIndex);
|
nuclear@0
|
1756 if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
|
nuclear@0
|
1757 {
|
nuclear@0
|
1758 LogWarning("UV-Face has an invalid index. It will be ignored");
|
nuclear@0
|
1759 }
|
nuclear@0
|
1760 else
|
nuclear@0
|
1761 {
|
nuclear@0
|
1762 // copy UV indices
|
nuclear@0
|
1763 mesh.mFaces[iIndex].amUVIndices[iChannel][0] = aiValues[0];
|
nuclear@0
|
1764 mesh.mFaces[iIndex].amUVIndices[iChannel][1] = aiValues[1];
|
nuclear@0
|
1765 mesh.mFaces[iIndex].amUVIndices[iChannel][2] = aiValues[2];
|
nuclear@0
|
1766 }
|
nuclear@0
|
1767 continue;
|
nuclear@0
|
1768 }
|
nuclear@0
|
1769 }
|
nuclear@0
|
1770 AI_ASE_HANDLE_SECTION("3","*MESH_TFACE_LIST");
|
nuclear@0
|
1771 }
|
nuclear@0
|
1772 return;
|
nuclear@0
|
1773 }
|
nuclear@0
|
1774 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1775 void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh& mesh)
|
nuclear@0
|
1776 {
|
nuclear@0
|
1777 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1778
|
nuclear@0
|
1779 unsigned int iNumTVertices = 0;
|
nuclear@0
|
1780 unsigned int iNumTFaces = 0;
|
nuclear@0
|
1781 while (true)
|
nuclear@0
|
1782 {
|
nuclear@0
|
1783 if ('*' == *filePtr)
|
nuclear@0
|
1784 {
|
nuclear@0
|
1785 ++filePtr;
|
nuclear@0
|
1786
|
nuclear@0
|
1787 // Number of texture coordinates in the mesh
|
nuclear@0
|
1788 if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15))
|
nuclear@0
|
1789 {
|
nuclear@0
|
1790 ParseLV4MeshLong(iNumTVertices);
|
nuclear@0
|
1791 continue;
|
nuclear@0
|
1792 }
|
nuclear@0
|
1793 // Number of UVWed faces in the mesh
|
nuclear@0
|
1794 if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15))
|
nuclear@0
|
1795 {
|
nuclear@0
|
1796 ParseLV4MeshLong(iNumTFaces);
|
nuclear@0
|
1797 continue;
|
nuclear@0
|
1798 }
|
nuclear@0
|
1799 // mesh texture vertex list block
|
nuclear@0
|
1800 if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14))
|
nuclear@0
|
1801 {
|
nuclear@0
|
1802 ParseLV3MeshTListBlock(iNumTVertices,mesh,iChannel);
|
nuclear@0
|
1803 continue;
|
nuclear@0
|
1804 }
|
nuclear@0
|
1805 // mesh texture face block
|
nuclear@0
|
1806 if (TokenMatch(filePtr,"MESH_TFACELIST" ,14))
|
nuclear@0
|
1807 {
|
nuclear@0
|
1808 ParseLV3MeshTFaceListBlock(iNumTFaces,mesh, iChannel);
|
nuclear@0
|
1809 continue;
|
nuclear@0
|
1810 }
|
nuclear@0
|
1811 }
|
nuclear@0
|
1812 AI_ASE_HANDLE_SECTION("3","*MESH_MAPPING_CHANNEL");
|
nuclear@0
|
1813 }
|
nuclear@0
|
1814 return;
|
nuclear@0
|
1815 }
|
nuclear@0
|
1816 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1817 void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh& mesh)
|
nuclear@0
|
1818 {
|
nuclear@0
|
1819 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1820
|
nuclear@0
|
1821 // allocate enough storage in the array
|
nuclear@0
|
1822 mesh.mVertexColors.resize(iNumVertices);
|
nuclear@0
|
1823 while (true)
|
nuclear@0
|
1824 {
|
nuclear@0
|
1825 if ('*' == *filePtr)
|
nuclear@0
|
1826 {
|
nuclear@0
|
1827 ++filePtr;
|
nuclear@0
|
1828
|
nuclear@0
|
1829 // Vertex entry
|
nuclear@0
|
1830 if (TokenMatch(filePtr,"MESH_VERTCOL" ,12))
|
nuclear@0
|
1831 {
|
nuclear@0
|
1832 aiColor4D vTemp;
|
nuclear@0
|
1833 vTemp.a = 1.0f;
|
nuclear@0
|
1834 unsigned int iIndex;
|
nuclear@0
|
1835 ParseLV4MeshFloatTriple(&vTemp.r,iIndex);
|
nuclear@0
|
1836
|
nuclear@0
|
1837 if (iIndex >= iNumVertices)
|
nuclear@0
|
1838 {
|
nuclear@0
|
1839 LogWarning("Vertex color has an invalid index. It will be ignored");
|
nuclear@0
|
1840 }
|
nuclear@0
|
1841 else mesh.mVertexColors[iIndex] = vTemp;
|
nuclear@0
|
1842 continue;
|
nuclear@0
|
1843 }
|
nuclear@0
|
1844 }
|
nuclear@0
|
1845 AI_ASE_HANDLE_SECTION("3","*MESH_CVERTEX_LIST");
|
nuclear@0
|
1846 }
|
nuclear@0
|
1847 return;
|
nuclear@0
|
1848 }
|
nuclear@0
|
1849 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1850 void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
|
nuclear@0
|
1851 {
|
nuclear@0
|
1852 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1853 while (true)
|
nuclear@0
|
1854 {
|
nuclear@0
|
1855 if ('*' == *filePtr)
|
nuclear@0
|
1856 {
|
nuclear@0
|
1857 ++filePtr;
|
nuclear@0
|
1858
|
nuclear@0
|
1859 // Face entry
|
nuclear@0
|
1860 if (TokenMatch(filePtr,"MESH_CFACE" ,11))
|
nuclear@0
|
1861 {
|
nuclear@0
|
1862 unsigned int aiValues[3];
|
nuclear@0
|
1863 unsigned int iIndex = 0;
|
nuclear@0
|
1864
|
nuclear@0
|
1865 ParseLV4MeshLongTriple(aiValues,iIndex);
|
nuclear@0
|
1866 if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
|
nuclear@0
|
1867 {
|
nuclear@0
|
1868 LogWarning("UV-Face has an invalid index. It will be ignored");
|
nuclear@0
|
1869 }
|
nuclear@0
|
1870 else
|
nuclear@0
|
1871 {
|
nuclear@0
|
1872 // copy color indices
|
nuclear@0
|
1873 mesh.mFaces[iIndex].mColorIndices[0] = aiValues[0];
|
nuclear@0
|
1874 mesh.mFaces[iIndex].mColorIndices[1] = aiValues[1];
|
nuclear@0
|
1875 mesh.mFaces[iIndex].mColorIndices[2] = aiValues[2];
|
nuclear@0
|
1876 }
|
nuclear@0
|
1877 continue;
|
nuclear@0
|
1878 }
|
nuclear@0
|
1879 }
|
nuclear@0
|
1880 AI_ASE_HANDLE_SECTION("3","*MESH_CFACE_LIST");
|
nuclear@0
|
1881 }
|
nuclear@0
|
1882 return;
|
nuclear@0
|
1883 }
|
nuclear@0
|
1884 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1885 void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
|
nuclear@0
|
1886 {
|
nuclear@0
|
1887 AI_ASE_PARSER_INIT();
|
nuclear@0
|
1888
|
nuclear@0
|
1889 // Allocate enough storage for the normals
|
nuclear@0
|
1890 sMesh.mNormals.resize(sMesh.mFaces.size()*3,aiVector3D( 0.f, 0.f, 0.f ));
|
nuclear@0
|
1891 unsigned int index, faceIdx = UINT_MAX;
|
nuclear@0
|
1892
|
nuclear@0
|
1893 // FIXME: rewrite this and find out how to interpret the normals
|
nuclear@0
|
1894 // correctly. This is crap.
|
nuclear@0
|
1895
|
nuclear@0
|
1896 // Smooth the vertex and face normals together. The result
|
nuclear@0
|
1897 // will be edgy then, but otherwise everything would be soft ...
|
nuclear@0
|
1898 while (true) {
|
nuclear@0
|
1899 if ('*' == *filePtr) {
|
nuclear@0
|
1900 ++filePtr;
|
nuclear@0
|
1901 if (faceIdx != UINT_MAX && TokenMatch(filePtr,"MESH_VERTEXNORMAL",17)) {
|
nuclear@0
|
1902 aiVector3D vNormal;
|
nuclear@0
|
1903 ParseLV4MeshFloatTriple(&vNormal.x,index);
|
nuclear@0
|
1904 if (faceIdx >= sMesh.mFaces.size())
|
nuclear@0
|
1905 continue;
|
nuclear@0
|
1906
|
nuclear@0
|
1907 // Make sure we assign it to the correct face
|
nuclear@0
|
1908 const ASE::Face& face = sMesh.mFaces[faceIdx];
|
nuclear@0
|
1909 if (index == face.mIndices[0])
|
nuclear@0
|
1910 index = 0;
|
nuclear@0
|
1911 else if (index == face.mIndices[1])
|
nuclear@0
|
1912 index = 1;
|
nuclear@0
|
1913 else if (index == face.mIndices[2])
|
nuclear@0
|
1914 index = 2;
|
nuclear@0
|
1915 else {
|
nuclear@0
|
1916 DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_VERTEXNORMAL section");
|
nuclear@0
|
1917 continue;
|
nuclear@0
|
1918 }
|
nuclear@0
|
1919 // We'll renormalize later
|
nuclear@0
|
1920 sMesh.mNormals[faceIdx*3+index] += vNormal;
|
nuclear@0
|
1921 continue;
|
nuclear@0
|
1922 }
|
nuclear@0
|
1923 if (TokenMatch(filePtr,"MESH_FACENORMAL",15)) {
|
nuclear@0
|
1924 aiVector3D vNormal;
|
nuclear@0
|
1925 ParseLV4MeshFloatTriple(&vNormal.x,faceIdx);
|
nuclear@0
|
1926
|
nuclear@0
|
1927 if (faceIdx >= sMesh.mFaces.size()) {
|
nuclear@0
|
1928 DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_FACENORMAL section");
|
nuclear@0
|
1929 continue;
|
nuclear@0
|
1930 }
|
nuclear@0
|
1931
|
nuclear@0
|
1932 // We'll renormalize later
|
nuclear@0
|
1933 sMesh.mNormals[faceIdx*3] += vNormal;
|
nuclear@0
|
1934 sMesh.mNormals[faceIdx*3+1] += vNormal;
|
nuclear@0
|
1935 sMesh.mNormals[faceIdx*3+2] += vNormal;
|
nuclear@0
|
1936 continue;
|
nuclear@0
|
1937 }
|
nuclear@0
|
1938 }
|
nuclear@0
|
1939 AI_ASE_HANDLE_SECTION("3","*MESH_NORMALS");
|
nuclear@0
|
1940 }
|
nuclear@0
|
1941 return;
|
nuclear@0
|
1942 }
|
nuclear@0
|
1943 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1944 void Parser::ParseLV4MeshFace(ASE::Face& out)
|
nuclear@0
|
1945 {
|
nuclear@0
|
1946 // skip spaces and tabs
|
nuclear@0
|
1947 if(!SkipSpaces(&filePtr))
|
nuclear@0
|
1948 {
|
nuclear@0
|
1949 LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]");
|
nuclear@0
|
1950 SkipToNextToken();
|
nuclear@0
|
1951 return;
|
nuclear@0
|
1952 }
|
nuclear@0
|
1953
|
nuclear@0
|
1954 // parse the face index
|
nuclear@0
|
1955 out.iFace = strtoul10(filePtr,&filePtr);
|
nuclear@0
|
1956
|
nuclear@0
|
1957 // next character should be ':'
|
nuclear@0
|
1958 if(!SkipSpaces(&filePtr))
|
nuclear@0
|
1959 {
|
nuclear@0
|
1960 // FIX: there are some ASE files which haven't got : here ....
|
nuclear@0
|
1961 LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]");
|
nuclear@0
|
1962 SkipToNextToken();
|
nuclear@0
|
1963 return;
|
nuclear@0
|
1964 }
|
nuclear@0
|
1965 // FIX: There are some ASE files which haven't got ':' here
|
nuclear@0
|
1966 if(':' == *filePtr)++filePtr;
|
nuclear@0
|
1967
|
nuclear@0
|
1968 // Parse all mesh indices
|
nuclear@0
|
1969 for (unsigned int i = 0; i < 3;++i)
|
nuclear@0
|
1970 {
|
nuclear@0
|
1971 unsigned int iIndex = 0;
|
nuclear@0
|
1972 if(!SkipSpaces(&filePtr))
|
nuclear@0
|
1973 {
|
nuclear@0
|
1974 LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL");
|
nuclear@0
|
1975 SkipToNextToken();
|
nuclear@0
|
1976 return;
|
nuclear@0
|
1977 }
|
nuclear@0
|
1978 switch (*filePtr)
|
nuclear@0
|
1979 {
|
nuclear@0
|
1980 case 'A':
|
nuclear@0
|
1981 case 'a':
|
nuclear@0
|
1982 break;
|
nuclear@0
|
1983 case 'B':
|
nuclear@0
|
1984 case 'b':
|
nuclear@0
|
1985 iIndex = 1;
|
nuclear@0
|
1986 break;
|
nuclear@0
|
1987 case 'C':
|
nuclear@0
|
1988 case 'c':
|
nuclear@0
|
1989 iIndex = 2;
|
nuclear@0
|
1990 break;
|
nuclear@0
|
1991 default:
|
nuclear@0
|
1992 LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. "
|
nuclear@0
|
1993 "A,B or C expected [#3]");
|
nuclear@0
|
1994 SkipToNextToken();
|
nuclear@0
|
1995 return;
|
nuclear@0
|
1996 };
|
nuclear@0
|
1997 ++filePtr;
|
nuclear@0
|
1998
|
nuclear@0
|
1999 // next character should be ':'
|
nuclear@0
|
2000 if(!SkipSpaces(&filePtr) || ':' != *filePtr)
|
nuclear@0
|
2001 {
|
nuclear@0
|
2002 LogWarning("Unable to parse *MESH_FACE Element: "
|
nuclear@0
|
2003 "Unexpected EOL. \':\' expected [#2]");
|
nuclear@0
|
2004 SkipToNextToken();
|
nuclear@0
|
2005 return;
|
nuclear@0
|
2006 }
|
nuclear@0
|
2007
|
nuclear@0
|
2008 ++filePtr;
|
nuclear@0
|
2009 if(!SkipSpaces(&filePtr))
|
nuclear@0
|
2010 {
|
nuclear@0
|
2011 LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. "
|
nuclear@0
|
2012 "Vertex index ecpected [#4]");
|
nuclear@0
|
2013 SkipToNextToken();
|
nuclear@0
|
2014 return;
|
nuclear@0
|
2015 }
|
nuclear@0
|
2016 out.mIndices[iIndex] = strtoul10(filePtr,&filePtr);
|
nuclear@0
|
2017 }
|
nuclear@0
|
2018
|
nuclear@0
|
2019 // now we need to skip the AB, BC, CA blocks.
|
nuclear@0
|
2020 while (true)
|
nuclear@0
|
2021 {
|
nuclear@0
|
2022 if ('*' == *filePtr)break;
|
nuclear@0
|
2023 if (IsLineEnd(*filePtr))
|
nuclear@0
|
2024 {
|
nuclear@0
|
2025 //iLineNumber++;
|
nuclear@0
|
2026 return;
|
nuclear@0
|
2027 }
|
nuclear@0
|
2028 filePtr++;
|
nuclear@0
|
2029 }
|
nuclear@0
|
2030
|
nuclear@0
|
2031 // parse the smoothing group of the face
|
nuclear@0
|
2032 if (TokenMatch(filePtr,"*MESH_SMOOTHING",15))
|
nuclear@0
|
2033 {
|
nuclear@0
|
2034 if(!SkipSpaces(&filePtr))
|
nuclear@0
|
2035 {
|
nuclear@0
|
2036 LogWarning("Unable to parse *MESH_SMOOTHING Element: "
|
nuclear@0
|
2037 "Unexpected EOL. Smoothing group(s) expected [#5]");
|
nuclear@0
|
2038 SkipToNextToken();
|
nuclear@0
|
2039 return;
|
nuclear@0
|
2040 }
|
nuclear@0
|
2041
|
nuclear@0
|
2042 // Parse smoothing groups until we don't anymore see commas
|
nuclear@0
|
2043 // FIX: There needn't always be a value, sad but true
|
nuclear@0
|
2044 while (true)
|
nuclear@0
|
2045 {
|
nuclear@0
|
2046 if (*filePtr < '9' && *filePtr >= '0')
|
nuclear@0
|
2047 {
|
nuclear@0
|
2048 out.iSmoothGroup |= (1 << strtoul10(filePtr,&filePtr));
|
nuclear@0
|
2049 }
|
nuclear@0
|
2050 SkipSpaces(&filePtr);
|
nuclear@0
|
2051 if (',' != *filePtr)
|
nuclear@0
|
2052 {
|
nuclear@0
|
2053 break;
|
nuclear@0
|
2054 }
|
nuclear@0
|
2055 ++filePtr;
|
nuclear@0
|
2056 SkipSpaces(&filePtr);
|
nuclear@0
|
2057 }
|
nuclear@0
|
2058 }
|
nuclear@0
|
2059
|
nuclear@0
|
2060 // *MESH_MTLID is optional, too
|
nuclear@0
|
2061 while (true)
|
nuclear@0
|
2062 {
|
nuclear@0
|
2063 if ('*' == *filePtr)break;
|
nuclear@0
|
2064 if (IsLineEnd(*filePtr))
|
nuclear@0
|
2065 {
|
nuclear@0
|
2066 return;
|
nuclear@0
|
2067 }
|
nuclear@0
|
2068 filePtr++;
|
nuclear@0
|
2069 }
|
nuclear@0
|
2070
|
nuclear@0
|
2071 if (TokenMatch(filePtr,"*MESH_MTLID",11))
|
nuclear@0
|
2072 {
|
nuclear@0
|
2073 if(!SkipSpaces(&filePtr))
|
nuclear@0
|
2074 {
|
nuclear@0
|
2075 LogWarning("Unable to parse *MESH_MTLID Element: Unexpected EOL. "
|
nuclear@0
|
2076 "Material index expected [#6]");
|
nuclear@0
|
2077 SkipToNextToken();
|
nuclear@0
|
2078 return;
|
nuclear@0
|
2079 }
|
nuclear@0
|
2080 out.iMaterial = strtoul10(filePtr,&filePtr);
|
nuclear@0
|
2081 }
|
nuclear@0
|
2082 return;
|
nuclear@0
|
2083 }
|
nuclear@0
|
2084 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
2085 void Parser::ParseLV4MeshLongTriple(unsigned int* apOut)
|
nuclear@0
|
2086 {
|
nuclear@0
|
2087 ai_assert(NULL != apOut);
|
nuclear@0
|
2088
|
nuclear@0
|
2089 for (unsigned int i = 0; i < 3;++i)
|
nuclear@0
|
2090 ParseLV4MeshLong(apOut[i]);
|
nuclear@0
|
2091 }
|
nuclear@0
|
2092 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
2093 void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut)
|
nuclear@0
|
2094 {
|
nuclear@0
|
2095 ai_assert(NULL != apOut);
|
nuclear@0
|
2096
|
nuclear@0
|
2097 // parse the index
|
nuclear@0
|
2098 ParseLV4MeshLong(rIndexOut);
|
nuclear@0
|
2099
|
nuclear@0
|
2100 // parse the three others
|
nuclear@0
|
2101 ParseLV4MeshLongTriple(apOut);
|
nuclear@0
|
2102 }
|
nuclear@0
|
2103 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
2104 void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut)
|
nuclear@0
|
2105 {
|
nuclear@0
|
2106 ai_assert(NULL != apOut);
|
nuclear@0
|
2107
|
nuclear@0
|
2108 // parse the index
|
nuclear@0
|
2109 ParseLV4MeshLong(rIndexOut);
|
nuclear@0
|
2110
|
nuclear@0
|
2111 // parse the three others
|
nuclear@0
|
2112 ParseLV4MeshFloatTriple(apOut);
|
nuclear@0
|
2113 }
|
nuclear@0
|
2114 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
2115 void Parser::ParseLV4MeshFloatTriple(float* apOut)
|
nuclear@0
|
2116 {
|
nuclear@0
|
2117 ai_assert(NULL != apOut);
|
nuclear@0
|
2118
|
nuclear@0
|
2119 for (unsigned int i = 0; i < 3;++i)
|
nuclear@0
|
2120 ParseLV4MeshFloat(apOut[i]);
|
nuclear@0
|
2121 }
|
nuclear@0
|
2122 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
2123 void Parser::ParseLV4MeshFloat(float& fOut)
|
nuclear@0
|
2124 {
|
nuclear@0
|
2125 // skip spaces and tabs
|
nuclear@0
|
2126 if(!SkipSpaces(&filePtr))
|
nuclear@0
|
2127 {
|
nuclear@0
|
2128 // LOG
|
nuclear@0
|
2129 LogWarning("Unable to parse float: unexpected EOL [#1]");
|
nuclear@0
|
2130 fOut = 0.0f;
|
nuclear@0
|
2131 ++iLineNumber;
|
nuclear@0
|
2132 return;
|
nuclear@0
|
2133 }
|
nuclear@0
|
2134 // parse the first float
|
nuclear@0
|
2135 filePtr = fast_atoreal_move<float>(filePtr,fOut);
|
nuclear@0
|
2136 }
|
nuclear@0
|
2137 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
2138 void Parser::ParseLV4MeshLong(unsigned int& iOut)
|
nuclear@0
|
2139 {
|
nuclear@0
|
2140 // Skip spaces and tabs
|
nuclear@0
|
2141 if(!SkipSpaces(&filePtr))
|
nuclear@0
|
2142 {
|
nuclear@0
|
2143 // LOG
|
nuclear@0
|
2144 LogWarning("Unable to parse long: unexpected EOL [#1]");
|
nuclear@0
|
2145 iOut = 0;
|
nuclear@0
|
2146 ++iLineNumber;
|
nuclear@0
|
2147 return;
|
nuclear@0
|
2148 }
|
nuclear@0
|
2149 // parse the value
|
nuclear@0
|
2150 iOut = strtoul10(filePtr,&filePtr);
|
nuclear@0
|
2151 }
|
nuclear@0
|
2152
|
nuclear@0
|
2153 #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER
|