Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/src/GtpVisibility.vcproj
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/src/GtpVisibility.vcproj	(revision 1239)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/src/GtpVisibility.vcproj	(revision 1288)
@@ -62,4 +62,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
+				GlobalOptimizations="TRUE"
+				FavorSizeOrSpeed="1"
+				OmitFramePointers="TRUE"
 				OptimizeForWindowsApplication="TRUE"
 				AdditionalIncludeDirectories="..\include;&quot;$(OGRE_PATH)\OgreMain\include&quot;;..\..\Preprocessing\src"
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/Plugin_VisibilitySceneManager.vcproj
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/Plugin_VisibilitySceneManager.vcproj	(revision 1276)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/Plugin_VisibilitySceneManager.vcproj	(revision 1288)
@@ -87,5 +87,5 @@
 				OmitFramePointers="TRUE"
 				EnableFiberSafeOptimizations="TRUE"
-				OptimizeForProcessor="3"
+				OptimizeForProcessor="0"
 				OptimizeForWindowsApplication="TRUE"
 				AdditionalIncludeDirectories="&quot;$(OGRE_PATH)\PlugIns\OctreeSceneManager\include&quot;;&quot;$(OGRE_PATH)\Samples\Common\include&quot;;&quot;$(OGRE_PATH)\Dependencies\include\CEGUI&quot;;&quot;$(OGRE_PATH)\Samples\Common\CEGUIRenderer\include&quot;;&quot;$(OGRE_PATH)\OgreMain\include&quot;;&quot;$(OGRE_PATH)\Dependencies\include&quot;;..\include;..\..\..\OnlineCullingCHC\include;..\..\..\Preprocessing\src"
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 1233)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 1288)
@@ -672,8 +672,7 @@
 
 		// cost ratio of cost decrease / totalCost
-		float costRatio = splitCandidate.GetPriority() / mTotalCost;
+		float costRatio = splitCandidate.mRenderCostDecr / mTotalCost;
 
 		//Debug << "cost ratio: " << costRatio << endl;
-
 		if (costRatio < mTermMinGlobalCostRatio)
 			++ mGlobalCostMisses;
