在 3D 虚拟城市中展示自定义建筑

在本教程中,您将学习如何创建 Cesium 应用程序,用您自己的 3D 模型替换真实城市中的建筑物。您可以使用它来可视化拟建建筑的影响,及如何改变天际线?从特定楼层或房间看到的景色会是什么样子?

我们将介绍如何:

  • 在网络上设置并部署您的 Cesium 应用程序。

  • 添加全球 3D 建筑物、地形和图像的基础图层。

  • 隐藏单个建筑物并用您自己的 3D 模型替换它们。

开始之前

我们将从 Cesium ion(一个用于流式传输和托管 3D 内容的开放平台)获取全球卫星图像、3D 建筑物和地形。

如果您还没有免费的Cesium ion帐户,请注册一个。

登录后:

  1. 转到您的 访问令牌 选项卡。

  2. 请注意默认令牌旁边的复制按钮。我们将在下一步中使用此令牌。

1 设置你的Cesium应用程序

我们将使用 CesiumJS(一个开源 JavaScript 引擎)创建我们的应用程序。我们将使用 Glitch(一个在线 IDE)来托管我们的应用程序。

1 使用我们组合的基本模板创建一个新的 Glitch 项目。

2单击 左侧面板中的index.html以查看应用程序的代码。

3替换 为您的令牌页面your_token_here 中的访问令牌 。

4单击 顶部的 "显示"并选择"代码旁边"来运行应用程序。

到目前为止,index.html中的代码 做了三件事:

  • 导入 CesiumJS 库。JavaScript 和 CSS 文件在这两行中加载:

    <script src="https://cesium.com/downloads/cesiumjs/releases/1.115/Build/Cesium/Cesium.js"></script><link href="https://cesium.com/downloads/cesiumjs/releases/1.115/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
  • 为场景添加一个 HTML 容器: <div id="cesiumContainer"></div>

  • 用 ; 初始化查看器 const viewer = new Cesium.Viewer('cesiumContainer')

现在,您的浏览器中运行了一个基本的 CesiumJS 应用程序,其中包含来自 Cesium ion 的全球卫星图像。

配置自动刷新

每次代码更改时,Glitch 都会自动刷新页面。您可以通过单击左上角的项目名称并取消选中此框来切换此选项:

使用应用程序窗口顶部的刷新按钮重新运行应用程序:

2添加Cesium OSM建筑物和Cesium世界地形

Cesium OSM Buildings是一个全球基础层,拥有来自 OpenStreetMap 数据的超过 3.5 亿座建筑物。它被用作 3D Tiles,这是由 Cesium 创建的开放标准,可以将 3D 内容流式传输到任何兼容的客户端。

让我们添加这些图层,然后将摄像机移动到我们虚构的新建筑将位于的城市 - 美国科罗拉多州丹佛市。

1将index.html中的 JavaScript 代码替换 为以下代码,保留之前的访问令牌行。

2单击并拖动以移动相机。按住 CTRL 键的同时拖动可倾斜。

3单击任何建筑物以查看其元数据。

// Keep your Cesium.Ion.defaultAccessToken = 'your_token_here' line above. // STEP 2 CODE// Initialize the viewer with Cesium World Terrain.const viewer = new Cesium.Viewer('cesiumContainer', {  terrain: Cesium.Terrain.fromWorldTerrain(),});
// Fly the camera to Denver, Colorado at the given longitude, latitude, and height.viewer.camera.flyTo({  destination: Cesium.Cartesian3.fromDegrees(-104.9965, 39.74248, 4000)});
// Add Cesium OSM Buildings.const buildingsTileset = await Cesium.createOsmBuildingsAsync();viewer.scene.primitives.add(buildingsTileset);

此时,完整的index.html将如下所示(访问令牌除外)。在后续步骤中,您将在标记内的现有代码下方添加新代码。​​​​​​​

<!DOCTYPE html><html lang="en"><head>  <script src="https://cesium.com/downloads/cesiumjs/releases/1.115/Build/Cesium/Cesium.js"></script>  <link href="https://cesium.com/downloads/cesiumjs/releases/1.115/Build/Cesium/Widgets/widgets.css" rel="stylesheet">  <link href="style.css" rel="stylesheet"></head><body>  <div id="cesiumContainer"></div>  <script type="module">    // Your access token can be found at: https://ion.cesium.com/tokens.    // Replace `your_access_token` with your Cesium ion access token.    Cesium.Ion.defaultAccessToken = 'your_access_token';        // Keep your Cesium.Ion.defaultAccessToken = 'your_token_here' line above.     // STEP 2 CODE    // Initialize the viewer with Cesium World Terrain.    const viewer = new Cesium.Viewer('cesiumContainer', {      terrain: Cesium.Terrain.fromWorldTerrain(),    });
    // Fly the camera to Denver, Colorado at the given longitude, latitude, and height.    viewer.camera.flyTo({      destination: Cesium.Cartesian3.fromDegrees(-104.9965, 39.74248, 4000)    });
    // Add Cesium OSM Buildings.    const buildingsTileset = await Cesium.createOsmBuildingsAsync();    viewer.scene.primitives.add(buildingsTileset);</script></body></html>

