diff options
Diffstat (limited to 'source/blender/nodes/NOD_math_functions.hh')
-rw-r--r-- | source/blender/nodes/NOD_math_functions.hh | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/source/blender/nodes/NOD_math_functions.hh b/source/blender/nodes/NOD_math_functions.hh index cc750f9595a..c662220fea7 100644 --- a/source/blender/nodes/NOD_math_functions.hh +++ b/source/blender/nodes/NOD_math_functions.hh @@ -18,6 +18,7 @@ #include "DNA_node_types.h" +#include "BLI_float3.hh" #include "BLI_math_base_safe.h" #include "BLI_math_rotation.h" #include "BLI_string_ref.hh" @@ -36,6 +37,7 @@ struct FloatMathOperationInfo { }; const FloatMathOperationInfo *get_float_math_operation_info(const int operation); +const FloatMathOperationInfo *get_float3_math_operation_info(const int operation); const FloatMathOperationInfo *get_float_compare_operation_info(const int operation); /** @@ -231,4 +233,228 @@ inline bool try_dispatch_float_math_fl_fl_to_bool(const FloatCompareOperation op return false; } +/** + * This is similar to try_dispatch_float_math_fl_to_fl, just with a different callback signature. + */ +template<typename Callback> +inline bool try_dispatch_float_math_fl3_fl3_to_fl3(const NodeVectorMathOperation operation, + Callback &&callback) +{ + const FloatMathOperationInfo *info = get_float3_math_operation_info(operation); + if (info == nullptr) { + return false; + } + + /* This is just a utility function to keep the individual cases smaller. */ + auto dispatch = [&](auto math_function) -> bool { + callback(math_function, *info); + return true; + }; + + switch (operation) { + case NODE_VECTOR_MATH_ADD: + return dispatch([](float3 a, float3 b) { return a + b; }); + case NODE_VECTOR_MATH_SUBTRACT: + return dispatch([](float3 a, float3 b) { return a - b; }); + case NODE_VECTOR_MATH_MULTIPLY: + return dispatch([](float3 a, float3 b) { return a * b; }); + case NODE_VECTOR_MATH_DIVIDE: + return dispatch([](float3 a, float3 b) { + return float3(safe_divide(a.x, b.x), safe_divide(a.y, b.y), safe_divide(a.z, b.z)); + }); + case NODE_VECTOR_MATH_CROSS_PRODUCT: + return dispatch([](float3 a, float3 b) { return float3::cross_high_precision(a, b); }); + case NODE_VECTOR_MATH_PROJECT: + return dispatch([](float3 a, float3 b) { + float length_squared = float3::dot(a, b); + return (length_squared != 0.0) ? (float3::dot(a, b) / length_squared) * b : float3(0.0f); + }); + case NODE_VECTOR_MATH_REFLECT: + return dispatch([](float3 a, float3 b) { + b.normalize(); + return a.reflected(b); + }); + case NODE_VECTOR_MATH_SNAP: + return dispatch([](float3 a, float3 b) { + return float3(floor(safe_divide(a.x, b.x)), + floor(safe_divide(a.y, b.y)), + floor(safe_divide(a.z, b.z))) * + b; + }); + case NODE_VECTOR_MATH_MODULO: + return dispatch([](float3 a, float3 b) { + return float3(safe_modf(a.x, b.x), safe_modf(a.y, b.y), safe_modf(a.z, b.z)); + }); + case NODE_VECTOR_MATH_MINIMUM: + return dispatch([](float3 a, float3 b) { + return float3(min_ff(a.x, b.x), min_ff(a.y, b.y), min_ff(a.z, b.z)); + }); + case NODE_VECTOR_MATH_MAXIMUM: + return dispatch([](float3 a, float3 b) { + return float3(max_ff(a.x, b.x), max_ff(a.y, b.y), max_ff(a.z, b.z)); + }); + default: + return false; + } + return false; +} + +/** + * This is similar to try_dispatch_float_math_fl_to_fl, just with a different callback signature. + */ +template<typename Callback> +inline bool try_dispatch_float_math_fl3_fl3_to_fl(const NodeVectorMathOperation operation, + Callback &&callback) +{ + const FloatMathOperationInfo *info = get_float3_math_operation_info(operation); + if (info == nullptr) { + return false; + } + + /* This is just a utility function to keep the individual cases smaller. */ + auto dispatch = [&](auto math_function) -> bool { + callback(math_function, *info); + return true; + }; + + switch (operation) { + case NODE_VECTOR_MATH_DOT_PRODUCT: + return dispatch([](float3 a, float3 b) { return float3::dot(a, b); }); + case NODE_VECTOR_MATH_DISTANCE: + return dispatch([](float3 a, float3 b) { return float3::distance(a, b); }); + default: + return false; + } + return false; +} + +/** + * This is similar to try_dispatch_float_math_fl_to_fl, just with a different callback signature. + */ +template<typename Callback> +inline bool try_dispatch_float_math_fl3_fl3_fl3_to_fl3(const NodeVectorMathOperation operation, + Callback &&callback) +{ + const FloatMathOperationInfo *info = get_float3_math_operation_info(operation); + if (info == nullptr) { + return false; + } + + /* This is just a utility function to keep the individual cases smaller. */ + auto dispatch = [&](auto math_function) -> bool { + callback(math_function, *info); + return true; + }; + + switch (operation) { + case NODE_VECTOR_MATH_WRAP: + return dispatch([](float3 a, float3 b, float3 c) { + return float3(wrapf(a.x, b.x, c.x), wrapf(a.y, b.y, c.y), wrapf(a.z, b.z, c.z)); + }); + default: + return false; + } + return false; +} + +/** + * This is similar to try_dispatch_float_math_fl_to_fl, just with a different callback signature. + */ +template<typename Callback> +inline bool try_dispatch_float_math_fl3_to_fl(const NodeVectorMathOperation operation, + Callback &&callback) +{ + const FloatMathOperationInfo *info = get_float3_math_operation_info(operation); + if (info == nullptr) { + return false; + } + + /* This is just a utility function to keep the individual cases smaller. */ + auto dispatch = [&](auto math_function) -> bool { + callback(math_function, *info); + return true; + }; + + switch (operation) { + case NODE_VECTOR_MATH_LENGTH: + return dispatch([](float3 in) { return in.length(); }); + default: + return false; + } + return false; +} + +/** + * This is similar to try_dispatch_float_math_fl_to_fl, just with a different callback signature. + */ +template<typename Callback> +inline bool try_dispatch_float_math_fl3_fl_to_fl3(const NodeVectorMathOperation operation, + Callback &&callback) +{ + const FloatMathOperationInfo *info = get_float3_math_operation_info(operation); + if (info == nullptr) { + return false; + } + + /* This is just a utility function to keep the individual cases smaller. */ + auto dispatch = [&](auto math_function) -> bool { + callback(math_function, *info); + return true; + }; + + switch (operation) { + case NODE_VECTOR_MATH_SCALE: + return dispatch([](float3 a, float b) { return a * b; }); + default: + return false; + } + return false; +} + +/** + * This is similar to try_dispatch_float_math_fl_to_fl, just with a different callback signature. + */ +template<typename Callback> +inline bool try_dispatch_float_math_fl3_to_fl3(const NodeVectorMathOperation operation, + Callback &&callback) +{ + const FloatMathOperationInfo *info = get_float3_math_operation_info(operation); + if (info == nullptr) { + return false; + } + + /* This is just a utility function to keep the individual cases smaller. */ + auto dispatch = [&](auto math_function) -> bool { + callback(math_function, *info); + return true; + }; + + switch (operation) { + case NODE_VECTOR_MATH_NORMALIZE: + return dispatch([](float3 in) { + float3 out = in; + out.normalize(); + return out; + }); /* Should be safe. */ + case NODE_VECTOR_MATH_FLOOR: + return dispatch([](float3 in) { return float3(floor(in.x), floor(in.y), floor(in.z)); }); + case NODE_VECTOR_MATH_CEIL: + return dispatch([](float3 in) { return float3(ceil(in.x), ceil(in.y), ceil(in.z)); }); + case NODE_VECTOR_MATH_FRACTION: + return dispatch( + [](float3 in) { return in - float3(floor(in.x), floor(in.y), floor(in.z)); }); + case NODE_VECTOR_MATH_ABSOLUTE: + return dispatch([](float3 in) { return float3::abs(in); }); + case NODE_VECTOR_MATH_SINE: + return dispatch([](float3 in) { return float3(sinf(in.x), sinf(in.y), sinf(in.z)); }); + case NODE_VECTOR_MATH_COSINE: + return dispatch([](float3 in) { return float3(cosf(in.x), cosf(in.y), cosf(in.z)); }); + case NODE_VECTOR_MATH_TANGENT: + return dispatch([](float3 in) { return float3(tanf(in.x), tanf(in.y), tanf(in.z)); }); + default: + return false; + } + return false; +} + } // namespace blender::nodes |