Index: trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h	(revision 607)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h	(revision 610)
@@ -716,4 +716,6 @@
 	bool mUsePolygonSplitIfAvailable;
 
+	int mTimeStamp;
+
 private:
 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.cpp	(revision 608)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.cpp	(revision 610)
@@ -1286,5 +1286,5 @@
 
 		// compress root node
-		PropagateUpVisibility(interior);
+		PullUpVisibility(interior);
 	}
 }
@@ -1328,5 +1328,5 @@
 	
 
-void ViewCellsTree::PropagateUpVisibility(ViewCellInterior *interior)
+void ViewCellsTree::PullUpVisibility(ViewCellInterior *interior)
 {
 	Intersectable::NewMail((int)interior->mChildren.size());
@@ -1536,4 +1536,13 @@
 }
 
+
+void ViewCellsTree::PropagateUpPvs(ViewCell *vc)
+{
+	while (vc->GetParent())
+	{
+		vc->GetParent()->GetPvs().Merge(vc->GetPvs());
+		vc = vc->GetParent();
+	}
+}
 
 
@@ -1624,4 +1633,55 @@
 
 
+bool ViewCellsTree::Export(ofstream &stream)
+{
+	ExportViewCell(mRoot, stream);
+
+	return true;
+}
+
+
+void ViewCellsTree::ExportViewCell(ViewCell *viewCell, ofstream &stream)
+{
+	ObjectPvsMap::iterator it, it_end = viewCell->GetPvs().mEntries.end();
+
+	if (0) // test with empty pvs
+	for (it = viewCell->GetPvs().mEntries.begin(); it != it_end; ++ it)
+	{
+		stream << (*it).first->GetId() << " ";
+	}
+
+	stream << "\" />" << endl;
+
+	if (viewCell->IsLeaf())
+	{
+		stream << "<Leaf ";
+		stream << "id=\"" << viewCell->GetId() << "\" ";
+		stream << "active=\"" << viewCell->mIsActive << "\" ";
+		stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
+		stream << "pvs=\"";
+		stream << "</Leaf>" << endl;
+	}
+	else
+	{
+		ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
+	
+		stream << "<Interior ";
+		stream << "id=\"" << viewCell->GetId() << "\" ";
+		stream << "active=\"" << viewCell->mIsActive << "\" ";
+		stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
+		stream << "pvs=\"";
+
+		ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
+
+		for (it = interior->mChildren.begin(); it != it_end; ++ it)
+		{
+			ExportViewCell(*it, stream);
+		}
+
+		stream << "</Interior>" << endl;
+	}
+}
+
+
 
 /**************************************************************************/
@@ -1704,4 +1764,7 @@
 
 
+
+
+
 /************************************************************************/
 /*                    MergeStatistics implementation                    */
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Pvs.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Pvs.h	(revision 581)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Pvs.h	(revision 610)
@@ -59,7 +59,7 @@
   void NormalizeMaximum();
   
-  /** Merges pvs of a and pvs of b into this pvs.
+  /** Merges pvs of a into this pvs.
    */
