How to use the camera frame rotation from the JSON file exported from Google Earth Studio in Cesium to setView?

Hi,

I’m trying to implement the camera flight produced by Google Earth Studio in Cesium.

But cannot understand the meaning of rotation and how to use it.

This is a simple:

For the complete JSON, please refer to the attachment.

Google Earth Studio.json.zip (57.5 KB)

Thanks for any help!

Hi @hayderGo,

Welcome back to the forums!

This sounds a little more like a Google Earth Studio question than a Cesium one. The question really is, how has Google Earth defined rotation in this file format? What coordinate system and reference frame are they using? What unit of rotation are they using (based on the numbers, I think degrees is a reasonable guess)?

I tried to find a link to some docs on this, but I didn’t come up with much. I didn’t make an account, so I’m not sure what workflow you used to export this file - maybe search some keywords related to whatever that workflow is to find more info.

Best,
Matt

I don’t know if it’s worth much, but this is what Copilot had to say about it:

* position: Earth-centered, Earth-fixed (ECEF) meters.
* coordinate: WGS84 latitude/longitude/altitude.
* rotation: Euler angles (x, y, z) in degrees; camera orientation.

Hi @mzschwartz5 ,
Thank you for the information!
Suppose the rotation field is the ECEF Euler angles, how to use it to setView?
I attempted to convert it into ENU Euler angles in the following way:

//  ENU HeadingPitchRoll in degrees should be approximately (270.12, -44.61, 0).
  const destination = Cartesian3.fromDegrees(
    121.73286024286688,
    31.23933153689792,
    20695,
  );
  const rx = CesiumMath.toRadians(159.34465662912814);
  const ry = CesiumMath.toRadians(67.17562316976208);
  const rz = CesiumMath.toRadians(45.669011717197826);
  const matrix3_rx = Matrix3.fromRotationX(rx);
  const matrix3_ry = Matrix3.fromRotationY(ry);
  const matrix3_rz = Matrix3.fromRotationZ(rz);
  const matrix3_r = new Matrix3();

  //  x -> y -> z
  // Matrix3.multiply(matrix3_ry, matrix3_rz, matrix3_r);
  // Matrix3.multiply(matrix3_rx, matrix3_r, matrix3_r);
  Matrix3.multiply(matrix3_rx, matrix3_ry, matrix3_r);
  Matrix3.multiply(matrix3_r, matrix3_rz, matrix3_r);

  // //  x -> z -> y
  // Matrix3.multiply(matrix3_rz, matrix3_ry, matrix3_r);
  // Matrix3.multiply(matrix3_rx, matrix3_r, matrix3_r);
  // Matrix3.multiply(matrix3_rx, matrix3_rz, matrix3_r);
  // Matrix3.multiply(matrix3_r, matrix3_ry, matrix3_r);

  // //  y -> x -> z
  // Matrix3.multiply(matrix3_rx, matrix3_rz, matrix3_r);
  // Matrix3.multiply(matrix3_ry, matrix3_r, matrix3_r);
  // Matrix3.multiply(matrix3_ry, matrix3_rx, matrix3_r);
  // Matrix3.multiply(matrix3_r, matrix3_rz, matrix3_r);

  // //  y -> z -> x
  // Matrix3.multiply(matrix3_rz, matrix3_rx, matrix3_r);
  // Matrix3.multiply(matrix3_ry, matrix3_r, matrix3_r);
  // Matrix3.multiply(matrix3_ry, matrix3_rz, matrix3_r);
  // Matrix3.multiply(matrix3_r, matrix3_rx, matrix3_r);

  // //  z -> x -> y
  // Matrix3.multiply(matrix3_rx, matrix3_ry, matrix3_r);
  // Matrix3.multiply(matrix3_rz, matrix3_r, matrix3_r);
  // Matrix3.multiply(matrix3_rz, matrix3_rx, matrix3_r);
  // Matrix3.multiply(matrix3_r, matrix3_ry, matrix3_r);

  // //  z -> y -> x
  // Matrix3.multiply(matrix3_ry, matrix3_rx, matrix3_r);
  // Matrix3.multiply(matrix3_rz, matrix3_r, matrix3_r);
  // Matrix3.multiply(matrix3_rz, matrix3_ry, matrix3_r);
  // Matrix3.multiply(matrix3_r, matrix3_rx, matrix3_r);

  const enuTransform = Transforms.eastNorthUpToFixedFrame(destination);
  const enuTransformInv = Matrix4.inverse(enuTransform, new Matrix4());
  const ecefRotationMatrix4 = Matrix4.fromRotationTranslation(matrix3_r);
  const enuRotationMatrix4 = Matrix4.multiply(enuTransformInv, ecefRotationMatrix4, new Matrix4());
  const enuRotationMatrix = Matrix4.getMatrix3(enuRotationMatrix4, new Matrix3());

  const quaternion = Quaternion.fromRotationMatrix(enuRotationMatrix);
  const headingPitchRoll = HeadingPitchRoll.fromQuaternion(quaternion);
  const { heading, pitch, roll } = headingPitchRoll;
  console.log('heading: ', CesiumMath.toDegrees(heading).toFixed(2)); 
  console.log('pitch: ', CesiumMath.toDegrees(pitch).toFixed(2));
  console.log('roll: ', CesiumMath.toDegrees(roll).toFixed(2));

  viewer.camera.setView({
    destination,
    orientation: {
      heading,
      pitch,
      roll,
    },
  });

