【发布时间】:2015-06-10 01:43:47
【问题描述】:
我最近对图形编程产生了兴趣,并尝试从使用 PyOpenGL 和 PyGame 制作一个简单的立方体开始。我已经设法让它旋转,但我无法让连续旋转正常工作。
我在空间中有一个简单的立方体,我想使用箭头键(最终使用鼠标)在全局 x 和 y 轴上旋转它。但是,我尝试应用到立方体的所有旋转都相对于立方体的方向在局部 x 和 y 轴上旋转它,而不是相对于观察者视角的一组全局轴。
我尝试的第一件事是使用 glRotatef,但这当然会导致局部旋转。环顾四周,我发现很多人都有类似的问题,除了“试试这个”或“使用四元数”之外,没有多少答案提供了太多信息,所以我尝试了四元数。我现在(大部分)了解四元数是如何工作的,但由于某种原因,我对它们的使用仍然会导致同样的问题,所以我想我可能在某个地方遗漏了一两步。
这是我正在使用的代码:
import numpy
from math import *
from quat import *
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
axis_points = (
(-6.0, 0.0, 0.0),
( 6.0, 0.0, 0.0),
( 0.0,-6.0, 0.0),
( 0.0, 6.0, 0.0),
( 0.0, 0.0,-6.0),
( 0.0, 0.0, 6.0)
)
axes = (
(0,1),
(2,3),
(4,5)
)
verticies = (
(-3.0,-3.0, 3.0),
(-3.0, 3.0, 3.0),
( 3.0, 3.0, 3.0),
( 3.0,-3.0, 3.0),
(-3.0,-3.0,-3.0),
(-3.0, 3.0,-3.0),
( 3.0, 3.0,-3.0),
( 3.0,-3.0,-3.0),
)
edges = (
(0,1),
(0,3),
(0,4),
(2,1),
(2,3),
(2,6),
(5,1),
(5,4),
(5,6),
(7,3),
(7,4),
(7,6)
)
surfaces = (
(0,1,2,3),
(3,2,6,7),
(7,6,5,4),
(4,5,1,0),
(1,5,6,2),
(4,0,3,7),
)
colors = (
(0.769,0.118,0.227), # Red
( 0.0,0.318,0.729), # Blue
( 1.0,0.345, 0.0), # Orange
( 0.0, 0.62,0.376), # Green
( 1.0, 1.0, 1.0), # White
( 1.0,0.835, 0.0), # Yellow
)
def Axis():
glBegin(GL_LINES)
glColor3f(1,1,1)
for axis in axes:
for point in axis:
glVertex3fv(axis_points[point])
glEnd()
def Cube():
glBegin(GL_QUADS)
for color,surface in zip(colors,surfaces):
glColor3fv(color)
for vertex in surface:
glVertex3fv(verticies[vertex])
glEnd()
glBegin(GL_LINES)
glColor3fv((0,0,0))
for edge in edges:
for vertex in edge:
glVertex3fv(verticies[vertex])
glEnd()
def main():
pygame.init()
display = (1800,1600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
# Using depth test to make sure closer colors are shown over further ones
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LESS)
# Default view
gluPerspective(45, (display[0]/display[1]), 0.05, 50.0)
glTranslatef(0.0,0.0,-25)
inc_x = 0
inc_y = 0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
print "Modelview Matrix:"
print glGetFloatv(GL_MODELVIEW_MATRIX)
#Rotating about the x axis
if event.key == pygame.K_UP:
inc_x = pi/100
if event.key == pygame.K_DOWN:
inc_x = -pi/100
# Rotating about the y axis
if event.key == pygame.K_LEFT:
inc_y = pi/100
if event.key == pygame.K_RIGHT:
inc_y = -pi/100
# Reset to default view
if event.key == pygame.K_SPACE:
glLoadIdentity()
gluPerspective(45, (display[0]/display[1]), 0.05, 50.0)
glTranslatef(0.0,0.0,-25)
if event.type == pygame.KEYUP:
# Stoping rotation
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
inc_x = 0.0
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
inc_y = 0.0
rot_x = normalize(axisangle_to_q((1.0,0.0,0.0), inc_x))
rot_y = normalize(axisangle_to_q((0.0,1.0,0.0), inc_y))
tot_rot = q_to_mat4(q_mult(rot_x,rot_y))
glMultMatrixf(tot_rot)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
Cube()
Axis()
pygame.display.flip()
pygame.time.wait(10)
main()
和
from math import *
import numpy
def normalize(v, tolerance=0.00001):
mag2 = sum(n * n for n in v)
if abs(mag2 - 1.0) > tolerance:
mag = sqrt(mag2)
v = tuple(n / mag for n in v)
return v
def q_mult(q1, q2):
w1, x1, y1, z1 = q1
w2, x2, y2, z2 = q2
w = w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2
x = w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2
y = w1 * y2 + y1 * w2 + z1 * x2 - x1 * z2
z = w1 * z2 + z1 * w2 + x1 * y2 - y1 * x2
return w, x, y, z
def q_conjugate(q):
w, x, y, z = q
return (w, -x, -y, -z)
def qv_mult(q1, v1):
q2 = (0.0,) + v1
return q_mult(q_mult(q1, q2), q_conjugate(q1))[1:]
def axisangle_to_q(v, theta):
v = normalize(v)
x, y, z = v
theta /= 2
w = cos(theta)
x = x * sin(theta)
y = y * sin(theta)
z = z * sin(theta)
return w, x, y, z
def q_to_axisangle(q):
w, v = q[0], q[1:]
theta = acos(w) * 2.0
return normalize(v), theta
def q_to_mat4(q):
w, x, y, z = q
return numpy.array(
[[1 - 2*y*y - 2*z*z, 2*x*y - 2*z*w, 2*x*z + 2*y*w, 0],
[2*x*y + 2*z*w, 1 - 2*x*x - 2*z*z, 2*y*z - 2*x*w, 0],
[2*x*z - 2*y*w, 2*y*z + 2*x*w, 1 - 2*x*x - 2*y*y, 0],
[0, 0, 0, 1] ],'f')
我在某人对关于在 python 中实现四元数的堆栈溢出问题的回答中找到了四元数方法的代码,但我找不到它的链接。
我使用的逻辑也是基于另一个堆栈溢出问题 (opengl matrix rotation quaternions)。我和问这个问题的人有几乎完全相同的问题。但是,我不太明白他的解决方案与他最初使用四元数的尝试有何不同。这可能是由于不精通 C/C++。
【问题讨论】:
标签: python opengl transformation quaternions pyopengl