예제 #1
0
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self, size=(512, 512), title='Rotating cube',
                            keys='interactive')
        self.timer = app.Timer('auto', self.on_timer)

    def on_initialize(self, event):
        # Build cube data
        V, I, O = create_cube()
        vertices = VertexBuffer(V)
        self.faces = IndexBuffer(I)
        self.outline = IndexBuffer(O)

        # Build program
        # --------------------------------------
        self.program = Program(vertex, fragment)
        self.program.bind(vertices)

        # Build view, model, projection & normal
        # --------------------------------------
        view = translate((0, 0, -5))
        model = np.eye(4, dtype=np.float32)

        self.program['u_model'] = model
        self.program['u_view'] = view
        self.phi, self.theta = 0, 0

        # OpenGL initalization
        # --------------------------------------
        gloo.set_state(clear_color=(0.30, 0.30, 0.35, 1.00), depth_test=True,
                       polygon_offset=(1, 1), line_width=0.75,
                       blend_func=('src_alpha', 'one_minus_src_alpha'))
        self.timer.start()

    def on_draw(self, event):
        gloo.clear(color=True, depth=True)

        # Filled cube
        gloo.set_state(blend=False, depth_test=True, polygon_offset_fill=True)
        self.program['u_color'] = 1, 1, 1, 1
        self.program.draw('triangles', self.faces)

        # Outlined cube
        gloo.set_state(blend=True, depth_mask=False, polygon_offset_fill=False)
        self.program['u_color'] = 0, 0, 0, 1
        self.program.draw('lines', self.outline)
        gloo.set_state(depth_mask=True)

    def on_resize(self, event):
        gloo.set_viewport(0, 0, *event.size)
        projection = perspective(45.0, event.size[0] / float(event.size[1]),
                                 2.0, 10.0)
        self.program['u_projection'] = projection

    def on_timer(self, event):
        self.theta += .02
        self.phi += .02
        model = rotate(self.phi, (0, 1, 0)) * rotate(self.theta, (0, 0, 1))
        self.program['u_model'] = model
        self.update()
예제 #2
0
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self,
                            size=(750, 750),
                            title='Textured cube',
                            keys='interactive')
        self.timer = app.Timer('auto', self.on_timer)
        self.counter = 0

        # Build cube data
        V, I, _ = create_cube()
        vertices = VertexBuffer(V)
        self.indices = IndexBuffer(I)

        # Build program
        self.program = Program(vertex, fragment)
        self.program.bind(vertices)

        # Build view, model, projection & normal
        view = translate((0, 0, -5))
        model = np.eye(4, dtype=np.float32)
        self.program['model'] = model
        self.program['view'] = view
        self.program['texture'] = cam  # checkerboard()

        self.activate_zoom()

        self.phi, self.theta = 0, 0

        # OpenGL initalization
        gloo.set_state(clear_color=(0.30, 0.30, 0.35, 1.00), depth_test=True)
        self.timer.start()

        self.show()

    def on_draw(self, event):
        gloo.clear(color=True, depth=True)
        self.program.draw('triangles', self.indices)

    def on_resize(self, event):
        self.activate_zoom()

    def activate_zoom(self):
        gloo.set_viewport(0, 0, *self.physical_size)
        projection = perspective(45.0, self.size[0] / float(self.size[1]), 2.0,
                                 10.0)
        self.program['projection'] = projection

    def on_timer(self, event):
        self.counter += 1
        print("on_timer", self.counter)
        self.theta += .5
        self.phi += .5
        self.program['model'] = np.dot(rotate(self.theta, (0, 1, 0)),
                                       rotate(self.phi, (0, 1, 0)))
        # self.program['texture'] = im if self.counter % 200 else checkerboard()
        self.update()
예제 #3
0
파일: rain.py 프로젝트: zymspindrift/vispy
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self,
                            title='Rain [Move mouse]',
                            size=(512, 512),
                            keys='interactive')

        # Build data
        # --------------------------------------
        n = 500
        self.data = np.zeros(n, [('a_position', np.float32, 2),
                                 ('a_fg_color', np.float32, 4),
                                 ('a_size', np.float32, 1)])
        self.index = 0
        self.program = Program(vertex, fragment)
        self.vdata = VertexBuffer(self.data)
        self.program.bind(self.vdata)
        self.program['u_antialias'] = 1.00
        self.program['u_linewidth'] = 1.00
        self.program['u_model'] = np.eye(4, dtype=np.float32)
        self.program['u_view'] = np.eye(4, dtype=np.float32)

        self.activate_zoom()

        gloo.set_clear_color('white')
        gloo.set_state(blend=True,
                       blend_func=('src_alpha', 'one_minus_src_alpha'))
        self.timer = app.Timer('auto', self.on_timer, start=True)

        self.show()

    def on_draw(self, event):
        gloo.clear()
        self.program.draw('points')

    def on_resize(self, event):
        self.activate_zoom()

    def activate_zoom(self):
        gloo.set_viewport(0, 0, *self.physical_size)
        projection = ortho(0, self.size[0], 0, self.size[1], -1, +1)
        self.program['u_projection'] = projection

    def on_timer(self, event):
        self.data['a_fg_color'][..., 3] -= 0.01
        self.data['a_size'] += 1.0
        self.vdata.set_data(self.data)
        self.update()

    def on_mouse_move(self, event):
        x, y = event.pos
        h = self.size[1]
        self.data['a_position'][self.index] = x, h - y
        self.data['a_size'][self.index] = 5
        self.data['a_fg_color'][self.index] = 0, 0, 0, 1
        self.index = (self.index + 1) % 500
예제 #4
0
파일: rain.py 프로젝트: Eric89GXL/vispy
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self, title='Rain [Move mouse]',
                            size=(512, 512), keys='interactive')

        # Build data
        # --------------------------------------
        n = 500
        self.data = np.zeros(n, [('a_position', np.float32, 2),
                                 ('a_fg_color', np.float32, 4),
                                 ('a_size',     np.float32, 1)])
        self.index = 0
        self.program = Program(vertex, fragment)
        self.vdata = VertexBuffer(self.data)
        self.program.bind(self.vdata)
        self.program['u_antialias'] = 1.00
        self.program['u_linewidth'] = 1.00
        self.program['u_model'] = np.eye(4, dtype=np.float32)
        self.program['u_view'] = np.eye(4, dtype=np.float32)

        self.activate_zoom()

        gloo.set_clear_color('white')
        gloo.set_state(blend=True,
                       blend_func=('src_alpha', 'one_minus_src_alpha'))
        self.timer = app.Timer('auto', self.on_timer, start=True)

        self.show()

    def on_draw(self, event):
        gloo.clear()
        self.program.draw('points')

    def on_resize(self, event):
        self.activate_zoom()

    def activate_zoom(self):
        gloo.set_viewport(0, 0, *self.physical_size)
        projection = ortho(0, self.size[0], 0,
                           self.size[1], -1, +1)
        self.program['u_projection'] = projection

    def on_timer(self, event):
        self.data['a_fg_color'][..., 3] -= 0.01
        self.data['a_size'] += 1.0
        self.vdata.set_data(self.data)
        self.update()

    def on_mouse_move(self, event):
        x, y = event.pos
        h = self.size[1]
        self.data['a_position'][self.index] = x, h - y
        self.data['a_size'][self.index] = 5
        self.data['a_fg_color'][self.index] = 0, 0, 0, 1
        self.index = (self.index + 1) % 500
예제 #5
0
class MyCanvas(app.Canvas):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.timer = app.Timer('auto', connect=self.on_timer, start=True)

        with open('vertex.glsl') as f:
            self.vshader = f.read()
        with open('fragment.glsl') as f:
            self.fshader = f.read()
        self.program = Program(self.vshader, self.fshader)

        v, i, iOutline = create_cube()
        self.vertices = VertexBuffer(v)
        self.indices = IndexBuffer(i)
        self.outlineIndices = IndexBuffer(iOutline)
        self.program.bind(self.vertices)

        self.theta, self.phi = 0, 0
        self.program['model'] = np.eye(4)
        self.program['view'] = translate([0, 0, -5])

        self.program['texture'] = checkerboard()
        gloo.set_state(clear_color=(0.30, 0.30, 0.35, 1.00),
                       polygon_offset=(1, 1),
                       blend_func=('src_alpha', 'one_minus_src_alpha'),
                       line_width=5,
                       depth_test=True)

    def on_resize(self, event):
        gloo.set_viewport(0, 0, *self.physical_size)
        proj = perspective(45.0, self.size[0] / self.size[1], 0.01, 1000)
        self.program['projection'] = proj

    def on_draw(self, event):
        gloo.clear(color=True, depth=True)

        gloo.set_state(blend=False, depth_test=True, polygon_offset_fill=True)
        self.program['u_color'] = [1, 1, 1, 1]
        self.program.draw('triangles', self.indices)

        gloo.set_state(blend=True, depth_mask=False, polygon_offset_fill=False)
        self.program['u_color'] = [0, 0, 0, 1]
        self.program.draw('lines', self.outlineIndices)
        gloo.set_state(depth_mask=True)

    def on_timer(self, event):
        self.theta = event.elapsed * 30
        self.phi = 0
        self.program['model'] = np.dot(
            rotate(self.phi, [1, 0, 0]),
            rotate(self.theta, [0, 1, 0]),
        )
        self.update()
예제 #6
0
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self, size=(512, 512), title='Textured cube',
                            keys='interactive')
        self.timer = app.Timer('auto', self.on_timer)

        # Build cube data
        V, I, _ = create_cube()
        vertices = VertexBuffer(V)
        self.indices = IndexBuffer(I)

        # Build program
        self.program = Program(vertex, fragment)
        self.program.bind(vertices)

        # Build view, model, projection & normal
        view = translate((0, 0, -5))
        model = np.eye(4, dtype=np.float32)
        self.program['model'] = model
        self.program['view'] = view
        self.program['texture'] = checkerboard()

        self.activate_zoom()

        self.phi, self.theta = 0, 0

        # OpenGL initalization
        gloo.set_state(clear_color=(0.30, 0.30, 0.35, 1.00), depth_test=True)
        self.timer.start()

        self.show()

    def on_draw(self, event):
        gloo.clear(color=True, depth=True)
        self.program.draw('triangles', self.indices)

    def on_resize(self, event):
        self.activate_zoom()

    def activate_zoom(self):
        gloo.set_viewport(0, 0, *self.physical_size)
        projection = perspective(45.0, self.size[0] / float(self.size[1]),
                                 2.0, 10.0)
        self.program['projection'] = projection

    def on_timer(self, event):
        self.theta += .5
        self.phi += .5
        self.program['model'] = np.dot(rotate(self.theta, (0, 0, 1)),
                                       rotate(self.phi, (0, 1, 0)))
        self.update()
예제 #7
0
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self,
                            size=(512, 512),
                            title='Textured cube',
                            keys='interactive')
        self.timer = app.Timer('auto', self.on_timer)

    def on_initialize(self, event):
        # Build cube data
        V, I, _ = create_cube()
        vertices = VertexBuffer(V)
        self.indices = IndexBuffer(I)

        # Build program
        self.program = Program(vertex, fragment)
        self.program.bind(vertices)

        # Build view, model, projection & normal
        view = np.eye(4, dtype=np.float32)
        model = np.eye(4, dtype=np.float32)
        translate(view, 0, 0, -5)
        self.program['model'] = model
        self.program['view'] = view
        self.program['texture'] = checkerboard()

        self.phi, self.theta = 0, 0

        # OpenGL initalization
        gloo.set_state(clear_color=(0.30, 0.30, 0.35, 1.00), depth_test=True)
        self.timer.start()

    def on_draw(self, event):
        gloo.clear(color=True, depth=True)
        self.program.draw('triangles', self.indices)

    def on_resize(self, event):
        gloo.set_viewport(0, 0, *event.size)
        projection = perspective(45.0, event.size[0] / float(event.size[1]),
                                 2.0, 10.0)
        self.program['projection'] = projection

    def on_timer(self, event):
        self.theta += .5
        self.phi += .5
        model = np.eye(4, dtype=np.float32)
        rotate(model, self.theta, 0, 0, 1)
        rotate(model, self.phi, 0, 1, 0)
        self.program['model'] = model
        self.update()
예제 #8
0
class GpaphicBlueprint:
    def __init__(self):
        self.kind = ''
        self._color = (0, 0, 0)
        self._program = None
        self._indices = None
        self._mesh = None

    def getProgram(self):
        return self._program

    def getIndices(self):
        return self._indices

    def setColor(self, newColor):
        '''

        Mit dieser Methode koennen andere Klassen die Farb-Uniform des _programs setzen.

        Parameter: newColor
        Rueckgabewerte: -

        '''

        self._color = newColor
        self._program['color'] = self._color

    def buildProgram(self):
        '''

        In dieser Methode wird das Programm samt Indices einer Kugel errechnet. Das Ganze wird mithilfe der
        Bibliothek vispy.gloo gemacht.

        Parameter: -
        Rueckgabewerte: -

        '''

        vertices = np.zeros(self._mesh.getVertices().shape[0],
                            [("position", np.float32, 3)])
        vertices["position"] = self._mesh.getVertices()
        vertices = VertexBuffer(vertices)
        indices = self._mesh.getIndices()
        self._indices = IndexBuffer(indices)
        self._program = Program(vertex, fragment)
        self._program.bind(vertices)
        self._program['color'] = self._color
        self._program['model'] = None
        self._program['view'] = None
        self._program['drawHorizon'] = -3
예제 #9
0
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self, size=(512, 512), title='Textured cube',
                            close_keys='escape')
        self.timer = app.Timer(1./60., self.on_timer)

    def on_initialize(self, event):
        # Build cube data
        V, I, _ = cube()
        vertices = VertexBuffer(V)
        self.indices = IndexBuffer(I)

        # Build program
        self.program = Program(vertex, fragment)
        self.program.bind(vertices)

        # Build view, model, projection & normal
        view = np.eye(4, dtype=np.float32)
        model = np.eye(4, dtype=np.float32)
        translate(view, 0, 0, -5)
        self.program['model'] = model
        self.program['view'] = view
        self.program['texture'] = checkerboard()

        self.phi, self.theta = 0, 0

        # OpenGL initalization
        gloo.set_state(clear_color=(0.30, 0.30, 0.35, 1.00), depth_test=True)
        self.timer.start()

    def on_draw(self, event):
        gloo.clear(color=True, depth=True)
        self.program.draw('triangles', self.indices)

    def on_resize(self, event):
        gloo.set_viewport(0, 0, *event.size)
        projection = perspective(45.0, event.size[0] / float(event.size[1]),
                                 2.0, 10.0)
        self.program['projection'] = projection

    def on_timer(self, event):
        self.theta += .5
        self.phi += .5
        model = np.eye(4, dtype=np.float32)
        rotate(model, self.theta, 0, 0, 1)
        rotate(model, self.phi, 0, 1, 0)
        self.program['model'] = model
        self.update()
예제 #10
0
class Example(Drawable):
    '''Draw a cube'''    
    cube_vertex = """
        #version 120
        uniform mat4 model;
        uniform mat4 view;
        uniform mat4 projection;
        attribute vec3 position;
        attribute vec2 texcoord;
        varying vec2 v_texcoord;
        void main()
        {
            gl_Position = projection * view * model * vec4(position, 1.0);
            v_texcoord = texcoord;
        }
    """
    
    cube_fragment = """
        #version 120
        uniform sampler2D texture;
        varying vec2 v_texcoord;
        void main()
        {
            float r = texture2D(texture, v_texcoord).r;
            gl_FragColor = vec4(0, r, r, 1);
        }
    """

    def __init__(self):
        vertices, indices, _ = create_cube()
        vertices = VertexBuffer(vertices)
        self.indices = IndexBuffer(indices)
        self.program = Program(self.cube_vertex, self.cube_fragment)

        self.model = np.eye(4)
        self.view = np.eye(4)

        self.program.bind(vertices)
        self.program['texture'] = utils.checkerboard()
        self.program['texture'].interpolation = 'linear'
        self.program['model'] = self.model
        self.program['view'] = self.view

    def draw(self):
        self.program.draw('triangles', self.indices)
예제 #11
0
    def make_mesh(self):
        '''mesh()
        Generates a default mesh (a cube)
        treat it as though it is a property (i.e. not a function)
        ex:
        >>> x = Target((100, 100, 100))
        >>> mesh = Target.mesh
        '''
        cube = Program(cube_vertex, cube_fragment)
        cube.bind(vertices)
        self.program['model'] = model
        self.program['view'] = view
        self.program['projection'] = projection

        if self.mesh is None:
            vertices, indices, _ = create_cube()
            # self.mesh = 
            
        else:
            return self.mesh
예제 #12
0
    def make_mesh(self):
        '''mesh()
        Generates a default mesh (a cube)
        treat it as though it is a property (i.e. not a function)
        ex:
        >>> x = Target((100, 100, 100))
        >>> mesh = Target.mesh
        '''
        cube = Program(cube_vertex, cube_fragment)
        cube.bind(vertices)
        self.program['model'] = model
        self.program['view'] = view
        self.program['projection'] = projection

        if self.mesh is None:
            vertices, indices, _ = create_cube()
            # self.mesh =

        else:
            return self.mesh
