Revision: 48693
          
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=48693
Author:   psy-fi
Date:     2012-07-06 22:05:10 +0000 (Fri, 06 Jul 2012)
Log Message:
-----------
UV transform correction
========================
* Big rewrite of the tool, now properly supporting seams and extensions
outside mesh boundaries.
* todo, coming ASAP is fixing of exceptional case where boundary edges
are parallel (needs another way to map to data space)

Modified Paths:
--------------
    branches/soc-2012-bratwurst/source/blender/editors/transform/transform.h
    
branches/soc-2012-bratwurst/source/blender/editors/transform/transform_conversions.c
    
branches/soc-2012-bratwurst/source/blender/editors/transform/transform_generics.c

Modified: 
branches/soc-2012-bratwurst/source/blender/editors/transform/transform.h
===================================================================
--- branches/soc-2012-bratwurst/source/blender/editors/transform/transform.h    
2012-07-06 20:28:35 UTC (rev 48692)
+++ branches/soc-2012-bratwurst/source/blender/editors/transform/transform.h    
2012-07-06 22:05:10 UTC (rev 48693)
@@ -236,8 +236,7 @@
        /* initial vertex value. We have to store it here too because for 
proportional editing
         * we can't correlate vertex indices to transdata anymore due to 
sorting */
        float (*init_vec)[3];
-       float *edge_length;
-       int total_edges;
+       float (*init_normal)[3];
        int total_verts;
 } UVTransCorrect;
 

Modified: 
branches/soc-2012-bratwurst/source/blender/editors/transform/transform_conversions.c
===================================================================
--- 
branches/soc-2012-bratwurst/source/blender/editors/transform/transform_conversions.c
        2012-07-06 20:28:35 UTC (rev 48692)
+++ 
branches/soc-2012-bratwurst/source/blender/editors/transform/transform_conversions.c
        2012-07-06 22:05:10 UTC (rev 48693)
@@ -1956,7 +1956,6 @@
        int propmode = (t->flag & T_PROP_EDIT) ? (t->flag & (T_PROP_EDIT | 
T_PROP_CONNECTED)) : 0;
        int mirror = 0;
        char *selstate = NULL;
-       char *edge_length_calc; /* setting to remember which edges have had 
their length calculated */
        short selectmode = ts->selectmode;
 
        if (t->flag & T_MIRROR) {
@@ -2054,10 +2053,8 @@
                uvtc = t->uvtc = MEM_callocN(sizeof(*t->uvtc), 
"UVTransformCorrect");
                uvtc->initial_uvs = initial_uvs = MEM_mallocN(bm->totvert * 
sizeof(*t->uvtc->initial_uvs), "uvtc_inituvs");
                uvtc->init_vec = MEM_mallocN(bm->totvert * 
sizeof(*t->uvtc->init_vec), "uvtc_initial_vertexes");
+               uvtc->init_normal = MEM_mallocN(bm->totvert * 
sizeof(*t->uvtc->init_normal), "uvtc_initial_normals");
                uvtc->total_verts = bm->totvert;
-               uvtc->total_edges = bm->totedge;
-               uvtc->edge_length = 
MEM_mallocN(sizeof(*uvtc->edge_length)*bm->totedge, "uvtc_edge_length");
-               edge_length_calc = 
MEM_callocN(sizeof(*edge_length_calc)*bm->totedge, 
"transform_edge_length_calc");
                BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE);
        }
 
@@ -2135,11 +2132,9 @@
                                        UVTransCorrInfoUV *uviter = NULL, 
*uviter2 = NULL;
 
                                        tob->eve = eve;
+                                       copy_v3_v3(uvtc->init_normal[a], 
eve->no);
 
                                        BM_ITER_ELEM(l, &iter2, eve, 
BM_LOOPS_OF_VERT) {
-                                               int edge_index = 
BM_elem_index_get(l->e);
-                                               /* we also need the previous 
edge in case the face normals do not behave well */
-                                               int edge_index_prev = 
BM_elem_index_get(l->prev->e);
                                                MLoopUV *luv = 
CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 
                                                *uvtcuv = 
MEM_mallocN(sizeof(**uvtcuv), "uvtcelem");
@@ -2151,15 +2146,6 @@
                                                (*uvtcuv)->l = l;
                                                (*uvtcuv)->next = NULL;
                                                uvtcuv = &((*uvtcuv)->next);
-
-                                               
if(!edge_length_calc[edge_index]) {
-                                                       
uvtc->edge_length[edge_index] = BM_edge_calc_length(l->e);
-                                                       
edge_length_calc[edge_index] = TRUE;
-                                               }
-                                               
if(!edge_length_calc[edge_index_prev]) {
-                                                       
uvtc->edge_length[edge_index_prev] = BM_edge_calc_length(l->prev->e);
-                                                       
edge_length_calc[edge_index_prev] = TRUE;
-                                               }
                                        }
 
                                        /* Now we need to sort uvs according to 
uv island */
@@ -2277,8 +2263,6 @@
                MEM_freeN(defmats);
        if (dists)
                MEM_freeN(dists);
-       if(edge_length_calc)
-               MEM_freeN(edge_length_calc);
        
        MEM_freeN(selstate);
 

Modified: 
branches/soc-2012-bratwurst/source/blender/editors/transform/transform_generics.c
===================================================================
--- 
branches/soc-2012-bratwurst/source/blender/editors/transform/transform_generics.c
   2012-07-06 20:28:35 UTC (rev 48692)
+++ 
branches/soc-2012-bratwurst/source/blender/editors/transform/transform_generics.c
   2012-07-06 22:05:10 UTC (rev 48693)
@@ -1266,9 +1266,9 @@
                MEM_freeN(uvtc->init_vec);
                uvtc->init_vec = NULL;
        }
-       if(uvtc->edge_length) {
-               MEM_freeN(uvtc->edge_length);
-               uvtc->edge_length = NULL;
+       if(uvtc->init_normal) {
+               MEM_freeN(uvtc->init_normal);
+               uvtc->init_normal = NULL;
        }
        if(uvtc->initial_uvs) {
                int i;
@@ -1695,9 +1695,95 @@
 }
 
 /* flush the calculated displacement to uvs of the same uv island */
-static void flushUVdisplacement(UVTransCorrInfoUV *first, float disp[2], int 
optimal)
+static void flushUVdisplacement(UVTransCorrInfoUV *first, BMLoop *loops[2], 
BMEditMesh *em, TransData *td, UVTransCorrect *uvtc)
 {
+       UVTransCorrInfoUV *uvtcuv = first;
+       float normal[3];
+       float edge_vec_init1[3], edge_vec_init2[3];
+       float edge_uv_init1[2], edge_uv_init2[2];
+       float projv[3];
+       float uv_result[2];
+       MLoopUV *luv;
+       BMLoop *l = first->l;
+       BMLoop *l1 = loops[0];
+       BMLoop *l2 = loops[1];
 
+       int index = BM_elem_index_get(td->eve);
+       int index1 = BM_elem_index_get(loops[0]->v);
+       int index2 = BM_elem_index_get(loops[1]->v);
+
+       /* first we need to calculate the displacement based on the projection 
of the vertex to the
+        * boundary loops plane */
+       sub_v3_v3v3(edge_vec_init1, uvtc->init_vec[index1], td->iloc);
+       if(uvtc->initial_uvs[index1]) {
+               UVTransCorrInfoUV *uvtmp = uvtc->initial_uvs[index1];
+               while(uvtmp->l != l1) {
+                       uvtmp = uvtmp->next;
+               }
+               sub_v2_v2v2(edge_uv_init1, uvtmp->init_uv, uvtcuv->init_uv);
+       } else {
+               luv = CustomData_bmesh_get(&em->bm->ldata, l1->head.data, 
CD_MLOOPUV);
+               sub_v2_v2v2(edge_uv_init1, luv->uv, uvtcuv->init_uv);
+       }
+
+       sub_v3_v3v3(edge_vec_init2, uvtc->init_vec[index2], td->iloc);
+       if(uvtc->initial_uvs[index2]) {
+               UVTransCorrInfoUV *uvtmp = uvtc->initial_uvs[index2];
+               while(uvtmp->l != l2) {
+                       uvtmp = uvtmp->next;
+               }
+               sub_v2_v2v2(edge_uv_init2, uvtmp->init_uv, uvtcuv->init_uv);
+       } else {
+               luv = CustomData_bmesh_get(&em->bm->ldata, l2->head.data, 
CD_MLOOPUV);
+               sub_v2_v2v2(edge_uv_init2, luv->uv, uvtcuv->init_uv);
+       }
+
+       /* calculate a normal from the two edges */
+       cross_v3_v3v3(normal, edge_vec_init1, edge_vec_init2);
+
+       /* parallel edges, do exceptional solution */
+       if(len_v3(normal) < 0.00001) {
+               int duck = 0;
+       } else {
+               int ax, ay;
+               float det, det1, det2, coeff1, coeff2;
+               float uvtmp[2];
+               /* project vertex along its normal to the plane defined by the 
two closest edges */
+               copy_v3_v3(projv, td->eve->co);
+               project_v3_v3_plane(projv, uvtc->init_normal[index], normal, 
td->iloc);
+               sub_v3_v3v3(projv, projv, td->iloc);
+
+               /* next we need to express the projected vector as a linear 
combination of
+                * the edge vectors. The coefficients will be multiplied with 
the uv-space
+                * vectors, giving the final result */
+
+               /* find dominant axis so that we can solve a 2x2 system instead 
of a 3x3.
+                * This works since projection is not altered by 
rotation/projection */
+               axis_dominant_v3(&ax, &ay, normal);
+
+               det = determinant_m2(edge_vec_init1[ax], edge_vec_init2[ax], 
edge_vec_init1[ay], edge_vec_init2[ay]);
+               det1 = determinant_m2(projv[ax], edge_vec_init2[ax], projv[ay], 
edge_vec_init2[ay]);
+               det2 = determinant_m2(edge_vec_init1[ax], projv[ax], 
edge_vec_init1[ay], projv[ay]);
+
+               coeff1 = det1/det;
+               coeff2 = det2/det;
+
+               luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, 
CD_MLOOPUV);
+
+               copy_v2_v2(uv_result, first->init_uv);
+               mul_v2_v2fl(uvtmp, edge_uv_init1, coeff1);
+               add_v2_v2(uv_result, uvtmp);
+               mul_v2_v2fl(uvtmp, edge_uv_init2, coeff2);
+               add_v2_v2(uv_result, uvtmp);
+       }
+
+       while(uvtcuv && uvtcuv->island_index == first->island_index) {
+               BMLoop *l_flush = uvtcuv->l;
+               luv = CustomData_bmesh_get(&em->bm->ldata, l_flush->head.data, 
CD_MLOOPUV);
+
+               copy_v2_v2(luv->uv, uv_result);
+               uvtcuv = uvtcuv->next;
+       }
 }
 
 
