Index: GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.h	(revision 1686)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.h	(revision 1706)
@@ -450,4 +450,14 @@
 	void ExportStats(ofstream &stats, SplitQueue &tQueue, const ObjectContainer &objects);
 
+	void CollectBestSet(const int maxSplits,
+						const float maxMemoryCost,
+						vector<VspNode *> &vspNodes,
+						vector<BvhNode *> &bvhNodes);
+
+	void ExtractStatistics(const int maxSplits,
+						   const float maxMemoryCost,
+						   float &renderCost,
+						   float &memory,
+						   int &pvsEntries);
 protected:
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp	(revision 1695)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp	(revision 1706)
@@ -686,11 +686,8 @@
 			mergedVc->SetMergeCost(totalRenderCost);
 			
-			// HACK
-			//mergedVc->SetMergeCost(1.0f / (float)realNumActiveViewCells);
-
 			// check if "siblings (back and front node of the same parent)
-			if (0)
-				++ mergeStats.siblings;
-			// set the coŽst for rendering a view cell
+			if (0) ++ mergeStats.siblings;
+
+			// set the cost for rendering a view cell
 			mergedVc->SetCost(realExpectedCost);
 
@@ -763,9 +760,7 @@
 	}
 
-	// test if voluje is equal
-	Debug << "volume of the root view cell: " << mRoot->GetVolume() << " " << mViewCellsManager->GetViewSpaceBox().GetVolume() << endl;
-
-	//hack!!
-	//mRoot->GetPvs().Clear();
+	// test if computed volumes are correct
+	Debug << "volume of the root view cell: " << mRoot->GetVolume() 
+		  << " " << mViewCellsManager->GetViewSpaceBox().GetVolume() << endl;
 	
 	// TODO: delete because makes no sense here
Index: GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 1705)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 1706)
@@ -310,4 +310,11 @@
 	virtual void CollectObjects(ObjectContainer &objects);
 
+	/** returns level of the hierarchy that is "active" right now.
+	*/
+	BvhNode *GetActiveNode()
+	{
+		return mActiveNode;
+	}
+
 public:
 
@@ -323,4 +330,7 @@
 	/// pointer to a split plane candidate splitting this leaf
 	SubdivisionCandidate *mSubdivisionCandidate;
+
+	
+	BvhNode *mActiveNode;
 };
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h	(revision 1694)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h	(revision 1706)
@@ -29,17 +29,17 @@
 class PvsData {
 public:
-  // sum of probability density of visible sample rays
-  float mSumPdf;
-
-  PvsData() {}
-  PvsData(const float sumPdf):
+	/// sum of probability density of visible sample rays
+	float mSumPdf;
+
+	PvsData() {}
+	PvsData(const float sumPdf):
 	mSumPdf(sumPdf) {}
 
-  // $$JB in order to return meaningfull values
-  // it assumes that the sum pdf has been normalized somehow!!!
-  float GetVisibility() 
-  { 
-	  return mSumPdf; 
-  }
+	// $$JB in order to return meaningfull values
+	// it assumes that the sum pdf has been normalized somehow!!!
+	float GetVisibility() 
+	{ 
+		return mSumPdf; 
+	}
 };
 
