Пример #1
0
    def __init__(self, filename=None, buffer=None):
        super(Data, self).__init__()

        self.meshes = {}

        # create our shader
        self.shader = Shader(vert=Data.shader_source['vert'],
                             frag=Data.shader_source['frag'])
        self.shader.attribute(0, 'in_position')
        self.shader.attribute(1, 'in_texture_coord')
        self.shader.attribute(2, 'in_normal')
        self.shader.frag_location('fragColor')
        self.shader.link()

        # bind our uniform indices
        self.shader.bind()
        self.shader.uniformi('tex0', 0)
        self.shader.unbind()

        self.obj = pymesh.obj.OBJ()
        if filename != None:
            self.obj.load(filename)
        else:
            self.obj.load_from_buffer(buffer)

        self._load()
Пример #2
0
    def __init__(self):
        super(SkeletonRenderer, self).__init__()

        self.num_joints = None
        self.shader = None

        self.vao = (GLuint)()
        self.indices_vbo = (GLuint)()
        self.matrix_vbo = (GLuint)()
        self.matrix_tbo = (GLuint)()

        # load our shader
        self.shader = ShaderProgram(
            Shader(GL_VERTEX_SHADER, SkeletonRenderer.shader_source['vert']),
            Shader(GL_FRAGMENT_SHADER, SkeletonRenderer.shader_source['frag']),
            link_now=False)

        # set our shader data
        # we MUST do this before we link the shader
        self.shader.attributes.in_index = 0
        self.shader.frag_location('out_frag_colour')

        # link the shader now
        self.shader.link()

        # bind our uniform indices
        self.shader.bind()
        self.shader.uniforms.in_bone_matrices = 0
        self.shader.unbind()

        # generate our buffers
        glGenVertexArrays(1, self.vao)
        glGenBuffers(1, self.indices_vbo)
        glGenBuffers(1, self.matrix_vbo)
        glGenTextures(1, self.matrix_tbo)
Пример #3
0
    def __init__(self, filename=None, buffer=None):
        super(Data, self).__init__()

        self.meshes = {}

        # create our shader
        self.shader = ShaderProgram(Shader(GL_VERTEX_SHADER,
                                           Data.shader_source['vert']),
                                    Shader(GL_FRAGMENT_SHADER,
                                           Data.shader_source['frag']),
                                    link_now=False)

        # set our shader data
        # we MUST do this before we link the shader
        self.shader.attributes.in_position = 0
        self.shader.attributes.in_texture_coord = 1
        self.shader.attributes.in_normal = 2
        self.shader.frag_location('out_frag_colour')

        # link the shader now
        self.shader.link()

        # bind our uniform indices
        self.shader.bind()
        self.shader.uniforms.tex0 = 0
        self.shader.unbind()

        self.obj = pymesh.obj.OBJ()
        if filename != None:
            self.obj.load(filename)
        else:
            self.obj.load_from_buffer(buffer)

        self._load()
Пример #4
0
    def __init__( self, filename = None, buffer = None ):
        super( Data, self ).__init__()

        self.meshes = {}

        # create our shader
        self.shader = Shader(
            vert = Data.shader_source['vert'],
            frag = Data.shader_source['frag']
            )
        self.shader.attribute( 0, 'in_position' )
        self.shader.attribute( 1, 'in_texture_coord' )
        self.shader.attribute( 2, 'in_normal' )
        self.shader.frag_location( 'fragColor' )
        self.shader.link()

        # bind our uniform indices
        self.shader.bind()
        self.shader.uniformi( 'tex0', 0 )
        self.shader.unbind()

        self.obj = pymesh.obj.OBJ()
        if filename != None:
            self.obj.load( filename )
        else:
            self.obj.load_from_buffer( buffer )
        
        self._load()
Пример #5
0
    def __init__(self, filename=None, buffer=None):
        super(Data, self).__init__()

        self.meshes = {}

        # create our shader
        self.shader = Shader(vert=Data.shader_source["vert"], frag=Data.shader_source["frag"])

        self.shader.attribute(0, "in_position_index")
        self.shader.attribute(1, "in_texture_coord_index")
        self.shader.attribute(2, "in_normal_index")
        self.shader.frag_location("fragColor")
        self.shader.link()

        # bind our uniform indices
        self.shader.bind()
        self.shader.uniformi("tex0", 0)
        self.shader.uniformi("in_positions", 1)
        self.shader.uniformi("in_texture_coords", 2)
        self.shader.uniformi("in_normals", 3)
        self.shader.unbind()

        self.meshes = {}
        self.vertex_texture = None
        self.texture_coord_texture = None
        self.normal_texture = None

        self.obj = pymesh.obj.OBJ()
        if filename != None:
            self.obj.load(filename)
        else:
            self.obj.load_from_buffer(buffer)

        self._load()
Пример #6
0
    def __init__( self, md5mesh ):
        super( Mesh, self ).__init__()

        self.mesh = MeshData( md5mesh )
        self.vbo = (GLuint)()
        self.tbo = (GLuint)()
        self.shader = None

        glGenBuffers( 1, self.vbo )
        glGenTextures( 1, self.tbo )

        self.shader = ShaderProgram(
            Shader( GL_VERTEX_SHADER, Mesh.shader_source['vert'] ),
            Shader( GL_FRAGMENT_SHADER, Mesh.shader_source['frag'] ),
            link_now = False
            )

        # set our shader data
        # we MUST do this before we link the shader
        self.shader.attributes.in_normal = 0
        self.shader.attributes.in_texture_coord = 1
        self.shader.attributes.in_bone_indices = 2
        self.shader.attributes.in_bone_weights_1 = 3
        self.shader.attributes.in_bone_weights_2 = 4
        self.shader.attributes.in_bone_weights_3 = 5
        self.shader.attributes.in_bone_weights_4 = 6
        self.shader.frag_location( 'out_frag_colour' )

        # link the shader now
        self.shader.link()

        # bind our uniform indices
        self.shader.bind()
        self.shader.uniforms.in_diffuse = 0
        self.shader.uniforms.in_specular = 1
        self.shader.uniforms.in_normal = 2
        self.shader.uniforms.in_bone_matrices = 4
        self.shader.unbind()
