In this tutorial, youâll learn how to create a Cesium app to replace buildings in a real city with your own 3D model.
You can use this as a way to visualize the impact of a proposed building. How does it change the skyline? And what will the view look like from a specific floor or room?
Weâll cover how to:
This is the app youâll build. You can toggle the proposed building and view it from multiple angles.
Before you get startedWeâre going to get global satellite imagery, 3D buildings, and terrain from Cesium ion, an open platform for streaming and hosting 3D content.
Sign up for a free Cesium ion account if you donât already have one.
Once youâre logged in:
Weâre going to create our app using CesiumJS, an open source JavaScript engine. Weâll use Glitch, an online IDE, to host our app.
2Click on index.html in the left-side panel to see the appâs code.
4Run the app by clicking Show in the top and select Next to The Code.
The code in index.html so far does three things:
<script src="https://cesium.com/downloads/cesiumjs/releases/1.132/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.132/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<div id="cesiumContainer"></div>
.const viewer = new Cesium.Viewer('cesiumContainer')
;.You now have a basic CesiumJS app running in your browser with global satellite imagery from Cesium ion.
Configure auto-refreshGlitch will automatically refresh the page every time the code changes. You can toggle this by clicking on the project name in the top left and unchecking this box:
Use the refresh button on top of the app window to re-run the app:
2Add Cesium OSM Buildings and Cesium World Terrain InformationCesium OSM Buildings is a global base layer with over 350 million buildings derived from OpenStreetMap data. Itâs served as 3D Tiles, an open standard created by Cesium, that makes it possible to stream 3D content to any compatible client.
Letâs add these layers then move the camera to the city that our fictional new building will be placed inâDenver, Colorado, USA.
1Replace your JavaScript code in index.html with the code below, keeping your access token line from before.
2Click and drag to move the camera. Hold CTRL while dragging to tilt.
3Click on any building to see its metadata.
const viewer = new Cesium.Viewer('cesiumContainer', {
terrain: Cesium.Terrain.fromWorldTerrain(),
});
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(-104.9965, 39.74248, 4000)
});
const buildingsTileset = await Cesium.createOsmBuildingsAsync();
viewer.scene.primitives.add(buildingsTileset);
At this point, your complete index.html will look like this (except for your access token). In future steps, youâll add new code below the existing code, inside the script
tag.
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cesium.com/downloads/cesiumjs/releases/1.132/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.132/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<link href="style.css" rel="stylesheet">
</head>
<body>
<div id="cesiumContainer"></div>
<script type="module">
Cesium.Ion.defaultAccessToken = 'your_access_token';
const viewer = new Cesium.Viewer('cesiumContainer', {
terrain: Cesium.Terrain.fromWorldTerrain(),
});
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(-104.9965, 39.74248, 4000)
});
const buildingsTileset = await Cesium.createOsmBuildingsAsync();
viewer.scene.primitives.add(buildingsTileset);
</script>
</body>
</html>
Information
Cesium OSM Buildings is clamped to a global high-resolution 3D terrain layer, Cesium World Terrain. This makes it ideal for applications that require accurate building heights, like flood-analysis tools.
3Identify the new building areaBefore we add the new building, letâs add a GeoJSON file to mark the footprint for it. This will show us which existing buildings need to be removed.
4After uploading, note the asset ID under the preview window.1Add the code below in index.html.
your_asset_id
 with your asset ID. The ID is a number, so you don't need quotes.
