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 /** @file Defines helper data structures for the import of 3DS files */
43 
44 #ifndef AI_3DSFILEHELPER_H_INC
45 #define AI_3DSFILEHELPER_H_INC
46 
47 #include "SpatialSort.h"
48 #include "SmoothingGroups.h"
49 #include "StringUtils.h"
50 #include "qnan.h"
51 #include <assimp/material.h>
52 #include <assimp/camera.h>
53 #include <assimp/light.h>
54 #include <assimp/anim.h>
55 #include <stdio.h> //sprintf
56 
57 namespace Assimp    {
58 namespace D3DS  {
59 
60 #include "./../include/assimp/Compiler/pushpack1.h"
61 
62 // ---------------------------------------------------------------------------
63 /** Discreet3DS class: Helper class for loading 3ds files. Defines chunks
64 *  and data structures.
65 */
66 class Discreet3DS {
67 private:
Discreet3DS()68     Discreet3DS() {
69         // empty
70     }
71 
~Discreet3DS()72     ~Discreet3DS() {
73         // empty
74     }
75 
76 public:
77     //! data structure for a single chunk in a .3ds file
78     struct Chunk {
79         uint16_t    Flag;
80         uint32_t    Size;
81     } PACK_STRUCT;
82 
83 
84     //! Used for shading field in material3ds structure
85     //! From AutoDesk 3ds SDK
86     typedef enum
87     {
88         // translated to gouraud shading with wireframe active
89         Wire = 0x0,
90 
91         // if this material is set, no vertex normals will
92         // be calculated for the model. Face normals + gouraud
93         Flat = 0x1,
94 
95         // standard gouraud shading
96         Gouraud = 0x2,
97 
98         // phong shading
99         Phong = 0x3,
100 
101         // cooktorrance or anistropic phong shading ...
102         // the exact meaning is unknown, if you know it
103         // feel free to tell me ;-)
104         Metal = 0x4,
105 
106         // required by the ASE loader
107         Blinn = 0x5
108     } shadetype3ds;
109 
110     // Flags for animated keys
111     enum
112     {
113         KEY_USE_TENS         = 0x1,
114         KEY_USE_CONT         = 0x2,
115         KEY_USE_BIAS         = 0x4,
116         KEY_USE_EASE_TO      = 0x8,
117         KEY_USE_EASE_FROM    = 0x10
118     } ;
119 
120     enum
121     {
122 
123         // ********************************************************************
124         // Basic chunks which can be found everywhere in the file
125         CHUNK_VERSION   = 0x0002,
126         CHUNK_RGBF      = 0x0010,       // float4 R; float4 G; float4 B
127         CHUNK_RGBB      = 0x0011,       // int1 R; int1 G; int B
128 
129         // Linear color values (gamma = 2.2?)
130         CHUNK_LINRGBF      = 0x0013,    // float4 R; float4 G; float4 B
131         CHUNK_LINRGBB      = 0x0012,    // int1 R; int1 G; int B
132 
133         CHUNK_PERCENTW  = 0x0030,       // int2   percentage
134         CHUNK_PERCENTF  = 0x0031,       // float4  percentage
135         CHUNK_PERCENTD  = 0x0032,       // float8  percentage
136         // ********************************************************************
137 
138         // Prj master chunk
139         CHUNK_PRJ       = 0xC23D,
140 
141         // MDLI master chunk
142         CHUNK_MLI       = 0x3DAA,
143 
144         // Primary main chunk of the .3ds file
145         CHUNK_MAIN      = 0x4D4D,
146 
147         // Mesh main chunk
148         CHUNK_OBJMESH   = 0x3D3D,
149 
150         // Specifies the background color of the .3ds file
151         // This is passed through the material system for
152         // viewing purposes.
153         CHUNK_BKGCOLOR  = 0x1200,
154 
155         // Specifies the ambient base color of the scene.
156         // This is added to all materials in the file
157         CHUNK_AMBCOLOR  = 0x2100,
158 
159         // Specifies the background image for the whole scene
160         // This value is passed through the material system
161         // to the viewer
162         CHUNK_BIT_MAP   = 0x1100,
163         CHUNK_BIT_MAP_EXISTS  = 0x1101,
164 
165         // ********************************************************************
166         // Viewport related stuff. Ignored
167         CHUNK_DEFAULT_VIEW = 0x3000,
168         CHUNK_VIEW_TOP = 0x3010,
169         CHUNK_VIEW_BOTTOM = 0x3020,
170         CHUNK_VIEW_LEFT = 0x3030,
171         CHUNK_VIEW_RIGHT = 0x3040,
172         CHUNK_VIEW_FRONT = 0x3050,
173         CHUNK_VIEW_BACK = 0x3060,
174         CHUNK_VIEW_USER = 0x3070,
175         CHUNK_VIEW_CAMERA = 0x3080,
176         // ********************************************************************
177 
178         // Mesh chunks
179         CHUNK_OBJBLOCK  = 0x4000,
180         CHUNK_TRIMESH   = 0x4100,
181         CHUNK_VERTLIST  = 0x4110,
182         CHUNK_VERTFLAGS = 0x4111,
183         CHUNK_FACELIST  = 0x4120,
184         CHUNK_FACEMAT   = 0x4130,
185         CHUNK_MAPLIST   = 0x4140,
186         CHUNK_SMOOLIST  = 0x4150,
187         CHUNK_TRMATRIX  = 0x4160,
188         CHUNK_MESHCOLOR = 0x4165,
189         CHUNK_TXTINFO   = 0x4170,
190         CHUNK_LIGHT     = 0x4600,
191         CHUNK_CAMERA    = 0x4700,
192         CHUNK_HIERARCHY = 0x4F00,
193 
194         // Specifies the global scaling factor. This is applied
195         // to the root node's transformation matrix
196         CHUNK_MASTER_SCALE    = 0x0100,
197 
198         // ********************************************************************
199         // Material chunks
200         CHUNK_MAT_MATERIAL  = 0xAFFF,
201 
202             // asciiz containing the name of the material
203             CHUNK_MAT_MATNAME   = 0xA000,
204             CHUNK_MAT_AMBIENT   = 0xA010, // followed by color chunk
205             CHUNK_MAT_DIFFUSE   = 0xA020, // followed by color chunk
206             CHUNK_MAT_SPECULAR  = 0xA030, // followed by color chunk
207 
208             // Specifies the shininess of the material
209             // followed by percentage chunk
210             CHUNK_MAT_SHININESS  = 0xA040,
211             CHUNK_MAT_SHININESS_PERCENT  = 0xA041 ,
212 
213             // Specifies the shading mode to be used
214             // followed by a short
215             CHUNK_MAT_SHADING  = 0xA100,
216 
217             // NOTE: Emissive color (self illumination) seems not
218             // to be a color but a single value, type is unknown.
219             // Make the parser accept both of them.
220             // followed by percentage chunk (?)
221             CHUNK_MAT_SELF_ILLUM = 0xA080,
222 
223             // Always followed by percentage chunk  (?)
224             CHUNK_MAT_SELF_ILPCT = 0xA084,
225 
226             // Always followed by percentage chunk
227             CHUNK_MAT_TRANSPARENCY = 0xA050,
228 
229             // Diffuse texture channel 0
230             CHUNK_MAT_TEXTURE   = 0xA200,
231 
232             // Contains opacity information for each texel
233             CHUNK_MAT_OPACMAP = 0xA210,
234 
235             // Contains a reflection map to be used to reflect
236             // the environment. This is partially supported.
237             CHUNK_MAT_REFLMAP = 0xA220,
238 
239             // Self Illumination map (emissive colors)
240             CHUNK_MAT_SELFIMAP = 0xA33d,
241 
242             // Bumpmap. Not specified whether it is a heightmap
243             // or a normal map. Assme it is a heightmap since
244             // artist normally prefer this format.
245             CHUNK_MAT_BUMPMAP = 0xA230,
246 
247             // Specular map. Seems to influence the specular color
248             CHUNK_MAT_SPECMAP = 0xA204,
249 
250             // Holds shininess data.
251             CHUNK_MAT_MAT_SHINMAP = 0xA33C,
252 
253             // Scaling in U/V direction.
254             // (need to gen separate UV coordinate set
255             // and do this by hand)
256             CHUNK_MAT_MAP_USCALE      = 0xA354,
257             CHUNK_MAT_MAP_VSCALE      = 0xA356,
258 
259             // Translation in U/V direction.
260             // (need to gen separate UV coordinate set
261             // and do this by hand)
262             CHUNK_MAT_MAP_UOFFSET     = 0xA358,
263             CHUNK_MAT_MAP_VOFFSET     = 0xA35a,
264 
265             // UV-coordinates rotation around the z-axis
266             // Assumed to be in radians.
267             CHUNK_MAT_MAP_ANG = 0xA35C,
268 
269             // Tiling flags for 3DS files
270             CHUNK_MAT_MAP_TILING = 0xa351,
271 
272             // Specifies the file name of a texture
273             CHUNK_MAPFILE   = 0xA300,
274 
275             // Specifies whether a materail requires two-sided rendering
276             CHUNK_MAT_TWO_SIDE = 0xA081,
277         // ********************************************************************
278 
279         // Main keyframer chunk. Contains translation/rotation/scaling data
280         CHUNK_KEYFRAMER     = 0xB000,
281 
282         // Supported sub chunks
283         CHUNK_TRACKINFO     = 0xB002,
284         CHUNK_TRACKOBJNAME  = 0xB010,
285         CHUNK_TRACKDUMMYOBJNAME  = 0xB011,
286         CHUNK_TRACKPIVOT    = 0xB013,
287         CHUNK_TRACKPOS      = 0xB020,
288         CHUNK_TRACKROTATE   = 0xB021,
289         CHUNK_TRACKSCALE    = 0xB022,
290 
291         // ********************************************************************
292         // Keyframes for various other stuff in the file
293         // Partially ignored
294         CHUNK_AMBIENTKEY    = 0xB001,
295         CHUNK_TRACKMORPH    = 0xB026,
296         CHUNK_TRACKHIDE     = 0xB029,
297         CHUNK_OBJNUMBER     = 0xB030,
298         CHUNK_TRACKCAMERA   = 0xB003,
299         CHUNK_TRACKFOV      = 0xB023,
300         CHUNK_TRACKROLL     = 0xB024,
301         CHUNK_TRACKCAMTGT   = 0xB004,
302         CHUNK_TRACKLIGHT    = 0xB005,
303         CHUNK_TRACKLIGTGT   = 0xB006,
304         CHUNK_TRACKSPOTL    = 0xB007,
305         CHUNK_FRAMES        = 0xB008,
306         // ********************************************************************
307 
308         // light sub-chunks
309         CHUNK_DL_OFF                 = 0x4620,
310         CHUNK_DL_OUTER_RANGE         = 0x465A,
311         CHUNK_DL_INNER_RANGE         = 0x4659,
312         CHUNK_DL_MULTIPLIER          = 0x465B,
313         CHUNK_DL_EXCLUDE             = 0x4654,
314         CHUNK_DL_ATTENUATE           = 0x4625,
315         CHUNK_DL_SPOTLIGHT           = 0x4610,
316 
317         // camera sub-chunks
318         CHUNK_CAM_RANGES             = 0x4720
319     };
320 };
321 
322 // ---------------------------------------------------------------------------
323 /** Helper structure representing a 3ds mesh face */
324 struct Face : public FaceWithSmoothingGroup
325 {
326 };
327 
328 // ---------------------------------------------------------------------------
329 /** Helper structure representing a texture */
330 struct Texture
331 {
332     //! Default constructor
TextureTexture333     Texture()
334         : mOffsetU  (0.0)
335         , mOffsetV  (0.0)
336         , mScaleU   (1.0)
337         , mScaleV   (1.0)
338         , mRotation (0.0)
339         , mMapMode  (aiTextureMapMode_Wrap)
340         , bPrivate()
341         , iUVSrc    (0)
342     {
343         mTextureBlend = get_qnan();
344     }
345 
346     //! Specifies the blend factor for the texture
347     ai_real mTextureBlend;
348 
349     //! Specifies the filename of the texture
350     std::string mMapName;
351 
352     //! Specifies texture coordinate offsets/scaling/rotations
353     ai_real mOffsetU;
354     ai_real mOffsetV;
355     ai_real mScaleU;
356     ai_real mScaleV;
357     ai_real mRotation;
358 
359     //! Specifies the mapping mode to be used for the texture
360     aiTextureMapMode mMapMode;
361 
362     //! Used internally
363     bool bPrivate;
364     int iUVSrc;
365 };
366 
367 #include "./../include/assimp/Compiler/poppack1.h"
368 
369 // ---------------------------------------------------------------------------
370 /** Helper structure representing a 3ds material */
371 struct Material
372 {
373     //! Default constructor. Builds a default name for the material
MaterialMaterial374     Material()
375     : mDiffuse            ( ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 0.6 ) ) // FIX ... we won't want object to be black
376     , mSpecularExponent   ( ai_real( 0.0 ) )
377     , mShininessStrength  ( ai_real( 1.0 ) )
378     , mShading(Discreet3DS::Gouraud)
379     , mTransparency       ( ai_real( 1.0 ) )
380     , mBumpHeight         ( ai_real( 1.0 ) )
381     , mTwoSided           (false)
382     {
383         static int iCnt = 0;
384 
385         char szTemp[128];
386         ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
387         mName = szTemp;
388     }
389 
390     //! Name of the material
391     std::string mName;
392     //! Diffuse color of the material
393     aiColor3D mDiffuse;
394     //! Specular exponent
395     ai_real mSpecularExponent;
396     //! Shininess strength, in percent
397     ai_real mShininessStrength;
398     //! Specular color of the material
399     aiColor3D mSpecular;
400     //! Ambient color of the material
401     aiColor3D mAmbient;
402     //! Shading type to be used
403     Discreet3DS::shadetype3ds mShading;
404     //! Opacity of the material
405     ai_real mTransparency;
406     //! Diffuse texture channel
407     Texture sTexDiffuse;
408     //! Opacity texture channel
409     Texture sTexOpacity;
410     //! Specular texture channel
411     Texture sTexSpecular;
412     //! Reflective texture channel
413     Texture sTexReflective;
414     //! Bump texture channel
415     Texture sTexBump;
416     //! Emissive texture channel
417     Texture sTexEmissive;
418     //! Shininess texture channel
419     Texture sTexShininess;
420     //! Scaling factor for the bump values
421     ai_real mBumpHeight;
422     //! Emissive color
423     aiColor3D mEmissive;
424     //! Ambient texture channel
425     //! (used by the ASE format)
426     Texture sTexAmbient;
427     //! True if the material must be rendered from two sides
428     bool mTwoSided;
429 };
430 
431 // ---------------------------------------------------------------------------
432 /** Helper structure to represent a 3ds file mesh */
433 struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
434 {
435     //! Default constructor
MeshMesh436     Mesh()
437     {
438         static int iCnt = 0;
439 
440         // Generate a default name for the mesh
441         char szTemp[128];
442         ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
443         mName = szTemp;
444     }
445 
446     //! Name of the mesh
447     std::string mName;
448 
449     //! Texture coordinates
450     std::vector<aiVector3D> mTexCoords;
451 
452     //! Face materials
453     std::vector<unsigned int> mFaceMaterials;
454 
455     //! Local transformation matrix
456     aiMatrix4x4 mMat;
457 };
458 
459 // ---------------------------------------------------------------------------
460 /** Float key - quite similar to aiVectorKey and aiQuatKey. Both are in the
461     C-API, so it would be difficult to make them a template. */
462 struct aiFloatKey
463 {
464     double mTime;      ///< The time of this key
465     ai_real mValue;   ///< The value of this key
466 
467 #ifdef __cplusplus
468 
469     // time is not compared
470     bool operator == (const aiFloatKey& o) const
471         {return o.mValue == this->mValue;}
472 
473     bool operator != (const aiFloatKey& o) const
474         {return o.mValue != this->mValue;}
475 
476     // Only time is compared. This operator is defined
477     // for use with std::sort
478     bool operator < (const aiFloatKey& o) const
479         {return mTime < o.mTime;}
480 
481     bool operator > (const aiFloatKey& o) const
482         {return mTime > o.mTime;}
483 
484 #endif
485 };
486 
487 // ---------------------------------------------------------------------------
488 /** Helper structure to represent a 3ds file node */
489 struct Node
490 {
NodeNode491     Node():
492     	mParent(NULL)
493 		,	mInstanceNumber(0)
494 		,	mHierarchyPos		(0)
495 		,	mHierarchyIndex		(0)
496 		,	mInstanceCount		(1)
497     {
498         static int iCnt = 0;
499 
500         // Generate a default name for the node
501         char szTemp[128];
502         ::ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
503         mName = szTemp;
504 
505         aRotationKeys.reserve (20);
506         aPositionKeys.reserve (20);
507         aScalingKeys.reserve  (20);
508     }
509 
~NodeNode510     ~Node()
511     {
512         for (unsigned int i = 0; i < mChildren.size();++i)
513             delete mChildren[i];
514     }
515 
516     //! Pointer to the parent node
517     Node* mParent;
518 
519     //! Holds all child nodes
520     std::vector<Node*> mChildren;
521 
522     //! Name of the node
523     std::string mName;
524 
525     //! InstanceNumber of the node
526     int32_t mInstanceNumber;
527 
528     //! Dummy nodes: real name to be combined with the $$$DUMMY
529     std::string mDummyName;
530 
531     //! Position of the node in the hierarchy (tree depth)
532     int16_t mHierarchyPos;
533 
534     //! Index of the node
535     int16_t mHierarchyIndex;
536 
537     //! Rotation keys loaded from the file
538     std::vector<aiQuatKey> aRotationKeys;
539 
540     //! Position keys loaded from the file
541     std::vector<aiVectorKey> aPositionKeys;
542 
543     //! Scaling keys loaded from the file
544     std::vector<aiVectorKey> aScalingKeys;
545 
546 
547     // For target lights (spot lights and directional lights):
548     // The position of the target
549     std::vector< aiVectorKey > aTargetPositionKeys;
550 
551     // For cameras: the camera roll angle
552     std::vector< aiFloatKey > aCameraRollKeys;
553 
554     //! Pivot position loaded from the file
555     aiVector3D vPivot;
556 
557     //instance count, will be kept only for the first node
558     int32_t mInstanceCount;
559 
560     //! Add a child node, setup the right parent node for it
561     //! \param pc Node to be 'adopted'
push_backNode562     inline Node& push_back(Node* pc)
563     {
564         mChildren.push_back(pc);
565         pc->mParent = this;
566         return *this;
567     }
568 };
569 // ---------------------------------------------------------------------------
570 /** Helper structure analogue to aiScene */
571 struct Scene
572 {
573     //! List of all materials loaded
574     //! NOTE: 3ds references materials globally
575     std::vector<Material> mMaterials;
576 
577     //! List of all meshes loaded
578     std::vector<Mesh> mMeshes;
579 
580     //! List of all cameras loaded
581     std::vector<aiCamera*> mCameras;
582 
583     //! List of all lights loaded
584     std::vector<aiLight*> mLights;
585 
586     //! Pointer to the root node of the scene
587     // --- moved to main class
588     // Node* pcRootNode;
589 };
590 
591 
592 } // end of namespace D3DS
593 } // end of namespace Assimp
594 
595 #endif // AI_XFILEHELPER_H_INC
596