void PhotonEstimationTask::EstimatePhotonsForObjectAndLight(ObjectPtr Object, LightSource *Light) { int mergedFlags=0; /* merged flags to see if we should shoot photons */ ViewThreadData *renderDataPtr = GetViewDataPtr(); /* first, check on various flags... make sure all is a go for this ObjectPtr */ LightTargetCombo combo(Light,Object); mergedFlags = combo.computeMergedFlags(); if (!( ((mergedFlags & PH_RFR_ON_FLAG) && !(mergedFlags & PH_RFR_OFF_FLAG)) || ((mergedFlags & PH_RFL_ON_FLAG) && !(mergedFlags & PH_RFL_OFF_FLAG)) )) /* it is a no-go for this object... bail out now */ return; if(!Object) return; ShootingDirection shootingDirection(Light,Object); shootingDirection.compute(); /* calculate the spacial separation (spread) */ renderDataPtr->photonSpread = combo.target->Ph_Density*GetSceneData()->photonSettings.surfaceSeparation; /* if rays aren't parallel, divide by dist so we get separation at a distance of 1 unit */ if (!combo.light->Parallel) { renderDataPtr->photonSpread /= shootingDirection.dist; } /* try to guess the number of photons */ DBL x=shootingDirection.rad / (combo.target->Ph_Density*GetSceneData()->photonSettings.surfaceSeparation); x=x*x*M_PI; if ( ((mergedFlags & PH_RFR_ON_FLAG) && !(mergedFlags & PH_RFR_OFF_FLAG)) && ((mergedFlags & PH_RFL_ON_FLAG) && !(mergedFlags & PH_RFL_OFF_FLAG)) ) { x *= 1.5; /* assume 2 times as many photons with both reflection & refraction */ } if ( !Test_Flag(combo.target, PH_IGNORE_PHOTONS_FLAG) ) { if ( ((mergedFlags & PH_RFR_ON_FLAG) && !(mergedFlags & PH_RFR_OFF_FLAG)) ) { if ( ((mergedFlags & PH_RFL_ON_FLAG) && !(mergedFlags & PH_RFL_OFF_FLAG)) ) x *= 3; /* assume 3 times as many photons if ignore_photons not used */ else x *= 2; /* assume less for only refraction */ } } x *= 0.5; /* assume 1/2 of photons hit target ObjectPtr */ photonCountEstimate += x; }
void PhotonSortingTask::SendProgress(void) { #if 0 // TODO FIXME PHOTONS // for now, we won't send this, as it can be confusing on the front-end due to out-of-order delivery from multiple threads. // we need to create a new progress message for sorting. if (timer.ElapsedRealTime() > 1000) { timer.Reset(); POVMS_Object obj(kPOVObjectClass_PhotonProgress); obj.SetInt(kPOVAttrib_CurrentPhotonCount, (GetSceneData()->surfacePhotonMap.numPhotons + GetSceneData()->mediaPhotonMap.numPhotons)); RenderBackend::SendViewOutput(GetViewData()->GetViewId(), GetSceneData()->frontendAddress, kPOVMsgIdent_Progress, obj); } #endif }
void PhotonEstimationTask::SearchThroughObjectsEstimatePhotons(vector<ObjectPtr>& Objects, LightSource *Light) { ViewThreadData *renderDataPtr = GetViewDataPtr(); shared_ptr<SceneData> sceneData = GetSceneData(); /* check this object and all siblings */ for(vector<ObjectPtr>::iterator Sib = Objects.begin(); Sib != Objects.end(); Sib++) { if(Test_Flag((*Sib), PH_TARGET_FLAG) && !((*Sib)->Type & LIGHT_SOURCE_OBJECT)) { /* do not shoot photons if global lights are turned off for ObjectPtr */ if(!Test_Flag((*Sib), NO_GLOBAL_LIGHTS_FLAG)) { EstimatePhotonsForObjectAndLight((*Sib), Light); } Cooperate(); } /* if it has children, check them too */ else if(((*Sib)->Type & IS_COMPOUND_OBJECT)) { SearchThroughObjectsEstimatePhotons(((CSG *)(*Sib))->children, Light); } } }
void PhotonSortingTask::Run() { // quit right away if photons not enabled if (!GetSceneData()->photonSettings.photonsEnabled) return; Cooperate(); if(strategy!=NULL) { delete strategy; sortPhotonMap(); } else { if (!this->load()) messageFactory.Error(POV_EXCEPTION_STRING("Failed to load photon map from disk"), "Could not load photon map (%s)",GetSceneData()->photonSettings.fileName); // set photon options automatically if (GetSceneData()->surfacePhotonMap.numPhotons>0) GetSceneData()->surfacePhotonMap.setGatherOptions(GetSceneData()->photonSettings,false); if (GetSceneData()->mediaPhotonMap.numPhotons>0) GetSceneData()->mediaPhotonMap.setGatherOptions(GetSceneData()->photonSettings,true); } // good idea to make sure all warnings and errors arrive frontend now [trf] SendProgress(); Cooperate(); }
void PhotonEstimationTask::Run() { // quit right away if photons not enabled if (!GetSceneData()->photonSettings.photonsEnabled) return; if (GetSceneData()->photonSettings.surfaceCount==0) return; Cooperate(); // COUNT THE PHOTONS DBL factor; photonCountEstimate = 0.0; // global lights GetViewDataPtr()->Light_Is_Global = true; for(vector<LightSource *>::iterator Light = GetSceneData()->lightSources.begin(); Light != GetSceneData()->lightSources.end(); Light++) { if((*Light)->Light_Type != FILL_LIGHT_SOURCE) SearchThroughObjectsEstimatePhotons(GetSceneData()->objects, *Light); } // light_group lights /* TODO renderer->sceneData->photonSettings.Light_Is_Global = false; for(vector<LightSource *>::iterator Light_Group_Light = renderer->sceneData->lightGroupLights.begin(); Light_Group_Light != renderer->sceneData->lightGroupLights.end(); Light_Group_Light++) { Light = Light_Group_Light->Light; if (Light->Light_Type != FILL_LightSource) { SearchThroughObjectsEstimatePhotons(GetSceneData()->objects, *Light); } } */ factor = (DBL)photonCountEstimate/GetSceneData()->photonSettings.surfaceCount; factor = sqrt(factor); GetSceneData()->photonSettings.surfaceSeparation *= factor; // good idea to make sure all warnings and errors arrive frontend now [trf] Cooperate(); }
/* loadPhotonMap() Loads the caustic photon map from a file. Preconditions: InitBacktraceEverything was called the photon map is empty renderer->sceneData->photonSettings.fileName contains the filename to load Postconditions: Returns 1 if success, 0 if failure. If success, the photon map has been loaded from the file. If failure then the render should stop with an error */ int PhotonSortingTask::load() { int i; size_t err; Photon *ph; FILE *f; int numph; if (!GetSceneData()->photonSettings.photonsEnabled) return 0; messageFactory.Warning(kWarningGeneral,"Starting the load of photon file %s\n",GetSceneData()->photonSettings.fileName); f = fopen(GetSceneData()->photonSettings.fileName, "rb"); if (!f) return 0; fread(&numph, sizeof(numph),1,f); for(i=0; i<numph; i++) { ph = GetSceneData()->surfacePhotonMap.AllocatePhoton(); err = fread(ph, sizeof(Photon), 1, f); if (err<=0) { /* fread returned an error! */ fclose(f); return 0; } } if (!feof(f)) /* for backwards file format compatibility */ { #ifdef GLOBAL_PHOTONS /* global photons */ fread(&numph, sizeof(numph),1,f); for(i=0; i<numph; i++) { ph = GetSceneData()->globalPhotonMap.AllocatePhoton(); err = fread(ph, sizeof(Photon), 1, f); if (err<=0) { /* fread returned an error! */ fclose(f); return 0; } } #endif /* media photons */ fread(&numph, sizeof(numph),1,f); for(i=0; i<numph; i++) { ph = GetSceneData()->mediaPhotonMap.AllocatePhoton(); err = fread(ph, sizeof(Photon), 1, f); if (err<=0) { /* fread returned an error! */ fclose(f); return 0; } } } fclose(f); return true; }
/* savePhotonMap() Saves the caustic photon map to a file. Preconditions: InitBacktraceEverything was called the photon map has been built and balanced photonSettings.fileName contains the filename to save Postconditions: Returns 1 if success, 0 if failure. If success, the photon map has been written to the file. */ int PhotonSortingTask::save() { Photon *ph; FILE *f; int i; size_t err; int numph; f = fopen(GetSceneData()->photonSettings.fileName, "wb"); if (!f) return 0; /* caustic photons */ numph = GetSceneData()->surfacePhotonMap.numPhotons; fwrite(&numph, sizeof(numph),1,f); if (numph>0 && GetSceneData()->surfacePhotonMap.head) { for(i=0; i<numph; i++) { ph = &(PHOTON_AMF(GetSceneData()->surfacePhotonMap.head, i)); err = fwrite(ph, sizeof(Photon), 1, f); if (err<=0) { /* fwrite returned an error! */ fclose(f); return 0; } } } else { messageFactory.PossibleError("Photon map for surface is empty."); } #ifdef GLOBAL_PHOTONS /* global photons */ numph = globalPhotonMap.numPhotons; fwrite(&numph, sizeof(numph),1,f); if (numph>0 && globalPhotonMap.head) { for(i=0; i<numph; i++) { ph = &(PHOTON_AMF(globalPhotonMap.head, i)); err = fwrite(ph, sizeof(Photon), 1, f); if (err<=0) { /* fwrite returned an error! */ fclose(f); return 0; } } } else { messageFactory.PossibleError("Global photon map is empty."); } #endif /* media photons */ numph = GetSceneData()->mediaPhotonMap.numPhotons; fwrite(&numph, sizeof(numph),1,f); if (numph>0 && GetSceneData()->mediaPhotonMap.head) { for(i=0; i<numph; i++) { ph = &(PHOTON_AMF(GetSceneData()->mediaPhotonMap.head, i)); err = fwrite(ph, sizeof(Photon), 1, f); if (err<=0) { /* fwrite returned an error! */ fclose(f); return 0; } } } else { messageFactory.PossibleError("Photon map for media is empty."); } fclose(f); return true; }
void PhotonSortingTask::sortPhotonMap() { vector<PhotonMap*>::iterator mapIter; for(mapIter = surfaceMaps.begin(); mapIter != surfaceMaps.end(); mapIter++) { GetSceneData()->surfacePhotonMap.mergeMap(*mapIter); //delete (*mapIter); } for(mapIter = mediaMaps.begin(); mapIter != mediaMaps.end(); mapIter++) { GetSceneData()->mediaPhotonMap.mergeMap(*mapIter); //delete (*mapIter); } /* now actually build the kd-tree by sorting the array of photons */ if (GetSceneData()->surfacePhotonMap.numPhotons>0) { //povwin::WIN32_DEBUG_FILE_OUTPUT("\n\nsurfacePhotonMap.buildTree about to be called\n"); GetSceneData()->surfacePhotonMap.buildTree(); GetSceneData()->surfacePhotonMap.setGatherOptions(GetSceneData()->photonSettings,false); // povwin::WIN32_DEBUG_FILE_OUTPUT("gatherNumSteps: %d\n",GetSceneData()->surfacePhotonMap.gatherNumSteps); // povwin::WIN32_DEBUG_FILE_OUTPUT("gatherRadStep: %lf\n",GetSceneData()->surfacePhotonMap.gatherRadStep); // povwin::WIN32_DEBUG_FILE_OUTPUT("minGatherRad: %lf\n",GetSceneData()->surfacePhotonMap.minGatherRad); // povwin::WIN32_DEBUG_FILE_OUTPUT("minGatherRadMult: %lf\n",GetSceneData()->surfacePhotonMap.minGatherRadMult); // povwin::WIN32_DEBUG_FILE_OUTPUT("numBlocks: %d\n",GetSceneData()->surfacePhotonMap.numBlocks); // povwin::WIN32_DEBUG_FILE_OUTPUT("numPhotons: %d\n",GetSceneData()->surfacePhotonMap.numPhotons); } #ifdef GLOBAL_PHOTONS /* ----------- global photons ------------- */ if (globalPhotonMap.numPhotons>0) { globalPhotonMap.buildTree(); globalPhotonMap.setGatherOptions(false); } #endif /* ----------- media photons ------------- */ if (GetSceneData()->mediaPhotonMap.numPhotons>0) { GetSceneData()->mediaPhotonMap.buildTree(); GetSceneData()->mediaPhotonMap.setGatherOptions(GetSceneData()->photonSettings,true); } if (GetSceneData()->surfacePhotonMap.numPhotons+ #ifdef GLOBAL_PHOTONS globalPhotonMap.numPhotons+ #endif GetSceneData()->mediaPhotonMap.numPhotons > 0) { /* should we load the photon map now that it is built? */ if (GetSceneData()->photonSettings.fileName && !GetSceneData()->photonSettings.loadFile) { /* status bar for user */ // Send_Progress("Saving Photon Maps", PROGRESS_SAVING_PHOTON_MAPS); if (!this->save()) messageFactory.Warning(kWarningGeneral,"Could not save photon map."); } } else { if (GetSceneData()->photonSettings.fileName && !GetSceneData()->photonSettings.loadFile) messageFactory.Warning(kWarningGeneral,"Could not save photon map - no photons!"); } }
} RGBTColour& TraceTask::SubdivisionBuffer::operator()(size_t x, size_t y) { return colors[x + (y * size)]; } void TraceTask::SubdivisionBuffer::Clear() { for(vector<bool>::iterator i(sampled.begin()); i != sampled.end(); i++) *i = false; } TraceTask::TraceTask(ViewData *vd, unsigned int tm, DBL js, DBL aat, unsigned int aad, pov_base::GammaCurvePtr& aag, unsigned int ps, bool psc, bool final, bool hr) : RenderTask(vd, "Trace"), trace(vd->GetSceneData(), &vd->GetCamera(), GetViewDataPtr(), vd->GetSceneData()->parsedMaxTraceLevel, vd->GetSceneData()->parsedAdcBailout, vd->GetQualityFeatureFlags(), cooperate, media, radiosity), cooperate(*this), tracingMethod(tm), jitterScale(js), aaThreshold(aat), aaDepth(aad), aaGamma(aag), previewSize(ps), previewSkipCorner(psc), finalTrace(final), highReproducibility(hr), media(GetViewDataPtr(), &trace, &photonGatherer), radiosity(vd->GetSceneData(), GetViewDataPtr(), vd->GetSceneData()->radiositySettings, vd->GetRadiosityCache(), cooperate, final, vd->GetCamera().Location), photonGatherer(&vd->GetSceneData()->mediaPhotonMap, vd->GetSceneData()->photonSettings)