8604219387f47f2cc434bf1fe675aa98935c89e9
[blender.git] / source / blender / src / previewrender.c
1 /* 
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 /* global includes */
34
35 #include <stdlib.h>
36 #include <math.h>
37 #include <string.h>
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 #ifndef WIN32
44 #include <unistd.h>
45 #else
46 #include <io.h>
47 #endif   
48 #include "MEM_guardedalloc.h"
49 #include "BLI_arithb.h"
50 #include "BKE_utildefines.h"
51
52 #include "MTC_matrixops.h"
53
54 #include "render.h"
55 #include "mydevice.h"
56
57 #include "DNA_texture_types.h"
58 #include "DNA_world_types.h"
59 #include "DNA_camera_types.h"
60 #include "DNA_image_types.h"
61 #include "DNA_material_types.h"
62 #include "DNA_object_types.h"
63 #include "DNA_lamp_types.h"
64 #include "DNA_space_types.h"
65 #include "DNA_scene_types.h"
66 #include "DNA_screen_types.h"
67
68 #include "BKE_global.h"
69 #include "BKE_image.h"
70 #include "BKE_texture.h"
71 #include "BKE_material.h"
72 #include "BKE_world.h"
73 #include "BKE_texture.h"
74
75 #include "BSE_headerbuttons.h"
76
77 #include "BIF_gl.h"
78 #include "BIF_screen.h"
79 #include "BIF_space.h"          /* allqueue */
80 #include "BIF_butspace.h"       
81 #include "BIF_mywindow.h"
82 #include "BIF_interface.h"
83 #include "BIF_glutil.h"
84
85 #include "BIF_previewrender.h"  /* include ourself for prototypes */
86
87 #include "PIL_time.h"
88
89 #include "RE_renderconverter.h"
90
91 #include "blendef.h"    /* CLAMP */
92 #include "interface.h"  /* ui_graphics_to_window() SOLVE! (ton) */
93
94 #define PR_RECTX        141
95 #define PR_RECTY        141
96 #define PR_XMIN         10
97 #define PR_YMIN         5
98 #define PR_XMAX         200
99 #define PR_YMAX         195
100
101 #define PR_FACY         (PR_YMAX-PR_YMIN-4)/(PR_RECTY)
102
103 static rctf prerect;
104 static float pr_facx, pr_facy;
105
106
107 /* implementation */
108
109 static short snijpunt(float *v1,   float *v2,  float *v3,  float *rtlabda, float *ray1, float *ray2)
110 {
111         float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22;
112         float m0,m1,m2,deeldet,det1,det2,det3;
113         float rtu, rtv;
114         
115         t00= v3[0]-v1[0];
116         t01= v3[1]-v1[1];
117         t02= v3[2]-v1[2];
118         t10= v3[0]-v2[0];
119         t11= v3[1]-v2[1];
120         t12= v3[2]-v2[2];
121         t20= ray1[0]-ray2[0];
122         t21= ray1[1]-ray2[1];
123         t22= ray1[2]-ray2[2];
124         
125         x0= t11*t22-t12*t21;
126         x1= t12*t20-t10*t22;
127         x2= t10*t21-t11*t20;
128
129         deeldet= t00*x0+t01*x1+t02*x2;
130         if(deeldet!=0.0f) {
131                 m0= ray1[0]-v3[0];
132                 m1= ray1[1]-v3[1];
133                 m2= ray1[2]-v3[2];
134                 det1= m0*x0+m1*x1+m2*x2;
135                 rtu= det1/deeldet;
136                 if(rtu<=0.0f) {
137                         det2= t00*(m1*t22-m2*t21);
138                         det2+= t01*(m2*t20-m0*t22);
139                         det2+= t02*(m0*t21-m1*t20);
140                         rtv= det2/deeldet;
141                         if(rtv<=0.0f) {
142                                 if(rtu+rtv>= -1.0f) {
143                                         
144                                         det3=  m0*(t12*t01-t11*t02);
145                                         det3+= m1*(t10*t02-t12*t00);
146                                         det3+= m2*(t11*t00-t10*t01);
147                                         *rtlabda= det3/deeldet;
148                                         
149                                         if(*rtlabda>=0.0f && *rtlabda<=1.0f) {
150                                                 return 1;
151                                         }
152                                 }
153                         }
154                 }
155         }
156         return 0;
157 }
158
159 static float rcubev[7][3]= {
160         {-0.002055,  6.627364, -3.369742}, 
161         {-6.031684, -3.750204, -1.992980}, 
162         {-6.049086,  3.817431,  1.969788}, 
163         { 6.031685,  3.833064,  1.992979}, 
164         { 6.049086, -3.734571, -1.969787}, 
165         { 0.002054, -6.544502,  3.369744}, 
166         {-0.015348,  1.023131,  7.332510} };
167
168 static int rcubi[3][4]= {
169         {3,  6,  5,  4},
170         {1,  5,  6,  2},  
171         {3,  0,  2,  6} };
172
173
174 static int ray_previewrender(int x,  int y,  float *vec, float *vn)
175 {
176         float scalef= 10.0f/100.0f;
177         float ray1[3], ray2[3];
178         float minlabda, labda;
179         int totface= 3, hitface= -1;
180         int a;
181
182         ray1[0]= ray2[0]= x*scalef;
183         ray1[1]= ray2[1]= y*scalef;
184         ray1[2]= -10.0f;
185         ray2[2]= 10.0f;
186         
187         minlabda= 1.0f;
188         for(a=0; a<totface; a++) {
189                 if(snijpunt( rcubev[rcubi[a][0]], rcubev[rcubi[a][1]], rcubev[rcubi[a][2]], &labda, ray1, ray2)) {
190                         if( labda < minlabda) {
191                                 minlabda= labda;
192                                 hitface= a;
193                         }
194                 }
195                 if(snijpunt( rcubev[rcubi[a][0]], rcubev[rcubi[a][2]], rcubev[rcubi[a][3]], &labda, ray1, ray2)) {
196                         if( labda < minlabda) {
197                                 minlabda= labda;
198                                 hitface= a;
199                         }
200                 }
201         }
202         
203         if(hitface > -1) {
204                 
205                 CalcNormFloat(rcubev[rcubi[hitface][0]], rcubev[rcubi[hitface][1]], rcubev[rcubi[hitface][2]], vn);
206                 
207                 vec[0]= (minlabda*(ray1[0]-ray2[0])+ray2[0])/4.1;
208                 vec[1]= (minlabda*(ray1[1]-ray2[1])+ray2[1])/4.1;
209                 vec[2]= (minlabda*(ray1[2]-ray2[2])+ray2[2])/4.1;
210                 
211                 return 1;
212         }
213         return 0;
214 }
215
216
217 static unsigned int previewback(int type, int x, int y)
218 {
219         
220         /* checkerboard, for later
221         x+= PR_RECTX/2;
222         y+= PR_RECTX/2;
223         if( ((x/24) + (y/24)) & 1) return 0x40404040;
224         else return 0xa0a0a0a0;
225         */
226         
227         if(type & MA_DARK) {
228                 if(abs(x)>abs(y)) return 0;
229                 else return 0x40404040;
230         }
231         else {
232                 if(abs(x)>abs(y)) return 0x40404040;
233                 else return 0xa0a0a0a0;
234         }
235 }
236
237 static void set_previewrect(int win, int xmin, int ymin, int xmax, int ymax)
238 {
239         float pr_sizex, pr_sizey;
240         
241         prerect.xmin= xmin;
242         prerect.ymin= ymin;
243         prerect.xmax= xmax;
244         prerect.ymax= ymax;
245
246         ui_graphics_to_window(win, &prerect.xmin, &prerect.ymin);
247         ui_graphics_to_window(win, &prerect.xmax, &prerect.ymax);
248         
249         pr_sizex= (prerect.xmax-prerect.xmin);
250         pr_sizey= (prerect.ymax-prerect.ymin);
251
252         pr_facx= ( pr_sizex-1.0f)/PR_RECTX;
253         pr_facy= ( pr_sizey-1.0f)/PR_RECTY;
254
255         /* correction for gla draw */
256         prerect.xmin-= curarea->winrct.xmin;
257         prerect.ymin-= curarea->winrct.ymin;
258         
259         glMatrixMode(GL_PROJECTION);
260         glPushMatrix();
261         glMatrixMode(GL_MODELVIEW);
262         glPushMatrix();
263         
264         glaDefine2DArea(&curarea->winrct);
265
266         glPixelZoom(pr_facx, pr_facy);
267         
268 }
269
270 static void end_previewrect(void)
271 {
272         glMatrixMode(GL_PROJECTION);
273         glPopMatrix();
274         glMatrixMode(GL_MODELVIEW);
275         glPopMatrix();
276         
277         glPixelZoom(1.0f, 1.0f);
278         
279         // restore viewport / scissor which was set by glaDefine2DArea
280         glViewport(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winx, curarea->winy);
281         glScissor(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winx, curarea->winy);
282
283 }
284
285 static void display_pr_scanline(unsigned int *rect, int recty)
286 {
287         
288         /* we do steps of 4 scanlines. but draw 5, because of errors in some gfx cards (nvidia geforce, ati...) */
289         if( (recty & 3)==3) {
290                 
291                 if(recty == 3) {
292                         glaDrawPixelsSafe(prerect.xmin, prerect.ymin, PR_RECTX, 4, rect);
293                 }
294                 else {
295                         rect+= (recty-4)*PR_RECTX;
296                         glaDrawPixelsSafe(prerect.xmin, prerect.ymin + (((float)recty-4.0)*pr_facy), PR_RECTX, 5, rect);
297                 }
298         }
299 }
300
301 static void draw_tex_crop(Tex *tex)
302 {
303         rcti rct;
304         int ret= 0;
305         
306         if(tex==0) return;
307         
308         if(tex->type==TEX_IMAGE) {
309                 if(tex->cropxmin==0.0f) ret++;
310                 if(tex->cropymin==0.0f) ret++;
311                 if(tex->cropxmax==1.0f) ret++;
312                 if(tex->cropymax==1.0f) ret++;
313                 if(ret==4) return;
314                 
315                 rct.xmin= PR_XMIN+2+tex->cropxmin*(PR_XMAX-PR_XMIN-4);
316                 rct.xmax= PR_XMIN+2+tex->cropxmax*(PR_XMAX-PR_XMIN-4);
317                 rct.ymin= PR_YMIN+2+tex->cropymin*(PR_YMAX-PR_YMIN-4);
318                 rct.ymax= PR_YMIN+2+tex->cropymax*(PR_YMAX-PR_YMIN-4);
319
320                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
321
322                 glColor3ub(0, 0, 0);
323                 glRecti(rct.xmin+1,  rct.ymin-1,  rct.xmax+1,  rct.ymax-1); 
324
325                 glColor3ub(255, 255, 255);
326                 glRecti(rct.xmin,  rct.ymin,  rct.xmax,  rct.ymax);
327
328                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);                      
329         }
330         
331 }
332
333 void BIF_all_preview_changed(void)
334 {
335         ScrArea *sa;
336         SpaceButs *sbuts;
337         
338         sa= G.curscreen->areabase.first;
339         while(sa) {
340                 if(sa->spacetype==SPACE_BUTS) {
341                         sbuts= sa->spacedata.first;
342                         sbuts->cury= 0;
343                         addafterqueue(sa->win, RENDERPREVIEW, 1);
344                 }
345                 sa= sa->next;
346         }
347 }
348
349 /* signal all previews in current screen of current type */
350 void BIF_preview_changed(SpaceButs *sbuts)
351 {
352
353         /* can be called when no buttonswindow visible */
354         if(sbuts) {
355                 ScrArea *sa;
356                 short mainb= sbuts->mainb;
357                 short tab= sbuts->tab[mainb];
358                 
359                 sa= G.curscreen->areabase.first;
360                 while(sa) {
361                         if(sa->spacetype==SPACE_BUTS) {
362                                 sbuts= sa->spacedata.first;
363                                 if(sbuts->mainb==mainb && sbuts->tab[mainb]==tab) {
364                                         sbuts->cury= 0;
365                                         addafterqueue(sbuts->area->win, RENDERPREVIEW, 1);
366                                 }
367                         }
368                         sa= sa->next;
369                 }
370         }
371 }
372
373 /* is panel callback, supposed to be called with correct panel offset matrix */
374 void BIF_previewdraw(void)
375 {
376         SpaceButs *sbuts= curarea->spacedata.first;
377         
378         if (sbuts->rect==0) BIF_preview_changed(sbuts);
379         else {
380                 int y;
381
382                 set_previewrect(sbuts->area->win, PR_XMIN, PR_YMIN, PR_XMAX, PR_YMAX);
383                 
384                 for (y=0; y<PR_RECTY; y++) {
385                         display_pr_scanline(sbuts->rect, y);
386                 }
387
388                 end_previewrect();
389                 
390                 if (sbuts->mainb==CONTEXT_SHADING && sbuts->tab[CONTEXT_SHADING]==TAB_SHADING_TEX) {
391                         draw_tex_crop(sbuts->lockpoin);
392                 }
393         }
394         if(sbuts->cury==0) BIF_preview_changed(sbuts);
395         
396 }
397
398 static void sky_preview_pixel(float lens, int x, int y, char *rect)
399 {
400         float view[3];
401         
402         if(R.wrld.skytype & WO_SKYPAPER) {
403                 view[0]= (2*x)/(float)PR_RECTX;
404                 view[1]= (2*y)/(float)PR_RECTY;
405                 view[2]= 0.0f;
406         }
407         else {
408                 view[0]= x;
409                 view[1]= y;
410                 view[2]= -lens*PR_RECTX/32.0;
411                 Normalise(view);
412         }
413         RE_sky_char(view, rect);
414 }
415
416 static void lamp_preview_pixel(ShadeInput *shi, LampRen *la, int x, int y, char *rect)
417 {
418         float inpr, i, t, dist, distkw, vec[3], lacol[3];
419         int col;
420         
421         shi->co[0]= (float)x/(PR_RECTX/4);
422         shi->co[1]= (float)y/(PR_RECTX/4);
423         shi->co[2]= 0;
424         
425         vec[0]= 0.02f*x;
426         vec[1]= 0.02f*y;
427         vec[2]= 0.005f*PR_RECTX;
428         VECCOPY(shi->view, vec);
429         dist= Normalise(shi->view);
430
431         lacol[0]= la->r;
432         lacol[1]= la->g;
433         lacol[2]= la->b;
434         
435         if(la->mode & LA_TEXTURE) do_lamp_tex(la, vec, shi, lacol);
436
437         if(la->type==LA_SUN || la->type==LA_HEMI) {
438                 dist= 1.0f;
439         }
440         else {
441                 
442                 if(la->mode & LA_QUAD) {
443                         
444                         t= 1.0f;
445                         if(la->ld1>0.0f)
446                                 t= la->dist/(la->dist+la->ld1*dist);
447                         if(la->ld2>0.0f) {
448                                 distkw= la->dist*la->dist;
449                                 t= t*distkw/(t*distkw+la->ld2*dist*dist);
450                         }
451                         dist= t;
452                 }
453                 else {
454                         dist= (la->dist/(la->dist+dist));
455                 }
456         }
457
458         /* yafray: preview shade as spot, sufficient */
459         if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
460
461                 
462                 if(la->mode & LA_SQUARE) {
463                         /* slightly smaller... */
464                         inpr= 1.7*cos(MAX2(fabs(shi->view[0]/shi->view[2]) , fabs(shi->view[1]/shi->view[2]) ));
465                 }
466                 else {
467                         inpr= shi->view[2];
468                 }
469                 
470                 t= la->spotsi;
471                 if(inpr<t) dist= 0.0f;
472                 else {
473                         t= inpr-t;
474                         if(t<la->spotbl && la->spotbl!=0.0f) {
475                                 /* soft area */
476                                 i= t/la->spotbl;
477                                 t= i*i;
478                                 i= t*i;
479                                 inpr*=(3.0*t-2.0*i);
480                         }
481                 }
482                 dist*=inpr;
483         }
484         else if ELEM(la->type, LA_LOCAL, LA_AREA) dist*= shi->view[2];
485         
486         col= 255.0*dist*lacol[0];
487         if(col<=0) rect[0]= 0; else if(col>=255) rect[0]= 255; else rect[0]= col;
488
489         col= 255.0*dist*lacol[1];
490         if(col<=0) rect[1]= 0; else if(col>=255) rect[1]= 255; else rect[1]= col;
491
492         col= 255.0*dist*lacol[2];
493         if(col<=0) rect[2]= 0; else if(col>=255) rect[2]= 255; else rect[2]= col;
494 }
495
496 static void init_previewhalo(HaloRen *har, Material *mat)
497 {
498         
499         har->type= 0;
500         if(mat->mode & MA_HALO_XALPHA) har->type |= HA_XALPHA;
501         har->mat= mat;
502         har->hard= mat->har;
503         har->rad= PR_RECTX/2.0;
504         har->radsq= PR_RECTX*PR_RECTX/4.0;
505         har->alfa= mat->alpha;
506         har->add= 255.0*mat->add;
507         har->r= mat->r;
508         har->g= mat->g; 
509         har->b= mat->b;
510         har->xs= PR_RECTX/2.0;
511         har->ys= PR_RECTX/2.0;
512         har->zs= har->zd= 0;
513         har->seed= (mat->seed1 % 256);
514         
515         if( (mat->mode & MA_HALOTEX) && mat->mtex[0] ) har->tex= 1; else har->tex=0;
516
517         if(mat->mode & MA_STAR) har->starpoints= mat->starc; else har->starpoints= 0;
518         if(mat->mode & MA_HALO_LINES) har->linec= mat->linec; else har->linec= 0;
519         if(mat->mode & MA_HALO_RINGS) har->ringc= mat->ringc; else har->ringc= 0;
520         if(mat->mode & MA_HALO_FLARE) har->flarec= mat->flarec; else har->flarec= 0;
521         
522         if(har->flarec) {
523                 har->xs-= PR_RECTX/3;
524                 har->ys+= PR_RECTX/3;
525                 
526                 har->rad*= 0.3;
527                 har->radsq= har->rad*har->rad;
528                 
529                 har->pixels= har->rad*har->rad*har->rad;
530         }
531 }       
532
533 static void halo_preview_pixel(HaloRen *har, int startx, int endx, int y, char *rect)
534 {
535         float dist, xn, yn, xsq, ysq, colf[4];
536         int x;
537         char front[4];
538         
539         if(har->flarec) yn= y-PR_RECTX/3;
540         else yn= y;
541         ysq= yn*yn;
542         
543         for(x=startx; x<endx; x++) {
544                 
545                 if(har->flarec) xn= x+PR_RECTX/3;
546                 else xn= x;
547                 
548                 xsq= xn*xn;
549                 dist= xsq+ysq;
550
551                 if(dist<har->radsq) {
552                         RE_shadehalo(har, front, colf, 0, dist, xn, yn, har->flarec);
553                         RE_addalphaAddfac(rect, front, har->add);
554                 }
555                 rect+= 4;
556         }
557 }
558
559 static void previewflare(SpaceButs *sbuts, HaloRen *har, unsigned int *rect)
560 {
561         uiBlock *block;
562         float ycor;
563         unsigned int *rectot;
564         int afmx, afmy, rectx, recty, y;
565         
566         block= uiFindOpenPanelBlockName(&curarea->uiblocks, "Preview");
567         if(block==NULL) return;
568
569         /* temps */
570         ycor= R.ycor;
571         rectx= R.rectx;
572         recty= R.recty;
573         afmx= R.afmx;
574         afmy= R.afmy;
575         rectot= R.rectot;
576
577         R.r.postmul= R.r.postgamma= R.r.postsat= 1.0f;
578         R.r.posthue= R.r.postadd= 0.0f;
579         R.ycor= 1.0f;
580         R.rectx= PR_RECTX;      
581         R.recty= PR_RECTY;
582         R.afmx= PR_RECTX/2;
583         R.afmy= PR_RECTY/2;
584         R.rectot= rect;
585
586         waitcursor(1);
587         RE_renderflare(har);
588         waitcursor(0);
589         // not sure why, either waitcursor or renderflare screws up (disabled then)
590         //areawinset(curarea->win);
591         
592         /* draw can just be this way, all settings are OK */
593         for (y=0; y<PR_RECTY; y++) {
594                 display_pr_scanline(sbuts->rect, y);
595         }
596         
597         /* temps */
598         R.ycor= ycor;
599         R.rectx= rectx;
600         R.recty= recty;
601         R.afmx= afmx;
602         R.afmy= afmy;
603         R.rectot= rectot;
604 }
605
606 static void texture_preview_pixel(Tex *tex, int x, int y, char *rect)
607 {
608         float i, v1, xsq, ysq, texvec[3];
609         float tin=1.0f, tr, tg, tb, ta;
610         int rgbnor, tracol, skip=0;
611         
612         if(tex->type==TEX_IMAGE) {
613                 v1= 1.0f/PR_RECTX;
614                 
615                 texvec[0]= 0.5+v1*x;
616                 texvec[1]= 0.5+v1*y;
617                 
618                 /* no coordinate mapping, exception: repeat */
619                 if(tex->extend==TEX_REPEAT) {
620                         if(tex->xrepeat>1) {
621                                 texvec[0] *= tex->xrepeat;
622                                 if(texvec[0]>1.0f) texvec[0] -= (int)(texvec[0]);
623                         }
624                         if(tex->yrepeat>1) {
625                                 texvec[1] *= tex->yrepeat;
626                                 if(texvec[1]>1.0f) texvec[1] -= (int)(texvec[1]);
627                         }
628                 }
629                 else if(tex->extend==TEX_CHECKER) {
630                         texvec[0]= 0.5+1.6*v1*x;
631                         texvec[1]= 0.5+1.6*v1*y;
632                 }
633         }
634         else if(tex->type==TEX_ENVMAP) {
635                 if(tex->env) {
636                         ysq= y*y;
637                         xsq= x*x;
638                         if(xsq+ysq < (PR_RECTX/2)*(PR_RECTY/2)) {
639                                 texvec[2]= sqrt( (float)((PR_RECTX/2)*(PR_RECTY/2)-xsq-ysq) );
640                                 texvec[0]= -x;
641                                 texvec[1]= -y;
642                                 Normalise(texvec);
643
644                                 i= 2.0*(texvec[2]);
645                                 texvec[0]= (i*texvec[0]);
646                                 texvec[1]= (i*texvec[1]);
647                                 texvec[2]= (-1.0f+i*texvec[2]);
648
649                         }
650                         else {
651                                 skip= 1;
652                                 tr= tg= tb= ta= 0.0f;
653                         }
654                 }
655                 else {
656                         skip= 1;
657                         tr= tg= tb= ta= 0.0f;
658                 }
659         }
660         else {
661                 v1= 2.0/PR_RECTX;
662         
663                 texvec[0]= v1*x;
664                 texvec[1]= v1*y;
665                 texvec[2]= 0.0f;
666         }
667         
668         if(skip==0) rgbnor= multitex_ext(tex, texvec, &tin, &tr, &tg, &tb, &ta);
669         else rgbnor= 1;
670         
671         if(rgbnor & 1) {
672                 
673                 v1= 255.0*tr;
674                 rect[0]= CLAMPIS(v1, 0, 255);
675                 v1= 255.0*tg;
676                 rect[1]= CLAMPIS(v1, 0, 255);
677                 v1= 255.0*tb;
678                 rect[2]= CLAMPIS(v1, 0, 255);
679                 
680                 if(ta!=1.0f) {
681                         tracol=  64+100*(abs(x)>abs(y));
682                         tracol= (1.0f-ta)*tracol;
683                         
684                         rect[0]= tracol+ (rect[0]*ta) ;
685                         rect[1]= tracol+ (rect[1]*ta) ;
686                         rect[2]= tracol+ (rect[2]*ta) ;
687                                         
688                 }
689         }
690         else {
691                 rect[0]= 255.0*tin;
692                 rect[1]= 255.0*tin;
693                 rect[2]= 255.0*tin;
694         }
695 }
696
697 static float pr1_lamp[3]= {2.3, -2.4, -4.6};
698 static float pr2_lamp[3]= {-8.8, -5.6, -1.5};
699 static float pr1_col[3]= {0.8, 0.8, 0.8};
700 static float pr2_col[3]= {0.5, 0.6, 0.7};
701
702 static void refraction_prv(int *x, int *y, float *n, float index)
703 {
704         float dot, fac, view[3], len;
705
706         index= 1.0f/index;
707         
708         view[0]= index*(float)*x;
709         view[1]= ((float)*y)/index;
710         view[2]= 20.0f;
711         len= Normalise(view);
712         
713         dot= view[0]*n[0] + view[1]*n[1] + view[2]*n[2];
714
715         if(dot>0.0f) {
716                 fac= 1.0f - (1.0f - dot*dot)*index*index;
717                 if(fac<= 0.0f) return;
718                 fac= -dot*index + sqrt(fac);
719         }
720         else {
721                 index = 1.0f/index;
722                 fac= 1.0f - (1.0f - dot*dot)*index*index;
723                 if(fac<= 0.0f) return;
724                 fac= -dot*index - sqrt(fac);
725         }
726
727         *x= (int)(len*(index*view[0] + fac*n[0]));
728         *y= (int)(len*(index*view[1] + fac*n[1]));
729 }
730
731 static void shade_lamp_loop_preview(ShadeInput *shi, ShadeResult *shr, int pr_lamp)
732 {
733         extern float fresnel_fac(float *view, float *vn, float ior, float fac);
734         Material *mat= shi->mat;
735         float inp, is, inprspec=0;
736         float lv[3], *la;
737         int a;
738         
739         // copy all relevant material vars, note, keep this synced with render_types.h
740         memcpy(&shi->r, &mat->r, 23*sizeof(float));
741         // set special cases:
742         shi->har= mat->har;
743         
744         if((mat->mode & MA_RAYMIRROR)==0) shi->ray_mirror= 0.0f;
745         memset(shr, 0, sizeof(ShadeResult));
746         
747         /* normals flipped in render for smooth... */
748         if( (mat->mapto & MAP_NORM)) VecMulf(shi->vn, -1.0f);
749         
750         do_material_tex(shi);
751         
752         /* normals flipped in render... */
753         if( (mat->mapto & MAP_NORM)) VecMulf(shi->vn, -1.0f);   
754         
755         shr->alpha= shi->alpha;
756         
757         if(mat->mode & (MA_ZTRA|MA_RAYTRANSP)) 
758                 if(mat->fresnel_tra!=0.0f) 
759                         shr->alpha*= fresnel_fac(shi->view, shi->vn, mat->fresnel_tra_i, mat->fresnel_tra);
760         
761         if(mat->mode & MA_SHLESS) {
762                 shr->diff[0]= shi->r;
763                 shr->diff[1]= shi->g;
764                 shr->diff[2]= shi->b;
765                 
766         }
767         else {
768                 
769                 for(a=0; a<2; a++) {
770                         
771                         if((pr_lamp & (1<<a))==0) continue;
772                         
773                         if(a==0) la= pr1_lamp;
774                         else la= pr2_lamp;
775                         
776                         lv[0]= shi->co[0]-la[0];
777                         lv[1]= shi->co[1]-la[1];
778                         lv[2]= shi->co[2]-la[2];
779                         Normalise(lv);
780                         
781                         is= shi->vn[0]*lv[0]+shi->vn[1]*lv[1]+shi->vn[2]*lv[2];
782                         if(is<0.0f) is= 0.0f;
783                         
784                         if(shi->spec>0.0f)  {
785                                 
786                                 if(is>0.0f) {
787                                         /* specular shaders */
788                                         float specfac;
789                                         
790                                         if(mat->spec_shader==MA_SPEC_PHONG) 
791                                                 specfac= Phong_Spec(shi->vn, lv, shi->view, shi->har, 0);
792                                         else if(mat->spec_shader==MA_SPEC_COOKTORR) 
793                                                 specfac= CookTorr_Spec(shi->vn, lv, shi->view, shi->har, 0);
794                                         else if(mat->spec_shader==MA_SPEC_BLINN) 
795                                                 specfac= Blinn_Spec(shi->vn, lv, shi->view, mat->refrac, (float)shi->har, 0);
796                                         else if(mat->spec_shader==MA_SPEC_WARDISO)
797                                                 specfac= WardIso_Spec(shi->vn, lv, shi->view, mat->rms, 0);
798                                         else 
799                                                 specfac= Toon_Spec(shi->vn, lv, shi->view, mat->param[2], mat->param[3], 0);
800                                         
801                                         inprspec= specfac*shi->spec;
802                                         
803                                         if(mat->mode & MA_RAMP_SPEC) {
804                                                 float spec[3];
805                                                 do_specular_ramp(shi, specfac, inprspec, spec);
806                                                 shr->spec[0]+= inprspec*spec[0];
807                                                 shr->spec[1]+= inprspec*spec[1];
808                                                 shr->spec[2]+= inprspec*spec[2];
809                                         }
810                                         else {  
811                                                 shr->spec[0]+= inprspec*shi->specr;
812                                                 shr->spec[1]+= inprspec*shi->specg;
813                                                 shr->spec[2]+= inprspec*shi->specb;
814                                         }
815                                 }
816                         }
817                         /* diffuse shaders */
818                         if(mat->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(shi->vn, lv, shi->view, mat->roughness);
819                         else if(mat->diff_shader==MA_DIFF_TOON) is= Toon_Diff(shi->vn, lv, shi->view, mat->param[0], mat->param[1]);
820                         else if(mat->diff_shader==MA_DIFF_MINNAERT) is= Minnaert_Diff(is, shi->vn, shi->view, mat->darkness);
821                         else if(mat->diff_shader==MA_DIFF_FRESNEL) is= Fresnel_Diff(shi->vn, lv, shi->view, mat->param[0], mat->param[1]);
822                         // else Lambert
823                         
824                         inp= (shi->refl*is + shi->emit);
825                         
826                         if(a==0) la= pr1_col;
827                         else la= pr2_col;
828                         
829                         add_to_diffuse(shr->diff, shi, is, inp*la[0], inp*la[1], inp*la[2]);
830                 }
831                 /* end lamp loop */
832                 
833                 /* drawing checkerboard and sky */
834                 if(mat->mode & MA_RAYMIRROR) {
835                         float col, div, y, z;
836                         int fac;
837                         
838                         /* rotate a bit in x */
839                         y= shi->ref[1]; z= shi->ref[2];
840                         shi->ref[1]= 0.98*y - 0.17*z;
841                         shi->ref[2]= 0.17*y + 0.98*z;
842                         
843                         /* scale */
844                         div= (0.85f*shi->ref[1]);
845                         
846                         shi->refcol[0]= shi->ray_mirror*fresnel_fac(shi->view, shi->vn, mat->fresnel_mir_i, mat->fresnel_mir);
847                         /* not real 'alpha', but mirror overriding transparency */
848                         if(mat->mode & MA_RAYTRANSP) {
849                                 float fac= sqrt(shi->refcol[0]);
850                                 shr->alpha= shr->alpha*(1.0f-fac) + fac;
851                         }
852                         else shr->alpha= shr->alpha*(1.0f-shi->refcol[0]) + shi->refcol[0];
853                         
854                         if(div<0.0f) {
855                                 /* minus 0.5 prevents too many small tiles in distance */
856                                 fac= (int)(shi->ref[0]/(div-0.1f) ) + (int)(shi->ref[2]/(div-0.1f) );
857                                 if(fac & 1) col= 0.8f;
858                                 else col= 0.3f;
859                                 
860                                 shi->refcol[1]= shi->refcol[0]*col;
861                                 shi->refcol[2]= shi->refcol[1];
862                                 shi->refcol[3]= shi->refcol[2];
863                         }
864                         else {
865                                 shi->refcol[1]= 0.0f;
866                                 shi->refcol[2]= shi->refcol[0]*0.3f*div;
867                                 shi->refcol[3]= shi->refcol[0]*0.8f*div;
868                         }
869                 }
870                 
871                 shr->diff[0]+= shi->ambr;
872                 shr->diff[1]+= shi->ambg;
873                 shr->diff[2]+= shi->ambb;
874                 
875                 if(mat->mode & MA_RAMP_COL) ramp_diffuse_result(shr->diff, shi);
876                 if(mat->mode & MA_RAMP_SPEC) ramp_spec_result(shr->spec, shr->spec+1, shr->spec+2, shi);
877                 
878                 /* refcol */
879                 if(shi->refcol[0]!=0.0f) {
880                         shr->diff[0]= shi->mirr*shi->refcol[1] + (1.0f - shi->mirr*shi->refcol[0])*shr->diff[0];
881                         shr->diff[1]= shi->mirg*shi->refcol[2] + (1.0f - shi->mirg*shi->refcol[0])*shr->diff[1];
882                         shr->diff[2]= shi->mirb*shi->refcol[3] + (1.0f - shi->mirb*shi->refcol[0])*shr->diff[2];
883                 }
884         
885                 /* ztra shade */
886                 if(shi->spectra!=0.0f) {
887                         inp = MAX3(shr->spec[0], shr->spec[1], shr->spec[2]);
888                         inp *= shi->spectra;
889                         if(inp>1.0f) inp= 1.0f;
890                         shr->alpha= (1.0f-inp)*shr->alpha+inp;
891                 }
892         }       
893 }
894
895 static void shade_preview_pixel(ShadeInput *shi, float *vec, int x, int y, char *rect, int smooth)
896 {
897         Material *mat;
898         MaterialLayer *ml;
899         ShadeResult shr;
900         float v1, inp;
901         float eul[3], tmat[3][3], imat[3][3], col[3];
902         char tracol;
903                 
904         mat= shi->mat;
905
906         v1= 1.0/PR_RECTX;
907         shi->view[0]= v1*x;
908         shi->view[1]= v1*y;
909         shi->view[2]= 1.0f;
910         Normalise(shi->view);
911         
912         shi->xs= (float)x;
913         shi->ys= (float)y;
914         
915         shi->refcol[0]= shi->refcol[1]= shi->refcol[2]= shi->refcol[3]= 0.0f;
916         VECCOPY(shi->co, vec);
917         
918         /* texture handling */
919         if(mat->texco) {
920                 
921                 VECCOPY(shi->lo, vec);
922                 
923                 if(mat->pr_type==MA_CUBE) {
924                         
925                         eul[0]= (297)*M_PI/180.0;
926                         eul[1]= 0.0;
927                         eul[2]= (45)*M_PI/180.0;
928                         EulToMat3(eul, tmat);
929
930                         MTC_Mat3MulVecfl(tmat, shi->lo);
931                         MTC_Mat3MulVecfl(tmat, shi->vn);
932                         /* hack for cubemap, why!!! */
933                         SWAP(float, shi->vn[0], shi->vn[1]);
934                 }
935                 /* textures otherwise upside down */
936                 if(mat->pr_type==MA_CUBE || mat->pr_type==MA_SPHERE) 
937                         shi->lo[2]= -shi->lo[2];
938
939                 if(mat->texco & TEXCO_GLOB) {
940                         VECCOPY(shi->gl, shi->lo);
941                 }
942                 if(mat->texco & TEXCO_WINDOW) {
943                         VECCOPY(shi->winco, shi->lo);
944                 }
945                 if(mat->texco & TEXCO_STICKY) {
946                         VECCOPY(shi->sticky, shi->lo);
947                 }
948                 if(mat->texco & TEXCO_UV) {
949                         VECCOPY(shi->uv, shi->lo);
950                 }
951                 if(mat->texco & TEXCO_STRAND) {
952                         shi->strand= shi->lo[0];
953                 }
954                 if(mat->texco & TEXCO_OBJECT) {
955                         /* nothing */
956                 }
957                 if(mat->texco & (TEXCO_NORM)) {
958                         shi->orn[0]= shi->vn[0];
959                         shi->orn[1]= shi->vn[1];
960                         shi->orn[2]= shi->vn[2];
961                 }
962                 if(mat->texco & TEXCO_REFL) {
963                         
964                         inp= -2.0*(shi->vn[0]*shi->view[0]+shi->vn[1]*shi->view[1]+shi->vn[2]*shi->view[2]);
965                         shi->ref[0]= (shi->view[0]+inp*shi->vn[0]);
966                         shi->ref[1]= (shi->view[1]+inp*shi->vn[1]);
967                         shi->ref[2]= (shi->view[2]+inp*shi->vn[2]);
968                 }
969
970                 /* Clear displase vec for preview */
971                 shi->displace[0]= shi->displace[1]= shi->displace[2]= 0.0;
972                         
973                 if(mat->texco & TEXCO_REFL) {
974                         /* normals in render are pointing different... rhm */
975                         if(smooth) shi->ref[1]= -shi->ref[1];
976                 }
977
978                 if(mat->pr_type==MA_CUBE) {
979                         /* rotate normal back for normals texture */
980                         SWAP(float, shi->vn[0], shi->vn[1]);
981                         MTC_Mat3Inv(imat, tmat);
982                         MTC_Mat3MulVecfl(imat, shi->vn);
983                 }
984                 
985         }
986
987         if(mat->mapto & MAP_DISPLACE) { /* Quick hack of fake displacement preview */
988 //              shi->vn[0]-=2.0*shi->displace[2];
989 //              shi->vn[1]-=2.0*shi->displace[0];
990 //              shi->vn[2]+=2.0*shi->displace[1];
991 //              Normalise(shi->vn);
992         }
993
994         /* ------  main shading loop with material layers */
995         VECCOPY(shi->vno, shi->vn);
996         if(mat->ml_flag & ML_RENDER) 
997                 shade_lamp_loop_preview(shi, &shr, mat->pr_lamp);
998         else {
999                 memset(&shr, 0, sizeof(ShadeResult));
1000                 shr.alpha= 1.0f;
1001         }
1002
1003         for(ml= mat->layers.first; ml; ml= ml->next) {
1004                 if(ml->mat && (ml->flag & ML_RENDER)) {
1005                         ShadeResult shrlay;
1006                         
1007                         shi->mat= ml->mat;
1008                         shi->layerfac= ml->blendfac;
1009                         VECCOPY(shi->vn, shi->vno);
1010                         if(ml->flag & ML_NEG_NORMAL)
1011                                 VecMulf(shi->vn, -1.0);
1012
1013                         shade_lamp_loop_preview(shi, &shrlay, mat->pr_lamp);
1014                         matlayer_blend(ml, shi->layerfac, &shr, &shrlay);
1015                 }
1016         }
1017
1018         shi->mat= mat;  /* restore, shade input is re-used! */
1019
1020         /* after shading and composit layers */
1021         if(shr.spec[0]<0.0f) shr.spec[0]= 0.0f;
1022         if(shr.spec[1]<0.0f) shr.spec[1]= 0.0f;
1023         if(shr.spec[2]<0.0f) shr.spec[2]= 0.0f;
1024
1025         if(shr.diff[0]<0.0f) shr.diff[0]= 0.0f;
1026         if(shr.diff[1]<0.0f) shr.diff[1]= 0.0f;
1027         if(shr.diff[2]<0.0f) shr.diff[2]= 0.0f;
1028
1029         VECADD(col, shr.diff, shr.spec);
1030         if(col[0]<=0.0f) rect[0]= 0; else if(col[0]>=1.0f) rect[0]= 255; else rect[0]= (char)(255.0*col[0]);
1031         if(col[1]<=0.0f) rect[1]= 0; else if(col[1]>=1.0f) rect[1]= 255; else rect[1]= (char)(255.0*col[1]);
1032         if(col[2]<=0.0f) rect[2]= 0; else if(col[2]>=1.0f) rect[2]= 255; else rect[2]= (char)(255.0*col[2]);
1033
1034         if(shr.alpha!=1.0f) {
1035                 if(mat->mode & MA_RAYTRANSP) {
1036                         refraction_prv(&x, &y, shi->vn, shi->ang);
1037                 }
1038                 
1039                 tracol=  previewback(mat->pr_back, x, y) & 255;
1040                 
1041                 tracol= (1.0f-shr.alpha)*tracol;
1042                 
1043                 if((mat->mode & MA_RAYTRANSP) && mat->filter!=0.0) {
1044                         float fr= 1.0f+ mat->filter*(shr.diff[0]-1.0f);
1045                         rect[0]= fr*tracol+ (rect[0]*shr.alpha) ;
1046                         fr= 1.0f+ mat->filter*(shr.diff[0]-1.0f);
1047                         rect[1]= fr*tracol+ (rect[1]*shr.alpha) ;
1048                         fr= 1.0f+ mat->filter*(shr.diff[0]-1.0f);
1049                         rect[2]= fr*tracol+ (rect[2]*shr.alpha) ;
1050                 }
1051                 else {
1052                         rect[0]= tracol+ (rect[0]*shr.alpha) ;
1053                         rect[1]= tracol+ (rect[1]*shr.alpha) ;
1054                         rect[2]= tracol+ (rect[2]*shr.alpha) ;
1055                 }
1056         }
1057 }
1058
1059 static void preview_init_render_textures(MTex **mtex)
1060 {
1061         int x;
1062         
1063         for(x=0; x<MAX_MTEX; x++) {
1064                 if(mtex[x]) {
1065                         if(mtex[x]->tex) {
1066                                 init_render_texture(mtex[x]->tex);
1067                                 
1068                                 if(mtex[x]->tex->env && mtex[x]->tex->env->object) 
1069                                         MTC_Mat4One(mtex[x]->tex->env->object->imat);
1070                                 
1071                         }
1072                         if(mtex[x]->object) MTC_Mat4One(mtex[x]->object->imat);
1073                         if(mtex[x]->object) MTC_Mat4One(mtex[x]->object->imat);
1074                 }
1075         }
1076         
1077 }
1078
1079 void BIF_previewrender(SpaceButs *sbuts)
1080 {
1081         static double lasttime= 0;
1082         ID *id, *idfrom;
1083         Material *mat= NULL;
1084         Tex *tex= NULL;
1085         Lamp *la= NULL;
1086         World *wrld= NULL;
1087         LampRen *lar= NULL;
1088         Image *ima;
1089         HaloRen har;
1090         Object *ob;
1091         uiBlock *block;
1092         ShadeInput shi;
1093         float lens = 0.0, vec[3];
1094         int x, y, starty, startx, endy, endx, radsq, xsq, ysq, last = 0;
1095         unsigned int *rect;
1096
1097         if(sbuts->cury>=PR_RECTY) return;
1098         
1099         /* we safely assume curarea has panel "preview" */
1100         /* quick hack for now, later on preview should become uiBlock itself */
1101         
1102         block= uiFindOpenPanelBlockName(&curarea->uiblocks, "Preview");
1103         if(block==NULL) return;
1104
1105         ob= ((G.scene->basact)? (G.scene->basact)->object: 0);
1106         
1107         /* we cant trust this global lockpoin.. for example with headerless window */
1108         buttons_active_id(&id, &idfrom);
1109         G.buts->lockpoin= id;
1110
1111         if(sbuts->mainb==CONTEXT_SHADING) {
1112                 int tab= sbuts->tab[CONTEXT_SHADING];
1113                 
1114                 if(tab==TAB_SHADING_MAT) 
1115                         mat= sbuts->lockpoin;
1116                 else if(tab==TAB_SHADING_TEX) 
1117                         tex= sbuts->lockpoin;
1118                 else if(tab==TAB_SHADING_LAMP) {
1119                         if(ob && ob->type==OB_LAMP) la= ob->data;
1120                 }
1121                 else if(tab==TAB_SHADING_WORLD)
1122                         wrld= sbuts->lockpoin;
1123         }
1124         else if(sbuts->mainb==CONTEXT_OBJECT) {
1125                 if(ob && ob->type==OB_LAMP) la= ob->data;
1126         }
1127         
1128         /* return: when no active block to render. but we do draw black if possible */
1129         if(mat==NULL && tex==NULL && la==NULL && wrld==NULL) {
1130                 if(sbuts->rect) {
1131                         memset(sbuts->rect, 0, sizeof(int)*PR_RECTX*PR_RECTY);
1132                         sbuts->cury= PR_RECTY;
1133                         addqueue(curarea->win, REDRAW, 1);
1134                 }
1135                 return;
1136         }
1137         
1138         har.flarec= 0;  /* below is a test for postrender flare */
1139         
1140         if(qtest()) {
1141                 addafterqueue(curarea->win, RENDERPREVIEW, 1);
1142                 return;
1143         }
1144
1145         MTC_Mat4One(R.viewmat);
1146         MTC_Mat4One(R.viewinv);
1147         
1148         shi.osatex= 0;
1149         
1150         if(mat) {
1151                 MaterialLayer *ml;
1152                 
1153                 /* rendervars */
1154                 init_render_world();
1155                 init_render_material(mat);
1156                 /* also clears imats */
1157                 preview_init_render_textures(mat->mtex);
1158                 
1159                 for(ml= mat->layers.first; ml; ml= ml->next) {
1160                         if(ml->mat && (ml->flag & ML_RENDER)) {
1161                                 init_render_material(ml->mat);
1162                                 preview_init_render_textures(ml->mat->mtex);
1163                                 mat->texco |= ml->mat->texco;
1164                         }
1165                 }
1166                 
1167                 shi.vlr= NULL;          
1168                 shi.mat= mat;
1169                 
1170                 if(mat->mode & MA_HALO) init_previewhalo(&har, mat);
1171         }
1172         else if(tex) {
1173
1174                 ima= tex->ima;
1175                 if(ima) last= ima->lastframe;
1176                 init_render_texture(tex);
1177                 free_unused_animimages();
1178                 if(tex->ima) {
1179                         if(tex->ima!=ima) allqueue(REDRAWBUTSSHADING, 0);
1180                         else if(last!=ima->lastframe) allqueue(REDRAWBUTSSHADING, 0);
1181                 }
1182                 if(tex->env && tex->env->object) 
1183                         MTC_Mat4Invert(tex->env->object->imat, tex->env->object->obmat);
1184         }
1185         else if(la) {
1186
1187                 init_render_world();
1188                 preview_init_render_textures(la->mtex);
1189                 R.totlamp= 0;
1190                 RE_add_render_lamp(ob, 0);      /* 0=no shadbuf or tables */
1191                 lar= R.la[0];
1192                 
1193                 /* exceptions: */
1194                 lar->spottexfac= 1.0f;
1195                 lar->spotsi= cos( M_PI/3.0f );
1196                 lar->spotbl= (1.0f-lar->spotsi)*la->spotblend;
1197                 
1198                 MTC_Mat3One(lar->imat);
1199         }
1200         else if(wrld) {
1201                 
1202                 lens= 35.0;
1203                 if(G.scene->camera) {
1204                         lens= ( (Camera *)G.scene->camera->data)->lens;
1205
1206                         /* needed for init_render_world */
1207                         MTC_Mat4CpyMat4(R.viewinv, G.scene->camera->obmat);
1208                         MTC_Mat4Ortho(R.viewinv);
1209                         MTC_Mat4Invert(R.viewmat, R.viewinv);
1210                 }
1211                 init_render_world();
1212                 preview_init_render_textures(wrld->mtex);       
1213         }
1214
1215         uiPanelPush(block);     // sets UImat
1216         
1217         set_previewrect(sbuts->area->win, PR_XMIN, PR_YMIN, PR_XMAX, PR_YMAX); // uses UImat
1218
1219         if(sbuts->rect==NULL) {
1220                 sbuts->rect= MEM_callocN(sizeof(int)*PR_RECTX*PR_RECTY, "butsrect");
1221                 
1222                 /* built in emboss */
1223                 rect= sbuts->rect;
1224                 for(y=0; y<PR_RECTY; y++, rect++) *rect= 0xFFFFFFFF;
1225                 
1226                 rect= sbuts->rect + PR_RECTX-1;
1227                 for(y=0; y<PR_RECTY; y++, rect+=PR_RECTX) *rect= 0xFFFFFFFF;
1228         }
1229         
1230         starty= -PR_RECTY/2;
1231         endy= starty+PR_RECTY;
1232         starty+= sbuts->cury;
1233         
1234         /* offset +1 for emboss */
1235         startx= -PR_RECTX/2 +1;
1236         endx= startx+PR_RECTX -2;
1237
1238         radsq= (PR_RECTX/2)*(PR_RECTY/2);
1239         
1240         if(mat) {
1241                 if(mat->pr_type==MA_SPHERE) {
1242                         pr1_lamp[0]= 2.3; pr1_lamp[1]= -2.4; pr1_lamp[2]= -4.6;
1243                         pr2_lamp[0]= -8.8; pr2_lamp[1]= -5.6; pr2_lamp[2]= -1.5;
1244                 }
1245                 else {
1246                         pr1_lamp[0]= 1.9; pr1_lamp[1]= 3.1; pr1_lamp[2]= -8.5;
1247                         pr2_lamp[0]= 1.2; pr2_lamp[1]= -18; pr2_lamp[2]= 3.2;
1248                 }
1249         }
1250
1251         /* here it starts! */
1252         glDrawBuffer(GL_FRONT);
1253
1254         for(y=starty; y<endy; y++) {
1255                 
1256                 rect= sbuts->rect + 1 + PR_RECTX*sbuts->cury;
1257                 
1258                 if(y== -PR_RECTY/2 || y==endy-1);               /* emboss */
1259                 else if(mat) {
1260                         
1261                         if(mat->mode & MA_HALO) {
1262                                 for(x=startx; x<endx; x++, rect++) {
1263                                         rect[0]= previewback(mat->pr_back, x, y);
1264                                 }
1265
1266                                 if(har.flarec) {
1267                                         if(y==endy-2) previewflare(sbuts, &har, sbuts->rect);
1268                                 }
1269                                 else {
1270                                         halo_preview_pixel(&har, startx, endx, y, (char *) (rect-PR_RECTX));
1271                                 }
1272                         }
1273                         else {
1274                                 ysq= y*y;
1275                                 for(x=startx; x<endx; x++, rect++) {
1276                                         xsq= x*x;
1277                                         if(mat->pr_type==MA_SPHERE) {
1278                                         
1279                                                 if(xsq+ysq <= radsq) {
1280                                                         shi.vn[0]= x;
1281                                                         shi.vn[1]= y;
1282                                                         shi.vn[2]= sqrt( (float)(radsq-xsq-ysq) );
1283                                                         Normalise(shi.vn);
1284                                                         
1285                                                         vec[0]= shi.vn[0];
1286                                                         vec[1]= shi.vn[2];
1287                                                         vec[2]= -shi.vn[1];
1288                                                         
1289                                                         shade_preview_pixel(&shi, vec, x, y, (char *)rect, 1);
1290                                                 }
1291                                                 else {
1292                                                         rect[0]= previewback(mat->pr_back, x, y);
1293                                                 }
1294                                         }
1295                                         else if(mat->pr_type==MA_CUBE) {
1296                                                 if( ray_previewrender(x, y, vec, shi.vn) ) {
1297                                                         
1298                                                         shade_preview_pixel(&shi, vec, x, y, (char *)rect, 0);
1299                                                 }
1300                                                 else {
1301                                                         rect[0]= previewback(mat->pr_back, x, y);
1302                                                 }
1303                                         }
1304                                         else {
1305                                                 vec[0]= x*(2.0f/PR_RECTX);
1306                                                 vec[1]= y*(2.0f/PR_RECTX);
1307                                                 vec[2]= 0.0;
1308                                                 
1309                                                 shi.vn[0]= shi.vn[1]= 0.0f;
1310                                                 shi.vn[2]= 1.0f;
1311                                                 
1312                                                 shade_preview_pixel(&shi, vec, x, y, (char *)rect, 0);
1313                                         }
1314                                 }
1315                         }
1316                 }
1317                 else if(tex) {
1318                         for(x=startx; x<endx; x++, rect++) {
1319                                 texture_preview_pixel(tex, x, y, (char *)rect);
1320                         }
1321                 }
1322                 else if(la) {
1323                         for(x=startx; x<endx; x++, rect++) {
1324                                 lamp_preview_pixel(&shi, lar, x, y, (char *)rect);
1325                         }
1326                 }
1327                 else  {
1328                         for(x=startx; x<endx; x++, rect++) {                            
1329                                 sky_preview_pixel(lens, x, y, (char *)rect);
1330                         }
1331                 }
1332                 
1333                 if(y<endy-2) {
1334
1335                         if(qtest()) {
1336                                 addafterqueue(curarea->win, RENDERPREVIEW, 1);
1337                                 break;
1338                         }
1339                 }
1340
1341                 display_pr_scanline(sbuts->rect, sbuts->cury);
1342                 
1343                 /* flush opengl for cards with frontbuffer slowness */
1344                 if(sbuts->cury==PR_RECTY-1 || (PIL_check_seconds_timer() - lasttime > 0.05)) {
1345                         lasttime= PIL_check_seconds_timer();
1346                         glFlush();
1347                 }
1348                 
1349                 sbuts->cury++;
1350         }
1351
1352         end_previewrect();
1353         
1354         if(sbuts->cury>=PR_RECTY && tex) 
1355                 if (sbuts->tab[CONTEXT_SHADING]==TAB_SHADING_TEX) 
1356                         draw_tex_crop(sbuts->lockpoin);
1357         
1358         glDrawBuffer(GL_BACK);
1359         /* draw again for clean swapbufers */
1360         BIF_previewdraw();
1361
1362         uiPanelPop(block);
1363         
1364         if(la) {
1365                 if(R.totlamp) {
1366                         MEM_freeN(R.la[0]);
1367                 }
1368                 R.totlamp= 0;
1369         }
1370 }
1371