Index: /GTP/trunk/Lib/Vis/Preprocessing/src/TestPreprocessor.vcproj
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/TestPreprocessor.vcproj	(revision 2187)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/TestPreprocessor.vcproj	(revision 2198)
@@ -281,5 +281,5 @@
 				LinkIncremental="1"
 				AdditionalLibraryDirectories="..\src\GL;..\lib\release;..\..\Preprocessing\lib\release;..\..\..\..\..\..\NonGTP\Boost\lib;..\..\..\..\..\..\NonGTP\Xerces\xercesc\lib;..\..\..\..\..\..\NonGTP\Zlib\lib;..\..\..\..\..\..\NonGTP\Devil\lib;..\MultiLevelRayTracing\RTScene\Release;..\MultiLevelRayTracing\RTWorld\Release"
-				GenerateDebugInformation="FALSE"
+				GenerateDebugInformation="TRUE"
 				SubSystem="1"
 				LargeAddressAware="0"
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.cpp	(revision 2176)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.cpp	(revision 2198)
@@ -11,4 +11,7 @@
 mBvhLeaf(0), 
 mVssRays(NULL) 
+#if STORE_VIEWCELLS_WITH_BVH
+, mViewCells(NULL)
+#endif
 {}
 
@@ -62,4 +65,22 @@
 }
 
+#if STORE_VIEWCELLS_WITH_BVH
+
+ViewCellContainer *Intersectable::GetOrCreateViewCells() 
+{ 
+	if (!mViewCells)
+		mViewCells = new ViewCellContainer();
+
+	return mViewCells;
+}
+
+
+void Intersectable::DelViewCells()
+{
+	DEL_PTR(mViewCells);
+}
+
+#endif
+
 
 void Intersectable::DelRayRefs()
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 2187)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 2198)
@@ -1189,25 +1189,9 @@
 	const long t1 = GetTime();
 	
-	if (1 && (rays.size() > 10000))
+	if (rays.size() > 10000)
 	{
 	
 		mRayCaster->SortRays(rays);
 		cout<<"Rays sorted in "<<TimeDiff(t1, GetTime())<<" ms."<<endl;
-
-		if (0) {
-			VssRayContainer tmpRays;
-			int m = 890000;
-
-			for (int i=m; i < m+20; i++) {
-				tmpRays.push_back(new VssRay(rays[i].mOrigin,
-					rays[i].mOrigin + 100.0f*rays[i].mDirection,
-					NULL,
-					NULL
-					)
-					);
-
-			}
-			ExportRays("sorted_rays.x3d", tmpRays, 200);
-		}
 	}
 
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/VssPreprocessor.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/VssPreprocessor.cpp	(revision 2187)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/VssPreprocessor.cpp	(revision 2198)
@@ -624,7 +624,7 @@
 {
 	// store higher order object
-	mViewCellsManager->DeterminePvsObjects(rays, false);
-}
-
-
-}
+	mViewCellsManager->DeterminePvsObjects(rays, !mViewCellsManager->ViewCellsConstructed());
+}
+
+
+}
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.h	(revision 2187)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.h	(revision 2198)
@@ -728,4 +728,6 @@
 	PerfTimer mSubdivTimer;
 	PerfTimer mEvalTimer;
+	PerfTimer mPlaneTimer;
+	PerfTimer mViewCellsTimer;
 
 protected:
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp	(revision 2187)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp	(revision 2198)
@@ -366,4 +366,6 @@
 	ObjectContainer::const_iterator oit, oit_end = objects.end();
 
+	// warning: not exact number (there can be rays counted twice)
+	// otherwise we would have to traverse trough all rays
 	for (oit = objects.begin(); oit != oit_end; ++ oit)
 	{
@@ -373,4 +375,5 @@
 	return nRays;
 }
+
 									
 float BvHierarchy::GetViewSpaceVolume() const
@@ -384,5 +387,11 @@
 										BvhTraversalData &backData)
 { 
+	// fill view cells cache
 	mNodeTimer.Entry();
+
+#if STORE_VIEWCELLS_WITH_BVH
+	AssociateViewCellsWithObjects(sc.mFrontObjects);
+	AssociateViewCellsWithObjects(sc.mBackObjects);
+#endif	
 	const BvhTraversalData &tData = sc.mParentData;
 	BvhLeaf *leaf = tData.mNode;
@@ -400,5 +409,5 @@
 	// add the new nodes to the tree
 	BvhInterior *node = new BvhInterior(parentBox, leaf->GetParent());
-	
+
 
 	//////////////////
@@ -480,5 +489,10 @@
 		AssignSortedObjects(sc, frontData, backData);
 	}
