I have a custom terrain (quantized mesh output by CTB) that only cover a small area. I want to embed this small area to default Cesium 3D terrain. The constraints are that I cannot upload the data, and I cannot modify the input file (include the layer.json file of the terrain). The terrain is provided as a URL.
I have read this post about ground-push plug-in, but I am not sure it is similar to what I need. I was hoping I could simply replace the url to Cesium ION URL while requesting the tiles from url. The tiles at same postion on same layer shoule have same size, right?
My idea is to write a custom terrain provider by copying the the CesiumTerrainProvider and do some adjustments. Let’s call the new class fallbackTerrainProvider
. Here is my plan:
- Always return
true
in thegetTileDataAvailable
function to make all the tiles be requested. - Check the availability before the
requestTileGeometry()
is called inprototype.requestTileGeometry()
(CesiumTerrainProvider.js:905), if the tile is within custom terrain tileset, the terrain provider and the request of custom terrain will be passed in; if it is outside the custom terrain tileset, pass in adefaultTerrainProvider
and a request.
I created the defaultTerrainProvider
in some other module as follow:
- Create a resource:
default_resource = await Cesium.IonResource.fromAssetId(1);
- Create provider:
const defaultTerrainProvider = await Cesium.CesiumTerrainProvider.fromUrl(
default_resource,
{ requestVertexNormals: true }
);
The resource and provider are defined in a class in another module and was initialized before creating the fallbackTerrainProvider
object.
3. In prototype.requestTileGeometry()
, if the tile is not available in the custom tileset, pass the provider and request of the resource created above:
...
if (is_from_custom_source(this, x, y, level)) {
// same as original code
return requestTileGeometry(this, x, y, level, layerToUse, request);
else{
// not available in custom tileset
// make up some layer info
layerToUse.resource = defaultResource.d_resource;
layerToUse.version = "1.2.0";
layerToUse.availabilityTilesLoaded = new TileAvailability(
defaultResource.defaultTerrainProvider._tilingScheme,
19
);
return requestTileGeometry(
defaultTerrainProvider,
x,
y,
level,
layerToUse,
d_resource.request
);
In code above, I also changed the layerToUse
variable. If I do not add those info, I would recieved a Type Error in createQuantizedMeshTerrainData()
function.
Now I have the following error that causes the app to crash:
I have no idea about the Resource already being fetched error. However I did find out that if I set the d_resource.request
in code snipet above back to request
, the Resource already being fetched error would be gone, but Cesium would have some weired behavior. The world terrain else where are loaded correctly, but the region of my custom terrain is a bit spiky:
There are some stripes made of dynamic water texture on earth:
And my custom terrain would also fail to load. Not a single request was sent to the url.
Any suggestion on how to approach the goal (embed custom terrain in global terrain ) or fix the issue is appreciated.