Cesium学习笔记(六):几何和外观(Geometry and Appearances)

xiaoxiao2021-02-28  99

我们先直接来看一个例子

var viewer = new Cesium.Viewer('cesiumContainer'); var flag = viewer.entities.add({ rectangle : { coordinates : Cesium.Rectangle.fromDegrees(-100.0, 20.0, -90.0, 30.0), material : new Cesium.StripeMaterialProperty({ evenColor: Cesium.Color.WHITE, oddColor: Cesium.Color.BLUE, repeat: 5 }) } });

这是我们之前的写法,直接创建一个实体对象

而在这一章,我们将会使用几何和外观来创建实体对象,这样更灵活更有效率

首先,还是先看一下,上面那段代码的改造

var viewer = new Cesium.Viewer('cesiumContainer'); var scene = viewer.scene; //创建几何图形 var instance = new Cesium.GeometryInstance({ geometry : new Cesium.RectangleGeometry({ rectangle : Cesium.Rectangle.fromDegrees(-100.0, 20.0, -90.0, 30.0), vertexFormat : Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT }) }); scene.primitives.add(new Cesium.Primitive({ geometryInstances : instance, //使用系统自带的条纹样式 appearance : new Cesium.EllipsoidSurfaceAppearance({ material : Cesium.Material.fromType('Stripe') }) }));

这样的写法自然是有优点也有缺点的

优点:

性能 - 当绘制大量静态图元时,直接使用几何形状可以将它们组合成单个几何体,以减少CPU开销并更好地利用GPU。并且组合是在网络上完成的,可以保持UI的响应。灵活性 - 基元组合几何和外观。通过解耦,我们可以独立地修改。我们可以添加与许多不同外观兼容的新几何体,反之亦然。低级访问 - 外观提供了接近于渲染器的访问,可以直接使用渲染器的所有细节(Appearances provide close-to-the-metal access to rendering without having to worry about all the details of using the Renderer directly)。外观使其易于: 编写完整的GLSL顶点和片段着色器。使用自定义渲染状态。

缺点:

代码量增大,并且需要使用者对这方面有更深入的理解。组合几何可以使用静态数据,不一定是动态数据。primitives 的抽象级别适合于映射应用程序;几何图形和外观的抽象层次接近传统的3D引擎(Primitives are at the level of abstraction appropriate for mapping apps; geometries and appearances have a level of abstraction closer to a traditional 3D engine)(感觉翻译的不太好的地方都给上了原文)

我们可以用一个primitives画出多个几何图形,这样可以明显能看出性能上的优势

var viewer = new Cesium.Viewer('cesiumContainer'); var scene = viewer.scene; var instance = new Cesium.GeometryInstance({ geometry : new Cesium.RectangleGeometry({ rectangle : Cesium.Rectangle.fromDegrees(-100.0, 20.0, -90.0, 30.0), vertexFormat : Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT }) }); var anotherInstance = new Cesium.GeometryInstance({ geometry : new Cesium.RectangleGeometry({ rectangle : Cesium.Rectangle.fromDegrees(-85.0, 20.0, -75.0, 30.0), vertexFormat : Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT }) }); scene.primitives.add(new Cesium.Primitive({ geometryInstances : [instance, anotherInstance], appearance : new Cesium.EllipsoidSurfaceAppearance({ material : Cesium.Material.fromType('Stripe') }) }));

对于不同的图形,我们可以单独给它们设置属性,这里,我们使用PerInstanceColorAppearance不同颜色来遮蔽每个实例