@@ -1709,207 +1795,108 @@
        BMEditMesh *em = BMEdit_FromObject(t->obedit);
        TransData *td = t->data;
        UVTransCorrect *uvtc = t->uvtc;
-       UVTransCorrInfoUV *uvtcuv;
-//     float modelviewprojmat[4][4];
        char not_prop_edit = !(t->flag & T_PROP_EDIT);
 
-       /* transform the edge vectors to view space */
-       //mult_m4_m4m4(modelviewprojmat, t->persmat, t->viewmat);
-       //mult_m4_m4m4(modelviewprojmat, modelviewprojmat, t->obedit->obmat);
+       /* transform the vectors to view space(temp code, perhaps for later)
+       float modelviewprojmat[4][4];
+       mult_m4_m4m4(modelviewprojmat, t->persmat, t->viewmat);
+       mult_m4_m4m4(modelviewprojmat, modelviewprojmat, t->obedit->obmat);
+       transform the edge difference in screen space and do perspective 
correct transform in uv space
+       mul_m4_v3(modelviewprojmat, diff);
+       */
 
        /* iterate through loops of vert and calculate image space diff of uvs 
*/
        for (i = 0 ; i < t->total; i++) {
                if(not_prop_edit || td[i].factor > 0.0) {
                        /* first island visited, if this changes without an 
optimal face found,
                         * we must flush the result */
-                       UVTransCorrInfoUV *first_island_uv;
-
-                       float min_angles[2] = {100.0, 100.0} /* arbitrary, just 
bigger than 2PI */;
+                       UVTransCorrInfoUV *first_island_uv, *uvtcuv;
+                       float projv[3], proj_len;
+                       float min_angles[2] = {-10.0, -10.0} /* arbitrary, just 
bigger than 2PI */;
                        BMLoop *boundary_loops[2];
-
-                       /* nochange is set if we have very small displacement 
to avoid division
-                        * by zero. Good match is set to avoid reflushing uvs 
if a good face
-                        * match has been found */
-                       char nochange = FALSE, goodmatch = FALSE;
                        int index;
-                       float uv_tot[2];
-                       int uv_counter = 0;
                        BMVert *v = td[i].eve;
                        index = BM_elem_index_get(v);
 
-                       uv_tot[0] = uv_tot[1] = 0.0;
+                       /* first project the vector to the initial normal plane 
to get the displacement along that */
+                       copy_v3_v3(projv, v->co);
+                       project_v3_plane(projv, uvtc->init_normal[index], 
td[i].iloc);
+                       sub_v3_v3v3(projv, projv, td[i].iloc);
+                       proj_len = len_v3(projv);
 
+                       /* little change, do nothing */
+                       if(proj_len < 0.00001) {
+                               continue;
+                       }
+
                        first_island_uv = uvtc->initial_uvs[index];
                        for(uvtcuv = first_island_uv; uvtcuv; uvtcuv = 
uvtcuv->next) {
-                               float angle1, angle2, angle_boundary;
-                               float cross1[3], cross2[3], cross[3];
-                               float normal[3], projv[3];
-                               float edge_len_init, edge_len_init2, proj_len;
-                               float edge_len_final, edge_len_final2;
-                               float edge_vec_init[3], edge_vec_init2[3], 
neg_edge_prev[3];
-                               //float edge_vec_final[3], edge_vec_final2[3];
-                               float edge_uv_init[2], edge_uv_init2[2];
-                               float uvdiff[2], uvdiff2[2];
+                               float angle1, angle2;
+                               float dot_tmp;
+                               float proj_prev[3], proj_next[3];
                                int index_next, index_prev;
                                BMLoop *l_next, *l_prev, *l = uvtcuv->l;
-                               MLoopUV *luv;
 

@@ Diff output truncated at 10240 characters. @@
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to