Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/

本教程将向您介绍提供使用Primitive API的几何图形和外观系统。这是一个高级主题,用于扩展具有自定义网格、形状、体积和外观的CesiumJS,而不是面向通用的Cesium用户。如果您有兴趣学习如何在地球上绘制各种形状和体积,请查看创建实体教程。

CesiumJS可以使用实体(如多边形和椭圆体)创建不同的几何类型。例如,将以下代码复制并粘贴到Hello World Sandcastle示例中,以在球体上创建具有点模式的矩形:

var viewer = new Cesium.Viewer('cesiumContainer');

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
})
}
});

在本教程中,我们将深入到遮光罩下,查看构成它们的几何图形和外观类型。几何图形定义了Primitive结构,即构成基本体的三角形、线或点。外观定义了Primitive的着色,包括其完整的GLSL顶点和面片着色,以及渲染状态。

使用几何图形和外观的好处是:

  • Performance(性能):在绘制大量Primitive(如美国每个邮政编码的多边形)时,使用几何图形直接允许我们将它们组合成单个几何图形,以减少CPU开销并更好地利用GPU。组合Primitive是在Web worker上完成的,以保持UI的响应性。
  • Flexibility(灵活):Primitive结合了几何图形和外观。通过分离它们,我们可以独立地修改每一个。我们可以添加与许多不同外观兼容的新几何图形,反之亦然。
  • Low-level access(低层级访问):外观提供接近金属的渲染访问,无需担心直接使用Renderer的所有细节。外观使下列情况变得容易:
    • 写所有GLSL的顶点和面片着色器
    • 使用自定义渲染状态

当然也会有一些缺点:

  • 直接使用几何图形和外观需要更多的代码和对图形更深入的理解。实体处于适合映射应用程序的抽象级别;几何图形和外观的抽象级别更接近于传统的3D引擎
  • 组合几何图形对静态数据有效,对动态数据不一定有效。

让我们使用几何图形和外观重写初始代码示例:

var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene; // original code
//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 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')
})
}));

我们使用Primitive(Primitive)代替矩形实体,它结合了几何图形和外观。现在,我们将不区分GeometryGemometryInstance。实例不仅是几何图形的实例,更是其的容器。

为了创建矩形的几何图形,即覆盖矩形区域的三角形和适合球体曲率的三角形,我们创建了一个RectangleGeometry

因为它在表面上,所以我们可以使用EllipsoidSurfaceAppearance。这通过假设几何图形在曲面上或在椭球体上方的恒定高度来节省内存。

Geometry types 几何图形类型

CesiumJS提供下列几何图形:

组合几何图形

当我们使用一个Primitive绘制多个静态几何图形时,我们看到了性能优势。例如,在一个Primitive中绘制两个矩形。

 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')
})
}));

我们用不同的矩形创建了另一个实例,然后将这两个实例提供给Primitive。这将以相同的外观绘制两个实例。

有些外观允许每个实例提供唯一的属性。例如,我们可以使用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()
}));

每个实例都有一个颜色属性。Primitive是用PerinstanceColorAppearance构造的,它使用每个实例的颜色属性来确定着色。

组合几何图形可以使CesiumJS有效地绘制许多几何图形。下面的示例绘制2592个颜色独特的矩形。

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()
}));

Picking 拾取

实例合并后可以独立访问。为实例分配一个ID,并使用它来确定是否使用Scene.Pick拾取该实例。

下面的示例创建一个带id的实例,并在单击该实例时将消息写入控制台。

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, 30.0, -90.0, 40.0),
vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
}),
id : 'my rectangle',
attributes : {
color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
}
}); scene.primitives.add(new Cesium.Primitive({
geometryInstances : instance,
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) && (pick.id === 'my rectangle')) {
console.log('Mouse clicked rectangle.');
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

使用id避免了在内存中,在Primitive构造之后,对整个实例的引用,包括几何图形。

Geometry instances 几何实例

实例可用于在场景的不同部分定位、缩放和旋转相同的几何体。这是可能的,因为多个实例可以引用相同的Geometry,并且每个实例可以具有不同的modelMatrix。这允许我们只计算一次几何图形,并多次重复使用它。

以下示例创建一个EllipsoidGeometry和两个实例。每个实例引用相同的椭球几何体,但使用不同的modelMatrix放置它,导致一个椭球位于另一个椭球之上。

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
})
}));

