cesium 3DTiles之pnts格式详解

news2024/12/23 16:18:41

Point Cloud

1 概述

点云(Point Cloud)瓦片格式用于高效流式传输大规模点云数据,常用于 3D 可视化中。每个点由位置(Position)和可选的属性定义,这些属性用来描述点的外观(如颜色、法线等)或应用特定的元数据。

在 3D Tiles 的术语中,每个点被称为一个“特征”(Feature)。Point Cloud 瓦片本身是一个二进制块,采用小端字节序(Little Endian)。

2 布局

Point Cloud 瓦片由头部(Header)和正文(Body)两部分组成。以下是 Point Cloud 布局的简图(虚线表示可选字段):

| Header | Body (Feature Table + Batch Table) |
2.1 填充

瓦片的字节长度(byteLength)必须对齐到 8 字节边界。同时,瓦片中的特征表(Feature Table)和批处理表(Batch Table)也必须遵循各自的填充要求。

3 头部(Header)

头部是一个 28 字节的数据结构,包含以下字段:

字段名数据类型描述
magic4 字节 ANSI 字符串固定值 “pnts”,用于标识 Point Cloud 瓦片的内容。
versionuint32Point Cloud 格式的版本号,目前版本为 1。
byteLengthuint32整个瓦片的字节长度(包含头部和正文)。
featureTableJSONByteLengthuint32特征表 JSON 部分的字节长度。
featureTableBinaryByteLengthuint32特征表二进制部分的字节长度。
batchTableJSONByteLengthuint32批处理表 JSON 部分的字节长度。0 表示没有批处理表。
batchTableBinaryByteLengthuint32批处理表二进制部分的字节长度。如果批处理表 JSON 长度为 0,则该值为 0。

头部后面紧接着的是正文部分,它由特征表(Feature Table)和批处理表(Batch Table)组成。

4 特征表(Feature Table)

特征表包含每个瓦片和每个点的属性,这些属性定义了如何渲染点云数据。每个点的数据通过不同的语义(Semantics)进行标识,用于描述点的位置、颜色、法线等属性。

4.1 语义(Semantics)
4.1.1 点的语义(Point Semantics)

这些语义映射到一个特征值数组,用于定义每个点的属性。所有语义的数组长度必须相同,且等于点的数量。每个语义的值都是对特征表二进制部分的引用,而不是嵌入在特征表 JSON 头部中的。

  • 如果同时定义了 POSITIONPOSITION_QUANTIZED,则使用高精度的 POSITION
  • 如果同时定义了 NORMALNORMAL_OCT16P,则使用高精度的 NORMAL

常见的点语义包括:

语义名数据类型描述必需
POSITIONfloat32[3]定义点的位置,包含 x、y 和 z 坐标。
POSITION_QUANTIZEDuint16[3]定义量化的点位置,包含 x、y 和 z 坐标的量化值。
RGBAuint8[4]定义点的 RGBA 颜色值。
RGBuint8[3]定义点的 RGB 颜色值。
RGB565uint1616 位压缩 RGB 颜色,提供 5 位红色、6 位绿色、5 位蓝色。
NORMALfloat32[3]定义点的法向量。
NORMAL_OCT16Puint8[2]定义点的法向量,使用 16 位精度的八度编码。
BATCH_IDuint8, uint16, uint32定义点的批处理 ID,用于从批处理表中检索元数据。
4.1.2 全局语义(Global Semantics)

这些语义定义了所有点的全局属性。

语义名数据类型描述必需
POINTS_LENGTHuint32渲染的点的数量。每个语义的数组长度应与该值相同。
RTC_CENTERfloat32[3]定义点的位置相对于中心的偏移量。
QUANTIZED_VOLUME_OFFSETfloat32[3]定义量化体积的偏移量。
QUANTIZED_VOLUME_SCALEfloat32[3]定义量化体积的缩放值。
CONSTANT_RGBAuint8[4]定义所有点的常量 RGBA 颜色。
BATCH_LENGTHuint32定义唯一的 BATCH_ID 数量。

4.2 点的位置(Point Positions)

4.2.1 坐标参考系统(Coordinate Reference System, CRS)

3D Tiles 使用的是右手坐标系,具有三个轴(x, y, z),并且 x 和 y 的叉乘结果为 z。3D Tiles 定义了局部坐标系统中的 z 轴为上(up)轴。这意味着,在局部笛卡尔坐标系统中,z 轴指向上方。

4.2.2 RTC_CENTER

点的位置可以相对于一个中心点进行定义,以提高渲染的精度(见 “Precisions”)。如果定义了 RTC_CENTER,则所有点的位置都相对于该中心点进行计算。这种方法尤其适用于高精度渲染,允许对整个点云的变换应用更加精确的操作。

