#ifndef __BITVECTORPVS_H #define __BITVECTORPVS_H #include #include "common.h" #include "PvsBase.h" namespace GtpVisibilityPreprocessor { // specialisation of vector typedef vector bit_vector; /** Iterator over a bitvector pvs. */ template class BitVectorPvsIterator { public: BitVectorPvsIterator(const typename bit_vector::const_iterator &itBegin, const typename bit_vector::const_iterator &itEnd //,const int lastElement ): mItCurrent(itBegin), mItEnd(itEnd), mDistance(0)//, mLastElement { } bool HasMoreEntries() const { // find next element in bit vector // warning: has to do traversal each time typename bit_vector::const_iterator itNext = mItCurrent; for (;(itNext != mItEnd) && !(*itNext); ++ itNext); return (itNext != mItEnd); } T Next(S &pdf) { return Next(); } T Next() { // hack: create new pvs entry for (; !(*mItCurrent); ++ mItCurrent, ++ mDistance); T sample = sObjects[mDistance]; ++ mDistance; ++ mItCurrent; return sample; } // vector of objects corresponding to pvs entries static vector sObjects; private: typename bit_vector::const_iterator mItCurrent; //typename bit_vector::const_iterator mItNext; typename bit_vector::const_iterator mItEnd; // note: store distance explicitly because I // don't know how efficient // std::distance is on specialisation of vector int mDistance; }; /** Pvs implemented as bitvector */ template class BitVectorPvs//: public PvsBase { template friend class BitVectorPvsIterator; public: BitVectorPvs(); //virtual ~HashPvs() {}; int GetSize() const; bool Empty() const; /** Adds sample to PVS. @returns contribution of sample (0 or 1) */ float AddSample(T sample, const float pdf); /** Adds sample to PVS without checking for presence of the sample warning: pvs remains unsorted! */ void AddSampleDirty(T sample, const float pdf); /** Adds sample dirty (on the end of the vector) but first checks if sample is already in clean part of the pvs. */ bool AddSampleDirtyCheck(T sample, const float pdf); /** Sort pvs entries - this should always be called after a sequence of AddSampleDirty calls */ void Sort(); /** Clears the pvs. */ void Clear(const bool trim = true); bool IsDirty() const; bool RequiresResort() const; /** Finds sample in PVS. */ bool Find(T sample); BitVectorPvsIterator GetIterator() const; /** Compute continuous PVS difference */ float GetPvsHomogenity(BitVectorPvs &pvs); static void Merge(BitVectorPvs &mergedPvs, const BitVectorPvs &a, const BitVectorPvs &b); static int GetEntrySizeByte(); static float GetEntrySize(); bool GetSampleContribution(T sample, const float pdf, float &contribution); int GetSamples() const { return mSamples; } void MergeInPlace(const BitVectorPvs &a) { std::cerr << "bitvector: merge in place not implemented yet" << std::endl; } bool RequiresResortLog() const { return false; } void Reserve(const int n) { mEntries.reserve(n); } /** Sort pvs entries assume that the pvs contains unique entries */ void SimpleSort() { // not necessary } int SubtractPvs(const BitVectorPvs &pvs) { std::cerr << "not yet implemented" << std::endl; return 0; } /** Compute continuous PVS difference */ void ComputeContinuousPvsDifference(BitVectorPvs &pvs, float &pvsReduction, float &pvsEnlargement) { std::cerr << "not yet implemented" << std::endl; } static void SetPvsSize(const int pvsSize) { sPvsSize = pvsSize; }; protected: /// hash table of PVS entries bit_vector mEntries; /// Number of samples used to create the PVS int mSamples; public: static int sPvsSize; }; template BitVectorPvs::BitVectorPvs() { // initialize bit vector mEntries.reserve(sPvsSize); mEntries.resize(sPvsSize); // set pvs entries to false Clear(); } template bool BitVectorPvs::Find(T sample) { return mEntries[sample->GetId()]; } template int BitVectorPvs::GetSize() const { int size = 0; bit_vector::const_iterator bit, bit_end = mEntries.end(); for (bit = mEntries.begin(); bit != bit_end; ++ bit) { if (*bit) ++ size; } return size; } template bool BitVectorPvs::Empty() const { bit_vector::const_iterator bit, bit_end = mEntries.end(); for (bit = mEntries.begin(); bit != bit_end; ++ bit) { if (*bit) return false; } return true; } template float BitVectorPvs::AddSample(T sample, const float pdf) { if (Find(sample)) return 0.0f; mEntries[sample->GetId()] = true; return 1.0f; } template void BitVectorPvs::AddSampleDirty(T sample, const float pdf) { if (!Find(sample)) { mEntries[sample->GetId()] = true; } } template bool BitVectorPvs::AddSampleDirtyCheck(T sample, const float pdf) { if (Find(sample)) return false; mEntries[sample->GetId()] = true; return true; } template void BitVectorPvs::Sort() { } template void BitVectorPvs::Clear(const bool trim) { bit_vector::iterator bit, bit_end = mEntries.end(); for (bit = mEntries.begin(); bit != bit_end; ++ bit) { (*bit) = false; } } template bool BitVectorPvs::IsDirty() const { return false; } template bool BitVectorPvs::RequiresResort() const { return false; } template BitVectorPvsIterator BitVectorPvs::GetIterator() const { return BitVectorPvsIterator(mEntries.begin(), mEntries.end()); } template float BitVectorPvs::GetEntrySize() { return (float)(sizeof(bool)) / float(1024 * 1024); } template int BitVectorPvs::GetEntrySizeByte() { return sizeof(bool); } template float BitVectorPvs::GetPvsHomogenity(BitVectorPvs &pvs) { float pvsReduction, pvsEnlargement; ComputeContinuousPvsDifference(pvs, pvsReduction, pvsEnlargement); return pvsReduction + pvsEnlargement; } template bool BitVectorPvs::GetSampleContribution(T sample, const float pdf, float &contribution) { const bool entryFound = Find(sample); if (entryFound) { contribution = 0.0f; return false; } else { contribution = 1.0f; return true; } } template void BitVectorPvs::Merge(BitVectorPvs &mergedPvs, const BitVectorPvs &a, const BitVectorPvs &b) { bit_vector::iterator bit, bit_end = mergedPvs.mEntries.end(); bit_vector::const_iterator bitA = a.mEntries.begin(), bitB = b.mEntries.begin(); for (bit = mergedPvs.mEntries.begin(); bit != bit_end; ++ bit, ++ bitA, ++ bitB) { (*bit) = (*bitA) | (*bitB); } } template int BitVectorPvs::sPvsSize = 0; template vector BitVectorPvsIterator::sObjects; } #endif