@@ -47,21 +47,21 @@
 class MailablePvsData 
 {
-////////////////////////////
-//  Mailing stuff
+	////////////////////////////
+	//  Mailing stuff
 protected:
 	int mMailbox;
 
 public:
-  // last mail id -> warning not thread safe!
-  // both mailId and mailbox should be unique for each thread!!!
-  static int sMailId;
-  static int sReservedMailboxes;
-  
-  
+	// last mail id -> warning not thread safe!
+	// both mailId and mailbox should be unique for each thread!!!
+	static int sMailId;
+	static int sReservedMailboxes;
+
+
 	static void NewMail(const int reserve = 1) {
 		sMailId += sReservedMailboxes;
 		sReservedMailboxes = reserve;
 	}
-	
+
 	void Mail() { mMailbox = sMailId; }
 	bool Mailed() const { return mMailbox == sMailId; }
@@ -71,20 +71,20 @@
 
 	int IncMail() { return ++ mMailbox - sMailId; }
-//////////////////////////////////////////
-
-  // sum of probability density of visible sample rays
-  float mSumPdf;
-  int mCounter;
-
-  MailablePvsData() {}
-  MailablePvsData(const float sumPdf):
+	//////////////////////////////////////////
+
+	// sum of probability density of visible sample rays
+	float mSumPdf;
+	int mCounter;
+
+	MailablePvsData() {}
+	MailablePvsData(const float sumPdf):
 	mSumPdf(sumPdf) {}
 
-  // $$JB in order to return meaningfull values
-  // it assumes that the sum pdf has been normalized somehow!!!
-  float GetVisibility() 
-  { 
-	  return mSumPdf; 
-  }
+	// $$JB in order to return meaningfull values
+	// it assumes that the sum pdf has been normalized somehow!!!
+	float GetVisibility() 
+	{ 
+		return mSumPdf; 
+	}
 };
 