예제 #13
0
파일: renderer3d.py 프로젝트: yonghuming/p5
class Renderer3D(OpenGLRenderer):
    def __init__(self):
        super().__init__(src_fbuffer, src_default)
        self.style = Style3D()
        self.normal_prog = Program(src_normal.vert, src_normal.frag)
        self.phong_prog = Program(src_phong.vert, src_phong.frag)
        self.lookat_matrix = np.identity(4)

        # Camera position
        self.camera_pos = np.zeros(3)
        # Lights
        self.MAX_LIGHTS_PER_CATEGORY = 8
        self.ambient_light_color = GlslList(self.MAX_LIGHTS_PER_CATEGORY, 3,
                                            np.float32)
        self.directional_light_dir = GlslList(self.MAX_LIGHTS_PER_CATEGORY, 3,
                                              np.float32)
        self.directional_light_color = GlslList(self.MAX_LIGHTS_PER_CATEGORY,
                                                3, np.float32)
        self.directional_light_specular = GlslList(
            self.MAX_LIGHTS_PER_CATEGORY, 3, np.float32)
        self.point_light_color = GlslList(self.MAX_LIGHTS_PER_CATEGORY, 3,
                                          np.float32)
        self.point_light_pos = GlslList(self.MAX_LIGHTS_PER_CATEGORY, 3,
                                        np.float32)
        self.point_light_specular = GlslList(self.MAX_LIGHTS_PER_CATEGORY, 3,
                                             np.float32)
        self.const_falloff = GlslList(self.MAX_LIGHTS_PER_CATEGORY, 1,
                                      np.float32)
        self.linear_falloff = GlslList(self.MAX_LIGHTS_PER_CATEGORY, 1,
                                       np.float32)
        self.quadratic_falloff = GlslList(self.MAX_LIGHTS_PER_CATEGORY, 1,
                                          np.float32)
        self.curr_linear_falloff, self.curr_quadratic_falloff, self.curr_constant_falloff = 0.0, 0.0, 0.0
        self.light_specular = np.array([0.0] * 3)

    def initialize_renderer(self):
        super().initialize_renderer()
        self.reset_view()

    def reset_view(self):
        self.viewport = (
            0,
            0,
            int(builtins.width * builtins.pixel_x_density),
            int(builtins.height * builtins.pixel_y_density),
        )
        self.texture_viewport = (
            0,
            0,
            builtins.width,
            builtins.height,
        )

        gloo.set_viewport(*self.viewport)  # pylint: disable=no-member

        cz = (builtins.height / 2) / math.tan(math.radians(30))
        self.projection_matrix = matrix.perspective_matrix(
            math.radians(60), builtins.width / builtins.height, 0.1 * cz,
            10 * cz)

        self.transform_matrix = np.identity(4)
        self._update_shader_transforms()

        self.fbuffer_tex_front = Texture2D(
            (builtins.height, builtins.width, 3))
        self.fbuffer_tex_back = Texture2D((builtins.height, builtins.width, 3))
        self.fbuffer.depth_buffer = gloo.RenderBuffer(
            (builtins.height, builtins.width))

        for buf in [self.fbuffer_tex_front, self.fbuffer_tex_back]:
            self.fbuffer.color_buffer = buf
            with self.fbuffer:
                self.clear()

    def clear(self, color=True, depth=True):
        """Clear the renderer background."""
        gloo.set_state(clear_color=self.style.background_color)  # pylint: disable=no-member
        gloo.clear(color=color, depth=depth)  # pylint: disable=no-member

    def clear_lights(self):
        self.ambient_light_color.clear()
        self.directional_light_color.clear()
        self.directional_light_dir.clear()
        self.directional_light_specular.clear()
        self.point_light_color.clear()
        self.point_light_pos.clear()
        self.point_light_specular.clear()
        self.const_falloff.clear()
        self.linear_falloff.clear()
        self.quadratic_falloff.clear()

    def _comm_toggles(self, state=True):
        gloo.set_state(blend=state)  # pylint: disable=no-member
        gloo.set_state(depth_test=state)  # pylint: disable=no-member

        if state:
            gloo.set_state(blend_func=('src_alpha', 'one_minus_src_alpha'))  # pylint: disable=no-member
            gloo.set_state(depth_func='lequal')  # pylint: disable=no-member

    def _update_shader_transforms(self):
        # Default shader
        self.default_prog['projection'] = self.projection_matrix.T.flatten()
        self.default_prog['perspective_matrix'] = self.lookat_matrix.T.flatten(
        )

        # Normal shader
        self.normal_prog['projection'] = self.projection_matrix.T.flatten()
        self.normal_prog['perspective'] = self.lookat_matrix.T.flatten()
        # This is a no-op, meaning that the normals stay in world space, which
        # matches the behavior in p5.js
        normal_transform = np.identity(3)
        # I think the transformation below takes the vertices to camera space, but
        # the results are funky, so it's probably incorrect? - ziyaointl, 2020/07/20
        # normal_transform = np.linalg.inv(self.projection_matrix[:3, :3] @ self.lookat_matrix[:3, :3])
        self.normal_prog['normal_transform'] = normal_transform.flatten()

        # Blinn-Phong Shader
        self.phong_prog['projection'] = self.projection_matrix.T.flatten()
        self.phong_prog['perspective'] = self.lookat_matrix.T.flatten()

    @contextmanager
    def draw_loop(self):
        """The main draw loop context manager.
        """

        self.transform_matrix = np.identity(4)
        self._update_shader_transforms()
        self.fbuffer.color_buffer = self.fbuffer_tex_back

        with self.fbuffer:
            gloo.set_viewport(*self.texture_viewport)  # pylint: disable=no-member
            self._comm_toggles()
            self.fbuffer_prog['texture'] = self.fbuffer_tex_front
            self.fbuffer_prog.draw('triangle_strip')
            self.clear(color=False, depth=True)
            self.clear_lights()

            yield

            self.flush_geometry()
            self.transform_matrix = np.identity(4)

        gloo.set_viewport(*self.viewport)  # pylint: disable=no-member
        self._comm_toggles(False)
        self.clear()
        self.fbuffer_prog['texture'] = self.fbuffer_tex_back
        self.fbuffer_prog.draw('triangle_strip')

        self.fbuffer_tex_front, self.fbuffer_tex_back = self.fbuffer_tex_back, self.fbuffer_tex_front

    def _add_to_draw_queue_simple(self, stype, vertices, idx, color):
        """Adds shape of stype to draw queue
        """
        self.draw_queue.append((stype, (vertices, idx, color, None, None)))

    def tnormals(self, shape):
        """Obtain a list of vertex normals in world coordinates
        """
        if isinstance(shape.material,
                      BasicMaterial):  # Basic shader doesn't need this
            return None
        return shape.vertex_normals @ np.linalg.inv(
            to_3x3(self.transform_matrix) @ to_3x3(shape.matrix))

    def render(self, shape):
        if isinstance(shape, Geometry):
            n = len(shape.vertices)
            # Perform model transform
            # TODO: Investigate moving model transform from CPU to the GPU
            tverts = self._transform_vertices(
                np.hstack([shape.vertices, np.ones((n, 1))]), shape.matrix,
                self.transform_matrix)
            tnormals = self.tnormals(shape)

            edges = shape.edges
            faces = shape.faces

            self.add_to_draw_queue('poly', tverts, edges, faces,
                                   self.style.fill_color,
                                   self.style.stroke_color, tnormals,
                                   self.style.material)

        elif isinstance(shape, PShape):
            fill = shape.fill.normalized if shape.fill else None
            stroke = shape.stroke.normalized if shape.stroke else None

            obj_list = get_render_primitives(shape)
            for obj in obj_list:
                stype, vertices, idx = obj
                # Transform vertices
                vertices = self._transform_vertices(
                    np.hstack([vertices, np.ones((len(vertices), 1))]),
                    shape._matrix, self.transform_matrix)
                # Add to draw queue
                self._add_to_draw_queue_simple(
                    stype, vertices, idx, stroke if stype == 'lines' else fill)

    def add_to_draw_queue(self,
                          stype,
                          vertices,
                          edges,
                          faces,
                          fill=None,
                          stroke=None,
                          normals=None,
                          material=None):
        """Add the given vertex data to the draw queue.

        :param stype: type of shape to be added. Should be one of {'poly',
                'path', 'point'}
        :type stype: str

        :param vertices: (N, 3) array containing the vertices to be drawn.
        :type vertices: np.ndarray

        :param edges: (N, 2) array containing edges as tuples of indices
                into the vertex array. This can be None when not appropriate
                (eg. for points)
        :type edges: None | np.ndarray

        :param faces: (N, 3) array containing faces as tuples of indices
                into the vertex array. For 'point' and 'path' shapes, this can
                be None
        :type faces: np.ndarray

        :param fill: Fill color of the shape as a normalized RGBA tuple.
                When set to `None` the shape doesn't get a fill (default: None)
        :type fill: None | tuple

        :param stroke: Stroke color of the shape as a normalized RGBA
                tuple. When set to `None` the shape doesn't get stroke
                (default: None)
        :type stroke: None | tuple
        // TODO: Update documentation
        // TODO: Unite style-related attributes for both 2D and 3D under one material class
        """

        fill_shape = self.style.fill_enabled and not (fill is None)
        stroke_shape = self.style.stroke_enabled and not (stroke is None)

        if fill_shape and stype not in ['point', 'path']:
            idx = np.array(faces, dtype=np.uint32).ravel()
            self.draw_queue.append(
                ["triangles", (vertices, idx, fill, normals, material)])

        if stroke_shape:
            if stype == 'point':
                idx = np.arange(0, len(vertices), dtype=np.uint32)
                self.draw_queue.append(
                    ["points", (vertices, idx, stroke, normals, material)])
            else:
                idx = np.array(edges, dtype=np.uint32).ravel()
                self.draw_queue.append(
                    ["lines", (vertices, idx, stroke, normals, material)])

    def render_with_shaders(self, draw_type, draw_obj):
        vertices, idx, color, normals, material = draw_obj
        """Like render_default but is aware of shaders other than the basic one"""
        # 0. If material does not need normals nor extra info, strip them out
        # and use the method from superclass
        if material is None or isinstance(
                material, BasicMaterial) or draw_type in ['points', 'lines']:
            OpenGLRenderer.render_default(self, draw_type, [draw_obj[:3]])
            return

        # 1. Get the number of vertices
        num_vertices = len(vertices)

        # 2. Create empty buffers based on the number of vertices.
        #
        data = np.zeros(num_vertices,
                        dtype=[('position', np.float32, 3),
                               ('normal', np.float32, 3)])

        # 3. Loop through all the shapes in the geometry queue adding
        # it's information to the buffer.
        #
        draw_indices = []
        data['position'][0:num_vertices, ] = np.array(vertices)
        draw_indices.append(idx)
        data['normal'][0:num_vertices, ] = np.array(normals)
        self.vertex_buffer.set_data(data)
        self.index_buffer.set_data(np.hstack(draw_indices))

        if isinstance(material, NormalMaterial):
            # 4. Bind the buffer to the shader.
            #
            self.normal_prog.bind(self.vertex_buffer)

            # 5. Draw the shape using the proper shape type and get rid of
            # the buffers.
            #
            self.normal_prog.draw(draw_type, indices=self.index_buffer)
        elif isinstance(material, BlinnPhongMaterial):
            self.phong_prog.bind(self.vertex_buffer)
            self.phong_prog['u_cam_pos'] = self.camera_pos
            # Material attributes
            self.phong_prog['u_ambient_color'] = material.ambient
            self.phong_prog['u_diffuse_color'] = material.diffuse
            self.phong_prog['u_specular_color'] = material.specular
            self.phong_prog['u_shininess'] = material.shininess
            # Directional lights
            self.phong_prog[
                'u_directional_light_count'] = self.directional_light_color.size
            self.phong_prog[
                'u_directional_light_dir'] = self.directional_light_dir.data
            self.phong_prog[
                'u_directional_light_color'] = self.directional_light_color.data
            self.phong_prog[
                'u_directional_light_specular'] = self.directional_light_specular.data
            # Ambient lights
            self.phong_prog[
                'u_ambient_light_count'] = self.ambient_light_color.size
            self.phong_prog[
                'u_ambient_light_color'] = self.ambient_light_color.data
            # Point lights
            self.phong_prog[
                'u_point_light_count'] = self.point_light_color.size
            self.phong_prog[
                'u_point_light_color'] = self.point_light_color.data
            self.phong_prog['u_point_light_pos'] = self.point_light_pos.data
            self.phong_prog[
                'u_point_light_specular'] = self.point_light_specular.data
            # Point light falloffs
            self.phong_prog['u_const_falloff'] = self.const_falloff.data
            self.phong_prog['u_linear_falloff'] = self.linear_falloff.data
            self.phong_prog[
                'u_quadratic_falloff'] = self.quadratic_falloff.data
            # Draw
            self.phong_prog.draw(draw_type, indices=self.index_buffer)
        else:
            raise NotImplementedError("Material not implemented")

    def flush_geometry(self):
        """Flush all the shape geometry from the draw queue to the GPU.
        """
        for index, shape in enumerate(self.draw_queue):
            current_shape, current_obj = self.draw_queue[index][
                0], self.draw_queue[index][1]
            # If current_shape is lines, bring it to the front by epsilon
            # to resolve z-fighting
            if current_shape == 'lines':
                # line_transform is used whenever we render lines to break ties in depth
                # We transform the points to camera space, move them by
                # Z_EPSILON, and them move them back to world space
                line_transform = inv(self.lookat_matrix).dot(
                    translation_matrix(0, 0,
                                       Z_EPSILON).dot(self.lookat_matrix))
                vertices = current_obj[0]
                current_obj = (np.hstack([
                    vertices, np.ones((vertices.shape[0], 1))
                ]).dot(line_transform.T)[:, :3], *current_obj[1:])
            self.render_with_shaders(current_shape, current_obj)

        self.draw_queue = []

    def cleanup(self):
        super(Renderer3D, self).cleanup()
        self.normal_prog.delete()
        self.phong_prog.delete()

    def add_ambient_light(self, r, g, b):
        self.ambient_light_color.add(np.array((r, g, b)))

    def add_directional_light(self, r, g, b, x, y, z):
        self.directional_light_color.add(np.array((r, g, b)))
        self.directional_light_dir.add(np.array((x, y, z)))
        self.directional_light_specular.add(self.light_specular)

    def add_point_light(self, r, g, b, x, y, z):
        self.point_light_color.add(np.array((r, g, b)))
        self.point_light_pos.add(np.array((x, y, z)))
        self.point_light_specular.add(self.light_specular)
        self.const_falloff.add(self.curr_constant_falloff)
        self.linear_falloff.add(self.curr_linear_falloff)
        self.quadratic_falloff.add(self.curr_quadratic_falloff)
예제 #14
0
vertices = VertexBuffer(V)

I = [
    0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 1, 1, 6, 7, 1, 7, 2, 7,
    4, 3, 7, 3, 2, 4, 7, 6, 4, 6, 5
]
indices = IndexBuffer(I)

O = [0, 1, 1, 2, 2, 3, 3, 0, 4, 7, 7, 6, 6, 5, 5, 4, 0, 5, 1, 6, 2, 7, 3, 4]
outline = IndexBuffer(O)

# Build program
# --------------------------------------
program = Program(vertex, fragment)
program.bind(vertices)

# Build view, model, projection & normal
# --------------------------------------
view = np.eye(4, dtype=np.float32)
rotate(view, 20, 1, 0, 0)
translate(view, 0, 1, -8)
model = np.eye(4, dtype=np.float32)
projection = np.eye(4, dtype=np.float32)
program['model'] = model
program['view'] = view
program['o_projection'] = ortho(-10, 10, -10, 10, -10, 20)
phi, theta = 0, 0

program2 = Program(vertex, ilio.read('black.frag'), count=4)
program2['model'] = model
예제 #15
0
vertices = VertexBuffer(V)

I = [0,1,2, 0,2,3,  0,3,4, 0,4,5,  0,5,6, 0,6,1,
     1,6,7, 1,7,2,  7,4,3, 7,3,2,  4,7,6, 4,6,5]
indices = IndexBuffer(I)

O = [0,1, 1,2, 2,3, 3,0,
     4,7, 7,6, 6,5, 5,4,
     0,5, 1,6, 2,7, 3,4 ]
outline = IndexBuffer(O)

# Build program
# --------------------------------------
program = Program(vertex, fragment)
program.bind(vertices)

# Build view, model, projection & normal
# --------------------------------------
view = np.eye(4,dtype=np.float32)
rotate(view, 20, 1, 0, 0)
translate(view, 0,1 ,-8)
model = np.eye(4,dtype=np.float32)
projection = np.eye(4,dtype=np.float32)
program['model'] = model
program['view'] = view
program['o_projection'] = ortho(-10, 10, -10, 10, -10, 20)
phi, theta = 0,0

program2 = Program(vertex, ilio.read('black.frag'), count=4)
program2['model'] = model
예제 #16
0
vertices = VertexBuffer(V)
faces = IndexBuffer(F)
outline = IndexBuffer(O)

# Build view, model, projection & normal
# --------------------------------------
view = np.eye(4, dtype=np.float32)
model = np.eye(4, dtype=np.float32)
projection = np.eye(4, dtype=np.float32)
translate(view, 0, 0, -5)
normal = np.array(np.matrix(np.dot(view, model)).I.T)

# Build program
# --------------------------------------
program = Program(vertex, fragment)
program.bind(vertices)
program["u_light_position"] = 2, 2, 2
program["u_light_intensity"] = 1, 1, 1
program["u_model"] = model
program["u_view"] = view
program["u_normal"] = normal
phi, theta = 0, 0

# OpenGL initalization
# --------------------------------------
gl.glClearColor(1, 1, 1, 1)
gl.glEnable(gl.GL_DEPTH_TEST)
gl.glPolygonOffset(1, 1)
gl.glEnable(gl.GL_LINE_SMOOTH)
gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
gl.glLineWidth(0.75)
예제 #17
0
class Canvas(app.Canvas):

    def __init__(self):
        app.Canvas.__init__(self, title='Framebuffer post-processing',
                            keys='interactive', size=(512, 512))

    def on_initialize(self, event):
        # Build cube data
        # --------------------------------------
        vertices, indices, _ = create_cube()
        vertices = VertexBuffer(vertices)
        self.indices = IndexBuffer(indices)

        # Build program
        # --------------------------------------
        view = np.eye(4, dtype=np.float32)
        model = np.eye(4, dtype=np.float32)
        translate(view, 0, 0, -7)
        self.phi, self.theta = 60, 20
        rotate(model, self.theta, 0, 0, 1)
        rotate(model, self.phi, 0, 1, 0)

        self.cube = Program(cube_vertex, cube_fragment)
        self.cube.bind(vertices)
        self.cube["texture"] = checkerboard()
        self.cube["texture"].interpolation = 'linear'
        self.cube['model'] = model
        self.cube['view'] = view
        
        color = Texture2D((512, 512, 3), interpolation='linear')
        self.framebuffer = FrameBuffer(color, RenderBuffer((512, 512)))

        self.quad = Program(quad_vertex, quad_fragment, count=4)
        self.quad['texcoord'] = [(0, 0), (0, 1), (1, 0), (1, 1)]
        self.quad['position'] = [(-1, -1), (-1, +1), (+1, -1), (+1, +1)]
        self.quad['texture'] = color

        # OpenGL and Timer initalization
        # --------------------------------------
        set_state(clear_color=(.3, .3, .35, 1), depth_test=True)
        self.timer = app.Timer('auto', connect=self.on_timer, start=True)
        self._set_projection(self.size)

    def on_draw(self, event):
        with self.framebuffer:
            set_viewport(0, 0, 512, 512)
            clear(color=True, depth=True)
            set_state(depth_test=True)
            self.cube.draw('triangles', self.indices)
        set_viewport(0, 0, *self.size)
        clear(color=True)
        set_state(depth_test=False)
        self.quad.draw('triangle_strip')

    def on_resize(self, event):
        self._set_projection(event.size)
    
    def _set_projection(self, size):
        width, height = size
        set_viewport(0, 0, width, height)
        projection = perspective(30.0, width / float(height), 2.0, 10.0)
        self.cube['projection'] = projection

    def on_timer(self, event):
        self.theta += .5
        self.phi += .5
        model = np.eye(4, dtype=np.float32)
        rotate(model, self.theta, 0, 0, 1)
        rotate(model, self.phi, 0, 1, 0)
        self.cube['model'] = model
        self.update()
