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