3D Tiles点云(Point Cloud)数据格式标准规范

导航


官网文档

概述

点云瓦片格式支持大规模的点云三维可视化的高效数据流。每个点都由位置和可选的外观属性定义(例如颜色和法线)以及可选的定义特定于应用程序的元数据属性。

使用 3D Tiles 术语,每个点都是一个要是。

点云数据是小端字节序的二进制 Blob。


文件结构

数据由文件头部分和紧随其后的二进制主体组成。下图显示了实例化 3D 模型的布局(破折号表示可选字段):


结构填充

数据 byteLength 必须以 8 个字节进行边界对齐。包含的要素表(Feature Table)批处理表(Batch Table)必须符合其各自的填充要求。


文件头

28 字节的文件头包含以下字段:

字段名 数据类型 描述
magic 4-byte ANSI string "pnts"
version uint32 版本。现在是1
byteLength uint32 整个数据的长度(包括文件头)(以字节为单位)
featureTableJSONByteLength uint32 要素表 JSON 部分的长度(以字节为单位)
featureTableBinaryByteLength uint32 要素表二进制部分的长度(以字节为单位)
batchTableJSONByteLength uint32 批处理表 JSON 部分的长度(以字节为单位),零表示没有批处理表
batchTableBinaryByteLength uint32 批处理表二进制部分的长度(以字节为单位),如果batchTableJSONByteLength为零,则也将为零

主体部分紧着文件头,并且由Feature TableBatch Table组成。


要素表

包含每块和每点的值,这些值定义在何处以及如何渲染点。详见要素表(Feature Table)

pnts 要素表模式的属性参考。完整的 JSON 模式可以在 pnts.featureTable.schema.json 中找到。


语法定义


点语法

这些语法映射定义每个点的一组要素值数组。对于所有语法定义,这些数组的长度必须相同,并且等于点数。每个点语法的值必须是对要素表二进制主体的引用;它们不能嵌入要素表的 JSON 头中。

如果一个语法依赖于另一个语法,则必须定义该语法。如果同时为点定义 POSITIONPOSITION_QUANTIZEDPOSITION 将使用更高精度的值。如果同时为点定义 NORMALNORMAL_OCT16PNORMAL 将使用更高精度的值。

语法 数据类型 描述 是否必须
POSITION float32[3] 由三部分组成的数组,包含点的笛卡尔坐标系xyz的位置 Yes, 是,除非定义了 POSITION_QUANTIZED
POSITION_QUANTIZED uint16[3] 由三部分组成的数组,包含点的量化笛卡尔坐标系xyz的位置 Yes, 是,除非定义了 POSITION
RGBA uint8[4] 由四部分组成的数组,包含点的RGBA颜色值 🔴 No.
RGB uint8[3] 由三部分组成的数组,包含点的RGB颜色值 🔴 No.
RGB565 uint16 一种有损压缩的颜色格式,将RGB颜色打包为 16 位,其中红色 5 位,绿色 6 位和蓝色 5 位 🔴 No.
NORMAL float32[3] 定义点法线的单位向量 🔴 No.
NORMAL_OCT16P uint8[2] 具有 16 位精度的八进制编码单位向量,用于定义点的法线 🔴 No.
BATCH_ID uint8, uint16 (默认), or uint32 batchId用于从Batch Table检索点的元数据 🔴 No.

全局语法

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

语法 数据类型 描述 是否必须
POINTS_LENGTH uint32 渲染的点数。点定义的每个数组值的长度应等于此长度 Yes.
RTC_CENTER float32[3] 由三部分组成的数组,包含当点相对于中心定义时的位置 🔴 No.
QUANTIZED_VOLUME_OFFSET float32[3] 由三部分组成的数组,定义量化体积的偏移量 🔴 No, unless POSITION_QUANTIZED is defined.
QUANTIZED_VOLUME_SCALE float32[3] 由三部分组成的数组,定义量化体积的比例。 🔴 No, unless POSITION_QUANTIZED is defined.
CONSTANT_RGBA uint8[4] 由四部分组成的数组,定义所有点的RGBA颜色值 🔴 No.
BATCH_LENGTH uint32 唯一的BATCH_ID值的数量 🔴 No, unless BATCH_ID is defined.

