首先安装PyOpengl

  1. pip install PyOpenGL PyOpenGL_accelerate

64bit下可能存在glut的问题,解决如下

下载地址:(选择适合自己的版本)http://www.lfd.uci.edu/~gohlke/pythonlibs/#pyopengl

下载下来的whl文件,用pip install file_name.whl进行安装后,问题解决。

在Ubuntu环境下

sudo apt-get install python-opengl

工程文件下载

项目效果

程序框架简介:
primitive 负责具体渲染的模型,主要是生成显示列表

  1. G_OBJ_PLANE = 1
    G_OBJ_SPHERE = 2
    G_OBJ_CUBE = 3

这些模型会在程序初始化的时候运行一次 Viewer的init函数中。

  1.  
  2. 主框架是Viewer文件
    MainLoop 里面定时调用这里注册的render函数

render 每次设置好MV矩阵,调用scene里面的render

Scene本身是一个节点的列表。每个节点会调用相应的显示列表来渲染。

代码Viewer.py

  1. # -*- coding: utf8 -*-
  2. from OpenGL.GL import glCallList, glClear, glClearColor, glColorMaterial, glCullFace, glDepthFunc, glDisable, glEnable,\
  3. glFlush, glGetFloatv, glLightfv, glLoadIdentity, glMatrixMode, glMultMatrixf, glPopMatrix, \
  4. glPushMatrix, glTranslated, glViewport, \
  5. GL_AMBIENT_AND_DIFFUSE, GL_BACK, GL_CULL_FACE, GL_COLOR_BUFFER_BIT, GL_COLOR_MATERIAL, \
  6. GL_DEPTH_BUFFER_BIT, GL_DEPTH_TEST, GL_FRONT_AND_BACK, GL_LESS, GL_LIGHT0, GL_LIGHTING, \
  7. GL_MODELVIEW, GL_MODELVIEW_MATRIX, GL_POSITION, GL_PROJECTION, GL_SPOT_DIRECTION
  8. from OpenGL.constants import GLfloat_3, GLfloat_4
  9. from OpenGL.GLU import gluPerspective, gluUnProject
  10. from OpenGL.GLUT import glutCreateWindow, glutDisplayFunc, glutGet, glutInit, glutInitDisplayMode, \
  11. glutInitWindowSize, glutMainLoop, \
  12. GLUT_SINGLE, GLUT_RGB, GLUT_WINDOW_HEIGHT, GLUT_WINDOW_WIDTH
  13. import numpy
  14. from numpy.linalg import norm, inv
  15. from primitive import init_primitives
  16. from Scene import Scene
  17. from node import Sphere
  18. from node import SnowFigure,Cube,Plane
  19.  
  20. class Viewer(object):
  21. def __init__(self):
  22. """ Initialize the viewer. """
  23. #初始化接口,创建窗口并注册渲染函数
  24. self.init_interface()
  25. #初始化opengl的配置
  26. self.init_opengl()
  27. #初始化3d场景
  28. self.init_scene()
  29. #初始化交互操作相关的代码
  30. self.init_interaction()
  31. init_primitives()
  32.  
  33. def init_interface(self):
  34. """ 初始化窗口并注册渲染函数 """
  35. glutInit()
  36. glutInitWindowSize(640, 480)
  37. glutCreateWindow("3D Modeller")
  38. glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB)
  39. #注册窗口渲染函数
  40. glutDisplayFunc(self.render)
  41.  
  42. def init_opengl(self):
  43. """ 初始化opengl的配置 """
  44. #模型视图矩阵
  45. self.inverseModelView = numpy.identity(4)
  46. #模型视图矩阵的逆矩阵
  47. self.modelView = numpy.identity(4)
  48.  
  49. #开启剔除操作效果
  50. glEnable(GL_CULL_FACE)
  51. #取消对多边形背面进行渲染的计算(看不到的部分不渲染)
  52. glCullFace(GL_BACK)
  53. #开启深度测试
  54. glEnable(GL_DEPTH_TEST)
  55. #测试是否被遮挡,被遮挡的物体不予渲染
  56. glDepthFunc(GL_LESS)
  57. #启用0号光源
  58. glEnable(GL_LIGHT0)
  59. #设置光源的位置
  60. glLightfv(GL_LIGHT0, GL_POSITION, GLfloat_4(0, 0, 1, 0))
  61. #设置光源的照射方向
  62. glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, GLfloat_3(0, 0, -1))
  63. #设置材质颜色
  64. glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
  65. glEnable(GL_COLOR_MATERIAL)
  66. #设置清屏的颜色
  67. glClearColor(0.4, 0.4, 0.4, 0.0)
  68.  
  69. def init_scene(self):
  70. #初始化场景,之后实现
  71. # 创建一个场景实例
  72. self.scene = Scene()
  73. # 初始化场景内的对象
  74. self.create_sample_scene()
  75.  
  76. def create_sample_scene(self):
  77. # 创建一个球体
  78. sphere_node = Sphere()
  79. # 设置球体的颜色
  80. sphere_node.color_index = 2
  81. # 将球体放进场景中,默认在正中央
  82. sphere_node.translate(2, 2, 0)
  83. sphere_node.scale(4)
  84. self.scene.add_node(sphere_node)
  85.  
  86. # 添加小雪人
  87. hierarchical_node = SnowFigure()
  88. hierarchical_node.translate(-2, 0, -2)
  89. hierarchical_node.scale(2)
  90. self.scene.add_node(hierarchical_node)
  91.  
  92. #添加立方体
  93. cube_node=Cube()
  94. cube_node.color_index=5
  95. cube_node.translate(5,5,0)
  96. cube_node.scale(1.8)
  97. self.scene.add_node(cube_node)
  98.  
  99. #添加Plane
  100. plane_node=Plane()
  101. plane_node.color_index=2
  102. self.scene.add_node(plane_node)
  103.  
  104. def init_interaction(self):
  105. #初始化交互操作相关的代码,之后实现
  106. pass
  107.  
  108. def main_loop(self):
  109. #程序主循环开始
  110. glutMainLoop()
  111.  
  112. def render(self):
  113. #程序进入主循环后每一次循环调用的渲染函数
  114. # 初始化投影矩阵
  115. self.init_view()
  116.  
  117. # 启动光照
  118. glEnable(GL_LIGHTING)
  119. # 清空颜色缓存与深度缓存
  120. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
  121.  
  122. # 设置模型视图矩阵,目前为止用单位矩阵就行了。
  123. glMatrixMode(GL_MODELVIEW)
  124. glPushMatrix()
  125. glLoadIdentity()
  126.  
  127. # 渲染场景
  128. self.scene.render()
  129.  
  130. # 每次渲染后复位光照状态
  131. glDisable(GL_LIGHTING)
  132. glPopMatrix()
  133. # 把数据刷新到显存上
  134. glFlush()
  135. def init_view(self):
  136. """ 初始化投影矩阵 """
  137. xSize, ySize = glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT)
  138. #得到屏幕宽高比
  139. aspect_ratio = float(xSize) / float(ySize)
  140.  
  141. #设置投影矩阵
  142. glMatrixMode(GL_PROJECTION)
  143. glLoadIdentity()
  144.  
  145. #设置视口,应与窗口重合
  146. glViewport(0, 0, xSize, ySize)
  147. #设置透视,摄像机上下视野幅度70度
  148. #视野范围到距离摄像机1000个单位为止。
  149. gluPerspective(70, aspect_ratio, 0.1, 1000.0)
  150. #摄像机镜头从原点后退15个单位
  151. glTranslated(0, 0, -15)
  152. if __name__ == "__main__":
  153. viewer = Viewer()
  154. viewer.main_loop()

