UV Editor Tweaks:

- Set local sticky in the uv editor as default.
- Don't do live unwrap on fully selected charts or charts with no pins
  selected.
- Fixed bug with live unwrap not respecting transform cancel in some cases.
- "View Home" didn't work without an image.
- Move UV Calculation settings (cube size, cylinder radius, ..) into the scene
  toolsettings, instead of global variables
- Remove the name LSCM from the UI (and python docs on seams), and replace it
  with 'Unwrap', with upcoming ABF this didn't make sense anymore.
- Move the Old/New LSCM switch into the UV Calculation panel. New LSCM is the
  default now. Also renamed LSCM there to "Conformal".
- Made some room in the UV Calculation panel by removing the buttons to execute
  the UV calculation, only leaving the settings.

Fill Holes:

- LSCM now has an option to fill holes in the chart before unwrapping. This on
  by default, and enables two things:
  - Prevent internal overlaps (e.g. eyes, mouth) for LSCM unwrapping.
  - Allow the internal boundaries to move freely during stretch minimize.
- The possibility to switch it off is there because it is not always possible
  to define which the outer boundary is. For example with an open cylinder
  where there are two identical holes.
This commit is contained in:
Brecht Van Lommel 2006-02-05 14:12:45 +00:00
parent 3c9494bbfd
commit e66b5e5cd5
21 changed files with 5131 additions and 2776 deletions

@ -208,7 +208,7 @@ Scene *add_scene(char *name)
sce->r.stereomode = 1; // no stereo
sce->toolsettings = MEM_mallocN(sizeof(struct ToolSettings),"Tool Settings Struct");
sce->toolsettings = MEM_callocN(sizeof(struct ToolSettings),"Tool Settings Struct");
sce->toolsettings->cornertype=1;
sce->toolsettings->degr = 90;
sce->toolsettings->step = 9;
@ -219,6 +219,10 @@ Scene *add_scene(char *name)
sce->toolsettings->rings = 32;
sce->toolsettings->vertices = 32;
sce->toolsettings->editbutflag = 1;
sce->toolsettings->uvcalc_radius = 1.0f;
sce->toolsettings->uvcalc_cubesize = 1.0f;
sce->toolsettings->uvcalc_mapdir = 1;
sce->toolsettings->uvcalc_mapalign = 1;
strcpy(sce->r.backbuf, "//backbuf");
strcpy(sce->r.pic, U.renderdir);

@ -5280,6 +5280,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
if(arm->layer==0) arm->layer= 1;
}
for(sce= main->scene.first; sce; sce= sce->id.next) {
bScreen *sc;
if(sce->r.xparts<2) sce->r.xparts= 4;
if(sce->r.yparts<2) sce->r.yparts= 4;
/* adds default layer */
@ -5288,6 +5290,28 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
/* node version changes */
if(sce->nodetree)
ntree_version_241(sce->nodetree);
/* uv calculation options moved to toolsettings */
sce->toolsettings->uvcalc_radius = 1.0f;
sce->toolsettings->uvcalc_cubesize = 1.0f;
sce->toolsettings->uvcalc_mapdir = 1;
sce->toolsettings->uvcalc_mapalign = 1;
sce->toolsettings->uvcalc_flag = 1;
/* enable uv editor local sticky by default */
for (sc= main->screen.first; sc; sc= sc->id.next) {
ScrArea *sa;
for (sa= sc->areabase.first; sa; sa= sa->next) {
SpaceLink *sl;
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if(sl->spacetype==SPACE_IMAGE) {
SpaceImage *sima= (SpaceImage*)sl;
if(!(sima->flag & SI_STICKYUVS))
sima->flag |= SI_LOCALSTICKY;
}
}
}
}
}
for(ntree= main->nodetree.first; ntree; ntree= ntree->id.next)

@ -39,11 +39,12 @@ void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index);
void unwrap_lscm(void); /* unwrap faces selected in 3d view */
void unwrap_lscm_new(void);
void minimize_stretch_tface_uv(void); /* optimize faces selected in uv editor */
void smooth_area_tface_uv(void);
/* for live mode: no undo pushes, caching for quicky re-unwrap */
void unwrap_lscm_live_begin(void);
void unwrap_lscm_live_re_solve(void);
void unwrap_lscm_live_end(void);
void unwrap_lscm_live_end(short cancel);
#endif /* BDR_UNWRAPPER_H */

@ -626,7 +626,7 @@ enum {
B_UVAUTO_OBJECT,
B_UVAUTO_ALIGNX,
B_UVAUTO_ALIGNY,
B_UVAUTO_LSCM
B_UVAUTO_UNWRAP
};
#define B_EFFECTSBUTS 3500

