diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 1e62dacc158..1b594e6d492 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -47,7 +47,6 @@ struct MVert; struct Object; -struct TFace; struct EditMesh; struct DispListMesh; struct ModifierData; @@ -144,7 +143,7 @@ struct DerivedMesh { /* Draw all faces uses TFace * o Drawing options too complicated to enumerate, look at code. */ - void (*drawFacesTex)(DerivedMesh *dm, int (*setDrawOptions)(struct TFace *tf, int matnr)); + void (*drawMappedFacesTex)(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int matnr), void *userData); /* Draw mapped faces (no color, or texture) * o Only if !setDrawOptions or setDrawOptions(userData, mapped-face-index, drawSmooth_r) returns true diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 1a26b52a0aa..c51a50dd313 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -366,7 +366,7 @@ static void meshDM_drawFacesColored(DerivedMesh *dm, int useTwoSide, unsigned ch glShadeModel(GL_FLAT); glDisable(GL_CULL_FACE); } -static void meshDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, int matnr)) +static void meshDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawParams)(void *userData, int index, int matnr), void *userData) { MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm; Mesh *me = mdm->me; @@ -382,7 +382,7 @@ static void meshDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, int flag; unsigned char *cp= NULL; - flag = setDrawParams(tf, mf->mat_nr); + flag = setDrawParams(userData, i, mf->mat_nr); if (flag==0) { continue; @@ -535,7 +535,7 @@ static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3] mdm->dm.drawFacesSolid = meshDM_drawFacesSolid; mdm->dm.drawFacesColored = meshDM_drawFacesColored; - mdm->dm.drawFacesTex = meshDM_drawFacesTex; + mdm->dm.drawMappedFacesTex = meshDM_drawMappedFacesTex; mdm->dm.drawMappedFaces = meshDM_drawMappedFaces; mdm->dm.drawMappedEdges = meshDM_drawMappedEdges; @@ -1202,7 +1202,8 @@ static void ssDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned cha #undef PASSVERT } -static void ssDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, int matnr)) + +static void ssDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawParams)(void *userData, int index, int matnr), void *userData) { SSDerivedMesh *ssdm = (SSDerivedMesh*) dm; DispListMesh *dlm = ssdm->dlm; @@ -1210,7 +1211,7 @@ static void ssDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, i MFace *mface= dlm->mface; TFace *tface = dlm->tface; float *nors = dlm->nors; - int a; + int a, index=-1; for (a=0; atotface; a++) { MFace *mf= &mface[a]; @@ -1218,7 +1219,9 @@ static void ssDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, i int flag; unsigned char *cp= NULL; - flag = setDrawParams(tf, mf->mat_nr); + if (mf->flag&ME_FACE_STEPINDEX) index++; + + flag = setDrawParams(userData, index, mf->mat_nr); if (flag==0) { continue; @@ -1401,7 +1404,7 @@ DerivedMesh *derivedmesh_from_displistmesh(DispListMesh *dlm, float (*vertexCos) ssdm->dm.drawFacesSolid = ssDM_drawFacesSolid; ssdm->dm.drawFacesColored = ssDM_drawFacesColored; - ssdm->dm.drawFacesTex = ssDM_drawFacesTex; + ssdm->dm.drawMappedFacesTex = ssDM_drawMappedFacesTex; ssdm->dm.drawMappedFaces = ssDM_drawMappedFaces; /* EM functions */ @@ -1624,7 +1627,7 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, DerivedMesh **final_r) ModifierData *md; float (*deformedVerts)[3] = NULL; DerivedMesh *dm; - int i, numVerts, cageIndex = modifiers_getCageIndex(ob, NULL); + int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL); modifiers_clearErrors(ob); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index d0b741123b5..e7870fe150e 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1376,7 +1376,7 @@ static void ccgDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned ch ccgFaceIterator_free(fi); } -static void ccgDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, int matnr)) { +static void ccgDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawParams)(void *userData, int index, int matnr), void *userData) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); @@ -1395,7 +1395,8 @@ static void ccgDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, MFace *mf = &mface[index]; TFace *tf = tface?&tface[index]:NULL; unsigned char *cp= NULL; - int flag = setDrawParams(tf, mf->mat_nr); + int findex = ccgDM_getFaceMapIndex(ccgdm, ss, f); + int flag = (findex == -1)? 0: setDrawParams(userData, findex, mf->mat_nr); if (flag==0) { continue; @@ -1662,7 +1663,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int fromEditmesh, int d ccgdm->dm.drawLooseEdges = ccgDM_drawLooseEdges; ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid; ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored; - ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex; + ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex; ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces; ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp; diff --git a/source/blender/include/BDR_drawmesh.h b/source/blender/include/BDR_drawmesh.h index c6bcf061fcc..7463cffa6ef 100644 --- a/source/blender/include/BDR_drawmesh.h +++ b/source/blender/include/BDR_drawmesh.h @@ -37,6 +37,7 @@ struct Image; struct TFace; struct Object; struct Mesh; +struct EdgeHash; /** * Enables or disable mipmapping for realtime images (textures). @@ -74,6 +75,7 @@ void free_all_realtime_images(void); void make_repbind(struct Image *ima); int set_tpage(struct TFace *tface); void draw_tface_mesh(struct Object *ob, struct Mesh *me, int dt); +struct EdgeHash *get_tface_mesh_marked_edge_info(struct Mesh *me); void init_realtime_GL(void); #endif /* BDR_DRAWMESH_H */ diff --git a/source/blender/include/BDR_editface.h b/source/blender/include/BDR_editface.h index 0f817c17227..9b260a3df47 100644 --- a/source/blender/include/BDR_editface.h +++ b/source/blender/include/BDR_editface.h @@ -36,7 +36,7 @@ struct TFace; struct Mesh; -void set_lasttface(void); +struct TFace *get_active_tface(void); void calculate_uv_map(unsigned short mapmode); void default_uv(float uv[][2], float size); void default_tface(struct TFace *tface); @@ -49,13 +49,13 @@ void selectswap_tface(void); void rotate_uv_tface(void); void mirror_uv_tface(void); void minmax_tface(float *min, float *max); -int face_pick(struct Mesh *me, short x, short y, unsigned int *index); void face_select(void); void face_borderselect(void); void uv_autocalc_tface(void); void set_faceselect(void); void face_draw(void); void get_same_uv(void); +void seam_mark_clear_tface(short mode); #endif /* BDR_EDITFACE_H */ diff --git a/source/blender/include/BDR_unwrapper.h b/source/blender/include/BDR_unwrapper.h index 6107eba15a2..396bb17cff0 100644 --- a/source/blender/include/BDR_unwrapper.h +++ b/source/blender/include/BDR_unwrapper.h @@ -36,8 +36,7 @@ void set_seamtface(void); /* set TF_SEAM flags in tfaces */ 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 unwrap_lscm(short seamcut); /* unwrap faces selected in 3d view */ void minimize_stretch_tface_uv(void); /* optimize faces selected in uv editor */ void smooth_area_tface_uv(void); diff --git a/source/blender/include/BSE_drawview.h b/source/blender/include/BSE_drawview.h index 1d04062fb8d..1174aee6c64 100644 --- a/source/blender/include/BSE_drawview.h +++ b/source/blender/include/BSE_drawview.h @@ -37,6 +37,7 @@ struct Object; struct BGpic; struct rcti; struct ScrArea; +struct ImBuf; void setalpha_bgpic(struct BGpic *bgpic); void default_gl_light(void); @@ -52,6 +53,11 @@ void do_viewbuts(unsigned short event); void add_view3d_after(struct View3D *v3d, struct Base *base, int type); void backdrawview3d(int test); +void check_backbuf(void); +unsigned int sample_backbuf(int x, int y); +struct ImBuf *read_backbuf(short xmin, short ymin, short xmax, short ymax); +unsigned int sample_backbuf_rect(short mval[2], int size, unsigned int min, unsigned int max, short *dist);; + void drawview3dspace(struct ScrArea *sa, void *spacedata); void drawview3d_render(struct View3D *v3d, int winx, int winy); diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index 184763fd9da..6d6da4bc856 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -86,6 +86,7 @@ extern void do_latticebuts(unsigned short event); extern void do_fpaintbuts(unsigned short event); extern void do_cambuts(unsigned short event); extern void do_armbuts(unsigned short event); +extern void do_uvautocalculationbuts(unsigned short event); extern char *get_vertexgroup_menustr(struct Object *ob); // used in object buttons @@ -113,11 +114,6 @@ extern void do_scriptbuts(unsigned short event); /* ipowindow */ extern void do_ipobuts(unsigned short event); // drawipo.c (bad! ton) -/* uvautocalculation */ -void do_uvautocalculationbuts(unsigned short event); -void get_uvautocalculationsettings(float *radius,float *cubesize, int *mapdir, int *mapalign); - - /* butspace.c */ void test_meshpoin_but(char *name, struct ID **idpp); void test_obpoin_but(char *name, struct ID **idpp); diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index f6f16b94f3a..e5496c895bc 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -155,14 +155,14 @@ typedef struct Mesh { #define TF_SUB 3 /* tface->unwrap */ -#define TF_SEAM1 1 -#define TF_SEAM2 2 -#define TF_SEAM3 4 -#define TF_SEAM4 8 -#define TF_PIN1 16 -#define TF_PIN2 32 -#define TF_PIN3 64 -#define TF_PIN4 128 +#define TF_DEPRECATED1 1 +#define TF_DEPRECATED2 2 +#define TF_DEPRECATED3 4 +#define TF_DEPRECATED4 8 +#define TF_PIN1 16 +#define TF_PIN2 32 +#define TF_PIN3 64 +#define TF_PIN4 128 #define MESH_MAX_VERTS 2000000000L diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 9fe5a3acacf..834c206d8e0 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -85,6 +85,7 @@ typedef struct MSticky { // reserve 16 for ME_HIDE #define ME_EDGERENDER (1<<5) #define ME_LOOSEEDGE (1<<7) +#define ME_SEAM_LAST (1<<8) #define ME_EDGE_STEPINDEX (1<<15) /* puno = vertexnormal (mface) */ diff --git a/source/blender/src/butspace.c b/source/blender/src/butspace.c index e3f6a1d5515..2d293966e79 100644 --- a/source/blender/src/butspace.c +++ b/source/blender/src/butspace.c @@ -580,7 +580,7 @@ void do_butspace(unsigned short event) do_constraintbuts(event); } else if(event<=B_UVAUTOCALCBUTS) { - do_uvautocalculationbuts(event); + do_uvcalculationbuts(event); } else if(event<=B_EFFECTSBUTS) { do_effects_panels(event); diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 028f3d43540..9077aae86aa 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -3540,7 +3540,8 @@ void do_fpaintbuts(unsigned short event) Mesh *me; Object *ob; bDeformGroup *defGroup; - extern TFace *lasttface; /* caches info on tface bookkeeping ?*/ + TFace *activetf, *tf; + int a; extern VPaint Gwp; /* from vpaint */ ob= OBACT; @@ -3555,42 +3556,37 @@ void do_fpaintbuts(unsigned short event) case B_COPY_TF_UV: case B_COPY_TF_COL: case B_COPY_TF_TEX: - me= get_mesh(ob); - if(me && me->tface) { -/* extern TFace *lasttface; */ - TFace *tface= me->tface; - int a= me->totface; + me = get_mesh(OBACT); + activetf = get_active_tface(); - set_lasttface(); - if(lasttface) { - - while(a--) { - if(tface!=lasttface && (tface->flag & TF_SELECT)) { - if(event==B_COPY_TF_MODE) { - tface->mode= lasttface->mode; - tface->transp= lasttface->transp; - } - else if(event==B_COPY_TF_UV) { - memcpy(tface->uv, lasttface->uv, sizeof(tface->uv)); - tface->tpage= lasttface->tpage; - tface->tile= lasttface->tile; - - if(lasttface->mode & TF_TILES) tface->mode |= TF_TILES; - else tface->mode &= ~TF_TILES; - - } - else if(event==B_COPY_TF_TEX) { - tface->tpage= lasttface->tpage; - tface->tile= lasttface->tile; - - if(lasttface->mode & TF_TILES) tface->mode |= TF_TILES; - else tface->mode &= ~TF_TILES; - } - else if(event==B_COPY_TF_COL) memcpy(tface->col, lasttface->col, sizeof(tface->col)); + if(me && activetf) { + for (a=0, tf=me->tface; a < me->totface; a++, tf++) { + if(tf!=activetf && (tf->flag & TF_SELECT)) { + if(event==B_COPY_TF_MODE) { + tf->mode= activetf->mode; + tf->transp= activetf->transp; } - tface++; + else if(event==B_COPY_TF_UV) { + memcpy(tf->uv, activetf->uv, sizeof(tf->uv)); + tf->tpage= activetf->tpage; + tf->tile= activetf->tile; + + if(activetf->mode & TF_TILES) tf->mode |= TF_TILES; + else tf->mode &= ~TF_TILES; + + } + else if(event==B_COPY_TF_TEX) { + tf->tpage= activetf->tpage; + tf->tile= activetf->tile; + + if(activetf->mode & TF_TILES) tf->mode |= TF_TILES; + else tf->mode &= ~TF_TILES; + } + else if(event==B_COPY_TF_COL) + memcpy(tf->col, activetf->col, sizeof(tf->col)); } } + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); do_shared_vertexcol(me); allqueue(REDRAWVIEW3D, 0); @@ -3616,17 +3612,17 @@ void do_fpaintbuts(unsigned short event) break; case B_TFACE_HALO: - set_lasttface(); - if(lasttface) { - lasttface->mode &= ~TF_BILLBOARD2; + activetf = get_active_tface(); + if(activetf) { + activetf->mode &= ~TF_BILLBOARD2; allqueue(REDRAWBUTSEDIT, 0); } break; case B_TFACE_BILLB: - set_lasttface(); - if(lasttface) { - lasttface->mode &= ~TF_BILLBOARD; + activetf = get_active_tface(); + if(activetf) { + activetf->mode &= ~TF_BILLBOARD; allqueue(REDRAWBUTSEDIT, 0); } break; @@ -3786,38 +3782,37 @@ static void editing_panel_mesh_texface(void) { extern VPaint Gvp; /* from vpaint */ uiBlock *block; - extern TFace *lasttface; + TFace *tf; block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_texface", UI_EMBOSS, UI_HELV, curarea->win); if(uiNewPanel(curarea, block, "Texture face", "Editing", 960, 0, 318, 204)==0) return; - set_lasttface(); // checks for ob type - if(lasttface) { + tf = get_active_tface(); + if(tf) { + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, TF_TEX, B_REDR_3D_IMA, "Tex", 600,160,60,19, &tf->mode, 0, 0, 0, 0, "Render face with texture"); + uiDefButBitS(block, TOG, TF_TILES, B_REDR_3D_IMA, "Tiles", 660,160,60,19, &tf->mode, 0, 0, 0, 0, "Use tilemode for face"); + uiDefButBitS(block, TOG, TF_LIGHT, REDRAWVIEW3D, "Light", 720,160,60,19, &tf->mode, 0, 0, 0, 0, "Use light for face"); + uiDefButBitS(block, TOG, TF_INVISIBLE, REDRAWVIEW3D, "Invisible",780,160,60,19, &tf->mode, 0, 0, 0, 0, "Make face invisible"); + uiDefButBitS(block, TOG, TF_DYNAMIC, REDRAWVIEW3D, "Collision", 840,160,60,19, &tf->mode, 0, 0, 0, 0, "Use face for collision detection"); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, TF_TEX, B_REDR_3D_IMA, "Tex", 600,160,60,19, &lasttface->mode, 0, 0, 0, 0, "Render face with texture"); - uiDefButBitS(block, TOG, TF_TILES, B_REDR_3D_IMA, "Tiles", 660,160,60,19, &lasttface->mode, 0, 0, 0, 0, "Use tilemode for face"); - uiDefButBitS(block, TOG, TF_LIGHT, REDRAWVIEW3D, "Light", 720,160,60,19, &lasttface->mode, 0, 0, 0, 0, "Use light for face"); - uiDefButBitS(block, TOG, TF_INVISIBLE, REDRAWVIEW3D, "Invisible",780,160,60,19, &lasttface->mode, 0, 0, 0, 0, "Make face invisible"); - uiDefButBitS(block, TOG, TF_DYNAMIC, REDRAWVIEW3D, "Collision", 840,160,60,19, &lasttface->mode, 0, 0, 0, 0, "Use face for collision detection"); - - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, TF_SHAREDCOL, REDRAWVIEW3D, "Shared", 600,135,60,19, &lasttface->mode, 0, 0, 0, 0, "Blend vertex colours across face when vertices are shared"); - uiDefButBitS(block, TOG, TF_TWOSIDE, REDRAWVIEW3D, "Twoside",660,135,60,19, &lasttface->mode, 0, 0, 0, 0, "Render face twosided"); - uiDefButBitS(block, TOG, TF_OBCOL, REDRAWVIEW3D, "ObColor",720,135,60,19, &lasttface->mode, 0, 0, 0, 0, "Use ObColor instead of vertex colours"); + uiDefButBitS(block, TOG, TF_SHAREDCOL, REDRAWVIEW3D, "Shared", 600,135,60,19, &tf->mode, 0, 0, 0, 0, "Blend vertex colours across face when vertices are shared"); + uiDefButBitS(block, TOG, TF_TWOSIDE, REDRAWVIEW3D, "Twoside",660,135,60,19, &tf->mode, 0, 0, 0, 0, "Render face twosided"); + uiDefButBitS(block, TOG, TF_OBCOL, REDRAWVIEW3D, "ObColor",720,135,60,19, &tf->mode, 0, 0, 0, 0, "Use ObColor instead of vertex colours"); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, TF_BILLBOARD, B_TFACE_HALO, "Halo", 600,110,60,19, &lasttface->mode, 0, 0, 0, 0, "Screen aligned billboard"); - uiDefButBitS(block, TOG, TF_BILLBOARD2, B_TFACE_BILLB, "Billboard",660,110,60,19, &lasttface->mode, 0, 0, 0, 0, "Billboard with Z-axis constraint"); - uiDefButBitS(block, TOG, TF_SHADOW, REDRAWVIEW3D, "Shadow", 720,110,60,19, &lasttface->mode, 0, 0, 0, 0, "Face is used for shadow"); - uiDefButBitS(block, TOG, TF_BMFONT, REDRAWVIEW3D, "Text", 780,110,60,19, &lasttface->mode, 0, 0, 0, 0, "Enable bitmap text on face"); + uiDefButBitS(block, TOG, TF_BILLBOARD, B_TFACE_HALO, "Halo", 600,110,60,19, &tf->mode, 0, 0, 0, 0, "Screen aligned billboard"); + uiDefButBitS(block, TOG, TF_BILLBOARD2, B_TFACE_BILLB, "Billboard",660,110,60,19, &tf->mode, 0, 0, 0, 0, "Billboard with Z-axis constraint"); + uiDefButBitS(block, TOG, TF_SHADOW, REDRAWVIEW3D, "Shadow", 720,110,60,19, &tf->mode, 0, 0, 0, 0, "Face is used for shadow"); + uiDefButBitS(block, TOG, TF_BMFONT, REDRAWVIEW3D, "Text", 780,110,60,19, &tf->mode, 0, 0, 0, 0, "Enable bitmap text on face"); uiBlockBeginAlign(block); uiBlockSetCol(block, TH_BUT_SETTING1); - uiDefButC(block, ROW, REDRAWVIEW3D, "Opaque", 600,80,60,19, &lasttface->transp, 2.0, 0.0, 0, 0, "Render colour of textured face as colour"); - uiDefButC(block, ROW, REDRAWVIEW3D, "Add", 660,80,60,19, &lasttface->transp, 2.0, 1.0, 0, 0, "Render face transparent and add colour of face"); - uiDefButC(block, ROW, REDRAWVIEW3D, "Alpha", 720,80,60,19, &lasttface->transp, 2.0, 2.0, 0, 0, "Render polygon transparent, depending on alpha channel of the texture"); + uiDefButC(block, ROW, REDRAWVIEW3D, "Opaque", 600,80,60,19, &tf->transp, 2.0, 0.0, 0, 0, "Render colour of textured face as colour"); + uiDefButC(block, ROW, REDRAWVIEW3D, "Add", 660,80,60,19, &tf->transp, 2.0, 1.0, 0, 0, "Render face transparent and add colour of face"); + uiDefButC(block, ROW, REDRAWVIEW3D, "Alpha", 720,80,60,19, &tf->transp, 2.0, 2.0, 0, 0, "Render polygon transparent, depending on alpha channel of the texture"); uiBlockSetCol(block, TH_AUTO); @@ -3832,29 +3827,9 @@ static void editing_panel_mesh_texface(void) } } -void do_uvautocalculationbuts(unsigned short event) +void do_uvcalculationbuts(unsigned short event) { - switch(event) { - case B_UVAUTO_STD1: - case B_UVAUTO_STD2: - case B_UVAUTO_STD4: - case B_UVAUTO_STD8: - case B_UVAUTO_CUBE: - calculate_uv_map(event); - break; - case B_UVAUTO_BOUNDS1: - case B_UVAUTO_BOUNDS2: - case B_UVAUTO_BOUNDS4: - case B_UVAUTO_BOUNDS8: - case B_UVAUTO_SPHERE: - case B_UVAUTO_CYLINDER: - case B_UVAUTO_WINDOW: - if(select_area(SPACE_VIEW3D)) calculate_uv_map(event); - break; - case B_UVAUTO_UNWRAP: - unwrap_lscm(); - break; - } + /* nothing to do here */ } static void editing_panel_mesh_uvautocalculation(void) @@ -3877,9 +3852,8 @@ static void editing_panel_mesh_uvautocalculation(void) row-= 4*butHB+butS; uiBlockBeginAlign(block); - uiDefButS(block, MENU, REDRAWBUTSEDIT, "Unwrapper%t|Conformal%x0|Angle Based%x1|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"); + uiDefButS(block, MENU, REDRAWBUTSEDIT, "Unwrapper%t|Conformal%x0|Angle Based%x1",100,row,200,butH, &G.scene->toolsettings->unwrapper, 0, 0, 0, 0, "Unwrap method"); + 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; diff --git a/source/blender/src/drawimage.c b/source/blender/src/drawimage.c index af34d6ae849..154d12e38f1 100644 --- a/source/blender/src/drawimage.c +++ b/source/blender/src/drawimage.c @@ -205,24 +205,24 @@ void calc_image_view(SpaceImage *sima, char mode) void what_image(SpaceImage *sima) { - extern TFace *lasttface; /* editface.c */ + TFace *activetf; Mesh *me; if(sima->mode==SI_TEXTURE) { if(G.f & G_FACESELECT) { sima->image= 0; - me= get_mesh((G.scene->basact) ? (G.scene->basact->object) : 0); - set_lasttface(); + me= get_mesh(OBACT); + activetf = get_active_tface(); - if(me && me->tface && lasttface && lasttface->mode & TF_TEX) { - sima->image= lasttface->tpage; + if(me && me->tface && activetf && activetf->mode & TF_TEX) { + sima->image= activetf->tpage; if(sima->flag & SI_EDITTILE); - else sima->curtile= lasttface->tile; + else sima->curtile= activetf->tile; if(sima->image) { - if(lasttface->mode & TF_TILES) + if(activetf->mode & TF_TILES) sima->image->tpageflag |= IMA_TILES; else sima->image->tpageflag &= ~IMA_TILES; } diff --git a/source/blender/src/drawmesh.c b/source/blender/src/drawmesh.c index acf81405547..ec69eecd8d0 100644 --- a/source/blender/src/drawmesh.c +++ b/source/blender/src/drawmesh.c @@ -515,7 +515,8 @@ static void get_marked_edge_info__orFlags(EdgeHash *eh, int v0, int v1, int flag flags_p = (int*) BLI_edgehash_lookup_p(eh, v0, v1); *flags_p |= flags; } -static EdgeHash *get_marked_edge_info(Mesh *me) + +EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me) { EdgeHash *eh = BLI_edgehash_new(); int i; @@ -618,20 +619,25 @@ static int draw_tfaces3D__setActiveOpts(void *userData, int index) return 0; } } -static int draw_tfaces3D__drawFaceOpts(TFace *tface, int matnr) +static int draw_tfaces3D__drawFaceOpts(void *userData, int index, int matnr) { - if (tface && !(tface->flag&TF_HIDE) && (tface->flag&TF_SELECT)) { - return 2; /* Don't set color */ - } else { + Mesh *me = (Mesh*)userData; + + if (me->tface) { + TFace *tface = &me->tface[index]; + if (!(tface->flag&TF_HIDE) && (tface->flag&TF_SELECT)) + return 2; /* Don't set color */ + else + return 0; + } else return 0; - } } static void draw_tfaces3D(Object *ob, Mesh *me, DerivedMesh *dm) { struct { Mesh *me; EdgeHash *eh; } data; data.me = me; - data.eh = get_marked_edge_info(me); + data.eh = get_tface_mesh_marked_edge_info(me); glEnable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); @@ -657,7 +663,7 @@ static void draw_tfaces3D(Object *ob, Mesh *me, DerivedMesh *dm) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); BIF_ThemeColor4(TH_FACE_SELECT); - dm->drawFacesTex(dm, draw_tfaces3D__drawFaceOpts); + dm->drawMappedFacesTex(dm, draw_tfaces3D__drawFaceOpts, (void*)me); glDisable(GL_BLEND); } @@ -838,8 +844,11 @@ static Object *g_draw_tface_mesh_ob = NULL; static int g_draw_tface_mesh_islight = 0; static int g_draw_tface_mesh_istex = 0; static unsigned char g_draw_tface_mesh_obcol[4]; -static int draw_tface_mesh__set_draw(TFace *tface, int matnr) +static int draw_tface_mesh__set_draw(void *userData, int index, int matnr) { + Mesh *me = (Mesh*)userData; + TFace *tface = (me->tface)? &me->tface[index]: NULL; + if (tface && ((tface->flag&TF_HIDE) || (tface->mode&TF_INVISIBLE))) return 0; if (set_draw_settings_cached(0, g_draw_tface_mesh_istex, tface, g_draw_tface_mesh_islight, g_draw_tface_mesh_ob, matnr, TF_TWOSIDE)) { @@ -901,7 +910,7 @@ void draw_tface_mesh(Object *ob, Mesh *me, int dt) int editing= (G.f & (G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT)) && (ob==((G.scene->basact) ? (G.scene->basact->object) : 0)); int start, totface; - dm->drawFacesTex(dm, draw_tface_mesh__set_draw); + dm->drawMappedFacesTex(dm, draw_tface_mesh__set_draw, (void*)me); start = 0; totface = me->totface; diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 14e9b46df87..d4e5d102f7c 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -71,6 +71,7 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BLI_editVert.h" +#include "BLI_edgehash.h" #include "BKE_utildefines.h" #include "BKE_curve.h" @@ -4110,17 +4111,47 @@ static int bbs_mesh_solid__setDrawOpts(void *userData, int index, int *drawSmoot return 0; } } + +static int bbs_mesh_wire__setDrawOpts(void *userData, int index) +{ + struct { Mesh *me; EdgeHash *eh; int offset; } *data = userData; + MEdge *med = data->me->medge + index; + unsigned int flags = (int)BLI_edgehash_lookup(data->eh, med->v1, med->v2); + + if (flags & 1) { + set_framebuffer_index_color(data->offset+index); + return 1; + } else + return 0; +} + static void bbs_mesh_solid(Object *ob) { int dmNeedsFree; DerivedMesh *dm = mesh_get_derived_final(ob, &dmNeedsFree); + Mesh *me = (Mesh*)ob->data; glColor3ub(0, 0, 0); - dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, ob->data, 0); - - if (dmNeedsFree) { - dm->release(dm); + dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, me, 0); + + /* draw edges for seam marking in faceselect mode, but not when painting, + so that painting doesn't get interrupted on an edge */ + if ((G.f & G_FACESELECT) && !(G.f & (G_VERTEXPAINT|G_TEXTUREPAINT|G_WEIGHTPAINT))) { + struct { Mesh *me; EdgeHash *eh; int offset; } userData; + + userData.me = me; + userData.eh = get_tface_mesh_marked_edge_info(me); + userData.offset = userData.me->totface+1; + + bglPolygonOffset(1.0); + dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOpts, (void*)&userData); + bglPolygonOffset(0.0); + + BLI_edgehash_free(userData.eh, NULL); } + + if (dmNeedsFree) + dm->release(dm); } void draw_object_backbufsel(Object *ob) @@ -4145,7 +4176,7 @@ void draw_object_backbufsel(Object *ob) // we draw edges always, for loop (select) tools em_wireoffs= bbs_mesh_wire(dm, em_solidoffs); - + if(G.scene->selectmode & SCE_SELECT_VERTEX) em_vertoffs= bbs_mesh_verts(dm, em_wireoffs); else em_vertoffs= em_wireoffs; diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 28001e2918d..26704d4d876 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -49,6 +49,7 @@ #include "BMF_Api.h" #include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" #include "DNA_action_types.h" #include "DNA_armature_types.h" @@ -1054,7 +1055,143 @@ void backdrawview3d(int test) } +void check_backbuf(void) +{ + if(G.vd->flag & V3D_NEEDBACKBUFDRAW) + backdrawview3d(0); +} + +/* samples a single pixel (copied from vpaint) */ +unsigned int sample_backbuf(int x, int y) +{ + unsigned int col; + + if(x>=curarea->winx || y>=curarea->winy) return 0; + x+= curarea->winrct.xmin; + y+= curarea->winrct.ymin; + + check_backbuf(); // actually not needed for apple + +#ifdef __APPLE__ + glReadBuffer(GL_AUX0); +#endif + glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); + glReadBuffer(GL_BACK); + + if(G.order==B_ENDIAN) SWITCH_INT(col); + + return framebuffer_to_index(col); +} + +/* reads full rect, converts indices */ +ImBuf *read_backbuf(short xmin, short ymin, short xmax, short ymax) +{ + unsigned int *dr, *rd; + struct ImBuf *ibuf, *ibuf1; + int a; + short xminc, yminc, xmaxc, ymaxc, xs, ys; + + /* clip */ + if(xmin<0) xminc= 0; else xminc= xmin; + if(xmax>=curarea->winx) xmaxc= curarea->winx-1; else xmaxc= xmax; + if(xminc > xmaxc) return NULL; + + if(ymin<0) yminc= 0; else yminc= ymin; + if(ymax>=curarea->winy) ymaxc= curarea->winy-1; else ymaxc= ymax; + if(yminc > ymaxc) return NULL; + + ibuf= IMB_allocImBuf((xmaxc-xminc+1),(ymaxc-yminc+1),32,IB_rect,0); + + check_backbuf(); // actually not needed for apple + +#ifdef __APPLE__ + glReadBuffer(GL_AUX0); +#endif + glReadPixels(curarea->winrct.xmin+xminc, curarea->winrct.ymin+yminc, (xmaxc-xminc+1), (ymaxc-yminc+1), GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + glReadBuffer(GL_BACK); + + if(G.order==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf); + + a= (xmaxc-xminc+1)*(ymaxc-yminc+1); + dr= ibuf->rect; + while(a--) { + if(*dr) *dr= framebuffer_to_index(*dr); + dr++; + } + + /* put clipped result back, if needed */ + if(xminc==xmin && xmaxc==xmax && yminc==ymin && ymaxc==ymax) return ibuf; + ibuf1= IMB_allocImBuf( (xmax-xmin+1),(ymax-ymin+1),32,IB_rect,0); + rd= ibuf->rect; + dr= ibuf1->rect; + for(ys= ymin; ys<=ymax; ys++) { + for(xs= xmin; xs<=xmax; xs++, dr++) { + if( xs>=xminc && xs<=xmaxc && ys>=yminc && ys<=ymaxc) { + *dr= *rd; + rd++; + } + } + } + IMB_freeImBuf(ibuf); + return ibuf1; +} + +/* smart function to sample a rect spiralling outside, nice for backbuf selection */ +unsigned int sample_backbuf_rect(short mval[2], int size, unsigned int min, unsigned int max, short *dist) +{ + struct ImBuf *buf; + unsigned int *bufmin, *bufmax, *tbuf; + int minx, miny; + int a, b, rc, nr, amount, dirvec[4][2]; + short distance=0; + unsigned int index = 0; + + amount= (size-1)/2; + + minx = mval[0]-(amount+1); + miny = mval[1]-(amount+1); + buf = read_backbuf(minx, miny, minx+size-1, miny+size-1); + if (!buf) return 0; + + rc= 0; + + dirvec[0][0]= 1; dirvec[0][1]= 0; + dirvec[1][0]= 0; dirvec[1][1]= -size; + dirvec[2][0]= -1; dirvec[2][1]= 0; + dirvec[3][0]= 0; dirvec[3][1]= size; + + bufmin = buf->rect; + tbuf = buf->rect; + bufmax = buf->rect + size*size; + tbuf+= amount*size+ amount; + + for(nr=1; nr<=size; nr++) { + + for(a=0; a<2; a++) { + for(b=0; b=min && *tbuf=bufmax) { + goto exit; + } + } + rc++; + rc &= 3; + } + } + +exit: + IMB_freeImBuf(buf); + return index; +} + void drawname(Object *ob) { cpack(0x404040); diff --git a/source/blender/src/editface.c b/source/blender/src/editface.c index d1812bba205..e6b64a276c1 100644 --- a/source/blender/src/editface.c +++ b/source/blender/src/editface.c @@ -38,6 +38,8 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" +#include "BLI_heap.h" +#include "BLI_edgehash.h" #include "MTC_matrixops.h" @@ -91,7 +93,59 @@ #include "BDR_unwrapper.h" -TFace *lasttface=NULL; +/* returns 0 if not found, otherwise 1 */ +static int facesel_face_pick(Mesh *me, short *mval, unsigned int *index, short rect) +{ + if (!me->tface || me->totface==0) + return 0; + + if (G.vd->flag & V3D_NEEDBACKBUFDRAW) { + check_backbuf(); + persp(PERSP_VIEW); + } + + if (rect) { + /* sample rect to increase changes of selecting, so that when clicking + on an edge in the backbuf, we can still select a face */ + short dist; + *index = sample_backbuf_rect(mval, 3, 1, me->totface+1, &dist); + } + else + /* sample only on the exact position */ + *index = sample_backbuf(mval[0], mval[1]); + + if ((*index)<=0 || (*index)>(unsigned int)me->totface) + return 0; + + (*index)--; + + return 1; +} + +/* returns 0 if not found, otherwise 1 */ +static int facesel_edge_pick(Mesh *me, short *mval, unsigned int *index) +{ + short dist; + unsigned int min = me->totface + 1; + unsigned int max = me->totface + me->totedge + 1; + + if (me->totedge == 0) + return 0; + + if (G.vd->flag & V3D_NEEDBACKBUFDRAW) { + check_backbuf(); + persp(PERSP_VIEW); + } + + *index = sample_backbuf_rect(mval, 50, min, max, &dist); + + if (*index == 0) + return 0; + + (*index)--; + + return 1; +} static void uv_calc_center_vector(float *result, Object *ob, Mesh *me) { @@ -487,47 +541,32 @@ void calculate_uv_map(unsigned short mapmode) allqueue(REDRAWIMAGE, 0); } -void set_lasttface() +TFace *get_active_tface() { Mesh *me; - TFace *tface; + TFace *tf; int a; - lasttface= 0; - if(OBACT==NULL || OBACT->type!=OB_MESH) return; + if(OBACT==NULL || OBACT->type!=OB_MESH) + return NULL; me= get_mesh(OBACT); - if(me==0 || me->tface==0) return; + if(me==0 || me->tface==0) + return NULL; - tface= me->tface; - a= me->totface; - while(a--) { - if(tface->flag & TF_ACTIVE) { - lasttface= tface; - return; - } - tface++; - } + for(a=0, tf=me->tface; a < me->totface; a++, tf++) + if(tf->flag & TF_ACTIVE) + return tf; - tface= me->tface; - a= me->totface; - while(a--) { - if(tface->flag & TF_SELECT) { - lasttface= tface; - return; - } - tface++; - } + for(a=0, tf=me->tface; a < me->totface; a++, tf++) + if(tf->flag & TF_SELECT) + return tf; - tface= me->tface; - a= me->totface; - while(a--) { - if((tface->flag & TF_HIDE)==0) { - lasttface= tface; - return; - } - tface++; - } + for(a=0, tf=me->tface; a < me->totface; a++, tf++) + if((tf->flag & TF_HIDE)==0) + return tf; + + return NULL; } void default_uv(float uv[][2], float size) @@ -660,7 +699,7 @@ void select_linked_tfaces(int mode) error("The active object is not in this layer"); getmouseco_areawin(mval); - if (!face_pick(me, mval[0], mval[1], &index)) return; + if (!facesel_face_pick(me, mval, &index, 1)) return; } select_linked_tfaces_with_seams(mode, me, index); @@ -910,55 +949,275 @@ void minmax_tface(float *min, float *max) } } -/** - * Returns the face under the give position in screen coordinates. - * Code extracted from face_select routine. - * Question: why is all of the backbuffer drawn? - * We're only interested in one pixel! - * @author Maarten Gribnau - * @param me the mesh with the faces to be picked - * @param x the x-coordinate to pick at - * @param y the y-coordinate to pick at - * @param index the index of the face - * @return 1 if found, 0 if none found - */ -int face_pick(Mesh *me, short x, short y, unsigned int *index) +#define ME_SEAM_DONE ME_SEAM_LAST /* reuse this flag */ + +static float seam_cut_cost(Mesh *me, int e1, int e2, int vert) { - unsigned int col; + MVert *v = me->mvert + vert; + MEdge *med1 = me->medge + e1, *med2 = me->medge + e2; + MVert *v1 = me->mvert + ((med1->v1 == vert)? med1->v2: med1->v1); + MVert *v2 = me->mvert + ((med2->v1 == vert)? med2->v2: med2->v1); + float cost, d1[3], d2[3]; - if (me==0 || me->tface==0) - return 0; + cost = VecLenf(v1->co, v->co); + cost += VecLenf(v->co, v2->co); - /* Have OpenGL draw in the back buffer with color coded face indices */ - if (curarea->win_swap==WIN_EQUAL) { - G.vd->flag |= V3D_NEEDBACKBUFDRAW; + VecSubf(d1, v->co, v1->co); + VecSubf(d2, v2->co, v->co); + + cost = cost + 0.5f*cost*(2.0f - fabs(d1[0]*d2[0] + d1[1]*d2[1] + d1[2]*d2[2])); + + return cost; +} + +static void seam_add_adjacent(Mesh *me, Heap *heap, int mednum, int vertnum, int *nedges, int *edges, int *prevedge, float *cost) +{ + int startadj, endadj = nedges[vertnum+1]; + + for (startadj = nedges[vertnum]; startadj < endadj; startadj++) { + int adjnum = edges[startadj]; + MEdge *medadj = me->medge + adjnum; + float newcost; + + if (medadj->flag & ME_SEAM_DONE) + continue; + + newcost = cost[mednum] + seam_cut_cost(me, mednum, adjnum, vertnum); + + if (cost[adjnum] > newcost) { + cost[adjnum] = newcost; + prevedge[adjnum] = mednum; + BLI_heap_insert(heap, newcost, (void*)adjnum); + } } - if (G.vd->flag & V3D_NEEDBACKBUFDRAW) { - backdrawview3d(0); - persp(PERSP_VIEW); - } - /* Read the pixel under the cursor */ -#ifdef __APPLE__ - glReadBuffer(GL_AUX0); -#endif - glReadPixels(x+curarea->winrct.xmin, y+curarea->winrct.ymin, 1, 1, - GL_RGBA, GL_UNSIGNED_BYTE, &col); - glReadBuffer(GL_BACK); +} - /* Unbelievable! */ - if (G.order==B_ENDIAN) { - SWITCH_INT(col); - } - /* Convert the color back to a face index */ - *index = framebuffer_to_index(col); - if (col==0 || (*index)<=0 || (*index)>(unsigned) me->totface) - return 0; +static int seam_shortest_path(Mesh *me, int source, int target) +{ + Heap *heap; + EdgeHash *ehash; + float *cost; + MEdge *med; + int a, *nedges, *edges, *prevedge, mednum = -1, nedgeswap = 0; + TFace *tf; + MFace *mf; - (*index)--; + /* mark hidden edges as done, so we don't use them */ + ehash = BLI_edgehash_new(); + + for (a=0, mf=me->mface, tf=me->tface; atotface; a++, tf++, mf++) { + if (!(tf->flag & TF_HIDE)) { + BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL); + BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL); + if (mf->v4) { + BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL); + BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL); + } + else + BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL); + } + } + + for (a=0, med=me->medge; atotedge; a++, med++) + if (!BLI_edgehash_haskey(ehash, med->v1, med->v2)) + med->flag |= ME_SEAM_DONE; + + BLI_edgehash_free(ehash, NULL); + + /* alloc */ + nedges = MEM_callocN(sizeof(*nedges)*me->totvert+1, "SeamPathNEdges"); + edges = MEM_mallocN(sizeof(*edges)*me->totedge*2, "SeamPathEdges"); + prevedge = MEM_mallocN(sizeof(*prevedge)*me->totedge, "SeamPathPrevious"); + cost = MEM_mallocN(sizeof(*cost)*me->totedge, "SeamPathCost"); + + /* count edges, compute adjacent edges offsets and fill adjacent edges */ + for (a=0, med=me->medge; atotedge; a++, med++) { + nedges[med->v1+1]++; + nedges[med->v2+1]++; + } + + for (a=1; atotvert; a++) { + int newswap = nedges[a+1]; + nedges[a+1] = nedgeswap + nedges[a]; + nedgeswap = newswap; + } + nedges[0] = nedges[1] = 0; + + for (a=0, med=me->medge; atotedge; a++, med++) { + edges[nedges[med->v1+1]++] = a; + edges[nedges[med->v2+1]++] = a; + + cost[a] = 1e20f; + prevedge[a] = -1; + } + + /* regular dijkstra shortest path, but over edges instead of vertices */ + heap = BLI_heap_new(); + BLI_heap_insert(heap, 0.0f, (void*)source); + cost[source] = 0.0f; + + while (!BLI_heap_empty(heap)) { + mednum = (int)BLI_heap_popmin(heap); + med = me->medge + mednum; + + if (mednum == target) + break; + + if (med->flag & ME_SEAM_DONE) + continue; + + med->flag |= ME_SEAM_DONE; + + seam_add_adjacent(me, heap, mednum, med->v1, nedges, edges, prevedge, cost); + seam_add_adjacent(me, heap, mednum, med->v2, nedges, edges, prevedge, cost); + } + MEM_freeN(nedges); + MEM_freeN(edges); + MEM_freeN(cost); + BLI_heap_free(heap, NULL); + + for (a=0, med=me->medge; atotedge; a++, med++) + med->flag &= ~ME_SEAM_DONE; + + if (mednum != target) { + MEM_freeN(prevedge); + return 0; + } + + /* follow path back to source and mark as seam */ + if (mednum == target) { + short allseams = 1; + + mednum = target; + do { + med = me->medge + mednum; + if (!(med->flag & ME_SEAM)) { + allseams = 0; + break; + } + mednum = prevedge[mednum]; + } while (mednum != source); + + mednum = target; + do { + med = me->medge + mednum; + if (allseams) + med->flag &= ~ME_SEAM; + else + med->flag |= ME_SEAM; + mednum = prevedge[mednum]; + } while (mednum != -1); + } + + MEM_freeN(prevedge); return 1; } +static void seam_select(Mesh *me, short *mval, short path) +{ + unsigned int index = 0; + MEdge *medge, *med; + int a, lastindex = -1; + + if (!facesel_edge_pick(me, mval, &index)) + return; + + for (a=0, med=me->medge; atotedge; a++, med++) { + if (med->flag & ME_SEAM_LAST) { + lastindex = a; + med->flag &= ~ME_SEAM_LAST; + break; + } + } + + medge = me->medge + index; + if (!path || (lastindex == -1) || (index == lastindex) || + !seam_shortest_path(me, lastindex, index)) + medge->flag ^= ME_SEAM; + medge->flag |= ME_SEAM_LAST; + + G.f |= G_DRAWSEAMS; + + if (G.rt == 8) + unwrap_lscm(1); + + BIF_undo_push("Mark Seam"); + + object_tface_flags_changed(OBACT, 1); +} + +void seam_edgehash_insert_face(EdgeHash *ehash, MFace *mf) +{ + BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL); + BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL); + if (mf->v4) { + BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL); + BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL); + } + else + BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL); +} + +void seam_mark_clear_tface(short mode) +{ + Mesh *me; + TFace *tf; + MFace *mf; + MEdge *med; + int a; + + me= get_mesh(OBACT); + if(me==0 || me->tface==0 || me->totface==0) return; + + if (mode == 0) + mode = pupmenu("Seams%t|Mark Border Seam %x1|Clear Seam %x2"); + + if (mode != 1 && mode != 2) + return; + + if (mode == 2) { + EdgeHash *ehash = BLI_edgehash_new(); + + for (a=0, mf=me->mface, tf=me->tface; atotface; a++, tf++, mf++) + if (!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT)) + seam_edgehash_insert_face(ehash, mf); + + for (a=0, med=me->medge; atotedge; a++, med++) + if (BLI_edgehash_haskey(ehash, med->v1, med->v2)) + med->flag &= ~ME_SEAM; + + BLI_edgehash_free(ehash, NULL); + } + else { + /* mark edges that are on both selected and deselected faces */ + EdgeHash *ehash1 = BLI_edgehash_new(); + EdgeHash *ehash2 = BLI_edgehash_new(); + + for (a=0, mf=me->mface, tf=me->tface; atotface; a++, tf++, mf++) { + if ((tf->flag & TF_HIDE) || !(tf->flag & TF_SELECT)) + seam_edgehash_insert_face(ehash1, mf); + else + seam_edgehash_insert_face(ehash2, mf); + } + + for (a=0, med=me->medge; atotedge; a++, med++) + if (BLI_edgehash_haskey(ehash1, med->v1, med->v2) && + BLI_edgehash_haskey(ehash2, med->v1, med->v2)) + med->flag |= ME_SEAM; + + BLI_edgehash_free(ehash1, NULL); + BLI_edgehash_free(ehash2, NULL); + } + + if (G.rt == 8) + unwrap_lscm(1); + + BIF_undo_push("Mark Seam"); + + object_tface_flags_changed(OBACT, 1); +} + void face_select() { Object *ob; @@ -975,7 +1234,13 @@ void face_select() } me = get_mesh(ob); getmouseco_areawin(mval); - if (!face_pick(me, mval[0], mval[1], &index)) return; + + if (G.qual & LR_ALTKEY) { + seam_select(me, mval, (G.qual & LR_SHIFTKEY) != 0); + return; + } + + if (!facesel_face_pick(me, mval, &index, 1)) return; tsel= (((TFace*)me->tface)+index); msel= (((MFace*)me->mface)+index); @@ -1003,8 +1268,6 @@ void face_select() } else tsel->flag |= TF_SELECT; - lasttface = tsel; - /* image window redraw */ BIF_undo_push("Select UV face"); @@ -1149,7 +1412,7 @@ void uv_autocalc_tface() case UV_WINDOW_MAPPING: calculate_uv_map(B_UVAUTO_WINDOW); break; case UV_UNWRAP_MAPPING: - unwrap_lscm(); break; + unwrap_lscm(0); break; } } @@ -1176,10 +1439,6 @@ void set_faceselect() /* toggle */ if(G.f & G_FACESELECT) { setcursor_space(SPACE_VIEW3D, CURSOR_FACESEL); - if(me) { - set_lasttface(); - set_seamtface(); /* set TF_SEAM flags in tface */ - } BIF_undo_push("Set UV Faceselect"); } else if((G.f & (G_WEIGHTPAINT|G_VERTEXPAINT|G_TEXTUREPAINT))==0) { @@ -1497,7 +1756,7 @@ void face_draw() if ((xy[0] != xy_old[0]) || (xy[1] != xy_old[1])) { /* Get face to draw on */ - if (!face_pick(me, xy[0], xy[1], &face_index)) face = NULL; + if (!facesel_face_pick(me, xy, &face_index, 0)) face = NULL; else face = (((TFace*)me->tface)+face_index); /* Check if this is another face. */ diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index 8c8315f23fa..aa3353046a8 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -123,145 +123,6 @@ void EM_select_mirrored(void) unsigned int em_solidoffs=0, em_wireoffs=0, em_vertoffs=0; // set in drawobject.c ... for colorindices -static void check_backbuf(void) -{ - if(G.vd->flag & V3D_NEEDBACKBUFDRAW) { - backdrawview3d(0); - } -} - -/* samples a single pixel (copied from vpaint) */ -static unsigned int sample_backbuf(int x, int y) -{ - unsigned int col; - - if(x>=curarea->winx || y>=curarea->winy) return 0; - x+= curarea->winrct.xmin; - y+= curarea->winrct.ymin; - - check_backbuf(); // actually not needed for apple - -#ifdef __APPLE__ - glReadBuffer(GL_AUX0); -#endif - glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); - glReadBuffer(GL_BACK); - - if(G.order==B_ENDIAN) SWITCH_INT(col); - - return framebuffer_to_index(col); -} - -/* reads full rect, converts indices */ -struct ImBuf *read_backbuf(short xmin, short ymin, short xmax, short ymax) -{ - unsigned int *dr, *rd; - struct ImBuf *ibuf, *ibuf1; - int a; - short xminc, yminc, xmaxc, ymaxc, xs, ys; - - /* clip */ - if(xmin<0) xminc= 0; else xminc= xmin; - if(xmax>=curarea->winx) xmaxc= curarea->winx-1; else xmaxc= xmax; - if(xminc > xmaxc) return NULL; - - if(ymin<0) yminc= 0; else yminc= ymin; - if(ymax>=curarea->winy) ymaxc= curarea->winy-1; else ymaxc= ymax; - if(yminc > ymaxc) return NULL; - - ibuf= IMB_allocImBuf((xmaxc-xminc+1),(ymaxc-yminc+1),32,IB_rect,0); - - check_backbuf(); // actually not needed for apple - -#ifdef __APPLE__ - glReadBuffer(GL_AUX0); -#endif - glReadPixels(curarea->winrct.xmin+xminc, curarea->winrct.ymin+yminc, (xmaxc-xminc+1), (ymaxc-yminc+1), GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); - glReadBuffer(GL_BACK); - - if(G.order==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf); - - a= (xmaxc-xminc+1)*(ymaxc-yminc+1); - dr= ibuf->rect; - while(a--) { - if(*dr) *dr= framebuffer_to_index(*dr); - dr++; - } - - /* put clipped result back, if needed */ - if(xminc==xmin && xmaxc==xmax && yminc==ymin && ymaxc==ymax) return ibuf; - ibuf1= IMB_allocImBuf( (xmax-xmin+1),(ymax-ymin+1),32,IB_rect,0); - rd= ibuf->rect; - dr= ibuf1->rect; - - for(ys= ymin; ys<=ymax; ys++) { - for(xs= xmin; xs<=xmax; xs++, dr++) { - if( xs>=xminc && xs<=xmaxc && ys>=yminc && ys<=ymaxc) { - *dr= *rd; - rd++; - } - } - } - IMB_freeImBuf(ibuf); - return ibuf1; -} - - -/* smart function to sample a rect spiralling outside, nice for backbuf selection */ -static unsigned int sample_backbuf_rect(short mval[2], int size, unsigned int min, unsigned int max, short *dist) -{ - struct ImBuf *buf; - unsigned int *bufmin, *bufmax, *tbuf; - int minx, miny; - int a, b, rc, nr, amount, dirvec[4][2]; - short distance=0; - unsigned int index = 0; - - amount= (size-1)/2; - - minx = mval[0]-(amount+1); - miny = mval[1]-(amount+1); - buf = read_backbuf(minx, miny, minx+size-1, miny+size-1); - if (!buf) return 0; - - rc= 0; - - dirvec[0][0]= 1; dirvec[0][1]= 0; - dirvec[1][0]= 0; dirvec[1][1]= -size; - dirvec[2][0]= -1; dirvec[2][1]= 0; - dirvec[3][0]= 0; dirvec[3][1]= size; - - bufmin = buf->rect; - tbuf = buf->rect; - bufmax = buf->rect + size*size; - tbuf+= amount*size+ amount; - - for(nr=1; nr<=size; nr++) { - - for(a=0; a<2; a++) { - for(b=0; b=min && *tbuf=bufmax) { - goto exit; - } - } - rc++; - rc &= 3; - } - } - -exit: - IMB_freeImBuf(buf); - return index; -} - /* facilities for border select and circle select */ static char *selbuf= NULL; diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 40a83d03a94..a54ac6106fe 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -1504,10 +1504,8 @@ void exit_editmode(int freedata) /* freedata==0 at render, 1= freedata, 2= do un if(freedata) free_editMesh(G.editMesh); - if(G.f & G_FACESELECT) { - set_seamtface(); + if(G.f & G_FACESELECT) allqueue(REDRAWIMAGE, 0); - } if(G.f & G_WEIGHTPAINT) mesh_octree_table(G.obedit, NULL, 'e'); } diff --git a/source/blender/src/header_image.c b/source/blender/src/header_image.c index 998839844c5..61456fb0c38 100644 --- a/source/blender/src/header_image.c +++ b/source/blender/src/header_image.c @@ -1029,7 +1029,7 @@ static void do_image_uvsmenu(void *arg, int event) pin_tface_uv(0); break; case 10: - unwrap_lscm(); + unwrap_lscm(0); break; case 11: if(G.sima->flag & SI_LIVE_UNWRAP) G.sima->flag &= ~SI_LIVE_UNWRAP; @@ -1072,7 +1072,7 @@ static uiBlock *image_uvsmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Minimize Stretch|Ctrl V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Minimize Stretch|Ctrl V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 12, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Limit Stitch...|Shift V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Stitch|V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, ""); uiDefIconTextBlockBut(block, image_uvs_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, ""); diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index e8598bd265f..6ffd2bd68a1 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -3574,55 +3574,56 @@ static uiBlock *view3d_paintmenu(void *arg_unused) static void do_view3d_facesel_propertiesmenu(void *arg, int event) { - extern TFace *lasttface; - set_lasttface(); - - switch(event) { - case 0: /* textured */ - lasttface->mode ^= TF_TEX; - break; - case 1: /* tiled*/ - lasttface->mode ^= TF_TILES; - break; - case 2: /* light */ - lasttface->mode ^= TF_LIGHT; - break; - case 3: /* invisible */ - lasttface->mode ^= TF_INVISIBLE; - break; - case 4: /* collision */ - lasttface->mode ^= TF_DYNAMIC; - break; - case 5: /* shared vertex colors */ - lasttface->mode ^= TF_SHAREDCOL; - break; - case 6: /* two sided */ - lasttface->mode ^= TF_TWOSIDE; - break; - case 7: /* use object color */ - lasttface->mode ^= TF_OBCOL; - break; - case 8: /* halo */ - lasttface->mode ^= TF_BILLBOARD; - break; - case 9: /* billboard */ - lasttface->mode ^= TF_BILLBOARD2; - break; - case 10: /* shadow */ - lasttface->mode ^= TF_SHADOW; - break; - case 11: /* text */ - lasttface->mode ^= TF_BMFONT; - break; - case 12: /* opaque blend mode */ - lasttface->transp = TF_SOLID; - break; - case 13: /* additive blend mode */ - lasttface->transp |= TF_ADD; - break; - case 14: /* alpha blend mode */ - lasttface->transp = TF_ALPHA; - break; + TFace *tf = get_active_tface(); + + if (tf) { + switch(event) { + case 0: /* textured */ + tf->mode ^= TF_TEX; + break; + case 1: /* tiled*/ + tf->mode ^= TF_TILES; + break; + case 2: /* light */ + tf->mode ^= TF_LIGHT; + break; + case 3: /* invisible */ + tf->mode ^= TF_INVISIBLE; + break; + case 4: /* collision */ + tf->mode ^= TF_DYNAMIC; + break; + case 5: /* shared vertex colors */ + tf->mode ^= TF_SHAREDCOL; + break; + case 6: /* two sided */ + tf->mode ^= TF_TWOSIDE; + break; + case 7: /* use object color */ + tf->mode ^= TF_OBCOL; + break; + case 8: /* halo */ + tf->mode ^= TF_BILLBOARD; + break; + case 9: /* billboard */ + tf->mode ^= TF_BILLBOARD2; + break; + case 10: /* shadow */ + tf->mode ^= TF_SHADOW; + break; + case 11: /* text */ + tf->mode ^= TF_BMFONT; + break; + case 12: /* opaque blend mode */ + tf->transp = TF_SOLID; + break; + case 13: /* additive blend mode */ + tf->transp |= TF_ADD; + break; + case 14: /* alpha blend mode */ + tf->transp = TF_ALPHA; + break; + } } allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSEDIT, 0); @@ -3630,61 +3631,60 @@ static void do_view3d_facesel_propertiesmenu(void *arg, int event) static uiBlock *view3d_facesel_propertiesmenu(void *arg_unused) { - extern TFace *lasttface; + TFace *tf = get_active_tface(); uiBlock *block; short yco = 20, menuwidth = 120; - /* to display ticks/crosses depending on face properties */ - set_lasttface(); + /* display ticks/crosses depending on active tface properties */ block= uiNewBlock(&curarea->uiblocks, "view3d_facesel_propertiesmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); uiBlockSetButmFunc(block, do_view3d_facesel_propertiesmenu, NULL); - if (lasttface->mode & TF_TEX) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Textured", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, ""); + if (tf->mode & TF_TEX) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Textured", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Textured", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, ""); - if (lasttface->mode & TF_TILES) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Tiled", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, ""); + if (tf->mode & TF_TILES) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Tiled", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Tiled", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, ""); - if (lasttface->mode & TF_LIGHT) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Light", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, ""); + if (tf->mode & TF_LIGHT) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Light", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Light", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, ""); - if (lasttface->mode & TF_INVISIBLE) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Invisible", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, ""); + if (tf->mode & TF_INVISIBLE) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Invisible", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Invisible", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, ""); - if (lasttface->mode & TF_DYNAMIC) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Collision", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, ""); + if (tf->mode & TF_DYNAMIC) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Collision", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Collision", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, ""); - if (lasttface->mode & TF_SHAREDCOL) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Shared Vertex Colors", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, ""); + if (tf->mode & TF_SHAREDCOL) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Shared Vertex Colors", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Shared Vertex Colors", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, ""); - if (lasttface->mode & TF_TWOSIDE) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Two Sided", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, ""); + if (tf->mode & TF_TWOSIDE) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Two Sided", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Two Sided", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, ""); - if (lasttface->mode & TF_OBCOL) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Use Object Color", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); + if (tf->mode & TF_OBCOL) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Use Object Color", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Use Object Color", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); - if (lasttface->mode & TF_BILLBOARD) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Halo", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); + if (tf->mode & TF_BILLBOARD) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Halo", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Halo", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); - if (lasttface->mode & TF_BILLBOARD2) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Billboard", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, ""); + if (tf->mode & TF_BILLBOARD2) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Billboard", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Billboard", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, ""); - if (lasttface->mode & TF_SHADOW) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Shadow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 10, ""); + if (tf->mode & TF_SHADOW) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Shadow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 10, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Shadow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 10, ""); - if (lasttface->mode & TF_BMFONT) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Text", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, ""); + if (tf->mode & TF_BMFONT) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Text", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Text", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - if (lasttface->transp == TF_SOLID) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Opaque Blend Mode", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 12, ""); + if (tf->transp == TF_SOLID) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Opaque Blend Mode", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 12, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Opaque Blend Mode", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 12, ""); - if (lasttface->transp == TF_ADD) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Additive Blend Mode", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 13, ""); + if (tf->transp == TF_ADD) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Additive Blend Mode", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 13, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Additive Blend Mode", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 13, ""); - if (lasttface->transp == TF_ALPHA) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Alpha Blend Mode", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 14, ""); + if (tf->transp == TF_ALPHA) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Alpha Blend Mode", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 14, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Alpha Blend Mode", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 14, ""); uiBlockSetDirection(block, UI_RIGHT); @@ -3731,44 +3731,36 @@ static void do_view3d_faceselmenu(void *arg, int event) { /* code copied from buttons.c :( would be nice if it was split up into functions */ - Mesh *me=NULL; - Object *ob=NULL; - extern TFace *lasttface; /* caches info on tface bookkeeping ?*/ - TFace *tface; + Mesh *me; + TFace *tf, *activetf; int a; switch(event) { case 0: /* copy draw mode */ case 1: /* copy UVs */ case 2: /* copy vertex colors */ - ob= OBACT; - if(ob==0) return; - me= get_mesh(ob); - if(!(me && me->tface)) return; + me= get_mesh(OBACT); + activetf = get_active_tface(); - tface= me->tface; - a= me->totface; - set_lasttface(); - if(lasttface) { - - while(a--) { - if(tface!=lasttface && (tface->flag & TF_SELECT)) { + if (me && activetf) { + for (a=0, tf=me->tface; a < me->totface; a++, tf++) { + if(tf!=activetf && (tf->flag & TF_SELECT)) { if(event==0) { - tface->mode= lasttface->mode; - tface->transp= lasttface->transp; + tf->mode= activetf->mode; + tf->transp= activetf->transp; } else if(event==1) { - memcpy(tface->uv, lasttface->uv, sizeof(tface->uv)); - tface->tpage= lasttface->tpage; - tface->tile= lasttface->tile; + memcpy(tf->uv, activetf->uv, sizeof(tf->uv)); + tf->tpage= activetf->tpage; + tf->tile= activetf->tile; - if(lasttface->mode & TF_TILES) tface->mode |= TF_TILES; - else tface->mode &= ~TF_TILES; + if(activetf->mode & TF_TILES) tf->mode |= TF_TILES; + else tf->mode &= ~TF_TILES; } else if(event==2) - memcpy(tface->col, lasttface->col, sizeof(tface->col)); + memcpy(tf->col, activetf->col, sizeof(tf->col)); } - tface++; } + do_shared_vertexcol(me); } break; @@ -3784,7 +3776,12 @@ static void do_view3d_faceselmenu(void *arg, int event) case 9: /* mirror UVs */ mirror_uv_tface(); break; - + case 10: /* mark border seam */ + seam_mark_clear_tface(1); + break; + case 11: /* clear seam */ + seam_mark_clear_tface(2); + break; } allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWIMAGE, 0); @@ -3795,8 +3792,6 @@ static uiBlock *view3d_faceselmenu(void *arg_unused) uiBlock *block; short yco= 0, menuwidth=120; - set_lasttface(); - block= uiNewBlock(&curarea->uiblocks, "view3d_faceselmenu", UI_EMBOSSP, UI_HELV, curarea->headwin); uiBlockSetButmFunc(block, do_view3d_faceselmenu, NULL); @@ -3817,6 +3812,11 @@ static uiBlock *view3d_faceselmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Seam|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Mark Border Seam|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBlockBut(block, view3d_facesel_showhidemenu, NULL, ICON_RIGHTARROW_THIN, "Show/Hide Faces", 0, yco-=20, 120, 19, ""); if(curarea->headertype==HEADERTOP) { diff --git a/source/blender/src/parametrizer.c b/source/blender/src/parametrizer.c index 5f5c9c39f3b..043ece74523 100644 --- a/source/blender/src/parametrizer.c +++ b/source/blender/src/parametrizer.c @@ -4,6 +4,7 @@ #include "BLI_memarena.h" #include "BLI_arithb.h" #include "BLI_rand.h" +#include "BLI_heap.h" #include "BKE_utildefines.h" @@ -129,148 +130,6 @@ static PHashLink *phash_next(PHash *ph, PHashKey key, PHashLink *link) return link; } -/* Heap */ - -#define PHEAP_PARENT(i) ((i-1)>>1) -#define PHEAP_LEFT(i) ((i<<1)+1) -#define PHEAP_RIGHT(i) ((i<<1)+2) -#define PHEAP_COMPARE(a, b) (a->value < b->value) -#define PHEAP_EQUALS(a, b) (a->value == b->value) -#define PHEAP_SWAP(heap, i, j) \ - { SWAP(int, heap->tree[i]->index, heap->tree[j]->index); \ - SWAP(PHeapLink*, heap->tree[i], heap->tree[j]); } - -static void pheap_down(PHeap *heap, int i) -{ - while (P_TRUE) { - int size = heap->size, smallest; - int l = PHEAP_LEFT(i); - int r = PHEAP_RIGHT(i); - - smallest = ((l < size) && PHEAP_COMPARE(heap->tree[l], heap->tree[i]))? l: i; - - if ((r < size) && PHEAP_COMPARE(heap->tree[r], heap->tree[smallest])) - smallest = r; - - if (smallest == i) - break; - - PHEAP_SWAP(heap, i, smallest); - i = smallest; - } -} - -static void pheap_up(PHeap *heap, int i) -{ - while (i > 0) { - int p = PHEAP_PARENT(i); - - if (PHEAP_COMPARE(heap->tree[p], heap->tree[i])) - break; - - PHEAP_SWAP(heap, p, i); - i = p; - } -} - -static PHeap *pheap_new() -{ - PHeap *heap = (PHeap*)MEM_callocN(sizeof(PHeap), "PHeap"); - heap->bufsize = 1; - heap->tree = (PHeapLink**)MEM_mallocN(sizeof(PHeapLink*), "PHeapTree"); - heap->arena = BLI_memarena_new(1<<16); - - return heap; -} - -static void pheap_delete(PHeap *heap) -{ - MEM_freeN(heap->tree); - BLI_memarena_free(heap->arena); - MEM_freeN(heap); -} - -static PHeapLink *pheap_insert(PHeap *heap, float value, void *ptr) -{ - PHeapLink *link; - - if ((heap->size + 1) > heap->bufsize) { - int newsize = heap->bufsize*2; - - PHeapLink **ntree = (PHeapLink**)MEM_mallocN(newsize*sizeof(PHeapLink*), "PHeapTree"); - memcpy(ntree, heap->tree, sizeof(PHeapLink*)*heap->size); - MEM_freeN(heap->tree); - - heap->tree = ntree; - heap->bufsize = newsize; - } - - param_assert(heap->size < heap->bufsize); - - if (heap->freelinks) { - link = heap->freelinks; - heap->freelinks = (PHeapLink*)(((PHeapLink*)heap->freelinks)->ptr); - } - else - link = (PHeapLink*)BLI_memarena_alloc(heap->arena, sizeof *link); - link->value = value; - link->ptr = ptr; - link->index = heap->size; - - heap->tree[link->index] = link; - - heap->size++; - - pheap_up(heap, heap->size-1); - - return link; -} - -#if 0 -static int pheap_empty(PHeap *heap) -{ - return (heap->size == 0); -} - -static PHeapLink *pheap_toplink(PHeap *heap) -{ - return heap->tree[0]; -} -#endif - -static void *pheap_popmin(PHeap *heap) -{ - void *ptr = heap->tree[0]->ptr; - - heap->tree[0]->ptr = heap->freelinks; - heap->freelinks = heap->tree[0]; - - if (heap->size == 1) - heap->size--; - else { - PHEAP_SWAP(heap, 0, heap->size-1); - heap->size--; - - pheap_down(heap, 0); - } - - return ptr; -} - -static void pheap_remove(PHeap *heap, PHeapLink *link) -{ - int i = link->index; - - while (i > 0) { - int p = PHEAP_PARENT(i); - - PHEAP_SWAP(heap, p, i); - i = p; - } - - pheap_popmin(heap); -} - /* Geometry */ static float p_vec_angle_cos(float *v1, float *v2, float *v3) @@ -1110,13 +969,13 @@ static void p_chart_fill_boundary(PChart *chart, PEdge *be, int nedges) PEdge *e, *e1, *e2; PHashKey vkeys[3]; PFace *f; - struct PHeap *heap = pheap_new(nedges); + struct Heap *heap = BLI_heap_new(); float angle; e = be; do { angle = p_edge_boundary_angle(e); - e->u.heaplink = pheap_insert(heap, angle, e); + e->u.heaplink = BLI_heap_insert(heap, angle, e); e = p_boundary_edge_next(e); } while(e != be); @@ -1127,20 +986,20 @@ static void p_chart_fill_boundary(PChart *chart, PEdge *be, int nedges) e->pair = be; be->pair = e; - pheap_remove(heap, e->u.heaplink); - pheap_remove(heap, be->u.heaplink); + BLI_heap_remove(heap, e->u.heaplink); + BLI_heap_remove(heap, be->u.heaplink); } else { while (nedges > 2) { PEdge *ne, *ne1, *ne2; - e = (PEdge*)pheap_popmin(heap); + e = (PEdge*)BLI_heap_popmin(heap); e1 = p_boundary_edge_prev(e); e2 = p_boundary_edge_next(e); - pheap_remove(heap, e1->u.heaplink); - pheap_remove(heap, e2->u.heaplink); + BLI_heap_remove(heap, e1->u.heaplink); + BLI_heap_remove(heap, e2->u.heaplink); e->u.heaplink = e1->u.heaplink = e2->u.heaplink = NULL; e->flag |= PEDGE_FILLED; @@ -1175,15 +1034,15 @@ static void p_chart_fill_boundary(PChart *chart, PEdge *be, int nedges) else { ne2->vert->edge = ne2; - ne2->u.heaplink = pheap_insert(heap, p_edge_boundary_angle(ne2), ne2); - e2->u.heaplink = pheap_insert(heap, p_edge_boundary_angle(e2), e2); + ne2->u.heaplink = BLI_heap_insert(heap, p_edge_boundary_angle(ne2), ne2); + e2->u.heaplink = BLI_heap_insert(heap, p_edge_boundary_angle(e2), e2); } nedges--; } } - pheap_delete(heap); + BLI_heap_free(heap, NULL); } static void p_chart_fill_boundaries(PChart *chart, PEdge *outer) @@ -2008,7 +1867,7 @@ static void p_chart_simplify_compute(PChart *chart) collapsed may then be view as stacks, where the next collapse/split is at the top of the respective lists. */ - PHeap *heap = pheap_new(); + Heap *heap = BLI_heap_new(); PVert *v, **wheelverts; PEdge *collapsededges = NULL, *e; int nwheelverts, i, ncollapsed = 0; @@ -2023,7 +1882,7 @@ static void p_chart_simplify_compute(PChart *chart) p_collapse_cost_vertex(v, &cost, &e); if (e) - v->u.heaplink = pheap_insert(heap, cost, e); + v->u.heaplink = BLI_heap_insert(heap, cost, e); else v->u.heaplink = NULL; } @@ -2032,12 +1891,12 @@ static void p_chart_simplify_compute(PChart *chart) e->u.nextcollapse = NULL; /* pop edge collapse out of heap one by one */ - while (!pheap_empty(heap)) { + while (!BLI_heap_empty(heap)) { if (ncollapsed == NCOLLAPSE) break; - PHeapLink *link = pheap_toplink(heap); - PEdge *edge = (PEdge*)pheap_popmin(heap), *pair = edge->pair; + HeapNode *link = BLI_heap_top(heap); + PEdge *edge = (PEdge*)BLI_heap_popmin(heap), *pair = edge->pair; PVert *oldv, *keepv; PEdge *wheele, *nexte; @@ -2081,21 +1940,21 @@ static void p_chart_simplify_compute(PChart *chart) v = wheelverts[i]; if (v->u.heaplink) { - pheap_remove(heap, v->u.heaplink); + BLI_heap_remove(heap, v->u.heaplink); v->u.heaplink = NULL; } p_collapse_cost_vertex(v, &cost, &collapse); if (collapse) - v->u.heaplink = pheap_insert(heap, cost, collapse); + v->u.heaplink = BLI_heap_insert(heap, cost, collapse); } ncollapsed++; } MEM_freeN(wheelverts); - pheap_delete(heap); + BLI_heap_free(heap, NULL); p_chart_post_collapse_flush(chart, collapsededges); } diff --git a/source/blender/src/parametrizer_intern.h b/source/blender/src/parametrizer_intern.h index 1e3e7072c48..f5eeed656b8 100644 --- a/source/blender/src/parametrizer_intern.h +++ b/source/blender/src/parametrizer_intern.h @@ -51,23 +51,6 @@ struct PFace; struct PChart; struct PHandle; -/* Heap */ - -typedef struct PHeapLink { - void *ptr; - float value; - int index; -} PHeapLink; - -typedef struct PHeap { - unsigned int size; - unsigned int bufsize; - MemArena *arena; - PHeapLink *freelinks; - PHeapLink *links; - PHeapLink **tree; -} PHeap; - /* Simplices */ typedef struct PVert { @@ -77,7 +60,7 @@ typedef struct PVert { PHashKey key; /* construct */ int id; /* abf/lscm matrix index */ float distortion; /* area smoothing */ - PHeapLink *heaplink; /* edge collapsing */ + HeapNode *heaplink; /* edge collapsing */ } u; struct PEdge *edge; @@ -93,7 +76,7 @@ typedef struct PEdge { union PEdgeUnion { PHashKey key; /* construct */ int id; /* abf matrix index */ - PHeapLink *heaplink; /* fill holes */ + HeapNode *heaplink; /* fill holes */ struct PEdge *nextcollapse; /* simplification */ } u; diff --git a/source/blender/src/space.c b/source/blender/src/space.c index d005e1473a1..5319969e9ab 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1265,6 +1265,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if (G.qual==LR_CTRLKEY) { if(G.obedit && G.obedit->type==OB_MESH) Edge_Menu(); + else if (G.f & G_FACESELECT) + seam_mark_clear_tface(0); } else if (G.qual==LR_SHIFTKEY) { if (G.obedit && G.obedit->type==OB_MESH) { @@ -3992,7 +3994,7 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case EKEY : if(okee("Unwrap")) - unwrap_lscm(); + unwrap_lscm(0); break; case GKEY: if((G.qual==0) && is_uv_tface_editing_allowed()) { diff --git a/source/blender/src/unwrapper.c b/source/blender/src/unwrapper.c index a3ade13126f..fdf68b61a5a 100644 --- a/source/blender/src/unwrapper.c +++ b/source/blender/src/unwrapper.c @@ -60,49 +60,13 @@ #include "blendef.h" #include "mydevice.h" -#include "ONL_opennl.h" #include "BDR_unwrapper.h" #include "PIL_time.h" #include "parametrizer.h" -/* Implementation Least Squares Conformal Maps parameterization, based on - * chapter 2 of: - * Bruno Levy, Sylvain Petitjean, Nicolas Ray, Jerome Maillot. Least Squares - * Conformal Maps for Automatic Texture Atlas Generation. In Siggraph 2002, - * July 2002. - */ - -/* Data structure defines */ -#define LSCM_SEAM1 1 -#define LSCM_SEAM2 2 -#define LSCM_INDEXED 4 -#define LSCM_PINNED 8 - -/* LscmVert = One UV */ -typedef struct LscmVert { - int v, v1, v2; /* vertex indices */ - int index; /* index in solver */ - short tf_index; /* index in tface (0, 1, 2 or 3) */ - short flag; /* see above LSCM constants */ - TFace *tf; /* original tface */ -} LscmVert; - -/* QuickSort helper function, sort by vertex id */ -static int comp_lscmvert(const void *u1, const void *u2) -{ - LscmVert *v1, *v2; - - v1= *((LscmVert**)u1); - v2= *((LscmVert**)u2); - - if (v1->v > v2->v) return 1; - else if (v1->v < v2->v) return -1; - return 0; -} - -/* Hashed edge table utility */ +/* Set tface seams based on edge data, uses hash table to find seam edges. */ static void hash_add_face(EdgeHash *ehash, MFace *mf) { @@ -116,1149 +80,23 @@ static void hash_add_face(EdgeHash *ehash, MFace *mf) BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL); } -/* divide selected faces in groups, based on seams. note that group numbering - starts at 1 */ -static int make_seam_groups(Mesh *me, int **seamgroups) -{ - int a, b, gid; - TFace *tf, *tface; - MFace *mf, *mface; - int *gf, *gface, *groups; - EdgeHash *ehash; - int doit, mark; - - if(!me || !me->tface) return 0; - - groups= (int*)MEM_callocN(sizeof(int)*me->totface, "SeamGroups"); - - ehash= BLI_edgehash_new(); - - mface= (MFace*)me->mface; - tface= (TFace*)me->tface; - gface= groups; - gid= 0; - for(b=me->totface; b>0; b--, mface++, tface++, gface++) { - if(!(tface->flag & TF_SELECT) || *gface!=0) continue; - - if(gid != 0) - BLI_edgehash_clear(ehash, NULL); - - gid++; - *gface= gid; - mark= 0; - doit= 1; - - - while(doit) { - doit= 0; - - /* select connected: fill array */ - tf= tface; - mf= mface; - gf= gface; - a= b; - while(a--) { - if(tf->flag & TF_HIDE); - else if(tf->flag & TF_SELECT && *gf==gid) { - hash_add_face(ehash, mf); - } - tf++; mf++; gf++; - } - - /* select the faces using array - * consider faces connected when they share one non-seam edge */ - tf= tface; - mf= mface; - gf= gface; - a= b; - while(a--) { - if(tf->flag & TF_HIDE); - else if(tf->flag & TF_SELECT && *gf==0) { - mark= 0; - - if(!(tf->unwrap & TF_SEAM1)) - if(BLI_edgehash_haskey(ehash, mf->v1, mf->v2)) - mark= 1; - if(!(tf->unwrap & TF_SEAM2)) - if(BLI_edgehash_haskey(ehash, mf->v2, mf->v3)) - mark= 1; - if(!(tf->unwrap & TF_SEAM3)) { - if(mf->v4) { - if(BLI_edgehash_haskey(ehash, mf->v3, mf->v4)) - mark= 1; - } - else if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1)) - mark= 1; - } - if(mf->v4 && !(tf->unwrap & TF_SEAM4)) - if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1)) - mark= 1; - - if(mark) { - *gf= gid; - doit= 1; - } - } - tf++; mf++; gf++; - } - } - } - - BLI_edgehash_free(ehash, NULL); - *seamgroups= groups; - - return gid; -} - -static void lscm_rotate_vert(int a, LscmVert **sortvert, int v2, int index) -{ - LscmVert **sv, *v; - int found, b; - - /* starting from edge sortvert->v,v2, rotate around vertex and set - * index until a seam or an already marked tri is encountered */ - found = 1; - - while(found) { - found= 0; - sv=sortvert; - - for(b=a; b>0 && ((*sv)->v == (*sortvert)->v) && !found; b--, sv++) { - v= *sv; - - if(v->flag & LSCM_INDEXED); - else if(v->v1 == v2) { - v2= v->v2; - - if(v->flag & LSCM_SEAM1) break; - - v->index= index; - v->flag |= LSCM_INDEXED; - found= 1; - break; - } - else if(v->v2==v2) { - v2= v->v1; - - if(v->flag & LSCM_SEAM2) break; - - v->index= index; - v->flag |= LSCM_INDEXED; - found= 1; - break; - } - } - } -} - -static int lscm_vertex_set_index(int a, LscmVert **sortvert, int totindex) -{ - LscmVert **sv, *v; - int index, b; - - /* rotate over 'wheel' of faces around vertex, incrementing the index - everytime we meet a seam, or no next connected face is found. - repeat this until we have and id for all verts. - if mesh is non-manifold, non-manifold edges will be cut randomly */ - - index= totindex; - sv= sortvert; - - for(b=a; b>0 && ((*sv)->v == (*sortvert)->v); b--, sv++) { - v= *sv; - - if(v->flag & LSCM_INDEXED) continue; - - v->index= index; - v->flag |= LSCM_INDEXED; - - lscm_rotate_vert(b, sv, v->v1, index); - lscm_rotate_vert(b, sv, v->v2, index); - - index++; - } - - return index; -} - -static int lscm_set_indices(LscmVert **sortvert, int totvert) -{ - LscmVert *v, **sv; - int a, lastvert, totindex; - - totindex= 0; - lastvert= -1; - sv= sortvert; - - for(a=totvert; a>0; a--, sv++) { - v= *sv; - if(v->v != lastvert) { - totindex= lscm_vertex_set_index(a, sv, totindex); - lastvert= v->v; - } - } - - return totindex; -} - -static void lscm_normalize(float *co, float *center, float radius) -{ - /* normalize relative to complete surface */ - VecSubf(co, co, center); - VecMulf(co, (float)1.0/radius); -} - -static void lscm_add_triangle(float *v1, float *v2, float *v3, int vid1, int vid2, int vid3, float *center, float radius) -{ - float x[3], y[3], z[3], sub[3], z1[2], z2[2]; - int id0[2], id1[2], id2[2]; - - /* project 3d triangle - * edge length is lost, as this algorithm is angle based */ - lscm_normalize(v1, center, radius); - lscm_normalize(v2, center, radius); - lscm_normalize(v3, center, radius); - - VecSubf(x, v2, v1); - Normalise(x); - - VecSubf(sub, v3, v1); - Crossf(z, x, sub); - Normalise(z); - - Crossf(y, z, x); - - /* reduce to two 2d vectors */ - VecSubf(sub, v2, v1); - z1[0]= Normalise(sub); - z1[1]= 0; - - VecSubf(sub, v3, v1); - z2[0]= Inpf(sub, x); - z2[1]= Inpf(sub, y); - - /* split id's up for u and v - id = u, id + 1 = v */ - id0[0]= 2*vid1; - id0[1]= 2*vid1 + 1; - id1[0]= 2*vid2; - id1[1]= 2*vid2 + 1; - id2[0]= 2*vid3; - id2[1]= 2*vid3 + 1; - - /* The LSCM Equation: - * ------------------ - * (u,v) are the uv coords we are looking for -> complex number u + i*v - * (x,y) are the above calculated local coords -> complex number x + i*y - * Uk = uk + i*vk - * Zk = xk + i*yk (= zk[0] + i*zk[1] in the code) - * - * That makes the equation: - * (Z1 - Z0)(U2 - U0) = (Z2 - Z0)(U1 - U0) - * - * x0, y0 and y1 were made zero by projecting the triangle: - * (x1 + i*y1)(u2 + i*v2 - u0 - i*v0) = (x2 + i*y2)(u1 + i*v1 - u0 - i*v0) - * - * this gives the following coefficients: - * u0 * ((-x1 + x2) + i*(y2)) - * v0 * ((-y2) + i*(-x1 + x2)) - * u1 * ((-x2) + i*(-y2)) - * v1 * ((y2) + i*(-x2)) - * u2 * (x1) - * v2 * (i*(x1)) - */ - - /* real part */ - nlBegin(NL_ROW); - nlCoefficient(id0[0], -z1[0] + z2[0]); - nlCoefficient(id0[1], -z2[1] ); - nlCoefficient(id1[0], -z2[0] ); - nlCoefficient(id1[1], z2[1] ); - nlCoefficient(id2[0], z1[0] ); - nlEnd(NL_ROW); - - /* imaginary part */ - nlBegin(NL_ROW); - nlCoefficient(id0[0], z2[1] ); - nlCoefficient(id0[1], -z1[0] + z2[0]); - nlCoefficient(id1[0], -z2[1] ); - nlCoefficient(id1[1], -z2[0] ); - nlCoefficient(id2[1], z1[0] ); - nlEnd(NL_ROW); -} - -static float lscm_angle_cos(float *v1, float *v2, float *v3) -{ - float vec1[3], vec2[3]; - - VecSubf(vec1, v2, v1); - VecSubf(vec2, v3, v1); - Normalise(vec1); - Normalise(vec2); - - return vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2]; -} - -static int lscm_build_vertex_data(Mesh *me, int *groups, int gid, LscmVert **lscm_vertices, LscmVert ***sort_vertices) -{ - MVert *mv; - MFace *mf; - TFace *tf; - int *gf, totvert, a; - LscmVert *lscmvert, **sortvert; - LscmVert *v1, *v2, *v3, **sv1, **sv2, **sv3; - float a1, a2; - - /* determine size for malloc */ - totvert= 0; - mv = me->mvert; - mf= me->mface; - tf= me->tface; - gf= groups; - a1 = a2 = 0; - - for(a=me->totface; a>0; a--) { - if(*gf==gid) { - - totvert += 3; - if(mf->v4) totvert +=3; - } - tf++; mf++; gf++; - } - - /* a list per face vertices */ - lscmvert= (LscmVert*)MEM_mallocN(sizeof(LscmVert)*totvert,"LscmVerts"); - /* the above list sorted by vertex id */ - sortvert= (LscmVert**)MEM_mallocN(sizeof(LscmVert*)*totvert, "LscmVSort"); - - /* actually build the list (including virtual triangulation) */ - mf= me->mface; - tf= me->tface; - gf= groups; - - v1= lscmvert; - v2= lscmvert + 1; - v3= lscmvert + 2; - - sv1= sortvert; - sv2= sortvert + 1; - sv3= sortvert + 2; - - /* warning: ugly code :) */ - for(a=me->totface; a>0; a--) { - if(*gf==gid) { - /* determine triangulation direction, to avoid degenerate - triangles (small cos = degenerate). */ - if(mf->v4) { - a1 = lscm_angle_cos((mv+mf->v1)->co, (mv+mf->v2)->co, (mv+mf->v3)->co); - a1 += lscm_angle_cos((mv+mf->v2)->co, (mv+mf->v1)->co, (mv+mf->v3)->co); - a1 += lscm_angle_cos((mv+mf->v3)->co, (mv+mf->v1)->co, (mv+mf->v2)->co); - - a2 = lscm_angle_cos((mv+mf->v1)->co, (mv+mf->v2)->co, (mv+mf->v4)->co); - a2 += lscm_angle_cos((mv+mf->v2)->co, (mv+mf->v1)->co, (mv+mf->v4)->co); - a2 += lscm_angle_cos((mv+mf->v4)->co, (mv+mf->v1)->co, (mv+mf->v2)->co); - } - - a1 = 0.0; a2 = 1.0; - - if(!mf->v4 || a1 > a2) { - v1->v= mf->v1; - v2->v= mf->v2; - v3->v= mf->v3; - - v1->tf_index= 0; - v2->tf_index= 1; - v3->tf_index= 2; - - v1->flag= v2->flag= v3->flag= 0; - - v1->v1= v2->v; - v1->v2= v3->v; - - v2->v1= v1->v; - v2->v2= v3->v; - - v3->v1= v1->v; - v3->v2= v2->v; - - v1->tf= v2->tf= v3->tf= tf; - - *sv1= v1; - *sv2= v2; - *sv3= v3; - - if(tf->unwrap & TF_SEAM1) { - v1->flag |= LSCM_SEAM1; - v2->flag |= LSCM_SEAM1; - } - - if(tf->unwrap & TF_SEAM2) { - v2->flag |= LSCM_SEAM2; - v3->flag |= LSCM_SEAM2; - } - - if(!mf->v4 && tf->unwrap & TF_SEAM3) { - v1->flag |= LSCM_SEAM2; - v3->flag |= LSCM_SEAM1; - } - - v1 += 3; v2 += 3; v3 += 3; - sv1 += 3; sv2 += 3; sv3 += 3; - } - - if(mf->v4 && a1 > a2) { - v1->v= mf->v1; - v2->v= mf->v3; - v3->v= mf->v4; - - v1->tf_index= 0; - v2->tf_index= 2; - v3->tf_index= 3; - - v1->flag= v2->flag= v3->flag= 0; - - v1->v1= v2->v; - v1->v2= v3->v; - - v2->v1= v3->v; - v2->v2= v1->v; - - v3->v1= v1->v; - v3->v2= v2->v; - - v1->tf= v2->tf= v3->tf= tf; - - *sv1= v1; - *sv2= v2; - *sv3= v3; - - if(tf->unwrap & TF_SEAM3) { - v2->flag |= LSCM_SEAM1; - v3->flag |= LSCM_SEAM2; - } - - if(tf->unwrap & TF_SEAM4) { - v1->flag |= LSCM_SEAM2; - v3->flag |= LSCM_SEAM1; - } - - v1 += 3; v2 += 3; v3 += 3; - sv1 += 3; sv2 += 3; sv3 += 3; - } - - if(mf->v4 && a1 <= a2) { - v1->v= mf->v1; - v2->v= mf->v2; - v3->v= mf->v4; - - v1->tf_index= 0; - v2->tf_index= 1; - v3->tf_index= 3; - - v1->flag= v2->flag= v3->flag= 0; - - v1->v1= v2->v; - v1->v2= v3->v; - - v2->v1= v1->v; - v2->v2= v3->v; - - v3->v1= v1->v; - v3->v2= v2->v; - - v1->tf= v2->tf= v3->tf= tf; - - *sv1= v1; - *sv2= v2; - *sv3= v3; - - if(tf->unwrap & TF_SEAM1) { - v1->flag |= LSCM_SEAM1; - v2->flag |= LSCM_SEAM1; - } - - if(tf->unwrap & TF_SEAM4) { - v1->flag |= LSCM_SEAM2; - v3->flag |= LSCM_SEAM1; - } - - v1 += 3; v2 += 3; v3 += 3; - sv1 += 3; sv2 += 3; sv3 += 3; - - /* -- */ - - v1->v= mf->v2; - v2->v= mf->v3; - v3->v= mf->v4; - - v1->tf_index= 1; - v2->tf_index= 2; - v3->tf_index= 3; - - v1->flag= v2->flag= v3->flag= 0; - - v1->v1= v2->v; - v1->v2= v3->v; - - v2->v1= v1->v; - v2->v2= v3->v; - - v3->v1= v1->v; - v3->v2= v2->v; - - v1->tf= v2->tf= v3->tf= tf; - - *sv1= v1; - *sv2= v2; - *sv3= v3; - - if(tf->unwrap & TF_SEAM2) { - v1->flag |= LSCM_SEAM1; - v2->flag |= LSCM_SEAM1; - } - - if(tf->unwrap & TF_SEAM3) { - v2->flag |= LSCM_SEAM2; - v3->flag |= LSCM_SEAM2; - } - - v1 += 3; v2 += 3; v3 += 3; - sv1 += 3; sv2 += 3; sv3 += 3; - } - - } - tf++; mf++; gf++; - } - - /* sort by vertex id */ - qsort(sortvert, totvert, sizeof(LscmVert*), comp_lscmvert); - - *lscm_vertices= lscmvert; - *sort_vertices= sortvert; - return totvert; -} - -static void lscm_min_max_cent_rad(Mesh *me, LscmVert **sortvert, int totvert, float *min, float *max, float *center, float *radius) -{ - MVert *mv= me->mvert; - LscmVert *v, **sv; - int a, lastvert, vertcount; - float *co, sub[3]; - - /* find min, max and center */ - center[0]= center[1]= center[2]= 0.0; - INIT_MINMAX(min, max); - - vertcount= 0; - lastvert= -1; - sv= sortvert; - - for(a=totvert; a>0; a--, sv++) { - v= *sv; - if(v->v != lastvert) { - co= (mv+v->v)->co; - - VecAddf(center, center, (mv+v->v)->co); - DO_MINMAX(co, min, max); - - vertcount++; - lastvert= v->v; - } - } - - VecMulf(center, (float)1.0/(float)vertcount); - - /* find radius */ - VecSubf(sub, center, max); - *radius= Normalise(sub); - - if(*radius < 1e-20) - *radius= 1.0; -} - -static void lscm_projection_axes(float *min, float *max, float *p1, float *p2) -{ - float dx, dy, dz; - - dx= max[0] - min[0]; - dy= max[1] - min[1]; - dz= max[2] - min[2]; - - p1[0]= p1[1]= p1[2]= 0.0; - p2[0]= p2[1]= p2[2]= 0.0; - - if(dx < dy && dx < dz) { - if(dy > dz) p1[1]= p2[2]= 1.0; /* y, z */ - else p1[2]= p2[1]= 1.0; /* z, y */ - } - else if(dy < dx && dy < dz) { - if(dx > dz) p1[0]= p2[2]= 1.0; /* x, z */ - else p1[2]= p2[0]= 1.0; /* z, x */ - } - else { - if(dx > dy) p1[0]= p2[1]= 1.0; /* x, y */ - else p1[1]= p2[0]= 1.0; /* y, x */ - } -} - -static void lscm_set_initial_solution(Mesh *me, LscmVert **sortvert, int totvert, float *p1, float *p2, int *vertex_min, int *vertex_max) -{ - float umin, umax, *uv, *co; - int vmin, vmax, a; - LscmVert **sv, *v; - MVert *mv= me->mvert; - - umin= 1.0e30; - umax= -1.0e30; - - vmin= 0; - vmax= 2; - - sv= sortvert; - - for(a=totvert; a>0; a--, sv++) { - v= *sv; - co= (mv+v->v)->co; - uv= v->tf->uv[v->tf_index]; - - uv[0]= Inpf(co, p1); - uv[1]= Inpf(co, p2); - - if(uv[0] < umin) { - vmin= v->index; - umin= uv[0]; - } - if(uv[0] > umax) { - vmax= v->index; - umax= uv[0]; - } - - nlSetVariable(2*v->index, uv[0]); - nlSetVariable(2*v->index + 1, uv[1]); - } - - *vertex_min= vmin; - *vertex_max= vmax; -} - -static void lscm_set_pinned_solution(Mesh *me, LscmVert **sortvert, int totvert, int *pinned) -{ - float min[2], max[2], *uv, *co; - int a, pin; - LscmVert **sv, *v; - MVert *mv= me->mvert; - - INIT_MINMAX2(min, max); - *pinned= 0; - - sv= sortvert; - - for(a=totvert; a>0; a--, sv++) { - v= *sv; - co= (mv+v->v)->co; - uv= v->tf->uv[v->tf_index]; - - pin = ((v->tf->unwrap & TF_PIN1) && (v->tf_index == 0)) || - ((v->tf->unwrap & TF_PIN2) && (v->tf_index == 1)) || - ((v->tf->unwrap & TF_PIN3) && (v->tf_index == 2)) || - ((v->tf->unwrap & TF_PIN4) && (v->tf_index == 3)); - - nlSetVariable(2*v->index, uv[0]); - nlSetVariable(2*v->index + 1, uv[1]); - - if(pin){ - DO_MINMAX2(uv, min, max); - - *pinned += 1; - - nlLockVariable(2*v->index); - nlLockVariable(2*v->index + 1); - } - } - - if (*pinned){ - /* abuse umax vmax for caculating euclidian distance */ - max[0] -= min[0]; - max[1] -= min[1]; - - /* check for degenerated pinning box */ - if (((max[0]*max[0])+(max[1]*max[1])) < 1e-10) - *pinned = -1; - } -} - - -static void lscm_build_matrix(Mesh *me, LscmVert *lscmvert, int *groups, int gid, float *center, float radius) -{ - MVert *mv= me->mvert; - MFace *mf; - TFace *tf; - int *gf, a, id1, id2, id3; - LscmVert *v; - float co1[3], co2[3], co3[3]; - - nlBegin(NL_MATRIX); - - mf= me->mface; - tf= me->tface; - gf= groups; - v= lscmvert; - - for(a=me->totface; a>0; a--) { - if(*gf==gid) { - VecCopyf(co1, (mv+v->v)->co); - id1= v->index; v++; - VecCopyf(co2, (mv+v->v)->co); - id2= v->index; v++; - VecCopyf(co3, (mv+v->v)->co); - id3= v->index; v++; - lscm_add_triangle(co1, co2, co3, id1, id2, id3, center, radius); - - if(mf->v4) { - VecCopyf(co1, (mv+v->v)->co); - id1= v->index; v++; - VecCopyf(co2, (mv+v->v)->co); - id2= v->index; v++; - VecCopyf(co3, (mv+v->v)->co); - id3= v->index; v++; - lscm_add_triangle(co1, co2, co3, id1, id2, id3, center, radius); - } - } - tf++; mf++; gf++; - } - - nlEnd(NL_MATRIX); -} - -static void lscm_load_solution(Mesh *me, LscmVert *lscmvert, int *groups, int gid) -{ - MFace *mf; - TFace *tf; - int *gf, a, b; - LscmVert *v; - float *uv; - - mf= me->mface; - tf= me->tface; - gf= groups; - v= lscmvert; - - for(a=me->totface; a>0; a--) { - if(*gf==gid) { - - if(mf->v4) b= 6; - else b=3; - - /* index= u, index + 1= v */ - while(b > 0) { - uv= v->tf->uv[v->tf_index]; - - uv[0]= nlGetVariable(2*v->index); - uv[1]= nlGetVariable(2*v->index + 1); - - v++; - b--; - } - } - tf++; mf++; gf++; - } -} - -static int unwrap_lscm_face_group(Mesh *me, int *groups, int gid) -{ - LscmVert *lscmvert, **sortvert; - int totindex, totvert, vmin, vmax,pinned; - float min[3], max[3], center[3], radius, p1[3], p2[3]; - - /* build the data structures */ - totvert= lscm_build_vertex_data(me, groups, gid, &lscmvert, &sortvert); - - /* calculate min, max, center and radius */ - lscm_min_max_cent_rad(me, sortvert, totvert, min, max, center, &radius); - - /* index distinct vertices */ - totindex= lscm_set_indices(sortvert, totvert); - - /* create solver */ - nlNewContext(); - nlSolverParameteri(NL_NB_VARIABLES, 2*totindex); - nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); - - nlBegin(NL_SYSTEM); - - /* find axes for projecting initial solutions on */ - lscm_projection_axes(min, max, p1, p2); - /* see if pinned data is avail and set on fly */ - lscm_set_pinned_solution(me, sortvert, totvert, &pinned); - - if(pinned < 0); /* really small pinned uv's: won't see difference anyway */ - else { - /* auto pinning */ - if(pinned < 2) - { - /* set initial solution and locate two extrema vertices to pin */ - lscm_set_initial_solution(me,sortvert,totvert,p1,p2,&vmin,&vmax); - - /* pin 2 uv's */ - nlLockVariable(2*vmin); - nlLockVariable(2*vmin + 1); - nlLockVariable(2*vmax); - nlLockVariable(2*vmax + 1); - } - - /* add triangles to the solver */ - lscm_build_matrix(me, lscmvert, groups, gid, center, radius); - - nlEnd(NL_SYSTEM); - - /* LSCM solver magic! */ - nlSolve(NULL, NL_FALSE); - - /* load new uv's: will be projected uv's if solving failed */ - lscm_load_solution(me, lscmvert, groups, gid); - } - - nlDeleteContext(nlGetCurrent()); - MEM_freeN(lscmvert); - MEM_freeN(sortvert); - return (pinned); -} - -static void seam_group_bbox(Mesh *me, int *groups, int gid, float *min, float *max) -{ - MFace *mf; - TFace *tf; - int *gf, a; - - INIT_MINMAX2(min, max); - - mf= me->mface; - tf= me->tface; - gf= groups; - - for(a=me->totface; a>0; a--) { - if((gid!=0 && *gf==gid) || (gid==0 && *gf)) { - - DO_MINMAX2(tf->uv[0], min, max) - DO_MINMAX2(tf->uv[1], min, max) - DO_MINMAX2(tf->uv[2], min, max) - - if(mf->v4) { - DO_MINMAX2(tf->uv[3], min, max) - } - } - tf++; mf++; gf++; - } -} - -static void seam_group_scale(Mesh *me, int *groups, int gid, float scale) -{ - MFace *mf; - TFace *tf; - int *gf, a; - - mf= me->mface; - tf= me->tface; - gf= groups; - - for(a=me->totface; a>0; a--) { - if((gid!=0 && *gf==gid) || (gid==0 && *gf)) { - - Vec2Mulf(tf->uv[0], scale); - Vec2Mulf(tf->uv[1], scale); - Vec2Mulf(tf->uv[2], scale); - if(mf->v4) Vec2Mulf(tf->uv[3], scale); - } - tf++; mf++; gf++; - } -} - -static void seam_group_move(Mesh *me, int *groups, int gid, float add[2]) -{ - MFace *mf; - TFace *tf; - int *gf, a; - - mf= me->mface; - tf= me->tface; - gf= groups; - - for(a=me->totface; a>0; a--) { - if((gid!=0 && *gf==gid) || (gid==0 && *gf)) { - - Vec2Addf(tf->uv[0], tf->uv[0], add); - Vec2Addf(tf->uv[1], tf->uv[1], add); - Vec2Addf(tf->uv[2], tf->uv[2], add); - if(mf->v4) Vec2Addf(tf->uv[3], tf->uv[3], add); - } - tf++; mf++; gf++; - } -} - -/* put group withing (0,0)->(1,1) boundbox */ -static void seam_group_normalize(Mesh *me, int *groups, int gid) -{ - float min[2], max[2], sx, sy, scale, add[2]; - - seam_group_bbox(me, groups, gid, min, max); - - sx= (max[0]-min[0]); - sy= (max[1]-min[1]); - - scale= MAX2(sx, sy); - scale= (1.0/scale); - - add[0]= -min[0]; - add[1]= -min[1]; - - seam_group_move(me, groups, gid, add); - seam_group_scale(me, groups, gid, scale); -} - -/* get scale relative to mesh */ -static float seam_group_relative_scale(Mesh *me, int *groups, int gid) -{ - MVert *mv= me->mvert; - MFace *mf; - TFace *tf; - int *gf, a; - float len_xyz, len_uv; - - len_xyz= 0.0; - len_uv= 0.0; - mf= me->mface; - tf= me->tface; - gf= groups; - - for(a=me->totface; a>0; a--) { - if(*gf==gid) { - - len_uv += Vec2Lenf(tf->uv[0], tf->uv[1]); - len_xyz += VecLenf((mv+mf->v1)->co, (mv+mf->v2)->co); - - len_uv += Vec2Lenf(tf->uv[1], tf->uv[2]); - len_xyz += VecLenf((mv+mf->v2)->co, (mv+mf->v3)->co); - - if(mf->v4) { - - len_uv += Vec2Lenf(tf->uv[2], tf->uv[3]); - len_xyz += VecLenf((mv+mf->v3)->co, (mv+mf->v4)->co); - - len_uv += Vec2Lenf(tf->uv[3], tf->uv[0]); - len_xyz += VecLenf((mv+mf->v4)->co, (mv+mf->v1)->co); - } - else { - len_uv += Vec2Lenf(tf->uv[2], tf->uv[0]); - len_xyz += VecLenf((mv+mf->v3)->co, (mv+mf->v1)->co); - } - } - tf++; mf++; gf++; - } - - return (len_uv/len_xyz); -} - -/* very primitive packing */ -static void pack_seam_groups(Mesh *me, int *groups, int totgroup) -{ - float *groupscale, minscale, scale, add[2], groupw; - float dx, dy, packx, packy, min[2], max[2], rowh; - int a; - - groupscale = (float*)MEM_mallocN(sizeof(float)*totgroup, "SeamGroupScale"); - - minscale= 1e30; - - for(a=0; a 1.0) { - add[0]= 0.0; - add[1]= packy; - - packy += dy; - packx= 0.0; - rowh= 0.0; - } - else if(dx <= (1.0-packx)) { - add[0]= packx; - add[1]= packy; - - packx += dx; - rowh= MAX2(rowh, dy); - } - else { - packy += rowh; - packx= dx; - rowh= dy; - - add[0]= 0.0; - add[1]= packy; - } - - /* for padding */ - add[0] += 0.005; - add[1] += 0.005; - - seam_group_scale(me, groups, a+1, scale); - seam_group_move(me, groups, a+1, add); - } - - MEM_freeN(groupscale); - - seam_group_normalize(me, groups, 0); - seam_group_scale(me, groups, 0, 0.98); - add[0]= add[1]= 0.01; - seam_group_move(me, groups, 0, add); -} - -void unwrap_lscm(void) -{ - int dopack = 1; - int res; - Mesh *me; - int totgroup, *groups=NULL, a; - - if (G.scene->toolsettings->unwrapper != 2) { - unwrap_lscm_new(); - return; - } - - me= get_mesh(OBACT); - if(me==0 || me->tface==0) return; - - totgroup= make_seam_groups(me, &groups); - - if(totgroup==0) return; - - for(a=totgroup; a>0; a--) { - res= unwrap_lscm_face_group(me, groups, a); - if((res < 3) && (res > -1)) { - seam_group_normalize(me, groups, a); - } - else { - dopack = 0; - } - - } - - if(dopack) pack_seam_groups(me, groups, totgroup); - - MEM_freeN(groups); - - BIF_undo_push("UV lscm unwrap"); - - object_uvs_changed(OBACT); - - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWIMAGE, 0); -} - -/* note; to make it quick work, brecht/jens: you can make it nice later! (ton) */ -void unwrap_lscm_live(void) -{ - int dopack = 1; - int res; - Mesh *me; - int totgroup, *groups=NULL, a; - - me= get_mesh(OBACT); - if(me==0 || me->tface==0) return; - - totgroup= make_seam_groups(me, &groups); - - if(totgroup==0) return; - - for(a=totgroup; a>0; a--) { - res= unwrap_lscm_face_group(me, groups, a); - if((res < 3) && (res > -1)) { - seam_group_normalize(me, groups, a); - } - else { - dopack = 0; - } - - } - - if(dopack) pack_seam_groups(me, groups, totgroup); - - MEM_freeN(groups); - -} - -/* Set tface seams based on edge data, uses hash table to find seam edges. */ - -void set_seamtface() -{ - Mesh *me; - EdgeHash *ehash; - int a; - MFace *mf; - TFace *tf; - MEdge *medge; - - me= get_mesh(OBACT); - if(!me || !me->tface || !(G.f & G_FACESELECT)) return; - - ehash= BLI_edgehash_new(); - - for(medge=me->medge, a=me->totedge; a>0; a--, medge++) - if(medge->flag & ME_SEAM) - BLI_edgehash_insert(ehash, medge->v1, medge->v2, NULL); - - mf= me->mface; - tf= me->tface; - for(a=me->totface; a>0; a--, mf++, tf++) { - tf->unwrap &= ~(TF_SEAM1|TF_SEAM2|TF_SEAM3|TF_SEAM4); - - if(!ehash) continue; - - if(BLI_edgehash_haskey(ehash, mf->v1, mf->v2)) tf->unwrap |= TF_SEAM1; - if(BLI_edgehash_haskey(ehash, mf->v2, mf->v3)) tf->unwrap |= TF_SEAM2; - - if(mf->v4) { - if(BLI_edgehash_haskey(ehash, mf->v3, mf->v4)) tf->unwrap |= TF_SEAM3; - if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1)) tf->unwrap |= TF_SEAM4; - } - else if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1)) tf->unwrap |= TF_SEAM3; - } - - BLI_edgehash_free(ehash, NULL); -} - void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index) { TFace *tf; MFace *mf; int a, doit=1, mark=0; char *linkflag; - EdgeHash *ehash; + EdgeHash *ehash, *seamhash; + MEdge *med; ehash= BLI_edgehash_new(); + seamhash = BLI_edgehash_new(); linkflag= MEM_callocN(sizeof(char)*me->totface, "linkflaguv"); + for(med=me->medge, a=0; a < me->totedge; a++, med++) + if(med->flag & ME_SEAM) + BLI_edgehash_insert(seamhash, med->v1, med->v2, NULL); + if (mode==0 || mode==1) { /* only put face under cursor in array */ mf= ((MFace*)me->mface) + index; @@ -1285,27 +123,29 @@ void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index) tf= me->tface; mf= me->mface; for(a=0; atotface; a++, tf++, mf++) { - if(tf->flag & TF_HIDE); - else if(!linkflag[a]) { + if(tf->flag & TF_HIDE) + continue; + + if(!linkflag[a]) { mark= 0; - if(!(tf->unwrap & TF_SEAM1)) + if(!BLI_edgehash_haskey(seamhash, mf->v1, mf->v2)) if(BLI_edgehash_haskey(ehash, mf->v1, mf->v2)) mark= 1; - if(!(tf->unwrap & TF_SEAM2)) + if(!BLI_edgehash_haskey(seamhash, mf->v2, mf->v3)) if(BLI_edgehash_haskey(ehash, mf->v2, mf->v3)) mark= 1; - if(!(tf->unwrap & TF_SEAM3)) { - if(mf->v4) { + if(mf->v4) { + if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v4)) if(BLI_edgehash_haskey(ehash, mf->v3, mf->v4)) mark= 1; - } - else if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1)) - mark= 1; + if(!BLI_edgehash_haskey(seamhash, mf->v4, mf->v1)) + if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1)) + mark= 1; } - if(mf->v4 && !(tf->unwrap & TF_SEAM4)) - if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1)) - mark= 1; + else if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v1)) + if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1)) + mark = 1; if(mark) { linkflag[a]= 1; @@ -1317,6 +157,9 @@ void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index) } + BLI_edgehash_free(ehash, NULL); + BLI_edgehash_free(seamhash, NULL); + if(mode==0 || mode==2) { for(a=0, tf=me->tface; atotface; a++, tf++) if(linkflag[a]) @@ -1341,7 +184,6 @@ void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index) } } - BLI_edgehash_free(ehash, NULL); MEM_freeN(linkflag); BIF_undo_push("Select linked UV face"); @@ -1350,7 +192,7 @@ void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index) /* Parametrizer */ -ParamHandle *construct_param_handle(Mesh *me, short implicit, short fill) +ParamHandle *construct_param_handle(Mesh *me, short implicit, short fill, short sel) { int a; TFace *tf; @@ -1371,7 +213,10 @@ ParamHandle *construct_param_handle(Mesh *me, short implicit, short fill) float *uv[4]; int nverts; - if ((tf->flag & TF_HIDE) || !(tf->flag & TF_SELECT)) + if (tf->flag & TF_HIDE) + continue; + + if (sel && !(tf->flag & TF_SELECT)) continue; if (implicit && !(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4))) @@ -1429,7 +274,7 @@ ParamHandle *construct_param_handle(Mesh *me, short implicit, short fill) return handle; } -void unwrap_lscm_new(void) +void unwrap_lscm(short seamcut) { Mesh *me; ParamHandle *handle; @@ -1439,7 +284,7 @@ void unwrap_lscm_new(void) me= get_mesh(OBACT); if(me==0 || me->tface==0) return; - handle = construct_param_handle(me, 0, fillholes); + handle = construct_param_handle(me, 0, fillholes, seamcut == 0); param_lscm_begin(handle, PARAM_FALSE, abf); param_lscm_solve(handle); @@ -1451,7 +296,8 @@ void unwrap_lscm_new(void) param_delete(handle); - BIF_undo_push("UV unwrap"); + if (!seamcut) + BIF_undo_push("UV unwrap"); object_uvs_changed(OBACT); @@ -1471,7 +317,7 @@ void minimize_stretch_tface_uv(void) me = get_mesh(OBACT); if(me==0 || me->tface==0) return; - handle = construct_param_handle(me, 1, fillholes); + handle = construct_param_handle(me, 1, fillholes, 1); lasttime = PIL_check_seconds_timer(); @@ -1561,7 +407,7 @@ void smooth_area_tface_uv(void) me = get_mesh(OBACT); if(me==0 || me->tface==0) return; - handle = construct_param_handle(me, 1, fillholes); + handle = construct_param_handle(me, 1, fillholes, 1); param_smooth_area(handle); param_flush(handle); param_delete(handle); @@ -1584,24 +430,16 @@ void unwrap_lscm_live_begin(void) short abf = G.scene->toolsettings->unwrapper == 1; short fillholes = G.scene->toolsettings->uvcalc_flag & 1; - if (G.scene->toolsettings->unwrapper == 2) - return; - me= get_mesh(OBACT); if(me==0 || me->tface==0) return; - liveHandle = construct_param_handle(me, 0, fillholes); + liveHandle = construct_param_handle(me, 0, fillholes, 1); param_lscm_begin(liveHandle, PARAM_TRUE, abf); } void unwrap_lscm_live_re_solve(void) { - if (G.scene->toolsettings->unwrapper == 2) { - unwrap_lscm(); - return; - } - if (liveHandle) { param_lscm_solve(liveHandle); param_flush(liveHandle); @@ -1610,9 +448,6 @@ void unwrap_lscm_live_re_solve(void) void unwrap_lscm_live_end(short cancel) { - if (G.scene->toolsettings->unwrapper == 2) - return; - if (liveHandle) { param_lscm_end(liveHandle); if (cancel) diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 38703ef322f..b33495fad90 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -571,6 +571,8 @@ void viewmove(int mode) VECCOPY(obofs, ofs); } } + else + ofs[0] = ofs[1] = ofs[2] = 0.0f; reverse= 1.0f; if (G.vd->persmat[2][1] < 0.0f) diff --git a/source/blender/src/vpaint.c b/source/blender/src/vpaint.c index 749f45d772e..d6533fbe12f 100644 --- a/source/blender/src/vpaint.c +++ b/source/blender/src/vpaint.c @@ -652,26 +652,6 @@ static int sample_backbuf_area(int x, int y, float size) return tot; } -static unsigned int sample_backbuf(int x, int y) -{ - unsigned int col; - - if(x>=curarea->winx || y>=curarea->winy) return 0; - - x+= curarea->winrct.xmin; - y+= curarea->winrct.ymin; - -#ifdef __APPLE__ - glReadBuffer(GL_AUX0); -#endif - glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); - glReadBuffer(GL_BACK); - - if(G.order==B_ENDIAN) SWITCH_INT(col); - - return framebuffer_to_index(col); -} - static int calc_vp_alpha_dl(VPaint *vp, float *vert_nor, short *mval) { float fac, dx, dy;