[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [48693] branches/soc-2012-bratwurst/source /blender/editors/transform: UV transform correction

Antony Riakiotakis kalast at gmail.com
Sat Jul 7 00:05:13 CEST 2012


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. @@



More information about the Bf-blender-cvs mailing list