Пример #7
0
class Data( object ):

    shader_source = {
        'vert': open(os.path.dirname(__file__) + '/obj.vert','r').read(),
        'frag': open(os.path.dirname(__file__) + '/obj.frag','r').read()
    }

    _data = {}

    @classmethod
    def load( cls, filename ):
        # check if the model has been loaded previously 
        if filename in Data._data: 
            # create a new mesh with the same data 
            return Data._data[ filename ]

        data = cls( filename ) 

        # store mesh for later 
        Data._data[ filename ] = data

        return data

    @classmethod
    def unload( cls, filename ):
        if filename in Data._data:
            del Data._data[ filename ]

    def __init__( self, filename = None, buffer = None ):
        super( Data, self ).__init__()

        self.meshes = {}

        # create our shader
        self.shader = Shader(
            vert = Data.shader_source['vert'],
            frag = Data.shader_source['frag']
            )
        self.shader.attribute( 0, 'in_position' )
        self.shader.attribute( 1, 'in_texture_coord' )
        self.shader.attribute( 2, 'in_normal' )
        self.shader.frag_location( 'fragColor' )
        self.shader.link()

        # bind our uniform indices
        self.shader.bind()
        self.shader.uniformi( 'tex0', 0 )
        self.shader.unbind()

        self.obj = pymesh.obj.OBJ()
        if filename != None:
            self.obj.load( filename )
        else:
            self.obj.load_from_buffer( buffer )
        
        self._load()

    def _load( self ):
        """
        Processes the data loaded by the MD2 Loader
        """
        # convert the md2 data into data for the gpu
        # first, load our vertex buffer objects
        self._load_vertex_buffers()

    def _load_vertex_buffers( self ):
        # we need to convert from 3 lists with 3 sets of indices
        # to 3 lists with 1 set of indices
        # so for each index, we need to check if we already
        # have a matching vertex, and if not, make one
        raw_vertices = numpy.array( self.obj.model.vertices, dtype = 'float32' )
        raw_texture_coords = numpy.array( self.obj.model.texture_coords, dtype = 'float32' )
        raw_normals = numpy.array( self.obj.model.normals, dtype = 'float32' )


        # calculate our number of vertices
        # this way we can pre-allocate our arrays
        num_vertices = 0
        for mesh in self.obj.model.meshes:
            num_vertices += len(mesh['points'])

            # convert line strips to line segments
            # (size - 1) * 2
            for row in mesh['lines']:
                num_vertices += ((len(row) - 1) * 2)

            # convert triangle fans to triangles
            # (size - 2) *  3
            for row in mesh['faces']:
                num_vertices += ((len(row) - 2) * 3)

        vertices = numpy.empty( (num_vertices, 3), dtype = 'float32' )
        texture_coords = numpy.empty( (num_vertices, 2), dtype = 'float32' )
        normals = numpy.empty( (num_vertices, 3), dtype = 'float32' )

        current_offset = 0
        for mesh in self.obj.model.meshes:
            print 'Name:', mesh[ 'name' ],
            print 'Groups:', mesh['groups']

            initial_offset = current_offset

            # check if we need to create a point mesh
            num_point_indices = len(mesh['points'])
            if num_point_indices > 0:
                points = numpy.array( mesh['points'] )

                # ensure we don't have any 'None' values
                points = numpy.ma.masked_values( points, None ).filled( 0 ).astype('int32')

                # separate vertices, texture coords and normals
                points_v = points[ :, 0 ].repeat( 3 )
                points_t = points[ :, 1 ].repeat( 3 )
                points_n = points[ :, 2 ].repeat( 3 )

                v_d_indices = numpy.array([0,1,2], dtype = 'int32' ).tile( len(points) )
                t_d_indices = numpy.array([0,1,2], dtype = 'int32' ).tile( len(points) )
                t_d_indices = numpy.array([0,1,2], dtype = 'int32' ).tile( len(points) )

                # extract the indices
                vertices[ current_offset:num_point_indices ] = raw_vertices[ points_v, v_d_indices ]
                texture_coords[ current_offset:num_point_indices ] = raw_texture_coords[ points_t, t_d_indices ]
                normals[ current_offset:num_point_indices ] = raw_normals[ points_n, n_d_indices ]

                # increment the current offset
                current_offset += num_point_indices


            # check if we need to create a line mesh
            num_line_indices = len(mesh['lines'])
            if num_line_indices > 0:
                # each line tuple is a line strip
                # the easiest way to render is to convert to
                # line segments
                def convert_to_lines( strip ):
                    previous = strip[ 0 ]
                    for point in strip[ 1: ]:
                        yield previous
                        yield point
                        previous = point
                
                # convert each line strip into line segments
                lines = numpy.array([
                    point
                    for strip in mesh['lines']
                    for point in convert_to_lines( strip )
                    ])

                # update the number of lines
                num_line_indices = len(lines)

                # ensure we don't have any 'None' values
                lines = numpy.ma.masked_values( lines, None ).filled( 0 ).astype('int32')

                # separate vertices, texture coords and normals
                lines_v = lines[ :, 0 ]
                lines_t = lines[ :, 1 ]
                lines_n = lines[ :, 2 ]

                # extract the indices
                vertices[ current_offset:num_line_indices ] = raw_vertices[ lines_v ]
                texture_coords[ current_offset:num_line_indices ] = raw_texture_coords[ lines_t ]
                normals[ current_offset:num_line_indices ] = raw_normals[ lines_n ]

                # increment the current offset
                current_offset += num_line_indices


            # check if we need to create a face mesh
            num_face_indices = len(mesh['faces'])
            if num_face_indices > 0:
                # faces are stored as a list of triangle fans
                # we need to covnert them to triangles
                def convert_to_triangles( fan ):
                    # convert from triangle fan
                    # 0, 1, 2, 3, 4, 5
                    # to triangle list
                    # 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5
                    start = fan[ 0 ]
                    previous = fan[ 1 ]
                    for point in fan[ 2: ]:
                        yield start
                        yield previous
                        yield point
                        previous = point

                # convert each triangle face to triangles
                faces = numpy.array([
                    value
                    for triangle in mesh['faces']
                    for value in convert_to_triangles( triangle )
                    ])

                # update the number of faces
                num_face_indices = len(faces)

                # replace None with invalid values
                faces = numpy.ma.masked_values( faces, None ).filled( 0 ).astype('int32')

                # separate vertices, texture coords and normals
                faces_v = faces[ :, 0 ].repeat( 3 )
                faces_t = faces[ :, 1 ].repeat( 2 )
                faces_n = faces[ :, 2 ].repeat( 3 )

                indices3 = numpy.tile([0,1,2], num_face_indices ).astype( 'int32' )
                indices2 = numpy.tile([0,1], num_face_indices ).astype( 'int32' )

                # extract the indices
                start, end = current_offset, current_offset + num_face_indices

                extracted_v = raw_vertices[ faces_v, indices3 ].reshape( num_face_indices, 3 )
                vertices[ start:end ] = extracted_v

                if raw_texture_coords.size > 0:
                    extracted_t = raw_texture_coords[ faces_t, indices2 ].reshape( num_face_indices, 2 )
                    texture_coords[ start:end ] = extracted_t
                else:
                    texture_coords[ start:end ] = [ 0.0, 0.0 ]


                if raw_normals.size > 0:
                    extracted_n = raw_normals[ faces_n, indices3 ].reshape( num_face_indices, 3 )
                    normals[ start:end ] = extracted_n
                else:
                    normals[ start:end ] = [ 0.0, 0.0, 0.0 ]

                # increment the current offset
                current_offset += num_face_indices

            # store our indices
            gl_data = (
                (initial_offset, num_point_indices),
                (initial_offset + num_point_indices, num_line_indices),
                (initial_offset + num_point_indices + num_line_indices, num_face_indices)
                )

            # add the mesh to each of the mesh groups
            # each group has a list of meshes it owns
            for group in mesh['groups']:
                if group not in self.meshes:
                    self.meshes[ group ] = []
                self.meshes[ group ].append( gl_data )

        self.vao = (GLuint)()
        glGenVertexArrays( 1, self.vao )
        glBindVertexArray( self.vao )

        # create our global vertex data
        self.vbo = (GLuint * 3)()
        glGenBuffers( 3, self.vbo )

        vertices = vertices.flatten()
        texture_coords = texture_coords.flatten()
        normals = normals.flatten()

        # create a VBO for our vertices
        glBindBuffer( GL_ARRAY_BUFFER, self.vbo[ 0 ] )
        glBufferData(
            GL_ARRAY_BUFFER,
            vertices.nbytes,
            (GLfloat * len(vertices))(*vertices.flat),
            GL_STATIC_DRAW
            )

        # create a VBO for our texture coordinates
        glBindBuffer( GL_ARRAY_BUFFER, self.vbo[ 1 ] )
        glBufferData(
            GL_ARRAY_BUFFER,
            texture_coords.nbytes,
            (GLfloat * len(texture_coords))(*texture_coords.flat),
            GL_STATIC_DRAW
            )

        # create a VBO for our normals
        glBindBuffer( GL_ARRAY_BUFFER, self.vbo[ 2 ] )
        glBufferData(
            GL_ARRAY_BUFFER,
            normals.nbytes,
            (GLfloat * len(normals))(*normals.flat),
            GL_STATIC_DRAW
            )

        # unbind our buffers
        glBindBuffer( GL_ARRAY_BUFFER, 0 )
        glBindVertexArray( 0 )

    def render( self, projection, model_view, groups ):
        self.shader.bind()
        self.shader.uniform_matrixf( 'model_view', model_view.flat )
        self.shader.uniform_matrixf( 'projection', projection.flat )

        glBindVertexArray( self.vao )

        # bind our global data
        # vertices
        glBindBuffer( GL_ARRAY_BUFFER, self.vbo[ 0 ] )
        glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, 0 )
        glEnableVertexAttribArray( 0 )

        # texture coords
        glBindBuffer( GL_ARRAY_BUFFER, self.vbo[ 1 ] )
        glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, 0, 0 )
        glEnableVertexAttribArray( 1 )

        # normals
        glBindBuffer( GL_ARRAY_BUFFER, self.vbo[ 2 ] )
        glVertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, 0, 0 )
        glEnableVertexAttribArray( 2 )

        # iterate through the specified groups
        for group in groups:
            # get the group
            for mesh in self.meshes[ group ]:
                points, lines, faces = mesh

                point_start, point_count = points
                line_start, line_count = lines
                face_start, face_count = faces

                if points[ 1 ] > 0:
                    glDrawArrays( GL_POINTS, point_start, point_count )
                if lines[ 1 ] > 0:
                    glDrawArrays( GL_LINES, line_start, line_count )
                if faces[ 1 ] > 0:
                    glDrawArrays( GL_TRIANGLES, face_start, face_count )

        glDisableVertexAttribArray( 0 )
        glDisableVertexAttribArray( 1 )
        glDisableVertexAttribArray( 2 )

        glBindBuffer( GL_ARRAY_BUFFER, 0 )
        glBindVertexArray( 0 )

        self.shader.unbind()
