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:
authorNicholas Bishop <nicholasbishop@gmail.com>2012-05-11 00:34:08 +0400
committerNicholas Bishop <nicholasbishop@gmail.com>2012-05-11 00:34:08 +0400
commitf4929ad609727354bb6356aef788e8f2fa92d341 (patch)
tree03d2957f2e35eb2f7075d406bedf747992f3c262 /source/blender/blenkernel
parent4c66616f4457098f344d6660a8b011a0bbcd9bbb (diff)
Add mask support to CCGSubSurf and multires.
* Add new CCG function ccgSubSurf_setAllocMask(). Similar to to ccgSubSurf_setCalcVertexNormals(), it sets whether the CCG elements have a mask layer and what that layer's offset is. Unlike normals however, it doesn't change any behavior during CCG calculation; it's there only to give CCGKey information on the mask. * Add a new flag to _getSubSurf(), CCG_ALLOC_MASK. If set, space for an extra layer is allocated, but the number of CCG layers is not set to include it. This is done because GridPaintMasks are absolute, rather than being relative to the subdivided output (as MDisp displacements are), so we skip subdividing paint masks here. * Add a new flag to subsurf_make_derived_from_derived(), SUBSURF_ALLOC_PAINT_MASK. This controls whether CCG_ALLOC_MASK is set for _getSubSurf(). Related, masks are never loaded in during ss_sync_from_derivedmesh(). After subdivision is finished, if the alloc mask flag is set, the number of CCG layers is increase to 4 with ccgSubSurf_setNumLayers(). * Add a new flag to multires_make_from_derived(), MULTIRES_ALLOC_PAINT_MASK. Not all multires functions need paint mask data (e.g. multiresModifier_base_apply.) This flag is always set in MOD_multires.c so that subdividing a mesh with a mask updates properly even when not in sculpt mode. * Update multiresModifier_disp_run() to apply, calculate, and add mask elements. It's almost the same as the existing operations with xyz coordinates, but treats masks as absolute rather than displacements relative to subdivided values. * Update multires_customdata_delete to free CD_GRID_PAINT_MASK in addition to CD_MDISPS. * Update multires_del_higher() to call the new function multires_grid_paint_mask_downsample(), which allocates a lower-resolution paint mask grid and copies values over from the high-resolution grid.
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_multires.h3
-rw-r--r--source/blender/blenkernel/BKE_subsurf.h3
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c18
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.h1
-rw-r--r--source/blender/blenkernel/intern/multires.c123
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c22
6 files changed, 143 insertions, 27 deletions
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index e695fb83c23..396f849def1 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -44,7 +44,7 @@ struct MultiresModifierData;
struct Object;
struct Scene;
-/* Delete mesh mdisps */
+/* Delete mesh mdisps and grid paint masks */
void multires_customdata_delete(struct Mesh *me);
void multires_mark_as_modified(struct Object *ob, enum MultiresModifiedFlags flags);
@@ -62,6 +62,7 @@ void multiresModifier_set_levels_from_disps(struct MultiresModifierData *mmd, st
typedef enum {
MULTIRES_USE_LOCAL_MMD = 1,
MULTIRES_USE_RENDER_PARAMS = 2,
+ MULTIRES_ALLOC_PAINT_MASK = 4
} MultiresFlags;
struct DerivedMesh *multires_make_derived_from_derived(struct DerivedMesh *dm,
diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h
index c4d23a327d7..60a1e6ab68f 100644
--- a/source/blender/blenkernel/BKE_subsurf.h
+++ b/source/blender/blenkernel/BKE_subsurf.h
@@ -59,7 +59,8 @@ typedef enum {
SUBSURF_USE_RENDER_PARAMS = 1,
SUBSURF_IS_FINAL_CALC = 2,
SUBSURF_FOR_EDIT_MODE = 4,
- SUBSURF_IN_EDIT_MODE = 8
+ SUBSURF_IN_EDIT_MODE = 8,
+ SUBSURF_ALLOC_PAINT_MASK = 16
} SubsurfFlags;
struct DerivedMesh *subsurf_make_derived_from_derived(
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index a15d5938641..42c9fa84a91 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -387,6 +387,10 @@ struct CCGSubSurf {
int calcVertNormals;
int normalDataOffset;
+ /* data for paint masks */
+ int allocMask;
+ int maskDataOffset;
+
/* data for age'ing (to debug sync) */
int currentAge;
int useAgeCounts;
@@ -852,6 +856,8 @@ CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *a
ss->calcVertNormals = 0;
ss->normalDataOffset = 0;
+ ss->allocMask = 0;
+
ss->q = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize);
ss->r = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize);
@@ -996,6 +1002,12 @@ CCGError ccgSubSurf_setCalcVertexNormals(CCGSubSurf *ss, int useVertNormals, int
return eCCGError_None;
}
+void ccgSubSurf_setAllocMask(CCGSubSurf *ss, int allocMask, int maskOffset)
+{
+ ss->allocMask = allocMask;
+ ss->maskDataOffset = maskOffset;
+}
+
void ccgSubSurf_setNumLayers(CCGSubSurf *ss, int numLayers)
{
ss->meshIFC.numLayers = numLayers;
@@ -3123,6 +3135,12 @@ void CCG_key(CCGKey *key, const CCGSubSurf *ss, int level)
key->grid_size = ccgSubSurf_getGridLevelSize(ss, level);
key->grid_area = key->grid_size * key->grid_size;
key->grid_bytes = key->elem_size * key->grid_area;
+
+ key->has_mask = ss->allocMask;
+ if (key->has_mask)
+ key->mask_offset = ss->maskDataOffset;
+ else
+ key->mask_offset = -1;
}
void CCG_key_top_level(CCGKey *key, const CCGSubSurf *ss)
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h
index 76e1911b0a5..33b37ac281c 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.h
+++ b/source/blender/blenkernel/intern/CCGSubSurf.h
@@ -76,6 +76,7 @@ void ccgSubSurf_getUseAgeCounts (CCGSubSurf *ss, int *useAgeCounts_r, int *ve
CCGError ccgSubSurf_setUseAgeCounts (CCGSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset);
CCGError ccgSubSurf_setCalcVertexNormals (CCGSubSurf *ss, int useVertNormals, int normalDataOffset);
+void ccgSubSurf_setAllocMask (CCGSubSurf *ss, int allocMask, int maskOffset);
void ccgSubSurf_setNumLayers (CCGSubSurf *ss, int numLayers);
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 73705ab3752..bd23e92fe9e 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -90,12 +90,17 @@ void multires_customdata_delete(Mesh *me)
CustomData_external_remove(&em->bm->ldata, &me->id,
CD_MDISPS, 0);
BM_data_layer_free(em->bm, &em->bm->ldata, CD_MDISPS);
+
+ BM_data_layer_free(em->bm, &em->bm->ldata, CD_GRID_PAINT_MASK);
}
else {
CustomData_external_remove(&me->ldata, &me->id,
CD_MDISPS, me->totloop);
CustomData_free_layer_active(&me->ldata, CD_MDISPS,
- me->totloop);
+ me->totloop);
+
+ CustomData_free_layer_active(&me->ldata, CD_GRID_PAINT_MASK,
+ me->totloop);
}
}
@@ -594,15 +599,40 @@ static void multires_copy_dm_grid(CCGElem *gridA, CCGElem *gridB, CCGKey *keyA,
}
}
+/* Reallocate gpm->data at a lower resolution and copy values over
+ from the original high-resolution data */
+static void multires_grid_paint_mask_downsample(GridPaintMask *gpm, int level)
+{
+ if (level < gpm->level) {
+ int gridsize = ccg_gridsize(level);
+ float *data = MEM_callocN(sizeof(float) * gridsize * gridsize,
+ "multires_grid_paint_mask_downsample");
+ int x, y;
+
+ for (y = 0; y < gridsize; y++) {
+ for (x = 0; x < gridsize; x++) {
+ data[y * gridsize + x] =
+ paint_grid_paint_mask(gpm, level, x, y);
+ }
+ }
+
+ MEM_freeN(gpm->data);
+ gpm->data = data;
+ gpm->level = level;
+ }
+}
+
static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
{
Mesh *me = (Mesh *)ob->data;
int levels = mmd->totlvl - lvl;
MDisps *mdisps;
+ GridPaintMask *gpm;
multires_set_tot_mdisps(me, mmd->totlvl);
CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
+ gpm = CustomData_get_layer(&me->ldata, CD_GRID_PAINT_MASK);
multires_force_update(ob);
@@ -615,7 +645,8 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
for (i = 0; i < me->totpoly; ++i) {
for (j = 0; j < me->mpoly[i].totloop; j++) {
- MDisps *mdisp = &mdisps[me->mpoly[i].loopstart + j];
+ int g = me->mpoly[i].loopstart + j;
+ MDisps *mdisp = &mdisps[g];
float (*disps)[3], (*ndisps)[3], (*hdisps)[3];
int totdisp = multires_grid_tot[lvl];
@@ -641,6 +672,8 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
mdisp->disps = disps;
mdisp->totdisp = totdisp;
mdisp->level = lvl;
+
+ multires_grid_paint_mask_downsample(&gpm[g], lvl);
}
}
}
@@ -673,9 +706,10 @@ void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int dire
multires_set_tot_level(ob, mmd, lvl);
}
-static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int totlvl, int simple)
+static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int totlvl, int simple, int alloc_paint_mask)
{
MultiresModifierData mmd = {{NULL}};
+ MultiresFlags flags = MULTIRES_USE_LOCAL_MMD;
mmd.lvl = lvl;
mmd.sculptlvl = lvl;
@@ -683,10 +717,13 @@ static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lv
mmd.totlvl = totlvl;
mmd.simple = simple;
- return multires_make_derived_from_derived(dm, &mmd, ob, MULTIRES_USE_LOCAL_MMD);
+ if (alloc_paint_mask)
+ flags |= MULTIRES_ALLOC_PAINT_MASK;
+
+ return multires_make_derived_from_derived(dm, &mmd, ob, flags);
}
-static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple, int optimal, int plain_uv)
+static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple, int optimal, int plain_uv, int alloc_paint_mask)
{
SubsurfModifierData smd = {{NULL}};
SubsurfFlags flags = 0;
@@ -701,6 +738,10 @@ static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl
if (ob->mode & OB_MODE_EDIT)
flags |= SUBSURF_IN_EDIT_MODE;
+
+ if (alloc_paint_mask)
+ flags |= SUBSURF_ALLOC_PAINT_MASK;
+
return subsurf_make_derived_from_derived(dm, &smd, NULL, flags);
}
@@ -737,7 +778,7 @@ void multiresModifier_base_apply(MultiresModifierData *mmd, Object *ob)
/* generate highest level with displacements */
cddm = CDDM_from_mesh(me, NULL);
DM_set_only_copy(cddm, CD_MASK_BAREMESH);
- dispdm = multires_dm_create_local(ob, cddm, totlvl, totlvl, 0);
+ dispdm = multires_dm_create_local(ob, cddm, totlvl, totlvl, 0, 0);
cddm->release(cddm);
/* copy the new locations of the base verts into the mesh */
@@ -827,7 +868,7 @@ void multiresModifier_base_apply(MultiresModifierData *mmd, Object *ob)
/* subdivide the mesh to highest level without displacements */
cddm = CDDM_from_mesh(me, NULL);
DM_set_only_copy(cddm, CD_MASK_BAREMESH);
- origdm = subsurf_dm_create_local(ob, cddm, totlvl, 0, 0, mmd->flags & eMultiresModifierFlag_PlainUv);
+ origdm = subsurf_dm_create_local(ob, cddm, totlvl, 0, 0, mmd->flags & eMultiresModifierFlag_PlainUv, 0);
cddm->release(cddm);
/* calc disps */
@@ -863,10 +904,11 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl
/* create subsurf DM from original mesh at high level */
cddm = CDDM_from_mesh(me, NULL);
DM_set_only_copy(cddm, CD_MASK_BAREMESH);
- highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv);
+ highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, TRUE);
+ ss = ((CCGDerivedMesh*)highdm)->ss;
/* create multires DM from original mesh at low level */
- lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple);
+ lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple, TRUE);
cddm->release(cddm);
/* copy subsurf grids and replace them with low displaced grids */
@@ -892,7 +934,6 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl
lowdm->release(lowdm);
/* subsurf higher levels again with displaced data */
- ss = ((CCGDerivedMesh *)highdm)->ss;
ccgSubSurf_updateFromFaces(ss, lvl, NULL, 0);
ccgSubSurf_updateLevels(ss, lvl, NULL, 0);
@@ -952,6 +993,7 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm
CCGKey key;
MPoly *mpoly = me->mpoly;
MDisps *mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
+ GridPaintMask *grid_paint_mask = NULL;
int *gridOffset;
int i, k, /*numGrids, */ gridSize, dGridSize, dSkip;
int totloop, totpoly;
@@ -985,6 +1027,10 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm
dGridSize = multires_side_tot[totlvl];
dSkip = (dGridSize - 1) / (gridSize - 1);
+ /* multires paint masks */
+ if (key.has_mask)
+ grid_paint_mask = CustomData_get_layer(&me->ldata, CD_GRID_PAINT_MASK);
+
k = 0; /*current loop/mdisp index within the mloop array*/
#pragma omp parallel for private(i) if (totloop*gridSize*gridSize >= CCG_OMP_LIMIT)
@@ -994,6 +1040,7 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm
int S, x, y, gIndex = gridOffset[i];
for (S = 0; S < numVerts; ++S, ++gIndex, ++k) {
+ GridPaintMask *gpm = grid_paint_mask ? &grid_paint_mask[gIndex] : NULL;
MDisps *mdisp = &mdisps[mpoly[i].loopstart + S];
CCGElem *grid = gridData[gIndex];
CCGElem *subgrid = subGridData[gIndex];
@@ -1008,13 +1055,22 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm
dispgrid = mdisp->disps;
+ /* if needed, reallocate multires paint mask */
+ if (gpm && op == CALC_DISPLACEMENTS) {
+ if (gpm->level < key.level) {
+ gpm->level = key.level;
+ MEM_freeN(gpm->data);
+ gpm->data = MEM_callocN(sizeof(float) * key.grid_area, "gpm.data");
+ }
+ }
+
for (y = 0; y < gridSize; y++) {
for (x = 0; x < gridSize; x++) {
float *co = CCG_grid_elem_co(&key, grid, x, y);
float *sco = CCG_grid_elem_co(&key, subgrid, x, y);
float *no = CCG_grid_elem_no(&key, subgrid, x, y);
- float *data = dispgrid[dGridSize * y * dSkip + x * dSkip];
- float mat[3][3], tx[3], ty[3], disp[3], d[3];
+ float *data = dispgrid[dGridSize*y*dSkip + x*dSkip];
+ float mat[3][3], tx[3], ty[3], disp[3], d[3], mask;
/* construct tangent space matrix */
grid_tangent(&key, x, y, 0, subGridData[gIndex], tx);
@@ -1051,11 +1107,31 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm
add_v3_v3(data, d);
break;
}
+
+ if (gpm) {
+ switch (op) {
+ case APPLY_DISPLACEMENTS:
+ /* Copy mask from gpm to DM */
+ *CCG_grid_elem_mask(&key, grid, x, y) =
+ paint_grid_paint_mask(gpm, key.level, x, y);
+ break;
+ case CALC_DISPLACEMENTS:
+ /* Copy mask from DM to gpm */
+ mask = *CCG_grid_elem_mask(&key, grid, x, y);
+ gpm->data[y * gridSize + x] = CLAMPIS(mask, 0, 1);
+ break;
+ case ADD_DISPLACEMENTS:
+ /* Add mask displacement to gpm */
+ gpm->data[y * gridSize + x] +=
+ *CCG_grid_elem_mask(&key, grid, x, y);
+ break;
+ }
+ }
}
}
}
}
-
+
if (op == APPLY_DISPLACEMENTS) {
ccgSubSurf_stitchFaces(ccgdm->ss, 0, NULL, 0);
ccgSubSurf_updateNormals(ccgdm->ss, NULL, 0);
@@ -1094,10 +1170,11 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm)
else cddm = CDDM_from_mesh(me, NULL);
DM_set_only_copy(cddm, CD_MASK_BAREMESH);
- highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv);
+ highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, TRUE);
+ ss = ((CCGDerivedMesh*)highdm)->ss;
/* create multires DM from original mesh and displacements */
- lowdm = multires_dm_create_local(ob, cddm, lvl, totlvl, mmd->simple);
+ lowdm = multires_dm_create_local(ob, cddm, lvl, totlvl, mmd->simple, TRUE);
cddm->release(cddm);
/* gather grid data */
@@ -1122,7 +1199,7 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm)
/* write difference of subsurf and displaced low level into high subsurf */
for (j = 0; j < lowGridSize*lowGridSize; ++j) {
- sub_v3_v3v3(CCG_elem_offset_co(&lowGridKey, diffGrid, j),
+ sub_v4_v4v4(CCG_elem_offset_co(&lowGridKey, diffGrid, j),
CCG_elem_offset_co(&lowGridKey, gridData[i], j),
CCG_elem_offset_co(&lowGridKey, lowGridData[i], j));
}
@@ -1135,7 +1212,6 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm)
lowdm->release(lowdm);
/* subsurf higher levels again with difference of coordinates */
- ss = ((CCGDerivedMesh *)highdm)->ss;
ccgSubSurf_updateFromFaces(ss, lvl, NULL, 0);
ccgSubSurf_updateLevels(ss, lvl, NULL, 0);
@@ -1155,7 +1231,7 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm)
else cddm = CDDM_from_mesh(me, NULL);
DM_set_only_copy(cddm, CD_MASK_BAREMESH);
- subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv);
+ subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, TRUE);
cddm->release(cddm);
multiresModifier_disp_run(dm, me, NULL, CALC_DISPLACEMENTS, subdm->getGridData(subdm), mmd->totlvl);
@@ -1218,10 +1294,10 @@ void multires_set_space(DerivedMesh *dm, Object *ob, int from, int to)
}
totlvl = mmd->totlvl;
- ccgdm = multires_dm_create_local(ob, dm, totlvl, totlvl, mmd->simple);
+ ccgdm = multires_dm_create_local(ob, dm, totlvl, totlvl, mmd->simple, FALSE);
subsurf = subsurf_dm_create_local(ob, dm, totlvl,
- mmd->simple, mmd->flags & eMultiresModifierFlag_ControlEdges, mmd->flags & eMultiresModifierFlag_PlainUv);
+ mmd->simple, mmd->flags & eMultiresModifierFlag_ControlEdges, mmd->flags & eMultiresModifierFlag_PlainUv, 0);
numGrids = subsurf->getNumGrids(subsurf);
gridSize = subsurf->getGridSize(subsurf);
@@ -1362,8 +1438,9 @@ DerivedMesh *multires_make_derived_from_derived(DerivedMesh *dm,
return dm;
result = subsurf_dm_create_local(ob, dm, lvl,
- mmd->simple, mmd->flags & eMultiresModifierFlag_ControlEdges,
- mmd->flags & eMultiresModifierFlag_PlainUv);
+ mmd->simple, mmd->flags & eMultiresModifierFlag_ControlEdges,
+ mmd->flags & eMultiresModifierFlag_PlainUv,
+ flags & MULTIRES_ALLOC_PAINT_MASK);
if (!(flags & MULTIRES_USE_LOCAL_MMD)) {
ccgdm = (CCGDerivedMesh *)result;
@@ -2101,7 +2178,7 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3])
MEM_freeN(vertCos);
/* scaled ccgDM for tangent space of object with applied scale */
- dm = subsurf_dm_create_local(ob, cddm, high_mmd.totlvl, high_mmd.simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv);
+ dm = subsurf_dm_create_local(ob, cddm, high_mmd.totlvl, high_mmd.simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, 0);
cddm->release(cddm);
/*numGrids = dm->getNumGrids(dm);*/ /*UNUSED*/
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 0a36ccbf8e5..c6b3a8d3aba 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -111,7 +111,9 @@ static void arena_release(CCGAllocatorHDL a)
typedef enum {
CCG_USE_AGING = 1,
CCG_USE_ARENA = 2,
- CCG_CALC_NORMALS = 4
+ CCG_CALC_NORMALS = 4,
+ /* add an extra four bytes for a mask layer */
+ CCG_ALLOC_MASK = 8
} CCGFlags;
static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels,
@@ -152,6 +154,8 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels,
normalOffset += sizeof(float) * numLayers;
if(flags & CCG_CALC_NORMALS)
ifc.vertDataSize += sizeof(float) * 3;
+ if(flags & CCG_ALLOC_MASK)
+ ifc.vertDataSize += sizeof(float);
if (useArena) {
CCGAllocatorIFC allocatorIFC;
@@ -172,6 +176,12 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels,
ccgSubSurf_setUseAgeCounts(ccgSS, 1, 8, 8, 8);
}
+ if (flags & CCG_ALLOC_MASK) {
+ normalOffset += sizeof(float);
+ /* mask is allocated after regular layers */
+ ccgSubSurf_setAllocMask(ccgSS, 1, sizeof(float) * numLayers);
+ }
+
if (flags & CCG_CALC_NORMALS)
ccgSubSurf_setCalcVertexNormals(ccgSS, 1, normalOffset);
else
@@ -3496,12 +3506,17 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
useSubsurfUv, dm);
}
else {
+ CCGFlags ccg_flags = CCG_USE_ARENA | CCG_CALC_NORMALS;
+
if (smd->mCache && (flags & SUBSURF_IS_FINAL_CALC)) {
ccgSubSurf_free(smd->mCache);
smd->mCache = NULL;
}
- ss = _getSubSurf(NULL, levels, 3, CCG_USE_ARENA | CCG_CALC_NORMALS);
+ if (flags & SUBSURF_ALLOC_PAINT_MASK)
+ ccg_flags |= CCG_ALLOC_MASK;
+
+ ss = _getSubSurf(NULL, levels, 3, ccg_flags);
ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm);
@@ -3510,6 +3525,9 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
smd->mCache = ss;
else
result->freeSS = 1;
+
+ if (flags & SUBSURF_ALLOC_PAINT_MASK)
+ ccgSubSurf_setNumLayers(ss, 4);
}
}