Index: GTP/trunk/Lib/Vis/Preprocessing/scripts/Preprocessor.vcproj
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/scripts/Preprocessor.vcproj	(revision 1138)
+++ GTP/trunk/Lib/Vis/Preprocessing/scripts/Preprocessor.vcproj	(revision 1145)
@@ -164,19 +164,4 @@
 			</File>
 			<File
-				RelativePath="..\src\GlRenderer.cpp">
-			</File>
-			<File
-				RelativePath="..\src\GlRenderer.h">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCustomBuildTool"
-						Description="Performing moc on $(InputName).h"
-						CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp
-"
-						Outputs="$(InputDir)moc_$(InputName).cpp"/>
-				</FileConfiguration>
-			</File>
-			<File
 				RelativePath="..\src\GzBinFileInputStream.cpp">
 			</File>
@@ -246,13 +231,4 @@
 			<File
 				RelativePath="..\src\MeshKdTree.h">
-			</File>
-			<File
-				RelativePath="..\src\moc_GlRenderer.cpp">
-			</File>
-			<File
-				RelativePath="..\src\moc_Preprocessor.cpp">
-			</File>
-			<File
-				RelativePath="..\src\moc_PreprocessorThread.cpp">
 			</File>
 			<File
@@ -356,10 +332,4 @@
 			</File>
 			<File
-				RelativePath="..\src\Renderer.cpp">
-			</File>
-			<File
-				RelativePath="..\src\Renderer.h">
-			</File>
-			<File
 				RelativePath="..\src\RenderSampler.cpp">
 			</File>
@@ -548,4 +518,26 @@
 			<File
 				RelativePath="..\include\ViewCell.h">
+			</File>
+		</Filter>
+		<Filter
+			Name="Renderer"
+			Filter="">
+			<File
+				RelativePath="..\src\GlRenderer.cpp">
+			</File>
+			<File
+				RelativePath="..\src\GlRenderer.h">
+			</File>
+			<File
+				RelativePath="..\src\QtGlRenderer.cpp">
+			</File>
+			<File
+				RelativePath="..\src\QtGlRenderer.h">
+			</File>
+			<File
+				RelativePath="..\src\Renderer.cpp">
+			</File>
+			<File
+				RelativePath="..\src\Renderer.h">
 			</File>
 		</Filter>
Index: GTP/trunk/Lib/Vis/Preprocessing/scripts/TestPreprocessor.vcproj
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/scripts/TestPreprocessor.vcproj	(revision 1077)
+++ GTP/trunk/Lib/Vis/Preprocessing/scripts/TestPreprocessor.vcproj	(revision 1145)
@@ -70,5 +70,5 @@
 			<Tool
 				Name="VCCLCompilerTool"
-				AdditionalIncludeDirectories="..\include;&quot;$(QTDIR)\include\QtCore&quot;;&quot;$(QTDIR)\include\QtGui&quot;;&quot;$(QTDIR)\include&quot;;&quot;$(QTDIR)\include\QtOpenGl&quot;;..\src;&quot;$(CG_INC_PATH)&quot;;..\..\..\..\..\..\NonGTP\Devil\include;..\..\..\..\..\..\NonGTP\Zlib\include;..\..\..\..\..\..\NonGTP\Xerces"
+				AdditionalIncludeDirectories="..\include;&quot;$(QTDIR)\include\QtCore&quot;;&quot;$(QTDIR)\include\QtGui&quot;;&quot;$(QTDIR)\include&quot;;&quot;$(BOOST_INCLUDE)&quot;;&quot;$(QTDIR)\include\QtOpenGl&quot;;..\src;&quot;$(CG_INC_PATH)&quot;;..\..\..\..\..\..\NonGTP\Devil\include;..\..\..\..\..\..\NonGTP\Zlib\include;..\..\..\..\..\..\NonGTP\Xerces"
 				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
 				RuntimeLibrary="2"
@@ -85,5 +85,5 @@
 				OutputFile="$(OutDir)/Preprocessor.exe"
 				LinkIncremental="1"
-				AdditionalLibraryDirectories="..\support\xercesc\lib\;..\support\zlib\lib\;..\support\devil\lib;&quot;$(QTDIR)\lib&quot;;..\include;..\src\GL;&quot;$(CG_LIB_PATH)&quot;;&quot;$(GTPDIR)\NonGTP\Xerces&quot;;&quot;$(GTPDIR)\NonGTP\Xerces\xercesc\lib&quot;;&quot;$(GTPDIR)\NonGTP\zlib\lib&quot;;&quot;$(GTPDIR)\NonGTP\Devil\lib&quot;;..\lib\release;..\..\Preprocessing\lib\release"
+				AdditionalLibraryDirectories="..\support\xercesc\lib\;..\support\zlib\lib\;..\support\devil\lib;&quot;$(QTDIR)\lib&quot;;..\include;..\src\GL;&quot;$(CG_LIB_PATH)&quot;;&quot;$(GTPDIR)\NonGTP\Xerces&quot;;&quot;$(GTPDIR)\NonGTP\Xerces\xercesc\lib&quot;;&quot;$(GTPDIR)\NonGTP\zlib\lib&quot;;&quot;$(GTPDIR)\NonGTP\Devil\lib&quot;;..\lib\release;..\..\Preprocessing\lib\release;&quot;$(BOOST_LIB)&quot;"
 				GenerateDebugInformation="FALSE"
 				SubSystem="1"
Index: GTP/trunk/Lib/Vis/Preprocessing/src/OcclusionQuery.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/OcclusionQuery.cpp	(revision 1001)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/OcclusionQuery.cpp	(revision 1145)
@@ -1,7 +1,4 @@
-//#include "glInterface.h"
 #include "OcclusionQuery.h"
 #include <iostream>
-//#include <GL/gl.h>
-//#include <QtOpenGL>
 #include <glInterface.h>
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 1141)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 1145)
@@ -640,5 +640,7 @@
 	// compute first split candidate
 	VspBspSplitCandidate splitCandidate;
-	EvalSplitCandidate(tData, splitCandidate);
+	splitCandidate.mParentData = tData;
+
+	EvalSplitCandidate(splitCandidate);
 
 	tQueue.push(splitCandidate);
@@ -814,20 +816,6 @@
 			// evaluate subdivision stats
 			if (1)
-			{
-				const float cFront = (float)tFrontData.mPvs * tFrontData.mProbability;
-				const float cBack = (float)tBackData.mPvs * tBackData.mProbability;
-				const float cData = (float)tData.mPvs * tData.mProbability;;
-
-                const float costDecr = (cFront + cBack - cData) / mBox.GetVolume();
-
-				mTotalCost += costDecr;
-				mTotalPvsSize += tFrontData.mPvs + tBackData.mPvs - tData.mPvs;
-
-				AddSubdivisionStats(mBspStats.Leaves(),
-								    -costDecr,
-									0,
-									mTotalCost,
-									(float)mTotalPvsSize / (float)mBspStats.Leaves());
-			}
+				EvalSubdivisionStats(tData, tFrontData, tBackData);
+			
 
 			// push the children on the stack
@@ -964,8 +952,11 @@
 		//-- push the new split candidates on the stack
 		VspBspSplitCandidate frontCandidate;
+		frontCandidate.mParentData = tFrontData;
+
 		VspBspSplitCandidate backCandidate;
-
-		EvalSplitCandidate(tFrontData, frontCandidate);
-		EvalSplitCandidate(tBackData, backCandidate);
+		backCandidate.mParentData = tBackData;
+
+		EvalSplitCandidate(frontCandidate);
+		EvalSplitCandidate(backCandidate);
 	
 		tQueue.push(frontCandidate);
@@ -1047,4 +1038,5 @@
 
 
+/*
 void VspBspTree::EvalSplitCandidate(VspBspTraversalData &tData,
 									VspBspSplitCandidate &splitData)
@@ -1067,4 +1059,69 @@
 	splitData.mParentData = tData;
 	splitData.mMaxCostMisses = success ? tData.mMaxCostMisses : tData.mMaxCostMisses + 1;
+}
+*/
+
+void VspBspTree::EvalSplitCandidate(VspBspSplitCandidate &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);
+
+	float oldRenderCost;
+
+	// compute global decrease in render cost
+	const float renderCostDecr = EvalRenderCostDecrease(splitCandidate.mSplitPlane, 
+														splitCandidate.mParentData,
+														oldRenderCost);
+
+	splitCandidate.mRenderCostDecr = renderCostDecr;
+
+	// TODO: geometry could be reused
+	delete frontData.mGeometry;
+	delete backData.mGeometry;
+
+	// set priority for queue
+#if 0
+	const float priority = (float)-data.mDepth;
+#else	
+
+	// take render cost of node into account 
+	// otherwise danger of being stuck in a local minimum!!
+	const float factor = mRenderCostDecreaseWeight;
+	const float priority = factor * renderCostDecr + (1.0f - factor) * oldRenderCost;
+#endif
+	
+	splitCandidate.mPriority = priority;
+
+	// max cost threshold violated?
+	splitCandidate.mMaxCostMisses = 
+		success ? splitCandidate.mParentData.mMaxCostMisses : splitCandidate.mParentData.mMaxCostMisses + 1;
+}
+
+
+void VspBspTree::EvalSubdivisionStats(const VspBspTraversalData &tData,
+									  const VspBspTraversalData &tFrontData,
+									  const VspBspTraversalData &tBackData)
+{
+	const float cFront = (float)tFrontData.mPvs * tFrontData.mProbability;
+	const float cBack = (float)tBackData.mPvs * tBackData.mProbability;
+	const float cData = (float)tData.mPvs * tData.mProbability;
+	
+	const float costDecr = 
+		(cFront + cBack - cData) / mBox.GetVolume();
+
+	mTotalCost += costDecr;
+	mTotalPvsSize += tFrontData.mPvs + tBackData.mPvs - tData.mPvs;
+
+	AddSubdivisionStats(mBspStats.Leaves(),
+						-costDecr,
+						0,
+						mTotalCost,
+						(float)mTotalPvsSize / (float)mBspStats.Leaves());
 }
 
@@ -1896,5 +1953,6 @@
 
 float VspBspTree::EvalRenderCostDecrease(const Plane3 &candidatePlane,
-										 const VspBspTraversalData &data) const
+										 const VspBspTraversalData &data,
+										 float &normalizedOldRenderCost) const
 {
 	float pvsFront = 0;
@@ -1972,13 +2030,10 @@
 	const float newRenderCost = penaltyFront * pFront + penaltyBack * pBack;
 
-	//Debug << "decrease: " << oldRenderCost - newRenderCost << endl;
 	const float renderCostDecrease = (oldRenderCost - newRenderCost) / mBox.GetVolume();
 	
-	const float weight = mRenderCostDecreaseWeight;
 	// take render cost of node into account to avoid being stuck in a local minimum
-	const float normalizedOldRenderCost = oldRenderCost / mBox.GetVolume();
-	
-	//Debug << "rendercostdecr: " << weight * renderCostDecrease << " old render cost: " << (1.0f - weight) * normalizedOldRenderCost << endl;
-	return weight * renderCostDecrease + (1.0f - weight) * normalizedOldRenderCost;
+	normalizedOldRenderCost = oldRenderCost / mBox.GetVolume();
+	
+	return renderCostDecrease;
 }
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h	(revision 1142)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h	(revision 1145)
@@ -41,5 +41,6 @@
 
 
-/** Probably Visible Set */
+/** Probably Visible Set 
+*/
 class PrVs 
 {
@@ -379,7 +380,7 @@
 	void SetViewCellsActive();
 
-	/** Evaluates worth of current view cell hierarchy.
-	*/
-	void EvalViewCellPartition(Preprocessor *preprocessor);
+	/** Evaluates render cost statistics of current view cell hierarchy.
+	*/
+	void EvalViewCellPartition();
 
 	/** Sets maximal size of a view cell filter.
@@ -479,4 +480,5 @@
 
 protected:
+
 	/** Exports bounding boxes as xml stream
 	*/
@@ -570,5 +572,6 @@
 	////////////////////////////////////////////////
 
-	/// if bounding boxes should also be exported
+	Preprocessor *mPreprocessor;
+	/// if bounding boxes should be exported together with the view cells
 	bool mExportBboxesForPvs;
 		
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 1144)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 1145)
@@ -21,5 +21,5 @@
 const static bool ADDITIONAL_GEOMETRY_HACK = false;
 
-Preprocessor *preprocessor;
+//Preprocessor *preprocessor;
 
 
@@ -163,9 +163,11 @@
   cout << "done.\n";
  
-#if 0
-  cout << "Deleting vsp osp tree...\n";
-  DEL_PTR(mVspOspTree);
+  cout << "Deleting vsp tree...\n";
+  DEL_PTR(mVspTree);
   cout << "done.\n";
-#endif
+
+  cout << "Deleting osp tree...\n";
+  DEL_PTR(mOspTree);
+  cout << "done.\n";
 
   cout << "Deleting vspbsp tree...\n";
@@ -408,5 +410,6 @@
 		// NOTE: render texture should be power of 2 and square
 		// renderer must be initialised
-		renderer = new GlRendererBuffer(1024, 768, mSceneGraph, mViewCellsManager, mKdTree);
+		// $$matt
+//		renderer = new GlRendererBuffer(1024, 768, mSceneGraph, mViewCellsManager, mKdTree);
 		//		renderer->makeCurrent();
 		
