Index: /GTP/trunk/Lib/Vis/Preprocessing/scripts/Preprocessor.vcproj
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/scripts/Preprocessor.vcproj	(revision 1163)
+++ /GTP/trunk/Lib/Vis/Preprocessing/scripts/Preprocessor.vcproj	(revision 1184)
@@ -459,7 +459,4 @@
 			</File>
 			<File
-				RelativePath="..\src\VssRay.cpp">
-			</File>
-			<File
 				RelativePath="..\src\VssRay.h">
 			</File>
@@ -538,4 +535,7 @@
 			<File
 				RelativePath="..\src\Renderer.h">
+			</File>
+			<File
+				RelativePath="..\src\VssRay.cpp">
 			</File>
 		</Filter>
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h	(revision 1180)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h	(revision 1184)
@@ -954,4 +954,5 @@
 };
 
+#define TEST_EVALUATION 1
 
 /**
@@ -1012,5 +1013,5 @@
 protected:
 
-#if 1
+#if TEST_EVALUATION
 	virtual void EvalViewCellPartition();
 #endif
@@ -1037,5 +1038,6 @@
 	/** Exports visualization of the PVS.
 	*/
-	void ExportPvs(const ObjectContainer &objects,
+	void ExportPvs(
+		const ObjectContainer &objects,
 		const VssRayContainer &rays);
 
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.cpp	(revision 1181)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.cpp	(revision 1184)
@@ -102,4 +102,6 @@
 	//app << "#N_PVS: " << pvs << endl;
 
+	//app << "#N_MAXOBJECTREFS  ( Max number of object refs / leaf )\n" << maxObjectRefs << "\n";
+
 	app << "========== END OF VspTree statistics ==========\n";
 }
@@ -134,6 +136,6 @@
 		<< minPvsNodes * 100 / (double)Leaves() << endl;
 
-	//app << "#N_PMINRAYSLEAVES  ( Percentage of leaves with minimal number of rays)\n" 
-	//	<< minRaysNodes * 100 / (double)Leaves() << endl;
+	//app << "#N_PMINOBJECTREFLEAVES  ( Percentage of leaves with minimal number of object ref)\n" 
+		//<< minObjectNodes * 100 / (double)Leaves() << endl;
 
 	app << "#N_MAXCOSTNODES  ( Percentage of leaves with terminated because of max cost ratio )\n"
@@ -143,7 +145,4 @@
 		<< minProbabilityNodes * 100 / (double)Leaves() << endl;
 
-//	app << "#N_PMAXRAYCONTRIBLEAVES  ( Percentage of leaves with maximal ray contribution )\n" 
-//		<<	maxRayContribNodes * 100 / (double)Leaves() << endl;
-
 	app << "#N_PMAXDEPTH ( Maximal reached depth )\n" << maxDepth << endl;
 
@@ -153,4 +152,7 @@
 
 	app << "#N_INVALIDLEAVES (number of invalid leaves )\n" << invalidLeaves << endl;
+
+	app << "#N_MAXOBJECTREFS  ( Max number of object refs / leaf )\n" <<
+		 maxObjectRefs << "\n";
 
 //	app << "#N_RAYS (number of rays / leaf)\n" << AvgRays() << endl;
@@ -632,5 +634,5 @@
 	}
 		
-	//
+	// set view cell values
 	viewCell->mLeaf = leaf;
 
@@ -734,5 +736,5 @@
 			{
 				(*it).mRay->Ref();			
-				dynamic_cast<VspLeaf *>(newNode)->mVssRays.push_back((*it).mRay);
+				leaf->mVssRays.push_back((*it).mRay);
 			}
 		}
@@ -933,5 +935,5 @@
 bool VspTree::AddKdLeafToPvs(KdLeaf *leaf, 
 							 ViewCell *vc, 
-							 float &pdf, 
+							 const float pdf, 
 							 float &contribution)
 {
@@ -948,5 +950,4 @@
 #else // add all objects of kd node
 
-	pdf = 0;
 	contribution = 0;
 
@@ -957,13 +958,12 @@
 		Intersectable *object = *it;						
 
-		float newpdf;
 		float newcontri;
 						
-		if (vc->AddPvsSample(object, newpdf, newcontri))
+		if (vc->AddPvsSample(object, pdf, newcontri))
 		{
 			contri = true;
 		}
 
-		pdf += newPdf;
+		//pdf += newPdf;
 		newContri += contribution;
 	}
@@ -2379,5 +2379,5 @@
 	stack<LineTraversalData> tStack;
 
-	Intersectable::NewMail();
+	//Intersectable::NewMail();
 	//ViewCell::NewMail();
 
@@ -2913,6 +2913,19 @@
 void VspTree::GetViewCells(const VssRay &ray, ViewCellContainer &viewCells)
 {
+	static Ray hray;
+	hray.Init(ray);
+	//hray.mFlags |= Ray::CULL_BACKFACES;
+	//Ray hray(ray);
+
+	float tmin = 0, tmax = 1.0;
+
+	if (!mBoundingBox.GetRaySegment(hray, tmin, tmax) || (tmin > tmax))
+		return;
+
+	const Vector3 origin = hray.Extrap(tmin);
+	const Vector3 termination = hray.Extrap(tmax);
+
 	// if no precomputation of view cells
-	CastLineSegment(ray.mOrigin, ray.mTermination, viewCells);
+	CastLineSegment(origin, termination, viewCells);
 }
 
@@ -3117,8 +3130,9 @@
 
 	//-- classify objects
