Index: /GTP/trunk/Lib/Vis/Preprocessing/EvalStats/EvalStats.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/EvalStats/EvalStats.cpp	(revision 827)
+++ /GTP/trunk/Lib/Vis/Preprocessing/EvalStats/EvalStats.cpp	(revision 1291)
@@ -13,9 +13,9 @@
 using namespace std;
 
+
+
 /** This is a small function which takes two log files and computes the
 	difference in percent of the weighted render cost.
 */
-
-
 struct RenderStats 
 {
@@ -105,6 +105,4 @@
 
 	statsOut << "#ViewCells\n" << index + 1 << endl
-			 //<< "#TotalRenderCostGain\n" << 100.0f - costRatio * 100.0f << endl
-			 //<< "#AvgRenderCostGain\n" << 100.0f - avgCostRatio * 100.0f << endl << endl;
 			 << "#TotalRenderCostRatio\n" << costRatio << endl
 			 << "#AvgRenderCostRatio\n" << avgCostRatio << endl << endl;
@@ -149,5 +147,5 @@
 		float val;
 
-		// soecial cases
+		// special cases
 		if (j == 0)
 		{
@@ -178,10 +176,6 @@
 		}
 
-		// lower bound
-		//int j = max (0, i - 1);
-		//cout << "i: " << i << " j: " << j << endl;
 		float ratio = (i && val) ? (float)i / val : 1;
 
-		//cout << "ratio: " << ratio << endl;
 		outstream << "#Pass\n" << i << endl;
 		outstream << "#RenderCost\n" << renderCost << endl;
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.h	(revision 1278)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.h	(revision 1291)
@@ -618,5 +618,4 @@
 	int	_CastRay(Ray &ray);
 
-
 	int	CastLineSegment(const Vector3 &origin,
 						const Vector3 &termination,
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 1288)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 1291)
@@ -3410,6 +3410,5 @@
 	float mint = 0.0f, maxt = 1.0f;
 
-	Intersectable::NewMail();
-	ViewCell::NewMail();
+	//ViewCell::NewMail();
 
 	Vector3 entp = origin;
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.cpp	(revision 1233)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.cpp	(revision 1291)
@@ -2061,6 +2061,5 @@
 	float mint = 0.0f, maxt = 1.0f;
 
-	Intersectable::NewMail();
-	ViewCell::NewMail();
+	//ViewCell::NewMail();
 
 	Vector3 entp = origin;
@@ -2131,5 +2130,5 @@
 				viewcells.push_back(leaf->mViewCell);
 				leaf->mViewCell->Mail();
-				hits++;
+				++ hits;
 			}
 		
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 1288)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 1291)
@@ -41,65 +41,66 @@
 	int n = 200;
 
-	if (0){
-	// form grid of boxes
-	for (int i = 0; i < n; ++ i)
-	{
-		for (int j = 0; j < n; ++ j)
+	if (0)
+	{
+		// form grid of boxes
+		for (int i = 0; i < n; ++ i)
 		{
-			const Vector3 scale2((float)j * 0.8f / n + 0.1f,  0.05f, (float)i * 0.8f  / (float)n + 0.1f);
-		
-			const Vector3 pt2 = sceneBox.Min() + scale2 * (sceneBox.Max() - sceneBox.Min());
-		
-			const Vector3 boxSize = sceneBox.Size() * Vector3(0.0025f, 0.01f, 0.0025f);
-			AxisAlignedBox3 box(pt2, pt2 + boxSize);
+			for (int j = 0; j < n; ++ j)
+			{
+				const Vector3 scale2((float)j * 0.8f / n + 0.1f,  0.05f, (float)i * 0.8f  / (float)n + 0.1f);
+
+				const Vector3 pt2 = sceneBox.Min() + scale2 * (sceneBox.Max() - sceneBox.Min());
+
+				const Vector3 boxSize = sceneBox.Size() * Vector3(0.0025f, 0.01f, 0.0025f);
+				AxisAlignedBox3 box(pt2, pt2 + boxSize);
+				Mesh *mesh = CreateMeshFromBox(box);
+
+				mesh->Preprocess();
+
+				MeshInstance *mi = new MeshInstance(mesh);
+				scene->mRoot->mGeometry.push_back(mi);
+			}
+		}
+
+		for (int i = 0; i < n; ++ i)
+		{
+			for (int j = 0; j < n; ++ j)
+			{
+				const Vector3 scale2(0.15f, (float)j * 0.8f / n + 0.1f, (float)i * 0.8f  / (float)n + 0.1f);
+
+				Vector3 pt2 = sceneBox.Min() + scale2 * (sceneBox.Max() - sceneBox.Min());
+
+				Vector3 boxSize = sceneBox.Size() * Vector3(0.0025f, 0.01f, 0.0025f);
+				AxisAlignedBox3 box(pt2, pt2 + boxSize);
+				Mesh *mesh = CreateMeshFromBox(box);
+
+				mesh->Preprocess();
+
+				MeshInstance *mi = new MeshInstance(mesh);
+				scene->mRoot->mGeometry.push_back(mi);
+			}
+		}
+
+		for (int i = 0; i < n; ++ i)
+		{
+			const Vector3 scale2(2, 0.2f, (float)i * 0.8f  / (float)n + 0.1f);
+
+			Vector3 pt2 = sceneBox.Min() + scale2 * (sceneBox.Max() - sceneBox.Min());
+
+			//Vector3 boxSize = sceneBox.Size() * Vector3(0.0025, 0.01, 0.0025);
+			Vector3 boxSize = sceneBox.Size() * Vector3(0.005f, 0.02f, 0.005f);
+
+			AxisAlignedBox3 box(pt2 + 0.1f, pt2 + boxSize);
 			Mesh *mesh = CreateMeshFromBox(box);
 
 			mesh->Preprocess();
-		
+
 			MeshInstance *mi = new MeshInstance(mesh);
 			scene->mRoot->mGeometry.push_back(mi);
 		}
-	}
-
-	for (int i = 0; i < n; ++ i)
-	{
-		for (int j = 0; j < n; ++ j)
-		{
-			const Vector3 scale2(0.15f, (float)j * 0.8f / n + 0.1f, (float)i * 0.8f  / (float)n + 0.1f);
-		
-			Vector3 pt2 = sceneBox.Min() + scale2 * (sceneBox.Max() - sceneBox.Min());
-		
-			Vector3 boxSize = sceneBox.Size() * Vector3(0.0025f, 0.01f, 0.0025f);
-			AxisAlignedBox3 box(pt2, pt2 + boxSize);
-			Mesh *mesh = CreateMeshFromBox(box);
-
-			mesh->Preprocess();
-		
-			MeshInstance *mi = new MeshInstance(mesh);
-			scene->mRoot->mGeometry.push_back(mi);
-		}
-	}
-
-	for (int i = 0; i < n; ++ i)
-	{
-		const Vector3 scale2(2, 0.2f, (float)i * 0.8f  / (float)n + 0.1f);
-		
-		Vector3 pt2 = sceneBox.Min() + scale2 * (sceneBox.Max() - sceneBox.Min());
-		
-		//Vector3 boxSize = sceneBox.Size() * Vector3(0.0025, 0.01, 0.0025);
-		Vector3 boxSize = sceneBox.Size() * Vector3(0.005f, 0.02f, 0.005f);
-
-		AxisAlignedBox3 box(pt2 + 0.1f, pt2 + boxSize);
-		Mesh *mesh = CreateMeshFromBox(box);
-
-		mesh->Preprocess();
-		
-		MeshInstance *mi = new MeshInstance(mesh);
-		scene->mRoot->mGeometry.push_back(mi);
-	}
-	
-	scene->mRoot->UpdateBox();
-	}
-		
+
+		scene->mRoot->UpdateBox();
+	}
+
 	if (1)
 	{
@@ -111,10 +112,10 @@
 		Plane3 cuttingPlane(Vector3(1, 0, 0), pt);
 		Mesh *planeMesh = new Mesh();
-		
+
 		Polygon3 *poly = sceneBox.CrossSection(cuttingPlane);
 		IncludePolyInMesh(*poly, *planeMesh);
-		
+
 		planeMesh->Preprocess();
-		
+
 		MeshInstance *planeMi = new MeshInstance(planeMesh);
 		scene->mRoot->mGeometry.push_back(planeMi);
@@ -145,7 +146,6 @@
 	Environment::GetSingleton()->GetBoolValue("Preprocessor.detectEmptyViewSpace", mDetectEmptyViewSpace);
 	Environment::GetSingleton()->GetBoolValue("Preprocessor.exportVisibility", mExportVisibility );
-//#if GTP_INTERNAL // choose other ray cast method
 	Environment::GetSingleton()->GetIntValue("Preprocessor.rayCastMethod", mRayCastMethod);
-//#endif
+
 	char buffer[256];
 	Environment::GetSingleton()->GetStringValue("Preprocessor.visibilityFile",  buffer);
@@ -163,36 +163,36 @@
 Preprocessor::~Preprocessor()
 {
-  cout << "cleaning up" << endl;
-
-  cout << "Deleting view cells manager ... \n";
-  DEL_PTR(mViewCellsManager);
-  cout << "done.\n";
-
-  cout << "Deleting bsp tree ... \n";
-  DEL_PTR(mBspTree);
-  cout << "done.\n";
-
-  cout << "Deleting kd tree...\n";
-  DEL_PTR(mKdTree);
-  cout << "done.\n";
- 
-  cout << "Deleting vsp tree...\n";
-  DEL_PTR(mVspTree);
-  cout << "done.\n";
-
-  cout << "Deleting hierarchy manager...\n";
-  DEL_PTR(mHierarchyManager);
-  cout << "done.\n";
-
-  cout << "Deleting vspbsp tree...\n";
-  DEL_PTR(mVspBspTree);
-  cout << "done.\n";
-
-   cout << "Deleting scene graph...\n";
-  DEL_PTR(mSceneGraph);
-  cout << "done.\n";
-
-  DEL_PTR(mRenderSimulator);
-  DEL_PTR(renderer);
+	cout << "cleaning up" << endl;
+
+	cout << "Deleting view cells manager ... \n";
+	DEL_PTR(mViewCellsManager);
+	cout << "done.\n";
+
+	cout << "Deleting bsp tree ... \n";
+	DEL_PTR(mBspTree);
+	cout << "done.\n";
+
+	cout << "Deleting kd tree...\n";
+	DEL_PTR(mKdTree);
+	cout << "done.\n";
+
+	cout << "Deleting vsp tree...\n";
+	DEL_PTR(mVspTree);
+	cout << "done.\n";
+
+	cout << "Deleting hierarchy manager...\n";
+	DEL_PTR(mHierarchyManager);
+	cout << "done.\n";
+
+	cout << "Deleting vspbsp tree...\n";
+	DEL_PTR(mVspBspTree);
+	cout << "done.\n";
+
+	cout << "Deleting scene graph...\n";
+	DEL_PTR(mSceneGraph);
+	cout << "done.\n";
+
+	DEL_PTR(mRenderSimulator);
+	DEL_PTR(renderer);
 }
 
@@ -461,4 +461,5 @@
 	if (strcmp(name, "osp") == 0)
 	{
+		Debug << "hierarchy manager: osp" << endl;
 		// HACK for testing if per kd evaluation works!!
 		const bool ishack = true;
@@ -470,5 +471,11 @@
 	else if (strcmp(name, "bvh") == 0)
 	{
+		Debug << "hierarchy manager: bvh" << endl;
 		hierarchyManager = new HierarchyManager(mVspTree, HierarchyManager::BV_BASED_OBJ_SUBDIV);
+	}
+	else // only view space partition
+	{
+		Debug << "hierarchy manager: obj" << endl;
+		hierarchyManager = new HierarchyManager(mVspTree, HierarchyManager::NO_OBJ_SUBDIV);
 	}
 
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.h	(revision 1289)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.h	(revision 1291)
@@ -548,5 +548,6 @@
     int CastLineSegment(const Vector3 &origin,
 						const Vector3 &termination,
-						ViewCellContainer &viewcells);
+						ViewCellContainer &viewcells,
+						const bool useMailboxing = true);
 
 		
@@ -618,7 +619,10 @@
 	void GetViewCells(const VssRay &ray, ViewCellContainer &viewCells);
 
-
+	/** Returns view cells tree.
+	*/
 	ViewCellsTree *GetViewCellsTree() const { return mViewCellsTree; }
 
+	/** Sets the view cells tree.
+	*/
 	void SetViewCellsTree(ViewCellsTree *vt) { mViewCellsTree = vt; }
 
@@ -763,12 +767,4 @@
 	int EvalPvsSize(const RayInfoContainer &rays) const;
 
-	/** Computes pvs increase with respect to the previous pvs for heuristics.
-	*/
-	int GetPvsIncr(Intersectable *object, const KdPvsMap &activeNodes);
-
-	/** Returns absolute pvs contribution of this object.
-	*/
-	int GetPvsContribution(Intersectable *object) const;
-
 	/** Computes best cost for axis aligned planes.
 	*/
@@ -778,4 +774,9 @@
 								  float &position);
 
