Index: GTP/trunk/Lib/Vis/Preprocessing/src/QtGlRenderer/QtGlRenderer.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/QtGlRenderer/QtGlRenderer.cpp	(revision 1252)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/QtGlRenderer/QtGlRenderer.cpp	(revision 1252)
@@ -0,0 +1,1840 @@
+#include "Mesh.h"
+#include "glInterface.h"
+#include "OcclusionQuery.h"
+#include "QtGlRenderer.h"
+#include "ViewCellsManager.h"
+#include "SceneGraph.h"
+#include "Pvs.h"
+#include "Viewcell.h"
+#include "Beam.h"
+#include "KdTree.h"
+#include "Environment.h"
+#include <Cg/cg.h>
+#include <Cg/cgGL.h>
+
+#include <QVBoxLayout>
+
+namespace GtpVisibilityPreprocessor {
+
+class ViewCellsManager;
+
+static CGcontext sCgContext = NULL;
+static CGprogram sCgFragmentProgram = NULL;
+static CGprofile sCgFragmentProfile;
+
+GLuint frontDepthMap;
+GLuint backDepthMap;
+
+const int depthMapSize = 512;
+
+//static vector<OcclusionQuery *> sQueries;
+
+QtGlRendererWidget *rendererWidget = NULL;
+QtGlDebuggerWidget *debuggerWidget = NULL;
+
+
+static inline bool ilt(Intersectable *obj1, Intersectable *obj2)
+{
+	return obj1->mId < obj2->mId;
+}
+
+
+static void handleCgError() 
+{
+    Debug << "Cg error: " << cgGetErrorString(cgGetError()) << endl;
+    exit(1);
+}
+
+void
+QtGlRendererBuffer::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 << " ";
+}
+
+
+QtGlRendererBuffer::~QtGlRendererBuffer()
+{
+	if (sCgFragmentProgram)
+		cgDestroyProgram(sCgFragmentProgram);
+	if (sCgContext)
+		cgDestroyContext(sCgContext);
+}
+
+
+void
+QtGlRendererBuffer::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();
+
+}
+  
+
+
+QtGlRendererBuffer::QtGlRendererBuffer(const int w,
+									   const int h,
+									   SceneGraph *sceneGraph,
+									   ViewCellsManager *viewcells,
+									   KdTree *tree):
+QGLPixelBuffer(QSize(w, h)), GlRendererBuffer(sceneGraph, viewcells, tree) {
+ 
+  Environment::GetSingleton()->GetIntValue("Preprocessor.pvsRenderErrorSamples", mPvsStatFrames);
+  mPvsErrorBuffer.resize(mPvsStatFrames);
+  ClearErrorBuffer();
+
+  mPixelBuffer = NULL;
+  
+  makeCurrent();
+  InitGL();
+  doneCurrent();
+  
+}
+
+float
+QtGlRendererBuffer::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
+	ObjectPvsMap::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();
+	  string str = mSnapPrefix + filename;
+	  QString qstr(str.c_str());
+
+	  im.save(qstr, "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
+	  ObjectPvsMap::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);
+	  str = mSnapPrefix + filename;
+	  qstr = str.c_str();
+	  im.save(qstr, "PNG");
+	  glPopAttrib();
+	}
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+  }
+
+  if (viewcell && mViewCellsManager->GetMaxFilterSize() > 0)
+	mViewCellsManager->DeleteLocalMergeTree(viewcell);
+  
+  return pErrorPixels;
+}
+
+
+void
+QtGlRendererBuffer::ClearErrorBuffer()
+{
+  for (int i=0; i < mPvsStatFrames; i++) {
+	mPvsErrorBuffer[i].mError = 1.0f;
+  }
+}
+
+
+void
+QtGlRendererBuffer::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 QtGlRendererBuffer::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 QtGlRendererBuffer::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(mOcclusionQueries, (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)
+	{
+		mOcclusionQueries[queryIdx ++]->BeginQuery();
+
+		RenderIntersectable(*vit);
+		
+		mOcclusionQueries[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 = mOcclusionQueries[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 QtGlRendererBuffer::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 QtGlRendererBuffer::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 QtGlRendererBuffer::ComputeRays(Intersectable *sourceObj, VssRayContainer &rays)
+{
+	for (int i = 0; i < depthMapSize * depthMapSize; ++ i)
+	{
+		//todo glGetTexImage()
+	}
+}
+
+
+
+int QtGlRendererBuffer::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;
+}
+
+
+
+void
+QtGlRendererWidget::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
+QtGlRendererWidget::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
+	ObjectPvsMap::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
+QtGlRendererWidget::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
+QtGlRendererWidget::mousePressEvent(QMouseEvent *e)
+{
+  int x = e->pos().x();
+  int y = e->pos().y();
+
+  mousePoint.x = x;
+  mousePoint.y = y;
+  
+}
+
+void
+QtGlRendererWidget::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
+QtGlRendererWidget::mouseReleaseEvent(QMouseEvent *)
+{
+
+
+}
+
+void
+QtGlRendererWidget::resizeGL(int w, int h)
+{
+  SetupProjection(w, h);
+  updateGL();
+}
+
+void
+QtGlRendererWidget::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
+QtGlRendererWidget::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
+QtGlRendererWidget::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;
+  }
+}
+
+  
+
+QtGlRendererWidget::QtGlRendererWidget(SceneGraph *sceneGraph,
+								   ViewCellsManager *viewcells,
+								   KdTree *tree,
+								   QWidget * parent,
+								   const QGLWidget * shareWidget,
+								   Qt::WFlags f
+								   )
+  :
+  GlRendererWidget(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 QtRendererControlWidget(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
+QtGlRendererWidget::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 = (int)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
+QtGlRendererWidget::SetViewCellGranularity(int number)
+{
+  if (mViewCellsManager) 
+	//  	mViewCellsManager->SetMaxFilterSize(number);
+    mViewCellsManager->CollectViewCells(number);
+
+  updateGL();
+}
+
+void
+QtGlRendererWidget::SetVisibilityFilterSize(int number)
+{
+  if (mViewCellsManager) 
+  	mViewCellsManager->SetMaxFilterSize(number);
+  updateGL();
+}
+
+void
+QtGlRendererWidget::SetSpatialFilterSize(int number)
+{
+  mSpatialFilterSize = 1e-3*number;
+  updateGL();
+}
+
+void
+QtGlRendererWidget::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
+QtGlRendererWidget::SetTopDistance(int number)
+{
+  mTopDistance = number/1000.0f;
+  updateGL();
+}
+
+void
+QtGlRendererWidget::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().CountObjectsInPvs();
+	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().CountObjectsInPvs() / (float)maxPvs;
+	  c = RgbColor(importance, 1.0f - importance, 0.0f);
+	}
+	glColor3f(c.r, c.g, c.b);
+	
+	RenderViewCell(vc);
+  }
+
+  glDisable(GL_CLIP_PLANE0);
+
+}
+
+
+
+
+
+/***********************************************************************/
+/*                     QtGlDebuggerWidget implementation				   */
+/***********************************************************************/
+
+
+QtGlDebuggerWidget::QtGlDebuggerWidget(QtGlRendererBuffer *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"));
+}
+
+
+QtGlDebuggerWidget::~QtGlDebuggerWidget()
+{
+ mRenderBuffer->releaseFromDynamicTexture();
+   glDeleteTextures(1, &dynamicTexture);
+	 
+	 DEL_PTR(mRenderBuffer);
+}
+
+
+
+QtRendererControlWidget::QtRendererControlWidget(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
+QtRendererControlWidget::FocusNextPvsErrorFrame(void)
+{
+  
+  
+}
+
+void
+QtRendererControlWidget::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();
+}
+
+
+void QtGlDebuggerWidget::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 QtGlDebuggerWidget::resizeGL(int w, int h)
+{
+	glViewport(0, 0, w, h);
+}
+
+
+void QtGlDebuggerWidget::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 QtGlDebuggerWidget::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 QtGlDebuggerWidget::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/QtGlRenderer/QtGlRenderer.vcproj
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/QtGlRenderer/QtGlRenderer.vcproj	(revision 1252)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/QtGlRenderer/QtGlRenderer.vcproj	(revision 1252)
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="QtGlRenderer"
+	ProjectGUID="{B85DC7B1-58B6-4912-BD64-8B452630A368}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="2"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="&quot;$(QTDIR)\include\QtCore&quot;;&quot;$(QTDIR)\include\QtGui&quot;;&quot;$(QTDIR)\include&quot;;&quot;$(QTDIR)\include\QtOpenGl&quot;;..\src;..\..\..\..\..\..\NonGTP\Zlib\include;&quot;$(CG_INC_PATH)&quot;"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;QTGLRENDERER_EXPORTS"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"
+				Description="Performing moc on $(InputName).h"
+				CommandLine="&quot;%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp&quot;
+"
+				Outputs="&quot;$(InputDir) moc_$(InputName).cpp&quot;"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="Preprocessor.lib qtmain.lib QtGui4.lib Qt3Support4.lib QAxContainerd.lib QtCore4.lib QtOpenGL4.lib xerces-c_2.lib glew32.lib OpenGL32.Lib glu32.lib cg.lib cgGL.lib"
+				OutputFile="$(OutDir)/QtGlRenderer.dll"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="&quot;$(QTDIR)\lib&quot;;..\..\..\..\..\..\NonGTP\Zlib\lib;&quot;$(CG_LIB_PATH)&quot;;..\src\GL;..\..\..\..\..\..\NonGTP\Xerces\xercesc\lib;&quot;..\lib\$(ConfigurationName)&quot;"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/QtGlRenderer.pdb"
+				SubSystem="2"
+				ImportLibrary="$(OutDir)/QtGlRenderer.lib"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="2"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\src;&quot;$(QTDIR)\include\QtCore&quot;;&quot;$(QTDIR)\include\QtGui&quot;;&quot;$(QTDIR)\include&quot;;&quot;$(QTDIR)\include\QtOpenGl&quot;;..\..\..\..\..\..\NonGTP\Zlib\include;&quot;$(CG_INC_PATH)&quot;"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;QTGLRENDERER_EXPORTS"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="3"/>
+			<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"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="Preprocessor.lib qtmain.lib QtGui4.lib Qt3Support4.lib QAxContainer.lib QtCore4.lib QtOpenGL4.lib xerces-c_2.lib glew32.lib OpenGL32.Lib glu32.lib cg.lib cgGL.lib"
+				OutputFile="$(OutDir)/QtGlRenderer.dll"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="&quot;$(QTDIR)\lib&quot;;..\..\..\..\..\..\NonGTP\Zlib\lib;&quot;$(CG_LIB_PATH)&quot;;&quot;..\lib\$(ConfigurationName)&quot;;..\src\GL;..\..\..\..\..\..\NonGTP\Xerces\xercesc\lib"
+				GenerateDebugInformation="FALSE"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				ImportLibrary="$(OutDir)/QtGlRenderer.lib"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+			<File
+				RelativePath=".\moc_QtGlRenderer.cpp">
+			</File>
+			<File
+				RelativePath=".\QtGlRenderer.cpp">
+			</File>
+			<File
+				RelativePath=".\QtGlRendererDll.cpp">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+			<File
+				RelativePath=".\QtGlRenderer.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>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: GTP/trunk/Lib/Vis/Preprocessing/src/QtGlRenderer/QtGlRenderer.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/QtGlRenderer/QtGlRenderer.h	(revision 1252)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/QtGlRenderer/QtGlRenderer.h	(revision 1252)
@@ -0,0 +1,341 @@
+#ifndef __QTGLRENDERER_H
+#define __QTGLRENDERER_H
+
+#include <QtOpenGL>
+#include <QWaitCondition>
+
+//#include <QGLPixelBuffer>
+
+#include "Vector3.h"
+#include "Containers.h"
+#include "Halton.h"
+#include "Renderer.h"
+#include "GlRenderer.h"
+#include "Beam.h"
+
+class QWidget;
+
+namespace GtpVisibilityPreprocessor {
+
+class SceneGraph;
+class ViewCellsManager;
+class Mesh;
+class MeshInstance;
+class Intersectable;
+class Material;
+class Beam;
+class KdTree;
+class GlRendererBuffer;
+class BeamSampleStatistics;
+class OcclusionQuery;
+class TransformedMeshInstance;
+
+struct VssRayContainer;
+struct PvsRenderStatistics; 
+struct RenderCostSample;
+
+
+class __declspec(dllexport) QtGlRendererBuffer : public QObject, public QGLPixelBuffer, public GlRendererBuffer
+{
+	Q_OBJECT
+public:
+	QtGlRendererBuffer(const int w,
+		const int h,
+		SceneGraph *sceneGraph,
+		ViewCellsManager *viewcells,
+		KdTree *tree);
+
+	~QtGlRendererBuffer();
+
+	/** Evaluates render cost of a point sample.
+	@param sample the render cost sample to be evaluated
+	@param useOcclusionQueries if occlusion queries should be used or item buffer
+	@param threshold number of pixels / samples from where an object is considered visible.
+	*/
+	void EvalRenderCostSample(RenderCostSample &sample,
+		const bool useOcclusionQueries,
+		const int threshold);
+
+	/** Evaluates render cost of a number of point samples. The point samples
+	are distributed uniformly over the defined view space.
+
+	@param numSamples the number of point samples taken
+	@param samples stores the taken point samples in a container
+	@param useOcclusionQueries if occlusion queries should be used or item buffer
+	@param threshold number of pixels / samples from where an object is considered visible.
+	*/
+	void SampleRenderCost(const int numSamples, 
+		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(); }
+
+
+ 
+  void SampleBeamContributions(
+							   Intersectable *sourceObject,
+							   Beam &beam,
+							   const int samples,
+							   BeamSampleStatistics &stat
+							   );
+
+  void
+  SampleViewpointContributions(
+							   Intersectable *sourceObject,
+							   const Vector3 viewPoint,
+							   Beam &beam,
+							   const int desiredSamples,
+							   BeamSampleStatistics &stat
+							   );
+
+  void InitGL();
+
+  /** Computes rays from information gained with hw sampling-
+  */
+  void ComputeRays(Intersectable *sourceObj, VssRayContainer &rays);
+
+  int ComputePvs() const;
+
+  float
+  GetPixelError(int &pvsSize);
+
+  int ComputePvs(ObjectContainer &objects, ObjectContainer &pvs) const;
+     
+   
+private:
+  	
+	void SetupProjectionForViewPoint(const Vector3 &viewPoint, 
+									 const Beam &beam, 
+									 Intersectable *sourceObject);
+
+
+public:
+  signals:
+	void UpdatePvsErrorItem(int i, GlRendererBuffer::PvsErrorEntry &);
+};
+
+
+class __declspec(dllexport) QtRendererControlWidget : public QWidget
+{
+  Q_OBJECT
+public:
+
+  QListWidget *mPvsErrorWidget;
+
+  QtRendererControlWidget(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 __declspec(dllexport) QtGlRendererWidget : public QGLWidget, public GlRendererWidget
+{
+  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;
+
+  QtRendererControlWidget *mControlWidget;
+  
+  QtGlRendererWidget(SceneGraph *sceneGraph,
+				   ViewCellsManager *viewcells,
+				   KdTree *tree,
+				   QWidget * parent = 0, const QGLWidget * shareWidget = 0, Qt::WFlags f = 0
+				   );
+
+  QtGlRendererWidget() {};
+
+  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();
+  }
+
+
+};
+
+
+class QtGlDebuggerWidget : public QGLWidget
+{
+	Q_OBJECT
+public:
+    QtGlDebuggerWidget(QtGlRendererBuffer *buf, QWidget *parent = NULL);
+    ~QtGlDebuggerWidget();
+    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();
+
+  
+	 QtGlRendererBuffer *mRenderBuffer;
+
+	 Beam mBeam;
+	 int mSamples;
+	 Intersectable *mSourceObject;
+
+private:
+    GLuint dynamicTexture;
+    int timerId;
+};
+
+extern QtGlDebuggerWidget *debuggerWidget;
+
+};
+
+#endif
+
Index: GTP/trunk/Lib/Vis/Preprocessing/src/QtGlRenderer/QtGlRenderer.sln
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/QtGlRenderer/QtGlRenderer.sln	(revision 1252)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/QtGlRenderer/QtGlRenderer.sln	(revision 1252)
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QtGlRenderer", "QtGlRenderer.vcproj", "{B85DC7B1-58B6-4912-BD64-8B452630A368}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		Debug = Debug
+		Release = Release
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{B85DC7B1-58B6-4912-BD64-8B452630A368}.Debug.ActiveCfg = Debug|Win32
+		{B85DC7B1-58B6-4912-BD64-8B452630A368}.Debug.Build.0 = Debug|Win32
+		{B85DC7B1-58B6-4912-BD64-8B452630A368}.Release.ActiveCfg = Release|Win32
+		{B85DC7B1-58B6-4912-BD64-8B452630A368}.Release.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
