Formats.OCT.pas 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. //
  2. // The graphics engine GLScene https://github.com/glscene
  3. //
  4. unit Formats.OCT;
  5. (* Loader for FSRad OCT files *)
  6. interface
  7. {$I GLScene.Defines.inc}
  8. uses
  9. System.Classes,
  10. System.SysUtils,
  11. GLScene.VectorGeometry,
  12. GLScene.VectorTypes,
  13. GLS.VectorLists;
  14. type
  15. TOCTHeader = record
  16. numVerts: Integer;
  17. numFaces: Integer;
  18. numTextures: Integer;
  19. numLightmaps: Integer;
  20. numLights: Integer;
  21. end;
  22. TOCTVertex = record
  23. tv: TTexPoint; // texture coordinates
  24. lv: TTexPoint; // lightmap coordinates
  25. pos: TAffineVector; // vertex position
  26. end;
  27. TOCTFace = record
  28. start: Integer; // first face vert in vertex array
  29. num: Integer; // number of verts in the face
  30. id: Integer; // texture index into the texture array
  31. lid: Integer; // lightmap index into the lightmap array
  32. p: THmgPlane;
  33. end;
  34. POCTFace = ^TOCTFace;
  35. TOCTTexture = record
  36. id: Integer; // texture id
  37. Name: array [0 .. 63] of AnsiChar; // texture name
  38. end;
  39. TOCTLightmap = record
  40. id: Integer; // lightmaps id
  41. map: array [0 .. 49151] of Byte; // 128 x 128 raw RGB data
  42. end;
  43. POCTLightmap = ^TOCTLightmap;
  44. TOCTLight = record
  45. pos: TAffineVector; // Position
  46. color: TAffineVector; // Color (RGB)
  47. intensity: Integer; // Intensity
  48. end;
  49. TOCTFile = class(TObject)
  50. public
  51. Header: TOCTHeader;
  52. Vertices: array of TOCTVertex;
  53. Faces: array of TOCTFace;
  54. Textures: array of TOCTTexture;
  55. Lightmaps: array of TOCTLightmap;
  56. Lights: array of TOCTLight;
  57. PlayerPos: TAffineVector;
  58. constructor Create; overload;
  59. constructor Create(octStream: TStream); overload;
  60. (* Saves content to stream in OCT format.
  61. The Header is automatically prepared before streaming. *)
  62. procedure SaveToStream(aStream: TStream);
  63. procedure AddTriangles(vertexCoords: TGLAffineVectorList;
  64. texMapCoords: TGLAffineVectorList; const textureName: String);
  65. procedure AddLight(const lightPos: TAffineVector; const lightColor: TGLVector;
  66. lightIntensity: Integer);
  67. end;
  68. // ------------------------------------------------------------------
  69. implementation
  70. // ------------------------------------------------------------------
  71. uses
  72. GLS.MeshUtils;
  73. // ------------------
  74. // ------------------ TOCTFile ------------------
  75. // ------------------
  76. constructor TOCTFile.Create;
  77. begin
  78. inherited Create;
  79. end;
  80. constructor TOCTFile.Create(octStream: TStream);
  81. begin
  82. inherited Create;
  83. // Read in the header
  84. octStream.Read(Header, SizeOf(Header));
  85. // then the rest of the stuff
  86. SetLength(Vertices, Header.numVerts);
  87. octStream.Read(Vertices[0], Header.numVerts * SizeOf(TOCTVertex));
  88. SetLength(Faces, Header.numFaces);
  89. octStream.Read(Faces[0], Header.numFaces * SizeOf(TOCTFace));
  90. SetLength(Textures, Header.numTextures);
  91. octStream.Read(Textures[0], Header.numTextures * SizeOf(TOCTTexture));
  92. SetLength(Lightmaps, Header.numLightmaps);
  93. octStream.Read(Lightmaps[0], Header.numLightmaps * SizeOf(TOCTLightmap));
  94. SetLength(Lights, Header.numLights);
  95. octStream.Read(Lights[0], Header.numLights * SizeOf(TOCTLight));
  96. octStream.Read(PlayerPos, SizeOf(PlayerPos))
  97. end;
  98. procedure TOCTFile.SaveToStream(aStream: TStream);
  99. begin
  100. with Header, aStream do
  101. begin
  102. numVerts := Length(Vertices);
  103. numFaces := Length(Faces);
  104. numTextures := Length(Textures);
  105. numLightmaps := Length(Lightmaps);
  106. numLights := Length(Lights);
  107. Write(Header, SizeOf(Header));
  108. Write(Vertices[0], numVerts * SizeOf(TOCTVertex));
  109. Write(Faces[0], numFaces * SizeOf(TOCTFace));
  110. Write(Textures[0], numTextures * SizeOf(TOCTTexture));
  111. Write(Lightmaps[0], numLightmaps * SizeOf(TOCTLightmap));
  112. Write(Lights[0], numLights * SizeOf(TOCTLight));
  113. Write(PlayerPos, SizeOf(PlayerPos))
  114. end;
  115. end;
  116. procedure TOCTFile.AddTriangles(vertexCoords: TGLAffineVectorList;
  117. texMapCoords: TGLAffineVectorList; const textureName: String);
  118. var
  119. i: Integer;
  120. baseIdx, texIdx: Integer;
  121. begin
  122. Assert((texMapCoords = nil) or (texMapCoords.Count = vertexCoords.Count));
  123. texIdx := Length(Textures);
  124. SetLength(Textures, texIdx + 1);
  125. Move(textureName[1], Textures[texIdx].Name[0], Length(textureName));
  126. SetLength(Lightmaps, 1);
  127. FillChar(Lightmaps[0].map[0], 128 * 3, 255);
  128. baseIdx := Length(Vertices);
  129. SetLength(Vertices, baseIdx + vertexCoords.Count);
  130. for i := 0 to vertexCoords.Count - 1 do
  131. with Vertices[baseIdx + i] do
  132. begin
  133. pos := vertexCoords.List[i];
  134. if Assigned(texMapCoords) then
  135. tv := PTexPoint(@texMapCoords.List[i])^;
  136. end;
  137. SetLength(Faces, vertexCoords.Count div 3);
  138. i := 0;
  139. while i < vertexCoords.Count do
  140. begin
  141. with Faces[i div 3] do
  142. begin
  143. start := baseIdx + i;
  144. num := 3;
  145. id := texIdx;
  146. p := PlaneMake(vertexCoords[i], CalcPlaneNormal(vertexCoords[i + 0],
  147. vertexCoords[i + 1], vertexCoords[i + 0]));
  148. end;
  149. Inc(i, 3);
  150. end;
  151. end;
  152. procedure TOCTFile.AddLight(const lightPos: TAffineVector;
  153. const lightColor: TGLVector; lightIntensity: Integer);
  154. var
  155. n: Integer;
  156. begin
  157. n := Length(Lights);
  158. SetLength(Lights, n + 1);
  159. with Lights[n] do
  160. begin
  161. pos := lightPos;
  162. color := PAffineVector(@lightColor)^;
  163. intensity := lightIntensity;
  164. end;
  165. end;
  166. end.