#ifndef __VERBOSEPVS_H #define __VERBOSEPVS_H #include #include "common.h" #include //#include "PvsBB.h" #include "PvsBase.h" #include "ObjectPvs.h" namespace GtpVisibilityPreprocessor { inline int operator< (PvsEntry const &a, PvsEntry const &b) { return a.mObject < b.mObject; } template VerbosePvs::VerbosePvs(const vector > &samples): mLastSorted(0) { mEntries.reserve(samples.size()); mEntries = samples; mSamples = samples.size(); } template void VerbosePvs::Sort() { typename vector >::iterator it = mEntries.begin() + mLastSorted; typename vector >::iterator it_end = mEntries.end(); // throw out double entries typename std::vector >::iterator newEnd = unique(it, it_end); sort(it, newEnd); // now merge sorted ranges ObjectPvs newPvs; Merge(newPvs, mEntries.begin(), it, it, newEnd, mSamples, 0); mEntries = newPvs.mEntries; mLastSorted = (int)mEntries.size(); mQueriesSinceSort = 0; } template void VerbosePvs::SimpleSort() { // sort(mEntries.begin(), mEntries.end()); typename vector >::iterator it = mEntries.begin() + mLastSorted; sort(it, mEntries.end()); inplace_merge(mEntries.begin(), it, mEntries.end()); mLastSorted = (int)mEntries.size(); mQueriesSinceSort = 0; } /** Compute continuous PVS difference of 'b' with respect to the base PVS (*this). Provides separatelly PVS reduction from PVS enlargement. */ template void VerbosePvs::ComputeContinuousPvsDifference(VerbosePvs &b, float &pvsReduction, float &pvsEnlargement) { pvsReduction = 0.0f; pvsEnlargement = 0.0f; // Uses sum of log differences, which corresponds to entropy typename vector >::iterator it; for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it) { float bSumPdf = (*it).mData.mSumPdf; float aSumPdf = 0.0f; typename vector >::iterator oit; const bool entryFound = Find((*it).mObject, oit); if (entryFound) { aSumPdf = (*it).mData.mSumPdf; // mark this entry as processed to avoid double counting (*it).mData.mSumPdf = -aSumPdf; } #if 0 const float diff = bSumPdf - aSumPdf; if (diff > 0.0f) { pvsEnlargement += diff; } else { pvsReduction += -diff; } #else if (!entryFound) { pvsEnlargement += 1.0f; } #endif } for (it = mEntries.begin(); it != mEntries.end(); ++ it) { float aSumPdf = (*it).mData.mSumPdf; float bSumPdf = 0.0f; if (aSumPdf < 0.0f) { // this entry was already accounted for! // just revert it back (*it).mData.mSumPdf = -aSumPdf; } else { typename vector >::iterator oit; const bool entryFound = b.Find((*it).mObject, oit); if (entryFound) { bSumPdf = (*oit).mData.mSumPdf; } #if 0 const float diff = bSumPdf - aSumPdf; if (diff > 0.0f) { pvsEnlargement += diff; } else { pvsReduction += -diff; } #else if (!entryFound) pvsReduction += 1.0f; #endif } } } template int VerbosePvs::Diff(const VerbosePvs &b) { int dif = 0; typename std::vector >::const_iterator it; for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it) { typename vector >::iterator bit; const bool entryFound = Find((*it).first, bit); if (!entryFound) ++ dif; } return dif; } template void VerbosePvs::MergeInPlace(const VerbosePvs &a) { // early exit if (a.Empty()) { return; } else if (Empty()) { mEntries.reserve(a.GetSize()); mEntries = a.mEntries; mSamples = a.mSamples; return; } ObjectPvs interPvs; Merge(interPvs, *this, a); mEntries.reserve(interPvs.GetSize()); mEntries = interPvs.mEntries; mSamples = interPvs.mSamples; } template void VerbosePvs::Merge(VerbosePvs &mergedPvs, const VerbosePvs &a, const VerbosePvs &b) { typename std::vector >::const_iterator ait = a.mEntries.begin(), ait_end = a.mEntries.end(); typename std::vector >::const_iterator bit = b.mEntries.begin(), bit_end = b.mEntries.end(); Merge(mergedPvs, ait, ait_end, bit, bit_end, a.mSamples, b.mSamples); } template void VerbosePvs::Merge(VerbosePvs &mergedPvs, const typename std::vector >::const_iterator &aBegin, const typename std::vector >::const_iterator &aEnd, const typename std::vector >::const_iterator &bBegin, const typename std::vector >::const_iterator &bEnd, const int aSamples, const int bSamples) { typename std::vector >::const_iterator ait = aBegin; typename std::vector >::const_iterator bit = bBegin; for (; (ait != aEnd); ++ ait) { Intersectable *aObj = (*ait).mObject; Intersectable *bObj = NULL; //Intersectable *bObjOld = NULL; const PvsEntry &aEntry = (*ait); for (; (bit != bEnd) && ((*bit).mObject <= (*ait).mObject); ++ bit) { bObj = (*bit).mObject; // object found => add up probabilities if (bObj == aEntry.mObject) { PvsData newData(aEntry.mData.mSumPdf + (*bit).mData.mSumPdf); PvsEntry entry(bObj, newData); mergedPvs.mEntries.push_back(entry); } else { mergedPvs.mEntries.push_back(*bit); } } // only push back if objects different // (equal case is handled by second loop) if (aObj != bObj) { mergedPvs.mEntries.push_back(*ait); } } // add the rest for (; (bit != bEnd); ++ bit) { mergedPvs.mEntries.push_back(*bit); } mergedPvs.mSamples = aSamples + bSamples; } template void VerbosePvs::Clear(const bool trim) { mEntries.clear(); mSamples = 0; mLastSorted = 0; if (trim) { vector >().swap(mEntries); } } template void VerbosePvs::Trim() { vector >(mEntries).swap(mEntries); } template bool VerbosePvs::Find(T sample, typename vector >::iterator &it, const bool checkDirty) { bool found = false; PvsEntry dummy(sample, PvsData()); // only check clean part typename vector >::iterator sorted_end = mEntries.begin() + mLastSorted; mQueriesSinceSort++; // binary search it = lower_bound(mEntries.begin(), sorted_end, dummy); if ((it != mEntries.end()) && ((*it).mObject == sample)) found = true; // sample not found yet => search further in the unsorted part if (!found && checkDirty) { typename vector >::iterator dit, dit_end = mEntries.end(); for (dit = sorted_end; (dit != dit_end) && ((*dit).mObject != sample); ++ dit); if (dit != dit_end) { found = true; it = dit; } } return found; } template void VerbosePvs::GetData(const int index, T &entry, S &data) { typename std::vector >::iterator i = mEntries.begin(); for (int k = 0; k != index && i != mEntries.end(); ++ i, ++ k); entry = (*i).first; data = (*i).second; } template float VerbosePvs::AddSample(T sample, const float pdf) { ++ mSamples; typename vector >::iterator it; const bool entryFound = Find(sample, it); if (entryFound) { S &data = (*it).mData; data.mSumPdf += pdf; return data.mSumPdf; } else { PvsEntry entry(sample, pdf); mEntries.insert(it, entry); ++ mLastSorted; return pdf; } } template void VerbosePvs::AddSampleDirty(T sample, const float pdf) { ++ mSamples; mEntries.push_back(PvsEntry(sample, pdf)); } template typename vector< PvsEntry >::iterator VerbosePvs::AddSample2(T sample, const float pdf) { ++ mSamples; typename vector >::iterator it; const bool entryFound = Find(sample, it); if (entryFound) { S &data = (*it).second; data->mSumPdf += pdf; } else { PvsEntry entry(sample, pdf); mEntries.insert(it, entry); ++ mLastSorted; } return it; } template bool VerbosePvs::AddSampleDirtyCheck(T sample, const float pdf) { ++ mSamples; typename vector >::iterator it; const bool entryFound = Find(sample, it); if (entryFound) { S &data = (*it).mData; data.mSumPdf += pdf; return false; } else { AddSampleDirty(sample, pdf); return true; } } template bool VerbosePvs::GetSampleContribution(T sample, const float pdf, float &contribution) { typename vector >::iterator it; const bool entryFound = Find(sample, it); if (entryFound) { S &data = (*it).mData; contribution = pdf / (data.mSumPdf + pdf); return false; } else { contribution = 1.0f; return true; } } template void VerbosePvs::Remove(typename vector >::iterator &it) { mEntries.erase(it); -- mLastSorted; // wrong if sample was in tail!! // $$JB decrement only if the sample found -- mSamples; } template bool VerbosePvs::RemoveSample(T sample, const float pdf) { typename vector >::iterator it; const bool entryFound = Find(sample, it); if (!entryFound) return false; // $$JB decrement only if the sample found -- mSamples; S &data = (*it).mData; data.mSumPdf -= pdf; if (data.mSumPdf <= 0.0f) { mEntries.erase(it); -- mLastSorted; // wrong if sample was in tail!! } return true; } template int VerbosePvs::SubtractPvs(const VerbosePvs &pvs) { const int samples = mSamples - pvs.mSamples; typename std::vector >:: const_iterator it, it_end = pvs.mEntries.end(); // output PVS of view cell for (it = pvs.mEntries.begin(); it != it_end; ++ it) RemoveSample((*it).mObject, (*it).mData.mSumPdf); mSamples = samples; return GetSize(); } template void VerbosePvs::CollectEntries(std::vector &entries) { typename std::vector >:: const_iterator it, it_end = mEntries.end(); // output PVS of view cell for (it = mEntries.begin(); it != it_end; ++ it) entries.push_back((*it)->first); } template void VerbosePvs::NormalizeMaximum() { typename std::vector >:: const_iterator it, it_end = mEntries.end(); float maxPdfSum = -1.0f; // output PVS of view cell for (it = mEntries.begin(); it != it_end; ++ it) { float sum = (*it)->second.sumPdf; if (sum > maxPdfSum) maxPdfSum = sum; } maxPdfSum = 1.0f / maxPdfSum; for (it = mEntries.begin(); it != it_end; ++ it) { (*it)->second.sumPdf *= maxPdfSum; } } template float VerbosePvs::GetEntrySize() { return (float)(sizeof(T) + sizeof(S)) / float(1024 * 1024); } template int VerbosePvs::GetEntrySizeByte() { return sizeof(T) + sizeof(S); } template float VerbosePvs::GetPvsHomogenity(VerbosePvs &pvs) { float pvsReduction, pvsEnlargement; ComputeContinuousPvsDifference(pvs, pvsReduction, pvsEnlargement); return pvsReduction + pvsEnlargement; } template PvsIterator VerbosePvs::GetIterator() const { PvsIterator pit(mEntries.begin(), mEntries.end()); return pit; } } #endif