How to correctly implement gltf to 3Dtile

I exported my pipelines and manholes as gltf models through three js and then converted them into 3D tile data through cesium ion. Currently, 3D tile data can be generated and loaded correctly using cesiumjs, but when I use the following code to pick up the pipe segment。

const pickedObject  = viewer.scene.pick(movement.position);
if (!pickedObject) return;

if (pickedObject instanceof Cesium.Cesium3DTileFeature) {
  console.log("extras:", pickedObject.getProperty('extras')); 

  const properties = pickedObject.getPropertyNames();
  
}
else if (pickedObject.primitive instanceof Cesium.Cesium3DTileset) {
  const detail = pickedObject.detail;
  if (detail.node && detail.node.metadata) {
    
  }
}

This pickedObject is always a Cesium3DTileset type. I checked some information and it said that my gltf model needs to contain batchid. Then I added batchid to my gltf model and repeated the above process but still can’t select a certain pipe segment. I want to know if you have any suggestions? Thank you

Hi @wanghai1988,

It’s unclear from the snippet - but are you calling this line from inside a ScreenSpaceEventHandler?
const pickedObject = viewer.scene.pick(movement.position);

Otherwise, where is movement.position coming from? It needs to be updated in an event handler for the picked object to be properly updated.

If you’re doing that correctly already, but it’s still not working, the problem could still be with the tileset. A few questions:

  1. It sounds like you converted all your gltf models to a single 3D tileset. Is that right?
  2. Did you add the BatchID attribute manually, or did you use a tool like from 3d-tiles-tools?

A sandcastle example could be helpful, if you’re willing to share your asset (or message privately).

Best,
Matt

Thank you for your reply. The above code is just a small part of my feature picking code, which is not complete. I only have one gltf model, but this model contains many feature objects such as pipelines and inspection wells. I used cesium ion to convert gltf into 3D tiles, and manually added the batchid attribute. My asset ID is 3550583

Thank you for your reply. The above code is just a small part of my feature picking code, which is not complete. I only have one gltf model, but this model contains many feature objects such as pipelines and inspection wells. I used cesium ion to convert gltf into 3D tiles, and manually added the batchid attribute. My asset ID is 3550583

There are a few degrees of freedom of how an input model can be converted to 3D Tiles, and how certain elements of that input model can then be accessed in CesiumJS.

When you say that the "model contains many feature objects such as pipelines and inspection wells", then this sounds like a CAD model. Which option did you choose when uploading this to Cesium ion? You might want to try selecting the
“Architecture, Engineering or Construction model (BIM/CAD)”
option. This should retain some of the structures from the input data as pickable elements (and it in the best case, it should not be necessary to manually add the Batch ID attribute).

If you can share one of the models (if it’s not too large, and can be attached here as a ZIP file), it may be possible to give further advice.

Thank you for your reply, but I can’t choose the “BIM/CAD” option, because this gltf file is generated by reading the shpfile through threejs and combining some parameter information. I can upload this gltf file, I hope you can help me take a look. Thank you
demo.zip (1.4 MB)

I took this glTF, and uploaded it as BIM/CAD data, and tried it with the following sandcastle:

// Grant CesiumJS access to your ion assets
Cesium.Ion.defaultAccessToken = "YOUR TOKEN HERE";
const assetId = "YOUR_ID_HERE";

const viewer = new Cesium.Viewer("cesiumContainer");

const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(assetId, {
  modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(
    Cesium.Cartesian3.fromDegrees(0, 0),
  ),
});
viewer.scene.primitives.add(tileset);
await viewer.zoomTo(tileset);

const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (movement) {
  let tooltipText = "";
  const picked = viewer.scene.pick(movement.endPosition);
  if (!picked) {
    return;
  }
  const isFeature = picked instanceof Cesium.Cesium3DTileFeature;
  if (!isFeature) {
    return;
  }
  const featureId = picked.featureId;
  console.log("Picked element ", featureId);
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

(You have to use your token and asset ID inserted accordingly)

And it seems to be possible to identify the individual pipes:

Cesium Forum 42155

I’m not sure if this is what you’re looking for.


An aside: The glTF is invalid. It’s not clear how you inserted the batch ID attribute there, but when you drag-and-drop it into glTF Validator , you’ll see many messages

“Mesh attributes cannot use UNSIGNED_INT component type.”

Oh great, thank you so much. It seems that I can pick up the feature now, but I tried your code, why is the featureid I got empty?

I have two more questions: 1. Why do I choose BIM/CAD to upload? What is the difference between this and gltf upload? 2. My gltf file contains “extras”: {
“properties”: [
“187”,
“38”,
“2001”,
“2”,
“1738”,
“3352”
] properties. Can I get this data during the picking process? Thank you again for your help.

why is the featureid I got empty?

The console in the sandcastle (unfortunately) does not include the additional arguments. When you change the line from
console.log("Picked element ", featureId); to
console.log("Picked element " + featureId);
then it should also be visible in the console.

  1. Why do I choose BIM/CAD to upload?

There are different ways of how a glTF file can be structured, and accordingly, different ways of how it can be processed and converted into 3D Tiles. For example, when you have a glTF file that only contains a single, huge mesh (for example, a scan of a building or so), then it is necessary to slice this huge mesh into smaller pieces, so that it can be rendered efficiently. In contrast to that, glTF files that are exported from CAD applications usually contain data that has an important, inherent structure - like in your example, many meshes that represent individual objects. Such CAD data has to be processed differently.

  1. My gltf file contains “extras”

These “extras” are defined as “application specific”. They are, by default, not retained in the tiling process. Depending on where that data is coming from, and how it should be represented, there may be solutions for that, but they may require some custom code and/or engineering efforts.