Index: /trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env	(revision 538)
+++ /trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env	(revision 540)
@@ -29,6 +29,6 @@
 VssPreprocessor {
 	samplesPerPass  100000
-	initialSamples 300000
-	vssSamples 300000
+	initialSamples 200000
+	vssSamples 200000
 	vssSamplesPerPass 100000
 	useImportanceSampling true
@@ -52,5 +52,5 @@
 	maxDepth 	40
 	minPvs		30
-	minRays		100
+	minRays		500
 	minSize		0.001
  	maxCostRatio	1.5
@@ -66,5 +66,5 @@
 	
 	interleaveDirSplits	true
-    dirSplitDepth 0
+    dirSplitDepth 10
 	
 	numberOfEndPointDomains	10000
@@ -171,5 +171,5 @@
 ViewCells {
 	loadFromFile false
-	exportToFile false
+	exportToFile true
 	#type kdTree
 	#type vspKdTree
@@ -182,5 +182,5 @@
 	maxViewCells 100000
 	#percentage of total visible objects where pvs is considered invalid
-	maxPvsRatio 0.1
+	maxPvsRatio 0.5
 		
 	delayedConstruction false
@@ -207,5 +207,6 @@
 #	filename ../data/vienna/viewcells-25.x3d
 #	filename ../data/vienna/viewcells-large-sel.x3d
-	filename ../scripts/viewcells_vienna.xml
+#	filename ../scripts/viewcells_vienna.xml
+	filename ../scripts/viewcells_atlanta.xml
 }
 
@@ -270,5 +271,5 @@
 	# pvs                  = 1024
 	
-	splitPlaneStrategy 1024
+	splitPlaneStrategy 1026
 	
 	# maximal candidates for split planes
@@ -288,5 +289,5 @@
 	Termination {
 		# parameters used for autopartition
-		minRays 		400
+		minRays 		1000
 		minPolygons 		-1
 		maxDepth		30
@@ -299,5 +300,5 @@
 		#maxAccRayLength	100
 		
-		maxViewCells		200000
+		maxViewCells		200
 		
 		# used for pvs criterium
@@ -305,5 +306,5 @@
 		
 		AxisAligned {
-			minRays 		200000
+			minRays 		5000
 			maxRayContribution	0.5
 		}
@@ -314,10 +315,10 @@
 	Visualization {
 		# x3d visualization of the split planes
-		exportSplits true
+		exportSplits false
 	}
 	
 	PostProcess {
 		maxCostRatio 0.1
-		minViewCells 6000
+		minViewCells 1000
 		maxPvsSize   10000
 		useRaysForMerge true
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Beam.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Beam.cpp	(revision 535)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Beam.cpp	(revision 540)
@@ -1,9 +1,10 @@
 #include "VssRay.h"
 #include "Beam.h"
-
+#include "Mesh.h"
+#include "Polygon3.h"
 
 
 void
-Beam::Construct(const  AxisAlignedBox3 &box, const  AxisAlignedBox3 &dBox)
+Beam::Construct(const AxisAlignedBox3 &box, const AxisAlignedBox3 &dBox)
 {
   // the frustum is defined by set of negative halfspace described by mPlanes
@@ -73,20 +74,45 @@
 
 
-void Beam::ComputeFrustum(float &left, float &right,
-						  float &bottom, float &top,
-						  float &near, float &far,
-						  const AxisAlignedBox3 &sceneBBox) const
+void Beam::ComputePerspectiveFrustum(float &left, float &right,
+									 float &bottom, float &top,
+									 float &near, float &far,
+									 const AxisAlignedBox3 &sceneBBox) const
 {
 	const float xDirRange = mDirBox.Max().x - mDirBox.Min().x;
 	const float yDirRange = mDirBox.Max().y - mDirBox.Min().y;
+	//Debug << "xdir range: " << xDirRange << endl;
+	//Debug << "ydir range: " << yDirRange << endl;
 
 	near = 0.1f; // NOTE: what is the best value for near and far plane?
 	far = 2.0f * Magnitude(sceneBBox.Diagonal());
-
-	left = near / tan(xDirRange * 0.5f);
-	right = near / tan(xDirRange * 0.5f);
-
-	bottom = near / tan(yDirRange * 0.5f);
-	top = near / tan(yDirRange * 0.5f);
+	
+	right = fabs(near * tan(xDirRange * 0.5f));
+	left = -right;
+
+	top = fabs(near * tan(yDirRange * 0.5f));
+	bottom = -top;
+}
+
+
+void Beam::ComputeOrthoFrustum(float &left, float &right,
+							   float &bottom, float &top,
+							   float &near, float &far,
+							   const AxisAlignedBox3 &sceneBBox) const
+{
+	const int vAxis = GetMainDirection().DrivingAxis();
+	const int axis2 = (vAxis + 1) % 3;
+	const int axis3 = (vAxis + 2) % 3;
+
+	const float xDirRange = mBox.Max()[axis2] - mDirBox.Min()[axis2];
+	const float yDirRange = mDirBox.Max()[axis3] - mDirBox.Min()[axis3];
+
+	near = 0.1f; // NOTE: what is the best value for near and far plane?
+	far = 2.0f * Magnitude(sceneBBox.Diagonal());
+
+	right = xDirRange * 0.5f;
+	left = -right;
+
+	top = yDirRange * 0.5;
+	bottom = -top;
 }
 
@@ -94,6 +120,5 @@
 Vector3 Beam::GetMainDirection() const
 {
-	const Vector3 dCenter = mDirBox.Center();
-	return VssRay::GetDirection(dCenter.x, dCenter.y);
+	return - mPlanes[0].mNormal;
 }
 
@@ -123,2 +148,57 @@
 }
 
+
+void Beam::CreateMesh(const float zfar)
+{
+	if (mMesh)
+		return;
+
+	mMesh = new Mesh();
+	
+	// -- compute far plane
+
+	// box should not never remove part of beam polygons
+	Vector3 bmin = mBox.Min() - Vector3(zfar * 2.0);
+	Vector3 bmax = mBox.Max() + Vector3(zfar * 2.0);
+
+	AxisAlignedBox3 bbox(bmin, bmax);
+	Plane3 fplane;
+	fplane.mNormal = -mPlanes[0].mNormal;
+
+	// NOTE: beam far plane must not not be culled by gl far plane
+	fplane.mD = mPlanes[0].mD - zfar - 1.0f; 
+	mPlanes.push_back(fplane);
+
+	for (int i = 0; i < mPlanes.size(); ++ i)
+	{
+		Polygon3 *poly = bbox.CrossSection(mPlanes[i]);
+		
+		if (!poly->Valid(Limits::Small))
+			DEL_PTR(poly);
+		
+		for (int j = 0; (j < mPlanes.size()) && poly; ++ j)
+		{
+			if (j != i)
+			{
+				Polygon3 *front = new Polygon3();
+				Polygon3 *back = new Polygon3();
+				
+				poly->Split(mPlanes[j], *front, *back, Limits::Small);
+				DEL_PTR(poly);
+				DEL_PTR(front);
+
+				if (!back->Valid(Limits::Small))
+					DEL_PTR(back);
+				poly = back;
+			}
+		}
+	
+		if (poly)
+		{
+			poly->AddToMesh(*mMesh);
+		}
+	}
+
+	// remove far plane
+	mPlanes.pop_back();
+}
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Beam.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Beam.h	(revision 532)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Beam.h	(revision 540)
@@ -10,4 +10,5 @@
 class KdNode;
 class Intersectable;
+class Mesh;
 
 // the values need for rss tree update computed already inside the glrendererbuffer
@@ -74,12 +75,24 @@
   vector<Plane3> mPlanes;
 
+  Mesh *mMesh;
     
+  /** Constructs a beam from a spatial and a directional box.
+  */
   void Construct(const AxisAlignedBox3 &box,
-	  const AxisAlignedBox3 &dBox);
+		 	     const AxisAlignedBox3 &dBox);
   
-  void ComputeFrustum(float &left, float &right,
-					  float &bottom, float &top,
-					  float &near, float &far,
-					  const AxisAlignedBox3 &sceneBBox) const;
+  /** Computes parameters for glFrustum.
+  */
+  void ComputePerspectiveFrustum(float &left, float &right,
+								 float &bottom, float &top,
+								 float &near, float &far,
+								 const AxisAlignedBox3 &sceneBBox) const;
+
+  /* Computes parameters for glOrtho.
+  */
+  void ComputeOrthoFrustum(float &left, float &right,
+						   float &bottom, float &top,
+						   float &near, float &far,
+						   const AxisAlignedBox3 &sceneBBox) const;
 
   int ComputeIntersection(const AxisAlignedBox3 &box);
@@ -90,7 +103,9 @@
   bool SetValid() { return mFlags |= VALID; }
 
-  Beam():mFlags(STORE_KD_NODES+STORE_OBJECTS), mKdNodes(0), mObjects(0), mViewCells(0)
+  Beam():mFlags(STORE_KD_NODES+STORE_OBJECTS), mKdNodes(0), mObjects(0), mViewCells(0), mMesh(NULL)
   {
   }
+
+  void CreateMesh(const float zfar);
 };
 
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 538)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 540)
@@ -259,5 +259,10 @@
 	}
 	if (mUseGlRenderer || mUseGlDebugger)
