Exemple #1
0
    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()
Exemple #2
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 #3
0
    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
Exemple #4
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 )
    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
Exemple #6
0
    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
Exemple #7
0
    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
Exemple #8
0
    def initializeGL(self, gls):
        self.gls = gls
        # Basic solid-color program
        self.prog = self.gls.shader_cache.get("vert2", "frag1")
        self.mat_loc = GL.glGetUniformLocation(self.prog, "mat")
        self.col_loc = GL.glGetUniformLocation(self.prog, "color")

        # Build a VBO for rendering square "drag-handles"
        self.vbo_handles_ar = numpy.ndarray(4, dtype=[("vertex", numpy.float32, 2)])
        self.vbo_handles_ar["vertex"] = numpy.array(corners) * HANDLE_HALF_SIZE


        self.vbo_handles = VBO(self.vbo_handles_ar, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER)

        self.vao_handles = VAO()
        with self.vbo_handles, self.vao_handles:
            vbobind(self.prog, self.vbo_handles_ar.dtype, "vertex").assign()

        # Build a VBO/VAO for the perimeter
        # We don't initialize it here because it is updated every render
        # 4 verticies for outside perimeter
        # 6 verticies for each dim
        self.vbo_per_dim_ar = numpy.zeros(16, dtype=[("vertex", numpy.float32, 2)])

        self.vbo_per_dim = VBO(self.vbo_per_dim_ar, GL.GL_DYNAMIC_DRAW, GL.GL_ARRAY_BUFFER)

        self.vao_per_dim = VAO()
        with self.vao_per_dim, self.vbo_per_dim:
            vbobind(self.prog, self.vbo_per_dim_ar.dtype, "vertex").assign()
Exemple #9
0
    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 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()
Exemple #11
0
    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
Exemple #12
0
    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
Exemple #13
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())
Exemple #14
0
        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 __init__(self):
        self.face = None
        self.textures = dict()

        # compile rendering program
        self.renderProgram = GLProgram(_textVertexShaderSource,
                                       _textFragmentShaderSource)
        self.renderProgram.compile_and_link()

        # make projection uniform
        self.projectionUniform = GLUniform(self.renderProgram.get_program_id(),
                                           'projection', 'mat4f')
        self.textColorUniform = GLUniform(self.renderProgram.get_program_id(),
                                          'textColor', 'vec3f')
        self.textureSizeUniform = GLUniform(
            self.renderProgram.get_program_id(), 'textureSize', 'vec2f')

        # create rendering buffer
        self.vbo = VBO(_get_rendering_buffer(0, 0, 0, 0))
        self.vbo.create_buffers()
        self.vboId = glGenBuffers(1)

        # initialize VAO
        self.vao = glGenVertexArrays(1)
        glBindVertexArray(self.vao)
        glBindBuffer(GL_ARRAY_BUFFER, self.vboId)
        self.vbo.bind()
        self.vbo.copy_data()
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
                              5 * ctypes.sizeof(ctypes.c_float),
                              ctypes.c_void_p(0))
        glEnableVertexAttribArray(0)
        glVertexAttribPointer(
            1, 2, GL_FLOAT, GL_FALSE, 5 * ctypes.sizeof(ctypes.c_float),
            ctypes.c_void_p(3 * ctypes.sizeof(ctypes.c_float)))
        glEnableVertexAttribArray(1)
        # self.vbo.unbind()
        glBindVertexArray(0)

        self.zNear = -1.0
        self.zFar = 1.0
Exemple #16
0
    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 #17
0
    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)
Exemple #18
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)
Exemple #19
0
 def __init__(self,
              data,
              attributes,
              segment,
              bufferSize,
              target=gl.GL_ARRAY_BUFFER,
              usage=gl.GL_STATIC_DRAW):
     self.target = target
     self.usage = usage
     
     if data==None or data.size==0:
         self.bind = doNothing
         self.bindAttributes = doNothing
         self.unbind = doNothing
         return
     
     GLVBO.__init__(self,
                    data=data,
                    usage=usage,
                    target=target,
                    size=bufferSize)
     
     self.segment = segment
     
     # GLVertexAttribute instances
     self.attributes = []
     
     # queued slices
     self.slices = []
     
     self.DUMMY = False
     
     # remember attribute locations in the shader
     for att in attributes:
         att.location = gl.glGetAttribLocation(segment.shaderProgram, att.name)
         if att.location!=-1:
             self.attributes.append(att)
         else:
             print "WARNING: cannot find attribute %s in shader" % att.name
Exemple #20
0
    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)
Exemple #21
0
    def initializeGL(self, gls: 'GLShared') -> None:
        self.gls = gls

        # zap the cached text on GL reinitialize (VBO handles / etc are likely invalid)
        self.textCached = {}

        # basic solid-color shader
        self.prog = gls.shader_cache.get("vert2", "frag1")

        # Construct a VBO containing all the points we need for rendering
        dtype = numpy.dtype([("vertex", numpy.float32, 2)])
        points = numpy.ndarray((16, ), dtype=dtype)

        # keypoint display: edge half-dimension in pixels
        self.d1 = d1 = 20

        # keypoint display: text-area "flag" height in pixels
        th = 16

        # keypoint display: right-edge offset of text flag in pixels
        tw = 6

        points["vertex"] = [
            # Lines making up keypoint cross (rendered with GL_LINES)
            (-d1, -d1),
            (-d1, d1),
            (-d1, d1),
            (d1, d1),
            (d1, d1),
            (d1, -d1),
            (d1, -d1),
            (-d1, -d1),
            (0, -d1),
            (0, d1),
            (-d1, 0),
            (d1, 0),

            # flag (rendered with GL_TRIANGLE_STRIP)
            (-d1, -d1),
            (-d1, -d1 - th),
            (-tw, -d1),
            (-tw, -d1 - th)
        ]

        # Pack it all into a VBO
        self.handle_vbo = VBO(points, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER)

        # and bind the program for rendering
        self.handle_vao = VAO()
        with self.handle_vao, self.handle_vbo:
            VBOBind(self.prog.program, dtype, "vertex").assign()
