Import_3ds: Improved distance cue node setup
[blender-addons.git] / mesh_snap_utilities_line / drawing_utilities.py
blob4c7b62de6867ff74cd1cb42df41646d01d01d629
1 # SPDX-FileCopyrightText: 2019-2023 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 import gpu
6 from mathutils import Vector, Matrix
9 class SnapDrawn():
10 __slots__ = (
11 'out_color',
12 'face_color',
13 'edge_color',
14 'vert_color',
15 'center_color',
16 'perpendicular_color',
17 'constrain_shift_color',
18 'axis_x_color',
19 'axis_y_color',
20 'axis_z_color',
21 'rv3d',
22 '_point_size',
23 '_line_width',
24 '_format_pos',
25 '_format_pos_and_color',
26 '_program_unif_col',
27 '_program_smooth_col',
28 '_UBO',
29 '_batch_point',)
31 def __init__(self, out_color, face_color,
32 edge_color, vert_color, center_color,
33 perpendicular_color, constrain_shift_color,
34 axis_x_color, axis_y_color, axis_z_color, rv3d, ui_scale):
36 import gpu
38 self.out_color = out_color
39 self.face_color = face_color
40 self.edge_color = edge_color
41 self.vert_color = vert_color
42 self.center_color = center_color
43 self.perpendicular_color = perpendicular_color
44 self.constrain_shift_color = constrain_shift_color
46 self.axis_x_color = axis_x_color
47 self.axis_y_color = axis_y_color
48 self.axis_z_color = axis_z_color
50 self.rv3d = rv3d
52 self._point_size = 5 * ui_scale
53 self._line_width = 3 * ui_scale
55 self._format_pos = gpu.types.GPUVertFormat()
56 self._format_pos.attr_add(
57 id="pos", comp_type='F32', len=3, fetch_mode='FLOAT')
59 self._format_pos_and_color = gpu.types.GPUVertFormat()
60 self._format_pos_and_color.attr_add(
61 id="pos", comp_type='F32', len=3, fetch_mode='FLOAT')
62 self._format_pos_and_color.attr_add(
63 id="color", comp_type='F32', len=4, fetch_mode='FLOAT')
65 self._UBO = None
67 self._batch_point = None
69 def _gl_state_push(self, ob_mat=None):
70 clip_planes = self.rv3d.clip_planes if self.rv3d.use_clip_planes else None
71 config = 'CLIPPED' if clip_planes else 'DEFAULT'
72 self._program_unif_col = gpu.shader.from_builtin(
73 "UNIFORM_COLOR", config=config)
74 self._program_smooth_col = gpu.shader.from_builtin(
75 "SMOOTH_COLOR", config=config)
77 gpu.state.program_point_size_set(False)
78 gpu.state.blend_set('ALPHA')
79 gpu.matrix.push()
80 if ob_mat:
81 gpu.matrix.multiply_matrix(ob_mat)
83 if clip_planes:
84 gpu.state.clip_distances_set(4)
85 if self._UBO is None:
86 import ctypes
88 class _GPUClipPlanes(ctypes.Structure):
89 _pack_ = 16
90 _fields_ = [
91 ("ModelMatrix", (ctypes.c_float * 4) * 4),
92 ("world", (ctypes.c_float * 4) * 6),
95 mat = ob_mat.transposed() if ob_mat else Matrix.Identity(4)
97 UBO_data = _GPUClipPlanes()
98 UBO_data.ModelMatrix[0] = mat[0][:]
99 UBO_data.ModelMatrix[1] = mat[1][:]
100 UBO_data.ModelMatrix[2] = mat[2][:]
101 UBO_data.ModelMatrix[3] = mat[3][:]
103 UBO_data.world[0] = clip_planes[0][:]
104 UBO_data.world[1] = clip_planes[1][:]
105 UBO_data.world[2] = clip_planes[2][:]
106 UBO_data.world[3] = clip_planes[3][:]
108 self._UBO = gpu.types.GPUUniformBuf(UBO_data)
110 self._program_unif_col.bind()
111 self._program_unif_col.uniform_block("clipPlanes", self._UBO)
113 self._program_smooth_col.bind()
114 self._program_smooth_col.uniform_block("clipPlanes", self._UBO)
116 def _gl_state_restore(self):
117 gpu.state.blend_set('NONE')
118 gpu.matrix.pop()
119 if self._UBO:
120 # del self._UBO
121 self._UBO = None
122 gpu.state.clip_distances_set(0)
124 def batch_line_strip_create(self, coords):
125 from gpu.types import (
126 GPUVertBuf,
127 GPUBatch,
130 vbo = GPUVertBuf(self._format_pos, len=len(coords))
131 vbo.attr_fill(0, data=coords)
132 batch_lines = GPUBatch(type="LINE_STRIP", buf=vbo)
133 return batch_lines
135 def batch_lines_smooth_color_create(self, coords, colors):
136 from gpu.types import (
137 GPUVertBuf,
138 GPUBatch,
141 vbo = GPUVertBuf(self._format_pos_and_color, len=len(coords))
142 vbo.attr_fill(0, data=coords)
143 vbo.attr_fill(1, data=colors)
144 batch_lines = GPUBatch(type="LINES", buf=vbo)
145 return batch_lines
147 def batch_triangles_create(self, coords):
148 from gpu.types import (
149 GPUVertBuf,
150 GPUBatch,
153 vbo = GPUVertBuf(self._format_pos, len=len(coords))
154 vbo.attr_fill(0, data=coords)
155 batch_tris = GPUBatch(type="TRIS", buf=vbo)
156 return batch_tris
158 def batch_point_get(self):
159 if self._batch_point is None:
160 from gpu.types import (
161 GPUVertBuf,
162 GPUBatch,
164 vbo = GPUVertBuf(self._format_pos, len=1)
165 vbo.attr_fill(0, ((0.0, 0.0, 0.0),))
166 self._batch_point = GPUBatch(type="POINTS", buf=vbo)
167 return self._batch_point
169 def draw(self, type, location, list_verts_co, vector_constrain, prevloc):
170 import gpu
172 self._gl_state_push()
173 self._program_unif_col.bind()
175 if list_verts_co:
176 # draw 3d line OpenGL in the 3D View
177 winmat = gpu.matrix.get_projection_matrix()
178 winmat[3][2] -= 0.0001
179 gpu.matrix.push_projection()
180 gpu.matrix.load_projection_matrix(winmat)
181 gpu.state.line_width_set(self._line_width)
183 batch = self.batch_line_strip_create(
184 [v.to_tuple() for v in list_verts_co] + [location.to_tuple()])
186 self._program_unif_col.bind()
187 self._program_unif_col.uniform_float("color", (1.0, 0.8, 0.0, 0.5))
189 batch.draw(self._program_unif_col)
190 gpu.matrix.pop_projection()
191 del batch
193 gpu.state.depth_test_set('NONE')
195 point_batch = self.batch_point_get()
196 if vector_constrain:
197 if prevloc:
198 gpu.state.point_size_set(self._point_size)
199 gpu.matrix.translate(prevloc)
201 self._program_unif_col.bind()
202 self._program_unif_col.uniform_float(
203 "color", (1.0, 1.0, 1.0, 0.5))
205 point_batch.draw(self._program_unif_col)
206 gpu.matrix.translate(-prevloc)
208 if vector_constrain[2] == 'X':
209 Color4f = self.axis_x_color
210 elif vector_constrain[2] == 'Y':
211 Color4f = self.axis_y_color
212 elif vector_constrain[2] == 'Z':
213 Color4f = self.axis_z_color
214 else:
215 Color4f = self.constrain_shift_color
216 else:
217 if type == 'OUT':
218 Color4f = self.out_color
219 elif type == 'FACE':
220 Color4f = self.face_color
221 elif type == 'EDGE':
222 Color4f = self.edge_color
223 elif type == 'VERT':
224 Color4f = self.vert_color
225 elif type == 'CENTER':
226 Color4f = self.center_color
227 elif type == 'PERPENDICULAR':
228 Color4f = self.perpendicular_color
229 else: # type == None
230 Color4f = self.out_color
232 gpu.state.point_size_set(2 * self._point_size)
234 gpu.matrix.translate(location)
235 self._program_unif_col.bind()
236 self._program_unif_col.uniform_float("color", Color4f)
237 point_batch.draw(self._program_unif_col)
239 # restore opengl defaults
240 gpu.state.point_size_set(1.0)
241 gpu.state.line_width_set(1.0)
242 gpu.state.depth_test_set('LESS_EQUAL')
244 self._gl_state_restore()
246 def draw_elem(self, snap_obj, bm, elem):
247 # TODO: Cache coords (because antialiasing)
248 import gpu
249 from bmesh.types import (
250 BMVert,
251 BMEdge,
252 BMFace,
255 self._gl_state_push(snap_obj.mat)
256 gpu.state.depth_test_set('NONE')
258 if isinstance(elem, BMVert):
259 if elem.link_edges:
260 import numpy as np
262 color = self.vert_color
263 edges = np.empty((len(elem.link_edges), 2), [
264 ("pos", "f4", 3), ("color", "f4", 4)])
265 edges["pos"][:, 0] = elem.co
266 edges["pos"][:, 1] = [e.other_vert(
267 elem).co for e in elem.link_edges]
268 edges["color"][:, 0] = color
269 edges["color"][:, 1] = (color[0], color[1], color[2], 0.0)
270 edges.shape = -1
272 self._program_smooth_col.bind()
273 gpu.state.line_width_set(self._line_width)
274 batch = self.batch_lines_smooth_color_create(
275 edges["pos"], edges["color"])
276 batch.draw(self._program_smooth_col)
277 gpu.state.line_width_set(1.0)
278 else:
279 if isinstance(elem, BMEdge):
280 self._program_unif_col.bind()
281 self._program_unif_col.uniform_float("color", self.edge_color)
283 gpu.state.line_width_set(self._line_width)
284 batch = self.batch_line_strip_create(
285 [v.co for v in elem.verts])
286 batch.draw(self._program_unif_col)
287 gpu.state.line_width_set(1.0)
289 elif isinstance(elem, BMFace):
290 if len(snap_obj.data) == 2:
291 face_color = self.face_color[0], self.face_color[1], self.face_color[2], self.face_color[3] * 0.2
292 self._program_unif_col.bind()
293 self._program_unif_col.uniform_float("color", face_color)
295 tris = snap_obj.data[1].get_loop_tri_co_by_bmface(bm, elem)
296 tris.shape = (-1, 3)
297 batch = self.batch_triangles_create(tris)
298 batch.draw(self._program_unif_col)
300 # restore opengl defaults
301 gpu.state.depth_test_set('LESS_EQUAL')
303 self._gl_state_restore()