Index: GTP/trunk/Lib/Vis/Preprocessing/src/SubdivisionCandidate.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/SubdivisionCandidate.h	(revision 1473)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/SubdivisionCandidate.h	(revision 1576)
@@ -38,8 +38,36 @@
 	/** Position in queue.
 	*/
-	int GetPosition() const
+	inline int GetPosition() const
 	{
 		return mPosition;
 	}
+
+	inline void SetSplitAxis(const int splitAxis)
+	{
+		mSplitAxis = splitAxis;
+	}
+	inline void SetMaxCostMisses(const int misses)
+	{
+		mMaxCostMisses = misses;
+	}
+	inline void SetPvsEntriesIncr(const int pvsEntriesIncr)
+	{
+		mPvsEntriesIncr = pvsEntriesIncr;
+	}
+
+	inline int GetSplitAxis() const
+	{
+		return mSplitAxis;
+	}
+	inline int GetMaxCostMisses() const
+	{
+		return mMaxCostMisses;
+	}
+	inline int GetPvsEntriesIncr() const
+	{
+		return mPvsEntriesIncr;
+	}
+
+protected:
 
 	/// split axis of this plane (0, 1, 2, or 3 if non-axis-aligned)
@@ -47,10 +75,8 @@
 	/// the number of misses of max cost ratio until this split
 	int mMaxCostMisses;
-
-protected:
-
 	/// render cost decrease achieved through this split
 	float mRenderCostDecrease;
-	
+	/// the decrease of the number of pvs entries
+	int mPvsEntriesIncr;
 };
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h	(revision 1571)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h	(revision 1576)
@@ -692,6 +692,6 @@
 	int mMaxFilterSize;
 	
-	
-
+	// only for debugging
+VssRayContainer storedRays;
 	//////////////////
 	//-- visualization options
@@ -1027,5 +1027,5 @@
 };
 
