-
Notifications
You must be signed in to change notification settings - Fork 1
/
Object.py
116 lines (105 loc) · 5.42 KB
/
Object.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
from operations import multMatriz, mult_vetor_matriz, product_vetorial, minus_vetorial, unitarizador
import math
class Object:
def __init__(self, file):
"""Construtor de um objeto. Um arquivo .obj deve ser passado como argumento"""
self.vertices = []
self.faces = []
self.normais = []
self.transformacao = [[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]]
with open(file, 'r') as arquivo:
for linha in arquivo:
partes = linha.split()
if partes[0] == 'v':
vertice = list(map(float, partes[1:]))
self.vertices.append(vertice)
elif partes[0] == 'f':
vertice = list(map(int, partes[1:]))
self.faces.append(vertice)
def translacao(self, offset_x=0, offset_y=0, offset_z=0):
"""Move um objeto na cena. Deve ser passado a variação a ser realizada nos eixos."""
matriz = [[1, 0, 0, offset_x],
[0, 1, 0, offset_y],
[0, 0, 1, offset_z],
[0, 0, 0, 1]]
self.transformacao = multMatriz(matriz, self.transformacao)
def escala(self, prop_x=1, prop_y=1, prop_z=1):
"""Expande ou contrai um objeto na cena. Deve ser passado a variação a ser realizada nos eixos."""
matriz = [[prop_x, 0, 0, 0],
[0, prop_y, 0, 0],
[0, 0, prop_z, 0],
[0, 0, 0, 1]]
self.transformacao = multMatriz(matriz, self.transformacao)
def rotacao(self, grau_x=0, grau_y=0, grau_z=0):
"""Expande ou contrai um objeto na cena. Deve ser passado a variação a ser realizada nos eixos."""
if grau_x != 0:
seno = math.sin(grau_x * math.pi / 180)
cosseno = math.cos(grau_x * math.pi / 180)
matriz = [[1, 0, 0, 0],
[0, cosseno, -seno, 0],
[0, seno, cosseno, 0],
[0, 0, 0, 1]]
self.transformacao = multMatriz(matriz, self.transformacao)
if grau_y != 0:
seno = math.sin(grau_y * math.pi / 180)
cosseno = math.cos(grau_y * math.pi / 180)
matriz = [[cosseno, 0, seno, 0],
[0, 1, 0, 0],
[-seno, 0, cosseno, 0],
[0, 0, 0, 1]]
self.transformacao = multMatriz(matriz, self.transformacao)
if grau_z != 0:
seno = math.sin(grau_z * math.pi / 180)
cosseno = math.cos(grau_z * math.pi / 180)
matriz = [[cosseno, -seno, 0, 0],
[seno, cosseno, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]]
self.transformacao = multMatriz(matriz, self.transformacao)
def transformar(self):
"""Aplica a matriz de transformação nos vértices do objeto."""
self.vertices = list(map(lambda v: mult_vetor_matriz(v + [1], self.transformacao), self.vertices))
def salvar_objeto(self, file):
"""Construtor de um objeto. Um arquivo .obj deve ser passado como argumento."""
with open(file, 'w') as arquivo:
for vertice in self.vertices:
string = "v {0} {1} {2}\n".format(*vertice)
arquivo.write(string)
for face in self.faces:
string = "f {0} {1} {2}\n".format(*face)
arquivo.write(string)
def normal_vertices(self):
"""Retorna todas as normais de cada vértice"""
# Preciso calcular a normal de cada face
n = len(self.vertices)
media = [[0] * n, [0] * n, [0] * n, [0] * n]
for face in self.faces:
# Calcula a normal
v1, v2, v3 = self.vertices[face[0] - 1], self.vertices[face[1] - 1], self.vertices[face[2] - 1]
normal = product_vetorial(minus_vetorial(v2, v1), minus_vetorial(v3, v1))
# Soma a normal no acumulado
media[0][face[0] - 1] = media[0][face[0] - 1] + normal[0]
media[0][face[1] - 1] = media[0][face[1] - 1] + normal[0]
media[0][face[2] - 1] = media[0][face[2] - 1] + normal[0]
media[1][face[0] - 1] = media[1][face[0] - 1] + normal[1]
media[1][face[1] - 1] = media[1][face[1] - 1] + normal[1]
media[1][face[2] - 1] = media[1][face[2] - 1] + normal[1]
media[2][face[0] - 1] = media[2][face[0] - 1] + normal[2]
media[2][face[1] - 1] = media[2][face[1] - 1] + normal[2]
media[2][face[2] - 1] = media[2][face[2] - 1] + normal[2]
# Soma 1 na qtde
media[3][face[0] - 1] = media[3][face[0] - 1] + 1
media[3][face[1] - 1] = media[3][face[1] - 1] + 1
media[3][face[2] - 1] = media[3][face[2] - 1] + 1
# Depois calcular a normal de cada vértice pela média das faces
for i in range(n):
media[0][i] = media[0][i] / media[3][i]
media[1][i] = media[1][i] / media[3][i]
media[2][i] = media[2][i] / media[3][i]
# Unitarizar
media[0][i], media[1][i], media[2][i] = unitarizador([media[0][i], media[1][i], media[2][i]])
# Então dá para fazer um vetor n por 2 com o acumulado e a quantidade de faces
self.normais = media[0:3]