Draco 源码执行过程分析

可结合源码对比查看

(一)、压缩格网信息
position顶点信息 、normal法线信息、TexCoord纹理信息、face 面

声明数组获取数据--》声明draco网格(unique_ptr<draco::Mesh> dracomesh)--》向draco网格添加面

定义面的索引信息--》向draco网格设置面的个数--》声明网格面--》将面的索引信息循环存储到网格面--》根据网格面数据设置draco网格SetFace

定义position顶点数组信息--》计算获取到顶点数--》计算每个顶点的步长--》声明压缩属性并初始化属性--》使用网格的AddAttribute()方法添加网格属性--》声明点属性并赋值为根据属性ID获取的网格属性--》将position顶点数组信息循环存储到网格里

法线、纹理同上

创建压缩encoder--》设置压缩参数--》声明压缩所以后存储的对象EncoderBuffer dracobuffer--》使用encoder压缩中的EncodeMeshToBuffer方法参数为(dracomesh,dracobuffer)。

使用Draco压缩库进行几何编码的高级助手类--》重置创建编码器选项--》编码缓冲--》设置编码后点数--》设置编码后面数

********编码缓冲*******
EncodeToBuffer(EncoderBuffer *out_buffer)方法
判断point_cloud_是否为null为null时提示无效输入几何学。--》判断mesh网格是否为null,为null执行EncodePointCloudToBuffer(*point_cloud_, out_buffer);不为则执行EncodeMeshToBuffer(*mesh_, out_buffer);

注:判断数据中是否有多个面:
如果有面,则进行Mesh to File的过程
若不存在面,则只进行PointCloud to File的过程
两个函数都会返回一个bool变量,来表示是否成功。PointCloud是n维空间中的点的集合,PointCloud的相关信息在 …/point_cloud/point_cloud.h 中,而Mesh是PointCloud的继承类,Mesh只是比PointCloud多了Face数据:
…/mesh/mesh.h

********EncodeMeshToBuffer()*******
定义所有网格编码器的基类--》根据提供的选项选择编码方法 MeshEdgebreakerEncoder()或MeshSequentialEncoder()--》利用encoder->SetMesh(const Mesh &m)来对encoder内部的一些数据进行了初始化(把Mesh和CloudPoint信息在Encoder里也存了一下)
…/compression/mesh/mesh_encoder.cc
void MeshEncoder::SetMesh(const Mesh &m) {
  mesh_ = &m;
  SetPointCloud(m);
}
…/compression/point_cloud/point_cloud_encoder.cc
void PointCloudEncoder::SetPointCloud(const PointCloud &pc) {
  point_cloud_ = &pc;
}
因为Mesh是PointCloud的继承,所以可以直接把Mesh数据传进SetPointCloud函数。
--》Encode(const EncoderOptions &options,EncoderBuffer *out_buffer)--》设置编码后点数--》设置编码后面数

********Encode()*******
 options_ = &options; (赋值编码选项) buffer_ = out_buffer;(这个缓冲区保存最终编码的数据。)--》清除以前运行的内存属性--》判断point_cloud_是否为null返回无效输入几何学。--》执行EncodeHeader、EncodeMetadata、InitializeEncoder、具体对EncodeEncoderData、EncodeGeometryData、EncodePointAttributes进行了编码

EncoderHeader()将encoder的一些基本信息写入buffer,以便今后decode
这些信息包括:”DRACO”字符串标识、major version、minor version、encoder type(point cloud, mesh, …)、selected encoding method (edgebreaker, etc…)、保留标识
然后用encoder->Encode根据option对数据进行编码,写入buffer

InitializeEncoder()功能是:可以由派生类实现,以执行编码器的任何自定义初始化。在Encode()方法中调用。

EncodeEncoderData()功能是:应该用于编码任何特定于编码器的数据。
不过这两个都是预留接口,设置了虚函数但没有实现,直接返回true

EncoderGeometryData()会把mesh 的 connectivity进行编码并存入buffer,根据encoder的不同,编码connectivity的方式会分为sequential encoding 和 edgebreaker encoding。

EncodePointAttributes()功能是对顶点坐标等信息压缩编码,关于每个属性的点特定数据。一般情况下,存储在点云中的多个点可以共享相同的属性值,这个类提供了点id和属性值id之间必要的映射。

