Exemple #1
0
class VolumeObject(object):

    def __init__(self, stack, spacing):
        self.active = True
        self.stack_object = StackObject(stack, spacing)
        shape = self.stack_object.shape

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

        tl = np.array((shape[2]*spacing[0],   # x
                       shape[1]*spacing[1],   # y
                       shape[0]*spacing[2]))  # z

        # Vertex buffer: corners of cube.
        # x, y, z, texture_x, texture_y, texture_z
        vb = [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  # Corner 0.
              [tl[0], 0.0, 0.0, 1.0, 0.0, 0.0],
              [0.0, tl[1], 0.0, 0.0, 1.0, 0.0],
              [tl[0], tl[1], 0.0, 1.0, 1.0, 0.0],
              [0.0, 0.0, tl[2], 0.0, 0.0, 1.0],
              [tl[0], 0.0, tl[2], 1.0, 0.0, 1.0],
              [0.0, tl[1], tl[2], 0.0, 1.0, 1.0],
              [tl[0], tl[1], tl[2], 1.0, 1.0, 1.0]]  # Corner 7.

        vb = np.array(vb, dtype=np.float32)
        vb = vb.flatten()

        # Triangles of cube.
        idx_out = np.array([[0, 2, 1], [2, 3, 1],  # Triangle 0, triangle 1.
                            [1, 4, 0], [1, 5, 4],
                            [3, 5, 1], [3, 7, 5],
                            [2, 7, 3], [2, 6, 7],
                            [0, 6, 2], [0, 4, 6],
                            [5, 6, 4], [5, 7, 6]],  # Triangle 10, triangle 11.
                           dtype=np.uint32)

        self.vtVBO = VBO(vb)
        self.vtVBO.bind()

        sc = 1.0/la.norm(tl)
        c = 0.5*tl

        self.transform = np.array(((sc, 0.0, 0.0, -sc*c[0]),
                                   (0.0, sc, 0.0, -sc*c[1]),
                                   (0.0, 0.0, sc, -sc*c[2]),
                                   (0.0, 0.0, 0.0, 1.0)))

        self.tex_transform = np.array(((1.0/tl[0], 0.0, 0.0, 0.0),
                                       (0.0, 1.0/tl[1], 0.0, 0.0),
                                       (0.0, 0.0, 1.0/tl[2], 0.0),
                                       (0.0, 0.0, 0.0, 1.0)))

        glBindVertexArray(0)

        self.elVBO = VBO(idx_out, target=GL_ELEMENT_ARRAY_BUFFER)
        self.elCount = len(idx_out.flatten())

    def update_stack(self, stack):
        self.stack_object.update_stack(stack)
Exemple #2
0
class model:
    ''' class for STL file / 3d model '''
    def __init__(self, stl_data, batchh=None):
        ''' initialise model data'''
        vert, norm = stl_data
        self.vertices = numpy.array(vert, dtype=GLfloat)
        self.normals = numpy.array(norm, dtype=GLfloat)
        self.vertex_buffer = VBO(self.vertices, 'GL_STATIC_DRAW')
        self.normal_buffer = VBO(self.normals, 'GL_STATIC_DRAW')

        # calculate model scale
        self.corner = self.vertices.transpose().min(1)
        self.corner2 = self.vertices.transpose().max(1)
        self.scale = abs(self.corner) + abs(self.corner2)
        self.scale = max(self.scale[0], self.scale[1], self.scale[2])
        print 'STL File loaded in: ', loadtime
        print 'Object information'
        print 'corner 1: ', self.corner
        print 'corner 2: ', self.corner2
        print 'object scale: ', self.scale

    def draw(self):
        ''' draw model on screen '''
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        glLoadIdentity()

        # center the model
        glTranslate(window.width / 2, window.height / 2, -150)

        # scale the model
        glScale(150 / self.scale, 150 / self.scale, 150 / self.scale)

        # draw grid and coordinate lines
        draw_grid()
        draw_xyz(0, 0, 0, -20, -20)

        # demo rotation
        glRotate(rot, 1, 0, 0)
        glRotate(rot2, 0, 1, 0)
        glRotate(rot3, 0, 0, 1)

        self.vertex_buffer.bind()
        glVertexPointer(3, GL_FLOAT, 0, None)
        self.normal_buffer.bind()
        glNormalPointer(GL_FLOAT, 0, None)

        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_NORMAL_ARRAY)

        glDrawArrays(GL_TRIANGLES, 0, len(self.vertices))

        glDisableClientState(GL_NORMAL_ARRAY)
        glDisableClientState(GL_VERTEX_ARRAY)

        self.normal_buffer.unbind()
        self.vertex_buffer.unbind()

        glPopMatrix()
Exemple #3
0
 def bind(self):
     """
     bind the vbo to the gl context.
     needs to be done before accessing the vbo.
     """
     GLVBO.bind(self)
     for att in self.attributes:
         gl.glEnableVertexAttribArray( att.location )
Exemple #4
0
class BackGroundImage:
    vs_source = 'gl/empty.vs.glsl'
    fs_source = 'gl/image.fs.glsl'

    def __init__(self, width, height):
        vertices = [-1, -1, 0, 1, -1, 0, 1, 1, 0, 1, 1, 0, -1, 1, 0, -1, -1, 0]

        self.num_vertices = len(vertices) // 3
        self.vbo = VBO(np.array(vertices, dtype=np.float32), GL_STATIC_DRAW,
                       GL_ARRAY_BUFFER)

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

        self.vbo.bind()
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * 4, self.vbo)
        glEnableVertexAttribArray(0)

        glBindVertexArray(0)

        self.shader = compile_shader(self.vs_source, self.fs_source)

        self.texture = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, self.texture)

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, width, height)

        # img = Image.open('board.jpg').transpose(Image.FLIP_TOP_BOTTOM)
        # glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
        #              img.size[0], img.size[1], 0,
        #              GL_RGB, GL_UNSIGNED_BYTE, img.tobytes())

    def set_image(self, image):
        glBindTexture(GL_TEXTURE_2D, self.texture)
        np.flipud(image)

        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image.shape[1], image.shape[0],
                        GL_BGR, GL_UNSIGNED_BYTE,
                        np.flipud(image).tobytes())

    def render(self):
        glDisable(GL_DEPTH_TEST)

        glUseProgram(self.shader)

        glUniform1i(0, 0)

        glActiveTexture(GL_TEXTURE0)
        glBindTexture(GL_TEXTURE_2D, self.texture)

        glBindVertexArray(self.vao)
        glDrawArrays(GL_TRIANGLES, 0, self.num_vertices)
class RenderBatch(object):
    def __init__(self, draw_type=GL_QUADS):
        self.count = 0
        self.color_data = []
        self.position_data = []
        self.color_buffer = VBO(np.array([]))
        self.position_buffer = VBO(np.array([]))

        self.draw_type = draw_type


    def draw2d(self, points, color=(0, 0, 0, 1), rotation=0, center=(0, 0)):
        n = len(points)
        self.count += n

        if not isinstance(color[0], (tuple, list)):
            color = [color]*n

        if rotation:
            transform = psi.calc.rotation_matrix(rotation)

            temp = np.array(points) - center
            temp = transform.dot(temp.T).T + center
            points = temp.tolist()

        self.color_data.extend(color)
        self.position_data.extend(points)

    def clear(self):
        self.position_data = []
        self.color_data = []
        self.count = 0

    def render(self):
        self.color_buffer.set_array(np.array(self.color_data, dtype='float32'))
        self.position_buffer.set_array(np.array(self.position_data, dtype='float32'))

        self.color_buffer.bind()
        glColorPointer(4, GL_FLOAT, 0, self.color_buffer)

        self.position_buffer.bind()
        glVertexPointer(2, GL_FLOAT, 0, self.position_buffer)

        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_COLOR_ARRAY)
        glDrawArrays(self.draw_type, 0, self.count)
        glDisableClientState(GL_COLOR_ARRAY)
        glDisableClientState(GL_VERTEX_ARRAY)
class RenderBatch(object):
    def __init__(self, draw_type=GL_QUADS):
        self.count = 0
        self.color_data = []
        self.position_data = []
        self.color_buffer = VBO(np.array([]))
        self.position_buffer = VBO(np.array([]))

        self.draw_type = draw_type

    def draw2d(self, points, color=(0, 0, 0, 1), rotation=0, center=(0, 0)):
        n = len(points)
        self.count += n

        if not isinstance(color[0], (tuple, list)):
            color = [color] * n

        if rotation:
            transform = psi.calc.rotation_matrix(rotation)

            temp = np.array(points) - center
            temp = transform.dot(temp.T).T + center
            points = temp.tolist()

        self.color_data.extend(color)
        self.position_data.extend(points)

    def clear(self):
        self.position_data = []
        self.color_data = []
        self.count = 0

    def render(self):
        self.color_buffer.set_array(np.array(self.color_data, dtype='float32'))
        self.position_buffer.set_array(
            np.array(self.position_data, dtype='float32'))

        self.color_buffer.bind()
        glColorPointer(4, GL_FLOAT, 0, self.color_buffer)

        self.position_buffer.bind()
        glVertexPointer(2, GL_FLOAT, 0, self.position_buffer)

        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_COLOR_ARRAY)
        glDrawArrays(self.draw_type, 0, self.count)
        glDisableClientState(GL_COLOR_ARRAY)
        glDisableClientState(GL_VERTEX_ARRAY)
Exemple #7
0
class OBJModel:
    vs_source = 'gl/mvp.vs.glsl'
    fs_source = 'gl/phong.fs.glsl'

    def __init__(self, obj_file):
        obj = pywavefront.Wavefront(obj_file, strict=True, collect_faces=True)
        assert len(obj.mesh_list) == 1 and len(obj.mesh_list[0].materials) == 1
        material = obj.mesh_list[0].materials[0]
        #
        self.num_vertices = len(material.vertices) // material.vertex_size
        self.vbo = VBO(np.array(material.vertices, dtype=np.float32),
                       GL_STATIC_DRAW, GL_ARRAY_BUFFER)

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

        self.vbo.bind()
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * 4, self.vbo)
        glEnableVertexAttribArray(0)
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * 4,
                              self.vbo + 3 * 4)
        glEnableVertexAttribArray(1)

        glBindVertexArray(0)

        self.shader = compile_shader(self.vs_source, self.fs_source)

    def render(self, model, view, perjection, light_position, color):
        glEnable(GL_DEPTH_TEST)

        glUseProgram(self.shader)

        glUniformMatrix4fv(0, 1, True, model)
        glUniformMatrix4fv(1, 1, True, view)
        glUniformMatrix4fv(2, 1, True, perjection)
        glUniform3fv(3, 1, light_position)
        glUniform3fv(4, 1, color)

        glBindVertexArray(self.vao)
        glDrawArrays(GL_TRIANGLES, 0, self.num_vertices)
class RenderBatchOpt(object):
    def __init__(self, draw_type=GL_QUADS):
        self.count = 0
        self.color_buffer = VBO(np.array([]))
        self.vertex_buffer = VBO(np.array([]))
        self.draw_type = draw_type


    def draw2d(self, points, color=(0, 0, 0, 1), rotation=0, center=(0, 0)):
        n = points.shape[0]
        self.count += n

        if rotation:
            transform = psi.calc.rotation_matrix(rotation)

            temp = points - center
            temp = transform.dot(temp.T).T + center
            points = temp.tolist()

        self.color_buffer.set_array(color)
        self.vertex_buffer.set_array(points)

    def clear(self):
        self.color_buffer.set_array(np.array([]))
        self.vertex_buffer.set_array(np.array([]))
        self.count = 0

    def render(self):
        self.color_buffer.bind()
        glColorPointer(4, GL_FLOAT, 0, self.color_buffer)

        self.vertex_buffer.bind()
        glVertexPointer(2, GL_FLOAT, 0, self.vertex_buffer)

        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_COLOR_ARRAY)
        glDrawArrays(self.draw_type, 0, self.count)
        glDisableClientState(GL_COLOR_ARRAY)
        glDisableClientState(GL_VERTEX_ARRAY)
Exemple #9
0
class RenderObject:
    def __init__(self, program, obj):
        self.mtl_list = obj.mtl_list
        self.vao = glGenVertexArrays(1)

        glBindVertexArray(self.vao)

        vertices = (GLfloat * len(obj.vertices))(*obj.vertices);
        self.vbo = VBO(vertices, GL_STATIC_DRAW, GL_ARRAY_BUFFER)
        self.vbo.bind()

        vertex_attrib = program.attribs["vertex"]
        glEnableVertexAttribArray(vertex_attrib)
        glVertexAttribPointer(vertex_attrib, 3, GL_FLOAT, GL_FALSE, 8 * 4, c_void_p(0))

        vertex_tex_attrib = program.attribs["vertex_tex"]
        glEnableVertexAttribArray(vertex_tex_attrib)
        glVertexAttribPointer(vertex_tex_attrib, 2, GL_FLOAT, GL_FALSE, 8 * 4, c_void_p(3 * 4))

        vertex_normal_attrib = program.attribs["vertex_normal"]
        glEnableVertexAttribArray(vertex_normal_attrib)
        glVertexAttribPointer(vertex_normal_attrib, 2, GL_FLOAT, GL_FALSE, 8 * 4, c_void_p(5 * 4))
Exemple #10
0
class RenderBatchOpt(object):
    def __init__(self, draw_type=GL_QUADS):
        self.count = 0
        self.color_buffer = VBO(np.array([]))
        self.vertex_buffer = VBO(np.array([]))
        self.draw_type = draw_type

    def draw2d(self, points, color=(0, 0, 0, 1), rotation=0, center=(0, 0)):
        n = points.shape[0]
        self.count += n

        if rotation:
            transform = psi.calc.rotation_matrix(rotation)

            temp = points - center
            temp = transform.dot(temp.T).T + center
            points = temp.tolist()

        self.color_buffer.set_array(color)
        self.vertex_buffer.set_array(points)

    def clear(self):
        self.color_buffer.set_array(np.array([]))
        self.vertex_buffer.set_array(np.array([]))
        self.count = 0

    def render(self):
        self.color_buffer.bind()
        glColorPointer(4, GL_FLOAT, 0, self.color_buffer)

        self.vertex_buffer.bind()
        glVertexPointer(2, GL_FLOAT, 0, self.vertex_buffer)

        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_COLOR_ARRAY)
        glDrawArrays(self.draw_type, 0, self.count)
        glDisableClientState(GL_COLOR_ARRAY)
        glDisableClientState(GL_VERTEX_ARRAY)
Exemple #11
0
class MeshObject(object):
    def __init__(self, fn, spacing):
        self.active = True
        m = GLMesh()
        self.mesh = m
        sc = m.load_ply(fn)
        v_out, n_out, col_out, idx_out = m.generate_arrays()

        vb = np.concatenate((v_out, n_out, col_out), axis=1)
        self.elVBO = VBO(idx_out, target=GL_ELEMENT_ARRAY_BUFFER)
        self.elCount = len(idx_out.flatten())

        self.vao = glGenVertexArrays(1)
        glBindVertexArray(self.vao)
        self.vtVBO = VBO(vb)
        self.vtVBO.bind()

        glBindVertexArray(0)

        c = np.array((0, 0, 0))
        self.transform = np.array(((sc, 0.0, 0.0, -sc*c[0]),
                                   (0.0, sc, 0.0, -sc*c[1]),
                                   (0.0, 0.0, sc, -sc*c[2]),
                                   (0.0, 0.0, 0.0, 1.0)))
Exemple #12
0
class GcodeModel(Model):
    """
    Model for displaying Gcode data.
    """
    # vertices for arrow to display the direction of movement
    arrow = numpy.require([
        [0.0, 0.0, 0.0],
        [0.4, -0.1, 0.0],
        [0.4, 0.1, 0.0],
    ], 'f')
    layer_entry_marker = numpy.require([
        [0.23, -0.14, 0.0],
        [0.0, 0.26, 0.0],
        [-0.23, -0.14, 0.0],
    ], 'f')
    layer_exit_marker = numpy.require([
        [-0.23, -0.23, 0.0],
        [0.23, -0.23, 0.0],
        [0.23, 0.23, 0.0],
        [0.23, 0.23, 0.0],
        [-0.23, 0.23, 0.0],
        [-0.23, -0.23, 0.0],
    ], 'f')

    def load_data(self, model_data, callback=None):
        t_start = time.time()

        vertex_list = []
        color_list = []
        self.layer_stops = [0]
        self.layer_heights = []
        arrow_list = []
        layer_markers_list = []
        self.layer_marker_stops = [0]

        num_layers = len(model_data)
        callback_every = max(1, int(math.floor(num_layers / 100)))

        # the first movement designates the starting point
        start = prev = model_data[0][0]
        del model_data[0][0]

        for layer_idx, layer in enumerate(model_data):
            first = layer[0]
            for movement in layer:
                vertex_list.append(prev.v)
                vertex_list.append(movement.v)

                arrow = self.arrow
                # position the arrow with respect to movement
                arrow = vector.rotate(arrow, movement.angle(prev.v), 0.0, 0.0,
                                      1.0)
                arrow_list.extend(arrow)

                vertex_color = self.movement_color(movement)
                color_list.append(vertex_color)

                prev = movement

            self.layer_stops.append(len(vertex_list))
            self.layer_heights.append(first.v[2])

            # add the layer entry marker
            if layer_idx > 0 and len(model_data[layer_idx - 1]) > 0:
                layer_markers_list.extend(self.layer_entry_marker +
                                          model_data[layer_idx - 1][-1].v)
            elif layer_idx == 0 and len(layer) > 0:
                layer_markers_list.extend(self.layer_entry_marker + layer[0].v)

            # add the layer exit marker
            if len(layer) > 1:
                layer_markers_list.extend(self.layer_exit_marker + layer[-1].v)

            self.layer_marker_stops.append(len(layer_markers_list))

            if callback and layer_idx % callback_every == 0:
                callback(layer_idx + 1, num_layers)

        self.vertices = numpy.array(vertex_list, 'f')
        self.colors = numpy.array(color_list, 'f')
        self.arrows = numpy.array(arrow_list, 'f')
        self.layer_markers = numpy.array(layer_markers_list, 'f')

        # by translating the arrow vertices outside of the loop, we achieve a
        # significant performance gain thanks to numpy. it would be really nice
        # if we could rotate in a similar fashion...
        self.arrows = self.arrows + self.vertices[1::2].repeat(3, 0)

        # for every pair of vertices of the model, there are 3 vertices for the arrow
        assert len(self.arrows) == ((len(self.vertices) // 2) * 3), \
            'The 2:3 ratio of model vertices to arrow vertices does not hold.'

        self.max_layers = len(self.layer_stops) - 1
        self.num_layers_to_draw = self.max_layers
        self.arrows_enabled = True
        self.initialized = False
        self.vertex_count = len(self.vertices)

        t_end = time.time()

        logging.info('Initialized Gcode model in %.2f seconds' %
                     (t_end - t_start))
        logging.info('Vertex count: %d' % self.vertex_count)

    def movement_color(self, move):
        """
        Return the color to use for particular type of movement.
        """
        # default movement color is gray
        color = (0.6, 0.6, 0.6, 0.6)

        extruder_on = (move.flags & Movement.FLAG_EXTRUDER_ON
                       or move.delta_e > 0)
        outer_perimeter = (move.flags & Movement.FLAG_PERIMETER
                           and move.flags & Movement.FLAG_PERIMETER_OUTER)

        if extruder_on and outer_perimeter:
            color = (0.0, 0.875, 0.875, 0.6)  # cyan
        elif extruder_on and move.flags & Movement.FLAG_PERIMETER:
            color = (0.0, 1.0, 0.0, 0.6)  # green
        elif extruder_on and move.flags & Movement.FLAG_LOOP:
            color = (1.0, 0.875, 0.0, 0.6)  # yellow
        elif extruder_on:
            color = (1.0, 0.0, 0.0, 0.6)  # red

        return color

    # ------------------------------------------------------------------------
    # DRAWING
    # ------------------------------------------------------------------------

    def init(self):
        self.vertex_buffer = VBO(self.vertices, 'GL_STATIC_DRAW')
        self.vertex_color_buffer = VBO(self.colors.repeat(
            2, 0), 'GL_STATIC_DRAW')  # each pair of vertices shares the color

        if self.arrows_enabled:
            self.arrow_buffer = VBO(self.arrows, 'GL_STATIC_DRAW')
            self.arrow_color_buffer = VBO(
                self.colors.repeat(3, 0),
                'GL_STATIC_DRAW')  # each triplet of vertices shares the color

        self.layer_marker_buffer = VBO(self.layer_markers, 'GL_STATIC_DRAW')

        self.initialized = True

    def display(self,
                elevation=0,
                eye_height=0,
                mode_ortho=False,
                mode_2d=False):
        glPushMatrix()

        offset_z = self.offset_z if not mode_2d else 0
        glTranslate(self.offset_x, self.offset_y, offset_z)

        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_COLOR_ARRAY)

        self._display_movements(elevation, eye_height, mode_ortho, mode_2d)

        if self.arrows_enabled:
            self._display_arrows()

        glDisableClientState(GL_COLOR_ARRAY)

        if self.arrows_enabled:
            self._display_layer_markers()

        glDisableClientState(GL_VERTEX_ARRAY)
        glPopMatrix()

    def _display_movements(self,
                           elevation=0,
                           eye_height=0,
                           mode_ortho=False,
                           mode_2d=False):
        self.vertex_buffer.bind()
        glVertexPointer(3, GL_FLOAT, 0, None)

        self.vertex_color_buffer.bind()
        glColorPointer(4, GL_FLOAT, 0, None)

        if mode_2d:
            glScale(1.0, 1.0, 0.0)  # discard z coordinates
            start = self.layer_stops[self.num_layers_to_draw - 1]
            end = self.layer_stops[self.num_layers_to_draw]

            glDrawArrays(GL_LINES, start, end - start)

        elif mode_ortho:
            if elevation >= 0:
                # draw layers in normal order, bottom to top
                start = 0
                end = self.layer_stops[self.num_layers_to_draw]

                glDrawArrays(GL_LINES, start, end - start)

            else:
                # draw layers in reverse order, top to bottom
                stop_idx = self.num_layers_to_draw - 1
                while stop_idx >= 0:
                    start = self.layer_stops[stop_idx]
                    end = self.layer_stops[stop_idx + 1]

                    glDrawArrays(GL_LINES, start, end - start)

                    stop_idx -= 1

        else:  # 3d projection mode
            reverse_threshold_layer = self._layer_up_to_height(eye_height -
                                                               self.offset_z)

            if reverse_threshold_layer >= 0:
                # draw layers up to (and including) the threshold in normal order, bottom to top
                normal_layers_to_draw = min(self.num_layers_to_draw,
                                            reverse_threshold_layer + 1)
                start = 0
                end = self.layer_stops[normal_layers_to_draw]

                glDrawArrays(GL_LINES, start, end - start)

            if reverse_threshold_layer + 1 < self.num_layers_to_draw:
                # draw layers from the threshold in reverse order, top to bottom
                stop_idx = self.num_layers_to_draw - 1
                while stop_idx > reverse_threshold_layer:
                    start = self.layer_stops[stop_idx]
                    end = self.layer_stops[stop_idx + 1]

                    glDrawArrays(GL_LINES, start, end - start)

                    stop_idx -= 1

        self.vertex_buffer.unbind()
        self.vertex_color_buffer.unbind()

    def _layer_up_to_height(self, height):
        """Return the index of the last layer lower than height."""
        for idx in range(len(self.layer_heights) - 1, -1, -1):
            if self.layer_heights[idx] < height:
                return idx

        return 0

    def _display_arrows(self):
        self.arrow_buffer.bind()
        glVertexPointer(3, GL_FLOAT, 0, None)

        self.arrow_color_buffer.bind()
        glColorPointer(4, GL_FLOAT, 0, None)

        start = (self.layer_stops[self.num_layers_to_draw - 1] // 2) * 3
        end = (self.layer_stops[self.num_layers_to_draw] // 2) * 3

        glDrawArrays(GL_TRIANGLES, start, end - start)

        self.arrow_buffer.unbind()
        self.arrow_color_buffer.unbind()

    def _display_layer_markers(self):
        self.layer_marker_buffer.bind()
        glVertexPointer(3, GL_FLOAT, 0, None)

        start = self.layer_marker_stops[self.num_layers_to_draw - 1]
        end = self.layer_marker_stops[self.num_layers_to_draw]

        glColor4f(0.6, 0.6, 0.6, 0.6)
        glDrawArrays(GL_TRIANGLES, start, end - start)

        self.layer_marker_buffer.unbind()
Exemple #13
0
class TextBatch:
    __tag = namedtuple("tag", ['mat', 'inf'])

    def __init__(self, tr):
        self.__text_render = tr

        self.__elem_count = 0
        self.__color = [1.0, 1.0, 1.0, 1.0]

    def initializeGL(self):
        self.vbo = VBO(numpy.ndarray(0, dtype=self.__text_render.buffer_dtype),
                       GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER)
        self.vao = VAO()

        with self.vao, self.vbo:
            self.__text_render.b1.assign()
            self.__text_render.b2.assign()

    def restart(self):
        self.__strs = []

    # TEMP
    def get_string(self, text):
        """

        :param text:
        :return:
        :returns: _StringMetrics
        """
        return self.__text_render.getStringMetrics(text)

    def add(self, mat, str_info):
        """
        Queues a text string to be rendered in the batch
        :param mat: location matrix
        :param str_info:
        :type str_info: _StringMetrics
        :return:
        """
        self.__strs.append(TextBatch.__tag(mat, str_info))

    def prepare(self):
        self.__text_render.updateTexture()

        clist = []

        for mat, str_info in self.__strs:
            for (x, y), (u, v) in str_info.arr:
                newpt = projectPoint(mat, Point2(x, y))
                clist.append(((newpt.x, newpt.y), (u, v)))

        arr = numpy.array(clist, dtype=self.__text_render.buffer_dtype)

        self.vbo.data = arr
        self.vbo.size = None
        self.vbo.copied = False
        self.vbo.bind()

        self.__elem_count = len(arr)

    def render(self, mat):
        with self.__text_render.sdf_shader, self.__text_render.tex.on(
                GL.GL_TEXTURE_2D), self.vao:
            GL.glUniform1i(self.__text_render.sdf_shader.uniforms.tex1, 0)
            GL.glUniformMatrix3fv(self.__text_render.sdf_shader.uniforms.mat,
                                  1, True, mat.astype(numpy.float32))
            GL.glUniform4f(self.__text_render.sdf_shader.uniforms.color,
                           *self.__color)

            GL.glDrawArrays(GL.GL_TRIANGLES, 0, self.__elem_count)

        print("Drawing %d elements" % self.__elem_count)
Exemple #14
0
class TextBatch:
    __tag = namedtuple("__tag", ['mat', 'inf'])

    def __init__(self, tr: 'TextRender') -> None:
        self.__text_render = tr

        self.__elem_count = 0
        self.__color = (255, COL_TEXT, 0, 0)

    def initializeGL(self) -> None:
        self.vbo = VBO(
            numpy.ndarray([], dtype=self.__text_render.buffer_dtype),
            GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER)
        self.vao = VAO()

        self._va = VA_tex(1024)

        with self.vao, self.vbo:
            self.__text_render.b1.assign()
            self.__text_render.b2.assign()

    def restart(self) -> None:
        self.__strs: List[TextBatch.__tag] = []

    # TEMP
    def get_string(self, text: str) -> '_StringMetrics':
        """

        :param text:
        :return:
        :returns: _StringMetrics
        """
        return self.__text_render.getStringMetrics(text)

    def add(self, mat: 'npt.NDArray[numpy.float64]',
            str_info: '_StringMetrics') -> None:
        """
        Queues a text string to be rendered in the batch
        :param mat: location matrix
        :param str_info:
        :type str_info: _StringMetrics
        :return:
        """
        self.__strs.append(TextBatch.__tag(mat, str_info))

    def prepare(self) -> None:
        self.__text_render.updateTexture()

        self._va.clear()

        for mat, str_info in self.__strs:
            self._va.extend_project(mat, str_info.arr)

        self.vbo.set_array(self._va.buffer()[:])
        self.vbo.bind()

        self.__elem_count = self._va.count()

    def render(self, mat: 'npt.NDArray[numpy.float64]') -> None:
        with self.__text_render.sdf_shader.program, self.__text_render.tex.on(
                GL.GL_TEXTURE_2D), self.vao:
            GL.glUniform1i(self.__text_render.sdf_shader.uniforms.tex1, 0)
            GL.glUniformMatrix3fv(self.__text_render.sdf_shader.uniforms.mat,
                                  1, True, mat.astype(numpy.float32))
            GL.glUniform4ui(self.__text_render.sdf_shader.uniforms.layer_info,
                            *self.__color)

            GL.glDrawArrays(GL.GL_TRIANGLES, 0, self.__elem_count)
Exemple #15
0
    class _RenderData:
        def __init__(self, dtype, shader, glhint):
            self.__dtype = dtype

            self.vao = VAO()
            self.batch_vbo = VBO(numpy.array([], dtype=dtype), glhint)

            with self.vao, self.batch_vbo:
                vbobind(shader, dtype, "vertex").assign()

            self.clear()

        def clear(self):
            self.__vbo_update = True
            self.__groups = defaultdict(list)
            self.__group_lookup = {}
            self.group_offsets = {}

        def build_vbo(self):
            if not self.__vbo_update:
                return

            self.__vbo_update = False

            self.group_offsets = {}

            built_list = []
            for group, points in self.__groups.items():
                self.group_offsets[group] = len(built_list)
                built_list.extend([(i, ) for i in points])

            if not built_list:
                return

            ar = numpy.array(built_list, dtype=self.__dtype)

            self.batch_vbo.data = ar
            self.batch_vbo.size = None
            self.batch_vbo.copied = False
            self.batch_vbo.bind()

        def last_index(self, group):
            return len(self.__groups[group])

        def add_point(self, p1, p2, group):
            group = self.__groups[group]
            idx = len(group) // 2
            group.append(p1)
            group.append(p2)
            self.__vbo_update = True
            return idx

        def get_point_index(self, p1, p2, group):
            key = group, p1.intTuple(), p2.intTuple()
            try:
                return self.__group_lookup[key]
            except KeyError:
                pass

            idx = self.__group_lookup[key] = self.add_point(p1, p2, group)
            return idx
def image_server(evtQueue, resultQueue):

    # resource-taking objects
    resObjs = []

    # initialize glfw
    glfw.init()

    # set glfw config
    glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3)
    glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
    glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
    glfw.window_hint(glfw.RESIZABLE, GL_FALSE)

    if pyPlatform.system().lower() == 'darwin':
        glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, GL_TRUE)

    # create window
    theWindow = glfw.create_window(windowSize[0], windowSize[1], 'Spherical Projection', None, None)
    # make window the current context
    glfw.make_context_current(theWindow)


    # enable z-buffer
    glEnable(GL_DEPTH_TEST)

    # set resizing callback function
    # glfw.set_framebuffer_size_callback(theWindow, window_resize_callback)

    #glfw.set_key_callback(theWindow, window_keypress_callback)
    # disable cursor
    #glfw.set_input_mode(theWindow, glfw.CURSOR, glfw.CURSOR_DISABLED)

    #glfw.set_cursor_pos_callback(theWindow, window_cursor_callback)
    # initialize cursor position
    cursorPos = glfw.get_cursor_pos(theWindow)

    # glfw.set_scroll_callback(theWindow, window_scroll_callback)

    vbo = VBO(vertices, 'GL_STATIC_DRAW')
    vbo.create_buffers()
    resObjs.append(vbo)

    vao = glGenVertexArrays(1)
    glBindVertexArray(vao)
    vbo.bind()
    vbo.copy_data()
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(0))
    glEnableVertexAttribArray(0)
    glBindVertexArray(0)

    # compile program
    renderProgram = GLProgram(rayTracingVertexShaderSource, rayTracingFragmentShaderSource)
    renderProgram.compile_and_link()
    uniformInfos = [
        ('backColor', 'vec3f'),
        ('ambientColor', 'vec3f'),
        ('o_c', 'vec3f'),
        ('o_p', 'vec3f'),
        ('x_c', 'vec3f'),
        ('y_c', 'vec3f'),
        ('x_p', 'vec3f'),
        ('y_p', 'vec3f'),
        ('c_c', 'vec3f'),
        ('c_p', 'vec3f'),
        ('winSize', 'vec2f')
    ]
    uniforms = create_uniform(renderProgram.get_program_id(), uniformInfos)


    # keep rendering until the window should be closed
    while not glfw.window_should_close(theWindow):

        # set background color
        glClearColor(*windowBackgroundColor)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        renderProgram.use()

        # update uniforms
        o_c, c_c, x_c, y_c = get_camera_vectors(camera)
        o_p, c_p, x_p, y_p = get_camera_vectors(projector)
        uniforms['o_c'].update(o_c)
        uniforms['x_c'].update(x_c)
        uniforms['y_c'].update(y_c)
        uniforms['c_c'].update(c_c)

        uniforms['o_p'].update(o_p)
        uniforms['x_p'].update(x_p)
        uniforms['y_p'].update(y_p)
        uniforms['c_p'].update(c_p)
        uniforms['backColor'].update(backColor)
        uniforms['ambientColor'].update(ambientColor)
        uniforms['winSize'].update(windowSize.astype(np.float32))

        try:
            newImage = evtQueue.get(timeout=0.05)
        except Exception as e:
            # tell glfw to poll and process window events
            glfw.poll_events()
            # swap frame buffer
            glfw.swap_buffers(theWindow)
            continue

        texture = create_texture(newImage)

        glBindVertexArray(vao)
        glActiveTexture(GL_TEXTURE0)
        texture.bind()
        glDrawArrays(GL_TRIANGLES, 0, 6)
        texture.unbind()
        glBindVertexArray(0)

        texture.delete()

        # respond key press
        keyboard_respond_func()
        # tell glfw to poll and process window events
        glfw.poll_events()
        # swap frame buffer
        glfw.swap_buffers(theWindow)

        result = get_screenshot(windowSize)
        resultQueue.put(result)

    for obj in resObjs:
        obj.delete()

    # terminate glfw
    glfw.terminate()