@@ -1041,38 +1040,24 @@
 
 
-/*
-void VspBspTree::EvalSubdivisionCandidate(VspBspTraversalData &tData,
-									VspBspSubdivisionCandidate &splitData)
+void VspBspTree::EvalSubdivisionCandidate(VspBspSubdivisionCandidate &splitCandidate)
 {
 	VspBspTraversalData frontData;
 	VspBspTraversalData backData;
-
-	BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode);
-
+	
+	BspLeaf *leaf = dynamic_cast<BspLeaf *>(splitCandidate.mParentData.mNode);
+	
 	// compute locally best split plane
-    bool success = SelectPlane(splitData.mSplitPlane, leaf, tData, 
-							   frontData, backData, splitData.mSplitAxis);
-
-	// TODO: reuse
-	delete frontData.mGeometry;
-	delete backData.mGeometry;
-	
-	// compute global decrease in render cost
-	splitData.mPriority = EvalRenderCostDecrease(splitData.mSplitPlane, tData);
-	splitData.mParentData = tData;
-	splitData.mMaxCostMisses = success ? tData.mMaxCostMisses : tData.mMaxCostMisses + 1;
-}
-*/
-
-void VspBspTree::EvalSubdivisionCandidate(VspBspSubdivisionCandidate &splitCandidate)
-{
-	VspBspTraversalData frontData;
-	VspBspTraversalData backData;
-	
-	BspLeaf *leaf = dynamic_cast<BspLeaf *>(splitCandidate.mParentData.mNode);
-	
-	// compute locally best split plane
-    bool success = SelectPlane(splitCandidate.mSplitPlane, leaf, splitCandidate.mParentData, 
-							   frontData, backData, splitCandidate.mSplitAxis);
+    const bool costRatioViolated = 
+		SelectPlane(splitCandidate.mSplitPlane, 
+					leaf, 
+					splitCandidate.mParentData, 
+					frontData, 
+					backData, 
+					splitCandidate.mSplitAxis);
+
+	// max cost threshold violated?
+	splitCandidate.mMaxCostMisses = costRatioViolated ? 
+		splitCandidate.mParentData.mMaxCostMisses : 
+		splitCandidate.mParentData.mMaxCostMisses + 1;
 
 	float oldRenderCost;
@@ -1101,8 +1086,4 @@
 	
 	splitCandidate.mPriority = priority;
-
-	// max cost threshold violated?
-	splitCandidate.mMaxCostMisses = 
-		success ? splitCandidate.mParentData.mMaxCostMisses : splitCandidate.mParentData.mMaxCostMisses + 1;
 }
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 1287)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 1288)
@@ -2237,13 +2237,13 @@
 
 
-/***************************************************************************/
-/*               Object space partition tree related options               */
-/***************************************************************************/
-
+
+/***********************************************************************/
+/*           Object space partition tree related options               */
+/***********************************************************************/
 
 	RegisterOption("OspTree.Construction.randomize",
-		optBool,
-		"osp_construction_randomize=",
-		"false");
+					optBool,
+					"osp_construction_randomize=",
+					"false");
 
 	RegisterOption("OspTree.Termination.maxDepth",
@@ -2265,10 +2265,10 @@
 					optFloat,
 					"osp_term_min_objects=",
-					"0.0001");
+					"0.00001");
 
 	RegisterOption("OspTree.Termination.missTolerance",
 					optInt,
 					"osp_term_miss_tolerance=",
-					"4");
+					"8");
 
 	RegisterOption("OspTree.Termination.maxCostRatio",
@@ -2293,23 +2293,23 @@
 	
 	RegisterOption("OspTree.Construction.epsilon",
-					optFloat,
-					"osp_construction_epsilon=",
-					"0.00001");
+				   optFloat,
+				   "osp_construction_epsilon=",
+				   "0.00001");
 	
 	// if only the driving axis is used for axis aligned split
 	RegisterOption("OspTree.splitUseOnlyDrivingAxis", 
-					optBool, 
-					"osp_split_only_driving_axis=", 
-					"false");
+				   optBool, 
+				   "osp_split_only_driving_axis=", 
+				   "false");
 
 	RegisterOption("OspTree.maxStaticMemory", 
-		optFloat, 
-		"osp_max_static_mem=", 
-		"8.0");
+				   optFloat, 
+				   "osp_max_static_mem=", 
+				   "8.0");
 
 	RegisterOption("OspTree.useCostHeuristics",
-		optBool,
-		"osp_use_cost_heuristics=",
-		"true");
+				   optBool,
+				   "osp_use_cost_heuristics=",
+				   "true");
 
 	RegisterOption("OspTree.subdivisionStats",
@@ -2324,14 +2324,130 @@
 
 	RegisterOption("OspTree.Construction.renderCostDecreaseWeight",
-			optFloat,
-			"osp_construction_render_cost_decrease_weight=",
-			"0.99");
-
+				   optFloat,
+				   "osp_construction_render_cost_decrease_weight=",
+				   "0.99");
+
+
+
+/***********************************************************************/
+/*            Bounding Volume Hierarchy related options                */
+/***********************************************************************/
+
+	RegisterOption("BvHierarchy.Construction.randomize",
+					optBool,
+					"bvh_construction_randomize=",
+					"false");
+
+	RegisterOption("BvHierarchy.Termination.maxDepth",
+					optInt,
+					"bvh_term_max_depth=",
+					"30");
+	
+	RegisterOption("BvHierarchy.Termination.maxLeaves",
+					optInt,
+					"bvh_term_max_leaves=",
+					"1000");
+	
+	RegisterOption("BvHierarchy.Termination.minObjects",
+					optInt,
+					"bvh_term_min_objects=",
+					"1");
+
+	RegisterOption("BvHierarchy.Termination.minProbability",
+					optFloat,
+					"bvh_term_min_objects=",
+					"0.00001");
+
+	RegisterOption("BvHierarchy.Termination.missTolerance",
+					optInt,
+					"osp_term_miss_tolerance=",
+					"8");
+
+	RegisterOption("BvHierarchy.Termination.maxCostRatio",
+					optFloat,
+					"bvh_term_max_cost_ratio=",
+					"0.99");
+
+	RegisterOption("BvHierarchy.Termination.minGlobalCostRatio",
+					optFloat,
+					"bvh_term_min_global_cost_ratio=",
+					"0.00001");
+
+	RegisterOption("BvHierarchy.Termination.globalCostMissTolerance",
+					optInt,
+					"bvh_term_global_cost_miss_tolerance=",
+					"4");
+
+	RegisterOption("BvHierarchy.Termination.ct_div_ci",
+					optFloat,
+					"bvh_term_ct_div_ci=",
+					"0");
+	
+	RegisterOption("BvHierarchy.Construction.epsilon",
+				   optFloat,
+				   "bvh_construction_epsilon=",
+				   "0.00001");
+	
+	// if only the driving axis is used for axis aligned split
+	RegisterOption("BvHierarchy.splitUseOnlyDrivingAxis", 
+				   optBool, 
+				   "bvh_split_only_driving_axis=", 
+				   "false");
+
+	RegisterOption("BvHierarchy.maxStaticMemory", 
+				   optFloat, 
+				   "bvh_max_static_mem=", 
+				   "8.0");
+
+	RegisterOption("BvHierarchy.useCostHeuristics",
+				   optBool,
+				   "bvh_use_cost_heuristics=",
+				   "true");
+
+	RegisterOption("BvHierarchy.subdivisionStats",
+					optString,
+					"bvh_subdivision_stats=",
+					"bvhSubdivisionStats.log");
+
+	RegisterOption("BvHierarchy.Construction.splitBorder",
+					optFloat,
+					"bvh_construction_split_border=",
+					"0.01");
+
+	RegisterOption("BvHierarchy.Construction.renderCostDecreaseWeight",
+				   optFloat,
+				   "bvh_construction_render_cost_decrease_weight=",
+				   "0.99");
+
+
+/*******************************************************************/
+/*               Hierarchy Manager related options                 */
+/*******************************************************************/
 
 	RegisterOption("Hierarchy.subdivisionStats",
-					optString,
-					"hierarchy_subdivision_stats=",
-					"hierarchySubdivisionStats.log");
-
+        		   optString,
+				   "hierarchy_subdivision_stats=",
+				   "hierarchySubdivisionStats.log");
+
+	RegisterOption("Hierarchy.type",
+        		   optString,
+				   "hierarchy_type=",
+				   "bvh");
+
+	RegisterOption("Hierarchy.Termination.minGlobalCostRatio",
+					optFloat,
+					"hierarchy_term_min_global_cost_ratio=",
+					"0.00001");
+
+	RegisterOption("Hierarchy.Termination.globalCostMissTolerance",
+					optInt,
+					"hierarchy_term_global_cost_miss_tolerance=",
+					"4");
+
+	RegisterOption("Hierarchy.Termination.maxLeaves",
+					optInt,
+					"hierarchy_term_max_leaves=",
+					"1000");
+	
 	//////////////////////////////////////////////////////////////////////////////////
 }
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 1287)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 1288)
@@ -420,6 +420,5 @@
 	else
 	{
-		//-- parse type of view cell container
-
+		// parse type of view cell container
 		Environment::GetSingleton()->GetStringValue("ViewCells.type", buf);		
 	    mViewCellsManager = CreateViewCellsManager(buf);
@@ -456,4 +455,26 @@
 
 
+HierarchyManager *Preprocessor::CreateHierarchyManager(const char *name)
+{
+	HierarchyManager *hierarchyManager;
+
+	if (strcmp(name, "osp") == 0)
+	{
+		// HACK for testing if per kd evaluation works!!
+		const bool ishack = true;
+		if (ishack)
+			hierarchyManager = new HierarchyManager(mVspTree, mKdTree);
+		else
+			hierarchyManager = new HierarchyManager(mVspTree, HierarchyManager::KD_BASED_OBJ_SUBDIV);
+	}
+	else if (strcmp(name, "bvh") == 0)
+	{
+		hierarchyManager = new HierarchyManager(mVspTree, HierarchyManager::BV_BASED_OBJ_SUBDIV);
+	}
+
+	return hierarchyManager;
+}
+
+
 ViewCellsManager *Preprocessor::CreateViewCellsManager(const char *name)
 {
@@ -481,15 +502,8 @@
 	{
 		mVspTree = new VspTree();
-				
-		// HACK for testing if per kd evaluation works!!
-		const bool ishack = true;
-
-		/*if (ishack)
-			mHierarchyManager = new HierarchyManager(mVspTree, mKdTree);
-		else
-			mHierarchyManager = new HierarchyManager(mVspTree, HierarchyManager::KD_BASED_OBJ_SUBDIV);
-		*/
-		mHierarchyManager = new HierarchyManager(mVspTree, HierarchyManager::BV_BASED_OBJ_SUBDIV);
-
+		char buf[100];		
+		Environment::GetSingleton()->GetStringValue("Hierarchy.type", buf);	
+
+		HierarchyManager *mHierarchyManager = CreateHierarchyManager(buf);
 		mViewCellsManager = new VspOspViewCellsManager(vcTree, mHierarchyManager);
 	}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.h	(revision 1287)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.h	(revision 1288)
@@ -59,4 +59,52 @@
 
 
+
+/** View space partition statistics.
+*/
+class HierarchyStatistics: public StatisticsBase
+{
+public:
+
+	/// total number of nodes
+	int nodes;
+		
+	/// maximal reached depth
+	int maxDepth;
+	
+	/// accumulated depth
+	int accumDepth;
+
+	// Constructor
+	HierarchyStatistics() 
+	{
+		Reset();
+	}
+
+	int Nodes() const {return nodes;}
+	int Interior() const { return nodes / 2; }
+	int Leaves() const { return (nodes / 2) + 1; }
+	
+	// TODO: computation wrong
+	double AvgDepth() const { return accumDepth / (double)Leaves();}
+	
+
+	void Reset() 
+	{
+		nodes = 0;
+		maxDepth = 0;
+		accumDepth = 0;
+	}
+
+
+	void Print(ostream &app) const;
+
+	friend ostream &operator<<(ostream &s, const HierarchyStatistics &stat) 
+	{
+		stat.Print(s);
+		return s;
+	} 
+};
+
+
 typedef FlexibleHeap<SubdivisionCandidate *> SplitQueue;
 
@@ -213,4 +261,7 @@
 		const ObjectContainer &objects);
 
+	void ParseEnvironment();
+
+
 protected:
 
@@ -235,4 +286,7 @@
 	float mTotalCost;
 
+	HierarchyStatistics mHierarchyStats;
+
+	int mMaxLeaves;
 	ofstream mSubdivisionStats;
 };
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h	(revision 1287)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h	(revision 1288)
@@ -149,7 +149,10 @@
 						VssRayContainer &vssRays);
 