-	  renderer = new GlRendererBuffer(1024, 768, mSceneGraph, mViewCellsManager, mKdTree);
+	{
+		// NOTE: render texture should be power of 2 and square
+		// renderer must be initialised
+		renderer = new GlRendererBuffer(1024, 768, mSceneGraph, mViewCellsManager, mKdTree);
+		renderer->makeCurrent();
+	}
 
 
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/dual_depth.cg
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/dual_depth.cg	(revision 532)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/dual_depth.cg	(revision 540)
@@ -15,5 +15,6 @@
 {
 	pixel OUT;
-
+	OUT.color = IN.color0;
+	
 	// the depth buffer	has to be compared to the current depth
 	float4 depth = tex2D(depthMap, IN.depthTexCoord.xy);
@@ -22,6 +23,9 @@
 	// reject by alpha test
 	if (test < depth.x)
+	{
 		OUT.color.w = 0;
-
+	//	OUT.color.y += 0.5;
+	}
+	
 	return OUT;
 }
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/VssPreprocessor.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/VssPreprocessor.cpp	(revision 538)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/VssPreprocessor.cpp	(revision 540)
@@ -360,4 +360,8 @@
 									  const ObjectContainer &objects)
 {
+	//debuggerWidget = new GlDebuggerWidget(renderer);
+	//  renderer->resize(640, 480);
+	//debuggerWidget->resize(640, 480);
+
 	vector<VssTreeLeaf *> leaves;
 	tree->CollectLeaves(leaves);
@@ -366,13 +370,26 @@
 
 	exporter->SetWireframe();
-	//exporter->ExportGeometry(objects);
+	exporter->ExportGeometry(objects);
 	exporter->SetFilled();
 	//Randomize();
-	for (int i = 0; i < 1; ++ i)
+	debuggerWidget = new GlDebuggerWidget(renderer);
+
+	/*debuggerWidget->mBeam = beam;
+	debuggerWidget->mSourceObject = sourceObj;
+	debuggerWidget->mSamples = 10000;
+	
+	Debug << "showing window" << endl;
+	debuggerWidget->show();*/
+	
+	renderer->makeCurrent();
+
+	for (int i = 0; i < 10; ++ i)
 	{
+		Beam beam;
+		Intersectable *sourceObj = mObjects[5];
+
 		const int index = (int)RandomValue(0, (Real)((int)leaves.size() - 1));
 		VssTreeLeaf *leaf = leaves[index];
 
-		Beam beam;
 		AxisAlignedBox3 dirBox = tree->GetDirBBox(leaf);
 		AxisAlignedBox3 box = tree->GetBBox(leaf);
@@ -387,22 +404,28 @@
 			  << beam.mKdNodes.size() << " kd nodes" << endl;
 
-		Intersectable *sourceObj = mObjects[5];
 		BeamSampleStatistics stats;
 
 		renderer->SampleBeamContributions(sourceObj,
 										  beam,
-										  10000,
+										  200000,
 										  stats);
 
+		char s[64]; sprintf(s, "shaft%04d.png", i);
+
+		QImage image = renderer->toImage();
+		image.save(s, "PNG");
 		Debug << "beam statistics: " << stats << endl << endl;
+
+		if (1)
+		{
+			AxisAlignedBox3 sbox = mSceneGraph->GetBox();
+			Vector3 bmin = sbox.Min() - 150.0f;
+			Vector3 bmax = sbox.Max() + 150.0f;
+			AxisAlignedBox3 vbox(bmin, bmax);
 		
-		AxisAlignedBox3 sbox = mSceneGraph->GetBox();
-		Vector3 bmin = sbox.Min() - 150.0f;
-		Vector3 bmax = sbox.Max() + 150.0f;
-		AxisAlignedBox3 vbox(bmin, bmax);
-		
-		exporter->ExportBeam(beam, vbox);
-
-		bool exportViewCells = true;
+			exporter->ExportBeam(beam, vbox);
+		}
+
+		bool exportViewCells = false;
 		
 		if (exportViewCells)
@@ -431,6 +454,10 @@
 		}
 	}
