Skip to content

Commit

Permalink
Camera and Navigation are split into 2 properties and 2 classes
Browse files Browse the repository at this point in the history
Camera holds the viewer position/dir/up.
It is automatically created with each viewport.

Navigation reacts to user input, changing camera.
It may be, but doesn't have to be, assigned to a viewport.
It's more-or-less a normal TCastleUserInterface descendant.
  • Loading branch information
michaliskambi committed Jul 20, 2019
1 parent 7371573 commit fcc2985
Show file tree
Hide file tree
Showing 10 changed files with 1,489 additions and 1,230 deletions.
1,977 changes: 1,094 additions & 883 deletions src/3d/castlecameras.pas

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions src/3d/castletransform.pas
Expand Up @@ -1009,7 +1009,7 @@ TCastleTransform = class(TCastleComponent)
{ Main camera observing this 3D object changed.
This is usually called by our container (like TCastleSceneManager)
to notify that camera changed. }
procedure CameraChanged(ACamera: TCamera); virtual;
procedure CameraChanged(const ACamera: TCastleCamera); virtual;

{ Mouse cursor over this object. }
property Cursor: TMouseCursor read FCursor write SetCursor default mcDefault;
Expand Down Expand Up @@ -1864,7 +1864,7 @@ TSceneManagerWorld = class(TCastleTransform)
property CameraKnown: boolean read FCameraKnown;
{ @groupEnd }

procedure CameraChanged(ACamera: TCamera); override;
procedure CameraChanged(const ACamera: TCastleCamera); override;

{ Yoo can temporarily disable physics (no transformations will be updated
by the physics engine) by setting this property to @false. }
Expand Down Expand Up @@ -2605,7 +2605,7 @@ procedure TCastleTransform.VisibleChangeNotification(const Changes: TVisibleChan
List[I].VisibleChangeNotification(Changes);
end;

procedure TCastleTransform.CameraChanged(ACamera: TCamera);
procedure TCastleTransform.CameraChanged(const ACamera: TCastleCamera);
var
I: Integer;
begin
Expand Down Expand Up @@ -3393,7 +3393,7 @@ function TSceneManagerWorld.WorldPointCollision2D(const Point: TVector2): boolea
Result := PointCollision2D(Point, nil);
end;

procedure TSceneManagerWorld.CameraChanged(ACamera: TCamera);
procedure TSceneManagerWorld.CameraChanged(const ACamera: TCastleCamera);
begin
ACamera.GetView(FCameraPosition, FCameraDirection, FCameraUp);
FCameraKnown := true;
Expand Down
8 changes: 4 additions & 4 deletions src/3d/castletransform_renderparams.inc
Expand Up @@ -90,7 +90,7 @@
This is interesting to you only if you write custom rendering code.
In normal applications, you shoud only get/set camera using TCamera
In normal applications, you shoud only get/set camera using TCastleCamera
descendants, through TCastleAbstractViewport.Camera and related properties.
Do not use the TRenderingCamera class in normal applications. }
TRenderingCamera = class
Expand Down Expand Up @@ -147,11 +147,11 @@
function RotationMatrix3: TMatrix3;
function RotationInverseMatrix3: TMatrix3;

