diff options
-rw-r--r-- | source/blender/blenkernel/BKE_mesh.h | 16 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/CCGSubSurf.c | 65 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/CCGSubSurf.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh.c | 121 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/modifier.c | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/subsurf_ccg.c | 250 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_meshdata_types.h | 1 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_modifier_types.h | 3 | ||||
-rw-r--r-- | source/blender/src/buttons_editing.c | 3 | ||||
-rw-r--r-- | source/blender/src/editsima.c | 318 |
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); |