+	/*while (1)
+	{ debuggerWidget->repaint();
+	};*/
 	delete exporter;
 }
+
 
 float
@@ -591,6 +618,6 @@
 
   
-  int numExportRays = 5000;
-  //int numExportRays = 0;
+  //int numExportRays = 5000;
+  int numExportRays = 0;
 
   if (numExportRays) {
@@ -723,6 +750,8 @@
   mViewCellsManager->PostProcess(mObjects, viewCellRays);
 
-  if (mTestBeamSampling)
+  if (mTestBeamSampling && mUseGlRenderer)
+  {	
 	  TestBeamCasting(vssTree, mViewCellsManager, mObjects);
+  }
 
   //-- several visualizations and statistics
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp	(revision 538)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp	(revision 540)
@@ -100,12 +100,4 @@
 
 	pt->start(QThread::LowPriority);
-	
-  } else if (0 /*p->UseGlDebugger*/) {
-	    //debuggerWidget = new GlDebuggerWidget(*, (p->mSceneGraph, p->mViewCellsManager, p->mKdTree);
-		//  renderer->resize(640, 480);
-	//	debuggerWidget->resize(640, 480);
-	//	debuggerWidget->show();
-
-	pt->start(QThread::LowPriority);
   } else
   {
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp	(revision 535)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp	(revision 540)
@@ -1242,12 +1242,35 @@
 void X3dExporter::ExportBeam(const Beam &beam, const AxisAlignedBox3 &box)
 {
+	if (beam.mMesh)
+	{
+		ExportMesh(beam.mMesh);
+		return;
+	}
+
 	PolygonContainer polys;
 	//ExportBox(beam.mBox);
 
-	for (int i = 0; i < beam.mPlanes.size(); ++ i)
-	{
-		Polygon3 *poly = box.CrossSection(beam.mPlanes[i]);
+	const float zfar = 2.0f * Magnitude(box.Diagonal());
+
+	// box should not never remove part of beam polygons
+	Vector3 bmin = beam.mBox.Min() - Vector3(zfar * 2.0);
+	Vector3 bmax = beam.mBox.Max() + Vector3(zfar * 2.0);
+
+	AxisAlignedBox3 bbox(bmin, bmax);
+	Plane3 fplane;
+	fplane.mNormal = -beam.mPlanes[0].mNormal;
+
+	fplane.mD = beam.mPlanes[0].mD - zfar - 1.0f; 
+	
+	vector<Plane3> planes = beam.mPlanes;
+	planes.push_back(fplane);
+
+	for (int i = 0; i < planes.size(); ++ i)
+	{
+		Polygon3 *poly = bbox.CrossSection(planes[i]);
+		if (!poly->Valid(Limits::Small))
+			DEL_PTR(poly);
 		
-		for (int j = 0; (j < beam.mPlanes.size()) && poly; ++ j)
+		for (int j = 0; (j < planes.size()) && poly; ++ j)
 		{
 			if (j != i)
@@ -1256,5 +1279,5 @@
 				Polygon3 *back = new Polygon3();
 				
-				poly->Split(beam.mPlanes[j], *front, *back, Limits::Small);
+				poly->Split(planes[j], *front, *back, Limits::Small);
 				DEL_PTR(poly);
 				DEL_PTR(front);
@@ -1269,5 +1292,4 @@
 	}
 
-
 	ExportPolygons(polys);
 	CLEAR_CONTAINER(polys);
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.h	(revision 538)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.h	(revision 540)
@@ -10,4 +10,5 @@
 #include "Halton.h"
 #include "Renderer.h"
+#include "Beam.h"
 
 class SceneGraph;
@@ -23,4 +24,6 @@
 class BeamSampleStatistics;
 
+struct VssRayContainer;
+
 struct PvsRenderStatistics {
   
@@ -104,4 +107,6 @@
   virtual int GetWidth() const = 0;
   virtual int GetHeight() const = 0;
+
+  int GetId(int r, int g, int b) const;
 };
 
@@ -154,11 +159,24 @@
 							   );
 
-   PvsRenderStatistics mPvsStat;
+  void InitGL();
+
+  /** Computes rays from information gained with hw sampling-
+  */
+  void ComputeRays(Intersectable *sourceObj, VssRayContainer &rays);
+
+  int ComputePvs() const;
+
+
+  int ComputePvs(ObjectContainer &objects, ObjectContainer &pvs) const;
+
+  PvsRenderStatistics mPvsStat;
    
-   int mPvsStatFrames;
-   vector<float> mPvsErrorBuffer;
+  int mPvsStatFrames;
+  vector<float> mPvsErrorBuffer;
 
 private:
+	
 	static void GenQueries(const int numQueries);
+	
 	void SetupProjectionForViewPoint(const Vector3 &viewPoint, 
 									 const Beam &beam, 
@@ -217,6 +235,7 @@
 class GlDebuggerWidget : public QGLWidget
 {
-public:
-    GlDebuggerWidget(QWidget *parent, GlRendererBuffer *buf);
+	Q_OBJECT
+public:
+    GlDebuggerWidget(GlRendererBuffer *buf, QWidget *parent = NULL);
     ~GlDebuggerWidget();
     void initializeGL();
@@ -232,4 +251,7 @@
 	 GlRendererBuffer *mRenderBuffer;
 
+	 Beam mBeam;
+	 int mSamples;
+	 Intersectable *mSourceObject;
 private:
     GLuint dynamicTexture;
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.cpp	(revision 538)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.cpp	(revision 540)
@@ -1715,5 +1715,5 @@
 	}
 
-	// order intersectioins	
+	// order intersections	
 	if (planePoly->mVertices.size() > 3)
 	{
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp	(revision 535)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp	(revision 540)
@@ -13,5 +13,6 @@
 #include "ViewCellsParser.h"
 #include "Beam.h"
-
+#include "VssPreprocessor.h"
+#include "RssPreprocessor.h"
 
 
@@ -76,4 +77,8 @@
 int ViewCellsManager::Construct(VssRayContainer &rays)
 {
+	VssPreprocessor preprocessor;
+
+
+
 	return 0;
 }
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.cpp	(revision 538)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.cpp	(revision 540)
@@ -16,5 +16,7 @@
 static CGprofile sCgFragmentProfile;
 
-GLuint depthMap;
+GLuint frontDepthMap;
+GLuint backDepthMap;
+
 const int depthMapSize = 512;
 static vector<int> sQueries;
@@ -99,4 +101,10 @@
 }
 
+
+int GlRenderer::GetId(int r, int g, int b) const
+{
+	return r + (g << 8) + (b << 16);
+}
+
 void
 GlRenderer::SetupMaterial(Material *m)
@@ -152,47 +160,4 @@
   glGetOcclusionQueryuivNV = (PFNGLGETOCCLUSIONQUERYUIVNVPROC)
 	wglGetProcAddress("glGetOcclusionQueryuivNV");
-
-  // initialise second depth buffer texture
-  glGenTextures(1, &depthMap);
-  glBindTexture(GL_TEXTURE_2D, depthMap);
-  
-  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 {
-		  fprintf(stderr, "Neither arbfp1 or fp30 fragment profiles supported on this system.\n");
-		  exit(1);
-	  }
-  }
-
-  sCgFragmentProgram = cgCreateProgramFromFile(sCgContext, 		
-											   CG_SOURCE, "../src/dual_depth.cg",
-											   sCgFragmentProfile,
-											   NULL, 
-											   NULL);
-
-  if (!cgIsProgramCompiled(sCgFragmentProgram))
-	  cgCompileProgram(sCgFragmentProgram);
-
-  cgGLLoadProgram(sCgFragmentProgram);
-  cgGLBindProgram(sCgFragmentProgram);
- // Debug << "LAST LISTING----" << cgGetLastListing(sCgContext) << "----\n";
-
-  Debug << "---- PROGRAM BEGIN ----\n" << 
-	  cgGetProgramString(sCgFragmentProgram, CG_COMPILED_PROGRAM) << "---- PROGRAM END ----\n";
 }
 
@@ -617,4 +582,9 @@
 											   BeamSampleStatistics &stat)
 {
+	// create beam mesh if not already doen
+	//TODO: should this be done here?
+	
+	beam.CreateMesh(2.0f * Magnitude(mSceneGraph->GetBox().Diagonal()));
+
 	// TODO: should not be done every time here
 	// only back faces are interesting for the depth pass
@@ -636,10 +606,12 @@
 	// would distribute the 'efective viewpoints' of the object surface and thus
 	// with a few viewpoints better sample the vipoint space....
-  
-	int viewPointSamples = sqrt((float)desiredSamples);
-
+  //TODO: remove
+	//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;
-	
+	int directionalSamples = desiredSamples / viewPointSamples;
+	
+	Debug << "directional samples: " << directionalSamples << endl;
 	for (int i = 0; i < viewPointSamples; ++ i) 
 	{
@@ -674,25 +646,34 @@
 													const Vector3 viewPoint,
 													Beam &beam,
-													const int desiredSamples,
+													const int samples,
                                                     BeamSampleStatistics &stat)
 {
-	// 1. setup the view port to match the desired samples
-	glViewport(0, 0, desiredSamples, desiredSamples);
+    // 1. setup the view port to match the desired samples
+	glViewport(0, 0, GetWidth(), GetHeight());
 
 	// 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 depth map
+
+	// front depth buffer must bé 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);
-	glEnable(GL_STENCIL_TEST);
 	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_INCR, GL_INCR, GL_INCR);
+	glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
 
 #if 0
@@ -713,9 +694,34 @@
 
 #endif	
+	// reset clear function
+	glClearDepth(clearDepth);
+
+	// copy contents of depth buffer into depth texture
+	// depth buffer holds ray origins
+	glBindTexture(GL_TEXTURE_2D, frontDepthMap);	
+	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
+
+
+#if 0
+	// only the samples which are inside the beam AND on the source object
+	// should be considered => only where stencil == 2
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	glStencilFunc(GL_ALWAYS, 0x2, 0x2);
+	glStencilOp(GL_INCR, GL_INCR, GL_INCR);
+
+	// render back face of frustum beam
+	RenderMesh(beam.mMesh);
+#endif
+
 
 	// 4. set back to normal rendering and clear the ray termination depth buffer
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 	glColorMask(1, 1, 1, 1);
-	
+	glDepthMask(1);
+	glEnable(GL_DEPTH_TEST);
+	glDisable(GL_STENCIL_TEST);	
+	glEnable(GL_CULL_FACE);
+	glCullFace(GL_BACK);
+
 	// 5. render all objects inside the beam using id based false color
 	//    (objects can be compiled to a gl list now so that subsequent rendering for
@@ -743,5 +749,8 @@
 		ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
 		for (it = beam.mObjects.begin(); it != it_end; ++ it)
-			RenderIntersectable(*it);
+		{
+			if (*it != sourceObject)
+				RenderIntersectable(*it);
+		}
 		
 		glEndList();
@@ -750,29 +759,28 @@
 #else
 	ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
-		for (it = beam.mObjects.begin(); it != it_end; ++ it)
+	for (it = beam.mObjects.begin(); it != it_end; ++ it)
+	{	
+		if (*it != sourceObject)
 			RenderIntersectable(*it);
+	}
 #endif
 
-	// remove objects again
-	if (beam.mFlags & !Beam::STORE_OBJECTS)
-		beam.mObjects.clear();
-
-	// bind ray origin depth buffer
-	glBindTexture(GL_TEXTURE_2D, depthMap);
-    glEnable(GL_TEXTURE_2D);
-	
-
-	//Read the depth buffer into the shadow map texture
-	glBindTexture(GL_TEXTURE_2D, depthMap);
-	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
-
-	
-	// 6. Now we have a two depth buffers defining the ray origin and termination
+	
+    // 6. Now we have a two depth buffers defining the ray origin and termination
 	//    only rays which have non-zero entry in the origin buffer are valid since
 	//    they realy start on the object surface (this can also be tagged by setting a
 	//    stencil buffer bit at step 3)
+	
+	glDisable(GL_STENCIL_TEST);
+	//glEnable(GL_STENCIL_TEST);
 	glStencilFunc(GL_EQUAL, 0x1, 0x1);
- 
-	//cgGLBindProgram(sCgFragmentProgram);
+	//glStencilFunc(GL_EQUAL, 0x2, 0x2);
+	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+	// bind depth texture
+	glEnable(GL_TEXTURE_2D);
+	
+	// bind depth cull pixel shader
+	cgGLBindProgram(sCgFragmentProgram);
 	cgGLEnableProfile(sCgFragmentProfile);
 
@@ -785,4 +793,6 @@
 
 	// now 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);
@@ -817,6 +827,6 @@
 								 GL_PIXEL_COUNT_NV,
 								 &pixelCount);
-
-		Debug << "visble pixels: " << pixelCount << endl;
+		if (pixelCount)
+			Debug << "view cell " << (*vit)->GetId() << " visible pixels: " << pixelCount << endl;
 	}
 	
