9

【Unity3D】Cesium加载大地图 - little_fat_sheep

 11 months ago
source link: https://www.cnblogs.com/zhyan8/p/17760965.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

​ Cesium 是一个地球可视化平台和工具链,具有数据切片、数据分发、三维可视等功能。

img

​ Cesium 支持 JS、Unity、Unreal、O3DE、Omniverse 等平台,框架如下。

img

​ Cesium 相关链接如下:

​ 本文实验完整资源见→Cesium加载大地图案例

2 环境搭建

​ 本节主要参考 Cesium for Unity Quickstart

1)创建 3D (URP) 或 3D (HDRP) 项目

img

​ 说明:官方建议 Unity Editor 最低版本为 2021.3.2f1,笔者 Unity Editor 版本为 2021.3.11f1c2;Cesium for Unity 可与通用渲染管线(URP)和高清渲染管线(HDRP)配合使用,但是,它不支持 Unity 的内置渲染器,如果选择 3D 项目作为模板,Cesium 加载的数据集将无法正确渲染。

2)添加作用域注册表

​ 依次点击【Edit→Project Settings→Package Manager】,添加注册表信息如下。

img
Name: Cesium
URL: https://unity.pkg.cesium.com
Scope(s): com.cesium.unity

3)下载 Cesium For Unity

​ 依次点击【Window→Package Manager】打开包管理器窗口,在 Packages 菜单中选择 My Registries,下载 Cesium for Unity,如下。

img

​ 下载成功后, 菜单栏会多出一个 Cesium 菜单,如下。

img

4)连接到 Cesium ion

​ 在 Cesium 窗口点击 Connect to Cesium io 按钮,跳转到 Web 网页,点击 Allow。

img
img

5)添加 Token

​ 在 Cesium 窗口点击 Token 按钮,添加 token,如果没有 token,就创建一个 token,如果有 token,就使用已创建的 token。

img

6)创建世界地图

​ 在 Cesium 窗口点击 Cesium World Terrain + Bing Maps Aerial imagery 添加世界地图。

img

​ 场景显示如下。

img

​ 如果看不见地图,可能是相机的位置比较远,被裁剪了,可以调整远裁剪平面的位置,如下。

img

7)添加动态相机

​ 屏蔽场景中默认的相机,在 Cesium 窗口添加 Dynamic Camera,如下。此时,在 Hierarchy 窗口可以看到 CesiumGeoreference 对象下面自动生成了一个名为 DynamicCamera 的对象,该对象上挂了 Camera 组件。

img

​ 运行后,可以通过鼠标和方向按键控制相机位置和姿态,如下。

img

​ 说明:视觉的变化通过调整 CesiumGeoreference 组件下的 Latitude 和 Longitude 属性实现,如下。

img

​ 补充:读者也可以下载 Cesium 官方 Deom 体验一下,详见→cesium-unity-samples

3 地图切片

​ 本节主要介绍 fbx 文件切片流程,对于其他文件的切片,可以参考 CesiumLab地理信息基础数据处理平台使用手册

3.1 切片

​ 下载并安装 CesiumLab 后,打开 CesiumLab 客户端,fbx 文件的切片如下。

img

​ 在处理日志中可以查看任务是否处理成功,如下。如果切片失败,可能是 fbx 文件中包含相机或灯光,使用 Blender 删除相机和灯光,再重新导出 fbx 文件。

img

​ 生成的文件如下,加载切片时,需要用到 tileset.json 文件。

img

3.2 预览切片

​ 在分发服务中可以查看切片,步骤如下。

img

​ 点击预览后,会跳转到另一个网页,显示切片如下。

img

​ 用户在浏览器中输入:http://localhost:9003/viewer/index.html,再按以下步骤添加切片,也可以预览切片。

img

3.3 上传切片到 Cesium ion

​ 在 Cesium ion 官网登录账号后,按以下步骤上传切片。

img

