style cleanup: braces, compositor
[blender.git] / source / blender / compositor / operations / COM_LensGhostOperation.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_LensGhostOperation.h"
24 #include "BLI_math.h"
25 #include "BLI_utildefines.h"
26
27 #define MAX_STEP 256
28 class Ray {
29 public:
30         float position[3];
31         float direction[3];
32         float uv[2];
33         double wavelength;
34         float intensity;
35         bool valid;
36         void copyFrom(Ray* other) {
37                 copy_v3_v3(position, other->position);
38                 copy_v3_v3(direction, other->direction);
39                 copy_v2_v2(uv, other->uv);
40                 wavelength = other->wavelength;
41                 intensity = other->intensity;
42                 this->valid = other->valid;
43         }
44 };
45
46 class Intersection {
47 public:
48         float position[3];
49         float normal[3];
50         double theta;
51         bool hit;
52         bool inverted;
53 };
54
55 class LensInterface {
56 public:
57         float position[3];
58         float radius;
59         float nominalRadius;
60         double refraction1;
61         double refraction2;
62         double refraction3;
63         float thicknessCoathing;
64         virtual bool isFlat() = 0;
65         virtual void intersect(Intersection* result, Ray* ray) = 0;
66 };
67
68 class FlatInterface: public LensInterface {
69 public:
70         bool isFlat() {return true;}
71         FlatInterface(float positionX, float positionY, float positionZ, float radius) {
72                 this->position[0] = positionX;
73                 this->position[1] = positionY;
74                 this->position[2] = positionZ;
75                 this->radius = radius;
76                 this->nominalRadius = radius;
77                 this->refraction1 = 1.0f;
78                 this->refraction2 = 1.0f;
79                 this->refraction3 = 1.0f;
80                 this->thicknessCoathing = 0.0f;
81
82         }
83         void intersect(Intersection* result, Ray* ray) {
84                 const float dz = this->position[2]-ray->position[2];
85                 result->position[0] = ray->position[0] + ray->direction[0]*(dz)/ray->direction[2];
86                 result->position[1] = ray->position[1] + ray->direction[1]*(dz)/ray->direction[2];
87                 result->position[2] = ray->position[2] + ray->direction[2]*(dz)/ray->direction[2];
88                 result->normal[0] = 0.0f;
89                 result->normal[1] = 0.0f;
90                 result->normal[2] = ray->direction[2]>0?-1.0f:1.0f;
91                 result->theta = 0.0f;
92 //              result->hit = this->nominalRadius>maxf(fabs(result->position[0]), fabs(result->position[1]));
93                 result->hit = true;
94                 result->inverted = false;
95         }
96 };
97
98 class SphereInterface: public LensInterface {
99 public:
100         SphereInterface(float positionX, float positionY, float positionZ, float radius, float nominalRadius, float n0, float n2, float coatingPhase) {
101                 this->position[0] = positionX;
102                 this->position[1] = positionY;
103                 this->position[2] = positionZ;
104                 this->radius = radius;
105                 this->nominalRadius = nominalRadius;
106                 this->refraction1 = n0;
107                 this->refraction3 = n2;
108                 this->refraction2 = maxf(sqrtf(n0*n2), 1.38);
109
110                 this->thicknessCoathing = coatingPhase/4/this->refraction2;
111         }
112         bool isFlat() {return false;}
113         void intersect(Intersection* result, Ray* ray) {
114                 float delta[3] ={ray->position[0] - this->position[0],
115                         ray->position[1] - this->position[1],
116                         ray->position[2] - this->position[2]};
117                 float b = dot_v3v3(delta, ray->direction);
118                 float c = dot_v3v3(delta, delta) - this->radius*this->radius;
119                 float b2c = b*b-c;
120                 if (b2c < 0) {
121                         result->hit = false;
122                 }
123                 else {
124                         float sgn = (this->radius*ray->direction[2])>0?1.0f:-1.0f;
125                         float t = sqrtf(b2c)*sgn-b;
126                         result->position[0] = ray->direction[0]*t+ray->position[0];
127                         result->position[1] = ray->direction[1]*t+ray->position[1];
128                         result->position[2] = ray->direction[2]*t+ray->position[2];
129
130                         float p[3] = {
131                                 result->position[0] - this->position[0],
132                                 result->position[1] - this->position[1],
133                                 result->position[2] - this->position[2]
134                         };
135                         normalize_v3(p);
136
137                         if (dot_v3v3(p, ray->direction)> 0) {
138                                 result->normal[0] = -p[0];
139                                 result->normal[1] = -p[1];
140                                 result->normal[2] = -p[2];
141                         }
142                         else {
143                                 result->normal[0] = p[0];
144                                 result->normal[1] = p[1];
145                                 result->normal[2] = p[2];
146                         }
147
148                         float inverse[3] ={
149                                 -ray->direction[0],
150                                 -ray->direction[1],
151                                 -ray->direction[2]};
152
153                         result->theta = acosf(dot_v3v3(inverse, result->normal));
154                         result->hit = this->nominalRadius>sqrt(result->position[0]*result->position[0]+result->position[1]*result->position[1]);
155 //                      result->hit = this->nominalRadius>maxf(fabs(result->position[0]), fabs(result->position[1]));
156 //                      result->hit = true;
157                         result->inverted = t < 0;
158                 }
159         }
160 };
161 class RayResult {
162 public:
163         float x;
164         float y;
165         float intensity[3];
166         float u;
167         float v;
168         float screenX;
169         float screenY;
170         bool valid;
171         bool hasIntensity;
172 };
173 class Bounce {
174 public:
175         LensInterface *interface1;
176         LensInterface *interface2;
177         RayResult *raster;
178         int length; // number of interfaces to travel
179         int rasterLength;
180         Bounce(LensInterface *interface1, LensInterface *interface2, int length, int rasterStep) {
181                 this->interface1 = interface1;
182                 this->interface2 = interface2;
183                 this->length = length;
184                 this->rasterLength = rasterStep;
185                 this->raster = new RayResult[rasterLength*rasterLength];
186                 for (int i = 0 ; i < rasterLength*rasterLength ; i++) {
187                         RayResult * res = &this->raster[i];
188                         res->intensity[0] = 0.0f;
189                         res->intensity[1] = 0.0f;
190                         res->intensity[2] = 0.0f;
191                         res->x = 0.0f;
192                         res->y = 0.0f;
193                         res->u = 0.0f;
194                         res->v = 0.0f;
195                         res->valid = false;
196                 }
197         }
198         ~Bounce() {
199                 delete raster;
200
201         }
202
203         RayResult* getRayResult(int x, int y) {
204                 return &(raster[x+y*rasterLength]);
205         }
206 };
207 class LensSystem {
208 public:
209         vector<LensInterface*> interfaces;
210         vector<Bounce*> bounces;
211         int bokehIndex;
212         int lensIndex;
213
214         ~LensSystem() {
215                 for (int index = 0 ; index <bounces.size();index++) {delete bounces[index];}
216                 for (int index = 0 ; index <interfaces.size();index++) {delete interfaces[index];}
217         }
218
219         void updateBounces(int step) {
220                 for (int i = 0; i < interfaces.size()-1 ; i ++) {
221                         if (!interfaces[i]->isFlat()) {
222                                 for (int j = i+1; j < interfaces.size()-1 ; j ++) {
223                                         if (!interfaces[j]->isFlat()) {
224                                                 int length = interfaces.size()+2*(j-i);
225                                                 Bounce* bounce = new Bounce(interfaces[j], interfaces[i], length, step);
226                                                 bounces.push_back(bounce);
227                                         }
228                                 }
229                         }
230                 }
231
232         }
233
234         void addInterface(LensInterface* pinterface) {
235                 this->interfaces.push_back(pinterface);
236                 this->lensIndex = this->interfaces.size()-1;
237         }
238
239         static int refraction(float *refract, float *n, float *view, double index)
240         {
241
242                 return 1;
243
244 //                float dot, fac;
245
246 //                VECCOPY(refract, view);
247
248 //                dot= view[0]*n[0] + view[1]*n[1] + view[2]*n[2];
249
250 //                if (dot>0.0f) {
251 //                        index = 1.0f/index;
252 //                        fac= 1.0f - (1.0f - dot*dot)*index*index;
253 //                        if (fac<= 0.0f) return 0;
254 //                        fac= -dot*index + sqrt(fac);
255 //                }
256 //                else {
257 //                        fac= 1.0f - (1.0f - dot*dot)*index*index;
258 //                        if (fac<= 0.0f) return 0;
259 //                        fac= -dot*index - sqrt(fac);
260 //                }
261
262 //                refract[0]= index*view[0] + fac*n[0];
263 //                refract[1]= index*view[1] + fac*n[1];
264 //                refract[2]= index*view[2] + fac*n[2];
265
266 //                normalize_v3(refract);
267 //                return 1;
268                 //---
269 //              const double cosI = dot_v3v3(n, view);
270 //              const double sinT2 = index * index * (1.0 - cosI * cosI);
271 //              if (sinT2 >= 1.0f)
272 //              {
273 //                      return 0;
274 //              }
275 //              refract[0] = index*view[0] - (index + sqrt(1.0-sinT2))*n[0];
276 //              refract[1] = index*view[1] - (index + sqrt(1.0-sinT2))*n[1];
277 //              refract[2] = index*view[2] - (index + sqrt(1.0-sinT2))*n[2];
278 //              normalize_v3(refract);
279 //              return 1;
280                 //---
281
282 //                double ni = -dot_v3v3(view, n);
283 //                double test = 1.0f - index*index*(1.0f-ni*ni);
284 //                if (test < 0) {
285 //                        return 0;
286 //                }
287 //                else {
288 //                        double mul = index*ni + sqrt(test);
289 //                        refract[0] = index * view[0] - mul*n[0];
290 //                        refract[1] = index * view[1] - mul*n[1];
291 //                        refract[2] = index * view[2] - mul*n[2];
292 //                        normalize_v3(refract);
293 //                        return 1;
294 //                }
295         }
296
297         /* orn = original face normal */
298         static void reflection(float *ref, float *n, float *view)
299         {
300                 float f1;
301
302                 f1= -2.0f*dot_v3v3(n, view);
303
304                 ref[0]= (view[0]+f1*n[0]);
305                 ref[1]= (view[1]+f1*n[1]);
306                 ref[2]= (view[2]+f1*n[2]);
307                 normalize_v3(ref);
308         }
309
310         static float fresnelAR(float theta0, float lambda, float d1, float n0, float n1, float n2) {
311                 // refractionangles in coating and the 2nd medium
312                 float theta1 = asin(sin(theta0)*n0/n1);
313                 float theta2 = asin(sin(theta0)*n0/n2);
314
315                 float rs01 = -sin(theta0-theta1)/sin(theta0+theta1);
316                 float rp01 = tan( theta0-theta1)/tan(theta0+theta1);
317                 float ts01 = 2 * sin ( theta1 ) * cos ( theta0 ) / sin ( theta0+theta1 ) ;
318                 float tp01 = ts01*cos(theta0-theta1);
319                 // amplitude for inner reflection
320                 float rs12 = -sin ( theta1-theta2 ) / sin ( theta1+theta2 ) ;
321                 float rp12 = +tan ( theta1-theta2 ) / tan ( theta1+theta2 ) ;
322                 // after passing through first surface twice :
323                 // 2 transmissions and 1 reflection
324                 float ris = ts01 * ts01 * rs12 ;
325                 float rip = tp01 * tp01 * rp12 ;
326                 // phase difference between outer and inner reflections
327                 float dy = d1 * n1 ;
328                 float dx = tan ( theta1 ) * dy ;
329                 float delay = sqrt ( dx * dx+dy * dy ) ;
330                 float relPhase = 4 * M_PI / lambda * ( delay-dx * sin ( theta0 ) ) ;
331                 // Add up sines of different phase and amplitude
332                 float out_s2 = rs01 * rs01 + ris * ris + 2 * rs01 * ris * cos ( relPhase ) ;
333                 float out_p2 = rp01 * rp01 + rip * rip + 2 * rp01 * rip * cos ( relPhase ) ;
334                 return ( out_s2+out_p2 ) / 2 ;
335         }
336
337         void detectHit(Ray* result, Ray* inputRay, Bounce *bounce) {
338                 int phase = 0;
339                 int delta = 1;
340                 int t = 1;
341                 int k;
342                 result->copyFrom(inputRay);
343                 result->valid = false;
344                 LensInterface* next = bounce->interface1;
345                 LensInterface* f = NULL;
346                 Intersection intersection;
347                 for (k = 0 ; k < bounce->length-1;k++, t+=delta) {
348                         f = this->interfaces[t];
349                         bool breflect = next == f;
350                         if (breflect) {
351                                 delta = -delta;
352                                 if (phase == 0) {
353                                         next = bounce->interface2;
354                                 }
355                                 else {
356                                         next = NULL;
357                                 }
358                                 phase ++;
359                         }
360
361                         f->intersect(&intersection, result);
362                         if (!intersection.hit) {
363                                 break;
364                         }
365                         if (f->isFlat()) {
366                                 if (t == this->bokehIndex) {
367                                         result->uv[0] = intersection.position[0]/f->nominalRadius;
368                                         result->uv[1] = intersection.position[1]/f->nominalRadius;
369                                 }
370                         }
371
372                         float p[3] = {
373                                 intersection.position[0]-result->position[0],
374                                 intersection.position[1]-result->position[1],
375                                 intersection.position[2]-result->position[2]
376                         };
377
378                         float nfac = sqrt(p[0]*p[0]+p[1]*p[1]+p[2]*p[2]);
379
380                         if (intersection.inverted) {
381                                 nfac *= -1;
382                         }
383
384                         result->direction[0] = p[0]/nfac;
385                         result->direction[1] = p[1]/nfac;
386                         result->direction[2] = p[2]/nfac;
387                         result->position[0] = intersection.position[0];
388                         result->position[1] = intersection.position[1];
389                         result->position[2] = intersection.position[2];
390
391                         if (!f->isFlat()) {
392                                 // do refraction and reflection
393                                 double n0 = result->direction[2]<0?f->refraction1:f->refraction3;
394                                 double n1 = f->refraction2;
395                                 double n2 = result->direction[2]<0?f->refraction3:f->refraction1;
396                                 if (!breflect) {
397                                         float view[3] ={
398                                                 result->direction[0],
399                                                 result->direction[1],
400                                                 result->direction[2]
401                                         };
402                                         int ref = this->refraction(result->direction, intersection.normal, view, n0/n1);
403                                         if (ref == 0) {
404                                                 break;
405                                         }
406                                 }
407                                 else {
408                                         this->reflection(result->direction, intersection.normal, result->direction);
409                                         float  fresnelMultiplyer = fresnelAR(intersection.theta, result->wavelength, f->thicknessCoathing, n0, n1, n2);
410                                         if (isnan(fresnelMultiplyer)) {
411                                                 fresnelMultiplyer = 0.0f;
412                                         }
413                                         result->intensity *= fresnelMultiplyer;
414                                 }
415                         }
416
417                 }
418                 if (k < bounce->length-1) {
419                         result->intensity = 0;
420                 }
421                 else {
422                         result->valid = true;
423                 }
424         }
425 };
426
427 typedef struct LensFace {
428         RayResult* v1;
429         RayResult* v2;
430         RayResult* v3;
431 } LensFace;
432
433 LensGhostProjectionOperation::LensGhostProjectionOperation(): NodeOperation() {
434         this->addInputSocket(COM_DT_COLOR);
435         this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE);
436         this->addOutputSocket(COM_DT_COLOR);
437         this->lampObject = NULL;
438         this->cameraObject = NULL;
439         this->system = NULL;
440         this->quality = COM_QUALITY_HIGH;
441         this->setComplex(false);
442 }
443
444 LensGhostOperation::LensGhostOperation(): LensGhostProjectionOperation() {
445         this->setComplex(true);
446
447 }
448
449 void LensGhostProjectionOperation::initExecution() {
450         if (this->cameraObject != NULL && this->lampObject != NULL) {
451                 if (lampObject == NULL || cameraObject == NULL) {
452                         visualLampPosition[0] = 0;
453                         visualLampPosition[1] = 0;
454                         visualLampPosition[2] = 0;
455                 }
456                 else {
457                         /* too simple, better to return the distance on the view axis only
458                          * return len_v3v3(ob->obmat[3], cam->dof_ob->obmat[3]); */
459                         float matt[4][4], imat[4][4], obmat[4][4];
460
461                         copy_m4_m4(obmat, cameraObject->obmat);
462                         normalize_m4(obmat);
463                         invert_m4_m4(imat, obmat);
464                         mult_m4_m4m4(matt, imat, lampObject->obmat);
465
466                         visualLampPosition[0] = (float)(matt[3][0]);
467                         visualLampPosition[1] = (float)(matt[3][1]);
468                         visualLampPosition[2] = (float)fabs(matt[3][2]);
469                 }
470         }
471         this->lamp = (Lamp*)lampObject->data;
472
473         this->step = this->quality==COM_QUALITY_LOW?64:this->quality==COM_QUALITY_MEDIUM?128:256;
474         this->bokehReader = this->getInputSocketReader(1);
475
476 #define MM *0.001f
477 #define CM *0.01f
478 #define NM *0.000000001
479 #define RED 650 NM
480 #define GREEN 510 NM
481 #define BLUE 475 NM
482 #define AIR 1.000293f
483 #define GLASS 1.5200f
484 #define TEST 0.000002f
485         // determine interfaces
486         LensSystem *system = new LensSystem();
487         system->addInterface(new FlatInterface(0.0f,0.0f, 6.5 CM, 30 MM)); //ENTRANCE
488         system->addInterface(new SphereInterface(0.0f,0.0f, -3 CM, 8 CM, 3 CM, AIR, GLASS , 0.f));
489         system->addInterface(new SphereInterface(0.0f,0.0f, -4 CM, 8 CM, 3 CM, GLASS, AIR, GREEN));
490         system->addInterface(new FlatInterface(0.0f,0.0f, 3.0 CM, 15 MM)); // BOKEH
491         system->addInterface(new SphereInterface(0.0f,0.0f, 6 CM, 3 CM, 2 CM, AIR, GLASS, 0.0f));
492         system->addInterface(new SphereInterface(0.0f,0.0f, 5.5 CM, 3 CM, 2 CM, GLASS, AIR, 0.f));
493         system->addInterface(new FlatInterface(0.0f,0.0f,0 CM, 30 MM)); // SENSOR
494         system->bokehIndex =3;
495
496         // determine interfaces
497 //      LensSystem *system = new LensSystem();
498 //      system->addInterface(new FlatInterface(0.0f,0.0f, 6.5 CM, 30 MM)); //ENTRANCE
499 //      system->addInterface(new SphereInterface(0.0f,0.0f, 14 CM, 8 CM, 6 CM, AIR, GLASS , 0.0f));
500 //      system->addInterface(new SphereInterface(0.0f,0.0f, 12 CM, 8 CM, 6 CM, GLASS, AIR, GREEN));
501 //      system->addInterface(new FlatInterface(0.0f,0.0f, 3.0 CM, 30 MM)); // BOKEH
502 //      system->addInterface(new SphereInterface(0.0f,0.0f, 1 CM, 3 CM, 2 CM, AIR, GLASS, GREEN));
503 //      system->addInterface(new SphereInterface(0.0f,0.0f, -2 CM, 3 CM, 2 CM, GLASS, AIR, RED));
504 //      system->addInterface(new FlatInterface(0.0f,0.0f,0 CM, 20 MM)); // SENSOR
505 //      system->bokehIndex = 3;
506 #undef CM
507 #undef MM
508         // determine bounces
509         system->updateBounces(step);
510         this->system = system;
511 }
512
513 void LensGhostOperation::initExecution() {
514         LensGhostProjectionOperation::initExecution();
515         LensSystem *system = (LensSystem*)this->system;
516         LensInterface *interface1 = system->interfaces[0];
517
518         // for every herz
519         float HERZ[3]={650 NM,510 NM,475 NM}; /// @todo use 7 for high quality?
520         for (int iw = 0 ; iw < 3 ; iw ++) {
521                 float wavelength = HERZ[iw];
522         // for every bounce
523                 for (int ib = 0 ; ib < system->bounces.size() ; ib++) {
524                         Bounce* bounce = system->bounces[ib];
525         // based on quality setting the number of iteration will be different (128^2, 64^2, 32^2)
526                         for (int xi = 0 ; xi < step ; xi ++) {
527                                 float x = -interface1->radius+xi*(interface1->radius*2/step);
528                                 for (int yi = 0 ; yi < step ; yi ++) {
529                                         float y = -interface1->radius+yi*(interface1->radius*2/step);
530                                         Ray r;
531                                         Ray result;
532                                         r.wavelength = wavelength;
533                                         r.intensity = this->lamp->energy;
534                                         r.uv[0] = 0.0f;
535                                         r.uv[1] = 0.0f;
536                                         r.position[0] = visualLampPosition[0];
537                                         r.position[1] = visualLampPosition[1];
538                                         r.position[2] = visualLampPosition[2];
539                                         r.direction[0] = interface1->position[0]+x - r.position[0];
540                                         r.direction[1] = interface1->position[1]+y - r.position[1];
541                                         r.direction[2] = interface1->position[2] - r.position[2];
542                                         normalize_v3(r.direction);
543                                         system->detectHit(&result, &r, bounce);
544                                         RayResult *res = bounce->getRayResult(xi, yi);
545                                         if (iw == 0) {
546                                                 res->x = result.position[0];
547                                                 res->y = result.position[1];
548                                                 res->u = result.uv[0];
549                                                 res->v = result.uv[1];
550                                         }
551                                         res->intensity[iw] = result.intensity;
552                                         if (result.valid) {
553                                                 res->valid = true;
554                                         }
555                                 }
556                         }
557                 }
558         }
559 #undef NM
560         const int width = this->getWidth();
561         const int height = this->getHeight();
562         const float width2 = width/2.0f;
563         const float height2 = height/2.0f;
564         float *data = new float[width*height*4];
565         for (int i = 0 ; i < width*height ; i ++) {
566                 data[i*4+0] = 0.0f;
567                 data[i*4+1] = 0.0f;
568                 data[i*4+2] = 0.0f;
569                 data[i*4+3] = 1.0f;
570         }
571         /// @todo every bounce creates own image. these images are added together at the end
572 //      LensSystem *system = (LensSystem*)this->system;
573         LensInterface * lens = system->interfaces[system->lensIndex];
574         for (int i = 0 ; i < system->bounces.size() ; i ++) {
575                 Bounce* bounce = system->bounces[i];
576                 for (int r = 0 ; r < bounce->rasterLength*bounce->rasterLength ; r ++) {
577                         RayResult *result = &bounce->raster[r];
578 //                      if (result->valid) {
579                                 float ru= result->x/lens->nominalRadius*width2+width2;
580                                 float rv  = result->y/lens->nominalRadius*height2+height2;
581                                 result->screenX = ru;
582                                 result->screenY = rv;
583                                 result->hasIntensity = result->intensity[0]>0.0f &&result->intensity[1]>0.0f&& result->intensity[2]>0.0f;
584 //                      }
585                 }
586         }
587 }
588
589 void* LensGhostOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers) {
590         vector<LensFace*>* result = new vector<LensFace*>();
591         LensSystem *system = (LensSystem*)this->system;
592         const float minx = rect->xmin;
593         const float miny = rect->ymin;
594         const float maxx = rect->xmax;
595         const float maxy = rect->ymax;
596         for (int i = 0 ; i < system->bounces.size() ; i ++) {
597                 Bounce* bounce = system->bounces[i];
598                 int faceX, faceY;
599                 for (faceX = 0 ; faceX < bounce->rasterLength-1 ; faceX++) {
600                         for (faceY = 0 ; faceY < bounce->rasterLength-1 ; faceY++) {
601                                 RayResult* vertex1 = bounce->getRayResult(faceX, faceY);
602                                 RayResult* vertex2 = bounce->getRayResult(faceX+1, faceY);
603                                 RayResult* vertex3 = bounce->getRayResult(faceX+1, faceY+1);
604                                 RayResult* vertex4 = bounce->getRayResult(faceX, faceY+1);
605                                 // early hit test
606                                 if (!((vertex1->screenX < minx && vertex2->screenX < minx && vertex3->screenX < minx && vertex4->screenX < minx) ||
607                                         (vertex1->screenX > maxx && vertex2->screenX > maxx && vertex3->screenX > maxx && vertex4->screenX > maxx) ||
608                                         (vertex1->screenY < miny && vertex2->screenY < miny && vertex3->screenY < miny && vertex4->screenY < miny) ||
609                                         (vertex1->screenY > maxy && vertex2->screenY > maxy && vertex3->screenY > maxy && vertex4->screenY > maxy))) {
610                                         int number = vertex1->hasIntensity +vertex2->hasIntensity +vertex3->hasIntensity +vertex4->hasIntensity;
611                                         if (number == 4) {
612                                                 LensFace* face = new LensFace();
613                                                 face->v1 = vertex1;
614                                                 face->v2 = vertex2;
615                                                 face->v3 = vertex3;
616                                                 result->push_back(face);
617                                                 face = new LensFace();
618                                                 face->v1 = vertex3;
619                                                 face->v2 = vertex4;
620                                                 face->v3 = vertex1;
621                                                 result->push_back(face);
622                                         }
623                                         else if (number == 3) {
624                                                 LensFace *face = new LensFace();
625                                                 if (!vertex1->hasIntensity) {
626                                                         face->v1 = vertex2;
627                                                         face->v2 = vertex3;
628                                                         face->v3 = vertex4;
629                                                 }
630                                                 else if (!vertex2->hasIntensity) {
631                                                         face->v1 = vertex1;
632                                                         face->v2 = vertex3;
633                                                         face->v3 = vertex4;
634                                                 }
635                                                 else if (!vertex3->hasIntensity) {
636                                                         face->v1 = vertex1;
637                                                         face->v2 = vertex2;
638                                                         face->v3 = vertex4;
639                                                 }
640                                                 else {
641                                                         face->v1 = vertex1;
642                                                         face->v2 = vertex2;
643                                                         face->v3 = vertex3;
644                                                 }
645                                                 result->push_back(face);
646                                         }
647                                 }
648                         }
649                 }
650         }
651
652         return result;
653 }
654
655 void LensGhostOperation::deinitializeTileData(rcti *rect, MemoryBuffer **memoryBuffers, void *data) {
656         if (data) {
657                 vector<LensFace*>* faces = (vector<LensFace*>*)data;
658                 while (faces->size() != 0) {
659                         LensFace *face = faces->back();
660                         faces->pop_back();
661                         delete face;
662                 }
663                 delete faces;
664         }
665 }
666
667
668 void LensGhostProjectionOperation::executePixel(float* color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]) {
669         float bokeh[4];
670         LensSystem *system = (LensSystem*)this->system;
671         LensInterface *interface1 = system->interfaces[0];
672         color[0] = 0.0f;
673         color[1] = 0.0f;
674         color[2] = 0.0f;
675         color[3] = 0.0f;
676         const float width = this->getWidth();
677         const float height = this->getHeight();
678         const float size = min(height, width);
679         const float width2 = width/2;
680         const float height2 = height/2;
681         const float size2 = size/2;
682
683 #define NM *0.000000001
684         float HERZ[3]={650 NM,510 NM,475 NM}; /// @todo use 7 for high quality?
685         float rx = ((x-width2)/size2) * interface1->radius;
686         float ry = ((y-height2)/size2) * interface1->radius;
687
688         for (int iw = 0 ; iw < 3 ; iw ++) {
689                 float intensity = 0.0f;
690                 float wavelength = HERZ[iw];
691                 float colorcomponent = 0.0f;
692                 if (iw ==0 ) colorcomponent = lamp->r;
693                 if (iw ==1 ) colorcomponent = lamp->g;
694                 if (iw ==2 ) colorcomponent = lamp->b;
695
696
697         // for every bounce
698                 for (int ib = 0 ; ib < system->bounces.size() ; ib++) {
699                         Bounce* bounce = system->bounces[ib];
700         // based on quality setting the number of iteration will be different (128^2, 64^2, 32^2)
701
702                         Ray r;
703                         Ray result;
704                         r.wavelength = wavelength;
705                         r.intensity = this->lamp->energy;
706                         r.uv[0] = 0.0f;
707                         r.uv[1] = 0.0f;
708                         r.position[0] = visualLampPosition[0];
709                         r.position[1] = visualLampPosition[1];
710                         r.position[2] = visualLampPosition[2];
711                         r.direction[0] = interface1->position[0]+rx - r.position[0];
712                         r.direction[1] = interface1->position[1]+ry - r.position[1];
713                         r.direction[2] = interface1->position[2] - r.position[2];
714                         normalize_v3(r.direction);
715                         system->detectHit(&result, &r, bounce);
716                         if (result.valid) {
717                                 float u = ((result.uv[0]+1.0f)/2)*bokehReader->getWidth();
718                                 float v = ((result.uv[1]+1.0f)/2)*bokehReader->getHeight();
719
720                                 bokehReader->read(bokeh, u, v, sampler, inputBuffers);
721
722                                 intensity += result.intensity *bokeh[iw];
723                         }
724                 }
725                 intensity = maxf(0.0f, intensity);
726                 color[iw] = intensity*colorcomponent;
727         }
728         color[3] = 1.0f;
729 #undef NM
730
731 }
732
733
734
735 void LensGhostOperation::executePixel(float* color, int x, int y, MemoryBuffer *inputBuffers[], void* data) {
736         vector<LensFace*>* faces = (vector<LensFace*>*)data;
737 #if 0 /* UNUSED */
738         const float bokehWidth = bokehReader->getWidth();
739         const float bokehHeight = bokehReader->getHeight();
740         float bokeh[4];
741 #endif
742         color[0] = 0.0f;
743         color[1] = 0.0f;
744         color[2] = 0.0f;
745         color[3] = 1.0f;
746
747         unsigned int index;
748         for (index = 0 ; index < faces->size() ; index ++) {
749                 LensFace * face = faces->operator [](index);
750                 RayResult* vertex1 = face->v1;
751                 RayResult* vertex2 = face->v2;
752                 RayResult* vertex3 = face->v3;
753                 if (!((vertex1->screenX < x && vertex2->screenX < x && vertex3->screenX < x) ||
754                         (vertex1->screenX > x && vertex2->screenX > x && vertex3->screenX > x) ||
755                         (vertex1->screenY < y && vertex2->screenY < y && vertex3->screenY < y) ||
756                         (vertex1->screenY > y && vertex2->screenY > y && vertex3->screenY > y))) {
757
758                         const float v1[2] = {vertex1->screenX, vertex1->screenY};
759                         const float v2[2] = {vertex2->screenX, vertex2->screenY};
760                         const float v3[2] = {vertex3->screenX, vertex3->screenY};
761                         const float co[2] = {x, y};
762                         float weights[3];
763
764                         barycentric_weights_v2(v1, v2, v3, co, weights);
765                         if (weights[0]>=0.0f && weights[0]<=1.0f &&
766                                         weights[1]>=0.0f && weights[1]<=1.0f &&
767                                         weights[2]>=0.0f && weights[2]<=1.0f) {
768 //                            const float u = (vertex1->u*weights[0]+vertex2->u*weights[1]+vertex3->u*weights[2]);
769 //                            const float v = (vertex1->v*weights[0]+vertex2->v*weights[1]+vertex3->v*weights[2]);
770 //                            const float tu = ((u+1.0f)/2.0f)*bokehWidth;
771 //                            const float tv = ((v+1.0f)/2.0f)*bokehHeight;
772 //                            bokehReader->read(bokeh, tu, tv, inputBuffers);
773
774 //                                                      color[0] = max(color[0], bokeh[0]*(vertex1->intensity[0]*weights[0]+vertex2->intensity[0]*weights[1]+vertex3->intensity[0]*weights[2]));
775 //                            color[1] = max(color[1], bokeh[1]*(vertex1->intensity[1]*weights[0]+vertex2->intensity[1]*weights[1]+vertex3->intensity[1]*weights[2]));
776 //                            color[2] = max(color[2], bokeh[2]*(vertex1->intensity[2]*weights[0]+vertex2->intensity[2]*weights[1]+vertex3->intensity[2]*weights[2]));
777                                                         color[0] = max(color[0], (vertex1->intensity[0]*weights[0]+vertex2->intensity[0]*weights[1]+vertex3->intensity[0]*weights[2]));
778                             color[1] = max(color[1], (vertex1->intensity[1]*weights[0]+vertex2->intensity[1]*weights[1]+vertex3->intensity[1]*weights[2]));
779                             color[2] = max(color[2], (vertex1->intensity[2]*weights[0]+vertex2->intensity[2]*weights[1]+vertex3->intensity[2]*weights[2]));
780                         }
781                 }
782         }
783 }
784
785
786 void LensGhostProjectionOperation::deinitExecution() {
787         if (this->system) delete (LensSystem*)this->system;
788         this->system = NULL;
789         this->bokehReader = NULL;
790 }
791
792 bool LensGhostProjectionOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) {
793         rcti bokehInput;
794
795         NodeOperation *operation = this->getInputOperation(1);
796         bokehInput.xmax = operation->getWidth();
797         bokehInput.xmin = 0;
798         bokehInput.ymax = operation->getHeight();
799         bokehInput.ymin = 0;
800         if (operation->determineDependingAreaOfInterest(&bokehInput, readOperation, output) ) {
801                 return true;
802         }
803
804         return NodeOperation::determineDependingAreaOfInterest(input, readOperation, output);
805 }