Use of scratch value in createVerticesFromQuantizedTerrainMesh

Hi All,

I’m just in the middle of implementing terrain quantisation for my Cesium port, and have come across this use of a scratch Cartesian3 in the vertex generation worker.

for (var i = 0; i < quantizedVertexCount; ++i) {
var u = uBuffer[i] / maxShort;
var v = vBuffer[i] / maxShort;
var height = CesiumMath.lerp(minimumHeight, maximumHeight, heightBuffer[i] / maxShort);
cartographicScratch.longitude = CesiumMath.lerp(west, east, u);
cartographicScratch.latitude = CesiumMath.lerp(south, north, v);
cartographicScratch.height = height;
var position = ellipsoid.cartographicToCartesian(cartographicScratch);
uvs[i] = new Cartesian2(u, v);
heights[i] = height;
positions[i] = position;
Matrix4.multiplyByPoint(toENU, position, cartesian3Scratch);
Cartesian3.minimumByComponent(cartesian3Scratch, minimum, minimum);
Cartesian3.maximumByComponent(cartesian3Scratch, maximum, maximum);

var bufferIndex = 0;
for (var j = 0; j < quantizedVertexCount; ++j) {
if (hasVertexNormals) {
var n = j * 2.0;
toPack.x = octEncodedNormals[n];
toPack.y = octEncodedNormals[n + 1];
if (exaggeration !== 1.0) {
var normal = AttributeCompression.octDecode(toPack.x, toPack.y, scratchNormal);
var fromENUNormal = Transforms.eastNorthUpToFixedFrame(cartesian3Scratch, ellipsoid, scratchFromENU);



It seems to be reset for each vertex but then used to generate normals for the next step even though it seemingly just ends up as the last vertex position in the array.

Is there some significance to this I’m missing?



Hi Ryan,

It’s used in the next lines to compute the min/max vertex positions, which are then used to building a bounding box for the tile.


Hi Kevin,

Thanks for replying.

It’s used in the next lines to compute the min/max vertex positions, which are then used to building a bounding box for the tile.

No I understand that, I just can’t quite work out the subsequent usage in the loop to compute normals for exaggerated terrain, as it seems to just end up as the last position following the position calculation loop.



Oh ok, I see what you mean now, sorry for stating the obvious before.

So yeah, that’s a bit odd. Either it’s a bug, or it’s “ok” to use any old point in the tile as the basis for the ENU reference frame for the purpose of computing an exaggerated normal. I suspect it actually is ok-ish. For high-detail tiles, the surface normal vector won’t vary much across the tile so it’s a valid optimization. For low-detail tiles (e.g. the root tiles), it’ll be pretty wrong, but maybe it doesn’t matter much because the globe is basically smooth at low detail anyway. If it was intentional, a comment saying so would probably be handy.

Maybe it’s worth a quick look by Dan Bagnell to make sure it’s not just a small oversight?


That was definitely not intentional. I think Kevin provided a good explanation of why we weren’t seeing any issues. I opened a PR to fix the issue here. Thanks Ryan and Kevin.