Blender  V2.93
NOD_math_functions.hh
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 #pragma once
18 
19 #include "DNA_node_types.h"
20 
21 #include "BLI_float3.hh"
22 #include "BLI_math_base_safe.h"
23 #include "BLI_math_rotation.h"
24 #include "BLI_string_ref.hh"
25 
26 namespace blender::nodes {
27 
31 
35  {
36  }
37 };
38 
39 const FloatMathOperationInfo *get_float_math_operation_info(const int operation);
40 const FloatMathOperationInfo *get_float3_math_operation_info(const int operation);
41 const FloatMathOperationInfo *get_float_compare_operation_info(const int operation);
42 
58 template<typename Callback>
59 inline bool try_dispatch_float_math_fl_to_fl(const int operation, Callback &&callback)
60 {
62  if (info == nullptr) {
63  return false;
64  }
65 
66  /* This is just an utility function to keep the individual cases smaller. */
67  auto dispatch = [&](auto math_function) -> bool {
68  callback(math_function, *info);
69  return true;
70  };
71 
72  switch (operation) {
73  case NODE_MATH_EXPONENT:
74  return dispatch([](float a) { return expf(a); });
75  case NODE_MATH_SQRT:
76  return dispatch([](float a) { return safe_sqrtf(a); });
77  case NODE_MATH_INV_SQRT:
78  return dispatch([](float a) { return safe_inverse_sqrtf(a); });
79  case NODE_MATH_ABSOLUTE:
80  return dispatch([](float a) { return fabs(a); });
81  case NODE_MATH_RADIANS:
82  return dispatch([](float a) { return (float)DEG2RAD(a); });
83  case NODE_MATH_DEGREES:
84  return dispatch([](float a) { return (float)RAD2DEG(a); });
85  case NODE_MATH_SIGN:
86  return dispatch([](float a) { return compatible_signf(a); });
87  case NODE_MATH_ROUND:
88  return dispatch([](float a) { return floorf(a + 0.5f); });
89  case NODE_MATH_FLOOR:
90  return dispatch([](float a) { return floorf(a); });
91  case NODE_MATH_CEIL:
92  return dispatch([](float a) { return ceilf(a); });
93  case NODE_MATH_FRACTION:
94  return dispatch([](float a) { return a - floorf(a); });
95  case NODE_MATH_TRUNC:
96  return dispatch([](float a) { return a >= 0.0f ? floorf(a) : ceilf(a); });
97  case NODE_MATH_SINE:
98  return dispatch([](float a) { return sinf(a); });
99  case NODE_MATH_COSINE:
100  return dispatch([](float a) { return cosf(a); });
101  case NODE_MATH_TANGENT:
102  return dispatch([](float a) { return tanf(a); });
103  case NODE_MATH_SINH:
104  return dispatch([](float a) { return sinhf(a); });
105  case NODE_MATH_COSH:
106  return dispatch([](float a) { return coshf(a); });
107  case NODE_MATH_TANH:
108  return dispatch([](float a) { return tanhf(a); });
109  case NODE_MATH_ARCSINE:
110  return dispatch([](float a) { return safe_asinf(a); });
111  case NODE_MATH_ARCCOSINE:
112  return dispatch([](float a) { return safe_acosf(a); });
114  return dispatch([](float a) { return atanf(a); });
115  }
116  return false;
117 }
118 
122 template<typename Callback>
123 inline bool try_dispatch_float_math_fl_fl_to_fl(const int operation, Callback &&callback)
124 {
125  const FloatMathOperationInfo *info = get_float_math_operation_info(operation);
126  if (info == nullptr) {
127  return false;
128  }
129 
130  /* This is just an utility function to keep the individual cases smaller. */
131  auto dispatch = [&](auto math_function) -> bool {
132  callback(math_function, *info);
133  return true;
134  };
135 
136  switch (operation) {
137  case NODE_MATH_ADD:
138  return dispatch([](float a, float b) { return a + b; });
139  case NODE_MATH_SUBTRACT:
140  return dispatch([](float a, float b) { return a - b; });
141  case NODE_MATH_MULTIPLY:
142  return dispatch([](float a, float b) { return a * b; });
143  case NODE_MATH_DIVIDE:
144  return dispatch([](float a, float b) { return safe_divide(a, b); });
145  case NODE_MATH_POWER:
146  return dispatch([](float a, float b) { return safe_powf(a, b); });
147  case NODE_MATH_LOGARITHM:
148  return dispatch([](float a, float b) { return safe_logf(a, b); });
149  case NODE_MATH_MINIMUM:
150  return dispatch([](float a, float b) { return std::min(a, b); });
151  case NODE_MATH_MAXIMUM:
152  return dispatch([](float a, float b) { return std::max(a, b); });
153  case NODE_MATH_LESS_THAN:
154  return dispatch([](float a, float b) { return (float)(a < b); });
156  return dispatch([](float a, float b) { return (float)(a > b); });
157  case NODE_MATH_MODULO:
158  return dispatch([](float a, float b) { return safe_modf(a, b); });
159  case NODE_MATH_SNAP:
160  return dispatch([](float a, float b) { return floorf(safe_divide(a, b)) * b; });
161  case NODE_MATH_ARCTAN2:
162  return dispatch([](float a, float b) { return atan2f(a, b); });
163  case NODE_MATH_PINGPONG:
164  return dispatch([](float a, float b) { return pingpongf(a, b); });
165  }
166  return false;
167 }
168 
172 template<typename Callback>
173 inline bool try_dispatch_float_math_fl_fl_fl_to_fl(const int operation, Callback &&callback)
174 {
175  const FloatMathOperationInfo *info = get_float_math_operation_info(operation);
176  if (info == nullptr) {
177  return false;
178  }
179 
180  /* This is just an utility function to keep the individual cases smaller. */
181  auto dispatch = [&](auto math_function) -> bool {
182  callback(math_function, *info);
183  return true;
184  };
185 
186  switch (operation) {
188  return dispatch([](float a, float b, float c) { return a * b + c; });
189  case NODE_MATH_COMPARE:
190  return dispatch([](float a, float b, float c) -> float {
191  return ((a == b) || (fabsf(a - b) <= fmaxf(c, FLT_EPSILON))) ? 1.0f : 0.0f;
192  });
194  return dispatch([](float a, float b, float c) { return smoothminf(a, b, c); });
196  return dispatch([](float a, float b, float c) { return -smoothminf(-a, -b, -c); });
197  case NODE_MATH_WRAP:
198  return dispatch([](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 {
211  if (info == nullptr) {
212  return false;
213  }
214 
215  /* This is just an utility function to keep the individual cases smaller. */
216  auto dispatch = [&](auto math_function) -> bool {
217  callback(math_function, *info);
218  return true;
219  };
220 
221  switch (operation) {
223  return dispatch([](float a, float b) { return a < b; });
225  return dispatch([](float a, float b) { return a <= b; });
227  return dispatch([](float a, float b) { return a > b; });
229  return dispatch([](float a, float b) { return a >= b; });
230  default:
231  return false;
232  }
233  return false;
234 }
235 
239 template<typename Callback>
241  Callback &&callback)
242 {
244  if (info == nullptr) {
245  return false;
246  }
247 
248  /* This is just a utility function to keep the individual cases smaller. */
249  auto dispatch = [&](auto math_function) -> bool {
250  callback(math_function, *info);
251  return true;
252  };
253 
254  switch (operation) {
256  return dispatch([](float3 a, float3 b) { return a + b; });
258  return dispatch([](float3 a, float3 b) { return a - b; });
260  return dispatch([](float3 a, float3 b) { return a * b; });
262  return dispatch([](float3 a, float3 b) {
263  return float3(safe_divide(a.x, b.x), safe_divide(a.y, b.y), safe_divide(a.z, b.z));
264  });
266  return dispatch([](float3 a, float3 b) { return float3::cross_high_precision(a, b); });
268  return dispatch([](float3 a, float3 b) {
269  float length_squared = float3::dot(b, b);
270  return (length_squared != 0.0) ? (float3::dot(a, b) / length_squared) * b : float3(0.0f);
271  });
273  return dispatch([](float3 a, float3 b) {
274  b.normalize();
275  return a.reflected(b);
276  });
278  return dispatch([](float3 a, float3 b) {
279  return float3(floor(safe_divide(a.x, b.x)),
280  floor(safe_divide(a.y, b.y)),
281  floor(safe_divide(a.z, b.z))) *
282  b;
283  });
285  return dispatch([](float3 a, float3 b) {
286  return float3(safe_modf(a.x, b.x), safe_modf(a.y, b.y), safe_modf(a.z, b.z));
287  });
289  return dispatch([](float3 a, float3 b) {
290  return float3(min_ff(a.x, b.x), min_ff(a.y, b.y), min_ff(a.z, b.z));
291  });
293  return dispatch([](float3 a, float3 b) {
294  return float3(max_ff(a.x, b.x), max_ff(a.y, b.y), max_ff(a.z, b.z));
295  });
296  default:
297  return false;
298  }
299  return false;
300 }
301 
305 template<typename Callback>
307  Callback &&callback)
308 {
310  if (info == nullptr) {
311  return false;
312  }
313 
314  /* This is just a utility function to keep the individual cases smaller. */
315  auto dispatch = [&](auto math_function) -> bool {
316  callback(math_function, *info);
317  return true;
318  };
319 
320  switch (operation) {
322  return dispatch([](float3 a, float3 b) { return float3::dot(a, b); });
324  return dispatch([](float3 a, float3 b) { return float3::distance(a, b); });
325  default:
326  return false;
327  }
328  return false;
329 }
330 
334 template<typename Callback>
336  Callback &&callback)
337 {
339  if (info == nullptr) {
340  return false;
341  }
342 
343  /* This is just a utility function to keep the individual cases smaller. */
344  auto dispatch = [&](auto math_function) -> bool {
345  callback(math_function, *info);
346  return true;
347  };
348 
349  switch (operation) {
351  return dispatch([](float3 a, float3 b, float3 c) {
352  return float3(wrapf(a.x, b.x, c.x), wrapf(a.y, b.y, c.y), wrapf(a.z, b.z, c.z));
353  });
355  return dispatch([](float3 a, float3 b, float3 c) { return float3::faceforward(a, b, c); });
356  default:
357  return false;
358  }
359  return false;
360 }
361 
365 template<typename Callback>
367  Callback &&callback)
368 {
370  if (info == nullptr) {
371  return false;
372  }
373 
374  /* This is just a utility function to keep the individual cases smaller. */
375  auto dispatch = [&](auto math_function) -> bool {
376  callback(math_function, *info);
377  return true;
378  };
379 
380  switch (operation) {
382  return dispatch(
383  [](float3 a, float3 b, float c) { return float3::refract(a, b.normalized(), c); });
384  default:
385  return false;
386  }
387  return false;
388 }
389 
393 template<typename Callback>
395  Callback &&callback)
396 {
398  if (info == nullptr) {
399  return false;
400  }
401 
402  /* This is just a utility function to keep the individual cases smaller. */
403  auto dispatch = [&](auto math_function) -> bool {
404  callback(math_function, *info);
405  return true;
406  };
407 
408  switch (operation) {
410  return dispatch([](float3 in) { return in.length(); });
411  default:
412  return false;
413  }
414  return false;
415 }
416 
420 template<typename Callback>
422  Callback &&callback)
423 {
425  if (info == nullptr) {
426  return false;
427  }
428 
429  /* This is just a utility function to keep the individual cases smaller. */
430  auto dispatch = [&](auto math_function) -> bool {
431  callback(math_function, *info);
432  return true;
433  };
434 
435  switch (operation) {
437  return dispatch([](float3 a, float b) { return a * b; });
438  default:
439  return false;
440  }
441  return false;
442 }
443 
447 template<typename Callback>
449  Callback &&callback)
450 {
452  if (info == nullptr) {
453  return false;
454  }
455 
456  /* This is just a utility function to keep the individual cases smaller. */
457  auto dispatch = [&](auto math_function) -> bool {
458  callback(math_function, *info);
459  return true;
460  };
461 
462  switch (operation) {
464  return dispatch([](float3 in) {
465  float3 out = in;
466  out.normalize();
467  return out;
468  }); /* Should be safe. */
470  return dispatch([](float3 in) { return float3(floor(in.x), floor(in.y), floor(in.z)); });
472  return dispatch([](float3 in) { return float3(ceil(in.x), ceil(in.y), ceil(in.z)); });
474  return dispatch(
475  [](float3 in) { return in - float3(floor(in.x), floor(in.y), floor(in.z)); });
477  return dispatch([](float3 in) { return float3::abs(in); });
479  return dispatch([](float3 in) { return float3(sinf(in.x), sinf(in.y), sinf(in.z)); });
481  return dispatch([](float3 in) { return float3(cosf(in.x), cosf(in.y), cosf(in.z)); });
483  return dispatch([](float3 in) { return float3(tanf(in.x), tanf(in.y), tanf(in.z)); });
484  default:
485  return false;
486  }
487  return false;
488 }
489 
490 } // namespace blender::nodes
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
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_divide(float a, float b)
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_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
FloatCompareOperation
@ NODE_FLOAT_COMPARE_GREATER_THAN
@ NODE_FLOAT_COMPARE_GREATER_EQUAL
@ NODE_FLOAT_COMPARE_LESS_EQUAL
@ NODE_FLOAT_COMPARE_LESS_THAN
DEGForeachIDComponentCallback callback
#define sinf(x)
#define cosf(x)
#define expf(x)
#define tanf(x)
#define atan2f(x, y)
#define fmaxf(x, y)
#define ceilf(x)
#define atanf(x)
#define floorf(x)
#define tanhf(x)
#define sinhf(x)
#define coshf(x)
#define fabsf(x)
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)
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
bool try_dispatch_float_math_fl_fl_to_bool(const FloatCompareOperation operation, Callback &&callback)
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)
#define min(a, b)
Definition: sort.c:51
static float3 cross_high_precision(const float3 &a, const float3 &b)
Definition: BLI_float3.hh:241
float3 normalized() const
Definition: BLI_float3.hh:160
float length() const
Definition: BLI_float3.hh:167
static float3 abs(const float3 &a)
Definition: BLI_float3.hh:271
static float dot(const float3 &a, const float3 &b)
Definition: BLI_float3.hh:236
static float3 faceforward(const float3 &vector, const float3 &incident, const float3 &reference)
Definition: BLI_float3.hh:207
static float distance(const float3 &a, const float3 &b)
Definition: BLI_float3.hh:255
static float3 refract(const float3 &incident, const float3 &normal, const float eta)
Definition: BLI_float3.hh:194
FloatMathOperationInfo(StringRefNull title_case_name, StringRefNull shader_name)
float max
ccl_device_inline float2 floor(const float2 &a)
ccl_device_inline float2 fabs(const float2 &a)
ccl_device_inline float3 ceil(const float3 &a)