-	
+
+#if STORE_VIEWCELLS_WITH_BVH
+	ReleaseViewCells(sc.mFrontObjects);
+	ReleaseViewCells(sc.mBackObjects);
+#endif
+
 	mNodeTimer.Exit();
 
@@ -615,5 +629,11 @@
 										   bool computeSplitPlane)
 {
-	mEvalTimer.Entry();
+	mPlaneTimer.Entry();
+
+#if STORE_VIEWCELLS_WITH_BVH
+	// fill view cells cache
+	AssociateViewCellsWithObjects(*splitCandidate.mParentData.mSortedObjects[3]);
+#endif
+
 	if (computeSplitPlane)
 	{
@@ -640,5 +660,7 @@
 										previousMisses + 1 : previousMisses);
 	}
-
+	mPlaneTimer.Exit();
+
+	mEvalTimer.Entry();
 
 	const BvhTraversalData &tData = splitCandidate.mParentData;
@@ -705,4 +727,9 @@
   	// compute global decrease in render cost
 	splitCandidate.SetPriority(priority);
+
+#if STORE_VIEWCELLS_WITH_BVH
+	ReleaseViewCells(*splitCandidate.mParentData.mSortedObjects[3]);
+#endif
+
 	mEvalTimer.Exit();
 }
@@ -710,5 +737,5 @@
 
 int BvHierarchy::EvalPvsEntriesIncr(BvhSubdivisionCandidate &splitCandidate, 
-									const float avgRayContri) const
+									const float avgRayContri) //const
 {
 	const float oldPvsSize = (float)CountViewCells(splitCandidate.mParentData.mNode->mObjects);
@@ -991,6 +1018,5 @@
 
 	SortableEntryContainer::reverse_iterator rcit = 
-		mSubdivisionCandidates->rbegin(), rcit_end = 
-		mSubdivisionCandidates->rend();
+		mSubdivisionCandidates->rbegin(), rcit_end = mSubdivisionCandidates->rend();
 
 	vector<float>::reverse_iterator rbit = bordersRight.rbegin();
@@ -1406,5 +1432,5 @@
 void BvHierarchy::PrepareLocalSubdivisionCandidates(const BvhTraversalData &tData,
 													const int axis)											
-{
+{mSort2Timer.Entry();
 	//-- insert object queries
 	ObjectContainer *objects = mUseGlobalSorting ? 
@@ -1412,4 +1438,5 @@
 
 	CreateLocalSubdivisionCandidates(*objects, &mSubdivisionCandidates, !mUseGlobalSorting, axis);
+		mSort2Timer.Exit();
 }
 
@@ -1472,5 +1499,12 @@
 	ViewCellContainer viewCells;
 
-	const int numRays = CollectViewCells(tData.mNode->mObjects, viewCells, true, true);
+	const bool setCounter = true;
+	const bool onlyUnmailed = true;
+
+	const int numRays = CollectViewCells(tData.mNode->mObjects, 
+										 viewCells, 
+										 setCounter, 
+										 onlyUnmailed);
+
 	//cout << "number of rays: " << numRays << endl;
 
@@ -1781,5 +1815,5 @@
 
 
-float BvHierarchy::EvalRenderCost(const ObjectContainer &objects) const
+float BvHierarchy::EvalRenderCost(const ObjectContainer &objects)// const
 {	
 	///////////////
@@ -1793,16 +1827,4 @@
 	
 	return objRenderCost * p;
-}
-
-
-float BvHierarchy::EvalProb(const ObjectContainer &objects) const
-{	
-	///////////////
-	//-- render cost heuristics
-
-	const float viewSpaceVol = mViewCellsManager->GetViewSpaceBox().GetVolume();
-
-	// probability that view point lies in a view cell which sees this node
-	return EvalViewCellsVolume(objects) / viewSpaceVol;
 }
 
@@ -1890,8 +1912,12 @@
 								  ViewCellContainer &viewCells,
 								  const bool setCounter,
-								  const bool onlyUnmailedRays) const
+								  const bool onlyUnmailedRays)// const
 {
 	ViewCell::NewMail();
+
 	ObjectContainer::const_iterator oit, oit_end = objects.end();
+
+	// use mailing to avoid dublicates
+	const bool useMailBoxing = true;
 
 	int numRays = 0;
@@ -1899,9 +1925,94 @@
 	for (oit = objects.begin(); oit != oit_end; ++ oit)
 	{
-		// always use only mailed objects
-		numRays += CollectViewCells(*oit, viewCells, true, setCounter, onlyUnmailedRays);
+		// use mailing to avoid duplicates
+		numRays += CollectViewCells(*oit, viewCells, useMailBoxing, setCounter, onlyUnmailedRays);
 	}
 
 	return numRays;
+}
+
+
+#if STORE_VIEWCELLS_WITH_BVH
+
+
+void BvHierarchy::ReleaseViewCells(const ObjectContainer &objects)
+{
+	ObjectContainer::const_iterator oit, oit_end = objects.end();
+
+	for (oit = objects.begin(); oit != oit_end; ++ oit)
+	{
+		(*oit)->DelViewCells();
+	}
+}
+
+
+void BvHierarchy::AssociateViewCellsWithObjects(const ObjectContainer &objects) const
+{
+	ObjectContainer::const_iterator oit, oit_end = objects.end();
+
+	const bool useMailBoxing = true;
+	for (oit = objects.begin(); oit != oit_end; ++ oit)
+	{
+		ViewCell::NewMail();
+		// use mailing to avoid duplicates
+		AssociateViewCellsWithObject(*oit, useMailBoxing);
+	}
+}
+
+
+int BvHierarchy::AssociateViewCellsWithObject(Intersectable *obj, const bool useMailBoxing) const
+{
+	if (!obj->GetOrCreateViewCells()->empty())
+	{
+		cerr << "AssociateViewCellsWithObject: view cells cache not working" << endl;
+	}
+
+	ViewCellContainer *objViewCells = obj->GetOrCreateViewCells();
+	VssRayContainer *vssRays = obj->GetOrCreateRays();
+
+	VssRayContainer::const_iterator rit, rit_end = vssRays->end();
+
+	// fill cache
+	for (rit = vssRays->begin(); rit < rit_end; ++ rit)
+	{
+		VssRay *ray = (*rit);
+
+		//	if (onlyUnmailedRays && ray->Mailed())
+		//		continue;
+		mHierarchyManager->mVspTree->GetViewCells(*ray, *objViewCells);
+	}
+
+	return (int)vssRays->size();
+}
+
+
+
+int BvHierarchy::CountViewCells(Intersectable *obj) //const
+{
+	ViewCellContainer *viewCells = obj->GetOrCreateViewCells();
+
+	if (obj->GetOrCreateViewCells()->empty())
+	{
+		//cerr << "h";//CountViewCells: view cells empty, view cells cache not working" << endl;
+		return CountViewCellsFromRays(obj);
+	}
+	
+	int result = 0;
+
+	ViewCellContainer::const_iterator vit, vit_end = viewCells->end();
+	
+	for (vit = viewCells->begin(); vit != vit_end; ++ vit)
+	{
+		ViewCell *vc = *vit;
+
+		// store view cells
+		if (!vc->Mailed())
+		{
+			vc->Mail();
+			++ result;
+		}
+	}
+
+	return result;
 }
 
