GXS.HeightTileFileHDS.pas 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. //
  2. // The graphics engine GXScene https://github.com/glscene
  3. //
  4. unit GXS.HeightTileFileHDS;
  5. (* HeightDataSource for the HTF (HeightTileFile) format *)
  6. interface
  7. {$I Stage.Defines.inc}
  8. uses
  9. System.Classes,
  10. System.SysUtils,
  11. GXS.HeightData,
  12. GXS.HeightTileFile;
  13. type
  14. // An Height Data Source for the HTF format.
  15. TgxHeightTileFileHDS = class(TgxHeightDataSource)
  16. private
  17. FInfiniteWrap: Boolean;
  18. FInverted: Boolean;
  19. FHTFFileName: String;
  20. FHTF: TgxHeightTileFile;
  21. FMinElevation: Integer;
  22. protected
  23. procedure SetHTFFileName(const val: String);
  24. procedure SetInfiniteWrap(val: Boolean);
  25. procedure SetInverted(val: Boolean);
  26. procedure SetMinElevation(val: Integer);
  27. public
  28. constructor Create(AOwner: TComponent); override;
  29. destructor Destroy; override;
  30. procedure StartPreparingData(HeightData: TgxHeightData); override;
  31. function Width: Integer; override;
  32. function Height: Integer; override;
  33. function OpenHTF: TgxHeightTileFile;
  34. // gives you direct access to the HTF object
  35. published
  36. { FileName of the HTF file.
  37. Note that it is accessed via the services of GXS.ApplicationFileIO,
  38. so this may not necessarily be a regular file on a disk... }
  39. property HTFFileName: String read FHTFFileName write SetHTFFileName;
  40. { If true the height field is wrapped indefinetely. }
  41. property InfiniteWrap: Boolean read FInfiniteWrap write SetInfiniteWrap
  42. default True;
  43. { If true the height data is inverted.(Top to bottom) }
  44. property Inverted: Boolean read FInverted write SetInverted default True;
  45. { Minimum elevation of the tiles that are considered to exist.
  46. This property can typically be used to hide underwater tiles. }
  47. property MinElevation: Integer read FMinElevation write SetMinElevation
  48. default -32768;
  49. property MaxPoolSize;
  50. property DefaultHeight;
  51. end;
  52. // ------------------------------------------------------------------
  53. implementation
  54. // ------------------------------------------------------------------
  55. // ------------------
  56. // ------------------ TgxHeightTileFileHDS ------------------
  57. // ------------------
  58. constructor TgxHeightTileFileHDS.Create(AOwner: TComponent);
  59. begin
  60. inherited Create(AOwner);
  61. FInfiniteWrap := True;
  62. FInverted := True;
  63. FMinElevation := -32768;
  64. end;
  65. destructor TgxHeightTileFileHDS.Destroy;
  66. begin
  67. FHTF.Free;
  68. inherited Destroy;
  69. end;
  70. procedure TgxHeightTileFileHDS.SetHTFFileName(const val: String);
  71. begin
  72. if FHTFFileName <> val then
  73. begin
  74. MarkDirty;
  75. FreeAndNil(FHTF);
  76. FHTFFileName := val;
  77. end;
  78. end;
  79. procedure TgxHeightTileFileHDS.SetInfiniteWrap(val: Boolean);
  80. begin
  81. if FInfiniteWrap = val then
  82. exit;
  83. FInfiniteWrap := val;
  84. MarkDirty;
  85. end;
  86. procedure TgxHeightTileFileHDS.SetInverted(val: Boolean);
  87. begin
  88. if FInverted = val then
  89. exit;
  90. FInverted := val;
  91. MarkDirty;
  92. end;
  93. procedure TgxHeightTileFileHDS.SetMinElevation(val: Integer);
  94. begin
  95. if FMinElevation <> val then
  96. begin
  97. FMinElevation := val;
  98. MarkDirty;
  99. end;
  100. end;
  101. // OpenHTF
  102. // Tries to open the assigned HeightTileFile.
  103. //
  104. function TgxHeightTileFileHDS.OpenHTF: TgxHeightTileFile;
  105. begin
  106. if not Assigned(FHTF) then
  107. begin
  108. if FHTFFileName = '' then
  109. FHTF := nil
  110. else
  111. FHTF := TgxHeightTileFile.Create(FHTFFileName);
  112. end;
  113. result := FHTF;
  114. end;
  115. procedure TgxHeightTileFileHDS.StartPreparingData(HeightData: TgxHeightData);
  116. var
  117. oldType: TgxHeightDataType;
  118. htfTile: PHeightTile;
  119. htfTileInfo: PgxHeightTileInfo;
  120. x, y: Integer;
  121. YPos: Integer;
  122. inY, outY: Integer;
  123. PLineIn, PLineOut: ^PSmallIntArray;
  124. LineDataSize: Integer;
  125. begin
  126. // access htf data
  127. if OpenHTF = nil then
  128. begin
  129. HeightData.DataState := hdsNone;
  130. exit;
  131. end
  132. else
  133. Assert(FHTF.TileSize = HeightData.Size,
  134. 'HTF TileSize and HeightData size don''t match.(' +
  135. IntToStr(FHTF.TileSize) + ' and ' + IntToStr(HeightData.Size) + ')');
  136. HeightData.DataState := hdsPreparing;
  137. // retrieve data and place it in the HeightData
  138. with HeightData do
  139. begin
  140. if Inverted then
  141. YPos := YTop
  142. else
  143. YPos := FHTF.SizeY - YTop - Size + 1;
  144. if InfiniteWrap then
  145. begin
  146. x := XLeft mod FHTF.SizeX;
  147. if x < 0 then
  148. x := x + FHTF.SizeX;
  149. y := YPos mod FHTF.SizeY;
  150. if y < 0 then
  151. y := y + FHTF.SizeY;
  152. htfTile := FHTF.GetTile(x, y, @htfTileInfo);
  153. end
  154. else
  155. begin
  156. htfTile := FHTF.GetTile(XLeft, YPos, @htfTileInfo);
  157. end;
  158. if (htfTile = nil) or (htfTileInfo.max <= FMinElevation) then
  159. begin
  160. // non-aligned tiles aren't handled (would be slow anyway)
  161. DataState := hdsNone;
  162. end
  163. else
  164. begin
  165. oldType := DataType;
  166. Allocate(hdtSmallInt);
  167. if Inverted then
  168. Move(htfTile.data[0], SmallIntData^, DataSize)
  169. else
  170. begin // invert the terrain (top to bottom) To compensate for the inverted terrain renderer
  171. LineDataSize := DataSize div Size;
  172. for y := 0 to Size - 1 do
  173. begin
  174. inY := y * HeightData.Size;
  175. outY := ((Size - 1) - y) * HeightData.Size;
  176. PLineIn := @htfTile.data[inY];
  177. PLineOut := @HeightData.SmallIntData[outY];
  178. Move(PLineIn^, PLineOut^, LineDataSize);
  179. end;
  180. end;
  181. // ---Move(htfTile.data[0], SmallIntData^, DataSize);---
  182. if oldType <> hdtSmallInt then
  183. DataType := oldType;
  184. TextureCoordinates(HeightData);
  185. inherited;
  186. HeightMin := htfTileInfo.min;
  187. HeightMax := htfTileInfo.max;
  188. end;
  189. end;
  190. end;
  191. function TgxHeightTileFileHDS.Width: Integer;
  192. begin
  193. if OpenHTF = nil then
  194. result := 0
  195. else
  196. result := FHTF.SizeX;
  197. end;
  198. function TgxHeightTileFileHDS.Height: Integer;
  199. begin
  200. if OpenHTF = nil then
  201. result := 0
  202. else
  203. result := FHTF.SizeY;
  204. end;
  205. // ------------------------------------------------------------------
  206. initialization
  207. // ------------------------------------------------------------------
  208. RegisterClasses([TgxHeightTileFileHDS]);
  209. end.