Cesium学习笔记

Cesium简介

Cesium是一个基于JavaScript的开源框架,可用于在浏览器中绘制3D的地球,并在其上绘制地图(支持多种格式的瓦片服务),该框架不需要任何插件支持,但是浏览器必须支持WebGL。

Cesium支持多种数据可视化方式,可以绘制各种几何图形、导入图片,甚至3D模型。同时,Cesium还支持基于时间轴的动态数据展示,例如,我们可以用它绘制卫星运行轨迹。

Cesium HelloWorld

下面的例子在浏览器中显示一个太空背景、具有地图覆盖的3D地球:


可以加快时间的运行,并且模拟日光照射效果:

通过以下代码,可以设置镜头位置与指向,Cesium的Camera对象提供了多种操控镜头的方法:

可以添加若干实体,实体可以用于组织多个可视化对象,下面的例子模拟了卫星波束的覆盖范围:

空间数据可视化

Cesium提供Entity API来绘制空间数据,例如点、标记、标签、线、3D模型、形状、立体形状(volume)。

Entity API简介

Cesium提供两类API:

  1. 面向图形开发人员的底层API,通常称为“Primitive API”。该API暴露最小限度的抽象,使用图形学术语,具有很大的灵活性,需要具有图形学编程的知识
  2. 高级别的数据驱动的API,称为“Entity API”。该API使用一致性设计的、高级别的对象来管理一组相关性的可视化对象,其底层使用Primitive API

下面是Entity API的简单例子,用红色半透明区域标记出美国怀俄明州:

形状与立体(Shapes and Volumes)
支持的形状与立体列表
形状  代码示例
立方体
(Boxes)
圆和椭圆
(Circles Ellipses)
走廊
(Corridor)
圆柱和圆锥
(Cylinder Cones)
 
多边形
(Polygons)
多段线
(Polylines)
多段线体
(Polyline Volumes)
矩形
(Rectangles)
球和椭球
(Spheres Ellipsoids)
 

(Walls)
材质(Material)与轮廓(Outline)

多数形状均支持通过一致的方式来设置属性、控制外观:

  1. fill:布尔型,用于指定目标形状是否被填充
  2. outline:布尔型,用于指定是否绘制形状的边缘
  3. material:如果fill为true,该属性可以控制填充的材质类型

一个例外是多段线,可以设置outlineWidth 、outlineColor、glowPower 等属性。

高度与拉伸(Extrusion)

所有的形状均默认均是沿着地表的,目前圆形、椭圆、矩形可以在一定高度浮空显示,或者拉伸为Volume。

需要注意:Cesium总是使用米、弧度、秒为度量单位。下面是一个例子:

在Viewer中可用的Entity特性

除非显式禁用,点击实体后会显示SelectionIndicator小器件,以及一个信息框。通过设置Entity.description,可以在信息框中显示任何HTML内容。

镜头控制

zoomTo方法可以立即定位到某个位置,而flyTo则是通过动画方式转移到某个位置,这两个方法均可以传递EntityCollection对象,并且均是异步方法,返回一个Promises对象

默认情况下,镜头是朝北、45度倾斜查看地球。下面的代码可以让镜头朝东、倾斜三十度查看:

有时需要镜头跟踪某个实体(使居中)而不是地球,可以使用如下代码:

管理Entity

EntityCollection对象是一个从Entity Id到Entity的关联数组,其提供例如add、remove、removeAll之类的常规函数,用于添加或者删除某个Entity:

点、图标和标签

添加一个点、标签或者图标很简单:

3D模型

Cesium支持glTF格式的3D模型,glTF是WebGL、 OpenGL ES、 OpenGL的一种运行时模型格式,在Cesium中创建3D模型很简单:

默认情况下,模型竖直放置、并且面向东面。可以指定四元组(Quaternion)给Entity.orientation属性,以改变放置的方向:

例子中的heading(yaw)、pitch、roll对应了绕Z(垂直轴)、Y(维度方向)、X(经度方向)进行旋转,正数表示顺时针旋转(由于相对运动,在浏览器上看起来是地球在逆时针旋转),可以参考下图理解(人面向北面,摇头heading、点头pitch、歪头roll):head-pitch-roll

属性系统

