Bootstrap

重读Cesium(五):Primitive相关介绍(一)

在Cesium中, EntityPrimitive 两个接口是用于绘制几何图形的重要接口,我们在平时开发中会经常调用。

今天我们就来详细了解一下Primitive接口。

PS:当然后续也会聊一聊 DrawCommand 这个接口。

1.Entity与Primitive

这里会有一个疑问,为什么要有两套绘制图形的接口呢?

Entity
是Cesium封装的较高级的绘图接口,适用于普通的开发人员,即使你没有图形开发技术,你能快速使用Entity在场景中绘制各种几何形状。

Primitive
是Cesium封装的低级的绘图接口,它的绘图方式接近渲染引擎底层,但又可以不直接使用WebGL底层的接口,主要面向图形开发人员。

这里也就意味着使用Primitive进行图形绘制时需要具备一定的图形相关开发知识。

2.Primitive的构成


const circle = new Cesium.CircleGeometry({
      center: Cesium.Cartesian3.fromDegrees(110.0, 30.0, 500),
      radius: 200.0
  });
  const geometry = Cesium.CircleGeometry.createGeometry(circle); 
  const instance = new Cesium.GeometryInstance({
      geometry: geometry, 
  });
  viewer.scene.primitives.add(new Cesium.Primitive({
      geometryInstances: instance,
      appearance: new Cesium.MaterialAppearance({
          material: new Cesium.Material({
              fabric: {
                  type: "Color",
                  uniforms: {
                      color: Cesium.Color.BLUE
                  }
              }
          })
      })
  }));

上面的实例是使用Primitive创建圆并渲染到场景中,通过这个实例我们发现创建一个Primitive必须设置 geometry 与 appear
ance 两个属性,才能在场景中渲染出来。

3.Geometry与Appearance

geometry : 代表要显示的几何形状。

appear ance : 代表该几何的外观样式。

即 geometry 形成一个骨架, appear ance 表示对 geometry 上色。

一个Primitive中可以包含多个Geometry,但是只能有一个Appearance

比如下方的案例代码:


let p = [110.0, 30.0];
    let instances = [];
    for (let i = 0; i < 10; i++) {
        const instance = new Cesium.GeometryInstance({
            geometry: new Cesium.EllipseGeometry({
                center: Cesium.Cartesian3.fromDegrees(p[0], p[1]),
                semiMinorAxis: 2000.0,
                semiMajorAxis: 2000.0,
                height:1000*i
            })
        });
        instances.push(instance);
    }
    viewer.scene.primitives.add(new Cesium.Primitive({
        geometryInstances: instances,
        appearance: new Cesium.EllipsoidSurfaceAppearance({
            material: Cesium.Material.fromType('Color')
        })
    }));

每个Geometry是通过GeometryInstance来进行实例化的,通过GeometryInstance对Geometry进行实例化,同一个Geometry可以被实例化多次。
这对于展示大量数
据时很有用,比如有10万个BoxGeometry需要被显示,我们只需要创建一个BoxGeometry,然后通过GeometryInstance来设置每一个的大小、位置、颜色等。



let p = [110.0, 30.0];
    let instances = [];
    let boxGeometry = Cesium.BoxGeometry.fromDimensions({
            dimensions: new Cesium.Cartesian3(100, 100, 100)
        })
    for (let i = 0; i < 100000; i++) { 
        const instance = new Cesium.GeometryInstance({
            geometry: boxGeometry,
            modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(p[0] + Math.random() , p[1] + Math.random()  , 200+Math.random()*100))//通过modelMatrix设置不同的位置
        });
        instances.push(instance);
    }
    viewer.scene.primitives.add(new Cesium.Primitive({
        geometryInstances: instances,
        appearance: new Cesium.EllipsoidSurfaceAppearance({
            material: Cesium.Material.fromType('Color')
        })
    }));

我们还可以通过对GeometryInstance设置一些属性来进行Geometry的识别,当一个Primitive中装载有多个Geometry时,我们在鼠标交互的时候如果希望知道拾取到
的是那个Geometry,那么就可以通过GeometryInstance设置一个id,这样我们就知道拾取到的是哪个Geometry。