예제 #18
0
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self, size=(512, 512), title="Lighted cube", keys="interactive")
        self.timer = app.Timer("auto", self.on_timer)

        # Build cube data
        V, F, O = create_cube()
        vertices = VertexBuffer(V)
        self.faces = IndexBuffer(F)
        self.outline = IndexBuffer(O)

        # Build view, model, projection & normal
        # --------------------------------------
        self.view = np.eye(4, dtype=np.float32)
        model = np.eye(4, dtype=np.float32)
        translate(self.view, 0, 0, -5)
        normal = np.array(np.matrix(np.dot(self.view, model)).I.T)

        # Build program
        # --------------------------------------
        self.program = Program(vertex, fragment)
        self.program.bind(vertices)
        self.program["u_light_position"] = 2, 2, 2
        self.program["u_light_intensity"] = 1, 1, 1
        self.program["u_model"] = model
        self.program["u_view"] = self.view
        self.program["u_normal"] = normal
        self.phi, self.theta = 0, 0

        # OpenGL initalization
        # --------------------------------------
        gloo.set_state(
            clear_color=(0.30, 0.30, 0.35, 1.00),
            depth_test=True,
            polygon_offset=(1, 1),
            blend_func=("src_alpha", "one_minus_src_alpha"),
            line_width=0.75,
        )
        self.timer.start()

    def on_draw(self, event):
        gloo.clear(color=True, depth=True)
        # program.draw(gl.GL_TRIANGLES, indices)

        # Filled cube
        gloo.set_state(blend=False, depth_test=True, polygon_offset_fill=True)
        self.program["u_color"] = 1, 1, 1, 1
        self.program.draw("triangles", self.faces)

        # Outlined cube
        gloo.set_state(polygon_offset_fill=False, blend=True, depth_mask=False)
        self.program["u_color"] = 0, 0, 0, 1
        self.program.draw("lines", self.outline)
        gloo.set_state(depth_mask=True)

    def on_resize(self, event):
        gloo.set_viewport(0, 0, *event.size)
        projection = perspective(45.0, event.size[0] / float(event.size[1]), 2.0, 10.0)
        self.program["u_projection"] = projection

    def on_timer(self, event):
        self.theta += 0.5
        self.phi += 0.5
        model = np.eye(4, dtype=np.float32)
        rotate(model, self.theta, 0, 0, 1)
        rotate(model, self.phi, 0, 1, 0)
        normal = np.array(np.matrix(np.dot(self.view, model)).I.T)
        self.program["u_model"] = model
        self.program["u_normal"] = normal
        self.update()
예제 #19
0
파일: renderer2d.py 프로젝트: zostercr/p5
class Renderer2D:
    def __init__(self):
        self.default_prog = None
        self.fbuffer_prog = None
        self.texture_prog = None
        self.line_prog = None

        self.fbuffer = None
        self.fbuffer_tex_front = None
        self.fbuffer_tex_back = None

        self.vertex_buffer = None
        self.index_buffer = None

        ## Renderer Globals: USEFUL CONSTANTS
        self.COLOR_WHITE = (1, 1, 1, 1)
        self.COLOR_BLACK = (0, 0, 0, 1)
        self.COLOR_DEFAULT_BG = (0.8, 0.8, 0.8, 1.0)

        ## Renderer Globals: STYLE/MATERIAL PROPERTIES
        ##
        self.background_color = self.COLOR_DEFAULT_BG

        self.fill_color = self.COLOR_WHITE
        self.fill_enabled = True

        self.stroke_color = self.COLOR_BLACK
        self.stroke_enabled = True

        self.tint_color = self.COLOR_BLACK
        self.tint_enabled = False

        ## Renderer Globals: Curves
        self.stroke_weight = 1
        self.stroke_cap = 2
        self.stroke_join = 0

        ## Renderer Globals
        ## VIEW MATRICES, ETC
        ##
        self.viewport = None
        self.texture_viewport = None
        self.transform_matrix = np.identity(4)
        self.modelview_matrix = np.identity(4)
        self.projection_matrix = np.identity(4)

        ## Renderer Globals: RENDERING
        self.draw_queue = []

    def initialize_renderer(self):
        self.fbuffer = FrameBuffer()

        vertices = np.array(
            [[-1.0, -1.0], [+1.0, -1.0], [-1.0, +1.0], [+1.0, +1.0]],
            np.float32)
        texcoords = np.array([[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]],
                             dtype=np.float32)

        self.fbuf_vertices = VertexBuffer(data=vertices)
        self.fbuf_texcoords = VertexBuffer(data=texcoords)

        self.fbuffer_prog = Program(src_fbuffer.vert, src_fbuffer.frag)
        self.fbuffer_prog['texcoord'] = self.fbuf_texcoords
        self.fbuffer_prog['position'] = self.fbuf_vertices

        self.vertex_buffer = VertexBuffer()
        self.index_buffer = IndexBuffer()

        self.default_prog = Program(src_default.vert, src_default.frag)
        self.texture_prog = Program(src_texture.vert, src_texture.frag)
        self.texture_prog['texcoord'] = self.fbuf_texcoords

        self.reset_view()

    def reset_view(self):
        self.viewport = (
            0,
            0,
            int(builtins.width * builtins.pixel_x_density),
            int(builtins.height * builtins.pixel_y_density),
        )
        self.texture_viewport = (
            0,
            0,
            builtins.width,
            builtins.height,
        )

        gloo.set_viewport(*self.viewport)

        cz = (builtins.height / 2) / math.tan(math.radians(30))
        self.projection_matrix = matrix.perspective_matrix(
            math.radians(60), builtins.width / builtins.height, 0.1 * cz,
            10 * cz)
        self.modelview_matrix = matrix.translation_matrix(-builtins.width / 2, \
                    builtins.height / 2, \
                    -cz)
        self.modelview_matrix = self.modelview_matrix.dot(
            matrix.scale_transform(1, -1, 1))

        self.transform_matrix = np.identity(4)

        self.default_prog['modelview'] = self.modelview_matrix.T.flatten()
        self.default_prog['projection'] = self.projection_matrix.T.flatten()

        self.texture_prog['modelview'] = self.modelview_matrix.T.flatten()
        self.texture_prog['projection'] = self.projection_matrix.T.flatten()

        self.line_prog = Program(src_line.vert, src_line.frag)

        self.line_prog['modelview'] = self.modelview_matrix.T.flatten()
        self.line_prog['projection'] = self.projection_matrix.T.flatten()
        self.line_prog["height"] = builtins.height

        self.fbuffer_tex_front = Texture2D(
            (builtins.height, builtins.width, 3))
        self.fbuffer_tex_back = Texture2D((builtins.height, builtins.width, 3))

        for buf in [self.fbuffer_tex_front, self.fbuffer_tex_back]:
            self.fbuffer.color_buffer = buf
            with self.fbuffer:
                self.clear()

    def clear(self, color=True, depth=True):
        """Clear the renderer background."""
        gloo.set_state(clear_color=self.background_color)
        gloo.clear(color=color, depth=depth)

    def _comm_toggles(self, state=True):
        gloo.set_state(blend=state)
        gloo.set_state(depth_test=state)

        if state:
            gloo.set_state(blend_func=('src_alpha', 'one_minus_src_alpha'))
            gloo.set_state(depth_func='lequal')

    @contextmanager
    def draw_loop(self):
        """The main draw loop context manager.
		"""

        self.transform_matrix = np.identity(4)

        self.default_prog['modelview'] = self.modelview_matrix.T.flatten()
        self.default_prog['projection'] = self.projection_matrix.T.flatten()

        self.fbuffer.color_buffer = self.fbuffer_tex_back

        with self.fbuffer:
            gloo.set_viewport(*self.texture_viewport)
            self._comm_toggles()
            self.fbuffer_prog['texture'] = self.fbuffer_tex_front
            self.fbuffer_prog.draw('triangle_strip')

            yield

            self.flush_geometry()
            self.transform_matrix = np.identity(4)

        gloo.set_viewport(*self.viewport)
        self._comm_toggles(False)
        self.clear()
        self.fbuffer_prog['texture'] = self.fbuffer_tex_back
        self.fbuffer_prog.draw('triangle_strip')

        self.fbuffer_tex_front, self.fbuffer_tex_back = self.fbuffer_tex_back, self.fbuffer_tex_front

    def _transform_vertices(self, vertices, local_matrix, global_matrix):
        return np.dot(np.dot(vertices, local_matrix.T), global_matrix.T)[:, :3]

    def _add_to_draw_queue_simple(self, stype, vertices, idx, fill, stroke,
                                  stroke_weight, stroke_cap, stroke_join):
        """Adds shape of stype to draw queue
		"""
        if stype == 'lines':
            self.draw_queue.append(
                (stype, (vertices, idx, stroke, stroke_weight, stroke_cap,
                         stroke_join)))
        else:
            self.draw_queue.append((stype, (vertices, idx, fill)))

    def render(self, shape):
        fill = shape.fill.normalized if shape.fill else None
        stroke = shape.stroke.normalized if shape.stroke else None
        stroke_weight = shape.stroke_weight
        stroke_cap = shape.stroke_cap
        stroke_join = shape.stroke_join

        obj_list = get_render_primitives(shape)
        for obj in obj_list:
            stype, vertices, idx = obj
            # Transform vertices
            vertices = self._transform_vertices(
                np.hstack([vertices, np.ones((len(vertices), 1))]),
                shape._matrix, self.transform_matrix)
            # Add to draw queue
            self._add_to_draw_queue_simple(stype, vertices, idx, fill, stroke,
                                           stroke_weight, stroke_cap,
                                           stroke_join)

    def flush_geometry(self):
        """Flush all the shape geometry from the draw queue to the GPU.
		"""
        current_queue = []
        for index, shape in enumerate(self.draw_queue):
            current_shape = self.draw_queue[index][0]
            current_queue.append(self.draw_queue[index][1])

            if current_shape == "lines":
                self.render_line(current_queue)
            else:
                self.render_default(current_shape, current_queue)

            current_queue = []

        self.draw_queue = []

    def render_default(self, draw_type, draw_queue):
        # 1. Get the maximum number of vertices persent in the shapes
        # in the draw queue.
        #
        if len(draw_queue) == 0:
            return

        num_vertices = 0
        for vertices, _, _ in draw_queue:
            num_vertices = num_vertices + len(vertices)

        # 2. Create empty buffers based on the number of vertices.
        #
        data = np.zeros(num_vertices,
                        dtype=[('position', np.float32, 3),
                               ('color', np.float32, 4)])

        # 3. Loop through all the shapes in the geometry queue adding
        # it's information to the buffer.
        #
        sidx = 0
        draw_indices = []
        for vertices, idx, color in draw_queue:
            num_shape_verts = len(vertices)

            data['position'][sidx:(sidx + num_shape_verts), ] = vertices

            color_array = np.array([color] * num_shape_verts)
            data['color'][sidx:sidx + num_shape_verts, :] = color_array

            draw_indices.append(sidx + idx)

            sidx += num_shape_verts

        self.vertex_buffer.set_data(data)
        self.index_buffer.set_data(np.hstack(draw_indices))

        # 4. Bind the buffer to the shader.
        #
        self.default_prog.bind(self.vertex_buffer)

        # 5. Draw the shape using the proper shape type and get rid of
        # the buffers.
        #
        self.default_prog.draw(draw_type, indices=self.index_buffer)

    def render_line(self, queue):
        '''
		This rendering algorithm works by tesselating the line into
		multiple triangles.

		Reference: https://blog.mapbox.com/drawing-antialiased-lines-with-opengl-8766f34192dc
		'''

        if len(queue) == 0:
            return

        pos = []
        posPrev = []
        posCurr = []
        posNext = []
        markers = []
        side = []

        linewidth = []
        join_type = []
        cap_type = []
        color = []

        for line in queue:
            if len(line[1]) == 0:
                continue

            for segment in line[1]:
                for i in range(
                        len(segment) -
                        1):  # the data is sent to renderer in line segments
                    for j in [0, 0, 1, 0, 1,
                              1]:  # all the vertices of triangles
                        if i + j - 1 >= 0:
                            posPrev.append(line[0][segment[i + j - 1]])
                        else:
                            posPrev.append(line[0][segment[i + j]])

                        if i + j + 1 < len(segment):
                            posNext.append(line[0][segment[i + j + 1]])
                        else:
                            posNext.append(line[0][segment[i + j]])

                        posCurr.append(line[0][segment[i + j]])

                    markers.extend(
                        [1.0, -1.0, -1.0, -1.0, 1.0,
                         -1.0])  # Is the vertex up/below the line segment
                    side.extend([1.0, 1.0, -1.0, 1.0, -1.0,
                                 -1.0])  # Left or right side of the segment
                    pos.extend([line[0][segment[i]]] *
                               6)  # Left vertex of each segment
                    linewidth.extend([line[3]] * 6)
                    join_type.extend([line[5]] * 6)
                    cap_type.extend([line[4]] * 6)
                    color.extend([line[2]] * 6)

        if len(pos) == 0:
            return

        posPrev = np.array(posPrev, np.float32)
        posCurr = np.array(posCurr, np.float32)
        posNext = np.array(posNext, np.float32)
        markers = np.array(markers, np.float32)
        side = np.array(side, np.float32)
        pos = np.array(pos, np.float32)
        linewidth = np.array(linewidth, np.float32)
        join_type = np.array(join_type, np.float32)
        cap_type = np.array(cap_type, np.float32)
        color = np.array(color, np.float32)

        self.line_prog['pos'] = gloo.VertexBuffer(pos)
        self.line_prog['posPrev'] = gloo.VertexBuffer(posPrev)
        self.line_prog['posCurr'] = gloo.VertexBuffer(posCurr)
        self.line_prog['posNext'] = gloo.VertexBuffer(posNext)
        self.line_prog['marker'] = gloo.VertexBuffer(markers)
        self.line_prog['side'] = gloo.VertexBuffer(side)
        self.line_prog['linewidth'] = gloo.VertexBuffer(linewidth)
        self.line_prog['join_type'] = gloo.VertexBuffer(join_type)
        self.line_prog['cap_type'] = gloo.VertexBuffer(cap_type)
        self.line_prog["color"] = gloo.VertexBuffer(color)

        self.line_prog.draw('triangles')

    def render_image(self, image, location, size):
        """Render the image.

		:param image: image to be rendered
		:type image: builtins.Image

		:param location: top-left corner of the image
		:type location: tuple | list | builtins.Vector

		:param size: target size of the image to draw.
		:type size: tuple | list | builtins.Vector
		"""
        self.flush_geometry()

        self.texture_prog[
            'fill_color'] = self.tint_color if self.tint_enabled else self.COLOR_WHITE
        self.texture_prog['transform'] = self.transform_matrix.T.flatten()

        x, y = location
        sx, sy = size
        imx, imy = image.size
        data = np.zeros(4,
                        dtype=[('position', np.float32, 2),
                               ('texcoord', np.float32, 2)])
        data['texcoord'] = np.array(
            [[0.0, 1.0], [1.0, 1.0], [0.0, 0.0], [1.0, 0.0]], dtype=np.float32)
        data['position'] = np.array(
            [[x, y + sy], [x + sx, y + sy], [x, y], [x + sx, y]],
            dtype=np.float32)

        self.texture_prog['texture'] = image._texture
        self.texture_prog.bind(VertexBuffer(data))
        self.texture_prog.draw('triangle_strip')

    def cleanup(self):
        """Run the clean-up routine for the renderer.

		This method is called when all drawing has been completed and the
		program is about to exit.

		"""
        self.default_prog.delete()
        self.fbuffer_prog.delete()
        self.line_prog.delete()
        self.fbuffer.delete()
