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:
@@ -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
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user