+
 	int objectsBack = 0;
 	int objectsFront = 0;
 
-	ObjectContainer::const_iterator mi, mi_end = leaf->mObjects.end();
+    ObjectContainer::const_iterator mi, mi_end = leaf->mObjects.end();
 
 	for ( mi = leaf->mObjects.begin(); mi != mi_end; ++ mi) 
@@ -3127,10 +3141,11 @@
 		const AxisAlignedBox3 box = (*mi)->GetBox();
 		
-		if (box.Max(axis) > position + mEpsilon) 
+		if (box.Max(axis) >= position) 
 			++ objectsFront;
     
-		if (box.Min(axis) < position - mEpsilon)
+		if (box.Min(axis) < position)
 			++ objectsBack;
 	}
+
 
 	// TODO matt: compute pvs
@@ -3138,7 +3153,12 @@
 	backData.mPvs = objectsBack;
 
+	//CheckViewCellsPvs(leaf, *tData.mRays);
+	RemoveParentViewCellsPvs(leaf, *tData.mRays);
+
+
 	KdLeaf *back = new KdLeaf(node, objectsBack);
 	KdLeaf *front = new KdLeaf(node, objectsFront);
 
+	
 	/////////////
 	//-- create front and back leaf
@@ -3161,4 +3181,24 @@
 
 	SplitObjects(leaf, splitPlane, leaf->mObjects, front->mObjects, back->mObjects);
+
+
+	//-- eval view cells pvs
+	
+	// remove parent pvs update pvs of left and right leaves
+	// Note: It is necessary to update first left and then right pvs.
+	// We need to store the view cells seen by each object,
+	// but also if the view cells are seen as part of two different
+	// kd leaves, which is stored in the pdf component of the pvs entry. 
+	// Because if an object is part of a view cell more than once,
+	// it cannot be removed from the pvs by splitting a kd node where
+	// the view cell sees only the other child of the node.
+	// This is important during the subdivision
+
+//ViewCellPvsData::NewMail();
+	UpdateViewCellsPvs(front, *frontData.mRays);
+	UpdateViewCellsPvs(back, *backData.mRays);
+
+	////////////////////////////////////
+
 
 	ProcessMultipleRefs(front);
@@ -3234,4 +3274,18 @@
 	{
 		EvaluateLeafStats(tData);		
+const bool mStoreRays= true;
+		//-- store additional info
+		if (mStoreRays)
+		{
+			KdLeaf *leaf = dynamic_cast<KdLeaf *>(newNode);
+
+			RayInfoContainer::const_iterator it, it_end = tData.mRays->end();
+
+			for (it = tData.mRays->begin(); it != it_end; ++ it)
+			{
+				(*it).mRay->Ref();			
+				leaf->mVssRays.push_back((*it).mRay);
+			}
+		}
 	}
 	
@@ -3250,5 +3304,8 @@
 	// compute locally best split plane
 	const bool success = 
-		SelectSplitPlane(splitCandidate.mParentData, splitCandidate.mSplitPlane, frontProb, backProb);
+		SelectSplitPlane(splitCandidate.mParentData, 
+						 splitCandidate.mSplitPlane, 
+						 frontProb, 
+						 backProb);
 
 	float oldRenderCost;
@@ -3275,5 +3332,6 @@
 
 	splitCandidate.mMaxCostMisses = 
-		success ? splitCandidate.mParentData.mMaxCostMisses : splitCandidate.mParentData.mMaxCostMisses + 1;
+		success ? splitCandidate.mParentData.mMaxCostMisses : 
+	splitCandidate.mParentData.mMaxCostMisses + 1;
 }
 
@@ -3305,4 +3363,6 @@
 	// the node became a leaf -> evaluate stats for leafs
 	KdLeaf *leaf = data.mNode;
+	
+	++ mCreatedLeaves;
 
 	if (data.mPvs > mOspStats.maxPvs)
@@ -3324,7 +3384,4 @@
 	}
 
-//	if (data.mPvs < mTermMinPvs)
-//		++ mOspStats.minPvsNodes;
-
 	if (data.mProbability <= mTermMinProbability)
 		++ mOspStats.minProbabilityNodes;
@@ -3332,6 +3389,10 @@
 	// accumulate depth to compute average depth
 	mOspStats.accumDepth += data.mDepth;
-
-	++ mCreatedLeaves;
+ 
+	//	if ((int)(leaf->mObjects.size()) < mTermMinCost)
+	//     ++ mOspStats.minCostNodes;
+ 
+	if ((int)(leaf->mObjects.size()) > mOspStats.maxObjectRefs)
+		mOspStats.maxObjectRefs = (int)leaf->mObjects.size();
 
 #ifdef _DEBUG
@@ -3500,10 +3561,10 @@
 	//      << "\t pb=(" << volBack << ")\t pf=(" << volFront << ")" << endl;
 
-	Debug << "\n§§§§ eval local cost §§§§" << endl
+/*	Debug << "\n§§§§ eval local cost §§§§" << endl
 		  << "back pvs: " << pvsBack << " front pvs: " << pvsFront << " total pvs: " << totalPvs << endl 
 		  << "back p: " << volBack / viewSpaceVol << " front p " << volFront / viewSpaceVol << " p: " << totalVol / viewSpaceVol << endl
 		  << "old rc: " << oldRenderCost / viewSpaceVol << " new rc: " << newRenderCost / viewSpaceVol << endl
 		  << "render cost decrease: " << oldRenderCost / viewSpaceVol - newRenderCost / viewSpaceVol << endl;
-
+*/
 	if (oldRenderCost < newRenderCost)
 		Debug << "\nwarning!!:\n" << "old rc: " << oldRenderCost * viewSpaceVol << " new rc: " << newRenderCost * viewSpaceVol << endl;