@@ -97,105 +97,106 @@
 {
 public:
-  Pvs(): /*mSamples(0), */mEntries() {}
-  
-  //virtual ~Pvs();
-    
-  /** Compresses PVS lossless or lossy.
-  */
-  int Compress() {return 0;}
-  int GetSize() const {return (int)mEntries.size();}
-  bool Empty() const {return mEntries.empty();}
-
-  /** Normalize the visibility of entries in order to get comparable
-	  results 
-  */
-  void NormalizeMaximum();
-  
-  /** Merges pvs of a into this pvs.
-   */
-  void Merge(const Pvs<T, S> &a);
-  
-  /** Difference of pvs to pvs b.
-	  @returns number of different entries.
-  */
-  int Diff(const Pvs<T, S> &b);
-  
-  /** Finds sample in PVS.
-	  @returns sample if found, NULL otherwise.
-  */
-  S *Find(T sample);
-
-  bool GetSampleContribution(T sample, const float pdf, float &contribution);
-  
-  /** Adds sample to PVS. 
-	  @contribution contribution of sample (0 or 1)
-	  @returns true if sample was not already in PVS.
-  */
-  bool AddSample(T sample, const float pdf, float &contribution);
-
-  /** Adds sample to PVS.
-	  @returns contribution of sample (0 or 1)
-  */
-  float AddSample(T sample, const float pdf);
-  
-  /** Adds sample to PVS.
-	  @returns PvsData
-  */
-  S *AddSample2(T sample, const float pdf);
-
-  /** Adds one pvs to another one.
-	  @returns new pvs size
-  */
-  int AddPvs(const Pvs<T, S> &pvs);
-
-  /** Subtracts one pvs from another one.
-  WARNING: could contains bugs
-	  @returns new pvs size
-  */
-  int SubtractPvs(const Pvs<T, S> &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, S &data);
-
-  /** Collects the PVS entries and returns them in the vector.
-  */
-  void CollectEntries(std::vector<T> &entries);
-
-  /** Removes sample from PVS if reference count is zero.
-	  @param visibleSamples number of references to be removed
-  */
-  bool RemoveSample(T sample, const float pdf);
-
-  /** Compute continuous PVS difference */
-  void ComputeContinuousPvsDifference(Pvs<T, S> &pvs,
-									  float &pvsReduction,
-									  float &pvsEnlargement);
-  
-
-  /** Clears the pvs.
-  */
-  void Clear();
-
-  static int GetEntrySizeByte(); 
-  static float GetEntrySize();
-
-  /** Compute continuous PVS difference */
-  float GetPvsHomogenity(Pvs<T, S> &pvs) {
-	float 
-	  pvsReduction,
-	  pvsEnlargement;
-	
-	ComputeContinuousPvsDifference(pvs,
-								   pvsReduction,
-								   pvsEnlargement);
-	
-	return pvsReduction + pvsEnlargement;
-  }
-  
-  int Size() { return mEntries.size(); }
-					  
-  /// Map of PVS entries
-  std::map<T, S, LtSample<T> > mEntries;
+	Pvs(): /*mSamples(0), */mEntries() {}
+
+	//virtual ~Pvs();
+
+	/** Compresses PVS lossless or lossy.
+	*/
+	int Compress() {return 0;}
+	int GetSize() const {return (int)mEntries.size();}
+	bool Empty() const {return mEntries.empty();}
+
+	/** Normalize the visibility of entries in order to get comparable
+		results 
+	*/
+	void NormalizeMaximum();
+
+	/** Merges pvs of a into this pvs.
+	*/
+	void Merge(const Pvs<T, S> &a);
+
+	/** Difference of pvs to pvs b.
+		@returns number of different entries.
+	*/
+	int Diff(const Pvs<T, S> &b);
+
+	/** Finds sample in PVS.
+		@returns sample if found, NULL otherwise.
+	*/
+	S *Find(T sample);
+
+	bool GetSampleContribution(T sample, const float pdf, float &contribution);
+
+	/** Adds sample to PVS. 
+		@contribution contribution of sample (0 or 1)
+		@returns true if sample was not already in PVS.
+	*/
+	bool AddSample(T sample, const float pdf, float &contribution);
+
+	/** Adds sample to PVS.
+		@returns contribution of sample (0 or 1)
+	*/
+	float AddSample(T sample, const float pdf);
+
+	/** Adds sample to PVS.
+		@returns PvsData
+	*/
+	S *AddSample2(T sample, const float pdf);
+
+	/** Adds one pvs to another one.
+		@returns new pvs size
+	*/
+	int AddPvs(const Pvs<T, S> &pvs);
+
+	/** Subtracts one pvs from another one.
+		WARNING: could contains bugs
+		@returns new pvs size
+	*/
+	int SubtractPvs(const Pvs<T, S> &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, S &data);
+
+	/** Collects the PVS entries and returns them in the vector.
+	*/
+	void CollectEntries(std::vector<T> &entries);
+
+	/** Removes sample from PVS if reference count is zero.
+		@param visibleSamples number of references to be removed
+	*/
+	bool RemoveSample(T sample, const float pdf);
+
+	/** Compute continuous PVS difference 
+	*/
+	void ComputeContinuousPvsDifference(Pvs<T, S> &pvs,
+		float &pvsReduction,
+		float &pvsEnlargement);
+
+
+	/** Clears the pvs.
+	*/
+	void Clear();
+
+	static int GetEntrySizeByte(); 
+	static float GetEntrySize();
+
+	/** Compute continuous PVS difference */
+	float GetPvsHomogenity(Pvs<T, S> &pvs) {
+		float 
+			pvsReduction,
+			pvsEnlargement;
+
+		ComputeContinuousPvsDifference(pvs,
+			pvsReduction,
+			pvsEnlargement);
+
+		return pvsReduction + pvsEnlargement;
+	}
+
+	int Size() { return mEntries.size(); }
+
+	/// Map of PVS entries
+	std::map<T, S, LtSample<T> > mEntries;
 };
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp	(revision 1705)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp	(revision 1706)
@@ -1600,13 +1600,5 @@
 }
 
-/*typedef priority_queue<ViewCell *, vector<ViewCell *>, 
-					   myless<vector<ViewCell *>::value_type> > ViewCellsQueue;
-
-typedef priority_queue<BvhNode *, vector<BvhNode *>, 
-					   myless<vector<BvhNode *>::value_type> > BvhQueue;
-
-typedef priority_queue<VspNode *, vector<VspNode *>, 
-					   myless<vector<VspNode *>::value_type> > VspQueue;
-*/
+
 static void UpdateStats(ofstream &stats,
 						const int splits,
@@ -1776,4 +1768,252 @@
 }
 