+
+
+	//////////////////////////////////////////
+	// Helper function for computing heuristics
+
 	/** Evaluates the contribution to left and right pvs at a visibility event ve.
 		@param ve the visibility event
@@ -783,26 +784,37 @@
 		@param rightPvs updates the right pvs
 	*/
-	void EvalHeuristicsContribution(
-		const SortableEntry &ve, 
-		int &pvsLeft, 
-		int &pvsRight) const;
-
-	/** Evaluates contribution of the ray to the left and right pvs.
+	void EvalHeuristics(const SortableEntry &ve, int &pvsLeft, int &pvsRight) const;
+
+	/** Evaluates contribution of min event to pvs
 	*/
 	int EvalMinEventContribution(
 		const VssRay &ray, const bool isTermination) const;
 
+	/** Evaluates contribution of max event to pvs
+	*/
 	int EvalMaxEventContribution(
 		const VssRay &ray, const bool isTermination) const;
 
+	/** Evaluates contribution of kd leaf when encountering a min event
+	*/
 	int EvalMinEventContribution(KdLeaf *leaf) const;
+	/**  Evaluates contribution of kd leaf when encountering a max event
+	*/
 	int EvalMaxEventContribution(KdLeaf *leaf) const;
 
 	/** Prepares objects for the heuristics.
-		@returns pvs size of the ray container
+		@returns pvs size as seen by the rays.
 	*/
 	int PrepareHeuristics(const RayInfoContainer &rays);
+	
+	/** Prepare a single ray for heuristics.
+	*/
 	int PrepareHeuristics(const VssRay &ray, const bool isTermination);
+	/** Prepare a single kd leaf for heuristics.
+	*/
 	int PrepareHeuristics(KdLeaf *leaf);
+
+	/////////////////////////////////////////////////////////////////////////////
+
 
 	/** Subdivides the rays into front and back rays according to the split plane.
@@ -831,5 +843,15 @@
 	
 	*/
