Get openGLwidget linked with Qtimer update - python

I m trying to build a gui with Pyqt5. and withing the gui there is an openGLwidget, that should contain a rotating cube. But i cannot figure out how to make the cube rotate.
Thank you.
this is the setup function
def setupUI(self):
self.openGLWidget.initializeGL()
self.openGLWidget.resizeGL(651,551)
self.openGLWidget.paintGL = self.paintGL
self.rotX=10.0
self.rotY=0.0
self.rotZ=0.0
timer = QTimer(self)
timer.timeout.connect(self.Update)
timer.start(1000)
and here is the paintGL and update functions:
def paintGL(self):
glClear(GL_COLOR_BUFFER_BIT)
glColor3f(0,1,0)
self.Cube()
gluPerspective(45, 651/551, 1, 100.0)
glTranslatef(0.0,0.0, -5)
glRotate(self.rotX, 1.0, 0.0, 0.0)
def Update(self):
glClear(GL_COLOR_BUFFER_BIT)
self.rotX+=10
self.openGLWidget.paintGL = self.paintGL

There are different current matrices, see glMatrixMode. The projection matrix should be set to the current GL_PROJECTION and the model view matrix to GL_MODELVIEW.
The operations which manipulate the current matrix (like gluPerspective, glTranslate, glRotate), do not just set a matrix, they specify a matrix and multiply the current matrix by the new matrix. Thus you have to set the Identity matrix at the begin of every frame, by glLoadIdentity:
def paintGL(self):
glClear(GL_COLOR_BUFFER_BIT)
glColor3f(0,1,0)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45, 651/551, 1, 100.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glTranslatef(0, 0, -7)
glRotate(self.rotX, 1, 0, 0)
self.Cube()
Invoke update() to update respectively repaint a QOpenGLWidget:
timer = QTimer(self)
timer.timeout.connect(self.Update)
timer.start(10)
def Update(self):
self.rotX += 1
self.openGLWidget.update()

Related

Draw 2D OpenGL points with a delay in python

Suppose I want to draw 3 points in my window. One point at a time with 1 second delay each. So I want the window to open when I run the code, then wait 1 second and draw first point and then wait another second and write the second point in the same window.
But what is happening is that, when I run the code, it shows nothing and then shows all three points at once after 3 seconds have passed.
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
import time
def draw_points(x0,y0):
glPointSize(5)
glBegin(GL_POINTS)
glVertex2f(x0,y0)
glEnd()
def iterate():
glViewport(0, 0, 1000, 1000)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0.0, 1000, 0.0, 1000, 0.0, 1.0)
glMatrixMode (GL_MODELVIEW)
glLoadIdentity()
def showScreen():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
iterate()
glColor3f(255, 255, 255)
draw_points(200,200)
time.sleep(1)
draw_points(300,300)
time.sleep(1)
draw_points(400,400)
glutSwapBuffers()
glutInit()
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(1000, 1000)
glutInitWindowPosition(0, 0)
wind = glutCreateWindow(b"")
glutDisplayFunc(showScreen)
glutMainLoop()
Don't wait in the application loop. The application executed continuously and the scene is redrawn in every frame. Measure the time and draw the points depending on the time elapsed. You can get the elapsed time in milliseconds with glutGet(GLUT_ELAPSED_TIME):
def showScreen():
elapesed_ms = glutGet(GLUT_ELAPSED_TIME)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
iterate()
glColor3f(255, 255, 255)
draw_points(200,200)
if elapesed_ms > 1000:
draw_points(300,300)
if elapesed_ms > 2000:
draw_points(400,400)
glutSwapBuffers()

Pygame and PyOpenGL: No shapes appear on screen

