2
0
Эх сурвалжийг харах

Merge git://github.com/bjowi/assimp

acgessler 12 жил өмнө
parent
commit
29a7126589

+ 3 - 4
Readme.md

@@ -1,4 +1,4 @@
-Open Asset Import Library (_assimp_) 
+Open Asset Import Library (assimp) 
 ========
 
 
@@ -29,8 +29,9 @@ __Note__: this `README` refers to the file structure used by release packages, w
 The library provides importers for a lot of file formats, including:
 
 - 3DS
-- BLEND 
+- BLEND (Blender 3D)
 - DAE (Collada)
+- FBX
 - IFC-STEP 
 - ASE
 - DXF
@@ -121,5 +122,3 @@ For the formal details, see the `LICENSE` file.
 
 
 ------------------------------
-
-(This repository is a mirror of the SVN repository located [here](https://assimp.svn.sourceforge.net/svnroot/assimp). Thanks to [klickverbot](https://github.com/klickverbot) for setting this up!)

+ 4 - 4
assimp.pc.in

@@ -1,10 +1,10 @@
 prefix=@CMAKE_INSTALL_PREFIX@
-exec_prefix=@CMAKE_INSTALL_PREFIX@/@BIN_INSTALL_DIR@
-libdir=@CMAKE_INSTALL_PREFIX@/@LIB_INSTALL_DIR@
-includedir=@CMAKE_INSTALL_PREFIX@/@INCLUDE_INSTALL_DIR@/assimp
+exec_prefix=@CMAKE_INSTALL_PREFIX@/@ASSIMP_BIN_INSTALL_DIR@
+libdir=@CMAKE_INSTALL_PREFIX@/@ASSIMP_LIB_INSTALL_DIR@
+includedir=@CMAKE_INSTALL_PREFIX@/@ASSIMP_INCLUDE_INSTALL_DIR@/assimp
 
 Name: @CMAKE_PROJECT_NAME@
 Description: Import various well-known 3D model formats in an uniform manner.
 Version: @PROJECT_VERSION@
 Libs: -L${libdir} -lassimp@ASSIMP_LIBRARY_SUFFIX@
-Cflags: -I${includedir} 
+Cflags: -I${includedir}

+ 11 - 11
port/PyAssimp/README.md

@@ -1,8 +1,8 @@
 PyAssimp Readme
 ===============
 
--- a simple Python wrapper for Assimp using ctypes to access
-the library. Requires Python >= 2.6.
+A simple Python wrapper for Assimp using `ctypes` to access the library.
+Requires Python >= 2.6.
 
 Python 3 support is mostly here, but not well tested.
 
@@ -12,10 +12,10 @@ particular, only loading of models is currently supported (no export).
 USAGE
 -----
 
-To get started with pyAssimp, examine the sample.py script in scripts/, which
-illustrates the basic usage. All Assimp data structures are wrapped using
+To get started with pyAssimp, examine the `sample.py` script in `scripts/`,
+which illustrates the basic usage. All Assimp data structures are wrapped using
 ctypes. All the data+length fields in Assimp's data structures (such as
-'aiMesh::mNumVertices','aiMesh::mVertices') are replaced by simple python
+`aiMesh::mNumVertices`, `aiMesh::mVertices`) are replaced by simple python
 lists, so you can call len() on them to get their respective size and access
 members using [].
 
@@ -57,18 +57,18 @@ release(scene)
 INSTALL
 -------
 
-Install pyassimp by running:
+Install `pyassimp` by running:
 
 > python setup.py install
 
-PyAssimp requires a assimp dynamic library (DLL on windows,
-so on linux :-) in order to work. The default search directories 
+PyAssimp requires a assimp dynamic library (`DLL` on windows,
+`.so` on linux :-) in order to work. The default search directories 
 are:
 
 - the current directory
-- on linux additionally: /usr/lib and /usr/local/lib
+- on linux additionally: `/usr/lib` and `/usr/local/lib`
 
 To build that library, refer to the Assimp master INSTALL
-instructions. To look in more places, edit ./pyassimp/helper.py.
-There's an 'additional_dirs' list waiting for your entries.
+instructions. To look in more places, edit `./pyassimp/helper.py`.
+There's an `additional_dirs` list waiting for your entries.
 

