Blender  V2.93
editmesh_preselect_edgering.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include "MEM_guardedalloc.h"
22 
23 #include "BLI_math.h"
24 #include "BLI_stack.h"
25 
26 #include "BKE_editmesh.h"
27 
28 #include "GPU_immediate.h"
29 #include "GPU_matrix.h"
30 #include "GPU_state.h"
31 
32 #include "ED_mesh.h"
33 
34 #include "UI_resources.h"
35 
36 /* -------------------------------------------------------------------- */
48 static void edgering_vcos_get(BMVert *v[2][2], float r_cos[2][2][3], const float (*coords)[3])
49 {
50  if (coords) {
51  int j, k;
52  for (j = 0; j < 2; j++) {
53  for (k = 0; k < 2; k++) {
54  copy_v3_v3(r_cos[j][k], coords[BM_elem_index_get(v[j][k])]);
55  }
56  }
57  }
58  else {
59  int j, k;
60  for (j = 0; j < 2; j++) {
61  for (k = 0; k < 2; k++) {
62  copy_v3_v3(r_cos[j][k], v[j][k]->co);
63  }
64  }
65  }
66 }
67 
68 static void edgering_vcos_get_pair(BMVert *v[2], float r_cos[2][3], const float (*coords)[3])
69 {
70  if (coords) {
71  int j;
72  for (j = 0; j < 2; j++) {
73  copy_v3_v3(r_cos[j], coords[BM_elem_index_get(v[j])]);
74  }
75  }
76  else {
77  int j;
78  for (j = 0; j < 2; j++) {
79  copy_v3_v3(r_cos[j], v[j]->co);
80  }
81  }
82 }
83 
88 static void edgering_find_order(BMEdge *eed_last, BMEdge *eed, BMVert *eve_last, BMVert *v[2][2])
89 {
90  BMLoop *l = eed->l;
91 
92  /* find correct order for v[1] */
93  if (!(BM_edge_in_face(eed, l->f) && BM_edge_in_face(eed_last, l->f))) {
94  BMIter liter;
95  BM_ITER_ELEM (l, &liter, l, BM_LOOPS_OF_LOOP) {
96  if (BM_edge_in_face(eed, l->f) && BM_edge_in_face(eed_last, l->f)) {
97  break;
98  }
99  }
100  }
101 
102  /* this should never happen */
103  if (!l) {
104  v[0][0] = eed->v1;
105  v[0][1] = eed->v2;
106  v[1][0] = eed_last->v1;
107  v[1][1] = eed_last->v2;
108  return;
109  }
110 
111  BMLoop *l_other = BM_loop_other_edge_loop(l, eed->v1);
112  const bool rev = (l_other == l->prev);
113  while (!ELEM(l_other->v, eed_last->v1, eed_last->v2)) {
114  l_other = rev ? l_other->prev : l_other->next;
115  }
116 
117  if (l_other->v == eve_last) {
118  v[0][0] = eed->v1;
119  v[0][1] = eed->v2;
120  }
121  else {
122  v[0][0] = eed->v2;
123  v[0][1] = eed->v1;
124  }
125 }
126 
128  float (*edges)[2][3];
130 
131  float (*verts)[3];
133 };
134 
136 {
137  struct EditMesh_PreSelEdgeRing *psel = MEM_callocN(sizeof(*psel), __func__);
138  return psel;
139 }
140 
142 {
144  MEM_freeN(psel);
145 }
146 
148 {
149  MEM_SAFE_FREE(psel->edges);
150  psel->edges_len = 0;
151 
152  MEM_SAFE_FREE(psel->verts);
153  psel->verts_len = 0;
154 }
155 
156 void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const float matrix[4][4])
157 {
158  if ((psel->edges_len == 0) && (psel->verts_len == 0)) {
159  return;
160  }
161 
163 
164  GPU_matrix_push();
165  GPU_matrix_mul(matrix);
166 
168 
171 
172  if (psel->edges_len > 0) {
173  immBegin(GPU_PRIM_LINES, psel->edges_len * 2);
174 
175  for (int i = 0; i < psel->edges_len; i++) {
176  immVertex3fv(pos, psel->edges[i][0]);
177  immVertex3fv(pos, psel->edges[i][1]);
178  }
179 
180  immEnd();
181  }
182 
183  if (psel->verts_len > 0) {
184  GPU_point_size(3.0f);
185 
187 
188  for (int i = 0; i < psel->verts_len; i++) {
189  immVertex3fv(pos, psel->verts[i]);
190  }
191 
192  immEnd();
193  }
194 
196 
197  GPU_matrix_pop();
198 
199  /* Reset default */
201 }
202 
204  struct EditMesh_PreSelEdgeRing *psel,
205  BMesh *UNUSED(bm),
206  BMEdge *eed_start,
207  int previewlines,
208  const float (*coords)[3])
209 {
210  float v_cos[2][3];
211  float(*verts)[3];
212  int i, tot = 0;
213 
214  verts = MEM_mallocN(sizeof(*psel->verts) * previewlines, __func__);
215 
216  edgering_vcos_get_pair(&eed_start->v1, v_cos, coords);
217 
218  for (i = 1; i <= previewlines; i++) {
219  const float fac = (i / ((float)previewlines + 1));
220  interp_v3_v3v3(verts[tot], v_cos[0], v_cos[1], fac);
221  tot++;
222  }
223 
224  psel->verts = verts;
225  psel->verts_len = previewlines;
226 }
227 
229  struct EditMesh_PreSelEdgeRing *psel,
230  BMesh *bm,
231  BMEdge *eed_start,
232  int previewlines,
233  const float (*coords)[3])
234 {
235  BMWalker walker;
236  BMEdge *eed, *eed_last;
237  BMVert *v[2][2] = {{NULL}}, *eve_last;
238  float(*edges)[2][3] = NULL;
239  BLI_Stack *edge_stack;
240 
241  int i, tot = 0;
242 
243  BMW_init(&walker,
244  bm,
245  BMW_EDGERING,
246  BMW_MASK_NOP,
247  BMW_MASK_NOP,
248  BMW_MASK_NOP,
250  BMW_NIL_LAY);
251 
252  edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
253 
254  eed_last = NULL;
255  for (eed = eed_last = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) {
256  BLI_stack_push(edge_stack, &eed);
257  }
258  BMW_end(&walker);
259 
260  eed_start = *(BMEdge **)BLI_stack_peek(edge_stack);
261 
262  edges = MEM_mallocN((sizeof(*edges) * (BLI_stack_count(edge_stack) + (eed_last != eed_start))) *
263  previewlines,
264  __func__);
265 
266  eve_last = NULL;
267  eed_last = NULL;
268 
269  while (!BLI_stack_is_empty(edge_stack)) {
270  BLI_stack_pop(edge_stack, &eed);
271 
272  if (eed_last) {
273  if (eve_last) {
274  v[1][0] = v[0][0];
275  v[1][1] = v[0][1];
276  }
277  else {
278  v[1][0] = eed_last->v1;
279  v[1][1] = eed_last->v2;
280  eve_last = eed_last->v1;
281  }
282 
283  edgering_find_order(eed_last, eed, eve_last, v);
284  eve_last = v[0][0];
285 
286  for (i = 1; i <= previewlines; i++) {
287  const float fac = (i / ((float)previewlines + 1));
288  float v_cos[2][2][3];
289 
290  edgering_vcos_get(v, v_cos, coords);
291 
292  interp_v3_v3v3(edges[tot][0], v_cos[0][0], v_cos[0][1], fac);
293  interp_v3_v3v3(edges[tot][1], v_cos[1][0], v_cos[1][1], fac);
294  tot++;
295  }
296  }
297  eed_last = eed;
298  }
299 
300  if ((eed_last != eed_start) &&
301 #ifdef BMW_EDGERING_NGON
302  BM_edge_share_face_check(eed_last, eed_start)
303 #else
304  BM_edge_share_quad_check(eed_last, eed_start)
305 #endif
306  ) {
307  v[1][0] = v[0][0];
308  v[1][1] = v[0][1];
309 
310  edgering_find_order(eed_last, eed_start, eve_last, v);
311 
312  for (i = 1; i <= previewlines; i++) {
313  const float fac = (i / ((float)previewlines + 1));
314  float v_cos[2][2][3];
315 
316  if (!v[0][0] || !v[0][1] || !v[1][0] || !v[1][1]) {
317  continue;
318  }
319 
320  edgering_vcos_get(v, v_cos, coords);
321 
322  interp_v3_v3v3(edges[tot][0], v_cos[0][0], v_cos[0][1], fac);
323  interp_v3_v3v3(edges[tot][1], v_cos[1][0], v_cos[1][1], fac);
324  tot++;
325  }
326  }
327 
328  BLI_stack_free(edge_stack);
329 
330  psel->edges = edges;
331  psel->edges_len = tot;
332 }
333 
335  BMesh *bm,
336  BMEdge *eed_start,
337  int previewlines,
338  const float (*coords)[3])
339 {
341 
342  if (coords) {
344  }
345 
346  if (BM_edge_is_any_face_len_test(eed_start, 4)) {
348  psel, bm, eed_start, previewlines, coords);
349  }
350  else {
352  psel, bm, eed_start, previewlines, coords);
353  }
354 }
355 
typedef float(TangentPoint)[2]
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], const float t)
Definition: math_vector.c:49
MINLINE void copy_v3_v3(float r[3], const float a[3])
void BLI_stack_pop(BLI_Stack *stack, void *dst) ATTR_NONNULL()
Definition: stack.c:175
void * BLI_stack_peek(BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:220
size_t BLI_stack_count(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:285
void BLI_stack_push(BLI_Stack *stack, const void *src) ATTR_NONNULL()
Definition: stack.c:163
bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:310
void BLI_stack_free(BLI_Stack *stack) ATTR_NONNULL()
Definition: stack.c:114
#define BLI_stack_new(esize, descr)
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNUSED(x)
#define ELEM(...)
void immUnbindProgram(void)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immUniformThemeColor3(int color_id)
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:142
#define GPU_matrix_mul(x)
Definition: GPU_matrix.h:223
void GPU_matrix_push(void)
Definition: gpu_matrix.cc:135
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:36
@ GPU_PRIM_POINTS
Definition: GPU_primitive.h:35
@ GPU_SHADER_3D_UNIFORM_COLOR
Definition: GPU_shader.h:200
void GPU_point_size(float size)
Definition: gpu_state.cc:179
@ GPU_DEPTH_LESS_EQUAL
Definition: GPU_state.h:81
@ GPU_DEPTH_NONE
Definition: GPU_state.h:78
void GPU_depth_test(eGPUDepthTest test)
Definition: gpu_state.cc:75
@ 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_GIZMO_PRIMARY
Definition: UI_resources.h:321
@ BM_VERT
Definition: bmesh_class.h:383
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:124
#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.c:2152
bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2)
Definition: bmesh_query.c:1335
bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
Definition: bmesh_query.c:555
bool BM_edge_is_any_face_len_test(const BMEdge *e, const int len)
Definition: bmesh_query.c:2514
bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2)
Definition: bmesh_query.c:1314
BMLoop * BM_loop_other_edge_loop(BMLoop *l, BMVert *v)
Definition: bmesh_query.c:69
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:70
void BMW_end(BMWalker *walker)
End Walker.
void * BMW_begin(BMWalker *walker, void *start)
Definition: bmesh_walkers.c:55
void * BMW_step(BMWalker *walker)
Step Walker.
#define BMW_NIL_LAY
@ BMW_FLAG_TEST_HIDDEN
Definition: bmesh_walkers.h:34
#define BMW_MASK_NOP
Definition: bmesh_walkers.h:68
@ BMW_EDGERING
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:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
BMVert * v1
Definition: bmesh_class.h:134
BMVert * v2
Definition: bmesh_class.h:134
struct BMLoop * l
Definition: bmesh_class.h:140
struct BMVert * v
Definition: bmesh_class.h:165
struct BMLoop * prev
Definition: bmesh_class.h:245
struct BMFace * f
Definition: bmesh_class.h:183
struct BMLoop * next
Definition: bmesh_class.h:245