You mentioned earlier
The initial model was in glb
format - it is just a simple tree.
and you created a B3DM file from that. It may be worth mentioning that when you use 3D Tiles 1.1 (instead of 1.0), then you can also use .GLB
files directly. So you could create the corresponding tileset.json
like this:
{
"asset": {
"version": "1.1" // When you use "1.1" here....
},
...
"content": {
"uri": "model.glb" // ... then you can use the GLB file here
},
...
}
}
Beyond that, there are different tools for dealing with B3DM data, but I’m not aware of any tool that can directly compute the bounding box of a B3DM. One … solution (although a bit cumbersome) is
- Extract the
.GLB
file from the B3DM, e.g. with the 3d-tiles-tools
b3dmToGlb
command
- (You don’t have to do this, because you already have the GLB file!)
- Drop the GLB file into https://gltf.report/
- Select the “Metadata” tab
This will show be bounding box, as in the lower right of this screenshot:
When you have this bounding box, with its (min,max)
points, then you still have to convert this into the boundingVolume.box
representation of 3D Tiles. There, you need the (center,halfAxes)
representation (because it can not only represent an Axis-Aligned bounding box, but also an Oriented bounding box). The conversion from the (min,max)
representation into the representation that is used for 3D Tiles is… simple, but … currently, also has to be done manually. The computation is shown, for example, in this code snippet.
All this is indeed a bit cumbersome. I think that some of this could be simplified. One idea would be to add this information as part of the output of the analyze
command of the 3D Tiles Tools.
I opened Extend `analyze` command to include bounding volume information · Issue #59 · CesiumGS/3d-tiles-tools · GitHub for this. This could be a low-hanging fruit, be implemented with reasonable effort, and might be useful for various sorts of analysis and debugging.
I guess, my main goal is not to position the model at runtime […] I mean to say, that I need the position to be hard coded inside tileset.json file.
… it seems to work exactly like it should. At the same time the result looks very strange now.
This looks like … the transform
matrix is wrong.
One way of determining the right matrix could be:
- Create the transform with the
eastNorthUpToFixedFrame
function (for a given position)
- Print this as a flat array to the console
For example, the output of this
const transform = Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(43.970149521784, 56.260414816738106, 0)
);
console.log(Cesium.Matrix4.pack(transform, new Array(16), 0));
will be
-0.6942835079850745,0.7197016121559956,0,0,-0.5984826914710163,-0.5773457436868751,0.5554190852466787,0,0.399736011074243,0.3856183109069252,0.831570586146325,0,2555492.883786797,2465239.113014277,5280601.728445846,1
And you can just copy+paste this into the transform
array of the root tile.
The final tileset.json
should then be
{
"asset": {
"version": "1.1"
},
"geometricError": 4096,
"root": {
"transform": [
-0.6942835079850745,0.7197016121559956,0,0,
-0.5984826914710163,-0.5773457436868751,0.5554190852466787,0,
0.399736011074243,0.3856183109069252,0.831570586146325,0,
2555492.883786797,2465239.113014277,5280601.728445846,1
],
"boundingVolume": {
"box": [
0.8377834740791688,
0.38224225730407735,
7.952663400546863,
7.760191485177515,
0,
0,
0,
-7.9996707314338495,
0,
0,
0,
8.4149664158071
]
},
"geometricError": 512,
"content": {
"uri": "model.b3dm"
},
"refine": "ADD"
}
}
This can be loaded with this sandcastle:
const viewer = new Cesium.Viewer("cesiumContainer");
// Create the tileset in the viewer
const tileset = viewer.scene.primitives.add(
await Cesium.Cesium3DTileset.fromUrl(
"http://localhost:8003/tileset.json", {
debugShowBoundingVolume: true,
})
);
// Zoom to the tileset, with a small offset so that
// it is fully visible
const offset = new Cesium.HeadingPitchRange(
Cesium.Math.toRadians(-22.5),
Cesium.Math.toRadians(-22.5),
60.0
);
viewer.zoomTo(tileset, offset);
And it will display the tree at the same location as before, but without setting the modelMatrix
at runtime.