let p = [110.0, 30.0];
      let instances = [];
      let boxGeometry = Cesium.BoxGeometry.fromDimensions({
        dimensions: new Cesium.Cartesian3(100, 100, 100)
      })
      for (let i = 0; i < 100000; i++) {
        const instance = new Cesium.GeometryInstance({
          geometry: boxGeometry,
          modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(p[0] + Math.random(), p[1] + Math.random(), 200 + Math.random() * 100)),
          id: "BoxGeometry" + i
        });
        instances.push(instance);
      }
      viewer.scene.primitives.add(new Cesium.Primitive({
        geometryInstances: instances,
        appearance: new Cesium.EllipsoidSurfaceAppearance({
          material: Cesium.Material.fromType('Color')
        })
      }));
      new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas).setInputAction(e => {
        let pick = viewer.scene.pick(e.position);
        console.log(pick);
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

需要注意的是,因为一个Primitive只能设置一个Appearance,所以当一个Primitive装载有多个Geometry时,这些Geometry只能具有相同的外观。我们可以通过PerInstanceColorAppearance类型的外观为每个Geometry实例设置一个颜色。


let p = [110.0, 30.0];
      let instances = [];
      let boxGeometry = Cesium.BoxGeometry.fromDimensions({
        dimensions: new Cesium.Cartesian3(100, 100, 100)
      })
      for (let i = 0; i < 100000; i++) {
        const instance = new Cesium.GeometryInstance({
          geometry: boxGeometry,
          modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(p[0] + Math.random() / 10, p[1] + Math.random() / 10, 200 + Math.random() * 100)),
          id:"BoxGeometry" + i,
          attributes: {
            color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.fromRandom({ alpha: 1 }))
          }
        });
        instances.push(instance);
      }
      viewer.scene.primitives.add(new Cesium.Primitive({
        geometryInstances: instances,
        appearance: new Cesium.PerInstanceColorAppearance({
          flat: true,
          translucent: false
        })
      }));

4.Primitive的优缺点

优点: 1.灵活度高,因为Primitive由Geometry和Appearance构成,我们可以单独修改它们。

2.性能好。使用Primitive可以将多个Geometry合并为一个大的Geometry来减少CPU的使用,利用GPU。

3.自定义渲染强,我们有很大的可编程性。可以操作顶点着色器与片元着色器。

缺点:

1.对于动态数据不友好,使用primitive组合多个geometry时无法更新geometry。

2.使用复杂。编写代码增加,需要图形学知识。

大家可以使用Entity与Primitive分别去创建100万条数据进行性能测试,对下对比,会发现使用Primitive创建图形编写代码会比Entity方式编写代码量多很多。但是Primitive与Entity渲染出来的效果会相差更多,帧率也会相差很大。

5.Primitive的分类

Cesium中除了Primitive类以外,还有一些以Primitive结尾的类。

1. new Cesium.GroundPrimitive (options)

贴地Primitive,将几何图形贴地使用。适用于平面类型的Geometry,如:CircleGeometry,PolygonGeometry,RectangleGeometry。

贴地Primitive通过设置 classificationType 来设置贴的目标。

2. new Cesium.ClassificationPrimitive (options)

分类Primitive,将几何体贴模型高亮显示,常用于高亮显示模型。比如倾斜摄影分层单体化或者分户单体化。

3 . new Cesium.GroundPolylinePrimitive (options)

贴地线Primitive

4. new Cesium.PointPrimitive ()

通过调用PointPrimitiveCollection#add创建点并设置其初始属性。 不要直接调用构造函数。

5. new Cesium.PointPrimitiveCollection (options)

点集合

6 . new Cesium.VoxelPrimitive (options)

体渲染

7 . new Cesium.DebugCameraPrimitive (options)

相机可视化Primitive,常用于调试相机的相关参数,这个后面涉及到折射反射等功能。

6.Primitive的几何类型

Geomtry常用的一共有12中类型,每一种类型都有对应的边线模型的Geometry。

;