@@ -3552,7 +3613,19 @@
 
 		const bool positive = ray->HasPosDir(axis);
-		
+	
+		if (EndPointInsideNode(leaf, *ray, true))
+		{
+			pos = ray->mTermination[axis];
+
+			mSplitCandidates->push_back(
+				SortableEntry(SortableEntry::BOX_INTERSECT, 
+							  pos, 
+							  ray->mTerminationObject, 
+							  ray)
+							  );
+		}
+
 		// if hitpoint with object is inside this node
-		if (ray->mOriginObject && (GetLeaf(ray->mOrigin, ray->mOriginNode) == leaf))
+		if (EndPointInsideNode(leaf, *ray, false))
 		{
 			pos = ray->mOrigin[axis];
@@ -3562,16 +3635,4 @@
 							  pos, 
 							  ray->mOriginObject, 
-							  ray)
-							  );
-		}
-
-		if (ray->mTerminationObject && (GetLeaf(ray->mTermination, ray->mTerminationNode) == leaf))
-		{
-			pos = ray->mTermination[axis];
-
-			mSplitCandidates->push_back(
-				SortableEntry(SortableEntry::BOX_INTERSECT, 
-							  pos, 
-							  ray->mTerminationObject, 
 							  ray)
 							  );
@@ -3670,5 +3731,5 @@
 		// if hitpoint with one of the objects is inside this node, we
 		// evaluate the volume of the view cells seen by this ray
-		if (ray->mOriginObject && (GetLeaf(ray->mOrigin, ray->mOriginNode) == leaf))
+		if (EndPointInsideNode(leaf, *ray, true))
 		{
             vol += PrepareHeuristics(*ray, newViewCells);
@@ -3677,5 +3738,5 @@
 
 		// count double if both hit points are within the kd node
-		if (ray->mTerminationObject && (GetLeaf(ray->mTermination, ray->mTerminationNode) == leaf))
+		if (EndPointInsideNode(leaf, *ray, false))
 		{
 			vol += PrepareHeuristics(*ray, newViewCells);
@@ -3684,5 +3745,5 @@
 	}
 
-	//Debug << "vol: " << vol << endl;
+	
 	return vol;
 }
@@ -3716,6 +3777,6 @@
 				// process ray if the hit point with termination / origin object 
 				// is inside this kd leaf
-				if ((ray->mOriginObject && (GetLeaf(ray->mOrigin, ray->mOriginNode) == leaf)) ||
-					(ray->mTerminationObject && (GetLeaf(ray->mTermination, ray->mTerminationNode) == leaf)))
+				if (EndPointInsideNode(leaf, *ray, true) ||
+					EndPointInsideNode(leaf, *ray, false))
 				{
 					EvalVolumeContribution(*ray, volLeft, volRight);
@@ -3881,5 +3942,5 @@
 	if (isTermination)
 	{
-		 return ray.mTerminationObject && (GetLeaf(ray.mTermination, ray.mOriginNode) == leaf);
+		 return ray.mTerminationObject && (GetLeaf(ray.mTermination, ray.mTerminationNode) == leaf);
 	}
 	else
@@ -3945,4 +4006,26 @@
 
 
+static bool ViewCellHasMultipleReferences(Intersectable *obj, 
+										  ViewCell *vc, 
+										  bool checkOnlyMailed)
+{
+	ViewCellPvsData *vdata = obj->mViewCellPvs.Find(vc);
+
+	if (vdata)
+	{
+		//Debug << "sumpdf: " << vdata->mSumPdf << endl;
+		// more than one view cell sees this object inside different kd cells
+		if (!checkOnlyMailed || !vdata->Mailed())
+		{
+			vdata->Mail();//return true;
+			if (vdata->mSumPdf > 1.5f) 
+				return true;
+		}
+	}
+
+	return false;
+}
+
+
 float OspTree::EvalRenderCostDecrease(const AxisAlignedPlane &candidatePlane,
 									  const OspTraversalData &tData,
@@ -3958,11 +4041,8 @@
 	float pFrontAndBack = 0;
 
-
 	const float viewSpaceVol = mVspTree->GetBoundingBox().GetVolume();
 
-	//Intersectable::NewMail();
-	KdLeaf::NewMail();
-	ViewCell::NewMail();
-
+	Intersectable::NewMail(3);
+	
 	KdLeaf *leaf = tData.mNode;
 	const int totalPvs = (int)leaf->mObjects.size();
@@ -3983,4 +4063,5 @@
 		{
 			++ pvsFront;
+			obj->Mail();		
 		}
 
@@ -3988,6 +4069,17 @@
 		{
 			++ pvsBack;
-		}
-	}
+
+			if (obj->Mailed())
+				obj->Mail(2);
+			else 
+				obj->Mail(1);
+		}
+
+		//Debug << "here3 pt: " << obj << " mail: " << obj->mMailbox - Intersectable::sMailId << endl;
+	}
+
+	
+	ViewCellContainer touchedViewCells;
+	RayInfoContainer touchedRays;
 
 	// sum up volume seen from the objects of left and right children
@@ -3996,6 +4088,5 @@
 
 	RayInfoContainer::const_iterator rit, rit_end = tData.mRays->end();
