Formatx.MD3.pas 4.1 KB

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