Cycles/Compositor: Add arctan2 operation to the Math node
authorLukas Stockner <lukas.stockner@freenet.de>
Thu, 24 May 2018 00:51:41 +0000 (02:51 +0200)
committerLukas Stockner <lukas.stockner@freenet.de>
Thu, 24 May 2018 14:46:02 +0000 (16:46 +0200)
The Math node currently has the normal atan() function, but for
actual angles this is fairly useless without additional nodes to handle the signs.

Since the node has two inputs anyways, it only makes sense to add an arctan2 option.

Reviewers: sergey, brecht

Differential Revision: https://developer.blender.org/D3430

13 files changed:
intern/cycles/kernel/kernel_compat_opencl.h
intern/cycles/kernel/shaders/node_math.osl
intern/cycles/kernel/svm/svm_math_util.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/nodes.cpp
source/blender/compositor/nodes/COM_MathNode.cpp
source/blender/compositor/operations/COM_MathBaseOperation.cpp
source/blender/compositor/operations/COM_MathBaseOperation.h
source/blender/gpu/shaders/gpu_shader_material.glsl
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/intern/rna_nodetree.c
source/blender/nodes/shader/nodes/node_shader_math.c
source/blender/nodes/texture/nodes/node_texture_math.c

index 671c47e2225fa2001aa89d2ed0b4c94f3b29acba..ff7b69ab08f012914e44b841ae9ed958c051ea97 100644 (file)
 #define asinf(x) asin(((float)(x)))
 #define acosf(x) acos(((float)(x)))
 #define atanf(x) atan(((float)(x)))
+#define atan2f(x, y) atan2(((float)(x)), ((float)(y)))
 #define floorf(x) floor(((float)(x)))
 #define ceilf(x) ceil(((float)(x)))
 #define hypotf(x, y) hypot(((float)(x)), ((float)(y)))
index f309ef7c6f3e29546d77187e0e0f29ba67e1f982..c5fcbc311d35759f3f6d7b3387d51ed505ada582 100644 (file)
@@ -95,6 +95,8 @@ shader node_math(
                Value = safe_modulo(Value1, Value2);
        else if (type == "absolute")
                Value = fabs(Value1);
+       else if (type == "arctan2")
+               Value = atan2(Value1, Value2);
 
        if (use_clamp)
                Value = clamp(Value, 0.0, 1.0);
index 1ce7777aac3ff99ac0f11dc0b46c3587aaa20ebf..8e6bc73ddc760511f65d0e9ad60881f41cb9c1da 100644 (file)
@@ -92,6 +92,8 @@ ccl_device float svm_math(NodeMath type, float Fac1, float Fac2)
                Fac = safe_modulo(Fac1, Fac2);
        else if(type == NODE_MATH_ABSOLUTE)
                Fac = fabsf(Fac1);
+       else if(type == NODE_MATH_ARCTAN2)
+               Fac = atan2f(Fac1, Fac2);
        else if(type == NODE_MATH_CLAMP)
                Fac = saturate(Fac1);
        else
index 4c3a5975fb87410ba1dc7b1837d2fd1f10657b85..dc62e25b3401254eb746e83cb940c36f5564f0eb 100644 (file)
@@ -259,6 +259,7 @@ typedef enum NodeMath {
        NODE_MATH_GREATER_THAN,
        NODE_MATH_MODULO,
        NODE_MATH_ABSOLUTE,
+       NODE_MATH_ARCTAN2,
        NODE_MATH_CLAMP /* used for the clamp UI option */
 } NodeMath;
 
index 01399c85bc0300be7c3f6596b7eb841cca047916..c468924fa663fa741c6cef6b9cb180886bcd658f 100644 (file)
@@ -4953,6 +4953,7 @@ NODE_DEFINE(MathNode)
        type_enum.insert("greater_than", NODE_MATH_GREATER_THAN);
        type_enum.insert("modulo", NODE_MATH_MODULO);
        type_enum.insert("absolute", NODE_MATH_ABSOLUTE);
+       type_enum.insert("arctan2", NODE_MATH_ARCTAN2);
        SOCKET_ENUM(type, "Type", type_enum, NODE_MATH_ADD);
 
        SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
index eb6bb2caf56205e7f806f9c0926722408cf26581..0fb6933afe78c6db4b9d8a27f2e80f6379bc2b85 100644 (file)
@@ -86,6 +86,9 @@ void MathNode::convertToOperations(NodeConverter &converter, const CompositorCon
                case NODE_MATH_ABS:
                        operation = new MathAbsoluteOperation();
                        break;
+               case NODE_MATH_ATAN2:
+                       operation = new MathArcTan2Operation();
+                       break;
        }
        
        if (operation) {
index 32a1e77b9a741cd0d1116836e43432bbd4077a76..dbc91980acdaa0a668afc2431ed41d6bf74aa538 100644 (file)
@@ -343,3 +343,16 @@ void MathAbsoluteOperation::executePixelSampled(float output[4], float x, float
 
        clampIfNeeded(output);
 }
+
+void MathArcTan2Operation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+{
+       float inputValue1[4];
+       float inputValue2[4];
+
+       this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler);
+       this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler);
+
+       output[0] = atan2(inputValue1[0], inputValue2[0]);
+
+       clampIfNeeded(output);
+}
\ No newline at end of file
index 32cd19f1fb9410d3b384f58965df6d605a21397e..040193727114639a139ed1be556df603a5330d32 100644 (file)
@@ -169,4 +169,10 @@ public:
        void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
 };
 