-	void UpdateObjPvsContri(
+	void UpdateContributionsToPvs(
+		const VssRay &ray,
+		const bool isTermination,
+		const int cf,
+		float &frontPvs,
+		float &backPvs,
+		float &totalPvs) const;
+
+	/** Evaluates the contribution for objects.
+	*/
+	void UpdateContributionsToPvs(
 		Intersectable *obj, 
 		const int cf, 
@@ -838,5 +860,7 @@
 		float &totalPvs) const;
 
-	void UpdateBvhLeafPvsContri(
+	/** Evaluates the contribution for bounding volume leaves.
+	*/
+	void UpdateContributionsToPvs(
 		BvhLeaf *leaf,
 		const int cf,
@@ -845,8 +869,8 @@
 		float &totalPvs) const;
 
-	
-	/** See UpdateObjPvsContri. 
-	*/
-	void UpdateKdLeafPvsContri(KdLeaf *leaf,
+	/** Evaluates the contribution for kd leaves.
+	*/
+	void UpdateContributionsToPvs(
+		KdLeaf *leaf,
 		const int cf,
 		float &frontPvs,
@@ -854,9 +878,4 @@
 		float &totalPvs) const;
 
-	/** Collects pvs from rays.
-	*/
-	void CollectPvs(const RayInfoContainer &rays,
-					ObjectContainer &objects) const;
-
 	/** Returns true if tree can be terminated.
 	*/
@@ -916,7 +935,12 @@
 		RayInfoContainer &rays);
 
-	/** Add pvs contribution of this ray.
-	*/
-	int EvalPvsContribution(const VssRay &ray, const bool isTermination) const;
+	/** Evaluates pvs contribution of this ray.
+	*/
+	int EvalContributionToPvs(const VssRay &ray, const bool isTermination) const;
+
+	/** Evaluates pvs contribution of a kd node.
+	*/
+	int EvalContributionToPvs(KdLeaf *leaf) const;
+
 
 protected:
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp	(revision 1288)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp	(revision 1291)
@@ -25,6 +25,11 @@
 
 static float debugVol = 0;
+
 int BvhNode::sMailId = 2147483647;
+int BvhNode::sReservedMailboxes = 1;
+
+
 BvHierarchy *BvHierarchy::BvhSubdivisionCandidate::sBvHierarchy = NULL;
+
 
 
@@ -530,5 +535,7 @@
 		Intersectable *obj = *oit;
 		AxisAlignedBox3 box = obj->GetBox();
+
 		const float objMid = (box.Max(axis) + box.Min(axis)) * 0.5;
+
 		// object mailed => belongs to back objects
 		if (objMid < midPoint) 
@@ -599,11 +606,7 @@
 		const int nObjectsRight = nTotalObjects - nObjectsLeft;
 
-		// view cells that see both child nodes
-		//const float volLeftAndRight = totalVol - volLeft - volRight;
-
 		// the heuristics
 	    const float sum = volLeft * (float)nObjectsLeft + 
 						  volRight * (float)nObjectsRight;
-		//				  volLeftAndRight * (float)nTotalObjects;
 
 		if (sum < newRenderCost)
@@ -811,5 +814,5 @@
 		{
 			if (mUseCostHeuristics)
-			{
+			{cout << "a";
 				//-- partition objects using heuristics
 				nCostRatio[axis] =
@@ -821,5 +824,5 @@
 			}
 			else
-			{
+			{cout << "b";
 				nCostRatio[axis] =
 					EvalLocalObjectPartition(
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1287)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1291)
@@ -1788,4 +1788,6 @@
 	Vector3 termination = hray.Extrap(tmax);
 
+	ViewCell::NewMail();
+
 	// traverse the view space subdivision
 	CastLineSegment(origin, termination, viewcells);
@@ -1807,17 +1809,23 @@
 			// if ray not outside of view space
 			float contribution;
-			if (ray.mTerminationObject) {
-			  if (viewcell->GetPvs().GetSampleContribution(ray.mTerminationObject,
-														   ray.mPdf,
-														   contribution))
-			  {
-				++ ray.mPvsContribution;
-			  	  ray.mRelativePvsContribution += contribution;
-			  }
+
+			if (ray.mTerminationObject) 
+			{
+				cout << "f";
+				if (viewcell->GetPvs().GetSampleContribution(ray.mTerminationObject,
+					ray.mPdf,
+					contribution))
+				{
+					++ ray.mPvsContribution;
+					ray.mRelativePvsContribution += contribution;
+				}
 			}
+			
+#if SAMPLE_ORIGIN_OBJECTS
+
 			// for directional sampling it is important to count only contributions
 			// made in one direction!!!
 			// the other contributions of this sample will be counted for the oposite ray!
-#if SAMPLE_ORIGIN_OBJECTS
+
 			if (ray.mOriginObject && 
 				viewcell->GetPvs().GetSampleContribution(ray.mOriginObject,
@@ -3486,5 +3494,4 @@
 
 
-
 /**************************************************************************/
 /*                   VspBspViewCellsManager implementation                */
@@ -5506,9 +5513,12 @@
 	Vector3 termination = hray.Extrap(tmax);
 
+	ViewCell::NewMail();
+
 	// traverse the view space subdivision
 	CastLineSegment(origin, termination, viewcells);
 
 	if (storeViewCells)
-	{	// copy viewcells memory efficiently
+	{	
+		// copy viewcells memory efficiently
 		ray.mViewCells.reserve(viewcells.size());
 		ray.mViewCells = viewcells;
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 1288)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 1291)
@@ -159,12 +159,23 @@
 
 
+	/////////////////////////////////////
 	//-- mailing options
-
+	
+	static void NewMail(const int reserve = 1) {
+		sMailId += sReservedMailboxes;
+		sReservedMailboxes = reserve;
+	}
+	
 	void Mail() { mMailbox = sMailId; }
-	static void NewMail() { ++ sMailId; }
 	bool Mailed() const { return mMailbox == sMailId; }
+
+	void Mail(const int mailbox) { mMailbox = sMailId + mailbox; }
+	bool Mailed(const int mailbox) const { return mMailbox == sMailId + mailbox; }
+
+	int IncMail() { return ++ mMailbox - sMailId; }
 
 	static int sMailId;
 	int mMailbox;
+	static int sReservedMailboxes;
 
 	///////////////////////////////////
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.cpp	(revision 1290)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.cpp	(revision 1291)
@@ -730,12 +730,15 @@
 	
 	// compute locally best split plane
-	const float ratio = SelectSplitPlane(
-		splitCandidate.mParentData, 
-		splitCandidate.mSplitPlane, 
-		frontProb, 
-		backProb);
+	const float ratio = SelectSplitPlane(splitCandidate.mParentData, 
+								 		 splitCandidate.mSplitPlane, 
+										 frontProb, 
+										 backProb);
 
 	const bool success = ratio < mTermMaxCostRatio;
 
+	// max cost threshold violated?
+	splitCandidate.mMaxCostMisses = 
+		success ? splitCandidate.mParentData.mMaxCostMisses : splitCandidate.mParentData.mMaxCostMisses + 1;
+	
 	float oldRenderCost;
 
@@ -758,9 +761,4 @@
 	
 	splitCandidate.SetPriority(priority);
-
-	// max cost threshold violated?
-	splitCandidate.mMaxCostMisses = 
-		success ? splitCandidate.mParentData.mMaxCostMisses : splitCandidate.mParentData.mMaxCostMisses + 1;
-	//Debug << "p: " << tData.mNode << " depth: " << tData.mDepth << endl;
 }
 
@@ -907,6 +905,4 @@
 	}
 }
-
-
 
 
@@ -992,7 +988,5 @@
 	mLocalSubdivisionCandidates->reserve(requestedSize);
 
-
 	float pos;
-
 	RayInfoContainer::const_iterator rit, rit_end = rays.end();
 
@@ -1017,91 +1011,4 @@
 
 
-int VspTree::GetPvsContribution(Intersectable *object) const
-{
-    int pvsContri = 0;
-
-	KdPvsMap::const_iterator kit, kit_end = object->mKdPvs.mEntries.end();
-
-	Intersectable::NewMail();
-
-	// Search kd leaves this object is attached to
-	for (kit = object->mKdPvs.mEntries.begin(); kit != kit_end; ++ kit)
-	{
-		KdNode *l = (*kit).first;
-
-		// new object found during sweep 
-		// => increase pvs contribution of this kd node
-		if (!l->Mailed())
-		{
-			l->Mail();
-			++ pvsContri;
-		}
-	}
-
-	return pvsContri;
-}
-
-
-int VspTree::PrepareHeuristics(const VssRay &ray, const bool isTermination)
-{
-	int pvsSize = 0;
-	
-	Intersectable *obj;
-	Vector3 pt;
-	KdNode *node;
-
-	ray.GetSampleData(isTermination, pt, &obj, &node);
-
-	if (!obj)
-		return 0;
-
-	switch (mHierarchyManager->GetObjectSpaceSubdivisonType())
-	{
-	case HierarchyManager::NO_OBJ_SUBDIV:
-		{
-			if (!obj->Mailed())
-			{
-				obj->Mail();
-				obj->mCounter = 1;
-
-				++ pvsSize;
-			}
-			else
-			{
-				++ obj->mCounter;
-			}
-			break;
-		}
-	case HierarchyManager::KD_BASED_OBJ_SUBDIV:
-		{
-			KdLeaf *leaf = mHierarchyManager->mOspTree->GetLeaf(pt, node);
-			pvsSize += PrepareHeuristics(leaf);	
-			break;
-		}
-	case HierarchyManager::BV_BASED_OBJ_SUBDIV:
-		{
-			BvhLeaf *leaf = mHierarchyManager->mBvHierarchy->GetLeaf(obj);
-
-			if (!leaf->Mailed())
-			{
-				leaf->Mail();
-				leaf->mCounter = 1;
-
-				pvsSize += (int)leaf->mObjects.size();
-			}
-			else
-			{
-				++ leaf->mCounter;
-			}
-			break;
-		}
-	default:
-		break;
-	}
-
-	return pvsSize;
-}
-
-
 int VspTree::PrepareHeuristics(KdLeaf *leaf)
 {	
@@ -1112,8 +1019,6 @@
 		leaf->Mail();
 		leaf->mCounter = 1;
-
 		// add objects without the objects which are in several kd leaves
 		pvsSize += (int)(leaf->mObjects.size() - leaf->mMultipleObjects.size());
-		//Debug << "adding " << (int)leaf->mObjects.size() << " " << leaf->mMultipleObjects.size() << endl;
 	}
 	else
@@ -1123,5 +1028,4 @@
 
 	//-- the objects belonging to several leaves must be handled seperately
-
 	ObjectContainer::const_iterator oit, oit_end = leaf->mMultipleObjects.end();
 
@@ -1151,4 +1055,5 @@
 	Intersectable::NewMail();
 	KdNode::NewMail();
+	BvhNode::NewMail();
 
 	int pvsSize = 0;
@@ -1226,106 +1131,11 @@
 
 
-int VspTree::EvalMinEventContribution(const VssRay &ray, 
-									  const bool isTermination) const
-{
-	Intersectable *obj;
-	Vector3 pt;
-	KdNode *node;
-
-	ray.GetSampleData(isTermination, pt, &obj, &node);
-
-	if (!obj) return 0;
-
-	int pvs = 0;
-
-	switch (mHierarchyManager->GetObjectSpaceSubdivisonType())
-	{
-	case HierarchyManager::NO_OBJ_SUBDIV:
-		{
-			if (!obj->Mailed())
-			{
-				obj->Mail();
-				++ pvs;
-			}
-
-			break;
-		}
-	case HierarchyManager::KD_BASED_OBJ_SUBDIV:
-		{
-			KdLeaf *leaf = mHierarchyManager->mOspTree->GetLeaf(pt, node);
-			// add contributions of the kd nodes
-			pvs += EvalMinEventContribution(leaf);
-					
-			break;
-		}
-	case HierarchyManager::BV_BASED_OBJ_SUBDIV:
-		{
-			BvhLeaf *leaf = mHierarchyManager->mBvHierarchy->GetLeaf(obj);
-
-			if (!leaf->Mailed())
-			{
-				leaf->Mail();
-				pvs += (int)leaf->mObjects.size();
-			}
-			break;
-		}
-	default:
-		break;
-	}
-	return pvs;
-}
-
-
-int VspTree::EvalMaxEventContribution(const VssRay &ray, 
-									  const bool isTermination) const
-{
-	Intersectable *obj;
-	Vector3 pt;
-	KdNode *node;
-
-	ray.GetSampleData(isTermination, pt, &obj, &node);
-
-	if (!obj) return 0;
-
-	int pvs = 0;
-
-	switch (mHierarchyManager->GetObjectSpaceSubdivisonType())
-	{
-	case HierarchyManager::NO_OBJ_SUBDIV:
-		{
-			if (-- obj->mCounter == 0)
-				++ pvs;
-			break;
-		}
-	case HierarchyManager::KD_BASED_OBJ_SUBDIV:
-		{
-			KdLeaf *leaf = mHierarchyManager->mOspTree->GetLeaf(pt, node);
-
-			// add contributions of the kd nodes
-			pvs += EvalMaxEventContribution(leaf);
-			break;
-		}
-	case HierarchyManager::BV_BASED_OBJ_SUBDIV:
-		{
-			BvhLeaf *leaf = mHierarchyManager->mBvHierarchy->GetLeaf(obj);
-
-			if (-- leaf->mCounter == 0)
-				pvs += (int)leaf->mObjects.size();
-			break;
-		}
-	default:
-		break;
-	}
-
-	return pvs;
-}
-
-
-void VspTree::EvalHeuristicsContribution(const SortableEntry &ci,
-										 int &pvsLeft,
-										 int &pvsRight) const
+void VspTree::EvalHeuristics(const SortableEntry &ci,
+							 int &pvsLeft,
+							 int &pvsRight) const
 {
 	VssRay *ray = ci.ray;
 
+	// eval changes in pvs causes by min event 
 	if (ci.type == SortableEntry::ERayMin)
 	{
@@ -1333,5 +1143,5 @@
 		pvsLeft += EvalMinEventContribution(*ray, false);
 	}
-	else
+	else // eval changes in pvs causes by max event 
 	{
 		pvsRight -= EvalMaxEventContribution(*ray, true);
@@ -1358,6 +1168,4 @@
 	}
 
-	int pvsSize = tData.mPvs;
-
 	const float minBox = box.Min(axis);
 	const float maxBox = box.Max(axis);
@@ -1371,7 +1179,6 @@
 
 	// prepare the sweep
-	// (note: returns pvs size, so there would be no need 
-	// to give pvs size as argument)
-	pvsSize = PrepareHeuristics(usedRays);
+	// note: returns pvs size => no need t give pvs size as function parameter
+	const int pvsSize = PrepareHeuristics(usedRays);
 
 	// go through the lists, count the number of objects left and right
@@ -1398,5 +1205,5 @@
 	Intersectable::NewMail();
 	KdLeaf::NewMail();
-
+	BvhLeaf::NewMail();
 
 	//-- traverse through visibility events
@@ -1406,10 +1213,10 @@
 	for (ci = mLocalSubdivisionCandidates->begin(); ci != ci_end; ++ ci)
 	{
-		EvalHeuristicsContribution(*ci, pvsl, pvsr);
+		// compute changes to front and back pvs
+		EvalHeuristics(*ci, pvsl, pvsr);
 
 		// Note: sufficient to compare size of bounding boxes of front and back side?
 		if (((*ci).value >= minBand) && ((*ci).value <= maxBand))
 		{
-
 			float currentPos;
 			
@@ -1421,5 +1228,5 @@
 
 			sum = pvsl * ((*ci).value - minBox) + pvsr * (maxBox - (*ci).value);
-			//Debug  << "pos=" << (*ci).value << "\t newpos=" << currentPos << "\t pvs=(" <<  pvsl << "," << pvsr << ")" << "\t cost= " << sum << endl;
+			
 
 			if (sum < minSum)
@@ -1460,15 +1267,10 @@
 	const float volRatio = tData.mBoundingBox.GetVolume() / (sizeBox * mBoundingBox.GetVolume());
 
-/*	
-//if (axis != 1)
-	//Debug << "axis=" << axis << " costRatio=" << ratio << " pos=" << position << " t=" << (position - minBox) / (maxBox - minBox)
-	//      <<"\t pb=(" << pvsBack << ")\t pf=(" << pvsFront << ")" << endl;
-
-Debug << "\n§§§§ eval local cost §§§§" << endl
+	Debug << "\n§§§§ eval local cost §§§§" << endl
 		  << "back pvs: " << penaltyBack << " front pvs: " << penaltyFront << " total pvs: " << penaltyOld << endl 
 		  << "back p: " << pBack * volRatio << " front p " << pFront * volRatio << " p: " << pOverall * volRatio << endl
 		  << "old rc: " << oldRenderCost * volRatio << " new rc: " << newRenderCost * volRatio << endl
 		  << "render cost decrease: " << oldRenderCost * volRatio - newRenderCost * volRatio << endl;
-*/
+
 	return ratio;
 }
@@ -1494,5 +1296,5 @@
     const bool useSpecialAxis = 
 		mOnlyDrivingAxis || mCirculatingAxis;
-	//Debug << "data: " << tData.mBoundingBox << " pvs " << tData.mPvs << endl;
+	
 	if (mCirculatingAxis)
 	{
@@ -1546,7 +1348,5 @@
 	}
 
-
 	//-- assign values of best split
-	
 	plane.mAxis = bestAxis;
 	plane.mPosition = nPosition[bestAxis]; // split plane position
@@ -1555,5 +1355,4 @@
 	pBack = nProbBack[bestAxis];
 
-	//Debug << "val: " << nCostRatio[bestAxis] << " axis: " << bestAxis << endl;
 	return nCostRatio[bestAxis];
 }
@@ -1578,4 +1377,5 @@
 	Intersectable::NewMail(3);
 	KdLeaf::NewMail(3);
+	BvhLeaf::NewMail(3);
 
 	RayInfoContainer::const_iterator rit, rit_end = data.mRays->end();
@@ -1588,56 +1388,13 @@
 		VssRay *ray = rayInf.mRay;
 
+		// classify ray
 		const int cf = 
 			rayInf.ComputeRayIntersection(candidatePlane.mAxis, 
 										  candidatePlane.mPosition, t);
 
-		switch (mHierarchyManager->GetObjectSpaceSubdivisonType())
-		{
-		case HierarchyManager::NO_OBJ_SUBDIV:
-		{
-			// find front and back pvs for origing and termination object
-			UpdateObjPvsContri(ray->mTerminationObject, cf, pvsFront, pvsBack, totalPvs);
-			UpdateObjPvsContri(ray->mOriginObject, cf, pvsFront, pvsBack, totalPvs);
-
-			break;
-		}
-		case HierarchyManager::KD_BASED_OBJ_SUBDIV:
-		{
-			break;
-		}
-		case HierarchyManager::BV_BASED_OBJ_SUBDIV:
-		{
-			BvhLeaf *tLeaf = mHierarchyManager->mBvHierarchy->GetLeaf(ray->mTerminationObject);
-			BvhLeaf *oLeaf = mHierarchyManager->mBvHierarchy->GetLeaf(ray->mOriginObject);
-
-			UpdateBvhLeafPvsContri(tLeaf, cf, pvsFront, pvsBack, totalPvs);
-			UpdateBvhLeafPvsContri(oLeaf, cf, pvsFront, pvsBack, totalPvs);
-			
-			break;
-		}
-	default:
-		break;
-	}
-
-/*
-		if (!mUseKdPvsForHeuristics)
-		{
-			
-		}
-		else
-		{
-			if (ray->mTerminationObject)
-			{
-				KdLeaf *leaf = mHierarchyManager->mOspTree->GetLeaf(ray->mTermination, ray->mTerminationNode);
-				UpdateKdLeafPvsContri(leaf, cf, pvsFront, pvsBack, totalPvs);
-			}
-
-			if (ray->mOriginObject)
-			{
-				KdLeaf *leaf = mHierarchyManager->mOspTree->GetLeaf(ray->mOrigin, ray->mOriginNode);
-				UpdateKdLeafPvsContri(leaf, cf, pvsFront, pvsBack, totalPvs);
-			}
-		}
-*/
+		// evaluate contribution of ray endpoint to front and back pvs
+		// with respect to the classification
+		UpdateContributionsToPvs(*ray, true, cf, pvsFront, pvsBack, totalPvs);
+		UpdateContributionsToPvs(*ray, false, cf, pvsFront, pvsBack, totalPvs);
 	}
 
@@ -1649,12 +1406,13 @@
 
 	pFront = frontBox.GetVolume();
-	pBack = pOverall - pFront;
-		
+	pBack = pOverall - pFront;	
 
 	//-- pvs rendering heuristics
+
 	const int lowerPvsLimit = mViewCellsManager->GetMinPvsSize();
 	const int upperPvsLimit = mViewCellsManager->GetMaxPvsSize();
 
 	//-- only render cost heuristics or combined with standard deviation
+
 	const float penaltyOld = EvalPvsPenalty((int)totalPvs, lowerPvsLimit, upperPvsLimit);
     const float penaltyFront = EvalPvsPenalty((int)pvsFront, lowerPvsLimit, upperPvsLimit);
@@ -1667,5 +1425,5 @@
 
 	const float renderCostDecrease = (oldRenderCost - newRenderCost) / viewSpaceVol;
-	/*
+	
 	Debug << "\n==== eval render cost decrease ===" << endl
 		  << "back pvs: " << pvsBack << " front pvs " << pvsFront << " total pvs: " << totalPvs << endl 
@@ -1673,7 +1431,8 @@
 		  << "old rc: " << normalizedOldRenderCost << " new rc: " << newRenderCost / viewSpaceVol << endl
 		  << "render cost decrease: " << renderCostDecrease << endl;
-*/
+
 	return renderCostDecrease;
 }
+
 
 
@@ -1699,17 +1458,18 @@
 	for(rit = data.mRays->begin(); rit != rit_end; ++ rit)
 	{
+		VssRay *ray = (*rit).mRay;
+
 		// determine the side of this ray with respect to the plane
 		float t;
 		const int side = (*rit).ComputeRayIntersection(axis, position, t);
 	
-		UpdateObjPvsContri((*rit).mRay->mTerminationObject, side, pvsFront, pvsBack, pvsTotal);
-		UpdateObjPvsContri((*rit).mRay->mOriginObject, side, pvsFront, pvsBack, pvsTotal);
-	}
+		UpdateContributionsToPvs(*ray, true, side, pvsFront, pvsBack, pvsTotal);
+		UpdateContributionsToPvs(*ray, false, side, pvsFront, pvsBack, pvsTotal);
+	}
+
 
 	//-- evaluate cost heuristics
 
-	float pOverall;
-	
-	pOverall = data.mProbability;
+	float pOverall = data.mProbability;
 
 	// we use spatial mid split => simplified computation
@@ -1728,9 +1488,9 @@
 
 
-void VspTree::UpdateObjPvsContri(Intersectable *obj,
-								 const int cf,
-								 float &frontPvs,
-								 float &backPvs,
-								 float &totalPvs) const
+void VspTree::UpdateContributionsToPvs(Intersectable *obj,
+									   const int cf,
+									   float &frontPvs,
+									   float &backPvs,
+									   float &totalPvs) const
 {
 	if (!obj) return;
@@ -1779,12 +1539,12 @@
 
 
-void VspTree::UpdateBvhLeafPvsContri(BvhLeaf *leaf,
-									 const int cf,
-									 float &frontPvs,
-									 float &backPvs,
-									 float &totalPvs) const
+void VspTree::UpdateContributionsToPvs(BvhLeaf *leaf,
+									   const int cf,
+									   float &frontPvs,
+									   float &backPvs,
+									   float &totalPvs) const
 {
 	if (!leaf) return;
-/*
+
 	const int renderCost = (int)leaf->mObjects.size();
 
@@ -1825,14 +1585,14 @@
 				leaf->Mail(1);
 		}
-	}*/
-}
-
-
-
-void VspTree::UpdateKdLeafPvsContri(KdLeaf *leaf,
-									const int cf,
-									float &frontPvs,
-									float &backPvs,
-									float &totalPvs) const
+	}
+}
+
+
+
+void VspTree::UpdateContributionsToPvs(KdLeaf *leaf,
+									   const int cf,
+									   float &frontPvs,
+									   float &backPvs,
+									   float &totalPvs) const
 {
 	if (!leaf) return;
@@ -1847,10 +1607,10 @@
 	}
 
-	// compute contribution of yet unclassified objects
+	// recursivly update contributions of yet unclassified objects
 	ObjectContainer::const_iterator oit, oit_end = leaf->mMultipleObjects.end();
 
 	for (oit = leaf->mMultipleObjects.begin(); oit != oit_end; ++ oit)
 	{	
-		UpdateObjPvsContri(*oit, cf, frontPvs, backPvs, totalPvs);
+		UpdateContributionsToPvs(*oit, cf, frontPvs, backPvs, totalPvs);
     }	
 	
@@ -2296,109 +2056,4 @@
 
 
-void VspTree::CollectPvs(const RayInfoContainer &rays, 
-						 ObjectContainer &objects) const
-{
-	RayInfoContainer::const_iterator rit, rit_end = rays.end();
-
-	Intersectable::NewMail();
-
-	for (rit = rays.begin(); rit != rays.end(); ++ rit)
-	{
-		VssRay *ray = (*rit).mRay;
-
-		Intersectable *object;
-		object = ray->mOriginObject;
-
-        if (object)
-		{
-			if (!object->Mailed())
-			{
-				object->Mail();
-				objects.push_back(object);
-			}
-		}
-
-		object = ray->mTerminationObject;
-
-		if (object)
-		{
-			if (!object->Mailed())
-			{
-				object->Mail();
-				objects.push_back(object);
-			}
-		}
-	}
-}
-
-
-int VspTree::EvalPvsContribution(const VssRay &ray, const bool isTermination) const
-{	
-	Intersectable *obj; 
-	Vector3 pt;
-	KdNode *node;
-
-	ray.GetSampleData(isTermination, pt, &obj, &node);
-
-	if (!obj) return 0;
-
-	int pvs = 0;
-
-	switch(mHierarchyManager->GetObjectSpaceSubdivisonType())
-	{
-	case HierarchyManager::NO_OBJ_SUBDIV:
-		{
-			if (!obj->Mailed())
-			{
-				obj->Mail();
-				++ pvs;
-			}
-
-			break;
-		}
-	case HierarchyManager::KD_BASED_OBJ_SUBDIV:
-		{
-			KdLeaf *leaf = mHierarchyManager->mOspTree->GetLeaf(pt, node);
-
-			if (!leaf->Mailed())
-			{
-				leaf->Mail();
-				pvs += (int)(leaf->mObjects.size() - leaf->mMultipleObjects.size());
-				
-				ObjectContainer::const_iterator oit, oit_end = leaf->mMultipleObjects.end();
-				for (oit = leaf->mMultipleObjects.begin(); oit != oit_end; ++ oit)
-				{
-					Intersectable *obj = *oit;
-
-					if (!obj->Mailed())
-					{
-						obj->Mail();
-						++ pvs;
-					}
-				}
-			}
-
-			break;
-		}
-	case HierarchyManager::BV_BASED_OBJ_SUBDIV:
-		{
-			BvhLeaf *bvhleaf = mHierarchyManager->mBvHierarchy->GetLeaf(obj);
-
-			if (!bvhleaf->Mailed())
-			{
-				bvhleaf->Mail();
-				pvs += (int)bvhleaf->mObjects.size();
-			}
-
-			break;
-		}
-	default:
-		break;
-	}
-
-	return pvs;
-}
-
-
 int VspTree::EvalPvsSize(const RayInfoContainer &rays) const
 {
@@ -2414,6 +2069,7 @@
 	{
 		VssRay *ray = (*rit).mRay;
-		pvsSize += EvalPvsContribution(*ray, true);
-		pvsSize += EvalPvsContribution(*ray, false);
+
+		pvsSize += EvalContributionToPvs(*ray, true);
+		pvsSize += EvalContributionToPvs(*ray, false);
 	}
 	
@@ -2430,5 +2086,6 @@
 int VspTree::CastLineSegment(const Vector3 &origin,
 							 const Vector3 &termination,
-                             ViewCellContainer &viewcells)
+                             ViewCellContainer &viewcells,
+							 const bool useMailboxing)
 {
 	int hits = 0;
@@ -2438,7 +2095,4 @@
 
 	stack<LineTraversalData> tStack;
-
-	//Intersectable::NewMail();
-	//ViewCell::NewMail();
 
 	Vector3 entp = origin;
@@ -2503,11 +2157,13 @@
 			ViewCell *vc = leaf->GetViewCell();
 
-			// don't have to mail because each view cell belongs to exactly one leaf
-			//if (!vc->Mailed())
-			//{
-			//	vc->Mail();
+			// don't have to mail if each view cell belongs to exactly one leaf
+			if (!useMailboxing || !vc->Mailed())
+			{
+				if (useMailboxing)
+					vc->Mail();
+
 				viewcells.push_back(vc);
 				++ hits;
-			//}
+			}
 #if 0
 			leaf->mRays.push_back(RayInfo(new VssRay(origin, termination, NULL, NULL, 0)));
@@ -2932,11 +2588,4 @@
 void VspTree::GetViewCells(const VssRay &ray, ViewCellContainer &viewCells)
 {
-#if 1 
-	// use view cells manager to compute view cells
-	VssRay vcRay(ray);
-
-	mViewCellsManager->ComputeSampleContribution(vcRay, false, true);
-	viewCells = vcRay.mViewCells;
-#else
 	static Ray hray;
 	hray.Init(ray);
@@ -2950,7 +2599,7 @@
 	const Vector3 termination = hray.Extrap(tmax);
 
-	// if no precomputation of view cells
-	CastLineSegment(origin, termination, viewCells);
-#endif
+	// view cells were not precomputed
+	// don't mail because we need mailboxing for something else
+	CastLineSegment(origin, termination, viewCells, false);
 }
 
@@ -3052,3 +2701,273 @@
 }
 
-}
+
+int VspTree::EvalMaxEventContribution(const VssRay &ray, 
+									  const bool isTermination) const
+{
+	Intersectable *obj;
+	Vector3 pt;
+	KdNode *node;
+
+	ray.GetSampleData(isTermination, pt, &obj, &node);
+
+	if (!obj) 
+		return 0;
+
+	int pvs = 0;
+
+	switch ( mHierarchyManager->GetObjectSpaceSubdivisonType())
+	{
+	case HierarchyManager::NO_OBJ_SUBDIV:
+		{
+			if (-- obj->mCounter == 0)
+				++ pvs;
+			break;
+		}
+	case HierarchyManager::KD_BASED_OBJ_SUBDIV:
+		{
+			KdLeaf *leaf = mHierarchyManager->mOspTree->GetLeaf(pt, node);
+
+			// add contributions of the kd nodes
+			pvs += EvalMaxEventContribution(leaf);
+			break;
+		}
+	case HierarchyManager::BV_BASED_OBJ_SUBDIV:
+		{
+			BvhLeaf *leaf = mHierarchyManager->mBvHierarchy->GetLeaf(obj);
+
+			if (-- leaf->mCounter == 0)
+				pvs += (int)leaf->mObjects.size();
+			break;
+		}
+	default:
+		break;
+	}
+
+	return pvs;
+}
+
+
+int VspTree::PrepareHeuristics(const VssRay &ray, const bool isTermination)
+{
+	int pvsSize = 0;
+	
+	Intersectable *obj;
+	Vector3 pt;
+	KdNode *node;
+
+	ray.GetSampleData(isTermination, pt, &obj, &node);
+
+	if (!obj)
+		return 0;
+
+	switch (mHierarchyManager->GetObjectSpaceSubdivisonType())
+	{
+	case HierarchyManager::NO_OBJ_SUBDIV:
+		{
+			if (!obj->Mailed())
+			{
+				obj->Mail();
+				obj->mCounter = 0;
+
+				++ pvsSize;
+			}
+
+			++ obj->mCounter;	
+			break;
+		}
+	case HierarchyManager::KD_BASED_OBJ_SUBDIV:
+		{
+			KdLeaf *leaf = mHierarchyManager->mOspTree->GetLeaf(pt, node);
+			pvsSize += PrepareHeuristics(leaf);	
+			break;
+		}
+	case HierarchyManager::BV_BASED_OBJ_SUBDIV:
+		{
+			BvhLeaf *leaf = mHierarchyManager->mBvHierarchy->GetLeaf(obj);
+
+			if (!leaf->Mailed())
+			{
+				leaf->Mail();
+				leaf->mCounter = 0;
+
+				pvsSize += (int)leaf->mObjects.size();
+			}
+
+			++ leaf->mCounter;	
+			break;
+		}
+	default:
+		break;
+	}
+
+	return pvsSize;
+}
+
+
+int VspTree::EvalMinEventContribution(const VssRay &ray, 
+									  const bool isTermination) const
+{
+	Intersectable *obj;
+	Vector3 pt;
+	KdNode *node;
+
+	ray.GetSampleData(isTermination, pt, &obj, &node);
+
+	if (!obj) return 0;
+
+	int pvs = 0;
+
+	switch (mHierarchyManager->GetObjectSpaceSubdivisonType())
+	{
+	case HierarchyManager::NO_OBJ_SUBDIV:
+		{
+			if (!obj->Mailed())
+			{
+				obj->Mail();
+				++ pvs;
+			}
+			break;
+		}
+	case HierarchyManager::KD_BASED_OBJ_SUBDIV:
+		{
+			KdLeaf *leaf = mHierarchyManager->mOspTree->GetLeaf(pt, node);
+			// add contributions of the kd nodes
+			pvs += EvalMinEventContribution(leaf);				
+			break;
+		}
+	case HierarchyManager::BV_BASED_OBJ_SUBDIV:
+		{
+			BvhLeaf *leaf = mHierarchyManager->mBvHierarchy->GetLeaf(obj);
+
+			if (!leaf->Mailed())
+			{
+				leaf->Mail();
+				pvs += (int)leaf->mObjects.size();
+			}
+			break;
+		}
+	default:
+		break;
+	}
+
+	return pvs;
+}
+
+
+void VspTree::UpdateContributionsToPvs(const VssRay &ray,
+									   const bool isTermination,
+									   const int cf,
+									   float &frontPvs,
+									   float &backPvs,
+									   float &totalPvs) const
+{
+	Intersectable *obj;
+	Vector3 pt;
+	KdNode *node;
+
+	ray.GetSampleData(isTermination, pt, &obj, &node);
+
+	if (!obj) return;
+
+	switch (mHierarchyManager->GetObjectSpaceSubdivisonType())
+	{
+		case HierarchyManager::NO_OBJ_SUBDIV:
+		{
+			// find front and back pvs for origing and termination object
+			UpdateContributionsToPvs(obj, cf, frontPvs, backPvs, totalPvs);
+			break;
+		}
+		case HierarchyManager::KD_BASED_OBJ_SUBDIV:
+		{
+			KdLeaf *leaf = mHierarchyManager->mOspTree->GetLeaf(pt, node);
+			UpdateContributionsToPvs(leaf, cf, frontPvs, backPvs, totalPvs);
+			break;
+		}
+		case HierarchyManager::BV_BASED_OBJ_SUBDIV:
+		{
+			BvhLeaf *leaf = mHierarchyManager->mBvHierarchy->GetLeaf(obj);
+			UpdateContributionsToPvs(leaf, cf, frontPvs, backPvs, totalPvs);
+			break;
+		}
+	}
+}
+
+
+int VspTree::EvalContributionToPvs(const VssRay &ray, 
+								   const bool isTermination) const
+{	
+	Intersectable *obj; 
+	Vector3 pt;
+	KdNode *node;
+
+	ray.GetSampleData(isTermination, pt, &obj, &node);
+
+	if (!obj) 
+		return 0;
+
+	int pvs = 0;
+
+	switch(mHierarchyManager->GetObjectSpaceSubdivisonType())
+	{
+	case HierarchyManager::NO_OBJ_SUBDIV:
+		{
+			if (!obj->Mailed())
+			{
+				obj->Mail();
+				++ pvs;
+			}
+			break;
+		}
+	case HierarchyManager::KD_BASED_OBJ_SUBDIV:
+		{
+			KdLeaf *leaf = mHierarchyManager->mOspTree->GetLeaf(pt, node);
+
+			pvs += EvalContributionToPvs(leaf);
+			break;
+		}
+	case HierarchyManager::BV_BASED_OBJ_SUBDIV:
+		{
+			BvhLeaf *bvhleaf = mHierarchyManager->mBvHierarchy->GetLeaf(obj);
+
+			if (!bvhleaf->Mailed())
+			{
+				bvhleaf->Mail();
+				pvs += (int)bvhleaf->mObjects.size();
+			}
+			break;
+		}
+	default:
+		break;
+	}
+
+	return pvs;
+}
+
+
+int VspTree::EvalContributionToPvs(KdLeaf *leaf) const
+{
+	if (leaf->Mailed()) // leaf already mailed
+		return 0;
+
+	leaf->Mail();
+
+	int pvs = 0;
+	pvs += (int)(leaf->mObjects.size() - leaf->mMultipleObjects.size());
+
+	ObjectContainer::const_iterator oit, oit_end = leaf->mMultipleObjects.end();
+
+	for (oit = leaf->mMultipleObjects.begin(); oit != oit_end; ++ oit)
+	{
+		Intersectable *obj = *oit;
+
+		if (!obj->Mailed())
+		{
+			obj->Mail();
+			++ pvs;
+		}
+	}
+
+	return pvs;
+}
+
+}
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.cpp	(revision 1284)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.cpp	(revision 1291)
@@ -86,13 +86,11 @@
 	if (node->IsLeaf())	
 	{
-		if (!node->Mailed())
-		{
-			node->Mail();
-			return (int)(((BvhLeaf *)node)->mObjects.size());
-		}
-		else
-		{
+		// objects already accounted for
+		if (node->Mailed())
 			return 0;
-		}
+
+		node->Mail();
+
+		return (int)(((BvhLeaf *)node)->mObjects.size());
 	}			 
 