@@ -828,13 +838,27 @@
 	// 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 threashold ... 
-
+	// (new viewcell has been discovered) or relative contribution greater than a threshold ... 
+
+	ObjectContainer pvsObj;
+	stat.pvsSize = ComputePvs(beam.mObjects, pvsObj);
+	
+	
+#if 0
+	// copy contents of back depth buffer into depth texture
+	// depth buffer holds ray origins
+	glBindTexture(GL_TEXTURE_2D, backDepthMap);	
+	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
+#endif
+	// reset 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 again
+	if (beam.mFlags & !Beam::STORE_OBJECTS)
+		beam.mObjects.clear();
 }
 
@@ -845,7 +869,7 @@
 	{
 		const int n = numQueries - (int)sQueries.size();
-		int *newQueries = new int[n];
-
-		glGenOcclusionQueriesNV(n, (unsigned int *)&newQueries);
+		unsigned int *newQueries = new unsigned int[n];
+
+		glGenOcclusionQueriesNV(n, (unsigned int *)newQueries);
 
 		for (int i = 0; i < n; ++ i)
@@ -854,5 +878,5 @@
 		}
 
-		delete newQueries;
+		delete [] newQueries;
 	}
 }
@@ -860,31 +884,153 @@
 
 void GlRendererBuffer::SetupProjectionForViewPoint(const Vector3 &viewPoint, 
-												 const Beam &beam, 
-												 Intersectable *sourceObject)
+												   const Beam &beam, 
+												   Intersectable *sourceObject)
 {
 	float left, right, bottom, top, znear, zfar;
 
-	beam.ComputeFrustum(left, right, bottom, top, znear, zfar,
-						mSceneGraph->GetBox());
-
+	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);
-
-    const Vector3 eye = viewPoint + beam.GetMainDirection();
-	const Vector3 up;//AbitraryNormal(eye);
-
-	gluLookAt(eye.x, eye.y, eye.z, 
-			  viewPoint.x, viewPoint.y, viewPoint.z, 
+	//glFrustum(-1, 1, -1, 1, 1, 20000);
+
+    const Vector3 center = viewPoint + beam.GetMainDirection() * (zfar - znear) * 0.3;
+	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()
+{
+	GlRenderer::InitGL();
+	// 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);
  
-
-/***************************************************************/
-/*             GlDebuggerWidget implementation				   */
-/***************************************************************/
-
-
-GlDebuggerWidget::GlDebuggerWidget(QWidget *parent, GlRendererBuffer *buf)
+  Debug << "---- PROGRAM BEGIN ----\n" << 
+	  cgGetProgramString(sCgFragmentProgram, CG_COMPILED_PROGRAM) << "---- PROGRAM END ----\n";
+}
+
+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);
+			obj = *oit;
+			if (!obj->Mailed())
+			{
+				obj->Mail();
+				++ pvsSize;
+				pvs.push_back(obj);
+			}
+		}
+	}
+
+	return pvsSize;
+}
+
+/***********************************************************************/
+/*                     GlDebuggerWidget implementation				   */
+/***********************************************************************/
+
+
+GlDebuggerWidget::GlDebuggerWidget(GlRendererBuffer *buf, QWidget *parent)
       : QGLWidget(QGLFormat(QGL::SampleBuffers), parent), mRenderBuffer(buf)
 {
@@ -932,11 +1078,14 @@
 	// draw a spinning cube into the pbuffer..
 	mRenderBuffer->makeCurrent();
-	//mRenderBuffer->SampleBeamContributions();
+	
+	BeamSampleStatistics stats;
+	mRenderBuffer->SampleBeamContributions(mSourceObject, mBeam, mSamples, stats);
+
 	glFlush();
 
-    // rendering directly to a texture is not supported on X11, unfortunately
+	// 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
+    // and use the pbuffer contents as a texture when rendering the
     // background and the bouncing cubes
     makeCurrent();
@@ -962,5 +1111,5 @@
 	// set up the pbuffer context
     mRenderBuffer->makeCurrent();
-	initCommon();
+	/*mRenderBuffer->InitGL();
 
 	glViewport(0, 0, mRenderBuffer->size().width(), mRenderBuffer->size().height());
@@ -972,6 +1121,6 @@
 	glLoadIdentity();
 
-	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-
+	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);*/
+	
 	// generate a texture that has the same size/format as the pbuffer
     dynamicTexture = mRenderBuffer->generateDynamicTexture();
