Camera Control and animation
The viewer provides a level of abstraction over the cameras in the scene to make it easy to manage multiple cameras, enable/disable/configure camera controls(like OrbitControls
), and integrate with post-processing and XR pipelines. This is managed in a class called CameraController
.
On initialisation, the viewer creates a default PerspectiveCamera
with a CameraController
with OrbitControls
which is used for scene rendering.
The active camera controller can be accessed by:
const controller = viewer.scene.activeCamera;
// get the threejs camera
const perspectiveCamera = controller.cameraObj;
// get orbit controls
const orbitControls = controller.controls;
activeCamera
is the camera that is used for scene rendering. This can be set to a custom camera like:
const cameraObj = new PerspectiveCamera();
...
viewer.scene.activeCamera = viewer.createCamera(cameraObj);
createCamera
above, creates and returns a CameraController
instance. It is automatically ensured that only one controller is created for a camera instance, even if this function is called multiple times.
To get the CameraController
from the camera use controller = cameraObj.userData.iCamera
three.js internals can be imported directly from webgi
import { PerspectiveCamera, Vector3, Vector2, Texture} from "webgi";
The active camera instance and view can also be managed from events in the scene objects. To activate a scene camera, get the instance from the camera and dispatch the activateMain
event.
camera.dispatchEvent({type: 'activateMain', camera: camera})
Here, camera is an instance of PerspectiveCamera
or OrthographicCamera
. The camera
in the event can be set to null
to activate the default camera in the scene.
To change the view of the camera, dispatch the setView
event.
camera.dispatchEvent({type: 'setView', camera: camera})
This copies the properties from the camera and sets them on the active camera.
Camera Transform
The camera position
and target
can be set directly in the controller;
viewer.scene.activeCamera.position = new Vector3(2, 3, -5);
viewer.scene.activeCamera.target = new Vector3(0, 2, 0);
// or
viewer.scene.activeCamera.position.set(2, 3, -5);
viewer.scene.activeCamera.positionUpdated(); // this must be called to notify the controller on value update
viewer.scene.activeCamera.target.set(0, 2, 0);
viewer.scene.activeCamera.targetUpdated(); // this must be called to notify the controller on value update
Camera global scale must be set to 1.0
in x
, y
and z
. This is automatically ensured while models and cameras are imported, but it must be taken care of when updating models and hierarchy by code.
Camera Options
Various camera options can be get/set from the controller:
const options = viewer.scene.activeCamera.getCameraOptions();
options.fov = 25;
viewer.scene.activeCamera.setCameraOptions(options);
The following options can be set:
fov
: Vertical Field of View in degrees. Perspective Camera only.zoom
: Camera zoom valueaspect
: Camera aspect ratio. Default is set to'auto'
, which calculates the aspect ratio based on canvas size, and updates on size change.controlsEnabled
: Enable or disable Orbit Controls etc.frustumSize
: for Orthographic camera.
Controls Options
Options for controls like OrbitControls
can be set directly after accessing it.
For example:
const controls = viewer.scene.activeCamera.controls;
controls.autoRotate = true;
controls.autoRotateSpeed = true;
controls.enableDamping = true;
controls.rotateSpeed = 2.0;
controls.enableZoom = false;
...
For all properties, see three.js docs on OrbitControls
OrbitControls
in webgi also support smooth dolly zooming with mouse wheel when used with enabledDamping=true
. To control the speed and max speed of this zooming see controls.maxSpeed
and controls.zoomSpeed
.
The OrbitControls
in webgi is extended for some extra performance improvements, and camera movements are syned with the render loop. So, prefer to use the instance of OrbitControls
in the default camera instead of passing in a custom one.
Currently only OrbitControls
is supported, internally, but others can be added by extending CameraController
.
Here's a codepen with live demo for accessing and modifying the camera properties:
Camera Animation and Views
CameraViewPlugin
can be used to manage and animate between multiple camera states(views).
First add the plugin (This is done in addBasePlugins
):
await viewer.addPlugin(CameraViewPlugin)
Then get the reference to the plugin
const camViewPlugin = viewer.getPlugin(CameraViewPlugin)
Camera views can be created in the editor and downloaded as a preset and applied at runtime or they can be added programmatically like below:
let view = camViewPlugin.getCurrentCameraView(viewer.scene.activeCamera) // Get the current camera state
view.position.set(-2,4,5)
view.target.set(0,1,0)
camViewPlugin.camViews.push(view) // save it for later.
// add more views
Now we can animate the camera to a view:
await camViewPlugin.animateToView(camViews.camViews[1], 2000) // 2000 ms is the duration
Once the camera views are added, they can be looped or played through once.
camViewPlugin.animDuration = 3000 // ms, default duration of one animation
await camViewPlugin.animateAllViews() // This will loop once
camViewPlugin.viewLooping = true // This will loop indefinitely
Interpolation of camera position is spherical by default to ensure smooth movement, but it can be changed to linear for direct interpolation.
Animation easing is set to easeInOutSine
by default, but can be set to any easing from PopmotionPlugin
.
Check the API docs for more parameters in
CameraViewPlugin
Here is a codepen with live demo for the CameraViewPlugin
API: