Fix simple subsurf on wire edges
authorNicholas Bishop <nicholasbishop@gmail.com>
Sat, 18 Aug 2012 19:54:21 +0000 (19:54 +0000)
committerNicholas Bishop <nicholasbishop@gmail.com>
Sat, 18 Aug 2012 19:54:21 +0000 (19:54 +0000)
Subsurf on wire edges gave smooth results even if set to simple
subdiv. Added a field to the CCG meshIFC to flag simple subdivision,
then when syncing vertices simply skip moving vertices if in
simple-subdiv mode.

This change affects two places, the level-1 build in sync and the
subdivision up to other levels.

Fixes bug [#32268] Simple Subsurf Modifier gives unexpected results on
edges without faces
projects.blender.org/tracker/index.php?func=detail&aid=32268&group_id=9&atid=498

source/blender/blenkernel/intern/CCGSubSurf.c
source/blender/blenkernel/intern/CCGSubSurf.h
source/blender/blenkernel/intern/subsurf_ccg.c

index c456840637ad5a4da28b26375deda174f2bcfd5b..387d4775ad43a84bfca4aefa93217a3df6a783ae 100644 (file)
@@ -1798,7 +1798,7 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
                if (seamEdges < 2 || seamEdges != v->numEdges)
                        seam = 0;
 
-               if (!v->numEdges) {
+               if (!v->numEdges || ss->meshIFC.simpleSubdiv) {
                        VertDataCopy(nCo, co, ss);
                }
                else if (_vert_isBoundary(v)) {
@@ -2246,7 +2246,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss)
                if (seamEdges < 2 || seamEdges != v->numEdges)
                        seam = 0;
 
-               if (!v->numEdges) {
+               if (!v->numEdges || ss->meshIFC.simpleSubdiv) {
                        VertDataCopy(nCo, co, ss);
                }
                else if (_vert_isBoundary(v)) {
@@ -2827,6 +2827,11 @@ int ccgSubSurf_getGridLevelSize(const CCGSubSurf *ss, int level)
        }
 }
 
+int ccgSubSurf_getSimpleSubdiv(const CCGSubSurf *ss)
+{
+       return ss->meshIFC.simpleSubdiv;
+}
+
 /* Vert accessors */
 
 CCGVertHDL ccgSubSurf_getVertVertHandle(CCGVert *v)
index 33b37ac281cf4e613afb777f3245417def58b7c2..0f96bcf172daa3c2a4d471ca2c1ada04591c321c 100644 (file)
@@ -17,6 +17,7 @@ typedef struct CCGMeshIFC {
        int                     vertUserSize, edgeUserSize, faceUserSize;
        int                     numLayers;
        int                     vertDataSize;
+       int                     simpleSubdiv;
 } CCGMeshIFC;
 
 /***/
@@ -91,6 +92,7 @@ int                   ccgSubSurf_getEdgeSize                          (const CCGSubSurf *ss);
 int                    ccgSubSurf_getEdgeLevelSize                     (const CCGSubSurf *ss, int level);
 int                    ccgSubSurf_getGridSize                          (const CCGSubSurf *ss);
 int                    ccgSubSurf_getGridLevelSize                     (const CCGSubSurf *ss, int level);
+int                    ccgSubSurf_getSimpleSubdiv                      (const CCGSubSurf *ss);
 
 CCGVert*       ccgSubSurf_getVert                                      (CCGSubSurf *ss, CCGVertHDL v);
 CCGVertHDL     ccgSubSurf_getVertVertHandle            (CCGVert *v);
index 5c387e8cee0fa2469c73cb693811696dfd559048..b2762d23ef342b08e8151b9c01e2a3a9a986fc0f 100644 (file)
@@ -113,7 +113,8 @@ typedef enum {
        CCG_USE_ARENA = 2,
        CCG_CALC_NORMALS = 4,
        /* add an extra four bytes for a mask layer */
-       CCG_ALLOC_MASK = 8
+       CCG_ALLOC_MASK = 8,
+       CCG_SIMPLE_SUBDIV = 16
 } CCGFlags;
 
 static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels,
@@ -133,7 +134,10 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels,
 
                ccgSubSurf_getUseAgeCounts(prevSS, &oldUseAging, NULL, NULL, NULL);
 
-               if (oldUseAging != useAging) {
+               if ((oldUseAging != useAging) ||
+                       (ccgSubSurf_getSimpleSubdiv(prevSS) !=
+                        !!(flags & CCG_SIMPLE_SUBDIV)))
+               {
                        ccgSubSurf_free(prevSS);
                }
                else {
@@ -156,6 +160,7 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels,
                ifc.vertDataSize += sizeof(float) * 3;
        if (flags & CCG_ALLOC_MASK)
                ifc.vertDataSize += sizeof(float);
+       ifc.simpleSubdiv = !!(flags & CCG_SIMPLE_SUBDIV);
 
        if (useArena) {
                CCGAllocatorIFC allocatorIFC;
@@ -3474,7 +3479,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
         float (*vertCos)[3],
         SubsurfFlags flags)
 {
-       int useSimple = smd->subdivType == ME_SIMPLE_SUBSURF;
+       int useSimple = (smd->subdivType == ME_SIMPLE_SUBSURF) ? CCG_SIMPLE_SUBDIV : 0;
        CCGFlags useAging = smd->flags & eSubsurfModifierFlag_DebugIncr ? CCG_USE_AGING : 0;
        int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv;
        int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges);
@@ -3483,7 +3488,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
        if (flags & SUBSURF_FOR_EDIT_MODE) {
                int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels) : smd->levels;
 
-               smd->emCache = _getSubSurf(smd->emCache, levels, 3, useAging | CCG_CALC_NORMALS);
+               smd->emCache = _getSubSurf(smd->emCache, levels, 3, useSimple | useAging | CCG_CALC_NORMALS);
                ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple);
 
                result = getCCGDerivedMesh(smd->emCache,
@@ -3498,7 +3503,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
                if (levels == 0)
                        return dm;
                
-               ss = _getSubSurf(NULL, levels, 3, CCG_USE_ARENA | CCG_CALC_NORMALS);
+               ss = _getSubSurf(NULL, levels, 3, useSimple | CCG_USE_ARENA | CCG_CALC_NORMALS);
 
                ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
 
@@ -3529,7 +3534,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
                }
 
                if (useIncremental && (flags & SUBSURF_IS_FINAL_CALC)) {
-                       smd->mCache = ss = _getSubSurf(smd->mCache, levels, 3, useAging | CCG_CALC_NORMALS);
+                       smd->mCache = ss = _getSubSurf(smd->mCache, levels, 3, useSimple | useAging | CCG_CALC_NORMALS);
 
                        ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
 
@@ -3538,7 +3543,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
                                                   useSubsurfUv, dm);
                }
                else {
-                       CCGFlags ccg_flags = CCG_USE_ARENA | CCG_CALC_NORMALS;
+                       CCGFlags ccg_flags = useSimple | CCG_USE_ARENA | CCG_CALC_NORMALS;
                        
                        if (smd->mCache && (flags & SUBSURF_IS_FINAL_CALC)) {
                                ccgSubSurf_free(smd->mCache);