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_mesh.h16
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c65
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.h3
-rw-r--r--source/blender/blenkernel/intern/mesh.c121
-rw-r--r--source/blender/blenkernel/intern/modifier.c2
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c250
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h1
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h3
-rw-r--r--source/blender/src/buttons_editing.c3
-rw-r--r--source/blender/src/editsima.c318
10 files changed, 554 insertions, 228 deletions
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 9f8ee3c6127..5cf6dd41e6f 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -92,6 +92,22 @@ void mesh_calc_normals(struct MVert *mverts, int numVerts, struct MFace *mfaces,
* (_numVerts_r_ may be NULL) */
float (*mesh_getVertexCos(struct Mesh *me, int *numVerts_r))[3];
+/* map from uv vertex to face (for select linked, stitch, uv suburf) */
+
+struct UvVertMap;
+typedef struct UvVertMap UvVertMap;
+
+typedef struct UvMapVert {
+ struct UvMapVert *next;
+ unsigned int f;
+ unsigned char tfindex, separate;
+} UvMapVert;
+
+UvVertMap *make_uv_vert_map(struct MFace *mface, struct TFace *tface, unsigned int totface, unsigned int totvert, int selected, float *limit);
+UvMapVert *get_uv_map_vert(UvVertMap *vmap, unsigned int v);
+UvMapVert *get_first_uv_map_vert(UvVertMap *vmap);
+void free_uv_vert_map(UvVertMap *vmap);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index dc6543858c1..5bbd397e9c4 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -223,6 +223,7 @@ static int _edge_isBoundary(CCGEdge *e);
enum {
Vert_eEffected= (1<<0),
Vert_eChanged= (1<<1),
+ Vert_eSeam= (1<<2),
} VertFlags;
enum {
Edge_eEffected= (1<<0),
@@ -400,6 +401,10 @@ static void _vert_free(CCGVert *v, CCGSubSurf *ss) {
CCGSUBSURF_free(ss, v);
}
+static int VERT_seam(CCGVert *v, CCGSubSurf *ss) {
+ return ((v->flags & Vert_eSeam) != 0);
+}
+
/***/
static CCGEdge *_edge_new(CCGEdgeHDL eHDL, CCGVert *v0, CCGVert *v1, float crease, int levels, int dataSize, CCGSubSurf *ss) {
@@ -871,9 +876,10 @@ CCGError ccgSubSurf_syncFaceDel(CCGSubSurf *ss, CCGFaceHDL fHDL) {
return eCCGError_None;
}
-CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, CCGVert **v_r) {
+CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, int seam, CCGVert **v_r) {
void **prevp;
CCGVert *v = NULL;
+ short seamflag = (seam)? Vert_eSeam: 0;
if (ss->syncState==eSyncState_Partial) {
v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
@@ -881,12 +887,12 @@ CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, CC
v = _vert_new(vHDL, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
_ehash_insert(ss->vMap, (EHEntry*) v);
- v->flags = Vert_eEffected;
- } else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize))) {
+ v->flags = Vert_eEffected|seamflag;
+ } else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize)) || ((v->flags & Vert_eSeam) != seamflag)) {
int i, j;
VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
- v->flags = Vert_eEffected;
+ v->flags = Vert_eEffected|seamflag;
for (i=0; i<v->numEdges; i++) {
CCGEdge *e = v->edges[i];
@@ -910,12 +916,12 @@ CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, CC
v = _vert_new(vHDL, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
_ehash_insert(ss->vMap, (EHEntry*) v);
- v->flags = Vert_eEffected;
- } else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize))) {
+ v->flags = Vert_eEffected|seamflag;
+ } else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize)) || ((v->flags & Vert_eSeam) != seamflag)) {
*prevp = v->next;
_ehash_insert(ss->vMap, (EHEntry*) v);
VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
- v->flags = Vert_eEffected|Vert_eChanged;
+ v->flags = Vert_eEffected|Vert_eChanged|seamflag;
} else {
*prevp = v->next;
_ehash_insert(ss->vMap, (EHEntry*) v);
@@ -1222,11 +1228,15 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
void *nCo = VERT_getCo(v, nextLvl);
int sharpCount = 0, allSharp = 1;
float avgSharpness = 0.0;
+ int seam = VERT_seam(v, ss), seamEdges = 0;
for (i=0; i<v->numEdges; i++) {
CCGEdge *e = v->edges[i];
float sharpness = EDGE_getSharpness(e, curLvl, ss);
+ if (seam && _edge_isBoundary(e))
+ seamEdges++;
+
if (sharpness!=0.0f) {
sharpCount++;
avgSharpness += sharpness;
@@ -1240,6 +1250,9 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
avgSharpness = 1.0;
}
+ if (seam && seamEdges < 2)
+ seam = 0;
+
if (!v->numEdges) {
VertDataCopy(nCo, co);
} else if (_vert_isBoundary(v)) {
@@ -1282,14 +1295,25 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
VertDataMulN(nCo, 1.0f/numEdges);
}
- if (sharpCount>1 && v->numFaces) {
+ if ((sharpCount>1 && v->numFaces) || seam) {
VertDataZero(q);
+ if (seam) {
+ avgSharpness = 1.0f;
+ sharpCount = seamEdges;
+ allSharp = 1;
+ }
+
for (i=0; i<v->numEdges; i++) {
CCGEdge *e = v->edges[i];
float sharpness = EDGE_getSharpness(e, curLvl, ss);
- if (sharpness != 0.0) {
+ if (seam) {
+ if (_edge_isBoundary(e)) {
+ CCGVert *oV = _edge_getOtherVert(e, v);
+ VertDataAdd(q, VERT_getCo(oV, curLvl));
+ }
+ } else if (sharpness != 0.0) {
CCGVert *oV = _edge_getOtherVert(e, v);
VertDataAdd(q, VERT_getCo(oV, curLvl));
}
@@ -1502,11 +1526,15 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
void *nCo = VERT_getCo(v, nextLvl);
int sharpCount = 0, allSharp = 1;
float avgSharpness = 0.0;
+ int seam = VERT_seam(v, ss), seamEdges = 0;
for (i=0; i<v->numEdges; i++) {
CCGEdge *e = v->edges[i];
float sharpness = EDGE_getSharpness(e, curLvl, ss);
+ if (seam && _edge_isBoundary(e))
+ seamEdges++;
+
if (sharpness!=0.0f) {
sharpCount++;
avgSharpness += sharpness;
@@ -1520,6 +1548,9 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
avgSharpness = 1.0;
}
+ if (seam && seamEdges < 2)
+ seam = 0;
+
if (!v->numEdges) {
VertDataCopy(nCo, co);
} else if (_vert_isBoundary(v)) {
@@ -1564,14 +1595,23 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
VertDataMulN(nCo, 1.0f/numEdges);
}
- if (sharpCount>1 && v->numFaces) {
+ if ((sharpCount>1 && v->numFaces) || seam) {
VertDataZero(q);
+ if (seam) {
+ avgSharpness = 1.0f;
+ sharpCount = seamEdges;
+ allSharp = 1;
+ }
+
for (i=0; i<v->numEdges; i++) {
CCGEdge *e = v->edges[i];
float sharpness = EDGE_getSharpness(e, curLvl, ss);
- if (sharpness != 0.0) {
+ if (seam) {
+ if (_edge_isBoundary(e))
+ VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
+ } else if (sharpness != 0.0) {
VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
}
}
@@ -2121,6 +2161,9 @@ void *ccgSubSurf_getEdgeLevelData(CCGSubSurf *ss, CCGEdge *e, int x, int level)
return _edge_getCo(e, level, x, ss->meshIFC.vertDataSize);
}
}
+float ccgSubSurf_getEdgeCrease(CCGSubSurf *ss, CCGEdge *e) {
+ return e->crease;
+}
/* Face accessors */
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h
index 9f276989bc5..91f3ffab43b 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.h
+++ b/source/blender/blenkernel/intern/CCGSubSurf.h
@@ -49,7 +49,7 @@ CCGError ccgSubSurf_sync (CCGSubSurf *ss);
CCGError ccgSubSurf_initFullSync (CCGSubSurf *ss);
CCGError ccgSubSurf_initPartialSync (CCGSubSurf *ss);
-CCGError ccgSubSurf_syncVert (CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, CCGVert **v_r);
+CCGError ccgSubSurf_syncVert (CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, int seam, CCGVert **v_r);
CCGError ccgSubSurf_syncEdge (CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1, float crease, CCGEdge **e_r);
CCGError ccgSubSurf_syncFace (CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs, CCGFace **f_r);
@@ -99,6 +99,7 @@ int ccgSubSurf_getEdgeNumFaces (CCGSubSurf *ss, CCGEdge *e);
CCGFace* ccgSubSurf_getEdgeFace (CCGSubSurf *ss, CCGEdge *e, int index);
CCGVert* ccgSubSurf_getEdgeVert0 (CCGSubSurf *ss, CCGEdge *e);
CCGVert* ccgSubSurf_getEdgeVert1 (CCGSubSurf *ss, CCGEdge *e);
+float ccgSubSurf_getEdgeCrease (CCGSubSurf *ss, CCGEdge *e);
int ccgSubSurf_getEdgeAge (CCGSubSurf *ss, CCGEdge *e);
void* ccgSubSurf_getEdgeUserData (CCGSubSurf *ss, CCGEdge *e);
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index ab213f78200..bbe2a35bcd4 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -1082,3 +1082,124 @@ float (*mesh_getVertexCos(Mesh *me, int *numVerts_r))[3]
return cos;
}
+
+/* UvVertMap */
+
+struct UvVertMap {
+ struct UvMapVert **vert;
+ struct UvMapVert *buf;
+};
+
+UvVertMap *make_uv_vert_map(struct MFace *mface, struct TFace *tface, unsigned int totface, unsigned int totvert, int selected, float *limit)
+{
+ UvVertMap *vmap;
+ UvMapVert *buf;
+ MFace *mf;
+ TFace *tf;
+ int a, i, totuv, nverts;
+
+ totuv = 0;
+
+ /* generate UvMapVert array */
+ mf= mface;
+ tf= tface;
+ for(a=0; a<totface; a++, mf++, tf++)
+ if(!selected || (!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT)))
+ totuv += (mf->v4)? 4: 3;
+
+ if(totuv==0)
+ return NULL;
+
+ vmap= (UvVertMap*)MEM_mallocN(sizeof(*vmap), "UvVertMap");
+ if (!vmap)
+ return NULL;
+
+ vmap->vert= (UvMapVert**)MEM_callocN(sizeof(*vmap->vert)*totvert, "UvMapVert*");
+ buf= vmap->buf= (UvMapVert*)MEM_mallocN(sizeof(*vmap->buf)*totuv, "UvMapVert");
+
+ if (!vmap->vert || !vmap->buf) {
+ free_uv_vert_map(vmap);
+ return NULL;
+ }
+
+ mf= mface;
+ tf= tface;
+ for(a=0; a<totface; a++, mf++, tf++) {
+ if(!selected || (!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT))) {
+ nverts= (mf->v4)? 4: 3;
+
+ for(i=0; i<nverts; i++) {
+ buf->tfindex= i;
+ buf->f= a;
+ buf->separate = 0;
+ buf->next= vmap->vert[*(&mf->v1 + i)];
+ vmap->vert[*(&mf->v1 + i)]= buf;
+ buf++;
+ }
+ }
+ }
+
+ /* sort individual uvs for each vert */
+ tf= tface;
+ for(a=0; a<totvert; a++) {
+ UvMapVert *newvlist= NULL, *vlist=vmap->vert[a];
+ UvMapVert *iterv, *v, *lastv, *next;
+ float *uv, *uv2, uvdiff[2];
+
+ while(vlist) {
+ v= vlist;
+ vlist= vlist->next;
+ v->next= newvlist;
+ newvlist= v;
+
+ uv= (tf+v->f)->uv[v->tfindex];
+ lastv= NULL;
+ iterv= vlist;
+
+ while(iterv) {
+ next= iterv->next;
+
+ uv2= (tf+iterv->f)->uv[iterv->tfindex];
+ Vec2Subf(uvdiff, uv2, uv);
+
+
+ if(fabs(uv[0]-uv2[0]) < limit[0] && fabs(uv[1]-uv2[1]) < limit[1]) {
+ if(lastv) lastv->next= next;
+ else vlist= next;
+ iterv->next= newvlist;
+ newvlist= iterv;
+ }
+ else
+ lastv=iterv;
+
+ iterv= next;
+ }
+
+ newvlist->separate = 1;
+ }
+
+ vmap->vert[a]= newvlist;
+ }
+
+ return vmap;
+}
+
+UvMapVert *get_uv_map_vert(UvVertMap *vmap, unsigned int v)
+{
+ return vmap->vert[v];
+}
+
+UvMapVert *get_first_uv_map_vert(UvVertMap *vmap)
+{
+ return ((vmap->buf != NULL)? vmap->buf: NULL);
+}
+
+void free_uv_vert_map(UvVertMap *vmap)
+{
+ if (vmap) {
+ if (vmap->vert) MEM_freeN(vmap->vert);
+ if (vmap->buf) MEM_freeN(vmap->buf);
+ MEM_freeN(vmap);
+ }
+}
+
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 34777930b4b..5f3a57ce4db 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -147,6 +147,7 @@ static void subsurfModifier_initData(ModifierData *md)
smd->levels = 1;
smd->renderLevels = 2;
+ smd->flags |= eSubsurfModifierFlag_SubsurfUv;
}
static void subsurfModifier_copyData(ModifierData *md, ModifierData *target)
@@ -505,6 +506,7 @@ static DispListMesh *mirrorModifier__doMirror(MirrorModifierData *mmd, DispListM
if (isShared) {
mv->co[axis] = 0;
+ mv->flag |= ME_VERT_MERGED;
} else {
MVert *mv2 = &dlm->mvert[dlm->totvert++];
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 3fb6a486dc3..0bb6e11faad 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -56,6 +56,7 @@
#include "BLI_arithb.h"
#include "BLI_linklist.h"
#include "BLI_memarena.h"
+#include "BLI_edgehash.h"
#include "BIF_gl.h"
@@ -66,6 +67,16 @@ typedef struct _VertData {
float no[3];
} VertData;
+struct CCGDerivedMesh {
+ DerivedMesh dm;
+
+ CCGSubSurf *ss;
+ int fromEditmesh, drawInteriorEdges, useSubsurfUv;
+
+ Mesh *me;
+ DispListMesh *dlm;
+};
+
typedef struct CCGDerivedMesh CCGDerivedMesh;
static int ccgDM_getVertMapIndex(CCGDerivedMesh *ccgdm, CCGSubSurf *ss, CCGVert *v);
@@ -194,6 +205,155 @@ static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edg
}
}
+static float *getFaceUV(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize)
+{
+ int numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+
+ if (x==gridSize-1 && y==gridSize-1) {
+ CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
+ return ccgSubSurf_getVertData(ss, v);
+ }
+ else if (x==gridSize-1) {
+ CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
+ CCGEdge *e = ccgSubSurf_getFaceEdge(ss, f, S);
+
+ if (v==ccgSubSurf_getEdgeVert0(ss, e))
+ return ccgSubSurf_getEdgeData(ss, e, gridSize-1-y);
+ else
+ return ccgSubSurf_getEdgeData(ss, e, (edgeSize-2-1)-(gridSize-1-y-2));
+ }
+ else if (y==gridSize-1) {
+ CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
+ S = (S+numVerts-1)%numVerts;
+ CCGEdge *e = ccgSubSurf_getFaceEdge(ss, f, S);
+
+ if (v==ccgSubSurf_getEdgeVert0(ss, e))
+ return ccgSubSurf_getEdgeData(ss, e, gridSize-1-x);
+ else
+ return ccgSubSurf_getEdgeData(ss, e, (edgeSize-2-1)-(gridSize-1-x-2));
+ }
+ else if (x==0 && y==0)
+ return ccgSubSurf_getFaceCenterData(ss, f);
+ else if (x==0)
+ return ccgSubSurf_getFaceGridEdgeData(ss, f, (S+numVerts-1)%numVerts, y);
+ else if (y==0)
+ return ccgSubSurf_getFaceGridEdgeData(ss, f, S, x);
+ else
+ return ccgSubSurf_getFaceGridData(ss, f, S, x, y);
+}
+
+static void get_face_uv_map_vert(UvVertMap *vmap, struct MFace *mf, int fi, CCGVertHDL *fverts) {
+ unsigned int *fv = &mf->v1;
+ UvMapVert *v, *nv, *firstv = get_first_uv_map_vert(vmap);
+ int j, nverts= mf->v4? 4: 3;
+
+ for (j=0; j<nverts; j++, fv++) {
+ for (nv=v=get_uv_map_vert(vmap, *fv); v; v=v->next) {
+ if (v->separate)
+ nv= v;
+ if (v->f == fi)
+ break;
+ }
+
+ fverts[j]= (CCGVertHDL)(nv - firstv);
+ }
+}
+
+static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, Mesh *me, DispListMesh *dlm) {
+ MFace *mface = dlm?dlm->mface:me->mface;
+ TFace *tface = dlm?dlm->tface:me->tface;
+ MVert *mvert = dlm?dlm->mvert:me->mvert;
+ int totvert = dlm?dlm->totvert:me->totvert;
+ int totface = dlm?dlm->totface:me->totface;
+ int i, j, seam;
+ UvMapVert *v, *firstv;
+ UvVertMap *vmap;
+ float limit[2];
+ CCGVertHDL fverts[4];
+ EdgeHash *ehash;
+
+ limit[0]= limit[1]= 0.0001;
+ vmap= make_uv_vert_map(mface, tface, totface, totvert, 0, limit);
+ if (!vmap)
+ return 0;
+
+ ccgSubSurf_initFullSync(ss);
+
+ /* use this to get consistent vert handles with different heap addresses */
+ firstv= (totvert > 0)? get_first_uv_map_vert(vmap): NULL;
+
+ /* create vertices */
+ for (i=0; i<totvert; i++) {
+ for (v=get_uv_map_vert(vmap, i)->next; v; v=v->next)
+ if (v->separate)
+ break;
+
+ seam = (v != NULL) || ((mvert+i)->flag & ME_VERT_MERGED);
+
+ for (v=get_uv_map_vert(vmap, i); v; v=v->next) {
+ if (v->separate) {
+ CCGVert *ssv;
+ CCGVertHDL vhdl = (CCGVertHDL)(v - firstv);
+ float uv[3];
+
+ uv[0]= (tface+v->f)->uv[v->tfindex][0];
+ uv[1]= (tface+v->f)->uv[v->tfindex][1];
+ uv[2]= 0.0f;
+
+ ccgSubSurf_syncVert(ss, vhdl, uv, seam, &ssv);
+ }
+ }
+ }
+
+ /* create edges */
+ ehash = BLI_edgehash_new();
+
+ for (i=0; i<totface; i++) {
+ MFace *mf = &((MFace*) mface)[i];
+ int nverts= mf->v4? 4: 3;
+ CCGFace *origf= ccgSubSurf_getFace(origss, (CCGFaceHDL)i);
+ unsigned int *fv = &mf->v1;
+
+ get_face_uv_map_vert(vmap, mf, i, fverts);
+
+ for (j=0; j<nverts; j++) {
+ int v0 = (int)fverts[j];
+ int v1 = (int)fverts[(j+1)%nverts];
+ MVert *mv0 = mvert + *(fv+j);
+ MVert *mv1 = mvert + *(fv+((j+1)%nverts));
+
+ if (!BLI_edgehash_haskey(ehash, v0, v1)) {
+ CCGEdge *e, *orige= ccgSubSurf_getFaceEdge(origss, origf, j);
+ CCGEdgeHDL ehdl= (CCGEdgeHDL)((int)fverts[j], (int)fverts[(j+1)%nverts]);
+ float crease = ccgSubSurf_getEdgeCrease(origss, orige);
+
+ if ((mv0->flag&mv1->flag) & ME_VERT_MERGED)
+ crease = 2.0f;
+
+ ccgSubSurf_syncEdge(ss, ehdl, fverts[j], fverts[(j+1)%nverts], crease, &e);
+ BLI_edgehash_insert(ehash, v0, v1, NULL);
+ }
+ }
+ }
+
+ BLI_edgehash_free(ehash, NULL);
+
+ /* create faces */
+ for (i=0; i<totface; i++) {
+ MFace *mf = &((MFace*) mface)[i];
+ int nverts= mf->v4? 4: 3;
+ CCGFace *f;
+
+ get_face_uv_map_vert(vmap, mf, i, fverts);
+ ccgSubSurf_syncFace(ss, (CCGFaceHDL)i, nverts, fverts, &f);
+ }
+
+ free_uv_vert_map(vmap);
+ ccgSubSurf_processSync(ss);
+
+ return 1;
+}
+
#if 0
static unsigned int ss_getEdgeFlags(CCGSubSurf *ss, CCGEdge *e, int ssFromEditmesh, DispListMesh *dlm, MEdge *medge, TFace *tface)
{
@@ -225,7 +385,7 @@ static unsigned int ss_getEdgeFlags(CCGSubSurf *ss, CCGEdge *e, int ssFromEditme
}
#endif
-static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, int ssFromEditmesh, int drawInteriorEdges, Mesh *inMe, DispListMesh *inDLM) {
+static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, int ssFromEditmesh, int drawInteriorEdges, int useSubsurfUv, Mesh *inMe, DispListMesh *inDLM) {
DispListMesh *dlm = MEM_callocN(sizeof(*dlm), "dlm");
int edgeSize = ccgSubSurf_getEdgeSize(ss);
int gridSize = ccgSubSurf_getGridSize(ss);
@@ -239,11 +399,12 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
CCGVertIterator *vi;
CCGEdgeIterator *ei;
CCGFaceIterator *fi;
- CCGFace **faceMap2;
+ CCGFace **faceMap2, **faceMap2Uv = NULL;
CCGEdge **edgeMap2;
CCGVert **vertMap2;
int totvert, totedge, totface;
-
+ CCGSubSurf *uvss= NULL;
+
totvert = ccgSubSurf_getNumVerts(ss);
vertMap2 = MEM_mallocN(totvert*sizeof(*vertMap2), "vertmap");
vi = ccgSubSurf_getVertIterator(ss);
@@ -317,6 +478,23 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
dlm->mcol = NULL;
}
+
+ if (useSubsurfUv && tface) {
+ /* not for editmesh currently */
+ uvss= _getSubSurf(NULL, ccgSubSurf_getSubdivisionLevels(ss), 0, 1, 0);
+
+ if (ss_sync_from_uv(uvss, ss, inMe, inDLM)) {
+ faceMap2Uv = MEM_mallocN(totface*sizeof(*faceMap2Uv), "facemapuv");
+
+ fi = ccgSubSurf_getFaceIterator(uvss);
+ for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ faceMap2Uv[(int) ccgSubSurf_getFaceFaceHandle(uvss, f)] = f;
+ }
+ ccgFaceIterator_free(fi);
+ }
+ }
+
/* Load vertices... we do in this funny order because
* all "added" vertices" are required to appear first
* in the displist (before STEPINDEX flags start). Also
@@ -460,6 +638,7 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
lastIndex = -1;
for (index=0; index<totface; index++) {
CCGFace *f = faceMap2[index];
+ CCGFace *uvf = faceMap2Uv? faceMap2Uv[index]: NULL;
int numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
float edge_data[4][6];
float corner_data[4][6];
@@ -483,10 +662,12 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
corner_data[S][1] = col[1]/255.0f;
corner_data[S][2] = col[2]/255.0f;
corner_data[S][3] = col[3]/255.0f;
- corner_data[S][4] = origTFace->uv[S][0];
- corner_data[S][5] = origTFace->uv[S][1];
+ if (!uvf) {
+ corner_data[S][4] = origTFace->uv[S][0];
+ corner_data[S][5] = origTFace->uv[S][1];
+ }
}
- numDataComponents = 6;
+ numDataComponents = uvf? 4: 6;
} else if (mcol) {
MCol *origMCol = &mcol[origIdx*4];
@@ -523,6 +704,8 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
for (y=0; y<gridSize-1; y++) {
for (x=0; x<gridSize-1; x++) {
+ float smoothuv[4][3];
+
MFace *mf = &dlm->mface[i];
mf->v1 = getFaceIndex(ss, f, S, x+0, y+0, edgeSize, gridSize);
mf->v2 = getFaceIndex(ss, f, S, x+0, y+1, edgeSize, gridSize);
@@ -531,6 +714,13 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
mf->mat_nr = mat_nr;
mf->flag = flag&~ME_FACE_STEPINDEX;
+ if(uvf) {
+ VECCOPY(smoothuv[0], getFaceUV(uvss, uvf, S, x+0, y+0, edgeSize, gridSize));
+ VECCOPY(smoothuv[1], getFaceUV(uvss, uvf, S, x+0, y+1, edgeSize, gridSize));
+ VECCOPY(smoothuv[2], getFaceUV(uvss, uvf, S, x+1, y+1, edgeSize, gridSize));
+ VECCOPY(smoothuv[3], getFaceUV(uvss, uvf, S, x+1, y+0, edgeSize, gridSize));
+ }
+
if (S==0 && x==0 && y==0) {
if (mapIndex!=lastIndex)
mf->flag |= ME_FACE_STEPINDEX;
@@ -557,8 +747,14 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
col[2] = (int) (data[2]*255);
col[3] = (int) (data[3]*255);
tf->col[j] = *((unsigned int*) col);
- tf->uv[j][0] = data[4];
- tf->uv[j][1] = data[5];
+ if (uvf) {
+ tf->uv[j][0] = smoothuv[j][0];
+ tf->uv[j][1] = smoothuv[j][1];
+ }
+ else {
+ tf->uv[j][0] = (float)(data[4]);
+ tf->uv[j][1] = (float)(data[5]);
+ }
} else if (dlm->mcol) {
unsigned char *col = (unsigned char*) &dlm->mcol[i*4+j];
col[0] = (int) (data[0]*255);
@@ -587,6 +783,11 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
MEM_freeN(edgeMap2);
MEM_freeN(vertMap2);
+ if(uvss) {
+ ccgSubSurf_free(uvss);
+ MEM_freeN(faceMap2Uv);
+ }
+
mesh_calc_normals(dlm->mvert, dlm->totvert, dlm->mface, dlm->totface, &dlm->nors);
return dlm;
@@ -607,7 +808,7 @@ static void ss_sync_from_mesh(CCGSubSurf *ss, Mesh *me, DispListMesh *dlm, float
for (i=0,index=-1; i<totvert; i++) {
CCGVert *v;
- ccgSubSurf_syncVert(ss, (CCGVertHDL) i, vertexCos?vertexCos[i]:mvert[i].co, &v);
+ ccgSubSurf_syncVert(ss, (CCGVertHDL) i, vertexCos?vertexCos[i]:mvert[i].co, 0, &v);
if (!dlm || (mvert[i].flag&ME_VERT_STEPINDEX)) index++;
((int*) ccgSubSurf_getVertUserData(ss, v))[1] = index;
@@ -676,13 +877,13 @@ void ss_sync_from_editmesh(CCGSubSurf *ss, EditMesh *em, float (*vertCos)[3], in
if (vertCos) {
for (i=0,ev=em->verts.first; ev; i++,ev=ev->next) {
CCGVert *v;
- ccgSubSurf_syncVert(ss, ev, vertCos[i], &v);
+ ccgSubSurf_syncVert(ss, ev, vertCos[i], 0, &v);
((int*) ccgSubSurf_getVertUserData(ss, v))[1] = i;
}
} else {
for (i=0,ev=em->verts.first; ev; i++,ev=ev->next) {
CCGVert *v;
- ccgSubSurf_syncVert(ss, ev, ev->co, &v);
+ ccgSubSurf_syncVert(ss, ev, ev->co, 0, &v);
((int*) ccgSubSurf_getVertUserData(ss, v))[1] = i;
}
}
@@ -710,16 +911,6 @@ void ss_sync_from_editmesh(CCGSubSurf *ss, EditMesh *em, float (*vertCos)[3], in
/***/
-struct CCGDerivedMesh {
- DerivedMesh dm;
-
- CCGSubSurf *ss;
- int fromEditmesh, drawInteriorEdges;
-
- Mesh *me;
- DispListMesh *dlm;
-};
-
static int ccgDM_getVertMapIndex(CCGDerivedMesh *ccgdm, CCGSubSurf *ss, CCGVert *v) {
return ((int*) ccgSubSurf_getVertUserData(ss, v))[1];
}
@@ -918,7 +1109,7 @@ static void ccgDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData
static DispListMesh *ccgDM_convertToDispListMesh(DerivedMesh *dm, int allowShared) {
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- return ss_to_displistmesh(ccgdm->ss, ccgdm, ccgdm->fromEditmesh, ccgdm->drawInteriorEdges, ccgdm->me, ccgdm->dlm);
+ return ss_to_displistmesh(ccgdm->ss, ccgdm, ccgdm->fromEditmesh, ccgdm->drawInteriorEdges, ccgdm->useSubsurfUv, ccgdm->me, ccgdm->dlm);
}
static void ccgDM_drawVerts(DerivedMesh *dm) {
@@ -1452,7 +1643,7 @@ static void ccgDM_release(DerivedMesh *dm) {
MEM_freeN(ccgdm);
}
-static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int fromEditmesh, int drawInteriorEdges, Mesh *me, DispListMesh *dlm) {
+static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int fromEditmesh, int drawInteriorEdges, int useSubsurfUv, Mesh *me, DispListMesh *dlm) {
CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm");
ccgdm->dm.getMinMax = ccgDM_getMinMax;
@@ -1480,6 +1671,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int fromEditmesh, int d
ccgdm->ss = ss;
ccgdm->fromEditmesh = fromEditmesh;
ccgdm->drawInteriorEdges = drawInteriorEdges;
+ ccgdm->useSubsurfUv = useSubsurfUv;
ccgdm->me = me;
ccgdm->dlm = dlm;
@@ -1496,23 +1688,25 @@ DerivedMesh *subsurf_make_derived_from_editmesh(EditMesh *em, SubsurfModifierDat
smd->emCache = _getSubSurf(smd->emCache, smd->levels, useAging, 0, useSimple);
ss_sync_from_editmesh(smd->emCache, em, vertCos, useSimple);
- return (DerivedMesh*) getCCGDerivedMesh(smd->emCache, 1, drawInteriorEdges, NULL, NULL);
+ return (DerivedMesh*) getCCGDerivedMesh(smd->emCache, 1, drawInteriorEdges, 0, NULL, NULL);
}
DerivedMesh *subsurf_make_derived_from_dlm_em(DispListMesh *dlm, SubsurfModifierData *smd, float (*vertCos)[3]) {
int useSimple = smd->subdivType==ME_SIMPLE_SUBSURF;
int useAging = smd->flags&eSubsurfModifierFlag_DebugIncr;
+ int useSubsurfUv = smd->flags&eSubsurfModifierFlag_SubsurfUv;
int drawInteriorEdges = !(smd->flags&eSubsurfModifierFlag_ControlEdges);
smd->emCache = _getSubSurf(smd->emCache, smd->levels, useAging, 0, useSimple);
ss_sync_from_mesh(smd->emCache, NULL, dlm, vertCos, useSimple);
- return (DerivedMesh*) getCCGDerivedMesh(smd->emCache, 0, drawInteriorEdges, NULL, dlm);
+ return (DerivedMesh*) getCCGDerivedMesh(smd->emCache, 0, drawInteriorEdges, useSubsurfUv, NULL, dlm);
}
DerivedMesh *subsurf_make_derived_from_mesh(Mesh *me, DispListMesh *dlm, SubsurfModifierData *smd, int useRenderParams, float (*vertCos)[3], int isFinalCalc) {
int useSimple = smd->subdivType==ME_SIMPLE_SUBSURF;
+ int useSubsurfUv = smd->flags&eSubsurfModifierFlag_SubsurfUv;
int drawInteriorEdges = !(smd->flags&eSubsurfModifierFlag_ControlEdges);
DispListMesh *ndlm;
@@ -1522,7 +1716,7 @@ DerivedMesh *subsurf_make_derived_from_mesh(Mesh *me, DispListMesh *dlm, Subsurf
ss_sync_from_mesh(ss, me, dlm, vertCos, useSimple);
- ndlm = ss_to_displistmesh(ss, NULL, 0, drawInteriorEdges, me, dlm);
+ ndlm = ss_to_displistmesh(ss, NULL, 0, drawInteriorEdges, useSubsurfUv, me, dlm);
if (dlm) displistmesh_free(dlm);
ccgSubSurf_free(ss);
@@ -1551,7 +1745,7 @@ DerivedMesh *subsurf_make_derived_from_mesh(Mesh *me, DispListMesh *dlm, Subsurf
ss_sync_from_mesh(ss, me, dlm, vertCos, useSimple);
- return (DerivedMesh*) getCCGDerivedMesh(ss, 0, drawInteriorEdges, me, dlm);
+ return (DerivedMesh*) getCCGDerivedMesh(ss, 0, drawInteriorEdges, useSubsurfUv, me, dlm);
} else {
if (smd->mCache && isFinalCalc) {
ccgSubSurf_free(smd->mCache);
@@ -1561,7 +1755,7 @@ DerivedMesh *subsurf_make_derived_from_mesh(Mesh *me, DispListMesh *dlm, Subsurf
ss = _getSubSurf(NULL, smd->levels, 0, 1, useSimple);
ss_sync_from_mesh(ss, me, dlm, vertCos, useSimple);
- ndlm = ss_to_displistmesh(ss, NULL, 0, drawInteriorEdges, me, dlm);
+ ndlm = ss_to_displistmesh(ss, NULL, 0, drawInteriorEdges, useSubsurfUv, me, dlm);
if (dlm) displistmesh_free(dlm);
ccgSubSurf_free(ss);
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index eaacdb3a398..9fe5a3acacf 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -75,6 +75,7 @@ typedef struct MSticky {
#define ME_SPHERETEST 2
#define ME_SPHERETEMP 4
#define ME_HIDE 16
+#define ME_VERT_MERGED (1<<6)
#define ME_VERT_STEPINDEX (1<<7)
/* medge->flag (1=SELECT)*/
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index b1b8239ac7d..19128bd0286 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -47,7 +47,8 @@ typedef struct ModifierData {
typedef enum {
eSubsurfModifierFlag_Incremental = (1<<0),
eSubsurfModifierFlag_DebugIncr = (1<<1),
- eSubsurfModifierFlag_ControlEdges = (1<<2)
+ eSubsurfModifierFlag_ControlEdges = (1<<2),
+ eSubsurfModifierFlag_SubsurfUv = (1<<3)
} SubsurfModifierFlag;
typedef struct SubsurfModifierData {
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index 6d615b4b085..53460d316a9 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -1212,7 +1212,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
int lx = x + width - 60 - 15;
if (md->type==eModifierType_Subsurf) {
- height = 86;
+ height = 106;
} else if (md->type==eModifierType_Lattice) {
height = 46;
} else if (md->type==eModifierType_Curve) {
@@ -1274,6 +1274,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
*/
uiDefButBitS(block, TOG, eSubsurfModifierFlag_ControlEdges, B_MODIFIER_RECALC, "Optimal Draw", lx, (cy-=19), buttonWidth,19,&smd->flags, 0, 0, 0, 0, "Skip drawing/rendering of interior subdivided edges");
+ uiDefButBitS(block, TOG, eSubsurfModifierFlag_SubsurfUv, B_MODIFIER_RECALC, "Subsurf UV", lx, (cy-=19),buttonWidth,19,&smd->flags, 0, 0, 0, 0, "Use subsurf to subdivide UVs");
} else if (md->type==eModifierType_Lattice) {
LatticeModifierData *lmd = (LatticeModifierData*) md;
uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
diff --git a/source/blender/src/editsima.c b/source/blender/src/editsima.c
index 6e717147bda..eca241c155f 100644
--- a/source/blender/src/editsima.c
+++ b/source/blender/src/editsima.c
@@ -87,25 +87,11 @@
#include "blendef.h"
#include "mydevice.h"
-struct uvvertsort {
- unsigned int v, f;
- unsigned char tf_sel;
- char flag;
-};
-
/* local prototypes */
void clever_numbuts_sima(void);
void sel_uvco_inside_radius(short , TFace *, int , float *, float *, short);
void uvedit_selectionCB(short , Object *, short *, float ); /* used in edit.c*/
-static int compuvvert(const void *u1, const void *u2)
-{
- const struct uvvertsort *v1=u1, *v2=u2;
- if (v1->v > v2->v) return 1;
- else if (v1->v < v2->v) return -1;
- return 0;
-}
-
void object_uvs_changed(Object *ob)
{
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
@@ -594,7 +580,7 @@ void mouse_select_sima(void)
{
Mesh *me;
TFace *tf, *nearesttf;
- MFace *mf, *nearestmf;
+ MFace *mf, *nearestmf=NULL;
int a, selectsticky, sticky, actface, nearestuv, i;
unsigned int hitv[4], nearestv;
float *hituv[4], limit[2];
@@ -1024,14 +1010,15 @@ void reveal_tface_uv(void)
void stitch_uv_tface(int mode)
{
- MFace *mf;
- TFace *tf, *tface;
Mesh *me;
- int a, b, c, tot, vtot, vtot2;
- float newuv[2], limit[2], *uv, *uv1;
- struct uvvertsort *sortblock, *sb, *sb1, *sb2;
+ TFace *tf;
+ int a, vtot;
+ float newuv[2], limit[2];
+ UvMapVert *vlist, *iterv, *v;
+ UvVertMap *vmap;
- if( is_uv_tface_editing_allowed()==0 ) return;
+ if(is_uv_tface_editing_allowed()==0)
+ return;
limit[0]= limit[1]= 20.0;
if(mode==1) {
@@ -1047,115 +1034,80 @@ void stitch_uv_tface(int mode)
}
else
limit[0]= limit[1]= limit[0]/256.0;
-
- me= get_mesh(OBACT);
- tface= (TFace*)me->tface;
-
- tot= 0;
- mf= (MFace*)me->mface;
- tf= (TFace*)me->tface;
- for(a=me->totface; a>0; a--, tf++, mf++) {
- if((tf->flag & TF_SELECT)) {
- if(tf->flag & TF_SEL1) tot++;
- if(tf->flag & TF_SEL2) tot++;
- if(tf->flag & TF_SEL3) tot++;
- if(mf->v4 && tf->flag & TF_SEL4) tot++;
- }
- }
- if(tot==0) return;
- sb= sortblock= MEM_callocN(sizeof(struct uvvertsort)*tot,"sortstitchuv");
+ me= get_mesh(OBACT);
+ tf= me->tface;
- mf= (MFace*)me->mface;
- tf= (TFace*)me->tface;
- for(a=0; a<me->totface; a++, tf++, mf++) {
- if((tf->flag & TF_SELECT)) {
- if(tf->flag & TF_SEL1) {
- sb->v= mf->v1;
- sb->f= a;
- sb->tf_sel= 0;
- sb++;
- }
- if(tf->flag & TF_SEL2) {
- sb->v= mf->v2;
- sb->f= a;
- sb->tf_sel= 1;
- sb++;
- }
- if(tf->flag & TF_SEL3) {
- sb->v= mf->v3;
- sb->f= a;
- sb->tf_sel= 2;
- sb++;
- }
- if(mf->v4 && tf->flag & TF_SEL4) {
- sb->v= mf->v4;
- sb->f= a;
- sb->tf_sel= 3;
- sb++;
- }
- }
- }
-
- /* sort by vertex */
- qsort(sortblock, tot, sizeof(struct uvvertsort), compuvvert);
+ vmap= make_uv_vert_map(me->mface, tf, me->totface, me->totvert, 1, limit);
+ if(vmap == NULL)
+ return;
if(mode==0) {
- for (a=0, sb=sortblock; a<tot; a+=vtot, sb+=vtot) {
+ for(a=0; a<me->totvert; a++) {
+ v = get_uv_map_vert(vmap, a);
+
+ if(v == NULL)
+ continue;
+
newuv[0]= 0; newuv[1]= 0;
vtot= 0;
- for (b=a, sb1=sb; b<tot && sb1->v==sb->v; b++, sb1++) {
- newuv[0] += tface[sb1->f].uv[sb1->tf_sel][0];
- newuv[1] += tface[sb1->f].uv[sb1->tf_sel][1];
- vtot++;
+ for(iterv=v; iterv; iterv=iterv->next) {
+ if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
+ newuv[0] += tf[iterv->f].uv[iterv->tfindex][0];
+ newuv[1] += tf[iterv->f].uv[iterv->tfindex][1];
+ vtot++;
+ }
}
- newuv[0] /= vtot; newuv[1] /= vtot;
+ if (vtot > 1) {
+ newuv[0] /= vtot; newuv[1] /= vtot;
- for (b=a, sb1=sb; b<a+vtot; b++, sb1++) {
- tface[sb1->f].uv[sb1->tf_sel][0]= newuv[0];
- tface[sb1->f].uv[sb1->tf_sel][1]= newuv[1];
+ for(iterv=v; iterv; iterv=iterv->next) {
+ if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
+ tf[iterv->f].uv[iterv->tfindex][0]= newuv[0];
+ tf[iterv->f].uv[iterv->tfindex][1]= newuv[1];
+ }
+ }
}
}
} else if(mode==1) {
- for (a=0, sb=sortblock; a<tot; a+=vtot, sb+=vtot) {
- vtot= 0;
- for (b=a, sb1=sb; b<tot && sb1->v==sb->v; b++, sb1++)
- vtot++;
-
- for (b=a, sb1=sb; b<a+vtot; b++, sb1++) {
- if(sb1->flag & 2) continue;
+ for(a=0; a<me->totvert; a++) {
+ vlist= get_uv_map_vert(vmap, a);
+ while(vlist) {
newuv[0]= 0; newuv[1]= 0;
- vtot2 = 0;
-
- for (c=b, sb2=sb1; c<a+vtot; c++, sb2++) {
- uv = tface[sb2->f].uv[sb2->tf_sel];
- uv1 = tface[sb1->f].uv[sb1->tf_sel];
- if (fabs(uv[0]-uv1[0]) < limit[0] &&
- fabs(uv[1]-uv1[1]) < limit[1]) {
- newuv[0] += uv[0];
- newuv[1] += uv[1];
- sb2->flag |= 2;
- sb2->flag |= 4;
- vtot2++;
+ vtot= 0;
+
+ for(iterv=vlist; iterv; iterv=iterv->next) {
+ if((iterv != vlist) && iterv->separate)
+ break;
+ if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
+ newuv[0] += tf[iterv->f].uv[iterv->tfindex][0];
+ newuv[1] += tf[iterv->f].uv[iterv->tfindex][1];
+ vtot++;
}
}
- newuv[0] /= vtot2; newuv[1] /= vtot2;
+ if (vtot > 1) {
+ newuv[0] /= vtot; newuv[1] /= vtot;
- for (c=b, sb2=sb1; c<a+vtot; c++, sb2++) {
- if(sb2->flag & 4) {
- tface[sb2->f].uv[sb2->tf_sel][0]= newuv[0];
- tface[sb2->f].uv[sb2->tf_sel][1]= newuv[1];
- sb2->flag &= ~4;
+ for(iterv=vlist; iterv; iterv=iterv->next) {
+ if((iterv != vlist) && iterv->separate)
+ break;
+ if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
+ tf[iterv->f].uv[iterv->tfindex][0]= newuv[0];
+ tf[iterv->f].uv[iterv->tfindex][1]= newuv[1];
+ }
}
}
+
+ vlist= iterv;
}
}
}
- MEM_freeN(sortblock);
+
+ free_uv_vert_map(vmap);
if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(me);
@@ -1166,109 +1118,102 @@ void stitch_uv_tface(int mode)
void select_linked_tface_uv(int mode)
{
- MFace *mf;
- TFace *tface, *tf, *nearesttf=NULL;
Mesh *me;
- char sel, *linkflag;
- int a, b, c, tot, vtot, nearestv, nearestuv, i, nverts;
- float limit[2], *uv, *uv1;
- struct uvvertsort *sortblock, *sb, *sb1, *sb2;
+ MFace *mf;
+ TFace *tf, *nearesttf=NULL;
+ UvVertMap *vmap;
+ UvMapVert *vlist, *iterv, *startv;
+ unsigned int *stack, stacksize= 0, nearestv;
+ char *flag;
+ int a, nearestuv, i, nverts;
+ float limit[2];
- if( is_uv_tface_editing_allowed()==0 ) return;
+ if(is_uv_tface_editing_allowed()==0)
+ return;
me= get_mesh(OBACT);
- get_connected_limit_tface_uv(limit);
-
- tot= 0;
- mf= (MFace*)me->mface;
- tf= (TFace*)me->tface;
- for(a=me->totface; a>0; a--, tf++, mf++)
- if(tf->flag & TF_SELECT)
- tot += mf->v4? 4: 3;
-
- if(tot==0) return;
+ if (mode == 2) {
+ nearesttf= NULL;
+ nearestuv= 0;
+ }
if (mode!=2) {
find_nearest_uv(&nearesttf, &nearestv, &nearestuv);
-
if(nearesttf==NULL)
return;
}
- else {
- nearesttf= NULL;
- nearestuv= 0;
- }
- sb= sortblock= MEM_callocN(sizeof(struct uvvertsort)*tot, "sortsellinkuv");
- linkflag= MEM_callocN(sizeof(char)*me->totface, "linkflaguv");
+ get_connected_limit_tface_uv(limit);
+ vmap= make_uv_vert_map(me->mface, me->tface, me->totface, me->totvert, 1, limit);
+ if(vmap == NULL)
+ return;
- mf= (MFace*)me->mface;
- tf= (TFace*)me->tface;
- for(a=0; a<me->totface; a++, tf++, mf++) {
- if(!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT)) {
- sel= 0;
- sb1= sb;
- nverts= mf->v4? 4: 3;
- for(i=0; i<nverts; i++) {
- if(tf->flag & TF_SEL_MASK(i))
- sel= 1;
- sb->f= a;
- sb->tf_sel= i;
- sb++;
+ stack= MEM_mallocN(sizeof(*stack)*me->totface, "UvLinkStack");
+ flag= MEM_callocN(sizeof(*flag)*me->totface, "UvLinkFlag");
+
+ if (mode == 2) {
+ tf= me->tface;
+ for(a=0; a<me->totface; a++, tf++)
+ if(!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT))
+ if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) {
+ stack[stacksize]= a;
+ stacksize++;
+ flag[a]= 1;
+ }
+ }
+ else {
+ tf= me->tface;
+ for(a=0; a<me->totface; a++, tf++)
+ if(tf == nearesttf) {
+ stack[stacksize]= a;
+ stacksize++;
+ flag[a]= 1;
+ break;
}
+ }
- if(nearesttf==tf || ((sel && mode==2)))
- linkflag[a] = 1;
+ while(stacksize > 0) {
+ stacksize--;
+ a= stack[stacksize];
+ mf= me->mface+a;
+ tf= me->tface+a;
- (sb1)->v= mf->v1;
- (sb1+1)->v= mf->v2;
- (sb1+2)->v= mf->v3;
- if(mf->v4) (sb1+3)->v= mf->v4;
- }
- }
-
- /* sort by vertex */
- qsort(sortblock, tot, sizeof(struct uvvertsort), compuvvert);
+ nverts= mf->v4? 4: 3;
- tface= (TFace*)me->tface;
- sel= 1;
- while(sel) {
- sel= 0;
+ for(i=0; i<nverts; i++) {
+ vlist= get_uv_map_vert(vmap, *(&mf->v1 + i));
+ startv= vlist;
- /* select all tex vertices that are near a selected tex vertex */
- for (a=0, sb=sortblock; a<tot; a+=vtot, sb+=vtot) {
- vtot= 0;
- for (b=a, sb1=sb; b<tot && sb1->v==sb->v; b++, sb1++)
- vtot++;
- for (b=a, sb1=sb; b<a+vtot; b++, sb1++) {
- if(linkflag[sb1->f]) continue;
+ for(iterv=vlist; iterv; iterv=iterv->next) {
+ if(iterv->separate)
+ startv= iterv;
+ if(iterv->f == a)
+ break;
+ }
- for (c=a, sb2=sb; c<a+vtot; c++, sb2++) {
- if(!(linkflag[sb2->f])) continue;
-
- uv = tface[sb2->f].uv[sb2->tf_sel];
- uv1 = tface[sb1->f].uv[sb1->tf_sel];
- if (fabs(uv[0]-uv1[0]) < limit[0] &&
- fabs(uv[1]-uv1[1]) < limit[1]) {
- linkflag[sb1->f] = 1;
- sel= 1;
- break;
- }
+ for(iterv=startv; iterv; iterv=iterv->next) {
+ if((startv != iterv) && (iterv->separate))
+ break;
+ else if(!flag[iterv->f]) {
+ flag[iterv->f]= 1;
+ stack[stacksize]= iterv->f;;
+ stacksize++;
}
}
}
}
if(mode==0 || mode==2) {
- for(a=0, tf=tface; a<me->totface; a++, tf++)
- if(linkflag[a])
+ for(a=0, tf=me->tface; a<me->totface; a++, tf++)
+ if(flag[a])
tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
else
tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
}
else if(mode==1) {
- for(a=0, tf=tface; a<me->totface; a++, tf++) {
- if(linkflag[a]) {
+ mf= me->mface;
+ for(a=0, tf=me->tface; a<me->totface; a++, tf++, mf++) {
+ if(flag[a]) {
if (mf->v4) {
if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)))
break;
@@ -1279,19 +1224,20 @@ void select_linked_tface_uv(int mode)
}
if (a<me->totface) {
- for(a=0, tf=tface; a<me->totface; a++, tf++)
- if(linkflag[a])
+ for(a=0, tf=me->tface; a<me->totface; a++, tf++)
+ if(flag[a])
tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
}
else {
- for(a=0, tf=tface; a<me->totface; a++, tf++)
- if(linkflag[a])
+ for(a=0, tf=me->tface; a<me->totface; a++, tf++)
+ if(flag[a])
tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
}
}
- MEM_freeN(sortblock);
- MEM_freeN(linkflag);
+ MEM_freeN(stack);
+ MEM_freeN(flag);
+ free_uv_vert_map(vmap);
BIF_undo_push("Select linked UV");
scrarea_queue_winredraw(curarea);