问题
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?
回答1:
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()
来源:https://stackoverflow.com/questions/54188353/how-do-i-make-3d-in-pyglet