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