* corrective UV transformation - only works with UV edge slide right now. but should...
authorCampbell Barton <ideasman42@gmail.com>
Fri, 5 Sep 2008 00:28:17 +0000 (00:28 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 5 Sep 2008 00:28:17 +0000 (00:28 +0000)
* smooth respects mirror option (will move mirrored vert too)

source/blender/blenkernel/BKE_action.h
source/blender/blenkernel/intern/action.c
source/blender/makesdna/DNA_scene_types.h
source/blender/src/buttons_editing.c
source/blender/src/editmesh_mods.c
source/blender/src/editmesh_tools.c

index 716eac81b55a6392a5132792ce856ac8df5636f3..4a13fa31f6cc606b6e3a1deb6689476d6c1894fb 100644 (file)
@@ -159,7 +159,7 @@ float get_action_frame(struct Object *ob, float cframe);
 /* map strip time to global time (frame nr)  */
 float get_action_frame_inv(struct Object *ob, float cframe);
 /* builds a list of NlaIpoChannel with ipo values to write in datablock */
-void extract_ipochannels_from_action(ListBase *lb, struct ID *id, struct bAction *act, char *name, float ctime);
+void extract_ipochannels_from_action(ListBase *lb, struct ID *id, struct bAction *act, const char *name, float ctime);
 /* write values returned by extract_ipochannels_from_action, returns the number of value written */
 int execute_ipochannels(ListBase *lb);
 
index 2648233aca592e652870b4763c822dec4b60800b..043ede5987a4b096b9221409efb3979e625034ea 100644 (file)
@@ -862,7 +862,7 @@ typedef struct NlaIpoChannel {
        int type;
 } NlaIpoChannel;
 
-void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act, char *name, float ctime)
+void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act, const char *name, float ctime)
 {
        bActionChannel *achan= get_action_channel(act, name);
        IpoCurve *icu;
index 72050b0809e1414e4a9cd42624dfae42e06f8313..32522d1e866adc69a77945236c3eabf1c7add6a6 100644 (file)
@@ -790,6 +790,7 @@ typedef struct Scene {
 /* toolsettings->uvcalc_flag */
 #define UVCALC_FILLHOLES                       1
 #define UVCALC_NO_ASPECT_CORRECT       2       /* would call this UVCALC_ASPECT_CORRECT, except it should be default with old file */
+#define UVCALC_TRANSFORM_CORRECT       4       /* adjust UV's while transforming to avoid distortion */
 
 /* toolsettings->edge_mode */
 #define EDGE_MODE_SELECT                               0
index 76f244db6fc27ab7e2b2463289f2e58e4f3fe6b9..c83d7b2e12443a8581bb4126aab75da0fdb9e1ef 100644 (file)
@@ -6277,6 +6277,11 @@ static void editing_panel_mesh_uvautocalculation(void)
        row= 180;
 
        uiDefButBitS(block, TOGN, UVCALC_NO_ASPECT_CORRECT, B_NOP, "Image Aspect",100,row,200,butH,&G.scene->toolsettings->uvcalc_flag, 0, 0, 0, 0,  "Scale the UV Unwrapping to correct for the current images aspect ratio");
+
+       row-= butHB+butS;       
+               uiDefButBitS(block, TOG, UVCALC_TRANSFORM_CORRECT, B_NOP, "Transform Correction",100,row,200,butH,&G.scene->toolsettings->uvcalc_flag, 0, 0, 0, 0,  "Correct for UV distortion while transforming, (only works with edge slide now)");
+
+       row= 180;
        
        uiBlockBeginAlign(block);
        uiDefButF(block, NUM,B_UVAUTO_CUBESIZE ,"Cube Size:",315,row,200,butH, &G.scene->toolsettings->uvcalc_cubesize, 0.0001, 100.0, 10, 3, "Defines the cubemap size for cube mapping");
index c162c904776638bf8270cf49cfcbfac0241a01cd..81d0ffeeb3bc4424214e3bb413b81e88828a3d8d 100644 (file)
@@ -4202,7 +4202,7 @@ void editmesh_align_view_to_selected(View3D *v3d, int axis)
 void vertexsmooth(void)
 {
        EditMesh *em = G.editMesh;
-       EditVert *eve;
+       EditVert *eve, *eve_mir = NULL;
        EditEdge *eed;
        float *adror, *adr, fac;
        float fvec[3];
@@ -4285,13 +4285,19 @@ void vertexsmooth(void)
        while(eve) {
                if(eve->f & SELECT) {
                        if(eve->f1) {
+                               
+                               if (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR) {
+                                       eve_mir= editmesh_get_x_mirror_vert(G.obedit, eve->co);
+                               }
+                               
                                adr = eve->tmp.p;
                                fac= 0.5/(float)eve->f1;
                                
                                eve->co[0]= 0.5*eve->co[0]+fac*adr[0];
                                eve->co[1]= 0.5*eve->co[1]+fac*adr[1];
                                eve->co[2]= 0.5*eve->co[2]+fac*adr[2];
-
+                               
+                               
                                /* clip if needed by mirror modifier */
                                if (eve->f2) {
                                        if (eve->f2 & 1) {
@@ -4304,6 +4310,13 @@ void vertexsmooth(void)
                                                eve->co[2]= 0.0f;
                                        }
                                }
+                               
+                               if (eve_mir) {
+                                       eve_mir->co[0]=-eve->co[0];
+                                       eve_mir->co[1]= eve->co[1];
+                                       eve_mir->co[2]= eve->co[2];
+                               }
+                               
                        }
                        eve->tmp.p= NULL;
                }
index 2b25253dc95d18fc3e27c347bc736e30433a5f86..c2fccb0e50f0d9b110a31a72b3d7d800a8f88bfa 100644 (file)
@@ -4648,6 +4648,12 @@ void bevel_menu_old()
 }
 
 /* *********** END BEVEL *********/
+typedef struct SlideUv {
+       float origuv[2];
+       float *uv_up, *uv_down;
+       //float *fuv[4];
+       LinkNode *fuv_list;
+} SlideUv;
 
 typedef struct SlideVert {
        EditEdge *up,*down;
@@ -4655,9 +4661,19 @@ typedef struct SlideVert {
 } SlideVert;
 
 int EdgeLoopDelete(void) {
+       
+       /* temporal flag setting so we keep UVs when deleting edge loops,
+        * this is a bit of a hack but it works how you would want in almost all cases */
+       short uvcalc_flag_orig = G.scene->toolsettings->uvcalc_flag; 
+       G.scene->toolsettings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT;
+       
        if(!EdgeSlide(1, 1)) {
                return 0;
        }
+       
+       /* restore uvcalc flag */
+       G.scene->toolsettings->uvcalc_flag = uvcalc_flag_orig;
+       
        EM_select_more();
        removedoublesflag(1,0, 0.001);
        EM_select_flush();
@@ -4674,11 +4690,21 @@ int EdgeSlide(short immediate, float imperc)
        EditVert *ev, *nearest;
        LinkNode *edgelist = NULL, *vertlist=NULL, *look;
        GHash *vertgh;
+
        SlideVert *tempsv;
        float perc = 0, percp = 0,vertdist, projectMat[4][4], viewMat[4][4];
        float shiftlabda= 0.0f,len = 0.0f;
        int i = 0,j, numsel, numadded=0, timesthrough = 0, vertsel=0, prop=1, cancel = 0,flip=0;
        int wasshift = 0;
+       
+       /* UV correction vars */
+       GHash **uvarray;
+       int  uvlay_tot= CustomData_number_of_layers(&G.editMesh->fdata, CD_MTFACE);
+       int uvlay_idx;
+       SlideUv *slideuvs, *suv, *suv_last;     
+       float uv_tmp[2];
+       LinkNode *fuv_link;
+       
        short event, draw=1;
        short mval[2], mvalo[2];
        char str[128]; 
@@ -4985,6 +5011,99 @@ int EdgeSlide(short immediate, float imperc)
                
                look = look->next;   
        }          
+       
+       
+       if (uvlay_tot && (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
+               int maxnum = 0;
+               uvarray = MEM_callocN( uvlay_tot * sizeof(GHash *), "SlideUVs Array");
+               suv_last = slideuvs = MEM_callocN( uvlay_tot * (numadded+1) * sizeof(SlideUv), "SlideUVs"); /* uvLayers * verts */
+               suv = NULL;
+               
+               for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+                       
+                       uvarray[uvlay_idx] = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); 
+                       
+                       for(ev=em->verts.first;ev;ev=ev->next) {
+                               ev->tmp.l = 0;
+                       }
+                       look = vertlist;
+                       while(look) {
+                               float *uv_new;
+                               tempsv  = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
+                               
+                               ev = look->link;
+                               suv = NULL;
+                               for(efa = em->faces.first;efa;efa=efa->next) {
+                                       if (ev->tmp.l != -1) { /* test for self, in this case its invalid */
+                                               int k=-1; /* face corner */
+                                       
+                                               /* Is this vert in the faces corner? */
+                                               if              (efa->v1==ev)                           k=0;
+                                               else if (efa->v2==ev)                           k=1;
+                                               else if (efa->v3==ev)                           k=2;
+                                               else if (efa->v4 && efa->v4==ev)        k=3;
+                                               
+                                               if (k != -1) {
+                                                       MTFace *tf = CustomData_em_get_n(&em->fdata, efa->data, CD_MTFACE, uvlay_idx);
+                                                       EditVert *ev_up, *ev_down;
+                                                       
+                                                       uv_new = tf->uv[k];
+                               
+                                                       if (ev->tmp.l) {
+                                                               if (fabs(suv->origuv[0]-uv_new[0]) > 0.0001 || fabs(suv->origuv[1]-uv_new[1])) {
+                                                                       ev->tmp.l = -1; /* Tag as invalid */
+                                                                       BLI_linklist_free(suv->fuv_list,NULL);
+                                                                       suv->fuv_list = NULL;
+                                                                       BLI_ghash_remove(uvarray[uvlay_idx],ev, NULL, NULL);
+                                                                       suv = NULL;
+                                                                       break;
+                                                               }
+                                                       } else {
+                                                               ev->tmp.l = 1;
+                                                               suv = suv_last;
+
+                                                               suv->fuv_list = NULL;
+                                                               suv->uv_up = suv->uv_down = NULL;
+                                                               suv->origuv[0] = uv_new[0];
+                                                               suv->origuv[1] = uv_new[1];
+                                                               
+                                                               BLI_linklist_prepend(&suv->fuv_list, uv_new);
+                                                               BLI_ghash_insert(uvarray[uvlay_idx],ev,suv);
+                                                               
+                                                               suv_last++; /* advance to next slide UV */
+                                                               maxnum++;
+                                                       }
+                               
+                                                       /* Now get the uvs along the up or down edge if we can */
+                                                       if (suv) {
+                                                               if (!suv->uv_up) {
+                                                                       ev_up = editedge_getOtherVert(tempsv->up,ev);
+                                                                       if              (efa->v1==ev_up)                                suv->uv_up = tf->uv[0];
+                                                                       else if (efa->v2==ev_up)                                suv->uv_up = tf->uv[1];
+                                                                       else if (efa->v3==ev_up)                                suv->uv_up = tf->uv[2];
+                                                                       else if (efa->v4 && efa->v4==ev_up)             suv->uv_up = tf->uv[3];
+                                                               }
+                                                               if (!suv->uv_down) { /* if the first face was apart of the up edge, it cant be apart of the down edge */
+                                                                       ev_down = editedge_getOtherVert(tempsv->down,ev);
+                                                                       if              (efa->v1==ev_down)                              suv->uv_down = tf->uv[0];
+                                                                       else if (efa->v2==ev_down)                              suv->uv_down = tf->uv[1];
+                                                                       else if (efa->v3==ev_down)                              suv->uv_down = tf->uv[2];
+                                                                       else if (efa->v4 && efa->v4==ev_down)   suv->uv_down = tf->uv[3];
+                                                               }
+                                       
+                                                               /* Copy the pointers to the face UV's */
+                                                               BLI_linklist_prepend(&suv->fuv_list, uv_new);
+                                                       }
+                                               }
+                                       }
+                               }
+                               look = look->next;
+                       }
+               } /* end uv layer loop */
+       } /* end uvlay_tot */
+       
+       
+       
        // we should have enough info now to slide
 
        len = 0.0f; 
@@ -5089,7 +5208,21 @@ int EdgeSlide(short immediate, float imperc)
                                        
                                        tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev);
                                        VecLerpf(ev->co, tempsv->origvert.co, tempev->co, fabs(perc));
-                                                                       
+                                       
+                                       if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
+                                               for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+                                                       suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
+                                                       if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
+                                                               Vec2Lerpf(uv_tmp, suv->origuv,  (perc>=0)?suv->uv_up:suv->uv_down, fabs(perc));
+                                                               fuv_link = suv->fuv_list;
+                                                               while (fuv_link) {
+                                                                       VECCOPY2D(((float *)fuv_link->link), uv_tmp);
+                                                                       fuv_link = fuv_link->next;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       
                                        look = look->next;       
                                }
                        }
@@ -5105,8 +5238,37 @@ int EdgeSlide(short immediate, float imperc)
                                        if(newlen < 0.0) {newlen = 0.0;}
                                        if(flip == 0) {
                                                VecLerpf(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen));                                                                   
+                                               if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
+                                                       /* dont do anything if no UVs */
+                                                       for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+                                                               suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
+                                                               if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
+                                                                       Vec2Lerpf(uv_tmp, suv->uv_down, suv->uv_up, fabs(newlen));
+                                                                       fuv_link = suv->fuv_list;
+                                                                       while (fuv_link) {
+                                                                               VECCOPY2D(((float *)fuv_link->link), uv_tmp);
+                                                                               fuv_link = fuv_link->next;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
                                        } else{
                                                VecLerpf(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen));                           
+                                               
+                                               if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
+                                                       /* dont do anything if no UVs */
+                                                       for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+                                                               suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
+                                                               if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
+                                                                       Vec2Lerpf(uv_tmp, suv->uv_up, suv->uv_down, fabs(newlen));
+                                                                       fuv_link = suv->fuv_list;
+                                                                       while (fuv_link) {
+                                                                               VECCOPY2D(((float *)fuv_link->link), uv_tmp);
+                                                                               fuv_link = fuv_link->next;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
                                        }
                                        look = look->next;       
                                }
@@ -5276,6 +5438,24 @@ int EdgeSlide(short immediate, float imperc)
        BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
        BLI_linklist_free(vertlist,NULL); 
        BLI_linklist_free(edgelist,NULL); 
+       
+       if (uvlay_tot && (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
+               for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+                       BLI_ghash_free(uvarray[uvlay_idx], NULL, NULL);
+               }
+               MEM_freeN(uvarray);
+               MEM_freeN(slideuvs);
+               
+               suv = suv_last-1;
+               while (suv >= slideuvs) {
+                       if (suv->fuv_list) {
+                               BLI_linklist_free(suv->fuv_list,NULL);
+                       }
+                       suv--;
+               }
+               
+               allqueue(REDRAWIMAGE, 0);
+       }
 
        if(cancel == 1) {
                return -1;