Index: GTP/trunk/Lib/Vis/Preprocessing/src/SubdivisionCandidate.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/SubdivisionCandidate.h	(revision 1695)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/SubdivisionCandidate.h	(revision 1727)
@@ -93,4 +93,8 @@
 	}
 
+	inline bool IsDirty() const
+	{
+		return mDirty;
+	}
 
 	//////////
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 1715)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 1727)
@@ -1333,5 +1333,5 @@
 	RayInfoContainer usedRays;
 
-	if (mMaxTests < rays.size())
+	if (mMaxTests < (int)rays.size())
 	{
 		GetRayInfoSets(rays, mMaxTests, usedRays);
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 1723)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 1727)
@@ -2458,5 +2458,4 @@
 				   "bvh_use_cost_heuristics=",
 				   "true");
-
 	
 	RegisterOption("BvHierarchy.useSah",
@@ -2485,4 +2484,9 @@
 					"0");
 
+	RegisterOption("BvHierarchy.maxTests",
+					optInt,
+					"bvh_max_tests=",
+					"50000");
+
 
 	/*******************************************************************/
@@ -2574,5 +2578,10 @@
 					"hierarchy_construction_levels=",
 					"4");
-	
+
+	RegisterOption("Hierarchy.Construction.maxRepairs",
+					optInt,
+					"hierarchy_construction_maxRepairs=",
+					"1000");
+
 	RegisterOption("Hierarchy.Construction.minStepsOfSameType",
 					optInt,
Index: GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.h	(revision 1723)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.h	(revision 1727)
@@ -625,4 +625,6 @@
 	bool mConsiderMemory2;
 
+	int mMaxRepairs;
+
 	int mTimeStamp;
 	friend VspTree;
Index: GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp	(revision 1723)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp	(revision 1727)
@@ -287,10 +287,9 @@
 	Environment::GetSingleton()->GetFloatValue(
 		"BvHierarchy.Construction.renderCostDecreaseWeight", mRenderCostDecreaseWeight);
-	
 	Environment::GetSingleton()->GetBoolValue(
 		"BvHierarchy.Construction.useGlobalSorting", mUseGlobalSorting);
-
 	Environment::GetSingleton()->GetIntValue("BvHierarchy.minRaysForVisibility", mMinRaysForVisibility);
-	
+	Environment::GetSingleton()->GetIntValue("BvHierarchy.maxTests", mMaxTests);
+
 	//mUseBboxAreaForSah = false;
 	mUseBboxAreaForSah = true;
@@ -1183,5 +1182,5 @@
 #endif
 
-	///////////////////////////////////////////////////
+	///////////////////////
 	//-- the sweep heuristics
 	//-- traverse through events and find best split plane
@@ -1320,5 +1319,6 @@
 
 
-float BvHierarchy::PrepareHeuristics(const BvhTraversalData &tData, const int axis)
+float BvHierarchy::PrepareHeuristics(const BvhTraversalData &tData, 
+									 const int axis)
 {	
 	BvhLeaf *leaf = tData.mNode;
@@ -1328,7 +1328,26 @@
 	PrepareLocalSubdivisionCandidates(tData, axis);
 	
+	VssRayContainer rays;
+	rays.reserve(tData.mNumRays);
+	CollectRays(tData.mNode->mObjects, rays);
+
+	const float prop = (float)mMaxTests / (float)tData.mNumRays;
+
+	VssRay::NewMail();
+
+	// only use a subset of the rays
+	VssRayContainer::const_iterator rit, rit_end = rays.end();
+
+	for (rit = rays.begin(); rit != rit_end; ++ rit)
+	{
+		if ((mMaxTests >= tData.mNumRays) || (Random(1.0f) < prop))
+		{
+			(*rit)->Mail();
+		}
+	}
+	
 	// collect and mark the view cells as belonging to front pvs
 	ViewCellContainer viewCells;
-	CollectViewCells(tData.mNode->mObjects, viewCells, true);
+	CollectViewCells(tData.mNode->mObjects, viewCells, true, true);
 			
 	ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
@@ -1361,5 +1380,5 @@
 	const bool useMailboxing = false;
 
-	CollectViewCells(obj, viewCells, useMailboxing);
+	CollectViewCells(obj, viewCells, useMailboxing, true, true);
 
 	// classify view cells and compute volume contri accordingly
@@ -1666,11 +1685,7 @@
 void BvHierarchy::CollectViewCells(const ObjectContainer &objects, 
 								   ViewCellContainer &viewCells,
-								   const bool setCounter) const
-{
-	// no view cells yet
-	if (0 && mHierarchyManager->GetViewSpaceSubdivisionType() == 
-		HierarchyManager::NO_VIEWSPACE_SUBDIV)
-		return;
-
+								   const bool setCounter,
+								   const bool onlyMailedRays) const
+{
 	ViewCell::NewMail();
 	ObjectContainer::const_iterator oit, oit_end = objects.end();
@@ -1679,5 +1694,6 @@
 	for (oit = objects.begin(); oit != oit_end; ++ oit)
 	{
-		CollectViewCells(*oit, viewCells, true, setCounter);
+		// always use only mailed objects
+		CollectViewCells(*oit, viewCells, true, setCounter, onlyMailedRays);
 	}
 }
@@ -1687,5 +1703,6 @@
 								   ViewCellContainer &viewCells,
 								   const bool useMailBoxing,
-								   const bool setCounter) const
+								   const bool setCounter,
+								   const bool onlyMailedRays) const
 {
 	VssRayContainer::const_iterator rit, rit_end = obj->GetOrCreateRays()->end();
@@ -1694,6 +1711,11 @@
 	{
 		VssRay *ray = (*rit);
+
+		if (onlyMailedRays && !ray->Mailed())
+			continue;
+
+		ray->Mail();
+
 		ViewCellContainer tmpViewCells;
-	
 		mHierarchyManager->mVspTree->GetViewCells(*ray, tmpViewCells);
 
@@ -1784,5 +1806,5 @@
 	ViewCellContainer viewCells;
 	ViewCell::NewMail();
-	CollectViewCells(node->mObjects, viewCells, true);
+	CollectViewCells(node->mObjects, viewCells, true, false);
 
 	if (0) cout << "collected " << (int)viewCells.size() << " dirty candidates" << endl;
@@ -1965,5 +1987,7 @@
 
 	ViewCellContainer viewCells;
-	CollectViewCells(objects, viewCells);
+	// here we have to account for all view cells that can 
+	// be seen from the objects
+	CollectViewCells(objects, viewCells, false, false);
 
 	ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
Index: GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 1718)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 1727)
@@ -783,5 +783,6 @@
 	void CollectViewCells(const ObjectContainer &objects, 
 						  ViewCellContainer &viewCells,
-						  const bool setCounter = false) const;
+						  const bool setCounter,
+						  const bool onlyMailedRays) const;
 
 	/** Counts the view cells of this object. note: only
@@ -799,5 +800,6 @@
 						  ViewCellContainer &viewCells, 
 						  const bool useMailBoxing,
-						  const bool setCounter = false) const;
+						  const bool setCounter,
+						  const bool onlyMailedRays) const;
 
 	/** Evaluates increase in pvs size.
@@ -951,4 +953,6 @@
 
 	int mMinRaysForVisibility;
+
+	int mMaxTests;
 };
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.cpp	(revision 1715)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.cpp	(revision 1727)
@@ -462,5 +462,6 @@
 	Environment::GetSingleton()->GetIntValue("VspTree.maxTests", mMaxTests);
 
-	Environment::GetSingleton()->GetFloatValue("VspTree.Construction.renderCostDecreaseWeight", mRenderCostDecreaseWeight);
+	Environment::GetSingleton()->
+		GetFloatValue("VspTree.Construction.renderCostDecreaseWeight", mRenderCostDecreaseWeight);
 	
 	// if only the driving axis is used for axis aligned split
@@ -1254,13 +1255,17 @@
 {
 	// get subset of rays
-	RayInfoContainer usedRays;
+	RayInfoContainer randomRays;
+	randomRays.reserve(mMaxTests);
+
+	RayInfoContainer *usedRays;
 
 	if (mMaxTests < (int)tData.mRays->size())
 	{
-		GetRayInfoSets(*tData.mRays, mMaxTests, usedRays);
+		GetRayInfoSets(*tData.mRays, mMaxTests, randomRays);
+		usedRays = &randomRays;
 	}
 	else
 	{
-		usedRays = *tData.mRays;
+		usedRays = tData.mRays;
 	}
 
@@ -1273,9 +1278,9 @@
 	const float maxBand = minBox + mMaxBand * sizeBox;
 
-	SortSubdivisionCandidates(usedRays, axis, minBand, maxBand);
+	SortSubdivisionCandidates(*usedRays, axis, minBand, maxBand);
 
 	// prepare the sweep
 	// note: returns pvs size => no need t give pvs size as function parameter
-	const int pvsSize = PrepareHeuristics(usedRays);
+	const int pvsSize = PrepareHeuristics(*usedRays);
 
 	// go through the lists, count the number of objects left and right
Index: GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp	(revision 1723)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp	(revision 1727)
@@ -149,4 +149,7 @@
 		"Hierarchy.Termination.maxMemory", mTermMaxMemory);
 
+	Environment::GetSingleton()->GetIntValue(
+		"Hierarchy.Construction.maxRepairs", mMaxRepairs);
+
 	if (1 && mConsiderMemory2)
 	{
@@ -177,4 +180,5 @@
 	Debug << "min steps of same kind: " << mMinStepsOfSameType << endl;
 	Debug << "max steps of same kind: " << mMaxStepsOfSameType << endl;
+	Debug << "max repairs: " << mMaxRepairs << endl;
 
 	switch (mConstructionType)
@@ -418,7 +422,7 @@
 	const int maxSteps = mMaxStepsOfSameType;
 
-	SubdivisionCandidate *osc = PrepareObjectSpaceSubdivision(sampleRays, objects);
+	SubdivisionCandidate *osc = 
+		PrepareObjectSpaceSubdivision(sampleRays, objects);
 	objectSpaceQueue.Push(osc);
-
 
 	/////////////////////////
@@ -430,5 +434,10 @@
 	// for first round, use sah splits. Once view space partition
 	// has started, use render cost heuristics instead
-	ospSteps = RunConstruction(objectSpaceQueue, dirtyList, NULL, minSteps, maxSteps);
+	ospSteps = RunConstruction(objectSpaceQueue, 
+							   dirtyList, 
+							   NULL, 
+							   minSteps, 
+							   maxSteps);
+
 	cout << "\n" << ospSteps << " object space partition steps taken" << endl;
 
@@ -474,4 +483,10 @@
 	{
 		// decide upon next split type
+		if (viewSpaceQueue.Top()->IsDirty())
+			viewSpaceQueue.Top()->EvalCandidate();
+
+		if (objectSpaceQueue.Top()->IsDirty())
+			objectSpaceQueue.Top()->EvalCandidate();
+
 		const float vspPriority = viewSpaceQueue.Top() ? viewSpaceQueue.Top()->GetPriority() : -1e20f;
 		const float ospPriority = objectSpaceQueue.Top() ? objectSpaceQueue.Top()->GetPriority() : -1e20f;
@@ -489,9 +504,12 @@
 			SubdivisionCandidateContainer dirtyVspList;
 
-			// subdivide object space first
-			// for first round, use sah splits. Once view space partition
+			// subdivide object space first for first round, 
+			// use sah splits. Once view space partition
 			// has started, use render cost heuristics instead
-			const int ospSteps = 
-				RunConstruction(objectSpaceQueue, dirtyVspList, viewSpaceQueue.Top(), minSteps, maxSteps);
+			const int ospSteps = RunConstruction(objectSpaceQueue, 
+												 dirtyVspList, 
+												 viewSpaceQueue.Top(), 
+												 minSteps, 
+												 maxSteps);
 
 			cout << "\n" << ospSteps << " object space partition steps taken" << endl;
@@ -501,4 +519,5 @@
 			cout << "repairing queue ... " << endl;
 			RepairQueue(dirtyVspList, viewSpaceQueue, true);
+            
 			cout << "\nrepaired " << (int)dirtyVspList.size() << " candidates" << endl;
 		}
@@ -515,6 +534,9 @@
 
 			// process view space candidates
-			const int vspSteps = 
-				RunConstruction(viewSpaceQueue, dirtyOspList, objectSpaceQueue.Top(), minSteps, maxSteps);
+			const int vspSteps = RunConstruction(viewSpaceQueue, 
+												 dirtyOspList, 
+												 objectSpaceQueue.Top(), 
+												 minSteps, 
+												 maxSteps);
 
 			cout << "\n" << vspSteps << " view space partition steps taken" << endl;
@@ -527,4 +549,5 @@
 			cout << "repairing queue ... " << endl;
 			RepairQueue(dirtyOspList, objectSpaceQueue, true);
+
 			cout << "repaired " << (int)dirtyOspList.size() << " candidates" << endl;
 		}
@@ -965,4 +988,8 @@
 	while (!splitQueue.Empty())
 	{
+		// reevaluate current candidate
+		if (splitQueue.Top()->IsDirty())
+			splitQueue.Top()->EvalCandidate();
+		
 		const float priority = splitQueue.Top()->GetPriority();
 		const float threshold = oldCandidate ? oldCandidate->GetPriority() : 1e20f;
@@ -975,9 +1002,9 @@
 		}
 		
-		SubdivisionCandidate *sc = NextSubdivisionCandidate(splitQueue); 
-				
 		////////
 		//-- subdivide leaf node of either type
 
+		SubdivisionCandidate *sc = NextSubdivisionCandidate(splitQueue); 
+			
 		const bool repairQueue = false;
 		const bool success = ApplySubdivisionCandidate(sc, splitQueue, repairQueue);
@@ -1323,5 +1350,6 @@
 	const long startTime = GetTime();
    	if (0) cout << "repairing " << (int)dirtyList.size() << " candidates ... ";
-	
+
+	const float prop = (float)mMaxRepairs / (float)dirtyList.size();
 
 	///////////////////////////
@@ -1332,4 +1360,8 @@
 	for (sit = dirtyList.begin(); sit != sit_end; ++ sit)
 	{
+		// only repair a certain number of candidates
+		if ((mMaxRepairs < (int)dirtyList.size()) && (Random(1.0f) >= prop))
+			continue;
+
 		SubdivisionCandidate* sc = *sit;
 		const float rcd = sc->GetRenderCostDecrease();
