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

cesium系列篇:Entity vs Primitive 源码解析(从Entity到Primitive)02

上篇文章中,我们介绍了使用viewer.entities.add添加entity之后的信号传递以及最后entity对象被传递到GeometryVisualizer

这篇文章,我们则介绍如何在逐帧渲染的过程中根据GeometryVisualizer中的entity对象创建相应的primitive

这是下文中涉及到的类的类图,从中可以清晰的了解各个对象之间的关系,下面我们结合代码来仔细讲解。

在这里插入图片描述

循环的一帧

我们先看下viewer初始化的时候做了什么,在何处定义了每一帧的循环,并持续的进行渲染,结合时序图(见第三节)和源码,可以将其分为两个部分

Viewer初始化

  1. viewer初始化并创建clock
function Viewer(container, options){let clock;let clockViewModel;let destroyClockViewModel = false;if (defined(options.clockViewModel)) {clockViewModel = options.clockViewModel;clock = clockViewModel.clock;} else {clock = new Clock();clockViewModel = new ClockViewModel(clock);destroyClockViewModel = true;}
}
  1. clock作为参数之一创建cesiumWidget
// 省略其他参数
const cesiumWidget = new CesiumWidget(cesiumWidgetContainer, {clock: clock});
  1. 添加监听事件,建立事件响应,其效果我们在后面再具体描述
eventHelper.add(clock.onTick, Viewer.prototype._onTick, this);

cesiumWidget初始化

  1. 在构造函数中设置渲染循环策略this.useDefaultRenderLoop
this._useDefaultRenderLoop = undefined;
this.useDefaultRenderLoop = defaultValue(options.useDefaultRenderLoop,true
);

结合useDefaultRenderLoopset函数可知其实是调用了startRenderLoop函数

useDefaultRenderLoop: {get: function () {return this._useDefaultRenderLoop;},set: function (value) {if (this._useDefaultRenderLoop !== value) {this._useDefaultRenderLoop = value;if (value && !this._renderLoopRunning) {startRenderLoop(this);}}},
}
  1. startRenderLoop中定义了render函数并每一帧进行调用
