cesium 学习(五) 加载场景模型
cesium 学习(五) 加载场景模型
一、前言
现在开始实际的看看效果,目前我所接触到基本上都是使用Cesium加载模型这个内容,以及在模型上进行操作。So,现在进行一些加载模型的学习,数据的话可以去网上找,因为目前使用的都是需要保密的数据,所以不能发在网上。
二、加载Entity类型模型
说到加载Entity模型,内容就有点多了,cesium场景中的点、线、面、label以及模型(gltf、glb);还有圆、墙体、方体、球等几何对象也都可以使用Entity来加载。下面分别加载试试看。
2.1加载点、线、面
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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一般和其他一起使用,比如点。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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加载动画模型
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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加载多个几何对象
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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在内存使用上就稍微弱了。