1 /****************************************************************************
2  *                  postproc.cpp
3  *
4  *  Author: Wlodzimierz ABX Skiba (abx@abx.art.pl)
5  *
6  * from Persistence of Vision(tm) Ray Tracer version 3.6.
7  * Copyright 1991-2003 Persistence of Vision Team
8  * Copyright 2003-2004 Persistence of Vision Raytracer Pty. Ltd.
9  *---------------------------------------------------------------------------
10  * NOTICE: This source code file is provided so that users may experiment
11  * with enhancements to POV-Ray and to port the software to platforms other
12  * than those supported by the POV-Ray developers. There are strict rules
13  * regarding how you are permitted to use this file. These rules are contained
14  * in the distribution and derivative versions licenses which should have been
15  * provided with this file.
16  *
17  * These licences may be found online, linked from the end-user license
18  * agreement that is located at http://www.povray.org/povlegal.html
19  *---------------------------------------------------------------------------
20  * This program is based on the popular DKB raytracer version 2.12.
21  * DKBTrace was originally written by David K. Buck.
22  * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
23  *---------------------------------------------------------------------------
24  *
25  *===========================================================================
26  * This file is part of MegaPOV, a modified and unofficial version of POV-Ray
27  * For more information on MegaPOV visit our website:
28  * http://megapov.inetart.net/
29  *===========================================================================
30  *
31  * $RCSfile: postproc.cpp,v $
32  * $Revision: 1.18 $
33  * $Author: chris $
34  *
35  *****************************************************************************/
36 
37 #include "frame.h"
38 #include "vector.h"
39 #include "povray.h"
40 #include "function.h"
41 #include "fpmetric.h"
42 #include "renderio.h"
43 #include "pov_util.h"
44 #include "statspov.h"
45 #include "vbuffer.h"
46 #include "colour.h"
47 #include "fnpovfpu.h"
48 #include "povmsend.h"
49 
50 #ifdef POST_PROCESS_PATCH
51 
52 #include "postproc.h"
53 
54 BEGIN_POV_NAMESPACE
55 
56 /*****************************************************************************
57 * Local preprocessor defines
58 ******************************************************************************/
59 
60 #define PP_DATA_EXTENSION ".ppd"
61 /*****************************************************************************
62 * Local preprocessor defines
63 ******************************************************************************/
64 const unsigned int FIRST_INTERNAL_PP_FUNCTION = 79
65                                  #ifdef F_TRIANGLE_PATCH
66                                    + 1
67                                  #endif
68                                  ;
69 const unsigned int LAST_INTERNAL_PP_FUNCTION  = FIRST_INTERNAL_PP_FUNCTION + PP_LAST_INFO + 3;
70 const char * pp_postfix[PP_LAST_INFO] =
71 {
72   "red"   ,
73   "green" ,
74   "blue"  ,
75   "alpha" ,
76   "ix"    ,
77   "iy"    ,
78   "iz"    ,
79   "nx"    ,
80   "ny"    ,
81   "nz"    ,
82   "pnx"   ,
83   "pny"   ,
84   "pnz"   ,
85   "depth" ,
86   "u"     ,
87   "v"
88 };
89 
90 /*****************************************************************************
91 * Global variables
92 ******************************************************************************/
93 
94 POST_PROCESS * First_Post_Process;
95 int Post_Process_Index;
96 int Post_Process_Pass;
97 int Post_Process_X;
98 int Post_Process_Y;
99 
100 /*****************************************************************************
101 * Static variables
102 ******************************************************************************/
103 static IOBase * PP_Files[PP_LAST_INFO];
104 static char * pp_names[PP_LAST_INFO];
105 
106 
107 
108 /*****************************************************************************
109 *
110 * FUNCTION
111 *
112 *   Create_Post_Process
113 *
114 * DESCRIPTION
115 *
116 *   Memory allocation for structure and initialization of all fields.
117 *
118 ******************************************************************************/
119 
Create_Post_Process()120 POST_PROCESS *Create_Post_Process()
121 {
122   POST_PROCESS *New=(POST_PROCESS *)POV_MALLOC(sizeof (POST_PROCESS), "post_process block");
123 
124   New->next = NULL;
125   New->prev = NULL;
126   New->Order = 0;
127   New->Function[PP_COLOUR_RED] = NULL;
128   New->Function[PP_COLOUR_GREEN] = NULL;
129   New->Function[PP_COLOUR_BLUE] = NULL;
130   New->Function[PP_COLOUR_ALPHA] = NULL;
131   New->Save_File_Name = NULL;
132   New->time = 0.0;
133 
134   return New;
135 };
136 
137 /*****************************************************************************
138 *
139 * FUNCTION
140 *
141 *   Destroy_Post_Process
142 *
143 * DESCRIPTION
144 *
145 *   Unlock memory for structure and its components.
146 *
147 ******************************************************************************/
148 
Destroy_Post_Process(POST_PROCESS ** Post_Process)149 void Destroy_Post_Process(POST_PROCESS **Post_Process)
150 {
151   POST_PROCESS *Next_Post_Process;
152   POST_PROCESS *Current_Post_Process;
153 
154   Current_Post_Process = *Post_Process;
155   while(Current_Post_Process)
156   {
157     Destroy_Function(Current_Post_Process->Function[PP_COLOUR_RED]);
158     Destroy_Function(Current_Post_Process->Function[PP_COLOUR_GREEN]);
159     Destroy_Function(Current_Post_Process->Function[PP_COLOUR_BLUE]);
160     Destroy_Function(Current_Post_Process->Function[PP_COLOUR_ALPHA]);
161 
162     Next_Post_Process = Current_Post_Process->next;
163 
164     if(Current_Post_Process->Save_File_Name!=NULL)
165     {
166       POV_FREE(Current_Post_Process->Save_File_Name);
167       Current_Post_Process->Save_File_Name = NULL;
168     }
169     POV_FREE(Current_Post_Process);
170     Current_Post_Process = NULL;
171     Current_Post_Process = Next_Post_Process;
172   }
173   *Post_Process = NULL;
174 };
175 
176 /*****************************************************************************
177 *
178 * FUNCTION
179 *
180 *   Post_Process_Initialize_Info
181 *
182 * DESCRIPTION
183 *
184 *   Writes 0.0 to every entry
185 *
186 ******************************************************************************/
187 
Post_Process_Initialize_Info(DBL * PP_Info)188 void Post_Process_Initialize_Info(DBL *PP_Info)
189 {
190   if(PP_Info)
191     for (int i=0; i<PP_LAST_INFO; i++)
192       PP_Info[i] = ( i == PP_DEPTH ? Max_Distance : 0.0);
193 }
194 
195 /*****************************************************************************
196 *
197 * FUNCTION
198 *
199 *   Post_Process_Intersection_Info
200 *
201 * DESCRIPTION
202 *
203 *   Stores intersection components as post_processing data.
204 *
205 ******************************************************************************/
206 
Post_Process_Intersection_Info(DBL * PP_Info,INTERSECTION * Best_Intersection)207 void Post_Process_Intersection_Info(DBL *PP_Info, INTERSECTION *Best_Intersection)
208 {
209   PP_Info[PP_IPOINT_X]=Best_Intersection->IPoint[X];
210   PP_Info[PP_IPOINT_Y]=Best_Intersection->IPoint[Y];
211   PP_Info[PP_IPOINT_Z]=Best_Intersection->IPoint[Z];
212   PP_Info[PP_INORMAL_X]=Best_Intersection->INormal[X];
213   PP_Info[PP_INORMAL_Y]=Best_Intersection->INormal[Y];
214   PP_Info[PP_INORMAL_Z]=Best_Intersection->INormal[Z];
215   PP_Info[PP_PNORMAL_X]=Best_Intersection->PNormal[X];
216   PP_Info[PP_PNORMAL_Y]=Best_Intersection->PNormal[Y];
217   PP_Info[PP_PNORMAL_Z]=Best_Intersection->PNormal[Z];
218   PP_Info[PP_DEPTH]=Best_Intersection->Depth;
219   PP_Info[PP_U]=Best_Intersection->Iuv[U];
220   PP_Info[PP_V]=Best_Intersection->Iuv[V];
221 }
222 
223 /*****************************************************************************
224 *
225 * FUNCTION
226 *
227 *   Post_Process_Colour_Info
228 *
229 * DESCRIPTION
230 *
231 *   Stores colour components as post_processing data.
232 *
233 ******************************************************************************/
234 
Post_Process_Colour_Info(DBL * PP_Info,COLOUR Colour)235 void Post_Process_Colour_Info(DBL *PP_Info, COLOUR Colour)
236 {
237   PP_Info[PP_COLOUR_RED]=Colour[pRED];
238   PP_Info[PP_COLOUR_GREEN]=Colour[pGREEN];
239   PP_Info[PP_COLOUR_BLUE]=Colour[pBLUE];
240   PP_Info[PP_COLOUR_ALPHA]=Colour[pTRANSM];
241 }
242 
243 /*****************************************************************************
244 *
245 * FUNCTION
246 *
247 *   Initialize_Post_Processing
248 *
249 * DESCRIPTION
250 *
251 *   NULL values for files and filenames. Has to be executed before each parsing.
252 *
253 ******************************************************************************/
254 
Initialize_Post_Processing()255 void Initialize_Post_Processing()
256 {
257   for (int i=0; i<PP_LAST_INFO; i++)
258   {
259     pp_names[ i ] = NULL;
260     PP_Files[ i ] = NULL;
261   }
262   First_Post_Process = NULL;
263   Post_Process_Index = 0;
264   Post_Process_Pass = 0;
265   Post_Process_X = 0;
266   Post_Process_Y = 0;
267 }
268 
269 /*****************************************************************************
270 *
271 * FUNCTION
272 *
273 *   Initialize_Post_Processing_Cache
274 *
275 * DESCRIPTION
276 *
277 *   Opens cache for one component of post_process data.
278 *   Has to be executed when function{internal(post_process_function)} appear in script.
279 *
280 ******************************************************************************/
281 
Initialize_Post_Processing_Cache(int component)282 void Initialize_Post_Processing_Cache(int component)
283 {
284   char File_Name[256];
285 
286   if((pp_names[component]==NULL)&&(PP_Files[component]==NULL))
287   {
288     strcpy(File_Name, opts.Output_Numbered_Name);
289     strcat(File_Name, ".");
290     strcat(File_Name, pp_postfix[ component ]);
291     strcat(File_Name, PP_DATA_EXTENSION);
292 
293     pp_names[component] = (char *) POV_MALLOC( strlen( File_Name ) + 1, "filename" );
294     strcpy(pp_names[component],File_Name);
295 
296     if ((PP_Files[component] = New_OStream(File_Name, POV_File_Unknown, false)) == NULL)
297     {
298       Error("Cannot save post processing data to %s", File_Name );
299     }
300   }
301 }
302 
303 /*****************************************************************************
304 *
305 * FUNCTION
306 *
307 *   Reinitialize_Post_Processing
308 *
309 * DESCRIPTION
310 *
311 *   Closes opened caches and reopens it for reading.
312 *   Has to be executed after rendering and before postprocessing
313 *
314 ******************************************************************************/
315 
Reinitialize_Post_Processing()316 void Reinitialize_Post_Processing()
317 {
318   int i;
319   unsigned long correct_size=(opts.Last_Line-opts.First_Line)*(opts.Last_Column-opts.First_Column)*sizeof(DBL);
320 
321   for (i=0; i<PP_LAST_INFO; i++)
322     if( PP_Files[i] != NULL )
323       {
324         // change output to input
325         delete PP_Files[i];
326         if ((PP_Files[i] = New_IStream(pp_names[i], POV_File_Unknown)) == NULL)
327         {
328           Error("Cannot open post processing data from %s", pp_names[i] );
329         }
330         // test for correct number of outputed files
331         if ( PP_Files[i]->fsize() != correct_size)
332           Error("Wrong size of post processing data file");
333       }
334 }
335 
336 /*****************************************************************************
337 *
338 * FUNCTION
339 *
340 *   Deinitialize_Post_Processing
341 *
342 * DESCRIPTION
343 *
344 *   Closes cache files and deletes files.
345 *   Has to be executed after post processing
346 *
347 ******************************************************************************/
348 
Deinitialize_Post_Processing()349 void Deinitialize_Post_Processing()
350 {
351   int i;
352 
353   for (i=0; i<PP_LAST_INFO; i++)
354     if( PP_Files[i] != NULL )
355       {
356         delete PP_Files[i];
357         PP_Files[i]=NULL;
358         if( pp_names[i] )
359         {
360        	  DELETE_FILE( pp_names[i] );
361           POV_FREE( pp_names[i] );
362         }
363         pp_names[i] = NULL;
364       }
365   if(First_Post_Process)
366   {
367     Destroy_Post_Process(&First_Post_Process);
368     First_Post_Process = NULL;
369     Post_Process_Index = 0;
370   }
371 }
372 
373 /*****************************************************************************
374 *
375 * FUNCTION
376 *
377 *   Save_Post_Process_Info
378 *
379 * DESCRIPTION
380 *
381 *   Stores components in caches.
382 *   Has to be executed once per pixel.
383 *
384 ******************************************************************************/
385 
Save_Post_Process_Info(DBL * PP_Info)386 void Save_Post_Process_Info(DBL *PP_Info)
387 {
388   if(PP_Info)
389     for (int i=0; i<PP_LAST_INFO; i++)
390       if( PP_Files[ i ] != NULL )
391         PP_Files[ i ]->write( & ( PP_Info[ i ] ) , sizeof( PP_Info[ i ] ) );
392 }
393 
394 /*****************************************************************************
395 *
396 * FUNCTION
397 *
398 *   Read_Output
399 *
400 * DESCRIPTION
401 *
402 *   Reads output of rendering as one of colour or intersection components
403 *
404 ******************************************************************************/
405 
Read_Output(DBL x,DBL y,int Component)406 DBL Read_Output(DBL x, DBL y, int Component)
407 {
408   if(Post_Process_Index==0)
409     Error("Post process related functions can't be used before post processing");
410   if(PP_Files[Component]==NULL)
411     Error("Not cached component used for post processing");
412   if((x<0.0)||(x>=1.0)||(y<0.0)||(y>=1.0))
413     return 0.0;
414 
415   DBL Value=0.0;
416   int ix = (int) floor( x * (DBL) Frame.Screen_Width );
417   int iy = (int) floor( y * (DBL) Frame.Screen_Height );
418   unsigned long pos = opts.Last_Column - opts.First_Column ;
419   pos *= iy - opts.First_Line;
420   pos += ix - opts.First_Column;
421   pos *= sizeof( Value );
422   PP_Files[Component]->seekg(pos,SEEK_SET);
423   PP_Files[Component]->read( (char *) &Value , sizeof( Value ) );
424   return Value;
425 }
426 
427 /*****************************************************************************
428 *
429 * FUNCTION
430 *
431 *   Read_Post_Process
432 *
433 * DESCRIPTION
434 *
435 *   Reads output of post_processes as one of colour components
436 *
437 ******************************************************************************/
438 
Read_Post_Process(DBL x,DBL y,int PP_Index,int Component)439 DBL Read_Post_Process(DBL x, DBL y, int PP_Index, int Component)
440 {
441   POST_PROCESS **Post_Process_Cursor = &First_Post_Process;
442   int prev_order = Post_Process_Index;
443   UV_VECT uv_screen;
444   DBL Value;
445 
446   if(PP_Index<0)
447     PP_Index += Post_Process_Index;
448   if(PP_Index==0)
449     return Read_Output(x,y,Component);
450   while((*Post_Process_Cursor)&&((*Post_Process_Cursor)->Order!=PP_Index))
451     Post_Process_Cursor = &((*Post_Process_Cursor)->next);
452   if(((*Post_Process_Cursor)==NULL)||
453      (PP_Index<0)||
454      (PP_Index>=Post_Process_Index))
455     Error("Wrong refference to post process");
456   Make_UV_Vector(uv_screen,x,y);
457   Post_Process_Index = (*Post_Process_Cursor)->Order;
458   Value = Evaluate_Function_UV( *((*Post_Process_Cursor)->Function[Component]), uv_screen),
459   Post_Process_Index = prev_order;
460   return Value;
461 }
462 
463 /*****************************************************************************
464 *
465 * FUNCTION
466 *
467 *   Post_Process_Loop
468 *
469 * DESCRIPTION
470 *
471 *   Calculates all pixel for specified post process
472 *   Not null with not empty Save_File_Name have to be passed
473 *   NULL checking for above should be done outside
474 *
475 ******************************************************************************/
476 
Post_Process_Loop(int & Post_Process_Pass,POST_PROCESS * Rendered_Post_Process)477 void Post_Process_Loop(int &Post_Process_Pass,POST_PROCESS *Rendered_Post_Process)
478 {
479   int x;
480   int skip_lines;
481   int skip_odd_lines;
482   UV_VECT uv_screen;
483 
484   if(Rendered_Post_Process->Save_File_Name)
485     open_output_file(Rendered_Post_Process->Save_File_Name);
486 
487   /* Odd/even line tracing depends on the frame number. */
488 
489   skip_odd_lines = !(((opts.FrameSeq.FrameNumber % 2)==1) ^ opts.FrameSeq.Odd_Field_Flag);
490 
491   /* Field rendering starts on an odd or even line. */
492 
493   skip_lines = (opts.FrameSeq.Field_Render_Flag) && !(opts.Options & ANTIALIAS);
494 
495   /* Loop over all rows. */
496 
497   for (Current_Line_Number = opts.First_Line; Current_Line_Number < opts.Last_Line; Current_Line_Number++)
498   {
499     uv_screen[V] = ((DBL)Current_Line_Number + .5 )/Frame.Screen_Height;
500 
501     /* Skip odd or even lines depending on the line number. */
502 
503     if ((skip_lines) && ((Current_Line_Number % 2) == skip_odd_lines))
504     {
505       /* Write previous line again. */
506 
507       if (Current_Line_Number > opts.First_Line)
508       {
509         output_single_image_line_with_alpha_correction(Previous_Line, Current_Line_Number);
510       }
511       else
512       {
513         POV_WRITE_LINE (Previous_Line, Current_Line_Number)
514       }
515 
516       continue;
517     }
518 
519     Post_Process_Y = Current_Line_Number;
520     Post_Process_X = opts.First_Column;
521     Send_ProgressUpdate(PROGRESS_POST_PROCESS);
522     Do_Cooperate(0);
523 
524     /* Loop over all columns. */
525 
526     for (x = opts.First_Column; x < opts.Last_Column; x++)
527     {
528       Post_Process_X = x;
529 
530       /* Check for user abort. */
531 
532       Check_User_Abort(false);
533 
534       /* Get current pixel post_processed */
535 
536       uv_screen[U] = ((DBL)x + .5 )/Frame.Screen_Width;
537 
538       /* Get current pixel post_processed */
539 
540       Post_Process_Index = Rendered_Post_Process->Order;
541       Make_ColourA(
542         Current_Line[x],
543         Evaluate_Function_UV( *(Rendered_Post_Process->Function[PP_COLOUR_RED]), uv_screen),
544         Evaluate_Function_UV( *(Rendered_Post_Process->Function[PP_COLOUR_GREEN]), uv_screen),
545         Evaluate_Function_UV( *(Rendered_Post_Process->Function[PP_COLOUR_BLUE]), uv_screen),
546         0,
547         Evaluate_Function_UV( *(Rendered_Post_Process->Function[PP_COLOUR_ALPHA]), uv_screen)
548       );
549       // Clip_Colour( Current_Line[x] , Current_Line[x] );
550       Post_Process_Index = 0;
551 
552       /* Display pixel. */
553       plot_pixel(x, Current_Line_Number, Current_Line[x]);
554       POV_ASSIGN_PIXEL (x, Current_Line_Number, Current_Line [x])
555     }
556 
557     /* Write current row to disk. */
558 
559     output_prev_image_line_and_advance(Current_Line_Number);
560   }
561 
562   /* Write last row to disk. */
563 
564   if (opts.Last_Line != opts.First_Line)
565   {
566     output_single_image_line_with_alpha_correction(Previous_Line,opts.Last_Line - 1);
567   }
568 
569   /* close output file */
570   if(Output_File != NULL)
571   {
572     delete Output_File;
573     Output_File = NULL;
574   }
575 }
576 
577 END_POV_NAMESPACE
578 
579 #endif
580