Which part of .b3dm contains the position property?

2,072 views
Skip to first unread message

Chris Wang

unread,
Aug 18, 2016, 5:05:05 AM8/18/16
to cesium-dev
Hello everyone
 
I am interested in 3d-tiles spec and learning tile formats now. It is really an excellent method to organize 3d models. 

However, I am confused when learning .b3dm format and want to know which part of .b3dm actually contains the position property.
In other words, how does .b3dm locate models in the right longitude and latitude?
Is it in batch table, binary glTF or other parts of the file. Or even other files?

Looking forward to your reply.

Thanks

Best

Chris 

Sean Lilley

unread,
Aug 18, 2016, 10:58:49 AM8/18/16
to cesium-dev
Hi Chris,

The position of the model is typically in the glTF itself. There are a few options:
  • the vertex data itself is already geolocated
  • the glTF contains a node that transforms the model to a longitude/latitude
  • the glTF uses the CESIUM_RTC extension. However this only applies a translation and not a rotation.
And then one other option is to add a transform to the tile in the tileset.json file. This feature is currently in progress here and here.

Chris Wang

unread,
Aug 20, 2016, 11:23:58 PM8/20/16
to cesium-dev
Thanks, Sean
That helps a lot. 

Since the gltf contains the longitude and latitude, how can I read these information?
In the example data, the glTF is binary and unreadable.
Is there a tool to interpret the binary part into readable string or something easy to find the longitute and latitude?

Chris

在 2016年8月18日星期四 UTC+8下午10:58:49,Sean Lilley写道:

Chris Wang

unread,
Aug 20, 2016, 11:46:59 PM8/20/16
to cesium-dev
Or can you tell me which property in the glTF contains the longitude and latitude.
That will be really helpful.


在 2016年8月18日星期四 UTC+8下午10:58:49,Sean Lilley写道:
Hi Chris,

Sean Lilley

unread,
Aug 22, 2016, 9:24:29 AM8/22/16
to cesium-dev
The glTF doesn't have the longitude and latitude exactly, but in some cases it may have a 4x4 matrix that transform it.(like in option 2 above) . Really the best place to get the longitude and latitude would be from the tileset.json, which defines the bounding volumes. Many of the example tilesets will have a boundingVolume.region property that gives you the [west longitude, south latitude, east longitude, north latitude, minHeight, maxHeight], which you can easily get the center longitude and latitude from.

Chris Wang

unread,
Aug 22, 2016, 10:13:49 AM8/22/16
to cesium-dev
Thanks Sean, your reply really helps me a lot.

在 2016年8月22日星期一 UTC+8下午9:24:29,Sean Lilley写道:

Chris Wang

unread,
Aug 23, 2016, 10:42:09 PM8/23/16
to cesium-dev
Hi Sean,

I am now doing experiments using the tileset data in Specs\Data\Cesium3DTiles\Tilesets\Tileset.
My aim is to move the whole models to another location.
For example, I mius the longitude and latitude of the center point by 5 degrees, and use the new center to do the following steps.

To move the tiles, I have done the following steps:

1. I changed the boundingVolume.region properties of both parent tile and children in tileset.json. (Even the properties)
2. Then I modified the extensions.CESIUM_RTC.center property into my new ECEF coordinates in all the five .b3dm files (parent, ll, lr, ul, ur).
    (I use this website to transform the coordinates: http://www.nevaridge.com/georeferencing-tools.php)

Now when I load the tileset into Sandcastle of 3d-tiles branch, I can see the boundingRectangle (red and blue), and there is no error occurring.
The problem is the models can not be loaded or displayed.

Am I missing some points? OR my idea is totally wrong. 

any help appreciated.

Chris


在 2016年8月22日星期一 UTC+8下午9:24:29,Sean Lilley写道:
The glTF doesn't have the longitude and latitude exactly, but in some cases it may have a 4x4 matrix that transform it.(like in option 2 above) . Really the best place to get the longitude and latitude would be from the tileset.json, which defines the bounding volumes. Many of the example tilesets will have a boundingVolume.region property that gives you the [west longitude, south latitude, east longitude, north latitude, minHeight, maxHeight], which you can easily get the center longitude and latitude from.

Sean Lilley

unread,
Aug 24, 2016, 11:22:03 AM8/24/16
to cesium-dev
These steps won't work for that specific tileset. The model vertex data has the longitude and latitude baked in, so trying to update the CESIUM_RTC not have an effect, besides positioning the models really far from away. Also modifying the bounding volumes does not move the content, the purpose of the bounding volumes is more for describing the content rather than moving it. Overall I think trying to re-position any of the example tilesets may be difficult to do and it's better to try to build a tileset from scratch. We have a repo that we are working on to make it easier for people to create tilesets, but it's not quite ready yet: https://github.com/AnalyticalGraphicsInc/3d-tiles-tools.

You may be interested in checking out this sample tileset in our 3d-tiles-samples repo: https://github.com/AnalyticalGraphicsInc/3d-tiles-samples/tree/master/tilesets/TilesetWithDiscreteLOD. To move the dragon around it should be as easy as changing the transform property of tileset.json. In order to run this tileset though you will need to be on the 3d-tiles-transform branch.

Chris Wang

unread,
Aug 26, 2016, 2:51:22 AM8/26/16
to cesium-dev
Hello Sean,
I am now building a tileset from scratch by myself.
I do the following steps:
1. I wrote a tileset.json with only one root tile, there is a parent.b3dm in the content.
2. I transform my models (four cubes exported from sketchup) into binary glTF through the web converter on your website.
3. I wrote the 20 byte binary header, and append the bglTF after the header. The batchlength and batchtablelength are both 0.
4. I add and modified three parts of the bglTF in .b3dm after appending:
  I add CESIUM_RTC to extensionUsed:
  "extensionsUsed":["CESIUM_RTC"],
 And I add center ECEF coordinates to CESIUM_RTC, the coordinates are generated by Cesium.Transforms.eastNorthUpToFixedFrame from a origin in WGS84. 
  "extensions": {
   ....
    "CESIUM_RTC": {
      "center": [
        -2854779.6449591094,
        4665794.49663563,
        3269432.1747686574
      ]
    }
  }
 And I changed the modelViewMatrix to CESIUM_RTC_MODELVIEW:
  "techniques": {
    "technique0": {
      "parameters": {
        "modelViewMatrix": {
          "semantic": "CESIUM_RTC_MODELVIEW",
          "type": 35676
        },
  .....
4. And I modified the byteLength field in the header to the right bytelength after all modification.

However, the models is not displayed when I load the tileset.json in 3d-tiles example in Sandcastle,
The camera manged to fly to the right location and the console exports like this:
[Color]: Visited: 0, Selected: 0, Commands: 0 | Requests: 0, Processing: 0, Ready: 0, Total: 1 | Tiles styled: 0, Features styled: 0
[Color]: Visited: 0, Selected: 0, Commands: 0 | Requests: 1, Processing: 0, Ready: 0, Total: 1 | Tiles styled: 0, Features styled: 0
[Color]: Visited: 1, Selected: 0, Commands: 0 | Requests: 1, Processing: 0, Ready: 0, Total: 1 | Tiles styled: 0, Features styled: 0 
[Color]: Visited: 1, Selected: 0, Commands: 0 | Requests: 0, Processing: 0, Ready: 0, Total: 1 | Tiles styled: 0, Features styled: 0

But I can not see models and even boundingRectangles. I guess I miss some important parts but I can't see it.
Any help appreciated.
Thanks

Chris

在 2016年8月24日星期三 UTC+8下午11:22:03,Sean Lilley写道:

Chris Wang

unread,
Aug 26, 2016, 2:52:33 AM8/26/16
to cesium-dev
This is my tileset.json and .b3dm
parent.b3dm
tileset.json

Sean Lilley

unread,
Aug 26, 2016, 8:57:46 AM8/26/16
to cesium-dev
I noticed a few problems. Your byteLength is 448,643,055 whereas the actual tile byte length is 7464. Also it looks like the glTF starts at byte 22 rather than byte 20.

Chris Wang

unread,
Aug 26, 2016, 11:18:41 AM8/26/16
to cesium-dev
Hello Sean
Thanks for your help again. Sorry for my little mistakes, I have modified the bytelength field and move the glTF at byte 20.
And I also find the CESIUM_RTC center is not within the boundingVolume, so I modified the center value.
But I still cannot see the models and boundingRectangle. 

I should mention that all the boundingVolume region are typed manully. So I wonder if the boundingVolume of root tile should tightly surround the models? Or does it matter?
The following files are my tileset.json and the modified parent.b3dm

Best,
Chris

在 2016年8月26日星期五 UTC+8下午8:57:46,Sean Lilley写道:
tileset.json
parent.b3dm

Sean Lilley

unread,
Aug 26, 2016, 11:36:50 AM8/26/16
to cesium-dev
I think the problem now is is you edited the glTF manually but didn't update the contentLength field: https://github.com/KhronosGroup/glTF/tree/master/extensions/Khronos/KHR_binary_glTF. It may be easier if you use the online converter, uncheck the binary gltf checkbox, modify the gltf, then run through the converter again with the binary checkbox set.

I should also warn in advance that using the CESIUM_RTC extension will only translate the model, and won't orient it to fit the surface. In general using the "transform" property in tileset.json is the easier way to go.

Chris Wang

unread,
Aug 27, 2016, 10:57:52 AM8/27/16
to cesium-dev
Thanks Sean, now I see the models in the right place. As you said, the models can't be orientated rightly.
So I try to use the transform property. But I don't how to define the boundingBox, so I copy the transform and boundingVolune in TilesetWithDiscreteLOD/tileset.json
I can see the models on the surface,but they are too big, and out of the boundingVolume like the picture below:
   The red box is the boundingVolume and the model shouldn't be that large.



在 2016年8月26日星期五 UTC+8下午11:36:50,Sean Lilley写道:

Sean Lilley

unread,
Aug 27, 2016, 11:24:30 AM8/27/16
to cesium-dev
You won't have much luck with using the same bounding box and transform on a different model. The transform in TilesetWithDiscreteLOD has a scale in it so that explains why they are so big. This is the code I used to make a bounding box and transform:

var centerLatitude = 0.698874;
var centerLongitude = -1.31968;
var dragonWidth = 14.191;
var dragonHeight = 10.075;
var dragonDepth = 6.281;
var dragonBox = [0.0, 0.0, 0.0, dragonWidth, 0.0, 0.0, 0.0, dragonDepth, 0.0, 0.0, 0.0, dragonHeight];
// this line above swaps from y-up to z-up, but there will be a change in Cesium soon for all local bounding volumes to stay y-up
var dragonScale = 100.0;
var dragonOffset = dragonHeight / 2.0 * dragonScale;
var dragonCartesian = Cartesian3.fromRadians(centerLongitude, centerLatitude, dragonOffset);
var scaleMatrix = Matrix4.fromUniformScale(dragonScale);
var wgs84Matrix = Transforms.headingPitchRollToFixedFrame(dragonCartesian, 0.0, 0.0, 0.0);
var dragonMatrix = Matrix4.multiply(wgs84Matrix, scaleMatrix, new Matrix4());
var dragonTransform = new Array(16);
Matrix4.pack(dragonMatrix, dragonTransform);

Chris Wang

unread,
Aug 29, 2016, 11:50:20 AM8/29/16
to cesium-dev
Thanks Sean, I finally figure out how to create .b3dm tiles. I have a few questions:
1. If I use the transform matrix in root tile, can I use another transform matrix in children tile? (maybe the two models have different centers)
2. When I use the code you offered to generate box matrix, the I will lift the models at the height of dragonHeight/2. I guess that's because the origin of my glTF model is on the ground.
    So I change the  var dragonOffset = dragonHeight / 2.0 * dragonScale to var dragonOffset = 0. Then the models are on the ground, but the boundingVolume are buried half into the earth.
    Then I change the Box to Region, and find out it also works well. I want to know is there a solution for this problem or should I change the origin when building the models?
3. My .b3dm has no batchTable, so they are just models with no information. Are there any tutorial for add batchTable into .b3dm?

BTW, I learn so much from you this week and that make more insterested in 3d-tiles. I should say the whole community is great and hope you create more innovative techs.

Best
Chris

在 2016年8月27日星期六 UTC+8下午11:24:30,Sean Lilley写道:

Sean Lilley

unread,
Aug 29, 2016, 12:05:46 PM8/29/16
to cesium-dev
1. Yes you can do that
2. You will need to update the boundingVolume box as well. The first three values are the center position - you may want to change the 2nd value to half the height of the model.
3. The glTF model will need a batchId vertex attribute. You may be able to examine our example tilesets and work backwards to see what's going on in terms of the glTF, but as of now we don't have any tutorials for doing this.

Thanks for your interest in 3D Tiles!

Sean Lilley

unread,
Aug 29, 2016, 12:12:02 PM8/29/16
to cesium-dev
Quick edit: For number 2, you should edit the 3rd value, not the 2nd. However this will change in Cesium pretty soon.

Chris Wang

unread,
Aug 30, 2016, 9:01:04 AM8/30/16
to cesium-dev
Hi Sean, I'm now trying to figure out batch table. But I don't know how to add batchID to the glTF.
I find there are places in glTF relating to batchID:
1. "techniques":{"technique0":{"attributes":{"a_batchId":"batchId","a_normal":"normal","a_position":"position"},"parameters":{"ambient":{"type":35666},"batchId":{"semantic":"BATCHID","type":5126}...
2. "primitives":[{"attributes":{"BATCHID":"accessor_27"}...}...]
3. "accessor_27":{"bufferView":"bufferView_30","byteOffset":33600,"byteStride":2,"componentType":5123,"count":2400,"max":[99],"min":[0],"type":"SCALAR"}
Then I find the accessor_27 contains the batchID buffer. So I guess I need to fill the buffer in glTF with batchID. 
So I open an ordinary glTF file and find the buffer containing position and normal data (should the batchID be put in the same buffer?). 
The buffer is organized like this:
"buffer_0": {
      "type": "arraybuffer",
      "byteLength": 1512,
      "uri": "data:application/octet-stream;base64,//8AQzpej0......UABcA"
    }
Now, I have a few questions: 
1. Is the uri containing the position and normal data? 
2. Should the batchID also be in the above uri?
3. What does octet-stream mean? How can I read the encoded data? It seems this data has been encoded twice (base64 and something related to octet-stream).
4. After I manage to add batchID into the buffer, and modify the abovementioned parts relating to batchID (including batchTable). Can I get the right .b3dm with batchTable and display it in Cesium?.

Best
Chris


在 2016年8月30日星期二 UTC+8上午12:05:46,Sean Lilley写道:

Chris Wang

unread,
Aug 30, 2016, 10:00:54 AM8/30/16
to cesium-dev
Sorry, I find out the octet-stream means binary file. 
I'd like to change Question 3 to: How can I append batchIDs to the base64 encoded uri data? 

在 2016年8月30日星期二 UTC+8下午9:01:04,Chris Wang写道:

Sean Lilley

unread,
Aug 30, 2016, 8:28:15 PM8/30/16
to cesium-dev
Yeah the data uri represents the buffer data, which includes positions, normals, and any other vertex attributes. This is getting into pretty technical territory and there are probably too many steps to explain it in perfect detail here, but you should become more familiarized with the glTF format and the concept of vertex attributes. Basically for each vertex you need to store a batchId that says this vertex belongs to this feature. I'm not sure what tools you're using to edit these tiles, but the batchId buffer is typically a Uint16Array. You can append this to the main buffer, or make a new buffer for it.

In addition to the glTF changes you will need to edit the batchLength property of the b3dm header, which says how many features there are (I'm guessing your model above would be 4). Finally you need to create a batch table JSON and insert that into the tile as described in the b3dm spec: https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/TileFormats/Batched3DModel

Chris Wang

unread,
Sep 1, 2016, 7:59:21 AM9/1/16
to cesium-dev
Hello Sean,
First of all, thanks very much for your advice.
I have created my first .b3dm with batchTable, and load it into 3d-tiles-transform branch. Then, I manage to use simple styling code to change the apperance according to a batchTable field (shown in the following picture).

Since I have gone through all the procedures of creating .b3dm (or 3d-tiles) from scratch, I have questions about the procedure itself:
1. My 3d tiles are based on the COLLADA models created from 3d softwares (such as Sketchup). So I need to convert the models to gltf, glb, and then to .b3dm. Is there any method to create .b3dm directly? Or can I convert 3d models in 3d softwares to .b3dm directly?
2. For each tile, I need a COLLADA model. So for the whole five tiles (one parent tile and four children), I need four different .dae file and convert each file seperately to .b3dm. Is there a method to convert a whole .dae file to five seperate .b3dm according to my tiling scheme?
3. I write the tileset.json almost manually. The boundingVolume is divided by myself. Is there any tool or algorithm that can divide the models into tiles according to their spatial distribution?
4. I really appreciate the NewYork city example in demos. I wonder for such a large dataset, how do you generate the .b3dm files, and divide tiles? Are the .b3dm generated from ordinary 3d models like COLLADA, or from something like GityGML? And by which criteria do you define the tiling scheme?
5. I will continue to learn other tile formats in 3d-tiles. And I am likely to met other problems. Should I ask question in this thread or start a new thread?

Thanks again for your great work.

Chris

在 2016年8月31日星期三 UTC+8上午8:28:15,Sean Lilley写道:

Sean Lilley

unread,
Sep 1, 2016, 10:58:57 PM9/1/16
to cesium-dev
I'm glad you got the batch table up and running quickly, I like the screenshot.

1. As of now, the main way is just COLLADA to glTF to b3dm. We hope to see more 3d software exporting glTF directly, and possibly b3dm sometime in the future.
2. Tools like that don't exist yet, at the moment you will just need your own toolchain.
3. Also no tools for that right now that I know of. This is an interesting problem to solve, and we are working on it now.
4. In the New York demo the data comes from CityGML / OpenStreetMap. The individual buildings are in COLLADA and we have a custom pipeline for batching building models together and splitting into tiles. Usually the tiling scheme is based around a quadtree that takes geometric error into account.
5. Maybe a different thread per tile format is a good idea? It doesn't matter too much to me.

Chris Wang

unread,
Sep 2, 2016, 3:49:49 AM9/2/16
to cesium-dev
Thanks again, Sean

Chris

在 2016年9月2日星期五 UTC+8上午10:58:57,Sean Lilley写道:

nim...@gmail.com

unread,
Sep 23, 2017, 4:39:53 AM9/23/17
to cesium-dev
Hello Chris,
I really appreciate your wonderful post, which helps me a lot. I have managed to generate the .b3dm file without batch table, but i am stuck when adding batchId to the glTF. I have no idea where to add batchId or what should i modify in glTF. Can you offer me a example glTF with batchId? Or can you tell me where did you find the example glTF with batchID, because i didn't find any of them in Cesium data folder. There are only many .b3dm files in it.
You said "need to fill the buffer in glTF with batchID", which confuses me a lot. The buffer containing position and normal data is binary and what should i do to add batchID into the buffer?

Best
Zhang


在 2016年8月30日星期二 UTC+8下午9:01:04,Chris Wang写道:
Hi Sean, I'm now trying to figure out batch table. But I don't know how to add batchID to the glTF.
在 2016年8月30日星期二 UTC+8下午9:01:04,Chris Wang写道:
Hi Sean, I'm now trying to figure out batch table. But I don't know how to add batchID to the glTF.
在 2016年8月30日星期二 UTC+8下午9:01:04,Chris Wang写道:
Hi Sean, I'm now trying to figure out batch table. But I don't know how to add batchID to the glTF.

Sean Lilley

unread,
Sep 25, 2017, 7:15:51 PM9/25/17
to cesium-dev
You can extract the gltf from the b3dm using 3d-tiles-tools and gltf-pipeline. I attached a glTF extracted from here so you can reference it easily.

I would also recommend checking out 3d-tiles-samples-generator for a basic idea of how b3dm tiles are created. The code that you should focus on is here: https://github.com/AnalyticalGraphicsInc/3d-tiles-tools/blob/master/samples-generator/lib/createGltf.js#L371-L452. Basically the batch id is just another vertex attribute like positions and normals. It is typically an array of unsigned shorts whose length is equal to the number of vertices.
batchedWithBatchTable.gltf

nim...@gmail.com

unread,
Sep 26, 2017, 2:54:37 AM9/26/17
to cesium-dev
Hi Sean,
Thanks very much for your reply! 
Yesterday, I had managed to create the b3dm with batch table. It is so cool. Although I encountered many problems in the past few days, I learned a lot from them. 
Currently, i find out that the model doesn't match the correct position like the below shown:

The model should be placed in the red bounding volume but it deviates away from its position. I used a transform property in tileset.json file and the transform matrix was generated by 
Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(lon,lat,0))
where, the (lon, lat, 0) is the center of bounding volume. I thought it was a translation problem, so i added Cesium_RTC extension when creating b3dm and the CESIUM_RTC center was ECEF coordinate. However, the model didn't display in cesium and only red bounding volume was visible.
Am i wrong in mentionedabove steps? Or can you tell me how i can fix this translation problem?
在 2017年9月26日星期二 UTC+8上午7:15:51,Sean Lilley写道:

Sean Lilley

unread,
Sep 26, 2017, 7:22:27 PM9/26/17
to cesium-dev
It looks like the model is off center, almost as if the origin of the model is at one of its corners. The reason I suspect this is one corner is directly at the center of the tile. I think you'll need to tweak the geometry or add a node to the glTF to translate it a bit.
















If you decide to use RTC, make sure you are not also using a transform. That will cause the model to be offset by both the transform and the RTC causing it to not show up where expected. Just be aware that since RTC does not include a rotation the model geometry will need to be rotated.

Chris Wang

unread,
Oct 17, 2017, 1:38:34 AM10/17/17
to cesium-dev
Hi Sean

I'm now trying to convert gltf 2.0 models to 3d-tiles.

I wonder if 3d-tiles in Cesium support gltf 2.0?

if so, how should I add batchid to each meshes?

In fact, I can't find shaders property in gltf 2.0, so there is no way to insert attribute float a_batchId into gltf file

Any help appreciated

Chris

Sean Lilley

unread,
Oct 17, 2017, 7:51:50 PM10/17/17
to cesium-dev
Cesium supports glTF 2.0 models, so using glTF 2.0 models in your tilesets should be fine.

For batch ids, continue to use the _BATCHID semantic on the vertex attribute. However you don't need to do anything for shaders and techniques since these were removed from glTF 2.0. Cesium will generate the correct shaders automatically.

王忠樑

unread,
Oct 17, 2017, 8:08:13 PM10/17/17
to Sean Lilley
Great, THANKS Sean

--
You received this message because you are subscribed to a topic in the Google Groups "cesium-dev" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/cesium-dev/qMKvqBUGsoE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to cesium-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Chris Wang

unread,
Dec 6, 2017, 8:55:49 AM12/6/17
to cesium-dev
Hi Sean

I write a .gltf 2.0 file with _BATCHID in the vertex attribute.

But I can't load it into Cesium. It shows some errors about a_BATCHID redefinition.

The error is shown below:

The gltf file is uploaded.

Any help is appreciated.

Thanks

Chris.

在 2017年10月18日星期三 UTC+8上午7:51:50,Sean Lilley写道:
0_100_bid.gltf

Sean Lilley

unread,
Dec 6, 2017, 7:55:49 PM12/6/17
to cesium-dev
Thanks for the bug report. I submitted a fix: https://github.com/AnalyticalGraphicsInc/cesium/pull/6036.

By the way, this bug happened to be exposed by loading the gltf by itself, but I think it would have loaded fine as part of the b3dm. Nevertheless, good catch!

王忠樑

unread,
Dec 6, 2017, 10:17:21 PM12/6/17
to Sean Lilley
Thanks Sean

I will try it with .b3dm



--

Chris Wang

unread,
Dec 7, 2017, 12:57:17 AM12/7/17
to cesium-dev
Hi Sean

Just let you know, the .b3dm works perfectly.


Patrick Cozzi

unread,
Dec 8, 2017, 4:14:44 PM12/8/17
to cesium-dev
Hi Chris,

Sean's fix #6036 was just merged, and will be in Cesium 1.41 on January 2.

Patrick

王忠樑

unread,
Dec 8, 2017, 8:14:59 PM12/8/17
to Patrick Cozzi
Thanks Patrick
Reply all
Reply to author
Forward
0 new messages