4.2.3 量化位置(Quantized Positions)

如果未定义 POSITION,则可以使用 POSITION_QUANTIZED 来存储点的位置,这些位置是相对于量化体积(Quantized Volume)定义的。量化体积通过偏移量(offset)和缩放因子(scale)来映射量化位置到局部坐标空间。

如果既没有定义 POSITION 也没有定义 POSITION_QUANTIZED,则该瓦片无需渲染。

请添加图片描述

量化体积的定义包括偏移量和缩放因子,分别存储在全局语义 QUANTIZED_VOLUME_OFFSETQUANTIZED_VOLUME_SCALE 中。如果没有定义这些全局语义,就无法使用 POSITION_QUANTIZED

量化位置到局部空间的映射公式如下:

POSITION = POSITION_QUANTIZED * QUANTIZED_VOLUME_SCALE / 65535.0 + QUANTIZED_VOLUME_OFFSET

4.3 点的颜色(Point Colors)

如果定义了多个颜色语义,则颜色的优先顺序为:RGBA > RGB > RGB565 > CONSTANT_RGBA。例如,如果一个瓦片的特征表包含 RGBACONSTANT_RGBA 属性,运行时将使用 RGBA 作为每个点的颜色。

如果没有定义任何颜色语义,运行时可以使用应用程序定义的默认颜色来渲染点。

无论如何,都可以使用 3D Tiles 样式(Style)在运行时改变最终渲染的颜色和其他视觉属性。

4.4 点的法线(Point Normals)

每个点的法线是一个可选属性,能够通过启用光照、隐藏表面去除等渲染技术来提高点云的视觉质量。法线将在应用瓦片变换的逆转置矩阵后进行变换。

4.4.1 八度编码法线向量(Oct-encoded Normal Vectors)

八度编码(Oct-encoding)是一种高效表示独立单位向量的方式。具体而言,八度编码将单位法线向量存储为无符号且未归一化的范围([0, 255]),并在运行时将其映射到有符号归一化范围([-1.0, 1.0])。

Cesium 中提供了一个实现,用于编码和解码这些单位向量,相关模块为 AttributeCompression

4.5 批处理点(Batched Points)

点云中的不同特征可以通过 BATCH_ID 语义进行批处理。例如,一个房间的门的所有点会分配相同的 BATCH_ID,而窗户的点则会有不同的 BATCH_ID。这对于按对象进行拾取(picking)或存储应用程序特定的元数据非常有用,特别是在声明式样式(styling)和应用程序用例(如填充用户界面、发出 REST API 请求等)中。

BATCH_ID 语义可以具有 UNSIGNED_BYTEUNSIGNED_SHORTUNSIGNED_INT 的数据类型。如果没有指定 componentType,则默认为 UNSIGNED_SHORT

全局语义 BATCH_LENGTH 定义了唯一的 BATCH_ID 数量,类似于Batched 3D Model

4.6 示例(Examples)

4.6.1 只有位置(Positions Only)

这是一个简单的示例,包含四个点,它们位于单位长度正方形的四个角上:

var featureTableJSON = { 
  POINTS_LENGTH: 4, 
  POSITION: { 
    byteOffset: 0 
  } 
}; 

var featureTableBinary = new Buffer(new Float32Array([ 
  0.0, 0.0, 0.0,  
  1.0, 0.0, 0.0, 
  0.0, 0.0, 1.0, 
  1.0, 0.0, 1.0 
]).buffer);
4.6.2 位置和颜色(Positions and Colors)

以下示例包含四个点(分别为红色、绿色、蓝色和黄色),它们的位置是相对于中心定义的:

var featureTableJSON = { 
  POINTS_LENGTH: 4, 
  RTC_CENTER: [1215013.8, -4736316.7, 4081608.4], 
  POSITION: { 
    byteOffset: 0 
  }, 
  RGB: { 
    byteOffset: 48 
  } 
}; 

var positionBinary = new Buffer(new Float32Array([ 
  0.0, 0.0, 0.0,  
  1.0, 0.0, 0.0,  
  0.0, 0.0, 1.0,  
  1.0, 0.0, 1.0 
]).buffer); 

var colorBinary = new Buffer(new Uint8Array([ 
  255, 0, 0, 
  0, 255, 0, 
  0, 0, 255, 
  255, 255, 0 
]).buffer); 

var featureTableBinary = Buffer.concat([positionBinary, colorBinary]);
4.6.3 量化位置和八度编码法线(Quantized Positions and Oct-encoded Normals)

