[UE5] Limiting WebTileRasterOverlay Request Bounds to a Specific WMTS Sub-region (Fixed TileMatrix)

Hi Cesium Team and Community,

I am currently using CesiumWebTileRasterOverlay in Unreal Engine to load a custom WMTS service that generates heatmap data.

The Problem:
My WMTS service has specific constraints:

  1. The valid data only exists at TileMatrix level 7.
  2. The valid geographic extent is very limited, specifically within these tile coordinates:
    • TileCol: [209, 215]
    • TileRow: [36, 39]

Currently, when I add the overlay, Cesium attempts to request tiles based on the camera’s view and standard quadtree splitting. This results in two issues:

  • It requests tiles outside my valid range (which are empty or invalid).
  • It only shows a small fragment of the heatmap because it doesn’t seem to “lock” onto this specific small region effectively at the correct zoom level.

My Goal:
I want to configure the WebTileRasterOverlay (or use a specific material/logic) such that:

  1. Regardless of where the camera moves, the overlay focuses on displaying this specific rectangular region defined by the TileCol/TileRow bounds above.
  2. It forces the request to use TileMatrix 7 (or scales appropriately from it) so the heatmap covers the intended area completely, rather than trying to fetch global tiles.

Is there a way to set a custom bounding box or tile range limit for a WebTileRasterOverlay? Or should I be modifying the URL template to enforce these parameters?

Any advice on how to clamp the overlay to this specific sub-region would be greatly appreciated.

Thanks!

Hi @WorldtoStar, welcome to the forum!

I dug into the source for this one. A few things to untangle:

First, two quick checks on your service config

Which TileMatrixSet/CRS does your service use? I believe the Cesium for Unreal WMTS overlay (and Cesium Native underneath it) only supports Geographic (EPSG:4326) and Web Mercator (EPSG:3857), set via the Projection property. If your TileMatrixSet is in a different CRS, you’ll mostly see missing tiles (the tile indices won’t match your server’s matrix), and anything that does load will be draped in the wrong place. If your server publishes the same layer in multiple TileMatrixSets, pick the 3857 or 4326 one.

Also check the TileMatrix labels. The plugin never reads your capabilities document, so TileMatrixSetID must exactly match the identifier your server expects, and if your TileMatrix identifiers aren’t bare level numbers (many servers use labels like “EPSG:4326:7”), you need to set the Tile Matrix Set Label Prefix or specify the labels manually. Otherwise Cesium requests TileMatrix “7” and your server won’t recognize it.

Forcing level 7 as the deepest level requested

Set “Specify Zoom Levels” to true on the overlay, with Minimum Level = 0 and Maximum Level = 7. With that set, Cesium won’t request anything deeper than TileMatrix 7, and when the camera gets closer it upsamples the level 7 imagery onto the more detailed geometry, so your heatmap will still cover the area fully when zoomed in. I believe the plugin only applies these when Maximum Level is strictly greater than Minimum Level, so don’t set both to 7.

I suspect this is also behind the “small fragment” you’re seeing. By default the overlay requests levels much deeper than 7 as you zoom in, and those requests fail on your server, leaving only scattered pieces where level 7 happened to be used. The zoom clamp above should fix that. Separately, when the camera is far away Cesium may request levels 0-6, which also don’t exist on your server, so nothing will display zoomed out unless you generate downsampled tiles for those lower levels covering your extent. I’d recommend doing that if you can.

Limiting requests to your TileCol/TileRow range

Here I have less good news. Cesium Native (which Cesium for Unreal is built on) has a coverage rectangle option internally that does exactly what you want, limit requests to a geographic region without changing tile numbering, and CesiumJS exposes the same thing (the rectangle option on WebMapTileServiceImageryProvider). But the Cesium for Unreal component doesn’t currently expose it on its own.

You might be tempted by the “Specify Tiling Scheme” option with a rectangle matching your data extent, but that won’t work for your case: it renumbers the tiles relative to the custom scheme, so your server would receive TileCol/TileRow values that no longer match your TileMatrixSet numbering (209-215 / 36-39).

Two paths forward:

  1. Server-side guard (quickest): have your server return a fast 404 for out-of-range requests. Cesium handles failed tile requests gracefully, those areas just render without the overlay. The invalid requests are wasted round trips, but they’re cheap if the server rejects them quickly.

  2. Modify the plugin: if you’re comfortable building the plugin from source, look at CreateOverlay() in Source/CesiumRuntime/Private/CesiumWebMapTileServiceRasterOverlay.cpp. Cesium Native’s WebMapTileServiceRasterOverlayOptions already has a coverageRectangle field, the plugin currently only sets it inside the “Specify Tiling Scheme” branch (where it also replaces the tiling scheme, causing the renumbering). Adding a separate boolean like “Specify Coverage Rectangle” with its own west/south/east/north properties that set wmtsOptions.coverageRectangle without touching wmtsOptions.tilingScheme would give you exactly the behavior you need. If you build this, we’d welcome a pull request, it would bring the Unreal component in line with what CesiumJS already offers: cesium-unreal/CONTRIBUTING.md at main · CesiumGS/cesium-unreal · GitHub

I checked and there’s no existing feature request for this, so feel free to open one describing your use case either way: Issues · CesiumGS/cesium-unreal · GitHub

Hope that helps, let us know how it goes!