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 | 202 |
1 files changed, 120 insertions, 82 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index cde2b59ea23..6a9e6c126e9 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[]; @@ -357,14 +361,14 @@ static GPUVertFormat *get_subdiv_vertex_format() struct CompressedPatchCoord { int ptex_face_index; /* UV coordinate encoded as u << 16 | v, where u and v are quantized on 16-bits. */ - unsigned int encoded_uv; + uint encoded_uv; }; MINLINE CompressedPatchCoord make_patch_coord(int ptex_face_index, float u, float v) { CompressedPatchCoord patch_coord = { ptex_face_index, - (static_cast<unsigned int>(u * 65535.0f) << 16) | static_cast<unsigned int>(v * 65535.0f), + (uint(u * 65535.0f) << 16) | uint(v * 65535.0f), }; return patch_coord; } @@ -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,24 +659,32 @@ 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); } } -static void draw_subdiv_cache_extra_coarse_face_data_mesh(Mesh *mesh, uint32_t *flags_data) +static void draw_subdiv_cache_extra_coarse_face_data_mesh(const MeshRenderData *mr, + 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 ((mesh->mpoly[i].flag & ME_HIDE) != 0) { + 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); } } @@ -691,13 +694,20 @@ static void draw_subdiv_cache_extra_coarse_face_data_mapped(Mesh *mesh, uint32_t *flags_data) { if (bm == nullptr) { - draw_subdiv_cache_extra_coarse_face_data_mesh(mesh, flags_data); + draw_subdiv_cache_extra_coarse_face_data_mesh(mr, mesh, flags_data); 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); } } @@ -717,16 +727,16 @@ static void draw_subdiv_cache_update_extra_coarse_face_data(DRWSubdivCache *cach mesh->totpoly); } - uint32_t *flags_data = (uint32_t *)(GPU_vertbuf_get_data(cache->extra_coarse_face_data)); + uint32_t *flags_data = (uint32_t *)GPU_vertbuf_get_data(cache->extra_coarse_face_data); 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 { - draw_subdiv_cache_extra_coarse_face_data_mesh(mesh, flags_data); + draw_subdiv_cache_extra_coarse_face_data_mesh(mr, mesh, flags_data); } /* Make sure updated data is re-uploaded. */ @@ -801,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; } @@ -818,14 +828,14 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con /* Set topology information only if we have loops. */ 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_edges = uint(num_edges); + cache->num_subdiv_loops = uint(num_loops); + 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 @@ -876,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; } } @@ -893,13 +903,13 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con } static void draw_subdiv_vertex_corner_cb(const SubdivForeachContext *foreach_context, - void *UNUSED(tls), - const int UNUSED(ptex_face_index), - const float UNUSED(u), - const float UNUSED(v), + void * /*tls*/, + const int /*ptex_face_index*/, + const float /*u*/, + const float /*v*/, const int coarse_vertex_index, - const int UNUSED(coarse_poly_index), - const int UNUSED(coarse_corner), + const int /*coarse_poly_index*/, + const int /*coarse_corner*/, const int subdiv_vertex_index) { BLI_assert(coarse_vertex_index != ORIGINDEX_NONE); @@ -907,26 +917,26 @@ static void draw_subdiv_vertex_corner_cb(const SubdivForeachContext *foreach_con ctx->vert_origindex_map[subdiv_vertex_index] = coarse_vertex_index; } -static void draw_subdiv_vertex_edge_cb(const SubdivForeachContext *UNUSED(foreach_context), - void *UNUSED(tls_v), - const int UNUSED(ptex_face_index), - const float UNUSED(u), - const float UNUSED(v), - const int UNUSED(coarse_edge_index), - const int UNUSED(coarse_poly_index), - const int UNUSED(coarse_corner), - const int UNUSED(subdiv_vertex_index)) +static void draw_subdiv_vertex_edge_cb(const SubdivForeachContext * /*foreach_context*/, + void * /*tls_v*/, + const int /*ptex_face_index*/, + const float /*u*/, + const float /*v*/, + const int /*coarse_edge_index*/, + const int /*coarse_poly_index*/, + const int /*coarse_corner*/, + const int /*subdiv_vertex_index*/) { /* Required if SubdivForeachContext.vertex_corner is also set. */ } static void draw_subdiv_edge_cb(const SubdivForeachContext *foreach_context, - void *UNUSED(tls), + void * /*tls*/, const int coarse_edge_index, const int subdiv_edge_index, - const bool UNUSED(is_loose), - const int UNUSED(subdiv_v1), - const int UNUSED(subdiv_v2)) + const bool /*is_loose*/, + const int /*subdiv_v1*/, + const int /*subdiv_v2*/) { DRWCacheBuildingContext *ctx = (DRWCacheBuildingContext *)(foreach_context->user_data); @@ -946,13 +956,13 @@ static void draw_subdiv_edge_cb(const SubdivForeachContext *foreach_context, } static void draw_subdiv_loop_cb(const SubdivForeachContext *foreach_context, - void *UNUSED(tls_v), + void * /*tls_v*/, const int ptex_face_index, const float u, const float v, - const int UNUSED(coarse_loop_index), + const int /*coarse_loop_index*/, const int coarse_poly_index, - const int UNUSED(coarse_corner), + const int /*coarse_corner*/, const int subdiv_loop_index, const int subdiv_vertex_index, const int subdiv_edge_index) @@ -1089,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); @@ -1102,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); } @@ -1115,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 @@ -1284,7 +1295,7 @@ static void drw_subdiv_compute_dispatch(const DRWSubdivCache *cache, uint total_dispatch_size, const bool has_sculpt_mask = false) { - const uint max_res_x = static_cast<uint>(GPU_max_work_group_count(0)); + const uint max_res_x = uint(GPU_max_work_group_count(0)); const uint dispatch_size = get_dispatch_size(total_dispatch_size); uint dispatch_rx = dispatch_size; @@ -1307,7 +1318,7 @@ static void drw_subdiv_compute_dispatch(const DRWSubdivCache *cache, /* X and Y dimensions may have different limits so the above computation may not be right, but * even with the standard 64k minimum on all dimensions we still have a lot of room. Therefore, * we presume it all fits. */ - BLI_assert(dispatch_ry < static_cast<uint>(GPU_max_work_group_count(1))); + BLI_assert(dispatch_ry < uint(GPU_max_work_group_count(1))); draw_subdiv_ubo_update_and_bind( cache, shader, src_offset, dst_offset, total_dispatch_size, has_sculpt_mask); @@ -1960,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; } @@ -1989,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 : @@ -2019,11 +2031,12 @@ static bool draw_subdiv_create_requested_buffers(Object *ob, const float obmat[4][4], const bool do_final, const bool do_uvedit, + const bool do_cage, const ToolSettings *ts, const bool use_hide, OpenSubdiv_EvaluatorCache *evaluator_cache) { - SubsurfRuntimeData *runtime_data = mesh->runtime.subsurf_runtime_data; + SubsurfRuntimeData *runtime_data = mesh->runtime->subsurf_runtime_data; BLI_assert(runtime_data && runtime_data->has_gpu_subdiv); if (runtime_data->settings.level == 0) { @@ -2062,9 +2075,8 @@ static bool draw_subdiv_create_requested_buffers(Object *ob, return false; } - /* Edges which do not come from coarse edges should not be drawn in edit mode, only in object - * mode when optimal display in turned off. */ - const bool optimal_display = runtime_data->use_optimal_display || is_editmode; + /* Edges which do not come from coarse edges should not be drawn in edit cage mode. */ + const bool optimal_display = runtime_data->use_optimal_display || (is_editmode && !do_cage); draw_cache->bm = bm; draw_cache->mesh = mesh_eval; @@ -2125,7 +2137,7 @@ void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cac const bool is_simple = subdiv_cache->subdiv->settings.is_simple; const int resolution = subdiv_cache->resolution; const int resolution_1 = resolution - 1; - const float inv_resolution_1 = 1.0f / (float)resolution_1; + const float inv_resolution_1 = 1.0f / float(resolution_1); const int num_subdiv_vertices_per_coarse_edge = resolution - 2; const int num_subdivided_edge = coarse_loose_edge_len * @@ -2147,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++) { @@ -2160,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++; @@ -2169,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]; @@ -2195,13 +2231,13 @@ void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cac blender::Span<DRWSubdivLooseEdge> draw_subdiv_cache_get_loose_edges(const DRWSubdivCache *cache) { - return {cache->loose_geom.edges, static_cast<int64_t>(cache->loose_geom.edge_len)}; + return {cache->loose_geom.edges, int64_t(cache->loose_geom.edge_len)}; } blender::Span<DRWSubdivLooseVertex> draw_subdiv_cache_get_loose_verts(const DRWSubdivCache *cache) { return {cache->loose_geom.verts + cache->loose_geom.edge_len * 2, - static_cast<int64_t>(cache->loose_geom.vert_len)}; + int64_t(cache->loose_geom.vert_len)}; } static OpenSubdiv_EvaluatorCache *g_evaluator_cache = nullptr; @@ -2216,6 +2252,7 @@ void DRW_create_subdivision(Object *ob, const float obmat[4][4], const bool do_final, const bool do_uvedit, + const bool do_cage, const ToolSettings *ts, const bool use_hide) { @@ -2239,6 +2276,7 @@ void DRW_create_subdivision(Object *ob, obmat, do_final, do_uvedit, + do_cage, ts, use_hide, g_evaluator_cache)) { |