当前位置: 首页 > news >正文

Cesium 快速入门(八)Primitive(图元)系统深度解析

Cesium 快速入门(八)Primitive(图元)系统深度解析

看过的知识不等于学会。唯有用心总结、系统记录,并通过温故知新反复实践,才能真正掌握一二
作为一名摸爬滚打三年的前端开发,开源社区给了我饭碗,我也将所学的知识体系回馈给大家,助你少走弯路!
OpenLayers、Leaflet 快速入门 ,每周保持更新 2 个案例
Cesium 快速入门,每周保持更新 4 个案例

Cesium 快速入门(一)快速搭建项目
Cesium 快速入门(二)底图更换
Cesium 快速入门(三)Viewer:三维场景的“外壳”
Cesium 快速入门(四)相机控制完全指南
Cesium 快速入门(五)坐标系
Cesium 快速入门(六)实体类型介绍
Cesium 快速入门(七)材质详解
Cesium 快速入门(八)Primitive(图元)系统深度解析
Cesium 快速入门(九)Appearance(外观)系统深度解析
Cesium 快速入门(十) JulianDate(儒略日期)详解
Cesium 快速入门(十一)3D Tiles 大规模三维地理空间数据
Cesium 快速入门(十二)数据加载详解
Cesium 快速入门(十三)事件系统

Cesium Primitive(图元)系统深度解析

Primitive 核心概念

Primitive(图元)是 Cesium 中直接与 WebGL 交互的底层渲染单元,提供了对渲染管线的精细控制。与高层封装的 Entity API 不同,Primitive 允许开发者直接操作几何数据、着色器和渲染状态,是实现高性能复杂场景的关键技术。

Primitive 渲染流水线

Primitive 的渲染流程涉及以下关键步骤:

  1. 几何定义:创建 Geometry 描述顶点数据
  2. 实例化:通过 GeometryInstance 创建可渲染实例(支持属性差异化)
  3. 外观定义:通过 Appearance 指定渲染样式和着色器
  4. 批处理:合并相同外观的实例以减少绘制调用
  5. 渲染状态:配置 WebGL 渲染状态(深度测试、混合模式等)
  6. 绘制:提交 GPU 渲染指令

在这里插入图片描述

<template><div ref="cesiumContainer" class="container"></div>
</template><script setup>
import { ref, onMounted } from "vue";
import * as Cesium from "cesium";
const cesiumContainer = ref(null);
let viewer = null;// 天地图TOKEN
const token = "05be06461004055923091de7f3e51aa6";onMounted(() => {// 初始化Viewerviewer = new Cesium.Viewer(cesiumContainer.value, {geocoder: false, // 关闭地理编码搜索homeButton: false, // 关闭主页按钮sceneModePicker: false, // 关闭场景模式选择器baseLayerPicker: false, // 关闭底图选择器navigationHelpButton: false, // 关闭导航帮助animation: false, // 关闭动画控件timeline: false, // 关闭时间轴fullscreenButton: false, // 关闭全屏按钮baseLayer: false, // 关闭默认地图});// 清空logoviewer.cesiumWidget.creditContainer.style.display = "none";// 1. 定义几何体(矩形)const rectangleGeometry = new Cesium.RectangleGeometry({rectangle: Cesium.Rectangle.fromDegrees(116.3, 39.9, 116.5, 40.1),vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,height: 1000,});// 2. 创建几何实例(可包含实例属性)const instance = new Cesium.GeometryInstance({geometry: rectangleGeometry,id: "rectangle-instance",attributes: {color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED.withAlpha(0.7)),show: new Cesium.ShowGeometryInstanceAttribute(true),},modelMatrix: Cesium.Matrix4.IDENTITY.clone(),});// 3. 定义外观const appearance = new Cesium.PerInstanceColorAppearance({translucent: true,closed: true,});// 4. 创建Primitiveconst primitive = new Cesium.Primitive({geometryInstances: instance,appearance: appearance,asynchronous: true, // 异步加载(大场景推荐)releaseGeometryInstances: true, // 释放几何实例内存compressVertices: true, // 压缩顶点数据allowPicking: true, // 允许拾取});// 5. 添加到场景并监听状态viewer.scene.primitives.add(primitive);viewer.camera.setView({destination: Cesium.Rectangle.fromDegrees(116.3, 39.8, 116.5, 40.19),orientation: {heading: Cesium.Math.toRadians(0),pitch: Cesium.Math.toRadians(-90),roll: 0,},});initMap();
});// 加载天地图
const initMap = () => {// 以下为天地图及天地图标注加载const tiandituProvider = new Cesium.WebMapTileServiceImageryProvider({url:"http://{s}.tianditu.gov.cn/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=" +token,layer: "img",style: "default",format: "tiles",tileMatrixSetID: "w", // 天地图使用 Web 墨卡托投影(EPSG:3857),需确保 tileMatrixSetID: "w"subdomains: ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"], // 子域名maximumLevel: 18,credit: new Cesium.Credit("天地图影像"),});// 添加地理标注const labelProvider = new Cesium.WebMapTileServiceImageryProvider({url:"http://{s}.tianditu.gov.cn/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&tileMatrix={TileMatrix}&tileRow={TileRow}&tileCol={TileCol}&style=default&format=tiles&tk=" +token,layer: "img",style: "default",format: "tiles",tileMatrixSetID: "w",subdomains: ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"], // 子域名轮询maximumLevel: 18,credit: new Cesium.Credit("天地图影像"),});// 天地图影像添加到viewer实例的影像图层集合中viewer.imageryLayers.addImageryProvider(tiandituProvider);// 天地图地理标注(后添加的会覆盖前面的)viewer.imageryLayers.addImageryProvider(labelProvider);
};
</script>
<style scoped>
.container {width: 100vw;height: 100vh;
}
</style>