@@ -468,5 +471,5 @@
 
 
-inline bool ilt(Intersectable *obj1, Intersectable *obj2)
+static inline bool ilt(Intersectable *obj1, Intersectable *obj2)
 {
 	return obj1->mId < obj2->mId;
Index: GTP/trunk/Lib/Vis/Preprocessing/src/RssPreprocessor.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/RssPreprocessor.cpp	(revision 1112)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/RssPreprocessor.cpp	(revision 1145)
@@ -484,4 +484,5 @@
 {
   // compute rendering error
+	
   if (renderer && renderer->mPvsStatFrames) {
 	//	emit EvalPvsStat();
@@ -835,8 +836,18 @@
 
 	if (0 && mPass > 0) {
+		char buf[100];
 	  if (mUseImportanceSampling)
-		renderer->mSnapPrefix.sprintf("snap/i-%02d-", mPass);
+	  {
+		sprintf(buf, "snap/i-%02d-", mPass);
+
+		renderer->mSnapPrefix = buf;
+	  }
 	  else
-		renderer->mSnapPrefix.sprintf("snap/r-%02d-", mPass);
+	  {
+		sprintf(buf, "snap/r-%02d-", mPass);
+
+		renderer->mSnapPrefix = buf;
+	  }
+
 	  renderer->mSnapErrorFrames = true;
 	}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VssPreprocessor.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VssPreprocessor.cpp	(revision 1076)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VssPreprocessor.cpp	(revision 1145)
@@ -432,5 +432,6 @@
 	exporter->SetFilled();
 	//Randomize();
-	debuggerWidget = new GlDebuggerWidget(renderer);
+// §§matt
+//	debuggerWidget = new GlDebuggerWidget(renderer);
 
 	/*debuggerWidget->mBeam = beam;
@@ -439,7 +440,7 @@
 	
 	Debug << "showing window" << endl;
-	debuggerWidget->show();*/
-	
-	renderer->makeCurrent();
+	debuggerWidget->show();
+	
+	renderer->makeCurrent();*/
 
 	for (int i = 0; i < 10; ++ i)
@@ -464,6 +465,6 @@
 
 		BeamSampleStatistics stats;
-
-		renderer->SampleBeamContributions(sourceObj,
+// §§matt
+/*		renderer->SampleBeamContributions(sourceObj,
 										  beam,
 										  200000,
@@ -475,5 +476,5 @@
 		image.save(s, "PNG");
 		Debug << "beam statistics: " << stats << endl << endl;
-
+*/
 		if (1)
 		{
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h	(revision 1022)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h	(revision 1145)
@@ -8,5 +8,6 @@
 #include "KdTree.h"
 
-#include <QObject>
+// matt: remove qt dependencies
+//#include <QObject>
 
 namespace GtpVisibilityPreprocessor {
@@ -33,10 +34,12 @@
 */
   
-  /** Main class of the visibility preprocessor. Responsible for loading and
-      saving of the input and output files. Initiates construction of the kD-tree,
-      viewcell loading/generation and the visibility computation itself.
-  */
-class Preprocessor : public QObject {
-  Q_OBJECT
+/** Main class of the visibility preprocessor. Responsible for loading and
+    saving of the input and output files. Initiates construction of the kD-tree,
+    viewcell loading/generation and the visibility computation itself.
+*/
+// matt: remove qt dependencies
+class Preprocessor// : public QObject 
+{
+  //Q_OBJECT
 
 public:
@@ -49,5 +52,5 @@
   /** Load the input scene. 
       @param filename file to load
-	@return true on success
+	  @return true on success
   */
   virtual bool LoadScene(const string filename);
@@ -202,13 +205,11 @@
 
   GlRendererBuffer *renderer;
-  
-  signals:
+// matt: remove qt dependencies 
+//signals:
   void EvalPvsStat();
 
 };
 
-
-
-extern Preprocessor *preprocessor;
+//extern Preprocessor *preprocessor;
 
 }
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.cpp	(revision 1144)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.cpp	(revision 1145)
@@ -103,4 +103,59 @@
 
 
+void OspTreeStatistics::Print(ostream &app) const
+{
+	app << "=========== OspTree statistics ===============\n";
+
+	app << setprecision(4);
+
+	app << "#N_CTIME  ( Construction time [s] )\n" << Time() << " \n";
+
+	app << "#N_NODES ( Number of nodes )\n" << nodes << "\n";
+
+	app << "#N_INTERIORS ( Number of interior nodes )\n" << Interior() << "\n";
+
+	app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n";
+
+	app << "#AXIS_ALIGNED_SPLITS (number of axis aligned splits)\n" << splits[0] + splits[1] + splits[2] << endl;
+
+	app << "#N_SPLITS ( Number of splits in axes x y z)\n";
+
+	for (int i = 0; i < 3; ++ i)
+		app << splits[i] << " ";
+	app << 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_PMINRAYSLEAVES  ( Percentage of leaves with minimal number of rays)\n" 
+	//	<< minRaysNodes * 100 / (double)Leaves() << endl;
+
+	app << "#N_MAXCOSTNODES  ( Percentage of leaves with terminated because of max cost ratio )\n"
+		<< maxCostNodes * 100 / (double)Leaves() << endl;
+
+	app << "#N_PMINPROBABILITYLEAVES  ( Percentage of leaves with mininum probability )\n"
+		<< minProbabilityNodes * 100 / (double)Leaves() << endl;
+
+//	app << "#N_PMAXRAYCONTRIBLEAVES  ( Percentage of leaves with maximal ray contribution )\n" 
+//		<<	maxRayContribNodes * 100 / (double)Leaves() << endl;
+
+	app << "#N_PMAXDEPTH ( Maximal reached depth )\n" << maxDepth << endl;
+
+	app << "#N_PMINDEPTH ( Minimal reached depth )\n" << minDepth << endl;
+
+	app << "#AVGDEPTH ( average depth )\n" << AvgDepth() << endl;
+
+	app << "#N_INVALIDLEAVES (number of invalid leaves )\n" << invalidLeaves << endl;
+
+//	app << "#N_RAYS (number of rays / leaf)\n" << AvgRays() << endl;
+	//app << "#N_PVS: " << pvs << endl;
+
+	app << "========== END OF VspTree statistics ==========\n";
+}
+
+
 /******************************************************************/
 /*                  class VspNode implementation                  */
@@ -471,5 +526,4 @@
 void VspTree::AddSubdivisionStats(const int viewCells,
 								  const float renderCostDecr,
-								  const float splitCandidateCost,
 								  const float totalRenderCost,
 								  const float avgRenderCost)
@@ -478,5 +532,4 @@
 			<< "#ViewCells\n" << viewCells << endl
 			<< "#RenderCostDecrease\n" << renderCostDecr << endl 
-			<< "#SplitCandidateCost\n" << splitCandidateCost << endl
 			<< "#TotalRenderCost\n" << totalRenderCost << endl
 			<< "#AvgRenderCost\n" << avgRenderCost << endl;
@@ -584,9 +637,33 @@
 
 
+void VspTree::EvalSubdivisionStats(const VspTraversalData &tData,
+								   const VspTraversalData &tFrontData,
+								   const VspTraversalData &tBackData
+								   )
+{
+	const float cFront = (float)tFrontData.mPvs * tFrontData.mProbability;
+	const float cBack = (float)tBackData.mPvs * tBackData.mProbability;
+	const float cData = (float)tData.mPvs * tData.mProbability;
+	
+	const float costDecr = 
+		(cFront + cBack - cData) / mBoundingBox.GetVolume();
+
+	mTotalCost += costDecr;
+	mTotalPvsSize += tFrontData.mPvs + tBackData.mPvs - tData.mPvs;
+
+	AddSubdivisionStats(mVspStats.Leaves(),
+						-costDecr,
+						mTotalCost,
+						(float)mTotalPvsSize / (float)mVspStats.Leaves());
+}
+
+
 VspNode *VspTree::Subdivide(SplitQueue &tQueue,
-							VspSplitCandidate &splitCandidate,
+							SplitCandidate *splitCandidate,
 							const bool globalCriteriaMet)
 {
-	VspTraversalData &tData = splitCandidate.mParentData;
+	// doto remove dynamic cast
+	VspSplitCandidate *sc = dynamic_cast<VspSplitCandidate *>(splitCandidate);
+	VspTraversalData &tData = sc->mParentData;
 
 	VspNode *newNode = tData.mNode;
@@ -600,8 +677,8 @@
 		
 		// create new interior node and two leaf node
-		const AxisAlignedPlane splitPlane = splitCandidate.mSplitPlane;
+		const AxisAlignedPlane splitPlane = sc->mSplitPlane;
 		newNode = SubdivideNode(splitPlane, tData, tFrontData, tBackData);
 	
-		const int maxCostMisses = splitCandidate.mMaxCostMisses;
+		const int maxCostMisses = sc->mMaxCostMisses;
 
 
@@ -611,27 +688,9 @@
 			
 	
-		if (1)
-		{
-			//-- subdivision statistics
-
-			const float cFront = (float)tFrontData.mPvs * tFrontData.mProbability;
-			const float cBack = (float)tBackData.mPvs * tBackData.mProbability;
-			const float cData = (float)tData.mPvs * tData.mProbability;
-	
-			const float costDecr = 
-				(cFront + cBack - cData) / mBoundingBox.GetVolume();
-
-			mTotalCost += costDecr;
-			mTotalPvsSize += tFrontData.mPvs + tBackData.mPvs - tData.mPvs;
-
-			AddSubdivisionStats(mVspStats.Leaves(),
-								-costDecr,
-								splitCandidate.GetPriority(),
-								mTotalCost,
-								(float)mTotalPvsSize / (float)mVspStats.Leaves());
-		}
-
-
+		if (1) //-- subdivision statistics
+			EvalSubdivisionStats(tData, tFrontData, tBackData);
+		
 		//-- evaluate new split candidates for global greedy cost heuristics
+
 		VspSplitCandidate *frontCandidate = new VspSplitCandidate(tFrontData);
 		VspSplitCandidate *backCandidate = new VspSplitCandidate(tBackData);
@@ -645,4 +704,5 @@
 		// delete old view cell
 		delete tData.mNode->mViewCell;
+
 		// delete old leaf node
 		DEL_PTR(tData.mNode);
@@ -702,8 +762,28 @@
 		SelectSplitPlane(splitCandidate.mParentData, splitCandidate.mSplitPlane, frontProb, backProb);
 
+	float oldRenderCost;
+
 	// compute global decrease in render cost
-	const float priority = EvalRenderCostDecrease(splitCandidate.mSplitPlane, splitCandidate.mParentData);
+	const float renderCostDecr = EvalRenderCostDecrease(splitCandidate.mSplitPlane, 
+														splitCandidate.mParentData,
+														oldRenderCost);
+
+	splitCandidate.SetRenderCostDecrease(renderCostDecr);
+
+#if 0
+	const float priority = (float)-data.mDepth;
+#else	
+
+	// take render cost of node into account 
+	// otherwise danger of being stuck in a local minimum!!
+	const float factor = mRenderCostDecreaseWeight;
+	const float priority = factor * renderCostDecr + (1.0f - factor) * oldRenderCost;
+#endif
+	
 	splitCandidate.SetPriority(priority);
-	splitCandidate.mMaxCostMisses = success ? splitCandidate.mParentData.mMaxCostMisses : splitCandidate.mParentData.mMaxCostMisses + 1;
+
+	// max cost threshold violated?
+	splitCandidate.mMaxCostMisses = 
+		success ? splitCandidate.mParentData.mMaxCostMisses : splitCandidate.mParentData.mMaxCostMisses + 1;
 	//Debug << "p: " << tData.mNode << " depth: " << tData.mDepth << endl;
 }
@@ -1404,6 +1484,14 @@
 	
 	//if (axis != 1)
-	Debug << "axis=" << axis << " costRatio=" << ratio << " pos=" << position << " t=" << (position - minBox) / (maxBox - minBox)
-	      <<"\t pb=(" << pvsBack << ")\t pf=(" << pvsFront << ")" << endl;
+	//Debug << "axis=" << axis << " costRatio=" << ratio << " pos=" << position << " t=" << (position - minBox) / (maxBox - minBox)
+	//      <<"\t pb=(" << pvsBack << ")\t pf=(" << pvsFront << ")" << endl;
+
+	const float volRatio = tData.mBoundingBox.GetVolume() / (sizeBox * mBoundingBox.GetVolume());
+
+	Debug << "\n§§§§ eval local cost §§§§" << endl
+		  << "back pvs: " << penaltyBack << " front pvs: " << penaltyFront << " total pvs: " << penaltyOld << endl 
+		  << "back p: " << pBack * volRatio << " front p " << pFront * volRatio << " p: " << pOverall * volRatio << endl
+		  << "old rc: " << oldRenderCost * volRatio << " new rc: " << newRenderCost * volRatio << endl
+		  << "render cost decrease: " << oldRenderCost * volRatio - newRenderCost * volRatio << endl;
 
 	return ratio;
@@ -1497,9 +1585,7 @@
 
 float VspTree::EvalRenderCostDecrease(const AxisAlignedPlane &candidatePlane,
-									  const VspTraversalData &data) const
-{
-#if 0
-	return (float)-data.mDepth;
-#endif
+									  const VspTraversalData &data,
+									  float &normalizedOldRenderCost) const
+{
 	float pvsFront = 0;
 	float pvsBack = 0;
@@ -1511,7 +1597,8 @@
 	float pBack = 0;
 
+	const float viewSpaceVol = mBoundingBox.GetVolume();
 
 	// create unique ids for pvs heuristics
-	Intersectable::NewMail();
+	Intersectable::NewMail(3);
 	
 	RayInfoContainer::const_iterator rit, rit_end = data.mRays->end();
@@ -1555,13 +1642,17 @@
 	const float newRenderCost = penaltyFront * pFront + penaltyBack * pBack;
 
+	normalizedOldRenderCost = oldRenderCost / viewSpaceVol;
+
 	//Debug << "decrease: " << oldRenderCost - newRenderCost << endl;
-	const float renderCostDecrease = (oldRenderCost - newRenderCost) / mBoundingBox.GetVolume();
-	
-	// take render cost of node into account 
-	// otherwise danger of being stuck in a local minimum!!
-	const float factor = mRenderCostDecreaseWeight;
-
-	const float normalizedOldRenderCost = oldRenderCost / mBoundingBox.GetVolume();
-	return factor * renderCostDecrease + (1.0f - factor) * normalizedOldRenderCost;
+	const float renderCostDecrease = (oldRenderCost - newRenderCost) / viewSpaceVol;
+	
+	
+	Debug << "\n==== eval render cost decrease ===" << endl
+		  << "back pvs: " << pvsBack << " front pvs " << pvsFront << " total pvs: " << totalPvs << endl 
+		  << "back p: " << pBack / viewSpaceVol << " front p " << pFront / viewSpaceVol << " p: " << pOverall / viewSpaceVol << endl
+		  << "old rc: " << normalizedOldRenderCost << " new rc: " << newRenderCost / viewSpaceVol << endl
+		  << "render cost decrease: " << renderCostDecrease << endl;
+
+	return renderCostDecrease;
 }
 
@@ -1579,5 +1670,5 @@
 	
 	// create unique ids for pvs heuristics
-	Intersectable::NewMail();
+	Intersectable::NewMail(3);
 
 	const int pvsSize = data.mPvs;
@@ -1601,5 +1692,5 @@
 	pOverall = data.mProbability;
 
-	// we take simplified computation for spatial mid split
+	// we use spatial mid split => simplified computation
 	pBack = pFront = pOverall * 0.5f;
 	
@@ -1625,5 +1716,5 @@
 		return;
 
-	//const float renderCost = mViewCellsManager->EvalRenderCost(obj);
+	//const float renderCost = mViewCellsManager->SimpleRay &raynderCost(obj);
 	const int renderCost = 1;
 
@@ -1634,5 +1725,6 @@
 	}
 
-	// TODO: does this really belong to no pvs?
+	// QUESTION matt: is it safe to assume that 
+	// the object belongs to no pvs in this case?
 	//if (cf == Ray::COINCIDENT) return;
 
@@ -2162,5 +2254,5 @@
 
 	Intersectable::NewMail();
-	ViewCell::NewMail();
+	//ViewCell::NewMail();
 
 	Vector3 entp = origin;
@@ -2225,10 +2317,11 @@
 			ViewCell *vc = leaf->GetViewCell();
 
-			if (!vc->Mailed())
-			{
-				vc->Mail();
+			// don't have to mail because each view cell belongs to exactly one leaf
+			//if (!vc->Mailed())
+			//{
+			//	vc->Mail();
 				viewcells.push_back(vc);
 				++ hits;
-			}
+			//}
 #if 0
 			leaf->mRays.push_back(RayInfo(new VssRay(origin, termination, NULL, NULL, 0)));
@@ -2785,5 +2878,5 @@
 	//-- debug output
 
-	Debug << "******* OSP options ******** " << endl;
+	Debug << "******* OSP tree options ******** " << endl;
 
     Debug << "max depth: " << mTermMaxDepth << endl;
@@ -2951,8 +3044,10 @@
 
 KdNode *OspTree::Subdivide(SplitQueue &tQueue,
-						   OspSplitCandidate &splitCandidate,
+						   SplitCandidate *splitCandidate,
 						   const bool globalCriteriaMet)
 {
-	OspTraversalData &tData = splitCandidate.mParentData;
+	OspSplitCandidate *sc = dynamic_cast<OspSplitCandidate *>(splitCandidate);
+	OspTraversalData &tData = sc->mParentData;
+
 	KdNode *newNode = tData.mNode;
 
@@ -2965,5 +3060,5 @@
 		
 		// create new interior node and two leaf node
-		const AxisAlignedPlane splitPlane = splitCandidate.mSplitPlane;
+		const AxisAlignedPlane splitPlane = sc->mSplitPlane;
 		
 		newNode = SubdivideNode(splitPlane, 
@@ -2972,5 +3067,5 @@
 								tBackData);
 	
-		const int maxCostMisses = splitCandidate.mMaxCostMisses;
+		const int maxCostMisses = sc->mMaxCostMisses;
 
 		// how often was max cost ratio missed in this branch?
@@ -3015,5 +3110,23 @@
 		SelectSplitPlane(splitCandidate.mParentData, splitCandidate.mSplitPlane, frontProb, backProb);
 
-	const float priority = EvalRenderCostDecrease(splitCandidate.mSplitPlane, splitCandidate.mParentData);
+	float oldRenderCost;
+
+	// compute global decrease in render cost
+	const float renderCostDecr = EvalRenderCostDecrease(splitCandidate.mSplitPlane, 
+														splitCandidate.mParentData,
+														oldRenderCost);
+
+	splitCandidate.SetRenderCostDecrease(renderCostDecr);
+
+#if 0
+	const float priority = (float)-data.mDepth;
+#else	
+	// take render cost of node into account 
+	// otherwise danger of being stuck in a local minimum!!
+	const float factor = mRenderCostDecreaseWeight;
+	const float priority = factor * renderCostDecr + (1.0f - factor) * oldRenderCost;
+
+#endif
+
 	// compute global decrease in render cost
 	splitCandidate.SetPriority(priority);
@@ -3112,7 +3225,12 @@
 	SortSplitCandidates(tData, axis, minBand, maxBand);
 
-	float totalVol = PrepareHeuristics(tData);
+	int numViewCells;
+
+	float totalVol = PrepareHeuristics(tData, numViewCells);
 	float voll = 0;
 	float volr = totalVol;
+
+	int vcl = 0;
+	int vcr = numViewCells;
   
 	const int totalPvs = tData.mNode->mObjects.size();
@@ -3121,5 +3239,10 @@
 	int pvsr = totalPvs;
 
-	// if no good split can be found, take mid split
+	float sum = (float)totalVol * sizeBox;
+
+	/////////////////////////////////
+
+	// note: initialised to take mid split 
+	// if no good split can be found,
 	position = minBox + 0.5f * sizeBox;
 	
@@ -3127,15 +3250,14 @@
 	float ratio = 99999999.0f;
 	bool splitPlaneFound = false;
-   
-    float minSum = 1e20f;
 
 	float volBack = voll;
 	float volFront = volr;
 
-	int pvsBack = 0;
-	int pvsFront = 0;
-	
-
-	float sum = (float)totalVol * sizeBox;
+	int pvsBack = pvsl;
+	int pvsFront = pvsr;
+	
+	float minSum = 1e20f;
+
+	/////////////////////////////
 
 	Intersectable::NewMail();
@@ -3150,19 +3272,24 @@
 		Intersectable *object = (*ci).mObject;
 
-		EvalHeuristicsContribution(*ci, voll, volr, pvsl, pvsr);
-
-		cout << "incr: " << ci->mObject->mViewCellPvs.GetSize() << " obj id " 
-			 << ci->mObject->GetId() << endl;
+		EvalHeuristicsContribution(tData.mNode, 
+								   *ci, 
+								   voll, volr, 
+								   pvsl, pvsr,
+								   vcl, vcr);
 
 		// Note: sufficient to compare size of bounding boxes of front and back side?
+
 		if (((*ci).mPos >= minBand) && ((*ci).mPos <= maxBand))
 		{
-			//sum = costl * ((*ci).value - minBox) + costr * (maxBox - (*ci).value);
-			sum = voll * pvsBack + volr * pvsFront;
-
-			cout << "pos: " << (*ci).mPos 
-				 << "\t (pvsl: " << pvsBack << ", pvsr: " << pvsFront << ")"
+			sum = voll * pvsl + volr * pvsr;
+
+			// note matt: can happen that volr is less than zero: bug or numerical error?
+			//if (volr < 0) 	Debug << "warning!! " << totalVol << " " << volRightDecr << " " << volRightDecr - totalVol << endl;
+
+			/*Debug << "pos: " << (*ci).mPos 
+				 << "\t (pvsl: " << pvsl << ", pvsr: " << pvsr << ")"
 				 << "\t (voll: " << voll << ", volr: " << volr << ")"
-				 << "\t sum: " << sum << endl;
+				 << "\t (vcl: " << vcl << ", vcr: " << vcr << ", nvc: " << numViewCells << ")"
+				 << "\t sum: " << sum << endl;*/
 
 			if (sum < minSum)
@@ -3193,7 +3320,7 @@
 	const float pFront = volFront;
 
-	const float penaltyOld = (float)totalPvs;//EvalPvsPenalty(pvsSize, lowerPvsLimit, upperPvsLimit);
-    const float penaltyFront = (float)pvsFront;//EvalPvsPenalty(pvsFront, lowerPvsLimit, upperPvsLimit);
-	const float penaltyBack = (float)pvsBack;//EvalPvsPenalty(pvsBack, lowerPvsLimit, upperPvsLimit);
+	const float penaltyOld = (float)totalPvs;
+    const float penaltyFront = (float)pvsFront;
+	const float penaltyBack = (float)pvsBack;
 	
 	const float oldRenderCost = penaltyOld * pOverall + Limits::Small;
@@ -3206,8 +3333,15 @@
 	}
 	
-	//if (axis != 1)
-	Debug << "axis=" << axis << " costRatio=" << ratio << " pos=" 
-		  << position << " t=" << (position - minBox) / (maxBox - minBox)
-	      << "\t pb=(" << volBack << ")\t pf=(" << volFront << ")" << endl;
+	//Debug << "axis=" << axis << " costRatio=" << ratio << " pos=" 
+	//	  << position << " t=" << (position - minBox) / (maxBox - minBox)
+	//      << "\t pb=(" << volBack << ")\t pf=(" << volFront << ")" << endl;
+
+	const float viewSpaceVol = mVspTree->GetBoundingBox().GetVolume();
+
+	Debug << "\n§§§§ eval local cost §§§§" << endl
+		  << "back pvs: " << pvsBack << " front pvs: " << pvsFront << " total pvs: " << totalPvs << endl 
+		  << "back p: " << pBack / viewSpaceVol << " front p " << pFront / viewSpaceVol << " p: " << pOverall / viewSpaceVol << endl
+		  << "old rc: " << oldRenderCost / viewSpaceVol << " new rc: " << newRenderCost / viewSpaceVol << endl
+		  << "render cost decrease: " << oldRenderCost / viewSpaceVol - newRenderCost / viewSpaceVol << endl;
 
 	return ratio;
@@ -3255,5 +3389,5 @@
 		
 		// if hitpoint with object is inside this node
-		if (GetLeaf(ray->mOrigin, ray->mOriginNode) == leaf)
+		if (ray->mOriginObject && (GetLeaf(ray->mOrigin, ray->mOriginNode) == leaf))
 		{
 			pos = ray->mOrigin[axis];
@@ -3267,5 +3401,5 @@
 		}
 
-		if (GetLeaf(ray->mTermination, ray->mTerminationNode) == leaf)
+		if (ray->mTerminationObject && (GetLeaf(ray->mTermination, ray->mTerminationNode) == leaf))
 		{
 			pos = ray->mTermination[axis];
@@ -3274,5 +3408,5 @@
 				SortableEntry(SortableEntry::BOX_INTERSECT, 
 							  pos, 
-							  ray->mOriginObject, 
+							  ray->mTerminationObject, 
 							  ray)
 							  );
@@ -3319,12 +3453,13 @@
 
 
-float OspTree::PrepareHeuristics(const VssRay &ray)
+float OspTree::PrepareHeuristics(const VssRay &ray, int &numViewCells)
 {
 	float vol = 0;
+	numViewCells = 0;
 
 	ViewCellContainer viewCells;
 
 	mVspTree->GetViewCells(ray, viewCells);
-    
+    	
 	ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
 
@@ -3335,8 +3470,13 @@
 		if (!vc->Mailed())
 		{
+			//Debug << "single vol: "<< vc->GetVolume() << endl;
 			vc->Mail();
 			vc->mCounter = 0;
 			vol += vc->GetVolume();
-		}
+			++ numViewCells;
+		}
+		
+		// view cell volume already added => just increase counter
+		++ vc->mCounter;
 	}
 
@@ -3345,10 +3485,11 @@
 
 
-float OspTree::PrepareHeuristics(const OspTraversalData &tData)
+float OspTree::PrepareHeuristics(const OspTraversalData &tData, int &numViewCells)
 {	
+	float vol = 0;
+
 	Intersectable::NewMail();
 	ViewCell::NewMail();
-
-	float vol = 0;
+	numViewCells = 0;
 
 	KdLeaf *leaf = tData.mNode;
@@ -3359,27 +3500,40 @@
 	{
 		VssRay *ray = (*rit).mRay;
+
+		int newViewCells;
 
 		// if hitpoint with one of the objects is inside this node, we
 		// evaluate the volume of the view cells seen by this ray
-		if ((GetLeaf(ray->mOrigin, ray->mOriginNode) == leaf) ||
-			(GetLeaf(ray->mTermination, ray->mTerminationNode) == leaf))
-		{
-            vol += PrepareHeuristics(tData);
-		}
-	}
-
+		if (ray->mOriginObject && (GetLeaf(ray->mOrigin, ray->mOriginNode) == leaf))
+		{
+            vol += PrepareHeuristics(*ray, newViewCells);
+			numViewCells += newViewCells;
+		}
+
+		// count double if both hit points are within the kd node
+		if (ray->mTerminationObject && (GetLeaf(ray->mTermination, ray->mTerminationNode) == leaf))
+		{
+			vol += PrepareHeuristics(*ray, newViewCells);
+			numViewCells += newViewCells;
+		}
+	}
+
+	//Debug << "vol: " << vol << endl;
 	return vol;
 }
 
 
-void OspTree::EvalHeuristicsContribution(const SortableEntry &ci,
+void OspTree::EvalHeuristicsContribution(KdLeaf *leaf,
+										 const SortableEntry &ci,
 										 float &volLeft,
 										 float &volRight,
 										 int &pvsLeft,
-										 int &pvsRight)
+										 int &pvsRight,
+										 int &viewCellsLeft,
+										 int &viewCellsRight)
 {
 	Intersectable *obj = ci.mObject;
 	VssRay *ray = ci.mRay;
-
+	
 	switch (ci.mType) 
 	{
@@ -3395,5 +3549,9 @@
 		// compute volume contribution from view cells
 		case SortableEntry::BOX_INTERSECT:
-			EvalVolumeContribution(*ray, volRight, volLeft);
+				if ((ray->mOriginObject && (GetLeaf(ray->mOrigin, ray->mOriginNode) == leaf)) ||
+					(ray->mTerminationObject && (GetLeaf(ray->mTermination, ray->mTerminationNode) == leaf)))
+				{
+					EvalVolumeContribution(*ray, volLeft, volRight, viewCellsLeft, viewCellsRight);
+				}
 			break;
 		default:
@@ -3406,5 +3564,9 @@
 
 
-void OspTree::EvalVolumeContribution(const VssRay &ray, float &volLeft, float &volRight)
+void OspTree::EvalVolumeContribution(const VssRay &ray, 
+									 float &volLeft, 
+									 float &volRight,
+									 int &viewCellsLeft,
+									 int &viewCellsRight)
 {
 	ViewCellContainer viewCells;
@@ -3413,8 +3575,8 @@
 
 	ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
-
+	
 	for (vit = viewCells.begin(); vit != vit_end; ++ vit)
 	{
-		// view cells comes to left child node
+		// add view cells volume to left child node
 		ViewCell *viewCell = *vit;
 
@@ -3422,12 +3584,16 @@
 		{
 			viewCell->Mail();
+			
 			volLeft += viewCell->GetVolume();
+
+			++ viewCellsLeft;
 		}
 
 		// remove from right child node
-
 		if (-- viewCell->mCounter == 0)
 		{
 			volRight -= viewCell->GetVolume();
+
+			-- viewCellsRight;
 		}
 	}
@@ -3520,16 +3686,85 @@
 	pBack = nProbBack[bestAxis];
 
-	//Debug << "val: " << nCostRatio[bestAxis] << " axis: " << bestAxis << endl;
+	Debug << "val: " << nCostRatio[bestAxis] << " axis: " << bestAxis << endl;
 	return nCostRatio[bestAxis];
 }
 
 
+bool OspTree::EndPointInsideNode(KdLeaf *leaf, 
+								 VssRay &ray, 
+								 bool isTermination) const
+{
+	// test if the leaf where the hitpoint is located is the current leaf
+	if (isTermination)
+	{
+		 return ray.mTerminationObject && (GetLeaf(ray.mTermination, ray.mOriginNode) == leaf);
+	}
+	else
+	{
+		 return ray.mOriginObject && (GetLeaf(ray.mOrigin, ray.mOriginNode) == leaf);
+	}
+}
+
+
+#if TODO
+void OspTree::EvalSubdivisionStats(const VspTraversalData &tData,
+								   const VspTraversalData &tFrontData,
+								   const VspTraversalData &tBackData
+								   )
+{
+	const float cFront = (float)tFrontData.mPvs * tFrontData.mProbability;
+	const float cBack = (float)tBackData.mPvs * tBackData.mProbability;
+	const float cData = (float)tData.mPvs * tData.mProbability;
+	
+	const float costDecr = 
+		(cFront + cBack - cData) / mBoundingBox.GetVolume();
+
+	mTotalCost += costDecr;
+	mTotalPvsSize += tFrontData.mPvs + tBackData.mPvs - tData.mPvs;
+
+	AddSubdivisionStats(mVspStats.Leaves(),
+						-costDecr,
+						sc->GetPriority(),
+						mTotalCost,
+						(float)mTotalPvsSize / (float)mVspStats.Leaves());
+}
+#endif
+
+
+int OspTree::ClassifyRay(VssRay *ray, 
+						 KdLeaf *leaf, 
+						 const AxisAlignedPlane &plane) const
+{
+	const bool originInside = EndPointInsideNode(leaf, *ray, false);
+    const bool terminationInside = EndPointInsideNode(leaf, *ray, true);
+
+	const bool originGt = 
+		ray->mOrigin[plane.mAxis] > plane.mPosition;
+		
+	const bool terminationGt = 
+		ray->mTermination[plane.mAxis] > plane.mPosition;
+
+	// add view cell volume to front volume
+	const bool addToFront = ((originInside && originGt) || (terminationInside && terminationGt));
+
+	// add view cell volume to back volume
+	const bool addToBack = ((originInside && !originGt) || (terminationInside && !terminationGt));
+
+	// classify ray with respect to the child nodes the view cells contribute
+	if (addToFront && addToBack)
+		return 0;
+	else if (addToBack)
+		return -1;
+	else if (addToFront)
+		return 1;
+
+	return -2;
+}
+
+
 float OspTree::EvalRenderCostDecrease(const AxisAlignedPlane &candidatePlane,
-									  const OspTraversalData &tData) const
-{
-#if 0
-	return (float)-tData.mDepth;
-#endif
-
+									  const OspTraversalData &tData,
+									  float &normalizedOldRenderCost) const
+{
 	float pvsFront = 0;
 	float pvsBack = 0;
@@ -3541,5 +3776,7 @@
 	float pBack = 0;
 
-	Intersectable::NewMail();
+	const float viewSpaceVol = mVspTree->GetBoundingBox().GetVolume();
+
+	//Intersectable::NewMail();
 	KdLeaf::NewMail();
 	ViewCell::NewMail();
@@ -3549,4 +3786,5 @@
 
 	// evaluate reverse pvs and view cell volume on left and right cell
+	// note: should I take all leaf objects or rather the objects hit by rays?
 	for (oit = leaf->mObjects.begin(); oit != oit_end; ++ oit)
 	{
@@ -3556,6 +3794,7 @@
 		++ totalPvs;
 
-		cout << "totalpvs " << totalPvs << endl;
-
+		//cout << "totalpvs " << totalPvs << endl;
+
+		// test if box falls in left / right child node
 		if (box.Max(candidatePlane.mAxis) > candidatePlane.mPosition)
 		{
@@ -3569,5 +3808,7 @@
 
 
-	ViewCell::NewMail();
+	// 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);
 	
 	RayInfoContainer::const_iterator rit, rit_end = tData.mRays->end();
@@ -3577,7 +3818,14 @@
 		VssRay *ray = (*rit).mRay;
 
-		// if hitpoint with one of the objects is inside this node
-		if (GetLeaf(ray->mOrigin, ray->mOriginNode) == leaf)
-		{
+		// test if intersection point with one of the objects is inside this node
+		const bool originInside = EndPointInsideNode(leaf, *ray, false);
+        const bool terminationInside = EndPointInsideNode(leaf, *ray, true);
+
+		if (originInside || terminationInside)
+		{
+			// add volume to volumes of left and / or right children
+			// if one of the ray end points is inside
+			const int classification = ClassifyRay(ray, leaf, candidatePlane);
+
 			ViewCellContainer viewCells;		
 			mVspTree->GetViewCells(*ray, viewCells);
@@ -3585,21 +3833,8 @@
 			ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
 
-			// add view cells volume to front	
+			// evaluate view cells volume contribution
 			for (vit = viewCells.begin(); vit != vit_end; ++ vit)
 			{
-				ViewCell *vc = *vit;
-
-				if (!vc->Mailed())
-				{
-					vc->Mail();
-
-					const float vol = vc->GetVolume();
-					pOverall += vol;
-
-					if (ray->mOrigin[candidatePlane.mAxis] > candidatePlane.mPosition)
-						pFront += vol;
-					else
-						pBack += vol;
-				}
+				AddViewCellVolume(*vit, classification, pFront, pBack, pOverall);
 			}
 		}
@@ -3611,17 +3846,16 @@
 	const float newRenderCost = pvsFront * pFront + pvsBack * pBack;
 
-	Debug << "total pvs: " << totalPvs << " p " << pOverall << endl
-		  << "old: " << oldRenderCost << " new: " << newRenderCost << " decrease: " 
-		  << oldRenderCost - newRenderCost << endl;
-
-	// todo matt§§: how to normalize volume??
-	const float renderCostDecrease = (oldRenderCost - newRenderCost);// / mBoundingBox.GetVolume();
-	
-	// take render cost of node into account 
-	// otherwise danger of being stuck in a local minimum!!
-	const float factor = mRenderCostDecreaseWeight;
-
-	const float normalizedOldRenderCost = oldRenderCost;// / mBoundingBox.GetVolume();
-	return factor * renderCostDecrease + (1.0f - factor) * normalizedOldRenderCost;
+	// normalize volume with view space volume
+	const float renderCostDecrease = (oldRenderCost - newRenderCost) / viewSpaceVol;
+
+	Debug << "\n==== eval render cost decrease ===" << endl
+		  << "back pvs: " << pvsBack << " front pvs " << pvsFront << " total pvs: " << totalPvs << endl 
+		  << "back p: " << pBack / viewSpaceVol << " front p " << pFront / viewSpaceVol << " p: " << pOverall / viewSpaceVol << endl
+		  << "old rc: " << oldRenderCost / viewSpaceVol << " new rc: " << newRenderCost / viewSpaceVol << endl
+		  << "render cost decrease: " << renderCostDecrease << endl;
+
+	normalizedOldRenderCost = oldRenderCost / viewSpaceVol;
+
+	return renderCostDecrease;
 }
 
@@ -3741,5 +3975,4 @@
 		}
 	}
-
 }
 
@@ -3961,4 +4194,48 @@
 
 
+void OspTree::AddViewCellVolume(ViewCell *vc,
+								const int cf,
+								float &frontVol,
+								float &backVol,
+								float &totalVol) const
+{
+	//const float renderCost = mViewCellsManager->SimpleRay &raynderCost(obj);
+	const float vol = vc->GetVolume();
+
+	// view cell not found yet => new
+	if (!vc->Mailed() && !vc->Mailed(1) && !vc->Mailed(2))
+	{
+		totalVol += vol;
+	}
+
+	if (cf >= 0) // front volume
+	{
+		if (!vc->Mailed() && !vc->Mailed(2))
+		{
+			frontVol += vol;
+		
+			// already in back volume => in both volumes
+			if (vc->Mailed(1))
+				vc->Mail(2);
+			else
+				vc->Mail();
+		}
+	}
+
+	if (cf <= 0) // back volume
+	{
+		if (!vc->Mailed(1) && !vc->Mailed(2))
+		{
+			backVol += vol;
+		
+			// already in front volume => in both volume
+			if (vc->Mailed())
+				vc->Mail(2);
+			else
+				vc->Mail(1);
+		}
+	}
+}
+
 
 /********************************************************************/
@@ -3989,5 +4266,5 @@
 
 
-SplitCandidate *HierarchyManager::PrepareVsp(const VssRayContainer &sampleRays,
+VspTree::VspSplitCandidate *HierarchyManager::PrepareVsp(const VssRayContainer &sampleRays,
 											 AxisAlignedBox3 *forcedViewSpace,
 											 RayInfoContainer &rays)
@@ -4009,6 +4286,6 @@
 	const int pvsSize = mVspTree.ComputePvsSize(rays);
 	
-	Debug <<  "pvs size: " << pvsSize << endl;
-	Debug <<  "rays size: " << rays.size() << endl;
+	Debug <<  "pvs size: " << (int)pvsSize << endl;
+	Debug <<  "rays size: " << (int)rays.size() << endl;
 
 	//-- prepare view space partition
@@ -4052,5 +4329,5 @@
 
 
-SplitCandidate * HierarchyManager::PrepareOsp(const VssRayContainer &sampleRays,
+OspTree::OspSplitCandidate * HierarchyManager::PrepareOsp(const VssRayContainer &sampleRays,
 											  const ObjectContainer &objects,
 											  AxisAlignedBox3 *forcedObjectSpace,
@@ -4139,50 +4416,66 @@
 	const long startTime = GetTime();	
 	
-	int i = 0;
+	RunConstruction(true);
+
+	cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl;
+
+	mVspTree.mVspStats.Stop();
+}
+
+
+bool HierarchyManager::SubdivideSplitCandidate(SplitCandidate *sc)
+{
+	const bool globalTerminationCriteriaMet = 
+			GlobalTerminationCriteriaMet(sc);
+
+	const bool vspSplit = (sc->Type() == SplitCandidate::VIEW_SPACE);
+
+	if (vspSplit)
+	{
+		mVspTree.Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
+		return true;
+	}
+	else
+	{
+		mOspTree.Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
+		return false;
+	}
+}
+
+
+void HierarchyManager::RunConstruction(const bool repair)
+{
+	int numNodes = 0;
+
 	while (!FinishedConstruction())
 	{
-		mCurrentCandidate = NextSplitCandidate();
-	   
-		const bool globalTerminationCriteriaMet = 
-			GlobalTerminationCriteriaMet(mCurrentCandidate);
-
-		cout << "view cells: " << i ++ << endl;
-
+		SplitCandidate *splitCandidate = NextSplitCandidate();
+	    
+		cout << "nodes: " << ++ numNodes << endl;
+
+		mTotalCost -= splitCandidate->GetRenderCostDecrease();
+
+		//-- subdivide leaf node
+		SubdivideSplitCandidate(splitCandidate);
+		
 		// cost ratio of cost decrease / totalCost
-		const float costRatio = mCurrentCandidate->GetPriority() / mTotalCost;
-		//Debug << "cost ratio: " << costRatio << endl;
+		const float costRatio = splitCandidate->GetRenderCostDecrease() / mTotalCost;
+		
+		Debug << "\n**********" << endl
+			  << "total cost: " << mTotalCost << " render cost decr: " 
+			  << splitCandidate->GetRenderCostDecrease() 
+			  << " cost ratio: " << costRatio << endl << endl;
 
 		if (costRatio < mTermMinGlobalCostRatio)
 			++ mGlobalCostMisses;
-
-		//-- subdivide leaf node
-
-		// we have either a object space or view space split
-		if (mCurrentCandidate->Type() == SplitCandidate::VIEW_SPACE)
-		{
-			VspTree::VspSplitCandidate *sc = 
-				dynamic_cast<VspTree::VspSplitCandidate *>(mCurrentCandidate);
-
-			VspNode *r = mVspTree.Subdivide(mTQueue, *sc, globalTerminationCriteriaMet);
-		}
-		else // object space split
-		{			
-			OspTree::OspSplitCandidate *sc = 
-				dynamic_cast<OspTree::OspSplitCandidate *>(mCurrentCandidate);
-
-			KdNode *r = mOspTree.Subdivide(mTQueue, *sc, globalTerminationCriteriaMet);
-		}
 
 		// reevaluate candidates affected by the split
 		// for view space splits, this would be object space splits
 		// and other way round
-		RepairQueue();
-
-		DEL_PTR(mCurrentCandidate);
-	}
-
-	cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl;
-
-	mVspTree.mVspStats.Stop();
+		if (repair)
+			RepairQueue();
+
+		DEL_PTR(splitCandidate);
+	}
 }
 
@@ -4195,7 +4488,9 @@
 	RayInfoContainer *objectSpaceRays = new RayInfoContainer();
 
+
 	/////////////////////////////////////////////////////////////
 	// view space space partition
 	/////////////////////////////////////////////////////////////
+
 
 	// makes no sense otherwise because only one kd cell available
@@ -4207,6 +4502,8 @@
 	mVspTree.mStoreKdPvs = false;
 
-	SplitCandidate *sc = PrepareVsp(sampleRays, forcedViewSpace, *viewSpaceRays);
-	mTQueue.Push(sc);
+	VspTree::VspSplitCandidate *vsc = 
+		PrepareVsp(sampleRays, forcedViewSpace, *viewSpaceRays);
+	// add to queue
+	mTQueue.Push(vsc);
 
 	long startTime = GetTime();
@@ -4218,81 +4515,50 @@
 	int i = 0;
 
-	while (!FinishedConstruction())
-	{
-		SplitCandidate *splitCandidate = NextSplitCandidate();
-	    
-		const bool globalTerminationCriteriaMet = 
-			GlobalTerminationCriteriaMet(splitCandidate);
-
-		cout << "vsp nodes: " << i ++ << endl;
-
-		// cost ratio of cost decrease / totalCost
-		const float costRatio = splitCandidate->GetPriority() / mTotalCost;
-		//cout << "cost ratio: " << costRatio << endl;
-
-		if (costRatio < mTermMinGlobalCostRatio)
-			++ mGlobalCostMisses;
-
-		//-- subdivide leaf node
-
-		// we have either a object space or view space split
-		VspTree::VspSplitCandidate *sc = 
-			dynamic_cast<VspTree::VspSplitCandidate *>(splitCandidate);
-
-	
-		VspNode *r = mVspTree.Subdivide(mTQueue, *sc, globalTerminationCriteriaMet);
-
-		DEL_PTR(splitCandidate);
-	}
+	// all objects can be seen from everywhere
+	mTotalCost = (float)vsc->mParentData.mPvs;
+
+	const bool repairQueue = false;
+
+	// process view space candidates
+	RunConstruction(repairQueue);
 
 	cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl;
 	mVspTree.mVspStats.Stop();
 	
-	
+
+
 	/////////////////////////////////////////////////////////////
 	// object space partition
 	/////////////////////////////////////////////////////////////
 
-	Debug << "**************** osp construction **************" << endl;
+	Debug << "\n$$$$$$$$$ osp tree construction $$$$$$$$$$\n" << endl;
 	cout << "starting osp contruction ... " << endl;
 
+	// compute first candidate
+	OspTree::OspSplitCandidate *osc =
+		PrepareOsp(sampleRays, objects, forcedViewSpace, *objectSpaceRays);
+
+    mTQueue.Push(osc);
+
+	mOspTree.mOspStats.Reset();
+	mOspTree.mOspStats.Start();
+
 	startTime = GetTime();
 
-	SplitCandidate *osc =
-		PrepareOsp(sampleRays, objects, forcedViewSpace, *objectSpaceRays);
-
-    mTQueue.Push(osc);
-
-
-	i = 0;
-	while (!FinishedConstruction())
-	{
-		SplitCandidate *splitCandidate = NextSplitCandidate();
-	    
-		const bool globalTerminationCriteriaMet = 
-			GlobalTerminationCriteriaMet(splitCandidate);
-
-		// cost ratio of cost decrease / totalCost
-		const float costRatio = splitCandidate->GetPriority() / mTotalCost;
-		
-		//Debug << "cost ratio: " << costRatio << endl;
-		//cout << "kd nodes: " << i ++ << endl;
-
-		if (costRatio < mTermMinGlobalCostRatio)
-			++ mGlobalCostMisses;
-
-		//-- subdivide leaf node
-
-		// object space split
-		OspTree::OspSplitCandidate *sc = 
-			dynamic_cast<OspTree::OspSplitCandidate *>(splitCandidate);
-
-		KdNode *r = mOspTree.Subdivide(mTQueue, *sc, globalTerminationCriteriaMet);
-		
-		DEL_PTR(splitCandidate);
-	}
-	
-	cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl;
-
+	// reset cost
+	// start with one big kd cell - all objects can be seen from everywhere
+	// note: only true for view space = object space
+	mTotalCost = (float)osc->mParentData.mNode->mObjects.size();//(float)sc->mParentData.mPvs;
+
+	Debug << "reseting cost, new total cost: " << mTotalCost << endl;
+
+	// process object space candidates
+	RunConstruction(repairQueue);
+	
+	cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
+
+	mOspTree.mOspStats.Stop();
+
+	// reset parameters
 	mVspTree.mUseKdPvsForHeuristics = savedCountMethod;
 	mVspTree.mStoreKdPvs = savedStoreMethod;
@@ -4304,4 +4570,7 @@
 								  AxisAlignedBox3 *forcedViewSpace)
 {
+	// only view space partition
+	// object kd tree is taken for osp
+
 	mVspTree.mVspStats.Reset();
 	mVspTree.mVspStats.Start();
@@ -4315,33 +4584,6 @@
 
 	long startTime = GetTime();
-	int i = 0;
-
-	while (!FinishedConstruction())
-	{
-		SplitCandidate *splitCandidate = NextSplitCandidate();
-	    
-		const bool globalTerminationCriteriaMet = 
-			GlobalTerminationCriteriaMet(splitCandidate);
-
-		cout << "vsp nodes: " << i ++ << endl;
-		
-		// cost ratio of cost decrease / totalCost
-		const float costRatio = splitCandidate->GetPriority() / mTotalCost;
-		//cout << "cost ratio: " << costRatio << endl;
-
-		if (costRatio < mTermMinGlobalCostRatio)
-			++ mGlobalCostMisses;
-
-		//-- subdivide leaf node
-	
-		// we have either a object space or view space split
-		VspTree::VspSplitCandidate *sc = 
-			dynamic_cast<VspTree::VspSplitCandidate *>(splitCandidate);
-
-	
-		VspNode *r = mVspTree.Subdivide(mTQueue, *sc, globalTerminationCriteriaMet);
-
-		DEL_PTR(splitCandidate);
-	}
+
+	RunConstruction(false);
 
 	cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl;
@@ -4350,5 +4592,5 @@
 
 
-bool HierarchyManager::FinishedConstruction()
+bool HierarchyManager::FinishedConstruction() const
 {
 	return mTQueue.Empty();
Index: GTP/trunk/Lib/Vis/Preprocessing/src/PreprocessorThread.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/PreprocessorThread.cpp	(revision 878)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/PreprocessorThread.cpp	(revision 1145)
@@ -1,4 +1,3 @@
-#include <QApplication>
-
+//#include <QApplication>
 #include "PreprocessorThread.h"
 #include "Camera.h"
@@ -11,50 +10,62 @@
 
 
+// matt: remove qt dependencies
+/*
 PreprocessorThread::PreprocessorThread(Preprocessor *p,
 									   QObject *parent):QThread(parent)
 {
   mPreprocessor = p;
+  
   if (p->mQuitOnFinish)
 	connect(this, SIGNAL(finished()), qApp, SLOT(closeAllWindows(void)));
 }
+*/
 
-void
-PreprocessorThread::Main()
+PreprocessorThread::PreprocessorThread(Preprocessor *p):
+mPreprocessor(p)
 {
-  
-  Camera camera;
-
-  if (0) {
-	// camera.LookAtBox(mPreprocessor->mKdTree->GetBox());
-	 //	camera.LookInBox(mPreprocessor->mKdTree->GetBox());
-	camera.SetPosition(Vector3(3473, 6.778, -1699));
-	camera.SetDirection(Vector3(-0.2432, 0, 0.97));
-	//	camera.SetPosition(Vector3(991.7, 187.8, -271));
-	//	camera.SetDirection(Vector3(0.9, 0, -0.4));
-
-    camera.SnapImage("camera.jpg", mPreprocessor->mKdTree, mPreprocessor->mSceneGraph);
-  } 
-
-  if (0) {
-    camera.LookInBox(mPreprocessor->mKdTree->GetBox());
-    camera.SetPosition(camera.mPosition + Vector3(-250,0,-550));
-    camera.SnapImage("camera2.jpg", mPreprocessor->mKdTree, mPreprocessor->mSceneGraph);
-  }
-
-  if (0) {
-    camera.SetPosition( mPreprocessor->mKdTree->GetBox().Center() - Vector3(0,-100,0) );
-	camera.SetDirection(Vector3(1, 0, 0));
-	camera.SnapImage("camera3.jpg", mPreprocessor->mKdTree, mPreprocessor->mSceneGraph);
-  }
-
-  if (mPreprocessor->mComputeVisibility) {
-    mPreprocessor->ComputeVisibility();
-	//	mPreprocessor->ExportPreprocessedData("scene.vis");
-	mPreprocessor->PostProcessVisibility();
-  }
-  
+}
 
 
-  cerr << "Preprocessor main finished...\n";
+void PreprocessorThread::operator()()
+{
+	Main();
+}
+
+void PreprocessorThread::Main()
+{
+	Camera camera;
+
+	if (0) 
+	{
+		// camera.LookAtBox(mPreprocessor->mKdTree->GetBox());
+		//	camera.LookInBox(mPreprocessor->mKdTree->GetBox());
+		camera.SetPosition(Vector3(3473, 6.778, -1699));
+		camera.SetDirection(Vector3(-0.2432, 0, 0.97));
+		//	camera.SetPosition(Vector3(991.7, 187.8, -271));
+		//	camera.SetDirection(Vector3(0.9, 0, -0.4));
+
+		camera.SnapImage("camera.jpg", mPreprocessor->mKdTree, mPreprocessor->mSceneGraph);
+	} 
+
+	if (0) {
+		camera.LookInBox(mPreprocessor->mKdTree->GetBox());
+		camera.SetPosition(camera.mPosition + Vector3(-250,0,-550));
+		camera.SnapImage("camera2.jpg", mPreprocessor->mKdTree, mPreprocessor->mSceneGraph);
+	}
+
+	if (0) {
+		camera.SetPosition( mPreprocessor->mKdTree->GetBox().Center() - Vector3(0,-100,0) );
+		camera.SetDirection(Vector3(1, 0, 0));
+		camera.SnapImage("camera3.jpg", mPreprocessor->mKdTree, mPreprocessor->mSceneGraph);
+	}
+
+	if (mPreprocessor->mComputeVisibility) {
+		mPreprocessor->ComputeVisibility();
+		//	mPreprocessor->ExportPreprocessedData("scene.vis");
+		mPreprocessor->PostProcessVisibility();
+	}
+
+	cerr << "Preprocessor main finished...\n";
   
 }
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1144)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1145)
@@ -53,5 +53,6 @@
 mMinPvsSize(0), // one means only empty view cells are invalid
 mMaxPvsRatio(1.0),
-mViewCellPvsIsUpdated(false)
+mViewCellPvsIsUpdated(false),
+mPreprocessor(NULL)
 {
 	mViewSpaceBox.Initialize();
@@ -343,10 +344,10 @@
 	SimpleRayContainer simpleRays;
 
-	preprocessor->GenerateRays(samplesPerPass,
+	mPreprocessor->GenerateRays(samplesPerPass,
 							   sampleType,
 							   simpleRays);
 
 	// shoot simple ray and add it to importance samples
-	preprocessor->CastRays(simpleRays, passSamples);
+	mPreprocessor->CastRays(simpleRays, passSamples);
 
 	return (int)passSamples.size();
@@ -390,4 +391,6 @@
 int ViewCellsManager::Construct(Preprocessor *preprocessor, VssRayContainer *outRays)
 {
+	mPreprocessor = preprocessor;
+
 	int numSamples = 0;
 
@@ -544,5 +547,5 @@
 	if (mEvaluateViewCells)
 	{
-		EvalViewCellPartition(preprocessor);
+		EvalViewCellPartition();
 	}
 
@@ -597,5 +600,5 @@
 	int histoMaxVal;
 	Environment::GetSingleton()->GetIntValue("Preprocessor.histogram.maxValue", histoMaxVal);
-	maxRenderCost = max(histoMaxVal, maxRenderCost);
+	maxRenderCost = max((float)histoMaxVal, maxRenderCost);
 
 	
@@ -872,5 +875,5 @@
 
 
-void ViewCellsManager::EvalViewCellPartition(Preprocessor *preprocessor)
+void ViewCellsManager::EvalViewCellPartition()
 {
 	int samplesPerPass;
@@ -895,6 +898,5 @@
 	cout << "reseting pvs ... ";
 		
-
-	bool startFromZero = true;
+	const bool startFromZero = true;
 
 	// reset pvs and start over from zero
@@ -903,6 +905,7 @@
 		mViewCellsTree->ResetPvs();
 	}
-	else // statistics without addidtional samples
-	{
+	else // start from current sampless
+	{
+		// statistics before casting more samples
 		cout << "compute new statistics ... ";
 		sprintf(s, "-%09d-eval.log", castSamples);
@@ -1015,10 +1018,4 @@
 		}
 	}
-
-	// find empty view cells bug
-	if (TEST_EMPTY_VIEW_CELLS)
-	{
-		TestEmptyViewCells(preprocessor->mObjects);
-	}
 }
 
@@ -1030,5 +1027,5 @@
 
 
-// Returns index of the best view cells of the neighborhood
+/// Returns index of the best view cells of the neighborhood
 int GetBestViewCellIdx(ViewCell *root, const ViewCellContainer &neighborhood)
 {
@@ -1070,5 +1067,5 @@
 	
 	case PER_TRIANGLE:
-		{cout << "pertriangle" << endl;
+		{//cout << "pertriangle" << endl;
 			// HACK
 			MeshInstance *mi = dynamic_cast<MeshInstance *>(obj);
@@ -1077,5 +1074,5 @@
 			if (mi->GetMesh())
 			{
-				return mi->GetMesh()->mFaces.size();
+				return (float)mi->GetMesh()->mFaces.size();
 			}
 		}
@@ -1292,6 +1289,6 @@
 	sort(mViewCells.begin(), mViewCells.end(), ViewCell::SmallerPvs);
 
-	int start = mViewCells.size()*minValid;
-	int end = mViewCells.size()*maxValid;
+	int start = mViewCells.size() * minValid;
+	int end = mViewCells.size() * maxValid;
 
 	for (int i = 0; i < mViewCells.size(); ++ i)
@@ -1957,5 +1954,5 @@
 float ViewCellsManager::GetRendercost(ViewCell *viewCell) const
 {
-	return mViewCellsTree->GetPvsSize(viewCell);
+	return (float)mViewCellsTree->GetPvsSize(viewCell);
 }
 
@@ -2449,7 +2446,7 @@
 
 
-/**********************************************************************/
-/*                 BspViewCellsManager implementation                 */
-/**********************************************************************/
+/*******************************************************************/
+/*               BspViewCellsManager implementation                */
+/*******************************************************************/
 
 
@@ -4578,12 +4575,12 @@
 	vector<RenderCostSample> samples;
   
-	if (!preprocessor->GetRenderer())
+	if (!mPreprocessor->GetRenderer())
 		return;
 
-	//start the from point queries
+	//start the view point queries
 	long startTime = GetTime();
 	cout << "starting sampling of render cost ... ";
 	
-	preprocessor->GetRenderer()->SampleRenderCost(numSamples, samples, true);
+	mPreprocessor->GetRenderer()->SampleRenderCost(numSamples, samples, true);
 
 	cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
@@ -4916,4 +4913,5 @@
 	// print subdivision statistics
 	Debug << mVspTree->GetStatistics() << endl;
+	Debug << mOspTree->GetStatistics() << endl;
 
 	// print view cell statistics
@@ -5333,7 +5331,10 @@
 	
 			const int savedColorCode = mColorCode;
+			mColorCode = 0;
 			const int maxPvs = 200;//mOspTree.GetStatistics().maxPvs;
 
 			exporter->ExportOspTree(*mOspTree, mColorCode == 0 ? 0 : maxPvs);
+
+			mColorCode = savedColorCode;
 
 			delete exporter;
Index: GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp	(revision 1141)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp	(revision 1145)
@@ -23,16 +23,13 @@
 namespace GtpVisibilityPreprocessor {
 
-static CGcontext sCgContext = NULL;
-static CGprogram sCgFragmentProgram = NULL;
-static CGprofile sCgFragmentProfile;
-
+
+/*
 GLuint frontDepthMap;
 GLuint backDepthMap;
 
 const int depthMapSize = 512;
-static vector<OcclusionQuery *> sQueries;
-
-GlRendererWidget *rendererWidget = NULL;
-GlDebuggerWidget *debuggerWidget = NULL;
+
+//static vector<OcclusionQuery *> sQueries;
+*/
 
 static bool arbQuerySupport = false;
@@ -101,20 +98,11 @@
 {
   cerr<<"gl renderer destructor..\n";
-  if (sCgFragmentProgram)
-	cgDestroyProgram(sCgFragmentProgram);
-  if (sCgContext)
-	cgDestroyContext(sCgContext);
+ 
+  //CLEAR_CONTAINER(sQueries);
+  CLEAR_CONTAINER(mOcclusionQueries);
+
   cerr<<"done."<<endl;
-   
-  CLEAR_CONTAINER(sQueries);
-  CLEAR_CONTAINER(mOcclusionQueries);
-}
-
-
-static void handleCgError() 
-{
-    Debug << "Cg error: " << cgGetErrorString(cgGetError()) << endl;
-    exit(1);
-}
+}
+
 
 void
@@ -264,5 +252,4 @@
   glEnable(GL_CULL_FACE);
   
-  // HACK!! but using glew keeps crashing for some reason ...
   InitExtensions();
   
@@ -328,128 +315,4 @@
 }
 
-void
-GlRendererWidget::RenderInfo()
-{
-  QString s;
-  int vc = 0;
-  if (mViewCellsManager)
-	vc = mViewCellsManager->GetViewCells().size();
-  int filter = 0;
-  if (mViewCellsManager)
-	filter = mViewCellsManager->GetMaxFilterSize();
-
-  s.sprintf("frame:%04d viewpoint:(%4.1f,%4.1f,%4.1f) dir:(%4.1f,%4.1f,%4.1f) viewcells:%04d filter:%04d pvs:%04d error:%5.5f\%",
-			mFrame,
-			mViewPoint.x,
-			mViewPoint.y,
-			mViewPoint.z,
-			mViewDirection.x,
-			mViewDirection.y,
-			mViewDirection.z,
-			vc,
-
-			filter,
-			mPvsSize,
-			mRenderError*100.0f
-			);
-  
-  glColor3f(0.0f,0.0f,0.0f);
-  renderText(0,20,s);
-  
-  if (mShowRenderCost) {
-	static vector<float> costFunction;
-	static float maxCost = -1;
-	if (costFunction.size()==0) {
-	  ViewCellsTree *tree = mViewCellsManager->GetViewCellsTree();
-	  if (tree) {
-		tree->GetCostFunction(costFunction);
-		maxCost = -1;
-		for (int i=0;  i < costFunction.size(); i++) {
-		  //		  cout<<i<<":"<<costFunction[i]<<" ";
-		  if (costFunction[i] > maxCost)
-			maxCost = costFunction[i];
-		}
-	  }
-	}
-
-	
-	int currentPos = mViewCellsManager->GetViewCells().size();
-	float currentCost=-1;
-
-	if (currentPos < costFunction.size())
-	  currentCost = costFunction[currentPos];
-#if 0	
-	cout<<"costFunction.size()="<<costFunction.size()<<endl;
-	cout<<"CP="<<currentPos<<endl;
-	cout<<"MC="<<maxCost<<endl;
-	cout<<"CC="<<currentCost<<endl;
-#endif
-	if (costFunction.size()) {
-	  glDisable(GL_DEPTH_TEST);
-	  // init ortographic projection
-	  glMatrixMode(GL_PROJECTION);
-	  glPushMatrix();
-	  
-	  glLoadIdentity();
-	  gluOrtho2D(0, 1.0f, 0, 1.0f);
-	  
-	  glTranslatef(0.1f, 0.1f, 0.0f);
-	  glScalef(0.8f, 0.8f, 1.0f);
-	  glMatrixMode(GL_MODELVIEW);
-	  glLoadIdentity();
-	  
-	  glColor3f(1.0f,0,0);
-	  glBegin(GL_LINE_STRIP);
-	  //	  glVertex3f(0,0,0);
-	  
-	  for (int i=0;  i < costFunction.size(); i++) {
-		float x =  i/(float)costFunction.size();
-		float y = costFunction[i]/(maxCost*0.5f);
-		glVertex3f(x,y,0.0f);
-	  }
-	  glEnd();
-	  
-	  glColor3f(1.0f,0,0);
-	  glBegin(GL_LINES);
-	  float x =  currentPos/(float)costFunction.size();
-	  glVertex3f(x,0.0,0.0f);
-	  glVertex3f(x,1.0f,0.0f);
-	  glEnd();
-	  
-	  glColor3f(0.0f,0,0);
-	  // show a grid
-	  glBegin(GL_LINE_LOOP);
-	  glVertex3f(0,0,0.0f);
-	  glVertex3f(1,0,0.0f);
-	  glVertex3f(1,1,0.0f);
-	  glVertex3f(0,1,0.0f);
-	  glEnd();
-
-	  glBegin(GL_LINES);
-	  for (int i=0;  i < 50000 && i < costFunction.size(); i+=10000) {
-		float x =  i/(float)costFunction.size();
-		glVertex3f(x,0.0,0.0f);
-		glVertex3f(x,1.0f,0.0f);
-	  }
-
-	  for (int i=0;  i < maxCost; i+=100) {
-		float y = i/(maxCost*0.5f);
-		glVertex3f(0,y,0.0f);
-		glVertex3f(1,y,0.0f);
-	  }
-
-	  glEnd();
-
-	  
-	  // restore the projection matrix
-	  glMatrixMode(GL_PROJECTION);
-	  glPopMatrix();
-	  glMatrixMode(GL_MODELVIEW);
-	  glEnable(GL_DEPTH_TEST);
-
-	}
-  }
-}
-
 
 void
@@ -477,4 +340,32 @@
 			target.x, target.y, target.z,
 			up.x, up.y, up.z);
+}
+
+void
+GlRenderer::_RenderScene()
+{
+  ObjectContainer::const_iterator oi = mObjects.begin();
+
+  for (; oi != mObjects.end(); oi++)
+	RenderIntersectable(*oi);
+}
+
+bool
+GlRenderer::RenderScene()
+{
+  static int glList = -1;
+  if (mUseGlLists) {
+	if (glList == -1) {
+	  glList = glGenLists(1);
+	  glNewList(glList, GL_COMPILE);
+	  _RenderScene();
+	  glEndList();
+	}
+	glCallList(glList);
+  } else
+	_RenderScene();
+	
+  
+  return true;
 }
 
@@ -507,5 +398,23 @@
 }
 
-//std::ofstream outfile("try_arb.txt");
+
+
+/****************************************************************/
+/*               GlRendererBuffer implementation                */
+/****************************************************************/
+
+
+
+GlRendererBuffer::GlRendererBuffer(SceneGraph *sceneGraph,
+								   ViewCellsManager *viewcells,
+								   KdTree *tree):
+GlRenderer(sceneGraph, viewcells, tree)  
+{
+	mPixelBuffer = NULL;
+
+	// implement width and height in subclasses
+}
+
+
 void
 GlRendererBuffer::EvalQueryWithOcclusionQueries(
@@ -604,138 +513,4 @@
 
 void
-GlRendererBuffer::EvalRenderCostSample(RenderCostSample &sample,
-									   const bool useOcclusionQueries,
-									   const int threshold
-									   )
-{
-	// choose a random view point
-	mViewCellsManager->GetViewPoint(mViewPoint);
-	sample.mPosition = mViewPoint;
-	//cout << "viewpoint: " << mViewPoint << endl;
-
-	// take a render cost sample by rendering a cube
-	Vector3 directions[6];
-
-	directions[0] = Vector3(1,0,0);
-	directions[1] = Vector3(0,1,0);
-	directions[2] = Vector3(0,0,1);
-	directions[3] = Vector3(-1,0,0);
-	directions[4] = Vector3(0,-1,0);
-	directions[5] = Vector3(0,0,-1);
-
-	sample.mVisibleObjects = 0;
-
-	// reset object counters
-	ObjectContainer::const_iterator it, it_end = mObjects.end();
-
-	for (it = mObjects.begin(); it != it_end; ++ it) 
-	{
-		(*it)->mCounter = 0;
-	}
-
-	++ mFrame;
-
-	//glCullFace(GL_FRONT);
-	glCullFace(GL_BACK);
-	glDisable(GL_CULL_FACE);
-	
-
-	// query all 6 directions for a full point sample
-	for (int i = 0; i < 6; ++ i) 
-	{
-		mViewDirection = directions[i];
-		SetupCamera();
-
-		glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
-		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-		//glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);	glDepthMask(GL_TRUE);
-		glDepthFunc(GL_LESS);
-
-		mUseFalseColors = true;
-
-		// the actual scene rendering fills the depth (for occlusion queries)
-		// and the frame buffer (for item buffer)
-		RenderScene();
-
-
-		if (0) 
-		{
-			char filename[256];
-			sprintf(filename, "snap/frame-%04d-%d.png", mFrame, i);
-			QImage im = toImage();
-			im.save(filename, "PNG");
-		}
-         
-		// evaluate the sample
-		if (useOcclusionQueries) 
-		{
-			EvalQueryWithOcclusionQueries();
-		}
-		else 
-		{
-			EvalQueryWithItemBuffer();
-		}
-	}  
-
-	// now evaluate the statistics over that sample
-	// currently only the number of visible objects is taken into account
-	sample.Reset();
-
-	for (it = mObjects.begin(); it != it_end; ++ it) 
-	{
-		Intersectable *obj = *it;
-		if (obj->mCounter >= threshold) 
-		{
-			++ sample.mVisibleObjects;
-			sample.mVisiblePixels += obj->mCounter;
-		}
-	}
-
-	//cout << "RS=" << sample.mVisibleObjects << " ";
-}
-
-
-void
-GlRendererBuffer::SampleRenderCost(const int numSamples,
-								   vector<RenderCostSample> &samples,
-								   const bool useOcclusionQueries,
-								   const int threshold
-								   )
-{
-  makeCurrent();
-
-  if (mPixelBuffer == NULL)
-	  mPixelBuffer = new unsigned int[GetWidth()*GetHeight()];
-  
-  // using 90 degree projection to capture 360 view with 6 samples
-  SetupProjection(GetHeight(), GetHeight(), 90.0f);
-
-  //samples.resize(numSamples);
-  halton.Reset();
-  
-  // the number of queries queried in batch mode
-  const int numQ = 500;
-
-  //const int numQ = (int)mObjects.size();
-  if (useOcclusionQueries)
-  {
-	  cout << "\ngenerating " << numQ << " queries ... ";
-	  OcclusionQuery::GenQueries(mOcclusionQueries, numQ);
-	  cout << "finished" << endl;
-  }
-
-  // sampling queries 
-  for (int i = 0; i < numSamples; ++ i)
-  {
-	  cout << ".";
-	  EvalRenderCostSample(samples[i], useOcclusionQueries, threshold);
-  }
-
-  doneCurrent();
-
-}
-  
-
-void
 GlRendererBuffer::RandomViewPoint()
 { 
@@ -770,1546 +545,3 @@
 
 
-GlRendererBuffer::GlRendererBuffer(const int w,
-								   const int h,
-								   SceneGraph *sceneGraph,
-								   ViewCellsManager *viewcells,
-								   KdTree *tree):
-QGLPixelBuffer(QSize(w, h)), GlRenderer(sceneGraph, viewcells, tree) {
- 
-  Environment::GetSingleton()->GetIntValue("Preprocessor.pvsRenderErrorSamples", mPvsStatFrames);
-  mPvsErrorBuffer.resize(mPvsStatFrames);
-  ClearErrorBuffer();
-
-  mPixelBuffer = NULL;
-  
-  makeCurrent();
-  InitGL();
-  doneCurrent();
-  
-}
-
-float
-GlRendererBuffer::GetPixelError(int &pvsSize)
-{
-  float pErrorPixels = -1.0f;
-  
-  glReadBuffer(GL_BACK);
-  
-  //  mUseFalseColors = true;
-  
-  mUseFalseColors = false;
-  unsigned int pixelCount;
-
-  //static int query = -1;
-  //if (query == -1)
-//	  glGenOcclusionQueriesNV(1, (unsigned int *)&query);
-
-  OcclusionQuery query;
-
-  if (mDetectEmptyViewSpace) {
-	// now check whether any backfacing polygon would pass the depth test
-	SetupCamera();
-	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-	glEnable( GL_CULL_FACE );
-	
-	RenderScene();
-	
-	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-	glDepthMask(GL_FALSE);
-	glDisable( GL_CULL_FACE );
-
-	
-	query.BeginQuery();
-	
-	RenderScene();
-	
-	query.EndQuery();
-	
-	// at this point, if possible, go and do some other computation
-	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-	glDepthMask(GL_TRUE);
-	glEnable( GL_CULL_FACE );
-	
-	// reenable other state
-	pixelCount = query.GetQueryResult();
-	
-	if (pixelCount > 0)
-	  return -1.0f; // backfacing polygon found -> not a valid viewspace sample
-  } else
-	glDisable( GL_CULL_FACE );
-	
-
-  ViewCell *viewcell = NULL;
-  
-  PrVs prvs;
-  
-  mViewCellsManager->SetMaxFilterSize(0);
-  mViewCellsManager->GetPrVS(mViewPoint, prvs, mViewCellsManager->GetFilterWidth());
-  viewcell = prvs.mViewCell;
-  
-  //  ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint);
-  pvsSize = 0;
-  if (viewcell) {
-	SetupCamera();
-	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-	glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
-	
-	// Render PVS
-	std::map<Intersectable *,
-	  PvsData<Intersectable *>,
-	  LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
-
-	pvsSize = viewcell->GetPvs().mEntries.size();
-	
-	for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
-	  Intersectable *object = (*it).first;
-	  RenderIntersectable(object);
-	}
-
-	//	glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
-	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-	mUseFalseColors = true;
-
-	query.BeginQuery();
-
-	SetupCamera();
-
-	RenderScene();
-	
-	query.EndQuery();
-	
-
-	unsigned int pixelCount;
-	// reenable other state
-	pixelCount = query.GetQueryResult();
-	
-	
-	pErrorPixels = ((float)pixelCount)/(GetWidth()*GetHeight());
-	if (mSnapErrorFrames && pErrorPixels > 0.01) {
-	  
-	  char filename[256];
-	  sprintf(filename, "error-frame-%04d-%0.5f.png", mFrame, pErrorPixels);
-	  QImage im = toImage();
-	  im.save(mSnapPrefix + filename, "PNG");
-	  if (1) { //0 && mFrame == 1543) {
-		int x,y;
-		int lastIndex = -1;
-		for (y=0; y < im.height(); y++)
-		  for (x=0; x < im.width(); x++) {
-			QRgb p = im.pixel(x,y);
-			int index = qRed(p) + (qGreen(p)<<8) + (qBlue(p)<<16);
-			if (qGreen(p) != 255 && index!=0) {
-			  if (index != lastIndex) {
-				//				Debug<<"ei="<<index<<" ";
-				lastIndex = index;
-			  }
-			}
-		  }
-	  }
-
-
-	  mUseFalseColors = false;
-	  glPushAttrib(GL_CURRENT_BIT);
-	  glColor3f(0,1,0);
-	  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-	  SetupCamera();
-	  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-	  
-	  // Render PVS
-	  std::map<Intersectable *,
-		PvsData<Intersectable *>,
-		LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
-	  
-	  for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
-		Intersectable *object = (*it).first;
-		RenderIntersectable(object);
-	  }
-
-	  im = toImage();
-	  sprintf(filename, "error-frame-%04d-%0.5f-pvs.png", mFrame, pErrorPixels);
-	  im.save(mSnapPrefix + filename, "PNG");
-	  glPopAttrib();
-	}
-	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-  }
-
-  if (viewcell && mViewCellsManager->GetMaxFilterSize() > 0)
-	mViewCellsManager->DeleteLocalMergeTree(viewcell);
-  
-  return pErrorPixels;
-}
-
-
-void
-GlRendererWidget::SetupProjection(const int w, const int h, const float angle)
-{
-  if (!mTopView)
-	GlRenderer::SetupProjection(w, h, angle);
-  else {
-	glViewport(0, 0, w, h);
-	glMatrixMode(GL_PROJECTION);
-	glLoadIdentity();
-	gluPerspective(50.0, 1.0, 0.1, 20.0*Magnitude(mSceneGraph->GetBox().Diagonal()));
-	glMatrixMode(GL_MODELVIEW);
-  }
-}
-
-void
-GlRendererWidget::RenderPvs()
-{
-  SetupCamera();
-  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-  
-  ViewCell *viewcell = NULL;
-
-  PrVs prvs;
-  
-  if (!mUseFilter) {
-	viewcell = mViewCellsManager->GetViewCell(mViewPoint, true);
-  } else {
-	//  mViewCellsManager->SetMaxFilterSize(1);
-	mViewCellsManager->GetPrVS(mViewPoint, prvs, mViewCellsManager->GetFilterWidth());
-	viewcell = prvs.mViewCell;
-  }
-  
-  if (viewcell) {
-	// copy the pvs so that it can be filtered...
-	ObjectPvs pvs = viewcell->GetPvs();
-
-	if (mUseSpatialFilter) {
-	  mViewCellsManager->ApplySpatialFilter(mKdTree,
-											mSpatialFilterSize*
-											Magnitude(mViewCellsManager->GetViewSpaceBox().Size()),
-											pvs);
-	}
-	
-	
-	// read back the texture
-	std::map<Intersectable *,
-	  PvsData<Intersectable *>,
-	  LtSample<Intersectable *> >::const_iterator it = pvs.mEntries.begin();
-
-	mPvsSize = pvs.mEntries.size();
-	  
-	for (; it != pvs.mEntries.end(); ++ it) {
-	  Intersectable *object = (*it).first;
-	  float visibility = log10((*it).second.mSumPdf + 1)/5.0f;
-	  glColor3f(visibility, 0.0f, 0.0f);
-	  mUseForcedColors = true;
-	  RenderIntersectable(object);
-	  mUseForcedColors = false;
-	}
-
-	if (mRenderFilter) {
-	  mWireFrame = true;
-	  RenderIntersectable(viewcell);
-	  mWireFrame = false;
-	}
-	
-	if (mUseFilter)
-	  mViewCellsManager->DeleteLocalMergeTree(viewcell);
-  } else {
-	ObjectContainer::const_iterator oi = mObjects.begin();
-	for (; oi != mObjects.end(); oi++)
-	  RenderIntersectable(*oi);
-  }
-}
-
-float
-GlRendererWidget::RenderErrors()
-{
-  float pErrorPixels = -1.0f;
-
-  glReadBuffer(GL_BACK);
-  
-  mUseFalseColors = true;
-
-  SetupCamera();
-  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-  
-  double eq[4];
-  eq[0] = mSceneCutPlane.mNormal.x;
-  eq[1] = mSceneCutPlane.mNormal.y;
-  eq[2] = mSceneCutPlane.mNormal.z;
-  eq[3] = mSceneCutPlane.mD;
-  
-  if (mCutScene) {
-	glClipPlane(GL_CLIP_PLANE0, eq);
-    glEnable(GL_CLIP_PLANE0);
-  }
-  
-  if (mDetectEmptyViewSpace) 
-	glEnable( GL_CULL_FACE );
-  else
-	glDisable( GL_CULL_FACE );
-
-  ObjectContainer::const_iterator oi = mObjects.begin();
-  for (; oi != mObjects.end(); oi++)
-	RenderIntersectable(*oi);
-
-  ViewCell *viewcell = NULL;
-
-  QImage im1, im2;
-  QImage diff;
-  
-  if (viewcell) {
-	// read back the texture
-	im1 = grabFrameBuffer(true);
-	
-	RenderPvs();
-
-	// read back the texture
-	im2 = grabFrameBuffer(true);
-	
-	diff = im1;
-	int x, y;
-	int errorPixels = 0;
-	
-	for (y = 0; y < im1.height(); y++)
-	  for (x = 0; x < im1.width(); x++)
-		if (im1.pixel(x, y) == im2.pixel(x, y))
-		  diff.setPixel(x, y, qRgba(0,0,0,0));
-		else {
-		  diff.setPixel(x, y, qRgba(255,128,128,255));
-		  errorPixels++;
-		}
-	pErrorPixels = ((float)errorPixels)/(im1.height()*im1.width());
-  }
-
-  // now render the pvs again
-  SetupCamera();
-  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-  mUseFalseColors = false;
-  
-  oi = mObjects.begin();
-  for (; oi != mObjects.end(); oi++)
-	RenderIntersectable(*oi);
-
-  // now render im1
-  if (viewcell) {
-	if (0 && mTopView) {
-	  mWireFrame = true;
-	  RenderIntersectable(viewcell);
-	  mWireFrame = false;
-	}
-	
-	// init ortographic projection
-	glMatrixMode(GL_PROJECTION);
-	glPushMatrix();
-	
-	glLoadIdentity();
-	gluOrtho2D(0, 1.0f, 0, 1.0f);
-	
-	glMatrixMode(GL_MODELVIEW);
-	glLoadIdentity();
-	
-	bindTexture(diff);
-	
-	glPushAttrib(GL_ENABLE_BIT);
-	glEnable( GL_ALPHA_TEST );
-	glDisable( GL_CULL_FACE );
-	glAlphaFunc( GL_GREATER, 0.5 );
-	
-	glEnable( GL_TEXTURE_2D );
-	glBegin(GL_QUADS);
-	
-	glTexCoord2f(0,0);
-	glVertex3f(0,0,0);
-	
-	glTexCoord2f(1,0);
-	glVertex3f( 1, 0, 0);
-	
-	glTexCoord2f(1,1);
-	glVertex3f( 1, 1, 0);
-	
-	glTexCoord2f(0,1);
-	glVertex3f(0, 1, 0);
-	glEnd();
-	
-	glPopAttrib();
-	
-	// restore the projection matrix
-	glMatrixMode(GL_PROJECTION);
-	glPopMatrix();
-	glMatrixMode(GL_MODELVIEW);
-  }
-
-  glDisable(GL_CLIP_PLANE0);
-  
-  mRenderError = pErrorPixels;
-  return pErrorPixels;
-}
-
-void
-GlRenderer::_RenderScene()
-{
-  ObjectContainer::const_iterator oi = mObjects.begin();
-
-  for (; oi != mObjects.end(); oi++)
-	RenderIntersectable(*oi);
-}
-
-bool
-GlRenderer::RenderScene()
-{
-  static int glList = -1;
-  if (mUseGlLists) {
-	if (glList == -1) {
-	  glList = glGenLists(1);
-	  glNewList(glList, GL_COMPILE);
-	  _RenderScene();
-	  glEndList();
-	}
-	glCallList(glList);
-  } else
-	_RenderScene();
-	
-  
-  return true;
-}
-
-
-void
-GlRendererBuffer::ClearErrorBuffer()
-{
-  for (int i=0; i < mPvsStatFrames; i++) {
-	mPvsErrorBuffer[i].mError = 1.0f;
-  }
-}
-
-
-void
-GlRendererBuffer::EvalPvsStat()
-{
-  mPvsStat.Reset();
-  halton.Reset();
-
-  makeCurrent();
-
-
-  SetupProjection(GetWidth(), GetHeight());
-
-  
-  for (int i=0; i < mPvsStatFrames; i++) {
-	float err;
-	// set frame id for saving the error buffer
-	mFrame = i;
-	RandomViewPoint();
-
-	// atlanta problematic frames: 325 525 691 1543
-#if 0
-	if (mFrame != 325 &&
-		mFrame != 525 &&
-		mFrame != 691 &&
-		mFrame != 1543)
-	  mPvsErrorBuffer[i] = -1;
-	else {
-	  Debug<<"frame ="<<mFrame<<" vp="<<mViewPoint<<" vd="<<mViewDirection<<endl;
-	}
-#endif
-	if (mPvsErrorBuffer[i].mError > 0.0f) {
-	  int pvsSize;
-
-
-	  float error = GetPixelError(pvsSize);
-	  mPvsErrorBuffer[i].mError = error;
-	  mPvsErrorBuffer[i].mPvsSize = pvsSize;
-
-	  emit UpdatePvsErrorItem(i,
-							  mPvsErrorBuffer[i]);
-	  
-	  cout<<"("<<i<<","<<mPvsErrorBuffer[i].mError<<")";
-	  //	  swapBuffers();
-	}
-	
-	err = mPvsErrorBuffer[i].mError;
-	
-	if (err >= 0.0f) {
-	  if (err > mPvsStat.maxError)
-		mPvsStat.maxError = err;
-	  mPvsStat.sumError += err;
-	  mPvsStat.sumPvsSize += mPvsErrorBuffer[i].mPvsSize;
-	  
-	  if (err == 0.0f)
-		mPvsStat.errorFreeFrames++;
-	  mPvsStat.frames++;
-	}
-  }
-
-  glFinish();
-  doneCurrent();
-
-  cout<<endl<<flush;
-  //  mRenderingFinished.wakeAll();
-}
-
-
-
-
-
-void
-GlRendererWidget::mousePressEvent(QMouseEvent *e)
-{
-  int x = e->pos().x();
-  int y = e->pos().y();
-
-  mousePoint.x = x;
-  mousePoint.y = y;
-  
-}
-
-void
-GlRendererWidget::mouseMoveEvent(QMouseEvent *e)
-{
-  float MOVE_SENSITIVITY = Magnitude(mSceneGraph->GetBox().Diagonal())*1e-3;
-  float TURN_SENSITIVITY=0.1f;
-  float TILT_SENSITIVITY=32.0 ;
-  float TURN_ANGLE= M_PI/36.0 ;
-
-  int x = e->pos().x();
-  int y = e->pos().y();
-  
-  if (e->modifiers() & Qt::ControlModifier) {
-	mViewPoint.y += (y-mousePoint.y)*MOVE_SENSITIVITY/2.0;
-	mViewPoint.x += (x-mousePoint.x)*MOVE_SENSITIVITY/2.0;
-  } else {
-	mViewPoint += mViewDirection*((mousePoint.y - y)*MOVE_SENSITIVITY);
-	float adiff = TURN_ANGLE*(x - mousePoint.x)*-TURN_SENSITIVITY;
-	float angle = atan2(mViewDirection.x, mViewDirection.z);
-	mViewDirection.x = sin(angle+adiff);
-	mViewDirection.z = cos(angle+adiff);
-  }
-  
-  mousePoint.x = x;
-  mousePoint.y = y;
-  
-  updateGL();
-}
-
-void
-GlRendererWidget::mouseReleaseEvent(QMouseEvent *)
-{
-
-
-}
-
-void
-GlRendererWidget::resizeGL(int w, int h)
-{
-  SetupProjection(w, h);
-  updateGL();
-}
-
-void
-GlRendererWidget::paintGL()
-{
-  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-  
-  if (!mRenderViewCells) {
-	if (mRenderErrors)
-	  RenderErrors();
-	else
-	  RenderPvs();
-	RenderInfo();
-  } else {
-	RenderViewCells();
-	
-	mWireFrame = true;
-	RenderScene();
-	mWireFrame = false;
-	
-	RenderInfo();
-  }
-
-  mFrame++;
-}
-
-
-void
-GlRendererWidget::SetupCamera()
-{
-  if (!mTopView)
-	GlRenderer::SetupCamera();
-  else {
-	if (0) {
-	  float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*0.05;
-	  Vector3 pos = mViewPoint - dist*Vector3(mViewDirection.x,
-											  -1,
-											  mViewDirection.y);
-	  
-	  Vector3 target = mViewPoint + dist*mViewDirection;
-	  Vector3 up(0,1,0);
-	  
-	  glLoadIdentity();
-	  gluLookAt(pos.x, pos.y, pos.z,
-				target.x, target.y, target.z,
-				up.x, up.y, up.z);
-	} else {
-	  float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*mTopDistance;
-	  Vector3 pos = mViewPoint  + dist*Vector3(0,
-											   1,
-											   0);
-	  
-	  Vector3 target = mViewPoint;
-	  Vector3 up(mViewDirection.x, 0, mViewDirection.z);
-	  
-	  glLoadIdentity();
-	  gluLookAt(pos.x, pos.y, pos.z,
-				target.x, target.y, target.z,
-				up.x, up.y, up.z);
-	  
-	}
-  }
-
-}
-
-void
-GlRendererWidget::keyPressEvent ( QKeyEvent * e )
-{
-  switch (e->key()) {
-  case Qt::Key_T:
-	mTopView = !mTopView;
-	SetupProjection(width(), height());
-	updateGL();
-	break;
-  case Qt::Key_V:
-	mRenderViewCells = !mRenderViewCells;
-	updateGL();
-	break;
-  case Qt::Key_P:
-	// set random viewpoint
-	mViewCellsManager->GetViewPoint(mViewPoint);
-	updateGL();
-	break;
-
-  default:
-	e->ignore();
-	break;
-  }
-}
-
-  
-RendererControlWidget::RendererControlWidget(QWidget * parent, Qt::WFlags f):
-  QWidget(parent, f)
-{
-
-  QVBoxLayout *vl = new QVBoxLayout;
-  setLayout(vl);
-  
-  QWidget *vbox = new QGroupBox("ViewCells", this);
-  layout()->addWidget(vbox);
-  
-  vl = new QVBoxLayout;
-  vbox->setLayout(vl);
-
-  QLabel *label = new QLabel("Granularity");
-  vbox->layout()->addWidget(label);
-
-  QSlider *slider = new QSlider(Qt::Horizontal, vbox);
-  vl->addWidget(slider);
-  slider->show();
-  slider->setRange(1, 10000);
-  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
-  slider->setValue(200);
-
-  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetViewCellGranularity(int)));
-
-  label = new QLabel("Filter size");
-  vbox->layout()->addWidget(label);
-  
-  slider = new QSlider(Qt::Horizontal, vbox);
-  vbox->layout()->addWidget(slider);
-  slider->show();
-  slider->setRange(1, 100);
-  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
-  slider->setValue(3);
-  
-  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetVisibilityFilterSize(int)));
-
-
-  label = new QLabel("Spatial Filter size");
-  vbox->layout()->addWidget(label);
-  
-  slider = new QSlider(Qt::Horizontal, vbox);
-  vbox->layout()->addWidget(slider);
-  slider->show();
-  slider->setRange(1, 100);
-  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
-  slider->setValue(10);
-  
-  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetSpatialFilterSize(int)));
-
-
-
-  QWidget *hbox = new QWidget(vbox);
-  vl->addWidget(hbox);
-  QHBoxLayout *hlayout = new QHBoxLayout;
-  hbox->setLayout(hlayout);
-  
-  QCheckBox *cb = new QCheckBox("Show viewcells", hbox);
-  hlayout->addWidget(cb);
-  cb->setChecked(false);
-  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowViewCells(bool)));
-
-  cb = new QCheckBox("Show render cost", hbox);
-  hlayout->addWidget(cb);
-  cb->setChecked(false);
-  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowRenderCost(bool)));
-
-  cb = new QCheckBox("Show pvs sizes", hbox);
-  hlayout->addWidget(cb);
-  cb->setChecked(false);
-  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowPvsSizes(bool)));
-
-  vbox->resize(800,100);
-
-  
-  vbox = new QGroupBox("Rendering", this);
-  layout()->addWidget(vbox);
-  
-  vl = new QVBoxLayout;
-  vbox->setLayout(vl);
-
-
-
-  slider = new QSlider(Qt::Horizontal, vbox);
-  vbox->layout()->addWidget(slider);
-  slider->show();
-  slider->setRange(0, 1000);
-  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
-  slider->setValue(1000);
-
-  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetSceneCut(int)));
-
-  cb = new QCheckBox("Render errors", vbox);
-  vbox->layout()->addWidget(cb);
-  cb->setChecked(false);
-  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetRenderErrors(bool)));
-
-  cb = new QCheckBox("Use filter", vbox);
-  vbox->layout()->addWidget(cb);
-  cb->setChecked(true);
-  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetUseFilter(bool)));
-
-  cb = new QCheckBox("Use spatial filter", vbox);
-  vbox->layout()->addWidget(cb);
-  cb->setChecked(true);
-  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetUseSpatialFilter(bool)));
-
-  cb = new QCheckBox("Render filter", vbox);
-  vbox->layout()->addWidget(cb);
-  cb->setChecked(true);
-  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetRenderFilter(bool)));
-
-
-  cb = new QCheckBox("Cut view cells", vbox);
-  vbox->layout()->addWidget(cb);
-  cb->setChecked(false);
-  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetCutViewCells(bool)));
-
-  cb = new QCheckBox("Cut scene", vbox);
-  vbox->layout()->addWidget(cb);
-  cb->setChecked(false);
-  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetCutScene(bool)));
-
-  
-  slider = new QSlider(Qt::Horizontal, vbox);
-  vbox->layout()->addWidget(slider);
-  slider->show();
-  slider->setRange(1, 1000);
-  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
-  slider->setValue(500);
-  
-  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetTopDistance(int)));
-  
-  cb = new QCheckBox("Top View", vbox);
-  vbox->layout()->addWidget(cb);
-  cb->setChecked(false);
-  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetTopView(bool)));
-
-  vbox = new QGroupBox("PVS Errors", this);
-  layout()->addWidget(vbox);
-
-  vl = new QVBoxLayout;
-  vbox->setLayout(vl);
-
-  mPvsErrorWidget = new QListWidget(vbox);
-  vbox->layout()->addWidget(mPvsErrorWidget);
-  
-  connect(mPvsErrorWidget,
-  		  SIGNAL(doubleClicked(const QModelIndex &)),
-  		  this,
-  		  SLOT(PvsErrorClicked(const QModelIndex &)));
-  
-  QPushButton *button = new QPushButton("Next Error Frame", vbox);
-  vbox->layout()->addWidget(button);
-  connect(button, SIGNAL(clicked(void)), SLOT(FocusNextPvsErrorFrame(void)));
-
-  setWindowTitle("Preprocessor Control Widget");
-  adjustSize();
-}
-
-
-
-void
-RendererControlWidget::FocusNextPvsErrorFrame(void)
-{
-  
-  
-}
-
-void
-RendererControlWidget::UpdatePvsErrorItem(int row,
-										  GlRendererBuffer::PvsErrorEntry &pvsErrorEntry)
-{
-
-  QListWidgetItem *i = mPvsErrorWidget->item(row);
-  QString s;
-  s.sprintf("%5.5f", pvsErrorEntry.mError);
-  if (i) {
-	i->setText(s);
-  } else {
-	new QListWidgetItem(s, mPvsErrorWidget);
-  }
-  mPvsErrorWidget->update();
-}
-
-GlRendererWidget::GlRendererWidget(SceneGraph *sceneGraph,
-								   ViewCellsManager *viewcells,
-								   KdTree *tree,
-								   QWidget * parent,
-								   const QGLWidget * shareWidget,
-								   Qt::WFlags f
-								   )
-  :
-  GlRenderer(sceneGraph, viewcells, tree), QGLWidget(parent, shareWidget, f)
-{
-  mTopView = false;
-  mRenderViewCells = false;
-  mTopDistance = 1.0f;
-  mCutViewCells = false;
-  mCutScene = false;
-  mRenderErrors = false;
-  mRenderFilter = true;
-
-  bool tmp;
-
-  Environment::GetSingleton()->GetBoolValue("Preprocessor.applyVisibilityFilter", tmp );
-  mUseFilter = tmp;
-  
-  Environment::GetSingleton()->GetBoolValue("Preprocessor.applyVisibilitySpatialFilter",
-							tmp );
-
-  mUseSpatialFilter = tmp;
-
-  mShowRenderCost = false;
-  mShowPvsSizes = false;
-  mSpatialFilterSize = 0.01;
-  mPvsSize = 0;
-  mRenderError = 0.0f;
-  mControlWidget = new RendererControlWidget(NULL);
-  
-  connect(mControlWidget, SIGNAL(SetViewCellGranularity(int)), this, SLOT(SetViewCellGranularity(int)));
-  connect(mControlWidget, SIGNAL(SetSceneCut(int)), this, SLOT(SetSceneCut(int)));
-  connect(mControlWidget, SIGNAL(SetTopDistance(int)), this, SLOT(SetTopDistance(int)));
-
-  connect(mControlWidget, SIGNAL(SetVisibilityFilterSize(int)), this, SLOT(SetVisibilityFilterSize(int)));
-  connect(mControlWidget, SIGNAL(SetSpatialFilterSize(int)), this, SLOT(SetSpatialFilterSize(int)));
-
-  connect(mControlWidget, SIGNAL(SetShowViewCells(bool)), this, SLOT(SetShowViewCells(bool)));
-  connect(mControlWidget, SIGNAL(SetShowRenderCost(bool)), this, SLOT(SetShowRenderCost(bool)));
-  connect(mControlWidget, SIGNAL(SetShowPvsSizes(bool)), this, SLOT(SetShowPvsSizes(bool)));
-  connect(mControlWidget, SIGNAL(SetTopView(bool)), this, SLOT(SetTopView(bool)));
-  connect(mControlWidget, SIGNAL(SetCutViewCells(bool)), this, SLOT(SetCutViewCells(bool)));
-  connect(mControlWidget, SIGNAL(SetCutScene(bool)), this, SLOT(SetCutScene(bool)));
-  connect(mControlWidget, SIGNAL(SetRenderErrors(bool)), this, SLOT(SetRenderErrors(bool)));
-  connect(mControlWidget, SIGNAL(SetRenderFilter(bool)), this, SLOT(SetRenderFilter(bool)));
-  connect(mControlWidget, SIGNAL(SetUseFilter(bool)), this, SLOT(SetUseFilter(bool)));
-  connect(mControlWidget, SIGNAL(SetUseSpatialFilter(bool)),
-		  this, SLOT(SetUseSpatialFilter(bool)));
-
-  
-  mControlWidget->show();
-}
-
-void
-GlRendererWidget::SetViewCellGranularity(int number)
-{
-  if (mViewCellsManager) 
-	//  	mViewCellsManager->SetMaxFilterSize(number);
-    mViewCellsManager->CollectViewCells(number);
-
-  updateGL();
-}
-
-void
-GlRendererWidget::SetVisibilityFilterSize(int number)
-{
-  if (mViewCellsManager) 
-  	mViewCellsManager->SetMaxFilterSize(number);
-  updateGL();
-}
-
-void
-GlRendererWidget::SetSpatialFilterSize(int number)
-{
-  mSpatialFilterSize = 1e-3*number;
-  updateGL();
-}
-
-void
-GlRendererWidget::SetSceneCut(int number)
-{
-  // assume the cut plane can only be aligned with xz plane
-  // shift it along y according to number, which is percentage of the bounding
-  // box position
-  if (mViewCellsManager) {
-	AxisAlignedBox3 box = mViewCellsManager->GetViewSpaceBox();
-	Vector3 p = box.Min() + (number/1000.0f)*box.Max();
-	mSceneCutPlane.mNormal = Vector3(0,-1,0);
-	mSceneCutPlane.mD = -DotProd(mSceneCutPlane.mNormal, p);
-	updateGL();
-  }
-}
-
-void
-GlRendererWidget::SetTopDistance(int number)
-{
-  mTopDistance = number/1000.0f;
-  updateGL();
-}
-
-void
-GlRendererWidget::RenderViewCells()
-{
-  mUseFalseColors = true;
-
-  SetupCamera();
-  glEnable(GL_CULL_FACE);
-  //glDisable(GL_CULL_FACE);
-  glCullFace(GL_FRONT);
-  double eq[4];
-  eq[0] = mSceneCutPlane.mNormal.x;
-  eq[1] = mSceneCutPlane.mNormal.y;
-  eq[2] = mSceneCutPlane.mNormal.z;
-  eq[3] = mSceneCutPlane.mD;
-
-  if (mCutViewCells) {
-	glClipPlane(GL_CLIP_PLANE0, eq);
-	glEnable(GL_CLIP_PLANE0);
-  }
-  
-  int i;
-  ViewCellContainer &viewcells = mViewCellsManager->GetViewCells();
-  int maxPvs = -1;
-  for (i=0; i < viewcells.size(); i++) 
-  {
-	ViewCell *vc = viewcells[i];
-	const int p = vc->GetPvs().CountPvs();
-	if (p > maxPvs)
-	  maxPvs = p;
-  }
-
-
-  for (i=0; i < viewcells.size(); i++) {
-	ViewCell *vc = viewcells[i];
-	//	Mesh *m = vc->GetMesh();
-
-
-	RgbColor c;
-
-	if (!mShowPvsSizes) 
-	  c = vc->GetColor();
-	else {
-	  const float importance = (float)vc->GetPvs().CountPvs() / (float)maxPvs;
-	  c = RgbColor(importance, 1.0f - importance, 0.0f);
-	}
-	glColor3f(c.r, c.g, c.b);
-	
-	RenderViewCell(vc);
-  }
-
-  glDisable(GL_CLIP_PLANE0);
-
-}
-
-void GlRendererBuffer::SampleBeamContributions(Intersectable *sourceObject,
-											   Beam &beam,
-											   const int desiredSamples,
-											   BeamSampleStatistics &stat)
-{
-	// TODO: should be moved out of here (not to be done every time)
-	// only back faces are interesting for the depth pass
-	glShadeModel(GL_FLAT);
-	glDisable(GL_LIGHTING);
-
-	// needed to kill the fragments for the front buffer
-	glEnable(GL_ALPHA_TEST);
-	glAlphaFunc(GL_GREATER, 0);
-
-	// assumes that the beam is constructed and contains kd-tree nodes
-	// and viewcells which it intersects
-  
-  
-	// Get the number of viewpoints to be sampled
-	// Now it is a sqrt but in general a wiser decision could be made.
-	// The less viewpoints the better for rendering performance, since less passes
-	// over the beam is needed.
-	// The viewpoints could actually be generated outside of the bounding box which
-	// would distribute the 'efective viewpoints' of the object surface and thus
-	// with a few viewpoints better sample the viewpoint space....
-
-	//TODO: comment in
-	//int viewPointSamples = sqrt((float)desiredSamples);
-	int viewPointSamples = max(desiredSamples / (GetWidth() * GetHeight()), 1);
-	
-	// the number of direction samples per pass is given by the number of viewpoints
-	int directionalSamples = desiredSamples / viewPointSamples;
-	
-	Debug << "directional samples: " << directionalSamples << endl;
-	for (int i = 0; i < viewPointSamples; ++ i) 
-	{
-		Vector3 viewPoint = beam.mBox.GetRandomPoint();
-		
-		// perhaps the viewpoint should be shifted back a little bit so that it always lies
-		// inside the source object
-		// 'ideally' the viewpoints would be distributed on the soureObject surface, but this
-        // would require more complicated sampling (perhaps hierarchical rejection sampling of
-		// the object surface is an option here - only the mesh faces which are inside the box
-		// are considered as candidates) 
-		
-		SampleViewpointContributions(sourceObject,
-									 viewPoint,
-									 beam,
-									 directionalSamples,
-									 stat);
-	}
-
-
-	// note:
-	// this routine would be called only if the number of desired samples is sufficiently
-	// large - for other rss tree cells the cpu based sampling is perhaps more efficient
-	// distributing the work between cpu and gpu would also allow us to place more sophisticated
-	// sample distributions (silhouette ones) using the cpu and the jittered once on the GPU
-	// in order that thios scheme is working well the gpu render buffer should run in a separate
-	// thread than the cpu sampler, which would not be such a big problem....
-
-	// disable alpha test again
-	glDisable(GL_ALPHA_TEST);
-}
-
-
-void GlRendererBuffer::SampleViewpointContributions(Intersectable *sourceObject,
-													const Vector3 viewPoint,
-													Beam &beam,
-													const int samples,
-                                                    BeamSampleStatistics &stat)
-{
-    // 1. setup the view port to match the desired samples
-	glViewport(0, 0, samples, samples);
-
-	// 2. setup the projection matrix and view matrix to match the viewpoint + beam.mDirBox
-	SetupProjectionForViewPoint(viewPoint, beam, sourceObject);
-
-
-	// 3. reset z-buffer to 0 and render the source object for the beam
-	//    with glCullFace(Enabled) and glFrontFace(GL_CW)
-	//    save result to the front depth map
-	//    the front depth map holds ray origins
-
-
-	// front depth buffer must be initialised to 0
-	float clearDepth;
-	
-	glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth);
-	glClearDepth(0.0f);
-	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-
-
-	//glFrontFace(GL_CW);
-	glEnable(GL_CULL_FACE);
-	glCullFace(GL_FRONT);
-	glColorMask(0, 0, 0, 0);
-	
-
-	// stencil is increased where the source object is located
-	glEnable(GL_STENCIL_TEST);	
-	glStencilFunc(GL_ALWAYS, 0x1, 0x1);
-	glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
-
-
-#if 0
-	static int glSourceObjList = -1;	 
-	if (glSourceObjList != -1) 
-	{
-		glSourceObjList = glGenLists(1);
-		glNewList(glSourceObjList, GL_COMPILE);
-
-		RenderIntersectable(sourceObject);
-	
-		glEndList();
-	}
-	glCallList(glSourceObjList);
-
-#else
-	RenderIntersectable(sourceObject);
-
-#endif	
-
-	 // copy contents of the front depth buffer into depth texture
-	glBindTexture(GL_TEXTURE_2D, frontDepthMap);	
-	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
-
-
-	// reset clear function
-	glClearDepth(clearDepth);
-
-	
-	
-	// 4. set up the termination depth buffer (= standard depth buffer)
-	//    only rays which have non-zero entry in the origin buffer are valid since
-	//    they realy start on the object surface (this is tagged by setting a
-	//    stencil buffer bit at step 3).
-	
-	glStencilFunc(GL_EQUAL, 0x1, 0x1);
-	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-
-	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-	glDepthMask(1);
-
-	glEnable(GL_DEPTH_TEST);
-		
-	glEnable(GL_CULL_FACE);
-	glCullFace(GL_BACK);
-
-	// setup front depth buffer
-	glEnable(GL_TEXTURE_2D);
-	
-	// bind pixel shader implementing the front depth buffer functionality
-	cgGLBindProgram(sCgFragmentProgram);
-	cgGLEnableProfile(sCgFragmentProfile);
-
-
-	// 5. render all objects inside the beam 
-	//    we can use id based false color to read them back for gaining the pvs
-
-	glColorMask(1, 1, 1, 1);
-
-	
-	// if objects not stored in beam => extract objects
-	if (beam.mFlags & !Beam::STORE_OBJECTS)
-	{
-		vector<KdNode *>::const_iterator it, it_end = beam.mKdNodes.end();
-
-		Intersectable::NewMail();
-		for (it = beam.mKdNodes.begin(); it != it_end; ++ it)
-		{
-			mKdTree->CollectObjects(*it, beam.mObjects);
-		}
-	}
-
-
-	//    (objects can be compiled to a gl list now so that subsequent rendering for
-	//    this beam is fast - the same hold for step 3)
-	//    Afterwards we have two depth buffers defining the ray origin and termination
-	
-
-#if 0
-	static int glObjList = -1; 
-	if (glObjList != -1) 
-	{
-		glObjList = glGenLists(1);
-		glNewList(glObjList, GL_COMPILE);
-	
-		ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
-		for (it = beam.mObjects.begin(); it != it_end; ++ it)
-		{
-			// render all objects except the source object
-			if (*it != sourceObject)
-				RenderIntersectable(*it);
-		}
-		
-		glEndList();
-	}
-
-	glCallList(glObjList);
-#else
-	ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
-	for (it = beam.mObjects.begin(); it != it_end; ++ it)
-	{	
-		// render all objects except the source object
-		if (*it != sourceObject)
-			RenderIntersectable(*it);
-	}
-#endif
-	
-   
-
-	// 6. Use occlusion queries for all viewcell meshes associated with the beam ->
-	//     a fragment passes if the corresponding stencil fragment is set and its depth is
-	//     between origin and termination buffer
-
-	// create new queries if necessary
-	OcclusionQuery::GenQueries(sQueries, (int)beam.mViewCells.size());
-
-	// check whether any backfacing polygon would pass the depth test?
-	// matt: should check both back /front facing because of dual depth buffer
-	// and danger of cutting the near plane with front facing polys.
-	
-	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-	glDepthMask(GL_FALSE);
-	glDisable(GL_CULL_FACE);
-
-  
-	ViewCellContainer::const_iterator vit, vit_end = beam.mViewCells.end();
-
-	int queryIdx = 0;
-
-	for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
-	{
-		sQueries[queryIdx ++]->BeginQuery();
-
-		RenderIntersectable(*vit);
-		
-		sQueries[queryIdx]->EndQuery();
-
-		++ queryIdx;
-	}
-
-
-
-	// at this point, if possible, go and do some other computation
-
-
-	
-	// 7. The number of visible pixels is the number of sample rays which see the source
-	//    object from the corresponding viewcell -> remember these values for later update
-	//   of the viewcell pvs - or update immediately?
-
-	queryIdx = 0;
-
-	for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
-	{
-		// fetch queries
-		unsigned int pixelCount = sQueries[queryIdx ++]->GetQueryResult();
-
-		if (pixelCount)
-			Debug << "view cell " << (*vit)->GetId() << " visible pixels: " << pixelCount << endl;
-	}
-	
-
-	// 8. Copmpute rendering statistics
-	// In general it is not neccessary to remember to extract all the rays cast. I hope it
-	// would be sufficient to gain only the intergral statistics about the new contributions
-	// and so the rss tree would actually store no new rays (only the initial ones)
-	// the subdivision of the tree would only be driven by the statistics (the glrender could
-	// evaluate the contribution entropy for example)
-	// However might be an option to extract/store only those the rays which made a contribution
-	// (new viewcell has been discovered) or relative contribution greater than a threshold ... 
-
-	ObjectContainer pvsObj;
-	stat.pvsSize = ComputePvs(beam.mObjects, pvsObj);
-	
-	// to gain ray source and termination
-	// copy contents of ray termination buffer into depth texture
-	// and compare with ray source buffer
-#if 0
-	VssRayContainer rays;
-
-	glBindTexture(GL_TEXTURE_2D, backDepthMap);	
-	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
-
-	ComputeRays(Intersectable *sourceObj, rays);
-
-#endif
-
-
-
-	//-- cleanup
-
-
-	// reset gl state
-	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-	glDepthMask(GL_TRUE);
-	glEnable(GL_CULL_FACE);
-	glDisable(GL_STENCIL_TEST);
-	cgGLDisableProfile(sCgFragmentProfile);
-	glDisable(GL_TEXTURE_2D);
-
-	// remove objects from beam
-	if (beam.mFlags & !Beam::STORE_OBJECTS)
-		beam.mObjects.clear();
-}
-
-
-void GlRendererBuffer::SetupProjectionForViewPoint(const Vector3 &viewPoint, 
-												   const Beam &beam, 
-												   Intersectable *sourceObject)
-{
-	float left, right, bottom, top, znear, zfar;
-
-	beam.ComputePerspectiveFrustum(left, right, bottom, top, znear, zfar,
-								   mSceneGraph->GetBox());
-
-	//Debug << left << " " << right << " " << bottom << " " << top << " " << znear << " " << zfar << endl;
-	glMatrixMode(GL_PROJECTION);
-	glLoadIdentity();
-	glFrustum(left, right, bottom, top, znear, zfar);
-	//glFrustum(-1, 1, -1, 1, 1, 20000);
-
-    const Vector3 center = viewPoint + beam.GetMainDirection() * (zfar - znear) * 0.3f;
-	const Vector3 up = 
-		Normalize(CrossProd(beam.mPlanes[0].mNormal, beam.mPlanes[4].mNormal));
-
-#ifdef _DEBUG
-	Debug << "view point: " << viewPoint << endl;
-	Debug << "eye: " << center << endl;
-	Debug << "up: " << up << endl;
-#endif
-
-	glMatrixMode(GL_MODELVIEW);
-	glLoadIdentity();
-	gluLookAt(viewPoint.x, viewPoint.y, viewPoint.z, 
-			  center.x, center.y, center.z,			  
-			  up.x, up.y, up.z);
-}		
-
-  
-void GlRendererBuffer::InitGL()
-{
- makeCurrent(); 
- GlRenderer::InitGL();
-
-#if 1
-	// initialise dual depth buffer textures
-	glGenTextures(1, &frontDepthMap);
-	glBindTexture(GL_TEXTURE_2D, frontDepthMap);
-	
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize, 
-		depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
-
-	glGenTextures(1, &backDepthMap);
-	glBindTexture(GL_TEXTURE_2D, backDepthMap);
-	
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize, 
-		depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
-
-	// cg initialization
-	cgSetErrorCallback(handleCgError);
-	sCgContext = cgCreateContext();
-	
-	if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1))
-		sCgFragmentProfile = CG_PROFILE_ARBFP1;
-	else 
-	{
-	  // try FP30
-	  if (cgGLIsProfileSupported(CG_PROFILE_FP30))
-            sCgFragmentProfile = CG_PROFILE_FP30;
-	  else 
-	  {
-		  Debug << "Neither arbfp1 or fp30 fragment profiles supported on this system" << endl;
-		  exit(1);
-	  }
-  }
-
-
- sCgFragmentProgram = cgCreateProgramFromFile(sCgContext,
-											   CG_SOURCE, "../src/dual_depth.cg",
-											   sCgFragmentProfile,
-											   NULL, 
-											   NULL);
-
-  if (!cgIsProgramCompiled(sCgFragmentProgram))
-	  cgCompileProgram(sCgFragmentProgram);
-
-  cgGLLoadProgram(sCgFragmentProgram);
-  cgGLBindProgram(sCgFragmentProgram);
-
-  Debug << "---- PROGRAM BEGIN ----\n" <<
-	  cgGetProgramString(sCgFragmentProgram, CG_COMPILED_PROGRAM) << "---- PROGRAM END ----\n";
-
-#endif
-  doneCurrent();
-}
-
-
-void GlRendererBuffer::ComputeRays(Intersectable *sourceObj, VssRayContainer &rays)
-{
-	for (int i = 0; i < depthMapSize * depthMapSize; ++ i)
-	{
-		//todo glGetTexImage()
-	}
-}
-
-
-
-inline bool ilt(Intersectable *obj1, Intersectable *obj2)
-{
-	return obj1->mId < obj2->mId;
-}
-
-
-int GlRendererBuffer::ComputePvs(ObjectContainer &objects, 
-								 ObjectContainer &pvs) const
-{
-	int pvsSize = 0;
-	QImage image = toImage();
-	Intersectable::NewMail();
-
-	std::stable_sort(objects.begin(), objects.end(), ilt);
-
-	MeshInstance dummy(NULL);
-
-	Intersectable *obj = NULL;
-			
-	for (int x = 0; x < image.width(); ++ x)
-	{
-		for (int y = 0; y < image.height(); ++ y)
-		{
-			QRgb pix = image.pixel(x, y);
-			const int id = GetId(qRed(pix), qGreen(pix), qBlue(pix));
-
-			dummy.SetId(id);
-
-			ObjectContainer::iterator oit =
-				lower_bound(objects.begin(), objects.end(), &dummy, ilt);
-			
-			
-			if (//(oit != oit.end()) && 
-				((*oit)->GetId() == id) && 
-				!obj->Mailed())
-			{
-				obj = *oit;
-				obj->Mail();
-				++ pvsSize;
-				pvs.push_back(obj);
-			}
-		}
-	}
-
-	return pvsSize;
-}
-
-/***********************************************************************/
-/*                     GlDebuggerWidget implementation				   */
-/***********************************************************************/
-
-
-GlDebuggerWidget::GlDebuggerWidget(GlRendererBuffer *buf, QWidget *parent)
-      : QGLWidget(QGLFormat(QGL::SampleBuffers), parent), mRenderBuffer(buf)
-{
-	// create the pbuffer
-    //pbuffer = new QGLPixelBuffer(QSize(512, 512), format(), this);
-    timerId = startTimer(20);
-    setWindowTitle(("OpenGL pbuffers"));
-}
-
-
-GlDebuggerWidget::~GlDebuggerWidget()
-{
- mRenderBuffer->releaseFromDynamicTexture();
-   glDeleteTextures(1, &dynamicTexture);
-	 
-	 DEL_PTR(mRenderBuffer);
-}
-
-
-void GlDebuggerWidget::initializeGL()
-{
-	glMatrixMode(GL_PROJECTION);
-	glLoadIdentity();
-
-	glFrustum(-1, 1, -1, 1, 10, 100);
-	glTranslatef(-0.5f, -0.5f, -0.5f);
-	glTranslatef(0.0f, 0.0f, -15.0f);
-	glMatrixMode(GL_MODELVIEW);
-
-	glEnable(GL_CULL_FACE);
-	initCommon();
-	initPbuffer();
-
-}
-
-
-void GlDebuggerWidget::resizeGL(int w, int h)
-{
-	glViewport(0, 0, w, h);
-}
-
-
-void GlDebuggerWidget::paintGL()
-{
-	// draw a spinning cube into the pbuffer..
-	mRenderBuffer->makeCurrent();
-	
-	BeamSampleStatistics stats;
-	mRenderBuffer->SampleBeamContributions(mSourceObject, mBeam, mSamples, stats);
-
-	glFlush();
-
-	// rendering directly to a texture is not supported on X11, unfortunately
-    mRenderBuffer->updateDynamicTexture(dynamicTexture);
-   
-    // and use the pbuffer contents as a texture when rendering the
-    // background and the bouncing cubes
-    makeCurrent();
-    glBindTexture(GL_TEXTURE_2D, dynamicTexture);
-    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-    // draw the background
-    glMatrixMode(GL_MODELVIEW);
-    glPushMatrix();
-    glLoadIdentity();
-    glMatrixMode(GL_PROJECTION);
-    glPushMatrix();
-    glLoadIdentity();
-
-  	glPopMatrix();
-	glMatrixMode(GL_MODELVIEW);
-	glPopMatrix();
-}
-
-
-void GlDebuggerWidget::initPbuffer()
-{
-	// set up the pbuffer context
-    mRenderBuffer->makeCurrent();
-	/*mRenderBuffer->InitGL();
-
-	glViewport(0, 0, mRenderBuffer->size().width(), mRenderBuffer->size().height());
-	glMatrixMode(GL_PROJECTION);
-	glLoadIdentity();
-	glOrtho(-1, 1, -1, 1, -99, 99);
-	glTranslatef(-0.5f, -0.5f, 0.0f);
-	glMatrixMode(GL_MODELVIEW);
-	glLoadIdentity();
-
-	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);*/
-	
-	// generate a texture that has the same size/format as the pbuffer
-    dynamicTexture = mRenderBuffer->generateDynamicTexture();
-
-	// bind the dynamic texture to the pbuffer - this is a no-op under X11
-	mRenderBuffer->bindToDynamicTexture(dynamicTexture);
-	makeCurrent();
-}
-
-void GlDebuggerWidget::initCommon()
-{
-	glEnable(GL_TEXTURE_2D);
-	glEnable(GL_DEPTH_TEST);
-
-	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
-}
-
-}
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/common.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/common.h	(revision 1112)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/common.h	(revision 1145)
@@ -38,5 +38,5 @@
 //#pragma warning(disable:4244)
 
