vrshoot

view libs/assimp/MDLLoader.h @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
line source
1 /*
2 Open Asset Import Library (assimp)
3 ----------------------------------------------------------------------
5 Copyright (c) 2006-2012, assimp team
6 All rights reserved.
8 Redistribution and use of this software in source and binary forms,
9 with or without modification, are permitted provided that the
10 following conditions are met:
12 * Redistributions of source code must retain the above
13 copyright notice, this list of conditions and the
14 following disclaimer.
16 * Redistributions in binary form must reproduce the above
17 copyright notice, this list of conditions and the
18 following disclaimer in the documentation and/or other
19 materials provided with the distribution.
21 * Neither the name of the assimp team, nor the names of its
22 contributors may be used to endorse or promote products
23 derived from this software without specific prior
24 written permission of the assimp team.
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 ----------------------------------------------------------------------
39 */
42 /** @file MDLLoader.h
43 * @brief Declaration of the loader for MDL files
44 */
46 #ifndef AI_MDLLOADER_H_INCLUDED
47 #define AI_MDLLOADER_H_INCLUDED
49 #include "BaseImporter.h"
51 struct aiNode;
52 #include "MDLFileData.h"
53 #include "HalfLifeFileData.h"
55 namespace Assimp {
58 using namespace MDL;
60 // --------------------------------------------------------------------------------------
61 // Include file/line information in debug builds
62 #ifdef ASSIMP_BUILD_DEBUG
63 # define VALIDATE_FILE_SIZE(msg) SizeCheck(msg,__FILE__,__LINE__)
64 #else
65 # define VALIDATE_FILE_SIZE(msg) SizeCheck(msg)
66 #endif
68 // --------------------------------------------------------------------------------------
69 /** @brief Class to load MDL files.
70 *
71 * Several subformats exist:
72 * <ul>
73 * <li>Quake I</li>
74 * <li>3D Game Studio MDL3, MDL4</li>
75 * <li>3D Game Studio MDL5</li>
76 * <li>3D Game Studio MDL7</li>
77 * <li>Halflife 2</li>
78 * </ul>
79 * These formats are partially identical and it would be possible to load
80 * them all with a single 1000-line function-beast. However, it has been
81 * split into several code paths to make the code easier to read and maintain.
82 */
83 class MDLImporter : public BaseImporter
84 {
85 public:
86 MDLImporter();
87 ~MDLImporter();
90 public:
92 // -------------------------------------------------------------------
93 /** Returns whether the class can handle the format of the given file.
94 * See BaseImporter::CanRead() for details. */
95 bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
96 bool checkSig) const;
99 // -------------------------------------------------------------------
100 /** Called prior to ReadFile().
101 * The function is a request to the importer to update its configuration
102 * basing on the Importer's configuration property list.
103 */
104 void SetupProperties(const Importer* pImp);
106 protected:
109 // -------------------------------------------------------------------
110 /** Return importer meta information.
111 * See #BaseImporter::GetInfo for the details
112 */
113 const aiImporterDesc* GetInfo () const;
115 // -------------------------------------------------------------------
116 /** Imports the given file into the given scene structure.
117 * See BaseImporter::InternReadFile() for details
118 */
119 void InternReadFile( const std::string& pFile, aiScene* pScene,
120 IOSystem* pIOHandler);
122 protected:
124 // -------------------------------------------------------------------
125 /** Import a quake 1 MDL file (IDPO)
126 */
127 void InternReadFile_Quake1( );
129 // -------------------------------------------------------------------
130 /** Import a GameStudio A4/A5 file (MDL 3,4,5)
131 */
132 void InternReadFile_3DGS_MDL345( );
134 // -------------------------------------------------------------------
135 /** Import a GameStudio A7 file (MDL 7)
136 */
137 void InternReadFile_3DGS_MDL7( );
139 // -------------------------------------------------------------------
140 /** Import a CS:S/HL2 MDL file (not fully implemented)
141 */
142 void InternReadFile_HL2( );
144 // -------------------------------------------------------------------
145 /** Check whether a given position is inside the valid range
146 * Throw a DeadlyImportError if it is not
147 * \param szPos Cursor position
148 * \param szFile Name of the source file from which the function was called
149 * \param iLine Source code line from which the function was called
150 */
151 void SizeCheck(const void* szPos);
152 void SizeCheck(const void* szPos, const char* szFile, unsigned int iLine);
155 // -------------------------------------------------------------------
156 /** Validate the header data structure of a game studio MDL7 file
157 * \param pcHeader Input header to be validated
158 */
159 void ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7* pcHeader);
161 // -------------------------------------------------------------------
162 /** Validate the header data structure of a Quake 1 model
163 * \param pcHeader Input header to be validated
164 */
165 void ValidateHeader_Quake1(const MDL::Header* pcHeader);
168 // -------------------------------------------------------------------
169 /** Try to load a palette from the current directory (colormap.lmp)
170 * If it is not found the default palette of Quake1 is returned
171 */
172 void SearchPalette(const unsigned char** pszColorMap);
174 // -------------------------------------------------------------------
175 /** Free a palette created with a previous call to SearchPalette()
176 */
177 void FreePalette(const unsigned char* pszColorMap);
180 // -------------------------------------------------------------------
181 /** Load a paletized texture from the file and convert it to 32bpp
182 */
183 void CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData);
185 // -------------------------------------------------------------------
186 /** Used to load textures from MDL3/4
187 * \param szData Input data
188 * \param iType Color data type
189 * \param piSkip Receive: Size to skip, in bytes
190 */
191 void CreateTexture_3DGS_MDL4(const unsigned char* szData,
192 unsigned int iType,
193 unsigned int* piSkip);
196 // -------------------------------------------------------------------
197 /** Used to load textures from MDL5
198 * \param szData Input data
199 * \param iType Color data type
200 * \param piSkip Receive: Size to skip, in bytes
201 */
202 void CreateTexture_3DGS_MDL5(const unsigned char* szData,
203 unsigned int iType,
204 unsigned int* piSkip);
207 // -------------------------------------------------------------------
208 /** Checks whether a texture can be replaced with a single color
209 * This is useful for all file formats before MDL7 (all those
210 * that are not containing material colors separate from textures).
211 * MED seems to write dummy 8x8 monochrome images instead.
212 * \param pcTexture Input texture
213 * \return aiColor.r is set to qnan if the function fails and no
214 * color can be found.
215 */
216 aiColor4D ReplaceTextureWithColor(const aiTexture* pcTexture);
219 // -------------------------------------------------------------------
220 /** Converts the absolute texture coordinates in MDL5 files to
221 * relative in a range between 0 and 1
222 */
223 void CalculateUVCoordinates_MDL5();
226 // -------------------------------------------------------------------
227 /** Read an UV coordinate from the file. If the file format is not
228 * MDL5, the function calculates relative texture coordinates
229 * \param vOut Receives the output UV coord
230 * \param pcSrc UV coordinate buffer
231 * \param UV coordinate index
232 */
233 void ImportUVCoordinate_3DGS_MDL345( aiVector3D& vOut,
234 const MDL::TexCoord_MDL3* pcSrc,
235 unsigned int iIndex);
237 // -------------------------------------------------------------------
238 /** Setup the material properties for Quake and MDL<7 models.
239 * These formats don't support more than one material per mesh,
240 * therefore the method processes only ONE skin and removes
241 * all others.
242 */
243 void SetupMaterialProperties_3DGS_MDL5_Quake1( );
246 // -------------------------------------------------------------------
247 /** Parse a skin lump in a MDL7/HMP7 file with all of its features
248 * variant 1: Current cursor position is the beginning of the skin header
249 * \param szCurrent Current data pointer
250 * \param szCurrentOut Output data pointer
251 * \param pcMats Material list for this group. To be filled ...
252 */
253 void ParseSkinLump_3DGS_MDL7(
254 const unsigned char* szCurrent,
255 const unsigned char** szCurrentOut,
256 std::vector<aiMaterial*>& pcMats);
258 // -------------------------------------------------------------------
259 /** Parse a skin lump in a MDL7/HMP7 file with all of its features
260 * variant 2: Current cursor position is the beginning of the skin data
261 * \param szCurrent Current data pointer
262 * \param szCurrentOut Output data pointer
263 * \param pcMatOut Output material
264 * \param iType header.typ
265 * \param iWidth header.width
266 * \param iHeight header.height
267 */
268 void ParseSkinLump_3DGS_MDL7(
269 const unsigned char* szCurrent,
270 const unsigned char** szCurrentOut,
271 aiMaterial* pcMatOut,
272 unsigned int iType,
273 unsigned int iWidth,
274 unsigned int iHeight);
276 // -------------------------------------------------------------------
277 /** Skip a skin lump in a MDL7/HMP7 file
278 * \param szCurrent Current data pointer
279 * \param szCurrentOut Output data pointer. Points to the byte just
280 * behind the last byte of the skin.
281 * \param iType header.typ
282 * \param iWidth header.width
283 * \param iHeight header.height
284 */
285 void SkipSkinLump_3DGS_MDL7(const unsigned char* szCurrent,
286 const unsigned char** szCurrentOut,
287 unsigned int iType,
288 unsigned int iWidth,
289 unsigned int iHeight);
291 // -------------------------------------------------------------------
292 /** Parse texture color data for MDL5, MDL6 and MDL7 formats
293 * \param szData Current data pointer
294 * \param iType type of the texture data. No DDS or external
295 * \param piSkip Receive the number of bytes to skip
296 * \param pcNew Must point to fully initialized data. Width and
297 * height must be set. If pcNew->pcData is set to UINT_MAX,
298 * piSkip will receive the size of the texture, in bytes, but no
299 * color data will be read.
300 */
301 void ParseTextureColorData(const unsigned char* szData,
302 unsigned int iType,
303 unsigned int* piSkip,
304 aiTexture* pcNew);
306 // -------------------------------------------------------------------
307 /** Join two materials / skins. Setup UV source ... etc
308 * \param pcMat1 First input material
309 * \param pcMat2 Second input material
310 * \param pcMatOut Output material instance to be filled. Must be empty
311 */
312 void JoinSkins_3DGS_MDL7(aiMaterial* pcMat1,
313 aiMaterial* pcMat2,
314 aiMaterial* pcMatOut);
316 // -------------------------------------------------------------------
317 /** Add a bone transformation key to an animation
318 * \param iTrafo Index of the transformation (always==frame index?)
319 * No need to validate this index, it is always valid.
320 * \param pcBoneTransforms Bone transformation for this index
321 * \param apcOutBones Output bones array
322 */
323 void AddAnimationBoneTrafoKey_3DGS_MDL7(unsigned int iTrafo,
324 const MDL::BoneTransform_MDL7* pcBoneTransforms,
325 MDL::IntBone_MDL7** apcBonesOut);
327 // -------------------------------------------------------------------
328 /** Load the bone list of a MDL7 file
329 * \return If the bones could be loaded successfully, a valid
330 * array containing pointers to a temporary bone
331 * representation. NULL if the bones could not be loaded.
332 */
333 MDL::IntBone_MDL7** LoadBones_3DGS_MDL7();
335 // -------------------------------------------------------------------
336 /** Load bone transformation keyframes from a file chunk
337 * \param groupInfo -> doc of data structure
338 * \param frame -> doc of data structure
339 * \param shared -> doc of data structure
340 */
341 void ParseBoneTrafoKeys_3DGS_MDL7(
342 const MDL::IntGroupInfo_MDL7& groupInfo,
343 IntFrameInfo_MDL7& frame,
344 MDL::IntSharedData_MDL7& shared);
346 // -------------------------------------------------------------------
347 /** Calculate absolute bone animation matrices for each bone
348 * \param apcOutBones Output bones array
349 */
350 void CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7** apcOutBones);
352 // -------------------------------------------------------------------
353 /** Add all bones to the nodegraph (as children of the root node)
354 * \param apcBonesOut List of bones
355 * \param pcParent Parent node. New nodes will be added to this node
356 * \param iParentIndex Index of the parent bone
357 */
358 void AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7** apcBonesOut,
359 aiNode* pcParent,uint16_t iParentIndex);
361 // -------------------------------------------------------------------
362 /** Build output animations
363 * \param apcBonesOut List of bones
364 */
365 void BuildOutputAnims_3DGS_MDL7(const MDL::IntBone_MDL7** apcBonesOut);
367 // -------------------------------------------------------------------
368 /** Handles materials that are just referencing another material
369 * There is no test file for this feature, but Conitec's doc
370 * say it is used.
371 */
372 void HandleMaterialReferences_3DGS_MDL7();
374 // -------------------------------------------------------------------
375 /** Copies only the material that are referenced by at least one
376 * mesh to the final output material list. All other materials
377 * will be discarded.
378 * \param shared -> doc of data structure
379 */
380 void CopyMaterials_3DGS_MDL7(MDL::IntSharedData_MDL7 &shared);
382 // -------------------------------------------------------------------
383 /** Process the frame section at the end of a group
384 * \param groupInfo -> doc of data structure
385 * \param shared -> doc of data structure
386 * \param szCurrent Pointer to the start of the frame section
387 * \param szCurrentOut Receives a pointer to the first byte of the
388 * next data section.
389 * \return false to read no further groups (a small workaround for
390 * some tiny and unsolved problems ... )
391 */
392 bool ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
393 MDL::IntGroupData_MDL7& groupData,
394 MDL::IntSharedData_MDL7& shared,
395 const unsigned char* szCurrent,
396 const unsigned char** szCurrentOut);
398 // -------------------------------------------------------------------
399 /** Sort all faces by their materials. If the mesh is using
400 * multiple materials per face (that are blended together) the function
401 * might create new materials.
402 * \param groupInfo -> doc of data structure
403 * \param groupData -> doc of data structure
404 * \param splitGroupData -> doc of data structure
405 */
406 void SortByMaterials_3DGS_MDL7(
407 const MDL::IntGroupInfo_MDL7& groupInfo,
408 MDL::IntGroupData_MDL7& groupData,
409 MDL::IntSplitGroupData_MDL7& splitGroupData);
411 // -------------------------------------------------------------------
412 /** Read all faces and vertices from a MDL7 group. The function fills
413 * preallocated memory buffers.
414 * \param groupInfo -> doc of data structure
415 * \param groupData -> doc of data structure
416 */
417 void ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
418 MDL::IntGroupData_MDL7& groupData);
420 // -------------------------------------------------------------------
421 /** Generate the final output meshes for a7 models
422 * \param groupData -> doc of data structure
423 * \param splitGroupData -> doc of data structure
424 */
425 void GenerateOutputMeshes_3DGS_MDL7(
426 MDL::IntGroupData_MDL7& groupData,
427 MDL::IntSplitGroupData_MDL7& splitGroupData);
429 protected:
431 /** Configuration option: frame to be loaded */
432 unsigned int configFrameID;
434 /** Configuration option: palette to be used to decode palletized images*/
435 std::string configPalette;
437 /** Buffer to hold the loaded file */
438 unsigned char* mBuffer;
440 /** For GameStudio MDL files: The number in the magic word, either 3,4 or 5
441 * (MDL7 doesn't need this, the format has a separate loader) */
442 unsigned int iGSFileVersion;
444 /** Output I/O handler. used to load external lmp files */
445 IOSystem* pIOHandler;
447 /** Output scene to be filled */
448 aiScene* pScene;
450 /** Size of the input file in bytes */
451 unsigned int iFileSize;
452 };
454 } // end of namespace Assimp
456 #endif // AI_3DSIMPORTER_H_INC