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
        },
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值