Cleanup: style
[blender-staging.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, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
39         { SOCK_FLOAT, 1, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
40         { -1, 0, "" }
41 };
42
43 static bNodeSocketTemplate sh_node_math_out[] = {
44         { SOCK_FLOAT, 0, N_("Value")},
45         { -1, 0, "" }
46 };
47
48 static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) 
49 {
50         float a, b, r = 0.0f;
51         
52         nodestack_get_vec(&a, SOCK_FLOAT, in[0]);
53         nodestack_get_vec(&b, SOCK_FLOAT, in[1]);
54         
55         switch (node->custom1) {
56         
57                 case NODE_MATH_ADD:
58                         r = a + b;
59                         break;
60                 case NODE_MATH_SUB:
61                         r = a - b;
62                         break;
63                 case NODE_MATH_MUL:
64                         r = a * b;
65                         break;
66                 case NODE_MATH_DIVIDE:
67                 {
68                         if (b == 0) /* We don't want to divide by zero. */
69                                 r = 0.0;
70                         else
71                                 r = a / b;
72                         break;
73                 }
74                 case NODE_MATH_SIN:
75                 {
76                         if (in[0]->hasinput || !in[1]->hasinput)  /* This one only takes one input, so we've got to choose. */
77                                 r = sinf(a);
78                         else
79                                 r = sinf(b);
80                         break;
81                 }
82                 case NODE_MATH_COS:
83                 {
84                         if (in[0]->hasinput || !in[1]->hasinput)  /* This one only takes one input, so we've got to choose. */
85                                 r = cosf(a);
86                         else
87                                 r = cosf(b);
88                         break;
89                 }
90                 case NODE_MATH_TAN:
91                 {
92                         if (in[0]->hasinput || !in[1]->hasinput)  /* This one only takes one input, so we've got to choose. */
93                                 r = tanf(a);
94                         else
95                                 r = tanf(b);
96                         break;
97                 }
98                 case NODE_MATH_ASIN:
99                 {
100                         if (in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */
101                                 /* Can't do the impossible... */
102                                 if (a <= 1 && a >= -1)
103                                         r = asinf(a);
104                                 else
105                                         r = 0.0;
106                         }
107                         else {
108                                 /* Can't do the impossible... */
109                                 if (b <= 1 && b >= -1)
110                                         r = asinf(b);
111                                 else
112                                         r = 0.0;
113                         }
114                         break;
115                 }
116                 case NODE_MATH_ACOS:
117                 {
118                         if (in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */
119                                 /* Can't do the impossible... */
120                                 if (a <= 1 && a >= -1)
121                                         r = acosf(a);
122                                 else
123                                         r = 0.0;
124                         }
125                         else {
126                                 /* Can't do the impossible... */
127                                 if (b <= 1 && b >= -1)
128                                         r = acosf(b);
129                                 else
130                                         r = 0.0;
131                         }
132                         break;
133                 }
134                 case NODE_MATH_ATAN:
135                 {
136                         if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
137                                 r = atan(a);
138                         else
139                                 r = atan(b);
140                         break;
141                 }
142                 case NODE_MATH_POW:
143                 {
144                         /* Only raise negative numbers by full integers */
145                         if (a >= 0) {
146                                 r = pow(a, b);
147                         }
148                         else {
149                                 float y_mod_1 = fabsf(fmodf(b, 1.0f));
150                                 
151                                 /* if input value is not nearly an integer, fall back to zero, nicer than straight rounding */
152                                 if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) {
153                                         r = powf(a, floorf(b + 0.5f));
154                                 }
155                                 else {
156                                         r = 0.0f;
157                                 }
158                         }
159
160                         break;
161                 }
162                 case NODE_MATH_LOG:
163                 {
164                         /* Don't want any imaginary numbers... */
165                         if (a > 0  && b > 0)
166                                 r = log(a) / log(b);
167                         else
168                                 r = 0.0;
169                         break;
170                 }
171                 case NODE_MATH_MIN:
172                 {
173                         if (a < b)
174                                 r = a;
175                         else
176                                 r = b;
177                         break;
178                 }
179                 case NODE_MATH_MAX:
180                 {
181                         if (a > b)
182                                 r = a;
183                         else
184                                 r = b;
185                         break;
186                 }
187                 case NODE_MATH_ROUND:
188                 {
189                         if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
190                                 r = (a < 0) ? (int)(a - 0.5f) : (int)(a + 0.5f);
191                         else
192                                 r = (b < 0) ? (int)(b - 0.5f) : (int)(b + 0.5f);
193                         break;
194                 }
195                 case NODE_MATH_LESS:
196                 {
197                         if (a < b)
198                                 r = 1.0f;
199                         else
200                                 r = 0.0f;
201                         break;
202                 }
203                 case NODE_MATH_GREATER:
204                 {
205                         if (a > b)
206                                 r = 1.0f;
207                         else
208                                 r = 0.0f;
209                         break;
210                 }
211                 case NODE_MATH_MOD:
212                 {
213                         if (b == 0.0f)
214                                 r = 0.0f;
215                         else
216                                 r = fmod(a, b);
217                         break;
218                 }
219                 case NODE_MATH_ABS:
220                 {
221                         r = fabsf(a);
222                         break;
223                 }
224         }
225         if (node->custom2 & SHD_MATH_CLAMP) {
226                 CLAMP(r, 0.0f, 1.0f);
227         }
228         out[0]->vec[0] = r;
229 }
230
231 static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
232 {
233         static const char *names[] = {
234             "math_add", "math_subtract", "math_multiply",
235             "math_divide", "math_sine", "math_cosine", "math_tangent", "math_asin",
236             "math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max",
237             "math_round", "math_less_than", "math_greater_than", "math_modulo", "math_abs",
238         };
239
240         switch (node->custom1) {
241                 case NODE_MATH_ADD:
242                 case NODE_MATH_SUB:
243                 case NODE_MATH_MUL:
244                 case NODE_MATH_DIVIDE:
245                 case NODE_MATH_POW:
246                 case NODE_MATH_LOG:
247                 case NODE_MATH_MIN:
248                 case NODE_MATH_MAX:
249                 case NODE_MATH_LESS:
250                 case NODE_MATH_GREATER:
251                 case NODE_MATH_MOD:
252                         GPU_stack_link(mat, names[node->custom1], in, out);
253                         break;
254                 case NODE_MATH_SIN:
255                 case NODE_MATH_COS:
256                 case NODE_MATH_TAN:
257                 case NODE_MATH_ASIN:
258                 case NODE_MATH_ACOS:
259                 case NODE_MATH_ATAN:
260                 case NODE_MATH_ROUND:
261                 case NODE_MATH_ABS:
262                         if (in[0].hasinput || !in[1].hasinput) {
263                                 /* use only first item and terminator */
264                                 GPUNodeStack tmp_in[2];
265                                 memcpy(&tmp_in[0], &in[0], sizeof(GPUNodeStack));
266                                 memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack));
267                                 GPU_stack_link(mat, names[node->custom1], tmp_in, out);
268                         }
269                         else {
270                                 /* use only second item and terminator */
271                                 GPUNodeStack tmp_in[2];
272                                 memcpy(&tmp_in[0], &in[1], sizeof(GPUNodeStack));
273                                 memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack));
274                                 GPU_stack_link(mat, names[node->custom1], tmp_in, out);
275                         }
276                         break;
277                 default:
278                         return 0;
279         }
280
281         if (node->custom2 & SHD_MATH_CLAMP) {
282                 float min[3] = {0.0f, 0.0f, 0.0f};
283                 float max[3] = {1.0f, 1.0f, 1.0f};
284                 GPU_link(mat, "clamp_val", out[0].link, GPU_uniform(min), GPU_uniform(max), &out[0].link);
285         }
286
287         return 1;
288 }
289
290 void register_node_type_sh_math(void)
291 {
292         static bNodeType ntype;
293
294         sh_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0);
295         node_type_compatibility(&ntype, NODE_OLD_SHADING | NODE_NEW_SHADING);
296         node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out);
297         node_type_label(&ntype, node_math_label);
298         node_type_storage(&ntype, "", NULL, NULL);
299         node_type_exec(&ntype, NULL, NULL, node_shader_exec_math);
300         node_type_gpu(&ntype, gpu_shader_math);
301
302         nodeRegisterType(&ntype);
303 }