cesium 3DTiles之pnts格式详解

news/2024/11/13 15:48:15/

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.ppmy.cn/news/1546711.html

相关文章

Spring Cloud微服务超详细讲解

Spring Cloud 是一个基于 Spring Boot 的微服务框架,它提供了一系列工具和服务来帮助开发者构建和管理微服务架构。以下是一个超级详细的讲解,涵盖了 Spring Cloud 的核心概念、组件以及如何构建一个简单的微服务应用。 1. 微服务架构概述 什么是微服务…

【开源免费】基于SpringBoot+Vue.JS医疗病历交互系统(JAVA毕业设计)

博主说明:本文项目编号 T 072 ,文末自助获取源码 \color{red}{T072,文末自助获取源码} T072,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…

Java从入门到精通笔记篇(十二)

枚举类型与泛型 枚举类型可以取代以往常量的定义方式,即将常量封装在类或接口中 使用枚举类型设置常量 关键字为enum 枚举类型的常用方法 values()方法 枚举类型实例包含一个values()方法,该方法将枚举中所有的枚举值以数组的形式返回。 valueOf()可…

初始化mysql5.7

-- 环境变量 MYSQL_HOME %MYSQL_HOME%\bin -- 新增配置文件 my.ini [mysqld] port 3306 basedir D:/develop/MySQL/mysql-5.7.44-winx64 datadir D:/develop/MySQL/mysql-5.7.44-winx64/data max_connections 200character-set-serverutf8 default-storage-engineINNODB …

科研绘图系列:R语言差异分析双侧柱状图(grouped barplot)

文章目录 介绍加载R包数据画图系统信息介绍 双侧柱状图(grouped barplot),也称为分组柱状图,是一种用于展示不同组别之间比较的数据可视化图表。它通过将不同组别的柱状图并排放置,可以直观地比较不同组在各个类别上的表现或特征。以下是双侧柱状图的一些关键特点和用途:…

VBA高级应用30例应用3在Excel中的ListObject对象:插入行和列

《VBA高级应用30例》(版权10178985),是我推出的第十套教程,教程是专门针对高级学员在学习VBA过程中提高路途上的案例展开,这套教程案例与理论结合,紧贴“实战”,并做“战术总结”,以…

软考系统架构设计师论文:论多源数据集成及应用

试题二 论多源数据集成及应用 在如今信息爆炸的时代,企业、组织和个人面临着大量的数据。这些数据来自不同的渠道和资源,包括传感器、社交媒体、销售记录等,它们各自具有不同的数据格式、分布和存储方式。因此如何收集、整理和清洗数据,以建立一个一致、完整的数据集尤为重…

推荐一个Star超过2K的.Net轻量级的CMS开源项目

推荐一个具有模块化和可扩展的架构的CMS开源项目。 01 项目简介 Piranha CMS是一个轻量级且跨平台的CMS库,专为.NET 8设计。 该项目提供多种模板,具备CMS基本功能,也有空模板方便从头开始构建新网站,甚至可以作为移动应用的后端…