Revision: 58825
          
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=58825
Author:   walid
Date:     2013-08-02 10:07:15 +0000 (Fri, 02 Aug 2013)
Log Message:
-----------
UV transfer through faces: fully implementing the uv transfer

Modified Paths:
--------------
    
branches/soc-2013-meshdata_transfer/source/blender/bmesh/tools/bmesh_data_transfer.c
    
branches/soc-2013-meshdata_transfer/source/blender/bmesh/tools/bmesh_data_transfer.h

Modified: 
branches/soc-2013-meshdata_transfer/source/blender/bmesh/tools/bmesh_data_transfer.c
===================================================================
--- 
branches/soc-2013-meshdata_transfer/source/blender/bmesh/tools/bmesh_data_transfer.c
        2013-08-02 09:40:42 UTC (rev 58824)
+++ 
branches/soc-2013-meshdata_transfer/source/blender/bmesh/tools/bmesh_data_transfer.c
        2013-08-02 10:07:15 UTC (rev 58825)
@@ -1094,6 +1094,16 @@
        return true;
 }
 
+void mid_poly_v2(float r[2], float v[][2], const int n)
+{
+       int i;
+
+       for (i = 0; i < n; i++) {
+               r[0] += v[i][0] * (1.0f/n);
+               r[1] += v[i][1] * (1.0f/n);
+       }
+}
+
 void mid_poly_v3(float r[3], float v[][3], const int n)
 {
        int i;
@@ -1262,6 +1272,71 @@
        int len;
 } BM_UV_per_face_mapping;
 