Scene.py

  1. # -*- coding: utf8 -*-
  2. class Scene(object):
  3.  
  4. #放置节点的深度,放置的节点距离摄像机15个单位
  5. PLACE_DEPTH = 15.0
  6.  
  7. def __init__(self):
  8. #场景下的节点队列
  9. self.node_list = list()
  10.  
  11. def add_node(self, node):
  12. """ 在场景中加入一个新节点 """
  13. self.node_list.append(node)
  14.  
  15. def render(self):
  16. """ 遍历场景下所有节点并渲染 """
  17. for node in self.node_list:
  18. node.render()

color.py

  1. # -*- coding: utf8 -*-
  2. MAX_COLOR = 9
  3. MIN_COLOR = 0
  4. COLORS = { # RGB Colors
  5. 0: (1.0, 1.0, 1.0),
  6. 1: (0.05, 0.05, 0.9),
  7. 2: (0.05, 0.9, 0.05),
  8. 3: (0.9, 0.05, 0.05),
  9. 4: (0.9, 0.9, 0.0),
  10. 5: (0.1, 0.8, 0.7),
  11. 6: (0.7, 0.2, 0.7),
  12. 7: (0.7, 0.7, 0.7),
  13. 8: (0.4, 0.4, 0.4),
  14. 9: (0.0, 0.0, 0.0),
  15. }

