#ifndef __PVS_H #define __PVS_H #include #include class KdNode; class BspNode; class Ray; class Intersectable; class ViewCellKdNode; template struct LtSample { bool operator()(const T a, const T b) const { return a < b; } }; /** Information stored with a PVS entry. Consists of the number the object was seen from the view cell. */ template struct PvsData { int mVisibleSamples; PvsData() {} PvsData(const int samples): mVisibleSamples(samples) {} }; /** Template class representing the Potentially Visible Set (PVS) mainly from a view cell, but also e.g., from objects. */ template class Pvs { public: Pvs(): /*mSamples(0), */mEntries() {} //int mSamples; /** Compresses PVS lossless or lossy. */ int Compress() {return 0;} int GetSize() const {return (int)mEntries.size();} bool Empty() const {return mEntries.empty();} /** Merges pvs of a and pvs of b into this pvs. */ void Merge(const Pvs &a, const Pvs &b); /** Difference of pvs to pvs b. @returns number of different entries. */ int Diff(const Pvs &b); /** Finds sample in PVS. @returns sample if found, NULL otherwise. */ PvsData *Find(T sample); /** Adds sample to PVS. @contribution contribution of sample (0 or 1) @returns true if sample was not already in PVS. */ bool AddSample(T sample, float &contribution); /** Adds sample to PVS. @returns contribution of sample (0 or 1) */ int AddSample(T sample); /** Adds one pvs to another one. @returns new pvs size */ int AddPvs(const Pvs &pvs); /** Subtracts one pvs from another one. @returns new pvs size */ int SubtractPvs(const Pvs &pvs); /** Returns PVS data, i.e., how often it was seen from the view cell, and the object itsef. */ void GetData(const int index, T &entry, PvsData &data); /** Collects the PVS entries and returns them in the vector. */ void CollectEntries(std::vector &entries); /** Removes sample from PVS if reference count is zero. @param visibleSampels number of references to be removed */ bool RemoveSample(T sample, const int visibleSamples); /// Map of PVS entries std::map, LtSample > mEntries; }; template int Pvs::Diff(const Pvs &b) { int dif = 0; std::map, LtSample >::const_iterator it; for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it) { PvsData *data = Find((*it).first); if (!data) ++ dif; } return dif; } template void Pvs::Merge(const Pvs &a, const Pvs &b) { std::map, LtSample >::const_iterator it; // todo: copy all elements instead of inserting for (it = a.mEntries.begin(); it != a.mEntries.end(); ++ it) mEntries.insert(*it); for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it) { PvsData *data = Find((*it).first); if (data) data->mVisibleSamples += (*it).second.mVisibleSamples; else mEntries.insert(*it); } } template PvsData *Pvs::Find(T sample) { std::map, LtSample >::iterator i = mEntries.find(sample); if (i != mEntries.end()) { return &(*i).second; } else return NULL; } template void Pvs::GetData(const int index, T &entry, PvsData &data) { std::map, LtSample >::iterator i = mEntries.begin(); for (int k = 0; k != index && i != mEntries.end(); i++, k++); entry = (*i).first; data = (*i).second; } template int Pvs::AddSample(T sample) { float dummy; return AddSample(sample, dummy) ? 1 : 0; } template bool Pvs::AddSample(T sample, float &contribution) { PvsData *data = Find(sample); if (data) { data->mVisibleSamples++; contribution = 1.0f/data->mVisibleSamples; return false; } else { mEntries[sample] = PvsData(1); contribution = 1.0f; return true; } } template bool Pvs::RemoveSample(T sample, const int visibleSamples) { std::map, LtSample >:: iterator it = mEntries.find(sample); if (it == mEntries.end()) return false; PvsData *data = &(*it).second; data->mVisibleSamples -= visibleSamples; if (data->mVisibleSamples <= 0) mEntries.erase(it); return true; } template int Pvs::AddPvs(const Pvs &pvs) { std::map, LtSample >:: const_iterator it, it_end = pvs.mEntries.end(); float contri; // output PVS of view cell for (it = pvs.mEntries.begin(); it != it_end; ++ it) AddSample((*it).first, contri); return GetSize(); } template int Pvs::SubtractPvs(const Pvs &pvs) { std::map, LtSample >:: const_iterator it, it_end = pvs.mEntries.end(); // output PVS of view cell for (it = pvs.mEntries.begin(); it != it_end; ++ it) RemoveSample((*it).first, (*it).second.mVisibleSamples); return GetSize(); } template void Pvs::CollectEntries(std::vector &entries) { std::map, LtSample >:: 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); } /** Class instantiating the Pvs template for kd tree nodes. */ class KdPvs: public Pvs { int Compress(); }; typedef std::map, LtSample > KdPvsMap; typedef std::map, LtSample > ObjectPvsMap; typedef PvsData ObjectPvsData; typedef PvsData KdPvsData; typedef Pvs ObjectPvs; #endif