Cesium intermediate tutorial 7 - Geometry and Appearances geometry and appearance

Cesium Chinese network: http://cesiumcn.org/ | domestic fast access: http://cesium.coinidea.com/

This tutorial will introduce you to use Primitive API provides the geometry and appearance of the system. This is an advanced topic for expansion has a custom mesh, shape, volume and appearance CesiumJS, Cesium-oriented instead of a generic user. If you are interested in learning how to draw a variety of shapes and volumes on the earth, see Creating entity tutorial. CesiumJS can create different types of geometric entities used (e.g., polygonal and ellipsoid). For example, the following code will copy and paste the Hello World Sandcastle example, to create a rectangular pattern having a point on the sphere:

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

In this tutorial, we'll dive under the hood to see their constituent geometry and appearance types. Primitive geometry defined structure, i.e., form a triangle, line, or point of the base body. Primitive the appearance of colored, including its full coloring sheet GLSL vertices and faces, and the rendering state.

The benefits of using geometry and appearance are:

  • Performance (performance): when drawing a large amount Primitive (U.S. ZIP code for each polygon), directly using geometry allows us to combine them into a single geometry to reduce CPU overhead and better utilization of GPU. Primitive combination is done on the Web worker, in order to maintain the responsiveness of the UI.
  • Flexibility (flexibility): Primitive combination of geometry and appearance. By separating them, we can modify each independently. We can add compatible with many different looks of the new geometry, and vice versa.
  • Low-level access (access to the lower level): Exterior rendering provides close access to the metal, used directly without worrying about Renderer all the details. The appearance of the following situations easier:
    • Write all patch vertices and GLSL shaders
    • Use custom renderer state

Of course, there are also some disadvantages:

  • Direct use of geometry and appearance requires more code and more in-depth understanding of graphics. Entity is in the level of abstraction for mapping application; abstraction level geometry and appearance closer to traditional 3D engine .
  • Geometry effective combination of static data, dynamic data may not be effective.

Let's use an initial geometry and appearance rewrite the code example:

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

We use Primitive ( Primitive ) instead of a rectangular solid, which combines geometry and appearance. Now, we will not distinguish between Geometry and GemometryInstance . Instances are instances geometry, which is more containers.

To create a rectangular geometry, i.e. rectangular area and a triangular cover for spherical curvature triangle, we created a a RectangleGeometry .

Because it is on the surface, so we can use EllipsoidSurfaceAppearance . This is on the surface or at a constant height above the ellipsoid to save memory by assuming geometry.

Geometry types geometry types

CesiumJS following geometry:

A combination of geometric shapes

When we use a Primitive drawing more static geometry, we see a performance advantage. For example, drawing a Primitive in the two rectangles.

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

We create another instance of a different rectangle, and then the two examples provided to the Primitive. This will draw the same appearance as two examples.

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

Reference documents:

For more material please visit: Fabric more future plans, please visit: the Geometry and Appearances Roadmap

Cesium Chinese net exchange QQ group: 807 482 793

This article from the admin creation, using the Creative Commons Attribution 3.0 China Mainland License Agreement for licensing. It can be freely reproduced, quoted with named authors and indicate the source of the article.

Cesium Chinese net exchange QQ group: 807 482 793

Cesium Chinese network: http://cesiumcn.org/ | domestic fast access: http://cesium.coinidea.com/

Reproduced in: https: //my.oschina.net/u/1470240/blog/3057398

Guess you like

Origin blog.csdn.net/weixin_34198762/article/details/92129850