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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_global.h2
-rw-r--r--source/blender/blenkernel/BKE_utildefines.h2
-rw-r--r--source/blender/blenkernel/intern/displist.c9
-rw-r--r--source/blender/blenkernel/intern/subsurf.c32
-rw-r--r--source/blender/blenlib/BLI_arithb.h17
-rw-r--r--source/blender/blenlib/BLI_editVert.h6
-rw-r--r--source/blender/blenlib/intern/arithb.c21
-rw-r--r--source/blender/include/BDR_unwrapper.h40
-rw-r--r--source/blender/include/BIF_editmesh.h4
-rw-r--r--source/blender/include/BIF_editsima.h1
-rw-r--r--source/blender/include/BIF_resources.h2
-rw-r--r--source/blender/include/butspace.h39
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h12
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h2
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h1
-rw-r--r--source/blender/src/Makefile2
-rw-r--r--source/blender/src/SConscript4
-rw-r--r--source/blender/src/buttons_editing.c70
-rw-r--r--source/blender/src/drawimage.c51
-rw-r--r--source/blender/src/drawmesh.c180
-rw-r--r--source/blender/src/drawobject.c22
-rw-r--r--source/blender/src/editface.c50
-rw-r--r--source/blender/src/editmesh.c315
-rw-r--r--source/blender/src/editobject.c8
-rw-r--r--source/blender/src/editsima.c32
-rw-r--r--source/blender/src/header_image.c19
-rw-r--r--source/blender/src/header_view3d.c11
-rw-r--r--source/blender/src/resources.c8
-rw-r--r--source/blender/src/space.c25
-rw-r--r--source/blender/src/toolbox.c3
-rw-r--r--source/blender/src/unwrapper.c1159
31 files changed, 1876 insertions, 273 deletions
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index 7586f14c894..b9c45834840 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -187,6 +187,8 @@ typedef struct Global {
#define G_NOFROZEN (1 << 17) // frozen modules inactive
#define G_DRAWEDGES (1 << 18)
#define G_DRAWCREASES (1 << 19)
+#define G_DRAWSEAMS (1 << 20)
+#define G_HIDDENEDGES (1 << 21)
/* G.fileflags */
diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h
index 97cd46aa3fc..44cef530f48 100644
--- a/source/blender/blenkernel/BKE_utildefines.h
+++ b/source/blender/blenkernel/BKE_utildefines.h
@@ -81,6 +81,8 @@
#define INIT_MINMAX(min, max) (min)[0]= (min)[1]= (min)[2]= 1.0e30; (max)[0]= (max)[1]= (max)[2]= -1.0e30;
+#define INIT_MINMAX2(min, max) (min)[0]= (min)[1]= 1.0e30; (max)[0]= (max)[1]= -1.0e30;
+
#define DO_MINMAX(vec, min, max) if( (min)[0]>(vec)[0] ) (min)[0]= (vec)[0]; \
if( (min)[1]>(vec)[1] ) (min)[1]= (vec)[1]; \
if( (min)[2]>(vec)[2] ) (min)[2]= (vec)[2]; \
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 530442f03a9..1b100d339fb 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -277,12 +277,17 @@ void displistmesh_to_mesh(DispListMesh *dlm, Mesh *me)
} else {
me->totface= dlm->totface;
me->totvert= dlm->totvert;
-
+
me->mvert= MEM_dupallocN(dlm->mvert);
me->mface= mfaces= MEM_mallocN(sizeof(*mfaces)*me->totface, "me->mface");
me->tface= MEM_dupallocN(dlm->tface);
me->mcol= MEM_dupallocN(dlm->mcol);
-
+
+ if(dlm->medge) {
+ me->totedge= dlm->totedge;
+ me->medge= MEM_dupallocN(dlm->medge);
+ }
+
for (i=0; i<me->totface; i++) {
MFace *mf= &mfaces[i];
MFace *oldmf= &dlm->mface[i];
diff --git a/source/blender/blenkernel/intern/subsurf.c b/source/blender/blenkernel/intern/subsurf.c
index 6b069782336..4a8724272b7 100644
--- a/source/blender/blenkernel/intern/subsurf.c
+++ b/source/blender/blenkernel/intern/subsurf.c
@@ -176,8 +176,9 @@ struct _HyperVert {
LinkNode *edges, *faces;
};
-/* hyper edge flag */
+/* hyper edge flags */
#define DR_OPTIM 1
+#define HE_SEAM 2
struct _HyperEdge {
HyperEdge *next;
@@ -200,6 +201,7 @@ struct _HyperFace {
unsigned char (*vcol)[4];
float (*uvco)[2];
+ short unwrap;
/* for getting back tface, matnr, etc */
union {
@@ -342,7 +344,7 @@ static HyperMesh *hypermesh_from_mesh(Mesh *me, float *extverts, int subdivLevel
MFace *mface= me->mface;
MEdge *medge= me->medge;
float creasefac= ((float)subdivLevels)/255.0; // in Mesh sharpness is byte
- int i, j;
+ int i, j, flag;
hme->orig_me= me;
if (me->tface)
@@ -362,8 +364,11 @@ static HyperMesh *hypermesh_from_mesh(Mesh *me, float *extverts, int subdivLevel
if(medge) {
for (i=0; i<me->totedge; i++) {
MEdge *med= &medge[i];
+
+ flag= DR_OPTIM;
+ if(med->flag & ME_SEAM) flag |= HE_SEAM;
- hypermesh_add_edge(hme, vert_tbl[med->v1], vert_tbl[med->v2], DR_OPTIM,
+ hypermesh_add_edge(hme, vert_tbl[med->v1], vert_tbl[med->v2], flag,
creasefac*((float)med->crease) );
}
}
@@ -395,6 +400,8 @@ static HyperMesh *hypermesh_from_mesh(Mesh *me, float *extverts, int subdivLevel
f->vcol= BLI_memarena_alloc(hme->arena, sizeof(*f->vcol)*nverts);
for (j=0; j<nverts; j++)
*((unsigned int*) f->vcol[j])= tf->col[j];
+
+ f->unwrap= tf->unwrap;
} else if (hme->hasvcol) {
MCol *mcol= &me->mcol[i*4];
@@ -418,6 +425,7 @@ static HyperMesh *hypermesh_from_editmesh(EditMesh *em, int subdivLevels) {
EditEdge *ee;
EditVlak *ef;
float creasefac= (float)subdivLevels;
+ int flag;
/* we only add vertices with edges, 'f1' is a free flag */
/* added: check for hide flag in vertices */
@@ -437,8 +445,10 @@ static HyperMesh *hypermesh_from_editmesh(EditMesh *em, int subdivLevels) {
ee->v2->prev= (EditVert*) hypermesh_add_vert(hme, ee->v2->co, ee->v2->co);
ee->v2->f1= 0;
}
-
- hypermesh_add_edge(hme, (HyperVert*) ee->v1->prev, (HyperVert*) ee->v2->prev, DR_OPTIM,
+
+ flag= DR_OPTIM;
+ if(ee->seam) flag |= HE_SEAM;
+ hypermesh_add_edge(hme, (HyperVert*) ee->v1->prev, (HyperVert*) ee->v2->prev, flag,
creasefac*ee->crease);
}
}
@@ -743,6 +753,13 @@ static void hypermesh_subdivide(HyperMesh *me, HyperMesh *nme) {
Vec2Cpy(nf->uvco[1], uvco_edge[j]);
Vec2Cpy(nf->uvco[2], uvco_mid);
Vec2Cpy(nf->uvco[3], uvco_edge[last]);
+
+ if(j==0 && (f->unwrap & ((f->nverts==4)?TF_PIN4:TF_PIN3)))
+ nf->unwrap= TF_PIN1;
+ else if(j==1 && f->unwrap & TF_PIN1) nf->unwrap= TF_PIN1;
+ else if(j==2 && f->unwrap & TF_PIN2) nf->unwrap= TF_PIN1;
+ else if(j==3 && f->unwrap & TF_PIN3) nf->unwrap= TF_PIN1;
+ else nf->unwrap= 0;
}
}
}
@@ -956,8 +973,8 @@ static DispListMesh *hypermesh_to_displistmesh(HyperMesh *hme, short flag) {
med->v1= (int) e->v[0]->nmv;
med->v2= (int) e->v[1]->nmv;
- /* flag only for optimal */
- if(e->flag) med->flag = ME_EDGEDRAW;
+ if(e->flag & DR_OPTIM) med->flag |= ME_EDGEDRAW;
+ if(e->flag & HE_SEAM) med->flag |= ME_SEAM;
}
/* and we add the handles (med is re-used) */
@@ -1036,6 +1053,7 @@ static DispListMesh *hypermesh_to_displistmesh(HyperMesh *hme, short flag) {
tf->transp= origtf->transp;
tf->mode= origtf->mode;
tf->tile= origtf->tile;
+ tf->unwrap= f->unwrap;
} else if (hme->hasvcol) {
MCol *mcolbase= &dlm->mcol[i*4];
diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h
index 5941d421d16..4df5db5f39e 100644
--- a/source/blender/blenlib/BLI_arithb.h
+++ b/source/blender/blenlib/BLI_arithb.h
@@ -749,7 +749,22 @@ triatoquat(
MinMaxRGB(
short c[]
);
-
+ float
+Vec2Lenf(
+ float *v1,
+ float *v2
+);
+ void
+Vec2Mulf(
+ float *v1,
+ float f
+);
+ void
+Vec2Addf(
+ float *v,
+ float *v1,
+ float *v2
+);
#ifdef __cplusplus
}
diff --git a/source/blender/blenlib/BLI_editVert.h b/source/blender/blenlib/BLI_editVert.h
index 568aa6b65ae..3f477036c0b 100644
--- a/source/blender/blenlib/BLI_editVert.h
+++ b/source/blender/blenlib/BLI_editVert.h
@@ -58,9 +58,9 @@ typedef struct EditEdge
{
struct EditEdge *next, *prev;
struct EditVert *v1, *v2, *vn;
- short f,h;
- short f1, dir;
- float crease;
+ short f, f1;
+ unsigned char h, dir, seam;
+ float crease;
} EditEdge;
typedef struct EditVlak
diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c
index ac025b34127..ff057a61e51 100644
--- a/source/blender/blenlib/intern/arithb.c
+++ b/source/blender/blenlib/intern/arithb.c
@@ -2181,6 +2181,27 @@ void MinMaxRGB(short c[])
else if(c[2]<0) c[2]=0;
}
+float Vec2Lenf(float *v1, float *v2)
+{
+ float x, y;
+
+ x = v1[0]-v2[0];
+ y = v1[1]-v2[1];
+ return (float)sqrt(x*x+y*y);
+}
+
+void Vec2Mulf(float *v1, float f)
+{
+ v1[0]*= f;
+ v1[1]*= f;
+}
+
+void Vec2Addf(float *v, float *v1, float *v2)
+{
+ v[0]= v1[0]+ v2[0];
+ v[1]= v1[1]+ v2[1];
+}
+
void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b)
{
int i;
diff --git a/source/blender/include/BDR_unwrapper.h b/source/blender/include/BDR_unwrapper.h
new file mode 100644
index 00000000000..72633bab9e4
--- /dev/null
+++ b/source/blender/include/BDR_unwrapper.h
@@ -0,0 +1,40 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BDR_UNWRAPPER_H
+#define BDR_UNWRAPPER_H
+
+void set_seamtface(); /* set TF_SEAM flags in tfaces */
+void unwrap_lscm(); /* unwrap selected tfaces */
+
+#endif /* BDR_UNWRAPPER_H */
+
diff --git a/source/blender/include/BIF_editmesh.h b/source/blender/include/BIF_editmesh.h
index 09dcd69dc9f..de289c88e20 100644
--- a/source/blender/include/BIF_editmesh.h
+++ b/source/blender/include/BIF_editmesh.h
@@ -165,8 +165,12 @@ void select_more(void);
void select_less(void);
void selectrandom_mesh(void);
+void Edge_Menu(void);
+
void editmesh_select_by_material(int index);
void editmesh_deselect_by_material(int index);
+void editmesh_mark_seam(int clear);
+
#endif
diff --git a/source/blender/include/BIF_editsima.h b/source/blender/include/BIF_editsima.h
index e3e803ad5d2..c3750bfc018 100644
--- a/source/blender/include/BIF_editsima.h
+++ b/source/blender/include/BIF_editsima.h
@@ -45,4 +45,5 @@ void stitch_uv_tface(int mode);
void unlink_selection(void);
void select_linked_tface_uv(void);
void toggle_uv_select(int mode);
+void pin_tface_uv(int mode);
diff --git a/source/blender/include/BIF_resources.h b/source/blender/include/BIF_resources.h
index 6bce7e4e3f1..ededfab7489 100644
--- a/source/blender/include/BIF_resources.h
+++ b/source/blender/include/BIF_resources.h
@@ -376,6 +376,8 @@ enum {
TH_VERTEX_SIZE,
TH_EDGE,
TH_EDGE_SELECT,
+ TH_EDGE_SEAM,
+ TH_EDGE_FACESEL,
TH_FACE,
TH_FACE_SELECT
};
diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h
index 55fac76e7fb..eb9e7455baf 100644
--- a/source/blender/include/butspace.h
+++ b/source/blender/include/butspace.h
@@ -524,25 +524,26 @@ enum {
#define B_UVAUTOCALCBUTS 3400
enum {
B_UVAUTO_REDRAW = 3301,
- B_UVAUTO_SPHERE,
- B_UVAUTO_CYLINDER,
- B_UVAUTO_CYLRADIUS,
- B_UVAUTO_WINDOW,
- B_UVAUTO_CUBE,
- B_UVAUTO_CUBESIZE,
- B_UVAUTO_STD1,
- B_UVAUTO_STD2,
- B_UVAUTO_STD4,
- B_UVAUTO_STD8,
- B_UVAUTO_BOUNDS1,
- B_UVAUTO_BOUNDS2,
- B_UVAUTO_BOUNDS4,
- B_UVAUTO_BOUNDS8,
- B_UVAUTO_TOP,
- B_UVAUTO_FACE,
- B_UVAUTO_OBJECT,
- B_UVAUTO_ALIGNX,
- B_UVAUTO_ALIGNY
+ B_UVAUTO_SPHERE,
+ B_UVAUTO_CYLINDER,
+ B_UVAUTO_CYLRADIUS,
+ B_UVAUTO_WINDOW,
+ B_UVAUTO_CUBE,
+ B_UVAUTO_CUBESIZE,
+ B_UVAUTO_STD1,
+ B_UVAUTO_STD2,
+ B_UVAUTO_STD4,
+ B_UVAUTO_STD8,
+ B_UVAUTO_BOUNDS1,
+ B_UVAUTO_BOUNDS2,
+ B_UVAUTO_BOUNDS4,
+ B_UVAUTO_BOUNDS8,
+ B_UVAUTO_TOP,
+ B_UVAUTO_FACE,
+ B_UVAUTO_OBJECT,
+ B_UVAUTO_ALIGNX,
+ B_UVAUTO_ALIGNY,
+ B_UVAUTO_LSCM
};
#define B_EFFECTSBUTS 3500
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index 674c144923d..f9cb375572b 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -53,7 +53,7 @@ typedef struct TFace {
float uv[4][2]; /* when you change this: also do function set_correct_uv in editmesh.c, and there are more locations that use the size of this part */
unsigned int col[4];
char flag, transp;
- short mode, tile, pad;
+ short mode, tile, unwrap;
} TFace;
typedef struct Mesh {
@@ -153,6 +153,16 @@ typedef struct Mesh {
#define TF_ALPHA 2
#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 MESH_MAX_VERTS 2000000000L
#endif
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index 04de27f58b0..f0ac467afb2 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -79,7 +79,7 @@ typedef struct MSticky {
/* medge->flag (1=SELECT)*/
#define ME_EDGEDRAW 2
-
+#define ME_SEAM 4
/* puno = vertexnormal (mface) */
#define ME_FLIPV1 1
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 97a944db70d..7c2773f0b5b 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -82,6 +82,7 @@ typedef struct ThemeSpace {
char active[4], transform[4];
char vertex[4], vertex_select[4];
char edge[4], edge_select[4];
+ char edge_seam[4], edge_facesel[4];
char face[4], face_select[4];
char vertex_size, pad;
diff --git a/source/blender/src/Makefile b/source/blender/src/Makefile
index bdb5af6b801..210ed7d7320 100644
--- a/source/blender/src/Makefile
+++ b/source/blender/src/Makefile
@@ -85,6 +85,8 @@ CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
CPPFLAGS += -I$(NAN_DECIMATION)/include
CPPFLAGS += -I$(NAN_BSP)/include
+CPPFLAGS += -I$(NAN_OPENNL)/include
+
CPPFLAGS += -I../readstreamglue
CPPFLAGS += -I../include
diff --git a/source/blender/src/SConscript b/source/blender/src/SConscript
index 24471f09b47..2c371369679 100644
--- a/source/blender/src/SConscript
+++ b/source/blender/src/SConscript
@@ -101,6 +101,7 @@ source_files = ['B.blend.c',
'swapbuffers.c',
'toets.c',
'toolbox.c',
+ 'unwrapper.c',
'usiblender.c',
'view.c',
'vpaint.c',
@@ -128,7 +129,8 @@ src_env.Append (CPPPATH = ['#/intern/guardedalloc',
'../readstreamglue',
'../img',
'../quicktime',
- '#/intern/ghost'])
+ '#/intern/ghost',
+ '#/intern/opennl/extern'])
src_env.Append (CPPPATH = user_options_dict['PYTHON_INCLUDE'])
src_env.Append (CPPPATH = user_options_dict['SDL_INCLUDE'])
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index 33021c7d17f..9167e4ccd7f 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -137,6 +137,7 @@
#include "BDR_editface.h"
#include "BDR_editobject.h"
#include "BDR_vpaint.h"
+#include "BDR_unwrapper.h"
#include "BSE_drawview.h"
#include "BSE_editipo.h"
@@ -2037,26 +2038,25 @@ static void editing_panel_mesh_tools1(Object *ob, Mesh *me)
block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_tools1", UI_EMBOSS, UI_HELV, curarea->win);
if(uiNewPanel(curarea, block, "Mesh Tools 1", "Editing", 960, 0, 318, 204)==0) return;
- uiDefBut(block, BUT,B_DOCENTRE, "Centre", 1091, 200, 166, 19, 0, 0, 0, 0, 0, "Shifts object data to be centered about object's origin");
uiBlockBeginAlign(block);
- uiDefBut(block, BUT,B_HIDE, "Hide", 1091,155,77,24, 0, 0, 0, 0, 0, "Hides selected faces");
- uiDefBut(block, BUT,B_REVEAL, "Reveal", 1171,155,86,24, 0, 0, 0, 0, 0, "Reveals selected faces");
+ uiDefBut(block, BUT,B_DOCENTRE, "Centre", 1091, 200, 166, 19, 0, 0, 0, 0, 0, "Shifts object data to be centered about object's origin");
+ uiDefBut(block, BUT,B_HIDE, "Hide", 1091, 180, 77, 19, 0, 0, 0, 0, 0, "Hides selected faces");
+ uiDefBut(block, BUT,B_REVEAL, "Reveal", 1171, 180, 86, 19, 0, 0, 0, 0, 0, "Reveals selected faces");
+ uiDefBut(block, BUT,B_SELSWAP, "Select Swap", 1091, 160, 166, 19, 0, 0, 0, 0, 0, "Selects unselected faces, and deselects selected faces");
uiBlockEndAlign(block);
- uiDefBut(block, BUT,B_SELSWAP, "Select Swap", 1091,130,166,24, 0, 0, 0, 0, 0, "Selects unselected faces, and deselects selected faces");
-
uiBlockBeginAlign(block);
- uiDefButF(block, NUM, REDRAWVIEW3D, "NSize:", 1090, 110, 164, 19, &editbutsize, 0.001, 2.0, 10, 0, "Sets the length to use when displaying face normals");
- uiDefButI(block, TOG|BIT|19, REDRAWVIEW3D, "Draw Creases", 1090,90,164,19, &G.f, 0, 0, 0, 0, "Displays face normals as lines");
- uiDefButI(block, TOG|BIT|6, REDRAWVIEW3D, "Draw Normals", 1090,70,164,19, &G.f, 0, 0, 0, 0, "Displays face normals as lines");
- uiDefButI(block, TOG|BIT|7, REDRAWVIEW3D, "Draw Faces", 1090,50,164,19, &G.f, 0, 0, 0, 0, "Displays all faces as shades");
- uiDefButI(block, TOG|BIT|18, REDRAWVIEW3D, "Draw Edges", 1090,30,164,19, &G.f, 0, 0, 0, 0, "Displays selected edges using hilights");
- uiDefButI(block, TOG|BIT|11, 0, "All edges", 1090,10,164,19, &G.f, 0, 0, 0, 0, "Displays all edges in object mode without optimization");
+ uiDefButF(block, NUM, REDRAWVIEW3D, "NSize:", 1090, 131, 166, 19, &editbutsize, 0.001, 2.0, 10, 0, "Sets the length to use when displaying face normals");
+ uiDefButI(block, TOG|BIT|6, REDRAWVIEW3D, "Draw Normals", 1090,110,166,19, &G.f, 0, 0, 0, 0, "Displays face normals as lines");
+ uiDefButI(block, TOG|BIT|7, REDRAWVIEW3D, "Draw Faces", 1090,88,166,19, &G.f, 0, 0, 0, 0, "Displays all faces as shades");
+ uiDefButI(block, TOG|BIT|18, REDRAWVIEW3D, "Draw Edges", 1090,66,166,19, &G.f, 0, 0, 0, 0, "Displays selected edges using hilights");
+ uiDefButI(block, TOG|BIT|19, REDRAWVIEW3D, "Draw Creases", 1090,44,166,19, &G.f, 0, 0, 0, 0, "Displays creased edges using hilights");
+ uiDefButI(block, TOG|BIT|20, REDRAWVIEW3D, "Draw Seams", 1090,22,166,19, &G.f, 0, 0, 0, 0, "Displays UV unwrapping seams");
+ uiDefButI(block, TOG|BIT|11, 0, "All Edges", 1090, 0,166,19, &G.f, 0, 0, 0, 0, "Displays all edges in object mode without optimization");
uiBlockEndAlign(block);
}
-
static void editing_panel_links(Object *ob)
{
uiBlock *block;
@@ -2365,7 +2365,6 @@ static void editing_panel_mesh_paint(void)
}
-
static void editing_panel_mesh_texface(void)
{
uiBlock *block;
@@ -2403,9 +2402,9 @@ static void editing_panel_mesh_texface(void)
uiBlockSetCol(block, TH_AUTO);
uiBlockBeginAlign(block);
- uiDefBut(block, BUT, B_COPY_TF_MODE, "Copy DrawMode", 600,7,117,28, 0, 0, 0, 0, 0, "Copy the drawmode");
- uiDefBut(block, BUT, B_COPY_TF_UV, "Copy UV+tex", 721,7,85,28, 0, 0, 0, 0, 0, "Copy UV information and textures");
- uiDefBut(block, BUT, B_COPY_TF_COL, "Copy VertCol", 809,7,103,28, 0, 0, 0, 0, 0, "Copy vertex colours");
+ uiDefBut(block, BUT, B_COPY_TF_MODE, "Copy DrawMode", 600,7,117,28, 0, 0, 0, 0, 0, "Copy the drawmode from active face to selected faces");
+ uiDefBut(block, BUT, B_COPY_TF_UV, "Copy UV+tex", 721,7,85,28, 0, 0, 0, 0, 0, "Copy UV information and textures from active face to selected faces");
+ uiDefBut(block, BUT, B_COPY_TF_COL, "Copy VertCol", 809,7,103,28, 0, 0, 0, 0, 0, "Copy vertex colours from active face to selected faces");
}
}
@@ -2429,6 +2428,9 @@ void do_uvautocalculationbuts(unsigned short event)
case B_UVAUTO_WINDOW:
if(select_area(SPACE_VIEW3D)) calculate_uv_map(event);
break;
+ case B_UVAUTO_LSCM:
+ unwrap_lscm();
+ break;
}
}
@@ -2444,28 +2446,34 @@ static void editing_panel_mesh_uvautocalculation(void)
return;
uiBlockBeginAlign(block);
- uiDefBut(block, BUT, B_UVAUTO_STD1,"Standard 1/1",100,row,200,butH, 0, 0, 0, 0, 0, "Applies standard UV mapping");
- uiDefBut(block, BUT, B_UVAUTO_STD2,"1/2",100,row-butHB,66,butH, 0, 0, 0, 0, 0, "Applies standard UV mapping 1/2");
- uiDefBut(block, BUT, B_UVAUTO_STD4,"1/4",166,row-butHB,67,butH, 0, 0, 0, 0, 0, "Applies standard UV mapping 1/4");
- uiDefBut(block, BUT, B_UVAUTO_STD8,"1/8",234,row-butHB,66,butH, 0, 0, 0, 0, 0, "Applies standard UV mapping 1/8");
+ uiDefBut(block, BUT, B_UVAUTO_LSCM,"LSCM Unwrap",100,row,200,butH, 0, 0, 0, 0, 0, "Applies conformal UV mapping, preserving local angles");
uiBlockEndAlign(block);
- row-= 2*butHB+butS;
+ row-= butHB+butS;
uiBlockBeginAlign(block);
- uiDefBut(block, BUT, B_UVAUTO_BOUNDS1,"Bounds 1/1",100,row,200,butH, 0, 0, 0, 0, 0, "Applies planar UV mapping with bounds 1/1");
- uiDefBut(block, BUT, B_UVAUTO_BOUNDS2,"1/2",100,row-butHB,66,butH, 0, 0, 0, 0, 0, "Applies planar UV mapping with bounds 1/2");
- uiDefBut(block, BUT, B_UVAUTO_BOUNDS4,"1/4",166,row-butHB,67,butH, 0, 0, 0, 0, 0, "Applies planar UV mapping with bounds 1/4");
- uiDefBut(block, BUT, B_UVAUTO_BOUNDS8,"1/8",234,row-butHB,66,butH, 0, 0, 0, 0, 0, "Applies planar UV mapping with bounds 1/8");
- uiDefBut(block, BUT, B_UVAUTO_WINDOW,"From Window",100,row-2*butH,200,butH, 0, 0, 0, 0, 0, "Applies planar UV mapping from window");
+ uiDefBut(block, BUT, B_UVAUTO_STD1,"Standard",100,row,100,butH, 0, 0, 0, 0, 0, "Applies standard UV mapping");
+ uiDefBut(block, BUT, B_UVAUTO_STD2,"/2",200,row,33,butH, 0, 0, 0, 0, 0, "Applies standard UV mapping 1/2");
+ uiDefBut(block, BUT, B_UVAUTO_STD4,"/4",233,row,34,butH, 0, 0, 0, 0, 0, "Applies standard UV mapping 1/4");
+ uiDefBut(block, BUT, B_UVAUTO_STD8,"/8",267,row,33,butH, 0, 0, 0, 0, 0, "Applies standard UV mapping 1/8");
uiBlockEndAlign(block);
- row-= 3*butHB+butS;
+ row-= butHB+butS;
+
+ uiBlockBeginAlign(block);
+ uiDefBut(block, BUT, B_UVAUTO_BOUNDS1,"Bounds",100,row,100,butH, 0, 0, 0, 0, 0, "Applies planar UV mapping with bounds 1/1");
+ uiDefBut(block, BUT, B_UVAUTO_BOUNDS2,"/2",200,row,33,butH, 0, 0, 0, 0, 0, "Applies planar UV mapping with bounds 1/2");
+ uiDefBut(block, BUT, B_UVAUTO_BOUNDS4,"/4",233,row,34,butH, 0, 0, 0, 0, 0, "Applies planar UV mapping with bounds 1/4");
+ uiDefBut(block, BUT, B_UVAUTO_BOUNDS8,"/8",267,row,33,butH, 0, 0, 0, 0, 0, "Applies planar UV mapping with bounds 1/8");
+ uiDefBut(block, BUT, B_UVAUTO_WINDOW,"From Window",100,row-butH,200,butH, 0, 0, 0, 0, 0, "Applies planar UV mapping from window");
+ uiBlockEndAlign(block);
+ row-= 2*butHB+butS;
uiBlockBeginAlign(block);
- uiDefButS(block,ROW,REDRAWVIEW3D,"No Edges",100,row,200,butH,&facesel_draw_edges, 2.0, 0, 0, 0, "Don't draw edges of deselected faces in 3D view");
- uiDefButS(block,ROW,REDRAWVIEW3D,"Draw Edges",100,row-butH,200,butH,&facesel_draw_edges, 2.0, 1.0, 0, 0, "Draw edges of deselected faces z-buffered in 3D view");
- uiDefButS(block,ROW,REDRAWVIEW3D,"All Edges",100,row-2*butH,200,butH,&facesel_draw_edges, 2.0, 2.0, 0, 0, "Draw all edges of deselected faces in 3D view");
+ uiDefButI(block, TOG|BIT|7, REDRAWVIEW3D, "Draw Faces", 100,row,200,butH, &G.f, 0, 0, 0, 0, "Displays all faces as shades");
+ uiDefButI(block,TOG|BIT|18,REDRAWVIEW3D,"Draw Edges",100,row-butHB,200,butH,&G.f, 2.0, 0, 0, 0, "Displays edges of visible faces");
+ uiDefButI(block,TOG|BIT|21,REDRAWVIEW3D,"Draw Hidden Edges",100,row-2*butHB,200,butH,&G.f, 2.0, 1.0, 0, 0, "Displays edges of hidden faces");
+ uiDefButI(block,TOG|BIT|20,REDRAWVIEW3D,"Draw Seams",100,row-3*butHB,200,butH,&G.f, 2.0, 2.0, 0, 0, "Displays UV unwrapping seams");
uiBlockEndAlign(block);
- row-= 3*butHB+butS;
+ row-= 4*butHB+butS;
row= 180;
diff --git a/source/blender/src/drawimage.c b/source/blender/src/drawimage.c
index 5155fb6e422..5f4042ee962 100644
--- a/source/blender/src/drawimage.c
+++ b/source/blender/src/drawimage.c
@@ -316,9 +316,8 @@ void draw_tfaces(void)
Mesh *me;
int a;
char col1[4], col2[4];
+ float pointsize= BIF_GetThemeValuef(TH_VERTEX_SIZE);
- glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
-
if(G.f & G_FACESELECT) {
me= get_mesh((G.scene->basact) ? (G.scene->basact->object) : 0);
if(me && me->tface) {
@@ -460,16 +459,16 @@ void draw_tfaces(void)
setlinestyle(0);
}
- /* to make sure vertices markers are visible, draw them last */
- /* we draw selected over unselected, so two loops */
- BIF_GetThemeColor3ubv(TH_VERTEX, col1);
- glColor4ubv(col1);
+ /* unselected uv's */
+ BIF_ThemeColor(TH_VERTEX);
+ glPointSize(pointsize);
+
+ bglBegin(GL_POINTS);
tface= me->tface;
mface= me->mface;
a= me->totface;
while(a--) {
if(mface->v3 && (tface->flag & TF_SELECT) ) {
- bglBegin(GL_POINTS);
if(tface->flag & TF_SEL1); else bglVertex2fv(tface->uv[0]);
if(tface->flag & TF_SEL2); else bglVertex2fv(tface->uv[1]);
@@ -477,20 +476,46 @@ void draw_tfaces(void)
if(mface->v4) {
if(tface->flag & TF_SEL4); else bglVertex2fv(tface->uv[3]);
}
- bglEnd();
}
tface++;
mface++;
}
- /* selected */
- BIF_GetThemeColor3ubv(TH_VERTEX_SELECT, col2);
- glColor4ubv(col2);
+ bglEnd();
+
+ /* pinned uv's */
+ /* give odd pointsizes odd pin pointsizes */
+ glPointSize(pointsize*2 + (((int)pointsize % 2)? (-1): 0));
+ cpack(0xFF);
+
+ bglBegin(GL_POINTS);
+ tface= me->tface;
+ mface= me->mface;
+ a= me->totface;
+ while(a--) {
+ if(mface->v3 && (tface->flag & TF_SELECT) ) {
+
+ if(tface->unwrap & TF_PIN1) bglVertex2fv(tface->uv[0]);
+ if(tface->unwrap & TF_PIN2) bglVertex2fv(tface->uv[1]);
+ if(tface->unwrap & TF_PIN3) bglVertex2fv(tface->uv[2]);
+ if(mface->v4) {
+ if(tface->unwrap & TF_PIN4) bglVertex2fv(tface->uv[3]);
+ }
+ }
+ tface++;
+ mface++;
+ }
+ bglEnd();
+
+ /* selected uv's */
+ BIF_ThemeColor(TH_VERTEX_SELECT);
+ glPointSize(pointsize);
+
+ bglBegin(GL_POINTS);
tface= me->tface;
mface= me->mface;
a= me->totface;
while(a--) {
if(mface->v3 && (tface->flag & TF_SELECT) ) {
- bglBegin(GL_POINTS);
if(tface->flag & TF_SEL1) bglVertex2fv(tface->uv[0]);
if(tface->flag & TF_SEL2) bglVertex2fv(tface->uv[1]);
@@ -498,11 +523,11 @@ void draw_tfaces(void)
if(mface->v4) {
if(tface->flag & TF_SEL4) bglVertex2fv(tface->uv[3]);
}
- bglEnd();
}
tface++;
mface++;
}
+ bglEnd();
}
}
glPointSize(1.0);
diff --git a/source/blender/src/drawmesh.c b/source/blender/src/drawmesh.c
index 0f9f8c3cfaa..b06ff19170e 100644
--- a/source/blender/src/drawmesh.c
+++ b/source/blender/src/drawmesh.c
@@ -68,7 +68,9 @@
#include "BKE_object.h"
#include "BKE_material.h"
+#include "BIF_resources.h"
#include "BIF_gl.h"
+#include "BIF_glutil.h"
#include "BIF_mywindow.h"
#include "BIF_resources.h"
@@ -83,8 +85,6 @@
//#include "glext.h"
/* some local functions */
-static void draw_hide_tfaces(Object *ob, Mesh *me);
-
#if defined(GL_EXT_texture_object) && (!defined(__sun__) || (!defined(__sun))) && !defined(__APPLE__)
/* exception for mesa... not according th opengl specs */
@@ -496,42 +496,6 @@ void spack(unsigned int ucol)
glColor3ub(cp[3], cp[2], cp[1]);
}
-static void draw_hide_tfaces(Object *ob, Mesh *me)
-{
- TFace *tface;
- MFace *mface;
- float *v1, *v2, *v3, *v4;
- int a;
-
- if(me==0 || me->tface==0) return;
-
- mface= me->mface;
- tface= me->tface;
-
- cpack(0x0);
- setlinestyle(1);
- for(a=me->totface; a>0; a--, mface++, tface++) {
- if(mface->v3==0) continue;
-
- if( (tface->flag & TF_HIDE)) {
-
- v1= (me->mvert+mface->v1)->co;
- v2= (me->mvert+mface->v2)->co;
- v3= (me->mvert+mface->v3)->co;
- if(mface->v4) v4= (me->mvert+mface->v4)->co; else v4= 0;
-
- glBegin(GL_LINE_LOOP);
- glVertex3fv( v1 );
- glVertex3fv( v2 );
- glVertex3fv( v3 );
- if(mface->v4) glVertex3fv( v4 );
- glEnd();
- }
- }
- setlinestyle(0);
-}
-
-
void draw_tfaces3D(Object *ob, Mesh *me)
{
MFace *mface;
@@ -540,26 +504,42 @@ void draw_tfaces3D(Object *ob, Mesh *me)
float *v1, *v2, *v3, *v4;
float *av1= NULL, *av2= NULL, *av3= NULL, *av4= NULL, *extverts= NULL;
int a, activeFaceInSelection= 0;
- extern short facesel_draw_edges;
+ extern void bPolygonOffset(short val);
if(me==0 || me->tface==0) return;
dl= find_displist(&ob->disp, DL_VERTS);
if (dl) extverts= dl->verts;
- /* shadow view */
- if(facesel_draw_edges>0){
- if(facesel_draw_edges==2) glDisable(GL_DEPTH_TEST);
- else glEnable(GL_DEPTH_TEST);
- cpack(0x00);
+ glEnable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ bPolygonOffset(1);
+
+ /* Draw (Hidden) Edges */
+ if(G.f & G_DRAWEDGES || G.f & G_HIDDENEDGES){
+ BIF_ThemeColor(TH_EDGE_FACESEL);
mface= me->mface;
tface= me->tface;
for(a=me->totface; a>0; a--, mface++, tface++) {
- v1= (me->mvert+mface->v1)->co;
- v2= (me->mvert+mface->v2)->co;
- v3= (me->mvert+mface->v3)->co;
- v4= mface->v4?(me->mvert+mface->v4)->co: NULL;
+ if(mface->v3==0) continue;
+ if(tface->flag & TF_HIDE) {
+ if(!(G.f & G_HIDDENEDGES)) continue;
+ }
+ else if(!(G.f & G_DRAWEDGES)) continue;
+
+ if(extverts) {
+ v1= extverts+3*mface->v1;
+ v2= extverts+3*mface->v2;
+ v3= extverts+3*mface->v3;
+ v4= mface->v4?(extverts+3*mface->v4):NULL;
+ } else {
+ v1= (me->mvert+mface->v1)->co;
+ v2= (me->mvert+mface->v2)->co;
+ v3= (me->mvert+mface->v3)->co;
+ v4= mface->v4?(me->mvert+mface->v4)->co:NULL;
+ }
+
glBegin(GL_LINE_LOOP);
glVertex3fv(v1);
glVertex3fv(v2);
@@ -569,17 +549,101 @@ void draw_tfaces3D(Object *ob, Mesh *me)
}
}
- glDisable(GL_DEPTH_TEST);
+ if(G.f & G_DRAWSEAMS) {
+ BIF_ThemeColor(TH_EDGE_SEAM);
+ glLineWidth(2);
+ glBegin(GL_LINES);
+ mface= me->mface;
+ tface= me->tface;
+ for(a=me->totface; a>0; a--, mface++, tface++) {
+ if(mface->v3==0) continue;
+ if(tface->flag & TF_HIDE) continue;
+
+ if(extverts) {
+ v1= extverts+3*mface->v1;
+ v2= extverts+3*mface->v2;
+ v3= extverts+3*mface->v3;
+ v4= mface->v4?(extverts+3*mface->v4):NULL;
+ } else {
+ v1= (me->mvert+mface->v1)->co;
+ v2= (me->mvert+mface->v2)->co;
+ v3= (me->mvert+mface->v3)->co;
+ v4= mface->v4?(me->mvert+mface->v4)->co:NULL;
+ }
+
+ if(tface->unwrap & TF_SEAM1) {
+ glVertex3fv(v1);
+ glVertex3fv(v2);
+ }
+
+ if(tface->unwrap & TF_SEAM2) {
+ glVertex3fv(v2);
+ glVertex3fv(v3);
+ }
+
+ if(tface->unwrap & TF_SEAM3) {
+ glVertex3fv(v3);
+ if(v4) glVertex3fv(v4);
+ else glVertex3fv(v1);
+ }
+
+ if(v4 && tface->unwrap & TF_SEAM4) {
+ glVertex3fv(v4);
+ glVertex3fv(v1);
+ }
+ }
+ glEnd();
+
+ glLineWidth(1);
+ }
+
+ /* Draw Selected Faces in transparent purple */
+ if(G.f & G_DRAWFACES) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ BIF_ThemeColor4(TH_FACE_SELECT);
+
+ mface= me->mface;
+ tface= me->tface;
+ for(a=me->totface; a>0; a--, mface++, tface++) {
+ if(mface->v3==0) continue;
+ if(tface->flag & TF_HIDE) continue;
+
+ if(tface->flag & TF_SELECT) {
+ if(extverts) {
+ v1= extverts+3*mface->v1;
+ v2= extverts+3*mface->v2;
+ v3= extverts+3*mface->v3;
+ v4= mface->v4?(extverts+3*mface->v4):NULL;
+ } else {
+ v1= (me->mvert+mface->v1)->co;
+ v2= (me->mvert+mface->v2)->co;
+ v3= (me->mvert+mface->v3)->co;
+ v4= mface->v4?(me->mvert+mface->v4)->co:NULL;
+ }
+
+ glBegin(v4?GL_QUADS:GL_TRIANGLES);
+ glVertex3fv( v1 );
+ glVertex3fv( v2 );
+ glVertex3fv( v3 );
+ if(v4) glVertex3fv( v4 );
+ glEnd();
+ }
+ }
+ glDisable(GL_BLEND);
+ }
+
+ /* Draw Stippled Outline for selected faces */
mface= me->mface;
tface= me->tface;
- /* SELECT faces */
+ bPolygonOffset(1);
for(a=me->totface; a>0; a--, mface++, tface++) {
if(mface->v3==0) continue;
if(tface->flag & TF_HIDE) continue;
- if( tface->flag & (TF_ACTIVE|TF_SELECT) ) {
- if (extverts) {
+ if(tface->flag & (TF_ACTIVE|TF_SELECT) ) {
+ if(extverts) {
v1= extverts+3*mface->v1;
v2= extverts+3*mface->v2;
v3= extverts+3*mface->v3;
@@ -619,7 +683,7 @@ void draw_tfaces3D(Object *ob, Mesh *me)
}
}
- /* draw active face on top */
+ /* Draw Active Face on top */
/* colors: R=x G=y */
if(av1) {
cpack(0xFF);
@@ -646,7 +710,10 @@ void draw_tfaces3D(Object *ob, Mesh *me)
setlinestyle(0);
}
- glEnable(GL_DEPTH_TEST);
+ /* We added 2 offsets, so go back 2, and disable */
+ bPolygonOffset(-1);
+ bPolygonOffset(-1);
+ bPolygonOffset(0);
}
static int set_gl_light(Object *ob)
@@ -998,16 +1065,13 @@ void draw_tface_mesh(Object *ob, Mesh *me, int dt)
glEnd();
}
}
-
+
/* switch off textures */
set_tpage(0);
}
-
glShadeModel(GL_FLAT);
glDisable(GL_CULL_FACE);
- draw_hide_tfaces(ob, me);
-
if(ob==OBACT && (G.f & G_FACESELECT)) {
draw_tfaces3D(ob, me);
}
diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c
index 87f2b1c0014..971e4222f8e 100644
--- a/source/blender/src/drawobject.c
+++ b/source/blender/src/drawobject.c
@@ -2490,6 +2490,26 @@ static void drawmeshwire(Object *ob)
}
glEnd();
}
+
+ if(handles==0 && G.f & G_DRAWSEAMS) {
+ BIF_ThemeColor(TH_EDGE_SEAM);
+ glLineWidth(2);
+
+ glBegin(GL_LINES);
+ eed= em->edges.first;
+ while(eed) {
+ if(eed->h==0 && eed->seam) {
+ glVertex3fv(eed->v1->co);
+ glVertex3fv(eed->v2->co);
+ }
+ eed= eed->next;
+ }
+ glEnd();
+
+ cpack(0x0);
+ glLineWidth(1);
+ }
+
if(ob!=G.obedit) return;
calc_meshverts();
@@ -3405,7 +3425,7 @@ static int ob_from_decimator(Object *ob)
}
/* true or false */
-static void bPolygonOffset(short val)
+void bPolygonOffset(short val)
{
static float winmat[16], ofs=0.0;
diff --git a/source/blender/src/editface.c b/source/blender/src/editface.c
index f2c6585d51e..5fe27735e12 100644
--- a/source/blender/src/editface.c
+++ b/source/blender/src/editface.c
@@ -96,7 +96,9 @@
#include "BSE_trans_types.h"
#endif /* NAN_TPT */
-TFace *lasttface=0;
+#include "BDR_unwrapper.h"
+
+TFace *lasttface=NULL;
static void uv_calc_center_vector(float *result, Object *ob, Mesh *me)
{
@@ -651,7 +653,7 @@ void select_linked_tfaces()
Mesh *me;
TFace *tface;
MFace *mface;
- int a, doit=1;
+ int a, doit=1, mark=0;
char *cpmain;
me= get_mesh(OBACT);
@@ -669,7 +671,7 @@ void select_linked_tfaces()
while(a--) {
if(tface->flag & TF_HIDE);
else if(tface->flag & TF_SELECT) {
- if( mface->v3) {
+ if(mface->v3) {
cpmain[mface->v1]= 1;
cpmain[mface->v2]= 1;
cpmain[mface->v3]= 1;
@@ -686,18 +688,30 @@ void select_linked_tfaces()
a= me->totface;
while(a--) {
if(tface->flag & TF_HIDE);
- else if((tface->flag & TF_SELECT)==0) {
- if( mface->v3) {
+ else if(mface->v3 && ((tface->flag & TF_SELECT)==0)) {
+ mark= 0;
+
+ if(!(tface->unwrap & TF_SEAM1))
+ if(cpmain[mface->v1] && cpmain[mface->v2])
+ mark= 1;
+ if(!(tface->unwrap & TF_SEAM2))
+ if(cpmain[mface->v2] && cpmain[mface->v3])
+ mark= 1;
+ if(!(tface->unwrap & TF_SEAM3)) {
if(mface->v4) {
- if(cpmain[mface->v4]) {
- tface->flag |= TF_SELECT;
- doit= 1;
- }
- }
- if( cpmain[mface->v1] || cpmain[mface->v2] || cpmain[mface->v3] ) {
- tface->flag |= TF_SELECT;
- doit= 1;
+ if(cpmain[mface->v3] && cpmain[mface->v4])
+ mark= 1;
}
+ else if(cpmain[mface->v3] && cpmain[mface->v1])
+ mark= 1;
+ }
+ if(mface->v4 && !(tface->unwrap & TF_SEAM4))
+ if(cpmain[mface->v4] && cpmain[mface->v1])
+ mark= 1;
+
+ if(mark) {
+ tface->flag |= TF_SELECT;
+ doit= 1;
}
}
tface++; mface++;
@@ -708,7 +722,6 @@ void select_linked_tfaces()
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWIMAGE, 0);
-
}
void deselectall_tface()
@@ -1024,6 +1037,7 @@ float CalcNormUV(float *a, float *b, float *c)
#define UV_STD2_MAPPING 129
#define UV_STD1_MAPPING 128
#define UV_WINDOW_MAPPING 5
+#define UV_LSCM_MAPPING 6
#define UV_CYL_EX 32
#define UV_SPHERE_EX 34
@@ -1043,6 +1057,7 @@ void uv_autocalc_tface()
MENUSTRING("Cube", UV_CUBE_MAPPING) "|"
MENUSTRING("Cylinder", UV_CYL_MAPPING) "|"
MENUSTRING("Sphere", UV_SPHERE_MAPPING) "|"
+ MENUSTRING("LSCM", UV_LSCM_MAPPING) "|"
MENUSTRING("Bounds to 1/8", UV_BOUNDS8_MAPPING) "|"
MENUSTRING("Bounds to 1/4", UV_BOUNDS4_MAPPING) "|"
MENUSTRING("Bounds to 1/2", UV_BOUNDS2_MAPPING) "|"
@@ -1079,6 +1094,8 @@ void uv_autocalc_tface()
calculate_uv_map(B_UVAUTO_STD1); break;
case UV_WINDOW_MAPPING:
calculate_uv_map(B_UVAUTO_WINDOW); break;
+ case UV_LSCM_MAPPING:
+ unwrap_lscm(); break;
}
}
@@ -1104,7 +1121,10 @@ void set_faceselect() /* toggle */
if(G.f & G_FACESELECT) {
setcursor_space(SPACE_VIEW3D, CURSOR_FACESEL);
- if(me) set_lasttface();
+ if(me) {
+ set_lasttface();
+ set_seamtface(); /* set TF_SEAM flags in tface */
+ }
}
else if((G.f & (G_WEIGHTPAINT|G_VERTEXPAINT|G_TEXTUREPAINT))==0) {
if(me) reveal_tface();
diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c
index 20455fe0b6e..f745bb44740 100644
--- a/source/blender/src/editmesh.c
+++ b/source/blender/src/editmesh.c
@@ -363,7 +363,7 @@ EditEdge *addedgelist(EditVert *v1, EditVert *v2, EditEdge *example)
/* find in hashlist */
eed= findedgelist(v1, v2);
-
+
if(eed==NULL) {
eed= (EditEdge *)calloc(sizeof(EditEdge), 1);
@@ -372,11 +372,12 @@ EditEdge *addedgelist(EditVert *v1, EditVert *v2, EditEdge *example)
BLI_addtail(&em->edges, eed);
eed->dir= swap;
insert_hashedge(eed);
- }
-
- /* copy crease data, seam flag? */
- if(example) {
- eed->crease = example->crease;
+ /* copy edge data:
+ rule is to do this with addedgelist call, before addvlaklist */
+ if(example) {
+ eed->crease= example->crease;
+ eed->seam = example->seam;
+ }
}
return eed;
@@ -452,15 +453,14 @@ EditVlak *addvlaklist(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, Ed
EditMesh *em = G.editMesh;
EditVlak *evl;
EditEdge *e1, *e2=0, *e3=0, *e4=0;
-
/* add face to list and do the edges */
- e1= addedgelist(v1, v2, example?example->e1:NULL);
- e2= addedgelist(v2, v3, example?example->e2:NULL);
- if(v4) e3= addedgelist(v3, v4, example?example->e3:NULL);
- else e3= addedgelist(v3, v1, example?example->e3:NULL);
- if(v4) e4= addedgelist(v4, v1, example?example->e4:NULL);
-
+ e1= addedgelist(v1, v2, NULL);
+ e2= addedgelist(v2, v3, NULL);
+ if(v4) e3= addedgelist(v3, v4, NULL);
+ else e3= addedgelist(v3, v1, NULL);
+ if(v4) e4= addedgelist(v4, v1, NULL);
+
if(v1==v2 || v2==v3 || v1==v3) return NULL;
if(e2==0) return NULL;
@@ -480,7 +480,7 @@ EditVlak *addvlaklist(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, Ed
evl->tf= example->tf;
evl->flag= example->flag;
}
- else {
+ else {
if (G.obedit && G.obedit->actcol)
evl->mat_nr= G.obedit->actcol-1;
default_uv(evl->tf.uv, 1.0);
@@ -488,7 +488,7 @@ EditVlak *addvlaklist(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, Ed
/* Initialize colors */
evl->tf.col[0]= evl->tf.col[1]= evl->tf.col[2]= evl->tf.col[3]= vpaint_get_current_col();
}
-
+
BLI_addtail(&em->faces, evl);
if(evl->v4) CalcNormFloat4(v1->co, v2->co, v3->co, v4->co, evl->n);
@@ -1023,6 +1023,7 @@ void make_editMesh_real(Mesh *me)
for(a=0; a<me->totedge; a++, medge++) {
eed= addedgelist(evlist[medge->v1], evlist[medge->v2], NULL);
eed->crease= ((float)medge->crease)/255.0;
+ if(medge->flag & ME_SEAM) eed->seam= 1;
}
}
@@ -1341,7 +1342,8 @@ void load_editMesh_real(Mesh *me, int undo)
medge->v2= (unsigned int) eed->v2->vn;
if(eed->f<2) medge->flag = ME_EDGEDRAW;
medge->crease= (char)(255.0*eed->crease);
-
+ if(eed->seam) medge->flag |= ME_SEAM;
+
medge++;
eed= eed->next;
}
@@ -3686,8 +3688,11 @@ short extrudeflag(short flag,short type)
if(eed->dir==1) evl2= addvlaklist(eed->v1, eed->v2, eed->v2->vn, eed->v1->vn, NULL);
else evl2= addvlaklist(eed->v2, eed->v1, eed->v1->vn, eed->v2->vn, NULL);
if (smooth) evl2->flag |= ME_SMOOTH;
-
- /* new edges, needs copied from old edge. actually we should find face that has this edge */
+
+ /* Needs smarter adaption of existing creases.
+ * If addedgelist is used, make sure seams are set to 0 on these
+ * new edges, since we do not want to add any seams on extrusion.
+ */
evl2->e1->crease= eed->crease;
evl2->e2->crease= eed->crease;
evl2->e3->crease= eed->crease;
@@ -3876,7 +3881,6 @@ short removedoublesflag(short flag, float limit) /* return amount */
if(eed->v1->f & 128) eed->v1= eed->v1->vn;
if(eed->v2->f & 128) eed->v2= eed->v2->vn;
-
e1= addedgelist(eed->v1, eed->v2, eed);
if(e1) e1->f= 1;
@@ -4187,12 +4191,30 @@ static void uv_quart(float *uv, float *uv1)
uv[1]= (uv1[1]+uv1[3]+uv1[5]+uv1[7])/4.0;
}
-static void set_wuv(int tot, EditVlak *evl, int v1, int v2, int v3, int v4)
+static void vlak_pin_vertex(EditVlak *evl, EditVert *vertex)
+{
+ if(evl->v1 == vertex) evl->tf.unwrap |= TF_PIN1;
+ else if(evl->v2 == vertex) evl->tf.unwrap |= TF_PIN2;
+ else if(evl->v3 == vertex) evl->tf.unwrap |= TF_PIN3;
+ else if(evl->v4 && vertex && evl->v4 == vertex) evl->tf.unwrap |= TF_PIN4;
+}
+
+static void set_wuv(int tot, EditVlak *evl, int v1, int v2, int v3, int v4, EditVlak *evlpin)
{
/* this weird function only to be used for subdivide, the 'w' in the name has no meaning! */
float *uv, uvo[4][2];
unsigned int *col, colo[4], col1, col2;
int a, v;
+
+ /* recover pinning */
+ if(evlpin){
+ evl->tf.unwrap= 0;
+ if(evlpin->tf.unwrap & TF_PIN1) vlak_pin_vertex(evl, evlpin->v1);
+ if(evlpin->tf.unwrap & TF_PIN2) vlak_pin_vertex(evl, evlpin->v2);
+ if(evlpin->tf.unwrap & TF_PIN3) vlak_pin_vertex(evl, evlpin->v3);
+ if(evlpin->tf.unwrap & TF_PIN4) vlak_pin_vertex(evl, evlpin->v4);
+ }
+
/* Numbers corespond to verts (corner points), */
/* edge->vn's (center edges), the Center */
memcpy(uvo, evl->tf.uv, sizeof(uvo)); /* And the quincunx points of a face */
@@ -4311,7 +4333,7 @@ static EditVert *vert_from_number(EditVlak *evl, int nr)
return NULL;
}
-static void addvlak_subdiv(EditVlak *evl, int val1, int val2, int val3, int val4, EditVert *eve)
+static void addvlak_subdiv(EditVlak *evl, int val1, int val2, int val3, int val4, EditVert *eve, EditVlak *evlpin)
{
EditVlak *w;
EditVert *v1, *v2, *v3, *v4;
@@ -4330,8 +4352,8 @@ static void addvlak_subdiv(EditVlak *evl, int val1, int val2, int val3, int val4
w= addvlaklist(v1, v2, v3, v4, evl);
if(w) {
- if(evl->v4) set_wuv(4, w, val1, val2, val3, val4);
- else set_wuv(3, w, val1, val2, val3, val4);
+ if(evl->v4) set_wuv(4, w, val1, val2, val3, val4, evlpin);
+ else set_wuv(3, w, val1, val2, val3, val4, evlpin);
}
}
@@ -4404,7 +4426,7 @@ void subdivideflag(int flag, float rad, int beauty)
extern float doublimit;
EditVert *eve;
EditEdge *eed, *e1, *e2, *e3, *e4, *nexted;
- EditVlak *evl;
+ EditVlak *evl, evlpin;
float fac, vec[3], vec1[3], len1, len2, len3, percent;
short test;
@@ -4534,6 +4556,9 @@ void subdivideflag(int flag, float rad, int beauty)
evl= em->faces.last;
while(evl) {
+
+ evlpin= *evl; /* make a copy of evl to recover uv pinning later */
+
if( vlakselectedOR(evl, flag) ) {
e1= evl->e1;
e2= evl->e2;
@@ -4542,67 +4567,79 @@ void subdivideflag(int flag, float rad, int beauty)
test= 0;
if(e1 && e1->vn) {
- test+= 1;
+ test+= 1;
e1->f= 1;
+ /* add edges here, to copy correct edge data */
+ eed= addedgelist(e1->v1, e1->vn, e1);
+ eed= addedgelist(e1->vn, e1->v2, e1);
}
- if(e2 && e2->vn) {
- test+= 2;
+ if(e2 && e2->vn) {
+ test+= 2;
e2->f= 1;
+ /* add edges here, to copy correct edge data */
+ eed= addedgelist(e2->v1, e2->vn, e2);
+ eed= addedgelist(e2->vn, e2->v2, e2);
}
- if(e3 && e3->vn) {
- test+= 4;
+ if(e3 && e3->vn) {
+ test+= 4;
e3->f= 1;
+ /* add edges here, to copy correct edge data */
+ eed= addedgelist(e3->v1, e3->vn, e3);
+ eed= addedgelist(e3->vn, e3->v2, e3);
}
- if(e4 && e4->vn) {
- test+= 8;
+ if(e4 && e4->vn) {
+ test+= 8;
e4->f= 1;
+ /* add edges here, to copy correct edge data */
+ eed= addedgelist(e4->v1, e4->vn, e4);
+ eed= addedgelist(e4->vn, e4->v2, e4);
}
if(test) {
if(evl->v4==0) { /* All the permutations of 3 edges*/
- if((test & 3)==3) addvlak_subdiv(evl, 2, 2+4, 1+4, 0, 0);
- if((test & 6)==6) addvlak_subdiv(evl, 3, 3+4, 2+4, 0, 0);
- if((test & 5)==5) addvlak_subdiv(evl, 1, 1+4, 3+4, 0, 0);
+ if((test & 3)==3) addvlak_subdiv(evl, 2, 2+4, 1+4, 0, 0, &evlpin);
+ if((test & 6)==6) addvlak_subdiv(evl, 3, 3+4, 2+4, 0, 0, &evlpin);
+ if((test & 5)==5) addvlak_subdiv(evl, 1, 1+4, 3+4, 0, 0, &evlpin);
if(test==7) { /* four new faces, old face renews */
evl->v1= e1->vn;
evl->v2= e2->vn;
evl->v3= e3->vn;
- set_wuv(3, evl, 1+4, 2+4, 3+4, 0);
+ set_wuv(3, evl, 1+4, 2+4, 3+4, 0, &evlpin);
}
else if(test==3) {
- addvlak_subdiv(evl, 1+4, 2+4, 3, 0, 0);
+ addvlak_subdiv(evl, 1+4, 2+4, 3, 0, 0, &evlpin);
evl->v2= e1->vn;
- set_wuv(3, evl, 1, 1+4, 3, 0);
+ set_wuv(3, evl, 1, 1+4, 3, 0, &evlpin);
}
else if(test==6) {
- addvlak_subdiv(evl, 2+4, 3+4, 1, 0, 0);
+ addvlak_subdiv(evl, 2+4, 3+4, 1, 0, 0, &evlpin);
evl->v3= e2->vn;
- set_wuv(3, evl, 1, 2, 2+4, 0);
+ set_wuv(3, evl, 1, 2, 2+4, 0, &evlpin);
}
else if(test==5) {
- addvlak_subdiv(evl, 3+4, 1+4, 2, 0, 0);
+ addvlak_subdiv(evl, 3+4, 1+4, 2, 0, 0, &evlpin);
evl->v1= e3->vn;
- set_wuv(3, evl, 3+4, 2, 3, 0);
+ set_wuv(3, evl, 3+4, 2, 3, 0, &evlpin);
}
else if(test==1) {
- addvlak_subdiv(evl, 1+4, 2, 3, 0, 0);
+ addvlak_subdiv(evl, 1+4, 2, 3, 0, 0, &evlpin);
evl->v2= e1->vn;
- set_wuv(3, evl, 1, 1+4, 3, 0);
+ set_wuv(3, evl, 1, 1+4, 3, 0, &evlpin);
}
else if(test==2) {
- addvlak_subdiv(evl, 2+4, 3, 1, 0, 0);
+ addvlak_subdiv(evl, 2+4, 3, 1, 0, 0, &evlpin);
evl->v3= e2->vn;
- set_wuv(3, evl, 1, 2, 2+4, 0);
+ set_wuv(3, evl, 1, 2, 2+4, 0, &evlpin);
}
else if(test==4) {
- addvlak_subdiv(evl, 3+4, 1, 2, 0, 0);
+ addvlak_subdiv(evl, 3+4, 1, 2, 0, 0, &evlpin);
evl->v1= e3->vn;
- set_wuv(3, evl, 3+4, 2, 3, 0);
+ set_wuv(3, evl, 3+4, 2, 3, 0, &evlpin);
}
- evl->e1= addedgelist(evl->v1, evl->v2, evl->e1);
- evl->e2= addedgelist(evl->v2, evl->v3, evl->e2);
- evl->e3= addedgelist(evl->v3, evl->v1, evl->e3);
-
+ evl->e1= addedgelist(evl->v1, evl->v2, NULL);
+ evl->e2= addedgelist(evl->v2, evl->v3, NULL);
+ evl->e3= addedgelist(evl->v3, evl->v1, NULL);
+
}
else { /* All the permutations of 4 faces */
if(test==15) {
@@ -4615,170 +4652,170 @@ void subdivideflag(int flag, float rad, int beauty)
eve= addvertlist(vec);
eve->f |= flag;
-
- addvlak_subdiv(evl, 2, 2+4, 9, 1+4, eve);
- addvlak_subdiv(evl, 3, 3+4, 9, 2+4, eve);
- addvlak_subdiv(evl, 4, 4+4, 9, 3+4, eve);
+
+ addvlak_subdiv(evl, 2, 2+4, 9, 1+4, eve, &evlpin);
+ addvlak_subdiv(evl, 3, 3+4, 9, 2+4, eve, &evlpin);
+ addvlak_subdiv(evl, 4, 4+4, 9, 3+4, eve, &evlpin);
evl->v2= e1->vn;
evl->v3= eve;
evl->v4= e4->vn;
- set_wuv(4, evl, 1, 1+4, 9, 4+4);
+ set_wuv(4, evl, 1, 1+4, 9, 4+4, &evlpin);
}
- else {
- if(((test & 3)==3)&&(test!=3)) addvlak_subdiv(evl, 1+4, 2, 2+4, 0, 0);
- if(((test & 6)==6)&&(test!=6)) addvlak_subdiv(evl, 2+4, 3, 3+4, 0, 0);
- if(((test & 12)==12)&&(test!=12)) addvlak_subdiv(evl, 3+4, 4, 4+4, 0, 0);
- if(((test & 9)==9)&&(test!=9)) addvlak_subdiv(evl, 4+4, 1, 1+4, 0, 0);
-
+ else {
+ if(((test & 3)==3)&&(test!=3)) addvlak_subdiv(evl, 1+4, 2, 2+4, 0, 0, &evlpin);
+ if(((test & 6)==6)&&(test!=6)) addvlak_subdiv(evl, 2+4, 3, 3+4, 0, 0, &evlpin);
+ if(((test & 12)==12)&&(test!=12)) addvlak_subdiv(evl, 3+4, 4, 4+4, 0, 0, &evlpin);
+ if(((test & 9)==9)&&(test!=9)) addvlak_subdiv(evl, 4+4, 1, 1+4, 0, 0, &evlpin);
+
if(test==1) { /* Edge 1 has new vert */
- addvlak_subdiv(evl, 1+4, 2, 3, 0, 0);
- addvlak_subdiv(evl, 1+4, 3, 4, 0, 0);
+ addvlak_subdiv(evl, 1+4, 2, 3, 0, 0, &evlpin);
+ addvlak_subdiv(evl, 1+4, 3, 4, 0, 0, &evlpin);
evl->v2= e1->vn;
evl->v3= evl->v4;
evl->v4= 0;
- set_wuv(4, evl, 1, 1+4, 4, 0);
+ set_wuv(4, evl, 1, 1+4, 4, 0, &evlpin);
}
else if(test==2) { /* Edge 2 has new vert */
- addvlak_subdiv(evl, 2+4, 3, 4, 0, 0);
- addvlak_subdiv(evl, 2+4, 4, 1, 0, 0);
+ addvlak_subdiv(evl, 2+4, 3, 4, 0, 0, &evlpin);
+ addvlak_subdiv(evl, 2+4, 4, 1, 0, 0, &evlpin);
evl->v3= e2->vn;
evl->v4= 0;
- set_wuv(4, evl, 1, 2, 2+4, 0);
+ set_wuv(4, evl, 1, 2, 2+4, 0, &evlpin);
}
else if(test==4) { /* Edge 3 has new vert */
- addvlak_subdiv(evl, 3+4, 4, 1, 0, 0);
- addvlak_subdiv(evl, 3+4, 1, 2, 0, 0);
+ addvlak_subdiv(evl, 3+4, 4, 1, 0, 0, &evlpin);
+ addvlak_subdiv(evl, 3+4, 1, 2, 0, 0, &evlpin);
evl->v1= evl->v2;
evl->v2= evl->v3;
evl->v3= e3->vn;
evl->v4= 0;
- set_wuv(4, evl, 2, 3, 3+4, 0);
+ set_wuv(4, evl, 2, 3, 3+4, 0, &evlpin);
}
else if(test==8) { /* Edge 4 has new vert */
- addvlak_subdiv(evl, 4+4, 1, 2, 0, 0);
- addvlak_subdiv(evl, 4+4, 2, 3, 0, 0);
+ addvlak_subdiv(evl, 4+4, 1, 2, 0, 0, &evlpin);
+ addvlak_subdiv(evl, 4+4, 2, 3, 0, 0, &evlpin);
evl->v1= evl->v3;
evl->v2= evl->v4;
evl->v3= e4->vn;
evl->v4= 0;
- set_wuv(4, evl, 3, 4, 4+4, 0);
+ set_wuv(4, evl, 3, 4, 4+4, 0, &evlpin);
}
else if(test==3) { /*edge 1&2 */
- /* make new vert in center of new edge */
+ /* make new vert in center of new edge */
vec[0]=(e1->vn->co[0]+e2->vn->co[0])/2;
vec[1]=(e1->vn->co[1]+e2->vn->co[1])/2;
vec[2]=(e1->vn->co[2]+e2->vn->co[2])/2;
eve= addvertlist(vec);
eve->f |= flag;
/* Add new faces */
- addvlak_subdiv(evl, 4, 10, 2+4, 3, eve);
- addvlak_subdiv(evl, 4, 1, 1+4, 10, eve);
+ addvlak_subdiv(evl, 4, 10, 2+4, 3, eve, &evlpin);
+ addvlak_subdiv(evl, 4, 1, 1+4, 10, eve, &evlpin);
/* orig face becomes small corner */
evl->v1=e1->vn;
//evl->v2=evl->v2;
evl->v3=e2->vn;
evl->v4=eve;
-
- set_wuv(4, evl, 1+4, 2, 2+4, 10);
+
+ set_wuv(4, evl, 1+4, 2, 2+4, 10, &evlpin);
}
else if(test==6) { /* 2&3 */
- /* make new vert in center of new edge */
+ /* make new vert in center of new edge */
vec[0]=(e2->vn->co[0]+e3->vn->co[0])/2;
vec[1]=(e2->vn->co[1]+e3->vn->co[1])/2;
vec[2]=(e2->vn->co[2]+e3->vn->co[2])/2;
eve= addvertlist(vec);
eve->f |= flag;
/*New faces*/
- addvlak_subdiv(evl, 1, 11, 3+4, 4, eve);
- addvlak_subdiv(evl, 1, 2, 2+4, 11, eve);
+ addvlak_subdiv(evl, 1, 11, 3+4, 4, eve, &evlpin);
+ addvlak_subdiv(evl, 1, 2, 2+4, 11, eve, &evlpin);
/* orig face becomes small corner */
evl->v1=e2->vn;
evl->v2=evl->v3;
evl->v3=e3->vn;
evl->v4=eve;
-
- set_wuv(4, evl, 2+4, 3, 3+4, 11);
+
+ set_wuv(4, evl, 2+4, 3, 3+4, 11, &evlpin);
}
else if(test==12) { /* 3&4 */
- /* make new vert in center of new edge */
+ /* make new vert in center of new edge */
vec[0]=(e3->vn->co[0]+e4->vn->co[0])/2;
vec[1]=(e3->vn->co[1]+e4->vn->co[1])/2;
vec[2]=(e3->vn->co[2]+e4->vn->co[2])/2;
eve= addvertlist(vec);
eve->f |= flag;
/*New Faces*/
- addvlak_subdiv(evl, 2, 12, 4+4, 1, eve);
- addvlak_subdiv(evl, 2, 3, 3+4, 12, eve);
+ addvlak_subdiv(evl, 2, 12, 4+4, 1, eve, &evlpin);
+ addvlak_subdiv(evl, 2, 3, 3+4, 12, eve, &evlpin);
/* orig face becomes small corner */
evl->v1=e3->vn;
evl->v2=evl->v4;
evl->v3=e4->vn;
evl->v4=eve;
-
- set_wuv(4, evl, 3+4, 4, 4+4, 12);
+
+ set_wuv(4, evl, 3+4, 4, 4+4, 12, &evlpin);
}
else if(test==9) { /* 4&1 */
- /* make new vert in center of new edge */
+ /* make new vert in center of new edge */
vec[0]=(e1->vn->co[0]+e4->vn->co[0])/2;
vec[1]=(e1->vn->co[1]+e4->vn->co[1])/2;
vec[2]=(e1->vn->co[2]+e4->vn->co[2])/2;
eve= addvertlist(vec);
eve->f |= flag;
/*New Faces*/
- addvlak_subdiv(evl, 3, 13, 1+4, 2, eve);
- addvlak_subdiv(evl, 3, 4, 4+4, 13, eve);
+ addvlak_subdiv(evl, 3, 13, 1+4, 2, eve, &evlpin);
+ addvlak_subdiv(evl, 3, 4, 4+4,13, eve, &evlpin);
/* orig face becomes small corner */
evl->v2=evl->v1;
evl->v1=e4->vn;
evl->v3=e1->vn;
evl->v4=eve;
-
- set_wuv(4, evl, 4+4, 1, 1+4, 13);
+
+ set_wuv(4, evl, 4+4, 1, 1+4, 13, &evlpin);
}
else if(test==5) { /* 1&3 */
- addvlak_subdiv(evl, 1+4, 2, 3, 3+4, 0);
+ addvlak_subdiv(evl, 1+4, 2, 3, 3+4, 0, &evlpin);
evl->v2= e1->vn;
evl->v3= e3->vn;
- set_wuv(4, evl, 1, 1+4, 3+4, 4);
+ set_wuv(4, evl, 1, 1+4, 3+4, 4, &evlpin);
}
else if(test==10) { /* 2&4 */
- addvlak_subdiv(evl, 2+4, 3, 4, 4+4, 0);
+ addvlak_subdiv(evl, 2+4, 3, 4, 4+4, 0, &evlpin);
evl->v3= e2->vn;
evl->v4= e4->vn;
- set_wuv(4, evl, 1, 2, 2+4, 4+4);
+ set_wuv(4, evl, 1, 2, 2+4, 4+4, &evlpin);
}/* Unfortunately, there is no way to avoid tris on 1 or 3 edges*/
else if(test==7) { /*1,2&3 */
- addvlak_subdiv(evl, 1+4, 2+4, 3+4, 0, 0);
+ addvlak_subdiv(evl, 1+4, 2+4, 3+4, 0, 0, &evlpin);
evl->v2= e1->vn;
evl->v3= e3->vn;
- set_wuv(4, evl, 1, 1+4, 3+4, 4);
+ set_wuv(4, evl, 1, 1+4, 3+4, 4, &evlpin);
}
else if(test==14) { /* 2,3&4 */
- addvlak_subdiv(evl, 2+4, 3+4, 4+4, 0, 0);
+ addvlak_subdiv(evl, 2+4, 3+4, 4+4, 0, 0, &evlpin);
evl->v3= e2->vn;
evl->v4= e4->vn;
- set_wuv(4, evl, 1, 2, 2+4, 4+4);
+ set_wuv(4, evl, 1, 2, 2+4, 4+4, &evlpin);
}
else if(test==13) {/* 1,3&4 */
- addvlak_subdiv(evl, 3+4, 4+4, 1+4, 0, 0);
+ addvlak_subdiv(evl, 3+4, 4+4, 1+4, 0, 0, &evlpin);
evl->v4= e3->vn;
evl->v1= e1->vn;
- set_wuv(4, evl, 1+4, 3, 3, 3+4);
+ set_wuv(4, evl, 1+4, 3, 3, 3+4, &evlpin);
}
else if(test==11) { /* 1,2,&4 */
- addvlak_subdiv(evl, 4+4, 1+4, 2+4, 0, 0);
+ addvlak_subdiv(evl, 4+4, 1+4, 2+4, 0, 0, &evlpin);
evl->v1= e4->vn;
evl->v2= e2->vn;
- set_wuv(4, evl, 4+4, 2+4, 3, 4);
+ set_wuv(4, evl, 4+4, 2+4, 3, 4, &evlpin);
}
}
- evl->e1= addedgelist(evl->v1, evl->v2, evl->e1);
- evl->e2= addedgelist(evl->v2, evl->v3, evl->e2);
- if(evl->v4) evl->e3= addedgelist(evl->v3, evl->v4, evl->e3);
- else evl->e3= addedgelist(evl->v3, evl->v1, evl->e3);
- if(evl->v4) evl->e4= addedgelist(evl->v4, evl->v1, evl->e4);
+ evl->e1= addedgelist(evl->v1, evl->v2, NULL);
+ evl->e2= addedgelist(evl->v2, evl->v3, NULL);
+ if(evl->v4) evl->e3= addedgelist(evl->v3, evl->v4, NULL);
+ else evl->e3= addedgelist(evl->v3, evl->v1, NULL);
+ if(evl->v4) evl->e4= addedgelist(evl->v4, evl->v1, NULL);
else evl->e4= NULL;
}
}
@@ -8900,6 +8937,7 @@ void bevel_mesh(float bsize, int allfaces)
#endif
}
+ /* Needs better adaption of creases? */
addedgelist(evl->e1->v1->vn, evl->e1->v2->vn, evl->e1);
addedgelist(evl->e2->v1->vn,evl->e2->v2->vn, evl->e2);
addedgelist(evl->e3->v1->vn,evl->e3->v2->vn, evl->e3);
@@ -9832,3 +9870,58 @@ void editmesh_deselect_by_material(int index) {
}
}
}
+
+void editmesh_mark_seam(int clear)
+{
+ EditMesh *em= G.editMesh;
+ EditEdge *eed;
+ Mesh *me= G.obedit->data;
+
+ /* auto-enable seams drawing */
+ if(clear==0) {
+ if(!(G.f & G_DRAWSEAMS)) {
+ G.f |= G_DRAWSEAMS;
+ allqueue(REDRAWBUTSEDIT, 0);
+ }
+ if(!me->medge)
+ me->medge= MEM_callocN(sizeof(MEdge), "fake mesh edge");
+ }
+
+ if(clear) {
+ eed= em->edges.first;
+ while(eed) {
+ if((eed->h==0) && (eed->v1->f & 1) && (eed->v2->f & 1)) {
+ eed->seam = 0;
+ }
+ eed= eed->next;
+ }
+ }
+ else {
+ eed= em->edges.first;
+ while(eed) {
+ if((eed->h==0) && (eed->v1->f & 1) && (eed->v2->f & 1)) {
+ eed->seam = 1;
+ }
+ eed= eed->next;
+ }
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+void Edge_Menu() {
+ short ret;
+
+ ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2");
+
+ switch(ret)
+ {
+ case 1:
+ editmesh_mark_seam(0);
+ break;
+ case 2:
+ editmesh_mark_seam(1);
+ break;
+ }
+}
+
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
index 0a995064bda..39cd046b5bd 100644
--- a/source/blender/src/editobject.c
+++ b/source/blender/src/editobject.c
@@ -143,6 +143,7 @@
#include "BDR_editobject.h"
#include "BDR_drawobject.h"
#include "BDR_editcurve.h"
+#include "BDR_unwrapper.h"
#include "render.h"
#include <time.h>
@@ -1097,8 +1098,11 @@ void exit_editmode(int freedata) /* freedata==0 at render */
load_editMesh(); /* makes new displist */
if(freedata) free_editMesh();
-
- if(G.f & G_FACESELECT) allqueue(REDRAWIMAGE, 0);
+
+ if(G.f & G_FACESELECT) {
+ set_seamtface();
+ allqueue(REDRAWIMAGE, 0);
+ }
build_particle_system(G.obedit);
}
diff --git a/source/blender/src/editsima.c b/source/blender/src/editsima.c
index 9e3558be259..a55de075504 100644
--- a/source/blender/src/editsima.c
+++ b/source/blender/src/editsima.c
@@ -79,6 +79,7 @@
#include "BSE_trans_types.h"
#include "BDR_editobject.h"
+#include "BDR_unwrapper.h"
#include "blendef.h"
#include "mydevice.h"
@@ -1682,3 +1683,34 @@ void toggle_uv_select(int mode)
allqueue(REDRAWIMAGE, 0);
}
+void pin_tface_uv(int mode)
+{
+ Mesh *me;
+ TFace *tface;
+ MFace *mface;
+ int a;
+
+ if( is_uv_tface_editing_allowed()==0 ) return;
+ me= get_mesh(OBACT);
+
+ mface= me->mface;
+ tface= me->tface;
+ for(a=me->totface; a>0; a--, tface++, mface++) {
+ if(mode ==1){
+ if(tface->flag & TF_SEL1) tface->unwrap |= TF_PIN1;
+ if(tface->flag & TF_SEL2) tface->unwrap |= TF_PIN2;
+ if(tface->flag & TF_SEL3) tface->unwrap |= TF_PIN3;
+ if(mface->v4)
+ if(tface->flag & TF_SEL4) tface->unwrap |= TF_PIN4;
+ }
+ else if (mode ==0){
+ if(tface->flag & TF_SEL1) tface->unwrap &= ~TF_PIN1;
+ if(tface->flag & TF_SEL2) tface->unwrap &= ~TF_PIN2;
+ if(tface->flag & TF_SEL3) tface->unwrap &= ~TF_PIN3;
+ if(mface->v4)
+ if(tface->flag & TF_SEL4) tface->unwrap &= ~TF_PIN4;
+ }
+ }
+ scrarea_queue_winredraw(curarea);
+}
+
diff --git a/source/blender/src/header_image.c b/source/blender/src/header_image.c
index b110a3d9a2c..bcf4fcaa334 100644
--- a/source/blender/src/header_image.c
+++ b/source/blender/src/header_image.c
@@ -62,6 +62,7 @@
#include "DNA_userdef_types.h"
#include "BDR_drawmesh.h"
+#include "BDR_unwrapper.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_main.h"
@@ -816,8 +817,6 @@ static uiBlock *image_uvs_transformmenu(void *arg_unused)
static void do_image_uvsmenu(void *arg, int event)
{
- ScrArea *sa;
-
/* events >=20 are registered bpython scripts */
if (event >= 20) BPY_menu_do_python(PYMENU_UV, event - 20);
@@ -847,6 +846,16 @@ static void do_image_uvsmenu(void *arg, int event)
if(G.sima->flag & SI_NOPIXELSNAP) G.sima->flag &= ~SI_NOPIXELSNAP;
else G.sima->flag |= SI_NOPIXELSNAP;
break;
+ case 8:
+ pin_tface_uv(1);
+ break;
+ case 9:
+ pin_tface_uv(0);
+ break;
+ case 10:
+ if (okee("LSCM unwrap"))
+ unwrap_lscm();
+ break;
}
}
@@ -873,6 +882,12 @@ 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, "Unpin|Alt P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Pin|P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "LSCM Unwrap|E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 10, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
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 aaf063d28d1..badbef1b450 100644
--- a/source/blender/src/header_view3d.c
+++ b/source/blender/src/header_view3d.c
@@ -1938,6 +1938,12 @@ void do_view3d_edit_mesh_edgesmenu(void *arg, int event)
case 6:
bevel_menu();
break;
+ case 7: /* Mark Seam */
+ editmesh_mark_seam(0);
+ break;
+ case 8: /* Clear Seam */
+ editmesh_mark_seam(1);
+ break;
}
allqueue(REDRAWVIEW3D, 0);
}
@@ -1964,6 +1970,11 @@ static uiBlock *view3d_edit_mesh_edgesmenu(void *arg_unused)
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide Fractal|W, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide Smooth|W, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Mark Seam|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear Seam|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
+
uiBlockSetDirection(block, UI_RIGHT);
uiTextBoundsBlock(block, 60);
return block;
diff --git a/source/blender/src/resources.c b/source/blender/src/resources.c
index 78d01e6b9ea..028cec1a5d2 100644
--- a/source/blender/src/resources.c
+++ b/source/blender/src/resources.c
@@ -428,6 +428,10 @@ char *BIF_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
cp= ts->edge; break;
case TH_EDGE_SELECT:
cp= ts->edge_select; break;
+ case TH_EDGE_SEAM:
+ cp= ts->edge_seam; break;
+ case TH_EDGE_FACESEL:
+ cp= ts->edge_facesel; break;
case TH_FACE:
cp= ts->face; break;
case TH_FACE_SELECT:
@@ -502,6 +506,8 @@ void BIF_InitTheme(void)
btheme->tv3d.vertex_size= 2;
SETCOL(btheme->tv3d.edge, 0x0, 0x0, 0x0, 255);
SETCOL(btheme->tv3d.edge_select, 0x90, 0x90, 0x30, 255);
+ SETCOL(btheme->tv3d.edge_seam, 230, 150, 50, 255);
+ SETCOL(btheme->tv3d.edge_facesel, 75, 75, 75, 255);
SETCOL(btheme->tv3d.face, 0, 50, 150, 30);
SETCOL(btheme->tv3d.face_select, 200, 100, 200, 60);
@@ -648,6 +654,8 @@ char *BIF_ThemeColorsPup(int spacetype)
sprintf(str, "Vertex Selected %%x%d|", TH_VERTEX_SELECT); strcat(cp, str);
sprintf(str, "Vertex Size %%x%d|", TH_VERTEX_SIZE); strcat(cp, str);
sprintf(str, "Edge Selected %%x%d|", TH_EDGE_SELECT); strcat(cp, str);
+ sprintf(str, "Edge Seam %%x%d|", TH_EDGE_SEAM); strcat(cp, str);
+ sprintf(str, "Edge UV Face Select %%x%d|", TH_EDGE_FACESEL); strcat(cp, str);
sprintf(str, "Face %%x%d|", TH_FACE); strcat(cp, str);
sprintf(str, "Face Selected %%x%d", TH_FACE_SELECT); strcat(cp, str);
}
diff --git a/source/blender/src/space.c b/source/blender/src/space.c
index a35de2087f5..8683d66e232 100644
--- a/source/blender/src/space.c
+++ b/source/blender/src/space.c
@@ -128,6 +128,7 @@
#include "BDR_editface.h"
#include "BDR_drawmesh.h"
#include "BDR_drawobject.h"
+#include "BDR_unwrapper.h"
#include "BLO_readfile.h" /* for BLO_blendhandle_close */
@@ -1015,11 +1016,15 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
extrude_ika(ob, 1);
}
}
- if (G.qual == LR_SHIFTKEY) {
- if (G.obedit && G.obedit->type==OB_MESH) {
- transform('e');
- }
- }
+ else if (G.qual==LR_CTRLKEY) {
+ if(G.obedit && G.obedit->type==OB_MESH)
+ Edge_Menu();
+ }
+ else if (G.qual==LR_SHIFTKEY) {
+ if (G.obedit && G.obedit->type==OB_MESH) {
+ transform('e');
+ }
+ }
break;
case FKEY:
if(G.obedit) {
@@ -3419,6 +3424,10 @@ void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
else
toggle_uv_select('f');
break;
+ case EKEY :
+ if (okee("LSCM unwrap"))
+ unwrap_lscm();
+ break;
case GKEY:
if((G.qual==0))
transform_tface_uv('g');
@@ -3457,6 +3466,12 @@ void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
G.f |= G_PROPORTIONAL;
}
break;
+ case PKEY:
+ if(G.qual==LR_ALTKEY)
+ pin_tface_uv(0);
+ else
+ pin_tface_uv(1);
+ break;
case RKEY:
if((G.qual==0))
transform_tface_uv('r');
diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c
index c2422434562..188499378af 100644
--- a/source/blender/src/toolbox.c
+++ b/source/blender/src/toolbox.c
@@ -1712,6 +1712,9 @@ static TBitem tb_mesh_edit_edge[]= {
{ 0, "Subdivide|W, 1", 2, NULL},
{ 0, "Subdivide Fractal|W, 2", 1, NULL},
{ 0, "Subdivide Smooth|W, 3", 0, NULL},
+{ 0, "SEPR", 0, NULL},
+{ 0, "Mark Seam|Ctrl E", 7, NULL},
+{ 0, "Clear Seam|Ctrl E", 8, NULL},
{ -1, "", 0, do_view3d_edit_mesh_edgesmenu}};
static TBitem tb_mesh_edit_face[]= {
diff --git a/source/blender/src/unwrapper.c b/source/blender/src/unwrapper.c
new file mode 100644
index 00000000000..13c31b308e6
--- /dev/null
+++ b/source/blender/src/unwrapper.c
@@ -0,0 +1,1159 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_utildefines.h"
+
+#include "BLI_arithb.h"
+
+#include "BIF_space.h"
+
+#include "blendef.h"
+#include "mydevice.h"
+
+#include "ONL_opennl.h"
+#include "BDR_unwrapper.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;
+}
+
+/* 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;
+ char *cpmain;
+ int doit, mark;
+
+ if(!me || !me->tface) return 0;
+
+ groups= (int*)MEM_callocN(sizeof(int)*me->totface, "SeamGroups");
+ cpmain= (char*)MEM_mallocN(me->totvert, "cpmain");
+
+ 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;
+ gid++;
+ *gface= gid;
+ mark= 0;
+ doit= 1;
+ memset(cpmain, 0, me->totvert);
+
+ 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 && mf->v3) {
+ cpmain[mf->v1]= 1;
+ cpmain[mf->v2]= 1;
+ cpmain[mf->v3]= 1;
+ if(mf->v4) cpmain[mf->v4]= 1;
+ }
+ 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 && mf->v3 && *gf==0) {
+ mark= 0;
+
+ if(!(tf->unwrap & TF_SEAM1))
+ if(cpmain[mf->v1] && cpmain[mf->v2])
+ mark= 1;
+ if(!(tf->unwrap & TF_SEAM2))
+ if(cpmain[mf->v2] && cpmain[mf->v3])
+ mark= 1;
+ if(!(tf->unwrap & TF_SEAM3)) {
+ if(mf->v4) {
+ if(cpmain[mf->v3] && cpmain[mf->v4])
+ mark= 1;
+ }
+ else if(cpmain[mf->v3] && cpmain[mf->v1])
+ mark= 1;
+ }
+ if(mf->v4 && !(tf->unwrap & TF_SEAM4))
+ if(cpmain[mf->v4] && cpmain[mf->v1])
+ mark= 1;
+
+ if(mark) {
+ *gf= gid;
+ doit= 1;
+ }
+ }
+ tf++; mf++; gf++;
+ }
+ }
+ }
+ *seamgroups= groups;
+
+ MEM_freeN(cpmain);
+ 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 int lscm_build_vertex_data(Mesh *me, int *groups, int gid, LscmVert **lscm_vertices, LscmVert ***sort_vertices)
+{
+ MFace *mf;
+ TFace *tf;
+ int *gf, totvert, a;
+ LscmVert *lscmvert, **sortvert;
+ LscmVert *v1, *v2, *v3, **sv1, **sv2, **sv3;
+
+ /* determine size for malloc */
+ totvert= 0;
+ mf= me->mface;
+ tf= me->tface;
+ gf= groups;
+
+ 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) {
+ 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= mf->v2;
+ v1->v2= mf->v3;
+
+ v2->v1= mf->v1;
+ v2->v2= mf->v3;
+
+ v3->v1= mf->v1;
+ v3->v2= mf->v2;
+
+ 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) {
+ 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= mf->v3;
+ v1->v2= mf->v4;
+
+ v2->v1= mf->v4;
+ v2->v2= mf->v1;
+
+ v3->v1= mf->v1;
+ v3->v2= mf->v3;
+
+ 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;
+ }
+ }
+ 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(dz < dx && dz < dy) {
+ 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();
+
+ /* 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<totgroup; a++) {
+ groupscale[a]= seam_group_relative_scale(me, groups, a+1);
+ minscale= MIN2(groupscale[a], minscale);
+ }
+
+ packx= packy= 0.0;
+ rowh= 0.0;
+ groupw= 1.0/sqrt(totgroup);
+
+ for(a=0; a<totgroup; a++) {
+
+ /* scale so all groups have the same size relative to the mesh */
+ scale = minscale/groupscale[a];
+ scale *= groupw;
+
+ seam_group_bbox(me, groups, a+1, min, max);
+ dx= (max[0]-min[0])*scale;
+ dy= (max[1]-min[1])*scale;
+
+ /* for padding */
+ dx += 0.05;
+ dy += 0.05;
+
+ add[0]= add[1]= 0.0;
+
+ if(dx > 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.025;
+ add[1] += 0.025;
+
+ 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.9);
+ add[0]= add[1]= 0.05;
+ seam_group_move(me, groups, 0, add);
+}
+
+void unwrap_lscm(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);
+
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+}
+
+/* Set tface seams based on edge data, uses hash table to find seam edges. */
+
+#define SEDHASH(a, b) ((a)*256 + (b))
+#define SEDHASHSIZE 65536
+#define SEDHMAX 256
+
+typedef struct SeamHashEdge {
+ MEdge *e;
+ struct SeamHashEdge *next;
+} SeamHashEdge;
+
+/* Hash table with edges, to find edges based on v1, v2 */
+static SeamHashEdge *make_seam_hash_edge_table(Mesh *me)
+{
+ SeamHashEdge *htable, *first, *he;
+ MEdge *medge;
+ unsigned int a, hv1, hv2;
+
+ if(me->medge==NULL)
+ return NULL;
+
+ htable= MEM_callocN(SEDHASHSIZE*sizeof(SeamHashEdge), "lscmedgehashtable");
+
+ medge= me->medge;
+ for(a=me->totedge; a>0; a--, medge++) {
+ if(!(medge->flag & ME_SEAM)) continue;
+
+ hv1= medge->v1 % SEDHMAX;
+ hv2= medge->v2 % SEDHMAX;
+ if(hv1 > hv2)
+ SWAP(unsigned int, hv1, hv2);
+
+ first = htable + SEDHASH(hv1, hv2);
+
+ if(first->e == NULL) {
+ first->e = medge;
+ }
+ else {
+ he= (SeamHashEdge*)malloc(sizeof(SeamHashEdge));
+ he->e= medge;
+ he->next= first->next;
+ first->next= he;
+ }
+ }
+
+ return htable;
+}
+
+static int edge_is_seam(SeamHashEdge *htable, unsigned int v1, unsigned int v2)
+{
+ SeamHashEdge *he;
+ unsigned int hv1, hv2;
+
+ hv1 = v1 % SEDHMAX;
+ hv2 = v2 % SEDHMAX;
+
+ if(hv1 > hv2)
+ SWAP(unsigned int, hv1, hv2);
+
+ he= htable + SEDHASH(hv1, hv2);
+
+ while(he) {
+ if(he->e) {
+ if(he->e->v1==v1 && he->e->v2==v2) return 1;
+ else if(he->e->v1==v2 && he->e->v2==v1) return 1;
+ }
+ he= he->next;
+ }
+
+ return 0;
+}
+
+static void free_seam_hash_edge_table(SeamHashEdge *htable)
+{
+ SeamHashEdge *first, *he, *hen;
+ int a;
+
+ if(htable) {
+ first= htable;
+ for(a=SEDHASHSIZE; a>0; a--, first++) {
+ he= first->next;
+ while(he) {
+ hen= he->next;
+ free(he);
+ he= hen;
+ }
+ }
+ MEM_freeN(htable);
+ htable= NULL;
+ }
+}
+
+void set_seamtface()
+{
+ Mesh *me;
+ SeamHashEdge *htable;
+ int a;
+ MFace *mf;
+ TFace *tf;
+
+ me= get_mesh(OBACT);
+ if(!me || !me->tface || !(G.f & G_FACESELECT)) return;
+
+ htable= make_seam_hash_edge_table(me);
+
+ mf= me->mface;
+ tf= me->tface;
+ for(a=me->totface; a>0; a--, mf++, tf++) {
+ if(mf->v3==0) continue;
+ tf->unwrap &= ~(TF_SEAM1|TF_SEAM2|TF_SEAM3|TF_SEAM4);
+
+ if(!htable) continue;
+
+ if(edge_is_seam(htable, mf->v1, mf->v2)) tf->unwrap |= TF_SEAM1;
+ if(edge_is_seam(htable, mf->v2, mf->v3)) tf->unwrap |= TF_SEAM2;
+
+ if(mf->v4) {
+ if(edge_is_seam(htable, mf->v3, mf->v4)) tf->unwrap |= TF_SEAM3;
+ if(edge_is_seam(htable, mf->v4, mf->v1)) tf->unwrap |= TF_SEAM4;
+ }
+ else if(edge_is_seam(htable, mf->v3, mf->v1)) tf->unwrap |= TF_SEAM3;
+ }
+
+ free_seam_hash_edge_table(htable);
+}
+