-
-	ViewCellContainer collectedViewCells;
+	//map<Intersectable *, ViewCellContainer> objectsMap;
 
 	for (rit = tData.mRays->begin(); rit < rit_end; ++ rit)
@@ -4009,4 +4100,5 @@
 		if (originInside || terminationInside)
 		{
+			touchedRays.push_back(*rit);
 			// add volume to volumes of left and / or right children
 			// if one of the ray end points is inside
@@ -4026,20 +4118,100 @@
 				// if not previously mailed
 				if (!vc->Mailed() && !vc->Mailed(1) && !vc->Mailed(2))
-					collectedViewCells.push_back(vc);
-
-				// classify / mail the view cell
-				MailViewCell(*vit, classification);	
-			}
-		}
-	}
-
-
-	// evaluate view cells volume contribution with respect to the mail box classification
-	ViewCellContainer::const_iterator vit, vit_end = collectedViewCells.end();
-
-	for (vit = collectedViewCells.begin(); vit != vit_end; ++ vit)
+				{
+					touchedViewCells.push_back(vc);
+				}
+
+                // classify / mail the view cell
+				MailViewCell(vc, classification);	
+
+				/*if (terminationInside)
+					objectsMap[ray->mTerminationObject].push_back(vc);
+				if (originInside)
+					objectsMap[ray->mOriginObject].push_back(vc);*/
+			}
+		}
+	}
+
+	// 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;
+	
+	ViewCellPvsData::NewMail();
+
+	for (rit = touchedRays.begin(); rit != touchedRays.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 (EndPointInsideNode(leaf, *ray, true))
+			{	
+				Intersectable *obj = ray->mTerminationObject;
+				
+				const bool renderCostWrong = 
+					ViewCellHasMultipleReferences(obj, viewCell, true);
+			//	if(!obj->Mailed()){
+			//	Debug << "pt: " << obj << endl;
+			//	Debug << "vc mail: " << viewCell->mMailbox - ViewCell::sMailId << " obj mail: " << obj->mMailbox << " "<< Intersectable::sMailId << " " <<obj->mMailbox - Intersectable::sMailId << endl;
+			//	obj->Mail();
+			//	}
+				// 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 (EndPointInsideNode(leaf, *ray, false))
+			{
+				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();
+				}
+			}
+		}
+	}
+
+	/////////////////////////////
 
 
@@ -4057,5 +4229,6 @@
 	// 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;
+	const float newRenderCost = pvsFront * pFront + pvsBack * pBack + totalPvs * pFrontAndBack
+		+ additionalFrontRenderCost + additionalBackRenderCost;
 
 	// normalize volume with view space volume
@@ -4067,6 +4240,11 @@
 		  << " 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;
-		  
+		  << "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;
@@ -4383,4 +4561,135 @@
 
 
+int OspTree::SplitViewCells(const AxisAlignedPlane &candidatePlane,
+							const RayInfoContainer &rays,
+							KdLeaf *leaf,							
+							ViewCellContainer &frontViewCells,
+							ViewCellContainer &backViewCells,
+							ViewCellContainer &frontAndBackViewCells) const 
+{
+	ViewCellContainer touchedViewCells;
+	RayInfoContainer touchedRays;
+
+	// 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 = 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
+		const bool originInside = EndPointInsideNode(leaf, *ray, false);
+        const bool terminationInside = EndPointInsideNode(leaf, *ray, true);
+
+		if (originInside || terminationInside)
+		{
+			touchedRays.push_back(*rit);
+			// 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(*vit, classification);	
+			}
+		}
+	}
+	
+	// the important view cells
+	ViewCellContainer::const_iterator vit, vit_end = touchedViewCells.end();
+
+	for (vit = touchedViewCells.begin(); vit != vit_end; ++ vit)
+	{
+		ViewCell *vc = *vit;
+
+		if (vc->Mailed())
+			frontViewCells.push_back(vc);
+		else if (vc->Mailed(1))
+			backViewCells.push_back(vc);
+		else if (vc->Mailed(2))
+			frontAndBackViewCells.push_back(vc);
+	}
+
+	return 0;
+}
+
+
+int OspTree::CheckViewCellsPvs(KdLeaf *leaf, 
+							   const RayInfoContainer &rays) const
+{
+	RayInfoContainer::const_iterator rit, rit_end = rays.end();
+
+	Intersectable::NewMail();
+	ObjectContainer touchedObjects;
+	
+
+	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
+		const bool originInside = EndPointInsideNode(leaf, *ray, false);
+        const bool terminationInside = EndPointInsideNode(leaf, *ray, true);
+
+		if (terminationInside)
+		{
+			Intersectable *obj = ray->mTerminationObject;
+
+			if (!obj->Mailed())
+			{
+				obj->Mail();
+				touchedObjects.push_back(obj);
+			}
+		}
+
+		if (originInside)
+		{
+			Intersectable *obj = ray->mOriginObject;
+
+			if (!obj->Mailed())
+			{
+				obj->Mail();
+				touchedObjects.push_back(obj);
+			}
+		}
+	}
+	Debug << "here65 " << touchedObjects.size() << endl;
+	ObjectContainer::const_iterator it, it_end = touchedObjects.end();
+	for (it = touchedObjects.begin(); it != it_end; ++ it)
+	{
+		Debug << "\nhere94 obj: " << (*it) << " size: " << (*it)->mViewCellPvs.GetSize() << endl << endl;
+		ViewCellPvsMap::const_iterator mit, mit_end = (*it)->mViewCellPvs.mEntries.end();
+
+		for (mit = (*it)->mViewCellPvs.mEntries.begin(); mit != mit_end; ++ mit)
+		{
+			Debug << "newsumpdf: " << (*mit).second.mSumPdf << endl;
+		}
+	}
+
+	return 0;
+}
+
+
+
+
 KdIntersectable *OspTree::GetOrCreateKdIntersectable(KdNode *node)
 {
@@ -4448,4 +4757,6 @@
 }
 */
