[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [58825] branches/ soc-2013-meshdata_transfer/source/blender/bmesh/tools: UV transfer through faces: fully implementing the uv transfer
Walid Shouman
eng.walidshouman at gmail.com
Fri Aug 2 12:07:15 CEST 2013
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. @@
More information about the Bf-blender-cvs
mailing list