Blender V4.3
editmesh_preselect_edgering.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "MEM_guardedalloc.h"
10
11#include "DNA_userdef_types.h"
12
13#include "BLI_stack.h"
14
15#include "BKE_editmesh.hh"
16
17#include "GPU_immediate.hh"
18#include "GPU_matrix.hh"
19#include "GPU_state.hh"
20
21#include "ED_mesh.hh"
22
23#include "UI_resources.hh"
24
25using blender::float3;
26using blender::Span;
27
28/* -------------------------------------------------------------------- */
40static void edgering_vcos_get(BMVert *v[2][2],
41 float r_cos[2][2][3],
42 const Span<float3> vert_positions)
43{
44 if (!vert_positions.is_empty()) {
45 int j, k;
46 for (j = 0; j < 2; j++) {
47 for (k = 0; k < 2; k++) {
48 copy_v3_v3(r_cos[j][k], vert_positions[BM_elem_index_get(v[j][k])]);
49 }
50 }
51 }
52 else {
53 int j, k;
54 for (j = 0; j < 2; j++) {
55 for (k = 0; k < 2; k++) {
56 copy_v3_v3(r_cos[j][k], v[j][k]->co);
57 }
58 }
59 }
60}
61
63 float r_cos[2][3],
64 const Span<float3> vert_positions)
65{
66 if (!vert_positions.is_empty()) {
67 int j;
68 for (j = 0; j < 2; j++) {
69 copy_v3_v3(r_cos[j], vert_positions[BM_elem_index_get(v[j])]);
70 }
71 }
72 else {
73 int j;
74 for (j = 0; j < 2; j++) {
75 copy_v3_v3(r_cos[j], v[j]->co);
76 }
77 }
78}
79
84static void edgering_find_order(BMEdge *eed_last, BMEdge *eed, BMVert *eve_last, BMVert *v[2][2])
85{
86 BMLoop *l = eed->l;
87
88 /* find correct order for v[1] */
89 if (!(BM_edge_in_face(eed, l->f) && BM_edge_in_face(eed_last, l->f))) {
90 BMIter liter;
91 BM_ITER_ELEM (l, &liter, l, BM_LOOPS_OF_LOOP) {
92 if (BM_edge_in_face(eed, l->f) && BM_edge_in_face(eed_last, l->f)) {
93 break;
94 }
95 }
96 }
97
98 /* this should never happen */
99 if (!l) {
100 v[0][0] = eed->v1;
101 v[0][1] = eed->v2;
102 v[1][0] = eed_last->v1;
103 v[1][1] = eed_last->v2;
104 return;
105 }
106
107 BMLoop *l_other = BM_loop_other_edge_loop(l, eed->v1);
108 const bool rev = (l_other == l->prev);
109 while (!ELEM(l_other->v, eed_last->v1, eed_last->v2)) {
110 l_other = rev ? l_other->prev : l_other->next;
111 }
112
113 if (l_other->v == eve_last) {
114 v[0][0] = eed->v1;
115 v[0][1] = eed->v2;
116 }
117 else {
118 v[0][0] = eed->v2;
119 v[0][1] = eed->v1;
120 }
121}
122
124 float (*edges)[2][3];
126
129};
130
132{
134 MEM_callocN(sizeof(*psel), __func__));
135 return psel;
136}
137
143
145{
146 MEM_SAFE_FREE(psel->edges);
147 psel->edges_len = 0;
148
149 MEM_SAFE_FREE(psel->verts);
150 psel->verts_len = 0;
151}
152
153void EDBM_preselect_edgering_draw(EditMesh_PreSelEdgeRing *psel, const float matrix[4][4])
154{
155 if ((psel->edges_len == 0) && (psel->verts_len == 0)) {
156 return;
157 }
158
161
163 GPU_matrix_mul(matrix);
164
166
167 if (psel->edges_len > 0) {
168 float viewport[4];
169 GPU_viewport_size_get_f(viewport);
170
172 immUniform2fv("viewportSize", &viewport[2]);
174 immUniform1f("lineWidth", U.pixelsize);
176
177 for (int i = 0; i < psel->edges_len; i++) {
178 immVertex3fv(pos, psel->edges[i][0]);
179 immVertex3fv(pos, psel->edges[i][1]);
180 }
181
182 immEnd();
184 }
185
186 if (psel->verts_len > 0) {
190
191 /* Same size as an edit mode vertex */
192 immUniform1f("size",
193 2.0 * U.pixelsize *
194 max_ff(1.0f, UI_GetThemeValuef(TH_VERTEX_SIZE) * float(M_SQRT2) / 2.0f));
195
197
198 for (int i = 0; i < psel->verts_len; i++) {
199 immVertex3fv(pos, psel->verts[i]);
200 }
201
202 immEnd();
205 }
206
208
209 /* Reset default */
212}
213
216 BMesh * /*bm*/,
217 BMEdge *eed_start,
218 int previewlines,
219 const Span<float3> vert_positions)
220{
221 float v_cos[2][3];
222 float(*verts)[3];
223 int i, tot = 0;
224
225 verts = static_cast<float(*)[3]>(MEM_mallocN(sizeof(*psel->verts) * previewlines, __func__));
226
227 edgering_vcos_get_pair(&eed_start->v1, v_cos, vert_positions);
228
229 for (i = 1; i <= previewlines; i++) {
230 const float fac = (i / (float(previewlines) + 1));
231 interp_v3_v3v3(verts[tot], v_cos[0], v_cos[1], fac);
232 tot++;
233 }
234
235 psel->verts = verts;
236 psel->verts_len = previewlines;
237}
238
241 BMesh *bm,
242 BMEdge *eed_start,
243 int previewlines,
244 const Span<float3> vert_positions)
245{
246 BMWalker walker;
247 BMEdge *eed, *eed_last;
248 BMVert *v[2][2] = {{nullptr}}, *eve_last;
249 float(*edges)[2][3] = nullptr;
250 BLI_Stack *edge_stack;
251
252 int i, tot = 0;
253
254 BMW_init(&walker,
255 bm,
262
263 edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
264
265 eed_last = nullptr;
266 for (eed = eed_last = static_cast<BMEdge *>(BMW_begin(&walker, eed_start)); eed;
267 eed = static_cast<BMEdge *>(BMW_step(&walker)))
268 {
269 BLI_stack_push(edge_stack, &eed);
270 }
271 BMW_end(&walker);
272
273 eed_start = *(BMEdge **)BLI_stack_peek(edge_stack);
274
275 edges = static_cast<float(*)[2][3]>(MEM_mallocN(
276 (sizeof(*edges) * (BLI_stack_count(edge_stack) + (eed_last != eed_start))) * previewlines,
277 __func__));
278
279 eve_last = nullptr;
280 eed_last = nullptr;
281
282 while (!BLI_stack_is_empty(edge_stack)) {
283 BLI_stack_pop(edge_stack, &eed);
284
285 if (eed_last) {
286 if (eve_last) {
287 v[1][0] = v[0][0];
288 v[1][1] = v[0][1];
289 }
290 else {
291 v[1][0] = eed_last->v1;
292 v[1][1] = eed_last->v2;
293 eve_last = eed_last->v1;
294 }
295
296 edgering_find_order(eed_last, eed, eve_last, v);
297 eve_last = v[0][0];
298
299 for (i = 1; i <= previewlines; i++) {
300 const float fac = (i / (float(previewlines) + 1));
301 float v_cos[2][2][3];
302
303 edgering_vcos_get(v, v_cos, vert_positions);
304
305 interp_v3_v3v3(edges[tot][0], v_cos[0][0], v_cos[0][1], fac);
306 interp_v3_v3v3(edges[tot][1], v_cos[1][0], v_cos[1][1], fac);
307 tot++;
308 }
309 }
310 eed_last = eed;
311 }
312
313 if ((eed_last != eed_start) &&
314#ifdef BMW_EDGERING_NGON
315 BM_edge_share_face_check(eed_last, eed_start)
316#else
317 BM_edge_share_quad_check(eed_last, eed_start)
318#endif
319 )
320 {
321 v[1][0] = v[0][0];
322 v[1][1] = v[0][1];
323
324 edgering_find_order(eed_last, eed_start, eve_last, v);
325
326 for (i = 1; i <= previewlines; i++) {
327 const float fac = (i / (float(previewlines) + 1));
328 float v_cos[2][2][3];
329
330 if (!v[0][0] || !v[0][1] || !v[1][0] || !v[1][1]) {
331 continue;
332 }
333
334 edgering_vcos_get(v, v_cos, vert_positions);
335
336 interp_v3_v3v3(edges[tot][0], v_cos[0][0], v_cos[0][1], fac);
337 interp_v3_v3v3(edges[tot][1], v_cos[1][0], v_cos[1][1], fac);
338 tot++;
339 }
340 }
341
342 BLI_stack_free(edge_stack);
343
344 psel->edges = edges;
345 psel->edges_len = tot;
346}
347
349 BMesh *bm,
350 BMEdge *eed_start,
351 int previewlines,
352 const Span<float3> vert_positions)
353{
355
356 if (!vert_positions.is_empty()) {
358 }
359
360 if (BM_edge_is_any_face_len_test(eed_start, 4)) {
362 psel, bm, eed_start, previewlines, vert_positions);
363 }
364 else {
366 psel, bm, eed_start, previewlines, vert_positions);
367 }
368}
369
MINLINE float max_ff(float a, float b)
#define M_SQRT2
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:36
void BLI_stack_pop(BLI_Stack *stack, void *dst) ATTR_NONNULL()
Definition stack.c:137
size_t BLI_stack_count(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition stack.c:227
void BLI_stack_push(BLI_Stack *stack, const void *src) ATTR_NONNULL()
Definition stack.c:131
bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition stack.c:249
void BLI_stack_free(BLI_Stack *stack) ATTR_NONNULL()
Definition stack.c:96
void * BLI_stack_peek(BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition stack.c:168
#define BLI_stack_new(esize, descr)
unsigned int uint
#define ELEM(...)
void immEnd()
void immUniform2fv(const char *name, const float data[2])
void immUnbindProgram()
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immUniformThemeColor3(int color_id)
void immUniform1f(const char *name, float x)
GPUVertFormat * immVertexFormat()
void immVertex3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void GPU_matrix_push()
#define GPU_matrix_mul(x)
void GPU_matrix_pop()
@ GPU_PRIM_LINES
@ GPU_PRIM_POINTS
@ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR
@ GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA
void GPU_program_point_size(bool enable)
Definition gpu_state.cc:175
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
void GPU_blend(eGPUBlend blend)
Definition gpu_state.cc:42
@ GPU_DEPTH_LESS_EQUAL
Definition GPU_state.hh:111
@ GPU_DEPTH_NONE
Definition GPU_state.hh:108
void GPU_depth_test(eGPUDepthTest test)
Definition gpu_state.cc:68
void GPU_viewport_size_get_f(float coords[4])
Definition gpu_state.cc:262
@ 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
@ TH_GIZMO_PRIMARY
float UI_GetThemeValuef(int colorid)
#define BM_elem_index_get(ele)
#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)
#define BM_VERT
BMLoop * BM_loop_other_edge_loop(BMLoop *l, BMVert *v)
bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2)
bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
bool BM_edge_is_any_face_len_test(const BMEdge *e, const int len)
bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2)
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
void * BMW_begin(BMWalker *walker, void *start)
void BMW_init(BMWalker *walker, BMesh *bm, int type, short mask_vert, short mask_edge, short mask_face, BMWFlag flag, int layer)
Init Walker.
void BMW_end(BMWalker *walker)
End Walker.
void * BMW_step(BMWalker *walker)
Step Walker.
#define BMW_NIL_LAY
@ BMW_FLAG_TEST_HIDDEN
#define BMW_MASK_NOP
@ BMW_EDGERING
unsigned int U
Definition btGjkEpa3.h:78
constexpr bool is_empty() const
Definition BLI_span.hh:261
void EDBM_preselect_edgering_destroy(EditMesh_PreSelEdgeRing *psel)
static void view3d_preselect_mesh_edgering_update_verts_from_edge(EditMesh_PreSelEdgeRing *psel, BMesh *, BMEdge *eed_start, int previewlines, const Span< float3 > vert_positions)
void EDBM_preselect_edgering_clear(EditMesh_PreSelEdgeRing *psel)
void EDBM_preselect_edgering_draw(EditMesh_PreSelEdgeRing *psel, const float matrix[4][4])
static void edgering_vcos_get_pair(BMVert *v[2], float r_cos[2][3], const Span< float3 > vert_positions)
EditMesh_PreSelEdgeRing * EDBM_preselect_edgering_create()
void EDBM_preselect_edgering_update_from_edge(EditMesh_PreSelEdgeRing *psel, BMesh *bm, BMEdge *eed_start, int previewlines, const Span< float3 > vert_positions)
static void view3d_preselect_mesh_edgering_update_edges_from_edge(EditMesh_PreSelEdgeRing *psel, BMesh *bm, BMEdge *eed_start, int previewlines, const Span< float3 > vert_positions)
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 Span< float3 > vert_positions)
draw_view in_light_buf[] float
static float verts[][3]
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
BMVert * v1
BMVert * v2
struct BMLoop * l
struct BMVert * v
struct BMLoop * prev
struct BMFace * f
struct BMLoop * next