+
+
 void OspTree::MailViewCell(ViewCell *vc, const int cf) const
 {
@@ -4501,5 +4812,6 @@
 
 
-float OspTree::EvalViewCellsVolume(KdLeaf *leaf, const RayInfoContainer &rays) const
+float OspTree::EvalViewCellsVolume(KdLeaf *leaf, 
+								   const RayInfoContainer &rays) const
 {
 	float vol = 0;
@@ -4514,6 +4826,6 @@
 		// process ray if the hit point with termination / origin object 
 		// is inside this kd leaf
-		if (!((ray->mOriginObject && (GetLeaf(ray->mOrigin, ray->mOriginNode) == leaf)) ||
-			  (ray->mTerminationObject && (GetLeaf(ray->mTermination, ray->mTerminationNode) == leaf))))
+		if (!((EndPointInsideNode(leaf, *ray, true)) ||
+			  (EndPointInsideNode(leaf, *ray, false))))
 			continue;
 		
@@ -4536,4 +4848,221 @@
 
 	return vol;
+}
+
+
+bool OspTree::AddViewCellToObjectPvs(Intersectable *obj, 
+									 ViewCell *vc, 
+									 float &contribution,
+									 bool onlyMailed) const
+{	
+	contribution = 0; // todo
+
+	ViewCellPvsData *vdata = obj->mViewCellPvs.Find(vc);
+
+	if (!vdata)
+	{
+		vdata = obj->mViewCellPvs.AddSample2(vc, 1);
+	}
+	else if (!onlyMailed || !vdata->Mailed())
+	{
+		obj->mViewCellPvs.AddSample(vc, 1);
+	}
+	
+	vdata->Mail();
+
+	return true;
+}
+
+
+int OspTree::UpdateViewCellsPvs(KdLeaf *leaf, 
+								const RayInfoContainer &rays) const
+
+{
+	RayInfoContainer::const_iterator rit, rit_end = rays.end();
+
+	//ViewCell::NewMail(); Intersectable::NewMail();
+	ViewCellPvsData::NewMail();
+
+	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
+		const bool originInside = EndPointInsideNode(leaf, *ray, false);
+        const bool terminationInside = EndPointInsideNode(leaf, *ray, true);
+
+		if (originInside || terminationInside)
+		{
+			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);
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+
+
+int OspTree::RemoveParentViewCellsPvs(KdLeaf *leaf, 
+									  const RayInfoContainer &rays
+									  ) const
+
+{
+	RayInfoContainer::const_iterator rit, rit_end = rays.end();
+	//ViewCell::NewMail(); Intersectable::NewMail();
+	ViewCellPvsData::NewMail();
+
+	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
+		const bool originInside = EndPointInsideNode(leaf, *ray, false);
+        const bool terminationInside = EndPointInsideNode(leaf, *ray, true);
+
+		if (originInside || terminationInside)
+		{
+			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)
+				{
+					ViewCellPvsData *vdata = obj->mViewCellPvs.Find(vc);
+
+					if (vdata && !vdata->Mailed())
+					{
+						vdata->Mail();
+						obj->mViewCellPvs.RemoveSample(vc, 1);
+					}
+					
+				}
+
+				obj = ray->mOriginObject;
+				if (obj)
+				{
+					ViewCellPvsData *vdata = obj->mViewCellPvs.Find(vc);
+
+					if (vdata && !vdata->Mailed())
+					{
+						vdata->Mail();
+						obj->mViewCellPvs.RemoveSample(vc, 1);
+					}
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+
+
+float OspTree::EvalRenderCost()
+{
+	float rc = 0;
+float prop = mVspTree->GetBoundingBox().GetVolume();	
+	KdLeafContainer leaves;
+	CollectLeaves(leaves);
+
+	KdLeafContainer::const_iterator kit, kit_end = leaves.end();
+	for (kit = leaves.begin(); kit != kit_end; ++ kit)
+	{
+		KdLeaf *leaf = *kit;
+		float newCost = 0;
+		float vol = 0;
+
+		ViewCell::NewMail();
+		VssRayContainer::const_iterator rit, rit_end = leaf->mVssRays.end();
+		ViewCellContainer touchedViewCells;
+
+		for (rit = leaf->mVssRays.begin(); rit != rit_end; ++ rit)
+		{
+			VssRay *ray = *rit;
+			
+			// test if intersection point with one of the objects is inside this node
+			const bool originInside = EndPointInsideNode(leaf, *ray, false);
+			const bool terminationInside = EndPointInsideNode(leaf, *ray, true);
+
+			if (originInside || terminationInside)
+			{
+				ViewCellContainer viewCells;
+				mVspTree->GetViewCells(*ray, viewCells);
+			
+				ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
+
+				for (vit = viewCells.begin(); vit != vit_end; ++ vit)
+				{
+					ViewCell *vc = *vit;
+
+					// if not previously mailed
+					if (!vc->Mailed())
+					{
+						vc->Mail();
+						vc->GetPvs().Clear();
+						touchedViewCells.push_back(vc);
+					}
+
+        		}
+			}
+		}
+		
+		//ViewCellPvsData::NewMail();
+		ObjectContainer::const_iterator oit, oit_end = leaf->mObjects.end();
+
+		for (oit = leaf->mObjects.begin(); oit != oit_end; ++ oit)
+		{
+			Intersectable *obj = *oit;
+			ViewCellContainer::const_iterator vit, vit_end = touchedViewCells.end();
+
+			for (vit = touchedViewCells.begin(); vit != vit_end; ++ vit)
+			{
+				ViewCell *vc = *vit;
+				ObjectPvsData *vdata = vc->GetPvs().Find(obj);
+
+				if (!vdata)
+				{
+					vc->GetPvs().AddSample(obj, 1);
+					newCost += vc->GetVolume();
+					//prop += vc->GetVolume();
+				}
+			}
+		}
+
+		rc += newCost;
+	}
+
+	return rc / prop;
 }
 
@@ -4657,9 +5186,14 @@
 	mOspTree.mRoot = kdleaf;
 	
+	// probabilty is voume of all "seen" view cells
+#if 1
 	const float prop = mOspTree.EvalViewCellsVolume(kdleaf, rays);
-
-	//-- add first candidate for view space partition
-
-	// first osp traversal data
+#else
+	const float prop = mVspTree.GetBoundingBox().GetVolume();
+#endif
+
+	//-- add first candidate for object space partition
+
+	// create osp traversal data
 	OspTree::OspTraversalData oData(kdleaf,
 									0,
@@ -4670,5 +5204,5 @@
 
 		
-	// compute first split candidate
+	// first split candidate
 	OspTree::OspSplitCandidate *oSplitCandidate = 
 		new OspTree::OspSplitCandidate(oData);
@@ -4676,5 +5210,7 @@
 	mOspTree.EvalSplitCandidate(*oSplitCandidate);
 
-	mOspTree.mTotalCost = (float)objects.size() * prop / mVspTree.GetBoundingBox().GetVolume();
+	mOspTree.mTotalCost = (float)objects.size() * prop / 
+		mVspTree.GetBoundingBox().GetVolume();
+
 	mOspTree.EvalSubdivisionStats(*oSplitCandidate);
 
@@ -4793,8 +5329,8 @@
 			++ mGlobalCostMisses;
 	
-		Debug << "\n**********" << endl
+		/*Debug << "\n**********" << endl
 			  << "total cost: " << mTotalCost << " render cost decr: " 
 			  << splitCandidate->GetRenderCostDecrease() 
-			  << " cost ratio: " << costRatio << endl << endl;
+			  << " cost ratio: " << costRatio << endl << endl;*/
 
 		//-- subdivide leaf node
@@ -4876,8 +5412,14 @@
 	cout << "starting osp contruction ... " << endl;
 
+	// start with one big kd cell - all objects can be seen from everywhere
+	// note: only true for view space = object space
+
 	// compute first candidate
 	OspTree::OspSplitCandidate *osc =
 		PrepareOsp(sampleRays, objects, forcedViewSpace, *objectSpaceRays);
 
+	Debug << "reseting cost, new total cost: " << mTotalCost << endl;
+	mTotalCost = mOspTree.mTotalCost;
+
     mTQueue.Push(osc);
 
@@ -4886,12 +5428,5 @@
 
 	startTime = GetTime();
-
-	// reset cost
-	// start with one big kd cell - all objects can be seen from everywhere
-	// note: only true for view space = object space
-	mTotalCost = (float)osc->mParentData.mNode->mObjects.size();//(float)sc->mParentData.mPvs;
-	
-	Debug << "reseting cost, new total cost: " << mTotalCost << endl;
-
+	
 	// process object space candidates
 	RunConstruction(repairQueue);
@@ -4901,4 +5436,27 @@
 	mOspTree.mOspStats.Stop();
 
+	float rc = mOspTree.EvalRenderCost();
+
+	Debug << "My render cost evalulation: " << rc << endl;
+
+	
+
+
+ViewCellContainer leaves;
+
+mVspTree.CollectViewCells(leaves, false);
+float rc2 = 0;
+	ViewCellContainer::const_iterator vit, vit_end = leaves.end();
+	for (vit = leaves.begin(); vit != vit_end; ++ vit)
+	{
+		ViewCell *vc = *vit;
+
+		int pvs = vc->GetPvs().CountObjectsInPvs();
+		float vol = vc->GetVolume();
+		rc2 += (float)pvs * vol;
+
+	}
+	
+	Debug << "here225 " << rc2 / mVspTree.GetBoundingBox().GetVolume()<<endl;
 #if 0
 	// reset parameters
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Containers.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Containers.h	(revision 1072)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Containers.h	(revision 1184)
@@ -17,4 +17,5 @@
 class Ray;
 class Mesh;
+class KdLeaf;
 
 struct IndexedBoundingBox;
@@ -55,4 +56,10 @@
 typedef vector<IndexedBoundingBox> IndexedBoundingBoxContainer;
 
+/** Container for ViewCell pointers primarily for the use within the kDTree and
+    BSP hierarchies */
+
+typedef vector<KdLeaf *> KdLeafContainer;
+
+
 typedef std::map<int, Intersectable *> ObjectMap;
 
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/BoostPreprocessorThread.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/BoostPreprocessorThread.cpp	(revision 1166)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/BoostPreprocessorThread.cpp	(revision 1184)
@@ -29,6 +29,6 @@
 		// camera.LookAtBox(mPreprocessor->mKdTree->GetBox());
 		//	camera.LookInBox(mPreprocessor->mKdTree->GetBox());
-		camera.SetPosition(Vector3(3473, 6.778, -1699));
-		camera.SetDirection(Vector3(-0.2432, 0, 0.97));
+		camera.SetPosition(Vector3(3473, 6.778f, -1699.0f));
+		camera.SetDirection(Vector3(-0.2432f, 0, 0.97f));
 		//	camera.SetPosition(Vector3(991.7, 187.8, -271));
 		//	camera.SetDirection(Vector3(0.9, 0, -0.4));
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1180)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1184)
@@ -1889,6 +1889,8 @@
 														   ray.mPdf,
 														   contribution))
+			  {
 				++ ray.mPvsContribution;
-			  ray.mRelativePvsContribution += contribution;
+			  	  ray.mRelativePvsContribution += contribution;
+			  }
 			}
 			// for directional sampling it is important to count only contributions
