Completed
Push — master ( d8abfd...1806b7 )
by
unknown
51s
created

ed2d.assets.OBJ.get_final_data()   B

Complexity

Conditions 5

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 5
dl 0
loc 16
rs 8.5454
1
2
from ed2d.mesh import MeshBase
3
from ed2d.assets.mtlloader import MTL
4
5
class OBJ(object):
6
    def __init__(self, fileName):
7
        ''' Wavefront .obj file parser.'''
8
        fcount = 0
9
        vcount = 0
10
        vtcount = 0
11
        vncount = 0
12
        matcount = 0
13
14
        __objpath = files.resolve_path('data', 'models', 'fileName' + '.obj')
15
        __mtlpath = files.resolve_path('data', 'models', 'fileName' + '.mtl')
16
17
        # Load the mtl file
18
        self.mtlfile = MTL(__mtlpath)
19
20
        # Load the obj file
21
        objfile = open(fileName, "r")
22
23
        # Do a head count
24
        for line in objfile:
25
            value = line[:2]
26
            if value == 'f ':
27
                fcount += 1
28
            elif value == 'v ':
29
                vcount += 1
30
            elif value == 'vt':
31
                vtcount += 1
32
            elif value == 'vn':
33
                vncount += 1
34
            elif value == 'g ':
35
                matcount += 1
36
37
        # Close the file
38
        objfile.close()
39
40
        fcount *= 3
41
        vcount *= 3
42
        vtcount *= 3
43
        vncount *= 3
44
45
        self.tempVertices = [None] * vcount
46
        self.tempNormals = [None] * vncount
47
        self.tempUVs = [None] * fcount
48
        self.tempMaterials = [None] * matcount
49
50
        self.vertexIndices = [None] * fcount
51
        self.normalIndices = [None] * fcount
52
        self.uvIndices = [None] * fcount
53
54
        self.finalVertices = [None] * fcount
55
        self.finalNormals = [None] * fcount
56
        self.finalUVs = [None] * fcount
57
        self.usedMaterials = [None] * matcount
58
59
        self.fnumber = 0
60
        self.vnumber = 0
61
        self.vtnumber = 0
62
        self.vnnumber = 0
63
        self.matnumber = 0
64
65
        self.tmvnig = {}
66
        self.fmvnig = {}
67
68
        # Process the data
69
        self.__process_in_house(__objpath)
70
        # Finalize
71
        self.get_final_data()
72
73
    def __process_in_house(self, filename):
74
        with open(filename, "r") as objfl:
75
76
            for line in objfl:
77
78
                value = line.split()
79
                valueType = value[0]
80
81
                # Don't bother unless the following key words exist in the line
82
                if valueType not in ['f', 'v', 'vt', 'vn', 'g', 'usemtl']:
83
                    continue
84
85
                # Start ignoring the first word of the line to grab the values
86
                value = value[1:]
87
                matname = None
88
                # Check first and continue on early because of string splitting
89
                if valueType == "usemtl":
90
                    matname = value[1]
91
                    # Material Vertex UV Normal Indices Group (Vertex, UV, Normal)
92
                    self.tmvnig[matname] = [[],[],[]]
93
                    self.matnumber += 1
94
                    continue
95
96
                if valueType == "f":
97
                    temp = [item.split("/") for item in value]
98
99
                    for i in range(3):
100
                        # 0 - Vertex
101
                        # 1 - UV
102
                        # 2 - Normal
103
                        # Make sure UV index data exists
104
                        if temp[i][1] != '':
105
                            self.tmvnig[matname][1][self.fnumber] = int(temp[i][1])
106
                        self.tmvnig[matname][0][self.fnumber] = int(temp[i][0])
107
                        self.tmvnig[matname][2][self.fnumber] = int(temp[i][2])
108
                        self.fnumber += 1
109
                    continue
110
111
                # Map the values after the keyword to floats
112
                value = list(map(float, value))
113
114
                if valueType == "v":
115
                    v = [value[0], value[1], value[2]]
116
                    self.tempVertices[self.vnumber] = v
117
                    self.vnumber += 1
118
119
                elif valueType == "vt":
120
                    vt = [value[0], value[0]]
121
                    self.tempUVs[self.vtnumber] = vt
122
                    self.vtnumber += 1
123
124
                elif valueType == "vn":
125
                    n = [value[0], value[1], value[2]]
126
                    self.tempNormals[self.vnnumber] = n
127
                    self.vnnumber += 1
128
129
                elif valueType == "g":
130
                    g = value[0]
131
                    self.tempMaterials[self.matnumber] = g
132
                    self.matnumber += 1
133
134
    def get_final_data(self):
135
        for j in range(self.matnumber):
136
            matrname = self.tmvnig.keys[j]
137
            for i in range(self.fcount):
138
                vertexIndex = int(self.tmvnig[matrname][0][i]) - 1
139
                vertex = self.tempVertices[vertexIndex]
140
                self.fmvnig[matrname][0][i] = vertex
141
142
                normalIndex = int(self.tmvnig[matrname][2][i]) - 1
143
                normal = self.tempNormals[normalIndex]
144
                self.fmvnig[matrname][2][i] = normal
145
146
                if self.uvIndices[0] is None and self.vtcount != 0:
147
                    uvIndex = int(self.tmvnig[matrname][1][i]) - 1
148
                    uv = self.tempUVs[uvIndex]
149
                    self.fmvnig[matrname][1][i] = uv
150
151
class ObjMesh(MeshBase):
152
    def __init__(self, filePath, name, program, vertexLoc, normalLoc):
153
        super(ObjMesh, self).__init__(filePath, name, program, vertexLoc, normalLoc)
154