这个示例中,四个点将有指向上方的法线向量 [0.0, 1.0, 0.0],并且它们位于一个量化体积的角上,量化体积的范围从 -250.0 到 250.0 单位:

var featureTableJSON = { 
  POINTS_LENGTH: 4, 
  QUANTIZED_VOLUME_OFFSET: [-250.0, 0.0, -250.0], 
  QUANTIZED_VOLUME_SCALE: [500.0, 0.0, 500.0], 
  POSITION_QUANTIZED: { 
    byteOffset: 0 
  }, 
  NORMAL_OCT16P: { 
    byteOffset: 24 
  } 
}; 

var positionQuantizedBinary = new Buffer(new Uint16Array([ 
  0, 0, 0,  
  65535, 0, 0,  
  0, 0, 65535,  
  65535, 0, 65535 
]).buffer); 

var normalOct16PBinary = new Buffer(new Uint8Array([ 
  128, 255, 
  128, 255, 
  128, 255, 
  128, 255 
]).buffer); 

var featureTableBinary = Buffer.concat([positionQuantizedBinary, normalOct16PBinary]);
4.6.4 批处理点(Batched Points)

这个示例中,前两个点的 batchId 为 0,后两个点的 batchId 为 1。注意,Batch Table 只包含两个名字:

var featureTableJSON = { 
  POINTS_LENGTH: 4, 
  BATCH_LENGTH: 2, 
  POSITION: { 
    byteOffset: 0 
  }, 
  BATCH_ID: { 
    byteOffset: 48, 
    componentType: "UNSIGNED_BYTE" 
  } 
}; 

var positionBinary = new Buffer(new Float32Array([ 
  0.0, 0.0, 0.0, 
  1.0, 0.0, 0.0, 
  0.0, 0.0, 1.0, 
  1.0, 0.0, 1.0 
]).buffer); 

var batchIdBinary = new Buffer(new Uint8Array([ 
  0, 
  0, 
  1, 
  1 
]).buffer); 

var featureTableBinary = Buffer.concat([positionBinary, batchIdBinary]); 

var batchTableJSON = { 
  names: ['object1', 'object2'] 
};
4.6.5 每点属性(Per-point Properties)

在这个示例中,四个点将有元数据存储在 Batch Table 的 JSON 和二进制部分:

var featureTableJSON = { 
  POINTS_LENGTH: 4, 
  POSITION: { 
    byteOffset: 0 
  } 
}; 

var featureTableBinary = new Buffer(new Float32Array([ 
  0.0, 0.0, 0.0, 
  1.0, 0.0, 0.0, 
  0.0, 0.0, 1.0, 
  1.0, 0.0, 1.0 
]).buffer); 

var batchTableJSON = { 
  names: ['point1', 'point2', 'point3', 'point4'] 
};

5 批处理表(Batch Table)

批处理表存储的是按 batchId 索引的应用程序特定元数据,可用于声明式样式和应用程序特定用例(如填充 UI 或发出 REST API 请求)。

  • 如果定义了 BATCH_ID 语义,批处理表存储每个 batchId 的元数据,批处理表的数组长度将等于 BATCH_LENGTH
  • 如果未定义 BATCH_ID 语义,批处理表存储每个点的元数据,批处理表的数组长度将等于 POINTS_LENGTH

6 文件扩展名和 MIME 类型(File Extension and MIME Type)

点云瓦片使用 .pnts 扩展名和 application/octet-stream MIME 类型。文件扩展名是可选的,有效的实现可以忽略扩展名,直接通过头部的魔术字段来识别内容格式。

7 实现示例(Implementation Example)

这部分内容是非规范性的,实际代码实现可以参考 Cesium 的 PointCloud3DModelTileContent.js 文件,它提供了 3D Tiles 的头部读取代码。
TilesBuilder 工具可转换部分三维格式

8 属性参考(Property Reference)

8.1 点云特征表(Point Cloud Feature Table)

点云特征表定义了用于描述瓦片中点的位置信息和外观属性的语义。其属性包括:

  • POSITION: 定义点的位置(包括量化位置)。
  • POSITION_QUANTIZED: 定义量化点的位置。
  • RGBA, RGB, RGB565: 定义点的颜色。
  • NORMAL, NORMAL_OCT16P: 定义点的法线。
  • BATCH_ID: 用于批处理每个点的 batchId
  • POINTS_LENGTH: 定义点的数量。
  • RTC_CENTER: 定义渲染中心。
  • QUANTIZED_VOLUME_OFFSETQUANTIZED_VOLUME_SCALE: 定义量化体积的偏移和缩放因子。

