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