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