-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathobjLoaderV3.py
204 lines (159 loc) · 7.33 KB
/
objLoaderV3.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
import numpy as np
class ObjLoader:
def __init__(self, file):
'''
This Objloader class loads a mesh from an obj file.
The mesh is made up of vertices.
Each vertex is generally defined by the following attributes
- position coordinates (v)
- texture coordinates (vt)
- normal coordinates (vn)
There are other attributes that can be defined for a vertex,
but we will not use them for now.
Note: Sometimes, the obj file only contains position coordinates (v).
If the obj file contains information for all three (v, vt, vn),
then each vertex is made up of 8 floats:
3 for position coordinates v = (x,y,z),
2 for texture coordinates vt = (u,v),
3 for normals vn = (xn,yn,zn)
Important member variables to note:
self.vertices:
a one dimensional array of floats in the form:
vertices = [ x,y,z, u,v, xn,yn,zn, x,y,z, u,v, xn,yn,zn, ...]
------ --- ------ ------ --- ------
| v vt vn | | v vt vn |
------------------- ------------------- ...
vertex 1 vertex 2
self.v:
a list of vertex position coordinates
v = [ [x,y,z], [x,y,z], [x,y,z], ...]
self.vt:
a list of vertex texture coordinates
vt = [ [u,v], [u,v], [u,v], ...]
self.vn:
a list of vertex normal coordinates
vn = [ [xn,yn,zn], [xn,yn,zn], [xn,yn,zn], ...]
:param file: full path to the obj file
'''
self.vertices = [] # 1D array of floats
self.v = [] # list of vertex position coordinates
self.vt = [] # list of vertex texture coordinates
self.vn = [] # list of vertex normal coordinates
self.load_mesh(file)
self.compute_model_extent(self.v)
def load_mesh(self, filename):
'''
Load a mesh from an obj file.
:param filename:
:return:
'''
vertices = []
with open(filename, "r") as file:
for line in file:
words = line.split()
if len(words) == 0:
continue
if words[0] == "v":
self.v.append(list(map(float, words[1:4])))
elif words[0] == "vt":
self.vt.append(list(map(float, words[1:3])))
elif words[0] == "vn":
self.vn.append(list(map(float, words[1:4])))
elif words[0] == "f":
n_triangle = len(words) - 3
for i in range(n_triangle):
self.add_vertex(words[1], self.v, self.vt, self.vn, vertices)
self.add_vertex(words[2 + i], self.v, self.vt, self.vn, vertices)
self.add_vertex(words[3 + i], self.v, self.vt, self.vn, vertices)
self.vertices = np.array(vertices, dtype=np.float32)
self.v = np.array(self.v, dtype=np.float32)
self.vt = np.array(self.vt, dtype=np.float32)
self.vn = np.array(self.vn, dtype=np.float32)
def add_vertex(self, corner_description: str,
v, vt,
vn, vertices) -> None:
'''
Add a vertex to the list of positions.
:param corner_description:
:param v: list of vertex position coordinates
:param vt: list of vertex texture coordinates
:param vn: list of vertex normal coordinates
:param vertices:
:return:
'''
v_vt_vn = corner_description.split("/")
v_vt_vn = list(filter(None, v_vt_vn))
v_vt_vn = list(map(int, v_vt_vn))
if len(v_vt_vn) == 1:
vertices.extend(v[int(v_vt_vn[0]) - 1])
elif len(v_vt_vn) == 2:
if len(vn) == 0:
vertices.extend(v[int(v_vt_vn[0]) - 1]) # add vertex coordinates to the list
vertices.extend(vt[int(v_vt_vn[1]) - 1]) # add texture coordinates to the list
elif len(vt) == 0:
vertices.extend(v[int(v_vt_vn[0]) - 1]) # add vertex coordinates to the list
vertices.extend(vn[int(v_vt_vn[1]) - 1]) # add normal coordinates to the list
elif len(v_vt_vn) == 3:
vertices.extend(v[int(v_vt_vn[0]) - 1]) # add vertex coordinates to the list
vertices.extend(vt[int(v_vt_vn[1]) - 1]) # add texture coordinates to the list
vertices.extend(vn[int(v_vt_vn[2]) - 1]) # add normal coordinates to the list
def compute_model_extent(self, positions):
'''
Compute the model extent (min, max, center, diameter)
:param positions:
:return:
'''
self.min = np.array([np.inf, np.inf, np.inf])
self.max = np.array([-np.inf, -np.inf, -np.inf])
for v in positions:
v = np.array(v)
self.min = np.minimum(self.min, v)
self.max = np.maximum(self.max, v)
self.dia = np.linalg.norm(self.max - self.min)
self.center = (self.min + self.max) / 2
self.min = self.min.astype('float32')
self.max = self.max.astype('float32')
self.center = self.center.astype('float32')
if __name__ == '__main__':
'''
This Objloader class loads a mesh from an obj file.
The mesh is made up of vertices.
Each vertex is generally defined by the following attributes
- position coordinates (v)
- texture coordinates (vt)
- normal coordinates (vn)
There are other attributes that can be defined for a vertex,
but we will not use them for now.
Note: Sometimes, the obj file only contains position coordinates (v).
If the obj file contains information for all three (v, vt, vn),
then each vertex will be made up of 8 floats:
3 for position coordinates v = (x,y,z),
2 for texture coordinates vt = (u,v),
3 for normals vn = (xn,yn,zn)
Important member variables to note:
self.vertices:
a one dimensional array of floats in the form:
vertices = [ x,y,z, u,v, xn,yn,zn, x,y,z, u,v, xn,yn,zn, ...]
------ --- ------ ------ --- ------
| v vt vn | | v vt vn |
------------------- -------------------
vertex 1 vertex 2 ...
self.v:
a list of vertex position coordinates
v = [ [x,y,z], [x,y,z], [x,y,z], ...]
self.vt:
a list of vertex texture coordinates
vt = [ [u,v], [u,v], [u,v], ...]
self.vn:
a list of vertex normal coordinates
vn = [ [xn,yn,zn], [xn,yn,zn], [xn,yn,zn], ...]
'''
obj = ObjLoader("objects/raymanModel.obj")
positions = obj.v
print("Dimension of v: ", obj.v.shape)
texture_coordinates = obj.vt
print("Dimension of vt: ", obj.vt.shape)
normal_coordinates = obj.vn
print("Dimension of vn: ", obj.vn.shape)
vertices = obj.vertices # 1D array of vertices (position, texture, normal)
print("Dimension of vertices: ", obj.vertices.shape)