-  void Merge(const Pvs<T> &a, const Pvs<T> &b);
+  void Merge(const Pvs<T> &a);
   
   /** Difference of pvs to pvs b.
@@ -130,11 +130,9 @@
 
 template <typename T>
-void Pvs<T>::Merge(const Pvs<T> &a, const Pvs<T> &b)
+void Pvs<T>::Merge(const Pvs<T> &a)
 {
 	std::map<T, PvsData<T>, LtSample<T> >::const_iterator it;
 
-	mEntries = a.mEntries;
-	
-	for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
+	for (it = a.mEntries.begin(); it != a.mEntries.end(); ++ it)
 	{
 		PvsData<T> *data = Find((*it).first);
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 590)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 610)
@@ -261,4 +261,6 @@
 	int mMailbox;
 
+	int mTimeStamp;
+
 protected:
 
@@ -955,4 +957,5 @@
 	ViewCellsManager *mViewCellsManager;
 
+	int mTimeStamp;
 
 private:
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h	(revision 609)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h	(revision 610)
@@ -6,4 +6,5 @@
 #include "Containers.h"
 #include "ViewCell.h"
+#include "ViewCellBsp.h"
 
 class ViewCell;
@@ -349,14 +350,12 @@
 										vector<MergeCandidate> &candidates) = 0;
 
-	
-  
-  void CollectViewCells(const int n) {
-	mNumActiveViewCells = n;
-	mViewCells.clear();
-	CollectViewCells();
-  }
-
-
-  virtual bool EqualToSpatialNode(ViewCell *viewCell) const { return false;}
+	void CollectViewCells(const int n);
+
+
+	virtual void CreateMergeHierarchy() {};
+	
+	virtual bool EqualToSpatialNode(ViewCell *viewCell) const { return false;}
+
+
 protected:
 
@@ -411,13 +410,6 @@
 	void CreateViewCellMeshes();
 
-	/**
-		Exports single view cell.
-		NOTE: should be in exporter!!
-	*/
-	void ExportViewCell(ViewCell *viewCell, ofstream &stream);
-
-
-	/** 
-		Takes different measures to prepares the view cells after loading them from disc.
+
+	/** Takes different measures to prepares the view cells after loading them from disc.
 	*/
 	virtual void PrepareLoadedViewCells() {};
@@ -537,5 +529,27 @@
 	bool ExportViewCells(const string filename);
 
+	void CreateMergeHierarchy();
+
+
 protected:
+
+	struct TraversalData
+	{  
+		ViewCellInterior *mParentViewCell;
+		BspNode *mNode;
+		
+
+		TraversalData() {}
+		TraversalData(BspNode *node, ViewCellInterior *vc):
+			 mNode(node), mParentViewCell(vc)
+		{}
+   
+		bool operator<(const TraversalData &b) const 
+		{
+			return mNode->mTimeStamp < b.mNode->mTimeStamp;
+		}
+	};
+
+	typedef priority_queue<TraversalData> TraversalQueue;
 
 	/** HACK
@@ -754,5 +768,28 @@
 protected:
 
+	struct TraversalData
+	{  
+		ViewCellInterior *mParentViewCell;
+		BspNode *mNode;
+		
+
+		TraversalData() {}
+		TraversalData(BspNode *node, ViewCellInterior *vc):
+			 mNode(node), mParentViewCell(vc)
+		{}
+   
+		bool operator<(const TraversalData &b) const 
+		{
+			return mNode->mTimeStamp < b.mNode->mTimeStamp;
+		}
+	};
+
+	typedef priority_queue<TraversalData> TraversalQueue;
+
+	/** Returns node of the spatial hierarchy corresponding to the view cell
+		if such a node exists.
+	*/
 	BspNode *GetSpatialNode(ViewCell *viewCell) const;
+
 	/** HACK
 	*/
@@ -778,5 +815,5 @@
 	void PrepareLoadedViewCells();
 
-	
+	void CreateMergeHierarchy();
 	/// the view space partition BSP tree.
 	VspBspTree *mVspBspTree;
Index: trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp	(revision 609)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp	(revision 610)
@@ -68,5 +68,6 @@
 mStoreRays(false),
 mRenderCostWeight(0.5),
-mUseRandomAxis(false)
+mUseRandomAxis(false),
+mTimeStamp(0)
 {
 	bool randomize = false;
@@ -87,5 +88,8 @@
 	//-- max cost ratio for early tree termination
 	environment->GetFloatValue("VspBspTree.Termination.maxCostRatio", mTermMaxCostRatio);
-mTermMinPolygons = 25;
+
+	// HACK
+	mTermMinPolygons = 25;
+
 	//-- factors for bsp tree split plane heuristics
 	environment->GetFloatValue("VspBspTree.Factor.balancedRays", mBalancedRaysFactor);
@@ -729,4 +733,7 @@
 	frontData.mNode = interior->GetFront();
 	backData.mNode = interior->GetBack();
+
+	frontData.mNode->mTimeStamp = mTimeStamp;
+	backData.mNode->mTimeStamp = mTimeStamp ++;
 
 	//DEL_PTR(leaf);
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 605)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 610)
@@ -50,5 +50,5 @@
 
 BspNode::BspNode(): 