Exemple #17
0
class CompositeManager:
    def __init__(self) -> None:
        self.__width = 0
        self.__height = 0

        self.__layer_fbs: 'List[RenderLayer]' = []

        self.__active_count = 0
        self.__keys: 'Dict[Any, RenderLayer]' = {}

    def get(self, key: Any) -> 'RenderLayer':
        # If we've already got a composite target for this key
        # return it
        if key in self.__keys:
            return self.__keys[key]

        # Allocate a new layer if required
        if self.__active_count == len(self.__layer_fbs):
            self.__layer_fbs.append(RenderLayer(self.__width, self.__height))

        # Save new layer fb for reuse
        self.__keys[key] = self.__layer_fbs[self.__active_count]
        self.__active_count += 1
        return self.__keys[key]

    def resize(self, width: int, height: int) -> None:
        if width == self.__width and height == self.__height:
            return

        self.__width = width
        self.__height = height

        for i in self.__layer_fbs:
            i.resize(width, height)

        self.__composite_vbo.set_array(self.__get_vbo_data())
        with self.__composite_vbo:
            self.__composite_vbo.copy_data()

    def restart(self) -> None:
        """
        Call at the start of rendering. Resets all layers to initial state
        :return:
        """

        self.__keys = {}

        self.__active_count = 0

        for n, _ in enumerate(self.__layer_fbs):
            self.reset_layer(n)

    def reset_layer(self, n: int) -> None:
        """
        Reset a particular layer to an empty state. This implies alpha of 0 (transparent) and type of 0 (undrawn)
        :param n:
        :return:
        """
        with self.__layer_fbs[n]:
            GL.glClearBufferfv(GL.GL_COLOR, 0, (0, 255, 0, 0))

    def __get_vbo_data(self) -> 'npt.NDArray[numpy.float64]':
        if self.__width == 0 or self.__height == 0:
            assert False

        # Fullscreen textured quad
        filled_points = [
            ((-1.0, -1.0), (0.0, 0.0)),
            ((1.0, -1.0), (1.0, 0.0)),
            ((-1.0, 1.0), (0.0, 1.0)),
            ((1.0, 1.0), (1.0, 1.0)),
        ]

        ar = numpy.array(filled_points,
                         dtype=[("vertex", numpy.float32, 2),
                                ("texpos", numpy.float32, 2)])

        sscale = max(self.__width, self.__height)
        xscale = self.__width / sscale
        yscale = self.__height / sscale

        ar["vertex"][:, 0] *= xscale
        ar["vertex"][:, 1] *= yscale

        return ar

    def initializeGL(self, gls: 'GLShared', width: int, height: int) -> None:
        self.__width = width
        self.__height = height

        # Initialize (but don't fill) the Color LUT
        self.__texture_colors = Texture(debug_name="Layer Color LUT")
        with self.__texture_colors.on(GL.GL_TEXTURE_1D):
            GL.glTexParameteri(GL.GL_TEXTURE_1D, GL.GL_TEXTURE_MIN_FILTER,
                               GL.GL_NEAREST)
            GL.glTexParameteri(GL.GL_TEXTURE_1D, GL.GL_TEXTURE_MAG_FILTER,
                               GL.GL_NEAREST)
            GL.glTexParameteri(GL.GL_TEXTURE_1D, GL.GL_TEXTURE_WRAP_S,
                               GL.GL_CLAMP_TO_EDGE)
            GL.glTexParameteri(GL.GL_TEXTURE_1D, GL.GL_TEXTURE_WRAP_T,
                               GL.GL_CLAMP_TO_EDGE)

        # Compositing shader and geometry
        self.__composite_shader = gls.shader_cache.get(
            "layer_composite_vert",
            "layer_composite_frag",
            fragment_bindings={"final_color": 0})

        ar = self.__get_vbo_data()
        self.__composite_vao = VAO(debug_name="Compositor Quad VAO")
        self.__composite_vbo = VBO(ar, GL.GL_STATIC_DRAW)
        GL.glObjectLabel(GL.GL_BUFFER, int(self.__composite_vbo), -1,
                         "Compositor Quad VBO")

        with self.__composite_vao:
            self.__composite_vbo.bind()
            VBOBind(self.__composite_shader.program, ar.dtype,
                    "vertex").assign()
            VBOBind(self.__composite_shader.program, ar.dtype,
                    "texpos").assign()

    def set_color_table(self,
                        colors: 'Sequence[Tuple[int, int, int, int]]') -> None:
        array: 'npt.NDArray[numpy.uint8]' = numpy.ndarray((256, 4),
                                                          dtype=numpy.uint8)

        # Create a stub array with the color table data
        array.fill(0)
        array[:] = (255, 0, 255, 255)
        array[:len(colors)] = colors

        with self.__texture_colors.on(GL.GL_TEXTURE_1D):
            GL.glTexImage1D(GL.GL_TEXTURE_1D, 0, GL.GL_RGBA, 256, 0,
                            GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, array)

    class _PREBIND:
        def __init__(self, layer_list: 'Dict[Any, RenderLayer]',
                     composite_shader: 'EnhShaderProgram'):
            self.layer_list = layer_list
            self.composite_shader = composite_shader

        def composite(self, n: Any,
                      layer_primary_color: 'Tuple[int,int,int]') -> None:
            alpha = 0.5 * 255
            try:
                layer = self.layer_list[n]
            except KeyError:
                return

            GL.glActiveTexture(GL.GL_TEXTURE0)
            GL.glBindTexture(GL.GL_TEXTURE_2D, layer.info_texture.v)

            GL.glUniform4f(self.composite_shader.uniforms.layer_color,
                           layer_primary_color[0], layer_primary_color[1],
                           layer_primary_color[2], alpha)

            GL.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4)

    @contextlib.contextmanager
    def composite_prebind(self) -> Generator['_PREBIND', None, None]:
        GL.glActiveTexture(GL.GL_TEXTURE1)
        GL.glBindTexture(GL.GL_TEXTURE_1D, self.__texture_colors.v)

        GL.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA)

        # Composite the layer to the screen
        with self.__composite_shader.program, self.__composite_vao:
            GL.glUniform1i(self.__composite_shader.uniforms.layer_info, 0)
            GL.glUniform1i(self.__composite_shader.uniforms.color_tab, 1)

            yield self._PREBIND(self.__keys, self.__composite_shader)
Exemple #18
0
class THRenderer:
    def __init__(self, parent_view: 'BoardViewWidget') -> None:
        self.parent = parent_view

    def initializeGL(self, glshared: 'GLShared') -> None:

        self._filled_shader = glshared.shader_cache.get(
            "via_filled_vertex_shader", "via_filled_fragment_shader")

        self._outline_shader = glshared.shader_cache.get(
            "via_outline_vertex_shader", "basic_fill_frag")

        # Build geometry for filled rendering using the frag shader for circle borders
        filled_points = [
            ((-1, -1), ),
            ((1, -1), ),
            ((-1, 1), ),
            ((1, 1), ),
        ]
        ar = numpy.array(filled_points, dtype=[("vertex", numpy.float32, 2)])

        self._sq_vbo = VBO(ar, GL.GL_STATIC_DRAW)
        GL.glObjectLabel(GL.GL_BUFFER, int(self._sq_vbo), -1, "Via SQ VBO")

        # Build geometry for outline rendering
        outline_points = []
        for i in numpy.linspace(0, math.pi * 2, N_OUTLINE_SEGMENTS, False):
            outline_points.append(((math.cos(i), math.sin(i)), ))

        outline_points_array = numpy.array(outline_points,
                                           dtype=[("vertex", numpy.float32, 2)
                                                  ])

        self._outline_vbo = VBO(outline_points_array, GL.GL_STATIC_DRAW)
        GL.glObjectLabel(GL.GL_BUFFER, int(self._sq_vbo), -1,
                         "Via Outline VBO")

        self.__dtype = numpy.dtype([
            ("pos", numpy.float32, 2),
            ("r", numpy.float32),
            ("r_inside_frac_sq", numpy.float32),
        ])

        self.__filled_vao = VAO()
        self.__outline_vao = VAO()

        with self.__filled_vao, self._sq_vbo:
            VBOBind(self._filled_shader.program, self._sq_vbo.data.dtype,
                    "vertex").assign()

        # Use a fake array to get a zero-length VBO for initial binding
        filled_instance_array = numpy.ndarray(0, dtype=self.__dtype)
        self.filled_instance_vbo = VBO(filled_instance_array)
        GL.glObjectLabel(GL.GL_BUFFER, int(self._sq_vbo), -1,
                         "Via Filled Instance VBO")

        with self.__filled_vao, self.filled_instance_vbo:
            VBOBind(self._filled_shader.program, self.__dtype, "pos",
                    div=1).assign()
            VBOBind(self._filled_shader.program, self.__dtype, "r",
                    div=1).assign()
            VBOBind(self._filled_shader.program,
                    self.__dtype,
                    "r_inside_frac_sq",
                    div=1).assign()

        with self.__outline_vao, self._outline_vbo:
            VBOBind(self._outline_shader.program, self._outline_vbo.data.dtype,
                    "vertex").assign()

        # Build instance for outline rendering
        # We don't have an inner 'r' for this because we just do two instances per vertex

        # Use a fake array to get a zero-length VBO for initial binding
        outline_instance_array = numpy.ndarray(0, dtype=self.__dtype)
        self.outline_instance_vbo = VBO(outline_instance_array)
        GL.glObjectLabel(GL.GL_BUFFER, int(self.outline_instance_vbo), -1,
                         "Via Outline Instance VBO")

        with self.__outline_vao, self.outline_instance_vbo:
            VBOBind(self._outline_shader.program, self.__dtype, "pos",
                    div=1).assign()
            VBOBind(self._outline_shader.program, self.__dtype, "r",
                    div=1).assign()

    def render_filled(self,
                      mat: 'npt.NDArray[numpy.float64]',
                      va: 'VA_xy',
                      color: Tuple[float, float, float] = COL_VIA) -> None:
        self.filled_instance_vbo.set_array(va.buffer()[:])

        try:
            with self._filled_shader.program:
                with self.__filled_vao:
                    with self.filled_instance_vbo:
                        with self._sq_vbo:
                            GL.glUniformMatrix3fv(
                                self._filled_shader.uniforms.mat, 1, True,
                                mat.astype(numpy.float32))
                            GL.glUniform1ui(self._filled_shader.uniforms.color,
                                            color)
                            GL.glDrawArraysInstancedBaseInstance(
                                GL.GL_TRIANGLE_STRIP, 0, 4, va.count(), 0)
        except OpenGL.error.GLError as e:
            print("Threw OGL error:", e)

    def render_outlines(self, mat: 'npt.NDArray[numpy.float64]',
                        va: 'VA_xy') -> None:
        if not va.count():
            return

        self.outline_instance_vbo.set_array(va.buffer()[:])
        self.outline_instance_vbo.bind()

        with self._outline_shader.program, self.__outline_vao, self.outline_instance_vbo, self._sq_vbo:
            GL.glUniformMatrix3fv(self._outline_shader.uniforms.mat, 1, True,
                                  mat.astype(numpy.float32))
            GL.glUniform4ui(self._outline_shader.uniforms.layer_info, 255,
                            COL_SEL, 0, 0)
            GL.glDrawArraysInstanced(GL.GL_LINE_LOOP, 0, N_OUTLINE_SEGMENTS,
                                     va.count())
Exemple #19
0
 glEnable(GL_DEPTH_TEST)
 glEnable(GL_CULL_FACE)
 glClearColor(1, 1, 1, 0)
 glPointSize(5)
 # Set up the shader.
 prog = shaderutil.createProgram("./shader.vs", "./shader.fs")
 mvploc = glGetUniformLocation(prog, "mvp")
 positionloc = glGetAttribLocation(prog, "vs_position")
 colorloc = glGetAttribLocation(prog, "vs_color")    
 
 # Setup VAO
 vertobj = glGenVertexArrays(1)
 glBindVertexArray(vertobj)
 # Setup the VBO (using the fancy VBO Object from pyopengl, doing it "manually" would also be a possibility)
 vertbuf = VBO(cubedata, GL_STATIC_DRAW)
 vertbuf.bind()
 glEnableVertexAttribArray(positionloc)
 glEnableVertexAttribArray(colorloc)
 glVertexAttribPointer(positionloc, 4, GL_FLOAT, GL_TRUE, 8 * 4, vertbuf+0) # "+0" since we need to create an offset.
 glVertexAttribPointer(colorloc, 4, GL_FLOAT, GL_TRUE, 8 * 4, vertbuf+16) # 4 * 4 Bytes per float.
 vertbuf.unbind() # We can unbind the VBO, since it's linked to the VAO
 # glBindVertexArray(0)
 
 running = True
 t = time.time()
 rotation = 0.0
 while running:
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
     glUseProgram(prog)
     glUniformMatrix4fv(mvploc, 1, GL_TRUE, hm.rotation(mvp, rotation,[0,1,0]).tolist())
     # glBindVertexArray(vertobj)
Exemple #20
0
class VolumeObject(object):

    def __init__(self, stack, spacing):
        self.stack_texture, shape = self.load_stack(stack)

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

        tl = np.array((shape[2]*spacing[2],
                       shape[1]*spacing[1],
                       shape[0]*spacing[0]))

        # Vertex buffer: corners of cube.
        # x, y, z, texture_x, texture_y, texture_z
        vb = [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  # Corner 0.
              [tl[0], 0.0, 0.0, 1.0, 0.0, 0.0],
              [0.0, tl[1], 0.0, 0.0, 1.0, 0.0],
              [tl[0], tl[1], 0.0, 1.0, 1.0, 0.0],
              [0.0, 0.0, tl[2], 0.0, 0.0, 1.0],
              [tl[0], 0.0, tl[2], 1.0, 0.0, 1.0],
              [0.0, tl[1], tl[2], 0.0, 1.0, 1.0],
              [tl[0], tl[1], tl[2], 1.0, 1.0, 1.0]]  # Corner 7.

        vb = np.array(vb, dtype=np.float32)
        vb = vb.flatten()

        # Triangles of cube.
        idx_out = np.array([[0, 2, 1], [2, 3, 1],  # Triangle 0, triangle 1.
                            [1, 4, 0], [1, 5, 4],
                            [3, 5, 1], [3, 7, 5],
                            [2, 7, 3], [2, 6, 7],
                            [0, 6, 2], [0, 4, 6],
                            [5, 6, 4], [5, 7, 6]],  # Triangle 10, triangle 11.
                           dtype=np.uint32)
        self.vtVBO = VBO(vb)

        sc = 1.0/la.norm(tl)
        c = 0.5*tl

        self.transform = np.array(((0.0, 0.0, sc, -sc*c[2]),
                                   (0.0, sc, 0.0, -sc*c[1]),
                                   (sc, 0.0, 0.0, -sc*c[0]),
                                   (0.0, 0.0, 0.0, 1.0)))

        self.elVBO = VBO(idx_out, target=GL_ELEMENT_ARRAY_BUFFER)
        self.elCount = len(idx_out.flatten())

        print('made VBO')
        self.vtVBO.bind()

    def load_stack(self, stack):
        print('stack shape', stack.shape)

        s = np.array(stack, dtype=np.uint8, order='F')

        print(s.shape)

        w, h, d = s.shape
        print('shape', s.shape)

        stack_texture = glGenTextures(1)
        print(stack_texture)

        glActiveTexture(GL_TEXTURE0)
        glBindTexture(GL_TEXTURE_3D, stack_texture)

        glTexParameter(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexParameter(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)

        glPixelStorei(GL_UNPACK_ALIGNMENT, 1)

#       glTexParameter(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
#       glTexParameter(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
#       glTexParameter(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE)

        glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, d, h, w, 0, GL_RED,
                     GL_UNSIGNED_BYTE, s)
        print("made 3D texture")
        return stack_texture, s.shape
