1/*
2Open Asset Import Library (assimp)
3----------------------------------------------------------------------
4
5Copyright (c) 2006-2017, assimp team
6
7All rights reserved.
8
9Redistribution and use of this software in source and binary forms,
10with or without modification, are permitted provided that the
11following 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
27THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
39----------------------------------------------------------------------
40*/
41
42
43/** @file Defines the helper data structures for importing ASE files */
44#ifndef AI_ASEFILEHELPER_H_INC
45#define AI_ASEFILEHELPER_H_INC
46
47// public ASSIMP headers
48#include <assimp/types.h>
49#include <assimp/mesh.h>
50#include <assimp/anim.h>
51
52#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
53
54// for some helper routines like IsSpace()
55#include "ParsingUtils.h"
56#include "qnan.h"
57
58// ASE is quite similar to 3ds. We can reuse some structures
59#include "3DSLoader.h"
60
61namespace Assimp {
62namespace ASE {
63
64using namespace D3DS;
65
66// ---------------------------------------------------------------------------
67/** Helper structure representing an ASE material */
68struct Material : public D3DS::Material
69{
70 //! Default constructor
71 Material() : pcInstance(NULL), bNeed (false)
72 {}
73
74 //! Contains all sub materials of this material
75 std::vector<Material> avSubMaterials;
76
77 //! aiMaterial object
78 aiMaterial* pcInstance;
79
80 //! Can we remove this material?
81 bool bNeed;
82};
83
84// ---------------------------------------------------------------------------
85/** Helper structure to represent an ASE file face */
86struct Face : public FaceWithSmoothingGroup
87{
88 //! Default constructor. Initializes everything with 0
89 Face()
90 {
91 mColorIndices[0] = mColorIndices[1] = mColorIndices[2] = 0;
92 for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
93 {
94 amUVIndices[i][0] = amUVIndices[i][1] = amUVIndices[i][2] = 0;
95 }
96
97 iMaterial = DEFAULT_MATINDEX;
98 iFace = 0;
99 }
100
101 //! special value to indicate that no material index has
102 //! been assigned to a face. The default material index
103 //! will replace this value later.
104 static const unsigned int DEFAULT_MATINDEX = 0xFFFFFFFF;
105
106
107
108 //! Indices into each list of texture coordinates
109 unsigned int amUVIndices[AI_MAX_NUMBER_OF_TEXTURECOORDS][3];
110
111 //! Index into the list of vertex colors
112 unsigned int mColorIndices[3];
113
114 //! (Sub)Material index to be assigned to this face
115 unsigned int iMaterial;
116
117 //! Index of the face. It is not specified whether it is
118 //! a requirement of the file format that all faces are
119 //! written in sequential order, so we have to expect this case
120 unsigned int iFace;
121};
122
123// ---------------------------------------------------------------------------
124/** Helper structure to represent an ASE file bone */
125struct Bone
126{
127 //! Constructor
128 Bone()
129 {
130 static int iCnt = 0;
131
132 // Generate a default name for the bone
133 char szTemp[128];
134 ::ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
135 mName = szTemp;
136 }
137
138 //! Construction from an existing name
139 explicit Bone( const std::string& name)
140 : mName (name)
141 {}
142
143 //! Name of the bone
144 std::string mName;
145};
146
147// ---------------------------------------------------------------------------
148/** Helper structure to represent an ASE file bone vertex */
149struct BoneVertex
150{
151 //! Bone and corresponding vertex weight.
152 //! -1 for unrequired bones ....
153 std::vector<std::pair<int,float> > mBoneWeights;
154
155 //! Position of the bone vertex.
156 //! MUST be identical to the vertex position
157 //aiVector3D mPosition;
158};
159
160// ---------------------------------------------------------------------------
161/** Helper structure to represent an ASE file animation */
162struct Animation
163{
164 enum Type
165 {
166 TRACK = 0x0,
167 BEZIER = 0x1,
168 TCB = 0x2
169 } mRotationType, mScalingType, mPositionType;
170
171 Animation()
172 : mRotationType (TRACK)
173 , mScalingType (TRACK)
174 , mPositionType (TRACK)
175 {}
176
177 //! List of track rotation keyframes
178 std::vector< aiQuatKey > akeyRotations;
179
180 //! List of track position keyframes
181 std::vector< aiVectorKey > akeyPositions;
182
183 //! List of track scaling keyframes
184 std::vector< aiVectorKey > akeyScaling;
185
186};
187
188// ---------------------------------------------------------------------------
189/** Helper structure to represent the inheritance information of an ASE node */
190struct InheritanceInfo
191{
192 //! Default constructor
193 InheritanceInfo()
194 {
195 // set the inheritance flag for all axes by default to true
196 for (unsigned int i = 0; i < 3;++i)
197 abInheritPosition[i] = abInheritRotation[i] = abInheritScaling[i] = true;
198 }
199
200 //! Inherit the parent's position?, axis order is x,y,z
201 bool abInheritPosition[3];
202
203 //! Inherit the parent's rotation?, axis order is x,y,z
204 bool abInheritRotation[3];
205
206 //! Inherit the parent's scaling?, axis order is x,y,z
207 bool abInheritScaling[3];
208};
209
210// ---------------------------------------------------------------------------
211/** Represents an ASE file node. Base class for mesh, light and cameras */
212struct BaseNode
213{
214 enum Type {Light, Camera, Mesh, Dummy} mType;
215
216 //! Constructor. Creates a default name for the node
217 explicit BaseNode(Type _mType)
218 : mType (_mType)
219 , mProcessed (false)
220 {
221 // generate a default name for the node
222 static int iCnt = 0;
223 char szTemp[128]; // should be sufficiently large
224 ::ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
225 mName = szTemp;
226
227 // Set mTargetPosition to qnan
228 const ai_real qnan = get_qnan();
229 mTargetPosition.x = qnan;
230 }
231
232 //! Name of the mesh
233 std::string mName;
234
235 //! Name of the parent of the node
236 //! "" if there is no parent ...
237 std::string mParent;
238
239 //! Transformation matrix of the node
240 aiMatrix4x4 mTransform;
241
242 //! Target position (target lights and cameras)
243 aiVector3D mTargetPosition;
244
245 //! Specifies which axes transformations a node inherits
246 //! from its parent ...
247 InheritanceInfo inherit;
248
249 //! Animation channels for the node
250 Animation mAnim;
251
252 //! Needed for lights and cameras: target animation channel
253 //! Should contain position keys only.
254 Animation mTargetAnim;
255
256 bool mProcessed;
257};
258
259// ---------------------------------------------------------------------------
260/** Helper structure to represent an ASE file mesh */
261struct Mesh : public MeshWithSmoothingGroups<ASE::Face>, public BaseNode
262{
263 //! Constructor.
264 Mesh()
265 : BaseNode (BaseNode::Mesh)
266 , bSkip (false)
267 {
268 // use 2 texture vertex components by default
269 for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
270 this->mNumUVComponents[c] = 2;
271
272 // setup the default material index by default
273 iMaterialIndex = Face::DEFAULT_MATINDEX;
274 }
275
276 //! List of all texture coordinate sets
277 std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
278
279 //! List of all vertex color sets.
280 std::vector<aiColor4D> mVertexColors;
281
282 //! List of all bone vertices
283 std::vector<BoneVertex> mBoneVertices;
284
285 //! List of all bones
286 std::vector<Bone> mBones;
287
288 //! Material index of the mesh
289 unsigned int iMaterialIndex;
290
291 //! Number of vertex components for each UVW set
292 unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
293
294 //! used internally
295 bool bSkip;
296};
297
298// ---------------------------------------------------------------------------
299/** Helper structure to represent an ASE light source */
300struct Light : public BaseNode
301{
302 enum LightType
303 {
304 OMNI,
305 TARGET,
306 FREE,
307 DIRECTIONAL
308 };
309
310 //! Constructor.
311 Light()
312 : BaseNode (BaseNode::Light)
313 , mLightType (OMNI)
314 , mColor (1.f,1.f,1.f)
315 , mIntensity (1.f) // light is white by default
316 , mAngle (45.f)
317 , mFalloff (0.f)
318 {
319 }
320
321 LightType mLightType;
322 aiColor3D mColor;
323 ai_real mIntensity;
324 ai_real mAngle; // in degrees
325 ai_real mFalloff;
326};
327
328// ---------------------------------------------------------------------------
329/** Helper structure to represent an ASE camera */
330struct Camera : public BaseNode
331{
332 enum CameraType
333 {
334 FREE,
335 TARGET
336 };
337
338 //! Constructor
339 Camera()
340 : BaseNode (BaseNode::Camera)
341 , mFOV (0.75f) // in radians
342 , mNear (0.1f)
343 , mFar (1000.f) // could be zero
344 , mCameraType (FREE)
345 {
346 }
347
348 ai_real mFOV, mNear, mFar;
349 CameraType mCameraType;
350};
351
352// ---------------------------------------------------------------------------
353/** Helper structure to represent an ASE helper object (dummy) */
354struct Dummy : public BaseNode
355{
356 //! Constructor
357 Dummy()
358 : BaseNode (BaseNode::Dummy)
359 {
360 }
361};
362
363// Parameters to Parser::Parse()
364#define AI_ASE_NEW_FILE_FORMAT 200
365#define AI_ASE_OLD_FILE_FORMAT 110
366
367// Internally we're a little bit more tolerant
368#define AI_ASE_IS_NEW_FILE_FORMAT() (iFileFormat >= 200)
369#define AI_ASE_IS_OLD_FILE_FORMAT() (iFileFormat < 200)
370
371// -------------------------------------------------------------------------------
372/** \brief Class to parse ASE files
373 */
374class Parser
375{
376
377private:
378
379 Parser() {}
380
381public:
382
383 // -------------------------------------------------------------------
384 //! Construct a parser from a given input file which is
385 //! guaranted to be terminated with zero.
386 //! @param szFile Input file
387 //! @param fileFormatDefault Assumed file format version. If the
388 //! file format is specified in the file the new value replaces
389 //! the default value.
390 Parser (const char* szFile, unsigned int fileFormatDefault);
391
392 // -------------------------------------------------------------------
393 //! Parses the file into the parsers internal representation
394 void Parse();
395
396
397private:
398
399 // -------------------------------------------------------------------
400 //! Parse the *SCENE block in a file
401 void ParseLV1SceneBlock();
402
403 // -------------------------------------------------------------------
404 //! Parse the *MESH_SOFTSKINVERTS block in a file
405 void ParseLV1SoftSkinBlock();
406
407 // -------------------------------------------------------------------
408 //! Parse the *MATERIAL_LIST block in a file
409 void ParseLV1MaterialListBlock();
410
411 // -------------------------------------------------------------------
412 //! Parse a *<xxx>OBJECT block in a file
413 //! \param mesh Node to be filled
414 void ParseLV1ObjectBlock(BaseNode& mesh);
415
416 // -------------------------------------------------------------------
417 //! Parse a *MATERIAL blocks in a material list
418 //! \param mat Material structure to be filled
419 void ParseLV2MaterialBlock(Material& mat);
420
421 // -------------------------------------------------------------------
422 //! Parse a *NODE_TM block in a file
423 //! \param mesh Node (!) object to be filled
424 void ParseLV2NodeTransformBlock(BaseNode& mesh);
425
426 // -------------------------------------------------------------------
427 //! Parse a *TM_ANIMATION block in a file
428 //! \param mesh Mesh object to be filled
429 void ParseLV2AnimationBlock(BaseNode& mesh);
430 void ParseLV3PosAnimationBlock(ASE::Animation& anim);
431 void ParseLV3ScaleAnimationBlock(ASE::Animation& anim);
432 void ParseLV3RotAnimationBlock(ASE::Animation& anim);
433
434 // -------------------------------------------------------------------
435 //! Parse a *MESH block in a file
436 //! \param mesh Mesh object to be filled
437 void ParseLV2MeshBlock(Mesh& mesh);
438
439 // -------------------------------------------------------------------
440 //! Parse a *LIGHT_SETTINGS block in a file
441 //! \param light Light object to be filled
442 void ParseLV2LightSettingsBlock(Light& light);
443
444 // -------------------------------------------------------------------
445 //! Parse a *CAMERA_SETTINGS block in a file
446 //! \param cam Camera object to be filled
447 void ParseLV2CameraSettingsBlock(Camera& cam);
448
449 // -------------------------------------------------------------------
450 //! Parse the *MAP_XXXXXX blocks in a material
451 //! \param map Texture structure to be filled
452 void ParseLV3MapBlock(Texture& map);
453
454 // -------------------------------------------------------------------
455 //! Parse a *MESH_VERTEX_LIST block in a file
456 //! \param iNumVertices Value of *MESH_NUMVERTEX, if present.
457 //! Otherwise zero. This is used to check the consistency of the file.
458 //! A warning is sent to the logger if the validations fails.
459 //! \param mesh Mesh object to be filled
460 void ParseLV3MeshVertexListBlock(
461 unsigned int iNumVertices,Mesh& mesh);
462
463 // -------------------------------------------------------------------
464 //! Parse a *MESH_FACE_LIST block in a file
465 //! \param iNumFaces Value of *MESH_NUMFACES, if present.
466 //! Otherwise zero. This is used to check the consistency of the file.
467 //! A warning is sent to the logger if the validations fails.
468 //! \param mesh Mesh object to be filled
469 void ParseLV3MeshFaceListBlock(
470 unsigned int iNumFaces,Mesh& mesh);
471
472 // -------------------------------------------------------------------
473 //! Parse a *MESH_TVERT_LIST block in a file
474 //! \param iNumVertices Value of *MESH_NUMTVERTEX, if present.
475 //! Otherwise zero. This is used to check the consistency of the file.
476 //! A warning is sent to the logger if the validations fails.
477 //! \param mesh Mesh object to be filled
478 //! \param iChannel Output UVW channel
479 void ParseLV3MeshTListBlock(
480 unsigned int iNumVertices,Mesh& mesh, unsigned int iChannel = 0);
481
482 // -------------------------------------------------------------------
483 //! Parse a *MESH_TFACELIST block in a file
484 //! \param iNumFaces Value of *MESH_NUMTVFACES, if present.
485 //! Otherwise zero. This is used to check the consistency of the file.
486 //! A warning is sent to the logger if the validations fails.
487 //! \param mesh Mesh object to be filled
488 //! \param iChannel Output UVW channel
489 void ParseLV3MeshTFaceListBlock(
490 unsigned int iNumFaces,Mesh& mesh, unsigned int iChannel = 0);
491
492 // -------------------------------------------------------------------
493 //! Parse an additional mapping channel
494 //! (specified via *MESH_MAPPINGCHANNEL)
495 //! \param iChannel Channel index to be filled
496 //! \param mesh Mesh object to be filled
497 void ParseLV3MappingChannel(
498 unsigned int iChannel, Mesh& mesh);
499
500 // -------------------------------------------------------------------
501 //! Parse a *MESH_CVERTLIST block in a file
502 //! \param iNumVertices Value of *MESH_NUMCVERTEX, if present.
503 //! Otherwise zero. This is used to check the consistency of the file.
504 //! A warning is sent to the logger if the validations fails.
505 //! \param mesh Mesh object to be filled
506 void ParseLV3MeshCListBlock(
507 unsigned int iNumVertices, Mesh& mesh);
508
509 // -------------------------------------------------------------------
510 //! Parse a *MESH_CFACELIST block in a file
511 //! \param iNumFaces Value of *MESH_NUMCVFACES, if present.
512 //! Otherwise zero. This is used to check the consistency of the file.
513 //! A warning is sent to the logger if the validations fails.
514 //! \param mesh Mesh object to be filled
515 void ParseLV3MeshCFaceListBlock(
516 unsigned int iNumFaces, Mesh& mesh);
517
518 // -------------------------------------------------------------------
519 //! Parse a *MESH_NORMALS block in a file
520 //! \param mesh Mesh object to be filled
521 void ParseLV3MeshNormalListBlock(Mesh& mesh);
522
523 // -------------------------------------------------------------------
524 //! Parse a *MESH_WEIGHTSblock in a file
525 //! \param mesh Mesh object to be filled
526 void ParseLV3MeshWeightsBlock(Mesh& mesh);
527
528 // -------------------------------------------------------------------
529 //! Parse the bone list of a file
530 //! \param mesh Mesh object to be filled
531 //! \param iNumBones Number of bones in the mesh
532 void ParseLV4MeshBones(unsigned int iNumBones,Mesh& mesh);
533
534 // -------------------------------------------------------------------
535 //! Parse the bone vertices list of a file
536 //! \param mesh Mesh object to be filled
537 //! \param iNumVertices Number of vertices to be parsed
538 void ParseLV4MeshBonesVertices(unsigned int iNumVertices,Mesh& mesh);
539
540 // -------------------------------------------------------------------
541 //! Parse a *MESH_FACE block in a file
542 //! \param out receive the face data
543 void ParseLV4MeshFace(ASE::Face& out);
544
545 // -------------------------------------------------------------------
546 //! Parse a *MESH_VERT block in a file
547 //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...)
548 //! \param apOut Output buffer (3 floats)
549 //! \param rIndexOut Output index
550 void ParseLV4MeshFloatTriple(ai_real* apOut, unsigned int& rIndexOut);
551
552 // -------------------------------------------------------------------
553 //! Parse a *MESH_VERT block in a file
554 //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...)
555 //! \param apOut Output buffer (3 floats)
556 void ParseLV4MeshFloatTriple(ai_real* apOut);
557
558 // -------------------------------------------------------------------
559 //! Parse a *MESH_TFACE block in a file
560 //! (also works for MESH_CFACE)
561 //! \param apOut Output buffer (3 ints)
562 //! \param rIndexOut Output index
563 void ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut);
564
565 // -------------------------------------------------------------------
566 //! Parse a *MESH_TFACE block in a file
567 //! (also works for MESH_CFACE)
568 //! \param apOut Output buffer (3 ints)
569 void ParseLV4MeshLongTriple(unsigned int* apOut);
570
571 // -------------------------------------------------------------------
572 //! Parse a single float element
573 //! \param fOut Output float
574 void ParseLV4MeshFloat(ai_real& fOut);
575
576 // -------------------------------------------------------------------
577 //! Parse a single int element
578 //! \param iOut Output integer
579 void ParseLV4MeshLong(unsigned int& iOut);
580
581 // -------------------------------------------------------------------
582 //! Skip everything to the next: '*' or '\0'
583 bool SkipToNextToken();
584
585 // -------------------------------------------------------------------
586 //! Skip the current section until the token after the closing }.
587 //! This function handles embedded subsections correctly
588 bool SkipSection();
589
590 // -------------------------------------------------------------------
591 //! Output a warning to the logger
592 //! \param szWarn Warn message
593 void LogWarning(const char* szWarn);
594
595 // -------------------------------------------------------------------
596 //! Output a message to the logger
597 //! \param szWarn Message
598 void LogInfo(const char* szWarn);
599
600 // -------------------------------------------------------------------
601 //! Output an error to the logger
602 //! \param szWarn Error message
603 AI_WONT_RETURN void LogError(const char* szWarn) AI_WONT_RETURN_SUFFIX;
604
605 // -------------------------------------------------------------------
606 //! Parse a string, enclosed in double quotation marks
607 //! \param out Output string
608 //! \param szName Name of the enclosing element -> used in error
609 //! messages.
610 //! \return false if an error occurred
611 bool ParseString(std::string& out,const char* szName);
612
613public:
614
615 //! Pointer to current data
616 const char* filePtr;
617
618 //! background color to be passed to the viewer
619 //! QNAN if none was found
620 aiColor3D m_clrBackground;
621
622 //! Base ambient color to be passed to all materials
623 //! QNAN if none was found
624 aiColor3D m_clrAmbient;
625
626 //! List of all materials found in the file
627 std::vector<Material> m_vMaterials;
628
629 //! List of all meshes found in the file
630 std::vector<Mesh> m_vMeshes;
631
632 //! List of all dummies found in the file
633 std::vector<Dummy> m_vDummies;
634
635 //! List of all lights found in the file
636 std::vector<Light> m_vLights;
637
638 //! List of all cameras found in the file
639 std::vector<Camera> m_vCameras;
640
641 //! Current line in the file
642 unsigned int iLineNumber;
643
644 //! First frame
645 unsigned int iFirstFrame;
646
647 //! Last frame
648 unsigned int iLastFrame;
649
650 //! Frame speed - frames per second
651 unsigned int iFrameSpeed;
652
653 //! Ticks per frame
654 unsigned int iTicksPerFrame;
655
656 //! true if the last character read was an end-line character
657 bool bLastWasEndLine;
658
659 //! File format version
660 unsigned int iFileFormat;
661};
662
663
664} // Namespace ASE
665} // Namespace ASSIMP
666
667#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
668
669#endif // !! include guard
670