diff --git a/source/blender/blenkernel/BKE_cloth.hh b/source/blender/blenkernel/BKE_cloth.hh index 63387ecbdf9..d02f813d535 100644 --- a/source/blender/blenkernel/BKE_cloth.hh +++ b/source/blender/blenkernel/BKE_cloth.hh @@ -8,6 +8,8 @@ */ #include "BLI_math_vector_types.hh" +#include "BLI_ordered_edge.hh" +#include "BLI_set.hh" #include @@ -17,8 +19,6 @@ struct ClothModifierData; struct CollisionModifierData; struct Implicit_Data; struct Depsgraph; -struct EdgeSet; -struct GHash; struct LinkNode; struct Mesh; struct MVertTri; @@ -78,13 +78,13 @@ struct Cloth { BVHTree *bvhtree; /* collision tree for this cloth object */ BVHTree *bvhselftree; /* collision tree for this cloth object (may be same as bvhtree) */ MVertTri *tri; - Implicit_Data *implicit; /* our implicit solver connects to this pointer */ - EdgeSet *edgeset; /* used for selfcollisions */ + Implicit_Data *implicit; /* our implicit solver connects to this pointer */ + blender::Set edgeset; /* used for selfcollisions */ int last_frame; float initial_mesh_volume; /* Initial volume of the mesh. Used for pressure */ float average_acceleration[3]; /* Moving average of overall acceleration. */ const blender::int2 *edges; /* Used for hair collisions. */ - EdgeSet *sew_edge_graph; /* Sewing edges represented using a GHash */ + blender::Set sew_edge_graph; /* Sewing edges. */ }; /** diff --git a/source/blender/blenkernel/BKE_paint.hh b/source/blender/blenkernel/BKE_paint.hh index 0cd19e309dd..b91a811fc37 100644 --- a/source/blender/blenkernel/BKE_paint.hh +++ b/source/blender/blenkernel/BKE_paint.hh @@ -13,6 +13,8 @@ #include "BLI_compiler_compat.h" #include "BLI_math_vector_types.hh" #include "BLI_offset_indices.hh" +#include "BLI_ordered_edge.hh" +#include "BLI_set.hh" #include "BLI_utildefines.h" #include "DNA_brush_enums.h" @@ -31,7 +33,6 @@ struct BlendWriter; struct Brush; struct CurveMapping; struct Depsgraph; -struct EdgeSet; struct EnumPropertyItem; struct ExpandCache; struct FilterCache; @@ -353,7 +354,7 @@ struct SculptClothLengthConstraint { struct SculptClothSimulation { SculptClothLengthConstraint *length_constraints; int tot_length_constraints; - EdgeSet *created_length_constraints; + blender::Set created_length_constraints; int capacity_length_constraints; float *length_constraint_tweak; diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 5217bc3ad5d..8be441d047e 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -11,6 +11,8 @@ #include "BLI_buffer.h" #include "BLI_compiler_attrs.h" +#include "BLI_map.hh" +#include "BLI_ordered_edge.hh" #include "BLI_utildefines.h" #include "DNA_particle_types.h" @@ -31,7 +33,6 @@ struct BlendLibReader; struct BlendWriter; struct CustomData_MeshMasks; struct Depsgraph; -struct EdgeHash; struct KDTree_3d; struct LinkNode; struct MCol; @@ -84,7 +85,7 @@ typedef struct SPHData { ParticleSystem *psys[10]; ParticleData *pa; float mass; - struct EdgeHash *eh; + blender::Map eh; float *gravity; float hfac; /* Average distance to neighbors (other particles in the support domain), diff --git a/source/blender/blenkernel/BKE_subsurf.hh b/source/blender/blenkernel/BKE_subsurf.hh index 51476b32e4a..b5c2e36cca2 100644 --- a/source/blender/blenkernel/BKE_subsurf.hh +++ b/source/blender/blenkernel/BKE_subsurf.hh @@ -11,8 +11,10 @@ #include "BKE_DerivedMesh.h" /* Thread sync primitives used directly. */ +#include "BLI_ordered_edge.hh" #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BLI_vector_set.hh" struct CCGEdge; struct CCGElem; @@ -21,7 +23,6 @@ struct CCGSubSurf; struct CCGVert; struct DMFlagMat; struct DerivedMesh; -struct EdgeHash; struct Mesh; struct MeshElemMap; struct MultiresModifierData; @@ -122,7 +123,7 @@ struct CCGDerivedMesh { MultiresModifiedFlags modified_flags; } multires; - EdgeHash *ehash; + blender::VectorSet *ehash; ThreadMutex loops_cache_lock; ThreadRWMutex origindex_cache_rwlock; diff --git a/source/blender/blenkernel/intern/cloth.cc b/source/blender/blenkernel/intern/cloth.cc index ef360b34bcd..f71885523c1 100644 --- a/source/blender/blenkernel/intern/cloth.cc +++ b/source/blender/blenkernel/intern/cloth.cc @@ -14,7 +14,6 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "BLI_edgehash.h" #include "BLI_linklist.h" #include "BLI_math_geom.h" #include "BLI_math_matrix.h" @@ -482,21 +481,12 @@ void cloth_free_modifier(ClothModifierData *clmd) MEM_freeN(cloth->tri); } - if (cloth->edgeset) { - BLI_edgeset_free(cloth->edgeset); - } - - if (cloth->sew_edge_graph) { - BLI_edgeset_free(cloth->sew_edge_graph); - cloth->sew_edge_graph = nullptr; - } - #if 0 if (clmd->clothObject->facemarks) { MEM_freeN(clmd->clothObject->facemarks); } #endif - MEM_freeN(cloth); + MEM_delete(cloth); clmd->clothObject = nullptr; } } @@ -559,21 +549,12 @@ void cloth_free_modifier_extern(ClothModifierData *clmd) MEM_freeN(cloth->tri); } - if (cloth->edgeset) { - BLI_edgeset_free(cloth->edgeset); - } - - if (cloth->sew_edge_graph) { - BLI_edgeset_free(cloth->sew_edge_graph); - cloth->sew_edge_graph = nullptr; - } - #if 0 if (clmd->clothObject->facemarks) { MEM_freeN(clmd->clothObject->facemarks); } #endif - MEM_freeN(cloth); + MEM_delete(cloth); clmd->clothObject = nullptr; } } @@ -742,10 +723,9 @@ static bool cloth_from_object( } /* Allocate a new cloth object. */ - clmd->clothObject = MEM_cnew(__func__); + clmd->clothObject = MEM_new(__func__); if (clmd->clothObject) { clmd->clothObject->old_solver_type = 255; - clmd->clothObject->edgeset = nullptr; } else { BKE_modifier_set_error(ob, &(clmd->modifier), "Out of memory on allocating clmd->clothObject"); @@ -763,8 +743,6 @@ static bool cloth_from_object( clmd->clothObject->springs = nullptr; clmd->clothObject->numsprings = -1; - clmd->clothObject->sew_edge_graph = nullptr; - if (clmd->sim_parms->shapekey_rest && !(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH)) { @@ -944,10 +922,7 @@ static void cloth_free_errorsprings(Cloth *cloth, MEM_SAFE_FREE(spring_ref); - if (cloth->edgeset) { - BLI_edgeset_free(cloth->edgeset); - cloth->edgeset = nullptr; - } + cloth->edgeset.clear_and_shrink(); } BLI_INLINE void cloth_bend_poly_dir( @@ -1407,7 +1382,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata, float max_length, float max_diversion, bool check_normal, - uint *r_tar_v_idx) + int *r_tar_v_idx) { float co[3], no[3], new_co[3]; float radius; @@ -1444,7 +1419,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata, BLI_bvhtree_ray_cast( treedata->tree, new_co, no, radius, &rayhit, treedata->raycast_callback, treedata); - uint vert_idx = -1; + int vert_idx = -1; const int *corner_verts = treedata->corner_verts; const MLoopTri *lt = nullptr; @@ -1458,7 +1433,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata, lt = &treedata->looptri[rayhit.index]; for (int i = 0; i < 3; i++) { - uint tmp_vert_idx = corner_verts[lt->tri[i]]; + int tmp_vert_idx = corner_verts[lt->tri[i]]; if (tmp_vert_idx == v_idx) { /* We managed to hit ourselves. */ return false; @@ -1495,7 +1470,6 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) const Span corner_edges = mesh->corner_edges(); int index2 = 0; /* our second vertex index */ LinkNodePair *edgelist = nullptr; - EdgeSet *edgeset = nullptr; LinkNode *search = nullptr, *search2 = nullptr; BendSpringRef *spring_ref = nullptr; @@ -1507,10 +1481,9 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) /* NOTE: handling ownership of springs and edgeset is quite sloppy * currently they are never initialized but assert just to be sure */ BLI_assert(cloth->springs == nullptr); - BLI_assert(cloth->edgeset == nullptr); + BLI_assert(cloth->edgeset.is_empty()); cloth->springs = nullptr; - cloth->edgeset = nullptr; if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { spring_ref = static_cast( @@ -1532,7 +1505,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) if (use_internal_springs && numface > 0) { BVHTreeFromMesh treedata = {nullptr}; - uint tar_v_idx; + int tar_v_idx; Mesh *tmp_mesh = nullptr; RNG *rng; @@ -1543,7 +1516,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) tmp_mesh = cloth_make_rest_mesh(clmd, mesh); } - EdgeSet *existing_vert_pairs = BLI_edgeset_new("cloth_sewing_edges_graph"); + Set existing_vert_pairs; BKE_bvhtree_from_mesh_get(&treedata, tmp_mesh ? tmp_mesh : mesh, BVHTREE_FROM_LOOPTRI, 2); rng = BLI_rng_new_srandom(0); @@ -1561,12 +1534,12 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS_NORMAL), &tar_v_idx)) { - if (BLI_edgeset_haskey(existing_vert_pairs, i, tar_v_idx)) { + if (existing_vert_pairs.contains({i, tar_v_idx})) { /* We have already created a spring between these verts! */ continue; } - BLI_edgeset_insert(existing_vert_pairs, i, tar_v_idx); + existing_vert_pairs.add({i, tar_v_idx}); spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); @@ -1592,7 +1565,6 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) } else { cloth_free_errorsprings(cloth, edgelist, spring_ref); - BLI_edgeset_free(existing_vert_pairs); free_bvhtree_from_mesh(&treedata); if (tmp_mesh) { BKE_id_free(nullptr, &tmp_mesh->id); @@ -1601,7 +1573,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) } } } - BLI_edgeset_free(existing_vert_pairs); + existing_vert_pairs.clear_and_shrink(); free_bvhtree_from_mesh(&treedata); if (tmp_mesh) { BKE_id_free(nullptr, &tmp_mesh->id); @@ -1616,8 +1588,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW) { /* cloth->sew_edge_graph should not exist before this */ - BLI_assert(cloth->sew_edge_graph == nullptr); - cloth->sew_edge_graph = BLI_edgeset_new("cloth_sewing_edges_graph"); + BLI_assert(cloth->sew_edge_graph.is_empty()); } /* Structural springs. */ @@ -1635,7 +1606,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) spring->lin_stiffness = 1.0f; spring->type = CLOTH_SPRING_TYPE_SEWING; - BLI_edgeset_insert(cloth->sew_edge_graph, edges[i][0], edges[i][1]); + cloth->sew_edge_graph.add({edges[i][0], edges[i][1]}); } else { shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl); @@ -1681,8 +1652,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) } } - edgeset = BLI_edgeset_new_ex(__func__, numedges); - cloth->edgeset = edgeset; + cloth->edgeset.reserve(numedges); if (numface) { for (int i = 0; i < numface; i++) { @@ -1799,7 +1769,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) /* Check for existing spring. */ /* Check also if start-point is equal to endpoint. */ - if ((index2 != tspring2->ij) && !BLI_edgeset_haskey(edgeset, tspring2->ij, index2)) { + if ((index2 != tspring2->ij) && !cloth->edgeset.contains({tspring2->ij, index2})) { spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); if (!spring) { @@ -1816,7 +1786,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) spring->lin_stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f; - BLI_edgeset_insert(edgeset, spring->ij, spring->kl); + cloth->edgeset.add({spring->ij, spring->kl}); bend_springs++; BLI_linklist_prepend(&cloth->springs, spring); @@ -1911,15 +1881,13 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) /* Insert other near springs in `edgeset` AFTER bending springs are calculated * (for self-collision). */ for (int i = 0; i < numedges; i++) { /* struct springs */ - BLI_edgeset_add(edgeset, edges[i][0], edges[i][1]); + cloth->edgeset.add({edges[i][0], edges[i][1]}); } for (int i = 0; i < numface; i++) { /* edge springs */ if (faces[i].size() == 4) { - BLI_edgeset_add( - edgeset, corner_verts[faces[i].start() + 0], corner_verts[faces[i].start() + 2]); - BLI_edgeset_add( - edgeset, corner_verts[faces[i].start() + 1], corner_verts[faces[i].start() + 3]); + cloth->edgeset.add({corner_verts[faces[i].start() + 0], corner_verts[faces[i].start() + 2]}); + cloth->edgeset.add({corner_verts[faces[i].start() + 1], corner_verts[faces[i].start() + 3]}); } } diff --git a/source/blender/blenkernel/intern/collision.cc b/source/blender/blenkernel/intern/collision.cc index 5b3bc5ca226..257ed8924d5 100644 --- a/source/blender/blenkernel/intern/collision.cc +++ b/source/blender/blenkernel/intern/collision.cc @@ -17,7 +17,6 @@ #include "DNA_scene_types.h" #include "BLI_blenlib.h" -#include "BLI_edgehash.h" #include "BLI_linklist.h" #include "BLI_math_geom.h" #include "BLI_math_vector.h" @@ -1079,7 +1078,7 @@ static bool cloth_bvh_selfcollision_is_active(const ClothModifierData *clmd, } if (sewing_active) { - if (BLI_edgeset_haskey(cloth->sew_edge_graph, tri_a->tri[i], tri_b->tri[j])) { + if (cloth->sew_edge_graph.contains({tri_a->tri[i], tri_b->tri[j]})) { return false; } } diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 414425eb034..17598efdefd 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -19,7 +19,6 @@ #include "DNA_object_types.h" #include "BLI_bounds.hh" -#include "BLI_edgehash.h" #include "BLI_endian_switch.h" #include "BLI_ghash.h" #include "BLI_hash.h" @@ -30,7 +29,9 @@ #include "BLI_math_matrix.h" #include "BLI_math_vector.hh" #include "BLI_memarena.h" +#include "BLI_ordered_edge.hh" #include "BLI_resource_scope.hh" +#include "BLI_set.hh" #include "BLI_span.hh" #include "BLI_string.h" #include "BLI_task.hh" @@ -468,6 +469,7 @@ static bool is_uv_bool_sublayer(const CustomDataLayer &layer) static int customdata_compare( CustomData *c1, CustomData *c2, const int total_length, Mesh *m1, const float thresh) { + using namespace blender; CustomDataLayer *l1, *l2; int layer_count1 = 0, layer_count2 = 0, j; const uint64_t cd_mask_non_generic = CD_MASK_MDEFORMVERT; @@ -535,18 +537,17 @@ static int customdata_compare( if (StringRef(l1->name) == ".edge_verts") { int etot = m1->totedge; - EdgeHash *eh = BLI_edgehash_new_ex(__func__, etot); - - for (j = 0; j < etot; j++, e1++) { - BLI_edgehash_insert(eh, (*e1)[0], (*e1)[1], e1); + Set ordered_edges; + ordered_edges.reserve(etot); + for (const int2 value : Span(e1, etot)) { + ordered_edges.add(value); } - for (j = 0; j < etot; j++, e2++) { - if (!BLI_edgehash_lookup(eh, (*e2)[0], (*e2)[1])) { + for (j = 0; j < etot; j++) { + if (!ordered_edges.contains(e2[j])) { return MESHCMP_EDGEUNKNOWN; } } - BLI_edgehash_free(eh, nullptr); } else { for (j = 0; j < total_length; j++) { diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc index 816e1b61d9a..55aa48616c4 100644 --- a/source/blender/blenkernel/intern/mesh_convert.cc +++ b/source/blender/blenkernel/intern/mesh_convert.cc @@ -20,7 +20,6 @@ #include "DNA_pointcloud_types.h" #include "DNA_scene_types.h" -#include "BLI_edgehash.h" #include "BLI_index_range.hh" #include "BLI_listbase.h" #include "BLI_span.hh" diff --git a/source/blender/blenkernel/intern/mesh_evaluate.cc b/source/blender/blenkernel/intern/mesh_evaluate.cc index 6fe3509f2f7..6a650780c9c 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.cc +++ b/source/blender/blenkernel/intern/mesh_evaluate.cc @@ -19,7 +19,6 @@ #include "BLI_alloca.h" #include "BLI_array_utils.hh" #include "BLI_bitmap.h" -#include "BLI_edgehash.h" #include "BLI_index_range.hh" #include "BLI_math_geom.h" #include "BLI_span.hh" diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index 5695ab7cf12..47810570c22 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -16,7 +16,7 @@ #include "DNA_meshdata_types.h" #include "DNA_object_types.h" -#include "BLI_edgehash.h" +#include "BLI_map.hh" #include "BLI_math_geom.h" #include "BLI_math_matrix.h" #include "BLI_math_vector_types.hh" @@ -97,7 +97,6 @@ static void mesh_calc_edges_mdata(const MVert * /*allvert*/, const MPoly *mpoly; const MFace *mface; MEdge *edges, *edge; - EdgeHash *hash; EdgeSort *edsort, *ed; int a, totedge = 0; uint totedge_final = 0; @@ -177,9 +176,10 @@ static void mesh_calc_edges_mdata(const MVert * /*allvert*/, MEM_freeN(edsort); /* set edge members of mloops */ - hash = BLI_edgehash_new_ex(__func__, totedge_final); + blender::Map hash; + hash.reserve(totedge_final); for (edge_index = 0, edge = edges; edge_index < totedge_final; edge_index++, edge++) { - BLI_edgehash_insert(hash, edge->v1, edge->v2, POINTER_FROM_UINT(edge_index)); + hash.add({edge->v1, edge->v2}, edge_index); } mpoly = allpoly; @@ -191,14 +191,12 @@ static void mesh_calc_edges_mdata(const MVert * /*allvert*/, ml = &ml_next[i - 1]; /* last loop */ while (i-- != 0) { - ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(hash, ml->v, ml_next->v)); + ml->e = hash.lookup({ml->v, ml_next->v}); ml = ml_next; ml_next++; } } - BLI_edgehash_free(hash, nullptr); - *r_medge = edges; *r_totedge = totedge_final; } @@ -464,7 +462,6 @@ static void convert_mfaces_to_mpolys(ID *id, MFace *mf; MLoop *ml, *mloop; MPoly *poly, *mpoly; - EdgeHash *eh; int numTex, numCol; int i, j, totloop, faces_num, *polyindex; @@ -506,11 +503,12 @@ static void convert_mfaces_to_mpolys(ID *id, CustomData_external_read(fdata_legacy, id, CD_MASK_MDISPS, totface_i); } - eh = BLI_edgehash_new_ex(__func__, uint(totedge_i)); + blender::Map eh; + eh.reserve(totedge_i); /* build edge hash */ for (i = 0; i < totedge_i; i++) { - BLI_edgehash_insert(eh, edges[i][0], edges[i][1], POINTER_FROM_UINT(i)); + eh.add(edges[i], i); } polyindex = (int *)CustomData_get_layer(fdata_legacy, CD_ORIGINDEX); @@ -530,7 +528,7 @@ static void convert_mfaces_to_mpolys(ID *id, #define ML(v1, v2) \ { \ ml->v = mf->v1; \ - ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(eh, mf->v1, mf->v2)); \ + ml->e = eh.lookup({mf->v1, mf->v2}); \ ml++; \ j++; \ } \ @@ -560,8 +558,6 @@ static void convert_mfaces_to_mpolys(ID *id, /* NOTE: we don't convert NGons at all, these are not even real ngons, * they have their own UVs, colors etc - it's more an editing feature. */ - BLI_edgehash_free(eh, nullptr); - *r_faces_num = faces_num; *r_totloop = totloop; } diff --git a/source/blender/blenkernel/intern/mesh_validate.cc b/source/blender/blenkernel/intern/mesh_validate.cc index a23addcb92e..1b74d5115d2 100644 --- a/source/blender/blenkernel/intern/mesh_validate.cc +++ b/source/blender/blenkernel/intern/mesh_validate.cc @@ -13,17 +13,18 @@ #include "CLG_log.h" -#include "BLI_bitmap.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" -#include "BLI_sys_types.h" - -#include "BLI_edgehash.h" +#include "BLI_bitmap.h" +#include "BLI_map.hh" #include "BLI_math_base.h" #include "BLI_math_vector.h" +#include "BLI_ordered_edge.hh" +#include "BLI_sys_types.h" #include "BLI_utildefines.h" +#include "BLI_vector_set.hh" #include "BKE_attribute.hh" #include "BKE_customdata.h" @@ -227,6 +228,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, const bool do_fixes, bool *r_changed) { + using namespace blender; #define REMOVE_EDGE_TAG(_me) \ { \ _me[0] = _me[1]; \ @@ -286,7 +288,8 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, int as_flag; } recalc_flag; - EdgeHash *edge_hash = BLI_edgehash_new_ex(__func__, totedge); + Map edge_hash; + edge_hash.reserve(totedge); BLI_assert(!(do_fixes && mesh == nullptr)); @@ -332,16 +335,14 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, remove = do_fixes; } - if ((edge[0] != edge[1]) && BLI_edgehash_haskey(edge_hash, edge[0], edge[1])) { - PRINT_ERR("\tEdge %u: is a duplicate of %d", - i, - POINTER_AS_INT(BLI_edgehash_lookup(edge_hash, edge[0], edge[1]))); + if ((edge[0] != edge[1]) && edge_hash.contains(edge)) { + PRINT_ERR("\tEdge %u: is a duplicate of %d", i, edge_hash.lookup(edge)); remove = do_fixes; } if (remove == false) { if (edge[0] != edge[1]) { - BLI_edgehash_insert(edge_hash, edge[0], edge[1], POINTER_FROM_INT(i)); + edge_hash.add(edge, i); } } else { @@ -363,7 +364,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, } \ (void)0 #define CHECK_FACE_EDGE(a, b) \ - if (!BLI_edgehash_haskey(edge_hash, mf->a, mf->b)) { \ + if (!edge_hash.contains({mf->a, mf->b})) { \ PRINT_ERR(" face %u: edge " STRINGIFY(a) "/" STRINGIFY(b) " (%u,%u) is missing edge data", \ i, \ mf->a, \ @@ -613,7 +614,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, const int edge_i = corner_edges[corner]; v1 = vert; v2 = corner_verts[sp->loopstart + (j + 1) % poly_size]; - if (!BLI_edgehash_haskey(edge_hash, v1, v2)) { + if (!edge_hash.contains({v1, v2})) { /* Edge not existing. */ PRINT_ERR("\tPoly %u needs missing edge (%d, %d)", sp->index, v1, v2); if (do_fixes) { @@ -628,7 +629,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, * We already know from previous text that a valid edge exists, use it (if allowed)! */ if (do_fixes) { int prev_e = edge_i; - corner_edges[corner] = POINTER_AS_INT(BLI_edgehash_lookup(edge_hash, v1, v2)); + corner_edges[corner] = edge_hash.lookup({v1, v2}); fix_flag.loops_edge = true; PRINT_ERR("\tLoop %d has invalid edge reference (%d), fixed using edge %d", corner, @@ -650,7 +651,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, * use it (if allowed)! */ if (do_fixes) { int prev_e = edge_i; - corner_edges[corner] = POINTER_AS_INT(BLI_edgehash_lookup(edge_hash, v1, v2)); + corner_edges[corner] = edge_hash.lookup({v1, v2}); fix_flag.loops_edge = true; PRINT_ERR( "\tPoly %u has invalid edge reference (%d, is_removed: %d), fixed using edge " @@ -788,8 +789,6 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, MEM_freeN(sort_polys); } - BLI_edgehash_free(edge_hash, nullptr); - /* fix deform verts */ if (dverts) { MDeformVert *dv; @@ -1326,25 +1325,26 @@ void mesh_strip_edges(Mesh *me) void BKE_mesh_calc_edges_tessface(Mesh *mesh) { const int numFaces = mesh->totface_legacy; - EdgeSet *eh = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_FACES(numFaces)); + blender::VectorSet eh; + eh.reserve(numFaces); MFace *mfaces = (MFace *)CustomData_get_layer_for_write( &mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy); MFace *mf = mfaces; for (int i = 0; i < numFaces; i++, mf++) { - BLI_edgeset_add(eh, mf->v1, mf->v2); - BLI_edgeset_add(eh, mf->v2, mf->v3); + eh.add({mf->v1, mf->v2}); + eh.add({mf->v2, mf->v3}); if (mf->v4) { - BLI_edgeset_add(eh, mf->v3, mf->v4); - BLI_edgeset_add(eh, mf->v4, mf->v1); + eh.add({mf->v3, mf->v4}); + eh.add({mf->v4, mf->v1}); } else { - BLI_edgeset_add(eh, mf->v3, mf->v1); + eh.add({mf->v3, mf->v1}); } } - const int numEdges = BLI_edgeset_len(eh); + const int numEdges = eh.size(); /* write new edges into a temporary CustomData */ CustomData edgeData; @@ -1356,21 +1356,13 @@ void BKE_mesh_calc_edges_tessface(Mesh *mesh) &edgeData, CD_PROP_INT32_2D, ".edge_verts", mesh->totedge); int *index = (int *)CustomData_get_layer_for_write(&edgeData, CD_ORIGINDEX, mesh->totedge); - EdgeSetIterator *ehi = BLI_edgesetIterator_new(eh); - for (int i = 0; BLI_edgesetIterator_isDone(ehi) == false; - BLI_edgesetIterator_step(ehi), i++, ege++, index++) - { - BLI_edgesetIterator_getKey(ehi, &(*ege)[0], &(*ege)[1]); - *index = ORIGINDEX_NONE; - } - BLI_edgesetIterator_free(ehi); + memset(index, ORIGINDEX_NONE, sizeof(int) * numEdges); + MutableSpan(ege, numEdges).copy_from(eh.as_span().cast()); /* free old CustomData and assign new one */ CustomData_free(&mesh->edge_data, mesh->totedge); mesh->edge_data = edgeData; mesh->totedge = numEdges; - - BLI_edgeset_free(eh); } /** \} */ diff --git a/source/blender/blenkernel/intern/particle_system.cc b/source/blender/blenkernel/intern/particle_system.cc index 6c48757a167..a32efe15b83 100644 --- a/source/blender/blenkernel/intern/particle_system.cc +++ b/source/blender/blenkernel/intern/particle_system.cc @@ -30,7 +30,6 @@ #include "DNA_texture_types.h" #include "BLI_blenlib.h" -#include "BLI_edgehash.h" #include "BLI_kdopbvh.h" #include "BLI_kdtree.h" #include "BLI_linklist.h" @@ -1666,17 +1665,16 @@ static void sph_springs_modify(ParticleSystem *psys, float dtime) } } } -static EdgeHash *sph_springhash_build(ParticleSystem *psys) +static blender::Map sph_springhash_build(ParticleSystem *psys) { - EdgeHash *springhash = nullptr; + blender::Map springhash; + springhash.reserve(psys->tot_fluidsprings); + ParticleSpring *spring; int i = 0; - springhash = BLI_edgehash_new_ex(__func__, psys->tot_fluidsprings); - for (i = 0, spring = psys->fluid_springs; i < psys->tot_fluidsprings; i++, spring++) { - BLI_edgehash_insert( - springhash, spring->particle_index[0], spring->particle_index[1], POINTER_FROM_INT(i + 1)); + springhash.add({spring->particle_index[0], spring->particle_index[1]}, i + 1); } return springhash; @@ -1808,7 +1806,7 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa SPHRangeData pfr; SPHNeighbor *pfn; float *gravity = sphdata->gravity; - EdgeHash *springhash = sphdata->eh; + const blender::Map &springhash = sphdata->eh; float q, u, rij, dv[3]; float pressure, near_pressure; @@ -1892,9 +1890,9 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa if (spring_constant > 0.0f) { /* Viscoelastic spring force */ - if (pfn->psys == psys[0] && fluid->flag & SPH_VISCOELASTIC_SPRINGS && springhash) { - /* BLI_edgehash_lookup appears to be thread-safe. - z0r */ - spring_index = POINTER_AS_INT(BLI_edgehash_lookup(springhash, index, pfn->index)); + if (pfn->psys == psys[0] && fluid->flag & SPH_VISCOELASTIC_SPRINGS && !springhash.is_empty()) + { + spring_index = springhash.lookup({index, pfn->index}); if (spring_index) { spring = psys[0]->fluid_springs + spring_index - 1; @@ -2183,11 +2181,6 @@ static void psys_sph_flush_springs(SPHData *sphdata) void psys_sph_finalize(SPHData *sphdata) { psys_sph_flush_springs(sphdata); - - if (sphdata->eh) { - BLI_edgehash_free(sphdata->eh, nullptr); - sphdata->eh = nullptr; - } } void psys_sph_density(BVHTree *tree, SPHData *sphdata, float co[3], float vars[2]) diff --git a/source/blender/blenkernel/intern/pbvh_uv_islands.cc b/source/blender/blenkernel/intern/pbvh_uv_islands.cc index a9700742647..8dc6523d470 100644 --- a/source/blender/blenkernel/intern/pbvh_uv_islands.cc +++ b/source/blender/blenkernel/intern/pbvh_uv_islands.cc @@ -2,6 +2,9 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BLI_map.hh" +#include "BLI_math_matrix.hh" +#include "BLI_ordered_edge.hh" #include "BLI_math_geom.h" #include "BLI_math_matrix.hh" #include "BLI_math_vector.h" @@ -107,7 +110,8 @@ static rctf primitive_uv_bounds(const MLoopTri &looptri, const Span uv_m static void mesh_data_init_edges(MeshData &mesh_data) { mesh_data.edges.reserve(mesh_data.looptris.size() * 2); - EdgeHash *eh = BLI_edgehash_new_ex(__func__, mesh_data.looptris.size() * 3); + Map eh; + eh.reserve(mesh_data.looptris.size() * 3); for (int64_t i = 0; i < mesh_data.looptris.size(); i++) { const MLoopTri &tri = mesh_data.looptris[i]; Vector edges; @@ -115,21 +119,19 @@ static void mesh_data_init_edges(MeshData &mesh_data) int v1 = mesh_data.corner_verts[tri.tri[j]]; int v2 = mesh_data.corner_verts[tri.tri[(j + 1) % 3]]; - void **edge_index_ptr; int64_t edge_index; - if (BLI_edgehash_ensure_p(eh, v1, v2, &edge_index_ptr)) { - edge_index = POINTER_AS_INT(*edge_index_ptr) - 1; - *edge_index_ptr = POINTER_FROM_INT(edge_index); - } - else { - edge_index = mesh_data.edges.size(); - *edge_index_ptr = POINTER_FROM_INT(edge_index + 1); - MeshEdge edge; - edge.vert1 = v1; - edge.vert2 = v2; - mesh_data.edges.append(edge); - mesh_data.vert_to_edge_map.add(edge_index, v1, v2); - } + eh.add_or_modify( + {v1, v2}, + [&](int *value) { + edge_index = mesh_data.edges.size(); + *value = edge_index + 1; + mesh_data.edges.append({v1, v2}); + mesh_data.vert_to_edge_map.add(edge_index, v1, v2); + }, + [&](int *value) { + edge_index = *value - 1; + *value = edge_index; + }); edges.append(edge_index); } @@ -142,8 +144,6 @@ static void mesh_data_init_edges(MeshData &mesh_data) mesh_data.edge_to_primitive_map.add(prim_i, edge_i); } } - - BLI_edgehash_free(eh, nullptr); } static constexpr int INVALID_UV_ISLAND_ID = -1; /** diff --git a/source/blender/blenkernel/intern/pbvh_uv_islands.hh b/source/blender/blenkernel/intern/pbvh_uv_islands.hh index e7e5b945a90..998664c7997 100644 --- a/source/blender/blenkernel/intern/pbvh_uv_islands.hh +++ b/source/blender/blenkernel/intern/pbvh_uv_islands.hh @@ -25,7 +25,6 @@ #include #include "BLI_array.hh" -#include "BLI_edgehash.h" #include "BLI_map.hh" #include "BLI_math_matrix_types.hh" #include "BLI_math_vector_types.hh" diff --git a/source/blender/blenkernel/intern/subsurf_ccg.cc b/source/blender/blenkernel/intern/subsurf_ccg.cc index 55d52480eba..8d51e2e6fc9 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.cc +++ b/source/blender/blenkernel/intern/subsurf_ccg.cc @@ -24,8 +24,9 @@ #include "BLI_bitmap.h" #include "BLI_blenlib.h" -#include "BLI_edgehash.h" #include "BLI_memarena.h" +#include "BLI_ordered_edge.hh" +#include "BLI_set.hh" #include "BLI_task.h" #include "BLI_threads.h" #include "BLI_utildefines.h" @@ -264,7 +265,6 @@ static int ss_sync_from_uv(CCGSubSurf *ss, UvVertMap *vmap; blender::Vector fverts; float limit[2]; - EdgeSet *eset; float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */ limit[0] = limit[1] = STD_UV_CONNECT_LIMIT; @@ -308,7 +308,8 @@ static int ss_sync_from_uv(CCGSubSurf *ss, } /* create edges */ - eset = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_FACES(totface)); + blender::Set eset; + eset.reserve(totface); for (i = 0; i < totface; i++) { const blender::IndexRange face = faces[i]; @@ -325,7 +326,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, uint v0 = POINTER_AS_UINT(fverts[j_next]); uint v1 = POINTER_AS_UINT(fverts[j]); - if (BLI_edgeset_add(eset, v0, v1)) { + if (eset.add({v0, v1})) { CCGEdge *e, *orige = ccgSubSurf_getFaceEdge(origf, j_next); CCGEdgeHDL ehdl = POINTER_FROM_INT(face[j_next]); float crease = ccgSubSurf_getEdgeCrease(orige); @@ -335,8 +336,6 @@ static int ss_sync_from_uv(CCGSubSurf *ss, } } - BLI_edgeset_free(eset); - /* create faces */ for (i = 0; i < totface; i++) { const blender::IndexRange face = faces[i]; @@ -912,10 +911,10 @@ static void copyFinalLoopArray_task_cb(void *__restrict userdata, corner_verts[loop_i + 3] = v4; } if (corner_edges) { - corner_edges[loop_i + 0] = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v1, v2)); - corner_edges[loop_i + 1] = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v2, v3)); - corner_edges[loop_i + 2] = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v3, v4)); - corner_edges[loop_i + 3] = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v4, v1)); + corner_edges[loop_i + 0] = ccgdm->ehash->index_of({v1, v2}); + corner_edges[loop_i + 1] = ccgdm->ehash->index_of({v2, v3}); + corner_edges[loop_i + 2] = ccgdm->ehash->index_of({v3, v4}); + corner_edges[loop_i + 3] = ccgdm->ehash->index_of({v4, v1}); } loop_i += 4; @@ -953,15 +952,14 @@ static void ccgDM_copyFinalCornerEdgeArray(DerivedMesh *dm, int *r_corner_edges) if (!ccgdm->ehash) { BLI_mutex_lock(&ccgdm->loops_cache_lock); if (!ccgdm->ehash) { - const blender::int2 *medge; - EdgeHash *ehash; + auto *ehash = new blender::VectorSet(); + ehash->reserve(ccgdm->dm.numEdgeData); - ehash = BLI_edgehash_new_ex(__func__, ccgdm->dm.numEdgeData); - medge = reinterpret_cast( + const blender::int2 *medge = reinterpret_cast( ccgdm->dm.getEdgeArray((DerivedMesh *)ccgdm)); for (int i = 0; i < ccgdm->dm.numEdgeData; i++) { - BLI_edgehash_insert(ehash, medge[i][0], medge[i][1], POINTER_FROM_INT(i)); + ehash->add({medge[i][0], medge[i][1]}); } atomic_cas_ptr((void **)&ccgdm->ehash, ccgdm->ehash, ehash); @@ -1037,9 +1035,7 @@ static void ccgDM_release(DerivedMesh *dm) } } - if (ccgdm->ehash) { - BLI_edgehash_free(ccgdm->ehash, nullptr); - } + delete ccgdm->ehash; if (ccgdm->reverseFaceMap) { MEM_freeN(ccgdm->reverseFaceMap); diff --git a/source/blender/blenlib/BLI_edgehash.h b/source/blender/blenlib/BLI_edgehash.h deleted file mode 100644 index 432803ce135..00000000000 --- a/source/blender/blenlib/BLI_edgehash.h +++ /dev/null @@ -1,239 +0,0 @@ -/* SPDX-FileCopyrightText: 2023 Blender Authors - * - * SPDX-License-Identifier: GPL-2.0-or-later */ - -#pragma once - -/** \file - * \ingroup bli - */ - -#include "BLI_compiler_attrs.h" -#include "BLI_utildefines.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct EdgeHash; -typedef struct EdgeHash EdgeHash; - -struct _EdgeHash_Edge { - uint v_low, v_high; -}; - -struct _EdgeHash_Entry { - struct _EdgeHash_Edge edge; - void *value; -}; - -typedef struct EdgeHashIterator { - struct _EdgeHash_Entry *entries; - uint length; - uint index; -} EdgeHashIterator; - -typedef void (*EdgeHashFreeFP)(void *key); - -enum { - /** - * Only checked for in debug mode. - */ - EDGEHASH_FLAG_ALLOW_DUPES = (1 << 0), -}; - -EdgeHash *BLI_edgehash_new_ex(const char *info, unsigned int nentries_reserve); -EdgeHash *BLI_edgehash_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; -void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP free_value); -void BLI_edgehash_print(EdgeHash *eh); -/** - * Insert edge (\a v0, \a v1) into hash with given value, does - * not check for duplicates. - */ -void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val); -/** - * Assign a new value to a key that may already be in edgehash. - */ -bool BLI_edgehash_reinsert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val); -/** - * Return value for given edge (\a v0, \a v1), or NULL if - * if key does not exist in hash. (If need exists - * to differentiate between key-value being NULL and - * lack of key then see #BLI_edgehash_lookup_p(). - */ -void *BLI_edgehash_lookup(const EdgeHash *eh, - unsigned int v0, - unsigned int v1) ATTR_WARN_UNUSED_RESULT; -/** - * A version of #BLI_edgehash_lookup which accepts a fallback argument. - */ -void *BLI_edgehash_lookup_default(const EdgeHash *eh, - unsigned int v0, - unsigned int v1, - void *default_value) ATTR_WARN_UNUSED_RESULT; -/** - * Return pointer to value for given edge (\a v0, \a v1), - * or NULL if key does not exist in hash. - */ -void **BLI_edgehash_lookup_p(EdgeHash *eh, - unsigned int v0, - unsigned int v1) ATTR_WARN_UNUSED_RESULT; -/** - * Ensure \a (v0, v1) is exists in \a eh. - * - * This handles the common situation where the caller needs ensure a key is added to \a eh, - * constructing a new value in the case the key isn't found. - * Otherwise use the existing value. - * - * Such situations typically incur multiple lookups, however this function - * avoids them by ensuring the key is added, - * returning a pointer to the value so it can be used or initialized by the caller. - * - * \return true when the value didn't need to be added. - * (when false, the caller _must_ initialize the value). - */ -bool BLI_edgehash_ensure_p(EdgeHash *eh, unsigned int v0, unsigned int v1, void ***r_val) - ATTR_WARN_UNUSED_RESULT; -/** - * Remove \a key (v0, v1) from \a eh, or return false if the key wasn't found. - * - * \param v0, v1: The key to remove. - * \param free_value: Optional callback to free the value. - * \return true if \a key was removed from \a eh. - */ -bool BLI_edgehash_remove(EdgeHash *eh, - unsigned int v0, - unsigned int v1, - EdgeHashFreeFP free_value); - -/** - * Remove \a key (v0, v1) from \a eh, returning the value or NULL if the key wasn't found. - * - * \param v0, v1: The key to remove. - * \return the value of \a key int \a eh or NULL. - */ -void *BLI_edgehash_popkey(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT; -/** - * Return boolean true/false if edge (v0,v1) in hash. - */ -bool BLI_edgehash_haskey(const EdgeHash *eh, - unsigned int v0, - unsigned int v1) ATTR_WARN_UNUSED_RESULT; -/** - * Return number of keys in hash. - */ -int BLI_edgehash_len(const EdgeHash *eh) ATTR_WARN_UNUSED_RESULT; -/** - * Remove all edges from hash. - */ -void BLI_edgehash_clear_ex(EdgeHash *eh, EdgeHashFreeFP free_value, uint reserve); -/** - * Wraps #BLI_edgehash_clear_ex with zero entries reserved. - */ -void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP free_value); - -/** - * Create a new #EdgeHashIterator. The hash table must not be mutated - * while the iterator is in use, and the iterator will step exactly - * #BLI_edgehash_len(eh) times before becoming done. - */ -EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; -/** - * Initialize an already allocated #EdgeHashIterator. The hash table must not - * be mutated while the iterator is in use, and the iterator will - * step exactly BLI_edgehash_len(eh) times before becoming done. - * - * \param ehi: The #EdgeHashIterator to initialize. - * \param eh: The #EdgeHash to iterate over. - */ -void BLI_edgehashIterator_init(EdgeHashIterator *ehi, EdgeHash *eh); -/** - * Free an #EdgeHashIterator. - */ -void BLI_edgehashIterator_free(EdgeHashIterator *ehi); - -BLI_INLINE void BLI_edgehashIterator_step(EdgeHashIterator *ehi) -{ - ehi->index++; -} -BLI_INLINE bool BLI_edgehashIterator_isDone(const EdgeHashIterator *ehi) -{ - return ehi->index >= ehi->length; -} -BLI_INLINE void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, int *r_v0, int *r_v1) -{ - struct _EdgeHash_Edge edge = ehi->entries[ehi->index].edge; - *r_v0 = edge.v_low; - *r_v1 = edge.v_high; -} -BLI_INLINE void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi) -{ - return ehi->entries[ehi->index].value; -} -BLI_INLINE void **BLI_edgehashIterator_getValue_p(EdgeHashIterator *ehi) -{ - return &ehi->entries[ehi->index].value; -} -BLI_INLINE void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val) -{ - ehi->entries[ehi->index].value = val; -} - -#define BLI_EDGEHASH_SIZE_GUESS_FROM_LOOPS(totloop) ((totloop) / 2) -#define BLI_EDGEHASH_SIZE_GUESS_FROM_FACES(faces_num) ((faces_num)*2) - -/* *** EdgeSet *** */ - -struct EdgeSet; -typedef struct EdgeSet EdgeSet; - -typedef struct EdgeSetIterator { - struct _EdgeHash_Edge *edges; - uint length; - uint index; -} EdgeSetIterator; - -EdgeSet *BLI_edgeset_new_ex(const char *info, - unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; -EdgeSet *BLI_edgeset_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; -int BLI_edgeset_len(const EdgeSet *es) ATTR_WARN_UNUSED_RESULT; -/** - * A version of BLI_edgeset_insert which checks first if the key is in the set. - * \returns true if a new key has been added. - * - * \note #EdgeHash has no equivalent to this because typically the value would be different. - */ -bool BLI_edgeset_add(EdgeSet *es, unsigned int v0, unsigned int v1); -/** - * Adds the key to the set (no checks for unique keys!). - * Matching #BLI_edgehash_insert - */ -void BLI_edgeset_insert(EdgeSet *es, unsigned int v0, unsigned int v1); -bool BLI_edgeset_haskey(const EdgeSet *es, - unsigned int v0, - unsigned int v1) ATTR_WARN_UNUSED_RESULT; -void BLI_edgeset_free(EdgeSet *es); - -/* rely on inline api for now */ - -EdgeSetIterator *BLI_edgesetIterator_new(EdgeSet *es); -void BLI_edgesetIterator_free(EdgeSetIterator *esi); - -BLI_INLINE void BLI_edgesetIterator_getKey(EdgeSetIterator *esi, int *r_v0, int *r_v1) -{ - struct _EdgeHash_Edge edge = esi->edges[esi->index]; - *r_v0 = edge.v_low; - *r_v1 = edge.v_high; -} -BLI_INLINE void BLI_edgesetIterator_step(EdgeSetIterator *esi) -{ - esi->index++; -} -BLI_INLINE bool BLI_edgesetIterator_isDone(const EdgeSetIterator *esi) -{ - return esi->index >= esi->length; -} - -#ifdef __cplusplus -} -#endif diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 404e778ac1c..ec0c2d73bd8 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -63,7 +63,6 @@ set(SRC intern/dot_export.cc intern/dynlib.c intern/easing.c - intern/edgehash.c intern/endian_switch.c intern/expr_pylike_eval.c intern/fileops.c @@ -221,7 +220,6 @@ set(SRC BLI_dynlib.h BLI_dynstr.h BLI_easing.h - BLI_edgehash.h BLI_endian_defines.h BLI_endian_switch.h BLI_endian_switch_inline.h @@ -498,7 +496,6 @@ if(WITH_GTESTS) tests/BLI_cpp_type_test.cc tests/BLI_delaunay_2d_test.cc tests/BLI_disjoint_set_test.cc - tests/BLI_edgehash_test.cc tests/BLI_expr_pylike_eval_test.cc tests/BLI_fileops_test.cc tests/BLI_function_ref_test.cc diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 934ccb4cfe2..30be271b81c 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -36,7 +36,7 @@ /** * Next prime after `2^n` (skipping 2 & 3). * - * \note Also used by: `BLI_edgehash` & `BLI_smallhash`. + * \note Also used by: `BLI_smallhash`. */ extern const uint BLI_ghash_hash_sizes[]; /* Quiet warning, this is only used by smallhash.c */ const uint BLI_ghash_hash_sizes[] = { diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c deleted file mode 100644 index 1b717a2c292..00000000000 --- a/source/blender/blenlib/intern/edgehash.c +++ /dev/null @@ -1,543 +0,0 @@ -/* SPDX-FileCopyrightText: 2023 Blender Authors - * - * SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup bli - * - * An (edge -> pointer) hash table. - * Using unordered int-pairs as keys. - * - * \note The API matches BLI_ghash.c, but the implementation is different. - */ - -#include -#include -#include -#include - -#include "MEM_guardedalloc.h" - -#include "BLI_edgehash.h" -#include "BLI_strict_flags.h" -#include "BLI_utildefines.h" - -typedef struct _EdgeHash_Edge Edge; -typedef struct _EdgeHash_Entry EdgeHashEntry; - -typedef struct EdgeHash { - EdgeHashEntry *entries; - int32_t *map; - uint32_t slot_mask; - uint capacity_exp; - uint length; - uint dummy_count; -} EdgeHash; - -typedef struct EdgeSet { - Edge *entries; - int32_t *map; - uint32_t slot_mask; - uint capacity_exp; - uint length; -} EdgeSet; - -/* -------------------------------------------------------------------- */ -/** \name Internal Helper Macros & Defines - * \{ */ - -#define ENTRIES_CAPACITY(container) (uint)(1 << (container)->capacity_exp) -#define MAP_CAPACITY(container) (uint)(1 << ((container)->capacity_exp + 1)) -#define CLEAR_MAP(container) \ - memset((container)->map, 0xFF, sizeof(int32_t) * MAP_CAPACITY(container)) -#define UPDATE_SLOT_MASK(container) \ - { \ - (container)->slot_mask = MAP_CAPACITY(container) - 1; \ - } \ - ((void)0) -#define PERTURB_SHIFT 5 - -#define ITER_SLOTS(CONTAINER, EDGE, SLOT, INDEX) \ - uint32_t hash = calc_edge_hash(EDGE); \ - uint32_t mask = (CONTAINER)->slot_mask; \ - uint32_t perturb = hash; \ - int32_t *map = (CONTAINER)->map; \ - uint32_t SLOT = mask & hash; \ - int INDEX = map[SLOT]; \ - for (;; SLOT = mask & ((5 * SLOT) + 1 + perturb), perturb >>= PERTURB_SHIFT, INDEX = map[SLOT]) - -#define SLOT_EMPTY -1 -#define SLOT_DUMMY -2 - -#define CAPACITY_EXP_DEFAULT 3 - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Internal Edge API - * \{ */ - -BLI_INLINE uint32_t calc_edge_hash(Edge edge) -{ - return (edge.v_low << 8) ^ edge.v_high; -} - -BLI_INLINE Edge init_edge(uint v0, uint v1) -{ - /* If there are use cases where we need this it could be removed (or flag to allow), - * for now this helps avoid incorrect usage (creating degenerate geometry). */ - BLI_assert(v0 != v1); - Edge edge; - if (v0 < v1) { - edge.v_low = v0; - edge.v_high = v1; - } - else { - edge.v_low = v1; - edge.v_high = v0; - } - return edge; -} - -BLI_INLINE bool edges_equal(Edge e1, Edge e2) -{ - return memcmp(&e1, &e2, sizeof(Edge)) == 0; -} - -static uint calc_capacity_exp_for_reserve(uint reserve) -{ - uint result = 1; - while (reserve >>= 1) { - result++; - } - return result; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Internal Utility API - * \{ */ - -#define EH_INDEX_HAS_EDGE(eh, index, edge) \ - ((index) >= 0 && edges_equal((edge), (eh)->entries[index].edge)) - -static void edgehash_free_values(EdgeHash *eh, EdgeHashFreeFP free_value) -{ - if (free_value) { - for (uint i = 0; i < eh->length; i++) { - free_value(eh->entries[i].value); - } - } -} - -BLI_INLINE void edgehash_insert_index(EdgeHash *eh, Edge edge, uint entry_index) -{ - ITER_SLOTS (eh, edge, slot, index) { - if (index == SLOT_EMPTY) { - eh->map[slot] = (int32_t)entry_index; - break; - } - } -} - -BLI_INLINE EdgeHashEntry *edgehash_insert_at_slot(EdgeHash *eh, uint slot, Edge edge, void *value) -{ - EdgeHashEntry *entry = &eh->entries[eh->length]; - entry->edge = edge; - entry->value = value; - eh->map[slot] = (int32_t)eh->length; - eh->length++; - return entry; -} - -BLI_INLINE bool edgehash_ensure_can_insert(EdgeHash *eh) -{ - if (UNLIKELY(ENTRIES_CAPACITY(eh) <= eh->length + eh->dummy_count)) { - eh->capacity_exp++; - UPDATE_SLOT_MASK(eh); - eh->dummy_count = 0; - eh->entries = MEM_reallocN(eh->entries, sizeof(EdgeHashEntry) * ENTRIES_CAPACITY(eh)); - eh->map = MEM_reallocN(eh->map, sizeof(int32_t) * MAP_CAPACITY(eh)); - CLEAR_MAP(eh); - for (uint i = 0; i < eh->length; i++) { - edgehash_insert_index(eh, eh->entries[i].edge, i); - } - return true; - } - return false; -} - -BLI_INLINE EdgeHashEntry *edgehash_insert(EdgeHash *eh, Edge edge, void *value) -{ - ITER_SLOTS (eh, edge, slot, index) { - if (index == SLOT_EMPTY) { - return edgehash_insert_at_slot(eh, slot, edge, value); - } - if (index == SLOT_DUMMY) { - eh->dummy_count--; - return edgehash_insert_at_slot(eh, slot, edge, value); - } - } -} - -BLI_INLINE EdgeHashEntry *edgehash_lookup_entry(const EdgeHash *eh, uint v0, uint v1) -{ - Edge edge = init_edge(v0, v1); - - ITER_SLOTS (eh, edge, slot, index) { - if (EH_INDEX_HAS_EDGE(eh, index, edge)) { - return &eh->entries[index]; - } - if (index == SLOT_EMPTY) { - return NULL; - } - } -} - -BLI_INLINE void edgehash_change_index(EdgeHash *eh, Edge edge, int new_index) -{ - ITER_SLOTS (eh, edge, slot, index) { - if (EH_INDEX_HAS_EDGE(eh, index, edge)) { - eh->map[slot] = new_index; - break; - } - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Edge Hash API - * \{ */ - -EdgeHash *BLI_edgehash_new_ex(const char *info, const uint reserve) -{ - EdgeHash *eh = MEM_mallocN(sizeof(EdgeHash), info); - eh->capacity_exp = calc_capacity_exp_for_reserve(reserve); - UPDATE_SLOT_MASK(eh); - eh->length = 0; - eh->dummy_count = 0; - eh->entries = MEM_calloc_arrayN(ENTRIES_CAPACITY(eh), sizeof(EdgeHashEntry), "eh entries"); - eh->map = MEM_malloc_arrayN(MAP_CAPACITY(eh), sizeof(int32_t), "eh map"); - CLEAR_MAP(eh); - return eh; -} - -EdgeHash *BLI_edgehash_new(const char *info) -{ - return BLI_edgehash_new_ex(info, 1 << CAPACITY_EXP_DEFAULT); -} - -void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP free_value) -{ - edgehash_free_values(eh, free_value); - MEM_freeN(eh->map); - MEM_freeN(eh->entries); - MEM_freeN(eh); -} - -void BLI_edgehash_print(EdgeHash *eh) -{ - printf("Edgehash at %p:\n", eh); - printf(" Map:\n"); - for (uint i = 0; i < MAP_CAPACITY(eh); i++) { - int index = eh->map[i]; - printf(" %u: %d", i, index); - if (index >= 0) { - EdgeHashEntry entry = eh->entries[index]; - printf(" -> (%u, %u) -> %p", entry.edge.v_low, entry.edge.v_high, entry.value); - } - printf("\n"); - } - printf(" Entries:\n"); - for (uint i = 0; i < ENTRIES_CAPACITY(eh); i++) { - if (i == eh->length) { - printf(" **** below is rest capacity ****\n"); - } - EdgeHashEntry entry = eh->entries[i]; - printf(" %u: (%u, %u) -> %p\n", i, entry.edge.v_low, entry.edge.v_high, entry.value); - } -} - -void BLI_edgehash_insert(EdgeHash *eh, uint v0, uint v1, void *value) -{ - edgehash_ensure_can_insert(eh); - Edge edge = init_edge(v0, v1); - edgehash_insert(eh, edge, value); -} - -bool BLI_edgehash_reinsert(EdgeHash *eh, uint v0, uint v1, void *value) -{ - Edge edge = init_edge(v0, v1); - - ITER_SLOTS (eh, edge, slot, index) { - if (EH_INDEX_HAS_EDGE(eh, index, edge)) { - eh->entries[index].value = value; - return false; - } - if (index == SLOT_EMPTY) { - if (edgehash_ensure_can_insert(eh)) { - edgehash_insert(eh, edge, value); - } - else { - edgehash_insert_at_slot(eh, slot, edge, value); - } - return true; - } - } -} - -void *BLI_edgehash_lookup_default(const EdgeHash *eh, uint v0, uint v1, void *default_value) -{ - EdgeHashEntry *entry = edgehash_lookup_entry(eh, v0, v1); - return entry ? entry->value : default_value; -} - -void *BLI_edgehash_lookup(const EdgeHash *eh, uint v0, uint v1) -{ - EdgeHashEntry *entry = edgehash_lookup_entry(eh, v0, v1); - return entry ? entry->value : NULL; -} - -void **BLI_edgehash_lookup_p(EdgeHash *eh, uint v0, uint v1) -{ - EdgeHashEntry *entry = edgehash_lookup_entry(eh, v0, v1); - return entry ? &entry->value : NULL; -} - -bool BLI_edgehash_ensure_p(EdgeHash *eh, uint v0, uint v1, void ***r_value) -{ - Edge edge = init_edge(v0, v1); - - ITER_SLOTS (eh, edge, slot, index) { - if (EH_INDEX_HAS_EDGE(eh, index, edge)) { - *r_value = &eh->entries[index].value; - return true; - } - if (index == SLOT_EMPTY) { - if (edgehash_ensure_can_insert(eh)) { - *r_value = &edgehash_insert(eh, edge, NULL)->value; - } - else { - *r_value = &edgehash_insert_at_slot(eh, slot, edge, NULL)->value; - } - return false; - } - } -} - -bool BLI_edgehash_remove(EdgeHash *eh, uint v0, uint v1, EdgeHashFreeFP free_value) -{ - uint old_length = eh->length; - void *value = BLI_edgehash_popkey(eh, v0, v1); - if (free_value && value) { - free_value(value); - } - return old_length > eh->length; -} - -void *BLI_edgehash_popkey(EdgeHash *eh, uint v0, uint v1) -{ - /* Same as #BLI_edgehash_remove but return the value, - * no free value argument since it will be returned */ - - Edge edge = init_edge(v0, v1); - - ITER_SLOTS (eh, edge, slot, index) { - if (EH_INDEX_HAS_EDGE(eh, index, edge)) { - void *value = eh->entries[index].value; - eh->length--; - eh->dummy_count++; - eh->map[slot] = SLOT_DUMMY; - eh->entries[index] = eh->entries[eh->length]; - if ((uint)index < eh->length) { - edgehash_change_index(eh, eh->entries[index].edge, index); - } - return value; - } - if (index == SLOT_EMPTY) { - return NULL; - } - } -} - -bool BLI_edgehash_haskey(const EdgeHash *eh, uint v0, uint v1) -{ - return edgehash_lookup_entry(eh, v0, v1) != NULL; -} - -int BLI_edgehash_len(const EdgeHash *eh) -{ - return (int)eh->length; -} - -void BLI_edgehash_clear_ex(EdgeHash *eh, EdgeHashFreeFP free_value, const uint UNUSED(reserve)) -{ - /* TODO: handle reserve */ - edgehash_free_values(eh, free_value); - eh->length = 0; - eh->dummy_count = 0; - eh->capacity_exp = CAPACITY_EXP_DEFAULT; - CLEAR_MAP(eh); -} - -void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP free_value) -{ - BLI_edgehash_clear_ex(eh, free_value, 0); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Edge Hash Iterator API - * \{ */ - -EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) -{ - EdgeHashIterator *ehi = MEM_mallocN(sizeof(EdgeHashIterator), __func__); - BLI_edgehashIterator_init(ehi, eh); - return ehi; -} - -void BLI_edgehashIterator_init(EdgeHashIterator *ehi, EdgeHash *eh) -{ - ehi->entries = eh->entries; - ehi->length = eh->length; - ehi->index = 0; -} - -void BLI_edgehashIterator_free(EdgeHashIterator *ehi) -{ - MEM_freeN(ehi); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name EdgeSet API - * - * Use edgehash API to give 'set' functionality - * \{ */ - -#define ES_INDEX_HAS_EDGE(es, index, edge) \ - (index) >= 0 && edges_equal((edge), (es)->entries[index]) - -EdgeSet *BLI_edgeset_new_ex(const char *info, const uint reserve) -{ - EdgeSet *es = MEM_mallocN(sizeof(EdgeSet), info); - es->capacity_exp = calc_capacity_exp_for_reserve(reserve); - UPDATE_SLOT_MASK(es); - es->length = 0; - es->entries = MEM_malloc_arrayN(ENTRIES_CAPACITY(es), sizeof(Edge), "es entries"); - es->map = MEM_malloc_arrayN(MAP_CAPACITY(es), sizeof(int32_t), "es map"); - CLEAR_MAP(es); - return es; -} - -EdgeSet *BLI_edgeset_new(const char *info) -{ - return BLI_edgeset_new_ex(info, 1 << CAPACITY_EXP_DEFAULT); -} - -void BLI_edgeset_free(EdgeSet *es) -{ - MEM_freeN(es->entries); - MEM_freeN(es->map); - MEM_freeN(es); -} - -int BLI_edgeset_len(const EdgeSet *es) -{ - return (int)es->length; -} - -static void edgeset_insert_index(EdgeSet *es, Edge edge, uint entry_index) -{ - ITER_SLOTS (es, edge, slot, index) { - if (index == SLOT_EMPTY) { - es->map[slot] = (int)entry_index; - break; - } - } -} - -BLI_INLINE void edgeset_ensure_can_insert(EdgeSet *es) -{ - if (UNLIKELY(ENTRIES_CAPACITY(es) <= es->length)) { - es->capacity_exp++; - UPDATE_SLOT_MASK(es); - es->entries = MEM_reallocN(es->entries, sizeof(Edge) * ENTRIES_CAPACITY(es)); - es->map = MEM_reallocN(es->map, sizeof(int32_t) * MAP_CAPACITY(es)); - CLEAR_MAP(es); - for (uint i = 0; i < es->length; i++) { - edgeset_insert_index(es, es->entries[i], i); - } - } -} - -BLI_INLINE void edgeset_insert_at_slot(EdgeSet *es, uint slot, Edge edge) -{ - es->entries[es->length] = edge; - es->map[slot] = (int)es->length; - es->length++; -} - -bool BLI_edgeset_add(EdgeSet *es, uint v0, uint v1) -{ - edgeset_ensure_can_insert(es); - Edge edge = init_edge(v0, v1); - - ITER_SLOTS (es, edge, slot, index) { - if (ES_INDEX_HAS_EDGE(es, index, edge)) { - return false; - } - if (index == SLOT_EMPTY) { - edgeset_insert_at_slot(es, slot, edge); - return true; - } - } -} - -void BLI_edgeset_insert(EdgeSet *es, uint v0, uint v1) -{ - edgeset_ensure_can_insert(es); - Edge edge = init_edge(v0, v1); - - ITER_SLOTS (es, edge, slot, index) { - if (index == SLOT_EMPTY) { - edgeset_insert_at_slot(es, slot, edge); - return; - } - } -} - -bool BLI_edgeset_haskey(const EdgeSet *es, uint v0, uint v1) -{ - Edge edge = init_edge(v0, v1); - - ITER_SLOTS (es, edge, slot, index) { - if (ES_INDEX_HAS_EDGE(es, index, edge)) { - return true; - } - if (index == SLOT_EMPTY) { - return false; - } - } -} - -EdgeSetIterator *BLI_edgesetIterator_new(EdgeSet *es) -{ - EdgeSetIterator *esi = MEM_mallocN(sizeof(EdgeSetIterator), __func__); - esi->edges = es->entries; - esi->length = es->length; - esi->index = 0; - return esi; -} - -void BLI_edgesetIterator_free(EdgeSetIterator *esi) -{ - MEM_freeN(esi); -} - -/** \} */ diff --git a/source/blender/blenlib/tests/BLI_edgehash_test.cc b/source/blender/blenlib/tests/BLI_edgehash_test.cc deleted file mode 100644 index e8ac3e76108..00000000000 --- a/source/blender/blenlib/tests/BLI_edgehash_test.cc +++ /dev/null @@ -1,410 +0,0 @@ -/* SPDX-FileCopyrightText: 2023 Blender Authors - * - * SPDX-License-Identifier: Apache-2.0 */ - -#include "testing/testing.h" -#include -#include -#include - -#include "BLI_edgehash.h" -#include "BLI_utildefines.h" - -#define VALUE_1 POINTER_FROM_INT(1) -#define VALUE_2 POINTER_FROM_INT(2) -#define VALUE_3 POINTER_FROM_INT(3) - -TEST(edgehash, InsertIncreasesLength) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - ASSERT_EQ(BLI_edgehash_len(eh), 0); - BLI_edgehash_insert(eh, 1, 2, VALUE_1); - ASSERT_EQ(BLI_edgehash_len(eh), 1); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, ReinsertNewIncreasesLength) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - ASSERT_EQ(BLI_edgehash_len(eh), 0); - BLI_edgehash_reinsert(eh, 1, 2, VALUE_1); - ASSERT_EQ(BLI_edgehash_len(eh), 1); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, ReinsertExistingDoesNotIncreaseLength) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - ASSERT_EQ(BLI_edgehash_len(eh), 0); - BLI_edgehash_reinsert(eh, 1, 2, VALUE_1); - ASSERT_EQ(BLI_edgehash_len(eh), 1); - BLI_edgehash_reinsert(eh, 1, 2, VALUE_2); - ASSERT_EQ(BLI_edgehash_len(eh), 1); - BLI_edgehash_reinsert(eh, 2, 1, VALUE_2); - ASSERT_EQ(BLI_edgehash_len(eh), 1); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, ReinsertCanChangeValue) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - BLI_edgehash_insert(eh, 1, 2, VALUE_1); - ASSERT_EQ(BLI_edgehash_lookup(eh, 1, 2), VALUE_1); - BLI_edgehash_reinsert(eh, 2, 1, VALUE_2); - ASSERT_EQ(BLI_edgehash_lookup(eh, 1, 2), VALUE_2); - BLI_edgehash_reinsert(eh, 1, 2, VALUE_3); - ASSERT_EQ(BLI_edgehash_lookup(eh, 2, 1), VALUE_3); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, LookupExisting) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - BLI_edgehash_insert(eh, 1, 2, VALUE_1); - ASSERT_EQ(BLI_edgehash_lookup(eh, 1, 2), VALUE_1); - ASSERT_EQ(BLI_edgehash_lookup(eh, 2, 1), VALUE_1); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, LookupNonExisting) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - ASSERT_EQ(BLI_edgehash_lookup(eh, 1, 2), nullptr); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, LookupNonExistingWithDefault) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - ASSERT_EQ(BLI_edgehash_lookup_default(eh, 1, 2, VALUE_1), VALUE_1); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, LookupExistingWithDefault) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - BLI_edgehash_insert(eh, 1, 2, VALUE_1); - ASSERT_EQ(BLI_edgehash_lookup_default(eh, 1, 2, VALUE_2), VALUE_1); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, LookupPExisting) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - void *value = VALUE_1; - BLI_edgehash_insert(eh, 1, 2, value); - void **value_p = BLI_edgehash_lookup_p(eh, 1, 2); - ASSERT_EQ(*value_p, VALUE_1); - *value_p = VALUE_2; - ASSERT_EQ(BLI_edgehash_lookup(eh, 1, 2), VALUE_2); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, LookupPNonExisting) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - ASSERT_EQ(BLI_edgehash_lookup_p(eh, 1, 2), nullptr); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, EnsurePNonExisting) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - void **value_p; - bool existed = BLI_edgehash_ensure_p(eh, 1, 2, &value_p); - ASSERT_FALSE(existed); - *value_p = VALUE_1; - ASSERT_EQ(BLI_edgehash_lookup(eh, 1, 2), VALUE_1); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, EnsurePExisting) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - BLI_edgehash_insert(eh, 1, 2, VALUE_1); - void **value_p; - bool existed = BLI_edgehash_ensure_p(eh, 1, 2, &value_p); - ASSERT_TRUE(existed); - ASSERT_EQ(*value_p, VALUE_1); - *value_p = VALUE_2; - ASSERT_EQ(BLI_edgehash_lookup(eh, 1, 2), VALUE_2); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, RemoveExistingDecreasesLength) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - BLI_edgehash_insert(eh, 1, 2, VALUE_1); - ASSERT_EQ(BLI_edgehash_len(eh), 1); - bool has_been_removed = BLI_edgehash_remove(eh, 1, 2, nullptr); - ASSERT_EQ(BLI_edgehash_len(eh), 0); - ASSERT_TRUE(has_been_removed); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, RemoveNonExistingDoesNotDecreaseLength) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - BLI_edgehash_insert(eh, 1, 2, VALUE_1); - ASSERT_EQ(BLI_edgehash_len(eh), 1); - bool has_been_removed = BLI_edgehash_remove(eh, 4, 5, nullptr); - ASSERT_EQ(BLI_edgehash_len(eh), 1); - ASSERT_FALSE(has_been_removed); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, PopKeyTwice) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - BLI_edgehash_insert(eh, 1, 2, VALUE_1); - ASSERT_EQ(BLI_edgehash_popkey(eh, 1, 2), VALUE_1); - ASSERT_EQ(BLI_edgehash_popkey(eh, 1, 2), nullptr); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, LookupInvertedIndices) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - BLI_edgehash_insert(eh, 1, 2, VALUE_1); - ASSERT_EQ(BLI_edgehash_lookup(eh, 2, 1), VALUE_1); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, HasKeyExisting) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - BLI_edgehash_insert(eh, 1, 2, VALUE_1); - ASSERT_TRUE(BLI_edgehash_haskey(eh, 1, 2)); - ASSERT_TRUE(BLI_edgehash_haskey(eh, 2, 1)); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, HasKeyNonExisting) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - ASSERT_FALSE(BLI_edgehash_haskey(eh, 1, 2)); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, ClearSetsLengthToZero) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - BLI_edgehash_insert(eh, 1, 2, VALUE_1); - BLI_edgehash_insert(eh, 1, 2, VALUE_2); - ASSERT_EQ(BLI_edgehash_len(eh), 2); - BLI_edgehash_clear(eh, nullptr); - ASSERT_EQ(BLI_edgehash_len(eh), 0); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, IteratorFindsAllValues) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - BLI_edgehash_insert(eh, 1, 2, VALUE_1); - BLI_edgehash_insert(eh, 1, 3, VALUE_2); - BLI_edgehash_insert(eh, 1, 4, VALUE_3); - - EdgeHashIterator *ehi = BLI_edgehashIterator_new(eh); - auto *a = BLI_edgehashIterator_getValue(ehi); - BLI_edgehashIterator_step(ehi); - auto *b = BLI_edgehashIterator_getValue(ehi); - BLI_edgehashIterator_step(ehi); - auto *c = BLI_edgehashIterator_getValue(ehi); - BLI_edgehashIterator_step(ehi); - - ASSERT_NE(a, b); - ASSERT_NE(b, c); - ASSERT_NE(a, c); - ASSERT_TRUE(ELEM(a, VALUE_1, VALUE_2, VALUE_3)); - ASSERT_TRUE(ELEM(b, VALUE_1, VALUE_2, VALUE_3)); - ASSERT_TRUE(ELEM(c, VALUE_1, VALUE_2, VALUE_3)); - - BLI_edgehashIterator_free(ehi); - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, IterateIsDone) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - BLI_edgehash_insert(eh, 1, 2, VALUE_1); - BLI_edgehash_insert(eh, 1, 3, VALUE_2); - BLI_edgehash_insert(eh, 1, 4, VALUE_3); - - EdgeHashIterator *ehi = BLI_edgehashIterator_new(eh); - ASSERT_FALSE(BLI_edgehashIterator_isDone(ehi)); - BLI_edgehashIterator_step(ehi); - ASSERT_FALSE(BLI_edgehashIterator_isDone(ehi)); - BLI_edgehashIterator_step(ehi); - ASSERT_FALSE(BLI_edgehashIterator_isDone(ehi)); - BLI_edgehashIterator_step(ehi); - ASSERT_TRUE(BLI_edgehashIterator_isDone(ehi)); - - BLI_edgehashIterator_free(ehi); - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgehash, DoubleRemove) -{ - EdgeHash *eh = BLI_edgehash_new(__func__); - - BLI_edgehash_insert(eh, 1, 2, VALUE_1); - BLI_edgehash_insert(eh, 1, 3, VALUE_2); - BLI_edgehash_insert(eh, 1, 4, VALUE_3); - ASSERT_EQ(BLI_edgehash_len(eh), 3); - - BLI_edgehash_remove(eh, 1, 2, nullptr); - BLI_edgehash_remove(eh, 1, 3, nullptr); - ASSERT_EQ(BLI_edgehash_len(eh), 1); - - BLI_edgehash_free(eh, nullptr); -} - -struct Edge { - uint v1, v2; -}; - -TEST(edgehash, StressTest) -{ - std::srand(0); - int amount = 10000; - - std::vector edges; - for (int i = 0; i < amount; i++) { - edges.push_back({uint(i), amount + uint(std::rand()) % 12345}); - } - - EdgeHash *eh = BLI_edgehash_new(__func__); - - /* first insert all the edges */ - for (int i = 0; i < edges.size(); i++) { - BLI_edgehash_insert(eh, edges[i].v1, edges[i].v2, POINTER_FROM_INT(i)); - } - - std::vector shuffled = edges; - std::shuffle(shuffled.begin(), shuffled.end(), std::default_random_engine()); - - /* then remove half of them */ - int remove_until = shuffled.size() / 2; - for (int i = 0; i < remove_until; i++) { - BLI_edgehash_remove(eh, shuffled[i].v2, shuffled[i].v1, nullptr); - } - - ASSERT_EQ(BLI_edgehash_len(eh), edges.size() - remove_until); - - /* check if the right ones have been removed */ - for (int i = 0; i < shuffled.size(); i++) { - bool haskey = BLI_edgehash_haskey(eh, shuffled[i].v1, shuffled[i].v2); - if (i < remove_until) { - ASSERT_FALSE(haskey); - } - else { - ASSERT_TRUE(haskey); - } - } - - /* reinsert all edges */ - for (int i = 0; i < edges.size(); i++) { - BLI_edgehash_reinsert(eh, edges[i].v1, edges[i].v2, POINTER_FROM_INT(i)); - } - - ASSERT_EQ(BLI_edgehash_len(eh), edges.size()); - - /* pop all edges */ - for (int i = 0; i < edges.size(); i++) { - int value = POINTER_AS_INT(BLI_edgehash_popkey(eh, edges[i].v1, edges[i].v2)); - ASSERT_EQ(i, value); - } - - ASSERT_EQ(BLI_edgehash_len(eh), 0); - - BLI_edgehash_free(eh, nullptr); -} - -TEST(edgeset, AddNonExistingIncreasesLength) -{ - EdgeSet *es = BLI_edgeset_new(__func__); - - ASSERT_EQ(BLI_edgeset_len(es), 0); - BLI_edgeset_add(es, 1, 2); - ASSERT_EQ(BLI_edgeset_len(es), 1); - BLI_edgeset_add(es, 1, 3); - ASSERT_EQ(BLI_edgeset_len(es), 2); - BLI_edgeset_add(es, 1, 4); - ASSERT_EQ(BLI_edgeset_len(es), 3); - - BLI_edgeset_free(es); -} - -TEST(edgeset, AddExistingDoesNotIncreaseLength) -{ - EdgeSet *es = BLI_edgeset_new(__func__); - - ASSERT_EQ(BLI_edgeset_len(es), 0); - BLI_edgeset_add(es, 1, 2); - ASSERT_EQ(BLI_edgeset_len(es), 1); - BLI_edgeset_add(es, 2, 1); - ASSERT_EQ(BLI_edgeset_len(es), 1); - BLI_edgeset_add(es, 1, 2); - ASSERT_EQ(BLI_edgeset_len(es), 1); - - BLI_edgeset_free(es); -} - -TEST(edgeset, HasKeyNonExisting) -{ - EdgeSet *es = BLI_edgeset_new(__func__); - - ASSERT_FALSE(BLI_edgeset_haskey(es, 1, 2)); - - BLI_edgeset_free(es); -} - -TEST(edgeset, HasKeyExisting) -{ - EdgeSet *es = BLI_edgeset_new(__func__); - - BLI_edgeset_insert(es, 1, 2); - ASSERT_TRUE(BLI_edgeset_haskey(es, 1, 2)); - - BLI_edgeset_free(es); -} diff --git a/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc b/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc index 7f65caa3f5e..301ed914ee5 100644 --- a/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc +++ b/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc @@ -14,8 +14,9 @@ #include "MEM_guardedalloc.h" #include "BLI_array_utils.h" -#include "BLI_edgehash.h" +#include "BLI_map.hh" #include "BLI_math_geom.h" +#include "BLI_ordered_edge.hh" #include "BLI_polyfill_2d.h" #include "BLI_utildefines.h" @@ -92,42 +93,29 @@ static void test_polyfill_topology(const float /*poly*/[][2], const uint tris[][3], const uint tris_num) { - EdgeHash *edgehash = BLI_edgehash_new(__func__); - EdgeHashIterator *ehi; + blender::Map edgehash; uint i; for (i = 0; i < tris_num; i++) { uint j; for (j = 0; j < 3; j++) { const uint v1 = tris[i][j]; const uint v2 = tris[i][(j + 1) % 3]; - void **p = BLI_edgehash_lookup_p(edgehash, v1, v2); - if (p) { - *p = (void *)(intptr_t(*p) + intptr_t(1)); - } - else { - BLI_edgehash_insert(edgehash, v1, v2, (void *)intptr_t(1)); - } + edgehash.add_or_modify( + {v1, v2}, [](int *value) { *value = 1; }, [](int *value) { (*value)++; }); } } - EXPECT_EQ(BLI_edgehash_len(edgehash), poly_num + (poly_num - 3)); + EXPECT_EQ(edgehash.size(), poly_num + (poly_num - 3)); for (i = 0; i < poly_num; i++) { const uint v1 = i; const uint v2 = (i + 1) % poly_num; - void **p = BLI_edgehash_lookup_p(edgehash, v1, v2); - EXPECT_NE((void *)p, nullptr); - EXPECT_EQ(intptr_t(*p), 1); + EXPECT_TRUE(edgehash.contains({v1, v2})); + EXPECT_EQ(edgehash.lookup({v1, v2}), 1); } - for (ehi = BLI_edgehashIterator_new(edgehash), i = 0; BLI_edgehashIterator_isDone(ehi) == false; - BLI_edgehashIterator_step(ehi), i++) - { - void **p = BLI_edgehashIterator_getValue_p(ehi); - EXPECT_TRUE(ELEM(intptr_t(*p), 1, 2)); + for (const int value : edgehash.values()) { + EXPECT_TRUE(ELEM(value, 1, 2)); } - - BLI_edgehashIterator_free(ehi); - BLI_edgehash_free(edgehash, nullptr); } /** diff --git a/source/blender/bmesh/intern/bmesh_mesh_validate.cc b/source/blender/bmesh/intern/bmesh_mesh_validate.cc index 3fe228e2188..cb5850b67a6 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_validate.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_validate.cc @@ -11,7 +11,8 @@ /* debug builds only */ #ifdef DEBUG -# include "BLI_edgehash.h" +# include "BLI_map.hh" +# include "BLI_ordered_edge.hh" # include "BLI_utildefines.h" # include "bmesh.h" @@ -37,7 +38,8 @@ bool BM_mesh_validate(BMesh *bm) { - EdgeHash *edge_hash = BLI_edgehash_new_ex(__func__, bm->totedge); + blender::Map edge_hash; + edge_hash.reserve(bm->totedge); int errtot; BMIter iter; @@ -70,21 +72,17 @@ bool BM_mesh_validate(BMesh *bm) /* check edges */ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { - void **val_p; - if (e->v1 == e->v2) { ERRMSG("edge %d: duplicate index: %d", i, BM_elem_index_get(e->v1)); } /* build edgehash at the same time */ - if (BLI_edgehash_ensure_p( - edge_hash, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2), &val_p)) { - BMEdge *e_other = static_cast(*val_p); - ERRMSG("edge %d, %d: are duplicates", i, BM_elem_index_get(e_other)); - } - else { - *val_p = e; - } + edge_hash.add_or_modify( + {BM_elem_index_get(e->v1), BM_elem_index_get(e->v2)}, + [&](BMEdge **value) { *value = e; }, + [&](BMEdge **value) { + ERRMSG("edge %d, %d: are duplicates", i, BM_elem_index_get(*value)); + }); } /* edge radial structure */ @@ -192,8 +190,6 @@ bool BM_mesh_validate(BMesh *bm) } while ((l_iter = l_iter->next) != l_first); } - BLI_edgehash_free(edge_hash, nullptr); - const bool is_valid = (errtot == 0); ERRMSG("Finished - errors %d", errtot); return is_valid; diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.cc b/source/blender/draw/intern/draw_cache_impl_mesh.cc index dd59c8cefab..ddc7b799227 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.cc +++ b/source/blender/draw/intern/draw_cache_impl_mesh.cc @@ -14,7 +14,6 @@ #include "BLI_bitmap.h" #include "BLI_buffer.h" -#include "BLI_edgehash.h" #include "BLI_index_range.hh" #include "BLI_listbase.h" #include "BLI_map.hh" diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc index cfb60f3c626..c5ec644b72f 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc @@ -6,7 +6,8 @@ * \ingroup draw */ -#include "BLI_edgehash.h" +#include "BLI_map.hh" +#include "BLI_ordered_edge.hh" #include "BLI_vector.hh" #include "MEM_guardedalloc.h" @@ -24,7 +25,7 @@ namespace blender::draw { struct MeshExtract_LineAdjacency_Data { GPUIndexBufBuilder elb; - EdgeHash *eh; + Map *eh; bool is_manifold; /* Array to convert vert index to any loop index of this vert. */ uint *vert_to_loop; @@ -38,7 +39,8 @@ static void line_adjacency_data_init(MeshExtract_LineAdjacency_Data *data, data->vert_to_loop = static_cast(MEM_callocN(sizeof(uint) * vert_len, __func__)); GPU_indexbuf_init(&data->elb, GPU_PRIM_LINES_ADJ, tess_edge_len, loop_len); - data->eh = BLI_edgehash_new_ex(__func__, tess_edge_len); + data->eh = new Map(); + data->eh->reserve(tess_edge_len); data->is_manifold = true; } @@ -66,34 +68,41 @@ BLI_INLINE void lines_adjacency_triangle( SHIFT3(uint, l3, l2, l1); bool inv_indices = (v2 > v3); - void **pval; - bool value_is_init = BLI_edgehash_ensure_p(data->eh, v2, v3, &pval); - int v_data = POINTER_AS_INT(*pval); - if (!value_is_init || v_data == NO_EDGE) { - /* Save the winding order inside the sign bit. Because the - * Edge-hash sort the keys and we need to compare winding later. */ - int value = int(l1) + 1; /* 0 cannot be signed so add one. */ - *pval = POINTER_FROM_INT((inv_indices) ? -value : value); - /* Store loop indices for remaining non-manifold edges. */ - data->vert_to_loop[v2] = l2; - data->vert_to_loop[v3] = l3; - } - else { - /* HACK Tag as not used. Prevent overhead of BLI_edgehash_remove. */ - *pval = POINTER_FROM_INT(NO_EDGE); - bool inv_opposite = (v_data < 0); - uint l_opposite = uint(abs(v_data)) - 1; - /* TODO: Make this part thread-safe. */ - if (inv_opposite == inv_indices) { - /* Don't share edge if triangles have non matching winding. */ - GPU_indexbuf_add_line_adj_verts(elb, l1, l2, l3, l1); - GPU_indexbuf_add_line_adj_verts(elb, l_opposite, l2, l3, l_opposite); - data->is_manifold = false; - } - else { - GPU_indexbuf_add_line_adj_verts(elb, l1, l2, l3, l_opposite); - } - } + data->eh->add_or_modify( + {v2, v3}, + [&](int *value) { + int new_value = int(l1) + 1; /* 0 cannot be signed so add one. */ + *value = inv_indices ? -new_value : new_value; + /* Store loop indices for remaining non-manifold edges. */ + data->vert_to_loop[v2] = l2; + data->vert_to_loop[v3] = l3; + }, + [&](int *value) { + int v_data = *value; + if (v_data == NO_EDGE) { + int new_value = int(l1) + 1; /* 0 cannot be signed so add one. */ + *value = inv_indices ? -new_value : new_value; + /* Store loop indices for remaining non-manifold edges. */ + data->vert_to_loop[v2] = l2; + data->vert_to_loop[v3] = l3; + } + else { + /* HACK Tag as not used. Prevent overhead of BLI_edgehash_remove. */ + *value = NO_EDGE; + bool inv_opposite = (v_data < 0); + uint l_opposite = uint(abs(v_data)) - 1; + /* TODO: Make this part thread-safe. */ + if (inv_opposite == inv_indices) { + /* Don't share edge if triangles have non matching winding. */ + GPU_indexbuf_add_line_adj_verts(elb, l1, l2, l3, l1); + GPU_indexbuf_add_line_adj_verts(elb, l_opposite, l2, l3, l_opposite); + data->is_manifold = false; + } + else { + GPU_indexbuf_add_line_adj_verts(elb, l1, l2, l3, l_opposite); + } + } + }); } } @@ -142,24 +151,25 @@ static void extract_lines_adjacency_finish(const MeshRenderData & /*mr*/, GPUIndexBuf *ibo = static_cast(buf); MeshExtract_LineAdjacency_Data *data = static_cast(_data); /* Create edges for remaining non manifold edges. */ - EdgeHashIterator *ehi = BLI_edgehashIterator_new(data->eh); - for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { - int v2, v3, l1, l2, l3; - int v_data = POINTER_AS_INT(BLI_edgehashIterator_getValue(ehi)); - if (v_data != NO_EDGE) { - BLI_edgehashIterator_getKey(ehi, &v2, &v3); - l1 = uint(abs(v_data)) - 1; - if (v_data < 0) { /* `inv_opposite`. */ - std::swap(v2, v3); - } - l2 = data->vert_to_loop[v2]; - l3 = data->vert_to_loop[v3]; - GPU_indexbuf_add_line_adj_verts(&data->elb, l1, l2, l3, l1); - data->is_manifold = false; + for (const auto item : data->eh->items()) { + int v_data = item.value; + if (v_data == NO_EDGE) { + continue; } + + int v2 = item.key.v_low; + int v3 = item.key.v_high; + + int l1 = uint(abs(v_data)) - 1; + if (v_data < 0) { /* `inv_opposite`. */ + std::swap(v2, v3); + } + int l2 = data->vert_to_loop[v2]; + int l3 = data->vert_to_loop[v3]; + GPU_indexbuf_add_line_adj_verts(&data->elb, l1, l2, l3, l1); + data->is_manifold = false; } - BLI_edgehashIterator_free(ehi); - BLI_edgehash_free(data->eh, nullptr); + delete data->eh; cache.is_manifold = data->is_manifold; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc index 63eeeb653eb..45961f53594 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc @@ -8,10 +8,10 @@ #include "MEM_guardedalloc.h" -#include "BLI_edgehash.h" #include "BLI_jitter_2d.h" #include "BLI_math_matrix.h" #include "BLI_math_rotation.h" +#include "BLI_ordered_edge.hh" #include "BKE_bvhutils.h" #include "BKE_editmesh_bvh.h" @@ -534,7 +534,8 @@ static void statvis_calc_sharp(const MeshRenderData &mr, float *r_sharp) else { /* first assign float values to verts */ - EdgeHash *eh = BLI_edgehash_new_ex(__func__, mr.edge_len); + Map eh; + eh.reserve(mr.edge_len); for (int face_index = 0; face_index < mr.face_len; face_index++) { const IndexRange face = mr.faces[face_index]; @@ -542,28 +543,28 @@ static void statvis_calc_sharp(const MeshRenderData &mr, float *r_sharp) const int vert_curr = mr.corner_verts[face.start() + (i + 0) % face.size()]; const int vert_next = mr.corner_verts[face.start() + (i + 1) % face.size()]; float angle; - void **pval; - bool value_is_init = BLI_edgehash_ensure_p(eh, vert_curr, vert_next, &pval); - if (!value_is_init) { - *pval = (void *)&mr.face_normals[face_index]; - /* non-manifold edge, yet... */ - continue; - } - if (*pval != nullptr) { - const float *f1_no = mr.face_normals[face_index]; - const float *f2_no = static_cast(*pval); - angle = angle_normalized_v3v3(f1_no, f2_no); - angle = is_edge_convex_v3( - mr.vert_positions[vert_curr], mr.vert_positions[vert_next], f1_no, f2_no) ? - angle : - -angle; - /* Tag as manifold. */ - *pval = nullptr; - } - else { - /* non-manifold edge */ - angle = DEG2RADF(90.0f); - } + eh.add_or_modify( + {vert_curr, vert_next}, + [&](int *value) { *value = face_index; }, + [&](int *value) { + const int other_face_index = *value; + if (other_face_index == -1) { + /* non-manifold edge */ + angle = DEG2RADF(90.0f); + return; + } + const float *f1_no = mr.face_normals[face_index]; + const float *f2_no = mr.face_normals[other_face_index]; + angle = angle_normalized_v3v3(f1_no, f2_no); + angle = is_edge_convex_v3(mr.vert_positions[vert_curr], + mr.vert_positions[vert_next], + f1_no, + f2_no) ? + angle : + -angle; + /* Tag as manifold. */ + *value = -1; + }); float *col1 = &vert_angles[vert_curr]; float *col2 = &vert_angles[vert_next]; *col1 = max_ff(*col1, angle); @@ -571,20 +572,13 @@ static void statvis_calc_sharp(const MeshRenderData &mr, float *r_sharp) } } /* Remaining non manifold edges. */ - EdgeHashIterator *ehi = BLI_edgehashIterator_new(eh); - for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { - if (BLI_edgehashIterator_getValue(ehi) != nullptr) { - int v1, v2; - const float angle = DEG2RADF(90.0f); - BLI_edgehashIterator_getKey(ehi, &v1, &v2); - float *col1 = &vert_angles[v1]; - float *col2 = &vert_angles[v2]; - *col1 = max_ff(*col1, angle); - *col2 = max_ff(*col2, angle); - } + for (const OrderedEdge &edge : eh.keys()) { + const float angle = DEG2RADF(90.0f); + float *col1 = &vert_angles[edge.v_low]; + float *col2 = &vert_angles[edge.v_high]; + *col1 = max_ff(*col1, angle); + *col2 = max_ff(*col2, angle); } - BLI_edgehashIterator_free(ehi); - BLI_edgehash_free(eh, nullptr); for (int l_index = 0; l_index < mr.loop_len; l_index++) { const int vert = mr.corner_verts[l_index]; diff --git a/source/blender/editors/armature/meshlaplacian.cc b/source/blender/editors/armature/meshlaplacian.cc index c74cc8d4983..954e68b9ed7 100644 --- a/source/blender/editors/armature/meshlaplacian.cc +++ b/source/blender/editors/armature/meshlaplacian.cc @@ -14,12 +14,13 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "BLI_edgehash.h" +#include "BLI_map.hh" #include "BLI_math_geom.h" #include "BLI_math_matrix.h" #include "BLI_math_rotation.h" #include "BLI_math_vector.h" #include "BLI_memarena.h" +#include "BLI_ordered_edge.hh" #include "BLI_string.h" #include "BLT_translation.h" @@ -67,7 +68,7 @@ struct LaplacianSystem { int storeweights; /* store cotangent weights in fweights */ bool variablesdone; /* variables set in linear system */ - EdgeHash *edgehash; /* edge hash for construction */ + blender::Map edgehash; /* edge hash for construction */ struct HeatWeighting { const MLoopTri *mlooptri; @@ -100,21 +101,19 @@ struct LaplacianSystem { * vertex and adjacent faces, since we don't store this adjacency. Also, the * formulas are tweaked a bit to work for non-manifold meshes. */ -static void laplacian_increase_edge_count(EdgeHash *edgehash, int v1, int v2) +static void laplacian_increase_edge_count(blender::Map &edgehash, + int v1, + int v2) { - void **p; - - if (BLI_edgehash_ensure_p(edgehash, v1, v2, &p)) { - *p = (void *)(intptr_t(*p) + intptr_t(1)); - } - else { - *p = (void *)intptr_t(1); - } + edgehash.add_or_modify( + {v1, v2}, [](int *value) { *value = 1; }, [](int *value) { (*value)++; }); } -static int laplacian_edge_count(EdgeHash *edgehash, int v1, int v2) +static int laplacian_edge_count(const blender::Map &edgehash, + int v1, + int v2) { - return int(intptr_t(BLI_edgehash_lookup(edgehash, v1, v2))); + return edgehash.lookup({v1, v2}); } static void laplacian_triangle_area(LaplacianSystem *sys, int i1, int i2, int i3) @@ -253,8 +252,7 @@ static void laplacian_system_construct_end(LaplacianSystem *sys) sys->varea = static_cast( MEM_callocN(sizeof(float) * verts_num, "LaplacianSystemVarea")); - sys->edgehash = BLI_edgehash_new_ex(__func__, - BLI_EDGEHASH_SIZE_GUESS_FROM_FACES(sys->faces_num)); + sys->edgehash.reserve(sys->faces_num); for (a = 0, face = sys->faces; a < sys->faces_num; a++, face++) { laplacian_increase_edge_count(sys->edgehash, (*face)[0], (*face)[1]); laplacian_increase_edge_count(sys->edgehash, (*face)[1], (*face)[2]); @@ -296,9 +294,6 @@ static void laplacian_system_construct_end(LaplacianSystem *sys) sys->faces = nullptr; MEM_SAFE_FREE(sys->varea); - - BLI_edgehash_free(sys->edgehash, nullptr); - sys->edgehash = nullptr; } static void laplacian_system_delete(LaplacianSystem *sys) diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.cc b/source/blender/editors/sculpt_paint/sculpt_cloth.cc index 8b3d5f3e8da..7d0e71d33cc 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.cc +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.cc @@ -8,7 +8,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_edgehash.h" #include "BLI_gsqueue.h" #include "BLI_math_matrix.h" #include "BLI_math_rotation.h" @@ -154,7 +153,7 @@ static bool cloth_brush_sim_has_length_constraint(SculptClothSimulation *cloth_s const int v1, const int v2) { - return BLI_edgeset_haskey(cloth_sim->created_length_constraints, v1, v2); + return cloth_sim->created_length_constraints.contains({v1, v2}); } static void cloth_brush_reallocate_constraints(SculptClothSimulation *cloth_sim) @@ -207,7 +206,7 @@ static void cloth_brush_add_length_constraint(SculptSession *ss, cloth_brush_reallocate_constraints(cloth_sim); /* Add the constraint to the #GSet to avoid creating it again. */ - BLI_edgeset_add(cloth_sim->created_length_constraints, v1, v2); + cloth_sim->created_length_constraints.add({v1, v2}); } static void cloth_brush_add_softbody_constraint(SculptClothSimulation *cloth_sim, @@ -1011,7 +1010,7 @@ SculptClothSimulation *SCULPT_cloth_brush_simulation_create(Object *ob, const int totverts = SCULPT_vertex_count_get(ss); SculptClothSimulation *cloth_sim; - cloth_sim = MEM_cnew(__func__); + cloth_sim = MEM_new(__func__); cloth_sim->length_constraints = MEM_cnew_array( CLOTH_LENGTH_CONSTRAINTS_BLOCK, __func__); @@ -1065,14 +1064,14 @@ void SCULPT_cloth_brush_ensure_nodes_constraints( /* Currently all constrains are added to the same global array which can't be accessed from * different threads. */ - cloth_sim->created_length_constraints = BLI_edgeset_new("created length constraints"); + cloth_sim->created_length_constraints.clear(); for (const int i : nodes.index_range()) { do_cloth_brush_build_constraints_task( ob, brush, cloth_sim, initial_location, radius, nodes[i]); } - BLI_edgeset_free(cloth_sim->created_length_constraints); + cloth_sim->created_length_constraints.clear_and_shrink(); } void SCULPT_cloth_brush_simulation_init(SculptSession *ss, SculptClothSimulation *cloth_sim) diff --git a/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_cpu.cc b/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_cpu.cc index fff5ad29736..c87399abbad 100644 --- a/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_cpu.cc +++ b/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_cpu.cc @@ -9,7 +9,6 @@ #include "MOD_gpencil_legacy_lineart.h" #include "MOD_lineart.h" -#include "BLI_edgehash.h" #include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_math_geom.h" diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index 808b664b0b7..c3ba2ea642f 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -22,10 +22,10 @@ #include "DNA_object_types.h" #include "BLI_compiler_compat.h" -#include "BLI_edgehash.h" #include "BLI_index_range.hh" #include "BLI_listbase.h" #include "BLI_math_geom.h" +#include "BLI_ordered_edge.hh" #include "BLT_translation.h" @@ -994,37 +994,26 @@ static void read_edge_creases(Mesh *mesh, } MutableSpan edges = mesh->edges_for_write(); - EdgeHash *edge_hash = BLI_edgehash_new_ex(__func__, edges.size()); + Map edge_hash; + edge_hash.reserve(edges.size()); float *creases = static_cast(CustomData_add_layer_named( &mesh->edge_data, CD_PROP_FLOAT, CD_SET_DEFAULT, edges.size(), "crease_edge")); for (const int i : edges.index_range()) { - int2 &edge = edges[i]; - BLI_edgehash_insert(edge_hash, edge[0], edge[1], &edge); + edge_hash.add(edges[i], i); } for (int i = 0, s = 0, e = indices->size(); i < e; i += 2, s++) { int v1 = (*indices)[i]; int v2 = (*indices)[i + 1]; - - if (v2 < v1) { - /* It appears to be common to store edges with the smallest index first, in which case this - * prevents us from doing the second search below. */ - std::swap(v1, v2); + const int *index = edge_hash.lookup_ptr({v1, v2}); + if (!index) { + continue; } - int2 *edge = static_cast(BLI_edgehash_lookup(edge_hash, v1, v2)); - if (edge == nullptr) { - edge = static_cast(BLI_edgehash_lookup(edge_hash, v2, v1)); - } - - if (edge) { - creases[edge - edges.data()] = unit_float_to_uchar_clamp((*sharpnesses)[s]); - } + creases[*index] = unit_float_to_uchar_clamp((*sharpnesses)[s]); } - - BLI_edgehash_free(edge_hash, nullptr); } /* ************************************************************************** */ diff --git a/source/blender/io/collada/MeshImporter.cpp b/source/blender/io/collada/MeshImporter.cpp index c28e186c869..a6ce30a6db7 100644 --- a/source/blender/io/collada/MeshImporter.cpp +++ b/source/blender/io/collada/MeshImporter.cpp @@ -27,7 +27,6 @@ #include "BKE_mesh.hh" #include "BKE_object.h" -#include "BLI_edgehash.h" #include "BLI_listbase.h" #include "BLI_string.h" diff --git a/source/blender/io/collada/MeshImporter.h b/source/blender/io/collada/MeshImporter.h index bd984e86a69..4ced8d22e32 100644 --- a/source/blender/io/collada/MeshImporter.h +++ b/source/blender/io/collada/MeshImporter.h @@ -25,7 +25,6 @@ #include "ArmatureImporter.h" #include "collada_utils.h" -#include "BLI_edgehash.h" #include "BLI_math_vector_types.hh" #include "DNA_material_types.h" diff --git a/source/blender/modifiers/intern/MOD_explode.cc b/source/blender/modifiers/intern/MOD_explode.cc index 483cc9c4a29..fa5fb3e7a22 100644 --- a/source/blender/modifiers/intern/MOD_explode.cc +++ b/source/blender/modifiers/intern/MOD_explode.cc @@ -10,12 +10,12 @@ #include "BLI_utildefines.h" -#include "BLI_edgehash.h" #include "BLI_kdtree.h" #include "BLI_math_matrix.h" #include "BLI_math_rotation.h" #include "BLI_math_vector.h" #include "BLI_rand.h" +#include "BLI_vector_set.hh" #include "BLT_translation.h" @@ -208,9 +208,9 @@ static void createFacepa(ExplodeModifierData *emd, ParticleSystemModifierData *p BLI_rng_free(rng); } -static int edgecut_get(EdgeHash *edgehash, uint v1, uint v2) +static int edgecut_get(const blender::VectorSet &edgehash, uint v1, uint v2) { - return POINTER_AS_INT(BLI_edgehash_lookup(edgehash, v1, v2)); + return edgehash.index_of({int(v1), int(v2)}); } static const short add_faces[24] = { @@ -249,7 +249,7 @@ static void remap_faces_3_6_9_12(Mesh *mesh, int *facepa, const int *vertpa, int i, - EdgeHash *eh, + const blender::VectorSet &eh, int cur, int v1, int v2, @@ -319,7 +319,7 @@ static void remap_faces_5_10(Mesh *mesh, int *facepa, const int *vertpa, int i, - EdgeHash *eh, + const blender::VectorSet &eh, int cur, int v1, int v2, @@ -377,7 +377,7 @@ static void remap_faces_15(Mesh *mesh, int *facepa, const int *vertpa, int i, - EdgeHash *eh, + const blender::VectorSet &eh, int cur, int v1, int v2, @@ -463,7 +463,7 @@ static void remap_faces_7_11_13_14(Mesh *mesh, int *facepa, const int *vertpa, int i, - EdgeHash *eh, + const blender::VectorSet &eh, int cur, int v1, int v2, @@ -534,7 +534,7 @@ static void remap_faces_19_21_22(Mesh *mesh, int *facepa, const int *vertpa, int i, - EdgeHash *eh, + const blender::VectorSet &eh, int cur, int v1, int v2, @@ -590,7 +590,7 @@ static void remap_faces_23(Mesh *mesh, int *facepa, const int *vertpa, int i, - EdgeHash *eh, + const blender::VectorSet &eh, int cur, int v1, int v2, @@ -659,21 +659,18 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) MFace *mface = static_cast( CustomData_get_layer_for_write(&mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy)); float *dupve; - EdgeHash *edgehash; - EdgeHashIterator *ehi; int totvert = mesh->totvert; int totface = mesh->totface_legacy; int *facesplit = static_cast(MEM_calloc_arrayN(totface, sizeof(int), __func__)); int *vertpa = static_cast(MEM_calloc_arrayN(totvert, sizeof(int), __func__)); int *facepa = emd->facepa; - int *fs, totesplit = 0, totfsplit = 0, curdupface = 0; - int i, v1, v2, v3, v4, esplit, v[4] = {0, 0, 0, 0}, /* To quite gcc barking... */ - uv[4] = {0, 0, 0, 0}; /* To quite gcc barking... */ + int *fs, totfsplit = 0, curdupface = 0; + int i, v1, v2, v3, v4, v[4] = {0, 0, 0, 0}, /* To quite gcc barking... */ + uv[4] = {0, 0, 0, 0}; /* To quite gcc barking... */ int layers_num; - int ed_v1, ed_v2; - edgehash = BLI_edgehash_new(__func__); + blender::VectorSet edgehash; /* recreate vertpa from facepa calculation */ for (i = 0, mf = mface; i < totface; i++, mf++) { @@ -692,12 +689,12 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) v3 = vertpa[mf->v3]; if (v1 != v2) { - BLI_edgehash_reinsert(edgehash, mf->v1, mf->v2, nullptr); + edgehash.add({mf->v1, mf->v2}); (*fs) |= 1; } if (v2 != v3) { - BLI_edgehash_reinsert(edgehash, mf->v2, mf->v3, nullptr); + edgehash.add({mf->v2, mf->v3}); (*fs) |= 2; } @@ -705,38 +702,31 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) v4 = vertpa[mf->v4]; if (v3 != v4) { - BLI_edgehash_reinsert(edgehash, mf->v3, mf->v4, nullptr); + edgehash.add({mf->v3, mf->v4}); (*fs) |= 4; } if (v1 != v4) { - BLI_edgehash_reinsert(edgehash, mf->v1, mf->v4, nullptr); + edgehash.add({mf->v1, mf->v4}); (*fs) |= 8; } /* mark center vertex as a fake edge split */ if (*fs == 15) { - BLI_edgehash_reinsert(edgehash, mf->v1, mf->v3, nullptr); + edgehash.add({mf->v1, mf->v3}); } } else { (*fs) |= 16; /* mark face as tri */ if (v1 != v3) { - BLI_edgehash_reinsert(edgehash, mf->v1, mf->v3, nullptr); + edgehash.add({mf->v1, mf->v3}); (*fs) |= 4; } } } /* count splits & create indexes for new verts */ - ehi = BLI_edgehashIterator_new(edgehash); - totesplit = totvert; - for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { - BLI_edgehashIterator_setValue(ehi, POINTER_FROM_INT(totesplit)); - totesplit++; - } - BLI_edgehashIterator_free(ehi); /* count new faces due to splitting */ for (i = 0, fs = facesplit; i < totface; i++, fs++) { @@ -744,7 +734,7 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) } split_m = BKE_mesh_new_nomain_from_template_ex( - mesh, totesplit, 0, totface + totfsplit, 0, 0, CD_MASK_EVERYTHING); + mesh, totvert + edgehash.size(), 0, totface + totfsplit, 0, 0, CD_MASK_EVERYTHING); layers_num = CustomData_number_of_layers(&split_m->fdata_legacy, CD_MTFACE); @@ -767,10 +757,9 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) emd->facepa = facepa; /* create new verts */ - ehi = BLI_edgehashIterator_new(edgehash); - for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { - BLI_edgehashIterator_getKey(ehi, &ed_v1, &ed_v2); - esplit = POINTER_AS_INT(BLI_edgehashIterator_getValue(ehi)); + for (const int esplit : edgehash.index_range()) { + const int ed_v1 = edgehash[esplit].v_low; + const int ed_v2 = edgehash[esplit].v_high; CustomData_copy_data(&split_m->vert_data, &split_m->vert_data, ed_v2, esplit, 1); @@ -779,7 +768,6 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) mid_v3_v3v3(dupve, dupve, split_m_positions[ed_v1]); } - BLI_edgehashIterator_free(ehi); /* create new faces */ curdupface = 0; //=totface; @@ -897,7 +885,6 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) mf, &split_m->fdata_legacy, i, ((mf->flag & ME_FACE_SEL) ? 4 : 3)); } - BLI_edgehash_free(edgehash, nullptr); MEM_freeN(facesplit); MEM_freeN(vertpa); @@ -919,16 +906,14 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, ParticleSimulationData sim = {nullptr}; ParticleData *pa = nullptr, *pars = psmd->psys->particles; ParticleKey state, birth; - EdgeHash *vertpahash; - EdgeHashIterator *ehi; float *vertco = nullptr, imat[4][4]; float rot[4]; float ctime; // float timestep; const int *facepa = emd->facepa; - int totdup = 0, totvert = 0, totface = 0, totpart = 0, delface = 0; - int i, v, u; - int ed_v1, ed_v2, mindex = 0; + int totvert = 0, totface = 0, totpart = 0, delface = 0; + int i, u; + uint mindex = 0; totface = mesh->totface_legacy; totvert = mesh->totvert; @@ -947,7 +932,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, ctime = BKE_scene_ctime_get(scene); /* hash table for vertex <-> particle relations */ - vertpahash = BLI_edgehash_new(__func__); + blender::VectorSet vertpahash; for (i = 0; i < totface; i++) { if (facepa[i] != totpart) { @@ -965,8 +950,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, pa = nullptr; } - /* do mindex + totvert to ensure the vertex index to be the first - * with BLI_edgehashIterator_getKey */ + /* do mindex + totvert to ensure the vertex index to be the first. */ if (pa == nullptr || ctime < pa->time) { mindex = totvert + totpart; } @@ -977,25 +961,17 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, mf = &mface[i]; /* set face vertices to exist in particle group */ - BLI_edgehash_reinsert(vertpahash, mf->v1, mindex, nullptr); - BLI_edgehash_reinsert(vertpahash, mf->v2, mindex, nullptr); - BLI_edgehash_reinsert(vertpahash, mf->v3, mindex, nullptr); + vertpahash.add({mf->v1, mindex}); + vertpahash.add({mf->v2, mindex}); + vertpahash.add({mf->v3, mindex}); if (mf->v4) { - BLI_edgehash_reinsert(vertpahash, mf->v4, mindex, nullptr); + vertpahash.add({mf->v4, mindex}); } } - /* make new vertex indexes & count total vertices after duplication */ - ehi = BLI_edgehashIterator_new(vertpahash); - for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { - BLI_edgehashIterator_setValue(ehi, POINTER_FROM_INT(totdup)); - totdup++; - } - BLI_edgehashIterator_free(ehi); - /* the final duplicated vertices */ explode = BKE_mesh_new_nomain_from_template_ex( - mesh, totdup, 0, totface - delface, 0, 0, CD_MASK_EVERYTHING); + mesh, vertpahash.size(), 0, totface - delface, 0, 0, CD_MASK_EVERYTHING); MTFace *mtface = static_cast(CustomData_get_layer_named_for_write( &explode->fdata_legacy, CD_MTFACE, emd->uvname, explode->totface_legacy)); @@ -1008,14 +984,11 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, const blender::Span positions = mesh->vert_positions(); blender::MutableSpan explode_positions = explode->vert_positions_for_write(); - /* duplicate & displace vertices */ - ehi = BLI_edgehashIterator_new(vertpahash); - for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { - + for (const int v : vertpahash.index_range()) { /* get particle + vertex from hash */ - BLI_edgehashIterator_getKey(ehi, &ed_v1, &ed_v2); + int ed_v1 = vertpahash[v].v_low; + int ed_v2 = vertpahash[v].v_high; ed_v2 -= totvert; - v = POINTER_AS_INT(BLI_edgehashIterator_getValue(ehi)); copy_v3_v3(explode_positions[v], positions[ed_v1]); @@ -1053,7 +1026,6 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, pa = nullptr; } } - BLI_edgehashIterator_free(ehi); /* Map new vertices to faces. */ MFace *explode_mface = static_cast( @@ -1119,9 +1091,6 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, u++; } - /* cleanup */ - BLI_edgehash_free(vertpahash, nullptr); - /* finalization */ BKE_mesh_calc_edges_tessface(explode); BKE_mesh_convert_mfaces_to_mpolys(explode);