Blender V4.5
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
8
9#include "MEM_guardedalloc.h"
10
11#include "BLI_math_matrix.h"
12#include "BLI_math_vector.h"
13
14#include "GPU_immediate.hh"
15#include "GPU_matrix.hh"
16#include "GPU_state.hh"
17
18#include "DNA_object_types.h"
19
20#include "ED_mesh.hh"
21#include "ED_view3d.hh"
22
23#include "bmesh.hh"
24
25using blender::float3;
26using blender::Span;
27
28/* -------------------------------------------------------------------- */
39
40static void vcos_get(BMVert *v, float r_co[3], const Span<float3> vert_positions)
41{
42 if (!vert_positions.is_empty()) {
43 copy_v3_v3(r_co, vert_positions[BM_elem_index_get(v)]);
44 }
45 else {
46 copy_v3_v3(r_co, v->co);
47 }
48}
49
50static void vcos_get_pair(BMVert *v[2], float r_cos[2][3], const Span<float3> vert_positions)
51{
52 if (!vert_positions.is_empty()) {
53 for (int j = 0; j < 2; j++) {
54 copy_v3_v3(r_cos[j], vert_positions[BM_elem_index_get(v[j])]);
55 }
56 }
57 else {
58 for (int j = 0; j < 2; j++) {
59 copy_v3_v3(r_cos[j], v[j]->co);
60 }
61 }
62}
63
78
83
88
90{
91 EditMesh_PreSelElem *psel = static_cast<EditMesh_PreSelElem *>(
92 MEM_callocN(sizeof(*psel), __func__));
94 return psel;
95}
96
103
112
114{
115 MEM_SAFE_FREE(psel->edges);
116 psel->edges_len = 0;
117
118 MEM_SAFE_FREE(psel->verts);
119 psel->verts_len = 0;
120}
121
123static void edbm_preselect_imm_color(PreselectColor preselect_color)
124{
125 switch (preselect_color) {
127 immUniformColor4ub(141, 171, 186, 100);
128 break;
130 immUniformColor4ub(3, 161, 252, 200);
131 break;
133 immUniformColor4ub(252, 49, 10, 200);
134 break;
135 }
136}
137
138void EDBM_preselect_elem_draw(EditMesh_PreSelElem *psel, const float matrix[4][4])
139{
140 if ((psel->edges_len == 0) && (psel->verts_len == 0)) {
141 return;
142 }
143
145
147 GPU_matrix_mul(matrix);
148
150
152
155 if (psel->preview_tris_len > 0) {
157
158 for (int i = 0; i < psel->preview_tris_len; i++) {
159 immVertex3fv(pos, psel->preview_tris[i][0]);
160 immVertex3fv(pos, psel->preview_tris[i][1]);
161 immVertex3fv(pos, psel->preview_tris[i][2]);
162 }
163 immEnd();
164 }
165
166 if (psel->preview_lines_len > 0) {
168 GPU_line_width(2.0f);
170 for (int i = 0; i < psel->preview_lines_len; i++) {
171 immVertex3fv(pos, psel->preview_lines[i][0]);
172 immVertex3fv(pos, psel->preview_lines[i][1]);
173 }
174 immEnd();
175 }
176 }
177
181
182 if (psel->edges_len > 0) {
183 GPU_line_width(3.0f);
185
186 for (int i = 0; i < psel->edges_len; i++) {
187 immVertex3fv(pos, psel->edges[i][0]);
188 immVertex3fv(pos, psel->edges[i][1]);
189 }
190
191 immEnd();
192 }
193
194 if (psel->verts_len > 0) {
200 GPU_point_size(4.0f);
201
203
204 for (int i = 0; i < psel->verts_len; i++) {
205 immVertex3fv(pos, psel->verts[i]);
206 }
207
208 immEnd();
209 }
210
212
214
215 /* Reset default */
217}
218
220 BMesh * /*bm*/,
221 BMVert *eve,
222 const Span<float3> vert_positions)
223{
224 float(*verts)[3] = static_cast<float(*)[3]>(MEM_mallocN(sizeof(*psel->verts), __func__));
225 vcos_get(eve, verts[0], vert_positions);
226 psel->verts = verts;
227 psel->verts_len = 1;
228}
229
231 BMesh * /*bm*/,
232 BMEdge *eed,
233 const Span<float3> vert_positions)
234{
235 float(*edges)[2][3] = static_cast<float(*)[2][3]>(MEM_mallocN(sizeof(*psel->edges), __func__));
236 vcos_get_pair(&eed->v1, edges[0], vert_positions);
237 psel->edges = edges;
238 psel->edges_len = 1;
239}
240
242 EditMesh_PreSelElem *psel, ViewContext *vc, BMesh * /*bm*/, BMVert *eed, const int mval[2])
243{
244 BMVert *v_act = eed;
245 BMEdge *e_pair[2] = {nullptr};
246 float center[3];
247
248 if (v_act->e != nullptr) {
249 for (uint allow_wire = 0; allow_wire < 2 && (e_pair[1] == nullptr); allow_wire++) {
250 int i = 0;
251 BMEdge *e_iter = v_act->e;
252 do {
253 if ((BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) &&
254 (allow_wire ? BM_edge_is_wire(e_iter) : BM_edge_is_boundary(e_iter)))
255 {
256 if (i == 2) {
257 e_pair[0] = e_pair[1] = nullptr;
258 break;
259 }
260 e_pair[i++] = e_iter;
261 }
262 } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_act)) != v_act->e);
263 }
264 }
265
266 if (e_pair[1] != nullptr) {
267 mul_v3_m4v3(center, vc->obedit->object_to_world().ptr(), v_act->co);
268 ED_view3d_win_to_3d_int(vc->v3d, vc->region, center, mval, center);
269 mul_m4_v3(vc->obedit->world_to_object().ptr(), center);
270
271 psel->preview_tris = static_cast<float(*)[3][3]>(
272 MEM_mallocN(sizeof(*psel->preview_tris) * 2, __func__));
273 psel->preview_lines = static_cast<float(*)[2][3]>(
274 MEM_mallocN(sizeof(*psel->preview_lines) * 4, __func__));
275
276 copy_v3_v3(psel->preview_tris[0][0], e_pair[0]->v1->co);
277 copy_v3_v3(psel->preview_tris[0][1], e_pair[0]->v2->co);
278 copy_v3_v3(psel->preview_tris[0][2], center);
279
280 copy_v3_v3(psel->preview_tris[1][0], e_pair[1]->v1->co);
281 copy_v3_v3(psel->preview_tris[1][1], e_pair[1]->v2->co);
282 copy_v3_v3(psel->preview_tris[1][2], center);
283
284 copy_v3_v3(psel->preview_lines[0][0], e_pair[0]->v1->co);
285 copy_v3_v3(psel->preview_lines[0][1], e_pair[0]->v2->co);
286
287 copy_v3_v3(psel->preview_lines[1][0], e_pair[1]->v1->co);
288 copy_v3_v3(psel->preview_lines[1][1], e_pair[1]->v2->co);
289
290 copy_v3_v3(psel->preview_lines[2][0], center);
291 if (e_pair[0]->v1 == v_act) {
292 copy_v3_v3(psel->preview_lines[2][1], e_pair[0]->v2->co);
293 }
294 else {
295 copy_v3_v3(psel->preview_lines[2][1], e_pair[0]->v1->co);
296 }
297
298 copy_v3_v3(psel->preview_lines[3][0], center);
299 if (e_pair[1]->v1 == v_act) {
300 copy_v3_v3(psel->preview_lines[3][1], e_pair[1]->v2->co);
301 }
302 else {
303 copy_v3_v3(psel->preview_lines[3][1], e_pair[1]->v1->co);
304 }
305 psel->preview_tris_len = 2;
306 psel->preview_lines_len = 4;
307 }
308}
309
311 ViewContext * /*vc*/,
312 BMesh * /*bm*/,
313 BMFace *efa,
314 const int /*mval*/[2])
315{
316 float(*preview_lines)[2][3] = static_cast<float(*)[2][3]>(
317 MEM_mallocN(sizeof(*psel->edges) * efa->len, __func__));
318 BMLoop *l_iter, *l_first;
319 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
320 int i = 0;
321 do {
322 vcos_get_pair(&l_iter->e->v1, preview_lines[i++], {});
323 } while ((l_iter = l_iter->next) != l_first);
324 psel->preview_lines = preview_lines;
325 psel->preview_lines_len = efa->len;
326}
327
329 EditMesh_PreSelElem *psel, ViewContext *vc, BMesh * /*bm*/, BMEdge *eed, const int mval[2])
330{
331 float center[3];
332 psel->preview_tris = static_cast<float(*)[3][3]>(
333 MEM_mallocN(sizeof(*psel->preview_tris), __func__));
334 psel->preview_lines = static_cast<float(*)[2][3]>(
335 MEM_mallocN(sizeof(*psel->preview_lines) * 3, __func__));
336 mid_v3_v3v3(center, eed->v1->co, eed->v2->co);
337 mul_m4_v3(vc->obedit->object_to_world().ptr(), center);
338 ED_view3d_win_to_3d_int(vc->v3d, vc->region, center, mval, center);
339 mul_m4_v3(vc->obedit->world_to_object().ptr(), center);
340
341 copy_v3_v3(psel->preview_tris[0][0], eed->v1->co);
342 copy_v3_v3(psel->preview_tris[0][1], eed->v2->co);
343 copy_v3_v3(psel->preview_tris[0][2], center);
344
345 copy_v3_v3(psel->preview_lines[0][0], eed->v1->co);
346 copy_v3_v3(psel->preview_lines[0][1], eed->v2->co);
347
348 copy_v3_v3(psel->preview_lines[1][0], eed->v2->co);
349 copy_v3_v3(psel->preview_lines[1][1], center);
350
351 copy_v3_v3(psel->preview_lines[2][0], center);
352 copy_v3_v3(psel->preview_lines[2][1], eed->v1->co);
353 psel->preview_tris_len = 1;
354 psel->preview_lines_len = 3;
355}
356
358 BMesh * /*bm*/,
359 BMFace *efa,
360 const Span<float3> vert_positions)
361{
362 float(*edges)[2][3] = static_cast<float(*)[2][3]>(
363 MEM_mallocN(sizeof(*psel->edges) * efa->len, __func__));
364 BMLoop *l_iter, *l_first;
365 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
366 int i = 0;
367 do {
368 vcos_get_pair(&l_iter->e->v1, edges[i++], vert_positions);
369 } while ((l_iter = l_iter->next) != l_first);
370 psel->edges = edges;
371 psel->edges_len = efa->len;
372}
373
375 BMesh *bm,
376 BMElem *ele,
377 const Span<float3> vert_positions)
378{
380
381 if (!vert_positions.is_empty()) {
383 }
384
385 switch (ele->head.htype) {
386 case BM_VERT:
387 view3d_preselect_mesh_elem_update_from_vert(psel, bm, (BMVert *)ele, vert_positions);
388 break;
389 case BM_EDGE:
390 view3d_preselect_mesh_elem_update_from_edge(psel, bm, (BMEdge *)ele, vert_positions);
391 break;
392 case BM_FACE:
393 view3d_preselect_mesh_elem_update_from_face(psel, bm, (BMFace *)ele, vert_positions);
394 break;
395 default:
396 BLI_assert(0);
397 }
398}
399
401 EditMesh_PreSelElem *psel, ViewContext *vc, BMesh *bm, BMElem *ele, const int mval[2])
402{
404
405 switch (ele->head.htype) {
406 case BM_VERT:
409 }
410 break;
411 case BM_EDGE:
413 break;
414 case BM_FACE:
416 break;
417 default:
418 BLI_assert(0);
419 }
420}
421
#define BLI_assert(a)
Definition BLI_assert.h:46
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:358
@ PRESELECT_ACTION_CREATE
Definition ED_mesh.hh:360
@ PRESELECT_ACTION_DELETE
Definition ED_mesh.hh:361
@ PRESELECT_ACTION_TRANSFORM
Definition ED_mesh.hh:359
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
@ GPU_SHADER_3D_POINT_UNIFORM_COLOR
void GPU_line_width(float width)
Definition gpu_state.cc:166
void GPU_point_size(float size)
Definition gpu_state.cc:172
@ GPU_DEPTH_LESS_EQUAL
Definition GPU_state.hh:114
@ GPU_DEPTH_NONE
Definition GPU_state.hh:111
void GPU_depth_test(eGPUDepthTest test)
Definition gpu_state.cc:68
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, blender::StringRef name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Read Guarded memory(de)allocation.
@ BM_ELEM_HIDDEN
#define BM_DISK_EDGE_NEXT(e, v)
#define BM_FACE_FIRST_LOOP(p)
#define BM_elem_index_get(ele)
#define BM_elem_flag_test(ele, hflag)
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:260
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)
static void edbm_preselect_imm_color(PreselectColor preselect_color)
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)
static float verts[][3]
uint pos
#define MEM_SAFE_FREE(v)
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
VecBase< float, 3 > float3
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:77
View3D * v3d
Definition ED_view3d.hh:78
Object * obedit
Definition ED_view3d.hh:76
i
Definition text_draw.cc:230