move topology mirror out into its own functions - needed for bmesh branch so we can...
authorCampbell Barton <ideasman42@gmail.com>
Tue, 20 Dec 2011 10:05:58 +0000 (10:05 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 20 Dec 2011 10:05:58 +0000 (10:05 +0000)
source/blender/blenlib/BLI_dynstr.h
source/blender/editors/include/ED_mesh.h
source/blender/editors/mesh/editface.c
source/blender/editors/mesh/meshtools.c

index 861da665a305506418802745911e59b4a5bea70f..32c4e012d1d3c81d1489dfc8150165a3dbc03173 100644 (file)
@@ -103,7 +103,7 @@ char*       BLI_dynstr_get_cstring                  (DynStr *ds);
 /**
  * Get a DynStr's contents as a c-string.
  * <i> The str argument must be allocated to be at
- * least the size of BLI_dynstr_get_len(ds). </i>
+ * least the size of BLI_dynstr_get_len(ds) + 1. </i>
  *
  * @param ds The DynStr of interest.
  * @param str The string to fill.
index f75f2921e5150266fa86283a1a1fd8db381bdb46..3a69db013c0b93819e0984d05b3d73b476e4d570 100644 (file)
@@ -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
index 02d20e64bc3062eb63fc8062004370467216ada0..95c71488d26621dde5ffea3dd497480259fca017 100644 (file)
@@ -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; a<me->totedge; 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; a<totvert; a++) {
+                       if (MirrTopoHash_Prev[a-1] != MirrTopoHash_Prev[a]) {
+                               totUnique++;
+                       }
+               }
+
+               if (totUnique <= totUniqueOld) {
+                       /* Finish searching for unique valus when 1 loop dosnt give a
+                        * higher number of unique values compared to the previous loop */
+                       break;
+               } else {
+                       totUniqueOld = totUnique;
+               }
+               /* Copy the hash calculated this iter, so we can use them next time */
+               memcpy(MirrTopoHash_Prev, MirrTopoHash, sizeof(MirrTopoHash_t) * totvert);
+       }
+
+       /* restore eve->tmp.* */
+       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; a<totvert; a++) {
+               MirrTopoPairs[a].hash= MirrTopoHash[a];
+               MirrTopoPairs[a].v_index = a;
+
+               /* initialize lookup */
+               mesh_topo_store->index_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;
+}
index dd82f055f14bd747e02727033270e58e92698582..77daf21affa3740c6b080183ae398bb4f64ef624 100644 (file)
@@ -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; a<me->totedge; 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; a<totvert; a++) {
-                               if (MirrTopoHash_Prev[a-1] != MirrTopoHash_Prev[a]) {
-                                       totUnique++;
-                               }
-                       }
-
-                       if (totUnique <= totUniqueOld) {
-                               /* Finish searching for unique valus when 1 loop dosnt give a
-                                * higher number of unique values compared to the previous loop */
-                               break;
-                       } else {
-                               totUniqueOld = totUnique;
-                       }
-                       /* Copy the hash calculated this iter, so we can use them next time */
-                       memcpy(MirrTopoHash_Prev, MirrTopoHash, sizeof(MirrTopoHash_t) * totvert);
-               }
-
-               /* restore eve->tmp.* */
-               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<totvert; a++) {
-                       MirrTopoPairs[a].hash= MirrTopoHash[a];
-                       MirrTopoPairs[a].vIndex = a;
-
-                       /* initialize lookup */
-                       mesh_topo_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+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);