123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 |
- unit FViewerForm;
- interface
- uses
- Winapi.Windows,
- System.SysUtils,
- System.Classes,
- System.Actions,
- Vcl.Graphics,
- Vcl.Controls,
- Vcl.Forms,
- Vcl.Dialogs,
- Vcl.ActnList,
- Vcl.StdCtrls,
- Vcl.ExtCtrls,
- Vcl.ComCtrls,
- Vcl.ImgList,
- Vcl.ToolWin,
- Vcl.Menus,
- // GR32
- GR32_Image,
- GR32,
- GLS.HeightTileFileHDS,
- GLS.VectorGeometry,
- GLS.Utils, System.ImageList;
- type
- TViewerForm = class(TForm)
- ToolBar: TToolBar;
- ImageList: TImageList;
- ActionList: TActionList;
- ToolButton1: TToolButton;
- LAMap: TLabel;
- ToolButton2: TToolButton;
- ACOpen: TAction;
- ACExit: TAction;
- ToolButton3: TToolButton;
- OpenDialog: TOpenDialog;
- PaintBox: TPaintBox32;
- ToolButton4: TToolButton;
- TBGrid: TToolButton;
- ToolButton5: TToolButton;
- ToolButton6: TToolButton;
- ACNavMap: TAction;
- StatusBar: TStatusBar;
- ToolButton7: TToolButton;
- ACPalette: TAction;
- PMPalettes: TPopupMenu;
- OpenDialogPal: TOpenDialog;
- procedure ACExitExecute(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- procedure ACOpenExecute(Sender: TObject);
- procedure FormCreate(Sender: TObject);
- procedure PaintBoxResize(Sender: TObject);
- procedure PaintBoxMouseDown(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- procedure PaintBoxMouseMove(Sender: TObject; Shift: TShiftState;
- X, Y: Integer);
- procedure TBGridClick(Sender: TObject);
- procedure ACNavMapExecute(Sender: TObject);
- procedure PaintBoxMouseUp(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- procedure ACNavMapUpdate(Sender: TObject);
- procedure ACPaletteExecute(Sender: TObject);
- private
- public
- htf: TGLHeightTileFile;
- bmpTile: TBitmap32;
- curX, curY, mx, my: Integer;
- procedure PrepareBitmap;
- end;
- var
- ViewerForm: TViewerForm;
- var
- heightColor: array [Low(SmallInt) .. High(SmallInt)] of TColor32;
- implementation
- {$R *.dfm}
- uses FNavForm;
- { Quick'n dirty parser for palette file format '.pal', in which each line defines
- nodes in the color ramp palette:
- value:red,green,blue
- color is then interpolated between node values (ie. between each line in the file)
- }
- procedure PreparePal(const fileName: String);
- procedure ParseLine(buf: String; var n: Integer; var c: TAffineVector);
- var
- p: Integer;
- begin
- p := Pos(':', buf);
- n := StrToInt(Copy(buf, 1, p - 1));
- buf := Copy(buf, p + 1, MaxInt);
- p := Pos(',', buf);
- c.X := StrToInt(Copy(buf, 1, p - 1));
- buf := Copy(buf, p + 1, MaxInt);
- p := Pos(',', buf);
- c.Y := StrToInt(Copy(buf, 1, p - 1));
- buf := Copy(buf, p + 1, MaxInt);
- c.Z := StrToInt(buf);
- end;
- var
- prev, next: Integer;
- pC, nC: TAffineVector;
- procedure Ramp;
- var
- cur: Integer;
- cC: TAffineVector;
- d: Single;
- begin
- if prev < next then
- d := 1 / (next - prev)
- else
- d := 0;
- for cur := prev to next do
- begin
- cC := VectorLerp(pC, nC, (cur - prev) * d);
- heightColor[cur] := Color32(Round(cC.X), Round(cC.Y), Round(cC.Z));
- end;
- end;
- var
- i: Integer;
- sl: TStrings;
- begin
- sl := TStringList.Create;
- try
- sl.LoadFromFile(fileName);
- prev := 0;
- pC := NullVector;
- for i := 0 to sl.Count - 1 do
- begin
- ParseLine(sl[i], next, nC);
- Ramp;
- prev := next;
- pC := nC;
- end;
- finally
- sl.Free;
- end;
- end;
- procedure TViewerForm.FormCreate(Sender: TObject);
- var
- i: Integer;
- sr: TSearchRec;
- mi: TMenuItem;
- sl: TStringList;
- AppDir: String;
- begin
- bmpTile := TBitmap32.Create;
- AppDir := ExtractFilePath(ParamStr(0));
- PreparePal(AppDir + 'Blue-Green-Red.pal');
- i := FindFirst(AppDir + '*.pal', faAnyFile, sr);
- sl := TStringList.Create;
- try
- while i = 0 do
- begin
- sl.Add(sr.Name);
- i := FindNext(sr);
- end;
- sl.Sort;
- for i := 0 to sl.Count - 1 do
- begin
- mi := TMenuItem.Create(PMPalettes);
- mi.Caption := Copy(sl[i], 1, Length(sl[i]) - 4);
- mi.Hint := AppDir + sl[i];
- mi.OnClick := ACPaletteExecute;
- PMPalettes.Items.Add(mi);
- end;
- finally
- sl.Free;
- FindClose(sr);
- end;
- end;
- procedure TViewerForm.FormDestroy(Sender: TObject);
- begin
- htf.Free;
- bmpTile.Free;
- end;
- procedure TViewerForm.ACExitExecute(Sender: TObject);
- begin
- Close;
- end;
- procedure TViewerForm.ACOpenExecute(Sender: TObject);
- var
- i: Integer;
- begin
- SetGLSceneMediaDir;
- OpenDialog.InitialDir := GetCurrentDir;
- if OpenDialog.Execute then
- begin
- htf.Free;
- htf := TGLHeightTileFile.Create(OpenDialog.fileName);
- Caption := 'HTFViewer - ' + ExtractFileName(OpenDialog.fileName);
- curX := 0;
- curY := 0;
- PrepareBitmap;
- PaintBox.Invalidate;
- end;
- end;
- procedure TViewerForm.PrepareBitmap;
- var
- i, sx, tx, ty: Integer;
- scanLine: PColor32Array;
- tileInfo: PHeightTileInfo;
- dataRow: PSmallIntArray;
- tile: PHeightTile;
- start, lap, stop, htfTime, drawTime, freq: Int64;
- tileList: TList;
- bmp: TBitmap32;
- begin
- sx := PaintBox.Width;
- bmp := PaintBox.Buffer;
- bmp.Clear(clBlack32);
- if not Assigned(htf) then
- Exit;
- drawTime := 0;
- tileList := TList.Create;
- try
- QueryPerformanceCounter(start);
- htf.TilesInRect(curX, curY, curX + sx - 1, curY + bmp.Height - 1, tileList);
- QueryPerformanceCounter(stop);
- htfTime := stop - start;
- for i := 0 to tileList.Count - 1 do
- begin
- tileInfo := PHeightTileInfo(tileList[i]);
- QueryPerformanceCounter(start);
- tile := htf.GetTile(tileInfo.left, tileInfo.top);
- QueryPerformanceCounter(lap);
- bmpTile.Width := tileInfo.Width;
- bmpTile.Height := tileInfo.Height;
- for ty := 0 to tileInfo.Height - 1 do
- begin
- scanLine := bmpTile.scanLine[ty];
- dataRow := @tile.data[ty * tileInfo.Width];
- for tx := 0 to tileInfo.Width - 1 do
- scanLine[tx] := heightColor[dataRow[tx]];
- end;
- bmp.Draw(tileInfo.left - curX, tileInfo.top - curY, bmpTile);
- QueryPerformanceCounter(stop);
- htfTime := htfTime + lap - start;
- drawTime := drawTime + stop - lap;
- end;
- if TBGrid.Down then
- begin
- for i := 0 to tileList.Count - 1 do
- with PHeightTileInfo(tileList[i])^ do
- begin
- bmp.FrameRectS(left - curX, top - curY, left + Width - curX + 1,
- top + Height - curY + 1, clWhite32);
- end;
- end;
- finally
- tileList.Free;
- end;
- QueryPerformanceFrequency(freq);
- LAMap.Caption := Format(' %d x %d - %.1f ms HTF - %.1fms Draw ',
- [htf.SizeX, htf.SizeY, 1000 * htfTime / freq, 1000 * drawTime / freq]);
- end;
- procedure TViewerForm.PaintBoxResize(Sender: TObject);
- begin
- if Assigned(htf) then
- PrepareBitmap;
- end;
- procedure TViewerForm.PaintBoxMouseDown(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- begin
- mx := X;
- my := Y;
- Screen.Cursor := crSizeAll;
- end;
- procedure TViewerForm.PaintBoxMouseUp(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- begin
- Screen.Cursor := crDefault;
- end;
- procedure TViewerForm.PaintBoxMouseMove(Sender: TObject; Shift: TShiftState;
- X, Y: Integer);
- var
- tileIdx, n: Integer;
- tileInfo: PHeightTileInfo;
- begin
- if Shift <> [] then
- begin
- curX := curX - (X - mx);
- curY := curY - (Y - my);
- mx := X;
- my := Y;
- PrepareBitmap;
- PaintBox.Refresh;
- end;
- if Assigned(htf) then
- begin
- X := X + curX;
- Y := Y + curY;
- StatusBar.Panels[0].Text := ' X: ' + IntToStr(X);
- StatusBar.Panels[1].Text := ' Y: ' + IntToStr(Y);
- StatusBar.Panels[2].Text := ' H: ' + IntToStr(htf.XYHeight(X, Y));
- tileInfo := htf.XYTileInfo(X, Y);
- if Assigned(tileInfo) then
- begin
- tileIdx := htf.IndexOfTile(tileInfo);
- StatusBar.Panels[3].Text := ' Tile: ' + IntToStr(tileIdx);
- n := htf.TileCompressedSize(tileIdx) + SizeOf(TGLHeightTileInfo);
- StatusBar.Panels[4].Text := Format(' %.2f kB (%.0f %%)',
- [n / 1024, 100 - 100 * n / (htf.TileSize * htf.TileSize * 2)]);
- StatusBar.Panels[5].Text := Format(' Tile average: %d, range: [%d; %d])',
- [tileInfo.average, tileInfo.min, tileInfo.max]);
- end
- else
- begin
- StatusBar.Panels[3].Text := ' Tile: N/A';
- StatusBar.Panels[4].Text := ' N/A';
- StatusBar.Panels[5].Text := ' N/A';
- end;
- end;
- end;
- procedure TViewerForm.TBGridClick(Sender: TObject);
- begin
- PrepareBitmap;
- PaintBox.Invalidate;
- end;
- procedure TViewerForm.ACNavMapExecute(Sender: TObject);
- begin
- if NavForm.Execute(htf) then
- begin
- curX := NavForm.PickX;
- curY := NavForm.PickY;
- PrepareBitmap;
- PaintBox.Invalidate;
- end;
- end;
- procedure TViewerForm.ACNavMapUpdate(Sender: TObject);
- begin
- ACNavMap.Enabled := Assigned(htf);
- end;
- procedure TViewerForm.ACPaletteExecute(Sender: TObject);
- begin
- if Sender is TMenuItem then
- PreparePal(TMenuItem(Sender).Hint)
- else if OpenDialogPal.Execute then
- PreparePal(OpenDialogPal.fileName);
- PrepareBitmap;
- PaintBox.Invalidate;
- end;
- end.
|