1 /*
2 Open Asset Import Library (assimp)
3 ----------------------------------------------------------------------
4
5 Copyright (c) 2006-2017, assimp team
6
7 All rights reserved.
8
9 Redistribution and use of this software in source and binary forms,
10 with or without modification, are permitted provided that the
11 following conditions are met:
12
13 * Redistributions of source code must retain the above
14 copyright notice, this list of conditions and the
15 following disclaimer.
16
17 * Redistributions in binary form must reproduce the above
18 copyright notice, this list of conditions and the
19 following disclaimer in the documentation and/or other
20 materials provided with the distribution.
21
22 * Neither the name of the assimp team, nor the names of its
23 contributors may be used to endorse or promote products
24 derived from this software without specific prior
25 written permission of the assimp team.
26
27 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
39 ----------------------------------------------------------------------
40 */
41
42
43 /** @file MD5Parser.h
44 * @brief Definition of the .MD5 parser class.
45 * http://www.modwiki.net/wiki/MD5_(file_format)
46 */
47 #ifndef AI_MD5PARSER_H_INCLUDED
48 #define AI_MD5PARSER_H_INCLUDED
49
50 #include <assimp/types.h>
51 #include "ParsingUtils.h"
52 #include <vector>
53 #include <stdint.h>
54
55 struct aiFace;
56
57 namespace Assimp {
58 namespace MD5 {
59
60 // ---------------------------------------------------------------------------
61 /** Represents a single element in a MD5 file
62 *
63 * Elements are always contained in sections.
64 */
65 struct Element
66 {
67 //! Points to the starting point of the element
68 //! Whitespace at the beginning and at the end have been removed,
69 //! Elements are terminated with \0
70 char* szStart;
71
72 //! Original line number (can be used in error messages
73 //! if a parsing error occurs)
74 unsigned int iLineNumber;
75 };
76
77 typedef std::vector< Element > ElementList;
78
79 // ---------------------------------------------------------------------------
80 /** Represents a section of a MD5 file (such as the mesh or the joints section)
81 *
82 * A section is always enclosed in { and } brackets.
83 */
84 struct Section
85 {
86 //! Original line number (can be used in error messages
87 //! if a parsing error occurs)
88 unsigned int iLineNumber;
89
90 //! List of all elements which have been parsed in this section.
91 ElementList mElements;
92
93 //! Name of the section
94 std::string mName;
95
96 //! For global elements: the value of the element as string
97 //! Iif !length() the section is not a global element
98 std::string mGlobalValue;
99 };
100
101 typedef std::vector< Section> SectionList;
102
103 // ---------------------------------------------------------------------------
104 /** Basic information about a joint
105 */
106 struct BaseJointDescription
107 {
108 //! Name of the bone
109 aiString mName;
110
111 //! Parent index of the bone
112 int mParentIndex;
113 };
114
115 // ---------------------------------------------------------------------------
116 /** Represents a bone (joint) descriptor in a MD5Mesh file
117 */
118 struct BoneDesc : BaseJointDescription
119 {
120 //! Absolute position of the bone
121 aiVector3D mPositionXYZ;
122
123 //! Absolute rotation of the bone
124 aiVector3D mRotationQuat;
125 aiQuaternion mRotationQuatConverted;
126
127 //! Absolute transformation of the bone
128 //! (temporary)
129 aiMatrix4x4 mTransform;
130
131 //! Inverse transformation of the bone
132 //! (temporary)
133 aiMatrix4x4 mInvTransform;
134
135 //! Internal
136 unsigned int mMap;
137 };
138
139 typedef std::vector< BoneDesc > BoneList;
140
141 // ---------------------------------------------------------------------------
142 /** Represents a bone (joint) descriptor in a MD5Anim file
143 */
144 struct AnimBoneDesc : BaseJointDescription
145 {
146 //! Flags (AI_MD5_ANIMATION_FLAG_xxx)
147 unsigned int iFlags;
148
149 //! Index of the first key that corresponds to this anim bone
150 unsigned int iFirstKeyIndex;
151 };
152
153 typedef std::vector< AnimBoneDesc > AnimBoneList;
154
155
156 // ---------------------------------------------------------------------------
157 /** Represents a base frame descriptor in a MD5Anim file
158 */
159 struct BaseFrameDesc
160 {
161 aiVector3D vPositionXYZ;
162 aiVector3D vRotationQuat;
163 };
164
165 typedef std::vector< BaseFrameDesc > BaseFrameList;
166
167 // ---------------------------------------------------------------------------
168 /** Represents a camera animation frame in a MDCamera file
169 */
170 struct CameraAnimFrameDesc : BaseFrameDesc
171 {
172 float fFOV;
173 };
174
175 typedef std::vector< CameraAnimFrameDesc > CameraFrameList;
176
177 // ---------------------------------------------------------------------------
178 /** Represents a frame descriptor in a MD5Anim file
179 */
180 struct FrameDesc
181 {
182 //! Index of the frame
183 unsigned int iIndex;
184
185 //! Animation keyframes - a large blob of data at first
186 std::vector< float > mValues;
187 };
188
189 typedef std::vector< FrameDesc > FrameList;
190
191 // ---------------------------------------------------------------------------
192 /** Represents a vertex descriptor in a MD5 file
193 */
194 struct VertexDesc
195 {
VertexDescVertexDesc196 VertexDesc()
197 : mFirstWeight (0)
198 , mNumWeights (0)
199 {}
200
201 //! UV cordinate of the vertex
202 aiVector2D mUV;
203
204 //! Index of the first weight of the vertex in
205 //! the vertex weight list
206 unsigned int mFirstWeight;
207
208 //! Number of weights assigned to this vertex
209 unsigned int mNumWeights;
210 };
211
212 typedef std::vector< VertexDesc > VertexList;
213
214 // ---------------------------------------------------------------------------
215 /** Represents a vertex weight descriptor in a MD5 file
216 */
217 struct WeightDesc
218 {
219 //! Index of the bone to which this weight refers
220 unsigned int mBone;
221
222 //! The weight value
223 float mWeight;
224
225 //! The offset position of this weight
226 // ! (in the coordinate system defined by the parent bone)
227 aiVector3D vOffsetPosition;
228 };
229
230 typedef std::vector< WeightDesc > WeightList;
231 typedef std::vector< aiFace > FaceList;
232
233 // ---------------------------------------------------------------------------
234 /** Represents a mesh in a MD5 file
235 */
236 struct MeshDesc
237 {
238 //! Weights of the mesh
239 WeightList mWeights;
240
241 //! Vertices of the mesh
242 VertexList mVertices;
243
244 //! Faces of the mesh
245 FaceList mFaces;
246
247 //! Name of the shader (=texture) to be assigned to the mesh
248 aiString mShader;
249 };
250
251 typedef std::vector< MeshDesc > MeshList;
252
253 // ---------------------------------------------------------------------------
254 // Convert a quaternion to its usual representation
ConvertQuaternion(const aiVector3D & in,aiQuaternion & out)255 inline void ConvertQuaternion (const aiVector3D& in, aiQuaternion& out) {
256
257 out.x = in.x;
258 out.y = in.y;
259 out.z = in.z;
260
261 const float t = 1.0f - (in.x*in.x) - (in.y*in.y) - (in.z*in.z);
262
263 if (t < 0.0f)
264 out.w = 0.0f;
265 else out.w = std::sqrt (t);
266
267 // Assimp convention.
268 out.w *= -1.f;
269 }
270
271 // ---------------------------------------------------------------------------
272 /** Parses the data sections of a MD5 mesh file
273 */
274 class MD5MeshParser
275 {
276 public:
277
278 // -------------------------------------------------------------------
279 /** Constructs a new MD5MeshParser instance from an existing
280 * preparsed list of file sections.
281 *
282 * @param mSections List of file sections (output of MD5Parser)
283 */
284 explicit MD5MeshParser(SectionList& mSections);
285
286 //! List of all meshes
287 MeshList mMeshes;
288
289 //! List of all joints
290 BoneList mJoints;
291 };
292
293 // remove this flag if you need to the bounding box data
294 #define AI_MD5_PARSE_NO_BOUNDS
295
296 // ---------------------------------------------------------------------------
297 /** Parses the data sections of a MD5 animation file
298 */
299 class MD5AnimParser
300 {
301 public:
302
303 // -------------------------------------------------------------------
304 /** Constructs a new MD5AnimParser instance from an existing
305 * preparsed list of file sections.
306 *
307 * @param mSections List of file sections (output of MD5Parser)
308 */
309 explicit MD5AnimParser(SectionList& mSections);
310
311
312 //! Output frame rate
313 float fFrameRate;
314
315 //! List of animation bones
316 AnimBoneList mAnimatedBones;
317
318 //! List of base frames
319 BaseFrameList mBaseFrames;
320
321 //! List of animation frames
322 FrameList mFrames;
323
324 //! Number of animated components
325 unsigned int mNumAnimatedComponents;
326 };
327
328 // ---------------------------------------------------------------------------
329 /** Parses the data sections of a MD5 camera animation file
330 */
331 class MD5CameraParser
332 {
333 public:
334
335 // -------------------------------------------------------------------
336 /** Constructs a new MD5CameraParser instance from an existing
337 * preparsed list of file sections.
338 *
339 * @param mSections List of file sections (output of MD5Parser)
340 */
341 explicit MD5CameraParser(SectionList& mSections);
342
343
344 //! Output frame rate
345 float fFrameRate;
346
347 //! List of cuts
348 std::vector<unsigned int> cuts;
349
350 //! Frames
351 CameraFrameList frames;
352 };
353
354 // ---------------------------------------------------------------------------
355 /** Parses the block structure of MD5MESH and MD5ANIM files (but does no
356 * further processing)
357 */
358 class MD5Parser
359 {
360 public:
361
362 // -------------------------------------------------------------------
363 /** Constructs a new MD5Parser instance from an existing buffer.
364 *
365 * @param buffer File buffer
366 * @param fileSize Length of the file in bytes (excluding a terminal 0)
367 */
368 MD5Parser(char* buffer, unsigned int fileSize);
369
370
371 // -------------------------------------------------------------------
372 /** Report a specific error message and throw an exception
373 * @param error Error message to be reported
374 * @param line Index of the line where the error occurred
375 */
376 AI_WONT_RETURN static void ReportError (const char* error, unsigned int line) AI_WONT_RETURN_SUFFIX;
377
378 // -------------------------------------------------------------------
379 /** Report a specific warning
380 * @param warn Warn message to be reported
381 * @param line Index of the line where the error occurred
382 */
383 static void ReportWarning (const char* warn, unsigned int line);
384
385
ReportError(const char * error)386 void ReportError (const char* error) {
387 return ReportError(error, lineNumber);
388 }
389
ReportWarning(const char * warn)390 void ReportWarning (const char* warn) {
391 return ReportWarning(warn, lineNumber);
392 }
393
394 public:
395
396 //! List of all sections which have been read
397 SectionList mSections;
398
399 private:
400
401 // -------------------------------------------------------------------
402 /** Parses a file section. The current file pointer must be outside
403 * of a section.
404 * @param out Receives the section data
405 * @return true if the end of the file has been reached
406 * @throws ImportErrorException if an error occurs
407 */
408 bool ParseSection(Section& out);
409
410 // -------------------------------------------------------------------
411 /** Parses the file header
412 * @throws ImportErrorException if an error occurs
413 */
414 void ParseHeader();
415
416
417 // override these functions to make sure the line counter gets incremented
418 // -------------------------------------------------------------------
SkipLine(const char * in,const char ** out)419 bool SkipLine( const char* in, const char** out)
420 {
421 ++lineNumber;
422 return Assimp::SkipLine(in,out);
423 }
424 // -------------------------------------------------------------------
SkipLine()425 bool SkipLine( )
426 {
427 return SkipLine(buffer,(const char**)&buffer);
428 }
429 // -------------------------------------------------------------------
SkipSpacesAndLineEnd(const char * in,const char ** out)430 bool SkipSpacesAndLineEnd( const char* in, const char** out)
431 {
432 bool bHad = false;
433 bool running = true;
434 while (running) {
435 if( *in == '\r' || *in == '\n') {
436 // we open files in binary mode, so there could be \r\n sequences ...
437 if (!bHad) {
438 bHad = true;
439 ++lineNumber;
440 }
441 }
442 else if (*in == '\t' || *in == ' ')bHad = false;
443 else break;
444 in++;
445 }
446 *out = in;
447 return *in != '\0';
448 }
449 // -------------------------------------------------------------------
SkipSpacesAndLineEnd()450 bool SkipSpacesAndLineEnd( )
451 {
452 return SkipSpacesAndLineEnd(buffer,(const char**)&buffer);
453 }
454 // -------------------------------------------------------------------
SkipSpaces()455 bool SkipSpaces( )
456 {
457 return Assimp::SkipSpaces((const char**)&buffer);
458 }
459
460 char* buffer;
461 unsigned int fileSize;
462 unsigned int lineNumber;
463 };
464 }}
465
466 #endif // AI_MD5PARSER_H_INCLUDED
467