Merging r58475 through r58700 from trunk into soc-2013-depsgraph_mt
[blender.git] / source / blender / compositor / operations / COM_MathBaseOperation.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
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  * Contributor: 
19  *              Jeroen Bakker 
20  *              Monique Dewanchand
21  */
22
23 #include "COM_MathBaseOperation.h"
24 extern "C" {
25 #include "BLI_math.h"
26 }
27
28 MathBaseOperation::MathBaseOperation() : NodeOperation()
29 {
30         this->addInputSocket(COM_DT_VALUE);
31         this->addInputSocket(COM_DT_VALUE);
32         this->addOutputSocket(COM_DT_VALUE);
33         this->m_inputValue1Operation = NULL;
34         this->m_inputValue2Operation = NULL;
35         this->m_useClamp = false;
36 }
37
38 void MathBaseOperation::initExecution()
39 {
40         this->m_inputValue1Operation = this->getInputSocketReader(0);
41         this->m_inputValue2Operation = this->getInputSocketReader(1);
42 }
43
44
45 void MathBaseOperation::deinitExecution()
46 {
47         this->m_inputValue1Operation = NULL;
48         this->m_inputValue2Operation = NULL;
49 }
50
51 void MathBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
52 {
53         InputSocket *socket;
54         unsigned int tempPreferredResolution[2] = {0, 0};
55         unsigned int tempResolution[2];
56
57         socket = this->getInputSocket(0);
58         socket->determineResolution(tempResolution, tempPreferredResolution);
59         if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) {
60                 this->setResolutionInputSocketIndex(0);
61         }
62         else {
63                 this->setResolutionInputSocketIndex(1);
64         }
65         NodeOperation::determineResolution(resolution, preferredResolution);
66 }
67
68 void MathBaseOperation::clampIfNeeded(float *color)
69 {
70         if (this->m_useClamp) {
71                 CLAMP(color[0], 0.0f, 1.0f);
72         }
73 }
74
75 void MathAddOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
76 {
77         float inputValue1[4];
78         float inputValue2[4];
79         
80         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
81         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
82         
83         output[0] = inputValue1[0] + inputValue2[0];
84
85         clampIfNeeded(output);
86 }
87
88 void MathSubtractOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
89 {
90         float inputValue1[4];
91         float inputValue2[4];
92         
93         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
94         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
95         
96         output[0] = inputValue1[0] - inputValue2[0];
97
98         clampIfNeeded(output);
99 }
100
101 void MathMultiplyOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
102 {
103         float inputValue1[4];
104         float inputValue2[4];
105         
106         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
107         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
108         
109         output[0] = inputValue1[0] * inputValue2[0];
110
111         clampIfNeeded(output);
112 }
113
114 void MathDivideOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
115 {
116         float inputValue1[4];
117         float inputValue2[4];
118         
119         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
120         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
121         
122         if (inputValue2[0] == 0) /* We don't want to divide by zero. */
123                 output[0] = 0.0;
124         else
125                 output[0] = inputValue1[0] / inputValue2[0];
126
127         clampIfNeeded(output);
128 }
129
130 void MathSineOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
131 {
132         float inputValue1[4];
133         float inputValue2[4];
134         
135         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
136         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
137         
138         output[0] = sin(inputValue1[0]);
139
140         clampIfNeeded(output);
141 }
142
143 void MathCosineOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
144 {
145         float inputValue1[4];
146         float inputValue2[4];
147         
148         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
149         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
150         
151         output[0] = cos(inputValue1[0]);
152
153         clampIfNeeded(output);
154 }
155
156 void MathTangentOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
157 {
158         float inputValue1[4];
159         float inputValue2[4];
160         
161         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
162         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
163         
164         output[0] = tan(inputValue1[0]);
165
166         clampIfNeeded(output);
167 }
168
169 void MathArcSineOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
170 {
171         float inputValue1[4];
172         float inputValue2[4];
173         
174         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
175         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
176         
177         if (inputValue1[0] <= 1 && inputValue1[0] >= -1)
178                 output[0] = asin(inputValue1[0]);
179         else
180                 output[0] = 0.0;
181
182         clampIfNeeded(output);
183 }
184
185 void MathArcCosineOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
186 {
187         float inputValue1[4];
188         float inputValue2[4];
189         
190         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
191         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
192         
193         if (inputValue1[0] <= 1 && inputValue1[0] >= -1)
194                 output[0] = acos(inputValue1[0]);
195         else
196                 output[0] = 0.0;
197
198         clampIfNeeded(output);
199 }
200
201 void MathArcTangentOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
202 {
203         float inputValue1[4];
204         float inputValue2[4];
205         
206         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
207         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
208         
209         output[0] = atan(inputValue1[0]);
210
211         clampIfNeeded(output);
212 }
213
214 void MathPowerOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
215 {
216         float inputValue1[4];
217         float inputValue2[4];
218         
219         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
220         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
221         
222         if (inputValue1[0] >= 0) {
223                 output[0] = pow(inputValue1[0], inputValue2[0]);
224         }
225         else {
226                 float y_mod_1 = fmod(inputValue2[0], 1);
227                 /* if input value is not nearly an integer, fall back to zero, nicer than straight rounding */
228                 if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) {
229                         output[0] = pow(inputValue1[0], floorf(inputValue2[0] + 0.5f));
230                 }
231                 else {
232                         output[0] = 0.0;
233                 }
234         }
235
236         clampIfNeeded(output);
237 }
238
239 void MathLogarithmOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
240 {
241         float inputValue1[4];
242         float inputValue2[4];
243         
244         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
245         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
246         
247         if (inputValue1[0] > 0  && inputValue2[0] > 0)
248                 output[0] = log(inputValue1[0]) / log(inputValue2[0]);
249         else
250                 output[0] = 0.0;
251
252         clampIfNeeded(output);
253 }
254
255 void MathMinimumOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
256 {
257         float inputValue1[4];
258         float inputValue2[4];
259         
260         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
261         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
262         
263         output[0] = min(inputValue1[0], inputValue2[0]);
264
265         clampIfNeeded(output);
266 }
267
268 void MathMaximumOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
269 {
270         float inputValue1[4];
271         float inputValue2[4];
272         
273         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
274         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
275         
276         output[0] = max(inputValue1[0], inputValue2[0]);
277
278         clampIfNeeded(output);
279 }
280
281 void MathRoundOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
282 {
283         float inputValue1[4];
284         float inputValue2[4];
285         
286         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
287         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
288         
289         output[0] = round(inputValue1[0]);
290
291         clampIfNeeded(output);
292 }
293
294 void MathLessThanOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
295 {
296         float inputValue1[4];
297         float inputValue2[4];
298         
299         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
300         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
301         
302         output[0] = inputValue1[0] < inputValue2[0] ? 1.0f : 0.0f;
303
304         clampIfNeeded(output);
305 }
306
307 void MathGreaterThanOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
308 {
309         float inputValue1[4];
310         float inputValue2[4];
311         
312         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
313         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
314         
315         output[0] = inputValue1[0] > inputValue2[0] ? 1.0f : 0.0f;
316
317         clampIfNeeded(output);
318 }
319
320 void MathModuloOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
321 {
322         float inputValue1[4];
323         float inputValue2[4];
324         
325         this->m_inputValue1Operation->read(inputValue1, x, y, sampler);
326         this->m_inputValue2Operation->read(inputValue2, x, y, sampler);
327         
328         if (inputValue2[0] == 0)
329                 output[0] = 0.0;
330         else
331                 output[0] = fmod(inputValue1[0], inputValue2[0]);
332
333         clampIfNeeded(output);
334 }
335