使用这些语法的示例可以在下面的实现示例中找到。


点位置

POSITION 在应用任何图块转换之前定义点的位置。


坐标系

3D Tiles 局部坐标系统使用右手 3 轴(x,y,z)直角坐标系;xy 的叉积得出 z 。3D Tiles 定义 z 轴向上。


RTC_CENTER

可以相对于中心位置定义以进行高精度渲染,参见 Precisions,Precisions。如果定义,则 RTC_CENTER 指定中心位置,并将所有点位置都视为相对于该值的位置。


量化位置

如果 POSITION 未定义,则位置可以存储在POSITION_QUANTIZED中,该位置定义了相对于量化体积的点位置。如果 POSITIONPOSITION_QUANTIZED 都未定义,则不需要渲染数据。

量化体积由offsetscale定义量化位置到本地空间位置的映射。下图显示了基于 offsetscale的量化体积:

offset保存在全局语义QUANTIZED_VOLUME_OFFSET中,scale保存在全局语义QUANTIZED_VOLUME_SCALE中。如果这些全局语义未定义,POSITION_QUANTIZED 无法使用。

可以使用以下公式将量化位置映射到本地空间位置:

POSITION = POSITION_QUANTIZED * QUANTIZED_VOLUME_SCALE / 65535.0 + QUANTIZED_VOLUME_OFFSET


点颜色

如果定义多种颜色,则优先顺序是 RGBARGBRGB565CONSTANT_RGBA。例如,如果图块的要素表同时包含 RGBACONSTANT_RGBA 属性,则运行时使用RGBA 对每个点颜色进行渲染 。

如果没有颜色定义,则运行时可以使用特定于应用程序的默认颜色来自由设置点颜色。

任何情况下,运行时都可以使用 3D Tiles 样式 更改最终渲染的颜色和其他视觉属性。


点法线

每个点的法线是一个可选属性,可以通过启用照明、隐藏的表面移除(hidden surface removal)和其他渲染技术来帮助改善点的视觉质量。使用平铺变换的逆转置来变换法线。


八进制编码的法向向量

独立单位向量的有效表示法中描述的八进制编码。八进制编码的值存储在无符号的非归一化范围([0, 255])中,然后在运行时映射到有符号的规范化范围([-1.0, 1.0])。

在 CesiumJS 的AttributeCompression模块中可以找到对这些单位矢量进行编码和解码的实现。


批处理点

使用BATCH_ID可以将点云特定功能的点批处理在一起。例如,组成房屋门的所有点可以分配相同的BATCH_ID,而组成窗户的所有点分配不同的BATCH_ID。这对于按对象选择和存储应用程序特定的元数据以进行样式声明和特定于应用程序的用例(例如,填充 UI 或基于每个对象而不是基于每个点发出 REST API 请求)很有用。

BATCH_ID语义可以有一个 componentTypeUNSIGNED_BYTEUNSIGNED_SHORTUNSIGNED_INT。当 componentType 不存在时,使用 UNSIGNED_SHORT。全局语义 BATCH_LENGTH 定义唯一 batchId 值的数量,类似于 Batched 3D Model 标头中的 batchLength 字段。


例子

本节是非规范性的

这些示例说明如何为要素表生成 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 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]);

量化位置和八进制编码法线

在此示例中,四个点的法线以八进制编码格式指向朝上[0.0, 1.0, 0.0],并且将它们放置在量化体积的角上,在xz方向上的跨度为-250.0250.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]);

批处理点

在此示例中,前两个点的batchId0,后两个点的batchId 1。请注意,批处理表只有两个名称:

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 个点中的每个点都将元数据存储在 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']
};

批量表

批处理表包含应用程序特定的元数据,通过batchId进行索引,可被用于声明式样式和应用特定的用例如填充 UI 或者发出 REST API 请求。

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

更多信息,请参见批处理表(Batch Table)


扩展

以下扩展可以应用于点云瓦片。


文件扩展名和 MIME 类型

