RenderEngine/Nodes: system to check for shading nodes compatibility
[blender.git] / source / blender / nodes / shader / nodes / node_shader_math.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/nodes/shader/nodes/node_shader_math.c
29  *  \ingroup shdnodes
30  */
31
32
33 #include "node_shader_util.h"
34
35
36 /* **************** SCALAR MATH ******************** */ 
37 static bNodeSocketTemplate sh_node_math_in[]= { 
38         { SOCK_FLOAT, 1, "Value", 0.5f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f, PROP_NONE}, 
39         { SOCK_FLOAT, 1, "Value", 0.5f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f, PROP_NONE}, 
40         { -1, 0, "" } 
41 };
42
43 static bNodeSocketTemplate sh_node_math_out[]= { 
44         { SOCK_FLOAT, 0, "Value"}, 
45         { -1, 0, "" } 
46 };
47
48 static void node_shader_exec_math(void *UNUSED(data), bNode *node, bNodeStack **in, 
49 bNodeStack **out) 
50 {
51         switch(node->custom1){ 
52         
53         case 0: /* Add */
54                 out[0]->vec[0]= in[0]->vec[0] + in[1]->vec[0]; 
55                 break; 
56         case 1: /* Subtract */
57                 out[0]->vec[0]= in[0]->vec[0] - in[1]->vec[0];
58                 break; 
59         case 2: /* Multiply */
60                 out[0]->vec[0]= in[0]->vec[0] * in[1]->vec[0]; 
61                 break; 
62         case 3: /* Divide */
63                 {
64                         if(in[1]->vec[0]==0)    /* We don't want to divide by zero. */
65                                 out[0]->vec[0]= 0.0;
66                         else
67                                 out[0]->vec[0]= in[0]->vec[0] / in[1]->vec[0];
68                         }
69                 break;
70         case 4: /* Sine */
71                 {
72                         if(in[0]->hasinput || !in[1]->hasinput)  /* This one only takes one input, so we've got to choose. */
73                                 out[0]->vec[0]= sin(in[0]->vec[0]);
74                         else
75                                 out[0]->vec[0]= sin(in[1]->vec[0]);
76                 }
77                 break;
78         case 5: /* Cosine */
79                 {
80                         if(in[0]->hasinput || !in[1]->hasinput)  /* This one only takes one input, so we've got to choose. */   
81                                 out[0]->vec[0]= cos(in[0]->vec[0]);
82                         else
83                                 out[0]->vec[0]= cos(in[1]->vec[0]);
84                 }
85                 break;
86         case 6: /* Tangent */
87                 {
88                         if(in[0]->hasinput || !in[1]->hasinput)  /* This one only takes one input, so we've got to choose. */   
89                                 out[0]->vec[0]= tan(in[0]->vec[0]);
90                         else
91                                 out[0]->vec[0]= tan(in[1]->vec[0]);
92                 }
93                 break;
94         case 7: /* Arc-Sine */
95                 {
96                         if(in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */
97                                 /* Can't do the impossible... */
98                                 if( in[0]->vec[0] <= 1 && in[0]->vec[0] >= -1 )
99                                         out[0]->vec[0]= asin(in[0]->vec[0]);
100                                 else
101                                         out[0]->vec[0]= 0.0;
102                         }
103                         else {
104                                 /* Can't do the impossible... */
105                                 if( in[1]->vec[0] <= 1 && in[1]->vec[0] >= -1 )
106                                         out[0]->vec[0]= asin(in[1]->vec[0]);
107                                 else
108                                         out[0]->vec[0]= 0.0;
109                         }
110                 }
111                 break;
112         case 8: /* Arc-Cosine */
113                 {
114                         if(in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */
115                                 /* Can't do the impossible... */
116                                 if( in[0]->vec[0] <= 1 && in[0]->vec[0] >= -1 )
117                                         out[0]->vec[0]= acos(in[0]->vec[0]);
118                                 else
119                                         out[0]->vec[0]= 0.0;
120                         }
121                         else {
122                                 /* Can't do the impossible... */
123                                 if( in[1]->vec[0] <= 1 && in[1]->vec[0] >= -1 )
124                                         out[0]->vec[0]= acos(in[1]->vec[0]);
125                                 else
126                                         out[0]->vec[0]= 0.0;
127                         }
128                 }
129                 break;
130         case 9: /* Arc-Tangent */
131                 {
132                         if(in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
133                                 out[0]->vec[0]= atan(in[0]->vec[0]);
134                         else
135                                 out[0]->vec[0]= atan(in[1]->vec[0]);
136                 }
137                 break;
138         case 10: /* Power */
139                 {
140                         /* Don't want any imaginary numbers... */
141                         if( in[0]->vec[0] >= 0 )
142                                 out[0]->vec[0]= pow(in[0]->vec[0], in[1]->vec[0]);
143                         else
144                                 out[0]->vec[0]= 0.0;
145                 }
146                 break;
147         case 11: /* Logarithm */
148                 {
149                         /* Don't want any imaginary numbers... */
150                         if( in[0]->vec[0] > 0  && in[1]->vec[0] > 0 )
151                                 out[0]->vec[0]= log(in[0]->vec[0]) / log(in[1]->vec[0]);
152                         else
153                                 out[0]->vec[0]= 0.0;
154                 }
155                 break;
156         case 12: /* Minimum */
157                 {
158                         if( in[0]->vec[0] < in[1]->vec[0] )
159                                 out[0]->vec[0]= in[0]->vec[0];
160                         else
161                                 out[0]->vec[0]= in[1]->vec[0];
162                 }
163                 break;
164         case 13: /* Maximum */
165                 {
166                         if( in[0]->vec[0] > in[1]->vec[0] )
167                                 out[0]->vec[0]= in[0]->vec[0];
168                         else
169                                 out[0]->vec[0]= in[1]->vec[0];
170                 }
171                 break;
172         case 14: /* Round */
173                 {
174                         if(in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
175                                 out[0]->vec[0]= (in[0]->vec[0]<0)?(int)(in[0]->vec[0] - 0.5f):(int)(in[0]->vec[0] + 0.5f);
176                         else
177                                 out[0]->vec[0]= (in[1]->vec[0]<0)?(int)(in[1]->vec[0] - 0.5f):(int)(in[1]->vec[0] + 0.5f);
178                 }
179                 break;
180         case 15: /* Less Than */
181                 {
182                         if( in[0]->vec[0] < in[1]->vec[0] )
183                                 out[0]->vec[0]= 1.0f;
184                         else
185                                 out[0]->vec[0]= 0.0f;
186                 }
187                 break;
188         case 16: /* Greater Than */
189                 {
190                         if( in[0]->vec[0] > in[1]->vec[0] )
191                                 out[0]->vec[0]= 1.0f;
192                         else
193                                 out[0]->vec[0]= 0.0f;
194                 }
195                 break;
196         } 
197 }
198
199 static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
200 {
201         static const char *names[] = {"math_add", "math_subtract", "math_multiply",
202                 "math_divide", "math_sine", "math_cosine", "math_tangent", "math_asin",
203                 "math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max",
204                 "math_round", "math_less_than", "math_greater_than"};
205
206         switch (node->custom1) {
207                 case 0:
208                 case 1:
209                 case 2:
210                 case 3:
211                 case 10:
212                 case 11:
213                 case 12:
214                 case 13:
215                 case 15:
216                 case 16:
217                         GPU_stack_link(mat, names[node->custom1], NULL, out,
218                                 GPU_socket(&in[0]), GPU_socket(&in[1]));
219                         break;
220                 case 4:
221                 case 5:
222                 case 6:
223                 case 7:
224                 case 8:
225                 case 9:
226                 case 14:
227                         if(in[0].hasinput || !in[1].hasinput)
228                                 GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[0]));
229                         else
230                                 GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[1]));
231                         break;
232                 default:
233                         return 0;
234         }
235         
236         return 1;
237 }
238
239 void register_node_type_sh_math(ListBase *lb)
240 {
241         static bNodeType ntype;
242
243         node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
244         node_type_compatibility(&ntype, NODE_OLD_SHADING);
245         node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out);
246         node_type_size(&ntype, 120, 110, 160);
247         node_type_label(&ntype, node_math_label);
248         node_type_storage(&ntype, "node_math", NULL, NULL);
249         node_type_exec(&ntype, node_shader_exec_math);
250         node_type_gpu(&ntype, gpu_shader_math);
251
252         nodeRegisterType(lb, &ntype);
253 }
254
255