Exemple #22
0
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 #23
0
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 #24
0
    def initGL(self, gls: 'GLShared') -> None:
        self._tex = Texture()

        # Setup the basic texture parameters
        with self._tex.on(GL.GL_TEXTURE_2D):
            GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER,
                               GL.GL_NEAREST)
            GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER,
                               GL.GL_LINEAR)
            GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S,
                               GL.GL_CLAMP_TO_EDGE)
            GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T,
                               GL.GL_CLAMP_TO_EDGE)

            # numpy packs data tightly, whereas the openGL default is 4-byte-aligned
            # fix line alignment to 1 byte so odd-sized textures load right
            GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1)

            # Download the data to the buffer. cv2 stores data in BGR format
            GL.glTexImage2D(
                GL.GL_TEXTURE_2D, 0, GL.GL_RGB, self.im.shape[1],
                self.im.shape[0], 0, GL.GL_BGR, GL.GL_UNSIGNED_BYTE,
                self.im.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)))

        self.prog = gls.shader_cache.get("image_vert", "image_frag")

        ar = numpy.ndarray(
            (4, ),
            dtype=[("vertex", numpy.float32, 2),
                   ("texpos", numpy.float32, 2)])  # type: ignore

        sca = max(self.im.shape[0], self.im.shape[1])
        x = self.im.shape[1] / float(sca)
        y = self.im.shape[0] / float(sca)
        ar["vertex"] = [(-x, -y), (-x, y), (x, -y), (x, y)]
        ar["texpos"] = [(0, 0), (0, 1), (1, 0), (1, 1)]

        self.b1 = VBOBind(self.prog.program, ar.dtype, "vertex")
        self.b2 = VBOBind(self.prog.program, ar.dtype, "texpos")

        self.vbo = VBO(ar, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER)

        self.mat_loc = GL.glGetUniformLocation(self.prog.program, "mat")
        self.tex1_loc = GL.glGetUniformLocation(self.prog.program, "tex1")

        self.vao = VAO()
        with self.vbo, self.vao:
            self.b1.assign()
            self.b2.assign()
Exemple #25
0
    def _prepareNormals(self, canvas):
        """Prepare the normals buffer object for the actor.

        The normals buffer object depends on the renderer settings:
        lighting, avgnormals
        """
        #if renderer.canvas.settings.lighting:
        if True:
            if canvas.settings.avgnormals:
                normals = self.b_avgnormals
            else:
                normals = self.b_normals
            # Normals are always full fcoords size
            #print("SIZE OF NORMALS: %s; COORDS: %s" % (normals.size,self.fcoords.size))
            self.nbo = VBO(normals)
Exemple #26
0
class BackgroundGridRender:
    def __init__(self):
        self.__width = 0
        self.__height = 0
        self.__vbo_dtype = numpy.dtype([("vertex", numpy.float32, 2)])

    def initializeGL(self, gls, width, height):
        # Get shader

        self.__shader = gls.shader_cache.get("basic_fill_vert", "basic_fill_frag")

        self.__vbo = VBO(numpy.ndarray(0, dtype=self.__vbo_dtype), GL.GL_STATIC_DRAW)
        self.__vao = VAO()

        # Create array of lines sufficient to fill screen
        self.resize(width, height)

    def __get_vbo_data(self):
        va = VA_xy(1024)

        # Unit steps from -n/2..n/2 along X axis. Y lines from -1 to +1
        for i in range(0, self.n_steps * 2, 2):
            i_ = i - int(self.n_steps / 2)
            va.add_line(i_, -1, i_, 1)

        return va

    def resize(self, width, height):
        self.n_steps = max(self.__width, self.__height) // MIN_PIXEL_SPACE
        self.__vbo.set_array(self.__get_vbo_data())

    def set_grid(self, step):
        pass

    def draw(self, transform_matrix):
        pass
Exemple #27
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 #28
0
 def addHighlightPoints(self, sel=None):
     """Add a highlight for the selected points. Default is all."""
     self.removeHighlight()
     vbo = VBO(self.object.points())
     self._highlight = Drawable(self,
                                vbo=vbo,
                                subelems=sel.reshape(-1, 1),
                                name=self.name + "_highlight",
                                linewidth=10,
                                lighting=False,
                                color=np.array(colors.yellow),
                                opak=True,
                                pointsize=10,
                                offset=1.0)
     # Put at the front to make visible
     self.drawable.insert(0, self._highlight)
Exemple #29
0
    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()
Exemple #30
0
    def compile_VBO(self, force=False):
        "Compiles the verticies of all faces into a VBO and saves the ref."
        if self._VBO_is_compiled and not force:
            return
        vbos = []
        try:
            self._VBO_format = self.shapes[0].compile_VBO(force=True)
        except IndexError:
            raise ValueError("Shape3D tried to compile to VBO, but it didn't\
                              have any shapes.")
        for s in self.shapes:
            fmt = s.compile_VBO()
            if fmt != self._VBO_format and fmt is not None:
                # TODO figure out a good way of filling in the blanks?
                raise ValueError("While compiling a Shape3D to VBO, a Shape2D\
                    format mismatched with the format for the other shapes.")
            vbos.append(s._VBO)

        self._VBO = VBO(np.concatenate(vbos))
        self._VBO_is_compiled = True