@ -308,7 +308,15 @@ typedef struct ToolSettings {
// Cylinder - Tube - Circle
short vertices;
char pad2,pad3;
// UV Calculation
short unwrapper;
float uvcalc_radius;
float uvcalc_cubesize;
short uvcalc_mapdir;
short uvcalc_mapalign;
short uvcalc_flag;
short pad2;
} ToolSettings;
typedef struct Scene {

@ -465,7 +465,7 @@ typedef struct SpaceImaSel {
#define SI_LOCALSTICKY 256
#define SI_COORDFLOATS 512
#define SI_PIXELSNAP 1024
#define SI_LSCM_LIVE 2048
#define SI_LIVE_UNWRAP 2048
#define SI_USE_ALPHA 4096
#define SI_SHOW_ALPHA 8192
#define SI_SHOW_ZBUF 16384

@ -98,7 +98,7 @@ Example::
@var EdgeFlags: The available edge flags.
- SELECT - selected.
- EDGEDRAW - edge is drawn out of edition mode.
- SEAM - edge is a seam for LSCM UV unwrapping
- SEAM - edge is a seam for UV unwrapping
- FGON - edge is part of a F-Gon.
@type AssignModes: readonly dictionary.
@var AssignModes: The available vertex group assignment modes, used by

@ -82,7 +82,7 @@ Example::
@var EdgeFlags: The available edge flags.
- SELECT - selected.
- EDGEDRAW - edge is drawn out of edition mode.
- SEAM - edge is a seam for LSCM UV unwrapping
- SEAM - edge is a seam for UV unwrapping
- FGON - edge is part of a F-Gon.
"""

File diff suppressed because it is too large Load Diff

@ -159,8 +159,6 @@
static float editbutweight=1.0;
float editbutvweight=1;
float uv_calc_radius= 1.0, uv_calc_cubesize= 1.0;
short uv_calc_mapdir= 1, uv_calc_mapalign= 1, facesel_draw_edges= 0;
extern ListBase editNurb;
@ -3853,7 +3851,7 @@ void do_uvautocalculationbuts(unsigned short event)
case B_UVAUTO_WINDOW:
if(select_area(SPACE_VIEW3D)) calculate_uv_map(event);
break;
case B_UVAUTO_LSCM:
case B_UVAUTO_UNWRAP:
unwrap_lscm();
break;
}
@ -3870,28 +3868,6 @@ static void editing_panel_mesh_uvautocalculation(void)
if(uiNewPanel(curarea, block, "UV Calculation", "Editing", 960, 0, 318, 204)==0)
return;
uiBlockBeginAlign(block);
uiDefBut(block, BUT, B_UVAUTO_LSCM,"LSCM Unwrap",100,row,200,butH, 0, 0, 0, 0, 0, "Applies conformal UV mapping, preserving local angles");
uiBlockEndAlign(block);
row-= butHB+butS;
uiBlockBeginAlign(block);
uiDefBut(block, BUT, B_UVAUTO_STD1,"Standard",100,row,100,butH, 0, 0, 0, 0, 0, "Applies standard UV mapping");
uiDefBut(block, BUT, B_UVAUTO_STD2,"/2",200,row,33,butH, 0, 0, 0, 0, 0, "Applies standard UV mapping 1/2");
uiDefBut(block, BUT, B_UVAUTO_STD4,"/4",233,row,34,butH, 0, 0, 0, 0, 0, "Applies standard UV mapping 1/4");
uiDefBut(block, BUT, B_UVAUTO_STD8,"/8",267,row,33,butH, 0, 0, 0, 0, 0, "Applies standard UV mapping 1/8");
uiBlockEndAlign(block);
row-= butHB+butS;
uiBlockBeginAlign(block);
uiDefBut(block, BUT, B_UVAUTO_BOUNDS1,"Bounds",100,row,100,butH, 0, 0, 0, 0, 0, "Applies planar UV mapping with bounds 1/1");
uiDefBut(block, BUT, B_UVAUTO_BOUNDS2,"/2",200,row,33,butH, 0, 0, 0, 0, 0, "Applies planar UV mapping with bounds 1/2");
uiDefBut(block, BUT, B_UVAUTO_BOUNDS4,"/4",233,row,34,butH, 0, 0, 0, 0, 0, "Applies planar UV mapping with bounds 1/4");
uiDefBut(block, BUT, B_UVAUTO_BOUNDS8,"/8",267,row,33,butH, 0, 0, 0, 0, 0, "Applies planar UV mapping with bounds 1/8");
uiDefBut(block, BUT, B_UVAUTO_WINDOW,"From Window",100,row-butH,200,butH, 0, 0, 0, 0, 0, "Applies planar UV mapping from window");
uiBlockEndAlign(block);
row-= 2*butHB+butS;
uiBlockBeginAlign(block);
uiDefButBitI(block, TOG, G_DRAWFACES, REDRAWVIEW3D, "Draw Faces", 100,row,200,butH, &G.f, 0, 0, 0, 0, "Displays all faces as shades");
uiDefButBitI(block,TOG, G_DRAWEDGES, REDRAWVIEW3D,"Draw Edges",100,row-butHB,200,butH,&G.f, 2.0, 0, 0, 0, "Displays edges of visible faces");
@ -3900,36 +3876,35 @@ static void editing_panel_mesh_uvautocalculation(void)
uiBlockEndAlign(block);
row-= 4*butHB+butS;
row= 180;
uiBlockBeginAlign(block);
uiDefBut(block, BUT, B_UVAUTO_CUBE,"Cube",315,row,200,butH, 0, 0, 0, 0, 0, "Applies cube UV mapping");
uiDefButF(block, NUM,B_UVAUTO_CUBESIZE ,"Size:",315,row-butHB,200,butH, &uv_calc_cubesize, 0.0001, 100.0, 10, 3, "Defines the cubemap size");
uiDefButS(block, MENU, REDRAWBUTSEDIT, "Unwrapper%t|Conformal%x0|Conformal (Old)%x2",100,row,200,butH, &G.scene->toolsettings->unwrapper, 0, 0, 0, 0, "Unwrap method");
if (G.scene->toolsettings->unwrapper != 2)
uiDefButBitS(block, TOG, 1, B_NOP, "Fill Holes",100,row-butHB,200,butH,&G.scene->toolsettings->uvcalc_flag, 0, 0, 0, 0, "Fill holes to prevent internal overlaps");
uiBlockEndAlign(block);
row-= 2*butHB+butS;
row= 180;
uiBlockBeginAlign(block);
uiDefBut(block, BUT, B_UVAUTO_SPHERE,"Sphere",315,row,200,butH, 0, 0, 0, 0, 0, "Applies spherical UV mapping");
uiDefButF(block, NUM,B_UVAUTO_CUBESIZE ,"Cube Size:",315,row,200,butH, &G.scene->toolsettings->uvcalc_cubesize, 0.0001, 100.0, 10, 3, "Defines the cubemap size for cube mapping");
uiBlockEndAlign(block);
row-= butHB+butS;
uiBlockBeginAlign(block);
uiDefBut(block, BUT, B_UVAUTO_CYLINDER,"Cylinder",315,row,200,butH, 0, 0, 0, 0, 0, "Applies cylindrical UV mapping");
uiDefButF(block, NUM,B_UVAUTO_CYLRADIUS ,"Radius:",315,row-butHB,200,butH, &uv_calc_radius, 0.1, 100.0, 10, 3, "Defines the radius of the UV mapping cylinder");
uiDefButF(block, NUM,B_UVAUTO_CYLRADIUS ,"Cyl Radius:",315,row,200,butH, &G.scene->toolsettings->uvcalc_radius, 0.1, 100.0, 10, 3, "Defines the radius of the UV mapping cylinder");
uiBlockEndAlign(block);
row-= 2*butHB+butS;
row-= butHB+butS;
uiBlockBeginAlign(block);
uiDefButS(block, ROW,B_UVAUTO_FACE,"View Aligns Face",315,row,200,butH, &uv_calc_mapdir,2.0, 1.0, 0.0,0.0, "View is on equator for cylindrical and spherical UV mapping");
uiDefButS(block, ROW,B_UVAUTO_TOP,"VA Top",315,row-butHB,100,butH, &uv_calc_mapdir,2.0, 0.0, 0.0,0.0, "View is on poles for cylindrical and spherical UV mapping");
uiDefButS(block, ROW,B_UVAUTO_TOP,"Al Obj",415,row-butHB,100,butH, &uv_calc_mapdir,2.0, 2.0, 0.0,0.0, "Align to object for cylindrical and spherical UV mapping");
uiDefButS(block, ROW,B_UVAUTO_FACE,"View Aligns Face",315,row,200,butH, &G.scene->toolsettings->uvcalc_mapdir,2.0, 1.0, 0.0,0.0, "View is on equator for cylindrical and spherical UV mapping");
uiDefButS(block, ROW,B_UVAUTO_TOP,"VA Top",315,row-butHB,100,butH, &G.scene->toolsettings->uvcalc_mapdir,2.0, 0.0, 0.0,0.0, "View is on poles for cylindrical and spherical UV mapping");
uiDefButS(block, ROW,B_UVAUTO_TOP,"Al Obj",415,row-butHB,100,butH, &G.scene->toolsettings->uvcalc_mapdir,2.0, 2.0, 0.0,0.0, "Align to object for cylindrical and spherical UV mapping");
uiBlockEndAlign(block);
row-= 2*butHB+butS;
uiBlockBeginAlign(block);
uiDefButS(block, ROW,B_UVAUTO_ALIGNX,"Polar ZX",315,row,100,butH, &uv_calc_mapalign,2.0, 0.0, 0.0,0.0, "Polar 0 is X for cylindrical and spherical UV mapping");
uiDefButS(block, ROW,B_UVAUTO_ALIGNY,"Polar ZY",415,row,100,butH, &uv_calc_mapalign,2.0, 1.0, 0.0,0.0, "Polar 0 is Y for cylindrical and spherical UV mapping");
uiDefButS(block, ROW,B_UVAUTO_ALIGNX,"Polar ZX",315,row,100,butH, &G.scene->toolsettings->uvcalc_mapalign,2.0, 0.0, 0.0,0.0, "Polar 0 is X for cylindrical and spherical UV mapping");
uiDefButS(block, ROW,B_UVAUTO_ALIGNY,"Polar ZY",415,row,100,butH, &G.scene->toolsettings->uvcalc_mapalign,2.0, 1.0, 0.0,0.0, "Polar 0 is Y for cylindrical and spherical UV mapping");
uiBlockEndAlign(block);
}

@ -602,7 +602,7 @@ static void draw_image_view_icon(void)
BIF_icon_draw(xPos, 5.0, ICON_STICKY2_UVS);
xPos = 25.0;
}
else if(G.sima->flag & SI_LOCALSTICKY) {
else if(!(G.sima->flag & SI_LOCALSTICKY)) {
BIF_icon_draw(xPos, 5.0, ICON_STICKY_UVS);
xPos = 25.0;
}
@ -1503,20 +1503,28 @@ void image_viewzoom(unsigned short event, int invert)
*/
void image_home(void)
{
int width, height;
int width, height, imgwidth, imgheight;
float zoomX, zoomY;
if (curarea->spacetype != SPACE_IMAGE) return;
if ((G.sima->image == 0) || (G.sima->image->ibuf == 0)) return;
if ((G.sima->image == 0) || (G.sima->image->ibuf == 0)) {
imgwidth = 256;
imgheight = 256;
}
else {
imgwidth = G.sima->image->ibuf->x;
imgheight = G.sima->image->ibuf->y;
}
/* Check if the image will fit in the image with zoom==1 */
width = curarea->winx;
height = curarea->winy;
if (((G.sima->image->ibuf->x >= width) || (G.sima->image->ibuf->y >= height)) &&
if (((imgwidth >= width) || (imgheight >= height)) &&
((width > 0) && (height > 0))) {
/* Find the zoom value that will fit the image in the image space */
zoomX = ((float)width) / ((float)G.sima->image->ibuf->x);
zoomY = ((float)height) / ((float)G.sima->image->ibuf->y);
zoomX = ((float)width) / ((float)imgwidth);
zoomY = ((float)height) / ((float)imgheight);
G.sima->zoom= MIN2(zoomX, zoomY);
image_zoom_power_of_two();

@ -265,17 +265,14 @@ void calculate_uv_map(unsigned short mapmode)
float dx, dy, rotatematrix[4][4], radius= 1.0, min[3], cent[3], max[3];
float fac= 1.0, upangledeg= 0.0, sideangledeg= 90.0;
int i, b, mi, a, n;
/* settings from buttonswindow */
extern float uv_calc_radius, uv_calc_cubesize;
extern short uv_calc_mapdir, uv_calc_mapalign;
if(uv_calc_mapdir==1) {
if(G.scene->toolsettings->uvcalc_mapdir==1) {
upangledeg= 90.0;
sideangledeg= 0.0;
}
else {
upangledeg= 0.0;
if(uv_calc_mapalign==1) sideangledeg= 0.0;
if(G.scene->toolsettings->uvcalc_mapalign==1) sideangledeg= 0.0;
else sideangledeg= 90.0;
}
@ -366,10 +363,10 @@ void calculate_uv_map(unsigned short mapmode)
case B_UVAUTO_SPHERE:
uv_calc_center_vector(cent, ob, me);
if(mapmode==B_UVAUTO_CYLINDER) radius = uv_calc_radius;
if(mapmode==B_UVAUTO_CYLINDER) radius = G.scene->toolsettings->uvcalc_radius;
/* be compatible to the "old" sphere/cylinder mode */
if (uv_calc_mapdir== 2)
if (G.scene->toolsettings->uvcalc_mapdir== 2)
Mat4One(rotatematrix);
else
uv_calc_map_matrix(rotatematrix,ob,upangledeg,sideangledeg,radius);
@ -410,6 +407,7 @@ void calculate_uv_map(unsigned short mapmode)
short cox, coy;
float *loc= ob->obmat[3];
MVert *mv= me->mvert;
float cubesize = G.scene->toolsettings->uvcalc_cubesize;
tface= me->tface;
mface= me->mface;
@ -426,23 +424,23 @@ void calculate_uv_map(unsigned short mapmode)
else if(no[1]>=no[0] && no[1]>=no[2]) coy= 2;
else { cox= 1; coy= 2; }
tface->uv[0][0]= 0.5+0.5*uv_calc_cubesize*(loc[cox] + (mv+mface->v1)->co[cox]);
tface->uv[0][1]= 0.5+0.5*uv_calc_cubesize*(loc[coy] + (mv+mface->v1)->co[coy]);
tface->uv[0][0]= 0.5+0.5*cubesize*(loc[cox] + (mv+mface->v1)->co[cox]);
tface->uv[0][1]= 0.5+0.5*cubesize*(loc[coy] + (mv+mface->v1)->co[coy]);
dx = floor(tface->uv[0][0]);
dy = floor(tface->uv[0][1]);
tface->uv[0][0] -= dx;
tface->uv[0][1] -= dy;
tface->uv[1][0]= 0.5+0.5*uv_calc_cubesize*(loc[cox] + (mv+mface->v2)->co[cox]);
tface->uv[1][1]= 0.5+0.5*uv_calc_cubesize*(loc[coy] + (mv+mface->v2)->co[coy]);
tface->uv[1][0]= 0.5+0.5*cubesize*(loc[cox] + (mv+mface->v2)->co[cox]);
tface->uv[1][1]= 0.5+0.5*cubesize*(loc[coy] + (mv+mface->v2)->co[coy]);
tface->uv[1][0] -= dx;
tface->uv[1][1] -= dy;
tface->uv[2][0]= 0.5+0.5*uv_calc_cubesize*(loc[cox] + (mv+mface->v3)->co[cox]);
tface->uv[2][1]= 0.5+0.5*uv_calc_cubesize*(loc[coy] + (mv+mface->v3)->co[coy]);
tface->uv[2][0]= 0.5+0.5*cubesize*(loc[cox] + (mv+mface->v3)->co[cox]);
tface->uv[2][1]= 0.5+0.5*cubesize*(loc[coy] + (mv+mface->v3)->co[coy]);
tface->uv[2][0] -= dx;
tface->uv[2][1] -= dy;
if(mface->v4) {
tface->uv[3][0]= 0.5+0.5*uv_calc_cubesize*(loc[cox] + (mv+mface->v4)->co[cox]);
tface->uv[3][1]= 0.5+0.5*uv_calc_cubesize*(loc[coy] + (mv+mface->v4)->co[coy]);
tface->uv[3][0]= 0.5+0.5*cubesize*(loc[cox] + (mv+mface->v4)->co[cox]);
tface->uv[3][1]= 0.5+0.5*cubesize*(loc[coy] + (mv+mface->v4)->co[coy]);
tface->uv[3][0] -= dx;
tface->uv[3][1] -= dy;
}
@ -1093,7 +1091,7 @@ void face_borderselect()
#define UV_STD2_MAPPING 129
#define UV_STD1_MAPPING 128
#define UV_WINDOW_MAPPING 5
#define UV_LSCM_MAPPING 6
#define UV_UNWRAP_MAPPING 6
#define UV_CYL_EX 32
#define UV_SPHERE_EX 34
@ -1113,7 +1111,7 @@ void uv_autocalc_tface()
MENUSTRING("Cube", UV_CUBE_MAPPING) "|"
MENUSTRING("Cylinder", UV_CYL_MAPPING) "|"
MENUSTRING("Sphere", UV_SPHERE_MAPPING) "|"
MENUSTRING("LSCM", UV_LSCM_MAPPING) "|"
MENUSTRING("Unwrap", UV_UNWRAP_MAPPING) "|"
MENUSTRING("Bounds to 1/8", UV_BOUNDS8_MAPPING) "|"
MENUSTRING("Bounds to 1/4", UV_BOUNDS4_MAPPING) "|"
MENUSTRING("Bounds to 1/2", UV_BOUNDS2_MAPPING) "|"
@ -1150,7 +1148,7 @@ void uv_autocalc_tface()
calculate_uv_map(B_UVAUTO_STD1); break;
case UV_WINDOW_MAPPING:
calculate_uv_map(B_UVAUTO_WINDOW); break;
case UV_LSCM_MAPPING:
case UV_UNWRAP_MAPPING:
unwrap_lscm(); break;
}
}

@ -1282,6 +1282,7 @@ void toggle_uv_select(int mode)
case 's':
G.sima->flag ^= SI_STICKYUVS;
if (G.sima->flag & SI_STICKYUVS) G.sima->flag &= ~SI_LOCALSTICKY;
else G.sima->flag |= SI_LOCALSTICKY;
break;
case 'l':
G.sima->flag ^= SI_LOCALSTICKY;

@ -543,8 +543,10 @@ static void do_image_selectmenu(void *arg, int event)
allqueue(REDRAWIMAGE, 0);
break;
case 5: /* Toggle UVs Stick to Vertex in Mesh */
if(G.sima->flag & SI_STICKYUVS)
if(G.sima->flag & SI_STICKYUVS) {
G.sima->flag &= ~SI_STICKYUVS;
G.sima->flag |= SI_LOCALSTICKY;
}
else {
G.sima->flag |= SI_STICKYUVS;
G.sima->flag &= ~SI_LOCALSTICKY;
@ -1030,8 +1032,8 @@ static void do_image_uvsmenu(void *arg, int event)
unwrap_lscm();
break;
case 11:
if(G.sima->flag & SI_LSCM_LIVE) G.sima->flag &= ~SI_LSCM_LIVE;
else G.sima->flag |= SI_LSCM_LIVE;
if(G.sima->flag & SI_LIVE_UNWRAP) G.sima->flag &= ~SI_LIVE_UNWRAP;
else G.sima->flag |= SI_LIVE_UNWRAP;
break;
case 12:
minimize_stretch_tface_uv();
@ -1062,9 +1064,9 @@ static uiBlock *image_uvsmenu(void *arg_unused)
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
if(G.sima->flag & SI_LSCM_LIVE) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "LSCM Live Transform", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, "");
else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "LSCM Live Transform", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "LSCM Unwrap|E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 10, "");
if(G.sima->flag & SI_LIVE_UNWRAP) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Live Unwrap Transform", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, "");
else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Live Unwrap Transform", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Unwrap|E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 10, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Unpin|Alt P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Pin|P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
@ -1123,7 +1125,6 @@ void image_buttons(void)
char naam[256];
/* This should not be a static var */
static int headerbuttons_packdummy;
extern short CurrentUnwrapper;
headerbuttons_packdummy = 0;
@ -1212,9 +1213,6 @@ void image_buttons(void)
/* draw LOCK */
uiDefIconButS(block, ICONTOG, 0, ICON_UNLOCKED, xco,0,XIC,YIC, &(G.sima->lock), 0, 0, 0, 0, "Updates other affected window spaces automatically to reflect changes in real time");
xco += 2*XIC;
uiDefButS(block, MENU, B_NOP, "Unwrapper%t|Old LSCM%x0|New LSCM%x1",xco,0,85,YIC, &CurrentUnwrapper, 0, 0, 0, 0, "Unwrapper");
/* Always do this last */
curarea->headbutlen= xco+2*XIC;

File diff suppressed because it is too large Load Diff

@ -52,7 +52,7 @@ void param_delete(ParamHandle *chart);
quick re-solving
*/
void param_lscm_begin(ParamHandle *handle, ParamBool live);
void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf);
void param_lscm_solve(ParamHandle *handle);
void param_lscm_end(ParamHandle *handle);
@ -63,6 +63,10 @@ void param_stretch_blend(ParamHandle *handle, float blend);
void param_stretch_iter(ParamHandle *handle);
void param_stretch_end(ParamHandle *handle);
/* Area Smooth */
void param_smooth_area(ParamHandle *handle);
/* Packing */
void param_pack(ParamHandle *handle);
@ -72,6 +76,7 @@ void param_pack(ParamHandle *handle);
void param_flush(ParamHandle *handle);
void param_flush_restore(ParamHandle *handle);
#ifdef __cplusplus
}
#endif

@ -2,11 +2,33 @@
#ifndef __PARAMETRIZER_INTERN_H__
#define __PARAMETRIZER_INTERN_H__
/* Hash:
-----
- insert only
- elements are all stored in a flat linked list
*/
/* Utils */
#if 0
#define param_assert(condition);
#define param_warning(message);
#define param_test_equals_ptr(condition);
#define param_test_equals_int(condition);
#else
#define param_assert(condition) \
if (!(condition)) \
{ printf("Assertion %s:%d\n", __FILE__, __LINE__); abort(); }
#define param_warning(message) \
{ printf("Warning %s:%d: %s\n", __FILE__, __LINE__, message); }
#define param_test_equals_ptr(str, a, b) \
if (a != b) \
{ printf("Equals %s => %p != %p\n", str, a, b); };
#define param_test_equals_int(str, a, b) \
if (a != b) \
{ printf("Equals %s => %d != %d\n", str, a, b); };
#endif
typedef enum PBool {
P_TRUE = 1,
P_FALSE = 0
} PBool;
/* Special Purpose Hash */
typedef long PHashKey;
@ -16,36 +38,12 @@ typedef struct PHashLink {
} PHashLink;
typedef struct PHash {
PHashLink *first;
PHashLink **list;
PHashLink **buckets;
int size, cursize, cursize_id;
} PHash;
PHash *phash_new(int sizehint);
void phash_delete_with_links(PHash *ph);
void phash_delete(PHash *ph);
int phash_size(PHash *ph);
void phash_insert(PHash *ph, PHashLink *link);
PHashLink *phash_lookup(PHash *ph, PHashKey key);
PHashLink *phash_next(PHash *ph, PHashKey key, PHashLink *link);
#if 0
#define param_assert(condition)
#define param_warning(message);
#else
#define param_assert(condition) \
if (!(condition)) \
{ printf("Assertion %s:%d\n", __FILE__, __LINE__); abort(); }
#define param_warning(message) \
{ printf("Warning %s:%d: %s\n", __FILE__, __LINE__, message); }
#endif
typedef enum PBool {
P_TRUE = 1,
P_FALSE = 0
} PBool;
struct PVert;
struct PEdge;
@ -64,6 +62,8 @@ typedef struct PHeapLink {
typedef struct PHeap {
unsigned int size;
unsigned int bufsize;
MemArena *arena;
PHeapLink *freelinks;
PHeapLink *links;
PHeapLink **tree;
} PHeap;
@ -71,58 +71,61 @@ typedef struct PHeap {
/* Simplices */
typedef struct PVert {
struct PVertLink {
struct PVert *next;
PHashKey key;
} link;
struct PVert *nextlink;
union PVertUnion {
PHashKey key; /* construct */
int id; /* abf/lscm matrix index */
float distortion; /* area smoothing */
PHeapLink *heaplink; /* edge collapsing */
} u;
struct PEdge *edge;
float *co;
float uv[2];
int flag;
unsigned char flag;
union PVertUnion {
int index; /* lscm matrix index */
float distortion; /* area smoothing */
} u;
} PVert;
typedef struct PEdge {
struct PEdgeLink {
struct PEdge *next;
PHashKey key;
} link;
struct PEdge *nextlink;
union PEdgeUnion {
PHashKey key; /* construct */
int id; /* abf matrix index */
PHeapLink *heaplink; /* fill holes */
struct PEdge *nextcollapse; /* simplification */
} u;
struct PVert *vert;
struct PEdge *pair;
struct PEdge *next;
struct PFace *face;
float *orig_uv, old_uv[2];
int flag;
unsigned short flag;
union PEdgeUnion {
PHeapLink *heaplink;
} u;
} PEdge;
typedef struct PFace {
struct PFaceLink {
struct PFace *next;
PHashKey key;
} link;
struct PEdge *edge;
int flag;
struct PFace *nextlink;
union PFaceUnion {
int chart; /* chart construction */
float area3d; /* stretch */
PHashKey key; /* construct */
int chart; /* construct splitting*/
float area3d; /* stretch */
int id; /* abf matrix index */
} u;
struct PEdge *edge;
unsigned char flag;
} PFace;
enum PVertFlag {
PVERT_PIN = 1,
PVERT_SELECT = 2
PVERT_SELECT = 2,
PVERT_INTERIOR = 4,
PVERT_COLLAPSE = 8
};
enum PEdgeFlag {
@ -131,7 +134,10 @@ enum PEdgeFlag {
PEDGE_PIN = 4,
PEDGE_SELECT = 8,
PEDGE_DONE = 16,
PEDGE_FILLED = 32
PEDGE_FILLED = 32,
PEDGE_COLLAPSE = 64,
PEDGE_COLLAPSE_EDGE = 128,
PEDGE_COLLAPSE_PAIR = 256
};
/* for flipping faces */
@ -139,15 +145,21 @@ enum PEdgeFlag {
enum PFaceFlag {
PFACE_CONNECTED = 1,
PFACE_FILLED = 2
PFACE_FILLED = 2,
PFACE_COLLAPSE = 4
};
/* Chart */
typedef struct PChart {
PHash *verts;
PHash *edges;
PHash *faces;
PVert *verts;
PEdge *edges;
PFace *faces;
int nverts, nedges, nfaces;
PVert *collapsed_verts;
PEdge *collapsed_edges;
PFace *collapsed_faces;
union PChartUnion {
struct PChartLscm {
@ -161,7 +173,7 @@ typedef struct PChart {
} pack;
} u;
int flag;
unsigned char flag;
struct PHandle *handle;
} PChart;
@ -173,16 +185,21 @@ enum PHandleState {
PHANDLE_STATE_ALLOCATED,
PHANDLE_STATE_CONSTRUCTED,
PHANDLE_STATE_LSCM,
PHANDLE_STATE_STRETCH,
PHANDLE_STATE_STRETCH
};
typedef struct PHandle {
PChart *construction_chart;
PChart **charts;
int ncharts;
enum PHandleState state;
MemArena *arena;
PBool implicit;
PChart *construction_chart;
PHash *hash_verts;
PHash *hash_edges;
PHash *hash_faces;
PChart **charts;
int ncharts;
RNG *rng;
float blend;
} PHandle;

@ -3973,7 +3973,7 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
toggle_uv_select('f');
break;
case EKEY :
if(okee("LSCM Unwrap"))
if(okee("Unwrap"))
unwrap_lscm();
break;
case GKEY:
@ -4036,6 +4036,8 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
initTransform(TFM_RESIZE, CTX_NONE);
Transform();
}
else if((G.qual==LR_SHIFTKEY) && is_uv_tface_editing_allowed())
smooth_area_tface_uv();
break;
case VKEY:
if((G.qual==0))
@ -4100,6 +4102,7 @@ static void init_imagespace(ScrArea *sa)
sima->spacetype= SPACE_IMAGE;
sima->zoom= 1;
sima->blockscale= 0.7;
sima->flag = SI_LOCALSTICKY;
}

@ -1786,7 +1786,7 @@ static void createTransUVs(TransInfo *t)
}
}
if (G.sima->flag & SI_LSCM_LIVE)
if (G.sima->flag & SI_LIVE_UNWRAP)
unwrap_lscm_live_begin();
}

@ -300,7 +300,7 @@ void recalcData(TransInfo *t)
}
else if(t->spacetype==SPACE_IMAGE) {
flushTransUVs(t);
if (G.sima->flag & SI_LSCM_LIVE)
if (G.sima->flag & SI_LIVE_UNWRAP)
unwrap_lscm_live_re_solve();
}
else {
@ -484,8 +484,8 @@ void postTrans (TransInfo *t)
}
if(t->spacetype==SPACE_IMAGE) {
if (G.sima->flag & SI_LSCM_LIVE)
unwrap_lscm_live_end();
if (G.sima->flag & SI_LIVE_UNWRAP)
unwrap_lscm_live_end(t->state == TRANS_CANCEL);
}
}

@ -67,8 +67,6 @@
#include "parametrizer.h"
short CurrentUnwrapper = 0;
/* Implementation Least Squares Conformal Maps parameterization, based on
* chapter 2 of:
* Bruno Levy, Sylvain Petitjean, Nicolas Ray, Jerome Maillot. Least Squares
@ -1143,7 +1141,7 @@ void unwrap_lscm(void)
Mesh *me;
int totgroup, *groups=NULL, a;
if (CurrentUnwrapper == 1) {
if (G.scene->toolsettings->unwrapper != 2) {
unwrap_lscm_new();
return;
}
@ -1435,22 +1433,25 @@ void unwrap_lscm_new(void)
{
Mesh *me;
ParamHandle *handle;
short abf = G.scene->toolsettings->unwrapper == 1;
short fillholes = G.scene->toolsettings->uvcalc_flag & 1;
me= get_mesh(OBACT);
if(me==0 || me->tface==0) return;
handle = construct_param_handle(me, 0, 1);
handle = construct_param_handle(me, 0, fillholes);
param_lscm_begin(handle, PARAM_FALSE);
param_lscm_begin(handle, PARAM_FALSE, abf);
param_lscm_solve(handle);
param_lscm_end(handle);
param_pack(handle);
param_flush(handle);
param_delete(handle);
BIF_undo_push("UV lscm unwrap");
BIF_undo_push("UV unwrap");
object_uvs_changed(OBACT);
@ -1465,11 +1466,12 @@ void minimize_stretch_tface_uv(void)
double lasttime;
short doit = 1, escape = 0, val, blend = 0;
unsigned short event = 0;
short fillholes = G.scene->toolsettings->uvcalc_flag & 1;
me = get_mesh(OBACT);
if(me==0 || me->tface==0) return;
handle = construct_param_handle(me, 1, 0);
handle = construct_param_handle(me, 1, fillholes);
lasttime = PIL_check_seconds_timer();
@ -1527,6 +1529,7 @@ void minimize_stretch_tface_uv(void)
headerprint(str);
lasttime = PIL_check_seconds_timer();
object_uvs_changed(OBACT);
if(G.sima->lock) force_draw_plus(SPACE_VIEW3D, 0);
else force_draw(0);
}
@ -1549,6 +1552,28 @@ void minimize_stretch_tface_uv(void)
allqueue(REDRAWIMAGE, 0);
}
void smooth_area_tface_uv(void)
{
Mesh *me;
ParamHandle *handle;
short fillholes = G.scene->toolsettings->uvcalc_flag & 1;
me = get_mesh(OBACT);
if(me==0 || me->tface==0) return;
handle = construct_param_handle(me, 1, fillholes);
param_smooth_area(handle);
param_flush(handle);
param_delete(handle);
BIF_undo_push("UV smooth area");
object_uvs_changed(OBACT);
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWIMAGE, 0);
}
/* LSCM live mode */
static ParamHandle *liveHandle = NULL;
@ -1556,21 +1581,23 @@ static ParamHandle *liveHandle = NULL;
void unwrap_lscm_live_begin(void)
{
Mesh *me;
short abf = G.scene->toolsettings->unwrapper == 1;
short fillholes = G.scene->toolsettings->uvcalc_flag & 1;
if (CurrentUnwrapper == 0)
if (G.scene->toolsettings->unwrapper == 2)
return;
me= get_mesh(OBACT);
if(me==0 || me->tface==0) return;
liveHandle = construct_param_handle(me, 0, 0);
liveHandle = construct_param_handle(me, 0, fillholes);
param_lscm_begin(liveHandle, PARAM_TRUE);
param_lscm_begin(liveHandle, PARAM_TRUE, abf);
}
void unwrap_lscm_live_re_solve(void)
{
if (CurrentUnwrapper == 0) {
if (G.scene->toolsettings->unwrapper == 2) {
unwrap_lscm();
return;
}
@ -1581,13 +1608,15 @@ void unwrap_lscm_live_re_solve(void)
}
}
void unwrap_lscm_live_end(void)
void unwrap_lscm_live_end(short cancel)
{
if (CurrentUnwrapper == 0)
if (G.scene->toolsettings->unwrapper == 2)
return;
if (liveHandle) {
param_lscm_end(liveHandle);
if (cancel)
param_flush_restore(liveHandle);
param_delete(liveHandle);
liveHandle = NULL;
}