Пример #8
0
class Data(object):

    shader_source = {
        'vert': open(os.path.dirname(__file__) + '/obj.vert', 'r').read(),
        'frag': open(os.path.dirname(__file__) + '/obj.frag', 'r').read()
    }

    _data = {}

    @classmethod
    def load(cls, filename):
        # check if the model has been loaded previously
        if filename in Data._data:
            # create a new mesh with the same data
            return Data._data[filename]

        data = cls(filename)

        # store mesh for later
        Data._data[filename] = data

        return data

    @classmethod
    def unload(cls, filename):
        if filename in Data._data:
            del Data._data[filename]

    def __init__(self, filename=None, buffer=None):
        super(Data, self).__init__()

        self.meshes = {}

        # create our shader
        self.shader = Shader(vert=Data.shader_source['vert'],
                             frag=Data.shader_source['frag'])
        self.shader.attribute(0, 'in_position')
        self.shader.attribute(1, 'in_texture_coord')
        self.shader.attribute(2, 'in_normal')
        self.shader.frag_location('fragColor')
        self.shader.link()

        # bind our uniform indices
        self.shader.bind()
        self.shader.uniformi('tex0', 0)
        self.shader.unbind()

        self.obj = pymesh.obj.OBJ()
        if filename != None:
            self.obj.load(filename)
        else:
            self.obj.load_from_buffer(buffer)

        self._load()

    def _load(self):
        """
        Processes the data loaded by the MD2 Loader
        """
        # convert the md2 data into data for the gpu
        # first, load our vertex buffer objects
        self._load_vertex_buffers()

    def _load_vertex_buffers(self):
        # we need to convert from 3 lists with 3 sets of indices
        # to 3 lists with 1 set of indices
        # so for each index, we need to check if we already
        # have a matching vertex, and if not, make one
        raw_vertices = numpy.array(self.obj.model.vertices, dtype='float32')
        raw_texture_coords = numpy.array(self.obj.model.texture_coords,
                                         dtype='float32')
        raw_normals = numpy.array(self.obj.model.normals, dtype='float32')

        # calculate our number of vertices
        # this way we can pre-allocate our arrays
        num_vertices = 0
        for mesh in self.obj.model.meshes:
            num_vertices += len(mesh['points'])

            # convert line strips to line segments
            # (size - 1) * 2
            for row in mesh['lines']:
                num_vertices += ((len(row) - 1) * 2)

            # convert triangle fans to triangles
            # (size - 2) *  3
            for row in mesh['faces']:
                num_vertices += ((len(row) - 2) * 3)

        vertices = numpy.empty((num_vertices, 3), dtype='float32')
        texture_coords = numpy.empty((num_vertices, 2), dtype='float32')
        normals = numpy.empty((num_vertices, 3), dtype='float32')

        current_offset = 0
        for mesh in self.obj.model.meshes:
            print 'Name:', mesh['name'],
            print 'Groups:', mesh['groups']

            initial_offset = current_offset

            # check if we need to create a point mesh
            num_point_indices = len(mesh['points'])
            if num_point_indices > 0:
                points = numpy.array(mesh['points'])

                # ensure we don't have any 'None' values
                points = numpy.ma.masked_values(points,
                                                None).filled(0).astype('int32')

                # separate vertices, texture coords and normals
                points_v = points[:, 0].repeat(3)
                points_t = points[:, 1].repeat(3)
                points_n = points[:, 2].repeat(3)

                v_d_indices = numpy.array([0, 1, 2],
                                          dtype='int32').tile(len(points))
                t_d_indices = numpy.array([0, 1, 2],
                                          dtype='int32').tile(len(points))
                t_d_indices = numpy.array([0, 1, 2],
                                          dtype='int32').tile(len(points))

                # extract the indices
                vertices[current_offset:num_point_indices] = raw_vertices[
                    points_v, v_d_indices]
                texture_coords[
                    current_offset:num_point_indices] = raw_texture_coords[
                        points_t, t_d_indices]
                normals[current_offset:num_point_indices] = raw_normals[
                    points_n, n_d_indices]

                # increment the current offset
                current_offset += num_point_indices

            # check if we need to create a line mesh
            num_line_indices = len(mesh['lines'])
            if num_line_indices > 0:
                # each line tuple is a line strip
                # the easiest way to render is to convert to
                # line segments
                def convert_to_lines(strip):
                    previous = strip[0]
                    for point in strip[1:]:
                        yield previous
                        yield point
                        previous = point

                # convert each line strip into line segments
                lines = numpy.array([
                    point for strip in mesh['lines']
                    for point in convert_to_lines(strip)
                ])

                # update the number of lines
                num_line_indices = len(lines)

                # ensure we don't have any 'None' values
                lines = numpy.ma.masked_values(lines,
                                               None).filled(0).astype('int32')

                # separate vertices, texture coords and normals
                lines_v = lines[:, 0]
                lines_t = lines[:, 1]
                lines_n = lines[:, 2]

                # extract the indices
                vertices[current_offset:num_line_indices] = raw_vertices[
                    lines_v]
                texture_coords[current_offset:
                               num_line_indices] = raw_texture_coords[lines_t]
                normals[current_offset:num_line_indices] = raw_normals[lines_n]

                # increment the current offset
                current_offset += num_line_indices

            # check if we need to create a face mesh
            num_face_indices = len(mesh['faces'])
            if num_face_indices > 0:
                # faces are stored as a list of triangle fans
                # we need to covnert them to triangles
                def convert_to_triangles(fan):
                    # convert from triangle fan
                    # 0, 1, 2, 3, 4, 5
                    # to triangle list
                    # 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5
                    start = fan[0]
                    previous = fan[1]
                    for point in fan[2:]:
                        yield start
                        yield previous
                        yield point
                        previous = point

                # convert each triangle face to triangles
                faces = numpy.array([
                    value for triangle in mesh['faces']
                    for value in convert_to_triangles(triangle)
                ])

                # update the number of faces
                num_face_indices = len(faces)

                # replace None with invalid values
                faces = numpy.ma.masked_values(faces,
                                               None).filled(0).astype('int32')

                # separate vertices, texture coords and normals
                faces_v = faces[:, 0].repeat(3)
                faces_t = faces[:, 1].repeat(2)
                faces_n = faces[:, 2].repeat(3)

                indices3 = numpy.tile([0, 1, 2],
                                      num_face_indices).astype('int32')
                indices2 = numpy.tile([0, 1], num_face_indices).astype('int32')

                # extract the indices
                start, end = current_offset, current_offset + num_face_indices

                extracted_v = raw_vertices[faces_v, indices3].reshape(
                    num_face_indices, 3)
                vertices[start:end] = extracted_v

                if raw_texture_coords.size > 0:
                    extracted_t = raw_texture_coords[faces_t,
                                                     indices2].reshape(
                                                         num_face_indices, 2)
                    texture_coords[start:end] = extracted_t
                else:
                    texture_coords[start:end] = [0.0, 0.0]

                if raw_normals.size > 0:
                    extracted_n = raw_normals[faces_n, indices3].reshape(
                        num_face_indices, 3)
                    normals[start:end] = extracted_n
                else:
                    normals[start:end] = [0.0, 0.0, 0.0]

                # increment the current offset
                current_offset += num_face_indices

            # store our indices
            gl_data = ((initial_offset, num_point_indices),
                       (initial_offset + num_point_indices, num_line_indices),
                       (initial_offset + num_point_indices + num_line_indices,
                        num_face_indices))

            # add the mesh to each of the mesh groups
            # each group has a list of meshes it owns
            for group in mesh['groups']:
                if group not in self.meshes:
                    self.meshes[group] = []
                self.meshes[group].append(gl_data)

        self.vao = (GLuint)()
        glGenVertexArrays(1, self.vao)
        glBindVertexArray(self.vao)

        # create our global vertex data
        self.vbo = (GLuint * 3)()
        glGenBuffers(3, self.vbo)

        vertices = vertices.flatten()
        texture_coords = texture_coords.flatten()
        normals = normals.flatten()

        # create a VBO for our vertices
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo[0])
        glBufferData(GL_ARRAY_BUFFER, vertices.nbytes,
                     (GLfloat * len(vertices))(*vertices.flat), GL_STATIC_DRAW)

        # create a VBO for our texture coordinates
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo[1])
        glBufferData(GL_ARRAY_BUFFER, texture_coords.nbytes,
                     (GLfloat * len(texture_coords))(*texture_coords.flat),
                     GL_STATIC_DRAW)

        # create a VBO for our normals
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo[2])
        glBufferData(GL_ARRAY_BUFFER, normals.nbytes,
                     (GLfloat * len(normals))(*normals.flat), GL_STATIC_DRAW)

        # unbind our buffers
        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glBindVertexArray(0)

    def render(self, projection, model_view, groups):
        self.shader.bind()
        self.shader.uniform_matrixf('model_view', model_view.flat)
        self.shader.uniform_matrixf('projection', projection.flat)

        glBindVertexArray(self.vao)

        # bind our global data
        # vertices
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo[0])
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0)
        glEnableVertexAttribArray(0)

        # texture coords
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo[1])
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0)
        glEnableVertexAttribArray(1)

        # normals
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo[2])
        glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0)
        glEnableVertexAttribArray(2)

        # iterate through the specified groups
        for group in groups:
            # get the group
            for mesh in self.meshes[group]:
                points, lines, faces = mesh

                point_start, point_count = points
                line_start, line_count = lines
                face_start, face_count = faces

                if points[1] > 0:
                    glDrawArrays(GL_POINTS, point_start, point_count)
                if lines[1] > 0:
                    glDrawArrays(GL_LINES, line_start, line_count)
                if faces[1] > 0:
                    glDrawArrays(GL_TRIANGLES, face_start, face_count)

        glDisableVertexAttribArray(0)
        glDisableVertexAttribArray(1)
        glDisableVertexAttribArray(2)

        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glBindVertexArray(0)

        self.shader.unbind()