-  /** Returns a view cells manager with respect to the given name.
+  /** Returns a view cells manager of the given name.
   */
   ViewCellsManager *CreateViewCellsManager(const char *name);
+  /** Returns a hierarchy manager of the given name.
+  */
+  HierarchyManager *CreateHierarchyManager(const char *name);
    
   GlRendererBuffer *GetRenderer() { return renderer;}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp	(revision 1287)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp	(revision 1288)
@@ -196,36 +196,37 @@
 
 	//-- termination criteria for autopartition
-	Environment::GetSingleton()->GetIntValue("OspTree.Termination.maxDepth", mTermMaxDepth);
-	Environment::GetSingleton()->GetIntValue("OspTree.Termination.maxLeaves", mTermMaxLeaves);
-	Environment::GetSingleton()->GetIntValue("OspTree.Termination.minObjects", mTermMinObjects);
-	Environment::GetSingleton()->GetFloatValue("OspTree.Termination.minProbability", mTermMinProbability);
-	
-	Environment::GetSingleton()->GetIntValue("OspTree.Termination.missTolerance", mTermMissTolerance);
+	Environment::GetSingleton()->GetIntValue("BvHierarchy.Termination.maxDepth", mTermMaxDepth);
+	Environment::GetSingleton()->GetIntValue("BvHierarchy.Termination.maxLeaves", mTermMaxLeaves);
+	Environment::GetSingleton()->GetIntValue("BvHierarchy.Termination.minObjects", mTermMinObjects);
+	Environment::GetSingleton()->GetFloatValue("BvHierarchy.Termination.minProbability", mTermMinProbability);
+	
+	Environment::GetSingleton()->GetIntValue("BvHierarchy.Termination.missTolerance", mTermMissTolerance);
 	
 	//-- max cost ratio for early tree termination
