我們先直接來看一個例子
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
垂直於表面的折線,寬度以米爲單位,可選擇擠壓高度
CorridorOutlineGeometry
CylinderGeometry
圓柱體,圓錐體或截錐體
CylinderOutlineGeometry
EllipseGeometry
橢圓或擠出橢圓
EllipseOutlineGeometry
EllipsoidGeometry
橢圓形
EllipsoidOutlineGeometry
RectangleGeometry
矩形或擠壓矩形
RectangleOutlineGeometry
PolygonGeometry
具有可選孔或擠出多邊形的多邊形
PolygonOutlineGeometry
PolylineGeometry
一組寬度爲像素的線段
SimplePolylineGeometry
PolylineVolumeGeometry
沿着折線擠壓的2D形狀
PolylineVolumeOutlineGeometry
SphereGeometry
一個球體
SphereOutlineGeometry
WallGeometry
垂直於地球的牆壁
WallOutlineGeometry
外觀
描述
MaterialAppearance
外觀與所有幾何類型一起使用,並支持材料描述陰影。
EllipsoidSurfaceAppearance
幾何像幾何平行於地球表面的“Material Appearance”一樣,就像一個多邊形,並且使用這個假設來通過程序上計算許多頂點屬性來節省內存。
PerInstanceColorAppearance
使用每個實例的顏色來遮蔽每個實例。
PolylineMaterialAppearance
支持材料遮蔽Polyline。
PolylineColorAppearance
使用每頂點或每段着色來遮蔽折線。