在这里插入图片描述

与 Entity 的核心区别

Entity 是基于 Primitive 的封装, 提供了更高级的 API, 更易用, 但性能不如 Primitive

特性PrimitiveEntity技术本质
抽象层级底层(接近 WebGL)高层(声明式 API)架构定位
性能控制完全手动控制自动优化性能管理
内存占用低(直接管理)中(额外封装开销)资源消耗
动态更新复杂(需重建或更新缓冲区)简单(属性直接修改)交互灵活性
学习曲线陡峭(需了解 WebGL 概念)平缓(面向业务逻辑)开发门槛
适用规模大规模静态数据(10 万+对象)中小规模动态对象(1 万以下)数据量级

核心配置项

  1. geometryInstances - 几何实例 官网

    • 单个实例:直接传递一个 GeometryInstance 对象

    • 多个实例:使用数组传递多个 GeometryInstance 对象

    • 性能技巧:相同外观的几何实例应放在同一个 Primitive 中

  2. appearance - 外观控制

    • 定义渲染样式(材质、着色器等)
const primitive = new Cesium.Primitive({// 必需:几何实例(单个或多个)geometryInstances: [geometryInstance1, geometryInstance2],// 必需:外观定义appearance: new Cesium.PerInstanceColorAppearance(),// 可选:是否异步创建(默认true)asynchronous: true,// 可选:是否释放几何实例(默认true)releaseGeometryInstances: true,// 可选:是否压缩顶点(默认true)compressVertices: true,// 可选:是否允许拾取(默认true)allowPicking: true,// 可选:模型矩阵(全局变换)modelMatrix: Cesium.Matrix4.IDENTITY.clone(),// 可选:调试显示包围盒(默认false)debugShowBoundingVolume: false,// 可选:是否始终在地平线上方(默认false)show: true,// 可选:顶点缓存优化(默认false)interleave: false,
});

添加几何形状

  1. 定义几何类型
// 创建矩形几何
const rectangle = Cesium.Rectangle.fromDegrees(-120.0, 30.0, -100.0, 40.0);
const geometry = new Cesium.RectangleGeometry({rectangle: rectangle,vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT, // 使用默认的顶点格式height: 10000,
});
  1. 创建几何实例
const instance = new Cesium.GeometryInstance({geometry: geometry,attributes: {color: new Cesium.ColorGeometryInstanceAttribute(1.0, 0.0, 0.0, 0.5),},
});
  1. 定义外观,这里的material可以选择材质类型
const appearance = new Cesium.EllipsoidSurfaceAppearance({// 材质定义,checkerboard 是一个内置的材质类型,用于创建棋盘格效果material: Cesium.Material.fromType("Checkerboard", {evenColor: Cesium.Color.WHITE,oddColor: Cesium.Color.BLUE,repeat: new Cesium.Cartesian2(10, 10),}),aboveGround: true,
});
  1. 创建 Primitive
const primitive = new Cesium.Primitive({geometryInstances: [instance],appearance: appearance,releaseGeometryInstances: false,compressVertices: true, // 顶点压缩优化
});viewer.scene.primitives.add(primitive);
viewer.camera.flyTo({destination: rectangle,orientation: {heading: Cesium.Math.toRadians(0),pitch: Cesium.Math.toRadians(-90),roll: 0,},
});

在这里插入图片描述

GeometryInstance 详解

创建 GeometryInstance

