diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2019-03-18 17:56:16 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2019-03-18 19:11:43 +0300 |
commit | 8fb0b9aebbd409216dec77c4b1bf2a2fbba80698 (patch) | |
tree | 5de8ac995f5eac6d5c7c299ea5c4228aacac33fd /source/blender/modifiers/intern/MOD_subsurf.c | |
parent | 91ffd39e77498b81634750527aa5069c950a4d59 (diff) |
Subdiv: Enable topology cache in edit mode
The general idea of this change is to have a runtime data pointer
in the ModifierData, so it can be preserved through copy-on-write
updates by the dependency graph.
This is where subdivision surface modifier can store its topology
cache, so it is not getting trashed on every copy-on-write which
is happening when moving a vertex.
Similar mechanism should be used by multiresolution, dynamic paint
and some other modifiers which cache evaluated data.
This fixes T61746.
Thing to keep in mind, that there are more reports about slow
subdivision surface in the tracker, but that boils down to the
fact that those have a lot of extraordinary vertices, and hence
a lot slower to evaluated topology.
Other thing is, this speeds up oeprations which doesn't change
topology (i.e. moving vertices).
Reviewers: brecht
Reviewed By: brecht
Maniphest Tasks: T61746
Differential Revision: https://developer.blender.org/D4541
Diffstat (limited to 'source/blender/modifiers/intern/MOD_subsurf.c')
-rw-r--r-- | source/blender/modifiers/intern/MOD_subsurf.c | 45 |
1 files changed, 38 insertions, 7 deletions
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index 1899faa3583..c092b3f3621 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -24,6 +24,8 @@ #include <stddef.h> +#include "MEM_guardedalloc.h" + #include "BLI_utildefines.h" #include "DNA_object_types.h" @@ -44,6 +46,11 @@ #include "intern/CCGSubSurf.h" +typedef struct SubsurfRuntimeData { + /* Cached subdivision surface descriptor, with topology and settings. */ + struct Subdiv *subdiv; +} SubsurfRuntimeData; + static void initData(ModifierData *md) { SubsurfModifierData *smd = (SubsurfModifierData *) md; @@ -64,7 +71,18 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla modifier_copyData_generic(md, target, flag); tsmd->emCache = tsmd->mCache = NULL; - tsmd->subdiv = NULL; +} + +static void freeRuntimeData(void *runtime_data_v) +{ + if (runtime_data_v == NULL) { + return; + } + SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)runtime_data_v; + if (runtime_data->subdiv != NULL) { + BKE_subdiv_free(runtime_data->subdiv); + } + MEM_freeN(runtime_data); } static void freeData(ModifierData *md) @@ -79,9 +97,7 @@ static void freeData(ModifierData *md) ccgSubSurf_free(smd->emCache); smd->emCache = NULL; } - if (smd->subdiv != NULL) { - BKE_subdiv_free(smd->subdiv); - } + freeRuntimeData(smd->modifier.runtime); } static bool isDisabled(const Scene *scene, ModifierData *md, bool useRenderParams) @@ -121,9 +137,11 @@ static Subdiv *subdiv_descriptor_ensure(SubsurfModifierData *smd, const SubdivSettings *subdiv_settings, const Mesh *mesh) { + SubsurfRuntimeData *runtime_data = + (SubsurfRuntimeData *)smd->modifier.runtime; Subdiv *subdiv = BKE_subdiv_update_from_mesh( - smd->subdiv, subdiv_settings, mesh); - smd->subdiv = subdiv; + runtime_data->subdiv, subdiv_settings, mesh); + runtime_data->subdiv = subdiv; return subdiv; } @@ -181,6 +199,17 @@ static Mesh *subdiv_as_ccg(SubsurfModifierData *smd, return result; } +static SubsurfRuntimeData *subsurf_ensure_runtime(SubsurfModifierData *smd) +{ + SubsurfRuntimeData *runtime_data = + (SubsurfRuntimeData *)smd->modifier.runtime; + if (runtime_data == NULL) { + runtime_data = MEM_callocN(sizeof(*runtime_data), "subsurf runtime"); + smd->modifier.runtime = runtime_data; + } + return runtime_data; +} + /* Modifier itself. */ static Mesh *applyModifier(ModifierData *md, @@ -195,6 +224,7 @@ static Mesh *applyModifier(ModifierData *md, return result; } BKE_subdiv_settings_validate_for_mesh(&subdiv_settings, mesh); + SubsurfRuntimeData *runtime_data = subsurf_ensure_runtime(smd); Subdiv *subdiv = subdiv_descriptor_ensure(smd, &subdiv_settings, mesh); if (subdiv == NULL) { /* Happens on bad topology, but also on empty input mesh. */ @@ -209,7 +239,7 @@ static Mesh *applyModifier(ModifierData *md, result = subdiv_as_ccg(smd, ctx, mesh, subdiv); } // BKE_subdiv_stats_print(&subdiv->stats); - if (subdiv != smd->subdiv) { + if (subdiv != runtime_data->subdiv) { BKE_subdiv_free(subdiv); } return result; @@ -250,4 +280,5 @@ ModifierTypeInfo modifierType_Subsurf = { /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, + /* freeRuntimeData */ freeRuntimeData, }; |