Blender  V2.93
node_geo_attribute_math.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 "UI_interface.h"
18 #include "UI_resources.h"
19 
20 #include "NOD_math_functions.hh"
21 
22 #include "node_geometry_util.hh"
23 
25  {SOCK_GEOMETRY, N_("Geometry")},
26  {SOCK_STRING, N_("A")},
27  {SOCK_FLOAT, N_("A"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
28  {SOCK_STRING, N_("B")},
29  {SOCK_FLOAT, N_("B"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
30  {SOCK_STRING, N_("C")},
31  {SOCK_FLOAT, N_("C"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
32  {SOCK_STRING, N_("Result")},
33  {-1, ""},
34 };
35 
37  {SOCK_GEOMETRY, N_("Geometry")},
38  {-1, ""},
39 };
40 
41 static bool operation_use_input_c(const NodeMathOperation operation)
42 {
43  return ELEM(operation,
49 }
50 
51 static bool operation_use_input_b(const NodeMathOperation operation)
52 {
53  switch (operation) {
54  case NODE_MATH_ADD:
55  case NODE_MATH_SUBTRACT:
56  case NODE_MATH_MULTIPLY:
57  case NODE_MATH_DIVIDE:
58  case NODE_MATH_POWER:
60  case NODE_MATH_MINIMUM:
61  case NODE_MATH_MAXIMUM:
64  case NODE_MATH_MODULO:
65  case NODE_MATH_ARCTAN2:
66  case NODE_MATH_SNAP:
67  case NODE_MATH_WRAP:
68  case NODE_MATH_COMPARE:
70  case NODE_MATH_PINGPONG:
73  return true;
74  case NODE_MATH_SINE:
75  case NODE_MATH_COSINE:
76  case NODE_MATH_TANGENT:
77  case NODE_MATH_ARCSINE:
80  case NODE_MATH_ROUND:
81  case NODE_MATH_ABSOLUTE:
82  case NODE_MATH_FLOOR:
83  case NODE_MATH_CEIL:
84  case NODE_MATH_FRACTION:
85  case NODE_MATH_SQRT:
86  case NODE_MATH_INV_SQRT:
87  case NODE_MATH_SIGN:
88  case NODE_MATH_EXPONENT:
89  case NODE_MATH_RADIANS:
90  case NODE_MATH_DEGREES:
91  case NODE_MATH_SINH:
92  case NODE_MATH_COSH:
93  case NODE_MATH_TANH:
94  case NODE_MATH_TRUNC:
95  return false;
96  }
97  BLI_assert(false);
98  return false;
99 }
100 
102 {
103  bNode *node = (bNode *)ptr->data;
104  NodeAttributeMath *node_storage = (NodeAttributeMath *)node->storage;
105  NodeMathOperation operation = (NodeMathOperation)node_storage->operation;
106 
107  uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
108 
109  uiLayoutSetPropSep(layout, true);
110  uiLayoutSetPropDecorate(layout, false);
111  uiItemR(layout, ptr, "input_type_a", 0, IFACE_("A"), ICON_NONE);
112  if (operation_use_input_b(operation)) {
113  uiItemR(layout, ptr, "input_type_b", 0, IFACE_("B"), ICON_NONE);
114  }
115  if (operation_use_input_c(operation)) {
116  uiItemR(layout, ptr, "input_type_c", 0, IFACE_("C"), ICON_NONE);
117  }
118 }
119 
121 {
123 
124  data->operation = NODE_MATH_ADD;
128  node->storage = data;
129 }
130 
131 namespace blender::nodes {
132 
134 {
135  NodeAttributeMath &node_storage = *(NodeAttributeMath *)node->storage;
136  NodeMathOperation operation = static_cast<NodeMathOperation>(node_storage.operation);
137 
139  *node, "A", (GeometryNodeAttributeInputMode)node_storage.input_type_a);
141  *node,
142  "B",
144  operation_use_input_b(operation));
146  *node,
147  "C",
149  operation_use_input_c(operation));
150 }
151 
152 static void do_math_operation(Span<float> span_a,
153  Span<float> span_b,
154  Span<float> span_c,
155  MutableSpan<float> span_result,
156  const NodeMathOperation operation)
157 {
159  operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) {
160  for (const int i : IndexRange(span_result.size())) {
161  span_result[i] = math_function(span_a[i], span_b[i], span_c[i]);
162  }
163  });
164  BLI_assert(success);
165  UNUSED_VARS_NDEBUG(success);
166 }
167 
168 static void do_math_operation(Span<float> span_a,
169  Span<float> span_b,
170  MutableSpan<float> span_result,
171  const NodeMathOperation operation)
172 {
174  operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) {
175  for (const int i : IndexRange(span_result.size())) {
176  span_result[i] = math_function(span_a[i], span_b[i]);
177  }
178  });
179  BLI_assert(success);
180  UNUSED_VARS_NDEBUG(success);
181 }
182 
183 static void do_math_operation(Span<float> span_input,
184  MutableSpan<float> span_result,
185  const NodeMathOperation operation)
186 {
187  bool success = try_dispatch_float_math_fl_to_fl(
188  operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) {
189  for (const int i : IndexRange(span_result.size())) {
190  span_result[i] = math_function(span_input[i]);
191  }
192  });
193  BLI_assert(success);
194  UNUSED_VARS_NDEBUG(success);
195 }
196 
198  const GeoNodeExecParams &params,
199  const NodeMathOperation operation,
200  StringRef result_name)
201 {
202  /* Use the domain of the result attribute if it already exists. */
203  ReadAttributePtr result_attribute = component.attribute_try_get_for_read(result_name);
204  if (result_attribute) {
205  return result_attribute->domain();
206  }
207 
208  /* Otherwise use the highest priority domain from existing input attributes, or the default. */
210  if (operation_use_input_b(operation)) {
211  if (operation_use_input_c(operation)) {
212  return params.get_highest_priority_input_domain({"A", "B", "C"}, component, default_domain);
213  }
214  return params.get_highest_priority_input_domain({"A", "B"}, component, default_domain);
215  }
216  return params.get_highest_priority_input_domain({"A"}, component, default_domain);
217 }
218 
220 {
221  const bNode &node = params.node();
222  const NodeAttributeMath *node_storage = (const NodeAttributeMath *)node.storage;
223  const NodeMathOperation operation = static_cast<NodeMathOperation>(node_storage->operation);
224  const std::string result_name = params.get_input<std::string>("Result");
225 
226  /* The result type of this node is always float. */
227  const CustomDataType result_type = CD_PROP_FLOAT;
228  const AttributeDomain result_domain = get_result_domain(
229  component, params, operation, result_name);
230 
231  OutputAttributePtr attribute_result = component.attribute_try_get_for_output(
232  result_name, result_domain, result_type);
233  if (!attribute_result) {
234  return;
235  }
236 
237  ReadAttributePtr attribute_a = params.get_input_attribute(
238  "A", component, result_domain, result_type, nullptr);
239  if (!attribute_a) {
240  return;
241  }
242 
243  /* Note that passing the data with `get_span<float>()` works
244  * because the attributes were accessed with #CD_PROP_FLOAT. */
245  if (operation_use_input_b(operation)) {
246  ReadAttributePtr attribute_b = params.get_input_attribute(
247  "B", component, result_domain, result_type, nullptr);
248  if (!attribute_b) {
249  return;
250  }
251  if (operation_use_input_c(operation)) {
252  ReadAttributePtr attribute_c = params.get_input_attribute(
253  "C", component, result_domain, result_type, nullptr);
254  if (!attribute_c) {
255  return;
256  }
257  do_math_operation(attribute_a->get_span<float>(),
258  attribute_b->get_span<float>(),
259  attribute_c->get_span<float>(),
260  attribute_result->get_span_for_write_only<float>(),
261  operation);
262  }
263  else {
264  do_math_operation(attribute_a->get_span<float>(),
265  attribute_b->get_span<float>(),
266  attribute_result->get_span_for_write_only<float>(),
267  operation);
268  }
269  }
270  else {
271  do_math_operation(attribute_a->get_span<float>(),
272  attribute_result->get_span_for_write_only<float>(),
273  operation);
274  }
275 
276  attribute_result.apply_span_and_save();
277 }
278 
280 {
281  GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
282 
283  geometry_set = geometry_set_realize_instances(geometry_set);
284 
285  if (geometry_set.has<MeshComponent>()) {
287  }
288  if (geometry_set.has<PointCloudComponent>()) {
290  }
291 
292  params.set_output("Geometry", geometry_set);
293 }
294 
295 } // namespace blender::nodes
296 
298 {
299  static bNodeType ntype;
300 
301  geo_node_type_base(&ntype, GEO_NODE_ATTRIBUTE_MATH, "Attribute Math", NODE_CLASS_ATTRIBUTE, 0);
308  &ntype, "NodeAttributeMath", node_free_standard_storage, node_copy_standard_storage);
309  nodeRegisterType(&ntype);
310 }
AttributeDomain
Definition: BKE_attribute.h:41
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:43
void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs)
Definition: node.cc:4527
void node_type_update(struct bNodeType *ntype, void(*updatefunc)(struct bNodeTree *ntree, struct bNode *node))
Definition: node.cc:4623
void node_type_init(struct bNodeType *ntype, void(*initfunc)(struct bNodeTree *ntree, struct bNode *node))
Definition: node.cc:4559
void node_type_storage(struct bNodeType *ntype, const char *storagename, void(*freefunc)(struct bNode *node), void(*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, const struct bNode *src_node))
Definition: node.cc:4599
#define NODE_CLASS_ATTRIBUTE
Definition: BKE_node.h:360
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1298
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
#define ELEM(...)
#define IFACE_(msgid)
#define N_(msgid)
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:126
CustomDataType
@ CD_PROP_FLOAT
NodeMathOperation
@ NODE_MATH_SINH
@ NODE_MATH_SMOOTH_MIN
@ NODE_MATH_TRUNC
@ NODE_MATH_COSH
@ NODE_MATH_SIGN
@ NODE_MATH_DEGREES
@ NODE_MATH_MODULO
@ NODE_MATH_ABSOLUTE
@ NODE_MATH_DIVIDE
@ NODE_MATH_SINE
@ NODE_MATH_ARCTAN2
@ NODE_MATH_ARCCOSINE
@ NODE_MATH_MULTIPLY_ADD
@ NODE_MATH_POWER
@ NODE_MATH_WRAP
@ NODE_MATH_ARCTANGENT
@ NODE_MATH_MINIMUM
@ NODE_MATH_SQRT
@ NODE_MATH_CEIL
@ NODE_MATH_TANH
@ NODE_MATH_GREATER_THAN
@ NODE_MATH_ADD
@ NODE_MATH_FRACTION
@ NODE_MATH_EXPONENT
@ NODE_MATH_LESS_THAN
@ NODE_MATH_ARCSINE
@ NODE_MATH_MAXIMUM
@ NODE_MATH_LOGARITHM
@ NODE_MATH_COMPARE
@ NODE_MATH_INV_SQRT
@ NODE_MATH_MULTIPLY
@ NODE_MATH_PINGPONG
@ NODE_MATH_ROUND
@ NODE_MATH_FLOOR
@ NODE_MATH_SUBTRACT
@ NODE_MATH_COSINE
@ NODE_MATH_SNAP
@ NODE_MATH_TANGENT
@ NODE_MATH_SMOOTH_MAX
@ NODE_MATH_RADIANS
@ SOCK_FLOAT
@ SOCK_GEOMETRY
@ SOCK_STRING
GeometryNodeAttributeInputMode
@ GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction Transparent Toon Principled Hair Volume Principled Light Particle Volume Image Sky Noise Wave Voronoi Brick Texture Vector Combine Vertex Separate Vector White RGB Map Separate Set Z Dilate Combine Combine Color Channel Split ID Combine Luminance Directional Alpha Distance Hue Movie Ellipse Bokeh View Corner Anti Mix RGB Hue Separate TEX_NODE_PROC TEX_NODE_PROC TEX_NODE_PROC TEX_NODE_PROC TEX_NODE_PROC Boolean Random Edge Subdivision Point Object GEO_NODE_ATTRIBUTE_MATH
#define C
Definition: RandGen.cpp:39
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
static std::string default_domain
constexpr int64_t size() const
Definition: BLI_span.hh:524
fn::GMutableSpan get_span_for_write_only()
OperationNode * node
void * tree
bNodeTree * ntree
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set)
std::unique_ptr< ReadAttribute > ReadAttributePtr
static void geo_node_attribute_math_exec(GeoNodeExecParams params)
bool try_dispatch_float_math_fl_fl_to_fl(const int operation, Callback &&callback)
void update_attribute_input_socket_availabilities(bNode &node, const StringRef name, const GeometryNodeAttributeInputMode mode, const bool name_is_available)
bool try_dispatch_float_math_fl_to_fl(const int operation, Callback &&callback)
static void geo_node_attribute_math_update(bNodeTree *UNUSED(ntree), bNode *node)
static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecParams &params)
static AttributeDomain get_result_domain(const GeometryComponent &component, StringRef source_name, StringRef result_name)
bool try_dispatch_float_math_fl_fl_fl_to_fl(const int operation, Callback &&callback)
static void do_math_operation(const FloatReadAttribute &input_a, const FloatReadAttribute &input_b, const FloatCompareOperation operation, MutableSpan< bool > span_result)
static void geo_node_attribute_math_init(bNodeTree *UNUSED(tree), bNode *node)
static bool operation_use_input_c(const NodeMathOperation operation)
static bNodeSocketTemplate geo_node_attribute_math_in[]
void register_node_type_geo_attribute_math()
static bool operation_use_input_b(const NodeMathOperation operation)
static bNodeSocketTemplate geo_node_attribute_math_out[]
static void geo_node_attribute_math_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node)
Definition: node_util.c:67
void node_free_standard_storage(bNode *node)
Definition: node_util.c:55
GeometryComponent & get_component_for_write(GeometryComponentType component_type)
bool has(const GeometryComponentType component_type) const
void * data
Definition: RNA_types.h:52
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
void(* draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr)
Definition: BKE_node.h:253
PointerRNA * ptr
Definition: wm_files.c:3157