+ 6 - 38
port/PyAssimp/pyassimp/core.py

@@ -346,60 +346,28 @@ def _get_properties(properties, length):
     for p in [properties[i] for i in range(length)]:
         #the name
         p = p.contents
-        key = str(p.mKey.data)
+        key = str(p.mKey.data).split('.')[1]
 
         #the data
         from ctypes import POINTER, cast, c_int, c_float, sizeof
         if p.mType == 1:
             arr = cast(p.mData, POINTER(c_float * int(p.mDataLength/sizeof(c_float)) )).contents
-            value = numpy.array([x for x in arr])
+            value = [x for x in arr]
         elif p.mType == 3: #string can't be an array
             value = cast(p.mData, POINTER(structs.String)).contents.data
         elif p.mType == 4:
             arr = cast(p.mData, POINTER(c_int * int(p.mDataLength/sizeof(c_int)) )).contents
-            value = numpy.array([x for x in arr])
+            value = [x for x in arr]
         else:
             value = p.mData[:p.mDataLength]
 
+        if len(value) == 1:
+            [value] = value
+
         result[key] = value
 
     return result
 
-def aiGetMaterialFloatArray(material, key):
-    AI_SUCCESS = 0
-    from ctypes import byref, pointer, cast, c_float, POINTER, sizeof, c_uint
-    out = structs.Color4D()
-    max = c_uint(sizeof(structs.Color4D))
-    r=_assimp_lib.dll.aiGetMaterialFloatArray(pointer(material), 
-                                            key[0], 
-                                            key[1], 
-                                            key[2], 
-                                            byref(out), 
-                                            byref(max))
-                                            
-    if (r != AI_SUCCESS):    
-        raise AssimpError("aiGetMaterialFloatArray failed!")
-      
-    out._init()
-    return [out[i] for i in range(max.value)]
-    
-def aiGetMaterialString(material, key):
-    AI_SUCCESS = 0
-    from ctypes import byref, pointer, cast, c_float, POINTER, sizeof, c_uint
-    out = structs.String()
-    r=_assimp_lib.dll.aiGetMaterialString(pointer(material), 
-                                            key[0], 
-                                            key[1], 
-                                            key[2], 
-                                            byref(out))
-                                            
-    if (r != AI_SUCCESS):    
-        raise AssimpError("aiGetMaterialString failed!")
-        
-    return str(out.data)
-
-    
-    
 def decompose_matrix(matrix):
     if not isinstance(matrix, structs.Matrix4x4):
         raise AssimpError("pyassimp.decompose_matrix failed: Not a Matrix4x4!")

+ 7 - 4
port/PyAssimp/pyassimp/helper.py

@@ -9,6 +9,7 @@ import ctypes
 from ctypes import POINTER
 import operator
 import numpy
+from numpy import linalg
 
 import logging;logger = logging.getLogger("pyassimp")
 
@@ -47,12 +48,14 @@ def transform(vector3, matrix4x4):
 def get_bounding_box(scene):
     bb_min = [1e10, 1e10, 1e10] # x,y,z
     bb_max = [-1e10, -1e10, -1e10] # x,y,z
-    return get_bounding_box_for_node(scene.rootnode, bb_min, bb_max)
+    return get_bounding_box_for_node(scene.rootnode, bb_min, bb_max, linalg.inv(scene.rootnode.transformation))
 
-def get_bounding_box_for_node(node, bb_min, bb_max):
+def get_bounding_box_for_node(node, bb_min, bb_max, transformation):
+
+    transformation = numpy.dot(transformation, node.transformation)
     for mesh in node.meshes:
         for v in mesh.vertices:
-            v = transform(v, node.transformation)
+            v = transform(v, transformation)
             bb_min[0] = min(bb_min[0], v[0])
             bb_min[1] = min(bb_min[1], v[1])
             bb_min[2] = min(bb_min[2], v[2])
@@ -62,7 +65,7 @@ def get_bounding_box_for_node(node, bb_min, bb_max):
 
 
     for child in node.children:
