Raster Mesh Creation - jgoffeney/Cesium4Unreal GitHub Wiki

Back

Description

The goal is to create meshes from elevation raster tiles. They need to be created to match imagery to use as textures.

Method

The raster meshes need to be converted to 3d vertices, uv texture coordinates, vertex normals and triangles.

Source Rasters

The source rasters for elevation and imagery are at the same resolution but to use the imagery as textures then the vertices need to be created from the intersections of the raster cells as shown below.

Raster

Vertices

Each vertex has an x, y and z component. To find the x and y components in meters you can use the raster's geospatial affine transform to get geospatial coordinates and if unprojected you can use a Haversine distance equation. For latitude and longitude it is worth noting the spacing between latitude points is constant for a given raster cell size while the longitude distances decrease as you approach the poles.

The z is the average of the values of the surrounding raster cells. The edge vertex z values should be identical between raster tiles so it is necessary to have an overlapping row of pixels between the adjacent rasters so the vertex averages are computed from the same values (to compute the vertex normals you need two overlapping rows and will be addressed below).

The units in Unreal are in centimeters so to convert from meters the x, y and z values should be multiplied by 100.

Vertex Normals

Normals are computed per vertex as the average of the face normals of the triangles surrounding the vertex. As noted above you need an extra row of pixels to compute the z value for the edge pixels. But to similarly ensure the edge vertices have the same normals between raster tiles you need to compute the z values for all the triangle points so you need an addition row (as shown below).

VertexNormals

Computing Face Normal

The snippet below computes the face normal for the triangle defined by FVector vertexIndices containing the three vertices in counter clockwise winding.

FVector v0 = vertices[_vertexIndices[0]];
FVector v1 = vertices[_vertexIndices[1]];
FVector v2 = vertices[_vertexIndices[2]];

FVector BA = v1 - v0;
FVector CA = v2 - v0;
FVector normVector = FVector::CrossProduct(CA, BA);
normVector.Normalize();

To compute the vertex normal, compute it for each triangle, add the results together and then divide the sum by the vector magnitude.

FVector vertexNormal = FVector(0);

for (unsigned int tIdx = 0; tIdx < triangles.size(); tIdx++) {
	vertexNormal += triangles[tIdx].computeNormal(vertices);
}

vertexNormal = vertexNormal / vertexNormal.Size();

Triangles

The triangles are created by three vertices in a counter clockwise winding. Note that these triangles do not need to be the same as the the triangles used to compute the vertex normals. For a raster the simplest method is to split each cell from upper left to the lower right into two triangles.

Triangles