@@ -1911,6 +2022,63 @@
 								  const bool useMailBoxing,
 								  const bool setCounter,
-								  const bool onlyUnmailedRays) const
-{
+								  const bool onlyUnmailedRays)// const
+{
+	if (obj->GetOrCreateViewCells()->empty())
+	{
+		//cerr << "g";//CollectViewCells: view cells empty, view cells cache not working" << endl;
+		return CollectViewCellsFromRays(obj, viewCells, useMailBoxing, setCounter, onlyUnmailedRays);
+	}
+
+	mCollectTimer.Entry();
+
+	ViewCellContainer *objViewCells = obj->GetOrCreateViewCells();
+
+	///////////
+	//-- use view cells cache
+
+	// fastest way: just copy to the end
+	//if (!useMailBoxing)	viewCells.insert(viewCells.end(), objViewCells->begin(), objViewCells->end());
+
+	// loop through view cells
+	// matt: probably slow to insert  view cells one by one
+	ViewCellContainer::const_iterator vit, vit_end = objViewCells->end();
+
+	for (vit = objViewCells->begin(); vit != vit_end; ++ vit)
+	{
+		ViewCell *vc = *vit;
+
+		// store view cells
+		if (!useMailBoxing || !vc->Mailed())
+		{
+			if (useMailBoxing) 
+			{
+				// view cell not mailed
+				vc->Mail();
+				
+				if (setCounter)
+					vc->mCounter = 0;
+				//viewCells.push_back(vc);
+			}
+
+			viewCells.push_back(vc);
+		}
+
+		if (setCounter)
+			++ vc->mCounter;
+	}
+
+	mCollectTimer.Exit();
+
+	return (int)objViewCells->size();
+}
+
+
+int BvHierarchy::CollectViewCellsFromRays(Intersectable *obj, 
+										  ViewCellContainer &viewCells,
+										  const bool useMailBoxing,
+										  const bool setCounter,
+										  const bool onlyUnmailedRays)
+{
+	mCollectTimer.Entry();
 	VssRayContainer::const_iterator rit, rit_end = obj->GetOrCreateRays()->end();
 
@@ -1922,8 +2090,6 @@
 
 		if (onlyUnmailedRays && ray->Mailed())
-		{
 			continue;
-		}
-
+		
 		++ numRays;
 
@@ -1945,7 +2111,5 @@
 					vc->Mail();
 					if (setCounter)
-					{
 						vc->mCounter = 0;
-					}
 				}
 