Cesium OSM Buildings 被固定在全球高分辨率 3D 地形层Cesium World Terrain上。这使得它非常适合需要精确建筑高度的应用,例如洪水分析工具。

3确定新建筑面积

在添加新建筑物之前,让我们添加一个 GeoJSON 文件来标记它的占地面积。这将向我们展示哪些现有建筑物需要拆除。

1下载 GeoJSON 文件。

2将 GeoJSON 文件拖放到 Cesium ion 仪表板中。

3按 UPLOAD

4上传后,记下预览窗口下的3D对象 ID。

1在index.html中添加以下代码。

  • 替换 your_asset_id 为您的3D对象ID。ID 是一个数字,因此不需要引号。

    // STEP 3 CODEasync function addBuildingGeoJSON() { // Load the GeoJSON file from Cesium ion. const geoJSONURL = await Cesium.IonResource.fromAssetId(your_asset_id); // Create the geometry from the GeoJSON, and clamp it to the ground. const geoJSON = await Cesium.GeoJsonDataSource.load(geoJSONURL, { clampToGround: true }); // Add it to the scene. const dataSource = await viewer.dataSources.add(geoJSON); // By default, polygons in CesiumJS will be draped over all 3D content in the scene. // Modify the polygons so that this draping only applies to the terrain, not 3D buildings. for (const entity of dataSource.entities.values) { entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN; } // Move the camera so that the polygon is in view. viewer.flyTo(dataSource);}addBuildingGeoJSON();

您现在会在地面上看到建筑物的足迹。使用鼠标滚轮放大或右键单击并拖动以仔细查看。

5隐藏现场现有的3D建筑物

现在我们已经确定了新建筑的去向,我们可以看到当前有哪些建筑。我们将使用 3D Tiles 样式语言 来隐藏它们。

在上面的足迹中,我们可以看到我们新拟建建筑的场地上有六栋建筑------一栋大型建筑和五栋小得多的建筑。

1添加以下代码。它隐藏了所有较小的 3D 建筑物。​​​​​​​

// STEP 4 CODE// Hide individual buildings in this area using 3D Tiles Styling language.buildingsTileset.style = new Cesium.Cesium3DTileStyle({  // Create a style rule to control each building's "show" property.  show: {    conditions : [      // Any building that has this elementId will have `show = false`.      ['${elementId} === 332469316', false],      ['${elementId} === 332469317', false],      ['${elementId} === 235368665', false],      ['${elementId} === 530288180', false],      ['${elementId} === 530288179', false],      // If a building does not have one of these elementIds, set `show = true`.      [true, true]    ]  },  // Set the default color style for this particular 3D Tileset.  // For any building that has a `cesium#color` property, use that color, otherwise make it white.  color: "Boolean(${feature['cesium#color']}) ? color(${feature['cesium#color']}) : color('#ffffff')"});

2扩展此代码以隐藏剩余的 3D 建筑。

  • 单击建筑物即可找到其 elementId

  • 添加另一行,例如: ['${elementId} === large_building_elementId', false],.

6上传并定位新建筑

让我们上传建议的建筑模型。

1下载此 glTF 模型。

2将其拖放到 Cesium ion 仪表板中。

3选择 3D 模型(平铺为 3D 平铺) 并按 UPLOAD

4平铺完成后,单击 资源预览窗口顶部的"调整平铺集位置"按钮。

5在搜索框中 输入建筑物的地址 1250 Cherokee Street ,然后单击NEXT。

6使用查看器上的控件,直观地定位并旋转建筑物,使其与下方的卫星图像对齐。您的最终设置应约为:

  • 经度:-104.9909

  • 纬度: 39.73579

  • 身高:1577

  • 标题:-8

7按SAVE。

7将新建筑添加到场景中

现在让我们将新建筑添加到场景中。

1在资源预览窗口下获取我们刚刚地理定位的建筑模型的3D对象 ID。

2在index.html 中添加以下代码。

  • 替换 your_asset_id 为您的3D对象 ID。

    // STEP 6 CODE// Add the 3D Tileset you created from your Cesium ion account.const newBuildingTileset = await Cesium.Cesium3DTileset.fromIonAssetId(your_asset_id);viewer.scene.primitives.add(newBuildingTileset);
    // Move the camera to the new building.viewer.flyTo(newBuildingTileset);

8添加一个按钮来切换新建筑

1在 index.html中,将按钮添加到 <body> 标记内的上方 <script>

<button id="toggle-building">Toggle new building</button>

2style 在标签内 添加以下 CSS 标签head 。​​​​​​​

  <style type="text/css">    #toggle-building { z-index: 1; position: fixed; top: 5px; left: 5px; }</style>

3在index.html中添加以下JavaScript ​​​​​​​

// STEP 7 CODE// Toggle the tileset's show property when the button is clicked.document.querySelector('#toggle-building').onclick = function() {  newBuildingTileset.show = !newBuildingTileset.show;};

9考虑建筑物对周围环境的影响

