123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- unit UnitMain;
- interface
- uses
- Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
- Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls,
- GR32,
- GR32_Transforms,
- GR32_Rasterizers,
- GR32_Image;
- const
- MSG_AFTER_SHOW = WM_USER;
- MSG_AFTER_RESIZE = WM_USER+1;
- type
- TFormMain = class(TForm)
- PaintBox32: TPaintBox32;
- TimerRotate: TTimer;
- procedure FormResize(Sender: TObject);
- procedure PaintBox32PaintBuffer(Sender: TObject);
- procedure FormShow(Sender: TObject);
- procedure PaintBox32MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- procedure PaintBox32MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- procedure PaintBox32MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
- procedure TimerRotateTimer(Sender: TObject);
- procedure PaintBox32DblClick(Sender: TObject);
- procedure PaintBox32MouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint;
- var Handled: Boolean);
- private
- FBitmap: TBitmap32;
- FTransformation: TSphereTransformation;
- FRasterizer: TRasterizer;
- FDraftRasterizer: TRasterizer;
- FCurrentRasterizer: TRasterizer;
- FLastMousePos: TPoint;
- procedure MsgAfterShow(var Msg: TMessage); message MSG_AFTER_SHOW;
- procedure MsgAfterResize(var Msg: TMessage); message MSG_AFTER_RESIZE;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- end;
- var
- FormMain: TFormMain;
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- implementation
- {$R *.dfm}
- {$if defined(DCC) and (CompilerVersion >= 26.0)} // XE5 and later?
- {-$define USE_GEOLOCATION}
- {$ifend}
- uses
- System.Math,
- System.Diagnostics,
- {$ifdef USE_GEOLOCATION}
- System.Sensors,
- {$endif}
- GR32_Backends_Generic,
- GR32.ImageFormats.JPG,
- GR32.Examples;
- //------------------------------------------------------------------------------
- constructor TFormMain.Create(AOwner: TComponent);
- begin
- inherited;
- FBitmap := TBitmap32.Create(TMemoryBackend);
- FBitmap.ResamplerClassName := 'TLinearResampler';
- FBitmap.Resampler.PixelAccessMode := pamTransparentEdge;
- FTransformation := TSphereTransformation.Create;
- FRasterizer := TMultithreadedRegularRasterizer.Create;
- FDraftRasterizer := TDraftRasterizer.Create;
- FCurrentRasterizer := FRasterizer;
- PaintBox32.Visible := False;
- end;
- destructor TFormMain.Destroy;
- begin
- FBitmap.Free;
- FTransformation.Free;
- FRasterizer.Free;
- FDraftRasterizer.Free;
- inherited;
- end;
- //------------------------------------------------------------------------------
- procedure TFormMain.FormResize(Sender: TObject);
- begin
- PostMessage(Handle, MSG_AFTER_RESIZE, 0, 0);
- end;
- procedure TFormMain.FormShow(Sender: TObject);
- begin
- // Loading the source image can take a while so defer it until the form has actually been shown
- PostMessage(Handle, MSG_AFTER_SHOW, 0, 0);
- end;
- //------------------------------------------------------------------------------
- procedure TFormMain.MsgAfterResize(var Msg: TMessage);
- begin
- FTransformation.Radius := Min(PaintBox32.Width, PaintBox32.Height) / 2;
- FTransformation.Center := FloatPoint(PaintBox32.Width / 2, PaintBox32.Height / 2);
- end;
- procedure TFormMain.MsgAfterShow(var Msg: TMessage);
- {$ifdef USE_GEOLOCATION}
- var
- SensorManager: TSensorManager;
- Sensors: TSensorArray;
- Sensor: TCustomSensor;
- WasStarted: boolean;
- {$endif}
- var
- s: string;
- Size: TSize;
- begin
- Screen.Cursor := crAppStart;
- PaintBox32.Buffer.Clear(clBlack32);
- PaintBox32.Visible := True;
- s := 'Loading - Please wait...';
- Size := PaintBox32.Buffer.TextExtent(s);
- PaintBox32.Buffer.RenderText((PaintBox32.Width-Size.cx) div 2, (PaintBox32.Height-Size.cy) div 2, s, -1, clRed32);
- PaintBox32.Flush;
- FBitmap.LoadFromFile(Graphics32Examples.MediaFolder + '\Globe.jpg');
- FTransformation.SrcRect := MakeRect(FBitmap.BoundsRect);
- Screen.Cursor := crDefault;
- // Start with some random location, a bit more interesting than the Pacific Ocean
- FTransformation.Longitude := 55.29952826015878 / 90 * PI*2; // TODO : Something wrong here
- FTransformation.Lattitude := -12.052785473578014 / 90 * PI*2;
- {$ifdef USE_GEOLOCATION}
- // Try to get current location. Unfortunately this doesn't seem to work without
- // an actual location device although Windows is able to provide a user-specified
- // default location.
- SensorManager := TSensorManager.Current;
- SensorManager.Activate;
- Sensors := SensorManager.GetSensorsByCategory(TSensorCategory.Location);
- for Sensor in Sensors do
- begin
- WasStarted := Sensor.Started;
- if (not WasStarted) then
- Sensor.Start;
- if (not Sensor.Started) then
- continue;
- FTransformation.Longitude := TCustomLocationSensor(Sensor).Longitude / 180 * PI;
- FTransformation.Lattitude := TCustomLocationSensor(Sensor).Latitude / 90 * PI*2;
- if (not WasStarted) then
- Sensor.Stop;
- break;
- end;
- {$endif}
- end;
- //------------------------------------------------------------------------------
- procedure TFormMain.PaintBox32DblClick(Sender: TObject);
- begin
- TimerRotate.Enabled := not TimerRotate.Enabled;
- end;
- procedure TFormMain.PaintBox32MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- begin
- if (FBitmap = nil) or (FBitmap.Empty) then
- Exit;
- if ([ssLeft, ssRight] * Shift = []) then
- Exit;
- // Store current mouse position and switch to the draft rasterizer
- FLastMousePos := Point(X, Y);
- FCurrentRasterizer := FDraftRasterizer;
- end;
- procedure TFormMain.PaintBox32MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
- var
- DeltaX, DeltaY: Integer;
- begin
- if (FBitmap = nil) or (FBitmap.Empty) then
- Exit;
- if ([ssLeft, ssRight] * Shift = []) then
- Exit;
- TimerRotate.Enabled := False;
- DeltaX := X - FLastMousePos.X;
- DeltaY := Y - FLastMousePos.Y;
- if (Abs(DeltaX) <= 5) and (Abs(DeltaY) <= 5) then
- Exit;
- FLastMousePos := Point(X, Y);
- if (ssLeft in Shift) then
- begin
- // Rotate
- FTransformation.Longitude := FTransformation.Longitude - (DeltaX / FTransformation.Radius) * (PI / 2);
- FTransformation.Lattitude := FTransformation.Lattitude - (DeltaY / FTransformation.Radius) * (PI / 2);
- end else
- if (ssRight in Shift) then
- // Pan
- FTransformation.Center := FloatPoint(FTransformation.Center.X + DeltaX, FTransformation.Center.Y + DeltaY);
- PaintBox32.Invalidate;
- end;
- procedure TFormMain.PaintBox32MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- begin
- if (FBitmap = nil) or (FBitmap.Empty) then
- Exit;
- FCurrentRasterizer := FRasterizer;
- PaintBox32.Invalidate;
- end;
- procedure TFormMain.PaintBox32MouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint;
- var Handled: Boolean);
- begin
- // Zoom
- FTransformation.Radius := FTransformation.Radius + 50 * WheelDelta / 120;
- PaintBox32.Invalidate;
- Handled := True;
- end;
- //------------------------------------------------------------------------------
- procedure TFormMain.PaintBox32PaintBuffer(Sender: TObject);
- var
- StopWatch: TStopWatch;
- begin
- PaintBox32.Buffer.Clear(clBlack32);
- StopWatch := TStopWatch.StartNew;
- if (FBitmap <> nil) and (not FBitmap.Empty) then
- Transform(PaintBox32.Buffer, FBitmap, FTransformation, FCurrentRasterizer);
- StopWatch.Stop;
- PaintBox32.Buffer.RenderText(0, 0, Format('Rasterized in %d mS', [StopWatch.ElapsedMilliseconds]), -1, clWhite32);
- // While manually panning or rotating, adjust the pixel size so we are able to maintain
- // a frame rate between 25-50 fps
- if (FCurrentRasterizer = FDraftRasterizer) then
- begin
- if (StopWatch.ElapsedMilliseconds < 20) then
- TDraftRasterizer(FDraftRasterizer).PixelSize := TDraftRasterizer(FDraftRasterizer).PixelSize - 1
- else
- if (StopWatch.ElapsedMilliseconds > 40) then
- TDraftRasterizer(FDraftRasterizer).PixelSize := TDraftRasterizer(FDraftRasterizer).PixelSize + 1;
- PaintBox32.Buffer.RenderText(0, 20, Format('Pixel size: %d', [TDraftRasterizer(FDraftRasterizer).PixelSize]), -1, clWhite32);
- end;
- end;
- //------------------------------------------------------------------------------
- procedure TFormMain.TimerRotateTimer(Sender: TObject);
- begin
- FTransformation.Longitude := FTransformation.Longitude - 0.001;
- PaintBox32.Invalidate;
- end;
- //------------------------------------------------------------------------------
- end.
|