+class MathArcTan2Operation : public MathBaseOperation {
+public:
+       MathArcTan2Operation() : MathBaseOperation() {}
+       void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+};
+
 #endif
index a0ca719e207d3ba363efb551bb4f7985050fa3f3..aace5e951694b58c7d898f6db40f6092791513d7 100644 (file)
@@ -413,6 +413,11 @@ void math_abs(float val1, out float outval)
        outval = abs(val1);
 }
 
+void math_atan2(float val1, float val2, out float outval)
+{
+       outval = atan(val1, val2);
+}
+
 void squeeze(float val, float width, float center, out float outval)
 {
        outval = 1.0 / (1.0 + pow(2.71828183, -((val - center) * width)));
index 8ae1a79f8f7097e3bf5ccf316b274a850a69e6c8..8d3ab29a2fb7e820e1021944b80351459454dd91 100644 (file)
@@ -1060,6 +1060,7 @@ enum {
        NODE_MATH_GREATER = 16,
        NODE_MATH_MOD     = 17,
        NODE_MATH_ABS     = 18,
+       NODE_MATH_ATAN2   = 19,
 };
 
 /* mix rgb node flags */
index 773ca307a8cc7a9263e901e149a790e771941f09..f5c464c0758b2f86e5416c8de68cee6f5107e10a 100644 (file)
@@ -140,6 +140,7 @@ const EnumPropertyItem rna_enum_node_math_items[] = {
        {NODE_MATH_GREATER, "GREATER_THAN", 0, "Greater Than", ""},
        {NODE_MATH_MOD,     "MODULO",       0, "Modulo",       ""},
        {NODE_MATH_ABS,     "ABSOLUTE",     0, "Absolute",     ""},
+       {NODE_MATH_ATAN2,   "ARCTAN2",      0, "Arctan2",      ""},
        {0, NULL, 0, NULL, NULL}
 };
 
index 2a1e936570d4e5549f70a40548a84a6c54dba7e6..9fa906729dc1865b5e8eed4316742cbbb5b6d85b 100644 (file)
@@ -221,6 +221,11 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
                        r = fabsf(a);
                        break;
                }
+               case NODE_MATH_ATAN2:
+               {
+                       r = atan2(a, b);
+                       break;
+               }
        }
        if (node->custom2 & SHD_MATH_CLAMP) {
                CLAMP(r, 0.0f, 1.0f);
@@ -235,6 +240,7 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(
            "math_divide", "math_sine", "math_cosine", "math_tangent", "math_asin",
            "math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max",
            "math_round", "math_less_than", "math_greater_than", "math_modulo", "math_abs",
+           "math_atan2"
        };
 
        switch (node->custom1) {
@@ -249,6 +255,7 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(
                case NODE_MATH_LESS:
                case NODE_MATH_GREATER:
                case NODE_MATH_MOD:
+               case NODE_MATH_ATAN2:
                        GPU_stack_link(mat, names[node->custom1], in, out);
                        break;
                case NODE_MATH_SIN:
index 19bc16fb82d61bd8ca1c6240b25503f09ae40a1a..d8dc2a62625e26335ba54314dcdb64679bc97838 100644 (file)
@@ -189,6 +189,12 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
                        break;
                }
 
+               case NODE_MATH_ATAN2:
+               {
+                       *out = atan2(in0, in1);
+                       break;
+               }
+
                default:
                {
                        BLI_assert(0);