将 OBJ 文件中的四边形转换为三角形?

2022-09-03 06:22:48

起初,这似乎是显而易见的...在找到4个索引的地方,每张脸做2个三角形,对吧?
意思是,以下内容:

v 1.000000 1.000000 0.000000
v -1.000000 1.000000 -0.000000
v 1.000000 -1.000000 0.000000
v -1.000000 -1.000000 -0.000000
f -4 -3 -2 -1

...反过来,需要转换为如下内容:

v 1.000000 1.000000 0.000000
v -1.000000 1.000000 -0.000000
v 1.000000 -1.000000 0.000000
v -1.000000 -1.000000 -0.000000
f -4 -3 -2
f -2 -3 -1

当然,这个特定的例子会正确呈现。
但是,并非所有情况都像将面拆分为两个面(如上例所示,第一个面包含原始面的前三个顶点,第二个面包含最后 3 个顶点)那么简单。以以下多维数据集为例:

v 0.000000 1.000000 1.000000
v 0.000000 0.000000 1.000000
v 1.000000 0.000000 1.000000
v 1.000000 1.000000 1.000000
v 0.000000 1.000000 0.000000
v 0.000000 0.000000 0.000000
v 1.000000 0.000000 0.000000
v 1.000000 1.000000 0.000000
f 1 2 3 4
f 8 7 6 5
f 4 3 7 8
f 5 1 4 8
f 5 6 2 1
f 2 6 7 3

这些面孔不能以与上一示例中相同的方式拆分...因此,我需要一些方法来了解如何将四边形面分成两个三角形面,同时为第二个面使用正确的索引......

如何实现这一点?请注意,我没有使用固定函数管道,因此,使用GL_QUADS不是一个选项。我的渲染引擎几乎只使用GL_TRIANGLES。


答案 1

如果您有 4 个索引,例如:

0 1 2 3

分成两个三角形,一个三角形包含前 3 个索引,另一个包含第一个、第三个和第四个索引。在此示例中:

0 1 2
0 2 3

让我们尝试一些 ASCII 艺术来说明这一点:

3-------2
|      /|
|    /  |
|  /    |
|/      |
0-------1

在这里,您可以看到四边形,第一个三角形(右下角)和第二个三角形(左上角)。0 1 2 30 1 20 2 3

更一般地说,对于具有顶点的面,您可以生成三角形:n

0 (i) (i + 1)  [for i in 1..(n - 2)]

如果你不坚持使用单独的三角形,你也可以使用基元,它们仍然在核心OpenGL中。这样,您就可以使用原始索引序列绘制任何带有三角形扇的凸多边形。因此,在这种情况下,具有顶点序列的三角形扇形描述了四边形,并且它很容易推广到具有4个以上顶点的面。GL_TRIANGLE_FAN0 1 2 3

编辑:由于您似乎仍有问题,让我们看看这如何适用于您帖子中的示例。我将列出每张面的四边形的原始索引序列,以及拆分四边形后两个三角形的索引序列。

f 1 2 3 4 --> (1 2 3) (1 3 4)
f 8 7 6 5 --> (8 7 6) (8 6 5)
f 4 3 7 8 --> (4 3 7) (4 7 8)
f 5 1 4 8 --> (5 1 4) (5 4 8)
f 5 6 2 1 --> (5 6 2) (5 2 1)
f 2 6 7 3 --> (2 6 7) (2 7 3)

当我画立方体时,这对我来说是正确的。请记住从索引中减去 1 以供使用,因为这些是基于 1 的索引,并且您几乎肯定需要基于 0 的索引。


答案 2

编写我自己的obj加载器并非常仔细地阅读规范,“f”参数上的细节非常模糊,特别是看到一些文件包含带有>4个参数的“f”行。

事实证明,这些实际上是一个奇怪的三角形条带。正确转换为三角形如下(伪代码):

n = 0;
triangles[n++] = [values[0], values[1], values[2]];
for(i = 3; i < count(values); ++i)
  triangles[n++] = [
    values[i - 3],
    values[i - 1],
    values[i]
  ];

例:

f: A B C D E F G

将是以下 5 个三角形:

A B C
A C D
B D E
C E F
D F G

推荐