Reverted incorrect merge (missing files)
[blender.git] / source / blender / radiosity / intern / source / radio.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
30     radio.c     nov/dec 1992
31                         may 1999
32
33     $Id$
34
35     - mainloop
36     - interactivity
37
38         
39         - PREPROCES
40                 - collect meshes 
41                 - spitconnected (all faces with different color and normals)
42                 - setedgepointers (nodes pointing to neighbours)
43
44         - EDITING
45                 - min-max patch en min-max element size
46                 - using this info patches subdividing
47                 - lamp subdivide
48         
49                 - if there are too many lamps for subdivide shooting:
50                         - temporal join patches 
51         
52         - SUBDIVIDE SHOOTING
53                 - except for last shooting, this defines patch subdivide
54                 - if subdivided patches still > 2*minsize : continue
55                 - at the end create as many elements as possible
56                 - als store if lamp (can still) cause subdivide.
57                 
58         - REFINEMENT SHOOTING
59                 - test for overflows (shootpatch subdivide)
60                 - testen for extreme color transitions:
61                         - if possible: shootpatch subdivide
62                         - elements subdivide = start over ?
63                 - continue itterate until ?
64                 
65         - DEFINITIVE SHOOTING
66                 - user indicates how many faces maximum and duration of itteration.
67                 
68         - POST PROCESS
69                 - join element- nodes when nothing happens in it (filter nodes, filter faces)
70                 - define gamma & mul
71
72  *************************************** */
73
74 #include <math.h>
75 #include <string.h>
76
77 #include "MEM_guardedalloc.h"
78 #include "PIL_time.h"
79
80 #include "BLI_blenlib.h"
81
82 #include "DNA_object_types.h"
83 #include "DNA_radio_types.h"
84 #include "DNA_scene_types.h"
85 #include "DNA_screen_types.h"
86
87 #include "BKE_customdata.h"
88 #include "BKE_global.h"
89 #include "BKE_main.h"
90
91 #include "radio.h"
92
93 #ifdef HAVE_CONFIG_H
94 #include <config.h>
95 #endif
96
97 /* locals? This one was already done in radio.h... */
98 /*  void rad_status_str(char *str); */
99
100 RadGlobal RG= {0, 0};
101
102 void freeAllRad(Scene *scene)
103 {
104         Base *base;
105         extern int Ntotvert, Ntotnode, Ntotpatch;
106         
107         /* clear flag that disables drawing the meshes */
108         if(scene) {
109                 base= (scene->base.first);
110                 while(base) {           
111                         if(base->object->type==OB_MESH) {
112                                 base->flag &= ~OB_RADIO;
113                         }
114                         base= base->next;
115                 }
116         }
117         
118         free_fastAll(); /* verts, nodes, patches */
119         RG.patchbase.first= RG.patchbase.last= 0;
120         Ntotvert= Ntotnode= Ntotpatch= 0;
121         
122         closehemiwindows();             /* not real windows anymore... */
123         if(RG.elem) MEM_freeN(RG.elem);
124         RG.elem= 0;
125         if(RG.verts) MEM_freeN(RG.verts);
126         RG.verts= 0;
127         if(RG.topfactors) MEM_freeN(RG.topfactors);
128         RG.topfactors= 0;
129         if(RG.sidefactors) MEM_freeN(RG.sidefactors);
130         RG.sidefactors= 0;
131         if(RG.formfactors) MEM_freeN(RG.formfactors);
132         RG.formfactors= 0;
133         if(RG.index) MEM_freeN(RG.index);
134         RG.index= 0;
135         if(RG.facebase) {
136                 init_face_tab();        /* frees all tables */
137                 MEM_freeN(RG.facebase);
138                 RG.facebase= 0;
139         }
140
141         if(RG.mfdata) {
142                 CustomData_free(RG.mfdata, RG.mfdatatot);
143                 MEM_freeN(RG.mfdata);
144                 MEM_freeN(RG.mfdatanodes);
145                 RG.mfdatanodes= NULL;
146                 RG.mfdata= NULL;
147                 RG.mfdatatot= 0;
148         }
149         RG.totelem= RG.totpatch= RG.totvert= RG.totface= RG.totlamp= RG.totmat= 0;      
150 }
151
152 int rad_phase()
153 {
154         int flag= 0;
155         
156         if(RG.totpatch) flag |= RAD_PHASE_PATCHES;
157         if(RG.totface) flag |= RAD_PHASE_FACES;
158         
159         return flag;
160 }
161
162 void rad_status_str(char *str)
163 {
164         extern int totfastmem;
165         int tot;
166         char *phase;
167         
168         tot= (RG.totface*sizeof(Face))/1024;
169         tot+= totfastmem/1024;
170         
171         if(RG.phase==RAD_SHOOTE) phase= "Phase: ELEMENT SUBD,  ";
172         else if(RG.phase==RAD_SHOOTP) phase= "Phase: PATCH SUBD,  ";
173         else if(RG.phase==RAD_SOLVE) phase= "Phase: SOLVE,  ";
174         else if(RG.totpatch==0) phase= "Phase: COLLECT MESHES ";
175         else if(RG.totface) phase= "Phase: FINISHED,  ";
176         else phase= "Phase: INIT, ";
177         
178         if(RG.totpatch==0) strcpy(str, phase);
179         else sprintf(str, "%s TotPatch: %d TotElem: %d Emit: %d Faces %d Mem: %d k ", phase, RG.totpatch, RG.totelem, RG.totlamp, RG.totface, tot);
180
181         if(RG.phase==RAD_SOLVE) strcat(str, "(press ESC to stop)");
182 }
183
184 void rad_printstatus()
185 {
186         /* actions always are started from a buttonswindow */
187 // XX   if(curarea) {
188 //              scrarea_do_windraw(curarea);
189 //              screen_swapbuffers();
190 //      }
191 }
192
193 void rad_setlimits(Scene *scene)
194 {
195         Radio *rad= scene->radio;
196         float fac;
197         
198         fac= 0.0005*rad->pama;
199         RG.patchmax= RG.maxsize*fac;
200         RG.patchmax*= RG.patchmax;
201         fac= 0.0005*rad->pami;
202         RG.patchmin= RG.maxsize*fac;
203         RG.patchmin*= RG.patchmin;
204
205         fac= 0.0005*rad->elma;
206         RG.elemmax= RG.maxsize*fac;
207         RG.elemmax*= RG.elemmax;
208         fac= 0.0005*rad->elmi;
209         RG.elemmin= RG.maxsize*fac;
210         RG.elemmin*= RG.elemmin;
211 }
212
213 void set_radglobal(Scene *scene)
214 {
215         /* always call before any action is performed */
216         Radio *rad= scene->radio;
217
218         if(RG.radio==0) {
219                 /* firsttime and to be sure */
220                 memset(&RG, 0, sizeof(RadGlobal));
221         }
222         
223         if(rad==0) return;
224
225         if(rad != RG.radio) {
226                 if(RG.radio) freeAllRad(scene);
227                 memset(&RG, 0, sizeof(RadGlobal));
228                 RG.radio= rad;
229         }
230         
231         RG.hemires= rad->hemires & 0xFFF0;
232         RG.drawtype= rad->drawtype;
233         RG.flag= rad->flag;
234         RG.subshootp= rad->subshootp;
235         RG.subshoote= rad->subshoote;
236         RG.nodelim= rad->nodelim;
237         RG.maxsublamp= rad->maxsublamp;
238         RG.maxnode= 2*rad->maxnode;             /* in button:max elem, subdividing! */
239         RG.convergence= rad->convergence/1000.0;
240         RG.radfac= rad->radfac;
241         RG.gamma= rad->gamma;
242         RG.maxiter= rad->maxiter;
243         
244         RG.re= NULL;    /* struct render, for when call it from render engine */
245         
246         rad_setlimits(scene);
247 }
248
249 /* called from buttons.c */
250 void add_radio(Scene *scene)
251 {
252         Radio *rad;
253         
254         if(scene->radio) MEM_freeN(scene->radio);
255         rad= scene->radio= MEM_callocN(sizeof(Radio), "radio");
256
257         rad->hemires= 300;
258         rad->convergence= 0.1;
259         rad->radfac= 30.0;
260         rad->gamma= 2.0;
261         rad->drawtype= RAD_SOLID;
262         rad->subshootp= 1;
263         rad->subshoote= 2;
264         rad->maxsublamp= 0;
265         
266         rad->pama= 500;
267         rad->pami= 200;
268         rad->elma= 100;
269         rad->elmi= 20;
270         rad->nodelim= 0;
271         rad->maxnode= 10000;
272         rad->maxiter= 120;      // arbitrary
273         rad->flag= 2;
274         set_radglobal(scene);
275 }
276
277 void delete_radio(Scene *scene)
278 {
279         freeAllRad(scene);
280         if(scene->radio) MEM_freeN(scene->radio);
281         scene->radio= 0;
282
283         RG.radio= 0;
284 }
285
286 int rad_go(Scene *scene)        /* return 0 when user escapes */
287 {
288         double stime= PIL_check_seconds_timer();
289         int retval;
290         
291         if(RG.totface) return 0;
292
293         G.afbreek= 0;
294         
295         set_radglobal(scene);
296         initradiosity();        /* LUT's */
297         inithemiwindows();      /* views */
298         
299         maxsizePatches();
300
301         setnodelimit(RG.patchmin);
302         RG.phase= RAD_SHOOTP;
303         subdivideshootPatches(RG.subshootp);
304
305         setnodelimit(RG.elemmin);
306         RG.phase= RAD_SHOOTE;
307         subdivideshootElements(RG.subshoote);
308
309         setnodelimit(RG.patchmin);
310         subdividelamps();
311
312         setnodelimit(RG.elemmin);
313
314         RG.phase= RAD_SOLVE;
315         subdiv_elements();
316
317         progressiverad();
318
319         removeEqualNodes(RG.nodelim);
320
321         make_face_tab();        /* now anchored */
322
323         closehemiwindows();
324         RG.phase= 0;
325
326         stime= PIL_check_seconds_timer()-stime;
327         printf("Radiosity solving time: %dms\n", (int) (stime*1000));
328
329         if(G.afbreek==1) retval= 1;
330         else retval= 0;
331         
332         G.afbreek= 0;
333         
334         return retval;
335 }
336
337 void rad_subdivshootpatch(Scene *scene)
338 {
339         
340         if(RG.totface) return;
341
342         G.afbreek= 0;
343
344         set_radglobal(scene);
345         initradiosity();        /* LUT's */
346         inithemiwindows();      /* views */
347         
348         subdivideshootPatches(1);
349
350         removeEqualNodes(RG.nodelim);
351         closehemiwindows();
352         
353 // XXX  allqueue(REDRAWVIEW3D, 1);
354 }
355
356 void rad_subdivshootelem(Scene *scene)
357 {
358         
359         if(RG.totface) return;
360
361         G.afbreek= 0;
362
363         set_radglobal(scene);
364         initradiosity();        /* LUT's */
365         inithemiwindows();      /* views */
366         
367         subdivideshootElements(1);
368
369         removeEqualNodes(RG.nodelim);
370         closehemiwindows();
371         
372 // XXX  allqueue(REDRAWVIEW3D, 1);
373 }
374
375 void rad_limit_subdivide(Scene *scene)
376 {
377
378         if(scene->radio==0) return;
379
380         set_radglobal(scene);
381
382         if(RG.totpatch==0) {
383                 /* printf("exit: no relevant data\n"); */
384                 return;
385         }
386         
387         maxsizePatches();
388
389         init_face_tab();        /* free faces */
390 }