Geometry Nodes: Separate and Delete Geometry for fields

Delete Geometry:
This adds a copy of the old node in the legacy folder and updates the
node to work with fields. The invert option is removed, because it is
something that should be very easy with fields, and to be consistent
with other nodes which have a selection. There is also a dropdown to
select the domain, because the domain can't be determined from the
field input. When the domain does not belong on any of the components
an info message is displayed.

Separate Geometry:
A more general version of the old Point Separate node. The "inverted"
output is the same as using the delete geometry node.

Differential Revision: https://developer.blender.org/D12574
This commit is contained in:
Wannes Malfait 2021-10-11 08:38:02 -05:00 committed by Hans Goudey
parent 275d0d3397
commit 9c00486451
14 changed files with 1434 additions and 1 deletions

View File

@ -552,9 +552,11 @@ geometry_node_categories = [
NodeItem("GeometryNodeProximity"),
NodeItem("GeometryNodeBoundBox"),
NodeItem("GeometryNodeConvexHull"),
NodeItem("GeometryNodeDeleteGeometry"),
NodeItem("GeometryNodeTransform"),
NodeItem("GeometryNodeJoinGeometry"),
NodeItem("GeometryNodeSeparateComponents"),
NodeItem("GeometryNodeSeparateGeometry"),
NodeItem("GeometryNodeSetPosition"),
NodeItem("GeometryNodeRealizeInstances"),
]),

View File

@ -1515,6 +1515,9 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_CURVE_SET_HANDLES 1100
#define GEO_NODE_POINTS_TO_VOLUME 1101
#define GEO_NODE_CURVE_HANDLE_TYPE_SELECTION 1102
#define GEO_NODE_DELETE_GEOMETRY 1103
#define GEO_NODE_SEPARATE_GEOMETRY 1104
/** \} */
/* -------------------------------------------------------------------- */

View File

@ -5712,6 +5712,7 @@ static void registerGeometryNodes()
register_node_type_geo_legacy_curve_set_handles();
register_node_type_geo_legacy_attribute_proximity();
register_node_type_geo_legacy_attribute_randomize();
register_node_type_geo_legacy_delete_geometry();
register_node_type_geo_legacy_material_assign();
register_node_type_geo_legacy_points_to_volume();
register_node_type_geo_legacy_select_by_material();
@ -5803,6 +5804,7 @@ static void registerGeometryNodes()
register_node_type_geo_realize_instances();
register_node_type_geo_sample_texture();
register_node_type_geo_separate_components();
register_node_type_geo_separate_geometry();
register_node_type_geo_set_position();
register_node_type_geo_string_join();
register_node_type_geo_string_to_curves();

View File

@ -1538,6 +1538,18 @@ typedef struct NodeGeometryStringToCurves {
char _pad[1];
} NodeGeometryStringToCurves;
typedef struct NodeGeometryDeleteGeometry {
/* AttributeDomain. */
int8_t domain;
/* GeometryNodeDeleteGeometryMode. */
int8_t mode;
} NodeGeometryDeleteGeometry;
typedef struct NodeGeometrySeparateGeometry {
/* AttributeDomain. */
int8_t domain;
} NodeGeometrySeparateGeometry;
/* script node mode */
#define NODE_SCRIPT_INTERNAL 0
#define NODE_SCRIPT_EXTERNAL 1
@ -2192,6 +2204,12 @@ typedef enum GeometryNodeStringToCurvesAlignYMode {
GEO_NODE_STRING_TO_CURVES_ALIGN_Y_BOTTOM = 4,
} GeometryNodeStringToCurvesAlignYMode;
typedef enum GeometryNodeDeleteGeometryMode {
GEO_NODE_DELETE_GEOMETRY_MODE_ALL = 0,
GEO_NODE_DELETE_GEOMETRY_MODE_EDGE_FACE = 1,
GEO_NODE_DELETE_GEOMETRY_MODE_ONLY_FACE = 2,
} GeometryNodeDeleteGeometryMode;
#ifdef __cplusplus
}
#endif

View File

