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