-#if 0 // $$$matt: comment this out because conflicts with definition in qt library!!
+#if 0 // Note matt: comment this out because conflicts with definition in qt library!!
 typedef unsigned int uint;
 #endif
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.h	(revision 1133)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.h	(revision 1145)
@@ -170,9 +170,11 @@
 		float mPriority;
 
-		VspBspSplitCandidate(): mPriority(0) 
+		float mRenderCostDecr;
+
+		VspBspSplitCandidate(): mPriority(0), mRenderCostDecr(0) 
 		{};
 
 		VspBspSplitCandidate(const Plane3 &plane, const VspBspTraversalData &tData): 
-		mSplitPlane(plane), mParentData(tData), mPriority(0)
+		mSplitPlane(plane), mParentData(tData), mPriority(0), mRenderCostDecr(0) 
 		{}
 
@@ -404,5 +406,5 @@
 	/** Evaluates candidate for splitting.
 	*/
-	void EvalSplitCandidate(VspBspTraversalData &tData, VspBspSplitCandidate &splitData);
+	void EvalSplitCandidate(VspBspSplitCandidate &splitData);
 
 	/** Computes priority of the traversal data and stores it in tData.
@@ -413,5 +415,6 @@
 	*/
 	float EvalRenderCostDecrease(const Plane3 &candidatePlane,
-								 const VspBspTraversalData &data) const;
+								 const VspBspTraversalData &data,
+								 float &normalizedOldRenderCost) const;
 
 	/** Constructs tree using the split priority queue.
@@ -705,4 +708,9 @@
 	//float GetMemUsage(const VspBspTraversalQueue &tstack) const;
 
+
+	void EvalSubdivisionStats(const VspBspTraversalData &tData,
+						      const VspBspTraversalData &tFrontData,
+							  const VspBspTraversalData &tBackData
+							  );
 
 	/** Adds stats to subdivision log file.
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.h	(revision 1144)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.h	(revision 1145)
@@ -66,7 +66,4 @@
 	int mMaxCostMisses;
 
-	/// priority of this split
-	//float mPriority;
-	
 	SplitCandidate()
 	{};
@@ -78,4 +75,22 @@
 	virtual int Type() const = 0;
 	virtual bool GlobalTerminationCriteriaMet() const = 0;
+
+	/** Set render cost decrease achieved through this split.
+	*/
+	void SetRenderCostDecrease(const float renderCostDecr)
+	{
+		mRenderCostDecrease = renderCostDecr;
+	}
+	
+	float GetRenderCostDecrease() const
+	{
+		return mRenderCostDecrease;
+	}
+
+protected:
+
+	/// render cost decrease achieved through this split
+	float mRenderCostDecrease;
+	
 };
 
@@ -814,5 +829,6 @@
 	*/
 	float EvalRenderCostDecrease(const AxisAlignedPlane &candidatePlane,
-								 const VspTraversalData &data) const;
+								 const VspTraversalData &data,
+								 float &normalizedOldRenderCost) const;
 
 	/** Collects view cells in the subtree under root.
@@ -852,5 +868,5 @@
 	*/
 	VspNode *Subdivide(SplitQueue &tQueue,
-					   VspSplitCandidate &splitCandidate,
+					   SplitCandidate *splitCandidate,
 					   const bool globalCriteriaMet);
 
@@ -859,5 +875,4 @@
 	void AddSubdivisionStats(const int viewCells,
 							 const float renderCostDecr,
-							 const float splitCandidateCost,
 							 const float totalRenderCost,
 							 const float avgRenderCost);
@@ -1024,5 +1039,9 @@
 		RayInfoContainer &rays);
 
+	void EvalSubdivisionStats(const VspTraversalData &tData,
+							  const VspTraversalData &tFrontData,
+							  const VspTraversalData &tBackData);
 protected:
+
 
 	bool mUseKdPvsForHeuristics;
@@ -1442,5 +1461,6 @@
 	*/
 	float EvalRenderCostDecrease(const AxisAlignedPlane &candidatePlane,
-								 const OspTraversalData &data) const;
+								 const OspTraversalData &data,
+								 float &normalizedOldRenderCost) const;
 
 
@@ -1463,5 +1483,5 @@
 	*/
 	KdNode *Subdivide(SplitQueue &tQueue,
-					  OspSplitCandidate &splitCandidate,
+					  SplitCandidate *splitCandidate,
 					  const bool globalCriteriaMet);
 	
