diff options
Diffstat (limited to 'source/blender/draw/intern/draw_cache_impl_subdivision.cc')
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_subdivision.cc | 118 |
1 files changed, 76 insertions, 42 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index 075e08eb49f..d4b3e392113 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -7,8 +7,10 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "BKE_attribute.hh" #include "BKE_editmesh.h" #include "BKE_mesh.h" +#include "BKE_mesh_mapping.h" #include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_scene.h" @@ -19,8 +21,8 @@ #include "BKE_subdiv_modifier.h" #include "BLI_linklist.h" - #include "BLI_string.h" +#include "BLI_virtual_array.hh" #include "PIL_time.h" @@ -44,6 +46,8 @@ #include "draw_cache_inline.h" #include "mesh_extractors/extract_mesh.hh" +using blender::Span; + extern "C" char datatoc_common_subdiv_custom_data_interp_comp_glsl[]; extern "C" char datatoc_common_subdiv_ibo_lines_comp_glsl[]; extern "C" char datatoc_common_subdiv_ibo_tris_comp_glsl[]; @@ -631,17 +635,9 @@ void draw_subdiv_cache_free(DRWSubdivCache *cache) SUBDIV_COARSE_FACE_FLAG_ACTIVE | SUBDIV_COARSE_FACE_FLAG_HIDDEN) \ << SUBDIV_COARSE_FACE_FLAG_OFFSET) -static uint32_t compute_coarse_face_flag(BMFace *f, BMFace *efa_act) +static uint32_t compute_coarse_face_flag_bm(BMFace *f, BMFace *efa_act) { - if (f == nullptr) { - /* May happen during mapped extraction. */ - return 0; - } - uint32_t flag = 0; - if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) { - flag |= SUBDIV_COARSE_FACE_FLAG_SMOOTH; - } if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { flag |= SUBDIV_COARSE_FACE_FLAG_SELECT; } @@ -651,8 +647,7 @@ static uint32_t compute_coarse_face_flag(BMFace *f, BMFace *efa_act) if (f == efa_act) { flag |= SUBDIV_COARSE_FACE_FLAG_ACTIVE; } - const int loopstart = BM_elem_index_get(f->l_first); - return (uint)(loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET); + return flag; } static void draw_subdiv_cache_extra_coarse_face_data_bm(BMesh *bm, @@ -664,7 +659,12 @@ static void draw_subdiv_cache_extra_coarse_face_data_bm(BMesh *bm, BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { const int index = BM_elem_index_get(f); - flags_data[index] = compute_coarse_face_flag(f, efa_act); + uint32_t flag = compute_coarse_face_flag_bm(f, efa_act); + if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) { + flag |= SUBDIV_COARSE_FACE_FLAG_SMOOTH; + } + const int loopstart = BM_elem_index_get(f->l_first); + flags_data[index] = (uint)(loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET); } } @@ -672,18 +672,19 @@ static void draw_subdiv_cache_extra_coarse_face_data_mesh(const MeshRenderData * Mesh *mesh, uint32_t *flags_data) { - for (int i = 0; i < mesh->totpoly; i++) { + const Span<MPoly> polys = mesh->polys(); + for (const int i : polys.index_range()) { uint32_t flag = 0; - if ((mesh->mpoly[i].flag & ME_SMOOTH) != 0) { + if ((polys[i].flag & ME_SMOOTH) != 0) { flag |= SUBDIV_COARSE_FACE_FLAG_SMOOTH; } - if ((mesh->mpoly[i].flag & ME_FACE_SEL) != 0) { + if (mr->select_poly && mr->select_poly[i]) { flag |= SUBDIV_COARSE_FACE_FLAG_SELECT; } if (mr->hide_poly && mr->hide_poly[i]) { flag |= SUBDIV_COARSE_FACE_FLAG_HIDDEN; } - flags_data[i] = (uint)(mesh->mpoly[i].loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET); + flags_data[i] = (uint)(polys[i].loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET); } } @@ -697,9 +698,16 @@ static void draw_subdiv_cache_extra_coarse_face_data_mapped(Mesh *mesh, return; } - for (int i = 0; i < mesh->totpoly; i++) { + const Span<MPoly> polys = mesh->polys(); + for (const int i : polys.index_range()) { BMFace *f = bm_original_face_get(mr, i); - flags_data[i] = compute_coarse_face_flag(f, mr->efa_act); + /* Selection and hiding from bmesh. */ + uint32_t flag = (f) ? compute_coarse_face_flag_bm(f, mr->efa_act) : 0; + /* Smooth from mesh. */ + if ((polys[i].flag & ME_SMOOTH) != 0) { + flag |= SUBDIV_COARSE_FACE_FLAG_SMOOTH; + } + flags_data[i] = (uint)(polys[i].loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET); } } @@ -724,7 +732,7 @@ static void draw_subdiv_cache_update_extra_coarse_face_data(DRWSubdivCache *cach if (mr->extract_type == MR_EXTRACT_BMESH) { draw_subdiv_cache_extra_coarse_face_data_bm(cache->bm, mr->efa_act, flags_data); } - else if (mr->extract_type == MR_EXTRACT_MAPPED) { + else if (mr->p_origindex != nullptr) { draw_subdiv_cache_extra_coarse_face_data_mapped(mesh, cache->bm, mr, flags_data); } else { @@ -803,15 +811,15 @@ struct DRWCacheBuildingContext { }; static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_context, - const int num_vertices, + const int num_verts, const int num_edges, const int num_loops, - const int num_polygons, + const int num_polys, const int *subdiv_polygon_offset) { /* num_loops does not take into account meshes with only loose geometry, which might be meshes - * used as custom bone shapes, so let's check the num_vertices also. */ - if (num_vertices == 0 && num_loops == 0) { + * used as custom bone shapes, so let's check the num_verts also. */ + if (num_verts == 0 && num_loops == 0) { return false; } @@ -822,12 +830,12 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con if (num_loops != 0) { cache->num_subdiv_edges = (uint)num_edges; cache->num_subdiv_loops = (uint)num_loops; - cache->num_subdiv_verts = (uint)num_vertices; - cache->num_subdiv_quads = (uint)num_polygons; + cache->num_subdiv_verts = (uint)num_verts; + cache->num_subdiv_quads = (uint)num_polys; cache->subdiv_polygon_offset = static_cast<int *>(MEM_dupallocN(subdiv_polygon_offset)); } - cache->may_have_loose_geom = num_vertices != 0 || num_edges != 0; + cache->may_have_loose_geom = num_verts != 0 || num_edges != 0; /* Initialize cache buffers, prefer dynamic usage so we can reuse memory on the host even after * it was sent to the device, since we may use the data while building other buffers on the CPU @@ -878,7 +886,7 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con if (cache->num_subdiv_verts) { ctx->vert_origindex_map = static_cast<int *>( MEM_mallocN(cache->num_subdiv_verts * sizeof(int), "subdiv_vert_origindex_map")); - for (int i = 0; i < num_vertices; i++) { + for (int i = 0; i < num_verts; i++) { ctx->vert_origindex_map[i] = -1; } } @@ -1091,6 +1099,7 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache, } /* Only build polygon related data if we have polygons. */ + const Span<MPoly> polys = mesh_eval->polys(); if (cache->num_subdiv_loops != 0) { /* Build buffers for the PatchMap. */ draw_patch_map_build(&cache->gpu_patch_map, subdiv); @@ -1104,7 +1113,7 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache, GPU_vertbuf_get_data(cache->fdots_patch_coords); for (int i = 0; i < mesh_eval->totpoly; i++) { const int ptex_face_index = cache->face_ptex_offset[i]; - if (mesh_eval->mpoly[i].totloop == 4) { + if (polys[i].totloop == 4) { /* For quads, the center coordinate of the coarse face has `u = v = 0.5`. */ blender_fdots_patch_coords[i] = make_patch_coord(ptex_face_index, 0.5f, 0.5f); } @@ -1117,16 +1126,16 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache, } cache->subdiv_polygon_offset_buffer = draw_subdiv_build_origindex_buffer( - cache->subdiv_polygon_offset, mesh_eval->totpoly); + cache->subdiv_polygon_offset, polys.size()); cache->face_ptex_offset_buffer = draw_subdiv_build_origindex_buffer(cache->face_ptex_offset, - mesh_eval->totpoly + 1); + polys.size() + 1); build_vertex_face_adjacency_maps(cache); } cache->resolution = to_mesh_settings.resolution; - cache->num_coarse_poly = mesh_eval->totpoly; + cache->num_coarse_poly = polys.size(); /* To avoid floating point precision issues when evaluating patches at patch boundaries, * ensure that all loops sharing a vertex use the same patch coordinate. This could cause @@ -1962,17 +1971,19 @@ static void draw_subdiv_cache_ensure_mat_offsets(DRWSubdivCache *cache, return; } + const blender::VArraySpan<int> material_indices = mesh_eval->attributes().lookup_or_default<int>( + "material_index", ATTR_DOMAIN_FACE, 0); + /* Count number of subdivided polygons for each material. */ int *mat_start = static_cast<int *>(MEM_callocN(sizeof(int) * mat_len, "subdiv mat_start")); int *subdiv_polygon_offset = cache->subdiv_polygon_offset; /* TODO: parallel_reduce? */ for (int i = 0; i < mesh_eval->totpoly; i++) { - const MPoly *mpoly = &mesh_eval->mpoly[i]; const int next_offset = (i == mesh_eval->totpoly - 1) ? number_of_quads : subdiv_polygon_offset[i + 1]; const int quad_count = next_offset - subdiv_polygon_offset[i]; - const int mat_index = mpoly->mat_nr; + const int mat_index = material_indices[i]; mat_start[mat_index] += quad_count; } @@ -1991,8 +2002,7 @@ static void draw_subdiv_cache_ensure_mat_offsets(DRWSubdivCache *cache, MEM_mallocN(sizeof(int) * mesh_eval->totpoly, "per_polygon_mat_offset")); for (int i = 0; i < mesh_eval->totpoly; i++) { - const MPoly *mpoly = &mesh_eval->mpoly[i]; - const int mat_index = mpoly->mat_nr; + const int mat_index = material_indices[i]; const int single_material_index = subdiv_polygon_offset[i]; const int material_offset = mat_end[mat_index]; const int next_offset = (i == mesh_eval->totpoly - 1) ? number_of_quads : @@ -2149,9 +2159,20 @@ void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cac int subd_vert_offset = 0; /* Subdivide each loose coarse edge. */ + const Span<MVert> coarse_verts = coarse_mesh->verts(); + const Span<MEdge> coarse_edges = coarse_mesh->edges(); + + int *vert_to_edge_buffer; + MeshElemMap *vert_to_edge_map; + BKE_mesh_vert_edge_map_create(&vert_to_edge_map, + &vert_to_edge_buffer, + coarse_edges.data(), + coarse_mesh->totvert, + coarse_edges.size()); + for (int i = 0; i < coarse_loose_edge_len; i++) { const int coarse_edge_index = cache->loose_geom.edges[i]; - const MEdge *coarse_edge = &coarse_mesh->medge[cache->loose_geom.edges[i]]; + const MEdge *coarse_edge = &coarse_edges[cache->loose_geom.edges[i]]; /* Perform interpolation of each vertex. */ for (int i = 0; i < resolution - 1; i++, subd_edge_offset++) { @@ -2162,8 +2183,13 @@ void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cac DRWSubdivLooseVertex &subd_v1 = loose_subd_verts[subd_vert_offset]; subd_v1.coarse_vertex_index = (i == 0) ? coarse_edge->v1 : -1u; const float u1 = i * inv_resolution_1; - BKE_subdiv_mesh_interpolate_position_on_edge( - coarse_mesh, coarse_edge, is_simple, u1, subd_v1.co); + BKE_subdiv_mesh_interpolate_position_on_edge(coarse_verts.data(), + coarse_edges.data(), + vert_to_edge_map, + coarse_edge_index, + is_simple, + u1, + subd_v1.co); subd_edge.loose_subdiv_v1_index = subd_vert_offset++; @@ -2171,17 +2197,25 @@ void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cac DRWSubdivLooseVertex &subd_v2 = loose_subd_verts[subd_vert_offset]; subd_v2.coarse_vertex_index = ((i + 1) == resolution - 1) ? coarse_edge->v2 : -1u; const float u2 = (i + 1) * inv_resolution_1; - BKE_subdiv_mesh_interpolate_position_on_edge( - coarse_mesh, coarse_edge, is_simple, u2, subd_v2.co); + BKE_subdiv_mesh_interpolate_position_on_edge(coarse_verts.data(), + coarse_edges.data(), + vert_to_edge_map, + coarse_edge_index, + is_simple, + u2, + subd_v2.co); subd_edge.loose_subdiv_v2_index = subd_vert_offset++; } } + MEM_freeN(vert_to_edge_buffer); + MEM_freeN(vert_to_edge_map); + /* Copy the remaining loose_verts. */ for (int i = 0; i < coarse_loose_vert_len; i++) { const int coarse_vertex_index = cache->loose_geom.verts[i]; - const MVert &coarse_vertex = coarse_mesh->mvert[coarse_vertex_index]; + const MVert &coarse_vertex = coarse_verts[coarse_vertex_index]; DRWSubdivLooseVertex &subd_v = loose_subd_verts[subd_vert_offset++]; subd_v.coarse_vertex_index = cache->loose_geom.verts[i]; |