MDLLoader.h 17 KB

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