原文地址:https://cesiumjs.org/tutorials/3D-Models-Tutorial/
三維模型 (3D Models)
這篇教程給大家介紹,如何在Cesium中通過Primitive API來轉(zhuǎn)換、加載、使用三維模型。如果你是新手,建議你先看下這篇 空間數(shù)據(jù)可視化教程 的三維模型部分。
Cesium支持包含關(guān)鍵幀(key-frame)動畫、骨骼(skinning)動畫 的glTF格式的三維模型,并且支持模型節(jié)點(node)的拾取。 glTF是 Khronos Group 定義的一個基于web上的新興三維模型格式行業(yè)標(biāo)準(zhǔn)。Khronos Group是WebGL和 COLLADA的背后財團(tuán)。Cesium提供了一個 在線的工具 ,可以把COLLADA(.dae)模型轉(zhuǎn)換為專為Cesium優(yōu)化的glTF格式。
快速開始
Cesium內(nèi)置了一些隨時可用的glTF模型:
- 帶螺旋槳動畫的飛機(jī)模型
- 帶輪子動畫的汽車模型
- 帶行走骨骼動畫的人物模型
- 熱氣球模型
- 牛奶卡車 Draco壓縮




這些模型都在
Apps/SampleData/models目錄下有各自的存放目錄。一部分還包含一個COLLADA (.dae)格式的源文件(Cesium中不需要),一個glTF格式(.gltf)、一個二進(jìn)制glTF格式 (.glb)。
下來我們寫示例代碼. 打開Sandcastle Hello World 示例。在 var viewer = ... 之后第4行,增加一個 scene 變量。
var scene = viewer.scene;
下來,使用Cesium.Model.fromGltf 加載汽車模型 ,添加下面的代碼:
var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(-75.62898254394531, 40.02804946899414, 0.0));
var model = scene.primitives.add(Cesium.Model.fromGltf({
url : '../../../../Apps/SampleData/models/GroundVehicle/GroundVehicle.glb',
modelMatrix : modelMatrix,
scale : 200.0
}));
按F8運(yùn)行,使用右上角的位置查詢工具,定位到 Exton, PA。

現(xiàn)在我們垂直俯視觀察這個汽車了。使用鼠標(biāo)右鍵拉近一點,然后鼠標(biāo)中鍵按下旋轉(zhuǎn)視角放平一點。

Cesium.Model.fromGltf方法異步載入了glTF 以及它的一些外部資源文件,完全載入(響應(yīng)了 readyPromise)之后進(jìn)行了渲染。只需要gltf文件的url路徑,示例中就是這個../../../../Apps/SampleData/models/GroundVehicle/GroundVehicle.glb。
fromGltf有個可選的參數(shù)scale 可以用來放大縮小模型。很多實際大小的模型都相對地球來說太小了,為了測試可以用 scale把模型放大一些,有時候甚至可以非常大,比如200000.0:

fromGltf也可以設(shè)置一個 modelMatrix 去放置或者旋轉(zhuǎn)模型。這個參數(shù)會用來創(chuàng)建模型的局部坐標(biāo)系。我們這里使用了 Cesium.Transforms.eastNorthUpToFixedFrame去創(chuàng)建了一個以經(jīng)緯度(-75.62898254394531,40.02804946899414)為原點的enu(east-north-up )局部坐標(biāo)系。為了移動模型,可以隨時修改模型的 modelMatrix 屬性。
為了能看見坐標(biāo)系統(tǒng),使用Cesium的調(diào)試工具, 在第4行的var viewer = ...之后添加如下代碼:
viewer.extend(Cesium.viewerCesiumInspectorMixin);
按 F8運(yùn)行,調(diào)試工具已經(jīng)顯示在右上角了。展開 Primitives面板,點擊Pick a Primitive,然后在場景中點擊汽車模型,然后勾選show reference frame。

這里
x 軸(正東向)是紅色的, y 軸(正北向)是綠色的,z 軸(垂直向上)是藍(lán)色的。如果加載飛機(jī)或者人物的模型,那么只需要修改代碼里的
url參數(shù)為 '../../../../Apps/SampleData/models/CesiumAir/Cesium_Air.glb' 或者'../../../../Apps/SampleData/models/CesiumMan/Cesium_Man.glb'。完整的配置參數(shù) 查看用戶手冊Cesium.Model.fromGltf 。
動畫
上面的模型都自帶了模型數(shù)據(jù)制作者內(nèi)置的關(guān)鍵幀動畫,數(shù)據(jù)制作者定義了一些關(guān)鍵位置的模型姿態(tài),Cesium會實時插值做變換展示一個平滑的動畫效果。 為了能播放動畫,在 Cesium.Model.fromGltf調(diào)用后,添加下面的代碼:
Cesium.when(model.readyPromise).then(function(model) {
model.activeAnimations.addAll({
loop : Cesium.ModelAnimationLoop.REPEAT
});
});
因為動畫也是存儲在glTF模型里,所以需要等待readyPromise執(zhí)行后才能訪問他們。addAll 方法調(diào)用后播放模型的所有動畫。Cesium.ModelAnimationLoop.REPEAT參數(shù)設(shè)置后,會一直循環(huán)播放動畫,直到activeAnimations集合里刪除了對應(yīng)的動畫。如果要播放某一個特定動畫,那么使用 add 方法,傳一個動畫 id (glTF文件內(nèi)部定義的)。
除了loop 選項,addAll和 add 函數(shù)提供了一些列的參數(shù)選項,用來控制動畫的開始、結(jié)束、播放速度,以及播放方向。比如下面的代碼設(shè)定動畫逆向按照半速(相對Cesium時鐘)播放:
model.activeAnimations.addAll({
loop : Cesium.ModelAnimationLoop.REPEAT,
speedup : 0.5,
reverse : true
});
add 函數(shù)返回一個 ModelAnimation 類實例 (addAll 返回一個該類的實例數(shù)組), 這個類包含了動畫的開始、停止、每幀更新的事件。比如可以用來控制一個動畫在另一個結(jié)束后開始播放。具體查看 start, stop, 和update 事件.
動畫是和Cesium時鐘同步的,所以可以在動畫播放控件上按下播放按鈕控制它。也可以通過該控件和時間線的加速、減速、逆向播放功能來控制動畫的狀態(tài)。