-	Environment::GetSingleton()->GetFloatValue("OspTree.Termination.maxCostRatio", mTermMaxCostRatio);
-
-	Environment::GetSingleton()->GetFloatValue("OspTree.Termination.minGlobalCostRatio",
+	Environment::GetSingleton()->GetFloatValue("BvHierarchy.Termination.maxCostRatio", mTermMaxCostRatio);
+
+	Environment::GetSingleton()->GetFloatValue("BvHierarchy.Termination.minGlobalCostRatio",
 		mTermMinGlobalCostRatio);
-	
+	Environment::GetSingleton()->GetIntValue("BvHierarchy.Termination.globalCostMissTolerance", mTermGlobalCostMissTolerance);
 
 	//-- factors for bsp tree split plane heuristics
-	Environment::GetSingleton()->GetFloatValue("OspTree.Termination.ct_div_ci", mCtDivCi);
+	Environment::GetSingleton()->GetFloatValue("BvHierarchy.Termination.ct_div_ci", mCtDivCi);
 
 	//-- partition criteria
-	Environment::GetSingleton()->GetFloatValue("OspTree.Construction.epsilon", mEpsilon);
+	Environment::GetSingleton()->GetFloatValue("BvHierarchy.Construction.epsilon", mEpsilon);
 
 	// if only the driving axis is used for axis aligned split
-	Environment::GetSingleton()->GetBoolValue("OspTree.splitUseOnlyDrivingAxis", mOnlyDrivingAxis);
-	Environment::GetSingleton()->GetFloatValue("OspTree.maxStaticMemory", mMaxMemory);
-	Environment::GetSingleton()->GetBoolValue("OspTree.useCostHeuristics", mUseCostHeuristics);
+	Environment::GetSingleton()->GetBoolValue("BvHierarchy.splitUseOnlyDrivingAxis", mOnlyDrivingAxis);
+	Environment::GetSingleton()->GetFloatValue("BvHierarchy.maxStaticMemory", mMaxMemory);
+	Environment::GetSingleton()->GetBoolValue("BvHierarchy.useCostHeuristics", mUseCostHeuristics);
 
 
 	char subdivisionStatsLog[100];
-	Environment::GetSingleton()->GetStringValue("OspTree.subdivisionStats", subdivisionStatsLog);
+	Environment::GetSingleton()->GetStringValue("BvHierarchy.subdivisionStats", subdivisionStatsLog);
 	mSubdivisionStats.open(subdivisionStatsLog);
 
-	Environment::GetSingleton()->GetFloatValue("OspTree.Construction.splitBorder", mSplitBorder);
-	Environment::GetSingleton()->GetFloatValue("OspTree.Construction.renderCostDecreaseWeight", mRenderCostDecreaseWeight);
+	Environment::GetSingleton()->GetFloatValue("BvHierarchy.Construction.splitBorder", mSplitBorder);
+	Environment::GetSingleton()->GetFloatValue(
+		"BvHierarchy.Construction.renderCostDecreaseWeight", mRenderCostDecreaseWeight);
 	
 
@@ -279,6 +280,6 @@
 	// add the new nodes to the tree
 	BvhInterior *node = new BvhInterior(tData.mBoundingBox, leaf->GetParent());
-
-	cout << "here55 " << tData.mBoundingBox << " | " << node->GetBoundingBox() << endl;
+	//cout << "bbox: " << tData.mBoundingBox << endl;
+
 
 	//-- the front and back traversal data is filled with the new values
@@ -288,6 +289,5 @@
 	frontData.mBoundingBox = ComputeBoundingBox(frontObjects, &(tData.mBoundingBox));
 	backData.mBoundingBox = ComputeBoundingBox(backObjects, &(tData.mBoundingBox));
-	//RemoveParentViewCellsPvs(leaf, *tData.mRays);
-
+	
 	/////////////
 	//-- create front and back leaf
@@ -317,11 +317,6 @@
 	++ mBvhStats.splits;
 
-	//UpdateViewCellsPvs(front, *frontData.mRays);
-	//UpdateViewCellsPvs(back, *backData.mRays);
 
 	////////////////////////////////////
-
-	//ProcessMultipleRefs(front);
-    //ProcessMultipleRefs(back);
 
 	frontData.mNode = front;
@@ -346,5 +341,6 @@
 								const bool globalCriteriaMet)
 {
-	BvhSubdivisionCandidate *sc = dynamic_cast<BvhSubdivisionCandidate *>(splitCandidate);
+	BvhSubdivisionCandidate *sc = 
+		dynamic_cast<BvhSubdivisionCandidate *>(splitCandidate);
 	BvhTraversalData &tData = sc->mParentData;
 
@@ -410,6 +406,5 @@
 	}
 	
