forked from ivansipiran/grafica
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathex_mouse.py
203 lines (149 loc) · 5.97 KB
/
ex_mouse.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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# coding=utf-8
"""
Interactions with keyboard and mouse via GLFW/python
More information at:
https://www.glfw.org/docs/latest/input_guide.html
How to convert GLFW/C calls to GLFW/python
https://pypi.org/project/glfw/
"""
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.easy_shaders as es
__author__ = "Daniel Calderon"
__license__ = "MIT"
# We will use 32 bits data, so an integer has 4 bytes
# 1 byte = 8 bits
SIZE_IN_BYTES = 4
# A class to control the application
class Controller:
def __init__(self):
self.leftClickOn = False
self.theta = 0.0
self.mousePos = (0.0, 0.0)
# we will use the global controller as communication with the callback function
controller = Controller()
def on_key(window, key, scancode, action, mods):
if action == glfw.PRESS:
if key == glfw.KEY_ESCAPE:
glfw.set_window_should_close(window, True)
def cursor_pos_callback(window, x, y):
global controller
controller.mousePos = (x,y)
def mouse_button_callback(window, button, action, mods):
global controller
"""
glfw.MOUSE_BUTTON_1: left click
glfw.MOUSE_BUTTON_2: right click
glfw.MOUSE_BUTTON_3: scroll click
"""
if (action == glfw.PRESS or action == glfw.REPEAT):
if (button == glfw.MOUSE_BUTTON_1):
controller.leftClickOn = True
print("Mouse click - button 1")
if (button == glfw.MOUSE_BUTTON_2):
print("Mouse click - button 2:", glfw.get_cursor_pos(window))
if (button == glfw.MOUSE_BUTTON_3):
print("Mouse click - button 3")
elif (action ==glfw.RELEASE):
if (button == glfw.MOUSE_BUTTON_1):
controller.leftClickOn = False
def scroll_callback(window, x, y):
print("Mouse scroll:", x, y)
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, "Handling mouse events", 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)
# Connecting callback functions to handle mouse events:
# - Cursor moving over the window
# - Mouse buttons input
# - Mouse scroll
glfw.set_cursor_pos_callback(window, cursor_pos_callback)
glfw.set_mouse_button_callback(window, mouse_button_callback)
glfw.set_scroll_callback(window, scroll_callback)
# Creating our shader program and telling OpenGL to use it
pipeline = es.SimpleTransformShaderProgram()
glUseProgram(pipeline.shaderProgram)
# Setting up the clear screen color
glClearColor(0.15, 0.15, 0.15, 1.0)
# Convenience function to ease initialization
def createGPUColorQuad(r,g,b):
shapeQuad = bs.createColorQuad(r,g,b)
gpuQuad = es.GPUShape().initBuffers()
pipeline.setupVAO(gpuQuad)
gpuQuad.fillBuffers(shapeQuad.vertices, shapeQuad.indices, GL_STATIC_DRAW)
return gpuQuad
# Creating shapes on GPU memory
blueQuad = createGPUColorQuad(0,0,1)
redQuad = createGPUColorQuad(1,0,0)
yellowQuad = createGPUColorQuad(1,1,0)
greenQuad = createGPUColorQuad(0,1,0)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
t0 = glfw.get_time()
while not glfw.window_should_close(window):
# Getting the time difference from the previous iteration
t1 = glfw.get_time()
dt = t1 - t0
t0 = t1
# Using GLFW to check for input events
glfw.poll_events()
# Clearing the screen in both, color and depth
glClear(GL_COLOR_BUFFER_BIT)
# While left click is pressed, we have continous rotation movement
if controller.leftClickOn:
controller.theta += 4 * dt
if controller.theta >= 2 * np.pi:
controller.theta -= 2 * np.pi
# Setting transform and drawing the rotating red quad
glUniformMatrix4fv(glGetUniformLocation(pipeline.shaderProgram, "transform"), 1, GL_TRUE, tr.matmul([
tr.rotationZ(controller.theta),
tr.translate(0.5, 0.0, 0.0),
tr.uniformScale(0.5)
]))
pipeline.drawCall(redQuad)
# Getting the mouse location in opengl coordinates
mousePosX = 2 * (controller.mousePos[0] - width/2) / width
mousePosY = 2 * (height/2 - controller.mousePos[1]) / height
glUniformMatrix4fv(glGetUniformLocation(pipeline.shaderProgram, "transform"), 1, GL_TRUE, np.matmul(
tr.translate(mousePosX, mousePosY, 0),
tr.uniformScale(0.3)
))
pipeline.drawCall(greenQuad)
# This is another way to work with keyboard inputs
# Here we request the state of a given key
if (glfw.get_key(window, glfw.KEY_LEFT_CONTROL) == glfw.PRESS):
glUniformMatrix4fv(glGetUniformLocation(pipeline.shaderProgram, "transform"), 1, GL_TRUE, np.matmul(
tr.translate(-0.6, 0.4, 0.0),
tr.uniformScale(0.2)
))
pipeline.drawCall(blueQuad)
# All "non-pressed" keys are in release state
if (glfw.get_key(window, glfw.KEY_LEFT_CONTROL) == glfw.RELEASE):
glUniformMatrix4fv(glGetUniformLocation(pipeline.shaderProgram, "transform"), 1, GL_TRUE, np.matmul(
tr.translate(-0.6, 0.6, 0.0),
tr.uniformScale(0.2)
))
pipeline.drawCall(yellowQuad)
# Once the render is done, buffers are swapped, showing only the complete scene.
glfw.swap_buffers(window)
# freeing GPU memory
blueQuad.clear()
redQuad.clear()
yellowQuad.clear()
greenQuad.clear()
glfw.terminate()