​ 选择文件后,上传切片。

img

​ 在 My Assets 窗口可以查看已经上传的切片,如下。

img

​ 注意:第一列的 ID 在加载资源时会用到;用户也可以将 Asset Depot 中的资源添加到 My Assets 中。

4 Unity 中加载切片

4.1 加载 Cesium ion 中切片

​ 在 Cesium 窗口单击 Add 按钮,在底部 Console 右边会出现 Cesium ion Assets 窗口,选择地图添加到场景中,如下。

img

​ 在 Hierachy 窗口双击 CesiumGeoreference 下面的地图对象,使相机聚焦到地图,地图显示如下,通过修改 ion Asset ID 可以加载不同地图。

img

4.2 加载 CesiumLab 服务中切片

​ 在 Cesium 窗口点击 Blank 3D Tiles Tileset,在 Hierarchy 窗口会生成 CesiumGeoreference 和 Cesium3DTileset 对象,选中 Cesium3DTileset 对象,设置切片的 url,如下。

img

​ url 来自 CesiumLab,如下。

img

​ 在 Hierachy 窗口双击 Cesium3DTileset 对象,使相机聚焦到地图,地图显示如下。

img

​ 可以看到,地图方位异常,在 4.4 节将介绍调整地图方位的方法。

4.3 加载本地切片

​ 将切片拷贝到项目目录下的 Resources / city 目录下。在 Cesium 窗口点击 Blank 3D Tiles Tileset,在 Hierarchy 窗口会生成 CesiumGeoreference 和 Cesium3DTileset 对象,选中 Cesium3DTileset 对象,设置切片的 url,如下。

img

​ 在 Hierachy 窗口双击 Cesium3DTileset 对象,使相机聚焦到地图,地图显示同 4.2 节。

4.4 调整地图方位

1)通过 CesiumLab 预览参数调整地图

​ 使用 3.2 节中方法预览切片,调整好方位后,将鼠标放在屏幕正中间,记录底部的经度、纬度、高度,如下。

img

​ 选中 CesiumGeoreference 对象,设置经度、纬度、高度为上面记录的值,如下。

img

​ 在 Hierachy 窗口双击 CesiumGeoreference 对象,使相机聚焦到地图,地图显示如下。

img

​ 可以看到,地图的方位已正确显示,用户如果对该方位还是不满意,在调整好视觉后,点击 Place Origin Here 按钮重置该视觉下的经度、纬度、高度,如下。

img

2)通过 tileset 文件中 transform 参数调整地图

​ 在 CesiumLab地理信息基础数据处理平台使用手册 的 2.2.2.1 节 “输出数据的空间参考” 中,我们可以看到以下公式:

img

​ 其中,3dtiles 里的 transform 矩阵是指切片文件中的 tileset.json 文件,如下。

img

​ 可以看到 transform 矩阵是一个 4x4 的矩阵,并且最后一列的列向量是 [0, 0, 0, 1]',类似于平移矩阵的形式(平移矩阵详见空间和变换中 2.1.1 节,这篇文章的变换是列向量右乘,Cesium 中是行向量左乘),因此 transform 矩阵的最后一行是平移偏移量,我们将该偏移量设置到 Cesium Georeference 中,如下,地图显示效果同 4.4 1)节。

img

5 添加对象

5.1 CesiumGlobalAnchor

​ 给场景中添加 DynamicCamera,并屏蔽掉 Main Camera,添加热气球对象,如下。

img

​ 运行后,发现气球跟随相机一起运动,如下。

img

​ 将气球对象移到 CesiumGeoreference 下面,并添加 CesiumGlobalAnchor 组件,如下。

img

​ 运行效果如下,可以看到气球对象没有跟随相机一起运动了。

img

5.2 参考子场景

​ 选中 CesiumGeoreference 对象,点击 Create Sub-Scene Here 添加子场景,CesiumGeoreference 对象下面会生成一个挂有 CesiumSubScene 组件的对象,重命名为 Sub-Scene。

