[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [58686] branches/ soc-2013-meshdata_transfer/source/blender/bmesh/tools: UV transfer through faces: integrating the island matching into the code -WIP-
Walid Shouman
eng.walidshouman at gmail.com
Sun Jul 28 10:21:21 CEST 2013
Revision: 58686
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=58686
Author: walid
Date: 2013-07-28 08:21:21 +0000 (Sun, 28 Jul 2013)
Log Message:
-----------
UV transfer through faces: integrating the island matching into the code -WIP-
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_path.c
branches/soc-2013-meshdata_transfer/source/blender/bmesh/tools/bmesh_path.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-07-28 07:11:00 UTC (rev 58685)
+++ branches/soc-2013-meshdata_transfer/source/blender/bmesh/tools/bmesh_data_transfer.c 2013-07-28 08:21:21 UTC (rev 58686)
@@ -13,6 +13,9 @@
#include "BLI_array.h" //used for interpolation (reserving custom size)
#include "DNA_key_types.h" //used for dealing with keyblocks
#include "BLI_math_vector.h" //for copying vectors
+#include "BLI_linklist.h" //used for path finding (ie for seams)
+#include "../editors/include/ED_mesh.h" //used to check the editmesh in the flag_islands function
+#include "BKE_mesh.h" //used for UvVertMap in flag_islands function
#include "DNA_object_types.h" //using the bDeformGroup
#include "BKE_bvhutils.h" //using the bvhutils.h
@@ -152,6 +155,185 @@
return loop_match;
}
+bool flag_islands(BMesh *bm, int *UNUSED_count, bool mark_seams, bool mark_sharp, bool mark_tag);
+//take the bmesh, get the islands, with their count
+bool flag_islands(BMesh *bm, int *UNUSED(count), bool mark_seams, bool mark_sharp, bool mark_tag)
+{
+ UvVertMap *vmap;
+ BMEditMesh *em;
+ BMEdge *editedge;
+ float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
+
+ BMIter iter;
+
+ em = BKE_editmesh_create(bm, true);
+
+ //is that needed!?
+ if (!(em && em->bm->totface && CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY) &&
+ CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV))) {
+ return false;
+ }
+
+ /* This code sets editvert->tmp.l to the index. This will be useful later on. */
+ EDBM_index_arrays_ensure(em, BM_FACE);
+ vmap = EDBM_uv_vert_map_create(em, 0, limit);
+
+ BM_ITER_MESH (editedge, &iter, bm, BM_EDGES_OF_MESH) {
+ /* flags to determine if we uv is separated from first editface match */
+ char separated1 = 0, separated2;
+ /* set to denote edge must be flagged as seam */
+ char faces_separated = 0;
+ /* flag to keep track if uv1 is disconnected from first editface match */
+ char v1coincident = 1;
+ /* For use with v1coincident. v1coincident will change only if we've had commonFaces */
+ int commonFaces = 0;
+
+ BMFace *efa1, *efa2;
+
+ UvMapVert *mv1, *mvinit1, *mv2, *mvinit2, *mviter;
+ /* mv2cache stores the first of the list of coincident uv's for later comparison
+ * mv2sep holds the last separator and is copied to mv2cache when a hit is first found */
+ UvMapVert *mv2cache = NULL, *mv2sep = NULL;
+
+ mvinit1 = vmap->vert[BM_elem_index_get(editedge->v1)];
+ if (mark_seams)
+ BM_elem_flag_disable(editedge, BM_ELEM_SEAM);
+ if (mark_tag)
+ BM_elem_flag_disable(editedge, BM_ELEM_TAG);
+
+ //start looping from the first vertex, as long as the iterator (mv1) exists and there are no
+ //separated faces execute the for loop then move mv1 a step forward
+ for (mv1 = mvinit1; mv1 && !faces_separated; mv1 = mv1->next) {
+ if (mv1->separate && commonFaces)
+ v1coincident = 0;
+
+ separated2 = 0;
+ efa1 = EDBM_face_at_index(em, mv1->f);
+ mvinit2 = vmap->vert[BM_elem_index_get(editedge->v2)];
+
+ for (mv2 = mvinit2; mv2; mv2 = mv2->next) {
+ if (mv2->separate)
+ mv2sep = mv2;
+
+ efa2 = EDBM_face_at_index(em, mv2->f);
+ if (efa1 == efa2) {
+ /* if v1 is not coincident no point in comparing */
+ if (v1coincident) {
+ /* have we found previously anything? */
+ if (mv2cache) {
+ /* flag seam unless proved to be coincident with previous hit */
+ separated2 = 1;
+ for (mviter = mv2cache; mviter; mviter = mviter->next) {
+ if (mviter->separate && mviter != mv2cache)
+ break;
+ /* coincident with previous hit, do not flag seam */
+ if (mviter == mv2)
+ separated2 = 0;
+ }
+ }
+ /* First hit case, store the hit in the cache */
+ else {
+ mv2cache = mv2sep;
+ commonFaces = 1;
+ }
+ }
+ else
+ separated1 = 1;
+
+ if (separated1 || separated2) {
+ faces_separated = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if (faces_separated) {
+ if (mark_seams)
+ BM_elem_flag_enable(editedge, BM_ELEM_SEAM);
+ if (mark_sharp)
+ BM_elem_flag_disable(editedge, BM_ELEM_SMOOTH);
+ if (mark_tag)
+ BM_elem_flag_enable(editedge, BM_ELEM_TAG);
+
+ }
+ }
+
+ EDBM_uv_vert_map_free(vmap);
+
+ return true;
+}
+
+bool BM_edge_in_paths(LinkNode **e_lists, BMEdge *e, int count);
+
+bool BM_edge_in_paths(LinkNode **e_lists, BMEdge *e, int count)
+{
+ LinkNode *link_iter;
+ int i;
+
+ //looping over the paths
+ for (i = 0; i < count; i++) {
+ link_iter = e_lists[i];
+
+ //check if the list is empty!
+ if (link_iter == NULL) {
+ continue;
+ }
+
+ while (link_iter->next != NULL) {
+ if (e == (BMEdge*) link_iter->link) {
+ return true;
+ }
+
+ link_iter = link_iter->next;
+ }
+ }
+
+ //end of search
+ return false;
+
+}
+
+bool BM_test_and_set_visited_vert_cb(BMVert *v, bool *visited_verts);
+bool BM_test_and_set_visited_vert_cb(BMVert *v, bool *visited_verts)
+{
+ if (visited_verts[BM_elem_index_get(v)] == true) {
+ return false;
+ }
+ else {
+ visited_verts[BM_elem_index_get(v)] = true;
+ return true;
+ }
+}
+
+LinkNode *BM_get_vert_path_relative_to_edge(BMesh *bm_dst, BMBVHTree *bm_dst_tree, BMEdge *e, float rad_search, bool *visited_verts_dst);
+
+/**
+ * @brief BM_get_vert_path_relative_to_edge: get the corresponding vertex path to a single edge
+ * @param bm_dst: the bmesh
+ * @param bm_dst_tree: the bmesh tree where the vertices exist //we shall make it ourselves!!
+ * @param e: the source edge
+ * @param rad_search: the maximum distance we should search within
+ * @param visited_verts_dst: used to avoid passing by a visited vertex from a previous search
+ * @return the vert path within the bm_dst
+ */
+
+LinkNode *BM_get_vert_path_relative_to_edge(BMesh *bm_dst, BMBVHTree *bm_dst_tree, BMEdge *e, float rad_search,
+ bool *visited_verts_dst)
+{
+ BMVert *v_start, *v_end;
+
+ v_start = BKE_bmbvh_find_vert_closest(bm_dst_tree, e->v1->co, rad_search);
+ v_end = BKE_bmbvh_find_vert_closest(bm_dst_tree, e->v1->co, rad_search);
+
+ if ((v_start != NULL) && (v_end != NULL) && (v_start->head.index != v_end->head.index)) {
+ return BM_mesh_calc_path_vert(bm_dst, v_start, v_end, true, visited_verts_dst,
+ (bool (*)(BMVert *, void *))BM_test_and_set_visited_vert_cb);
+ }
+ else
+ return NULL;
+}
+
bool BM_mesh_uv_copy(BMesh *bm_src,BMesh *bm_dst, float tolerance, float radius_interp, int dist_pow, int no_pow,
bool USE_NORMALS)
{
@@ -1042,6 +1224,10 @@
return true;
}
+static bool check_e_table_cb(BMEdge *e, void *user_data) {
+ return ((bool*)user_data)[e->head.index];
+}
+
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])
@@ -1079,8 +1265,32 @@
int src_lay_start, src_lay_end;
int dst_lay_start, dst_lay_end; //dst_lay_end currently isn't being used
- zero_v2(weight_accu);
+ //-------island finding definitions
+ int* count = NULL;
+ int path_count;
+ int path_count_dst;
+ BMEdge *e_start;
+// BMEdge *e_end;
+ BMIter eiter1; //,eiter2;
+ LinkNode **edge_paths;
+// LinkNode temp_path;
+ LinkNode **vert_paths;
+// LinkNode **vert_paths_dst;
+ LinkNode *path_iter;
+ bool *seam_backup;
+ bool *visited_verts_dst;
+ int island_miss = 0;
+ BMEdge **e_table; //fast looping over the edges
+ bool *ind_e_table; //fast access when we have the index
+ BMEdge *e;
+ int num_islands_edges;
+ int k;
+ int j, i; //path_counter
+ float island_tolerance = FLT_MAX;
+ LinkNode *vert_path_fragment;
+ //=======end of island finding def
+
//Is that good to support edit mesh mode at the cost of receiving me_src too ?
//if (me_src->edit_btmesh != NULL) em_src = me_src->edit_btmesh; //edit mesh mode
//else
@@ -1088,18 +1298,161 @@
//if it was false ... data other than
//em->bm won't be copied
+ //get the faces tree
+ bmtree_src = BKE_bmbvh_new(em_src, 0, NULL, false);
+
+ //-----------start finding the source island boundaries and importing them into a list
+
+ //this will give us a list of seams from the starting edge
+
+ j = 0;
+ path_count = 0;
+ edge_paths = MEM_mallocN(sizeof(*edge_paths), "edge_paths bmesh_data_transfer.c");
+
+ //backing up the bm_src seams
+ //we're making a backup cause we can't use tags with BM_mesh_calc_path_edge
+ seam_backup = MEM_mallocN(sizeof(*seam_backup) * bm_src->totedge, "seam_backup bmesh_data_transfer");
+ BM_ITER_MESH_INDEX (e, &eiter1, bm_src, BM_EDGES_OF_MESH, a) {
+ seam_backup[a] = BM_elem_flag_test(e, BM_ELEM_SEAM);
+ }
+
+ //find the islands' seams
+ ///we should get rid of using the seams and path our own table! ind_e_table
+ flag_islands(bm_src, count, true, false, false);
+
+ //we shall get a list of the seams from the flag islands .. even if they didn't connect whole paths
+ //and from them we shall continue what the flag islands couldn't achieve (connect those seams!)
+ //that we know only and all the seams that we should cover
+
+ e_table = MEM_mallocN(sizeof(*e_table) * bm_src->totedge, "e_table bmesh_data_transfer.c");
+ ind_e_table = MEM_mallocN(sizeof(*e_table) * bm_src->totedge, "ind_e_table bmesh_data_transfer.c");
+
+ num_islands_edges = 0;
+ BM_ITER_MESH_INDEX (e, &eiter1, bm_src, BM_EDGES_OF_MESH, a) {
+ if (BM_elem_flag_test(e, BM_ELEM_SEAM)) {
+ ind_e_table[a] = true;
+ e_table[num_islands_edges] = e;
+ num_islands_edges++;
+ }
+ }
+
+ //get the paths representing each seam_path (or edge_path)
+ //this for loop is responsible for getting all the paths! either they were zero or the max number of islands - 1
+ //we may get rid of it by using another function that makes that directly!!
+ for (k = 0; k < num_islands_edges; k++) {
+
+ e_start = e_table[k];
+ if (BM_edge_in_paths(edge_paths, e_start, path_count)){
+ //for each (seam path )edge_path there must be at least one new seam
+ continue;
+ }
+
+ path_count++;
+ edge_paths = MEM_reallocN(edge_paths, sizeof(*edge_paths) * path_count);
+
+ //calculate a vert path!
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list