d92fe04eb15aa0fa886f398715437ee5d9c76815
[blender.git] / source / blender / compositor / operations / COM_ProjectorLensDistortionOperation.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_ProjectorLensDistortionOperation.h"
24 #include "BLI_math.h"
25 #include "BLI_utildefines.h"
26
27 ProjectorLensDistortionOperation::ProjectorLensDistortionOperation() : NodeOperation()
28 {
29         this->addInputSocket(COM_DT_COLOR);
30         this->addInputSocket(COM_DT_VALUE);
31         this->addOutputSocket(COM_DT_COLOR);
32         this->setComplex(true);
33         this->m_inputProgram = NULL;
34         this->m_dispersionAvailable = false;
35         this->m_dispersion = 0.0f;
36 }
37 void ProjectorLensDistortionOperation::initExecution()
38 {
39         this->initMutex();
40         this->m_inputProgram = this->getInputSocketReader(0);
41 }
42
43 void *ProjectorLensDistortionOperation::initializeTileData(rcti *rect)
44 {
45         updateDispersion();
46         void *buffer = this->m_inputProgram->initializeTileData(NULL);
47         return buffer;
48 }
49
50 void ProjectorLensDistortionOperation::executePixel(float output[4], int x, int y, void *data)
51 {
52         float inputValue[4];
53         const float height = this->getHeight();
54         const float width = this->getWidth();
55         const float v = (y + 0.5f) / height;
56         const float u = (x + 0.5f) / width;
57         MemoryBuffer *inputBuffer = (MemoryBuffer *)data;
58         inputBuffer->readCubic(inputValue, (u * width + this->m_kr2) - 0.5f, v * height - 0.5f);
59         output[0] = inputValue[0];
60         inputBuffer->read(inputValue, x, y);
61         output[1] = inputValue[1];
62         inputBuffer->readCubic(inputValue, (u * width - this->m_kr2) - 0.5f, v * height - 0.5f);
63         output[2] = inputValue[2];
64         output[3] = 1.0f;
65 }
66
67 void ProjectorLensDistortionOperation::deinitExecution()
68 {
69         this->deinitMutex();
70         this->m_inputProgram = NULL;
71 }
72
73 bool ProjectorLensDistortionOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
74 {
75         rcti newInput;
76         if (this->m_dispersionAvailable) {
77                 newInput.ymax = input->ymax;
78                 newInput.ymin = input->ymin;
79                 newInput.xmin = input->xmin - this->m_kr2 - 2;
80                 newInput.xmax = input->xmax + this->m_kr2 + 2;
81         }
82         else {
83                 rcti dispInput;
84                 BLI_rcti_init(&dispInput, 0,5,0,5);
85                 if (this->getInputOperation(1)->determineDependingAreaOfInterest(&dispInput, readOperation, output)) {
86                         return true;
87                 }
88                 newInput.xmin = input->xmin - 7;  /* (0.25f * 20 * 1) + 2 == worse case dispersion */
89                 newInput.ymin = input->ymin;
90                 newInput.ymax = input->ymax;
91                 newInput.xmax = input->xmax + 7;  /* (0.25f * 20 * 1) + 2 == worse case dispersion */
92         }
93         if (this->getInputOperation(0)->determineDependingAreaOfInterest(&newInput, readOperation, output)) {
94                 return true;
95         }
96         return false;
97 }
98
99 void ProjectorLensDistortionOperation::updateDispersion() 
100 {
101         if (this->m_dispersionAvailable) return;
102         this->lockMutex();
103         if (!this->m_dispersionAvailable) {
104                 float result[4];
105                 this->getInputSocketReader(1)->read(result, 1, 1, COM_PS_NEAREST);
106                 this->m_dispersion = result[0];
107                 this->m_kr = 0.25f * maxf(minf(this->m_dispersion, 1.0f), 0.0f);
108                 this->m_kr2 = this->m_kr * 20;
109                 this->m_dispersionAvailable = true;
110         }
111         this->unlockMutex();
112 }