Index: trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp	(revision 419)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp	(revision 420)
@@ -24,4 +24,5 @@
 #include "Intersectable.h"
 #include "Ray.h"
+#include "RayInfo.h"
 
 // Static variables
@@ -34,6 +35,5 @@
 float VspKdTree::sTermMaxRayContribution = 0.1f;
 
-
-
+/// Adds object to the pvs of the front and back node
 inline void AddObject2Pvs(Intersectable *object,
 						  const int side,
@@ -71,4 +71,36 @@
 
 /**************************************************************/
+/*                class VspKdTreeNode implementation          */
+/**************************************************************/
+
+// Inline constructor
+VspKdTreeNode::VspKdTreeNode(VspKdTreeInterior *p):
+mParent(p), mAxis(-1), mDepth(p ? p->mDepth + 1 : 0) 
+{}
+
+VspKdTreeNode::~VspKdTreeNode() 
+{};
+
+inline VspKdTreeInterior *VspKdTreeNode::GetParent() const
+{
+	return mParent;
+}
+
+inline void VspKdTreeNode::SetParent(VspKdTreeInterior *p)
+{
+	mParent = p;
+}
+
+bool VspKdTreeNode::IsLeaf() const 
+{ 
+	return mAxis == -1; 
+}
+  
+int VspKdTreeNode::GetAccessTime() 
+{
+	return 0x7FFFFFF;
+}
+
+/**************************************************************/
 /*                VspKdTreeInterior implementation            */
 /**************************************************************/
@@ -88,5 +120,6 @@
 	mBack = b;
 	mFront = f;
-	b->mParent = f->mParent = this;
+	b->SetParent(this);
+	f->SetParent(this);
 }
 
@@ -140,7 +173,79 @@
 }
 
-/**************************************************/
-/*         class VspKdTree implementation         */
-/**************************************************/
+
+/*********************************************************/
+/*            class VspKdTreeLeaf implementation         */
+/*********************************************************/
+VspKdTreeLeaf::VspKdTreeLeaf(VspKdTreeInterior *p,	const int nRays):
+VspKdTreeNode(p), mRays(), mPvsSize(0), mValidPvs(false) 
+{
+	mRays.reserve(nRays);
+}
+
+VspKdTreeLeaf::~VspKdTreeLeaf() 
+{}
+
+int VspKdTreeLeaf::Type() const  
+{ 
+	return ELeaf; 
+}
+
+void VspKdTreeLeaf::Print(ostream &s) const 
+{
+	s << endl << "L: r = " << (int)mRays.size() << endl;
+};
+
+void VspKdTreeLeaf::AddRay(const RayInfo &data) 
+{
+	mValidPvs = false;
+	mRays.push_back(data);
+	data.mRay->Ref();
+}
+
+int VspKdTreeLeaf::GetPvsSize() const 
+{
+	return mPvsSize;
+}
+
+void VspKdTreeLeaf::SetPvsSize(const int s) 
+{
+	mPvsSize = s;
+}
+
+void VspKdTreeLeaf::Mail()
+{ 
+	mMailbox = mailID; 
+}
+
+void VspKdTreeLeaf::NewMail() 
+{ 
+	++ mailID; 
+}
+
+bool VspKdTreeLeaf::Mailed() const 
+{ 
+	return mMailbox == mailID; 
+}
+
+bool VspKdTreeLeaf::Mailed(const int mail) 
+{
+	return mMailbox >= mailID + mail;
+}
+
+float VspKdTreeLeaf::GetAvgRayContribution() const 
+{
+	return GetPvsSize() / ((float)mRays.size() + Limits::Small);
+}
+
+float VspKdTreeLeaf::GetSqrRayContribution() const 
+{
+	return sqr(GetAvgRayContribution());
+}
+
+/*********************************************************/
+/*            class VspKdTree implementation             */
+/*********************************************************/
+
+
 void VspKdTree::ParseEnvironment()
 {
@@ -271,6 +376,6 @@
 		Intersectable::NewMail();
 		int pvsSize = 0;
-		for(VspKdTreeNode::RayInfoContainer::iterator ri = rays.begin(); 
-			ri != rays.end(); ++ ri)
+		for(RayInfoContainer::iterator ri = mRays.begin(); 
+			ri != mRays.end(); ++ ri)
 		{
 			if ((*ri).mRay->IsActive()) 
@@ -323,5 +428,5 @@
 	for (VssRayContainer::const_iterator ri = rays.begin(); ri != rays.end(); ++ ri)
 	{
-		leaf->AddRay(VspKdTreeNode::RayInfo(*ri));
+		leaf->AddRay(RayInfo(*ri));
 
 		mBox.Include((*ri)->GetOrigin());
@@ -334,5 +439,5 @@
 	cout << "Bbox = " << mBox << endl;
 	
-	mStat.rays = (int)leaf->rays.size();
+	mStat.rays = (int)leaf->mRays.size();
 	leaf->UpdatePvsSize();
 	
@@ -467,5 +572,5 @@
 	cout<<
 		"pvs="<<leaf->mPvsSize<<
-		" rays="<<leaf->rays.size()<<
+		" rays="<<leaf->mRays.size()<<
 		" rc="<<leaf->GetAvgRayContribution()<<
 		" axis="<<axis<<endl;
@@ -502,6 +607,6 @@
 
 	// this is the main ray classification loop!
-    for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
-		ri != leaf->rays.end();	ri++)
+    for(RayInfoContainer::iterator ri = leaf->mRays.begin();
+		ri != leaf->mRays.end();	ri++)
 	{
 		if (!(*ri).mRay->IsActive()) 
@@ -533,5 +638,5 @@
 	
 	//	cout<<axis<<" "<<pvsSize<<" "<<pvsBack<<" "<<pvsFront<<endl;
-	//  float oldCost = leaf->rays.size();
+	//  float oldCost = leaf->mRays.size();
 	float oldCost = (float)pvsSize;
 	
@@ -616,6 +721,6 @@
 	// C = ct_div_ci  + (ql*rl + qr*rr)/queries
 	
-	int rl=0, rr = (int)leaf->rays.size();
-	int pl=0, pr = leaf->GetPvsSize();
+	int rl = 0, rr = (int)leaf->mRays.size();
+	int pl = 0, pr = leaf->GetPvsSize();
 	float minBox = box.Min(axis);
 	float maxBox = box.Max(axis);
@@ -630,6 +735,6 @@
 	Intersectable::NewMail();
 	// set all object as belonging to the fron pvs
-	for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
-		ri != leaf->rays.end();	++ ri)
+	for(RayInfoContainer::iterator ri = leaf->mRays.begin();
+		ri != leaf->mRays.end();	++ ri)
 	{
 		if ((*ri).mRay->IsActive())
@@ -724,5 +829,5 @@
 	splitCandidates->clear();
   
-	int requestedSize = 2 * (int)(node->rays.size());
+	int requestedSize = 2 * (int)(node->mRays.size());
 	// creates a sorted split candidates array
 	if (splitCandidates->capacity() > 500000 &&
@@ -736,6 +841,6 @@
 
 	// insert all queries 
-	for(VspKdTreeNode::RayInfoContainer::const_iterator ri = node->rays.begin();
-		ri < node->rays.end(); ++ ri) 
+	for(RayInfoContainer::const_iterator ri = node->mRays.begin();
+		ri < node->mRays.end(); ++ ri) 
 	{
 		bool positive = (*ri).mRay->HasPosDir(axis);
@@ -759,5 +864,5 @@
 		++ mStat.maxDepthNodes;
   
-	//  if ( (int)(leaf->rays.size()) < termMinCost)
+	//  if ( (int)(leaf->mRays.size()) < termMinCost)
 	//    stat.minCostNodes++;
 	if (leaf->GetPvsSize() < sTermMinPvs)
@@ -773,6 +878,6 @@
 		++ mStat.minSizeNodes;
 
-//	if ((int)(leaf->rays.size()) > stat.maxRayRefs)
-//		mStat.maxRayRefs = (int)leaf->rays.size();
+//	if ((int)(leaf->mRays.size()) > stat.maxRayRefs)
+//		mStat.maxRayRefs = (int)leaf->mRays.size();
 }
 
@@ -784,5 +889,5 @@
 										AxisAlignedBox3 &frontBBox)
 {
-	if ( (leaf->GetPvsSize() < sTermMinPvs) || (leaf->rays.size() < sTermMinRays) ||
+	if ( (leaf->GetPvsSize() < sTermMinPvs) || (leaf->mRays.size() < sTermMinRays) ||
 	// (leaf->GetAvgRayContribution() > termMaxRayContribution ) ||
        (leaf->mDepth >= sTermMaxDepth) || SqrMagnitude(box.Size()) <= sTermMinSize ) 
@@ -791,5 +896,5 @@
 #if 0
 		if (leaf->mDepth >= termMaxDepth) {
-			cout<<"Warning: max depth reached depth="<<(int)leaf->mDepth<<" rays="<<leaf->rays.size()<<endl;
+			cout<<"Warning: max depth reached depth="<<(int)leaf->mDepth<<" rays="<<leaf->mRays.size()<<endl;
 			cout<<"Bbox: "<<GetBBox(leaf)<<" dirbbox:"<<GetDirBBox(leaf)<<endl;
 		}
@@ -846,6 +951,6 @@
 		frontBBox.SetMin(axis, position);
 		
-		for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
-				ri != leaf->rays.end();	ri++) 
+		for(RayInfoContainer::iterator ri = leaf->mRays.begin();
+				ri != leaf->mRays.end(); ++ ri) 
 		{
 			if ((*ri).mRay->IsActive()) 
@@ -861,19 +966,19 @@
 					if ((*ri).mRay->HasPosDir(axis)) 
 					{
-						back->AddRay(VspKdTreeNode::RayInfo((*ri).mRay,
-															(*ri).mMinT,
-															(*ri).mRay->mT));
-						front->AddRay(VspKdTreeNode::RayInfo((*ri).mRay,
-															 (*ri).mRay->mT,
-															 (*ri).mMaxT));
+						back->AddRay(RayInfo((*ri).mRay,
+											 (*ri).mMinT,
+											 (*ri).mRay->mT));
+						front->AddRay(RayInfo((*ri).mRay,
+									 		  (*ri).mRay->mT,
+											  (*ri).mMaxT));
 					} 
 					else 
 					{
-						back->AddRay(VspKdTreeNode::RayInfo((*ri).mRay,
-															(*ri).mRay->mT,
-															(*ri).mMaxT));
-						front->AddRay(VspKdTreeNode::RayInfo((*ri).mRay,
-															 (*ri).mMinT,
-															 (*ri).mRay->mT));
+						back->AddRay(RayInfo((*ri).mRay,
+											 (*ri).mRay->mT,
+											 (*ri).mMaxT));
+						front->AddRay(RayInfo((*ri).mRay,
+									 		  (*ri).mMinT,
+											  (*ri).mRay->mT));
 					}
 				} 
@@ -891,6 +996,6 @@
 		// rays front/back
     
-        for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
-			ri != leaf->rays.end(); ++ ri) 
+        for (RayInfoContainer::iterator ri = leaf->mRays.begin();
+			ri != leaf->mRays.end(); ++ ri) 
 		{
 			if ((*ri).mRay->IsActive()) 
@@ -916,8 +1021,9 @@
 	
 	// update stats
-	mStat.rayRefs -= (int)leaf->rays.size();
+	mStat.rayRefs -= (int)leaf->mRays.size();
 	mStat.rayRefs += raysBack + raysFront;
 
-	delete leaf;
+	DEL_PTR(leaf);
+
 	return node;
 }
@@ -929,5 +1035,5 @@
 	// find a node in the tree which subtree will be collapsed
 	int maxAccessTime = time - accessTimeThreshold;
-	int released;
+	int released = 0;
 
 	tstack.push(mRoot);
@@ -947,5 +1053,5 @@
 				break;
 			}
-			if (in->GetBack()->GetAccessTime() <  in->GetFront()->GetAccessTime()) 
+			if (in->GetBack()->GetAccessTime() < in->GetFront()->GetAccessTime()) 
 			{
 				tstack.push(in->GetFront());
@@ -984,5 +1090,5 @@
 	
 	// check if we should perform a dynamic subdivision of the leaf
-	if (// leaf->rays.size() > (unsigned)termMinCost &&
+	if (// leaf->mRays.size() > (unsigned)termMinCost &&
 		(leaf->GetPvsSize() >= sTermMinPvs) && 
 		(SqrMagnitude(leafBBox.Size()) > sizeThreshold) )
@@ -1042,5 +1148,5 @@
 	stack<RayTraversalData> tstack;
 
-	tstack.push(RayTraversalData(mRoot, VspKdTreeNode::RayInfo(ray)));
+	tstack.push(RayTraversalData(mRoot, RayInfo(ray)));
   
 	RayTraversalData data;
@@ -1056,5 +1162,4 @@
 			// split the set of rays in two groups intersecting the
 			// two subtrees
-
 			TraverseInternalNode(data, tstack);
       	} 
@@ -1074,16 +1179,16 @@
 				if (removeAllScheduledRays) 
 				{
-					int tail = (int)leaf->rays.size() - 1;
-
-					for (int i=0; i < (int)(leaf->rays.size()); ++ i) 
+					int tail = (int)leaf->mRays.size() - 1;
+
+					for (int i=0; i < (int)(leaf->mRays.size()); ++ i) 
 					{
-						if (leaf->rays[i].mRay->ScheduledForRemoval()) 
+						if (leaf->mRays[i].mRay->ScheduledForRemoval()) 
 						{
 							// find a ray to replace it with
-							while (tail >= i && leaf->rays[tail].mRay->ScheduledForRemoval()) 
+							while (tail >= i && leaf->mRays[tail].mRay->ScheduledForRemoval()) 
 							{
 								++ mStat.removedRayRefs;
-								leaf->rays[tail].mRay->Unref();
-								leaf->rays.pop_back();
+								leaf->mRays[tail].mRay->Unref();
+								leaf->mRays.pop_back();
 								
 								-- tail;
@@ -1095,7 +1200,7 @@
 							++ mStat.removedRayRefs;
 	      
-							leaf->rays[i].mRay->Unref();
-							leaf->rays[i] = leaf->rays[tail];
-							leaf->rays.pop_back();
+							leaf->mRays[i].mRay->Unref();
+							leaf->mRays[i] = leaf->mRays[tail];
+							leaf->mRays.pop_back();
 							-- tail;
 						}
@@ -1105,12 +1210,12 @@
       
 			if (!removeAllScheduledRays)
-				for (int i=0; i < (int)leaf->rays.size(); i++) 
+				for (int i=0; i < (int)leaf->mRays.size(); i++) 
 				{
-					if (leaf->rays[i].mRay == ray) 
+					if (leaf->mRays[i].mRay == ray) 
 					{
 						++ mStat.removedRayRefs;
 						ray->Unref();
-						leaf->rays[i] = leaf->rays[leaf->rays.size() - 1];
-						leaf->rays.pop_back();
+						leaf->mRays[i] = leaf->mRays[leaf->mRays.size() - 1];
+						leaf->mRays.pop_back();
 					    // check this ray again
 						break;
@@ -1132,5 +1237,5 @@
 	stack<RayTraversalData> tstack;
   
-	tstack.push(RayTraversalData(mRoot, VspKdTreeNode::RayInfo(ray)));
+	tstack.push(RayTraversalData(mRoot, RayInfo(ray)));
   
 	RayTraversalData data;
@@ -1148,6 +1253,6 @@
 		{
 			// remove the ray from the leaf
-			// find the ray in the leaf and swap it with the last ray...
-			VspKdTreeLeaf *leaf = (VspKdTreeLeaf *)data.mNode;
+			// find the ray in the leaf and swap it with the last ray
+			VspKdTreeLeaf *leaf = dynamic_cast<VspKdTreeLeaf *>(data.mNode);
 			leaf->AddRay(data.mRayData);
 			++ mStat.addedRayRefs;
@@ -1171,10 +1276,8 @@
 		{
 			tstack.push(RayTraversalData(in->GetBack(), 
-						VspKdTreeNode::RayInfo(data.mRayData.mRay, data.mRayData.mMinT, 
-											   data.mRayData.mRay->mT)));
+						RayInfo(data.mRayData.mRay, data.mRayData.mMinT, data.mRayData.mRay->mT)));
 				
 			tstack.push(RayTraversalData(in->GetFront(),
-						VspKdTreeNode::RayInfo(data.mRayData.mRay, data.mRayData.mRay->mT, 
-											   data.mRayData.mMaxT)));
+						RayInfo(data.mRayData.mRay, data.mRayData.mRay->mT, data.mRayData.mMaxT)));
 	
 		} 
@@ -1182,11 +1285,11 @@
 		{
 			tstack.push(RayTraversalData(in->GetBack(),
-										 VspKdTreeNode::RayInfo(data.mRayData.mRay,
-																data.mRayData.mRay->mT,
-																data.mRayData.mMaxT)));
+										 RayInfo(data.mRayData.mRay,
+												 data.mRayData.mRay->mT,
+												 data.mRayData.mMaxT)));
 			tstack.push(RayTraversalData(in->GetFront(),
-										 VspKdTreeNode::RayInfo(data.mRayData.mRay,
-																data.mRayData.mMinT,
-																data.mRayData.mRay->mT)));
+										 RayInfo(data.mRayData.mRay,
+												 data.mRayData.mMinT,
+												 data.mRayData.mRay->mT)));
 		}
 	  } 