node.py

  1. # -*- coding: utf8 -*-
  2. import random
  3. from OpenGL.GL import glCallList, glColor3f, glMaterialfv, glMultMatrixf, glPopMatrix, glPushMatrix, \
  4. GL_EMISSION, GL_FRONT
  5. import numpy
  6. import color
  7. from primitive import G_OBJ_SPHERE,G_OBJ_CUBE,G_OBJ_PLANE
  8. from transform import scaling, translation
  9. class Node(object):
  10. def __init__(self):
  11. #该节点的颜色序号
  12. self.color_index = random.randint(color.MIN_COLOR, color.MAX_COLOR)
  13. #该节点的平移矩阵,决定了该节点在场景中的位置
  14. self.translation_matrix = numpy.identity(4)
  15. #该节点的缩放矩阵,决定了该节点的大小
  16. self.scaling_matrix = numpy.identity(4)
  17.  
  18. def render(self):
  19. """ 渲染节点 """
  20. glPushMatrix()
  21. #实现平移
  22. glMultMatrixf(numpy.transpose(self.translation_matrix))
  23. #实现缩放
  24. glMultMatrixf(self.scaling_matrix)
  25. cur_color = color.COLORS[self.color_index]
  26. #设置颜色
  27. glColor3f(cur_color[0], cur_color[1], cur_color[2])
  28. #渲染对象模型
  29. self.render_self()
  30. glPopMatrix()
  31.  
  32. def render_self(self):
  33. raise NotImplementedError(
  34. "The Abstract Node Class doesn't define 'render_self'")
  35.  
  36. def translate(self, x, y, z):
  37. self.translation_matrix = numpy.dot(self.translation_matrix, translation([x, y, z]))
  38.  
  39. def scale(self, s):
  40. self.scaling_matrix = numpy.dot(self.scaling_matrix, scaling([s,s,s]))
  41.  
  42. class Primitive(Node):
  43. def __init__(self):
  44. super(Primitive, self).__init__()
  45. self.call_list = None
  46.  
  47. def render_self(self):
  48. glCallList(self.call_list)
  49.  
  50. class Sphere(Primitive):
  51. """ 球形图元 """
  52.  
  53. def __init__(self):
  54. super(Sphere, self).__init__()
  55. self.call_list = G_OBJ_SPHERE
  56. class Cube(Primitive):
  57. """ 立方体图元 """
  58. def __init__(self):
  59. super(Cube, self).__init__()
  60. self.call_list = G_OBJ_CUBE
  61.  
  62. class Plane(Primitive):
  63. def __init__(self):
  64. super(Plane,self).__init__()
  65. self.call_list=G_OBJ_PLANE
  66.  
  67. class HierarchicalNode(Node):
  68. def __init__(self):
  69. super(HierarchicalNode, self).__init__()
  70. self.child_nodes = []
  71.  
  72. def render_self(self):
  73. for child in self.child_nodes:
  74. child.render()
  75.  
  76. class SnowFigure(HierarchicalNode):
  77. def __init__(self):
  78. super(SnowFigure, self).__init__()
  79. self.child_nodes = [Sphere(), Sphere(), Sphere()]
  80. self.child_nodes[0].translate(0, -0.6, 0)
  81. self.child_nodes[1].translate(0, 0.1, 0)
  82. self.child_nodes[1].scale(0.8)
  83. self.child_nodes[2].translate(0, 0.75, 0)
  84. self.child_nodes[2].scale(0.7)
  85. for child_node in self.child_nodes:
  86. child_node.color_index = color.MIN_COLOR