+typedef struct BM_loop_pool {
+       struct BMLoop **l;
+       int count;
+} BM_loop_pool;
+
+bool BM_loop_in_loops(BMLoop **l_grp, int len, BMLoop *l)
+{
+       int i;
+
+       for (i = 0; i < len; i++) {
+               if (l == l_grp[i]) {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+//consistency is based on uv coords of a given customdata offset
+bool BM_edge_has_consistant_loops(BMEdge *e, int CD_offset) {
+       BMFace *f_first;
+
+       //get the 2 loops corresponding to v1 in a face
+       BMVert *v1;
+       BMVert *v2;
+
+       BMLoop *l1_first;
+       BMLoop *l2_first;
+
+       BMFace *f;
+       BMLoop *l1, *l2;
+
+       BMLoop *l_iter;
+
+       if (e->l == e->l->radial_next) { // if only one face exists then the 
loops are surely consistant with themselves
+               return true;
+       }
+
+       f_first = e->l->f;
+       v1 = e->v1;
+       v2 = e->v2;
+
+       l1_first = BM_face_vert_share_loop(f_first, v1);
+       l2_first = BM_face_vert_share_loop(f_first, v2);
+
+       //we won't use BM_ITER_ELEM to avoid comparing the first face to itself 
which will grind the speed to the half
+       //in most cases (having an edge connecting 2 face)
+       l_iter = e->l->radial_next;
+       do {
+               f = l_iter->f;
+
+               l1 = BM_face_vert_share_loop(f, v1);
+               l2 = BM_face_vert_share_loop(f, v2);
+               //if both the loops weren't consistant return false!
+               if (!(equals_v2v2(BM_ELEM_CD_GET_VOID_P(l1, CD_offset), 
BM_ELEM_CD_GET_VOID_P(l1_first, CD_offset)) &&
+                   equals_v2v2(BM_ELEM_CD_GET_VOID_P(l2, CD_offset), 
BM_ELEM_CD_GET_VOID_P(l2_first, CD_offset)))) {
+                       return false;
+               }
+
+               l_iter = l_iter->radial_next;
+       } while (l_iter != e->l);
+
+       return true;
+}
+
 bool BM_mesh_uv_copy2(BMesh *bm_src, BMesh *bm_dst, float UNUSED(tolerance), 
float UNUSED(radius_interp),
                             int UNUSED(dist_pow), int UNUSED(no_pow), bool 
UNUSED(USE_NORMALS),
                             ST_ShapekeyGroupMode replace_mode, int 
*act_shapekey_lay, float tmp_mat[4][4])
@@ -1287,7 +1362,7 @@
        int v_src_count;
        int v_dst_count;
 
-       int a, b, c, d, g;
+       int a, b, c, d, g, h, i;
        //====algorithm definitions end
 
        int CD_src, CD_dst;
@@ -1317,7 +1392,11 @@
        BMEdge *e;
        BMIter eiter;
        BM_UV_per_face_mapping *fuv_table = MEM_mallocN(sizeof(*fuv_table) * 
bm_dst->totface, "fuv_table bmesh_data_transfer.c");
-       BMLoop *l_iter;
+       BM_loop_pool *l_grp = MEM_mallocN(sizeof(*l_grp) * bm_dst->totloop, 
"l_grp bmesh_data_transfer.c");
+       int l_grp_count;
+       float (*uv_buffer)[2];
+       int uv_buffer_alloc_size;
+       float mid_uv[2];
        //======end of loops connnecting definitions
 
 /*
@@ -1529,8 +1608,8 @@
                CD_src = CustomData_get_n_offset(&bm_src->ldata, CD_MLOOPUV, 
src_lay_iter);     //get the offset of the
                CD_dst = CustomData_get_n_offset(&bm_dst->ldata, CD_MLOOPUV, 
dst_lay_iter);     //lay_iter(th)CD_SHAPEKEY layer
 
+               l_grp_count = 0;
                //the way we do it is by looping over each face!!
-
                BM_ITER_MESH (f_dst, &fiter, bm_dst, BM_FACES_OF_MESH) {
 
                        //get a coordinate list of the f_dst verts
@@ -1610,11 +1689,12 @@
 
                        //within it search for the neighboring faces
                        BM_ITER_ELEM (e, &eiter, f_src, BM_EDGES_OF_FACE) {
+
                                if (BM_edge_face_pair (e, &fa, &fb) == true) {
 
                                        f_n = (fa->head.index == 
f_src->head.index) ? fb: fa;
                                        //if any of them was found in our src 
tables
-                                       if (fl_table[f_n->head.index].f != 
NULL) {      ///we're missing a check ... connected face
+                                       if ((fl_table[f_n->head.index].f != 
NULL) && (BM_edge_has_consistant_loops(e, CD_dst))) {
 
                                                //search within the mapped -to 
the src face- loops in fl_table
                                                //for the loops that share the 
same vertex between f_src and f_n
@@ -1626,39 +1706,53 @@
                                                                    
fl_table[f_n->head.index].l[g]->v->head.index) {
                                                                        //we 
finally found loops that shall be averaged from different faces!
                                                                        //we 
now shall average them into a buffer!
-                                                                       
//currently we've a buffer that's the same size as as the dst faces
 
+                                                                       //we've 
got 2 loops ... search for them in the loop groups ... if found
+                                                                       //add a 
new entry to l_grp and eincrement l_grp_count
+                                                                       //else 
append the other loop
+                                                                       for (h 
= 0; h < l_grp_count; h++) {
+                                                                               
if (BM_loop_in_loops(l_grp[h].l,l_grp[h].count, 
fl_table[f_n->head.index].l[g])) {
+                                                                               
        //found the neighboring face's loop in the group
+                                                                               
        if (!BM_loop_in_loops(l_grp[h].l,l_grp[h].count, 
fl_table[f_src->head.index].l[d])) {
+                                                                               
                //we ensured its the first time for this loop, not to add loops 
twice when we search from
+                                                                               
                //the neighboring face
 
-                                                                       //we 
got the loops .. we need to use the buffer now ... which doesn't see loops
-                                                                       //but 
rather their indices per their faces' indices
+                                                                               
                (l_grp[h].count)++;
 
-                                                                       l = 
fuv_table[fl_table[f_src->head.index].l[d]->f->head.index].f->l_first;
-                                                                       l_iter 
= l;
-                                                                       b = -1;
-                                                                       do {
-                                                                               
b++;
-                                                                               
l_iter = l_iter->next;
-                                                                               
///the first check should always be reached after/atm of the second!!
-                                                                       } while 
(l_iter != l && (l_iter != fl_table[f_src->head.index].l[d]));
+                                                                               
                l_grp[h].l = MEM_reallocN(l_grp[h].l, sizeof(*(l_grp->l)) * 
(l_grp[h].count));
+                                                                               
                //and append it
+                                                                               
                l_grp[h].l[l_grp[h].count - 1] = fl_table[f_n->head.index].l[g];
 
-                                                                       l = 
fuv_table[fl_table[f_n->head.index].l[g]->f->head.index].f->l_first;
-                                                                       l_iter 
= l;
-                                                                       a = -1;
-                                                                       do {
-                                                                               
a++;
-                                                                               
l_iter = l_iter->next;
-                                                                               
///the first check should always be reached after/atm of the second!!
-                                                                       } while 
(l_iter != l && (l_iter != fl_table[f_n->head.index].l[g]));
+                                                                               
        }
 
-                                                                       ///this 
interpolation will be dependent on the order of accessed faces
-                                                                       ///that 
could be eliminated by getting the average while copying (which will need
-                                                                       ///from 
us keeping track of each loop's number of assigned vertices)
-                                                                       
mid_v2_v2v2(fuv_table[fl_table[f_src->head.index].l[d]->f->head.index].uv[b],
-                                                                               
        fuv_table[fl_table[f_src->head.index].l[d]->f->head.index].uv[b],
-                                                                               
        fuv_table[fl_table[f_n->head.index].l[g]->f->head.index].uv[a]);
+                                                                               
        break;
+                                                                               
}
 
-                                                                       
copy_v2_v2(fuv_table[fl_table[f_n->head.index].l[g]->f->head.index].uv[a],
-                                                                               
fuv_table[fl_table[f_src->head.index].l[d]->f->head.index].uv[b]);
+                                                                               
else if (BM_loop_in_loops(l_grp[h].l,l_grp[h].count, 
fl_table[f_src->head.index].l[d])) {
+                                                                               
        //found the source face's loop in the group
+                                                                               
        if (!BM_loop_in_loops(l_grp[h].l,l_grp[h].count, 
fl_table[f_n->head.index].l[g])) {
+                                                                               
                //now reallocate memory for a new loop
+                                                                               
                (l_grp[h].count)++;
+
+                                                                               
                l_grp[h].l = MEM_reallocN(l_grp[h].l, sizeof(*(l_grp->l)) * 
(l_grp[h].count));
+                                                                               
                //and append it
+                                                                               
                l_grp[h].l[l_grp[h].count - 1] = fl_table[f_n->head.index].l[g];
+                                                                               
        }
+
+                                                                               
        break;
+                                                                               
}
+                                                                       }
+
+                                                                       if ( h 
== l_grp_count) {
+                                                                               
//the loops weren't found in any group
+                                                                               
//make a new group entry and append it
+                                                                               
l_grp[l_grp_count].count = 2;
+                                                                               
//adding a place for 2 loops
+                                                                               
l_grp[l_grp_count].l = MEM_mallocN(sizeof(*(l_grp->l)) * 2, "l_grp[].l 
bmesh_data_transfer");
+                                                                               
l_grp[l_grp_count].l[0] = fl_table[f_src->head.index].l[d];
+                                                                               
l_grp[l_grp_count].l[1] = fl_table[f_n->head.index].l[g];
+                                                                               
l_grp_count++;
+                                                                       }
                                                                }
                                                        }
                                                }
@@ -1666,29 +1760,47 @@
                                }
 
                                else {
-                                       //we've got an edge with no 2 faces
+                                       //we've got an edge with no 2 faces 
(either more or less)
                                        continue;
                                }
                                //we still need to generalize for manifolds! 
(the previous check would treat both tthe manifolds/single
                                //face edge the same case
-
                        }
+                       //currently we've passed by all the edges surrounding a 
source face
+               }
 
-               }
                ///we need an optimized way for having a buffer, a way that 
optimizes for the speed, memory and less complicated
+               ///currently we use the l_grp which optimizes mainly for the 
speed of access ...
+               ///its problem is nested reallocation
+
                //get the mid of UVs into a buffer
                //get the UV coords after looping over the src faces!!
 
-               BM_ITER_MESH (f_dst, &fiter, bm_dst, BM_FACES_OF_MESH) {
-                       BM_ITER_ELEM_INDEX (l, &liter, f_dst, BM_LOOPS_OF_FACE, 
b) {
-                               //assuming: the looping over the face's loop is 
in the same order as in the prevloops of dst_f iteration
-                               //which should be the case!
-                               copy_v2_v2(BM_ELEM_CD_GET_VOID_P(l, CD_dst), 
fuv_table[f_dst->head.index].uv[b]);
+               for (h = 0; h < l_grp_count; h++) {
+                       //average the loops' uvs
 
+                       if (uv_buffer_alloc_size < l_grp[h].count) {    
//expand the buffer size when needed
+                               uv_buffer_alloc_size = l_grp[h].count;
+                               uv_buffer = MEM_reallocN(uv_buffer, 
sizeof(*uv_buffer) * uv_buffer_alloc_size);
                        }
+
+                       //prepare the uvs to be averaged
+                       for (i = 0; i < l_grp[h].count; i++) {
+                               //copying each element is really inefficient it 
-at least- doubles the time when we are already accessing
+                               //the pointer for read only! .. we should copy 
the pointer itself
+                               copy_v2_v2(uv_buffer[i], 
BM_ELEM_CD_GET_VOID_P(l_grp[h].l[i], CD_dst));
+                       }
+
+                       //get the mid value
+                       zero_v2(mid_uv);
+                       mid_poly_v2(mid_uv, uv_buffer, l_grp[h].count);
+
+                       //copy the value to each of them
+                       for (i = 0; i < l_grp[h].count; i++) {
+                               //commenting this would leave us with the 
output of interpolation for each face ^_^
+                               copy_v2_v2(BM_ELEM_CD_GET_VOID_P(l_grp[h].l[i], 
CD_dst),mid_uv);
+                       }
                }
-               //loop over the src faces to apply the changes made to the 
buffer
-
        }
 
        return true;

Modified: 
branches/soc-2013-meshdata_transfer/source/blender/bmesh/tools/bmesh_data_transfer.h
===================================================================

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

Reply via email to