Blender V5.0
NOD_math_functions.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
7#include "DNA_node_types.h"
8
10#include "BLI_math_rotation.h"
11#include "BLI_math_vector.hh"
12#include "BLI_string_ref.hh"
13
15
16#include "NOD_multi_function.hh"
17
18namespace blender::nodes {
19
21
32
33const FloatMathOperationInfo *get_float_math_operation_info(int operation);
34const FloatMathOperationInfo *get_float3_math_operation_info(int operation);
35const FloatMathOperationInfo *get_float_compare_operation_info(int operation);
36
52template<typename Callback>
53inline bool try_dispatch_float_math_fl_to_fl(const int operation, Callback &&callback)
54{
56 if (info == nullptr) {
57 return false;
58 }
59
60 static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
61 static auto exec_preset_slow = mf::build::exec_presets::Materialized();
62
63 /* This is just an utility function to keep the individual cases smaller. */
64 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
65 callback(exec_preset, math_function, *info);
66 return true;
67 };
68
69 switch (operation) {
71 return dispatch(exec_preset_slow, [](float a) { return expf(a); });
72 case NODE_MATH_SQRT:
73 return dispatch(exec_preset_fast, [](float a) { return safe_sqrtf(a); });
75 return dispatch(exec_preset_fast, [](float a) { return safe_inverse_sqrtf(a); });
77 return dispatch(exec_preset_fast, [](float a) { return fabs(a); });
79 return dispatch(exec_preset_fast, [](float a) { return (float)DEG2RAD(a); });
81 return dispatch(exec_preset_fast, [](float a) { return (float)RAD2DEG(a); });
82 case NODE_MATH_SIGN:
83 return dispatch(exec_preset_fast, [](float a) { return compatible_signf(a); });
84 case NODE_MATH_ROUND:
85 return dispatch(exec_preset_fast, [](float a) { return floorf(a + 0.5f); });
86 case NODE_MATH_FLOOR:
87 return dispatch(exec_preset_fast, [](float a) { return floorf(a); });
88 case NODE_MATH_CEIL:
89 return dispatch(exec_preset_fast, [](float a) { return ceilf(a); });
91 return dispatch(exec_preset_fast, [](float a) { return a - floorf(a); });
92 case NODE_MATH_TRUNC:
93 return dispatch(exec_preset_fast, [](float a) { return a >= 0.0f ? floorf(a) : ceilf(a); });
94 case NODE_MATH_SINE:
95 return dispatch(exec_preset_slow, [](float a) { return sinf(a); });
97 return dispatch(exec_preset_slow, [](float a) { return cosf(a); });
99 return dispatch(exec_preset_slow, [](float a) { return tanf(a); });
100 case NODE_MATH_SINH:
101 return dispatch(exec_preset_slow, [](float a) { return sinhf(a); });
102 case NODE_MATH_COSH:
103 return dispatch(exec_preset_slow, [](float a) { return coshf(a); });
104 case NODE_MATH_TANH:
105 return dispatch(exec_preset_slow, [](float a) { return tanhf(a); });
107 return dispatch(exec_preset_slow, [](float a) { return safe_asinf(a); });
109 return dispatch(exec_preset_slow, [](float a) { return safe_acosf(a); });
111 return dispatch(exec_preset_slow, [](float a) { return atanf(a); });
112 }
113 return false;
114}
115
119template<typename Callback>
120inline bool try_dispatch_float_math_fl_fl_to_fl(const int operation, Callback &&callback)
121{
123 if (info == nullptr) {
124 return false;
125 }
126
127 static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
128 static auto exec_preset_slow = mf::build::exec_presets::Materialized();
129
130 /* This is just an utility function to keep the individual cases smaller. */
131 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
132 callback(exec_preset, math_function, *info);
133 return true;
134 };
135
136 switch (operation) {
137 case NODE_MATH_ADD:
138 return dispatch(exec_preset_fast, [](float a, float b) { return a + b; });
140 return dispatch(exec_preset_fast, [](float a, float b) { return a - b; });
142 return dispatch(exec_preset_fast, [](float a, float b) { return a * b; });
143 case NODE_MATH_DIVIDE:
144 return dispatch(exec_preset_fast, [](float a, float b) { return safe_divide(a, b); });
145 case NODE_MATH_POWER:
146 return dispatch(exec_preset_slow, [](float a, float b) { return safe_powf(a, b); });
148 return dispatch(exec_preset_slow, [](float a, float b) { return safe_logf(a, b); });
150 return dispatch(exec_preset_fast, [](float a, float b) { return std::min(a, b); });
152 return dispatch(exec_preset_fast, [](float a, float b) { return std::max(a, b); });
154 return dispatch(exec_preset_fast, [](float a, float b) { return (float)(a < b); });
156 return dispatch(exec_preset_fast, [](float a, float b) { return (float)(a > b); });
157 case NODE_MATH_MODULO:
158 return dispatch(exec_preset_fast, [](float a, float b) { return safe_modf(a, b); });
160 return dispatch(exec_preset_fast, [](float a, float b) { return safe_floored_modf(a, b); });
161 case NODE_MATH_SNAP:
162 return dispatch(exec_preset_fast,
163 [](float a, float b) { return floorf(safe_divide(a, b)) * b; });
165 return dispatch(exec_preset_slow, [](float a, float b) { return atan2f(a, b); });
167 return dispatch(exec_preset_fast, [](float a, float b) { return pingpongf(a, b); });
168 }
169 return false;
170}
171
175template<typename Callback>
176inline bool try_dispatch_float_math_fl_fl_fl_to_fl(const int operation, Callback &&callback)
177{
179 if (info == nullptr) {
180 return false;
181 }
182
183 /* This is just an utility function to keep the individual cases smaller. */
184 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
185 callback(exec_preset, math_function, *info);
186 return true;
187 };
188
189 switch (operation) {
191 return dispatch(mf::build::exec_presets::AllSpanOrSingle(),
192 [](float a, float b, float c) { return a * b + c; });
194 return dispatch(mf::build::exec_presets::SomeSpanOrSingle<0, 1>(),
195 [](float a, float b, float c) -> float {
196 return ((a == b) || (fabsf(a - b) <= fmaxf(c, FLT_EPSILON))) ? 1.0f : 0.0f;
197 });
199 return dispatch(mf::build::exec_presets::SomeSpanOrSingle<0, 1>(),
200 [](float a, float b, float c) { return smoothminf(a, b, c); });
202 return dispatch(mf::build::exec_presets::SomeSpanOrSingle<0, 1>(),
203 [](float a, float b, float c) { return -smoothminf(-a, -b, c); });
204 case NODE_MATH_WRAP:
205 return dispatch(mf::build::exec_presets::SomeSpanOrSingle<0>(),
206 [](float a, float b, float c) { return wrapf(a, b, c); });
207 }
208 return false;
209}
210
214template<typename Callback>
216 Callback &&callback)
217{
218 using namespace blender::math;
219
221 if (info == nullptr) {
222 return false;
223 }
224
225 static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
226 static auto exec_preset_slow = mf::build::exec_presets::Materialized();
227
228 /* This is just a utility function to keep the individual cases smaller. */
229 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
230 callback(exec_preset, math_function, *info);
231 return true;
232 };
233
234 switch (operation) {
236 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return a + b; });
238 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return a - b; });
240 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return a * b; });
242 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return safe_divide(a, b); });
244 return dispatch(exec_preset_fast,
245 [](float3 a, float3 b) { return cross_high_precision(a, b); });
247 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return project(a, b); });
249 return dispatch(exec_preset_fast,
250 [](float3 a, float3 b) { return reflect(a, normalize(b)); });
252 return dispatch(exec_preset_fast,
253 [](float3 a, float3 b) { return floor(safe_divide(a, b)) * b; });
255 return dispatch(exec_preset_slow, [](float3 a, float3 b) { return mod(a, b); });
257 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return min(a, b); });
259 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return max(a, b); });
261 return dispatch(exec_preset_slow, [](float3 a, float3 b) {
262 return float3(safe_powf(a.x, b.x), safe_powf(a.y, b.y), safe_powf(a.z, b.z));
263 });
264 default:
265 return false;
266 }
267 return false;
268}
269
273template<typename Callback>
275 Callback &&callback)
276{
277 using namespace blender::math;
278
280 if (info == nullptr) {
281 return false;
282 }
283
284 static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
285
286 /* This is just a utility function to keep the individual cases smaller. */
287 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
288 callback(exec_preset, math_function, *info);
289 return true;
290 };
291
292 switch (operation) {
294 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return dot(a, b); });
296 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return distance(a, b); });
297 default:
298 return false;
299 }
300 return false;
301}
302
306template<typename Callback>
308 Callback &&callback)
309{
310 using namespace blender::math;
311
313 if (info == nullptr) {
314 return false;
315 }
316
317 static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
318 static auto exec_preset_slow = mf::build::exec_presets::Materialized();
319
320 /* This is just a utility function to keep the individual cases smaller. */
321 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
322 callback(exec_preset, math_function, *info);
323 return true;
324 };
325
326 switch (operation) {
328 return dispatch(exec_preset_fast, [](float3 a, float3 b, float3 c) { return a * b + c; });
330 return dispatch(exec_preset_slow, [](float3 a, float3 b, float3 c) {
331 return float3(wrapf(a.x, b.x, c.x), wrapf(a.y, b.y, c.y), wrapf(a.z, b.z, c.z));
332 });
334 return dispatch(exec_preset_fast,
335 [](float3 a, float3 b, float3 c) { return faceforward(a, b, c); });
336 default:
337 return false;
338 }
339 return false;
340}
341
345template<typename Callback>
347 Callback &&callback)
348{
349 using namespace blender::math;
350
352 if (info == nullptr) {
353 return false;
354 }
355
356 static auto exec_preset_slow = mf::build::exec_presets::Materialized();
357
358 /* This is just a utility function to keep the individual cases smaller. */
359 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
360 callback(exec_preset, math_function, *info);
361 return true;
362 };
363
364 switch (operation) {
366 return dispatch(exec_preset_slow,
367 [](float3 a, float3 b, float c) { return refract(a, normalize(b), c); });
368 default:
369 return false;
370 }
371 return false;
372}
373
377template<typename Callback>
379 Callback &&callback)
380{
381 using namespace blender::math;
382
384 if (info == nullptr) {
385 return false;
386 }
387
388 static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
389
390 /* This is just a utility function to keep the individual cases smaller. */
391 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
392 callback(exec_preset, math_function, *info);
393 return true;
394 };
395
396 switch (operation) {
398 return dispatch(exec_preset_fast, [](float3 in) { return length(in); });
399 default:
400 return false;
401 }
402 return false;
403}
404
408template<typename Callback>
410 Callback &&callback)
411{
413 if (info == nullptr) {
414 return false;
415 }
416
417 static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
418
419 /* This is just a utility function to keep the individual cases smaller. */
420 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
421 callback(exec_preset, math_function, *info);
422 return true;
423 };
424
425 switch (operation) {
427 return dispatch(exec_preset_fast, [](float3 a, float b) { return a * b; });
428 default:
429 return false;
430 }
431 return false;
432}
433
437template<typename Callback>
439 Callback &&callback)
440{
441 using namespace blender::math;
442
444 if (info == nullptr) {
445 return false;
446 }
447
448 static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
449 static auto exec_preset_slow = mf::build::exec_presets::Materialized();
450
451 /* This is just a utility function to keep the individual cases smaller. */
452 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
453 callback(exec_preset, math_function, *info);
454 return true;
455 };
456
457 switch (operation) {
459 /* Should be safe. */
460 return dispatch(exec_preset_fast, [](float3 in) { return normalize(in); });
462 return dispatch(exec_preset_fast, [](float3 in) { return floor(in); });
464 return dispatch(exec_preset_fast, [](float3 in) { return ceil(in); });
466 return dispatch(exec_preset_fast, [](float3 in) { return fract(in); });
468 return dispatch(exec_preset_fast, [](float3 in) { return abs(in); });
470 return dispatch(exec_preset_fast, [](float3 in) { return sign(in); });
472 return dispatch(exec_preset_slow,
473 [](float3 in) { return float3(sinf(in.x), sinf(in.y), sinf(in.z)); });
475 return dispatch(exec_preset_slow,
476 [](float3 in) { return float3(cosf(in.x), cosf(in.y), cosf(in.z)); });
478 return dispatch(exec_preset_slow,
479 [](float3 in) { return float3(tanf(in.x), tanf(in.y), tanf(in.z)); });
480 default:
481 return false;
482 }
483 return false;
484}
485
486} // 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_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_SIGN
@ 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_POWER
@ 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_FLOORED_MODULO
@ 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
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
#define expf(x)
#define tanhf(x)
#define sinhf(x)
#define coshf(x)
#define in
T fract(T) RET
VecBase< T, D > refract(VecOp< T, D >, VecOp< T, D >, float) RET
VecBase< T, D > reflect(VecOp< T, D >, VecOp< T, D >) RET
VecBase< float, D > normalize(VecOp< float, D >) RET
constexpr T sign(T) RET
VecBase< T, D > faceforward(VecOp< T, D >, VecOp< T, D >, VecOp< T, D >) RET
#define abs
VecBase< float, D > constexpr mod(VecOp< float, D >, VecOp< float, D >) RET
#define floor
#define ceil
float distance(VecOp< float, D >, VecOp< float, D >) RET
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)
MINLINE float safe_floored_modf(float a, float b)
ccl_device_inline float2 fabs(const float2 a)
VecBase< float, 3 > cross_high_precision(const VecBase< float, 3 > &a, const VecBase< float, 3 > &b)
void node_math_build_multi_function(NodeMultiFunctionBuilder &builder)
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)
VecBase< float, 3 > float3
vector project(vector v, vector v_proj)
Definition node_math.h:91
#define floorf
#define fabsf
#define atanf
#define fmaxf
#define sinf
#define tanf
#define cosf
#define ceilf
#define atan2f
#define min(a, b)
Definition sort.cc:36
FloatMathOperationInfo(StringRefNull title_case_name, StringRefNull shader_name)
max
Definition text_draw.cc:251