Blender V5.0
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) {
77 }
78 }
79#endif
80}
81
83 const BMVert *eve,
84 EditLoopData &eattr)
85{
86 if (eve == mr.eve_act) {
88 }
91 }
92 /* Use half a byte for value range */
93 if (mr.vert_crease_ofs != -1) {
94 float crease = BM_ELEM_CD_GET_FLOAT(eve, mr.vert_crease_ofs);
95 if (crease > 0) {
96 eattr.crease |= uchar(ceil(crease * 15.0f)) << 4;
97 }
98 }
99}
100
102{
103 static const GPUVertFormat format = []() {
105 /* WARNING: Adjust #EditLoopData struct accordingly. */
106 GPU_vertformat_attr_add(&format, "data", gpu::VertAttrType::UINT_8_8_8_8);
108 return format;
109 }();
110 return format;
111}
112
114{
115 MutableSpan corners_data = vbo_data.take_front(mr.corners_num);
116 MutableSpan loose_edge_data = vbo_data.slice(mr.corners_num, mr.loose_edges.size() * 2);
117 MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
118
119 const BMUVOffsets uv_offsets_none = BMUVOFFSETS_NONE;
120 const OffsetIndices faces = mr.faces;
121 const Span<int> corner_verts = mr.corner_verts;
122 const Span<int> corner_edges = mr.corner_edges;
123 threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) {
124 for (const int face : range) {
125 EditLoopData face_value = {};
126 if (const BMFace *bm_face = bm_original_face_get(mr, face)) {
127 mesh_render_data_face_flag(mr, bm_face, uv_offsets_none, face_value);
128 }
129 for (const int corner : faces[face]) {
130 EditLoopData &value = corners_data[corner];
131 value = face_value;
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 const BMUVOffsets uv_offsets_none = BMUVOFFSETS_NONE;
185
186 threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
187 for (const int face_index : range) {
188 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
189 EditLoopData face_value = {};
190 mesh_render_data_face_flag(mr, &face, uv_offsets_none, face_value);
191 const BMLoop *loop = BM_FACE_FIRST_LOOP(&face);
192 for ([[maybe_unused]] const int i : IndexRange(face.len)) {
193 const int index = BM_elem_index_get(loop);
194 EditLoopData &value = corners_data[index];
195 value = face_value;
196 mesh_render_data_edge_flag(mr, loop->e, value);
197 mesh_render_data_vert_flag(mr, loop->v, value);
198 loop = loop->next;
199 }
200 }
201 });
202
203 const Span<int> loose_edges = mr.loose_edges;
204 threading::parallel_for(loose_edges.index_range(), 2048, [&](const IndexRange range) {
205 for (const int i : range) {
206 EditLoopData &value_1 = loose_edge_data[i * 2 + 0];
207 EditLoopData &value_2 = loose_edge_data[i * 2 + 1];
208 const BMEdge &edge = *BM_edge_at_index(&const_cast<BMesh &>(bm), loose_edges[i]);
209 value_1 = {};
210 mesh_render_data_edge_flag(mr, &edge, value_1);
211 value_2 = value_1;
212 mesh_render_data_vert_flag(mr, edge.v1, value_1);
213 mesh_render_data_vert_flag(mr, edge.v2, value_2);
214 }
215 });
216
217 const Span<int> loose_verts = mr.loose_verts;
218 threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
219 for (const int i : range) {
220 loose_vert_data[i] = {};
221 const BMVert &vert = *BM_vert_at_index(&const_cast<BMesh &>(bm), loose_verts[i]);
222 mesh_render_data_vert_flag(mr, &vert, loose_vert_data[i]);
223 }
224 });
225}
226
228{
230 const int size = mr.corners_num + mr.loose_indices_num;
232 MutableSpan vbo_data = vbo->data<EditLoopData>();
234 extract_edit_data_mesh(mr, vbo_data);
235 }
236 else {
237 extract_edit_data_bm(mr, vbo_data);
238 }
239 return vbo;
240}
241
243 const DRWSubdivCache &subdiv_cache,
245{
246 const BMUVOffsets uv_offsets_none = BMUVOFFSETS_NONE;
247 const int corners_num = subdiv_cache.num_subdiv_loops;
248 const int loose_edges_num = mr.loose_edges.size();
249 const int verts_per_edge = subdiv_verts_per_coarse_edge(subdiv_cache);
250 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index, corners_num);
251 const Span<int> subdiv_loop_vert_index = subdiv_cache.verts_orig_index->data<int>();
252 /* NOTE: #subdiv_loop_edge_index already has the origindex layer baked in. */
253 const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
254
255 MutableSpan corners_data = vbo_data.take_front(corners_num);
256 MutableSpan loose_edge_data = vbo_data.slice(corners_num, loose_edges_num * verts_per_edge);
257 MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
258
259 threading::parallel_for(IndexRange(subdiv_cache.num_subdiv_quads), 2048, [&](IndexRange range) {
260 for (const int subdiv_quad : range) {
261 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
262
263 EditLoopData face_value = {};
264 if (const BMFace *bm_face = bm_original_face_get(mr, coarse_face)) {
265 mesh_render_data_face_flag(mr, bm_face, uv_offsets_none, face_value);
266 }
267 for (const int subdiv_corner : IndexRange(subdiv_quad * 4, 4)) {
268 EditLoopData &value = corners_data[subdiv_corner];
269 value = face_value;
270
271 const int vert_origindex = subdiv_loop_vert_index[subdiv_corner];
272 if (vert_origindex != -1) {
273 if (const BMVert *bm_vert = bm_original_vert_get(mr, vert_origindex)) {
274 mesh_render_data_vert_flag(mr, bm_vert, value);
275 }
276 }
277
278 const int edge_origindex = subdiv_loop_edge_index[subdiv_corner];
279 if (edge_origindex != -1) {
280 if (const BMEdge *bm_edge = BM_edge_at_index(mr.bm, edge_origindex)) {
281 mesh_render_data_edge_flag(mr, bm_edge, value);
282 }
283 }
284 }
285 }
286 });
287
288 const Span<int2> edges = mr.edges;
289 const Span<int> loose_edges = mr.loose_edges;
290 threading::parallel_for(loose_edges.index_range(), 2048, [&](const IndexRange range) {
291 for (const int i : range) {
292 MutableSpan<EditLoopData> data = loose_edge_data.slice(i * verts_per_edge, verts_per_edge);
293 if (const BMEdge *edge = bm_original_edge_get(mr, loose_edges[i])) {
294 EditLoopData value{};
295 mesh_render_data_edge_flag(mr, edge, value);
296 data.fill(value);
297 }
298 else {
299 data.fill({});
300 }
301 const int2 edge = edges[loose_edges[i]];
302 if (const BMVert *bm_vert = bm_original_vert_get(mr, edge[0])) {
303 mesh_render_data_vert_flag(mr, bm_vert, data.first());
304 }
305 if (const BMVert *bm_vert = bm_original_vert_get(mr, edge[1])) {
306 mesh_render_data_vert_flag(mr, bm_vert, data.last());
307 }
308 }
309 });
310
311 const Span<int> loose_verts = mr.loose_verts;
312 threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
313 for (const int i : range) {
314 loose_vert_data[i] = {};
315 if (const BMVert *eve = bm_original_vert_get(mr, loose_verts[i])) {
316 mesh_render_data_vert_flag(mr, eve, loose_vert_data[i]);
317 }
318 }
319 });
320}
321
323 const DRWSubdivCache &subdiv_cache,
325{
326 const BMUVOffsets uv_offsets_none = BMUVOFFSETS_NONE;
327 const int corners_num = subdiv_cache.num_subdiv_loops;
328 const int loose_edges_num = mr.loose_edges.size();
329 const int verts_per_edge = subdiv_verts_per_coarse_edge(subdiv_cache);
330 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index, corners_num);
331 const Span<int> subdiv_loop_vert_index = subdiv_cache.verts_orig_index->data<int>();
332 const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
333
334 MutableSpan corners_data = vbo_data.take_front(corners_num);
335 MutableSpan loose_edge_data = vbo_data.slice(corners_num, loose_edges_num * verts_per_edge);
336 MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
337
338 BMesh &bm = *mr.bm;
339 threading::parallel_for(IndexRange(subdiv_cache.num_subdiv_quads), 2048, [&](IndexRange range) {
340 for (const int subdiv_quad : range) {
341 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
342 const BMFace *bm_face = BM_face_at_index(&bm, coarse_face);
343
344 EditLoopData face_value = {};
345 mesh_render_data_face_flag(mr, bm_face, uv_offsets_none, face_value);
346
347 for (const int subdiv_corner : IndexRange(subdiv_quad * 4, 4)) {
348 EditLoopData &value = corners_data[subdiv_corner];
349 value = face_value;
350
351 const int vert_origindex = subdiv_loop_vert_index[subdiv_corner];
352 if (vert_origindex != -1) {
353 const BMVert *bm_vert = BM_vert_at_index(mr.bm, vert_origindex);
354 mesh_render_data_vert_flag(mr, bm_vert, value);
355 }
356
357 const int edge_origindex = subdiv_loop_edge_index[subdiv_corner];
358 if (edge_origindex != -1) {
359 const BMEdge *bm_edge = BM_edge_at_index(mr.bm, edge_origindex);
360 mesh_render_data_edge_flag(mr, bm_edge, value);
361 }
362 }
363 }
364 });
365
366 const Span<int> loose_edges = mr.loose_edges;
367 threading::parallel_for(loose_edges.index_range(), 2048, [&](const IndexRange range) {
368 for (const int i : range) {
369 MutableSpan<EditLoopData> data = loose_edge_data.slice(i * verts_per_edge, verts_per_edge);
370 const BMEdge *edge = BM_edge_at_index(&bm, loose_edges[i]);
371 EditLoopData value{};
372 mesh_render_data_edge_flag(mr, edge, value);
373 data.fill(value);
374 mesh_render_data_vert_flag(mr, edge->v1, data.first());
375 mesh_render_data_vert_flag(mr, edge->v2, data.last());
376 }
377 });
378
379 const Span<int> loose_verts = mr.loose_verts;
380 threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
381 for (const int i : range) {
382 loose_vert_data[i] = {};
383 const BMVert *vert = BM_vert_at_index(&bm, loose_verts[i]);
384 mesh_render_data_vert_flag(mr, vert, loose_vert_data[i]);
385 }
386 });
387}
388
390 const DRWSubdivCache &subdiv_cache)
391{
393 const int size = subdiv_full_vbo_size(mr, subdiv_cache);
395 MutableSpan vbo_data = vbo->data<EditLoopData>();
397 extract_edit_subdiv_data_mesh(mr, subdiv_cache, vbo_data);
398 }
399 else {
400 extract_edit_subdiv_data_bm(mr, subdiv_cache, vbo_data);
401 }
402 return vbo;
403}
404
405} // namespace blender::draw
#define BMUVOFFSETS_NONE
unsigned char uchar
@ SCE_SELECT_FACE
@ SCE_SELECT_VERTEX
static blender::gpu::VertBuf * GPU_vertbuf_create_with_format(const GPUVertFormat &format)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
void GPU_vertformat_alias_add(GPUVertFormat *, blender::StringRef alias)
uint GPU_vertformat_attr_add(GPUVertFormat *format, blender::StringRef name, blender::gpu::VertAttrType type)
#define BM_ELEM_CD_GET_BOOL(ele, offset)
#define BM_ELEM_CD_GET_FLOAT(ele, offset)
@ BM_ELEM_SEAM
@ BM_ELEM_SELECT
@ BM_ELEM_SMOOTH
#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