@@ -1585,22 +1605,29 @@
 		@param rightPvs updates the right pvs
 	*/
-	void EvalHeuristicsContribution(const SortableEntry &ci,
+	void EvalHeuristicsContribution(KdLeaf *leaf,
+		const SortableEntry &ci,
 		float &volLeft,
 		float &volRight,
 		int &pvsLeft,
-		int &pvsRight);
+		int &pvsRight,
+		int &viewCellsLeft,
+		int &viewCellsRight);
 
 	/** Evaluate the contributions of view cell volume of the left and the right view cell.
 	*/
-	void EvalVolumeContribution(const VssRay &ray, float &volLeft, float &volRight);
+	void EvalVolumeContribution(const VssRay &ray, 
+								float &volLeft, 
+								float &volRight,
+								int &viewCellsLeft,
+								int &viewCellsRight);
 
 	/** Prepares objects for the cost heuristics.
 		@returns pvs size of the node
 	*/
-	float PrepareHeuristics(const OspTraversalData &tData);
+	float PrepareHeuristics(const OspTraversalData &tData, int &numViewCells);
 
 	/** Prepares heuristics for a particular ray.
 	*/
-	float PrepareHeuristics(const VssRay &ray);
+	float PrepareHeuristics(const VssRay &ray, int &numViewCells);
 
 	/** Prepares construction for vsp and osp trees.
@@ -1620,6 +1647,20 @@
 		RayInfoContainer &rays);
 
-
+	/** Reads parameters from environment singleton.
+	*/
 	void ReadEnvironment();