********EncodePointAttributes()********

GenerateAttributesEncoders()生成属性器--》Encode()对属性编码器的数量进行编码。--》初始化所有编码器--》RearrangeAttributesEncoders()重新排列属性--》EncodeAttributesEncoderIdentifier()对创建相应的属性解码器所需的任何数据进行编码。--》EncodeAttributesEncoderData()还要编码任何属性编码器数据(例如关于已编码属性的信息)。---》EncodeAllAttributes() 最后,使用提供的属性编码器对所有属性进行编码。

********EncodeAllAttributes()********
EncodeAttributes() 将属性数据编码到目标缓冲区。

********EncodeAttributes()********
TransformAttributesToPortableFormat() 将输入属性数据转换为应进行无损编码的形式(转换本身可能是有损的)。--》
EncodePortableAttributes(out_buffer) 编码可移动属性 --》
EncodeDataNeededByPortableTransforms(out_buffer) 在对属性进行编码后,对可移植转换所需的数据进行编码。这对应于数据将被解码器解码的顺序。

********EncodePortableAttributes(out_buffer)********
EncodeValues()方法 输入值的无损编码

********EncodeValues()********
初始化一般量化数据--》预案的方法--》预测计划--》便携式属性数据--》encoded_data 保存我们储存的可移动数据--》预测计划--》设置符号编码压缩级别--》编码符号--》编码预测数据

初始化一般量化数据--》……--》EncodeSymbols()

********EncodeSymbols() 编码符号********

ComputeBitLengths 计算比特长度--》tagged_scheme_total_bits 标记方案总位数(使用标记模式存储符号所需的大约位数。)--》raw_scheme_total_bits 原始方案总位数(  使用原始方案存储符号所需的大约比特数。)--》max_value_bit_length最大位长(可以使用原始方案编码的单个条目值的最大位长。)--》比较 标记方案总位数和原始方案总位数的大小(根据总位数大小选择熵编码方法)或者 比较最大位长与kMaxRawEncodingBitLength(固定值18)的大小--》当标记方案总位数小于原始方案总位数的大小或者最大位长大于k最大原始编码位长度的大小时使用EncodeTaggedSymbols()熵编码方法 ,否则使用EncodeRawSymbols()熵编码方法

********EncodeTaggedSymbols() 熵编码********
frequencies带标记位长频率--》将每个条目的频率设置为零。--》根据输入数据计算频率。--》创建一个额外的缓冲区来存储原始值。--》开始编码位标记。--》还可以开始对值进行编码。--》判断是否需要反向编码 (for循环索引不同)--》EndEncoding()结束编码位标记。--》EndBitEncoding()结束对值进行编码--》将值附加到目标缓冲区的末尾。

********EncodeRawSymbols() 熵编码********
symbol_bits符号位默认为0--》如果num_unique_symbols值大于0则符号位获取MostSignificantBit()最重要位--》计算unique_symbols_bit_length唯一符号位长判断如果大于k最大原始编码位长度则返回False(不支持超过2^18个唯一符号的编码。)--》获取压缩级别取默认值7--》若options选项不为空且设置了符号编码压缩级则取设置的符号编码压缩级--》比较compression_level压缩级别修改unique_symbols_bit_length唯一符号位长--》将unique_symbols_bit_length设置为一个有效的范围。--》EncodeRawSymbolsInternal()根据最大符号位长度使用适当的符号编码器。

********EncodeRawSymbolsInternal() 符号编码器********
frequencies 计算每个条目值的频率。--》创建符号编码器--》开始编码--》编码所有值 判断是否反向编码(for循环索引不同)--》结束编码

*********TransformAttributeToPortableFormat()********

TransformAttributeToPortableFormat()将属性转换为可移植格式

********EncodeDataNeededByPortableTransforms(out_buffer)********

(二)、压缩点信息
position顶点信息 、normal法线信息、color颜色信息、noise噪声信息