@@ -1219,7 +1322,7 @@
 
 #if DEBUG_COLLAPSE
-	cout<<"Collapsing subtree"<<endl;
-	cout<<"acessTime="<<sroot->GetAccessTime()<<endl;
-	cout<<"depth="<<(int)sroot->depth<<endl;
+	cout << "Collapsing subtree" << endl;
+	cout << "acessTime=" << sroot->GetAccessTime() << endl;
+	cout << "depth=" << (int)sroot->depth << endl;
 #endif
 
@@ -1240,6 +1343,6 @@
 			VspKdTreeLeaf *leaf = (VspKdTreeLeaf *) node;
 			
-			for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
-					ri != leaf->rays.end(); ++ ri) 
+			for(RayInfoContainer::iterator ri = leaf->mRays.begin();
+					ri != leaf->mRays.end(); ++ ri) 
 			{
 				++ totalRayCount;
@@ -1278,6 +1381,6 @@
 			VspKdTreeLeaf *leaf = dynamic_cast<VspKdTreeLeaf *>(node);
 
-			for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
-					ri != leaf->rays.end(); ++ ri) 
+			for(RayInfoContainer::iterator ri = leaf->mRays.begin();
+					ri != leaf->mRays.end(); ++ ri) 
 			{
 				// unref this ray from the old node		
@@ -1305,8 +1408,8 @@
   
 	// delete the node and all its children
-	delete sroot;
-  
-	// for(VspKdTreeNode::SRayContainer::iterator ri = newLeaf->rays.begin();
-    //      ri != newLeaf->rays.end(); ++ ri)
+	DEL_PTR(sroot);
+  
+	// for(VspKdTreeNode::SRayContainer::iterator ri = newleaf->mRays.begin();
+    //      ri != newleaf->mRays.end(); ++ ri)
 	//     (*ri).ray->UnMail(2);
 
@@ -1347,6 +1450,6 @@
 		{
 			VspKdTreeLeaf *leaf = (VspKdTreeLeaf *)node;
-			for (VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin();
-				ri != leaf->rays.end(); ++ ri)
+			for (RayInfoContainer::iterator ri = leaf->mRays.begin();
+				 ri != leaf->mRays.end(); ++ ri)
 			{
 				if ((*ri).mRay->IsActive()) 
@@ -1548,2 +1651,23 @@
 	return mStat;
 }
+
+void VspKdTree::AddRays(VssRayContainer &add)
+{
+	VssRayContainer remove;
+	UpdateRays(remove, add);
+}
+ 
+// return memory usage in MB
+float VspKdTree::GetMemUsage() const 
+{
+	return 
+		(sizeof(VspKdTree) + 
+		 mStat.Leaves() * sizeof(VspKdTreeLeaf) +
+		 mStat.Interior() * sizeof(VspKdTreeInterior) +
+		 mStat.rayRefs * sizeof(RayInfo)) / (1024.0f * 1024.0f);
+}
+	
+float VspKdTree::GetRayMemUsage() const 
+{
+	return mStat.rays * (sizeof(VssRay))/(1024.0f * 1024.0f);
+}
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 419)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 420)
@@ -316,5 +316,5 @@
 	*/
 	void AddToPvs(const BoundedRayContainer &rays, int &sampleContributions,
-				  int &contributingSamples);
+				  int &contributingSamples, bool storeLeavesWithRays = false);
 
 protected:
@@ -495,4 +495,7 @@
 	void EvaluateViewCellsStats(BspViewCellsStatistics &stat) const;
 
