摘要(直接回答)
PLY 文件格式(Polygon File Format,也称为斯坦福三角形格式)是一种单对象三维数据格式,将几何体存储为一组元素(如顶点和面),并带有带有类型属性(如坐标、法线或颜色),这些属性由 ASCII 头部声明,定义了后续数据的模式。[1] PLY 有两个子格式——ASCII 和二进制——通常使用带有 、 或 的头部行。[1][4]format ... 1.0asciibinary_little_endianbinary_big_endian

历史背景
规范的“PLY 多边形文件格式”规范归功于 Greg Turk,版权归属于 (c) 1994。[1] 在规范中,该格式被呈现为一个直接、带有头部描述的多边形数据(及其他元素/属性记录)容器,而非完整的场景交换语言。[1]
当代摘要将PLY定位为起源于学术图形工作流程的格式,并在数字保存领域中也被广泛认可。[2] 佐治亚理工学院关于大型3D模型的档案页面指出,该格式的早期版本曾被斯坦福大学和北卡罗来纳大学教堂山分校使用,并将文件描述为一个头部,后面跟随包括顶点和多边形在内的列表。[3]
PLY格式所代表的意义(概念模型)
PLY 恰好将一个对象表示为元素集合,每个元素有固定数量的记录,每条记录是一组声明的属性,具有指定的标量或列表类型。[1] 实际上,“网格PLY”通常指包含和元素的文件,而“点云PLY”通常只定义一个元素(以及可能额外的每个顶点属性),但这些都是使用模式,而非单独的格式修订。[1] 原始规范明确将 PLY 定义为非通用场景描述语言,排除变换矩阵和层级等结构,这限制了其作用于对象级交换,而非场景图。[1]vertexfacevertex
文件布局概述(元素列表→头部)
PLY 文件由一个 ASCII 头部组成,后面是元素数据,每个元素以一个连续列表的形式编写,顺序与声明在首部出现的顺序相同。[1] 头部声明每个元素的名称和记录数量,然后声明该元素的每个属性,结尾为 。[1]elementend_header
无论是机构描述还是学术描述,都强调这种两部分布局(先是头部,然后是数据列表)。[2][3] 佐治亚理工学院的概述进一步将常见情况描述为“一个头部后面跟一个顶点列表和一个多边形列表”,这与当时网格通常使用的排序方式相符。[3]vertexface
头部语法与必需令牌
原始规范定义了严格的头部前言和基于关键词的语法:起始字符串必须是文件的前四个字符,作为一个魔术数字,头部行是以回车结束的 ASCII 字符串。[1] 头部通过一行声明数据编码和版本(版本通常写为),每个元素用 声明,用一行或多行声明元素属性,允许以 开头的关键词标识注释行,并以 结束头部,之后数据部分开始并根据声明的模式进行解释。[1][4] 一个最小的原理图式头部示例(为便于阅读而显示的换行符)是:,其中 是头部中声明的顶点记录计数。[1]ply<cr>format <data format> <PLY version>1.0element <name> <number-in-file>property ...commentend_header⏎ply⏎ format ascii 1.0⏎ element vertex <N>⏎ property float x⏎ property float y⏎ property float z⏎ end_header⏎<N>
头部关键词及其作用
ply:将文件标识为PLY,并且必须以魔法数开头。[1]ply<cr>format: 声明正体编码和 PLY 版本,使用 。[1][4]format <data format> <PLY version>element: 声明元素名称及其在数据部分中的记录数量。[1]property: 声明属于最近声明元素的类型属性,定义每条记录字段。[1]comment: 在头部引入一条注释行,由前置关键词标识。[1]commentend_header: 标记头部结束和数据部分的开始。[1]
编码变体(ASCII 与二进制;恩迪安性)
PLY 规范定义了两种子格式:ASCII 表示和二进制表示。[1] 在这两种情况下,头部都是ASCII,开头是ASCII字符串,后面是回车作为文件标识符,而数据部分的解释由行控制。[2]plyformat
实现文档通常认可三个版本的标记:、、和。[4] 二进制变体在编码多字节标量值时使用指示的字节顺序(端序性),而 ASCII 则将数字值编码为可读文本;因此,当需要更快的输入输出和较小的文件时,通常会使用二进制形式,而当优先进行人工检查和临时编辑时,则常使用ASCII。[1][4]format1.0asciibinary_little_endianbinary_big_endian
标量数据类型(可移植性约束)
原始规范定义了一组固定的标量属性类型,字节大小固定:(1)、(1)、(2)、(2)、(4)、(4)、(4)和(8)。[1] 它还规定了可移植性限制:如果文件要保持可移植性,这些大小不能在不同实现间变化,这意味着读者和写者必须将 PLY 类型名称视为规范级别类型,而非语言原生类型,其大小可能因平台或编译器而异。[1]charucharshortushortintuintfloatdouble
| PLY标量类型名称 | 字节 | 便携性说明 |
|---|---|---|
| char,uchar | 1. [1] | 规范中为固定尺寸;实现不应替代平台依赖类型。[1] |
| short,ushort | 2. [1] | 多字节标量必须遵循二进制编码中宣告的端序。[1][4] |
| int, ,uintfloat | 4. [1] | 尺寸是便携性的标准;不匹配打破二元交换。[1] |
| double | 8. [1] | 写入器应准确输出指定的宽度,而不是不同尺寸的“原生”浮动类型。[1] |