async function addBuildingGeoJSON() {
const geoJSONURL = await Cesium.IonResource.fromAssetId(your_asset_id);
const geoJSON = await Cesium.GeoJsonDataSource.load(geoJSONURL, { clampToGround: true });
const dataSource = await viewer.dataSources.add(geoJSON);
for (const entity of dataSource.entities.values) {
entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN;
}
viewer.flyTo(dataSource);
}
addBuildingGeoJSON();
Youâll see the building footprint on the ground now. Zoom in with the mouse wheel or right click + drag to take a closer look.
5Hide the existing 3D buildings on the siteNow that weâve identified where the new building will go, we can see which buildings are currently there. Weâre going to use 3D Tiles styling language to hide them.
In the footprint above, we can see that there are six buildings on the site of our new proposed buildingâone large building and five much smaller ones.
1Add the following code. It hides all the smaller 3D buildings.
buildingsTileset.style = new Cesium.Cesium3DTileStyle({
show: {
conditions : [
['${elementId} === 332469316', false],
['${elementId} === 332469317', false],
['${elementId} === 235368665', false],
['${elementId} === 530288180', false],
['${elementId} === 530288179', false],
[true, true]
]
},
color: "Boolean(${feature['cesium#color']}) ? color(${feature['cesium#color']}) : color('#ffffff')"
});
2Extend this code to hide the remaining 3D building.
elementId
. ['${elementId} === large_building_elementId', false]
,.Letâs upload the proposed building model.
3Select 3D Model (tile as 3D Tiles) and press Upload.
4After itâs done tiling, click the Adjust Tileset Location button at the top of the asset preview window.
5Enter the address of the building, 1250 Cherokee Street, in the search box and click Next.
6Using the controls on the viewer, visually position and rotate the building to line up with the satellite imagery underneath. Your final settings should be approximately:
For this tutorial, you manually positioned a new building. If a building is already georeferenced, Cesium ion will automatically place it in the right location. You can also geolocate it using the REST API. Learn more with the geolocation guide.
7Add the new building to the sceneNow letâs add the new building to the scene.
1Get the asset ID for the building model we just geolocated, under the asset preview window.
2Add the code below in index.html.
your_asset_idÂ
with your asset ID.
const newBuildingTileset = await Cesium.Cesium3DTileset.fromIonAssetId(your_asset_id);
viewer.scene.primitives.add(newBuildingTileset);
viewer.flyTo(newBuildingTileset);
8Add a button to toggle the new building
1In index.html, add the button right inside your <body>
 tag, above <script>
.
<button id="toggle-building">Toggle new building</button>
2Add the following CSSÂ style
 tag inside the head
 tag.
<style type="text/css">
#toggle-building { z-index: 1; position: fixed; top: 5px; left: 5px; }
</style>
3Add the following JavaScript in index.html.
document.querySelector('#toggle-building').onclick = function() {
newBuildingTileset.show = !newBuildingTileset.show;
};
9Consider the buildingâs impact on its surroundings
Now you can compare the scene with and without this new building!
Denverâs panoramic mountain view is highly prized. How does this building affect the view from other locations, such as the Colorado State Capitol Building?
The impact on the view from the Colorado State Capitol Building.
To reproduce this, search for State Capitol Building, Denver, CO, USA and adjust the camera.
We can even explore how the view will change from the capitol entryway.
The impact on the view from closer to ground level.
Complete tutorial source codeHere is the complete source code for this app with your_token_here
 and your_asset_id
 placeholders.
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cesium.com/downloads/cesiumjs/releases/1.132/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.132/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<link href="style.css" rel="stylesheet">
<style type="text/css">
#toggle-building { z-index: 1; position: fixed; top: 5px; left: 5px; }
</style>
</head>
<body type="module">
<div id="cesiumContainer"></div>
<button id="toggle-building">Toggle new building</button>
<script>
Cesium.Ion.defaultAccessToken = 'your_access_token';
const viewer = new Cesium.Viewer('cesiumContainer', {
terrain: Cesium.Terrain.fromWorldTerrain(),
});
const buildingsTileset = await Cesium.createOsmBuildingsAsync();
viewer.scene.primitives.add(buildingsTileset);
async function addBuildingGeoJSON() {
const geoJSONURL = await Cesium.IonResource.fromAssetId(your_asset_id);
const geoJSON = await Cesium.GeoJsonDataSource.load(geoJSONURL, { clampToGround: true });
const dataSource = await viewer.dataSources.add(geoJSON);
for (const entity of dataSource.entities.values) {
entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN;
}
}
addBuildingGeoJSON();
buildingsTileset.style = new Cesium.Cesium3DTileStyle({
show: {
conditions : [
['${elementId} === 532245203', false],
['${elementId} === 332469316', false],
['${elementId} === 332469317', false],
['${elementId} === 235368665', false],
['${elementId} === 530288180', false],
['${elementId} === 530288179', false],
[true, true]
]
},
color: "Boolean(${feature['cesium#color']}) ? color(${feature['cesium#color']}) : color('#ffffff')"
});
const newBuildingTileset = await Cesium.Cesium3DTileset.fromIonAssetId(your_asset_id);
viewer.scene.primitives.add(newBuildingTileset);
viewer.flyTo(newBuildingTileset);
document.querySelector('#toggle-building').onclick = function() {
newBuildingTileset.show = !newBuildingTileset.show;
};
</script>
</body>
</html>
Next steps
If you have your own building model, try using it instead of the provided sampleâglTF, OBJ, and FBX are all supported. Or place the building in your own city.
See the 3D models import guide to learn more.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4