/* * Implementation of the special importance map functions */ #include "statistics.h" #include "pmapoptions.H" #include "importancemap.H" #include "error.h" bool CImportanceMap::AddPhoton(CPhoton &photon, VECTOR &normal, short flags) { return CPhotonMap::AddPhoton(photon, normal, flags); } // Reconstruct float CImportanceMap::ReconstructImp(VECTOR &pos, VECTOR &normal /*, IMPORTANCE_OPTION option */) { float maxDistance = 0.0; float result=0., importance; float factor; // Nearest photons must be found beforehand! // Construct radiance estimate maxDistance = m_distances[0]; for(int i = 0; i < m_nrpFound; i++) { CImporton *importon = (CImporton *)m_photons[i]; VECTOR dir = importon->Dir(); // No bsdf eval : incoming importance !!!!!! importance = importon->Importance(); float cos_theta = VECTORDOTPRODUCT(dir, normal); if(cos_theta > 0.0) { result += importance; } } // Now we have a 'importance' integrated over area estimate, // so we convert it to 'importance/potential', maxDistance is already squared if(maxDistance < 1e-5) return 0; factor = 1.0 / (M_PI * maxDistance * m_totalPaths); result *= factor; #ifdef PMAP_DEBUG printf("\nReconstruct: NRP %i MAXD %f\n", m_nrpFound, maxDistance); printf("POS: "); VectorPrint(stdout, pos); printf("\n"); printf("OUT: "); VectorPrint(stdout, outDir); printf("\n"); printf("N: "); VectorPrint(stdout, normal); printf("\n"); printf("RES: "); ColorPrint(stdout, result); printf("\n"); printf("-------------------------------------------------\n"); #endif return result; } float CImportanceMap::GetImpReqDensity(VECTOR &pos, VECTOR &normal) { float density; // Reconstruct importance density = ReconstructImp(pos,normal); // Rescale //if(!pmapstate.pixelImportance) // density *= Camera.hres * Camera.vres; // We want impScale photons per pixel density, account for // the pixel area here density /= Camera.pixh * Camera.pixv; return(density); } float CImportanceMap::GetRequiredDensity(VECTOR &pos, VECTOR &normal) { if(m_nrPhotons == 0) return pmapstate.constantRD; // Safety, if no importance map was constructed float density; CheckNBalance(); if(m_precomputeIrradiance) { if(!m_irradianceComputed || (m_preReconPhotons != *m_estimate_nrp)) PrecomputeIrradiance(); CImporton *photon = (CImporton *)DoIrradianceQuery(&pos, &normal, m_totalMaxDistance); if(photon) { switch(pmapstate.importanceOption) { case USE_IMPORTANCE: density = photon->PImportance(); density *= *m_impScalePtr; break; default: Error("CImportanceMap::GetRequiredDensity", "Unsupported importance option"); return 0; break; } } else density = 0; } else { // normal query or no irradiance photon found // Query photons, to be used by the appropriate req dest method m_nrpFound = DoQuery(&pos); if(m_nrpFound < 3) return 0; // pmapstate.minimumImpRD; switch(pmapstate.importanceOption) { case USE_IMPORTANCE: density = GetImpReqDensity(pos,normal); density *= *m_impScalePtr; break; default: Error("CImportanceMap::GetRequiredDensity", "Unsupported importance option"); return 0; break; } } // Minimum required density if(density < pmapstate.minimumImpRD) density = pmapstate.minimumImpRD; return density; } void CImportanceMap::ComputeAllRequiredDensities(VECTOR &pos, VECTOR &normal, float *imp, float *pot, float *diff) { // Query photons, to be used by the appropriate req dest method m_nrpFound = DoQuery(&pos); if(m_nrpFound < 5) { // not enough photons *imp = *pot = *diff = 0.0; } *imp = GetImpReqDensity(pos,normal); } void CImportanceMap::PhotonPrecomputeIrradiance(CIrrPhoton *photon) { float imp, pot, diff; VECTOR pos = photon->Pos(); VECTOR normal = photon->Normal(); ComputeAllRequiredDensities(pos, normal, &imp, &pot, &diff); // Abuse pot for tail enhancement pot = m_distances[0]; // Only valid since max heap is used in kdtree m_totalMaxDistance = MAX(pot, m_totalMaxDistance); ((CImporton *)photon)->PSetAll(imp, pot, diff); if(imp > m_maxImp) m_maxImp = imp; m_avgImp += imp; } void CImportanceMap::PrecomputeIrradiance(void) { fprintf(stderr, "CImportanceMap::PrecomputeIrradiance\n"); m_maxImp = 0; m_avgImp = 0; m_preReconPhotons = *m_estimate_nrp; m_totalMaxDistance = 0.0; m_irradianceComputed = false; // fprintf(stderr, "MSDiff %g, AVGSDIFF %g\n", m_maxSingleDiff, // m_sumSingleDiff/ m_nrPhotons); CPhotonMap::PrecomputeIrradiance(); // fprintf(stderr, "MaxImp %g, MaxDiff %g\n", m_maxImp, m_maxDiff); m_avgImp /= m_nrPhotons; m_totalMaxDistance *= 20.0 / *m_estimate_nrp; // fprintf(stderr, "MaxImp %g, MaxDiff %g\n", m_maxImp, m_maxDiff); // fprintf(stderr, "AvgImp %g, AvgDiff %g\n", m_avgImp, m_avgDiff); }