+
+	/** Returns true if the specified ray end points is inside the kd leaf.
+		@param isTermination if origin or termination point should be checked
+	*/
+	bool EndPointInsideNode(KdLeaf *leaf, VssRay &ray, bool isTermination) const;
+
+	void AddViewCellVolume(ViewCell *vc,
+						   const int cf,
+						   float &frontPvs,
+						   float &backPvs,
+						   float &totalPvs) const;
+
+	int ClassifyRay(VssRay *ray, KdLeaf *leaf, const AxisAlignedPlane &plane) const;
 
 protected:
@@ -1779,5 +1820,8 @@
 		RayInfoContainer &objectSpaceRays);
 
-	bool FinishedConstruction();
+	void RunConstruction(const bool repair);
+	bool SubdivideSplitCandidate(SplitCandidate *sc);
+
+	bool FinishedConstruction() const;
 
 	SplitCandidate *NextSplitCandidate();
@@ -1787,9 +1831,9 @@
 	void CollectDirtyCandidates(vector<SplitCandidate *> &dirtyList);
 
-	SplitCandidate *PrepareVsp(const VssRayContainer &sampleRays,
+	VspTree::VspSplitCandidate *PrepareVsp(const VssRayContainer &sampleRays,
 							   AxisAlignedBox3 *forcedViewSpace,
 							   RayInfoContainer &rays);
 
-	SplitCandidate *PrepareOsp(const VssRayContainer &sampleRays,
+	OspTree::OspSplitCandidate *PrepareOsp(const VssRayContainer &sampleRays,
 		const ObjectContainer &objects,
 		AxisAlignedBox3 *forcedObjectSpace,
Index: GTP/trunk/Lib/Vis/Preprocessing/src/PreprocessorThread.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/PreprocessorThread.h	(revision 860)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/PreprocessorThread.h	(revision 1145)
@@ -1,6 +1,6 @@
 #ifndef __PREPROCESSOR_THREAD_H
 #define __PREPROCESSOR_THREAD_H
-
-#include <QThread>
+// matt: remove qt dependencies
+//#include <QThread>
 
 namespace GtpVisibilityPreprocessor {
@@ -8,19 +8,24 @@
 class Preprocessor;
 
-class PreprocessorThread : public QThread
+/** This class represents a preprocessor thread.
+*/
+class PreprocessorThread//: public QThread
 {
-  Q_OBJECT
+  //Q_OBJECT
 
   Preprocessor *mPreprocessor;
 public:
-  PreprocessorThread(Preprocessor *p, QObject *parent = 0);
+  //PreprocessorThread(Preprocessor *p, QObject *parent = 0);
+	PreprocessorThread(Preprocessor *p);
   ~PreprocessorThread();
+
+  void operator()();
 
   void Main();
 
-protected:
+/*protected:
   void run() {
 	Main();
-  }
+  }*/
 };
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.h	(revision 1142)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.h	(revision 1145)
@@ -250,5 +250,5 @@
 	bool Mailed(const int mailbox) const { return mMailbox == sMailId + mailbox; }
 
-	int IncMail() { return ++mMailbox - sMailId; }
+	int IncMail() { return ++ mMailbox - sMailId; }
 
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/RssTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/RssTree.cpp	(revision 1112)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/RssTree.cpp	(revision 1145)
@@ -2086,5 +2086,5 @@
 	//	exporter->ExportKdTree(*mKdTree);
 	exporter->SetWireframe();
-	exporter->ExportScene(preprocessor->mSceneGraph->mRoot);
+//	exporter->ExportScene(preprocessor->mSceneGraph->mRoot);
 	exporter->SetWireframe();
 	exporter->ExportBox(box);
Index: GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp	(revision 1112)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp	(revision 1145)
@@ -16,6 +16,8 @@
 #include "ResourceManager.h"
 
-#include <QApplication>
-#include <QtOpenGL>
+//#include <QApplication>
+//#include <QtOpenGL>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/xtime.hpp>
 #include "GlRenderer.h"
 
@@ -25,4 +27,62 @@
 
 using namespace GtpVisibilityPreprocessor;
+
+Preprocessor *preprocessor = NULL;
+
+#if QT_ENABLED
+QApplication *app = NULL;
+#endif
+
+
+void Cleanup()
+{
+#if QT_ENABLED
+	DEL_PTR(rendererWidget);
+#endif
+
+	DEL_PTR(preprocessor);
+
+	Environment::DelSingleton();
+	MeshManager::DelSingleton();
+	MaterialManager::DelSingleton();
+}
+
+
+void DisplayWidget()
+{
+#if QT_ENABLED
+	QApplication *app = NULL;
+
+	// create a qt application first (must be created before any opengl widget ...)
+	app = new QApplication(argc, argv);
+
+	if (!QGLFormat::hasOpenGL() || !QGLPixelBuffer::hasOpenGLPbuffers()) {
+		QMessageBox::information(0, "OpenGL pbuffers", 
+			"This system does not support OpenGL/pbuffers.",
+			QMessageBox::Ok);
+		return -1;
+	}
+	
+	// note matt: capsulate qt dependent code as good as possible
+	rendererWidget = 
+		new GlRendererWidget(p->mSceneGraph, p->mViewCellsManager, p->mKdTree);
+
+	rendererWidget->resize(640, 480);
+	rendererWidget->show();
+
+	if (0 && p->GetRenderer()) 
+	{
+		cout<<"CONNECTING"<<endl;
+		QObject::connect(p->GetRenderer(),
+		SIGNAL(UpdatePvsErrorItem(int i, GlRendererBuffer::PvsErrorEntry &)),
+				rendererWidget->mControlWidget, 
+				SLOT(UpdatePvsErrorItem(int i,
+				GlRendererBuffer::PvsErrorEntry &)));
+
+		cout<<"CONNECTED"<<endl;
+	}
+#endif
+}
+
 
 int
@@ -30,153 +90,118 @@
 {
 
-  //Now just call this function at the start of your program and if you're
-  //compiling in debug mode (F5), any leaks will be displayed in the Output
-  //window when the program shuts down. If you're not in debug mode this will
-  //be ignored. Use it as you will!
-  //note: from GDNet Direct [3.8.04 - 3.14.04] void detectMemoryLeaks() {
-  _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);
-  _CrtSetReportMode(_CRT_ASSERT,_CRTDBG_MODE_FILE);
-  _CrtSetReportFile(_CRT_ASSERT,_CRTDBG_FILE_STDERR); 
-
-  InitTiming();
-
-  Debug.open("debug.log");
-  
-  Environment::GetSingleton()->Parse(argc, argv, USE_EXE_PATH);
-  MeshKdTree::ParseEnvironment();
-
-  char buff[128];
-  Environment::GetSingleton()->GetStringValue("Preprocessor.type", buff);
-  string preprocessorType(buff);
-
-  Preprocessor *p = NULL;
-
- 
-  if (preprocessorType == "vss")
-  {
-	  p = new VssPreprocessor();
-  }
-  else
-  {
-	if (preprocessorType == "rss")
-	{
-		p = new RssPreprocessor();
+	//Now just call this function at the start of your program and if you're
+	//compiling in debug mode (F5), any leaks will be displayed in the Output
+	//window when the program shuts down. If you're not in debug mode this will
+	//be ignored. Use it as you will!
+	//note: from GDNet Direct [3.8.04 - 3.14.04] void detectMemoryLeaks() {
+	_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);
+	_CrtSetReportMode(_CRT_ASSERT,_CRTDBG_MODE_FILE);
+	_CrtSetReportFile(_CRT_ASSERT,_CRTDBG_FILE_STDERR); 
+
+	int returnCode = 0;
+
+	InitTiming();
+
+	Debug.open("debug.log");
+
+	Environment::GetSingleton()->Parse(argc, argv, USE_EXE_PATH);
+	MeshKdTree::ParseEnvironment();
+
+	char buff[128];
+	Environment::GetSingleton()->GetStringValue("Preprocessor.type", buff);
+	string preprocessorType(buff);
+
+	if (preprocessorType == "vss")
+	{
+		preprocessor = new VssPreprocessor();
 	}
 	else
 	{
-	  if (preprocessorType == "exact")
-	  {
-		p = new ExactPreprocessor();
-	  }
-	  else
-	  {
-		if (preprocessorType == "sampling")
+		if (preprocessorType == "rss")
 		{
-		  p = new SamplingPreprocessor();
+			preprocessor = new RssPreprocessor();
 		}
 		else
-		{	
-		  if (preprocessorType == "render")
-		  {
-			 p = new RenderSampler();
-		  }
-		  else {
-			  Environment::DelSingleton();
-			  cerr<<"Unknown preprocessor type"<<endl;
-			  Debug<<"Unknown preprocessor type"<<endl;
-			  exit(1);
-		  }
+		{
+			if (preprocessorType == "exact")
+			{
+				preprocessor = new ExactPreprocessor();
+			}
+			else
+			{
+				if (preprocessorType == "sampling")
+				{
+					preprocessor = new SamplingPreprocessor();
+				}
+				else
+				{	
+					if (preprocessorType == "render")
+					{
+						preprocessor = new RenderSampler();
+					}
+					else {
+						Environment::DelSingleton();
+						cerr<<"Unknown preprocessor type"<<endl;
+						Debug<<"Unknown preprocessor type"<<endl;
+						exit(1);
+					}
+				}
+			}
 		}
-	  }
-	}
-  }
-  
-  QApplication *app = NULL;
-
-  if (p->mUseGlRenderer || p->mUseGlDebugger) {
+	}
 	
-	// create a qt application first (must be created before any opengl widget...
-	app = new QApplication(argc, argv);
-	
-	if (!QGLFormat::hasOpenGL() || !QGLPixelBuffer::hasOpenGLPbuffers()) {
-	  QMessageBox::information(0, "OpenGL pbuffers", 
-							   "This system does not support OpenGL/pbuffers.",
-							   QMessageBox::Ok);
-	  return -1;
-	}
-  }
-  
-  preprocessor = p;
-  
-  Environment::GetSingleton()->GetStringValue("Scene.filename", buff);
-  string filename(buff);
- 
-  p->LoadScene(filename);
-  
-  p->BuildKdTree();
-  p->KdTreeStatistics(cout);
- 
-  // parse view cells related options
-  p->PrepareViewCells();
-  
-
-  // create a preprocessor thread
-  PreprocessorThread *pt = new PreprocessorThread(p, app);
-
-  //  p->mSceneGraph->Export("soda.x3d");
-  if (0) {
-    p->Export(filename + "-out.x3d", true, false, false);
-    p->Export(filename + "-kdtree.x3d", false, true, false);	
-  }
-
-  if (p->mUseGlRenderer) {
-	 
-	rendererWidget = new GlRendererWidget(p->mSceneGraph, p->mViewCellsManager, p->mKdTree);
-	//  renderer->resize(640, 480);
-	 
-	rendererWidget->resize(640, 480);
-	rendererWidget->show();
-	
-	if (0 && p->GetRenderer()) {
-	  
-	  cout<<"CONNECTING"<<endl;
-	  QObject::connect(p->GetRenderer(),
-					   SIGNAL(UpdatePvsErrorItem(int i,
-												 GlRendererBuffer::PvsErrorEntry &)),
-					   
-					   rendererWidget->mControlWidget,
-					   SLOT(UpdatePvsErrorItem(int i,
-											   GlRendererBuffer::PvsErrorEntry &)));
-	  cout<<"CONNECTED"<<endl;
-	}
-	
-	pt->start(QThread::LowPriority);
-	
-	
-  } else{
-	// just call the mail method -> will be executed in the main thread
-	pt->Main();
-  }
-  
-
-  int returnCode = 0;
-
-  if (app)
-  {
-	 returnCode = app->exec();
-	DEL_PTR(app);
-	}
-
-  //-- clean up
-  DEL_PTR(p);
-  Environment::DelSingleton();
-  DEL_PTR(rendererWidget);
-
-  MeshManager::DelSingleton();
-  MaterialManager::DelSingleton();
-
-  DEL_PTR(pt);
-
-  return returnCode;
+
+	//-- load scene 
+
+	Environment::GetSingleton()->GetStringValue("Scene.filename", buff);
+	string filename(buff);
+	preprocessor->LoadScene(filename);
+
+	//-- build kd tree from scene geometry
+
+	preprocessor->BuildKdTree();
+	preprocessor->KdTreeStatistics(cout);
+
+	// parse view cells related options
+	preprocessor->PrepareViewCells();
+
+	//  p->mSceneGraph->Export("soda.x3d");
+	if (0) {
+		preprocessor->Export(filename + "-out.x3d", true, false, false);
+		preprocessor->Export(filename + "-kdtree.x3d", false, true, false);	
+	}
+
+
+	// create a preprocessor thread
+	//PreprocessorThread *pt = new PreprocessorThread(p, app);
+	PreprocessorThread pt(preprocessor);
+
+	if (preprocessor->mUseGlRenderer || preprocessor->mUseGlDebugger)
+	{
+		// display the render widget
+		DisplayWidget();
+
+		// create and run the thread
+		boost::thread thrd(pt);
+		thrd.join();
+		//pt->start(QThread::LowPriority);
+	} 
+	else
+	{
+		// just call the mail method -> will be executed in the main thread
+		pt.Main();
+	}
+
+#if QT_ENABLED
+	if (app)
+	{
+		returnCode = app->exec();
+        DEL_PTR(app);
+	}
+#endif
+
+	Cleanup();
+
+	return returnCode;
 }
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.h	(revision 1008)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.h	(revision 1145)
@@ -3,8 +3,10 @@
 
 //#include "glInterface.h"
-#include <QtOpenGL>
-#include <QWaitCondition>
-
+
+//#include <QWaitCondition>
+//#include <QtOpenGL>
 //#include <QGLPixelBuffer>
+
+//class QWidget;
 
 #include "Vector3.h"
@@ -14,5 +16,4 @@
 #include "Beam.h"
 
-class QWidget;
 
 namespace GtpVisibilityPreprocessor {
@@ -105,9 +106,9 @@
   bool mUseGlLists;
   
-  QString mSnapPrefix;
+  string mSnapPrefix;
 
   KdTree *mKdTree;
 
-  QWaitCondition mRenderingFinished;
+  //QWaitCondition mRenderingFinished;
   
   vector<OcclusionQuery *> mOcclusionQueries;
@@ -117,5 +118,5 @@
 			 KdTree *tree);
   
-  ~GlRenderer();
+  virtual ~GlRenderer();
 
 
@@ -151,11 +152,10 @@
 
 
-class GlRendererBuffer : public QObject, public QGLPixelBuffer, public GlRenderer
+class GlRendererBuffer: public GlRenderer
 {
-Q_OBJECT
+
+//Q_OBJECT
 public:
-GlRendererBuffer(const int w,
-				 const int h,
-				 SceneGraph *sceneGraph,
+GlRendererBuffer(SceneGraph *sceneGraph,
 				 ViewCellsManager *viewcells,
 				 KdTree *tree);
@@ -182,16 +182,16 @@
 						  vector<RenderCostSample> &samples,
 						  const bool useOcclusionQueries,
-						  const int threshold = 0);
-
-
-  void
-  EvalPvsStat();
-
-  void
-  ClearErrorBuffer();
-  
-
-  virtual int GetWidth() const { return width(); }
-  virtual int GetHeight() const { return height(); }
+						  const int threshold = 0)
+	{}
+
+	/** Implerment in subclasses.
+	*/
+	void EvalPvsStat() {};
+
+	void ClearErrorBuffer();
+  
+
+  virtual int GetWidth() const { return 0; }
+  virtual int GetHeight() const { return 0; }
 
 
@@ -230,9 +230,9 @@
   int mPvsStatFrames;
   struct PvsErrorEntry {
-	PvsErrorEntry() {}
-	float mError;
-	int mPvsSize;
-	Vector3 mPosition;
-	Vector3 mDirection;
+	  PvsErrorEntry() {}
+	  float mError;
+	  int mPvsSize;
+	  Vector3 mPosition;
+	  Vector3 mDirection;
   };
   
@@ -240,6 +240,6 @@
 
   
-private:
-  unsigned int *mPixelBuffer;
+protected:
+	unsigned int *mPixelBuffer;
   
 	static void GenQueries(const int numQueries);
@@ -258,219 +258,8 @@
 
 public:
-  signals:
-	void UpdatePvsErrorItem(int i, GlRendererBuffer::PvsErrorEntry &);
-};
-
-
-class RendererControlWidget : public QWidget
-{
-  Q_OBJECT
-public:
-
-  QListWidget *mPvsErrorWidget;
-
-  RendererControlWidget(QWidget * parent = 0, Qt::WFlags f = 0);
-
-  public slots:
-
-  void FocusNextPvsErrorFrame();
-  void UpdatePvsErrorItem(int i,
-						  GlRendererBuffer::PvsErrorEntry &);
-
-  signals:
-  
-  void SetViewCellGranularity(int);
-  void SetSceneCut(int);
-  void SetTopDistance(int);
-  void SetVisibilityFilterSize(int);
-  void SetSpatialFilterSize(int);
-
-  void SetRenderFilter(bool);
-  void SetUseFilter(bool);
-  void SetUseSpatialFilter(bool);
-  void SetRenderErrors(bool);
-  void SetShowViewCells(bool);
-  void SetShowRenderCost(bool);
-  void SetShowPvsSizes(bool);
-  void SetTopView(bool);
-  void SetCutViewCells(bool);
-  void SetCutScene(bool);
-
-  
-};
-
-class GlRendererWidget : public QGLWidget, public GlRenderer
-{
-  Q_OBJECT
-public:
-
-  // point of the last mouse click used for movement in the scene
-  Vector3 mousePoint;
-
-  bool mTopView;
-  bool mRenderViewCells;
-  bool mCutViewCells;
-  bool mCutScene;
-  bool mRenderErrors;
-  bool mRenderFilter;
-  bool mUseFilter;
-  bool mUseSpatialFilter;
-  bool mShowRenderCost;
-  
-  bool mShowPvsSizes;
-  float mSpatialFilterSize;
-  
-  Plane3 mSceneCutPlane;
-  float mTopDistance;
-
-  // some statistics
-  int mPvsSize;
-  float mRenderError;
-
-  RendererControlWidget *mControlWidget;
-  
-  GlRendererWidget(SceneGraph *sceneGraph,
-				   ViewCellsManager *viewcells,
-				   KdTree *tree,
-				   QWidget * parent = 0, const QGLWidget * shareWidget = 0, Qt::WFlags f = 0
-				   );
-
-
-  virtual void SetupCamera();
-
-  void initializeGL() {
-	InitGL();
-  }
-  void resizeGL(int w, int h);
-  void paintGL();
-  void timerEvent(QTimerEvent *) {
-	  update();
-  }
-
-  void mousePressEvent(QMouseEvent *);
-  void mouseReleaseEvent(QMouseEvent *);
-  void mouseMoveEvent(QMouseEvent *);
-
-  void keyPressEvent ( QKeyEvent * e ) ;
-
-  void
-  RenderPvs();
-
-  float
-  RenderErrors();
-  void
-  RenderInfo();
-
-  virtual int GetWidth() const { return width(); }
-  virtual int GetHeight() const { return height(); }
-
- virtual void
-  SetupProjection(const int w, const int h, const float angle = 70.0f);
-
-  void
-  RenderViewCells();
-
- public slots:
-
- void SetRenderErrors(bool b) {
-   mRenderErrors = b;
-   updateGL();
- }
-
- void SetRenderFilter(bool b) {
-   mRenderFilter = b;
-   updateGL();
- }
-
-  void SetUseFilter(bool b) {
-   mUseFilter = b;
-   updateGL();
- }
-
-  void SetUseSpatialFilter(bool b) {
-	mUseSpatialFilter = b;
-	updateGL();
-  }
-
-  
-  void
-  SetViewCellGranularity(int number);
-  
-  void
-  SetVisibilityFilterSize(int number);
-
-  void
-  SetSpatialFilterSize(int number);
-  
-  void
-  SetSceneCut(int cut);
-  
-  void
-  SetTopDistance(int dist);
-  
-  void SetShowViewCells(bool b) {
-	mRenderViewCells = b;
-	updateGL();
-  }
-
-  void SetShowRenderCost(bool b) {
-	mShowRenderCost = b;
-	updateGL();
-  }
-
-  void SetShowPvsSizes(bool b) {
-	mShowPvsSizes = b;
-	updateGL();
-  }
-
-  void SetTopView(bool b) {
-	mTopView = b;
-	updateGL();
-  }
-
-  void SetCutViewCells(bool b) {
-	mCutViewCells = b;
-	updateGL();
-  }
-  void SetCutScene(bool b) {
-	mCutScene = b;
-	updateGL();
-  }
-
-
-};
-
-
-extern GlRendererWidget *rendererWidget;
-
-class GlDebuggerWidget : public QGLWidget
-{
-	Q_OBJECT
-public:
-    GlDebuggerWidget(GlRendererBuffer *buf, QWidget *parent = NULL);
-    ~GlDebuggerWidget();
-    void initializeGL();
-    void resizeGL(int w, int h);
-    void paintGL();
-    void timerEvent(QTimerEvent *) { update(); }
-    void mousePressEvent(QMouseEvent *) { killTimer(timerId); }
-    void mouseReleaseEvent(QMouseEvent *) { timerId = startTimer(20); }
-
-    void initCommon();
-    void initPbuffer();
-
-  
-	 GlRendererBuffer *mRenderBuffer;
-
-	 Beam mBeam;
-	 int mSamples;
-	 Intersectable *mSourceObject;
-
-private:
-    GLuint dynamicTexture;
-    int timerId;
-};
-
-extern GlDebuggerWidget *debuggerWidget;
+	// matt: remove qt dependencies
+ // signals:
+//	void UpdatePvsErrorItem(int i, GlRendererBuffer::PvsErrorEntry &);
+};
 
 };
