SkyScript Graphics API
The Graphics API provides coordinate conversion functions between X-Plane's local OpenGL coordinate system and world coordinates (latitude/longitude/altitude).
Overview
X-Plane uses two coordinate systems:
- World Coordinates: Latitude, longitude, and altitude (meters MSL)
- Local Coordinates: OpenGL coordinates in meters, centered on the aircraft reference point, with Y pointing up
typescript
// Convert between coordinate systems
const local = XPlane.graphics.worldToLocal(lat, lon, alt);
const world = XPlane.graphics.localToWorld(x, y, z);Functions
worldToLocal
Convert world coordinates (lat/lon/alt) to local OpenGL coordinates.
typescript
const local = XPlane.graphics.worldToLocal(
latitude: number,
longitude: number,
altitude: number
): LocalCoordinates;Parameters:
latitude- Latitude in degreeslongitude- Longitude in degreesaltitude- Altitude in meters MSL
Returns:
typescript
interface LocalCoordinates {
x: number; // Local OpenGL X (meters)
y: number; // Local OpenGL Y (meters, altitude)
z: number; // Local OpenGL Z (meters)
}Example:
typescript
// Convert Seattle Tacoma Airport coordinates to local
const seatac = XPlane.graphics.worldToLocal(47.4502, -122.3088, 130);
console.log(`SeaTac local: x=${seatac.x}, y=${seatac.y}, z=${seatac.z}`);localToWorld
Convert local OpenGL coordinates to world coordinates.
typescript
const world = XPlane.graphics.localToWorld(
x: number,
y: number,
z: number
): WorldCoordinates;Parameters:
x- Local OpenGL X coordinatey- Local OpenGL Y coordinatez- Local OpenGL Z coordinate
Returns:
typescript
interface WorldCoordinates {
latitude: number; // Latitude in degrees
longitude: number; // Longitude in degrees
altitude: number; // Altitude in meters MSL
}Example:
typescript
// Get aircraft position in world coordinates
const x = XPlane.dataref.getDouble("sim/flightmodel/position/local_x");
const y = XPlane.dataref.getDouble("sim/flightmodel/position/local_y");
const z = XPlane.dataref.getDouble("sim/flightmodel/position/local_z");
const world = XPlane.graphics.localToWorld(x, y, z);
console.log(`Aircraft at: ${world.latitude.toFixed(6)}°, ${world.longitude.toFixed(6)}°`);
console.log(`Altitude: ${world.altitude.toFixed(1)} meters MSL`);Understanding X-Plane Coordinates
Local OpenGL Coordinates
The local coordinate system is:
- Centered at the scenery reference point (not the aircraft)
- X - Positive east
- Y - Positive up
- Z - Positive south
All distances are in meters.
World Coordinates
- Latitude - Degrees, positive north, negative south
- Longitude - Degrees, positive east, negative west
- Altitude - Meters above mean sea level (MSL)
Complete Examples
Display Current Position
typescript
function displayAircraftPosition() {
// Get local coordinates from datarefs
const x = XPlane.dataref.getDouble("sim/flightmodel/position/local_x");
const y = XPlane.dataref.getDouble("sim/flightmodel/position/local_y");
const z = XPlane.dataref.getDouble("sim/flightmodel/position/local_z");
// Convert to world coordinates
const world = XPlane.graphics.localToWorld(x, y, z);
// Format latitude
const latDir = world.latitude >= 0 ? "N" : "S";
const latDeg = Math.abs(world.latitude);
const latMin = (latDeg % 1) * 60;
// Format longitude
const lonDir = world.longitude >= 0 ? "E" : "W";
const lonDeg = Math.abs(world.longitude);
const lonMin = (lonDeg % 1) * 60;
console.log(`Position: ${Math.floor(latDeg)}°${latMin.toFixed(2)}'${latDir} ` +
`${Math.floor(lonDeg)}°${lonMin.toFixed(2)}'${lonDir}`);
console.log(`Altitude: ${(world.altitude * 3.28084).toFixed(0)} ft MSL`);
}Calculate Distance to Waypoint
typescript
function distanceToWaypoint(targetLat: number, targetLon: number): number {
// Get current aircraft position
const x = XPlane.dataref.getDouble("sim/flightmodel/position/local_x");
const y = XPlane.dataref.getDouble("sim/flightmodel/position/local_y");
const z = XPlane.dataref.getDouble("sim/flightmodel/position/local_z");
// Convert target to local coordinates
const target = XPlane.graphics.worldToLocal(targetLat, targetLon, 0);
// Calculate horizontal distance (ignore altitude)
const dx = target.x - x;
const dz = target.z - z;
const distance = Math.sqrt(dx * dx + dz * dz);
return distance; // meters
}
// Usage
const distanceToSeaTac = distanceToWaypoint(47.4502, -122.3088);
console.log(`Distance to SeaTac: ${(distanceToSeaTac / 1852).toFixed(1)} NM`);Place Object at GPS Coordinates
typescript
function placeObjectAtCoordinates(
objPath: string,
lat: number,
lon: number,
altMSL: number,
heading: number
): { obj: string, instanceId: number } | null {
// Load the object
const obj = XPlane.scenery.loadObject(objPath);
if (!obj) {
console.error("Failed to load object");
return null;
}
// Convert GPS coordinates to local
const local = XPlane.graphics.worldToLocal(lat, lon, altMSL);
// Create and position instance
const instanceId = XPlane.instance.create(obj);
if (!instanceId) {
console.error("Failed to create instance");
return null;
}
XPlane.instance.setPosition(instanceId, {
x: local.x,
y: local.y,
z: local.z,
heading: heading
});
return { obj, instanceId };
}
// Place a marker at the Golden Gate Bridge
const marker = placeObjectAtCoordinates(
"path/to/marker.obj",
37.8199, // Latitude
-122.4783, // Longitude
70, // Altitude MSL
0 // Heading
);Create Flight Path Visualization
typescript
interface Waypoint {
lat: number;
lon: number;
alt: number;
}
class FlightPathMarkers {
private instances: number[] = [];
private obj: string | null = null;
constructor(markerObjPath: string) {
this.obj = XPlane.scenery.loadObject(markerObjPath);
}
showPath(waypoints: Waypoint[]) {
if (!this.obj) return;
// Clear existing markers
this.clearPath();
// Create marker at each waypoint
for (const wp of waypoints) {
const local = XPlane.graphics.worldToLocal(wp.lat, wp.lon, wp.alt);
const instanceId = XPlane.instance.create(this.obj);
if (instanceId) {
XPlane.instance.setPosition(instanceId, {
x: local.x,
y: local.y,
z: local.z
});
this.instances.push(instanceId);
}
}
}
clearPath() {
for (const instanceId of this.instances) {
XPlane.instance.destroy(instanceId);
}
this.instances = [];
}
destroy() {
this.clearPath();
if (this.obj) {
XPlane.scenery.unloadObject(this.obj);
}
}
}
// Usage
const path = new FlightPathMarkers("path/to/waypoint_marker.obj");
path.showPath([
{ lat: 47.4502, lon: -122.3088, alt: 3000 }, // SeaTac
{ lat: 47.6062, lon: -122.3321, alt: 3500 }, // Downtown Seattle
{ lat: 47.9790, lon: -122.2021, alt: 4000 }, // Everett
]);Notes
- Coordinate conversion accuracy depends on distance from the scenery reference point
- For very long distances (hundreds of kilometers), consider the Earth's curvature
- The local coordinate system shifts when loading new scenery
See Also
- Scenery API - Terrain probing and object loading
- Instance API - Object instancing
- DataRef API - Reading aircraft position