Blender  V3.3
NOD_math_functions.hh
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #pragma once
4 
5 #include "DNA_node_types.h"
6 
7 #include "BLI_math_base_safe.h"
8 #include "BLI_math_rotation.h"
9 #include "BLI_math_vector.hh"
10 #include "BLI_string_ref.hh"
11 
13 
14 namespace blender::nodes {
15 
19 
23  {
24  }
25 };
26 
27 const FloatMathOperationInfo *get_float_math_operation_info(int operation);
28 const FloatMathOperationInfo *get_float3_math_operation_info(int operation);
29 const FloatMathOperationInfo *get_float_compare_operation_info(int operation);
30 
46 template<typename Callback>
47 inline bool try_dispatch_float_math_fl_to_fl(const int operation, Callback &&callback)
48 {
50  if (info == nullptr) {
51  return false;
52  }
53 
54  static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle();
55  static auto exec_preset_slow = fn::CustomMF_presets::Materialized();
56 
57  /* This is just an utility function to keep the individual cases smaller. */
58  auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
59  callback(exec_preset, math_function, *info);
60  return true;
61  };
62 
63  switch (operation) {
64  case NODE_MATH_EXPONENT:
65  return dispatch(exec_preset_slow, [](float a) { return expf(a); });
66  case NODE_MATH_SQRT:
67  return dispatch(exec_preset_fast, [](float a) { return safe_sqrtf(a); });
68  case NODE_MATH_INV_SQRT:
69  return dispatch(exec_preset_fast, [](float a) { return safe_inverse_sqrtf(a); });
70  case NODE_MATH_ABSOLUTE:
71  return dispatch(exec_preset_fast, [](float a) { return fabs(a); });
72  case NODE_MATH_RADIANS:
73  return dispatch(exec_preset_fast, [](float a) { return (float)DEG2RAD(a); });
74  case NODE_MATH_DEGREES:
75  return dispatch(exec_preset_fast, [](float a) { return (float)RAD2DEG(a); });
76  case NODE_MATH_SIGN:
77  return dispatch(exec_preset_fast, [](float a) { return compatible_signf(a); });
78  case NODE_MATH_ROUND:
79  return dispatch(exec_preset_fast, [](float a) { return floorf(a + 0.5f); });
80  case NODE_MATH_FLOOR:
81  return dispatch(exec_preset_fast, [](float a) { return floorf(a); });
82  case NODE_MATH_CEIL:
83  return dispatch(exec_preset_fast, [](float a) { return ceilf(a); });
84  case NODE_MATH_FRACTION:
85  return dispatch(exec_preset_fast, [](float a) { return a - floorf(a); });
86  case NODE_MATH_TRUNC:
87  return dispatch(exec_preset_fast, [](float a) { return a >= 0.0f ? floorf(a) : ceilf(a); });
88  case NODE_MATH_SINE:
89  return dispatch(exec_preset_slow, [](float a) { return sinf(a); });
90  case NODE_MATH_COSINE:
91  return dispatch(exec_preset_slow, [](float a) { return cosf(a); });
92  case NODE_MATH_TANGENT:
93  return dispatch(exec_preset_slow, [](float a) { return tanf(a); });
94  case NODE_MATH_SINH:
95  return dispatch(exec_preset_slow, [](float a) { return sinhf(a); });
96  case NODE_MATH_COSH:
97  return dispatch(exec_preset_slow, [](float a) { return coshf(a); });
98  case NODE_MATH_TANH:
99  return dispatch(exec_preset_slow, [](float a) { return tanhf(a); });
100  case NODE_MATH_ARCSINE:
101  return dispatch(exec_preset_slow, [](float a) { return safe_asinf(a); });
102  case NODE_MATH_ARCCOSINE:
103  return dispatch(exec_preset_slow, [](float a) { return safe_acosf(a); });
105  return dispatch(exec_preset_slow, [](float a) { return atanf(a); });
106  }
107  return false;
108 }
109 
113 template<typename Callback>
114 inline bool try_dispatch_float_math_fl_fl_to_fl(const int operation, Callback &&callback)
115 {
116  const FloatMathOperationInfo *info = get_float_math_operation_info(operation);
117  if (info == nullptr) {
118  return false;
119  }
120 
121  static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle();
122  static auto exec_preset_slow = fn::CustomMF_presets::Materialized();
123 
124  /* This is just an utility function to keep the individual cases smaller. */
125  auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
126  callback(exec_preset, math_function, *info);
127  return true;
128  };
129 
130  switch (operation) {
131  case NODE_MATH_ADD:
132  return dispatch(exec_preset_fast, [](float a, float b) { return a + b; });
133  case NODE_MATH_SUBTRACT:
134  return dispatch(exec_preset_fast, [](float a, float b) { return a - b; });
135  case NODE_MATH_MULTIPLY:
136  return dispatch(exec_preset_fast, [](float a, float b) { return a * b; });
137  case NODE_MATH_DIVIDE:
138  return dispatch(exec_preset_fast, [](float a, float b) { return safe_divide(a, b); });
139  case NODE_MATH_POWER:
140  return dispatch(exec_preset_slow, [](float a, float b) { return safe_powf(a, b); });
141  case NODE_MATH_LOGARITHM:
142  return dispatch(exec_preset_slow, [](float a, float b) { return safe_logf(a, b); });
143  case NODE_MATH_MINIMUM:
144  return dispatch(exec_preset_fast, [](float a, float b) { return std::min(a, b); });
145  case NODE_MATH_MAXIMUM:
146  return dispatch(exec_preset_fast, [](float a, float b) { return std::max(a, b); });
147  case NODE_MATH_LESS_THAN:
148  return dispatch(exec_preset_fast, [](float a, float b) { return (float)(a < b); });
150  return dispatch(exec_preset_fast, [](float a, float b) { return (float)(a > b); });
151  case NODE_MATH_MODULO:
152  return dispatch(exec_preset_fast, [](float a, float b) { return safe_modf(a, b); });
153  case NODE_MATH_SNAP:
154  return dispatch(exec_preset_fast,
155  [](float a, float b) { return floorf(safe_divide(a, b)) * b; });
156  case NODE_MATH_ARCTAN2:
157  return dispatch(exec_preset_slow, [](float a, float b) { return atan2f(a, b); });
158  case NODE_MATH_PINGPONG:
159  return dispatch(exec_preset_fast, [](float a, float b) { return pingpongf(a, b); });
160  }
161  return false;
162 }
163 
167 template<typename Callback>
168 inline bool try_dispatch_float_math_fl_fl_fl_to_fl(const int operation, Callback &&callback)
169 {
170  const FloatMathOperationInfo *info = get_float_math_operation_info(operation);
171  if (info == nullptr) {
172  return false;
173  }
174 
175  /* This is just an utility function to keep the individual cases smaller. */
176  auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
177  callback(exec_preset, math_function, *info);
178  return true;
179  };
180 
181  switch (operation) {
183  return dispatch(fn::CustomMF_presets::AllSpanOrSingle(),
184  [](float a, float b, float c) { return a * b + c; });
185  case NODE_MATH_COMPARE:
187  [](float a, float b, float c) -> float {
188  return ((a == b) || (fabsf(a - b) <= fmaxf(c, FLT_EPSILON))) ? 1.0f : 0.0f;
189  });
192  [](float a, float b, float c) { return smoothminf(a, b, c); });
195  [](float a, float b, float c) { return -smoothminf(-a, -b, c); });
196  case NODE_MATH_WRAP:
198  [](float a, float b, float c) { return wrapf(a, b, c); });
199  }
200  return false;
201 }
202 
206 template<typename Callback>
208  Callback &&callback)
209 {
210  using namespace blender::math;
211 
213  if (info == nullptr) {
214  return false;
215  }
216 
217  static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle();
218  static auto exec_preset_slow = fn::CustomMF_presets::Materialized();
219 
220  /* This is just a utility function to keep the individual cases smaller. */
221  auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
222  callback(exec_preset, math_function, *info);
223  return true;
224  };
225 
226  switch (operation) {
228  return dispatch(exec_preset_fast, [](float3 a, float3 b) { return a + b; });
230  return dispatch(exec_preset_fast, [](float3 a, float3 b) { return a - b; });
232  return dispatch(exec_preset_fast, [](float3 a, float3 b) { return a * b; });
234  return dispatch(exec_preset_fast, [](float3 a, float3 b) { return safe_divide(a, b); });
236  return dispatch(exec_preset_fast,
237  [](float3 a, float3 b) { return cross_high_precision(a, b); });
239  return dispatch(exec_preset_fast, [](float3 a, float3 b) { return project(a, b); });
241  return dispatch(exec_preset_fast,
242  [](float3 a, float3 b) { return reflect(a, normalize(b)); });
244  return dispatch(exec_preset_fast,
245  [](float3 a, float3 b) { return floor(safe_divide(a, b)) * b; });
247  return dispatch(exec_preset_slow, [](float3 a, float3 b) { return mod(a, b); });
249  return dispatch(exec_preset_fast, [](float3 a, float3 b) { return min(a, b); });
251  return dispatch(exec_preset_fast, [](float3 a, float3 b) { return max(a, b); });
252  default:
253  return false;
254  }
255  return false;
256 }
257 
261 template<typename Callback>
263  Callback &&callback)
264 {
265  using namespace blender::math;
266 
268  if (info == nullptr) {
269  return false;
270  }
271 
272  static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle();
273 
274  /* This is just a utility function to keep the individual cases smaller. */
275  auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
276  callback(exec_preset, math_function, *info);
277  return true;
278  };
279 
280  switch (operation) {
282  return dispatch(exec_preset_fast, [](float3 a, float3 b) { return dot(a, b); });
284  return dispatch(exec_preset_fast, [](float3 a, float3 b) { return distance(a, b); });
285  default:
286  return false;
287  }
288  return false;
289 }
290 
294 template<typename Callback>
296  Callback &&callback)
297 {
298  using namespace blender::math;
299 
301  if (info == nullptr) {
302  return false;
303  }
304 
305  static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle();
306  static auto exec_preset_slow = fn::CustomMF_presets::Materialized();
307 
308  /* This is just a utility function to keep the individual cases smaller. */
309  auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
310  callback(exec_preset, math_function, *info);
311  return true;
312  };
313 
314  switch (operation) {
316  return dispatch(exec_preset_fast, [](float3 a, float3 b, float3 c) { return a * b + c; });
318  return dispatch(exec_preset_slow, [](float3 a, float3 b, float3 c) {
319  return float3(wrapf(a.x, b.x, c.x), wrapf(a.y, b.y, c.y), wrapf(a.z, b.z, c.z));
320  });
322  return dispatch(exec_preset_fast,
323  [](float3 a, float3 b, float3 c) { return faceforward(a, b, c); });
324  default:
325  return false;
326  }
327  return false;
328 }
329 
333 template<typename Callback>
335  Callback &&callback)
336 {
337  using namespace blender::math;
338 
340  if (info == nullptr) {
341  return false;
342  }
343 
344  static auto exec_preset_slow = fn::CustomMF_presets::Materialized();
345 
346  /* This is just a utility function to keep the individual cases smaller. */
347  auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
348  callback(exec_preset, math_function, *info);
349  return true;
350  };
351 
352  switch (operation) {
354  return dispatch(exec_preset_slow,
355  [](float3 a, float3 b, float c) { return refract(a, normalize(b), c); });
356  default:
357  return false;
358  }
359  return false;
360 }
361 
365 template<typename Callback>
367  Callback &&callback)
368 {
369  using namespace blender::math;
370 
372  if (info == nullptr) {
373  return false;
374  }
375 
376  static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle();
377 
378  /* This is just a utility function to keep the individual cases smaller. */
379  auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
380  callback(exec_preset, math_function, *info);
381  return true;
382  };
383 
384  switch (operation) {
386  return dispatch(exec_preset_fast, [](float3 in) { return length(in); });
387  default:
388  return false;
389  }
390  return false;
391 }
392 
396 template<typename Callback>
398  Callback &&callback)
399 {
401  if (info == nullptr) {
402  return false;
403  }
404 
405  static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle();
406 
407  /* This is just a utility function to keep the individual cases smaller. */
408  auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
409  callback(exec_preset, math_function, *info);
410  return true;
411  };
412 
413  switch (operation) {
415  return dispatch(exec_preset_fast, [](float3 a, float b) { return a * b; });
416  default:
417  return false;
418  }
419  return false;
420 }
421 
425 template<typename Callback>
427  Callback &&callback)
428 {
429  using namespace blender::math;
430 
432  if (info == nullptr) {
433  return false;
434  }
435 
436  static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle();
437  static auto exec_preset_slow = fn::CustomMF_presets::Materialized();
438 
439  /* This is just a utility function to keep the individual cases smaller. */
440  auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
441  callback(exec_preset, math_function, *info);
442  return true;
443  };
444 
445  switch (operation) {
447  return dispatch(exec_preset_fast,
448  [](float3 in) { return normalize(in); }); /* Should be safe. */
450  return dispatch(exec_preset_fast, [](float3 in) { return floor(in); });
452  return dispatch(exec_preset_fast, [](float3 in) { return ceil(in); });
454  return dispatch(exec_preset_fast, [](float3 in) { return fract(in); });
456  return dispatch(exec_preset_fast, [](float3 in) { return abs(in); });
458  return dispatch(exec_preset_slow,
459  [](float3 in) { return float3(sinf(in.x), sinf(in.y), sinf(in.z)); });
461  return dispatch(exec_preset_slow,
462  [](float3 in) { return float3(cosf(in.x), cosf(in.y), cosf(in.z)); });
464  return dispatch(exec_preset_slow,
465  [](float3 in) { return float3(tanf(in.x), tanf(in.y), tanf(in.z)); });
466  default:
467  return false;
468  }
469  return false;
470 }
471 
472 } // namespace blender::nodes
MINLINE float safe_sqrtf(float a)
MINLINE float safe_logf(float a, float base)
MINLINE float safe_acosf(float a)
MINLINE float safe_modf(float a, float b)
MINLINE float safe_powf(float base, float exponent)
MINLINE float safe_asinf(float a)
MINLINE float safe_inverse_sqrtf(float a)
#define DEG2RAD(_deg)
#define RAD2DEG(_rad)
NodeVectorMathOperation
@ NODE_VECTOR_MATH_NORMALIZE
@ NODE_VECTOR_MATH_LENGTH
@ NODE_VECTOR_MATH_CROSS_PRODUCT
@ NODE_VECTOR_MATH_CEIL
@ NODE_VECTOR_MATH_MODULO
@ NODE_VECTOR_MATH_ADD
@ NODE_VECTOR_MATH_COSINE
@ NODE_VECTOR_MATH_REFLECT
@ NODE_VECTOR_MATH_WRAP
@ NODE_VECTOR_MATH_REFRACT
@ NODE_VECTOR_MATH_DOT_PRODUCT
@ NODE_VECTOR_MATH_ABSOLUTE
@ NODE_VECTOR_MATH_DIVIDE
@ NODE_VECTOR_MATH_TANGENT
@ NODE_VECTOR_MATH_DISTANCE
@ NODE_VECTOR_MATH_FLOOR
@ NODE_VECTOR_MATH_SNAP
@ NODE_VECTOR_MATH_SINE
@ NODE_VECTOR_MATH_FRACTION
@ NODE_VECTOR_MATH_PROJECT
@ NODE_VECTOR_MATH_MULTIPLY
@ NODE_VECTOR_MATH_SCALE
@ NODE_VECTOR_MATH_MAXIMUM
@ NODE_VECTOR_MATH_FACEFORWARD
@ NODE_VECTOR_MATH_SUBTRACT
@ NODE_VECTOR_MATH_MULTIPLY_ADD
@ NODE_VECTOR_MATH_MINIMUM
@ 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
#define sinf(x)
Definition: cuda/compat.h:102
#define cosf(x)
Definition: cuda/compat.h:101
#define expf(x)
Definition: cuda/compat.h:106
#define tanf(x)
Definition: cuda/compat.h:104
DEGForeachIDComponentCallback callback
MINLINE float smoothminf(float a, float b, float c)
MINLINE float pingpongf(float value, float scale)
MINLINE float compatible_signf(float f)
MINLINE float wrapf(float value, float max, float min)
ccl_device_inline float2 fabs(const float2 &a)
Definition: math_float2.h:222
ccl_device_inline float3 refract(const float3 incident, const float3 normal, const float eta)
Definition: math_float3.h:435
ccl_device_inline float3 faceforward(const float3 vector, const float3 incident, const float3 reference)
Definition: math_float3.h:444
ccl_device_inline float3 ceil(const float3 &a)
Definition: math_float3.h:363
ccl_device_inline float3 reflect(const float3 incident, const float3 normal)
Definition: math_float3.h:429
#define atan2f(x, y)
Definition: metal/compat.h:227
#define fmaxf(x, y)
Definition: metal/compat.h:228
#define ceilf(x)
Definition: metal/compat.h:225
#define atanf(x)
Definition: metal/compat.h:223
#define floorf(x)
Definition: metal/compat.h:224
#define tanhf(x)
Definition: metal/compat.h:233
#define sinhf(x)
Definition: metal/compat.h:231
#define coshf(x)
Definition: metal/compat.h:232
#define fabsf(x)
Definition: metal/compat.h:219
static unsigned c
Definition: RandGen.cpp:83
static unsigned a[3]
Definition: RandGen.cpp:78
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
T length(const vec_base< T, Size > &a)
T distance(const T &a, const T &b)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
vec_base< T, Size > project(const vec_base< T, Size > &p, const vec_base< T, Size > &v_proj)
T floor(const T &a)
T abs(const T &a)
T safe_divide(const T &a, const T &b)
vec_base< float, 3 > cross_high_precision(const vec_base< float, 3 > &a, const vec_base< float, 3 > &b)
bool try_dispatch_float_math_fl_fl_to_fl(const int operation, Callback &&callback)
bool try_dispatch_float_math_fl3_fl3_to_fl3(const NodeVectorMathOperation operation, Callback &&callback)
bool try_dispatch_float_math_fl3_to_fl(const NodeVectorMathOperation operation, Callback &&callback)
const FloatMathOperationInfo * get_float3_math_operation_info(const int operation)
bool try_dispatch_float_math_fl3_fl3_to_fl(const NodeVectorMathOperation operation, Callback &&callback)
bool try_dispatch_float_math_fl_to_fl(const int operation, Callback &&callback)
const FloatMathOperationInfo * get_float_compare_operation_info(const int operation)
const FloatMathOperationInfo * get_float_math_operation_info(const int operation)
bool try_dispatch_float_math_fl3_fl_to_fl3(const NodeVectorMathOperation operation, Callback &&callback)
bool try_dispatch_float_math_fl3_fl3_fl_to_fl3(const NodeVectorMathOperation operation, Callback &&callback)
bool try_dispatch_float_math_fl3_to_fl3(const NodeVectorMathOperation operation, Callback &&callback)
bool try_dispatch_float_math_fl_fl_fl_to_fl(const int operation, Callback &&callback)
bool try_dispatch_float_math_fl3_fl3_fl3_to_fl3(const NodeVectorMathOperation operation, Callback &&callback)
vec_base< float, 3 > float3
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
float fract(float a)
Definition: node_math.h:21
#define min(a, b)
Definition: sort.c:35
FloatMathOperationInfo(StringRefNull title_case_name, StringRefNull shader_name)
float max
ccl_device_inline int mod(int x, int m)
Definition: util/math.h:490