-#define TEST_EVALUATION 0
+#define TEST_EVALUATION 1
 
 /**
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 1545)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 1576)
@@ -2165,7 +2165,7 @@
 	
 	RegisterOption("VspTree.Construction.renderCostDecreaseWeight",
-			optFloat,
-			"vsp_construction_render_cost_decrease_weight=",
-			"0.99");
+				optFloat,
+				"vsp_construction_render_cost_decrease_weight=",
+				"0.99");
 
 	RegisterOption("VspTree.Termination.maxDepth",
@@ -2188,26 +2188,26 @@
 					optFloat,
 					"vsp_term_min_probability=",
-					"0.001");
+					"0.0000001");
 
 	RegisterOption("VspTree.Termination.maxRayContribution",
-			optFloat,
-			"vsp_term_ray_contribution=",
-			"0.9");
+				optFloat,
+				"vsp_term_ray_contribution=",
+				"0.9");
 	
 	RegisterOption("VspTree.Termination.maxCostRatio",
-		optFloat,
-		"vsp_term_max_cost_ratio=",
-		"1.5");
+				optFloat,
+				"vsp_term_max_cost_ratio=",
+				"1.5");
 	
 	RegisterOption("VspTree.Termination.maxViewCells",
-		optInt,
-		"vsp_term_max_view_cells=",
-		"10000");
+				optInt,
+				"vsp_term_max_view_cells=",
+				"10000");
 
 	
 	RegisterOption("VspTree.Termination.missTolerance",
-		optInt,
-		"vsp_term_miss_tolerance=",
-		"4");
+				optInt,
+				"vsp_term_miss_tolerance=",
+				"4");
 
 	RegisterOption("VspTree.Termination.minGlobalCostRatio",
@@ -2237,22 +2237,22 @@
 
 	RegisterOption("VspTree.maxStaticMemory", 
-		optFloat, 
-		"vsp_max_static_mem=", 
-		"8.0");
+					optFloat, 
+					"vsp_max_static_mem=", 
+					"8.0");
 
 	RegisterOption("VspTree.useCostHeuristics",
-		optBool,
-		"vsp_use_cost_heuristics=",
-		"false");
+					optBool,
+					"vsp_use_cost_heuristics=",
+					"false");
 
 	RegisterOption("VspTree.simulateOctree", 
-		optBool, 
-		"vsp_simulate_octree=", 
-		"false");
+					optBool, 
+					"vsp_simulate_octree=", 
+					"false");
 
 	RegisterOption("VspTree.Construction.randomize", 
-		optBool, 
-		"vsp_construction_randomize=", 
-		"false");
+					optBool, 
+					"vsp_construction_randomize=", 
+					"false");
 
 	RegisterOption("VspTree.subdivisionStats",
@@ -2398,5 +2398,5 @@
 					optFloat,
 					"bvh_term_min_objects=",
-					"0.00001");
+					"0.0000001");
 
 	RegisterOption("BvHierarchy.Termination.minRays",
@@ -2515,4 +2515,9 @@
 					"hierarchy_construction_multilevel=",
 					"false");
+
+	RegisterOption("Hierarchy.Construction.levels",
+					optInt,
+					"hierarchy_construction_levels=",
+					"4");
 
 	/////////////////////////////////////////////////////////////////
Index: GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.h	(revision 1563)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.h	(revision 1576)
@@ -49,5 +49,8 @@
 {
 public:
-
+	/// total number of entries in the pvs
+	int pvsEntries;
+	/// storage cost
+	int memory;
 	/// total number of nodes
 	int nodes;
@@ -81,4 +84,6 @@
 		accumDepth = 0;
 		repairTime = 0;
+		memory = 0;
+		pvsEntries = 0;
 	}
 
@@ -255,5 +260,6 @@
 		const int splits,
 		const float renderCostDecr,
-		const float totalRenderCost);
+		const float totalRenderCost,
+		const int totalPvsEntries);
 
 	void CollectObjectSpaceDirtyList();
@@ -343,11 +349,15 @@
 
 	////////
-	//-- global criteria
+	//-- global termination criteria
+
 	float mTermMinGlobalCostRatio;
 	int mTermGlobalCostMissTolerance;
 	
+	////////////////////
+
 	/// keeps track of cost during subdivision
 	float mTotalCost;
 
+	int mTotalPvsEntries;
 	HierarchyStatistics mHierarchyStats;
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.h	(revision 1570)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.h	(revision 1576)
@@ -36,6 +36,5 @@
 class VspTree;
 class KdTreeStatistics;
-//class SubdivisionCandidate;
-//class VspSubdivisionCandidate;
+
 
 /** View space partition statistics.
@@ -781,4 +780,10 @@
 	int EvalPvsSize(const RayInfoContainer &rays) const;
 
+	int EvalPvsEntriesIncr(VspSubdivisionCandidate &splitCandidate) const;
+
+	/** Returns number of effective entries in the pvs.
+	*/
+	int EvalPvsEntriesSize(const RayInfoContainer &rays) const;
+	int EvalPvsEntriesContribution(const VssRay &ray, const bool isTermination) const;
 	/** Computes best cost for axis aligned planes.
 	*/
@@ -845,4 +850,12 @@
 			      RayInfoContainer &frontRays, 
 				  RayInfoContainer &backRays) const;
