[pyassimp] Simplified and beautify simple_opengl_viewer.py

Since the new SDL based viewer is much better suited to interactive exploration, simplify
the basic OpenGL viewer to make it an easy introductive read.
pull/10/head
Séverin Lemaignan 2012-11-10 23:47:59 +01:00 committed by Séverin Lemaignan
parent 2cdda51455
commit d3dbde02d6
1 changed files with 40 additions and 81 deletions

View File

@ -1,14 +1,21 @@
#!/usr/bin/env python #!/usr/bin/env python
#-*- coding: UTF-8 -*- #-*- coding: UTF-8 -*-
""" This program demonstrate the use of pyassimp to render """ This program demonstrates the use of pyassimp to load and
objects in OpenGL. render objects with OpenGL.
It loads a 3D model with ASSIMP and display it. 'c' cycles between cameras (if any available)
'q' to quit
This example mixes 'old' OpenGL fixed-function pipeline with
Vertex Buffer Objects.
Materials are supported but textures are currently ignored. Materials are supported but textures are currently ignored.
Half-working keyboard + mouse navigation is supported. For a more advanced example (with shaders + keyboard/mouse
controls), check scripts/sdl_viewer.py
Author: Séverin Lemaignan, 2012
This sample is based on several sources, including: This sample is based on several sources, including:
- http://www.lighthouse3d.com/tutorials - http://www.lighthouse3d.com/tutorials
@ -21,9 +28,8 @@ import os, sys
from OpenGL.GLUT import * from OpenGL.GLUT import *
from OpenGL.GLU import * from OpenGL.GLU import *
from OpenGL.GL import * from OpenGL.GL import *
from OpenGL.arrays import ArrayDatatype
import logging;logger = logging.getLogger("assimp_opengl") import logging;logger = logging.getLogger("pyassimp_opengl")
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
import math import math
@ -40,20 +46,14 @@ width = 900
class GLRenderer(): class GLRenderer():
def __init__(self): def __init__(self):
self.scene = None self.scene = None
self.drot = 0.0
self.dp = 0.0
self.angle = 0.0
self.x = 1.0
self.z = 3.0
self.lx = 0.0
self.lz = 0.0
self.using_fixed_cam = False self.using_fixed_cam = False
self.current_cam_index = 0 self.current_cam_index = 0
self.x_origin = -1 # x position of the mouse when pressing left btn # store the global scene rotation
self.angle = 0.
# for FPS calculation # for FPS calculation
self.prev_time = 0 self.prev_time = 0
@ -61,6 +61,10 @@ class GLRenderer():
self.frames = 0 self.frames = 0
def prepare_gl_buffers(self, mesh): def prepare_gl_buffers(self, mesh):
""" Creates 3 buffer objets for each mesh,
to store the vertices, the normals, and the faces
indices.
"""
mesh.gl = {} mesh.gl = {}
@ -90,8 +94,7 @@ class GLRenderer():
glBindBuffer(GL_ARRAY_BUFFER,0) glBindBuffer(GL_ARRAY_BUFFER,0)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0)
def load_model(self, path, postprocess = None):
def load_dae(self, path, postprocess = None):
logger.info("Loading model:" + path + "...") logger.info("Loading model:" + path + "...")
if postprocess: if postprocess:
@ -129,9 +132,11 @@ class GLRenderer():
if not self.using_fixed_cam: if not self.using_fixed_cam:
glLoadIdentity() glLoadIdentity()
gluLookAt(self.x ,1., self.z, # pos
self.x + self.lx - 1.0, 1., self.z + self.lz - 3.0, # look at gluLookAt(0.,0.,3.,
0.,1.,0.) # up vector 0.,0.,-5.,
0.,1.,0.)
def set_camera(self, camera): def set_camera(self, camera):
@ -178,13 +183,13 @@ class GLRenderer():
tmp = max(x_max, y_max) tmp = max(x_max, y_max)
z_max = self.bb_max[2] - self.bb_min[2] z_max = self.bb_max[2] - self.bb_min[2]
tmp = max(z_max, tmp) tmp = max(z_max, tmp)
if not restore: if not restore:
tmp = 1. / tmp tmp = 1. / tmp
logger.info("Scaling the scene by %.03f" % tmp) logger.info("Scaling the scene by %.03f" % tmp)
glScalef(tmp, tmp, tmp) glScalef(tmp, tmp, tmp)
# center the model # center the model
direction = -1 if not restore else 1 direction = -1 if not restore else 1
glTranslatef( direction * self.scene_center[0], glTranslatef( direction * self.scene_center[0],
@ -192,14 +197,14 @@ class GLRenderer():
direction * self.scene_center[2] ) direction * self.scene_center[2] )
return x_max, y_max, z_max return x_max, y_max, z_max
def apply_material(self, mat): def apply_material(self, mat):
""" Apply an OpenGL, using one OpenGL list per material to cache """ Apply an OpenGL, using one OpenGL display list per material to cache
the operation. the operation.
""" """
if not hasattr(mat, "gl_mat"): # evaluate once the mat properties, and cache the values in a glDisplayList. if not hasattr(mat, "gl_mat"): # evaluate once the mat properties, and cache the values in a glDisplayList.
diffuse = numpy.array(mat.properties.get("diffuse", [0.8, 0.8, 0.8, 1.0])) diffuse = numpy.array(mat.properties.get("diffuse", [0.8, 0.8, 0.8, 1.0]))
specular = numpy.array(mat.properties.get("specular", [0., 0., 0., 1.0])) specular = numpy.array(mat.properties.get("specular", [0., 0., 0., 1.0]))
ambient = numpy.array(mat.properties.get("ambient", [0.2, 0.2, 0.2, 1.0])) ambient = numpy.array(mat.properties.get("ambient", [0.2, 0.2, 0.2, 1.0]))
@ -207,10 +212,8 @@ class GLRenderer():
shininess = min(mat.properties.get("shininess", 1.0), 128) shininess = min(mat.properties.get("shininess", 1.0), 128)
wireframe = mat.properties.get("wireframe", 0) wireframe = mat.properties.get("wireframe", 0)
twosided = mat.properties.get("twosided", 1) twosided = mat.properties.get("twosided", 1)
from OpenGL.raw import GL setattr(mat, "gl_mat", glGenLists(1))
setattr(mat, "gl_mat", GL.GLuint(0))
mat.gl_mat = glGenLists(1)
glNewList(mat.gl_mat, GL_COMPILE) glNewList(mat.gl_mat, GL_COMPILE)
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse) glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse)
@ -239,6 +242,8 @@ class GLRenderer():
self.lz = -math.cos(self.angle) self.lz = -math.cos(self.angle)
self.set_default_camera() self.set_default_camera()
self.angle = (gl_time - self.prev_time) * 0.1
self.prev_time = gl_time self.prev_time = gl_time
# Compute FPS # Compute FPS
@ -290,9 +295,10 @@ class GLRenderer():
""" GLUT callback to redraw OpenGL surface """ GLUT callback to redraw OpenGL surface
""" """
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glRotatef(self.angle,0.,1.,0.)
self.recursive_render(self.scene.rootnode) self.recursive_render(self.scene.rootnode)
glutSwapBuffers() glutSwapBuffers()
self.do_motion() self.do_motion()
return return
@ -307,42 +313,6 @@ class GLRenderer():
if key == 'q': if key == 'q':
sys.exit(0) sys.exit(0)
def onspecialkeypress(self, key, x, y):
fraction = 0.05
if key == GLUT_KEY_UP:
self.dp = 0.5
if key == GLUT_KEY_DOWN:
self.dp = -0.5
if key == GLUT_KEY_LEFT:
self.drot = -0.01
if key == GLUT_KEY_RIGHT:
self.drot = 0.01
def onspecialkeyrelease(self, key, x, y):
if key == GLUT_KEY_UP:
self.dp = 0.
if key == GLUT_KEY_DOWN:
self.dp = 0.
if key == GLUT_KEY_LEFT:
self.drot = 0.0
if key == GLUT_KEY_RIGHT:
self.drot = 0.0
def onclick(self, button, state, x, y):
if button == GLUT_LEFT_BUTTON:
if state == GLUT_UP:
self.drot = 0
self.x_origin = -1
else: # GLUT_DOWN
self.x_origin = x
def onmousemove(self, x, y):
if self.x_origin >= 0:
self.drot = (x - self.x_origin) * 0.001
def render(self, filename=None, fullscreen = False, autofit = True, postprocess = None): def render(self, filename=None, fullscreen = False, autofit = True, postprocess = None):
""" """
@ -364,7 +334,8 @@ class GLRenderer():
print("Fullscreen mode not available!") print("Fullscreen mode not available!")
sys.exit(1) sys.exit(1)
self.load_dae(filename, postprocess = postprocess) self.load_model(filename, postprocess = postprocess)
glClearColor(0.1,0.1,0.1,1.) glClearColor(0.1,0.1,0.1,1.)
#glShadeModel(GL_SMOOTH) #glShadeModel(GL_SMOOTH)
@ -374,16 +345,10 @@ class GLRenderer():
glEnable(GL_CULL_FACE) glEnable(GL_CULL_FACE)
glEnable(GL_DEPTH_TEST) glEnable(GL_DEPTH_TEST)
#lightZeroPosition = [10.,4.,10.,1.]
#lightZeroColor = [0.8,1.0,0.8,1.0] #green tinged
#glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition)
#glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor)
#glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1)
#glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05)
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE) glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE)
glEnable(GL_NORMALIZE) glEnable(GL_NORMALIZE)
glEnable(GL_LIGHT0) glEnable(GL_LIGHT0)
glutDisplayFunc(self.display) glutDisplayFunc(self.display)
@ -399,14 +364,8 @@ class GLRenderer():
glPushMatrix() glPushMatrix()
# Register GLUT callbacks for keyboard and mouse
glutKeyboardFunc(self.onkeypress) glutKeyboardFunc(self.onkeypress)
glutSpecialFunc(self.onspecialkeypress)
glutIgnoreKeyRepeat(1) glutIgnoreKeyRepeat(1)
glutSpecialUpFunc(self.onspecialkeyrelease)
glutMouseFunc(self.onclick)
glutMotionFunc(self.onmousemove)
glutMainLoop() glutMainLoop()