Пример #9
0
class Data(object):

    shader_source = {
        "vert": open(os.path.dirname(__file__) + "/obj.vert", "r").read(),
        "frag": open(os.path.dirname(__file__) + "/obj.frag", "r").read(),
    }

    _data = {}

    @classmethod
    def load(cls, filename):
        # check if the model has been loaded previously
        if filename in Data._data:
            # create a new mesh with the same data
            return Data._data[filename]

        data = cls(filename)

        # store mesh for later
        Data._data[filename] = data

        return data

    @classmethod
    def unload(cls, filename):
        if filename in Data._data:
            del Data._data[filename]

    def __init__(self, filename=None, buffer=None):
        super(Data, self).__init__()

        self.meshes = {}

        # create our shader
        self.shader = Shader(vert=Data.shader_source["vert"], frag=Data.shader_source["frag"])

        self.shader.attribute(0, "in_position_index")
        self.shader.attribute(1, "in_texture_coord_index")
        self.shader.attribute(2, "in_normal_index")
        self.shader.frag_location("fragColor")
        self.shader.link()

        # bind our uniform indices
        self.shader.bind()
        self.shader.uniformi("tex0", 0)
        self.shader.uniformi("in_positions", 1)
        self.shader.uniformi("in_texture_coords", 2)
        self.shader.uniformi("in_normals", 3)
        self.shader.unbind()

        self.meshes = {}
        self.vertex_texture = None
        self.texture_coord_texture = None
        self.normal_texture = None

        self.obj = pymesh.obj.OBJ()
        if filename != None:
            self.obj.load(filename)
        else:
            self.obj.load_from_buffer(buffer)

        self._load()

    def _load(self):
        """
        Processes the data loaded by the MD2 Loader
        """
        # convert the md2 data into data for the gpu
        # first, load our vertex buffer objects
        self._load_vertex_buffers()

    def _load_vertex_buffers(self):
        # create a Vertex Array Object
        # these are required to do any rendering
        self.vao = (GLuint)()
        glGenVertexArrays(1, self.vao)
        glBindVertexArray(self.vao)

        # convert to numpy for easy manipulation
        vertices = numpy.array(self.obj.model.vertices, dtype="float32")
        texture_coords = numpy.array(self.obj.model.texture_coords, dtype="float32")
        normals = numpy.array(self.obj.model.normals, dtype="float32")

        # ensure our vertices fit within our max texture width
        max_width = GLint()
        glGetIntegerv(GL_MAX_TEXTURE_SIZE, max_width)
        max_width = max_width.value

        def resize_array(array, max_width):
            if array.shape[0] > max_width:
                num_arrays = int(array.shape[0] / max_width) + 1
                array = numpy.resize(array, (num_arrays, max_width, array.shape[1]))
            else:
                array.shape = (1, array.shape[0], array.shape[1])
            print array.shape, max_width
            return array

        vertices = resize_array(vertices, max_width)
        if texture_coords.size > 0:
            texture_coords = resize_array(texture_coords, max_width)
        if normals.size > 0:
            normals = resize_array(normals, max_width)

        # convert to Texture1D
        def create_texture(data, format):
            # convert data to a  1D texture
            # first convert to a 1D array
            # and then to GLubyte format

            # create a texture
            texture = Texture2D(GL_TEXTURE_1D_ARRAY)
            texture.bind()

            # disable texture filtering
            texture.set_min_mag_filter(min=GL_NEAREST, mag=GL_NEAREST)

            # set the texture data
            texture.set_image(data.astype("float32").flat, [data.shape[1], data.shape[0]], format)

            texture.unbind()

            return texture

        self.vertex_texture = create_texture(vertices, "f32/rgb/rgb32f")
        if texture_coords.size > 0:
            self.texture_coord_texture = create_texture(texture_coords, "f32/rg/rg32f")
        if normals.size > 0:
            self.normal_texture = create_texture(normals, "f32/rgb/rgb32f")

        # convert each meshes' indices into attribute arrays
        # iterate through each mesh group
        for mesh in self.obj.model.meshes:
            # for mesh in self.obj.model.meshes.itervalues():
            print "Name:", mesh["name"], "Groups:", mesh["groups"]

            # points
            points = numpy.array(mesh["points"])

            num_point_indices = len(points)
            if num_point_indices:
                # replace None with invalid values
                points = numpy.ma.masked_values(points, None).filled(-1)

                points_v = points[:, 0]
                points_t = points[:, 1]
                points_n = points[:, 2]

            # lines
            # convert from line strips to line segments
            def convert_to_lines(strip):
                previous = strip[0]
                for point in strip[1:]:
                    yield previous
                    yield point
                    previous = point

            # convert each line strip into line segments
            lines = numpy.array([value for strip in mesh["lines"] for value in convert_to_lines(strip)])

            num_line_indices = len(lines)
            if num_line_indices:
                # replace None with invalid values
                lines = numpy.ma.masked_values(lines, None).filled(-1)

                lines_v = lines[:, 0]
                lines_t = lines[:, 1]
                lines_n = lines[:, 2]

            # faces
            # convert from triangle fans to triangles
            def convert_to_triangles(fan):
                # convert from triangle fan
                # 0, 1, 2, 3, 4, 5
                # to triangle list
                # 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5
                start = fan[0]
                previous = fan[1]
                for point in fan[2:]:
                    yield start
                    yield previous
                    yield point
                    previous = point

            # convert each triangle face to triangles
            triangles = numpy.array([value for triangle in mesh["faces"] for value in convert_to_triangles(triangle)])

            num_triangle_indices = len(triangles)
            if num_triangle_indices:
                # replace None with invalid values
                triangles = numpy.ma.masked_values(triangles, None).filled(-1)

                triangles_v = triangles[:, 0]
                triangles_t = triangles[:, 1]
                triangles_n = triangles[:, 2]

            v = []
            t = []
            n = []
            if num_point_indices:
                v.append(points_v)
                t.append(points_t)
                n.append(points_n)
            if num_line_indices:
                v.append(lines_v)
                t.append(lines_t)
                n.append(lines_n)
            if num_triangle_indices:
                v.append(triangles_v)
                t.append(triangles_t)
                n.append(triangles_n)

            v_indices = numpy.hstack(tuple(v)).astype("int32")
            t_indices = numpy.hstack(tuple(t)).astype("int32")
            n_indices = numpy.hstack(tuple(n)).astype("int32")

            # create our global vertex data
            mesh_vbos = (GLuint * 3)()
            glGenBuffers(3, mesh_vbos)

            # create ours VBOs to store our indices
            # TODO: store these in 1 buffer using stride
            # http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttribPointer.xml

            # vertices
            glBindBuffer(GL_ARRAY_BUFFER, mesh_vbos[0])
            glBufferData(GL_ARRAY_BUFFER, v_indices.nbytes, (GLint * v_indices.size)(*v_indices), GL_STATIC_DRAW)

            # texture coords
            glBindBuffer(GL_ARRAY_BUFFER, mesh_vbos[1])
            glBufferData(GL_ARRAY_BUFFER, t_indices.nbytes, (GLint * t_indices.size)(*t_indices), GL_STATIC_DRAW)

            # normals
            glBindBuffer(GL_ARRAY_BUFFER, mesh_vbos[2])
            glBufferData(GL_ARRAY_BUFFER, n_indices.nbytes, (GLint * n_indices.size)(*n_indices), GL_STATIC_DRAW)

            # store our indices
            gl_data = (
                mesh_vbos,
                (0, num_point_indices),
                (num_point_indices, num_line_indices),
                (num_point_indices + num_line_indices, num_triangle_indices),
            )

            # add the mesh to each of the mesh groups
            # each group has a list of meshes it owns
            for group in mesh["groups"]:
                if group not in self.meshes:
                    self.meshes[group] = []
                self.meshes[group].append(gl_data)

        # unbind our arrays
        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glBindVertexArray(0)

    def render(self, projection, model_view, groups):
        self.shader.bind()
        self.shader.uniform_matrixf("model_view", model_view.flat)
        self.shader.uniform_matrixf("projection", projection.flat)

        glBindVertexArray(self.vao)

        # bind our global data
        # vertices
        glActiveTexture(GL_TEXTURE1)
        self.vertex_texture.bind()

        # texture coordinates
        if self.texture_coord_texture:
            glActiveTexture(GL_TEXTURE2)
            self.texture_coord_texture.bind()

        # normals
        if self.normal_texture:
            glActiveTexture(GL_TEXTURE3)
            self.normal_texture.bind()

        # render each set of indices
        glEnableVertexAttribArray(0)
        glEnableVertexAttribArray(1)
        glEnableVertexAttribArray(2)

        # iterate through the specified groups
        for group in groups:
            # get the group
            for mesh in self.meshes[group]:
                mesh_vbo, points, lines, triangles = mesh
                v_indices, t_indices, n_indices = mesh_vbo

                # vertex indices
                glBindBuffer(GL_ARRAY_BUFFER, v_indices)
                glVertexAttribIPointer(0, 1, GL_INT, GL_FALSE, 0, 0)

                # texture coordinate indices
                glBindBuffer(GL_ARRAY_BUFFER, t_indices)
                glVertexAttribIPointer(1, 1, GL_INT, GL_FALSE, 0, 0)

                # normal indices
                glBindBuffer(GL_ARRAY_BUFFER, n_indices)
                glVertexAttribIPointer(2, 1, GL_INT, GL_FALSE, 0, 0)

                # render the group
                if points[1] > 0:
                    start, count = 0, points[1]
                    glDrawArrays(GL_POINTS, start, count)
                if lines[1] > 0:
                    start, count = points[1], lines[1]
                    glDrawArrays(GL_LINES, start, count)
                if triangles[1] > 0:
                    start, count = points[1] + lines[1], triangles[1]
                    glDrawArrays(GL_TRIANGLES, start, count)

        # cleanup
        glDisableVertexAttribArray(0)
        glDisableVertexAttribArray(1)
        glDisableVertexAttribArray(2)

        # unbind our textures
        if self.normal_texture:
            self.normal_texture.unbind()
        if self.texture_coord_texture:
            glActiveTexture(GL_TEXTURE2)
            self.texture_coord_texture.unbind()
        glActiveTexture(GL_TEXTURE1)
        self.vertex_texture.unbind()
        glActiveTexture(GL_TEXTURE0)

        # unbind our buffers
        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
        glBindVertexArray(0)

        self.shader.unbind()