-	//-- cleanup
-	tData.Clear();
+	tData.Clear(); // cleanup
 	
 	return newNode;
@@ -425,10 +420,14 @@
 							splitCandidate.mBackObjects);
 	
-	const bool success = ratio < mTermMaxCostRatio;
-
 	BvhLeaf *leaf = splitCandidate.mParentData.mNode;
 
+	// cost ratio violated?
+	const bool maxCostRatioViolated = ratio < mTermMaxCostRatio;
+
+	splitCandidate.mMaxCostMisses = maxCostRatioViolated ? 
+		splitCandidate.mParentData.mMaxCostMisses : 
+		splitCandidate.mParentData.mMaxCostMisses + 1;
+
 	const float viewSpaceVol = mVspTree->GetBoundingBox().GetVolume();
-
 	const float oldRenderCost = 
 		splitCandidate.mParentData.mProbability * (float)leaf->mObjects.size() / viewSpaceVol;
@@ -443,5 +442,5 @@
 	const float renderCostDecr = oldRenderCost - newRenderCost;
 
-	Debug << "!!render cost decr: " << renderCostDecr << endl;
+	//Debug << "render cost decr: " << renderCostDecr << endl;
 	splitCandidate.SetRenderCostDecrease(renderCostDecr);
 
@@ -458,8 +457,4 @@
 	// compute global decrease in render cost
 	splitCandidate.SetPriority(priority);
-
-	splitCandidate.mMaxCostMisses = 
-		success ? splitCandidate.mParentData.mMaxCostMisses : 
-	splitCandidate.mParentData.mMaxCostMisses + 1;
 }
 
