-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmesh.py
134 lines (120 loc) · 5.29 KB
/
mesh.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
#!/usr/bin/env python3
import os
import OpenGL.GL as GL
import numpy as np
from ctypes import sizeof, c_float, c_void_p
import pyrr
class Mesh():
def __init__(self):
self.vertices = np.array([], np.float32)
self.faces = np.array([], np.uint32)
def normalize(self):
max = np.amax(self.vertices, axis=0)
min = np.amin(self.vertices, axis=0)
avg = (max+min)/2
amp = np.amax(max[:3]-min[:3])/2
self.vertices = np.array([np.concatenate((((v[:3]-avg[:3])/amp), v[3:])) for v in self.vertices], np.float32)
def apply_matrix(self, m):
vert = []
for v in self.vertices:
p = pyrr.Vector4(v[:3].tolist()+[1])
p = pyrr.matrix44.apply_to_vector(m, p)[:3].astype('float32')
v = np.array(p.tolist()+v[3:].tolist(), np.float32)
vert.append(v)
self.vertices = np.array(vert, np.float32)
def load_to_gpu(self):
# attribution d'une liste d'état (1 indique la création d'une seule liste)
vao = GL.glGenVertexArrays(1)
# affectation de la liste d'état courante
GL.glBindVertexArray(vao)
# attribution d’un buffer de donnees (1 indique la création d’un seul buffer)
vbo = GL.glGenBuffers(1)
# affectation du buffer courant
GL.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo)
# copie des donnees des sommets sur la carte graphique
GL.glBufferData(GL.GL_ARRAY_BUFFER, self.vertices, GL.GL_STATIC_DRAW)
# les deux commandes suivantes sont stockées dans l'état du vao courant
# activation l'utilisation des données de positions (le 0 correspond à la location dans le vertex shader)
GL.glEnableVertexAttribArray(0)
# indication sur le buffer courant (dernier vbo "bindé") est utilisé pour les positions des sommets
GL.glVertexAttribPointer(0, 3, GL.GL_FLOAT, GL.GL_FALSE, sizeof(c_float())*11, None)
GL.glEnableVertexAttribArray(1)
GL.glVertexAttribPointer(1, 3, GL.GL_FLOAT, GL.GL_FALSE, sizeof(c_float())*11, c_void_p(sizeof(c_float())*3))
GL.glEnableVertexAttribArray(2)
GL.glVertexAttribPointer(2, 3, GL.GL_FLOAT, GL.GL_FALSE, sizeof(c_float())*11, c_void_p(2*sizeof(c_float())*3))
GL.glEnableVertexAttribArray(3)
GL.glVertexAttribPointer(3, 2, GL.GL_FLOAT, GL.GL_FALSE, sizeof(c_float())*11, c_void_p(3*sizeof(c_float())*3))
# attribution d’un autre buffer de donnees
vboi = GL.glGenBuffers(1)
# affectation du buffer courant (buffer d’indice)
GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,vboi)
# copie des indices sur la carte graphique
GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER,self.faces,GL.GL_STATIC_DRAW)
return vao
def get_nb_triangles(self):
return len(self.faces)
def copy(self):
m = Mesh()
m.vertices = self.vertices.copy()
m.faces = self.faces.copy()
return m
"""only process one object containing triangular faces"""
@staticmethod
def load_obj(filename):
if not os.path.exists(filename):
print(f'{25*"-"}\nError reading file:\n{filename}\n{25*"-"}')
m = Mesh()
tmpv = []
tmpvn = []
tmpvt = []
vi = []
vni = []
vti = []
with open(filename) as f:
for line in f:
l = line.split()
if l[0] == 'v' :
v = np.array(l[1:], np.float32)
tmpv.append(v)
elif l[0] == 'vn' :
vn = np.array(l[1:], np.float32)
tmpvn.append(vn)
elif l[0] == 'vt' :
vt = np.array(l[1:], np.float32)
tmpvt.append(vt)
elif l[0] == 'f' :
f1 = l[1].split('/')
f2 = l[2].split('/')
f3 = l[3].split('/')
vi.append(np.array([f1[0], f2[0], f3[0]], np.uint32))
if f3[1] != '' :
vti.append(np.array([f1[1], f2[1], f3[1]], np.uint32))
else :
vti.append(np.array([1, 1, 1], np.uint32))
if f3[2] != '' :
vni.append(np.array([f1[2], f2[2], f3[2]], np.uint32))
else :
vni.append(np.array([1, 1, 1], np.uint32))
if len(tmpvn) == 0:
tmpvn.append(np.array([0, 0, 0], np.float32))
if len(tmpvt) == 0:
tmpvt.append(np.array([0, 0], np.float32))
vi = [i-1 for i in vi]
vni = [i-1 for i in vni]
vti = [i-1 for i in vti]
dic = dict()
tmp = []
tmpf = []
for v, vn, vt in zip(vi, vni, vti):
idx = []
for i in [0, 1, 2]:
if (v[i], vn[i], vt[i]) in dic :
idx.append(dic[(v[i], vn[i], vt[i])])
else :
tmp.append(np.concatenate((tmpv[v[i]], tmpvn[vn[i]], np.array(3*[1], np.float32), tmpvt[vt[i]])))
dic[(v[i], vn[i], vt[i])] = len(tmp)-1
idx.append(dic[(v[i], vn[i], vt[i])])
tmpf.append(np.array(idx, np.uint32))
m.vertices = np.array(tmp, np.float32)
m.faces = np.array(tmpf, np.uint32)
return m