点云瓦片使用.pnts 扩展名和 application/octet-stream MIME 类型。

显式文件扩展名是可选的。有效的实现可能会忽略它,并通过 magic 其标头中的字段标识内容的格式。


实现示例

本节是非规范性的

可以在 3D Tiles 的 CesiumJS 实现PointCloud3DModelTileContent.js中找到用于读取标头的代码。


属性参考


点云要素表

一组点云语义,其中包含定义图块中点的位置和外观属性的值。

类型 描述 是否必须
extensions object 扩展特定的字典对象 No
extras any 应用特定数据 No
POSITION object 二进制体引用 对象,定义存储了属性值的二进制体部分的引用。查看相应属性的定义语法定义 No
POSITION_QUANTIZED object 二进制体引用 对象,定义存储了属性值的二进制体部分的引用。查看相应属性的定义语法定义 No
RGBA object 二进制体引用 对象,定义存储了属性值的二进制体部分的引用。查看相应属性的定义语法定义 No
RGB object 二进制体引用 对象,定义存储了属性值的二进制体部分的引用。查看相应属性的定义语法定义 No
RGB565 object 二进制体引用 对象,定义存储了属性值的二进制体部分的引用。查看相应属性的定义语法定义 No
NORMAL object 二进制体引用 对象,定义存储了属性值的二进制体部分的引用。查看相应属性的定义语法定义 No
NORMAL_OCT16P object 二进制体引用 对象,定义存储了属性值的二进制体部分的引用。查看相应属性的定义语法定义 No
BATCH_ID object 二进制体引用 对象,定义存储了属性值的二进制体部分的引用。查看相应属性的定义语法定义 No
POINTS_LENGTH object, number [1], number 全局标量属性 对象,定义所有要素的数量。查看相应属性的定义语法定义 Yes
RTC_CENTER object, number [3] 全局笛卡尔 3 坐标系属性 对象,定义所有要素的数量。查看相应属性的定义语法定义 No
QUANTIZED_VOLUME_OFFSET object, number [3] 全局笛卡尔 3 坐标系属性 对象,定义所有要素的数量。查看相应属性的定义语法定义 No
QUANTIZED_VOLUME_SCALE object, number [3] 全局笛卡尔 3 坐标系属性 对象,定义所有要素的数量。查看相应属性的定义语法定义 No
CONSTANT_RGBA object, number [4] 全局笛卡尔 4 坐标系属性 对象,定义所有要素的数量。查看相应属性的定义语法定义 No
BATCH_LENGTH object, number [1], number 全局标量属性 对象,定义所有要素的数量。查看相应属性的定义语法定义 No

允许其他属性。


二进制体引用

一个对象,用于定义对要素表的二进制主体部分的引用,如果未在 JSON 中直接定义属性值,则在该部分存储属性值。

类型 描述 是否必须
byteOffset number 缓冲区的偏移量(以字节为单位) Yes

全局笛卡尔 3 坐标系属性

为所有要素定义全局 3 组分数值属性值的对象。


全局笛卡尔 4 坐标系属性

为所有要素定义全局 4 组分数值属性值的对象。


全局标量属性

为所有要素定义全局数值属性值的对象。


属性

用户自定义的属性,用来在数据中指定每个要素的应用程序特定的元数据。值可以直接在 JSON 中定义为数组,也可以引用二进制体中的部分。

JSON 定义示例