+	/// BSP tree construction method
+	int mConstructionMethod;
+
 protected:
 
@@ -733,5 +736,5 @@
 	int ComputePvsSize(const BoundedRayContainer &rays) const;
 
-	bool TerminationCriteriaMet(const BspTraversalData &data) const;
+	inline bool TerminationCriteriaMet(const BspTraversalData &data) const;
 
 	float AccumulatedRayLength(BoundedRayContainer &rays) const;
@@ -766,62 +769,60 @@
 	bool mGenerateViewCells;
 
-	/// if rays should be stored that are piercing this view cell
-	bool mStorePiercingRays;
-
-public:
-	/** Parses the environment and stores the global BSP tree parameters
-	*/
-	static void ParseEnvironment();
+		/** Parses the environment and stores the global BSP tree parameters
+	*/
+	void ParseEnvironment();
 
 	/// maximal number of polygons before subdivision termination
-	static int sTermMaxPolygons;
+	int mTermMaxPolygons;
 	/// maximal number of rays before subdivision termination
-	static int sTermMaxRays;
+	int mTermMaxRays;
 	/// maximal possible depth
-	static int sTermMaxDepth;
+	int mTermMaxDepth;
 	/// mininum area
-	static float sTermMinArea;
+	float mTermMinArea;
 	/// mininum PVS
-	static int sTermMinPvs;
+	int mTermMinPvs;
 	/// strategy to get the best split plane
-	static int sSplitPlaneStrategy;
+	int mSplitPlaneStrategy;
 	/// number of candidates evaluated for the next split plane
-	static int sMaxPolyCandidates;
-	static int sMaxRayCandidates;
-	/// BSP tree construction method
-	static int sConstructionMethod;
+	int mMaxPolyCandidates;
+	/// number of candidates for split planes evaluated using the rays
+	int mMaxRayCandidates;
+	
 	/// maximal number of polygons for axis aligned split
-	static int sTermMaxPolysForAxisAligned;
+	int mTermMaxPolysForAxisAligned;
 	/// maximal number of rays for axis aligned split
-	static int sTermMaxRaysForAxisAligned;
+	int mTermMaxRaysForAxisAligned;
 	/// maximal number of objects for axis aligned split
-	static int sTermMaxObjectsForAxisAligned;
-
-	static float sTermMaxRayContribution;
-	static float sTermMaxAccRayLength;
-
-	static bool sStoreLeavesWithRays;
+	int mTermMaxObjectsForAxisAligned;
+	/// maximal contribution per ray
+	float mTermMaxRayContribution;
+	/// maximal accumulated ray length
+	float mTermMaxAccRayLength;
+
+	bool mStoreLeavesWithRays;
 
 	/// axis aligned split criteria
-	static float sCt_div_ci;
-	static float sSplitBorder;
-	static float sMaxCostRatio;
+	float mCt_div_ci;
+	float mSplitBorder;
+	float mMaxCostRatio;
 
 	// factors guiding the split plane heuristics
-	static float sLeastSplitsFactor;
-	static float sBalancedPolysFactor;
-	static float sBalancedViewCellsFactor;
-	static float sVerticalSplitsFactor;
-	static float sLargestPolyAreaFactor;
-	static float sBlockedRaysFactor;
-	static float sLeastRaySplitsFactor;
-	static float sBalancedRaysFactor;
-	static float sPvsFactor;
-
-	//-- thresholds used for view cells are merging
-	static int sMinPvsDif;
-	static int sMinPvs;
-	static int sMaxPvs;
-	static bool sPvsUseArea;
+	float sLeastSplitsFactor;
+	float sBalancedPolysFactor;
+	float sBalancedViewCellsFactor;
+	float sVerticalSplitsFactor;
+	float sLargestPolyAreaFactor;
+	float sBlockedRaysFactor;
+	float sLeastRaySplitsFactor;
+	float sBalancedRaysFactor;
+	float sPvsFactor;
+
+	//-- thresholds used for view cells merge
+	int mMinPvsDif;
+	int mMinPvs;
+	int mMaxPvs;
+	/// if area or accumulated ray lenght should be used for PVS heuristics
+	bool mPvsUseArea;
 
 private:
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 418)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 420)
@@ -14,45 +14,4 @@
 #include "Plane3.h"
 
-int BspTree::sMaxPolyCandidates = 10;
-int BspTree::sMaxRayCandidates = 10;
-int BspTree::sSplitPlaneStrategy = BALANCED_POLYS; 
-int BspTree::sConstructionMethod = FROM_INPUT_VIEW_CELLS;
-
-
-int BspTree::sTermMaxPolygons = 10;
-int BspTree::sTermMinPvs = 20;
-int BspTree::sTermMaxDepth = 20;
-float BspTree::sTermMinArea = 0.001f;
-int BspTree::sTermMaxPolysForAxisAligned = 50;
-int BspTree::sTermMaxObjectsForAxisAligned = 50;
-int BspTree::sTermMaxRaysForAxisAligned = -1;
-int BspTree::sTermMaxRays = -1;
-float BspTree::sTermMaxRayContribution = 0.05f;
-float BspTree::sTermMaxAccRayLength = 50;
-
-
-int BspTree::sMinPvsDif = 10;
-int BspTree::sMinPvs = 10;
-int BspTree::sMaxPvs = 500;
-
-float BspTree::sCt_div_ci = 1.0f;
-float BspTree::sSplitBorder = 1.0f;
-float BspTree::sMaxCostRatio = 0.9f;
-
-//-- factors for bsp tree split plane heuristics
-
-float BspTree::sLeastSplitsFactor = 1.0f;
-float BspTree::sBalancedPolysFactor = 1.0f;
-float BspTree::sBalancedViewCellsFactor = 1.0f;
-
-// NOTE:  very important criterium for 2.5d scenes
-float BspTree::sVerticalSplitsFactor = 1.0f;
-float BspTree::sLargestPolyAreaFactor = 1.0f;
-float BspTree::sBlockedRaysFactor = 1.0f;
-float BspTree::sLeastRaySplitsFactor = 1.0f;
-float BspTree::sBalancedRaysFactor = 1.0f;
-float BspTree::sPvsFactor = 1.0f;
-
-bool BspTree::sStoreLeavesWithRays = false;
 int BspNode::mailID = 1;
 
@@ -74,6 +33,4 @@
 */
 float BspTree::sBalancedRaysTable[] = {1, -1, 0, 0, 0};
-
-bool BspTree::sPvsUseArea = true;
 
 /****************************************************************/
@@ -271,5 +228,6 @@
 void BspLeaf::AddToPvs(const BoundedRayContainer &rays, 
 					   int &sampleContributions,
-					   int &contributingSamples)
+					   int &contributingSamples,
+					   bool storeLeavesWithRays)
 {
 	sampleContributions = 0;
@@ -296,5 +254,5 @@
 		}
 		
-		if (BspTree::sStoreLeavesWithRays)
+		if (storeLeavesWithRays)
 			// warning: intersections not ordered
 			ray->bspIntersections.push_back(Ray::BspIntersection((*it)->mMinT, this));
@@ -308,7 +266,22 @@
 
 BspTree::BspTree(BspViewCell *viewCell): 
-mRootCell(viewCell), mRoot(NULL), mGenerateViewCells(false),
-mStorePiercingRays(true)
-{
+mRootCell(viewCell), 
+mRoot(NULL), 
+mGenerateViewCells(false),
+//-- factors for bsp tree split plane heuristics
+mVerticalSplitsFactor(1.0f),
+mLargestPolyAreaFactor(1.0f),
+mBlockedRaysFactor(1.0f),
+mLeastRaySplitsFactor(1.0f),
+mBalancedRaysFactor(1.0f),
+mPvsFactor(1.0f),
+mLeastSplitsFactor(1.0f),
+mBalancedPolysFactor(1.0f),
+mBalancedViewCellsFactor(1.0f),
+//------------------------------------
+mStoreLeavesWithRays(false),
+mPvsUseArea(true)
+{
+	ParseEnvironment();
 	Randomize(); // initialise random generator for heuristics
 }
@@ -593,5 +566,5 @@
 			{
 				//store rays if needed for heuristics
-				if (sSplitPlaneStrategy & BLOCKED_RAYS)
+				if (mSplitPlaneStrategy & BLOCKED_RAYS)
 					(*it).second->mPiercingRays.push_back(ray);
 			} 
@@ -602,5 +575,5 @@
 				polys->push_back(poly);
 
-				if (sSplitPlaneStrategy & BLOCKED_RAYS)
+				if (mSplitPlaneStrategy & BLOCKED_RAYS)
 					poly->mPiercingRays.push_back(ray);
 
@@ -664,13 +637,14 @@
 }
 
-inline bool BspTree::TerminationCriteriaMet(const BspTraversalData &data) const
+bool BspTree::TerminationCriteriaMet(const BspTraversalData &data) const
 {
 	return 
-		(((int)data.mPolygons->size() <= sTermMaxPolygons) || 
-		 ((int)data.mRays->size() <= sTermMaxRays) ||
-		 (data.mPvs <= sTermMinPvs) ||
-		 (data.mArea <= sTermMinArea) ||
-		 (data.mDepth >= sTermMaxDepth) ||
-		 (((float)data.mPvs / (float)data.mRays->size()) < sTermMaxRayContribution));
+		(((int)data.mPolygons->size() <= mTermMaxPolygons) || 
+		 ((int)data.mRays->size() <= mTermMaxRays) ||
+		 (data.mPvs <= mTermMinPvs) ||
+		 (data.mArea <= mTermMinArea) ||
+		 (data.mDepth >= mTermMaxDepth) ||
+		 (((float)data.mPvs / ((float)data.mRays->size() + Limits::Small)) < 
+			mTermMaxRayContribution));
 }
 
@@ -926,6 +900,6 @@
 	float boxArea = box.SurfaceArea();
   
-	float minBand = minBox + sSplitBorder * (maxBox - minBox);
-	float maxBand = minBox + (1.0f - sSplitBorder) * (maxBox - minBox);
+	float minBand = minBox + mSplitBorder * (maxBox - minBox);
+	float maxBand = minBox + (1.0f - mSplitBorder) * (maxBox - minBox);
 	
 	float minSum = 1e20f;
@@ -968,5 +942,5 @@
   
 	float oldCost = (float)polys.size();
-	float newCost = sCt_div_ci + minSum / boxArea;
+	float newCost = mCt_div_ci + minSum / boxArea;
 	float ratio = newCost / oldCost;
 