@@ -1954,15 +2118,14 @@
 			
 			if (setCounter)
-			{
 				++ vc->mCounter;
-			}
-		}
-	}
-
+		}
+	}
+
+	mCollectTimer.Exit();
 	return numRays;
 }
 
 
-int BvHierarchy::CountViewCells(Intersectable *obj) const
+int BvHierarchy::CountViewCellsFromRays(Intersectable *obj) //const
 {
 	int result = 0;
@@ -1994,9 +2157,96 @@
 }
 
-
-int BvHierarchy::CountViewCells(const ObjectContainer &objects) const
+#else
+
+int BvHierarchy::CountViewCells(Intersectable *obj) //const
+{
+	int result = 0;
+	
+	VssRayContainer::const_iterator rit, rit_end = obj->GetOrCreateRays()->end();
+
+	for (rit = obj->GetOrCreateRays()->begin(); rit < rit_end; ++ rit)
+	{
+		VssRay *ray = (*rit);
+		ViewCellContainer tmpViewCells;
+	
+		mHierarchyManager->mVspTree->GetViewCells(*ray, tmpViewCells);
+		
+		ViewCellContainer::const_iterator vit, vit_end = tmpViewCells.end();
+		for (vit = tmpViewCells.begin(); vit != vit_end; ++ vit)
+		{
+			ViewCell *vc = *vit;
+
+			// store view cells
+			if (!vc->Mailed())
+			{
+				vc->Mail();
+				++ result;
+			}
+		}
+	}
+
+	return result;
+}
+
+
+int BvHierarchy::CollectViewCells(Intersectable *obj, 
+								  ViewCellContainer &viewCells,
+								  const bool useMailBoxing,
+								  const bool setCounter,
+								  const bool onlyUnmailedRays)
+{
+	mCollectTimer.Entry();
+	VssRayContainer::const_iterator rit, rit_end = obj->GetOrCreateRays()->end();
+
+	int numRays = 0;
+
+	for (rit = obj->GetOrCreateRays()->begin(); rit < rit_end; ++ rit)
+	{
+		VssRay *ray = (*rit);
+
+		if (onlyUnmailedRays && ray->Mailed())
+			continue;
+		
+		++ numRays;
+
+		ViewCellContainer tmpViewCells;
+		mHierarchyManager->mVspTree->GetViewCells(*ray, tmpViewCells);
+
+		// matt: probably slow to allocate memory for view cells every time
+		ViewCellContainer::const_iterator vit, vit_end = tmpViewCells.end();
+
+		for (vit = tmpViewCells.begin(); vit != vit_end; ++ vit)
+		{
+			ViewCell *vc = *vit;
+
+			// store view cells
+			if (!useMailBoxing || !vc->Mailed())
+			{
+				if (useMailBoxing) // => view cell not mailed
+				{
+					vc->Mail();
+					if (setCounter)
+						vc->mCounter = 0;
+				}
+
+				viewCells.push_back(vc);
+			}
+			
+			if (setCounter)
+				++ vc->mCounter;
+		}
+	}
+
+	mCollectTimer.Exit();
+	return numRays;
+}
+#endif
+
+
+int BvHierarchy::CountViewCells(const ObjectContainer &objects)// const
 {
 	int nViewCells = 0;
-	ViewCell::NewMail();
+
+	//ViewCell::NewMail();
 	ObjectContainer::const_iterator oit, oit_end = objects.end();
 
@@ -2179,5 +2429,5 @@
 
 
-float BvHierarchy::EvalViewCellsVolume(const ObjectContainer &objects) const
+float BvHierarchy::EvalViewCellsVolume(const ObjectContainer &objects)// const
 {
 	float vol = 0;
@@ -2257,4 +2507,8 @@
 	//cout << "using " << nRays << " of " << (int)sampleRays.size() << " rays" << endl;
 	
+#if STORE_VIEWCELLS_WITH_BVH
+	AssociateViewCellsWithObjects(objects);
+#endif
+
 	// probability that volume is "seen" from the view cells
 	const float prop = EvalViewCellsVolume(objects) / GetViewSpaceVolume();
@@ -2283,4 +2537,8 @@
 	bvhLeaf->SetSubdivisionCandidate(oSubdivisionCandidate);
 
+#if STORE_VIEWCELLS_WITH_BVH
+	ReleaseViewCells(objects);
+#endif
+
 	if (mApplyInitialPartition)
 	{
@@ -2325,6 +2583,4 @@
 												const ObjectContainer &objects)
 {
-	mSortTimer.Entry();
-
 	const bool doSort = true;
 
@@ -2362,6 +2618,4 @@
 	stable_sort(tData.mSortedObjects[3]->begin(), tData.mSortedObjects[3]->end(), smallerSize);
 	//sort(tData.mSortedObjects[3]->begin(), tData.mSortedObjects[3]->end(), smallerSize);
-
-	mSortTimer.Exit();
 }
 
@@ -2412,4 +2666,5 @@
 						const ObjectContainer &objects)
 {
+
 	// reset stats
 	mBvhStats.Reset();
@@ -2424,4 +2679,8 @@
 	mRoot = bvhleaf;
 	
+#if STORE_VIEWCELLS_WITH_BVH
+	AssociateViewCellsWithObjects(objects);
+#endif
+
 	//mTermMinProbability *= mVspTree->GetBoundingBox().GetVolume();
 	// probability that volume is "seen" from the view cells
@@ -2438,5 +2697,7 @@
 		AssignInitialSortedObjectList(oData, objects);
 	
-
+#if STORE_VIEWCELLS_WITH_BVH
+	ReleaseViewCells(objects);
+#endif
 	///////////////////
 	//-- add first candidate for object space partition	
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 2187)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 2198)
@@ -2791,5 +2791,5 @@
 	
 	// check if last ray was not same ray with reverse direction