@@ -156,13 +154,15 @@
 					KdIntersectable *kdObj = dynamic_cast<KdIntersectable *>(obj);
 					pvs += CountNewObjectsInKdNode(kdObj);	
+					cout << "z";
 					break;
 				}
 			case Intersectable::BVH_INTERSECTABLE:
 				{
+					cout << "x";
 					BvhIntersectable *bvhObj = dynamic_cast<BvhIntersectable *>(obj);
 					pvs += CountNewObjectsInBvhNode(bvhObj);
 					break;
 				}
-			default:
+			default:cout << "y";
 				++ pvs;
 				break;
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp	(revision 1288)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp	(revision 1291)
@@ -279,5 +279,5 @@
 		const float costRatio = splitCandidate->GetRenderCostDecrease() / mTotalCost;
 
-		Debug << "ratio: " << costRatio << " min ratio: " << mTermMinGlobalCostRatio << endl;
+		//Debug << "ratio: " << costRatio << " min ratio: " << mTermMinGlobalCostRatio << endl;
 		if (costRatio < mTermMinGlobalCostRatio)
 			++ mGlobalCostMisses;
@@ -685,3 +685,5 @@
 }
 
-}
+
+
+}
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/OspTree.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/OspTree.cpp	(revision 1288)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/OspTree.cpp	(revision 1291)
@@ -1264,6 +1264,4 @@
 
 
-#if 0
-
 float OspTree::EvalRenderCostDecrease(const AxisAlignedPlane &candidatePlane,
 									  const OspTraversalData &tData,
@@ -1274,195 +1272,5 @@
 
 	// probability that view point lies in back / front node
-	float pOverall = 0;//data.mProbability; // todo matt§: value ok?
-	float pFront = 0;
-	float pBack = 0;
-	float pFrontAndBack = 0;
-
-	const float viewSpaceVol = mVspTree->GetBoundingBox().GetVolume();
-
-	Intersectable::NewMail(3);
-	
-	KdLeaf *leaf = tData.mNode;
-	const int totalPvs = (int)leaf->mObjects.size();
-	
-	RayInfoContainer frontRays, backRays;
-	ClassifyRays(*tData.mRays, leaf, candidatePlane, frontRays, backRays);
-
-	ViewCellContainer touchedViewCells;
-	
-	// sum up volume seen from the objects of left and right children
-	// => the volume is the weight for the render cost equation
-	ViewCell::NewMail(3);
-
-	RayInfoContainer::const_iterator rit, rit_end = tData.mRays->end();
-
-	for (rit = tData.mRays->begin(); rit < rit_end; ++ rit)
-	{
-		VssRay *ray = (*rit).mRay;
-
-		// add volume to volumes of left and / or right children
-		// if one of the ray end points is inside
-		const int classification = ClassifyRay(ray, leaf, candidatePlane);
-
-		ViewCellContainer viewCells;
-		mVspTree->GetViewCells(*ray, viewCells);
-			
-		ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
-
-		// traverse through view cells and classify them according
-		// to them being seen from to back / front / front and back node
-		for (vit = viewCells.begin(); vit != vit_end; ++ vit)
-		{
-			ViewCell *vc = *vit;
-
-			// if not previously mailed
-			if (!vc->Mailed() && !vc->Mailed(1) && !vc->Mailed(2))
-			{
-				touchedViewCells.push_back(vc);
-			}
-
-			// classify / mail the view cell
-			MailViewCell(vc, classification);	
-		}
-	}
-
-	// evaluate view cells volume contribution 
-	// with respect to the mail box classification
-	ViewCellContainer::const_iterator vit, vit_end = touchedViewCells.end();
-
-	for (vit = touchedViewCells.begin(); vit != vit_end; ++ vit)
-	{
-		AddViewCellVolumeContri(*vit, pFront, pBack, pFrontAndBack);
-	}
-
-	//////////////////////////////////////////////
-	//
-	// evaluate contribution of objects which are part of other kd nodes
-	// which are seen by the same view cell
-	// These contributions cannot be reduced by splitting, because
-	// the object would still be part of the pvs
-
-	float additionalFrontRenderCost = 0;
-	float additionalBackRenderCost = 0;
-	
-	MailablePvsData::NewMail();
-
-	for (rit = tData.mRays->begin(); rit != tData.mRays->end(); ++ rit)
-	{
-		VssRay *ray = (*rit).mRay;
-
-		ViewCellContainer viewCells;
-		mVspTree->GetViewCells(*ray, viewCells);
-
-		ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
-
-		// traverse through view cells
-		for (vit = viewCells.begin(); vit != vit_end; ++ vit)
-		{
-			ViewCell *viewCell = *vit;
-
-			// for a view cell:
-			// if object is also in the kd pvs entries from other kd leaves,
-			// render cost cannot be reduced for this view cell
-			// => the render cost was falsly reduced, add them again
-
-			if (ray->mTerminationObject)
-			{	
-				Intersectable *obj = ray->mTerminationObject;
-				
-				const bool renderCostWrong = 
-					ViewCellHasMultipleReferences(obj, viewCell, true);
-			
-				// if there is already an entry of this object in the view cell pvs 
-				if (renderCostWrong)
-				{
-					// view cell was counted only for front or back => correct tjos
-					if (viewCell->Mailed(1) && obj->Mailed())
-					{
-						additionalFrontRenderCost += viewCell->GetVolume();
-					}
-					else if (viewCell->Mailed() && obj->Mailed(1))
-					{
-						additionalBackRenderCost += viewCell->GetVolume();
-					}
-				}
-			}
-	
-			if (ray->mOriginObject)
-			{
-				Intersectable *obj = ray->mOriginObject;
-
-				const bool renderCostWrong = 
-					ViewCellHasMultipleReferences(obj, viewCell, true);
-				// if there is already an entry of this object in the view cell pvs 
-				if (renderCostWrong)
-				{
-					if (viewCell->Mailed(1) && obj->Mailed())
-					{
-						additionalFrontRenderCost += viewCell->GetVolume();
-					}
-					else if (viewCell->Mailed() && obj->Mailed(1))
-					{
-						additionalBackRenderCost += viewCell->GetVolume();
-					}
-				}
-			}
-		}
-	}
-
-	/////////////////////////////
-
-
-	// these are non-overlapping sets
-	pOverall = pFront + pBack + pFrontAndBack;
-
-
-	//-- pvs rendering heuristics
-
-	const float oldRenderCost = pOverall * totalPvs;
-	
-	// sum up the terms: 
-	// the view cells seeing
-	// a) the left node are weighted by the #left node objects
-	// b) the right node are weighted by the #right node objects
-	// c) both nodes are weighted by the #parent node objects
-	const float newRenderCost = pvsFront * pFront + pvsBack * pBack + totalPvs * pFrontAndBack
-		+ additionalFrontRenderCost + additionalBackRenderCost;
-
-	// normalize volume with view space volume
-	const float renderCostDecrease = (oldRenderCost - newRenderCost) / viewSpaceVol;
-
-	Debug << "\n(((( eval render cost decrease ))))" << endl
-		  << "back pvs: " << pvsBack << " front pvs " << pvsFront << " total pvs: " << totalPvs << endl 
-		  << "back p: " << pBack / viewSpaceVol << " front p " << pFront / viewSpaceVol 
-		  << " front and back p " << pFrontAndBack / viewSpaceVol << " p: " << tData.mProbability / viewSpaceVol << endl
-		  << "old rc: " << oldRenderCost / viewSpaceVol << " new rc: " << newRenderCost / viewSpaceVol << endl
-		  << "render cost decrease: " << renderCostDecrease << endl
-		  << "additional front " << additionalFrontRenderCost / viewSpaceVol 
-		  << " additional back " << additionalBackRenderCost  / viewSpaceVol << endl;
-
-	if (oldRenderCost < newRenderCost * 0.99)
-		Debug <<"error!!"<<endl;
-
-	//if ((((pOverall - tData.mProbability) / viewSpaceVol) > 0.00001))
-	//	Debug << "ERROR!!"<<endl;
-
-	normalizedOldRenderCost = oldRenderCost / viewSpaceVol;
-
-		
-	return renderCostDecrease;
-}
-
-#else
-
-float OspTree::EvalRenderCostDecrease(const AxisAlignedPlane &candidatePlane,
-									  const OspTraversalData &tData,
-									  float &normalizedOldRenderCost) const
-{
-	float pvsFront = 0;
-	float pvsBack = 0;
-
-	// probability that view point lies in back / front node
-	float pOverall = 0;//data.mProbability; // todo matt§: value ok?
+	float pOverall = 0;
 	float pFront = 0;
 	float pBack = 0;
@@ -1504,5 +1312,4 @@
 	}
 
