CesiumGS / cesium

An open-source JavaScript library for world-class 3D globes and maps :earth_americas:
https://cesium.com/cesiumjs/
Apache License 2.0
12.98k stars 3.5k forks source link

Point Cloud Sandcastle Example Loads Point Clouds Under the Terrain #7063

Closed bbehling-trimble closed 6 years ago

bbehling-trimble commented 6 years ago

Using this example

https://cesiumjs.org/Cesium/Build/Apps/Sandcastle/?src=3D%20Tiles%20Point%20Cloud.html

If a terrain is added, the 3D Tile Point cloud is not clamped to the terrain.

Is there a setting we need to configure to clamp point clouds to terrain models, or is this a known issue?

Note, using the NYC 3D building models (b3dm) with terrain works fine.

hpinkos commented 6 years ago

Hello @bbehling-trimble, 3D Tiles is not terrain aware, so setting the height to match terrain either has to be baked in to the tileset during processing, or can be adjusted using the modelMatrix at runtime.

You can see this example for adjusting the tileset height using a modelMatrix: https://cesiumjs.org/Cesium/Build/Apps/Sandcastle/?src=3D%20Tiles%20Adjust%20Height.html&label=3D%20Tiles

If you are using Cesium ion on cesium.com, we recently added a tileset location tool that lets you move the 3D tiles tileset and save the new location so it is set correctly when you stream your tileset from ion to your CesiumJS applications. To open the tool, select the asset you wish to adjust from the list of assets, then click the Adjust Tileset Location button above the preview window on the right side of the screen.

image

bbehling-trimble commented 6 years ago

Hi @hpinkos

I tried the example you sent. I tried loading the church 3D TileSet with terrain

var tileset = new Cesium.Cesium3DTileset({ url: Cesium.IonResource.fromAssetId(5714) });

Trying different height values, including 5000, the 3d Tileset is still rendered below the terrain.

Do you why this is still happening when setting the Tile Set's Model Matrix property?

hpinkos commented 6 years ago

Hi @bbehling-trimble,

Sorry, I forgot that particular sample church tileset was generated before we made some updates to our point cloud tiling pipeline and cannot be positioned using the model matrix method. However, this method will work for all point cloud tilesets generated with the current version of our ion point cloud tiler. I'll make a note to update our sample point cloud model.

hpinkos commented 6 years ago

@bbehling-trimble I'm sorry, I was mistaken. I had written my sample code incorrectly. You can see an example of how to change the church point cloud height using a modelMatrix in this Sandcastle example.

Hope this helps!

bbehling-trimble commented 6 years ago

@hpinkos What was changed from the previous example? Other loading a new tile set, it looks to be the same code.

hpinkos commented 6 years ago

@bbehling-trimble yes, it is using the same method to reposition the tileset as the first Sandcastle demo I linked you too

bbehling-trimble commented 6 years ago

@hpinkos Do you re-run the church tileset through the new CLI?

hpinkos commented 6 years ago

@bbehling-trimble no, that is using the same church tileset.

Here's an example for positioning it direction on terrain without using the slider. The height of the terrain at that location is approximately 413 meters.

var viewer = new Cesium.Viewer('cesiumContainer', {
    terrainProvider: Cesium.createWorldTerrain()
});

viewer.scene.globe.depthTestAgainstTerrain = true;

var tileset = new Cesium.Cesium3DTileset({
    url: Cesium.IonResource.fromAssetId(5714),
    maximumScreenSpaceError : 1024
});

tileset.readyPromise.then(function(tileset) {
    var cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center);
    var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
    var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 413.0);
    var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
    tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);

    viewer.scene.primitives.add(tileset);
    viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0.0, -0.5, tileset.boundingSphere.radius * 2.0));
}).otherwise(function(error) {
    console.log(error);
});