@ -208,6 +208,7 @@ DEF_ENUM(rna_enum_preference_section_items)
DEF_ENUM(rna_enum_attribute_type_items)
DEF_ENUM(rna_enum_attribute_type_with_auto_items)
DEF_ENUM(rna_enum_attribute_domain_items)
DEF_ENUM(rna_enum_attribute_domain_without_corner_items)
DEF_ENUM(rna_enum_attribute_domain_with_auto_items)
DEF_ENUM(rna_enum_collection_color_items)

View File

@ -75,6 +75,14 @@ const EnumPropertyItem rna_enum_attribute_domain_items[] = {
{0, NULL, 0, NULL, NULL},
};
const EnumPropertyItem rna_enum_attribute_domain_without_corner_items[] = {
{ATTR_DOMAIN_POINT, "POINT", 0, "Point", "Attribute on point"},
{ATTR_DOMAIN_EDGE, "EDGE", 0, "Edge", "Attribute on mesh edge"},
{ATTR_DOMAIN_FACE, "FACE", 0, "Face", "Attribute on mesh faces"},
{ATTR_DOMAIN_CURVE, "CURVE", 0, "Spline", "Attribute on spline"},
{0, NULL, 0, NULL, NULL},
};
const EnumPropertyItem rna_enum_attribute_domain_with_auto_items[] = {
{ATTR_DOMAIN_AUTO, "AUTO", 0, "Auto", ""},
{ATTR_DOMAIN_POINT, "POINT", 0, "Point", "Attribute on point"},

View File

@ -10700,6 +10700,31 @@ static void def_geo_attribute_capture(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_geo_delete_geometry(StructRNA *srna)
{
PropertyRNA *prop;
static const EnumPropertyItem mode_items[] = {
{GEO_NODE_DELETE_GEOMETRY_MODE_ALL, "ALL", 0, "All", ""},
{GEO_NODE_DELETE_GEOMETRY_MODE_EDGE_FACE, "EDGE_FACE", 0, "Only Edges & Faces", ""},
{GEO_NODE_DELETE_GEOMETRY_MODE_ONLY_FACE, "ONLY_FACE", 0, "Only Faces", ""},
{0, NULL, 0, NULL, NULL},
};
RNA_def_struct_sdna_from(srna, "NodeGeometryDeleteGeometry", "storage");
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, mode_items);
RNA_def_property_enum_default(prop, GEO_NODE_DELETE_GEOMETRY_MODE_ALL);
RNA_def_property_ui_text(prop, "Mode", "Which parts of the mesh component to delete");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "domain", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_attribute_domain_without_corner_items);
RNA_def_property_enum_default(prop, ATTR_DOMAIN_POINT);
RNA_def_property_ui_text(prop, "Domain", "Which domain to delete in");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_geo_string_to_curves(StructRNA *srna)
{
static const EnumPropertyItem rna_node_geometry_string_to_curves_overflow_items[] = {
@ -10814,6 +10839,19 @@ static void def_geo_string_to_curves(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_geo_separate_geometry(StructRNA *srna)
{
PropertyRNA *prop;
RNA_def_struct_sdna_from(srna, "NodeGeometrySeparateGeometry", "storage");
prop = RNA_def_property(srna, "domain", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_attribute_domain_without_corner_items);
RNA_def_property_enum_default(prop, ATTR_DOMAIN_POINT);
RNA_def_property_ui_text(prop, "Domain", "Which domain to separate on");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
/* -------------------------------------------------------------------------- */
static void rna_def_shader_node(BlenderRNA *brna)

View File

@ -217,6 +217,7 @@ set(SRC
geometry/nodes/node_geo_curve_subdivide.cc
geometry/nodes/node_geo_curve_to_mesh.cc
geometry/nodes/node_geo_curve_trim.cc
geometry/nodes/node_geo_delete_geometry.cc
geometry/nodes/node_geo_distribute_points_on_faces.cc
geometry/nodes/node_geo_input_index.cc
geometry/nodes/node_geo_input_material.cc
@ -246,6 +247,7 @@ set(SRC
geometry/nodes/node_geo_proximity.cc
geometry/nodes/node_geo_realize_instances.cc
geometry/nodes/node_geo_separate_components.cc
geometry/nodes/node_geo_separate_geometry.cc
geometry/nodes/node_geo_set_position.cc
geometry/nodes/node_geo_string_join.cc
geometry/nodes/node_geo_string_to_curves.cc

View File

@ -32,6 +32,7 @@ void register_node_type_geo_custom_group(bNodeType *ntype);
void register_node_type_geo_legacy_curve_set_handles(void);
void register_node_type_geo_legacy_attribute_proximity(void);
void register_node_type_geo_legacy_attribute_randomize(void);
void register_node_type_geo_legacy_delete_geometry(void);
void register_node_type_geo_legacy_material_assign(void);
void register_node_type_geo_legacy_points_to_volume(void);
void register_node_type_geo_legacy_select_by_material(void);
@ -125,6 +126,7 @@ void register_node_type_geo_realize_instances(void);
void register_node_type_geo_sample_texture(void);
void register_node_type_geo_select_by_handle_type(void);
void register_node_type_geo_separate_components(void);
void register_node_type_geo_separate_geometry(void);
void register_node_type_geo_set_position(void);
void register_node_type_geo_string_join(void);
void register_node_type_geo_string_to_curves(void);

View File

@ -345,6 +345,7 @@ DefNode(GeometryNode, GEO_NODE_CURVE_SET_HANDLES, def_geo_curve_set_handles, "CU
DefNode(GeometryNode, GEO_NODE_CURVE_SUBDIVIDE, 0, "CURVE_SUBDIVIDE", CurveSubdivide, "Curve Subdivide", "")
DefNode(GeometryNode, GEO_NODE_CURVE_TO_MESH, 0, "CURVE_TO_MESH", CurveToMesh, "Curve to Mesh", "")
DefNode(GeometryNode, GEO_NODE_CURVE_TRIM, def_geo_curve_trim, "CURVE_TRIM", CurveTrim, "Curve Trim", "")
DefNode(GeometryNode, GEO_NODE_DELETE_GEOMETRY, def_geo_delete_geometry, "DELETE_GEOMETRY", DeleteGeometry, "Delete Geometry", "")
DefNode(GeometryNode, GEO_NODE_DISTRIBUTE_POINTS_ON_FACES, def_geo_distribute_points_on_faces, "DISTRIBUTE_POINTS_ON_FACES", DistributePointsOnFaces, "Distribute Points on Faces", "")
DefNode(GeometryNode, GEO_NODE_INPUT_INDEX, 0, "INDEX", InputIndex, "Index", "")
DefNode(GeometryNode, GEO_NODE_INPUT_MATERIAL, def_geo_input_material, "INPUT_MATERIAL", InputMaterial, "Material", "")
@ -374,6 +375,7 @@ DefNode(GeometryNode, GEO_NODE_POINTS_TO_VOLUME, def_geo_points_to_volume, "POIN
DefNode(GeometryNode, GEO_NODE_PROXIMITY, def_geo_proximity, "PROXIMITY", Proximity, "Geometry Proximity", "")
DefNode(GeometryNode, GEO_NODE_REALIZE_INSTANCES, 0, "REALIZE_INSTANCES", RealizeInstances, "Realize Instances", "")
DefNode(GeometryNode, GEO_NODE_SEPARATE_COMPONENTS, 0, "SEPARATE_COMPONENTS", SeparateComponents, "Separate Components", "")
DefNode(GeometryNode, GEO_NODE_SEPARATE_GEOMETRY, def_geo_separate_geometry, "SEPARATE_GEOMETRY", SeparateGeometry, "Separate Geometry", "")
DefNode(GeometryNode, GEO_NODE_SET_POSITION, 0, "SET_POSITION", SetPosition, "Set Position", "")
DefNode(GeometryNode, GEO_NODE_STRING_JOIN, 0, "STRING_JOIN", StringJoin, "Join Strings", "")
DefNode(GeometryNode, GEO_NODE_STRING_TO_CURVES, def_geo_string_to_curves, "STRING_TO_CURVES", StringToCurves, "String to Curves", "")

View File

@ -79,6 +79,17 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component,
GeometryComponent &result_component,
Span<bool> masks,
const bool invert);
/**
* Returns the parts of the geometry that are on the selection for the given domain. If the domain
* is not applicable for the component, e.g. face domain for point cloud, nothing happens to that
* component. If no component can work with the domain, then `error_message` is set to true.
*/
void separate_geometry(GeometrySet &geometry_set,
const AttributeDomain domain,
const GeometryNodeDeleteGeometryMode mode,
const Field<bool> &selection_field,
const bool invert,
bool &r_error_message);
struct CurveToPointsResults {
int result_size;

View File

@ -664,7 +664,7 @@ static void geo_node_delete_geometry_exec(GeoNodeExecParams params)
} // namespace blender::nodes
void register_node_type_geo_delete_geometry()
void register_node_type_geo_legacy_delete_geometry()
{
static bNodeType ntype;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "UI_interface.h"
#include "UI_resources.h"
#include "node_geometry_util.hh"
namespace blender::nodes {
static void geo_node_separate_geometry_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>("Geometry");
b.add_input<decl::Bool>("Selection")
.default_value(true)
.hide_value()
.supports_field()
.description("The parts of the geometry that go into the first output");
b.add_output<decl::Geometry>("Selection")
.description("The parts of the geometry in the selection");
b.add_output<decl::Geometry>("Inverted")
.description("The parts of the geometry not in the selection");
}
static void geo_node_separate_geometry_layout(uiLayout *layout,
bContext *UNUSED(C),
PointerRNA *ptr)
{
uiItemR(layout, ptr, "domain", 0, "", ICON_NONE);
}
static void geo_node_separate_geometry_init(bNodeTree *UNUSED(tree), bNode *node)
{
NodeGeometrySeparateGeometry *data = (NodeGeometrySeparateGeometry *)MEM_callocN(
sizeof(NodeGeometrySeparateGeometry), __func__);
data->domain = ATTR_DOMAIN_POINT;
node->storage = data;
}
static void geo_node_separate_geometry_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
const Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
const bNode &node = params.node();
const NodeGeometryDeleteGeometry &storage = *(const NodeGeometryDeleteGeometry *)node.storage;
const AttributeDomain domain = static_cast<AttributeDomain>(storage.domain);
bool all_is_error = false;
GeometrySet second_set(geometry_set);
if (params.output_is_required("Selection")) {
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
bool this_is_error = false;
separate_geometry(geometry_set,
domain,
GEO_NODE_DELETE_GEOMETRY_MODE_ALL,
selection_field,
false,
this_is_error);
all_is_error &= this_is_error;
});
params.set_output("Selection", std::move(geometry_set));
}
if (params.output_is_required("Inverted")) {
second_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
bool this_is_error = false;
separate_geometry(geometry_set,
domain,
GEO_NODE_DELETE_GEOMETRY_MODE_ALL,
selection_field,
true,
this_is_error);
all_is_error &= this_is_error;
});
params.set_output("Inverted", std::move(second_set));
}
if (all_is_error) {
/* Only show this if none of the instances/components actually changed. */
params.error_message_add(NodeWarningType::Info, TIP_("No geometry with given domain"));
}
}
} // namespace blender::nodes
void register_node_type_geo_separate_geometry()
{
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_SEPARATE_GEOMETRY, "Separate Geometry", NODE_CLASS_GEOMETRY, 0);
node_type_storage(&ntype,
"NodeGeometrySeparateGeometry",
node_free_standard_storage,
node_copy_standard_storage);
node_type_init(&ntype, blender::nodes::geo_node_separate_geometry_init);
ntype.declare = blender::nodes::geo_node_separate_geometry_declare;
ntype.geometry_node_execute = blender::nodes::geo_node_separate_geometry_exec;
ntype.draw_buttons = blender::nodes::geo_node_separate_geometry_layout;
nodeRegisterType(&ntype);
}