现在您可以比较有和没有这座新建筑的场景!丹佛的全景山景非常珍贵。这座建筑如何影响其他地点(例如科罗拉多州议会大厦)的景观?

对科罗拉多州议会大厦景观的影响。
要重现此效果,请搜索State Capitol Building, Denver, CO, USA并调整相机。

我们甚至可以探索国会大厦入口处的景色将如何变化。

从更接近地面的角度对视野的影响。

完整教程源码

这是此应用程序的完整源代码,带有 your_token_hereyour_asset_id 占位符​​​​​​​

<!DOCTYPE html><html lang="en"><head>  <script src="https://cesium.com/downloads/cesiumjs/releases/1.115/Build/Cesium/Cesium.js"></script>  <link href="https://cesium.com/downloads/cesiumjs/releases/1.115/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>    // Your access token can be found at: https://ion.cesium.com/tokens.    // Replace `your_access_token` with your Cesium ion access token.    Cesium.Ion.defaultAccessToken = 'your_access_token';
    // Keep your Cesium.Ion.defaultAccessToken = 'your_token_here' line from above.     // STEP 2 CODE    // Initialize the viewer with Cesium World Terrain.    const viewer = new Cesium.Viewer('cesiumContainer', {      terrain: Cesium.Terrain.fromWorldTerrain(),    });
    // Fly the camera to Denver, Colorado at the given longitude, latitude, and height.    /* viewer.camera.flyTo({      destination: Cesium.Cartesian3.fromDegrees(-104.9965, 39.74248, 4000)    }); */
    // Add Cesium OSM Buildings.    const buildingsTileset = await Cesium.createOsmBuildingsAsync();    viewer.scene.primitives.add(buildingsTileset);
    // STEP 3 CODE    async function addBuildingGeoJSON() {      // Load the GeoJSON file from Cesium ion.      const geoJSONURL = await Cesium.IonResource.fromAssetId(your_asset_id);      // Create the geometry from the GeoJSON, and clamp it to the ground.      const geoJSON = await Cesium.GeoJsonDataSource.load(geoJSONURL, { clampToGround: true });      // Add it to the scene.      const dataSource = await viewer.dataSources.add(geoJSON);      // By default, polygons in CesiumJS will be draped over all 3D content in the scene.      // Modify the polygons so that this draping only applies to the terrain, not 3D buildings.      for (const entity of dataSource.entities.values) {        entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN;      }      // Move the camera so that the polygon is in view.      // viewer.flyTo(dataSource);    }    addBuildingGeoJSON();
    // STEP 4 CODE    // Hide individual buildings in this area using 3D Tiles Styling language.    buildingsTileset.style = new Cesium.Cesium3DTileStyle({      // Create a style rule to control each building's "show" property.      show: {        conditions : [          // Any building that has this elementId will have `show = false`.          ['${elementId} === 532245203', false],          ['${elementId} === 332469316', false],          ['${elementId} === 332469317', false],          ['${elementId} === 235368665', false],          ['${elementId} === 530288180', false],          ['${elementId} === 530288179', false],          // If a building does not have one of these elementIds, set `show = true`.          [true, true]        ]      },      // Set the default color style for this particular 3D Tileset.      // For any building that has a `cesium#color` property, use that color, otherwise make it white.      color: "Boolean(${feature['cesium#color']}) ? color(${feature['cesium#color']}) : color('#ffffff')"    });
    // STEP 6 CODE    // Add the 3D Tileset you created from your Cesium ion account.    const newBuildingTileset = await Cesium.Cesium3DTileset.fromIonAssetId(your_asset_id);    viewer.scene.primitives.add(newBuildingTileset);
    // Move the camera to the new building.    viewer.flyTo(newBuildingTileset);
    // STEP 7 CODE    // Toggle the tileset's show property when the button is clicked.    document.querySelector('#toggle-building').onclick = function() {      newBuildingTileset.show = !newBuildingTileset.show;    };</script></body></html>
相关推荐
CSDN云计算4 分钟前
如何以开源加速AI企业落地,红帽带来新解法
人工智能·开源·openshift·红帽·instructlab
customer082 小时前
【开源免费】基于SpringBoot+Vue.JS医院管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·开源·intellij-idea
道可云3 小时前
道可云人工智能&元宇宙每日资讯|2024国际虚拟现实创新大会将在青岛举办
大数据·人工智能·3d·机器人·ar·vr
梓羽玩Python5 小时前
推荐一款用了5年的全能下载神器:Motrix!全平台支持,不限速下载网盘文件就靠它!
程序员·开源·github
逆天的蝈蝈5 小时前
开源与商业的碰撞TPFLOW与Gadmin低代码的商业合作
低代码·开源
Sitarrrr6 小时前
【Unity】ScriptableObject的应用和3D物体跟随鼠标移动:鼠标放置物体在场景中
3d·unity
FIT2CLOUD飞致云7 小时前
仪表板展示|DataEase看中国:历年双十一电商销售数据分析
数据分析·开源·数据可视化·dataease·双十一
小华同学ai7 小时前
AJ-Report:一款开源且非常强大的数据可视化大屏和报表工具
数据库·信息可视化·开源