.obj 文件中的面孔是什么以及它们如何工作?

问题描述 投票:0回答:1

我有this .obj 文件。这是 Mini-Cooper 的模型。我将所有顶点和面提取到如下所示的列表中:

vertices = [(14.82, -22.56, 25.83), (25.38, 29.02, 15.87), (-31.71, -57.05, 19.29), (-27.95, 46.76, 17.98), (-25.44, 47.58, 3.38), (33.63, 48.57, 7.97), (-30.81, 32.23, 22.08), (-14.13, 29.34, 27.43), (3.94, 47.76, 52.66), (25.38, -69.78, 16.93), (29.55, 4.96, 38.49), (33.31, 42.57, 13.42), (27.8, 8.16, 38.6), (-26.77, 46.93, 2.27), (-30.21, -80.45, 24.88), (-33.48, 40.09, 23.68), (33.29, 51.84, 13.67), (-9.08, 67.39, 17.91), (25.27, 31.68, 5.62), (-30.2, -36.77, 39.17)]

faces = [('1962/1/1962', '1958/1/1958', '1957/541/1957'), ('1957/541/1957', '1961/541/1961', '1962/1/1962'), ('1960/3202/1960', '1959/542/1959', '1963/542/1963'), ('1963/542/1963', '1964/3202/1964', '1960/3202/1960'), ('1966/543/1966', '1962/1/1962', '1961/541/1961'), ('1961/541/1961', '1965/544/1965', '1966/543/1966'), ('1964/3202/1964', '1963/542/1963', '1967/546/1967'), ('1967/546/1967', '1968/545/1968', '1964/3202/1964'), ('1970/543/1970', '1966/543/1966', '1965/544/1965'), ('1965/544/1965', '1969/544/1969', '1970/543/1970'), ('1968/545/1968', '1967/546/1967', '1971/546/1971'), ('1971/546/1971', '1972/545/1972', '1968/545/1968'), ('1985/547/1985', '1970/543/1970', '1969/544/1969'), ('1969/544/1969', '1984/550/1984', '1985/547/1985'), ('1993/551/1993', '1961/541/1961', '1957/541/1957'), ('1957/541/1957', '1991/551/1991', '1993/551/1993'), ('1958/1/1958', '1962/1/1962', '1994/548/1994'), ('1994/548/1994', '1992/548/1992', '1958/1/1958'), ('1965/544/1965', '1961/541/1961', '1993/551/1993'), ('1993/551/1993', '1995/550/1995', '1965/544/1965')]

这些只是前 20 个。我编写了一个渲染程序,当我输入顶点时,它会显示以下内容:

它看起来就像一辆汽车的俯视图,这是有道理的。我是 3D 模型的初学者。如何添加面孔?我的程序可以从 3 个点绘制三角形,但面有很大的数字,所以它们不能只是坐标。它们是什么以及如何从中获取三角形?

python rendering 3d-model
1个回答
2
投票

面列表中的每个元组代表一个面,该面由三个或更多顶点组成。因此,如果以第一个面为例,

1962/1/1962
是第一个顶点。每个顶点的格式为
{vertex index}/{vertex texture coordinate index}/{vertex normal index}
。因此,第一个数字 1962 代表顶点索引(先前定义的第 1962 个顶点)。第二个数字1是顶点纹理坐标索引,第三个1962是顶点法线索引。根据规范,只需要顶点索引。

如何解析某些文件并用顶点索引替换坐标:

def main():

    import re

    flt = r"-?[\d\.]+"
    vertex_pattern = r"v\s+(?P<x>{})\s+(?P<y>{})\s+(?P<z>{})".format(flt, flt, flt)
    face_pattern = r"f\s+((\d+/\d+/\d+\s*){3,})"

    vertices = []
    faces = []

    with open("alfa147.obj.txt", "r") as file:
        for line in map(str.strip, file):
            match = re.match(vertex_pattern, line)
            if match is not None:
                vertices.append(tuple(map(float, match.group("x", "y", "z"))))
                continue
            match = re.match(face_pattern, line)
            if match is not None:
                faces.append(tuple(tuple(map(int, vertex.split("/"))) for vertex in match.group(1).split()))

    print(f"The first face has {len(faces[0])} vertices:")
    for vertex in faces[0]:
        print(vertex)

    print("\nWe do not care about the texture coordinate indices or normal indices, so we get the three vertex indices:")
    for vertex in faces[0]:
        print(vertex[0])

    print("\nAfter substituting the indices for their values, the face is made up of these coordinates:")
    for vertex in faces[0]:
        print(vertices[vertex[0]-1]) # -1 because in the OBJ spec, collections start at index 1 rather than 0

    return 0


if __name__ == "__main__":
    import sys
    sys.exit(main())

输出:

The first face has 3 vertices:
(1962, 1, 1962)
(1958, 1, 1958)
(1957, 541, 1957)

We do not care about the texture coordinate indices or normal indices, so we get the three vertex indices:
1962
1958
1957

After substituting the indices for their values, the face is made up of these coordinates:
(-4.29133, 47.755795, 51.585678)
(-4.29133, 47.716423, 51.585678)
(-4.29133, 47.716423, 52.661789)
© www.soinside.com 2019 - 2024. All rights reserved.