@@ -468,8 +463,8 @@
 {
 	// matt: TODO
-	return ( 
-		//(data.mNode->mObjects.size() < mTermMinObjects) ||
-		//(data.mProbability <= mTermMinProbability) ||
-		(data.mDepth >= mTermMaxDepth)
+	return ( 0
+		|| (data.mNode->mObjects.size() < mTermMinObjects)
+		|| (data.mProbability <= mTermMinProbability)
+		|| (data.mDepth >= mTermMaxDepth)
 		 );
 }
@@ -479,8 +474,8 @@
 {
 	// matt: TODO
-	return (
-		(mBvhStats.Leaves() >= mTermMaxLeaves)
-		//mOutOfMemory || 
-		//(mGlobalCostMisses >= mTermGlobalCostMissTolerance)
+	return (0
+		|| (mBvhStats.Leaves() >= mTermMaxLeaves)
+		|| (mGlobalCostMisses >= mTermGlobalCostMissTolerance)
+		//|| mOutOfMemory 
 		);
 }
@@ -498,4 +493,9 @@
         ++ mBvhStats.maxDepthNodes;
 		//Debug << "new max depth: " << mVspStats.maxDepthNodes << endl;
+	}
+
+	if (data.mDepth < mTermMaxDepth)
+	{
+        ++ mBvhStats.minDepthNodes;
 	}
 
@@ -506,6 +506,6 @@
 	mBvhStats.accumDepth += data.mDepth;
  
-	//	if ((int)(leaf->mObjects.size()) < mTermMinCost)
-	//     ++ mOspStats.minCostNodes;
+	if ((int)(leaf->mObjects.size()) < mTermMinObjects)
+	     ++ mBvhStats.minObjectsNodes;
  
 	if ((int)(leaf->mObjects.size()) > mBvhStats.maxObjectRefs)
@@ -914,46 +914,4 @@
 
 
-void BvHierarchy::ClassifyViewCells(const ViewCellContainer &viewCells, 
-									const bool isFront) const
-{
-	int mailed = 0;
-	ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
-
-	// mail view cell
-	for (vit = viewCells.begin(); vit != vit_end; ++ vit)
-	{
-		ViewCell *vc = *vit;
-
-		if (isFront)
-		{
-			if (!vc->Mailed())
-			{
-				vc->Mail();
-				//Debug << " " << vc->mMailBox << endl;
-				++ mailed;
-			}
-		}
-		else
-		{
-			if (vc->Mailed())
-			{
-				vc->Mail(2);
-				//Debug << " " << vc->mMailBox << endl;
-				++ mailed;
-			}
-			else if (!vc->Mailed(1) && !vc->Mailed(2))
-			{
-				vc->Mail(1);
-				//Debug << " " << vc->mMailBox << endl;
-				++ mailed;
-			}
-
-		}
-	}				
-
-	Debug << "mailed " << mailed << " view cells " << endl;
-}
-
-
 float BvHierarchy::EvalRenderCost(const BvhTraversalData &tData,
 								  const ObjectContainer &objectsFront,
@@ -982,82 +940,4 @@
 	return newRenderCost;
 }
-
-
-/*float BvHierarchy::EvalRenderCostDecrease(const BvhTraversalData &tData,
-										  const ObjectContainer &objectsFront,
-										  const ObjectContainer &objectsBack,
-										  float &normalizedOldRenderCost) const
-{
-	BvhLeaf *leaf = tData.mNode;
-
-	// probability that view point lies in a view cell which sees this node
-	float pOverall = 0;
-	float pFront = 0;
-	float pBack = 0;
-	float pFrontAndBack = 0;
-
-	const float viewSpaceVol = mVspTree->GetBoundingBox().GetVolume();
-	
-	ViewCellContainer collectedViewCells;
-	ViewCellContainer viewCellsFront, viewCellsBack;
-
-	// the view cells seen from the front bv
-	
-    CollectViewCells(objectsFront, viewCellsFront);
-	// the view cells seen from the back bv
-	CollectViewCells(objectsBack, viewCellsBack);
-	// the view cells seen from both bvs
-	// note: could be evaluated simpler
-	CollectViewCells(leaf->mObjects, collectedViewCells);
-
-
-	// 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);
-	ClassifyViewCells(viewCellsFront, true);
-	ClassifyViewCells(viewCellsBack, false);
-
-	ViewCellContainer::const_iterator vit, vit_end = collectedViewCells.end();
-
-	// evaluate view cells volume contribution with respect to the mail id
-	for (vit = collectedViewCells.begin(); vit != vit_end; ++ vit)
-	{
-		ViewCell *vc = *vit;
-		if (vc->Mailed())
-			pFront += vc->GetVolume();
-		else if (vc->Mailed(1))
-			pBack += vc->GetVolume();
-		else if (vc->Mailed(2))
-			pFrontAndBack += vc->GetVolume();
-	}
-
-	const int totalObjects = (int)leaf->mObjects.size();
-	const int nObjectsFront = (int)objectsFront.size();
-	const int nObjectsBack = (int)objectsBack.size();
-
-	// these are non-overlapping sets
-	pOverall = pFront + pBack + pFrontAndBack;
-
-	//-- pvs rendering heuristics
-	const float oldRenderCost = pOverall * totalObjects;
-	const float newRenderCost = nObjectsFront * pFront + 
-								nObjectsBack * pBack + 
-								totalObjects * pFrontAndBack;
-
-	// normalize volume with view space volume
-	const float renderCostDecrease = (oldRenderCost - newRenderCost) / viewSpaceVol;
-
-	Debug << "\n(((( eval render cost decrease ))))" << endl
-		  << "back objects: " << nObjectsBack << " front objects " << nObjectsFront << " total objects: " << totalObjects << endl 
-		  << "back p: " << pBack / viewSpaceVol << " front p " << pFront / viewSpaceVol 
-		  << " front and back p " << pFrontAndBack / viewSpaceVol << " p: " << pOverall / viewSpaceVol << endl
-		  << "old rc: " << oldRenderCost / viewSpaceVol << " new rc: " << newRenderCost / viewSpaceVol << endl
-		  << "render cost decrease: " << renderCostDecrease << endl;
-
-	normalizedOldRenderCost = oldRenderCost / viewSpaceVol;
-
-	return renderCostDecrease;
-}*/
 
 
@@ -1469,5 +1349,5 @@
 #endif
 
-	// create osp traversal data
+	// create bvh traversal data
 	BvhTraversalData oData(bvhleaf, 0, mBoundingBox, prop);
 
@@ -1503,5 +1383,5 @@
 void BvhStatistics::Print(ostream &app) const
 {
-	app << "=========== OspTree statistics ===============\n";
+	app << "=========== BvHierarchy statistics ===============\n";
 
 	app << setprecision(4);
@@ -1517,11 +1397,10 @@
 	app << "#AXIS_ALIGNED_SPLITS (number of axis aligned splits)\n" << splits << endl;
 
-	
+	app << "#N_PMINDEPTHLEAVES ( Percentage of leaves at minimum depth )\n" 
+		<<	minDepthNodes * 100 / (double)Leaves() << endl;
+
 	app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maximum depth )\n" 
 		<<	maxDepthNodes * 100 / (double)Leaves() << endl;
 
-	app << "#N_PMINPVSLEAVES  ( Percentage of leaves with mininimal PVS )\n" 
-		<< minPvsNodes * 100 / (double)Leaves() << endl;
-
 	app << "#N_MAXCOSTNODES  ( Percentage of leaves with terminated because of max cost ratio )\n"
 		<< maxCostNodes * 100 / (double)Leaves() << endl;
@@ -1530,4 +1409,7 @@
 		<< minProbabilityNodes * 100 / (double)Leaves() << endl;
 
+	app << "#N_PMINOBJECTSLEAVES  ( Percentage of leaves with mininum objects )\n"
+		<< minObjectsNodes * 100 / (double)Leaves() << endl;
+
 	app << "#N_PMAXDEPTH ( Maximal reached depth )\n" << maxDepth << endl;
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.h	(revision 1251)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.h	(revision 1288)
@@ -156,19 +156,7 @@
 	
 	
-	struct VspBspSubdivisionCandidate
+	class VspBspSubdivisionCandidate
 	{  
-		/// the current split plane
-		Plane3 mSplitPlane;
-		/// split axis of this plane (0, 1, 2, or 3 if non-axis-aligned)
-		int mSplitAxis;
-		/// the number of misses of max cost ratio until this split
-		int mMaxCostMisses;
-
-		// parent data
-		VspBspTraversalData mParentData;
-		// prioriry of this split
-		float mPriority;
-
-		float mRenderCostDecr;
+	public:
 
 		VspBspSubdivisionCandidate(): mPriority(0), mRenderCostDecr(0) 
@@ -189,4 +177,19 @@
 #endif
 		}
+
+		/// the current split plane
+		Plane3 mSplitPlane;
+		/// split axis of this plane (0, 1, 2, or 3 if non-axis-aligned)
+		int mSplitAxis;
+		/// the number of misses of max cost ratio until this split
+		int mMaxCostMisses;
+
+		/// parent data
+		VspBspTraversalData mParentData;
+		/// prioriry of this split
+		float mPriority;
+
+		float mRenderCostDecr;
+
 
 		friend bool operator<(const VspBspSubdivisionCandidate &a, const VspBspSubdivisionCandidate &b)
Index: GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 1287)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 1288)
@@ -55,10 +55,6 @@
 	// minimum depth nodes
 	int minDepthNodes;
