# How God's Eye View Handles Aircraft and Ship Icon Orientation in Cesium.js

> Learn how God's Eye View orients aircraft and ship icons in CesiumJS using screen-space projection and deadband stabilization for smooth visuals. See the code implementation.

- Repository: [Bilawal Sidhu/gods-eye-view](https://github.com/bilawalsidhu/gods-eye-view)
- Tags: how-to-guide
- Published: 2026-09-13

---

**God's Eye View orients aircraft and ship icons by projecting world-space heading vectors onto the camera's screen-space basis and applying a 0.5° deadband stabilization to prevent jitter, implemented in [`src/data/iconOrientation.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/iconOrientation.js) and applied to Cesium billboards in the flights and vessels rendering layers.**

God's Eye View, an open-source Cesium-based tracking visualization in the `bilawalsidhu/gods-eye-view` repository, renders real-time aircraft and maritime traffic. Handling **aircraft and ship icon orientation** requires converting geographic course data into screen-space billboard rotations that remain accurate regardless of camera position or viewing angle.

## The Challenge of Camera-Facing Billboards

Cesium billboards are camera-facing quads that always rotate to face the viewer. This makes standard world-space rotation impossible because the icon must appear to point in the direction of travel while remaining perpendicular to the camera's view direction. The solution requires transforming the entity's course vector into screen-space coordinates relative to the current camera orientation.

## Screen-Space Projection Pipeline

### Converting World Heading to Screen Coordinates

The core logic resides in [`src/data/iconOrientation.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/iconOrientation.js) within the `screenProjectedRotation` function (lines 52-80). This utility converts a heading in degrees clockwise from north into a stable screen-space rotation angle.

The function projects the world-space forward vector onto the camera's right (`camera.rightWC`) and up (`camera.upWC`) vectors. It calculates screen-space components (`dx`, `dy`) and derives the rotation angle using `Math.atan2(-dx, -dy)`. This approach ensures the icon points correctly even when the entity is behind the camera or in tracked-orbit mode.

### Stabilizing Sub-Degree Rotations

Rapid micro-changes in calculated angles cause visual jitter. The `stabilizeScreenRotation` function (lines 92-100 of [`src/data/iconOrientation.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/iconOrientation.js)) compares the newly computed angle with the previous frame's rotation. If the angular difference falls below the **0.5° deadband threshold**, the function retains the previous rotation value, smoothing out insignificant variations while preserving responsiveness to actual course changes.

## Entity-Specific Implementation

### Aircraft Icons in flights/rendering.js

For aircraft tracking, the orientation helpers are imported and applied in [`src/layers/flights/rendering.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/layers/flights/rendering.js) at line 1172. Each aircraft billboard's `rotation` property receives the stabilized screen-projected value, ensuring flight icons align with their ADS-B reported heading.

### Ship Icons in vessels/rendering.js

Maritime vessels utilize identical orientation logic in [`src/layers/vessels/rendering.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/layers/vessels/rendering.js) at line 199. The system processes AIS-reported courses through the same projection pipeline, allowing ship icons to point along their actual track regardless of the map's current perspective.

## Icon Assets and Visual Reference

The actual SVG silhouettes rendered as billboards are defined in [`src/data/aircraftIcons.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/aircraftIcons.js) (lines 15-19). These nose-up white glyphs—including airliner, widebody, and turboprop variants—are rendered as data-URI billboards. The rotation calculated by the orientation pipeline is applied to these assets, making the icons appear to point in the direction of travel.

## Practical Implementation Example

```javascript
// Pattern used in src/layers/flights/rendering.js
import { screenProjectedRotation, stabilizeScreenRotation } from '@/data/iconOrientation';

let previousRotation = null;

// scene: Cesium.Scene, position: Cartesian3, courseDeg: number from ADS-B/AIS
const projected = screenProjectedRotation(scene, position, courseDeg, previousRotation);
const stableRotation = stabilizeScreenRotation(previousRotation, projected);

// Apply to Cesium billboard entity
billboard.rotation = stableRotation;
previousRotation = stableRotation; // Store for next frame's deadband comparison

```

The same pattern applies to maritime vessels in [`src/layers/vessels/rendering.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/layers/vessels/rendering.js), ensuring consistent orientation behavior across both domain types.

## Summary

- **Screen-space projection**: The `screenProjectedRotation` function in [`src/data/iconOrientation.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/iconOrientation.js) converts world heading to camera-relative rotation using `camera.rightWC` and `camera.upWC` basis vectors with `Math.atan2(-dx, -dy)`.
- **Jitter prevention**: The `stabilizeScreenRotation` function applies a 0.5° deadband to suppress sub-degree oscillations while maintaining responsiveness to actual course changes.
- **Cross-domain usage**: Both aircraft ([`src/layers/flights/rendering.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/layers/flights/rendering.js)) and ships ([`src/layers/vessels/rendering.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/layers/vessels/rendering.js)) use identical orientation logic imported from the central utility module.
- **Asset definition**: SVG silhouettes in [`src/data/aircraftIcons.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/aircraftIcons.js) serve as the visual base for rotated billboards.

## Frequently Asked Questions

### Why can't billboards be rotated in world space directly?

Cesium billboards are implemented as camera-facing quads that always orient toward the viewer. World-space rotation would cause the icon to appear tilted or edge-on when viewed from certain angles. By projecting the heading vector onto the camera's screen-space basis (`rightWC` and `upWC`), the icon remains flat to the viewer while pointing in the correct geographic direction.

### What is the default deadband threshold for rotation stabilization?

The default deadband is **0.5 degrees** (approximately 0.0087 radians). The `stabilizeScreenRotation` function compares the new rotation angle against the previous frame's value and suppresses updates below this threshold, preventing visual jitter from minor floating-point variations or sensor noise.

### How does the system handle entities behind the camera?

The screen-space projection method using `Math.atan2(-dx, -dy)` on the camera's right and up vectors produces correct orientation even when entities are behind the camera or in tracked-orbit mode. This ensures icons remain visually consistent regardless of the entity's position relative to the camera frustum.

### Where are the aircraft icon graphics defined?

The SVG silhouettes are defined in [`src/data/aircraftIcons.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/aircraftIcons.js) (lines 15-19) as data URIs. These include multiple aircraft types (airliner, widebody, turboprop) rendered as nose-up white glyphs that rotate based on the calculated screen-space rotation values applied in the rendering layers.