123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- unit fSynthTerrain;
- interface
- uses
- Winapi.Windows,
- Winapi.OpenGL,
- System.SysUtils,
- System.Classes,
- System.UITypes,
- Vcl.Graphics,
- Vcl.Controls,
- Vcl.Forms,
- Vcl.Dialogs,
- Vcl.ExtCtrls,
- Vcl.StdCtrls,
- Vcl.Imaging.Jpeg,
- GLS.Scene,
- GLS.Objects,
- GLS.TerrainRenderer,
- GLS.HeightData,
- GLS.Cadencer,
- GLS.VectorTypes,
- GLS.Texture,
- GLS.SceneViewer,
- GLS.VectorGeometry,
- GLS.Material,
- GLS.Coordinates,
- GLS.BaseClasses,
- GLS.Keyboard, GLS.ShadowHDS;
- type
- TFormSynthTerrain = class(TForm)
- GLSceneViewer1: TGLSceneViewer;
- GLScene1: TGLScene;
- GLCamera1: TGLCamera;
- DummyCube1: TGLDummyCube;
- TerrainRenderer1: TGLTerrainRenderer;
- Timer1: TTimer;
- GLCadencer1: TGLCadencer;
- GLMaterialLibrary1: TGLMaterialLibrary;
- GLCustomHDS: TGLCustomHDS;
- GLShadowHDS: TGLShadowHDS;
- procedure GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
- X, Y: Integer);
- procedure Timer1Timer(Sender: TObject);
- procedure GLCadencer1Progress(Sender: TObject;
- const deltaTime, newTime: Double);
- procedure FormCreate(Sender: TObject);
- procedure FormKeyPress(Sender: TObject; var Key: Char);
- procedure GLCustomHDSStartPreparingData(HeightData: TGLHeightData);
- public
- mx, my: Integer;
- fullScreen: Boolean;
- FCamHeight: Single;
- end;
- var
- FormSynthTerrain: TFormSynthTerrain;
- implementation
- {$R *.DFM}
- procedure TFormSynthTerrain.FormCreate(Sender: TObject);
- var
- i: Integer;
- bmp: TBitmap;
- begin
- // 8 MB height data cache
- // Note this is the data size in terms of elevation samples, it does not
- // take into account all the data required/allocated by the renderer
- GLCustomHDS.MaxPoolSize := 8 * 1024 * 1024;
- // Move camera starting point to an interesting hand-picked location
- DummyCube1.Position.X := 50;
- DummyCube1.Position.Z := 150;
- // Initial camera height offset (controled with pageUp/pageDown)
- FCamHeight := 20;
- // We build several basic 1D textures which are just color ramps
- // all use automatic texture mapping corodinates, in ObjectLinear method
- // (ie. texture coordinates for a vertex depend on that vertex coordinates)
- bmp := TBitmap.Create;
- bmp.PixelFormat := pf24bit;
- bmp.Width := 256;
- bmp.Height := 1;
- // Black-White ramp, autotexture maps to Z coordinate
- // This one changes with altitude, this is a quick way to obtain
- // altitude-dependant coloring
- for i := 0 to 255 do
- bmp.Canvas.Pixels[i, 0] := RGB(i, i, i);
- with GLMaterialLibrary1.AddTextureMaterial('BW', bmp) do
- begin
- Material.Texture.MappingMode := tmmObjectLinear;
- Material.Texture.MappingSCoordinates.AsVector := VectorMake(0, 0, 0.0001, 0);
- end;
- // Red, Blue map linearly to X and Y axis respectively
- for i := 0 to 255 do
- bmp.Canvas.Pixels[i, 0] := RGB(i, 0, 0);
- with GLMaterialLibrary1.AddTextureMaterial('Red', bmp) do
- begin
- Material.Texture.MappingMode := tmmObjectLinear;
- Material.Texture.MappingSCoordinates.AsVector := VectorMake(0.1, 0, 0, 0);
- end;
- for i := 0 to 255 do
- bmp.Canvas.Pixels[i, 0] := RGB(0, 0, i);
- with GLMaterialLibrary1.AddTextureMaterial('Blue', bmp) do
- begin
- Material.Texture.MappingMode := tmmObjectLinear;
- Material.Texture.MappingSCoordinates.AsVector := VectorMake(0, 0.1, 0, 0);
- end;
- bmp.Free;
- TerrainRenderer1.MaterialLibrary := GLMaterialLibrary1;
- end;
- //
- // The beef : this event does all the interesting elevation data stuff
- //
- procedure TFormSynthTerrain.GLCustomHDSStartPreparingData(HeightData: TGLHeightData);
- var
- Y, X: Integer;
- rasterLine: PByteArray;
- oldType: TGLHeightDataType;
- b: Byte;
- d, dy: Single;
- begin
- HeightData.DataState := hdsPreparing;
- // retrieve data
- with HeightData do
- begin
- oldType := DataType;
- Allocate(hdtByte);
- // Cheap texture changed (32 is our tileSize = 2^5)
- // This basicly picks a texture for each tile depending on the tile's position
- case (((XLeft xor YTop) shr 5) and 3) of
- 0, 3: HeightData.MaterialName := 'BW';
- 1: HeightData.MaterialName := 'Blue';
- 2: HeightData.MaterialName := 'Red';
- end;
- // 'Cheap' elevation data : this is just a formula z=f(x, y)
- for Y := YTop to YTop + Size - 1 do
- begin
- rasterLine := ByteRaster[Y - YTop];
- dy := Sqr(Y);
- for X := XLeft to XLeft + Size - 1 do
- begin
- d := Sqrt(Sqr(X) + dy);
- b := Round(128 + 128 * Sin(d * 0.2) / (d * 0.1 + 1));
- rasterLine[X - XLeft] := b;
- end;
- end;
- if oldType <> hdtByte then
- DataType := oldType;
- end;
- inherited;
- end;
- // Movement, mouse handling etc.
- procedure TFormSynthTerrain.GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- begin
- mx := X;
- my := Y;
- end;
- procedure TFormSynthTerrain.GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
- X, Y: Integer);
- begin
- if ssLeft in Shift then
- begin
- GLCamera1.MoveAroundTarget(my - Y, mx - X);
- mx := X;
- my := Y;
- end;
- end;
- procedure TFormSynthTerrain.Timer1Timer(Sender: TObject);
- begin
- Caption := Format('%.1f FPS - %d', [GLSceneViewer1.FramesPerSecond,
- TerrainRenderer1.LastTriangleCount]);
- GLSceneViewer1.ResetPerformanceMonitor;
- end;
- procedure TFormSynthTerrain.FormKeyPress(Sender: TObject; var Key: Char);
- begin
- case Key of
- '+':
- if GLCamera1.DepthOfView < 4000 then
- begin
- GLCamera1.DepthOfView := GLCamera1.DepthOfView * 1.2;
- with GLSceneViewer1.Buffer.FogEnvironment do
- begin
- FogEnd := FogEnd * 1.2;
- FogStart := FogStart * 1.2;
- end;
- end;
- '-':
- if GLCamera1.DepthOfView > 300 then
- begin
- GLCamera1.DepthOfView := GLCamera1.DepthOfView / 1.2;
- with GLSceneViewer1.Buffer.FogEnvironment do
- begin
- FogEnd := FogEnd / 1.2;
- FogStart := FogStart / 1.2;
- end;
- end;
- '*':
- with TerrainRenderer1 do
- if CLODPrecision > 5 then
- CLODPrecision := Round(CLODPrecision * 0.8);
- '/':
- with TerrainRenderer1 do
- if CLODPrecision < 500 then
- CLODPrecision := Round(CLODPrecision * 1.2);
- '8':
- with TerrainRenderer1 do
- if QualityDistance > 40 then
- QualityDistance := Round(QualityDistance * 0.8);
- '9':
- with TerrainRenderer1 do
- if QualityDistance < 1000 then
- QualityDistance := Round(QualityDistance * 1.2);
- end;
- Key := #0;
- end;
- procedure TFormSynthTerrain.GLCadencer1Progress(Sender: TObject;
- const deltaTime, newTime: Double);
- var
- speed: Single;
- begin
- // handle keypresses
- if IsKeyDown(VK_SHIFT) then
- speed := 5 * deltaTime
- else
- speed := deltaTime;
- with GLCamera1.Position do
- begin
- if IsKeyDown(VK_RIGHT) then
- DummyCube1.Translate(Z * speed, 0, -X * speed);
- if IsKeyDown(VK_LEFT) then
- DummyCube1.Translate(-Z * speed, 0, X * speed);
- if IsKeyDown(VK_UP) then
- DummyCube1.Translate(-X * speed, 0, -Z * speed);
- if IsKeyDown(VK_DOWN) then
- DummyCube1.Translate(X * speed, 0, Z * speed);
- if IsKeyDown(VK_PRIOR) then
- FCamHeight := FCamHeight + 10 * speed;
- if IsKeyDown(VK_NEXT) then
- FCamHeight := FCamHeight - 10 * speed;
- if IsKeyDown(VK_ESCAPE) then
- Close;
- end;
- // don't drop through terrain!
- with DummyCube1.Position do
- Y := TerrainRenderer1.InterpolatedHeight(AsVector) + FCamHeight;
- end;
- end.
|