I have created a complete snake game using C++ and OpenGL before, and I want to do the same using Python, pygame, and PyOpenGL. The current problem I have is that after I spawn a fruit, it does not appear on the screen. Here's the code for my main function:
def main(): # Main function
# Initialize game components
game = Game(800, 600)
test_fruit = game.spawn_fruit(Point(100, 100))
# Initialize pygame module
pygame.init()
pygame.display.set_mode(game.get_window_size(), DOUBLEBUF | OPENGL)
pygame.display.set_caption("Python Game")
# Define variable to control main loop
running = True
# Main loop
while running:
# event handling, gets all event from the event queue
for event in pygame.event.get():
# only do something if the event is of type QUIT
if event.type == pygame.QUIT:
# change the value to False, to exit the main loop
running = False
# Modify game properties
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
game.draw_shapes()
pygame.display.flip()
pygame.time.wait(5)
It's possible I'm missing a pygame or pyopengl function, but I'm not sure. I've also tried changing pygame.display.flip() to pygame.display.update(), yet it gives me an error ("cannot update an OpenGL display") instead.
Here's the code for the shape I am attempting to display:
class Circle:
def __init__(self, pivot: Point, radius: int, sides: int, fill: bool, color: Color):
self.pivot = pivot
self.radius = radius
self.sides = sides
self.fill = fill
self.color = color
# Draw the shape of the circle
def draw(self):
glColor3f(self.color.r, self.color.g, self.color.b)
if self.fill:
glBegin(GL_POLYGON)
else:
glBegin(GL_LINE_LOOP)
for i in range(100):
cosine = self.radius * cos(i*2*pi/self.sides) + self.pivot.x
sine = self.radius * sin(i*2*pi/self.sides) + self.pivot.y
glVertex2f(cosine, sine)
glEnd()
OpenGL coordinates are in range [-1.0, 1.0] (Normalized Device Space). The Normalized device space is a unique cube from the left, bottom, near (-1, -1, -1) to the right, top, far (1, 1, 1).
If you want to use "window" coordinates, you must specify an Orthographic projection using glOrtho:
glOrtho(0, 800, 600, 0, -1, 1)
Choose the matrix mode with glMatrixMode and load the Identity matrix with glLoadIdentity.
Example:
def main(): # Main function
# Initialize game components
game = Game(800, 600)
test_fruit = game.spawn_fruit(Point(100, 100))
# Initialize pygame module
pygame.init()
pygame.display.set_mode(game.get_window_size(), DOUBLEBUF | OPENGL)
pygame.display.set_caption("Python Game")
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0, 800, 600, 0, -1, 1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
# Define variable to control main loop
running = True
# [...]

Why this octagon doesn't fit window?

