Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.h	(revision 653)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.h	(revision 654)
@@ -64,4 +64,6 @@
 		/// if this node is a kd-node (i.e., boundaries are axis aligned
 		bool mIsKdNode;
+
+
 #if OCTREE_HACK // OCTREE HACK
 		int mAxis;
@@ -398,5 +400,5 @@
 								 const VspBspTraversalData &data) const;
 
-	void ConstructWithSplitQueueQueue(const PolygonContainer &polys, RayInfoContainer *rays);
+	void ConstructWithSplitQueue(const PolygonContainer &polys, RayInfoContainer *rays);
 
 
@@ -585,5 +587,7 @@
 	/** Returns true if tree can be terminated.
 	*/
-	inline bool TerminationCriteriaMet(const VspBspTraversalData &data) const;
+	inline bool LocalTerminationCriteriaMet(const VspBspTraversalData &data) const;
+
+	inline bool GlobalTerminationCriteriaMet(const VspBspTraversalData &data) const;
 
 	/** Computes accumulated ray lenght of this rays.
@@ -706,4 +710,9 @@
 	int mTermMinPolygons;
 
+	float mTermMinGlobalCostRatio;
+	int mTermGlobalCostMissTolerance;
+
+	int mGlobalCostMisses;
+
 	//-- termination criteria for axis aligned split
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 653)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 654)
@@ -91,6 +91,8 @@
 	environment->GetFloatValue("VspBspTree.Termination.maxCostRatio", mTermMaxCostRatio);
 
-	// HACK
-	mTermMinPolygons = 25;
+	environment->GetFloatValue("VspBspTree.Termination.minGlobalCostRatio", mTermMinGlobalCostRatio);
+	environment->GetIntValue("VspBspTree.Termination.globalCostMissTolerance", mTermGlobalCostMissTolerance);
+
+	// HACK//mTermMinPolygons = 25;
 
 	//-- factors for bsp tree split plane heuristics
@@ -389,4 +391,6 @@
 	mBspStats.polys = (int)polys.size();
 
+	mGlobalCostMisses = 0;
+
 	cout << "finished" << endl;
 
@@ -395,5 +399,8 @@
 		  << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl << endl;
 
-	Construct(polys, rays);
+	if (0)
+		ConstructWithSplitQueue(polys, rays);
+	else
+		Construct(polys, rays);
 
 	// clean up polygons
@@ -496,5 +503,5 @@
 				  << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl;
 
-		if (mBspStats.Leaves() == nLeaves)
+		if (mBspStats.Leaves() >= nLeaves)
 		{
 			nLeaves += 500;
@@ -523,5 +530,5 @@
 
 
-void VspBspTree::ConstructWithSplitQueueQueue(const PolygonContainer &polys, 
+void VspBspTree::ConstructWithSplitQueue(const PolygonContainer &polys, 
 											  RayInfoContainer *rays)
 {
@@ -551,5 +558,4 @@
 	tQueue.push(splitCandidate);
 
-
 	mTotalCost = tData.mPvs * tData.mProbability / mBox.GetVolume();
 	mTotalPvsSize = tData.mPvs;
@@ -558,4 +564,5 @@
 			<< "#ViewCells\n1\n" <<  endl
 			<< "#RenderCostDecrease\n0\n" << endl 
+			<< "#dummy\n0\n" << endl
 			<< "#TotalRenderCost\n" << mTotalCost << endl
 			<< "#AvgRenderCost\n" << mTotalPvsSize << endl;
@@ -583,4 +590,13 @@
 	    tQueue.pop();		
 
+		// cost ratio of cost decrease / totalCost
+		float costRatio = splitCandidate.GetCost() / mTotalCost;
+
+		Debug << "cost ratio: " << costRatio << endl;
+
+		if (costRatio < mTermMinGlobalCostRatio)
+		{Debug << "here1 cost ratio: " << costRatio << " max " << mTermMinGlobalCostRatio << endl;
+			++ mGlobalCostMisses;
+		}
 		if (0 && !mOutOfMemory)
 		{
@@ -601,5 +617,5 @@
 				  << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl;
 
-		if (mBspStats.Leaves() == nLeaves)
+		if (mBspStats.Leaves() >= nLeaves)
 		{
 			nLeaves += 500;
@@ -627,5 +643,5 @@
 
 
-bool VspBspTree::TerminationCriteriaMet(const VspBspTraversalData &data) const
+bool VspBspTree::LocalTerminationCriteriaMet(const VspBspTraversalData &data) const
 {
 	return
@@ -633,8 +649,4 @@
 		 (data.mPvs <= mTermMinPvs)   ||
 		 (data.mProbability <= mTermMinProbability) ||
-		 (mBspStats.Leaves() >= mMaxViewCells) ||
-#if 0
-		 (((int)data.mPolygons->size() <= mTermMinPolygons) && !data.mPolygons->empty())||
-#endif
 		 (data.GetAvgRayContribution() > mTermMaxRayContribution) ||
 		 (data.mDepth >= mTermMaxDepth));
@@ -642,4 +654,15 @@
 
 
+bool VspBspTree::GlobalTerminationCriteriaMet(const VspBspTraversalData &data) const
+{
+	return
+		(mOutOfMemory 
+		|| (mBspStats.Leaves() >= mMaxViewCells) 
+		|| (mGlobalCostMisses >= mTermGlobalCostMissTolerance)
+		 );
+}
+
+
+
 BspNode *VspBspTree::Subdivide(VspBspTraversalQueue &tQueue,
 							   VspBspTraversalData &tData)
@@ -647,5 +670,5 @@
 	BspNode *newNode = tData.mNode;
 
-	if (!mOutOfMemory && !TerminationCriteriaMet(tData))
+	if (!LocalTerminationCriteriaMet(tData) && !GlobalTerminationCriteriaMet(tData))
 	{
 		PolygonContainer coincident;
@@ -786,5 +809,5 @@
 	BspNode *newNode = tData.mNode;
 
-	if (!mOutOfMemory && !TerminationCriteriaMet(tData))
+	if (!LocalTerminationCriteriaMet(tData) && !GlobalTerminationCriteriaMet(tData))
 	{
 		PolygonContainer coincident;
@@ -801,17 +824,18 @@
 		// create new interior node and two leaf node
 		const Plane3 splitPlane = splitCandidate.mSplitPlane;
-			
+				
 		newNode = SubdivideNode(splitPlane, tData, tFrontData, tBackData, coincident);
-
+		
 #if 0 // TODO
-			if (splitAxis < 3)
-				++ mBspStats.splits[splitAxis];
-			else
-				++ mBspStats.polySplits;
-
-			tFrontData.mIsKdNode = tBackData.mIsKdNode = (tData.mIsKdNode && splitAxis < 3);
-			// how often was max cost ratio missed in this branch?
-			tFrontData.mMaxCostMisses = maxCostMisses;
-			tBackData.mMaxCostMisses = maxCostMisses;
+		if (splitAxis < 3)
+			++ mBspStats.splits[splitAxis];
+		else
+			++ mBspStats.polySplits;
+
+		tFrontData.mIsKdNode = tBackData.mIsKdNode = (tData.mIsKdNode && splitAxis < 3);
+		// how often was max cost ratio missed in this branch?
+		tFrontData.mMaxCostMisses = maxCostMisses;
+		tBackData.mMaxCostMisses = maxCostMisses;
+
 #endif
 		if (1)
@@ -829,5 +853,6 @@
 			mSubdivisionStats 
 					<< "#ViewCells\n" << mBspStats.Leaves() << endl
-					<< "#RenderCostDecrease\n" << -costDecr << endl 
+					<< "#RenderCostDecrease\n" << -costDecr << endl
+					<< "#dummy\n" << splitCandidate.GetCost() << endl
 					<< "#TotalRenderCost\n" << mTotalCost << endl
 					<< "#AvgRenderCost\n" << (float)mTotalPvsSize / (float)mBspStats.Leaves() << endl;
@@ -838,7 +863,7 @@
 		VspBspSplitCandidate backCandidate;
 
-		EvalSplitCandidate(tData, frontCandidate);
-		EvalSplitCandidate(tData, backCandidate);
-
+		EvalSplitCandidate(tFrontData, frontCandidate);
+		EvalSplitCandidate(tBackData, backCandidate);
+	
 		tQueue.push(frontCandidate);
 		tQueue.push(backCandidate);
@@ -847,4 +872,5 @@
 		DEL_PTR(tData.mNode);
 	}
+
 
 	//-- terminate traversal and create new view cell
@@ -904,4 +930,6 @@
 
 	BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode);
+
+	// compute locally best split plane
 	SelectPlane(splitData.mSplitPlane, leaf, tData, frontData, backData, splitAxis);
 
@@ -910,4 +938,5 @@
 	DEL_PTR(backData.mGeometry);
 	
+	// compute global decrease in render cost
 	splitData.mRenderCost = EvalRenderCostDecrease(splitData.mSplitPlane, tData);
 	splitData.mParentData = tData;
@@ -966,5 +995,5 @@
 		{
 			frontData.mProbability = frontData.mGeometry->GetVolume();
-			backData.mProbability =  tData.mProbability - frontData.mProbability;
+			backData.mProbability = tData.mProbability - frontData.mProbability;
 		}
 	}
@@ -1590,5 +1619,5 @@
 	int pvsFront = 0;
 	int pvsBack = 0;
-	int totalPvs = data.mPvs;
+	int totalPvs = 0;
 
 	// probability that view point lies in back / front node
@@ -1649,5 +1678,6 @@
 	const float newRenderCost = penaltyFront * pFront + penaltyBack * pBack;
 
-	return oldRenderCost - newRenderCost;
+	//Debug << "decrease: " << oldRenderCost - newRenderCost << endl;
+	return (oldRenderCost - newRenderCost) / mBox.GetVolume();
 }
 
@@ -1860,5 +1890,5 @@
 	if (!obj)
 		return;
-	
+	// new object
 	if ((obj->mMailbox != sFrontId) &&
 		(obj->mMailbox != sBackId) &&
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 612)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 654)
@@ -1811,4 +1811,13 @@
 /************************************************************************************/
 
