Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2006-01-10 14:36:57 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2006-01-10 14:36:57 +0300
commitdd7e0b6bfeefae727bb9bcb9a5241fc3af482e4d (patch)
tree556b33bfa2e1ab09a019e240b093f2acd1a193f3 /source/blender/src/editsima.c
parentb7be6620d6ecfbec1d82128f402b585041910ca9 (diff)
Apply Subsurf to UV's.
This fixes most of the UV distortion issues with subsurf. Near seams however there might still be some distortion, but this should at least not be worse than before. Subsurf UV is enabled by default on new meshes, and can be enabled in the modifier panel for existing ones. Before and after: http://users.pandora.be/blendix/notsmooth.png http://users.pandora.be/blendix/smooth.png
Diffstat (limited to 'source/blender/src/editsima.c')
-rw-r--r--source/blender/src/editsima.c318
1 files changed, 132 insertions, 186 deletions
diff --git a/source/blender/src/editsima.c b/source/blender/src/editsima.c
index 6e717147bda..eca241c155f 100644
--- a/source/blender/src/editsima.c
+++ b/source/blender/src/editsima.c
@@ -87,25 +87,11 @@
#include "blendef.h"
#include "mydevice.h"
-struct uvvertsort {
- unsigned int v, f;
- unsigned char tf_sel;
- char flag;
-};
-
/* local prototypes */
void clever_numbuts_sima(void);
void sel_uvco_inside_radius(short , TFace *, int , float *, float *, short);
void uvedit_selectionCB(short , Object *, short *, float ); /* used in edit.c*/
-static int compuvvert(const void *u1, const void *u2)
-{
- const struct uvvertsort *v1=u1, *v2=u2;
- if (v1->v > v2->v) return 1;
- else if (v1->v < v2->v) return -1;
- return 0;
-}
-
void object_uvs_changed(Object *ob)
{
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
@@ -594,7 +580,7 @@ void mouse_select_sima(void)
{
Mesh *me;
TFace *tf, *nearesttf;
- MFace *mf, *nearestmf;
+ MFace *mf, *nearestmf=NULL;
int a, selectsticky, sticky, actface, nearestuv, i;
unsigned int hitv[4], nearestv;
float *hituv[4], limit[2];
@@ -1024,14 +1010,15 @@ void reveal_tface_uv(void)
void stitch_uv_tface(int mode)
{
- MFace *mf;
- TFace *tf, *tface;
Mesh *me;
- int a, b, c, tot, vtot, vtot2;
- float newuv[2], limit[2], *uv, *uv1;
- struct uvvertsort *sortblock, *sb, *sb1, *sb2;
+ TFace *tf;
+ int a, vtot;
+ float newuv[2], limit[2];
+ UvMapVert *vlist, *iterv, *v;
+ UvVertMap *vmap;
- if( is_uv_tface_editing_allowed()==0 ) return;
+ if(is_uv_tface_editing_allowed()==0)
+ return;
limit[0]= limit[1]= 20.0;
if(mode==1) {
@@ -1047,115 +1034,80 @@ void stitch_uv_tface(int mode)
}
else
limit[0]= limit[1]= limit[0]/256.0;
-
- me= get_mesh(OBACT);
- tface= (TFace*)me->tface;
-
- tot= 0;
- mf= (MFace*)me->mface;
- tf= (TFace*)me->tface;
- for(a=me->totface; a>0; a--, tf++, mf++) {
- if((tf->flag & TF_SELECT)) {
- if(tf->flag & TF_SEL1) tot++;
- if(tf->flag & TF_SEL2) tot++;
- if(tf->flag & TF_SEL3) tot++;
- if(mf->v4 && tf->flag & TF_SEL4) tot++;
- }
- }
- if(tot==0) return;
- sb= sortblock= MEM_callocN(sizeof(struct uvvertsort)*tot,"sortstitchuv");
+ me= get_mesh(OBACT);
+ tf= me->tface;
- mf= (MFace*)me->mface;
- tf= (TFace*)me->tface;
- for(a=0; a<me->totface; a++, tf++, mf++) {
- if((tf->flag & TF_SELECT)) {
- if(tf->flag & TF_SEL1) {
- sb->v= mf->v1;
- sb->f= a;
- sb->tf_sel= 0;
- sb++;
- }
- if(tf->flag & TF_SEL2) {
- sb->v= mf->v2;
- sb->f= a;
- sb->tf_sel= 1;
- sb++;
- }
- if(tf->flag & TF_SEL3) {
- sb->v= mf->v3;
- sb->f= a;
- sb->tf_sel= 2;
- sb++;
- }
- if(mf->v4 && tf->flag & TF_SEL4) {
- sb->v= mf->v4;
- sb->f= a;
- sb->tf_sel= 3;
- sb++;
- }
- }
- }
-
- /* sort by vertex */
- qsort(sortblock, tot, sizeof(struct uvvertsort), compuvvert);
+ vmap= make_uv_vert_map(me->mface, tf, me->totface, me->totvert, 1, limit);
+ if(vmap == NULL)
+ return;
if(mode==0) {
- for (a=0, sb=sortblock; a<tot; a+=vtot, sb+=vtot) {
+ for(a=0; a<me->totvert; a++) {
+ v = get_uv_map_vert(vmap, a);
+
+ if(v == NULL)
+ continue;
+
newuv[0]= 0; newuv[1]= 0;
vtot= 0;
- for (b=a, sb1=sb; b<tot && sb1->v==sb->v; b++, sb1++) {
- newuv[0] += tface[sb1->f].uv[sb1->tf_sel][0];
- newuv[1] += tface[sb1->f].uv[sb1->tf_sel][1];
- vtot++;
+ for(iterv=v; iterv; iterv=iterv->next) {
+ if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
+ newuv[0] += tf[iterv->f].uv[iterv->tfindex][0];
+ newuv[1] += tf[iterv->f].uv[iterv->tfindex][1];
+ vtot++;
+ }
}
- newuv[0] /= vtot; newuv[1] /= vtot;
+ if (vtot > 1) {
+ newuv[0] /= vtot; newuv[1] /= vtot;
- for (b=a, sb1=sb; b<a+vtot; b++, sb1++) {
- tface[sb1->f].uv[sb1->tf_sel][0]= newuv[0];
- tface[sb1->f].uv[sb1->tf_sel][1]= newuv[1];
+ for(iterv=v; iterv; iterv=iterv->next) {
+ if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
+ tf[iterv->f].uv[iterv->tfindex][0]= newuv[0];
+ tf[iterv->f].uv[iterv->tfindex][1]= newuv[1];
+ }
+ }
}
}
} else if(mode==1) {
- for (a=0, sb=sortblock; a<tot; a+=vtot, sb+=vtot) {
- vtot= 0;
- for (b=a, sb1=sb; b<tot && sb1->v==sb->v; b++, sb1++)
- vtot++;
-
- for (b=a, sb1=sb; b<a+vtot; b++, sb1++) {
- if(sb1->flag & 2) continue;
+ for(a=0; a<me->totvert; a++) {
+ vlist= get_uv_map_vert(vmap, a);
+ while(vlist) {
newuv[0]= 0; newuv[1]= 0;
- vtot2 = 0;
-
- for (c=b, sb2=sb1; c<a+vtot; c++, sb2++) {
- uv = tface[sb2->f].uv[sb2->tf_sel];
- uv1 = tface[sb1->f].uv[sb1->tf_sel];
- if (fabs(uv[0]-uv1[0]) < limit[0] &&
- fabs(uv[1]-uv1[1]) < limit[1]) {
- newuv[0] += uv[0];
- newuv[1] += uv[1];
- sb2->flag |= 2;
- sb2->flag |= 4;
- vtot2++;
+ vtot= 0;
+
+ for(iterv=vlist; iterv; iterv=iterv->next) {
+ if((iterv != vlist) && iterv->separate)
+ break;
+ if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
+ newuv[0] += tf[iterv->f].uv[iterv->tfindex][0];
+ newuv[1] += tf[iterv->f].uv[iterv->tfindex][1];
+ vtot++;
}
}
- newuv[0] /= vtot2; newuv[1] /= vtot2;
+ if (vtot > 1) {
+ newuv[0] /= vtot; newuv[1] /= vtot;
- for (c=b, sb2=sb1; c<a+vtot; c++, sb2++) {
- if(sb2->flag & 4) {
- tface[sb2->f].uv[sb2->tf_sel][0]= newuv[0];
- tface[sb2->f].uv[sb2->tf_sel][1]= newuv[1];
- sb2->flag &= ~4;
+ for(iterv=vlist; iterv; iterv=iterv->next) {
+ if((iterv != vlist) && iterv->separate)
+ break;
+ if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
+ tf[iterv->f].uv[iterv->tfindex][0]= newuv[0];
+ tf[iterv->f].uv[iterv->tfindex][1]= newuv[1];
+ }
}
}
+
+ vlist= iterv;
}
}
}
- MEM_freeN(sortblock);
+
+ free_uv_vert_map(vmap);
if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(me);
@@ -1166,109 +1118,102 @@ void stitch_uv_tface(int mode)
void select_linked_tface_uv(int mode)
{
- MFace *mf;
- TFace *tface, *tf, *nearesttf=NULL;
Mesh *me;
- char sel, *linkflag;
- int a, b, c, tot, vtot, nearestv, nearestuv, i, nverts;
- float limit[2], *uv, *uv1;
- struct uvvertsort *sortblock, *sb, *sb1, *sb2;
+ MFace *mf;
+ TFace *tf, *nearesttf=NULL;
+ UvVertMap *vmap;
+ UvMapVert *vlist, *iterv, *startv;
+ unsigned int *stack, stacksize= 0, nearestv;
+ char *flag;
+ int a, nearestuv, i, nverts;
+ float limit[2];
- if( is_uv_tface_editing_allowed()==0 ) return;
+ if(is_uv_tface_editing_allowed()==0)
+ return;
me= get_mesh(OBACT);
- get_connected_limit_tface_uv(limit);
-
- tot= 0;
- mf= (MFace*)me->mface;
- tf= (TFace*)me->tface;
- for(a=me->totface; a>0; a--, tf++, mf++)
- if(tf->flag & TF_SELECT)
- tot += mf->v4? 4: 3;
-
- if(tot==0) return;
+ if (mode == 2) {
+ nearesttf= NULL;
+ nearestuv= 0;
+ }
if (mode!=2) {
find_nearest_uv(&nearesttf, &nearestv, &nearestuv);
-
if(nearesttf==NULL)
return;
}
- else {
- nearesttf= NULL;
- nearestuv= 0;
- }
- sb= sortblock= MEM_callocN(sizeof(struct uvvertsort)*tot, "sortsellinkuv");
- linkflag= MEM_callocN(sizeof(char)*me->totface, "linkflaguv");
+ get_connected_limit_tface_uv(limit);
+ vmap= make_uv_vert_map(me->mface, me->tface, me->totface, me->totvert, 1, limit);
+ if(vmap == NULL)
+ return;
- mf= (MFace*)me->mface;
- tf= (TFace*)me->tface;
- for(a=0; a<me->totface; a++, tf++, mf++) {
- if(!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT)) {
- sel= 0;
- sb1= sb;
- nverts= mf->v4? 4: 3;
- for(i=0; i<nverts; i++) {
- if(tf->flag & TF_SEL_MASK(i))
- sel= 1;
- sb->f= a;
- sb->tf_sel= i;
- sb++;
+ stack= MEM_mallocN(sizeof(*stack)*me->totface, "UvLinkStack");
+ flag= MEM_callocN(sizeof(*flag)*me->totface, "UvLinkFlag");
+
+ if (mode == 2) {
+ tf= me->tface;
+ for(a=0; a<me->totface; a++, tf++)
+ if(!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT))
+ if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) {
+ stack[stacksize]= a;
+ stacksize++;
+ flag[a]= 1;
+ }
+ }
+ else {
+ tf= me->tface;
+ for(a=0; a<me->totface; a++, tf++)
+ if(tf == nearesttf) {
+ stack[stacksize]= a;
+ stacksize++;
+ flag[a]= 1;
+ break;
}
+ }
- if(nearesttf==tf || ((sel && mode==2)))
- linkflag[a] = 1;
+ while(stacksize > 0) {
+ stacksize--;
+ a= stack[stacksize];
+ mf= me->mface+a;
+ tf= me->tface+a;
- (sb1)->v= mf->v1;
- (sb1+1)->v= mf->v2;
- (sb1+2)->v= mf->v3;
- if(mf->v4) (sb1+3)->v= mf->v4;
- }
- }
-
- /* sort by vertex */
- qsort(sortblock, tot, sizeof(struct uvvertsort), compuvvert);
+ nverts= mf->v4? 4: 3;
- tface= (TFace*)me->tface;
- sel= 1;
- while(sel) {
- sel= 0;
+ for(i=0; i<nverts; i++) {
+ vlist= get_uv_map_vert(vmap, *(&mf->v1 + i));
+ startv= vlist;
- /* select all tex vertices that are near a selected tex vertex */
- for (a=0, sb=sortblock; a<tot; a+=vtot, sb+=vtot) {
- vtot= 0;
- for (b=a, sb1=sb; b<tot && sb1->v==sb->v; b++, sb1++)
- vtot++;
- for (b=a, sb1=sb; b<a+vtot; b++, sb1++) {
- if(linkflag[sb1->f]) continue;
+ for(iterv=vlist; iterv; iterv=iterv->next) {
+ if(iterv->separate)
+ startv= iterv;
+ if(iterv->f == a)
+ break;
+ }
- for (c=a, sb2=sb; c<a+vtot; c++, sb2++) {
- if(!(linkflag[sb2->f])) continue;
-
- uv = tface[sb2->f].uv[sb2->tf_sel];
- uv1 = tface[sb1->f].uv[sb1->tf_sel];
- if (fabs(uv[0]-uv1[0]) < limit[0] &&
- fabs(uv[1]-uv1[1]) < limit[1]) {
- linkflag[sb1->f] = 1;
- sel= 1;
- break;
- }
+ for(iterv=startv; iterv; iterv=iterv->next) {
+ if((startv != iterv) && (iterv->separate))
+ break;
+ else if(!flag[iterv->f]) {
+ flag[iterv->f]= 1;
+ stack[stacksize]= iterv->f;;
+ stacksize++;
}
}
}
}
if(mode==0 || mode==2) {
- for(a=0, tf=tface; a<me->totface; a++, tf++)
- if(linkflag[a])
+ for(a=0, tf=me->tface; a<me->totface; a++, tf++)
+ if(flag[a])
tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
else
tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
}
else if(mode==1) {
- for(a=0, tf=tface; a<me->totface; a++, tf++) {
- if(linkflag[a]) {
+ mf= me->mface;
+ for(a=0, tf=me->tface; a<me->totface; a++, tf++, mf++) {
+ if(flag[a]) {
if (mf->v4) {
if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)))
break;
@@ -1279,19 +1224,20 @@ void select_linked_tface_uv(int mode)
}
if (a<me->totface) {
- for(a=0, tf=tface; a<me->totface; a++, tf++)
- if(linkflag[a])
+ for(a=0, tf=me->tface; a<me->totface; a++, tf++)
+ if(flag[a])
tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
}
else {
- for(a=0, tf=tface; a<me->totface; a++, tf++)
- if(linkflag[a])
+ for(a=0, tf=me->tface; a<me->totface; a++, tf++)
+ if(flag[a])
tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
}
}
- MEM_freeN(sortblock);
- MEM_freeN(linkflag);
+ MEM_freeN(stack);
+ MEM_freeN(flag);
+ free_uv_vert_map(vmap);
BIF_undo_push("Select linked UV");
scrarea_queue_winredraw(curarea);