-mParent(NULL), mTreeValid(true)
+mParent(NULL), mTreeValid(true), mTimeStamp(0)
 {}
 
@@ -216,5 +216,6 @@
 mRoot(NULL), 
 mUseAreaForPvs(false),
-mGenerateViewCells(true)
+mGenerateViewCells(true),
+mTimeStamp(0)
 {
 	Randomize(); // initialise random generator for heuristics
@@ -1098,4 +1099,7 @@
 	backData.mNode = interior->GetBack();
 	
+	frontData.mNode->mTimeStamp = mTimeStamp;
+	backData.mNode->mTimeStamp = mTimeStamp ++;
+
 	//DEL_PTR(leaf);
 	return interior;
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.h	(revision 609)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.h	(revision 610)
@@ -351,4 +351,11 @@
 	ViewCell *GetActiveViewCell(ViewCell *vc) const;
 
+	/** Propagates pvs up the tree to the root.
+	*/
+	void PropagateUpPvs(ViewCell *vc);
+
+	bool Export(ofstream &stream);
+
+
 protected:
 
@@ -421,5 +428,5 @@
 	int UpdateActiveViewCells(ViewCellContainer &viewCells);
 
-	void PropagateUpVisibility(ViewCellInterior *interior);
+	void PullUpVisibility(ViewCellInterior *interior);
 
 	void CompressViewCellsPvs(ViewCell *root);
@@ -428,4 +435,11 @@
 	*/
 	float GetMemUsage() const;
+	
+	/**
+		Exports single view cell.
+		NOTE: should be in exporter!!
+	*/
+	void ExportViewCell(ViewCell *viewCell, ofstream &stream);
+
 
 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp	(revision 609)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp	(revision 610)
@@ -334,5 +334,5 @@
 float ViewCellsManager::GetViewSpaceVolume()
 {
-	return mViewSpaceBox.GetVolume()*(2.0f*sqr((float)M_PI));
+	return mViewSpaceBox.GetVolume() * (2.0f * sqr((float)M_PI));
 }
 
@@ -544,6 +544,7 @@
 	ViewCellInterior *vc = new ViewCellInterior();//GenerateViewCell();
 
+	vc->GetPvs() = left->GetPvs();
 	// merge pvs
-	vc->GetPvs().Merge(left->GetPvs(), right->GetPvs());
+	vc->GetPvs().Merge(right->GetPvs());
 
 	//-- merge ray sets
@@ -576,5 +577,5 @@
 	{
 		// merge pvs
-		vc->GetPvs().Merge(vc->GetPvs(), (*it)->GetPvs());
+		vc->GetPvs().Merge((*it)->GetPvs());
 
 		vc->SetupChildLink(*it);
@@ -940,18 +941,11 @@
 
 
-void ViewCellsManager::ExportViewCell(ViewCell *viewCell, ofstream &stream)
-{
-	stream << "<ViewCell id=\"" << viewCell->GetId() << "\" ";
-	stream << "pvs=\"";
-
-	ObjectPvsMap::iterator it, it_end = viewCell->GetPvs().mEntries.end();
-	if(0) // test with empty pvs
-	for (it = viewCell->GetPvs().mEntries.begin(); it != it_end; ++ it)
-	{
-		stream << (*it).first->GetId() << " ";
-	}
-
-	stream << "\" />" << endl;
-}
+void ViewCellsManager::CollectViewCells(const int n) 
+{
+	mNumActiveViewCells = n;
+	mViewCells.clear();
+	CollectViewCells();
+}
+
 
 
@@ -1625,7 +1619,14 @@
 	//-- load the view cells itself, i.e., the ids and the pvs
 	stream << "<ViewCells>" << endl;
+
+#if 0
+	
 	ViewCellContainer::const_iterator it, it_end = mViewCells.end();
+		
 	for (it = mViewCells.begin(); it != it_end; ++ it)
 		ExportViewCell(*it, stream);
+#else
+	mViewCellsTree->Export(stream);
+#endif
 
 	stream << "</ViewCells>" << endl;
@@ -1660,4 +1661,44 @@
 			BspViewCell *bspVc = dynamic_cast<BspViewCell *>(*lit);
 			bspVc->mLeaf->SetViewCell(vc);
+		}
+	}
+}
+
+
+void BspViewCellsManager::CreateMergeHierarchy()
+{
+	TraversalQueue tQueue;
+
+	tQueue.push(TraversalData(mBspTree->GetRoot(), NULL));
+
+	while (!tQueue.empty())
+	{
+		TraversalData tData = tQueue.top();
+		tQueue.pop();
+
+		if (tData.mNode->IsLeaf())
+		{
+			ViewCell *viewCell = dynamic_cast<BspLeaf *>(tData.mNode)->GetViewCell();
+			viewCell->SetMergeCost((float)tData.mNode->mTimeStamp);
+
+			if (tData.mParentViewCell)
+			{
+				tData.mParentViewCell->SetupChildLink(viewCell);
+				// probagate up pvs
+				mViewCellsTree->PropagateUpPvs(viewCell);
+			}
+		}
+		else
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(tData.mNode);
+			ViewCellInterior *viewCellInterior = new ViewCellInterior();
+			viewCellInterior->SetMergeCost((float)tData.mNode->mTimeStamp);
+
+
+			tQueue.push(TraversalData(interior->GetBack(), viewCellInterior));
+			tQueue.push(TraversalData(interior->GetFront(), viewCellInterior));
+
+			if (tData.mParentViewCell)
+				tData.mParentViewCell->SetupChildLink(viewCellInterior);
 		}
 	}