Updating per-instance attributes 更新实例属性

将几何图形添加到Primitive后,更新几何图形的每个实例属性以更改可视化效果。每个实例的属性包括:

  • Color: ColorGeometryInstanceAttribute决定了颜色实例。Primitive必须具有PerInstanceColorAppearance。
  • Show:boolean类型决定实例是否可见。所有实例都具有该属性。

下列展示了如何改变几何实例的颜色:

var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene; var circleInstance = new Cesium.GeometryInstance({
geometry : new Cesium.CircleGeometry({
center : Cesium.Cartesian3.fromDegrees(-95.0, 43.0),
radius : 250000.0,
vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
}),
attributes : {
color : Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 0.0, 0.0, 0.5))
},
id: 'circle'
});
var primitive = new Cesium.Primitive({
geometryInstances : circleInstance,
appearance : new Cesium.PerInstanceColorAppearance({
translucent : false,
closed : true
})
});
scene.primitives.add(primitive); setInterval(function() {
var attributes = primitive.getGeometryInstanceAttributes('circle');
attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue(Cesium.Color.fromRandom({alpha : 1.0}));
},2000);

几何图形实例的属性可以被primitive使用primitive.getGeometryInstanceAttributes检索。attirbutes的属性可以直接被改变。

外观

几何定义结构。primitive的另一个关键属性,appearance,定义了primitive的纹理,即单个像素的颜色。primitive可以有多个几何实例,但只能有一个外观。根据外观的类型,外观将具有定义着色的主体的material

CesiumJS具有下列外观:

外观定义了绘制Primitive时在GPU上执行的完整GLSL顶点和面片着色器。外观还定义了完整的渲染状态,它控制绘制primitvie时GPU的状态。我们可以直接定义渲染状态,也可以使用更高级的属性,如“闭合(closed)”和“半透明(translucent)”,外观将转换为渲染状态。例如:

// Perhaps for an opaque box that the viewer will not enter.
// - Backface culled and depth tested. No blending. var appearance = new Cesium.PerInstanceColorAppearance({
translucent : false,
closed : true
}); // This appearance is the same as above
var anotherAppearance = new Cesium.PerInstanceColorAppearance({
renderState : {
depthTest : {
enabled : true
},
cull : {
enabled : true,
face : Cesium.CullFace.BACK
}
}
});

创建外观后,不能更改其renderState属性,但可以更改其material。我们还可以更改primitive的appearnace属性。

大多数外观还具有flatfaceForward属性,这些属性间接控制GLSL着色器。

  • flat:平面阴影。不要考虑照明。
  • faceForward:照明时,翻转法线,使其始终面向观众。回避背面的黑色区域,例如墙的内侧。

Geometry and appearance compatibility 几何图形和外观兼容

并非所有外观都适用于所有几何图形。例如,EllipsoidSurfaceAppearance外观不适用于WallGeometry几何图形,因为墙不在球体的表面上。

要使外观与几何图形兼容,它们必须具有匹配的顶点格式,这意味着几何图形必须具有外观所期待的输入数据。创建几何图形时可以提供vertexFormat

几何图形的vertexFormat确定它是否可以与其他几何图形组合。两个几何图形不必是相同的类型,但它们需要匹配的顶点格式。

为方便起见,外观要么具有vertexFormat属性,要么具有可作为几何体选项传入的VERTEX_FORMAT静态常量。