{ Set all properties (except Target) from TCamera instance in ACamera.
{ Set all properties (except Target) from TCastleCamera instance in ACamera.
See @link(FromMatrix) for comments about @link(Target) property.
The IgnoredViewpoint parameter is only for backward compatibility,
it is ignored. }
procedure FromCameraObject(const ACamera: TCamera;
procedure FromCameraObject(const ACamera: TCastleCamera;
const IgnoredViewpoint: TObject = nil);

{ Set all properties (except Target) from explict matrices.
Expand Down Expand Up @@ -290,7 +290,7 @@ begin
Move(RotationInverseMatrix.Data[2], Result.Data[2], SizeOf(Single) * 3);
end;

procedure TRenderingCamera.FromCameraObject(const ACamera: TCamera;
procedure TRenderingCamera.FromCameraObject(const ACamera: TCastleCamera;
const IgnoredViewpoint: TObject = nil);
begin
Matrix := ACamera.Matrix;
Expand Down
28 changes: 14 additions & 14 deletions src/game/castle2dscenemanager.pas
Expand Up @@ -83,7 +83,7 @@ TCastle2DSceneManager = class(TCastleSceneManager)
DefaultCameraZ = DefaultProjectionSpan / 2;

constructor Create(AOwner: TComponent); override;
procedure AssignDefaultCamera; override;
procedure AssignDefaultNavigation; override;

property CurrentProjectionWidth: Single read FCurrentProjectionWidth;
property CurrentProjectionHeight: Single read FCurrentProjectionHeight;
Expand Down Expand Up @@ -221,24 +221,24 @@ constructor TCastle2DSceneManager.Create(AOwner: TComponent);
FProjectionWidth := 0;

{ Make camera already existing, so WalkCamera returns it,
instead of using AssignDefaultCamera and then switching to ntWalk. }
AssignDefaultCamera;
instead of using AssignDefaultNavigation and then switching to ntWalk. }
AssignDefaultNavigation;
end;

procedure TCastle2DSceneManager.AssignDefaultCamera;
procedure TCastle2DSceneManager.AssignDefaultNavigation;
begin
{ Set Camera explicitly, otherwise SetNavigationType below could call
ExamineCamera / WalkCamera that call AssignDefaultCamera when Camera = nil,
and we would have infinite AssignDefaultCamera calls loop. }
Camera := InternalWalkCamera;
ExamineCamera / WalkCamera that call AssignDefaultNavigation when Camera = nil,
and we would have infinite AssignDefaultNavigation calls loop. }
Navigation := InternalWalkNavigation;

NavigationType := ntNone;
Camera.SetInitialView(
Navigation.SetInitialView(
{ pos } Vector3(0, 0, DefaultCameraZ),
{ dir } Vector3(0, 0, -1),
{ up } Vector3(0, 1, 0), false);
Camera.GoToInitial;
Camera.Radius := 0.01; { will not be used for anything, but set to something sensible just in case }
Navigation.GoToInitial;
Navigation.Radius := 0.01; { will not be used for anything, but set to something sensible just in case }
end;

function TCastle2DSceneManager.PositionTo2DWorld(const Position: TVector2;
Expand All @@ -262,8 +262,8 @@ function TCastle2DSceneManager.PositionTo2DWorld(const Position: TVector2;
raise Exception.Create('TCastle2DSceneManager.PositionTo2DWorld assumes an orthographic projection, like the one set by TCastle2DSceneManager.CalculateProjection');
ProjRect := Proj.Dimensions;
if Camera <> nil then
ProjRect := ProjRect.Translate(Camera.Position.XY);
if Navigation <> nil then
ProjRect := ProjRect.Translate(Navigation.Position.XY);
Result := Vector2(
MapRange(P.X, 0, EffectiveWidth , ProjRect.Left , ProjRect.Right),
Expand All @@ -285,7 +285,7 @@ function TCastle2DSceneManager.PositionTo2DWorld(const Position: TVector2;
P := Position * UIScale + RenderRect.LeftBottom
else
P := Position;
RequiredCamera.CustomRay(RenderRect, P, Projection, RayOrigin, RayDirection);
RequiredNavigation.CustomRay(RenderRect, P, Projection, RayOrigin, RayDirection);
Result := RayOrigin.XY;
end; }

Expand All @@ -300,7 +300,7 @@ function TCastle2DSceneManager.PositionTo2DWorld(const Position: TVector2;
ScreenToWorldMatrix: TMatrix4;
P: TVector2;
begin
WorldToScreenMatrix := RequiredCamera.ProjectionMatrix * RequiredCamera.Matrix;
WorldToScreenMatrix := RequiredNavigation.ProjectionMatrix * RequiredNavigation.Matrix;
if not WorldToScreenMatrix.TryInverse(ScreenToWorldMatrix) then
raise Exception.Create('Cannot invert projection * camera matrix. Possibly one of them was not initialized, or camera contains scale to zero.');
Expand Down
4 changes: 2 additions & 2 deletions src/game/castlelevels.pas
Expand Up @@ -841,7 +841,7 @@ procedure TGameSceneManager.LoadLevelCore(const AInfo: TLevelInfo);
WalkCamera.MoveVerticalSpeed := 20;
end;

Camera := WalkCamera;
Navigation := WalkCamera;

WalkCamera.Init(InitialPosition, InitialDirection,
InitialUp, GravityUp, PreferredHeight, CameraRadius);
Expand Down Expand Up @@ -875,7 +875,7 @@ procedure TGameSceneManager.LoadLevelCore(const AInfo: TLevelInfo);
Otherwise, it would be updated by MainScene loading binding new
NavigationInfo (with it's speed) and Viewpoint.
We prefer to do it ourselves in InitializeCamera. }
Camera := nil;
Navigation := nil;

MainScene := TCastleScene.Create(Self);
Inc(MainScene.InternalDirty);
Expand Down

0 comments on commit fcc2985

Please sign in to comment.