带有纹理坐标的 PLY 文件规范

Posted

技术标签:

【中文标题】带有纹理坐标的 PLY 文件规范【英文标题】:PLY file specifications with texture coordinates 【发布时间】:2015-04-12 01:54:00 【问题描述】:

出于某种目的,我需要读取带有嵌入纹理的 PLY 文件(斯坦福三角格式)。我看到了 PLY 文件的多个规范,但找不到指定纹理映射语法的单一来源。似乎有很多库可以读取 PLY 文件,但其中大多数似乎不支持纹理(它们只是崩溃;我尝试了其中的 2-3 个)。 以下是带有纹理的层文件的标题:

ply
format binary_little_endian 1.0
comment TextureFile Parameterization.png
element vertex 50383               
property float x
property float y
property float z
property float nx
property float ny
property float nz
element face 99994               
property list uint8 int32 vertex_index
property list uint8 float texcoord
end_header

我不明白的是property list uint8 float texcoord 这一行。与人脸对应的列表也是

3 1247 1257 1279 6 0.09163 0.565323 0.109197 0.565733 0.10888 0.602539 6 9 0.992157 0.992157 0.992157 0.992157 0.992157 0.992157 0.992157 0.992157 0.992157`. 

这个列表是什么;格式是什么?虽然我知道 PLY 让您有机会为元素定义自己的属性,但处理纹理似乎几乎是一种标准,并且相当多的应用程序(如流行的 Meshlab)似乎使用上述语法打开带纹理的 PLY 文件.

我想知道读取带纹理的 PLY 文件所遵循的标准语法是什么,如果可能的话,我想知道该信息的来源。

【问题讨论】:

【参考方案1】:

在 PLY 文件中,面通常包含值列表,这些列表的大小可能不同。如果它是三角形面,则期望三个值,四边形 = 4 等等,直到任意 n 边形。列表在这样的一行中声明:

property list uint8 int32 vertex_index

这是一个名为“vertex_index”的列表。它总是包含一个大小为 N 的 8 位无符号整数(即 uint8),后跟 N 个 32 位整数(即 int32)。

在示例行中立即显示:

3 1247 1257 1279

这就是说,这里有 3 个值,然后它给你三个值。

现在第二个列表是纹理坐标的位置:

property list uint8 float texcoord

就像第一个列表一样,大小排在第一位(作为无符号字节),但这次它后面是一系列 32 位浮点数而不是整数(对于纹理坐标有意义)。简单的解释是 vertex_index 中列出的每个顶点都有一个纹理坐标。如果我们假设这些只是 2d 纹理坐标(一个非常安全的假设),我们应该期望看到数字 6 后跟 6 个浮点值......我们做到了:

6 0.09163 0.565323 0.109197 0.565733 0.10888 0.602539

这些是与已经列出的三个顶点对应的纹理坐标。

现在,对于一张脸,应该就是这样。我不知道线路的其余部分是什么东西。根据您的标题,文件的其余部分应该是二进制的,所以我不知道您是如何将它作为一行 ascii 文本获得的,但该行上的额外数据不应该存在(也根据完全定义的标题脸)。

【讨论】:

感谢您的回答,但问题在于解释整个字符串 3 1247 1257 1279 6 0.09163 0.565323 0.109197 0.565733 0.10888 0.602539 6 9 0.992157 0.992157 0.992157 0.992157 0.992157 0.992157 0.992157 0.992157 0.992157 而不仅仅是其中的一半。我了解到的是,PLY 没有“严格”的规则,实际上您可以定义自己的规则并对其进行解释——这就是 PLY 的全部理念。这就是为什么一个软件编写的 txt 坐标可能与其他软件不同的原因。 好吧,最终我的回答是这个字符串不是正确的 PLY 行。它违反了标头设置的规则。 PLY 文件是独立的。标题描述了您应该在每一行中预期的数据,然后是后面的行。您显示的行包含的数据比标题显示的要多。【参考方案2】:

让我添加到@OllieBrown 的回复中,作为任何遇到此问题的人的进一步信息,上面的格式使用每面纹理坐标,也称为楔形 UV。这意味着,如果您共享顶点,则共享顶点(基本上是多个相邻三角形中使用的顶点索引)有可能可能根据它参与的三角形具有不同的 UV当顶点位于 UV 接缝上或 UV 与纹理边界相交时,通常会发生这种情况。通常这意味着复制顶点,因为 GPU 需要每个顶点的属性。所以一个共享的顶点最终是 X 顶点在空间中重叠(其中 X 是它们共享的三角形的数量),但是根据它们参与的三角形具有不同的 UV。将这样的数据保存在磁盘上的一个优点是由于这是一种文本格式,它减少了您需要的文本量,因此减小了磁盘大小。 OBJ 也有这一点,尽管它保留一个平面 UV 数组并使用对该数组的索引,而不管它是每个顶点还是每个面的 UV。

我也无法弄清楚 6 9 <9*0.992157> 部分是什么(虽然 9 部分看起来像是 3 个 vector3s,它们对所有 3 个轴具有相同的值),但 Paul Bourke 的代码 here 有 setup_other_props 的描述功能:

/******************************************************************************
Make ready for "other" properties of an element-- those properties that
the user has not explicitly asked for, but that are to be stashed away
in a special structure to be carried along with the element's other
information.

Entry:
  plyfile - file identifier
  elem    - element for which we want to save away other properties
******************************************************************************/

void setup_other_props(PlyFile *plyfile, PlyElement *elem)

据我了解,每个元素都可以保留不属于标题的数据。这些数据应该被保留和存储,但不会被解释为在每个应用程序中使用。 Bourke 对格式的描述谈到了与旧软件的向后兼容性,因此这可能是一种自定义格式,只有某些应用程序可以理解,但额外信息不应妨碍不需要它们的旧应用程序理解和/或渲染内容。

【讨论】:

以上是关于带有纹理坐标的 PLY 文件规范的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 LMV Toolkit 规范或 Autodesk 材质库材质显示非光照材质 + 纹理?

CocoaPods:带有子规范的规范 lint 丢弃了父规范?

我的渲染技术进阶之旅关于ARCore的标准人脸3D模型canonical_face_mesh.fbx和2D面部网格参考纹理canonical_face_mesh.psd文件

我的渲染技术进阶之旅关于ARCore的标准人脸3D模型canonical_face_mesh.fbx和2D面部网格参考纹理canonical_face_mesh.psd文件

使用带有纹理分析和 (x,y) 坐标的 K-means 进行图像分割

QML加载并显示带有颜色属性的.ply网格