@@ -2791,5 +2832,36 @@
 void VspBspViewCellsManager::CreateMergeHierarchy()
 {
-	
+	TraversalQueue tQueue;
+
+	tQueue.push(TraversalData(mVspBspTree->GetRoot(), NULL));
+
+	while (!tQueue.empty())
+	{
+		TraversalData tData = tQueue.top();
+		tQueue.pop();
+
+		if (tData.mNode->IsLeaf())
+		{
+			ViewCell *viewCell = dynamic_cast<BspLeaf *>(tData.mNode)->GetViewCell();
+
+			if (tData.mParentViewCell)
+			{
+				tData.mParentViewCell->SetupChildLink(viewCell);
+				// probagate up pvs
+				mViewCellsTree->PropagateUpPvs(viewCell);
+			}
+		}
+		else
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(tData.mNode);
+			ViewCellInterior *viewCellInterior = new ViewCellInterior();
+			
+			tQueue.push(TraversalData(interior->GetBack(), viewCellInterior));
+			tQueue.push(TraversalData(interior->GetFront(), viewCellInterior));
+
+			if (tData.mParentViewCell)
+				tData.mParentViewCell->SetupChildLink(viewCellInterior);
+		}
+	}
 }
 
@@ -3342,7 +3414,14 @@
 	//-- load the view cells itself, i.e., the ids and the pvs
 	stream << "<ViewCells>" << endl;
+	
+#if 0
+	
 	ViewCellContainer::const_iterator it, it_end = mViewCells.end();
+		
 	for (it = mViewCells.begin(); it != it_end; ++ it)
 		ExportViewCell(*it, stream);
+#else
+	mViewCellsTree->Export(stream);
+#endif
 
 	stream << "</ViewCells>" << endl;