為了讓場景中的動畫自動播放,可以用下面的代碼來初始化Viewer:
var viewer = new Cesium.Viewer('cesiumContainer', {
shouldAnimate : true
});
拾取
和Cesium的所有圖元一樣, 如果模型被選中了,那么 Scene.pick 的返回值將包括 Model 類的實例。同時,glTF中的節(jié)點(node)id 和 三角網(wǎng)(mesh)id 也會被返回。用這個可以判定精確的模型點擊部位。下面的代碼在控制臺輸出了鼠標(biāo)所在位置對應(yīng)的glTF模型中的節(jié)點和三角網(wǎng)。
var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction(
function (movement) {
var pick = scene.pick(movement.endPosition);
if (Cesium.defined(pick) && Cesium.defined(pick.node) && Cehack.mesh)) {
console.log('node: ' + pick.node.name + '. mesh: ' + pick.mesh.name);
}
},
Cesium.ScreenSpaceEventType.MOUSE_MOVE
);
把 COLLADA(dae)轉(zhuǎn) glTF
可以使用Cesium的 在線工具. 把 .dae 和圖片文件轉(zhuǎn)為一個內(nèi)嵌圖片資源的.gltf文件。
問題
如果Cesium加載三維模型有問題,那么首先定位問題出現(xiàn)在哪個階段:
- Max,Maya, Modo, SketchUp 等建模工具的 COLLADA 導(dǎo)出器有沒有問題
- COLLADA-to-glTF轉(zhuǎn)換工具有沒有問題
- Cesium glTF 渲染代碼有沒有問題
Mac 上解決問題
在Mac系統(tǒng)上,判定一個COLLADA 文件是否導(dǎo)出正常,雙擊.dae 文件,它應(yīng)該會顯示在預(yù)覽窗口上。如果模型帶動畫,那么鼠標(biāo)移動到這個窗口上會顯示一個動畫控制的工具欄。

如果COLLADA 文件有問題,那么預(yù)覽界面會提示錯誤。這一般是由于建模工具的導(dǎo)出器有bug。

為了解決這個問題,安裝 Xcode,然后右鍵單機(jī)這個.dae 文件,選擇 Open With -> Xcode。

Xcode 如同預(yù)覽窗口一樣顯示模型,但是它有更多額外功能,比如選擇一個獨立的節(jié)點。Xcode實際上對于預(yù)覽窗口上顯示不了的dae有很多解決辦法。如果模型可以在Xcode 中加載,那么選擇
File - Save 保存一下就能解決問題,這時候預(yù)覽就沒有問題了。

如果還是無法預(yù)覽,那就是COLLADA 導(dǎo)出器有嚴(yán)重問題了。首先確認(rèn)你使用的最新版的建模工具,然后試下 這篇文章。如果還不能解決,那么給建模工具提bug去吧。也可以試下先導(dǎo)出
.fbx 格式,然后在其他工具中導(dǎo)入fbx,再導(dǎo)出dae。
Windows 上解決問題
Windows上,VS2013(包括免費的社區(qū)版本)包含一個模型編輯器,他可以加載COLLADA模型。判斷一個COLLADA文件是否導(dǎo)出正常,把 .dae 文件拖拽到VS窗口里,如果正常顯示,就是正常的。否則,可能有一些bug。試下 這篇文章。果還不能解決,那么給建模工具提bug去吧。也可以試下先導(dǎo)出.fbx 格式,然后在其他工具中導(dǎo)入fbx,再導(dǎo)出dae。

如果你沒有Visual Studio,Autodesk 提供了一個基于WebGL的可視化工具 ??梢园涯P屯献нM(jìn)去,無需登陸就能測試。但是這個工具不支持動畫,如果模型包含圖片,那么上傳一個zip壓縮包,把dae和圖片都打進(jìn)去。
Cesium 上解決問題
COLLADA 文件準(zhǔn)備好之后,那么使用[在線工具 ] (https://cesiumjs.org/convertmodel.html)轉(zhuǎn)下格式再在Cesium中加載。如果沒于加載成功,那么說明這個轉(zhuǎn)換工具或者Cesium有bug。為了獲取更多信息,打開瀏覽器的調(diào)試工具 (Chrome快捷鍵Ctrl-Shift-I ) ,并且選中 Pause on all exceptions (Chrome在 Sources面板里 ), 然后刷新頁面.

也可以在Cesium論壇 上發(fā)一個帖子,我們修正bug后會提供一個解決方法。如果你發(fā)帖子,請包含下面內(nèi)容:
- COLLADA 源文件 和轉(zhuǎn)換后的 glTF文件。我們也知道不是所有人都愿意共享它的模型數(shù)據(jù),但是如果你共享了,那么對于解決問題很有幫助。
- 當(dāng)模型加載的時候 瀏覽器控制臺窗口輸出的所有異常信息 。

其他資源
再看下Sandcastle 中 3D models 示例。 Model 類和ModelAnimationCollection類的官方文檔。
