Python>>>创建一个简单的3D场景
首先安装PyOpengl
- 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 负责具体渲染的模型,主要是生成显示列表
- G_OBJ_PLANE = 1
G_OBJ_SPHERE = 2
G_OBJ_CUBE = 3
这些模型会在程序初始化的时候运行一次 Viewer的init函数中。
- 主框架是Viewer文件
MainLoop 里面定时调用这里注册的render函数
render 每次设置好MV矩阵,调用scene里面的render
Scene本身是一个节点的列表。每个节点会调用相应的显示列表来渲染。
代码Viewer.py
- # -*- coding: utf8 -*-
- from OpenGL.GL import glCallList, glClear, glClearColor, glColorMaterial, glCullFace, glDepthFunc, glDisable, glEnable,\
- glFlush, glGetFloatv, glLightfv, glLoadIdentity, glMatrixMode, glMultMatrixf, glPopMatrix, \
- glPushMatrix, glTranslated, glViewport, \
- GL_AMBIENT_AND_DIFFUSE, GL_BACK, GL_CULL_FACE, GL_COLOR_BUFFER_BIT, GL_COLOR_MATERIAL, \
- GL_DEPTH_BUFFER_BIT, GL_DEPTH_TEST, GL_FRONT_AND_BACK, GL_LESS, GL_LIGHT0, GL_LIGHTING, \
- GL_MODELVIEW, GL_MODELVIEW_MATRIX, GL_POSITION, GL_PROJECTION, GL_SPOT_DIRECTION
- from OpenGL.constants import GLfloat_3, GLfloat_4
- from OpenGL.GLU import gluPerspective, gluUnProject
- from OpenGL.GLUT import glutCreateWindow, glutDisplayFunc, glutGet, glutInit, glutInitDisplayMode, \
- glutInitWindowSize, glutMainLoop, \
- GLUT_SINGLE, GLUT_RGB, GLUT_WINDOW_HEIGHT, GLUT_WINDOW_WIDTH
- import numpy
- from numpy.linalg import norm, inv
- from primitive import init_primitives
- from Scene import Scene
- from node import Sphere
- from node import SnowFigure,Cube,Plane
- class Viewer(object):
- def __init__(self):
- """ Initialize the viewer. """
- #初始化接口,创建窗口并注册渲染函数
- self.init_interface()
- #初始化opengl的配置
- self.init_opengl()
- #初始化3d场景
- self.init_scene()
- #初始化交互操作相关的代码
- self.init_interaction()
- init_primitives()
- def init_interface(self):
- """ 初始化窗口并注册渲染函数 """
- glutInit()
- glutInitWindowSize(640, 480)
- glutCreateWindow("3D Modeller")
- glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB)
- #注册窗口渲染函数
- glutDisplayFunc(self.render)
- def init_opengl(self):
- """ 初始化opengl的配置 """
- #模型视图矩阵
- self.inverseModelView = numpy.identity(4)
- #模型视图矩阵的逆矩阵
- self.modelView = numpy.identity(4)
- #开启剔除操作效果
- glEnable(GL_CULL_FACE)
- #取消对多边形背面进行渲染的计算(看不到的部分不渲染)
- glCullFace(GL_BACK)
- #开启深度测试
- glEnable(GL_DEPTH_TEST)
- #测试是否被遮挡,被遮挡的物体不予渲染
- glDepthFunc(GL_LESS)
- #启用0号光源
- glEnable(GL_LIGHT0)
- #设置光源的位置
- glLightfv(GL_LIGHT0, GL_POSITION, GLfloat_4(0, 0, 1, 0))
- #设置光源的照射方向
- glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, GLfloat_3(0, 0, -1))
- #设置材质颜色
- glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
- glEnable(GL_COLOR_MATERIAL)
- #设置清屏的颜色
- glClearColor(0.4, 0.4, 0.4, 0.0)
- def init_scene(self):
- #初始化场景,之后实现
- # 创建一个场景实例
- self.scene = Scene()
- # 初始化场景内的对象
- self.create_sample_scene()
- def create_sample_scene(self):
- # 创建一个球体
- sphere_node = Sphere()
- # 设置球体的颜色
- sphere_node.color_index = 2
- # 将球体放进场景中,默认在正中央
- sphere_node.translate(2, 2, 0)
- sphere_node.scale(4)
- self.scene.add_node(sphere_node)
- # 添加小雪人
- hierarchical_node = SnowFigure()
- hierarchical_node.translate(-2, 0, -2)
- hierarchical_node.scale(2)
- self.scene.add_node(hierarchical_node)
- #添加立方体
- cube_node=Cube()
- cube_node.color_index=5
- cube_node.translate(5,5,0)
- cube_node.scale(1.8)
- self.scene.add_node(cube_node)
- #添加Plane
- plane_node=Plane()
- plane_node.color_index=2
- self.scene.add_node(plane_node)
- def init_interaction(self):
- #初始化交互操作相关的代码,之后实现
- pass
- def main_loop(self):
- #程序主循环开始
- glutMainLoop()
- def render(self):
- #程序进入主循环后每一次循环调用的渲染函数
- # 初始化投影矩阵
- self.init_view()
- # 启动光照
- glEnable(GL_LIGHTING)
- # 清空颜色缓存与深度缓存
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
- # 设置模型视图矩阵,目前为止用单位矩阵就行了。
- glMatrixMode(GL_MODELVIEW)
- glPushMatrix()
- glLoadIdentity()
- # 渲染场景
- self.scene.render()
- # 每次渲染后复位光照状态
- glDisable(GL_LIGHTING)
- glPopMatrix()
- # 把数据刷新到显存上
- glFlush()
- def init_view(self):
- """ 初始化投影矩阵 """
- xSize, ySize = glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT)
- #得到屏幕宽高比
- aspect_ratio = float(xSize) / float(ySize)
- #设置投影矩阵
- glMatrixMode(GL_PROJECTION)
- glLoadIdentity()
- #设置视口,应与窗口重合
- glViewport(0, 0, xSize, ySize)
- #设置透视,摄像机上下视野幅度70度
- #视野范围到距离摄像机1000个单位为止。
- gluPerspective(70, aspect_ratio, 0.1, 1000.0)
- #摄像机镜头从原点后退15个单位
- glTranslated(0, 0, -15)
- if __name__ == "__main__":
- viewer = Viewer()
- viewer.main_loop()
Scene.py
- # -*- coding: utf8 -*-
- class Scene(object):
- #放置节点的深度,放置的节点距离摄像机15个单位
- PLACE_DEPTH = 15.0
- def __init__(self):
- #场景下的节点队列
- self.node_list = list()
- def add_node(self, node):
- """ 在场景中加入一个新节点 """
- self.node_list.append(node)
- def render(self):
- """ 遍历场景下所有节点并渲染 """
- for node in self.node_list:
- node.render()
color.py
- # -*- coding: utf8 -*-
- MAX_COLOR = 9
- MIN_COLOR = 0
- COLORS = { # RGB Colors
- 0: (1.0, 1.0, 1.0),
- 1: (0.05, 0.05, 0.9),
- 2: (0.05, 0.9, 0.05),
- 3: (0.9, 0.05, 0.05),
- 4: (0.9, 0.9, 0.0),
- 5: (0.1, 0.8, 0.7),
- 6: (0.7, 0.2, 0.7),
- 7: (0.7, 0.7, 0.7),
- 8: (0.4, 0.4, 0.4),
- 9: (0.0, 0.0, 0.0),
- }
node.py
- # -*- coding: utf8 -*-
- import random
- from OpenGL.GL import glCallList, glColor3f, glMaterialfv, glMultMatrixf, glPopMatrix, glPushMatrix, \
- GL_EMISSION, GL_FRONT
- import numpy
- import color
- from primitive import G_OBJ_SPHERE,G_OBJ_CUBE,G_OBJ_PLANE
- from transform import scaling, translation
- class Node(object):
- def __init__(self):
- #该节点的颜色序号
- self.color_index = random.randint(color.MIN_COLOR, color.MAX_COLOR)
- #该节点的平移矩阵,决定了该节点在场景中的位置
- self.translation_matrix = numpy.identity(4)
- #该节点的缩放矩阵,决定了该节点的大小
- self.scaling_matrix = numpy.identity(4)
- def render(self):
- """ 渲染节点 """
- glPushMatrix()
- #实现平移
- glMultMatrixf(numpy.transpose(self.translation_matrix))
- #实现缩放
- glMultMatrixf(self.scaling_matrix)
- cur_color = color.COLORS[self.color_index]
- #设置颜色
- glColor3f(cur_color[0], cur_color[1], cur_color[2])
- #渲染对象模型
- self.render_self()
- glPopMatrix()
- def render_self(self):
- raise NotImplementedError(
- "The Abstract Node Class doesn't define 'render_self'")
- def translate(self, x, y, z):
- self.translation_matrix = numpy.dot(self.translation_matrix, translation([x, y, z]))
- def scale(self, s):
- self.scaling_matrix = numpy.dot(self.scaling_matrix, scaling([s,s,s]))
- class Primitive(Node):
- def __init__(self):
- super(Primitive, self).__init__()
- self.call_list = None
- def render_self(self):
- glCallList(self.call_list)
- class Sphere(Primitive):
- """ 球形图元 """
- def __init__(self):
- super(Sphere, self).__init__()
- self.call_list = G_OBJ_SPHERE
- class Cube(Primitive):
- """ 立方体图元 """
- def __init__(self):
- super(Cube, self).__init__()
- self.call_list = G_OBJ_CUBE
- class Plane(Primitive):
- def __init__(self):
- super(Plane,self).__init__()
- self.call_list=G_OBJ_PLANE
- class HierarchicalNode(Node):
- def __init__(self):
- super(HierarchicalNode, self).__init__()
- self.child_nodes = []
- def render_self(self):
- for child in self.child_nodes:
- child.render()
- class SnowFigure(HierarchicalNode):
- def __init__(self):
- super(SnowFigure, self).__init__()
- self.child_nodes = [Sphere(), Sphere(), Sphere()]
- self.child_nodes[0].translate(0, -0.6, 0)
- self.child_nodes[1].translate(0, 0.1, 0)
- self.child_nodes[1].scale(0.8)
- self.child_nodes[2].translate(0, 0.75, 0)
- self.child_nodes[2].scale(0.7)
- for child_node in self.child_nodes:
- child_node.color_index = color.MIN_COLOR
transform.py
- # -*- coding: utf8 -*-
- import numpy
- def translation(displacement):
- """ 生成平移矩阵 """
- t = numpy.identity(4)
- t[0, 3] = displacement[0]
- t[1, 3] = displacement[1]
- t[2, 3] = displacement[2]
- return t
- def scaling(scale):
- """ 生成缩放矩阵 """
- s = numpy.identity(4)
- s[0, 0] = scale[0]
- s[1, 1] = scale[1]
- s[2, 2] = scale[2]
- s[3, 3] = 1
- return s
primitive.py
- # -*- coding: utf8 -*-
- from OpenGL.GL import glBegin, glColor3f, glEnd, glEndList, glLineWidth, glNewList, glNormal3f, glVertex3f, \
- GL_COMPILE, GL_LINES, GL_QUADS
- from OpenGL.GLU import gluDeleteQuadric, gluNewQuadric, gluSphere
- G_OBJ_PLANE = 1
- G_OBJ_SPHERE = 2
- G_OBJ_CUBE = 3
- def make_plane():
- glNewList(G_OBJ_PLANE, GL_COMPILE)
- glBegin(GL_LINES)
- glColor3f(0, 0, 0)
- for i in xrange(41):
- glVertex3f(-10.0 + 0.5 * i, 0, -10)
- glVertex3f(-10.0 + 0.5 * i, 0, 10)
- glVertex3f(-10.0, 0, -10 + 0.5 * i)
- glVertex3f(10.0, 0, -10 + 0.5 * i)
- # Axes
- glEnd()
- glLineWidth(5)
- glBegin(GL_LINES)
- glColor3f(0.5, 0.7, 0.5)
- glVertex3f(0.0, 0.0, 0.0)
- glVertex3f(5, 0.0, 0.0)
- glEnd()
- glBegin(GL_LINES)
- glColor3f(0.5, 0.7, 0.5)
- glVertex3f(0.0, 0.0, 0.0)
- glVertex3f(0.0, 5, 0.0)
- glEnd()
- glBegin(GL_LINES)
- glColor3f(0.5, 0.7, 0.5)
- glVertex3f(0.0, 0.0, 0.0)
- glVertex3f(0.0, 0.0, 5)
- glEnd()
- # Draw the Y.
- glBegin(GL_LINES)
- glColor3f(0.0, 0.0, 0.0)
- glVertex3f(0.0, 5.0, 0.0)
- glVertex3f(0.0, 5.5, 0.0)
- glVertex3f(0.0, 5.5, 0.0)
- glVertex3f(-0.5, 6.0, 0.0)
- glVertex3f(0.0, 5.5, 0.0)
- glVertex3f(0.5, 6.0, 0.0)
- # Draw the Z.
- glVertex3f(-0.5, 0.0, 5.0)
- glVertex3f(0.5, 0.0, 5.0)
- glVertex3f(0.5, 0.0, 5.0)
- glVertex3f(-0.5, 0.0, 6.0)
- glVertex3f(-0.5, 0.0, 6.0)
- glVertex3f(0.5, 0.0, 6.0)
- # Draw the X.
- glVertex3f(5.0, 0.0, 0.5)
- glVertex3f(6.0, 0.0, -0.5)
- glVertex3f(5.0, 0.0, -0.5)
- glVertex3f(6.0, 0.0, 0.5)
- glEnd()
- glLineWidth(1)
- glEndList()
- def make_sphere():
- """ 创建球形的渲染函数列表 """
- glNewList(G_OBJ_SPHERE, GL_COMPILE)
- quad = gluNewQuadric()
- gluSphere(quad, 0.5, 30, 30)
- gluDeleteQuadric(quad)
- glEndList()
- def make_cube():
- glNewList(G_OBJ_CUBE, GL_COMPILE)
- 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)),
- ((-0.5, -0.5, -0.5), (-0.5, 0.5, -0.5), (0.5, 0.5, -0.5), (0.5, -0.5, -0.5)),
- ((0.5, -0.5, -0.5), (0.5, 0.5, -0.5), (0.5, 0.5, 0.5), (0.5, -0.5, 0.5)),
- ((-0.5, -0.5, 0.5), (0.5, -0.5, 0.5), (0.5, 0.5, 0.5), (-0.5, 0.5, 0.5)),
- ((-0.5, -0.5, 0.5), (-0.5, -0.5, -0.5), (0.5, -0.5, -0.5), (0.5, -0.5, 0.5)),
- ((-0.5, 0.5, -0.5), (-0.5, 0.5, 0.5), (0.5, 0.5, 0.5), (0.5, 0.5, -0.5))]
- 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)]
- glBegin(GL_QUADS)
- for i in xrange(6):
- glNormal3f(normals[i][0], normals[i][1], normals[i][2])
- for j in xrange(4):
- glVertex3f(vertices[i][j][0], vertices[i][j][1], vertices[i][j][2])
- glEnd()
- glEndList()
- def init_primitives():
- """ 初始化所有的图元渲染函数列表 """
- make_plane()
- make_sphere()
- make_cube()
Python>>>创建一个简单的3D场景的更多相关文章
- Python创建一个简单的区块链
区块链(Blockchain)是一种分布式账本(listributed ledger),它是一种仅供增加(append-only),内容不可变(immutable)的有序(ordered)链式数据结构 ...
- 基于python创建一个简单的HTTP-WEB服务器
背景 大多数情况下主机资源只有开发和测试相关人员可以登录直接操作,且有些特定情况"答辩.演示.远程"等这些场景下是无法直接登录主机的.web是所有终端用户都可以访问了,解决了人员权 ...
- python创建一个简单的服务
python -m http.server 8000 --bind 0.0.0.0 8000为端口 0.0.0.0允许远程访问
- 通过创建一个简单的骰子游戏来探究 Python
在我的这系列的第一篇文章 中, 我已经讲解如何使用 Python 创建一个简单的.基于文本的骰子游戏.这次,我将展示如何使用 Python 模块 Pygame 来创建一个图形化游戏.它将需要几篇文章才 ...
- 使用Python创建一个简易的Web Server
Python 2.x中自带了SimpleHTTPServer模块,到Python3.x中,该模块被合并到了http.server模块中.使用该模块,可以快速创建一个简易的Web服务器. 我们在C:\U ...
- Python框架学习之用Flask创建一个简单项目
在前面一篇讲了如何创建一个虚拟环境,今天这一篇就来说说如何创建一个简单的Flask项目.关于Flask的具体介绍就不详细叙述了,我们只要知道它非常简洁.灵活和扩展性强就够了.它不像Django那样集成 ...
- Unity 2D游戏开发高速入门第1章创建一个简单的2D游戏
Unity 2D游戏开发高速入门第1章创建一个简单的2D游戏 即使是如今,非常多初学游戏开发的同学.在谈到Unity的时候.依旧会觉得Unity仅仅能用于制作3D游戏的. 实际上.Unity在2013 ...
- 用django创建一个简单的sns
用django创建一个简单的sns 1.首先创建一个工程newsns django-admin.py startproject newsns 在工程目录下新建一个文件夹templates,在该文件夹下 ...
- django创建一个简单的web站点
一.新建project 使用Pycharm,File->New Project…,选择Django,给project命名 (project不能用test命名) 新建的project目录如下: ...
随机推荐
- jQuery原生框架-----------------事件
jQuery.extend({ // 绑定事件 addEvent: function( ele, type, fn ) { // ele不是DOM,type不是字符串,fn不是函数,打包打走 if( ...
- UITableView去掉section的header的粘性
思路:若header的高度为25,在滑动的时候将scrollView的内容偏移量上衣25,其实他还是粘在上面只不过我们看不到他了. ///---用于判断往上滑还是往下滑 var deltaY:CGFl ...
- 优化mysql运行环境的方法
Mysql优化已经讲过很多篇教程了,而且网上也很多相关内容,但是本文我们是讲Linux下Mysql运行环境如何进行优化,有些地方与以往有所不同,也具有参考价值.具体mysql教程 如下: 一.修改Li ...
- 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 ...
- 布局容器layout Container
画布canvas 盒子Box VBox Hbox-->HGroup VGroup 控制条 ControlBar
- PyCharm 3.4.1注册码
PyCharm 3.4下载地址:http://www.jetbrains.com/pycharm/download/index.html PyCharm 3.0 注册码 PyCharm3 序列号 Li ...
- Java SCP copy local file to remote implementation
最近做的项目中,有一个小需求,需要通过SCP把本地文件copy到远程服务器.查了好多资料,最终解决方案简单快速,分享一下. 在这里,需要用到4个jar包,分别是ant-jsch.jar,ant-lau ...
- lumia520刷机注意事项
1.下载后的固件名称中设备名前的随机字符都要去掉 2.安装完nokia care suit后最好在driver目录下重新双击安装usb driver
- HTML5 LocalStorage 本地存储
HTML5 LocalStorage 本地存储 说到本地存储,这玩意真是历尽千辛万苦才走到HTML5这一步,之前的历史大概如下图所示: 最早的Cookies自然是大家都知道,问题主要就是太小,大概也就 ...
- 主要由顶点容器构成的平面图形类(Shape)——(第一次作业Draw类定义升级)
// https://github.com/orocos/orocos_kinematics_dynamics/blob/master/orocos_kdl/src/frames.hpp // Vec ...