-	if (lastVssRay == NULL ||
+	if (!lastVssRay ||
 		!(ray.mOrigin == lastVssRay->mTermination) ||
 		!(ray.mTermination == lastVssRay->mOrigin)) 
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 2187)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 2198)
@@ -35,5 +35,4 @@
 class BvhTree;
 class VspTree;
-class ViewCellsContainer;
 class HierarchyManager;
 
@@ -649,6 +648,4 @@
 	static float EvalAbsCost(const ObjectContainer &objects);
 
-	float EvalProb(const ObjectContainer &objects) const;
-
 	void CollectObjects(const AxisAlignedBox3 &box, ObjectContainer &objects);
 
@@ -658,9 +655,11 @@
 	void CreateUniqueObjectIds();
 
-	PerfTimer mSortTimer;
 	PerfTimer mNodeTimer;
 	PerfTimer mSubdivTimer;
 	PerfTimer mEvalTimer;
 	PerfTimer mSplitTimer;
+	PerfTimer mPlaneTimer;
+	PerfTimer mSort2Timer;
+	PerfTimer mCollectTimer;
 
 protected:
@@ -710,5 +709,5 @@
 	/** Evaluates render cost of the bv induced by these objects
 	*/
-	float EvalRenderCost(const ObjectContainer &objects) const;
+	float EvalRenderCost(const ObjectContainer &objects);// const;
 
 	/** Evaluates tree stats in the BSP tree leafs.
@@ -759,5 +758,5 @@
 	static void AssociateObjectsWithLeaf(BvhLeaf *leaf);
 
-
+	
 	/////////////////////////////
 	// Helper functions for local cost heuristics
@@ -834,5 +833,5 @@
 						 ViewCellContainer &viewCells,
 						 const bool setCounter,
-						 const bool onlyUnmailedRays) const;
+						 const bool onlyUnmailedRays);// const;
 
 	/** Collects view cells which see an object.
@@ -846,18 +845,36 @@
 						 const bool useMailBoxing,
 						 const bool setCounter,
-						 const bool onlyUnmailedRays) const;
+						 const bool onlyUnmailedRays);// const;
 
 	/** Counts the view cells of this object. note: only
 		counts unmailed objects.
 	*/
