Blender V5.0
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
8
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/* ---------------------------------------------------------------------- */
22
24{
25 static const GPUVertFormat format = []() {
27 /* WARNING: Adjust #EditLoopData struct accordingly. */
28 GPU_vertformat_attr_add(&format, "data", gpu::VertAttrType::UINT_8_8_8_8);
30 return format;
31 }();
32 return format;
33}
34
36{
37 const BMesh &bm = *mr.bm;
38 const BMUVOffsets offsets = BM_uv_map_offsets_get(&bm);
39 threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
40 for (const int face_index : range) {
41 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
42 EditLoopData face_value = {};
43 mesh_render_data_face_flag(mr, &face, offsets, face_value);
44 const BMLoop *loop = BM_FACE_FIRST_LOOP(&face);
45 for ([[maybe_unused]] const int i : IndexRange(face.len)) {
46 const int index = BM_elem_index_get(loop);
47 EditLoopData &value = vbo_data[index];
48 value = face_value;
49 mesh_render_data_loop_flag(mr, loop, offsets, value);
50 mesh_render_data_loop_edge_flag(mr, loop, offsets, value);
51 loop = loop->next;
52 }
53 }
54 });
55}
56
58{
59 const BMesh &bm = *mr.bm;
60 const BMUVOffsets offsets = BM_uv_map_offsets_get(&bm);
61 const OffsetIndices faces = mr.faces;
62 const Span<int> corner_verts = mr.corner_verts;
63 const Span<int> corner_edges = mr.corner_edges;
64 threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) {
65 for (const int face_index : range) {
66 const IndexRange face = faces[face_index];
67 BMFace *face_orig = bm_original_face_get(mr, face_index);
68 if (!face_orig) {
69 vbo_data.slice(face).fill({});
70 continue;
71 }
72 for (const int corner : face) {
73 EditLoopData &value = vbo_data[corner];
74 value = {};
75 BMVert *vert = bm_original_vert_get(mr, corner_verts[corner]);
76 BMEdge *edge = bm_original_edge_get(mr, corner_edges[corner]);
77 if (edge && vert) {
78 /* Loop on an edge endpoint. */
79 BMLoop *l = BM_face_edge_share_loop(face_orig, edge);
80 mesh_render_data_loop_flag(mr, l, offsets, value);
81 mesh_render_data_loop_edge_flag(mr, l, offsets, value);
82 }
83 else {
84 if (edge == nullptr) {
85 /* Find if the loop's vert is not part of an edit edge.
86 * For this, we check if the previous loop was on an edge. */
87 const int corner_prev = bke::mesh::face_corner_prev(face, corner);
88 edge = bm_original_edge_get(mr, corner_edges[corner_prev]);
89 }
90 if (edge) {
91 /* Mapped points on an edge between two edit verts. */
92 BMLoop *l = BM_face_edge_share_loop(face_orig, edge);
93 mesh_render_data_loop_edge_flag(mr, l, offsets, value);
94 }
95 }
96 }
97 }
98 });
99}
100
102{
105 MutableSpan vbo_data = vbo->data<EditLoopData>();
106
108 extract_edituv_data_bm(mr, vbo_data);
109 }
110 else {
111 extract_edituv_data_mesh(mr, vbo_data);
112 }
113 return vbo;
114}
115
117 const BMUVOffsets &offsets,
118 const Span<int> subdiv_loop_vert_index,
119 const Span<int> subdiv_loop_edge_index,
120 const int subdiv_quad_index,
121 const BMFace *coarse_quad,
123{
124
125 uint start_loop_idx = subdiv_quad_index * 4;
126 uint end_loop_idx = (subdiv_quad_index + 1) * 4;
127 EditLoopData edit_loop_data_face = {};
128 mesh_render_data_face_flag(mr, coarse_quad, offsets, edit_loop_data_face);
129 for (uint i = start_loop_idx; i < end_loop_idx; i++) {
130 const int vert_origindex = subdiv_loop_vert_index[i];
131 int edge_origindex = subdiv_loop_edge_index[i];
132
133 EditLoopData *edit_loop_data = &vbo_data[i];
134 *edit_loop_data = edit_loop_data_face;
135
136 if (vert_origindex != -1 && edge_origindex != -1) {
137 BMEdge *eed = BM_edge_at_index(mr.bm, edge_origindex);
138 /* Loop on an edge endpoint. */
139 BMLoop *l = BM_face_edge_share_loop(const_cast<BMFace *>(coarse_quad), eed);
140 mesh_render_data_loop_flag(mr, l, offsets, *edit_loop_data);
141 mesh_render_data_loop_edge_flag(mr, l, offsets, *edit_loop_data);
142 }
143 else {
144 if (edge_origindex == -1) {
145 /* Find if the loop's vert is not part of an edit edge.
146 * For this, we check if the previous loop was on an edge. */
147 const uint loop_index_last = (i == start_loop_idx) ? end_loop_idx - 1 : i - 1;
148 edge_origindex = subdiv_loop_edge_index[loop_index_last];
149 }
150 if (edge_origindex != -1) {
151 /* Mapped points on an edge between two edit verts. */
152 BMEdge *eed = BM_edge_at_index(mr.bm, edge_origindex);
153 BMLoop *l = BM_face_edge_share_loop(const_cast<BMFace *>(coarse_quad), eed);
154 mesh_render_data_loop_edge_flag(mr, l, offsets, *edit_loop_data);
155 }
156 }
157 }
158}
159
161 const DRWSubdivCache &subdiv_cache,
163{
164 const int corners_num = subdiv_cache.num_subdiv_loops;
165 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index, corners_num);
166 const Span<int> subdiv_loop_vert_index = subdiv_cache.verts_orig_index->data<int>();
167 /* NOTE: #subdiv_loop_edge_index already has the origindex layer baked in. */
168 const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
169
170 const BMUVOffsets offsets = BM_uv_map_offsets_get(mr.bm);
171 threading::parallel_for(IndexRange(subdiv_cache.num_subdiv_quads), 2048, [&](IndexRange range) {
172 for (const int subdiv_quad : range) {
173 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
174 extract_edituv_data_iter_subdiv_bm(mr,
175 offsets,
176 subdiv_loop_vert_index,
177 subdiv_loop_edge_index,
178 subdiv_quad,
179 BM_face_at_index(mr.bm, coarse_face),
180 vbo_data);
181 }
182 });
183}
184
186 const DRWSubdivCache &subdiv_cache,
188{
189 const int corners_num = subdiv_cache.num_subdiv_loops;
190 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index, corners_num);
191 const Span<int> subdiv_loop_vert_index = subdiv_cache.verts_orig_index->data<int>();
192 /* NOTE: #subdiv_loop_edge_index already has the origindex layer baked in. */
193 const Span<int> subdiv_loop_edge_index = subdiv_cache.edges_orig_index->data<int>();
194
195 const BMUVOffsets offsets = BM_uv_map_offsets_get(mr.bm);
196 threading::parallel_for(IndexRange(subdiv_cache.num_subdiv_quads), 2048, [&](IndexRange range) {
197 for (const int subdiv_quad : range) {
198 const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
199 extract_edituv_data_iter_subdiv_bm(mr,
200 offsets,
201 subdiv_loop_vert_index,
202 subdiv_loop_edge_index,
203 subdiv_quad,
204 bm_original_face_get(mr, coarse_face),
205 vbo_data);
206 }
207 });
208}
209
211 const DRWSubdivCache &subdiv_cache)
212{
214 const int size = subdiv_cache.num_subdiv_loops;
216 MutableSpan vbo_data = vbo->data<EditLoopData>();
217
219 extract_edituv_subdiv_data_bm(mr, subdiv_cache, vbo_data);
220 }
221 else {
222 extract_edituv_subdiv_data_mesh(mr, subdiv_cache, vbo_data);
223 }
224 return vbo;
225}
226
227} // namespace blender::draw
unsigned int uint
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)
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_offsets_get(const BMesh *bm)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
constexpr T * data() const
Definition BLI_span.hh:539
MutableSpan< T > data()
Extraction of Mesh data into VBO to feed to GPU.
format
static char faces[256]
static void extract_edituv_data_bm(const MeshRenderData &mr, MutableSpan< EditLoopData > vbo_data)
void mesh_render_data_loop_flag(const MeshRenderData &mr, const BMLoop *l, const BMUVOffsets &offsets, EditLoopData &eattr)
static const GPUVertFormat & edituv_data_format()
static void extract_edituv_data_mesh(const MeshRenderData &mr, MutableSpan< EditLoopData > vbo_data)
void mesh_render_data_face_flag(const MeshRenderData &mr, const BMFace *efa, const BMUVOffsets &offsets, EditLoopData &eattr)
static void extract_edituv_subdiv_data_mesh(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, MutableSpan< EditLoopData > vbo_data)
void mesh_render_data_loop_edge_flag(const MeshRenderData &mr, const BMLoop *l, const BMUVOffsets &offsets, EditLoopData &eattr)
gpu::VertBufPtr extract_edituv_data(const MeshRenderData &mr)
static void extract_edituv_subdiv_data_bm(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)
gpu::VertBufPtr extract_edituv_data_subdiv(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache)
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
OffsetIndices< int > faces
i
Definition text_draw.cc:230