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(, , ), // 位置
point: { // 点
color: new Cesium.Color.fromCssColorString("#3388ff"), // 点颜色
pixelSize: , // 点大小
outlineColor: new Cesium.Color.fromCssColorString("#ffffff"), // 点的外圈线颜色
outlineWidth: , // 点的外圈线宽度
disableDepthTestDistance: Number.POSITIVE_INFINITY // 被遮挡是否可见(也就是将这个Entity在场景中置顶)
}
});
// 线的Entity
var lineEntity = new Cesium.Entity({
name: "line", // 线的name属性
polyline: { // 线
positions: [Cesium.Cartesian3.fromDegrees(, , ), Cesium.Cartesian3.fromDegrees(, , )], // 由点构线
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([, , , , , , , , ])), // 面的顶点坐标集合
material: new Cesium.Color.fromCssColorString("#FFD700").withAlpha(.), // 材质样式
perPositionHeight: true, // 是否支持坐标高度
}
});
2.2加载label
其实label一般和其他一起使用,比如点。
var entity = viewer.entities.add({
id: '',
position: Cesium.Cartesian3.fromDegrees(, , ),
point: {
color: new Cesium.Color.fromCssColorString("#3388ff"),
pixelSize: ,
outlineColor: new Cesium.Color.fromCssColorString("#3388ff"),
outlineWidth: ,
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
disableDepthTestDistance: Number.POSITIVE_INFINITY
},
label: {
text: 'lable文本',
font: '10px sans-serif', // 字体
style: Cesium.LabelStyle.FILL_AND_OUTLINE, // 样式
fillColor: Cesium.Color.WHITE, // 填充色
outlineWidth: , // 字体外圈线宽度(同样也有颜色可设置)
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 垂直位置
pixelOffset: new Cesium.Cartesian2(, -), // 中心位置
disableDepthTestDistance: Number.POSITIVE_INFINITY
}
});
2.3加载model
model类型的entity的资源可以是使用max等建模软件做的模型,然后转换成webgl加载的模型——gltf、glb。
var modelentity = viewer.entities.add({
name:'',
description:"<div><img src='Build/Cesium/Assets/Images/cesium_credit.png' /><p>这是一辆大车!</div>", // 这是模型的描述属性,可以是html标签
position : Cesium.Cartesian3.fromDegrees(, ),
model : {
uri : 'Models/GroundVehicle/GroundVehicle.glb' // 资源路径
}
});
三、加载Primitive类型模型
Primitive类型的加载也是比较有趣的,在Entity中不好控制的一些属性,可以在Primitive中很好的控制,比如Entity没有加载完成事件,而Primitive有加载完成事件;entity只能加载一个对象,而Primitive可以一次加载多个对象。
当然Entity类型也是有它独特的好处的,不然官方也不会将其制造出来,明显的就是Entity类封装了很多个几何对象,非常方便的绘制出几何对象来,而如果使用Primitive的话你需要懂的知识不少,比如几何对象的构造。
回到Primitive上,它的好处是高效加载、灵活绘制;Primitive的加载机制要好于Entity,这点我没有去做详细测试,但是网上是有这个测试的;对于其灵活性,主要是它可以不仅是单个几何对象,可以是多个几何对象或是不规则的对象的绘制加载,这点Entity没法做。
好,还是通过几个加载来认识下Primitive。
3.1加载模型
var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(-75.62898254394531, 40.02804946899414, 0.0)
);
viewer.scene.primitives.add(Cesium.Model.fromGltf({ //fromGltf方法:从Gltf资源加载模型
url: 'Models/GroundVehicle/GroundVehicle.glb',
modelMatrix: modelMatrix,
// minimumPixelSize : 512,
// maximumScale : 200000
})
);
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(-75.62898254394531, 40.02804946899414, 30.0)
});
3.2加载动画模型
var controller = viewer.scene.screenSpaceCameraController;
//中心点
var center = new Cesium.Cartesian3();
//模型的偏移参数
var hpRoll = new Cesium.HeadingPitchRoll();
//相机的偏移参数
var hpRange = new Cesium.HeadingPitchRange();
//初始位置
position = Cesium.Cartesian3.fromDegrees(, , 0.08);
//速度向量
var speedVector = new Cesium.Cartesian3();
//生成一个由两个参考系生成的矩阵
var fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator('north', 'west');
//加载模型
peoPrimitive = scene.primitives.add(Cesium.Model.fromGltf({
//这里需要把模型路径改下(如果你用的还是HelloWord.html的话就用这个,不是的话请自行修改)
url: '../Models/GLTF/CesiumMan/Cesium_Man.glb',
modelMatrix: Cesium.Transforms.headingPitchRollToFixedFrame(position, hpRoll, Cesium.Ellipsoid.WGS84, fixedFrameTransform),
//minimumPixelSize: 128
})); //动画播放
peoPrimitive.readyPromise.then(function (model) {
// 以半速循环动画
model.activeAnimations.addAll({
speedup: ,
loop: Cesium.ModelAnimationLoop.REPEAT
});
//r=2*max(模型的半径,相机的最近距离)
r = 2.0 * Math.max(model.boundingSphere.radius, camera.frustum.near);
//镜头最近距离
controller.minimumZoomDistance = r * 0.5;
//计算center位置(也为下面的镜头跟随提供了center位置)
Cesium.Matrix4.multiplyByPoint(model.modelMatrix, model.boundingSphere.center, center);
//相机偏移角度
var heading = Cesium.Math.toRadians(0.0);
var pitch = Cesium.Math.toRadians(-20.0);
hpRange.heading = heading;
hpRange.pitch = pitch;
hpRange.range = r + ;
//固定相机
camera.lookAt(center, hpRange);
});
3.3加载多个几何对象
var instances = [];
var positions_l = [......]; // Cartesian3坐标集合
positions_l.forEach(position => {
instances.push(new Cesium.GeometryInstance({
geometry: new Cesium.EllipseGeometry({
center: position,
semiMinorAxis: 0.024,
semiMajorAxis: 0.024,
height: ,
extrudedHeight: height1,
material: Cesium.Color.GOLD,
}),
id: { guid: guid, jsj_name: name, name: '立杆' },
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.GOLDENROD)
}
}));
});
// instances 就是很多个几何对象(这里是圆柱),然后后用primitive统一合并加载
var ganmodel = viewer.scene.primitives.add(new Cesium.Primitive({
geometryInstances: instances,
appearance: new Cesium.MaterialAppearance({
material: Cesium.Material.fromType('Color', {
color: Cesium.Color.GOLD
}),
}),
}));
四、总结
Entity加载方式在一定程度上是比Primitive方式更加方便的,特别是Entity不仅可以加载点、线、面、标签、模型、几何对象,而且是可以同时加载比如点和标签一起加载,如果愿意可以使用一个Entity对象加载一个点、一条线、一个面、一个模型、多个不同的几何对象!当然Primitive方法也是可以的,不过就没有Entity这么方便了。
Primitive主要是更偏底层一些,它可以使用Entity没有的一些属性,然后也更加灵活一些,比如我最后的添加多个立杆模型,Entity方法是没法构造一个Entity对象完成多个立杆的绘制的,有多少个立杆就得创建多少个Entity在内存使用上就稍微弱了。