diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 4 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_modifier_types.h | 2 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_multires.c | 35 |
3 files changed, 34 insertions, 7 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 0094a6a2f57..ff79ba056e1 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5393,6 +5393,10 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) BevelModifierData *bmd = (BevelModifierData *)md; bmd->clnordata.faceHash = NULL; } + else if (md->type == eModifierType_Multires) { + MultiresModifierData *mmd = (MultiresModifierData *)md; + mmd->subdiv = NULL; + } } } diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 30c093ab3a8..101d655ded5 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -949,6 +949,8 @@ typedef struct MultiresModifierData { short quality; short uv_smooth; short pad2[2]; + struct Subdiv *subdiv; + void *pad3; } MultiresModifierData; typedef enum { diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c index fc8a376d2d7..9775a536e99 100644 --- a/source/blender/modifiers/intern/MOD_multires.c +++ b/source/blender/modifiers/intern/MOD_multires.c @@ -67,6 +67,28 @@ static void initData(ModifierData *md) mmd->quality = 3; } +static void freeData(ModifierData *md) +{ + MultiresModifierData *mmd = (MultiresModifierData *) md; + if (mmd->subdiv != NULL) { + BKE_subdiv_free(mmd->subdiv); + } +} + +/* Main goal of this function is to give usable subdivision surface descriptor + * which matches settings and topology. */ +static Subdiv *subdiv_descriptor_ensure(MultiresModifierData *mmd, + const SubdivSettings *subdiv_settings, + const Mesh *mesh) +{ + Subdiv *subdiv = BKE_subdiv_update_from_mesh( + mmd->subdiv, subdiv_settings, mesh); + if (false) { + mmd->subdiv = subdiv; + } + return subdiv; +} + /* Subdivide into fully qualified mesh. */ static Mesh *multires_as_mesh(MultiresModifierData *mmd, @@ -137,16 +159,14 @@ static Mesh *applyModifier(ModifierData *md, if (subdiv_settings.level == 0) { return result; } - /* TODO(sergey): Try to re-use subdiv when possible. */ - Subdiv *subdiv = BKE_subdiv_new_from_mesh(&subdiv_settings, mesh); + Subdiv *subdiv = subdiv_descriptor_ensure(mmd, &subdiv_settings, mesh); if (subdiv == NULL) { /* Happens on bad topology, ut also on empty input mesh. */ return result; } /* NOTE: Orco needs final coordinates on CPU side, which are expected to be * accessible via MVert. For this reason we do not evaluate multires to - * grids when orco is requested. - */ + * grids when orco is requested. */ const bool for_orco = (ctx->flag & MOD_APPLY_ORCO) != 0; if ((ctx->object->mode & OB_MODE_SCULPT) && !for_orco) { /* NOTE: CCG takes ownership over Subdiv. */ @@ -156,9 +176,10 @@ static Mesh *applyModifier(ModifierData *md, } else { result = multires_as_mesh(mmd, ctx, mesh, subdiv); - /* TODO(sergey): Cache subdiv somehow. */ // BKE_subdiv_stats_print(&subdiv->stats); - BKE_subdiv_free(subdiv); + if (subdiv != mmd->subdiv) { + BKE_subdiv_free(subdiv); + } } return result; } @@ -188,7 +209,7 @@ ModifierTypeInfo modifierType_Multires = { /* initData */ initData, /* requiredDataMask */ NULL, - /* freeData */ NULL, + /* freeData */ freeData, /* isDisabled */ NULL, /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, |