Blender  V3.3
extract_mesh_ibo_lines.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 "MEM_guardedalloc.h"
9 
10 #include "extract_mesh.hh"
11 
12 #include "draw_subdivision.h"
13 
14 namespace blender::draw {
15 
16 /* ---------------------------------------------------------------------- */
20 static void extract_lines_init(const MeshRenderData *mr,
21  MeshBatchCache *UNUSED(cache),
22  void *UNUSED(buf),
23  void *tls_data)
24 {
25  GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(tls_data);
26  /* Put loose edges at the end. */
28  elb, GPU_PRIM_LINES, mr->edge_len + mr->edge_loose_len, mr->loop_len + mr->loop_loose_len);
29 }
30 
32  const BMFace *f,
33  const int UNUSED(f_index),
34  void *data)
35 {
36  GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
37  BMLoop *l_iter, *l_first;
38  /* Use #BMLoop.prev to match mesh order (to avoid minor differences in data extraction). */
39  l_iter = l_first = BM_FACE_FIRST_LOOP(f)->prev;
40  do {
41  if (!BM_elem_flag_test(l_iter->e, BM_ELEM_HIDDEN)) {
43  BM_elem_index_get(l_iter->e),
44  BM_elem_index_get(l_iter),
45  BM_elem_index_get(l_iter->next));
46  }
47  else {
49  }
50  } while ((l_iter = l_iter->next) != l_first);
51 }
52 
54  const MPoly *mp,
55  const int UNUSED(mp_index),
56  void *data)
57 {
58  GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
59  /* Using poly & loop iterator would complicate accessing the adjacent loop. */
60  const MLoop *mloop = mr->mloop;
61  const MEdge *medge = mr->medge;
62  if (mr->use_hide || (mr->extract_type == MR_EXTRACT_MAPPED) || (mr->e_origindex != nullptr)) {
63  const int ml_index_last = mp->loopstart + (mp->totloop - 1);
64  int ml_index = ml_index_last, ml_index_next = mp->loopstart;
65  do {
66  const MLoop *ml = &mloop[ml_index];
67  const MEdge *med = &medge[ml->e];
68  if (!((mr->use_hide && (med->flag & ME_HIDE)) ||
69  ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
70  (mr->e_origindex[ml->e] == ORIGINDEX_NONE)))) {
71  GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next);
72  }
73  else {
75  }
76  } while ((ml_index = ml_index_next++) != ml_index_last);
77  }
78  else {
79  const int ml_index_last = mp->loopstart + (mp->totloop - 1);
80  int ml_index = ml_index_last, ml_index_next = mp->loopstart;
81  do {
82  const MLoop *ml = &mloop[ml_index];
83  GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next);
84  } while ((ml_index = ml_index_next++) != ml_index_last);
85  }
86 }
87 
89  const BMEdge *eed,
90  const int ledge_index,
91  void *data)
92 {
93  GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
94  const int l_index_offset = mr->edge_len + ledge_index;
95  if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
96  const int l_index = mr->loop_len + ledge_index * 2;
97  GPU_indexbuf_set_line_verts(elb, l_index_offset, l_index, l_index + 1);
98  }
99  else {
100  GPU_indexbuf_set_line_restart(elb, l_index_offset);
101  }
102  /* Don't render the edge twice. */
104 }
105 
107  const MEdge *med,
108  const int ledge_index,
109  void *data)
110 {
111  GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
112  const int l_index_offset = mr->edge_len + ledge_index;
113  const int e_index = mr->ledges[ledge_index];
114  if (!((mr->use_hide && (med->flag & ME_HIDE)) ||
115  ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
116  (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) {
117  const int l_index = mr->loop_len + ledge_index * 2;
118  GPU_indexbuf_set_line_verts(elb, l_index_offset, l_index, l_index + 1);
119  }
120  else {
121  GPU_indexbuf_set_line_restart(elb, l_index_offset);
122  }
123  /* Don't render the edge twice. */
124  GPU_indexbuf_set_line_restart(elb, e_index);
125 }
126 
127 static void extract_lines_task_reduce(void *_userdata_to, void *_userdata_from)
128 {
129  GPUIndexBufBuilder *elb_to = static_cast<GPUIndexBufBuilder *>(_userdata_to);
130  GPUIndexBufBuilder *elb_from = static_cast<GPUIndexBufBuilder *>(_userdata_from);
131  GPU_indexbuf_join(elb_to, elb_from);
132 }
133 
135  MeshBatchCache *UNUSED(cache),
136  void *buf,
137  void *data)
138 {
139  GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
140  GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf);
141  GPU_indexbuf_build_in_place(elb, ibo);
142 }
143 
144 static void extract_lines_init_subdiv(const DRWSubdivCache *subdiv_cache,
145  const MeshRenderData *UNUSED(mr),
146  MeshBatchCache *UNUSED(cache),
147  void *buffer,
148  void *UNUSED(data))
149 {
150  const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
151  GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buffer);
153  subdiv_cache->num_subdiv_loops * 2 + loose_geom.edge_len * 2);
154 
155  if (subdiv_cache->num_subdiv_loops == 0) {
156  return;
157  }
158 
159  draw_subdiv_build_lines_buffer(subdiv_cache, ibo);
160 }
161 
162 static void extract_lines_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
163  const MeshRenderData *mr,
164  void *buffer,
165  void *UNUSED(data))
166 {
167  const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
168  if (loose_geom.edge_len == 0) {
169  return;
170  }
171 
172  /* Update flags for loose edges, points are already handled. */
173  static GPUVertFormat format;
174  if (format.attr_len == 0) {
176  }
177 
178  GPUVertBuf *flags = GPU_vertbuf_calloc();
180 
182  GPU_vertbuf_data_alloc(flags, loose_edges.size());
183 
184  uint *flags_data = static_cast<uint *>(GPU_vertbuf_get_data(flags));
185 
186  switch (mr->extract_type) {
187  case MR_EXTRACT_MESH: {
188  const MEdge *medge = mr->medge;
189  for (DRWSubdivLooseEdge edge : loose_edges) {
190  *flags_data++ = (medge[edge.coarse_edge_index].flag & ME_HIDE) != 0;
191  }
192  break;
193  }
194  case MR_EXTRACT_MAPPED: {
195  if (mr->bm) {
196  for (DRWSubdivLooseEdge edge : loose_edges) {
197  const BMEdge *bm_edge = bm_original_edge_get(mr, edge.coarse_edge_index);
198  *flags_data++ = BM_elem_flag_test_bool(bm_edge, BM_ELEM_HIDDEN) != 0;
199  }
200  }
201  else {
202  for (DRWSubdivLooseEdge edge : loose_edges) {
203  int e = edge.coarse_edge_index;
204 
205  if (mr->e_origindex && mr->e_origindex[e] != ORIGINDEX_NONE) {
206  *flags_data++ = (mr->medge[mr->e_origindex[e]].flag & ME_HIDE) != 0;
207  }
208  else {
209  *flags_data++ = false;
210  }
211  }
212  }
213 
214  break;
215  }
216  case MR_EXTRACT_BMESH: {
217  BMesh *bm = mr->bm;
218  for (DRWSubdivLooseEdge edge : loose_edges) {
219  const BMEdge *bm_edge = BM_edge_at_index(bm, edge.coarse_edge_index);
220  *flags_data++ = BM_elem_flag_test_bool(bm_edge, BM_ELEM_HIDDEN) != 0;
221  }
222  break;
223  }
224  }
225 
226  GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buffer);
228  subdiv_cache, ibo, flags, static_cast<uint>(loose_geom.edge_len));
229 
230  GPU_vertbuf_discard(flags);
231 }
232 
234 {
235  MeshExtract extractor = {nullptr};
236  extractor.init = extract_lines_init;
244  extractor.finish = extract_lines_finish;
245  extractor.data_type = MR_DATA_NONE;
246  extractor.data_size = sizeof(GPUIndexBufBuilder);
247  extractor.use_threading = true;
248  extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.lines);
249  return extractor;
250 }
251 
254 /* ---------------------------------------------------------------------- */
259 {
260  BLI_assert(cache->final.buff.ibo.lines);
261  /* Multiply by 2 because these are edges indices. */
262  const int start = mr->edge_len * 2;
263  const int len = mr->edge_loose_len * 2;
265  cache->final.buff.ibo.lines_loose, cache->final.buff.ibo.lines, start, len);
266  cache->no_loose_wire = (len == 0);
267 }
268 
270  MeshBatchCache *cache,
271  void *buf,
272  void *data)
273 {
274  GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
275  GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf);
276  GPU_indexbuf_build_in_place(elb, ibo);
278 }
279 
280 static void extract_lines_with_lines_loose_finish_subdiv(const struct DRWSubdivCache *subdiv_cache,
281  const MeshRenderData *UNUSED(mr),
282  MeshBatchCache *cache,
283  void *UNUSED(buf),
284  void *UNUSED(_data))
285 {
286  /* Multiply by 2 because these are edges indices. */
287  const int start = subdiv_cache->num_subdiv_loops * 2;
288  const int len = subdiv_cache->loose_geom.edge_len * 2;
290  cache->final.buff.ibo.lines_loose, cache->final.buff.ibo.lines, start, len);
291  cache->no_loose_wire = (len == 0);
292 }
293 
295 {
296  MeshExtract extractor = {nullptr};
297  extractor.init = extract_lines_init;
307  extractor.data_type = MR_DATA_NONE;
308  extractor.data_size = sizeof(GPUIndexBufBuilder);
309  extractor.use_threading = true;
310  extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.lines);
311  return extractor;
312 }
313 
316 /* ---------------------------------------------------------------------- */
321  MeshBatchCache *cache,
322  void *buf,
323  void *UNUSED(tls_data))
324 {
325  BLI_assert(buf == cache->final.buff.ibo.lines_loose);
326  UNUSED_VARS_NDEBUG(buf);
328 }
329 
331  const MeshRenderData *mr,
332  MeshBatchCache *cache,
333  void *buffer,
334  void *UNUSED(data))
335 {
339 }
340 
342 {
343  MeshExtract extractor = {nullptr};
346  extractor.data_type = MR_DATA_LOOSE_GEOM;
347  extractor.data_size = 0;
348  extractor.use_threading = false;
349  extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.lines_loose);
350  return extractor;
351 }
352 
355 } // namespace blender::draw
356 
#define ORIGINDEX_NONE
#define BLI_assert(a)
Definition: BLI_assert.h:46
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
@ ME_HIDE
struct GPUIndexBufBuilder GPUIndexBufBuilder
struct GPUIndexBuf GPUIndexBuf
void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint vertex_len)
void GPU_indexbuf_init_build_on_device(GPUIndexBuf *elem, uint index_len)
void GPU_indexbuf_join(GPUIndexBufBuilder *builder, const GPUIndexBufBuilder *builder_from)
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_create_subrange_in_place(GPUIndexBuf *elem, GPUIndexBuf *elem_src, uint start, uint length)
void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *, GPUIndexBuf *)
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:20
void GPU_vertbuf_discard(GPUVertBuf *)
struct GPUVertBuf GPUVertBuf
GPUVertBuf * GPU_vertbuf_calloc(void)
void GPU_vertbuf_data_alloc(GPUVertBuf *, uint v_len)
#define GPU_vertbuf_init_with_format(verts, format)
void * GPU_vertbuf_get_data(const GPUVertBuf *verts)
@ GPU_FETCH_INT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_U32
Read Guarded memory(de)allocation.
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:622
@ BM_ELEM_HIDDEN
Definition: bmesh_class.h:472
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:12
#define BM_elem_flag_test_bool(ele, hflag)
Definition: bmesh_inline.h:13
ATTR_WARN_UNUSED_RESULT BMesh * bm
BLI_INLINE BMEdge * BM_edge_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:109
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
constexpr int64_t size() const
Definition: BLI_span.hh:240
@ MR_DATA_NONE
@ MR_DATA_LOOSE_GEOM
void draw_subdiv_build_lines_buffer(const DRWSubdivCache *cache, GPUIndexBuf *lines_indices)
void draw_subdiv_build_lines_loose_buffer(const DRWSubdivCache *cache, GPUIndexBuf *lines_indices, GPUVertBuf *lines_flags, uint num_loose_edges)
blender::Span< DRWSubdivLooseEdge > draw_subdiv_cache_get_loose_edges(const DRWSubdivCache *cache)
int len
Definition: draw_manager.c:108
Extraction of Mesh data into VBO to feed to GPU.
BLI_INLINE BMEdge * bm_original_edge_get(const MeshRenderData *mr, int idx)
@ MR_EXTRACT_BMESH
Definition: extract_mesh.hh:31
@ MR_EXTRACT_MESH
Definition: extract_mesh.hh:33
@ MR_EXTRACT_MAPPED
Definition: extract_mesh.hh:32
const MeshExtract extract_lines_with_lines_loose
const MeshExtract extract_lines_loose_only
const MeshExtract extract_lines
ccl_global float * buffer
format
Definition: logImageCore.h:38
static void extract_lines_task_reduce(void *_userdata_to, void *_userdata_from)
constexpr MeshExtract create_extractor_lines()
static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr, MeshBatchCache *cache, void *buf, void *data)
static void extract_lines_iter_ledge_mesh(const MeshRenderData *mr, const MEdge *med, const int ledge_index, void *data)
static void extract_lines_with_lines_loose_finish_subdiv(const struct DRWSubdivCache *subdiv_cache, const MeshRenderData *UNUSED(mr), MeshBatchCache *cache, void *UNUSED(buf), void *UNUSED(_data))
static void extract_lines_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, void *buffer, void *UNUSED(data))
constexpr MeshExtract create_extractor_lines_with_lines_loose()
static void extract_lines_loose_only_init(const MeshRenderData *mr, MeshBatchCache *cache, void *buf, void *UNUSED(tls_data))
static void extract_lines_loose_subbuffer(const MeshRenderData *mr, MeshBatchCache *cache)
static void extract_lines_finish(const MeshRenderData *UNUSED(mr), MeshBatchCache *UNUSED(cache), void *buf, void *data)
static void extract_lines_iter_poly_mesh(const MeshRenderData *mr, const MPoly *mp, const int UNUSED(mp_index), void *data)
constexpr MeshExtract create_extractor_lines_loose_only()
static void extract_lines_init(const MeshRenderData *mr, MeshBatchCache *UNUSED(cache), void *UNUSED(buf), void *tls_data)
static void extract_lines_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *UNUSED(mr), MeshBatchCache *UNUSED(cache), void *buffer, void *UNUSED(data))
static void extract_lines_loose_only_init_subdiv(const DRWSubdivCache *UNUSED(subdiv_cache), const MeshRenderData *mr, MeshBatchCache *cache, void *buffer, void *UNUSED(data))
static void extract_lines_iter_poly_bm(const MeshRenderData *UNUSED(mr), const BMFace *f, const int UNUSED(f_index), void *data)
static void extract_lines_iter_ledge_bm(const MeshRenderData *mr, const BMEdge *eed, const int ledge_index, void *data)
struct BMEdge * e
Definition: bmesh_class.h:164
struct BMLoop * next
Definition: bmesh_class.h:233
DRWSubdivLooseGeom loose_geom
unsigned int e
MeshBufferCache final
MeshBufferList buff
GPUIndexBuf * lines_loose
GPUIndexBuf * lines
struct MeshBufferList::@273 ibo
size_t mesh_buffer_offset
eMRDataType data_type
ExtractFinishFn * finish
ExtractLEdgeBMeshFn * iter_ledge_bm
ExtractInitSubdivFn * init_subdiv
size_t data_size
ExtractPolyBMeshFn * iter_poly_bm
ExtractLEdgeMeshFn * iter_ledge_mesh
ExtractFinishSubdivFn * finish_subdiv
ExtractPolyMeshFn * iter_poly_mesh
ExtractLooseGeomSubdivFn * iter_loose_geom_subdiv
ExtractTaskReduceFn * task_reduce
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