Index: GTP/trunk/Lib/Vis/Preprocessing/src/VrmlExporter.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VrmlExporter.cpp	(revision 1139)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VrmlExporter.cpp	(revision 1141)
@@ -261,5 +261,5 @@
 
 				mForcedMaterial.mDiffuseColor.b = 1.0f;
-  				const float importance = (float)leaf->GetViewCell()->GetPvs().GetSize() / (float)maxPvs;
+  				const float importance = (float)leaf->GetViewCell()->GetPvs().CountPvs() / (float)maxPvs;
 
 				mForcedMaterial.mDiffuseColor.r = importance;
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 1137)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 1141)
@@ -854,5 +854,5 @@
 
 		// update scalar pvs size lookup
-		mViewCellsManager->SetScalarPvsSize(viewCell, viewCell->GetPvs().GetSize());
+		mViewCellsManager->SetScalarPvsSize(viewCell, viewCell->GetPvs().CountPvs());
 	
 
@@ -991,5 +991,5 @@
 
 		// update scalar pvs size value
-		mViewCellsManager->SetScalarPvsSize(viewCell, viewCell->GetPvs().GetSize());
+		mViewCellsManager->SetScalarPvsSize(viewCell, viewCell->GetPvs().CountPvs());
 
 		mBspStats.contributingSamples += conSamp;
@@ -2343,5 +2343,5 @@
 			if (leaf->TreeValid() && 
 				(!onlyUnmailed || !leaf->Mailed()) &&
-				((maxPvsSize < 0) || (leaf->GetViewCell()->GetPvs().GetSize() <= maxPvsSize)))
+				((maxPvsSize < 0) || (leaf->GetViewCell()->GetPvs().CountPvs() <= maxPvsSize)))
 			{
 				leaves.push_back(leaf);
@@ -2420,5 +2420,5 @@
 		  << "PVS: " << data.mPvs << " (min: " << mTermMinPvs << "), "
 	  	  << "#rays: " << (int)data.mRays->size() << " (max: " << mTermMinRays << "), "
-		  << "#pvs: " << leaf->GetViewCell()->GetPvs().GetSize() << "), "
+		  << "#pvs: " << leaf->GetViewCell()->GetPvs().CountPvs() << "), "
 		  << "#avg ray contrib (pvs): " << (float)data.mPvs / (float)data.mRays->size() << endl;
 #endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h	(revision 1121)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h	(revision 1141)
@@ -655,5 +655,5 @@
 	/// if pvs should be exported with view cells
 	bool mExportPvs;
-
+// matt§§: need this?
 	bool mCountKdPvs;
 };
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 1139)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 1141)
@@ -2212,9 +2212,13 @@
 					"0.99");
 