定义position 、normal、color、noise vector数组数据--》声明定义dracoPointCloud点云--》设置要压缩的点数--》获取顶点数、组件数、每个顶点的步长--》创建压缩属性并初始化--》将压缩属性对象、点数添加到dracoPointCloud点云中--》根据添加到点云返回的ID获取添加的属性对象--》将顶点数据添加到压缩属性att中--》定义压缩对象--》设置压缩参数--》设置压缩方法--》EncodePointCloudToBuffer()压缩点法线颜色噪声

*********EncodePointCloudToBuffer()*********
使用Draco压缩库进行几何编码的高级助手类--》重置创建编码器选项--》EncodeToBuffer()编码缓冲--》EncodePointCloudToBuffer() 编码--》encoder定义点云编码的基类--》获取编码方法--》设置编码器--》利用encoder->SetPointCloud(pc)来对encoder内部的一些数据进行了初始化(把CloudPoint信息在Encoder存一下)--》Encode()编码

*********Encode()*********
options_ = &options; (赋值编码选项) buffer_ = out_buffer;(这个缓冲区保存最终编码的数据。)--》清除以前运行的内存属性--》判断point_cloud_是否为null返回无效输入几何学。--》执行EncodeHeader、EncodeMetadata、InitializeEncoder、具体对EncodeEncoderData、EncodeGeometryData、EncodePointAttributes进行了编码

EncoderHeader()将encoder的一些基本信息写入buffer,以便今后decode
这些信息包括:”DRACO”字符串标识、major version、minor version、encoder type(point cloud, mesh, …)、selected encoding method (edgebreaker, etc…)、保留标识
然后用encoder->Encode根据option对数据进行编码,写入buffer

InitializeEncoder()功能是:可以由派生类实现,以执行编码器的任何自定义初始化。在Encode()方法中调用。

EncodeEncoderData()功能是:应该用于编码任何特定于编码器的数据。
不过这两个都是预留接口,设置了虚函数但没有实现,直接返回true

EncoderGeometryData()会把mesh 的 connectivity进行编码并存入buffer,根据encoder的不同,编码connectivity的方式会分为sequential encoding 和 edgebreaker encoding。

EncodePointAttributes()功能是对顶点坐标等信息压缩编码,关于每个属性的点特定数据。一般情况下,存储在点云中的多个点可以共享相同的属性值,这个类提供了点id和属性值id之间必要的映射。

********EncodePointAttributes()********

GenerateAttributesEncoders()生成属性器--》Encode()对属性编码器的数量进行编码。--》初始化所有编码器--》RearrangeAttributesEncoders()重新排列属性--》EncodeAttributesEncoderIdentifier()对创建相应的属性解码器所需的任何数据进行编码。--》EncodeAttributesEncoderData()还要编码任何属性编码器数据(例如关于已编码属性的信息)。---》EncodeAllAttributes() 最后,使用提供的属性编码器对所有属性进行编码。

********EncodeAllAttributes()********
EncodeAttributes() 将属性数据编码到目标缓冲区。

********EncodeAttributes()********
TransformAttributesToPortableFormat() 将输入属性数据转换为应进行无损编码的形式(转换本身可能是有损的)。--》
EncodePortableAttributes(out_buffer) 编码可移动属性 --》
EncodeDataNeededByPortableTransforms(out_buffer) 在对属性进行编码后,对可移植转换所需的数据进行编码。这对应于数据将被解码器解码的顺序。

*********EncodePortableAttributes(out_buffer) *********
使用kd树编码算法对数据进行编码,将compression_level的最大值限制为6,因为目前没有这样做为更高的压缩级别提供可行的算法。--》获取压缩级别--》创建编码--》获取点数、组件数--》创建点向量--》复制数据到点向量--》复制源属性到矢量--》计算kd树编码所需的最大比特长度。--》根据压缩等级使用对应动态整数点Kd树编码器--》执行点解码--》

