Initial revision
[blender.git] / source / blender / radiosity / intern / source / raddisplay.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
33     raddisplay.c        nov/dec 1992
34                                         may 1999
35
36     - drawing
37     - color calculation for display during solving
38
39     $Id$
40
41  *************************************** */
42
43 #include <stdlib.h>
44 #include <math.h>
45
46 #ifdef WIN32
47 #include "BLI_winstuff.h"
48 #endif
49
50 #include "BLI_blenlib.h"
51
52 #include "DNA_screen_types.h"
53 #include "DNA_view3d_types.h"
54
55 #include "BKE_global.h"
56 #include "BKE_main.h"
57
58 #include "BIF_gl.h"
59 #include "BIF_screen.h"
60 #include "BIF_space.h"
61 #include "BIF_mywindow.h"
62
63 #include "radio.h"
64
65 /* Mij afspraak is cpack een getal dat als 0xFFaa66 of zo kan worden
66  * uitgedrukt. Is dus gevoelig voor endian. Met deze define wordt het
67  * altijd goed afgebeeld */
68 #define cpack(x)   glColor3ub( ((x)&0xFF), (((x)>>8)&0xFF), (((x)>>16)&0xFF) )
69
70 char calculatecolor(float col)
71 {
72         int b;
73
74         if(RG.gamma==1.0) {
75                 b= RG.radfactor*col;
76         }
77         else if(RG.gamma==2.0) {
78                 b= RG.radfactor*sqrt(col);
79         }
80         else {
81                 b= RG.radfactor*pow(col, RG.igamma);
82         }
83         
84         if(b>255) b=255;
85         return b;
86 }
87
88 void make_node_display()
89 {
90         RNode *rn, **el;
91         int a;
92         char *charcol;
93
94         RG.igamma= 1.0/RG.gamma;
95         RG.radfactor= RG.radfac*pow(64*64, RG.igamma);
96
97         el= RG.elem;
98         for(a=RG.totelem; a>0; a--, el++) {
99                 rn= *el;
100                 charcol= (char *)&( rn->col );
101
102                 charcol[3]= calculatecolor(rn->totrad[0]);
103                 charcol[2]= calculatecolor(rn->totrad[1]);
104                 charcol[1]= calculatecolor(rn->totrad[2]);
105                 
106                 /* gouraudcolor */
107                 *(rn->v1+3)= 0;
108                 *(rn->v2+3)= 0;
109                 *(rn->v3+3)= 0;
110                 if(rn->v4) *(rn->v4+3)= 0;
111         }
112         
113         el= RG.elem;
114         for(a=RG.totelem; a>0; a--, el++) {
115                 rn= *el;
116                 addaccuweight( (char *)&(rn->col), (char *)(rn->v1+3), 16 );
117                 addaccuweight( (char *)&(rn->col), (char *)(rn->v2+3), 16 );
118                 addaccuweight( (char *)&(rn->col), (char *)(rn->v3+3), 16 );
119                 if(rn->v4) addaccuweight( (char *)&(rn->col), (char *)(rn->v4+3), 16 );
120         }
121 }
122
123 void drawnodeWire(RNode *rn)
124 {
125
126         if(rn->down1) {
127                 drawnodeWire(rn->down1);
128                 drawnodeWire(rn->down2);
129         }
130         else {
131                 glBegin(GL_LINE_LOOP);
132                         glVertex3fv(rn->v1);
133                         glVertex3fv(rn->v2);
134                         glVertex3fv(rn->v3);
135                         if(rn->type==4) glVertex3fv(rn->v4);
136                 glEnd();
137         }
138 }
139
140 void drawsingnodeWire(RNode *rn)
141 {
142         
143         glBegin(GL_LINE_LOOP);
144                 glVertex3fv(rn->v1);
145                 glVertex3fv(rn->v2);
146                 glVertex3fv(rn->v3);
147                 if(rn->type==4) glVertex3fv(rn->v4);
148         glEnd();
149 }
150
151 void drawnodeSolid(RNode *rn)
152 {
153         char *cp;
154         
155         if(rn->down1) {
156                 drawnodeSolid(rn->down1);
157                 drawnodeSolid(rn->down2);
158         }
159         else {
160                 cp= (char *)&rn->col;
161                 glColor3ub(cp[3], cp[2], cp[1]);
162                 glBegin(GL_POLYGON);
163                         glVertex3fv(rn->v1);
164                         glVertex3fv(rn->v2);
165                         glVertex3fv(rn->v3);
166                         if(rn->type==4) glVertex3fv(rn->v4);
167                 glEnd();
168         }
169 }
170
171 void drawnodeGour(RNode *rn)
172 {
173         char *cp;
174         
175         if(rn->down1) {
176                 drawnodeGour(rn->down1);
177                 drawnodeGour(rn->down2);
178         }
179         else {
180                 glBegin(GL_POLYGON);
181                         cp= (char *)(rn->v1+3);
182                         glColor3ub(cp[3], cp[2], cp[1]);
183                         glVertex3fv(rn->v1);
184                         
185                         cp= (char *)(rn->v2+3);
186                         glColor3ub(cp[3], cp[2], cp[1]);
187                         glVertex3fv(rn->v2);
188                         
189                         cp= (char *)(rn->v3+3);
190                         glColor3ub(cp[3], cp[2], cp[1]);
191                         glVertex3fv(rn->v3);
192                         
193                         if(rn->type==4) {
194                                 cp= (char *)(rn->v4+3);
195                                 glColor3ub(cp[3], cp[2], cp[1]);
196                                 glVertex3fv(rn->v4);
197                         }
198                 glEnd();
199         }
200 }
201
202 void drawpatch_ext(RPatch *patch, unsigned int col)
203 {
204         ScrArea *sa, *oldsa;
205         
206         glDrawBuffer(GL_FRONT);
207         if(G.zbuf) glDisable(GL_DEPTH_TEST);
208
209         cpack(col);
210
211         oldsa= curarea;
212
213         sa= G.curscreen->areabase.first;
214         while(sa) {
215                 if (sa->spacetype==SPACE_VIEW3D) {
216                         /* hier mywinget() gebruiken: anders wordt in header getekend */
217                         if(sa->win != mywinget()) areawinset(sa->win);
218                         drawnodeWire(patch->first);
219                 }
220                 sa= sa->next;
221         }
222
223         if(oldsa && oldsa!=curarea) areawinset(oldsa->win);
224
225         glDrawBuffer(GL_BACK);
226         if(G.zbuf) glEnable(GL_DEPTH_TEST);
227 }
228
229 void drawnode_ext(RNode *rn, unsigned int col)
230 {
231         
232         glDrawBuffer(GL_FRONT);
233         if(G.zbuf) glDisable(GL_DEPTH_TEST);
234
235         cpack(col);
236         
237         drawnodeWire(rn);
238
239         glDrawBuffer(GL_BACK);
240         if(G.zbuf) glEnable(GL_DEPTH_TEST);
241 }
242
243 void drawOverflowElem()
244 {
245         RNode **el, *rn;
246         float *fp;
247         int a;
248
249         glDrawBuffer(GL_FRONT);
250         if(G.zbuf) glDisable(GL_DEPTH_TEST);
251
252         cpack(0xFF9900);
253
254         el= RG.elem;
255         fp= RG.formfactors;
256         for(a=0; a<RG.totelem; a++, el++, fp++) {
257                 if(*fp>1.0) {
258                         rn= *el;
259                         glBegin(GL_LINE_LOOP);
260                                 glVertex3fv( rn->v1);
261                                 glVertex3fv( rn->v2);
262                                 glVertex3fv( rn->v3);
263                                 if(rn->type==4) glVertex3fv( rn->v4);
264                         glEnd();
265                 }
266         }
267
268         glDrawBuffer(GL_BACK);
269         if(G.zbuf) glEnable(GL_DEPTH_TEST);
270 }
271
272 void drawfaceGour(Face *face)
273 {
274         char *cp;
275         
276         glBegin(GL_POLYGON);
277                 cp= (char *)(face->v1+3);
278                 glColor3ub(cp[3], cp[2], cp[1]);
279                 glVertex3fv(face->v1);
280                 
281                 cp= (char *)(face->v2+3);
282                 glColor3ub(cp[3], cp[2], cp[1]);
283                 glVertex3fv(face->v2);
284                 
285                 cp= (char *)(face->v3+3);
286                 glColor3ub(cp[3], cp[2], cp[1]);
287                 glVertex3fv(face->v3);
288                 
289                 if(face->v4) {
290                         cp= (char *)(face->v4+3);
291                         glColor3ub(cp[3], cp[2], cp[1]);
292                         glVertex3fv(face->v4);
293                 }
294         glEnd();
295         
296 }
297
298 void drawfaceSolid(Face *face)
299 {
300         char *cp;
301         
302         cp= (char *)&face->col;
303         glColor3ub(cp[3], cp[2], cp[1]);
304         
305         glBegin(GL_POLYGON);
306                 glVertex3fv(face->v1);
307                 glVertex3fv(face->v2);
308                 glVertex3fv(face->v3);
309                 if(face->v4) {
310                         glVertex3fv(face->v4);
311                 }
312         glEnd();
313         
314 }
315
316 void drawfaceWire(Face *face)
317 {
318         char *cp;
319         
320         cp= (char *)&face->col;
321         glColor3ub(cp[3], cp[2], cp[1]);
322
323         glBegin(GL_LINE_LOOP);
324                 glVertex3fv(face->v1);
325                 glVertex3fv(face->v2);
326                 glVertex3fv(face->v3);
327                 if(face->v4) {
328                         glVertex3fv(face->v4);
329                 }
330         glEnd();
331         
332 }
333
334 void drawsquare(float *cent, float size, short cox, short coy)
335 {
336         float vec[3];   
337
338         vec[0]= cent[0];
339         vec[1]= cent[1];
340         vec[2]= cent[2];
341         
342         glBegin(GL_LINE_LOOP);
343                 vec[cox]+= .5*size;
344                 vec[coy]+= .5*size;
345                 glVertex3fv(vec);       
346                 vec[coy]-= size;
347                 glVertex3fv(vec);
348                 vec[cox]-= size;
349                 glVertex3fv(vec);
350                 vec[coy]+= size;
351                 glVertex3fv(vec);
352         glEnd();        
353 }
354
355 void drawlimits()
356 {
357         /* centreer rond cent */
358         short cox=0, coy=1;
359         
360         if((RG.flag & 3)==2) coy= 2;
361         if((RG.flag & 3)==3) {
362                 cox= 1; 
363                 coy= 2; 
364         }
365         
366         cpack(0);
367         drawsquare(RG.cent, sqrt(RG.patchmax), cox, coy);
368         drawsquare(RG.cent, sqrt(RG.patchmin), cox, coy);
369
370         drawsquare(RG.cent, sqrt(RG.elemmax), cox, coy);
371         drawsquare(RG.cent, sqrt(RG.elemmin), cox, coy);
372
373         cpack(0xFFFFFF);
374         drawsquare(RG.cent, sqrt(RG.patchmax), cox, coy);
375         drawsquare(RG.cent, sqrt(RG.patchmin), cox, coy);
376         cpack(0xFFFF00);
377         drawsquare(RG.cent, sqrt(RG.elemmax), cox, coy);
378         drawsquare(RG.cent, sqrt(RG.elemmin), cox, coy);
379         
380 }
381
382 void setcolNode(RNode *rn, unsigned int *col)
383 {
384
385         if(rn->down1) {
386                  setcolNode(rn->down1, col);
387                  setcolNode(rn->down2, col);
388         }
389         rn->col= *col;
390         
391         *((unsigned int *)rn->v1+3)= *col;
392         *((unsigned int *)rn->v2+3)= *col;
393         *((unsigned int *)rn->v3+3)= *col;
394         if(rn->v4) *((unsigned int *)rn->v4+3)= *col;
395 }
396
397 void pseudoAmb()
398 {
399         RPatch *rp;
400         float fac;
401         char col[4];
402         
403         /* zet pseudo ambient kleuren in de nodes */
404
405         rp= RG.patchbase.first;
406         while(rp) {
407
408                 if(rp->emit[0]!=0.0 || rp->emit[1]!=0.0 || rp->emit[2]!=0.0) {
409                         col[1]= col[2]= col[3]= 255;
410                 }
411                 else {
412                         fac= rp->norm[0]+ rp->norm[1]+ rp->norm[2];
413                         fac= 225.0*(3+fac)/6.0;
414                         
415                         col[3]= fac*rp->ref[0];
416                         col[2]= fac*rp->ref[1];
417                         col[1]= fac*rp->ref[2];
418                 }
419                 
420                 setcolNode(rp->first, (unsigned int *)col);
421                 
422                 rp= rp->next;
423         }
424 }
425
426 void RAD_drawall(int depth_is_on)
427 {
428         /* maakt afbeelding van elements of van faces */
429         Face *face = NULL;
430         RNode **el;
431         RPatch *rp;
432         int a;
433
434         if(!depth_is_on) {
435                 glEnable(GL_DEPTH_TEST);
436                 glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT);
437         }
438         
439         if(RG.totface) {
440                 if(RG.drawtype==DTGOUR) {
441                         glShadeModel(GL_SMOOTH);
442                         for(a=0; a<RG.totface; a++) {
443                                 RAD_NEXTFACE(a);
444                                 
445                                 drawfaceGour(face);
446                         }
447                 }
448                 else if(RG.drawtype==DTSOLID) {
449                         for(a=0; a<RG.totface; a++) {
450                                 RAD_NEXTFACE(a);
451                                 
452                                 drawfaceSolid(face);
453                         }
454                 }
455                 else {
456                         if(!(get_qual()&LR_SHIFTKEY)) {
457
458                                 for(a=0; a<RG.totface; a++) {
459                                         RAD_NEXTFACE(a);
460                                         
461                                         drawfaceWire(face);
462                                 }
463                         }
464                         else {
465                                 cpack(0);
466                                 rp= RG.patchbase.first;
467                                 while(rp) {
468                                         drawsingnodeWire(rp->first);
469                                         rp= rp->next;
470                                 }
471                         }
472                 }
473         }
474         else {
475                 el= RG.elem;
476                 if(RG.drawtype==DTGOUR) {
477                         glShadeModel(GL_SMOOTH);
478                         for(a=RG.totelem; a>0; a--, el++) {
479                                 drawnodeGour(*el);
480                         }
481                 }
482                 else if(RG.drawtype==DTSOLID) {
483                         for(a=RG.totelem; a>0; a--, el++) {
484                                 drawnodeSolid(*el);
485                         }
486                 }
487                 else {
488                         cpack(0);
489                         for(a=RG.totelem; a>0; a--, el++) {
490                                 drawnodeWire(*el);
491                         }
492                 }
493         }
494         glShadeModel(GL_FLAT);
495         
496         if(RG.totpatch) {
497                 if(RG.flag & 3) {
498                         if(depth_is_on) glDisable(GL_DEPTH_TEST);
499                         drawlimits();
500                         if(depth_is_on) glEnable(GL_DEPTH_TEST);
501                 }
502         }       
503         if(!depth_is_on) {
504                 glDisable(GL_DEPTH_TEST);
505         }
506 }
507
508 void rad_forcedraw()
509 {
510         ScrArea *sa, *oldsa;
511         
512         oldsa= curarea;
513
514         sa= G.curscreen->areabase.first;
515         while(sa) {
516                 if (sa->spacetype==SPACE_VIEW3D) {
517                         /* hier mywinget() gebruiken: anders wordt in header getekend */
518                         if(sa->win != mywinget()) areawinset(sa->win);
519                         scrarea_do_windraw(sa);
520                 }
521                 sa= sa->next;
522         }
523         screen_swapbuffers();
524         
525         if(oldsa && oldsa!=curarea) areawinset(oldsa->win);
526 }
527