holoride
Search Results for

    Show / Hide Table of Contents
    ❮ Sensor Data
    Sample Map Nodes via Code ❯

    Coordinate Systems

    To synchronize a flat virtual Unity scene with a curved, geographical Earth, the Spatial Experience SDK employs a multi-tiered coordinate architecture. Because Unity uses single-precision floats (float / Vector3), travelling long distances from the coordinate origin (0, 0, 0) quickly triggers severe floating-point jitter, rendering artifacts, and physics instability.

    To solve this, the SDK abstracts spatial coordinates into three distinct layers: GeoCoordinate, GlobalPosition, and Vector3. Understanding how these coordinates map together—and the role of the Pivot and ShiftOffset—is essential for writing robust, bug-free scripts.


    The Three Coordinate Layers

    ---
    config:
      flowchart:
        subGraphTitleMargin:
          bottom: 30
    ---
    graph TD
        A("GeoCoordinate <br> (Latitude, Longitude, Altitude)") -->|Relative to Pivot| B("GlobalPosition <br> (Double-precision meters)")
        B -->|Offset by ShiftOffset| C("Vector3 <br> (Unity single-precision float)")
        
        style A fill:#CCCCCC,stroke-width:0px
        style B fill:#0099ff,stroke-width:0px,color:#fff
        style C fill:#ae00ff,stroke-width:0px,color:#fff
    

    1. GeoCoordinate (Ellipsoidal Geography)

    Represents raw geographical positions on the Earth's surface using double-precision latitude, longitude, and altitude values (double). This format is ideal for mapping and querying global databases (like OpenStreetMap), but cannot be used directly by Unity's rendering engine.

    2. GlobalPosition (Double-Precision Local Space)

    Represents a coordinate in double-precision meters relative to a fixed geographic Pivot point. This is the most reliable and persistent representation of any object's spatial coordinates within the SDK. It is completely immune to coordinate shifts and floating-point errors.

    3. Vector3 (Single-Precision Floating Origin)

    The standard coordinate space used by Unity's rendering and physics engines. It represents positions in single-precision floating-point meters. In the Spatial Experience SDK, these coordinates are continually offset using the active ShiftOffset to keep the vehicle near (0, 0, 0).


    The Role of Pivot and ShiftOffset

    To understand how a persistent geographic point translates into a transient rendering coordinate, we must define the roles of Pivot and ShiftOffset:

    1. The Pivot (Geographic Origin)

    When an elastic scene loads, the ElasticSceneGenerator establishes a fixed geographic coordinate (often the player's spawning coordinate) as the Pivot.

    • The Pivot acts as the anchoring (0, 0, 0) origin for all geographic calculations in that session.
    • A GlobalPosition is simply the double-precision displacement (in meters) of a point away from this Pivot.

    2. The ShiftOffset (World Displacement Vector)

    As the vehicle travels, it drifts further away from the local Unity origin (0, 0, 0). To prevent precision jitter, the World Shift Manager periodically shifts the entire active scene (including the vehicle, terrain, and procedurally spawned props) back to (0, 0, 0).

    • The World Shift Manager tracks the cumulative displacement of these origin resets inside a three-dimensional vector called the ShiftOffset (accessed via WorldShiftManager.Instance.ShiftOffset).

    • At any given frame, a Unity Vector3 position represents the shifted coordinate:

      Shifted Position (Vector3) = GlobalPosition - ShiftOffset


    CRITICAL: The Single-Frame Lifecycle of Vector3

    Important

    A Unity Vector3 coordinate is only reliable within the boundaries of a single frame.

    Because the World Shift Manager can trigger an origin shift at the end of any active frame, a raw Vector3 is a transient coordinate.

    • Never store a raw Vector3 coordinate in a class variable, array, coroutine, or database for persistent tracking across frames.
    • If a world shift occurs on the next frame boundary, your stored Vector3 will instantly be offset and point to the wrong virtual location.

    The Solution: Persistent Storage via GlobalPosition

    Whenever you need to track or store a coordinate persistently (for pathfinding, waypoint tracking, spawner positions, or game state synchronization), immediately convert it into a GlobalPosition!

    1. Converting a Unity Position (Vector3) to a Persistent GlobalPosition

    using Holoride.ElasticSDK;
    using UnityEngine;
    
    public class MyCoordinateTracker : MonoBehaviour
    {
        // Store persistently as a GlobalPosition, NOT a Vector3!
        private GlobalPosition persistentWaypoint;
    
        public void SetWaypoint(Vector3 currentUnityPosition)
        {
            // GlobalPosition.FromShifted automatically incorporates the active ShiftOffset
            this.persistentWaypoint = GlobalPosition.FromShifted(currentUnityPosition);
            
            Debug.Log($"Waypoint safely anchored at GlobalPosition: {this.persistentWaypoint}");
        }
    }
    

    2. Converting a GlobalPosition Back to a Rendering-Safe Vector3

    When you need to use the stored coordinate for rendering, physics, or transforms, convert it back to a Vector3 on the active frame using .offset:

        private void Update()
        {
            // Convert back to a local Vector3 on the active frame boundary
            Vector3 activeFramePosition = this.persistentWaypoint.offset;
            
            // Transform transforms or physics parameters safely
            transform.position = activeFramePosition;
        }
    

    Coordinate Conversion API Cheat-Sheet

    To translate between coordinate layers cleanly inside your scripts, use the following core APIs:

    Conversion Flow API Implementation Description
    Vector3 ➡️ GlobalPosition GlobalPosition.FromShifted(Vector3) Compiles a persistent global coordinate by incorporating the active ShiftOffset.
    GlobalPosition ➡️ Vector3 globalPosition.offset Translates a persistent coordinate back to a rendering-safe Vector3 relative to the active frame's origin.
    GeoCoordinate ➡️ GlobalPosition new GlobalPosition(GeoCoordinate, Pivot) Calculates the double-precision meter displacement relative to the active Pivot.
    GlobalPosition ➡️ GeoCoordinate globalPosition.ToGeoCoordinate(Pivot) Converts local meter offsets back into ellipsoidal latitude and longitude.

    ❮ Sensor Data
    Sample Map Nodes via Code ❯
    In This Article

    Back to top
    ©   holoride
    Privacy   Imprint