-	// max depth nodes
-	int minPvsNodes;
-	// nodes with minimum PVS
-	int minRaysNodes;
-	// max ray contribution nodes
-	int maxRayContribNodes;
+	// nodes with minimum objects
+	int minObjectsNodes;
 	// minimum area nodes
 	int minProbabilityNodes;
@@ -99,7 +95,5 @@
 		accumDepth = 0;
        	maxDepthNodes = 0;
-		minPvsNodes = 0;
-		minRaysNodes = 0;
-		maxRayContribNodes = 0;
+		minObjectsNodes = 0;
 		minProbabilityNodes = 0;
 		maxCostNodes = 0;
@@ -699,15 +693,7 @@
 	bool IsObjectInLeaf(BvhLeaf *, Intersectable *object) const;
 
-	/** Classifies view cells using the mail id.
-		0 = front bv, 1 = back bv, 2 = both bvs
-	*/
-	void ClassifyViewCells(
-		const ViewCellContainer &objects, 
-		const bool isFront) const;
-
 	SubdivisionCandidate *PrepareConstruction(
 		const VssRayContainer &sampleRays,
 		const ObjectContainer &objects
-		//,AxisAlignedBox3 *forcedObjectSpace
 		);
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp	(revision 1287)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp	(revision 1288)
@@ -62,29 +62,41 @@
 		mVspTree->mHierarchyManager = this;
 
