GLS.TexturedHDS.pas 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. //
  2. // The graphics engine GLScene
  3. //
  4. unit GLS.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 TGLHeightTileFile)
  8. The HDS also links to a TGLMaterial 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 TGLTerrainRenderer.
  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. GLS.Coordinates,
  25. GLS.HeightData,
  26. GLS.Material;
  27. type
  28. TGLTexturedHDS = class(TGLHeightDataSource)
  29. private
  30. FOnStartPreparingData: TStartPreparingDataEvent;
  31. FOnMarkDirty: TMarkDirtyEvent;
  32. FHeightDataSource: TGLHeightDataSource;
  33. FMaterialLibrary: TGLMaterialLibrary;
  34. FWholeTilesOnly: Boolean;
  35. FTileSize: integer;
  36. FTilesPerTexture: integer;
  37. protected
  38. procedure SetHeightDataSource(val: TGLHeightDataSource);
  39. public
  40. constructor Create(AOwner: TComponent); override;
  41. destructor Destroy; override;
  42. procedure StartPreparingData(heightData: TGLHeightData); override;
  43. procedure MarkDirty(const area: TRect); override;
  44. published
  45. property MaxPoolSize;
  46. property OnStartPreparingData: TStartPreparingDataEvent read FOnStartPreparingData write FOnStartPreparingData;
  47. property OnMarkDirtyEvent: TMarkDirtyEvent read FOnMarkDirty write FOnMarkDirty;
  48. property HeightDataSource: TGLHeightDataSource read FHeightDataSource write SetHeightDataSource;
  49. property MaterialLibrary: TGLMaterialLibrary read FMaterialLibrary write FMaterialLibrary;
  50. property WholeTilesOnly: Boolean read FWholeTilesOnly write FWholeTilesOnly;
  51. // This should match TileSize in TGLTerrainRenderer
  52. property TileSize: integer read FTileSize write FTileSize;
  53. // This should match TilesPerTexture in TGLTerrainRenderer
  54. property TilesPerTexture: integer read FTilesPerTexture write FTilesPerTexture;
  55. end;
  56. //=========================================================================
  57. implementation
  58. //=========================================================================
  59. // ------------------
  60. // ------------------ TGLTexturedHDS ------------------
  61. // ------------------
  62. constructor TGLTexturedHDS.Create(AOwner: TComponent);
  63. begin
  64. FHeightDataSource:=nil;
  65. FMaterialLibrary:=nil;
  66. FTileSize:=16;
  67. FTilesPerTexture:=1;
  68. inherited Create(AOwner);
  69. end;
  70. destructor TGLTexturedHDS.Destroy;
  71. begin
  72. inherited Destroy;
  73. end;
  74. procedure TGLTexturedHDS.MarkDirty(const area : TRect);
  75. begin
  76. inherited;
  77. if Assigned(FOnMarkDirty) then
  78. FOnMarkDirty(area);
  79. end;
  80. procedure TGLTexturedHDS.StartPreparingData(heightData : TGLHeightData);
  81. var
  82. HDS: TGLHeightDataSource;
  83. htfHD: TGLHeightData;
  84. MatLib: TGLMaterialLibrary;
  85. Mat: TGLLibMaterial;
  86. HD: TGLHeightData;
  87. MatInx: integer;
  88. tileL, tileR, tileT, tileB: single;
  89. found: Boolean;
  90. texL, texR, texT, texB, swp: single;
  91. texSize: integer;
  92. begin
  93. if not Assigned(FHeightDataSource) then begin
  94. heightData.DataState:=hdsNone;
  95. exit;
  96. end;
  97. // ---Height Data--
  98. HD := heightData;
  99. HD.DataType := hdtSmallInt;
  100. HD.Allocate(hdtSmallInt);
  101. HDS := self.FHeightDataSource;
  102. // HD.FTextureCoordinatesMode:=tcmWorld;
  103. htfHD := HDS.GetData(HD.XLeft, HD.YTop, HD.Size, HD.DataType);
  104. if htfHD.DataState = hdsNone then
  105. begin
  106. HD.DataState := hdsNone;
  107. exit;
  108. end
  109. else
  110. HD.DataState := hdsPreparing;
  111. Move(htfHD.SmallIntData^, heightData.SmallIntData^, htfHD.DataSize); // NOT inverted
  112. // ----------------
  113. // ---Select the best texture from the attached material library--
  114. MatLib := self.FMaterialLibrary;
  115. if Assigned(MatLib) then
  116. begin
  117. // --Get the world coordinates of the current terrain height tile--
  118. texSize := FTileSize * FTilesPerTexture;
  119. if FWholeTilesOnly then
  120. begin // picks top texture that covers the WHOLE tile.
  121. tileL := (HD.XLeft) / texSize;
  122. tileT := (HD.YTop + (HD.Size - 1)) / texSize - 1;
  123. tileR := (HD.XLeft + (HD.Size - 1)) / texSize;
  124. tileB := (HD.YTop) / texSize - 1;
  125. end
  126. else
  127. 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.
  128. tileL:=(HD.XLeft+(HD.Size-2))/texSize;
  129. tileT:=(HD.YTop +1 )/texSize-1;
  130. tileR:=(HD.XLeft+1 )/texSize;
  131. tileB:=(HD.YTop +(HD.Size-2))/texSize-1;
  132. end;
  133. //--picks top texture that covers tile center--
  134. //tileL:=(HD.XLeft+(HD.Size/2))/HTFSizeX;
  135. //tileT:=(HD.YTop +(HD.Size/2))/HTFSizeY-1;
  136. //tileB:=tileT;
  137. //tileR:=tileL;
  138. //---------------------------------------------
  139. MatInx := MatLib.Materials.Count;
  140. Mat := nil;
  141. found := false;
  142. while (not found) and (MatInx > 0) do
  143. begin
  144. MatInx := MatInx - 1;
  145. Mat := MatLib.Materials[MatInx];
  146. texL := -Mat.TextureOffset.X / Mat.TextureScale.X;
  147. texR := texL + (1 / Mat.TextureScale.X);
  148. texT := Mat.TextureOffset.Y / Mat.TextureScale.Y;
  149. texB := texT - (1 / Mat.TextureScale.Y);
  150. if texB > texT then
  151. begin
  152. swp := texB;
  153. texB := texT;
  154. texT := swp;
  155. end;
  156. if texL > texR then
  157. begin
  158. swp := texL;
  159. texL := texR;
  160. texR := swp;
  161. end;
  162. if (tileL >= texL) and (tileR <= texR) and (tileT <= texT) and
  163. (tileB >= texB) then
  164. found := true;
  165. end;
  166. if found then
  167. HD.MaterialName := Mat.Name;
  168. end;
  169. //---------------------------------------------------------------
  170. //HD.MaterialName:=self.FMaterialLibrary.Materials[15].Name;
  171. HDS.Release(htfHD);
  172. //heightData.DataState:=hdsReady;
  173. inherited;
  174. end;
  175. procedure TGLTexturedHDS.SetHeightDataSource(val:TGLHeightDataSource);
  176. begin
  177. if val=self then FHeightDataSource:=nil
  178. else FHeightDataSource:=val;
  179. end;
  180. // ------------------------------------------------------------------
  181. initialization
  182. // ------------------------------------------------------------------
  183. RegisterClasses([TGLTexturedHDS]);
  184. end.