@@ -1008,5 +982,5 @@
 	}
 	
-	if (costRatio >= sMaxCostRatio)
+	if (costRatio >= mMaxCostRatio)
 		return false;
 
@@ -1037,9 +1011,9 @@
 	}
 	
-	if ((sSplitPlaneStrategy & AXIS_ALIGNED) &&
-		((int)data.mPolygons->size() > sTermMaxPolysForAxisAligned) &&
-		((int)data.mRays->size() > sTermMaxRaysForAxisAligned) &&
-		((sTermMaxObjectsForAxisAligned < 0) || 
-		  (Polygon3::ParentObjectsSize(*data.mPolygons) > sTermMaxObjectsForAxisAligned)))
+	if ((mSplitPlaneStrategy & AXIS_ALIGNED) &&
+		((int)data.mPolygons->size() > mTermMaxPolysForAxisAligned) &&
+		((int)data.mRays->size() > mTermMaxRaysForAxisAligned) &&
+		((mTermMaxObjectsForAxisAligned < 0) || 
+		  (Polygon3::ParentObjectsSize(*data.mPolygons) > mTermMaxObjectsForAxisAligned)))
 	{
 		Plane3 plane;
@@ -1049,5 +1023,5 @@
 
 	// simplest strategy: just take next polygon
-	if (sSplitPlaneStrategy & RANDOM_POLYGON)
+	if (mSplitPlaneStrategy & RANDOM_POLYGON)
 	{
         if (!data.mPolygons->empty())
@@ -1086,5 +1060,5 @@
 	Plane3 plane;
 
-	int limit = Min((int)data.mPolygons->size(), sMaxPolyCandidates);
+	int limit = Min((int)data.mPolygons->size(), mMaxPolyCandidates);
 	
 	int candidateIdx = limit;
@@ -1116,5 +1090,5 @@
 	const BoundedRayContainer *rays = data.mRays;
 
-	for (int i = 0; i < sMaxRayCandidates / 2; ++ i)
+	for (int i = 0; i < mMaxRayCandidates / 2; ++ i)
 	{
 		candidateIdx = Random((int)rays->size());
@@ -1143,6 +1117,5 @@
 
 	//Debug << "lowest: " << lowestCost << endl;
-		
-	for (int i = 0; i < sMaxRayCandidates / 2; ++ i)
+	for (int i = 0; i < mMaxRayCandidates / 2; ++ i)
 	{
 		Vector3 pt[3];
@@ -1228,11 +1201,11 @@
 		const int classification = (*it)->ClassifyPlane(candidatePlane);
 
-		if (sSplitPlaneStrategy & BALANCED_POLYS)
+		if (mSplitPlaneStrategy & BALANCED_POLYS)
 			sumBalancedPolys += sBalancedPolysTable[classification];
 		
-		if (sSplitPlaneStrategy & LEAST_SPLITS)
+		if (mSplitPlaneStrategy & LEAST_SPLITS)
 			sumSplits += sLeastPolySplitsTable[classification];
 
-		if (sSplitPlaneStrategy & LARGEST_POLY_AREA)
+		if (mSplitPlaneStrategy & LARGEST_POLY_AREA)
 		{
 			if (classification == Polygon3::COINCIDENT)
@@ -1241,5 +1214,5 @@
 		}
 		
-		if (sSplitPlaneStrategy & BLOCKED_RAYS)
+		if (mSplitPlaneStrategy & BLOCKED_RAYS)
 		{
 			const float blockedRays = (float)(*it)->mPiercingRays.size();
@@ -1252,5 +1225,5 @@
 
 		// assign view cells to back or front according to classificaion
-		if (sSplitPlaneStrategy & BALANCED_VIEW_CELLS)
+		if (mSplitPlaneStrategy & BALANCED_VIEW_CELLS)
 		{
 			MeshInstance *viewCell = (*it)->mParent;
@@ -1291,23 +1264,25 @@
 	}
 
+	const float polysSize = (float)polys.size() + Limits::Small;
+
 	// all values should be approx. between 0 and 1 so they can be combined
 	// and scaled with the factors according to their importance
-	if ((sSplitPlaneStrategy & BALANCED_POLYS) && (!polys.empty()))
-		val += sBalancedPolysFactor * fabs(sumBalancedPolys) / (float)polys.size();
-	
-	if ((sSplitPlaneStrategy & LEAST_SPLITS) && (!polys.empty()))  
-		val += sLeastSplitsFactor * sumSplits / (float)polys.size();
-
-	if (sSplitPlaneStrategy & LARGEST_POLY_AREA) 
+	if (mSplitPlaneStrategy & BALANCED_POLYS)
+		val += sBalancedPolysFactor * fabs(sumBalancedPolys) / polysSize;
+	
+	if (mSplitPlaneStrategy & LEAST_SPLITS)  
+		val += sLeastSplitsFactor * sumSplits / polysSize;
+
+	if (mSplitPlaneStrategy & LARGEST_POLY_AREA) 
 		// HACK: polys.size should be total area so scaling is between 0 and 1
 		val += sLargestPolyAreaFactor * (float)polys.size() / sumPolyArea;
 
-	if (sSplitPlaneStrategy & BLOCKED_RAYS)
+	if (mSplitPlaneStrategy & BLOCKED_RAYS)
 		if (totalBlockedRays != 0)
 			val += sBlockedRaysFactor * (totalBlockedRays - sumBlockedRays) / totalBlockedRays;
 
-	if (sSplitPlaneStrategy & BALANCED_VIEW_CELLS)
-		if (totalViewCells != 0)
-			val += sBalancedViewCellsFactor * fabs(sumBalancedViewCells) / (float)totalViewCells;
+	if (mSplitPlaneStrategy & BALANCED_VIEW_CELLS)
+		val += sBalancedViewCellsFactor * fabs(sumBalancedViewCells) / 
+			((float)totalViewCells + Limits::Small);
 	
 	return val;
@@ -1360,5 +1335,5 @@
 	float pBack = 0;
 
-	if (sSplitPlaneStrategy & PVS)
+	if (mSplitPlaneStrategy & PVS)
 	{
 		// create three unique ids for pvs heuristics
@@ -1367,5 +1342,5 @@
 		Intersectable::NewMail(); frontAndBackId = ViewCell::sMailId;
 
-		if (sPvsUseArea) // use front and back cell areas to approximate volume
+		if (mPvsUseArea) // use front and back cell areas to approximate volume
 		{	
 			// construct child geometry with regard to the candidate split plane
@@ -1395,15 +1370,15 @@
 			ray->ClassifyPlane(candidatePlane, minT, maxT, entP, extP);
 
-		if (sSplitPlaneStrategy & LEAST_RAY_SPLITS)
+		if (mSplitPlaneStrategy & LEAST_RAY_SPLITS)
 		{
 			sumBalancedRays += sBalancedRaysTable[cf];
 		}
 		
-		if (sSplitPlaneStrategy & BALANCED_RAYS)
+		if (mSplitPlaneStrategy & BALANCED_RAYS)
 		{
 			sumRaySplits += sLeastRaySplitsTable[cf];
 		}
 
-		if (sSplitPlaneStrategy & PVS)
+		if (mSplitPlaneStrategy & PVS)
 		{
 			if (!ray->intersections.empty())
@@ -1423,5 +1398,5 @@
 			}
 
-			if (!sPvsUseArea) // use front and back cell areas to approximate volume
+			if (!mPvsUseArea) // use front and back cell areas to approximate volume
 			{
 				float len = Distance(entP, extP);
@@ -1475,14 +1450,15 @@
 	}
 
-	if ((sSplitPlaneStrategy & LEAST_RAY_SPLITS) && !rays.empty())
-			val += sLeastRaySplitsFactor * sumRaySplits / (float)rays.size();
-
-	if ((sSplitPlaneStrategy & BALANCED_RAYS) && !rays.empty())
-			val += sBalancedRaysFactor * fabs(sumBalancedRays) / (float)rays.size();
-
-	if ((sSplitPlaneStrategy & PVS) && area && pvs)
-	{
-		val += sPvsFactor * (frontPvs * pFront + (backPvs * pBack)) /
-			   (pOverall * (float)pvs * 2);
+	const float raysSize = (float)rays.size() + Limits::Small;
+	if (mSplitPlaneStrategy & LEAST_RAY_SPLITS)
+		val += sLeastRaySplitsFactor * sumRaySplits / raysSize;
+
+	if (mSplitPlaneStrategy & BALANCED_RAYS)
+		val += sBalancedRaysFactor * fabs(sumBalancedRays) /  raysSize;
+
+	float denom = pOverall * (float)pvs * 2.0f + Limits::Small;
+	if ((mSplitPlaneStrategy & PVS) && area && pvs)
+	{
+		val += sPvsFactor * (frontPvs * pFront + (backPvs * pBack)) / denom;
 
 		// give penalty to unbalanced split
@@ -1557,5 +1533,5 @@
 	float val = 0;
 
-	if (sSplitPlaneStrategy & VERTICAL_AXIS)
+	if (mSplitPlaneStrategy & VERTICAL_AXIS)
 	{
 		Vector3 tinyAxis(0,0,0); tinyAxis[mBox.Size().TinyAxis()] = 1.0f;
@@ -1567,9 +1543,9 @@
 
 	// the following criteria loop over all polygons to find the cost value
-	if ((sSplitPlaneStrategy & BALANCED_POLYS)      ||
-		(sSplitPlaneStrategy & LEAST_SPLITS)        ||
-		(sSplitPlaneStrategy & LARGEST_POLY_AREA)   ||
-		(sSplitPlaneStrategy & BALANCED_VIEW_CELLS) ||
-		(sSplitPlaneStrategy & BLOCKED_RAYS))
+	if ((mSplitPlaneStrategy & BALANCED_POLYS)      ||
+		(mSplitPlaneStrategy & LEAST_SPLITS)        ||
+		(mSplitPlaneStrategy & LARGEST_POLY_AREA)   ||
+		(mSplitPlaneStrategy & BALANCED_VIEW_CELLS) ||
+		(mSplitPlaneStrategy & BLOCKED_RAYS))
 	{
 		val += SplitPlaneCost(candidatePlane, *data.mPolygons);
@@ -1577,7 +1553,7 @@
 
 	// the following criteria loop over all rays to find the cost value
-	if ((sSplitPlaneStrategy & BALANCED_RAYS)      ||
-		(sSplitPlaneStrategy & LEAST_RAY_SPLITS)   ||
-		(sSplitPlaneStrategy & PVS))
+	if ((mSplitPlaneStrategy & BALANCED_RAYS)      ||
+		(mSplitPlaneStrategy & LEAST_RAY_SPLITS)   ||
+		(mSplitPlaneStrategy & PVS))
 	{
 		val += SplitPlaneCost(candidatePlane, *data.mRays, data.mPvs, 
@@ -1592,16 +1568,16 @@
 {
 	//-- parse bsp cell tree construction method
-	char constructionMethodStr[60];
+	/*char constructionMethodStr[60];
 	
 	environment->GetStringValue("BspTree.Construction.input", constructionMethodStr);
 
-	sConstructionMethod = FROM_INPUT_VIEW_CELLS;
+	mConstructionMethod = FROM_INPUT_VIEW_CELLS;
 	
 	if (strcmp(constructionMethodStr, "fromViewCells") == 0)
-		sConstructionMethod = FROM_INPUT_VIEW_CELLS;
+		mConstructionMethod = FROM_INPUT_VIEW_CELLS;
 	else if (strcmp(constructionMethodStr, "fromSceneGeometry") == 0)
-		sConstructionMethod = FROM_SCENE_GEOMETRY;
+		mConstructionMethod = FROM_SCENE_GEOMETRY;
 	else if (strcmp(constructionMethodStr, "fromRays") == 0)
-		sConstructionMethod = FROM_RAYS;
+		mConstructionMethod = FROM_RAYS;
 	else 
 	{
@@ -1611,28 +1587,28 @@
 
 	Debug << "Construction method: " << constructionMethodStr << endl;
-
+*/
 	//-- termination criteria for autopartition
-	environment->GetIntValue("BspTree.Termination.maxDepth", sTermMaxDepth);
-	environment->GetIntValue("BspTree.Termination.minPvs", sTermMinPvs);
-	environment->GetIntValue("BspTree.Termination.maxPolygons", sTermMaxPolygons);
-	environment->GetIntValue("BspTree.Termination.maxRays", sTermMaxRays);
-	environment->GetFloatValue("BspTree.Termination.minArea", sTermMinArea);	
-	environment->GetFloatValue("BspTree.Termination.maxRayContribution", sTermMaxRayContribution);
-	environment->GetFloatValue("BspTree.Termination.maxAccRayLenght", sTermMaxAccRayLength);
+	environment->GetIntValue("BspTree.Termination.maxDepth", mTermMaxDepth);
+	environment->GetIntValue("BspTree.Termination.minPvs", mTermMinPvs);
+	environment->GetIntValue("BspTree.Termination.maxPolygons", mTermMaxPolygons);
+	environment->GetIntValue("BspTree.Termination.maxRays", mTermMaxRays);
+	environment->GetFloatValue("BspTree.Termination.minArea", mTermMinArea);	
+	environment->GetFloatValue("BspTree.Termination.maxRayContribution", mTermMaxRayContribution);
+	environment->GetFloatValue("BspTree.Termination.maxAccRayLenght", mTermMaxAccRayLength);
 
 	//-- termination criteria for axis aligned split
-	environment->GetFloatValue("BspTree.Termination.AxisAligned.ct_div_ci", sCt_div_ci);
-	environment->GetFloatValue("BspTree.Termination.AxisAligned.maxCostRatio", sMaxCostRatio);
+	environment->GetFloatValue("BspTree.Termination.AxisAligned.ct_div_ci", mCt_div_ci);
+	environment->GetFloatValue("BspTree.Termination.AxisAligned.maxCostRatio", mMaxCostRatio);
 	environment->GetIntValue("BspTree.Termination.AxisAligned.maxPolys", 
-							 sTermMaxPolysForAxisAligned);
+							 mTermMaxPolysForAxisAligned);
 	environment->GetIntValue("BspTree.Termination.AxisAligned.maxRays", 
-							 sTermMaxRaysForAxisAligned);
+							 mTermMaxRaysForAxisAligned);
 	environment->GetIntValue("BspTree.Termination.AxisAligned.maxObjects", 
-							 sTermMaxObjectsForAxisAligned);
+							 mTermMaxObjectsForAxisAligned);
 	//-- partition criteria
-	environment->GetIntValue("BspTree.maxPolyCandidates", sMaxPolyCandidates);
-	environment->GetIntValue("BspTree.maxRayCandidates", sMaxRayCandidates);
-	environment->GetIntValue("BspTree.splitPlaneStrategy", sSplitPlaneStrategy);
-	environment->GetFloatValue("BspTree.AxisAligned.splitBorder", sSplitBorder);
+	environment->GetIntValue("BspTree.maxPolyCandidates", mMaxPolyCandidates);
+	environment->GetIntValue("BspTree.maxRayCandidates", mMaxRayCandidates);
+	environment->GetIntValue("BspTree.splitPlaneStrategy", mSplitPlaneStrategy);
+	environment->GetFloatValue("BspTree.AxisAligned.splitBorder", mSplitBorder);
 
 	environment->GetFloatValue("BspTree.Construction.sideTolerance", Vector3::sDistTolerance);
@@ -1640,38 +1616,38 @@
 
 	// post processing stuff
-	environment->GetIntValue("ViewCells.PostProcessing.minPvsDif", sMinPvsDif);
-	environment->GetIntValue("ViewCells.PostProcessing.minPvs", sMinPvs);
-	environment->GetIntValue("ViewCells.PostProcessing.maxPvs", sMaxPvs);
-
-    Debug << "BSP max depth: " << sTermMaxDepth << endl;
-	Debug << "BSP min PVS: " << sTermMinPvs << endl;
-	Debug << "BSP min area: " << sTermMinArea << endl;
-	Debug << "BSP max polys: " << sTermMaxPolygons << endl;
-	Debug << "BSP max rays: " << sTermMaxRays << endl;
-	Debug << "BSP max polygon candidates: " << sMaxPolyCandidates << endl;
-	Debug << "BSP max plane candidates: " << sMaxRayCandidates << endl;
+	environment->GetIntValue("ViewCells.PostProcessing.minPvsDif", mMinPvsDif);
+	environment->GetIntValue("ViewCells.PostProcessing.minPvs", mMinPvs);
+	environment->GetIntValue("ViewCells.PostProcessing.maxPvs", mMaxPvs);
+
+    Debug << "BSP max depth: " << mTermMaxDepth << endl;
+	Debug << "BSP min PVS: " << mTermMinPvs << endl;
+	Debug << "BSP min area: " << mTermMinArea << endl;
+	Debug << "BSP max polys: " << mTermMaxPolygons << endl;
+	Debug << "BSP max rays: " << mTermMaxRays << endl;
+	Debug << "BSP max polygon candidates: " << mMaxPolyCandidates << endl;
+	Debug << "BSP max plane candidates: " << mMaxRayCandidates << endl;
 
 	Debug << "Split plane strategy: ";
-	if (sSplitPlaneStrategy & RANDOM_POLYGON)
+	if (mSplitPlaneStrategy & RANDOM_POLYGON)
 		Debug << "random polygon ";
-	if (sSplitPlaneStrategy & AXIS_ALIGNED)
+	if (mSplitPlaneStrategy & AXIS_ALIGNED)
 		Debug << "axis aligned ";
-	if (sSplitPlaneStrategy & LEAST_SPLITS)     
+	if (mSplitPlaneStrategy & LEAST_SPLITS)     
 		Debug << "least splits ";
-	if (sSplitPlaneStrategy & BALANCED_POLYS)
+	if (mSplitPlaneStrategy & BALANCED_POLYS)
 		Debug << "balanced polygons ";
-	if (sSplitPlaneStrategy & BALANCED_VIEW_CELLS)
+	if (mSplitPlaneStrategy & BALANCED_VIEW_CELLS)
 		Debug << "balanced view cells ";
-	if (sSplitPlaneStrategy & LARGEST_POLY_AREA)
+	if (mSplitPlaneStrategy & LARGEST_POLY_AREA)
 		Debug << "largest polygon area ";
-	if (sSplitPlaneStrategy & VERTICAL_AXIS)
+	if (mSplitPlaneStrategy & VERTICAL_AXIS)
 		Debug << "vertical axis ";
-	if (sSplitPlaneStrategy & BLOCKED_RAYS)
+	if (mSplitPlaneStrategy & BLOCKED_RAYS)
 		Debug << "blocked rays ";
-	if (sSplitPlaneStrategy & LEAST_RAY_SPLITS)
+	if (mSplitPlaneStrategy & LEAST_RAY_SPLITS)
 		Debug << "least ray splits ";
-	if (sSplitPlaneStrategy & BALANCED_RAYS)
+	if (mSplitPlaneStrategy & BALANCED_RAYS)
 		Debug << "balanced rays ";
-	if (sSplitPlaneStrategy & PVS)
+	if (mSplitPlaneStrategy & PVS)
 		Debug << "pvs";
 	Debug << endl;
@@ -1719,5 +1695,5 @@
 	BspLeaf *leaf = dynamic_cast<BspLeaf *>(data.mNode);
 
-	if (data.mDepth >= sTermMaxDepth)
+	if (data.mDepth >= mTermMaxDepth)
 		++ mStat.maxDepthNodes;
 	
@@ -1734,9 +1710,9 @@
 #ifdef _DEBUG
 	Debug << "BSP stats: "
-		  << "Depth: " << data.mDepth << " (max: " << sTermMaxDepth << "), "
-		  << "PVS: " << data.mPvs << " (min: " << sTermMinPvs << "), "
-		  << "Area: " << data.mArea << " (min: " << sTermMinArea << "), "
-		  << "#polygons: " << (int)data.mPolygons->size() << " (max: " << sTermMaxPolygons << "), "
-		  << "#rays: " << (int)data.mRays->size() << " (max: " << sTermMaxRays << "), " 
+		  << "Depth: " << data.mDepth << " (max: " << mTermMaxDepth << "), "
+		  << "PVS: " << data.mPvs << " (min: " << mTermMinPvs << "), "
+		  << "Area: " << data.mArea << " (min: " << mTermMinArea << "), "
+		  << "#polygons: " << (int)data.mPolygons->size() << " (max: " << mTermMaxPolygons << "), "
+		  << "#rays: " << (int)data.mRays->size() << " (max: " << mTermMaxRays << "), " 
 		  << "#pvs: " << leaf->GetViewCell()->GetPvs().GetSize() << "=, "
 		  << "#avg ray contrib (pvs): " << (float)data.mPvs / (float)data.mRays->size() << endl;
@@ -1795,9 +1771,9 @@
 			}
 			else // ray and plane are coincident
-			// WHAT TO DO IN THIS CASE ?
 			{
-				break;
-				//node = in->GetFront();
-				//continue;
+				// WHAT TO DO IN THIS CASE ?
+				//break;
+				node = in->GetFront();
+				continue;
 			}
 
@@ -1990,9 +1966,9 @@
 	int fdiff = fvc->GetPvs().Diff(bvc->GetPvs());
 
-	if (fvc->GetPvs().GetSize() + fdiff < sMaxPvs)
-	{
-		if ((fvc->GetPvs().GetSize() < sMinPvs) ||	
-			(bvc->GetPvs().GetSize() < sMinPvs) ||
-			((fdiff < sMinPvsDif) && (bvc->GetPvs().Diff(fvc->GetPvs()) < sMinPvsDif)))
+	if (fvc->GetPvs().GetSize() + fdiff < mMaxPvs)
+	{
+		if ((fvc->GetPvs().GetSize() < mMinPvs) ||	
+			(bvc->GetPvs().GetSize() < mMinPvs) ||
+			((fdiff < mMinPvsDif) && (bvc->GetPvs().Diff(fvc->GetPvs()) < mMinPvsDif)))
 		{
 			return true;
@@ -2055,6 +2031,6 @@
 		{
 		case Ray::COINCIDENT: // TODO: should really discard ray?
-			//frontRays.push_back(bRay);
-			DEL_PTR(bRay);
+			frontRays.push_back(bRay);
+			//DEL_PTR(bRay);
 			break;
 		case Ray::BACK:
Index: trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.cpp	(revision 419)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.cpp	(revision 420)
@@ -66,5 +66,5 @@
 	// surface area substitute for probability
 	PolygonContainer geom;
-
+float overallarea = 0;
 	for (it = viewCells.begin(); it != it_end; ++ it)
 	{
@@ -72,4 +72,6 @@
 		mBspTree->ConstructGeometry(dynamic_cast<BspViewCell *>(*it), geom);
 		const float area = Polygon3::GetArea(geom);
+		if (area < 0.0001)
+			Debug << "warning, area: " << area << endl;
 		CLEAR_CONTAINER(geom);
 
@@ -92,8 +94,8 @@
 		// crossing the border of a view cell is also depending on the move speed
 		loadPvsOverhead += pCrossVc * mVcOverhead;
-
+overallarea+=area;
 		pInVcTotal += pInVc;
 	}
-
+	Debug << "overall area: " << overallarea << endl;
 	
 	renderTime /= pInVcTotal;
@@ -103,4 +105,7 @@
 	mStat.avgRenderTime = renderTime + loadPvsOverhead;
 	
+	mStat.maxCost /= pInVcTotal;
+	mStat.minCost /= pInVcTotal;
+
 	mStat.Stop();
 
@@ -183,6 +188,7 @@
     mStat.avgRtWithoutOverhead = renderTime;
 	mStat.avgRenderTime = renderTime + loadPvsOverhead;
-	mStat.maxCost /= pCrossVcTotal;
-	mStat.minCost /= pCrossVcTotal;
+
+	mStat.maxCost /= pInVcTotal;
+	mStat.minCost /= pInVcTotal;
 
 	mStat.Stop();
Index: trunk/VUT/GtpVisibilityPreprocessor/src/RayInfo.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/RayInfo.h	(revision 420)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/RayInfo.h	(revision 420)
@@ -0,0 +1,65 @@
+#ifndef __RAYINFO_H__
+#define __RAYINFO_H__
+
+#include <vector>
+using namespace std;
+
+class VssRay;
+class RayInfo;
+
+typedef vector<RayInfo> RayInfoContainer;
+/** Structure holding additional info about
+	the ray during traversal.
+*/
+class RayInfo
+{
+public:
+	/// pointer to the actual ray
+	VssRay *mRay;
+	
+	// endpoints  - do we need them?
+#if USE_FIXEDPOINT_T
+	short mMinT, mMaxT;
+#else
+	float mMinT, mMaxT;
+#endif
+	
+	RayInfo();
+	
+	RayInfo(VssRay *r);
+	
+	RayInfo(VssRay *r, const float _min, const float _max);
+	
+	RayInfo(VssRay *r, const short _min, const float _max); 
+	
+	RayInfo(VssRay *r, const float _min, const short _max);
+		
+	friend bool operator<(const RayInfo &a, const RayInfo &b) 
+	{
+		return a.mRay < b.mRay;
+	}
+	
+	
+	float ExtrapOrigin(const int axis) const;
+	
+	float ExtrapTermination(const int axis) const;
+	
+	float GetMinT () const;
+	float GetMaxT () const;
+	
+	void SetMinT (const float t);
+	
+	void SetMaxT (const float t);
+
+	/** Computes intersection of this ray with the axis aligned split plane.
+		@param axis axis of the split plane
+		@param position position of the split plane
+		@param t returns the t value of the ray intersection
+
+		@returns 0 if ray intersects plane, -1 if on back side of plane, 1 if on front side
+	*/
+	int ComputeRayIntersection(const int axis, const float position, float &t) const;
+};
+
+#endif 
+
Index: trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp	(revision 419)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp	(revision 420)
@@ -23,5 +23,5 @@
   environment->Parse(argc, argv, USE_EXE_PATH);
   MeshKdTree::ParseEnvironment();
-  BspTree::ParseEnvironment();
+  
   VspKdTree::ParseEnvironment();
 
@@ -63,7 +63,7 @@
   // a certain number of rays collected
   if (ViewCell::sHierarchy == ViewCell::BSP &&
-	  !(BspTree::sConstructionMethod == BspTree::FROM_RAYS)) 
+	  !(BspTree::mConstructionMethod == BspTree::FROM_RAYS)) 
   {
-	  if (BspTree::sConstructionMethod == BspTree::FROM_INPUT_VIEW_CELLS)
+	  if (BspTree::mConstructionMethod == BspTree::FROM_INPUT_VIEW_CELLS)
 	  {
 		  // view cells input file name
Index: trunk/VUT/GtpVisibilityPreprocessor/src/RayInfo.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/RayInfo.cpp	(revision 420)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/RayInfo.cpp	(revision 420)
@@ -0,0 +1,111 @@
+#include "RayInfo.h"
+#include "Ray.h"
+#include "VssRay.h"
+
+RayInfo::RayInfo(): mRay(NULL) 
+{}
+		
+RayInfo::RayInfo(VssRay *r):mRay(r), mMinT(0),
+#if USE_FIXEDPOINT_T
+#define FIXEDPOINT_ONE 0x7FFE
+	// mMaxT(0xFFFF)
+	mMaxT(FIXEDPOINT_ONE)
+#else
+	mMaxT(1.0f)
+#endif
+{}
+		
+RayInfo::RayInfo(VssRay *r,	const float _min, const float _max):
+mRay(r) 
+{
+	SetMinT(_min);
+	SetMaxT(_max);
+}
+		
+RayInfo::RayInfo(VssRay *r, const short _min, const float _max):
+mRay(r), mMinT(_min) 
+{
+	SetMaxT(_max);
+}
+		
+RayInfo::RayInfo(VssRay *r,	const float _min, const short _max): 
+mRay(r), mMaxT(_max) 
+{
+	SetMinT(_min);
+}
+		
+float RayInfo::ExtrapOrigin(const int axis) const 
+{
+	return mRay->GetOrigin(axis) + GetMinT()*mRay->GetDir(axis);
+}
+		
+float RayInfo::ExtrapTermination(const int axis) const 
+{
+	return mRay->GetOrigin(axis) + GetMaxT()*mRay->GetDir(axis);
+}
+		
+#if USE_FIXEDPOINT_T
+	float RayInfo::GetMinT () const 
+	{ 
+		return mMinT/(float)(FIXEDPOINT_ONE); 
+	}
+
+	float RayInfo::GetMaxT() const 
+	{ 
+		return mMaxT / (float)(FIXEDPOINT_ONE); 
+	}
+		
+	void RayInfo::SetMinT (const float t) 
+	{
+		mMinT = (short) (t * (float)(FIXEDPOINT_ONE));
+	}
+		
+	void RayInfo::SetMaxT (const float t) 
+	{
+		mMaxT = (short) (t*(float)(FIXEDPOINT_ONE));
+		++ mMaxT;
+		//      if (mMaxT!=0xFFFF)
+		//	mMaxT++;
+	}
+#else
+	float RayInfo::GetMinT () const 
+	{ 
+		return mMinT; 
+	}
+	
+	float RayInfo::GetMaxT () const 
+	{ 
+		return mMaxT; 
+	}
+		
+	void RayInfo::SetMinT (const float t) 
+	{ 
+		mMinT = t; 
+	}
+	
+	void RayInfo::SetMaxT (const float t) 
+	{ 
+		mMaxT = t; 
+	}
+	
+#endif 
+
+int RayInfo::ComputeRayIntersection(const int axis, const float position, float &t) const
+{		
+	// intersect the ray with the plane
+	const float denom = mRay->GetDir(axis);
+
+	if (fabs(denom) < 1e-20)
+		//if (denom == 0.0f)
+		return (mRay->GetOrigin(axis) > position) ? 1 : -1;
+
+	t = (position - mRay->GetOrigin(axis)) / denom;
+
+	if (t < GetMinT())
+		return (denom > 0) ? 1 : -1;
+
+	if (t > GetMaxT())
+		return (denom > 0) ? -1 : 1;
+
+	return 0;
+}
Index: trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.h	(revision 419)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.h	(revision 420)
@@ -31,75 +31,75 @@
 #include "Ray.h"
 
-// --------------------------------------------------------------
-// Static statistics for kd-tree search
-// --------------------------------------------------------------
+#include "RayInfo.h"
+
+
+/**
+	Static statistics for vsp kd-tree search
+*/
 class VspKdStatistics:  public StatisticsBase
 {
 public:  
-  // total number of nodes
-  int nodes;
-  // number of splits along each of the axes
-  int splits[7];
-  // totals number of rays
-  int rays;
+	// total number of nodes
+	int nodes;
+	// number of splits along each of the axes
+	int splits[7];
+	// totals number of rays
+	int rays;
 	// initial size of the pvs
-  int initialPvsSize;
+	int initialPvsSize;
 	// total number of query domains
-  int queryDomains;
-  // total number of ray references
-  int rayRefs;
+	int queryDomains;
+	// total number of ray references
+	int rayRefs;
 
 	// max depth nodes
-  int maxDepthNodes;
-  // max depth nodes
-  int minPvsNodes;
-  int minRaysNodes;
+	int maxDepthNodes;
+	// max depth nodes
+	int minPvsNodes;
+	int minRaysNodes;
 	// max ray contribution nodes
-  int maxRayContribNodes;
+	int maxRayContribNodes;
 	// max depth nodes
-  int minSizeNodes;
-	
-  // max number of rays per node
-  int maxRayRefs;
-  // number of dynamically added ray refs
-  int addedRayRefs;
-  // number of dynamically removed ray refs
-  int removedRayRefs;
-  
-  // Constructor
-  VspKdStatistics() 
-  {
-	  Reset();
-  }
-
-  int Nodes() const {return nodes;}
-  int Interior() const { return nodes/2; }
-  int Leaves() const { return (nodes/2) + 1; }
-
-  void Reset() 
-  {
-	  nodes = 0;
-	  for (int i=0; i<7; i++)
-		  splits[i] = 0;
-	  rays = queryDomains = 0;
-	  rayRefs = 0;
-	  maxDepthNodes = 0;
-	  minPvsNodes = 0;
-	  minRaysNodes = 0; 
-	  maxRayRefs = 0;
-	  addedRayRefs = removedRayRefs = 0;
-	  initialPvsSize = 0;
-	  maxRayContribNodes = 0;
-	  minSizeNodes = 0;
-  }
-  
-  void
-  Print(ostream &app) const;
-
-  friend ostream &operator<<(ostream &s, const VspKdStatistics &stat) {
-    stat.Print(s);
-    return s;
-  }
-  
+	int minSizeNodes;
+	
+	// max number of rays per node
+	int maxRayRefs;
+	// number of dynamically added ray refs
+	int addedRayRefs;
+	// number of dynamically removed ray refs
+	int removedRayRefs;
+  
+	/** Default constructor.
+	*/
+	VspKdStatistics() {	Reset(); }
+	int Nodes() const { return nodes; }
+	int Interior() const { return nodes / 2; }
+	int Leaves() const { return (nodes / 2) + 1; }
+
+	void Reset() 
+	{
+		nodes = 0;
+
+		for (int i=0; i<7; i++)
+			splits[i] = 0;
+
+		rays = queryDomains = 0;
+		rayRefs = 0;
+		maxDepthNodes = 0;
+		minPvsNodes = 0;
+		minRaysNodes = 0; 
+		maxRayRefs = 0;
+		addedRayRefs = removedRayRefs = 0;
+		initialPvsSize = 0;
+		maxRayContribNodes = 0;
+		minSizeNodes = 0;
+	}
+
+	void Print(ostream &app) const;
+	friend ostream &operator<<(ostream &s, const VspKdStatistics &stat) 
+	{
+	    stat.Print(s);
+	    return s;
+	}  
 };
 
@@ -108,7 +108,6 @@
 
 
-// --------------------------------------------------------------
-// KD-tree node - abstract class
-// --------------------------------------------------------------
+/** Abstract superclass of Vsp-Kd-Tree nodes.
+*/
 class VspKdTreeNode
 {
@@ -118,152 +117,51 @@
 #define USE_FIXEDPOINT_T 1
 
-struct RayInfo
-{
-	// pointer to the actual ray
-	VssRay *mRay;
-	
-	// endpoints  - do we need them?
-#if USE_FIXEDPOINT_T
-	short mMinT, mMaxT;
-#else
-	float mMinT, mMaxT;
-#endif
-	
-	RayInfo():mRay(NULL) {}
-	
-	RayInfo(VssRay *r):mRay(r), mMinT(0),
-#if USE_FIXEDPOINT_T
-#define FIXEDPOINT_ONE 0x7FFE
-	// mMaxT(0xFFFF)
-		mMaxT(FIXEDPOINT_ONE)
-#else
-		mMaxT(1.0f)
-#endif
-	{}
-	
-	RayInfo(VssRay *r,
-			const float _min,
-			const float _max
-			):mRay(r) 
-	{
-		SetMinT(_min);
-		SetMaxT(_max);
-	}
-	
-	RayInfo(VssRay *r,
-			const short _min,
-			const float _max):mRay(r), mMinT(_min) 
-	{
-		SetMaxT(_max);
-	}
-	
-	RayInfo(VssRay *r,
-			const float _min,
-			const short _max):
-	mRay(r), mMaxT(_max) 
-	{
-		SetMinT(_min);
-	}
-	
-	friend bool operator<(const RayInfo &a, const RayInfo &b) {
-		return a.mRay < b.mRay;
-	}
-  
-	
-	float ExtrapOrigin(const int axis) const {
-		return mRay->GetOrigin(axis) + GetMinT()*mRay->GetDir(axis);
-	}
-	
-	float ExtrapTermination(const int axis) const {
-		return mRay->GetOrigin(axis) + GetMaxT()*mRay->GetDir(axis);
-	}
-	
-#if USE_FIXEDPOINT_T
-	float GetMinT () const { return mMinT/(float)(FIXEDPOINT_ONE); }
-	float GetMaxT () const { return mMaxT/(float)(FIXEDPOINT_ONE); }
-	
-	void SetMinT (const float t) {
-		mMinT = (short) (t*(float)(FIXEDPOINT_ONE));
-	}
-	
-	void SetMaxT (const float t) {
-		mMaxT = (short) (t*(float)(FIXEDPOINT_ONE));
-		mMaxT++;
-		//      if (mMaxT!=0xFFFF)
-		//	mMaxT++;
-	}
-#else
-	float GetMinT () const { return mMinT; }
-	float GetMaxT () const { return mMaxT; }
-	
-	void SetMinT (const float t) { mMinT = t; }
-	void SetMaxT (const float t) { mMaxT = t; }
-#endif 
-
-
-	int ComputeRayIntersection(const int axis, const float position, float &t) const 
-	{		
-		// intersect the ray with the plane
-		float denom = mRay->GetDir(axis);
-    
-		if (fabs(denom) < 1e-20)
-			//if (denom == 0.0f)
-			return (mRay->GetOrigin(axis) > position) ? 1 : -1;
-    
-		t = (position - mRay->GetOrigin(axis))/denom;
-
-		if (t < GetMinT())
-			return (denom > 0) ? 1 : -1;
-
-		if (t > GetMaxT())
-			return (denom > 0) ? -1 : 1;
-
-		return 0;
-	}
-
-
-};
-
-
-typedef vector<RayInfo> RayInfoContainer;
-
-enum {EInterior, ELeaf};
-
-  /////////////////////////////////
-  // The actual data goes here
-  
-  // link to the parent
-  VspKdTreeInterior *mParent;
-
-  enum {SPLIT_X=0, SPLIT_Y, SPLIT_Z, SPLIT_DIRX, SPLIT_DIRY, SPLIT_DIRZ};
-  
-  // splitting axis
-  char mAxis;
-	
-  // depth
-  unsigned char mDepth;
-  
-  //  short depth;
-  //
-  /////////////////////////////////
-  
-  inline VspKdTreeNode(VspKdTreeInterior *p);
-
-  
-  virtual ~VspKdTreeNode() {};
-  virtual int Type() const = 0;
-  
-
-  bool IsLeaf() const { return mAxis == -1; }
-  
-  virtual void Print(ostream &s) const = 0;
-
-  virtual int GetAccessTime() 
-  {
-	  return 0x7FFFFFF;
-  }
-
-  
-	
+	enum {EInterior, ELeaf};
+
+	/** Constructs new interior node from the parent node.
+	*/
+	inline VspKdTreeNode(VspKdTreeInterior *p);
+
+	/** Destroys this node and the subtree.
+	*/
+	virtual ~VspKdTreeNode();
+
+	/** Type of the node (Einterior or ELeaf)
+	*/
+	virtual int Type() const = 0;
+ 
+	/** Returns true if this node is a leaf.
+	*/
+	bool IsLeaf() const;
+	
+	/** Prints node stats.
+	*/
+	virtual void Print(ostream &s) const = 0;
+
+	/** Returns time needed to access this node.
+	*/
+	virtual int GetAccessTime(); // NOTE: don't really know how it is used!
+
+	/** Returns parent node.
+	*/
+	VspKdTreeInterior *GetParent() const;
+	/** Sets parent node.
+	*/
+	void SetParent(VspKdTreeInterior *p);
+
+protected:
+	/////////////////////////////////
+	// The actual data goes here
+  
+	/// link to the parent
+	VspKdTreeInterior *mParent;
+
+	enum {SPLIT_X = 0, SPLIT_Y, SPLIT_Z, SPLIT_DIRX, SPLIT_DIRY, SPLIT_DIRZ};
+  
+	/// splitting axis
+	char mAxis;
+	
+	/// depth
+	unsigned char mDepth;
 };
 
@@ -276,4 +174,6 @@
 	friend class VspKdTree;
 
+	/** Constructs new interior node from parent node.
+	*/
 	VspKdTreeInterior(VspKdTreeInterior *p);
 			
@@ -286,13 +186,23 @@
 	virtual void Print(ostream &s) const;
 
+	/** Returns back child.
+	*/
 	inline VspKdTreeNode *GetBack() const;
+	/** Returns front child.
+	*/
 	inline VspKdTreeNode *GetFront() const;
 
 protected:
 
+	/** Sets pointers to back child and front child.
+	*/
 	void SetupChildLinks(VspKdTreeNode *b, VspKdTreeNode *f);
- 
+
+	/** Replaces the pointer to oldChild with a pointer to newChild.
+	*/
 	void ReplaceChildLink(VspKdTreeNode *oldChild, VspKdTreeNode *newChild);
  
+	/** Computes intersection of the ray with the node boundaries.
+	*/
 	int ComputeRayIntersection(const RayInfo &rayData, float &t);
 
@@ -321,83 +231,58 @@
 	friend class VspKdTree;
 
+	/** Constructs leaf from parent node.
+		@param p the parent node
+		@param nRays preallocates memory to store this number of rays
+	*/
+	VspKdTreeLeaf(VspKdTreeInterior *p,	const int nRays);
+	
+	virtual ~VspKdTreeLeaf();
+
+	virtual int Type() const;  
+
+	virtual void Print(ostream &s) const;
+  
+	/** Adds a ray to the leaf ray container.
+	*/
+	void AddRay(const RayInfo &data);
+	/** Returns size of the leaf PVS as induced by the rays
+		@note returns precomputed PVS size, which may not be valid
+		anymore. Run UpdatePvsSize to get a valid PVS.
+	*/
+	int GetPvsSize() const;
+	void SetPvsSize(const int s);
+
+	/** If PVS is not valid, this function recomputes the leaf 
+		PVS as induced by the rays.
+	*/
+	void UpdatePvsSize();
+
+	void Mail();
+
+	bool Mailed() const;
+  
+	bool Mailed(const int mail);
+
+	/** Returns average contribution of a ray to the PVS
+	*/
+	inline float GetAvgRayContribution() const;
+	/** Returns square of average contribution of a ray.
+	*/
+	inline float GetSqrRayContribution() const;
+
+	static void NewMail();
+
 	static int mailID;
-	int mailbox;
-  
-	RayInfoContainer rays;
+
+protected:
+	
+	int mMailbox;
+  
+	RayInfoContainer mRays;
 	bool mValidPvs;
 	
-	VspKdTreeLeaf(VspKdTreeInterior *p,	const int nRays):
-	VspKdTreeNode(p), rays(), mPvsSize(0), mValidPvs(false) 
-	{
-		rays.reserve(nRays);
-	}
-	
-	virtual ~VspKdTreeLeaf() { }
-
-	virtual int Type() const  
-	{ 
-		return ELeaf; 
-	}
-
-	virtual void Print(ostream &s) const 
-	{
-		s << endl << "L: r = " << (int)rays.size() << endl;
-	};
-  
-	void AddRay(const RayInfo &data) 
-	{
-		mValidPvs = false;
-		rays.push_back(data);
-		data.mRay->Ref();
-	}
-	
-	int GetPvsSize() const 
-	{
-		return mPvsSize;
-	}
-	void SetPvsSize(const int s) 
-	{
-		mPvsSize = s;
-	}
-
-	void UpdatePvsSize();
-
-	void Mail() 
-	{ 
-		mailbox = mailID; 
-	}
-  
-	static void NewMail() 
-	{ 
-		++ mailID; 
-	}
-  
-	bool Mailed() const 
-	{ 
-		return mailbox == mailID; 
-	}
-  
-	bool Mailed(const int mail) 
-	{
-		return mailbox >= mailID + mail;
-	}
-
-	float GetAvgRayContribution() const 
-	{
-		return GetPvsSize()/((float)rays.size() + Limits::Small);
-	}
-
-	float GetSqrRayContribution() const 
-	{
-		return sqr(GetPvsSize()/((float)rays.size() + Limits::Small));
-	}
 private:
 	int mPvsSize;
 };
-
-// Inline functions
-inline VspKdTreeNode::VspKdTreeNode(VspKdTreeInterior *p):
-mParent(p), mAxis(-1), mDepth(p ? p->mDepth + 1 : 0) 
-{}
 
 
@@ -501,14 +386,14 @@
   };
   
-  // simplified data for ray traversal only...
-
+  /** Simplified data for ray traversal only.
+  */
   struct RayTraversalData 
   {
-	  VspKdTreeNode::RayInfo mRayData;
+	  RayInfo mRayData;
 	  VspKdTreeNode *mNode;
       
 	  RayTraversalData() {}
 	  
-	  RayTraversalData(VspKdTreeNode *n, const VspKdTreeNode::RayInfo &data):
+	  RayTraversalData(VspKdTreeNode *n, const RayInfo &data):
 	  mRayData(data), mNode(n) {}
   };
@@ -521,13 +406,55 @@
 	virtual void Construct(VssRayContainer &rays,
 						   AxisAlignedBox3 *forcedBoundingBox = NULL);
-	
-	// incemental construction
+
+	/** Returns bounding box of the specified node.
+	*/
+	AxisAlignedBox3 GetBBox(VspKdTreeNode *node) const;
+
+	const VspKdStatistics &GetStatistics() const;
+
+	/** Get the root of the tree.
+	*/
+	VspKdTreeNode *GetRoot() const;
+
+	/** Returns average PVS size in tree.
+	*/
+	float GetAvgPvsSize();
+
+	/** Parses the environment and stores the global VspKd tree parameters
+	*/
+	static void ParseEnvironment();
+
+	/////////////////////////////
+	// Construction parameters
+
+	/// max depth of the tree
+	static int sTermMaxDepth;
+
+	/// minimal ratio of the volume of the cell and the query volume
+	static float sTermMinSize;
+
+	/// minimal pvs per node to still get subdivided
+	static int sTermMinPvs;
+
+	/// minimal ray number per node to still get subdivided
+	static int sTermMinRays;
+	
+	/// maximal cost ration to subdivide a node
+	static float sTermMaxCostRatio;
+	
+	/// maximal contribution per ray to subdivide the node
+	static float sTermMaxRayContribution;
+
+	/** Returns memory usage in MB.
+	*/
+	float GetMemUsage() const;
+	
+	float GetRayMemUsage() const;
+
+protected:
+	// incremental construction
 	virtual void UpdateRays(VssRayContainer &remove, VssRayContainer &add);
 
-	virtual void AddRays(VssRayContainer &add)
-	{
-		VssRayContainer remove;
-		UpdateRays(remove, add);
-	}
+	virtual void AddRays(VssRayContainer &add);
 
 	VspKdTreeNode *Locate(const Vector3 &v);
@@ -549,21 +476,5 @@
 
 	void SortSplitCandidates(VspKdTreeLeaf *node,
-							 const int axis);
-	
-  
-	// return memory usage in MB
-	float GetMemUsage() const 
-	{
-		return 
-			(sizeof(VspKdTree) + 
-			 mStat.Leaves() * sizeof(VspKdTreeLeaf) +
-			 mStat.Interior() * sizeof(VspKdTreeInterior) +
-			 mStat.rayRefs * sizeof(VspKdTreeNode::RayInfo)) / (1024.0f*1024.0f);
-	}
-	
-	float GetRayMemUsage() const 
-	{
-		return mStat.rays * (sizeof(VssRay))/(1024.0f * 1024.0f);
-	}
+							 const int axis);	
   
 	float BestCostRatioHeuristic(VspKdTreeLeaf *node,
@@ -591,5 +502,4 @@
 						int &pvsFront);
 
-	AxisAlignedBox3 GetBBox(VspKdTreeNode *node) const; 	
 
 	VspKdTreeNode * SubdivideLeaf(VspKdTreeLeaf *leaf,
@@ -619,40 +529,7 @@
 					 SimpleRayContainer &rays);
 
-	float GetAvgPvsSize();
-
-	/** Get the root of the tree.
-	*/
-	VspKdTreeNode *GetRoot() const;
-
 	int CollapseSubtree(VspKdTreeNode *sroot, const int time);
-
-	const VspKdStatistics &GetStatistics() const;
 	
 	int ReleaseMemory(const int time);
-
-	/** Parses the environment and stores the global BSP tree parameters
-	*/
-	static void ParseEnvironment();
-
-	/////////////////////////////
-	// Construction parameters
-
-	// max depth of the tree
-	static int sTermMaxDepth;
-
-	// minimal ratio of the volume of the cell and the query volume
-	static float sTermMinSize;
-
-	// minimal pvs per node to still get subdivided
-	static int sTermMinPvs;
-
-	// minimal ray number per node to still get subdivided
-	static int sTermMinRays;
-	
-	// maximal cost ration to subdivide a node
-	static float sTermMaxCostRatio;
-	
-	// maximal contribution per ray to subdivide the node
-	static float sTermMaxRayContribution;
 
 protected:
Index: trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp	(revision 419)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp	(revision 420)
@@ -61,5 +61,5 @@
 	ObjectContainer objects;
 	
-	switch (BspTree::sConstructionMethod)
+	switch (mBspTree->mConstructionMethod)
 	{
 	case BspTree::FROM_INPUT_VIEW_CELLS:
@@ -181,32 +181,42 @@
 	}
 
-	if (ViewCell::sHierarchy == ViewCell::BSP)
+	switch(ViewCell::sHierarchy)
 	{
-		// cast ray to BSP tree to get intersection with view cells
-		if (mBspTree)
-		{
-			mBspTree->CastRay(ray);
-			
-			if (object)
-				sampleContributions += AddObjectSamples(object, ray);
-			
-			if (!ray.intersections.empty()) // second intersection found
-			{
-				sampleContributions += 
-					AddObjectSamples(ray.intersections[0].mObject, ray);
-			}
-		}
-	}
-	else {
-		if (ray.kdLeaves.size()) {
+	case ViewCell::BSP:
+		
+		//-- cast ray to BSP tree to get intersection with view cells
+		if (!mBspTree)
+			break;
+		
+		mBspTree->CastRay(ray);
+			
+		if (object)
+			sampleContributions += AddObjectSamples(object, ray);
+			
+		if (!ray.intersections.empty()) // second intersection found
+		{
+			sampleContributions += 
+				AddObjectSamples(ray.intersections[0].mObject, ray);
+		}
+		break;
+	case ViewCell::KD:
+		if (ray.kdLeaves.size()) 
+		{
 			Intersectable *terminator =
 				ray.intersections.size() ? ray.intersections[0].mObject: NULL;
 
 			sampleContributions += AddNodeSamples(ray,
-																						object,
-																						terminator);
-		}
-	}
-	
+																					object,
+																					terminator);
+		}
+		break;
+	case ViewCell::VSP:
+		// TODO:
+		break;
+	default:
+		Debug << "Should never come here" << endl;
+		break;
+	}
+
 	return sampleContributions;
 }
@@ -573,6 +583,19 @@
 			if (exporter)
 			{
+				exporter->SetWireframe();
 				exporter->ExportBspLeaves(*mBspTree, stat.maxPvs);
 				//exporter->ExportBspViewCellPartition(*mBspTree, 0);
+				
+				if (1) // export scene geometry
+				{
+					Material m;//= RandomMaterial();
+					m.mDiffuseColor = RgbColor(0, 1, 0);
+					exporter->SetForcedMaterial(m);
+					exporter->SetWireframe();
+	
+					for (int j = 0; j < objects.size(); ++ j)
+						exporter->ExportIntersectable(objects[j]);
+				}
+					
 				delete exporter;
 			}
@@ -756,5 +779,5 @@
 	if (!mBspTree)
 	{
-		if ((BspTree::sConstructionMethod == BspTree::FROM_RAYS) &&
+		if ((BspTree::mConstructionMethod == BspTree::FROM_RAYS) &&
 			((int)mSampleRays.size() < mBspConstructionSamples))
 		{
@@ -866,5 +889,5 @@
 					outRays.push_back(mSampleRays[i]);
 			}
-			if (BspTree::sConstructionMethod == BspTree::FROM_RAYS)
+			if (BspTree::mConstructionMethod == BspTree::FROM_RAYS)
 			{
 				// export rays 
