Blender V4.3
extract_mesh_ibo_tris.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_editmesh.hh"
10
11#include "GPU_index_buffer.hh"
12
13#include "extract_mesh.hh"
14
15#include "draw_subdivision.hh"
16
17namespace blender::draw {
18
19static void extract_tris_mesh(const MeshRenderData &mr,
20 const SortedFaceData &face_sorted,
21 gpu::IndexBuf &ibo)
22{
23 const Span<int3> corner_tris = mr.mesh->corner_tris();
24 if (!face_sorted.face_tri_offsets) {
25 /* There are no hidden faces and no reordering is necessary to group triangles with the same
26 * material. The corner indices from #Mesh::corner_tris() can be copied directly to the GPU. */
27 BLI_assert(face_sorted.visible_tris_num == corner_tris.size());
30 corner_tris.cast<uint32_t>().data(),
31 corner_tris.size(),
32 0,
33 mr.corners_num,
34 false);
35 return;
36 }
37
38 const OffsetIndices faces = mr.faces;
39 const Span<bool> hide_poly = mr.hide_poly;
40
41 GPUIndexBufBuilder builder;
44
45 const Span<int> face_tri_offsets = face_sorted.face_tri_offsets->as_span();
46 threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) {
47 for (const int face : range) {
48 if (!hide_poly.is_empty() && hide_poly[face]) {
49 continue;
50 }
51 const IndexRange mesh_range = bke::mesh::face_triangles_range(faces, face);
52 const Span<uint3> mesh_tris = corner_tris.slice(mesh_range).cast<uint3>();
53 MutableSpan<uint3> ibo_tris = data.slice(face_tri_offsets[face], mesh_tris.size());
54 ibo_tris.copy_from(mesh_tris);
55 }
56 });
57
58 GPU_indexbuf_build_in_place_ex(&builder, 0, mr.corners_num, false, &ibo);
59}
60
61static void extract_tris_bmesh(const MeshRenderData &mr,
62 const SortedFaceData &face_sorted,
63 gpu::IndexBuf &ibo)
64{
65 GPUIndexBufBuilder builder;
68
69 BMesh &bm = *mr.bm;
71 const Span<int> face_tri_offsets = *face_sorted.face_tri_offsets;
72 threading::parallel_for(IndexRange(bm.totface), 1024, [&](const IndexRange range) {
73 for (const int face_index : range) {
74 const BMFace &face = *BM_face_at_index(&bm, face_index);
75 if (BM_elem_flag_test(&face, BM_ELEM_HIDDEN)) {
76 continue;
77 }
78 const int loop_index = BM_elem_index_get(BM_FACE_FIRST_LOOP(&face));
79 const IndexRange bm_tris(poly_to_tri_count(face_index, loop_index),
80 bke::mesh::face_triangles_num(face.len));
81 const IndexRange ibo_tris(face_tri_offsets[face_index], bm_tris.size());
82 for (const int i : bm_tris.index_range()) {
83 data[ibo_tris[i]] = uint3(BM_elem_index_get(looptris[bm_tris[i]][0]),
84 BM_elem_index_get(looptris[bm_tris[i]][1]),
85 BM_elem_index_get(looptris[bm_tris[i]][2]));
86 }
87 }
88 });
89
90 GPU_indexbuf_build_in_place_ex(&builder, 0, bm.totloop, false, &ibo);
91}
92
94 const SortedFaceData &face_sorted,
95 MeshBatchCache &cache,
96 gpu::IndexBuf &ibo)
97{
98 /* Create ibo sub-ranges. Always do this to avoid error when the standard surface batch
99 * is created before the surfaces-per-material. */
100 int mat_start = 0;
101 for (int i = 0; i < mr.materials_num; i++) {
102 /* These IBOs have not been queried yet but we create them just in case they are needed
103 * later since they are not tracked by mesh_buffer_cache_create_requested(). */
104 if (cache.tris_per_mat[i] == nullptr) {
106 }
107 const int mat_tri_len = face_sorted.tris_num_by_material[i];
108 /* Multiply by 3 because these are triangle indices. */
109 const int start = mat_start * 3;
110 const int len = mat_tri_len * 3;
112 mat_start += mat_tri_len;
113 }
114}
115
117 const SortedFaceData &face_sorted,
118 MeshBatchCache &cache,
119 gpu::IndexBuf &ibo)
120{
121 if (mr.extract_type == MR_EXTRACT_MESH) {
122 extract_tris_mesh(mr, face_sorted, ibo);
123 }
124 else {
125 extract_tris_bmesh(mr, face_sorted, ibo);
126 }
127
128 if (mr.use_final_mesh && !cache.tris_per_mat.is_empty()) {
129 create_material_subranges(mr, face_sorted, cache, ibo);
130 }
131}
132
133void extract_tris_subdiv(const DRWSubdivCache &subdiv_cache,
134 MeshBatchCache &cache,
135 gpu::IndexBuf &ibo)
136{
137 /* Initialize the index buffer, it was already allocated, it will be filled on the device. */
139
140 if (!cache.tris_per_mat.is_empty()) {
141 for (int i = 0; i < cache.mat_len; i++) {
142 if (cache.tris_per_mat[i] == nullptr) {
144 }
145
146 /* Multiply by 6 since we have 2 triangles per quad. */
147 const int start = subdiv_cache.mat_start[i] * 6;
148 const int len = (subdiv_cache.mat_end[i] - subdiv_cache.mat_start[i]) * 6;
150 }
151 }
152
153 draw_subdiv_build_tris_buffer(subdiv_cache, &ibo, cache.mat_len);
154}
155
156} // namespace blender::draw
#define BLI_assert(a)
Definition BLI_assert.h:50
void GPU_indexbuf_build_in_place_ex(GPUIndexBufBuilder *builder, uint index_min, uint index_max, bool uses_restart_indices, blender::gpu::IndexBuf *elem)
blender::MutableSpan< uint32_t > GPU_indexbuf_get_data(GPUIndexBufBuilder *)
void GPU_indexbuf_create_subrange_in_place(blender::gpu::IndexBuf *elem, blender::gpu::IndexBuf *elem_src, uint start, uint length)
void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint vertex_len)
blender::gpu::IndexBuf * GPU_indexbuf_calloc()
void GPU_indexbuf_build_in_place_from_memory(blender::gpu::IndexBuf *ibo, GPUPrimType prim_type, const uint32_t *data, int32_t data_len, int32_t index_min, int32_t index_max, bool uses_restart_indices)
void GPU_indexbuf_init_build_on_device(blender::gpu::IndexBuf *elem, uint index_len)
@ GPU_PRIM_TRIS
ATTR_WARN_UNUSED_RESULT BMesh * bm
constexpr MutableSpan< NewT > cast() const
Definition BLI_span.hh:736
Span< NewT > constexpr cast() const
Definition BLI_span.hh:419
constexpr int64_t size() const
Definition BLI_span.hh:253
int len
Extraction of Mesh data into VBO to feed to GPU.
void extract_tris(const MeshRenderData &mr, const SortedFaceData &face_sorted, MeshBatchCache &cache, gpu::IndexBuf &ibo)
void extract_tris_subdiv(const DRWSubdivCache &subdiv_cache, MeshBatchCache &cache, gpu::IndexBuf &ibo)
void draw_subdiv_build_tris_buffer(const DRWSubdivCache &cache, gpu::IndexBuf *subdiv_tris, const int material_count)
static void extract_tris_mesh(const MeshRenderData &mr, const SortedFaceData &face_sorted, gpu::IndexBuf &ibo)
static void create_material_subranges(const MeshRenderData &mr, const SortedFaceData &face_sorted, MeshBatchCache &cache, gpu::IndexBuf &ibo)
static void extract_tris_bmesh(const MeshRenderData &mr, const SortedFaceData &face_sorted, gpu::IndexBuf &ibo)
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
unsigned int uint32_t
Definition stdint.h:80
blender::Array< std::array< BMLoop *, 3 > > looptris
int totloop
int totface
Array< gpu::IndexBuf * > tris_per_mat
OffsetIndices< int > faces
std::optional< Array< int > > face_tri_offsets