예제 #20
0
파일: Map2D.py 프로젝트: udde/pybuildings
class Map2D(app.Canvas):
    def __init__(self, data_handler, parent):

        app.Canvas.__init__(self,
                            size=(512, 512),
                            title='map',
                            keys='interactive')

        self.__parent__ = parent
        self.__data_handler = data_handler

        ##read building data
        ##fetch single building
        #building1 = self.__sh.get_single_at_id(1595) #nya
        #building2 = self.__sh.get_single_at_id(1999) #stryk
        #building3 = self.__sh.get_single_at_id(1886) #strykbrada
        #building4 = self.__sh.get_single_at_id(1722) #Gula vid bron
        #building5 = self.__sh.get_single_at_id(1723) #
        ##and its vertices
        #verts1 = building1.gl_ready_vertices()
        #verts2 = building2.gl_ready_vertices()
        #verts3 = building3.gl_ready_vertices()
        #verts4 = building4.gl_ready_vertices()
        #verts5 = building5.gl_ready_vertices()

        self.all_buildings = self.__data_handler.get_all_buildings()

        all_pos = self.all_buildings[0].gl_ready_vertices()

        for building in self.all_buildings[1:]:
            all_pos = np.vstack((all_pos, building.gl_ready_vertices()))

        abets = self.__data_handler.get_single_at_id(1886)
        abets = abets.gl_ready_vertices()

        #Problem: 977, 1061, 1342(tva stora hal), 1389(hal), 1393(hal), 1434(hal), 1327(rese)
        #Error 1072, 1327(rese). 1472(?!?!?), 1504(!?!?!)
        #for j in range(100000):
        #    for i in range(1503, 1504):
        #print("----------------\n----------------",i)
        #all_pos = all_buildings[i].gl_ready_vertices()

        self.translate_by = np.mean(abets[:], 0)
        self.scale = 1.0

        all_pos = (all_pos - self.translate_by) * self.scale

        allverts = np.zeros(len(all_pos), [('position', np.float32, 2)])
        allverts['position'] = all_pos

        self.selectedverts = np.zeros(len(abets),
                                      [('position', np.float32, 2)])
        self.selectedverts['position'] = (abets -
                                          self.translate_by) * self.scale

        self.vertices = VertexBuffer(allverts)
        self.selectedvertices = VertexBuffer(self.selectedverts)
        #self.indices = IndexBuffer(I)

        # Build program
        self.program = Program(vertex, fragment)
        self.program.bind(self.vertices)

        self.cam2 = Cam3D.Camera([0, 0, 250], [0, 0, 0], [0, 1, 0],
                                 45.0,
                                 self.size[0] / float(self.size[1]),
                                 0.001,
                                 10000.0,
                                 is_2d=True)

        # Build view, model, projection & normal
        self.program['model'] = np.eye(
            4, dtype=np.float32)  #models are at palce from beginnings?
        self.program['model'] = np.transpose(vut.rotx(-10))

        self.program['view'] = self.cam2.view

        projection = perspective(45.0, self.size[0] / float(self.size[1]), 1.0,
                                 1000.0)
        self.program['projection'] = projection

        self.phi, self.theta = 0, 0

        gloo.set_state(clear_color=(0.70, 0.70, 0.7, 1.00), depth_test=True)
        self.set_selected([1999])
        self.activate_zoom()
        self.timer = app.Timer('auto', self.on_timer, start=True)

        self.show()

    def set_selected(self, ids):

        #building = self.__data_handler.get_single_at_id(id)
        #verts2 = building.gl_ready_vertices()

        self.selectedverts = np.zeros(0, [('position', np.float32, 2)])

        for id in ids:
            building = self.__data_handler.get_single_at_id(id)
            verts = building.gl_ready_vertices()
            data = np.zeros(len(verts), [('position', np.float32, 2)])
            data['position'] = (verts - self.translate_by) * self.scale
            self.selectedverts = np.concatenate([self.selectedverts, data])

        #self.selectedverts['position'] = (verts2 - self.translate_by) * self.scale
        self.selectedvertices = VertexBuffer(self.selectedverts)

        selected_pos = np.mean(self.all_buildings[id].points,
                               0) - self.translate_by
        self.cam2.translate_to(selected_pos)
        self.program['view'] = self.cam2.view

        self.update()

    def on_mouse_press(self, event):

        if event.button == 1:

            self.cam2.is_move = True
            self.cam2.is_rotate = False

        if event.button == 2:

            self.cam2.is_move = False
            self.cam2.is_rotate = True

        self.cam2.prev_mouse_pos = event.pos

    def on_mouse_release(self, event):

        self.cam2.is_move = False
        self.cam2.is_rotate = False

    def on_mouse_move(self, event):

        if self.cam2.is_move:

            self.cam2.translate2d(-1 * np.array(
                event.pos - self.cam2.prev_mouse_pos, dtype=np.float32))
            self.program['view'] = self.cam2.view
            self.update()

        elif self.cam2.is_rotate:

            self.cam2.rotx(-1 * np.array(
                (event.pos - self.cam2.prev_mouse_pos))[1:2])
            self.cam2.roty(-1 * np.array(
                (event.pos - self.cam2.prev_mouse_pos))[0:1])
            self.program['view'] = self.cam2.view
            self.update()

        self.cam2.prev_mouse_pos = event.pos

    def on_mouse_wheel(self, event):

        self.cam2.scale(event.delta[1])
        self.program['view'] = self.cam2.view
        self.update()

    def on_draw(self, event):

        gloo.clear(color=True, depth=True)

        self.program.set_shaders(vertex, fragment_active)
        self.program.bind(self.selectedvertices)
        self.program.draw('triangles')

        self.program.set_shaders(vertex, fragment)
        self.program.bind(self.vertices)
        self.program.draw('triangles')

    def on_resize(self, event):

        self.activate_zoom()

    def activate_zoom(self):

        gloo.set_viewport(0, 0, *self.physical_size)
        projection = perspective(45.0, self.size[0] / float(self.size[1]), 1.0,
                                 10000.0)
        self.program['projection'] = projection
        self.update()

    def on_timer(self, event):

        self.update()

    def on_resize(self, event):

        self.activate_zoom()

    def on_key_press(self, event):

        modifiers = [key.name for key in event.modifiers]
        print('Key pressed - text: %r, key: %s, modifiers: %r' %
              (event.text, event.key.name, modifiers))

    def on_key_release(self, event):

        modifiers = [key.name for key in event.modifiers]
        print('Key released - text: %r, key: %s, modifiers: %r' %
              (event.text, event.key.name, modifiers))
예제 #21
0
class Canvas(app.Canvas):
    def __init__(self,
                 image_acquisition_manager=None,
                 width=640,
                 height=480,
                 fps=50.,
                 background_color='gray',
                 vertex_shader=None,
                 fragment_shader=None):
        """
        NOTE: fps should be smaller than or equal to 50 fps. If it's exceed
        VisPy drags down the acquisition performance. This is the issue we
        have to investigate.
        """

        self._vertex_shader = vertex_shader if vertex_shader else """
            // Uniforms
            uniform mat4 u_model;
            uniform mat4 u_view;
            uniform mat4 u_projection;

            // Attributes
            attribute vec2 a_position;
            attribute vec2 a_texcoord;

            // Varyings
            varying vec2 v_texcoord;

            // Main
            void main (void)
            {
                v_texcoord = a_texcoord;
                gl_Position = u_projection * u_view * u_model * vec4(a_position, 0.0, 1.0);
            }
        """

        self._fragment_shader = fragment_shader if fragment_shader else """
            varying vec2 v_texcoord;
            uniform sampler2D texture;
            void main()
            {
                gl_FragColor = texture2D(texture, v_texcoord);
            }
        """

        #
        self._iaa = image_acquisition_manager

        #
        app.Canvas.__init__(self,
                            size=(width, height),
                            vsync=True,
                            autoswap=True)

        #
        self._program = None
        self._data = None
        self._coordinate = None
        self._origin = None
        self._translate = 0.
        self._latest_translate = self._translate
        self._magnification = 1.

        #
        self._background_color = background_color
        self._has_filled_texture = False
        self._width, self._height = width, height

        #
        self._is_dragging = False

        # If it's True , the canvas keeps image acquisition but do not
        # draw images on the canvas.
        self._pause_drawing = False

        # Apply shaders.
        self.set_shaders(vertex_shader=self._vertex_shader,
                         fragment_shader=self._fragment_shader)

        #
        self._timer = app.Timer(1. / fps, connect=self.update, start=True)

    @property
    def iaa(self):
        return self._iaa

    @iaa.setter
    def iaa(self, value):
        self._iaa = value

    def set_shaders(self, vertex_shader=None, fragment_shader=None):
        #
        vs = vertex_shader if vertex_shader else self._vertex_shader
        fs = fragment_shader if fragment_shader else self._fragment_shader
        self._program = Program(vs, fs, count=4)

        #
        self._data = np.zeros(4,
                              dtype=[('a_position', np.float32, 2),
                                     ('a_texcoord', np.float32, 2)])

        #
        self._data['a_texcoord'] = np.array([[0., 1.], [1., 1.], [0., 0.],
                                             [1., 0.]])

        #
        self._program['u_model'] = np.eye(4, dtype=np.float32)
        self._program['u_view'] = np.eye(4, dtype=np.float32)

        #
        self._coordinate = [0, 0]
        self._origin = [0, 0]

        #
        self._program['texture'] = np.zeros((self._height, self._width),
                                            dtype='uint8')

        #
        self.apply_magnification()

    def set_rect(self, width, height):
        #
        self._has_filled_texture = False

        #
        updated = False

        #
        if self._width != width or self._height != height:
            self._width = width
            self._height = height
            updated = True

        #
        if updated:
            self.apply_magnification()

    def on_draw(self, event):
        # Clear the canvas in gray.
        gloo.clear(color=self._background_color)
        self._update_texture()

    def _update_texture(self):
        # Fetch a buffer.
        try:
            with self._iaa.fetch_buffer_manager(timeout_ms=0.1) as bm:
                # Set the image as the texture of our canvas.
                if not self._pause_drawing and bm:
                    # Update the canvas size if needed.
                    self.set_rect(bm.buffer.width, bm.buffer.height)

                    #
                    update = True
                    power = 0

                    #
                    pixel_format = bm.pixel_format
                    if pixel_format in component_8bit_formats:
                        payload = bm.payload
                    else:
                        if pixel_format in component_10bit_formats:
                            power = 2
                        elif pixel_format in component_12bit_formats:
                            power = 4
                        elif pixel_format in component_14bit_formats:
                            power = 6
                        elif pixel_format in component_16bit_formats:
                            power = 8
                        else:
                            update = False

                        if update:
                            payload = bm.payload / (2**power)

                        # Explicitly cast the payload to an uint8 array.
                        payload = payload.astype(np.uint8)

                    if update:
                        self._program['texture'] = payload

                # Draw the texture.
                self._draw()

        except AttributeError:
            # Harvester Core has not started image acquisition so
            # calling fetch_buffer() raises AttributeError because
            # None object is used for the with statement.

            # Update on June 15th, 2018:
            # According to a VisPy developer, they have not finished
            # porting VisPy to PyQt5. Once they finished the development
            # we should try it out if it gives us the maximum refresh rate.
            # See the following URL to check the latest information:
            #
            #     https://github.com/vispy/vispy/issues/1394

            # Draw the texture.
            self._draw()

    def _draw(self):
        self._program.draw('triangle_strip')

    def on_resize(self, event):
        self.apply_magnification()

    def apply_magnification(self):
        #
        canvas_w, canvas_h = self.physical_size
        gloo.set_viewport(0, 0, canvas_w, canvas_h)

        #
        ratio = self._magnification
        w, h = self._width, self._height

        self._program['u_projection'] = ortho(
            self._coordinate[0], canvas_w * ratio + self._coordinate[0],
            self._coordinate[1], canvas_h * ratio + self._coordinate[1], -1, 1)

        x, y = int((canvas_w * ratio - w) / 2), int(
            (canvas_h * ratio - h) / 2)  # centering x & y

        #
        self._data['a_position'] = np.array([[x, y], [x + w, y], [x, y + h],
                                             [x + w, y + h]])

        #
        self._program.bind(gloo.VertexBuffer(self._data))

    def on_mouse_wheel(self, event):
        self._translate += event.delta[1]
        power = 7. if is_running_on_macos() else 5.  # 2 ** power
        stride = 4. if is_running_on_macos() else 7.
        translate = self._translate
        translate = min(power * stride, translate)
        translate = max(-power * stride, translate)
        self._translate = translate
        self._magnification = 2**-(self._translate / stride)
        if self._latest_translate != self._translate:
            self.apply_magnification()
            self._latest_translate = self._translate

    def on_mouse_press(self, event):
        self._is_dragging = True
        self._origin = event.pos

    def on_mouse_release(self, event):
        self._is_dragging = False

    def on_mouse_move(self, event):
        if self._is_dragging:
            adjustment = 2. if is_running_on_macos() else 1.
            ratio = self._magnification * adjustment
            delta = event.pos - self._origin
            self._origin = event.pos
            self._coordinate[0] -= (delta[0] * ratio)
            self._coordinate[1] += (delta[1] * ratio)
            self.apply_magnification()

    def pause_drawing(self, pause=True):
        self._pause_drawing = pause

    def toggle_drawing(self):
        self._pause_drawing = False if self._pause_drawing else True

    @property
    def is_pausing(self):
        return True if self._pause_drawing else False

    def resume_drawing(self):
        self._pause_drawing = False

    @property
    def background_color(self):
        return self._background_color

    @background_color.setter
    def background_color(self, color):
        self._background_color = color
예제 #22
0
class Drawable(object):
    name = "Default Drawable"
    skip = False

    def __init__(self, *args, **kwargs):
        '''Drawable(*args, **kwargs) -> Drawable
        Everything is tracked internally, different drawables will handle things differently
        Inherit from this for all drawables.

        Inheriting:
            You must define a make_mesh, make_shaders, and draw method. 
            If you do not make shaders, you will get a default
            If you do not make a mesh, you'll get a square that takes up the screen

        '''
        self.model = np.eye(4)
        self.view = np.eye(4)
        self.projection = np.eye(4)

        self.mesh = self.make_mesh()
        self.vert_shader, self.frag_shader = self.make_shaders()
        self.program = Program(self.vert_shader, self.frag_shader)
        self.program.bind(VertexBuffer(self.mesh))
        if hasattr(self, make_texture):
            self.texture = self.make_texture()
            assert isinstance(self.texture,
                              Texture2D), "Texture passed is not a texture!"

        self.program['texture'] = self.texture
        cube["texture"].interpolation = 'linear'

    def __setitem__(self, key, value):
        self.bind(key, value)

    def translate(self, *args):
        translate(self.model, *args)
        self.program['model'] = self.model

    def rotate(self, *args):
        rotate(self.model, *args)
        self.program['model'] = self.model

    def bind(self, key, value):
        '''Rebind a single program item to a value'''
        self.program[key] = value

    def bind_multiple(self, **kwargs):
        '''rebind multiple things!'''
        for key, value in kwargs:
            self.bind(key, value)

    def make_mesh(self):
        '''mesh()
        Generates a default mesh (a cube)
        treat it as though it is a property (i.e. not a function)
        ex:
        >>> x = Target((100, 100, 100))
        >>> mesh = Target.mesh
        '''
        cube = Program(cube_vertex, cube_fragment)
        cube.bind(vertices)
        self.program['model'] = model
        self.program['view'] = view
        self.program['projection'] = projection

        if self.mesh is None:
            vertices, indices, _ = create_cube()
            # self.mesh =

        else:
            return self.mesh

    def make_shaders(self):
        '''shader -> (vertex, fragment) 
        Returns vertex and fragment shaders as 2-tuple of strings

        THIS IS A DEFAULT SHADER
        '''
        fragment = ''
        vertex = ''
        return vertex, fragment

    def make_texture(self):
        '''Make a texture
        THIS IS A DEFAULT TEXTURE
        '''
        texture = utils.checkerboard()
        return texture

    def update(self):
        pass

    def draw(self):
        self.program.draw()
예제 #23
0
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self,
                            size=(512, 512),
                            title='Lighted cube',
                            keys='interactive')
        self.timer = app.Timer('auto', self.on_timer)

        # Build cube data
        V, F, outline = create_cube()
        vertices = VertexBuffer(V)
        self.faces = IndexBuffer(F)
        self.outline = IndexBuffer(outline)

        # Build view, model, projection & normal
        # --------------------------------------
        self.view = translate((0, 0, -5))
        model = np.eye(4, dtype=np.float32)
        normal = np.array(np.matrix(np.dot(self.view, model)).I.T)

        # Build program
        # --------------------------------------
        self.program = Program(vertex, fragment)
        self.program.bind(vertices)
        self.program["u_light_position"] = 2, 2, 2
        self.program["u_light_intensity"] = 1, 1, 1
        self.program["u_model"] = model
        self.program["u_view"] = self.view
        self.program["u_normal"] = normal
        self.phi, self.theta = 0, 0

        self.activate_zoom()

        # OpenGL initialization
        # --------------------------------------
        gloo.set_state(clear_color=(0.30, 0.30, 0.35, 1.00),
                       depth_test=True,
                       polygon_offset=(1, 1),
                       blend_func=('src_alpha', 'one_minus_src_alpha'),
                       line_width=0.75)
        self.timer.start()

        self.show()

    def on_draw(self, event):
        gloo.clear(color=True, depth=True)
        # program.draw(gl.GL_TRIANGLES, indices)

        # Filled cube
        gloo.set_state(blend=False, depth_test=True, polygon_offset_fill=True)
        self.program['u_color'] = 1, 1, 1, 1
        self.program.draw('triangles', self.faces)

        # Outlined cube
        gloo.set_state(polygon_offset_fill=False, blend=True, depth_mask=False)
        self.program['u_color'] = 0, 0, 0, 1
        self.program.draw('lines', self.outline)
        gloo.set_state(depth_mask=True)

    def on_resize(self, event):
        self.activate_zoom()

    def activate_zoom(self):
        gloo.set_viewport(0, 0, *self.physical_size)
        projection = perspective(45.0, self.size[0] / float(self.size[1]), 2.0,
                                 10.0)
        self.program['u_projection'] = projection

    def on_timer(self, event):
        self.theta += .5
        self.phi += .5
        model = np.dot(rotate(self.theta, (0, 0, 1)),
                       rotate(self.phi, (0, 1, 0)))
        normal = np.linalg.inv(np.dot(self.view, model)).T
        self.program['u_model'] = model
        self.program['u_normal'] = normal
        self.update()