-	
-}
+
+
+class HierarchyNodeWrapper;
+
+
+template <typename T> class myless
+{
+public:
+	bool operator() (T v1, T v2) const
+	{
+		return (v1->GetMergeCost() < v2->GetMergeCost());
+	}
+};
+
+typedef priority_queue<HierarchyNodeWrapper *, vector<HierarchyNodeWrapper *>, 
+					   myless<vector<HierarchyNodeWrapper *>::value_type> > HierarchyNodeQueue;
+
+class HierarchyNodeWrapper
+{
+public:
+	enum {VSP_NODE, BVH_NODE};
+
+	virtual float GetMergeCost() const = 0;
+	virtual int Type() const  = 0;
+	virtual bool IsLeaf() const = 0;
+
+	virtual void PushChildren(HierarchyNodeQueue &tQueue) = 0;
+};
+
+
+class VspNodeWrapper: public HierarchyNodeWrapper
+{
+public:
+	VspNodeWrapper(VspNode *node): mNode(node) {}
+
+	int Type() const { return VSP_NODE; }
+
+	float GetMergeCost() const { return (float) -mNode->mTimeStamp; };
+
+	bool IsLeaf() const { return mNode->IsLeaf(); }
+
+	void PushChildren(HierarchyNodeQueue &tQueue)
+	{
+		if (!mNode->IsLeaf())
+		{
+			VspInterior *interior = dynamic_cast<VspInterior *>(mNode);
+
+			tQueue.push(new VspNodeWrapper(interior->GetFront()));
+			tQueue.push(new VspNodeWrapper(interior->GetBack()));
+		}
+	}
+
+	VspNode *mNode;
+};
+
+
+class BvhNodeWrapper: public HierarchyNodeWrapper
+{
+public:
+	BvhNodeWrapper(BvhNode *node): mNode(node) {}
+	
+	int Type()  const { return BVH_NODE; }
+
+	float GetMergeCost() const { return (float)-mNode->mTimeStamp; };
+
+	bool IsLeaf() const { return mNode->IsLeaf(); }
+
+	void PushChildren(HierarchyNodeQueue &tQueue)
+	{
+		if (!mNode->IsLeaf())
+		{
+			BvhInterior *interior = dynamic_cast<BvhInterior *>(mNode);
+
+			tQueue.push(new BvhNodeWrapper(interior->GetFront()));
+			tQueue.push(new BvhNodeWrapper(interior->GetBack()));
+		}
+	}
+
+	BvhNode *mNode;
+};
+
+
+void HierarchyManager::CollectBestSet(const int maxSplits,
+									  const float maxMemoryCost,
+									  vector<VspNode *> &vspNodes,
+									  vector<BvhNode *> &bvhNodes)
+{
+	HierarchyNodeQueue tqueue;
+	tqueue.push(new VspNodeWrapper(mVspTree->GetRoot()));
+	tqueue.push(new BvhNodeWrapper(mBvHierarchy->GetRoot()));
+	
+	float memCost = 0;
+
+	while (!tqueue.empty())
+	{
+		HierarchyNodeWrapper *nodeWrapper = tqueue.top();
+		tqueue.pop();
+
+		// save the view cells if it is a leaf or if enough view cells have already been traversed
+		// because of the priority queue, this will be the optimal set of v
+		if (nodeWrapper->IsLeaf() || 
+			((vspNodes.size() + bvhNodes.size() + tqueue.size() + 1) >= maxSplits) ||
+			(memCost > maxMemoryCost)
+			)
+		{
+			if (nodeWrapper->Type() == HierarchyNodeWrapper::VSP_NODE)
+			{
+				VspNodeWrapper *vspNodeWrapper = dynamic_cast<VspNodeWrapper *>(nodeWrapper);
+				vspNodes.push_back(vspNodeWrapper->mNode);
+			}
+			else
+			{
+				BvhNodeWrapper *bvhNodeWrapper = dynamic_cast<BvhNodeWrapper *>(nodeWrapper);
+				bvhNodes.push_back(bvhNodeWrapper->mNode);
+			}
+		}
+		else 
+		{	
+			nodeWrapper->PushChildren(tqueue);
+		}
+
+		delete nodeWrapper;
+	}
+}
+
+
+void HierarchyManager::ExtractStatistics(const int maxSplits,
+										 const float maxMemoryCost,
+										 float &renderCost,
+										 float &memory,
+										 int &pvsEntries)
+{
+	/*TraversalQueue tqueue;
+	tqueue.push(mRoot);
+
+	//cout << "exporting stats ... " << endl;
+	int numViewCells = 1;
+	
+	const AxisAlignedBox3 box = mViewCellsManager->GetViewSpaceBox();
+	const float vol = box.GetVolume();
+
+	const int rootPvs = GetPvsSize(mRoot);
+	const int rootEntries = GetPvsEntries(mRoot);
+	float totalRenderCost, avgRenderCost, expectedCost;
+
+	float deviation = 0;
+	int totalPvs = rootPvs;
+	int entriesInPvs = rootEntries;
+
+	totalRenderCost = avgRenderCost = expectedCost = (float)rootPvs;
+
+	ofstream stats;
+	stats.open(mergeStats.c_str());
+
+	const float memoryCost = (float)entriesInPvs * ObjectPvs::GetEntrySize();
+
+	/////////////
+	//-- first view cell
+
+	UpdateStats(stats,
+				0, 
+				numViewCells, 
+				0, 
+				totalRenderCost, 
+				rootPvs, 
+				expectedCost, 
+				avgRenderCost, 
+				deviation,
+				totalPvs, 
+				entriesInPvs,
+				memoryCost,
+				0, 
+				mRoot->GetVolume());
+		
+
+	//-- go through tree in the order of render cost decrease
+	//-- which is the same order as the view cells were merged
+	//-- or the reverse order of subdivision for subdivision-only 
+	//-- view cell hierarchies.
+
+	while (!tqueue.empty())
+	{
+		ViewCell *vc = tqueue.top();
+		tqueue.pop();
+
+		if (!vc->IsLeaf()) 
+		{	
+			ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
+
+			const int parentPvs = GetPvsSize(interior);
+			const int parentPvsEntries = GetPvsEntries(interior);
+            const float parentCost = (float)parentPvs * interior->GetVolume();
+
+			float childCost = 0;
+			int childPvs = 0;
+			int childPvsEntries = 0;
+
+			-- numViewCells;
+
+			ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
+
+			for (it = interior->mChildren.begin(); it != it_end; ++ it)
+			{
+				ViewCell *vc = *it;
+
+				const int pvsSize = GetPvsSize(vc);
+				const int pvsEntries = GetPvsEntries(vc);
+
+				childCost += (float) pvsSize * vc->GetVolume();
+				childPvs += pvsSize;
+				childPvsEntries += pvsEntries;
+
+				tqueue.push(vc);
+				++ numViewCells;
+			}
+
+			// update stats for this view cell
+			const float costDecr = (parentCost - childCost) / vol;
+
+			totalRenderCost -= costDecr;
+			totalPvs += childPvs - parentPvs;
+			entriesInPvs += childPvsEntries - parentPvsEntries;
+
+			expectedCost = totalRenderCost / (float)numViewCells;
+			avgRenderCost = (float)totalPvs / (float)numViewCells;
+
+			const float memoryCost = (float)entriesInPvs * ObjectPvs::GetEntrySize();
+
+			UpdateStats(stats,
+						0, 
+						numViewCells, 
+						costDecr, 
+						totalRenderCost,
+						parentPvs, 
+						expectedCost, 
+						avgRenderCost, 
+						deviation,
+                        totalPvs, 
+						entriesInPvs, 
+						memoryCost,
+						childPvs - parentPvs,
+						vc->GetVolume());
+		}
+	}
+
+	stats.close();
+	*/
+}
+	
+}
