Skip to content
Browse files

Camera and Navigation are split into 2 properties and 2 classes

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 fcc298544eb439da25b46e64ca1c10bef495c5a2

Large diffs are not rendered by default.

@@ -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;
@@ -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. }
@@ -2605,7 +2605,7 @@ procedure TCastleTransform.VisibleChangeNotification(const Changes: TVisibleChan

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

procedure TSceneManagerWorld.CameraChanged(ACamera: TCamera);
procedure TSceneManagerWorld.CameraChanged(const ACamera: TCastleCamera);
ACamera.GetView(FCameraPosition, FCameraDirection, FCameraUp);
FCameraKnown := true;
@@ -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
@@ -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.
@@ -290,7 +290,7 @@ begin
Move(RotationInverseMatrix.Data[2], Result.Data[2], SizeOf(Single) * 3);

procedure TRenderingCamera.FromCameraObject(const ACamera: TCamera;
procedure TRenderingCamera.FromCameraObject(const ACamera: TCastleCamera;
const IgnoredViewpoint: TObject = nil);
Matrix := ACamera.Matrix;
@@ -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;
@@ -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. }
instead of using AssignDefaultNavigation and then switching to ntWalk. }

procedure TCastle2DSceneManager.AssignDefaultCamera;
procedure TCastle2DSceneManager.AssignDefaultNavigation;
{ 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;
{ pos } Vector3(0, 0, DefaultCameraZ),
{ dir } Vector3(0, 0, -1),
{ up } Vector3(0, 1, 0), false);
Camera.Radius := 0.01; { will not be used for anything, but set to something sensible just in case }
Navigation.Radius := 0.01; { will not be used for anything, but set to something sensible just in case }

function TCastle2DSceneManager.PositionTo2DWorld(const Position: TVector2;
@@ -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),
@@ -285,7 +285,7 @@ function TCastle2DSceneManager.PositionTo2DWorld(const Position: TVector2;
P := Position * UIScale + RenderRect.LeftBottom
P := Position;
RequiredCamera.CustomRay(RenderRect, P, Projection, RayOrigin, RayDirection);
RequiredNavigation.CustomRay(RenderRect, P, Projection, RayOrigin, RayDirection);
Result := RayOrigin.XY;
end; }

@@ -300,7 +300,7 @@ function TCastle2DSceneManager.PositionTo2DWorld(const Position: TVector2;
ScreenToWorldMatrix: TMatrix4;
P: TVector2;
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.');
@@ -841,7 +841,7 @@ procedure TGameSceneManager.LoadLevelCore(const AInfo: TLevelInfo);
WalkCamera.MoveVerticalSpeed := 20;

Camera := WalkCamera;
Navigation := WalkCamera;

WalkCamera.Init(InitialPosition, InitialDirection,
InitialUp, GravityUp, PreferredHeight, CameraRadius);
@@ -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);

0 comments on commit fcc2985

Please sign in to comment.
You can’t perform that action at this time.