Cesium提供了一些快捷方式来设置属性,例如outline:true,但是尝试使用e.polygon.outline这样的形式来获取轮廓时,会得到一个ConstantProperty对象,如果不使用快捷方式,则需要编写更多的代码,例如:

所有属性的实例均是Property的子类型,引入属性类层次而不是使用基本类型的原因是,某些属性是随着时间而变化的。

要得到属性的原始值,需要调用Property.getValue()方法,例如:

几何图形与外观

我们可以通过Primitive API来操控几何图形及其外观,或者绘制各种特殊的形状。需要先得到Scene对象,然后在其上添加Primitive对象:

Primitive由两个部分组成:

  1. 几何形状(Geometry):定义了Primitive的结构,例如三角形、线条、点等
  2. 外观(Appearance ):定义Primitive的着色(Sharding),包括GLSL(OpenGL着色语言,OpenGL Shading Language)顶点着色器和片段着色器( vertex and fragment shaders),以及渲染状态(render state)

Cesium支持以下几何图形:

几何图形  说明
BoxGeometry立方体
BoxOutlineGeometry仅有轮廓的立方体
CircleGeometry圆形或者拉伸的圆形
CircleOutlineGeometry只有轮廓的圆形
CorridorGeometry走廊:沿着地表的多段线,且具有一定的宽度,可以拉伸到一定的高度
CorridorOutlineGeometry只有轮廓的走廊
CylinderGeometry圆柱、圆锥或者截断的圆锥
CylinderOutlineGeometry只有轮廓的圆柱、圆锥或者截断的圆锥
EllipseGeometry椭圆或者拉伸的椭圆
EllipseOutlineGeometry只有轮廓的椭圆或者拉伸的椭圆
EllipsoidGeometry椭球体
EllipsoidOutlineGeometry只有轮廓的椭球体
RectangleGeometry矩形或者拉伸的矩形
RectangleOutlineGeometry只有轮廓的矩形或者拉伸的矩形
PolygonGeometry多边形,可以具有空洞或者拉伸一定的高度
PolygonOutlineGeometry只有轮廓的多边形
PolylineGeometry多段线,可以具有一定的宽度
SimplePolylineGeometry简单的多段线
PolylineVolumeGeometry多段线柱体
PolylineVolumeOutlineGeometry只有轮廓的多段线柱体
SphereGeometry球体
SphereOutlineGeometry只有轮廓的球体
WallGeometry
WallOutlineGeometry只有轮廓的墙

使用Geometry和Appearance 具有以下优势:

  1. 性能:绘制大量Primitive时,可以将其合并为单个Geometry以减轻CPU负担、更好的使用GPU。合并Primitive由web worker线程执行,UI保持响应性
  2. 灵活性:Geometry与Appearance 解耦,两者可以分别进行修改
  3. 低级别访问:易于编写GLSL 顶点、片段着色器、使用自定义的渲染状态 

同时,具有以下劣势:

  1. 需要编写更多地代码
  2. 需要对图形编程有更多的理解,特别是OpenGL的知识

使用来Geometry、Appearance 改写上面的例子,代码为:

合并几何图形(Combing Geometries)

合并多个GeometryInstances 为一个Primitive可以极大的提高性能,下面的例子创建了2592一颜色各异的矩形,覆盖整个地球 :

选取几何图形(Picking)

即使多个 GeometryInstance被合并为单个Primitive,让然可以独立的被访问。我们可以为每一个GeometryInstance指定一个id,并且可以通过Scene.pick来判断该实例是否被选取:

几何图形实例(Geometry Instances)

上面的例子中,我们已经用到了GeometryInstances,注意GeometryInstance与Geometry的关系:前者是后者的容器,多个Instance可以共用一个Geometry,并且可以通过GeometryInstances.modelMatrix属性提供不同position、scale、rotate等位置、缩放、旋转信息。例如,下面的例子使用同一个Geometry绘制了两个Instance,一个位于另一个的上方:

更新单个GeometryInstance的属性

在添加到Primitive中以后,让然可以修改几何图形的某些属性:

  1. 颜色:如果Primitive设置了PerInstanceColorAppearance外观,则可以修改ColorGeometryInstanceAttribute类型的颜色
  2. 可见性:任何实例可以修改可见性

示例代码:

外观(Appearances)