+
+	void UpdatePvsEntriesContribution(
+		const VssRay &ray,
+		const bool isTermination,
+		const int cf,
+		float &frontPvs,
+		float &backPvs,
+		float &totalPvs) const;
 
 	/** Classfifies the object with respect to the 
@@ -880,5 +893,6 @@
 		float &frontPvs,
 		float &backPvs,
-		float &totalPvs) const;
+		float &totalPvsm,
+		const bool countEntries = false) const;
 
 	/** Evaluates the contribution for kd leaves.
Index: GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp	(revision 1571)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp	(revision 1576)
@@ -369,6 +369,6 @@
 
     // how often was max cost ratio missed in this branch?
-	frontData.mMaxCostMisses = sc.mMaxCostMisses;
-	backData.mMaxCostMisses = sc.mMaxCostMisses;
+	frontData.mMaxCostMisses = sc.GetMaxCostMisses();
+	backData.mMaxCostMisses = sc.GetMaxCostMisses();
 	
 	// assign the objects in sorted order
@@ -475,7 +475,7 @@
 	const bool maxCostRatioViolated = mTermMaxCostRatio < ratio;
 
-	splitCandidate.mMaxCostMisses = maxCostRatioViolated ? 
+	splitCandidate.SetMaxCostMisses(maxCostRatioViolated ? 
 		splitCandidate.mParentData.mMaxCostMisses + 1 :
-		splitCandidate.mParentData.mMaxCostMisses;
+		splitCandidate.mParentData.mMaxCostMisses);
 
 	const float oldProp = EvalViewCellsVolume(leaf->mObjects);
@@ -488,4 +488,5 @@
 
 	const float renderCostDecr = oldRenderCost - newRenderCost;
+	const int pvsEntriesIncr = EvalPvsEntriesIncr(splitCandidate);
 
 #ifdef _DEBUG
@@ -494,5 +495,7 @@
 	Debug << "render cost decrease: " << renderCostDecr << endl;
 #endif
+
 	splitCandidate.SetRenderCostDecrease(renderCostDecr);
+	splitCandidate.SetPvsEntriesIncr(EvalPvsEntriesIncr(splitCandidate));
 
 #if 1
@@ -510,4 +513,15 @@
 
 
+int BvHierarchy::EvalPvsEntriesIncr(BvhSubdivisionCandidate &splitCandidate) const
+{
+	const int oldPvsSize = CountViewCells(splitCandidate.mParentData.mNode->mObjects);
+	
+	const int fPvsSize = CountViewCells(splitCandidate.mFrontObjects);
+	const int bPvsSize = CountViewCells(splitCandidate.mBackObjects);
+
+	return fPvsSize + bPvsSize - oldPvsSize;
+}
+
+
 inline bool BvHierarchy::LocalTerminationCriteriaMet(const BvhTraversalData &data) const
 {
@@ -515,7 +529,6 @@
 	return ( 0
 		|| ((int)data.mNode->mObjects.size() <= mTermMinObjects)
-		|| (data.mProbability <= mTermMinProbability)
-		|| (data.mDepth >= mTermMaxDepth)
-		|| (data.mNumRays <= mTermMinRays)
+		//|| (data.mProbability <= mTermMinProbability)
+		//|| (data.mNumRays <= mTermMinRays)
 		 );
 }
@@ -1063,4 +1076,5 @@
 	return vol;
 }
+
 ///////////////////////////////////////////////////////////
 
@@ -1289,5 +1303,5 @@
 			return 0.0f;
 
-		////////////////////
+		////////////////
 		//-- surface area heuristics
 
@@ -1298,8 +1312,9 @@
 	}
 	else
-	{	////////////////////
+	{	///////////////
 		//-- render cost heuristics
 
 		const float viewSpaceVol = mViewCellsManager->GetViewSpaceBox().GetVolume();
+
 		// probability that view point lies in a view cell which sees this node
 		const float p = EvalViewCellsVolume(objects) / viewSpaceVol;	
@@ -1404,5 +1419,6 @@
 		for (vit = tmpViewCells.begin(); vit != vit_end; ++ vit)
 		{
-			VspViewCell *vc = dynamic_cast<VspViewCell *>(*vit);
+			//VspViewCell *vc = dynamic_cast<VspViewCell *>(*vit);
+			ViewCell *vc = *vit;
 
 			// store view cells
@@ -1426,4 +1442,58 @@
 		}
 	}
+}
+
+
+int BvHierarchy::CountViewCells(Intersectable *obj) const
+{
+	int result = 0;
+	
+	VssRayContainer::const_iterator rit, rit_end = obj->mVssRays.end();
+
+	for (rit = obj->mVssRays.begin(); rit < rit_end; ++ rit)
+	{
+		VssRay *ray = (*rit);
+		ViewCellContainer tmpViewCells;
+	
+		mHierarchyManager->mVspTree->GetViewCells(*ray, tmpViewCells);
+		
+		ViewCellContainer::const_iterator vit, vit_end = tmpViewCells.end();
+		for (vit = tmpViewCells.begin(); vit != vit_end; ++ vit)
+		{
+			ViewCell *vc = *vit;
+
+			// store view cells
+			if (!vc->Mailed())
+			{
+				vc->Mail();
+				++ result;
+			}
+		}
+	}
+
+	return result;
+}
+
+
+int BvHierarchy::CountViewCells(const ObjectContainer &objects) const
+{
+	// no view cells yet
+	if (mHierarchyManager->GetViewSpaceSubdivisionType() == 
+		HierarchyManager::NO_VIEWSPACE_SUBDIV)
+		return 1;
+
+	int nViewCells = 0;
+
+	ViewCell::NewMail();
+
+	ObjectContainer::const_iterator oit, oit_end = objects.end();
+
+	// loop through all object and collect view cell pvs of this node
+	for (oit = objects.begin(); oit != oit_end; ++ oit)
+	{
+		nViewCells += CountViewCells(*oit);
+	}
+
+	return nViewCells;
 }
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1571)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1576)
@@ -4774,5 +4774,4 @@
 
 	int sampleContributions = 0;
-
 	VssRayContainer sampleRays;
 
@@ -4792,5 +4791,12 @@
 	mHierarchyManager->Construct(constructionRays, objects, &mViewSpaceBox);
 
-	
+#if TEST_EVALUATION
+	VssRayContainer::const_iterator tit, tit_end = constructionRays.end();
+	for (tit = constructionRays.begin(); tit != tit_end; ++ tit)
+	{
+		storedRays.push_back(new VssRay(*(*tit)));
+	}
+#endif
+
 	/////////////////////////
 	//-- print satistics for subdivision and view cells
@@ -4800,11 +4806,4 @@
 	ResetViewCells();
 	Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
-
-	if (0)
-	{
-		OUT_STREAM stream("osptree.xml.zip");
-		mHierarchyManager->ExportObjectSpaceHierarchy(stream);
-	}	
-
 
 	//////////////
@@ -5573,5 +5572,4 @@
 }
 
-//#define TEST_EVALUATION
 
 #if TEST_EVALUATION
@@ -5587,5 +5585,5 @@
 
 	// should directional sampling be used?
-	const bool dirSamples = (mEvaluationSamplingType == Preprocessor::DIRECTION_BASED_DISTRIBUTION);
+	const bool dirSamples = (mEvaluationSamplingType == SamplingStrategy::DIRECTION_BASED_DISTRIBUTION);
 
 	cout << "reseting pvs ... ";
@@ -5649,5 +5647,5 @@
 	}
 
-	Debug << "\nrendercost hack: " << rc / mHierarchyManager->GetViewSpaceBox() << endl;
+	Debug << "\nrendercost hack: " << rc / mViewSpaceBox.GetVolume() << endl;
 	mViewCellsTree->ExportStats(fileName);
 	cout << "finished" << endl;
Index: GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 1548)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 1576)
@@ -724,4 +724,13 @@
 		const bool setCounter = false) const;
 
+	/** Counts the view cells of this object. note: only
+		counts unmailed objects.
+	*/
+	int CountViewCells(Intersectable *obj) const;
+
+	/** Counts the view cells seen by this bvh leaf
+	*/
+	int CountViewCells(const ObjectContainer &objects) const;
+
 	/** Collects view cells which see an object.
 	*/
