Math Node:
authorThomas Dinges <blender@dingto.org>
Mon, 20 May 2013 14:38:47 +0000 (14:38 +0000)
committerThomas Dinges <blender@dingto.org>
Mon, 20 May 2013 14:38:47 +0000 (14:38 +0000)
* Added a Modulo operation to the math node, available in Compositor, Shader and Texture Nodes.

12 files changed:
intern/cycles/kernel/shaders/node_math.osl
intern/cycles/kernel/svm/svm_math.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/nodes.cpp
intern/cycles/util/util_math.h
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/makesrna/intern/rna_nodetree.c
source/blender/nodes/shader/nodes/node_shader_math.c
source/blender/nodes/texture/nodes/node_texture_math.c

index 2ec1a5f0a32365bc952b57ba28326fc62f23f006..214ef931660493d07ac50302352e38c1d94475a9 100644 (file)
@@ -30,6 +30,18 @@ float safe_divide(float a, float b)
        return result;
 }
 
+float safe_modulo(float a, float b)
+{
+       float result;
+
+       if (b == 0.0)
+               result = 0.0;
+       else
+               result = fmod(a, b);
+       
+       return result;
+}
+
 float safe_log(float a, float b)
 {
        if (a < 0.0 || b < 0.0)
@@ -81,6 +93,8 @@ shader node_math(
                Value = Value1 < Value2;
        else if (type == "Greater Than")
                Value = Value1 > Value2;
+       else if (type == "Modulo")
+               Value = safe_modulo(Value1, Value2);
 
        if (Clamp)
                Value = clamp(Value1, 0.0, 1.0);
index c7cd5200cd06b4de38710cc3bb8dc2b39e0abede..dbf477a0a969c94648d4918188347e75103f5921 100644 (file)
@@ -56,6 +56,8 @@ __device float svm_math(NodeMath type, float Fac1, float Fac2)
                Fac = Fac1 < Fac2;
        else if(type == NODE_MATH_GREATER_THAN)
                Fac = Fac1 > Fac2;
+       else if(type == NODE_MATH_MODULO)
+               Fac = safe_modulo(Fac1, Fac2);
        else if(type == NODE_MATH_CLAMP)
                Fac = clamp(Fac1, 0.0f, 1.0f);
        else
index d89fde898dc75abd7dcab55576197dc7241cb295..2cf3ccbe575e8f112ad1c33c3fdd1f30d545da95 100644 (file)
@@ -210,6 +210,7 @@ typedef enum NodeMath {
        NODE_MATH_ROUND,
        NODE_MATH_LESS_THAN,
        NODE_MATH_GREATER_THAN,
+       NODE_MATH_MODULO,
        NODE_MATH_CLAMP /* used for the clamp UI option */
 } NodeMath;
 
index 7435616ffc0844d4bde58a403b2e49c91be4544e..06322fec820e7e58cb83e0bceede13b778be7280 100644 (file)
@@ -2959,6 +2959,7 @@ static ShaderEnum math_type_init()
        enm.insert("Round", NODE_MATH_ROUND);
        enm.insert("Less Than", NODE_MATH_LESS_THAN);
        enm.insert("Greater Than", NODE_MATH_GREATER_THAN);
+       enm.insert("Modulo", NODE_MATH_MODULO);
 
        return enm;
 }
index 6edf7fa354496ac4cf76248cd19a62fa9f209739..6fe1b2bcf54d6f337c36184c57d65bc444343675 100644 (file)
@@ -1166,6 +1166,11 @@ __device float safe_divide(float a, float b)
        return (b != 0.0f)? a/b: 0.0f;
 }
 
