[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