1 /*
2 Open Asset Import Library (assimp)
3 ----------------------------------------------------------------------
4 
5 Copyright (c) 2006-2019, assimp team
6 
7 
8 All rights reserved.
9 
10 Redistribution and use of this software in source and binary forms,
11 with or without modification, are permitted provided that the
12 following conditions are met:
13 
14 * Redistributions of source code must retain the above
15   copyright notice, this list of conditions and the
16   following disclaimer.
17 
18 * Redistributions in binary form must reproduce the above
19   copyright notice, this list of conditions and the
20   following disclaimer in the documentation and/or other
21   materials provided with the distribution.
22 
23 * Neither the name of the assimp team, nor the names of its
24   contributors may be used to endorse or promote products
25   derived from this software without specific prior
26   written permission of the assimp team.
27 
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 
40 ----------------------------------------------------------------------
41 */
42 
43 /** @file Declaration of the LWO importer class. */
44 #ifndef AI_LWOLOADER_H_INCLUDED
45 #define AI_LWOLOADER_H_INCLUDED
46 
47 #include <assimp/types.h>
48 #include <assimp/material.h>
49 #include <assimp/DefaultLogger.hpp>
50 
51 #include "LWOFileData.h"
52 #include <assimp/BaseImporter.h>
53 
54 #include <map>
55 
56 struct aiTexture;
57 struct aiNode;
58 struct aiMaterial;
59 
60 namespace Assimp    {
61 using namespace LWO;
62 
63 // ---------------------------------------------------------------------------
64 /** Class to load LWO files.
65  *
66  *  @note  Methods named "xxxLWO2[xxx]" are used with the newer LWO2 format.
67  *         Methods named "xxxLWOB[xxx]" are used with the older LWOB format.
68  *         Methods named "xxxLWO[xxx]" are used with both formats.
69  *         Methods named "xxx" are used to preprocess the loaded data -
70  *         they aren't specific to one format version
71 */
72 // ---------------------------------------------------------------------------
73 class LWOImporter : public BaseImporter
74 {
75 public:
76     LWOImporter();
77     ~LWOImporter();
78 
79 
80 public:
81 
82     // -------------------------------------------------------------------
83     /** Returns whether the class can handle the format of the given file.
84      * See BaseImporter::CanRead() for details.
85      */
86     bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
87         bool checkSig) const;
88 
89 
90     // -------------------------------------------------------------------
91     /** Called prior to ReadFile().
92     * The function is a request to the importer to update its configuration
93     * basing on the Importer's configuration property list.
94     */
95     void SetupProperties(const Importer* pImp);
96 
97 protected:
98 
99     // -------------------------------------------------------------------
100     // Get list of supported extensions
101     const aiImporterDesc* GetInfo () const;
102 
103     // -------------------------------------------------------------------
104     /** Imports the given file into the given scene structure.
105     * See BaseImporter::InternReadFile() for details
106     */
107     void InternReadFile( const std::string& pFile, aiScene* pScene,
108         IOSystem* pIOHandler);
109 
110 private:
111 
112     // -------------------------------------------------------------------
113     /** Loads a LWO file in the older LWOB format (LW < 6)
114      */
115     void LoadLWOBFile();
116 
117     // -------------------------------------------------------------------
118     /** Loads a LWO file in the newer LWO2 format (LW >= 6)
119      */
120     void LoadLWO2File();
121 
122 
123     // -------------------------------------------------------------------
124     /** Parsing functions used for all file format versions
125     */
126     inline void GetS0(std::string& out,unsigned int max);
127     inline float GetF4();
128     inline uint32_t GetU4();
129     inline uint16_t GetU2();
130     inline uint8_t  GetU1();
131 
132 
133     // -------------------------------------------------------------------
134     /** Loads a surface chunk from an LWOB file
135      *  @param size Maximum size to be read, in bytes.
136      */
137     void LoadLWOBSurface(unsigned int size);
138 
139     // -------------------------------------------------------------------
140     /** Loads a surface chunk from an LWO2 file
141      *  @param size Maximum size to be read, in bytes.
142      */
143     void LoadLWO2Surface(unsigned int size);
144 
145     // -------------------------------------------------------------------
146     /** Loads a texture block from a LWO2 file.
147      *  @param size Maximum size to be read, in bytes.
148      *  @param head Header of the SUF.BLOK header
149      */
150     void LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head,
151         unsigned int size );
152 
153     // -------------------------------------------------------------------
154     /** Loads a shader block from a LWO2 file.
155      *  @param size Maximum size to be read, in bytes.
156      *  @param head Header of the SUF.BLOK header
157      */
158     void LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* head,
159         unsigned int size );
160 
161     // -------------------------------------------------------------------
162     /** Loads an image map from a LWO2 file
163      *  @param size Maximum size to be read, in bytes.
164      *  @param tex Texture object to be filled
165      */
166     void LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex );
167     void LoadLWO2Gradient(unsigned int size, LWO::Texture& tex );
168     void LoadLWO2Procedural(unsigned int size, LWO::Texture& tex );
169 
170     // loads the header - used by thethree functions above
171     void LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex );
172 
173     // -------------------------------------------------------------------
174     /** Loads the LWO tag list from the file
175      *  @param size Maximum size to be read, in bytes.
176      */
177     void LoadLWOTags(unsigned int size);
178 
179     // -------------------------------------------------------------------
180     /** Load polygons from a POLS chunk
181      *  @param length Size of the chunk
182     */
183     void LoadLWO2Polygons(unsigned int length);
184     void LoadLWOBPolygons(unsigned int length);
185 
186     // -------------------------------------------------------------------
187     /** Load polygon tags from a PTAG chunk
188      *  @param length Size of the chunk
189     */
190     void LoadLWO2PolygonTags(unsigned int length);
191 
192     // -------------------------------------------------------------------
193     /** Load a vertex map from a VMAP/VMAD chunk
194      *  @param length Size of the chunk
195      *  @param perPoly Operate on per-polygon base?
196     */
197     void LoadLWO2VertexMap(unsigned int length, bool perPoly);
198 
199     // -------------------------------------------------------------------
200     /** Load polygons from a PNTS chunk
201      *  @param length Size of the chunk
202     */
203     void LoadLWOPoints(unsigned int length);
204 
205     // -------------------------------------------------------------------
206     /** Load a clip from a CLIP chunk
207      *  @param length Size of the chunk
208     */
209     void LoadLWO2Clip(unsigned int length);
210 
211     // -------------------------------------------------------------------
212     /** Load an envelope from an EVL chunk
213      *  @param length Size of the chunk
214     */
215     void LoadLWO2Envelope(unsigned int length);
216 
217     // -------------------------------------------------------------------
218     /** Count vertices and faces in a LWOB/LWO2 file
219     */
220     void CountVertsAndFacesLWO2(unsigned int& verts,
221         unsigned int& faces,
222         uint16_t*& cursor,
223         const uint16_t* const end,
224         unsigned int max = UINT_MAX);
225 
226     void CountVertsAndFacesLWOB(unsigned int& verts,
227         unsigned int& faces,
228         LE_NCONST uint16_t*& cursor,
229         const uint16_t* const end,
230         unsigned int max = UINT_MAX);
231 
232     // -------------------------------------------------------------------
233     /** Read vertices and faces in a LWOB/LWO2 file
234     */
235     void CopyFaceIndicesLWO2(LWO::FaceList::iterator& it,
236         uint16_t*& cursor,
237         const uint16_t* const end);
238 
239     // -------------------------------------------------------------------
240     void CopyFaceIndicesLWOB(LWO::FaceList::iterator& it,
241         LE_NCONST uint16_t*& cursor,
242         const uint16_t* const end,
243         unsigned int max = UINT_MAX);
244 
245     // -------------------------------------------------------------------
246     /** Resolve the tag and surface lists that have been loaded.
247     *   Generates the mMapping table.
248     */
249     void ResolveTags();
250 
251     // -------------------------------------------------------------------
252     /** Resolve the clip list that has been loaded.
253     *   Replaces clip references with real clips.
254     */
255     void ResolveClips();
256 
257     // -------------------------------------------------------------------
258     /** Add a texture list to an output material description.
259      *
260      *  @param pcMat Output material
261      *  @param in Input texture list
262      *  @param type Type identifier of the texture list
263     */
264     bool HandleTextures(aiMaterial* pcMat, const TextureList& in,
265         aiTextureType type);
266 
267     // -------------------------------------------------------------------
268     /** Adjust a texture path
269     */
270     void AdjustTexturePath(std::string& out);
271 
272     // -------------------------------------------------------------------
273     /** Convert a LWO surface description to an ASSIMP material
274     */
275     void ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat);
276 
277 
278     // -------------------------------------------------------------------
279     /** Get a list of all UV/VC channels required by a specific surface.
280      *
281      *  @param surf Working surface
282      *  @param layer Working layer
283      *  @param out Output list. The members are indices into the
284      *    UV/VC channel lists of the layer
285     */
286     void FindUVChannels(/*const*/ LWO::Surface& surf,
287         LWO::SortedRep& sorted,
288         /*const*/ LWO::Layer& layer,
289         unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS]);
290 
291     // -------------------------------------------------------------------
292     char FindUVChannels(LWO::TextureList& list,
293         LWO::Layer& layer,LWO::UVChannel& uv, unsigned int next);
294 
295     // -------------------------------------------------------------------
296     void FindVCChannels(const LWO::Surface& surf,
297         LWO::SortedRep& sorted,
298         const LWO::Layer& layer,
299         unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS]);
300 
301     // -------------------------------------------------------------------
302     /** Generate the final node graph
303      *  Unused nodes are deleted.
304      *  @param apcNodes Flat list of nodes
305     */
306     void GenerateNodeGraph(std::map<uint16_t,aiNode*>& apcNodes);
307 
308     // -------------------------------------------------------------------
309     /** Add children to a node
310      *  @param node Node to become a father
311      *  @param parent Index of the node
312      *  @param apcNodes Flat list of nodes - used nodes are set to NULL.
313     */
314     void AddChildren(aiNode* node, uint16_t parent,
315         std::vector<aiNode*>& apcNodes);
316 
317     // -------------------------------------------------------------------
318     /** Read a variable sized integer
319      *  @param inout Input and output buffer
320     */
321     int ReadVSizedIntLWO2(uint8_t*& inout);
322 
323     // -------------------------------------------------------------------
324     /** Assign a value from a VMAP to a vertex and all vertices
325      *  attached to it.
326      *  @param base VMAP destination data
327      *  @param numRead Number of float's to be read
328      *  @param idx Absolute index of the first vertex
329      *  @param data Value of the VMAP to be assigned - read numRead
330      *    floats from this array.
331     */
332     void DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int numRead,
333         unsigned int idx, float* data);
334 
335     // -------------------------------------------------------------------
336     /** Compute normal vectors for a mesh
337      *  @param mesh Input mesh
338      *  @param smoothingGroups Smoothing-groups-per-face array
339      *  @param surface Surface for the mesh
340     */
341     void ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>& smoothingGroups,
342         const LWO::Surface& surface);
343 
344 
345     // -------------------------------------------------------------------
346     /** Setup a new texture after the corresponding chunk was
347      *  encountered in the file.
348      *  @param list Texture list
349      *  @param size Maximum number of bytes to be read
350      *  @return Pointer to new texture
351     */
352     LWO::Texture* SetupNewTextureLWOB(LWO::TextureList& list,
353         unsigned int size);
354 
355 protected:
356 
357     /** true if the file is a LWO2 file*/
358     bool mIsLWO2;
359 
360     /** true if the file is a LXOB file*/
361     bool mIsLXOB;
362 
363     /** Temporary list of layers from the file */
364     LayerList* mLayers;
365 
366     /** Pointer to the current layer */
367     LWO::Layer* mCurLayer;
368 
369     /** Temporary tag list from the file */
370     TagList* mTags;
371 
372     /** Mapping table to convert from tag to surface indices.
373         UINT_MAX indicates that a no corresponding surface is available */
374     TagMappingTable* mMapping;
375 
376     /** Temporary surface list from the file */
377     SurfaceList* mSurfaces;
378 
379     /** Temporary clip list from the file */
380     ClipList mClips;
381 
382     /** Temporary envelope list from the file */
383     EnvelopeList mEnvelopes;
384 
385     /** file buffer */
386     uint8_t* mFileBuffer;
387 
388     /** Size of the file, in bytes */
389     unsigned int fileSize;
390 
391     /** Output scene */
392     aiScene* pScene;
393 
394     /** Configuration option: speed flag set? */
395     bool configSpeedFlag;
396 
397     /** Configuration option: index of layer to be loaded */
398     unsigned int configLayerIndex;
399 
400     /** Configuration option: name of layer to be loaded */
401     std::string  configLayerName;
402 
403     /** True if we have a named layer */
404     bool hasNamedLayer;
405 };
406 
407 
408 // ------------------------------------------------------------------------------------------------
GetF4()409 inline float LWOImporter::GetF4()
410 {
411     float f;
412     ::memcpy(&f, mFileBuffer, 4);
413     mFileBuffer += 4;
414     AI_LSWAP4(f);
415     return f;
416 }
417 
418 // ------------------------------------------------------------------------------------------------
GetU4()419 inline uint32_t LWOImporter::GetU4()
420 {
421     uint32_t f;
422     ::memcpy(&f, mFileBuffer, 4);
423     mFileBuffer += 4;
424     AI_LSWAP4(f);
425     return f;
426 }
427 
428 // ------------------------------------------------------------------------------------------------
GetU2()429 inline uint16_t LWOImporter::GetU2()
430 {
431     uint16_t f;
432     ::memcpy(&f, mFileBuffer, 2);
433     mFileBuffer += 2;
434     AI_LSWAP2(f);
435     return f;
436 }
437 
438 // ------------------------------------------------------------------------------------------------
GetU1()439 inline uint8_t LWOImporter::GetU1()
440 {
441     return *mFileBuffer++;
442 }
443 
444 // ------------------------------------------------------------------------------------------------
ReadVSizedIntLWO2(uint8_t * & inout)445 inline int LWOImporter::ReadVSizedIntLWO2(uint8_t*& inout)
446 {
447     int i;
448     int c = *inout;inout++;
449     if(c != 0xFF)
450     {
451         i = c << 8;
452         c = *inout;inout++;
453         i |= c;
454     }
455     else
456     {
457         c = *inout;inout++;
458         i = c << 16;
459         c = *inout;inout++;
460         i |= c << 8;
461         c = *inout;inout++;
462         i |= c;
463     }
464     return i;
465 }
466 
467 // ------------------------------------------------------------------------------------------------
GetS0(std::string & out,unsigned int max)468 inline void LWOImporter::GetS0(std::string& out,unsigned int max)
469 {
470     unsigned int iCursor = 0;
471     const char*sz = (const char*)mFileBuffer;
472     while (*mFileBuffer)
473     {
474         if (++iCursor > max)
475         {
476             ASSIMP_LOG_WARN("LWO: Invalid file, string is is too long");
477             break;
478         }
479         ++mFileBuffer;
480     }
481     size_t len = (size_t) ((const char*)mFileBuffer-sz);
482     out = std::string(sz,len);
483     mFileBuffer += (len&0x1 ? 1 : 2);
484 }
485 
486 
487 
488 } // end of namespace Assimp
489 
490 #endif // AI_LWOIMPORTER_H_INCLUDED
491