-	
 	ViewCellContainer touchedViewCells;
 
@@ -1603,13 +1410,7 @@
 
 	/////////////////////////////
-
-
-	// these are non-overlapping sets
-	pOverall = pFront + pBack + pFrontAndBack;
-
-
 	//-- pvs rendering heuristics
 
-	const float oldRenderCost = rc;//pOverall * totalPvs;
+	const float oldRenderCost = rc;
 	
 	// sum up the terms: 
@@ -1618,24 +1419,13 @@
 	// b) the right node are weighted by the #right node objects
 	// c) both nodes are weighted by the #parent node objects
-	const float newRenderCost = newRc//pvsFront * pFront + pvsBack * pBack + totalPvs * pFrontAndBack
-;//		+ additionalFrontRenderCost + additionalBackRenderCost;
+	const float newRenderCost = newRc;
+
 
 	// normalize volume with view space volume
 	const float renderCostDecrease = (oldRenderCost - newRenderCost) / viewSpaceVol;
 
-	Debug << "\n(((( eval render cost decrease ))))" << endl
-		  << "back pvs: " << pvsBack << " front pvs " << pvsFront << " total pvs: " << totalPvs << endl 
-		  << "back p: " << pBack / viewSpaceVol << " front p " << pFront / viewSpaceVol 
-		  << " front and back p " << pFrontAndBack / viewSpaceVol << " p: " << tData.mProbability / viewSpaceVol << endl
+	Debug << "\nrender cost decrease: " << endl
 		  << "old rc: " << oldRenderCost / viewSpaceVol << " new rc: " << newRenderCost / viewSpaceVol << endl
 		  << "render cost decrease: " << renderCostDecrease << endl;