-        bb_min, bb_max = get_bounding_box_for_node(child, bb_min, bb_max)
+        bb_min, bb_max = get_bounding_box_for_node(child, bb_min, bb_max, transformation)
 
     return bb_min, bb_max
 

+ 410 - 0
port/PyAssimp/scripts/advanced_3d_viewer.py

@@ -0,0 +1,410 @@
+#!/usr/bin/env python
+#-*- coding: UTF-8 -*-
+
+""" This program loads a model with PyASSIMP, and display it.
+
+It make a large use of shaders to illustrate a 'modern' OpenGL pipeline.
+
+Based on:
+- pygame + mouselook code from http://3dengine.org/Spectator_%28PyOpenGL%29
+ - http://www.lighthouse3d.com/tutorials
+ - http://www.songho.ca/opengl/gl_transform.html
+ - http://code.activestate.com/recipes/325391/
+ - ASSIMP's C++ SimpleOpenGL viewer
+"""
+import sys
+
+import logging
+logger = logging.getLogger("underworlds.3d_viewer")
+gllogger = logging.getLogger("OpenGL")
+gllogger.setLevel(logging.WARNING)
+logging.basicConfig(level=logging.INFO)
+
+import OpenGL
+#OpenGL.ERROR_CHECKING=False
+#OpenGL.ERROR_LOGGING = False
+#OpenGL.ERROR_ON_COPY = True
+#OpenGL.FULL_LOGGING = True
+from OpenGL.GL import *
+from OpenGL.error import GLError
+from OpenGL.GLU import *
+from OpenGL.GLUT import *
+from OpenGL.arrays import vbo
+from OpenGL.GL import shaders
+
+import pygame
+
+import math, random
+import numpy
+from numpy import linalg
+
+from pyassimp import core as pyassimp
+from pyassimp.postprocess import *
+from pyassimp.helper import *
+
+class DefaultCamera:
+    def __init__(self, w, h, fov):
+        self.clipplanenear = 0.001
+        self.clipplanefar = 100000.0
+        self.aspect = w/h
+        self.horizontalfov = fov * math.pi/180
+        self.transformation = [[ 0.68, -0.32, 0.65, 7.48],
+                               [ 0.73,  0.31, -0.61, -6.51],
+                               [-0.01,  0.89,  0.44,  5.34],
+                               [ 0.,    0.,    0.,    1.  ]]
+        self.lookat = [0.0,0.0,-1.0]
+
+    def __str__(self):
+        return "Default camera"
+
+class PyAssimp3DViewer:
+
+    base_name = "PyASSIMP 3D viewer"
+
+    def __init__(self, model, w=1024, h=768, fov=75):
+
+        pygame.init()
+        pygame.display.set_caption(self.base_name)
+        pygame.display.set_mode((w,h), pygame.OPENGL | pygame.DOUBLEBUF)
+
+        self.prepare_shaders()
+
+        self.cameras = [DefaultCamera(w,h,fov)]
+        self.current_cam_index = 0
+
+        self.load_model(model)
+
+        # for FPS computation
+        self.frames = 0
+        self.last_fps_time = glutGet(GLUT_ELAPSED_TIME)
+
+
+        self.cycle_cameras()
+
+    def prepare_shaders(self):
+
+        phong_weightCalc = """
+        float phong_weightCalc(
+            in vec3 light_pos, // light position
+            in vec3 frag_normal // geometry normal
+        ) {
+            // returns vec2( ambientMult, diffuseMult )
+            float n_dot_pos = max( 0.0, dot(
+                frag_normal, light_pos
+            ));
+            return n_dot_pos;
+        }
+        """
+
+        vertex = shaders.compileShader( phong_weightCalc +
+        """
+        uniform vec4 Global_ambient;
+        uniform vec4 Light_ambient;
+        uniform vec4 Light_diffuse;
+        uniform vec3 Light_location;
+        uniform vec4 Material_ambient;
+        uniform vec4 Material_diffuse;
+        attribute vec3 Vertex_position;
+        attribute vec3 Vertex_normal;
+        varying vec4 baseColor;
+        void main() {
+            gl_Position = gl_ModelViewProjectionMatrix * vec4(
+                Vertex_position, 1.0
+            );
+            vec3 EC_Light_location = gl_NormalMatrix * Light_location;
+            float diffuse_weight = phong_weightCalc(
+                normalize(EC_Light_location),
+                normalize(gl_NormalMatrix * Vertex_normal)
+            );
+            baseColor = clamp(
+            (
+                // global component
+                (Global_ambient * Material_ambient)
+                // material's interaction with light's contribution
+                // to the ambient lighting...
+                + (Light_ambient * Material_ambient)
+                // material's interaction with the direct light from
+                // the light.
+                + (Light_diffuse * Material_diffuse * diffuse_weight)
+            ), 0.0, 1.0);
+        }""", GL_VERTEX_SHADER)
+
+        fragment = shaders.compileShader("""
+        varying vec4 baseColor;
+        void main() {
+            gl_FragColor = baseColor;
+        }
+        """, GL_FRAGMENT_SHADER)
+
+        self.shader = shaders.compileProgram(vertex,fragment)
+        self.set_shader_accessors( (
+            'Global_ambient',
+            'Light_ambient','Light_diffuse','Light_location',
+            'Material_ambient','Material_diffuse',
+        ), (
+            'Vertex_position','Vertex_normal',
+        ), self.shader)
+
+    def set_shader_accessors(self, uniforms, attributes, shader):
+        # add accessors to the shaders uniforms and attributes
+        for uniform in uniforms:
+            location = glGetUniformLocation( shader,  uniform )
+            if location in (None,-1):
+                logger.warning('No uniform: %s'%( uniform ))
+            setattr( shader, uniform, location )
+
+        for attribute in attributes:
+            location = glGetAttribLocation( shader, attribute )
+            if location in (None,-1):
+                logger.warning('No attribute: %s'%( attribute ))
+            setattr( shader, attribute, location )
+
+
+    def prepare_gl_buffers(self, mesh):
+
+        mesh.gl = {}
+
+        # Fill the buffer for vertex and normals positions
+        v = numpy.array(mesh.vertices, 'f')
+        n = numpy.array(mesh.normals, 'f')
+
+        mesh.gl["vbo"] = vbo.VBO(numpy.hstack((v,n)))
+
+        # Fill the buffer for vertex positions
+        mesh.gl["faces"] = glGenBuffers(1)
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.gl["faces"])
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, 
+                    mesh.faces,
+                    GL_STATIC_DRAW)
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0)
+
+    
+    def load_model(self, path, postprocess = aiProcessPreset_TargetRealtime_MaxQuality):
+        logger.info("Loading model:" + path + "...")
+
+        if postprocess:
+            self.scene = pyassimp.load(path, postprocess)
+        else:
+            self.scene = pyassimp.load(path)
+        logger.info("Done.")
+
+        scene = self.scene
+        #log some statistics
+        logger.info("  meshes: %d" % len(scene.meshes))
+        logger.info("  total faces: %d" % sum([len(mesh.faces) for mesh in scene.meshes]))
+        logger.info("  materials: %d" % len(scene.materials))
+        self.bb_min, self.bb_max = get_bounding_box(self.scene)
+        logger.info("  bounding box:" + str(self.bb_min) + " - " + str(self.bb_max))
+
+        self.scene_center = [(a + b) / 2. for a, b in zip(self.bb_min, self.bb_max)]
+
+        for index, mesh in enumerate(scene.meshes):
+            self.prepare_gl_buffers(mesh)
+
+        # Finally release the model
+        pyassimp.release(scene)
+
+        logger.info("Ready for 3D rendering!")
+
+    def cycle_cameras(self):
+        if not self.cameras:
+            logger.info("No camera in the scene")
+            return None
+        self.current_cam_index = (self.current_cam_index + 1) % len(self.cameras)
+        self.current_cam = self.cameras[self.current_cam_index]
+        self.set_camera(self.current_cam)
+        logger.info("Switched to camera <%s>" % self.current_cam)
+
+    def set_camera_projection(self, camera = None):
+
+        if not camera:
+            camera = self.cameras[self.current_cam_index]
+
+        znear = camera.clipplanenear
+        zfar = camera.clipplanefar
+        aspect = camera.aspect
+        fov = camera.horizontalfov
+
+        glMatrixMode(GL_PROJECTION)
+        glLoadIdentity()
+
+        # Compute gl frustrum
+        tangent = math.tan(fov/2.)
+        h = znear * tangent
+        w = h * aspect
+
+        # params: left, right, bottom, top, near, far
+        glFrustum(-w, w, -h, h, znear, zfar)
+        # equivalent to:
+        #gluPerspective(fov * 180/math.pi, aspect, znear, zfar)
+        glMatrixMode(GL_MODELVIEW)
+        glLoadIdentity()
+
+
+    def set_camera(self, camera):
+
+        self.set_camera_projection(camera)
+
+        glMatrixMode(GL_MODELVIEW)
+        glLoadIdentity()
+
+        cam = transform([0.0, 0.0, 0.0], camera.transformation)
+        at = transform(camera.lookat, camera.transformation)
+        gluLookAt(cam[0], cam[2], -cam[1],
+                   at[0],  at[2],  -at[1],
+                       0,      1,       0)
+
+    def render(self, wireframe = False, twosided = False):
+
+        glEnable(GL_DEPTH_TEST)
+        glDepthFunc(GL_LEQUAL)
+
+
+        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE if wireframe else GL_FILL)
+        glDisable(GL_CULL_FACE) if twosided else glEnable(GL_CULL_FACE)
+
+        shader = self.shader
+
+        glUseProgram(shader)
+        glUniform4f( shader.Global_ambient, .4,.2,.2,.1 )
+        glUniform4f( shader.Light_ambient, .4,.4,.4, 1.0 )
+        glUniform4f( shader.Light_diffuse, 1,1,1,1 )
+        glUniform3f( shader.Light_location, 2,2,10 )
+
+        self.recursive_render(self.scene.rootnode, shader)
+
+
+        glUseProgram( 0 )
+
+    def recursive_render(self, node, shader):
+        """ Main recursive rendering method.
+        """
+
+        # save model matrix and apply node transformation
+        glPushMatrix()
+        m = node.transformation.transpose() # OpenGL row major
+        glMultMatrixf(m)
+
+        for mesh in node.meshes:
+
+            stride = 24 # 6 * 4 bytes
+
+            glUniform4f( shader.Material_diffuse, *mesh.material.properties["diffuse"] )
+            glUniform4f( shader.Material_ambient, *mesh.material.properties["ambient"] )
+
+            vbo = mesh.gl["vbo"]
+            vbo.bind()
+
+            glEnableVertexAttribArray( shader.Vertex_position )
+            glEnableVertexAttribArray( shader.Vertex_normal )
+
+            glVertexAttribPointer(
+                shader.Vertex_position,
+                3, GL_FLOAT,False, stride, vbo
+            )
+
+            glVertexAttribPointer(
+                shader.Vertex_normal,
+                3, GL_FLOAT,False, stride, vbo+12
+            )
+
+            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.gl["faces"])
+            glDrawElements(GL_TRIANGLES, len(mesh.faces) * 3, GL_UNSIGNED_INT, None)
+
+
+            vbo.unbind()
+            glDisableVertexAttribArray( shader.Vertex_position )
+
+            glDisableVertexAttribArray( shader.Vertex_normal )
+
+
+            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
+
+        for child in node.children:
+            self.recursive_render(child, shader)
+
+        glPopMatrix()
+
+
+    def loop(self):
+
+        pygame.display.flip()
+        pygame.event.pump()
+        self.keys = [k for k, pressed in enumerate(pygame.key.get_pressed()) if pressed]
+
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
+
+        # Compute FPS
+        gl_time = glutGet(GLUT_ELAPSED_TIME)
+        self.frames += 1
+        if gl_time - self.last_fps_time >= 1000:
+            current_fps = self.frames * 1000 / (gl_time - self.last_fps_time)
+            pygame.display.set_caption(self.base_name + " - %.0f fps" % current_fps)
+            self.frames = 0
+            self.last_fps_time = gl_time
+
+
+        return True
+
+    def controls_3d(self,
+                    mouse_button=1, \
+                    up_key=pygame.K_UP, \
+                    down_key=pygame.K_DOWN, \
+                    left_key=pygame.K_LEFT, \
+                    right_key=pygame.K_RIGHT):
+        """ The actual camera setting cycle """
+        mouse_dx,mouse_dy = pygame.mouse.get_rel()
+        if pygame.mouse.get_pressed()[mouse_button]:
+            look_speed = .2
+            buffer = glGetDoublev(GL_MODELVIEW_MATRIX)
+            c = (-1 * numpy.mat(buffer[:3,:3]) * \
+                numpy.mat(buffer[3,:3]).T).reshape(3,1)
+            # c is camera center in absolute coordinates, 
+            # we need to move it back to (0,0,0) 
+            # before rotating the camera
+            glTranslate(c[0],c[1],c[2])
+            m = buffer.flatten()
+            glRotate(mouse_dx * look_speed, m[1],m[5],m[9])
+            glRotate(mouse_dy * look_speed, m[0],m[4],m[8])
+            
+            # compensate roll
+            glRotated(-math.atan2(-m[4],m[5]) * \
+                57.295779513082320876798154814105 ,m[2],m[6],m[10])
+            glTranslate(-c[0],-c[1],-c[2])
+
+        # move forward-back or right-left
+        if up_key in self.keys:
+            fwd = .1
+        elif down_key in self.keys:
+            fwd = -.1
+        else:
+            fwd = 0
+
+        if left_key in self.keys:
+            strafe = .1
+        elif right_key in self.keys:
+            strafe = -.1
+        else:
+            strafe = 0
+
+        if abs(fwd) or abs(strafe):
+            m = glGetDoublev(GL_MODELVIEW_MATRIX).flatten()
+            glTranslate(fwd*m[2],fwd*m[6],fwd*m[10])
+            glTranslate(strafe*m[0],strafe*m[4],strafe*m[8])
+
+if __name__ == '__main__':
+    if not len(sys.argv) > 1:
+        print("Usage: " + __file__ + " <model>")
+        sys.exit(2)
+
+    app = PyAssimp3DViewer(model = sys.argv[1], w = 1024, h = 768, fov = 75)
+
+    while app.loop():
+        app.render()
+        app.controls_3d(0)
+        if pygame.K_f in app.keys: pygame.display.toggle_fullscreen()
+        if pygame.K_s in app.keys: app.screenshot()
+        if pygame.K_v in app.keys: app.check_visibility()
+        if pygame.K_TAB in app.keys: app.cycle_cameras()
+        if pygame.K_ESCAPE in app.keys:
+            break

