2

Ive got this .obj file. It's a model of a Mini-Cooper. I extracted all vertices and faces into lists that look like this:

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')]

These are only the first 20. I wrote a rendering program and when I put in the vertices it shows this: cooper-picture

It looks like a top-down view of a car, which makes sense. I am a complete beginner to 3d models. How can I add the faces? My program can draw triangles from 3 points, but the faces have huge numbers, so they can't just be coordinates. What are they and how can I get the triangles from them?

  • 1
    Each tuple in your `faces` list represents one face, which consists of three or more vertices. So, if you take the first face for example, `'1962/1/1962'` is the first vertex. The format for each vertex is `{vertex index}/{vertex texture coordinate index}/{vertex normal index}`. So, the first number `1962` represents the vertex index (the 1962nd previously defined vertex). The second number `1` is the vertex texture coordinate index, and the third `1962` is the vertex normal index. According to the specification, only the vertex index is required. – Paul M. Dec 29 '20 at 13:33

1 Answers1

2

I want to expand on my comment a bit with some code that shows how you could parse some of the file, and then substitute the vertex indices for the actual coordinates:

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())

Output:

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)
>>> 
Paul M.
  • 10,481
  • 2
  • 9
  • 15