Initial revision
[blender.git] / source / blender / render / intern / source / outerRenderLoop.c
1 /**  
2  * The outer loop for rendering, but only for calling the
3  * unified renderer :)
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 #include <stdlib.h>
37 #include <string.h>
38
39 #include "MEM_guardedalloc.h"
40 #include "BLI_blenlib.h"
41 #include "BLI_rand.h"
42
43 #include "BKE_global.h"
44 #include "BKE_object.h"
45
46 #include "render.h"
47 #include "render_intern.h"
48 #include "outerRenderLoop.h"
49 #include "renderPreAndPost.h"
50 #include "vanillaRenderPipe.h"
51 #include "renderHelp.h"
52 #include "RE_callbacks.h"
53
54 extern short pa; /* can move to inside the outer loop */
55 /* should make a gamtab module, just like the jitter... */
56 extern unsigned short *mask1[9], *mask2[9], *igamtab2;
57
58
59 /* Parts bookkeeping: done on this level, because it seems appropriate to me.*/
60 static short partsCoordinates[65][4];
61 short  setPart(short nr);/* return 0 if this is a bad part. Sets data in R....*/
62 void   initParts(void);
63 void   addPartToRect(short nr, Part *part);
64 void addToBlurBuffer(int blur);
65         
66 /* ------------------------------------------------------------------------- */
67 void addToBlurBuffer(int blur)
68 {
69         static unsigned int *blurrect= 0;
70         int tot, gamval;
71         short facr, facb;
72         char *rtr, *rtb;
73
74         if(blur<0) {
75                 if(blurrect) {
76                         if(R.rectot) MEM_freeN(R.rectot);
77                         R.rectot= blurrect;
78                         blurrect= 0;
79                 }
80         }
81         else if(blur==R.osa-1) {
82                 /* eerste keer */
83                 blurrect= MEM_mallocN(R.rectx*R.recty*sizeof(int), "rectblur");
84                 if(R.rectot) memcpy(blurrect, R.rectot, R.rectx*R.recty*4);
85         }
86         else if(blurrect) {
87                 /* accumuleren */
88
89                 facr= 256/(R.osa-blur);
90                 facb= 256-facr;
91
92                 if(R.rectot) {
93                         rtr= (char *)R.rectot;
94                         rtb= (char *)blurrect;
95                         tot= R.rectx*R.recty;
96                         while(tot--) {
97                                 if( *((unsigned int *)rtb) != *((unsigned int *)rtr) ) {
98
99                                         if(R.r.mode & R_GAMMA) {
100                                                 gamval= (facr* igamtab2[ rtr[0]<<8 ] + facb* igamtab2[ rtb[0]<<8 ])>>8;
101                                                 rtb[0]= gamtab[ gamval ]>>8;
102                                                 gamval= (facr* igamtab2[ rtr[1]<<8 ] + facb* igamtab2[ rtb[1]<<8 ])>>8;
103                                                 rtb[1]= gamtab[ gamval ]>>8;
104                                                 gamval= (facr* igamtab2[ rtr[2]<<8 ] + facb* igamtab2[ rtb[2]<<8 ])>>8;
105                                                 rtb[2]= gamtab[ gamval ]>>8;
106                                                 gamval= (facr* igamtab2[ rtr[3]<<8 ] + facb* igamtab2[ rtb[3]<<8 ])>>8;
107                                                 rtb[3]= gamtab[ gamval ]>>8;
108                                         }
109                                         else {
110                                                 rtb[0]= (facr*rtr[0] + facb*rtb[0])>>8;
111                                                 rtb[1]= (facr*rtr[1] + facb*rtb[1])>>8;
112                                                 rtb[2]= (facr*rtr[2] + facb*rtb[2])>>8;
113                                                 rtb[3]= (facr*rtr[3] + facb*rtb[3])>>8;
114                                         }
115                                 }
116                                 rtr+= 4;
117                                 rtb+= 4;
118                         }
119                 }
120                 if(blur==0) {
121                         /* laatste keer */
122                         if(R.rectot) MEM_freeN(R.rectot);
123                         R.rectot= blurrect;
124                         blurrect= 0;
125                 }
126         }
127 }
128
129
130 /* ------------------------------------------------------------------------- */
131
132 void addPartToRect(short nr, Part *part)
133 {
134         unsigned int *rt, *rp;
135         short y, heigth, len;
136
137         /* de juiste offset in rectot */
138
139         rt= R.rectot+ (partsCoordinates[nr][1]*R.rectx+ partsCoordinates[nr][0]);
140         rp= part->rect;
141         len= (partsCoordinates[nr][2]-partsCoordinates[nr][0]);
142         heigth= (partsCoordinates[nr][3]-partsCoordinates[nr][1]);
143
144         for(y=0;y<heigth;y++) {
145                 memcpy(rt, rp, 4*len);
146                 rt+=R.rectx;
147                 rp+= len;
148         }
149 }
150
151 /* ------------------------------------------------------------------------- */
152
153 void initParts()
154 {
155         short nr, xd, yd, xpart, ypart, xparts, yparts;
156         short a, xminb, xmaxb, yminb, ymaxb;
157
158         if(R.r.mode & R_BORDER) {
159                 xminb= R.r.border.xmin*R.rectx;
160                 xmaxb= R.r.border.xmax*R.rectx;
161
162                 yminb= R.r.border.ymin*R.recty;
163                 ymaxb= R.r.border.ymax*R.recty;
164
165                 if(xminb<0) xminb= 0;
166                 if(xmaxb>R.rectx) xmaxb= R.rectx;
167                 if(yminb<0) yminb= 0;
168                 if(ymaxb>R.recty) ymaxb= R.recty;
169         }
170         else {
171                 xminb=yminb= 0;
172                 xmaxb= R.rectx;
173                 ymaxb= R.recty;
174         }
175
176         xparts= R.r.xparts;     /* voor border */
177         yparts= R.r.yparts;
178
179         for(nr=0;nr<xparts*yparts;nr++)
180                 partsCoordinates[nr][0]= -1;    /* array leegmaken */
181
182         xpart= R.rectx/xparts;
183         ypart= R.recty/yparts;
184
185         /* als border: testen of aantal parts minder kan */
186         if(R.r.mode & R_BORDER) {
187                 a= (xmaxb-xminb-1)/xpart+1; /* zoveel parts in border */
188                 if(a<xparts) xparts= a;
189                 a= (ymaxb-yminb-1)/ypart+1; /* zoveel parts in border */
190                 if(a<yparts) yparts= a;
191
192                 xpart= (xmaxb-xminb)/xparts;
193                 ypart= (ymaxb-yminb)/yparts;
194         }
195
196         for(nr=0; nr<xparts*yparts; nr++) {
197
198                 if(R.r.mode & R_PANORAMA) {
199                         partsCoordinates[nr][0]= 0;
200                         partsCoordinates[nr][1]= 0;
201                         partsCoordinates[nr][2]= R.rectx;
202                         partsCoordinates[nr][3]= R.recty;
203                 }
204                 else {
205                         xd= (nr % xparts);
206                         yd= (nr-xd)/xparts;
207
208                         partsCoordinates[nr][0]= xminb+ xd*xpart;
209                         partsCoordinates[nr][1]= yminb+ yd*ypart;
210                         if(xd<R.r.xparts-1) partsCoordinates[nr][2]= partsCoordinates[nr][0]+xpart;
211                         else partsCoordinates[nr][2]= xmaxb;
212                         if(yd<R.r.yparts-1) partsCoordinates[nr][3]= partsCoordinates[nr][1]+ypart;
213                         else partsCoordinates[nr][3]= ymaxb;
214
215                         if(partsCoordinates[nr][2]-partsCoordinates[nr][0]<=0) partsCoordinates[nr][0]= -1;
216                         if(partsCoordinates[nr][3]-partsCoordinates[nr][1]<=0) partsCoordinates[nr][0]= -1;
217                 }
218         }
219 }
220
221 short setPart(short nr) /* return 0 als geen goede part */
222 {
223
224         if(partsCoordinates[nr][0]== -1) return 0;
225
226         R.xstart= partsCoordinates[nr][0]-R.afmx;
227         R.ystart= partsCoordinates[nr][1]-R.afmy;
228         R.xend= partsCoordinates[nr][2]-R.afmx;
229         R.yend= partsCoordinates[nr][3]-R.afmy;
230         R.rectx= R.xend-R.xstart;
231         R.recty= R.yend-R.ystart;
232
233         return 1;
234 }
235
236 /* ------------------------------------------------------------------------- */
237
238 void unifiedRenderingLoop(void)  /* hierbinnen de PART en FIELD lussen */
239 {
240         Part *part;
241         unsigned int *rt, *rt1, *rt2;
242         int len;
243         short blur, a,fields,fi,parts;  /* pa is globaal ivm print */
244         unsigned int *border_buf= NULL;
245         unsigned int border_x= 0;
246         unsigned int border_y= 0;
247         
248         if((R.r.mode & R_BORDER) && !(R.r.mode & R_MOVIECROP)) {
249                 border_buf= R.rectot;
250                 border_x= R.rectx;
251                 border_y= R.recty;
252                 R.rectot= 0;
253         }
254
255
256         if (R.rectz) MEM_freeN(R.rectz);
257         R.rectz = 0;
258
259         /* FIELDLUS */
260         fields= 1;
261         parts= R.r.xparts*R.r.yparts;
262
263         if(R.r.mode & R_FIELDS) {
264                 fields= 2;
265                 R.rectf1= R.rectf2= 0;  /* fieldrecten */
266                 R.r.ysch/= 2;
267                 R.afmy/= 2;
268                 R.r.yasp*= 2;
269                 R.ycor= ( (float)R.r.yasp)/( (float)R.r.xasp);
270
271         }
272
273         
274         for(fi=0; fi<fields; fi++) {
275
276                 /* INIT */
277                 BLI_srand( 2*(G.scene->r.cfra)+fi);
278         
279
280                 R.vlaknr= -1;
281                 R.flag|= R_RENDERING;
282                 if(fi==1) R.flag |= R_SEC_FIELD;
283         
284
285                 /* MOTIONBLUR lus */
286                 if(R.r.mode & R_MBLUR) blur= R.osa;
287                 else blur= 1;
288
289         
290                 while(blur--) {
291
292                         /* WINDOW */
293                         R.rectx= R.r.xsch;
294                         R.recty= R.r.ysch;
295                         R.xstart= -R.afmx;
296                         R.ystart= -R.afmy;
297                         R.xend= R.xstart+R.rectx-1;
298                         R.yend= R.ystart+R.recty-1;
299
300         
301                         if(R.r.mode & R_MBLUR) set_mblur_offs(R.osa-blur);
302
303                         initParts(); /* altijd doen ivm border */
304                         setPart(0);
305         
306                         RE_local_init_render_display();
307                         RE_local_clear_render_display(R.win);
308                         RE_local_timecursor((G.scene->r.cfra));
309
310                         prepareScene();
311                                                 
312                         /* PARTS */
313                         R.parts.first= R.parts.last= 0;
314                         for(pa=0; pa<parts; pa++) {
315                                 
316                                 if(RE_local_test_break()) break;
317                                 
318                                 if(pa) {        /* want pa==0 is al gedaan */
319                                         if(setPart(pa)==0) break;
320                                 }
321
322                                 if(R.r.mode & R_MBLUR) RE_setwindowclip(0, blur);
323                                 else RE_setwindowclip(0,-1);
324
325                                 if(R.r.mode & R_PANORAMA) setPanoRot(pa);
326
327                                 /* HOMOGENE COORDINATEN EN ZBUF EN CLIP OPT (per part) */
328                                 /* There may be some interference with z-coordinate    */
329                                 /* calculation here?                                   */
330
331                                 doClipping(RE_projectverto);
332                                 if(RE_local_test_break()) break;
333
334                                 
335                                 /* ZBUFFER & SHADE: zbuffer stores int distances, int face indices */
336                                 R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
337
338                                 if(R.r.mode & R_MBLUR) RE_local_printrenderinfo(0.0, R.osa - blur);
339                                 else RE_local_printrenderinfo(0.0, -1);
340
341                                 /* The inner loop */
342                                 zBufShadeAdvanced();
343                                 
344                                 if(RE_local_test_break()) break;
345                                 
346                                 /* uitzondering */
347                                 if( (R.r.mode & R_BORDER) && (R.r.mode & R_MOVIECROP));
348                                 else {
349                                         /* PART OF BORDER AFHANDELEN */
350                                         if(parts>1 || (R.r.mode & R_BORDER)) {
351                                                 
352                                                 part= MEM_callocN(sizeof(Part), "part");
353                                                 BLI_addtail(&R.parts, part);
354                                                 part->rect= R.rectot;
355                                                 R.rectot= 0;
356                                                 
357                                                 if (R.rectz) {
358                                                         MEM_freeN(R.rectz);
359                                                         R.rectz= 0;
360                                                 }
361                                         }
362                                 }
363                         }
364
365                         /* PARTS SAMENVOEGEN OF BORDER INVOEGEN */
366
367                         /* uitzondering: crop */
368                         if( (R.r.mode & R_BORDER) && (R.r.mode & R_MOVIECROP)) ;
369                         else {
370                                 R.rectx= R.r.xsch;
371                                 R.recty= R.r.ysch;
372
373                                 if(R.r.mode & R_PANORAMA) R.rectx*= R.r.xparts;
374
375                                 if(parts>1 || (R.r.mode & R_BORDER)) {
376                                         if(R.rectot) MEM_freeN(R.rectot);
377                                         if(R.r.mode & R_BORDER) {
378                                                 if(border_x<R.rectx || border_y<R.recty || border_buf==NULL)
379                                                         R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
380                                                 else 
381                                                         R.rectot= border_buf;
382                                         }
383                                         else R.rectot=(unsigned int *)MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot");
384                                         
385                                         part= R.parts.first;
386                                         for(pa=0; pa<parts; pa++) {
387                                                 if(partsCoordinates[pa][0]== -1) break;
388                                                 if(part==0) break;
389                                                 
390                                                 if(R.r.mode & R_PANORAMA) {
391                                                         if(pa) {
392                                                                 partsCoordinates[pa][0] += pa*R.r.xsch;
393                                                                 partsCoordinates[pa][2] += pa*R.r.xsch;
394                                                         }
395                                                 }
396                                                 addPartToRect(pa, part);
397                                                 
398                                                 part= part->next;
399                                         }
400                                         
401                                         part= R.parts.first;
402                                         while(part) {
403                                                 MEM_freeN(part->rect);
404                                                 part= part->next;
405                                         }
406                                         BLI_freelistN(&R.parts);
407                                 }
408                         }
409
410                         /* don't do this for unified renderer? */
411 /*                      if( (R.flag & R_HALO) && !G.magic) { */
412 /*                              add_halo_flare(); */
413 /*                      } */
414
415                         if(R.r.mode & R_MBLUR) {
416                                 addToBlurBuffer(blur);
417                         }
418
419                         /* EINDE (blurlus) */
420                         finalizeScene();
421
422                         if(RE_local_test_break()) break;
423                 }
424
425                 /* definitief vrijgeven */
426                 addToBlurBuffer(-1);
427
428                 /* FIELD AFHANDELEN */
429                 if(R.r.mode & R_FIELDS) {
430                         if(R.flag & R_SEC_FIELD) R.rectf2= R.rectot;
431                         else R.rectf1= R.rectot;
432                         R.rectot= 0;
433                 }
434
435                 if(RE_local_test_break()) break;
436         }
437
438         /* FIELDS SAMENVOEGEN */
439         if(R.r.mode & R_FIELDS) {
440                 R.r.ysch*= 2;
441                 R.afmy*= 2;
442                 R.recty*= 2;
443                 R.r.yasp/=2;
444
445                 if(R.rectot) MEM_freeN(R.rectot);       /* komt voor bij afbreek */
446                 R.rectot=(unsigned int *)MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot");
447
448                 if(RE_local_test_break()==0) {
449                         rt= R.rectot;
450
451                         if(R.r.mode & R_ODDFIELD) {
452                                 rt2= R.rectf1;
453                                 rt1= R.rectf2;
454                         }
455                         else {
456                                 rt1= R.rectf1;
457                                 rt2= R.rectf2;
458                         }
459
460                         len= 4*R.rectx;
461
462                         for(a=0; a<R.recty; a+=2) {
463                                 memcpy(rt, rt1, len);
464                                 rt+= R.rectx;
465                                 rt1+= R.rectx;
466                                 memcpy(rt, rt2, len);
467                                 rt+= R.rectx;
468                                 rt2+= R.rectx;
469                         }
470                 }
471         }
472
473         /* R.rectx= R.r.xsch; */
474         /* if(R.r.mode & R_PANORAMA) R.rectx*= R.r.xparts; */
475         /* R.recty= R.r.ysch; */
476
477         /* als border: wel de skybuf doen */
478         /*
479           This may be tricky
480          */
481 /*      if(R.r.mode & R_BORDER) { */
482 /*              if( (R.r.mode & R_MOVIECROP)==0) { */
483 /*                      if(R.r.bufflag & 1) { */
484 /*                              R.xstart= -R.afmx; */
485 /*                              R.ystart= -R.afmy; */
486 /*                              rt= R.rectot; */
487 /*                              for(y=0; y<R.recty; y++, rt+= R.rectx) scanLineSkyFloat((char *)rt, y); */
488 /*                      } */
489 /*              } */
490 /*      } */
491
492         set_mblur_offs(0);
493
494         /* VRIJGEVEN */
495
496         /* zbuf test */
497
498         /* don't free R.rectz, only when its size is not the same as R.rectot */
499
500         if (R.rectz && parts == 1 && (R.r.mode & R_FIELDS) == 0);
501         else {
502                 if(R.rectz) MEM_freeN(R.rectz);
503                 R.rectz= 0;
504         }
505
506         if(R.rectf1) MEM_freeN(R.rectf1);
507         R.rectf1= 0;
508         if(R.rectf2) MEM_freeN(R.rectf2);
509         R.rectf2= 0;
510 } /* End of void unifiedRenderingLoop()*/
511
512 /* ------------------------------------------------------------------------- */
513
514 /* eof */
515