Module Mesh
[hide private]
[frames] | no frames]

Source Code for Module Mesh

  1  #####################################################################
 
  2  # -*- coding: iso-8859-1 -*-                                        #
 
  3  #                                                                   #
 
  4  # Frets on Fire                                                     #
 
  5  # Copyright (C) 2006 Sami Kyöstilä                                  #
 
  6  #                                                                   #
 
  7  # This program is free software; you can redistribute it and/or     #
 
  8  # modify it under the terms of the GNU General Public License       #
 
  9  # as published by the Free Software Foundation; either version 2    #
 
 10  # of the License, or (at your option) any later version.            #
 
 11  #                                                                   #
 
 12  # This program is distributed in the hope that it will be useful,   #
 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of    #
 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     #
 
 15  # GNU General Public License for more details.                      #
 
 16  #                                                                   #
 
 17  # You should have received a copy of the GNU General Public License #
 
 18  # along with this program; if not, write to the Free Software       #
 
 19  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,        #
 
 20  # MA  02110-1301, USA.                                              #
 
 21  #####################################################################
 
 22  
 
 23  from OpenGL.GL import * 
 24  
 
 25  import Collada 
 26  
 
27 -class Mesh:
28 - def __init__(self, fileName):
29 self.doc = Collada.DaeDocument() 30 self.doc.LoadDocumentFromFile(fileName) 31 self.geoms = {} 32 self.fullGeoms = {}
33
34 - def _unflatten(self, array, stride):
35 return [tuple(array[i * stride : (i + 1) * stride]) for i in range(len(array) / stride)]
36
37 - def setupLight(self, light, n, pos):
38 l = light.techniqueCommon 39 glEnable(GL_LIGHTING) 40 glEnable(GL_LIGHT0 + n) 41 glLightfv(GL_LIGHT0 + n, GL_POSITION, (pos[0], pos[1], pos[2], 0.0)) 42 glLightfv(GL_LIGHT0 + n, GL_DIFFUSE, (l.color[0], l.color[1], l.color[2], 0.0)) 43 glLightfv(GL_LIGHT0 + n, GL_AMBIENT, (0.0, 0.0, 0.0, 0.0))
44
45 - def setupMaterial(self, material):
46 for m in material.techniqueCommon.iMaterials: 47 if m.object: 48 for fx in m.object.iEffects: 49 if fx.object: 50 shader = fx.object.profileCommon.technique.shader 51 if isinstance(shader, Collada.DaeFxShadePhong): 52 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shader.shininess.float) 53 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, shader.ambient.color.rgba) 54 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, shader.diffuse.color.rgba) 55 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, shader.specular.color.rgba)
56
57 - def render(self, geomName = None):
58 if geomName in self.fullGeoms: 59 glCallList(self.fullGeoms[geomName]) 60 return 61 62 # Prepare a new list for all the geometry 63 if not self.geoms: 64 for geom in self.doc.geometriesLibrary.items: 65 self.geoms[geom.name] = glGenLists(1) 66 glNewList(self.geoms[geom.name], GL_COMPILE) 67 68 for prim in geom.data.primitives: 69 maxOffset = vertexOffset = normalOffset = 0 70 vertexOffset = None 71 normalOffset = None 72 texcoordOffset = None 73 vertices = None 74 normals = None 75 texcoords = None 76 77 for input in prim.inputs: 78 maxOffset = max(maxOffset, input.offset) 79 if input.semantic == "VERTEX": 80 vertexOffset = input.offset 81 vertices = geom.data.FindSource(geom.data.vertices.FindInput("POSITION")) 82 assert vertices.techniqueCommon.accessor.stride == 3 83 vertices = self._unflatten(vertices.source.data, vertices.techniqueCommon.accessor.stride) 84 elif input.semantic == "NORMAL": 85 normalOffset = input.offset 86 normals = geom.data.FindSource(input) 87 normals = self._unflatten(normals.source.data, 3) 88 elif input.semantic == "TEXCOORD": 89 texcoordOffset = input.offset 90 texcoords = geom.data.FindSource(input) 91 texcoords = self._unflatten(texcoords.source.data, 2) 92 93 if normalOffset is None: 94 normals = geom.data.FindSource(geom.data.vertices.FindInput("NORMAL")) 95 normals = self._unflatten(normals.source.data, 3) 96 normalOffset = vertexOffset 97 98 def drawElement(indices, offset, array, func): 99 if offset is not None: 100 func(*array[indices[offset]])
101 102 if hasattr(prim, "polygons"): 103 for poly in prim.polygons: 104 glBegin(GL_POLYGON) 105 for indices in self._unflatten(poly, maxOffset + 1): 106 drawElement(indices, normalOffset, normals, glNormal3f) 107 drawElement(indices, texcoordOffset, texcoords, glTexCoord2f) 108 drawElement(indices, vertexOffset, vertices, glVertex3f) 109 glEnd() 110 elif hasattr(prim, "triangles"): 111 glBegin(GL_TRIANGLES) 112 for indices in self._unflatten(prim.triangles, maxOffset + 1): 113 drawElement(indices, normalOffset, normals, glNormal3f) 114 drawElement(indices, texcoordOffset, texcoords, glTexCoord2f) 115 drawElement(indices, vertexOffset, vertices, glVertex3f) 116 glEnd() 117 118 glEndList() 119 120 # Prepare a new display list for this particular geometry 121 self.fullGeoms[geomName] = glGenLists(1) 122 glNewList(self.fullGeoms[geomName], GL_COMPILE) 123 124 if self.geoms: 125 # setup lights 126 for scene in self.doc.visualScenesLibrary.items: 127 for node in scene.nodes: 128 for n, light in enumerate(node.iLights): 129 if light.object: 130 # TODO: hierarchical node transformation, other types of lights 131 pos = [0.0, 0.0, 0.0, 1.0] 132 for t in node.transforms: 133 if t[0] == "translate": 134 pos = t[1] 135 self.setupLight(light.object, n, pos) 136 137 # render geometry 138 for scene in self.doc.visualScenesLibrary.items: 139 for node in scene.nodes: 140 if geomName is not None and node.name != geomName: 141 continue 142 for geom in node.iGeometries: 143 if geom.object: 144 #for mat in geom.bindMaterials: 145 # self.setupMaterial(mat) 146 147 glPushMatrix() 148 for t in node.transforms: 149 if t[0] == "translate": 150 glTranslatef(*t[1]) 151 elif t[0] == "rotate": 152 glRotatef(t[1][3], t[1][0], t[1][1], t[1][2]) 153 elif t[0] == "scale": 154 glScalef(*t[1]) 155 if geom.object.name in self.geoms: 156 glCallList(self.geoms[geom.object.name]) 157 glPopMatrix() 158 glDisable(GL_LIGHTING) 159 for n in range(8): 160 glDisable(GL_LIGHT0 + n) 161 glEndList() 162 163 # Render the new list 164 self.render(geomName)
165