Gabriel
Gabriel

Reputation: 21

Get geometry for feature in Cesium3DTileset

(CesiumJS Version 1.37)

I load a batched 3D tileset layer into CesiumJS; I am aware that I can access the content of every tile in that tileset using tile.content; in my case, every feature in that tile's content corresponds to a building. Reading all properties of a feature (=building) is really easy:

var content = tile.content;
for (let i = 0; i < content.featuresLength; i++) {
  const feature = content.getFeature(i);
  const propertyNames = feature.getPropertyNames()
  const numProperties = propertyNames.length
  for(let j = 0; j < numProperties; j++){
    const propertyName = propertyNames[j]
    const propertyValue = feature.getProperty(propertyName)
    console.log('    ' + propertyName + ': ' + propertyValue)
  }
}

but now I seek a similarly easy-cheesy way to get the geometry of a feature (=building in my case). I get the impression that this info is somewhat hidden, because the gltf (or rather glb) file that a batched 3D tileset layer references goes to the graphics card immediately and is inaccessible to me (?).

Upvotes: 1

Views: 884

Answers (1)

Gabriel
Gabriel

Reputation: 21

I seem to have found a hack that works quite well. My problem had to do with the time at which I wanted to access the geometry for a feature (i.e. gltf), namely very much AFTER the content had been loaded. I found out that I can access the geometry AT LOADING TIME, though. So the whole problem turned into: "How can I intercept the loading process so that I can do my own analysis of the geometry at loading time".

Background: The geometry is stored in content._model.gltf. If content._model.releaseGltfJson is true, Cesium deletes the content._model.gltf (or the cache entry that this getter refers to) after loading.

My intercept was:

    // HACK!
    const oldB3dmFactory = Cesium.Cesium3DTileContentFactory.b3dm 
    Cesium.Cesium3DTileContentFactory.b3dm = function(tileset, tile, url, arrayBuffer, 
    byteOffset) {
        const content = oldB3dmFactory(tileset, tile, url, arrayBuffer, byteOffset)
        console.log("Cesium3DTileContentFactory.b3dm intercepted, so we can access the content with the GLTF")
        const gltf = content._model.gltf
        content.readyPromise.then(()=>{
            // _model.gltf is undefined because 
            // releaseGltfJson === true
            content.log(content._model.gltf)
        })
        return content
    }

Caveat: This only works for batched 3d tilesets (b3dm). You will need to replace Cesium.Cesium3DTileContentFactory.b3dm by pnts, i3dm, cmpt or json for this snippet to work with other types of geometry.

Upvotes: 1

Related Questions