tweaking TerrainMesh?

Hi,

I want to create a mesh which is an offset of the terrain below it,
offset by a specific elevation vertically.

I could somehow re-create this by querying elevation points using
sampleTerrain(), but I was wondering, isn't there a 'straightforward'
way to re-use TerrainMesh, which (judging from its name) exactly
represents the terrain elevation mesh?

(this would be in the batching branch)

Akos

I agree: there’s probably no reason to call sampleTerrain. What you should do instead depends on what you need the mesh for, however. Is your offset fixed for the entire tile, or will different height samples have different offsets? Are you planning to render the adjusted mesh, or use it for another purpose?

Kevin

the use case is that I have to render 'airspaces' (for aviation
purposes), some of which are defined like '1500ft above ground level'.
the airspace is otherwise bounded by a polygon

so, I'll need to render the offset to the terrain, bounded by a
particular polygon

one way of doing this would be to get a TerrainMesh, offset it, and 'cut
it' to polygon boundaries

Ok, that makes sense.

You’re going to have a couple of problems using TerrainMesh for that, though.

One is actually getting your hands on a TerrainMesh. They’re created by the terrain engine, but they exist only transiently. Once the mesh has been uploaded to the GPU as a vertex buffer, the TerrainMesh is discarded.

Another is bounding the mesh by a polygon. You’ll presumably have to walk through the mesh, testing each vertex to determine if it is inside or outside the polygon. And I’m guessing you’ll want to interpolate new vertices for the perimeter of your polygon as well. This will be especially tricky (read: slow) because the mesh vertices are expressed in a Cartesian space and your polygon is probably defined using lat/long points.

You might be better off working with the heightmap terrain data (HeightmapTerrainData) rather than the mesh representation of it. For one thing, it is kept around longer by the terrain engine. For another, it is a regular grid in lat/long space, which should make it much easier to test against the polygon. HeightmapTerrainData has a method to create a mesh from it, but you probably won’t be able to use it directly because your mesh won’t be a regular grid in the end. But you should be able to follow the general approach used by that method to create a mesh from the heights inside the polygon, plus some additional interpolated heights on its perimeter.

Sorry this isn’t anywhere near an easy answer, but I hope it helps.

Kevin

Kevin,

Ok, that makes sense.

You're going to have a couple of problems using TerrainMesh for that,
though.

One is actually getting your hands on a TerrainMesh. They're created
by the terrain engine, but they exist only transiently. Once the mesh
has been uploaded to the GPU as a vertex buffer, the TerrainMesh is
discarded.

Another is bounding the mesh by a polygon. You'll presumably have to
walk through the mesh, testing each vertex to determine if it is
inside or outside the polygon. And I'm guessing you'll want to
interpolate new vertices for the perimeter of your polygon as well.
This will be especially tricky (read: slow) because the mesh vertices
are expressed in a Cartesian space and your polygon is probably
defined using lat/long points.

You might be better off working with the heightmap terrain data
(HeightmapTerrainData) rather than the mesh representation of it.

I was looking at HeightmapTerrainData, and from the usage example in the
documentation, or from looking at references in the cesium source code,
it's not immediately clear to how to use it :slight_smile: what is actually not
clear: how would I specify the area for which I'd like to have height
map data for?

the actual documentation says:

var buffer = ...
var heightBuffer = new Uint16Array(buffer, 0, that._heightmapWidth *
that._heightmapWidth);
var childTileMask = new Uint8Array(buffer, heightBuffer.byteLength, 1)[0];
var waterMask = new Uint8Array(buffer, heightBuffer.byteLength + 1,
buffer.byteLength - heightBuffer.byteLength - 1);
var structure = HeightmapTessellator.DEFAULT_STRUCTURE;
var terrainData = new HeightmapTerrainData({
  buffer : heightBuffer,
  width : 65,
  height : 65,
  childTileMask : childTileMask,
  structure : structure,
  waterMask : waterMask
});

without elaborating on 'buffer'. the use cases are see, for example in
EllipsoidTerrainProvider:

        var width = 16;
        var height = 16;
        this._terrainData = new HeightmapTerrainData({
            buffer : new Uint8Array(width * height),
            width : 16,
            height : 16
        });

doesn't seem to specify any particular area.

CesiumTerrainProvider uses a buffer that is created by loadArrayBuffer:

            var heightBuffer = new Uint16Array(buffer, 0,
that._heightmapWidth * that._heightmapWidth);
            return new HeightmapTerrainData({
                buffer : heightBuffer,
                childTileMask : new Uint8Array(buffer,
heightBuffer.byteLength, 1)[0],
                waterMask : new Uint8Array(buffer,
heightBuffer.byteLength + 1, buffer.byteLength - heightBuffer.byteLength
- 1),
                width : that._heightmapWidth,
                height : that._heightmapWidth,
                structure : that._terrainDataStructure
            });

where it's not immediately clear what that buffer would contain?

thus, can you please explain, or provide an example / more details on
how to use HeightmapTerrainData to get terrain info for a particular area?

sorry for not being more clever on this :frowning:

Akos

HeightmapTerrainData doesn’t retrieve terrain data - that’s the job of the TerrainProviders - it simply holds the heightmap terrain data for a single tile. The actual structure of the ‘buffer’ is flexible and is defined by the structure parameter passed to the constructor. The extent covered by the data is not known to HeightmapTerrainData itself. Notice that the extent is passed to methods (like createMesh) that need it.

If you want to retrieve tiles independently, take a look at the sampleTerrain function, because it does the same. If you’re counting on the terrain data you need already being loaded for rendering purpose, you’ll need to root around in CentralBodySurface to pull out the data that the rendering engine has already loaded.

What you’re trying to do is going to be tricky…

Kevin