Formatx.MD2.pas 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. //
  2. // The graphics platform GLXcene https://github.com/glscene
  3. //
  4. unit Formatx.MD2;
  5. (* MD2 file loader *)
  6. interface
  7. {$R-}
  8. {$I Scene.inc}
  9. uses
  10. System.Classes,
  11. System.SysUtils,
  12. GLX.VectorGeometry,
  13. GLX.VectorTypes;
  14. const
  15. MAX_MD2_TRIANGLES = 4096;
  16. MAX_MD2_VERTICES = 2048;
  17. MAX_MD2_FRAMES = 512;
  18. MAX_MD2_SKINS = 32;
  19. MAX_MD2_SKINNAME = 64;
  20. type
  21. PMD2VertexIndex = ^TMD2VertexIndex;
  22. TMD2VertexIndex = record
  23. A, B, C: integer;
  24. A_S, A_T,
  25. B_S, B_T,
  26. C_S, C_T: single;
  27. end;
  28. TMD2Triangle = record
  29. VertexIndex: TVector3s;
  30. TextureCoordIndex: TVector3s;
  31. end;
  32. TMD2TriangleVertex = record
  33. Vert: array[0..2] of byte;
  34. LightnormalIndex: byte;
  35. end;
  36. PMD2AliasFrame = ^TMD2AliasFrame;
  37. TMD2AliasFrame = record
  38. Scale: TVector3f;
  39. Translate: TVector3f;
  40. Name: array[0..15] of AnsiChar;
  41. Vertices: array[0..0] of TMD2TriangleVertex;
  42. end;
  43. TMD2Header = record
  44. Ident: integer;
  45. Version: integer;
  46. SkinWidth: integer;
  47. SkinHeight: integer;
  48. FrameSize: integer;
  49. Num_Skins: integer;
  50. Num_Vertices: integer;
  51. Num_TextureCoords: integer;
  52. Num_VertexIndices: integer;
  53. Num_GLCommdands: integer;
  54. Num_Frames: integer;
  55. Offset_skins: integer;
  56. Offset_st: integer;
  57. Offset_tris: integer;
  58. Offset_frames: integer;
  59. Offset_glcmds: integer;
  60. Offset_end: integer;
  61. end;
  62. TIndexList = array of TMD2VertexIndex;
  63. TgxVertexList = array of array of TVector3f;
  64. type
  65. TFileMD2 = class
  66. private
  67. FiFrames: longint;
  68. FiVertices: longint;
  69. FiTriangles: longint;
  70. procedure FreeLists;
  71. public
  72. fIndexList : TIndexList;
  73. fVertexList : TgxVertexList;
  74. FrameNames : TStrings;
  75. constructor Create; virtual;
  76. destructor Destroy; override;
  77. procedure LoadFromStream(aStream : TStream);
  78. property iFrames: longInt read FiFrames;
  79. property iVertices: longInt read FiVertices;
  80. property iTriangles: longInt read FiTriangles;
  81. property IndexList: TIndexList read fIndexList;
  82. property VertexList: TgxVertexList read fVertexList;
  83. end;
  84. // ------------------------------------------------------------------
  85. implementation
  86. // ------------------------------------------------------------------
  87. // ------------------
  88. // ------------------ TFileMD2 ------------------
  89. // ------------------
  90. constructor TFileMD2.Create;
  91. begin
  92. inherited;
  93. FreeLists;
  94. FrameNames := TStringList.Create;
  95. end;
  96. destructor TFileMD2.Destroy;
  97. begin
  98. FreeLists;
  99. FrameNames.Free;
  100. inherited;
  101. end;
  102. procedure TFileMD2.FreeLists;
  103. begin
  104. SetLength(fIndexList,0);
  105. SetLength(fVertexList,0,0);
  106. FiFrames := 0;
  107. FiVertices := 0;
  108. FiTriangles := 0;
  109. end;
  110. procedure TFileMD2.LoadFromStream(aStream : TStream);
  111. var
  112. Skins: array[0..MAX_MD2_SKINS - 1, 0..63] of AnsiChar;
  113. TextureCoords: array[0..MAX_MD2_VERTICES - 1] of TVector2s;
  114. Buffer: array[0..MAX_MD2_VERTICES * 4 + 127] of byte;
  115. Header: TMD2Header;
  116. Triangle: TMD2Triangle;
  117. I: integer;
  118. J: integer;
  119. Frame: PMD2AliasFrame;
  120. FrameName : String;
  121. begin
  122. FreeLists;
  123. // read the modelinfo
  124. aStream.Read(Header, SizeOf(Header));
  125. FiFrames := Header.Num_Frames;
  126. FiVertices := Header.Num_Vertices;
  127. FiTriangles := Header.Num_VertexIndices;
  128. SetLength(fIndexList, FiTriangles);
  129. SetLength(fVertexList, FiFrames, FiVertices);
  130. // get the skins...
  131. aStream.Read(Skins, Header.Num_Skins * MAX_MD2_SKINNAME);
  132. // ...and the texcoords
  133. aStream.Read(TextureCoords, Header.Num_TextureCoords * SizeOf(TVector2s));
  134. for I := 0 to Header.Num_VertexIndices - 1 do begin
  135. aStream.Read(Triangle, SizeOf(TMD2Triangle));
  136. with fIndexList[I] do begin
  137. A := Triangle.VertexIndex.Z;
  138. B := Triangle.VertexIndex.Y;
  139. C := Triangle.VertexIndex.X;
  140. A_S := TextureCoords[Triangle.TextureCoordIndex.Z].X / Header.SkinWidth;
  141. A_T := TextureCoords[Triangle.TextureCoordIndex.Z].Y / Header.SkinHeight;
  142. B_S := TextureCoords[Triangle.TextureCoordIndex.Y].X / Header.SkinWidth;
  143. B_T := TextureCoords[Triangle.TextureCoordIndex.Y].Y / Header.SkinHeight;
  144. C_S := TextureCoords[Triangle.TextureCoordIndex.X].X / Header.SkinWidth;
  145. C_T := TextureCoords[Triangle.TextureCoordIndex.X].Y / Header.SkinHeight;
  146. end;
  147. end;
  148. for I := 0 to Header.Num_Frames - 1 do begin
  149. Frame := PMD2AliasFrame(@Buffer);
  150. // read animation / frame info
  151. aStream.Read(Frame^, Header.FrameSize);
  152. FrameName := Trim(String(Frame^.Name));
  153. if CharInSet(Copy(FrameName, Length(FrameName) - 1, 1)[1], ['0'..'9']) then
  154. FrameName := Copy(FrameName, 1, Length(FrameName) - 2)
  155. else
  156. FrameName := Copy(FrameName, 1, Length(FrameName) - 1);
  157. if FrameNames.IndexOf(FrameName) < 0 then
  158. FrameNames.AddObject(FrameName, TObject(Cardinal(I)));
  159. // fill the vertices list
  160. for J := 0 to FiVertices - 1 do begin
  161. fVertexList[i][J].X := Frame^.Vertices[J].Vert[0] * Frame^.Scale.X + Frame^.Translate.X;
  162. fVertexList[i][J].Y := Frame^.Vertices[J].Vert[1] * Frame^.Scale.Y + Frame^.Translate.Y;
  163. fVertexList[i][J].Z := Frame^.Vertices[J].Vert[2] * Frame^.Scale.Z + Frame^.Translate.Z;
  164. end;
  165. end;
  166. end;
  167. end.