Subdivision Surfaces: add option disable using the limit surface

This makes subdivision surfaces compatible with the old subdivision
surface modifier and other applications that do not use the limit surface.

This option is available on the Subdivision Surface modifier.

Differential Revision: https://developer.blender.org/D8413
This commit is contained in:
Piotr Ostrowski 2020-09-30 15:47:08 +02:00 committed by Brecht Van Lommel
parent ecdfb465cc
commit 53f20b940a
4 changed files with 50 additions and 8 deletions

@ -232,6 +232,8 @@ class FaceVaryingVolatileEval {
src_face_varying_desc_.stride;
const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
evaluator_cache_, src_face_varying_desc_, dst_face_varying_desc, device_context_);
// in and out points to same buffer so output is put directly after coarse vertices, needed in
// adaptive mode
EVALUATOR::EvalStencils(src_face_varying_data_,
src_face_varying_desc_,
src_face_varying_data_,
@ -249,8 +251,21 @@ class FaceVaryingVolatileEval {
ConstPatchCoordWrapperBuffer patch_coord_buffer(patch_coord, num_patch_coords);
const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
evaluator_cache_, src_face_varying_desc_, face_varying_desc, device_context_);
// src_face_varying_data_ always contains coarse vertices at the beginning.
// In adaptive mode they are followed by number of blocks for intermediate
// subdivision levels, and this is what OSD expects in this mode.
// In non-adaptive mode (generateIntermediateLevels == false),
// they are followed by max subdivision level, but they break interpolation as OSD
// expects only one subd level in this buffer.
// So in non-adaptive mode we put offset into buffer descriptor to skip over coarse vertices.
BufferDescriptor src_desc = src_face_varying_desc_;
if (!patch_table_->GetPatchArrayBuffer()[0].GetDescriptor().IsAdaptive()) {
src_desc.offset += num_coarse_face_varying_vertices_ * src_face_varying_desc_.stride;
}
EVALUATOR::EvalPatchesFaceVarying(src_face_varying_data_,
src_face_varying_desc_,
src_desc,
&face_varying_data,
face_varying_desc,
patch_coord_buffer.GetNumVertices(),

@ -162,6 +162,7 @@ typedef enum {
eSubsurfModifierFlag_SubsurfUv_DEPRECATED = (1 << 3),
eSubsurfModifierFlag_UseCrease = (1 << 4),
eSubsurfModifierFlag_UseCustomNormals = (1 << 5),
eSubsurfModifierFlag_UseRecursiveSubdivision = (1 << 6),
} SubsurfModifierFlag;
typedef enum {

@ -1762,6 +1762,15 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna)
prop, "Use Custom Normals", "Interpolates existing custom normals to resulting mesh");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "use_limit_surface", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(
prop, NULL, "flags", eSubsurfModifierFlag_UseRecursiveSubdivision);
RNA_def_property_ui_text(prop,
"Use Limit Surface",
"Place vertices at the surface that would be produced with infinite "
"levels of subdivision (smoothest possible shape)");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
RNA_define_lib_overridable(false);
}

@ -154,11 +154,18 @@ static int subdiv_levels_for_modifier_get(const SubsurfModifierData *smd,
return get_render_subsurf_level(&scene->r, requested_levels, use_render_params);
}
static void subdiv_settings_init(SubdivSettings *settings, const SubsurfModifierData *smd)
static void subdiv_settings_init(SubdivSettings *settings,
const SubsurfModifierData *smd,
const ModifierEvalContext *ctx)
{
const bool use_render_params = (ctx->flag & MOD_APPLY_RENDER);
const int requested_levels = (use_render_params) ? smd->renderLevels : smd->levels;
settings->is_simple = (smd->subdivType == SUBSURF_TYPE_SIMPLE);
settings->is_adaptive = true;
settings->level = settings->is_simple ? 1 : smd->quality;
settings->is_adaptive = !(smd->flags & eSubsurfModifierFlag_UseRecursiveSubdivision);
settings->level = settings->is_simple ?
1 :
(settings->is_adaptive ? smd->quality : requested_levels);
settings->use_creases = (smd->flags & eSubsurfModifierFlag_UseCrease);
settings->vtx_boundary_interpolation = SUBDIV_VTX_BOUNDARY_EDGE_ONLY;
settings->fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth(
@ -252,7 +259,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
#endif
SubsurfModifierData *smd = (SubsurfModifierData *)md;
SubdivSettings subdiv_settings;
subdiv_settings_init(&subdiv_settings, smd);
subdiv_settings_init(&subdiv_settings, smd, ctx);
if (subdiv_settings.level == 0) {
return result;
}
@ -296,7 +303,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
}
static void deformMatrices(ModifierData *md,
const ModifierEvalContext *UNUSED(ctx),
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertex_cos)[3],
float (*deform_matrices)[3][3],
@ -312,7 +319,7 @@ static void deformMatrices(ModifierData *md,
SubsurfModifierData *smd = (SubsurfModifierData *)md;
SubdivSettings subdiv_settings;
subdiv_settings_init(&subdiv_settings, smd);
subdiv_settings_init(&subdiv_settings, smd, ctx);
if (subdiv_settings.level == 0) {
return;
}
@ -345,6 +352,11 @@ static bool get_show_adaptive_options(const bContext *C, Panel *panel)
return false;
}
/* Don't show adaptive options if regular subdivision used*/
if (!RNA_boolean_get(ptr, "use_limit_surface")) {
return false;
}
/* Don't show adaptive options if the cycles experimental feature set is disabled. */
Scene *scene = CTX_data_scene(C);
PointerRNA scene_ptr;
@ -452,7 +464,12 @@ static void advanced_panel_draw(const bContext *C, Panel *panel)
uiLayoutSetPropSep(layout, true);
uiLayoutSetActive(layout, !(show_adaptive_options && ob_use_adaptive_subdivision));
uiItemR(layout, ptr, "quality", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "use_limit_surface", 0, NULL, ICON_NONE);
uiLayout *col = uiLayoutColumn(layout, true);
uiLayoutSetEnabled(col, RNA_boolean_get(ptr, "use_limit_surface"));
uiItemR(col, ptr, "quality", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "uv_smooth", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "use_creases", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "use_custom_normals", 0, NULL, ICON_NONE);