New: Editable cache. Fixed: Don't clear cache on e.g. lamp moving. Changed: Switched...
[blender.git] / source / blender / radiosity / intern / source / radrender.c
1 /* ***************************************
2  *
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  */
31  
32 /* radrender.c, aug 2003
33  *
34  * Most of the code here is copied from radiosity code, to optimize for renderfaces.
35  * Shared function calls mostly reside in radfactors.c
36  * No adaptive subdivision takes place
37  *
38  * - do_radio_render();  main call, extern
39  *   - initradfaces(); add radface structs in render faces, init radio globals
40  *   - 
41  *   - initradiosity(); LUTs
42  *   - inithemiwindows();
43  *   - progressiverad(); main itteration loop
44  *     - hemi zbuffers
45  *     - calc rad factors
46  * 
47  *   - closehemiwindows();
48  *   - freeAllRad();
49  *   - make vertex colors
50  *
51  * - during render, materials use totrad as ambient replacement
52  * - free radfaces
53  */
54
55 #include <stdlib.h>
56 #include <string.h>
57 #include <math.h>
58
59 #include "MEM_guardedalloc.h"
60
61 #include "BLI_blenlib.h"
62 #include "BLI_arithb.h"
63 #include "BLI_rand.h"
64
65 #include "BKE_utildefines.h"
66 #include "BKE_global.h"
67 #include "BKE_main.h"
68
69 #include "BIF_screen.h"
70
71 #include "radio.h"
72
73 /* the radiosity module uses internal includes from render! */
74 #include "renderpipeline.h" 
75 #include "render_types.h" 
76 #include "renderdatabase.h" 
77
78 #ifdef HAVE_CONFIG_H
79 #include <config.h>
80 #endif
81
82 /* only needed now for a print, if its useful move to RG */
83 static float maxenergy; 
84
85 /* find the face with maximum energy to become shooter */
86 /* nb: _rr means rad-render version of existing radio call */
87 static VlakRen *findshoot_rr(Render *re)
88 {
89         RadFace *rf;
90         ObjectRen *obr;
91         VlakRen *vlr=NULL, *shoot;
92         float energy;
93         int a;
94         
95         shoot= NULL;
96         maxenergy= 0.0;
97         
98         for(obr=re->objecttable.first; obr; obr=obr->next) {
99                 for(a=0; a<obr->totvlak; a++) {
100                         if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
101                         if(vlr->radface) {
102                                 rf= vlr->radface;
103                                 rf->flag &= ~RAD_SHOOT;
104                                 
105                                 energy= rf->unshot[0]*rf->area;
106                                 energy+= rf->unshot[1]*rf->area;
107                                 energy+= rf->unshot[2]*rf->area;
108
109                                 if(energy>maxenergy) {
110                                         shoot= vlr;
111                                         maxenergy= energy;
112                                 }
113                         }
114                 }
115         }
116
117         if(shoot) {
118                 maxenergy/= RG.totenergy;
119                 if(maxenergy<RG.convergence) return NULL;
120                 shoot->radface->flag |= RAD_SHOOT;
121         }
122
123         return shoot;
124 }
125
126 static void backface_test_rr(Render *re, VlakRen *shoot)
127 {
128         ObjectRen *obr;
129         VlakRen *vlr=NULL;
130         RadFace *rf;
131         float tvec[3];
132         int a;
133         
134         /* backface testing */
135         for(obr=re->objecttable.first; obr; obr=obr->next) {
136                 for(a=0; a<obr->totvlak; a++) {
137                         if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
138                         if(vlr->radface && vlr!=shoot) {
139                                 rf= vlr->radface;
140                                 VecSubf(tvec, shoot->radface->cent, rf->cent);
141                                 
142                                 if(tvec[0]*rf->norm[0]+ tvec[1]*rf->norm[1]+ tvec[2]*rf->norm[2] < 0.0)
143                                         rf->flag |= RAD_BACKFACE;
144                         }
145                 }
146         }
147 }
148
149 static void clear_backface_test_rr(Render *re)
150 {
151         ObjectRen *obr;
152         VlakRen *vlr=NULL;
153         RadFace *rf;
154         int a;
155         
156         /* backface flag clear */
157         for(obr=re->objecttable.first; obr; obr=obr->next) {
158                 for(a=0; a<obr->totvlak; a++) {
159                         if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
160                         
161                         if(vlr->radface) {
162                                 rf= vlr->radface;
163                                 rf->flag &= ~RAD_BACKFACE;
164                         }
165                 }
166         }
167 }
168
169 extern RadView hemitop, hemiside; // radfactors.c
170
171 /* hemi-zbuffering, delivers formfactors array */
172 static void makeformfactors_rr(Render *re, VlakRen *shoot)
173 {
174         ObjectRen *obr;
175         VlakRen *vlr=NULL;
176         RadFace *rf;
177         float len, vec[3], up[3], side[3], tar[5][3], *fp;
178         int a;
179
180         memset(RG.formfactors, 0, sizeof(float)*RG.totelem);
181
182         /* set up hemiview */
183         /* first: upvector for hemitop, we use diagonal hemicubes to prevent aliasing */
184         
185         VecSubf(vec, shoot->v1->co, shoot->radface->cent);
186         Crossf(up, shoot->radface->norm, vec);
187         len= Normalize(up);
188         
189         VECCOPY(hemitop.up, up);
190         VECCOPY(hemiside.up, shoot->radface->norm);
191
192         Crossf(side, shoot->radface->norm, up);
193
194         /* five targets */
195         VecAddf(tar[0], shoot->radface->cent, shoot->radface->norm);
196         VecAddf(tar[1], shoot->radface->cent, up);
197         VecSubf(tar[2], shoot->radface->cent, up);
198         VecAddf(tar[3], shoot->radface->cent, side);
199         VecSubf(tar[4], shoot->radface->cent, side);
200
201         /* camera */
202         VECCOPY(hemiside.cam, shoot->radface->cent);
203         VECCOPY(hemitop.cam, shoot->radface->cent);
204
205         /* do it! */
206         VECCOPY(hemitop.tar, tar[0]);
207         hemizbuf(&hemitop);
208
209         for(a=1; a<5; a++) {
210                 VECCOPY(hemiside.tar, tar[a]);
211                 hemizbuf(&hemiside);
212         }
213
214         /* convert factors to real radiosity */
215         fp= RG.formfactors;
216
217         for(obr=re->objecttable.first; obr; obr=obr->next) {
218                 for(a=0; a<obr->totvlak; a++) {
219                         if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
220                         
221                         if(vlr->radface) {
222                                 rf= vlr->radface;
223                                 if(*fp!=0.0 && rf->area!=0.0) {
224                                         *fp *= shoot->radface->area/rf->area;
225                                         if(*fp>1.0) *fp= 1.0001;
226                                 }
227                                 fp++;
228                         }
229                 }
230         }
231 }
232
233 /* based at RG.formfactors array, distribute shoot energy over other faces */
234 static void applyformfactors_rr(Render *re, VlakRen *shoot)
235 {
236         ObjectRen *obr;
237         VlakRen *vlr=NULL;
238         RadFace *rf;
239         float *fp, *ref, unr, ung, unb, r, g, b;
240         int a;
241
242         unr= shoot->radface->unshot[0];
243         ung= shoot->radface->unshot[1];
244         unb= shoot->radface->unshot[2];
245
246         fp= RG.formfactors;
247         
248         for(obr=re->objecttable.first; obr; obr=obr->next) {
249                 for(a=0; a<obr->totvlak; a++) {
250                         if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
251                         
252                         if(vlr->radface) {
253                                 rf= vlr->radface;
254                                 if(*fp!= 0.0) {
255                                         
256                                         ref= &(vlr->mat->r);
257                                         
258                                         r= (*fp)*unr*ref[0];
259                                         g= (*fp)*ung*ref[1];
260                                         b= (*fp)*unb*ref[2];
261                                         
262                                         // if(rf->flag & RAD_BACKFACE) {
263                                         
264                                         rf->totrad[0]+= r;
265                                         rf->totrad[1]+= g;
266                                         rf->totrad[2]+= b;
267                                         
268                                         rf->unshot[0]+= r;
269                                         rf->unshot[1]+= g;
270                                         rf->unshot[2]+= b;
271                                 }
272                                 fp++;
273                         }
274                 }
275         }
276         /* shoot energy has been shot */
277         shoot->radface->unshot[0]= shoot->radface->unshot[1]= shoot->radface->unshot[2]= 0.0;
278 }
279
280
281 /* main loop for itterations */
282 static void progressiverad_rr(Render *re)
283 {
284         VlakRen *shoot;
285         float unshot[3];
286         int it= 0;
287         
288         shoot= findshoot_rr(re);
289         while( shoot ) {
290                 
291                 /* backfaces receive no energy, but are zbuffered... */
292                 backface_test_rr(re, shoot);
293                 
294                 /* ...unless it's two sided */
295                 if(shoot->radface->flag & RAD_TWOSIDED) {
296                         VECCOPY(unshot, shoot->radface->unshot);
297                         VecMulf(shoot->radface->norm, -1.0);
298                         makeformfactors_rr(re, shoot);
299                         applyformfactors_rr(re, shoot);
300                         VecMulf(shoot->radface->norm, -1.0);
301                         VECCOPY(shoot->radface->unshot, unshot);
302                 }
303
304                 /* hemi-zbuffers */
305                 makeformfactors_rr(re, shoot);
306                 /* based at RG.formfactors array, distribute shoot energy over other faces */
307                 applyformfactors_rr(re, shoot);
308                 
309                 it++;
310                 re->timecursor(it);
311                 
312                 clear_backface_test_rr(re);
313                 
314                 if(re->test_break()) break;
315                 if(RG.maxiter && RG.maxiter<=it) break;
316                 
317                 shoot= findshoot_rr(re);
318         }
319         printf(" Unshot energy:%f\n", 1000.0*maxenergy);
320         
321         re->timecursor((G.scene->r.cfra));
322 }
323
324 static RadFace *radfaces=NULL;
325
326 static void initradfaces(Render *re)    
327 {
328         ObjectRen *obr;
329         VlakRen *vlr= NULL;
330         RadFace *rf;
331         int a, b;
332         
333         /* globals */
334         RG.totenergy= 0.0;
335         RG.totpatch= 0;         // we count initial emittors here
336         RG.totelem= 0;          // total # faces are put here (so we can use radfactors.c calls)
337         /* size is needed for hemicube clipping */
338         RG.min[0]= RG.min[1]= RG.min[2]= 1.0e20;
339         RG.max[0]= RG.max[1]= RG.max[2]= -1.0e20;
340         
341         /* count first for fast malloc */
342         for(obr=re->objecttable.first; obr; obr=obr->next) {
343                 for(a=0; a<obr->totvlak; a++) {
344                         if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
345                         
346                         if(vlr->mat->mode & MA_RADIO) {
347                                 if(vlr->mat->emit > 0.0) {
348                                         RG.totpatch++;
349                                 }
350                                 RG.totelem++;
351                         }
352                 }
353         }
354                 
355 printf(" Rad elems: %d emittors %d\n", RG.totelem, RG.totpatch);        
356         if(RG.totelem==0 || RG.totpatch==0) return;
357
358         /* make/init radfaces */
359         rf=radfaces= MEM_callocN(RG.totelem*sizeof(RadFace), "radfaces");
360         for(obr=re->objecttable.first; obr; obr=obr->next) {
361                 for(a=0; a<obr->totvlak; a++) {
362                         if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
363                         
364                         if(vlr->mat->mode & MA_RADIO) {
365                                 
366                                 /* during render, vlr->n gets flipped/corrected, we cannot have that */
367                                 if(vlr->v4) CalcNormFloat4(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co, rf->norm);
368                                 else CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, rf->norm);
369                                 
370                                 rf->totrad[0]= vlr->mat->emit*vlr->mat->r;
371                                 rf->totrad[1]= vlr->mat->emit*vlr->mat->g;
372                                 rf->totrad[2]= vlr->mat->emit*vlr->mat->b;
373                                 VECCOPY(rf->unshot, rf->totrad);
374                                 
375                                 if(vlr->v4) {
376                                         rf->area= AreaQ3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co);
377                                         CalcCent4f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co);
378                                 }
379                                 else {
380                                         rf->area= AreaT3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co);
381                                         CalcCent3f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co);
382                                 }
383                                 
384                                 RG.totenergy+= rf->unshot[0]*rf->area;
385                                 RG.totenergy+= rf->unshot[1]*rf->area;
386                                 RG.totenergy+= rf->unshot[2]*rf->area;
387                                 
388                                 for(b=0; b<3; b++) {
389                                         RG.min[b]= MIN2(RG.min[b], rf->cent[b]);
390                                         RG.max[b]= MAX2(RG.max[b], rf->cent[b]);
391                                 }
392
393         // uncommented; this isnt satisfying, but i leave it in the code for now (ton)                  
394         //                      if(vlr->mat->translucency!=0.0) rf->flag |= RAD_TWOSIDED;
395                                 
396                                 vlr->radface= rf++;
397                         }
398                 }
399         }
400         RG.size[0]= (RG.max[0]- RG.min[0]);
401         RG.size[1]= (RG.max[1]- RG.min[1]);
402         RG.size[2]= (RG.max[2]- RG.min[2]);
403         RG.maxsize= MAX3(RG.size[0],RG.size[1],RG.size[2]);
404
405         /* formfactor array */
406         if(RG.formfactors) MEM_freeN(RG.formfactors);
407         if(RG.totelem)
408                 RG.formfactors= MEM_mallocN(sizeof(float)*RG.totelem, "formfactors");
409         else
410                 RG.formfactors= NULL;
411         
412 }
413
414 static void vecaddfac(float *vec, float *v1, float *v2, float fac)
415 {
416         vec[0]= v1[0] + fac*v2[0];
417         vec[1]= v1[1] + fac*v2[1];
418         vec[2]= v1[2] + fac*v2[2];
419
420 }
421
422 /* unused now, doesnt work..., find it in cvs of nov 2005 or older */
423 /* static void filter_rad_values(void) */
424
425
426 static void make_vertex_rad_values(Render *re)
427 {
428         ObjectRen *obr;
429         VertRen *v1=NULL;
430         VlakRen *vlr=NULL;
431         RadFace *rf;
432         float *col;
433         int a;
434
435         RG.igamma= 1.0/RG.gamma;
436         RG.radfactor= RG.radfac*pow(64*64, RG.igamma)/128.0; /* compatible with radio-tool */
437
438         /* accumulate vertexcolors */
439         for(obr=re->objecttable.first; obr; obr=obr->next) {
440                 for(a=0; a<obr->totvlak; a++) {
441                         if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++;
442                         
443                         if(vlr->radface) {
444                                 rf= vlr->radface;
445                                 
446                                 /* apply correction */
447                                 rf->totrad[0]= RG.radfactor*pow( rf->totrad[0], RG.igamma);
448                                 rf->totrad[1]= RG.radfactor*pow( rf->totrad[1], RG.igamma);
449                                 rf->totrad[2]= RG.radfactor*pow( rf->totrad[2], RG.igamma);
450                                 
451                                 /* correct rf->rad values for color */
452                                 if(vlr->mat->r > 0.0) rf->totrad[0]/= vlr->mat->r;
453                                 if(vlr->mat->g > 0.0) rf->totrad[1]/= vlr->mat->g;
454                                 if(vlr->mat->b > 0.0) rf->totrad[2]/= vlr->mat->b;
455                                 
456                                 col= RE_vertren_get_rad(obr, vlr->v1, 1);
457                                 vecaddfac(col, col, rf->totrad, rf->area); 
458                                 col[3]+= rf->area;
459                                 
460                                 col= RE_vertren_get_rad(obr, vlr->v2, 1);
461                                 vecaddfac(col, col, rf->totrad, rf->area); 
462                                 col[3]+= rf->area;
463                                 
464                                 col= RE_vertren_get_rad(obr, vlr->v3, 1);
465                                 vecaddfac(col, col, rf->totrad, rf->area); 
466                                 col[3]+= rf->area;
467
468                                 if(vlr->v4) {
469                                         col= RE_vertren_get_rad(obr, vlr->v4, 1);
470                                         vecaddfac(col, col, rf->totrad, rf->area); 
471                                         col[3]+= rf->area;
472                                 }
473                         }
474                 }
475         
476                 /* make vertex colors */
477                 for(a=0; a<obr->totvert; a++) {
478                         if((a & 255)==0) v1= RE_findOrAddVert(obr, a); else v1++;
479                         
480                         col= RE_vertren_get_rad(obr, v1, 0);
481                         if(col && col[3]>0.0) {
482                                 col[0]/= col[3];
483                                 col[1]/= col[3];
484                                 col[2]/= col[3];
485                         }
486                 }
487         }
488 }
489
490 /* main call, extern */
491 void do_radio_render(Render *re)
492 {
493         if(G.scene->radio==NULL) add_radio();
494         freeAllRad();   /* just in case radio-tool is still used */
495         
496         set_radglobal(); /* init the RG struct */
497         RG.re= re;              /* only used by hemizbuf(), prevents polluting radio code all over */
498         
499         initradfaces(re);        /* add radface structs to render faces */
500         if(RG.totenergy>0.0) {
501
502                 initradiosity();        /* LUT's */
503                 inithemiwindows();      /* views, need RG.maxsize for clipping */
504         
505                 progressiverad_rr(re); /* main radio loop */
506                 
507                 make_vertex_rad_values(re); /* convert face energy to vertex ones */
508
509         }
510         
511         freeAllRad();   /* luts, hemis, sets vars at zero */
512 }
513
514 /* free call, after rendering, extern */
515 void end_radio_render(void)
516 {
517         if(radfaces) MEM_freeN(radfaces);
518         radfaces= NULL;
519 }
520