Blender V5.0
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 immVertexFormat(), "pos", blender::gpu::VertAttrType::SFLOAT_32_32_32);
151
153
156 if (psel->preview_tris_len > 0) {
158
159 for (int i = 0; i < psel->preview_tris_len; i++) {
160 immVertex3fv(pos, psel->preview_tris[i][0]);
161 immVertex3fv(pos, psel->preview_tris[i][1]);
162 immVertex3fv(pos, psel->preview_tris[i][2]);
163 }
164 immEnd();
165 }
166
167 if (psel->preview_lines_len > 0) {
169 GPU_line_width(2.0f);
171 for (int i = 0; i < psel->preview_lines_len; i++) {
172 immVertex3fv(pos, psel->preview_lines[i][0]);
173 immVertex3fv(pos, psel->preview_lines[i][1]);
174 }
175 immEnd();
176 }
177 }
178
182
183 if (psel->edges_len > 0) {
184 GPU_line_width(3.0f);
186
187 for (int i = 0; i < psel->edges_len; i++) {
188 immVertex3fv(pos, psel->edges[i][0]);
189 immVertex3fv(pos, psel->edges[i][1]);
190 }
191
192 immEnd();
193 }
194
195 if (psel->verts_len > 0) {
201 GPU_point_size(4.0f);
202
204
205 for (int i = 0; i < psel->verts_len; i++) {
206 immVertex3fv(pos, psel->verts[i]);
207 }
208
209 immEnd();
210 }
211
213
215
216 /* Reset default */
218}
219
221 BMesh * /*bm*/,
222 BMVert *eve,
223 const Span<float3> vert_positions)
224{
225 float (*verts)[3] = static_cast<float (*)[3]>(MEM_mallocN(sizeof(*psel->verts), __func__));
226 vcos_get(eve, verts[0], vert_positions);
227 psel->verts = verts;
228 psel->verts_len = 1;
229}
230
232 BMesh * /*bm*/,
233 BMEdge *eed,
234 const Span<float3> vert_positions)
235{
236 float (*edges)[2][3] = static_cast<float (*)[2][3]>(MEM_mallocN(sizeof(*psel->edges), __func__));
237 vcos_get_pair(&eed->v1, edges[0], vert_positions);
238 psel->edges = edges;
239 psel->edges_len = 1;
240}
241
243 EditMesh_PreSelElem *psel, ViewContext *vc, BMesh * /*bm*/, BMVert *eed, const int mval[2])
244{
245 BMVert *v_act = eed;
246 BMEdge *e_pair[2] = {nullptr};
247 float center[3];
248
249 if (v_act->e != nullptr) {
250 for (uint allow_wire = 0; allow_wire < 2 && (e_pair[1] == nullptr); allow_wire++) {
251 int i = 0;
252 BMEdge *e_iter = v_act->e;
253 do {
254 if ((BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) &&
255 (allow_wire ? BM_edge_is_wire(e_iter) : BM_edge_is_boundary(e_iter)))
256 {
257 if (i == 2) {
258 e_pair[0] = e_pair[1] = nullptr;
259 break;
260 }
261 e_pair[i++] = e_iter;
262 }
263 } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_act)) != v_act->e);
264 }
265 }
266
267 if (e_pair[1] != nullptr) {
268 mul_v3_m4v3(center, vc->obedit->object_to_world().ptr(), v_act->co);
269 ED_view3d_win_to_3d_int(vc->v3d, vc->region, center, mval, center);
270 mul_m4_v3(vc->obedit->world_to_object().ptr(), center);
271
272 psel->preview_tris = static_cast<float (*)[3][3]>(
273 MEM_mallocN(sizeof(*psel->preview_tris) * 2, __func__));
274 psel->preview_lines = static_cast<float (*)[2][3]>(
275 MEM_mallocN(sizeof(*psel->preview_lines) * 4, __func__));
276
277 copy_v3_v3(psel->preview_tris[0][0], e_pair[0]->v1->co);
278 copy_v3_v3(psel->preview_tris[0][1], e_pair[0]->v2->co);
279 copy_v3_v3(psel->preview_tris[0][2], center);
280
281 copy_v3_v3(psel->preview_tris[1][0], e_pair[1]->v1->co);
282 copy_v3_v3(psel->preview_tris[1][1], e_pair[1]->v2->co);
283 copy_v3_v3(psel->preview_tris[1][2], center);
284
285 copy_v3_v3(psel->preview_lines[0][0], e_pair[0]->v1->co);
286 copy_v3_v3(psel->preview_lines[0][1], e_pair[0]->v2->co);
287
288 copy_v3_v3(psel->preview_lines[1][0], e_pair[1]->v1->co);
289 copy_v3_v3(psel->preview_lines[1][1], e_pair[1]->v2->co);
290
291 copy_v3_v3(psel->preview_lines[2][0], center);
292 if (e_pair[0]->v1 == v_act) {
293 copy_v3_v3(psel->preview_lines[2][1], e_pair[0]->v2->co);
294 }
295 else {
296 copy_v3_v3(psel->preview_lines[2][1], e_pair[0]->v1->co);
297 }
298
299 copy_v3_v3(psel->preview_lines[3][0], center);
300 if (e_pair[1]->v1 == v_act) {
301 copy_v3_v3(psel->preview_lines[3][1], e_pair[1]->v2->co);
302 }
303 else {
304 copy_v3_v3(psel->preview_lines[3][1], e_pair[1]->v1->co);
305 }
306 psel->preview_tris_len = 2;
307 psel->preview_lines_len = 4;
308 }
309}
310
312 ViewContext * /*vc*/,
313 BMesh * /*bm*/,
314 BMFace *efa,
315 const int /*mval*/[2])
316{
317 float (*preview_lines)[2][3] = static_cast<float (*)[2][3]>(
318 MEM_mallocN(sizeof(*psel->edges) * efa->len, __func__));
319 BMLoop *l_iter, *l_first;
320 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
321 int i = 0;
322 do {
323 vcos_get_pair(&l_iter->e->v1, preview_lines[i++], {});
324 } while ((l_iter = l_iter->next) != l_first);
325 psel->preview_lines = preview_lines;
326 psel->preview_lines_len = efa->len;
327}
328
330 EditMesh_PreSelElem *psel, ViewContext *vc, BMesh * /*bm*/, BMEdge *eed, const int mval[2])
331{
332 float center[3];
333 psel->preview_tris = static_cast<float (*)[3][3]>(
334 MEM_mallocN(sizeof(*psel->preview_tris), __func__));
335 psel->preview_lines = static_cast<float (*)[2][3]>(
336 MEM_mallocN(sizeof(*psel->preview_lines) * 3, __func__));
337 mid_v3_v3v3(center, eed->v1->co, eed->v2->co);
338 mul_m4_v3(vc->obedit->object_to_world().ptr(), center);
339 ED_view3d_win_to_3d_int(vc->v3d, vc->region, center, mval, center);
340 mul_m4_v3(vc->obedit->world_to_object().ptr(), center);
341
342 copy_v3_v3(psel->preview_tris[0][0], eed->v1->co);
343 copy_v3_v3(psel->preview_tris[0][1], eed->v2->co);
344 copy_v3_v3(psel->preview_tris[0][2], center);
345
346 copy_v3_v3(psel->preview_lines[0][0], eed->v1->co);
347 copy_v3_v3(psel->preview_lines[0][1], eed->v2->co);
348
349 copy_v3_v3(psel->preview_lines[1][0], eed->v2->co);
350 copy_v3_v3(psel->preview_lines[1][1], center);
351
352 copy_v3_v3(psel->preview_lines[2][0], center);
353 copy_v3_v3(psel->preview_lines[2][1], eed->v1->co);
354 psel->preview_tris_len = 1;
355 psel->preview_lines_len = 3;
356}
357
359 BMesh * /*bm*/,
360 BMFace *efa,
361 const Span<float3> vert_positions)
362{
363 float (*edges)[2][3] = static_cast<float (*)[2][3]>(
364 MEM_mallocN(sizeof(*psel->edges) * efa->len, __func__));
365 BMLoop *l_iter, *l_first;
366 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
367 int i = 0;
368 do {
369 vcos_get_pair(&l_iter->e->v1, edges[i++], vert_positions);
370 } while ((l_iter = l_iter->next) != l_first);
371 psel->edges = edges;
372 psel->edges_len = efa->len;
373}
374
376 BMesh *bm,
377 BMElem *ele,
378 const Span<float3> vert_positions)
379{
381
382 if (!vert_positions.is_empty()) {
384 }
385
386 switch (ele->head.htype) {
387 case BM_VERT:
388 view3d_preselect_mesh_elem_update_from_vert(psel, bm, (BMVert *)ele, vert_positions);
389 break;
390 case BM_EDGE:
391 view3d_preselect_mesh_elem_update_from_edge(psel, bm, (BMEdge *)ele, vert_positions);
392 break;
393 case BM_FACE:
394 view3d_preselect_mesh_elem_update_from_face(psel, bm, (BMFace *)ele, vert_positions);
395 break;
396 default:
397 BLI_assert(0);
398 }
399}
400
402 EditMesh_PreSelElem *psel, ViewContext *vc, BMesh *bm, BMElem *ele, const int mval[2])
403{
405
406 switch (ele->head.htype) {
407 case BM_VERT:
410 }
411 break;
412 case BM_EDGE:
414 break;
415 case BM_FACE:
417 break;
418 default:
419 BLI_assert(0);
420 }
421}
422
#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:412
@ PRESELECT_ACTION_CREATE
Definition ED_mesh.hh:414
@ PRESELECT_ACTION_DELETE
Definition ED_mesh.hh:415
@ PRESELECT_ACTION_TRANSFORM
Definition ED_mesh.hh:413
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(GPUBuiltinShader 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
@ GPU_DEPTH_LESS_EQUAL
Definition GPU_state.hh:114
@ GPU_DEPTH_NONE
Definition GPU_state.hh:111
void GPU_line_width(float width)
Definition gpu_state.cc:166
void GPU_depth_test(GPUDepthTest test)
Definition gpu_state.cc:68
void GPU_point_size(float size)
Definition gpu_state.cc:172
uint GPU_vertformat_attr_add(GPUVertFormat *format, blender::StringRef name, blender::gpu::VertAttrType type)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define BM_DISK_EDGE_NEXT(e, v)
#define BM_FACE_FIRST_LOOP(p)
@ BM_ELEM_HIDDEN
#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
nullptr float
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
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