예제 #24
0
class VispyRenderer2D(OpenGLRenderer):
    def __init__(self):
        super().__init__(src_fbuffer, src_default)
        self.texture_prog = None
        self.line_prog = None
        self.modelview_matrix = np.identity(4)

    def initialize_renderer(self):
        super().initialize_renderer()
        self.texture_prog = Program(src_texture.vert, src_texture.frag)
        self.texture_prog['texcoord'] = self.fbuf_texcoords
        self.reset_view()

    def reset_view(self):
        self.viewport = (
            0,
            0,
            int(builtins.width * builtins.pixel_x_density),
            int(builtins.height * builtins.pixel_y_density),
        )
        self.texture_viewport = (
            0,
            0,
            builtins.width,
            builtins.height,
        )

        gloo.set_viewport(*self.viewport)  # pylint: disable=no-member

        cz = (builtins.height / 2) / math.tan(math.radians(30))
        self.projection_matrix = matrix.perspective_matrix(
            math.radians(60), builtins.width / builtins.height, 0.1 * cz,
            10 * cz)
        self.modelview_matrix = matrix.translation_matrix(
            -builtins.width / 2, builtins.height / 2, -cz)
        self.modelview_matrix = self.modelview_matrix.dot(
            matrix.scale_transform(1, -1, 1))

        self.transform_matrix = np.identity(4)

        self.default_prog['modelview'] = self.modelview_matrix.T.flatten()
        self.default_prog['projection'] = self.projection_matrix.T.flatten()

        self.texture_prog['modelview'] = self.modelview_matrix.T.flatten()
        self.texture_prog['projection'] = self.projection_matrix.T.flatten()

        self.line_prog = Program(src_line.vert, src_line.frag)

        self.line_prog['modelview'] = self.modelview_matrix.T.flatten()
        self.line_prog['projection'] = self.projection_matrix.T.flatten()
        self.line_prog["height"] = builtins.height

        self.fbuffer_tex_front = Texture2D(
            (builtins.height, builtins.width, 3))
        self.fbuffer_tex_back = Texture2D((builtins.height, builtins.width, 3))

        for buf in [self.fbuffer_tex_front, self.fbuffer_tex_back]:
            self.fbuffer.color_buffer = buf
            with self.fbuffer:
                self.clear()

    def clear(self, color=True, depth=True):
        """Clear the renderer background."""
        gloo.set_state(clear_color=self.style.background_color)  # pylint: disable=no-member
        gloo.clear(color=color, depth=depth)  # pylint: disable=no-member

    def _comm_toggles(self, state=True):
        gloo.set_state(blend=state)  # pylint: disable=no-member
        gloo.set_state(depth_test=state)  # pylint: disable=no-member

        if state:
            gloo.set_state(blend_func=('src_alpha', 'one_minus_src_alpha'))  # pylint: disable=no-member
            gloo.set_state(depth_func='lequal')  # pylint: disable=no-member

    @contextmanager
    def draw_loop(self):
        """The main draw loop context manager.
        """

        self.transform_matrix = np.identity(4)

        self.default_prog['modelview'] = self.modelview_matrix.T.flatten()
        self.default_prog['projection'] = self.projection_matrix.T.flatten()

        self.fbuffer.color_buffer = self.fbuffer_tex_back

        with self.fbuffer:
            gloo.set_viewport(*self.texture_viewport)  # pylint: disable=no-member
            self._comm_toggles()
            self.fbuffer_prog['texture'] = self.fbuffer_tex_front
            self.fbuffer_prog.draw('triangle_strip')

            yield

            self.flush_geometry()
            self.transform_matrix = np.identity(4)

        gloo.set_viewport(*self.viewport)  # pylint: disable=no-member
        self._comm_toggles(False)
        self.clear()
        self.fbuffer_prog['texture'] = self.fbuffer_tex_back
        self.fbuffer_prog.draw('triangle_strip')

        self.fbuffer_tex_front, self.fbuffer_tex_back = self.fbuffer_tex_back, self.fbuffer_tex_front

    def _add_to_draw_queue(self, stype, vertices, idx, fill, stroke,
                           stroke_weight, stroke_cap, stroke_join):
        """Adds shape of stype to draw queue
        """
        if stype == 'lines':
            self.draw_queue.append(
                (stype, (vertices, idx, stroke, stroke_weight, stroke_cap,
                         stroke_join)))
        else:
            self.draw_queue.append((stype, (vertices, idx, fill)))

    def render(self, shape):
        fill = shape.fill.normalized if shape.fill else None
        stroke = shape.stroke.normalized if shape.stroke else None
        stroke_weight = shape.stroke_weight
        stroke_cap = shape.stroke_cap
        stroke_join = shape.stroke_join

        obj_list = get_render_primitives(shape)
        for obj in obj_list:
            stype, vertices, idx = obj
            # Convert 2D vertices to 3D by adding "0" column, needed for further transformations
            if len(vertices[0]) == 2:
                vertices = np.hstack([vertices, np.zeros((len(vertices), 1))])
            # Transform vertices
            vertices = self._transform_vertices(
                np.hstack([vertices, np.ones((len(vertices), 1))]),
                shape._matrix, self.transform_matrix)
            # Add to draw queue
            self._add_to_draw_queue(stype, vertices, idx, fill, stroke,
                                    stroke_weight, stroke_cap, stroke_join)

    def flush_geometry(self):
        """Flush all the shape geometry from the draw queue to the GPU.
        """
        current_queue = []
        for index, shape in enumerate(self.draw_queue):
            current_shape = self.draw_queue[index][0]
            current_queue.append(self.draw_queue[index][1])

            if current_shape == "lines":
                self.render_line(current_queue)
            else:
                self.render_default(current_shape, current_queue)

            current_queue = []

        self.draw_queue = []

    def render_line(self, queue):
        '''
        This rendering algorithm works by tesselating the line into
        multiple triangles.

        Reference: https://blog.mapbox.com/drawing-antialiased-lines-with-opengl-8766f34192dc
        '''

        if len(queue) == 0:
            return

        pos = []
        posPrev = []
        posCurr = []
        posNext = []
        markers = []
        side = []

        linewidth = []
        join_type = []
        cap_type = []
        color = []

        stroke_cap_codes = {'PROJECT': 0, 'SQUARE': 1, 'ROUND': 2}

        stroke_join_codes = {'MITER': 0, 'BEVEL': 1, 'ROUND': 2}

        for line in queue:
            if len(line[1]) == 0:
                continue

            for segment in line[1]:
                for i in range(
                        len(segment) -
                        1):  # the data is sent to renderer in line segments
                    for j in [0, 0, 1, 0, 1,
                              1]:  # all the vertices of triangles
                        if i + j - 1 >= 0:
                            posPrev.append(line[0][segment[i + j - 1]])
                        else:
                            posPrev.append(line[0][segment[i + j]])

                        if i + j + 1 < len(segment):
                            posNext.append(line[0][segment[i + j + 1]])
                        else:
                            posNext.append(line[0][segment[i + j]])

                        posCurr.append(line[0][segment[i + j]])

                    # Is the vertex up/below the line segment
                    markers.extend([1.0, -1.0, -1.0, -1.0, 1.0, -1.0])
                    # Left or right side of the segment
                    side.extend([1.0, 1.0, -1.0, 1.0, -1.0, -1.0])
                    # Left vertex of each segment
                    pos.extend([line[0][segment[i]]] * 6)
                    linewidth.extend([line[3]] * 6)
                    join_type.extend([stroke_join_codes[line[5]]] * 6)
                    cap_type.extend([stroke_cap_codes[line[4]]] * 6)
                    color.extend([line[2]] * 6)

        if len(pos) == 0:
            return

        posPrev = np.array(posPrev, np.float32)
        posCurr = np.array(posCurr, np.float32)
        posNext = np.array(posNext, np.float32)
        markers = np.array(markers, np.float32)
        side = np.array(side, np.float32)
        pos = np.array(pos, np.float32)
        linewidth = np.array(linewidth, np.float32)
        join_type = np.array(join_type, np.float32)
        cap_type = np.array(cap_type, np.float32)
        color = np.array(color, np.float32)

        self.line_prog['pos'] = gloo.VertexBuffer(pos)
        self.line_prog['posPrev'] = gloo.VertexBuffer(posPrev)
        self.line_prog['posCurr'] = gloo.VertexBuffer(posCurr)
        self.line_prog['posNext'] = gloo.VertexBuffer(posNext)
        self.line_prog['marker'] = gloo.VertexBuffer(markers)
        self.line_prog['side'] = gloo.VertexBuffer(side)
        self.line_prog['linewidth'] = gloo.VertexBuffer(linewidth)
        self.line_prog['join_type'] = gloo.VertexBuffer(join_type)
        self.line_prog['cap_type'] = gloo.VertexBuffer(cap_type)
        self.line_prog["color"] = gloo.VertexBuffer(color)

        self.line_prog.draw('triangles')

    def render_image(self, image, location, size):
        """Render the image.

        :param image: image to be rendered
        :type image: builtins.Image

        :param location: top-left corner of the image
        :type location: tuple | list | builtins.Vector

        :param size: target size of the image to draw.
        :type size: tuple | list | builtins.Vector
        """
        self.flush_geometry()

        self.texture_prog[
            'fill_color'] = self.style.tint_color if self.style.tint_enabled else COLOR_WHITE
        self.texture_prog['transform'] = self.transform_matrix.T.flatten()

        x, y = location
        sx, sy = size
        imx, imy = image.size
        data = np.zeros(4,
                        dtype=[('position', np.float32, 2),
                               ('texcoord', np.float32, 2)])
        data['texcoord'] = np.array(
            [[0.0, 1.0], [1.0, 1.0], [0.0, 0.0], [1.0, 0.0]], dtype=np.float32)
        data['position'] = np.array(
            [[x, y + sy], [x + sx, y + sy], [x, y], [x + sx, y]],
            dtype=np.float32)

        self.texture_prog['texture'] = image._texture
        self.texture_prog.bind(VertexBuffer(data))
        self.texture_prog.draw('triangle_strip')

    def cleanup(self):
        """Run the clean-up routine for the renderer.

        This method is called when all drawing has been completed and the
        program is about to exit.

        """
        OpenGLRenderer.cleanup(self)
        self.line_prog.delete()

    def render_shape(self, shape):
        self.render(shape)
        for child_shape in shape.children:
            self.render_shape(child_shape)

    def line(self, *args):
        path = args[0]
        self.render_shape(PShape(vertices=path, shape_type=SType.LINES))

    def bezier(self, *args):
        vertices = args[0]
        self.render_shape(
            PShape(vertices=vertices, shape_type=SType.LINE_STRIP))

    def curve(self, *args):
        vertices = args[0]
        self.render_shape(
            PShape(vertices=vertices, shape_type=SType.LINE_STRIP))

    def triangle(self, *args):
        path = args[0]
        self.render_shape(PShape(vertices=path, shape_type=SType.TRIANGLES))

    def quad(self, *args):
        path = args[0]
        self.render_shape(PShape(vertices=path, shape_type=SType.QUADS))

    def arc(self, *args):
        center = args[0]
        dim = args[1]
        start_angle = args[2]
        stop_angle = args[3]
        mode = args[4]

        self.render_shape(Arc(center, dim, start_angle, stop_angle, mode))

    def shape(self, vertices, contours, shape_type, *args):
        """Render a Pshape"""
        self.render_shape(
            PShape(vertices=vertices, contours=contours,
                   shape_type=shape_type))
예제 #25
0
class Canvas(app.Canvas):
    def __init__(self, sensor=None, i=0, yaw=False, title='Rotating Cube'):
        app.Canvas.__init__(self,
                            size=(640, 640),
                            title=title,
                            keys='interactive')
        self.timer = app.Timer('auto', self.on_timer)
        self.sensor = sensor
        self.i = i
        self.yaw = yaw

        # Build cube data
        V, I, O = create_cube()
        vertices = VertexBuffer(V)
        self.faces = IndexBuffer(I)
        self.outline = IndexBuffer(O)

        # Build program
        # --------------------------------------
        self.program = Program(vertex, fragment)
        self.program.bind(vertices)

        # Build view, model, projection & normal
        # --------------------------------------
        view = translate((0, 0, -5))
        model = np.eye(4, dtype=np.float32)

        self.program['u_model'] = model
        self.program['u_view'] = view
        self.theta, self.psi, self.phi = 0, 0, 0

        self.activate_zoom()

        # OpenGL initialization
        # --------------------------------------
        gloo.set_state(clear_color=(0.30, 0.30, 0.35, 1.00),
                       depth_test=True,
                       polygon_offset=(1, 1),
                       line_width=0.75,
                       blend_func=('src_alpha', 'one_minus_src_alpha'))
        self.timer.start()

        self.show()

    def on_draw(self, event):
        gloo.clear(color=True, depth=True)

        # Filled cube
        gloo.set_state(blend=False, depth_test=True, polygon_offset_fill=True)
        self.program['u_color'] = 1, 1, 1, 1
        self.program.draw('triangles', self.faces)

        # Outlined cube
        gloo.set_state(blend=True, depth_mask=False, polygon_offset_fill=False)
        self.program['u_color'] = 0, 0, 0, 1
        self.program.draw('lines', self.outline)
        gloo.set_state(depth_mask=True)

    def on_resize(self, event):
        self.activate_zoom()

    def activate_zoom(self):
        gloo.set_viewport(0, 0, *self.physical_size)
        projection = perspective(45.0, self.size[0] / float(self.size[1]), 2.0,
                                 10.0)
        self.program['u_projection'] = projection

    def on_timer(self, event):
        if self.sensor is not None:
            data = next(self.sensor)
            self.theta, self.psi, self.phi = data[self.i]
            self.theta = -self.theta

            # read yaw from gyro
            if self.yaw:
                self.phi = data[2][2]
            else:
                self.phi = 0
        else:
            self.theta += .5
            self.phi += .5
#        self.program['u_model'] = np.dot(rotate(self.theta, (1, 0, 0)),
#                                         rotate(self.psi, (0, 0, 1)))
        self.program['u_model'] = np.dot(
            rotate(self.theta, (1, 0, 0)),
            np.dot(rotate(self.phi, (0, 1, 0)), rotate(self.psi, (0, 0, 1))))
        self.update()
예제 #26
0
class Renderer3D:
    def __init__(self):
        self.default_prog = None

        self.fbuffer = None
        self.fbuffer_tex_front = None
        self.fbuffer_tex_back = None

        self.vertex_buffer = None
        self.index_buffer = None

        ## Renderer Globals: USEFUL CONSTANTS
        self.COLOR_WHITE = (1, 1, 1, 1)
        self.COLOR_BLACK = (0, 0, 0, 1)
        self.COLOR_DEFAULT_BG = (0.8, 0.8, 0.8, 1.0)

        ## Renderer Globals: STYLE/MATERIAL PROPERTIES
        ##
        self.background_color = self.COLOR_DEFAULT_BG

        self.fill_color = self.COLOR_WHITE
        self.fill_enabled = True

        self.stroke_color = self.COLOR_BLACK
        self.stroke_enabled = True

        self.tint_color = self.COLOR_BLACK
        self.tint_enabled = False

        ## Renderer Globals: Curves
        self.stroke_weight = 1
        self.stroke_cap = 2
        self.stroke_join = 0

        ## Renderer Globals
        ## VIEW MATRICES, ETC
        ##
        self.viewport = None
        self.texture_viewport = None
        self.transform_matrix = np.identity(4)
        self.projection_matrix = np.identity(4)
        self.lookat_matrix = np.identity(4)

        ## Renderer Globals: RENDERING
        self.draw_queue = []

    def initialize_renderer(self):
        self.fbuffer = FrameBuffer()

        vertices = np.array(
            [[-1.0, -1.0], [+1.0, -1.0], [-1.0, +1.0], [+1.0, +1.0]],
            np.float32)
        texcoords = np.array([[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]],
                             dtype=np.float32)

        self.fbuf_vertices = VertexBuffer(data=vertices)
        self.fbuf_texcoords = VertexBuffer(data=texcoords)

        self.fbuffer_prog = Program(src_fbuffer.vert, src_fbuffer.frag)
        self.fbuffer_prog['texcoord'] = self.fbuf_texcoords
        self.fbuffer_prog['position'] = self.fbuf_vertices

        self.vertex_buffer = VertexBuffer()
        self.index_buffer = IndexBuffer()

        self.default_prog = Program(src_default.vert, src_default.frag)

        self.reset_view()

    def reset_view(self):
        self.viewport = (
            0,
            0,
            int(builtins.width * builtins.pixel_x_density),
            int(builtins.height * builtins.pixel_y_density),
        )
        self.texture_viewport = (
            0,
            0,
            builtins.width,
            builtins.height,
        )

        gloo.set_viewport(*self.viewport)

        cz = (builtins.height / 2) / math.tan(math.radians(30))
        self.projection_matrix = matrix.perspective_matrix(
            math.radians(60), builtins.width / builtins.height, 0.1 * cz,
            10 * cz)

        self.transform_matrix = np.identity(4)

        self.default_prog['projection'] = self.projection_matrix.T.flatten()
        self.default_prog['perspective_matrix'] = self.lookat_matrix.T.flatten(
        )

        self.fbuffer_tex_front = Texture2D(
            (builtins.height, builtins.width, 3))
        self.fbuffer_tex_back = Texture2D((builtins.height, builtins.width, 3))

        for buf in [self.fbuffer_tex_front, self.fbuffer_tex_back]:
            self.fbuffer.color_buffer = buf
            with self.fbuffer:
                self.clear()

        self.fbuffer.depth_buffer = gloo.RenderBuffer(
            (builtins.height, builtins.width))

    def clear(self, color=True, depth=True):
        """Clear the renderer background."""
        gloo.set_state(clear_color=self.background_color)
        gloo.clear(color=color, depth=depth)

    def _comm_toggles(self, state=True):
        gloo.set_state(blend=state)
        gloo.set_state(depth_test=state)

        if state:
            gloo.set_state(blend_func=('src_alpha', 'one_minus_src_alpha'))
            gloo.set_state(depth_func='lequal')

    @contextmanager
    def draw_loop(self):
        """The main draw loop context manager.
		"""

        self.transform_matrix = np.identity(4)

        self.default_prog['projection'] = self.projection_matrix.T.flatten()
        self.default_prog['perspective_matrix'] = self.lookat_matrix.T.flatten(
        )

        self.fbuffer.color_buffer = self.fbuffer_tex_back

        with self.fbuffer:
            gloo.set_viewport(*self.texture_viewport)
            self._comm_toggles()
            self.fbuffer_prog['texture'] = self.fbuffer_tex_front
            self.fbuffer_prog.draw('triangle_strip')

            yield

            self.flush_geometry()
            self.transform_matrix = np.identity(4)

        gloo.set_viewport(*self.viewport)
        self._comm_toggles(False)
        self.clear()
        self.fbuffer_prog['texture'] = self.fbuffer_tex_back
        self.fbuffer_prog.draw('triangle_strip')

        self.fbuffer_tex_front, self.fbuffer_tex_back = self.fbuffer_tex_back, self.fbuffer_tex_front

    def _transform_vertices(self, vertices, local_matrix, global_matrix):
        return np.dot(np.dot(vertices, local_matrix.T), global_matrix.T)[:, :3]

    def render(self, shape):
        if isinstance(shape, Geometry):
            n = len(shape.vertices)
            tverts = self._transform_vertices(
                np.hstack([shape.vertices, np.ones((n, 1))]), shape.matrix,
                self.transform_matrix)

            edges = shape.edges
            faces = shape.faces

            self.add_to_draw_queue('poly', tverts, edges, faces,
                                   self.fill_color, self.stroke_color)

        elif isinstance(shape, PShape):
            vertices = shape._draw_vertices
            n, _ = vertices.shape
            tverts = self._transform_vertices(
                np.hstack([vertices,
                           np.zeros((n, 1)),
                           np.ones((n, 1))]), shape._matrix,
                self.transform_matrix)

            fill = shape.fill.normalized if shape.fill else None
            stroke = shape.stroke.normalized if shape.stroke else None
            edges = shape._draw_edges
            faces = shape._draw_faces

            if edges is None:
                print(vertices)
                print("whale")
                exit()

            if 'open' in shape.attribs:
                overtices = shape._draw_outline_vertices
                no, _ = overtices.shape
                toverts = self._transform_vertices(
                    np.hstack([overtices,
                               np.zeros((no, 1)),
                               np.ones((no, 1))]), shape._matrix,
                    self.transform_matrix)

                self.add_to_draw_queue('poly', tverts, edges, faces, fill,
                                       None)
                self.add_to_draw_queue('path', toverts, edges[:-1], None, None,
                                       stroke)
            else:
                self.add_to_draw_queue(shape.kind, tverts, edges, faces, fill,
                                       stroke)

    def add_to_draw_queue(self,
                          stype,
                          vertices,
                          edges,
                          faces,
                          fill=None,
                          stroke=None):
        """Add the given vertex data to the draw queue.

		:param stype: type of shape to be added. Should be one of {'poly',
			'path', 'point'}
		:type stype: str

		:param vertices: (N, 3) array containing the vertices to be drawn.
		:type vertices: np.ndarray

		:param edges: (N, 2) array containing edges as tuples of indices
			into the vertex array. This can be None when not appropriate
			(eg. for points)
		:type edges: None | np.ndarray

		:param faces: (N, 3) array containing faces as tuples of indices
			into the vertex array. For 'point' and 'path' shapes, this can
			be None
		:type faces: np.ndarray

		:param fill: Fill color of the shape as a normalized RGBA tuple.
			When set to `None` the shape doesn't get a fill (default: None)
		:type fill: None | tuple

		:param stroke: Stroke color of the shape as a normalized RGBA
			tuple. When set to `None` the shape doesn't get stroke
			(default: None)
		:type stroke: None | tuple

		"""

        fill_shape = self.fill_enabled and not (fill is None)
        stroke_shape = self.stroke_enabled and not (stroke is None)

        if fill_shape and stype not in ['point', 'path']:
            idx = np.array(faces, dtype=np.uint32).ravel()
            self.draw_queue.append(["triangles", (vertices, idx, fill)])

        if stroke_shape:
            if stype == 'point':
                idx = np.arange(0, len(vertices), dtype=np.uint32)
                self.draw_queue.append(["points", (vertices, idx, stroke)])
            else:
                idx = np.array(edges, dtype=np.uint32).ravel()
                self.draw_queue.append(["lines", (vertices, idx, stroke)])

    def flush_geometry(self):
        """Flush all the shape geometry from the draw queue to the GPU.
		"""
        current_queue = []
        for index, shape in enumerate(self.draw_queue):
            current_shape, current_obj = self.draw_queue[index][
                0], self.draw_queue[index][1]
            # If current_shape is lines, bring it to the front by epsilon
            # to resolve z-fighting
            if current_shape == 'lines':
                # line_transform is used whenever we render lines to break ties in depth
                # We transform the points to camera space, move them by Z_EPSILON, and them move them back to world space
                line_transform = inv(self.lookat_matrix).dot(
                    translation_matrix(0, 0,
                                       Z_EPSILON).dot(self.lookat_matrix))
                vertices = current_obj[0]
                current_obj = (np.hstack(
                    [vertices, np.ones(
                        (vertices.shape[0], 1))]).dot(line_transform.T)[:, :3],
                               current_obj[1], current_obj[2])
            current_queue.append(current_obj)

            if index < len(self.draw_queue) - 1:
                if self.draw_queue[index][0] == self.draw_queue[index + 1][0]:
                    continue

            self.render_default(current_shape, current_queue)
            current_queue = []

        self.draw_queue = []

    def render_default(self, draw_type, draw_queue):
        # 1. Get the maximum number of vertices persent in the shapes
        # in the draw queue.
        #
        if len(draw_queue) == 0:
            return

        num_vertices = 0
        for vertices, _, _ in draw_queue:
            num_vertices = num_vertices + len(vertices)

        # 2. Create empty buffers based on the number of vertices.
        #
        data = np.zeros(num_vertices,
                        dtype=[('position', np.float32, 3),
                               ('color', np.float32, 4)])

        # 3. Loop through all the shapes in the geometry queue adding
        # it's information to the buffer.
        #
        sidx = 0
        draw_indices = []
        for vertices, idx, color in draw_queue:
            num_shape_verts = len(vertices)

            data['position'][sidx:(sidx +
                                   num_shape_verts), ] = np.array(vertices)

            color_array = np.array([color] * num_shape_verts)
            data['color'][sidx:sidx + num_shape_verts, :] = color_array

            draw_indices.append(sidx + idx)

            sidx += num_shape_verts

        self.vertex_buffer.set_data(data)
        self.index_buffer.set_data(np.hstack(draw_indices))

        # 4. Bind the buffer to the shader.
        #
        self.default_prog.bind(self.vertex_buffer)

        # 5. Draw the shape using the proper shape type and get rid of
        # the buffers.
        #
        self.default_prog.draw(draw_type, indices=self.index_buffer)

    def cleanup(self):
        """Run the clean-up routine for the renderer.

		This method is called when all drawing has been completed and the
		program is about to exit.

		"""
        self.default_prog.delete()
        self.fbuffer_prog.delete()
        self.fbuffer.delete()
