-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path2_polyhedron_cube_render.py
96 lines (71 loc) · 4.87 KB
/
2_polyhedron_cube_render.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
"""
Алгоритм отрисовки многогранника - куба, исп. pygame & OpenGl:
В этом алгоритме сначала определяется список вершин и соответствующих им ребер
для корректного отображения куба; Затем, исп. модуль pygame, задается холст,
на котором будет отрисовываться анимация, предварительно задав поддерждку OpenGl
флагами DOUBLEBUF & OPENGL; После этого задаются изначальные параметры отображения куба,
такие как угол бзора по оси ординат, соотношение сторон...
Далее, к делу подключается обработчик событий, который, в зависимости от НАЖАТОЙ клавиши
либо выйдет из холста, либо повернет куб в одну из сторон, в зависимости от его
текущего положения; Чтобы куб сохранял постоянную умеренную скорость вращения, на каждой
итерации беск. цикла устанавливается ожидание в 30мс, после чего и отрисовка продолжается вновь
"""
from itertools import combinations_with_replacement
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
cube_edges = [ # определяю набор из 12 ребер куба
(0, 1), (0, 2), (0, 6),
(4, 1), (4, 2), (4, 3),
(5, 2), (5, 3), (5, 6),
(7, 1), (7, 3), (7, 6),
]
cube_vertices = [ # определяю набор из 8 вершин куба
*set(
combinations_with_replacement((1, -1, 1, -1), 3)
)
]
def render_cube() -> None:
glBegin(GL_LINES) # Рассматривает каждую пару вершин как независимый отрезок прямой
for edge in cube_edges:
for vertex in edge:
glVertex3f(*cube_vertices[vertex]) # создаю "вершину", передав туда распакованный кортеж (x, y, z)
glEnd()
def main():
pygame.init()
pygame.display.set_mode(display := (1000, 800),
DOUBLEBUF | OPENGL) # устанавливаю 2 первых флага для поддержки OpenGL
gluPerspective(90, (display[0] / display[1]), .1, 50) # устанавливаю проекционную матрицу,
# где 90 - угол обзора по оси ординат (fovy),
# (1000 / 800) - cоотношение сторон, определяющее поле зрения по оси абсцисс (отношение ширины к высоте),
# 0.1 & 50 - Расстояние от верхней плоскости экрана до ближней/дальней плоскостей отсеч.
glTranslatef(0, 0, -5) # умножает текущую матрицу (glMatrixMode) на матрицу перевода:
# 1 0 0 x=0
# 0 1 0 y=0
# 0 0 1 z=-5
# 0 0 0 1, полученную из вектора перевода (x, y, z)
while True:
for e in pygame.event.get(): # для каждого события на итерации цикла
if e.type == pygame.QUIT: # устаналиваю обработку нажатия на крестик
pygame.quit()
exit()
if e.type == pygame.KEYDOWN: # устаналиваю обработку нажатия на клавишу
keys = pygame.key.get_pressed() # получаю список нажатых клавиш
if keys[K_UP]: # если нажата стрелка вверх
glTranslatef(0, 1, 0) # перевожу куб как матрицу в дркгое положение по оси y, и т д...
if keys[K_DOWN]:
glTranslatef(0, -1, 0)
if keys[K_LEFT]:
glTranslatef(-0.5, 0, 0)
if keys[K_RIGHT]:
glTranslatef(0.5, 0, 0)
glRotatef(2, 2, 2, 3) # устанавливаю угол и вектор вращения
glClear(GL_COLOR_BUFFER_BIT) # очищает цветовой буфер
render_cube() # вызов отрисовки куба
pygame.display.flip()
pygame.time.wait(30) # устанавливаю ожидание, чтобы куб вертелся с умеренной скоростью
glClearColor(*(0,) * 4) # ставлю черную заливку
glClear(GL_COLOR_BUFFER_BIT) # очищает цветовой буфер
if __name__ == '__main__':
main()