列表属性(面和其他可变长度记录)
除了固定宽度的标量属性外,PLY 还支持通过列表属性在元素记录中实现可变长度的数据。[1] 列表属性语法在头部声明为 ,第一个数值类型指定用于存储列表长度(计数)的标量类型,第二个数字类型指定每个列表条目的标量类型。[1] 在数据部分,每个列表实例被编码为计数值,后面是相应数量的标量条目,根据两种声明的类型进行解释。[1]property list <numerical-type> <numerical-type> <property-name>
这种机制常用于将多边形面表示为顶点数组中的索引列表。[1] 规范中的示例面编码表示无符号字符计数,后跟同数量的整数索引,每个索引引用一个顶点记录。[1] 佐治亚理工对该格式的描述以更简单的方式证实了相同的概念规则:在多边形列表中,每个面以计数开头,后面跟着相应数量的索引。[3] 由于计数是按面记录存储的,同一元素可以自然地在一个文件中包含三角形、四边形和高阶多边形,而无需更改元素模式。[1]property list uchar int vertex_indicesface
共同元素与性质(事实上的惯例)
规范展示了(但不强制)常见元素名称,如 、 、 和 ,并展示了属性与这些元素的关联。[1] 同样,常见的属性名称如坐标、、、、以及每个顶点颜色,应被视为基于实例和广泛实践的事实惯例,而非语法的强制要求。[1] 面向实现的文档同样展示了典型的网格导向用例,包含带有记录的面列表属性,如 ,作为头部定义模式在实际应用中的示例。[4]vertexfaceedgexyzredgreenbluevertexfacevertex_indices
非目标与已知限制
在原始规范中,PLY明确说明不打算成为通用场景描述语言,文档列举了遗漏的建模和场景构造,包括变换矩阵、实例化和层级关系。[1] 该设计将PLY定位为单一物体几何体及相关每个元素属性的交换机制,而非带有可复用子对象的结构化场景图。[1]
以保存为重点的描述同样将PLY定位为多边形模型(及密切相关的元素/属性记录),而非完整的外观和场景语义。[2] 在实际互操作性方面,缺乏标准化的场景级构造意味着需要多个对象、对象变换或更丰富材质/纹理行为的工作流程通常会在外部容器中叠加 PLY,或采用规范中包含此类构造的不同格式。[1][2]
互操作性陷阱(真实管道中出现的问题)
PLY 的“头部模式”方法实现了可扩展性,因为元素和属性声明可以由编写者定义,但这也将互操作性风险转移到命名、类型和严格解析。[1] 假设传统属性名称(例如,期望或)的读者可能无法导入使用不同名称的语义等价文件,尽管语法允许任意元素/属性标识符。[1] 在字节层面,严格遵守规范中固定的标量大小对于二进制可移植性至关重要,声明的大小与实际大小不匹配(或 / 与发射字节顺序不匹配)可能导致无声误读而非硬性失败。[1][4] 另一个反复出现的问题是头部的换行处理:规范定义了以回车为终结的ASCII头行,并且要求在文件开头,因此那些不加注意地规范行尾的实现,即使文件本身结构良好,也可能与严格读者产生分歧。[1]x y zvertex_indicesbinary_little_endianbinary_big_endianply<cr>
对比表(必备)
PLY 通常与多边形-网格交换格式(如 OBJ 和 STL)以及以点云为中心的格式如 PCD 进行比较,主要在模式扩展性、编码变体以及格式是否作为对象文件或更广泛的场景容器进行作用域方面进行比较。[1][2]
| 节目形式 | 典型内容重点 | 可扩展的每个顶点/每个点场 | 编码与作用域注释 |
|---|---|---|---|
| PLY | 单一对象被描述为具有属性(通常为顶点和面)的元素。[1] | 是的;任意元素和属性可以在头部声明。[1] | ASCII或二进制;二进制支持小端序/大端序,PLY也不是通用的场景描述语言。[1][4] |
| OBJ | 基于文本的几何交换,常用于多边形网格。[5] | 有限;属性通过预定义的记录类型表示,而非任意类型的属性。[5] | 主要是ASCII;可以引用不同的MTL材料文件,并且可以在一个文件中表示多个命名对象/组。[5] |
| 圣路易斯 | 用于制造导向工作流程的三角化曲面几何。[6] | 没有标准化的任意顶点属性模式。[6] | 定义于ASCII及二进制变体中;通常被视为无场景结构的单部分表面网格。[6] |
| PCD | 点云存储,带有标题字段描述。[7] | 是的;点字段在头部声明(字段名称和类型)。[7] | 支持PCL文档中描述的ASCII和二进制存储模式;以点云为中心,而非多边形面。[7] |
在这些格式中,PLY 和 PCD 的相似之处在于都使用一个头来声明后续记录的解释方式,支持添加字段而无需修改核心语法。[1][7] OBJ和STL则强调广泛理解的相对固定记录结构,当只需传统网格数据时可以简化交换,但当管道需要每个顶点类型化的元数据(如任意传感器属性或自定义标签)时,可能会受到限制。[5][6]
实用解析检查表(实现无关)
稳健的 PLY 解析将头部视为模式定义,然后根据声明的格式、元素计数和属性类型(包括列表属性计数和有效载荷语义)流式传输正文。[1] 原始规范中固定的标量类型集合(字节大小固定)为解码ASCII和二进制身体提供了规范基础,而必需的关键词(, , , , 和)则定义了读取器在解释数据记录前应验证的最小结构。[1][2]plyformatelementpropertyend_header
解析检查表
- 验证文件前四个字符以魔法数字开头。[1]
ply<cr> - 将头部行读取为包含 的 ASCII 关键词记录,仅将注释视为以 开头的行。[1]
end_headercomment - 解析该行,并选择对应的解码器(、 、 或 )。[1][4]
format <data format> <PLY version>asciibinary_little_endianbinary_big_endian - 对于每个 ,存储元素名称、声明记录计数及其声明的有序列表。[1]
element <name> <number-in-file>property - 对于每个标量,将PLY类型映射到规范定义的固定字节大小和数值解释,拒绝未知标量类型。[1]
property <type> <name> - 对于每个列表,将每条记录解码为计数,后面是相应数量的项,使用声明的标量类型。[1]
property list <count-type> <item-type> <name> - 逐元素、逐条记录流式传输正体,按标题中元素声明的顺序,确保读取记录数量与每个元素声明的计数一致。[1]
- 将缺失、记录数量不一致或类型大小不匹配视为硬性错误,因为它们使正文变得模糊或不可移植。[1]
end_header