예제 #27
0
glut.glutPassiveMotionFunc(on_passive_motion)
glut.glutTimerFunc(1000 / 60, timer, 60)

# Build data
# --------------------------------------
n = 500
data = np.zeros(n, [('a_position', np.float32, 2),
                    ('a_fg_color', np.float32, 4),
                    ('a_size',     np.float32, 1)])
index = 0

# Build program
# --------------------------------------
program = Program(vertex, fragment)
vdata = VertexBuffer(data)
program.bind(vdata)
program['u_antialias'] = 1.00
program['u_linewidth'] = 1.00

# Build view, model, projection
# --------------------------------------
program['u_model'] = np.eye(4, dtype=np.float32)
program['u_view'] = np.eye(4, dtype=np.float32)

# OpenGL initalization
# --------------------------------------
gloo.set_clear_color((1.0, 1.0, 1.0, 1.0))
gloo.set_state(blend=True, blend_func=('src_alpha', 'one_minus_src_alpha'))
gloo.gl_initialize()

# Start
예제 #28
0
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self,
                            title='Framebuffer post-processing',
                            keys='interactive',
                            size=(512, 512))

        # Build cube data
        # --------------------------------------
        vertices, indices, _ = create_cube()
        vertices = VertexBuffer(vertices)
        self.indices = IndexBuffer(indices)

        # Build program
        # --------------------------------------
        view = np.eye(4, dtype=np.float32)
        model = np.eye(4, dtype=np.float32)
        translate(view, 0, 0, -7)
        self.phi, self.theta = 60, 20
        rotate(model, self.theta, 0, 0, 1)
        rotate(model, self.phi, 0, 1, 0)

        self.cube = Program(cube_vertex, cube_fragment)
        self.cube.bind(vertices)
        self.cube["texture"] = checkerboard()
        self.cube["texture"].interpolation = 'linear'
        self.cube['model'] = model
        self.cube['view'] = view

        color = Texture2D((512, 512, 3), interpolation='linear')
        self.framebuffer = FrameBuffer(color, RenderBuffer((512, 512)))

        self.quad = Program(quad_vertex, quad_fragment, count=4)
        self.quad['texcoord'] = [(0, 0), (0, 1), (1, 0), (1, 1)]
        self.quad['position'] = [(-1, -1), (-1, +1), (+1, -1), (+1, +1)]
        self.quad['texture'] = color

        # OpenGL and Timer initalization
        # --------------------------------------
        set_state(clear_color=(.3, .3, .35, 1), depth_test=True)
        self.timer = app.Timer('auto', connect=self.on_timer, start=True)
        self._set_projection(self.size)

    def on_draw(self, event):
        with self.framebuffer:
            set_viewport(0, 0, 512, 512)
            clear(color=True, depth=True)
            set_state(depth_test=True)
            self.cube.draw('triangles', self.indices)
        set_viewport(0, 0, *self.size)
        clear(color=True)
        set_state(depth_test=False)
        self.quad.draw('triangle_strip')

    def on_resize(self, event):
        self._set_projection(event.size)

    def _set_projection(self, size):
        width, height = size
        set_viewport(0, 0, width, height)
        projection = perspective(30.0, width / float(height), 2.0, 10.0)
        self.cube['projection'] = projection

    def on_timer(self, event):
        self.theta += .5
        self.phi += .5
        model = np.eye(4, dtype=np.float32)
        rotate(model, self.theta, 0, 0, 1)
        rotate(model, self.phi, 0, 1, 0)
        self.cube['model'] = model
        self.update()
예제 #29
0
glut.glutReshapeWindow(512, 512)
glut.glutReshapeFunc(reshape)
glut.glutKeyboardFunc(keyboard)
glut.glutDisplayFunc(display)
glut.glutTimerFunc(1000 / 60, timer, 60)

# Build cube data
# --------------------------------------
V, I, _ = cube()
vertices = VertexBuffer(V)
indices = IndexBuffer(I)

# Build program
# --------------------------------------
program = Program(vertex, fragment)
program.bind(vertices)

# Build view, model, projection & normal
# --------------------------------------
view = np.eye(4, dtype=np.float32)
model = np.eye(4, dtype=np.float32)
projection = np.eye(4, dtype=np.float32)
translate(view, 0, 0, -5)
program["model"] = model
program["view"] = view
phi, theta = 0, 0

# OpenGL initalization
# --------------------------------------
gl.glClearColor(0.30, 0.30, 0.35, 1.00)
gl.glEnable(gl.GL_DEPTH_TEST)
예제 #30
0
class Canvas3D(app.Canvas):
    def __init__(self, data_handler, parent, currentdata):

        app.Canvas.__init__(self,
                            size=(512, 512),
                            title='3d view',
                            keys='interactive')

        self.current_data = currentdata
        self.render_params = {
            'transparent': False,
            'top_dogs_only': False,
            'draw_polygons': True,
            'draw_points': True,
            'debug_colors': True
        }
        self.__parent__ = parent
        self.__data_handler = data_handler
        self.__inliers, self.__outliers = 0, 0
        self.__render_points_params = {'inliers': False, 'outliers': False}

        self.setupCanvas()

        #Render objects
        self.render_objects = []

        #Data... SLICE
        self.__bfps = 0
        self.__points = 0
        self.__solids = 0
        self.__property_area = 0
        self.__mbb = 0
        self.__offset = 0
        self.__top_dogs = 0

        #self.__parent__.set_slice(1343)

        self.show()

    def setupCanvas(self):
        #Create the camera
        self.__camera = Cam3D.Camera([0, -200, 150], [0, 0, 0], [0, 0, 1],
                                     45.0,
                                     self.size[0] / float(self.size[1]),
                                     0.01,
                                     1000.0,
                                     is_2d=False)

        #Build and setup the glprogram for rendering the models
        self.program_solids = Program(vertex, fragment)

        self.program_solids['model'] = vut.rotx(90)
        self.program_solids['model'] = np.eye(4, dtype=np.float32)
        self.program_solids['view'] = self.__camera.view
        self.program_solids['u_alpha'] = np.float32(0.6)

        # build and setup glprogram for rendering the points
        self.program_points = gloo.Program(vert, frag)

        self.program_points['u_linewidth'] = 1.0
        self.program_points['u_antialias'] = 1.0
        self.program_points['u_model'] = np.eye(4, dtype=np.float32)
        self.program_points['u_view'] = self.__camera.view
        self.program_points['u_size'] = 0.3 + 0.8 / self.__camera.zoom_factor

        #Some aditional drawing variables/setups
        self.__draw_model_transparent = False
        self.context.set_clear_color(Color([0.7, 0.7, 0.7, 1.0]))
        self.__theta = 0
        self.__phi = 0
        self.timer = app.Timer('auto', self.on_timer, start=True)
        self.activate_zoom()

    def readTheData(self):
        self.__bfps = self.current_data['bfps']
        self.__points = np.array(self.current_data['points'], copy=True)

        self.__solids = self.current_data['solids']
        self.__property_area = self.current_data['property_area']
        self.__mbb = self.current_data['mbb']
        self.__top_dogs = self.current_data['top_dogs']
        self.__top_dog_points = self.current_data['top_dog_points']

        self.__offset = np.mean(self.__property_area.points, 0)

    def setCanvasData(self):
        #self.__bfps, self.__points, self.__solids, self.__property_area, self.__mbb, self.__top_dogs = self.__data_handler.get_slice_from_property(property_id)

        self.readTheData()
        for points in self.__points:
            points[:, 0:2] -= self.__offset

        self.setup_points_selected = self.setup_points
        self.setup_polygons_selected = self.setup_bfps
        self.updateCanvas()

        self.reset_camera()
        self.update()

        self.__parent__.focus_building_id = self.__top_dogs

    def updateCanvas(self):
        self.setup_points_selected()
        self.setup_polygons_selected()
        self.update()

    def points(self):
        self.setup_points_selected = self.setup_points
        self.readTheData()
        self.setup_points()

    def bfps(self):
        self.setup_polygons_selected = self.setup_bfps

    def features(self):
        self.setup_polygons_selected = self.setup_features
        self.setup_polygons_selected()
        self.update()

    def regions(self):
        self.setup_points_selected = self.setup_regions
        self.slice_regions = self.current_data['regions']
        self.top_dogs_regions = self.current_data['top_dog_regions']
        self.setup_regions()

    def planes(self):
        self.setup_points_selected = self.setup_regions
        self.all_planes = self.current_data['planes']
        self.top_dog_planes = self.current_data['top_dog_planes']
        self.setup_planes()

    def clearPoints(self):
        print("Clear Points")
        verts = np.zeros(0, [('position', np.float32, 3),
                             ('normal', np.float32, 3),
                             ('color', np.float32, 3)])  #start empty...
        self.program_points.bind(VertexBuffer(verts))
        self.update()

    def setup_bfps(self):

        verts = np.zeros(
            0, [('position', np.float32, 3), ('normal', np.float32, 3),
                ('color', np.float32, 3)])  #start with an empty array
        colors = distinct_colors(2)

        for i in range(len(self.__solids)):
            if self.render_params['top_dogs_only']:
                if self.__bfps[i].id in self.__top_dogs:
                    get_verts = self.__solids[i].get_gl_vertex_data(
                        self.__offset)
                    data = np.zeros(len(get_verts),
                                    [('position', np.float32, 3),
                                     ('normal', np.float32, 3),
                                     ('color', np.float32, 3)])
                    data['position'] = get_verts['position']
                    data['normal'] = get_verts['normal']
                    data['color'] = colors[1]
                    verts = np.concatenate([verts, data])
            else:
                get_verts = self.__solids[i].get_gl_vertex_data(self.__offset)
                data = np.zeros(len(get_verts), [('position', np.float32, 3),
                                                 ('normal', np.float32, 3),
                                                 ('color', np.float32, 3)])
                data['position'] = get_verts['position']
                data['normal'] = get_verts['normal']
                if self.__bfps[i].id in self.__top_dogs:
                    data['color'] = colors[1]
                else:
                    data['color'] = colors[0]
                verts = np.concatenate([verts, data])

        self.program_solids.bind(VertexBuffer(verts))

    def setup_features(self):
        verts = np.zeros(
            0, [('position', np.float32, 3), ('normal', np.float32, 3),
                ('color', np.float32, 3)])  #start with an empty array

        all_feature_groups = self.current_data['features']
        if self.render_params['top_dogs_only'] or all_feature_groups == None:
            all_feature_groups = self.current_data['top_dog_features']

        colors = distinct_colors(2)

        base_roof_color = [0.35, 0.35, 0.35]

        wallcolor = [0.72, 0.72, 0.72]
        yellow = [1, 0.76, 0]
        topwallcolor = [0.94, 0.94, 0.99]

        origin = [0, 0]

        for feature_group, gid in zip(all_feature_groups,
                                      range(len(all_feature_groups))):

            feature_group_wall_color = yellow
            feature_roof_color = base_roof_color

            top_roof_colors = distinct_colors(len(feature_group))

            if self.render_params['top_dogs_only'] or self.__bfps[
                    gid].id in self.__top_dogs:
                feature_group_wall_color = topwallcolor

            for feature, fid in zip(feature_group, range(len(feature_group))):
                get_verts = feature['roof'].get_gl_vertex_data(origin)
                data = np.zeros(len(get_verts), [('position', np.float32, 3),
                                                 ('normal', np.float32, 3),
                                                 ('color', np.float32, 3)])
                data['position'] = get_verts['position']
                data['normal'] = get_verts['normal']
                data['color'] = feature_roof_color
                if self.render_params['top_dogs_only'] or self.__bfps[
                        gid].id in self.__top_dogs:
                    data['color'] = top_roof_colors[fid]
                if self.render_params['debug_colors']:
                    data['color'] = top_roof_colors[fid]

                verts = np.concatenate([verts, data])

                get_verts = feature['walls'].get_gl_vertex_data(origin)
                data = np.zeros(len(get_verts), [('position', np.float32, 3),
                                                 ('normal', np.float32, 3),
                                                 ('color', np.float32, 3)])
                data['position'] = get_verts['position']
                data['normal'] = get_verts['normal']
                data['color'] = feature_group_wall_color
                if self.render_params['debug_colors']:
                    data['color'] = [i * 1.3 for i in top_roof_colors[fid]]

                verts = np.concatenate([verts, data])

        self.program_solids.bind(VertexBuffer(verts))

    def setup_points(self):

        self.setup_points_selected = self.setup_points

        if self.render_params['top_dogs_only']:
            all_points = np.array(self.__top_dog_points)
        else:
            all_points = np.array(self.__points)

        total_n = sum([len(points) for points in all_points])
        data = np.zeros(total_n, [('a_position', np.float32, 3),
                                  ('a_bg_color', np.float32, 4),
                                  ('a_fg_color', np.float32, 4),
                                  ('a_size', np.float32, 1)])

        start = 0
        for i in range(len(all_points)):
            points = all_points[i]
            n = len(points)
            if self.__bfps[i].id in self.__top_dogs:
                data[start:start + n]['a_bg_color'] = np.array(
                    [0.6, 0.92, 0.8, 0.5], dtype=np.float32)
            else:
                data[start:start + n]['a_bg_color'] = np.array(
                    [0.7, 0.7, 0.9, 0.5], dtype=np.float32)

            data[start:start + n]['a_fg_color'] = 0, 0, 0, 1
            data[start:start + n]['a_size'] = 10
            data[start:start + n]['a_position'] = points
            start += n

        self.program_points.bind(gloo.VertexBuffer(data))
        self.update()

    def setup_planes(self):

        self.setup_points_selected = self.setup_regions

        all_points = np.array(self.__points)

        self.selected_planes = self.all_planes
        if self.render_params['top_dogs_only']:
            self.selected_planes = self.top_dog_planes

        #all_points = copy.copy(all_points)
        all_plane_points = copy.deepcopy(all_points)
        print("running setup planes with {} points".format(
            len(all_plane_points)))
        n_regions = len(self.selected_regions)

        #PREPARE DATA ARRAY
        total_n = 0
        current_regions = 0
        for i in range(len(all_plane_points)):
            points = all_plane_points[i]

            if self.render_params['top_dogs_only']:

                if self.__bfps[i].id in self.__top_dogs:
                    n_in_region = sum([
                        len(region)
                        for region in self.selected_regions[current_regions]
                    ])
                    total_n += len(points)
                    current_regions += 1

            else:
                total_n += len(points)
        ##PREPARE DATA ARRAY
        #total_n = 0
        #current_regions = 0
        #for i in range(len(all_plane_points)):
        #    points = all_plane_points[i]

        #    if self.__bfps[i].id in self.__top_dogs :
        #        n_in_region = sum([len(region) for region in self.selected_regions[current_regions]])
        #        total_n += len(points)
        #        current_regions += 1

        #    elif self.render_params['top_dogs_only'] == False:
        #        total_n += len(points)

        data = np.zeros(total_n, [('a_position', np.float32, 3),
                                  ('a_bg_color', np.float32, 4),
                                  ('a_fg_color', np.float32, 4),
                                  ('a_size', np.float32, 1)])

        #POPULATE DATA ARRAY
        start = 0
        current_regions = 0
        for i in range(len(all_plane_points)):
            points = all_plane_points[i]

            if self.render_params['top_dogs_only']:
                if self.__bfps[i].id in self.__top_dogs:
                    regions = self.selected_regions[current_regions]
                    m = sum([len(region) for region in regions])
                    n = len(points)
                    #assert(m == n) m innehåller inte alla points då de kan ha försvunnit i små regions

                    for j in range(len(regions)):
                        #plane = pf.fitPlane(points[regions[j]])
                        plane = self.selected_planes[current_regions][j]
                        points[regions[j]] = elevatePointsToPlane(
                            points[regions[j]], plane)

                    datapoints = data[start:start + n]
                    self.setupRegionData(datapoints, regions, points)
                    current_regions += 1
                    start += n

            else:
                regions = self.selected_regions[current_regions]
                m = sum([len(region) for region in regions])
                n = len(points)
                #assert(m == n) m innehåller inte alla points då de kan ha försvunnit i små regions

                for j in range(len(regions)):
                    #plane = pf.fitPlane(points[regions[j]])
                    plane = self.selected_planes[current_regions][j]
                    points[regions[j]] = elevatePointsToPlane(
                        points[regions[j]], plane)
                datapoints = data[start:start + n]
                self.setupRegionData(datapoints, regions, points)
                current_regions += 1
                start += n

        ##POPULATE DATA ARRAY
        #start = 0
        #current_regions = 0
        #for i in range(len(all_plane_points)):
        #    points = all_plane_points[i]
        #    n = len(points)

        #    if self.__bfps[i].id in self.__top_dogs :

        #        regions = self.selected_regions[current_regions]
        #        datapoints = data[start:start+n]
        #        for j in range(len(regions)):
        #            plane = pf.fitPlane(points[regions[j]])
        #            points[regions[j]] = elevatePointsToPlane(points[regions[j]], plane)

        #        #region_points = elevatePointsToPlane(points[:,0:2], self.all_planes[current_regions])
        #        self.setupRegionData(datapoints, regions, points)
        #        current_regions += 1
        #        start += n

        #    elif self.render_params['top_dogs_only'] == False:
        #        n = len(points)
        #        data[start:start+n]['a_bg_color'] = np.array([0.7,0.7,0.9,0.5], dtype=np.float32)
        #        data[start:start+n]['a_position'] = points
        #        start += n

            data[0:total_n]['a_fg_color'] = 0, 0, 0, 1
            data[0:total_n]['a_size'] = 10

        #BIND DATA TO GL PROGRAM
        self.program_points.bind(gloo.VertexBuffer(data))
        self.update()

    def setup_regions(self):

        self.setup_points_selected = self.setup_regions
        all_points = np.array(self.__points)
        all_points = copy.copy(all_points)

        self.selected_regions = self.slice_regions

        if self.render_params['top_dogs_only']:
            self.selected_regions = self.top_dogs_regions

        if self.selected_regions == None:
            self.__parent__.pipelineWidget.cluster_layout.setRegions()
            self.selected_regions = self.slice_regions

        n_regions = len(self.selected_regions)

        #PREPARE DATA ARRAY
        total_n = 0
        current_regions = 0
        for i in range(len(all_points)):
            points = all_points[i]

            if self.render_params['top_dogs_only']:

                if self.__bfps[i].id in self.__top_dogs:
                    n_in_region = sum([
                        len(region)
                        for region in self.selected_regions[current_regions]
                    ])
                    total_n += len(points)
                    current_regions += 1

            else:
                total_n += len(points)

        data = np.zeros(total_n, [('a_position', np.float32, 3),
                                  ('a_bg_color', np.float32, 4),
                                  ('a_fg_color', np.float32, 4),
                                  ('a_size', np.float32, 1)])

        #POPULATE DATA ARRAY
        start = 0
        current_regions = 0
        for i in range(len(all_points)):
            points = all_points[i]

            if self.render_params['top_dogs_only']:
                if self.__bfps[i].id in self.__top_dogs:
                    regions = self.selected_regions[current_regions]
                    m = sum([len(region) for region in regions])
                    n = len(points)
                    #assert(m == n) m innehåller inte alla points då de kan ha försvunnit i små regions
                    datapoints = data[start:start + n]
                    self.setupRegionData(datapoints, regions, points)
                    current_regions += 1
                    start += n

            else:
                regions = self.selected_regions[current_regions]
                m = sum([len(region) for region in regions])
                n = len(points)
                #assert(m == n) m innehåller inte alla points då de kan ha försvunnit i små regions
                datapoints = data[start:start + n]
                self.setupRegionData(datapoints, regions, points)
                current_regions += 1
                start += n
            #else:
            #    n = len(points)
            #    data[start:start+n]['a_bg_color'] = np.array([0.7,0.7,0.9,0.5], dtype=np.float32)
            #    data[start:start+n]['a_position'] = points
            #    start += n

            data[0:total_n]['a_fg_color'] = 0, 0, 0, 1
            data[0:total_n]['a_size'] = 10

        #BIND DATA TO GL PROGRAM
        self.program_points.bind(gloo.VertexBuffer(data))
        self.update()

    def setupRegionData(self, datapoints, regions, points):
        n_regions = len(regions)
        colors = distinct_colors(n_regions)

        for region_idx in range(n_regions):
            n_points_in_region = len(regions[region_idx])
            r, g, b = colors[region_idx]
            for point_idx in regions[region_idx]:
                datapoints[point_idx]['a_bg_color'] = np.array(
                    [r, g, b, 0.5], dtype=np.float32)
                datapoints[point_idx]['a_position'] = np.array(
                    points[point_idx], dtype=np.float32)

    def reset_camera(self):
        #Create the camera
        self.__camera = Cam3D.Camera([0, -100, 50], [0, 0, 0], [0, 0, 1],
                                     45.0,
                                     self.size[0] / float(self.size[1]),
                                     0.01,
                                     1000.0,
                                     is_2d=False)

        self.program_solids['view'] = self.__camera.view

        self.program_points['u_view'] = self.__camera.view
        self.program_points['u_size'] = 0.3 + 0.8 / self.__camera.zoom_factor

        self.activate_zoom()

    def update_render_points_params(self, attr: str, value):
        self.__render_points_params[attr] = value
        self.setup_points()

    def on_mouse_press(self, event):

        if event.button == 1:

            self.__camera.is_move = True
            self.__camera.is_rotate = False

        if event.button == 2:

            self.__camera.is_move = False
            self.__camera.is_rotate = True

        self.__camera.prev_mouse_pos = event.pos

    def on_mouse_release(self, event):

        self.__camera.is_move = False
        self.__camera.is_rotate = False

    def on_mouse_move(self, event):

        if self.__camera.is_move:

            self.__camera.translate2d(-1 * np.array(
                event.pos - self.__camera.prev_mouse_pos, dtype=np.float32))
            self.program_solids['view'] = self.__camera.view
            self.program_points['u_view'] = self.__camera.view
            self.update()

        elif self.__camera.is_rotate:

            self.__camera.rotx(-1 * np.array(
                (event.pos - self.__camera.prev_mouse_pos))[1:2])
            self.__camera.roty(-1 * np.array(
                (event.pos - self.__camera.prev_mouse_pos))[0:1])
            self.program_solids['view'] = self.__camera.view
            self.program_points['u_view'] = self.__camera.view
            self.update()

        self.__camera.prev_mouse_pos = event.pos

    def on_mouse_wheel(self, event):

        self.__camera.scale(event.delta[1])
        self.program_solids['view'] = self.__camera.view
        self.program_points['u_view'] = self.__camera.view
        self.program_points[
            'u_size'] = 0.3 + 0.8 / self.__camera.zoom_factor  #magicnumber zoom on the poor camera
        self.update()

    def draw_model(self):

        gl.glEnable(gl.GL_DEPTH_TEST)
        gl.glDepthMask(gl.GL_TRUE)
        gl.glFrontFace(gl.GL_CCW)
        gl.glDisable(gl.GL_BLEND)
        gl.glBlendFunc(gl.GL_ZERO, gl.GL_ZERO)

        if self.render_params['transparent']:

            gl.glEnable(gl.GL_BLEND)
            gl.glDepthMask(gl.GL_FALSE)
            gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)

        self.program_solids.draw('triangles')

    def draw_points(self):

        gl.glDisable(gl.GL_BLEND)
        gl.glEnable(gl.GL_DEPTH_TEST)
        gl.glDepthMask(gl.GL_TRUE)

        self.program_points.draw('points')

    def on_draw(self, event):

        gl.glClear(gl.GL_COLOR_BUFFER_BIT)
        gl.glClear(gl.GL_DEPTH_BUFFER_BIT)

        if self.render_params['draw_polygons']:
            self.draw_model()

        if self.render_params['draw_points']:
            self.draw_points()

    def on_resize(self, event):

        self.activate_zoom()

    def activate_zoom(self):

        gloo.set_viewport(0, 0, *self.physical_size)
        projection = perspective(45.0, self.size[0] / float(self.size[1]), 1.0,
                                 1000.0)
        self.program_solids['projection'] = projection
        self.program_points['u_projection'] = projection

    def on_timer(self, event):

        self.__theta += .5
        self.__phi += .5

        self.__camera.roty(.0)
        self.program_solids['view'] = self.__camera.view
        self.program_points['u_view'] = self.__camera.view
        self.update()
예제 #31
0
class Canvas(app.Canvas):
    _visible_payloads = [
        PAYLOADTYPE_INFO_IDS.PAYLOAD_TYPE_IMAGE,
        PAYLOADTYPE_INFO_IDS.PAYLOAD_TYPE_CHUNK_DATA,
        PAYLOADTYPE_INFO_IDS.PAYLOAD_TYPE_MULTI_PART,
    ]

    def __init__(self,
                 image_acquisition_manager=None,
                 width=640,
                 height=480,
                 fps=30,
                 background_color='gray',
                 vertex_shader=None,
                 fragment_shader=None):
        """
        NOTE: fps should be smaller than or equal to 50 fps. If it's exceed
        VisPy drags down the acquisition performance. This is the issue we
        have to investigate.
        """
        """
        As far as we know, Vispy refreshes the canvas every 1/30 sec at the
        fastest no matter which faster number is specified. If we set any
        value which is greater than 30, then Vispy's callback is randomly
        called.
        """

        self._vertex_shader = vertex_shader if vertex_shader else """
            // Uniforms
            uniform mat4 u_model;
            uniform mat4 u_view;
            uniform mat4 u_projection;

            // Attributes
            attribute vec2 a_position;
            attribute vec2 a_texcoord;

            // Varyings
            varying vec2 v_texcoord;

            // Main
            void main (void)
            {
                v_texcoord = a_texcoord;
                gl_Position = u_projection * u_view * u_model * vec4(a_position, 0.0, 1.0);
            }
        """

        self._fragment_shader = fragment_shader if fragment_shader else """
            varying vec2 v_texcoord;
            uniform sampler2D texture;
            void main()
            {
                gl_FragColor = texture2D(texture, v_texcoord);
            }
        """

        #
        self._iam = image_acquisition_manager

        #
        app.Canvas.__init__(self,
                            size=(width, height),
                            vsync=True,
                            autoswap=True)

        #
        self._program = None
        self._data = None
        self._coordinate = None
        self._origin = None
        self._translate = 0.
        self._latest_translate = self._translate
        self._magnification = 1.

        #
        self._background_color = background_color
        self._has_filled_texture = False
        self._width, self._height = width, height

        #
        self._is_dragging = False

        # If it's True , the canvas keeps image acquisition but do not
        # draw images on the canvas.
        self._pause_drawing = False

        # Apply shaders.
        self.set_shaders(vertex_shader=self._vertex_shader,
                         fragment_shader=self._fragment_shader)

        #
        self._timer = app.Timer(1. / fps, connect=self.update, start=True)

    @property
    def iam(self):
        return self._iam

    @iam.setter
    def iam(self, value):
        self._iam = value

    def set_shaders(self, vertex_shader=None, fragment_shader=None):
        #
        vs = vertex_shader if vertex_shader else self._vertex_shader
        fs = fragment_shader if fragment_shader else self._fragment_shader
        self._program = Program(vs, fs, count=4)

        #
        self._data = np.zeros(4,
                              dtype=[('a_position', np.float32, 2),
                                     ('a_texcoord', np.float32, 2)])

        #
        self._data['a_texcoord'] = np.array([[0., 1.], [1., 1.], [0., 0.],
                                             [1., 0.]])

        #
        self._program['u_model'] = np.eye(4, dtype=np.float32)
        self._program['u_view'] = np.eye(4, dtype=np.float32)

        #
        self._coordinate = [0, 0]
        self._origin = [0, 0]

        #
        self._program['texture'] = np.zeros((self._height, self._width),
                                            dtype='uint8')

        #
        self.apply_magnification()

    def set_rect(self, width, height):
        #
        self._has_filled_texture = False

        #
        updated = False

        #
        if self._width != width or self._height != height:
            self._width = width
            self._height = height
            updated = True

        #
        if updated:
            self.apply_magnification()

    def on_draw(self, event):
        # Clear the canvas in gray.
        gloo.clear(color=self._background_color)
        self._update_texture()

    def _update_texture(self):
        # Fetch a buffer.
        try:
            with self.iam.fetch_buffer(timeout_ms=0.1) as buffer:
                update = True
                if buffer.payload_type not in self._visible_payloads:
                    update = False

                # Set the image as the texture of our canvas.
                if not self._pause_drawing and buffer:
                    # Update the canvas size if needed.
                    self.set_rect(buffer.payload.components[0].width,
                                  buffer.payload.components[0].height)

                    #
                    exponent = 0

                    #
                    data_format_value = buffer.payload.components[
                        0].data_format_value
                    if is_custom(data_format_value):
                        update = False
                    else:
                        data_format = buffer.payload.components[0].data_format
                        bpp = get_bits_per_pixel(data_format)
                        if bpp is not None:
                            exponent = bpp - 8
                        else:
                            update = False

                    if update:
                        # Convert each data to an 8bit.
                        content = buffer.payload.components[0].data
                        if exponent > 0:
                            # The following code may affect to the rendering
                            # performance:
                            content = (content / (2**exponent))

                            # Then cast each array element to an uint8:
                            content = content.astype(np.uint8)

                        self._program['texture'] = content

                # Draw the texture.
                self._draw()

        except AttributeError:
            # Harvester Core has not started image acquisition so
            # calling fetch_buffer() raises AttributeError because
            # None object is used for the with statement.

            # Update on June 15th, 2018:
            # According to a VisPy developer, they have not finished
            # porting VisPy to PyQt5. Once they finished the development
            # we should try it out if it gives us the maximum refresh rate.
            # See the following URL to check the latest information:
            #
            #     https://github.com/vispy/vispy/issues/1394

            # Draw the texture.
            self._draw()

    def _draw(self):
        self._program.draw('triangle_strip')

    def on_resize(self, event):
        self.apply_magnification()

    def apply_magnification(self):
        #
        canvas_w, canvas_h = self.physical_size
        gloo.set_viewport(0, 0, canvas_w, canvas_h)

        #
        ratio = self._magnification
        w, h = self._width, self._height

        self._program['u_projection'] = ortho(
            self._coordinate[0], canvas_w * ratio + self._coordinate[0],
            self._coordinate[1], canvas_h * ratio + self._coordinate[1], -1, 1)

        x, y = int((canvas_w * ratio - w) / 2), int(
            (canvas_h * ratio - h) / 2)  # centering x & y

        #
        self._data['a_position'] = np.array([[x, y], [x + w, y], [x, y + h],
                                             [x + w, y + h]])

        #
        self._program.bind(gloo.VertexBuffer(self._data))

    def on_mouse_wheel(self, event):
        self._translate += event.delta[1]
        power = 7. if is_running_on_macos() else 5.  # 2 ** power
        stride = 4. if is_running_on_macos() else 7.
        translate = self._translate
        translate = min(power * stride, translate)
        translate = max(-power * stride, translate)
        self._translate = translate
        self._magnification = 2**-(self._translate / stride)
        if self._latest_translate != self._translate:
            self.apply_magnification()
            self._latest_translate = self._translate

    def on_mouse_press(self, event):
        self._is_dragging = True
        self._origin = event.pos

    def on_mouse_release(self, event):
        self._is_dragging = False

    def on_mouse_move(self, event):
        if self._is_dragging:
            adjustment = 2. if is_running_on_macos() else 1.
            ratio = self._magnification * adjustment
            delta = event.pos - self._origin
            self._origin = event.pos
            self._coordinate[0] -= (delta[0] * ratio)
            self._coordinate[1] += (delta[1] * ratio)
            self.apply_magnification()

    def pause_drawing(self, pause=True):
        self._pause_drawing = pause

    def toggle_drawing(self):
        self._pause_drawing = False if self._pause_drawing else True

    @property
    def is_pausing(self):
        return True if self._pause_drawing else False

    def resume_drawing(self):
        self._pause_drawing = False

    @property
    def background_color(self):
        return self._background_color

    @background_color.setter
    def background_color(self, color):
        self._background_color = color
예제 #32
0
class Canvas2D(CanvasBase):
    _visible_payloads = [
        PAYLOADTYPE_INFO_IDS.PAYLOAD_TYPE_IMAGE,
        PAYLOADTYPE_INFO_IDS.PAYLOAD_TYPE_CHUNK_DATA,
        PAYLOADTYPE_INFO_IDS.PAYLOAD_TYPE_MULTI_PART,
    ]

    def __init__(
            self, *,
            image_acquirer=None,
            width=640, height=480,
            background_color='gray',
            vsync=True, display_rate=30.
    ):
        #
        super().__init__(
            image_acquirer=image_acquirer,
            width=width, height=height,
            display_rate=display_rate,
            background_color=background_color,
            vsync=vsync
        )

        #
        self._vertex_shader = """
            // Uniforms
            uniform mat4 u_model;
            uniform mat4 u_view;
            uniform mat4 u_projection;

            // Attributes
            attribute vec2 a_position;
            attribute vec2 a_texcoord;

            // Varyings
            varying vec2 v_texcoord;

            // Main
            void main (void)
            {
                v_texcoord = a_texcoord;
                gl_Position = u_projection * u_view * u_model * vec4(a_position, 0.0, 1.0);
            }
        """

        self._fragment_shader = """
            varying vec2 v_texcoord;
            uniform sampler2D texture;
            void main()
            {
                gl_FragColor = texture2D(texture, v_texcoord);
            }
        """

        #
        self._program = None
        self._data = None
        self._coordinate = None
        self._translate = 0.
        self._latest_translate = self._translate
        self._magnification = 1.

        # Apply shaders.
        self._program = Program(
            self._vertex_shader, self._fragment_shader, count=4
        )

        #
        self._data = np.zeros(
            4, dtype=[
                ('a_position', np.float32, 2),
                ('a_texcoord', np.float32, 2)
            ]
        )

        #
        self._data['a_texcoord'] = np.array(
            [[0., 1.], [1., 1.], [0., 0.], [1., 0.]]
        )

        #
        self._program['u_model'] = np.eye(4, dtype=np.float32)
        self._program['u_view'] = np.eye(4, dtype=np.float32)

        #
        self._coordinate = [0, 0]


        #
        self._program['texture'] = np.zeros(
            (self._height, self._width), dtype='uint8'
        )

        #
        self.apply_magnification()

    def _prepare_texture(self, buffer):
        update = True
        if buffer.payload_type not in self._visible_payloads:
            update = False

        # Set the image as the texture of our canvas.
        if buffer:
            #
            payload = buffer.payload
            component = payload.components[0]
            width = component.width
            height = component.height

            # Update the canvas size if needed.
            self.set_canvas_size(width, height)

            #
            exponent = 0
            data_format = None

            #
            data_format_value = component.data_format_value
            if is_custom(data_format_value):
                update = False
            else:
                data_format = component.data_format
                bpp = get_bits_per_pixel(data_format)
                if bpp is not None:
                    exponent = bpp - 8
                else:
                    update = False

            if update:
                # Reshape the image so that it can be drawn on the
                # VisPy canvas:
                if data_format in mono_location_formats or \
                        data_format in bayer_location_formats:
                    # Reshape the 1D NumPy array into a 2D so that VisPy
                    # can display it as a mono image:
                    content = component.data.reshape(height, width)
                else:
                    # The image requires you to reshape it to draw it on the
                    # canvas:
                    if data_format in rgb_formats or \
                            data_format in rgba_formats or \
                            data_format in bgr_formats or \
                            data_format in bgra_formats:
                        # Reshape the 1D NumPy array into a 2D so that VisPy
                        # can display it as an RGB image:
                        content = component.data.reshape(
                            height, width,
                            int(component.num_components_per_pixel)
                        )
                        #
                        if data_format in bgr_formats:
                            # Swap every R and B so that VisPy can display
                            # it as an RGB image:
                            content = content[:, :, ::-1]
                    else:
                        return

                # Convert each data to an 8bit.
                if exponent > 0:
                    # The following code may affect to the rendering
                    # performance:
                    content = (content / (2 ** exponent))

                    # Then cast each array element to an uint8:
                    content = content.astype(np.uint8)

                self._program['texture'] = content

    def _draw(self):
        self._program.draw('triangle_strip')

    def apply_magnification(self):
        #
        canvas_w, canvas_h = self.physical_size
        gloo.set_viewport(0, 0, canvas_w, canvas_h)

        #
        ratio = self._magnification
        w, h = self._width, self._height

        self._program['u_projection'] = ortho(
            self._coordinate[0],
            canvas_w * ratio + self._coordinate[0],
            self._coordinate[1],
            canvas_h * ratio + self._coordinate[1],
            -1, 1
        )

        x, y = int((canvas_w * ratio - w) / 2), int((canvas_h * ratio - h) / 2)  # centering x & y

        #
        self._data['a_position'] = np.array(
            [[x, y], [x + w, y], [x, y + h], [x + w, y + h]]
        )

        #
        self._program.bind(gloo.VertexBuffer(self._data))

    def on_mouse_wheel(self, event):
        self._translate += event.delta[1]
        power = 7. if is_running_on_macos() else 5.  # 2 ** exponent
        stride = 4. if is_running_on_macos() else 7.
        translate = self._translate
        translate = min(power * stride, translate)
        translate = max(-power * stride, translate)
        self._translate = translate
        self._magnification = 2 ** -(self._translate / stride)
        if self._latest_translate != self._translate:
            self.apply_magnification()
            self._latest_translate = self._translate

    def on_mouse_move(self, event):
        if self._is_dragging:
            adjustment = 2. if is_running_on_macos() else 1.
            ratio = self._magnification * adjustment
            delta = event.pos - self._origin
            self._origin = event.pos
            self._coordinate[0] -= (delta[0] * ratio)
            self._coordinate[1] += (delta[1] * ratio)
            self.apply_magnification()
예제 #33
0
class OpenGLRenderer(ABC):
    def __init__(self, src_fbuffer, src_default):
        self.default_prog = None
        self.fbuffer_prog = None

        self.fbuffer = None
        self.fbuffer_tex_front = None
        self.fbuffer_tex_back = None

        self.vertex_buffer = None
        self.index_buffer = None

        # Renderer Globals: STYLE/MATERIAL PROPERTIES
        #
        self.style = Style()

        # Renderer Globals: Curves
        self.stroke_weight = 1
        self.stroke_cap = ROUND
        self.stroke_join = MITER

        # Renderer Globals
        # VIEW MATRICES, ETC
        #
        self.viewport = None
        self.texture_viewport = None
        self.transform_matrix = np.identity(4)
        self.projection_matrix = np.identity(4)

        # Renderer Globals: RENDERING
        self.draw_queue = []

        # Shaders
        self.fbuffer_prog = Program(src_fbuffer.vert, src_fbuffer.frag)
        self.default_prog = Program(src_default.vert, src_default.frag)

    def initialize_renderer(self):
        self.fbuffer = FrameBuffer()

        vertices = np.array(
            [[-1.0, -1.0], [+1.0, -1.0], [-1.0, +1.0], [+1.0, +1.0]],
            np.float32)
        texcoords = np.array([[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]],
                             dtype=np.float32)

        self.fbuf_vertices = VertexBuffer(data=vertices)
        self.fbuf_texcoords = VertexBuffer(data=texcoords)

        self.fbuffer_prog['texcoord'] = self.fbuf_texcoords
        self.fbuffer_prog['position'] = self.fbuf_vertices

        self.vertex_buffer = VertexBuffer()
        self.index_buffer = IndexBuffer()

    def render_default(self, draw_type, draw_queue):
        # 1. Get the maximum number of vertices persent in the shapes
        # in the draw queue.
        #
        if len(draw_queue) == 0:
            return

        num_vertices = 0
        for vertices, _, _ in draw_queue:
            num_vertices = num_vertices + len(vertices)

        # 2. Create empty buffers based on the number of vertices.
        #
        data = np.zeros(num_vertices,
                        dtype=[('position', np.float32, 3),
                               ('color', np.float32, 4)])

        # 3. Loop through all the shapes in the geometry queue adding
        # it's information to the buffer.
        #
        sidx = 0
        draw_indices = []
        for vertices, idx, color in draw_queue:
            num_shape_verts = len(vertices)

            data['position'][sidx:(sidx +
                                   num_shape_verts), ] = np.array(vertices)

            color_array = np.array([color] * num_shape_verts)
            data['color'][sidx:sidx + num_shape_verts, :] = color_array

            draw_indices.append(sidx + idx)

            sidx += num_shape_verts

        self.vertex_buffer.set_data(data)
        self.index_buffer.set_data(np.hstack(draw_indices))

        # 4. Bind the buffer to the shader.
        #
        self.default_prog.bind(self.vertex_buffer)

        # 5. Draw the shape using the proper shape type and get rid of
        # the buffers.
        #
        self.default_prog.draw(draw_type, indices=self.index_buffer)

    def cleanup(self):
        """Run the clean-up routine for the renderer.

        This method is called when all drawing has been completed and the
        program is about to exit.

        """
        self.default_prog.delete()
        self.fbuffer_prog.delete()
        self.fbuffer.delete()

    def _transform_vertices(self, vertices, local_matrix, global_matrix):
        return np.dot(np.dot(vertices, local_matrix.T), global_matrix.T)[:, :3]
예제 #34
0
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self,
                            title='Visualize Mesh',
                            keys='interactive',
                            size=(1920, 1080))

    def on_initialize(self, event):
        self.rho = 0.0
        # Build cube data
        # --------------------------------------
        self.checker = Program(cube_vertex, cube_fragment)
        self.checker['texture'] = checkerboard()
        self.checker['position'] = [(-1, -1), (-1, +1), (+1, -1), (+1, +1)]
        self.checker['texcoord'] = [(0, 0), (0, 1), (1, 0), (1, 1)]

        # sheet, indices = make_sheet((960, 1080))
        # sheet_buffer = VertexBuffer(sheet)

        left_eye = Texture2D((960, 1080, 3), interpolation='linear')
        self.left_eye_buffer = FrameBuffer(left_eye, RenderBuffer((960, 1080)))
        # Build program
        # --------------------------------------
        self.view = np.eye(4, dtype=np.float32)
        self.program = Program(vertex, fragment)
        distortion_buffer = VertexBuffer(make_distortion())
        self.program.bind(distortion_buffer)
        self.program['rotation'] = self.view
        self.program['texture'] = left_eye

        # OpenGL and Timer initalization
        # --------------------------------------
        set_state(clear_color=(.3, .3, .35, 1), depth_test=True)
        self.timer = app.Timer('auto', connect=self.on_timer, start=True)
        self._set_projection(self.size)

    def on_draw(self, event):
        with self.left_eye_buffer:
            set_viewport(0, 0, *self.size)
            clear(color=True)
            set_state(depth_test=False)
            self.checker.draw('triangle_strip')
        set_viewport(0, 0, *self.size)
        clear(color=True)
        set_state(depth_test=True)
        self.program.draw('points')

    def on_resize(self, event):
        self._set_projection(event.size)

    def on_mouse_move(self, event):
        pos = np.array(event.pos)

    def on_key_press(self, event):
        if event.text == 'q':
            sys.exit()

    def _set_projection(self, size):
        width, height = size
        set_viewport(0, 0, width, height)
        projection = perspective(30.0, width / float(height), 2.0, 10.0)
        # self.program['projection'] = projection

    def on_timer(self, event):
        self.rho = 0.1
        if self.rho >= 30:
            self.rho = 0

        self.update()
예제 #35
0
class Drawable(object):
    name = "Default Drawable"
    skip = False
    def __init__(self, *args, **kwargs):
        '''Drawable(*args, **kwargs) -> Drawable
        Everything is tracked internally, different drawables will handle things differently
        Inherit from this for all drawables.

        Inheriting:
            You must define a make_mesh, make_shaders, and draw method. 
            If you do not make shaders, you will get a default
            If you do not make a mesh, you'll get a square that takes up the screen

        '''
        self.model = np.eye(4)
        self.view = np.eye(4)
        self.projection = np.eye(4)

        self.mesh = self.make_mesh()
        self.vert_shader, self.frag_shader = self.make_shaders()
        self.program = Program(self.vert_shader, self.frag_shader)
        self.program.bind(VertexBuffer(self.mesh))
        if hasattr(self, make_texture):
            self.texture = self.make_texture()
            assert isinstance(self.texture, Texture2D), "Texture passed is not a texture!"

        self.program['texture'] = self.texture
        cube["texture"].interpolation = 'linear'

    def __setitem__(self, key, value):
        self.bind(key, value)

    def translate(self, *args):
        translate(self.model, *args)
        self.program['model'] = self.model

    def rotate(self, *args):
        rotate(self.model, *args)
        self.program['model'] = self.model

    def bind(self, key, value):
        '''Rebind a single program item to a value'''
        self.program[key] = value

    def bind_multiple(self, **kwargs):
        '''rebind multiple things!'''
        for key, value in kwargs:
            self.bind(key, value)

    def make_mesh(self):
        '''mesh()
        Generates a default mesh (a cube)
        treat it as though it is a property (i.e. not a function)
        ex:
        >>> x = Target((100, 100, 100))
        >>> mesh = Target.mesh
        '''
        cube = Program(cube_vertex, cube_fragment)
        cube.bind(vertices)
        self.program['model'] = model
        self.program['view'] = view
        self.program['projection'] = projection

        if self.mesh is None:
            vertices, indices, _ = create_cube()
            # self.mesh = 
            
        else:
            return self.mesh

    def make_shaders(self):
        '''shader -> (vertex, fragment) 
        Returns vertex and fragment shaders as 2-tuple of strings

        THIS IS A DEFAULT SHADER
        '''
        fragment = ''
        vertex = ''
        return vertex, fragment

    def make_texture(self):
        '''Make a texture
        THIS IS A DEFAULT TEXTURE
        '''
        texture = utils.checkerboard()
        return texture

    def update(self):
        pass

    def draw(self):
        self.program.draw()
예제 #36
0
class Canvas(app.Canvas):

    def __init__(self):
        app.Canvas.__init__(self, title='Visualize Mesh',
                            keys='interactive', size=(1920, 1080))

    def on_initialize(self, event):
        self.rho = 0.0
        # Build cube data
        # --------------------------------------
        self.checker = Program(cube_vertex, cube_fragment)
        self.checker['texture'] = checkerboard()
        self.checker['position'] = [(-1, -1), (-1, +1), (+1, -1), (+1, +1)]
        self.checker['texcoord'] = [(0, 0), (0, 1), (1, 0), (1, 1)]

        # sheet, indices = make_sheet((960, 1080))
        # sheet_buffer = VertexBuffer(sheet)

        left_eye = Texture2D((960, 1080, 3), interpolation='linear')
        self.left_eye_buffer = FrameBuffer(left_eye, RenderBuffer((960, 1080)))
        # Build program
        # --------------------------------------
        self.view = np.eye(4, dtype=np.float32)
        self.program = Program(vertex, fragment)
        distortion_buffer = VertexBuffer(make_distortion())
        self.program.bind(distortion_buffer)
        self.program['rotation'] = self.view
        self.program['texture'] = left_eye

        # OpenGL and Timer initalization
        # --------------------------------------
        set_state(clear_color=(.3, .3, .35, 1), depth_test=True)
        self.timer = app.Timer('auto', connect=self.on_timer, start=True)
        self._set_projection(self.size)

    def on_draw(self, event):
        with self.left_eye_buffer:
            set_viewport(0, 0, *self.size)
            clear(color=True)
            set_state(depth_test=False)
            self.checker.draw('triangle_strip')
        set_viewport(0, 0, *self.size)
        clear(color=True)
        set_state(depth_test=True)
        self.program.draw('points')

    def on_resize(self, event):
        self._set_projection(event.size)

    def on_mouse_move(self, event):
        pos = np.array(event.pos)

    def on_key_press(self, event):
        if event.text == 'q':
            sys.exit()

    def _set_projection(self, size):
        width, height = size
        set_viewport(0, 0, width, height)
        projection = perspective(30.0, width / float(height), 2.0, 10.0)
        # self.program['projection'] = projection

    def on_timer(self, event):
        self.rho = 0.1
        if self.rho >= 30:
            self.rho = 0

        self.update()
예제 #37
0
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self,
                            size=(512, 512),
                            title='Rotating cube',
                            keys='interactive')
        self.timer = app.Timer('auto', self.on_timer)

        # Build cube data
        V, I, O = create_cube()
        vertices = VertexBuffer(V)
        self.faces = IndexBuffer(I)
        self.outline = IndexBuffer(O)

        # Build program
        # --------------------------------------
        self.program = Program(vertex, fragment)
        self.program.bind(vertices)

        # Build view, model, projection & normal
        # --------------------------------------
        view = np.eye(4, dtype=np.float32)
        model = np.eye(4, dtype=np.float32)
        translate(view, 0, 0, -5)
        self.program['u_model'] = model
        self.program['u_view'] = view
        self.phi, self.theta = 0, 0

        # OpenGL initalization
        # --------------------------------------
        gloo.set_state(clear_color=(0.30, 0.30, 0.35, 1.00),
                       depth_test=True,
                       polygon_offset=(1, 1),
                       line_width=0.75,
                       blend_func=('src_alpha', 'one_minus_src_alpha'))
        self.timer.start()

    def on_draw(self, event):
        gloo.clear(color=True, depth=True)

        # Filled cube
        gloo.set_state(blend=False, depth_test=True, polygon_offset_fill=True)
        self.program['u_color'] = 1, 1, 1, 1
        self.program.draw('triangles', self.faces)

        # Outlined cube
        gloo.set_state(blend=True, depth_mask=False, polygon_offset_fill=False)
        self.program['u_color'] = 0, 0, 0, 1
        self.program.draw('lines', self.outline)
        gloo.set_state(depth_mask=True)

    def on_resize(self, event):
        gloo.set_viewport(0, 0, *event.size)
        projection = perspective(45.0, event.size[0] / float(event.size[1]),
                                 2.0, 10.0)
        self.program['u_projection'] = projection

    def on_timer(self, event):
        self.theta += .5
        self.phi += .5
        model = np.eye(4, dtype=np.float32)
        rotate(model, self.theta, 0, 0, 1)
        rotate(model, self.phi, 0, 1, 0)
        self.program['u_model'] = model
        self.update()
예제 #38
0
파일: lighted_cube.py 프로젝트: Lx37/vispy
class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self, size=(512, 512), title='Lighted cube',
                            keys='interactive')
        self.timer = app.Timer('auto', self.on_timer)

        # Build cube data
        V, F, O = create_cube()
        vertices = VertexBuffer(V)
        self.faces = IndexBuffer(F)
        self.outline = IndexBuffer(O)

        # Build view, model, projection & normal
        # --------------------------------------
        self.view = translate((0, 0, -5))
        model = np.eye(4, dtype=np.float32)
        normal = np.array(np.matrix(np.dot(self.view, model)).I.T)

        # Build program
        # --------------------------------------
        self.program = Program(vertex, fragment)
        self.program.bind(vertices)
        self.program["u_light_position"] = 2, 2, 2
        self.program["u_light_intensity"] = 1, 1, 1
        self.program["u_model"] = model
        self.program["u_view"] = self.view
        self.program["u_normal"] = normal
        self.phi, self.theta = 0, 0

        self.activate_zoom()

        # OpenGL initialization
        # --------------------------------------
        gloo.set_state(clear_color=(0.30, 0.30, 0.35, 1.00), depth_test=True,
                       polygon_offset=(1, 1),
                       blend_func=('src_alpha', 'one_minus_src_alpha'),
                       line_width=0.75)
        self.timer.start()

        self.show()

    def on_draw(self, event):
        gloo.clear(color=True, depth=True)
        # program.draw(gl.GL_TRIANGLES, indices)

        # Filled cube
        gloo.set_state(blend=False, depth_test=True, polygon_offset_fill=True)
        self.program['u_color'] = 1, 1, 1, 1
        self.program.draw('triangles', self.faces)

        # Outlined cube
        gloo.set_state(polygon_offset_fill=False, blend=True, depth_mask=False)
        self.program['u_color'] = 0, 0, 0, 1
        self.program.draw('lines', self.outline)
        gloo.set_state(depth_mask=True)

    def on_resize(self, event):
        self.activate_zoom()

    def activate_zoom(self):
        gloo.set_viewport(0, 0, *self.physical_size)
        projection = perspective(45.0, self.size[0] / float(self.size[1]),
                                 2.0, 10.0)
        self.program['u_projection'] = projection

    def on_timer(self, event):
        self.theta += .5
        self.phi += .5
        model = np.dot(rotate(self.theta, (0, 0, 1)),
                       rotate(self.phi, (0, 1, 0)))
        normal = np.linalg.inv(np.dot(self.view, model)).T
        self.program['u_model'] = model
        self.program['u_normal'] = normal
        self.update()