Local tiles in the cesium viewer

It may be obvious question to others but it is making my work difficult. I have setup cesium 3d globe locally and accessing different imagery as WMS, TMS etc. While globe is sending the request to the local tiles and retrieving also, it is not visible on the globe. What could be reason for this?

S Shadab

What do you mean by local? The tiles must come from a web server of some sort; loading files directly from the file system (file:// URL) will not work due to browser restrictions. While the the browser may successfully go download such files, they can’t be used within WebGL because they are considered “cross origin”. This is true even if the Cesium Viewer page is accessed with a similar file:// URL as well.

If you mean a web server running on localhost, the problem is probably different. Are you getting any errors in the console?


Local tiles mean they are being served by a web server say apache. In my ImageryProviders, I am using TileMapServiceImageryProvider. URL for this is http://localhost/folder path for tiles.
When we see the firebug request, we could understand that globe is calling the tile correctly and it is retrieving also but it is not displayed on the globe.

Is the HTML page also served from the same server as your tiles? If not, you’ll need to configure the tile server to provide a CORS header to enable the images to be used in WebGL. This page has background information and instructions: http://enable-cors.org/

Could you share the code you’re using to configure and add the imagery provider?


code which is showing error when i am using tms is
// code to make widget and to remove the previous layer
var widget = new Cesium.CesiumWidget(‘cesiumContainer’);

var layers = widget.centralBody.getImageryLayers();


// code to put local tiles on 3d globe in cesium viewer by using tms

layers.addImageryProvider(new Cesium.TileMapServiceImageryProvider({

url : ‘http://localhost/for3dviewer’,

fileExtension: ‘png’,

maximumLevel: 10


but when i am using openstreetmap service then it is showing image on 3d globe so this is the code of osm service

layers.addImageryProvider(new Cesium.OpenStreetMapImageryProvider({

url : ‘http://tile.openstreetmap.org/



The code looks reasonable, so I can think of two possibilities. One is that it’s a CORS problem, as I mentioned before. Is the HTML file also running on http://localhost/…? It has to be the exact same port, even.

The other possibility is that your TMS tileset is somehow bad. I would expect an error in the console in that case, but maybe not. Does your TMS tilset have a tilemapresource.xml file? If so, can you share it?


yes it has tilemapresource.xml file n its here

<?xml version="1.0" encoding="utf-8"?> c1-19feb11-geo.img


Looks reasonable. This is only going to cover a tiny part of the globe, though. The rest will appear blue. Which version of Cesium are you using? Some older versions of Cesium may have had trouble with this TMS tileset because it starts at level 9, but newer versions should work fine.

Also, you didn’t answer my question about the servers.

no html file is running on localhost:8080
and i am using Cesium- b19 version of cesium

Ok, I recommend you upgrade to the latest version of Cesium. Then, change your code to use the proxy, like this:

layers.addImageryProvider(new Cesium.TileMapServiceImageryProvider({

url : ‘http://localhost/for3dviewer’,

fileExtension: ‘png’,

maximumLevel: 10,

proxy: new Cesium.DefaultProxy(’/proxy/’)


Better yet, enable CORS on the tile server, as I described before. But if you can’t do that, this proxy should work, assuming your localhost:8080 server is the standard web server that comes with Cesium.

Same problem here:

I can start up the node js server and browse to localhost:8080 and get index.html

I have a TMS sitting in a folder called /HRquad in the root folder.

I have edited HelloWorld.html to be:

var cesiumWidget = new Cesium.CesiumWidget(‘cesiumContainer’);

var layers = cesiumWidget.centralBody.getImageryLayers();

var tms = layers.addImageryProvider(new Cesium.TileMapServiceImageryProvider({

url : ‘http://localhost:8080/HRquad’,

proxy: new Cesium.DefaultProxy(’/proxy/’),


When I load that in firebug it looks like my tilremapresource.xml is getting found because it shows up as the response to the GET call.

With the break-on-all-errors property set, the error that gets thrown is ‘n is undefined’ on line 434 in Cesium.js in function T(e). That’s as far as I can track the problem.

Any suggestions?

I am using version b22

Wait, the ‘n is undefined’ error is not within function T(e). The first place n is defined in that line is in

var r=new c({attributes:{position:new h({componentDatatype:n.FLOAT

Try it with the unminified version of Cesium.js to more easily see what the error is. You can either download the “full” Cesium zip file, or you can change the script tag at the top of your HelloWorld.html to point to http://cesium.agi.com/releases/b22/Unminified/Cesium.js to load directly off the website.

Cool, that is much better.
I see now I am getting errors because of discrepancies in case between my .xml file and the loadXML function.

For instance, the loadXML function defines:

var format = xml.getElementsByTagName(‘TileFormat’)[0]; and the element in my file is ‘tileformat’

I can fix the problems manually, obviously, but I wonder if the function could re-written to be case-insensitive.

For the record, I used Global Mapper to export my TMS.

There seems to be more of an issue than just case. Here is the tilemapresource.xml that GlobalMapper is spitting out, edited for case by me:

<?xml version="1.0"?> HRquad


and the error that gets thrown now is ‘neTile is undefined’. I have been tracking the problem backwards and it appears that the tilingScheme is maybe getting incorrectly defined? not sure.

Hey Evan,

I think the problem is that the BoundingBox specifies the extent in Web Mercator meters, instead of geodetic decimal degrees like Cesium expects. Arguably this is correct, although I swear I’ve seen EPSG:900913 TMS resources that use decimal degrees there. I’ll check into it and get back to you.



So the TMS specification (http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification), such as it is, is not completely clear about what the units of the BoundingBox property should be. It’s never stated explicitly, but the examples clearly include some BoundingBoxes that are not geodetic degrees. Meanwhile, MapTiler, which is the main tool I’ve used to create TMS tilesets, uses geodetic longitude and latitude even when the SRS is EPSG:900913. Ugh. I think supporting both will require Cesium to guess the units based on the magnitude of the numbers or some such nonsense.

Regarding case, XML tags are case sensitive, and both the spec and MapTiler agree that PascalCase should be used. So in that case I’d say that GlobalMapper is generating incorrect output. We can change Cesium to be more tolerant of this, though. Scott wrote an issue for that: https://github.com/AnalyticalGraphicsInc/cesium/issues/1299.

Another gotcha: Cesium expects the profile to say “geodetic” or “mercator”, consistent with the output produced by MapTiler. But the spec says those should be called “global-geodetic” and “global-mercator”. It will be easy enough to change Cesium to support either. In your particular case, you should be ok, though, because the default tiling scheme for unrecognized profiles is WebMercator.

As a workaround prior to a fix, you should be able to use Cesium’s WebMercatorProjection class to manually transform the BoundingBox coordinates from 900913 to 4326 and update your tilemapresource.xml.


Ok, that’s kind of what I thought was going on. Thanks for checking. I have seen the developer of GM react pretty quickly to requests and suggestions, so I will post something over there.

i have a similar problem and my tiles cover just a part for the globe. i generated the tiles with gdal2tles. How can i fit it to the entire globe. I don't know where the problem is? Can you help me please. It works fine if i replace with 'NaturalEarthII' which is in the same folder and look like it has the "same propreties". Here is the code:

var viewer = new Cesium.Viewer('cesiumContainer', {
  imageryProvider : new Cesium.TileMapServiceImageryProvider({
    url : Cesium.buildModuleUrl('Assets/Textures/newglobe'), credit : 'New Globe'
  baseLayerPicker : false,
  geocoder : false

and tilemapressource.xml

<?xml version="1.0" encoding="utf-8"?>
    <TileMap version="1.0.0" tilemapservice="http://tms.osgeo.org/1.0.0">
      <BoundingBox minx="-90.00000000000000" miny="-180.00000000000000" maxx="90.00000000000000" maxy="180.00000000000000"/>
      <Origin x="-90.00000000000000" y="-180.00000000000000"/>
      <TileFormat width="256" height="256" mime-type="image/png" extension="png"/>
      <TileSets profile="geodetic">
        <TileSet href="0" units-per-pixel="0.70312500000000" order="0"/>
        <TileSet href="1" units-per-pixel="0.35156250000000" order="1"/>
        <TileSet href="2" units-per-pixel="0.17578125000000" order="2"/>
        <TileSet href="3" units-per-pixel="0.08789062500000" order="3"/>
        <TileSet href="4" units-per-pixel="0.04394531250000" order="4"/>
        <TileSet href="5" units-per-pixel="0.02197265625000" order="5"/>
        <TileSet href="6" units-per-pixel="0.01098632812500" order="6"/>


Can you share a sample of the imagery you sent through gdal2tiles?