<s> from OpenGL . GL import * <EOL> from OpenGL . GLU import * <EOL> import pygame <EOL> import os . path <EOL> class Material ( object ) : <EOL> def __init__ ( self ) : <EOL> self . name = "<STR_LIT>" <EOL> self . texture_fname = None <EOL> self . texture_id = None <EOL> class FaceGroup ( object ) : <EOL> def __init__ ( self ) : <EOL> self . tri_indices = [ ] <EOL> self . material_name = "<STR_LIT>" <EOL> class Model3D ( object ) : <EOL> def __init__ ( self ) : <EOL> self . vertices = [ ] <EOL> self . tex_coords = [ ] <EOL> self . normals = [ ] <EOL> self . materials = { } <EOL> self . face_groups = [ ] <EOL> self . display_list_id = None <EOL> def __del__ ( self ) : <EOL> self . free_resources ( ) <EOL> def free_resources ( self ) : <EOL> if self . display_list_id is not None : <EOL> glDeleteLists ( self . display_list_id , <NUM_LIT:1> ) <EOL> self . display_list_id = None <EOL> for material in self . materials . values ( ) : <EOL> if material . texture_id is not None : <EOL> glDeleteTextures ( material . texture_id ) <EOL> self . materials . clear ( ) <EOL> del self . vertices [ : ] <EOL> del self . tex_coords [ : ] <EOL> del self . normals [ : ] <EOL> del self . face_groups [ : ] <EOL> def read_obj ( self , fname ) : <EOL> current_face_group = None <EOL> file_in = open ( fname ) <EOL> for line in file_in : <EOL> words = line . split ( ) <EOL> command = words [ <NUM_LIT:0> ] <EOL> data = words [ <NUM_LIT:1> : ] <EOL> if command == '<STR_LIT>' : <EOL> model_path = os . path . split ( fname ) [ <NUM_LIT:0> ] <EOL> mtllib_path = os . path . join ( model_path , data [ <NUM_LIT:0> ] ) <EOL> self . read_mtllib ( mtllib_path ) <EOL> elif command == '<STR_LIT:v>' : <EOL> x , y , z = data <EOL> vertex = ( float ( x ) , float ( y ) , float ( z ) ) <EOL> self . vertices . append ( vertex ) <EOL> elif command == '<STR_LIT>' : <EOL> s , t = data <EOL> tex_coord = ( float ( s ) , float ( t ) ) <EOL> self . tex_coords . append ( tex_coord ) <EOL> elif command == '<STR_LIT>' : <EOL> x , y , z = data <EOL> normal = ( float ( x ) , float ( y ) , float ( z ) ) <EOL> self . normals . append ( normal ) <EOL> elif command == '<STR_LIT>' : <EOL> current_face_group = FaceGroup ( ) <EOL> current_face_group . material_name = data [ <NUM_LIT:0> ] <EOL> self . face_groups . append ( current_face_group ) <EOL> elif command == '<STR_LIT:f>' : <EOL> assert len ( data ) == <NUM_LIT:3> , "<STR_LIT>" <EOL> for word in data : <EOL> vi , ti , ni = word . split ( '<STR_LIT:/>' ) <EOL> indices = ( int ( vi ) - <NUM_LIT:1> , int ( ti ) - <NUM_LIT:1> , int ( ni ) - <NUM_LIT:1> ) <EOL> current_face_group . tri_indices . append ( indices ) <EOL> for material in self . materials . values ( ) : <EOL> model_path = os . path . split ( fname ) [ <NUM_LIT:0> ] <EOL> texture_path = os . path . join ( model_path , material . texture_fname ) <EOL> texture_surface = pygame . image . load ( texture_path ) <EOL> texture_data = pygame . image . tostring ( texture_surface , '<STR_LIT>' , True ) <EOL> material . texture_id = glGenTextures ( <NUM_LIT:1> ) <EOL> glBindTexture ( GL_TEXTURE_2D , material . texture_id ) <EOL> glTexParameteri ( GL_TEXTURE_2D , <EOL> GL_TEXTURE_MAG_FILTER , <EOL> GL_LINEAR ) <EOL> glTexParameteri ( GL_TEXTURE_2D , <EOL> GL_TEXTURE_MIN_FILTER , <EOL> GL_LINEAR_MIPMAP_LINEAR ) <EOL> glPixelStorei ( GL_UNPACK_ALIGNMENT , <NUM_LIT:1> ) <EOL> width , height = texture_surface . get_rect ( ) . size <EOL> gluBuild2DMipmaps ( GL_TEXTURE_2D , <EOL> <NUM_LIT:3> , <EOL> width , <EOL> height , <EOL> GL_RGB , <EOL> GL_UNSIGNED_BYTE , <EOL> texture_data ) <EOL> def read_mtllib ( self , mtl_fname ) : <EOL> file_mtllib = open ( mtl_fname ) <EOL> for line in file_mtllib : <EOL> words = line . split ( ) <EOL> command = words [ <NUM_LIT:0> ] <EOL> data = words [ <NUM_LIT:1> : ] <EOL> if command == '<STR_LIT>' : <EOL> material = Material ( ) <EOL> material . name = data [ <NUM_LIT:0> ] <EOL> self . materials [ data [ <NUM_LIT:0> ] ] = material <EOL> elif command == '<STR_LIT>' : <EOL> material . texture_fname = data [ <NUM_LIT:0> ] <EOL> def draw ( self ) : <EOL> vertices = self . vertices <EOL> tex_coords = self . tex_coords <EOL> normals = self . normals <EOL> for face_group in self . face_groups : <EOL> material = self . materials [ face_group . material_name ] <EOL> glBindTexture ( GL_TEXTURE_2D , material . texture_id ) <EOL> glBegin ( GL_TRIANGLES ) <EOL> for vi , ti , ni in face_group . tri_indices : <EOL> glTexCoord2fv ( tex_coords [ ti ] ) <EOL> glNormal3fv ( normals [ ni ] ) <EOL> glVertex3fv ( vertices [ vi ] ) <EOL> glEnd ( ) <EOL> def draw_quick ( self ) : <EOL> if self . display_list_id is None : <EOL> self . display_list_id = glGenLists ( <NUM_LIT:1> ) <EOL> glNewList ( self . display_list_id , GL_COMPILE ) <EOL> self . draw ( ) <EOL> glEndList ( ) <EOL> glCallList ( self . display_list_id ) </s>