这些属性可以直接在 JSON 中定义,或者通过 BinaryBodyReference 对象引用二进制体中的对应部分。

8.2 二进制体引用(BinaryBodyReference)

BinaryBodyReference 定义了一个对象,该对象指向二进制体中存储特定属性值的部分,包含 byteOffset 属性,指定从二进制缓冲区的偏移量。

属性:
  • byteOffset (类型: number, 必需):
    指定在二进制体中的偏移量(单位为字节)。

    • 要求: 必需
    • 最小值: 大于等于 0
  • 其他属性:
    可以根据需要在 BinaryBodyReference 中添加其他自定义属性,但 byteOffset 是必需的。

8.2.1 BinaryBodyReference.byteOffset

byteOffsetBinaryBodyReference 中的一个关键属性,定义了该属性值在二进制缓冲区中的起始位置。它指定了从二进制数据开始位置的偏移量,通常是字节单位。

  • 类型: number
  • 要求: 必需
  • 最小值: >= 0

8.3 GlobalPropertyCartesian3

GlobalPropertyCartesian3 是一个对象,它定义了适用于所有特征的全局 3 组件数值属性。 通常,这些数值表示与三维坐标相关的全局属性,如位置、方向等。

8.4 GlobalPropertyCartesian4

GlobalPropertyCartesian4 是一个对象,它定义了适用于所有特征的全局 4 组件数值属性。 这通常用于表示四维数值属性,例如带有时间或颜色信息的 3D 坐标。

8.5 GlobalPropertyScalar

GlobalPropertyScalar 是一个对象,它定义了适用于所有特征的全局标量数值属性。 这种类型的属性用于表示单一的数值,如某些全局设置或常量参数。

8.6 Property

Property 是一个用户定义的属性,指定每个特征的应用程序特定元数据。
这些属性的值可以直接在 JSON 中定义,也可以通过BinaryBodyReference 引用二进制体中的某个部分。 如果 Property 是数组类型,它允许存储每个特征的多个值。

如果你有兴趣了解如何实现或使用点云格式,或者在具体的项目中遇到技术难题,可以随时向我咨询!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2239128.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记录一次非常奇怪的MIME type of “text/html“报错

报错现象 访问指定地址,一直转圈打不开,打开游览器控制台发现有如下报错: Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of “text/html”. Strict MIME type checking i…

git新手使用教程

git新手使用教程 一、安装和初始化配置2、新建仓库3.工作区域和文件状态4.添加和提交文件5 git reset回退版本6 使用git diff查看差异7 使用git rm删除文件8 .gitignore忽略文件9 注册GitHub账号10 SSH配置和克隆仓库11 关联本地仓库和远程仓库12 Gitee的使用 由B站视频教程整理…

《TCP/IP网络编程》学习笔记 | Chapter 10:多进程服务器端

《TCP/IP网络编程》学习笔记 | Chapter 10:多进程服务器端 《TCP/IP网络编程》学习笔记 | Chapter 10:多进程服务器端进程概念及应用并发服务端的实现方法理解进程进程ID通过调用 fork 函数创建进程 进程和僵尸进程僵尸进程产生僵尸进程的原因销毁僵尸进…

推荐一款DBF文件查看器:DBF Viewer 2000

DBF Viewer 2000是一款强大、简洁且易于使用的 DBF(Clipper、dBase、FoxBase、Foxpro、Visual Foxpro、Visual DBase、VO、DB2K)文件浏览器和编辑器。 软件特点: - 能够快速、有效地浏览和编辑各种类型的 DBF 文件。 - 支持多种文件格式,包括 dBase、V…

基于构件的软件开发、软件维护、区块链技术及湖仓一体架构的应用

