使用Python和OpenGL实现3D立方体的交互式显示
简介
本文将介绍如何使用Python、Pygame和OpenGL创建一个可交互的3D立方体。这个立方体支持旋转、缩放等操作,是理解3D图形编程的良好入门示例。
技术栈
- Python
- Pygame:用于创建窗口和处理用户输入
- OpenGL:用于3D图形渲染
- PyOpenGL:Python的OpenGL绑定
核心功能
- 3D立方体的渲染
- 自动旋转
- 键盘控制旋转
- 鼠标滚轮缩放
- 视角重置
实现细节
1. 立方体的定义
首先,我们需要定义立方体的顶点和面:
vertices = (
(1, -1, -1), (1, 1, -1), (-1, 1, -1), (-1, -1, -1),
(1, -1, 1), (1, 1, 1), (-1, -1, 1), (-1, 1, 1)
)
surfaces = (
(0,1,2,3), # 后面
(3,2,7,6), # 左面
(6,7,5,4), # 前面
(4,5,1,0), # 右面
(1,5,7,2), # 上面
(4,0,3,6) # 下面
)
2. 绘制函数
立方体的绘制包括实心面和边框:
def draw_cube():
# 绘制实心面(绿色)
glColor3f(0.0, 1.0, 0.0)
glBegin(GL_QUADS)
for surface in surfaces:
for vertex in surface:
glVertex3fv(vertices[vertex])
glEnd()
# 绘制边框(白色)
glColor3f(1.0, 1.0, 1.0)
glBegin(GL_LINES)
for surface in surfaces:
for i in range(4):
glVertex3fv(vertices[surface[i]])
glVertex3fv(vertices[surface[(i+1)%4]])
glEnd()
3. 交互控制
实现了多种交互方式:
-
旋转控制:
- 方向键:手动控制旋转方向
- 空格键:切换自动旋转
- +/-键:调整旋转速度
-
视角控制:
- 鼠标滚轮:缩放
- R键:重置视角
4. 关键技术点
OpenGL初始化
glEnable(GL_DEPTH_TEST) # 启用深度测试
glDisable(GL_LIGHTING) # 禁用光照
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0) # 设置透视
矩阵变换
glLoadIdentity() # 重置矩阵
glTranslatef(0.0, 0.0, zoom) # 平移
glRotatef(rot_speed, 0, 1, 0) # 旋转
使用说明
-
控制方式:
- 方向键:控制旋转方向
- 空格键:开启/关闭自动旋转
- 鼠标滚轮:缩放
- R键:重置视角
- +/-键:调整旋转速度
-
运行环境:
pip install pygame PyOpenGL PyOpenGL_accelerate
完整代码
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
vertices = (
(1, -1, -1), (1, 1, -1), (-1, 1, -1), (-1, -1, -1),
(1, -1, 1), (1, 1, 1), (-1, -1, 1), (-1, 1, 1)
)
surfaces = (
(0,1,2,3), # 后面
(3,2,7,6), # 左面
(6,7,5,4), # 前面
(4,5,1,0), # 右面
(1,5,7,2), # 上面
(4,0,3,6) # 下面
)
def draw_cube():
glLineWidth(5.0)
# 绘制实心面
glDisable(GL_LIGHTING)
glColor3f(0.0, 1.0, 0.0) # 绿色
glBegin(GL_QUADS)
for surface in surfaces:
for vertex in surface:
glVertex3fv(vertices[vertex])
glEnd()
# 绘制边框
glColor3f(1.0, 1.0, 1.0) # 白色
glBegin(GL_LINES)
for surface in surfaces:
for i in range(4):
glVertex3fv(vertices[surface[i]])
glVertex3fv(vertices[surface[(i+1)%4]])
glEnd()
def main():
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
# 基础设置
glEnable(GL_DEPTH_TEST)
glDisable(GL_LIGHTING)
# 设置视角
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glTranslatef(0.0, 0.0, -5)
# 初始化变量
rot_speed = 1 # 旋转速度
auto_rotate = True # 自动旋转开关
zoom = -5 # 缩放程度
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
return
# 鼠标滚轮控制缩放
elif event.type == pygame.MOUSEWHEEL:
zoom += event.y * 0.5
glLoadIdentity()
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glTranslatef(0.0, 0.0, zoom)
# 空格键切换自动旋转
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
auto_rotate = not auto_rotate
# R键重置视角
elif event.key == pygame.K_r:
zoom = -5
glLoadIdentity()
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glTranslatef(0.0, 0.0, zoom)
keys = pygame.key.get_pressed()
# 方向键控制旋转
if keys[pygame.K_LEFT]:
glRotatef(rot_speed, 0, -1, 0)
if keys[pygame.K_RIGHT]:
glRotatef(rot_speed, 0, 1, 0)
if keys[pygame.K_UP]:
glRotatef(rot_speed, -1, 0, 0)
if keys[pygame.K_DOWN]:
glRotatef(rot_speed, 1, 0, 0)
# 调整旋转速度
if keys[pygame.K_PLUS] or keys[pygame.K_KP_PLUS]:
rot_speed = min(rot_speed + 0.1, 5.0)
if keys[pygame.K_MINUS] or keys[pygame.K_KP_MINUS]:
rot_speed = max(rot_speed - 0.1, 0.1)
# 自动旋转
if auto_rotate:
glRotatef(rot_speed, 3, 1, 1)
glClearColor(0.0, 0.0, 0.2, 1.0)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
draw_cube()
pygame.display.flip()
pygame.time.wait(10)
if __name__ == "__main__":
main()
总结
这个示例展示了如何使用Python和OpenGL创建一个基础的3D图形应用。通过这个例子,我们可以学习到:
- OpenGL的基本使用
- 3D图形的矩阵变换
- 用户输入处理
- 实时渲染循环的实现
这些知识点都是3D图形编程的基础,掌握它们将有助于开发更复杂的3D应用。