But the result is incorrect. Where might the problem be?

Another failed attempt :joy:

  //  ENU HeadingPitchRoll in degrees should be approximately (270.12, -44.61, 0).
  const destination = Cartesian3.fromDegrees(
    121.73286024286688,
    31.23933153689792,
    20695,
  );
  const rx = CesiumMath.toRadians(159.34465662912814);
  const ry = CesiumMath.toRadians(67.17562316976208);
  const rz = CesiumMath.toRadians(45.669011717197826);
  const matrix3_rx = Matrix3.fromRotationX(rx);
  const matrix3_ry = Matrix3.fromRotationY(ry);
  const matrix3_rz = Matrix3.fromRotationZ(rz);
  const matrix3_r = new Matrix3();

  // //  x -> y -> z
  // Matrix3.multiply(matrix3_ry, matrix3_rx, matrix3_r);
  // Matrix3.multiply(matrix3_rz, matrix3_r, matrix3_r);

  // //  x -> z -> y
  // Matrix3.multiply(matrix3_rz, matrix3_rx, matrix3_r);
  // Matrix3.multiply(matrix3_ry, matrix3_r, matrix3_r);

  //  y -> x -> z
  Matrix3.multiply(matrix3_rx, matrix3_ry, matrix3_r);
  Matrix3.multiply(matrix3_rz, matrix3_r, matrix3_r);

  // //  y -> z -> x
  // Matrix3.multiply(matrix3_rz, matrix3_ry, matrix3_r);
  // Matrix3.multiply(matrix3_rx, matrix3_r, matrix3_r);

  // //  z -> x -> y
  // Matrix3.multiply(matrix3_rx, matrix3_rz, matrix3_r);
  // Matrix3.multiply(matrix3_ry, matrix3_r, matrix3_r);

  // //  z -> y -> x
  // Matrix3.multiply(matrix3_ry, matrix3_rz, matrix3_r);
  // Matrix3.multiply(matrix3_rx, matrix3_r, matrix3_r);
  
  // const direction = new Cartesian3(0, 0, 1);
  // const up = new Cartesian3(0, 1, 0);
  const direction = new Cartesian3(-1, 0, 0);
  const up = new Cartesian3(0, 0, 1);
  Matrix3.multiplyByVector(
    matrix3_r,
    direction,
    direction,
  );
  Matrix3.multiplyByVector(
    matrix3_r,
    up,
    up,
  );
  Cartesian3.normalize(direction, direction,);
  Cartesian3.normalize(up, up,);
  // console.log("direction", direction);
  // console.log("up", up);
  viewer.camera.setView({
    destination: destination,
    orientation: {
      direction,
      up,
    },
  });

Hi @hayderGo, according to the Google Earth Studio camera export documentation, you can choose “Global” or “Local” coordinates when you export the file. Which one did you use?

Hi @jjhembd , i did chose “Global“ coordinate.
I did compared the two coordinate systems, and found that their “rotation” fields were the same.