典型的 PLY 文件结构:
头部
顶点列表
面片列表
(其他元素列表)
头部是一系列以回车结尾的文本行,用来描述文件的剩余部分。头部包含一个对每个元素类型的描述,包括元素名(如“边”),这个元素在工程里有多少,以及一 个与这个元素关联的不同属性的列表。头部还说明这个文件是二进制的或者是ASCII的。头部后面的是一个每个元素类型的元素列表,按照在头部中描述的顺序 出现。
下面是一个立方体的完整ASCII描述。相同工程的二进制版本头部的唯一不同是用词“binary_little_endian”或者 “binary_big_endian”替换词“ascii”。大括号中的注释不是文件的一部分,它们是这个例子的注解。文件中的注释一般在 “comment”开始的关键词定义行里。
ply
format ascii 1.0 { ascii/二进制,格式版本数 }
comment made by anonymous { 注释关键词说明,像其他行一样 }
comment this file is a cube
element vertex 8 { 定义“vertex”(顶点)元素,在文件中有8个 }
property float32 x { 顶点包含浮点坐标“x”}
property float32 y { y 坐标同样是一个顶点属性 }
property float32 z { z 也是坐标 }
element face 6 { 在文件里有6个“face”(面片) }
property list uint8 int32 vertex_index { “vertex_indices”(顶点素引)是一列整数 }
end_header { 划定头部结尾 }
0 0 0 { 顶点列表的开始 }
0 0 1
0 1 1
0 1 0
1 0 0
1 0 1
1 1 1
1 1 0
4 0 1 2 3 { 面片列表开始 }
4 7 6 5 4
4 0 4 5 1
4 1 5 6 2
4 2 6 7 3
4 3 7 4 0
这个例子说明头部的基本组成。头部的每个部分都是以一个关键词开头以回车结尾的ASCII串。即使是头部的开始和结尾(“ply”和 “end_header”)也是以这种形式。因为字符“ply”是文件的魔法数字,必须是文件的头四个字符。跟在文件头部开头之后的是关键词 “format”和一个特定的ASCII或者二进制的格式,接下来是一个版本号。再下面是多边形文件中每个元素的描述,在每个元素里还有多属性的说明。一 般元素以下面的格式描述:
element <元素名> <在文件中的个数>
property <数据类型> <属性名-1>
property <数据类型> <属性名-2>
property <数据类型> <属性名-3>
...
属性罗列在“element”(元素)行后面定义,既包含属性的数据类型也包含属性在每个元素中出现的次序。一个属性可以有三种数据类型:标量,字符串和列表。属性可能具有的标量数据类型列表如下:
名称 类型 字节数
-------------------------------
int8 字符 1
uint8 非负字符 1
int16 短整型 2
uint16 非负短整型 2
int32 整型 4
uint32 非负整型 4
float32 单精度浮点数 4
float64 双精度浮点数 8
这些字节计数很重要,而且在实现过程中不能修改以使这些文件可移植。使用列表数据类型的属性定义有一种特殊的格式:
property list <数值类型> <数值类型> <属性名>
这种格式的一类例子是上面的立方体文件中的:
property list uint8 int32 vertex_index
这表示属性“vertex_index”首先包含一个非负字符报苏在属性里包含多少索引,接下来是一个列表包含许多整数。在这个边长列表里的每个整数都是一个顶点的索引。
另外一个例子
------------
另外一个立方体定义:
ply
format ascii 1.0
comment author: anonymous
comment object: another cube
element vertex 8
property float32 x
property float32 y
property float32 z
property red uint8 { 顶点颜色开始 }
property green uint8
property blue uint8
element face 7
property list uint8 int32 vertex_index { 每个面片的顶点个数 }
element edge 5 { 物体里有5条边 }
property int32 vertex1 { 边的第一个顶点的索引 }
property int32 vertex2 { 第二个顶点的索引 }
property uint8 red { 边颜色开始 }
property uint8 green
property uint8 blue
end_header
0 0 0 255 0 0 { 顶点列表开始 }
0 0 1 255 0 0
0 1 1 255 0 0
0 1 0 255 0 0
1 0 0 0 0 255
1 0 1 0 0 255
1 1 1 0 0 255
1 1 0 0 0 255
3 0 1 2 { 面片列表开始,从一个三角形开始 }
3 0 2 3 { 另一个三角形 }
4 7 6 5 4 { 现在是一些四边形 }
4 0 4 5 1
4 1 5 6 2
4 2 6 7 3
4 3 7 4 0
0 1 255 255 255 { 边列表开始,从白边开始 }
1 2 255 255 255
2 3 255 255 255
3 0 255 255 255
2 0 0 0 0 { 以一个黑线结束 }
这个文件为每个顶点指定一个红、绿、蓝值。为了说明变长vertex_index(顶点索引)的能力,物体的头两个面片是两个三角形而不是一个四边形。这 意味着物体的面片数是7。这个物体还包括一个边列表。每条边包括两个指向说明边的顶点的指针。每条边也有一种颜色。上面定义的五条边指定了颜色,使文件里 的两个三角形高亮。前四条边白色,它们包围两个三角形。最后一条边是黑的,他是分割三角形的边。
用户定义元素
------------
上面的例子显示了顶点、面片和边三种元素的用法。PLY 格式同样允许用户定义它们自己的元素。定义新元素的格式于顶点、面片和边相同。这是头部定义材料属性的部分:
element material 6
property ambient_red uint8 { 环绕颜色 }
property ambient_green uint8
property ambient_blue uint8
property ambient_coeff float32
property diffuse_red uint8 { 扩散(diffuse)颜色 }
property diffuse_green uint8
property diffuse_blue uint8
property diffuse_coeff float32
property specular_red uint8 { 镜面(specular)颜色 }
property specular_green uint8
property specular_blue uint8
property specular_coeff float32
property specular_power float32 { Phong 指数 }
这些行应该在头部顶点、面片和边的说明后直接出现。如果我们希望每个顶点有一个材质说明,我们可以将这行加在顶点属性末尾:
property material_index int32
这个整数现在是一个到文件内包含的材质列表的索引。这可能诱使一个新应用的作者编制一些信的元素保存在 PLY 文件中。这个练习应该保持在最小。试着将普通元素(顶点、面片、边、材质)改编用于新用途更好,使得其他能够读懂这些元素的程序在操作这些改编过的元素时 更有用。比如,一个将分子描述成球体和圆柱体集合的应用。这将需要在包含分子的 PLY 文件里定义球体和圆柱体元素。然而,如果我们为了这个目的使用顶点和边元素(为每个添加半径属性),我们可以利用操作和显示顶点和边的程序。无疑不应该为 三角形和四边形创建特殊元素,而应该使用面片元素。
头部
顶点列表
面片列表
(其他元素列表)
头部是一系列以回车结尾的文本行,用来描述文件的剩余部分。头部包含一个对每个元素类型的描述,包括元素名(如“边”),这个元素在工程里有多少,以及一 个与这个元素关联的不同属性的列表。头部还说明这个文件是二进制的或者是ASCII的。头部后面的是一个每个元素类型的元素列表,按照在头部中描述的顺序 出现。
下面是一个立方体的完整ASCII描述。相同工程的二进制版本头部的唯一不同是用词“binary_little_endian”或者 “binary_big_endian”替换词“ascii”。大括号中的注释不是文件的一部分,它们是这个例子的注解。文件中的注释一般在 “comment”开始的关键词定义行里。
ply
format ascii 1.0 { ascii/二进制,格式版本数 }
comment made by anonymous { 注释关键词说明,像其他行一样 }
comment this file is a cube
element vertex 8 { 定义“vertex”(顶点)元素,在文件中有8个 }
property float32 x { 顶点包含浮点坐标“x”}
property float32 y { y 坐标同样是一个顶点属性 }
property float32 z { z 也是坐标 }
element face 6 { 在文件里有6个“face”(面片) }
property list uint8 int32 vertex_index { “vertex_indices”(顶点素引)是一列整数 }
end_header { 划定头部结尾 }
0 0 0 { 顶点列表的开始 }
0 0 1
0 1 1
0 1 0
1 0 0
1 0 1
1 1 1
1 1 0
4 0 1 2 3 { 面片列表开始 }
4 7 6 5 4
4 0 4 5 1
4 1 5 6 2
4 2 6 7 3
4 3 7 4 0
这个例子说明头部的基本组成。头部的每个部分都是以一个关键词开头以回车结尾的ASCII串。即使是头部的开始和结尾(“ply”和 “end_header”)也是以这种形式。因为字符“ply”是文件的魔法数字,必须是文件的头四个字符。跟在文件头部开头之后的是关键词 “format”和一个特定的ASCII或者二进制的格式,接下来是一个版本号。再下面是多边形文件中每个元素的描述,在每个元素里还有多属性的说明。一 般元素以下面的格式描述:
element <元素名> <在文件中的个数>
property <数据类型> <属性名-1>
property <数据类型> <属性名-2>
property <数据类型> <属性名-3>
...
属性罗列在“element”(元素)行后面定义,既包含属性的数据类型也包含属性在每个元素中出现的次序。一个属性可以有三种数据类型:标量,字符串和列表。属性可能具有的标量数据类型列表如下:
名称 类型 字节数
-------------------------------
int8 字符 1
uint8 非负字符 1
int16 短整型 2
uint16 非负短整型 2
int32 整型 4
uint32 非负整型 4
float32 单精度浮点数 4
float64 双精度浮点数 8
这些字节计数很重要,而且在实现过程中不能修改以使这些文件可移植。使用列表数据类型的属性定义有一种特殊的格式:
property list <数值类型> <数值类型> <属性名>
这种格式的一类例子是上面的立方体文件中的:
property list uint8 int32 vertex_index
这表示属性“vertex_index”首先包含一个非负字符报苏在属性里包含多少索引,接下来是一个列表包含许多整数。在这个边长列表里的每个整数都是一个顶点的索引。
另外一个例子
------------
另外一个立方体定义:
ply
format ascii 1.0
comment author: anonymous
comment object: another cube
element vertex 8
property float32 x
property float32 y
property float32 z
property red uint8 { 顶点颜色开始 }
property green uint8
property blue uint8
element face 7
property list uint8 int32 vertex_index { 每个面片的顶点个数 }
element edge 5 { 物体里有5条边 }
property int32 vertex1 { 边的第一个顶点的索引 }
property int32 vertex2 { 第二个顶点的索引 }
property uint8 red { 边颜色开始 }
property uint8 green
property uint8 blue
end_header
0 0 0 255 0 0 { 顶点列表开始 }
0 0 1 255 0 0
0 1 1 255 0 0
0 1 0 255 0 0
1 0 0 0 0 255
1 0 1 0 0 255
1 1 1 0 0 255
1 1 0 0 0 255
3 0 1 2 { 面片列表开始,从一个三角形开始 }
3 0 2 3 { 另一个三角形 }
4 7 6 5 4 { 现在是一些四边形 }
4 0 4 5 1
4 1 5 6 2
4 2 6 7 3
4 3 7 4 0
0 1 255 255 255 { 边列表开始,从白边开始 }
1 2 255 255 255
2 3 255 255 255
3 0 255 255 255
2 0 0 0 0 { 以一个黑线结束 }
这个文件为每个顶点指定一个红、绿、蓝值。为了说明变长vertex_index(顶点索引)的能力,物体的头两个面片是两个三角形而不是一个四边形。这 意味着物体的面片数是7。这个物体还包括一个边列表。每条边包括两个指向说明边的顶点的指针。每条边也有一种颜色。上面定义的五条边指定了颜色,使文件里 的两个三角形高亮。前四条边白色,它们包围两个三角形。最后一条边是黑的,他是分割三角形的边。
用户定义元素
------------
上面的例子显示了顶点、面片和边三种元素的用法。PLY 格式同样允许用户定义它们自己的元素。定义新元素的格式于顶点、面片和边相同。这是头部定义材料属性的部分:
element material 6
property ambient_red uint8 { 环绕颜色 }
property ambient_green uint8
property ambient_blue uint8
property ambient_coeff float32
property diffuse_red uint8 { 扩散(diffuse)颜色 }
property diffuse_green uint8
property diffuse_blue uint8
property diffuse_coeff float32
property specular_red uint8 { 镜面(specular)颜色 }
property specular_green uint8
property specular_blue uint8
property specular_coeff float32
property specular_power float32 { Phong 指数 }
这些行应该在头部顶点、面片和边的说明后直接出现。如果我们希望每个顶点有一个材质说明,我们可以将这行加在顶点属性末尾:
property material_index int32
这个整数现在是一个到文件内包含的材质列表的索引。这可能诱使一个新应用的作者编制一些信的元素保存在 PLY 文件中。这个练习应该保持在最小。试着将普通元素(顶点、面片、边、材质)改编用于新用途更好,使得其他能够读懂这些元素的程序在操作这些改编过的元素时 更有用。比如,一个将分子描述成球体和圆柱体集合的应用。这将需要在包含分子的 PLY 文件里定义球体和圆柱体元素。然而,如果我们为了这个目的使用顶点和边元素(为每个添加半径属性),我们可以利用操作和显示顶点和边的程序。无疑不应该为 三角形和四边形创建特殊元素,而应该使用面片元素。