Пример #10
0
class Data(object):

    shader_source = {
        'vert': open(os.path.dirname(__file__) + '/obj.vert', 'r').read(),
        'frag': open(os.path.dirname(__file__) + '/obj.frag', 'r').read()
    }

    _data = {}

    @classmethod
    def load(cls, filename):
        # check if the model has been loaded previously
        if filename in Data._data:
            # create a new mesh with the same data
            return Data._data[filename]

        data = cls(filename)

        # store mesh for later
        Data._data[filename] = data

        return data

    @classmethod
    def unload(cls, filename):
        if filename in Data._data:
            del Data._data[filename]

    def __init__(self, filename=None, buffer=None):
        super(Data, self).__init__()

        self.meshes = {}

        # create our shader
        self.shader = Shader(vert=Data.shader_source['vert'],
                             frag=Data.shader_source['frag'])

        self.shader.attribute(0, 'in_position_index')
        self.shader.attribute(1, 'in_texture_coord_index')
        self.shader.attribute(2, 'in_normal_index')
        self.shader.frag_location('fragColor')
        self.shader.link()

        # bind our uniform indices
        self.shader.bind()
        self.shader.uniformi('tex0', 0)
        self.shader.uniformi('in_positions', 1)
        self.shader.uniformi('in_texture_coords', 2)
        self.shader.uniformi('in_normals', 3)
        self.shader.unbind()

        self.meshes = {}
        self.vertex_texture = None
        self.texture_coord_texture = None
        self.normal_texture = None

        self.obj = pymesh.obj.OBJ()
        if filename != None:
            self.obj.load(filename)
        else:
            self.obj.load_from_buffer(buffer)

        self._load()

    def _load(self):
        """
        Processes the data loaded by the MD2 Loader
        """
        # convert the md2 data into data for the gpu
        # first, load our vertex buffer objects
        self._load_vertex_buffers()

    def _load_vertex_buffers(self):
        # create a Vertex Array Object
        # these are required to do any rendering
        self.vao = (GLuint)()
        glGenVertexArrays(1, self.vao)
        glBindVertexArray(self.vao)

        # convert to numpy for easy manipulation
        vertices = numpy.array(self.obj.model.vertices, dtype='float32')
        texture_coords = numpy.array(self.obj.model.texture_coords,
                                     dtype='float32')
        normals = numpy.array(self.obj.model.normals, dtype='float32')

        # ensure our vertices fit within our max texture width
        max_width = GLint()
        glGetIntegerv(GL_MAX_TEXTURE_SIZE, max_width)
        max_width = max_width.value

        def resize_array(array, max_width):
            if array.shape[0] > max_width:
                num_arrays = int(array.shape[0] / max_width) + 1
                array = numpy.resize(array,
                                     (num_arrays, max_width, array.shape[1]))
            else:
                array.shape = (1, array.shape[0], array.shape[1])
            print array.shape, max_width
            return array

        vertices = resize_array(vertices, max_width)
        if texture_coords.size > 0:
            texture_coords = resize_array(texture_coords, max_width)
        if normals.size > 0:
            normals = resize_array(normals, max_width)

        # convert to Texture1D
        def create_texture(data, format):
            # convert data to a  1D texture
            # first convert to a 1D array
            # and then to GLubyte format

            # create a texture
            texture = Texture2D(GL_TEXTURE_1D_ARRAY)
            texture.bind()

            # disable texture filtering
            texture.set_min_mag_filter(min=GL_NEAREST, mag=GL_NEAREST)

            # set the texture data
            texture.set_image(
                data.astype('float32').flat, [data.shape[1], data.shape[0]],
                format)

            texture.unbind()

            return texture

        self.vertex_texture = create_texture(vertices, 'f32/rgb/rgb32f')
        if texture_coords.size > 0:
            self.texture_coord_texture = create_texture(
                texture_coords, 'f32/rg/rg32f')
        if normals.size > 0:
            self.normal_texture = create_texture(normals, 'f32/rgb/rgb32f')

        # convert each meshes' indices into attribute arrays
        # iterate through each mesh group
        for mesh in self.obj.model.meshes:
            #for mesh in self.obj.model.meshes.itervalues():
            print 'Name:', mesh['name'], 'Groups:', mesh['groups']

            # points
            points = numpy.array(mesh['points'])

            num_point_indices = len(points)
            if num_point_indices:
                # replace None with invalid values
                points = numpy.ma.masked_values(points, None).filled(-1)

                points_v = points[:, 0]
                points_t = points[:, 1]
                points_n = points[:, 2]

            # lines
            # convert from line strips to line segments
            def convert_to_lines(strip):
                previous = strip[0]
                for point in strip[1:]:
                    yield previous
                    yield point
                    previous = point

            # convert each line strip into line segments
            lines = numpy.array([
                value for strip in mesh['lines']
                for value in convert_to_lines(strip)
            ])

            num_line_indices = len(lines)
            if num_line_indices:
                # replace None with invalid values
                lines = numpy.ma.masked_values(lines, None).filled(-1)

                lines_v = lines[:, 0]
                lines_t = lines[:, 1]
                lines_n = lines[:, 2]

            # faces
            # convert from triangle fans to triangles
            def convert_to_triangles(fan):
                # convert from triangle fan
                # 0, 1, 2, 3, 4, 5
                # to triangle list
                # 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5
                start = fan[0]
                previous = fan[1]
                for point in fan[2:]:
                    yield start
                    yield previous
                    yield point
                    previous = point

            # convert each triangle face to triangles
            triangles = numpy.array([
                value for triangle in mesh['faces']
                for value in convert_to_triangles(triangle)
            ])

            num_triangle_indices = len(triangles)
            if num_triangle_indices:
                # replace None with invalid values
                triangles = numpy.ma.masked_values(triangles, None).filled(-1)

                triangles_v = triangles[:, 0]
                triangles_t = triangles[:, 1]
                triangles_n = triangles[:, 2]

            v = []
            t = []
            n = []
            if num_point_indices:
                v.append(points_v)
                t.append(points_t)
                n.append(points_n)
            if num_line_indices:
                v.append(lines_v)
                t.append(lines_t)
                n.append(lines_n)
            if num_triangle_indices:
                v.append(triangles_v)
                t.append(triangles_t)
                n.append(triangles_n)

            v_indices = numpy.hstack(tuple(v)).astype('int32')
            t_indices = numpy.hstack(tuple(t)).astype('int32')
            n_indices = numpy.hstack(tuple(n)).astype('int32')

            # create our global vertex data
            mesh_vbos = (GLuint * 3)()
            glGenBuffers(3, mesh_vbos)

            # create ours VBOs to store our indices
            # TODO: store these in 1 buffer using stride
            # http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttribPointer.xml

            # vertices
            glBindBuffer(GL_ARRAY_BUFFER, mesh_vbos[0])
            glBufferData(GL_ARRAY_BUFFER, v_indices.nbytes,
                         (GLint * v_indices.size)(*v_indices), GL_STATIC_DRAW)

            # texture coords
            glBindBuffer(GL_ARRAY_BUFFER, mesh_vbos[1])
            glBufferData(GL_ARRAY_BUFFER, t_indices.nbytes,
                         (GLint * t_indices.size)(*t_indices), GL_STATIC_DRAW)

            # normals
            glBindBuffer(GL_ARRAY_BUFFER, mesh_vbos[2])
            glBufferData(GL_ARRAY_BUFFER, n_indices.nbytes,
                         (GLint * n_indices.size)(*n_indices), GL_STATIC_DRAW)

            # store our indices
            gl_data = (mesh_vbos, (0, num_point_indices), (num_point_indices,
                                                           num_line_indices),
                       (num_point_indices + num_line_indices,
                        num_triangle_indices))

            # add the mesh to each of the mesh groups
            # each group has a list of meshes it owns
            for group in mesh['groups']:
                if group not in self.meshes:
                    self.meshes[group] = []
                self.meshes[group].append(gl_data)

        # unbind our arrays
        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glBindVertexArray(0)

    def render(self, projection, model_view, groups):
        self.shader.bind()
        self.shader.uniform_matrixf('model_view', model_view.flat)
        self.shader.uniform_matrixf('projection', projection.flat)

        glBindVertexArray(self.vao)

        # bind our global data
        # vertices
        glActiveTexture(GL_TEXTURE1)
        self.vertex_texture.bind()

        # texture coordinates
        if self.texture_coord_texture:
            glActiveTexture(GL_TEXTURE2)
            self.texture_coord_texture.bind()

        # normals
        if self.normal_texture:
            glActiveTexture(GL_TEXTURE3)
            self.normal_texture.bind()

        # render each set of indices
        glEnableVertexAttribArray(0)
        glEnableVertexAttribArray(1)
        glEnableVertexAttribArray(2)

        # iterate through the specified groups
        for group in groups:
            # get the group
            for mesh in self.meshes[group]:
                mesh_vbo, points, lines, triangles = mesh
                v_indices, t_indices, n_indices = mesh_vbo

                # vertex indices
                glBindBuffer(GL_ARRAY_BUFFER, v_indices)
                glVertexAttribIPointer(0, 1, GL_INT, GL_FALSE, 0, 0)

                # texture coordinate indices
                glBindBuffer(GL_ARRAY_BUFFER, t_indices)
                glVertexAttribIPointer(1, 1, GL_INT, GL_FALSE, 0, 0)

                # normal indices
                glBindBuffer(GL_ARRAY_BUFFER, n_indices)
                glVertexAttribIPointer(2, 1, GL_INT, GL_FALSE, 0, 0)

                # render the group
                if points[1] > 0:
                    start, count = 0, points[1]
                    glDrawArrays(GL_POINTS, start, count)
                if lines[1] > 0:
                    start, count = points[1], lines[1]
                    glDrawArrays(GL_LINES, start, count)
                if triangles[1] > 0:
                    start, count = points[1] + lines[1], triangles[1]
                    glDrawArrays(GL_TRIANGLES, start, count)

        # cleanup
        glDisableVertexAttribArray(0)
        glDisableVertexAttribArray(1)
        glDisableVertexAttribArray(2)

        # unbind our textures
        if self.normal_texture:
            self.normal_texture.unbind()
        if self.texture_coord_texture:
            glActiveTexture(GL_TEXTURE2)
            self.texture_coord_texture.unbind()
        glActiveTexture(GL_TEXTURE1)
        self.vertex_texture.unbind()
        glActiveTexture(GL_TEXTURE0)

        # unbind our buffers
        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
        glBindVertexArray(0)

        self.shader.unbind()