diff options
author | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-03-02 17:22:19 +0300 |
---|---|---|
committer | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-03-02 17:22:19 +0300 |
commit | 3a0df7d37bcf55b2b0f9a070d5c80f908e46ebc4 (patch) | |
tree | 01e256d9f853dbed48217c0ce95b8cc2946a3031 /source | |
parent | 47396ea81edba585cc69c5760703cde727bc08a6 (diff) | |
parent | 6883c47bb5930be5a95d1c2e8e06fce2d3b68681 (diff) |
Merge remote-tracking branch 'origin/blender-v3.1-release'
Diffstat (limited to 'source')
13 files changed, 525 insertions, 216 deletions
diff --git a/source/blender/blenkernel/BKE_subdiv_mesh.h b/source/blender/blenkernel/BKE_subdiv_mesh.h index ede7ae60dc9..b24db517143 100644 --- a/source/blender/blenkernel/BKE_subdiv_mesh.h +++ b/source/blender/blenkernel/BKE_subdiv_mesh.h @@ -14,6 +14,7 @@ extern "C" { #endif struct Mesh; +struct MEdge; struct Subdiv; typedef struct SubdivToMeshSettings { @@ -33,6 +34,14 @@ struct Mesh *BKE_subdiv_to_mesh(struct Subdiv *subdiv, const SubdivToMeshSettings *settings, const struct Mesh *coarse_mesh); +/* Interpolate a position along the `coarse_edge` at the relative `u` coordinate. If `is_simple` is + * false, this will perform a B-Spline interpolation using the edge neighbors, otherwise a linear + * interpolation will be done base on the edge vertices. */ +void BKE_subdiv_mesh_interpolate_position_on_edge(const struct Mesh *coarse_mesh, + const struct MEdge *coarse_edge, + bool is_simple, + float u, + float pos_r[3]); #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c index 50135110a64..953f040fa0d 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.c +++ b/source/blender/blenkernel/intern/subdiv_mesh.c @@ -930,11 +930,10 @@ static void subdiv_mesh_vertex_loose(const SubdivForeachContext *foreach_context /* Get neighbor edges of the given one. * - neighbors[0] is an edge adjacent to edge->v1. * - neighbors[1] is an edge adjacent to edge->v2. */ -static void find_edge_neighbors(const SubdivMeshContext *ctx, +static void find_edge_neighbors(const Mesh *coarse_mesh, const MEdge *edge, const MEdge *neighbors[2]) { - const Mesh *coarse_mesh = ctx->coarse_mesh; const MEdge *coarse_medge = coarse_mesh->medge; neighbors[0] = NULL; neighbors[1] = NULL; @@ -964,12 +963,11 @@ static void find_edge_neighbors(const SubdivMeshContext *ctx, } } -static void points_for_loose_edges_interpolation_get(SubdivMeshContext *ctx, +static void points_for_loose_edges_interpolation_get(const Mesh *coarse_mesh, const MEdge *coarse_edge, const MEdge *neighbors[2], float points_r[4][3]) { - const Mesh *coarse_mesh = ctx->coarse_mesh; const MVert *coarse_mvert = coarse_mesh->mvert; /* Middle points corresponds to the edge. */ copy_v3_v3(points_r[1], coarse_mvert[coarse_edge->v1].co); @@ -1002,6 +1000,30 @@ static void points_for_loose_edges_interpolation_get(SubdivMeshContext *ctx, } } +void BKE_subdiv_mesh_interpolate_position_on_edge(const Mesh *coarse_mesh, + const MEdge *coarse_edge, + const bool is_simple, + const float u, + float pos_r[3]) +{ + if (is_simple) { + const MVert *coarse_mvert = coarse_mesh->mvert; + const MVert *vert_1 = &coarse_mvert[coarse_edge->v1]; + const MVert *vert_2 = &coarse_mvert[coarse_edge->v2]; + interp_v3_v3v3(pos_r, vert_1->co, vert_2->co, u); + } + else { + /* Find neighbors of the coarse edge. */ + const MEdge *neighbors[2]; + find_edge_neighbors(coarse_mesh, coarse_edge, neighbors); + float points[4][3]; + points_for_loose_edges_interpolation_get(coarse_mesh, coarse_edge, neighbors, points); + float weights[4]; + key_curve_position_weights(u, weights, KEY_BSPLINE); + interp_v3_v3v3v3v3(pos_r, points[0], points[1], points[2], points[3], weights); + } +} + static void subdiv_mesh_vertex_of_loose_edge_interpolate(SubdivMeshContext *ctx, const MEdge *coarse_edge, const float u, @@ -1038,9 +1060,6 @@ static void subdiv_mesh_vertex_of_loose_edge(const struct SubdivForeachContext * Mesh *subdiv_mesh = ctx->subdiv_mesh; MVert *subdiv_mvert = subdiv_mesh->mvert; const bool is_simple = ctx->subdiv->settings.is_simple; - /* Find neighbors of the current loose edge. */ - const MEdge *neighbors[2]; - find_edge_neighbors(ctx, coarse_edge, neighbors); /* Interpolate custom data when not an end point. * This data has already been copied from the original vertex by #subdiv_mesh_vertex_loose. */ if (!ELEM(u, 0.0, 1.0)) { @@ -1048,19 +1067,8 @@ static void subdiv_mesh_vertex_of_loose_edge(const struct SubdivForeachContext * } /* Interpolate coordinate. */ MVert *subdiv_vertex = &subdiv_mvert[subdiv_vertex_index]; - if (is_simple) { - const MVert *coarse_mvert = coarse_mesh->mvert; - const MVert *vert_1 = &coarse_mvert[coarse_edge->v1]; - const MVert *vert_2 = &coarse_mvert[coarse_edge->v2]; - interp_v3_v3v3(subdiv_vertex->co, vert_1->co, vert_2->co, u); - } - else { - float points[4][3]; - points_for_loose_edges_interpolation_get(ctx, coarse_edge, neighbors, points); - float weights[4]; - key_curve_position_weights(u, weights, KEY_BSPLINE); - interp_v3_v3v3v3v3(subdiv_vertex->co, points[0], points[1], points[2], points[3], weights); - } + BKE_subdiv_mesh_interpolate_position_on_edge( + coarse_mesh, coarse_edge, is_simple, u, subdiv_vertex->co); /* Reset flags and such. */ subdiv_vertex->flag = 0; /* TODO(sergey): This matches old behavior, but we can as well interpolate diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index 49e51d77f7b..dea3fa9b75a 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -806,7 +806,27 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache, extractors.append(&extract_fdots_pos); } - EXTRACT_ADD_REQUESTED(ibo, lines); + if (DRW_ibo_requested(mbuflist->ibo.lines_loose)) { + /* `ibo.lines_loose` require the `ibo.lines` buffer. */ + if (mbuflist->ibo.lines == nullptr) { + DRW_ibo_request(nullptr, &mbuflist->ibo.lines); + } + const MeshExtract *extractor = DRW_ibo_requested(mbuflist->ibo.lines) ? + &extract_lines_with_lines_loose : + &extract_lines_loose_only; + extractors.append(extractor); + } + else if (DRW_ibo_requested(mbuflist->ibo.lines)) { + const MeshExtract *extractor; + if (mbuflist->ibo.lines_loose != nullptr) { + /* Update `ibo.lines_loose` as it depends on `ibo.lines`. */ + extractor = &extract_lines_with_lines_loose; + } + else { + extractor = &extract_lines; + } + extractors.append(extractor); + } EXTRACT_ADD_REQUESTED(ibo, edituv_points); EXTRACT_ADD_REQUESTED(ibo, edituv_tris); EXTRACT_ADD_REQUESTED(ibo, edituv_lines); @@ -835,6 +855,7 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache, mesh_render_data_update_looptris(mr, MR_ITER_LOOPTRI, MR_DATA_LOOPTRI); mesh_render_data_update_loose_geom(mr, mbc, MR_ITER_LEDGE | MR_ITER_LVERT, MR_DATA_LOOSE_GEOM); + DRW_subdivide_loose_geom(subdiv_cache, mbc); void *data_stack = MEM_mallocN(extractors.data_size_total(), __func__); uint32_t data_offset = 0; @@ -868,7 +889,7 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache, } if (extractor->iter_loose_geom_subdiv) { - extractor->iter_loose_geom_subdiv(subdiv_cache, mr, &mbc->loose_geom, buffer, data); + extractor->iter_loose_geom_subdiv(subdiv_cache, mr, buffer, data); } if (extractor->finish_subdiv) { diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index 5d99478476c..8682a15feba 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -518,6 +518,11 @@ static void draw_patch_map_free(DRWPatchMap *gpu_patch_map) /** \name DRWSubdivCache * \{ */ +static bool draw_subdiv_cache_need_polygon_data(const DRWSubdivCache *cache) +{ + return cache->subdiv && cache->subdiv->evaluator && cache->num_subdiv_loops != 0; +} + static void draw_subdiv_cache_free_material_data(DRWSubdivCache *cache) { GPU_VERTBUF_DISCARD_SAFE(cache->polygon_mat_offset); @@ -550,6 +555,7 @@ void draw_subdiv_cache_free(DRWSubdivCache *cache) cache->num_subdiv_triangles = 0; cache->num_coarse_poly = 0; cache->num_subdiv_quads = 0; + cache->may_have_loose_geom = false; draw_subdiv_free_edit_mode_cache(cache); draw_subdiv_cache_free_material_data(cache); draw_patch_map_free(&cache->gpu_patch_map); @@ -557,6 +563,11 @@ void draw_subdiv_cache_free(DRWSubdivCache *cache) GPU_uniformbuf_free(cache->ubo); cache->ubo = nullptr; } + MEM_SAFE_FREE(cache->loose_geom.edges); + MEM_SAFE_FREE(cache->loose_geom.verts); + cache->loose_geom.edge_len = 0; + cache->loose_geom.vert_len = 0; + cache->loose_geom.loop_len = 0; } /* Flags used in #DRWSubdivCache.extra_coarse_face_data. The flags are packed in the upper bits of @@ -729,19 +740,25 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con const int num_polygons, const int *subdiv_polygon_offset) { - if (num_loops == 0) { + /* 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) { return false; } DRWCacheBuildingContext *ctx = (DRWCacheBuildingContext *)(foreach_context->user_data); DRWSubdivCache *cache = ctx->cache; - /* Set topology information. */ - 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->subdiv_polygon_offset = static_cast<int *>(MEM_dupallocN(subdiv_polygon_offset)); + /* 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->subdiv_polygon_offset = static_cast<int *>(MEM_dupallocN(subdiv_polygon_offset)); + } + + cache->may_have_loose_geom = num_vertices != 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 @@ -780,16 +797,20 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con ctx->e_origindex = static_cast<int *>( CustomData_get_layer(&ctx->coarse_mesh->edata, CD_ORIGINDEX)); - 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++) { - ctx->vert_origindex_map[i] = -1; + 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++) { + ctx->vert_origindex_map[i] = -1; + } } - ctx->edge_origindex_map = static_cast<int *>( - MEM_mallocN(cache->num_subdiv_edges * sizeof(int), "subdiv_edge_origindex_map")); - for (int i = 0; i < num_edges; i++) { - ctx->edge_origindex_map[i] = -1; + if (cache->num_subdiv_edges) { + ctx->edge_origindex_map = static_cast<int *>( + MEM_mallocN(cache->num_subdiv_edges * sizeof(int), "subdiv_edge_origindex_map")); + for (int i = 0; i < num_edges; i++) { + ctx->edge_origindex_map[i] = -1; + } } return true; @@ -833,6 +854,10 @@ static void draw_subdiv_edge_cb(const SubdivForeachContext *foreach_context, { DRWCacheBuildingContext *ctx = (DRWCacheBuildingContext *)(foreach_context->user_data); + if (!ctx->edge_origindex_map) { + return; + } + int coarse_index = coarse_edge_index; if (coarse_index != -1) { @@ -983,7 +1008,8 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache, cache_building_context.cache = cache; do_subdiv_traversal(&cache_building_context, subdiv); - if (cache->num_subdiv_loops == 0) { + if (cache->num_subdiv_loops == 0 && cache->num_subdiv_verts == 0 && + !cache->may_have_loose_geom) { /* Either the traversal failed, or we have an empty mesh, either way we cannot go any further. * The subdiv_polygon_offset cannot then be reliably stored in the cache, so free it directly. */ @@ -991,44 +1017,47 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache, return false; } - /* Build buffers for the PatchMap. */ - draw_patch_map_build(&cache->gpu_patch_map, subdiv); + /* Only build polygon related data if we have polygons. */ + if (cache->num_subdiv_loops != 0) { + /* Build buffers for the PatchMap. */ + draw_patch_map_build(&cache->gpu_patch_map, subdiv); + + cache->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv); + + /* Build patch coordinates for all the face dots. */ + cache->fdots_patch_coords = gpu_vertbuf_create_from_format(get_blender_patch_coords_format(), + mesh_eval->totpoly); + CompressedPatchCoord *blender_fdots_patch_coords = (CompressedPatchCoord *) + 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) { + /* 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); + } + else { + /* For N-gons, since they are split into quads from the center, and since the center is + * chosen to be the top right corner of each quad, the center coordinate of the coarse face + * is any one of those top right corners with `u = v = 1.0`. */ + blender_fdots_patch_coords[i] = make_patch_coord(ptex_face_index, 1.0f, 1.0f); + } + } - cache->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv); + cache->subdiv_polygon_offset_buffer = draw_subdiv_build_origindex_buffer( + cache->subdiv_polygon_offset, mesh_eval->totpoly); - /* Build patch coordinates for all the face dots. */ - cache->fdots_patch_coords = gpu_vertbuf_create_from_format(get_blender_patch_coords_format(), - mesh_eval->totpoly); - CompressedPatchCoord *blender_fdots_patch_coords = (CompressedPatchCoord *)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) { - /* 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); - } - else { - /* For N-gons, since they are split into quads from the center, and since the center is - * chosen to be the top right corner of each quad, the center coordinate of the coarse face - * is any one of those top right corners with `u = v = 1.0`. */ - blender_fdots_patch_coords[i] = make_patch_coord(ptex_face_index, 1.0f, 1.0f); - } + cache->face_ptex_offset_buffer = draw_subdiv_build_origindex_buffer(cache->face_ptex_offset, + mesh_eval->totpoly + 1); + + build_vertex_face_adjacency_maps(cache); } cache->resolution = to_mesh_settings.resolution; - - cache->subdiv_polygon_offset_buffer = draw_subdiv_build_origindex_buffer( - cache->subdiv_polygon_offset, mesh_eval->totpoly); - - cache->face_ptex_offset_buffer = draw_subdiv_build_origindex_buffer(cache->face_ptex_offset, - mesh_eval->totpoly + 1); cache->num_coarse_poly = mesh_eval->totpoly; - build_vertex_face_adjacency_maps(cache); - /* Cleanup. */ - MEM_freeN(cache_building_context.vert_origindex_map); - MEM_freeN(cache_building_context.edge_origindex_map); + MEM_SAFE_FREE(cache_building_context.vert_origindex_map); + MEM_SAFE_FREE(cache_building_context.edge_origindex_map); return true; } @@ -1184,6 +1213,11 @@ static void drw_subdiv_compute_dispatch(const DRWSubdivCache *cache, void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache, GPUVertBuf *pos_nor) { + if (!draw_subdiv_cache_need_polygon_data(cache)) { + /* Happens on meshes with only loose geometry. */ + return; + } + Subdiv *subdiv = cache->subdiv; OpenSubdiv_Evaluator *evaluator = subdiv->evaluator; @@ -1241,6 +1275,11 @@ void draw_subdiv_extract_uvs(const DRWSubdivCache *cache, const int face_varying_channel, const int dst_offset) { + if (!draw_subdiv_cache_need_polygon_data(cache)) { + /* Happens on meshes with only loose geometry. */ + return; + } + Subdiv *subdiv = cache->subdiv; OpenSubdiv_Evaluator *evaluator = subdiv->evaluator; @@ -1462,6 +1501,11 @@ void draw_subdiv_build_tris_buffer(const DRWSubdivCache *cache, GPUIndexBuf *subdiv_tris, const int material_count) { + if (!draw_subdiv_cache_need_polygon_data(cache)) { + /* Happens on meshes with only loose geometry. */ + return; + } + const bool do_single_material = material_count <= 1; const char *defines = "#define SUBDIV_POLYGON_OFFSET\n"; @@ -1498,6 +1542,11 @@ void draw_subdiv_build_fdots_buffers(const DRWSubdivCache *cache, GPUVertBuf *fdots_nor, GPUIndexBuf *fdots_indices) { + if (!draw_subdiv_cache_need_polygon_data(cache)) { + /* Happens on meshes with only loose geometry. */ + return; + } + Subdiv *subdiv = cache->subdiv; OpenSubdiv_Evaluator *evaluator = subdiv->evaluator; @@ -1616,6 +1665,11 @@ void draw_subdiv_build_lnor_buffer(const DRWSubdivCache *cache, GPUVertBuf *pos_nor, GPUVertBuf *lnor) { + if (!draw_subdiv_cache_need_polygon_data(cache)) { + /* Happens on meshes with only loose geometry. */ + return; + } + GPUShader *shader = get_subdiv_shader(SHADER_BUFFER_LNOR, "#define SUBDIV_POLYGON_OFFSET\n"); GPU_shader_bind(shader); @@ -1831,7 +1885,15 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene, if (!BKE_subdiv_eval_begin_from_mesh( subdiv, mesh_eval, nullptr, SUBDIV_EVALUATOR_TYPE_GLSL_COMPUTE, evaluator_cache)) { - return false; + /* This could happen in two situations: + * - OpenSubdiv is disabled. + * - Something totally bad happened, and OpenSubdiv rejected our + * topology. + * In either way, we can't safely continue. However, we still have to handle potential loose + * geometry, which is done separately. */ + if (mesh_eval->totpoly) { + return false; + } } DRWSubdivCache *draw_cache = mesh_batch_cache_ensure_subdiv_cache(batch_cache); @@ -1868,6 +1930,104 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene, return true; } +void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cache) +{ + const int coarse_loose_vert_len = cache->loose_geom.vert_len; + const int coarse_loose_edge_len = cache->loose_geom.edge_len; + + if (coarse_loose_vert_len == 0 && coarse_loose_edge_len == 0) { + /* Nothing to do. */ + return; + } + + if (subdiv_cache->loose_geom.edges || subdiv_cache->loose_geom.verts) { + /* Already processed. */ + return; + } + + const Mesh *coarse_mesh = subdiv_cache->mesh; + 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 int num_subdiv_vertices_per_coarse_edge = resolution - 2; + + const int num_subdivided_edge = coarse_loose_edge_len * + (num_subdiv_vertices_per_coarse_edge + 1); + + /* Each edge will store data for its 2 verts, that way we can keep the overall logic simple, here + * and in the buffer extractors. Although it duplicates memory (and work), the buffers also store + * duplicate values. */ + const int num_subdivided_verts = num_subdivided_edge * 2; + + DRWSubdivLooseEdge *loose_subd_edges = static_cast<DRWSubdivLooseEdge *>( + MEM_callocN(sizeof(DRWSubdivLooseEdge) * num_subdivided_edge, "DRWSubdivLooseEdge")); + + DRWSubdivLooseVertex *loose_subd_verts = static_cast<DRWSubdivLooseVertex *>( + MEM_callocN(sizeof(DRWSubdivLooseVertex) * (num_subdivided_verts + coarse_loose_vert_len), + "DRWSubdivLooseEdge")); + + int subd_edge_offset = 0; + int subd_vert_offset = 0; + + /* Subdivide each loose coarse edge. */ + 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]]; + + /* Perform interpolation of each vertex. */ + for (int i = 0; i < resolution - 1; i++, subd_edge_offset++) { + DRWSubdivLooseEdge &subd_edge = loose_subd_edges[subd_edge_offset]; + subd_edge.coarse_edge_index = coarse_edge_index; + + /* First vert. */ + 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); + + subd_edge.loose_subdiv_v1_index = subd_vert_offset++; + + /* Second vert. */ + 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); + + subd_edge.loose_subdiv_v2_index = subd_vert_offset++; + } + } + + /* 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]; + + DRWSubdivLooseVertex &subd_v = loose_subd_verts[subd_vert_offset++]; + subd_v.coarse_vertex_index = cache->loose_geom.verts[i]; + copy_v3_v3(subd_v.co, coarse_vertex.co); + } + + subdiv_cache->loose_geom.edges = loose_subd_edges; + subdiv_cache->loose_geom.verts = loose_subd_verts; + subdiv_cache->loose_geom.edge_len = num_subdivided_edge; + subdiv_cache->loose_geom.vert_len = coarse_loose_vert_len; + subdiv_cache->loose_geom.loop_len = num_subdivided_edge * 2 + coarse_loose_vert_len; +} + +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)}; +} + +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)}; +} + static OpenSubdiv_EvaluatorCache *g_evaluator_cache = nullptr; void DRW_create_subdivision(const Scene *scene, diff --git a/source/blender/draw/intern/draw_subdivision.h b/source/blender/draw/intern/draw_subdivision.h index bd02df6d48b..41d177a644a 100644 --- a/source/blender/draw/intern/draw_subdivision.h +++ b/source/blender/draw/intern/draw_subdivision.h @@ -41,6 +41,56 @@ typedef struct DRWPatchMap { /** \} */ /* -------------------------------------------------------------------- */ +/** \name DRWSubdivLooseEdge + * + * This stores information about a subdivided loose edge. + * \{ */ + +typedef struct DRWSubdivLooseEdge { + /* The corresponding coarse edge, this is always valid. */ + int coarse_edge_index; + /* Pointers into #DRWSubdivLooseGeom.verts. */ + int loose_subdiv_v1_index; + int loose_subdiv_v2_index; +} DRWSubdivLooseEdge; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name DRWSubdivLooseVertex + * + * This stores information about a subdivided loose vertex, that may or may not come from a loose + * edge. + * \{ */ + +typedef struct DRWSubdivLooseVertex { + /* The corresponding coarse vertex, or -1 if this vertex is the result + * of subdivision. */ + unsigned int coarse_vertex_index; + /* Position and normal of the vertex. */ + float co[3]; + float nor[3]; +} DRWSubdivLooseVertex; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name DRWSubdivLooseGeom + * + * This stores the subdivided vertices and edges of loose geometry from #MeshExtractLooseGeom. + * \{ */ + +typedef struct DRWSubdivLooseGeom { + DRWSubdivLooseEdge *edges; + DRWSubdivLooseVertex *verts; + int edge_len; + int vert_len; + int loop_len; +} DRWSubdivLooseGeom; + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name DRWSubdivCache * * This holds the various buffers used to evaluate and render subdivision through OpenGL. @@ -69,6 +119,11 @@ typedef struct DRWSubdivCache { uint num_subdiv_verts; uint num_subdiv_quads; + /* We only do the subdivision traversal for full faces, however we may have geometries that only + * have loose edges (e.g. a custom bone shape). This flag is used to detect those cases, as the + * counters above will all be set to zero if we do not have subdivision loops. */ + bool may_have_loose_geom; + /* Number of polygons in the coarse mesh, notably used to compute a coarse polygon index given a * subdivision loop index. */ int num_coarse_poly; @@ -113,6 +168,8 @@ typedef struct DRWSubdivCache { DRWPatchMap gpu_patch_map; + DRWSubdivLooseGeom loose_geom; + /* UBO to store settings for the various compute shaders. */ struct GPUUniformBuf *ubo; } DRWSubdivCache; @@ -228,3 +285,15 @@ void draw_subdiv_build_edituv_stretch_angle_buffer(const DRWSubdivCache *cache, #ifdef __cplusplus } #endif + +#ifdef __cplusplus +# include "BLI_span.hh" + +/* Helper to access the loose edges. */ +blender::Span<DRWSubdivLooseEdge> draw_subdiv_cache_get_loose_edges(const DRWSubdivCache *cache); + +/* Helper to access only the loose vertices, i.e. not the ones attached to loose edges. To access + * loose vertices of loose edges #draw_subdiv_cache_get_loose_edges should be used. */ +blender::Span<DRWSubdivLooseVertex> draw_subdiv_cache_get_loose_verts(const DRWSubdivCache *cache); + +#endif diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.h b/source/blender/draw/intern/mesh_extractors/extract_mesh.h index 176be3927f9..e43646037fc 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.h +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.h @@ -190,7 +190,6 @@ typedef void(ExtractLVertMeshFn)(const MeshRenderData *mr, void *data); typedef void(ExtractLooseGeomSubdivFn)(const struct DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, - const MeshExtractLooseGeom *loose_geom, void *buffer, void *data); typedef void(ExtractInitFn)(const MeshRenderData *mr, diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc index 37868e89c32..ce3ca428469 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc @@ -142,30 +142,35 @@ static void extract_lines_finish(const MeshRenderData *UNUSED(mr), } static void extract_lines_init_subdiv(const DRWSubdivCache *subdiv_cache, - const MeshRenderData *mr, + const MeshRenderData *UNUSED(mr), struct MeshBatchCache *UNUSED(cache), void *buffer, void *UNUSED(data)) { + const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom; GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buffer); GPU_indexbuf_init_build_on_device(ibo, - subdiv_cache->num_subdiv_loops * 2 + mr->edge_loose_len * 2); + subdiv_cache->num_subdiv_loops * 2 + loose_geom.edge_len * 2); + + if (subdiv_cache->num_subdiv_loops == 0) { + return; + } draw_subdiv_build_lines_buffer(subdiv_cache, ibo); } static void extract_lines_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *UNUSED(mr), - const MeshExtractLooseGeom *loose_geom, void *buffer, void *UNUSED(data)) { - if (loose_geom->edge_len == 0) { + const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom; + if (loose_geom.edge_len == 0) { return; } GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buffer); - draw_subdiv_build_lines_loose_buffer(subdiv_cache, ibo, static_cast<uint>(loose_geom->edge_len)); + draw_subdiv_build_lines_loose_buffer(subdiv_cache, ibo, static_cast<uint>(loose_geom.edge_len)); } constexpr MeshExtract create_extractor_lines() @@ -215,6 +220,20 @@ static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr, extract_lines_loose_subbuffer(mr, cache); } +static void extract_lines_with_lines_loose_finish_subdiv(const struct DRWSubdivCache *subdiv_cache, + const MeshRenderData *UNUSED(mr), + struct MeshBatchCache *cache, + void *UNUSED(buf), + void *UNUSED(_data)) +{ + /* Multiply by 2 because these are edges indices. */ + const int start = subdiv_cache->num_subdiv_loops * 2; + const int len = subdiv_cache->loose_geom.edge_len * 2; + GPU_indexbuf_create_subrange_in_place( + cache->final.buff.ibo.lines_loose, cache->final.buff.ibo.lines, start, len); + cache->no_loose_wire = (len == 0); +} + constexpr MeshExtract create_extractor_lines_with_lines_loose() { MeshExtract extractor = {nullptr}; @@ -225,6 +244,9 @@ constexpr MeshExtract create_extractor_lines_with_lines_loose() extractor.iter_ledge_mesh = extract_lines_iter_ledge_mesh; extractor.task_reduce = extract_lines_task_reduce; extractor.finish = extract_lines_with_lines_loose_finish; + extractor.init_subdiv = extract_lines_init_subdiv; + extractor.iter_loose_geom_subdiv = extract_lines_loose_geom_subdiv; + extractor.finish_subdiv = extract_lines_with_lines_loose_finish_subdiv; extractor.data_type = MR_DATA_NONE; extractor.data_size = sizeof(GPUIndexBufBuilder); extractor.use_threading = true; @@ -248,10 +270,22 @@ static void extract_lines_loose_only_init(const MeshRenderData *mr, extract_lines_loose_subbuffer(mr, cache); } +static void extract_lines_loose_only_init_subdiv(const DRWSubdivCache *UNUSED(subdiv_cache), + const MeshRenderData *mr, + struct MeshBatchCache *cache, + void *buffer, + void *UNUSED(data)) +{ + BLI_assert(buffer == cache->final.buff.ibo.lines_loose); + UNUSED_VARS_NDEBUG(buffer); + extract_lines_loose_subbuffer(mr, cache); +} + constexpr MeshExtract create_extractor_lines_loose_only() { MeshExtract extractor = {nullptr}; extractor.init = extract_lines_loose_only_init; + extractor.init_subdiv = extract_lines_loose_only_init_subdiv; extractor.data_type = MR_DATA_LOOSE_GEOM; extractor.data_size = 0; extractor.use_threading = false; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc index bf34d961281..272963f3fd5 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc @@ -147,8 +147,10 @@ static void extract_points_init_subdiv(const DRWSubdivCache *subdiv_cache, void *data) { GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data); - GPU_indexbuf_init( - elb, GPU_PRIM_POINTS, mr->vert_len, subdiv_cache->num_subdiv_loops + mr->loop_loose_len); + GPU_indexbuf_init(elb, + GPU_PRIM_POINTS, + mr->vert_len, + subdiv_cache->num_subdiv_loops + subdiv_cache->loose_geom.loop_len); } static void extract_points_iter_subdiv_common(GPUIndexBufBuilder *elb, @@ -196,46 +198,70 @@ static void extract_points_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cache, static void extract_points_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, - const MeshExtractLooseGeom *loose_geom, void *UNUSED(buffer), void *data) { - const int loop_loose_len = loose_geom->edge_len + loose_geom->vert_len; + const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom; + const int loop_loose_len = loose_geom.loop_len; if (loop_loose_len == 0) { return; } GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data); + uint offset = subdiv_cache->num_subdiv_loops; - if (mr->extract_type == MR_EXTRACT_MESH) { - const Mesh *coarse_mesh = subdiv_cache->mesh; - const MEdge *coarse_edges = coarse_mesh->medge; + if (mr->extract_type != MR_EXTRACT_BMESH) { + blender::Span<DRWSubdivLooseEdge> loose_edges = draw_subdiv_cache_get_loose_edges( + subdiv_cache); + + for (const DRWSubdivLooseEdge &loose_edge : loose_edges) { + const DRWSubdivLooseVertex &v1 = loose_geom.verts[loose_edge.loose_subdiv_v1_index]; + const DRWSubdivLooseVertex &v2 = loose_geom.verts[loose_edge.loose_subdiv_v2_index]; + if (v1.coarse_vertex_index != -1u) { + vert_set_mesh(elb, mr, v1.coarse_vertex_index, offset); + } + if (v2.coarse_vertex_index != -1u) { + vert_set_mesh(elb, mr, v2.coarse_vertex_index, offset + 1); + } - for (int i = 0; i < loose_geom->edge_len; i++) { - const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]]; - vert_set_mesh(elb, mr, loose_edge->v1, offset); - vert_set_mesh(elb, mr, loose_edge->v2, offset + 1); offset += 2; } + blender::Span<DRWSubdivLooseVertex> loose_verts = draw_subdiv_cache_get_loose_verts( + subdiv_cache); - for (int i = 0; i < loose_geom->vert_len; i++) { - vert_set_mesh(elb, mr, loose_geom->verts[i], offset); + for (const DRWSubdivLooseVertex &loose_vert : loose_verts) { + vert_set_mesh(elb, mr, loose_vert.coarse_vertex_index, offset); offset += 1; } } else { - BMesh *bm = mr->bm; - for (int i = 0; i < loose_geom->edge_len; i++) { - const BMEdge *loose_edge = BM_edge_at_index(bm, loose_geom->edges[i]); - vert_set_bm(elb, loose_edge->v1, offset); - vert_set_bm(elb, loose_edge->v2, offset + 1); + blender::Span<DRWSubdivLooseEdge> loose_edges = draw_subdiv_cache_get_loose_edges( + subdiv_cache); + + for (const DRWSubdivLooseEdge &loose_edge : loose_edges) { + const DRWSubdivLooseVertex &v1 = loose_geom.verts[loose_edge.loose_subdiv_v1_index]; + const DRWSubdivLooseVertex &v2 = loose_geom.verts[loose_edge.loose_subdiv_v2_index]; + if (v1.coarse_vertex_index != -1u) { + BMVert *eve = mr->v_origindex ? bm_original_vert_get(mr, v1.coarse_vertex_index) : + BM_vert_at_index(mr->bm, v1.coarse_vertex_index); + vert_set_bm(elb, eve, offset); + } + if (v2.coarse_vertex_index != -1u) { + BMVert *eve = mr->v_origindex ? bm_original_vert_get(mr, v2.coarse_vertex_index) : + BM_vert_at_index(mr->bm, v2.coarse_vertex_index); + vert_set_bm(elb, eve, offset + 1); + } + offset += 2; } + blender::Span<DRWSubdivLooseVertex> loose_verts = draw_subdiv_cache_get_loose_verts( + subdiv_cache); - for (int i = 0; i < loose_geom->vert_len; i++) { - const BMVert *loose_vert = BM_vert_at_index(bm, loose_geom->verts[i]); - vert_set_bm(elb, loose_vert, offset); + for (const DRWSubdivLooseVertex &loose_vert : loose_verts) { + BMVert *eve = mr->v_origindex ? bm_original_vert_get(mr, loose_vert.coarse_vertex_index) : + BM_vert_at_index(mr->bm, loose_vert.coarse_vertex_index); + vert_set_bm(elb, eve, offset); offset += 1; } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc index f998d8cb24e..f3b41efe1c3 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc @@ -217,16 +217,17 @@ static GPUVertFormat *get_subdiv_edge_fac_format() } static void extract_edge_fac_init_subdiv(const DRWSubdivCache *subdiv_cache, - const MeshRenderData *mr, + const MeshRenderData *UNUSED(mr), struct MeshBatchCache *cache, void *buffer, void *UNUSED(data)) { + const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom; GPUVertBuf *edge_idx = cache->final.buff.vbo.edge_idx; GPUVertBuf *pos_nor = cache->final.buff.vbo.pos_nor; GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer); GPU_vertbuf_init_build_on_device( - vbo, get_subdiv_edge_fac_format(), subdiv_cache->num_subdiv_loops + mr->loop_loose_len); + vbo, get_subdiv_edge_fac_format(), subdiv_cache->num_subdiv_loops + loose_geom.loop_len); /* Create a temporary buffer for the edge original indices if it was not requested. */ const bool has_edge_idx = edge_idx != nullptr; @@ -252,11 +253,11 @@ static void extract_edge_fac_init_subdiv(const DRWSubdivCache *subdiv_cache, static void extract_edge_fac_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *UNUSED(mr), - const MeshExtractLooseGeom *loose_geom, void *buffer, void *UNUSED(data)) { - if (loose_geom->edge_len == 0) { + const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom; + if (loose_geom.edge_len == 0) { return; } @@ -266,7 +267,7 @@ static void extract_edge_fac_loose_geom_subdiv(const DRWSubdivCache *subdiv_cach GPU_vertbuf_use(vbo); uint offset = subdiv_cache->num_subdiv_loops; - for (int i = 0; i < loose_geom->edge_len; i++) { + for (int i = 0; i < loose_geom.edge_len; i++) { if (GPU_crappy_amd_driver()) { float loose_edge_fac[2] = {1.0f, 1.0f}; GPU_vertbuf_update_sub(vbo, offset * sizeof(float), sizeof(loose_edge_fac), loose_edge_fac); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc index b777b67b984..1e158a7e6d7 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc @@ -240,14 +240,15 @@ static void extract_edit_data_iter_lvert_mesh(const MeshRenderData *mr, } static void extract_edit_data_init_subdiv(const DRWSubdivCache *subdiv_cache, - const MeshRenderData *mr, + const MeshRenderData *UNUSED(mr), MeshBatchCache *UNUSED(cache), void *buf, void *data) { + const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom; GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); GPU_vertbuf_init_with_format(vbo, get_edit_data_format()); - GPU_vertbuf_data_alloc(vbo, subdiv_cache->num_subdiv_loops + mr->loop_loose_len); + GPU_vertbuf_data_alloc(vbo, subdiv_cache->num_subdiv_loops + loose_geom.loop_len); EditLoopData *vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo); *(EditLoopData **)data = vbo_data; } @@ -306,27 +307,38 @@ static void extract_edit_data_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cach static void extract_edit_data_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, - const MeshExtractLooseGeom *loose_geom, void *UNUSED(buffer), void *_data) { - if (loose_geom->edge_len == 0) { + const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom; + if (loose_geom.edge_len == 0) { return; } + blender::Span<DRWSubdivLooseEdge> loose_edges = draw_subdiv_cache_get_loose_edges(subdiv_cache); + EditLoopData *vbo_data = *(EditLoopData **)_data; + int ledge_index = 0; - for (int ledge_index = 0; ledge_index < loose_geom->edge_len; ledge_index++) { - const int offset = subdiv_cache->num_subdiv_loops + ledge_index * 2; + for (const DRWSubdivLooseEdge &loose_edge : loose_edges) { + const int offset = subdiv_cache->num_subdiv_loops + ledge_index++ * 2; EditLoopData *data = &vbo_data[offset]; memset(data, 0, sizeof(EditLoopData)); - const int edge_index = loose_geom->edges[ledge_index]; + const int edge_index = loose_edge.coarse_edge_index; BMEdge *eed = mr->e_origindex ? bm_original_edge_get(mr, edge_index) : BM_edge_at_index(mr->bm, edge_index); mesh_render_data_edge_flag(mr, eed, &data[0]); data[1] = data[0]; - mesh_render_data_vert_flag(mr, eed->v1, &data[0]); - mesh_render_data_vert_flag(mr, eed->v2, &data[1]); + + const DRWSubdivLooseVertex &v1 = loose_geom.verts[loose_edge.loose_subdiv_v1_index]; + const DRWSubdivLooseVertex &v2 = loose_geom.verts[loose_edge.loose_subdiv_v2_index]; + + if (v1.coarse_vertex_index != -1u) { + mesh_render_data_vert_flag(mr, eed->v1, &data[0]); + } + if (v2.coarse_vertex_index != -1u) { + mesh_render_data_vert_flag(mr, eed->v2, &data[1]); + } } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc index 22fda284a74..ab17b2e5294 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc @@ -211,16 +211,21 @@ static GPUVertFormat *get_custom_normals_format() } static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache, - const MeshRenderData *mr, + const MeshRenderData *UNUSED(mr), struct MeshBatchCache *UNUSED(cache), void *buffer, void *UNUSED(data)) { GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer); + const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom; /* Initialize the vertex buffer, it was already allocated. */ GPU_vertbuf_init_build_on_device( - vbo, get_pos_nor_format(), subdiv_cache->num_subdiv_loops + mr->loop_loose_len); + vbo, get_pos_nor_format(), subdiv_cache->num_subdiv_loops + loose_geom.loop_len); + + if (subdiv_cache->num_subdiv_loops == 0) { + return; + } draw_subdiv_extract_pos_nor(subdiv_cache, vbo); @@ -273,13 +278,12 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache, } static void extract_pos_nor_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache, - const MeshRenderData *mr, - const MeshExtractLooseGeom *loose_geom, + const MeshRenderData *UNUSED(mr), void *buffer, void *UNUSED(data)) { - const int loop_loose_len = loose_geom->edge_len + loose_geom->vert_len; - if (loop_loose_len == 0) { + const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom; + if (loose_geom.loop_len == 0) { return; } @@ -293,75 +297,38 @@ static void extract_pos_nor_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache float flag; }; - if (mr->extract_type == MR_EXTRACT_MESH) { - const Mesh *coarse_mesh = subdiv_cache->mesh; - const MEdge *coarse_edges = coarse_mesh->medge; - const MVert *coarse_verts = coarse_mesh->mvert; - - SubdivPosNorLoop edge_data[2]; - memset(&edge_data, 0, sizeof(SubdivPosNorLoop) * 2); - for (int i = 0; i < loose_geom->edge_len; i++) { - const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]]; - const MVert *loose_vert1 = &coarse_verts[loose_edge->v1]; - const MVert *loose_vert2 = &coarse_verts[loose_edge->v2]; + /* Make sure buffer is active for sending loose data. */ + GPU_vertbuf_use(vbo); - copy_v3_v3(edge_data[0].pos, loose_vert1->co); - copy_v3_v3(edge_data[1].pos, loose_vert2->co); + blender::Span<DRWSubdivLooseEdge> loose_edges = draw_subdiv_cache_get_loose_edges(subdiv_cache); - GPU_vertbuf_update_sub( - vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop) * 2, &edge_data); + SubdivPosNorLoop edge_data[2]; + memset(edge_data, 0, sizeof(SubdivPosNorLoop) * 2); + for (const DRWSubdivLooseEdge &loose_edge : loose_edges) { + const DRWSubdivLooseVertex &v1 = loose_geom.verts[loose_edge.loose_subdiv_v1_index]; + const DRWSubdivLooseVertex &v2 = loose_geom.verts[loose_edge.loose_subdiv_v2_index]; - offset += 2; - } - - SubdivPosNorLoop vert_data; - memset(&vert_data, 0, sizeof(SubdivPosNorLoop)); - for (int i = 0; i < loose_geom->vert_len; i++) { - const MVert *loose_vertex = &coarse_verts[loose_geom->verts[i]]; + copy_v3_v3(edge_data[0].pos, v1.co); + copy_v3_v3(edge_data[1].pos, v2.co); - copy_v3_v3(vert_data.pos, loose_vertex->co); + GPU_vertbuf_update_sub( + vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop) * 2, &edge_data); - GPU_vertbuf_update_sub( - vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop), &vert_data); - - offset += 1; - } + offset += 2; } - else { - BMesh *bm = subdiv_cache->bm; - - SubdivPosNorLoop edge_data[2]; - memset(&edge_data, 0, sizeof(SubdivPosNorLoop) * 2); - for (int i = 0; i < loose_geom->edge_len; i++) { - const BMEdge *loose_edge = BM_edge_at_index(bm, loose_geom->edges[i]); - const BMVert *loose_vert1 = loose_edge->v1; - const BMVert *loose_vert2 = loose_edge->v2; - - copy_v3_v3(edge_data[0].pos, loose_vert1->co); - copy_v3_v3(edge_data[0].nor, loose_vert1->no); - - copy_v3_v3(edge_data[1].pos, loose_vert2->co); - copy_v3_v3(edge_data[1].nor, loose_vert2->no); - GPU_vertbuf_update_sub( - vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop) * 2, &edge_data); + SubdivPosNorLoop vert_data; + memset(&vert_data, 0, sizeof(SubdivPosNorLoop)); + blender::Span<DRWSubdivLooseVertex> loose_verts = draw_subdiv_cache_get_loose_verts( + subdiv_cache); - offset += 2; - } - - SubdivPosNorLoop vert_data; - memset(&vert_data, 0, sizeof(SubdivPosNorLoop)); - for (int i = 0; i < loose_geom->vert_len; i++) { - const BMVert *loose_vertex = BM_vert_at_index(bm, loose_geom->verts[i]); + for (const DRWSubdivLooseVertex &loose_vert : loose_verts) { + copy_v3_v3(vert_data.pos, loose_vert.co); - copy_v3_v3(vert_data.pos, loose_vertex->co); - copy_v3_v3(vert_data.nor, loose_vertex->no); + GPU_vertbuf_update_sub( + vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop), &vert_data); - GPU_vertbuf_update_sub( - vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop), &vert_data); - - offset += 1; - } + offset += 1; } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc index 0dcf59005bd..be4c292e842 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc @@ -188,12 +188,12 @@ static void extract_vert_idx_init_subdiv(const DRWSubdivCache *subdiv_cache, void *UNUSED(data)) { GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom; /* Each element points to an element in the ibo.points. */ draw_subdiv_init_origindex_buffer(vbo, (int *)GPU_vertbuf_get_data(subdiv_cache->verts_orig_index), subdiv_cache->num_subdiv_loops, - mr->loop_loose_len); - + loose_geom.loop_len); if (!mr->v_origindex) { return; } @@ -212,12 +212,11 @@ static void extract_vert_idx_init_subdiv(const DRWSubdivCache *subdiv_cache, static void extract_vert_idx_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, - const MeshExtractLooseGeom *loose_geom, void *buffer, void *UNUSED(data)) { - const int loop_loose_len = loose_geom->edge_len + loose_geom->vert_len; - if (loop_loose_len == 0) { + const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom; + if (loose_geom.loop_len == 0) { return; } @@ -225,60 +224,57 @@ static void extract_vert_idx_loose_geom_subdiv(const DRWSubdivCache *subdiv_cach uint *vert_idx_data = (uint *)GPU_vertbuf_get_data(vbo); uint offset = subdiv_cache->num_subdiv_loops; - if (mr->extract_type == MR_EXTRACT_MESH) { - const Mesh *coarse_mesh = subdiv_cache->mesh; - const MEdge *coarse_edges = coarse_mesh->medge; - for (int i = 0; i < loose_geom->edge_len; i++) { - const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]]; - vert_idx_data[offset] = loose_edge->v1; - vert_idx_data[offset + 1] = loose_edge->v2; - offset += 2; + blender::Span<DRWSubdivLooseEdge> loose_edges = draw_subdiv_cache_get_loose_edges(subdiv_cache); + + for (const DRWSubdivLooseEdge &loose_edge : loose_edges) { + const DRWSubdivLooseVertex &v1 = loose_geom.verts[loose_edge.loose_subdiv_v1_index]; + const DRWSubdivLooseVertex &v2 = loose_geom.verts[loose_edge.loose_subdiv_v2_index]; + + if (v1.coarse_vertex_index != -1u) { + vert_idx_data[offset] = mr->v_origindex ? mr->v_origindex[v1.coarse_vertex_index] : + v1.coarse_vertex_index; } - for (int i = 0; i < loose_geom->vert_len; i++) { - vert_idx_data[offset] = loose_geom->verts[i]; - offset += 1; + if (v2.coarse_vertex_index != -1u) { + vert_idx_data[offset + 1] = mr->v_origindex ? mr->v_origindex[v2.coarse_vertex_index] : + v2.coarse_vertex_index; } + + offset += 2; } - else { - BMesh *bm = mr->bm; - for (int i = 0; i < loose_geom->edge_len; i++) { - const BMEdge *loose_edge = BM_edge_at_index(bm, loose_geom->edges[i]); - vert_idx_data[offset] = BM_elem_index_get(loose_edge->v1); - vert_idx_data[offset + 1] = BM_elem_index_get(loose_edge->v2); - offset += 2; - } - for (int i = 0; i < loose_geom->vert_len; i++) { - const BMVert *loose_vert = BM_vert_at_index(bm, loose_geom->verts[i]); - vert_idx_data[offset] = BM_elem_index_get(loose_vert); - offset += 1; - } + blender::Span<DRWSubdivLooseVertex> loose_verts = draw_subdiv_cache_get_loose_verts( + subdiv_cache); + + for (const DRWSubdivLooseVertex &loose_vert : loose_verts) { + vert_idx_data[offset] = mr->v_origindex ? mr->v_origindex[loose_vert.coarse_vertex_index] : + loose_vert.coarse_vertex_index; + offset += 1; } } static void extract_edge_idx_init_subdiv(const DRWSubdivCache *subdiv_cache, - const MeshRenderData *mr, + const MeshRenderData *UNUSED(mr), MeshBatchCache *UNUSED(cache), void *buf, void *UNUSED(data)) { GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); + const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom; draw_subdiv_init_origindex_buffer( vbo, static_cast<int *>(GPU_vertbuf_get_data(subdiv_cache->edges_orig_index)), subdiv_cache->num_subdiv_loops, - mr->edge_loose_len * 2); + loose_geom.edge_len * 2); } static void extract_edge_idx_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache, - const MeshRenderData *UNUSED(mr), - const MeshExtractLooseGeom *loose_geom, + const MeshRenderData *mr, void *buffer, void *UNUSED(data)) { - const int loop_loose_len = loose_geom->edge_len + loose_geom->vert_len; - if (loop_loose_len == 0) { + const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom; + if (loose_geom.edge_len == 0) { return; } @@ -286,9 +282,12 @@ static void extract_edge_idx_loose_geom_subdiv(const DRWSubdivCache *subdiv_cach uint *vert_idx_data = (uint *)GPU_vertbuf_get_data(vbo); uint offset = subdiv_cache->num_subdiv_loops; - for (int i = 0; i < loose_geom->edge_len; i++) { - vert_idx_data[offset] = loose_geom->edges[i]; - vert_idx_data[offset + 1] = loose_geom->edges[i]; + blender::Span<DRWSubdivLooseEdge> loose_edges = draw_subdiv_cache_get_loose_edges(subdiv_cache); + for (const DRWSubdivLooseEdge &loose_edge : loose_edges) { + const int coarse_edge_index = mr->e_origindex ? mr->e_origindex[loose_edge.coarse_edge_index] : + loose_edge.coarse_edge_index; + vert_idx_data[offset] = coarse_edge_index; + vert_idx_data[offset + 1] = coarse_edge_index; offset += 2; } } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_context.cc b/source/blender/editors/space_spreadsheet/spreadsheet_context.cc index 1a61f021e92..ec9fa72edb1 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_context.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_context.cc @@ -451,9 +451,7 @@ bool ED_spreadsheet_context_path_is_active(const bContext *C, SpaceSpreadsheet * if (modifier == nullptr) { return false; } - if (!(modifier->flag & eModifierFlag_Active)) { - return false; - } + const bool modifier_is_active = modifier->flag & eModifierFlag_Active; if (modifier->type != eModifierType_Nodes) { return false; } @@ -480,6 +478,12 @@ bool ED_spreadsheet_context_path_is_active(const bContext *C, SpaceSpreadsheet * if (snode->nodetree != root_node_tree) { continue; } + if (!modifier_is_active) { + if (!(snode->flag & SNODE_PIN)) { + /* Node tree has to be pinned when the modifier is not active. */ + continue; + } + } if (snode->id != &object->id) { continue; } |