Blender V4.3
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
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 GPUVertFormat format = {0};
106 if (format.attr_len == 0) {
107 /* WARNING: Adjust #EditLoopData struct accordingly. */
110 }
111 return format;
112}
113
115{
116 MutableSpan corners_data = vbo_data.take_front(mr.corners_num);
117 MutableSpan loose_edge_data = vbo_data.slice(mr.corners_num, mr.loose_edges.size() * 2);
118 MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
119
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 for (const int corner : faces[face]) {
126 EditLoopData &value = corners_data[corner];
127 value = {};
128 if (const BMFace *bm_face = bm_original_face_get(mr, face)) {
129 mesh_render_data_face_flag(mr, bm_face, {-1, -1, -1, -1}, value);
130 }
131 if (const BMVert *bm_vert = bm_original_vert_get(mr, corner_verts[corner])) {
132 mesh_render_data_vert_flag(mr, bm_vert, value);
133 }
134 if (const BMEdge *bm_edge = bm_original_edge_get(mr, corner_edges[corner])) {
135 mesh_render_data_edge_flag(mr, bm_edge, value);
136 }
137 }
138 }
139 });
140
141 const Span<int2> edges = mr.edges;
142 const Span<int> loose_edges = mr.loose_edges;
143 threading::parallel_for(loose_edges.index_range(), 2048, [&](const IndexRange range) {
144 for (const int i : range) {
145 EditLoopData &value_1 = loose_edge_data[i * 2 + 0];
146 EditLoopData &value_2 = loose_edge_data[i * 2 + 1];
147 if (const BMEdge *bm_edge = bm_original_edge_get(mr, loose_edges[i])) {
148 value_1 = {};
149 mesh_render_data_edge_flag(mr, bm_edge, value_1);
150 value_2 = value_1;
151 }
152 else {
153 value_2 = value_1 = {};
154 }
155 const int2 edge = edges[loose_edges[i]];
156 if (const BMVert *bm_vert = bm_original_vert_get(mr, edge[0])) {
157 mesh_render_data_vert_flag(mr, bm_vert, value_1);
158 }
159 if (const BMVert *bm_vert = bm_original_vert_get(mr, edge[1])) {
160 mesh_render_data_vert_flag(mr, bm_vert, value_2);
161 }
162 }
163 });
164
165 const Span<int> loose_verts = mr.loose_verts;
166 threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
167 for (const int i : range) {
168 loose_vert_data[i] = {};
169 if (const BMVert *eve = bm_original_vert_get(mr, loose_verts[i])) {
170 mesh_render_data_vert_flag(mr, eve, loose_vert_data[i]);
171 }
172 }
173 });
174}
175
177{
178 MutableSpan corners_data = vbo_data.take_front(mr.corners_num);
179 MutableSpan loose_edge_data = vbo_data.slice(mr.corners_num, mr.loose_edges.size() * 2);
180 MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
181
182 const BMesh &bm = *mr.bm;
183
184 threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
185 for (const int face_index : range) {
186 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
187 const BMLoop *loop = BM_FACE_FIRST_LOOP(&face);
188 for ([[maybe_unused]] const int i : IndexRange(face.len)) {
189 const int index = BM_elem_index_get(loop);
190 EditLoopData &value = corners_data[index];
191 value = {};
192 mesh_render_data_face_flag(mr, &face, {-1, -1, -1, -1}, corners_data[index]);
193 mesh_render_data_edge_flag(mr, loop->e, corners_data[index]);
194 mesh_render_data_vert_flag(mr, loop->v, corners_data[index]);
195 loop = loop->next;
196 }
197 }
198 });
199
200 const Span<int> loose_edges = mr.loose_edges;
201 threading::parallel_for(loose_edges.index_range(), 2048, [&](const IndexRange range) {
202 for (const int i : range) {
203 EditLoopData &value_1 = loose_edge_data[i * 2 + 0];
204 EditLoopData &value_2 = loose_edge_data[i * 2 + 1];
205 const BMEdge &edge = *BM_edge_at_index(&const_cast<BMesh &>(bm), loose_edges[i]);
206 value_1 = {};
207 mesh_render_data_edge_flag(mr, &edge, value_1);
208 value_2 = value_1;
209 mesh_render_data_vert_flag(mr, edge.v1, value_1);
210 mesh_render_data_vert_flag(mr, edge.v2, value_2);
211 }
212 });
213
214 const Span<int> loose_verts = mr.loose_verts;
215 threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
216 for (const int i : range) {
217 loose_vert_data[i] = {};
218 const BMVert &vert = *BM_vert_at_index(&const_cast<BMesh &>(bm), loose_verts[i]);
219 mesh_render_data_vert_flag(mr, &vert, loose_vert_data[i]);
220 }
221 });
222}
223
225{
227 const int size = mr.corners_num + mr.loose_indices_num;
228 GPU_vertbuf_data_alloc(vbo, size);
229 MutableSpan vbo_data = vbo.data<EditLoopData>();
230 if (mr.extract_type == MR_EXTRACT_MESH) {
231 extract_edit_data_mesh(mr, vbo_data);
232 }
233 else {
234 extract_edit_data_bm(mr, vbo_data);
235 }
236}
237
239 const DRWSubdivCache &subdiv_cache,
241{
242 const int corners_num = subdiv_cache.num_subdiv_loops;
243 const int loose_edges_num = mr.loose_edges.size();
244 const int verts_per_edge = subdiv_verts_per_coarse_edge(subdiv_cache);
245 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index, corners_num);
246 const Span<int> subdiv_loop_vert_index = subdiv_cache.verts_orig_index->data<int>();
247 /* NOTE: #subdiv_loop_edge_index already has the origindex layer baked in. */
248 const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
249
250 MutableSpan corners_data = vbo_data.take_front(corners_num);
251 MutableSpan loose_edge_data = vbo_data.slice(corners_num, loose_edges_num * verts_per_edge);
252 MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
253
254 threading::parallel_for(IndexRange(subdiv_cache.num_subdiv_quads), 2048, [&](IndexRange range) {
255 for (const int subdiv_quad : range) {
256 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
257 for (const int subdiv_corner : IndexRange(subdiv_quad * 4, 4)) {
258 EditLoopData &value = corners_data[subdiv_corner];
259 value = {};
260
261 if (const BMFace *bm_face = bm_original_face_get(mr, coarse_face)) {
262 mesh_render_data_face_flag(mr, bm_face, {-1, -1, -1, -1}, value);
263 }
264
265 const int vert_origindex = subdiv_loop_vert_index[subdiv_corner];
266 if (vert_origindex != -1) {
267 if (const BMVert *bm_vert = bm_original_vert_get(mr, vert_origindex)) {
268 mesh_render_data_vert_flag(mr, bm_vert, value);
269 }
270 }
271
272 const int edge_origindex = subdiv_loop_edge_index[subdiv_corner];
273 if (edge_origindex != -1) {
274 if (const BMEdge *bm_edge = BM_edge_at_index(mr.bm, edge_origindex)) {
275 mesh_render_data_edge_flag(mr, bm_edge, value);
276 }
277 }
278 }
279 }
280 });
281
282 const Span<int2> edges = mr.edges;
283 const Span<int> loose_edges = mr.loose_edges;
284 threading::parallel_for(loose_edges.index_range(), 2048, [&](const IndexRange range) {
285 for (const int i : range) {
286 MutableSpan<EditLoopData> data = loose_edge_data.slice(i * verts_per_edge, verts_per_edge);
287 if (const BMEdge *edge = bm_original_edge_get(mr, loose_edges[i])) {
288 EditLoopData value{};
289 mesh_render_data_edge_flag(mr, edge, value);
290 data.fill(value);
291 }
292 else {
293 data.fill({});
294 }
295 const int2 edge = edges[loose_edges[i]];
296 if (const BMVert *bm_vert = bm_original_vert_get(mr, edge[0])) {
297 mesh_render_data_vert_flag(mr, bm_vert, data.first());
298 }
299 if (const BMVert *bm_vert = bm_original_vert_get(mr, edge[1])) {
300 mesh_render_data_vert_flag(mr, bm_vert, data.last());
301 }
302 }
303 });
304
305 const Span<int> loose_verts = mr.loose_verts;
306 threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
307 for (const int i : range) {
308 loose_vert_data[i] = {};
309 if (const BMVert *eve = bm_original_vert_get(mr, loose_verts[i])) {
310 mesh_render_data_vert_flag(mr, eve, loose_vert_data[i]);
311 }
312 }
313 });
314}
315
317 const DRWSubdivCache &subdiv_cache,
319{
320 const int corners_num = subdiv_cache.num_subdiv_loops;
321 const int loose_edges_num = mr.loose_edges.size();
322 const int verts_per_edge = subdiv_verts_per_coarse_edge(subdiv_cache);
323 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index, corners_num);
324 const Span<int> subdiv_loop_vert_index = subdiv_cache.verts_orig_index->data<int>();
325 const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
326
327 MutableSpan corners_data = vbo_data.take_front(corners_num);
328 MutableSpan loose_edge_data = vbo_data.slice(corners_num, loose_edges_num * verts_per_edge);
329 MutableSpan loose_vert_data = vbo_data.take_back(mr.loose_verts.size());
330
331 BMesh &bm = *mr.bm;
332 threading::parallel_for(IndexRange(subdiv_cache.num_subdiv_quads), 2048, [&](IndexRange range) {
333 for (const int subdiv_quad : range) {
334 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
335 const BMFace *bm_face = BM_face_at_index(&bm, coarse_face);
336 for (const int subdiv_corner : IndexRange(subdiv_quad * 4, 4)) {
337 EditLoopData &value = corners_data[subdiv_corner];
338 value = {};
339
340 mesh_render_data_face_flag(mr, bm_face, {-1, -1, -1, -1}, value);
341
342 const int vert_origindex = subdiv_loop_vert_index[subdiv_corner];
343 if (vert_origindex != -1) {
344 const BMVert *bm_vert = BM_vert_at_index(mr.bm, vert_origindex);
345 mesh_render_data_vert_flag(mr, bm_vert, value);
346 }
347
348 const int edge_origindex = subdiv_loop_edge_index[subdiv_corner];
349 if (edge_origindex != -1) {
350 const BMEdge *bm_edge = BM_edge_at_index(mr.bm, edge_origindex);
351 mesh_render_data_edge_flag(mr, bm_edge, value);
352 }
353 }
354 }
355 });
356
357 const Span<int> loose_edges = mr.loose_edges;
358 threading::parallel_for(loose_edges.index_range(), 2048, [&](const IndexRange range) {
359 for (const int i : range) {
360 MutableSpan<EditLoopData> data = loose_edge_data.slice(i * verts_per_edge, verts_per_edge);
361 const BMEdge *edge = BM_edge_at_index(&bm, loose_edges[i]);
362 EditLoopData value{};
363 mesh_render_data_edge_flag(mr, edge, value);
364 data.fill(value);
365 mesh_render_data_vert_flag(mr, edge->v1, data.first());
366 mesh_render_data_vert_flag(mr, edge->v2, data.last());
367 }
368 });
369
370 const Span<int> loose_verts = mr.loose_verts;
371 threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
372 for (const int i : range) {
373 loose_vert_data[i] = {};
374 const BMVert *vert = BM_vert_at_index(&bm, loose_verts[i]);
375 mesh_render_data_vert_flag(mr, vert, loose_vert_data[i]);
376 }
377 });
378}
379
381 const DRWSubdivCache &subdiv_cache,
382 gpu::VertBuf &vbo)
383{
385 const int size = subdiv_full_vbo_size(mr, subdiv_cache);
386 GPU_vertbuf_data_alloc(vbo, size);
387 MutableSpan vbo_data = vbo.data<EditLoopData>();
388 if (mr.extract_type == MR_EXTRACT_MESH) {
389 extract_edit_subdiv_data_mesh(mr, subdiv_cache, vbo_data);
390 }
391 else {
392 extract_edit_subdiv_data_bm(mr, subdiv_cache, vbo_data);
393 }
394}
395
396} // namespace blender::draw
unsigned char uchar
@ FREESTYLE_EDGE_MARK
@ SCE_SELECT_FACE
@ SCE_SELECT_VERTEX
#define GPU_vertbuf_init_with_format(verts, format)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
@ 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)
@ 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)
ATTR_WARN_UNUSED_RESULT BMesh * bm
bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
Definition BLI_span.hh:574
constexpr MutableSpan take_back(const int64_t n) const
Definition BLI_span.hh:641
constexpr MutableSpan take_front(const int64_t n) const
Definition BLI_span.hh:630
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
MutableSpan< T > data()
Extraction of Mesh data into VBO to feed to GPU.
format
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_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)
void extract_edit_data_subdiv(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, gpu::VertBuf &vbo)
static const GPUVertFormat & get_edit_data_format()
void extract_edit_data(const MeshRenderData &mr, gpu::VertBuf &vbo)
T ceil(const T &a)
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:95
BMVert * v1
BMVert * v2
int totface
const ToolSettings * toolsettings
OffsetIndices< int > faces