cesium 學習(五) 加載場景模型
一、前言
現在開始實際的看看效果,目前我所接觸到基本上都是使用Cesium加載模型這個內容,以及在模型上進行操作。So,現在進行一些加載模型的學習,數據的話可以去網上找,因為目前使用的都是需要保密的數據,所以不能發在網上。
二、加載Entity類型模型
說到加載Entity模型,內容就有點多了,cesium場景中的點、線、面、label以及模型(gltf、glb);還有圓、牆體、方體、球等幾何對象也都可以使用Entity來加載。下面分別加載試試看。
2.1加載點、線、面

var viewer = new Cesium.Viewer('cesiumContainer'); // 場景查看器對象 // 點的Entity var pointEntity = new Cesium.Entity({ id: 'point', // id屬性 position: Cesium.Cartesian3.fromDegrees(103, 30, 10), // 位置 point: { // 點 color: new Cesium.Color.fromCssColorString("#3388ff"), // 點顏色 pixelSize: 10, // 點大小 outlineColor: new Cesium.Color.fromCssColorString("#ffffff"), // 點的外圈線顏色 outlineWidth: 2, // 點的外圈線寬度 disableDepthTestDistance: Number.POSITIVE_INFINITY // 被遮擋是否可見(也就是將這個Entity在場景中置頂) } }); // 線的Entity var lineEntity = new Cesium.Entity({ name: "line", // 線的name屬性 polyline: { // 線 positions: [Cesium.Cartesian3.fromDegrees(103, 30, 50), Cesium.Cartesian3.fromDegrees(104, 30, 50)], // 由點構線 width: 5.0, // 線的寬度 material: new Cesium.PolylineGlowMaterialProperty({ color: Cesium.Color.GOLD, }), // 線的材質、樣式 depthFailMaterial: new Cesium.PolylineGlowMaterialProperty({ color: Cesium.Color.GOLD, }), // 視線被遮擋處的材質、樣式(和上一個材質一樣的話則就不會被遮擋,類似置頂效果) } }); // 面的Entity,其他Entity屬性可以自行查看API var polygon = new Cesium.Entity({ polygon: { height: 0.1, hierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArrayHeights([103, 30, 10, 103, 40, 10, 104, 30, 10])), // 面的頂點坐標集合 material: new Cesium.Color.fromCssColorString("#FFD700").withAlpha(.2), // 材質樣式 perPositionHeight: true, // 是否支持坐標高度 } });
2.2加載label
其實label一般和其他一起使用,比如點。

