Saving/Loading Camera State

I've been playing around with scripting camera positions at different points in time. So far, I've had luck with the standard operations exposed through the camera controller -> setting a reference frame, flying to a location, and following an object.

I would like to now see if it is possible to move the camera to look at something in Cesium, and by clicking a button, save the current camera settings so that they can be reloaded at a later time.

Has anyone done this before, or does anyone have any ideas on what exactly needs to be persisted from the combination of camera/scene/etc. to be able to reproduce a camera view?

Hi Wayne,

You can use CameraController:

http://cesium.agi.com/Cesium/Build/Documentation/CameraController.html

scene.getCamera().controller.lookAt(eye, target, up);

To save the camera properties, I save direction, position and up positions and later I set this properties:

scene.getCamera().direction = direction;

scene.getCamera().position = position;

scene.getCamera().up = up;

See: http://cesium.agi.com/Cesium/Build/Documentation/Camera.html

Tamy is mostly correct, and that solution will work for many use cases, however, (and Dan can correct me if I’m wrong) I believe to guarantee the camera is exactly the same, you actually need to save off 6 properties. Here’s a small (untested) object that should do the tick.

var StoredView = function()

{

this.position = undefined;

this.direction = undefined;

this.up = undefined;

this.right = undefined;

this.transform = undefined;

this.frustum = undefined;

};

StoredView.prototype.save = function(camera)

{

if(typeof camera === ‘undefined’)

{

throw new DeveloperError(‘camera is required’);

}

this.position = camera.position.clone(this.position);

this.direction = camera.direction.clone(this.direction);

this.up = camera.up.clone(this.up);

this.right = camera.right.clone(this.right);

this.transform = camera.transform.clone(this.transform);

this.frustum = camera.frustum.clone(this.frustum);

};

StoredView.prototype.load = function(camera)

{

if(typeof this.position === ‘undefined’)

{

throw new DeveloperError(‘no view has been stored’);

}

this.position.clone(camera.position);

this.direction.clone(camera.direction);

this.up.clone(camera.up);

this.right.clone(camera.right);

this.transform.clone(camera.transform);

this.frustum.clone(camera.frustum);

};

Thanks! Works like a charm! :slight_smile:

Hi!

This code doesn’t work to 2D view. What can I do to save “what I’m seeing now” on the map, on 2D view?

Thanks!

Tamy,

This code should work in 2D, are you trying to store in 3D and then restore in 2D? Because that would definitely be an issue. I think it should be easy to fix either way, I just wanted to confirm what the exact problem was.

Thanks,

Matt

No, Matt, I’m saving in 2D and trying to show in 2D.

I think the zoom is not restoring right.

Thank you.

Does anyone know how to save the zoom in 2D?

Thanks!

Hi Tamy,

The zoom in 3D and Columbus view is changed by moving the camera’s position, but the zoom in 2D is changed by properties on the frustum. This is because there are two different projections used in 3D/Columbus view and in 2D. The code that Matt posted will work as long as the correct frustum type is being cloned.

Regards,

Dan

is this code still valid in 1.17?

Here’s the updated example

var StoredView = function()
{
this.position = undefined;
this.direction = undefined;
this.up = undefined;
this.right = undefined;
this.transform = undefined;
this.frustum = undefined;
};

StoredView.prototype.save = function(camera)
{
this.position = Cesium.Cartesian3.clone(camera.positionWC, this.position);
this.heading = camera.heading;
this.picth = camera.pitch;
this.roll = camera.roll;
this.transform = Cesium.Matrix4.clone(camera.transform, this.transform);
};

StoredView.prototype.load = function(camera)
{
camera.position = Cesium.Cartesian3.clone(this.position, camera.position);
camera.heading = this.heading;
camera.pitch = this.pitch;
camera.roll = this.roll;
camera.transform = Cesium.Matrix4.clone(this.transform, camera.transform);
};

``

Best,

Hannah

Camera.Heading is a read-only property. Is there another way to accomplish this?

Oh, sorry. You can use the Camera.setView function to set the heading/pitch/roll. Here is an example:

viewer.camera.setView({
    destination : cartesianPosition,
    orientation: {
        heading : Cesium.Math.toRadians(90.0), // east, default value is 0.0 (north)
        pitch : Cesium.Math.toRadians(-90),    // default value (looking down)
        roll : 0.0                             // default value
    }
});

-Hannah