Blender  V3.3
extract_mesh_ibo_lines_paint_mask.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2021 Blender Foundation. All rights reserved. */
3 
8 #include "BLI_bitmap.h"
9 #include "BLI_vector.hh"
10 #include "atomic_ops.h"
11 
12 #include "MEM_guardedalloc.h"
13 
14 #include "draw_subdivision.h"
15 #include "extract_mesh.hh"
16 
17 namespace blender::draw {
18 /* ---------------------------------------------------------------------- */
26 };
27 
29  MeshBatchCache *UNUSED(cache),
30  void *UNUSED(ibo),
31  void *tls_data)
32 {
34  data->select_map = BLI_BITMAP_NEW(mr->edge_len, __func__);
36 }
37 
39  const MPoly *mp,
40  const int UNUSED(mp_index),
41  void *_data)
42 {
44  const MLoop *mloop = mr->mloop;
45  const int ml_index_end = mp->loopstart + mp->totloop;
46  for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
47  const MLoop *ml = &mloop[ml_index];
48 
49  const int e_index = ml->e;
50  const MEdge *me = &mr->medge[e_index];
51  if (!((mr->use_hide && (me->flag & ME_HIDE)) ||
52  ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
53  (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) {
54 
55  const int ml_index_last = mp->totloop + mp->loopstart - 1;
56  const int ml_index_other = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1);
57  if (mp->flag & ME_FACE_SEL) {
58  if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, e_index)) {
59  /* Hide edge as it has more than 2 selected loop. */
60  GPU_indexbuf_set_line_restart(&data->elb, e_index);
61  }
62  else {
63  /* First selected loop. Set edge visible, overwriting any unselected loop. */
64  GPU_indexbuf_set_line_verts(&data->elb, e_index, ml_index, ml_index_other);
65  }
66  }
67  else {
68  /* Set these unselected loop only if this edge has no other selected loop. */
69  if (!BLI_BITMAP_TEST(data->select_map, e_index)) {
70  GPU_indexbuf_set_line_verts(&data->elb, e_index, ml_index, ml_index_other);
71  }
72  }
73  }
74  else {
75  GPU_indexbuf_set_line_restart(&data->elb, e_index);
76  }
77  }
78 }
79 
81  MeshBatchCache *UNUSED(cache),
82  void *buf,
83  void *_data)
84 {
86  GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf);
88  MEM_freeN(data->select_map);
89 }
90 
91 static void extract_lines_paint_mask_init_subdiv(const DRWSubdivCache *subdiv_cache,
92  const MeshRenderData *mr,
93  MeshBatchCache *UNUSED(cache),
94  void *UNUSED(buf),
95  void *tls_data)
96 {
98  data->select_map = BLI_BITMAP_NEW(mr->edge_len, __func__);
99  GPU_indexbuf_init(&data->elb,
101  subdiv_cache->num_subdiv_edges,
102  subdiv_cache->num_subdiv_loops * 2);
103 }
104 
106  const MeshRenderData *mr,
107  void *_data,
108  uint subdiv_quad_index,
109  const MPoly *coarse_quad)
110 {
112  int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache->edges_orig_index);
113  int *subdiv_loop_subdiv_edge_index = subdiv_cache->subdiv_loop_subdiv_edge_index;
114 
115  uint start_loop_idx = subdiv_quad_index * 4;
116  uint end_loop_idx = (subdiv_quad_index + 1) * 4;
117  for (uint loop_idx = start_loop_idx; loop_idx < end_loop_idx; loop_idx++) {
118  const uint coarse_edge_index = (uint)subdiv_loop_edge_index[loop_idx];
119  const uint subdiv_edge_index = (uint)subdiv_loop_subdiv_edge_index[loop_idx];
120 
121  if (coarse_edge_index == -1u) {
122  GPU_indexbuf_set_line_restart(&data->elb, subdiv_edge_index);
123  }
124  else {
125  const MEdge *me = &mr->medge[coarse_edge_index];
126  if (!((mr->use_hide && (me->flag & ME_HIDE)) ||
127  ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
128  (mr->e_origindex[coarse_edge_index] == ORIGINDEX_NONE)))) {
129  const uint ml_index_other = (loop_idx == (end_loop_idx - 1)) ? start_loop_idx :
130  loop_idx + 1;
131  if (coarse_quad->flag & ME_FACE_SEL) {
132  if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, coarse_edge_index)) {
133  /* Hide edge as it has more than 2 selected loop. */
134  GPU_indexbuf_set_line_restart(&data->elb, subdiv_edge_index);
135  }
136  else {
137  /* First selected loop. Set edge visible, overwriting any unselected loop. */
138  GPU_indexbuf_set_line_verts(&data->elb, subdiv_edge_index, loop_idx, ml_index_other);
139  }
140  }
141  else {
142  /* Set these unselected loop only if this edge has no other selected loop. */
143  if (!BLI_BITMAP_TEST(data->select_map, coarse_edge_index)) {
144  GPU_indexbuf_set_line_verts(&data->elb, subdiv_edge_index, loop_idx, ml_index_other);
145  }
146  }
147  }
148  else {
149  GPU_indexbuf_set_line_restart(&data->elb, subdiv_edge_index);
150  }
151  }
152  }
153 }
154 
156  const struct DRWSubdivCache *UNUSED(subdiv_cache),
157  const MeshRenderData *mr,
158  MeshBatchCache *cache,
159  void *buf,
160  void *_data)
161 {
162  extract_lines_paint_mask_finish(mr, cache, buf, _data);
163 }
164 
166 {
167  MeshExtract extractor = {nullptr};
174  extractor.data_type = MR_DATA_NONE;
175  extractor.data_size = sizeof(MeshExtract_LinePaintMask_Data);
176  extractor.use_threading = false;
177  extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.lines_paint_mask);
178  return extractor;
179 }
180 
183 } // namespace blender::draw
184 
#define ORIGINDEX_NONE
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition: BLI_bitmap.h:40
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:64
#define BLI_BITMAP_TEST_AND_SET_ATOMIC(_bitmap, _index)
Definition: BLI_bitmap.h:68
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:16
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
@ ME_HIDE
@ ME_FACE_SEL
struct GPUIndexBuf GPUIndexBuf
void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint vertex_len)
void GPU_indexbuf_set_line_verts(GPUIndexBufBuilder *builder, uint elem, uint v1, uint v2)
void GPU_indexbuf_set_line_restart(GPUIndexBufBuilder *builder, uint elem)
void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *, GPUIndexBuf *)
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:20
void * GPU_vertbuf_get_data(const GPUVertBuf *verts)
Read Guarded memory(de)allocation.
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
@ MR_DATA_NONE
Extraction of Mesh data into VBO to feed to GPU.
@ MR_EXTRACT_MAPPED
Definition: extract_mesh.hh:32
const MeshExtract extract_lines_paint_mask
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
static void extract_lines_paint_mask_finish_subdiv(const struct DRWSubdivCache *UNUSED(subdiv_cache), const MeshRenderData *mr, MeshBatchCache *cache, void *buf, void *_data)
static void extract_lines_paint_mask_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, MeshBatchCache *UNUSED(cache), void *UNUSED(buf), void *tls_data)
static void extract_lines_paint_mask_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, void *_data, uint subdiv_quad_index, const MPoly *coarse_quad)
constexpr MeshExtract create_extractor_lines_paint_mask()
static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr), MeshBatchCache *UNUSED(cache), void *buf, void *_data)
static void extract_lines_paint_mask_init(const MeshRenderData *mr, MeshBatchCache *UNUSED(cache), void *UNUSED(ibo), void *tls_data)
static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr, const MPoly *mp, const int UNUSED(mp_index), void *_data)
struct GPUVertBuf * edges_orig_index
int * subdiv_loop_subdiv_edge_index
unsigned int e
GPUIndexBuf * lines_paint_mask
size_t mesh_buffer_offset
eMRDataType data_type
ExtractFinishFn * finish
ExtractIterSubdivMeshFn * iter_subdiv_mesh
ExtractInitSubdivFn * init_subdiv
size_t data_size
ExtractFinishSubdivFn * finish_subdiv
ExtractPolyMeshFn * iter_poly_mesh
bool use_threading
ExtractInitFn * init
eMRExtractType extract_type
Definition: extract_mesh.hh:37
const MLoop * mloop
Definition: extract_mesh.hh:76
const MEdge * medge
Definition: extract_mesh.hh:75
const int * e_origindex
Definition: extract_mesh.hh:66