# Cesium for Unreal Cesium for Unreal is a plugin that brings 3D geospatial capabilities to Unreal Engine. It enables high-accuracy visualization of real-world 3D content on a global scale using the WGS84 ellipsoid coordinate system. The plugin provides a runtime engine for streaming massive 3D Tiles datasets from the cloud or local sources, including terrain, imagery, 3D cities, and photogrammetry data. It integrates with Cesium ion for instant access to cloud-based global 3D content including Cesium World Terrain, Bing Maps imagery, and Google Photorealistic 3D Tiles. The plugin architecture centers around several key components: `ACesium3DTileset` for streaming 3D Tiles content, `ACesiumGeoreference` for coordinate system transformations between ECEF (Earth-Centered, Earth-Fixed) and Unreal coordinates, `UCesiumGlobeAnchorComponent` for anchoring actors to geographic positions, and various raster overlay components for draping imagery on terrain. The system supports sub-level streaming, dynamic origin shifting for precision at any location on the globe, and comprehensive Blueprint and C++ APIs for geospatial operations. ## ACesium3DTileset - 3D Tiles Streaming The primary actor for loading and rendering 3D Tiles datasets. It supports loading from Cesium ion, direct URLs, or generating from the georeference ellipsoid. The actor handles level-of-detail selection, tile caching, physics mesh generation, and multiple raster overlays. ```cpp // C++ - Create and configure a Cesium 3D Tileset from Cesium ion #include "Cesium3DTileset.h" void AMyActor::SpawnTileset() { // Spawn the tileset actor ACesium3DTileset* Tileset = GetWorld()->SpawnActor(); // Configure to load from Cesium ion Tileset->SetTilesetSource(ETilesetSource::FromCesiumIon); Tileset->SetIonAssetID(1); // Cesium World Terrain Tileset->SetIonAccessToken(TEXT("your-cesium-ion-access-token")); // Configure level-of-detail Tileset->SetMaximumScreenSpaceError(16.0); // Higher = less detail, better performance Tileset->MaximumSimultaneousTileLoads = 20; Tileset->MaximumCachedBytes = 256 * 1024 * 1024; // 256 MB cache // Enable physics Tileset->SetCreatePhysicsMeshes(true); Tileset->SetEnableDoubleSidedCollisions(false); // Configure rendering Tileset->SetUseLodTransitions(true); // Smooth LOD transitions Tileset->LodTransitionLength = 0.5f; // 0.5 second transitions // Bind to load completion event Tileset->OnTilesetLoaded.AddDynamic(this, &AMyActor::OnTilesetLoaded); } // Load tileset from URL instead of Cesium ion void AMyActor::LoadFromUrl() { ACesium3DTileset* Tileset = GetWorld()->SpawnActor(); Tileset->SetTilesetSource(ETilesetSource::FromUrl); Tileset->SetUrl(TEXT("https://example.com/tileset/tileset.json")); // Add custom request headers if needed TMap Headers; Headers.Add(TEXT("Authorization"), TEXT("Bearer your-token")); Tileset->SetRequestHeaders(Headers); } ``` ## ACesiumGeoreference - Coordinate System Management Controls how global geospatial coordinates (ECEF/WGS84) map to Unreal Engine coordinates. Defines the origin placement and provides transformation functions between coordinate systems. Essential for placing the globe in the Unreal world and maintaining precision. ```cpp // C++ - Working with CesiumGeoreference #include "CesiumGeoreference.h" void AMyActor::SetupGeoreference() { // Get or create the default georeference ACesiumGeoreference* Georeference = ACesiumGeoreference::GetDefaultGeoreference(GetWorld()); // Set origin to a specific location (Denver, Colorado) Georeference->SetOriginPlacement(EOriginPlacement::CartographicOrigin); Georeference->SetOriginLongitude(-105.25737); Georeference->SetOriginLatitude(39.736401); Georeference->SetOriginHeight(1609.0); // Height in meters above ellipsoid // Or set using a single vector (Longitude, Latitude, Height) FVector LLH(-122.4194, 37.7749, 0.0); // San Francisco Georeference->SetOriginLongitudeLatitudeHeight(LLH); // Set globe scale (100 = full scale, 50 = half scale) Georeference->SetScale(100.0); // Subscribe to georeference updates Georeference->OnGeoreferenceUpdated.AddDynamic( this, &AMyActor::OnGeoreferenceUpdated); } // Coordinate transformations void AMyActor::TransformCoordinates() { ACesiumGeoreference* Georeference = ACesiumGeoreference::GetDefaultGeoreference(GetWorld()); // Convert Longitude/Latitude/Height to Unreal position FVector LLH(-74.006, 40.7128, 10.0); // New York City FVector UnrealPos = Georeference->TransformLongitudeLatitudeHeightPositionToUnreal(LLH); // Convert Unreal position back to Longitude/Latitude/Height FVector ResultLLH = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(UnrealPos); // Convert ECEF coordinates to Unreal FVector ECEF(1215107.0, -4736682.0, 4081952.0); // Example ECEF position FVector UnrealFromECEF = Georeference->TransformEarthCenteredEarthFixedPositionToUnreal(ECEF); // Get East-South-Up transformation matrix at a location FMatrix ESUToUnreal = Georeference->ComputeEastSouthUpToUnrealTransformation(UnrealPos); // Transform rotation from Unreal to East-South-Up frame FRotator UnrealRotation = GetActorRotation(); FRotator ESURotation = Georeference->TransformUnrealRotatorToEastSouthUp( UnrealRotation, UnrealPos); } ``` ## UCesiumGlobeAnchorComponent - Geographic Actor Positioning An ActorComponent that anchors an actor to a specific geographic location on the globe. It automatically maintains the actor's position as the georeference origin changes and can adjust orientation based on globe curvature. ```cpp // C++ - Using CesiumGlobeAnchorComponent #include "CesiumGlobeAnchorComponent.h" void AMyActor::SetupGlobeAnchor() { // Add globe anchor component to this actor UCesiumGlobeAnchorComponent* GlobeAnchor = NewObject(this); GlobeAnchor->RegisterComponent(); // Move actor to specific coordinates (Eiffel Tower, Paris) FVector LLH(2.2945, 48.8584, 330.0); // Longitude, Latitude, Height GlobeAnchor->MoveToLongitudeLatitudeHeight(LLH); // Or move using ECEF coordinates FVector ECEF(4200983.0, 171996.0, 4780122.0); GlobeAnchor->MoveToEarthCenteredEarthFixedPosition(ECEF); // Get current position FVector CurrentLLH = GlobeAnchor->GetLongitudeLatitudeHeight(); double Longitude = GlobeAnchor->GetLongitude(); double Latitude = GlobeAnchor->GetLatitude(); double Height = GlobeAnchor->GetHeight(); // Configure orientation behavior GlobeAnchor->SetAdjustOrientationForGlobeWhenMoving(true); GlobeAnchor->SetTeleportWhenUpdatingTransform(true); // Snap actor to East-South-Up orientation GlobeAnchor->SnapToEastSouthUp(); // Or just align local up with ellipsoid normal GlobeAnchor->SnapLocalUpToEllipsoidNormal(); // Get/Set rotation in East-South-Up frame FQuat ESURotation = GlobeAnchor->GetEastSouthUpRotation(); GlobeAnchor->SetEastSouthUpRotation(FQuat::Identity); } ``` ## UCesiumFlyToComponent - Animated Camera Flights Smoothly animates an actor (typically a pawn/camera) to fly to a destination on the globe. Supports configurable flight curves, duration, and rotation interpolation. ```cpp // C++ - Flying to locations with CesiumFlyToComponent #include "CesiumFlyToComponent.h" void AMyPawn::SetupFlyTo() { // Add fly-to component UCesiumFlyToComponent* FlyTo = NewObject(this); FlyTo->RegisterComponent(); // Configure flight parameters FlyTo->Duration = 5.0f; // 5 second flight FlyTo->RotationToUse = ECesiumFlyToRotation::ControlRotationInEastSouthUp; // Optional: Set custom flight curves (loaded from Content) // FlyTo->ProgressCurve = LoadObject(...); // FlyTo->HeightPercentageCurve = LoadObject(...); // FlyTo->MaximumHeightByDistanceCurve = LoadObject(...); // Bind to flight events FlyTo->OnFlightComplete.AddDynamic(this, &AMyPawn::OnFlightComplete); FlyTo->OnFlightInterrupted.AddDynamic(this, &AMyPawn::OnFlightInterrupted); } void AMyPawn::FlyToDestination() { UCesiumFlyToComponent* FlyTo = FindComponentByClass(); // Fly to Longitude/Latitude/Height with specific orientation FVector Destination(-122.4194, 37.7749, 500.0); // San Francisco double YawAtDestination = 0.0; // Face North double PitchAtDestination = -30.0; // Look down 30 degrees bool CanInterruptByMoving = true; FlyTo->FlyToLocationLongitudeLatitudeHeight( Destination, YawAtDestination, PitchAtDestination, CanInterruptByMoving); } void AMyPawn::FlyToECEF() { UCesiumFlyToComponent* FlyTo = FindComponentByClass(); // Fly to ECEF coordinates FVector ECEFDestination(-2694044.0, -4266369.0, 3888310.0); FlyTo->FlyToLocationEarthCenteredEarthFixed( ECEFDestination, 45.0, -15.0, true); } void AMyPawn::InterruptCurrentFlight() { UCesiumFlyToComponent* FlyTo = FindComponentByClass(); if (FlyTo->IsFlightInProgress()) { FlyTo->InterruptFlight(); } } ``` ## UCesiumIonRasterOverlay - Cesium ion Imagery A raster overlay component that streams imagery from Cesium ion. Attach to a Cesium3DTileset to drape satellite imagery, maps, or other raster data over the 3D terrain. ```cpp // C++ - Adding raster overlays to a tileset #include "CesiumIonRasterOverlay.h" #include "CesiumBingMapsRasterOverlay.h" #include "CesiumPolygonRasterOverlay.h" void AMyActor::AddIonImagery(ACesium3DTileset* Tileset) { // Add Cesium ion raster overlay (e.g., Bing Maps Aerial) UCesiumIonRasterOverlay* IonOverlay = NewObject(Tileset); IonOverlay->IonAssetID = 2; // Bing Maps Aerial imagery IonOverlay->IonAccessToken = TEXT("your-cesium-ion-access-token"); IonOverlay->MaterialLayerKey = TEXT("Overlay0"); // Configure overlay quality IonOverlay->SetMaximumScreenSpaceError(2.0); IonOverlay->SetMaximumTextureSize(2048); IonOverlay->SetMaximumSimultaneousTileLoads(20); // Register and activate IonOverlay->RegisterComponent(); IonOverlay->Activate(true); } void AMyActor::AddBingMapsDirectly(ACesium3DTileset* Tileset) { // Add Bing Maps overlay directly (not through ion) UCesiumBingMapsRasterOverlay* BingOverlay = NewObject(Tileset); BingOverlay->BingMapsKey = TEXT("your-bing-maps-api-key"); BingOverlay->MapStyle = EBingMapsStyle::AerialWithLabelsOnDemand; BingOverlay->RegisterComponent(); BingOverlay->Activate(true); } void AMyActor::AddPolygonOverlay( ACesium3DTileset* Tileset, ACesiumCartographicPolygon* Polygon) { // Add polygon overlay for clipping or effects UCesiumPolygonRasterOverlay* PolyOverlay = NewObject(Tileset); PolyOverlay->Polygons.Add(Polygon); PolyOverlay->InvertSelection = false; PolyOverlay->ExcludeSelectedTiles = true; // Clip tiles inside polygon PolyOverlay->RegisterComponent(); PolyOverlay->Activate(true); } void AMyActor::RefreshOverlay(UCesiumRasterOverlay* Overlay) { // Refresh an overlay after changing properties Overlay->Refresh(); // Or remove and re-add Overlay->RemoveFromTileset(); Overlay->AddToTileset(); } ``` ## ACesiumCartographicPolygon - Geographic Polygons A spline-based polygon actor for defining geographic regions. Used with CesiumPolygonRasterOverlay for clipping, masking, or applying effects to specific areas of a tileset. ```cpp // C++ - Creating and using cartographic polygons #include "CesiumCartographicPolygon.h" void AMyActor::CreateClippingPolygon() { // Spawn a cartographic polygon ACesiumCartographicPolygon* Polygon = GetWorld()->SpawnActor(); // Define polygon points in Longitude/Latitude/Height TArray Points; Points.Add(FVector(-74.01, 40.70, 0.0)); // Point 1 Points.Add(FVector(-74.00, 40.70, 0.0)); // Point 2 Points.Add(FVector(-74.00, 40.71, 0.0)); // Point 3 Points.Add(FVector(-74.01, 40.71, 0.0)); // Point 4 Polygon->SetPolygonPoints( ECesiumCoordinateReferenceSystem::LongitudeLatitudeHeight, Points); // Or use ECEF coordinates TArray ECEFPoints; // ... populate with ECEF coordinates Polygon->SetPolygonPoints( ECesiumCoordinateReferenceSystem::EarthCenteredEarthFixed, ECEFPoints); } void AMyActor::ClipTileset( ACesium3DTileset* Tileset, ACesiumCartographicPolygon* Polygon) { // Add polygon overlay for clipping UCesiumPolygonRasterOverlay* ClipOverlay = NewObject(Tileset); ClipOverlay->Polygons.Add(Polygon); ClipOverlay->ExcludeSelectedTiles = true; ClipOverlay->InvertSelection = false; // Clip inside polygon ClipOverlay->RegisterComponent(); ClipOverlay->Activate(true); } ``` ## ACesiumSunSky - Globe-Aware Atmospheric Lighting A specialized sky and sun actor that provides accurate solar positioning based on geographic location, date, and time. Automatically adjusts atmosphere rendering based on camera position on the globe. ```cpp // C++ - Configuring CesiumSunSky #include "CesiumSunSky.h" void AMyActor::SetupSunSky() { ACesiumSunSky* SunSky = GetWorld()->SpawnActor(); // Set time and date SunSky->SolarTime = 14.0; // 2:00 PM SunSky->Day = 21; SunSky->Month = 6; // June SunSky->Year = 2024; // Set timezone (hours offset from GMT) SunSky->TimeZone = -5.0; // Eastern Time // Or estimate timezone from longitude SunSky->EstimateTimeZoneForLongitude(-74.0); // New York longitude // Configure Daylight Saving Time SunSky->UseDaylightSavingTime = true; SunSky->DSTStartMonth = 3; SunSky->DSTStartDay = 10; SunSky->DSTEndMonth = 11; SunSky->DSTEndDay = 3; // Update the sun position SunSky->UpdateSun(); // Get current sun position double Elevation = SunSky->Elevation; // Degrees above horizon double Azimuth = SunSky->Azimuth; // Degrees clockwise from North } void AMyActor::AnimateSunTime() { ACesiumSunSky* SunSky = /* get reference */; // Animate time of day float DeltaTime = GetWorld()->GetDeltaSeconds(); SunSky->SolarTime += DeltaTime * 0.1; // Speed up time if (SunSky->SolarTime >= 24.0) { SunSky->SolarTime -= 24.0; } SunSky->UpdateSun(); } ``` ## UCesiumOriginShiftComponent - Dynamic Origin Management Automatically shifts the Unreal world origin as the attached actor moves, maintaining precision at any location on the globe. Handles sub-level switching and continuous origin updates. ```cpp // C++ - Using CesiumOriginShiftComponent #include "CesiumOriginShiftComponent.h" void AMyPawn::SetupOriginShift() { UCesiumOriginShiftComponent* OriginShift = NewObject(this); OriginShift->RegisterComponent(); // Mode: Only shift when entering sub-levels OriginShift->SetMode(ECesiumOriginShiftMode::SwitchSubLevelsOnly); // Mode: Continuously shift origin as pawn moves OriginShift->SetMode(ECesiumOriginShiftMode::ChangeCesiumGeoreference); OriginShift->SetDistance(0.0); // Shift continuously (0 = always shift) // Mode: Shift when more than 10km from origin OriginShift->SetMode(ECesiumOriginShiftMode::ChangeCesiumGeoreference); OriginShift->SetDistance(10000.0); // 10km threshold } ``` ## Geocoder Service - Location Search Query the Cesium ion geocoder to search for locations and get their coordinates. Supports both full search and autocomplete for user input. ```cpp // C++ - Using the Geocoder service #include "CesiumGeocoderServiceBlueprintLibrary.h" // This is typically used via Blueprints with async nodes // The async action handles the network request void AMyActor::SearchLocation() { // Create the async action UCesiumGeocoderServiceIonGeocoderAsyncAction* Action = UCesiumGeocoderServiceIonGeocoderAsyncAction::Geocode( TEXT("your-cesium-ion-access-token"), nullptr, // Use default Cesium ion server ECesiumIonGeocoderProviderType::Default, ECesiumIonGeocoderRequestType::Search, TEXT("New York City")); // Bind to completion delegate Action->OnGeocodeRequestComplete.AddDynamic( this, &AMyActor::OnGeocodeComplete); Action->Activate(); } void AMyActor::OnGeocodeComplete( bool Success, UCesiumGeocoderServiceResult* Result, FString Error) { if (Success && Result) { for (const FCesiumGeocoderServiceFeature& Feature : Result->Features) { FString Name = Feature.DisplayName; FVector LLH = Feature.LongitudeLatitudeHeight; // Use the coordinates... } } } ``` ## Height Sampling - Query Terrain Heights Asynchronously query the height of a tileset at specific geographic positions. Useful for placing objects on terrain or calculating distances above ground. ```cpp // C++ - Sampling terrain heights #include "Cesium3DTileset.h" void AMyActor::SampleHeights(ACesium3DTileset* Tileset) { // Positions to sample (Longitude, Latitude, Height) // Height is ignored for input, used as fallback if sampling fails TArray Positions; Positions.Add(FVector(-74.006, 40.7128, 0.0)); // New York Positions.Add(FVector(-122.4194, 37.7749, 0.0)); // San Francisco Positions.Add(FVector(139.6917, 35.6895, 0.0)); // Tokyo // Start async height sampling Tileset->SampleHeightMostDetailed( Positions, FCesiumSampleHeightMostDetailedCallback::CreateUObject( this, &AMyActor::OnHeightsSampled)); } void AMyActor::OnHeightsSampled( ACesium3DTileset* Tileset, const TArray& Results, const TArray& Warnings) { for (const FCesiumSampleHeightResult& Result : Results) { if (Result.SampleSuccess) { FVector LLH = Result.LongitudeLatitudeHeight; double SampledHeight = LLH.Z; // Height in meters above ellipsoid // Use the height... } } // Check for any warnings for (const FString& Warning : Warnings) { UE_LOG(LogTemp, Warning, TEXT("Height sampling warning: %s"), *Warning); } } ``` ## Blueprint Integration Examples The plugin provides full Blueprint support for all major features. Here are common Blueprint patterns. ```cpp // Blueprint-equivalent operations in C++ // These demonstrate what's available in Blueprint graphs // Get default georeference ACesiumGeoreference* Geo = ACesiumGeoreference::GetDefaultGeoreference(WorldContext); // Transform coordinates (all Blueprint-callable) FVector UnrealPos = Geo->TransformLongitudeLatitudeHeightPositionToUnreal(LLH); FVector LLH = Geo->TransformUnrealPositionToLongitudeLatitudeHeight(UnrealPos); FVector ECEF = Geo->TransformUnrealPositionToEarthCenteredEarthFixed(UnrealPos); // Globe anchor operations UCesiumGlobeAnchorComponent* Anchor = Actor->FindComponentByClass(); FVector Position = Anchor->GetLongitudeLatitudeHeight(); Anchor->MoveToLongitudeLatitudeHeight(NewPosition); Anchor->SnapToEastSouthUp(); // Tileset operations ACesium3DTileset* Tileset = /* get reference */; float Progress = Tileset->GetLoadProgress(); // 0.0 to 1.0 Tileset->RefreshTileset(); // Reload tileset // Raster overlay operations UCesiumRasterOverlay* Overlay = /* get reference */; Overlay->Refresh(); Overlay->AddToTileset(); Overlay->RemoveFromTileset(); // Fly-to component UCesiumFlyToComponent* FlyTo = /* get reference */; FlyTo->FlyToLocationLongitudeLatitudeHeight(Destination, Yaw, Pitch, true); FlyTo->InterruptFlight(); ``` ## Summary Cesium for Unreal enables developers to build geospatial applications with global-scale 3D visualization capabilities. The primary use cases include: flight simulators and aviation training systems that require accurate global terrain and imagery; urban planning and architecture visualization with real-world context; GIS applications that need to visualize and analyze geographic data in 3D; gaming and simulation with realistic Earth environments; and digital twins of real-world locations. The plugin handles the complexity of streaming massive datasets efficiently while maintaining visual quality through level-of-detail algorithms. Integration patterns typically start with placing an `ACesiumGeoreference` to define the coordinate system origin, then adding `ACesium3DTileset` actors for terrain and buildings (often Cesium World Terrain and Google Photorealistic 3D Tiles via Cesium ion). Raster overlays like `UCesiumIonRasterOverlay` or `UCesiumBingMapsRasterOverlay` provide satellite imagery. For interactive applications, attach `UCesiumGlobeAnchorComponent` to movable actors and `UCesiumFlyToComponent` to player pawns for smooth navigation. Use `UCesiumOriginShiftComponent` on the player camera to maintain precision anywhere on the globe. The plugin's Blueprint support makes it accessible for rapid prototyping while the full C++ API enables deep customization for production applications.