-	int CountViewCells(Intersectable *obj) const;
+	int CountViewCells(Intersectable *obj);// const;
 
 	/** Counts the view cells seen by this bvh leaf
 	*/
-	int CountViewCells(const ObjectContainer &objects) const;
+	int CountViewCells(const ObjectContainer &objects);// const;
+
+#if STORE_VIEWCELLS_WITH_BVH
+
+	int AssociateViewCellsWithObject(Intersectable *obj, const bool useMailBoxing) const;
+
+	void AssociateViewCellsWithObjects(const ObjectContainer &objects) const;
+
+	void ReleaseViewCells(const ObjectContainer &objects);
+
+	int CollectViewCellsFromRays(Intersectable *obj, 
+								 ViewCellContainer &viewCells,
+								 const bool useMailBoxing,
+								 const bool setCounter,
+								 const bool onlyUnmailedRays);
+
+	int CountViewCellsFromRays(Intersectable *obj);
+#endif
 
 	/** Evaluates increase in pvs size.
 	*/
-	int EvalPvsEntriesIncr(BvhSubdivisionCandidate &splitCandidate, const float avgRayContri) const;
+	int EvalPvsEntriesIncr(BvhSubdivisionCandidate &splitCandidate, 
+						   const float avgRayContri);// const;
 
 	/** Rays will be clipped to the bounding box.
@@ -901,5 +918,5 @@
 	/** Evaluates volume of view cells that see the objects.
 	*/
