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/intern/multires.c
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/intern/multires.c')
-rw-r--r--source/blender/blenkernel/intern/multires.c123
1 files changed, 100 insertions, 23 deletions
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*/