Google Draco 源码解析相关推荐

  1. Redis源码解析——内存管理

    在<Redis源码解析--源码工程结构>一文中,我们介绍了Redis可能会根据环境或用户指定选择不同的内存管理库.在linux系统中,Redis默认使用jemalloc库.当然用户可以指定 ...

  2. Android之EasyPermissions源码解析

    转载请标明出处:[顾林海的博客] 个人开发的微信小程序,目前功能是书籍推荐,后续会完善一些新功能,希望大家多多支持! 前言 我们知道在Android中想要申请权限就需要在AndroidManifest ...

  3. Guava RateLimiter限流源码解析和实例应用

    2019独角兽企业重金招聘Python工程师标准>>> 在开发高并发系统时有三把利器用来保护系统:缓存.降级和限流 缓存 缓存的目的是提升系统访问速度和增大系统处理容量 降级 降级是 ...

  4. 深度学习框架Caffe源码解析

    作者:薛云峰(https://github.com/HolidayXue),主要从事视频图像算法的研究, 本文来源微信公众号:深度学习大讲堂.  原文:深度学习框架Caffe源码解析  欢迎技术投稿. ...

  5. The Wide and Deep Learning Model(译文+Tensorlfow源码解析) 原创 2017年11月03日 22:14:47 标签: 深度学习 / 谷歌 / tensorf

    The Wide and Deep Learning Model(译文+Tensorlfow源码解析) 原创 2017年11月03日 22:14:47 标签: 深度学习 / 谷歌 / tensorfl ...

  6. dubbo源码解析(九)远程通信——Transport层

    远程通讯--Transport层 目标:介绍Transport层的相关设计和逻辑.介绍dubbo-remoting-api中的transport包内的源码解析. 前言 先预警一下,该文篇幅会很长,做好 ...

  7. Android Lifecycle源码解析(一)

    Android Lifecycle源码解析(一) 首先我们看HomeActivity中我们添加到一行代码 public class HomeActivity extends AppCompatActi ...

  8. Volley 源码解析之网络请求

    Volley源码分析三部曲 Volley 源码解析之网络请求 Volley 源码解析之图片请求 Volley 源码解析之缓存机制 Volley 是 Google 推出的一款网络通信框架,非常适合数据量 ...

  9. 面试官系统精讲Java源码及大厂真题 - 02 String、Long 源码解析和面试题

    02 String.Long 源码解析和面试题 劳动是一切知识的源泉. --陶铸 引导语 String 和 Long 大家都很熟悉,本小节主要结合实际的工作场景,来一起看下 String 和 Long ...

  10. Ambari架构源码解析

    Ambari架构源码解析 一.Ambari介绍 Ambari是hadoop分布式集群配置管理工具,是由hortonworks主导的开源项目.它已经成为apache基金会的孵化器项目,已经成为hadoo ...

最新文章

  1. 智能物联网(AIoT,2020年)(上)
  2. 读博士所面临问题的解决对策
  3. 单页面应用微信分享跳坑指南
  4. was更换java版本,WAS如何更换JDK
  5. python socket编程详细介绍
  6. ui设计未来十年前景_UI设计的10条诫命
  7. java 获取方法名
  8. Spring boot:注解@SpringBootApplication
  9. 【第4篇】Python爬虫实战-抓取B站弹幕视频
  10. 【解决】打印机只打印第一页纸的问题
  11. 冷却水的循环方式有哪几种_VOCs2.0 | 闭式循环水系统,减少VOCs逸散的有效设施...
  12. 《Python核心编程》第二版第八章练习题答案 第三部分
  13. 英伟达显卡不同架构_NVIDIA显卡架构代号的另一面:他们都是伟大的科学先驱
  14. 微博这样的软件怎么测试,新浪微博都盘上了,这个测试玩嗨了!
  15. 开发流程与管理--国内IT项目开发流程
  16. detach()函数的用法
  17. Hinton最新演讲!一种新神经网络:前向-前向FF算法,论文已公开!
  18. jbox2d android教程,Jbox2d实践应用
  19. 战双帕弥什qq登录服务器未响应是什么意思,战双帕弥什qq登录
  20. 【Playwright】关于无痕模式与无头模式

热门文章

  1. 《胡雪岩 1》——读书笔记
  2. Windows 提权
  3. 推荐一款文献管理工具 Zotero |附使用教程和学习路径
  4. Deeper引领WEB3.0世界:去中心化、 安全性和超高速率的统一
  5. Pandas学习任务1-3
  6. 凸优化理论(一)数学优化问题的分类
  7. Babylongjs-动画
  8. 【模拟试题】czy的后宫3 莫队
  9. QQ空间认证之数据篇
  10. 2021平(jia)凡(ban)的一年