目录 试题一 论基于构件的软件开发方法及其应用 试题二 论软件维护方法及其应用 试题三 论区块链技术及应用 试题四 论湖仓一体架构及其应用 相关推荐 试题一 论基于构件的软件开发方法及其应用 基于构件的软件开发(Component-Based Software Development,CBSD…

SCRFD算法解读及环境安装实践

论文地址:https://arxiv.org/abs/2105.04714,accepted by ICLR-2022 工程地址:https://github.com/deepinsight/insightface/tree/master/detection/scrfd 下一篇博客,如何用SCRFD训练自己的数据 文章目录 1、算法解读2、环境安装…

在IntelliJ IDEA中创建带子模块的SpringBoot工程

前言 在项目开发中,一个工程往往有若干子工程或模块,所以主工程一般是一个容器,本文介绍在IntelliJ IDEA中创建带多模块的SpringBoot工程的详细步骤。 1、首先打开IntellJ IDEA(以下简称IDEA),创建一个新项目。假定新…

深入剖析输入URL按下回车,浏览器做了什么

DNS 查询 首先,是去寻找页面资源的位置。如果导航到https://example.com, 假设HTML页面被定位到IP地址为93.184.216.34 的服务器。如果以前没有访问过这个网站,就需要进行DNS查询。 浏览器向域名服务器发起DNS查询请求,最终得到一个IP地址。第一次请求…

提升百度排名的有效策略与技巧解析

内容概要 提升百度排名对于网站的成功至关重要。首先,了解百度排名的基本原则,掌握搜索引擎是如何评估网页质量的,是优化过程中不可或缺的一部分。搜索引擎越来越倾向于将用户需求放在首位,因此提供高质量的内容和良好的用户体验…

【GPTs】MJ Prompt Creator:轻松生成创意Midjourney提示词

博客主页: [小ᶻZ࿆] 本文专栏: AIGC | GPTs应用实例 文章目录 💯GPTs指令💯前言💯MJ Prompt Creator主要功能适用场景优点缺点 💯 小结 💯GPTs指令 中文翻译: 任务说明 您是一款为幻灯片工…

机器人领域顶刊TRO十月最新论文一览,覆盖状态估计、任务分配、人机协作等多个领域

No.1 基于可见性的近似追逃方法 论文标题:Approximate Methods for Visibility-Based Pursuit–Evasion 中文标题:基于可见性的近似追逃方法 作者:Emmanuel Antonio; Israel Becerra; Rafael Murrieta-Cid 本文提出了一种基于采样的动态规…

解决编译 fast-lio-lc 算法时遇到的error方法

1.创建工作空间和下载 fast-lio-lc功能包 mkdir -p fast_lio_lc_ws/src cd fast_lio_lc_ws/src/ catkin_init_workspace git clone https://github.com/yanliang-wang/FAST_LIO_LC.git2.进入工作空间,编译 编译 fast-lio-lc遇到的error: 🕐error: fatal error: opencv/cv…

【Qt】Macbook M1下载安装

文章目录 一、下载Xcode命令行工具二、在Cion中配置编译器三、安装Qt四、配置qmake环境五、创建Qt项目 博主已经下载了Clion,所以本文是将qt配置到Clion上 本博客所写的教程有一定的问题,因为我在官网下载后发现有一些所需的包是没有的,不知道…

Python+Pytest+Allure+Git+Jenkins接口自动化框架

一、接口基础 接口测试是对系统和组件之间的接口进行测试,主要是效验数据的交换,传递和控制管理过程,以及相互逻辑依赖关系。其中接口协议分为HTTP,RPC,Webservice,Dubbo,RESTful等类型。 接口…

Docker:镜像构建 DockerFile

Docker:镜像构建 DockerFile 镜像构建docker build DockerfileFROMCOPYENVWORKDIRADDRUNCMDENTRYPOINTUSERARGVOLUME 镜像构建 在Docker官方提供的镜像中,大部分都是基础镜像,他们只提供某个简单的功能,如果想要一个功能更加丰富…

《JavaEE进阶》----20.<基于Spring图书管理系统①(登录+添加图书)>

PS:关于接口定义 接口定义,通常由服务器提供方来定义。 1.路径:自己定义 2.参数:根据需求考虑,我们这个接口功能完成需要哪些信息。 3.返回结果:考虑我们能为对方提供什么。站在对方角度考虑。 我们使用到的…

【JavaEE】文件io

目录 文件类型 File概述 属性 构造方法 常用方法 Reader Writer InputStream OutputStream 字节流转字符流 通过Scanner读取InputStream 通过PrintWriter转换outputstream 示例 文件类型 从编程的角度看,文件类型主要就是两大类 文本(文…

D3入门:概念、主要特点、基本功能、常见应用场景

D3.js(Data-Driven Documents)是一个JavaScript库,用于基于数据操作文档。它利用了HTML、SVG和CSS等Web标准技术,使得开发者可以创建丰富的交互式图表和数据可视化。D3.js的强大之处在于其灵活的数据绑定机制和对DOM元素的高效操作…

go函数传值是值传递?还是引用传递?slice案例加图解

先说下结论 Go语言中所有的传参都是值传递(传值),都是一个副本,一个拷贝。 值语义类型:参数传递的时候,就是值拷贝,这样就在函数中就无法修改原内容数据。 基本类型:byte、int、bool…

tensorflow案例5--基于改进VGG16模型的马铃薯识别,准确率提升0.6%,计算量降低78.07%

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 前言 本次采用VGG16模型进行预测,准确率达到了98.875,但是修改VGG16网络结构, 准确率达到了0.9969,并且计算量…