forked from dantros/grafica
-
Notifications
You must be signed in to change notification settings - Fork 11
/
ex_scene_graph_2dcars.py
163 lines (116 loc) · 4.71 KB
/
ex_scene_graph_2dcars.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
# coding=utf-8
"""Drawing many cars in 2D using scene_graph2"""
import glfw
from OpenGL.GL import *
import OpenGL.GL.shaders
import numpy as np
import sys
import os.path
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import grafica.transformations as tr
import grafica.basic_shapes as bs
import grafica.scene_graph as sg
import grafica.easy_shaders as es
__author__ = "Daniel Calderon"
__license__ = "MIT"
def on_key(window, key, scancode, action, mods):
if action != glfw.PRESS:
return
if key == glfw.KEY_ESCAPE:
glfw.set_window_should_close(window, True)
else:
print('Unknown key')
def createCar(pipeline):
# Creating shapes on GPU memory
blackQuad = bs.createColorQuad(0,0,0)
gpuBlackQuad = es.GPUShape().initBuffers()
pipeline.setupVAO(gpuBlackQuad)
gpuBlackQuad.fillBuffers(blackQuad.vertices, blackQuad.indices, GL_STATIC_DRAW)
redQuad = bs.createColorQuad(1,0,0)
gpuRedQuad = es.GPUShape().initBuffers()
pipeline.setupVAO(gpuRedQuad)
gpuRedQuad.fillBuffers(redQuad.vertices, redQuad.indices, GL_STATIC_DRAW)
# Cheating a single wheel
wheel = sg.SceneGraphNode("wheel")
wheel.transform = tr.uniformScale(0.2)
wheel.childs += [gpuBlackQuad]
wheelRotation = sg.SceneGraphNode("wheelRotation")
wheelRotation.childs += [wheel]
# Instanciating 2 wheels, for the front and back parts
frontWheel = sg.SceneGraphNode("frontWheel")
frontWheel.transform = tr.translate(0.3,-0.3,0)
frontWheel.childs += [wheelRotation]
backWheel = sg.SceneGraphNode("backWheel")
backWheel.transform = tr.translate(-0.3,-0.3,0)
backWheel.childs += [wheelRotation]
# Creating the chasis of the car
chasis = sg.SceneGraphNode("chasis")
chasis.transform = tr.scale(1,0.5,1)
chasis.childs += [gpuRedQuad]
car = sg.SceneGraphNode("car")
car.childs += [chasis]
car.childs += [frontWheel]
car.childs += [backWheel]
traslatedCar = sg.SceneGraphNode("traslatedCar")
traslatedCar.transform = tr.translate(0,0.3,0)
traslatedCar.childs += [car]
return traslatedCar
def createCars(pipeline, N):
# First we scale a car
scaledCar = sg.SceneGraphNode("traslatedCar")
scaledCar.transform = tr.uniformScale(0.15)
scaledCar.childs += [createCar(pipeline)] # Re-using the previous function
cars = sg.SceneGraphNode("cars")
baseName = "scaledCar"
for i in range(N):
# A new node is only locating a scaledCar in the scene depending on index i
newNode = sg.SceneGraphNode(baseName + str(i))
newNode.transform = tr.translate(0.4 * i - 0.9, 0.9 - 0.4 * i, 0)
newNode.childs += [scaledCar]
# Now this car is added to the 'cars' scene graph
cars.childs += [newNode]
return cars
if __name__ == "__main__":
# Initialize glfw
if not glfw.init():
glfw.set_window_should_close(window, True)
width = 600
height = 600
window = glfw.create_window(width, height, "2D cars via scene graph", None, None)
if not window:
glfw.terminate()
glfw.set_window_should_close(window, True)
glfw.make_context_current(window)
# Connecting the callback function 'on_key' to handle keyboard events
glfw.set_key_callback(window, on_key)
# Assembling the shader program (pipeline) with both shaders
pipeline = es.SimpleTransformShaderProgram()
# Telling OpenGL to use our shader program
glUseProgram(pipeline.shaderProgram)
# Setting up the clear screen color
glClearColor(0.85, 0.85, 0.85, 1.0)
# Creating shapes on GPU memory
cars = createCars(pipeline, 5)
# Our shapes here are always fully painted
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
while not glfw.window_should_close(window):
# Using GLFW to check for input events
glfw.poll_events()
# Clearing the screen in both, color and depth
glClear(GL_COLOR_BUFFER_BIT)
# Modifying only a specific node in the scene graph
wheelRotationNode = sg.findNode(cars, "wheelRotation")
theta = -10 * glfw.get_time()
wheelRotationNode.transform = tr.rotationZ(theta)
# Modifying only car 3
car3 = sg.findNode(cars, "scaledCar3")
car3.transform = tr.translate(0.3, 0.5 * np.sin(0.1 * theta), 0)
# Uncomment to see the position of scaledCar_3, it will fill your terminal
#print("car3Position =", sg.findPosition(cars, "scaledCar3"))
# Drawing the Car
sg.drawSceneGraphNode(cars, pipeline, "transform")
# Once the render is done, buffers are swapped, showing only the complete scene.
glfw.swap_buffers(window)
# freeing GPU memory
cars.clear()
glfw.terminate()