Formatx.MD3.pas 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. //
  2. // The graphics engine GXScene https://github.com/glscene
  3. //
  4. unit Formatx.MD3;
  5. (* FileMD3 - File loading methods for the MD3 file format *)
  6. interface
  7. uses
  8. System.Classes,
  9. GLScene.VectorTypes;
  10. type
  11. // Quake3 MD3 structure types
  12. TMD3Tag = record
  13. strName: array [0 .. 63] of AnsiChar;
  14. vPosition: TVector3f;
  15. rotation: TMatrix3f;
  16. end;
  17. // This part of the MD3 structure calls 2 things:
  18. // A frame and a bone. It doesn't matter because we don't use it
  19. (* TMD3Frame = record
  20. min_bound,max_bounds,
  21. local_origin : TVector3f;
  22. radius : single;
  23. name : array[0..15] of char;
  24. end; *)
  25. TMD3Bone = record
  26. mins, maxs, position: TVector3f;
  27. scale: single;
  28. creator: array [0 .. 15] of AnsiChar;
  29. end;
  30. TMD3Triangle = record
  31. vertex: TVector3s; // value/64 to get real number position
  32. normal: TVector2b; // Latitude, Longitude
  33. end;
  34. TMD3Face = record
  35. vertexIndices: TVector3i;
  36. end;
  37. TMD3TexCoord = record
  38. textureCoord: TVector2f;
  39. end;
  40. TMD3Skin = record
  41. strName: array [0 .. 63] of AnsiChar;
  42. shaderIndex: Integer;
  43. end;
  44. TMD3Header = record
  45. fileID: array [0 .. 3] of AnsiChar;
  46. version: Integer;
  47. strFile: array [0 .. 63] of AnsiChar;
  48. flags, numFrames, numTags, numMeshes, numMaxSkins, headerSize, tagStart,
  49. tagEnd, fileSize: Integer;
  50. end;
  51. TMD3MeshHeader = record
  52. meshID: array [0 .. 3] of AnsiChar;
  53. strName: array [0 .. 63] of AnsiChar;
  54. flags, numMeshFrames, numSkins, numVertices, numTriangles, triStart,
  55. headerSize, uvStart, vertexStart, meshSize: Integer;
  56. end;
  57. TMD3MeshData = record
  58. MeshHeader: TMD3MeshHeader;
  59. Skins: array of TMD3Skin;
  60. Triangles: array of TMD3Face;
  61. TexCoords: array of TMD3TexCoord;
  62. Vertices: array of TMD3Triangle;
  63. end;
  64. TFileMD3 = class
  65. public
  66. ModelHeader: TMD3Header;
  67. Bones: array of TMD3Bone;
  68. Tags: array of TMD3Tag;
  69. MeshData: array of TMD3MeshData;
  70. procedure LoadFromStream(aStream: TStream);
  71. end;
  72. // ===================================================================
  73. implementation
  74. // ===================================================================
  75. // ------------------
  76. // ------------------ TFileMD3 ------------------
  77. // ------------------
  78. procedure TFileMD3.LoadFromStream(aStream: TStream);
  79. var
  80. i: Integer;
  81. meshOffset: LongInt;
  82. begin
  83. aStream.Read(ModelHeader, sizeof(ModelHeader));
  84. // Test for correct file ID and version
  85. Assert(ModelHeader.fileID = 'IDP3', 'Incorrect MD3 file ID');
  86. Assert(ModelHeader.version = 15, 'Incorrect MD3 version number');
  87. // Read in the bones
  88. SetLength(Bones, ModelHeader.numFrames);
  89. aStream.Read(Bones[0], sizeof(TMD3Bone) * ModelHeader.numFrames);
  90. // Read in the Tags
  91. SetLength(Tags, ModelHeader.numFrames * ModelHeader.numTags);
  92. if ModelHeader.numTags > 0 then
  93. aStream.Read(Tags[0], sizeof(TMD3Tag) * ModelHeader.numFrames *
  94. ModelHeader.numTags);
  95. // Read in the Mesh data
  96. meshOffset := aStream.position;
  97. SetLength(MeshData, ModelHeader.numMeshes);
  98. for i := 0 to ModelHeader.numMeshes - 1 do
  99. begin
  100. with MeshData[i] do
  101. begin
  102. aStream.position := meshOffset;
  103. aStream.Read(MeshHeader, sizeof(MeshHeader));
  104. // Set up the dynamic arrays
  105. SetLength(Skins, MeshHeader.numSkins);
  106. SetLength(Triangles, MeshHeader.numTriangles);
  107. SetLength(TexCoords, MeshHeader.numVertices);
  108. SetLength(Vertices, MeshHeader.numVertices * MeshHeader.numMeshFrames);
  109. // Skins
  110. aStream.Read(Skins[0], sizeof(TMD3Skin) * MeshHeader.numSkins);
  111. // Face data
  112. aStream.position := meshOffset + MeshHeader.triStart;
  113. aStream.Read(Triangles[0], sizeof(TMD3Face) * MeshHeader.numTriangles);
  114. // Texture coordinates
  115. aStream.position := meshOffset + MeshHeader.uvStart;
  116. aStream.Read(TexCoords[0], sizeof(TMD3TexCoord) * MeshHeader.numVertices);
  117. // Vertices
  118. aStream.position := meshOffset + MeshHeader.vertexStart;
  119. aStream.Read(Vertices[0], sizeof(TMD3Triangle) * MeshHeader.numMeshFrames
  120. * MeshHeader.numVertices);
  121. // Increase the offset
  122. meshOffset := meshOffset + MeshHeader.meshSize;
  123. end;
  124. end;
  125. end;
  126. end.