-	float EvalViewCellsVolume(const ObjectContainer &objects) const;
+	float EvalViewCellsVolume(const ObjectContainer &objects);// const;
 
 	/** Assigns or newly creates initial list of sorted objects.
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.cpp	(revision 2187)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.cpp	(revision 2198)
@@ -775,5 +775,5 @@
 									   bool computeSplitPlane)
 {
-	mEvalTimer.Entry();
+	mPlaneTimer.Entry();
 
 	if (computeSplitPlane)
@@ -796,4 +796,8 @@
 	}
 	
+	mPlaneTimer.Exit();
+
+	mEvalTimer.Entry();
+
 	VspLeaf *leaf = static_cast<VspLeaf *>(splitCandidate.mParentData.mNode);
 
@@ -1112,6 +1116,8 @@
 	}
 
-	stable_sort(mLocalSubdivisionCandidates->begin(), mLocalSubdivisionCandidates->end());
-	//sort(mLocalSubdivisionCandidates->begin(), mLocalSubdivisionCandidates->end());
+	if (1)
+		stable_sort(mLocalSubdivisionCandidates->begin(), mLocalSubdivisionCandidates->end());
+	else
+		sort(mLocalSubdivisionCandidates->begin(), mLocalSubdivisionCandidates->end());
 
 	mSortTimer.Exit();
@@ -2552,5 +2558,5 @@
 ViewCell *VspTree::GetViewCell(const Vector3 &point, const bool active)
 {
-	if (mRoot == NULL)
+	if (!mRoot)
 		return NULL;
 
@@ -2590,4 +2596,5 @@
 	}
   
+	// return active or leaf view cell
 	if (active)
 	{
@@ -2785,24 +2792,25 @@
 		const AxisAlignedBox3 bbox = GetBoundingBox(node);
 
-		if (Overlap(bbox, box)) {
-		  if (node->IsLeaf())
-			{
-			  VspLeaf *leaf = static_cast<VspLeaf *>(node);
-			  
-			  if (!leaf->GetViewCell()->Mailed() && leaf->TreeValid())
+		if (Overlap(bbox, box)) 
+		{
+			if (node->IsLeaf())
+			{
+				VspLeaf *leaf = static_cast<VspLeaf *>(node);
+
+				if (!leaf->GetViewCell()->Mailed() && leaf->TreeValid())
 				{
-				  leaf->GetViewCell()->Mail();
-				  viewCells.push_back(leaf->GetViewCell());
+					leaf->GetViewCell()->Mail();
+					viewCells.push_back(leaf->GetViewCell());
 				}
 			}
-		  else 
-			{
-			  VspInterior *interior = static_cast<VspInterior *>(node);
-			  
-			  VspNode *first = interior->GetFront();
-			  VspNode *second = interior->GetBack();
-			  
-			  nodeStack.push(first);
-			  nodeStack.push(second);
+			else 
+			{
+				VspInterior *interior = static_cast<VspInterior *>(node);
+
+				VspNode *first = interior->GetFront();
+				VspNode *second = interior->GetBack();
+
+				nodeStack.push(first);
+				nodeStack.push(second);
 			}
 		}
@@ -2852,4 +2860,6 @@
 void VspTree::GetViewCells(const VssRay &ray, ViewCellContainer &viewCells)
 {
+	mViewCellsTimer.Entry();
+	
 	static Ray hray;
 	hray.Init(ray);
@@ -2863,7 +2873,9 @@
 	const Vector3 termination = hray.Extrap(tmax);
 
-	// view cells were not precomputed
-	// don't mail because we need mailboxing for something else
+	// view cells were not precomputed and are extracted on the fly
+	// don't mail because the same view cells can be found for different rays
 	CastLineSegment(origin, termination, viewCells, false);
+
+	mViewCellsTimer.Exit();
 }
 
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/RayCaster.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/RayCaster.cpp	(revision 2187)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/RayCaster.cpp	(revision 2198)
@@ -250,5 +250,5 @@
 	
 	// old method: always allocate
-	if (1) return new VssRay(origin, termination, originObject, terminationObject, pass, pdf);
+	if (0) return new VssRay(origin, termination, originObject, terminationObject, pass, pdf);
 
 	VssRay *vssRay = mVssRayPool.Alloc();
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Statistics.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Statistics.h	(revision 2003)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Statistics.h	(revision 2198)
@@ -17,5 +17,5 @@
   static inline double TimeDiff(long time1, long time2) // in s
   {
-    const double clk = 1.0E-6; // ticks per second
+    const double clk = 1.0E-3; // ticks per second
     long t = time2 - time1;
 		
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.h	(revision 2176)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.h	(revision 2198)
@@ -2,8 +2,9 @@
 #define __INTERSECTABLE_H
 
+
 #include "AxisAlignedBox3.h"
-#include <set>
-//#include "VssRay.h"
 #include "Mailable.h"
+
+#define STORE_VIEWCELLS_WITH_BVH 0
 
 namespace GtpVisibilityPreprocessor {
@@ -137,8 +138,8 @@
    static bool GreaterCounter(const Intersectable *a,
 							  const Intersectable *b);
-
-  /** Returns the name of the type of this intersectable
-  */
-  static std::string GetTypeName(Intersectable *obj);
+   
+   /** Returns the name of the type of this intersectable
+   */
+   static std::string GetTypeName(Intersectable *obj);
 
    /** Returns normal from the face with the specified index.
@@ -155,8 +156,20 @@
    void DelRayRefs();
 
+
 protected:
-
 	/// some rays piercing this intersectable
 	VssRayContainer *mVssRays;
+
+#if STORE_VIEWCELLS_WITH_BVH
+public:
+   /** Returns rays stored with this intersectable.
+   */
+   ViewCellContainer *GetOrCreateViewCells();
+
+   void DelViewCells();
+
+protected:
+   ViewCellContainer *mViewCells;
+#endif
 };
 
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp	(revision 2187)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp	(revision 2198)
@@ -282,5 +282,7 @@
 	// split was not reevaluated before => do it now
 	if (splitCandidate->IsDirty())