1 var entity = viewer.entities.add({ 2 id: '123', 3 position: Cesium.Cartesian3.fromDegrees(103, 30, 5), 4 point: { 5 color: new Cesium.Color.fromCssColorString("#3388ff"), 6 pixelSize: 10, 7 outlineColor: new Cesium.Color.fromCssColorString("#3388ff"), 8 outlineWidth: 2, 9 heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND, 10 disableDepthTestDistance: Number.POSITIVE_INFINITY 11 }, 12 label: { 13 text: 'lable文本', 14 font: '10px sans-serif', // 字體 15 style: Cesium.LabelStyle.FILL_AND_OUTLINE, // 樣式 16 fillColor: Cesium.Color.WHITE, // 填充色 17 outlineWidth: 1, // 字體外圈線寬度(同樣也有顏色可設置) 18 verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 垂直位置 19 pixelOffset: new Cesium.Cartesian2(0, -15), // 中心位置 20 disableDepthTestDistance: Number.POSITIVE_INFINITY 21 } 22 });
2.3加載model
model類型的entity的資源可以是使用max等建模軟件做的模型,然后轉換成webgl加載的模型——gltf、glb。

1 var modelentity = viewer.entities.add({ 2 name:'123', 3 description:"<div><img src='Build/Cesium/Assets/Images/cesium_credit.png' /><p>這是一輛大車!</div>", // 這是模型的描述屬性,可以是html標簽 4 position : Cesium.Cartesian3.fromDegrees(103, 30), 5 model : { 6 uri : 'Models/GroundVehicle/GroundVehicle.glb' // 資源路徑 7 } 8 });
三、加載Primitive類型模型
Primitive類型的加載也是比較有趣的,在Entity中不好控制的一些屬性,可以在Primitive中很好的控制,比如Entity沒有加載完成事件,而Primitive有加載完成事件;entity只能加載一個對象,而Primitive可以一次加載多個對象。
當然Entity類型也是有它獨特的好處的,不然官方也不會將其制造出來,明顯的就是Entity類封裝了很多個幾何對象,非常方便的繪制出幾何對象來,而如果使用Primitive的話你需要懂的知識不少,比如幾何對象的構造。
回到Primitive上,它的好處是高效加載、靈活繪制;Primitive的加載機制要好於Entity,這點我沒有去做詳細測試,但是網上是有這個測試的;對於其靈活性,主要是它可以不僅是單個幾何對象,可以是多個幾何對象或是不規則的對象的繪制加載,這點Entity沒法做。
好,還是通過幾個加載來認識下Primitive。
3.1加載模型
1 var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame( 2 Cesium.Cartesian3.fromDegrees(-75.62898254394531, 40.02804946899414, 0.0) 3 ); 4 viewer.scene.primitives.add(Cesium.Model.fromGltf({ //fromGltf方法:從Gltf資源加載模型 5 url: 'Models/GroundVehicle/GroundVehicle.glb', 6 modelMatrix: modelMatrix, 7 // minimumPixelSize : 512, 8 // maximumScale : 200000 9 }) 10 ); 11 viewer.camera.flyTo({ 12 destination: Cesium.Cartesian3.fromDegrees(-75.62898254394531, 40.02804946899414, 30.0) 13 });
3.2加載動畫模型

1 var controller = viewer.scene.screenSpaceCameraController; 2 //中心點 3 var center = new Cesium.Cartesian3(); 4 //模型的偏移參數 5 var hpRoll = new Cesium.HeadingPitchRoll(); 6 //相機的偏移參數 7 var hpRange = new Cesium.HeadingPitchRange(); 8 //初始位置 9 position = Cesium.Cartesian3.fromDegrees(103, 30, 0.08); 10 //速度向量 11 var speedVector = new Cesium.Cartesian3(); 12 //生成一個由兩個參考系生成的矩陣 13 var fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator('north', 'west'); 14 //加載模型 15 peoPrimitive = scene.primitives.add(Cesium.Model.fromGltf({ 16 //這里需要把模型路徑改下(如果你用的還是HelloWord.html的話就用這個,不是的話請自行修改) 17 url: '../Models/GLTF/CesiumMan/Cesium_Man.glb', 18 modelMatrix: Cesium.Transforms.headingPitchRollToFixedFrame(position, hpRoll, Cesium.Ellipsoid.WGS84, fixedFrameTransform), 19 //minimumPixelSize: 128 20 })); 21 22 //動畫播放 23 peoPrimitive.readyPromise.then(function (model) { 24 // 以半速循環動畫 25 model.activeAnimations.addAll({ 26 speedup: 1, 27 loop: Cesium.ModelAnimationLoop.REPEAT 28 }); 29 //r=2*max(模型的半徑,相機的最近距離) 30 r = 2.0 * Math.max(model.boundingSphere.radius, camera.frustum.near); 31 //鏡頭最近距離 32 controller.minimumZoomDistance = r * 0.5; 33 //計算center位置(也為下面的鏡頭跟隨提供了center位置) 34 Cesium.Matrix4.multiplyByPoint(model.modelMatrix, model.boundingSphere.center, center); 35 //相機偏移角度 36 var heading = Cesium.Math.toRadians(0.0); 37 var pitch = Cesium.Math.toRadians(-20.0); 38 hpRange.heading = heading; 39 hpRange.pitch = pitch; 40 hpRange.range = r + 5; 41 //固定相機 42 camera.lookAt(center, hpRange); 43 });
3.3加載多個幾何對象

1 var instances = []; 2 var positions_l = [......]; // Cartesian3坐標集合 3 positions_l.forEach(position => { 4 instances.push(new Cesium.GeometryInstance({ 5 geometry: new Cesium.EllipseGeometry({ 6 center: position, 7 semiMinorAxis: 0.024, 8 semiMajorAxis: 0.024, 9 height: 0, 10 extrudedHeight: height1, 11 material: Cesium.Color.GOLD, 12 }), 13 id: { guid: guid, jsj_name: name, name: '立桿' }, 14 attributes: { 15 color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.GOLDENROD) 16 } 17 })); 18 }); 19 // instances 就是很多個幾何對象(這里是圓柱),然后后用primitive統一合並加載 20 var ganmodel = viewer.scene.primitives.add(new Cesium.Primitive({ 21 geometryInstances: instances, 22 appearance: new Cesium.MaterialAppearance({ 23 material: Cesium.Material.fromType('Color', { 24 color: Cesium.Color.GOLD 25 }), 26 }), 27 }));
四、總結
Entity加載方式在一定程度上是比Primitive方式更加方便的,特別是Entity不僅可以加載點、線、面、標簽、模型、幾何對象,而且是可以同時加載比如點和標簽一起加載,如果願意可以使用一個Entity對象加載一個點、一條線、一個面、一個模型、多個不同的幾何對象!當然Primitive方法也是可以的,不過就沒有Entity這么方便了。
Primitive主要是更偏底層一些,它可以使用Entity沒有的一些屬性,然后也更加靈活一些,比如我最后的添加多個立桿模型,Entity方法是沒法構造一個Entity對象完成多個立桿的繪制的,有多少個立桿就得創建多少個Entity在內存使用上就稍微弱了。