Cesium 是一個地球視覺化平臺和工具鏈,具有資料切片、資料分發、三維可視等功能。
Cesium 支援 JS、Unity、Unreal、O3DE、Omniverse 等平臺,框架如下。
Cesium 相關連結如下:
本文實驗完整資源見→Cesium載入大地圖案例。
本節主要參考 Cesium for Unity Quickstart。
1)建立 3D (URP) 或 3D (HDRP) 專案
說明:官方建議 Unity Editor 最低版本為 2021.3.2f1,筆者 Unity Editor 版本為 2021.3.11f1c2;Cesium for Unity 可與通用渲染管線(URP)和高清渲染管線(HDRP)配合使用,但是,它不支援 Unity 的內建渲染器,如果選擇 3D 專案作為模板,Cesium 載入的資料集將無法正確渲染。
2)新增作用域登入檔
依次點選【Edit→Project Settings→Package Manager】,新增登入檔資訊如下。
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,如下。
下載成功後, 選單欄會多出一個 Cesium 選單,如下。
4)連線到 Cesium ion
在 Cesium 視窗點選 Connect to Cesium io 按鈕,跳轉到 Web 網頁,點選 Allow。
5)新增 Token
在 Cesium 視窗點選 Token 按鈕,新增 token,如果沒有 token,就建立一個 token,如果有 token,就使用已建立的 token。
6)建立世界地圖
在 Cesium 視窗點選 Cesium World Terrain + Bing Maps Aerial imagery 新增世界地圖。
場景顯示如下。
如果看不見地圖,可能是相機的位置比較遠,被裁剪了,可以調整遠裁剪平面的位置,如下。
7)新增動態相機
遮蔽場景中預設的相機,在 Cesium 視窗新增 Dynamic Camera,如下。此時,在 Hierarchy 視窗可以看到 CesiumGeoreference 物件下面自動生成了一個名為 DynamicCamera 的物件,該物件上掛了 Camera 元件。
執行後,可以通過滑鼠和方向按鍵控制相機位置和姿態,如下。
說明:視覺的變化通過調整 CesiumGeoreference 元件下的 Latitude 和 Longitude 屬性實現,如下。
補充:讀者也可以下載 Cesium 官方 Deom 體驗一下,詳見→cesium-unity-samples。
本節主要介紹 fbx 檔案切片流程,對於其他檔案的切片,可以參考 CesiumLab地理資訊基礎資料處理平臺使用手冊。
下載並安裝 CesiumLab 後,開啟 CesiumLab 使用者端,fbx 檔案的切片如下。
在處理紀錄檔中可以檢視任務是否處理成功,如下。如果切片失敗,可能是 fbx 檔案中包含相機或燈光,使用 Blender 刪除相機和燈光,再重新匯出 fbx 檔案。
生成的檔案如下,載入切片時,需要用到 tileset.json 檔案。
在分發服務中可以檢視切片,步驟如下。
點選預覽後,會跳轉到另一個網頁,顯示切片如下。
使用者在瀏覽器中輸入:http://localhost:9003/viewer/index.html,再按以下步驟新增切片,也可以預覽切片。
在 Cesium ion 官網登入賬號後,按以下步驟上傳切片。
選擇檔案後,上傳切片。
在 My Assets 視窗可以檢視已經上傳的切片,如下。
注意:第一列的 ID 在載入資源時會用到;使用者也可以將 Asset Depot 中的資源新增到 My Assets 中。
在 Cesium 視窗單擊 Add 按鈕,在底部 Console 右邊會出現 Cesium ion Assets 視窗,選擇地圖新增到場景中,如下。
在 Hierachy 視窗雙擊 CesiumGeoreference 下面的地圖物件,使相機聚焦到地圖,地圖顯示如下,通過修改 ion Asset ID 可以載入不同地圖。
在 Cesium 視窗點選 Blank 3D Tiles Tileset,在 Hierarchy 視窗會生成 CesiumGeoreference 和 Cesium3DTileset 物件,選中 Cesium3DTileset 物件,設定切片的 url,如下。
url 來自 CesiumLab,如下。
在 Hierachy 視窗雙擊 Cesium3DTileset 物件,使相機聚焦到地圖,地圖顯示如下。
可以看到,地圖方位異常,在 4.4 節將介紹調整地圖方位的方法。
將切片拷貝到專案目錄下的 Resources / city 目錄下。在 Cesium 視窗點選 Blank 3D Tiles Tileset,在 Hierarchy 視窗會生成 CesiumGeoreference 和 Cesium3DTileset 物件,選中 Cesium3DTileset 物件,設定切片的 url,如下。
在 Hierachy 視窗雙擊 Cesium3DTileset 物件,使相機聚焦到地圖,地圖顯示同 4.2 節。
1)通過 CesiumLab 預覽引數調整地圖
使用 3.2 節中方法預覽切片,調整好方位後,將滑鼠放在螢幕正中間,記錄底部的經度、緯度、高度,如下。
選中 CesiumGeoreference 物件,設定經度、緯度、高度為上面記錄的值,如下。
在 Hierachy 視窗雙擊 CesiumGeoreference 物件,使相機聚焦到地圖,地圖顯示如下。
可以看到,地圖的方位已正確顯示,使用者如果對該方位還是不滿意,在調整好視覺後,點選 Place Origin Here 按鈕重置該視覺下的經度、緯度、高度,如下。
2)通過 tileset 檔案中 transform 引數調整地圖
在 CesiumLab地理資訊基礎資料處理平臺使用手冊 的 2.2.2.1 節 「輸出資料的空間參考」 中,我們可以看到以下公式:
其中,3dtiles 裡的 transform 矩陣是指切片檔案中的 tileset.json 檔案,如下。
可以看到 transform 矩陣是一個 4x4 的矩陣,並且最後一列的列向量是 [0, 0, 0, 1]',類似於平移矩陣的形式(平移矩陣詳見空間和變換中 2.1.1 節,這篇文章的變換是列向量右乘,Cesium 中是行向量左乘),因此 transform 矩陣的最後一行是平移偏移量,我們將該偏移量設定到 Cesium Georeference 中,如下,地圖顯示效果同 4.4 1)節。
給場景中新增 DynamicCamera,並遮蔽掉 Main Camera,新增熱氣球物件,如下。
執行後,發現氣球跟隨相機一起運動,如下。
將氣球物件移到 CesiumGeoreference 下面,並新增 CesiumGlobalAnchor 元件,如下。
執行效果如下,可以看到氣球物件沒有跟隨相機一起運動了。
選中 CesiumGeoreference 物件,點選 Create Sub-Scene Here 新增子場景,CesiumGeoreference 物件下面會生成一個掛有 CesiumSubScene 元件的物件,重新命名為 Sub-Scene。
調整 CesiumSubScene 元件中的 Activation Radius、Latitude、Longitude、Height 屬性,如下。Latitude、Longitude、Height 確定了子場景的中心,Activation Radius 為子場景的半徑,只有相機在子場景範圍內,才啟用子場景內的物體(子物件)。
將氣球物件拖拽到 Sub-Scene 物件下面,如下(氣球物件不需要掛 CesiumGlobalAnchor 元件)。
執行效果如下,可以看到,只有相機進入子場景範圍內,才啟用子場景內的物體(子物件)。
本節主要參考 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-native 是 cesium-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
1)開啟 native 原始碼工程
使用 Visual Studio 開啟 CesiumForUnityNative.sln 檔案來檢視原始碼,如下。
2)修改原始碼
修改 CesiumForUnityNative-Runtime 模組下的 CesiumCreditSystemImpl.cpp 檔案(原始碼位置:com.cesium.unity/native~/Runtime/src/CesiumCreditSystemImpl.cpp),如下。
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)修改前後對比
修改前底部有一行文字。
修改後底部文字消失。
宣告:本文轉自【Unity3D】Cesium載入大地圖。