Blender V4.5
extract_mesh_vbo_edit_data.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
10
11#include "extract_mesh.hh"
12
13#include "draw_cache_impl.hh"
14
15#include "draw_subdivision.hh"
16
17namespace blender::draw {
18
20 const BMEdge *eed,
21 EditLoopData &eattr)
22{
23 const ToolSettings *ts = mr.toolsettings;
24 const bool is_vertex_select_mode = (ts != nullptr) && (ts->selectmode & SCE_SELECT_VERTEX) != 0;
25 const bool is_face_only_select_mode = (ts != nullptr) && (ts->selectmode == SCE_SELECT_FACE);
26
27 if (eed == mr.eed_act) {
29 }
30 if (!is_vertex_select_mode && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
32 }
33 if (is_vertex_select_mode && BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) &&
35 {
38 }
40 eattr.e_flag |= VFLAG_EDGE_SEAM;
41 }
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 #55456#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)) {
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) {
75 const FreestyleEdge *fed = (const FreestyleEdge *)BM_ELEM_CD_GET_VOID_P(eed,
77 if (fed->flag & FREESTYLE_EDGE_MARK) {
79 }
80 }
81#endif
82}
83
85 const BMVert *eve,
86 EditLoopData &eattr)
87{
88 if (eve == mr.eve_act) {
90 }
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 const GPUVertFormat format = []() {
107 /* WARNING: Adjust #EditLoopData struct accordingly. */
110 return format;
111 }();
112 return format;
113}
114
116{
117 MutableSpan corners_data = vbo_data.take_front(mr.corners_num);
118 MutableSpan loose_edge_data = vbo_data.slice(mr.corners_num, mr.loose_edges.size() * 2);
119 MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
120
121 const OffsetIndices faces = mr.faces;
122 const Span<int> corner_verts = mr.corner_verts;
123 const Span<int> corner_edges = mr.corner_edges;
124 threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) {
125 for (const int face : range) {
126 for (const int corner : faces[face]) {
127 EditLoopData &value = corners_data[corner];
128 value = {};
129 if (const BMFace *bm_face = bm_original_face_get(mr, face)) {
130 mesh_render_data_face_flag(mr, bm_face, {-1, -1, -1, -1}, value);
131 }
132 if (const BMVert *bm_vert = bm_original_vert_get(mr, corner_verts[corner])) {
133 mesh_render_data_vert_flag(mr, bm_vert, value);
134 }
135 if (const BMEdge *bm_edge = bm_original_edge_get(mr, corner_edges[corner])) {
136 mesh_render_data_edge_flag(mr, bm_edge, value);
137 }
138 }
139 }
140 });
141
142 const Span<int2> edges = mr.edges;
143 const Span<int> loose_edges = mr.loose_edges;
144 threading::parallel_for(loose_edges.index_range(), 2048, [&](const IndexRange range) {
145 for (const int i : range) {
146 EditLoopData &value_1 = loose_edge_data[i * 2 + 0];
147 EditLoopData &value_2 = loose_edge_data[i * 2 + 1];
148 if (const BMEdge *bm_edge = bm_original_edge_get(mr, loose_edges[i])) {
149 value_1 = {};
150 mesh_render_data_edge_flag(mr, bm_edge, value_1);
151 value_2 = value_1;
152 }
153 else {
154 value_2 = value_1 = {};
155 }
156 const int2 edge = edges[loose_edges[i]];
157 if (const BMVert *bm_vert = bm_original_vert_get(mr, edge[0])) {
158 mesh_render_data_vert_flag(mr, bm_vert, value_1);
159 }
160 if (const BMVert *bm_vert = bm_original_vert_get(mr, edge[1])) {
161 mesh_render_data_vert_flag(mr, bm_vert, value_2);
162 }
163 }
164 });
165
166 const Span<int> loose_verts = mr.loose_verts;
167 threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
168 for (const int i : range) {
169 loose_vert_data[i] = {};
170 if (const BMVert *eve = bm_original_vert_get(mr, loose_verts[i])) {
171 mesh_render_data_vert_flag(mr, eve, loose_vert_data[i]);
172 }
173 }
174 });
175}
176
178{
179 MutableSpan corners_data = vbo_data.take_front(mr.corners_num);
180 MutableSpan loose_edge_data = vbo_data.slice(mr.corners_num, mr.loose_edges.size() * 2);
181 MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
182
183 const BMesh &bm = *mr.bm;
184
185 threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
186 for (const int face_index : range) {
187 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
188 const BMLoop *loop = BM_FACE_FIRST_LOOP(&face);
189 for ([[maybe_unused]] const int i : IndexRange(face.len)) {
190 const int index = BM_elem_index_get(loop);
191 EditLoopData &value = corners_data[index];
192 value = {};
193 mesh_render_data_face_flag(mr, &face, {-1, -1, -1, -1}, corners_data[index]);
194 mesh_render_data_edge_flag(mr, loop->e, corners_data[index]);
195 mesh_render_data_vert_flag(mr, loop->v, corners_data[index]);
196 loop = loop->next;
197 }
198 }
199 });
200
201 const Span<int> loose_edges = mr.loose_edges;
202 threading::parallel_for(loose_edges.index_range(), 2048, [&](const IndexRange range) {
203 for (const int i : range) {
204 EditLoopData &value_1 = loose_edge_data[i * 2 + 0];
205 EditLoopData &value_2 = loose_edge_data[i * 2 + 1];
206 const BMEdge &edge = *BM_edge_at_index(&const_cast<BMesh &>(bm), loose_edges[i]);
207 value_1 = {};
208 mesh_render_data_edge_flag(mr, &edge, value_1);
209 value_2 = value_1;
210 mesh_render_data_vert_flag(mr, edge.v1, value_1);
211 mesh_render_data_vert_flag(mr, edge.v2, value_2);
212 }
213 });
214
215 const Span<int> loose_verts = mr.loose_verts;
216 threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
217 for (const int i : range) {
218 loose_vert_data[i] = {};
219 const BMVert &vert = *BM_vert_at_index(&const_cast<BMesh &>(bm), loose_verts[i]);
220 mesh_render_data_vert_flag(mr, &vert, loose_vert_data[i]);
221 }
222 });
223}
224
226{
228 const int size = mr.corners_num + mr.loose_indices_num;
230 MutableSpan vbo_data = vbo->data<EditLoopData>();
232 extract_edit_data_mesh(mr, vbo_data);
233 }
234 else {
235 extract_edit_data_bm(mr, vbo_data);
236 }
237 return vbo;
238}
239
241 const DRWSubdivCache &subdiv_cache,
243{
244 const int corners_num = subdiv_cache.num_subdiv_loops;
245 const int loose_edges_num = mr.loose_edges.size();
246 const int verts_per_edge = subdiv_verts_per_coarse_edge(subdiv_cache);
247 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index, corners_num);
248 const Span<int> subdiv_loop_vert_index = subdiv_cache.verts_orig_index->data<int>();
249 /* NOTE: #subdiv_loop_edge_index already has the origindex layer baked in. */
250 const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
251
252 MutableSpan corners_data = vbo_data.take_front(corners_num);
253 MutableSpan loose_edge_data = vbo_data.slice(corners_num, loose_edges_num * verts_per_edge);
254 MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
255
256 threading::parallel_for(IndexRange(subdiv_cache.num_subdiv_quads), 2048, [&](IndexRange range) {
257 for (const int subdiv_quad : range) {
258 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
259 for (const int subdiv_corner : IndexRange(subdiv_quad * 4, 4)) {
260 EditLoopData &value = corners_data[subdiv_corner];
261 value = {};
262
263 if (const BMFace *bm_face = bm_original_face_get(mr, coarse_face)) {
264 mesh_render_data_face_flag(mr, bm_face, {-1, -1, -1, -1}, value);
265 }
266
267 const int vert_origindex = subdiv_loop_vert_index[subdiv_corner];
268 if (vert_origindex != -1) {
269 if (const BMVert *bm_vert = bm_original_vert_get(mr, vert_origindex)) {
270 mesh_render_data_vert_flag(mr, bm_vert, value);
271 }
272 }
273
274 const int edge_origindex = subdiv_loop_edge_index[subdiv_corner];
275 if (edge_origindex != -1) {
276 if (const BMEdge *bm_edge = BM_edge_at_index(mr.bm, edge_origindex)) {
277 mesh_render_data_edge_flag(mr, bm_edge, value);
278 }
279 }
280 }
281 }
282 });
283
284 const Span<int2> edges = mr.edges;
285 const Span<int> loose_edges = mr.loose_edges;
286 threading::parallel_for(loose_edges.index_range(), 2048, [&](const IndexRange range) {
287 for (const int i : range) {
288 MutableSpan<EditLoopData> data = loose_edge_data.slice(i * verts_per_edge, verts_per_edge);
289 if (const BMEdge *edge = bm_original_edge_get(mr, loose_edges[i])) {
290 EditLoopData value{};
291 mesh_render_data_edge_flag(mr, edge, value);
292 data.fill(value);
293 }
294 else {
295 data.fill({});
296 }
297 const int2 edge = edges[loose_edges[i]];
298 if (const BMVert *bm_vert = bm_original_vert_get(mr, edge[0])) {
299 mesh_render_data_vert_flag(mr, bm_vert, data.first());
300 }
301 if (const BMVert *bm_vert = bm_original_vert_get(mr, edge[1])) {
302 mesh_render_data_vert_flag(mr, bm_vert, data.last());
303 }
304 }
305 });
306
307 const Span<int> loose_verts = mr.loose_verts;
308 threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
309 for (const int i : range) {
310 loose_vert_data[i] = {};
311 if (const BMVert *eve = bm_original_vert_get(mr, loose_verts[i])) {
312 mesh_render_data_vert_flag(mr, eve, loose_vert_data[i]);
313 }
314 }
315 });
316}
317
319 const DRWSubdivCache &subdiv_cache,
321{
322 const int corners_num = subdiv_cache.num_subdiv_loops;
323 const int loose_edges_num = mr.loose_edges.size();
324 const int verts_per_edge = subdiv_verts_per_coarse_edge(subdiv_cache);
325 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index, corners_num);
326 const Span<int> subdiv_loop_vert_index = subdiv_cache.verts_orig_index->data<int>();
327 const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
328
329 MutableSpan corners_data = vbo_data.take_front(corners_num);
330 MutableSpan loose_edge_data = vbo_data.slice(corners_num, loose_edges_num * verts_per_edge);
331 MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
332
333 BMesh &bm = *mr.bm;
334 threading::parallel_for(IndexRange(subdiv_cache.num_subdiv_quads), 2048, [&](IndexRange range) {
335 for (const int subdiv_quad : range) {
336 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
337 const BMFace *bm_face = BM_face_at_index(&bm, coarse_face);
338 for (const int subdiv_corner : IndexRange(subdiv_quad * 4, 4)) {
339 EditLoopData &value = corners_data[subdiv_corner];
340 value = {};
341
342 mesh_render_data_face_flag(mr, bm_face, {-1, -1, -1, -1}, value);
343
344 const int vert_origindex = subdiv_loop_vert_index[subdiv_corner];
345 if (vert_origindex != -1) {
346 const BMVert *bm_vert = BM_vert_at_index(mr.bm, vert_origindex);
347 mesh_render_data_vert_flag(mr, bm_vert, value);
348 }
349
350 const int edge_origindex = subdiv_loop_edge_index[subdiv_corner];
351 if (edge_origindex != -1) {
352 const BMEdge *bm_edge = BM_edge_at_index(mr.bm, edge_origindex);
353 mesh_render_data_edge_flag(mr, bm_edge, value);
354 }
355 }
356 }
357 });
358
359 const Span<int> loose_edges = mr.loose_edges;
360 threading::parallel_for(loose_edges.index_range(), 2048, [&](const IndexRange range) {
361 for (const int i : range) {
362 MutableSpan<EditLoopData> data = loose_edge_data.slice(i * verts_per_edge, verts_per_edge);
363 const BMEdge *edge = BM_edge_at_index(&bm, loose_edges[i]);
364 EditLoopData value{};
365 mesh_render_data_edge_flag(mr, edge, value);
366 data.fill(value);
367 mesh_render_data_vert_flag(mr, edge->v1, data.first());
368 mesh_render_data_vert_flag(mr, edge->v2, data.last());
369 }
370 });
371
372 const Span<int> loose_verts = mr.loose_verts;
373 threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
374 for (const int i : range) {
375 loose_vert_data[i] = {};
376 const BMVert *vert = BM_vert_at_index(&bm, loose_verts[i]);
377 mesh_render_data_vert_flag(mr, vert, loose_vert_data[i]);
378 }
379 });
380}
381
383 const DRWSubdivCache &subdiv_cache)
384{
386 const int size = subdiv_full_vbo_size(mr, subdiv_cache);
388 MutableSpan vbo_data = vbo->data<EditLoopData>();
390 extract_edit_subdiv_data_mesh(mr, subdiv_cache, vbo_data);
391 }
392 else {
393 extract_edit_subdiv_data_bm(mr, subdiv_cache, vbo_data);
394 }
395 return vbo;
396}
397
398} // namespace blender::draw
unsigned char uchar
@ FREESTYLE_EDGE_MARK
@ SCE_SELECT_FACE
@ SCE_SELECT_VERTEX
#define GPU_vertbuf_create_with_format(format)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
@ GPU_FETCH_INT
void GPU_vertformat_alias_add(GPUVertFormat *, blender::StringRef alias)
uint GPU_vertformat_attr_add(GPUVertFormat *, blender::StringRef name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_U8
#define BM_ELEM_CD_GET_FLOAT(ele, offset)
@ BM_ELEM_SEAM
@ BM_ELEM_SELECT
@ BM_ELEM_SMOOTH
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
#define BM_elem_flag_test(ele, hflag)
BMesh * bm
bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
Definition BLI_span.hh:573
constexpr MutableSpan take_back(const int64_t n) const
Definition BLI_span.hh:640
constexpr T * data() const
Definition BLI_span.hh:539
constexpr MutableSpan take_front(const int64_t n) const
Definition BLI_span.hh:629
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
MutableSpan< T > data()
Extraction of Mesh data into VBO to feed to GPU.
#define ceil
format
static char faces[256]
gpu::VertBufPtr extract_edit_data_subdiv(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache)
static void extract_edit_subdiv_data_bm(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, MutableSpan< EditLoopData > vbo_data)
int subdiv_verts_per_coarse_edge(const DRWSubdivCache &cache)
static void mesh_render_data_edge_flag(const MeshRenderData &mr, const BMEdge *eed, EditLoopData &eattr)
static void extract_edit_data_mesh(const MeshRenderData &mr, MutableSpan< EditLoopData > vbo_data)
int subdiv_full_vbo_size(const MeshRenderData &mr, const DRWSubdivCache &cache)
static void extract_edit_data_bm(const MeshRenderData &mr, MutableSpan< EditLoopData > vbo_data)
static void extract_edit_data(const OffsetIndices< int > points_by_curve, const IndexMask &curve_selection, const VArray< bool > &selection_attr, const bool mark_active, const uint32_t fill_value, MutableSpan< uint32_t > data)
static void extract_edit_subdiv_data_mesh(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, MutableSpan< EditLoopData > vbo_data)
static void mesh_render_data_vert_flag(const MeshRenderData &mr, const BMVert *eve, EditLoopData &eattr)
static const GPUVertFormat & get_edit_data_format()
std::unique_ptr< gpu::VertBuf, gpu::VertBufDeleter > VertBufPtr
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
BMVert * v1
BMVert * v2
const ToolSettings * toolsettings
OffsetIndices< int > faces