A globe camera controller for Unity

I’m trying to implement a “good” camera controller for an application created in Unity using Cesium.

The CameraController provided in the cesium-unity repo is not suitable for our needs. We need to handle mouse/touch controls, but the CameraController provided just handles mouse movement and doesn’t handling click & drag with the mouse/touch.

The scene camera provided in the Cesium Sandcastle demo is more what I am looking for but I find it difficult to translate the ~4K lines of JavaScript code to C# in Unity and I suspect that someone may have implemented a camera model they are willing to share?

I’m using the camera controller in Google Earth as a reference for my own camera implementation, but I’m struggling to solve a few issues. For example: How to handle cases where a user clicks & drags into space (when the drag originates or moves off the globe), or when the horizon is clicked at oblique angles can cause large changes in the camera position.

Another issue occurs where the camera will lock up at the poles, and it seems the camera controller for the Sandcastle demos doesn’t handle this case very well either. I know I can use quaternion rotations to avoid the gimbal lock, but maybe someone else has solved this issue in Unity already?

Any help with this would be appreciated.

Thanks in advance!

Hi @jpvanoosten,

I can sympathize with CesiumJS’s camera controller code being hard to follow. Unfortunately we haven’t developed a counterpart in Unity, but I’ll try and take a stab at your questions. (Though I hope other community members can chime in with their own solutions!)

How to handle cases where a user clicks & drags into space (when the drag originates or moves off the globe),

I’ve tried to do some “globe spinning” behavior before, though it only activated when the user clicked on the globe. (so drags originating off of the globe didn’t work). But this is what I tried:

  • Get the geodetic normal of the grabbed position
  • As the user is dragging, find the geodetic normal of the new position
  • Compute the angle between these normals using quaternions
  • Apply this rotation.
    • If you want the globe to keep spinning as you let go, you’ll probably have to implement some inertia-based spinning behavior, using the previously computed rotation as a sort of “max rotational speed” value.

This worked well for me because I scaled the globe and set the CesiumGeoreference to the center of the globe (ECEF [0, 0, 0]). This meant that the Unity origin was at the center of my globe, simplifying the rotation computations. But this may get complicated if your CesiumGeoreference isn’t at the globe’s center.

Another issue occurs where the camera will lock up at the poles

I’m just theorizing, but maybe a drag action can be broken into “horizontal” and “vertical” components relative to the globe, and the resulting rotations can be applied as separate quaternions?

the horizon is clicked at oblique angles can cause large changes in the camera position.

Do you have a screenshot / video of how this happens, and how it affects your controller’s behavior?

1 Like