From fda97809bc6521e746e56341d5c7e7f19864d52c Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Thu, 20 Aug 2009 17:37:38 +0000 Subject: [PATCH] 2.5 Multires: * Fixed a memory corruption bug when deleting a multiresmodifier, was hanging on to a bad pointer. Reported on IRC by lusque --- source/blender/blenkernel/BKE_multires.h | 5 +-- .../blender/blenkernel/intern/cdderivedmesh.c | 36 ++++++++++++------- source/blender/blenkernel/intern/modifier.c | 3 +- source/blender/blenkernel/intern/multires.c | 21 ++++++----- source/blender/blenloader/intern/readfile.c | 2 +- 5 files changed, 41 insertions(+), 26 deletions(-) diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 6558212519f..e7c7d92c955 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -35,10 +35,11 @@ struct Object; typedef struct MultiresSubsurf { struct MultiresModifierData *mmd; - struct Mesh *me; + struct Object *ob; } MultiresSubsurf; /* MultiresDM */ +struct Object *MultiresDM_get_object(struct DerivedMesh *dm); struct Mesh *MultiresDM_get_mesh(struct DerivedMesh *dm); struct DerivedMesh *MultiresDM_new(struct MultiresSubsurf *, struct DerivedMesh*, int, int, int); void *MultiresDM_get_vertnorm(struct DerivedMesh *); @@ -59,7 +60,7 @@ void multires_mark_as_modified(struct Object *ob); void multires_force_update(struct Object *ob); struct DerivedMesh *multires_dm_create_from_derived(struct MultiresModifierData*, struct DerivedMesh*, - struct Mesh *, int, int); + struct Object *, int, int); struct MultiresModifierData *find_multires_modifier(struct Object *ob); int multiresModifier_switch_level(struct Object *, const int); diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 706eece108c..4829be21ed8 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1297,7 +1297,7 @@ typedef struct MultiresDM { IndexNode *vert_face_map_mem, *vert_edge_map_mem; int *face_offsets; - Mesh *me; + Object *ob; int modified; void (*update)(DerivedMesh*); @@ -1308,15 +1308,19 @@ static void MultiresDM_release(DerivedMesh *dm) MultiresDM *mrdm = (MultiresDM*)dm; int mvert_layer; + /* Check that mmd still exists */ + if(BLI_findindex(&mrdm->ob->modifiers, mrdm->mmd) < 0) + mrdm->mmd = NULL; + /* Before freeing, need to update the displacement map */ - if(dm->needsFree && mrdm->modified) + if(dm->needsFree && mrdm->modified && mrdm->mmd) mrdm->update(dm); /* If the MVert data is being used as the sculpt undo store, don't free it */ mvert_layer = CustomData_get_layer_index(&dm->vertData, CD_MVERT); if(mvert_layer != -1) { CustomDataLayer *cd = &dm->vertData.layers[mvert_layer]; - if(cd->data == mrdm->mmd->undo_verts) + if(mrdm->mmd && cd->data == mrdm->mmd->undo_verts) cd->flag |= CD_FLAG_NOFREE; } @@ -1348,7 +1352,7 @@ DerivedMesh *MultiresDM_new(MultiresSubsurf *ms, DerivedMesh *orig, int numVerts dm = &mrdm->cddm.dm; mrdm->mmd = ms->mmd; - mrdm->me = ms->me; + mrdm->ob = ms->ob; if(dm) { MDisps *disps; @@ -1391,7 +1395,12 @@ DerivedMesh *MultiresDM_new(MultiresSubsurf *ms, DerivedMesh *orig, int numVerts Mesh *MultiresDM_get_mesh(DerivedMesh *dm) { - return ((MultiresDM*)dm)->me; + return get_mesh(((MultiresDM*)dm)->ob); +} + +Object *MultiresDM_get_object(DerivedMesh *dm) +{ + return ((MultiresDM*)dm)->ob; } void *MultiresDM_get_orco(DerivedMesh *dm) @@ -1428,10 +1437,11 @@ void MultiresDM_set_update(DerivedMesh *dm, void (*update)(DerivedMesh*)) ListBase *MultiresDM_get_vert_face_map(DerivedMesh *dm) { MultiresDM *mrdm = (MultiresDM*)dm; + Mesh *me = mrdm->ob->data; if(!mrdm->vert_face_map) - create_vert_face_map(&mrdm->vert_face_map, &mrdm->vert_face_map_mem, mrdm->me->mface, - mrdm->me->totvert, mrdm->me->totface); + create_vert_face_map(&mrdm->vert_face_map, &mrdm->vert_face_map_mem, me->mface, + me->totvert, me->totface); return mrdm->vert_face_map; } @@ -1439,10 +1449,11 @@ ListBase *MultiresDM_get_vert_face_map(DerivedMesh *dm) ListBase *MultiresDM_get_vert_edge_map(DerivedMesh *dm) { MultiresDM *mrdm = (MultiresDM*)dm; + Mesh *me = mrdm->ob->data; if(!mrdm->vert_edge_map) - create_vert_edge_map(&mrdm->vert_edge_map, &mrdm->vert_edge_map_mem, mrdm->me->medge, - mrdm->me->totvert, mrdm->me->totedge); + create_vert_edge_map(&mrdm->vert_edge_map, &mrdm->vert_edge_map_mem, me->medge, + me->totvert, me->totedge); return mrdm->vert_edge_map; } @@ -1450,6 +1461,7 @@ ListBase *MultiresDM_get_vert_edge_map(DerivedMesh *dm) int *MultiresDM_get_face_offsets(DerivedMesh *dm) { MultiresDM *mrdm = (MultiresDM*)dm; + Mesh *me = mrdm->ob->data; int i, accum = 0; if(!mrdm->face_offsets) { @@ -1457,11 +1469,11 @@ int *MultiresDM_get_face_offsets(DerivedMesh *dm) int area = len * len; int t = 1 + len * 3 + area * 3, q = t + len + area; - mrdm->face_offsets = MEM_callocN(sizeof(int) * mrdm->me->totface, "mrdm face offsets"); - for(i = 0; i < mrdm->me->totface; ++i) { + mrdm->face_offsets = MEM_callocN(sizeof(int) * me->totface, "mrdm face offsets"); + for(i = 0; i < me->totface; ++i) { mrdm->face_offsets[i] = accum; - accum += (mrdm->me->mface[i].v4 ? q : t); + accum += (me->mface[i].v4 ? q : t); } } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 1e2560bf809..4d567245ce1 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -8102,14 +8102,13 @@ static DerivedMesh *multiresModifier_applyModifier(ModifierData *md, Object *ob, int useRenderParams, int isFinalCalc) { MultiresModifierData *mmd = (MultiresModifierData*)md; - Mesh *me = get_mesh(ob); DerivedMesh *final; /* TODO: for now just skip a level1 mesh */ if(mmd->lvl == 1) return dm; - final = multires_dm_create_from_derived(mmd, dm, me, useRenderParams, isFinalCalc); + final = multires_dm_create_from_derived(mmd, dm, ob, useRenderParams, isFinalCalc); if(mmd->undo_signal && mmd->undo_verts && mmd->undo_verts_tot == final->getNumVerts(final)) { int i; MVert *dst = CDDM_get_verts(final); diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index e91f318adad..09a6c27a88c 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -204,10 +204,11 @@ static void VecAddUf(float a[3], float b[3]) a[2] += b[2]; } -static void multires_subdisp(DerivedMesh *orig, Mesh *me, DerivedMesh *final, int lvl, int totlvl, +static void multires_subdisp(DerivedMesh *orig, Object *ob, DerivedMesh *final, int lvl, int totlvl, int totsubvert, int totsubedge, int totsubface, int addverts) { DerivedMesh *mrdm; + Mesh *me = ob->data; MultiresModifierData mmd_sub; MVert *mvs = CDDM_get_verts(final); MVert *mvd, *mvd_f1, *mvs_f1, *mvd_f3, *mvd_f4; @@ -222,7 +223,7 @@ static void multires_subdisp(DerivedMesh *orig, Mesh *me, DerivedMesh *final, in memset(&mmd_sub, 0, sizeof(MultiresModifierData)); mmd_sub.lvl = mmd_sub.totlvl = totlvl; - mrdm = multires_dm_create_from_derived(&mmd_sub, orig, me, 0, 0); + mrdm = multires_dm_create_from_derived(&mmd_sub, orig, ob, 0, 0); mvd = CDDM_get_verts(mrdm); /* Need to map from ccg to mrdm */ @@ -395,7 +396,7 @@ static void multires_subdisp(DerivedMesh *orig, Mesh *me, DerivedMesh *final, in } } - final->needsFree = 1; + final->needsFree = 1; final->release(final); mrdm->needsFree = 1; MultiresDM_mark_as_modified(mrdm); @@ -468,7 +469,7 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int dista orig = CDDM_from_mesh(me, NULL); memset(&mmd_sub, 0, sizeof(MultiresModifierData)); mmd_sub.lvl = mmd_sub.totlvl = mmd->lvl; - mrdm = multires_dm_create_from_derived(&mmd_sub, orig, me, 0, 0); + mrdm = multires_dm_create_from_derived(&mmd_sub, orig, ob, 0, 0); totsubvert = mrdm->getNumVerts(mrdm); totsubedge = mrdm->getNumEdges(mrdm); totsubface = mrdm->getNumFaces(mrdm); @@ -497,7 +498,7 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int dista orig = CDDM_from_mesh(me, NULL); - multires_subdisp(orig, me, final, mmd->lvl, mmd->totlvl, totsubvert, totsubedge, totsubface, 0); + multires_subdisp(orig, ob, final, mmd->lvl, mmd->totlvl, totsubvert, totsubedge, totsubface, 0); orig->needsFree = 1; orig->release(orig); @@ -1166,9 +1167,11 @@ static void multiresModifier_disp_run(DerivedMesh *dm, MVert *subco, int invert) static void multiresModifier_update(DerivedMesh *dm) { + Object *ob; Mesh *me; MDisps *mdisps; + ob = MultiresDM_get_object(dm); me = MultiresDM_get_mesh(dm); mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); @@ -1189,7 +1192,7 @@ static void multiresModifier_update(DerivedMesh *dm) (includes older displacements but not new sculpts) */ mmd.totlvl = totlvl; mmd.lvl = lvl; - subco_dm = multires_dm_create_from_derived(&mmd, orig, me, 0, 0); + subco_dm = multires_dm_create_from_derived(&mmd, orig, ob, 0, 0); cur_lvl_orig_verts = CDDM_get_verts(subco_dm); /* Subtract the original vertex cos from the new vertex cos */ @@ -1199,7 +1202,7 @@ static void multiresModifier_update(DerivedMesh *dm) final = multires_subdisp_pre(dm, totlvl - lvl, 0); - multires_subdisp(orig, me, final, lvl, totlvl, dm->getNumVerts(dm), dm->getNumEdges(dm), + multires_subdisp(orig, ob, final, lvl, totlvl, dm->getNumVerts(dm), dm->getNumEdges(dm), dm->getNumFaces(dm), 1); subco_dm->release(subco_dm); @@ -1226,7 +1229,7 @@ void multires_force_update(Object *ob) } } -struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, DerivedMesh *dm, Mesh *me, +struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, DerivedMesh *dm, Object *ob, int useRenderParams, int isFinalCalc) { SubsurfModifierData smd; @@ -1235,7 +1238,7 @@ struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, D int i; ms.mmd = mmd; - ms.me = me; + ms.ob = ob; memset(&smd, 0, sizeof(SubsurfModifierData)); smd.levels = smd.renderLevels = mmd->lvl - 1; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 71994b97521..58b439e4cb4 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -9416,7 +9416,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) mmd->lvl = mmd->totlvl; orig = CDDM_from_mesh(me, NULL); - dm = multires_dm_create_from_derived(mmd, orig, me, 0, 0); + dm = multires_dm_create_from_derived(mmd, orig, ob, 0, 0); multires_load_old(dm, me->mr);