Blender  V2.93
node_geo_point_separate.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #include "BKE_attribute_math.hh"
18 #include "BKE_mesh.h"
19 #include "BKE_pointcloud.h"
20 
21 #include "DNA_mesh_types.h"
22 #include "DNA_pointcloud_types.h"
23 
24 #include "node_geometry_util.hh"
25 
27  {SOCK_GEOMETRY, N_("Geometry")},
28  {SOCK_STRING, N_("Mask")},
29  {-1, ""},
30 };
31 
33  {SOCK_GEOMETRY, N_("Geometry 1")},
34  {SOCK_GEOMETRY, N_("Geometry 2")},
35  {-1, ""},
36 };
37 
38 namespace blender::nodes {
39 
40 template<typename T>
42  Span<bool> masks,
43  const bool invert,
44  MutableSpan<T> out_data)
45 {
46  int offset = 0;
47  for (const int i : data.index_range()) {
48  if (masks[i] != invert) {
49  out_data[offset] = data[i];
50  offset++;
51  }
52  }
53 }
54 
55 static void copy_attributes_based_on_mask(const GeometryComponent &in_component,
56  GeometryComponent &result_component,
57  Span<bool> masks,
58  const bool invert)
59 {
60  for (const std::string &name : in_component.attribute_names()) {
61  ReadAttributePtr attribute = in_component.attribute_try_get_for_read(name);
62  const CustomDataType data_type = attribute->custom_data_type();
63 
64  /* Only copy point attributes. Theoretically this could interpolate attributes on other
65  * domains to the point domain, but that would conflict with attributes that are built-in
66  * on other domains, which causes creating the attributes to fail. */
67  if (attribute->domain() != ATTR_DOMAIN_POINT) {
68  continue;
69  }
70 
71  OutputAttributePtr result_attribute = result_component.attribute_try_get_for_output(
72  name, ATTR_DOMAIN_POINT, data_type);
73 
74  attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
75  using T = decltype(dummy);
76  Span<T> span = attribute->get_span<T>();
77  MutableSpan<T> out_span = result_attribute->get_span_for_write_only<T>();
78  copy_data_based_on_mask(span, masks, invert, out_span);
79  });
80 
81  result_attribute.apply_span_and_save();
82  }
83 }
84 
85 static void create_component_points(GeometryComponent &component, const int total)
86 {
87  switch (component.type()) {
89  static_cast<MeshComponent &>(component).replace(BKE_mesh_new_nomain(total, 0, 0, 0, 0));
90  break;
92  static_cast<PointCloudComponent &>(component).replace(BKE_pointcloud_new_nomain(total));
93  break;
94  default:
95  BLI_assert(false);
96  break;
97  }
98 }
99 
100 static void separate_points_from_component(const GeometryComponent &in_component,
101  GeometryComponent &out_component,
102  const StringRef mask_name,
103  const bool invert)
104 {
105  if (!in_component.attribute_domain_supported(ATTR_DOMAIN_POINT) ||
106  in_component.attribute_domain_size(ATTR_DOMAIN_POINT) == 0) {
107  return;
108  }
109 
110  const BooleanReadAttribute mask_attribute = in_component.attribute_get_for_read<bool>(
111  mask_name, ATTR_DOMAIN_POINT, false);
112  Span<bool> masks = mask_attribute.get_span();
113 
114  const int total = masks.count(!invert);
115  if (total == 0) {
116  return;
117  }
118 
119  create_component_points(out_component, total);
120 
121  copy_attributes_based_on_mask(in_component, out_component, masks, invert);
122 }
123 
125  const StringRef mask_name,
126  const bool invert)
127 {
128  GeometrySet set_out;
129  for (const GeometryComponent *component : set_in.get_components_for_read()) {
130  GeometryComponent &out_component = set_out.get_component_for_write(component->type());
131  separate_points_from_component(*component, out_component, mask_name, invert);
132  }
133  return set_out;
134 }
135 
137 {
138  const std::string mask_attribute_name = params.extract_input<std::string>("Mask");
139  GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
140 
141  /* TODO: This is not necessary-- the input geometry set can be read only,
142  * but it must be rewritten to handle instance groups. */
143  geometry_set = geometry_set_realize_instances(geometry_set);
144 
145  params.set_output("Geometry 1", separate_geometry_set(geometry_set, mask_attribute_name, true));
146  params.set_output("Geometry 2", separate_geometry_set(geometry_set, mask_attribute_name, false));
147 }
148 
149 } // namespace blender::nodes
150 
152 {
153  static bNodeType ntype;
154 
155  geo_node_type_base(&ntype, GEO_NODE_POINT_SEPARATE, "Point Separate", NODE_CLASS_GEOMETRY, 0);
158  nodeRegisterType(&ntype);
159 }
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:43
@ GEO_COMPONENT_TYPE_MESH
@ GEO_COMPONENT_TYPE_POINT_CLOUD
struct Mesh * BKE_mesh_new_nomain(int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
Definition: mesh.c:877
#define GEO_NODE_POINT_SEPARATE
Definition: BKE_node.h:1390
void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs)
Definition: node.cc:4527
#define NODE_CLASS_GEOMETRY
Definition: BKE_node.h:359
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1298
General operations for point-clouds.
struct PointCloud * BKE_pointcloud_new_nomain(const int totpoint)
Definition: pointcloud.cc:240
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define N_(msgid)
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:126
CustomDataType
@ SOCK_GEOMETRY
@ SOCK_STRING
virtual int attribute_domain_size(const AttributeDomain domain) const
blender::Set< std::string > attribute_names() const
blender::bke::ReadAttributePtr attribute_try_get_for_read(const blender::StringRef attribute_name) const
OutputAttributePtr attribute_try_get_for_output(const blender::StringRef attribute_name, const AttributeDomain domain, const CustomDataType data_type, const void *default_value=nullptr)
blender::bke::ReadAttributePtr attribute_get_for_read(const blender::StringRef attribute_name, const AttributeDomain domain, const CustomDataType data_type, const void *default_value) const
bool attribute_domain_supported(const AttributeDomain domain) const
constexpr int64_t count(const T &value) const
Definition: BLI_span.hh:302
fn::GMutableSpan get_span_for_write_only()
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define T
void convert_to_static_type(const CustomDataType data_type, const Func &func)
GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set)
TypedReadAttribute< bool > BooleanReadAttribute
std::unique_ptr< ReadAttribute > ReadAttributePtr
static void create_component_points(GeometryComponent &component, const int total)
static void geo_node_point_separate_exec(GeoNodeExecParams params)
static GeometrySet separate_geometry_set(const GeometrySet &set_in, const StringRef mask_name, const bool invert)
static void separate_points_from_component(const GeometryComponent &in_component, GeometryComponent &out_component, const StringRef mask_name, const bool invert)
static void copy_data_based_on_mask(Span< T > data, Span< bool > masks, const bool invert, MutableSpan< T > out_data)
static void copy_attributes_based_on_mask(const GeometryComponent &in_component, GeometryComponent &result_component, Span< bool > masks, const bool invert)
static bNodeSocketTemplate geo_node_point_instance_out[]
void register_node_type_geo_point_separate()
static bNodeSocketTemplate geo_node_point_instance_in[]
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
GeometryComponent & get_component_for_write(GeometryComponentType component_type)
blender::Vector< const GeometryComponent * > get_components_for_read() const
Compact definition of a node socket.
Definition: BKE_node.h:95
Defines a node type.
Definition: BKE_node.h:221
NodeGeometryExecFunction geometry_node_execute
Definition: BKE_node.h:327
CCL_NAMESPACE_BEGIN ccl_device float invert(float color, float factor)
Definition: svm_invert.h:19