def displayfunc_gles2(display, surface, ctx):
    from OpenGL import GLES2 as GL
    from OpenGL.GLES2 import shaders
    eglMakeCurrent( display, surface, surface, ctx )
    GL.glClearColor( 1,0,0, 0 )
    GL.glClear( GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT )
    
    global shader,vbo,position_location,stride
    if shader is None:
        shader = shaders.compileProgram(
            shaders.compileShader( '''#version 130
    attribute vec3 position;
    void main() {
        gl_Position = vec4( position, 0 );
    }''', type=GL_VERTEX_SHADER),
            shaders.compileShader( '''#version 130
    void main() {
        gl_FragColor = vec4( 1,0,0,0 );
    }''', type=GL_FRAGMENT_SHADER),
        )
        vbo = VBO( array([
            (0,1,0),
            (1,-1,0),
            (-1,-1,0),
        ],dtype='f'))
        position_location = GL.glGetAttribLocation(
            self.shader, 'position'
        )
        stride = 3*4
    with vbo:
        with shader:
            GL.glEnableVertexAttribArray( position_location )
            stride = 3*4
            GL.glVertexAttribPointer(
                position_location,
                3, GL_FLOAT,False, stride, self.vbo
            )
            GL.glDrawArrays( GL.GL_TRIANGLES, 0, 3 )
    eglSwapBuffers( display, surface )
Exemple #32
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 #33
0
def sphere(radius=0.5, sectors=32, rings=16):
    """
    Generate a sphere

    :param radius: Radius or the sphere
    :param rings: number or horizontal rings
    :param sectors: number of vertical segments
    :return: VAO containing the sphere
    """
    R = 1.0 / (rings - 1)
    S = 1.0 / (sectors - 1)

    vertices = [0] * (rings * sectors * 3)
    normals = [0] * (rings * sectors * 3)
    uvs = [0] * (rings * sectors * 2)

    v, n, t = 0, 0, 0
    for r in range(rings):
        for s in range(sectors):
            y = math.sin(-math.pi / 2 + math.pi * r * R)
            x = math.cos(2 * math.pi * s * S) * math.sin(math.pi * r * R)
            z = math.sin(2 * math.pi * s * S) * math.sin(math.pi * r * R)

            uvs[t] = s * S
            uvs[t + 1] = r * R

            vertices[v] = x * radius
            vertices[v + 1] = y * radius
            vertices[v + 2] = z * radius

            normals[n] = x
            normals[n + 1] = y
            normals[n + 2] = z

            t += 2
            v += 3
            n += 3

    indices = [0] * rings * sectors * 6
    i = 0
    for r in range(rings - 1):
        for s in range(sectors - 1):
            indices[i] = r * sectors + s
            indices[i + 1] = (r + 1) * sectors + (s + 1)
            indices[i + 2] = r * sectors + (s + 1)

            indices[i + 3] = r * sectors + s
            indices[i + 4] = (r + 1) * sectors + s
            indices[i + 5] = (r + 1) * sectors + (s + 1)
            i += 6

    vbo_vertices = VBO(numpy.array(vertices, dtype=numpy.float32))
    vbo_normals = VBO(numpy.array(normals, dtype=numpy.float32))
    vbo_uvs = VBO(numpy.array(uvs, dtype=numpy.float32))
    vbo_element = VBO(numpy.array(indices, dtype=numpy.uint32),
                      target="GL_ELEMENT_ARRAY_BUFFER")

    vao = VAO("sphere")
    # VBOs
    vao.add_array_buffer(GL.GL_FLOAT, vbo_vertices)
    vao.add_array_buffer(GL.GL_FLOAT, vbo_normals)
    vao.add_array_buffer(GL.GL_FLOAT, vbo_uvs)
    # Mapping
    vao.map_buffer(vbo_vertices, "in_position", 3)
    vao.map_buffer(vbo_normals, "in_normal", 3)
    vao.map_buffer(vbo_uvs, "in_uv", 2)
    # Index
    vao.set_element_buffer(GL.GL_UNSIGNED_INT, vbo_element)
    vao.build()
    return vao
Exemple #34
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 #35
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 #36
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 #37
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 #38
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 #39
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 #40
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 #41
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 #42
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 #43
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 #44
0
    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()
Exemple #45
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 #46
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()
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 #48
0
        glEnable(GL_DEBUG_OUTPUT)
        glDebugMessageCallback(GLDEBUGPROC(debug_message_callback), None)
    # 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)

    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)
Exemple #49
0
 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
