A fix so that verts can be added or removed from a mesh with vertex keys
authorChris Want <cwant@ualberta.ca>
Mon, 8 Dec 2003 05:07:36 +0000 (05:07 +0000)
committerChris Want <cwant@ualberta.ca>
Mon, 8 Dec 2003 05:07:36 +0000 (05:07 +0000)
in editmode without damaging the mesh. Please test.

source/blender/blenlib/BLI_editVert.h
source/blender/src/editmesh.c

index 757306ed7cb18b7bf58b8122ea535c627c5f382a..cae08f8041fb89496cbc35cf7443be35809ca954 100644 (file)
@@ -47,6 +47,11 @@ typedef struct EditVert
        unsigned char f, h, f1, hash;
        int     totweight;                              /* __NLA */
        struct MDeformWeight *dw;       /* __NLA */
+       int keyindex; /* lets hold on to this so that maybe we can have a hope
+                                  * of restoring any key information if the number/order
+                                  * of verts change.
+                                  */
+
 } EditVert;
 
 typedef struct EditEdge
index 6f6bc18ae06fb7bd29172c093616ee8bcd693a0c..ca757ba5d6e065bdaf84c1be3051c372db7475aa 100644 (file)
@@ -268,6 +268,10 @@ EditVert *addvertlist(float *vec)
 
        eve->hash= hashnr++;
 
+       /* new verts get keyindex of -1 since they did not
+        * have a pre-editmode vertex order
+        */
+       eve->keyindex = -1;
        return eve;
 }
 
@@ -1013,6 +1017,13 @@ void make_editMesh_real(Mesh *me)
                eve->no[0]= mvert->no[0]/32767.0;
                eve->no[1]= mvert->no[1]/32767.0;
                eve->no[2]= mvert->no[2]/32767.0;
+
+               /* lets overwrite the keyindex of the editvert
+                * with the order it used to be in before
+                * editmode
+                */
+               eve->keyindex = a;
+
 #ifdef __NLA
 
                /* OLD VERSION */