+__device float safe_modulo(float a, float b)
+{
+       return (b != 0.0f)? fmodf(a, b): 0.0f;
+}
+
 /* Ray Intersection */
 
 __device bool ray_sphere_intersect(
index 307590b977b4b33e53f7295b48cf966b957ba28f..23e9a9d623dd291f2ff4572a9446eee50c96a13b 100644 (file)
@@ -80,6 +80,9 @@ void MathNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co
                case 16: /* Greater Than */
                        operation = new MathGreaterThanOperation();
                        break;
+               case 17: /* Modulo */
+                       operation = new MathModuloOperation();
+                       break;
        }
        
        if (operation != NULL) {
index 7039689aa5fa6ecaa63ec7079f96156367e7ace5..3749bcf42d8dabbafa7f5e5464efef7bc3299f0c 100644 (file)
@@ -317,4 +317,19 @@ void MathGreaterThanOperation::executePixel(float output[4], float x, float y, P
        clampIfNeeded(output);
 }
 
+void MathModuloOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+       float inputValue1[4];
+       float inputValue2[4];
+       
+       this->m_inputValue1Operation->read(&inputValue1[0], x, y, sampler);
+       this->m_inputValue2Operation->read(&inputValue2[0], x, y, sampler);
+       
+       if (inputValue2[0] == 0)
+               output[0] = 0.0;
+       else
+               output[0] = fmod(inputValue1[0], inputValue2[0]);
+
+       clampIfNeeded(output);
+}
 
index febfa9662c6b60deec1f41b64d584280c31fd0cb..649a9688037fa2326a05cb2f830ac5c936518682 100644 (file)
@@ -157,4 +157,10 @@ public:
        void executePixel(float output[4], float x, float y, PixelSampler sampler);
 };
 
+class MathModuloOperation : public MathBaseOperation {
+public:
+       MathModuloOperation() : MathBaseOperation() {}
+       void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
 #endif
index fd519a86fc9f7f34251973e3c270374efc9eda21..3a68b79d1543a5580462cdb62507fbc03456cffa 100644 (file)
@@ -279,6 +279,14 @@ void math_greater_than(float val1, float val2, out float outval)
                outval = 0.0;
 }
 
+void math_modulo(float val1, float val2, out float outval)
+{
+       if (val2 == 0.0)
+               outval = 0.0;
+       else
+               outval = mod(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 6238e3f7d3d0b2562986a8b2f988d8329f671f9d..a40d85ae954db4bff91d30bac5df1e811316f59c 100644 (file)
@@ -127,6 +127,7 @@ EnumPropertyItem node_math_items[] = {
        {14, "ROUND",        0, "Round",        ""},
        {15, "LESS_THAN",    0, "Less Than",    ""},
        {16, "GREATER_THAN", 0, "Greater Than", ""},
+       {17, "MODULO",           0, "Modulo",           ""},            
        {0, NULL, 0, NULL, NULL}
 };
 
index c3e2fc54c78ce7faa5b0be675ba7c908ac2e37ed..bef777e5d59004943246e2bb5001ba630278e2fb 100644 (file)
@@ -203,6 +203,14 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
                                out[0]->vec[0] = 0.0f;
                }
                break;
+       case 17: /* Modulo */
+               {
+                       if (in[1]->vec[0] == 0.0f)
+                               out[0]->vec[0] = 0.0f;
+                       else
+                               out[0]->vec[0] = fmod(in[0]->vec[0], in[1]->vec[0]);
+               }
+               break;
        }
 }
 
@@ -211,7 +219,7 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(
        static const char *names[] = {"math_add", "math_subtract", "math_multiply",
                "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_round", "math_less_than", "math_greater_than", "math_modulo"};
 
        switch (node->custom1) {
                case 0:
index 03349a5783258c863bcea00af2b22bde4006b2c9..1e4564161592cfcacbac9c46e7a8a7576a91ce54 100644 (file)
@@ -174,6 +174,15 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
                }
                break;
                
+       case 17: /* Modulo */
+               {
+                       if (in1 == 0.0f)
+                               *out = 0.0f;
+                       else
+                               *out= fmod(in0, in1);
+               }
+               break;
+               
        default:
                fprintf(stderr,
                        "%s:%d: unhandeld value in switch statement: %d\n",