GXS.TexturedHDS.pas 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. //
  2. // The graphics engine GLXEngine. The unit of GXScene for Delphi
  3. //
  4. unit GXS.TexturedHDS;
  5. (*
  6. Implements a HDS, which automatically maps textures onto a parent HDS .
  7. This HDS links to and extracts its height data from a parent HDS. (like TgxHeightTileFile)
  8. The HDS also links to a TgxMaterial Library, and maps ALL textures from the
  9. selected Material Library onto the terrain, WITHOUT using Multitexturing.
  10. The position and scale of each texture is determined by the material's own
  11. TextureOffset and TextureScale properties.
  12. This makes it easy to tile many textures onto a single, continuous TgxTerrainRenderer.
  13. If two or more textures in the library overlap, the top texture is used.( ie.the later one in the list)
  14. WARNING: Only one base texture is mapped onto each terrain tile, so, make
  15. sure your texture edges are alligned to height tile edges, or gaps will show.
  16. (Of course you can still multitexture in a detail texture too.)
  17. *)
  18. interface
  19. {$I Stage.Defines.inc}
  20. uses
  21. System.Types,
  22. System.Classes,
  23. Stage.VectorTypes,
  24. GXS.Coordinates,
  25. GXS.HeightData,
  26. GXS.Material;
  27. type
  28. TgxTexturedHDS = class(TgxHeightDataSource)
  29. private
  30. FOnStartPreparingData: TStartPreparingDataEvent;
  31. FOnMarkDirty: TMarkDirtyEvent;
  32. FHeightDataSource: TgxHeightDataSource;
  33. FMaterialLibrary: TgxMaterialLibrary;
  34. FWholeTilesOnly: Boolean;
  35. FTileSize: integer;
  36. FTilesPerTexture: integer;
  37. protected
  38. procedure SetHeightDataSource(val: TgxHeightDataSource);
  39. public
  40. constructor Create(AOwner: TComponent); override;
  41. destructor Destroy; override;
  42. procedure StartPreparingData(HeightData: TgxHeightData); override;
  43. procedure MarkDirty(const area: TRect); override;
  44. published
  45. property MaxPoolSize;
  46. property OnStartPreparingData: TStartPreparingDataEvent
  47. read FOnStartPreparingData write FOnStartPreparingData;
  48. property OnMarkDirtyEvent: TMarkDirtyEvent read FOnMarkDirty
  49. write FOnMarkDirty;
  50. property HeightDataSource: TgxHeightDataSource read FHeightDataSource
  51. write SetHeightDataSource;
  52. property MaterialLibrary: TgxMaterialLibrary read FMaterialLibrary
  53. write FMaterialLibrary;
  54. property WholeTilesOnly: Boolean read FWholeTilesOnly write FWholeTilesOnly;
  55. { This should match TileSize in TgxTerrainRenderer }
  56. property TileSize: integer read FTileSize write FTileSize;
  57. { This should match TilesPerTexture in TgxTerrainRenderer }
  58. property TilesPerTexture: integer read FTilesPerTexture
  59. write FTilesPerTexture;
  60. end;
  61. //------------------------------------------------------
  62. implementation
  63. //------------------------------------------------------
  64. // ------------------
  65. // ------------------ TgxTexturedHDS ------------------
  66. // ------------------
  67. constructor TgxTexturedHDS.Create(AOwner: TComponent);
  68. begin
  69. FHeightDataSource := nil;
  70. FMaterialLibrary := nil;
  71. FTileSize := 16;
  72. FTilesPerTexture := 1;
  73. inherited Create(AOwner);
  74. end;
  75. destructor TgxTexturedHDS.Destroy;
  76. begin
  77. inherited Destroy;
  78. end;
  79. procedure TgxTexturedHDS.MarkDirty(const area: TRect);
  80. begin
  81. inherited;
  82. if Assigned(FOnMarkDirty) then
  83. FOnMarkDirty(area);
  84. end;
  85. procedure TgxTexturedHDS.StartPreparingData(HeightData: TgxHeightData);
  86. var
  87. HDS: TgxHeightDataSource;
  88. htfHD: TgxHeightData;
  89. MatLib: TgxMaterialLibrary;
  90. Mat: TgxLibMaterial;
  91. HD: TgxHeightData;
  92. MatInx: integer;
  93. tileL, tileR, tileT, tileB: single;
  94. found: Boolean;
  95. texL, texR, texT, texB, swp: single;
  96. texSize: integer;
  97. begin
  98. if not Assigned(FHeightDataSource) then
  99. begin
  100. HeightData.DataState := hdsNone;
  101. exit;
  102. end;
  103. // ---Height Data--
  104. HD := HeightData;
  105. HD.DataType := hdtSmallInt;
  106. HD.Allocate(hdtSmallInt);
  107. HDS := self.FHeightDataSource;
  108. // HD.FTextureCoordinatesMode:=tcmWorld;
  109. htfHD := HDS.GetData(HD.XLeft, HD.YTop, HD.Size, HD.DataType);
  110. if htfHD.DataState = hdsNone then
  111. begin
  112. HD.DataState := hdsNone;
  113. exit;
  114. end
  115. else
  116. HD.DataState := hdsPreparing;
  117. Move(htfHD.SmallIntData^, HeightData.SmallIntData^, htfHD.DataSize); // NOT inverted
  118. // ----------------
  119. // ---Select the best texture from the attached material library--
  120. MatLib := self.FMaterialLibrary;
  121. if Assigned(MatLib) then
  122. begin
  123. // --Get the world coordinates of the current terrain height tile--
  124. texSize := FTileSize * FTilesPerTexture;
  125. if FWholeTilesOnly then
  126. begin // picks top texture that covers the WHOLE tile.
  127. tileL := (HD.XLeft) / texSize;
  128. tileT := (HD.YTop + (HD.Size - 1)) / texSize - 1;
  129. tileR := (HD.XLeft + (HD.Size - 1)) / texSize;
  130. tileB := (HD.YTop) / texSize - 1;
  131. end
  132. else
  133. begin // picks top texture that covers any part of the tile. If the texture si not wrapped, the rest of the tile is left blank.
  134. tileL := (HD.XLeft + (HD.Size - 2)) / texSize;
  135. tileT := (HD.YTop + 1) / texSize - 1;
  136. tileR := (HD.XLeft + 1) / texSize;
  137. tileB := (HD.YTop + (HD.Size - 2)) / texSize - 1;
  138. end;
  139. //--picks top texture that covers tile center--
  140. //tileL:=(HD.XLeft+(HD.Size/2))/HTFSizeX;
  141. //tileT:=(HD.YTop +(HD.Size/2))/HTFSizeY-1;
  142. //tileB:=tileT;
  143. //tileR:=tileL;
  144. //---------------------------------------------
  145. MatInx:=MatLib.Materials.Count;
  146. Mat:=nil;
  147. found:=false;
  148. while (not found) and (MatInx > 0) do
  149. begin
  150. MatInx := MatInx - 1;
  151. Mat := MatLib.Materials[MatInx];
  152. texL := -Mat.TextureOffset.X / Mat.TextureScale.X;
  153. texR := texL + (1 / Mat.TextureScale.X);
  154. texT := Mat.TextureOffset.Y / Mat.TextureScale.Y;
  155. texB := texT - (1 / Mat.TextureScale.Y);
  156. if texB > texT then
  157. begin
  158. swp := texB;
  159. texB := texT;
  160. texT := swp;
  161. end;
  162. if texL > texR then
  163. begin
  164. swp := texL;
  165. texL := texR;
  166. texR := swp;
  167. end;
  168. if (tileL >= texL) and (tileR <= texR) and (tileT <= texT) and (tileB >= texB) then
  169. found := true;
  170. end;
  171. if found then
  172. HD.MaterialName := Mat.Name;
  173. end;
  174. //---------------------------------------------------------------
  175. //HD.MaterialName:=self.FMaterialLibrary.Materials[15].Name;
  176. HDS.Release(htfHD);
  177. //heightData.DataState:=hdsReady;
  178. inherited;
  179. end;
  180. procedure TgxTexturedHDS.SetHeightDataSource(val:TgxHeightDataSource);
  181. begin
  182. if val=self then FHeightDataSource:=nil
  183. else FHeightDataSource:=val;
  184. end;
  185. // ------------------------------------------------------------------
  186. initialization
  187. // ------------------------------------------------------------------
  188. RegisterClasses([TgxTexturedHDS]);
  189. end.