-
Notifications
You must be signed in to change notification settings - Fork 0
/
Cube.py
119 lines (94 loc) · 4.36 KB
/
Cube.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
from OpenGL.GL import *
from collections import defaultdict
import numpy as np
import ctypes
import pathlib
DEBUG_PATH = f'{pathlib.Path(__file__).parent.resolve()}/debug/vert1.txt'
class Cube:
def __init__(self, position, eulers) -> None:
self.position = np.array(position, dtype=np.float32)
self.eulers = np.array(eulers, dtype=np.float32)
class Mesh:
def __init__(self, filename) -> None:
self.vertex_stride = 8
self.v_data = defaultdict(list)
# x, y, z, s, t, nx, ny, nz
vertices = self.load_mesh(filename)
self.vertex_count = len(vertices) // self.vertex_stride
vertices = np.array(vertices, dtype=np.float32)
# create VAO and VBO and binds them
self.vao = glGenVertexArrays(1)
glBindVertexArray(self.vao)
# vertices
self.vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW)
# Position
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4 * self.vertex_stride, ctypes.c_void_p(0))
# Texture
glEnableVertexAttribArray(1)
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * self.vertex_stride, ctypes.c_void_p(12))
def load_mesh(self, filename: str) -> list[float]:
vertices = []
with open(filename, 'r') as file:
for line in file:
words = line.strip().split()
if words and words[0] in {'v', 'vt', 'vn'}:
self.v_data[words[0]].append(self.read_mesh_data(words))
elif words and words[0] == 'f':
self.read_face_data(words, vertices)
# self.debug_print_vertices(vertices)
# print(vertices)
return vertices
def debug_print_vertices(self, vertices: list[float]) -> None:
with open(DEBUG_PATH, 'w') as f:
# Write the floats to the file with a newline every eighth number
f.write('\n'.join([' '.join(map(str, vertices[i:i+8])) for i in range(0, len(vertices), 8)]))
def read_mesh_data(self, words: list[str]) -> list[float]:
return [float(word) for word in words[1:] if word]
def read_face_data(self, words: list[str], vertices: list[float]) -> None:
v = self.v_data['v']
vt = self.v_data['vt']
vn = self.v_data['vn']
""" Previous code:
triangle_count = len(words) - 3
for i in range(triangle_count):
self.make_corner(words[1] , v, vt, vn, vertices)
self.make_corner(words[2 + i], v, vt, vn, vertices)
self.make_corner(words[3 + i], v, vt, vn, vertices)
"""
# Pre-process to extract all indices
indices = [word.split('/') for word in words[1:]]
# Validate indices and convert them to integers (assumes indices are complete and correct)
indices = [(int(v_idx)-1 if v_idx else None,
int(vt_idx)-1 if vt_idx else None,
int(vn_idx)-1 if vn_idx else None) for v_idx, vt_idx, vn_idx in indices]
# Each face is a polygon, triangulate the polygon by creating triangles from consecutive vertices
for i in range(1, len(indices) - 1):
for index_set in (indices[0], indices[i], indices[i + 1]):
for idx, data_array in zip(index_set, (v, vt, vn)):
if idx is not None: # Ensure the index is valid
vertices.extend(data_array[idx])
def make_corner(
self,
corner: str,
v: list[list[float]],
vt: list[list[float]],
vn: list[list[float]],
vertices: list[float],
) -> None:
""" Previous code:
v_vt_vn = corner.split('/')
for element in v[int(v_vt_vn[0]) - 1]:
vertices.append(element)
for element in vt[int(v_vt_vn[1]) - 1]:
vertices.append(element)
for element in vn[int(v_vt_vn[2]) - 1]:
vertices.append(element)
"""
v_idx, vt_idx, vn_idx = map(int, corner.split('/'))
vertices.extend(v[v_idx - 1] + vt[vt_idx - 1] + vn[vn_idx - 1])
def delete(self):
glDeleteVertexArrays(1, (self.vao, ))
glDeleteBuffers(1, (self.vbo, ))