Primitive由两个重要部分组成:几何图形实例、外观,一个Primitive只能有一个外观,而可以有多个实例。几何图形定义了结构,外观定义了每个像素被如何着色,外观可能使用材质(Material)。这些对象的关系如下图所示:highleveldesign

Cesium支持下表列出的外观:

 外观 说明
MaterialAppearance支持各种Geometry类型的外观,支持使用材质来定义着色
EllipsoidSurfaceAppearanceMaterialAppearance的一个版本。假设几何图形与地表是平行的,并且依此来进行顶点属性(vertex attributes)的计算
PerInstanceColorAppearance让每个实例使用自定义的颜色来着色
PolylineMaterialAppearance支持使用材质来着色多段线
PolylineColorAppearance使用每顶点或者每片段(per-vertex or per-segment )的颜色来着色多段线

外观定义了需要在GPU上执行的完整的GLSL顶点、片段着色器,通常不需要修改这一部分,除非需要定义自己的外观。

外观还定义了完整的render state,用于在绘制Primitive时控制GPU的状态,可以直接或者通过高层API来定义render state:

一旦外观被创建,其render state就不可再变,但是其材质是可以替换的。另外Primitive的外观也是不可修改的。

大部分外观具有flat、faceForward属性,可以间接的控制GLSL 着色器:

  1. flat:扁平化着色,不考虑光线的作用
  2. faceForward:布尔值,控制光照效果
Geometry与Appearance的兼容性

需要注意,不是所有外观和所有几何图形可以搭配使用,例如EllipsoidSurfaceAppearance与WallGeometry就不能搭配,原因是后者是垂直于地表的。

即使外观与几何图形兼容,它们还必须有匹配的顶点格式(vertex formats)—— 即几何图形必须具有外观可以作为输入的数据格式,在创建Geometry时可以提供VertexFormat。

为了简便,可以让Geometry计算所有顶点属性(vertex attributes),以使之适用于任何外观,但这样做效率较差:

 而如果我们使用外观EllipsoidSurfaceAppearance,其实只需要知道位置:

大部分外观具有vertexFormat属性或者VERTEX_FORMAT 静态常量,创建形状时只需要使用这些顶点格式即可:

此外,两个形状必须具有匹配的vertexFormat,才能被合并到一个Primitive中。

3D模型

我们可以转换、加载并且在Cesium中使用3D模型。Cesium支持glTF(一个新兴的Web 3D模型工业标准)格式的3D模型,并且提供在线的 COLLADA - glTF转换工具。Cesium针对3D模型支持关键帧动画、皮肤、单独节点选取等特性。

Cesium自带了三个模型:飞机、车辆、人。下面的例子载入一个车辆模型:

Cesium自带的3个模型已经内嵌了动画关键桢,如果需要播放动画,可以在调用Model.fromGltf后添加以下代码:

动画与Cesium的时钟系统同步化。

与其它Primitive一样,对3D模型的选取也是被支持的,当前点击的glTF node id、glTF mess一并被获取:

栅格图层

Cesium支持多种标准化格式的GIS瓦片服务,可以把栅格图层绘制到地球的表面。这些图层的亮度、对比度、色相均可以动态调整:

3D地形图

Cesium支持3D地形图、水体特效,下面的代码添加该特性:

需要注意的是,地形图、栅格图层是分别处理的,默认的栅格图层覆盖在地形图的上面。任何栅格图层均可与地形图搭配使用。

下面的代码可以启用光照、水体效果:

镜头

Cesium提供了以下默认鼠标行为:

  1. 单击并拖拽球体:旋转地球,镜头俯角不变
  2. 单击并拖拽空间:滚动roll、俯仰pitch镜头
  3. 右击并拖拽、中键滚动:缩放镜头
  4. 中键拖拽:沿着地表的点旋转镜头

调用camera.setView()可以设置相机的位置和方向:

Camera

相机对象表示当前镜头的位置(position)、方向(orientation)、参考坐标系(reference frame)、视见体(View Frustum)。

move*、zoom*方法用于沿着镜头的原点(orientation )或者一个给定的矢量来变换(translate)镜头的位置。移动过程中方向保持固定:direction-up-right

look*、twist*方法用于依照direction、up、right向量来旋转方向,旋转过程中位置保持不变:look-twist

rotate*方法用于依据给定的矢量来变换位置、旋转方向。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值