Blender  V3.3
extract_mesh_vbo_edit_data.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 "extract_mesh.hh"
9 
10 #include "draw_cache_impl.h"
11 
12 #include "draw_subdivision.h"
13 
14 namespace blender::draw {
15 
16 /* ---------------------------------------------------------------------- */
21  const BMEdge *eed,
22  EditLoopData *eattr)
23 {
24  const ToolSettings *ts = mr->toolsettings;
25  const bool is_vertex_select_mode = (ts != nullptr) && (ts->selectmode & SCE_SELECT_VERTEX) != 0;
26  const bool is_face_only_select_mode = (ts != nullptr) && (ts->selectmode == SCE_SELECT_FACE);
27 
28  if (eed == mr->eed_act) {
29  eattr->e_flag |= VFLAG_EDGE_ACTIVE;
30  }
31  if (!is_vertex_select_mode && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
32  eattr->e_flag |= VFLAG_EDGE_SELECTED;
33  }
34  if (is_vertex_select_mode && BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) &&
36  eattr->e_flag |= VFLAG_EDGE_SELECTED;
37  eattr->e_flag |= VFLAG_VERT_SELECTED;
38  }
39  if (BM_elem_flag_test(eed, BM_ELEM_SEAM)) {
40  eattr->e_flag |= VFLAG_EDGE_SEAM;
41  }
42  if (!BM_elem_flag_test(eed, BM_ELEM_SMOOTH)) {
43  eattr->e_flag |= VFLAG_EDGE_SHARP;
44  }
45 
46  /* Use active edge color for active face edges because
47  * specular highlights make it hard to see T55456#510873.
48  *
49  * This isn't ideal since it can't be used when mixing edge/face modes
50  * but it's still better than not being able to see the active face. */
51  if (is_face_only_select_mode) {
52  if (mr->efa_act != nullptr) {
53  if (BM_edge_in_face(eed, mr->efa_act)) {
54  eattr->e_flag |= VFLAG_EDGE_ACTIVE;
55  }
56  }
57  }
58 
59  /* Use half a byte for value range */
60  if (mr->edge_crease_ofs != -1) {
61  float crease = BM_ELEM_CD_GET_FLOAT(eed, mr->edge_crease_ofs);
62  if (crease > 0) {
63  eattr->crease = (uchar)ceil(crease * 15.0f);
64  }
65  }
66  /* Use a byte for value range */
67  if (mr->bweight_ofs != -1) {
68  float bweight = BM_ELEM_CD_GET_FLOAT(eed, mr->bweight_ofs);
69  if (bweight > 0) {
70  eattr->bweight = (uchar)(bweight * 255.0f);
71  }
72  }
73 #ifdef WITH_FREESTYLE
74  if (mr->freestyle_edge_ofs != -1) {
76  eed, mr->freestyle_edge_ofs);
77  if (fed->flag & FREESTYLE_EDGE_MARK) {
78  eattr->e_flag |= VFLAG_EDGE_FREESTYLE;
79  }
80  }
81 #endif
82 }
83 
85  const BMVert *eve,
86  EditLoopData *eattr)
87 {
88  if (eve == mr->eve_act) {
89  eattr->e_flag |= VFLAG_VERT_ACTIVE;
90  }
92  eattr->e_flag |= VFLAG_VERT_SELECTED;
93  }
94  /* Use half a byte for value range */
95  if (mr->vert_crease_ofs != -1) {
96  float crease = BM_ELEM_CD_GET_FLOAT(eve, mr->vert_crease_ofs);
97  if (crease > 0) {
98  eattr->crease |= (uchar)ceil(crease * 15.0f) << 4;
99  }
100  }
101 }
102 
104 {
105  static GPUVertFormat format = {0};
106  if (format.attr_len == 0) {
107  /* WARNING: Adjust #EditLoopData struct accordingly. */
110  }
111  return &format;
112 }
113 
115  MeshBatchCache *UNUSED(cache),
116  void *buf,
117  void *tls_data)
118 {
119  GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
123  EditLoopData *vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo);
124  *(EditLoopData **)tls_data = vbo_data;
125 }
126 
128  const BMFace *f,
129  const int UNUSED(f_index),
130  void *_data)
131 {
132  EditLoopData *vbo_data = *(EditLoopData **)_data;
133 
134  BMLoop *l_iter, *l_first;
135  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
136  do {
137  const int l_index = BM_elem_index_get(l_iter);
138 
139  EditLoopData *data = vbo_data + l_index;
140  memset(data, 0x0, sizeof(*data));
141  mesh_render_data_face_flag(mr, f, -1, data);
142  mesh_render_data_edge_flag(mr, l_iter->e, data);
143  mesh_render_data_vert_flag(mr, l_iter->v, data);
144  } while ((l_iter = l_iter->next) != l_first);
145 }
146 
148  const MPoly *mp,
149  const int mp_index,
150  void *_data)
151 {
152  EditLoopData *vbo_data = *(EditLoopData **)_data;
153 
154  const MLoop *mloop = mr->mloop;
155  const int ml_index_end = mp->loopstart + mp->totloop;
156  for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {
157  const MLoop *ml = &mloop[ml_index];
158  EditLoopData *data = vbo_data + ml_index;
159  memset(data, 0x0, sizeof(*data));
160  BMFace *efa = bm_original_face_get(mr, mp_index);
161  BMEdge *eed = bm_original_edge_get(mr, ml->e);
162  BMVert *eve = bm_original_vert_get(mr, ml->v);
163  if (efa) {
164  mesh_render_data_face_flag(mr, efa, -1, data);
165  }
166  if (eed) {
168  }
169  if (eve) {
171  }
172  }
173 }
174 
176  const BMEdge *eed,
177  const int ledge_index,
178  void *_data)
179 {
180  EditLoopData *vbo_data = *(EditLoopData **)_data;
181  EditLoopData *data = vbo_data + mr->loop_len + (ledge_index * 2);
182  memset(data, 0x0, sizeof(*data) * 2);
183  mesh_render_data_edge_flag(mr, eed, &data[0]);
184  data[1] = data[0];
185  mesh_render_data_vert_flag(mr, eed->v1, &data[0]);
186  mesh_render_data_vert_flag(mr, eed->v2, &data[1]);
187 }
188 
190  const MEdge *med,
191  const int ledge_index,
192  void *_data)
193 {
194  EditLoopData *vbo_data = *(EditLoopData **)_data;
195  EditLoopData *data = vbo_data + mr->loop_len + ledge_index * 2;
196  memset(data, 0x0, sizeof(*data) * 2);
197  const int e_index = mr->ledges[ledge_index];
198  BMEdge *eed = bm_original_edge_get(mr, e_index);
199  BMVert *eve1 = bm_original_vert_get(mr, med->v1);
200  BMVert *eve2 = bm_original_vert_get(mr, med->v2);
201  if (eed) {
202  mesh_render_data_edge_flag(mr, eed, &data[0]);
203  data[1] = data[0];
204  }
205  if (eve1) {
206  mesh_render_data_vert_flag(mr, eve1, &data[0]);
207  }
208  if (eve2) {
209  mesh_render_data_vert_flag(mr, eve2, &data[1]);
210  }
211 }
212 
214  const BMVert *eve,
215  const int lvert_index,
216  void *_data)
217 {
218  EditLoopData *vbo_data = *(EditLoopData **)_data;
219  const int offset = mr->loop_len + (mr->edge_loose_len * 2);
220  EditLoopData *data = vbo_data + offset + lvert_index;
221  memset(data, 0x0, sizeof(*data));
223 }
224 
226  const MVert *UNUSED(mv),
227  const int lvert_index,
228  void *_data)
229 {
230  EditLoopData *vbo_data = *(EditLoopData **)_data;
231  const int offset = mr->loop_len + (mr->edge_loose_len * 2);
232 
233  EditLoopData *data = vbo_data + offset + lvert_index;
234  memset(data, 0x0, sizeof(*data));
235  const int v_index = mr->lverts[lvert_index];
236  BMVert *eve = bm_original_vert_get(mr, v_index);
237  if (eve) {
239  }
240 }
241 
242 static void extract_edit_data_init_subdiv(const DRWSubdivCache *subdiv_cache,
243  const MeshRenderData *UNUSED(mr),
244  MeshBatchCache *UNUSED(cache),
245  void *buf,
246  void *data)
247 {
248  const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
249  GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
251  GPU_vertbuf_data_alloc(vbo, subdiv_cache->num_subdiv_loops + loose_geom.loop_len);
252  EditLoopData *vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo);
253  *(EditLoopData **)data = vbo_data;
254 }
255 
256 static void extract_edit_data_iter_subdiv_bm(const DRWSubdivCache *subdiv_cache,
257  const MeshRenderData *mr,
258  void *_data,
259  uint subdiv_quad_index,
260  const BMFace *coarse_quad)
261 {
262  EditLoopData *vbo_data = *(EditLoopData **)_data;
263  int *subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(subdiv_cache->verts_orig_index);
264  int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache->edges_orig_index);
265 
266  uint start_loop_idx = subdiv_quad_index * 4;
267  uint end_loop_idx = (subdiv_quad_index + 1) * 4;
268  for (uint i = start_loop_idx; i < end_loop_idx; i++) {
269  const int vert_origindex = subdiv_loop_vert_index[i];
270  const int edge_origindex = subdiv_loop_edge_index[i];
271 
272  EditLoopData *edit_loop_data = &vbo_data[i];
273  memset(edit_loop_data, 0, sizeof(EditLoopData));
274 
275  if (vert_origindex != -1) {
276  const BMVert *eve = mr->v_origindex ? bm_original_vert_get(mr, vert_origindex) :
277  BM_vert_at_index(mr->bm, vert_origindex);
278  if (eve) {
279  mesh_render_data_vert_flag(mr, eve, edit_loop_data);
280  }
281  }
282 
283  if (edge_origindex != -1) {
284  /* NOTE: #subdiv_loop_edge_index already has the origindex layer baked in. */
285  const BMEdge *eed = BM_edge_at_index(mr->bm, edge_origindex);
286  mesh_render_data_edge_flag(mr, eed, edit_loop_data);
287  }
288 
289  /* coarse_quad can be null when called by the mesh iteration below. */
290  if (coarse_quad) {
291  /* The -1 parameter is for edit_uvs, which we don't do here. */
292  mesh_render_data_face_flag(mr, coarse_quad, -1, edit_loop_data);
293  }
294  }
295 }
296 
297 static void extract_edit_data_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cache,
298  const MeshRenderData *mr,
299  void *_data,
300  uint subdiv_quad_index,
301  const MPoly *coarse_quad)
302 {
303  const int coarse_quad_index = static_cast<int>(coarse_quad - mr->mpoly);
304  BMFace *coarse_quad_bm = bm_original_face_get(mr, coarse_quad_index);
305  extract_edit_data_iter_subdiv_bm(subdiv_cache, mr, _data, subdiv_quad_index, coarse_quad_bm);
306 }
307 
308 static void extract_edit_data_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
309  const MeshRenderData *mr,
310  void *UNUSED(buffer),
311  void *_data)
312 {
313  const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
314  if (loose_geom.edge_len == 0) {
315  return;
316  }
317 
319 
320  EditLoopData *vbo_data = *(EditLoopData **)_data;
321  int ledge_index = 0;
322 
323  for (const DRWSubdivLooseEdge &loose_edge : loose_edges) {
324  const int offset = subdiv_cache->num_subdiv_loops + ledge_index++ * 2;
325  EditLoopData *data = &vbo_data[offset];
326  memset(data, 0, sizeof(EditLoopData));
327  const int edge_index = loose_edge.coarse_edge_index;
328  BMEdge *eed = mr->e_origindex ? bm_original_edge_get(mr, edge_index) :
329  BM_edge_at_index(mr->bm, edge_index);
330  mesh_render_data_edge_flag(mr, eed, &data[0]);
331  data[1] = data[0];
332 
333  const DRWSubdivLooseVertex &v1 = loose_geom.verts[loose_edge.loose_subdiv_v1_index];
334  const DRWSubdivLooseVertex &v2 = loose_geom.verts[loose_edge.loose_subdiv_v2_index];
335 
336  if (v1.coarse_vertex_index != -1u) {
337  mesh_render_data_vert_flag(mr, eed->v1, &data[0]);
338  }
339  if (v2.coarse_vertex_index != -1u) {
340  mesh_render_data_vert_flag(mr, eed->v2, &data[1]);
341  }
342  }
343 }
344 
346 {
347  MeshExtract extractor = {nullptr};
348  extractor.init = extract_edit_data_init;
359  extractor.data_type = MR_DATA_NONE;
360  extractor.data_size = sizeof(EditLoopData *);
361  extractor.use_threading = true;
362  extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.edit_data);
363  return extractor;
364 }
365 
368 } // namespace blender::draw
369 
unsigned char uchar
Definition: BLI_sys_types.h:70
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
@ FREESTYLE_EDGE_MARK
#define SCE_SELECT_FACE
#define SCE_SELECT_VERTEX
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
struct GPUVertBuf GPUVertBuf
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)
void GPU_vertformat_alias_add(GPUVertFormat *, const char *alias)
@ GPU_COMP_U8
#define BM_ELEM_CD_GET_FLOAT(ele, offset)
Definition: bmesh_class.h:553
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:622
@ BM_ELEM_SEAM
Definition: bmesh_class.h:473
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
@ BM_ELEM_SMOOTH
Definition: bmesh_class.h:477
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:541
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:12
BLI_INLINE BMEdge * BM_edge_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:109
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:103
bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
Definition: bmesh_query.c:420
ATTR_WARN_UNUSED_RESULT const BMVert * v2
@ MR_DATA_NONE
@ VFLAG_EDGE_SEAM
@ VFLAG_EDGE_FREESTYLE
@ VFLAG_EDGE_ACTIVE
@ VFLAG_EDGE_SHARP
@ VFLAG_EDGE_SELECTED
@ VFLAG_VERT_SELECTED
@ VFLAG_VERT_ACTIVE
blender::Span< DRWSubdivLooseEdge > draw_subdiv_cache_get_loose_edges(const DRWSubdivCache *cache)
void mesh_render_data_face_flag(const MeshRenderData *mr, const BMFace *efa, const int cd_ofs, EditLoopData *eattr)
Definition: extract_mesh.cc:92
Extraction of Mesh data into VBO to feed to GPU.
BLI_INLINE BMFace * bm_original_face_get(const MeshRenderData *mr, int idx)
BLI_INLINE BMEdge * bm_original_edge_get(const MeshRenderData *mr, int idx)
BLI_INLINE BMVert * bm_original_vert_get(const MeshRenderData *mr, int idx)
const MeshExtract extract_edit_data
ccl_global float * buffer
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
format
Definition: logImageCore.h:38
ccl_device_inline float3 ceil(const float3 &a)
Definition: math_float3.h:363
static void mesh_render_data_edge_flag(const MeshRenderData *mr, const BMEdge *eed, EditLoopData *eattr)
static void extract_edit_data_iter_ledge_bm(const MeshRenderData *mr, const BMEdge *eed, const int ledge_index, void *_data)
static void extract_edit_data_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, void *_data, uint subdiv_quad_index, const MPoly *coarse_quad)
static void extract_edit_data_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, void *UNUSED(buffer), void *_data)
static GPUVertFormat * get_edit_data_format()
static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr, const MPoly *mp, const int mp_index, void *_data)
static void extract_edit_data_iter_poly_bm(const MeshRenderData *mr, const BMFace *f, const int UNUSED(f_index), void *_data)
static void extract_edit_data_iter_subdiv_bm(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, void *_data, uint subdiv_quad_index, const BMFace *coarse_quad)
static void extract_edit_data_iter_ledge_mesh(const MeshRenderData *mr, const MEdge *med, const int ledge_index, void *_data)
static void mesh_render_data_vert_flag(const MeshRenderData *mr, const BMVert *eve, EditLoopData *eattr)
static void extract_edit_data_init(const MeshRenderData *mr, MeshBatchCache *UNUSED(cache), void *buf, void *tls_data)
static void extract_edit_data_iter_lvert_bm(const MeshRenderData *mr, const BMVert *eve, const int lvert_index, void *_data)
static void extract_edit_data_iter_lvert_mesh(const MeshRenderData *mr, const MVert *UNUSED(mv), const int lvert_index, void *_data)
constexpr MeshExtract create_extractor_edit_data()
static void extract_edit_data_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *UNUSED(mr), MeshBatchCache *UNUSED(cache), void *buf, void *data)
BMVert * v1
Definition: bmesh_class.h:122
BMVert * v2
Definition: bmesh_class.h:122
struct BMVert * v
Definition: bmesh_class.h:153
struct BMEdge * e
Definition: bmesh_class.h:164
struct BMLoop * next
Definition: bmesh_class.h:233
struct GPUVertBuf * edges_orig_index
struct GPUVertBuf * verts_orig_index
DRWSubdivLooseGeom loose_geom
DRWSubdivLooseVertex * verts
unsigned int v1
unsigned int v2
unsigned int e
unsigned int v
GPUVertBuf * edit_data
ExtractIterSubdivBMeshFn * iter_subdiv_bm
size_t mesh_buffer_offset
eMRDataType data_type
ExtractLVertBMeshFn * iter_lvert_bm
ExtractLVertMeshFn * iter_lvert_mesh
ExtractLEdgeBMeshFn * iter_ledge_bm
ExtractIterSubdivMeshFn * iter_subdiv_mesh
ExtractInitSubdivFn * init_subdiv
size_t data_size
ExtractPolyBMeshFn * iter_poly_bm
ExtractLEdgeMeshFn * iter_ledge_mesh
ExtractPolyMeshFn * iter_poly_mesh
ExtractLooseGeomSubdivFn * iter_loose_geom_subdiv
bool use_threading
ExtractInitFn * init
BMVert * eve_act
Definition: extract_mesh.hh:78
const MLoop * mloop
Definition: extract_mesh.hh:76
BMEdge * eed_act
Definition: extract_mesh.hh:79
const int * v_origindex
Definition: extract_mesh.hh:66
const ToolSettings * toolsettings
Definition: extract_mesh.hh:53
const MPoly * mpoly
Definition: extract_mesh.hh:77
BMFace * efa_act
Definition: extract_mesh.hh:80
const int * e_origindex
Definition: extract_mesh.hh:66