function startRenderLoop(widget) {widget._renderLoopRunning = true;let lastFrameTime = 0;function render(frameTime) {// 此处省略细节widget.render();requestAnimationFrame(render);}requestAnimationFrame(render);
}
  1. render函数中起实际作用的是函数widget.render,其内部通过调用this._clock.tick()发出信号,结合上一节viewer初始化中提到的事件监听的建立可以知道,进行响应的是Viewer.prototype._onTick函数
CesiumWidget.prototype.render = function () {if (this._canRender) {this._scene.initializeFrame();const currentTime = this._clock.tick();this._scene.render(currentTime);} else {this._clock.tick();}
};Clock.prototype.tick = function () {this.onTick.raiseEvent(this);return currentTime;
};
  1. Viewer.prototype._onTick函数中,会通过调用函数this._dataSourceDisplay.update(time)进行实际的primitive对象的创建
Viewer.prototype._onTick = function (clock) {const isUpdated = this._dataSourceDisplay.update(time);
};

时序图

  • 这里我们附上整个过程的时序图,帮助大家更好的了解整个过程
    [图片]

生成Primitive

通过上面的描述,我们知道了cesium的每一帧是如何更新的,以及其通过调用this._dataSourceDisplay.update(time)进行primitive的创建,下面我们就探究下具体的创建过程

  1. update中,获取了this._defaultDataSource_visualizers属性,通过上一篇文章我们知道,其是一个包含了GeometryVisualizer等多个Visualizer的列表,其中GeometryVisualizer是后续创建polygon对应primitive的类

    DataSourceDisplay.prototype.update = function (time) {visualizers = this._defaultDataSource._visualizers;vLength = visualizers.length;for (x = 0; x < vLength; x++) {result = visualizers[x].update(time) && result;}return result;
    };
    

    [图片]

  2. GeometryVisualizerupdate函数中主要做了如下几件事:

    • 获取被添加对象,在上一篇文章中我们知道,通过_onCollectionChanged函数,将添加的entity添加到了this._addedObjects属性中

      const addedObjects = this._addedObjects;
      addedObjects.set(id, entity);
      
    • 遍历每一个被添加的对象

      • 创建UpdaterSet,其内部的updaters包含了PolygonGeometryUpdater在内的10个Updater
        [图片]

      • 通过updater尝试创建instance(后面详细介绍)

    • 移除已经被添加的对象

    • batch中创建primitive(后面详细介绍)

代码节选如下:

GeometryVisualizer.prototype.update = function (time) {// 获取被添加对象const addedObjects = this._addedObjects;const added = addedObjects.values;// 遍历每一个被添加的对象for (i = added.length - 1; i > -1; i--) {entity = added[i];id = entity.id;// 创建UpdaterSetupdaterSet = new GeometryUpdaterSet(entity, this._scene);this._updaterSets.set(id, updaterSet);// 通过每一个updater尝试创建instance 并添加到batch中updaterSet.forEach(function (updater) {that._insertUpdaterIntoBatch(time, updater);});}// 移除已经被添加的对象addedObjects.removeAll();// 在batch中创建primitivelet isUpdated = true;const batches = this._batches;const length = batches.length;for (i = 0; i < length; i++) {isUpdated = batches[i].update(time) && isUpdated;}return isUpdated;
};

生成instance

  1. 获取polygonOutline对应的instance

    • 在函数GeometryVisualizer.prototype._insertUpdaterIntoBatch中将updater传递到StaticOutlineGeometryBatch.prototype.add函数中
    this._outlineBatches[shadows].add(time, updater);
    

    在这里插入图片描述

    • StaticOutlineGeometryBatch.prototype.add先创建polygonOutline对应的instance
    const instance = updater.createOutlineGeometryInstance(time);
    
    • StaticOutlineGeometryBatch.prototype.add中,调用batch.add函数,传入instance,并写入字典this.geometry
    this.geometry.set(id, instance);
    

    在这里插入图片描述

  2. 获取polygon对应的instance

    • 同样在函数GeometryVisualizer.prototype._insertUpdaterIntoBatch中,将updater传递到StaticGeometryColorBatch.prototype.add函数中

      this._closedColorBatches[shadows].add(time, updater);
      

      [图片]

    • StaticGeometryColorBatch.prototype.add先创建polygon对应的instance

    const instance = updater.createFillGeometryInstance(time);
    
    • StaticGeometryColorBatch.prototype.add中,调用batch.add函数,传入instance,并写入字典this.geometry
    this.geometry.set(id, instance);
    

生成primitive

在循环中遍历所有的GeometryBatch对象,并update
[图片]

  1. 生成polygonOutline对应的primitive

    • 通过StaticOutlineGeometryBatch.prototype.update遍历solidBatchesLength属性,并update
      在这里插入图片描述
    • batch.update中生成primitive
      在这里插入图片描述
  2. 生成polygon对应的primitive

    • 通过StaticGeometryColorBatch.prototype.update调用updateItems函数,在其内部,遍历batchupdate
      [图片]

    • batch.update中生成primitive
      [图片]

时序图

  • 在这里我们附上整个过程的时序图,可以帮助大家更好的了解整个过程
    在这里插入图片描述

后续

  • 后面我们会进一步探索创建得到的primitive如何被渲染,并对比其和我们直接添加的primitive在组织结构上有什么区别

相关文章:

cesium系列篇:Entity vs Primitive 源码解析(从Entity到Primitive)02

上篇文章中&#xff0c;我们介绍了使用viewer.entities.add添加entity之后的信号传递以及最后entity对象被传递到GeometryVisualizer&#xff1b; 这篇文章&#xff0c;我们则介绍如何在逐帧渲染的过程中根据GeometryVisualizer中的entity对象创建相应的primitive 这是下文中…...

golang windows 环境搭建 环境配置

golang windows 环境搭建 环境配置 Golang学习之路一环境搭建 MacBook Linux 树莓派raspberrypi安装Golang环境 官网下载地址: https://go.dev/dl/ https://golang.google.cn/dl/ 下载对应系统版本&#xff0c;例如windows 64位系统&#xff0c;下载&#xff1a;xxx.window…...

【Git】06 常用场景

文章目录 前言一、场景11.1 删除分支1.2 修改message信息1.2.1 最新一次commit的message1.2.2 过去commit的message 1.3 合并commit1.3.1 多个连续commit合并1.3.2 不连续commit合并 二、场景22.1 比较暂存区和HEAD所含文件的差异2.2 比较工作区和暂存区所含文件的差异2.3 将暂…...

docker下nacos(1.2.0)的持久化

一、创建数据库 运行以下代码自动创建数据库和表 CREATE DATABASE IF NOT EXISTS nacos_config /*!40100 DEFAULT CHARACTER SET utf8 */; USE nacos_config;SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0;-- ---------------------------- -- Table structure for config_…...

Win32 SDK Gui编程系列之--弹出式菜单

1.弹出式菜单 例如,在命令提示窗口中点击鼠标右键,会出现如下图所示的弹出菜单(下拉菜单)。 这种弹出式菜单的实现很简单。不创建菜单栏,用CreatePopupMenu函数创建的菜单是最顶端的菜单就可以了。 菜单的显示使用TrackPopupMenu函数进行。 例如,点击鼠标右键显示弹出…...

VisaulStudio2022下用VB.net实现socket与西门子PLC进行通讯案例(优化版)

前言 对于电气工程师来说,不仅要会PLC,还要会上位机。 此前,我写过一个VB.net下雨西门子PLC通讯案例的博文: VisaulStudio2019下用VB.net实现socket与西门子PLC进行通讯案例 但当时很多东西都理解不深,博文也写的比较浅,但我看有不少收藏,也有些朋友在底下询问,所以,…...

npm安装命令

–save-dev   简写&#xff1a; -D 适用于各类loder , plugin&#xff0c; babel, webpack等 -save     简写 &#xff1a;-S 适用于 UI框架&#xff0c;vue等 1.npm install 包名 将包安装到 node_modules 目录&#xff0c;npm install 初始化时不会自动下载模块&#xf…...

【Git版本控制 01】基本操作

目录 一、初始配置 二、添加文件 三、查看日志 四、修改文件 五、版本回退 六、撤销修改 七、删除文件 一、初始配置 Git版本控制器&#xff1a;记录每次的修改以及版本迭代的一个管理系统。 # 初始化本地仓库&#xff1a;git init(base) [rootlocalhost gitcode]# gi…...

Spring 开发 pom.xml 配置文件(通用配置)

因为在打 jar 包时总会出现各种各样莫名其妙的问题&#xff0c;所以本篇博客提供了含有 Java8.0 &#xff0c;mybatis&#xff0c;mysql&#xff0c;lombok 以及打 jar 包的完整 pom.xml 配置文件&#xff0c;直接复制使用即可 <project xmlns"http://maven.apache.or…...

LabVIEW高精度主动模拟肺系统的开发与应用

在医疗设备的研发与测试中&#xff0c;高精度主动模拟肺系统扮演了不可或缺的角色。这种系统能够精确模拟人体的呼吸过程&#xff0c;对于呼吸机性能的测试、医疗人员的培训以及临床研究具有极其重要的意义。通过利用先进的硬件控制技术和软件算法&#xff0c;主动模拟肺系统能…...

打包 iOS 的 IPA 文件

目录 摘要 引言 准备 选择证书类型 创建应用程序 设置应用程序标识和证书 配置构建设置 构建应用程序 导出IPA 签名和导出 代码案例演示 完成 总结 参考资料 摘要 本篇博客将为您介绍如何打包iOS的IPA文件。从APP提交、创建应用程序、设置应用程序标识和证书、配…...

[Vulnhub靶机] DriftingBlues: 2

[Vulnhub靶机] DriftingBlues: 2靶机渗透思路及方法&#xff08;个人分享&#xff09; 靶机下载地址&#xff1a; https://download.vulnhub.com/driftingblues/driftingblues2.ova 靶机地址&#xff1a;192.168.67.21 攻击机地址&#xff1a;192.168.67.3 一、信息收集 1.…...

鸿蒙 WiFi 扫描流程(1)

上一篇记录了WiFi 的打开流程&#xff0c;这里我们继续看&#xff0c;WiFi使能后&#xff0c;如何发起扫描&#xff1f;代码还是用的 鸿蒙OpenHarmony4.0基线代码。 foundation/communication/wifi/wifi/services/wifi_standard/wifi_hal/wifi_hal_sta_interface.c WifiError…...

基于YOLOv8的暗光低光环境下(ExDark数据集)检测,加入多种优化方式---DCNv4结合SPPF ,助力自动驾驶(一)

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文主要内容:详细介绍了暗光低光数据集检测整个过程&#xff0c;从数据集到训练模型到结果可视化分析&#xff0c;以及如何优化提升检测性能。 &#x1f4a1;&#x1f4a1;&#x1f4a1;加入 DCNv4结合SPPF mAP0.5由原始的0.682提升至…...

(十三)springboot实战——springboot前后端分离方式项目集成spring securtity安全框架

前言 Spring Security 是一款强大且高度可定制的认证和访问控制框架&#xff0c;它是为了保护基于Spring的应用程序提供安全性支持。Spring Security提供了全面的安全服务&#xff0c;主要针对企业级应用程序的需求。其核心组件主要包含&#xff1a;Authentication&#xff08…...

XCTF:3-1[WriteUP]

从题目中获取文件 使用file命令查看文件类型 修改后缀为.rar后进行解压缩 再次使用file命令查询该文件的类型 再次修改后缀为.pcap或者.pcapng 使用wireshark打开&#xff0c;直接搜索flag字样 在多个数据包里发现了flag.rar、flag.txt等文件 尝试使用http导出文件 有一个fl…...

常用ES技巧二

文章目录 一、Object.entries()和Object.fromEntries()1.1、Object.entries()1.2、Object.fromEntries() 二、Symbol类型和Symbol属性三、WeakMap和WeakSet四、Promise.allSettled()五、BigInt六、Array.of和Array.from七、.at和.flat八、总结九、最后 一、Object.entries()和O…...

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Rating组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Rating组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Rating组件 提供在给定范围内选择评分的组件。 子组件 无。 接口 Rating(opt…...

Python进阶--爬取下载人生格言(基于格言网的Python3爬虫)

目录 一、此处需要安装第三方库: 二、抓包分析及Python代码 1、打开人生格言网&#xff08;人生格言-人生格言大全_格言网&#xff09;进行抓包分析 2、请求模块的代码 3、抓包分析人生格言界面 4、获取目录页中各种类型的人生格言链接 5、获取下一页的链接 5、获取人生…...

FastAdmin

PHP 推荐链接FastAdmin禁用模板布局后台不需要验证权限的接口配置 推荐链接 链接目录 FastAdmin 禁用模板布局 /** 在application/common/controller/Backend.php里面的 _initialize() 方法里面有// 如果有使用模板布局if ($this->layout) {$this->view->engine-…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...

云原生周刊:k0s 成为 CNCF 沙箱项目

开源项目推荐 HAMi HAMi&#xff08;原名 k8s‑vGPU‑scheduler&#xff09;是一款 CNCF Sandbox 级别的开源 K8s 中间件&#xff0c;通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度&#xff0c;为容器提供统一接口&#xff0c;实现细粒度资源配额…...

MLP实战二:MLP 实现图像数字多分类

任务 实战&#xff08;二&#xff09;&#xff1a;MLP 实现图像多分类 基于 mnist 数据集&#xff0c;建立 mlp 模型&#xff0c;实现 0-9 数字的十分类 task: 1、实现 mnist 数据载入&#xff0c;可视化图形数字&#xff1b; 2、完成数据预处理&#xff1a;图像数据维度转换与…...

简单聊下阿里云DNS劫持事件

阿里云域名被DNS劫持事件 事件总结 根据ICANN规则&#xff0c;域名注册商&#xff08;Verisign&#xff09;认定aliyuncs.com域名下的部分网站被用于非法活动&#xff08;如传播恶意软件&#xff09;&#xff1b;顶级域名DNS服务器将aliyuncs.com域名的DNS记录统一解析到shado…...

持续交付的进化:从DevOps到AI驱动的IT新动能

文章目录 一、持续交付的本质&#xff1a;从手动到自动的交付飞跃关键特性案例&#xff1a;电商平台的高效部署 二、持续交付的演进&#xff1a;从CI到AI驱动的未来发展历程 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/101f72defaf3493ba0ba376bf09367a2.png)中国…...