Camera
We support the usage of TCamera and TGorillaCamera component. Both components work almost the same currently, but in the future they could differ significantly.
You can select the camera components from IDE components palette or create them at runtime.
If cameras are loaded from files like FBX, DAE or G3D the framework will create instances of TGorillaCamera and link the TCameraDef definition in the Def property of the camera.
Due to hardcoded Firemonkey restrictions the NearPlane and FarPlane property of TGorillaCamera has no effect yet, but in future we will solve this issue.
uses Gorilla.Camera; [...] /// Create a camera at runtime and activate it for rendering var FCamera : TGorillaCamera; /// Create the camera and attach it to the viewport as child component FCamera := TGorillaCamera.Create(GorillaViewport1); FCamera.Parent := GorillaViewport1; /// Is equivalent to "AngleOfView" property FCamera.FOV := 45; /// Set our new camera as active camera and disable design time camera GorillaViewport1.Camera := FCamera; GorillaViewport1.UsingDesignCamera := false;
Target
A very useful property of Firemonkey's TCamera component is the Target property. You can link the camera to another 3D object to always look at it. This will generate a view direction always towards the linked 3D object.
You can use this property for easy camera navigation in 3D space. Combine a camera component with a non-visual TDummy instance to navigate.
var FDummy : TDummy; var FCamera : TGorillaCamera; /// Create a dummy component FDummy := TDummy.Create(GorillaViewport1); FDummy.Parent := GorillaViewport1; /// Create the camera and attach it to the dummy! FCamera := TGorillaCamera.Create(FDummy); FCamera.Parent := FDummy; /// Set the dummy as viewing target and the camera will always look at it. FCamera.Target := FDummy; /// Set our camera as active camera and disable design time camera GorillaViewport1.Camera := FCamera; GorillaViewport1.UsingDesignCamera := false;
To navigate you can simple rotate the dummy around its y-axis and move the camera on y-axis up and down.
type TForm1 = class(TForm) GorillaViewport1: TGorillaViewport; FDummy: TDummy; FCamera: TGorillaCamera; private FIsMoving : Boolean; FLastPoint : TPointF; procedure DoOnViewportMouseUp(ASender : TObject; AButton : TMouseButton; AShift : TShiftState; X, Y : Single); procedure DoOnViewportMouseDown(ASender : TObject; AButton : TMouseButton; AShift : TShiftState; X, Y : Single); procedure DoOnViewportMouseMove(ASender : TObject; AShiftState : TShiftState; X, Y : Single); end; [...] procedure TForm1.FormCreate(Sender: TObject); begin GorillaViewport1.OnMouseUp := DoOnViewportMouseUp; GorillaViewport1.OnMouseDown := DoOnViewportMouseDown; GorillaViewport1.OnMouseMove := DoOnViewportMouseMove; [...] end; procedure TForm1.DoOnViewportMouseUp(ASender : TObject; AButton : TMouseButton; AShift : TShiftState; X, Y : Single); begin FIsMoving := false; end; procedure TForm1.DoOnViewportMouseDown(ASender : TObject; AButton : TMouseButton; AShift : TShiftState; X, Y : Single); begin FIsMoving := true; FLastPoint := PointF(X, Y); end; procedure TForm1.DoOnViewportMouseMove(ASender : TObject; AShiftState : TShiftState; X, Y : Single); var LDiff : TPointF; begin if FIsMoving then begin if (ssLeft in AShiftState) then begin LDiff := PointF(X, Y) - FLastPoint; /// Rotate around y-axis if left-right mouse movement FDummy.RotationAngle.Y := FDummy.RotationAngle.Y + LDiff.X; /// Move up and down, if up-down mouse movement /// We scale pixel offset down by 0.1 to move slowly FCamera.Position.Y := FCamera.Position.Y - LDiff.Y * 0.1; end; /// finally store the last mouse position FLastPoint := PointF(X, Y); end; end;
Frustum Culling
The viewing frustum is a geometric representation of the volume visible to the virtual camera. Naturally, objects outside this volume will not be visible in the final image, so they are discarded.
Read more about here: Frustum Culling
Smooth Camera Controller
Since version 0.8.4.2341 a TGorillaViewport component provides an embedded TGorillaSmoothCameraController component with automatic mouse feedback integration. This means: In case TGorillaViewport.UsingDesignCamera is set to TRUE, the viewport will register OnMouseDown, OnMouseUp and OnMouseMove events and forward those events to the embedded TGorillaSmoothCameraController.
This enables an easy-to-use mouse navigation for your 3D scene without any effort. The smooth camera controller supports the following control:
- Rotation around Y-axis
- Rotation around X-axis (moving up / down)
- Zooming in / out
- Shifting / Translating on X-, Y- and Z-axis
It is called “Smooth” because it moves smoothly and will not stop abruptly if user stops interacting. This provides a good user experience.
Nevertheless you're able to control this smoothness and the controller itself by a variety of properties:
Property | Description |
---|---|
Types | Enable or disable separated parts of the control. You're allowed to turn off/on rotation, movement, zooming and shifting. TGorillaSmoothCameraControlType = (scctRotateY, scctMoveY, scctZoom, scctShiftX, scctShiftY, scctShiftZ) |
ImpulseLimitRotate | Limit the maximum input values for the rotation impulse. |
ImpulseLimitUpAndDown | Limit the maximum input values for the up/down movement impulse. |
ImpulseLimitZoom | Limit the maximum input values for the zoom impulse. |
IntensityRotate | Get or set the intensity of camera rotation. |
IntensityUpAndDown | Get or set the intensity of camera up and down movement. |
IntensityZoom | Get or set the intensity of camera zoom. |
DampingRotate | Get or set the damping value of camera rotation impulse. |
DampingUpAndDown | Get or set the damping value of camera up/down movement impulse. |
DampingZoom | Get or set the damping value of camera zoom impulse. |
LimitRotationMin | Get or set the min value of camera rotation around Y axis. |
LimitRotationMax | Get or set the max value of camera rotation around Y axis. |
LimitUpAndDownMin | Get or set the min value of camera up/down movement on Y axis. |
LimitUpAndDownMax | Get or set the max value of camera up/down movement on Y axis. |
LimitZoomMin | Get or set the min value of camera zoom on Z axis. |
LimitZoomMax | Get or set the min value of camera zoom on Z axis. |
ShiftImpulseLimit | Get or set the shifting impulse limit. |
ShiftDamping | Get or set the shifting impulse damping. |
ShiftIntensity | Get or set the intensity of shifting on X, Y and Z axis. |
Camera | Link a TCamera or TGorillaCamera to the controller. If no camera is linked, the controller will do nothing. |
Viewport | Link a viewport to the controller for automatic mouse event registration. If you do not link a viewport you have to call AddImpulse(), Zoom() and Shift() yourself. |
ShowController | Activate or deactivate a cube rendered at the position of the controller from the view of the attached camera. |
Interval | Get or set the internal update interval. |
Enabled | Enable or disable work of controller. |
OnBeforeModify | A callback event before a specific type of control (rotate, up/down, zoom, …) getting modified. |
OnAfterModify | A callback event after a specific type of control (rotate, up/down, zoom, …) was modified. |
To retrieve and modify the embedded camera and camera controller from a viewport you can use the following public functions of a TGorillaViewport instance.
Function |
---|
function GetDesignCamera() : TCamera; |
function GetDesignCameraController() : TGorillaSmoothCameraController; |
Creating a Smooth Controller at Runtime
Besides the embedded camera controller in the viewport, you can of course create your own at runtime or designtime.
If you link the controller to a viewport component, it will automatically setup the necessary mouse events for you. But you are also allowed to control it yourself, f.e. by Gamepad or Keyboard events. For manual controlling please leave the viewport property empty.
In the following code snippet we modify rotation manually in user-specific mouse events. We're also blocking shifting, because we only want to rotate the camera.
uses Gorilla.Camera; [...] type TForm1 = class(TForm) GorillaViewport1: TGorillaViewport; FCameraCtrl : TGorillaSmoothCameraController; FMyCamera : TGorillaCamera; private FIsMoving : Boolean; FLastPoint : TPointF; procedure DoOnViewportMouseUp(ASender : TObject; AButton : TMouseButton; AShift : TShiftState; X, Y : Single); procedure DoOnViewportMouseDown(ASender : TObject; AButton : TMouseButton; AShift : TShiftState; X, Y : Single); procedure DoOnViewportMouseMove(ASender : TObject; AShiftState : TShiftState; X, Y : Single); end; [...] procedure TForm1.FormCreate(Sender: TObject); begin /// Deactivate design camera controller before registering user-specific events for mouse feedback GorillaViewport1.UsingDesignCamera := FALSE; /// Register user-specific mouse events to control our camera GorillaViewport1.OnMouseUp := DoOnViewportMouseUp; GorillaViewport1.OnMouseDown := DoOnViewportMouseDown; GorillaViewport1.OnMouseMove := DoOnViewportMouseMove; /// Create a smooth camera controller FCameraCtrl := TGorillaSmoothCameraController.Create(GorillaViewport1); FCameraCtrl.Parent := GorillaViewport; /// NOTICE: Enable only rotation. Disable zooming and shifting FCameraCtrl.Types := [TGorillaSmoothCameraControlType.scctRotateY, TGorillaSmoothCameraControlType.scctMoveY]; /// Create our own camera for this controller FMyCamera := TGorillaCamera.Create(FCameraCtrl); FMyCamera.Parent := FCameraCtrl; /// Link the camera to the controller FCameraCtrl.Camera := FMyCamera; /// Activate the camera for rendering GorillaViewport1.Camera := FMyCamera; [...] end; procedure TForm1.DoOnViewportMouseUp(ASender : TObject; AButton : TMouseButton; AShift : TShiftState; X, Y : Single); begin FIsMoving := false; end; procedure TForm1.DoOnViewportMouseDown(ASender : TObject; AButton : TMouseButton; AShift : TShiftState; X, Y : Single); begin FIsMoving := true; FLastPoint := PointF(X, Y); end; procedure TForm1.DoOnViewportMouseMove(ASender : TObject; AShiftState : TShiftState; X, Y : Single); var LDiff : TPointF; begin if FIsMoving then begin if (ssLeft in AShiftState) then begin LDiff := PointF(X, Y) - FLastPoint; /// Rotate around y-axis + Move up and down FCameraCtrl.AddImpulse(LDiff); end; /// finally store the last mouse position FLastPoint := PointF(X, Y); end; end;
The smooth camera controller provides a number of helpful functions to modify it from external.
Function | Description |
---|---|
procedure AddImpulse(AOfs : TPointF); | Call this procedure to rotate around Y axis (AOfs.X) and move the camera up or down (AOfs.Y). |
procedure AddXImpulse(AAngle : Single); | Call this procedure to rotate around Y axis. |
procedure AddYImpulse(AAngle : Single); | Call this procedure to move camera up and down. |
procedure Zoom(AStrength : Single = 1); | Call this procedure if you want to zoom in or out. The strength parameter defines the intensity of zooming. |
procedure Shift(AOfs : TPoint3D); | Move the camera controller on X, Y and Z axis. |
You can manipulate impulse values for rotation, zooming and shifting directly by the following properties.
Property | Description |
---|---|
Impulse.X | Get or set the current impulse for rotation around Y-axis (X value). |
Impulse.Y | Get or set the current impulse for moving up and down (Y value) |
Impulse.Z | Get or set the current impulse for zooming in/out (Z value) |
ShiftImpulse.X | Get or set the current impulse for shifting on X axis. |
ShiftImpulse.Y | Get or set the current impulse for shifting on Y axis. |
ShiftImpulse.Z | Get or set the current impulse for shifting on Z axis. |
Next step: Lights