| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952 |
- //
- // The graphics engine GLScene https://github.com/glscene
- //
- unit GLS.Navigator;
- (* Unit for navigating GLBaseObjects and GLSceneViewer. *)
- interface
- {$I GLScene.Defines.inc}
- uses
- Winapi.Windows,
- System.Types,
- System.Classes,
- System.SysUtils,
- System.Math,
- Vcl.Controls,
- Vcl.Graphics,
- Vcl.Forms,
- GLS.Scene,
- GLS.SceneViewer,
- GLS.Objects,
- GLS.GeomObjects,
- GLS.Context,
- GLScene.BaseClasses,
- GLScene.PersistentClasses,
- GLScene.VectorTypes,
- GLScene.VectorGeometry,
- GLS.Keyboard,
- GLS.HudObjects,
- GLScene.Coordinates,
- GLS.Screen,
- GLS.Material,
- GLS.Texture,
- GLScene.TextureFormat,
- GLS.RenderContextInfo;
- type
- (* TGLNavigator is the component for moving a TGLBaseSceneObject, and all Classes based on it,
- this includes all the objects from the Scene Editor.
- The four calls to get you started is
- TurnHorisontal : it turns left and right.
- TurnVertical : it turns up and down.
- MoveForward : moves back and forth.
- FlyForward : moves back and forth in the movingobject's direction
- The three properties to get you started is
- MovingObject : The Object that you are moving.
- UseVirtualUp : When UseVirtualUp is set you navigate Quake style. If it isn't more like Descent.
- AngleLock : Allows you to block the Vertical angles.
- Should only be used in conjunction with UseVirtualUp.
- MoveUpWhenMovingForward : Changes movement from Quake to Arcade Airplane...(no tilt and flying)
- InvertHorizontalSteeringWhenUpsideDown : When using virtual up, and vertically
- rotating beyond 90 degrees, will make steering seem inverted, so we "invert" back to normal *)
- TGLNavigator = class(TComponent)
- private
- FObject: TGLBaseSceneObject;
- FVirtualRight: TGLVector;
- FVirtualUp: TGCoordinates;
- FUseVirtualUp: boolean;
- FAutoUpdateObject: boolean;
- FMaxAngle: single;
- FMinAngle: single;
- FCurrentVAngle: single;
- FCurrentHAngle: single;
- FAngleLock: boolean;
- FMoveUpWhenMovingForward: boolean;
- FInvertHorizontalSteeringWhenUpsideDown: boolean;
- protected
- procedure Notification(AComponent: TComponent;
- Operation: TOperation); override;
- procedure SetObject(NewObject: TGLBaseSceneObject); virtual;
- procedure SetUseVirtualUp(UseIt: boolean);
- procedure SetVirtualUp(Up: TGCoordinates);
- function CalcRight: TGLVector;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure TurnHorizontal(Angle: single);
- procedure TurnVertical(Angle: single);
- procedure MoveForward(Distance: single);
- procedure StrafeHorizontal(Distance: single);
- procedure StrafeVertical(Distance: single);
- procedure Straighten;
- procedure FlyForward(Distance: single);
- procedure LoadState(Stream: TStream);
- procedure SaveState(Stream: TStream);
- property CurrentVAngle: single read FCurrentVAngle;
- property CurrentHAngle: single read FCurrentHAngle;
- published
- property MoveUpWhenMovingForward: boolean read FMoveUpWhenMovingForward
- write FMoveUpWhenMovingForward default False;
- property InvertHorizontalSteeringWhenUpsideDown: boolean
- read FInvertHorizontalSteeringWhenUpsideDown
- write FInvertHorizontalSteeringWhenUpsideDown default False;
- property VirtualUp: TGCoordinates read FVirtualUp write SetVirtualUp;
- property MovingObject: TGLBaseSceneObject read FObject write SetObject;
- property UseVirtualUp: boolean read FUseVirtualUp write SetUseVirtualUp
- default False;
- property AutoUpdateObject: boolean read FAutoUpdateObject
- write FAutoUpdateObject default False;
- property MaxAngle: single read FMaxAngle write FMaxAngle;
- property MinAngle: single read FMinAngle write FMinAngle;
- property AngleLock: boolean read FAngleLock write FAngleLock default False;
- end;
- (* TGLUserInterface is the component which reads the user input and transform it into action.
- The four calls to get you started is
- MouseLookActivate : set us up the bomb.
- MouseLookDeActivate : defuses it.
- Mouselook(deltaTime: double) : handles mouse look... Should be called in the Cadencer event. (Though it works every where!)
- MouseUpdate : Resets mouse position so that you don't notice that the mouse is limited to the screen should be called after Mouselook.
- The four properties to get you started are:
- InvertMouse : Inverts the mouse Y axis.
- MouseSpeed : Also known as mouse sensitivity.
- GLNavigator : The Navigator which receives the user movement.
- GLVertNavigator : The Navigator which if set receives the vertical user movement. Used mostly for cameras.... *)
- TGLUserInterface = class(TComponent)
- private
- FPrevPoint: TPoint;
- midScreenX, midScreenY: integer;
- FMouseActive: boolean;
- FMouseSpeed: single;
- FGLNavigator: TGLNavigator;
- FGLVertNavigator: TGLNavigator;
- FInvertMouse: boolean;
- procedure MouseInitialize;
- procedure SetMouseLookActive(const val: boolean);
- procedure setNavigator(val: TGLNavigator);
- procedure setVertNavigator(val: TGLNavigator);
- protected
- procedure Notification(AComponent: TComponent;
- Operation: TOperation); override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure MouseUpdate;
- function MouseLook: boolean;
- procedure MouseLookActiveToggle;
- procedure MouseLookActivate;
- procedure MouseLookDeactivate;
- function IsMouseLookOn: boolean;
- procedure TurnHorizontal(Angle: Double);
- procedure TurnVertical(Angle: Double);
- property MouseLookActive: boolean read FMouseActive
- write SetMouseLookActive;
- published
- property InvertMouse: boolean read FInvertMouse write FInvertMouse
- default False;
- property MouseSpeed: single read FMouseSpeed write FMouseSpeed;
- property GLNavigator: TGLNavigator read FGLNavigator write setNavigator;
- property GLVertNavigator: TGLNavigator read FGLVertNavigator
- write setVertNavigator;
- end;
- TGLNaviCube = class(TGLBaseSceneObject)
- private
- FDelta, FFps, FTimer, FInactiveTime: single;
- FCube: TGLDummyCube;
- FSel: integer;
- FSelPos: TGLVector;
- FCam, FNaviCam: TGLCamera;
- FHud: TGLHUDSprite;
- FMem: TGLMemoryViewer;
- FViewer: TGLSceneViewer;
- FReady, FMouse: boolean;
- FMouseRotation: boolean;
- FMousePos: TPoint;
- FPosAnimationStart: TGLVector;
- FPosAnimationEnd: TGLVector;
- public
- constructor CreateAsChild(aParentOwner: TGLBaseSceneObject); reintroduce;
- procedure DoProgress(const pt: TGProgressTimes); override;
- procedure DoRender(var ARci: TGLRenderContextInfo;
- ARenderSelf, ARenderChildren: boolean); override;
- property SceneViewer: TGLSceneViewer read FViewer write FViewer;
- property Camera: TGLCamera read FCam write FCam;
- property FPS: single read FFps write FFps;
- property ActiveMouse: boolean read FMouse write FMouse;
- property InactiveTime: single read FInactiveTime write FInactiveTime;
- end;
- var
- sW2, sH2: integer;
- // -------------------------------------------------------------
- implementation
- // -------------------------------------------------------------
- constructor TGLNavigator.Create(AOwner: TComponent);
- begin
- inherited;
- FVirtualUp := TGCoordinates.CreateInitialized(Self, ZHmgVector, csPoint);
- FCurrentVAngle := 0;
- FCurrentHAngle := 0;
- end;
- destructor TGLNavigator.Destroy;
- begin
- FVirtualUp.Free;
- inherited;
- end;
- procedure TGLNavigator.SetObject(NewObject: TGLBaseSceneObject);
- begin
- If FObject <> NewObject then
- begin
- If Assigned(FObject) then
- FObject.RemoveFreeNotification(Self);
- FObject := NewObject;
- If Assigned(FObject) then
- begin
- if csdesigning in componentstate then
- begin
- If VectorLength(FVirtualUp.AsVector) = 0 then
- begin
- FVirtualUp.AsVector := FObject.Up.AsVector;
- end;
- Exit;
- end;
- If FUseVirtualUp Then
- FVirtualRight := CalcRight;
- FObject.FreeNotification(Self);
- end;
- end;
- end;
- procedure TGLNavigator.Notification(AComponent: TComponent;
- Operation: TOperation);
- begin
- If Operation = opRemove then
- If AComponent = FObject then
- MovingObject := Nil;
- inherited;
- end;
- Function TGLNavigator.CalcRight: TGLVector;
- begin
- If Assigned(FObject) then
- If FUseVirtualUp Then
- begin
- VectorCrossProduct(FObject.Direction.AsVector,
- FVirtualUp.AsVector, Result);
- ScaleVector(Result, 1 / VectorLength(Result));
- End
- else
- VectorCrossProduct(FObject.Direction.AsVector, FObject.Up.AsVector,
- Result); { automaticly length(1), if not this is a bug }
- end;
- procedure TGLNavigator.TurnHorizontal(Angle: single);
- Var
- T: TGLVector;
- U: TAffineVector;
- TempVal: single;
- begin
- If InvertHorizontalSteeringWhenUpsideDown and
- ((CurrentVAngle < -90) or (CurrentVAngle > 90)) then
- Angle := -Angle;
- FCurrentHAngle := (FCurrentHAngle - Angle);
- If (FCurrentHAngle < 0) or (FCurrentHAngle > 360) then
- begin
- TempVal := (FCurrentHAngle) / 360;
- FCurrentHAngle := (TempVal - Floor(TempVal)) * 360;
- end;
- Angle := DegToRadian(Angle); { make it ready for Cos and Sin }
- If FUseVirtualUp Then
- begin
- SetVector(U, VirtualUp.AsVector);
- T := FObject.Up.AsVector;
- RotateVector(T, U, Angle);
- FObject.Up.AsVector := T;
- T := FObject.Direction.AsVector;
- RotateVector(T, U, Angle);
- FObject.Direction.AsVector := T;
- End
- else
- FObject.Direction.AsVector := VectorCombine(FObject.Direction.AsVector,
- CalcRight, Cos(Angle), Sin(Angle));
- end;
- procedure TGLNavigator.TurnVertical(Angle: single);
- Var
- ExpectedAngle: single;
- CosAngle, SinAngle: single;
- TempVal: single;
- Direction: TGLVector;
- begin
- ExpectedAngle := FCurrentVAngle + Angle;
- If FAngleLock then
- begin
- If ExpectedAngle > FMaxAngle then
- begin
- If FCurrentVAngle = FMaxAngle then
- Exit;
- Angle := FMaxAngle - FCurrentVAngle;
- ExpectedAngle := FMaxAngle;
- End
- else
- begin
- If ExpectedAngle < FMinAngle then
- begin
- If FCurrentVAngle = FMinAngle then
- Exit;
- Angle := FMinAngle - FCurrentVAngle;
- ExpectedAngle := FMinAngle;
- end;
- end;
- end;
- FCurrentVAngle := ExpectedAngle;
- If (FCurrentVAngle < -180) or (FCurrentVAngle > 180) then
- begin
- TempVal := (FCurrentVAngle + 180) / 360;
- FCurrentVAngle := (TempVal - Floor(TempVal)) * 360 - 180;
- end;
- Angle := DegToRadian(Angle); { make it ready for Cos and Sin }
- SinCosine(Angle, SinAngle, CosAngle);
- Direction := VectorCombine(MovingObject.Direction.AsVector,
- MovingObject.Up.AsVector, CosAngle, SinAngle);
- MovingObject.Up.AsVector := VectorCombine(MovingObject.Direction.AsVector,
- MovingObject.Up.AsVector, SinAngle, CosAngle);
- MovingObject.Direction.AsVector := Direction;
- end;
- procedure TGLNavigator.MoveForward(Distance: single);
- begin
- If (FUseVirtualUp and (not MoveUpWhenMovingForward)) Then
- begin
- FObject.Position.AsVector := VectorCombine(FObject.Position.AsVector,
- VectorCrossProduct(FVirtualUp.AsVector, CalcRight), 1, Distance);
- End
- else
- FObject.Position.AsVector := VectorCombine(FObject.Position.AsVector,
- FObject.Direction.AsVector, 1, Distance);
- end;
- procedure TGLNavigator.StrafeHorizontal(Distance: single);
- begin
- FObject.Position.AsVector := VectorCombine(FObject.Position.AsVector,
- CalcRight, 1, Distance);
- end;
- procedure TGLNavigator.StrafeVertical(Distance: single);
- begin
- If UseVirtualUp Then
- begin
- FObject.Position.AsVector := VectorCombine(FObject.Position.AsVector,
- FVirtualUp.AsVector, 1, Distance);
- End
- else
- FObject.Position.AsVector := VectorCombine(FObject.Position.AsVector,
- FObject.Up.AsVector, 1, Distance);
- end;
- procedure TGLNavigator.FlyForward(Distance: single);
- begin
- FObject.Position.AsVector := VectorCombine(FObject.Position.AsVector,
- FObject.Direction.AsVector, 1, Distance);
- end;
- procedure TGLNavigator.Straighten;
- Var
- R: TGLVector;
- D: TGLVector;
- A: single;
- begin
- FCurrentVAngle := 0;
- FCurrentHAngle := 0;
- R := CalcRight;
- A := VectorAngleCosine(AffineVectorMake(MovingObject.Up.AsVector),
- AffineVectorMake(VirtualUp.AsVector));
- MovingObject.Up.AsVector := VirtualUp.AsVector;
- VectorCrossProduct(R, FVirtualUp.AsVector, D);
- If A >= 0 then
- ScaleVector(D, -1 / VectorLength(D))
- else
- ScaleVector(D, 1 / VectorLength(D));
- MovingObject.Direction.AsVector := D;
- end;
- procedure TGLNavigator.SetUseVirtualUp(UseIt: boolean);
- begin
- FUseVirtualUp := UseIt;
- if csdesigning in componentstate then
- Exit;
- If FUseVirtualUp then
- FVirtualRight := CalcRight;
- end;
- procedure TGLNavigator.SetVirtualUp(Up: TGCoordinates);
- begin
- FVirtualUp.Assign(Up);
- if csdesigning in componentstate then
- Exit;
- If FUseVirtualUp then
- FVirtualRight := CalcRight;
- end;
- procedure TGLNavigator.LoadState(Stream: TStream);
- Var
- Vector: TAffineVector;
- B: ByteBool;
- S: single;
- begin
- Stream.Read(Vector, SizeOf(TAffineVector));
- FObject.Position.AsAffineVector := Vector;
- Stream.Read(Vector, SizeOf(TAffineVector));
- FObject.Direction.AsAffineVector := Vector;
- Stream.Read(Vector, SizeOf(TAffineVector));
- FObject.Up.AsAffineVector := Vector;
- Stream.Read(B, SizeOf(ByteBool));
- UseVirtualUp := B;
- Stream.Read(B, SizeOf(ByteBool));
- FAngleLock := B;
- Stream.Read(S, SizeOf(single));
- FMaxAngle := S;
- Stream.Read(S, SizeOf(single));
- FMinAngle := S;
- Stream.Read(S, SizeOf(single));
- FCurrentVAngle := S;
- Stream.Read(S, SizeOf(single));
- FCurrentHAngle := S;
- end;
- procedure TGLNavigator.SaveState(Stream: TStream);
- Var
- Vector: TAffineVector;
- B: ByteBool;
- S: single;
- begin
- Vector := FObject.Position.AsAffineVector;
- Stream.Write(Vector, SizeOf(TAffineVector));
- Vector := FObject.Direction.AsAffineVector;
- Stream.Write(Vector, SizeOf(TAffineVector));
- Vector := FObject.Up.AsAffineVector;
- Stream.Write(Vector, SizeOf(TAffineVector));
- B := UseVirtualUp;
- Stream.Write(B, SizeOf(ByteBool));
- B := FAngleLock;
- Stream.Write(B, SizeOf(ByteBool));
- S := FMaxAngle;
- Stream.Write(S, SizeOf(single));
- S := FMinAngle;
- Stream.Write(S, SizeOf(single));
- S := FCurrentVAngle;
- Stream.Write(S, SizeOf(single));
- S := FCurrentHAngle;
- Stream.Write(S, SizeOf(single));
- end;
- function TGLUserInterface.IsMouseLookOn: boolean;
- begin
- Result := FMouseActive;
- end;
- procedure TGLUserInterface.TurnHorizontal(Angle: Double);
- begin
- GLNavigator.TurnHorizontal(Angle);
- end;
- procedure TGLUserInterface.TurnVertical(Angle: Double);
- begin
- If Assigned(GLVertNavigator) then
- GLVertNavigator.TurnVertical(Angle)
- else
- GLNavigator.TurnVertical(Angle);
- end;
- procedure TGLUserInterface.MouseLookActiveToggle;
- begin
- if FMouseActive then
- MouseLookDeactivate
- else
- MouseLookActivate;
- end;
- procedure TGLUserInterface.MouseLookActivate;
- begin
- if not FMouseActive then
- begin
- FMouseActive := True;
- MouseInitialize;
- GLShowCursor(False);
- end;
- end;
- procedure TGLUserInterface.MouseLookDeactivate;
- begin
- if FMouseActive then
- begin
- FMouseActive := False;
- GLShowCursor(True);
- end;
- end;
- procedure TGLUserInterface.MouseInitialize;
- begin
- midScreenX := GLGetScreenWidth div 2;
- midScreenY := GLGetScreenHeight div 2;
- FPrevPoint.x := midScreenX;
- FPrevPoint.Y := midScreenY;
- GLSetCursorPos(midScreenX, midScreenY);
- end;
- procedure TGLUserInterface.SetMouseLookActive(const val: boolean);
- begin
- if val <> FMouseActive then
- if val then
- MouseLookActivate
- else
- MouseLookDeactivate;
- end;
- procedure TGLUserInterface.MouseUpdate;
- begin
- if FMouseActive then
- GLGetCursorPos(FPrevPoint);
- end;
- function TGLUserInterface.MouseLook: boolean;
- var
- deltaX, deltaY: single;
- begin
- Result := False;
- if not FMouseActive then
- Exit;
- deltaX := (FPrevPoint.x - midScreenX) * MouseSpeed;
- deltaY := -(FPrevPoint.Y - midScreenY) * MouseSpeed;
- If InvertMouse then
- deltaY := -deltaY;
- if deltaX <> 0 then
- begin
- TurnHorizontal(deltaX * 0.01);
- Result := True;
- end;
- if deltaY <> 0 then
- begin
- TurnVertical(deltaY * 0.01);
- Result := True;
- end;
- if (FPrevPoint.x <> midScreenX) or (FPrevPoint.Y <> midScreenY) then
- GLSetCursorPos(midScreenX, midScreenY);
- end;
- constructor TGLUserInterface.Create(AOwner: TComponent);
- begin
- inherited;
- FMouseSpeed := 0;
- FMouseActive := False;
- midScreenX := GLGetScreenWidth div 2;
- midScreenY := GLGetScreenHeight div 2;
- FPrevPoint.x := midScreenX;
- FPrevPoint.Y := midScreenY;
- end;
- destructor TGLUserInterface.Destroy;
- begin
- if FMouseActive then
- MouseLookDeactivate; // added by JAJ
- inherited;
- end;
- procedure TGLUserInterface.Notification(AComponent: TComponent;
- Operation: TOperation);
- begin
- if Operation = opRemove then
- begin
- if AComponent = FGLNavigator then
- setNavigator(nil);
- if AComponent = FGLVertNavigator then
- setVertNavigator(nil);
- end;
- inherited;
- end;
- procedure TGLUserInterface.setNavigator(val: TGLNavigator);
- begin
- if Assigned(FGLNavigator) then
- FGLNavigator.RemoveFreeNotification(Self);
- FGLNavigator := val;
- if Assigned(val) then
- val.FreeNotification(Self);
- end;
- procedure TGLUserInterface.setVertNavigator(val: TGLNavigator);
- begin
- if Assigned(FGLVertNavigator) then
- FGLVertNavigator.RemoveFreeNotification(Self);
- FGLVertNavigator := val;
- if Assigned(val) then
- val.FreeNotification(Self);
- end;
- constructor TGLNaviCube.CreateAsChild(aParentOwner: TGLBaseSceneObject);
- procedure genTex(S: string; mat: TGLMaterial);
- var
- bmp: TBitmap;
- begin
- bmp := TBitmap.Create;
- bmp.Width := 64;
- bmp.Height := 64;
- with bmp.Canvas do
- begin
- Font.Name := 'Verdana';
- Font.Size := 10;
- TextOut(32 - TextWidth(S) div 2, 24, S);
- end;
- mat.FrontProperties.Diffuse.SetColor(1, 1, 1);
- mat.Texture.Image.Assign(bmp);
- mat.Texture.Disabled := False;
- mat.Texture.FilteringQuality := tfAnisotropic;
- mat.Texture.TextureMode := tmModulate;
- bmp.Free;
- end;
- procedure SetColor(m: TGLMaterial; c: single);
- begin
- m.FrontProperties.Diffuse.SetColor(c, c, 1);
- end;
- procedure addPlane(T: integer; ttl: string; c, x, Y, z, dx, dy, dz: single);
- begin
- with TGLPlane.CreateAsChild(FCube) do
- begin
- tag := T;
- tagfloat := c;
- Position.SetPoint(x, Y, z);
- Direction.SetVector(dx, dy, dz);
- genTex(ttl, Material);
- end;
- end;
- procedure addCube(T: integer; c, x, Y, z, sx, sy, sz: single);
- begin
- with TGLCube.CreateAsChild(FCube) do
- begin
- tag := T;
- tagfloat := c;
- Position.SetPoint(x, Y, z);
- Scale.SetVector(sx, sy, sz);
- SetColor(Material, c);
- end;
- end;
- begin
- inherited CreateAsChild(aParentOwner);
- FDelta := 2;
- FFps := 30;
- FTimer := 10;
- FMouse := True;
- FInactiveTime := 0;
- FHud := TGLHUDSprite.CreateAsChild(Self);
- FHud.Width := 128;
- FHud.Height := 128;
- FHud.Material.BlendingMode := bmTransparency;
- with FHud.Material.Texture do
- begin
- Disabled := False;
- ImageClassName := 'TGLBlankImage';
- MinFilter := miNearest;
- TGLBlankImage(Image).Width := 128;
- TGLBlankImage(Image).Height := 128;
- TextureMode := tmReplace;
- end;
- FHud.Position.SetPoint(-200, 50, 0);
- FNaviCam := TGLCamera.CreateAsChild(aParentOwner);
- FNaviCam.FocalLength := 55;
- FNaviCam.TargetObject := Self;
- FMem := TGLMemoryViewer.Create(aParentOwner);
- FMem.Width := 128;
- FMem.Height := 128;
- FMem.Camera := FNaviCam;
- with FMem.Buffer do
- begin
- BackgroundAlpha := 0;
- Antialiasing := aa6x;
- ContextOptions := [roDestinationAlpha];
- Lighting := False;
- end;
- FCube := TGLDummyCube.CreateAsChild(Self);
- FCube.Visible := False;
- with TGLDisk.CreateAsChild(FCube) do
- begin
- Position.SetPoint(0, -0.805, 0);
- Direction.SetVector(0, 1, 0);
- InnerRadius := 0.9;
- OuterRadius := 1.3;
- Slices := 60;
- Loops := 1;
- SetColor(Material, 0.6);
- end;
- with TGLDisk.CreateAsChild(FCube) do
- begin
- Position.SetPoint(0, -0.8, 0);
- Direction.SetVector(0, 1, 0);
- InnerRadius := 0.95;
- OuterRadius := 1.25;
- Slices := 60;
- Loops := 1;
- SetColor(Material, 1);
- end;
- addPlane(0, 'FRONT', 1, 0, 0, 0.7, 0, 0, 1);
- addPlane(1, 'RIGHT', 1, 0.7, 0, 0, 1, 0, 0);
- addPlane(2, 'LEFT', 1, -0.7, 0, 0, -1, 0, 0);
- addPlane(3, 'BACK', 1, 0, 0, -0.7, 0, 0, -1);
- addPlane(4, 'TOP', 1, 0, 0.7, 0, 0, 1, 0);
- addPlane(5, 'BOTTOM', 1, 0, -0.7, 0, 0, -1, 0);
- addCube(6, 0.9, 0, 0.6, 0.6, 1, 0.2, 0.2);
- addCube(7, 0.9, 0, 0.6, -0.6, 1, 0.2, 0.2);
- addCube(8, 0.9, 0, -0.6, 0.6, 1, 0.2, 0.2);
- addCube(9, 0.9, 0, -0.6, -0.6, 1, 0.2, 0.2);
- addCube(10, 0.9, 0.6, 0.6, 0, 0.2, 0.2, 1);
- addCube(11, 0.9, 0.6, -0.6, 0, 0.2, 0.2, 1);
- addCube(12, 0.9, -0.6, 0.6, 0, 0.2, 0.2, 1);
- addCube(13, 0.9, -0.6, -0.6, 0, 0.2, 0.2, 1);
- addCube(14, 0.9, 0.6, 0, 0.6, 0.2, 1, 0.2);
- addCube(15, 0.9, 0.6, 0, -0.6, 0.2, 1, 0.2);
- addCube(16, 0.9, -0.6, 0, 0.6, 0.2, 1, 0.2);
- addCube(17, 0.9, -0.6, 0, -0.6, 0.2, 1, 0.2);
- addCube(18, 0.8, 0.6, 0.6, 0.6, 0.2, 0.2, 0.2);
- addCube(19, 0.8, 0.6, 0.6, -0.6, 0.2, 0.2, 0.2);
- addCube(20, 0.8, 0.6, -0.6, 0.6, 0.2, 0.2, 0.2);
- addCube(21, 0.8, -0.6, 0.6, 0.6, 0.2, 0.2, 0.2);
- addCube(22, 0.8, 0.6, -0.6, -0.6, 0.2, 0.2, 0.2);
- addCube(23, 0.8, -0.6, -0.6, 0.6, 0.2, 0.2, 0.2);
- addCube(24, 0.8, -0.6, 0.6, -0.6, 0.2, 0.2, 0.2);
- addCube(25, 0.8, -0.6, -0.6, -0.6, 0.2, 0.2, 0.2);
- end;
- procedure TGLNaviCube.DoProgress(const pt: TGProgressTimes);
- const
- tb: array [0 .. 1] of array [0 .. 3] of TGLVector = (((x: 0; Y: 20; z: 1;
- W: 0), (x: 1; Y: 20; z: 0; W: 0), (x: 0; Y: 20; z: - 1; W: 0), (x: - 1;
- Y: 20; z: 0; W: 0)), ((x: 0; Y: - 20; z: 1; W: 0), (x: 1; Y: - 20; z: 0;
- W: 0), (x: 0; Y: - 20; z: - 1; W: 0), (x: - 1; Y: - 20; z: 0; W: 0)));
- var
- mp: TPoint;
- mover: boolean;
- i: integer;
- v0, v1, v2, v: TGLVector;
- obj: TGLBaseSceneObject;
- procedure moveTo(trgv: TGLVector);
- begin
- FPosAnimationStart := FCam.Position.AsVector;
- FPosAnimationEnd := FCam.TargetObject.AbsoluteToLocal
- (VectorScale(VectorNormalize(trgv), FCam.DistanceToTarget));
- FDelta := 0;
- end;
- begin
- mp := FViewer.ScreenToClient(Mouse.CursorPos);
- mover := (mp.x > FHud.Position.x - 64) and (mp.x < FHud.Position.x + 64) and
- (mp.Y > FHud.Position.Y - 64) and (mp.Y < FHud.Position.Y + 64);
- // mouse Down/Up
- if FDelta > 1 then
- begin
- if IsKeyDown(VK_LBUTTON) and (not FMouseRotation) then
- begin
- // selection > start auto rotation
- if mover and (FSel >= 0) then
- begin
- v := FCam.AbsoluteVectorToTarget;
- v.Y := 0;
- if v.x < 0 then
- i := -1
- else
- i := 1;
- i := round((ArcCosine(VectorAngleCosine(v, ZHmgPoint)) * i + PI) / PI
- * 2) mod 4;
- if (FSel = 4) or (FSel = 5) then
- moveTo(tb[FSel - 4][i])
- else
- moveTo(FSelPos);
- FInactiveTime := 0;
- end // start manual rotation
- else if FMouse then
- begin
- FMouseRotation := True;
- FMousePos := Mouse.CursorPos;
- ShowCursor(False);
- Mouse.CursorPos := point(sW2, sH2);
- FInactiveTime := 0;
- end;
- end;
- // stop rotation, restore cursor
- if (not IsKeyDown(VK_LBUTTON)) and FMouseRotation and FMouse then
- begin
- ShowCursor(True);
- FMouseRotation := False;
- Mouse.CursorPos := FMousePos;
- FInactiveTime := 0;
- end;
- end
- // auto rotation progress
- else
- begin
- FDelta := FDelta + pt.deltaTime * 2;
- v := VectorLerp(FPosAnimationStart, FPosAnimationEnd,
- FDelta * FDelta * (3 - 2 * FDelta));
- v := VectorScale(VectorNormalize(v), VectorLength(FPosAnimationStart));
- if FDelta < 1 then
- FCam.Position.SetPoint(v)
- else
- FCam.Position.SetPoint(FPosAnimationEnd);
- v := VectorScale(VectorNormalize(v), 10);
- if FDelta < 1 then
- v := VectorScale(VectorNormalize(v), 10)
- else
- v := VectorScale(VectorNormalize(FPosAnimationEnd), 10);
- FNaviCam.Position.SetPoint(v);
- for i := 2 to FCube.Count - 1 do
- with TGLSceneObject(FCube.Children[i]) do
- Material.FrontProperties.Diffuse.SetColor(tagfloat, tagfloat, 1);
- FInactiveTime := 0;
- end;
- FSel := -1;
- // manual rotation progress
- if FMouseRotation and FMouse then
- begin
- mp := Mouse.CursorPos;
- if FCam <> nil then
- FCam.MoveAroundTarget((sH2 - mp.Y) * 0.2, (sW2 - mp.x) * 0.2);
- FNaviCam.MoveAroundTarget((sH2 - mp.Y) * 0.2, (sW2 - mp.x) * 0.2);
- Mouse.CursorPos := point(sW2, sH2);
- FInactiveTime := 0;
- end
- else if FReady then
- begin
- // selection
- if mover and (FDelta > 1) then
- begin
- v0 := FNaviCam.AbsolutePosition;
- v1 := FMem.Buffer.ScreenToVector(mp.x - round(FHud.Position.x) + 64,
- round(FHud.Position.Y) - mp.Y + 64);
- SetVector(v2, 99999, 99999, 99999);
- obj := nil;
- for i := 2 to FCube.Count - 1 do
- with TGLSceneObject(FCube.Children[i]) do
- begin
- Material.FrontProperties.Diffuse.SetColor(tagfloat, tagfloat, 1);
- if RayCastIntersect(v0, v1, @v) then
- if VectorDistance2(v2, v0) > VectorDistance2(v, v0) then
- begin
- SetVector(v2, v);
- FSel := FCube.Children[i].tag;
- FSelPos := FCube.Children[i].Position.AsVector;
- obj := FCube.Children[i];
- end;
- end;
- if FSel >= 0 then
- begin
- FViewer.cursor := -21;
- TGLSceneObject(obj).Material.FrontProperties.Diffuse.SetColor
- (1, 0.6, 0);
- end
- else
- FViewer.cursor := 0;
- end;
- v := VectorScale(VectorNormalize(FCam.AbsoluteVectorToTarget), 10);
- FNaviCam.Position.SetPoint(VectorNegate(v));
- FInactiveTime := FInactiveTime + pt.deltaTime;
- end;
- // rendering
- FTimer := FTimer + pt.deltaTime;
- if FTimer > 1 / FFps then
- begin
- FTimer := FTimer - Floor(FTimer * FFps) / FFps;
- FMem.Render(FCube);
- FMem.CopyToTexture(FHud.Material.Texture);
- FReady := True;
- end;
- end;
- procedure TGLNaviCube.DoRender(var ARci: TGLRenderContextInfo;
- ARenderSelf, ARenderChildren: boolean);
- begin
- inherited;
- if (FCam = nil) and (Scene.CurrentGLCamera <> nil) then
- begin
- FCam := Scene.CurrentGLCamera;
- FNaviCam.Position.SetPoint
- (VectorScale(VectorNormalize(FCam.Position.AsVector), 10));
- end;
- if FViewer <> nil then
- FHud.Position.SetPoint(FViewer.Width - 80, 50, 0);
- end;
- // ------------------------------------------------
- initialization
- // ------------------------------------------------
- sW2 := Screen.Width div 2;
- sH2 := Screen.Height div 2;
- end.
|