diff options
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/crazyspace.c | 448 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/paint.c | 241 |
3 files changed, 691 insertions, 1 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 26cc70e1089..228f4ce7730 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2251,7 +2251,8 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask, if ((ob->mode & OB_MODE_SCULPT) && ob->sculpt) { /* create PBVH immediately (would be created on the fly too, * but this avoids waiting on first stroke) */ - ob->sculpt->pbvh = ob->derivedFinal->getPBVH(ob, ob->derivedFinal); + + sculpt_update_mesh_elements(scene, scene->toolsettings->sculpt, ob, false, false); } BLI_assert(!(ob->derivedFinal->dirty & DM_DIRTY_NORMALS)); diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c new file mode 100644 index 00000000000..610a0fe0fbc --- /dev/null +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -0,0 +1,448 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/crazyspace.c + * \ingroup bke + */ + + +#include "MEM_guardedalloc.h" + +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_modifier_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BLI_utildefines.h" +#include "BLI_math.h" +#include "BLI_bitmap.h" + +#include "BKE_crazyspace.h" +#include "BKE_DerivedMesh.h" +#include "BKE_modifier.h" +#include "BKE_multires.h" +#include "BKE_mesh.h" +#include "BKE_editmesh.h" + +typedef struct { + float (*vertexcos)[3]; + BLI_bitmap *vertex_visit; +} MappedUserData; + +BLI_INLINE void tan_calc_quat_v3( + float r_quat[4], + const float co_1[3], const float co_2[3], const float co_3[3]) +{ + float vec_u[3], vec_v[3]; + float nor[3]; + + sub_v3_v3v3(vec_u, co_1, co_2); + sub_v3_v3v3(vec_v, co_1, co_3); + + cross_v3_v3v3(nor, vec_u, vec_v); + + if (normalize_v3(nor) > FLT_EPSILON) { + const float zero_vec[3] = {0.0f}; + tri_to_quat_ex(r_quat, zero_vec, vec_u, vec_v, nor); + } + else { + unit_qt(r_quat); + } +} + +static void set_crazy_vertex_quat( + float r_quat[4], + const float co_1[3], const float co_2[3], const float co_3[3], + const float vd_1[3], const float vd_2[3], const float vd_3[3]) +{ + float q1[4], q2[4]; + + tan_calc_quat_v3(q1, co_1, co_2, co_3); + tan_calc_quat_v3(q2, vd_1, vd_2, vd_3); + + sub_qt_qtqt(r_quat, q2, q1); +} + +static void make_vertexcos__mapFunc(void *userData, int index, const float co[3], + const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) +{ + MappedUserData *mappedData = (MappedUserData *)userData; + + if (BLI_BITMAP_GET(mappedData->vertex_visit, index) == 0) { + /* we need coord from prototype vertex, not from copies, + * assume they stored in the beginning of vertex array stored in DM + * (mirror modifier for eg does this) */ + copy_v3_v3(mappedData->vertexcos[index], co); + BLI_BITMAP_SET(mappedData->vertex_visit, index); + } +} + +static int modifiers_disable_subsurf_temporary(Object *ob) +{ + ModifierData *md; + int disabled = 0; + + for (md = ob->modifiers.first; md; md = md->next) + if (md->type == eModifierType_Subsurf) + if (md->mode & eModifierMode_OnCage) { + md->mode ^= eModifierMode_DisableTemporary; + disabled = 1; + } + + return disabled; +} + +/* disable subsurf temporal, get mapped cos, and enable it */ +float (*crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3] +{ + Mesh *me = obedit->data; + DerivedMesh *dm; + float (*vertexcos)[3]; + int nverts = me->edit_btmesh->bm->totvert; + BLI_bitmap *vertex_visit; + MappedUserData userData; + + /* disable subsurf temporal, get mapped cos, and enable it */ + if (modifiers_disable_subsurf_temporary(obedit)) { + /* need to make new derivemesh */ + makeDerivedMesh(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH, 0); + } + + /* now get the cage */ + dm = editbmesh_get_derived_cage(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH); + + vertexcos = MEM_callocN(sizeof(*vertexcos) * nverts, "vertexcos map"); + vertex_visit = BLI_BITMAP_NEW(nverts, "vertexcos flags"); + + userData.vertexcos = vertexcos; + userData.vertex_visit = vertex_visit; + dm->foreachMappedVert(dm, make_vertexcos__mapFunc, &userData, DM_FOREACH_NOP); + + dm->release(dm); + + /* set back the flag, no new cage needs to be built, transform does it */ + modifiers_disable_subsurf_temporary(obedit); + + MEM_freeN(vertex_visit); + + return vertexcos; +} + +void crazyspace_set_quats_editmesh(BMEditMesh *em, float (*origcos)[3], float (*mappedcos)[3], float (*quats)[4], + const bool use_select) +{ + BMFace *f; + BMIter iter; + int index; + + { + BMVert *v; + BM_ITER_MESH_INDEX (v, &iter, em->bm, BM_VERTS_OF_MESH, index) { + BM_elem_flag_disable(v, BM_ELEM_TAG); + BM_elem_index_set(v, index); /* set_inline */ + } + em->bm->elem_index_dirty &= ~BM_VERT; + } + + BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { + BMLoop *l_iter, *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter->v, BM_ELEM_HIDDEN) || + BM_elem_flag_test(l_iter->v, BM_ELEM_TAG) || + (use_select && !BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT))) + { + continue; + } + + if (!BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) { + const float *co_prev, *co_curr, *co_next; /* orig */ + const float *vd_prev, *vd_curr, *vd_next; /* deform */ + + const int i_prev = BM_elem_index_get(l_iter->prev->v); + const int i_curr = BM_elem_index_get(l_iter->v); + const int i_next = BM_elem_index_get(l_iter->next->v); + + /* retrieve mapped coordinates */ + vd_prev = mappedcos[i_prev]; + vd_curr = mappedcos[i_curr]; + vd_next = mappedcos[i_next]; + + if (origcos) { + co_prev = origcos[i_prev]; + co_curr = origcos[i_curr]; + co_next = origcos[i_next]; + } + else { + co_prev = l_iter->prev->v->co; + co_curr = l_iter->v->co; + co_next = l_iter->next->v->co; + } + + set_crazy_vertex_quat(quats[i_curr], + co_curr, co_next, co_prev, + vd_curr, vd_next, vd_prev); + + BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG); + } + } while ((l_iter = l_iter->next) != l_first); + } +} + +void crazyspace_set_quats_mesh(Mesh *me, float (*origcos)[3], float (*mappedcos)[3], float (*quats)[4]) +{ + int i; + MVert *mvert; + MLoop *mloop; + MPoly *mp; + + mvert = me->mvert; + for (i = 0; i < me->totvert; i++, mvert++) + mvert->flag &= ~ME_VERT_TMP_TAG; + + /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */ + mvert = me->mvert; + mp = me->mpoly; + mloop = me->mloop; + + for (i = 0; i < me->totpoly; i++, mp++) { + MLoop *ml_prev, *ml_curr, *ml_next; + int j; + + ml_next = &mloop[mp->loopstart]; + ml_curr = &ml_next[mp->totloop - 1]; + ml_prev = &ml_next[mp->totloop - 2]; + + for (j = 0; j < mp->totloop; j++) { + if ((mvert[ml_curr->v].flag & ME_VERT_TMP_TAG) == 0) { + const float *co_prev, *co_curr, *co_next; /* orig */ + const float *vd_prev, *vd_curr, *vd_next; /* deform */ + + /* retrieve mapped coordinates */ + vd_prev = mappedcos[ml_prev->v]; + vd_curr = mappedcos[ml_curr->v]; + vd_next = mappedcos[ml_next->v]; + + if (origcos) { + co_prev = origcos[ml_prev->v]; + co_curr = origcos[ml_curr->v]; + co_next = origcos[ml_next->v]; + } + else { + co_prev = mvert[ml_prev->v].co; + co_curr = mvert[ml_curr->v].co; + co_next = mvert[ml_next->v].co; + } + + set_crazy_vertex_quat(quats[ml_curr->v], + co_curr, co_next, co_prev, + vd_curr, vd_next, vd_prev); + + mvert[ml_curr->v].flag |= ME_VERT_TMP_TAG; + } + + ml_prev = ml_curr; + ml_curr = ml_next; + ml_next++; + } + } +} + +int editbmesh_get_first_deform_matrices(Scene *scene, Object *ob, BMEditMesh *em, + float (**deformmats)[3][3], float (**deformcos)[3]) +{ + ModifierData *md; + DerivedMesh *dm; + int i, a, numleft = 0, numVerts = 0; + int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1); + float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL; + VirtualModifierData virtualModifierData; + + modifiers_clearErrors(ob); + + dm = NULL; + md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + + /* compute the deformation matrices and coordinates for the first + * modifiers with on cage editing that are enabled and support computing + * deform matrices */ + for (i = 0; md && i <= cageIndex; i++, md = md->next) { + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (!editbmesh_modifier_is_enabled(scene, md, dm)) + continue; + + if (mti->type == eModifierTypeType_OnlyDeform && mti->deformMatricesEM) { + if (!defmats) { + dm = getEditDerivedBMesh(em, ob, NULL); + deformedVerts = editbmesh_get_vertex_cos(em, &numVerts); + defmats = MEM_mallocN(sizeof(*defmats) * numVerts, "defmats"); + + for (a = 0; a < numVerts; a++) + unit_m3(defmats[a]); + } + + mti->deformMatricesEM(md, ob, em, dm, deformedVerts, defmats, + numVerts); + } + else + break; + } + + for (; md && i <= cageIndex; md = md->next, i++) + if (editbmesh_modifier_is_enabled(scene, md, dm) && modifier_isCorrectableDeformed(md)) + numleft++; + + if (dm) + dm->release(dm); + + *deformmats = defmats; + *deformcos = deformedVerts; + + return numleft; +} + +int sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]) +{ + ModifierData *md; + DerivedMesh *dm; + int a, numVerts = 0; + float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL; + MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0); + const bool has_multires = mmd != NULL && mmd->sculptlvl > 0; + int numleft = 0; + VirtualModifierData virtualModifierData; + + if (has_multires) { + *deformmats = NULL; + *deformcos = NULL; + return numleft; + } + + dm = NULL; + md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + + for (; md; md = md->next) { + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue; + + if (mti->type == eModifierTypeType_OnlyDeform) { + if (!defmats) { + Mesh *me = (Mesh *)ob->data; + dm = mesh_create_derived(me, NULL); + deformedVerts = BKE_mesh_vertexCos_get(me, &numVerts); + defmats = MEM_callocN(sizeof(*defmats) * numVerts, "defmats"); + + for (a = 0; a < numVerts; a++) + unit_m3(defmats[a]); + } + + if (mti->deformMatrices) mti->deformMatrices(md, ob, dm, deformedVerts, defmats, numVerts); + else break; + } + } + + for (; md; md = md->next) { + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue; + + if (mti->type == eModifierTypeType_OnlyDeform) + numleft++; + } + + if (dm) + dm->release(dm); + + *deformmats = defmats; + *deformcos = deformedVerts; + + return numleft; +} + +void crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]) +{ + int totleft = sculpt_get_first_deform_matrices(scene, ob, deformmats, deformcos); + + if (totleft) { + /* there are deformation modifier which doesn't support deformation matrices + * calculation. Need additional crazyspace correction */ + + float (*deformedVerts)[3] = *deformcos; + float (*origVerts)[3] = MEM_dupallocN(deformedVerts); + float (*quats)[4]; + int i, deformed = 0; + VirtualModifierData virtualModifierData; + ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + Mesh *me = (Mesh *)ob->data; + + for (; md; md = md->next) { + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue; + + if (mti->type == eModifierTypeType_OnlyDeform) { + /* skip leading modifiers which have been already + * handled in sculpt_get_first_deform_matrices */ + if (mti->deformMatrices && !deformed) + continue; + + mti->deformVerts(md, ob, NULL, deformedVerts, me->totvert, 0); + deformed = 1; + } + } + + quats = MEM_mallocN(me->totvert * sizeof(*quats), "crazy quats"); + + crazyspace_set_quats_mesh(me, origVerts, deformedVerts, quats); + + for (i = 0; i < me->totvert; i++) { + float qmat[3][3], tmat[3][3]; + + quat_to_mat3(qmat, quats[i]); + mul_m3_m3m3(tmat, qmat, (*deformmats)[i]); + copy_m3_m3((*deformmats)[i], tmat); + } + + MEM_freeN(origVerts); + MEM_freeN(quats); + } + + if (*deformmats == NULL) { + int a, numVerts; + Mesh *me = (Mesh *)ob->data; + + *deformcos = BKE_mesh_vertexCos_get(me, &numVerts); + *deformmats = MEM_callocN(sizeof(*(*deformmats)) * numVerts, "defmats"); + + for (a = 0; a < numVerts; a++) + unit_m3((*deformmats)[a]); + } +} diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 1189b5715bb..d5059566dab 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -37,6 +37,7 @@ #include "DNA_object_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_scene_types.h" #include "DNA_brush_types.h" #include "DNA_space_types.h" @@ -47,10 +48,14 @@ #include "BKE_brush.h" #include "BKE_context.h" +#include "BKE_crazyspace.h" #include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_key.h" #include "BKE_library.h" +#include "BKE_mesh.h" +#include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_pbvh.h" @@ -499,3 +504,239 @@ void free_sculptsession(Object *ob) ob->sculpt = NULL; } } + +/* Sculpt mode handles multires differently from regular meshes, but only if + * it's the last modifier on the stack and it is not on the first level */ +MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob) +{ + Mesh *me = (Mesh *)ob->data; + ModifierData *md; + VirtualModifierData virtualModifierData; + + if (ob->sculpt && ob->sculpt->bm) { + /* can't combine multires and dynamic topology */ + return NULL; + } + + if (!CustomData_get_layer(&me->ldata, CD_MDISPS)) { + /* multires can't work without displacement layer */ + return NULL; + } + + for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); md; md = md->next) { + if (md->type == eModifierType_Multires) { + MultiresModifierData *mmd = (MultiresModifierData *)md; + + if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) + continue; + + if (mmd->sculptlvl > 0) return mmd; + else return NULL; + } + } + + return NULL; +} + + +/* Checks if there are any supported deformation modifiers active */ +static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob) +{ + ModifierData *md; + Mesh *me = (Mesh *)ob->data; + MultiresModifierData *mmd = sculpt_multires_active(scene, ob); + VirtualModifierData virtualModifierData; + + if (mmd || ob->sculpt->bm) + return 0; + + /* non-locked shape keys could be handled in the same way as deformed mesh */ + if ((ob->shapeflag & OB_SHAPE_LOCK) == 0 && me->key && ob->shapenr) + return 1; + + md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + + /* exception for shape keys because we can edit those */ + for (; md; md = md->next) { + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue; + if (md->type == eModifierType_ShapeKey) continue; + + if (mti->type == eModifierTypeType_OnlyDeform) return 1; + else if ((sd->flags & SCULPT_ONLY_DEFORM) == 0) return 1; + } + + return 0; +} + +/** + * \param need_mask So the DerivedMesh thats returned has mask data + */ +void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, + bool need_pmap, bool need_mask) +{ + DerivedMesh *dm; + SculptSession *ss = ob->sculpt; + Mesh *me = ob->data; + MultiresModifierData *mmd = sculpt_multires_active(scene, ob); + + ss->modifiers_active = sculpt_modifiers_active(scene, sd, ob); + ss->show_diffuse_color = (sd->flags & SCULPT_SHOW_DIFFUSE) != 0; + + if (need_mask) { + if (mmd == NULL) { + if (!CustomData_has_layer(&me->vdata, CD_PAINT_MASK)) { + ED_sculpt_mask_layers_ensure(ob, NULL); + } + } + else { + if (!CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK)) { +#if 1 + ED_sculpt_mask_layers_ensure(ob, mmd); +#else /* if we wanted to support adding mask data while multi-res painting, we would need to do this */ + if ((ED_sculpt_mask_layers_ensure(ob, mmd) & ED_SCULPT_MASK_LAYER_CALC_LOOP)) { + /* remake the derived mesh */ + ob->recalc |= OB_RECALC_DATA; + BKE_object_handle_update(scene, ob); + } +#endif + } + } + } + + /* BMESH ONLY --- at some point we should move sculpt code to use polygons only - but for now it needs tessfaces */ + BKE_mesh_tessface_ensure(me); + + if (!mmd) ss->kb = BKE_keyblock_from_object(ob); + else ss->kb = NULL; + + /* needs to be called after we ensure tessface */ + dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + + if (mmd) { + ss->multires = mmd; + ss->totvert = dm->getNumVerts(dm); + ss->totpoly = dm->getNumPolys(dm); + ss->mvert = NULL; + ss->mpoly = NULL; + ss->mloop = NULL; + ss->face_normals = NULL; + } + else { + ss->totvert = me->totvert; + ss->totpoly = me->totpoly; + ss->mvert = me->mvert; + ss->mpoly = me->mpoly; + ss->mloop = me->mloop; + ss->face_normals = NULL; + ss->multires = NULL; + ss->vmask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK); + } + + ss->pbvh = dm->getPBVH(ob, dm); + ss->pmap = (need_pmap && dm->getPolyMap) ? dm->getPolyMap(ob, dm) : NULL; + + pbvh_show_diffuse_color_set(ss->pbvh, ss->show_diffuse_color); + + if (ss->modifiers_active) { + if (!ss->orig_cos) { + int a; + + free_sculptsession_deformMats(ss); + + ss->orig_cos = (ss->kb) ? BKE_key_convert_to_vertcos(ob, ss->kb) : BKE_mesh_vertexCos_get(me, NULL); + + crazyspace_build_sculpt(scene, ob, &ss->deform_imats, &ss->deform_cos); + BKE_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos); + + for (a = 0; a < me->totvert; ++a) { + invert_m3(ss->deform_imats[a]); + } + } + } + else { + free_sculptsession_deformMats(ss); + } + + /* if pbvh is deformed, key block is already applied to it */ + if (ss->kb && !BKE_pbvh_isDeformed(ss->pbvh)) { + float (*vertCos)[3] = BKE_key_convert_to_vertcos(ob, ss->kb); + + if (vertCos) { + /* apply shape keys coordinates to PBVH */ + BKE_pbvh_apply_vertCos(ss->pbvh, vertCos); + MEM_freeN(vertCos); + } + } +} + +int ED_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd) +{ + const float *paint_mask; + Mesh *me = ob->data; + int ret = 0; + + paint_mask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK); + + /* if multires is active, create a grid paint mask layer if there + * isn't one already */ + if (mmd && !CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK)) { + GridPaintMask *gmask; + int level = max_ii(1, mmd->sculptlvl); + int gridsize = BKE_ccg_gridsize(level); + int gridarea = gridsize * gridsize; + int i, j; + + gmask = CustomData_add_layer(&me->ldata, CD_GRID_PAINT_MASK, + CD_CALLOC, NULL, me->totloop); + + for (i = 0; i < me->totloop; i++) { + GridPaintMask *gpm = &gmask[i]; + + gpm->level = level; + gpm->data = MEM_callocN(sizeof(float) * gridarea, + "GridPaintMask.data"); + } + + /* if vertices already have mask, copy into multires data */ + if (paint_mask) { + for (i = 0; i < me->totpoly; i++) { + const MPoly *p = &me->mpoly[i]; + float avg = 0; + + /* mask center */ + for (j = 0; j < p->totloop; j++) { + const MLoop *l = &me->mloop[p->loopstart + j]; + avg += paint_mask[l->v]; + } + avg /= (float)p->totloop; + + /* fill in multires mask corner */ + for (j = 0; j < p->totloop; j++) { + GridPaintMask *gpm = &gmask[p->loopstart + j]; + const MLoop *l = &me->mloop[p->loopstart + j]; + const MLoop *prev = ME_POLY_LOOP_PREV(me->mloop, p, j); + const MLoop *next = ME_POLY_LOOP_NEXT(me->mloop, p, j); + + gpm->data[0] = avg; + gpm->data[1] = (paint_mask[l->v] + + paint_mask[next->v]) * 0.5f; + gpm->data[2] = (paint_mask[l->v] + + paint_mask[prev->v]) * 0.5f; + gpm->data[3] = paint_mask[l->v]; + } + } + } + + ret |= ED_SCULPT_MASK_LAYER_CALC_LOOP; + } + + /* create vertex paint mask layer if there isn't one already */ + if (!paint_mask) { + CustomData_add_layer(&me->vdata, CD_PAINT_MASK, + CD_CALLOC, NULL, me->totvert); + ret |= ED_SCULPT_MASK_LAYER_CALC_VERT; + } + + return ret; +} |