void Build_Light_Buffers() { int Axis; PROJECT Project; LIGHT_SOURCE *Light; int proj_thru; PROJECT proj_proj; if (!(opts.Quality_Flags & Q_SHADOW) || (!opts.Use_Slabs)) { opts.Options &= ~USE_LIGHT_BUFFER; } if (opts.Options & USE_LIGHT_BUFFER) { Send_Progress("Creating light buffers", PROGRESS_CREATE_LIGHT_BUFFERS); /*YS 29 april 2000 bugfix*/ BuffersInit=true; /*YS 29 april 2000 bugfix*/ /* Build the light buffer for all point(!) light sources */ for (Light = Frame.Light_Sources; Light != NULL; Light = Light->Next_Light_Source) { if ((!Light->Area_Light) && (Light->Light_Type!=FILL_LIGHT_SOURCE) && !(Light->Parallel)) { Send_ProgressUpdate(PROGRESS_CREATE_LIGHT_BUFFERS); /* Project bounding slabs on all six sides */ for (Axis = 0; Axis < 6; Axis++) { if ( Light->Projected_Through_Object ) { proj_thru=1; project_object (&proj_proj, Light->Projected_Through_Object, Axis, Light->Center, 0, NULL); } else { proj_thru=0; } Light->Light_Buffer[Axis] = NULL; if ( !proj_thru || ((proj_proj.x1 <= proj_proj.x2) && (proj_proj.y1 <= proj_proj.y2))) { project_bounding_slab(Axis, Light->Center, &Project, &Light->Light_Buffer[Axis], Root_Object, proj_thru, &proj_proj); } } } } } }
SHELLRET pov_shellout (SHELLTYPE Type) { char real_command[POV_MAX_CMD_LENGTH]; int i, j, l = 0; int length; SHELLRET Return_Code; char *s = NULL; char *template_command; if ( opts.Shellouts == NULL ) return(IGNORE_RET); template_command=opts.Shellouts[Type].Command; if ((length = strlen(template_command)) == 0) { return(IGNORE_RET); } switch(Type) { case PRE_SCENE_SHL: s="pre-scene"; break; case PRE_FRAME_SHL: s="pre-frame"; break; case POST_FRAME_SHL: s="post-frame"; break; case POST_SCENE_SHL: s="post-scene"; break; case USER_ABORT_SHL: s="user about"; break; case FATAL_SHL: s="fatal error"; break; case MAX_SHL: /* To remove warnings*/ break; } Send_Progress(pov_tsprintf("Performing %s shell-out command", s), PROGRESS_PERFORMING_SHELLOUT_COMMAND); /* First, find the real command */ for (i = 0, j = 0; i < length; ) { if (template_command[i] == '%') { switch (toupper(template_command[i+1])) { case 'O': strncpy(&real_command[j], opts.Output_Numbered_Name, (unsigned)(l=strlen(opts.Output_Numbered_Name))); break; case 'P': strncpy(&real_command[j], opts.Output_Path,(unsigned)(l=strlen(opts.Output_Path))); break; case 'S': strncpy(&real_command[j], opts.Scene_Name, (unsigned)(l=strlen(opts.Scene_Name))); break; case 'N': sprintf(&real_command[j],"%d",opts.FrameSeq.FrameNumber); l = strlen(&real_command[j]); break; case 'K': sprintf(&real_command[j],"%f",opts.FrameSeq.Clock_Value); l = strlen(&real_command[j]); break; case 'H': sprintf(&real_command[j],"%d",Frame.Screen_Height); l = strlen(&real_command[j]); break; case 'W': sprintf(&real_command[j],"%d",Frame.Screen_Width); l = strlen(&real_command[j]); break; case '%': real_command[j]='%'; l=1; break; } j+=l; i+=2; /* we used 2 characters of template_command */ } else { real_command[j++]=template_command[i++]; } } real_command[j]='\0'; Return_Code=(POV_SHELLOUT_CAST)POV_SYSTEM(real_command); if (opts.Shellouts[Type].Inverse) { Return_Code=(POV_SHELLOUT_CAST)(!((int)Return_Code)); } if (Return_Code) { if (Type < USER_ABORT_SHL) { switch(opts.Shellouts[Type].Ret) { case FATAL_RET: Error("Fatal error returned from shellout command."); break; case USER_RET: Check_User_Abort(true); /* the true forces user abort */ break; case QUIT_RET: povray_exit(0); break; case IGNORE_RET: case SKIP_ONCE_RET: case ALL_SKIP_RET: /* Added to remove warnings */ break; } } return(opts.Shellouts[Type].Ret); } return(IGNORE_RET); }
/* Released all unfree'd memory from all pools */ void mem_release_all() { #if defined(MEM_RECLAIM) OStream *f = NULL; MEMNODE *p, *tmp; size_t totsize; Send_Progress("Reclaiming memory", PROGRESS_RECLAIMING_MEMORY); p = memlist; totsize = 0; #if defined(MEM_TRACE) if (p != NULL) f = New_OStream(MEM_LOG_FNAME, POV_File_Data_LOG, true); #endif while (p != NULL) { #if defined(MEM_TRACE) #if defined(MEM_TAG) if (!mem_check_tag(p)) Debug_Info("mem_release_all(): Memory pointer corrupt!\n"); #endif /* MEM_TAG */ totsize += (p->size - NODESIZE - (MEM_GUARD_SIZE * 2)); if (!leak_msg) { Debug_Info("Memory leakage detected, see file '%s' for list\n",MEM_LOG_FNAME); leak_msg = true; } if (f != NULL) f->printf("File:%13s Line:%4d Size:%lu\n", p->file, p->line, (unsigned long)(p->size - NODESIZE - (MEM_GUARD_SIZE * 2))); #endif #if defined(MEM_STATS) /* This is after we have printed stats, and this may slow us down a little, */ /* so we may want to simply re-initialize the mem-stats at the end of this loop. */ mem_stats_free(p->size); #endif tmp = p; p = p->next; remove_node(tmp); FREE(tmp); } if (f != NULL) delete f; if (totsize > 0) Debug_Info("\n%lu bytes reclaimed\n", totsize); poolno = 0; memlist = NULL; #endif #if defined(MEM_STATS) /* reinitialize the stats structure for next time through */ mem_stats_init(); #endif }
void FrameRender() { // Store start time for parse. START_TIME Current_Token_Count = 0; tparse_frame = tphoton_frame = trender_frame = 0.0; // Parse the scene file. Send_Progress("Parsing", PROGRESS_PARSING); opts.Do_Stats = false; // Set up noise-tables Initialize_Noise(); // Set up function VM POVFPU_Init(); // Init module specific stuff. Initialize_Mesh_Code(); Parse(); opts.Do_Stats = true; if (opts.Radiosity_Enabled) Experimental_Flag |= EF_RADIOS; if (Experimental_Flag) { char str[512] = "" ; if (Experimental_Flag & EF_SPLINE) strcat (str, str [0] ? ", spline" : "spline") ; if (Experimental_Flag & EF_RADIOS) strcat (str, str [0] ? ", radiosity" : "radiosity") ; if (Experimental_Flag & EF_SLOPEM) strcat (str, str [0] ? ", slope pattern" : "slope pattern") ; if (Experimental_Flag & EF_ISOFN) strcat (str, str [0] ? ", function '.hf'" : "function '.hf'") ; if (Experimental_Flag & EF_TIFF) strcat (str, str [0] ? ", TIFF image support" : "TIFF image support") ; Warning(0, "This rendering uses the following experimental feature(s): %s.\n" "The design and implementation of these features is likely to change in future versions\n" "of POV-Ray. Full backward compatibility with the current implementation is NOT guaranteed.", str); } Experimental_Flag = 0; // Switch off standard anti-aliasing. if((Frame.Camera->Aperture != 0.0) && (Frame.Camera->Blur_Samples > 0)) { opts.Options &= ~ANTIALIAS; Warning(0, "Focal blur is used. Standard antialiasing is switched off."); } // Create the bounding box hierarchy. Stage = STAGE_SLAB_BUILDING; if(opts.Use_Slabs) Send_Progress("Creating bounding slabs", PROGRESS_CREATING_BOUNDING_SLABS); // Init module specific stuff. Initialize_Atmosphere_Code(); Initialize_BBox_Code(); Initialize_Lighting_Code(); Initialize_VLBuffer_Code(); Initialize_Radiosity_Code(); // Always call this to print number of objects. Build_Bounding_Slabs(&Root_Object); // Create the vista buffer. Build_Vista_Buffer(); // Create the light buffers. Build_Light_Buffers(); // Save variable values. variable_store(STORE); // Get the parsing time. STOP_TIME tparse = TIME_ELAPSED Send_ProgressUpdate(PROGRESS_PARSING, 0); // Output parsing statistics. Send_ParseStatistics(); if (photonOptions.photonsEnabled) { /* Store start time for photons. */ START_TIME /* now backwards-trace the scene and build the photon maps */ InitBacktraceEverything(); BuildPhotonMaps(); /* Get the photon-shooting time. */ STOP_TIME tphoton = TIME_ELAPSED /* Get total parsing time. */ tphoton_total += tphoton; tphoton_frame = tphoton; tphoton = 0; } /* Store start time for the rest of parsing. */ START_TIME Stage = STAGE_INIT; // Open output file and if we are continuing an interrupted trace, // read in the previous file settings and any data there. This has to // be done before any image-size related allocations, since the settings // in a resumed file take precedence over that specified by the user. [AED] open_output_file(); // Start the display. if(opts.Options & DISPLAY) { Send_Progress("Displaying", PROGRESS_DISPLAYING); Display_Started = POV_DISPLAY_INIT(opts.Preview_RefCon, Frame.Screen_Width, Frame.Screen_Height); // Display vista tree. Draw_Vista_Buffer(); } else { Display_Started = false; } // Get things ready for ray tracing (misc init, mem alloc) Initialize_Renderer(); // This had to be taken out of open_output_file() because we don't have // the final image size until the output file has been opened, so we can't // initialize the display until we know this, which in turn means we can't // read the rendered part before the display is initialized. [AED] if((opts.Options & DISKWRITE) && (opts.Options & CONTINUE_TRACE)) { Read_Rendered_Part(Actual_Output_Name); if (opts.Last_Line > Frame.Screen_Height) opts.Last_Line = Frame.Screen_Height; if (opts.Last_Column > Frame.Screen_Width) opts.Last_Column = Frame.Screen_Width; } // Get the rest of the parsing time. STOP_TIME tparse += TIME_ELAPSED // Store start time for trace. START_TIME // Get total parsing time. tparse_total += tparse; tparse_frame = tparse; tparse = 0; // Start tracing. Stage = STAGE_RENDERING; POV_PRE_RENDER Send_Progress("Rendering", PROGRESS_RENDERING); // Macro for setting up any special FP options CONFIG_MATH // Ok, go for it - trace the picture. // If radiosity preview has been done, we are continuing a trace, so it // is important NOT to do the preview, even if the user requests it, as it // will cause discontinuities in radiosity shading by (probably) calculating // a few more radiosity values. // Note that radiosity REQUIRES a mosaic preview prior to main scan if ( opts.Radiosity_Enabled && !opts.Radiosity_Preview_Done) Start_Tracing_Radiosity_Preview(opts.PreviewGridSize_Start, opts.PreviewGridSize_End); else if((opts.Options & PREVIEW) && (opts.Options & DISPLAY)) Start_Tracing_Mosaic_Preview(opts.PreviewGridSize_Start, opts.PreviewGridSize_End); switch(opts.Tracing_Method) { case 2: Start_Adaptive_Tracing(); break; case 1: default: Start_Non_Adaptive_Tracing(); } // Record time so well spent before file close so it can be in comments STOP_TIME trender = TIME_ELAPSED // shutdown (freeing memory) does not get included in the time! // Get total render time. trender_total += trender; trender_frame = trender; trender = 0; // Close out our file if(Output_File != NULL) { delete Output_File; Output_File = NULL; } // For all those who never rtfm [trf] if((Highest_Trace_Level >= Max_Trace_Level) && (Had_Max_Trace_Level == false)) PossibleError("Maximum trace level reached! If your scene contains black spots\nread more about the max_trace_level setting in the documentation!"); Stage = STAGE_SHUTDOWN; POV_PRE_SHUTDOWN // DESTROY lots of stuff /* NK phmap */ FreeBacktraceEverything(); Deinitialize_Atmosphere_Code(); Deinitialize_BBox_Code(); Deinitialize_Lighting_Code(); Deinitialize_Mesh_Code(); Deinitialize_VLBuffer_Code(); Deinitialize_Radiosity_Code(); Destroy_Light_Buffers(); Destroy_Vista_Buffer(); Destroy_Bounding_Slabs(); Destroy_Frame(); Terminate_Renderer(); FreeFontInfo(); Free_Iteration_Stack(); Free_Noise_Tables(); POVFPU_Terminate(); POV_POST_SHUTDOWN if((opts.Options & DISPLAY) && Display_Started) { POV_DISPLAY_FINISHED(opts.Preview_RefCon); POV_DISPLAY_CLOSE(opts.Preview_RefCon); Display_Started = false; } if(opts.histogram_on) write_histogram(opts.Histogram_File_Name); Send_Progress("Done Tracing", PROGRESS_DONE_TRACING); // Print stats ... Send_RenderStatistics(); if(opts.FrameSeq.FrameType == FT_MULTIPLE_FRAME) { // Add them up sum_statistics(totalstats, stats); // ... and then clear them for the next frame init_statistics(stats); } // Restore variable values. variable_store(RESTORE); }
void FrameLoop() { int Diff_Frame; DBL Diff_Clock; SHELLRET Pre_Scene_Result, Frame_Result; Diff_Clock = opts.FrameSeq.FinalClock - opts.FrameSeq.InitialClock; if(opts.Options & CYCLIC_ANIMATION) Diff_Frame = opts.FrameSeq.FinalFrame - opts.FrameSeq.InitialFrame + 1; else Diff_Frame = opts.FrameSeq.FinalFrame - opts.FrameSeq.InitialFrame; Clock_Delta = ((Diff_Frame == 0) ? 0 : Diff_Clock/Diff_Frame); // Execute the first shell-out command Pre_Scene_Result = (POV_SHELLOUT_CAST)POV_SHELLOUT(PRE_SCENE_SHL); // Loop over each frame if(Pre_Scene_Result != ALL_SKIP_RET) { if(Pre_Scene_Result != SKIP_ONCE_RET) { for(opts.FrameSeq.FrameNumber = opts.FrameSeq.InitialFrame, opts.FrameSeq.Clock_Value = opts.FrameSeq.InitialClock; opts.FrameSeq.FrameNumber <= opts.FrameSeq.FinalFrame; // ISO/IEC 14882:1998(E) section 5.18 Comma operator [expr.comma] (page 90) says // that comma expressions are evaluated left-to-right, and according to section // 6.5.3 The for statement [stmt.for] (page 97) the following is an expression. // I just hope all compilers really know about the standard... [trf] opts.FrameSeq.FrameNumber++, opts.FrameSeq.Clock_Value = opts.FrameSeq.InitialClock + (Clock_Delta * (DBL)(opts.FrameSeq.FrameNumber - opts.FrameSeq.InitialFrame))) { if(opts.FrameSeq.FrameType == FT_MULTIPLE_FRAME) { START_TIME Send_Progress("Processing Frame", PROGRESS_PROCESSING_FRAME); } setup_output_file_name(); // Execute a shell-out command before tracing Frame_Result = (POV_SHELLOUT_CAST)POV_SHELLOUT(PRE_FRAME_SHL); if(Frame_Result == ALL_SKIP_RET) break; if(Frame_Result != SKIP_ONCE_RET) { FrameRender(); // Execute a shell-out command after tracing Frame_Result = (POV_SHELLOUT_CAST)POV_SHELLOUT(POST_FRAME_SHL); if((Frame_Result == SKIP_ONCE_RET) || (Frame_Result == ALL_SKIP_RET)) break; } if(opts.FrameSeq.FrameType == FT_MULTIPLE_FRAME) Send_FrameStatistics(); Do_Cooperate(1); } // Print total stats ... if(opts.FrameSeq.FrameType == FT_MULTIPLE_FRAME) { opts.FrameSeq.FrameNumber--; Send_RenderStatistics(true); opts.FrameSeq.FrameNumber++; } } // Execute the final shell-out command POV_SHELLOUT(POST_SCENE_SHL); } }