Mean Sea Level at Height = 0 does not equate to sea surface placement

I don’t understand what I’m doing wrong here…could someone from Cesium team help me debug. In my Unreal Engine 5.6 project I simply have an Actor spawner that:

  • Spawns a bunch of simple cube-actors (scaled by 10) scattered randomly around a lat/lon box roughly covering the Falkland Islands.

  • For each spawn, I treat altitude = 0 m as “sea level (MSL)”. I run it through GeographicLib’s geoid model (using “egm2008-2_5”) to convert to ellipsoidal height via geoid(lat, lon), then feed that into the actor’s CesiumGlobeAnchorComponent — so that should put the cube flush with actual sea-surface.

The problem: some cubes appear roughly at sea surface (as expected), but some are floating ~10–40 m above water.

I recorded a quick video of this to show what I mean.

CesiumForUnreal Demo MSL to Ellipsoidal height

here’s the code I use for the conversion and the spawning:

void AFalklandsSpawner::SpawnAt(double Lat, double Lon, double AltMSL)
{
	double geoidN = QueryGeoidHeight(Lat, Lon);
	double ellipsoidH = AltMSL + geoidN;

	FActorSpawnParameters spawnParams;
	AActor* newActor = GetWorld()->SpawnActor<AActor>(ActorToSpawn, FTransform::Identity, spawnParams);
	if (!newActor) return;

	// Add Cesium anchor
	UCesiumGlobeAnchorComponent* anchor = NewObject<UCesiumGlobeAnchorComponent>(newActor);
	anchor->RegisterComponent();
	newActor->AddInstanceComponent(anchor);

	FVector lonLatH = FVector(Lon, Lat, ellipsoidH);
	anchor->MoveToLongitudeLatitudeHeight(lonLatH);
	anchor->SnapLocalUpToEllipsoidNormal();

	// make actor big so it's visible
	newActor->SetActorScale3D(FVector(10.0, 10.0, 10.0));
}
double AFalklandsSpawner::QueryGeoidHeight(double Lat, double Lon) const
{
	using namespace GeographicLib;
	const std::string geoidModel = "egm2008-2_5";
	const Geoid geoid(geoidModel, /*dirname=*/"", /*threadsafe=*/true);
	return geoid(Lat, Lon);
}
double AFalklandsSpawner::RandomRange(double Min, double Max) const
{
	return FMath::Lerp(Min, Max, UKismetMathLibrary::RandomFloat());
}

Why are some cubes significantly above the “sea level plane”? Is this expected geoid-to-ellipsoid height variation around Falklands, or am I doing something wrong?

Any pointers what I should check next — or is this a known caveat when placing objects at MSL = 0 with geoid conversion in Cesium for Unreal?

@Kevin_Ring Sorry to ping you like this, but I noticed your name popping up in replies to similar posts, so I thought I’d ask the best person for the job :sweat_smile:

Thanks in advance :folded_hands:

Hi @darkmattersun, welcome to the community!

What’s the underlying tileset you’re comparing against there? Is it possible the tileset is wrong? i.e., the sea isn’t at MSL=0 in that area?

I don’t think this should be an issue, but one thing to check: does it match better if you remove the 10x scale?

Thank you for taking the time to reply Kevin, I initially used the Google Photorealistic 3D Tiles, after reading your comment I went and swapped them with Cesium World Terrain + Bing Aerial Maps and now all the cube actors at MSL = 0 are all exactly on the sea surface :raising_hands:. I don’t understand though why the Google tileset had this issue and why the Cesium World Terrain + Bing Aerial Maps tiles doesn’t? I went back and checked the Google Tiles set again, and noticed something interesting, it might just be coincidence, but I notice that cubes on tiles closer to actual terrain (light blue), had their altitude displayed correctly, whereas those placed over tiles representing open ocean (darker blue) had the displacement issue, it almost seemed like the further out you go into the ocean the worse it gets​:thinking:, you can see that in the video I shared as well, cubes that are placed at lat long corresponding to bodies of water in-land were placed right at surface level when their MSL height was 0, but the other cubes in the open ocean where meters off.

It’s hard to say what’s going on there @darkmattersun. We’re unfortunately not privy to Google’s process for producing Google Photorealistic 3D Tiles. If you believe their data is wrong, you should consider reporting to it to them. It’s worth considering - though I don’t think this is what’s going on here - whether the problem is that the tileset includes bathymetry in this area. That is, the terrain is following the undersea surface?