From b70174cb9350868e9dd26139a8980406b18415b8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 20 Dec 2011 10:05:58 +0000 Subject: move topology mirror out into its own functions - needed for bmesh branch so we can use then for bmeshes own internal mirror calculations. --- source/blender/blenlib/BLI_dynstr.h | 2 +- source/blender/editors/include/ED_mesh.h | 13 ++ source/blender/editors/mesh/editface.c | 226 +++++++++++++++++++++++++++++++ source/blender/editors/mesh/meshtools.c | 222 ++---------------------------- 4 files changed, 251 insertions(+), 212 deletions(-) (limited to 'source') diff --git a/source/blender/blenlib/BLI_dynstr.h b/source/blender/blenlib/BLI_dynstr.h index 861da665a30..32c4e012d1d 100644 --- a/source/blender/blenlib/BLI_dynstr.h +++ b/source/blender/blenlib/BLI_dynstr.h @@ -103,7 +103,7 @@ char* BLI_dynstr_get_cstring (DynStr *ds); /** * Get a DynStr's contents as a c-string. * The str argument must be allocated to be at - * least the size of BLI_dynstr_get_len(ds). + * least the size of BLI_dynstr_get_len(ds) + 1. * * @param ds The DynStr of interest. * @param str The string to fill. diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index f75f2921e51..3a69db013c0 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -243,6 +243,19 @@ int ED_mesh_color_add(struct bContext *C, struct Scene *scene, struct Object *ob int ED_mesh_color_remove(struct bContext *C, struct Object *ob, struct Mesh *me); int ED_mesh_color_remove_named(struct bContext *C, struct Object *ob, struct Mesh *me, const char *name); + +/* mirrtopo */ +typedef struct MirrTopoStore_t { + intptr_t *index_lookup; + int prev_vert_tot; + int prev_edge_tot; + int prev_ob_mode; +} MirrTopoStore_t; + +int ED_mesh_mirrtopo_recalc_check(struct Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store); +void ED_mesh_mirrtopo_init(struct Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store); +void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store); + #ifdef __cplusplus } #endif diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 02d20e64bc3..95c71488d26 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -815,3 +815,229 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend) return OPERATOR_FINISHED; } + + +/* ********************* MESH VERTEX MIRR TOPO LOOKUP *************** */ +/* note, this is not the best place for the function to be but moved + * here to for the purpose of syncing with bmesh */ + +typedef int MirrTopoHash_t; + +typedef struct MirrTopoPair_t { + MirrTopoHash_t hash; + int v_index; +} MirrTopoPair_t; + +static int MirrTopo_long_sort(const void *l1, const void *l2) +{ + if ((MirrTopoHash_t)(intptr_t)l1 > (MirrTopoHash_t)(intptr_t)l2 ) return 1; + else if ((MirrTopoHash_t)(intptr_t)l1 < (MirrTopoHash_t)(intptr_t)l2 ) return -1; + return 0; +} + +static int MirrTopo_item_sort(const void *v1, const void *v2) +{ + if (((MirrTopoPair_t *)v1)->hash > ((MirrTopoPair_t *)v2)->hash ) return 1; + else if (((MirrTopoPair_t *)v1)->hash < ((MirrTopoPair_t *)v2)->hash ) return -1; + return 0; +} + +int ED_mesh_mirrtopo_recalc_check(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store) +{ + int totvert; + int totedge; + + if (me->edit_mesh) { + totvert= me->edit_mesh->totvert; + totedge= me->edit_mesh->totedge; + } + else { + totvert= me->totvert; + totedge= me->totedge; + } + + if( (mesh_topo_store->index_lookup==NULL) || + (mesh_topo_store->prev_ob_mode != ob_mode) || + (totvert != mesh_topo_store->prev_vert_tot) || + (totedge != mesh_topo_store->prev_edge_tot)) + { + return TRUE; + } + else { + return FALSE; + } + +} + +void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store) +{ + MEdge *medge; + EditMesh *em= me->edit_mesh; + void **eve_tmp_back= NULL; /* some of the callers are using eve->tmp so restore after */ + + /* editmode*/ + EditEdge *eed; + + int a, last; + int totvert, totedge; + int totUnique= -1, totUniqueOld= -1; + + MirrTopoHash_t *MirrTopoHash = NULL; + MirrTopoHash_t *MirrTopoHash_Prev = NULL; + MirrTopoPair_t *MirrTopoPairs; + + /* reallocate if needed */ + ED_mesh_mirrtopo_free(mesh_topo_store); + + mesh_topo_store->prev_ob_mode= ob_mode; + + if(em) { + EditVert *eve; + totvert= 0; + eve_tmp_back= MEM_callocN( em->totvert * sizeof(void *), "TopoMirr" ); + for(eve= em->verts.first; eve; eve= eve->next) { + eve_tmp_back[totvert]= eve->tmp.p; + eve->tmp.l = totvert++; + } + } + else { + totvert = me->totvert; + } + + MirrTopoHash = MEM_callocN( totvert * sizeof(MirrTopoHash_t), "TopoMirr" ); + + /* Initialize the vert-edge-user counts used to detect unique topology */ + if(em) { + totedge= 0; + + for(eed=em->edges.first; eed; eed= eed->next, totedge++) { + MirrTopoHash[eed->v1->tmp.l]++; + MirrTopoHash[eed->v2->tmp.l]++; + } + } else { + totedge= me->totedge; + + for(a=0, medge=me->medge; a < me->totedge; a++, medge++) { + MirrTopoHash[medge->v1]++; + MirrTopoHash[medge->v2]++; + } + } + + MirrTopoHash_Prev = MEM_dupallocN( MirrTopoHash ); + + totUniqueOld = -1; + while(1) { + /* use the number of edges per vert to give verts unique topology IDs */ + + if(em) { + for(eed=em->edges.first; eed; eed= eed->next) { + MirrTopoHash[eed->v1->tmp.l] += MirrTopoHash_Prev[eed->v2->tmp.l]; + MirrTopoHash[eed->v2->tmp.l] += MirrTopoHash_Prev[eed->v1->tmp.l]; + } + } else { + for(a=0, medge=me->medge; atotedge; a++, medge++) { + /* This can make really big numbers, wrapping around here is fine */ + MirrTopoHash[medge->v1] += MirrTopoHash_Prev[medge->v2]; + MirrTopoHash[medge->v2] += MirrTopoHash_Prev[medge->v1]; + } + } + memcpy(MirrTopoHash_Prev, MirrTopoHash, sizeof(MirrTopoHash_t) * totvert); + + /* sort so we can count unique values */ + qsort(MirrTopoHash_Prev, totvert, sizeof(MirrTopoHash_t), MirrTopo_long_sort); + + totUnique = 1; /* account for skiping the first value */ + for(a=1; atmp.* */ + if(eve_tmp_back) { + EditVert *eve; + totvert= 0; + for(eve= em->verts.first; eve; eve= eve->next) { + eve->tmp.p= eve_tmp_back[totvert++]; + } + + MEM_freeN(eve_tmp_back); + eve_tmp_back= NULL; + } + + + /* Hash/Index pairs are needed for sorting to find index pairs */ + MirrTopoPairs= MEM_callocN( sizeof(MirrTopoPair_t) * totvert, "MirrTopoPairs"); + + /* since we are looping through verts, initialize these values here too */ + mesh_topo_store->index_lookup = MEM_mallocN( totvert * sizeof(long), "mesh_topo_lookup" ); + + if(em) { + EM_init_index_arrays(em,1,0,0); + } + + + for(a=0; aindex_lookup[a] = -1; + } + + qsort(MirrTopoPairs, totvert, sizeof(MirrTopoPair_t), MirrTopo_item_sort); + + /* Since the loop starts at 2, we must define the last index where the hash's differ */ + last = ((totvert >= 2) && (MirrTopoPairs[0].hash == MirrTopoPairs[1].hash)) ? 0 : 1; + + /* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2, + * but you cant ever access the last 'a' index of MirrTopoPairs */ + for(a=2; a <= totvert; a++) { + /* printf("I %d %ld %d\n", (a-last), MirrTopoPairs[a ].hash, MirrTopoPairs[a ].vIndex ); */ + if ((a==totvert) || (MirrTopoPairs[a-1].hash != MirrTopoPairs[a].hash)) { + if (a-last==2) { + if(em) { + mesh_topo_store->index_lookup[MirrTopoPairs[a-1].v_index] = (intptr_t)EM_get_vert_for_index(MirrTopoPairs[a-2].v_index); + mesh_topo_store->index_lookup[MirrTopoPairs[a-2].v_index] = (intptr_t)EM_get_vert_for_index(MirrTopoPairs[a-1].v_index); + } else { + mesh_topo_store->index_lookup[MirrTopoPairs[a-1].v_index] = MirrTopoPairs[a-2].v_index; + mesh_topo_store->index_lookup[MirrTopoPairs[a-2].v_index] = MirrTopoPairs[a-1].v_index; + } + } + last= a; + } + } + if(em) { + EM_free_index_arrays(); + } + + MEM_freeN( MirrTopoPairs ); + MirrTopoPairs = NULL; + + MEM_freeN( MirrTopoHash ); + MEM_freeN( MirrTopoHash_Prev ); + + mesh_topo_store->prev_vert_tot = totvert; + mesh_topo_store->prev_edge_tot = totedge; +} + +void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store) +{ + if (mesh_topo_store->index_lookup) { + MEM_freeN(mesh_topo_store->index_lookup); + } + mesh_topo_store->index_lookup = NULL; + mesh_topo_store->prev_vert_tot = -1; + mesh_topo_store->prev_edge_tot = -1; +} diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index dd82f055f14..77daf21affa 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -765,7 +765,7 @@ intptr_t mesh_octree_table(Object *ob, EditMesh *em, float *co, char mode) if(mode=='u') { /* use table */ if(MeshOctree.table==NULL) mesh_octree_table(ob, em, NULL, 's'); - + if(MeshOctree.table) { Mesh *me= ob->data; bt= MeshOctree.table + mesh_octree_get_base_offs(co, MeshOctree.offs, MeshOctree.div); @@ -848,34 +848,7 @@ intptr_t mesh_octree_table(Object *ob, EditMesh *em, float *co, char mode) return 0; } - -/* ********************* MESH VERTEX MIRR TOPO LOOKUP *************** */ - -typedef int MirrTopoHash_t; - -typedef struct MirrTopoPair_t { - MirrTopoHash_t hash; - int vIndex; -} MirrTopoPair_t; - -static int MirrTopo_long_sort(const void *l1, const void *l2) -{ - if ((MirrTopoHash_t)(intptr_t)l1 > (MirrTopoHash_t)(intptr_t)l2 ) return 1; - else if ((MirrTopoHash_t)(intptr_t)l1 < (MirrTopoHash_t)(intptr_t)l2 ) return -1; - return 0; -} - -static int MirrTopo_item_sort(const void *v1, const void *v2) -{ - if (((MirrTopoPair_t *)v1)->hash > ((MirrTopoPair_t *)v2)->hash ) return 1; - else if (((MirrTopoPair_t *)v1)->hash < ((MirrTopoPair_t *)v2)->hash ) return -1; - return 0; -} - -static intptr_t *mesh_topo_lookup = NULL; -static int mesh_topo_lookup_vert_tot = -1; -static int mesh_topo_lookup_edge_tot = -1; -static int mesh_topo_lookup_mode = -1; +MirrTopoStore_t mesh_topo_store= {NULL, -1. -1, -1}; /* mode is 's' start, or 'e' end, or 'u' use */ /* if end, ob can be NULL */ @@ -883,188 +856,15 @@ static int mesh_topo_lookup_mode = -1; int mesh_mirrtopo_table(Object *ob, char mode) { if(mode=='u') { /* use table */ - Mesh *me= ob->data; - if( (mesh_topo_lookup==NULL) || - (mesh_topo_lookup_mode != ob->mode) || - (me->edit_mesh && (me->edit_mesh->totvert != mesh_topo_lookup_vert_tot)) || - (me->edit_mesh && (me->edit_mesh->totedge != mesh_topo_lookup_edge_tot)) || - (me->edit_mesh==NULL && me->totvert != mesh_topo_lookup_vert_tot) || - (me->edit_mesh==NULL && me->totedge != mesh_topo_lookup_edge_tot) - ) { + if (ED_mesh_mirrtopo_recalc_check(ob->data, ob->mode, &mesh_topo_store)) { mesh_mirrtopo_table(ob, 's'); } - } else if(mode=='s') { /* start table */ - Mesh *me= ob->data; - MEdge *medge; - EditMesh *em= me->edit_mesh; - void **eve_tmp_back= NULL; /* some of the callers are using eve->tmp so restore after */ - - - /* editmode*/ - EditEdge *eed; - - int a, last; - int totvert, totedge; - int totUnique= -1, totUniqueOld= -1; - - MirrTopoHash_t *MirrTopoHash = NULL; - MirrTopoHash_t *MirrTopoHash_Prev = NULL; - MirrTopoPair_t *MirrTopoPairs; - mesh_topo_lookup_mode= ob->mode; - - /* reallocate if needed */ - if (mesh_topo_lookup) { - MEM_freeN(mesh_topo_lookup); - mesh_topo_lookup = NULL; - } - - if(em) { - EditVert *eve; - totvert= 0; - eve_tmp_back= MEM_callocN( em->totvert * sizeof(void *), "TopoMirr" ); - for(eve= em->verts.first; eve; eve= eve->next) { - eve_tmp_back[totvert]= eve->tmp.p; - eve->tmp.l = totvert++; - } - } - else { - totvert = me->totvert; - } - - MirrTopoHash = MEM_callocN( totvert * sizeof(MirrTopoHash_t), "TopoMirr" ); - - /* Initialize the vert-edge-user counts used to detect unique topology */ - if(em) { - totedge= 0; - - for(eed=em->edges.first; eed; eed= eed->next, totedge++) { - MirrTopoHash[eed->v1->tmp.l]++; - MirrTopoHash[eed->v2->tmp.l]++; - } - } else { - totedge= me->totedge; - - for(a=0, medge=me->medge; a < me->totedge; a++, medge++) { - MirrTopoHash[medge->v1]++; - MirrTopoHash[medge->v2]++; - } - } - - MirrTopoHash_Prev = MEM_dupallocN( MirrTopoHash ); - - totUniqueOld = -1; - while(1) { - /* use the number of edges per vert to give verts unique topology IDs */ - - if(em) { - for(eed=em->edges.first; eed; eed= eed->next) { - MirrTopoHash[eed->v1->tmp.l] += MirrTopoHash_Prev[eed->v2->tmp.l]; - MirrTopoHash[eed->v2->tmp.l] += MirrTopoHash_Prev[eed->v1->tmp.l]; - } - } else { - for(a=0, medge=me->medge; atotedge; a++, medge++) { - /* This can make really big numbers, wrapping around here is fine */ - MirrTopoHash[medge->v1] += MirrTopoHash_Prev[medge->v2]; - MirrTopoHash[medge->v2] += MirrTopoHash_Prev[medge->v1]; - } - } - memcpy(MirrTopoHash_Prev, MirrTopoHash, sizeof(MirrTopoHash_t) * totvert); - - /* sort so we can count unique values */ - qsort(MirrTopoHash_Prev, totvert, sizeof(MirrTopoHash_t), MirrTopo_long_sort); - - totUnique = 1; /* account for skiping the first value */ - for(a=1; atmp.* */ - if(eve_tmp_back) { - EditVert *eve; - totvert= 0; - for(eve= em->verts.first; eve; eve= eve->next) { - eve->tmp.p= eve_tmp_back[totvert++]; - } - - MEM_freeN(eve_tmp_back); - eve_tmp_back= NULL; - } - - - /* Hash/Index pairs are needed for sorting to find index pairs */ - MirrTopoPairs= MEM_callocN( sizeof(MirrTopoPair_t) * totvert, "MirrTopoPairs"); - - /* since we are looping through verts, initialize these values here too */ - mesh_topo_lookup = MEM_mallocN( totvert * sizeof(long), "mesh_topo_lookup" ); - - if(em) { - EM_init_index_arrays(em,1,0,0); - } - - - for(a=0; a= 2) && (MirrTopoPairs[0].hash == MirrTopoPairs[1].hash)) ? 0 : 1; - - /* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2, - * but you cant ever access the last 'a' index of MirrTopoPairs */ - for(a=2; a < totvert+1; a++) { - /* printf("I %d %ld %d\n", (a-last), MirrTopoPairs[a ].hash, MirrTopoPairs[a ].vIndex ); */ - if ((a==totvert) || (MirrTopoPairs[a-1].hash != MirrTopoPairs[a].hash)) { - if (a-last==2) { - if(em) { - mesh_topo_lookup[MirrTopoPairs[a-1].vIndex] = (intptr_t)EM_get_vert_for_index(MirrTopoPairs[a-2].vIndex); - mesh_topo_lookup[MirrTopoPairs[a-2].vIndex] = (intptr_t)EM_get_vert_for_index(MirrTopoPairs[a-1].vIndex); - } else { - mesh_topo_lookup[MirrTopoPairs[a-1].vIndex] = MirrTopoPairs[a-2].vIndex; - mesh_topo_lookup[MirrTopoPairs[a-2].vIndex] = MirrTopoPairs[a-1].vIndex; - } - } - last= a; - } - } - if(em) { - EM_free_index_arrays(); - } - - MEM_freeN( MirrTopoPairs ); - MirrTopoPairs = NULL; - - MEM_freeN( MirrTopoHash ); - MEM_freeN( MirrTopoHash_Prev ); - - mesh_topo_lookup_vert_tot = totvert; - mesh_topo_lookup_edge_tot = totedge; - - } else if(mode=='e') { /* end table */ - if (mesh_topo_lookup) { - MEM_freeN(mesh_topo_lookup); - } - mesh_topo_lookup = NULL; - mesh_topo_lookup_vert_tot= -1; - mesh_topo_lookup_edge_tot= -1; + } + else if(mode=='s') { /* start table */ + ED_mesh_mirrtopo_init(ob->data, ob->mode, &mesh_topo_store); + } + else if(mode=='e') { /* end table */ + ED_mesh_mirrtopo_free(&mesh_topo_store); } return 0; } @@ -1088,7 +888,7 @@ static int mesh_get_x_mirror_vert_topo(Object *ob, int index) if (mesh_mirrtopo_table(ob, 'u')==-1) return -1; - return mesh_topo_lookup[index]; + return mesh_topo_store.index_lookup[index]; } int mesh_get_x_mirror_vert(Object *ob, int index) @@ -1136,7 +936,7 @@ static EditVert *editmesh_get_x_mirror_vert_topo(Object *ob, struct EditMesh *em } } - poinval= mesh_topo_lookup[ index ]; + poinval= mesh_topo_store.index_lookup[index]; if(poinval != -1) return (EditVert *)(poinval); -- cgit v1.2.3