var viewer = new Cesium.Viewer('cesiumContainer'); var scene = viewer.scene; var instance = new Cesium.GeometryInstance({ geometry : new Cesium.RectangleGeometry({ rectangle : Cesium.Rectangle.fromDegrees(-100.0, 20.0, -90.0, 30.0), vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT }), attributes : { //(红,绿,蓝,透明度) color : new Cesium.ColorGeometryInstanceAttribute(0.0, 0.0, 1.0, 0.8) } }); var anotherInstance = new Cesium.GeometryInstance({ geometry : new Cesium.RectangleGeometry({ rectangle : Cesium.Rectangle.fromDegrees(-85.0, 20.0, -75.0, 30.0), vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT }), attributes : { color : new Cesium.ColorGeometryInstanceAttribute(1.0, 0.0, 0.0, 0.8) } }); scene.primitives.add(new Cesium.Primitive({ geometryInstances : [instance, anotherInstance], appearance : new Cesium.PerInstanceColorAppearance() }));

可能这样大家还感觉不出来性能上的优势,那我们可以这样

var viewer = new Cesium.Viewer('cesiumContainer'); var scene = viewer.scene; var instances = []; //循环创建随机颜色的矩形 for (var lon = -180.0; lon < 180.0; lon += 5.0) { for (var lat = -85.0; lat < 85.0; lat += 5.0) { instances.push(new Cesium.GeometryInstance({ geometry : new Cesium.RectangleGeometry({ rectangle : Cesium.Rectangle.fromDegrees(lon, lat, lon + 5.0, lat + 5.0), vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT }), attributes : { color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.fromRandom({alpha : 0.5})) } })); } } scene.primitives.add(new Cesium.Primitive({ geometryInstances : instances, appearance : new Cesium.PerInstanceColorAppearance() }));

这里画了2592个不同颜色的矩形,而且速度非常快,这就更明显的看出primitives在性能上的优势了

虽然我们是通过一个primitives来创建的,但是我们可以给每一个几何图形一个id,这样我们就可以单独访问他们了、

var instance = new Cesium.GeometryInstance({ id : "blue rectangle", geometry : new Cesium.RectangleGeometry({ rectangle : Cesium.Rectangle.fromDegrees(-100.0, 20.0, -90.0, 30.0), vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT }), attributes : { color : new Cesium.ColorGeometryInstanceAttribute(0.0, 0.0, 1.0, 0.8) } }); var anotherInstance = new Cesium.GeometryInstance({ id : "red rectangle", geometry : new Cesium.RectangleGeometry({ rectangle : Cesium.Rectangle.fromDegrees(-85.0, 20.0, -75.0, 30.0), vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT }), attributes : { color : new Cesium.ColorGeometryInstanceAttribute(1.0, 0.0, 0.0, 0.8) } }); scene.primitives.add(new Cesium.Primitive({ geometryInstances : [instance, anotherInstance], appearance : new Cesium.PerInstanceColorAppearance() })); //获取屏幕事件管理器 var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas); //监听屏幕输入事件(这里是监听左键点击事件) handler.setInputAction(function (movement) { var pick = scene.pick(movement.position); if (Cesium.defined(pick) ) { switch (pick.id) { case 'blue rectangle': console.log('Mouse clicked blue rectangle.'); break; case 'red rectangle': console.log('Mouse clicked red rectangle.'); break; } } }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

然后我点击两个矩形,控制台就输出了相应的log

当只要改变属性,不需要改变几何形状时候还可以把几何图形的创建给提出来

var viewer = new Cesium.Viewer('cesiumContainer'); var scene = viewer.scene; //使用同一个几何图形 var ellipsoidGeometry = new Cesium.EllipsoidGeometry({ vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT, radii : new Cesium.Cartesian3(300000.0, 200000.0, 150000.0) }); var cyanEllipsoidInstance = new Cesium.GeometryInstance({ geometry : ellipsoidGeometry, //不同的模型矩阵改变了位置 modelMatrix : Cesium.Matrix4.multiplyByTranslation( Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(-100.0, 40.0)), new Cesium.Cartesian3(0.0, 0.0, 150000.0), new Cesium.Matrix4() ), //改变了颜色 attributes : { color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.CYAN) } }); var orangeEllipsoidInstance = new Cesium.GeometryInstance({ geometry : ellipsoidGeometry, modelMatrix : Cesium.Matrix4.multiplyByTranslation( Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(-100.0, 40.0)), new Cesium.Cartesian3(0.0, 0.0, 450000.0), new Cesium.Matrix4() ), attributes : { color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.ORANGE) } }); scene.primitives.add(new Cesium.Primitive({ geometryInstances : [cyanEllipsoidInstance, orangeEllipsoidInstance], appearance : new Cesium.PerInstanceColorAppearance({ //不透明 translucent : false, closed : true }) }));

在创建完之后,我们依旧可以动态的修改模型的属性,当然,这需要给模型加上一个id

var viewer = new Cesium.Viewer('cesiumContainer'); var scene = viewer.scene; var ellipsoidGeometry = new Cesium.EllipsoidGeometry({ vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT, radii : new Cesium.Cartesian3(300000.0, 200000.0, 150000.0) }); var cyanEllipsoidInstance = new Cesium.GeometryInstance({ id : 'cyan', geometry : ellipsoidGeometry, modelMatrix : Cesium.Matrix4.multiplyByTranslation( Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(-100.0, 40.0)), new Cesium.Cartesian3(0.0, 0.0, 150000.0), new Cesium.Matrix4() ), attributes : { color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.CYAN) } }); var orangeEllipsoidInstance = new Cesium.GeometryInstance({ id : 'orange', geometry : ellipsoidGeometry, modelMatrix : Cesium.Matrix4.multiplyByTranslation( Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(-100.0, 40.0)), new Cesium.Cartesian3(0.0, 0.0, 450000.0), new Cesium.Matrix4() ), attributes : { color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.ORANGE) } }); var primitive = scene.primitives.add(new Cesium.Primitive({ geometryInstances : [cyanEllipsoidInstance, orangeEllipsoidInstance], appearance : new Cesium.PerInstanceColorAppearance({ //不透明 translucent : false, closed : true }) })); setInterval(function() { var attributes1 = primitive.getGeometryInstanceAttributes('cyan'); attributes1.color = Cesium.ColorGeometryInstanceAttribute.toValue(Cesium.Color.fromRandom({alpha : 1.0})); var attributes2 = primitive.getGeometryInstanceAttributes('orange'); attributes2.color = Cesium.ColorGeometryInstanceAttribute.toValue(Cesium.Color.fromRandom({alpha : 1.0})); },1000);

下面列举下cesium中的几何图形和外观,要注意的是有些外观和几何是不兼容的

几何图形描述BoxGeometry盒子BoxOutlineGeometry只有外部线条的的盒子CircleGeometry圆圈或挤压圆CircleOutlineGeometry同上(只有线条的圆,后面我就省略了)CorridorGeometry垂直于表面的折线,宽度以米为单位,可选择挤压高度CorridorOutlineGeometryCylinderGeometry圆柱体,圆锥体或截锥体CylinderOutlineGeometryEllipseGeometry椭圆或挤出椭圆EllipseOutlineGeometryEllipsoidGeometry椭圆形EllipsoidOutlineGeometryRectangleGeometry矩形或挤压矩形RectangleOutlineGeometryPolygonGeometry具有可选孔或挤出多边形的多边形PolygonOutlineGeometryPolylineGeometry一组宽度为像素的线段SimplePolylineGeometryPolylineVolumeGeometry沿着折线挤压的2D形状PolylineVolumeOutlineGeometrySphereGeometry一个球体SphereOutlineGeometryWallGeometry垂直于地球的墙壁WallOutlineGeometry 外观描述MaterialAppearance外观与所有几何类型一起使用,并支持材料描述阴影。EllipsoidSurfaceAppearance几何像几何平行于地球表面的“Material Appearance”一样,就像一个多边形,并且使用这个假设来通过程序上计算许多顶点属性来节省内存。PerInstanceColorAppearance使用每个实例的颜色来遮蔽每个实例。PolylineMaterialAppearance支持材料遮蔽Polyline。PolylineColorAppearance使用每顶点或每段着色来遮蔽折线。

参考资料:官方文档

转载请注明原文地址: https://www.6miu.com/read-24250.html

最新回复(0)