2
// This unit is part of the GLScene Engine https://github.com/glscene
5
Implements a HDS, which automatically maps textures onto a parent HDS .
6
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.
14
If two or more textures in the library overlap, the top texture is used.( ie.the later one in the list)
16
WARNING: Only one base texture is mapped onto each terrain tile, so, make
17
sure your texture edges are alligned to height tile edges, or gaps will show.
18
(Of course you can still multitexture in a detail texture too.)
21
22/01/07 - LIN - Added 'TileSize' and 'TilesPerTexture' properties
22
Removed 'Active' property
23
Now works with both TGLHeightTileFileHDS AND TGLBitmapHDS
24
19/01/07 - LIN - Creation
34
uses Classes, GLCrossPlatform, GLHeightData, GLMaterial;
37
TGLTexturedHDS = class (TGLHeightDataSource)
40
FOnStartPreparingData : TStartPreparingDataEvent;
41
FOnMarkDirty : TMarkDirtyEvent;
42
FHeightDataSource : TGLHeightDataSource;
43
FMaterialLibrary : TGLMaterialLibrary;
44
FWholeTilesOnly : Boolean;
46
FTilesPerTexture : integer;
49
procedure SeTGLHeightDataSource(val:TGLHeightDataSource);
52
constructor Create(AOwner: TComponent); override;
53
destructor Destroy; override;
54
procedure StartPreparingData(heightData : TGLHeightData); override;
55
procedure MarkDirty(const area : TGLRect); override;
60
property OnStartPreparingData : TStartPreparingDataEvent read FOnStartPreparingData write FOnStartPreparingData;
61
property OnMarkDirtyEvent : TMarkDirtyEvent read FOnMarkDirty write FOnMarkDirty;
62
property HeightDataSource : TGLHeightDataSource read FHeightDataSource write SeTGLHeightDataSource;
63
property MaterialLibrary : TGLMaterialLibrary read FMaterialLibrary write FMaterialLibrary;
64
property WholeTilesOnly : Boolean read FWholeTilesOnly write FWholeTilesOnly;
65
{This should match TileSize in TGLTerrainRenderer}
66
property TileSize : integer read FTileSize write FTileSize;
67
{This should match TilesPerTexture in TGLTerrainRenderer}
68
property TilesPerTexture : Integer read FTilesPerTexture write FTilesPerTexture;
74
// ------------------ TGLTexturedHDS ------------------
79
constructor TGLTexturedHDS.Create(AOwner: TComponent);
81
FHeightDataSource:=nil;
82
FMaterialLibrary:=nil;
85
inherited Create(AOwner);
90
destructor TGLTexturedHDS.Destroy;
97
procedure TGLTexturedHDS.MarkDirty(const area : TGLRect);
100
if Assigned(FOnMarkDirty) then
105
procedure TGLTexturedHDS.StartPreparingData(heightData : TGLHeightData);
106
var HDS:TGLHeightDataSource;
108
MatLib:TGLMaterialLibrary;
112
tileL,tileR,tileT,tileB:single;
114
texL,texR,texT,texB,swp:single;
117
if not Assigned(FHeightDataSource) then begin
118
heightData.DataState:=hdsNone;
124
HD.DataType:=hdtSmallInt;
125
HD.Allocate(hdtSmallInt);
126
HDS:=self.FHeightDataSource;
127
//HD.FTextureCoordinatesMode:=tcmWorld;
128
htfHD:=HDS.GetData(HD.XLeft,HD.YTop,HD.Size,HD.DataType);
129
if htfHD.DataState=hdsNone then begin
130
HD.DataState:=hdsNone;
132
end else HD.DataState:=hdsPreparing;
133
Move(htfHD.SmallIntData^, heightData.SmallIntData^, htfHD.DataSize); //NOT inverted
136
//---Select the best texture from the attached material library--
137
MatLib:=self.FMaterialLibrary;
138
if Assigned(MatLib) then begin
139
//--Get the world coordinates of the current terrain height tile--
140
texSize:=FTileSize*FTilesPerTexture;
141
if FWholeTilesOnly then begin //picks top texture that covers the WHOLE tile.
142
tileL:=(HD.XLeft )/texSize;
143
tileT:=(HD.YTop +(HD.Size-1))/texSize-1;
144
tileR:=(HD.XLeft+(HD.Size-1))/texSize;
145
tileB:=(HD.YTop )/texSize-1;
146
end else 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.
147
tileL:=(HD.XLeft+(HD.Size-2))/texSize;
148
tileT:=(HD.YTop +1 )/texSize-1;
149
tileR:=(HD.XLeft+1 )/texSize;
150
tileB:=(HD.YTop +(HD.Size-2))/texSize-1;
152
//--picks top texture that covers tile center--
153
//tileL:=(HD.XLeft+(HD.Size/2))/HTFSizeX;
154
//tileT:=(HD.YTop +(HD.Size/2))/HTFSizeY-1;
157
//---------------------------------------------
158
MatInx:=MatLib.Materials.Count;
161
while (not found)and(MatInx>0) do begin
163
Mat:=MatLib.Materials[MatInx];
164
texL:=-mat.TextureOffset.X/mat.TextureScale.X;
165
texR:=texL+(1/mat.TextureScale.X);
166
texT:=mat.TextureOffset.Y/mat.TextureScale.Y;
167
texB:=texT-(1/mat.TextureScale.Y);
168
if texB>texT then begin swp:=texB; texB:=texT; texT:=swp; end;
169
if texL>texR then begin swp:=texL; texL:=texR; texR:=swp; end;
170
if (tileL>=texL)and(tileR<=texR)and(tileT<=texT)and(tileB>=texB) then found:=true;
172
if found then HD.MaterialName:=Mat.Name;
174
//---------------------------------------------------------------
175
//HD.MaterialName:=self.FMaterialLibrary.Materials[15].Name;
178
//heightData.DataState:=hdsReady;
182
procedure TGLTexturedHDS.SeTGLHeightDataSource(val:TGLHeightDataSource);
184
if val=self then FHeightDataSource:=nil
185
else FHeightDataSource:=val;
188
// ------------------------------------------------------------------
189
// ------------------------------------------------------------------
190
// ------------------------------------------------------------------
192
// ------------------------------------------------------------------
193
// ------------------------------------------------------------------
194
// ------------------------------------------------------------------
196
Classes.RegisterClasses([TGLTexturedHDS]);