38b1dbfa8569bad29c820d3af9640e0a35fd9574
[blender.git] / source / blender / compositor / operations / COM_MovieDistortionOperation.h
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 #ifndef _COM_MovieDistortionOperation_h_
24 #define _COM_MovieDistortionOperation_h_
25
26 #include "COM_NodeOperation.h"
27 #include "DNA_movieclip_types.h"
28 #include "MEM_guardedalloc.h"
29
30 extern "C" {
31 #  include "BKE_tracking.h"
32 #  include "PIL_time.h"
33 }
34
35 #define COM_DISTORTIONCACHE_MAXSIZE 10
36
37 class DistortionCache {
38 private:
39         short m_distortion_model;
40         float m_k1, m_k2, m_k3;
41         float m_division_k1, m_division_k2;
42         float m_principal_x;
43         float m_principal_y;
44         float m_pixel_aspect;
45         int m_width;
46         int m_height;
47         int m_calibration_width;
48         int m_calibration_height;
49         bool m_inverted;
50         double timeLastUsage;
51         int m_margin[2];
52
53 public:
54         DistortionCache(MovieClip *movieclip,
55                         int width, int height,
56                         int calibration_width, int calibration_height,
57                         bool inverted,
58                         const int margin[2])
59         {
60                 this->m_distortion_model = movieclip->tracking.camera.distortion_model;
61                 this->m_k1 = movieclip->tracking.camera.k1;
62                 this->m_k2 = movieclip->tracking.camera.k2;
63                 this->m_k3 = movieclip->tracking.camera.k3;
64                 this->m_division_k1 = movieclip->tracking.camera.division_k1;
65                 this->m_division_k2 = movieclip->tracking.camera.division_k2;
66                 this->m_principal_x = movieclip->tracking.camera.principal[0];
67                 this->m_principal_y = movieclip->tracking.camera.principal[1];
68                 this->m_pixel_aspect = movieclip->tracking.camera.pixel_aspect;
69                 this->m_width = width;
70                 this->m_height = height;
71                 this->m_calibration_width = calibration_width;
72                 this->m_calibration_height = calibration_height;
73                 this->m_inverted = inverted;
74                 copy_v2_v2_int(this->m_margin, margin);
75                 this->updateLastUsage();
76         }
77
78         void updateLastUsage() {
79                 this->timeLastUsage = PIL_check_seconds_timer();
80         }
81
82         inline double getTimeLastUsage() {
83                 return this->timeLastUsage;
84         }
85
86         bool isCacheFor(MovieClip *movieclip,
87                         int width, int height,
88                         int calibration_width, int claibration_height,
89                         bool inverted)
90         {
91                 return this->m_distortion_model == movieclip->tracking.camera.distortion_model &&
92                        this->m_k1 == movieclip->tracking.camera.k1 &&
93                        this->m_k2 == movieclip->tracking.camera.k2 &&
94                        this->m_k3 == movieclip->tracking.camera.k3 &&
95                        this->m_division_k1 == movieclip->tracking.camera.division_k1 &&
96                        this->m_division_k2 == movieclip->tracking.camera.division_k2 &&
97                        this->m_principal_x == movieclip->tracking.camera.principal[0] &&
98                        this->m_principal_y == movieclip->tracking.camera.principal[1] &&
99                        this->m_pixel_aspect == movieclip->tracking.camera.pixel_aspect &&
100                        this->m_inverted == inverted &&
101                        this->m_width == width &&
102                        this->m_height == height &&
103                        this->m_calibration_width == calibration_width &&
104                        this->m_calibration_height == claibration_height;
105         }
106
107         void getUV(MovieTracking *trackingData,
108                    float x,
109                    float y,
110                    float *r_u,
111                    float *r_v)
112         {
113                 if (x < 0 || x >= this->m_width || y < 0 || y >= this->m_height) {
114                         *r_u = x;
115                         *r_v = y;
116                 }
117                 else {
118                         /* float overscan = 0.0f; */
119                         const float w = (float)this->m_width /* / (1 + overscan) */;
120                         const float h = (float)this->m_height /* / (1 + overscan) */;
121                         const float aspx = w / (float)this->m_calibration_width;
122                         const float aspy = h / (float)this->m_calibration_height;
123                         float in[2];
124                         float out[2];
125
126                         in[0] = (x /* - 0.5 * overscan * w */) / aspx;
127                         in[1] = (y /* - 0.5 * overscan * h */) / aspy / this->m_pixel_aspect;
128
129                         if (this->m_inverted) {
130                                 BKE_tracking_undistort_v2(trackingData, in, out);
131                         }
132                         else {
133                                 BKE_tracking_distort_v2(trackingData, in, out);
134                         }
135
136                         *r_u = out[0] * aspx /* + 0.5 * overscan * w */;
137                         *r_v = (out[1] * aspy /* + 0.5 * overscan * h */) * this->m_pixel_aspect;
138                 }
139         }
140
141         void getMargin(int margin[2])
142         {
143                 copy_v2_v2_int(margin, m_margin);
144         }
145 };
146
147 class MovieDistortionOperation : public NodeOperation {
148 private:
149         DistortionCache *m_cache;
150         SocketReader *m_inputOperation;
151         MovieClip *m_movieClip;
152         int m_margin[2];
153
154 protected:
155         bool m_distortion;
156         int m_framenumber;
157
158 public:
159         MovieDistortionOperation(bool distortion);
160         void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
161
162         void initExecution();
163         void deinitExecution();
164         
165         void setMovieClip(MovieClip *clip) { this->m_movieClip = clip; }
166         void setFramenumber(int framenumber) { this->m_framenumber = framenumber; }
167         bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
168
169 };
170
171 void deintializeDistortionCache(void);
172
173 #endif