Blender  V3.3
editmesh_preselect_edgering.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "MEM_guardedalloc.h"
8 
9 #include "DNA_userdef_types.h"
10 
11 #include "BLI_math.h"
12 #include "BLI_stack.h"
13 
14 #include "BKE_editmesh.h"
15 
16 #include "GPU_immediate.h"
17 #include "GPU_matrix.h"
18 #include "GPU_state.h"
19 
20 #include "ED_mesh.h"
21 
22 #include "UI_resources.h"
23 
24 /* -------------------------------------------------------------------- */
36 static void edgering_vcos_get(BMVert *v[2][2], float r_cos[2][2][3], const float (*coords)[3])
37 {
38  if (coords) {
39  int j, k;
40  for (j = 0; j < 2; j++) {
41  for (k = 0; k < 2; k++) {
42  copy_v3_v3(r_cos[j][k], coords[BM_elem_index_get(v[j][k])]);
43  }
44  }
45  }
46  else {
47  int j, k;
48  for (j = 0; j < 2; j++) {
49  for (k = 0; k < 2; k++) {
50  copy_v3_v3(r_cos[j][k], v[j][k]->co);
51  }
52  }
53  }
54 }
55 
56 static void edgering_vcos_get_pair(BMVert *v[2], float r_cos[2][3], const float (*coords)[3])
57 {
58  if (coords) {
59  int j;
60  for (j = 0; j < 2; j++) {
61  copy_v3_v3(r_cos[j], coords[BM_elem_index_get(v[j])]);
62  }
63  }
64  else {
65  int j;
66  for (j = 0; j < 2; j++) {
67  copy_v3_v3(r_cos[j], v[j]->co);
68  }
69  }
70 }
71 
76 static void edgering_find_order(BMEdge *eed_last, BMEdge *eed, BMVert *eve_last, BMVert *v[2][2])
77 {
78  BMLoop *l = eed->l;
79 
80  /* find correct order for v[1] */
81  if (!(BM_edge_in_face(eed, l->f) && BM_edge_in_face(eed_last, l->f))) {
82  BMIter liter;
83  BM_ITER_ELEM (l, &liter, l, BM_LOOPS_OF_LOOP) {
84  if (BM_edge_in_face(eed, l->f) && BM_edge_in_face(eed_last, l->f)) {
85  break;
86  }
87  }
88  }
89 
90  /* this should never happen */
91  if (!l) {
92  v[0][0] = eed->v1;
93  v[0][1] = eed->v2;
94  v[1][0] = eed_last->v1;
95  v[1][1] = eed_last->v2;
96  return;
97  }
98 
99  BMLoop *l_other = BM_loop_other_edge_loop(l, eed->v1);
100  const bool rev = (l_other == l->prev);
101  while (!ELEM(l_other->v, eed_last->v1, eed_last->v2)) {
102  l_other = rev ? l_other->prev : l_other->next;
103  }
104 
105  if (l_other->v == eve_last) {
106  v[0][0] = eed->v1;
107  v[0][1] = eed->v2;
108  }
109  else {
110  v[0][0] = eed->v2;
111  v[0][1] = eed->v1;
112  }
113 }
114 
116  float (*edges)[2][3];
118 
119  float (*verts)[3];
121 };
122 
124 {
125  struct EditMesh_PreSelEdgeRing *psel = MEM_callocN(sizeof(*psel), __func__);
126  return psel;
127 }
128 
130 {
132  MEM_freeN(psel);
133 }
134 
136 {
137  MEM_SAFE_FREE(psel->edges);
138  psel->edges_len = 0;
139 
140  MEM_SAFE_FREE(psel->verts);
141  psel->verts_len = 0;
142 }
143 
144 void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const float matrix[4][4])
145 {
146  if ((psel->edges_len == 0) && (psel->verts_len == 0)) {
147  return;
148  }
149 
152 
153  GPU_matrix_push();
154  GPU_matrix_mul(matrix);
155 
157 
158  if (psel->edges_len > 0) {
159  float viewport[4];
160  GPU_viewport_size_get_f(viewport);
161 
163  immUniform2fv("viewportSize", &viewport[2]);
165  immUniform1f("lineWidth", U.pixelsize);
166  immBegin(GPU_PRIM_LINES, psel->edges_len * 2);
167 
168  for (int i = 0; i < psel->edges_len; i++) {
169  immVertex3fv(pos, psel->edges[i][0]);
170  immVertex3fv(pos, psel->edges[i][1]);
171  }
172 
173  immEnd();
175  }
176 
177  if (psel->verts_len > 0) {
181 
182  /* Same size as an edit mode vertex */
183  immUniform1f("size",
184  2.0 * U.pixelsize *
185  (max_ff(1.0f, UI_GetThemeValuef(TH_VERTEX_SIZE) * (float)M_SQRT2 / 2.0f)));
186 
188 
189  for (int i = 0; i < psel->verts_len; i++) {
190  immVertex3fv(pos, psel->verts[i]);
191  }
192 
193  immEnd();
195  GPU_program_point_size(false);
196  }
197 
198  GPU_matrix_pop();
199 
200  /* Reset default */
203 }
204 
206  struct EditMesh_PreSelEdgeRing *psel,
207  BMesh *UNUSED(bm),
208  BMEdge *eed_start,
209  int previewlines,
210  const float (*coords)[3])
211 {
212  float v_cos[2][3];
213  float(*verts)[3];
214  int i, tot = 0;
215 
216  verts = MEM_mallocN(sizeof(*psel->verts) * previewlines, __func__);
217 
218  edgering_vcos_get_pair(&eed_start->v1, v_cos, coords);
219 
220  for (i = 1; i <= previewlines; i++) {
221  const float fac = (i / ((float)previewlines + 1));
222  interp_v3_v3v3(verts[tot], v_cos[0], v_cos[1], fac);
223  tot++;
224  }
225 
226  psel->verts = verts;
227  psel->verts_len = previewlines;
228 }
229 
231  struct EditMesh_PreSelEdgeRing *psel,
232  BMesh *bm,
233  BMEdge *eed_start,
234  int previewlines,
235  const float (*coords)[3])
236 {
237  BMWalker walker;
238  BMEdge *eed, *eed_last;
239  BMVert *v[2][2] = {{NULL}}, *eve_last;
240  float(*edges)[2][3] = NULL;
241  BLI_Stack *edge_stack;
242 
243  int i, tot = 0;
244 
245  BMW_init(&walker,
246  bm,
247  BMW_EDGERING,
248  BMW_MASK_NOP,
249  BMW_MASK_NOP,
250  BMW_MASK_NOP,
252  BMW_NIL_LAY);
253 
254  edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
255 
256  eed_last = NULL;
257  for (eed = eed_last = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) {
258  BLI_stack_push(edge_stack, &eed);
259  }
260  BMW_end(&walker);
261 
262  eed_start = *(BMEdge **)BLI_stack_peek(edge_stack);
263 
264  edges = MEM_mallocN((sizeof(*edges) * (BLI_stack_count(edge_stack) + (eed_last != eed_start))) *
265  previewlines,
266  __func__);
267 
268  eve_last = NULL;
269  eed_last = NULL;
270 
271  while (!BLI_stack_is_empty(edge_stack)) {
272  BLI_stack_pop(edge_stack, &eed);
273 
274  if (eed_last) {
275  if (eve_last) {
276  v[1][0] = v[0][0];
277  v[1][1] = v[0][1];
278  }
279  else {
280  v[1][0] = eed_last->v1;
281  v[1][1] = eed_last->v2;
282  eve_last = eed_last->v1;
283  }
284 
285  edgering_find_order(eed_last, eed, eve_last, v);
286  eve_last = v[0][0];
287 
288  for (i = 1; i <= previewlines; i++) {
289  const float fac = (i / ((float)previewlines + 1));
290  float v_cos[2][2][3];
291 
292  edgering_vcos_get(v, v_cos, coords);
293 
294  interp_v3_v3v3(edges[tot][0], v_cos[0][0], v_cos[0][1], fac);
295  interp_v3_v3v3(edges[tot][1], v_cos[1][0], v_cos[1][1], fac);
296  tot++;
297  }
298  }
299  eed_last = eed;
300  }
301 
302  if ((eed_last != eed_start) &&
303 #ifdef BMW_EDGERING_NGON
304  BM_edge_share_face_check(eed_last, eed_start)
305 #else
306  BM_edge_share_quad_check(eed_last, eed_start)
307 #endif
308  ) {
309  v[1][0] = v[0][0];
310  v[1][1] = v[0][1];
311 
312  edgering_find_order(eed_last, eed_start, eve_last, v);
313 
314  for (i = 1; i <= previewlines; i++) {
315  const float fac = (i / ((float)previewlines + 1));
316  float v_cos[2][2][3];
317 
318  if (!v[0][0] || !v[0][1] || !v[1][0] || !v[1][1]) {
319  continue;
320  }
321 
322  edgering_vcos_get(v, v_cos, coords);
323 
324  interp_v3_v3v3(edges[tot][0], v_cos[0][0], v_cos[0][1], fac);
325  interp_v3_v3v3(edges[tot][1], v_cos[1][0], v_cos[1][1], fac);
326  tot++;
327  }
328  }
329 
330  BLI_stack_free(edge_stack);
331 
332  psel->edges = edges;
333  psel->edges_len = tot;
334 }
335 
337  BMesh *bm,
338  BMEdge *eed_start,
339  int previewlines,
340  const float (*coords)[3])
341 {
343 
344  if (coords) {
346  }
347 
348  if (BM_edge_is_any_face_len_test(eed_start, 4)) {
350  psel, bm, eed_start, previewlines, coords);
351  }
352  else {
354  psel, bm, eed_start, previewlines, coords);
355  }
356 }
357 
typedef float(TangentPoint)[2]
MINLINE float max_ff(float a, float b)
#define M_SQRT2
Definition: BLI_math_base.h:29
MINLINE void copy_v3_v3(float r[3], const float a[3])
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
void BLI_stack_pop(BLI_Stack *stack, void *dst) ATTR_NONNULL()
Definition: stack.c:135
void * BLI_stack_peek(BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:166
size_t BLI_stack_count(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:225
void BLI_stack_push(BLI_Stack *stack, const void *src) ATTR_NONNULL()
Definition: stack.c:129
bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:247
void BLI_stack_free(BLI_Stack *stack) ATTR_NONNULL()
Definition: stack.c:94
#define BLI_stack_new(esize, descr)
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
#define ELEM(...)
void immUniform2fv(const char *name, const float data[2])
void immUnbindProgram(void)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immUniformThemeColor3(int color_id)
void immUniform1f(const char *name, float x)
GPUVertFormat * immVertexFormat(void)
void immVertex3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void immEnd(void)
void GPU_matrix_pop(void)
Definition: gpu_matrix.cc:126
#define GPU_matrix_mul(x)
Definition: GPU_matrix.h:224
void GPU_matrix_push(void)
Definition: gpu_matrix.cc:119
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:20
@ GPU_PRIM_POINTS
Definition: GPU_primitive.h:19
@ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR
Definition: GPU_shader.h:253
@ GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA
Definition: GPU_shader.h:338
void GPU_program_point_size(bool enable)
Definition: gpu_state.cc:172
@ GPU_BLEND_NONE
Definition: GPU_state.h:60
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:62
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:39
@ GPU_DEPTH_LESS_EQUAL
Definition: GPU_state.h:86
@ GPU_DEPTH_NONE
Definition: GPU_state.h:83
void GPU_depth_test(eGPUDepthTest test)
Definition: gpu_state.cc:65
void GPU_viewport_size_get_f(float coords[4])
Definition: gpu_state.cc:259
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
@ TH_VERTEX_SIZE
Definition: UI_resources.h:81
@ TH_GIZMO_PRIMARY
Definition: UI_resources.h:305
float UI_GetThemeValuef(int colorid)
Definition: resources.c:1141
@ BM_VERT
Definition: bmesh_class.h:383
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
#define BM_ITER_ELEM(ele, iter, data, itype)
@ BM_LOOPS_OF_LOOP
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.cc:446
bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2)
Definition: bmesh_query.c:1054
bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
Definition: bmesh_query.c:420
bool BM_edge_is_any_face_len_test(const BMEdge *e, const int len)
Definition: bmesh_query.c:2017
bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2)
Definition: bmesh_query.c:1036
BMLoop * BM_loop_other_edge_loop(BMLoop *l, BMVert *v)
Definition: bmesh_query.c:33
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
void BMW_init(BMWalker *walker, BMesh *bm, int type, short mask_vert, short mask_edge, short mask_face, BMWFlag flag, int layer)
Init Walker.
Definition: bmesh_walkers.c:49
void BMW_end(BMWalker *walker)
End Walker.
void * BMW_begin(BMWalker *walker, void *start)
Definition: bmesh_walkers.c:40
void * BMW_step(BMWalker *walker)
Step Walker.
#define BMW_NIL_LAY
@ BMW_FLAG_TEST_HIDDEN
Definition: bmesh_walkers.h:20
#define BMW_MASK_NOP
Definition: bmesh_walkers.h:54
@ BMW_EDGERING
unsigned int U
Definition: btGjkEpa3.h:78
static void edgering_vcos_get_pair(BMVert *v[2], float r_cos[2][3], const float(*coords)[3])
void EDBM_preselect_edgering_destroy(struct EditMesh_PreSelEdgeRing *psel)
static void view3d_preselect_mesh_edgering_update_verts_from_edge(struct EditMesh_PreSelEdgeRing *psel, BMesh *UNUSED(bm), BMEdge *eed_start, int previewlines, const float(*coords)[3])
void EDBM_preselect_edgering_clear(struct EditMesh_PreSelEdgeRing *psel)
void EDBM_preselect_edgering_update_from_edge(struct EditMesh_PreSelEdgeRing *psel, BMesh *bm, BMEdge *eed_start, int previewlines, const float(*coords)[3])
struct EditMesh_PreSelEdgeRing * EDBM_preselect_edgering_create(void)
void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const float matrix[4][4])
static void edgering_find_order(BMEdge *eed_last, BMEdge *eed, BMVert *eve_last, BMVert *v[2][2])
static void edgering_vcos_get(BMVert *v[2][2], float r_cos[2][2][3], const float(*coords)[3])
static void view3d_preselect_mesh_edgering_update_edges_from_edge(struct EditMesh_PreSelEdgeRing *psel, BMesh *bm, BMEdge *eed_start, int previewlines, const float(*coords)[3])
static float verts[][3]
uint pos
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
BMVert * v1
Definition: bmesh_class.h:122
BMVert * v2
Definition: bmesh_class.h:122
struct BMLoop * l
Definition: bmesh_class.h:128
struct BMVert * v
Definition: bmesh_class.h:153
struct BMLoop * prev
Definition: bmesh_class.h:233
struct BMFace * f
Definition: bmesh_class.h:171
struct BMLoop * next
Definition: bmesh_class.h:233