-	RegisterOption("VspTree.useKdPvs",
-					optBool,
-					"vsp_pvs_use_kd_pvs=",
+	RegisterOption("VspTree.useKdPvsForHeuristics",
+					optBool,
+					"vsp_use_kd_pvs_for_heuristics=",
 					"true");
 
+	RegisterOption("VspTree.storeKdPvs",
+					optBool,
+					"vsp_storeKdPvs=",
+					"true");
 	
 /***************************************************************************/
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.cpp	(revision 1106)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.cpp	(revision 1141)
@@ -1948,5 +1948,5 @@
 		  << "#polygons: " << (int)data.mPolygons->size() << " (max: " << mTermMinPolys << "), "
 		  << "#rays: " << (int)data.mRays->size() << " (max: " << mTermMinRays << "), " 
-		  << "#pvs: " << leaf->GetViewCell()->GetPvs().GetSize() << "=, "
+		  << "#pvs: " << leaf->GetViewCell()->GetPvs().CountPvs() << "=, "
 		  << "#avg ray contrib (pvs): " << (float)data.mPvs / (float)data.mRays->size() << endl;
 #endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/X3dExporter.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/X3dExporter.cpp	(revision 1121)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/X3dExporter.cpp	(revision 1141)
@@ -297,5 +297,6 @@
 
 				mForcedMaterial.mDiffuseColor.b = 1.0f;
-  				const float importance = (float)leaf->GetViewCell()->GetPvs().GetSize() / (float)maxPvs;
+  				const float importance = 
+					(float)leaf->GetViewCell()->GetPvs().CountPvs() / (float)maxPvs;
 
 				mForcedMaterial.mDiffuseColor.r = importance;
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.cpp	(revision 1139)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.cpp	(revision 1141)
@@ -364,5 +364,5 @@
 	Environment::GetSingleton()->GetBoolValue("VspTree.simulateOctree", mCirculatingAxis);
 	
-	Environment::GetSingleton()->GetBoolValue("VspTree.useKdPvs", mUseKdPvs);
+	Environment::GetSingleton()->GetBoolValue("VspTree.useKdPvsForHeuristics", mUseKdPvsForHeuristics);
 
 	char subdivisionStatsLog[100];
@@ -400,5 +400,5 @@
 	Debug << "maxband: " << mMaxBand << endl;
 
-	if (!mUseKdPvs)
+	if (!mUseKdPvsForHeuristics)
 		Debug << "pvs count method: per object" << endl;
 	else
@@ -534,8 +534,8 @@
 	int conSamp = 0;
 	float sampCon = 0.0f;
-	AddToPvs(leaf, *tData.mRays, sampCon, conSamp);
+	AddSamplesToPvs(leaf, *tData.mRays, sampCon, conSamp);
 
 	// update scalar pvs size value
-	mViewCellsManager->SetScalarPvsSize(viewCell, viewCell->GetPvs().GetSize());
+	mViewCellsManager->SetScalarPvsSize(viewCell, viewCell->GetPvs().CountPvs());
 
 	mVspStats.contributingSamples += conSamp;
@@ -847,8 +847,51 @@
 
 
-void VspTree::AddToPvs(VspLeaf *leaf,
-					   const RayInfoContainer &rays,
-					   float &sampleContributions,
-					   int &contributingSamples)
+bool VspTree::AddKdLeafToPvs(KdLeaf *leaf, 
+							 ViewCell *vc, 
+							 float &pdf, 
+							 float &contribution)
+{
+	bool contri = false;
+
+#if 1 // add kd intersecable to pvs
+	KdIntersectable *kdObj = mOspTree->GetOrCreateKdIntersectable(leaf);
+	
+	if (vc->AddPvsSample(kdObj, pdf, contribution))
+	{
+		return true;
+	}
+
+#else // add all objects of kd node
+
+	pdf = 0;
+	contribution = 0;
+
+	ObjectContainer::const_iterator it, it_end = leaf->mObjects.end();
+
+	for (it = leaf->mObjects.begin(); it != it_end; ++ it)
+	{
+		Intersectable *object = *it;						
+
+		float newpdf;
+		float newcontri;
+						
+		if (vc->AddPvsSample(object, newpdf, newcontri))
+		{
+			contri = true;
+		}
+
+		pdf += newPdf;
+		newContri += contribution;
+	}
+
+#endif
+
+	return contri;
+}
+
+void VspTree::AddSamplesToPvs(VspLeaf *leaf,
+							 const RayInfoContainer &rays,
+							 float &sampleContributions,
+							 int &contributingSamples)
 {
 	sampleContributions = 0;
@@ -859,4 +902,5 @@
 	ViewCellLeaf *vc = leaf->GetViewCell();
   
+	
 	// add contributions from samples to the PVS
 	for (it = rays.begin(); it != it_end; ++ it)
@@ -875,17 +919,15 @@
 
 			// potentially visible kd cells
-			if (mUseKdPvs)
+			if (mStoreKdPvs)
 			{
 				KdLeaf *leaf = mOspTree->GetLeaf(ray->mTermination, ray->mTerminationNode);
-				KdIntersectable *kdObj = new KdIntersectable(leaf);
-
-				entry = kdObj;
+				AddKdLeafToPvs(leaf, vc, ray->mPdf, contribution);
 			}
 			else
-				entry = obj;
-
-			if (vc->AddPvsSample(obj, ray->mPdf, contribution))
-			{
-				madeContrib = true;
+			{
+				if (vc->AddPvsSample(obj, ray->mPdf, contribution))
+				{
+					madeContrib = true;
+				}
 			}
 
@@ -900,17 +942,15 @@
 
 			// potentially visible kd cells
-			if (mUseKdPvs)
-			{
-				KdLeaf *leaf = mOspTree->GetLeaf(ray->mOrigin, ray->mOriginNode);
-				KdIntersectable *kdObj = new KdIntersectable(leaf);
-
-				entry = kdObj;				
+			if (mUseKdPvsForHeuristics)
+			{
+				KdLeaf *leaf = mOspTree->GetLeaf(ray->mOrigin, ray->mOriginNode);	
+				AddKdLeafToPvs(leaf, vc, ray->mPdf, contribution);
 			}
 			else
-				entry = obj;
-
-			if (vc->AddPvsSample(obj, ray->mPdf, contribution))
-			{
-				madeContrib = true;
+			{
+				if (vc->AddPvsSample(obj, ray->mPdf, contribution))
+				{
+					madeContrib = true;
+				}
 			}
 
@@ -919,6 +959,8 @@
 
 		if (madeContrib)
+		{
 			++ contributingSamples;
-		
+		}
+
 		// store rays for visualization
 		if (0) leaf->mVssRays.push_back(new VssRay(*ray));
@@ -1056,5 +1098,5 @@
 		if (oObject)
 		{
-			if (!mUseKdPvs)
+			if (!mUseKdPvsForHeuristics)
 			{
 				if (!oObject->Mailed())
@@ -1080,5 +1122,5 @@
 		if (tObject)
 		{
-			if (!mUseKdPvs)
+			if (!mUseKdPvsForHeuristics)
 			{
 				if (!tObject->Mailed())
@@ -1166,5 +1208,5 @@
 	if (oObject)
 	{	
-		if (!mUseKdPvs)
+		if (!mUseKdPvsForHeuristics)
 		{
 			if (ci.type == SortableEntry::ERayMin)
@@ -1202,5 +1244,5 @@
 	if (tObject)
 	{	
-		if (!mUseKdPvs)
+		if (!mUseKdPvsForHeuristics)
 		{
 			if (ci.type == SortableEntry::ERayMin)
@@ -1615,5 +1657,5 @@
 			if (leaf->TreeValid() && 
 				(!onlyUnmailed || !leaf->Mailed()) &&
-				((maxPvsSize < 0) || (leaf->GetViewCell()->GetPvs().GetSize() <= maxPvsSize)))
+				((maxPvsSize < 0) || (leaf->GetViewCell()->GetPvs().CountPvs() <= maxPvsSize)))
 			{
 				leaves.push_back(leaf);
@@ -1692,5 +1734,5 @@
 		  << "PVS: " << data.mPvs << " (min: " << mTermMinPvs << "), "
 		  << "#rays: " << (int)data.mRays->size() << " (max: " << mTermMinRays << "), "
-		  << "#pvs: " << leaf->GetViewCell()->GetPvs().GetSize() << "), "
+		  << "#pvs: " << leaf->GetViewCell()->GetPvs().CountPvs() << "), "
 		  << "#avg ray contrib (pvs): " << (float)data.mPvs / (float)data.mRays->size() << endl;
 #endif
@@ -2707,4 +2749,14 @@
 }
 
+
+OspTree::~OspTree()
+{
+	KdIntersectableMap::iterator it, it_end = mKdIntersectables.end();
+
+	for (it = mKdIntersectables.begin(); it != mKdIntersectables.end(); ++ it)
+	{
+		DEL_PTR((*it).second);
+	}
+}
 
 
@@ -3895,4 +3947,21 @@
 
 
+KdIntersectable *OspTree::GetOrCreateKdIntersectable(KdNode *node)
+{
+	// search nodes
+	std::map<KdNode *, KdIntersectable *>::const_iterator it = mKdIntersectables.find(node);
+
+	if (it != mKdIntersectables.end()) 
+	{
+		return (*it).second;
+	}
+
+	// not in map => create new entry
+	KdIntersectable *kdObj= new KdIntersectable(node);
+
+	mKdIntersectables[node] = kdObj;
+
+	return kdObj;
+}
 
 
@@ -3900,5 +3969,4 @@
 /*               class HierarchyManager implementation              */
 /********************************************************************/
-
 
 
@@ -4068,6 +4136,9 @@
 	// makes no sense otherwise because only one kd cell available
 	// during view space partition
-	const bool savedCountMethod = mVspTree.mUseKdPvs;
-	mVspTree.mUseKdPvs = false;
+	const bool savedCountMethod = mVspTree.mUseKdPvsForHeuristics;
+	const bool savedStoreMethod = mVspTree.mStoreKdPvs;
+	
+	mVspTree.mUseKdPvsForHeuristics = false;
+	mVspTree.mStoreKdPvs = false;
 
 	mTQueue.Push(PrepareVsp(sampleRays, forcedViewSpace, *viewSpaceRays));
@@ -4148,5 +4219,6 @@
 	cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl;
 
-	mVspTree.mUseKdPvs = savedCountMethod;
+	mVspTree.mUseKdPvsForHeuristics = savedCountMethod;
+	mVspTree.mStoreKdPvs = savedStoreMethod;
 }
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1139)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1141)
@@ -226,6 +226,8 @@
 	// question: rather create view cells resource manager?
 	if (!ViewCellsTreeConstructed())
+	{
 		CLEAR_CONTAINER(mViewCells);
-	
+	}
+
 	DEL_PTR(mViewCellsTree);
 }
@@ -301,5 +303,5 @@
 				Ray *pray = (*it)->mPiercingRays[0];
 				Debug << "view cell " << (*it)->GetId() << " not empty, pvs: " 
-					  << (*it)->GetPvs().GetSize() << " " << (int)pray->intersections.size() << endl;
+					  << (*it)->GetPvs().CountPvs() << " " << (int)pray->intersections.size() << endl;
 
 				exporter->ExportRays((*it)->mPiercingRays);
@@ -1195,6 +1197,6 @@
 {
 
-	if ((vc->GetPvs().GetSize() > maxPvsSize) ||
-		(vc->GetPvs().GetSize() < minPvsSize))
+	if ((vc->GetPvs().CountPvs() > maxPvsSize) ||
+		(vc->GetPvs().CountPvs() < minPvsSize))
 	{
 		return false;
@@ -1412,6 +1414,6 @@
 	{
 		ViewCell *vc = *it;
-		totalRenderCost += vc->GetPvs().GetSize() * vc->GetVolume();
-		totalPvs += (int)vc->GetPvs().GetSize();
+		totalRenderCost += vc->GetPvs().CountPvs() * vc->GetVolume();
+		totalPvs += (int)vc->GetPvs().CountPvs();
 	}
 
@@ -1430,9 +1432,9 @@
 		ViewCell *vc = *it;
 
-		float renderCost = vc->GetPvs().GetSize() * vc->GetVolume();
+		float renderCost = vc->GetPvs().CountPvs() * vc->GetVolume();
 		float dev;
 
 		if (1)
-			dev = fabs(avgRenderCost - (float)vc->GetPvs().GetSize());
+			dev = fabs(avgRenderCost - (float)vc->GetPvs().CountPvs());
 		else
 			dev = fabs(expectedRenderCost - renderCost);
@@ -1591,5 +1593,5 @@
 
 	// update pvs size
-	vc->mPvsSize = vc->GetPvs().GetSize();
+	vc->mPvsSize = vc->GetPvs().CountPvs();
 	vc->mPvsSizeValid = true;
 
@@ -4065,5 +4067,5 @@
 	{
 		pvs = root->GetPvs();
-		SetScalarPvsSize(root, root->GetPvs().GetSize());
+		SetScalarPvsSize(root, root->GetPvs().CountPvs());
 		
 		return;
@@ -5464,5 +5466,4 @@
 		exporter->SetFilled();
 
-
 		if (1)
 		{	
@@ -5479,5 +5480,5 @@
 			exporter->SetForcedMaterial(m);
 
-			// find kd nodes
+			// export pvs entries
 			for (oit = pvs.mEntries.begin(); oit != oit_end; ++ oit)
 			{	
@@ -5488,20 +5489,4 @@
 					exporter->ExportIntersectable(obj);
 					obj->Mail();
-				}					
-				
-				// export "original" pvs
-				m.mDiffuseColor = RgbColor(0, 0, 1);
-				exporter->SetForcedMaterial(m);
-
-				if ((*oit).first->Type() == Intersectable::KD_INTERSECTABLE)
-				{
-					KdIntersectable *kdObj = dynamic_cast<KdIntersectable *>(obj);
-					Intersectable *hitObj = kdObj->mHitObject;
-				
-					if (!hitObj->Mailed())
-					{
-						exporter->ExportIntersectable(hitObj);
-						hitObj->Mail();
-					}	
 				}
 			}		
Index: GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp	(revision 1112)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp	(revision 1141)
@@ -1705,7 +1705,8 @@
   ViewCellContainer &viewcells = mViewCellsManager->GetViewCells();
   int maxPvs = -1;
-  for (i=0; i < viewcells.size(); i++) {
+  for (i=0; i < viewcells.size(); i++) 
+  {
 	ViewCell *vc = viewcells[i];
-	int p = vc->GetPvs().GetSize();
+	const int p = vc->GetPvs().CountPvs();
 	if (p > maxPvs)
 	  maxPvs = p;
@@ -1723,5 +1724,5 @@
 	  c = vc->GetColor();
 	else {
-	  float importance = (float)vc->GetPvs().GetSize() / (float)maxPvs;
+	  const float importance = (float)vc->GetPvs().CountPvs() / (float)maxPvs;
 	  c = RgbColor(importance, 1.0f - importance, 0.0f);
 	}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp	(revision 1139)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp	(revision 1141)
@@ -823,5 +823,7 @@
 
 	Debug << "updating active vc: " << (int)viewCells.size() << endl;
-	// find all already merged view cells and remove them from view cells
+	
+	// find all already merged view cells and remove them from the
+	// container view cells
 		
 	// sort out all view cells which are not active anymore, i.e., they
@@ -883,5 +885,5 @@
 		const int upper = mViewCellsManager->GetMaxPvsSize();
 
-		const float penalty = EvalPvsPenalty((*vit)->GetPvs().GetSize(), lower, upper);
+		const float penalty = EvalPvsPenalty((*vit)->GetPvs().CountPvs(), lower, upper);
 		
 		mDeviation += fabs(mAvgRenderCost - penalty);
@@ -943,9 +945,11 @@
 
 // TODO: should be done in view cells manager
-ViewCellInterior *ViewCellsTree::MergeViewCells(ViewCell *l, 
-												ViewCell *r, 
+ViewCellInterior *ViewCellsTree::MergeViewCells(ViewCell *left, 
+												ViewCell *right, 
 												int &pvsDiff) //const
 {
-	ViewCellInterior *vc = mViewCellsManager->MergeViewCells(l, r);
+	// create merged view cell
+	ViewCellInterior *vc = 
+		mViewCellsManager->MergeViewCells(left, right);
 
 	// if merge was unsuccessful
@@ -953,15 +957,17 @@
 
 	// set to the new parent view cell
-	l->SetParent(vc);
-	r->SetParent(vc);
-
-	// set new size of view cell
+	left->SetParent(vc);
+	right->SetParent(vc);
+
+	
 	if (mUseAreaForPvs)
 	{
-		vc->SetArea(l->GetArea() + l->GetArea());
+		// set new area of view cell
+		// not not correct, but costly to compute real area!!
+		vc->SetArea(left->GetArea() + right->GetArea());
 	}
 	else
-	{
-		vc->SetVolume(r->GetVolume() + l->GetVolume());
+	{	// set new volume of view cell
+		vc->SetVolume(left->GetVolume() + right->GetVolume());
 	}
 
@@ -971,32 +977,35 @@
 	vc->Mail();
 
-	const int pvs1 = l->GetPvs().GetSize();
-	const int pvs2 = r->GetPvs().GetSize();
-
-
-	// new view cells are stored in this vector
+	const int pvs1 = left->GetPvs().CountPvs();
+	const int pvs2 = right->GetPvs().CountPvs();
+
+
+	// the new view cells are stored in this container
 	mMergedViewCells.push_back(vc);
 
-	pvsDiff = vc->GetPvs().GetSize() - pvs1 - pvs2;
-
-
-
-	//Ždon't store intermediate pvs
+	pvsDiff = vc->GetPvs().CountPvs() - pvs1 - pvs2;
+
+
+	// don't store pvs in interior cells, just a scalar
 	if (mViewCellsStorage == PVS_IN_LEAVES)
 	{
-		l->mPvsSize = l->GetPvs().GetSize(); 
-		l->mPvsSizeValid = true;
+		left->mPvsSize = left->GetPvs().GetSize(); 
+		left->mPvsSizeValid = true;
 		
-		if (!l->IsLeaf())
-			l->GetPvs().Clear();
+		// remove pvs, we don't store interior pvss
+		if (!left->IsLeaf())
+		{
+			left->GetPvs().Clear();
+		}
+
+		right->mPvsSize = right->GetPvs().CountPvs(); 
+		right->mPvsSizeValid = true;
 		
-		r->mPvsSize = r->GetPvs().GetSize(); 
-		r->mPvsSizeValid = true;
-		
-		if (!r->IsLeaf())
-			r->GetPvs().Clear();
-	
-}
-
+		// remove pvs, we don't store interior pvss
+		if (!right->IsLeaf())
+		{
+			right->GetPvs().Clear();
+		}
+	}
 
 	return vc;
@@ -1258,4 +1267,5 @@
 		const float penalty = 
 			EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper);
+
 		return (mAvgRenderCost - penalty) * (mAvgRenderCost - penalty) / 
 			(float)mNumActiveViewCells;
@@ -1274,5 +1284,5 @@
 	if (1)
 	{
-		const float penalty = EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper);
+		const float penalty = EvalPvsPenalty(vc->GetPvs().CountPvs(), lower, upper);
 		return fabs(mAvgRenderCost - penalty) / (float)mNumActiveViewCells;
 	}
@@ -1283,11 +1293,12 @@
 
 
-
 float ViewCellsTree::GetRenderCost(ViewCell *vc) const
 {
 	if (mUseAreaForPvs)
-		return vc->GetPvs().GetSize() * vc->GetArea();
-
-	return vc->GetPvs().GetSize() * vc->GetVolume();
+	{
+		return vc->GetPvs().CountPvs() * vc->GetArea();
+	}
+
+	return vc->GetPvs().CountPvs() * vc->GetVolume();
 }
 
@@ -1328,5 +1339,5 @@
 		newPvs = (int)ComputeMergedPvsCost(mc.mLeftViewCell->GetPvs(), mc.mRightViewCell->GetPvs());
 
-	const float newPenalty = EvalPvsPenalty(newPvs,
+	const float newPenalty = EvalPvsPenalty(newPvs, 
 											mViewCellsManager->GetMinPvsSize(),
 											mViewCellsManager->GetMaxPvsSize());
@@ -1477,5 +1488,5 @@
 			for (it = interior->mChildren.begin(); it != it_end; ++ it)
 			{
-				int pvsSize = GetPvsSize(*it);
+				const int pvsSize = GetPvsSize(*it);
 				childCost += (float) pvsSize * (*it)->GetVolume();
 				childPvs += pvsSize;
@@ -1603,5 +1614,4 @@
 
 
-
 	// delete all the objects from the leaf sets which were moved to parent pvs
 	ObjectPvsMap::const_iterator oit_end = interior->GetPvs().mEntries.end();
@@ -1615,12 +1625,4 @@
 		}
 	}
-
-	/*int dummy = interior->GetPvs().GetSize();
-
-	for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
-	{
-		dummy += (*cit)->GetPvs().GetSize();
-	}*/
-
 }
 
@@ -1729,5 +1731,5 @@
 			{
 				if (countKdPvs)
-					pvsSize = vc->GetPvs().GetSize();
+					pvsSize = vc->GetPvs().CountPvs();
 				else
 					pvsSize = CountKdPvs(dynamic_cast<ViewCellLeaf *>(vc));
@@ -1817,6 +1819,6 @@
 	case PVS_IN_INTERIORS:
 	default:
-		Debug << "in interiors: " << vc->mPvsSize << " $$ " << vc->GetPvs().GetSize() << endl;
-		pvsSize = vc->GetPvs().GetSize();		
+		Debug << "in interiors: " << vc->mPvsSize << " $$ " << vc->GetPvs().CountPvs() << endl;
+		pvsSize = vc->GetPvs().CountPvs();		
 	}
 
@@ -1840,5 +1842,5 @@
 	if ((mViewCellsStorage == PVS_IN_INTERIORS) || vc->IsLeaf())
 	{
-		pvsSize = vc->GetPvs().GetSize();
+		pvsSize = vc->GetPvs().CountPvs();
 	}
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h	(revision 1112)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h	(revision 1141)
@@ -58,6 +58,6 @@
 
   /** Normalize the visibility of entries in order to get comparable
-	  results */
-  
+	  results 
+  */
   void NormalizeMaximum();
   
@@ -413,7 +413,18 @@
 class KdPvs: public Pvs<KdNode *>
 {
+public:
 	int Compress();
 };
 
+
+class ObjectPvs: public Pvs<Intersectable *>
+{
+public:
+	/** Counts pvs. Different to GetSize(), not
+		only the raw container size is returned,
+		but the individual contributions of the entries are summed up.
+	*/
+	int CountPvs() const;
+};
 
 //-- typedefs
@@ -426,5 +437,5 @@
 typedef PvsData<KdNode *> KdPvsData;
 
-typedef Pvs<Intersectable *> ObjectPvs;
+//typedef Pvs<Intersectable *> ObjectPvs;
 typedef Pvs<ViewCell *> ViewCellPvs;
 }
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.h	(revision 1139)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.h	(revision 1141)
@@ -33,4 +33,6 @@
 class KdLeaf;
 class OspTree;
+class KdIntersectable;
+
 
 
@@ -461,4 +463,6 @@
 #endif
 
+typedef map<KdNode *, KdIntersectable *> KdIntersectableMap;
+
 typedef FlexibleHeap<SplitCandidate *> SplitQueue;
 
@@ -980,8 +984,10 @@
 		
 	*/
-	void AddToPvs(VspLeaf *leaf,
+	void AddSamplesToPvs(VspLeaf *leaf,
 				  const RayInfoContainer &rays, 
 				  float &sampleContributions,
 				  int &contributingSamples);
+
+	bool AddKdLeafToPvs(KdLeaf *leaf, ViewCell *vc, float &pvs, float &contribution);
 
 	/** Propagates valid flag up the tree.
@@ -1018,7 +1024,6 @@
 protected:
 
-	bool mUseKdPvs;
-
-	enum {PER_OBJECT, PER_KDLEAF};
+	bool mUseKdPvsForHeuristics;
+	bool mStoreKdPvs;
 
 	ViewCellsManager *mViewCellsManager;
@@ -1036,5 +1041,4 @@
 	/// box around the whole view domain
 	AxisAlignedBox3 mBoundingBox;
-
 
 
@@ -1339,4 +1343,9 @@
 #endif
 
+	/** Returns or creates a new intersectable for use in a kd based pvs.
+		The OspTree is responsible for destruction of the intersectable.
+	*/
+	KdIntersectable *GetOrCreateKdIntersectable(KdNode *node);
+
 	/** Collects rays stored in the leaves.
 	*/
@@ -1549,14 +1558,5 @@
 		float &pFront,
 		float &pBack);
-	/** Adds ray sample contributions to the PVS.
-		@param sampleContributions the number contributions of the samples
-		@param contributingSampels the number of contributing rays
-		
-	*/
-	void AddToPvs(VspLeaf *leaf,
-				  const RayInfoContainer &rays, 
-				  float &sampleContributions,
-				  int &contributingSamples);
-
+	
 	/** Propagates valid flag up the tree.
 	*/
@@ -1667,5 +1667,4 @@
 
 
-
 	//-- split heuristics based parameters
 	
@@ -1698,4 +1697,7 @@
 	/// weight between  render cost decrease and node render cost
 	float mRenderCostDecreaseWeight;
+
+	/// stores the kd node intersectables used for pvs
+	KdIntersectableMap mKdIntersectables;
 };
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.h	(revision 1139)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.h	(revision 1141)
@@ -206,5 +206,5 @@
 		return a->mPvsSize < b->mPvsSize;
 #else
-		return a->GetPvs().GetSize() < b->GetPvs().GetSize();
+		return a->GetPvs().CountPvs() < b->GetPvs().CountPvs();
 #endif
 	}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ResourceManager.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ResourceManager.h	(revision 1004)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ResourceManager.h	(revision 1141)
@@ -49,5 +49,5 @@
 	T *CreateResource()
 	{
-		const int id = CreateUniqueId();
+		const unsigned int id = CreateUniqueId();
 
 		T *resource = new T(id);
@@ -61,7 +61,7 @@
 		@returns mesh or NULL if mesh was not found.
 	*/
-	T *FindEntry(const int id) const
+	T *FindEntry(const unsigned int id) const
 	{
-		std::map<int, T *>::const_iterator mit = mEntries.find(id);
+		std::map<unsigned int, T *>::const_iterator mit = mEntries.find(id);
 
 		if (mit != mEntries.end()) 
@@ -76,5 +76,5 @@
 		@returns true if the mesh was found, false if not
 	*/
-	bool DestroyEntry(const int id)
+	bool DestroyEntry(const unsigned int id)
 	{	
 		if (!FindEntry(id))
@@ -112,5 +112,5 @@
 	~ResourceManager<T>()
 	{
-		std::map<int, T *>::iterator mit, mit_end = mEntries.end();
+		std::map<unsigned int, T *>::iterator mit, mit_end = mEntries.end();
 
 		for (mit = mEntries.begin(); mit != mEntries.end(); ++ mit)
@@ -129,5 +129,5 @@
 	 /** Helper function returning unique id for resource.
 	 */
-	static int CreateUniqueId()
+	static unsigned int CreateUniqueId()
 	{
 		return sCurrentId ++;
@@ -137,15 +137,15 @@
 
 	/// the resource container
-	std::map<int, T *> mEntries;
+	std::map<unsigned int, T *> mEntries;
 
 private:
 
 	static ResourceManager<T> *sResourceManager;
-	static int sCurrentId;
+	static unsigned int sCurrentId;
 };
 
 // only instance of the resource manager
 template <typename T> ResourceManager<T> *ResourceManager<T>::sResourceManager = NULL;
-template <typename T> int ResourceManager<T>::sCurrentId = 0;
+template <typename T> unsigned int ResourceManager<T>::sCurrentId = 0;
 
 /// This type is responsible for creation and disposal the meshes
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.cpp	(revision 863)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.cpp	(revision 1141)
@@ -1,12 +1,87 @@
 #include <iostream>
+#include <stack>
 #include "Pvs.h"
+#include "Intersectable.h"
+#include "KdIntersectable.h"
+#include "KdTree.h"
+#include "common.h"
+
 
 namespace GtpVisibilityPreprocessor {
 
-int
-KdPvs::Compress()
+
+int KdPvs::Compress()
 {
 	return 0; // TODO
 }
 
+
+int ObjectPvs::CountPvs() const
+{
+	int pvs = 0;
+
+	Intersectable::NewMail();
+	KdNode::NewMail();
+
+	ObjectPvsMap::const_iterator it, it_end = mEntries.end();
+
+	for (it = mEntries.begin(); it != it_end; ++ it)
+	{
+		Intersectable *obj = (*it).first;
+
+		if (obj->Type() == Intersectable::KD_INTERSECTABLE)
+		{
+			KdIntersectable *kdObj = dynamic_cast<KdIntersectable *>(obj);
+
+			stack<KdNode *> tStack;
+
+			tStack.push(kdObj->GetNode());
+
+			while (!tStack.empty())
+			{
+				KdNode *node = tStack.top();
+				tStack.pop();
+
+				// already processed node (objects in pvs)
+				if (node->Mailed())
+					continue;
+
+				node->Mail();
+
+				if (node->IsLeaf())
+				{
+					
+					KdLeaf *leaf = dynamic_cast<KdLeaf *>(node);
+
+					pvs += (int)(leaf->mObjects.size() - leaf->mMultipleObjects.size());
+
+					ObjectContainer::const_iterator it, it_end = leaf->mMultipleObjects.end();
+					{
+						Intersectable *object = *it;						
+						
+						if (!object->Mailed())
+						{
+							object->Mail();
+							++ pvs;
+						}
+					}
+				}
+				else
+				{
+					KdInterior *interior = dynamic_cast<KdInterior *>(node);
+
+					tStack.push(interior->mFront);
+					tStack.push(interior->mBack);
+				}
+			}
+		}
+		else
+		{
+			++ pvs;
+		}
+	}
+
+	return pvs;
 }
+
+}
