Initial revision
[blender.git] / source / blender / src / previewrender.c
1 /* previewrender.c              GRAPHICS
2  * 
3  * maart 95
4  * 
5  * $Id$
6  *
7  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version. The Blender
13  * Foundation also sells licenses for use in proprietary software under
14  * the Blender License.  See http://www.blender.org/BL/ for information
15  * about this.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  *
26  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
27  * All rights reserved.
28  *
29  * The Original Code is: all of this file.
30  *
31  * Contributor(s): none yet.
32  *
33  * ***** END GPL/BL DUAL LICENSE BLOCK *****
34  */
35
36 /* global includes */
37
38 #include <stdlib.h>
39 #include <math.h>
40
41 #ifndef WIN32
42 #include <unistd.h>
43 #else
44 #include <io.h>
45 #endif   
46 #include "MEM_guardedalloc.h"
47 #include "BLI_arithb.h"
48 #include "BKE_utildefines.h"
49
50 #include "MTC_matrixops.h"
51
52 #include "render.h"
53 #include "mydevice.h"
54
55 #include "DNA_texture_types.h"
56 #include "DNA_world_types.h"
57 #include "DNA_camera_types.h"
58 #include "DNA_image_types.h"
59 #include "DNA_object_types.h"
60 #include "DNA_lamp_types.h"
61 #include "DNA_space_types.h"
62 #include "DNA_scene_types.h"
63 #include "DNA_screen_types.h"
64
65 #include "BKE_global.h"
66 #include "BKE_image.h"
67 #include "BKE_texture.h"
68 #include "BKE_material.h"
69 #include "BKE_world.h"
70 #include "BKE_texture.h"
71
72 #include "BIF_gl.h"
73 #include "BIF_screen.h"
74 #include "BIF_space.h"          /* allqueue */
75 #include "BIF_drawimage.h"      /* rectwrite_part */
76 //#include "BIF_previewrender.h"
77 #include "BIF_mywindow.h"
78
79 #include "RE_renderconverter.h"
80
81 //#include "mydevice.h"
82
83 #define PR_RECTX        101
84 #define PR_RECTY        101
85 #define PR_XMIN         10
86 #define PR_YMIN         10
87 #define PR_XMAX         190
88 #define PR_YMAX         190
89
90 #define PR_FACY         (PR_YMAX-PR_YMIN-4)/(PR_RECTY)
91
92 static rcti prerect;
93 static int pr_sizex, pr_sizey;
94 static float pr_facx, pr_facy;
95
96
97 /* implementation */
98
99 static short snijpunt(float *v1, 
100                                           float *v2, 
101                                           float *v3, 
102                                           float *rtlabda, 
103                                           float *ray1, 
104                                           float *ray2)
105 {
106         float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22;
107         float m0,m1,m2,deeldet,det1,det2,det3;
108         float rtu, rtv;
109         
110         t00= v3[0]-v1[0];
111         t01= v3[1]-v1[1];
112         t02= v3[2]-v1[2];
113         t10= v3[0]-v2[0];
114         t11= v3[1]-v2[1];
115         t12= v3[2]-v2[2];
116         t20= ray1[0]-ray2[0];
117         t21= ray1[1]-ray2[1];
118         t22= ray1[2]-ray2[2];
119         
120         x0= t11*t22-t12*t21;
121         x1= t12*t20-t10*t22;
122         x2= t10*t21-t11*t20;
123
124         deeldet= t00*x0+t01*x1+t02*x2;
125         if(deeldet!=0.0) {
126                 m0= ray1[0]-v3[0];
127                 m1= ray1[1]-v3[1];
128                 m2= ray1[2]-v3[2];
129                 det1= m0*x0+m1*x1+m2*x2;
130                 rtu= det1/deeldet;
131                 if(rtu<=0.0) {
132                         det2= t00*(m1*t22-m2*t21);
133                         det2+= t01*(m2*t20-m0*t22);
134                         det2+= t02*(m0*t21-m1*t20);
135                         rtv= det2/deeldet;
136                         if(rtv<=0.0) {
137                                 if(rtu+rtv>= -1.0) {
138                                         
139                                         det3=  m0*(t12*t01-t11*t02);
140                                         det3+= m1*(t10*t02-t12*t00);
141                                         det3+= m2*(t11*t00-t10*t01);
142                                         *rtlabda= det3/deeldet;
143                                         
144                                         if(*rtlabda>=0.0 && *rtlabda<=1.0) {
145                                                 return 1;
146                                         }
147                                 }
148                         }
149                 }
150         }
151         return 0;
152 }
153
154 static float rcubev[7][3]= {
155         {-0.002055,  6.627364, -3.369742}, 
156         {-6.031684, -3.750204, -1.992980}, 
157         {-6.049086,  3.817431,  1.969788}, 
158         { 6.031685,  3.833064,  1.992979}, 
159         { 6.049086, -3.734571, -1.969787}, 
160         { 0.002054, -6.544502,  3.369744}, 
161         {-0.015348,  1.023131,  7.332510} };
162
163 static int rcubi[3][4]= {
164         {3,  6,  5,  4},
165         {1,  5,  6,  2},  
166         {3,  0,  2,  6} };
167
168
169 static int ray_previewrender(int x, 
170                                                          int y, 
171                                                          float *vec)
172 {
173         float scalef= 12.8/100.0;
174         float ray1[3], ray2[3];
175         float minlabda, labda;
176         int totface= 3, hitface= -1;
177         int a;
178
179         ray1[0]= ray2[0]= x*scalef;
180         ray1[1]= ray2[1]= y*scalef;
181         ray1[2]= -10.0;
182         ray2[2]= 10.0;
183         
184         minlabda= 1.0;
185         for(a=0; a<totface; a++) {
186                 if(snijpunt( rcubev[rcubi[a][0]], rcubev[rcubi[a][1]], rcubev[rcubi[a][2]], &labda, ray1, ray2)) {
187                         if( labda < minlabda) {
188                                 minlabda= labda;
189                                 hitface= a;
190                         }
191                 }
192                 if(snijpunt( rcubev[rcubi[a][0]], rcubev[rcubi[a][2]], rcubev[rcubi[a][3]], &labda, ray1, ray2)) {
193                         if( labda < minlabda) {
194                                 minlabda= labda;
195                                 hitface= a;
196                         }
197                 }
198         }
199         
200         if(hitface > -1) {
201                 
202                 CalcNormFloat(rcubev[rcubi[hitface][0]], rcubev[rcubi[hitface][1]], rcubev[rcubi[hitface][2]], R.vn);
203                 
204                 vec[0]= (minlabda*(ray1[0]-ray2[0])+ray2[0])/3.7;
205                 vec[1]= (minlabda*(ray1[1]-ray2[1])+ray2[1])/3.7;
206                 vec[2]= (minlabda*(ray1[2]-ray2[2])+ray2[2])/3.7;
207                 
208                 return 1;
209         }
210         return 0;
211 }
212
213
214 static unsigned int previewback(int type, int x, int y)
215 {
216         if(type & MA_DARK) {
217                 if(abs(x)>abs(y)) return 0;
218                 else return 0x40404040;
219         }
220         else {
221                 if(abs(x)>abs(y)) return 0x40404040;
222                 else return 0xa0a0a0a0;
223         }
224 }
225
226 static void view2d_to_window(int win, int *x_r, int *y_r)
227 {
228         int x= *x_r, y= *y_r;
229         int size[2], origin[2];
230         float winmat[4][4];
231
232         bwin_getsinglematrix(win, winmat);
233         bwin_getsize(win, &size[0], &size[1]);
234         bwin_getsuborigin(win, &origin[0], &origin[1]);
235         
236         *x_r= origin[0] + (size[0]*(0.5 + 0.5*(x*winmat[0][0] + y*winmat[1][0] + winmat[3][0])));
237         *y_r= origin[1] + (size[1]*(0.5 + 0.5*(x*winmat[0][1] + y*winmat[1][1] + winmat[3][1])));
238 }
239
240 static void set_previewrect(int win, int xmin, int ymin, int xmax, int ymax)
241 {
242         prerect.xmin= xmin;
243         prerect.ymin= ymin;
244         prerect.xmax= xmax;
245         prerect.ymax= ymax;
246
247         view2d_to_window(win, &prerect.xmin, &prerect.ymin);
248         view2d_to_window(win, &prerect.xmax, &prerect.ymax);
249         
250         pr_sizex= (prerect.xmax-prerect.xmin);
251         pr_sizey= (prerect.ymax-prerect.ymin);
252
253         pr_facx= ( (float)pr_sizex-1)/PR_RECTX;
254         pr_facy= ( (float)pr_sizey-1)/PR_RECTY;
255 }
256
257 static void display_pr_scanline(unsigned int *rect, int recty)
258 {
259         /* we display 3 new scanlines, one old */
260
261         if(recty % 2) return;
262         if(recty<2) return;
263         
264         rect+= (recty-2)*PR_RECTX;
265
266         /* iets meer uitvergroten in y om GL/mesa bugje te verhelpen */
267         glPixelZoom(pr_facx, pr_facy);
268
269         glRasterPos2f( (float)PR_XMIN+0.5, 1.0+(float)PR_YMIN + (recty*PR_FACY) );
270         glDrawPixels(PR_RECTX, 3, GL_RGBA, GL_UNSIGNED_BYTE,  rect);
271
272         glPixelZoom(1.0, 1.0);
273 }
274
275 static void draw_tex_crop(Tex *tex)
276 {
277         rcti rct;
278         int ret= 0;
279         
280         if(tex==0) return;
281         
282         if(tex->type==TEX_IMAGE) {
283                 if(tex->cropxmin==0.0) ret++;
284                 if(tex->cropymin==0.0) ret++;
285                 if(tex->cropxmax==1.0) ret++;
286                 if(tex->cropymax==1.0) ret++;
287                 if(ret==4) return;
288                 
289                 rct.xmin= PR_XMIN+2+tex->cropxmin*(PR_XMAX-PR_XMIN-4);
290                 rct.xmax= PR_XMIN+2+tex->cropxmax*(PR_XMAX-PR_XMIN-4);
291                 rct.ymin= PR_YMIN+2+tex->cropymin*(PR_YMAX-PR_YMIN-4);
292                 rct.ymax= PR_YMIN+2+tex->cropymax*(PR_YMAX-PR_YMIN-4);
293
294                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
295
296                 glColor3ub(0, 0, 0);
297                 glRecti(rct.xmin+1,  rct.ymin-1,  rct.xmax+1,  rct.ymax-1); 
298
299                 glColor3ub(255, 255, 255);
300                 glRecti(rct.xmin,  rct.ymin,  rct.xmax,  rct.ymax);
301
302                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);                      
303         }
304         
305 }
306
307 void BIF_preview_changed(SpaceButs *sbuts)
308 {
309         sbuts->cury= 0;
310         addafterqueue(sbuts->area->win, RENDERPREVIEW, 1);
311 }
312
313 void BIF_previewdraw(SpaceButs *sbuts)
314 {
315         set_previewrect(sbuts->area->win, PR_XMIN, PR_YMIN, PR_XMAX, PR_YMAX);
316
317         if (sbuts->rect==0 || sbuts->cury==0) {
318                 BIF_preview_changed(sbuts);
319         } else {
320                 int y;
321
322                 for (y=0; y<PR_RECTY; y++) {
323                         display_pr_scanline(sbuts->rect, y);
324                 }
325
326                 if (sbuts->mainb==BUTS_TEX) {
327                         draw_tex_crop(sbuts->lockpoin);
328                 }
329         }
330 }
331
332 static void sky_preview_pixel(float lens, int x, int y, char *rect)
333 {
334         
335         if(R.wrld.skytype & WO_SKYPAPER) {
336                 R.view[0]= (2*x)/(float)PR_RECTX;
337                 R.view[1]= (2*y)/(float)PR_RECTY;
338                 R.view[2]= 0.0;
339         }
340         else {
341                 R.view[0]= x;
342                 R.view[1]= y;
343                 R.view[2]= -lens*PR_RECTX/32.0;
344                 Normalise(R.view);
345         }
346         RE_sky(rect);
347 }
348
349 static void lamp_preview_pixel(LampRen *la, int x, int y, char *rect)
350 {
351         float inpr, i, t, dist, distkw, vec[3];
352         int col;
353         
354         R.co[0]= (float)x/(PR_RECTX/4);
355         R.co[1]= (float)y/(PR_RECTX/4);
356         R.co[2]= 0;
357         
358         vec[0]= 0.02*x;
359         vec[1]= 0.02*y;
360         vec[2]= 0.005*PR_RECTX;
361         VECCOPY(R.view, vec);
362         dist= Normalise(R.view);
363
364         if(la->mode & LA_TEXTURE) do_lamp_tex(la, vec);
365
366         if(la->type==LA_SUN || la->type==LA_HEMI) {
367                 dist= 1.0;
368         }
369         else {
370                 
371                 if(la->mode & LA_QUAD) {
372                         
373                         t= 1.0;
374                         if(la->ld1>0.0)
375                                 t= la->dist/(la->dist+la->ld1*dist);
376                         if(la->ld2>0.0) {
377                                 distkw= la->dist*la->dist;
378                                 t= t*distkw/(t*distkw+la->ld2*dist*dist);
379                         }
380                         dist= t;
381                 }
382                 else {
383                         dist= (la->dist/(la->dist+dist));
384                 }
385         }
386
387         if(la->type==LA_SPOT) {
388
389                 
390                 if(la->mode & LA_SQUARE) {
391                         /* slightly smaller... */
392                         inpr= 1.7*cos(MAX2(fabs(R.view[0]/R.view[2]) , fabs(R.view[1]/R.view[2]) ));
393                 }
394                 else {
395                         inpr= R.view[2];
396                 }
397                 
398                 t= la->spotsi;
399                 if(inpr<t) dist= 0.0;
400                 else {
401                         t= inpr-t;
402                         if(t<la->spotbl && la->spotbl!=0.0) {
403                                 /* zachte gebied */
404                                 i= t/la->spotbl;
405                                 t= i*i;
406                                 i= t*i;
407                                 inpr*=(3.0*t-2.0*i);
408                         }
409                 }
410                 dist*=inpr;
411         }
412         else if(la->type==LA_LOCAL) dist*= R.view[2];
413         
414         col= 255.0*dist*la->r;
415         if(col<=0) rect[0]= 0; else if(col>=255) rect[0]= 255; else rect[0]= col;
416
417         col= 255.0*dist*la->g;
418         if(col<=0) rect[1]= 0; else if(col>=255) rect[1]= 255; else rect[1]= col;
419
420         col= 255.0*dist*la->b;
421         if(col<=0) rect[2]= 0; else if(col>=255) rect[2]= 255; else rect[2]= col;
422 }
423
424 static void init_previewhalo(HaloRen *har, Material *mat)
425 {
426         
427         har->type= 0;
428         if(mat->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
429         har->mat= mat;
430         har->hard= mat->har;
431         har->rad= PR_RECTX/2.0;
432         har->radsq= PR_RECTX*PR_RECTX/4.0;
433         har->alfa= mat->alpha;
434         har->add= 255.0*mat->add;
435         har->r= 255.0*mat->r;
436         har->g= 255.0*mat->g; 
437         har->b= 255.0*mat->b;
438         har->xs= PR_RECTX/2.0;
439         har->ys= PR_RECTX/2.0;
440         har->zs= har->zd= 0;
441         har->seed= (mat->seed1 % 256);
442         
443         if( (mat->mode & MA_HALOTEX) && mat->mtex[0] ) har->tex= 1; else har->tex=0;
444
445         if(mat->mode & MA_STAR) har->starpoints= mat->starc; else har->starpoints= 0;
446         if(mat->mode & MA_HALO_LINES) har->linec= mat->linec; else har->linec= 0;
447         if(mat->mode & MA_HALO_RINGS) har->ringc= mat->ringc; else har->ringc= 0;
448         if(mat->mode & MA_HALO_FLARE) har->flarec= mat->flarec; else har->flarec= 0;
449         
450         if(har->flarec) {
451                 har->xs-= PR_RECTX/3;
452                 har->ys+= PR_RECTX/3;
453                 
454                 har->rad*= 0.3;
455                 har->radsq= har->rad*har->rad;
456                 
457                 har->pixels= har->rad*har->rad*har->rad;
458         }
459 }       
460
461 static void halo_preview_pixel(HaloRen *har, int startx, int endx, int y, char *rect)
462 {
463         float dist, xn, yn, xsq, ysq;
464         int x;
465         char front[4];
466         
467         if(har->flarec) yn= y-PR_RECTX/3;
468         else yn= y;
469         ysq= yn*yn;
470         
471         for(x=startx; x<endx; x++) {
472                 
473                 if(har->flarec) xn= x+PR_RECTX/3;
474                 else xn= x;
475                 
476                 xsq= xn*xn;
477                 dist= xsq+ysq;
478
479                 
480                 
481                 if(dist<har->radsq) {
482                         RE_shadehalo(har, front, 0, dist, xn, yn, har->flarec);
483                         RE_addalphaAddfac(rect, front, har->add);
484                 }
485                 rect+= 4;
486         }
487 }
488
489 static void previewflare(SpaceButs *sbuts, HaloRen *har, unsigned int *rect)
490 {
491         float ycor;
492         unsigned int *rectot;
493         int afmx, afmy, rectx, recty;
494         
495         /* temps */
496         ycor= R.ycor;
497         rectx= R.rectx;
498         recty= R.recty;
499         afmx= R.afmx;
500         afmy= R.afmy;
501         rectot= R.rectot;
502
503         R.ycor= 1.0;
504         R.rectx= PR_RECTX;      
505         R.recty= PR_RECTY;
506         R.afmx= PR_RECTX/2;
507         R.afmy= PR_RECTY/2;
508         R.rectot= rect;
509
510         waitcursor(1);
511
512         RE_renderflare(har);
513
514         BIF_previewdraw(sbuts);
515         
516         waitcursor(0);
517         
518         /* temps */
519         R.ycor= ycor;
520         R.rectx= rectx;
521         R.recty= recty;
522         R.afmx= afmx;
523         R.afmy= afmy;
524         R.rectot= rectot;
525 }
526
527 extern float Tin, Tr, Tg, Tb, Ta; /* texture.c */
528 static void texture_preview_pixel(Tex *tex, int x, int y, char *rect)
529 {
530         float i, v1, xsq, ysq, texvec[3];
531         int rgbnor, tracol, skip=0;
532                 
533         if(tex->type==TEX_IMAGE) {
534                 v1= 1.0/PR_RECTX;
535                 
536                 texvec[0]= 0.5+v1*x;
537                 texvec[1]= 0.5+v1*y;
538                 
539                 /* geen coordmapping, uitzondering: repeat */
540                 if(tex->xrepeat>1) {
541                         texvec[0] *= tex->xrepeat;
542                         if(texvec[0]>1.0) texvec[0] -= (int)(texvec[0]);
543                 }
544                 if(tex->yrepeat>1) {
545                         texvec[1] *= tex->yrepeat;
546                         if(texvec[1]>1.0) texvec[1] -= (int)(texvec[1]);
547                 }
548
549         }
550         else if(tex->type==TEX_ENVMAP) {
551                 if(tex->env) {
552                         ysq= y*y;
553                         xsq= x*x;
554                         if(xsq+ysq < (PR_RECTX/2)*(PR_RECTY/2)) {
555                                 texvec[2]= sqrt( (float)((PR_RECTX/2)*(PR_RECTY/2)-xsq-ysq) );
556                                 texvec[0]= -x;
557                                 texvec[1]= -y;
558                                 Normalise(texvec);
559
560                                 i= 2.0*(texvec[2]);
561                                 texvec[0]= (i*texvec[0]);
562                                 texvec[1]= (i*texvec[1]);
563                                 texvec[2]= (-1.0+i*texvec[2]);
564
565                         }
566                         else {
567                                 skip= 1;
568                                 Ta= 0.0;
569                         }
570                 }
571                 else {
572                         skip= 1;
573                         Ta= 0.0;
574                 }
575         }
576         else {
577                 v1= 2.0/PR_RECTX;
578         
579                 texvec[0]= v1*x;
580                 texvec[1]= v1*y;
581                 texvec[2]= 0.0;
582         }
583         
584         /* geeft geen Tin terug */
585         if(tex->type==TEX_STUCCI) {
586                 tex->nor= R.vn;
587                 R.vn[0]= 1.0;
588                 R.vn[1]= R.vn[2]= 0.0;
589         }
590         
591         if(skip==0) rgbnor= multitex(tex, texvec, 0, 0);
592         else rgbnor= 1;
593         
594         if(rgbnor & 1) {
595                 
596                 rect[0]= 255.0*Tr;
597                 rect[1]= 255.0*Tg;
598                 rect[2]= 255.0*Tb;
599                 
600                 if(Ta!=1.0) {
601                         tracol=  64+100*(abs(x)>abs(y));
602                         tracol= (1.0-Ta)*tracol;
603                         
604                         rect[0]= tracol+ (rect[0]*Ta) ;
605                         rect[1]= tracol+ (rect[1]*Ta) ;
606                         rect[2]= tracol+ (rect[2]*Ta) ;
607                                         
608                 }
609         }
610         else {
611         
612                 if(tex->type==TEX_STUCCI) {
613                         Tin= 0.5 + 0.7*tex->nor[0];
614                         CLAMP(Tin, 0.0, 1.0);
615                 }
616                 rect[0]= 255.0*Tin;
617                 rect[1]= 255.0*Tin;
618                 rect[2]= 255.0*Tin;
619         }
620 }
621
622 static float pr1_lamp[3]= {2.3, -2.4, -4.6};
623 static float pr2_lamp[3]= {-8.8, -5.6, -1.5};
624 static float pr1_col[3]= {0.8, 0.8, 0.8};
625 static float pr2_col[3]= {0.5, 0.6, 0.7};
626
627 static void shade_preview_pixel(float *vec, 
628                                                                 int x, 
629                                                                 int y, 
630                                                                 char *rect, 
631                                                                 int smooth)
632 {
633         Material *mat;
634         float v1,inp, inprspec=0, isr=0.0, isb=0.0, isg=0.0;
635         float ir=0.0, ib=0.0, ig=0.0;
636         float view[3], lv[3], *la, alpha;
637         float eul[3], tmat[3][3], imat[3][3];
638         int temp, a;
639         char tracol;
640         
641         mat= R.matren;
642         /* pr1_lamp[0]= mat->mtex[0]->ofs[0]; */
643         /* pr1_lamp[1]= mat->mtex[0]->ofs[1]; */
644         /* pr1_lamp[2]= mat->mtex[0]->ofs[2]; */
645
646         /* pr2_lamp[0]= mat->mtex[0]->size[0]; */
647         /* pr2_lamp[1]= mat->mtex[0]->size[1]; */
648         /* pr2_lamp[2]= mat->mtex[0]->size[2]; */
649
650         v1= 1.0/PR_RECTX;
651         view[0]= v1*x;
652         view[1]= v1*y;
653         view[2]= 1.0;
654         Normalise(view);
655         
656         R.refcol[0]= R.refcol[1]= R.refcol[2]= R.refcol[3]= 0.0;
657
658         /* texture afhandeling */
659         if(mat->texco) {
660                 
661                 VECCOPY(R.lo, vec);
662                 
663                 if(mat->pr_type==MA_CUBE) {
664                         
665                         eul[0]= (297)*M_PI/180.0;
666                         eul[1]= 0.0;
667                         eul[2]= (45)*M_PI/180.0;
668                         EulToMat3(eul, tmat);
669
670                         MTC_Mat3MulVecfl(tmat, R.lo);
671                         MTC_Mat3MulVecfl(tmat, R.vn);
672                         /* hack for cubemap, why!!! */
673                         SWAP(float, R.vn[0], R.vn[1]);
674                 }
675
676                 if(mat->texco & TEXCO_GLOB) {
677                         VECCOPY(R.gl, R.lo);
678                 }
679                 if(mat->texco & TEXCO_WINDOW) {
680                         VECCOPY(R.winco, R.lo);
681                 }
682                 if(mat->texco & TEXCO_STICKY) {
683                         VECCOPY(R.sticky, R.lo);
684                 }
685                 if(mat->texco & TEXCO_UV) {
686                         VECCOPY(R.uv, R.lo);
687                 }
688                 if(mat->texco & TEXCO_OBJECT) {
689                         VECCOPY(R.co, R.lo);
690                 }
691                 if(mat->texco & TEXCO_NORM) {
692                         R.orn[0]= R.vn[0];
693                         R.orn[1]= -R.vn[1];
694                         R.orn[2]= R.vn[2];
695                 }
696                 if(mat->texco & TEXCO_REFL) {
697                         /* for bump texture */
698                         VECCOPY(R.view, view);
699                         
700                         inp= -2.0*(R.vn[0]*view[0]+R.vn[1]*view[1]+R.vn[2]*view[2]);
701                         R.ref[0]= (view[0]+inp*R.vn[0]);
702                         R.ref[1]= -(view[1]+inp*R.vn[1]);
703                         R.ref[2]= (view[2]+inp*R.vn[2]);
704                 }
705
706                 do_material_tex();
707
708                 if(mat->pr_type==MA_CUBE) {
709                         /* rotate normal back for normals texture */
710                         SWAP(float, R.vn[0], R.vn[1]);
711                         MTC_Mat3Inv(imat, tmat);
712                         MTC_Mat3MulVecfl(imat, R.vn);
713                 }
714                 
715         }
716         
717         if(mat->mode & MA_SHLESS) {
718                 temp= 255.0*(mat->r);
719                 if(temp>255) rect[0]= 255; else if(temp<0) rect[0]= 0; else rect[0]= temp;
720
721                 temp= 255.0*(mat->g);
722                 if(temp>255) rect[1]= 255; else if(temp<0) rect[1]= 0; else rect[1]= temp;
723
724                 temp= 255.0*(mat->b);
725                 if(temp>255) rect[2]= 255; else if(temp<0) rect[2]= 0; else rect[2]= temp;
726         }
727         else {
728                 
729                 for(a=0; a<2; a++) {
730                         
731                         if(a==0) la= pr1_lamp;
732                         else la= pr2_lamp;
733                         
734                         lv[0]= vec[0]-la[0];
735                         lv[1]= vec[1]-la[1];
736                         lv[2]= vec[2]-la[2];
737                         Normalise(lv);
738                         
739                         inp= R.vn[0]*lv[0]+R.vn[1]*lv[1]+R.vn[2]*lv[2];
740                         if(inp<0.0) inp= 0.0;
741                         
742                         if(mat->spec)  {
743                                 
744                                 lv[0]+= view[0];
745                                 lv[1]+= view[1];
746                                 lv[2]+= view[2];
747                                 Normalise(lv);
748                                 
749                                 if(inp>0.0) {
750                                         v1= lv[0]*R.vn[0]+lv[1]*R.vn[1]+lv[2]*R.vn[2];
751                                         if(v1>0.0) {
752                                                 v1= RE_Spec(v1, mat->har);
753                                                 inprspec= v1*mat->spec;
754                                                 isr+= inprspec*mat->specr;
755                                                 isg+= inprspec*mat->specg;
756                                                 isb+= inprspec*mat->specb;
757                                         }
758                                 }
759                         }
760                         inp= (mat->ref*inp + mat->emit);
761                         
762                         if(a==0) la= pr1_col;
763                         else la= pr2_col;
764
765                         ir+= inp*la[0];
766                         ig+= inp*la[1];
767                         ib+= inp*la[2];
768                 }
769
770                 if(R.refcol[0]==0.0) {
771                         a= 255.0*( mat->r*ir +mat->ambr +isr);
772                         if(a>255) a=255; else if(a<0) a= 0;
773                         rect[0]= a;
774                         a= 255.0*(mat->g*ig +mat->ambg +isg);
775                         if(a>255) a=255; else if(a<0) a= 0;
776                         rect[1]= a;
777                         a= 255*(mat->b*ib +mat->ambb +isb);
778                         if(a>255) a=255; else if(a<0) a= 0;
779                         rect[2]= a;
780                 }
781                 else {
782                         a= 255.0*( mat->mirr*R.refcol[1] + (1.0 - mat->mirr*R.refcol[0])*(mat->r*ir +mat->ambr) +isr);
783                         if(a>255) a=255; else if(a<0) a= 0;
784                         rect[0]= a;
785                         a= 255.0*( mat->mirg*R.refcol[2] + (1.0 - mat->mirg*R.refcol[0])*(mat->g*ig +mat->ambg) +isg);
786                         if(a>255) a=255; else if(a<0) a= 0;
787                         rect[1]= a;
788                         a= 255.0*( mat->mirb*R.refcol[3] + (1.0 - mat->mirb*R.refcol[0])*(mat->b*ib +mat->ambb) +isb);
789                         if(a>255) a=255; else if(a<0) a= 0;
790                         rect[2]= a;
791                 }
792         }
793
794         if(mat->alpha!=1.0) {
795                 
796                 alpha= mat->alpha;
797                 
798                         /* ztra shade */
799                 if(mat->spectra!=0.0) {
800                         inp= mat->spectra*inprspec;
801                         if(inp>1.0) inp= 1.0;
802                         
803                         alpha= (1.0-inp)*alpha+ inp;
804                 }
805
806                 tracol=  previewback(mat->pr_back, x, y) & 255;
807                 
808                 tracol= (1.0-alpha)*tracol;
809                 
810                 rect[0]= tracol+ (rect[0]*alpha) ;
811                 rect[1]= tracol+ (rect[1]*alpha) ;
812                 rect[2]= tracol+ (rect[2]*alpha) ;
813
814         }
815 }
816
817
818 void BIF_previewrender(SpaceButs *sbuts)
819 {
820         Material *mat=0;
821         Tex *tex = NULL;
822         Image *ima;
823         Lamp *la;
824         LampRen *lar = NULL;
825         HaloRen har;
826         Object *ob;
827         World *wrld;
828         float lens = 0.0, vec[3];
829         int x, y, starty, startx, endy, endx, radsq, xsq, ysq, last = 0;
830         unsigned int *rect;
831
832         if(sbuts->cury>=PR_RECTY) return;
833         
834         if ELEM4(sbuts->mainb, BUTS_MAT, BUTS_TEX, BUTS_LAMP, BUTS_WORLD);
835         else return;
836         
837         har.flarec= 0;  /* verderop test op postrender flare */
838         
839         if(qtest()) {
840                 addafterqueue(curarea->win, RENDERPREVIEW, 1);
841                 return;
842         }
843
844         MTC_Mat4One(R.viewmat);
845         MTC_Mat4One(R.viewinv);
846         
847         R.osatex= 0;
848         if(sbuts->mainb==BUTS_MAT) {
849                 mat= sbuts->lockpoin;
850                 if(mat==0) return;
851
852                 /* rendervars */
853                 init_render_world();
854                 init_render_material(mat);
855                 
856                 /* clear imats */
857                 for(x=0; x<8; x++) {
858                         if(mat->mtex[x]) {
859                                 if(mat->mtex[x]->tex) {
860                                         init_render_texture(mat->mtex[x]->tex);
861                                         
862                                         if(mat->mtex[x]->tex->env && mat->mtex[x]->tex->env->object) 
863                                                 MTC_Mat4One(mat->mtex[x]->tex->env->object->imat);
864                                 }
865                                 if(mat->mtex[x]->object) MTC_Mat4One(mat->mtex[x]->object->imat);
866                                 if(mat->mtex[x]->object) MTC_Mat4One(mat->mtex[x]->object->imat);
867                         }
868                 }
869                 R.vlr= 0;
870                 R.mat= mat;
871                 R.matren= mat->ren;
872                 
873                 if(mat->mode & MA_HALO) init_previewhalo(&har, mat);
874         }
875         else if(sbuts->mainb==BUTS_TEX) {
876                 tex= sbuts->lockpoin;
877                 if(tex==0) return;
878                 ima= tex->ima;
879                 if(ima) last= ima->lastframe;
880                 init_render_texture(tex);
881                 free_unused_animimages();
882                 if(tex->ima) {
883                         if(tex->ima!=ima) allqueue(REDRAWBUTSTEX, 0);
884                         else if(last!=ima->lastframe) allqueue(REDRAWBUTSTEX, 0);
885                 }
886                 if(tex->env && tex->env->object) 
887                         MTC_Mat4Invert(tex->env->object->imat, tex->env->object->obmat);
888         }
889         else if(sbuts->mainb==BUTS_LAMP) {
890                 ob= ((G.scene->basact)? (G.scene->basact)->object: 0);
891                 if(ob==0 || ob->type!=OB_LAMP) return;
892                 la= ob->data;
893                 init_render_world();
894                 init_render_textures(); /* ze mogen niet twee keer!! (brightness) */
895                 R.totlamp= 0;
896                 RE_add_render_lamp(ob, 0);      /* 0=no shadbuf */
897                 lar= R.la[0];
898                 
899                 /* uitzonderingen: */
900                 lar->spottexfac= 1.0;
901                 lar->spotsi= cos( M_PI/3.0 );
902                 lar->spotbl= (1.0-lar->spotsi)*la->spotblend;
903                 
904                 MTC_Mat3One(lar->imat);
905         }
906         else {
907                 wrld= sbuts->lockpoin;
908                 if(wrld==0) return;
909                 
910                 lens= 35.0;
911                 if(G.scene->camera) {
912                         lens= ( (Camera *)G.scene->camera->data)->lens;
913                 }
914                 
915                 init_render_world();
916                 init_render_textures(); /* dont do it twice!! (brightness) */
917         }
918
919         set_previewrect(sbuts->area->win, PR_XMIN, PR_YMIN, PR_XMAX, PR_YMAX);
920
921         if(sbuts->rect==0) {
922                 sbuts->rect= MEM_callocN(sizeof(int)*PR_RECTX*PR_RECTY, "butsrect");
923                 
924                 /* built in emboss */
925                 rect= sbuts->rect;
926                 for(y=0; y<PR_RECTY; y++, rect++) *rect= 0xFFFFFFFF;
927                 
928                 rect= sbuts->rect + PR_RECTX-1;
929                 for(y=0; y<PR_RECTY; y++, rect+=PR_RECTX) *rect= 0xFFFFFFFF;
930         }
931         
932         starty= -PR_RECTY/2;
933         endy= starty+PR_RECTY;
934         starty+= sbuts->cury;
935         
936         /* offset +1 for emboss */
937         startx= -PR_RECTX/2 +1;
938         endx= startx+PR_RECTX -2;
939
940         radsq= (PR_RECTX/2)*(PR_RECTY/2);
941         
942         glDrawBuffer(GL_FRONT);
943         
944         if(mat) {
945                 if(mat->pr_type==MA_SPHERE) {
946                         pr1_lamp[0]= 2.3; pr1_lamp[1]= -2.4; pr1_lamp[2]= -4.6;
947                         pr2_lamp[0]= -8.8; pr2_lamp[1]= -5.6; pr2_lamp[2]= -1.5;
948                 }
949                 else {
950                         pr1_lamp[0]= 1.9; pr1_lamp[1]= 3.1; pr1_lamp[2]= -8.5;
951                         pr2_lamp[0]= 1.2; pr2_lamp[1]= -18; pr2_lamp[2]= 3.2;
952                 }
953         }
954         
955         for(y=starty; y<endy; y++) {
956                 
957                 rect= sbuts->rect + 1 + PR_RECTX*sbuts->cury;
958                 
959                 if(y== -PR_RECTY/2 || y==endy-1);               /* emboss */
960                 else if(sbuts->mainb==BUTS_MAT) {
961                         
962                         if(mat->mode & MA_HALO) {
963                                 for(x=startx; x<endx; x++, rect++) {
964                                         rect[0]= previewback(mat->pr_back, x, y);
965                                 }
966
967                                 if(har.flarec) {
968                                         if(y==endy-2) previewflare(sbuts, &har, sbuts->rect);
969                                 }
970                                 else {
971                                         halo_preview_pixel(&har, startx, endx, y, (char *) (rect-PR_RECTX));
972                                 }
973                         }
974                         else {
975                                 ysq= y*y;
976                                 for(x=startx; x<endx; x++, rect++) {
977                                         xsq= x*x;
978                                         if(mat->pr_type==MA_SPHERE) {
979                                         
980                                                 if(xsq+ysq < radsq) {
981                                                         R.vn[0]= x;
982                                                         R.vn[1]= y;
983                                                         R.vn[2]= sqrt( (float)(radsq-xsq-ysq) );
984                                                         Normalise(R.vn);
985                                                         
986                                                         vec[0]= R.vn[0];
987                                                         vec[1]= R.vn[2];
988                                                         vec[2]= -R.vn[1];
989                                                         
990                                                         shade_preview_pixel(vec, x, y, (char *)rect, 1);
991                                                 }
992                                                 else {
993                                                         rect[0]= previewback(mat->pr_back, x, y);
994                                                 }
995                                         }
996                                         else if(mat->pr_type==MA_CUBE) {
997                                                 if( ray_previewrender(x, y, vec) ) {
998                                                         
999                                                         shade_preview_pixel(vec, x, y, (char *)rect, 0);
1000                                                 }
1001                                                 else {
1002                                                         rect[0]= previewback(mat->pr_back, x, y);
1003                                                 }
1004                                         }
1005                                         else {
1006                                                 vec[0]= x*(2.0/PR_RECTX);
1007                                                 vec[1]= y*(2.0/PR_RECTX);
1008                                                 vec[2]= 0.0;
1009                                                 
1010                                                 R.vn[0]= R.vn[1]= 0.0;
1011                                                 R.vn[2]= 1.0;
1012                                                 
1013                                                 shade_preview_pixel(vec, x, y, (char *)rect, 0);
1014                                         }
1015                                 }
1016                         }
1017                 }
1018                 else if(sbuts->mainb==BUTS_TEX) {
1019                         for(x=startx; x<endx; x++, rect++) {
1020                                 texture_preview_pixel(tex, x, y, (char *)rect);
1021                         }
1022                 }
1023                 else if(sbuts->mainb==BUTS_LAMP) {
1024                         for(x=startx; x<endx; x++, rect++) {
1025                                 lamp_preview_pixel(lar, x, y, (char *)rect);
1026                         }
1027                 }
1028                 else  {
1029                         for(x=startx; x<endx; x++, rect++) {                            
1030                                 sky_preview_pixel(lens, x, y, (char *)rect);
1031                         }
1032                 }
1033                 
1034                 if(y<endy-2) {
1035
1036                         if(qtest()) {
1037                                 addafterqueue(curarea->win, RENDERPREVIEW, 1);
1038                                 break;
1039                         }
1040                 }
1041
1042                 display_pr_scanline(sbuts->rect, sbuts->cury);
1043                 
1044                 sbuts->cury++;
1045         }
1046
1047         if(sbuts->cury>=PR_RECTY && sbuts->mainb==BUTS_TEX) 
1048                 draw_tex_crop(sbuts->lockpoin);
1049         
1050         glDrawBuffer(GL_BACK);
1051         BIF_previewdraw(sbuts);
1052         
1053         if(sbuts->mainb==BUTS_MAT) {
1054                 end_render_material(mat);
1055                 for(x=0; x<8; x++) {
1056                         if(mat->mtex[x] && mat->mtex[x]->tex) end_render_texture(mat->mtex[x]->tex);
1057                 }       
1058         }
1059         else if(sbuts->mainb==BUTS_TEX) {
1060                 end_render_texture(tex);
1061         }
1062         else if(sbuts->mainb==BUTS_WORLD) {
1063                 end_render_textures();
1064         }
1065         else if(sbuts->mainb==BUTS_LAMP) {
1066                 if(R.totlamp) {
1067                         if(R.la[0]->org) MEM_freeN(R.la[0]->org);
1068                         MEM_freeN(R.la[0]);
1069                 }
1070                 R.totlamp= 0;
1071                 end_render_textures();
1072         }
1073 }
1074