+	{
 		splitCandidate->EvalCandidate();
+	}
 
 	return splitCandidate;
@@ -411,11 +413,13 @@
 void HierarchyManager::PrintTimings(const bool lastSplitWasOsp)
 {
-	double sortTime, evalTime, nodeTime, splitTime, subdTime;
-
-	sortTime = mBvHierarchy->mSortTimer.TotalTime();
+	double sortTime, evalTime, nodeTime, splitTime, subdTime, planeTime, collectTime, viewCellsTime;
+
+	sortTime = mBvHierarchy->mSort2Timer.TotalTime();
 	evalTime = mBvHierarchy->mEvalTimer.TotalTime();
 	nodeTime = mBvHierarchy->mNodeTimer.TotalTime();
 	splitTime = mBvHierarchy->mSplitTimer.TotalTime();
 	subdTime = mBvHierarchy->mSubdivTimer.TotalTime();
+	planeTime = mBvHierarchy->mPlaneTimer.TotalTime();
+	collectTime = mBvHierarchy->mCollectTimer.TotalTime();
 
 	cout << "bvh times"
@@ -424,5 +428,8 @@
 		 << " node : " << nodeTime
 		 << " split: " << splitTime
-		 << " subd : " << subdTime << endl;
+		 << " subd : " << subdTime 
+		 << " plane: " << planeTime 
+		 << " colct: " << collectTime
+		 << endl;
 
 	Debug << "bvh times"
@@ -431,5 +438,8 @@
 		 << " node : " << nodeTime
 		 << " split: " << splitTime
-		 << " subd : " << subdTime << endl;
+		 << " subd : " << subdTime
+		 << " plane: " << planeTime 
+		 << " colct: " << collectTime
+		 << endl;
 
 	sortTime = mVspTree->mSortTimer.TotalTime();
@@ -438,4 +448,6 @@
 	splitTime = mVspTree->mSplitTimer.TotalTime();
 	subdTime = mVspTree->mSubdivTimer.TotalTime();
+	planeTime = mVspTree->mPlaneTimer.TotalTime();
+	viewCellsTime = mVspTree->mViewCellsTimer.TotalTime();
 
 	cout << "vsp times"
@@ -444,12 +456,19 @@
 		 << " node : " << nodeTime
 		 << " split: " << splitTime
-		 << " subd : " << subdTime << endl;
+		 << " subd : " << subdTime
+		 << " plane: " << planeTime 
+		 << " viewc: " << viewCellsTime 
+		 << endl;
 
 	Debug << "vsp times"
-		<< " sort : " << sortTime
-		 << " eval : " << evalTime
-		 << " node : " << nodeTime
-		 << " split: " << splitTime
-		 << " subd : " << subdTime << endl;
+		  << " sort : " << sortTime
+		  << " eval : " << evalTime
+		  << " node : " << nodeTime
+		  << " split: " << splitTime
+		  << " subd : " << subdTime
+		  << " plane: " << planeTime 
+		  << " viewc: " << viewCellsTime 
+		  << endl;
+
 	cout << endl;
 	Debug << endl;
@@ -854,5 +873,5 @@
 	}
 
-	//cout << "priority: " << sc->GetPriority() << " rc decr: " << sc->GetRenderCostDecrease() << " | ";
+	
 	///////////////
 	//-- split was successful => update stats and queue
@@ -877,5 +896,5 @@
 	const int pvsEntriesIncr = sc->GetPvsEntriesIncr();
 	mHierarchyStats.mPvsEntries += pvsEntriesIncr;
-	//cout << "pvs entries: " << pvsEntriesIncr << " " << mHierarchyStats.pvsEntries << endl;
+	//cout << "pvs entries: " << pvsEntriesIncr << " " << mHierarchyStats.mPvsEntries << endl;
 
 	// memory size in byte
@@ -1156,4 +1175,5 @@
 			mHierarchyStats.mTotalCost = mBvHierarchy->mTotalCost;
 			
+
 			//mHierarchyStats.mPvsEntries -= mBvHierarchy->mPvsEntries + 1;
 			mHierarchyStats.mPvsEntries = mBvHierarchy->CountViewCells(objects);
