ebf3b772b3ba7c0bd326b8fe1c6c89891c695f7b
[blender.git] / source / blender / compositor / operations / COM_VectorBlurOperation.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_VectorBlurOperation.h"
24 #include "BLI_math.h"
25
26 // use the implementation of blender internal renderer to calculate the vector blur.
27 extern "C" {
28         #include "RE_pipeline.h"
29 }
30
31 VectorBlurOperation::VectorBlurOperation() : NodeOperation()
32 {
33         this->addInputSocket(COM_DT_COLOR);
34         this->addInputSocket(COM_DT_VALUE); // ZBUF
35         this->addInputSocket(COM_DT_COLOR); //SPEED
36         this->addOutputSocket(COM_DT_COLOR);
37         this->m_settings = NULL;
38         this->m_cachedInstance = NULL;
39         this->m_inputImageProgram = NULL;
40         this->m_inputSpeedProgram = NULL;
41         this->m_inputZProgram = NULL;
42         setComplex(true);
43 }
44 void VectorBlurOperation::initExecution()
45 {
46         initMutex();
47         this->m_inputImageProgram = getInputSocketReader(0);
48         this->m_inputZProgram = getInputSocketReader(1);
49         this->m_inputSpeedProgram = getInputSocketReader(2);
50         this->m_cachedInstance = NULL;
51         QualityStepHelper::initExecution(COM_QH_INCREASE);
52         
53 }
54
55 void VectorBlurOperation::executePixel(float output[4], int x, int y, void *data)
56 {
57         float *buffer = (float *) data;
58         int index = (y * this->getWidth() + x) * COM_NUMBER_OF_CHANNELS;
59         copy_v4_v4(output, &buffer[index]);
60 }
61
62 void VectorBlurOperation::deinitExecution()
63 {
64         deinitMutex();
65         this->m_inputImageProgram = NULL;
66         this->m_inputSpeedProgram = NULL;
67         this->m_inputZProgram = NULL;
68         if (this->m_cachedInstance) {
69                 delete [] this->m_cachedInstance;
70                 this->m_cachedInstance = NULL;
71         }
72 }
73 void *VectorBlurOperation::initializeTileData(rcti *rect)
74 {
75         if (this->m_cachedInstance) {
76                 return this->m_cachedInstance;
77         }
78         
79         lockMutex();
80         if (this->m_cachedInstance == NULL) {
81                 MemoryBuffer *tile = (MemoryBuffer *)this->m_inputImageProgram->initializeTileData(rect);
82                 MemoryBuffer *speed = (MemoryBuffer *)this->m_inputSpeedProgram->initializeTileData(rect);
83                 MemoryBuffer *z = (MemoryBuffer *)this->m_inputZProgram->initializeTileData(rect);
84                 float *data = new float[this->getWidth() * this->getHeight() * COM_NUMBER_OF_CHANNELS];
85                 memcpy(data, tile->getBuffer(), this->getWidth() * this->getHeight() * COM_NUMBER_OF_CHANNELS * sizeof(float));
86                 this->generateVectorBlur(data, tile, speed, z);
87                 this->m_cachedInstance = data;
88         }
89         unlockMutex();
90         return this->m_cachedInstance;
91 }
92
93 bool VectorBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
94 {
95         if (this->m_cachedInstance == NULL) {
96                 rcti newInput;
97                 newInput.xmax = this->getWidth();
98                 newInput.xmin = 0;
99                 newInput.ymax = this->getHeight();
100                 newInput.ymin = 0;
101                 return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
102         }
103         else {
104                 return false;
105         }
106 }
107
108 void VectorBlurOperation::generateVectorBlur(float *data, MemoryBuffer *inputImage, MemoryBuffer *inputSpeed, MemoryBuffer *inputZ)
109 {
110         float *zbuf = inputZ->convertToValueBuffer();
111         NodeBlurData blurdata;
112         blurdata.samples = this->m_settings->samples / QualityStepHelper::getStep();
113         blurdata.maxspeed = this->m_settings->maxspeed;
114         blurdata.minspeed = this->m_settings->minspeed;
115         blurdata.curved = this->m_settings->curved;
116         blurdata.fac = this->m_settings->fac;
117         RE_zbuf_accumulate_vecblur(&blurdata, this->getWidth(), this->getHeight(), data, inputImage->getBuffer(), inputSpeed->getBuffer(), zbuf);
118         delete [] zbuf;
119         return;
120 }