[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