cesium 绘制自定义geometry、三角面

前言: 网上找了不少资料,属实少,为后来者添加多一份参考。绘制geometry,主要的还是每个顶点的位置颜色。而由于我是先从three.js做好的效果,移植到cesium的时候 发现首先连坐标轴都不对。所以如果你想得到正确的结果,你最好想确认你的顶点位置 是对的。

效果

在这里插入图片描述

所需知识(新增修改 来自2022/4/28)

考虑到仍有许多没有webgl基础的人阅读此文章
特从传进去的realPos、colors、indices 分别说明

  • realPos 位置属性
    realPos 是由经纬度加高度(绝大部分数据都是如此)通过cesium内置的Cesium.Cartesian3.fromDegrees 此API 转换而来。 是一个一维数组,在后面传入顶点时需要用缓冲数组进行处理。指定Cesium每3个数值(x , y , z)读取为一个位置。
  • colors 颜色属性
    此处代码传入RGBA , 没有设置normalize(专业名词归一化,白话就是映射 => 0 - 255 => 0.0 - 1.0)的情况,此处传入的colors 应是 浮点数。如( 1.0, 0.0,0.0, 1.0) 表示透明度为1 的红色。指定Cesium 每4 个 数值读取为一个颜色
  • indices 顶点索引
    无需做缓冲处理,cesium内部已做处理,直接传入一维数组即可

核心

省去多余的数据处理部分主要是会引起误解,核心关键在于cesium是如何生成一个几何体的。three.js 里 是通过bufferGeometry的 各个bufferattribute。而cesium是通过geometryInstance 包装geometry,geometry里相关attribute,思路其实大致一样。通过appearance 这个外观类控制顶点着色器与片元着色器。所以第一步,我们需要装配相关的顶点属性。

generateGeometry: function (realPos, __colors, __indices) {
            /**
             * 构造 几何体的 内部属性
             */
            var attributes = new Cesium.GeometryAttributes({
                position: new Cesium.GeometryAttribute({
                    componentDatatype: Cesium.ComponentDatatype.DOUBLE,
                    componentsPerAttribute: 3,
                    values: new Float64Array(realPos),
                }),
                color: new Cesium.GeometryAttribute({
                    componentDatatype: Cesium.ComponentDatatype.FLOAT,
                    componentsPerAttribute: 4,
                    values: new Float32Array(__colors),
                }),
            })

            //包围球
            var boundingSphere = Cesium.BoundingSphere.fromVertices(
                realPos,
                new Cesium.Cartesian3(0.0, 0.0, 0.0),
                3
            )
            // console.log(boundingSphere)

            // 计算顶点法向量
            var geometry = new Cesium.Geometry({
                attributes: attributes,
                indices: __indices,
                primitiveType: Cesium.PrimitiveType.TRIANGLES,
                boundingSphere: boundingSphere,
            })
            return geometry
        },
  • 需要说明的是: realPos 顾名思义, 是 世界坐标才能在cesium球体上正常的显示,同时 包围球的计算也是必须的。顶点属性应该都是一维数组。这个不清楚的话,去搜索,不再此赘述。

添加该集合体进场景

// 添加geometry 进场景
        addPrimitive: function (realPos, __colors, __indices, wire) {
            if (wire) {
                //四面体的实例
                var instance = new Cesium.GeometryInstance({
                    geometry: Cesium.GeometryPipeline.toWireframe(
                        this.generateGeometry(realPos, __colors, __indices)
                    ),
                })
            } else {
                var instance = new Cesium.GeometryInstance({
                    geometry: this.generateGeometry(
                        realPos,
                        __colors,
                        __indices
                    ),
                })
            }

            //加入场景
            this.scene.primitives.add(
                new Cesium.Primitive({
                    geometryInstances: instance,
                    appearance: new Cesium.PerInstanceColorAppearance({
                        flat: true,
                        translucent: false,
                    }),
                    asynchronous: false,
                })
            )
        },
  • 两种表现形式,wire 为true时,不给三角面填充颜色,如上图效果一致。否则填色。
  • 如果需要表现出一种阴影(高低起伏)效果,需要在返回的geometry前包装一个如 Cesium.GeometryPipeline.computeNormal(geometry),计算每个点的法向量,在外观appearance里的flat设置为false,即可。

新增(2022/6/21)

wire为false时,还需要Appearance里面flat 更改为false ,才可正常填色。不用再问我。

友情赠送

// 将经纬度高度 转换未世界坐标
        transformCartesian3Pos: function (__positions) {
            let realPos = []
            for (let i = 0, ii = __positions.length; i < ii; i += 3) {
                let position = Cesium.Cartesian3.fromDegrees(
                    __positions[i],
                    __positions[i + 1],
                    __positions[i + 2]
                )
                realPos.push(position.x, position.y, position.z)
            }
            return realPos
        },
  • 10
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
要使用Cesium绘制,您需要使用Cesium.Primitive类型。以下是一个简单的示例,演示了如何使用Cesium.Primitive绘制一个三角形: ```javascript //创建顶点数组 var positions = [ 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0 ]; //创建颜色数组 var colors = [ 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0 ]; //创建索引数组 var indices = [0, 1, 2]; //创建几何体 var geometry = new Cesium.Geometry({ attributes: { position: new Cesium.GeometryAttribute({ componentDatatype: Cesium.ComponentDatatype.DOUBLE, componentsPerAttribute: 3, values: positions }), color: new Cesium.GeometryAttribute({ componentDatatype: Cesium.ComponentDatatype.FLOAT, componentsPerAttribute: 4, values: colors }) }, indices: indices, primitiveType: Cesium.PrimitiveType.TRIANGLES }); //创建材质 var material = new Cesium.Material({ fabric: { type: 'Color', uniforms: { color: new Cesium.Color(1.0, 1.0, 1.0, 1.0) } } }); //创建渲染参数 var renderState = Cesium.RenderState.fromCache({ depthTest: { enabled: true }, depthMask: true, blending: Cesium.BlendingState.ALPHA_BLEND }); //创建几何体实例 var primitive = new Cesium.Primitive({ geometryInstances: new Cesium.GeometryInstance({ geometry: geometry, modelMatrix: Cesium.Matrix4.IDENTITY, attributes: { color: colors }, id: 'triangle' }), appearance: new Cesium.PerInstanceColorAppearance({ flat: true }), material: material, renderState: renderState }); //将几何体添加到场景中 viewer.scene.primitives.add(primitive); ``` 在上的示例中,我们创建了一个三角形的顶点、颜色和索引数组。然后,我们使用这些数组创建了一个Cesium.Geometry实例。接下来,我们创建了一个Cesium.Material实例和一个渲染参数Cesium.RenderState实例。最后,我们将Cesium.Geometry实例和Cesium.Material实例一起传递给Cesium.Primitive构造函数,并将其添加到场景中。 注意,上的示例仅绘制了一个三角形,如果您需要绘制更复杂的几何体,您需要创建更复杂的顶点和索引数组。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值