@@ -4810,5 +4812,5 @@
 	mOspTree->SetViewCellsManager(this);
 
-	mVspTree->mViewCellsTree = mViewCellsTree;
+	mVspTree->SetViewCellsTree(mViewCellsTree);
 }
 
@@ -5726,9 +5728,7 @@
 }
 
-#if 1
+#if TEST_EVALUATION
 void VspOspViewCellsManager::EvalViewCellPartition()
 {
-	int samplesPerPass;
-	int numSamples;
 	int castSamples = (int)storedRays.size();
 
@@ -5746,4 +5746,5 @@
 		
 	const bool startFromZero = true;
+
 
 	// reset pvs and start over from zero
@@ -5787,4 +5788,21 @@
 	string fileName = string(statsPrefix) + string(s);
 
+	ViewCellContainer leaves;
+
+	mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
+float rc = 0;
+	ViewCellContainer::const_iterator vit, vit_end = leaves.end();
+	for (vit = leaves.begin(); vit != vit_end; ++ vit)
+	{
+		ViewCell *vc = *vit;
+
+		int pvs = vc->GetPvs().CountObjectsInPvs();
+		float vol = vc->GetVolume();
+		rc += pvs * vol;
+
+	}
+	
+	Debug << "here295 " << rc / mVspTree->GetBoundingBox().GetVolume();
+
 	mViewCellsTree->ExportStats(fileName);
 	
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h	(revision 1168)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h	(revision 1184)
@@ -28,7 +28,33 @@
 template<typename T> 
 struct PvsData {
-  //  int mVisibleSamples;
+////////////////////////////
+//  Mailing stuff
+protected:
+	int mMailbox;
+
+public:
+  // last mail id -> warning not thread safe!
+  // both mailId and mailbox should be unique for each thread!!!
+  static int sMailId;
+  static int sReservedMailboxes;
+  
+  
+	static void NewMail(const int reserve = 1) {
+		sMailId += sReservedMailboxes;
+		sReservedMailboxes = reserve;
+	}
+	
+	void Mail() { mMailbox = 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; }
+//////////////////////////////////////////
+
   // sum of probability density of visible sample rays
   float mSumPdf;
+
   PvsData<T>() {}
   PvsData<T>(const float sumPdf):
@@ -37,6 +63,12 @@
   // $$JB in order to return meaningfull values
   // it assumes that the sum pdf has been normalized somehow!!!
-  float GetVisibility() { return mSumPdf; }
+  float GetVisibility() 
+  { 
+	  return mSumPdf; 
+  }
 };
+
+template<typename T> int PvsData<T>::sMailId = 1;
+template<typename T> int PvsData<T>::sReservedMailboxes = 1;
 
 /** Template class representing the Potentially Visible Set (PVS) 
@@ -89,4 +121,9 @@
   float AddSample(T sample, const float pdf);
   
+  /** Adds sample to PVS.
+	  @returns PvsData
+  */
+  PvsData<T> *AddSample2(T sample, const float pdf);
+
   /** Adds one pvs to another one.
 	  @returns new pvs size
@@ -291,4 +328,20 @@
 
 template <typename T>
+PvsData<T> *
+Pvs<T>::AddSample2(T sample, const float pdf)
+{
+  PvsData<T> *data = Find(sample);
+  
+  if (data)  {
+	data->mSumPdf += pdf;
+  }
+  else {
+	mEntries[sample] = PvsData<T>(pdf);
+	data = Find(sample);
+  }
+  return data;
+}
+
+template <typename T>
 bool
 Pvs<T>::AddSample(T sample,
@@ -437,6 +490,7 @@
 typedef PvsData<KdNode *> KdPvsData;
 
-//typedef Pvs<Intersectable *> ObjectPvs;
 typedef Pvs<ViewCell *> ViewCellPvs;
+typedef PvsData<ViewCell *> ViewCellPvsData;
+
 }
 
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.h	(revision 1181)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.h	(revision 1184)
@@ -180,4 +180,5 @@
 		invalidLeaves = 0;
 		accumRays = 0;
+		maxObjectRefs = 0;
 	}
 
@@ -272,4 +273,6 @@
 		invalidLeaves = 0;
 		objectRefs = 0;
+
+		maxObjectRefs = 0;
 	}
 
@@ -778,8 +781,8 @@
 
 
-	/// pointer to the hierarchy of view cells
-	ViewCellsTree *mViewCellsTree;
-
-	OspTree *mOspTree;
+	ViewCellsTree *GetViewCellsTree() const { return mViewCellsTree; }
+
+	void SetViewCellsTree(ViewCellsTree *vt) { mViewCellsTree = vt; }
+
 
 protected:
@@ -1020,5 +1023,5 @@
 	bool AddKdLeafToPvs(KdLeaf *leaf, 
 						ViewCell *vc, 
-						float &pvs, 
+						const float pvs, 
 						float &contribution);
 
@@ -1062,6 +1065,12 @@
 
 
+
 protected:
 
+
+	/// pointer to the hierarchy of view cells
+	ViewCellsTree *mViewCellsTree;
+
+	OspTree *mOspTree;
 
 	bool mUseKdPvsForHeuristics;
@@ -1413,4 +1422,5 @@
 	void SetViewCellsTree(ViewCellsTree *vt) { mViewCellsTree = vt; }
 
+	float EvalRenderCost();
 
 protected:
@@ -1571,7 +1581,15 @@
 	*/
 	int SplitRays(const AxisAlignedPlane &plane,
-				  RayInfoContainer &rays, 
-			      RayInfoContainer &frontRays, 
-				  RayInfoContainer &backRays) const;
+		RayInfoContainer &rays, 
+		RayInfoContainer &frontRays, 
+		RayInfoContainer &backRays) const;
+
+	int SplitViewCells(
+		const AxisAlignedPlane &candidatePlane,
+		const RayInfoContainer &rays,
+		KdLeaf *leaf,
+		ViewCellContainer &frontViewCells,
+		ViewCellContainer &backViewCells,
+		ViewCellContainer &frontAndBackViewCells) const;
 
 	/** Adds the object to the pvs of the front and back leaf with a given classification.
@@ -1625,5 +1643,5 @@
 									float &volRight);
 
-/** Evaluates the influence on the pvs of the event.
+	/** Evaluates the influence on the pvs of the event.
 		@param ve the visibility event
 		@param pvsLeft updates the left pvs
@@ -1698,8 +1716,21 @@
 
 	float EvalViewCellsVolume(KdLeaf *leaf, const RayInfoContainer &rays) const;
-
+	
+	int RemoveParentViewCellsPvs(KdLeaf *leaf, 
+									  const RayInfoContainer &rays
+									  ) const;
+
+	int UpdateViewCellsPvs(KdLeaf *leaf, const RayInfoContainer &rays) const;
+int OspTree::CheckViewCellsPvs(KdLeaf *leaf, 
+							   const RayInfoContainer &rays) const;
+	bool AddViewCellToObjectPvs(
+		Intersectable *obj,
+		ViewCell *vc, 
+		float &contribution,
+		bool onlyMailed) const;
 
 protected:
 
+	
 	/// pointer to the hierarchy of view cells
 	ViewCellsTree *mViewCellsTree;
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.cpp	(revision 1176)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.cpp	(revision 1184)
@@ -370,5 +370,5 @@
     rayRefs/(double)Leaves() << "\n";
 
-  app << "#N_MAXOBJECTREFS  ( Max number of rayRefs / leaf )\n" <<
+  app << "#N_MAXOBJECTREFS  ( Max number of object refs / leaf )\n" <<
     maxObjectRefs << "\n";
 
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.h	(revision 1176)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.h	(revision 1184)
@@ -10,4 +10,6 @@
 #include "Pvs.h"
 #include "Viewcell.h"
+#include "VssRay.h"
+
 
 namespace GtpVisibilityPreprocessor {
@@ -216,4 +218,6 @@
   KdViewCell *mViewCell;
 
+  VssRayContainer mVssRays;
+
    /// Objects that are referenced in more than one leaf.
   ObjectContainer mMultipleObjects;
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.h	(revision 1176)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.h	(revision 1184)
@@ -5,4 +5,5 @@
 #include "Pvs.h"
 #include <set>
+#include "VssRay.h"
 
 namespace GtpVisibilityPreprocessor {
@@ -33,5 +34,5 @@
   /// kd leaves that this intersectable belongs to
   //set<KdLeaf *> mKdLeaves;
-
+VssRayContainer mVssRays;
   /// # of object references
   int mReferences;
@@ -50,4 +51,6 @@
 	int GetId() { return mId; }
 	
+////////////////////////////////////////////////
+//	Mailing stuff
 
 	static void NewMail(const int reserve = 1) {
@@ -64,5 +67,5 @@
 	int IncMail() { return ++ mMailbox - sMailId; }
 
-
+////////////////////////////////////////////////////
     virtual AxisAlignedBox3 GetBox() const = 0;
 	virtual int CastRay(GtpVisibilityPreprocessor::Ray &ray) = 0;
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.cpp	(revision 1176)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.cpp	(revision 1184)
@@ -47,5 +47,5 @@
 
 				// already processed node (= objects in pvs)?
-				if (!node->Mailed())
+				if (0 ||!node->Mailed())
 				{
 					node->Mail();
@@ -54,5 +54,5 @@
 					{
 						KdLeaf *leaf = dynamic_cast<KdLeaf *>(node);
-                        
+#if 1                        
 						// add #objects exclusivly in this node
 						pvs += (int)(leaf->mObjects.size() - leaf->mMultipleObjects.size());
@@ -72,4 +72,18 @@
 							}
 						}
+#else	
+						ObjectContainer::const_iterator oit, oit_end = leaf->mObjects.end();
+						
+						for (oit = leaf->mObjects.begin(); oit != oit_end; ++ oit)
+						{
+							Intersectable *object = *oit;						
+                            
+							if (!object->Mailed())
+							{
+								object->Mail();
+								++ pvs;
+							}
+						}
+#endif
 					}
 					else // traverse tree