Exemple #50
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 #51
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 #52
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 #53
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 #54
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 #55
0
class RectAlignmentControllerView(BaseToolController, GenModel):
    changed = QtCore.Signal()

    def __init__(self, parent, model):
        super(RectAlignmentControllerView, self).__init__()

        self._parent = parent
        self.model_overall = model
        self.model = model.ra

        self.__init_interaction()

        self.gls = None

        self.active = False

    idx_handle_sel = mdlacc(None)
    idx_handle_hover = mdlacc(None)

    #sel_mode = mdlacc(SEL_MODE_NONE)
    behave_mode = mdlacc(MODE_NONE)
    ghost_handle = mdlacc(None)

    def change(self):
        self.changed.emit()

    def __init_interaction(self):
        # Selection / drag handling
        self.idx_handle_sel = None
        #self.sel_mode = SEL_MODE_NONE

        self.behave_mode = MODE_NONE

        # ghost handle for showing placement
        self.ghost_handle = None

    def initialize(self):
        self.__init_interaction()
        self.active = True

    def finalize(self):
        self.active = False

    def initializeGL(self, gls):
        self.gls = gls
        # Basic solid-color program
        self.prog = self.gls.shader_cache.get("vert2", "frag1")
        self.mat_loc = GL.glGetUniformLocation(self.prog, "mat")
        self.col_loc = GL.glGetUniformLocation(self.prog, "color")

        # Build a VBO for rendering square "drag-handles"
        self.vbo_handles_ar = numpy.ndarray(4, dtype=[("vertex", numpy.float32, 2)])
        self.vbo_handles_ar["vertex"] = numpy.array(corners) * HANDLE_HALF_SIZE


        self.vbo_handles = VBO(self.vbo_handles_ar, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER)

        self.vao_handles = VAO()
        with self.vbo_handles, self.vao_handles:
            vbobind(self.prog, self.vbo_handles_ar.dtype, "vertex").assign()

        # Build a VBO/VAO for the perimeter
        # We don't initialize it here because it is updated every render
        # 4 verticies for outside perimeter
        # 6 verticies for each dim
        self.vbo_per_dim_ar = numpy.zeros(16, dtype=[("vertex", numpy.float32, 2)])

        self.vbo_per_dim = VBO(self.vbo_per_dim_ar, GL.GL_DYNAMIC_DRAW, GL.GL_ARRAY_BUFFER)

        self.vao_per_dim = VAO()
        with self.vao_per_dim, self.vbo_per_dim:
            vbobind(self.prog, self.vbo_per_dim_ar.dtype, "vertex").assign()

    def im2V(self, pt):
        """Translate Image coordinates to viewport coordinates"""

        if self.model_overall.view_mode:
            ph = projectPoint(self.model.image_matrix, pt)
            return self.viewState.tfW2V(ph)
        else:
            return self.viewState.tfW2V(pt)

    def V2im(self, pt):
        """
        Translate viewport coordinates to image coordinates
        :param pt:
        :return:
        """
        world = self.viewState.tfV2W(pt)

        if self.model_overall.view_mode:
            inv = numpy.linalg.inv(self.model.image_matrix)
            return projectPoint(inv, world)
        else:
            return Vec2(world)
        #inv = numpy.linalg.inv(self.model.image_matrix)
        #return Vec2(inv.dot(pt)[:2])

    def gen_dim(self, idx, always_above = True):
        """
        Generate rendering data for the dimension-lines
        :param idx:
        :return:
        """
        a = self.im2V(self.model.dim_handles[0 + idx])
        b = self.im2V(self.model.dim_handles[1 + idx])

        d = b-a

        delta = (b-a).norm()

        normal = Point2(rotate(math.pi / 2)[:2,:2].dot(delta))

        if always_above:
            if numpy.cross(Vec2(1,0), normal) > 0:
                normal = -normal

        res = numpy.array([
            a + normal * 8,
            a + normal * 20,
            a + normal * 15,
            b + normal * 15,
            b + normal * 8,
            b + normal * 20,
            ])

        return res


    def render(self, vs):
        self.viewState = vs

        disabled = not self.active or self.model_overall.view_mode

        # Perimeter is defined by the first 4 handles
        self.vbo_per_dim_ar["vertex"][:4] = [self.im2V(pt) for pt in self.model.align_handles[:4]]

        # Generate the dimension lines. For ease of use, we always draw the dim-lines above when dims are manual
        # or below when dims are unlocked
        self.vbo_per_dim_ar["vertex"][4:10] = self.gen_dim(0, not self.model.dims_locked)
        self.vbo_per_dim_ar["vertex"][10:16] = self.gen_dim(2, not self.model.dims_locked)

        self.vbo_per_dim.set_array(self.vbo_per_dim_ar)

        # Ugh..... PyOpenGL isn't smart enough to bind the data when it needs to be copied
        with self.vbo_per_dim:
            self.vbo_per_dim.copy_data()


        GL.glDisable(GL.GL_BLEND)

        # ... and draw the perimeter
        with self.vao_per_dim, self.prog:
            GL.glUniformMatrix3fv(self.mat_loc, 1, True, self.viewState.glWMatrix.astype(numpy.float32))

            # Draw the outer perimeter
            if disabled:
                GL.glUniform4f(self.col_loc, 0.8, 0.8, 0.8, 1)
            else:
                GL.glUniform4f(self.col_loc, 0.8, 0.8, 0, 1)
            GL.glDrawArrays(GL.GL_LINE_LOOP, 0, 4)

            # Draw the dimensions
            GL.glUniform4f(self.col_loc, 0.8, 0.0, 0.0, 1)
            GL.glDrawArrays(GL.GL_LINES, 4, 6)

            GL.glUniform4f(self.col_loc, 0.0, 0.0, 0.8, 1)
            GL.glDrawArrays(GL.GL_LINES, 10, 6)

        if disabled:
            return

        # Now draw a handle at each corner
        with self.vao_handles, self.prog:
            for n, i in enumerate(self.model.align_handles):
                # skip nonexistent handles
                if i is None:
                    continue

                is_anchor = IDX_IS_ANCHOR(n)

                corner_pos = self.im2V(i)

                if disabled:
                    color = [0.8, 0.8, 0.8, 1]
                elif self.idx_handle_sel == n:
                    color = [1, 1, 1, 1]
                elif self.idx_handle_hover == n:
                    color = [1, 1, 0, 1]
                else:
                    color = [0.8, 0.8, 0, 0.5]

                self.render_handle(corner_pos, color, is_anchor, True)

                if self.idx_handle_sel == n:
                    self.render_handle(corner_pos, [0,0,0,1], is_anchor, False)

            if self.ghost_handle is not None:
                self.render_handle(self.ghost_handle,[0.8, 0.8, 0, 0.5], True)

            if not self.model.dims_locked:
                for n, i in enumerate(self.model.dim_handles):
                    handle_pos = self.im2V(i)
                    if n == self.idx_handle_sel:
                        color = [1, 1, 1, 1]
                    if n < 2:
                        color = [0.8, 0.0, 0.0, 1]
                    else:
                        color = [0.0, 0.0, 0.8, 1]
                    self.render_handle(handle_pos, color, False, True)
                    if self.idx_handle_sel == n:
                        self.render_handle(corner_pos, [0,0,0,1], is_anchor, False)

    def render_handle(self, position, color, diagonal=False, filled=False):
        if diagonal:
            r = rotate(math.pi/4)
        else:
            r = numpy.identity(3)

        m = self.viewState.glWMatrix.dot(translate(*position).dot(r))
        GL.glUniformMatrix3fv(self.mat_loc, 1, True, m.astype(numpy.float32))
        GL.glUniform4f(self.col_loc, *color)
        GL.glDrawArrays(GL.GL_TRIANGLE_FAN if filled else GL.GL_LINE_LOOP, 0, 4)

    def get_handle_for_mouse(self, pos):
        for n, handle in enumerate(self.model.all_handles()):
            if handle is None:
                continue
            # get the pix-wise BBOX of the handle
            p = self.im2V(handle)
            r = QtCore.QRect(p[0], p[1], 0, 0)
            r.adjust(-HANDLE_HALF_SIZE, -HANDLE_HALF_SIZE, HANDLE_HALF_SIZE, HANDLE_HALF_SIZE)

            # If event inside the bbox
            if r.contains(pos):
                return n
        return None

    def get_line_query_for_mouse(self, pos):
        for n, (p1, p2) in enumerate(self.model.line_iter()):
            p1_v = self.im2V(p1)
            p2_v = self.im2V(p2)

            p, d = project_point_line(pos, p1_v, p2_v)
            if p is not None and d < HANDLE_HALF_SIZE:
                return n, p

        return None, None


    def mousePressEvent(self, event):
        disabled = not self.active or self.model_overall.view_mode
        if disabled:
            return False

        handle = self.get_handle_for_mouse(event.pos())

        if event.button() == QtCore.Qt.LeftButton and event.modifiers() & ADD_MODIFIER:
            idx, p = self.get_line_query_for_mouse(event.pos())
            if idx is not None:
                anchors = self.model.get_anchors(idx)
                if len(anchors) < 2:
                    p = self.V2im(p)
                    idx = new_anchor_index(self.model, idx)

                    cmd = cmd_set_handle_position(self.model, idx, p)
                    self._parent.undoStack.push(cmd)

                    self.idx_handle_sel = idx
                    self.idx_handle_hover = None

        elif event.button() == QtCore.Qt.LeftButton and event.modifiers() & DEL_MODIFIER and (
                        handle is not None and handle >= 4):
            cmd = cmd_set_handle_position(self.model, handle, None)
            self._parent.undoStack.push(cmd)
            #self.model.set_handle(handle, None)

            self.idx_handle_sel = None
            self.idx_handle_hover = None

        elif event.button() == QtCore.Qt.LeftButton:
            self.idx_handle_sel = handle
            self.idx_handle_hover = None
            if handle is not None:
                self.behave_mode = MODE_DRAGGING

        else:
            return False

        return True

    def mouseReleaseEvent(self, event):
        disabled = not self.active or self.model_overall.view_mode
        if disabled:
            return False

        if event.button() == QtCore.Qt.LeftButton and self.behave_mode == MODE_DRAGGING:
            self.behave_mode = MODE_NONE
        else:
            return False

        return True

    def mouseMoveEvent(self, event):
        disabled = not self.active or self.model_overall.view_mode
        if disabled:
            return False

        needs_update = False
        idx = self.get_handle_for_mouse(event.pos())

        if self.ghost_handle is not None:
            self.ghost_handle = None

        if self.behave_mode == MODE_NONE:
            if idx is not None:
                self.idx_handle_hover = idx

            else:
                self.idx_handle_hover = None

            if event.modifiers() & ADD_MODIFIER:
                line_idx, pos = self.get_line_query_for_mouse(event.pos())

                if line_idx is not None:
                    self.ghost_handle = pos

        elif self.behave_mode == MODE_DRAGGING:
            w_pos = self.V2im(Vec2(event.pos()))

            cmd = cmd_set_handle_position(self.model, self.idx_handle_sel, w_pos, merge=True)
            self._parent.undoStack.push(cmd)
            #self.model.set_handle(self.idx_handle_sel, w_pos)


        return False

    def focusOutEvent(self, evt):
        self.idx_handle_sel = None

    def keyPressEvent(self, evt):
        disabled = not self.active or self.model_overall.view_mode
        if disabled:
            return False

        if evt.key() == QtCore.Qt.Key_Escape:
            self.idx_handle_sel = None

        elif self.idx_handle_sel is not None:

            if evt.key() in (QtCore.Qt.Key_Delete, QtCore.Qt.Key_Backspace) and IDX_IS_ANCHOR(self.idx_handle_sel):

                cmd = cmd_set_handle_position(self.model, self.idx_handle_sel, None)
                self._parent.undoStack.push(cmd)
                #self.model.set_handle(self.idx_handle_sel, None)
                self.idx_handle_sel = None

            # Basic 1-px nudging
            elif evt.key() in (QtCore.Qt.Key_Left, QtCore.Qt.Key_Right, QtCore.Qt.Key_Up, QtCore.Qt.Key_Down):
                nudge = {
                    QtCore.Qt.Key_Left:  (-1,  0),
                    QtCore.Qt.Key_Right: ( 1,  0),
                    QtCore.Qt.Key_Up:    ( 0, -1),
                    QtCore.Qt.Key_Down:  ( 0,  1),
                }[evt.key()]

                current = Vec2(self.im2V(self.model.align_handles[self.idx_handle_sel]))
                viewspace = self.V2im(current + nudge)
                cmd = cmd_set_handle_position(self.model, self.idx_handle_sel, viewspace)
                self._parent.undoStack.push(cmd)
                #self.model.set_handle(self.idx_handle_sel, viewspace)

                self.ghost_handle = None

    def next_prev_child(self, next):
        all_handles = self.model.all_handles()

        step = -1
        if next:
            step = 1

        if self.behave_mode == MODE_DRAGGING:
            return True
        else:
            idx = self.idx_handle_sel

            if idx == None:
                return False

            while 1:
                idx = (idx + step) % len(all_handles)

                if all_handles[idx] is not None:
                    self.idx_handle_sel = idx
                    return True