img

​ 调整 CesiumSubScene 组件中的 Activation Radius、Latitude、Longitude、Height 属性,如下。Latitude、Longitude、Height 确定了子场景的中心,Activation Radius 为子场景的半径,只有相机在子场景范围内,才激活子场景内的物体(子对象)。

img

​ 将气球对象拖拽到 Sub-Scene 对象下面,如下(气球对象不需要挂 CesiumGlobalAnchor 组件)。

img

​ 运行效果如下,可以看到,只有相机进入子场景范围内,才激活子场景内的物体(子对象)。

img

6 Native 编译

​ 本节主要参考 Building Cesium for Unity

1)编译环境准备

dotnet --version # 6.0 or later
cmake --version # 3.15 or later
Visual Studio 2022
Git Bash # 拉代码和编译命令都可以在 Git Bash里执行

2)拉 cesium-unity-samples 代码

cesium-unity-samples 源码。

git clone --recurse-submodules [email protected]:CesiumGS/cesium-unity-samples.git

3)拉 cesium-unity 代码

cesium-unity 源码。

cd cesium-unity-samples/Packages
git clone --recurse-submodules [email protected]:CesiumGS/cesium-unity.git com.cesium.unity

​ clone 时如果忘记添加 --recurse-submodules,可以通过以下命令递归拉取子模块依赖。

cd cesium-unity-samples/Packages/com.cesium.unity
git submodule update --init --recursive

​ 注意:不要通过浏览器下载 cesium-unity 源码的 zip 文件,因为这样不会拉子模块代码,也不要试 图把所有子模块的 zip 文件下载下来后再合并,因为子模块太多了,有的子模块里面又包含子模块,很容易漏掉。cesium-unity 源码比较大,大概 1.89 GB(包含所有子模块),如果下载比较慢,可以使用 Git常用命令总结 中方法配置代理来加速下载。

​ 以下是子模块的依赖文件。

com.cesium.unity\.gitmodules
com.cesium.unity\native~\extern\cesium-native\.gitmodules
com.cesium.unity\native~\extern\cesium-native\extern\draco\.gitmodules
com.cesium.unity\native~\extern\cesium-native\extern\earcut\.gitmodules
com.cesium.unity\native~\extern\cesium-native\extern\rapidjson\.gitmodules

​ com.cesium.unity.gitmodules 内容如下,可以看到 cesium-nativecesium-unity 的一个子模块,这正是我们要编译的 native 子模块。

[submodule "native~/extern/cesium-native"]
	path = native~/extern/cesium-native
	url = ../cesium-native.git
[submodule "native~/extern/tidy-html5"]
	path = native~/extern/tidy-html5
	url = https://github.com/htacg/tidy-html5.git
[submodule "native~/extern/enum-flags"]
	path = native~/extern/enum-flags
	url = https://github.com/grisumbras/enum-flags.git

4)构建 Reinterop

​ Reinterop 是一个 Roslyn(C# 编译器)源代码生成器,在编译 cesium-unity C# 代码时由 Unity 自动调用,并生成 C# 与 C++的交互层。

cd cesium-unity-samples/Packages/com.cesium.unity
dotnet publish Reinterop~ -o .

5)打开 cesium-unity-samples 项目

​ 使用 Unity Editor 打卡 cesium-unity-samples 项目,Unity 将自动编译 cesium-unity C# 源代码,同时调用 Reinterop 生成 C# 和 C++ 源代码。此时 Cesium 的功能还不能正常使用,会抛出以下异常。这是因为 C++ 的代码还没编译。

DllNotFoundException: CesiumForUnityNative assembly:<unknown assembly> type:<unknown type> member:(null)
NotImplementedException: The native implementation is missing so OnValidate cannot be invoked.