@@ -731,4 +740,8 @@
 		const bool useMailBoxing,
 		const bool setCounter = false) const;
+
+	/** Evaluates increase in pvs size.
+	*/
+	int EvalPvsEntriesIncr(BvhSubdivisionCandidate &splitCandidate) const;
 
 	/** Rays will be clipped to the bounding box.
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.cpp	(revision 1571)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.cpp	(revision 1576)
@@ -616,6 +616,7 @@
 void VspTree::CreateViewCell(VspTraversalData &tData, const bool updatePvs)
 {
+	///////////////
 	//-- create new view cell
-	VspLeaf *leaf = dynamic_cast<VspLeaf *>(tData.mNode);
+	VspLeaf *leaf = tData.mNode;
 	
 	VspViewCell *viewCell = new VspViewCell();
@@ -627,5 +628,5 @@
 	if (updatePvs)
 	{
-		//-- update pvs of view cell
+		// update pvs of view cell
 		AddSamplesToPvs(leaf, *tData.mRays, sampCon, conSamp);
 
@@ -642,9 +643,10 @@
 		///////////
 		//-- store sampling rays
-		RayInfoContainer::const_iterator it, it_end = tData.mRays->end();
+        RayInfoContainer::const_iterator it, it_end = tData.mRays->end();
 
 		for (it = tData.mRays->begin(); it != it_end; ++ it)
 		{
 			(*it).mRay->Ref();			
+			// note: should rather store rays with view cell
 			leaf->mVssRays.push_back((*it).mRay);
 		}
@@ -689,5 +691,5 @@
 		// create new interior node and two leaf node
 		const AxisAlignedPlane splitPlane = sc->mSplitPlane;
-		const int maxCostMisses = sc->mMaxCostMisses;
+		const int maxCostMisses = sc->GetMaxCostMisses();
 
 		newNode = SubdivideNode(splitPlane, tData, tFrontData, tBackData);
@@ -788,7 +790,7 @@
 
 	// max cost threshold violated?
-	splitCandidate.mMaxCostMisses = maxCostRatioViolated  ? 
+	splitCandidate.SetMaxCostMisses(maxCostRatioViolated  ? 
 			splitCandidate.mParentData.mMaxCostMisses + 1:
-			splitCandidate.mParentData.mMaxCostMisses;
+			splitCandidate.mParentData.mMaxCostMisses);
 	
 	float oldRenderCost;
@@ -800,4 +802,8 @@
 
 	splitCandidate.SetRenderCostDecrease(renderCostDecr);
+
+	// the increase in pvs entries num induced by this split
+	const int pvsEntriesIncr = EvalPvsEntriesIncr(splitCandidate);
+	splitCandidate.SetPvsEntriesIncr(pvsEntriesIncr);
 
 #if 0
@@ -814,4 +820,33 @@
 
 
+int VspTree::EvalPvsEntriesIncr(VspSubdivisionCandidate &splitCandidate) const
+{
+	float oldPvsSize = 0;
+	float fPvsSize = 0;
+	float bPvsSize = 0;
+	
+	AxisAlignedPlane candidatePlane = splitCandidate.mSplitPlane;
+	RayInfoContainer::const_iterator rit, 
+		rit_end = splitCandidate.mParentData.mRays->end();
+
+	// this is the main ray classification loop!
+	for(rit = splitCandidate.mParentData.mRays->begin(); rit != rit_end; ++ rit)
+	{
+		VssRay *ray = (*rit).mRay;
+		RayInfo rayInf = *rit;
+		
+		float t;
+		// classify ray
+		const int cf = 
+			rayInf.ComputeRayIntersection(candidatePlane.mAxis, 
+										  candidatePlane.mPosition, t);
+
+		UpdatePvsEntriesContribution(*ray, true, cf, fPvsSize, bPvsSize, oldPvsSize);
+	}
+	
+	return (int)(fPvsSize + bPvsSize - oldPvsSize);
+}
+
+
 VspInterior *VspTree::SubdivideNode(const AxisAlignedPlane &splitPlane,
 									VspTraversalData &tData,
@@ -836,10 +871,8 @@
 			  *backData.mRays);
 
-	/////////////
 	//-- compute pvs
 	frontData.mPvs = EvalPvsSize(*frontData.mRays);
 	backData.mPvs = EvalPvsSize(*backData.mRays);
-	//Debug << "f pvs: " << frontData.mPvs << " b pvs: " << backData.mPvs << " pvs " << tData.mPvs << endl;
-	
+		
 	//-- split front and back node geometry and compute area
 	tData.mBoundingBox.Split(splitPlane.mAxis, 
@@ -851,13 +884,14 @@
 	backData.mProbability = tData.mProbability - frontData.mProbability;
 
-	// update some stats
-	// store maximal depth
+
+	////////
+	//-- update some stats
+	
 	if (tData.mDepth > mVspStats.maxDepth)
-	{
-		//Debug << "max depth increases to " << tData.mDepth << " at " << mVspStats.Leaves() << " leaves" << endl;
+	{	//Debug << "max depth increases to " << tData.mDepth << " at " << mVspStats.Leaves() << " leaves" << endl;
 		mVspStats.maxDepth = tData.mDepth;
 	}
 
-	// two more leaves
+	// two more leaves per split
 	mVspStats.nodes += 2;
 	/// and a new split
@@ -865,5 +899,5 @@
 
 
-    ///////////////////////
+	////////////////
 	//-- create front and back and subdivide further
 
@@ -902,5 +936,4 @@
 	CreateViewCell(frontData, false);
 	CreateViewCell(backData, false);
-
 
 #if WORK_WITH_VIEWCELL_PVS
@@ -1436,4 +1469,5 @@
 	// mark objects in the front / back / both using mailboxing
 	// then count pvs sizes
+
 	Intersectable::NewMail(3);
 	KdLeaf::NewMail(3);
@@ -1497,4 +1531,5 @@
 		  << "render cost decrease: " << renderCostDecrease << endl;
 #endif
+
 	return renderCostDecrease;
 }
@@ -1519,5 +1554,4 @@
 
 	const int pvsSize = data.mPvs;
-
 	RayInfoContainer::const_iterator rit, rit_end = data.mRays->end();
 
@@ -1535,7 +1569,6 @@
 	}
 
-
+	//////////////
 	//-- evaluate cost heuristics
-
 	float pOverall = data.mProbability;
 
@@ -1555,64 +1588,13 @@
 
 
-void VspTree::UpdateContributionsToPvs(Intersectable *obj,
-									   const int cf,
-									   float &frontPvs,
-									   float &backPvs,
-									   float &totalPvs) const
-{
-	if (!obj) return;
-
-	//const float renderCost = mViewCellsManager->SimpleRay &raynderCost(obj);
-	const int renderCost = 1;
-
-	// object in no pvs => new
-	if (!obj->Mailed() && !obj->Mailed(1) && !obj->Mailed(2))
-	{
-		totalPvs += renderCost;
-	}
-
-	// QUESTION matt: is it safe to assume that 
-	// the object belongs to no pvs in this case?
-	//if (cf == Ray::COINCIDENT) return;
-
-	if (cf >= 0) // front pvs
-	{
-		if (!obj->Mailed() && !obj->Mailed(2))
-		{
-			frontPvs += renderCost;
-		
-			// already in back pvs => in both pvss
-			if (obj->Mailed(1))
-				obj->Mail(2);
-			else
-				obj->Mail();
-		}
-	}
-
-	if (cf <= 0) // back pvs
-	{
-		if (!obj->Mailed(1) && !obj->Mailed(2))
-		{
-			backPvs += renderCost;
-		
-			// already in front pvs => in both pvss
-			if (obj->Mailed())
-				obj->Mail(2);
-			else
-				obj->Mail(1);
-		}
-	}
-}
-
-
 void VspTree::UpdateContributionsToPvs(BvhLeaf *leaf,
 									   const int cf,
 									   float &frontPvs,
 									   float &backPvs,
-									   float &totalPvs) const
+									   float &totalPvs,
+									   const bool countEntries) const
 {
 	if (!leaf) return;
-
-	const int renderCost = (int)leaf->mObjects.size();
+	const int renderCost = countEntries ? 1 : (int)leaf->mObjects.size();
 
 	// leaf in no pvs => new
@@ -1621,8 +1603,4 @@
 		totalPvs += renderCost;
 	}
-
-	// QUESTION matt: is it safe to assume that 
-	// the leaf belongs to no pvs in this case?
-	//if (cf == Ray::COINCIDENT) return;
 
 	if (cf >= 0) // front pvs
@@ -1684,8 +1662,4 @@
     }	
 	
-	// QUESTION matt: is it safe to assume that 
-	// the object belongs to no pvs in this case?
-	//if (cf == Ray::COINCIDENT) return;
-
 	if (cf >= 0) // front pvs
 	{
@@ -2146,4 +2120,81 @@
 
 
+int VspTree::EvalPvsEntriesContribution(const VssRay &ray, 
+										const bool isTermination) const
+
+{
+		Intersectable *obj; 
+		Vector3 pt;
+		KdNode *node;
+
+		ray.GetSampleData(isTermination, pt, &obj, &node);
+		if (!obj) return 0;
+
+		switch(mHierarchyManager->GetObjectSpaceSubdivisionType())
+		{
+		case HierarchyManager::NO_OBJ_SUBDIV:
+		{
+			if (!obj->Mailed())
+			{
+				obj->Mail();
+				return 1;
+			}
+			
+			return 0;
+		}
+
+		case HierarchyManager::KD_BASED_OBJ_SUBDIV:
+		{
+			KdLeaf *leaf = mHierarchyManager->mOspTree->GetLeaf(pt, node);
+			if (!leaf->Mailed())
+			{
+				leaf->Mail();
+				return 1;
+			}
+			
+			return 0;
+		}
+	case HierarchyManager::BV_BASED_OBJ_SUBDIV:
+		{
+			BvhLeaf *bvhleaf = mHierarchyManager->mBvHierarchy->GetLeaf(obj);
+
+			if (!bvhleaf->Mailed())
+			{
+				bvhleaf->Mail();
+				return 1;
+			}
+			
+			return 0;
+		}
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+
+int VspTree::EvalPvsEntriesSize(const RayInfoContainer &rays) const
+{
+	int pvsSize = 0;
+
+	Intersectable::NewMail();
+	KdNode::NewMail();
+	BvhLeaf::NewMail();
+
+	RayInfoContainer::const_iterator rit, rit_end = rays.end();
+
+	for (rit = rays.begin(); rit != rays.end(); ++ rit)
+	{
+		VssRay *ray = (*rit).mRay;
+
+		pvsSize += EvalPvsEntriesContribution(*ray, true);
+		pvsSize += EvalPvsEntriesContribution(*ray, false);
+	}
+
+	return pvsSize;
+}
+
+
 float VspTree::GetEpsilon() const
 {
@@ -2991,6 +3042,33 @@
 
 
-int VspTree::EvalContributionToPvs(const VssRay &ray, 
-								   const bool isTermination) const
+void VspTree::UpdatePvsEntriesContribution(const VssRay &ray,
+										   const bool isTermination,
+										   const int cf,
+										   float &frontPvs,
+										   float &backPvs,
+										   float &totalPvs) const
+{
+	/*ray.GetSampleData(isTermination, pt, &obj, &node);
+	if (!obj) return 0;
+
+	switch (mHierarchyManager->GetObjectSpaceSubdivisionType())
+	{
+	case HierarchyManager::KD_BASED_OBJ_SUBDIV:
+		// TODO
+		break;
+	case HierarchyManager::BV_BASED_OBJ_SUBDIV:
+		{
+			BvhLeaf *leaf = mHierarchyManager->mBvHierarchy->GetLeaf(obj);
+			UpdateContributionsToPvs(leaf, true, cf, pvsFront, pvsBack, totalPvs, true);	        
+			break;
+		}
+	default:
+		UpdateContributionsToPvs(obj, true, cf, pvsFront, pvsBack, totalPvs, true);	
+		break;
+	}*/
+}
+
+
+int VspTree::EvalContributionToPvs(const VssRay &ray, const bool isTermination) const
 {	
 	Intersectable *obj; 
@@ -3018,5 +3096,4 @@
 		{
 			KdLeaf *leaf = mHierarchyManager->mOspTree->GetLeaf(pt, node);
-
 			pvs += EvalContributionToPvs(leaf);
 			break;
@@ -3048,4 +3125,5 @@
 	leaf->Mail();
 
+	// this is the pvs which is uniquely part of this kd leaf
 	int pvs = (int)(leaf->mObjects.size() - leaf->mMultipleObjects.size());
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/GvsPreprocessor.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/GvsPreprocessor.cpp	(revision 1572)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/GvsPreprocessor.cpp	(revision 1576)
@@ -81,5 +81,5 @@
 bool GvsPreprocessor::HandleRay(VssRay *vssRay)
 {
-	cout << "\nhere12 " << (int)vssRay->mFlags << endl;
+	cout << "x " << (int)vssRay->mFlags;
 	const bool storeRaysForViz = true;
 	mViewCellsManager->ComputeSampleContribution(*vssRay, true, storeRaysForViz);
@@ -367,5 +367,5 @@
 	// add samples to ray queue
 	VssRayContainer::const_iterator vit, vit_end = samples.end();
-		for (vit = samples.begin(); vit != vit_end; ++ vit)
+	for (vit = samples.begin(); vit != vit_end; ++ vit)
 	{
 		HandleRay(*vit);
Index: GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp	(revision 1564)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp	(revision 1576)
@@ -146,7 +146,11 @@
 
 	if (mOspTree)
+	{
 		mOspTree->SetViewCellsManager(vcm);
+	}
 	else if (mBvHierarchy)
+	{
 		mBvHierarchy->SetViewCellsManager(vcm);
+	}
 }
 
@@ -179,5 +183,5 @@
 		return mBvHierarchy->mBoundingBox;
 	default:
-		// empty box
+		// hack: empty box
 		return AxisAlignedBox3();
 	}
@@ -198,25 +202,9 @@
 	const float costDecr = tData.GetRenderCostDecrease();
 
-	switch (mObjectSpaceSubdivisionType)
-	{
-	case KD_BASED_OBJ_SUBDIV:
-		AddSubdivisionStats(mOspTree->mOspStats.Leaves() + mVspTree->mVspStats.Leaves(),
-							costDecr,
-							mTotalCost
-							);
-		break;
-	case BV_BASED_OBJ_SUBDIV:
-		AddSubdivisionStats(mBvHierarchy->mBvhStats.Leaves() + mVspTree->mVspStats.Leaves(),
-							costDecr,
-							mTotalCost
-							);
-		break;
-	default:
-		AddSubdivisionStats(mVspTree->mVspStats.Leaves(),
-							costDecr,
-							mTotalCost
-							);
-		break;
-	}
+	AddSubdivisionStats(mHierarchyStats.Leaves(),
+						costDecr,
+						mTotalCost,
+						mTotalPvsEntries
+						);
 }
 
@@ -224,11 +212,12 @@
 void HierarchyManager::AddSubdivisionStats(const int splits,
 										   const float renderCostDecr,
-										   const float totalRenderCost)
+										   const float totalRenderCost,
+										   const int pvsEntries)
 {
 	mSubdivisionStats
 			<< "#Splits\n" << splits << endl
 			<< "#RenderCostDecrease\n" << renderCostDecr << endl 
+			<< "#TotalPvsEntries\n" << pvsEntries << endl
 			<< "#TotalRenderCost\n" << totalRenderCost << endl;
-			//<< "#AvgRenderCost\n" << avgRenderCost << endl;
 }
 
