Formatx.OCT.pas 5.1 KB

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