Exemple #21
0
class TraceRender:
    def __init__(self, parent_view: 'BoardViewWidget') -> None:
        self.parent = parent_view
        self.restart()

    def initializeGL(self, gls: 'GLShared') -> None:
        # Build trace vertex VBO and associated vertex data
        dtype = [("vertex", numpy.float32, 2), ("ptid", numpy.uint32)]
        self.working_array = numpy.zeros(NUM_ENDCAP_SEGMENTS * 2 + 2,
                                         dtype=dtype)
        self.trace_vbo = VBO(self.working_array, GL.GL_DYNAMIC_DRAW)
        GL.glObjectLabel(GL.GL_BUFFER, int(self.trace_vbo), -1,
                         "Thickline Trace VBO")

        # Generate geometry for trace and endcaps
        # ptid is a variable with value 0 or 1 that indicates which endpoint the geometry is associated with
        self.__build_trace()

        self.__attribute_shader_vao = VAO(
            debug_name="Thickline attribute shader VAO")
        shader = gls.shader_cache.get("line_vertex_shader",
                                      "basic_fill_frag",
                                      defines={"INPUT_TYPE": "in"})
        assert shader is not None
        self.__attribute_shader: 'EnhShaderProgram' = shader

        # Now we build an index buffer that allows us to render filled geometry from the same
        # VBO.
        arr = []
        for i in range(NUM_ENDCAP_SEGMENTS - 1):
            arr.append(0)
            arr.append(i + 2)
            arr.append(i + 3)

        for i in range(NUM_ENDCAP_SEGMENTS - 1):
            arr.append(1)
            arr.append(i + NUM_ENDCAP_SEGMENTS + 2)
            arr.append(i + NUM_ENDCAP_SEGMENTS + 3)

        arr.append(2)
        arr.append(2 + NUM_ENDCAP_SEGMENTS - 1)
        arr.append(2 + NUM_ENDCAP_SEGMENTS)
        arr.append(2 + NUM_ENDCAP_SEGMENTS)
        arr.append(2 + NUM_ENDCAP_SEGMENTS * 2 - 1)
        arr.append(2)

        arr2 = numpy.array(arr, dtype=numpy.uint32)
        self.index_vbo = VBO(arr2, target=GL.GL_ELEMENT_ARRAY_BUFFER)
        GL.glObjectLabel(GL.GL_BUFFER, int(self.index_vbo), -1,
                         "Thickline Index VBO")

        self.instance_dtype = numpy.dtype([
            ("pos_a", numpy.float32, 2),
            ("pos_b", numpy.float32, 2),
            ("thickness", numpy.float32),
            # ("color", numpy.float32, 4)
        ])

        # Use a fake array to get a zero-length VBO for initial binding
        instance_array: 'npt.NDArray[Any]' = numpy.ndarray(
            0, dtype=self.instance_dtype)
        self.instance_vbo = VBO(instance_array)
        GL.glObjectLabel(GL.GL_BUFFER, int(self.instance_vbo), -1,
                         "Thickline Instance VBO")

        with self.__attribute_shader_vao, self.trace_vbo:
            VBOBind(self.__attribute_shader.program, self.trace_vbo.dtype,
                    "vertex").assign()
            VBOBind(self.__attribute_shader.program, self.trace_vbo.dtype,
                    "ptid").assign()

        with self.__attribute_shader_vao, self.instance_vbo:
            self.__bind_pos_a = VBOBind(self.__attribute_shader.program,
                                        self.instance_dtype,
                                        "pos_a",
                                        div=1)
            self.__bind_pos_b = VBOBind(self.__attribute_shader.program,
                                        self.instance_dtype,
                                        "pos_b",
                                        div=1)
            self.__bind_thickness = VBOBind(self.__attribute_shader.program,
                                            self.instance_dtype,
                                            "thickness",
                                            div=1)
            # vbobind(self.__attribute_shader, self.instance_dtype, "color", div=1).assign()
            self.__base_rebind(0)

            self.index_vbo.bind()

    def __base_rebind(self, base: int) -> None:
        self.__bind_pos_a.assign(base)
        self.__bind_pos_b.assign(base)
        self.__bind_thickness.assign(base)

    def restart(self) -> None:
        pass

    def __build_trace(self) -> None:
        # Update trace VBO
        self.working_array["vertex"][0] = (0, 0)
        self.working_array["ptid"][0] = 0
        self.working_array["vertex"][1] = (0, 0)
        self.working_array["ptid"][1] = 1

        end = Vec2(1, 0)
        for i in range(0, NUM_ENDCAP_SEGMENTS):
            theta = math.pi * i / (NUM_ENDCAP_SEGMENTS - 1) + math.pi / 2
            m = rotate(theta).dot(end.homol())
            self.working_array["vertex"][2 + i] = m[:2]
            self.working_array["ptid"][2 + i] = 0
            self.working_array["vertex"][2 + i + NUM_ENDCAP_SEGMENTS] = -m[:2]
            self.working_array["ptid"][2 + i + NUM_ENDCAP_SEGMENTS] = 1

        # Force data copy
        self.trace_vbo.bind()
        self.trace_vbo.set_array(self.working_array)

    def __render_va_inner(self, col: int, is_outline: bool, first: int,
                          count: int) -> None:
        GL.glUniform4ui(self.__attribute_shader.uniforms.layer_info, 255, col,
                        0, 0)

        if has_base_instance:
            # Many instances backport glDrawElementsInstancedBaseInstance
            # This is faster than continually rebinding, so support if possible
            if not is_outline:
                # filled traces come first in the array
                GL.glDrawElementsInstancedBaseInstance(GL.GL_TRIANGLES,
                                                       TRIANGLES_SIZE,
                                                       GL.GL_UNSIGNED_INT,
                                                       ctypes.c_void_p(0),
                                                       count, first)
            else:
                # Then outline traces. We reuse the vertex data for the outside
                GL.glDrawArraysInstancedBaseInstance(GL.GL_LINE_LOOP, 2,
                                                     NUM_ENDCAP_SEGMENTS * 2,
                                                     count, first)
        else:
            with self.instance_vbo:
                if not is_outline:
                    # filled traces come first in the array
                    self.__base_rebind(first)
                    GL.glDrawElementsInstanced(GL.GL_TRIANGLES, TRIANGLES_SIZE,
                                               GL.GL_UNSIGNED_INT,
                                               ctypes.c_void_p(0), count)
                else:
                    self.__base_rebind(first)
                    # Then outline traces. We reuse the vertex data for the outside
                    GL.glDrawArraysInstanced(GL.GL_LINE_LOOP, 2,
                                             NUM_ENDCAP_SEGMENTS * 2, count)

    def render_va(self,
                  va: 'VA_thickline',
                  mat: 'npt.NDArray[numpy.float64]',
                  col: int,
                  is_outline: bool = False,
                  first: int = 0,
                  count: 'Optional[int]' = None) -> None:
        GL.glPushDebugGroup(GL.GL_DEBUG_SOURCE_APPLICATION, 0, -1,
                            "Thickline Draw")
        assert self.instance_dtype.itemsize == va.stride

        self.instance_vbo.set_array(va.buffer()[:])

        if count is None:
            count = va.count() - first

        with self.__attribute_shader.program, self.__attribute_shader_vao, self.instance_vbo:
            GL.glUniformMatrix3fv(self.__attribute_shader.uniforms.mat, 1,
                                  True, mat.astype(numpy.float32))

            self.__render_va_inner(col, is_outline, first, count)
        GL.glPopDebugGroup()
Exemple #22
0
class Mesh(Component):
    meshes = dict()  # cache to reuse meshes

    @classmethod
    def fromXMLElement(cls, xmlElement, actor=None):
        return cls.getMesh(xmlElement.get('src', 'Empty'), actor)
        # NOTE If src attribute is not found in XML element, special 'Empty' mesh is used

    @classmethod
    def getMesh(cls, src, actor=None):
        if not src in cls.meshes:
            if src == 'Empty':
                cls.meshes[src] = EmptyMesh(
                )  # special empty mesh to be used as a placeholder, and for empty actors
            else:
                cls.meshes[src] = Mesh(
                    src
                )  # NOTE Meshes are currently shared, therefore not linked to individual actors
        return cls.meshes[src]

    def __init__(self, src, actor=None):
        Component.__init__(self, actor)

        # TODO Include a mesh name (e.g. 'Dragon') as ID as well as src (e.g. '../res/models/Dragon.obj')
        self.src = src
        self.filepath = Context.getInstance().getResourcePath('models', src)

        # OpenGL version-dependent code (NOTE assumes major version = 3)
        self.vao = None
        if Context.getInstance().GL_version_minor > 0:  # 3.1 (or greater?)
            self.vao = glGenVertexArrays(1)
        else:  # 3.0 (or less?)
            self.vao = GLuint(0)
            glGenVertexArrays(1, self.vao)
        glBindVertexArray(self.vao)

        self.loadModel(self.filepath)

        self.vbo = VBO(self.meshData, GL_STATIC_DRAW)
        self.vbo.bind()

        glEnableVertexAttribArray(0)
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * 4, self.vbo + 0)

        glEnableVertexAttribArray(1)
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * 4, self.vbo + 12)

        self.ebo = glGenBuffers(1)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.ebo)
        glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                     len(self.elements) * 4, self.elements, GL_STATIC_DRAW)

    def loadModel(self, filename):
        f = open(filename, 'r')
        self.meshData = []
        self.elements = []
        vertices = []
        normals = []
        texCoords = []

        for line in f:
            s = line.split()
            if len(s) > 0:
                if s[0] == 'v':
                    v = np.array([s[1], s[2], s[3]], dtype=np.float32)
                    vertices.append(v)
                elif s[0] == 'vn':
                    v = np.array([s[1], s[2], s[3]], dtype=np.float32)
                    normals.append(v)
                elif s[0] == 'vt':
                    v = np.array([s[1], s[2]], dtype=np.float32)
                    texCoords.append(v)
                elif s[0] == 'f':
                    for i in xrange(1, 4):
                        l = s[i].split('/')
                        self.meshData.append(float(vertices[int(l[0]) - 1][0]))
                        self.meshData.append(float(vertices[int(l[0]) - 1][1]))
                        self.meshData.append(float(vertices[int(l[0]) - 1][2]))
                        self.meshData.append(float(normals[int(l[2]) - 1][0]))
                        self.meshData.append(float(normals[int(l[2]) - 1][1]))
                        self.meshData.append(float(normals[int(l[2]) - 1][2]))
                        self.elements.append(len(self.elements))

        self.meshData = np.array(self.meshData, dtype=np.float32)
        self.elements = np.array(self.elements, dtype=np.uint32)

    def render(self):
        glBindVertexArray(self.vao)
        glDrawElements(GL_TRIANGLES, self.elements.size, GL_UNSIGNED_INT, None)

    def toXMLElement(self):
        xmlElement = Component.toXMLElement(self)
        xmlElement.set('src', self.src)
        return xmlElement

    def toString(self, indent=""):
        return indent + "Mesh: { src: \"" + self.src + "\" }"

    def __str__(self):
        return self.toString()
Exemple #23
0
class MSGLCanvas2D(QGLWidget):
    """
    Canvas GL plotting in 2 dimensions
    """

    MAX = 100.

    corner_ = 100.0
    zoom_ = 1.5
    xrot_ = 220
    yrot_ = 220
    trans_x_ = 0.0
    trans_y_ = 0.0

    def __init__(self, data, parent=None, **kw):
        """
        Constructor, initialization
        """

        QGLWidget.__init__(self, parent)
        self.setFormat(QGLFormat(QGL.SampleBuffers))
        self.setMinimumSize(500, 300)  #300
        self.setMouseTracking(True)
        self.setFocusPolicy(Qt.StrongFocus)

        self.data = data
        vertexes = []
        colors = []
        from utils.misc import IceAndFire
        maxY = max(map(max, [log10(el.y_data) for el in data]))
        maxX = max(map(max, [el.x_data for el in data]))
        rtmax = max([z.rtmin for z in data])
        for el in data:
            for i, x in enumerate(el.x_data):
                c = IceAndFire.getQColor(log10(el.y_data[i]) / maxY)
                colors.append(c)
                vertexes.append([(x * 2 * self.corner_) / maxX,
                                 (el.rt * 2 * self.corner_) / rtmax])
        from OpenGL.arrays.vbo import VBO

        self.vertexes = VBO(array(vertexes, 'f'))
        self.colors = VBO(array(colors, 'f'))

        self.mode = "None"  # "ZOOMING", "PANNING", "NONE"
        self.lastpos = QPoint()

        self.counter_trans_x = 0
        self.counter_trans_y = 0

        self.defaultColors = {
            'ticks': (0., 0., 0., 0.),
            'axes': (0., 0., 0., 0.),
            'curves': (0., 0., 1., 0.),
            'backgroundColor': (1., 1., 1., 1.)
        }

        #self.axes=self.drawAxes()
        self.transformationMatrix = self.setupTransformationMatrix(
            self.width(), self.height())

    def setupTransformationMatrix(self, w, h):
        """
        use a matrix to translate in the gl landmark
        """

        m = QMatrix()
        m.translate(-w / 2, h / 2)
        m.scale(300. / w, 300. / h)
        print w, h, w / 300., 1 - ((h / 300) - 1)
        #m.scale((self.width()*100)/300, -(self.height()*100)/300)
        #self.currentSize.x = w
        #self.currentSize.y = h
        return m

    def inGLCoordinate(self, point):
        return self.transformationMatrix.map(point)

    def resizeGL(self, w, h):
        """
        called when window is being resized
        """

        glViewport(0, 0, w, h)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(-self.corner_ * self.zoom_, self.corner_ * self.zoom_,
                   -self.corner_ * self.zoom_, self.corner_ * self.zoom_)

        #self.transformationMatrix = self.setupTransformationMatrix(w, h)

        glMatrixMode(GL_MODELVIEW)

    def initializeGL(self):
        """needed, initialize GL parameters"""

        #glClearColor(1.,1.,1.,1.)
        glDisable(GL_DEPTH_TEST)
        glEnable(GL_LINE_SMOOTH)
        glEnable(GL_POINT_SMOOTH)
        glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
        glLoadIdentity()  #model view by default

#        self.grid_lines = self.drawGridLines()
#        self.ticks =self.drawAxisTick()
#        self.axes = self.drawAxes()

    def paintGL(self):
        """Draw the scene, needed, called each time glDraw"""

        glClear(GL_COLOR_BUFFER_BIT)
        glTranslated(self.trans_x_, self.trans_y_, 0.)
        #addition
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(-self.corner_ * self.zoom_, self.corner_ * self.zoom_,
                   -self.corner_ * self.zoom_, self.corner_ * self.zoom_)
        glMatrixMode(GL_MODELVIEW)
        #end addition
        #glCallList(self.grid_lines)
        #glCallList(self.ticks)
        #glCallList(self.axes)
        glLineWidth(30.0)
        self.scatterPlot()
#        if self.flags == "chrom":
#            self.drawAxisLegend("retention time[s]", "intensity[%]")
#            glCallList(self.lines)
#        elif self.flags == "spectrum":
#            self.drawAxisLegend("m/z", "intensity")

    def drawAxes(self, width=2., colour=(0., 0., 0.)):
        """
        Draw Axes 
        """
        #width must be a float
        axes = glGenLists(1)
        glNewList(axes, GL_COMPILE)
        glLineWidth(width)
        glColor(colour[0], colour[1], colour[2])
        glBegin(GL_LINES)
        #x_achse
        glVertex2d(-self.corner_, -self.corner_)
        glVertex2d(self.corner_, -self.corner_)
        #y-achse
        glVertex2d(-self.corner_, -self.corner_)
        glVertex2d(-self.corner_, self.corner_)
        glEnd()
        glEndList()
        return axes

    def drawLegends(self, pos):
        """
        draw legend at the specified position
        """
        pass

    def drawAxisLegend(self, x_label, y_label):
        """
        Draw Axis Legend
        """
        font = QFont("Typewriter")
        #RT axis legend
        font.setPixelSize(12)
        self.renderText(self.corner_, -self.corner_ - 20.0, 0.,
                        x_label)  # font
        self.renderText(-self.corner_ - 20.0, self.corner_, 0., y_label, font)

    def resetTranslations(self):
        """
        reset the different translation to 0
        """
        self.trans_x_ = 0.
        self.trans_y_ = 0.
        self.counter_trans_x = 0.
        self.counter_trans_y = 0.

    def normalizeAngle(self, angle):
        while (angle < 0):
            angle += 360 * 16
        while (angle > 360 * 16):
            angle -= 360 * 16


########DRAWING METHODS##################################################

    def drawLine(self, point_, point):
        glBegin(GL_LINES)
        glVertex2d(point_.x(), point_.y())
        glVertex2d(point.x(), point.y())
        glEnd()

    def drawRect(self, p_1, p_2, p_3=None, p_4=None):
        pass

    def drawOnePoint(self, point, colour=Qt.yellow):
        pass

    def scatterPlot(self):
        """ Draw Data (x, y)"""
        if self.vertexes is not None and self.colors is not None:
            self.vertexes.bind()
            glEnableClientState(GL_VERTEX_ARRAY)
            glVertexPointerf(self.vertexes)
            self.colors.bind()
            glEnableClientState(GL_COLOR_ARRAY)
            glColorPointerf(self.colors)
            glDrawArrays(GL_LINES, 0, len(self.vertexes))
            self.vertexes.unbind()
            self.colors.unbind()
            #self.textures.unbind()
            glDisableClientState(GL_VERTEX_ARRAY)
            glDisableClientState(GL_COLOR_ARRAY)

    def spectrumPlot(self, points):
        pass

    def histogramPlot(self, points, bin=5.):
        pass

    def barPlot(points, width=2.):
        pass

    ########MOUSE AND KEYBOARDS EVENTS###########################################################################

    def wheelEvent(self, event):
        if event.delta() > 0:
            self.zoom_ -= .05
        else:
            self.zoom_ += .05
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(-self.corner_ * self.zoom_, self.corner_ * self.zoom_,
                   -self.corner_ * self.zoom_, self.corner_ * self.zoom_)
        self.updateGL()
        glMatrixMode(GL_MODELVIEW)
        event.accept()

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Plus:
            self.zoom_ -= .1
            glMatrixMode(GL_PROJECTION)
            glLoadIdentity()
            gluOrtho2D(-self.corner_ * self.zoom_, self.corner_ * self.zoom_,
                       -self.corner_ * self.zoom_, self.corner_ * self.zoom_)
            glMatrixMode(GL_MODELVIEW)

        if event.key() == Qt.Key_Minus:
            self.zoom_ += .1
            glMatrixMode(GL_PROJECTION)  #// You had GL_MODELVIEW
            glLoadIdentity()
            gluOrtho2D(-self.corner_ * self.zoom_, self.corner_ * self.zoom_,
                       -self.corner_ * self.zoom_, self.corner_ * self.zoom_)
            glMatrixMode(GL_MODELVIEW)

        if event.key() == Qt.Key_Up:
            self.trans_y_ += 2
            self.counter_trans_y += 2

        if event.key() == Qt.Key_Down:
            self.trans_y_ -= 2
            self.counter_trans_y -= 2

        if event.key() == Qt.Key_Left:
            self.trans_x_ -= 2
            self.counter_trans_x -= 2

        if event.key() == Qt.Key_Right:
            self.trans_x_ += 2
            self.counter_trans_x += 2

        if event.key() == Qt.Key_Z:
            self.mode = "ZOOMING"
            if self.counter_trans_x < 0 and self.counter_trans_y < 0:
                while self.counter_trans_x < 0 and self.counter_trans_y < 0:
                    self.trans_x_ = self.counter_trans_x
                    self.trans_y_ = self.counter_trans_y
                    self.updateGL()
                    self.counter_trans_x += 1
                    self.counter_trans_y += 1

            if self.counter_trans_x > 0 and self.counter_trans_y < 0:
                while self.counter_trans_x < 0 and self.counter_trans_y < 0:
                    self.trans_x_ = self.counter_trans_x
                    self.trans_y_ = self.counter_trans_y
                    self.updateGL()
                    self.counter_trans_x -= 1
                    self.counter_trans_y += 1

            if self.counter_trans_x < 0 and self.counter_trans_y > 0:
                while self.counter_trans_x < 0 and self.counter_trans_y < 0:
                    self.trans_x_ = self.counter_trans_x
                    self.trans_y_ = self.counter_trans_y
                    self.updateGL()
                    self.counter_trans_x += 1
                    self.counter_trans_y -= 1

            if self.counter_trans_x < 0 and self.counter_trans_y > 0:
                while self.counter_trans_x < 0 and self.counter_trans_y < 0:
                    self.trans_x_ = self.counter_trans_x
                    self.trans_y_ = self.counter_trans_y
                    self.updateGL()
                    self.counter_trans_x -= 1
                    self.counter_trans_y -= 1

            if self.zoom_ != 1.5:
                self.zoom = 1.5
                #self.updateGL()
        self.updateGL()
        self.resetTranslations()

    def mousePressEvent(self, event):
        if self.mode == "ZOOMING":
            self.mode = "None"
            self.computeSelection()
        else:
            self.lastpos = QPoint(event.pos())
            self.setCursor(QCursor(Qt.ClosedHandCursor))

        #if event.buttons() ==  Qt.RightButton:
        #    self.mode = "PANNING"

    def computeSelection(self):
        print "selected"

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastpos.x()
        dy = event.y() - self.lastpos.y()

        if self.mode == "ZOOMING":
            font = QFont("Typewriter")
            self.renderText(-self.corner_ - 30.0, self.corner_, 0.,
                            "ZOOMING MODE ACTIVATED", font)
            self.updateGL()
            glColor(0., 0., 1., .5)
            XMAX = 900.
            XMIN = 180.
            pointer_x = (self.lastpos.x() * 200.) / XMAX
            norm_dx = (dx * 200.) / XMAX
            """
            if pointer_x > 100. or pointer_x < 100. \
                or norm_dx >100. or norm_dx<-100.:
                event.ignore()
            """

            glBegin(GL_QUADS)
            glVertex2d(pointer_x, -100.)
            glVertex2d(pointer_x + norm_dx, -100.)
            glVertex2d(pointer_x + norm_dx, 100.)
            glVertex2d(pointer_x, 100.)
            glEnd()

            self.updateGL()  #update for seeing the rectangle

        mapping = self.mapFromGlobal
        cursorPos = self.inGLCoordinate(mapping(self.cursor().pos()))
        QToolTip.showText(self.cursor().pos(),
                          "x:"+str(cursorPos.x())+ \
                          ", y:"+str(cursorPos.y())
                          )

        if self.mode == "None":
            if event.buttons() == Qt.LeftButton:
                self.trans_y_ -= dy / 5
                self.counter_trans_y -= dy / 5
                self.trans_x_ += dx / 5
                self.counter_trans_x += dx / 5
            self.lastpos = QPoint(event.pos())
            self.glDraw()
            self.resetTranslations()

    def mouseReleaseEvent(self, event):
        self.setCursor(QCursor(Qt.ArrowCursor))
Exemple #24
0
    # set resizing callback function
    glfw.set_framebuffer_size_callback(theWindow, window_resize_callback)

    # create VBO to store vertices
    verticesVBO = VBO(triangleVertices, usage='GL_STATIC_DRAW')
    verticesVBO.create_buffers()

    # create VAO to describe array information
    triangleVAO = glGenVertexArrays(1)

    # bind VAO
    glBindVertexArray(triangleVAO)

    # bind VBO
    verticesVBO.bind()
    # buffer data into OpenGL
    verticesVBO.copy_data()

    # configure the fist 3-vector (pos)
    # arguments: index, size, type, normalized, stride, pointer
    # the stride is 6 * 4 because there are six floats per vertex, and the size of
    # each float is 4 bytes
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * 4, ctypes.c_void_p(0))
    glEnableVertexAttribArray(0)

    # configure the second 3-vector (color)
    # the offset is 3 * 4 = 12 bytes
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * 4,
                          ctypes.c_void_p(3 * 4))
    glEnableVertexAttribArray(1)
Exemple #25
0
class TextBatcher(object):
    __tag_type = namedtuple("render_tag", ["textinfo", "matrix", "color"])

    def __init__(self, tr):
        self.text_render = tr
        self.__cached = {}

        self.__clist = []

        self.restart()

    def restart(self):
        self.__render_tags = defaultdict(list)


    def initializeGL(self):
        # Working VBO that will contain glyph data
        self.vbo = VBO(numpy.ndarray(0, dtype=self.text_render.buffer_dtype), GL.GL_DYNAMIC_DRAW, GL.GL_ARRAY_BUFFER)
        self.vao = VAO()

        with self.vao, self.vbo:
            self.text_render.b1.assign()
            self.text_render.b2.assign()
        self.__vbo_needs_update = True


    def render(self, key=None):
        if self.__vbo_needs_update:
            arr = numpy.array(self.__clist, dtype=self.text_render.buffer_dtype)

            self.vbo.data = arr
            self.vbo.size = None
            self.vbo.copied = False
            self.vbo.bind()
            self.__vbo_needs_update = False

        self.text_render.updateTexture()

        with self.text_render.sdf_shader, self.text_render.tex.on(GL.GL_TEXTURE_2D), self.vao:
            GL.glUniform1i(self.text_render.sdf_shader.uniforms.tex1, 0)

            for tag in self.__render_tags[key]:
                mat_calc = tag.matrix
                GL.glUniformMatrix3fv(self.text_render.sdf_shader.uniforms.mat, 1, True, mat_calc.astype(numpy.float32))
                GL.glUniform4f(self.text_render.sdf_shader.uniforms.color, *tag.color)

                GL.glDrawArrays(GL.GL_TRIANGLES, tag.textinfo.start, tag.textinfo.count)

    def submit(self, ts, mat, color, k=None):
        self.__render_tags[k].append(self.__tag_type(ts, mat, color))

    def submit_text_box(self, premat, text, box, color, k=None):
        ts = self.get_string(text)
        mat = premat.dot(ts.get_render_to_mat(box))
        self.submit(ts, mat, color, k)

    def get_string(self, text):
        if text in self.__cached:
            return self.__cached[text]

        self.__cached[text] = ti = self.text_render.getString(text)

        ti.start = len(self.__clist)

        self.__clist.extend(ti.arr)
        ti.count = len(ti.arr)
        self.__vbo_needs_update = True
        return ti