@@ -1221,13 +1232,13 @@ void load_editMesh()
 void load_editMesh_real(Mesh *me, int undo)
 {
        MFace *mface;
-       MVert *mvert;
+       MVert *mvert, *oldverts;
        MSticky *ms;
-       KeyBlock *actkey=0;
+       KeyBlock *actkey=0, *currkey;
        EditVert *eve;
        EditVlak *evl;
        EditEdge *eed;
-       float *fp, nor[3];
+       float *fp, *newkey, *oldkey, nor[3];
        int i, a, ototvert;
 #ifdef __NLA
        MDeformVert *dvert;
@@ -1235,260 +1246,281 @@ void load_editMesh_real(Mesh *me, int undo)
 #endif
 
        ototvert= me->totvert;
-       
-       /* are there keys? */
-       if(me->key) {
-               actkey= me->key->block.first;
-               while(actkey) {
-                       if(actkey->flag & SELECT) break;
-                       actkey= actkey->next;
-               }
-       }
 
+       /* lets save the old verts just in case we are actually working on
+        * a key ... we now do processing of the keys at the end*/
+       oldverts = me->mvert;
+
+       /* this one also tests of edges are not in faces: */
+       /* eed->f==0: not in face, f==1: draw it */
+       /* eed->f1 : flag for dynaface (cylindertest, old engine) */
+       /* eve->f1 : flag for dynaface (sphere test, old engine) */
+       edge_drawflags();
        
-       if(actkey && me->key->refkey!=actkey) {
-               /* active key && not the refkey: only vertices */
-                               
-               if(G.totvert) {
-                       if(actkey->data) MEM_freeN(actkey->data);
-               
-                       fp=actkey->data= MEM_callocN(me->key->elemsize*G.totvert, "actkey->data");
-                       actkey->totelem= G.totvert;
+       /* WATCH IT: in evl->f is punoflag (for vertex normal) */
+       vertexnormals( (me->flag & ME_NOPUNOFLIP)==0 );
        
-                       eve= G.edve.first;
-                       while(eve) {
-                               VECCOPY(fp, eve->co);
-                               fp+= 3;
-                               eve= eve->next;
-                       }
-               }
-       }
-       else if(me->key && actkey==0) {
-               /* there are keys, only write changes in mverts */
-               /* a bit unpredictable when the amount of vertices differ */
-                       
-               eve= G.edve.first;
-               mvert= me->mvert;
-               for(a=0; a<me->totvert; a++, mvert++) {
-                       VECCOPY(mvert->co, eve->co);
-                       eve= eve->next;
-                       if(eve==0) break;
-               }
+       eed= G.eded.first;
+       while(eed) {
+               if(eed->f==0) G.totface++;
+               eed= eed->next;
        }
-       else {
-               /* when there are keys: the refkey, otherise the mesh */
-               
-               /* this one also tests of edges are not in faces: */
-               /* eed->f==0: not in face, f==1: draw it */
-               /* eed->f1 : flag for dynaface (cylindertest, old engine) */
-               /* eve->f1 : flag for dynaface (sphere test, old engine) */
-               edge_drawflags();
-       
-               /* WATCH IT: in evl->f is punoflag (for vertex normal) */
-               vertexnormals( (me->flag & ME_NOPUNOFLIP)==0 );
-       
-               eed= G.eded.first;
-               while(eed) {
-                       if(eed->f==0) G.totface++;
-                       eed= eed->next;
-               }
        
-               /* new Face block */
-               if(G.totface==0) mface= 0;
-               else mface= MEM_callocN(G.totface*sizeof(MFace), "loadeditMesh1");
-               /* nieuw Vertex block */
-               if(G.totvert==0) mvert= 0;
-               else mvert= MEM_callocN(G.totvert*sizeof(MVert), "loadeditMesh2");
+       /* new Face block */
+       if(G.totface==0) mface= 0;
+       else mface= MEM_callocN(G.totface*sizeof(MFace), "loadeditMesh1");
+       /* nieuw Vertex block */
+       if(G.totvert==0) mvert= 0;
+       else mvert= MEM_callocN(G.totvert*sizeof(MVert), "loadeditMesh2");
 
 #ifdef __NLA
-               if (G.totvert==0) dvert=0;
-               else dvert = MEM_callocN(G.totvert*sizeof(MDeformVert), "loadeditMesh3");
+       if (G.totvert==0) dvert=0;
+       else dvert = MEM_callocN(G.totvert*sizeof(MDeformVert), "loadeditMesh3");
 
-               if (me->dvert) free_dverts(me->dvert, me->totvert);
-               me->dvert=dvert;
+       if (me->dvert) free_dverts(me->dvert, me->totvert);
+       me->dvert=dvert;
 #endif         
-               if(me->mvert) MEM_freeN(me->mvert);
-               me->mvert= mvert;
 
-               if(me->mface) MEM_freeN(me->mface);
-               me->mface= mface;
-               me->totvert= G.totvert;
-               me->totface= G.totface;
+       me->mvert= mvert;
+
+       if(me->mface) MEM_freeN(me->mface);
+       me->mface= mface;
+       me->totvert= G.totvert;
+       me->totface= G.totface;
                
-               /* the vertices, abuse ->vn as counter */
-               eve= G.edve.first;
-               a=0;
+       /* the vertices, abuse ->vn as counter */
+       eve= G.edve.first;
+       a=0;
 
-               while(eve) {
-                       VECCOPY(mvert->co, eve->co);
-                       mvert->mat_nr= 255;  /* what was this for, halos? */
-                       
-                       /* vertex normal */
-                       VECCOPY(nor, eve->no);
-                       VecMulf(nor, 32767.0);
-                       VECCOPY(mvert->no, nor);
+       while(eve) {
+               VECCOPY(mvert->co, eve->co);
+               mvert->mat_nr= 255;  /* what was this for, halos? */
+               
+               /* vertex normal */
+               VECCOPY(nor, eve->no);
+               VecMulf(nor, 32767.0);
+               VECCOPY(mvert->no, nor);
 #ifdef __NLA
-                       /* NEW VERSION */
-                       if (dvert){
-                               dvert->totweight=eve->totweight;
-                               if (eve->dw){
-                                       dvert->dw = MEM_callocN (sizeof(MDeformWeight)*eve->totweight, "deformWeight");
-                                       memcpy (dvert->dw, eve->dw, sizeof(MDeformWeight)*eve->totweight);
-                                       usedDvert++;
-                               }
+               /* NEW VERSION */
+               if (dvert){
+                       dvert->totweight=eve->totweight;
+                       if (eve->dw){
+                               dvert->dw = MEM_callocN (sizeof(MDeformWeight)*eve->totweight,
+                                                                                "deformWeight");
+                               memcpy (dvert->dw, eve->dw, 
+                                               sizeof(MDeformWeight)*eve->totweight);
+                               usedDvert++;
                        }
+               }
 #endif
 
-                       eve->vn= (EditVert *)(long)(a++);  /* counter */
+               eve->vn= (EditVert *)(long)(a++);  /* counter */
                        
-                       mvert->flag= 0;
-                       if(eve->f1==1) mvert->flag |= ME_SPHERETEST;
-                       mvert->flag |= (eve->f & 1);
-                       if (eve->h) mvert->flag |= ME_HIDE;                     
+               mvert->flag= 0;
                        
-                       eve= eve->next;
-                       mvert++;
+               mvert->flag= 0;
+               if(eve->f1==1) mvert->flag |= ME_SPHERETEST;
+               mvert->flag |= (eve->f & 1);
+               if (eve->h) mvert->flag |= ME_HIDE;                     
+                       
+               eve= eve->next;
+               mvert++;
 #ifdef __NLA
-                       dvert++;
+               dvert++;
 #endif
-               }
+       }
        
 #ifdef __NLA
-               /* If we didn't actually need the dverts, get rid of them */
-               if (!usedDvert){
-                       free_dverts(me->dvert, G.totvert);
-                       me->dvert=NULL;
-               }
+       /* If we didn't actually need the dverts, get rid of them */
+       if (!usedDvert){
+               free_dverts(me->dvert, G.totvert);
+               me->dvert=NULL;
+       }
 #endif
 
-               /* the faces */
-               evl= G.edvl.first;
-               i = 0;
-               while(evl) {
-                       mface= &((MFace *) me->mface)[i];
-
-                       mface->v1= (unsigned int) evl->v1->vn;
-                       mface->v2= (unsigned int) evl->v2->vn;
-                       mface->v3= (unsigned int) evl->v3->vn;
-                       if(evl->v4) mface->v4= (unsigned int) evl->v4->vn;
+       /* the faces */
+       evl= G.edvl.first;
+       i = 0;
+       while(evl) {
+               mface= &((MFace *) me->mface)[i];
                        
-                       mface->mat_nr= evl->mat_nr;
-                       mface->puno= evl->f;
-                       mface->flag= evl->flag;
+               mface->v1= (unsigned int) evl->v1->vn;
+               mface->v2= (unsigned int) evl->v2->vn;
+               mface->v3= (unsigned int) evl->v3->vn;
+               if(evl->v4) mface->v4= (unsigned int) evl->v4->vn;
                        
-                       /* mat_nr in vertex */
-                       if(me->totcol>1) {
-                               mvert= me->mvert+mface->v1;
-                               if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
-                               mvert= me->mvert+mface->v2;
-                               if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
-                               mvert= me->mvert+mface->v3;
+               mface->mat_nr= evl->mat_nr;
+               mface->puno= evl->f;
+               mface->flag= evl->flag;
+                       
+               /* mat_nr in vertex */
+               if(me->totcol>1) {
+                       mvert= me->mvert+mface->v1;
+                       if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
+                       mvert= me->mvert+mface->v2;
+                       if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
+                       mvert= me->mvert+mface->v3;
+                       if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
+                       if(mface->v4) {
+                               mvert= me->mvert+mface->v4;
                                if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
-                               if(mface->v4) {
-                                       mvert= me->mvert+mface->v4;
-                                       if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
-                               }
                        }
+               }
                        
-                       /* watch: evl->e1->f==0 means loose edge */ 
+               /* watch: evl->e1->f==0 means loose edge */ 
                        
-                       if(evl->e1->f==1) {
-                               mface->edcode |= ME_V1V2; 
-                               evl->e1->f= 2;
-                       }                       
-                       if(evl->e2->f==1) {
-                               mface->edcode |= ME_V2V3; 
-                               evl->e2->f= 2;
-                       }
-                       if(evl->e3->f==1) {
-                               if(evl->v4) {
-                                       mface->edcode |= ME_V3V4;
-                               }
-                               else {
-                                       mface->edcode |= ME_V3V1;
-                               }
-                               evl->e3->f= 2;
+               if(evl->e1->f==1) {
+                       mface->edcode |= ME_V1V2; 
+                       evl->e1->f= 2;
+               }                       
+               if(evl->e2->f==1) {
+                       mface->edcode |= ME_V2V3; 
+                       evl->e2->f= 2;
+               }
+               if(evl->e3->f==1) {
+                       if(evl->v4) {
+                               mface->edcode |= ME_V3V4;
                        }
-                       if(evl->e4 && evl->e4->f==1) {
-                               mface->edcode |= ME_V4V1; 
-                               evl->e4->f= 2;
+                       else {
+                               mface->edcode |= ME_V3V1;
                        }
+                       evl->e3->f= 2;
+               }
+               if(evl->e4 && evl->e4->f==1) {
+                       mface->edcode |= ME_V4V1; 
+                       evl->e4->f= 2;
+               }
                        
-                       /* no index '0' at location 3 or 4 */
-                       if(evl->v4) fix_faceindices(mface, evl, 4);
-                       else fix_faceindices(mface, evl, 3);
+               /* no index '0' at location 3 or 4 */
+               if(evl->v4) fix_faceindices(mface, evl, 4);
+               else fix_faceindices(mface, evl, 3);
                        
-                       i++;
-                       evl= evl->next;
-               }
+               i++;
+               evl= evl->next;
+       }
                
-               /* add loose edges as a face */
-               eed= G.eded.first;
-               while(eed) {
-                       if( eed->f==0 ) {
-                               mface= &((MFace *) me->mface)[i];
-                               mface->v1= (unsigned int) eed->v1->vn;
-                               mface->v2= (unsigned int) eed->v2->vn;
-                               test_index_mface(mface, 2);
-                               mface->edcode= ME_V1V2;
-                               i++;
-                       }
-                       eed= eed->next;
+       /* add loose edges as a face */
+       eed= G.eded.first;
+       while(eed) {
+               if( eed->f==0 ) {
+                       mface= &((MFace *) me->mface)[i];
+                       mface->v1= (unsigned int) eed->v1->vn;
+                       mface->v2= (unsigned int) eed->v2->vn;
+                       test_index_mface(mface, 2);
+                       mface->edcode= ME_V1V2;
+                       i++;
                }
+               eed= eed->next;
+       }
                
-               tex_space_mesh(me);
-               if(actkey) mesh_to_key(me, actkey);
-               
-               /* tface block, always when undo even when it wasnt used, this because of empty me pointer */
-               if( (me->tface || undo) && me->totface ) {
-                       TFace *tfn, *tf;
+       tex_space_mesh(me);
+
+       /* tface block, always when undo even when it wasnt used, 
+          this because of empty me pointer */
+       if( (me->tface || undo) && me->totface ) {
+               TFace *tfn, *tf;
                        
-                       tf=tfn= MEM_callocN(sizeof(TFace)*me->totface, "tface");
-                       evl= G.edvl.first;
-                       while(evl) {
-                               
-                               *tf= evl->tf;
+               tf=tfn= MEM_callocN(sizeof(TFace)*me->totface, "tface");
+               evl= G.edvl.first;
+               while(evl) {
                                
-                               if(G.f & G_FACESELECT) {
-                                       if( vlakselectedAND(evl, 1) ) tf->flag |= TF_SELECT;
-                                       else tf->flag &= ~TF_SELECT;
-                               }
+                       *tf= evl->tf;
                                
-                               tf++;
-                               evl= evl->next;
+                       if(G.f & G_FACESELECT) {
+                               if( vlakselectedAND(evl, 1) ) tf->flag |= TF_SELECT;
+                               else tf->flag &= ~TF_SELECT;
                        }
-                       /* if undo, me was empty */
-                       if(me->tface) MEM_freeN(me->tface);
-                       me->tface= tfn;
-               }
-               else if(me->tface) {
-                       MEM_freeN(me->tface);
-                       me->tface= NULL;
+                               
+                       tf++;
+                       evl= evl->next;
                }
+               /* if undo, me was empty */
+               if(me->tface) MEM_freeN(me->tface);
+               me->tface= tfn;
+       }
+       else if(me->tface) {
+               MEM_freeN(me->tface);
+               me->tface= NULL;
+       }
                
-               /* mcol: same as tface... */
-               if( (me->mcol || undo) && me->totface) {
-                       unsigned int *mcn, *mc;
-                       
-                       mc=mcn= MEM_mallocN(4*sizeof(int)*me->totface, "mcol");
-                       evl= G.edvl.first;
-                       while(evl) {
-                       
-                               memcpy(mc, evl->tf.col, 4*sizeof(int));
+       /* mcol: same as tface... */
+       if( (me->mcol || undo) && me->totface) {
+               unsigned int *mcn, *mc;
+
+               mc=mcn= MEM_mallocN(4*sizeof(int)*me->totface, "mcol");
+               evl= G.edvl.first;
+               while(evl) {
+                       memcpy(mc, evl->tf.col, 4*sizeof(int));
                                
-                               mc+=4;
-                               evl= evl->next;
-                       }
-                       
-                       if(me->mcol) MEM_freeN(me->mcol);
+                       mc+=4;
+                       evl= evl->next;
+               }
+               if(me->mcol) MEM_freeN(me->mcol);
                        me->mcol= (MCol *)mcn;
+       }
+       else if(me->mcol) {
+               MEM_freeN(me->mcol);
+               me->mcol= 0;
+       }
+
+
+       /* are there keys? */
+       if(me->key) {
+
+               /* find the active key */
+               actkey= me->key->block.first;
+               while(actkey) {
+                       if(actkey->flag & SELECT) break;
+                       actkey= actkey->next;
                }
-               else if(me->mcol) {
-                       MEM_freeN(me->mcol);
-                       me->mcol= NULL;
+
+               /* Lets reorder the key data so that things line up roughly
+                * with the way things were before editmode */
+               currkey = me->key->block.first;
+               while(currkey) {
+                       if(currkey->data) {
+                               fp=newkey= MEM_callocN(me->key->elemsize*G.totvert, 
+                                                                          "currkey->data");
+                               oldkey = currkey->data;
+
+                               eve= G.edve.first;
+
+                               i = 0;
+                               mvert = me->mvert;
+                               while(eve) {
+                                       if (eve->keyindex >= 0) {
+                                               if(currkey == actkey) {
+                                                       if (actkey == me->key->refkey) {
+                                                               VECCOPY(fp, mvert->co);
+                                                       }
+                                                       else {
+                                                               VECCOPY(fp, mvert->co);
+                                                               VECCOPY(mvert->co, oldverts[eve->keyindex].co);
+                                                       }
+                                               }
+                                               else {
+                                                       VECCOPY(fp, oldkey + 3 * eve->keyindex);
+                                               }
+                                       }
+                                       else {
+                                               VECCOPY(fp, mvert->co);
+                                       }
+                                       fp+= 3;
+                                       ++i;
+                                       ++mvert;
+                                       eve= eve->next;
+                               }
+                               currkey->totelem= G.totvert;
+                               MEM_freeN(currkey->data);
+                               currkey->data = newkey;
+                       }
+                       currkey= currkey->next;
                }
+
        }
-       
+
+       if(oldverts) MEM_freeN(oldverts);
+
        if(actkey) do_spec_key(me->key);
        
        /* te be sure: clear ->vn pointers */
@@ -1515,7 +1547,6 @@ void load_editMesh_real(Mesh *me, int undo)
        waitcursor(0);
 }
 
-
 void remake_editMesh(void)
 {
        undo_push_mesh("Undo all changes");