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目录如下: ...
随机推荐
- 涵涵和爸爸习惯养成进度表(二)(May 30 - )
规则说明 22天内,没有哭脸,不超过三个无表情脸,可以给一个奖励(动画书等) 涵涵违反规则,在爸爸和妈妈都同意的情况下,可以给无表情脸 爸爸违反规则,在妈妈和涵涵都同意的情况下,可以给无表情脸 获奖记 ...
- sqlite学习
一鼓作气,今天继续学习了sqlite数据库在Xcode上的一些操作,主要是通过用oc代码进行salite表格的创建,删除,修改:以及对现有的表格数据进行增,删,改,查.虽然有点累,但是收获不小,感觉很 ...
- jquery 如何去除select 控件重复的option
这个去重不是很好用,如果id值不同,text是一样的,也会被去掉 <input type="button" class="btn" id="bt ...
- CSS3 Gradient
CSS3CSS3发布很久了,现在在国外的一些页面上常能看到他的身影,这让我羡慕已久,只可惜在国内为了兼容IE,让这一项技术受到很大的限制,很多Web前端人员都望而止步.虽然如此但还是有很多朋友在钻研C ...
- .NET网页打印以及使用打印需要注意的事项(可能会引起VS崩溃的现象、打印预览后关闭功能不管用)
这两天进行给网页添加打印.打印预览.页面设置的功能.遇到了以下几个问题 [1]在网上查找了一些打印方法,一开始还可以用,后来不知道动到了哪里,点击vs中拆分或者切换到另一个设计和源代码显示方式,就会引 ...
- swift 闭包循环引用
当使用闭包时,类本身持有self,然后又在闭包中访问了self或者self的属性,就会导致恶心额循环引用.swift提供的解决方法是在闭包中定义捕获列表,捕获列表是闭包想怎么引用捕获来的变量.例如下面 ...
- 触发Full GC执行的情况
除直接调用System.gc外,触发Full GC执行的情况有如下四种. 1. 旧生代空间不足 旧生代空间只有在新生代对象转入及创建为大对象.大数组时才会出现不足的现象,当执行Full GC后空间仍然 ...
- android ORM框架ORMLite封装
源码:http://download.csdn.net/detail/a924571572/9415506 一.框架效率对比 由于目前公司里面android端数据的数据量基本在千条以内,所以选择了更为 ...
- 原创: How to build a query based on Definition Updates installed
In SCCM 2012 R2, you can use following class. Use SMS_CombinedDeviceResources.EPAntivirusSignatureLa ...
- .net web端导出Excel个人的看法
//对已有方法进行重写 public override void VerifyRenderingInServerForm(Control control) { } //设置文件名 string fil ...