var geometry = new Ceisum.RectangleGeometry({
vertexFormat : Ceisum.EllipsoidSurfaceAppearance.VERTEX_FORMAT
// ...
}); var geometry2 = new Ceisum.RectangleGeometry({
vertexFormat : Ceisum.PerInstanceColorAppearance.VERTEX_FORMAT
// ...
}); var appearance = new Ceisum.MaterialAppearance(/* ... */);
var geometry3 = new Ceisum.RectangleGeometry({
vertexFormat : appearance.vertexFormat
// ...
});

Resources 资源

参考文档:

更多材料请访问:Fabric

更多未来计划,请访问:Geometry and Appearances Roadmap

Cesium中文网交流QQ群:807482793

Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/

Cesium中级教程7 - Geometry and Appearances 几何图形和外观的更多相关文章

  1. Cesium中级教程4 - 空间数据可视化(二)

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ Viewer中的Entity功能 让我们看看Viewer为操作e ...

  2. Cesium中级教程10 - CesiumJS and webpack

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ webpack是打包JavaScript模块流行且强大的工具.它 ...

  3. Cesium中级教程6 - 3D Models 三维模型

    3D Models 三维模型 本教程将教您如何通过Primitive API转换.加载和使用Cesium中的三维模型.如果你是Cesium的新用户,可能需要阅读三维模型部分的(空间数据可视化教程)[h ...

  4. Cesium中级教程9 - Advanced Particle System Effects 高级粒子系统效应

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ 要了解粒子系统的基础知识,请参见粒子系统入门教程. Weathe ...

  5. Cesium中级教程8 - Introduction to Particle Systems 粒子系统入门

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ What is a particle system? 什么是粒子 ...

  6. Cesium中级教程5 - Terrain 地形

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ CesiumJS支持对与水流相关的海洋.湖泊和河流以及全球高分辨 ...

  7. Cesium中级教程2 - 图层

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ Cesium支持从几个标准服务绘制和添加高分辨率图像(地图)图层 ...

  8. Cesium中级教程1 - 空间数据可视化(一)

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ 本教程将教读者如何使用Cesium的实体(Entity)API绘 ...

  9. Cesium中级教程3 - Camera - 相机(摄像机)

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ Camera CesiumJS中的Camera控制场景的视图.有 ...

随机推荐

  1. 盘点 2021|「避坑宝典」为大家分享一下笔者在 2021 年所遇到“匪夷所思”的 Bug 趣事(上)

    正版内容:https://xie.infoq.cn/article/3145cd5f525fe26ce9d574c8d 2021尾声想跟大家说的话 虚则实之 引用 https://xie.infoq. ...

  2. 模块化和webpack模块化打包

    模块化和webpack模块化打包: 一.❀ 模块化 [导入import-----导出export] 1.为什么需要模块化? JavaScript 发展初期,代码简单地堆积在一起,只要能顺利地从上往下一 ...

  3. 【LeetCode】443. String Compression 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 使用额外空间 不使用额外空间 日期 题目地址:htt ...

  4. 【LeetCode】357. Count Numbers with Unique Digits 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  5. 【LeetCode】491. Increasing Subsequences 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  6. Game(hdu5218)

    Game  Accepts: 138  Submissions: 358  Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: 131072/1 ...

  7. Docker 与 K8S学习笔记(五)—— 容器的操作(上篇)

    上一篇我们介绍了Dockerfile的基本编写方法,这一节我们来看看Docker容器的常用操作. 一.容器的运行方式 容器有两种运行方式,即daemon形式运行与非daemon形式运行,通俗地讲就是长 ...

  8. Chapter 15 Outcome Regression and Propensity Scores

    目录 15.1 Outcome regression 15.2 Propensity scores 15.3 Propensity stratification and standardization ...

  9. Android物联网应用程序开发(智慧园区)—— 登录界面开发

    效果: 布局代码: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:an ...

  10. MySQL高级查询与编程作业目录 (作业笔记)

    MySQL高级查询与编程笔记 • [目录] 第1章 数据库设计原理与实战 >>> 第2章 数据定义和操作 >>> 2.1.4 使用 DDL 语句分别创建仓库表.供应 ...