transform.py

  1. # -*- coding: utf8 -*-
  2. import numpy
  3.  
  4. def translation(displacement):
  5. """ 生成平移矩阵 """
  6. t = numpy.identity(4)
  7. t[0, 3] = displacement[0]
  8. t[1, 3] = displacement[1]
  9. t[2, 3] = displacement[2]
  10. return t
  11.  
  12. def scaling(scale):
  13. """ 生成缩放矩阵 """
  14. s = numpy.identity(4)
  15. s[0, 0] = scale[0]
  16. s[1, 1] = scale[1]
  17. s[2, 2] = scale[2]
  18. s[3, 3] = 1
  19. return s

primitive.py

  1. # -*- coding: utf8 -*-
  2. from OpenGL.GL import glBegin, glColor3f, glEnd, glEndList, glLineWidth, glNewList, glNormal3f, glVertex3f, \
  3. GL_COMPILE, GL_LINES, GL_QUADS
  4. from OpenGL.GLU import gluDeleteQuadric, gluNewQuadric, gluSphere
  5.  
  6. G_OBJ_PLANE = 1
  7. G_OBJ_SPHERE = 2
  8. G_OBJ_CUBE = 3
  9. def make_plane():
  10. glNewList(G_OBJ_PLANE, GL_COMPILE)
  11. glBegin(GL_LINES)
  12. glColor3f(0, 0, 0)
  13. for i in xrange(41):
  14. glVertex3f(-10.0 + 0.5 * i, 0, -10)
  15. glVertex3f(-10.0 + 0.5 * i, 0, 10)
  16. glVertex3f(-10.0, 0, -10 + 0.5 * i)
  17. glVertex3f(10.0, 0, -10 + 0.5 * i)
  18.  
  19. # Axes
  20. glEnd()
  21. glLineWidth(5)
  22.  
  23. glBegin(GL_LINES)
  24. glColor3f(0.5, 0.7, 0.5)
  25. glVertex3f(0.0, 0.0, 0.0)
  26. glVertex3f(5, 0.0, 0.0)
  27. glEnd()
  28.  
  29. glBegin(GL_LINES)
  30. glColor3f(0.5, 0.7, 0.5)
  31. glVertex3f(0.0, 0.0, 0.0)
  32. glVertex3f(0.0, 5, 0.0)
  33. glEnd()
  34.  
  35. glBegin(GL_LINES)
  36. glColor3f(0.5, 0.7, 0.5)
  37. glVertex3f(0.0, 0.0, 0.0)
  38. glVertex3f(0.0, 0.0, 5)
  39. glEnd()
  40.  
  41. # Draw the Y.
  42. glBegin(GL_LINES)
  43. glColor3f(0.0, 0.0, 0.0)
  44. glVertex3f(0.0, 5.0, 0.0)
  45. glVertex3f(0.0, 5.5, 0.0)
  46. glVertex3f(0.0, 5.5, 0.0)
  47. glVertex3f(-0.5, 6.0, 0.0)
  48. glVertex3f(0.0, 5.5, 0.0)
  49. glVertex3f(0.5, 6.0, 0.0)
  50.  
  51. # Draw the Z.
  52. glVertex3f(-0.5, 0.0, 5.0)
  53. glVertex3f(0.5, 0.0, 5.0)
  54. glVertex3f(0.5, 0.0, 5.0)
  55. glVertex3f(-0.5, 0.0, 6.0)
  56. glVertex3f(-0.5, 0.0, 6.0)
  57. glVertex3f(0.5, 0.0, 6.0)
  58.  
  59. # Draw the X.
  60. glVertex3f(5.0, 0.0, 0.5)
  61. glVertex3f(6.0, 0.0, -0.5)
  62. glVertex3f(5.0, 0.0, -0.5)
  63. glVertex3f(6.0, 0.0, 0.5)
  64.  
  65. glEnd()
  66. glLineWidth(1)
  67. glEndList()
  68.  
  69. def make_sphere():
  70. """ 创建球形的渲染函数列表 """
  71. glNewList(G_OBJ_SPHERE, GL_COMPILE)
  72. quad = gluNewQuadric()
  73. gluSphere(quad, 0.5, 30, 30)
  74. gluDeleteQuadric(quad)
  75. glEndList()
  76.  
  77. def make_cube():
  78. glNewList(G_OBJ_CUBE, GL_COMPILE)
  79. vertices = [((-0.5, -0.5, -0.5), (-0.5, -0.5, 0.5), (-0.5, 0.5, 0.5), (-0.5, 0.5, -0.5)),
  80. ((-0.5, -0.5, -0.5), (-0.5, 0.5, -0.5), (0.5, 0.5, -0.5), (0.5, -0.5, -0.5)),
  81. ((0.5, -0.5, -0.5), (0.5, 0.5, -0.5), (0.5, 0.5, 0.5), (0.5, -0.5, 0.5)),
  82. ((-0.5, -0.5, 0.5), (0.5, -0.5, 0.5), (0.5, 0.5, 0.5), (-0.5, 0.5, 0.5)),
  83. ((-0.5, -0.5, 0.5), (-0.5, -0.5, -0.5), (0.5, -0.5, -0.5), (0.5, -0.5, 0.5)),
  84. ((-0.5, 0.5, -0.5), (-0.5, 0.5, 0.5), (0.5, 0.5, 0.5), (0.5, 0.5, -0.5))]
  85. normals = [(-1.0, 0.0, 0.0), (0.0, 0.0, -1.0), (1.0, 0.0, 0.0), (0.0, 0.0, 1.0), (0.0, -1.0, 0.0), (0.0, 1.0, 0.0)]
  86.  
  87. glBegin(GL_QUADS)
  88. for i in xrange(6):
  89. glNormal3f(normals[i][0], normals[i][1], normals[i][2])
  90. for j in xrange(4):
  91. glVertex3f(vertices[i][j][0], vertices[i][j][1], vertices[i][j][2])
  92. glEnd()
  93. glEndList()
  94.  
  95. def init_primitives():
  96. """ 初始化所有的图元渲染函数列表 """
  97. make_plane()
  98. make_sphere()
  99. make_cube()