@@ -525,8 +514,9 @@
 		{
 			cout << mCurrentCandidate->Type() << " ";
-			if (0) cout << "subdividing candidate " << ++ i << " of type " 
-						<< mCurrentCandidate->Type() << endl;
+		
+			// update stats
 			mHierarchyStats.nodes += 2;
-
+			mHierarchyStats.pvsEntries += mCurrentCandidate->GetPvsEntriesIncr();
+			mHierarchyStats.memory += 0; // TODO
 			// subdivision successful
 			EvalSubdivisionStats(*mCurrentCandidate);
@@ -534,5 +524,8 @@
 			// reevaluate candidates affected by the split for view space splits, 
 			// this would be object space splits and other way round
-			if (repairQueue) RepairQueue();
+			if (repairQueue) 
+			{	
+				RepairQueue();
+			}
 		}
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/OspTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/OspTree.cpp	(revision 1570)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/OspTree.cpp	(revision 1576)
@@ -433,5 +433,5 @@
 								tBackData);
 	
-		const int maxCostMisses = sc->mMaxCostMisses;
+		const int maxCostMisses = sc->GetMaxCostMisses();
 
         // how often was max cost ratio missed in this branch?
@@ -505,4 +505,5 @@
 	splitCandidate.SetRenderCostDecrease(renderCostDecr);
 
+	const float pvsSizeIncr = 0; // todo
 #if 0
 	const float priority = (float)-data.mDepth;
@@ -518,7 +519,7 @@
 	splitCandidate.SetPriority(priority);
 
-	splitCandidate.mMaxCostMisses = 
-		success ? splitCandidate.mParentData.mMaxCostMisses : 
-	splitCandidate.mParentData.mMaxCostMisses + 1;
+	splitCandidate.SetMaxCostMisses(success ? 
+		splitCandidate.mParentData.mMaxCostMisses : 
+		splitCandidate.mParentData.mMaxCostMisses + 1);
 }
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.cpp	(revision 1520)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.cpp	(revision 1576)
@@ -62,7 +62,5 @@
 {	
 	Vector3 origin, direction; 
-
     const int i = (int)RandomValue(0, (Real)((int)mPreprocessor.mObjects.size() - 1));
-
 	Intersectable *object = mPreprocessor.mObjects[i];
 	
@@ -95,5 +93,4 @@
 	 
 	direction = UniformRandomVector();
-
 	const float c = Magnitude(direction);
 
