Blender V4.3
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
16namespace blender::nodes {
17
28
29const FloatMathOperationInfo *get_float_math_operation_info(int operation);
30const FloatMathOperationInfo *get_float3_math_operation_info(int operation);
31const FloatMathOperationInfo *get_float_compare_operation_info(int operation);
32
48template<typename Callback>
49inline bool try_dispatch_float_math_fl_to_fl(const int operation, Callback &&callback)
50{
52 if (info == nullptr) {
53 return false;
54 }
55
56 static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
57 static auto exec_preset_slow = mf::build::exec_presets::Materialized();
58
59 /* This is just an utility function to keep the individual cases smaller. */
60 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
61 callback(exec_preset, math_function, *info);
62 return true;
63 };
64
65 switch (operation) {
67 return dispatch(exec_preset_slow, [](float a) { return expf(a); });
68 case NODE_MATH_SQRT:
69 return dispatch(exec_preset_fast, [](float a) { return safe_sqrtf(a); });
71 return dispatch(exec_preset_fast, [](float a) { return safe_inverse_sqrtf(a); });
73 return dispatch(exec_preset_fast, [](float a) { return fabs(a); });
75 return dispatch(exec_preset_fast, [](float a) { return (float)DEG2RAD(a); });
77 return dispatch(exec_preset_fast, [](float a) { return (float)RAD2DEG(a); });
78 case NODE_MATH_SIGN:
79 return dispatch(exec_preset_fast, [](float a) { return compatible_signf(a); });
80 case NODE_MATH_ROUND:
81 return dispatch(exec_preset_fast, [](float a) { return floorf(a + 0.5f); });
82 case NODE_MATH_FLOOR:
83 return dispatch(exec_preset_fast, [](float a) { return floorf(a); });
84 case NODE_MATH_CEIL:
85 return dispatch(exec_preset_fast, [](float a) { return ceilf(a); });
87 return dispatch(exec_preset_fast, [](float a) { return a - floorf(a); });
88 case NODE_MATH_TRUNC:
89 return dispatch(exec_preset_fast, [](float a) { return a >= 0.0f ? floorf(a) : ceilf(a); });
90 case NODE_MATH_SINE:
91 return dispatch(exec_preset_slow, [](float a) { return sinf(a); });
93 return dispatch(exec_preset_slow, [](float a) { return cosf(a); });
95 return dispatch(exec_preset_slow, [](float a) { return tanf(a); });
96 case NODE_MATH_SINH:
97 return dispatch(exec_preset_slow, [](float a) { return sinhf(a); });
98 case NODE_MATH_COSH:
99 return dispatch(exec_preset_slow, [](float a) { return coshf(a); });
100 case NODE_MATH_TANH:
101 return dispatch(exec_preset_slow, [](float a) { return tanhf(a); });
103 return dispatch(exec_preset_slow, [](float a) { return safe_asinf(a); });
105 return dispatch(exec_preset_slow, [](float a) { return safe_acosf(a); });
107 return dispatch(exec_preset_slow, [](float a) { return atanf(a); });
108 }
109 return false;
110}
111
115template<typename Callback>
116inline bool try_dispatch_float_math_fl_fl_to_fl(const int operation, Callback &&callback)
117{
119 if (info == nullptr) {
120 return false;
121 }
122
123 static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
124 static auto exec_preset_slow = mf::build::exec_presets::Materialized();
125
126 /* This is just an utility function to keep the individual cases smaller. */
127 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
128 callback(exec_preset, math_function, *info);
129 return true;
130 };
131
132 switch (operation) {
133 case NODE_MATH_ADD:
134 return dispatch(exec_preset_fast, [](float a, float b) { return a + b; });
136 return dispatch(exec_preset_fast, [](float a, float b) { return a - b; });
138 return dispatch(exec_preset_fast, [](float a, float b) { return a * b; });
139 case NODE_MATH_DIVIDE:
140 return dispatch(exec_preset_fast, [](float a, float b) { return safe_divide(a, b); });
141 case NODE_MATH_POWER:
142 return dispatch(exec_preset_slow, [](float a, float b) { return safe_powf(a, b); });
144 return dispatch(exec_preset_slow, [](float a, float b) { return safe_logf(a, b); });
146 return dispatch(exec_preset_fast, [](float a, float b) { return std::min(a, b); });
148 return dispatch(exec_preset_fast, [](float a, float b) { return std::max(a, b); });
150 return dispatch(exec_preset_fast, [](float a, float b) { return (float)(a < b); });
152 return dispatch(exec_preset_fast, [](float a, float b) { return (float)(a > b); });
153 case NODE_MATH_MODULO:
154 return dispatch(exec_preset_fast, [](float a, float b) { return safe_modf(a, b); });
156 return dispatch(exec_preset_fast, [](float a, float b) { return safe_floored_modf(a, b); });
157 case NODE_MATH_SNAP:
158 return dispatch(exec_preset_fast,
159 [](float a, float b) { return floorf(safe_divide(a, b)) * b; });
161 return dispatch(exec_preset_slow, [](float a, float b) { return atan2f(a, b); });
163 return dispatch(exec_preset_fast, [](float a, float b) { return pingpongf(a, b); });
164 }
165 return false;
166}
167
171template<typename Callback>
172inline bool try_dispatch_float_math_fl_fl_fl_to_fl(const int operation, Callback &&callback)
173{
175 if (info == nullptr) {
176 return false;
177 }
178
179 /* This is just an utility function to keep the individual cases smaller. */
180 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
181 callback(exec_preset, math_function, *info);
182 return true;
183 };
184
185 switch (operation) {
187 return dispatch(mf::build::exec_presets::AllSpanOrSingle(),
188 [](float a, float b, float c) { return a * b + c; });
190 return dispatch(mf::build::exec_presets::SomeSpanOrSingle<0, 1>(),
191 [](float a, float b, float c) -> float {
192 return ((a == b) || (fabsf(a - b) <= fmaxf(c, FLT_EPSILON))) ? 1.0f : 0.0f;
193 });
195 return dispatch(mf::build::exec_presets::SomeSpanOrSingle<0, 1>(),
196 [](float a, float b, float c) { return smoothminf(a, b, c); });
198 return dispatch(mf::build::exec_presets::SomeSpanOrSingle<0, 1>(),
199 [](float a, float b, float c) { return -smoothminf(-a, -b, c); });
200 case NODE_MATH_WRAP:
201 return dispatch(mf::build::exec_presets::SomeSpanOrSingle<0>(),
202 [](float a, float b, float c) { return wrapf(a, b, c); });
203 }
204 return false;
205}
206
210template<typename Callback>
212 Callback &&callback)
213{
214 using namespace blender::math;
215
217 if (info == nullptr) {
218 return false;
219 }
220
221 static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
222 static auto exec_preset_slow = mf::build::exec_presets::Materialized();
223
224 /* This is just a utility function to keep the individual cases smaller. */
225 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
226 callback(exec_preset, math_function, *info);
227 return true;
228 };
229
230 switch (operation) {
232 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return a + b; });
234 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return a - b; });
236 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return a * b; });
238 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return safe_divide(a, b); });
240 return dispatch(exec_preset_fast,
241 [](float3 a, float3 b) { return cross_high_precision(a, b); });
243 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return project(a, b); });
245 return dispatch(exec_preset_fast,
246 [](float3 a, float3 b) { return reflect(a, normalize(b)); });
248 return dispatch(exec_preset_fast,
249 [](float3 a, float3 b) { return floor(safe_divide(a, b)) * b; });
251 return dispatch(exec_preset_slow, [](float3 a, float3 b) { return mod(a, b); });
253 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return min(a, b); });
255 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return max(a, b); });
256 default:
257 return false;
258 }
259 return false;
260}
261
265template<typename Callback>
267 Callback &&callback)
268{
269 using namespace blender::math;
270
272 if (info == nullptr) {
273 return false;
274 }
275
276 static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
277
278 /* This is just a utility function to keep the individual cases smaller. */
279 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
280 callback(exec_preset, math_function, *info);
281 return true;
282 };
283
284 switch (operation) {
286 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return dot(a, b); });
288 return dispatch(exec_preset_fast, [](float3 a, float3 b) { return distance(a, b); });
289 default:
290 return false;
291 }
292 return false;
293}
294
298template<typename Callback>
300 Callback &&callback)
301{
302 using namespace blender::math;
303
305 if (info == nullptr) {
306 return false;
307 }
308
309 static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
310 static auto exec_preset_slow = mf::build::exec_presets::Materialized();
311
312 /* This is just a utility function to keep the individual cases smaller. */
313 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
314 callback(exec_preset, math_function, *info);
315 return true;
316 };
317
318 switch (operation) {
320 return dispatch(exec_preset_fast, [](float3 a, float3 b, float3 c) { return a * b + c; });
322 return dispatch(exec_preset_slow, [](float3 a, float3 b, float3 c) {
323 return float3(wrapf(a.x, b.x, c.x), wrapf(a.y, b.y, c.y), wrapf(a.z, b.z, c.z));
324 });
326 return dispatch(exec_preset_fast,
327 [](float3 a, float3 b, float3 c) { return faceforward(a, b, c); });
328 default:
329 return false;
330 }
331 return false;
332}
333
337template<typename Callback>
339 Callback &&callback)
340{
341 using namespace blender::math;
342
344 if (info == nullptr) {
345 return false;
346 }
347
348 static auto exec_preset_slow = mf::build::exec_presets::Materialized();
349
350 /* This is just a utility function to keep the individual cases smaller. */
351 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
352 callback(exec_preset, math_function, *info);
353 return true;
354 };
355
356 switch (operation) {
358 return dispatch(exec_preset_slow,
359 [](float3 a, float3 b, float c) { return refract(a, normalize(b), c); });
360 default:
361 return false;
362 }
363 return false;
364}
365
369template<typename Callback>
371 Callback &&callback)
372{
373 using namespace blender::math;
374
376 if (info == nullptr) {
377 return false;
378 }
379
380 static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
381
382 /* This is just a utility function to keep the individual cases smaller. */
383 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
384 callback(exec_preset, math_function, *info);
385 return true;
386 };
387
388 switch (operation) {
390 return dispatch(exec_preset_fast, [](float3 in) { return length(in); });
391 default:
392 return false;
393 }
394 return false;
395}
396
400template<typename Callback>
402 Callback &&callback)
403{
405 if (info == nullptr) {
406 return false;
407 }
408
409 static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
410
411 /* This is just a utility function to keep the individual cases smaller. */
412 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
413 callback(exec_preset, math_function, *info);
414 return true;
415 };
416
417 switch (operation) {
419 return dispatch(exec_preset_fast, [](float3 a, float b) { return a * b; });
420 default:
421 return false;
422 }
423 return false;
424}
425
429template<typename Callback>
431 Callback &&callback)
432{
433 using namespace blender::math;
434
436 if (info == nullptr) {
437 return false;
438 }
439
440 static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
441 static auto exec_preset_slow = mf::build::exec_presets::Materialized();
442
443 /* This is just a utility function to keep the individual cases smaller. */
444 auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
445 callback(exec_preset, math_function, *info);
446 return true;
447 };
448
449 switch (operation) {
451 /* Should be safe. */
452 return dispatch(exec_preset_fast, [](float3 in) { return normalize(in); });
454 return dispatch(exec_preset_fast, [](float3 in) { return floor(in); });
456 return dispatch(exec_preset_fast, [](float3 in) { return ceil(in); });
458 return dispatch(exec_preset_fast, [](float3 in) { return fract(in); });
460 return dispatch(exec_preset_fast, [](float3 in) { return abs(in); });
462 return dispatch(exec_preset_slow,
463 [](float3 in) { return float3(sinf(in.x), sinf(in.y), sinf(in.z)); });
465 return dispatch(exec_preset_slow,
466 [](float3 in) { return float3(cosf(in.x), cosf(in.y), cosf(in.z)); });
468 return dispatch(exec_preset_slow,
469 [](float3 in) { return float3(tanf(in.x), tanf(in.y), tanf(in.z)); });
470 default:
471 return false;
472 }
473 return false;
474}
475
476} // 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_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_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 btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
local_group_size(16, 16) .push_constant(Type b
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)
MINLINE float safe_floored_modf(float a, float b)
ccl_device_inline float2 floor(const float2 a)
ccl_device_inline float2 fabs(const float2 a)
ccl_device_inline float3 reflect(const float3 incident, const float3 unit_normal)
ccl_device_inline float3 refract(const float3 incident, const float3 normal, const float eta)
ccl_device_inline float3 faceforward(const float3 vector, const float3 incident, const float3 reference)
ccl_device_inline float3 ceil(const float3 a)
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
float fract(float a)
Definition node_math.h:27
vector project(vector v, vector v_proj)
Definition node_math.h:59
float distance(float a, float b)
#define min(a, b)
Definition sort.c:32
FloatMathOperationInfo(StringRefNull title_case_name, StringRefNull shader_name)
float max
ccl_device_inline int abs(int x)
Definition util/math.h:120
ccl_device_inline int mod(int x, int m)
Definition util/math.h:520