-		  //<< "additional front " << additionalFrontRenderCost / viewSpaceVol 
-		  //<< " additional back " << additionalBackRenderCost  / viewSpaceVol << endl;
-
-	if (oldRenderCost < newRenderCost * 0.99)
-		Debug <<"error!!"<<endl;
-
-	//if ((((pOverall - tData.mProbability) / viewSpaceVol) > 0.00001))
-	//	Debug << "ERROR!!"<<endl;
 
 	normalizedOldRenderCost = oldRenderCost / viewSpaceVol;
@@ -1644,5 +1434,4 @@
 	return renderCostDecrease;
 }
-#endif
 
 
@@ -2234,37 +2023,4 @@
 	MailablePvsData::NewMail();
 	
-	/*RayInfoContainer::const_iterator rit, rit_end = rays.end();
-
-	for (rit = rays.begin(); rit < rit_end; ++ rit)
-	{
-		VssRay *ray = (*rit).mRay;
-
-		ViewCellContainer viewCells;
-		mVspTree->GetViewCells(*ray, viewCells);
-
-		ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
-
-		// traverse through view cells and classify them according
-		// to them being seen from to back / front / front and back node
-		for (vit = viewCells.begin(); vit != vit_end; ++ vit)
-		{
-			ViewCell *vc = *vit;
-
-			Intersectable *obj = ray->mTerminationObject;
-			if (obj)
-			{
-				float contri;
-				AddViewCellToObjectPvs(obj, vc, contri, true);
-			}
-
-			obj = ray->mOriginObject;
-			if (obj)
-			{
-				float contri;
-				AddViewCellToObjectPvs(obj, vc, contri, true);
-			}
-		}
-	}*/
-	
 	ViewCellContainer touchedViewCells;
 	CollectTouchedViewCells(rays, touchedViewCells);
