Blender V4.3
editmesh_preselect_elem.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 "BLI_math_matrix.h"
12
13#include "BKE_editmesh.hh"
14
15#include "GPU_immediate.hh"
16#include "GPU_matrix.hh"
17#include "GPU_state.hh"
18
19#include "DNA_object_types.h"
20
21#include "ED_mesh.hh"
22#include "ED_view3d.hh"
23
24using blender::float3;
25using blender::Span;
26
27/* -------------------------------------------------------------------- */
39static void vcos_get(BMVert *v, float r_co[3], const Span<float3> vert_positions)
40{
41 if (!vert_positions.is_empty()) {
42 copy_v3_v3(r_co, vert_positions[BM_elem_index_get(v)]);
43 }
44 else {
45 copy_v3_v3(r_co, v->co);
46 }
47}
48
49static void vcos_get_pair(BMVert *v[2], float r_cos[2][3], const Span<float3> vert_positions)
50{
51 if (!vert_positions.is_empty()) {
52 for (int j = 0; j < 2; j++) {
53 copy_v3_v3(r_cos[j], vert_positions[BM_elem_index_get(v[j])]);
54 }
55 }
56 else {
57 for (int j = 0; j < 2; j++) {
58 copy_v3_v3(r_cos[j], v[j]->co);
59 }
60 }
61}
62
77
82
87
89{
90 EditMesh_PreSelElem *psel = static_cast<EditMesh_PreSelElem *>(
91 MEM_callocN(sizeof(*psel), __func__));
93 return psel;
94}
95
102
111
113{
114 MEM_SAFE_FREE(psel->edges);
115 psel->edges_len = 0;
116
117 MEM_SAFE_FREE(psel->verts);
118 psel->verts_len = 0;
119}
120
121void EDBM_preselect_elem_draw(EditMesh_PreSelElem *psel, const float matrix[4][4])
122{
123 if ((psel->edges_len == 0) && (psel->verts_len == 0)) {
124 return;
125 }
126
128
130 GPU_matrix_mul(matrix);
131
133
135
136 immUniformColor4ub(141, 171, 186, 100);
138 if (psel->preview_tris_len > 0) {
140
141 for (int i = 0; i < psel->preview_tris_len; i++) {
142 immVertex3fv(pos, psel->preview_tris[i][0]);
143 immVertex3fv(pos, psel->preview_tris[i][1]);
144 immVertex3fv(pos, psel->preview_tris[i][2]);
145 }
146 immEnd();
147 }
148
149 if (psel->preview_lines_len > 0) {
150
151 immUniformColor4ub(3, 161, 252, 200);
152 GPU_line_width(2.0f);
154 for (int i = 0; i < psel->preview_lines_len; i++) {
155 immVertex3fv(pos, psel->preview_lines[i][0]);
156 immVertex3fv(pos, psel->preview_lines[i][1]);
157 }
158 immEnd();
159 }
160 }
161
163 immUniformColor4ub(252, 49, 10, 200);
164 }
165 else {
166 immUniformColor4ub(3, 161, 252, 200);
167 }
168
169 if (psel->edges_len > 0) {
170 GPU_line_width(3.0f);
172
173 for (int i = 0; i < psel->edges_len; i++) {
174 immVertex3fv(pos, psel->edges[i][0]);
175 immVertex3fv(pos, psel->edges[i][1]);
176 }
177
178 immEnd();
179 }
180
181 if (psel->verts_len > 0) {
182 GPU_point_size(4.0f);
183
185
186 for (int i = 0; i < psel->verts_len; i++) {
187 immVertex3fv(pos, psel->verts[i]);
188 }
189
190 immEnd();
191 }
192
194
196
197 /* Reset default */
199}
200
202 BMesh * /*bm*/,
203 BMVert *eve,
204 const Span<float3> vert_positions)
205{
206 float(*verts)[3] = static_cast<float(*)[3]>(MEM_mallocN(sizeof(*psel->verts), __func__));
207 vcos_get(eve, verts[0], vert_positions);
208 psel->verts = verts;
209 psel->verts_len = 1;
210}
211
213 BMesh * /*bm*/,
214 BMEdge *eed,
215 const Span<float3> vert_positions)
216{
217 float(*edges)[2][3] = static_cast<float(*)[2][3]>(MEM_mallocN(sizeof(*psel->edges), __func__));
218 vcos_get_pair(&eed->v1, edges[0], vert_positions);
219 psel->edges = edges;
220 psel->edges_len = 1;
221}
222
224 EditMesh_PreSelElem *psel, ViewContext *vc, BMesh * /*bm*/, BMVert *eed, const int mval[2])
225{
226 BMVert *v_act = eed;
227 BMEdge *e_pair[2] = {nullptr};
228 float center[3];
229
230 if (v_act->e != nullptr) {
231 for (uint allow_wire = 0; allow_wire < 2 && (e_pair[1] == nullptr); allow_wire++) {
232 int i = 0;
233 BMEdge *e_iter = v_act->e;
234 do {
235 if ((BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) &&
236 (allow_wire ? BM_edge_is_wire(e_iter) : BM_edge_is_boundary(e_iter)))
237 {
238 if (i == 2) {
239 e_pair[0] = e_pair[1] = nullptr;
240 break;
241 }
242 e_pair[i++] = e_iter;
243 }
244 } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_act)) != v_act->e);
245 }
246 }
247
248 if (e_pair[1] != nullptr) {
249 mul_v3_m4v3(center, vc->obedit->object_to_world().ptr(), v_act->co);
250 ED_view3d_win_to_3d_int(vc->v3d, vc->region, center, mval, center);
251 mul_m4_v3(vc->obedit->world_to_object().ptr(), center);
252
253 psel->preview_tris = static_cast<float(*)[3][3]>(
254 MEM_mallocN(sizeof(*psel->preview_tris) * 2, __func__));
255 psel->preview_lines = static_cast<float(*)[2][3]>(
256 MEM_mallocN(sizeof(*psel->preview_lines) * 4, __func__));
257
258 copy_v3_v3(psel->preview_tris[0][0], e_pair[0]->v1->co);
259 copy_v3_v3(psel->preview_tris[0][1], e_pair[0]->v2->co);
260 copy_v3_v3(psel->preview_tris[0][2], center);
261
262 copy_v3_v3(psel->preview_tris[1][0], e_pair[1]->v1->co);
263 copy_v3_v3(psel->preview_tris[1][1], e_pair[1]->v2->co);
264 copy_v3_v3(psel->preview_tris[1][2], center);
265
266 copy_v3_v3(psel->preview_lines[0][0], e_pair[0]->v1->co);
267 copy_v3_v3(psel->preview_lines[0][1], e_pair[0]->v2->co);
268
269 copy_v3_v3(psel->preview_lines[1][0], e_pair[1]->v1->co);
270 copy_v3_v3(psel->preview_lines[1][1], e_pair[1]->v2->co);
271
272 copy_v3_v3(psel->preview_lines[2][0], center);
273 if (e_pair[0]->v1 == v_act) {
274 copy_v3_v3(psel->preview_lines[2][1], e_pair[0]->v2->co);
275 }
276 else {
277 copy_v3_v3(psel->preview_lines[2][1], e_pair[0]->v1->co);
278 }
279
280 copy_v3_v3(psel->preview_lines[3][0], center);
281 if (e_pair[1]->v1 == v_act) {
282 copy_v3_v3(psel->preview_lines[3][1], e_pair[1]->v2->co);
283 }
284 else {
285 copy_v3_v3(psel->preview_lines[3][1], e_pair[1]->v1->co);
286 }
287 psel->preview_tris_len = 2;
288 psel->preview_lines_len = 4;
289 }
290}
291
293 ViewContext * /*vc*/,
294 BMesh * /*bm*/,
295 BMFace *efa,
296 const int /*mval*/[2])
297{
298 float(*preview_lines)[2][3] = static_cast<float(*)[2][3]>(
299 MEM_mallocN(sizeof(*psel->edges) * efa->len, __func__));
300 BMLoop *l_iter, *l_first;
301 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
302 int i = 0;
303 do {
304 vcos_get_pair(&l_iter->e->v1, preview_lines[i++], {});
305 } while ((l_iter = l_iter->next) != l_first);
306 psel->preview_lines = preview_lines;
307 psel->preview_lines_len = efa->len;
308}
309
311 EditMesh_PreSelElem *psel, ViewContext *vc, BMesh * /*bm*/, BMEdge *eed, const int mval[2])
312{
313 float center[3];
314 psel->preview_tris = static_cast<float(*)[3][3]>(
315 MEM_mallocN(sizeof(*psel->preview_tris), __func__));
316 psel->preview_lines = static_cast<float(*)[2][3]>(
317 MEM_mallocN(sizeof(*psel->preview_lines) * 3, __func__));
318 mid_v3_v3v3(center, eed->v1->co, eed->v2->co);
319 mul_m4_v3(vc->obedit->object_to_world().ptr(), center);
320 ED_view3d_win_to_3d_int(vc->v3d, vc->region, center, mval, center);
321 mul_m4_v3(vc->obedit->world_to_object().ptr(), center);
322
323 copy_v3_v3(psel->preview_tris[0][0], eed->v1->co);
324 copy_v3_v3(psel->preview_tris[0][1], eed->v2->co);
325 copy_v3_v3(psel->preview_tris[0][2], center);
326
327 copy_v3_v3(psel->preview_lines[0][0], eed->v1->co);
328 copy_v3_v3(psel->preview_lines[0][1], eed->v2->co);
329
330 copy_v3_v3(psel->preview_lines[1][0], eed->v2->co);
331 copy_v3_v3(psel->preview_lines[1][1], center);
332
333 copy_v3_v3(psel->preview_lines[2][0], center);
334 copy_v3_v3(psel->preview_lines[2][1], eed->v1->co);
335 psel->preview_tris_len = 1;
336 psel->preview_lines_len = 3;
337}
338
340 BMesh * /*bm*/,
341 BMFace *efa,
342 const Span<float3> vert_positions)
343{
344 float(*edges)[2][3] = static_cast<float(*)[2][3]>(
345 MEM_mallocN(sizeof(*psel->edges) * efa->len, __func__));
346 BMLoop *l_iter, *l_first;
347 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
348 int i = 0;
349 do {
350 vcos_get_pair(&l_iter->e->v1, edges[i++], vert_positions);
351 } while ((l_iter = l_iter->next) != l_first);
352 psel->edges = edges;
353 psel->edges_len = efa->len;
354}
355
357 BMesh *bm,
358 BMElem *ele,
359 const Span<float3> vert_positions)
360{
362
363 if (!vert_positions.is_empty()) {
365 }
366
367 switch (ele->head.htype) {
368 case BM_VERT:
369 view3d_preselect_mesh_elem_update_from_vert(psel, bm, (BMVert *)ele, vert_positions);
370 break;
371 case BM_EDGE:
372 view3d_preselect_mesh_elem_update_from_edge(psel, bm, (BMEdge *)ele, vert_positions);
373 break;
374 case BM_FACE:
375 view3d_preselect_mesh_elem_update_from_face(psel, bm, (BMFace *)ele, vert_positions);
376 break;
377 default:
378 BLI_assert(0);
379 }
380}
381
383 EditMesh_PreSelElem *psel, ViewContext *vc, BMesh *bm, BMElem *ele, const int mval[2])
384{
386
387 switch (ele->head.htype) {
388 case BM_VERT:
391 }
392 break;
393 case BM_EDGE:
395 break;
396 case BM_FACE:
398 break;
399 default:
400 BLI_assert(0);
401 }
402}
403
#define BLI_assert(a)
Definition BLI_assert.h:50
void mul_m4_v3(const float M[4][4], float r[3])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
unsigned int uint
Object is a sort of wrapper for general info.
eEditMesh_PreSelPreviewAction
Definition ED_mesh.hh:345
@ PRESELECT_ACTION_CREATE
Definition ED_mesh.hh:347
@ PRESELECT_ACTION_DELETE
Definition ED_mesh.hh:348
@ PRESELECT_ACTION_TRANSFORM
Definition ED_mesh.hh:346
void ED_view3d_win_to_3d_int(const View3D *v3d, const ARegion *region, const float depth_pt[3], const int mval[2], float r_out[3])
void immEnd()
void immUnbindProgram()
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immUniformColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
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_PRIM_TRIS
@ GPU_SHADER_3D_UNIFORM_COLOR
void GPU_line_width(float width)
Definition gpu_state.cc:161
void GPU_point_size(float size)
Definition gpu_state.cc:167
@ 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
@ 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)
#define BM_DISK_EDGE_NEXT(e, v)
@ BM_ELEM_HIDDEN
#define BM_FACE_FIRST_LOOP(p)
#define BM_elem_index_get(ele)
#define BM_elem_flag_test(ele, hflag)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
#define BM_FACE
#define BM_EDGE
#define BM_VERT
BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert * v
constexpr bool is_empty() const
Definition BLI_span.hh:261
static void view3d_preselect_update_preview_triangle_from_edge(EditMesh_PreSelElem *psel, ViewContext *vc, BMesh *, BMEdge *eed, const int mval[2])
void EDBM_preselect_elem_clear(EditMesh_PreSelElem *psel)
eEditMesh_PreSelPreviewAction EDBM_preselect_action_get(EditMesh_PreSelElem *psel)
void EDBM_preselect_elem_draw(EditMesh_PreSelElem *psel, const float matrix[4][4])
void EDBM_preselect_elem_update_from_single(EditMesh_PreSelElem *psel, BMesh *bm, BMElem *ele, const Span< float3 > vert_positions)
static void view3d_preselect_mesh_elem_update_from_face(EditMesh_PreSelElem *psel, BMesh *, BMFace *efa, const Span< float3 > vert_positions)
void EDBM_preselect_elem_destroy(EditMesh_PreSelElem *psel)
EditMesh_PreSelElem * EDBM_preselect_elem_create()
void EDBM_preselect_elem_update_preview(EditMesh_PreSelElem *psel, ViewContext *vc, BMesh *bm, BMElem *ele, const int mval[2])
static void view3d_preselect_mesh_elem_update_from_vert(EditMesh_PreSelElem *psel, BMesh *, BMVert *eve, const Span< float3 > vert_positions)
static void view3d_preselect_update_preview_triangle_from_vert(EditMesh_PreSelElem *psel, ViewContext *vc, BMesh *, BMVert *eed, const int mval[2])
static void view3d_preselect_mesh_elem_update_from_edge(EditMesh_PreSelElem *psel, BMesh *, BMEdge *eed, const Span< float3 > vert_positions)
static void vcos_get_pair(BMVert *v[2], float r_cos[2][3], const Span< float3 > vert_positions)
static void vcos_get(BMVert *v, float r_co[3], const Span< float3 > vert_positions)
void EDBM_preselect_action_set(EditMesh_PreSelElem *psel, eEditMesh_PreSelPreviewAction action)
static void view3d_preselect_update_preview_triangle_from_face(EditMesh_PreSelElem *psel, ViewContext *, BMesh *, BMFace *efa, const int[2])
void EDBM_preselect_preview_clear(EditMesh_PreSelElem *psel)
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
BMHeader head
struct BMEdge * e
struct BMLoop * next
float co[3]
struct BMEdge * e
eEditMesh_PreSelPreviewAction preview_action
ARegion * region
Definition ED_view3d.hh:73
View3D * v3d
Definition ED_view3d.hh:74
Object * obedit
Definition ED_view3d.hh:72