Exemple #26
0
class instancingdemo(df.demoplate):
    
    def init(self):
        print "OpenGL Information:"
        for prop in ["GL_VENDOR", "GL_RENDERER", "GL_VERSION", "GL_SHADING_LANGUAGE_VERSION"]:
            print "\t%s = %s" % (prop, glGetString(globals()[prop]))

        
        self.campos = np.array([2.5, 1.5, 1.5, 1], dtype = np.float32)
        self.center = np.array([0.0,0.0,0.0,1.0], dtype = np.float32)
        
        self.perspective_mat = None
        self.mvp = None
        # OpenGL Stuff
        glEnable(GL_DEPTH_TEST)
        #glEnable(GL_CULL_FACE)
        glClearColor(1, 1, 1, 0)
        glPointSize(5)
        # Shader Stuff.
        with open('shader.fs') as fs, open('shader.vs') as vs:            
            self.shader = su.Shader(list(vs), list(fs))
        
        self.shader.bindfragdata(0, 'fragcolor')
        self.mvploc = self.shader.uniformlocation('mvp')
        self.objploc = self.shader.uniformlocation('objp')
        self.objoffsetloc = self.shader.uniformlocation('objoffset')
        self.positionloc = self.shader.attributelocation('vs_position')
        self.normalloc = self.shader.attributelocation('vs_normal')
        
        self.loadsquirrel()
        self.buildobjoffsets()
        
    def buildobjoffsets(self):
        objoffset = np.zeros((5,5,5,4), dtype = np.float32)
        start = np.array([-1, -1, -1, 0], dtype = np.float32)
        steps = np.arange(0, 2.1, 0.5, dtype = np.float32)
        for x in range(5):
            for y in range(5):
                for z in range(5):
                    objoffset[x,y,z,] = start + np.array([steps[x], steps[y], steps[z], 0], dtype = np.float32)
        self.shader.use()
        glUniform4fv(self.objoffsetloc, 5 * 5 * 5, objoffset.flatten().tolist())
                
    def loadsquirrel(self):
        # When loading the data, pad the normals to 4 floats (16bytes) since GPUs hate unaligned memory.
        obj = wf.ObjFileParser("squirrel.obj", padnormals = 4)
        self.objscale = 1 / np.max(obj.scale / 2)
        self.objcenter = obj.minpos + (obj.scale / 2)
        
        self.obj_mat = hm.scale(hm.identity(),
                                [self.objscale * 0.2] * 3)
        self.obj_mat = hm.translation(self.obj_mat,
                                      -self.objcenter)

        # Generate a GL compatible indexed vertex buffer for the object
        self.vbdata, ibdata = obj.generateIndexedBuffer([0,1], np.uint16)
        vbdata = self.vbdata
        self.elementnum = np.shape(ibdata)[0]
        # VAO
        self.vertobj = glGenVertexArrays(1)
        glBindVertexArray(self.vertobj)
        # Setup the VBO for the vertex data.
        self.vertbuf = VBO(vbdata, GL_STATIC_DRAW, GL_ARRAY_BUFFER)
        self.vertbuf.bind()
        glVertexAttribPointer(self.positionloc, 4, GL_FLOAT, GL_TRUE, 8 * 4, ctypes.c_void_p(0))
        glVertexAttribPointer(self.normalloc, 4, GL_FLOAT, GL_TRUE, 8 * 4, ctypes.c_void_p(16))
        glEnableVertexAttribArray(self.positionloc)
        glEnableVertexAttribArray(self.normalloc)
        # Indexbuffer
        self.indexbuf = VBO(ibdata, GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER)
        self.indexbuf.bind()
        
        glBindVertexArray(0)
        self.vertbuf.unbind()
        self.indexbuf.unbind()
        #Animation init...
        self.rotation = 0

                
    def resize(self, width, height):
        glViewport(0, 0, width, height)
        self.perspective_mat = hm.perspective(hm.identity(),
                                              60,
                                              float(width) / height,
                                              0.1,
                                              6.0)
        self.modelview_mat = hm.lookat(hm.identity(),
                                       self.campos,
                                       self.center)
        
        self.mvp = np.dot(self.perspective_mat, self.modelview_mat)
    
    def display(self, timediff):

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        self.shader.use()
        glUniformMatrix4fv(self.objploc, 1, GL_TRUE,
                           np.dot(hm.rotation(hm.identity(), self.rotation, [0,1,0]), self.obj_mat).tolist())
        glUniformMatrix4fv(self.mvploc, 1, GL_TRUE,
                           hm.rotation(self.mvp, self.rotation / 4, [0.577350269189626] * 3).tolist())
        
        glBindVertexArray(self.vertobj)
        glDrawElementsInstanced(GL_TRIANGLES, self.elementnum, GL_UNSIGNED_SHORT, ctypes.c_void_p(0), 125)
        glBindVertexArray(0)
        
        self.rotation += timediff / 5 * 360
Exemple #27
0
class _THBatch:
    def __init__(self, parent):
        self.parent = parent
        self.restart()
        self.initialized = False

    def restart(self):
        self.__deferred_list_filled = []
        self.__deferred_list_outline = []

    def _initializeGL(self):
        self.initialized = True

        self.__filled_vao = VAO()
        self.__outline_vao = VAO()

        with self.__filled_vao, self.parent._sq_vbo:
            vbobind(self.parent._filled_shader, self.parent._sq_vbo.data.dtype,
                    "vertex").assign()

        # Use a fake array to get a zero-length VBO for initial binding
        filled_instance_array = numpy.ndarray(
            0, dtype=self.parent._filled_instance_dtype)
        self.filled_instance_vbo = VBO(filled_instance_array)

        with self.__filled_vao, self.filled_instance_vbo:
            vbobind(self.parent._filled_shader,
                    self.parent._filled_instance_dtype,
                    "pos",
                    div=1).assign()
            vbobind(self.parent._filled_shader,
                    self.parent._filled_instance_dtype,
                    "r",
                    div=1).assign()
            vbobind(self.parent._filled_shader,
                    self.parent._filled_instance_dtype,
                    "r_inside_frac_sq",
                    div=1).assign()
            vbobind(self.parent._filled_shader,
                    self.parent._filled_instance_dtype,
                    "color",
                    div=1).assign()

        with self.__outline_vao, self.parent._outline_vbo:
            vbobind(self.parent._outline_shader,
                    self.parent._outline_vbo.data.dtype, "vertex").assign()

        # Build instance for outline rendering
        # We don't have an inner 'r' for this because we just do two instances per vertex

        # Use a fake array to get a zero-length VBO for initial binding
        outline_instance_array = numpy.ndarray(
            0, dtype=self.parent._outline_instance_dtype)
        self.outline_instance_vbo = VBO(outline_instance_array)

        with self.__outline_vao, self.outline_instance_vbo:
            vbobind(self.parent._outline_shader,
                    self.parent._outline_instance_dtype,
                    "pos",
                    div=1).assign()
            vbobind(self.parent._outline_shader,
                    self.parent._outline_instance_dtype,
                    "r",
                    div=1).assign()
            vbobind(self.parent._outline_shader,
                    self.parent._outline_instance_dtype,
                    "color",
                    div=1).assign()

    def deferred(self, center, r1, r2, rs, render_hint=RENDER_HINT_NORMAL):
        if rs & RENDER_OUTLINES:
            self.__deferred_list_outline.append((center, r1, r2, rs))
        else:
            self.__deferred_list_filled.append((center, r1, r2, rs))

    def prepare(self):
        self.__prepare_filled()
        self.__prepare_outline()

    def __prepare_filled(self):
        if not self.initialized:
            self._initializeGL()

        count = len(self.__deferred_list_filled)
        self.__filled_count = count

        if count == 0:
            return

        # Resize instance data array
        instance_array = numpy.ndarray(
            count, dtype=self.parent._filled_instance_dtype)

        color_a = [0.6, 0.6, 0.6, 1]

        for n, (center, r1, r2, rs) in enumerate(self.__deferred_list_filled):

            # HACK, color object
            color_mod = self.parent.parent.sel_colormod(
                rs & RENDER_SELECTED, color_a)

            # frag shader uses pythag to determine is frag is within
            # shaded area. Precalculate comparison term
            r_frac_sq = (r2 / r1)**2
            instance_array[n] = (center, r1, r_frac_sq, color_mod)

        self.filled_instance_vbo.data = instance_array
        self.filled_instance_vbo.size = None
        self.filled_instance_vbo.copied = False
        self.filled_instance_vbo.bind()

    def __prepare_outline(self):
        count = 0
        for center, r1, r2, rs in self.__deferred_list_outline:
            if r2 == 0:
                count += 1
            else:
                count += 2

        self.__outline_count = count
        if count == 0:
            return

        # Resize instance data array
        instance_array = numpy.ndarray(
            count, dtype=self.parent._outline_instance_dtype)

        n = 0
        for center, r1, r2, rs in self.__deferred_list_outline:
            color_a = [0.6, 0.6, 0.6, 1]

            # HACK, color object
            color_a = self.parent.parent.sel_colormod(rs & RENDER_SELECTED,
                                                      color_a)

            instance_array[n] = (center, r1, color_a)
            n += 1

            if r2 > 0:
                instance_array[n] = (center, r2, color_a)
                n += 1

        self.outline_instance_vbo.data = instance_array
        self.outline_instance_vbo.size = None
        self.outline_instance_vbo.copied = False
        self.outline_instance_vbo.bind()

    def render(self, mat):
        self.render_filled(mat)
        self.render_outline(mat)

    def render_filled(self, mat):
        if self.__filled_count == 0:
            return

        with self.parent._filled_shader, self.__filled_vao, self.filled_instance_vbo, self.parent._sq_vbo:
            GL.glUniformMatrix3fv(self.parent._filled_shader.uniforms.mat, 1,
                                  True, mat.ctypes.data_as(GLI.c_float_p))
            GL.glDrawArraysInstanced(GL.GL_TRIANGLE_STRIP, 0, 4,
                                     len(self.__deferred_list_filled))

    def render_outline(self, mat):
        if self.__outline_count == 0:
            return

        with self.parent._outline_shader, self.__outline_vao, self.outline_instance_vbo, self.parent._sq_vbo:
            GL.glUniformMatrix3fv(self.parent._outline_shader.uniforms.mat, 1,
                                  True, mat.ctypes.data_as(GLI.c_float_p))
            GL.glDrawArraysInstanced(GL.GL_LINE_LOOP, 0, N_OUTLINE_SEGMENTS,
                                     self.__outline_count)