Exemple #56
0
    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()
Exemple #57
0
class RectAlignmentControllerView(BaseToolController):
    changed = QtCore.Signal()

    def __init__(self, parent,
                 model: 'pcbre.ui.dialogs.layeralignmentdialog.dialog.AlignmentViewModel'):
        super(RectAlignmentControllerView, self).__init__()

        self._parent = parent
        self.model_overall = model
        self.model = model.ra

        self.__idx_handle_sel: Optional[int] = None
        self.__idx_handle_hover: Optional[int] = None

        self.__behave_mode = DM.NONE
        self.__ghost_handle = None

        self.__init_interaction()

        self.gls: Optional[Any] = None

        self.active = False

    def change(self) -> None:
        self.changed.emit()

    @property
    def tool_actions(self) -> 'Sequence[ToolActionDescription]':
        return g_ACTIONS

    def __init_interaction(self) -> None:
        # Selection / drag handling
        self.__idx_handle_sel = None

        self.__behave_mode = DM.NONE

        # ghost handle for showing placement
        self.__ghost_handle = None

    def initialize(self) -> None:
        self.__init_interaction()
        self.active = True

    def finalize(self) -> None:
        self.active = False

    def initializeGL(self, gls: 'GLShared') -> None:
        self.gls = gls

        assert self.gls is not None

        # Basic solid-color program
        self.prog = self.gls.shader_cache.get("vert2", "frag1")
        self.mat_loc = GL.glGetUniformLocation(self.prog.program, "mat")
        self.col_loc = GL.glGetUniformLocation(self.prog.program, "color")

        # Build a VBO for rendering square "drag-handles"
        self.vbo_handles_ar = numpy.ndarray((4, ), dtype=[("vertex", numpy.float32, 2)])
        self.vbo_handles_ar["vertex"] = numpy.array(corners) * HANDLE_HALF_SIZE

        self.vbo_handles = VBO(self.vbo_handles_ar, GL.GL_STATIC_DRAW, GL.GL_ARRAY_BUFFER)

        self.vao_handles = VAO()
        with self.vbo_handles, self.vao_handles:
            VBOBind(self.prog.program, self.vbo_handles_ar.dtype, "vertex").assign()

        # Build a VBO/VAO for the perimeter
        # We don't initialize it here because it is updated every render
        # 4 verticies for outside perimeter
        # 6 verticies for each dim
        self.vbo_per_dim_ar = numpy.zeros(16, dtype=[("vertex", numpy.float32, 2)])

        self.vbo_per_dim = VBO(self.vbo_per_dim_ar, GL.GL_DYNAMIC_DRAW, GL.GL_ARRAY_BUFFER)

        self.vao_per_dim = VAO()
        with self.vao_per_dim, self.vbo_per_dim:
            VBOBind(self.prog.program, self.vbo_per_dim_ar.dtype, "vertex").assign()

    def im2V(self, pt: Vec2) -> Vec2:
        """Translate Image coordinates to viewport coordinates"""

        if self.model_overall.view_mode.is_aligned():
            ph = project_point(self.model.image_matrix, pt)
            return self.viewPort.tfW2V(ph)
        else:
            return self.viewPort.tfW2V(pt)

    def V2im(self, pt: Vec2) -> Vec2:
        """
        Translate viewport coordinates to image coordinates
        :param pt:
        :return:
        """
        world = self.viewPort.tfV2W(pt)

        if self.model_overall.view_mode.is_aligned():
            inv = numpy.linalg.inv(self.model.image_matrix)
            return project_point(inv, world)
        else:
            return world
        # inv = numpy.linalg.inv(self.model.image_matrix)
        # return Vec2(inv.dot(pt)[:2])

    def gen_dim(self, idx: int, always_above: bool = True) -> 'npt.NDArray[numpy.float64]':
        """
        Generate rendering data for the dimension-lines
        :param idx:
        :return:
        """
        a = self.im2V(self.model.dim_handles[0 + idx])
        b = self.im2V(self.model.dim_handles[1 + idx])

        d = b - a

        delta = (b - a).norm()

        normal = Vec2.from_mat(rotate(math.pi / 2)[:2, :2].dot(delta))

        if always_above:
            if numpy.cross(Vec2(1, 0), normal) > 0:
                normal = -normal

        res = numpy.array([
            a + normal * 8,
            a + normal * 20,
            a + normal * 15,
            b + normal * 15,
            b + normal * 8,
            b + normal * 20,
        ], dtype=numpy.float64)

        return res

    @property
    def disabled(self) -> bool:
        # When the we're showing the aligned view; or if we are using keypoint align
        # don't render any handles
        return not self.active or self.model_overall.view_mode.is_aligned()

    def render(self, viewPort: 'ViewPort') -> None:
        self.viewPort = viewPort

        # Perimeter is defined by the first 4 handles
        self.vbo_per_dim_ar["vertex"][:4] = [self.im2V(pt) for pt in self.model.align_handles[:4]]

        # Generate the dimension lines. For ease of use, we always draw the dim-lines above when dims are manual
        # or below when dims are unlocked
        self.vbo_per_dim_ar["vertex"][4:10] = self.gen_dim(0, not self.model.dims_locked)
        self.vbo_per_dim_ar["vertex"][10:16] = self.gen_dim(2, not self.model.dims_locked)

        self.vbo_per_dim.set_array(self.vbo_per_dim_ar)

        # Ugh..... PyOpenGL isn't smart enough to bind the data when it needs to be copied
        with self.vbo_per_dim:
            self.vbo_per_dim.copy_data()

        GL.glDisable(GL.GL_BLEND)

        # ... and draw the perimeter
        with self.vao_per_dim, self.prog.program:
            GL.glUniformMatrix3fv(self.mat_loc, 1, True, self.viewPort.glWMatrix.astype(numpy.float32))

            # Draw the outer perimeter
            if self.disabled:
                GL.glUniform4f(self.col_loc, 0.8, 0.8, 0.8, 1)
            else:
                GL.glUniform4f(self.col_loc, 0.8, 0.8, 0, 1)
            GL.glDrawArrays(GL.GL_LINE_LOOP, 0, 4)

            # Draw the dimensions
            GL.glUniform4f(self.col_loc, 0.8, 0.0, 0.0, 1)
            GL.glDrawArrays(GL.GL_LINES, 4, 6)

            GL.glUniform4f(self.col_loc, 0.0, 0.0, 0.8, 1)
            GL.glDrawArrays(GL.GL_LINES, 10, 6)

        if self.disabled:
            return

        # Now draw a handle at each corner
        with self.vao_handles, self.prog.program:
            for n, i in enumerate(self.model.align_handles):
                # skip nonexistent handles
                if i is None:
                    continue

                is_anchor = IDX_IS_LINE(n)

                corner_pos = self.im2V(i)

                if self.disabled:
                    color = [0.8, 0.8, 0.8, 1]
                elif self.__idx_handle_sel == n:
                    color = [1, 1, 1, 1]
                elif self.__idx_handle_hover == n:
                    color = [1, 1, 0, 1]
                else:
                    color = [0.8, 0.8, 0, 0.5]

                self.render_handle(corner_pos, color, is_anchor, True)

                if self.__idx_handle_sel == n:
                    self.render_handle(corner_pos, [0, 0, 0, 1], is_anchor, False)

            if self.__ghost_handle is not None:
                self.render_handle(self.__ghost_handle, [0.8, 0.8, 0, 0.5], True)

            if not self.model.dims_locked:
                for n, i in enumerate(self.model.dim_handles):
                    handle_pos = self.im2V(i)
                    if n == self.__idx_handle_sel:
                        color = [1, 1, 1, 1]
                    if n < 2:
                        color = [0.8, 0.0, 0.0, 1]
                    else:
                        color = [0.0, 0.0, 0.8, 1]
                    self.render_handle(handle_pos, color, False, True)
                    if self.__idx_handle_sel == n:
                        self.render_handle(corner_pos, [0, 0, 0, 1], is_anchor, False)

    def render_handle(self, position: Vec2, color: Sequence[float],
                      diagonal: bool = False, filled: bool = False) -> None:
        if diagonal:
            r = rotate(math.pi / 4)
        else:
            r = numpy.identity(3)

        m = self.viewPort.glWMatrix.dot(translate(*position).dot(r))
        GL.glUniformMatrix3fv(self.mat_loc, 1, True, m.astype(numpy.float32))
        GL.glUniform4f(self.col_loc, *color)
        GL.glDrawArrays(GL.GL_TRIANGLE_FAN if filled else GL.GL_LINE_LOOP, 0, 4)

    def get_handle_index_for_mouse(self, pos: Vec2) -> Optional[int]:
        """ Returns the index of a handle (or None if one isn't present) given
            a MoveEvent"""
        for n, handle in enumerate(self.model.all_handles()):
            if handle is None:
                continue

            # get the pix-wise BBOX of the handle
            p = self.im2V(handle)

            # Rect encompassing the handle
            r = Rect.from_center_size(p, HANDLE_HALF_SIZE * 2, HANDLE_HALF_SIZE * 2)

            # If event inside the bbox
            if r.point_test(pos) != 0:
                return n
        return None

    def get_line_query_for_mouse(self, pos: Vec2) -> Tuple[Optional[int], Optional[Vec2]]:
        for n, (p1, p2) in enumerate(self.model.lines()):
            p1_v = self.im2V(p1)
            p2_v = self.im2V(p2)

            p, d = project_point_line(pos, p1_v, p2_v)
            if d is not None and d < HANDLE_HALF_SIZE:
                return n, p

        return None, None

    def event_add_constraint(self, event: 'ToolActionEvent') -> None:
        idx, p = self.get_line_query_for_mouse(event.cursor_pos)
        if idx is not None:
            anchors = self.model.get_anchors(idx)
            if len(anchors) < 2:
                p = self.V2im(p)
                idx = new_anchor_index(self.model, idx)

                cmd = cmd_set_handle_position(self.model, idx, p)
                self._parent.undoStack.push(cmd)

                self.__idx_handle_sel = idx
                self.__idx_handle_hover = None

    def event_remove_constraint(self, event: 'ToolActionEvent') -> None:
        handle = self.get_handle_index_for_mouse(event.cursor_pos)

        if handle is not None and handle >= 4:
            cmd = cmd_set_handle_position(self.model, handle, None)
            self._parent.undoStack.push(cmd)

        self.__idx_handle_sel = None
        self.__idx_handle_hover = None

    def event_select(self, event: 'ToolActionEvent') -> None:
        handle = self.get_handle_index_for_mouse(event.cursor_pos)

        self.__idx_handle_sel = handle
        self.__idx_handle_hover = None

        if handle is not None:
            self.__behave_mode = DM.DRAGGING

    def event_release(self, event: 'ToolActionEvent') -> None:
        if self.__behave_mode == DM.DRAGGING:
            self.__behave_mode = DM.NONE

    def tool_event(self, event: 'ToolActionEvent') -> None:
        if self.disabled:
            return

        if event.code == EventCode.Select:
            self.event_select(event)
        elif event.code == EventCode.Release:
            self.event_release(event)
        elif event.code == EventCode.AddToLine:
            self.event_add_constraint(event)
        elif event.code == EventCode.RemoveFromLine:
            self.event_remove_constraint(event)

    def mouseMoveEvent(self, event: 'MoveEvent') -> None:
        if self.disabled:
            return

        needs_update = False
        idx = self.get_handle_index_for_mouse(event.cursor_pos)

        if self.__ghost_handle is not None:
            self.__ghost_handle = None

        if self.__behave_mode == DM.NONE:
            if idx is not None:
                self.__idx_handle_hover = idx

            else:
                self.__idx_handle_hover = None

            # if event.modifiers() & ADD_MODIFIER:
            #    line_idx, pos = self.get_line_query_for_mouse(event.cursor_pos)

            #    if line_idx is not None:
            #        self.__ghost_handle = pos

        elif self.__behave_mode == DM.DRAGGING:
            w_pos = self.V2im(event.cursor_pos)
            # print(w_pos, event.world_pos)

            cmd = cmd_set_handle_position(self.model, self.__idx_handle_sel, w_pos, merge=True)
            self._parent.undoStack.push(cmd)

    def focusOutEvent(self, evt: QtCore.QEvent) -> None:
        self.__idx_handle_sel = None

    def keyPressEvent(self, evt: QtGui.QKeyEvent) -> bool:
        if self.disabled:
            return False

        if evt.key() == QtCore.Qt.Key_Escape:
            self.__idx_handle_sel = None

        elif self.__idx_handle_sel is not None:

            if evt.key() in (QtCore.Qt.Key_Delete, QtCore.Qt.Key_Backspace) and IDX_IS_LINE(self.__idx_handle_sel):

                cmd = cmd_set_handle_position(self.model, self.__idx_handle_sel, None)
                self._parent.undoStack.push(cmd)
                # self.model.set_handle(self.__idx_handle_sel, None)
                self.__idx_handle_sel = None

            # Basic 1-px nudging
            elif evt.key() in (QtCore.Qt.Key_Left, QtCore.Qt.Key_Right, QtCore.Qt.Key_Up, QtCore.Qt.Key_Down):
                _nudgetab: Dict[int,Tuple[int, int]] = {
                    QtCore.Qt.Key_Left: (-1, 0),
                    QtCore.Qt.Key_Right: (1, 0),
                    QtCore.Qt.Key_Up: (0, -1),
                    QtCore.Qt.Key_Down: (0, 1),
                }

                nudge = _nudgetab[evt.key()]

                current = self.im2V(self.model.align_handles[self.__idx_handle_sel])
                viewspace = self.V2im(current + Vec2.from_mat(nudge))
                cmd = cmd_set_handle_position(self.model, self.__idx_handle_sel, viewspace)
                self._parent.undoStack.push(cmd)
                # self.model.set_handle(self.__idx_handle_sel, viewspace)

                self.__ghost_handle = None

    def next_prev_child(self, next: bool) -> bool:
        all_handles = self.model.all_handles()

        step = -1
        if next:
            step = 1

        if self.__behave_mode == DM.DRAGGING:
            return True
        else:
            idx = self.__idx_handle_sel

            if idx is None:
                return False

            while 1:
                idx = (idx + step) % len(all_handles)

                if all_handles[idx] is not None:
                    self.__idx_handle_sel = idx
                    return True
Exemple #58
0
        glEnable(GL_DEBUG_OUTPUT)
        glDebugMessageCallback(GLDEBUGPROC(debug_message_callback), None)
    # 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()

    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'),