Python>>>创建一个简单的3D场景的更多相关文章

  1. Python创建一个简单的区块链

    区块链(Blockchain)是一种分布式账本(listributed ledger),它是一种仅供增加(append-only),内容不可变(immutable)的有序(ordered)链式数据结构 ...

  2. 基于python创建一个简单的HTTP-WEB服务器

    背景 大多数情况下主机资源只有开发和测试相关人员可以登录直接操作,且有些特定情况"答辩.演示.远程"等这些场景下是无法直接登录主机的.web是所有终端用户都可以访问了,解决了人员权 ...

  3. python创建一个简单的服务

    python -m http.server 8000 --bind 0.0.0.0 8000为端口 0.0.0.0允许远程访问

  4. 通过创建一个简单的骰子游戏来探究 Python

    在我的这系列的第一篇文章 中, 我已经讲解如何使用 Python 创建一个简单的.基于文本的骰子游戏.这次,我将展示如何使用 Python 模块 Pygame 来创建一个图形化游戏.它将需要几篇文章才 ...

  5. 使用Python创建一个简易的Web Server

    Python 2.x中自带了SimpleHTTPServer模块,到Python3.x中,该模块被合并到了http.server模块中.使用该模块,可以快速创建一个简易的Web服务器. 我们在C:\U ...

  6. Python框架学习之用Flask创建一个简单项目

    在前面一篇讲了如何创建一个虚拟环境,今天这一篇就来说说如何创建一个简单的Flask项目.关于Flask的具体介绍就不详细叙述了,我们只要知道它非常简洁.灵活和扩展性强就够了.它不像Django那样集成 ...

  7. Unity 2D游戏开发高速入门第1章创建一个简单的2D游戏

    Unity 2D游戏开发高速入门第1章创建一个简单的2D游戏 即使是如今,非常多初学游戏开发的同学.在谈到Unity的时候.依旧会觉得Unity仅仅能用于制作3D游戏的. 实际上.Unity在2013 ...

  8. 用django创建一个简单的sns

    用django创建一个简单的sns 1.首先创建一个工程newsns django-admin.py startproject newsns 在工程目录下新建一个文件夹templates,在该文件夹下 ...

  9. django创建一个简单的web站点

    一.新建project 使用Pycharm,File->New Project…,选择Django,给project命名 (project不能用test命名)   新建的project目录如下: ...

