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