I was trying to create an octagon:
import pyglet
from pyglet.gl import *
class mywindow(pyglet.window.Window):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.set_minimum_size(300,300)
def on_draw(self):
self.clear()
glBegin(GL_POLYGON)
glColor3ub(255,0,0)
glVertex2f(0,0)
glVertex2f(1.0,0)
glVertex2f(1.5,0.5)
glVertex2f(1.5,1.5)
glVertex2f(1.0,2.0)
glVertex2f(0,2.0)
glVertex2f(-0.5,1.5)
glVertex2f(-0.5,0.5)
glEnd()
def on_resize(self, width, height):
glViewport(10,10, width, height)
window = mywindow(300,300,"deneme",True)
pyglet.app.run()
everything seems fine. But when I run this code I see this output:
any idea how can I fix it?
Your polygon is simply too big !
By dividing the coordinates by 10 :
glVertex2f(0,0)
glVertex2f(0.1,0)
glVertex2f(0.15,0.05)
glVertex2f(0.15,.15)
glVertex2f(0.1,.2)
glVertex2f(0,0.2)
glVertex2f(-0.05,0.15)
glVertex2f(-0.05,0.05)
You will be able to see your octagon now
Most of the octagon is out of the viewport. By default the bottom left coordinate of the viewport is (-1, -1) and the top right is (1, 1).
You can set an orthographic projection matrix, to change the projected area (respectively volume), by glOrtho:
class mywindow(pyglet.window.Window):
# [...]
def on_resize(self, width, height):
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(-3, 3, -3, 3, -1, 1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()

Change perspective of a PyOpenGL widget

I am trying to change the perspective of my scene in a PyQt5 OpenGL widget. I know I have to override some methods, but I do not know which one should I use.
def initializeGL(self):
glClear(GL_COLOR_BUFFER_BIT)
glEnable(GL_DEPTH_TEST)
def paintGL(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glBegin(GL_LINES)
# More code
Where should I use the glOrtho function? And where can I found information about overriding this methods?
When I go to the declaration of this methods, they have a pass statement and nothing else, how and when are they executed? Should I use QPainter instead of OpenGL?
def __init__(self, parent=None):
super().__init__(parent)
self._x = 0
self._y = -0.3
self._z = 0.5
self._rz = 0
self._ry = -0.5
self.vertices_vertical = [[1000, 1000, 000], [1000, -1000, 000],
[-1000, -1000, 000], [-1000, 1000, 000]]
self.vertices_horizontal = [[1000, 000, -1000], [1000, 000, 1000],
[-1000, 000, 1000], [-1000, 000, -1000]]
def initializeGL(self):
glClear(GL_COLOR_BUFFER_BIT)
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0, 1000, 750, 0, -1, 1)
def paintGL(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glBegin(GL_LINES)
glColor3d(1, 0, 0)
glVertex3d(0, 0, 0)
glVertex3d(1, 0, 0)
glColor3d(0, 1, 0)
glVertex3d(0, 0, 0)
glVertex3d(0, 1, 0)
glColor3d(0, 0, 1)
glVertex3d(0, 0, 0)
glVertex3d(0, 0, 1)
glEnd()
# glLoadIdentity()
glTranslate(self._x, self._y, self._z)
glRotate(self._ry, 0, 1, 0)
glRotate(self._rz, 0, 0, 1)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR)
glBegin(GL_QUADS)
glColor4fv((0, 1, 0, 0.6))
for vertex in range(4):
glVertex3fv(self.vertices_vertical[vertex])
glColor4fv((1, 0, 0, 0.6))
for vertex in range(4):
glVertex3fv(self.vertices_horizontal[vertex])
glEnd()
glDisable(GL_BLEND)
In Legacy OpenGL the current matrix is a global state. There are different kind of matrices, for each kind of matrix exists a matrix stack. The top of the matrix stack is the current matrix. The matrix stack which is the target for subsequent matrix operations like glOrtho, glPushMatrix/glPopMatrix, glLoadIdentity,etc. can be chosen by glMatrixMode.
Each vertex coordinate (glVertex) is transformed by the model view matrix (GL_MODELVIEW) and the projection matrix (GL_PROJECTION).
Chose the projection matrix mode in initializeGL. Set the Identity matrix and set the orthographic projection by glOrtho. Note, glOrtho dose not only set a matrix, it defines a Orthographic projection matrix and multiplies the current matrix by the new matrix.
e.g. Set an orthographic projection, which transforms "window" coordinates to the normalized device space. In the following (windowdWidth, windowHeight) is the size of the window:
def initializeGL(self):
glClear(GL_COLOR_BUFFER_BIT)
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0, windowdWidth, windowHeight, 0, -1, 1)
Use the model view matrix mode to set the model view transformations, before you draw the model:
def paintGL(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
# model view transformations
# [...]
glBegin(GL_LINES)
# [...]
glEnd()

How do I make 3D in pyglet?

I was trying to create using OpenGL, Python and pyglet, a flat triangle in 3D space, I saw some tutorials on the internet, some videos on YouTube, and in the end I wrote this code down there, the problem is that it did not work as I expected, I thought that if I tried to spin, I would see the triangle turning flat, and when I walked away, the triangle did not have to diminish?
import pyglet
from pyglet.gl import *
config = Config(sample_buffers=1, samples=8)
tela = pyglet.window.Window(height=500, width=500, config=config)
glViewport(0,0,500,500)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(35,1,0.1,1000)
glMatrixMode(GL_MODELVIEW)
#tela.event
def on_draw():
glBegin(GL_POLYGON)
glVertex3f(10,10,0)
glVertex3f(100,10,0)
glVertex3f(50,100,0)
glEnd()
glFlush()
#tela.event
def on_key_press(s,m):
tela.clear()
if s == pyglet.window.key.W:
glTranslatef(0,0,1)
if s == pyglet.window.key.S:
glTranslatef(0,0,-1)
if s == pyglet.window.key.A:
glRotatef(1,0,1,0)
if s == pyglet.window.key.D:
glRotatef(-1,0,1,0)
pyglet.app.run()
When I run the code this appears:
And when I try to spin the scenario it happens:
Does anyone know where I'm going wrong?
The initialization of the viewport and the sting pf the projection and model view matrix is useless
glViewport(0,0,500,500)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(35,1,0.1,1000)
glMatrixMode(GL_MODELVIEW)
because the viewport and an orthographic projection is set when the application is started.
See pyglet - The OpenGL interface:
[...] pyglet sets up the viewport and an orthographic projection on each window automatically.
If you would use the perspective projection
gluPerspective(35,1,0.1,1000)
then the triangle would disappear, because it would be clipped by the near plane of the perspective projection (0.1).
To solve the issue, put the setup of perspective projection to the draw event:
#tela.event
def on_draw():
tela.clear()
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(90, 1, 0.1, 100)
I thought that if I tried to spin, I would see the triangle turning flat, and when I walked away, the triangle did not have to diminish?
In view space, the x axis points from the left to the right and the y axis points from the bottom to the top.
To rotate in the XY plane, you have to rotate around the Z axis.
Define a position and an Y-angle for the triangle. The Z coordinate has to be negative and the distance to the object has to be in between the near and far plane. If near is 0.1 and far is 100, then:
0.1 <= -z <= 100
e.g.
pos = [0, 0, -20]
rot_y = 0
Manipulate the position and the angle in the event:
#tela.event
def on_key_press(s,m):
global pos_z, rot_y
if s == pyglet.window.key.W:
pos[2] -= 1
if s == pyglet.window.key.S:
pos[2] += 1
if s == pyglet.window.key.A:
rot_y += 5
if s == pyglet.window.key.D:
rot_y -= 5
Apply the translation and the rotation to the model view matrix stack in draw:
#tela.event
def on_draw():
global pos_z, rot_y
# [...]
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glTranslatef(*pos)
glRotatef(rot_y, 0, 1, 0)
Draw an object which is arranged around (0, 0, 0). Note the position of the object is set by pos and in perspective projection the origin (0, 0, 0) is in the center of the window:
glBegin(GL_POLYGON)
glVertex3f(-5,-5,0)
glVertex3f(5,-5,0)
glVertex3f(0,5,0)
glEnd()
Full code with the suggested changes applied:
import pyglet
from pyglet.gl import *
pos = [0, 0, -20]
rot_y = 0
config = Config(sample_buffers=1, samples=8)
tela = pyglet.window.Window(height=500, width=500, config=config)
#tela.event
def on_draw():
global pos_z, rot_y
tela.clear()
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(90, 1, 0.1, 100)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glTranslatef(*pos)
glRotatef(rot_y, 0, 1, 0)
glBegin(GL_POLYGON)
glVertex3f(-5,-5,0)
glVertex3f(5,-5,0)
glVertex3f(0,5,0)
glEnd()
glFlush()
#tela.event
def on_key_press(s,m):
global pos_z, rot_y
if s == pyglet.window.key.W:
pos[2] -= 1
if s == pyglet.window.key.S:
pos[2] += 1
if s == pyglet.window.key.A:
rot_y += 5
if s == pyglet.window.key.D:
rot_y -= 5
pyglet.app.run()

Categories

Resources