@@ -2297,48 +2053,4 @@
 {
 	MailablePvsData::NewMail();
-
-	/*RayInfoContainer::const_iterator rit, rit_end = rays.end();
-	for (rit = rays.begin(); rit < rit_end; ++ rit)
-	{
-		VssRay *ray = (*rit).mRay;
-
-		// test if intersection point with one of the objects is inside this node
-		ViewCellContainer viewCells;
-		mVspTree->GetViewCells(*ray, viewCells);
-
-		ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
-
-		// traverse through view cells and classify them according
-		// to them being seen from to back / front / front and back node
-		for (vit = viewCells.begin(); vit != vit_end; ++ vit)
-		{
-			ViewCell *vc = *vit;
-			Intersectable *obj = ray->mTerminationObject;
-
-			if (obj)
-			{
-				MailablePvsData *vdata = obj->mViewCellPvs.Find(vc);
-
-				if (vdata && !vdata->Mailed())
-				{
-					vdata->Mail();
-					obj->mViewCellPvs.RemoveSample(vc, 1);
-				}
-			}
-
-			obj = ray->mOriginObject;
-
-			if (obj)
-			{
-				MailablePvsData *vdata = obj->mViewCellPvs.Find(vc);
-
-				if (vdata && !vdata->Mailed())
-				{
-					vdata->Mail();
-					obj->mViewCellPvs.RemoveSample(vc, 1);
-				}
-			}
-		}
-	}*/
 
 	ViewCellContainer touchedViewCells;