{
  "$schema": "http://json-schema.org/draft-04/schema",
  "id": "featureTable.schema.json",
  "title": "Feature Table",
  "type": "object",
  "description": "A set of semantics containing per-tile and per-feature values defining the position and appearance properties for features in a tile.",
  "definitions": {
    "binaryBodyReference": {
      "title": "BinaryBodyReference",
      "type": "object",
      "description": "An object defining the reference to a section of the binary body of the features table where the property values are stored if not defined directly in the JSON.",
      "properties": {
        "byteOffset": {
          "type": "number",
          "description": "The offset into the buffer in bytes.",
          "minimum": 0
        },
        "componentType": {
          "type": "number",
          "description": "The datatype of components in the property. This is defined only if the semantic allows for overriding the implicit component type. These cases are specified in each tile format.",
          "enum": [
            "BYTE",
            "UNSIGNED_BYTE",
            "SHORT",
            "UNSIGNED_SHORT",
            "INT",
            "UNSIGNED_INT",
            "FLOAT",
            "DOUBLE"
          ]
        }
      },
      "required": ["byteOffset"]
    },
    "numericArray": {
      "type": "array",
      "items": {
        "type": "number"
      }
    },
    "property": {
      "title": "Property",
      "description": "A user-defined property which specifies per-feature application-specific metadata in a tile. Values either can be defined directly in the JSON as an array, or can refer to sections in the binary body with a `BinaryBodyReference` object.",
      "oneOf": [
        {
          "$ref": "#/definitions/binaryBodyReference"
        },
        {
          "type": "array",
          "items": {
            "type": "number"
          }
        },
        {
          "type": "number"
        }
      ]
    },
    "globalPropertyBoolean": {
      "title": "GlobalPropertyBoolean",
      "description": "An object defining a global boolean property value for all features.",
      "type": "boolean"
    },
    "globalPropertyScalar": {
      "title": "GlobalPropertyScalar",
      "description": "An object defining a global numeric property value for all features.",
      "oneOf": [
        {
          "type": "object",
          "properties": {
            "byteOffset": {
              "type": "number",
              "description": "The offset into the buffer in bytes.",
              "minimum": 0
            }
          },
          "required": ["byteOffset"]
        },
        {
          "type": "array",
          "items": {
            "type": "number"
          },
          "minItems": 1,
          "maxItems": 1
        },
        {
          "type": "number",
          "minimum": 0
        }
      ]
    },
    "globalPropertyCartesian3": {
      "title": "GlobalPropertyCartesian3",
      "description": "An object defining a global 3-component numeric property values for all features.",
      "oneOf": [
        {
          "type": "object",
          "properties": {
            "byteOffset": {
              "type": "number",
              "description": "The offset into the buffer in bytes.",
              "minimum": 0
            }
          },
          "required": ["byteOffset"]
        },
        {
          "type": "array",
          "items": {
            "type": "number"
          },
          "minItems": 3,
          "maxItems": 3
        }
      ]
    },
    "globalPropertyCartesian4": {
      "title": "GlobalPropertyCartesian4",
      "description": "An object defining a global 4-component numeric property values for all features.",
      "oneOf": [
        {
          "type": "object",
          "properties": {
            "byteOffset": {
              "type": "number",
              "description": "The offset into the buffer in bytes.",
              "minimum": 0
            }
          },
          "required": ["byteOffset"]
        },
        {
          "type": "array",
          "items": {
            "type": "number"
          },
          "minItems": 4,
          "maxItems": 4
        }
      ]
    }
  },
  "properties": {
    "extensions": {
      "$ref": "extension.schema.json"
    },
    "extras": {
      "$ref": "extras.schema.json"
    }
  },
  "additionalProperties": {
    "$ref": "#/definitions/property"
  }
}

版权声明:
除非注明,本博文章均为原创,转载请以链接形式标明本文地址。



   转载规则


《3D Tiles点云(Point Cloud)数据格式标准规范》 Jackie Tang(唐浩桀) 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
3D Tiles复合对象(Composite)数据格式标准规范 3D Tiles复合对象(Composite)数据格式标准规范
导航 引 概述 文件结构 结构填充 文件头 内部瓦片 文件扩展名和 MIME 类型 实现示例 引官网文档 概述复合对象格式允许拼接的不同格式的数据变成一个区块。 3D 瓦片和复合对象瓦片为流式异构数据集提供了灵活性
下一篇 
3D Tiles实例3D模型(Instanced 3D Model)数据格式标准规范 3D Tiles实例3D模型(Instanced 3D Model)数据格式标准规范
导航 引 概述 文件结构 结构填充 文件头 要素表 语法定义 实例语法 全局语法 实例方向 八进制编码的法向向量 默认方向 实例位置 RTC_CENTER 量化位置 实例缩放 例子 仅位置 量化位置和八进
  目录