const geometryInstance = new Cesium.GeometryInstance({geometry: new Cesium.RectangleGeometry({// 几何体定义rectangle: Cesium.Rectangle.fromDegrees(-110.0, 20.0, -100.0, 30.0),vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,}),attributes: {// 实例属性color: new Cesium.ColorGeometryInstanceAttribute(1.0, 0.0, 0.0, 0.5),},modelMatrix: Cesium.Matrix4.IDENTITY.clone(), // 模型矩阵id: "rectangle-instance", // 唯一标识符
});

几何体属性 (Attributes)

attributes: {// 颜色属性 (RGBA)color: new Cesium.ColorGeometryInstanceAttribute(red, green, blue, alpha),// 是否显示show: new Cesium.ShowGeometryInstanceAttribute(true),// 距离显示属性distanceDisplayCondition: new Cesium.DistanceDisplayConditionGeometryInstanceAttribute(nearDistance, farDistance)
}

模型变换 (ModelMatrix)

// 创建平移矩阵
const translation = new Cesium.Cartesian3(10000, 0, 0);
const modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(-105.0, 40.0, 1000),Cesium.Ellipsoid.WGS84,new Cesium.Matrix4()
);
Cesium.Matrix4.multiplyByTranslation(modelMatrix, translation, modelMatrix);// 创建旋转矩阵
const rotation = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(45));
Cesium.Matrix4.multiplyByMatrix3(modelMatrix, rotation, modelMatrix);

Geometry 类型大全

基础几何类型

几何类型描述典型应用
BoxGeometry3D 长方体建筑、立方体
CylinderGeometry圆柱体柱状物、树木
EllipsoidGeometry椭球体行星、球体
SphereGeometry完美球体标记点、气泡
PolylineGeometry折线路径、边界
PolygonGeometry多边形区域、地块
RectangleGeometry矩形地图瓦片、区域

地表几何类型

几何类型描述典型应用
WallGeometry垂直墙围栏、堤坝
PolylineVolumeGeometry体积折线管道、道路
CorridorGeometry走廊河流、通道
EllipseGeometry椭圆圆形区域
CircleGeometry正圆范围圈、影响区

高级几何类型

几何类型描述典型应用
FrustumGeometry视锥体相机视野
GroundPolylineGeometry地表折线贴合地面的路径
CoplanarPolygonGeometry共面多边形复杂平面图形

创建 BoxGeometry

// 1. 定义盒子中心位置(WGS84坐标)
const center = Cesium.Cartesian3.fromDegrees(116.39, 39.9, 1000);// 2. 定义盒子尺寸(单位:米)
const boxSize = new Cesium.Cartesian3(500.0, 800.0, 300.0); // 长(x)、宽(y)、高(z)// 3. 计算最小和最大点(以中心为原点)
const halfSize = Cesium.Cartesian3.multiplyByScalar(boxSize,0.5,new Cesium.Cartesian3()
);
const minimum = Cesium.Cartesian3.negate(halfSize, new Cesium.Cartesian3());
const maximum = halfSize;// 4. 创建盒子几何体(使用正确的参数)
const boxGeometry = new Cesium.BoxGeometry({vertexFormat: Cesium.VertexFormat.POSITION_AND_NORMAL, // 包含法线信息(用于光照)minimum: minimum,maximum: maximum,
});// 5. 创建模型矩阵(包含位置和方向)
const modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(center);// 6. 创建几何实例
const instance = new Cesium.GeometryInstance({geometry: boxGeometry,modelMatrix: modelMatrix,id: "custom-box", // 可选ID,用于拾取识别attributes: {color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED.withAlpha(0.7)), // 带透明度},
});// 7. 创建Primitive并添加到场景
const boxPrimitive = new Cesium.Primitive({geometryInstances: instance,appearance: new Cesium.PerInstanceColorAppearance({closed: true, // 封闭几何体(盒子必须封闭)translucent: true, // 启用透明度}),asynchronous: false, // 同步加载(小几何体适用)
});viewer.scene.primitives.add(boxPrimitive);// 8. 视角定位
viewer.camera.flyTo({destination: center,offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-45), 2000),
});

销毁流程

  1. remove(boxPrimitive)从场景中移除
// 从场景中移除
viewer.scene.primitives.remove(boxPrimitive);
// 检查是否销毁
console.log(boxPrimitive.isDestroyed()); // true
  1. destroy()显式销毁,一旦对象被销毁,就不应该使用它;调用 isDestroyed 将导致 DeveloperError 异常,DeveloperError : This object was destroyed, i.e., destroy() was called.
