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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2006-01-10 14:36:57 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2006-01-10 14:36:57 +0300
commitdd7e0b6bfeefae727bb9bcb9a5241fc3af482e4d (patch)
tree556b33bfa2e1ab09a019e240b093f2acd1a193f3
parentb7be6620d6ecfbec1d82128f402b585041910ca9 (diff)
Apply Subsurf to UV's.
This fixes most of the UV distortion issues with subsurf. Near seams however there might still be some distortion, but this should at least not be worse than before. Subsurf UV is enabled by default on new meshes, and can be enabled in the modifier panel for existing ones. Before and after: http://users.pandora.be/blendix/notsmooth.png http://users.pandora.be/blendix/smooth.png
-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);