Could someone point me to some practical resources for learning about the Unity coordinate system… and specifically related to Cesium for Unity?
We’ve been working with CesiumJS since it was in beta. And we’re investigating the possibilities of using Cesium for Unity. But we have no experience with 3-D coordinate systems. And I’d like to find some good resources to study and gain a working understanding.
I’ve read all the Getting Started information on Cesium’s website along with “Cesium for Unity: Placing Objects on the Globe”. I’ve read through every post in the Cesium for Unity forum related to positioning and rotation. I’ve also read through many articles about position and rotation in Unity. But with absolutely no background or experience with 3-D coordinate systems I can’t put the pieces together so far.
We’d like to fly aircraft models along their radar flight paths in Cesium for Unity. At this point we’ve imported a single aircraft fbx model. We’ve created a prefab using that model which we use to create multiple instances of the aircraft. We’ve been able to load the radar track data and can move the aircraft with the following approach…
public IEnumerator FlightPlayback(Flight flt)
{
GameObject objectToMove = flt.gameObject;
List<TrackPoint> lstTPs = flt.pts;
//Debug.Log("FlightPlayback started for OpId: " + flt.oper_id + " trackStart: " + tracksStart.ToString());
for (int i = 1; i < lstTPs.Count; i++)
{
TrackPoint tp = lstTPs[i];
// Get the speed
float deltaSec = (tp.deltaSec - lstTPs[i - 1].deltaSec) / SpeedMultiplier;
float elapsedTime = 0;
while (elapsedTime < deltaSec)
{
// Get start for the trackpoint
double3 start = lstTPs[i - 1].xyz;
// Get end for the trackpoint
double3 tarPos = lstTPs[i].xyz;
var lerpPos = math.lerp(start, tarPos, (elapsedTime / deltaSec));
var ECEFStart = CesiumWgs84Ellipsoid.LongitudeLatitudeHeightToEarthCenteredEarthFixed(start);
var ECEFTarget = CesiumWgs84Ellipsoid.LongitudeLatitudeHeightToEarthCenteredEarthFixed(lerpPos);
objectToMove.GetComponent<CesiumGlobeAnchor>().positionGlobeFixed = ECEFTarget;
//var newPosLatLon = _map.WorldToGeoPosition(objectToMove.transform.localPosition);
//locPos = _map.GeoToWorldPosition(newPosLatLon, true);
//locVec = _map.WorldToGeoPosition(locPos);
// Rotate to look at the next point
//objectToMove.transform.rotation = Quaternion.LookRotation(tarPos - start);
Vector3 v3ECEFTarget = new Vector3();
v3ECEFTarget.x = (float)ECEFTarget.x;
v3ECEFTarget.y = (float)ECEFTarget.y;
v3ECEFTarget.z = (float)ECEFTarget.z;
Vector3 v3ECEFStart = new Vector3();
v3ECEFStart.x = (float)ECEFStart.x;
v3ECEFStart.y = (float)ECEFStart.y;
v3ECEFStart.z = (float)ECEFStart.z;
//float3 normalizedSource = (float3)math.normalize(ECEFStart);
//float3 normalizedDestination = (float3)math.normalize(ECEFTarget);
////Quaternion flyQuat = Quaternion.FromToRotation(normalizedSource, normalizedDestination);
//Quaternion flyQuat = Quaternion.FromToRotation(v3ECEFStart, v3ECEFTarget);
//Debug.Log(flyQuat);
//Vector3 directionToTarget = v3ECEFTarget - v3ECEFStart;
//Vector3 currentDirection = transform.forward;
//float maxTurnSpeed = 60f; // degrees per second
//Vector3 resultingDirection = Vector3.RotateTowards(currentDirection, directionToTarget, maxTurnSpeed * Mathf.Deg2Rad * Time.deltaTime, 1f);
//transform.rotation = Quaternion.LookRotation(resultingDirection);
Vector3 dir = v3ECEFTarget - v3ECEFStart;
float angle = Mathf.Atan2(dir.x, dir.y) * Mathf.Rad2Deg;
//objectToMove.GetComponent<CesiumGlobeAnchor>().transform.rotation = Quaternion.Euler(0, angle + 180.0f, 0);
////var q = Quaternion.identity;
//var q = Quaternion.LookRotation(v3ECEFTarget - v3ECEFStart);
////q.y = 0;
////objectToMove.GetComponent<CesiumGlobeAnchor>().rotationEastUpNorth = flyQuat;
//objectToMove.GetComponent<CesiumGlobeAnchor>().rotationGlobeFixed = q;
//Vector3 angles = this.transform.eulerAngles;
//angles.z = 0.0f;
//objectToMove.GetComponent<CesiumGlobeAnchor>().transform.eulerAngles = angles;
// Interpolate rotation in the EUN frame. The local EUN rotation will
// be transformed to the appropriate world rotation as we fly.
objectToMove.GetComponent<CesiumGlobeAnchor>().rotationEastUpNorth = Quaternion.Slerp(
objectToMove.GetComponent<CesiumGlobeAnchor>().rotationEastUpNorth,
Quaternion.Euler(0, (angle - 225), 0),
(float)(elapsedTime / deltaSec)
);
elapsedTime += Time.deltaTime;
yield return new WaitForEndOfFrame();
}
}
Each track point is held in a double3 ‘xyz’ as:
tp.xyz = new double3 { x = tp.lon, y = tp.lat, z = tp.alt * Constants.FEET_TO_METERS };
(By the way we are using the CesiumGeoreference and Cesium Globe Anchors.)
But we don’t have the first clue how to manipulate the heading, pitch, roll.
I left all of the rotation/transformation attempts in the code I posted. As you can see we have no idea what we’re doing and have basically been shooting in the dark hoping something will begin to make sense.
I’m not so much looking for someone to write the rotation code for us (although we certainly would love to see a good example of how to do what we’re trying to do). Instead, we’d love help with a couple of things…
- Can you point us to a practical resource or resources to understand and use the 3-D coordinate systems required for Cesium for Unity?
- Any thoughts about how the flight data is stored/structured would also be welcome. Is the double3 a practical approach? Or would we benefit from structuring the data differently? If so, what would be a better approach and why?
- Is the method we’re using to move the models reasonable? Or should we used a different approach for moving the models?
We’re open to all input as this is a new world for us… and we want to gain a solid, working understanding about these topics as we begin to experiment and develop in this environment.
Thanks for any help!