1 /****************************************************************************
2 * rendctrl.cpp
3 *
4 * This module contains the control for the raytracer.
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: rendctrl.cpp,v $
32 * $Revision: 1.27 $
33 * $Author: chris $
34 *
35 *****************************************************************************/
36
37 #include <ctype.h>
38 #include <time.h>
39 #include <algorithm>
40
41 #include "frame.h"
42 #include "bezier.h"
43 #include "blob.h"
44 #include "bbox.h"
45 #include "cones.h"
46 #include "csg.h"
47 #include "discs.h"
48 #include "express.h"
49 #include "fnpovfpu.h"
50 #include "fractal.h"
51 #include "hfield.h"
52 #include "lathe.h"
53 #include "lighting.h"
54 #include "lightgrp.h"
55 #include "mesh.h"
56 #include "photons.h"
57 #include "polysolv.h"
58 #include "objects.h"
59 #include "octree.h"
60 #include "parse.h"
61 #include "pigment.h"
62 #include "point.h"
63 #include "poly.h"
64 #include "polygon.h"
65 #include "povray.h"
66 #include "optout.h"
67 #include "quadrics.h"
68 #include "prism.h"
69 #include "radiosit.h"
70 #include "render.h"
71 #include "sor.h"
72 #include "spheres.h"
73 #include "super.h"
74 #include "targa.h"
75 #include "texture.h"
76 #include "tokenize.h"
77 #include "torus.h"
78 #include "triangle.h"
79 #include "truetype.h"
80 #include "userio.h"
81 #include "userdisp.h"
82 #include "lbuffer.h"
83 #include "vbuffer.h"
84 #include "povmsend.h"
85 #include "povmsrec.h"
86 #include "isosurf.h"
87 #include "sphsweep.h"
88 #include "pov_util.h"
89 #include "renderio.h"
90 #include "statspov.h"
91 #include "pov_err.h"
92 #include "optout.h"
93 #include "povms.h"
94 #include "rendctrl.h"
95
96 #ifdef MECHANICS_SIMULATION_PATCH /* Christoph Hormann August 2002 */
97 #include "mechsim.h"
98 #endif
99
100 #ifdef CLOTHRAY_PATCH
101 #include "clothray.h"
102 #endif
103
104 #ifdef POST_PROCESS_PATCH
105 #include "postproc.h"
106 #endif
107
108 BEGIN_POV_NAMESPACE
109
110 USING_POV_BASE_NAMESPACE
111
112 /*****************************************************************************
113 * Local preprocessor defines
114 ******************************************************************************/
115
116 /* Flags for the variable store. */
117
118 const int STORE = 1;
119 const int RESTORE = 2;
120
121 /*****************************************************************************
122 * Local typedefs
123 ******************************************************************************/
124
125
126 /*****************************************************************************
127 * Global variables
128 ******************************************************************************/
129 #ifdef TIME_MEASUREMENT_PATCH
130 /*YS enabling time mesurement */
131 extern DBL ChronoStart; // GLOBAL VARIABLE
132 #endif
133
134 // Photon map stuff
135 extern int backtraceFlag; // GLOBAL VARIABLE
136
137 extern PHOTON_OPTIONS photonOptions; // GLOBAL VARIABLE
138
139 extern int disp_elem; // GLOBAL VARIABLE
140 extern int disp_nelems; // GLOBAL VARIABLE
141
142 extern int warpNormalTextures; // GLOBAL VARIABLE
143 extern int InitBacktraceWasCalled; // GLOBAL VARIABLE
144
145 #ifdef MECHANICS_SIMULATION_PATCH /* Christoph Hormann August 2002 */
146 extern MECHSIM_OPTIONS MechsimOptions; // GLOBAL VARIABLE
147 #endif
148
149 // The frame and frame related stuff
150 FRAME Frame; // GLOBAL VARIABLE
151 DBL Clock_Delta; // GLOBAL VARIABLE
152
153 // Statistics stuff
154 OStream *stat_file; // GLOBAL VARIABLE
155 COUNTER stats[MaxStat]; // GLOBAL VARIABLE
156 COUNTER totalstats[MaxStat]; // GLOBAL VARIABLE
157
158 // Option stuff
159 Opts opts; // GLOBAL VARIABLE
160 char *Option_String_Ptr; // GLOBAL VARIABLE
161
162 // File and parsing stuff
163 int Number_Of_Files; // GLOBAL VARIABLE
164 Image_File_Class *Output_File; // GLOBAL VARIABLE
165 int Num_Echo_Lines; // May make user setable later - CEY // GLOBAL VARIABLE
166
167 // Timing stuff
168 time_t tstart, tstop; // GLOBAL VARIABLE
169 DBL tparse, tphoton, trender; // GLOBAL VARIABLE
170 DBL tparse_frame, tphoton_frame, trender_frame; // GLOBAL VARIABLE
171 DBL tparse_total, tphoton_total, trender_total; // GLOBAL VARIABLE
172 #ifdef CLOTHRAY_PATCH
173 DBL tcloth, tcloth_frame, tcloth_total ; // GLOBAL VARIABLE
174 #endif
175 #ifdef MECHANICS_SIMULATION_PATCH
176 DBL tmechsim, tmechsim_frame, tmechsim_total ; // GLOBAL VARIABLE
177 #endif
178 #ifdef POST_PROCESS_PATCH
179 DBL tpostproc, tpostproc_frame, tpostproc_total ; // GLOBAL VARIABLE
180 #endif
181 // Options and display stuff
182 char Color_Bits; // GLOBAL VARIABLE
183
184 // Options and display stuff
185 int Display_Started; // GLOBAL VARIABLE
186 int Abort_Test_Every; // GLOBAL VARIABLE
187 int Experimental_Flag; // GLOBAL VARIABLE
188
189 // Current stage of the program
190 int Stage; // GLOBAL VARIABLE
191
192 #ifdef POST_PROCESS_PATCH
193 extern int Post_Process_Pass;
194 #endif
195
196 // Stop flag (for abort etc)
197 volatile int Stop_Flag; // GLOBAL VARIABLE
198
199
200 /*****************************************************************************
201 * Local variables
202 ******************************************************************************/
203
204 char Actual_Output_Name[FILE_NAME_LENGTH]; // GLOBAL VARIABLE
205
206 // Flag if close_all() was already called
207 int closed_flag; // GLOBAL VARIABLE
208
209 int STORE_First_Line; // GLOBAL VARIABLE
210
211
212 /*****************************************************************************
213 * functions
214 ******************************************************************************/
215
216 #ifdef CUSTOM_TONE_MAPPING_PATCH /* Christoph Hormann September 2004 */
217 void Initialize_Tone_Mapping();
218 void Deinitialize_Tone_Mapping();
219 #endif
220
221
222 /*****************************************************************************
223 *
224 * FUNCTION
225 *
226 * FrameLoop
227 *
228 * INPUT
229 *
230 * OUTPUT
231 *
232 * RETURNS
233 *
234 * AUTHOR
235 *
236 * POV-Ray Team
237 *
238 * DESCRIPTION
239 *
240 * -
241 *
242 * CHANGES
243 *
244 * -
245 *
246 ******************************************************************************/
247
FrameLoop()248 void FrameLoop()
249 {
250 int Diff_Frame;
251 DBL Diff_Clock;
252 SHELLRET Pre_Scene_Result, Frame_Result;
253
254 Diff_Clock = opts.FrameSeq.FinalClock - opts.FrameSeq.InitialClock;
255
256 if(opts.Options & CYCLIC_ANIMATION)
257 Diff_Frame = opts.FrameSeq.FinalFrame - opts.FrameSeq.InitialFrame + 1;
258 else
259 Diff_Frame = opts.FrameSeq.FinalFrame - opts.FrameSeq.InitialFrame;
260
261 Clock_Delta = ((Diff_Frame == 0) ? 0 : Diff_Clock/Diff_Frame);
262
263 // Execute the first shell-out command
264 Pre_Scene_Result = (POV_SHELLOUT_CAST)POV_SHELLOUT(PRE_SCENE_SHL);
265
266 // Loop over each frame
267
268 if(Pre_Scene_Result != ALL_SKIP_RET)
269 {
270 if(Pre_Scene_Result != SKIP_ONCE_RET)
271 {
272 for(opts.FrameSeq.FrameNumber =
273 #ifdef FRAME_STEP_PATCH
274 ((opts.FrameSeq.FrameStep>0)?
275 #endif
276 opts.FrameSeq.InitialFrame
277 #ifdef FRAME_STEP_PATCH
278 :opts.FrameSeq.FinalFrame)
279 #endif
280 ,
281 opts.FrameSeq.Clock_Value =
282 #ifdef FRAME_STEP_PATCH
283 ((opts.FrameSeq.FrameStep>0)?
284 #endif
285 opts.FrameSeq.InitialClock
286 #ifdef FRAME_STEP_PATCH
287 :opts.FrameSeq.FinalClock)
288 #endif
289 ;
290
291 #ifdef FRAME_STEP_PATCH
292 ((opts.FrameSeq.FrameStep>0)?
293 #endif
294 opts.FrameSeq.FrameNumber <= opts.FrameSeq.FinalFrame
295 #ifdef FRAME_STEP_PATCH
296 :opts.FrameSeq.FrameNumber >= opts.FrameSeq.InitialFrame)
297 #endif
298 ;
299
300 // ISO/IEC 14882:1998(E) section 5.18 Comma operator [expr.comma] (page 90) says
301 // that comma expressions are evaluated left-to-right, and according to section
302 // 6.5.3 The for statement [stmt.for] (page 97) the following is an expression.
303 // I just hope all compilers really know about the standard... [trf]
304 #ifdef FRAME_STEP_PATCH
305 opts.FrameSeq.FrameNumber += opts.FrameSeq.FrameStep,
306 #else
307 opts.FrameSeq.FrameNumber++,
308 #endif
309 opts.FrameSeq.Clock_Value = opts.FrameSeq.InitialClock +
310 (Clock_Delta * (DBL)(opts.FrameSeq.FrameNumber - opts.FrameSeq.InitialFrame)))
311 {
312 if(opts.FrameSeq.FrameType == FT_MULTIPLE_FRAME)
313 {
314 START_TIME
315 Send_Progress("Processing Frame", PROGRESS_PROCESSING_FRAME);
316 }
317
318 setup_output_file_name();
319
320 // Execute a shell-out command before tracing
321
322 Frame_Result = (POV_SHELLOUT_CAST)POV_SHELLOUT(PRE_FRAME_SHL);
323
324 if(Frame_Result == ALL_SKIP_RET)
325 break;
326
327 if(Frame_Result != SKIP_ONCE_RET)
328 {
329 FrameRender();
330
331 // Execute a shell-out command after tracing
332
333 Frame_Result = (POV_SHELLOUT_CAST)POV_SHELLOUT(POST_FRAME_SHL);
334
335 if((Frame_Result == SKIP_ONCE_RET) || (Frame_Result == ALL_SKIP_RET))
336 break;
337 }
338
339 if(opts.FrameSeq.FrameType == FT_MULTIPLE_FRAME)
340 Send_FrameStatistics();
341
342 Do_Cooperate(1);
343 }
344
345 // Print total stats ...
346
347 if(opts.FrameSeq.FrameType == FT_MULTIPLE_FRAME)
348 {
349 #ifdef FRAME_STEP_PATCH
350 opts.FrameSeq.FrameNumber -= opts.FrameSeq.FrameStep;
351 #else
352 opts.FrameSeq.FrameNumber--;
353 #endif
354 Send_RenderStatistics(true);
355
356 #ifdef FRAME_STEP_PATCH
357 opts.FrameSeq.FrameNumber += opts.FrameSeq.FrameStep;
358 #else
359 opts.FrameSeq.FrameNumber++;
360 #endif
361 }
362 }
363
364 // Execute the final shell-out command
365 POV_SHELLOUT(POST_SCENE_SHL);
366 }
367 }
368
369 /*****************************************************************************
370 *
371 * FUNCTION
372 *
373 * FrameRender
374 *
375 * INPUT
376 *
377 * OUTPUT
378 *
379 * RETURNS
380 *
381 * AUTHOR
382 *
383 * POV-Ray Team
384 *
385 * DESCRIPTION
386 *
387 * Do all that is necessary for rendering a single frame, including parsing
388 *
389 * CHANGES
390 *
391 * Feb 1996: Make sure we are displaying when doing a mosaic preview [AED]
392 *
393 ******************************************************************************/
394
FrameRender()395 void FrameRender()
396 {
397 #ifdef POST_PROCESS_PATCH
398 DBL Post_Process_Info[PP_LAST_INFO];
399 #endif
400
401 // Store start time for parse.
402 START_TIME
403
404 Current_Token_Count = 0;
405
406 #ifdef CLOTHRAY_PATCH
407 tcloth_frame =
408 #endif
409 #ifdef MECHANICS_SIMULATION_PATCH
410 tmechsim_frame =
411 #endif
412 #ifdef POST_PROCESS_PATCH
413 tpostproc_frame =
414 #endif
415 tparse_frame = tphoton_frame = trender_frame = 0.0;
416
417 // Parse the scene file.
418 Send_Progress("Parsing", PROGRESS_PARSING);
419
420 opts.Do_Stats = false;
421
422 // Set up noise-tables
423 Initialize_Noise();
424
425 // Set up function VM
426 POVFPU_Init();
427
428 // Init module specific stuff.
429 Initialize_Mesh_Code();
430
431 #ifdef MECHANICS_SIMULATION_PATCH /* Christoph Hormann August 2002 */
432 Initialize_MechSim();
433 #endif
434
435 #ifdef POST_PROCESS_PATCH
436 Initialize_Post_Processing();
437 #endif
438
439 Parse();
440
441 opts.Do_Stats = true;
442
443 if (opts.Radiosity_Enabled)
444 Experimental_Flag |= EF_RADIOS;
445
446 if (Experimental_Flag)
447 {
448 char str[512] = "" ;
449
450 if (Experimental_Flag & EF_SPLINE)
451 strcat (str, str [0] ? ", spline" : "spline") ;
452 if (Experimental_Flag & EF_RADIOS)
453 strcat (str, str [0] ? ", radiosity" : "radiosity") ;
454 if (Experimental_Flag & EF_SLOPEM)
455 strcat (str, str [0] ? ", slope pattern" : "slope pattern") ;
456 if (Experimental_Flag & EF_ISOFN)
457 strcat (str, str [0] ? ", function '.hf'" : "function '.hf'") ;
458 if (Experimental_Flag & EF_TIFF)
459 strcat (str, str [0] ? ", TIFF image support" : "TIFF image support") ;
460
461 Warning(0, "This rendering uses the following experimental feature(s): %s.\n"
462 "The design and implementation of these features is likely to change in future versions\n"
463 "of POV-Ray. Full backward compatibility with the current implementation is NOT guaranteed.",
464 str);
465 }
466
467 Experimental_Flag = 0;
468
469 // Switch off standard anti-aliasing.
470
471 if((Frame.Camera->Aperture != 0.0) && (Frame.Camera->Blur_Samples > 0))
472 {
473 opts.Options &= ~ANTIALIAS;
474
475 Warning(0, "Focal blur is used. Standard antialiasing is switched off.");
476 }
477
478 // Create the bounding box hierarchy.
479
480 Stage = STAGE_SLAB_BUILDING;
481
482 if(opts.Use_Slabs)
483 Send_Progress("Creating bounding slabs", PROGRESS_CREATING_BOUNDING_SLABS);
484
485 // Init module specific stuff.
486 Initialize_Atmosphere_Code();
487 Initialize_BBox_Code();
488 Initialize_Lighting_Code();
489 Initialize_VLBuffer_Code();
490 Initialize_Radiosity_Code();
491
492 #ifdef CUSTOM_TONE_MAPPING_PATCH /* Christoph Hormann September 2004 */
493 Initialize_Tone_Mapping();
494 #endif
495
496 // Always call this to print number of objects.
497 Build_Bounding_Slabs(&Root_Object);
498
499 // Create the vista buffer.
500 Build_Vista_Buffer();
501
502 // Create the light buffers.
503 Build_Light_Buffers();
504
505 // Save variable values.
506 variable_store(STORE);
507
508 // Get the parsing time.
509 STOP_TIME
510 tparse = TIME_ELAPSED
511 Send_ProgressUpdate(PROGRESS_PARSING, 0);
512
513 // Output parsing statistics.
514 Send_ParseStatistics();
515
516 if (photonOptions.photonsEnabled)
517 {
518 /* Store start time for photons. */
519 START_TIME
520
521 /* now backwards-trace the scene and build the photon maps */
522 InitBacktraceEverything();
523 BuildPhotonMaps();
524
525 /* Get the photon-shooting time. */
526 STOP_TIME
527 tphoton = TIME_ELAPSED
528
529 /* Get total parsing time. */
530 tphoton_total += tphoton;
531 tphoton_frame = tphoton;
532 tphoton = 0;
533 }
534
535 /* Store start time for the rest of parsing. */
536 START_TIME
537 Stage = STAGE_INIT;
538
539 // Open output file and if we are continuing an interrupted trace,
540 // read in the previous file settings and any data there. This has to
541 // be done before any image-size related allocations, since the settings
542 // in a resumed file take precedence over that specified by the user. [AED]
543 open_output_file(
544 #ifdef POST_PROCESS_PATCH
545 Actual_Output_Name
546 #endif
547 );
548
549 // Start the display.
550 if(opts.Options & DISPLAY)
551 {
552 Send_Progress("Displaying", PROGRESS_DISPLAYING);
553
554 Display_Started = POV_DISPLAY_INIT(opts.Preview_RefCon, Frame.Screen_Width, Frame.Screen_Height);
555
556 // Display vista tree.
557 Draw_Vista_Buffer();
558 }
559 else
560 {
561 Display_Started = false;
562 }
563
564 // Get things ready for ray tracing (misc init, mem alloc)
565 Initialize_Renderer();
566
567 // This had to be taken out of open_output_file() because we don't have
568 // the final image size until the output file has been opened, so we can't
569 // initialize the display until we know this, which in turn means we can't
570 // read the rendered part before the display is initialized. [AED]
571 if((opts.Options & DISKWRITE) && (opts.Options & CONTINUE_TRACE))
572 {
573 Read_Rendered_Part(Actual_Output_Name);
574
575 if (opts.Last_Line > Frame.Screen_Height)
576 opts.Last_Line = Frame.Screen_Height;
577
578 if (opts.Last_Column > Frame.Screen_Width)
579 opts.Last_Column = Frame.Screen_Width;
580 }
581
582 // Get the rest of the parsing time.
583 STOP_TIME
584 tparse += TIME_ELAPSED
585
586 // Store start time for trace.
587 START_TIME
588
589 // Get total parsing time.
590 tparse_total += tparse;
591 tparse_frame = tparse;
592 tparse = 0;
593
594 // Start tracing.
595 Stage = STAGE_RENDERING;
596
597 POV_PRE_RENDER
598
599 #ifndef NEW_RADIOSITY_PRETRACE_PATCH /* Christoph Hormann March 2005 */
600 Send_Progress("Rendering", PROGRESS_RENDERING);
601 #endif
602
603 // Macro for setting up any special FP options
604 CONFIG_MATH
605
606 // Ok, go for it - trace the picture.
607
608 // If radiosity preview has been done, we are continuing a trace, so it
609 // is important NOT to do the preview, even if the user requests it, as it
610 // will cause discontinuities in radiosity shading by (probably) calculating
611 // a few more radiosity values.
612
613 // Note that radiosity REQUIRES a mosaic preview prior to main scan
614 if ( opts.Radiosity_Enabled && !opts.Radiosity_Preview_Done)
615
616 #ifdef NEW_RADIOSITY_PRETRACE_PATCH /* Christoph Hormann March 2005 */
617 {
618 if (opts.radPretraceAdaptive > 0)
619 {
620 Start_Tracing_Radiosity_Preview_Adaptive();
621 }
622 else
623 {
624 Send_Progress("Rendering", PROGRESS_RENDERING);
625 #endif
626
627 Start_Tracing_Radiosity_Preview(opts.PreviewGridSize_Start, opts.PreviewGridSize_End);
628
629 #ifdef NEW_RADIOSITY_PRETRACE_PATCH /* Christoph Hormann March 2005 */
630 }
631 }
632 #endif
633
634 else if((opts.Options & PREVIEW) && (opts.Options & DISPLAY))
635 Start_Tracing_Mosaic_Preview(opts.PreviewGridSize_Start, opts.PreviewGridSize_End);
636
637 switch(opts.Tracing_Method)
638 {
639 case 2:
640 Start_Adaptive_Tracing(
641 #ifdef POST_PROCESS_PATCH
642 Post_Process_Info
643 #endif
644 );
645 break;
646 case 1:
647 default:
648 Start_Non_Adaptive_Tracing(
649 #ifdef POST_PROCESS_PATCH
650 Post_Process_Info
651 #endif
652 );
653 }
654
655 // Record time so well spent before file close so it can be in comments
656 STOP_TIME
657 trender = TIME_ELAPSED
658
659 // shutdown (freeing memory) does not get included in the time!
660
661 // Get total render time.
662 trender_total += trender;
663 trender_frame = trender;
664 trender = 0;
665
666 // Close out our file
667 if(Output_File != NULL)
668 {
669 delete Output_File;
670 Output_File = NULL;
671 }
672
673 // For all those who never rtfm [trf]
674 if((Highest_Trace_Level >= Max_Trace_Level) && (Had_Max_Trace_Level == false))
675 PossibleError("Maximum trace level reached! If your scene contains black spots\nread more about the max_trace_level setting in the documentation!");
676
677 #ifdef POST_PROCESS_PATCH
678
679 Send_Progress("Postprocessing",PROGRESS_POST_PROCESS);
680
681 Reinitialize_Post_Processing();
682
683 POST_PROCESS **Post_Process_Cursor = &First_Post_Process;
684
685 while(*Post_Process_Cursor)
686 {
687 Post_Process_Pass++;
688 (*Post_Process_Cursor)->time = 0.0;
689 if((*Post_Process_Cursor)->Save_File_Name)
690 {
691 START_TIME
692 Post_Process_Loop(Post_Process_Pass,*Post_Process_Cursor);
693 STOP_TIME
694 (*Post_Process_Cursor)->time = TIME_ELAPSED;
695 tpostproc_frame += (*Post_Process_Cursor)->time;
696 tpostproc_total += (*Post_Process_Cursor)->time;
697 }
698 else
699 if((*Post_Process_Cursor)->next==NULL)
700 Warning(0,"Last post_process block has no save_file name defined and is not saved!");
701 Post_Process_Cursor = &((*Post_Process_Cursor)->next);
702 }
703
704 #endif
705
706 Stage = STAGE_SHUTDOWN;
707
708 POV_PRE_SHUTDOWN
709
710 // DESTROY lots of stuff
711 /* NK phmap */
712 FreeBacktraceEverything();
713 #ifdef CLOTHRAY_PATCH
714 Terminate_Cloth_Sys();
715 #endif
716 Deinitialize_Atmosphere_Code();
717 Deinitialize_BBox_Code();
718 Deinitialize_Lighting_Code();
719 Deinitialize_Mesh_Code();
720 Deinitialize_VLBuffer_Code();
721 Deinitialize_Radiosity_Code();
722 Destroy_Light_Buffers();
723 Destroy_Vista_Buffer();
724 Destroy_Bounding_Slabs();
725 Destroy_Frame();
726 Terminate_Renderer();
727 FreeFontInfo();
728 Free_Iteration_Stack();
729 Free_Noise_Tables();
730
731 POVFPU_Terminate();
732
733 #ifdef MECHANICS_SIMULATION_PATCH /* Christoph Hormann August 2002 */
734 Deinitialize_MechSim();
735 #endif
736
737 POV_POST_SHUTDOWN
738
739 if((opts.Options & DISPLAY) && Display_Started)
740 {
741 POV_DISPLAY_FINISHED(opts.Preview_RefCon);
742
743 POV_DISPLAY_CLOSE(opts.Preview_RefCon);
744
745 Display_Started = false;
746 }
747
748 if(opts.histogram_on)
749 write_histogram(opts.Histogram_File_Name);
750
751 Send_Progress("Done Tracing", PROGRESS_DONE_TRACING);
752
753 // Print stats ...
754 Send_RenderStatistics();
755
756 if(opts.FrameSeq.FrameType == FT_MULTIPLE_FRAME)
757 {
758 // Add them up
759 sum_statistics(totalstats, stats);
760
761 // ... and then clear them for the next frame
762 init_statistics(stats);
763 }
764
765 #ifdef CUSTOM_TONE_MAPPING_PATCH /* Christoph Hormann September 2004 */
766 Deinitialize_Tone_Mapping();
767 #endif
768
769 #ifdef POST_PROCESS_PATCH
770 Deinitialize_Post_Processing();
771 #endif
772
773 // Restore variable values.
774 variable_store(RESTORE);
775 }
776
777 /*****************************************************************************
778 *
779 * FUNCTION
780 *
781 * fix_up_rendering_window
782 *
783 * INPUT
784 *
785 * OUTPUT
786 *
787 * RETURNS
788 *
789 * AUTHOR
790 *
791 * POV-Ray Team
792 *
793 * DESCRIPTION
794 *
795 * Fix wrong window and mosaic preview values.
796 *
797 * CHANGES
798 *
799 * -
800 *
801 ******************************************************************************/
802
fix_up_rendering_window()803 void fix_up_rendering_window()
804 {
805 int temp;
806
807 if (opts.First_Column_Percent > 0.0)
808 opts.First_Column = (int) (Frame.Screen_Width * opts.First_Column_Percent);
809
810 if (opts.First_Line_Percent > 0.0)
811 opts.First_Line = (int) (Frame.Screen_Height * opts.First_Line_Percent);
812
813 /* The decrements are a fudge factor that used to be in OPTIN.C
814 * but it messed up Write_INI_File so its moved here.
815 */
816
817 if (opts.First_Column <= 0)
818 opts.First_Column = 0;
819 else
820 opts.First_Column--;
821
822 if (opts.First_Line <= 0)
823 opts.First_Line = 0;
824 else
825 opts.First_Line--;
826
827 if ((opts.Last_Column == -1) && (opts.Last_Column_Percent <= 1.0))
828 opts.Last_Column = (int) (Frame.Screen_Width * opts.Last_Column_Percent);
829
830 if ((opts.Last_Line == -1) && (opts.Last_Line_Percent <= 1.0))
831 opts.Last_Line = (int) (Frame.Screen_Height * opts.Last_Line_Percent);
832
833 if (opts.Last_Line == -1)
834 opts.Last_Line = Frame.Screen_Height;
835
836 if (opts.Last_Column == -1)
837 opts.Last_Column = Frame.Screen_Width;
838
839 if (opts.Last_Column < 0 || opts.Last_Column > Frame.Screen_Width)
840 opts.Last_Column = Frame.Screen_Width;
841
842 if (opts.Last_Line > Frame.Screen_Height)
843 opts.Last_Line = Frame.Screen_Height;
844
845 /* Fix up Mosaic Preview values */
846 opts.PreviewGridSize_Start=max(1,opts.PreviewGridSize_Start);
847 opts.PreviewGridSize_End=max(1,opts.PreviewGridSize_End);
848
849 if ((temp=closest_power_of_2((unsigned)opts.PreviewGridSize_Start))!=opts.PreviewGridSize_Start)
850 {
851 Warning(0,"Preview_Start_Size must be a power of 2. Changing to %d.",temp);
852 opts.PreviewGridSize_Start=temp;
853 }
854
855 if ((temp=closest_power_of_2((unsigned)opts.PreviewGridSize_End))!=opts.PreviewGridSize_End)
856 {
857 Warning(0,"Preview_End_Size must be a power of 2. Changing to %d.",temp);
858 opts.PreviewGridSize_End=temp;
859 }
860
861 /* End must be less than or equal to start */
862 if (opts.PreviewGridSize_End > opts.PreviewGridSize_Start)
863 opts.PreviewGridSize_End = opts.PreviewGridSize_Start;
864
865 if (opts.PreviewGridSize_Start > 1)
866 {
867 opts.PreviewGridSize_End=max(opts.PreviewGridSize_End,2);
868 opts.Options |= PREVIEW;
869 }
870 else
871 {
872 opts.Options &= ~PREVIEW;
873 }
874
875 /* Set histogram size here so it is available for Print_Options, and
876 * make sure that it has an integer number of pixels/bucket. */
877 if (opts.histogram_on)
878 {
879 if (opts.histogram_x == 0 || opts.histogram_x > Frame.Screen_Width)
880 opts.histogram_x = Frame.Screen_Width;
881 else if (opts.histogram_x < Frame.Screen_Width)
882 opts.histogram_x = Frame.Screen_Width / ((Frame.Screen_Width +
883 opts.histogram_x - 1) / opts.histogram_x);
884
885 if (opts.histogram_y == 0 || opts.histogram_y > Frame.Screen_Height)
886 opts.histogram_y = Frame.Screen_Height;
887 else if (opts.histogram_y < Frame.Screen_Height)
888 opts.histogram_y = Frame.Screen_Height / ((Frame.Screen_Height +
889 opts.histogram_y - 1) /opts.histogram_y);
890 }
891 }
892
893 /*****************************************************************************
894 *
895 * FUNCTION
896 *
897 * fix_up_animation_values
898 *
899 * INPUT
900 *
901 * OUTPUT
902 *
903 * RETURNS
904 *
905 * AUTHOR
906 *
907 * POV-Ray Team
908 *
909 * DESCRIPTION
910 *
911 * Validate animation parameters, compute subset values
912 *
913 * CHANGES
914 *
915 * -
916 *
917 ******************************************************************************/
fix_up_animation_values()918 void fix_up_animation_values()
919 {
920 DBL ClockDiff;
921 int FrameDiff;
922 int FrameIncr;
923 DBL ClockPerFrameIncr;
924 int NumFrames;
925
926 /*
927 * Added because that is no animation. [trf]
928 */
929 if ((opts.FrameSeq.InitialFrame == opts.FrameSeq.FinalFrame) &&
930 ((opts.FrameSeq.FinalFrame == 0) || (opts.FrameSeq.FinalFrame == 1)))
931 {
932 opts.FrameSeq.InitialFrame = -1;
933 opts.FrameSeq.FinalFrame = -1;
934 }
935
936 if (opts.FrameSeq.FinalFrame != -1)
937 {
938 opts.FrameSeq.FrameType = FT_MULTIPLE_FRAME;
939
940 if (opts.FrameSeq.Clock_Value != 0.0)
941 {
942 Warning(0,"Attempted to set single clock value in multi frame\n"
943 "animation. Clock value overridden.");
944 }
945 }
946 else
947 {
948 if (opts.FrameSeq.Clock_Value != 0.0)
949 {
950 opts.FrameSeq.FrameType = FT_SINGLE_FRAME;
951 }
952 }
953
954 if (opts.FrameSeq.FrameType == FT_SINGLE_FRAME)
955 {
956 /*
957 * These are dummy values that will work for single_frame,
958 * even in an animation loop.
959 */
960
961 opts.FrameSeq.InitialFrame = 0;
962 opts.FrameSeq.FinalFrame = 0;
963 opts.FrameSeq.InitialClock = opts.FrameSeq.Clock_Value;
964 opts.FrameSeq.FinalClock = 0.0;
965 }
966 else
967 {
968 /* FrameType==FT_MULTIPLE_FRAME */
969
970 if(opts.FrameSeq.InitialFrame == -1)
971 {
972 opts.FrameSeq.InitialFrame = 1;
973 }
974
975 if (opts.FrameSeq.FinalFrame < opts.FrameSeq.InitialFrame)
976 {
977 Error("Final frame %d is less than Start Frame %d.",
978 opts.FrameSeq.FinalFrame, opts.FrameSeq.InitialFrame);
979 }
980
981 ClockDiff = opts.FrameSeq.FinalClock-opts.FrameSeq.InitialClock;
982
983 if (opts.Options & CYCLIC_ANIMATION)
984 {
985 FrameDiff = opts.FrameSeq.FinalFrame-opts.FrameSeq.InitialFrame+1;
986 }
987 else
988 {
989 FrameDiff = opts.FrameSeq.FinalFrame-opts.FrameSeq.InitialFrame;
990 }
991
992 ClockPerFrameIncr = (FrameDiff == 0) ? 0 : (ClockDiff/FrameDiff);
993
994 /* Calculate width, which is an integer log10 */
995
996 NumFrames = opts.FrameSeq.FinalFrame;
997
998 opts.FrameSeq.FrameNumWidth = 1;
999
1000 while (NumFrames >= 10)
1001 {
1002 opts.FrameSeq.FrameNumWidth++;
1003
1004 NumFrames = NumFrames / 10;
1005 }
1006
1007 if (opts.FrameSeq.FrameNumWidth > POV_NAME_MAX-1)
1008 {
1009 Error("Cannot render %d frames requiring %d chars with %d width filename.",
1010 opts.FrameSeq.FinalFrame - opts.FrameSeq.InitialFrame + 1,
1011 opts.FrameSeq.FrameNumWidth, POV_NAME_MAX);
1012 }
1013
1014 /* STARTING FRAME SUBSET */
1015
1016 if (opts.FrameSeq.SubsetStartPercent != DBL_VALUE_UNSET)
1017 {
1018 FrameIncr =
1019 #ifdef AVOID_TYPE_CONVERSION_WARNINGS_PATCH
1020 (int)(
1021 #endif
1022 FrameDiff * opts.FrameSeq.SubsetStartPercent + 0.5
1023 #ifdef AVOID_TYPE_CONVERSION_WARNINGS_PATCH
1024 )
1025 #endif
1026 ; /* w/rounding */
1027
1028 opts.FrameSeq.SubsetStartFrame = opts.FrameSeq.InitialFrame + FrameIncr;
1029 }
1030
1031 if (opts.FrameSeq.SubsetStartFrame != INT_VALUE_UNSET)
1032 {
1033 NumFrames = opts.FrameSeq.SubsetStartFrame - opts.FrameSeq.InitialFrame;
1034
1035 opts.FrameSeq.InitialFrame = opts.FrameSeq.SubsetStartFrame;
1036 opts.FrameSeq.InitialClock = opts.FrameSeq.InitialClock + NumFrames * ClockPerFrameIncr;
1037 }
1038
1039 /* ENDING FRAME SUBSET */
1040
1041 if (opts.FrameSeq.SubsetEndPercent != DBL_VALUE_UNSET)
1042 {
1043 /*
1044 * By this time, we have possibly lost InitialFrame, so we calculate
1045 * it via FinalFrame-FrameDiff
1046 */
1047
1048 FrameIncr =
1049 #ifdef AVOID_TYPE_CONVERSION_WARNINGS_PATCH
1050 (int)(
1051 #endif
1052 FrameDiff * opts.FrameSeq.SubsetEndPercent + 0.5
1053 #ifdef AVOID_TYPE_CONVERSION_WARNINGS_PATCH
1054 )
1055 #endif
1056 ; /* w/rounding */
1057
1058 opts.FrameSeq.SubsetEndFrame = (opts.FrameSeq.FinalFrame - FrameDiff) + FrameIncr;
1059 }
1060
1061 if (opts.FrameSeq.SubsetEndFrame != INT_VALUE_UNSET)
1062 {
1063 NumFrames = opts.FrameSeq.FinalFrame - opts.FrameSeq.SubsetEndFrame;
1064
1065 opts.FrameSeq.FinalFrame = opts.FrameSeq.SubsetEndFrame;
1066 opts.FrameSeq.FinalClock = opts.FrameSeq.FinalClock - NumFrames * ClockPerFrameIncr;
1067 }
1068
1069 /*
1070 * Now that we have everything calculated, we check FinalFrame
1071 * and InitialFrame one more time, in case the subsets messed them up
1072 */
1073
1074 if (opts.FrameSeq.FinalFrame < opts.FrameSeq.InitialFrame)
1075 {
1076 Error("Final frame %d is less than Start Frame %d due to bad subset specification.",
1077 opts.FrameSeq.FinalFrame, opts.FrameSeq.InitialFrame);
1078 }
1079 }
1080
1081 /* Needed for pre-render shellout fixup */
1082
1083 opts.FrameSeq.FrameNumber = opts.FrameSeq.InitialFrame;
1084 opts.FrameSeq.Clock_Value = opts.FrameSeq.InitialClock;
1085
1086 #ifdef FRAME_STEP_PATCH
1087 if(opts.FrameSeq.FrameStep == 0)
1088 {
1089 Warning(0,"Attempted to set step for order of frames to zero.");
1090 opts.FrameSeq.FrameStep = 1;
1091 }
1092 #endif
1093 }
1094
1095 /*****************************************************************************
1096 *
1097 * FUNCTION
1098 *
1099 * fix_up_scene_name
1100 *
1101 * INPUT
1102 *
1103 * OUTPUT
1104 *
1105 * RETURNS
1106 *
1107 * AUTHOR
1108 *
1109 * POV-Ray Team
1110 *
1111 * DESCRIPTION
1112 *
1113 * Strip path and extention of input file to create scene name
1114 *
1115 * CHANGES
1116 *
1117 ******************************************************************************/
1118
fix_up_scene_name()1119 void fix_up_scene_name()
1120 {
1121 int i, l;
1122 char temp[FILE_NAME_LENGTH];
1123
1124 if ((l=strlen(opts.Input_File_Name)-1)<1)
1125 {
1126 strcpy(opts.Scene_Name,opts.Input_File_Name);
1127 return;
1128 }
1129
1130 strcpy(temp,opts.Input_File_Name);
1131 for (i=l;i>0;i--)
1132 {
1133 if (temp[i]==FILENAME_SEPARATOR)
1134 {
1135 break;
1136 }
1137 if (temp[i]=='.')
1138 {
1139 temp[i]=0;
1140 break;
1141 }
1142 }
1143
1144 i=strlen(temp)-1;
1145
1146 while ((i>0) && (temp[i]!=FILENAME_SEPARATOR))
1147 i--;
1148 if (temp[i]==FILENAME_SEPARATOR)
1149 i++;
1150 strcpy(opts.Scene_Name,&(temp[i]));
1151
1152 if (opts.Language_Version > OFFICIAL_VERSION_NUMBER)
1153 {
1154 Error("Your scene file requires POV-Ray version %g or later!\n", (DBL)(opts.Language_Version / 100.0));
1155 }
1156 }
1157
1158 /*****************************************************************************
1159 *
1160 * FUNCTION
1161 *
1162 * init_vars
1163 *
1164 * INPUT
1165 *
1166 * OUTPUT
1167 *
1168 * RETURNS
1169 *
1170 * AUTHOR
1171 *
1172 * POV-Ray Team
1173 *
1174 * DESCRIPTION
1175 *
1176 * Initialize all global variables.
1177 *
1178 * CHANGES
1179 *
1180 * -
1181 *
1182 ******************************************************************************/
1183
init_vars()1184 void init_vars()
1185 {
1186 Stage=STAGE_INIT;
1187 opts.Abort_Test_Counter = Abort_Test_Every ;
1188 Abort_Test_Every = 1;
1189 opts.AntialiasDepth = 3;
1190 opts.Antialias_Threshold = 0.3;
1191 opts.BBox_Threshold = 25;
1192 Color_Bits = 8;
1193 opts.DisplayFormat = '0';
1194 Display_Started = false;
1195 opts.First_Column = 0;
1196 opts.First_Column_Percent = 0.0;
1197 opts.First_Line = 0;
1198 opts.First_Line_Percent = 0.0;
1199 Frame.Screen_Height = 100;
1200 Frame.Screen_Width = 100;
1201 Root_Object = NULL;
1202 free_istack = NULL;
1203 opts.JitterScale = 1.0;
1204 opts.Language_Version = OFFICIAL_VERSION_NUMBER;
1205 opts.Last_Column = -1;
1206 opts.Last_Column_Percent = 1.0;
1207 opts.Last_Line = -1;
1208 opts.Last_Line_Percent = 1.0;
1209 opts.PreviewGridSize_Start = 1;
1210 opts.PreviewGridSize_End = 1;
1211 opts.Library_Paths[0] = NULL;
1212 opts.Library_Path_Index = 0;
1213 Max_Intersections = 64; /*128*/
1214 Number_Of_Files = 0;
1215 Number_of_istacks = 0;
1216
1217 opts.Options = USE_VISTA_BUFFER + USE_LIGHT_BUFFER + JITTER +
1218 DISKWRITE + REMOVE_BOUNDS;
1219 opts.OutputFormat = DEFAULT_OUTPUT_FORMAT;
1220 opts.OutputQuality = 8;
1221 Output_File = NULL;
1222 opts.Output_Numbered_Name[0]='\0';
1223 opts.Output_File_Name[0]='\0';
1224 opts.Output_Path[0]='\0';
1225 opts.Output_File_Type=0;
1226 opts.PaletteOption = '3';
1227 opts.Quality = 9;
1228 opts.Quality_Flags = QUALITY_9;
1229 opts.DisplayGamma = DEFAULT_DISPLAY_GAMMA;
1230
1231 opts.Header_File_Name[0] = '\0';
1232
1233 /*
1234 * If DisplayGamma == 2.2, then GammaFactor == .45, which is what we want.
1235 */
1236 opts.GammaFactor = DEFAULT_ASSUMED_GAMMA/opts.DisplayGamma;
1237
1238 opts.FrameSeq.FrameType = FT_SINGLE_FRAME;
1239 opts.FrameSeq.Clock_Value = 0.0;
1240 #ifdef FRAME_STEP_PATCH
1241 opts.FrameSeq.FrameStep = 1;
1242 #endif
1243 opts.FrameSeq.InitialFrame = 1;
1244 opts.FrameSeq.InitialClock = 0.0;
1245 opts.FrameSeq.FinalFrame = INT_VALUE_UNSET;
1246 opts.FrameSeq.FrameNumWidth = 0;
1247 opts.FrameSeq.FinalClock = 1.0;
1248 opts.FrameSeq.SubsetStartFrame = INT_VALUE_UNSET;
1249 opts.FrameSeq.SubsetStartPercent = DBL_VALUE_UNSET;
1250 opts.FrameSeq.SubsetEndFrame = INT_VALUE_UNSET;
1251 opts.FrameSeq.SubsetEndPercent = DBL_VALUE_UNSET;
1252 opts.FrameSeq.Field_Render_Flag = false;
1253 opts.FrameSeq.Odd_Field_Flag = false;
1254
1255 /* NK rad - these default settings are low quality
1256 for relatively high quality, use
1257
1258 opts.Radiosity_Nearest_Count = 8;
1259 opts.Radiosity_Count = 100;
1260 opts.Radiosity_Recursion_Limit = 5;
1261
1262 Only these variables should need adjustment
1263 */
1264
1265 opts.Radiosity_Brightness = 1.0;
1266 opts.Radiosity_Count = 35;
1267 opts.Radiosity_Dist_Max = 0.0; /* NK rad - dist_max is always computed on the fly now - FYI */
1268 opts.Radiosity_Error_Bound = 1.8;
1269 opts.Radiosity_Gray = 0.0; /* degree to which gathered light is grayed */
1270 opts.Radiosity_Low_Error_Factor = 0.5;
1271 opts.Radiosity_Min_Reuse = 0.015;
1272 opts.Radiosity_Nearest_Count = 5;
1273 opts.Radiosity_Recursion_Limit = 3;
1274 opts.Radiosity_Quality = 6; /* Q-flag value for light gathering */
1275 opts.Radiosity_File_ReadOnContinue = 1;
1276 opts.Radiosity_File_SaveWhileRendering = 1;
1277 opts.Radiosity_File_AlwaysReadAtStart = 0;
1278 opts.Radiosity_File_KeepOnAbort = 1;
1279 opts.Radiosity_File_KeepAlways = 0;
1280 opts.Maximum_Sample_Brightness = -1.0; /* default max brightness allows any */
1281 opts.Radiosity_ADC_Bailout = 0.01; /* use a fairly high default adc_bailout for rad */
1282 opts.Radiosity_Use_Normal = false;
1283 opts.Radiosity_Use_Media = false;
1284 opts.radPretraceStart = 0.08;
1285 opts.radPretraceEnd = 0.04;
1286 opts.Radiosity_Load_File_Name = NULL;
1287 opts.Radiosity_Save_File_Name = NULL;
1288 opts.Radiosity_Add_On_Final_Trace = true;
1289 opts.Radiosity_Enabled = false;
1290
1291 #ifdef NEW_RADIOSITY_PRETRACE_PATCH /* Christoph Hormann March 2005 */
1292 opts.radPretraceAdaptive = 0;
1293 #endif
1294
1295 #ifdef RAD_CUSTOM_SAMPLES_PATCH /* Christoph Hormann January 2003 */
1296 opts.Rad_Samples = NULL;
1297 opts.Rad_Samples_Count = 0;
1298 opts.Rad_Samples_Type = 0;
1299 opts.Rad_Samples_Weight = 0;
1300 #endif
1301 #ifdef RAD_SAMPLES_RANDOMIZE_PATCH /* Christoph Hormann January 2003 */
1302 opts.Rad_Samples_Random = false;
1303 #endif
1304
1305 Current_Line_Number = 0;
1306
1307 init_statistics(stats);
1308 init_statistics(totalstats);
1309
1310 strcpy (opts.Input_File_Name, "OBJECT.POV");
1311 opts.Scene_Name[0]='\0';
1312 opts.Ini_Output_File_Name[0]='\0';
1313 opts.Use_Slabs=true;
1314 Num_Echo_Lines = POV_NUM_ECHO_LINES; /* May make user setable later - CEY*/
1315
1316 closed_flag = false;
1317 Stop_Flag = false;
1318
1319 trender = trender_frame = trender_total = 0.0;
1320 tparse = tparse_frame = tparse_total = 0.0;
1321 tphoton = tphoton_frame = tphoton_total = 0.0;
1322 #ifdef CLOTHRAY_PATCH
1323 tcloth = tcloth_frame = tcloth_total = 0.0;
1324 #endif
1325 #ifdef MECHANICS_SIMULATION_PATCH
1326 tmechsim = tmechsim_frame = tmechsim_total = 0.0;
1327 #endif
1328 #ifdef POST_PROCESS_PATCH
1329 tpostproc = tpostproc_frame = tpostproc_total = 0.0;
1330 #endif
1331 #ifdef PIGMENT_CAMERA_VIEW_PATCH
1332 In_Camera_View_Ray=0;
1333 #endif
1334 histogram_grid = NULL;
1335 opts.histogram_on = false;
1336 opts.histogram_type = NONE;
1337 opts.histogram_file_type=0;
1338 opts.Histogram_File_Name[0] = '\0';
1339 Histogram_File = NULL;
1340 /*
1341 * Note that late initialization of the histogram_x and histogram_y
1342 * variables is done in fix_up_rendering_window, if they aren't specified
1343 * on the command line. This is because they are based on the image
1344 * dimensions, and we can't be certain that we have this info at the
1345 * time we parse the histogram options in optin.c. [AED]
1346 */
1347 opts.histogram_x = opts.histogram_y = 0;
1348 max_histogram_value = 0;
1349
1350 opts.Tracing_Method = 1;
1351 Experimental_Flag = 0;
1352 Make_Pigment_Entries();
1353
1354 opts.Preview_RefCon = 0;
1355
1356 opts.Warning_Level = 10; // all warnings
1357
1358 opts.String_Encoding = 0; // ASCII
1359
1360 (void)POVMSAttrList_New(&opts.Declared_Variables); // we have to be careful... [trf]
1361
1362 /* NK phmap */
1363 backtraceFlag=0;
1364 photonOptions.photonsEnabled = 0;
1365 InitBacktraceWasCalled=false;
1366
1367 photonOptions.photonMap.head = NULL;
1368 photonOptions.photonMap.numPhotons = 0;
1369 photonOptions.photonMap.numBlocks = 0;
1370
1371 photonOptions.photonMap.gatherNumSteps = 2;
1372 photonOptions.photonMap.minGatherRad = -1.0;
1373 photonOptions.photonMap.minGatherRadMult = 1.0;
1374 #ifdef GLOBAL_PHOTONS
1375 photonOptions.globalPhotonMap.gatherNumSteps = 1;
1376 photonOptions.globalPhotonMap.minGatherRad = -1.0;
1377 photonOptions.globalPhotonMap.minGatherRadMult = 1.0;
1378 #endif
1379 photonOptions.mediaPhotonMap.gatherNumSteps = 1;
1380 photonOptions.mediaPhotonMap.minGatherRad = -1.0;
1381 photonOptions.mediaPhotonMap.minGatherRadMult = 1.0;
1382
1383 photonOptions.minGatherCount = 20;
1384 photonOptions.maxGatherCount = 100;
1385
1386 photonOptions.ADC_Bailout = -1; /* use the normal adc bailout */
1387 photonOptions.Max_Trace_Level = -1; /* use the normal max_trace_level */
1388
1389 photonOptions.jitter = 0.4;
1390 photonOptions.autoStopPercent = 0.5;
1391
1392 photonOptions.expandTolerance = 0.2;
1393 photonOptions.minExpandCount = 35;
1394
1395 photonOptions.fileName = NULL;
1396 photonOptions.loadFile = false;
1397
1398 disp_elem = 0; /* for dispersion */
1399 disp_nelems = 0; /* reset this for next pixel's tracing */
1400
1401 photonOptions.photonGatherList = NULL;
1402 photonOptions.photonDistances = NULL;
1403
1404 #ifdef GLOBAL_PHOTONS
1405 /* global photon map */
1406 photonOptions.globalGatherRad = 10.0;
1407 photonOptions.globalPhotonsToShoot = 0;
1408 #endif
1409
1410 photonOptions.surfaceSeparation = 1.0;
1411 photonOptions.globalSeparation = 1.0;
1412
1413 photonOptions.photonMap.head = NULL;
1414 photonOptions.photonMap.numPhotons = 0;
1415 photonOptions.photonMap.numBlocks = 0;
1416 #ifdef GLOBAL_PHOTONS
1417 photonOptions.globalPhotonMap.head = NULL;
1418 photonOptions.globalPhotonMap.numPhotons = 0;
1419 photonOptions.globalPhotonMap.numBlocks = 0;
1420 #endif
1421 photonOptions.mediaPhotonMap.head = NULL;
1422 photonOptions.mediaPhotonMap.numPhotons = 0;
1423 photonOptions.mediaPhotonMap.numBlocks = 0;
1424
1425 photonOptions.maxMediaSteps = 0; /* disable media photons by default */
1426 photonOptions.mediaSpacingFactor = 1.0;
1427
1428 photonOptions.photonReflectionBlur = false; /* off by default */
1429
1430 photonOptions.surfaceCount = 0;
1431 photonOptions.globalCount = 0;
1432
1433 Highest_Trace_Level = 0 ;
1434
1435 /* NK 1999 - bugfix */
1436 Trace_Level = 0;
1437 // [trf] Total_Depth = 0.0;
1438 Radiosity_Trace_Level = 1;
1439
1440 warpNormalTextures = 0;
1441
1442 opts.Noise_Generator = 2; /* default is the range-corrected noise, since the perlin noise (gen 3) seems buggy */
1443
1444 ADC_Bailout = 1.0/255.0;
1445
1446 SuperSampleCount = 0;
1447 RadiosityCount = 0;
1448 MosaicPreviewSize = 0;
1449
1450 #ifdef FILM_EXPOSURE_SIMULATION_PATCH
1451 opts.Exposure = 0.0;
1452 opts.Exposure_Gain = 0.0;
1453 #endif
1454
1455 #ifdef CUSTOM_TONE_MAPPING_PATCH /* Christoph Hormann September 2004 */
1456 opts.Mapping_Function = NULL;
1457 opts.Mapping_Function_Inverse = NULL;
1458 opts.Mapping_Function_Invert = 0;
1459 opts.Mapping_Function_Inverse_Lookup_Table = NULL;
1460 opts.Use_Mapping_Function = false;
1461 #endif
1462
1463 #ifdef RADIOSITY_VISUALIZE_PATCH
1464 opts.Radiosity_Show_Low_Count = false;
1465 Make_Colour(opts.Radiosity_Low_Count_Color, 0.0, 0.0, 0.0);
1466 Make_Colour(opts.Radiosity_Gather_Final_Color, 0.0, 0.0, 0.0);
1467 Make_Colour(opts.Radiosity_Show_Sample_Points, 0.0, 0.0, 0.0);
1468 opts.Radiosity_Show_Sample_Points_Radius = 0.0;
1469 #endif
1470
1471 #ifdef RADIOSITY_ADAPTIVE_RADIUS_PATCH
1472 opts.Radiosity_Error_Bound_Multiplier = 1.0;
1473 opts.Radiosity_Error_Bound_Max = 1.0;
1474 #endif
1475
1476 #ifdef PIGMENT_CAMERA_VIEW_PATCH
1477 opts.Camera_View_Not_In_Rendering = false;
1478 #endif
1479 }
1480
1481
1482 /*****************************************************************************
1483 *
1484 * FUNCTION
1485 *
1486 * variable_store
1487 *
1488 * INPUT
1489 *
1490 * flag - flag telling wether to store or restore variables.
1491 *
1492 * OUTPUT
1493 *
1494 * RETURNS
1495 *
1496 * AUTHOR
1497 *
1498 * Dieter Bayer
1499 *
1500 * DESCRIPTION
1501 *
1502 * Store or restore variables whose value has to be the same for all
1503 * frames of an animation and who are changed during every frame.
1504 *
1505 * CHANGES
1506 *
1507 * May 1995 : Creation.
1508 *
1509 ******************************************************************************/
1510
variable_store(int Flag)1511 void variable_store(int Flag)
1512 {
1513 switch (Flag)
1514 {
1515 case STORE:
1516
1517 STORE_First_Line = opts.First_Line;
1518
1519 break;
1520
1521 case RESTORE:
1522
1523 opts.First_Line = STORE_First_Line;
1524
1525 break;
1526
1527 default:
1528
1529 Error("Unknown flag in variable_store().");
1530 }
1531 }
1532
1533 /*****************************************************************************
1534 *
1535 * FUNCTION
1536 *
1537 * destroy_libraries
1538 *
1539 * INPUT
1540 *
1541 * OUTPUT
1542 *
1543 * RETURNS
1544 *
1545 * AUTHOR
1546 *
1547 * POV-Ray Team
1548 *
1549 * DESCRIPTION
1550 *
1551 * Free library path memory.
1552 *
1553 * CHANGES
1554 *
1555 * -
1556 *
1557 ******************************************************************************/
1558
destroy_libraries()1559 void destroy_libraries()
1560 {
1561 int i;
1562
1563 for (i = 0; i < opts.Library_Path_Index; i++)
1564 {
1565 POV_FREE(opts.Library_Paths[i]);
1566
1567 opts.Library_Paths[i] = NULL;
1568 }
1569
1570 opts.Library_Path_Index = 0;
1571 }
1572
1573
1574
1575 /*****************************************************************************
1576 *
1577 * FUNCTION
1578 *
1579 * close_all
1580 *
1581 * INPUT
1582 *
1583 * OUTPUT
1584 *
1585 * RETURNS
1586 *
1587 * AUTHOR
1588 *
1589 * POV-Ray Team
1590 *
1591 * DESCRIPTION
1592 *
1593 * Close all the stuff that has been opened and free all allocated memory.
1594 *
1595 * CHANGES
1596 *
1597 * -
1598 *
1599 ******************************************************************************/
1600
close_all()1601 void close_all()
1602 {
1603 /* Only close things once */
1604
1605 if (closed_flag)
1606 {
1607 return;
1608 }
1609
1610 FlushDebugMessageBuffer();
1611
1612 FreeBacktraceEverything();
1613
1614 // Close out our file
1615 if(Output_File != NULL)
1616 {
1617 delete Output_File;
1618 Output_File = NULL;
1619 }
1620 #ifdef CLOTHRAY_PATCH
1621 Terminate_Cloth_Sys();
1622 #endif
1623 #ifdef MECHANICS_SIMULATION_PATCH /* Christoph Hormann August 2002 */
1624 Deinitialize_MechSim();
1625 #endif
1626 #ifdef CUSTOM_TONE_MAPPING_PATCH /* Christoph Hormann September 2004 */
1627 Deinitialize_Tone_Mapping();
1628 #endif
1629 #ifdef POST_PROCESS_PATCH
1630 Deinitialize_Post_Processing();
1631 #endif
1632 destroy_libraries();
1633 Terminate_Renderer();
1634 Destroy_Bounding_Slabs();
1635 Destroy_Vista_Buffer();
1636 Destroy_Light_Buffers();
1637 Destroy_Random_Generators();
1638 Deinitialize_Radiosity_Code();
1639 Free_Iteration_Stack();
1640 Free_Noise_Tables();
1641 destroy_histogram();
1642 Deinitialize_Atmosphere_Code();
1643 Deinitialize_BBox_Code();
1644 Deinitialize_Lighting_Code();
1645 Deinitialize_Mesh_Code();
1646 Deinitialize_VLBuffer_Code();
1647 Destroy_Frame();
1648 Destroy_IStacks();
1649 FreeFontInfo();
1650
1651 POVFPU_Terminate();
1652
1653 if ((opts.Options & DISPLAY) && Display_Started)
1654 {
1655 POV_DISPLAY_CLOSE(opts.Preview_RefCon);
1656 }
1657
1658 (void)POVMSAttrList_Delete(&opts.Declared_Variables);
1659
1660 FlushDebugMessageBuffer();
1661
1662 init_shellouts();
1663 closed_flag = true;
1664 }
1665
1666 #ifdef CUSTOM_TONE_MAPPING_PATCH /* Christoph Hormann September 2004 */
1667
1668 /*****************************************************************************
1669 *
1670 * FUNCTION
1671 *
1672 * Initialize_Tone_Mapping
1673 *
1674 * INPUT
1675 *
1676 * OUTPUT
1677 *
1678 * RETURNS
1679 *
1680 * AUTHOR
1681 *
1682 * Christoph Hormann
1683 *
1684 * DESCRIPTION
1685 *
1686 * Calculates the lookup table for inverse tone mapping
1687 * if necessary.
1688 *
1689 * This is done using simple bisection method which should always work
1690 * (i.e. lead to a usable result) even with non-invertible functions.
1691 *
1692 * CHANGES
1693 *
1694 * - February 2005 : Creation
1695 *
1696 ******************************************************************************/
1697
Initialize_Tone_Mapping()1698 void Initialize_Tone_Mapping()
1699 {
1700 COLC Step, Value, Value_Min, Value_Max, Value_XMax;
1701 COLC Function_Value, Function_Value_Min, Function_Value_Max, Function_Value_XMax, Function_Value_Diff;
1702 int i, Max_Idx;
1703
1704 if (opts.Use_Mapping_Function)
1705 if (opts.Mapping_Function_Invert > 0)
1706 {
1707 opts.Mapping_Function_Inverse_Lookup_Table = (COLC *)POV_MALLOC(opts.Mapping_Function_Invert*sizeof (COLC), "tone mapping lookup table");
1708
1709 Step = 1.0/opts.Mapping_Function_Invert;
1710
1711 /* first see if f(0)=0 is fulfilled */
1712 Value_Min = 0.0;
1713 POVFPU_SetLocal(X, Value_Min);
1714 Function_Value_Min = POVFPU_Run(*opts.Mapping_Function);
1715 if (fabs(Function_Value_Min) >= Step)
1716 {
1717 Error("Tone mapping function needs to fulfill f(0)=0\nto be used with numerical inversion.");
1718 }
1719 opts.Mapping_Function_Inverse_Lookup_Table[0] = 0.0;
1720
1721 /* if f(x)<1 for large x we set higher positions in lookup table to 1 */
1722 Value_Max = 1.0e5;
1723 POVFPU_SetLocal(X, Value_Max);
1724 Function_Value_Max = min(1.0, POVFPU_Run(*opts.Mapping_Function));
1725 if (Function_Value_Max <= (1.0-Step))
1726 {
1727 Max_Idx = (int)(Function_Value_Max*opts.Mapping_Function_Invert);
1728 for (i=opts.Mapping_Function_Invert-1;i>Max_Idx;i--)
1729 opts.Mapping_Function_Inverse_Lookup_Table[i] = 1.0;
1730 }
1731 else Max_Idx = opts.Mapping_Function_Invert-1;
1732
1733 /* overall upper limit for bisection interval */
1734 Value_XMax = Value_Max;
1735 Function_Value_XMax = Function_Value_Max;
1736
1737 /* find the root for the different thresholds */
1738 for (i=1;i<=Max_Idx;i++)
1739 {
1740 //Debug_Info(" Initialize_Tone_Mapping(): step %d, %g/%g,%g/%g\n", i, Value_Min, Function_Value_Min, Value_Max, Function_Value_Max);
1741
1742 Value =
1743 (Value_Min * (Function_Value_Max-(Step*i)) + Value_Max * ((Step*i)-Function_Value_Min))/
1744 (Function_Value_Max-Function_Value_Min);
1745
1746 POVFPU_SetLocal(X, Value);
1747 Function_Value = POVFPU_Run(*opts.Mapping_Function);
1748
1749 Function_Value_Diff = Function_Value-(Step*i);
1750
1751 /* we have a stop condition for both function value and interval size to prevent infinite looping */
1752 while((fabs(Function_Value_Diff) > 0.1*Step) && ((Value_Max-Value_Min)>1e-5))
1753 {
1754 if (Function_Value_Diff > 0.0)
1755 {
1756 Function_Value_Max = Function_Value;
1757 Value_Max = Value;
1758 }
1759 else
1760 {
1761 Function_Value_Min = Function_Value;
1762 Value_Min = Value;
1763 }
1764
1765 Value =
1766 (Value_Min * (Function_Value_Max-(Step*i)) + Value_Max * ((Step*i)-Function_Value_Min))/
1767 (Function_Value_Max-Function_Value_Min);
1768
1769 POVFPU_SetLocal(X, Value);
1770 Function_Value = POVFPU_Run(*opts.Mapping_Function);
1771 Function_Value_Diff = Function_Value-(Step*i);
1772 }
1773
1774 opts.Mapping_Function_Inverse_Lookup_Table[i] = Value;
1775
1776 Value_Max = Value_XMax;
1777 Function_Value_Max = Function_Value_XMax;
1778 Value_Min = Value;
1779 Function_Value_Min = Function_Value;
1780
1781 }
1782 }
1783 }
1784
1785 /*****************************************************************************
1786 *
1787 * FUNCTION
1788 *
1789 * Deinitialize_Tone_Mapping
1790 *
1791 * INPUT
1792 *
1793 * OUTPUT
1794 *
1795 * RETURNS
1796 *
1797 * AUTHOR
1798 *
1799 * Christoph Hormann
1800 *
1801 * DESCRIPTION
1802 *
1803 * frees functions and lookup table for tone mapping when necessary
1804 *
1805 * CHANGES
1806 *
1807 * - September 2004: Creation
1808 *
1809 ******************************************************************************/
1810
Deinitialize_Tone_Mapping()1811 void Deinitialize_Tone_Mapping()
1812 {
1813 if (opts.Mapping_Function != NULL) POV_FREE(opts.Mapping_Function);
1814 if (opts.Mapping_Function_Inverse != NULL) POV_FREE(opts.Mapping_Function_Inverse);
1815 if (opts.Mapping_Function_Inverse_Lookup_Table != NULL) POV_FREE(opts.Mapping_Function_Inverse_Lookup_Table);
1816
1817 opts.Mapping_Function_Invert = 0;
1818 opts.Use_Mapping_Function = false;
1819 }
1820
1821 #endif
1822
1823 END_POV_NAMESPACE
1824