随机推荐

  1. jQuery原生框架-----------------事件

    jQuery.extend({ // 绑定事件 addEvent: function( ele, type, fn ) { // ele不是DOM,type不是字符串,fn不是函数,打包打走 if( ...

  2. UITableView去掉section的header的粘性

    思路:若header的高度为25,在滑动的时候将scrollView的内容偏移量上衣25,其实他还是粘在上面只不过我们看不到他了. ///---用于判断往上滑还是往下滑 var deltaY:CGFl ...

  3. 优化mysql运行环境的方法

    Mysql优化已经讲过很多篇教程了,而且网上也很多相关内容,但是本文我们是讲Linux下Mysql运行环境如何进行优化,有些地方与以往有所不同,也具有参考价值.具体mysql教程 如下: 一.修改Li ...

  4. a primary example for Functional programming in javascript

    background In pursuit of a real-world application, let’s say we need an e-commerce web applicationfo ...

  5. 布局容器layout Container

    画布canvas 盒子Box VBox Hbox-->HGroup VGroup 控制条 ControlBar

  6. PyCharm 3.4.1注册码

    PyCharm 3.4下载地址:http://www.jetbrains.com/pycharm/download/index.html PyCharm 3.0 注册码 PyCharm3 序列号 Li ...

  7. Java SCP copy local file to remote implementation

    最近做的项目中,有一个小需求,需要通过SCP把本地文件copy到远程服务器.查了好多资料,最终解决方案简单快速,分享一下. 在这里,需要用到4个jar包,分别是ant-jsch.jar,ant-lau ...

  8. lumia520刷机注意事项

    1.下载后的固件名称中设备名前的随机字符都要去掉 2.安装完nokia care suit后最好在driver目录下重新双击安装usb driver

  9. HTML5 LocalStorage 本地存储

    HTML5 LocalStorage 本地存储 说到本地存储,这玩意真是历尽千辛万苦才走到HTML5这一步,之前的历史大概如下图所示: 最早的Cookies自然是大家都知道,问题主要就是太小,大概也就 ...

  10. 主要由顶点容器构成的平面图形类(Shape)——(第一次作业Draw类定义升级)

    // https://github.com/orocos/orocos_kinematics_dynamics/blob/master/orocos_kdl/src/frames.hpp // Vec ...