Blender V4.3
extract_mesh_vbo_edituv_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
9#include "BKE_mesh.hh"
10
11#include "extract_mesh.hh"
12
13#include "draw_cache_impl.hh"
14
15#include "draw_subdivision.hh"
16
17namespace blender::draw {
18
19/* ---------------------------------------------------------------------- */
24{
25 static GPUVertFormat format = {0};
26 if (format.attr_len == 0) {
27 /* WARNING: Adjust #EditLoopData struct accordingly. */
30 }
31 return format;
32}
33
35{
36 const BMesh &bm = *mr.bm;
37 const BMUVOffsets offsets = BM_uv_map_get_offsets(&bm);
38 threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
39 for (const int face_index : range) {
40 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
41 const BMLoop *loop = BM_FACE_FIRST_LOOP(&face);
42 for ([[maybe_unused]] const int i : IndexRange(face.len)) {
43 const int index = BM_elem_index_get(loop);
44 EditLoopData &value = vbo_data[index];
45 value = {};
46 mesh_render_data_loop_flag(mr, loop, offsets, value);
47 mesh_render_data_face_flag(mr, &face, offsets, value);
48 mesh_render_data_loop_edge_flag(mr, loop, offsets, value);
49 loop = loop->next;
50 }
51 }
52 });
53}
54
56{
57 const BMesh &bm = *mr.bm;
58 const BMUVOffsets offsets = BM_uv_map_get_offsets(&bm);
59 const OffsetIndices faces = mr.faces;
60 const Span<int> corner_verts = mr.corner_verts;
61 const Span<int> corner_edges = mr.corner_edges;
62 threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) {
63 for (const int face_index : range) {
64 const IndexRange face = faces[face_index];
65 BMFace *face_orig = bm_original_face_get(mr, face_index);
66 if (!face_orig) {
67 vbo_data.slice(face).fill({});
68 continue;
69 }
70 for (const int corner : face) {
71 EditLoopData &value = vbo_data[corner];
72 value = {};
73 BMVert *vert = bm_original_vert_get(mr, corner_verts[corner]);
74 BMEdge *edge = bm_original_edge_get(mr, corner_edges[corner]);
75 if (edge && vert) {
76 /* Loop on an edge endpoint. */
77 BMLoop *l = BM_face_edge_share_loop(face_orig, edge);
78 mesh_render_data_loop_flag(mr, l, offsets, value);
79 mesh_render_data_loop_edge_flag(mr, l, offsets, value);
80 }
81 else {
82 if (edge == nullptr) {
83 /* Find if the loop's vert is not part of an edit edge.
84 * For this, we check if the previous loop was on an edge. */
85 const int corner_prev = bke::mesh::face_corner_prev(face, corner);
86 edge = bm_original_edge_get(mr, corner_edges[corner_prev]);
87 }
88 if (edge) {
89 /* Mapped points on an edge between two edit verts. */
90 BMLoop *l = BM_face_edge_share_loop(face_orig, edge);
91 mesh_render_data_loop_edge_flag(mr, l, offsets, value);
92 }
93 }
94 }
95 }
96 });
97}
98
100{
103 MutableSpan vbo_data = vbo.data<EditLoopData>();
104
105 if (mr.extract_type == MR_EXTRACT_BMESH) {
106 extract_edituv_data_bm(mr, vbo_data);
107 }
108 else {
109 extract_edituv_data_mesh(mr, vbo_data);
110 }
111}
112
114 const BMUVOffsets offsets,
115 const Span<int> subdiv_loop_vert_index,
116 const Span<int> subdiv_loop_edge_index,
117 const int subdiv_quad_index,
118 const BMFace *coarse_quad,
120{
121
122 uint start_loop_idx = subdiv_quad_index * 4;
123 uint end_loop_idx = (subdiv_quad_index + 1) * 4;
124 for (uint i = start_loop_idx; i < end_loop_idx; i++) {
125 const int vert_origindex = subdiv_loop_vert_index[i];
126 int edge_origindex = subdiv_loop_edge_index[i];
127
128 EditLoopData *edit_loop_data = &vbo_data[i];
129 memset(edit_loop_data, 0, sizeof(EditLoopData));
130
131 if (vert_origindex != -1 && edge_origindex != -1) {
132 BMEdge *eed = BM_edge_at_index(mr.bm, edge_origindex);
133 /* Loop on an edge endpoint. */
134 BMLoop *l = BM_face_edge_share_loop(const_cast<BMFace *>(coarse_quad), eed);
135 mesh_render_data_loop_flag(mr, l, offsets, *edit_loop_data);
136 mesh_render_data_loop_edge_flag(mr, l, offsets, *edit_loop_data);
137 }
138 else {
139 if (edge_origindex == -1) {
140 /* Find if the loop's vert is not part of an edit edge.
141 * For this, we check if the previous loop was on an edge. */
142 const uint loop_index_last = (i == start_loop_idx) ? end_loop_idx - 1 : i - 1;
143 edge_origindex = subdiv_loop_edge_index[loop_index_last];
144 }
145 if (edge_origindex != -1) {
146 /* Mapped points on an edge between two edit verts. */
147 BMEdge *eed = BM_edge_at_index(mr.bm, edge_origindex);
148 BMLoop *l = BM_face_edge_share_loop(const_cast<BMFace *>(coarse_quad), eed);
149 mesh_render_data_loop_edge_flag(mr, l, offsets, *edit_loop_data);
150 }
151 }
152
153 mesh_render_data_face_flag(mr, coarse_quad, offsets, *edit_loop_data);
154 }
155}
156
158 const DRWSubdivCache &subdiv_cache,
160{
161 const int corners_num = subdiv_cache.num_subdiv_loops;
162 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index, corners_num);
163 const Span<int> subdiv_loop_vert_index = subdiv_cache.verts_orig_index->data<int>();
164 /* NOTE: #subdiv_loop_edge_index already has the origindex layer baked in. */
165 const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
166
167 const BMUVOffsets offsets = BM_uv_map_get_offsets(mr.bm);
168 threading::parallel_for(IndexRange(subdiv_cache.num_subdiv_quads), 2048, [&](IndexRange range) {
169 for (const int subdiv_quad : range) {
170 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
171 extract_edituv_data_iter_subdiv_bm(mr,
172 offsets,
173 subdiv_loop_vert_index,
174 subdiv_loop_edge_index,
175 subdiv_quad,
176 BM_face_at_index(mr.bm, coarse_face),
177 vbo_data);
178 }
179 });
180}
181
183 const DRWSubdivCache &subdiv_cache,
185{
186 const int corners_num = subdiv_cache.num_subdiv_loops;
187 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index, corners_num);
188 const Span<int> subdiv_loop_vert_index = subdiv_cache.verts_orig_index->data<int>();
189 /* NOTE: #subdiv_loop_edge_index already has the origindex layer baked in. */
190 const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
191
192 const BMUVOffsets offsets = BM_uv_map_get_offsets(mr.bm);
193 threading::parallel_for(IndexRange(subdiv_cache.num_subdiv_quads), 2048, [&](IndexRange range) {
194 for (const int subdiv_quad : range) {
195 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
196 extract_edituv_data_iter_subdiv_bm(mr,
197 offsets,
198 subdiv_loop_vert_index,
199 subdiv_loop_edge_index,
200 subdiv_quad,
201 bm_original_face_get(mr, coarse_face),
202 vbo_data);
203 }
204 });
205}
206
208 const DRWSubdivCache &subdiv_cache,
209 gpu::VertBuf &vbo)
210{
212 const int size = subdiv_cache.num_subdiv_loops;
213 GPU_vertbuf_data_alloc(vbo, size);
214 MutableSpan vbo_data = vbo.data<EditLoopData>();
215
216 if (mr.extract_type == MR_EXTRACT_BMESH) {
217 extract_edituv_subdiv_data_bm(mr, subdiv_cache, vbo_data);
218 }
219 else {
220 extract_edituv_subdiv_data_mesh(mr, subdiv_cache, vbo_data);
221 }
222}
223
224} // namespace blender::draw
unsigned int uint
#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
ATTR_WARN_UNUSED_RESULT BMesh * bm
BLI_INLINE BMEdge * BM_edge_at_index(BMesh *bm, const int index)
BMLoop * BM_face_edge_share_loop(BMFace *f, BMEdge *e)
Return the Loop Shared by Face and Edge.
ATTR_WARN_UNUSED_RESULT const BMLoop * l
BMUVOffsets BM_uv_map_get_offsets(const BMesh *bm)
MutableSpan< T > data()
Extraction of Mesh data into VBO to feed to GPU.
format
void extract_edituv_data(const MeshRenderData &mr, gpu::VertBuf &vbo)
static void extract_edituv_data_bm(const MeshRenderData &mr, MutableSpan< EditLoopData > vbo_data)
static const GPUVertFormat & edituv_data_format()
void extract_edituv_data_subdiv(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, gpu::VertBuf &vbo)
static void extract_edituv_data_mesh(const MeshRenderData &mr, MutableSpan< EditLoopData > vbo_data)
static void extract_edituv_subdiv_data_mesh(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, MutableSpan< EditLoopData > vbo_data)
static void extract_edituv_data_iter_subdiv_bm(const MeshRenderData &mr, const BMUVOffsets offsets, const Span< int > subdiv_loop_vert_index, const Span< int > subdiv_loop_edge_index, const int subdiv_quad_index, const BMFace *coarse_quad, MutableSpan< EditLoopData > vbo_data)
static void extract_edituv_subdiv_data_bm(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, MutableSpan< EditLoopData > vbo_data)
void mesh_render_data_face_flag(const MeshRenderData &mr, const BMFace *efa, const BMUVOffsets offsets, EditLoopData &eattr)
void mesh_render_data_loop_flag(const MeshRenderData &mr, const BMLoop *l, const BMUVOffsets offsets, EditLoopData &eattr)
void mesh_render_data_loop_edge_flag(const MeshRenderData &mr, const BMLoop *l, const BMUVOffsets offsets, EditLoopData &eattr)
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
int totface
OffsetIndices< int > faces