+	ParseEnvironment();
+}
+
+
+HierarchyManager::HierarchyManager(VspTree *vspTree, KdTree *kdTree): 
+mObjectSpaceSubdivisonType(KD_BASED_OBJ_SUBDIV),
+mVspTree(vspTree), 
+mBvHierarchy(NULL)
+{
+	mOspTree = new OspTree(*kdTree);
+	mOspTree->mVspTree = mVspTree;
+
+	//mOspTree->mHierarchyManager = this;
+	Debug << "creating osp tree" << endl;
+
+	if (mVspTree)
+		mVspTree->mHierarchyManager = this;
+
+	ParseEnvironment();
+}
+
+
+void HierarchyManager::ParseEnvironment()
+{
 	char subdivisionStatsLog[100];
 	Environment::GetSingleton()->GetStringValue("Hierarchy.subdivisionStats", 
 		subdivisionStatsLog);
 	mSubdivisionStats.open(subdivisionStatsLog);
-}
-
-
-HierarchyManager::HierarchyManager(VspTree *vspTree, KdTree *kdTree): 
-mObjectSpaceSubdivisonType(KD_BASED_OBJ_SUBDIV),
-mVspTree(vspTree), 
-mBvHierarchy(NULL)
-{
-	mOspTree = new OspTree(*kdTree);
-	mOspTree->mVspTree = mVspTree;
-
-	//mOspTree->mHierarchyManager = this;
-	Debug << "creating osp tree" << endl;
-
-	if (mVspTree)
-		mVspTree->mHierarchyManager = this;
-
-	char subdivisionStatsLog[100];
-	Environment::GetSingleton()->GetStringValue("Hierarchy.subdivisionStats", 
-		subdivisionStatsLog);
-	mSubdivisionStats.open(subdivisionStatsLog);
+
+	Environment::GetSingleton()->GetFloatValue(
+		"Hierarchy.Termination.minGlobalCostRatio", mTermMinGlobalCostRatio);
+	Environment::GetSingleton()->GetIntValue(
+		"Hierarchy.Termination.globalCostMissTolerance", mTermGlobalCostMissTolerance);
+
+	//Debug << "max depth: " << mTermMaxDepth << endl;
+	Debug << "min global cost ratio: " << mTermMinGlobalCostRatio << endl;
+	Debug << "global cost miss tolerance: " << mTermGlobalCostMissTolerance << endl;
 }
 
@@ -183,6 +195,9 @@
 bool HierarchyManager::GlobalTerminationCriteriaMet(SubdivisionCandidate *candidate) const
 {
-	// TODO matt: make virtual by creating superclasss for traveral data
-	return candidate->GlobalTerminationCriteriaMet();
+	return (0
+		|| (mHierarchyStats.Leaves() >= mMaxLeaves) 
+		|| (mGlobalCostMisses >= mTermGlobalCostMissTolerance)
+		||	candidate->GlobalTerminationCriteriaMet()
+		);
 }
 
@@ -200,4 +215,7 @@
 	mVspTree->mVspStats.Reset();
 	mVspTree->mVspStats.Start();
+	
+	mHierarchyStats.Reset();
+	mHierarchyStats.Start();
 
 	cout << "Constructing view space / object space tree ... \n";
@@ -222,4 +240,7 @@
 	{
 		VspNode *n = mVspTree->Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
+
+		if (n->IsLeaf()) // local or global termination criteria failed
+			return false;
 	}
 	else
@@ -228,12 +249,17 @@
 		{
 			KdNode *n = mOspTree->Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
+
+			if (n->IsLeaf()) // local or global termination criteria failed
+				return false;
 		}
 		else if (mObjectSpaceSubdivisonType == BV_BASED_OBJ_SUBDIV)
 		{
 			BvhNode *n = mBvHierarchy->Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
-		}
-	}
-	
-	return !globalTerminationCriteriaMet;
+			if (n->IsLeaf()) // local or global termination criteria failed
+				return false;
+		}
+	}
+	
+	return true;//!globalTerminationCriteriaMet;
 }
 
@@ -241,5 +267,6 @@
 void HierarchyManager::RunConstruction(const bool repair)
 {
-	int numNodes = 0;
+	mHierarchyStats.nodes = 0;
+	mGlobalCostMisses = 0;
 
 	while (!FinishedConstruction())
@@ -252,11 +279,7 @@
 		const float costRatio = splitCandidate->GetRenderCostDecrease() / mTotalCost;
 
+		Debug << "ratio: " << costRatio << " min ratio: " << mTermMinGlobalCostRatio << endl;
 		if (costRatio < mTermMinGlobalCostRatio)
 			++ mGlobalCostMisses;
-	
-		/*Debug << "\n**********" << endl
-			  << "total cost: " << mTotalCost << " render cost decr: " 
-			  << splitCandidate->GetRenderCostDecrease() 
-			  << " cost ratio: " << costRatio << endl << endl;*/
 
 		//-- subdivide leaf node
@@ -264,4 +287,6 @@
 		if (ApplySubdivisionCandidate(splitCandidate))
 		{
+			mHierarchyStats.nodes += 2;
+
 			// subdivision successful
 			EvalSubdivisionStats(*splitCandidate);
Index: GTP/trunk/Lib/Vis/Preprocessing/src/OspTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/OspTree.cpp	(revision 1287)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/OspTree.cpp	(revision 1288)
@@ -203,5 +203,6 @@
 
 	Environment::GetSingleton()->GetFloatValue("OspTree.Construction.splitBorder", mSplitBorder);
-	Environment::GetSingleton()->GetFloatValue("OspTree.Construction.renderCostDecreaseWeight", mRenderCostDecreaseWeight);
+	Environment::GetSingleton()->GetFloatValue(
+		"OspTree.Construction.renderCostDecreaseWeight", mRenderCostDecreaseWeight);
 	
 
