我们先直接来看一个例子
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使用每顶点或每段着色来遮蔽折线。
参考资料:官方文档