| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904 |
- //
- // This unit is part of the GLScene Engine, http://glscene.org
- //
- unit GLNavigator;
- (* Unit for navigating GLBaseObjects and GLSceneViewer. *)
- interface
- {$I GLScene.inc}
- uses
- Winapi.Windows,
- System.Types,
- System.Classes,
- System.SysUtils,
- System.Math,
- Vcl.Controls,
- Vcl.Graphics,
- Vcl.Forms,
- GLScene,
- GLObjects,
- GLGeomObjects,
- GLContext,
- GLBaseClasses,
- GLPersistentClasses,
- GLVectorGeometry,
- GLHUDObjects,
- GLCoordinates,
- GLScreen,
- GLKeyBoard,
- GLVectorTypes,
- GLMaterial,
- GLTexture,
- GLTextureFormat,
- GLSceneViewer,
- GLRenderContextInfo;
- 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: TVector;
- FVirtualUp: TGLCoordinates;
- 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: TGLCoordinates);
- function CalcRight: TVector;
- 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: TGLCoordinates 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: TVector;
- FCam, FNaviCam: TGLCamera;
- FHud: TGLHUDSprite;
- FMem: TGLMemoryViewer;
- FViewer: TGLSceneViewer;
- FReady, FMouse: boolean;
- FMouseRotation: boolean;
- FMousePos: TPoint;
- FPosAnimationStart: TVector;
- FPosAnimationEnd: TVector;
- public
- constructor CreateAsChild(aParentOwner: TGLBaseSceneObject); reintroduce;
- procedure DoProgress(const pt: TGLProgressTimes); 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 := TGLCoordinates.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 : TVector;
- 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 : TVector;
- 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 : TVector;
- 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 : TVector;
- D : TVector;
- 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 : TGLCoordinates);
- 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: TGLProgressTimes);
- const
- tb: array [0 .. 1] of array [0 .. 3] of TVector = (((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: TVector;
- obj: TGLBaseSceneObject;
- procedure moveTo(trgv: TVector);
- 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.
|