3D Tiles v1.1 - 3DTILES_content_gltf extension

I’m trying to use glTF 2.0 assets directly as 3D Tiles v1.1 content by applying 3DTILES_content_gltf extension. While any instructive documents are rate to find, I’ve come to perceive that

  • a preprocess to create or obtain a 3D Tiles tileset which references the glTF models is needed
  • and loading the 3D Tiles tileset with the 3DTILES_content_gltf extension suffices the goal. For example,

var tileset = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: “path/to/tileset”,
extensions: [“3DTILES_content_gltf”],

Here, I have a question. How can I create the tileset (in relevance with glTF files) which is ready for the 3DTILES_content_gltf extension?

The 3DTILES_content_gltf extension is an extension for 3D Tiles 1.0. There, the extension allows using glTF assets (.gltf or .glb files) directly as the tile content.

In 3D Tiles 1.1, this extension is obsolete. One could say that it has become part of the core specification in 3D Tiles 1.1.

So when you create a 3D Tiles 1.1 tileset (as indicated by tileset.asset.version === "1.1"), you don’t have to use, declare, or mention the 3DTILES_content_gltf extension at all. You can just use glTF assets as tile content.

Thanks a lot for clarifying the differences between 3D Tiles 1.0 and 1.1. Frankly speaking, it has been in a grey area in my understanding. Then, may I ask a favor of you - how should the code block of 6 lines change in the previous note?

There has been a change in the API at this point, in CesiumJS version 1.107. See the change log for 1.107 for details.

If you are using version 1.107 or later, then the code to create a tileset should be this:

const tileset = viewer.scene.primitives.add(
  await Cesium.Cesium3DTileset.fromUrl(

I.e. just await ... fromUrl with the proper URL for your case.

For older versions, it should be the code that you already posed, but you could just omit the extensions part.

Thanks again for the update. It really helped my understanding. While I still have some confusion, I just want to know how I can get the tileset.json.

In case of 3D Tiles 1.0 and the 3D Tiling Pipeline, the relevant tilers provide tileset.json as part of the output tileset. However, now I intend to use glTF 2.0 assets directly as 3D Tiles v1.1 content. Here, I don’t know how to describe/write the tileset.json.

  • Is the JSON format the same as that of 3D Tiles v1.0?
  • How can I lay out the root and children tiles?
  • How can I calculate each tile’s boundingVolume, geometricError, etc.

Let’s consider a single glTF file at cesium/Apps/SampleData/models/CesiumAir/Cesium_Air.glb at main · CesiumGS/cesium · GitHub, and suggest me a tileset.json to access it. That will greatly consolidate my comprehension.

Many thanks,

In 3D Tiles 1.1, new features have been added (for example, support for metadata or implicit tiling). But it is backward compatible, meaning that a valid 3D Tiles 1.0 JSON file is also a valid 3D Tiles 1.1 JSON file.

The question about creating the tileset JSON is a much broader one. As you said: Usually, it is generated by tilers. And these are doing a tremendous amount of work internally - for example, converting different input data types, optimizing and simplifying the data, and subdividing it spatially, in order to prepare it so that it can be streamed to clients efficiently.

But… if your goal is only to create a tileset JSON file for existing glTF assets, then there may be a simpler solution: A function to generate tileset JSON from content files has recently been added to the 3d-tiles-tools.

So after installing the 3D Tiles Tools with
npm install 3d-tiles-tools
you can create such a JSON file like this:
npx 3d-tiles-tools createTilesetJson --input ./data --output ./data/tileset.json
Here, the data directory is a directory that contains the input GLB files.

The resulting tileset JSON will still be a “simple” one: It will only have one tile (or one tile with several children, if there are multiple GLB files), so it will not represent a real “tile hierarchy”. It will have some default values for the geometric error. But it will contain the “real” bounding volume (which is important for the visualization). For example, for the Cesium_Ailr.glb, the result will look like this:

  "asset": {
    "version": "1.1"
  "geometricError": 4096,
  "root": {
    "boundingVolume": {
      "box": [
    "geometricError": 512,
    "content": {
      "uri": "Cesium_Air.glb"
    "refine": "ADD"

Happy New Year!
And, thank you so much for your clear answer. If I ask more of your favor, there are two topics that needs to consolidate. One, locating the tileset to the real world coordinates. The other, hosting the tileset in an offline environment to call via HTTP.

For the one, what’s your recommended API to locate the tileset to the real world coordinates? Any new APIs came up with 3D Tiles v1.1? In most of cases, the glTF models are provided in local coordinates measured in meters.

For the other, I may host the tileset using asset server that comes with 3D Tiling Pipeline. But, there can be a use case when Cesium ion SaaS content is mostly used and some selected glTF assets which are hosted in a secured offline server are mixed/blended. In this case, adopting asset server just for hosting the selected glTF assets is not regarded reasonable in terms of cost effectiveness. What would be the optimal technical solution to host the glTF assets to stream via HTTP?

Thanks in advance,

For the first question:

Placing the tileset that was generated from content files at a certain position on the globe certainly is a natural requirement. And there already are considerations to add this as some sort of convenience functionality in the 3d-tiles-tools. But there currently is no built-in functionality for that yet.

If you are already using Cesium ion, then there is the option to use the “Adjust Tileset Location” function (in the upper right of the “My Assets” page, after selecting an asset). There, you can adjust the location of the asset accordingly:

Cesium Location Editor

If you want to adjust the location manually and in an offline-process, then for now, a reasonable workaround could be the following (I already mentioned that in another post, but will replicate the relevant part here for convenience):

1. Use the eastNorhUpToFixedFrame function of CesiumJS to generate the required transform.

You can just open the CesiumJS sandcastle at Cesium Sandcastle , enter the following code (with your longitude/latitude/height values):

const transform = Cesium.Transforms.eastNorthUpToFixedFrame(
 Cesium.Cartesian3.fromDegrees(43.970149521784, 56.260414816738106, 0)
console.log(Cesium.Matrix4.pack(transform, new Array(16), 0));

and press “Run”. This will print a matrix to the console, for example,


2. Insert this as the transform of the root node of your tileset.json:

  "asset": {
    "version": "1.1"
  "geometricError": 4096,
  "root": {
    "transform": [

This should place your tileset, as a whole, at the desired location.

Again, we’ll try to improve the tooling for functionalities like this, but for now, this somewhat “manual” process has to be used.

For the second question:

I’d recommend asking this as a new question in the Cesium ion section. The question is unrelated to 3D Tiles (or the topic of this thread in particular). But it might be relevant for other users as well, and can better be handled there.

Hi Marco13,
Now, I’m fully answered. For the first one, I wanted to adjust the location manually and in an offline process. And, your guide was what I ultimately wanted. For the second, I’m going to seek an answer in the Cesium ion section. Many thanks for the professional support!