Exemple #28
0
class GcodeModel(Model):
    """
    Model for displaying Gcode data.
    """
    # vertices for arrow to display the direction of movement
    arrow = numpy.require([
        [0.0, 0.0, 0.0],
        [0.4, -0.1, 0.0],
        [0.4, 0.1, 0.0],
    ], 'f')

    def load_data(self, model_data, callback=None):
        t_start = time.time()

        vertex_list      = []
        color_list       = []
        self.layer_stops = [0]
        arrow_list       = []
        num_layers       = len(model_data)

        for layer_idx, layer in enumerate(model_data):
            for movement in layer:
                vertex_list.append(movement.src)
                vertex_list.append(movement.dst)

                arrow = self.arrow
                # position the arrow with respect to movement
                arrow = vector.rotate(arrow, movement.angle(), 0.0, 0.0, 1.0)
                arrow_list.extend(arrow)

                vertex_color = self.movement_color(movement)
                color_list.append(vertex_color)

            self.layer_stops.append(len(vertex_list))

            if callback:
                callback(layer_idx + 1, num_layers)

        self.vertices = numpy.array(vertex_list, 'f')
        self.colors   = numpy.array(color_list,  'f')
        self.arrows   = numpy.array(arrow_list,  'f')

        # by translating the arrow vertices outside of the loop, we achieve a
        # significant performance gain thanks to numpy. it would be really nice
        # if we could rotate in a similar fashion...
        self.arrows = self.arrows + self.vertices[1::2].repeat(3, 0)

        # for every pair of vertices of the model, there are 3 vertices for the arrow
        assert len(self.arrows) == ((len(self.vertices) // 2) * 3), \
            'The 2:3 ratio of model vertices to arrow vertices does not hold.'

        self.max_layers         = len(self.layer_stops) - 1
        self.num_layers_to_draw = self.max_layers
        self.arrows_enabled     = True
        self.initialized        = False

        t_end = time.time()

        logging.info('Initialized Gcode model in %.2f seconds' % (t_end - t_start))
        logging.info('Vertex count: %d' % len(self.vertices))

    def movement_color(self, move):
        """
        Return the color to use for particular type of movement.
        """
        # default movement color is gray
        color = [0.6, 0.6, 0.6, 0.6]

        extruder_on = (move.flags & Movement.FLAG_EXTRUDER_ON or
                       move.delta_e > 0)
        outer_perimeter = (move.flags & Movement.FLAG_PERIMETER and
                           move.flags & Movement.FLAG_PERIMETER_OUTER)

        if extruder_on and outer_perimeter:
            color = [0.0, 0.875, 0.875, 0.6] # cyan
        elif extruder_on and move.flags & Movement.FLAG_PERIMETER:
            color = [0.0, 1.0, 0.0, 0.6] # green
        elif extruder_on and move.flags & Movement.FLAG_LOOP:
            color = [1.0, 0.875, 0.0, 0.6] # yellow
        elif extruder_on:
            color = [1.0, 0.0, 0.0, 0.6] # red

        return color

    # ------------------------------------------------------------------------
    # DRAWING
    # ------------------------------------------------------------------------

    def init(self):
        self.vertex_buffer       = VBO(self.vertices, 'GL_STATIC_DRAW')
        self.vertex_color_buffer = VBO(self.colors.repeat(2, 0), 'GL_STATIC_DRAW') # each pair of vertices shares the color

        if self.arrows_enabled:
            self.arrow_buffer       = VBO(self.arrows, 'GL_STATIC_DRAW')
            self.arrow_color_buffer = VBO(self.colors.repeat(3, 0), 'GL_STATIC_DRAW') # each triplet of vertices shares the color

        self.initialized = True

    def display(self, mode_2d=False):
        glPushMatrix()
        glTranslate(self.offset_x, self.offset_y, 0)
        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_COLOR_ARRAY)

        self._display_movements(mode_2d)

        if self.arrows_enabled:
            self._display_arrows()

        glDisableClientState(GL_COLOR_ARRAY)
        glDisableClientState(GL_VERTEX_ARRAY)
        glPopMatrix()

    def _display_movements(self, mode_2d=False):
        self.vertex_buffer.bind()
        glVertexPointer(3, GL_FLOAT, 0, None)

        self.vertex_color_buffer.bind()
        glColorPointer(4, GL_FLOAT, 0, None)

        if mode_2d:
            glScale(1.0, 1.0, 0.0) # discard z coordinates
            start = self.layer_stops[self.num_layers_to_draw - 1]
            end   = self.layer_stops[self.num_layers_to_draw] - start
        else: # 3d
            start = 0
            end   = self.layer_stops[self.num_layers_to_draw]

        glDrawArrays(GL_LINES, start, end)

        self.vertex_buffer.unbind()
        self.vertex_color_buffer.unbind()

    def _display_arrows(self):
        self.arrow_buffer.bind()
        glVertexPointer(3, GL_FLOAT, 0, None)

        self.arrow_color_buffer.bind()
        glColorPointer(4, GL_FLOAT, 0, None)

        start = (self.layer_stops[self.num_layers_to_draw - 1] // 2) * 3
        end   = (self.layer_stops[self.num_layers_to_draw] // 2) * 3

        glDrawArrays(GL_TRIANGLES, start, end - start)

        self.arrow_buffer.unbind()
        self.arrow_color_buffer.unbind()
Exemple #29
0
    class _RenderData:
        def __init__(self, dtype, shader, glhint):
            self.__dtype = dtype

            self.vao = VAO()
            self.batch_vbo = VBO(numpy.array([], dtype=dtype), glhint)

            with self.vao, self.batch_vbo:
                vbobind(shader, dtype, "vertex").assign()

            self.clear()

        def clear(self):
            self.__vbo_update = True
            self.__groups = defaultdict(list)
            self.__group_lookup = {}
            self.group_offsets = {}


        def build_vbo(self):
            if not self.__vbo_update:
                return

            self.__vbo_update = False

            self.group_offsets = {}

            built_list = []
            for group, points in self.__groups.items():
                self.group_offsets[group] = len(built_list)
                built_list.extend([(i,) for i in points])

            if not built_list:
                return

            ar = numpy.array(built_list, dtype=self.__dtype)

            self.batch_vbo.data = ar
            self.batch_vbo.size = None
            self.batch_vbo.copied = False
            self.batch_vbo.bind()

        def last_index(self, group):
            return len(self.__groups[group])


        def add_point(self, p1, p2, group):
            group = self.__groups[group]
            idx = len(group) // 2
            group.append(p1)
            group.append(p2)
            self.__vbo_update = True
            return idx

        def get_point_index(self, p1, p2, group):
            key = group, p1.intTuple(), p2.intTuple()
            try:
                return self.__group_lookup[key]
            except KeyError:
                pass

            idx = self.__group_lookup[key] = self.add_point(p1, p2, group)
            return idx
Exemple #30
0
class GcodeModel(Model):
    """
    Model for displaying Gcode data.
    """
    # vertices for arrow to display the direction of movement
    arrow = numpy.require([
        [0.0, 0.0, 0.0],
        [0.4, -0.1, 0.0],
        [0.4, 0.1, 0.0],
    ], 'f')
    layer_entry_marker = numpy.require([
        [ 0.23, -0.14, 0.0],
        [ 0.0,   0.26, 0.0],
        [-0.23, -0.14, 0.0],
    ], 'f')
    layer_exit_marker = numpy.require([
        [-0.23, -0.23, 0.0],
        [ 0.23, -0.23, 0.0],
        [ 0.23,  0.23, 0.0],
        [ 0.23,  0.23, 0.0],
        [-0.23,  0.23, 0.0],
        [-0.23, -0.23, 0.0],
    ], 'f')

    def load_data(self, model_data, callback=None):
        t_start = time.time()

        vertex_list             = []
        color_list              = []
        self.layer_stops        = [0]
        self.layer_heights      = []
        arrow_list              = []
        layer_markers_list      = []
        self.layer_marker_stops = [0]

        num_layers     = len(model_data)
        callback_every = max(1, int(math.floor(num_layers / 100)))

        # the first movement designates the starting point
        start = prev = model_data[0][0]
        del model_data[0][0]

        for layer_idx, layer in enumerate(model_data):
            first = layer[0]
            for movement in layer:
                vertex_list.append(prev.v)
                vertex_list.append(movement.v)

                arrow = self.arrow
                # position the arrow with respect to movement
                arrow = vector.rotate(arrow, movement.angle(prev.v), 0.0, 0.0, 1.0)
                arrow_list.extend(arrow)

                vertex_color = self.movement_color(movement)
                color_list.append(vertex_color)

                prev = movement

            self.layer_stops.append(len(vertex_list))
            self.layer_heights.append(first.v[2])

            # add the layer entry marker
            if layer_idx > 0 and len(model_data[layer_idx - 1]) > 0:
                layer_markers_list.extend(self.layer_entry_marker + model_data[layer_idx-1][-1].v)
            elif layer_idx == 0 and len(layer) > 0:
                layer_markers_list.extend(self.layer_entry_marker + layer[0].v)

            # add the layer exit marker
            if len(layer) > 1:
                layer_markers_list.extend(self.layer_exit_marker + layer[-1].v)

            self.layer_marker_stops.append(len(layer_markers_list))

            if callback and layer_idx % callback_every == 0:
                callback(layer_idx + 1, num_layers)

        self.vertices      = numpy.array(vertex_list,        'f')
        self.colors        = numpy.array(color_list,         'f')
        self.arrows        = numpy.array(arrow_list,         'f')
        self.layer_markers = numpy.array(layer_markers_list, 'f')

        # by translating the arrow vertices outside of the loop, we achieve a
        # significant performance gain thanks to numpy. it would be really nice
        # if we could rotate in a similar fashion...
        self.arrows = self.arrows + self.vertices[1::2].repeat(3, 0)

        # for every pair of vertices of the model, there are 3 vertices for the arrow
        assert len(self.arrows) == ((len(self.vertices) // 2) * 3), \
            'The 2:3 ratio of model vertices to arrow vertices does not hold.'

        self.max_layers         = len(self.layer_stops) - 1
        self.num_layers_to_draw = self.max_layers
        self.arrows_enabled     = True
        self.initialized        = False
        self.vertex_count       = len(self.vertices)

        t_end = time.time()

        logging.info('Initialized Gcode model in %.2f seconds' % (t_end - t_start))
        logging.info('Vertex count: %d' % self.vertex_count)

    def movement_color(self, move):
        """
        Return the color to use for particular type of movement.
        """
        # default movement color is gray
        color = (0.6, 0.6, 0.6, 0.6)

        extruder_on = (move.flags & Movement.FLAG_EXTRUDER_ON or
                       move.delta_e > 0)
        outer_perimeter = (move.flags & Movement.FLAG_PERIMETER and
                           move.flags & Movement.FLAG_PERIMETER_OUTER)

        if extruder_on and outer_perimeter:
            color = (0.0, 0.875, 0.875, 0.6) # cyan
        elif extruder_on and move.flags & Movement.FLAG_PERIMETER:
            color = (0.0, 1.0, 0.0, 0.6) # green
        elif extruder_on and move.flags & Movement.FLAG_LOOP:
            color = (1.0, 0.875, 0.0, 0.6) # yellow
        elif extruder_on:
            color = (1.0, 0.0, 0.0, 0.6) # red

        return color

    # ------------------------------------------------------------------------
    # DRAWING
    # ------------------------------------------------------------------------

    def init(self):
        self.vertex_buffer       = VBO(self.vertices, 'GL_STATIC_DRAW')
        self.vertex_color_buffer = VBO(self.colors.repeat(2, 0), 'GL_STATIC_DRAW') # each pair of vertices shares the color

        if self.arrows_enabled:
            self.arrow_buffer       = VBO(self.arrows, 'GL_STATIC_DRAW')
            self.arrow_color_buffer = VBO(self.colors.repeat(3, 0), 'GL_STATIC_DRAW') # each triplet of vertices shares the color

        self.layer_marker_buffer = VBO(self.layer_markers, 'GL_STATIC_DRAW')

        self.initialized = True

    def display(self, elevation=0, eye_height=0, mode_ortho=False, mode_2d=False):
        glPushMatrix()

        offset_z = self.offset_z if not mode_2d else 0
        glTranslate(self.offset_x, self.offset_y, offset_z)

        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_COLOR_ARRAY)

        self._display_movements(elevation, eye_height, mode_ortho, mode_2d)

        if self.arrows_enabled:
            self._display_arrows()

        glDisableClientState(GL_COLOR_ARRAY)

        if self.arrows_enabled:
            self._display_layer_markers()

        glDisableClientState(GL_VERTEX_ARRAY)
        glPopMatrix()

    def _display_movements(self, elevation=0, eye_height=0, mode_ortho=False, mode_2d=False):
        self.vertex_buffer.bind()
        glVertexPointer(3, GL_FLOAT, 0, None)

        self.vertex_color_buffer.bind()
        glColorPointer(4, GL_FLOAT, 0, None)

        if mode_2d:
            glScale(1.0, 1.0, 0.0) # discard z coordinates
            start = self.layer_stops[self.num_layers_to_draw - 1]
            end   = self.layer_stops[self.num_layers_to_draw]

            glDrawArrays(GL_LINES, start, end - start)

        elif mode_ortho:
            if elevation >= 0:
                # draw layers in normal order, bottom to top
                start = 0
                end   = self.layer_stops[self.num_layers_to_draw]

                glDrawArrays(GL_LINES, start, end - start)

            else:
                # draw layers in reverse order, top to bottom
                stop_idx = self.num_layers_to_draw - 1
                while stop_idx >= 0:
                    start = self.layer_stops[stop_idx]
                    end   = self.layer_stops[stop_idx + 1]

                    glDrawArrays(GL_LINES, start, end - start)

                    stop_idx -= 1

        else: # 3d projection mode
            reverse_threshold_layer = self._layer_up_to_height(eye_height - self.offset_z)

            if reverse_threshold_layer >= 0:
                # draw layers up to (and including) the threshold in normal order, bottom to top
                normal_layers_to_draw = min(self.num_layers_to_draw, reverse_threshold_layer + 1)
                start = 0
                end   = self.layer_stops[normal_layers_to_draw]

                glDrawArrays(GL_LINES, start, end - start)

            if reverse_threshold_layer + 1 < self.num_layers_to_draw:
                # draw layers from the threshold in reverse order, top to bottom
                stop_idx = self.num_layers_to_draw - 1
                while stop_idx > reverse_threshold_layer:
                    start = self.layer_stops[stop_idx]
                    end   = self.layer_stops[stop_idx + 1]

                    glDrawArrays(GL_LINES, start, end - start)

                    stop_idx -= 1

        self.vertex_buffer.unbind()
        self.vertex_color_buffer.unbind()

    def _layer_up_to_height(self, height):
        """Return the index of the last layer lower than height."""
        for idx in range(len(self.layer_heights) - 1, -1, -1):
            if self.layer_heights[idx] < height:
                return idx

        return 0

    def _display_arrows(self):
        self.arrow_buffer.bind()
        glVertexPointer(3, GL_FLOAT, 0, None)

        self.arrow_color_buffer.bind()
        glColorPointer(4, GL_FLOAT, 0, None)

        start = (self.layer_stops[self.num_layers_to_draw - 1] // 2) * 3
        end   = (self.layer_stops[self.num_layers_to_draw] // 2) * 3

        glDrawArrays(GL_TRIANGLES, start, end - start)

        self.arrow_buffer.unbind()
        self.arrow_color_buffer.unbind()

    def _display_layer_markers(self):
        self.layer_marker_buffer.bind()
        glVertexPointer(3, GL_FLOAT, 0, None)

        start = self.layer_marker_stops[self.num_layers_to_draw - 1]
        end   = self.layer_marker_stops[self.num_layers_to_draw]

        glColor4f(0.6, 0.6, 0.6, 0.6)
        glDrawArrays(GL_TRIANGLES, start, end - start)

        self.layer_marker_buffer.unbind()
Exemple #31
0
    glfw.set_scroll_callback(theWindow, window_scroll_callback)

    # create VBOs to store vertices, normals and elements
    cubeDataVBO = VBO(cubeData, usage='GL_STATIC_DRAW')
    cubeDataVBO.create_buffers()

    sphereDataVBO = VBO(sphereData, usage='GL_STATIC_DRAW')
    sphereDataVBO.create_buffers()

    # create VAO to describe array information
    triangleVAO, sphereVAO = glGenVertexArrays(2)

    # bind VAO
    glBindVertexArray(triangleVAO)
    # bind data VBO
    cubeDataVBO.bind()
    cubeDataVBO.copy_data()
    glVertexAttribPointer(0, 3, GL_FLOAT,
                          GL_FALSE, 6 * ctypes.sizeof(ctypes.c_float),
                          ctypes.c_void_p(0))
    glEnableVertexAttribArray(0)
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
                          6 * ctypes.sizeof(ctypes.c_float),
                          ctypes.c_void_p(3 * ctypes.sizeof(ctypes.c_float)))
    glEnableVertexAttribArray(1)
    # unbind VBO
    cubeDataVBO.unbind()
    # unbind VAO
    glBindVertexArray(0)

    glBindVertexArray(sphereVAO)
Exemple #32
0
    glfw.set_key_callback(theWindow, window_keypress_callback)
    # disable cursor
    glfw.set_input_mode(theWindow, glfw.CURSOR, glfw.CURSOR_DISABLED)

    glfw.set_cursor_pos_callback(theWindow, window_cursor_callback)
    # initialize cursor position
    cursorPos = glfw.get_cursor_pos(theWindow)

    glfw.set_scroll_callback(theWindow, window_scroll_callback)

    vbo = VBO(vertices, 'GL_STATIC_DRAW')
    vbo.create_buffers()

    vao = glGenVertexArrays(1)
    glBindVertexArray(vao)
    vbo.bind()
    vbo.copy_data()
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(0))
    glEnableVertexAttribArray(0)
    glBindVertexArray(0)

    # compile program
    renderProgram = GLProgram(rayTracingVertexShaderSource, rayTracingFragmentShaderSource)
    renderProgram.compile_and_link()
    uniformInfos = [
        ('backColor', 'vec3f'),
        ('ambientColor', 'vec3f'),
        ('o_c', 'vec3f'),
        ('o_p', 'vec3f'),
        ('x_c', 'vec3f'),
        ('y_c', 'vec3f'),
Exemple #33
0
class Mesh(Component):
    meshes = dict()  # cache to reuse meshes
    
    @classmethod
    def fromXMLElement(cls, xmlElement, actor=None):
        return cls.getMesh(xmlElement.get('src', 'Empty'), actor)
        # NOTE If src attribute is not found in XML element, special 'Empty' mesh is used
    
    @classmethod
    def getMesh(cls, src, actor=None):
        if not src in cls.meshes:
            if src == 'Empty':
                cls.meshes[src] = EmptyMesh()  # special empty mesh to be used as a placeholder, and for empty actors
            else:
                cls.meshes[src] = Mesh(src)  # NOTE Meshes are currently shared, therefore not linked to individual actors
        return cls.meshes[src]
    
    def __init__(self, src, actor=None):
        Component.__init__(self, actor)

        # TODO Include a mesh name (e.g. 'Dragon') as ID as well as src (e.g. '../res/models/Dragon.obj')
        self.src = src
        self.filepath = Context.getInstance().getResourcePath('models', src)
        
        # OpenGL version-dependent code (NOTE assumes major version = 3)
        self.vao = None
        if Context.getInstance().GL_version_minor > 0:  # 3.1 (or greater?)
          self.vao = glGenVertexArrays(1)
        else:  # 3.0 (or less?)
          self.vao = GLuint(0)
          glGenVertexArrays(1, self.vao)
        glBindVertexArray(self.vao)

        self.loadModel(self.filepath)

        self.vbo = VBO(self.meshData, GL_STATIC_DRAW)
        self.vbo.bind()

        glEnableVertexAttribArray(0)
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*4, self.vbo+0)

        glEnableVertexAttribArray(1)
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*4, self.vbo+12)
        
        self.ebo = glGenBuffers(1)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.ebo)
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, len(self.elements)*4, self.elements, GL_STATIC_DRAW)

    def loadModel(self, filename):
        f = open(filename, 'r')
        self.meshData = []
        self.elements = []
        vertices = []
        normals = []
        texCoords = []

        for line in f:
            s = line.split()
            if len(s) > 0:
                if s[0] == 'v':
                    v = np.array([s[1], s[2], s[3]], dtype = np.float32)
                    vertices.append(v)
                elif s[0] == 'vn':
                    v = np.array([s[1], s[2], s[3]], dtype = np.float32)
                    normals.append(v)
                elif s[0] == 'vt':
                    v = np.array([s[1], s[2]], dtype = np.float32)
                    texCoords.append(v)
                elif s[0] == 'f':
                    for i in xrange(1, 4):
                        l = s[i].split('/')
                        self.meshData.append(float(vertices[int(l[0]) - 1][0]))
                        self.meshData.append(float(vertices[int(l[0]) - 1][1]))
                        self.meshData.append(float(vertices[int(l[0]) - 1][2]))
                        self.meshData.append(float(normals[int(l[2]) - 1][0]))
                        self.meshData.append(float(normals[int(l[2]) - 1][1]))
                        self.meshData.append(float(normals[int(l[2]) - 1][2]))
                        self.elements.append(len(self.elements))

        self.meshData = np.array(self.meshData, dtype = np.float32)
        self.elements = np.array(self.elements, dtype = np.uint32)

    def render(self):
        glBindVertexArray(self.vao)
        glDrawElements(GL_TRIANGLES, self.elements.size, GL_UNSIGNED_INT, None)
    
    def toXMLElement(self):
        xmlElement = Component.toXMLElement(self)
        xmlElement.set('src', self.src)
        return xmlElement
    
    def toString(self, indent=""):
        return indent + "Mesh: { src: \"" + self.src + "\" }"
    
    def __str__(self):
        return self.toString()
Exemple #34
0
class GcodeModel(Model):
    """
    Model for displaying Gcode data.
    """
    # define color names for different types of extruder movements
    color_map = {
        'red':    [1.0, 0.0, 0.0, 0.6],
        'yellow': [1.0, 0.875, 0.0, 0.6],
        'orange': [1.0, 0.373, 0.0, 0.6],
        'green':  [0.0, 1.0, 0.0, 0.6],
        'cyan':   [0.0, 0.875, 0.875, 0.6],
        'gray':   [0.6, 0.6, 0.6, 0.6],
    }

    # vertices for arrow to display the direction of movement
    arrow = numpy.require([
        [0.0, 0.0, 0.0],
        [0.4, -0.1, 0.0],
        [0.4, 0.1, 0.0],
    ], 'f')

    def __init__(self, model_data):
        Model.__init__(self)

        t_start = time.time()

        self.create_vertex_arrays(model_data)

        self.max_layers         = len(self.layer_stops) - 1
        self.num_layers_to_draw = self.max_layers
        self.arrows_enabled     = True
        self.initialized        = False

        t_end = time.time()

        logging.info('Initialized Gcode model in %.2f seconds' % (t_end - t_start))
        logging.info('Vertex count: %d' % len(self.vertices))

    def create_vertex_arrays(self, model_data):
        """
        Construct vertex lists from gcode data.
        """
        vertex_list = []
        color_list = []
        self.layer_stops = [0]
        arrow_list = []

        for layer in model_data:
            for movement in layer:
                a, b = movement.point_a, movement.point_b
                vertex_list.append([a.x, a.y, a.z])
                vertex_list.append([b.x, b.y, b.z])

                arrow = self.arrow
                # position the arrow with respect to movement
                arrow = vector.rotate(arrow, movement.angle(), 0.0, 0.0, 1.0)
                arrow_list.extend(arrow)

                vertex_color = self.movement_color(movement)
                color_list.append(vertex_color)

            self.layer_stops.append(len(vertex_list))

        self.vertices = numpy.array(vertex_list, 'f')
        self.colors = numpy.array(color_list, 'f')
        self.arrows = numpy.array(arrow_list, 'f')
        # by translating the arrow vertices outside of the loop, we achieve a
        # significant performance gain thanks to numpy. it would be really nice
        # if we could rotate in a similar fashion...
        self.arrows = self.arrows + self.vertices[1::2].repeat(3, 0)

        # for every pair of vertices of the model, there are 3 vertices for the arrow
        assert len(self.arrows) == ((len(self.vertices) // 2) * 3), \
            'The 2:3 ratio of model vertices to arrow vertices does not hold.'

    def movement_color(self, movement):
        """
        Return the color to use for particular type of movement.
        """
        if not movement.extruder_on:
            color = self.color_map['gray']
        elif movement.is_loop:
            color = self.color_map['yellow']
        elif movement.is_perimeter and movement.is_perimeter_outer:
            color = self.color_map['cyan']
        elif movement.is_perimeter:
            color = self.color_map['green']
        else:
            color = self.color_map['red']

        return color

    # ------------------------------------------------------------------------
    # DRAWING
    # ------------------------------------------------------------------------

    def init(self):
        self.vertex_buffer       = VBO(self.vertices, 'GL_STATIC_DRAW')
        self.vertex_color_buffer = VBO(self.colors.repeat(2, 0), 'GL_STATIC_DRAW') # each pair of vertices shares the color

        if self.arrows_enabled:
            self.arrow_buffer       = VBO(self.arrows, 'GL_STATIC_DRAW')
            self.arrow_color_buffer = VBO(self.colors.repeat(3, 0), 'GL_STATIC_DRAW') # each triplet of vertices shares the color

        self.initialized = True

    def display(self, mode_2d=False):
        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_COLOR_ARRAY)

        self._display_movements(mode_2d)

        if self.arrows_enabled:
            self._display_arrows()

        glDisableClientState(GL_COLOR_ARRAY)
        glDisableClientState(GL_VERTEX_ARRAY)

    def _display_movements(self, mode_2d=False):
        self.vertex_buffer.bind()
        glVertexPointer(3, GL_FLOAT, 0, None)

        self.vertex_color_buffer.bind()
        glColorPointer(4, GL_FLOAT, 0, None)

        if mode_2d:
            glScale(1.0, 1.0, 0.0) # discard z coordinates
            start = self.layer_stops[self.num_layers_to_draw - 1]
            end   = self.layer_stops[self.num_layers_to_draw] - start
        else: # 3d
            start = 0
            end   = self.layer_stops[self.num_layers_to_draw]

        glDrawArrays(GL_LINES, start, end)

        self.vertex_buffer.unbind()
        self.vertex_color_buffer.unbind()

    def _display_arrows(self):
        self.arrow_buffer.bind()
        glVertexPointer(3, GL_FLOAT, 0, None)

        self.arrow_color_buffer.bind()
        glColorPointer(4, GL_FLOAT, 0, None)

        start = (self.layer_stops[self.num_layers_to_draw - 1] // 2) * 3
        end   = (self.layer_stops[self.num_layers_to_draw] // 2) * 3

        glDrawArrays(GL_TRIANGLES, start, end - start)

        self.arrow_buffer.unbind()
        self.arrow_color_buffer.unbind()
Exemple #35
0
class model:

    ''' class for STL file / 3d model '''

    def __init__(self, stl_data, batchh=None):
        ''' initialise model data'''
        vert, norm = stl_data
        self.vertices = numpy.array(vert, dtype=GLfloat)
        self.normals = numpy.array(norm, dtype=GLfloat)
        self.vertex_buffer = VBO(self.vertices, 'GL_STATIC_DRAW')
        self.normal_buffer = VBO(self.normals, 'GL_STATIC_DRAW')

        # calculate model scale
        self.corner = self.vertices.transpose().min(1)
        self.corner2 = self.vertices.transpose().max(1)
        self.scale = abs(self.corner) + abs(self.corner2)
        self.scale = max(self.scale[0], self.scale[1], self.scale[2])
        print 'STL File loaded in: ', loadtime
        print 'Object information'
        print 'corner 1: ', self.corner
        print 'corner 2: ', self.corner2
        print 'object scale: ', self.scale

    def draw(self):
        ''' draw model on screen '''
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        glLoadIdentity()

        # center the model
        glTranslate(window.width/2, window.height/2, -150)

        # scale the model
        glScale(150/self.scale, 150/self.scale, 150/self.scale)

        # draw grid and coordinate lines
        draw_grid()
        draw_xyz(0, 0, 0, -20, -20)

        # demo rotation
        glRotate(rot, 1, 0, 0)
        glRotate(rot2, 0, 1, 0)
        glRotate(rot3, 0, 0, 1)

        self.vertex_buffer.bind()
        glVertexPointer(3, GL_FLOAT, 0, None)
        self.normal_buffer.bind()
        glNormalPointer(GL_FLOAT, 0, None)

        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_NORMAL_ARRAY)

        glDrawArrays(GL_TRIANGLES, 0, len(self.vertices))

        glDisableClientState(GL_NORMAL_ARRAY)
        glDisableClientState(GL_VERTEX_ARRAY)

        self.normal_buffer.unbind()
        self.vertex_buffer.unbind()

        glPopMatrix()
Exemple #36
0
class THRenderer:
    def __init__(self, parent_view):
        self.parent = parent_view
        self.restart()

    def restart(self):
        self.__deferred_list_filled = []
        self.__deferred_list_outline = []

    def initializeGL(self, glshared):

        self.__filled_shader = glshared.shader_cache.get(
            "via_filled_vertex_shader", "via_filled_fragment_shader")

        self.__outline_shader = glshared.shader_cache.get(
            "via_outline_vertex_shader", "frag1"
        )

        self.__filled_vao = VAO()
        self.__outline_vao = VAO()

        # Build geometry for filled rendering using the frag shader for circle borders
        filled_points = [
            ((-1, -1), ),
            ((1, -1), ),
            ((-1, 1), ),
            ((1,  1), ),
        ]
        ar = numpy.array(
            filled_points
            , dtype=[("vertex", numpy.float32, 2)])

        self.__sq_vbo = VBO(ar, GL.GL_STATIC_DRAW)
        with self.__filled_vao, self.__sq_vbo:
            vbobind(self.__filled_shader, ar.dtype, "vertex").assign()


        # Build and bind an instance array for the "filled" geometry
        self.filled_instance_dtype = numpy.dtype([
            ("pos", numpy.float32, 2),
            ("r", numpy.float32, 1),
            ("r_inside_frac_sq", numpy.float32, 1),
            ("color", numpy.float32, 4)
        ])

        # Use a fake array to get a zero-length VBO for initial binding
        filled_instance_array = numpy.ndarray(0, dtype=self.filled_instance_dtype)
        self.filled_instance_vbo = VBO(filled_instance_array)

        with self.__filled_vao, self.filled_instance_vbo:
            vbobind(self.__filled_shader, self.filled_instance_dtype, "pos", div=1).assign()
            vbobind(self.__filled_shader, self.filled_instance_dtype, "r", div=1).assign()
            vbobind(self.__filled_shader, self.filled_instance_dtype, "r_inside_frac_sq", div=1).assign()
            vbobind(self.__filled_shader, self.filled_instance_dtype, "color", div=1).assign()


        # Build geometry for outline rendering
        outline_points = []
        for i in numpy.linspace(0, math.pi * 2, N_OUTLINE_SEGMENTS, False):
            outline_points.append(((math.cos(i), math.sin(i)), ))

        ar = numpy.array(
            outline_points
            , dtype=[("vertex", numpy.float32, 2)])

        self.__outline_vbo = VBO(ar, GL.GL_STATIC_DRAW)
        with self.__outline_vao, self.__outline_vbo:
            vbobind(self.__outline_shader, ar.dtype, "vertex").assign()

        # Build instance for outline rendering
        # We don't have an inner 'r' for this because we just do two instances per vertex
        self.outline_instance_dtype = numpy.dtype([
            ("pos", numpy.float32, 2),
            ("r", numpy.float32, 1),
            ("color", numpy.float32, 4)
        ])

        # Use a fake array to get a zero-length VBO for initial binding
        outline_instance_array = numpy.ndarray(0, dtype=self.outline_instance_dtype)
        self.outline_instance_vbo = VBO(outline_instance_array)

        with self.__outline_vao, self.outline_instance_vbo:
            vbobind(self.__outline_shader, self.outline_instance_dtype, "pos", div=1).assign()
            vbobind(self.__outline_shader, self.outline_instance_dtype, "r", div=1).assign()
            vbobind(self.__outline_shader, self.outline_instance_dtype, "color", div=1).assign()

    def deferred(self, center, r1, r2, rs, render_hint=RENDER_HINT_NORMAL):
        if rs & RENDER_OUTLINES:
            self.__deferred_list_outline.append((center, r1, r2, rs))
        else:
            self.__deferred_list_filled.append((center, r1, r2, rs))

    def render(self, mat):
        self.render_filled(mat)
        self.render_outline(mat)

    def render_filled(self, mat):
        count = len(self.__deferred_list_filled)

        if count == 0:
            return

        # Resize instance data array
        instance_array = numpy.ndarray(count, dtype = self.filled_instance_dtype)

        for n, (center, r1, r2, rs) in enumerate(self.__deferred_list_filled):
            color_a = [0.6, 0.6, 0.6, 1]

            # HACK, color object
            color_a = self.parent.sel_colormod(rs & RENDER_SELECTED, color_a)

            # frag shader uses pythag to determine is frag is within
            # shaded area. Precalculate comparison term
            r_frac_sq = (r2 / r1) ** 2
            instance_array[n] = (center, r1, r_frac_sq, color_a)

        self.filled_instance_vbo.data = instance_array
        self.filled_instance_vbo.size = None
        self.filled_instance_vbo.copied = False
        self.filled_instance_vbo.bind()

        with self.__filled_shader, self.__filled_vao, self.filled_instance_vbo, self.__sq_vbo:
            GL.glUniformMatrix3fv(self.__filled_shader.uniforms.mat, 1, True, mat.ctypes.data_as(GLI.c_float_p))
            GL.glDrawArraysInstanced(GL.GL_TRIANGLE_STRIP, 0, 4, count)

    def render_outline(self, mat):
        count = 0
        for center, r1, r2, rs in self.__deferred_list_outline:
            if r2 == 0:
                count += 1
            else:
                count += 2

        if count == 0:
            return

        # Resize instance data array
        instance_array = numpy.ndarray(count, dtype = self.outline_instance_dtype)

        n = 0
        for center, r1, r2, rs in self.__deferred_list_outline:
            color_a = [0.6, 0.6, 0.6, 1]

            # HACK, color object
            color_a = self.parent.sel_colormod(rs & RENDER_SELECTED, color_a)

            instance_array[n] = (center, r1, color_a)
            n += 1

            if r2 > 0:
                instance_array[n] = (center, r2, color_a)
                n += 1

        self.outline_instance_vbo.data = instance_array
        self.outline_instance_vbo.size = None
        self.outline_instance_vbo.copied = False
        self.outline_instance_vbo.bind()

        with self.__outline_shader, self.__outline_vao, self.outline_instance_vbo, self.__sq_vbo:
            GL.glUniformMatrix3fv(self.__outline_shader.uniforms.mat, 1, True, mat.ctypes.data_as(GLI.c_float_p))
            GL.glDrawArraysInstanced(GL.GL_LINE_LOOP, 0, N_OUTLINE_SEGMENTS, count)
class PolygonVBOPair:
    __RESTART_INDEX = 2 ** 32 - 1

    def __init__(self, view):
        """
        :type gls: pcbre.ui.gl.glshared.GLShared
        :param gls:
        :return:
        """
        self.__view = view
        self.__gls = view.gls

        self.__position_list = []
        self.__position_lookup = {}

        # Known_polys is a list of (start,end) indicies in self.__index_list
        self.__tri_draw_ranges = {}
        self.__outline_draw_ranges = {}

        self.__tri_index_list = []
        self.__outline_index_list = []

        self.__vert_vbo_current = False
        self.__index_vbo_current = False

        self.restart()
        

    def restart(self):
        self.__deferred_tri_render_ranges = defaultdict(list)
        self.__deferred_line_render_ranges = defaultdict(list)

        
    def initializeGL(self):
        self.__vao = VAO()

        # Lookup for vertex positions
        self.__vert_vbo_dtype = numpy.dtype([("vertex", numpy.float32, 2)])
        self.__vert_vbo = VBO(numpy.ndarray(0, dtype=self.__vert_vbo_dtype),
                              GL.GL_DYNAMIC_DRAW)
        self.__vert_vbo_current = False

        self.__index_vbo_dtype = numpy.uint32
        self.__index_vbo = VBO(numpy.ndarray(0, dtype=self.__index_vbo_dtype), GL.GL_DYNAMIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER)
        self.__index_vbo_current = False

        self.__shader = self.__gls.shader_cache.get("vert2", "frag1")
        
        with self.__vao, self.__vert_vbo:
            vbobind(self.__shader, self.__vert_vbo_dtype, "vertex").assign()
            self.__index_vbo.bind()

    def __update_vert_vbo(self):
        if self.__vert_vbo_current or not len(self.__position_list):
            return

        ar = numpy.ndarray(len(self.__position_list), dtype=self.__vert_vbo_dtype)
        ar["vertex"] = self.__position_list
        self.__vert_vbo.data = ar
        self.__vert_vbo.size = None
        self.__vert_vbo.copied = False
        self.__vert_vbo.bind()
        self.__vert_vbo_current = True

    def __update_index_vbo(self):
        if self.__index_vbo_current or not len(self.__tri_index_list):
            return

        self.__outline_index_offset = len(self.__tri_index_list)
        self.__index_vbo.data = numpy.array(self.__tri_index_list + self.__outline_index_list, dtype=self.__index_vbo_dtype)
        self.__index_vbo.size = None
        self.__index_vbo.copied = False
        self.__index_vbo.bind()
        self.__index_vbo_current = True

    def __get_position_index(self, point):
        """
        Get the index in the point VBO for a given Point2 coordinate
        :type point: pcbre.matrix.Point2
        :param point:
        :return:
        """
        norm_pos = point.intTuple()

        try:
            return self.__position_lookup[norm_pos]
        except KeyError:
            self.__position_lookup[norm_pos] = len(self.__position_list)
            self.__position_list.append(norm_pos)
            self.__vert_vbo_current = False

        return self.__position_lookup[norm_pos]


    def __add(self, polygon):
        tris = polygon.get_tris_repr()
        tri_index_first = len(self.__tri_index_list)

        for t in tris:
            for p in t.a, t.b, t.c:
                self.__tri_index_list.append(self.__get_position_index(Point2(p.x, p.y)))

        tr = (tri_index_first, len(self.__tri_index_list))
        self.__tri_draw_ranges[polygon] = tr

        outline_index_first = len(self.__outline_index_list)
        poly_repr = polygon.get_poly_repr()
        for edge in [poly_repr.exterior] + list(poly_repr.interiors):
            for pt in edge.coords:
                self.__outline_index_list.append(self.__get_position_index(Point2(pt)))
            self.__outline_index_list.append(self.__RESTART_INDEX)

        lr = (outline_index_first, len(self.__outline_index_list))
        self.__outline_draw_ranges[polygon] = lr

        self.__index_vbo_current = False

        return tr, lr


    def deferred(self, polygon, render_settings=RENDER_STANDARD):
        if polygon in self.__tri_draw_ranges:
            trange, lrange = self.__tri_draw_ranges[polygon], self.__outline_draw_ranges[polygon]
        else:
            trange, lrange = self.__add(polygon)

        if render_settings & RENDER_OUTLINES:
            self.__deferred_line_render_ranges[render_settings].append(lrange)
        else:
            self.__deferred_tri_render_ranges[render_settings].append(trange)


    def render(self, matrix, layer):
        self.__update_vert_vbo()
        self.__update_index_vbo()

        overall_color = self.__view.color_for_layer(layer)
        sel_color  = self.__view.sel_colormod(True, overall_color)

        def _c_for_rs(rs):
            if rs & RENDER_SELECTED:
                return tuple(sel_color) + (1,)
            else:
                return tuple(overall_color) + (1,)


        with self.__shader, self.__vao:
            GL.glUniformMatrix3fv(self.__shader.uniforms.mat, 1, True, matrix.ctypes.data_as(GLI.c_float_p))

            for rs, ranges in self.__deferred_tri_render_ranges.items():
                tri_draw_list = get_consolidated_draws(ranges)
                GL.glUniform4f(self.__shader.uniforms.color, *_c_for_rs(rs))

                for first, last in tri_draw_list:
                        GL.glDrawElements(GL.GL_TRIANGLES, last - first, GL.GL_UNSIGNED_INT, ctypes.c_void_p(first * 4))

            GL.glEnable(GL.GL_PRIMITIVE_RESTART)
            GL.glPrimitiveRestartIndex(self.__RESTART_INDEX)
            for rs, ranges in self.__deferred_line_render_ranges.items():
                GL.glUniform4f(self.__shader.uniforms.color, *_c_for_rs(rs))
                line_draw_list = get_consolidated_draws(ranges)
                for first, last in line_draw_list:
                        GL.glDrawElements(GL.GL_LINE_STRIP, last - first, GL.GL_UNSIGNED_INT, ctypes.c_void_p((first + self.__outline_index_offset) * 4))
            GL.glDisable(GL.GL_PRIMITIVE_RESTART)
Exemple #38
0
class TextBatcher(object):
    __tag_type = namedtuple("render_tag", ["textinfo", "matrix", "color"])

    def __init__(self, tr):
        self.text_render = tr
        self.__cached = {}

        self.__clist = []

        self.restart()

    def restart(self):
        self.__render_tags = defaultdict(list)

    def initializeGL(self):
        # Working VBO that will contain glyph data
        self.vbo = VBO(numpy.ndarray(0, dtype=self.text_render.buffer_dtype),
                       GL.GL_DYNAMIC_DRAW, GL.GL_ARRAY_BUFFER)
        self.vao = VAO()

        with self.vao, self.vbo:
            self.text_render.b1.assign()
            self.text_render.b2.assign()
        self.__vbo_needs_update = True

    def render(self, key=None):
        if self.__vbo_needs_update:
            arr = numpy.array(self.__clist,
                              dtype=self.text_render.buffer_dtype)

            self.vbo.data = arr
            self.vbo.size = None
            self.vbo.copied = False
            self.vbo.bind()
            self.__vbo_needs_update = False

        self.text_render.updateTexture()

        with self.text_render.sdf_shader, self.text_render.tex.on(
                GL.GL_TEXTURE_2D), self.vao:
            GL.glUniform1i(self.text_render.sdf_shader.uniforms.tex1, 0)

            for tag in self.__render_tags[key]:
                mat_calc = tag.matrix
                GL.glUniformMatrix3fv(self.text_render.sdf_shader.uniforms.mat,
                                      1, True, mat_calc.astype(numpy.float32))
                GL.glUniform4f(self.text_render.sdf_shader.uniforms.color,
                               *tag.color)

                GL.glDrawArrays(GL.GL_TRIANGLES, tag.textinfo.start,
                                tag.textinfo.count)

    def submit(self, ts, mat, color, k=None):
        self.__render_tags[k].append(self.__tag_type(ts, mat, color))

    def submit_text_box(self, premat, text, box, color, k=None):
        ts = self.get_string(text)
        mat = premat.dot(ts.get_render_to_mat(box))
        self.submit(ts, mat, color, k)

    def get_string(self, text):
        if text in self.__cached:
            return self.__cached[text]

        self.__cached[text] = ti = self.text_render.getStringMetrics(text)

        ti.start = len(self.__clist)

        self.__clist.extend(ti.arr)
        ti.count = len(ti.arr)
        self.__vbo_needs_update = True
        return ti
Exemple #39
0
class TraceRender:
    def __init__(self, parent_view):
        self.parent = parent_view

        self.restart()

    def initializeGL(self, gls):
        self.__uniform_shader_vao = VAO()
        self.__attribute_shader_vao = VAO()

        # Load two versions of the shader, one for rendering a single line through uniforms
        # (no additional bound instance info), and one for rendering instanced geometry

        self.__uniform_shader = gls.shader_cache.get(
            "line_vertex_shader", "frag1", defines={"INPUT_TYPE": "uniform"})
        self.__attribute_shader = gls.shader_cache.get(
            "line_vertex_shader", "frag1", defines={"INPUT_TYPE": "in"})

        # Generate geometry for trace and endcaps
        # ptid is a variable with value 0 or 1 that indicates which endpoint the geometry is associated with

        # Build trace vertex VBO and associated vertex data
        dtype = [("vertex", numpy.float32, 2), ("ptid", numpy.uint32)]
        self.working_array = numpy.zeros(NUM_ENDCAP_SEGMENTS * 2 + 2,
                                         dtype=dtype)
        self.trace_vbo = VBO(self.working_array, GL.GL_DYNAMIC_DRAW)
        self.__build_trace()

        # Now we build an index buffer that allows us to render filled geometry from the same
        # VBO.
        arr = []
        for i in range(NUM_ENDCAP_SEGMENTS - 1):
            arr.append(0)
            arr.append(i + 2)
            arr.append(i + 3)

        for i in range(NUM_ENDCAP_SEGMENTS - 1):
            arr.append(1)
            arr.append(i + NUM_ENDCAP_SEGMENTS + 2)
            arr.append(i + NUM_ENDCAP_SEGMENTS + 3)

        arr.append(2)
        arr.append(2 + NUM_ENDCAP_SEGMENTS - 1)
        arr.append(2 + NUM_ENDCAP_SEGMENTS)
        arr.append(2 + NUM_ENDCAP_SEGMENTS)
        arr.append(2 + NUM_ENDCAP_SEGMENTS * 2 - 1)
        arr.append(2)

        arr = numpy.array(arr, dtype=numpy.uint32)
        self.index_vbo = VBO(arr, target=GL.GL_ELEMENT_ARRAY_BUFFER)

        # And bind the entire state together
        with self.__uniform_shader_vao, self.trace_vbo:
            vbobind(self.__uniform_shader, self.trace_vbo.dtype,
                    "vertex").assign()
            vbobind(self.__uniform_shader, self.trace_vbo.dtype,
                    "ptid").assign()
            self.index_vbo.bind()

        self.instance_dtype = numpy.dtype([
            ("pos_a", numpy.float32, 2),
            ("pos_b", numpy.float32, 2),
            ("thickness", numpy.float32, 1),
            #("color", numpy.float32, 4)
        ])

        # Use a fake array to get a zero-length VBO for initial binding
        instance_array = numpy.ndarray(0, dtype=self.instance_dtype)
        self.instance_vbo = VBO(instance_array)

        with self.__attribute_shader_vao, self.trace_vbo:
            vbobind(self.__attribute_shader, self.trace_vbo.dtype,
                    "vertex").assign()
            vbobind(self.__attribute_shader, self.trace_vbo.dtype,
                    "ptid").assign()

        with self.__attribute_shader_vao, self.instance_vbo:
            self.__bind_pos_a = vbobind(self.__attribute_shader,
                                        self.instance_dtype,
                                        "pos_a",
                                        div=1)
            self.__bind_pos_b = vbobind(self.__attribute_shader,
                                        self.instance_dtype,
                                        "pos_b",
                                        div=1)
            self.__bind_thickness = vbobind(self.__attribute_shader,
                                            self.instance_dtype,
                                            "thickness",
                                            div=1)
            #vbobind(self.__attribute_shader, self.instance_dtype, "color", div=1).assign()
            self.__base_rebind(0)

            self.index_vbo.bind()

        self.__last_prepared = weakref.WeakKeyDictionary()

    def __base_rebind(self, base):
        self.__bind_pos_a.assign(base)
        self.__bind_pos_b.assign(base)
        self.__bind_thickness.assign(base)

    def restart(self):
        self.__deferred_layer = defaultdict(list)
        self.__prepared = False
        self.__needs_rebuild = False

    def __build_trace(self):
        # Update trace VBO
        self.working_array["vertex"][0] = (0, 0)
        self.working_array["ptid"][0] = 0
        self.working_array["vertex"][1] = (0, 0)
        self.working_array["ptid"][1] = 1

        end = Vec2(1, 0)
        for i in range(0, NUM_ENDCAP_SEGMENTS):
            theta = math.pi * i / (NUM_ENDCAP_SEGMENTS - 1) + math.pi / 2
            m = rotate(theta).dot(end.homol())
            self.working_array["vertex"][2 + i] = m[:2]
            self.working_array["ptid"][2 + i] = 0
            self.working_array["vertex"][2 + i + NUM_ENDCAP_SEGMENTS] = -m[:2]
            self.working_array["ptid"][2 + i + NUM_ENDCAP_SEGMENTS] = 1

        # Force data copy
        self.trace_vbo.copied = False
        self.trace_vbo.bind()

    def deferred_multiple(self, trace_settings, render_settings=0):
        """
        :param trace_settings: list of traces to draw and the settings for that particular trace
        :param render_settings:
        :return:
        """
        for t, tr in trace_settings:
            tr |= render_settings
            self.deferred(t, tr)

    def deferred(self, trace, render_settings, render_hint):
        assert not self.__prepared
        self.__deferred_layer[trace.layer].append((trace, render_settings))
        if trace not in self.__last_prepared:
            self.__needs_rebuild = True

    def prepare(self):
        """
        :return: Build VBOs and information for rendering pass
        """
        self.__prepared = True

        if not self.__needs_rebuild:
            return

        self.__last_prepared = weakref.WeakKeyDictionary()

        # Total trace count, across all layers
        count = sum(len(i) for i in self.__deferred_layer.values())

        # Allocate an array of that size
        instance_array = numpy.ndarray(count, dtype=self.instance_dtype)

        pos = 0
        for layer, traces in self.__deferred_layer.items():
            # We reorder the traces to batch them by outline, and net to encourage
            # maximum draw call length. The rationale is that nets are commonly selected
            # or may be commonly drawn in different colors.
            traces = sorted(traces,
                            key=lambda i:
                            (i[1] & RENDER_OUTLINES, id(i[0].net)))

            for trace, _ in traces:
                # Now insert into the array
                instance_array[pos] = (trace.p0, trace.p1, trace.thickness / 2)

                # And memoize where the trace occurs
                self.__last_prepared[trace] = pos

                pos += 1

        # Force full resend of VBO
        self.instance_vbo.data = instance_array
        self.instance_vbo.size = None
        self.instance_vbo.copied = False
        self.instance_vbo.bind()

    def render_deferred_layer(self, mat, layer):
        if not self.__prepared:
            self.prepare()

        trace_settings = self.__deferred_layer[layer]

        count = len(trace_settings)
        if count == 0:
            return

        # key format: is_selected, is_outline
        draw_bins = defaultdict(list)
        draw_range_bins = dict()

        # Bin the traces by draw call
        for t, tr in trace_settings:
            is_selected = bool(tr & RENDER_SELECTED)
            is_outline = bool(tr & RENDER_OUTLINES)
            draw_bins[is_selected, is_outline].append(self.__last_prepared[t])

        # Build draw ranges
        for key, bin in draw_bins.items():
            draw_range_bins[key] = get_consolidated_draws_1(draw_bins[key])

        # HACK / Fixme: Precalculate selected / nonselected colors
        color_a = self.parent.color_for_layer(layer) + [1]
        color_sel = self.parent.sel_colormod(True, color_a)

        has_base_instance = False
        with self.__attribute_shader, self.__attribute_shader_vao:
            # Setup overall calls
            GL.glUniformMatrix3fv(self.__attribute_shader.uniforms.mat, 1,
                                  True, mat.ctypes.data_as(GLI.c_float_p))

            for (is_selected, is_outline), ranges in draw_range_bins.items():
                if is_selected:
                    color = color_sel
                else:
                    color = color_a

                GL.glUniform4f(self.__attribute_shader.uniforms.color, *color)

                if has_base_instance:
                    # Many instances backport glDrawElementsInstancedBaseInstance
                    # This is faster than continually rebinding, so support if possible
                    if not is_outline:
                        for first, last in ranges:
                            # filled traces come first in the array
                            GL.glDrawElementsInstancedBaseInstance(
                                GL.GL_TRIANGLES,
                                TRIANGLES_SIZE, GL.GL_UNSIGNED_INT,
                                ctypes.c_void_p(0), last - first, first)
                    else:
                        for first, last in ranges:
                            # Then outline traces. We reuse the vertex data for the outside
                            GL.glDrawArraysInstancedBaseInstance(
                                GL.GL_LINE_LOOP, 2, NUM_ENDCAP_SEGMENTS * 2,
                                last - first, first)
                else:
                    with self.instance_vbo:
                        if not is_outline:
                            for first, last in ranges:
                                # filled traces come first in the array
                                self.__base_rebind(first)
                                GL.glDrawElementsInstanced(
                                    GL.GL_TRIANGLES,
                                    TRIANGLES_SIZE, GL.GL_UNSIGNED_INT,
                                    ctypes.c_void_p(0), last - first)
                        else:
                            for first, last in ranges:
                                self.__base_rebind(first)
                                # Then outline traces. We reuse the vertex data for the outside
                                GL.glDrawArraysInstanced(
                                    GL.GL_LINE_LOOP, 2,
                                    NUM_ENDCAP_SEGMENTS * 2, last - first)

    # Immediate-mode render of a single trace
    # SLOW (at least for bulk-rendering)
    # Useful for rendering UI elements
    def render(self, mat, trace, render_settings=RENDER_STANDARD):
        color_a = self.parent.color_for_trace(trace) + [1]
        color_a = self.parent.sel_colormod(render_settings & RENDER_SELECTED,
                                           color_a)
        with self.__uniform_shader, self.__uniform_shader_vao:
            GL.glUniform1f(self.__uniform_shader.uniforms.thickness,
                           trace.thickness / 2)
            GL.glUniform2f(self.__uniform_shader.uniforms.pos_a, trace.p0.x,
                           trace.p0.y)
            GL.glUniform2f(self.__uniform_shader.uniforms.pos_b, trace.p1.x,
                           trace.p1.y)
            GL.glUniformMatrix3fv(self.__uniform_shader.uniforms.mat, 1, True,
                                  mat.ctypes.data_as(GLI.c_float_p))
            GL.glUniform4f(self.__uniform_shader.uniforms.color, *color_a)

            if render_settings & RENDER_OUTLINES:
                GL.glDrawArrays(GL.GL_LINE_LOOP, 2, NUM_ENDCAP_SEGMENTS * 2)
            else:
                GL.glDrawElements(GL.GL_TRIANGLES, TRIANGLES_SIZE,
                                  GL.GL_UNSIGNED_INT, ctypes.c_void_p(0))
Exemple #40
0
class TextBatcher:
    _render_tag = namedtuple("_render_tag", ["textinfo", "matrix", "color"])

    def __init__(self, tr: 'TextRender') -> None:
        self.text_render = tr
        self.__cached: Dict[str, '_StringMetrics'] = {}
        self._va = VA_tex(1024)

        self.restart()

    def restart(self) -> None:
        self.__render_tags: Dict[
            Any, List['TextBatcher._render_tag']] = defaultdict(list)
        self._va.clear()

    def initializeGL(self) -> None:
        # Working VBO that will contain glyph data
        self.vbo = VBO(numpy.ndarray([], dtype=self.text_render.buffer_dtype),
                       GL.GL_DYNAMIC_DRAW, GL.GL_ARRAY_BUFFER)
        self.vao = VAO()

        with self.vao, self.vbo:
            self.text_render.b1.assign()
            self.text_render.b2.assign()

        self.__vbo_needs_update = True

    def render(self, key: Any = None) -> None:
        return
        if self.__vbo_needs_update:

            self.vbo.data = self._va.buffer()[:]
            self.vbo.bind()
            self.__vbo_needs_update = False

        self.text_render.updateTexture()

        with self.text_render.sdf_shader.program, self.text_render.tex.on(
                GL.GL_TEXTURE_2D), self.vao:
            GL.glUniform1i(self.text_render.sdf_shader.program.uniforms.tex1,
                           0)
            GL.glUniform4ui(self.text_render.sdf_shader.uniforms.layer_info,
                            255, COL_TEXT, 0, 255)

            for tag in self.__render_tags[key]:
                mat_calc = tag.matrix
                GL.glUniformMatrix3fv(self.text_render.sdf_shader.uniforms.mat,
                                      1, True, mat_calc.astype(numpy.float32))
                GL.glDrawArrays(GL.GL_TRIANGLES, tag.textinfo.start,
                                tag.textinfo.count)

    def submit(self,
               ts: '_StringMetrics',
               mat: 'npt.NDArray[numpy.float64]',
               color: Any,
               k: Any = None) -> None:
        self.__render_tags[k].append(self._render_tag(ts, mat, color))

    def submit_text_box(self,
                        premat: 'npt.NDArray[numpy.float64]',
                        text: str,
                        box: Rect,
                        color: Any,
                        k: Any = None) -> None:
        ts = self.get_string(text)
        mat = premat.dot(ts.get_render_to_mat(box))
        self.submit(ts, mat, color, k)

    def get_string(self, text: str) -> '_StringMetrics':
        if text in self.__cached:
            return self.__cached[text]

        self.__cached[text] = ti = self.text_render.getStringMetrics(text)

        ti.start = self._va.tell()

        self._va.extend(ti.arr)

        ti.count = ti.arr.count()
        self.__vbo_needs_update = True
        return ti
Exemple #41
0
    glfw.set_input_mode(theWindow, glfw.CURSOR, glfw.CURSOR_DISABLED)

    glfw.set_cursor_pos_callback(theWindow, window_cursor_callback)
    # initialize cursor position
    cursorPos = glfw.get_cursor_pos(theWindow)

    glfw.set_scroll_callback(theWindow, window_scroll_callback)

    vertexVBO = VBO(vertices, usage='GL_STATIC_DRAW')
    vertexVBO.create_buffers()
    textureVBO = VBO(textureVertices, usage='GL_STATIC_DRAW')
    textureVBO.create_buffers()

    frameVAO = glGenVertexArrays(1)
    glBindVertexArray(frameVAO)
    vertexVBO.bind()
    vertexVBO.copy_data()
    glVertexAttribPointer(0, 3, GL_FLOAT,
                          GL_FALSE, 3 * ctypes.sizeof(ctypes.c_float),
                          ctypes.c_void_p(0))
    glEnableVertexAttribArray(0)
    glBindVertexArray(0)

    textureVAO = glGenVertexArrays(1)
    glBindVertexArray(textureVAO)
    textureVBO.bind()
    textureVBO.copy_data()
    glVertexAttribPointer(0, 3, GL_FLOAT,
                          GL_FALSE, 5 * ctypes.sizeof(ctypes.c_float),
                          ctypes.c_void_p(0))
    glEnableVertexAttribArray(0)
Exemple #42
0
    # disable cursor
    glfw.set_input_mode(theWindow, glfw.CURSOR, glfw.CURSOR_DISABLED)

    glfw.set_cursor_pos_callback(theWindow, window_cursor_callback)
    # initialize cursor position
    cursorPos = glfw.get_cursor_pos(theWindow)

    glfw.set_scroll_callback(theWindow, window_scroll_callback)

    sphereDataVBO = VBO(sphereData, usage='GL_STATIC_DRAW')
    sphereDataVBO.create_buffers()

    sphereVAO = glGenVertexArrays(1)

    glBindVertexArray(sphereVAO)
    sphereDataVBO.bind()
    sphereDataVBO.copy_data()
    glVertexAttribPointer(0, 3, GL_FLOAT,
                          GL_FALSE, 6 * ctypes.sizeof(ctypes.c_float),
                          ctypes.c_void_p(0))
    glEnableVertexAttribArray(0)
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
                          6 * ctypes.sizeof(ctypes.c_float),
                          ctypes.c_void_p(3 * ctypes.sizeof(ctypes.c_float)))
    glEnableVertexAttribArray(1)
    sphereDataVBO.unbind()
    glBindVertexArray(0)

    cylinderDataVBO = VBO(cylinderData, usage='GL_STATIC_DRAW')
    cylinderDataVBO.create_buffers()
Exemple #43
0
    # create window
    theWindow = glfw.create_window(windowSize[0], windowSize[1],
                                   'Audio Oscilloscope', None, None)
    # make window the current context
    glfw.make_context_current(theWindow)

    # enable z-buffer
    glEnable(GL_DEPTH_TEST)

    dataVBO = VBO(dataBuffer, usage='GL_STATIC_DRAW')

    dataVAO = glGenVertexArrays(1)

    glBindVertexArray(dataVAO)
    dataVBO.bind()
    dataVBO.copy_data()
    glVertexAttribPointer(0, 2, GL_FLOAT,
                          GL_FALSE, 2 * ctypes.sizeof(ctypes.c_float),
                          ctypes.c_void_p(0))
    glEnableVertexAttribArray(0)
    dataVBO.unbind()
    glBindVertexArray(0)

    renderProgram = GLProgram(waveVertexShaderSource, waveFragmentShaderSource)
    renderProgram.compile_and_link()

    waveColorUniform = GLUniform(renderProgram.get_program_id(), 'waveColor',
                                 'vec3f')

    # change drawing mode
Exemple #44
0
class PolygonVBOPair:
    __RESTART_INDEX = 2**32 - 1

    def __init__(self, view):
        """
        :type gls: pcbre.ui.gl.glshared.GLShared
        :param gls:
        :return:
        """
        self.__view = view
        self.__gls = view.gls

        self.__position_list = []
        self.__position_lookup = {}

        # Known_polys is a list of (start,end) indicies in self.__index_list
        self.__tri_draw_ranges = {}
        self.__outline_draw_ranges = {}

        self.__tri_index_list = []
        self.__outline_index_list = []

        self.__vert_vbo_current = False
        self.__index_vbo_current = False

        self.restart()

    def restart(self):
        self.__deferred_tri_render_ranges = defaultdict(list)
        self.__deferred_line_render_ranges = defaultdict(list)

    def initializeGL(self):
        self.__vao = VAO()

        # Lookup for vertex positions
        self.__vert_vbo_dtype = numpy.dtype([("vertex", numpy.float32, 2)])
        self.__vert_vbo = VBO(numpy.ndarray(0, dtype=self.__vert_vbo_dtype),
                              GL.GL_DYNAMIC_DRAW)
        self.__vert_vbo_current = False

        self.__index_vbo_dtype = numpy.uint32
        self.__index_vbo = VBO(numpy.ndarray(0, dtype=self.__index_vbo_dtype),
                               GL.GL_DYNAMIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER)
        self.__index_vbo_current = False

        self.__shader = self.__gls.shader_cache.get("vert2", "frag1")

        with self.__vao, self.__vert_vbo:
            vbobind(self.__shader, self.__vert_vbo_dtype, "vertex").assign()
            self.__index_vbo.bind()

    def __update_vert_vbo(self):
        if self.__vert_vbo_current or not len(self.__position_list):
            return

        ar = numpy.ndarray(len(self.__position_list),
                           dtype=self.__vert_vbo_dtype)
        ar["vertex"] = self.__position_list
        self.__vert_vbo.data = ar
        self.__vert_vbo.size = None
        self.__vert_vbo.copied = False
        self.__vert_vbo.bind()
        self.__vert_vbo_current = True

    def __update_index_vbo(self):
        if self.__index_vbo_current or not len(self.__tri_index_list):
            return

        self.__outline_index_offset = len(self.__tri_index_list)
        self.__index_vbo.data = numpy.array(self.__tri_index_list +
                                            self.__outline_index_list,
                                            dtype=self.__index_vbo_dtype)
        self.__index_vbo.size = None
        self.__index_vbo.copied = False
        self.__index_vbo.bind()
        self.__index_vbo_current = True

    def __get_position_index(self, point):
        """
        Get the index in the point VBO for a given Point2 coordinate
        :type point: pcbre.matrix.Point2
        :param point:
        :return:
        """
        norm_pos = point.intTuple()

        try:
            return self.__position_lookup[norm_pos]
        except KeyError:
            self.__position_lookup[norm_pos] = len(self.__position_list)
            self.__position_list.append(norm_pos)
            self.__vert_vbo_current = False

        return self.__position_lookup[norm_pos]

    def __add(self, polygon):
        tris = polygon.get_tris_repr()
        tri_index_first = len(self.__tri_index_list)

        for t in tris:
            for p in t.a, t.b, t.c:
                self.__tri_index_list.append(
                    self.__get_position_index(Point2(p.x, p.y)))

        tr = (tri_index_first, len(self.__tri_index_list))
        self.__tri_draw_ranges[polygon] = tr

        outline_index_first = len(self.__outline_index_list)
        poly_repr = polygon.get_poly_repr()
        for edge in [poly_repr.exterior] + list(poly_repr.interiors):
            for pt in edge.coords:
                self.__outline_index_list.append(
                    self.__get_position_index(Point2(pt)))
            self.__outline_index_list.append(self.__RESTART_INDEX)

        lr = (outline_index_first, len(self.__outline_index_list))
        self.__outline_draw_ranges[polygon] = lr

        self.__index_vbo_current = False

        return tr, lr

    def deferred(self, polygon, render_settings=RENDER_STANDARD):
        if polygon in self.__tri_draw_ranges:
            trange, lrange = self.__tri_draw_ranges[
                polygon], self.__outline_draw_ranges[polygon]
        else:
            trange, lrange = self.__add(polygon)

        if render_settings & RENDER_OUTLINES:
            self.__deferred_line_render_ranges[render_settings].append(lrange)
        else:
            self.__deferred_tri_render_ranges[render_settings].append(trange)

    def render(self, matrix, layer):
        self.__update_vert_vbo()
        self.__update_index_vbo()

        overall_color = self.__view.color_for_layer(layer)
        sel_color = self.__view.sel_colormod(True, overall_color)

        def _c_for_rs(rs):
            if rs & RENDER_SELECTED:
                return tuple(sel_color) + (1, )
            else:
                return tuple(overall_color) + (1, )

        with self.__shader, self.__vao:
            GL.glUniformMatrix3fv(self.__shader.uniforms.mat, 1, True,
                                  matrix.ctypes.data_as(GLI.c_float_p))

            for rs, ranges in self.__deferred_tri_render_ranges.items():
                tri_draw_list = get_consolidated_draws(ranges)
                GL.glUniform4f(self.__shader.uniforms.color, *_c_for_rs(rs))

                for first, last in tri_draw_list:
                    GL.glDrawElements(GL.GL_TRIANGLES, last - first,
                                      GL.GL_UNSIGNED_INT,
                                      ctypes.c_void_p(first * 4))

            GL.glEnable(GL.GL_PRIMITIVE_RESTART)
            GL.glPrimitiveRestartIndex(self.__RESTART_INDEX)
            for rs, ranges in self.__deferred_line_render_ranges.items():
                GL.glUniform4f(self.__shader.uniforms.color, *_c_for_rs(rs))
                line_draw_list = get_consolidated_draws(ranges)
                for first, last in line_draw_list:
                    GL.glDrawElements(
                        GL.GL_LINE_STRIP, last - first, GL.GL_UNSIGNED_INT,
                        ctypes.c_void_p(
                            (first + self.__outline_index_offset) * 4))
            GL.glDisable(GL.GL_PRIMITIVE_RESTART)
Exemple #45
0
class _THBatch:
    def __init__(self, parent):
        self.parent = parent
        self.restart()
        self.initialized = False

    def restart(self):
        self.__deferred_list_filled = []
        self.__deferred_list_outline = []

    def _initializeGL(self):
        self.initialized = True

        self.__filled_vao = VAO()
        self.__outline_vao = VAO()

        with self.__filled_vao, self.parent._sq_vbo:
            vbobind(self.parent._filled_shader, self.parent._sq_vbo.data.dtype, "vertex").assign()

        # Use a fake array to get a zero-length VBO for initial binding
        filled_instance_array = numpy.ndarray(0, dtype=self.parent._filled_instance_dtype)
        self.filled_instance_vbo = VBO(filled_instance_array)

        with self.__filled_vao, self.filled_instance_vbo:
            vbobind(self.parent._filled_shader, self.parent._filled_instance_dtype, "pos", div=1).assign()
            vbobind(self.parent._filled_shader, self.parent._filled_instance_dtype, "r", div=1).assign()
            vbobind(self.parent._filled_shader, self.parent._filled_instance_dtype, "r_inside_frac_sq", div=1).assign()
            vbobind(self.parent._filled_shader, self.parent._filled_instance_dtype, "color", div=1).assign()

        with self.__outline_vao, self.parent._outline_vbo:
            vbobind(self.parent._outline_shader, self.parent._outline_vbo.data.dtype, "vertex").assign()

        # Build instance for outline rendering
        # We don't have an inner 'r' for this because we just do two instances per vertex

        # Use a fake array to get a zero-length VBO for initial binding
        outline_instance_array = numpy.ndarray(0, dtype=self.parent._outline_instance_dtype)
        self.outline_instance_vbo = VBO(outline_instance_array)

        with self.__outline_vao, self.outline_instance_vbo:
            vbobind(self.parent._outline_shader, self.parent._outline_instance_dtype, "pos", div=1).assign()
            vbobind(self.parent._outline_shader, self.parent._outline_instance_dtype, "r", div=1).assign()
            vbobind(self.parent._outline_shader, self.parent._outline_instance_dtype, "color", div=1).assign()

    def deferred(self, center, r1, r2, rs, render_hint=RENDER_HINT_NORMAL):
        if rs & RENDER_OUTLINES:
            self.__deferred_list_outline.append((center, r1, r2, rs))
        else:
            self.__deferred_list_filled.append((center, r1, r2, rs))

    def prepare(self):
        self.__prepare_filled()
        self.__prepare_outline()

    def __prepare_filled(self):
        if not self.initialized:
            self._initializeGL()

        count = len(self.__deferred_list_filled)
        self.__filled_count = count

        if count == 0:
            return

        # Resize instance data array
        instance_array = numpy.ndarray(count, dtype = self.parent._filled_instance_dtype)

        color_a = [0.6, 0.6, 0.6, 1]

        for n, (center, r1, r2, rs) in enumerate(self.__deferred_list_filled):

            # HACK, color object
            color_mod = self.parent.parent.sel_colormod(rs & RENDER_SELECTED, color_a)

            # frag shader uses pythag to determine is frag is within
            # shaded area. Precalculate comparison term
            r_frac_sq = (r2 / r1) ** 2
            instance_array[n] = (center, r1, r_frac_sq, color_mod)

        self.filled_instance_vbo.data = instance_array
        self.filled_instance_vbo.size = None
        self.filled_instance_vbo.copied = False
        self.filled_instance_vbo.bind()

    def __prepare_outline(self):
        count = 0
        for center, r1, r2, rs in self.__deferred_list_outline:
            if r2 == 0:
                count += 1
            else:
                count += 2

        self.__outline_count = count
        if count == 0:
            return


        # Resize instance data array
        instance_array = numpy.ndarray(count, dtype = self.parent._outline_instance_dtype)

        n = 0
        for center, r1, r2, rs in self.__deferred_list_outline:
            color_a = [0.6, 0.6, 0.6, 1]

            # HACK, color object
            color_a = self.parent.parent.sel_colormod(rs & RENDER_SELECTED, color_a)

            instance_array[n] = (center, r1, color_a)
            n += 1

            if r2 > 0:
                instance_array[n] = (center, r2, color_a)
                n += 1

        self.outline_instance_vbo.data = instance_array
        self.outline_instance_vbo.size = None
        self.outline_instance_vbo.copied = False
        self.outline_instance_vbo.bind()


    def render(self, mat):
        self.render_filled(mat)
        self.render_outline(mat)

    def render_filled(self, mat):
        if self.__filled_count == 0:
            return

        with self.parent._filled_shader, self.__filled_vao, self.filled_instance_vbo, self.parent._sq_vbo:
            GL.glUniformMatrix3fv(self.parent._filled_shader.uniforms.mat, 1, True, mat.ctypes.data_as(GLI.c_float_p))
            GL.glDrawArraysInstanced(GL.GL_TRIANGLE_STRIP, 0, 4, len(self.__deferred_list_filled))

    def render_outline(self, mat):
        if self.__outline_count == 0:
            return

        with self.parent._outline_shader, self.__outline_vao, self.outline_instance_vbo, self.parent._sq_vbo:
            GL.glUniformMatrix3fv(self.parent._outline_shader.uniforms.mat, 1, True, mat.ctypes.data_as(GLI.c_float_p))
            GL.glDrawArraysInstanced(GL.GL_LINE_LOOP, 0, N_OUTLINE_SEGMENTS, self.__outline_count)
Exemple #46
0
class StlModel(Model):
    """
    Model for displaying and manipulating STL data.
    """
    def load_data(self, model_data, callback=None):
        t_start = time.time()

        vertices, normals = model_data
        # convert python lists to numpy arrays for constructing vbos
        self.vertices = numpy.require(vertices, 'f')
        self.normals  = numpy.require(normals, 'f')

        self.scaling_factor = 1.0
        self.rotation_angle = {
            self.AXIS_X: 0.0,
            self.AXIS_Y: 0.0,
            self.AXIS_Z: 0.0,
        }

        self.mat_specular   = (1.0, 1.0, 1.0, 1.0)
        self.mat_shininess  = 50.0
        self.light_position = (20.0, 20.0, 20.0)

        self.initialized = False

        t_end = time.time()

        logging.info('Initialized STL model in %.2f seconds' % (t_end - t_start))
        logging.info('Vertex count: %d' % len(self.vertices))

    def normal_data_empty(self):
        """
        Return true if the model has no normal data.
        """
        empty = (self.normals.max() == 0 and self.normals.min() == 0)
        return empty

    def calculate_normals(self):
        """
        Calculate surface normals for model vertices.
        """
        a = self.vertices[0::3] - self.vertices[1::3]
        b = self.vertices[1::3] - self.vertices[2::3]
        cross = numpy.cross(a, b)

        # normalize the cross product
        magnitudes = numpy.apply_along_axis(numpy.linalg.norm, 1, cross).reshape(-1, 1)
        normals = cross / magnitudes

        # each of 3 facet vertices shares the same normal
        normals = normals.repeat(3, 0)
        return normals

    # ------------------------------------------------------------------------
    # DRAWING
    # ------------------------------------------------------------------------

    def init(self):
        """
        Create vertex buffer objects (VBOs).
        """
        self.vertex_buffer = VBO(self.vertices, 'GL_STATIC_DRAW')

        if self.normal_data_empty():
            logging.info('STL model has no normal data')
            self.normals = self.calculate_normals()

        self.normal_buffer = VBO(self.normals, 'GL_STATIC_DRAW')
        self.initialized = True

    def draw_facets(self):
        glPushMatrix()

        glEnable(GL_LIGHT0)
        glEnable(GL_LIGHT1)
        glShadeModel(GL_SMOOTH)

        # material properties (white plastic)
        glMaterial(GL_FRONT, GL_AMBIENT, (0.0, 0.0, 0.0, 1.0))
        glMaterial(GL_FRONT, GL_DIFFUSE, (0.55, 0.55, 0.55, 1.0))
        glMaterial(GL_FRONT, GL_SPECULAR, (0.7, 0.7, 0.7, 1.0))
        glMaterial(GL_FRONT, GL_SHININESS, 32.0)

        # lights properties
        glLight(GL_LIGHT0, GL_AMBIENT, (0.3, 0.3, 0.3, 1.0))
        glLight(GL_LIGHT0, GL_DIFFUSE, (0.3, 0.3, 0.3, 1.0))
        glLight(GL_LIGHT1, GL_DIFFUSE, (0.3, 0.3, 0.3, 1.0))

        # lights position
        glLightfv(GL_LIGHT0, GL_POSITION, self.light_position)
        glLightfv(GL_LIGHT1, GL_POSITION, (-20.0, -20.0, 20.0))

        glColor(1.0, 1.0, 1.0)

        ### VBO stuff

        self.vertex_buffer.bind()
        glVertexPointer(3, GL_FLOAT, 0, None)
        self.normal_buffer.bind()
        glNormalPointer(GL_FLOAT, 0, None)

        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_NORMAL_ARRAY)

        glDrawArrays(GL_TRIANGLES, 0, len(self.vertices))

        glDisableClientState(GL_NORMAL_ARRAY)
        glDisableClientState(GL_VERTEX_ARRAY)
        self.normal_buffer.unbind()
        self.vertex_buffer.unbind()

        ### end VBO stuff

        glDisable(GL_LIGHT1)
        glDisable(GL_LIGHT0)

        glPopMatrix()

    def display(self, mode_2d=False):
        glEnable(GL_LIGHTING)
        self.draw_facets()
        glDisable(GL_LIGHTING)

    # ------------------------------------------------------------------------
    # TRANSFORMATIONS
    # ------------------------------------------------------------------------

    def scale(self, factor):
        if factor != self.scaling_factor:
            logging.info('actually scaling vertices')
            self.vertices *= (factor / self.scaling_factor)
            self.scaling_factor = factor
            self.invalidate_bounding_box()
            self.modified = True

    def translate(self, x, y, z):
        self.vertices = vector.translate(self.vertices, x, y, z)
        self.invalidate_bounding_box()
        self.modified = True

    def rotate_rel(self, angle, axis):
        logging.info('rotating vertices by a relative angle of '
                     '%.2f degrees along the %s axis' %
                     (angle, self.axis_letter_map[axis]))

        angle = angle % 360
        self.vertices = vector.rotate(self.vertices, angle, *axis)
        self.rotation_angle[axis] += angle
        self.invalidate_bounding_box()
        self.modified = True

    def rotate_abs(self, angle, axis):
        angle = angle % 360
        if self.rotation_angle[axis] == angle:
            return

        logging.info('rotating vertices by an absolute angle of '
                     '%.2f degrees along the %s axis' %
                     (angle, self.axis_letter_map[axis]))
        final_matrix = vector.identity_matrix()

        # modify matrix to rotate to initial position
        for v in [self.AXIS_Z, self.AXIS_Y, self.AXIS_X]:
            matrix = vector.rotation_matrix(-self.rotation_angle[v], *v)
            final_matrix = final_matrix.dot(matrix)

        # change the angle
        self.rotation_angle[axis] = angle

        # modify matrix to rotate to new position
        for v in [self.AXIS_X, self.AXIS_Y, self.AXIS_Z]:
            matrix = vector.rotation_matrix(self.rotation_angle[v], *v)
            final_matrix = final_matrix.dot(matrix)

        self.vertices = self.vertices.dot(final_matrix)
        self.invalidate_bounding_box()
        self.modified = True
Exemple #47
0
class Drawable(Attributes):
    """Base class for objects that can be rendered by the OpenGL engine.

    This is the basic drawable object in the pyFormex OpenGL rendering
    engine. It collects all the data that are needed to properly described
    any object to be rendered by the OpenGL shader programs.
    It has a multitude of optional attributes allowing it to describe
    many very different objects and rendering situations.

    This class is however not intended to be directly used to construct an
    object for rendering. The :class:`Actor` class and its multiple
    subclasses should be used for that purpose. The Actor classes provide
    an easier and more logical interface, and more powerful at the same time,
    since they can be compound: one Actor can hold multiple Drawables.

    The elementary objects that can be directly drawn by the shader programs
    are more simple, yet very diverse. The Drawable class collects all
    the data that are needed by the OpenGL engine to do a proper
    rendering of the object. It this represents a single, versatile
    interface of the Actor classes with the GPU shader programs.

    The versatility comes from the :class:`Attributes` base class, with
    an unlimited set of attributes. Any undefined attribute just returns
    None. Some of the most important attributes are described hereafter:

    - `rendertype`: int: the type of rendering process that will be applied
      by the rendering engine to the Drawable:

      0: A full 3D Actor. The Drawable will be rendered in full 3D with
         all active capabilities, such as camera rotation, projection,
         rendermode, lighting. The full object undergoes the camera
         transformations, and thus will appear as a 3D object in space.
         The object's vertices are defined in 3D world coordinates.
         Used in: :class:`Actor`.

      1: A 2D object (often a text or an image) inserted at a 3D position.
         The 2D object always keeps its orientation towards the camera.
         When the camera changes, the object can change its position on
         the viewport, but the oject itself looks the same.
         This can be used to add annotations to (parts of) a 3D object.
         The object is defined in viewport coordinates, the insertion
         points are in 3D world coordinates.
         Used in: :class:`textext.Text`.

      2: A 2D object inserted at a 2D position. Both object and position
         are defined in viewport coordinates. The object will take a fixed
         position on the viewport. This can be use to add decorations to
         the viewport (like color legends and background images).
         Used in: :class:`decors.ColorLegend`.

      3: Like 2, but with special purpose. These Drawables are not part of
         the user scene, but used for system purposes (like setting the
         background color, or adding an elastic rectangle during mouse picking).
         Used in: :meth:`Canvas.createBackground`.

      -1: Like 1, but with different insertion points for the multiple items
          in the object. Used to place a list of marks at a list of points.
          Used in: :class:`textext.Text`.

      -2: A 3D object inserted at a 2D position. The 3D object will rotate
          when the camera changes directions, but it will always be located
          on the same position of the viewport. This is normally used to
          display a helper object showing the global axis directions.
          Used in: :class:`decors.Triade`.


    The initialization of a Drawable takes a single parameter: `parent`,
    which is the Actor that created the Drawable. All other parameters
    should be keyword arguments, and are stored as attributes in the
    Drawable.

    Methods:

    - `prepare...`: creates sanitized and derived attributes/data. Its action
      pend on current canvas settings: mode, transparent, avgnormals

    - `render`: push values to shader and render the object:
      depends on canvas and renderer.

    - `pick`: fake render to be used during pick operations

    - `str`: format the full data set of the Drawable

    """

    # A list of acceptable attributes in the drawable
    # These are the parent attributes that can be overridden
    attributes = [
        'cullface',
        'subelems',
        'color',
        'name',
        'highlight',
        'opak',
        'linewidth',
        'pointsize',
        'lighting',
        'offset',
        'vbo',
        'nbo',
        'ibo',
        'alpha',
        'drawface',
        'objectColor',
        'useObjectColor',
        'rgbamode',
        'texture',
        'texcoords',
    ]

    def __init__(self, parent, **kargs):
        """Create a new drawable."""

        # Should we really restrict this????
        #kargs = utils.selectDict(kargs, Drawable.attributes)
        Attributes.__init__(self, kargs, default=parent)
        #print("ATTRIBUTES STORED IN DRAWABLE",self)
        #print("ATTRIBUTES STORED IN PARENT",parent)

        # Default lighting parameter:
        # rendertype 0 (3D) follows canvas lighting
        # other rendertypes set lighting=False by default
        if self.rendertype != 0 and self.lighting is None:
            self.lighting = False

        # The final plexitude of the drawn objects
        if self.subelems is not None:
            self.nplex = self.subelems.shape[-1]
        else:
            self.nplex = self._fcoords.shape[-2]
        self.glmode = glObjType(self.nplex)

        self.prepareColor()
        #self.prepareNormals()  # The normals are currently always vertex
        self.prepareSubelems()
        if self.texture is not None:
            self.prepareTexture()

    def prepareColor(self):
        """Prepare the colors for the shader."""
        #
        # This should probably be moved to Actor
        #
        if self.highlight:
            # we set single highlight color in shader
            # Currently do everything in Formex model
            # And we always need this one
            self.avbo = VBO(self.fcoords)
            self.useObjectColor = 1
            self.objectColor = np.array(colors.red)

        elif self.color is not None:
            #print("COLOR",self.color)
            if self.color.ndim == 1:
                # here we only accept a single color for front and back
                # different colors should have been handled before
                self.useObjectColor = 1
                self.objectColor = self.color
            elif self.color.ndim == 2:
                self.useObjectColor = 0
                self.vertexColor = at.multiplex(self.color,
                                                self.object.nplex())
                #pf.debug("Multiplexing colors: %s -> %s " % (self.color.shape, self.vertexColor.shape),pf.DEBUG.OPENGL2)
            elif self.color.ndim == 3:
                self.useObjectColor = 0
                self.vertexColor = self.color

            if self.vertexColor is not None:
                #print("Shader suffix:[%s]" %  pf.options.shader)
                if pf.options.shader == 'alpha':
                    self.alpha = 0.5
                    if self.vertexColor.shape[-1] == 3:
                        # Expand to 4 !!!
                        self.vertexColor = at.growAxis(self.vertexColor,
                                                       1,
                                                       fill=0.5)
                self.cbo = VBO(self.vertexColor.astype(float32))
                if pf.options.shader == 'alpha':
                    size_report("Created cbo VBO", self.cbo)

        self.rgbamode = self.useObjectColor == 0 and self.vertexColor.shape[
            -1] == 4

        #### TODO: should we make this configurable ??
        #
        #  !!!!!!!!!!!!   Fix a bug with AMD cards   !!!!!!!!!!!!!!!
        #
        #  it turns out that some? AMD? cards do not like an unbound cbo
        #  even if that attribute is not used in the shader.
        #  Creating a dummy color buffer seems to solve that problem
        #
        if self.cbo is None:
            self.cbo = VBO(np.array(colors.red))

        #if self.rendertype == 3:
        #    print("CBO DATA %s\n" % self.name,self.cbo.data)

    def changeVertexColor(self, color):
        """Change the vertex color buffer of the object.

        This is experimental!!!
        Just make sure that the passed data have the correct shape!
        """
        if self.useObjectColor:
            return
        if pf.options.shader == 'alpha':
            #if color.size != self.cbo.size:
            size_report('color', color)
            size_report('cbo', self.cbo)
            print(self.cbo.size / color.size)
            print("Can not change vertex color from shape %s to shape %s" %
                  (str(self.cbo.shape), str(color.shape)))
            #return
        self.vertexColor = self.color
        self.cbo = VBO(color.astype(float32))
        if pf.options.shader == 'alpha':
            print("Replace cbo with")
            size_report('cbo', self.cbo)

    def prepareTexture(self):
        """Prepare texture and texture coords"""
        if self.useTexture == 1:
            if self.texcoords.ndim == 2:
                #curshape = self.texcoords.shape
                self.texcoords = at.multiplex(self.texcoords,
                                              self.object.nelems(),
                                              axis=-2)
                #print("Multiplexing texture coords: %s -> %s " % (curshape, self.texcoords.shape))
        self.tbo = VBO(self.texcoords.astype(float32))
        self.texture.activate()

    def prepareSubelems(self):
        """Create an index buffer to draw subelements

        This is always used for nplex > 3, but also to draw the edges
        for nplex=3.
        """
        if self.ibo is None and self.subelems is not None:
            self.ibo = VBO(self.subelems.astype(int32),
                           target=GL.GL_ELEMENT_ARRAY_BUFFER)

    def render(self, renderer):
        """Render the geometry of this object"""
        def render_geom():
            if self.ibo:
                GL.glDrawElementsui(self.glmode, self.ibo)
            else:
                GL.glDrawArrays(self.glmode, 0,
                                np.asarray(self.vbo.shape[:-1]).prod())

        if self.offset:
            pf.debug("POLYGON OFFSET", pf.DEBUG.DRAW)
            GL.glPolygonOffset(1.0, 1.0)

        if self.linewidth:
            GL.glLineWidth(self.linewidth)

        renderer.shader.loadUniforms(self)

        if self.offset3d is not None:
            offset = renderer.camera.toNDC(self.offset3d)
            offset[..., 2] = 0.
            offset += (1., 1., 0.)

            #print(self.rendertype)
            #print("OFFSET=",offset)
            #print("COORDS=",self.vbo.data)
            if offset.shape == (3, ):
                renderer.shader.uniformVec3('offset3', offset)
            elif offset.ndim > 1:
                self.obo = VBO(offset.astype(float32))
                #self.obo = VBO(self._default_dict_.fcoords+offset)
                #print(self._default_dict_.fcoords)
                #print(offset)
                #print(self.obo.data.shape,self.vbo.data.shape)

                self.obo.bind()
                GL.glEnableVertexAttribArray(
                    renderer.shader.attribute['vertexOffset'])
                GL.glVertexAttribPointer(
                    renderer.shader.attribute['vertexOffset'], 3, GL.GL_FLOAT,
                    False, 0, self.obo)

        if self.rendertype == -2:
            # This is currently a special code for the Triade
            # It needs an object with coords in pixel values,
            # centered around the origin
            # and must have attributes x,y, set to the viewport
            # position of the (0,0,0) point after rotation.
            #
            rot = renderer.camera.modelview.rot
            x = np.dot(self._fcoords.reshape(-1, 3),
                       rot).reshape(self._fcoords.shape)
            x[:, :, 0] += self.x
            x[:, :, 1] += self.y
            x[:, :, 2] = 0
            self.vbo = VBO(x)

        self.vbo.bind()
        GL.glEnableVertexAttribArray(renderer.shader.attribute['vertexCoords'])
        GL.glVertexAttribPointer(renderer.shader.attribute['vertexCoords'], 3,
                                 GL.GL_FLOAT, False, 0, self.vbo)

        if self.ibo:
            self.ibo.bind()

        if self.nbo:
            self.nbo.bind()
            GL.glEnableVertexAttribArray(
                renderer.shader.attribute['vertexNormal'])
            GL.glVertexAttribPointer(renderer.shader.attribute['vertexNormal'],
                                     3, GL.GL_FLOAT, False, 0, self.nbo)

        if self.cbo:
            self.cbo.bind()
            GL.glEnableVertexAttribArray(
                renderer.shader.attribute['vertexColor'])
            GL.glVertexAttribPointer(renderer.shader.attribute['vertexColor'],
                                     self.cbo.shape[-1], GL.GL_FLOAT, False, 0,
                                     self.cbo)

        if self.tbo:
            self.tbo.bind()
            GL.glEnableVertexAttribArray(
                renderer.shader.attribute['vertexTexturePos'])
            GL.glVertexAttribPointer(
                renderer.shader.attribute['vertexTexturePos'], 2, GL.GL_FLOAT,
                False, 0, self.tbo)

        if self.cullface == 'front':
            # Draw back faces
            GL.glEnable(GL.GL_CULL_FACE)
            GL.glCullFace(GL.GL_FRONT)
        elif self.cullface == 'back':
            # Draw front faces
            GL.glEnable(GL.GL_CULL_FACE)
            GL.glCullFace(GL.GL_BACK)
        else:
            GL.glDisable(GL.GL_CULL_FACE)

        # Specifiy the depth comparison function
        if self.ontop:
            GL.glDepthFunc(GL.GL_ALWAYS)

        # Bind the texture
        if self.texture:
            self.texture.bind()

        render_geom()

        if self.ibo:
            self.ibo.unbind()

        if self.obo:
            self.obo.unbind()
            GL.glDisableVertexAttribArray(
                renderer.shader.attribute['vertexOffset'])

        if self.cbo:
            self.cbo.unbind()
            GL.glDisableVertexAttribArray(
                renderer.shader.attribute['vertexColor'])
        if self.tbo:
            self.tbo.unbind()
            GL.glDisableVertexAttribArray(
                renderer.shader.attribute['vertexTexturePos'])
        if self.nbo:
            self.nbo.unbind()
            GL.glDisableVertexAttribArray(
                renderer.shader.attribute['vertexNormal'])
        self.vbo.unbind()
        GL.glDisableVertexAttribArray(
            renderer.shader.attribute['vertexCoords'])
        if self.offset:
            pf.debug("POLYGON OFFSET RESET", pf.DEBUG.DRAW)
            GL.glPolygonOffset(0.0, 0.0)

    def pick(self, renderer):
        """Pick the geometry of this object"""
        def render_geom():
            if self.ibo:
                GL.glDrawElementsui(self.glmode, self.ibo)
            else:
                GL.glDrawArrays(self.glmode, 0,
                                np.asarray(self.vbo.shape[:-1]).prod())

        renderer.shader.loadUniforms(self)

        self.vbo.bind()
        GL.glEnableVertexAttribArray(renderer.shader.attribute['vertexCoords'])
        GL.glVertexAttribPointer(renderer.shader.attribute['vertexCoords'], 3,
                                 GL.GL_FLOAT, False, 0, self.vbo)

        if self.ibo:
            self.ibo.bind()

        if self.cullface == 'front':
            # Draw back faces
            GL.glEnable(GL.GL_CULL_FACE)
            GL.glCullFace(GL.GL_FRONT)
        elif self.cullface == 'back':
            # Draw front faces
            GL.glEnable(GL.GL_CULL_FACE)
            GL.glCullFace(GL.GL_BACK)
        else:
            GL.glDisable(GL.GL_CULL_FACE)

        # Specifiy the depth comparison function
        if self.ontop:
            GL.glDepthFunc(GL.GL_ALWAYS)

        render_geom()

        if self.ibo:
            self.ibo.unbind()
        self.vbo.unbind()
        GL.glDisableVertexAttribArray(
            renderer.shader.attribute['vertexCoords'])

    def __str__(self):
        keys = sorted(set(self.keys()) - set(('_default_dict_', )))
        print("Keys %s" % keys)
        out = utils.formatDict(utils.selectDict(self, keys))
        print(out)
        return out
Exemple #48
0
class TraceRender:
    def __init__(self, parent_view):
        self.parent = parent_view

        self.restart()

    def __initialize_uniform(self, gls):
        self.__uniform_shader_vao = VAO()
        self.__uniform_shader = gls.shader_cache.get("line_vertex_shader", "frag1", defines={"INPUT_TYPE": "uniform"})

        with self.__uniform_shader_vao, self.trace_vbo:
            vbobind(self.__uniform_shader, self.trace_vbo.dtype, "vertex").assign()
            vbobind(self.__uniform_shader, self.trace_vbo.dtype, "ptid").assign()
            self.index_vbo.bind()

    def initializeGL(self, gls):
        # Build trace vertex VBO and associated vertex data
        dtype = [("vertex", numpy.float32, 2), ("ptid", numpy.uint32)]
        self.working_array = numpy.zeros(NUM_ENDCAP_SEGMENTS * 2 + 2, dtype=dtype)
        self.trace_vbo = VBO(self.working_array, GL.GL_DYNAMIC_DRAW)

        # Generate geometry for trace and endcaps
        # ptid is a variable with value 0 or 1 that indicates which endpoint the geometry is associated with
        self.__build_trace()

        self.__attribute_shader_vao = VAO()
        self.__attribute_shader = gls.shader_cache.get("line_vertex_shader", "frag1", defines={"INPUT_TYPE": "in"})

        # Now we build an index buffer that allows us to render filled geometry from the same
        # VBO.
        arr = []
        for i in range(NUM_ENDCAP_SEGMENTS - 1):
            arr.append(0)
            arr.append(i + 2)
            arr.append(i + 3)

        for i in range(NUM_ENDCAP_SEGMENTS - 1):
            arr.append(1)
            arr.append(i + NUM_ENDCAP_SEGMENTS + 2)
            arr.append(i + NUM_ENDCAP_SEGMENTS + 3)

        arr.append(2)
        arr.append(2 + NUM_ENDCAP_SEGMENTS - 1)
        arr.append(2 + NUM_ENDCAP_SEGMENTS)
        arr.append(2 + NUM_ENDCAP_SEGMENTS)
        arr.append(2 + NUM_ENDCAP_SEGMENTS * 2 - 1)
        arr.append(2)

        arr = numpy.array(arr, dtype=numpy.uint32)
        self.index_vbo = VBO(arr, target=GL.GL_ELEMENT_ARRAY_BUFFER)

        self.instance_dtype = numpy.dtype(
            [
                ("pos_a", numpy.float32, 2),
                ("pos_b", numpy.float32, 2),
                ("thickness", numpy.float32, 1),
                # ("color", numpy.float32, 4)
            ]
        )

        # Use a fake array to get a zero-length VBO for initial binding
        instance_array = numpy.ndarray(0, dtype=self.instance_dtype)
        self.instance_vbo = VBO(instance_array)

        with self.__attribute_shader_vao, self.trace_vbo:
            vbobind(self.__attribute_shader, self.trace_vbo.dtype, "vertex").assign()
            vbobind(self.__attribute_shader, self.trace_vbo.dtype, "ptid").assign()

        with self.__attribute_shader_vao, self.instance_vbo:
            self.__bind_pos_a = vbobind(self.__attribute_shader, self.instance_dtype, "pos_a", div=1)
            self.__bind_pos_b = vbobind(self.__attribute_shader, self.instance_dtype, "pos_b", div=1)
            self.__bind_thickness = vbobind(self.__attribute_shader, self.instance_dtype, "thickness", div=1)
            # vbobind(self.__attribute_shader, self.instance_dtype, "color", div=1).assign()
            self.__base_rebind(0)

            self.index_vbo.bind()

        self.__initialize_uniform(gls)

        self.__last_prepared = weakref.WeakKeyDictionary()

    def __base_rebind(self, base):
        self.__bind_pos_a.assign(base)
        self.__bind_pos_b.assign(base)
        self.__bind_thickness.assign(base)

    def restart(self):
        self.__deferred_layer = defaultdict(list)
        self.__prepared = False
        self.__needs_rebuild = False

    def __build_trace(self):
        # Update trace VBO
        self.working_array["vertex"][0] = (0, 0)
        self.working_array["ptid"][0] = 0
        self.working_array["vertex"][1] = (0, 0)
        self.working_array["ptid"][1] = 1

        end = Vec2(1, 0)
        for i in range(0, NUM_ENDCAP_SEGMENTS):
            theta = math.pi * i / (NUM_ENDCAP_SEGMENTS - 1) + math.pi / 2
            m = rotate(theta).dot(end.homol())
            self.working_array["vertex"][2 + i] = m[:2]
            self.working_array["ptid"][2 + i] = 0
            self.working_array["vertex"][2 + i + NUM_ENDCAP_SEGMENTS] = -m[:2]
            self.working_array["ptid"][2 + i + NUM_ENDCAP_SEGMENTS] = 1

        # Force data copy
        self.trace_vbo.copied = False
        self.trace_vbo.bind()

    def deferred_multiple(self, trace_settings, render_settings=0):
        """
        :param trace_settings: list of traces to draw and the settings for that particular trace
        :param render_settings:
        :return:
        """
        for t, tr in trace_settings:
            tr |= render_settings
            self.deferred(t, tr)

    def deferred(self, trace, render_settings, render_hint):
        assert not self.__prepared
        self.__deferred_layer[trace.layer].append((trace, render_settings))
        if trace not in self.__last_prepared:
            self.__needs_rebuild = True

    def prepare(self):
        """
        :return: Build VBOs and information for rendering pass
        """
        self.__prepared = True

        if not self.__needs_rebuild:
            return

        self.__last_prepared = weakref.WeakKeyDictionary()

        # Total trace count, across all layers
        count = sum(len(i) for i in self.__deferred_layer.values())

        # Allocate an array of that size
        instance_array = numpy.ndarray(count, dtype=self.instance_dtype)

        pos = 0
        for layer, traces in self.__deferred_layer.items():
            # We reorder the traces to batch them by outline, and net to encourage
            # maximum draw call length. The rationale is that nets are commonly selected
            # or may be commonly drawn in different colors.
            traces = sorted(traces, key=lambda i: (i[1] & RENDER_OUTLINES, id(i[0].net)))

            for trace, _ in traces:
                # Now insert into the array
                instance_array[pos] = (trace.p0, trace.p1, trace.thickness / 2)

                # And memoize where the trace occurs
                self.__last_prepared[trace] = pos

                pos += 1

        # Force full resend of VBO
        self.instance_vbo.data = instance_array
        self.instance_vbo.size = None
        self.instance_vbo.copied = False
        self.instance_vbo.bind()

    def render_deferred_layer(self, mat, layer):
        if not self.__prepared:
            self.prepare()

        trace_settings = self.__deferred_layer[layer]

        count = len(trace_settings)
        if count == 0:
            return

        # key format: is_selected, is_outline
        draw_bins = defaultdict(list)
        draw_range_bins = dict()

        # Bin the traces by draw call
        for t, tr in trace_settings:
            is_selected = bool(tr & RENDER_SELECTED)
            is_outline = bool(tr & RENDER_OUTLINES)
            draw_bins[is_selected, is_outline].append(self.__last_prepared[t])

        # Build draw ranges
        for key, bin in draw_bins.items():
            draw_range_bins[key] = get_consolidated_draws_1(draw_bins[key])

        # HACK / Fixme: Precalculate selected / nonselected colors
        color_a = self.parent.color_for_layer(layer) + [1]
        color_sel = self.parent.sel_colormod(True, color_a)

        has_base_instance = False
        with self.__attribute_shader, self.__attribute_shader_vao:
            # Setup overall calls
            GL.glUniformMatrix3fv(self.__attribute_shader.uniforms.mat, 1, True, mat.ctypes.data_as(GLI.c_float_p))

            # We order the draw calls such that selected areas are drawn on top of nonselected.
            sorted_kvs = sorted(draw_range_bins.items(), key=lambda i: i[0][0])
            for (is_selected, is_outline), ranges in sorted_kvs:
                if is_selected:
                    color = color_sel
                else:
                    color = color_a

                GL.glUniform4f(self.__attribute_shader.uniforms.color, *color)

                if has_base_instance:
                    # Many instances backport glDrawElementsInstancedBaseInstance
                    # This is faster than continually rebinding, so support if possible
                    if not is_outline:
                        for first, last in ranges:
                            # filled traces come first in the array
                            GL.glDrawElementsInstancedBaseInstance(
                                GL.GL_TRIANGLES,
                                TRIANGLES_SIZE,
                                GL.GL_UNSIGNED_INT,
                                ctypes.c_void_p(0),
                                last - first,
                                first,
                            )
                    else:
                        for first, last in ranges:
                            # Then outline traces. We reuse the vertex data for the outside
                            GL.glDrawArraysInstancedBaseInstance(
                                GL.GL_LINE_LOOP, 2, NUM_ENDCAP_SEGMENTS * 2, last - first, first
                            )
                else:
                    with self.instance_vbo:
                        if not is_outline:
                            for first, last in ranges:
                                # filled traces come first in the array
                                self.__base_rebind(first)
                                GL.glDrawElementsInstanced(
                                    GL.GL_TRIANGLES,
                                    TRIANGLES_SIZE,
                                    GL.GL_UNSIGNED_INT,
                                    ctypes.c_void_p(0),
                                    last - first,
                                )
                        else:
                            for first, last in ranges:
                                self.__base_rebind(first)
                                # Then outline traces. We reuse the vertex data for the outside
                                GL.glDrawArraysInstanced(GL.GL_LINE_LOOP, 2, NUM_ENDCAP_SEGMENTS * 2, last - first)

    # Immediate-mode render of a single trace
    # SLOW (at least for bulk-rendering)
    # Useful for rendering UI elements
    def render(self, mat, trace, render_settings=RENDER_STANDARD):
        color_a = self.parent.color_for_trace(trace) + [1]
        color_a = self.parent.sel_colormod(render_settings & RENDER_SELECTED, color_a)
        with self.__uniform_shader, self.__uniform_shader_vao:
            GL.glUniform1f(self.__uniform_shader.uniforms.thickness, trace.thickness / 2)
            GL.glUniform2f(self.__uniform_shader.uniforms.pos_a, trace.p0.x, trace.p0.y)
            GL.glUniform2f(self.__uniform_shader.uniforms.pos_b, trace.p1.x, trace.p1.y)
            GL.glUniformMatrix3fv(self.__uniform_shader.uniforms.mat, 1, True, mat.ctypes.data_as(GLI.c_float_p))
            GL.glUniform4f(self.__uniform_shader.uniforms.color, *color_a)

            if render_settings & RENDER_OUTLINES:
                GL.glDrawArrays(GL.GL_LINE_LOOP, 2, NUM_ENDCAP_SEGMENTS * 2)
            else:
                GL.glDrawElements(GL.GL_TRIANGLES, TRIANGLES_SIZE, GL.GL_UNSIGNED_INT, ctypes.c_void_p(0))
Exemple #49
0
class MSGLCanvas2D(QGLWidget):
    """
    Canvas GL plotting in 2 dimensions
    """
    
    
    MAX = 100.
    
    
    corner_=100.0
    zoom_= 1.5
    xrot_=220
    yrot_ = 220
    trans_x_ =0.0
    trans_y_ = 0.0
    
    
    def __init__(self, data, parent=None, **kw):
        """
        Constructor, initialization
        """
        
        QGLWidget.__init__(self, parent)
        self.setFormat(QGLFormat(QGL.SampleBuffers))
        self.setMinimumSize(500,300)#300
        self.setMouseTracking(True) 
        self.setFocusPolicy(Qt.StrongFocus)
        
        self.data=data
        vertexes=[]
        colors=[]
        from utils.misc import IceAndFire
        maxY=max(map(max, [log10(el.y_data) for el in data]))
        maxX=max(map(max, [el.x_data for el in data]))
        rtmax=max([z.rtmin for z in data])
        for el in data:
            for i, x in enumerate(el.x_data):
                c=IceAndFire.getQColor(log10(el.y_data[i])/maxY)
                colors.append(c)
                vertexes.append([(x*2*self.corner_)/maxX, (el.rt*2*self.corner_)/rtmax])
        from OpenGL.arrays.vbo import VBO
        
        self.vertexes= VBO(array(vertexes,'f'))
        self.colors=VBO(array(colors,'f'))
        
        self.mode = "None" # "ZOOMING", "PANNING", "NONE"
        self.lastpos = QPoint()
        
        self.counter_trans_x = 0
        self.counter_trans_y = 0

        
        self.defaultColors = {'ticks':(0.,0.,0.,0.),
                              'axes':(0.,0.,0.,0.),
                              'curves':(0.,0.,1.,0.),
                              'backgroundColor':(1.,1.,1.,1.)
                              }
     
        #self.axes=self.drawAxes()
        self.transformationMatrix = self.setupTransformationMatrix(self.width(), 
                                                                   self.height())
    
    
 
                                 
        
    def setupTransformationMatrix(self,w, h):
        """
        use a matrix to translate in the gl landmark
        """
        
        m = QMatrix()
        m.translate(-w/2, h/2)
        m.scale(300./w, 300./h)
        print w, h, w/300., 1-((h/300)-1)
        #m.scale((self.width()*100)/300, -(self.height()*100)/300)
        #self.currentSize.x = w
        #self.currentSize.y = h        
        return m


    
    def inGLCoordinate(self, point):
        return self.transformationMatrix.map(point)        
        
    
    
    def resizeGL(self, w, h):
        """
        called when window is being resized
        """
    
        glViewport(0,0, w, h)    
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(-self.corner_*self.zoom_, 
                   self.corner_*self.zoom_, 
                   -self.corner_*self.zoom_, 
                   self.corner_*self.zoom_)

        #self.transformationMatrix = self.setupTransformationMatrix(w, h)
        
        glMatrixMode(GL_MODELVIEW)
    
    
    def initializeGL(self):
        """needed, initialize GL parameters"""
        
        #glClearColor(1.,1.,1.,1.)
        glDisable(GL_DEPTH_TEST)
        glEnable(GL_LINE_SMOOTH)
        glEnable(GL_POINT_SMOOTH)
        glHint (GL_LINE_SMOOTH_HINT, GL_NICEST)
        glLoadIdentity() #model view by default
        
#        self.grid_lines = self.drawGridLines()
#        self.ticks =self.drawAxisTick()
#        self.axes = self.drawAxes()

    
    
    def paintGL(self):
        """Draw the scene, needed, called each time glDraw"""
        
        glClear(GL_COLOR_BUFFER_BIT)
        glTranslated(self.trans_x_, self.trans_y_, 0.)
        #addition
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(-self.corner_*self.zoom_, 
                    self.corner_*self.zoom_,    
                    -self.corner_*self.zoom_, 
                    self.corner_*self.zoom_)
        glMatrixMode(GL_MODELVIEW)
        #end addition
        #glCallList(self.grid_lines)
        #glCallList(self.ticks)
        #glCallList(self.axes)
        glLineWidth(30.0)
        self.scatterPlot()
#        if self.flags == "chrom":
#            self.drawAxisLegend("retention time[s]", "intensity[%]")
#            glCallList(self.lines)
#        elif self.flags == "spectrum":
#            self.drawAxisLegend("m/z", "intensity")
        
    
    
    
    def drawAxes(self, width=2., colour=(0.,0.,0.)):
        """
        Draw Axes 
        """
        #width must be a float
        axes = glGenLists(1)
        glNewList(axes, GL_COMPILE)
        glLineWidth(width)
        glColor(colour[0],colour[1],colour[2])
        glBegin(GL_LINES)
        #x_achse
        glVertex2d(-self.corner_, -self.corner_)
        glVertex2d( self.corner_, -self.corner_)
        #y-achse
        glVertex2d(-self.corner_, -self.corner_)
        glVertex2d( -self.corner_, self.corner_)
        glEnd()
        glEndList()
        return axes
        
    
    def drawLegends(self, pos):
        """
        draw legend at the specified position
        """
        pass
    
    
    
   
        
    
    
    def drawAxisLegend(self, x_label, y_label):
        """
        Draw Axis Legend
        """
        font =QFont("Typewriter")                        
        #RT axis legend
        font.setPixelSize(12)
        self.renderText(self.corner_, -self.corner_-20.0, 0., x_label)# font
        self.renderText(-self.corner_-20.0, self.corner_, 0., y_label, font)
    
    
    
    
            
            
    def resetTranslations(self):            
        """
        reset the different translation to 0
        """
        self.trans_x_ =0.
        self.trans_y_ =0.
        self.counter_trans_x=0.
        self.counter_trans_y=0.
    
    
    
    def normalizeAngle(self,angle):
            while (angle < 0):
                    angle += 360 * 16
            while (angle > 360 * 16):
                    angle -= 360 * 16


########DRAWING METHODS##################################################

    def drawLine(self, point_, point):
        glBegin(GL_LINES)
        glVertex2d(point_.x(), point_.y())
        glVertex2d(point.x(), point.y())
        glEnd()
    
    def drawRect(self, p_1, p_2, p_3=None, p_4 = None):
        pass
    
    def drawOnePoint(self, point, colour= Qt.yellow):
        pass
    
    def scatterPlot(self):
        """ Draw Data (x, y)"""
        if self.vertexes is not None and self.colors is not None:
            self.vertexes.bind()
            glEnableClientState(GL_VERTEX_ARRAY)
            glVertexPointerf(self.vertexes)
            self.colors.bind()                  
            glEnableClientState(GL_COLOR_ARRAY)
            glColorPointerf(self.colors)
            glDrawArrays(GL_LINES, 0, len(self.vertexes))
            self.vertexes.unbind()
            self.colors.unbind()
            #self.textures.unbind()
            glDisableClientState(GL_VERTEX_ARRAY)
            glDisableClientState(GL_COLOR_ARRAY)
    
    def spectrumPlot(self, points):
        pass
    
    def histogramPlot(self, points, bin = 5.):
        pass
        
    def barPlot(points, width =2.):pass

    


########MOUSE AND KEYBOARDS EVENTS###########################################################################
    
    
    def wheelEvent(self, event):
        if event.delta() >0:
            self.zoom_ -= .05    
        else:
            self.zoom_ += .05
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(-self.corner_*self.zoom_, 
                   self.corner_*self.zoom_, 
                   -self.corner_*self.zoom_, 
                   self.corner_*self.zoom_)
        self.updateGL()
        glMatrixMode(GL_MODELVIEW)
        event.accept()
            
    
    
    
    def keyPressEvent(self,  event):
        if event.key() == Qt.Key_Plus:
            self.zoom_ -= .1
            glMatrixMode(GL_PROJECTION)
            glLoadIdentity()
            gluOrtho2D(-self.corner_*self.zoom_, 
                       self.corner_*self.zoom_,    
                       -self.corner_*self.zoom_, 
                       self.corner_*self.zoom_)
            glMatrixMode(GL_MODELVIEW)

        if event.key() == Qt.Key_Minus:
                self.zoom_ += .1
                glMatrixMode(GL_PROJECTION) #// You had GL_MODELVIEW
                glLoadIdentity()
                gluOrtho2D(-self.corner_*self.zoom_, self.corner_*self.zoom_, -self.corner_*self.zoom_, self.corner_*self.zoom_)
                glMatrixMode(GL_MODELVIEW)
                
        if event.key() == Qt.Key_Up:
                self.trans_y_ += 2
                self.counter_trans_y +=2
                
        if event.key() == Qt.Key_Down:
                self.trans_y_ -=2
                self.counter_trans_y -=2
                
        if event.key() == Qt.Key_Left:
                self.trans_x_ -=2
                self.counter_trans_x -=2
                
        if event.key() == Qt.Key_Right:
                self.trans_x_ +=2
                self.counter_trans_x +=2
        
        
        if event.key() == Qt.Key_Z:
            self.mode= "ZOOMING"
            if self.counter_trans_x < 0 and self.counter_trans_y < 0:
                while self.counter_trans_x < 0 and self.counter_trans_y < 0:
                    self.trans_x_ = self.counter_trans_x
                    self.trans_y_ = self.counter_trans_y                    
                    self.updateGL()
                    self.counter_trans_x += 1
                    self.counter_trans_y += 1
                    
            if self.counter_trans_x > 0 and self.counter_trans_y < 0:
                while self.counter_trans_x < 0 and self.counter_trans_y < 0:
                    self.trans_x_ = self.counter_trans_x
                    self.trans_y_ = self.counter_trans_y                    
                    self.updateGL()
                    self.counter_trans_x -= 1
                    self.counter_trans_y += 1
            
            if self.counter_trans_x < 0 and self.counter_trans_y > 0:
                while self.counter_trans_x < 0 and self.counter_trans_y < 0:
                    self.trans_x_ = self.counter_trans_x
                    self.trans_y_ = self.counter_trans_y                    
                    self.updateGL()
                    self.counter_trans_x += 1
                    self.counter_trans_y -= 1
    
            if self.counter_trans_x < 0 and self.counter_trans_y > 0:
                while self.counter_trans_x < 0 and self.counter_trans_y < 0:
                    self.trans_x_ = self.counter_trans_x
                    self.trans_y_ = self.counter_trans_y                    
                    self.updateGL()
                    self.counter_trans_x -= 1
                    self.counter_trans_y -= 1
                    
            if self.zoom_ != 1.5:    
                self.zoom = 1.5
                #self.updateGL()
        self.updateGL()
        self.resetTranslations()    
        
    
    def mousePressEvent(self, event):
        if self.mode == "ZOOMING":
            self.mode = "None"
            self.computeSelection()
        else: 
            self.lastpos = QPoint(event.pos())
            self.setCursor(QCursor(Qt.ClosedHandCursor))
        
        
        #if event.buttons() ==  Qt.RightButton:
        #    self.mode = "PANNING"
            
    def computeSelection(self):
        print "selected"

    
    
    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastpos.x()
        dy = event.y() - self.lastpos.y()
        
        if self.mode == "ZOOMING":
            font = QFont("Typewriter")
            self.renderText(-self.corner_ -30.0, self.corner_, 0., "ZOOMING MODE ACTIVATED", font)
            self.updateGL()
            glColor(0., 0., 1., .5)
            XMAX = 900.; XMIN = 180.
            pointer_x = (self.lastpos.x()*200.)/XMAX
            norm_dx = (dx*200.)/XMAX
            """
            if pointer_x > 100. or pointer_x < 100. \
                or norm_dx >100. or norm_dx<-100.:
                event.ignore()
            """

            
            glBegin(GL_QUADS)
            glVertex2d(pointer_x, -100.)
            glVertex2d(pointer_x+ norm_dx, -100.)
            glVertex2d(pointer_x+ norm_dx, 100.)
            glVertex2d(pointer_x, 100.)
            glEnd()
            
            self.updateGL()#update for seeing the rectangle
            
        mapping = self.mapFromGlobal
        cursorPos = self.inGLCoordinate(mapping(self.cursor().pos()))        
        QToolTip.showText(self.cursor().pos(),
                          "x:"+str(cursorPos.x())+ \
                          ", y:"+str(cursorPos.y())
                          )

        if self.mode == "None":      
            if event.buttons()== Qt.LeftButton:
                self.trans_y_ -= dy/5
                self.counter_trans_y -= dy/5
                self.trans_x_ += dx/5
                self.counter_trans_x += dx/5
            self.lastpos = QPoint(event.pos())
            self.glDraw()
            self.resetTranslations()        

    
    def mouseReleaseEvent(self, event):
        self.setCursor(QCursor(Qt.ArrowCursor))