Demo terrain server offline or broken?


I’m trying out Cesium for a small project and I’m having some issues with getting any sample data to work.

Mostly I’m interested in the “quantized mesh” file format and would this like to get a few sample tiles to try

render using my own renderer. However, it seems that the terrain servers all return 404:s. Initially I looked

Hello Jan,

We moved the terrain server but forgot to change that page. Here’s the new link: ‘’,

You can see an example for how to add terrain to your app here:



Aha, that URL works fine. Thank you for the quick response!

Maybe I’ve misunderstood something, but are the tiles all supposed to be really, really minimal? Only the top level two tiles are about 2kB, all lower level tiles seem to be 300-700 bytes large.

Or can that little really contain all the required data for an entire tile?

I noticed that I had missed the to add the required header “Accept: application/vnd.quantized-mesh,application/octet-stream;q=0.9”. It was right

there on the specification page but I missed it. However it has no effect, the files are anyway a bit over 300 bytes.

Is the server broken, or is this interface simply not supported anymore?

What problem are you seeing with the files? Keep in mind that tiles are served with gzip compression, so if you are attempting to read the data, you’ll need to decompress.

Compressed? Damn, I’ve read that spec page over and over again and I missed the short sentence that said they are gzipped.

I focused on the endianess mentioned on the same line. Maybe the data will make sense now. Thank your for pointing that out to a

blind idiot. :slight_smile:

Still the format baffles me a bit. I test with the top level tile at:

It gives me data like:

center: 0.00, -6378137.00, 0.00

height: -328.05 -> 6969.12

bound: 818.29, -2674.96, -673.90

radius: 6381056.81

occlusion: 5.11, -83458803638346672.00, 0.00

vertices: 218

Values printed as std::fixed with precision 2. They look quite ok to me and the 6381 km radius looks quite fine. The vertex data

seems to be 218 vertices (210 for the other top level tile). However, here is where my ability to grok the format drops. I don’t see

the point of the zig-zag encode as each value is always two bytes regardless of how well it’s encoded. Maybe it gzip compresses

better when encoded? Anyway, reading some values and decoding them gives me:

u0 encoded: 0, decoded: 0

u1 encoded: 0, decoded: 0

u2 encoded: 4094, decoded: 2047

u3 encoded: 4096, decoded: 2048

u4 encoded: 0, decoded: 0

u5 encoded: 8189, decoded: 61441

u6 encoded: 20478, decoded: 10239

u7 encoded: 45056, decoded: 22528

u8 encoded: 53247, decoded: 38912

u9 encoded: 4096, decoded: 2048

u10 encoded: 8191, decoded: 61440

u11 encoded: 4607, decoded: 63232

u12 encoded: 3581, decoded: 63745

From what I understand the values should all be in the range [0 … 32767], but I get some much larger values than that.

Or does it mean that exactly 32767 is on the edge and other values [0 … 66635] are interpolated?

unsigned short enc = ...;

unsigned short dec = (enc >> 1) ^ (-(enc & 1));

Maybe the top level tiles aren’t meant for displaying? So lets look at 4/0/0.terrain:

center: -624229.18, -61481.21, -6325938.02

height: -55.49 -> 3970.41

bound: -634972.14, -4385.67, -6294132.10

radius: 638901.40

occlusion: -0.10, -0.01, -1.00

vertices: 17

u0 encoded: 16382, decoded: 8191

u1 encoded: 16381, decoded: 57345

u2 encoded: 0, decoded: 0

u3 encoded: 65534, decoded: 32767

u4 encoded: 0, decoded: 0

u5 encoded: 32767, decoded: 49152

u6 encoded: 24575, decoded: 53248

u7 encoded: 8189, decoded: 61441

u8 encoded: 8190, decoded: 4095

u9 encoded: 24576, decoded: 12288

u10 encoded: 32768, decoded: 16384

u11 encoded: 0, decoded: 0

u12 encoded: 16383, decoded: 57344

u13 encoded: 49149, decoded: 40961

u14 encoded: 32766, decoded: 16383

u15 encoded: 32765, decoded: 49153

u16 encoded: 65534, decoded: 32767

Similar large values. There’s something fundamental that I don’t get here.

You could try comparing your code with the Cesium code that decodes the data.

Yeah, I looked at that and also a few other language versions. I did the decoding myself in C++, Python and Java.

However, now that I look at it again, I see:

for (i = 0; i < vertexCount; ++i) {

u += zigZagDecode(uBuffer[i]);

v += zigZagDecode(vBuffer[i]);

height += zigZagDecode(heightBuffer[i]);

uBuffer[i] = u;

vBuffer[i] = v;

heightBuffer[i] = height;


Why the +=? According to the specification each value should be decoded and used as-is, there is no mention that it’s all a long

wrapping sum. Maybe the sum is something that’s inherent to using zig-zag encoding? Could have been good to mention it anyway.

Summing up I get values that look real (just some u values from a small tile):

u0 encoded: 16382, decoded: 8191

u1 encoded: 16381, decoded: 0

u2 encoded: 0, decoded: 0

u3 encoded: 65534, decoded: 32767

u4 encoded: 0, decoded: 32767

u5 encoded: 32767, decoded: 16383

u6 encoded: 24575, decoded: 4095

u7 encoded: 8189, decoded: 0

u8 encoded: 8190, decoded: 4095

u9 encoded: 24576, decoded: 16383

u10 encoded: 32768, decoded: 32767

u11 encoded: 0, decoded: 32767

u12 encoded: 16383, decoded: 24575

u13 encoded: 49149, decoded: 0

u14 encoded: 32766, decoded: 16383

u15 encoded: 32765, decoded: 0

u16 encoded: 65534, decoded: 32767

No value exceeds 32767, which is how it should be. A small mention about this property could have been nice.