Simple test for asyncio.library.
[AROS-Contrib.git] / gfx / povray / povray.c
blob1dd24cea2209722abb6f79ef90a64c978b40a1c8
1 /****************************************************************************
2 * povray.c
4 * This module contains the entry routine for the raytracer and the code to
5 * parse the parameters on the command line.
7 * from Persistence of Vision(tm) Ray Tracer
8 * Copyright 1996,1999 Persistence of Vision Team
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 Team. There are strict rules under
13 * which you are permitted to use this file. The rules are in the file
14 * named POVLEGAL.DOC which should be distributed with this file.
15 * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
16 * Team Coordinator by email to team-coord@povray.org or visit us on the web at
17 * http://www.povray.org. The latest version of POV-Ray may be found at this site.
19 * This program is based on the popular DKB raytracer version 2.12.
20 * DKBTrace was originally written by David K. Buck.
21 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
23 *****************************************************************************/
25 #include <ctype.h>
26 #include <time.h> /* BP */
27 #include "frame.h" /* common to ALL modules in this program */
28 #include "povproto.h"
29 #include "bezier.h"
30 #include "blob.h"
31 #include "bbox.h"
32 #include "cones.h"
33 #include "csg.h"
34 #include "discs.h"
35 #include "express.h"
36 #include "fractal.h"
37 #include "hfield.h"
38 #include "lathe.h"
39 #include "lighting.h"
40 #include "mem.h"
41 #include "mesh.h"
42 #include "polysolv.h"
43 #include "objects.h"
44 #include "octree.h"
45 #include "parse.h"
46 #include "pigment.h"
47 #include "point.h"
48 #include "poly.h"
49 #include "polygon.h"
50 #include "povray.h"
51 #include "optin.h"
52 #include "optout.h"
53 #include "quadrics.h"
54 #include "pgm.h"
55 #include "png_pov.h"
56 #include "ppm.h"
57 #include "prism.h"
58 #include "radiosit.h"
59 #include "render.h"
60 #include "sor.h"
61 #include "spheres.h"
62 #include "super.h"
63 #include "targa.h"
64 #include "texture.h"
65 #include "tokenize.h"
66 #include "torus.h"
67 #include "triangle.h"
68 #include "truetype.h"
69 #include "userio.h" /*Error,Warning,Init_Text_Streams*/
70 #include "lbuffer.h"
71 #include "vbuffer.h"
74 /*****************************************************************************
75 * Local preprocessor defines
76 ******************************************************************************/
78 /* Flags for the variable store. */
80 #define STORE 1
81 #define RESTORE 2
85 /*****************************************************************************
86 * Local typedefs
87 ******************************************************************************/
91 /*****************************************************************************
92 * Local variables
93 ******************************************************************************/
95 /* The frame. */
97 FRAME Frame;
99 /* Options and display stuff. */
101 char Color_Bits;
103 int Display_Started;
105 int Abort_Test_Every;
107 int Experimental_Flag;
109 /* Current stage of the program. */
111 int Stage;
113 /* Flag if -h option will show help screens. */
115 int Help_Available;
117 /* File and parsing stuff. */
119 Opts opts;
120 COUNTER stats[MaxStat];
121 COUNTER totalstats[MaxStat];
123 int Num_Echo_Lines; /* May make user setable later - CEY*/
124 int Echo_Line_Length; /* May make user setable later - CEY*/
126 int Number_Of_Files;
128 FILE *stat_file;
129 FILE_HANDLE *Output_File_Handle;
131 char Actual_Output_Name[FILE_NAME_LENGTH];
133 /* Timing stuff .*/
135 time_t tstart, tstop;
136 DBL tparse, trender, tparse_total, trender_total;
138 /* Variable used by vector macros. */
140 DBL VTemp;
141 volatile int Stop_Flag;
143 /* Flag if close_all() was already called. */
144 static int closed_flag;
146 int pre_init_flag=0;
148 char *Option_String_Ptr;
149 DBL Clock_Delta;
151 /*****************************************************************************
152 * Static functions
153 ******************************************************************************/
155 static void init_vars (void);
156 static void destroy_libraries (void);
157 static void fix_up_rendering_window (void);
158 static void fix_up_animation_values (void);
159 static void fix_up_scene_name (void);
160 static void set_output_file_handle (void);
161 static void setup_output_file_name (void);
162 static void open_output_file (void);
163 static void FrameRender (void);
164 static void init_statistics (COUNTER *);
165 static void sum_statistics (COUNTER *, COUNTER *);
166 static void variable_store (int Flag);
167 static int Has_Extension (char *name);
168 static unsigned closest_power_of_2 (unsigned theNumber);
169 static void init_shellouts (void);
170 static void destroy_shellouts (void);
173 /*****************************************************************************
175 * FUNCTION
177 * main
179 * INPUT
181 * OUTPUT
183 * RETURNS
185 * AUTHOR
187 * POV-Ray Team
189 * DESCRIPTION
193 * CHANGES
197 ******************************************************************************/
200 #ifdef NOCMDLINE /* a main() by any other name... */
201 #ifdef ALTMAIN
202 MAIN_RETURN_TYPE alt_main()
203 #else
204 MAIN_RETURN_TYPE main()
205 #endif
206 #else
207 #ifdef ALTMAIN
208 MAIN_RETURN_TYPE alt_main(int argc, char **argv)
209 #else
210 MAIN_RETURN_TYPE main(int argc, char **argv)
211 #endif
212 #endif /* ...would be a lot less hassle!! :-) AAC */
214 register int i;
215 int Diff_Frame;
216 DBL Diff_Clock;
217 SHELLRET Pre_Scene_Result, Frame_Result;
219 /* Attention all ALTMAIN people! See comments attached to this function*/
220 pre_init_povray();
222 /* Startup povray. */
223 Stage = STAGE_STARTUP;
224 STARTUP_POVRAY
226 /* Print banner and credit info. */
227 Stage = STAGE_BANNER;
228 PRINT_CREDITS
229 PRINT_OTHER_CREDITS
231 #ifndef NOCMDLINE
232 /* Print help screens. */
234 if (argc == 1)
236 Print_Help_Screens();
238 #endif
240 /* Initialize variables. */
241 init_vars();
243 Stage = STAGE_ENVIRONMENT;
245 READ_ENV_VAR
247 Stage = STAGE_INI_FILE;
249 /* Read parameters from POVRAY.INI */
250 PROCESS_POVRAY_INI
252 #ifndef NOCMDLINE
253 /* Parse the command line parameters */
255 Stage = STAGE_COMMAND_LINE;
257 Help_Available = (argc == 2);
259 for (i = 1 ; i < argc ; i++ )
261 parse_option_line(argv[i]);
263 #endif
265 /* Strip path and extension off input name to create scene name */
266 fix_up_scene_name ();
268 /* Redirect text streams [SCD 2/95] */
269 Open_Text_Streams();
271 /* Write .INI file [SCD 2/95] */
272 Write_INI_File();
274 ALT_WRITE_INI_FILE
276 /* Make sure clock is okay, validate animation parameters */
277 fix_up_animation_values();
279 /* Fix-up rendering window values if necessary. */
280 fix_up_rendering_window();
282 /* Set output file handle for options screen. */
283 set_output_file_handle();
285 /* Print options used. */
286 Print_Options();
288 /* BEGIN SECTION */
289 /* VARIOUS INITIALIZATION THAT ONLY NEEDS TO BE DONE 1/EXECUTION */
291 /* Set up noise-tables. */
292 Initialize_Noise();
294 Diff_Clock = opts.FrameSeq.FinalClock - opts.FrameSeq.InitialClock;
296 if (opts.Options & CYCLIC_ANIMATION)
298 Diff_Frame = opts.FrameSeq.FinalFrame - opts.FrameSeq.InitialFrame + 1;
300 else
302 Diff_Frame = opts.FrameSeq.FinalFrame - opts.FrameSeq.InitialFrame;
305 Clock_Delta = ((Diff_Frame==0)?0:Diff_Clock/Diff_Frame);
307 /* END SECTION */
309 /* Execute the first shell-out command */
310 Pre_Scene_Result=(POV_SHELLOUT_CAST)POV_SHELLOUT(PRE_SCENE_SHL);
312 /* Loop over each frame */
314 if (Pre_Scene_Result != ALL_SKIP_RET)
316 if (Pre_Scene_Result != SKIP_ONCE_RET)
318 for (opts.FrameSeq.FrameNumber = opts.FrameSeq.InitialFrame,
319 opts.FrameSeq.Clock_Value = opts.FrameSeq.InitialClock;
321 opts.FrameSeq.FrameNumber <= opts.FrameSeq.FinalFrame;
323 opts.FrameSeq.FrameNumber++,
324 opts.FrameSeq.Clock_Value += Clock_Delta)
326 setup_output_file_name();
328 /* Execute a shell-out command before tracing */
330 Frame_Result=(POV_SHELLOUT_CAST)POV_SHELLOUT(PRE_FRAME_SHL);
332 if (Frame_Result == ALL_SKIP_RET)
334 break;
337 if (Frame_Result != SKIP_ONCE_RET)
339 FrameRender();
341 /* Execute a shell-out command after tracing */
343 Frame_Result = (POV_SHELLOUT_CAST)POV_SHELLOUT(POST_FRAME_SHL);
345 if ((Frame_Result==SKIP_ONCE_RET) || (Frame_Result==ALL_SKIP_RET))
347 break;
352 /* Print total stats ... */
354 if(opts.FrameSeq.FrameType==FT_MULTIPLE_FRAME)
356 Statistics("\nTotal Statistics");
358 opts.FrameSeq.FrameNumber--;
360 PRINT_STATS(totalstats);
362 opts.FrameSeq.FrameNumber++;
366 /* Execute the final shell-out command */
368 POV_SHELLOUT(POST_SCENE_SHL);
371 /* And finish. */
373 Terminate_POV(0);
375 MAIN_RETURN_STATEMENT
376 } /* main */
379 /*****************************************************************************
381 * FUNCTION
383 * FrameRender
385 * INPUT
387 * OUTPUT
389 * RETURNS
391 * AUTHOR
393 * POV-Ray Team
395 * DESCRIPTION
397 * Do all that is necessary for rendering a single frame, including parsing
399 * CHANGES
401 * Feb 1996: Make sure we are displaying when doing a mosaic preview [AED]
403 ******************************************************************************/
405 static void FrameRender()
407 unsigned long hours, minutes;
408 DBL seconds, t_total;
410 /* Store start time for parse. */
411 START_TIME
413 /* Parse the scene file. */
414 Status_Info("\n\nParsing...");
416 opts.Do_Stats=FALSE;
418 Init_Random_Generators();
420 Parse();
422 Destroy_Random_Generators();
424 opts.Do_Stats=TRUE;
426 if (opts.Options & RADIOSITY)
428 Experimental_Flag |= EF_RADIOS;
431 if (Experimental_Flag)
433 Warning(0.0,"Warning: This rendering uses the following experimental features:\n");
434 if (Experimental_Flag & EF_RADIOS)
436 Warning(0.0," radiosity");
438 Warning(0.0,".\nThe design and implementation of these features is likely to\n");
439 Warning(0.0,"change in future versions of POV-Ray. Full backward compatibility\n");
440 Warning(0.0,"with the current implementation is NOT guaranteed.\n");
443 Experimental_Flag=0;
445 /* Switch off standard anti-aliasing. */
447 if ((Frame.Camera->Aperture != 0.0) && (Frame.Camera->Blur_Samples > 0))
449 opts.Options &= ~ANTIALIAS;
451 Warning(0.0, "Focal blur is used. Standard antialiasing is switched off.\n");
454 /* Create the bounding box hierarchy. */
456 Stage = STAGE_SLAB_BUILDING;
458 if (opts.Use_Slabs)
460 Status_Info("\nCreating bounding slabs.");
463 /* Init module specific stuff. */
464 Initialize_Atmosphere_Code();
465 Initialize_BBox_Code();
466 Initialize_Lighting_Code();
467 Initialize_Mesh_Code();
468 Initialize_VLBuffer_Code();
469 Initialize_Radiosity_Code();
471 /* Always call this to print number of objects. */
472 Build_Bounding_Slabs(&Root_Object);
474 /* Create the vista buffer. */
475 Build_Vista_Buffer();
477 /* Create the light buffers. */
478 Build_Light_Buffers();
480 /* Create blob queue. */
481 Init_Blob_Queue();
483 /* Save variable values. */
484 variable_store(STORE);
486 /* Open output file and if we are continuing an interrupted trace,
487 * read in the previous file settings and any data there. This has to
488 * be done before any image-size related allocations, since the settings
489 * in a resumed file take precedence over that specified by the user. [AED]
491 open_output_file();
493 /* Start the display. */
494 if (opts.Options & DISPLAY)
496 Status_Info ("\nDisplaying...");
498 POV_DISPLAY_INIT(Frame.Screen_Width, Frame.Screen_Height);
500 Display_Started = TRUE;
502 /* Display vista tree. */
503 Draw_Vista_Buffer();
506 /* Get things ready for ray tracing (misc init, mem alloc) */
507 Initialize_Renderer();
509 /* This had to be taken out of open_output_file() because we don't have
510 * the final image size until the output file has been opened, so we can't
511 * initialize the display until we know this, which in turn means we can't
512 * read the rendered part before the display is initialized. [AED]
514 if ((opts.Options & DISKWRITE) && (opts.Options & CONTINUE_TRACE))
516 Read_Rendered_Part(Actual_Output_Name);
518 if (opts.Last_Line > Frame.Screen_Height)
519 opts.Last_Line = Frame.Screen_Height;
521 if (opts.Last_Column > Frame.Screen_Width)
522 opts.Last_Column = Frame.Screen_Width;
526 /* Get parsing time. */
527 STOP_TIME
528 tparse = TIME_ELAPSED
530 /* Get total parsing time. */
531 tparse_total += tparse;
533 /* Store start time for trace. */
534 START_TIME
536 if(opts.FrameSeq.FrameType==FT_MULTIPLE_FRAME)
538 t_total=tparse_total+trender_total;
539 SPLIT_TIME(t_total,&hours,&minutes,&seconds);
540 Render_Info("\n %02ld:%02ld:%02.0f so far, ",hours,minutes,seconds);
541 Render_Info("Rendering frame %d, going to %d.",
542 opts.FrameSeq.FrameNumber, opts.FrameSeq.FinalFrame);
544 /* Start tracing. */
545 Stage = STAGE_RENDERING;
547 POV_PRE_RENDER
549 Status_Info ("\nRendering...\r");
551 /* Macro for setting up any special FP options */
552 CONFIG_MATH
554 /* Ok, go for it - trace the picture. */
556 /* If radiosity preview has been done, we are continuing a trace, so it
557 * is important NOT to do the preview, even if the user requests it, as it
558 * will cause discontinuities in radiosity shading by (probably) calculating
559 * a few more radiosity values.
561 if ( !opts.Radiosity_Preview_Done )
563 if ( opts.Options & RADIOSITY )
565 /* Note that radiosity REQUIRES a mosaic preview prior to main scan */
567 Start_Tracing_Mosaic_Smooth(opts.PreviewGridSize_Start, opts.PreviewGridSize_End);
569 else
571 if (opts.Options & PREVIEW && opts.Options & DISPLAY)
573 Start_Tracing_Mosaic_Preview(opts.PreviewGridSize_Start, opts.PreviewGridSize_End);
578 switch (opts.Tracing_Method)
580 case 2 :
582 Start_Adaptive_Tracing();
584 break;
586 case 1 :
587 default:
589 Start_Non_Adaptive_Tracing();
592 /* We're done. */
594 /* Record time so well spent before file close so it can be in comments */
595 STOP_TIME
596 trender = TIME_ELAPSED
598 /* Close out our file */
599 if (Output_File_Handle)
601 Close_File(Output_File_Handle);
604 Stage = STAGE_SHUTDOWN;
606 POV_PRE_SHUTDOWN
608 /* DESTROY lots of stuff */
609 Deinitialize_Atmosphere_Code();
610 Deinitialize_BBox_Code();
611 Deinitialize_Lighting_Code();
612 Deinitialize_Mesh_Code();
613 Deinitialize_VLBuffer_Code();
614 Deinitialize_Radiosity_Code();
615 Destroy_Blob_Queue();
616 Destroy_Light_Buffers();
617 Destroy_Vista_Buffer();
618 Destroy_Bounding_Slabs();
619 Destroy_Frame();
620 Terminate_Renderer();
621 FreeFontInfo();
622 Free_Iteration_Stack();
624 POV_POST_SHUTDOWN
626 /* Get total render time. */
627 trender_total += trender;
629 POV_DISPLAY_FINISHED
631 if ((opts.Options & DISPLAY) && Display_Started)
633 POV_DISPLAY_CLOSE
635 Display_Started = FALSE;
638 if (opts.histogram_on)
639 write_histogram (opts.Histogram_File_Name) ;
641 Status_Info("\nDone Tracing");
643 /* Print stats ... */
644 PRINT_STATS(stats);
646 if(opts.FrameSeq.FrameType==FT_MULTIPLE_FRAME)
648 /* Add them up */
649 sum_statistics(totalstats, stats);
651 /* ... and then clear them for the next frame */
652 init_statistics(stats);
655 /* Restore variable values. */
656 variable_store(RESTORE);
662 /*****************************************************************************
664 * FUNCTION
666 * fix_up_rendering_window
668 * INPUT
670 * OUTPUT
672 * RETURNS
674 * AUTHOR
676 * POV-Ray Team
678 * DESCRIPTION
680 * Fix wrong window and mosaic preview values.
682 * CHANGES
686 ******************************************************************************/
688 static void fix_up_rendering_window()
690 int temp;
692 if (opts.First_Column_Percent > 0.0)
693 opts.First_Column = (int) (Frame.Screen_Width * opts.First_Column_Percent);
695 if (opts.First_Line_Percent > 0.0)
696 opts.First_Line = (int) (Frame.Screen_Height * opts.First_Line_Percent);
698 /* The decrements are a fudge factor that used to be in OPTIN.C
699 * but it messed up Write_INI_File so its moved here.
702 if (opts.First_Column <= 0)
703 opts.First_Column = 0;
704 else
705 opts.First_Column--;
707 if (opts.First_Line <= 0)
708 opts.First_Line = 0;
709 else
710 opts.First_Line--;
712 if ((opts.Last_Column == -1) && (opts.Last_Column_Percent <= 1.0))
713 opts.Last_Column = (int) (Frame.Screen_Width * opts.Last_Column_Percent);
715 if ((opts.Last_Line == -1) && (opts.Last_Line_Percent <= 1.0))
716 opts.Last_Line = (int) (Frame.Screen_Height * opts.Last_Line_Percent);
718 if (opts.Last_Line == -1)
719 opts.Last_Line = Frame.Screen_Height;
721 if (opts.Last_Column == -1)
722 opts.Last_Column = Frame.Screen_Width;
724 if (opts.Last_Column < 0 || opts.Last_Column > Frame.Screen_Width)
725 opts.Last_Column = Frame.Screen_Width;
727 if (opts.Last_Line > Frame.Screen_Height)
728 opts.Last_Line = Frame.Screen_Height;
730 /* Fix up Mosaic Preview values */
731 opts.PreviewGridSize_Start=max(1,opts.PreviewGridSize_Start);
732 opts.PreviewGridSize_End=max(1,opts.PreviewGridSize_End);
734 if ((temp=closest_power_of_2((unsigned)opts.PreviewGridSize_Start))!=opts.PreviewGridSize_Start)
736 Warning(0.0,"Preview_Start_Size must be a power of 2. Changing to %d.\n",temp);
737 opts.PreviewGridSize_Start=temp;
740 if ((temp=closest_power_of_2((unsigned)opts.PreviewGridSize_End))!=opts.PreviewGridSize_End)
742 Warning(0.0,"Preview_End_Size must be a power of 2. Changing to %d.\n",temp);
743 opts.PreviewGridSize_End=temp;
746 /* End must be less than or equal to start */
747 if (opts.PreviewGridSize_End > opts.PreviewGridSize_Start)
748 opts.PreviewGridSize_End = opts.PreviewGridSize_Start;
750 if (opts.PreviewGridSize_Start > 1)
752 opts.PreviewGridSize_End=max(opts.PreviewGridSize_End,2);
753 opts.Options |= PREVIEW;
755 else
757 opts.Options &= ~PREVIEW;
760 /* Set histogram size here so it is available for Print_Options, and
761 * make sure that it has an integer number of pixels/bucket. */
762 if (opts.histogram_on)
764 if (opts.histogram_x == 0 || opts.histogram_x > Frame.Screen_Width)
765 opts.histogram_x = Frame.Screen_Width;
766 else if (opts.histogram_x < Frame.Screen_Width)
767 opts.histogram_x = Frame.Screen_Width / ((Frame.Screen_Width +
768 opts.histogram_x - 1) / opts.histogram_x);
770 if (opts.histogram_y == 0 || opts.histogram_y > Frame.Screen_Height)
771 opts.histogram_y = Frame.Screen_Height;
772 else if (opts.histogram_y < Frame.Screen_Height)
773 opts.histogram_y = Frame.Screen_Height / ((Frame.Screen_Height +
774 opts.histogram_y - 1) /opts.histogram_y);
778 /*****************************************************************************
780 * FUNCTION
782 * fix_up_animation_values
784 * INPUT
786 * OUTPUT
788 * RETURNS
790 * AUTHOR
792 * POV-Ray Team
794 * DESCRIPTION
796 * Validate animation parameters, compute subset values
798 * CHANGES
802 ******************************************************************************/
803 static void fix_up_animation_values()
805 float ClockDiff;
806 int FrameDiff;
807 int FrameIncr;
808 float ClockPerFrameIncr;
809 int NumFrames;
811 if (opts.FrameSeq.FinalFrame != -1)
813 opts.FrameSeq.FrameType = FT_MULTIPLE_FRAME;
815 if (opts.FrameSeq.Clock_Value != 0.0)
817 Warning(0.0,"Attempted to set single clock value in multi frame\nanimation. Clock value overridden.\n");
820 else
822 if (opts.FrameSeq.Clock_Value != 0.0)
824 opts.FrameSeq.FrameType = FT_SINGLE_FRAME;
828 if (opts.FrameSeq.FrameType == FT_SINGLE_FRAME)
831 * These are dummy values that will work for single_frame,
832 * even in an animation loop.
835 opts.FrameSeq.InitialFrame = 0;
836 opts.FrameSeq.FinalFrame = 0;
837 opts.FrameSeq.InitialClock = opts.FrameSeq.Clock_Value;
838 opts.FrameSeq.FinalClock = 0.0;
840 else
842 /* FrameType==FT_MULTIPLE_FRAME */
844 if(opts.FrameSeq.InitialFrame == -1)
846 opts.FrameSeq.InitialFrame = 1;
849 if (opts.FrameSeq.FinalFrame < opts.FrameSeq.InitialFrame)
851 Error("Final frame %d is less than Start Frame %d.\n",
852 opts.FrameSeq.FinalFrame, opts.FrameSeq.InitialFrame);
855 ClockDiff = opts.FrameSeq.FinalClock-opts.FrameSeq.InitialClock;
857 if (opts.Options & CYCLIC_ANIMATION)
859 FrameDiff = opts.FrameSeq.FinalFrame-opts.FrameSeq.InitialFrame+1;
861 else
863 FrameDiff = opts.FrameSeq.FinalFrame-opts.FrameSeq.InitialFrame;
866 ClockPerFrameIncr = (FrameDiff == 0) ? 0 : (ClockDiff/FrameDiff);
868 /* Calculate width, which is an integer log10 */
870 NumFrames = opts.FrameSeq.FinalFrame;
872 opts.FrameSeq.FrameNumWidth = 1;
874 while (NumFrames >= 10)
876 opts.FrameSeq.FrameNumWidth++;
878 NumFrames = NumFrames / 10;
881 if (opts.FrameSeq.FrameNumWidth > POV_NAME_MAX-1)
883 Error("Can't render %d frames requiring %d chars with %d width filename.\n",
884 opts.FrameSeq.FinalFrame - opts.FrameSeq.InitialFrame + 1,
885 opts.FrameSeq.FrameNumWidth, POV_NAME_MAX);
888 /* STARTING FRAME SUBSET */
890 if (opts.FrameSeq.SubsetStartPercent != DBL_VALUE_UNSET)
892 FrameIncr = FrameDiff * opts.FrameSeq.SubsetStartPercent + 0.5; /* w/rounding */
894 opts.FrameSeq.SubsetStartFrame = opts.FrameSeq.InitialFrame + FrameIncr;
897 if (opts.FrameSeq.SubsetStartFrame != INT_VALUE_UNSET)
899 NumFrames = opts.FrameSeq.SubsetStartFrame - opts.FrameSeq.InitialFrame;
901 opts.FrameSeq.InitialFrame = opts.FrameSeq.SubsetStartFrame;
902 opts.FrameSeq.InitialClock = opts.FrameSeq.InitialClock + NumFrames * ClockPerFrameIncr;
905 /* ENDING FRAME SUBSET */
907 if (opts.FrameSeq.SubsetEndPercent != DBL_VALUE_UNSET)
910 * By this time, we have possibly lost InitialFrame, so we calculate
911 * it via FinalFrame-FrameDiff
914 FrameIncr = FrameDiff * opts.FrameSeq.SubsetEndPercent + 0.5; /* w/rounding */
916 opts.FrameSeq.SubsetEndFrame = (opts.FrameSeq.FinalFrame - FrameDiff) + FrameIncr;
919 if (opts.FrameSeq.SubsetEndFrame != INT_VALUE_UNSET)
921 NumFrames = opts.FrameSeq.FinalFrame - opts.FrameSeq.SubsetEndFrame;
923 opts.FrameSeq.FinalFrame = opts.FrameSeq.SubsetEndFrame;
924 opts.FrameSeq.FinalClock = opts.FrameSeq.FinalClock - NumFrames * ClockPerFrameIncr;
928 * Now that we have everything calculated, we check FinalFrame
929 * and InitialFrame one more time, in case the subsets messed them up
932 if (opts.FrameSeq.FinalFrame < opts.FrameSeq.InitialFrame)
934 Error("Final frame %d is less than Start Frame %d\ndue to bad subset specification.\n",
935 opts.FrameSeq.FinalFrame, opts.FrameSeq.InitialFrame);
939 /* Needed for pre-render shellout fixup */
941 opts.FrameSeq.FrameNumber = opts.FrameSeq.InitialFrame;
942 opts.FrameSeq.Clock_Value = opts.FrameSeq.InitialClock;
945 /*****************************************************************************
947 * FUNCTION
949 * fix_up_scene_name
951 * INPUT
953 * OUTPUT
955 * RETURNS
957 * AUTHOR
959 * POV-Ray Team
961 * DESCRIPTION
963 * Strip path and extention of input file to create scene name
965 * CHANGES
967 ******************************************************************************/
969 static void fix_up_scene_name()
971 int i, l;
972 char temp[FILE_NAME_LENGTH];
974 if ((l=strlen(opts.Input_File_Name)-1)<1)
976 strcpy(opts.Scene_Name,opts.Input_File_Name);
977 return;
980 strcpy(temp,opts.Input_File_Name);
981 for (i=l;i>0;i--)
983 if (temp[i]==FILENAME_SEPARATOR)
985 break;
987 if (temp[i]=='.')
989 temp[i]=0;
990 break;
994 i=strlen(temp)-1;
996 while ((i>0) && (temp[i]!=FILENAME_SEPARATOR))
997 i--;
998 if (temp[i]==FILENAME_SEPARATOR)
999 i++;
1000 strcpy(opts.Scene_Name,&(temp[i]));
1003 /*****************************************************************************
1005 * FUNCTION
1007 * set_output_file_handle
1009 * INPUT
1011 * OUTPUT
1013 * RETURNS
1015 * AUTHOR
1017 * POV-Ray Team
1019 * DESCRIPTION
1021 * Set the output file handle according to the file type used.
1023 * CHANGES
1025 * Oct 95 - Removed test where the output file handle was only set if
1026 * output_to_file was TRUE. The output file handle structure
1027 * contains a pointer to read line, which is used by the continue
1028 * trace option. If you tried a continue trace with file output
1029 * manually turned OFF, then a GPF would occur due to a call to a
1030 * NULL function pointer.
1032 ******************************************************************************/
1034 static void set_output_file_handle()
1036 char *def_ext = NULL;
1037 char temp[FILE_NAME_LENGTH];
1039 switch (opts.OutputFormat)
1041 case '\0':
1042 case 's' :
1043 case 'S' : Output_File_Handle = GET_SYS_FILE_HANDLE(); def_ext=SYS_DEF_EXT; break;
1045 case 't' :
1046 case 'T' :
1047 case 'c' :
1048 case 'C' : Output_File_Handle = Get_Targa_File_Handle(); def_ext=".tga"; break;
1050 case 'p' :
1051 case 'P' : Output_File_Handle = Get_PPM_File_Handle(); def_ext=".ppm"; break;
1053 case 'n' :
1054 case 'N' : Output_File_Handle = Get_Png_File_Handle(); def_ext=".png"; break;
1056 case 'd' :
1057 case 'D' : Error ("Dump format no longer supported.\n"); break;
1058 case 'r' :
1059 case 'R' : Error ("Raw format no longer supported.\n"); break;
1061 default : Error ("Unrecognized output file format %c.\n",
1062 opts.OutputFormat);
1065 Output_File_Handle->file_type = IMAGE_FTYPE;
1067 strcpy(temp,opts.Output_File_Name);
1069 POV_SPLIT_PATH(temp,opts.Output_Path,opts.Output_File_Name);
1071 if (opts.Output_File_Name[0] == '\0')
1073 sprintf(opts.Output_File_Name, "%s%s",opts.Scene_Name,def_ext);
1075 else if (!(opts.Options & TO_STDOUT))
1077 if (!Has_Extension(opts.Output_File_Name))
1079 strcat(opts.Output_File_Name, def_ext);
1083 strcpy(opts.Output_Numbered_Name,opts.Output_File_Name);
1086 /*****************************************************************************
1088 * FUNCTION
1090 * setup_output_file_name
1092 * INPUT
1094 * OUTPUT
1096 * RETURNS
1098 * AUTHOR
1100 * POV-Ray Team
1102 * DESCRIPTION
1104 * Determine the file name for this frame. For an animation, the frame
1105 * number is inserted into the file name.
1107 * CHANGES
1109 * Jan-97 [esp] Added conditional after getcwd, because Metrowerks getcwd
1110 * function appends a path separator on output.
1112 ******************************************************************************/
1113 static void setup_output_file_name()
1115 char number_string[10];
1116 char separator_string[2] = {FILENAME_SEPARATOR, 0} ;
1117 char *plast_period;
1118 int available_characters;
1119 int ilast_period;
1120 int fname_chars;
1122 /* This will create the real name for the file */
1123 if(opts.FrameSeq.FrameType!=FT_MULTIPLE_FRAME ||
1124 opts.Options & TO_STDOUT)
1126 strcpy(opts.Output_Numbered_Name,opts.Output_File_Name);
1128 else
1131 * This is the maximum number of characters that can be used of the
1132 * original filename. This will ensure that enough space is available
1133 * for the frame number in the filename
1136 available_characters = POV_NAME_MAX-opts.FrameSeq.FrameNumWidth;
1138 plast_period = strrchr(opts.Output_File_Name, '.');
1140 if (plast_period == NULL)
1142 Error("Illegal file name %s -- no extension.\n", opts.Output_File_Name);
1145 ilast_period = plast_period - opts.Output_File_Name;
1147 fname_chars = ilast_period;
1149 if (fname_chars > available_characters)
1151 /* Only give the warning once */
1153 if (opts.FrameSeq.FrameNumber == opts.FrameSeq.InitialFrame)
1155 Warning(0.0, "Need to cut the output filename by %d characters.\n",
1156 ilast_period - available_characters);
1159 fname_chars = available_characters;
1162 /* Perform actual generation of filename */
1164 strncpy(opts.Output_Numbered_Name, opts.Output_File_Name, (unsigned)fname_chars);
1166 /* strncpy doesn't terminate if strlen(opts.Output_File_Name)<fname_chars */
1168 opts.Output_Numbered_Name[fname_chars]='\0';
1170 sprintf(number_string, "%0*d", opts.FrameSeq.FrameNumWidth, opts.FrameSeq.FrameNumber);
1172 strcat(opts.Output_Numbered_Name, number_string);
1174 strcat(opts.Output_Numbered_Name, &opts.Output_File_Name[ilast_period]);
1177 if (strlen (opts.Output_Path) == 0)
1179 getcwd (opts.Output_Path, sizeof (opts.Output_Path) - 1) ;
1180 /* on some systems (MacOS) getcwd adds the path separator on the end */
1181 /* so only add it if it isn't already there... [esp] */
1182 if (opts.Output_Path[strlen(opts.Output_Path)-1] != FILENAME_SEPARATOR)
1183 strcat (opts.Output_Path, separator_string) ;
1185 strncpy (Actual_Output_Name,opts.Output_Path, sizeof (Actual_Output_Name));
1186 strncat (Actual_Output_Name,opts.Output_Numbered_Name, sizeof (Actual_Output_Name));
1188 Debug_Info("P='%s',O='%s',A='%s',N='%s'\n",opts.Output_Path,
1189 opts.Output_Numbered_Name, Actual_Output_Name,opts.Output_Numbered_Name);
1194 /*****************************************************************************
1196 * FUNCTION
1198 * open_output_file
1200 * INPUT
1202 * OUTPUT
1204 * RETURNS
1206 * AUTHOR
1208 * POV-Ray Team
1210 * DESCRIPTION
1212 * Open file and read in previous image if continued trace is on.
1214 * GOTCHA : This saves a POINTER to the file name, so the file
1215 * name must exist over the entire life/use of the file
1217 * CHANGES
1221 ******************************************************************************/
1223 static void open_output_file()
1225 int Buffer_Size;
1227 if (opts.Options & DISKWRITE)
1229 Stage = STAGE_FILE_INIT;
1231 if (opts.Options & BUFFERED_OUTPUT)
1233 Buffer_Size=opts.File_Buffer_Size;
1235 else
1237 Buffer_Size=0;
1240 if (opts.Options & CONTINUE_TRACE)
1242 Stage = STAGE_CONTINUING;
1244 if (Open_File(Output_File_Handle, Actual_Output_Name,
1245 &Frame.Screen_Width, &Frame.Screen_Height, Buffer_Size,
1246 READ_MODE) != 1)
1248 Close_File(Output_File_Handle);
1250 Warning (0.0,"Error opening continue trace output file.\n");
1252 Warning (0.0,"Opening new output file %s.\n",Actual_Output_Name);
1254 /* Turn off continue trace */
1256 opts.Options &= ~CONTINUE_TRACE;
1258 if (Open_File(Output_File_Handle, Actual_Output_Name,
1259 &Frame.Screen_Width, &Frame.Screen_Height, Buffer_Size,
1260 WRITE_MODE) != 1)
1262 Error ("Error opening output file.");
1266 else
1268 if (Open_File(Output_File_Handle, Actual_Output_Name,
1269 &Frame.Screen_Width, &Frame.Screen_Height, Buffer_Size,
1270 WRITE_MODE) != 1)
1272 Error ("Error opening output file.");
1279 /*****************************************************************************
1281 * FUNCTION
1283 * init_vars
1285 * INPUT
1287 * OUTPUT
1289 * RETURNS
1291 * AUTHOR
1293 * POV-Ray Team
1295 * DESCRIPTION
1297 * Initialize all global variables.
1299 * CHANGES
1303 ******************************************************************************/
1305 static void init_vars()
1307 Stage=STAGE_INIT;
1308 opts.Abort_Test_Counter = Abort_Test_Every ;
1309 Abort_Test_Every = 1;
1310 opts.AntialiasDepth = 3;
1311 opts.Antialias_Threshold = 0.3;
1312 opts.BBox_Threshold = 25;
1313 Color_Bits = 8;
1314 opts.DisplayFormat = '0';
1315 Display_Started = FALSE;
1316 opts.File_Buffer_Size = 0;
1317 opts.First_Column = 0;
1318 opts.First_Column_Percent = 0.0;
1319 opts.First_Line = 0;
1320 opts.First_Line_Percent = 0.0;
1321 Frame.Screen_Height = 100;
1322 Frame.Screen_Width = 100;
1323 Root_Object = NULL;
1324 free_istack = NULL;
1325 opts.JitterScale = 1.0;
1326 opts.Language_Version = 3.1;
1327 opts.Last_Column = -1;
1328 opts.Last_Column_Percent = 1.0;
1329 opts.Last_Line = -1;
1330 opts.Last_Line_Percent = 1.0;
1331 opts.PreviewGridSize_Start = 1;
1332 opts.PreviewGridSize_End = 1;
1333 opts.Library_Paths[0] = NULL;
1334 opts.Library_Path_Index = 0;
1335 Max_Intersections = 64; /*128*/
1336 Number_Of_Files = 0;
1337 Number_of_istacks = 0;
1339 opts.Options = USE_VISTA_BUFFER + USE_LIGHT_BUFFER + JITTER +
1340 DISKWRITE + REMOVE_BOUNDS;
1341 opts.OutputFormat = DEFAULT_OUTPUT_FORMAT;
1342 opts.OutputQuality = 8;
1343 Output_File_Handle = NULL;
1344 opts.Output_Numbered_Name[0]='\0';
1345 opts.Output_File_Name[0]='\0';
1346 opts.Output_Path[0]='\0';
1347 opts.PaletteOption = '3';
1348 opts.Quality = 9;
1349 opts.Quality_Flags = QUALITY_9;
1350 opts.DisplayGamma = DEFAULT_DISPLAY_GAMMA;
1353 * If DisplayGamma == 2.2, then GammaFactor == .45, which is what we want.
1355 opts.GammaFactor = DEFAULT_ASSUMED_GAMMA/opts.DisplayGamma;
1357 opts.FrameSeq.FrameType = FT_SINGLE_FRAME;
1358 opts.FrameSeq.Clock_Value = 0.0;
1359 opts.FrameSeq.InitialFrame = 1;
1360 opts.FrameSeq.InitialClock = 0.0;
1361 opts.FrameSeq.FinalFrame = INT_VALUE_UNSET;
1362 opts.FrameSeq.FrameNumWidth = 0;
1363 opts.FrameSeq.FinalClock = 1.0;
1364 opts.FrameSeq.SubsetStartFrame = INT_VALUE_UNSET;
1365 opts.FrameSeq.SubsetStartPercent = DBL_VALUE_UNSET;
1366 opts.FrameSeq.SubsetEndFrame = INT_VALUE_UNSET;
1367 opts.FrameSeq.SubsetEndPercent = DBL_VALUE_UNSET;
1368 opts.FrameSeq.Field_Render_Flag = FALSE;
1369 opts.FrameSeq.Odd_Field_Flag = FALSE;
1371 opts.Radiosity_Brightness = 3.3;
1372 opts.Radiosity_Count = 100;
1373 opts.Radiosity_Dist_Max = 0.; /* default calculated in Radiosity_Initialize */
1374 opts.Radiosity_Error_Bound = .4;
1375 opts.Radiosity_Gray = .5; /* degree to which gathered light is grayed */
1376 opts.Radiosity_Low_Error_Factor = .8;
1377 opts.Radiosity_Min_Reuse = .015;
1378 opts.Radiosity_Nearest_Count = 6;
1379 opts.Radiosity_Recursion_Limit = 1;
1380 opts.Radiosity_Quality = 6; /* Q-flag value for light gathering */
1381 opts.Radiosity_File_ReadOnContinue = 1;
1382 opts.Radiosity_File_SaveWhileRendering = 1;
1383 opts.Radiosity_File_AlwaysReadAtStart = 0;
1384 opts.Radiosity_File_KeepOnAbort = 1;
1385 opts.Radiosity_File_KeepAlways = 0;
1388 init_statistics(stats);
1389 init_statistics(totalstats);
1391 strcpy (opts.Input_File_Name, "OBJECT.POV");
1392 opts.Scene_Name[0]='\0';
1393 opts.Ini_Output_File_Name[0]='\0';
1394 opts.Use_Slabs=TRUE;
1395 Num_Echo_Lines = 5; /* May make user setable later - CEY*/
1396 Echo_Line_Length = 180; /* May make user setable later - CEY*/
1398 closed_flag = FALSE;
1399 Stop_Flag = FALSE;
1401 trender = trender_total = 0.0;
1402 tparse = tparse_total = 0.0;
1404 histogram_grid = NULL ;
1405 opts.histogram_on = FALSE ;
1406 opts.histogram_type = NONE ;
1407 opts.Histogram_File_Name[0] = '\0';
1408 Histogram_File_Handle = NULL ;
1410 * Note that late initialization of the histogram_x and histogram_y
1411 * variables is done in fix_up_rendering_window, if they aren't specified
1412 * on the command line. This is because they are based on the image
1413 * dimensions, and we can't be certain that we have this info at the
1414 * time we parse the histogram options in optin.c. [AED]
1416 opts.histogram_x = opts.histogram_y = 0 ;
1417 max_histogram_value = 0 ;
1419 opts.Tracing_Method = 1;
1420 Experimental_Flag = 0;
1421 Make_Pigment_Entries();
1425 /*****************************************************************************
1427 * FUNCTION
1429 * init_statistics
1431 * INPUT
1433 * OUTPUT
1435 * RETURNS
1437 * AUTHOR
1439 * POV-Ray Team
1441 * DESCRIPTION
1443 * Initialize statistics to 0
1445 * CHANGES
1449 ******************************************************************************/
1451 static void init_statistics(COUNTER *pstats)
1453 int i;
1455 for(i=0; i<MaxStat; i++)
1456 Init_Counter(pstats[i]);
1459 /*****************************************************************************
1461 * FUNCTION
1463 * sum_statistics
1465 * INPUT
1467 * OUTPUT
1469 * RETURNS
1471 * AUTHOR
1473 * POV-Ray Team
1475 * DESCRIPTION
1477 * Add current statistics to total statistics
1479 * CHANGES
1483 ******************************************************************************/
1485 static void sum_statistics(COUNTER *ptotalstats, COUNTER *pstats)
1487 int i;
1488 COUNTER tmp;
1490 for(i=0; i<MaxStat; i++)
1492 Add_Counter(tmp,pstats[i],ptotalstats[i]);
1493 ptotalstats[i]=tmp;
1498 /*****************************************************************************
1500 * FUNCTION
1502 * variable_store
1504 * INPUT
1506 * flag - flag telling wether to store or restore variables.
1508 * OUTPUT
1510 * RETURNS
1512 * AUTHOR
1514 * Dieter Bayer
1516 * DESCRIPTION
1518 * Store or restore variables whose value has to be the same for all
1519 * frames of an animation and who are changed during every frame.
1521 * CHANGES
1523 * May 1995 : Creation.
1525 ******************************************************************************/
1527 static void variable_store(int Flag)
1529 static int STORE_First_Line;
1531 switch (Flag)
1533 case STORE:
1535 STORE_First_Line = opts.First_Line;
1537 break;
1539 case RESTORE:
1541 opts.First_Line = STORE_First_Line;
1543 break;
1545 default:
1547 Error("Unknown flag in variable_store().\n");
1551 /*****************************************************************************
1553 * FUNCTION
1555 * destroy_libraries
1557 * INPUT
1559 * OUTPUT
1561 * RETURNS
1563 * AUTHOR
1565 * POV-Ray Team
1567 * DESCRIPTION
1569 * Free library path memory.
1571 * CHANGES
1575 ******************************************************************************/
1577 static void destroy_libraries()
1579 int i;
1581 for (i = 0; i < opts.Library_Path_Index; i++)
1583 POV_FREE(opts.Library_Paths[i]);
1585 opts.Library_Paths[i] = NULL;
1591 /*****************************************************************************
1593 * FUNCTION
1595 * close_all
1597 * INPUT
1599 * OUTPUT
1601 * RETURNS
1603 * AUTHOR
1605 * POV-Ray Team
1607 * DESCRIPTION
1609 * Close all the stuff that has been opened and free all allocated memory.
1611 * CHANGES
1615 ******************************************************************************/
1617 void close_all()
1619 /* Only close things once */
1621 if (closed_flag)
1623 return;
1626 if (Output_File_Handle != NULL)
1628 Close_File(Output_File_Handle);
1630 POV_FREE(Output_File_Handle);
1632 Output_File_Handle = NULL;
1635 destroy_shellouts();
1636 destroy_libraries();
1637 Destroy_Text_Streams();
1638 Free_Noise_Tables();
1639 Terminate_Renderer();
1640 Destroy_Bounding_Slabs();
1641 Destroy_Blob_Queue();
1642 Destroy_Vista_Buffer();
1643 Destroy_Light_Buffers();
1644 Destroy_Random_Generators();
1645 Deinitialize_Radiosity_Code();
1646 Free_Iteration_Stack();
1647 destroy_histogram();
1648 Deinitialize_Atmosphere_Code();
1649 Deinitialize_BBox_Code();
1650 Deinitialize_Lighting_Code();
1651 Deinitialize_Mesh_Code();
1652 Deinitialize_VLBuffer_Code();
1653 Destroy_Frame();
1654 Destroy_IStacks();
1655 FreeFontInfo();
1657 if ((opts.Options & DISPLAY) && Display_Started)
1659 POV_DISPLAY_CLOSE
1662 closed_flag = TRUE;
1667 /*****************************************************************************
1669 * FUNCTION
1671 * POV_Std_Split_Time
1673 * INPUT
1675 * OUTPUT
1677 * RETURNS
1679 * AUTHOR
1681 * POV-Ray Team
1683 * DESCRIPTION
1685 * Split time into hours, minutes and seconds.
1687 * CHANGES
1691 ******************************************************************************/
1693 void POV_Std_Split_Time(DBL time_dif, unsigned long *hrs, unsigned long *mins, DBL *secs)
1695 *hrs = (unsigned long)(time_dif / 3600.0);
1697 *mins = (unsigned long)((time_dif - (DBL)(*hrs * 3600)) / 60.0);
1699 *secs = time_dif - (DBL)(*hrs * 3600 + *mins * 60);
1705 /*****************************************************************************
1707 * FUNCTION
1709 * pov_stricmp
1711 * INPUT
1713 * OUTPUT
1715 * RETURNS
1717 * AUTHOR
1719 * POV-Ray Team
1721 * DESCRIPTION
1723 * Since the stricmp function isn't available on all systems, we've
1724 * provided a simplified version of it here.
1726 * CHANGES
1730 ******************************************************************************/
1732 int pov_stricmp (char *s1, char *s2)
1734 char c1, c2;
1736 while ((*s1 != '\0') && (*s2 != '\0'))
1738 c1 = *s1++;
1739 c2 = *s2++;
1741 c1 = (char)toupper(c1);
1742 c2 = (char)toupper(c2);
1744 if (c1 < c2)
1746 return(-1);
1749 if (c1 > c2)
1751 return(1);
1755 if (*s1 == '\0')
1757 if (*s2 == '\0')
1759 return(0);
1761 else
1763 return(-1);
1766 else
1768 return(1);
1773 /*****************************************************************************
1775 * FUNCTION
1777 * Locate_File
1779 * INPUT
1781 * OUTPUT
1783 * RETURNS
1785 * AUTHOR
1787 * POV-Ray Team
1789 * DESCRIPTION
1791 * Find a file in the search path.
1793 * CHANGES
1795 * Apr 1996: Don't add trailing FILENAME_SEPARATOR if we are immediately
1796 * following DRIVE_SEPARATOR because of Amiga probs. [AED]
1798 ******************************************************************************/
1800 FILE *Locate_File (char *filename, char *mode, char *ext1, char *ext2, char *buffer, int err_flag)
1802 int i,l1,l2;
1803 char pathname[FILE_NAME_LENGTH];
1804 char file0[FILE_NAME_LENGTH];
1805 char file1[FILE_NAME_LENGTH];
1806 char file2[FILE_NAME_LENGTH];
1807 FILE *f;
1809 if (Has_Extension(filename))
1811 l1=l2=0;
1813 else
1815 if ((l1 = strlen(ext1)) > 0)
1817 strcpy(file1, filename);
1818 strcat(file1, ext1);
1821 if ((l2 = strlen(ext2)) > 0)
1823 strcpy(file2, filename);
1824 strcat(file2, ext2);
1828 /* Check the current directory first. */
1829 if (l1)
1831 if ((f = fopen(file1, mode)) != NULL)
1833 POV_GET_FULL_PATH(f,file1,buffer);
1834 return(f);
1837 if (l2)
1839 if ((f = fopen(file2, mode)) != NULL)
1841 POV_GET_FULL_PATH(f,file2,buffer);
1842 return(f);
1845 if ((f = fopen(filename, mode)) != NULL)
1847 POV_GET_FULL_PATH(f,filename,buffer);
1848 return(f);
1851 for (i = 0; i < opts.Library_Path_Index; i++)
1853 strcpy(file0, opts.Library_Paths[i]);
1854 file0[strlen(file0)+1] = '\0';
1855 if (file0[strlen(file0) - 1] != DRIVE_SEPARATOR)
1856 file0[strlen(file0)] = FILENAME_SEPARATOR;
1858 if (l1)
1860 strcpy(pathname, file0);
1861 strcat(pathname, file1);
1862 if ((f = fopen(pathname, mode)) != NULL)
1864 POV_GET_FULL_PATH(f,pathname,buffer);
1865 return(f);
1869 if (l2)
1871 strcpy(pathname, file0);
1872 strcat(pathname, file2);
1873 if ((f = fopen(pathname, mode)) != NULL)
1875 POV_GET_FULL_PATH(f,pathname,buffer);
1876 return(f);
1879 strcpy(pathname, file0);
1880 strcat(pathname, filename);
1881 if ((f = fopen(pathname, mode)) != NULL)
1883 POV_GET_FULL_PATH(f,pathname,buffer);
1884 return(f);
1888 if (err_flag)
1890 if (l1)
1892 Error_Line("Could not find file '%s%s'\n",filename,ext1);
1894 else
1896 Error_Line("Could not find file '%s'\n",filename);
1900 return(NULL);
1903 /*****************************************************************************
1905 * FUNCTION
1907 * INPUT
1909 * OUTPUT
1911 * RETURNS
1913 * AUTHOR
1915 * DESCRIPTION
1917 * CHANGES
1919 ******************************************************************************/
1921 static int Has_Extension (char *name)
1923 char *p;
1925 if (name!=NULL)
1927 p=strrchr(name, '.');
1929 if (p!=NULL)
1931 if ((strlen(name)-(p-name))<=4)
1933 return (TRUE);
1937 return (FALSE);
1941 /*****************************************************************************
1943 * FUNCTION
1945 * pov_shellout
1947 * INPUT
1949 * template_command - the template command string to execute
1951 * OUTPUT
1953 * RETURNS
1955 * AUTHOR
1957 * POV-Ray Team
1959 * DESCRIPTION
1961 * Execute the command line described by the string being passed in
1963 * CHANGES
1967 ******************************************************************************/
1969 SHELLRET pov_shellout (SHELLTYPE Type)
1971 char real_command[POV_MAX_CMD_LENGTH];
1972 int i, j, l = 0;
1973 int length;
1974 SHELLRET Return_Code;
1975 char *s = NULL;
1976 char *template_command;
1979 if ( opts.Shellouts == NULL ) return(IGNORE_RET);
1981 template_command=opts.Shellouts[Type].Command;
1983 if ((length = strlen(template_command)) == 0)
1985 return(IGNORE_RET);
1988 switch(Type)
1990 case PRE_SCENE_SHL: s="pre-scene"; break;
1991 case PRE_FRAME_SHL: s="pre-frame"; break;
1992 case POST_FRAME_SHL: s="post-frame"; break;
1993 case POST_SCENE_SHL: s="post-scene"; break;
1994 case USER_ABORT_SHL: s="user about"; break;
1995 case FATAL_SHL: s="fatal error"; break;
1996 case MAX_SHL: /* To remove warnings*/ break;
1999 Status_Info("\nPerforming %s shell-out command",s);
2001 /* First, find the real command */
2003 for (i = 0, j = 0; i < length; )
2005 if (template_command[i] == '%')
2007 switch (toupper(template_command[i+1]))
2009 case 'O':
2011 strncpy(&real_command[j], opts.Output_Numbered_Name,
2012 (unsigned)(l=strlen(opts.Output_Numbered_Name)));
2014 break;
2016 case 'P':
2018 strncpy(&real_command[j], opts.Output_Path,(unsigned)(l=strlen(opts.Output_Path)));
2020 break;
2022 case 'S':
2024 strncpy(&real_command[j], opts.Scene_Name, (unsigned)(l=strlen(opts.Scene_Name)));
2026 break;
2028 case 'N':
2030 sprintf(&real_command[j],"%d",opts.FrameSeq.FrameNumber);
2031 l = strlen(&real_command[j]);
2033 break;
2035 case 'K':
2037 sprintf(&real_command[j],"%f",opts.FrameSeq.Clock_Value);
2038 l = strlen(&real_command[j]);
2040 break;
2042 case 'H':
2044 sprintf(&real_command[j],"%d",Frame.Screen_Height);
2045 l = strlen(&real_command[j]);
2047 break;
2049 case 'W':
2051 sprintf(&real_command[j],"%d",Frame.Screen_Width);
2052 l = strlen(&real_command[j]);
2054 break;
2056 case '%':
2058 real_command[j]='%';
2060 l=1;
2062 break;
2065 j+=l;
2067 i+=2; /* we used 2 characters of template_command */
2069 else
2071 real_command[j++]=template_command[i++];
2075 real_command[j]='\0';
2077 Return_Code=(POV_SHELLOUT_CAST)POV_SYSTEM(real_command);
2079 if (opts.Shellouts[Type].Inverse)
2081 Return_Code=(POV_SHELLOUT_CAST)(!((int)Return_Code));
2084 if (Return_Code)
2086 if (Type < USER_ABORT_SHL)
2088 switch(opts.Shellouts[Type].Ret)
2090 case FATAL_RET:
2092 Error("Fatal error returned from shellout command.");
2094 break;
2096 case USER_RET:
2098 Check_User_Abort(TRUE); /* the TRUE forces user abort */
2100 break;
2102 case QUIT_RET:
2104 Terminate_POV(0);
2106 break;
2108 case IGNORE_RET:
2109 case SKIP_ONCE_RET:
2110 case ALL_SKIP_RET: /* Added to remove warnings */
2111 break;
2115 return(opts.Shellouts[Type].Ret);
2118 return(IGNORE_RET);
2121 /*****************************************************************************
2123 * FUNCTION
2125 * INPUT
2127 * OUTPUT
2129 * RETURNS
2131 * AUTHOR
2133 * DESCRIPTION
2135 * CHANGES
2137 ******************************************************************************/
2139 static void init_shellouts()
2141 int i;
2143 opts.Shellouts=(SHELLDATA *)POV_MALLOC(sizeof(SHELLDATA)*MAX_SHL,"shellout data");
2145 for (i=0; i < MAX_SHL; i++)
2147 opts.Shellouts[i].Ret=IGNORE_RET;
2148 opts.Shellouts[i].Inverse=FALSE;
2149 opts.Shellouts[i].Command[0]='\0';
2153 /*****************************************************************************
2155 * FUNCTION
2157 * INPUT
2159 * OUTPUT
2161 * RETURNS
2163 * AUTHOR
2165 * DESCRIPTION
2167 * CHANGES
2169 ******************************************************************************/
2171 static void destroy_shellouts()
2173 if (opts.Shellouts != NULL)
2175 POV_FREE(opts.Shellouts);
2178 opts.Shellouts=NULL;
2182 /*****************************************************************************
2184 * FUNCTION
2186 * closest_power_of_2
2188 * INPUT
2190 * theNumber - the value to determine closest power of 2 for.
2192 * OUTPUT
2194 * RETURNS
2196 * The closest power of two is returned, or zero if the
2197 * argument is less than or equal to zero.
2199 * AUTHOR
2201 * Eduard Schwan
2203 * DESCRIPTION
2205 * Decription: Find the highest positive power of 2 that is
2206 * less than or equal to the number passed.
2208 * Input Output
2209 * ----- ------
2210 * 0 0
2211 * 1 1
2212 * 2 2
2213 * 3 2
2214 * 8 8
2215 * 9 8
2217 * CHANGES
2219 * Aug 1994 : Created by Eduard.
2221 ******************************************************************************/
2223 static unsigned closest_power_of_2(unsigned theNumber)
2225 int PowerOf2Counter;
2227 /* do not handle zero or negative numbers for now */
2229 if (theNumber <= 0)
2231 return(0);
2234 /* count the number in question down as we count up a power of 2 */
2236 PowerOf2Counter = 1;
2238 while (theNumber > 1)
2240 /* move our power of 2 counter bit up... */
2242 PowerOf2Counter <<= 1;
2244 /* and reduce our test number by a factor of 2 two */
2246 theNumber >>= 1;
2249 return(PowerOf2Counter);
2252 /*****************************************************************************
2254 * FUNCTION
2256 * pre_init_povray
2258 * INPUT -- none
2260 * OUTPUT
2262 * RETURNS
2264 * AUTHOR -- CEY
2266 * DESCRIPTION
2268 * This routine does essential initialization that is required before any
2269 * POV_MALLOC-like routines may be called and before any text streams
2270 * may be used.
2272 * If you are using alt_main and need access to any part of the generic code
2273 * before alt_main is called, you MUST call this routine first! Also note
2274 * that it is safe to call it twice. If you don't call it, alt_main will.
2275 * It won't hurt if you both do it.
2277 * NOTE: Terminate_POV de-initializes these features. Therefore you may
2278 * need to call it again between sucessive calls to alt_main. If you call
2279 * pre_init_povray but for some reason you abort and don't call alt_main,
2280 * then you should call Terminate_POV to clean up.
2282 * CHANGES
2283 * Nov 1995 : Created by CEY
2285 ******************************************************************************/
2287 void pre_init_povray()
2289 if (pre_init_flag==1234)
2291 return;
2294 /* Initialize memory. */
2295 POV_MEM_INIT();
2297 /* Initialize streams. In USERIO.C */
2298 Init_Text_Streams();
2300 init_shellouts();
2302 pre_init_tokenizer ();
2304 pre_init_flag=1234;
2307 void POV_Split_Path(char *s,char *p,char *f)
2309 char *l;
2311 strcpy(p,s);
2313 if ((l=strrchr(p,FILENAME_SEPARATOR))==NULL)
2315 if ((l=strrchr(p,DRIVE_SEPARATOR))==NULL)
2317 strcpy(f,s);
2318 p[0]='\0';
2319 return;
2323 l++;
2324 strcpy(f,l);
2325 *l='\0';