Newer
Older
# SPDX-License-Identifier: GPL-2.0-or-later
Germano Cavalcante
committed
import gpu
from mathutils import Vector, Matrix
'out_color',
'face_color',
'edge_color',
'vert_color',
'center_color',
'perpendicular_color',
'constrain_shift_color',
'axis_x_color',
'axis_y_color',
'axis_z_color',
'_point_size',
'_line_width',
'_format_pos',
'_format_pos_and_color',
'_program_unif_col',
'_program_smooth_col',
Germano Cavalcante
committed
'_batch_point',)
def __init__(self, out_color, face_color,
edge_color, vert_color, center_color,
perpendicular_color, constrain_shift_color,
axis_x_color, axis_y_color, axis_z_color, rv3d, ui_scale):
import gpu
self.out_color = out_color
self.face_color = face_color
self.edge_color = edge_color
self.vert_color = vert_color
self.center_color = center_color
self.perpendicular_color = perpendicular_color
self.constrain_shift_color = constrain_shift_color
self.axis_x_color = axis_x_color
self.axis_y_color = axis_y_color
self.axis_z_color = axis_z_color
self._point_size = 5 * ui_scale
self._line_width = 3 * ui_scale
self._format_pos = gpu.types.GPUVertFormat()
self._format_pos.attr_add(
id="pos", comp_type='F32', len=3, fetch_mode='FLOAT')
self._format_pos_and_color = gpu.types.GPUVertFormat()
self._format_pos_and_color.attr_add(
id="pos", comp_type='F32', len=3, fetch_mode='FLOAT')
self._format_pos_and_color.attr_add(
id="color", comp_type='F32', len=4, fetch_mode='FLOAT')
self._UBO = None
def _gl_state_push(self, ob_mat=None):
clip_planes = self.rv3d.clip_planes if self.rv3d.use_clip_planes else None
config = 'CLIPPED' if clip_planes else 'DEFAULT'
self._program_unif_col = gpu.shader.from_builtin(
"3D_UNIFORM_COLOR", config=config)
self._program_smooth_col = gpu.shader.from_builtin(
"3D_SMOOTH_COLOR", config=config)
Germano Cavalcante
committed
gpu.state.program_point_size_set(False)
gpu.state.blend_set('ALPHA')
gpu.matrix.push()
if ob_mat:
gpu.matrix.multiply_matrix(ob_mat)
if clip_planes:
gpu.state.clip_distances_set(4)
if self._UBO is None:
import ctypes
class _GPUClipPlanes(ctypes.Structure):
_pack_ = 16
_fields_ = [
("ModelMatrix", (ctypes.c_float * 4) * 4),
("world", (ctypes.c_float * 4) * 6),
]
mat = ob_mat.transposed() if ob_mat else Matrix.Identity(4)
UBO_data = _GPUClipPlanes()
UBO_data.ModelMatrix[0] = mat[0][:]
UBO_data.ModelMatrix[1] = mat[1][:]
UBO_data.ModelMatrix[2] = mat[2][:]
UBO_data.ModelMatrix[3] = mat[3][:]
UBO_data.world[0] = clip_planes[0][:]
UBO_data.world[1] = clip_planes[1][:]
UBO_data.world[2] = clip_planes[2][:]
UBO_data.world[3] = clip_planes[3][:]
self._UBO = gpu.types.GPUUniformBuf(UBO_data)
self._program_unif_col.bind()
self._program_unif_col.uniform_block("clipPlanes", self._UBO)
self._program_smooth_col.bind()
self._program_smooth_col.uniform_block("clipPlanes", self._UBO)
def _gl_state_restore(self):
Germano Cavalcante
committed
gpu.state.blend_set('NONE')
if self._UBO:
# del self._UBO
self._UBO = None
gpu.state.clip_distances_set(0)
def batch_line_strip_create(self, coords):
from gpu.types import (
GPUVertBuf,
GPUBatch,
)
vbo = GPUVertBuf(self._format_pos, len=len(coords))
vbo.attr_fill(0, data=coords)
batch_lines = GPUBatch(type="LINE_STRIP", buf=vbo)
return batch_lines
def batch_lines_smooth_color_create(self, coords, colors):
from gpu.types import (
GPUVertBuf,
GPUBatch,
)
vbo = GPUVertBuf(self._format_pos_and_color, len=len(coords))
vbo.attr_fill(0, data=coords)
vbo.attr_fill(1, data=colors)
batch_lines = GPUBatch(type="LINES", buf=vbo)
return batch_lines
def batch_triangles_create(self, coords):
from gpu.types import (
GPUVertBuf,
GPUBatch,
)
vbo = GPUVertBuf(self._format_pos, len=len(coords))
vbo.attr_fill(0, data=coords)
batch_tris = GPUBatch(type="TRIS", buf=vbo)
return batch_tris
def batch_point_get(self):
if self._batch_point is None:
from gpu.types import (
GPUVertBuf,
GPUBatch,
)
vbo = GPUVertBuf(self._format_pos, len=1)
self._batch_point = GPUBatch(type="POINTS", buf=vbo)
return self._batch_point
def draw(self, type, location, list_verts_co, vector_constrain, prevloc):
import gpu
self._program_unif_col.bind()
if list_verts_co:
# draw 3d line OpenGL in the 3D View
Germano Cavalcante
committed
winmat = gpu.matrix.get_projection_matrix()
winmat[3][2] -= 0.0001
gpu.matrix.push_projection()
gpu.matrix.load_projection_matrix(winmat)
gpu.state.line_width_set(self._line_width)
batch = self.batch_line_strip_create(
[v.to_tuple() for v in list_verts_co] + [location.to_tuple()])
Germano Cavalcante
committed
self._program_unif_col.bind()
self._program_unif_col.uniform_float("color", (1.0, 0.8, 0.0, 0.5))
Germano Cavalcante
committed
gpu.matrix.pop_projection()
Germano Cavalcante
committed
gpu.state.depth_test_set('NONE')
point_batch = self.batch_point_get()
if vector_constrain:
if prevloc:
gpu.state.point_size_set(self._point_size)
Germano Cavalcante
committed
self._program_unif_col.bind()
self._program_unif_col.uniform_float(
"color", (1.0, 1.0, 1.0, 0.5))
point_batch.draw(self._program_unif_col)
gpu.matrix.translate(-prevloc)
if vector_constrain[2] == 'X':
Color4f = self.axis_x_color
elif vector_constrain[2] == 'Y':
Color4f = self.axis_y_color
elif vector_constrain[2] == 'Z':
Color4f = self.axis_z_color
else:
Color4f = self.constrain_shift_color
else:
if type == 'OUT':
Color4f = self.out_color
elif type == 'FACE':
Color4f = self.face_color
elif type == 'EDGE':
Color4f = self.edge_color
elif type == 'VERT':
Color4f = self.vert_color
elif type == 'CENTER':
Color4f = self.center_color
elif type == 'PERPENDICULAR':
Color4f = self.perpendicular_color
gpu.state.point_size_set(2 * self._point_size)
Germano Cavalcante
committed
self._program_unif_col.bind()
self._program_unif_col.uniform_float("color", Color4f)
point_batch.draw(self._program_unif_col)
# restore opengl defaults
Germano Cavalcante
committed
gpu.state.point_size_set(1.0)
gpu.state.line_width_set(1.0)
gpu.state.depth_test_set('LESS_EQUAL')
def draw_elem(self, snap_obj, bm, elem):
# TODO: Cache coords (because antialiasing)
from bmesh.types import (
self._gl_state_push(snap_obj.mat)
gpu.state.depth_test_set('NONE')
if isinstance(elem, BMVert):
if elem.link_edges:
import numpy as np
color = self.vert_color
edges = np.empty((len(elem.link_edges), 2), [
("pos", "f4", 3), ("color", "f4", 4)])
edges["pos"][:, 0] = elem.co
edges["pos"][:, 1] = [e.other_vert(
elem).co for e in elem.link_edges]
edges["color"][:, 0] = color
edges["color"][:, 1] = (color[0], color[1], color[2], 0.0)
edges.shape = -1
self._program_smooth_col.bind()
gpu.state.line_width_set(self._line_width)
batch = self.batch_lines_smooth_color_create(
edges["pos"], edges["color"])
batch.draw(self._program_smooth_col)
gpu.state.line_width_set(1.0)
else:
if isinstance(elem, BMEdge):
self._program_unif_col.uniform_float("color", self.edge_color)
gpu.state.line_width_set(self._line_width)
batch = self.batch_line_strip_create(
[v.co for v in elem.verts])
batch.draw(self._program_unif_col)
gpu.state.line_width_set(1.0)
elif isinstance(elem, BMFace):
if len(snap_obj.data) == 2:
face_color = self.face_color[0], self.face_color[1], self.face_color[2], self.face_color[3] * 0.2
Germano Cavalcante
committed
self._program_unif_col.bind()
self._program_unif_col.uniform_float("color", face_color)
tris = snap_obj.data[1].get_loop_tri_co_by_bmface(bm, elem)
tris.shape = (-1, 3)
batch = self.batch_triangles_create(tris)
# restore opengl defaults
gpu.state.depth_test_set('LESS_EQUAL')
self._gl_state_restore()