// 显式销毁
boxPrimitive = boxPrimitive && boxPrimitive.destroy();

海量数据渲染

例举集中大量数据渲染集合,更多信息可参考PrimitiveCollection

数据类型典型应用性能关键点推荐结构
BillboardCollectionPOI 点、图标 纹理合并、批次渲染单集合 10 万+图标
PointPrimitiveCollection纯色点(无纹理)顶点着色器渲染单集合 100 万+点
PolylineCollection路径、轨迹批次渲染单集合 10 万+路径
LabelCollection文本标签、标注字体纹理合并单集合 10 万+标签
// 添加大量广告牌集合
const billboardCollection = viewer.scene.primitives.add(new Cesium.BillboardCollection()
);
for (let i = 0; i < 10000; i++) {billboardCollection.add({position: Cesium.Cartesian3.fromDegrees(Math.random() * 360 - 180, // 经度Math.random() * 180 - 90, // 纬度50),image: "/src/assets/vue.svg", // 替换为实际图片路径width: 32,height: 32,// scaleByDistance: new Cesium.NearFarScalar(10000, 1.0, 100000, 0.1), // 按距离缩放:避免远处图标浪费像素});
}

在这里插入图片描述

加载模型

const position = Cesium.Cartesian3.fromDegrees(116.3975, 39.9075, 500);
const headingPositionRoll = new Cesium.HeadingPitchRoll();
const fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator("north","west"
);
try {let animations;const model = await Cesium.Model.fromGltfAsync({url: new URL("./models/Cesium_Air.glb", import.meta.url).href,modelMatrix: Cesium.Transforms.headingPitchRollToFixedFrame(position,headingPositionRoll,Cesium.Ellipsoid.WGS84,fixedFrameTransform),gltfCallback: (gltf) => {animations = gltf.animations;},minimumPixelSize: 128, // 最小像素大小scale: 2.0, // 模型缩放比例});viewer.scene.primitives.add(model);viewer.camera.setView({destination: Cesium.Cartesian3.fromDegrees(116.3975, 39.9075, 550),orientation: {heading: Cesium.Math.toRadians(180),pitch: Cesium.Math.toRadians(-80),roll: 0,},});viewer.clock.shouldAnimate = true;// 播放模型的动画model.readyEvent.addEventListener(() => {model.activeAnimations.add({index: animations.length - 1,loop: Cesium.ModelAnimationLoop.REPEAT,multiplier: 0.5,});});
} catch (error) {console.log(`Failed to load model. ${error}`);
}
http://www.dtcms.com/a/307360.html

相关文章:

  • Web开发-PHP应用Cookie脆弱Session固定Token唯一身份验证数据库通讯
  • uniapp 3d模型预览组件 用于3d模型预览 工业配件展示 组件地址
  • 智慧园区系统:未来办公生活的新蓝图
  • 抓大鹅小游戏微信抖音流量主小程序开源
  • ros2--参数指令--rqt
  • iOS软件性能监控实战指南 开发到上线的完整流程解析
  • 在Linux中创建LVGL应用
  • 将开发的软件安装到手机:环境配置、android studio设置、命令行操作
  • #C语言——刷题攻略:牛客编程入门训练(一):简单输出、基本类型
  • 进程控制:从创建到终结的完整指南
  • 云计算一阶段Ⅱ——3. Linux 计划任务管理
  • Flutter兼容的iOS的最低版本号
  • USRP捕获手机/路由器数据传输信号波形(中)
  • 小杰数据结构(three day)——静以修身,俭以养德。
  • 报错:selenium.common.exceptions.ElementNotInteractableException: Message
  • 机器学习第二课之逻辑回归(一)LogisticRegression
  • viso 搜索形状无匹配 解决方案 viso2021下载
  • 【刷题】东方博宜oj 1412-快速幂(零基础,简单易懂)
  • H.266 vs H.265/AV1/H.264:从工程落地看下一代视频系统的技术演进
  • AR智能巡检:工业4.0时代的降本增效利器
  • Spring AI MCP 技术从使用到项目实战深度解析
  • Java学习第九十一部分——OkHttp
  • 8K、AI、低空智联,H.266能否撑起下一代视频通路?
  • Dify插件安装失败,一直处于安装状态?
  • 医保购药系统源码拆解:前后端架构、数据库设计与安全机制全览
  • 搭建文件共享服务器samba————附带详细步骤
  • SpringBoot+SpringAI打造智能对话机器人
  • 力扣46:全排列
  • k8s-master03加入集群失败解决方法之一
  • Table-Render:基于 JSON Schema 的高性能 React 动态表格渲染器