Fix simple subsurf on wire edges

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
This commit is contained in:
Nicholas Bishop 2012-08-18 19:54:21 +00:00
parent e30ed91b90
commit 12425588f2
3 changed files with 21 additions and 9 deletions

@ -1798,7 +1798,7 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
if (seamEdges < 2 || seamEdges != v->numEdges) if (seamEdges < 2 || seamEdges != v->numEdges)
seam = 0; seam = 0;
if (!v->numEdges) { if (!v->numEdges || ss->meshIFC.simpleSubdiv) {
VertDataCopy(nCo, co, ss); VertDataCopy(nCo, co, ss);
} }
else if (_vert_isBoundary(v)) { else if (_vert_isBoundary(v)) {
@ -2246,7 +2246,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss)
if (seamEdges < 2 || seamEdges != v->numEdges) if (seamEdges < 2 || seamEdges != v->numEdges)
seam = 0; seam = 0;
if (!v->numEdges) { if (!v->numEdges || ss->meshIFC.simpleSubdiv) {
VertDataCopy(nCo, co, ss); VertDataCopy(nCo, co, ss);
} }
else if (_vert_isBoundary(v)) { 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 */ /* Vert accessors */
CCGVertHDL ccgSubSurf_getVertVertHandle(CCGVert *v) CCGVertHDL ccgSubSurf_getVertVertHandle(CCGVert *v)

@ -17,6 +17,7 @@ typedef struct CCGMeshIFC {
int vertUserSize, edgeUserSize, faceUserSize; int vertUserSize, edgeUserSize, faceUserSize;
int numLayers; int numLayers;
int vertDataSize; int vertDataSize;
int simpleSubdiv;
} CCGMeshIFC; } CCGMeshIFC;
/***/ /***/
@ -91,6 +92,7 @@ int ccgSubSurf_getEdgeSize (const CCGSubSurf *ss);
int ccgSubSurf_getEdgeLevelSize (const CCGSubSurf *ss, int level); int ccgSubSurf_getEdgeLevelSize (const CCGSubSurf *ss, int level);
int ccgSubSurf_getGridSize (const CCGSubSurf *ss); int ccgSubSurf_getGridSize (const CCGSubSurf *ss);
int ccgSubSurf_getGridLevelSize (const CCGSubSurf *ss, int level); int ccgSubSurf_getGridLevelSize (const CCGSubSurf *ss, int level);
int ccgSubSurf_getSimpleSubdiv (const CCGSubSurf *ss);
CCGVert* ccgSubSurf_getVert (CCGSubSurf *ss, CCGVertHDL v); CCGVert* ccgSubSurf_getVert (CCGSubSurf *ss, CCGVertHDL v);
CCGVertHDL ccgSubSurf_getVertVertHandle (CCGVert *v); CCGVertHDL ccgSubSurf_getVertVertHandle (CCGVert *v);

@ -113,7 +113,8 @@ typedef enum {
CCG_USE_ARENA = 2, CCG_USE_ARENA = 2,
CCG_CALC_NORMALS = 4, CCG_CALC_NORMALS = 4,
/* add an extra four bytes for a mask layer */ /* add an extra four bytes for a mask layer */
CCG_ALLOC_MASK = 8 CCG_ALLOC_MASK = 8,
CCG_SIMPLE_SUBDIV = 16
} CCGFlags; } CCGFlags;
static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, 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); ccgSubSurf_getUseAgeCounts(prevSS, &oldUseAging, NULL, NULL, NULL);
if (oldUseAging != useAging) { if ((oldUseAging != useAging) ||
(ccgSubSurf_getSimpleSubdiv(prevSS) !=
!!(flags & CCG_SIMPLE_SUBDIV)))
{
ccgSubSurf_free(prevSS); ccgSubSurf_free(prevSS);
} }
else { else {
@ -156,6 +160,7 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels,
ifc.vertDataSize += sizeof(float) * 3; ifc.vertDataSize += sizeof(float) * 3;
if (flags & CCG_ALLOC_MASK) if (flags & CCG_ALLOC_MASK)
ifc.vertDataSize += sizeof(float); ifc.vertDataSize += sizeof(float);
ifc.simpleSubdiv = !!(flags & CCG_SIMPLE_SUBDIV);
if (useArena) { if (useArena) {
CCGAllocatorIFC allocatorIFC; CCGAllocatorIFC allocatorIFC;
@ -3474,7 +3479,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
float (*vertCos)[3], float (*vertCos)[3],
SubsurfFlags flags) 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; CCGFlags useAging = smd->flags & eSubsurfModifierFlag_DebugIncr ? CCG_USE_AGING : 0;
int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv; int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv;
int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges); int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges);
@ -3483,7 +3488,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
if (flags & SUBSURF_FOR_EDIT_MODE) { if (flags & SUBSURF_FOR_EDIT_MODE) {
int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels) : smd->levels; 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); ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple);
result = getCCGDerivedMesh(smd->emCache, result = getCCGDerivedMesh(smd->emCache,
@ -3498,7 +3503,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
if (levels == 0) if (levels == 0)
return dm; 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); 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)) { 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); ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
@ -3538,7 +3543,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
useSubsurfUv, dm); useSubsurfUv, dm);
} }
else { 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)) { if (smd->mCache && (flags & SUBSURF_IS_FINAL_CALC)) {
ccgSubSurf_free(smd->mCache); ccgSubSurf_free(smd->mCache);