​ 生成的 C++ 源码地址为:com.cesium.unity/native~/build,用户可以通过 Visual Studio 打开 CesiumForUnityNative.sln 文件来查看源码。

6)编译 C++ 代码

​ 关闭 cesium-unity-samples 项目,执行完以下命令行再打开项目。

​ 构建 Debug 版本。

# compile the C++ code for use in the Editor
cd cesium-unity-samples/Packages/com.cesium.unity/native~
# 在 build 目录中生成 CMake 构建配置, 并将构建类型设置为 Debug, 以便在构建项目时启用调试信息(只需执行一次, 第二次编译时不需要执行该命令)
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug
# 在 build 目录中执行构建操作, 使用 14 个构建线程并生成 Debug 版本的可执行文件或库, 将构建结果安装到 install 指向的目录中
cmake --build build -j14 --target install --config Debug

​ 构建 Release 版本。

# build a release build
cd cesium-unity-samples/Packages/com.cesium.unity/native~
# 在 build 目录中生成 CMake 构建配置, 并将构建类型设置为 RelWithDebInfo, 它允许在 Release 版本中包含调试信息(只需执行一次, 第二次编译时不需要执行该命令)
cmake -B build -S . -DCMAKE_BUILD_TYPE=RelWithDebInfo
# 在 build 目录中执行构建操作, 使用 14 个构建线程并生成带有调试信息的 Release 版本的可执行文件或库, 将构建结果安装到 install 指向的目录中
cmake --build build -j14 --target install --config RelWithDebInfo

​ 若在后面的编译过程中,报错:could not find any instance of Visual Studio,可以参考博客→解决CMake时“could not find any instance of Visual Studio”的问题

7)查看安装目录

​ 打开 com.cesium.unity/native~/CMakeLists.txt 文件,搜索 "CMAKE_INSTALL_PREFIX",如下。

# When building for the Editor, both Runtime and Editor assemblies are
# written to the Editor directory so that Unity won't load them in
# a standalone build.
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
  set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_LIST_DIR}/../Editor" CACHE PATH "Installed to the Editor directory." FORCE)
endif()

​ 可以看到,安装目录为 "${CMAKE_CURRENT_LIST_DIR}/../Editor",即 com.cesium.unity/Editor 目录,由此得构建和安装的目录如下。

com.cesium.unity\native~\build\Editor\Debug\CesiumForUnityNative-Editor.dll ->
com.cesium.unity\Editor\CesiumForUnityNative-Editor.dll

com.cesium.unity\native~\build\Runtime\Debug\CesiumForUnityNative-Runtime.dll ->
com.cesium.unity\Editor\CesiumForUnityNative-Runtime.dll

7 修改 Native 代码案例

1)打开 native 源码工程

​ 使用 Visual Studio 打开 CesiumForUnityNative.sln 文件来查看源码,如下。

img

2)修改源码

​ 修改 CesiumForUnityNative-Runtime 模块下的 CesiumCreditSystemImpl.cpp 文件(源码位置:com.cesium.unity/native~/Runtime/src/CesiumCreditSystemImpl.cpp),如下。

img

3)编译源码

# compile the C++ code for use in the Editor
cd cesium-unity-samples/Packages/com.cesium.unity/native~
# 在 build 目录中生成 CMake 构建配置, 并将构建类型设置为 Debug, 以便在构建项目时启用调试信息(只需执行一次, 第二次编译时不需要执行该命令)
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug
# 在 build 目录中执行构建操作, 使用 14 个构建线程并生成 Debug 版本的可执行文件或库, 将构建结果安装到 install 指向的目录中
cmake --build build -j14 --target install --config Debug

​ 编译完成后,可以看到 com.cesium.unity/Editor/CesiumForUnityNative-Runtime.dll 文件修改日期发生变化。

4)修改前后对比

​ 修改前底部有一行文字。

img

​ 修改后底部文字消失。

img

​ 声明:本文转自【Unity3D】Cesium加载大地图


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK