Geometry Nodes: Add "Limit Surface" option in subdivision surface node

Currently the node behaves differently from the modifier by default
because it lacks the option to use the limit surface. This is mainly
an oversight, since the option gives better results and better
performance.

This adds a new "Limit Surface" option. Because it's on by default,
there is also versioning to turn it off for existing files.

Resolves #112912.

Pull Request: https://projects.blender.org/blender/blender/pulls/130243
This commit is contained in:
Hans Goudey
2024-11-14 18:21:00 +01:00
committed by Hans Goudey
parent 2fef3ce61d
commit 7074daed04
3 changed files with 31 additions and 5 deletions

View File

@@ -31,7 +31,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 5
#define BLENDER_FILE_SUBVERSION 6
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and cancel loading the file, showing a warning to

View File

@@ -3118,6 +3118,21 @@ static bool versioning_convert_seq_text_anchor(Sequence *seq, void * /*user_data
return true;
}
static void add_subsurf_node_limit_surface_option(Main &bmain)
{
LISTBASE_FOREACH (bNodeTree *, ntree, &bmain.nodetrees) {
if (ntree->type == NTREE_GEOMETRY) {
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->type == GEO_NODE_SUBDIVISION_SURFACE) {
bNodeSocket *socket = version_node_add_socket_if_not_exist(
ntree, node, SOCK_IN, SOCK_BOOLEAN, PROP_NONE, "Limit Surface", "Limit Surface");
static_cast<bNodeSocketValueBoolean *>(socket->default_value)->value = false;
}
}
}
}
}
void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
{
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 1)) {
@@ -5018,6 +5033,10 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 404, 6)) {
add_subsurf_node_limit_surface_option(*bmain);
}
/* Always run this versioning; meshes are written with the legacy format which always needs to
* be converted to the new format on file load. Can be moved to a subversion check in a larger
* breaking release. */

View File

@@ -43,6 +43,11 @@ static void node_declare(NodeDeclarationBuilder &b)
.max(1.0f)
.subtype(PROP_FACTOR)
.field_on_all();
b.add_input<decl::Bool>("Limit Surface")
.default_value(true)
.description(
"Place vertices at the surface that would be produced with infinite "
"levels of subdivision (smoothest possible shape)");
b.add_output<decl::Geometry>("Mesh").propagate_all();
}
@@ -98,7 +103,8 @@ static Mesh *mesh_subsurf_calc(const Mesh *mesh,
const Field<float> &vert_crease_field,
const Field<float> &edge_crease_field,
const int boundary_smooth,
const int uv_smooth)
const int uv_smooth,
const bool use_limit_surface)
{
const bke::MeshFieldContext point_context{*mesh, AttrDomain::Point};
FieldEvaluator point_evaluator(point_context, mesh->verts_num);
@@ -132,7 +138,7 @@ static Mesh *mesh_subsurf_calc(const Mesh *mesh,
bke::subdiv::Settings subdiv_settings;
subdiv_settings.is_simple = false;
subdiv_settings.is_adaptive = false;
subdiv_settings.is_adaptive = use_limit_surface;
subdiv_settings.use_creases = use_creases;
subdiv_settings.level = level;
subdiv_settings.vtx_boundary_interpolation =
@@ -178,6 +184,7 @@ static void node_geo_exec(GeoNodeExecParams params)
const int uv_smooth = storage.uv_smooth;
const int boundary_smooth = storage.boundary_smooth;
const int level = std::clamp(params.extract_input<int>("Level"), 0, 11);
const bool use_limit_surface = params.extract_input<bool>("Limit Surface");
if (level == 0) {
params.set_output("Mesh", std::move(geometry_set));
return;
@@ -185,8 +192,8 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (const Mesh *mesh = geometry_set.get_mesh()) {
geometry_set.replace_mesh(
mesh_subsurf_calc(mesh, level, vert_crease, edge_crease, boundary_smooth, uv_smooth));
geometry_set.replace_mesh(mesh_subsurf_calc(
mesh, level, vert_crease, edge_crease, boundary_smooth, uv_smooth, use_limit_surface));
}
});
#else