+	RegisterOption("VspBspTree.Termination.minGlobalCostRatio",
+					optFloat,
+					"vsp_bsp_term_min_global_cost_ratio",
+					"0.0001");
+
+	RegisterOption("VspBspTree.Termination.globalCostMissTolerance",
+					optInt,
+					"vsp_bsp_term_global_cost_miss_tolerance",
+					"4");
 
 	RegisterOption("VspBspTree.Termination.minPolygons",
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VssPreprocessor.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VssPreprocessor.cpp	(revision 651)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VssPreprocessor.cpp	(revision 654)
@@ -531,6 +531,8 @@
   if (mUseViewSpaceBox)
   {
-	  if (1)
+	  if (0)
+	  {
 		  mViewSpaceBox = box;
+	  }
 	  else
 	  {
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsParser.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsParser.cpp	(revision 651)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsParser.cpp	(revision 654)
@@ -414,5 +414,5 @@
 		}
 	}
-Debug << "here22" << endl;
+
 	
 	if (viewCellId >= 0) // valid view cell
@@ -427,6 +427,5 @@
 		BspViewCell *viewCell = dynamic_cast<BspViewCell *>(*vit);
 
-		Debug << "here44" << endl;
-
+	
 		if (viewCell->GetId() == viewCellId)
 		{
@@ -447,5 +446,5 @@
 			mVspBspTree->PropagateUpValidity(leaf);
 		}
-	}Debug << "here33" << endl;
+	}
 }
 
@@ -496,5 +495,4 @@
 void ViewCellsParseHandlers::StartViewCellLeaf(AttributeList& attributes)
 {
-	Debug << "here111" << endl;
 	BspViewCell *viewCell = new BspViewCell();
 
@@ -518,5 +516,4 @@
 void ViewCellsParseHandlers::StartViewCellInterior(AttributeList& attributes)
 {
-	Debug << "here222" << endl;
 	ViewCellInterior* interior = new ViewCellInterior();
 	
