I have an old program written in python2, gtk2 and opengl1.2. It needs to be updated to modern standards. So I try to learn these. So far I have this example code that does render, but does not update on a mouseclick: the triangle should turn when clicked inside the triangle, but it does not. Why? Can someone please help to modify the code to make the triangle turn?
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GLib
from OpenGL.GL import *
from OpenGL.GL import shaders
import numpy as np
# Define your vertex and fragment shader source code
vertex_shader_source = """
#version 330 core
layout(location = 0) in vec3 a_position;
void main()
{
gl_Position = vec4(a_position, 1.0);
}
"""
fragment_shader_source = """
#version 330 core
out vec4 frag_color;
void main()
{
frag_color = vec4(1.0, 0.5, 0.2, 1.0);
}
"""
class OpenGLDrawingArea(Gtk.GLArea):
def __init__(self):
super().__init__()
self.connect("realize", self.on_realize)
self.connect("render", self.on_render)
self.connect("button-press-event", self.on_button_press_event)
self.set_has_depth_buffer(False)
self.set_has_stencil_buffer(False)
self.set_auto_render(True)
self.angle = 0.0
self.set_events(Gdk.EventMask.BUTTON_PRESS_MASK)
def on_realize(self, area):
ctx = self.get_context()
ctx.make_current()
# Compile shaders
vertex_shader = shaders.compileShader(vertex_shader_source, GL_VERTEX_SHADER)
fragment_shader = shaders.compileShader(fragment_shader_source, GL_FRAGMENT_SHADER)
self.shader_program = shaders.compileProgram(vertex_shader, fragment_shader)
# Define triangle vertices
self.vertices = np.array([
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0,
0.0, 0.5, 0.0
], dtype=np.float32)
# Create and bind Vertex Array Object
self.VAO = glGenVertexArrays(1)
glBindVertexArray(self.VAO)
# Create and bind Vertex Buffer Object
self.VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.VBO)
glBufferData(GL_ARRAY_BUFFER, self.vertices.nbytes, self.vertices, GL_STATIC_DRAW)
# Specify vertex attribute pointers
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), ctypes.c_void_p(0))
glEnableVertexAttribArray(0)
# Unbind buffers and VAO
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
def on_render(self, area, ctx):
glClearColor(0.0, 0.0, 0.0, 1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glUseProgram(self.shader_program)
glBindVertexArray(self.VAO)
# Apply rotation
rotation_matrix = np.array([
[np.cos(np.radians(self.angle)), -np.sin(np.radians(self.angle)), 0.0],
[np.sin(np.radians(self.angle)), np.cos(np.radians(self.angle)), 0.0],
[0.0, 0.0, 1.0]
], dtype=np.float32)
glUniformMatrix3fv(glGetUniformLocation(self.shader_program, "rotation"), 1, GL_TRUE, rotation_matrix)
glDrawArrays(GL_TRIANGLES, 0, 3)
glBindVertexArray(0)
def on_button_press_event(self, area, event):
if event.button == Gdk.BUTTON_PRIMARY: # Left mouse button
# Convert mouse coordinates to OpenGL coordinates
x, y = event.x, event.y
print(x,y)
width, height = area.get_allocated_width(), area.get_allocated_height()
gl_x = (2.0 * x / width - 1.0)
gl_y = (1.0 - 2.0 * y / height)
# Check if the mouse click is inside the triangle
if self.point_in_triangle(gl_x, gl_y):
print(gl_x,gl_y)
self.angle += 10.0 # Rotate clockwise by 10 degrees
self.queue_render() # Request redraw
def point_in_triangle(self, x, y):
# Check if the point (x, y) is inside the triangle
def sign(p1, p2, p3):
return (p1[0] - p3[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p3[1])
b1 = sign((x, y), self.vertices[:2], self.vertices[3:]) < 0.0
b2 = sign((x, y), self.vertices[3:], self.vertices[6:]) < 0.0
b3 = sign((x, y), self.vertices[6:], self.vertices[:2]) < 0.0
return (b1 == b2) and (b2 == b3)
class MainWindow(Gtk.Window):
def __init__(self):
super().__init__(title="OpenGL in GTK Window")
self.set_default_size(300, 300)
self.set_resizable(False) # Set window to be non-resizable
self.drawing_area = OpenGLDrawingArea()
self.add(self.drawing_area)
self.connect("destroy", Gtk.main_quit)
def main():
win = MainWindow()
win.show_all()
Gtk.main()
if __name__ == "__main__":
main()
Solved: the shader was wrong, did not rotate: