def new_custom_shape(type, verts): """ Create a new shape that can be passed to :class:`bpy.types.Gizmo.draw_custom_shape`. :arg type: The type of shape to create in (POINTS, LINES, TRIS, LINE_STRIP). :type type: string :arg verts: Coordinates. :type verts: sequence of of 2D or 3D coordinates. :arg display_name: Optional callback that takes the full path, returns the name to display. :type display_name: Callable that takes a string and returns a string. :return: The newly created shape. :rtype: Undefined (it may change). """ import gpu from gpu.types import ( GPUBatch, GPUVertBuf, GPUVertFormat, ) dims = len(verts[0]) if dims not in {2, 3}: raise ValueError("Expected 2D or 3D vertex") fmt = GPUVertFormat() pos_id = fmt.attr_add(id="pos", comp_type='F32', len=dims, fetch_mode='FLOAT') vbo = GPUVertBuf(len=len(verts), format=fmt) vbo.attr_fill(id=pos_id, data=verts) batch = GPUBatch(type=type, buf=vbo) shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR' if dims == 3 else '2D_UNIFORM_COLOR') batch.program_set(shader) return (batch, shader)
def draw_circle_2d(position, color, radius, *, segments=32): """ Draw a circle. :arg position: Position where the circle will be drawn. :type position: 2D Vector :arg color: Color of the circle. To use transparency GL_BLEND has to be enabled. :type color: tuple containing RGBA values :arg radius: Radius of the circle. :type radius: float :arg segments: How many segments will be used to draw the circle. Higher values give besser results but the drawing will take longer. :type segments: int """ from math import sin, cos, pi import gpu from gpu.types import ( GPUBatch, GPUVertBuf, GPUVertFormat, ) if segments <= 0: raise ValueError("Amount of segments must be greater than 0.") with gpu.matrix.push_pop(): gpu.matrix.translate(position) gpu.matrix.scale_uniform(radius) mul = (1.0 / (segments - 1)) * (pi * 2) verts = [(sin(i * mul), cos(i * mul)) for i in range(segments)] fmt = GPUVertFormat() pos_id = fmt.attr_add(id="pos", comp_type='F32', len=2, fetch_mode='FLOAT') vbo = GPUVertBuf(len=len(verts), format=fmt) vbo.attr_fill(id=pos_id, data=verts) batch = GPUBatch(type='LINE_STRIP', buf=vbo) shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR') batch.program_set(shader) shader.uniform_float("color", color) batch.draw()
def draw_circle_2d(position, color, radius, segments=32): """ Draw a circle. :arg position: Position where the circle will be drawn. :type position: 2D Vector :arg color: Color of the circle. To use transparency GL_BLEND has to be enabled. :type color: tuple containing RGBA values :arg radius: Radius of the circle. :type radius: float :arg segments: How many segments will be used to draw the circle. Higher values give besser results but the drawing will take longer. :type segments: int """ from math import sin, cos, pi import gpu from gpu.types import ( GPUBatch, GPUVertBuf, GPUVertFormat, ) if segments <= 0: raise ValueError("Amount of segments must be greater than 0.") with gpu.matrix.push_pop(): gpu.matrix.translate(position) gpu.matrix.scale_uniform(radius) mul = (1.0 / (segments - 1)) * (pi * 2) verts = [(sin(i * mul), cos(i * mul)) for i in range(segments)] fmt = GPUVertFormat() pos_id = fmt.attr_add(id="pos", comp_type='F32', len=2, fetch_mode='FLOAT') vbo = GPUVertBuf(len=len(verts), format=fmt) vbo.attr_fill(id=pos_id, data=verts) batch = GPUBatch(type='LINE_STRIP', buf=vbo) shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR') batch.program_set(shader) shader.uniform_float("color", color) batch.draw()
def draw_circle_2d(position, color, radius, segments=32, batch_type='TRI_FAN'): from math import sin, cos, pi import gpu from gpu.types import ( GPUBatch, GPUVertBuf, GPUVertFormat, ) if segments <= 0: raise ValueError("Amount of segments must be greater than 0.") bgl.glEnable(bgl.GL_LINE_SMOOTH) bgl.glEnable(bgl.GL_BLEND) bgl.glDepthMask(False) with gpu.matrix.push_pop(): gpu.matrix.translate(position) gpu.matrix.scale_uniform(radius) mul = (1.0 / (segments - 1)) * (pi * 2) verts = [(sin(i * mul), cos(i * mul)) for i in range(segments)] fmt = GPUVertFormat() pos_id = fmt.attr_add(id="pos", comp_type='F32', len=2, fetch_mode='FLOAT') vbo = GPUVertBuf(len=len(verts), format=fmt) vbo.attr_fill(id=pos_id, data=verts) batch = GPUBatch(type=batch_type, buf=vbo) shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR') batch.program_set(shader) shader.uniform_float("color", color) batch.draw() bgl.glDisable(bgl.GL_BLEND)
def draw_lines(self, context, obj, vertices, indices, topology=None): region = context.region region3d = context.region_data color = context.scene.DocProperties.decorations_colour fmt = GPUVertFormat() fmt.attr_add(id="pos", comp_type="F32", len=3, fetch_mode="FLOAT") if topology: fmt.attr_add(id="topo", comp_type="U8", len=1, fetch_mode="INT") vbo = GPUVertBuf(len=len(vertices), format=fmt) vbo.attr_fill(id="pos", data=vertices) if topology: vbo.attr_fill(id="topo", data=topology) ibo = GPUIndexBuf(type="LINES", seq=indices) batch = GPUBatch(type="LINES", buf=vbo, elem=ibo) bgl.glEnable(bgl.GL_LINE_SMOOTH) bgl.glHint(bgl.GL_LINE_SMOOTH_HINT, bgl.GL_NICEST) bgl.glEnable(bgl.GL_BLEND) bgl.glBlendFunc(bgl.GL_SRC_ALPHA, bgl.GL_ONE_MINUS_SRC_ALPHA) self.shader.bind() self.shader.uniform_float self.shader.uniform_float("viewMatrix", region3d.perspective_matrix) self.shader.uniform_float("winsize", (region.width, region.height)) self.shader.uniform_float("color", color) # Horrific prototype code factor = self.camera_zoom_to_factor( context.space_data.region_3d.view_camera_zoom) camera_width_px = factor * context.region.width mm_to_px = camera_width_px / self.camera_width_mm # 0.00025 is a magic constant number I visually discovered to get the right number. # It probably should be dynamically calculated using system.dpi or something. viewport_drawing_scale = 0.00025 * mm_to_px self.shader.uniform_float("viewportDrawingScale", viewport_drawing_scale) batch.draw(self.shader)