+ 47 - 88
port/PyAssimp/scripts/opengl_viewer.py → port/PyAssimp/scripts/simple_opengl_viewer.py

@@ -1,14 +1,21 @@
 #!/usr/bin/env python
 #-*- coding: UTF-8 -*-
 
-""" This program demonstrate the use of pyassimp to render
-objects in OpenGL.
+""" This program demonstrates the use of pyassimp to load and
+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.
 
-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:
  - http://www.lighthouse3d.com/tutorials
@@ -21,9 +28,8 @@ import os, sys
 from OpenGL.GLUT import *
 from OpenGL.GLU 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)
 
 import math
@@ -40,20 +46,14 @@ width = 900
 
 class GLRenderer():
     def __init__(self):
-        self.scene = None
 
-        self.drot = 0.0
-        self.dp = 0.0
+        self.scene = None
 
-        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.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
         self.prev_time = 0
@@ -61,6 +61,10 @@ class GLRenderer():
         self.frames = 0
 
     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 = {}
 
@@ -90,8 +94,7 @@ class GLRenderer():
         glBindBuffer(GL_ARRAY_BUFFER,0)
         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0)
 
-    
-    def load_dae(self, path, postprocess = None):
+    def load_model(self, path, postprocess = None):
         logger.info("Loading model:" + path + "...")
 
         if postprocess:
@@ -129,9 +132,11 @@ class GLRenderer():
 
         if not self.using_fixed_cam:
             glLoadIdentity()
-            gluLookAt(self.x ,1., self.z, # pos
-                    self.x + self.lx - 1.0, 1., self.z + self.lz - 3.0, # look at
-                    0.,1.,0.) # up vector
+
+            gluLookAt(0.,0.,3.,
+                      0.,0.,-5.,
+                      0.,1.,0.)
+
 
 
     def set_camera(self, camera):
@@ -178,13 +183,13 @@ class GLRenderer():
         tmp = max(x_max, y_max)
         z_max = self.bb_max[2] - self.bb_min[2]
         tmp = max(z_max, tmp)
-        
+
         if not restore:
             tmp = 1. / tmp
 
         logger.info("Scaling the scene by %.03f" % tmp)
         glScalef(tmp, tmp, tmp)
-    
+
         # center the model
         direction = -1 if not restore else 1
         glTranslatef( direction * self.scene_center[0], 
@@ -192,25 +197,23 @@ class GLRenderer():
                       direction * self.scene_center[2] )
 
         return x_max, y_max, z_max
- 
+
     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.
         """
 
         if not hasattr(mat, "gl_mat"): # evaluate once the mat properties, and cache the values in a glDisplayList.
-    
-            diffuse = mat.properties.get("$clr.diffuse", numpy.array([0.8, 0.8, 0.8, 1.0]))
-            specular = mat.properties.get("$clr.specular", numpy.array([0., 0., 0., 1.0]))
-            ambient = mat.properties.get("$clr.ambient", numpy.array([0.2, 0.2, 0.2, 1.0]))
-            emissive = mat.properties.get("$clr.emissive", numpy.array([0., 0., 0., 1.0]))
-            shininess = min(mat.properties.get("$mat.shininess", 1.0), 128)
-            wireframe = mat.properties.get("$mat.wireframe", 0)
-            twosided = mat.properties.get("$mat.twosided", 1)
-    
-            from OpenGL.raw import GL
-            setattr(mat, "gl_mat", GL.GLuint(0))
-            mat.gl_mat = glGenLists(1)
+
+            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]))
+            ambient = numpy.array(mat.properties.get("ambient", [0.2, 0.2, 0.2, 1.0]))
+            emissive = numpy.array(mat.properties.get("emissive", [0., 0., 0., 1.0]))
+            shininess = min(mat.properties.get("shininess", 1.0), 128)
+            wireframe = mat.properties.get("wireframe", 0)
+            twosided = mat.properties.get("twosided", 1)
+
+            setattr(mat, "gl_mat", glGenLists(1))
             glNewList(mat.gl_mat, GL_COMPILE)
     
             glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse)
@@ -239,6 +242,8 @@ class GLRenderer():
         self.lz = -math.cos(self.angle)
         self.set_default_camera()
 
+        self.angle = (gl_time - self.prev_time) * 0.1
+
         self.prev_time = gl_time
 
         # Compute FPS
@@ -290,9 +295,10 @@ class GLRenderer():
         """ GLUT callback to redraw OpenGL surface
         """
         glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
-    
+
+        glRotatef(self.angle,0.,1.,0.)
         self.recursive_render(self.scene.rootnode)
-    
+
         glutSwapBuffers()
         self.do_motion()
         return
@@ -307,42 +313,6 @@ class GLRenderer():
         if key == 'q':
             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):
         """
 
@@ -364,7 +334,8 @@ class GLRenderer():
                 print("Fullscreen mode not available!")
                 sys.exit(1)
 
-        self.load_dae(filename, postprocess = postprocess)
+        self.load_model(filename, postprocess = postprocess)
+
 
         glClearColor(0.1,0.1,0.1,1.)
         #glShadeModel(GL_SMOOTH)
@@ -374,16 +345,10 @@ class GLRenderer():
         glEnable(GL_CULL_FACE)
         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)
         glEnable(GL_NORMALIZE)
         glEnable(GL_LIGHT0)
-    
+
         glutDisplayFunc(self.display)
 
 
@@ -399,14 +364,8 @@ class GLRenderer():
 
         glPushMatrix()
 
-        # Register GLUT callbacks for keyboard and mouse
         glutKeyboardFunc(self.onkeypress)
-        glutSpecialFunc(self.onspecialkeypress)
         glutIgnoreKeyRepeat(1)
-        glutSpecialUpFunc(self.onspecialkeyrelease)
-
-        glutMouseFunc(self.onclick)
-        glutMotionFunc(self.onmousemove)
 
         glutMainLoop()