Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h	(revision 2530)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h	(revision 2538)
@@ -862,25 +862,19 @@
 	/// if view cells should be exported
 	bool mExportViewCells;
-
 	// if only valid view cells should be considered for processing
 	bool mOnlyValidViewCells;
-
 	/// if rays should be used to collect merge candidates
 	bool mUseRaysForMerge;
-
 	/// if there should be an additional merge step after the subdivision
 	bool mMergeViewCells;
-
 	/// the width of the box filter
 	float mFilterWidth;
 	/// Maximal size of the filter in terms of contributing view cells
 	int mMaxFilterSize;
-	
-	// only for debugging
+	/// only for debugging: stores some rays used during view cell construction
 	VssRayContainer storedRays;
-
+	/// if kd node based pvs is used for preprocessing
 	bool mUseKdPvs;
-	bool mUseKdPvsAfterFiltering;
-
+	/// types of distributions used for sampling
 	MixtureDistribution *mMixtureDistribution;
 
@@ -900,10 +894,9 @@
 	bool mExportPvs;
 
-	static int sRenderCostEvaluationType;
-
 	/// if view cells geometry should be used from other sources
 	bool mUsePredefinedViewCells;
-
+	/// the weight for one triangle in the heuristics
 	float mTriangleWeight;
+	/// the weight for one object (= one entity issued with one draw call) in the heuristics
 	float mObjectWeight;
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 2530)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 2538)
@@ -1417,9 +1417,4 @@
 					"50");
 
-	RegisterOption("ViewCells.renderCostEvaluationType",
-					optString,
-					"view_cells_render_cost_evaluation=",
-					"perobject");
-
 	RegisterOption("ViewCells.active",
 					optInt,
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.cpp	(revision 2231)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.cpp	(revision 2538)
@@ -28,23 +28,21 @@
 	{
 	case MESH_INSTANCE:
-		return "mesh_instance\n";
-
+		return "mesh instance";
 	case TRANSFORMED_MESH_INSTANCE:
-		return "transformed_mesh_instance\n";
-
+		return "transformed mesh instance";
 	case SPHERE:
-		return "sphere\n";
-
+		return "sphere";
 	case VIEW_CELL:
-		return "view cell\n";
-
+		return "view cell";
 	case OGRE_MESH_INSTANCE:
-		return "ogre_mesh_instance\n";
-
+		return "ogre_mesh_instance";
 	case KD_INTERSECTABLE:
-		return "kd_intersectable\n";
-
+		return "kd";
+	case TRIANGLE_INTERSECTABLE:
+		return "triangle";
+	case BVH_INTERSECTABLE:
+		return "bvh";
 	default:
-		return "unknown\n";
+		return "unknown";
 	}
 }
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.vcproj
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.vcproj	(revision 2530)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.vcproj	(revision 2538)
@@ -123,5 +123,5 @@
 				EnableFiberSafeOptimizations="TRUE"
 				WholeProgramOptimization="FALSE"
-				OptimizeForProcessor="3"
+				OptimizeForProcessor="2"
 				OptimizeForWindowsApplication="TRUE"
 				AdditionalIncludeDirectories="..\src;..\..\..\..\..\..\NonGTP\Devil\include;..\..\..\..\..\..\NonGTP\Zlib\include;..\..\..\..\..\..\NonGTP\Xerces;..\..\..\..\..\..\NonGTP\Boost;..\MultiLevelRayTracing;&quot;$(QTDIR)\include\QtCore&quot;;&quot;$(QTDIR)\include\QtGui&quot;;&quot;$(QTDIR)\include&quot;;&quot;$(QTDIR)\include\QtOpenGl&quot;;&quot;$(CG_INC_PATH)&quot;;Timer;..\src\sparsehash\src\google\sparsehash;..\src\sparsehash\src\windows;..\src\sparsehash\src\google;..\src\sparsehash\src;..\src\ootl\;..\src\ootl\src\;..\src\ootl\src\cpp;..\src\ootl\src\cpp\include\;..\src\ootl\src\include\ootl;..\src\ootl\src\include\ootl\sandbox;..\src\ootl\src\cpp\include\ootl\mswin"
Index: GTP/trunk/Lib/Vis/Preprocessing/src/QtInterface/QtGlRenderer.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/QtInterface/QtGlRenderer.cpp	(revision 2530)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/QtInterface/QtGlRenderer.cpp	(revision 2538)
@@ -15,4 +15,6 @@
 #include "QtPreprocessorThread.h"
 #include "Material.h"
+#include "IntersectableWrapper.h"
+
 
 #define USE_CG 1
@@ -109,12 +111,9 @@
   
   ObjectPvs pvs;
-  if (1) {
-	pvs = viewcell->GetPvs();
-  } else {
-	mViewCellsManager->ApplyFilter2(viewcell,
-									false,
-									1.0f,
-									pvs);
-  }
+  
+  if (1) 
+	  pvs = viewcell->GetPvs();
+  else 
+	  mViewCellsManager->ApplyFilter2(viewcell,	false, 1.0f, pvs);
   
   //  cout<<"pvs size"<<pvs.GetSize()<<endl<<flush;
@@ -128,5 +127,5 @@
   glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); 
   
-  // 	// Render PVS
+  // Render PVS
   ObjectPvsIterator it = pvs.GetIterator();
   
@@ -349,102 +348,209 @@
 
 
-
-void
-QtGlRendererWidget::RenderPvs()
-{
+bool QtGlRendererWidget::PvsChanged(ViewCell *viewCell) const
+{
+	if (viewCell != mPvsCache.mViewCell)
+		return true;
+
+	if (viewCell->GetPvs().GetSize() != mPvsCache.mUnfilteredPvsSize)
+		return true;
+
+	return false;
+}
+
+
+void QtGlRendererWidget::_RenderPvs()
+{
+	mUseFalseColors = false;
+
+	int offset = mObjects.size() * 3;
+	char *arrayPtr = mUseVbos ? NULL : (char *)mData;
 	
-  Intersectable::NewMail();
-
-  ViewCell *viewcell = NULL;
-
-  if (mDetectEmptyViewSpace) 
-	glEnable( GL_CULL_FACE );
-  else
-	glDisable( GL_CULL_FACE );
-  
-  viewcell = mViewCellsManager->GetViewCell(mViewPoint, true);
-  
-  if (viewcell) {
-	// copy the pvs so that it can be filtered...
-	
-	//	mPvsCache.mPvs;
-	
-	if (mPvsCache.mViewCell != viewcell) {
-	  mPvsCache.Reset();
-	  mPvsCache.mViewCell = viewcell;
-	  
-	  if (mUseSpatialFilter) {
-		// 9.11. 2006 -> experiment with new spatial filter
+	glVertexPointer(3, GL_FLOAT, 0, (char *)arrayPtr);
+	glNormalPointer(GL_FLOAT, 0, (char *)arrayPtr + offset * sizeof(Vector3));
+	glDrawElements(GL_TRIANGLES, mIndexBufferSize, GL_UNSIGNED_INT, mIndices);
+}
+
+
+void QtGlRendererWidget::_UpdatePvsIndices()
+{
+	mIndexBufferSize = 0;
+	KdNode::NewMail();
+
+	mPvsSize = mPvsCache.mPvs.GetSize();
+
+	ObjectPvsIterator it = mPvsCache.mPvs.GetIterator();
+
+	for (; it.HasMoreEntries(); ) 
+	{
+		Intersectable *obj = it.Next();
+		KdNode *node = static_cast<KdIntersectable *>(obj)->GetItem();
+		_UpdatePvsIndices(node);
+	}
+}
+
+
+void QtGlRendererWidget::_UpdatePvsIndices(KdNode *node)
+{
+	if (node->Mailed())
+		return;
+
+	node->Mail();
+
+	if (!node->IsLeaf()) 
+	{
+		KdInterior *in = static_cast<KdInterior *>(node);
+		
+		_UpdatePvsIndices(in->mBack);
+		_UpdatePvsIndices(in->mFront);
+	} 
+	else 
+	{
+		KdLeaf *leaf = static_cast<KdLeaf *>(node);
+
+		leaf->mIndexBufferStart = mIndexBufferSize;
+
+		for (size_t i = 0; i < leaf->mObjects.size(); ++ i)
+		{
+			TriangleIntersectable *obj = 
+				static_cast<TriangleIntersectable *>(leaf->mObjects[i]);
+
+			// check if already rendered
+			if (!obj->Mailed())
+			{
+				obj->Mail();
+
+				mIndices[mIndexBufferSize + 0] = (obj->GetId() - 1) * 3 + 0;
+				mIndices[mIndexBufferSize + 1] = (obj->GetId() - 1) * 3 + 1;
+				mIndices[mIndexBufferSize + 2] = (obj->GetId() - 1) * 3 + 2;
+
+				mIndexBufferSize += 3;
+			}
+		}
+
+		leaf->mIndexBufferSize = mIndexBufferSize - leaf->mIndexBufferStart;
+	}
+}
+
+
+void QtGlRendererWidget::RenderPvs()
+{
+	if (mUseVbos) 
+		glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVboId);
+
+	EnableDrawArrays();
+
+	Intersectable::NewMail();
+	ViewCell *viewcell = NULL;
+
+	if (mDetectEmptyViewSpace) 
+		glEnable(GL_CULL_FACE);
+	else
+		glDisable(GL_CULL_FACE);
+
+	viewcell = mViewCellsManager->GetViewCell(mViewPoint, true);
+
+	if (viewcell) 
+	{
+		// copy the pvs so that it can be filtered...
+		if (PvsChanged(viewcell)) 
+		{
+			mPvsCache.Reset();
+			mPvsCache.mViewCell = viewcell;
+			mPvsCache.mUnfilteredPvsSize = viewcell->GetPvs().GetSize();
+
+			if (mUseSpatialFilter) 
+			{
+				// 9.11. 2006 -> experiment with new spatial filter
 #if 0
-		mViewCellsManager->ApplySpatialFilter(mKdTree,
-											  mSpatialFilterSize*
-											  Magnitude(mViewCellsManager->GetViewSpaceBox().Size()),
-											  mPvsCache.mPvs);
+				mViewCellsManager->ApplySpatialFilter(mKdTree,
+					mSpatialFilterSize*
+					Magnitude(mViewCellsManager->GetViewSpaceBox().Size()),
+					mPvsCache.mPvs);
 #else
-		// mSpatialFilter size is in range 0.001 - 0.1
-		mViewCellsManager->ApplyFilter2(viewcell,
-										mUseFilter,
-										100*mSpatialFilterSize,
-										mPvsCache.mPvs,
-										&mPvsCache.filteredBoxes
-										);
+				//cout<<"updating filter" << endl;
+				// mSpatialFilter size is in range 0.001 - 0.1
+				mViewCellsManager->ApplyFilter2(viewcell,
+					mUseFilter,
+					100 * mSpatialFilterSize,
+					mPvsCache.mPvs,
+					&mPvsCache.filteredBoxes
+					);
 #endif
-	  } else
-		mPvsCache.mPvs = viewcell->GetPvs();
-	  
-	  emit PvsUpdated();
+			} 
+			else
+			{
+				mPvsCache.mPvs = viewcell->GetPvs();
+			}
+
+			/// update the indices for rendering
+			_UpdatePvsIndices();
+
+			emit PvsUpdated();
+		}
+
+		Intersectable::NewMail();
+		PvsData pvsData;
+
+		// Render PVS
+		if (mUseSpatialFilter && mRenderBoxes) 
+		{
+			for (int i=0; i < mPvsCache.filteredBoxes.size(); i++)
+				RenderBox(mPvsCache.filteredBoxes[i]);
+		} 
+		else 
+		{
+			if (!mRenderVisibilityEstimates)
+			{
+				_RenderPvs();
+			}
+			else
+			{
+				ObjectPvsIterator it = mPvsCache.mPvs.GetIterator();
+
+				mPvsSize = mPvsCache.mPvs.GetSize();
+				for (; it.HasMoreEntries(); ) 
+				{
+					Intersectable *object = it.Next(pvsData);
+
+					//float visibility = mTransferFunction*log10(entry.mData.mSumPdf + 1); // /5.0f
+					// glColor3f(visibility, 0.0f, 0.0f);
+					//cerr << "sumpdf: " << pvsData.mSumPdf << endl;
+					RgbColor color = RainbowColorMapping(mTransferFunction*log10(pvsData.mSumPdf + 1));
+					glColor3f(color.r, color.g, color.b);
+
+					mUseForcedColors = true;
+					RenderIntersectable(object);
+					mUseForcedColors = false;
+				}
+			}
+		}
+
+		if (mRenderFilter) 
+		{
+			mWireFrame = true;
+			RenderIntersectable(viewcell);
+			glPushMatrix();
+			glTranslatef(mViewPoint.x, mViewPoint.y, mViewPoint.z);
+			glScalef(5.0f,5.0f,5.0f);
+			glPushAttrib(GL_CURRENT_BIT);
+			glColor3f(1.0f, 0.0f, 0.0f);
+			//	  gluSphere((::GLUquadric *)mSphere,
+			//				1e-3*Magnitude(mViewCellsManager->GetViewSpaceBox().Size()), 6, 6);
+			glPopAttrib();
+			glPopMatrix();
+			mWireFrame = false;
+		}
+	} 
+	else 
+	{
+		/*ObjectContainer::const_iterator oi = mObjects.begin();
+		for (; oi != mObjects.end(); oi++)
+			RenderIntersectable(*oi);*/
+		RenderScene();
 	}
 
-	Intersectable::NewMail();
-
-	PvsData pvsData;
-
-	// Render PVS
-	if (mUseSpatialFilter && mRenderBoxes) {
-	  for (int i=0; i < mPvsCache.filteredBoxes.size(); i++)
-		RenderBox(mPvsCache.filteredBoxes[i]);
-	} else {
-	  ObjectPvsIterator it = mPvsCache.mPvs.GetIterator();
-	  
-	  mPvsSize = mPvsCache.mPvs.GetSize();
-	  for (; it.HasMoreEntries(); ) {
-		Intersectable *object = it.Next(pvsData);
-		
-		if (mRenderVisibilityEstimates) {
-		  //float visibility = mTransferFunction*log10(entry.mData.mSumPdf + 1); // /5.0f
-		  //		  glColor3f(visibility, 0.0f, 0.0f);
-			//cerr << "sumpdf: " << pvsData.mSumPdf << endl;
-		  RgbColor color = RainbowColorMapping(mTransferFunction*log10(pvsData.mSumPdf + 1));
-		  glColor3f(color.r, color.g, color.b);
-		  
-		  mUseForcedColors = true;
-		  RenderIntersectable(object);
-		  mUseForcedColors = false;
-		} else {
-		  mUseForcedColors = false;
-		  RenderIntersectable(object);
-		}
-	  }
-	}
-	
-	if (mRenderFilter) {
-	  mWireFrame = true;
-	  RenderIntersectable(viewcell);
-	  glPushMatrix();
-	  glTranslatef(mViewPoint.x, mViewPoint.y, mViewPoint.z);
-	  glScalef(5.0f,5.0f,5.0f);
-	  glPushAttrib(GL_CURRENT_BIT);
-	  glColor3f(1.0f, 0.0f, 0.0f);
-	  //	  gluSphere((::GLUquadric *)mSphere,
-	  //				1e-3*Magnitude(mViewCellsManager->GetViewSpaceBox().Size()), 6, 6);
-	  glPopAttrib();
-	  glPopMatrix();
-	  mWireFrame = false;
-	}
-  } else {
-	ObjectContainer::const_iterator oi = mObjects.begin();
-	for (; oi != mObjects.end(); oi++)
-	  RenderIntersectable(*oi);
-  }
+	//DisableDrawArrays();
+	//glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
 }
 
@@ -466,10 +572,10 @@
   glColor3f(0.0f, 0.8f, 0.2f);
 
-  // 	// Render PVS
+  // Render PVS
   RenderPvs();
   
   glEnable(GL_STENCIL_TEST); 
   
-  //  mUseFalseColors = true;
+  //mUseFalseColors = true;
   
   glDisable(GL_LIGHTING);
@@ -501,5 +607,5 @@
   int pixelCount = query->GetQueryResult();
   pErrorPixels = ((float)pixelCount)/(GetWidth()*GetHeight());
-  cout<<"error pixels="<<pixelCount<<endl;
+  if (0) cout<<"error pixels="<<pixelCount<<endl;
 
   mRenderError = pErrorPixels;
@@ -509,6 +615,12 @@
 
 
-void
-QtGlRendererWidget::mousePressEvent(QMouseEvent *e)
+void QtGlRendererWidget::timerEvent(QTimerEvent *event) 
+{
+	//std::cout << "Timer ID:" << event->timerId();
+	update();
+}
+
+
+void QtGlRendererWidget::mousePressEvent(QMouseEvent *e)
 {
   int x = e->pos().x();
@@ -523,30 +635,33 @@
 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();
-
-  int diffx = -(mousePoint.x - x);
-  int diffy = -(mousePoint.y - 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();
+	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();
+
+	int diffx = -(mousePoint.x - x);
+	int diffy = -(mousePoint.y - 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();
 }
 
@@ -554,6 +669,4 @@
 QtGlRendererWidget::mouseReleaseEvent(QMouseEvent *)
 {
-
-
 }
 
@@ -584,5 +697,5 @@
   RenderInfo();
 
-  mFrame++;
+  mFrame ++;
   
 }
@@ -707,4 +820,8 @@
   mRenderVisibilityEstimates = false;
   mTransferFunction = 0.2f;
+  mIndexBufferSize = 0;
+   
+  const int delay = 500; // half a second
+  timerId = startTimer(delay);
 
   bool tmp;
@@ -825,5 +942,5 @@
 	  currentCost = costFunction[currentPos];
 #if 1	
-	cout<<"costFunction.size()="<<costFunction.size()<<endl;
+	cout<<"costFunction.size()="<<(int)costFunction.size()<<endl;
 	cout<<"CP="<<currentPos<<endl;
 	cout<<"MC="<<maxCost<<endl;
@@ -913,5 +1030,5 @@
   int vc = 0;
   if (mViewCellsManager)
-	vc = mViewCellsManager->GetViewCells().size();
+	vc = (int)mViewCellsManager->GetViewCells().size();
 
   int filter = 0;
@@ -1070,9 +1187,7 @@
 
 
-
-
-/***********************************************************************/
-/*                     QtGlDebuggerWidget implementation				   */
-/***********************************************************************/
+/*********************************************************************/
+/*                   QtGlDebuggerWidget implementation               */
+/*********************************************************************/
 
 
@@ -1094,5 +1209,4 @@
 	 DEL_PTR(mRenderBuffer);
 }
-
 
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/QtInterface/QtGlRenderer.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/QtInterface/QtGlRenderer.h	(revision 1997)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/QtInterface/QtGlRenderer.h	(revision 2538)
@@ -148,4 +148,5 @@
   float mTransferFunction;
 
+  unsigned int mIndexBufferSize;
   
   QtRendererControlWidget *mControlWidget;
@@ -177,21 +178,15 @@
   void resizeGL(int w, int h);
   void paintGL();
-  void timerEvent(QTimerEvent *) {
-	  update();
-  }
-
+  void timerEvent(QTimerEvent *event);
   void mousePressEvent(QMouseEvent *);
   void mouseReleaseEvent(QMouseEvent *);
   void mouseMoveEvent(QMouseEvent *);
 
-  void keyPressEvent ( QKeyEvent * e ) ;
-
-  void
-  RenderPvs();
-
-  float
-  RenderErrors();
-  void
-  RenderInfo();
+  void keyPressEvent(QKeyEvent * e);
+
+  void RenderPvs();
+
+  float RenderErrors();
+  void RenderInfo();
 
   virtual int GetWidth() const { return width(); }
@@ -211,4 +206,7 @@
 	show();
   }
+
+  bool PvsChanged(ViewCell *viewcell) const;
+
 
  public slots:
@@ -306,4 +304,9 @@
 	updateGL();
   }
+
+  void _RenderPvs();
+
+  void _UpdatePvsIndices();
+  void _UpdatePvsIndices(KdNode *node);
 
   signals:
Index: GTP/trunk/Lib/Vis/Preprocessing/src/QtInterface/QtGlViewer.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/QtInterface/QtGlViewer.cpp	(revision 1997)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/QtInterface/QtGlViewer.cpp	(revision 2538)
@@ -100,22 +100,22 @@
 QtGlViewer::paintGL()
 {
-  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-  glLoadIdentity();
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	glLoadIdentity();
 
-  float m[4][4];
+	float m[4][4];
 
-  glLoadIdentity();
-  gluLookAt(0.0, 0.0, 1.0,  /* eye is at (0,0,30) */
-						0.0, 0.0, 0.0,      /* center is at (0,0,0) */
-						0.0, 1.0, 0.);      /* up is in positive Y direction */
-  
-  build_rotmatrix(m, manipulatorLastQuat);
-  glMultMatrixf(&m[0][0]);
+	glLoadIdentity();
+	gluLookAt(0.0, 0.0, 1.0,  /* eye is at (0,0,30) */
+		0.0, 0.0, 0.0,      /* center is at (0,0,0) */
+		0.0, 1.0, 0.);      /* up is in positive Y direction */
 
-  float s = scale*20.0f/Magnitude(mRenderer->mSceneGraph->GetBox().Diagonal());
-  glScalef(s, s, s);
-  
-  Vector3 t = -mRenderer->mSceneGraph->GetBox().Center();
-  glTranslatef(t.x, t.y, t.z);
+	build_rotmatrix(m, manipulatorLastQuat);
+	glMultMatrixf(&m[0][0]);
+
+	float s = scale*20.0f/Magnitude(mRenderer->mSceneGraph->GetBox().Diagonal());
+	glScalef(s, s, s);
+
+	Vector3 t = -mRenderer->mSceneGraph->GetBox().Center();
+	glTranslatef(t.x, t.y, t.z);
 
 	RenderScene();
Index: GTP/trunk/Lib/Vis/Preprocessing/src/OspTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/OspTree.h	(revision 2224)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/OspTree.h	(revision 2538)
@@ -377,22 +377,17 @@
 						const Vector3 &termination,
 						ViewCellContainer &viewcells);
-		
 	/** Sets pointer to view cells manager.
 	*/
 	void SetViewCellsManager(ViewCellsManager *vcm);
-
 	/** Writes tree to output stream
 	*/
 	bool Export(OUT_STREAM &stream);
-
 	/** Returns or creates a new intersectable for use in a kd based pvs.
 		The OspTree is responsible for destruction of the intersectable.
 	*/
 	KdIntersectable *GetOrCreateKdIntersectable(KdNode *node);
-
 	/** Collects rays stored in the leaves.
 	*/
 	void CollectRays(VssRayContainer &rays);
-
 	/** Intersects box with the tree and returns the number of intersected boxes.
 		@returns number of view cells found
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 2530)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 2538)
@@ -47,6 +47,4 @@
 
 
-int ViewCellsManager::sRenderCostEvaluationType = 0;
-
 
 template <typename T> class myless
@@ -156,5 +154,4 @@
 	Environment::GetSingleton()->GetIntValue("ViewCells.Filter.maxSize", mMaxFilterSize);
 	Environment::GetSingleton()->GetFloatValue("ViewCells.Filter.width", mFilterWidth);
-	Environment::GetSingleton()->GetIntValue("ViewCells.renderCostEvaluationType", sRenderCostEvaluationType);
 
 	Environment::GetSingleton()->GetBoolValue("ViewCells.exportBboxesForPvs", mExportBboxesForPvs);
@@ -251,21 +248,8 @@
 	}
 
-	Environment::GetSingleton()->GetStringValue("ViewCells.renderCostEvaluationType", buf);
-	
-	if (strcmp(buf, "perobject") == 0)
-	{
-		sRenderCostEvaluationType = ViewCellsManager::PER_OBJECT;
-	}
-	else if (strcmp(buf, "pertriangle") == 0)
-	{
-		sRenderCostEvaluationType = ViewCellsManager::PER_TRIANGLE;
-	}
-	else 
-	{
-		Debug << "error! wrong sampling type" << endl;
-		exit(0);
-	}
-
-    Environment::GetSingleton()->GetStringValue("ViewCells.Visualization.colorCode", buf);
+
+	/** The color code used during visualization.
+	*/
+	Environment::GetSingleton()->GetStringValue("ViewCells.Visualization.colorCode", buf);
 
 	if (strcmp(buf, "PVS") == 0)
@@ -300,5 +284,4 @@
 	Debug << "evaluate view cells: " << mEvaluateViewCells << endl;
 	Debug << "sampling type: " << mSamplingType << endl;
-	Debug << "render cost evaluation type: " << sRenderCostEvaluationType << endl;
 	Debug << "evaluation sampling type: " << mEvaluationSamplingType << endl;
 	Debug << "show visualization: " << mShowVisualization << endl;
@@ -686,6 +669,5 @@
 
 
-Intersectable *
-ViewCellsManager::GetIntersectable(const VssRay &ray, const bool isTermination) const
+Intersectable *ViewCellsManager::GetIntersectable(const VssRay &ray, const bool isTermination) const
 {
 	if (mUseKdPvs)
@@ -693,42 +675,45 @@
 		KdNode *node = GetPreprocessor()->
 			mKdTree->GetPvsNode(isTermination ?	ray.mTermination : ray.mOrigin);
-	  return GetPreprocessor()->mKdTree->GetOrCreateKdIntersectable(node);
+
+		return GetPreprocessor()->mKdTree->GetOrCreateKdIntersectable(node);
 	}
 	else
-	  {
+	{
 		return isTermination ? ray.mTerminationObject : ray.mOriginObject;
-	  }
-}
-
-
-void
-ViewCellsManager::CollectObjects(const AxisAlignedBox3 &box, ObjectContainer &objects)
+	}
+}
+
+
+void ViewCellsManager::CollectObjects(const AxisAlignedBox3 &box, ObjectContainer &objects)
 {
 	GetPreprocessor()->mKdTree->CollectObjects(box, objects);
 }
 
+
 AxisAlignedBox3 ViewCellsManager::GetViewCellBox(ViewCell *vc)
 {
-  Mesh *m = vc->GetMesh();
-  
-  if (m) 
-  {
-	  m->ComputeBoundingBox();
-	  return m->mBox;
-  }
-
-  AxisAlignedBox3 box;
-  box.Initialize();
-  
-  if (!vc->IsLeaf()) {
-	ViewCellInterior *vci = (ViewCellInterior *) vc;
-	
-	ViewCellContainer::iterator it = vci->mChildren.begin();
-	for (; it != vci->mChildren.end(); ++it) {
-	  box.Include(GetViewCellBox(*it));
-	}
-  }
-  
-  return box;
+	Mesh *m = vc->GetMesh();
+
+	if (m) 
+	{
+		m->ComputeBoundingBox();
+		return m->mBox;
+	}
+
+	AxisAlignedBox3 box;
+	box.Initialize();
+
+	if (!vc->IsLeaf()) 
+	{
+		ViewCellInterior *vci = (ViewCellInterior *) vc;
+
+		ViewCellContainer::iterator it = vci->mChildren.begin();
+		for (; it != vci->mChildren.end(); ++it) 
+		{
+			box.Include(GetViewCellBox(*it));
+		}
+	}
+
+	return box;
 }
 
@@ -744,5 +729,6 @@
 	
 	simpleRays.reserve(samplesPerPass);
-	passSamples.reserve(samplesPerPass * 2); // always creates double rays
+	// reserve 2 times the size because always creates double rays
+	passSamples.reserve(samplesPerPass * 2); 
 
 	// create one third of each type
@@ -3313,7 +3299,5 @@
 
   while (pit.HasMoreEntries())
-  {		
       pit.Next()->Mail();
-  }
 
   ObjectPvs nPvs;
@@ -3392,175 +3376,186 @@
 							   )
 {
-  PvsFilterStatistics stats;
-
-  AxisAlignedBox3 vbox = GetViewCellBox(viewCell);
-  Vector3 center = vbox.Center();
-  // copy the PVS
-  Intersectable::NewMail();
-  ObjectPvs basePvs = viewCell->GetPvs();
-  ObjectPvsIterator pit = basePvs.GetIterator();
-
-  pvs.Reserve(viewCell->GetFilteredPvsSize());
-
-  if (!mUseKdPvs)
-  {
-	  // first mark all objects from this pvs
-	  while (pit.HasMoreEntries()) 	
-	  {
-		  pit.Next()->Mail();
-	  }
-  }
-  
-  int pvsSize = 0;
-  int nPvsSize = 0;
-  float samples = (float)basePvs.GetSamples();
-  
-  Debug<<"f #s="<<samples<<"  pvs size = "<<basePvs.GetSize();
-  //  cout<<"Filter size = "<<filterSize<<endl;
-  //  cout<<"vbox = "<<vbox<<endl;
-  //  cout<<"center = "<<center<<endl;
-
-
-   // Minimal number of local samples to take into account
-   // the local sampling density.
-   // The size of the filter is a minimum of the conservative
-   // local sampling density estimate (#rays intersecting teh viewcell and
-   // the object)
-   // and gobal estimate for the view cell
-   // (total #rays intersecting the viewcell)
-  int minLocalSamples = 2;
-  
-  float viewCellRadius = 0.5f*Magnitude(vbox.Diagonal());
-  
-  // now compute the filter box around the current viewCell
-  
-  if (useViewSpaceFilter) {
-	//	float radius = Max(viewCellRadius/100.0f, avgRadius - viewCellRadius);
-	float radius = viewCellRadius/100.0f;
-	vbox.Enlarge(radius);
-	cout<<"vbox = "<<vbox<<endl;
-	ViewCellContainer viewCells;
-	ComputeBoxIntersections(vbox, viewCells);
-	
-	ViewCellContainer::const_iterator it = viewCells.begin(),
-	  it_end = viewCells.end();
-	int i = 0;
-	for (i=0; it != it_end; ++ it, ++ i)
-	  if ((*it) != viewCell) {
-		//cout<<"v"<<i<<" pvs="<<(*it)->GetPvs().mEntries.size()<<endl;
-		basePvs.MergeInPlace((*it)->GetPvs());
-	  }
-	
-	// update samples and globalC
-	samples = (float)pvs.GetSamples();
-	//	cout<<"neighboring viewcells = "<<i-1<<endl;
-	//	cout<<"Samples' = "<<samples<<endl;
-  }
-  
-  // Minimal number of samples so that filtering takes place
+	PvsFilterStatistics stats;
+
+	AxisAlignedBox3 vbox = GetViewCellBox(viewCell);
+	Vector3 center = vbox.Center();
+	// copy the PVS
+	Intersectable::NewMail();
+	ObjectPvs basePvs = viewCell->GetPvs();
+	ObjectPvsIterator pit = basePvs.GetIterator();
+
+	pvs.Reserve(viewCell->GetFilteredPvsSize());
+
+	if (!mUseKdPvs)
+	{
+		// first mark all objects from this pvs
+		while (pit.HasMoreEntries()) 	
+			pit.Next()->Mail();
+	}
+
+	int pvsSize = 0;
+	int nPvsSize = 0;
+	float samples = (float)basePvs.GetSamples();
+
+	Debug<<"f #s="<<samples<<"  pvs size = "<<basePvs.GetSize();
+	//  cout<<"Filter size = "<<filterSize<<endl;
+	//  cout<<"vbox = "<<vbox<<endl;
+	//  cout<<"center = "<<center<<endl;
+
+
+	// Minimal number of local samples to take into account
+	// the local sampling density.
+	// The size of the filter is a minimum of the conservative
+	// local sampling density estimate (#rays intersecting teh viewcell and
+	// the object)
+	// and gobal estimate for the view cell
+	// (total #rays intersecting the viewcell)
+	int minLocalSamples = 2;
+
+	float viewCellRadius = 0.5f*Magnitude(vbox.Diagonal());
+
+	// now compute the filter box around the current viewCell
+
+	if (useViewSpaceFilter) 
+	{
+		//	float radius = Max(viewCellRadius/100.0f, avgRadius - viewCellRadius);
+		float radius = viewCellRadius/100.0f;
+		vbox.Enlarge(radius);
+		cout<<"vbox = "<<vbox<<endl;
+		ViewCellContainer viewCells;
+		ComputeBoxIntersections(vbox, viewCells);
+
+		ViewCellContainer::const_iterator it = viewCells.begin(), it_end = viewCells.end();
+
+		for (int i = 0; it != it_end; ++ it, ++ i)
+		{
+			
+			if ((*it) != viewCell) 
+			{
+				//cout<<"v"<<i<<" pvs="<<(*it)->GetPvs().mEntries.size()<<endl;
+				basePvs.MergeInPlace((*it)->GetPvs());
+			}
+
+			// update samples and globalC
+			samples = (float)pvs.GetSamples();
+			//	cout<<"neighboring viewcells = "<<i-1<<endl;
+			//	cout<<"Samples' = "<<samples<<endl;
+		}
+	}
+
+	// Minimal number of samples so that filtering takes place
 #define MIN_SAMPLES  50
-  
-  if (samples > MIN_SAMPLES) {
-	float globalC = 2.0f*filterSize/sqrt(samples);
-	
-	pit = basePvs.GetIterator();
-	
-	ObjectContainer objects;
-	
-	PvsData pvsData;
-
-	while (pit.HasMoreEntries()) {		
-	  Intersectable *object = pit.Next(pvsData);
-	  
-	  // compute filter size based on the distance and the numebr of samples
-	  AxisAlignedBox3 box = object->GetBox();
-	  
-	  float distance = Distance(center, box.Center());
-	  float globalRadius = distance*globalC;
-	  
-	  int objectSamples = (int)pvsData.mSumPdf;
-	  float localRadius = MAX_FLOAT;
-	  
-	  localRadius = filterSize*0.5f*Magnitude(box.Diagonal())/
-		sqrt((float)objectSamples);
-	  
-	  //	  cout<<"os="<<objectSamples<<" lr="<<localRadius<<" gr="<<globalRadius<<endl;
-	  
-	  // now compute the filter size
-	  float radius;
-	  
+
+	if (samples > MIN_SAMPLES) 
+	{
+		float globalC = 2.0f * filterSize / sqrt(samples);
+
+		ObjectContainer objects;
+		PvsData pvsData;
+
+		pit = basePvs.GetIterator();
+
+		while (pit.HasMoreEntries()) 
+		{		
+			Intersectable *object = pit.Next(pvsData);
+
+			// compute filter size based on the distance and the numebr of samples
+			AxisAlignedBox3 box = object->GetBox();
+
+			float distance = Distance(center, box.Center());
+			float globalRadius = distance*globalC;
+
+			int objectSamples = (int)pvsData.mSumPdf;
+			float localRadius = MAX_FLOAT;
+
+			localRadius = filterSize*0.5f*Magnitude(box.Diagonal())/
+				sqrt((float)objectSamples);
+
+			// cout<<"os="<<objectSamples<<" lr="<<localRadius<<" gr="<<globalRadius<<endl;
+
+			// now compute the filter size
+			float radius;
+
 #if 0
-	  if (objectSamples <= 1) {
-		if (localRadius > globalRadius) {
-		  radius = 0.5flRadius;
-		  stats.mLocalFilterCount++;
-		} else {
-		  radius = globalRadius;
-		  stats.mGlobalFilterCount++;
-		}
-	  } else {
-		radius = localRadius;
-		stats.mLocalFilterCount++;
-	  }
+			if (objectSamples <= 1) 
+			{
+				if (localRadius > globalRadius) 
+				{
+					radius = 0.5flRadius;
+					stats.mLocalFilterCount++;
+				} 
+				else 
+				{
+					radius = globalRadius;
+					stats.mGlobalFilterCount++;
+				}
+			} 
+			else 
+			{
+				radius = localRadius;
+				stats.mLocalFilterCount++;
+			}
 #else
 
-	  //	  radius = 0.5f*globalRadius + 0.5f*localRadius;
-	  radius = Min(globalRadius, localRadius);
-	  
-	  if (localRadius > globalRadius) 
-		stats.mLocalFilterCount++;
-	  else
-		stats.mGlobalFilterCount++;
+			// radius = 0.5f*globalRadius + 0.5f*localRadius;
+			radius = Min(globalRadius, localRadius);
+
+			if (localRadius > globalRadius) 
+				++ stats.mLocalFilterCount;
+			else
+				++ stats.mGlobalFilterCount;
 #endif
-	  
-	  stats.mAvgFilterRadius += radius;
-	  
-	  // cout<<"box = "<<box<<endl;
-	  //	cout<<"distance = "<<distance<<endl;
-	  //	cout<<"radiues = "<<radius<<endl;
-	  
-	  box.Enlarge(Vector3(radius));
-
-	  if (filteredBoxes)
-		filteredBoxes->push_back(box);
-
-	  objects.clear();
-	  // $$ warning collect objects takes only unmailed ones!
-	  if (mUseKdPvsAfterFiltering) {
-		GetPreprocessor()->mKdTree->CollectKdObjects(box, objects);
-	  } else
-		CollectObjects(box, objects);
-	  
-	  //	cout<<"collected objects="<<objects.size()<<endl;
-	  ObjectContainer::const_iterator noi = objects.begin();
-	  for (; noi != objects.end(); ++ noi) {
-		Intersectable *o = *noi;
-		// $$ JB warning: pdfs are not correct at this point!	  
-		pvs.AddSampleDirty(o, Limits::Small);
-	  }
-	}
-	stats.mAvgFilterRadius /= (stats.mLocalFilterCount + stats.mGlobalFilterCount);
-  }
-  
-  Debug<<" nPvs size = "<<pvs.GetSize()<<endl;
-  
-  if (!mUseKdPvs)
-  {
-	  PvsData pvsData;
-
-	  // copy the base pvs to the new pvs
-	  pit = basePvs.GetIterator();
-	  while (pit.HasMoreEntries()) 
-	  {		
-		  Intersectable *obj = pit.Next(pvsData);
-		  pvs.AddSampleDirty(obj, pvsData.mSumPdf);
-	  }
-  }
-  
-  pvs.SimpleSort();
-  viewCell->SetFilteredPvsSize(pvs.GetSize());
-  
-  Intersectable::NewMail();
-  return stats;
+
+			stats.mAvgFilterRadius += radius;
+
+			// cout<<"box = "<<box<<endl;
+			//	cout<<"distance = "<<distance<<endl;
+			//	cout<<"radiues = "<<radius<<endl;
+
+			box.Enlarge(Vector3(radius));
+
+			if (filteredBoxes)
+				filteredBoxes->push_back(box);
+
+			objects.clear();
+
+			// $$ warning collect objects takes only unmailed ones!
+			if (mUseKdPvs) 
+				GetPreprocessor()->mKdTree->CollectKdObjects(box, objects);
+			else
+				CollectObjects(box, objects);
+
+			//	cout<<"collected objects="<<objects.size()<<endl;
+			ObjectContainer::const_iterator noi = objects.begin();
+			for (; noi != objects.end(); ++ noi) 
+			{
+				Intersectable *o = *noi;
+				// $$ JB warning: pdfs are not correct at this point!	  
+				pvs.AddSampleDirty(o, Limits::Small);
+			}
+		}
+		stats.mAvgFilterRadius /= (stats.mLocalFilterCount + stats.mGlobalFilterCount);
+	}
+
+	Debug << " nPvs size = " << pvs.GetSize() << endl;
+
+	if (!mUseKdPvs)
+	{
+		PvsData pvsData;
+
+		// copy the base pvs to the new pvs
+		pit = basePvs.GetIterator();
+		while (pit.HasMoreEntries()) 
+		{		
+			Intersectable *obj = pit.Next(pvsData);
+			pvs.AddSampleDirty(obj, pvsData.mSumPdf);
+		}
+	}
+
+	pvs.SimpleSort();
+	viewCell->SetFilteredPvsSize(pvs.GetSize());
+
+	Intersectable::NewMail();
+	return stats;
 }
 
@@ -5898,11 +5893,7 @@
 {
 	if (mUseKdPvs)
-	{
 		return ViewCellsManager::GetIntersectable(ray, isTermination);
-	}
 	else
-	{
 		return mHierarchyManager->GetIntersectable(ray, isTermination);
-	}
 }
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp	(revision 2530)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp	(revision 2538)
@@ -33,4 +33,5 @@
 const int depthMapSize = 512;
 
+
 static void InitExtensions() 
 {
@@ -49,5 +50,4 @@
 	if (GLEW_NV_occlusion_query) 
 		nvQuerySupport = true;
-	
 
 	if  (!arbQuerySupport && !nvQuerySupport)
@@ -55,4 +55,13 @@
 		cout << "I require the GL_ARB_occlusion_query or the GL_NV_occlusion_query OpenGL extension to work.\n";
 		exit(1);
+	}
+
+	if (!GLEW_ARB_vertex_buffer_object) 
+	{
+		cout << "vbos not supported" << endl;
+	}
+	else
+	{
+		cout << "vbos supported" << endl;
 	}
 }
@@ -64,5 +73,10 @@
   Renderer(sceneGraph, viewCellsManager),
   mKdTree(tree),
-  mUseFalseColors(false)
+  mUseFalseColors(false),
+  mVboId(-1),
+  mData(NULL),
+  mIndices(NULL),
+  mUseVbos(true)
+  //mUseVbos(false)
 {
   mSceneGraph->CollectObjects(&mObjects);
@@ -90,6 +104,6 @@
   mUseForcedColors = false;
   mRenderBoxes = false;
- // mUseGlLists = true;
-  mUseGlLists = false;
+  mUseGlLists = true;
+  //mUseGlLists = false;
 
   if (mViewCellsManager->GetViewCellPoints()->size())
@@ -103,11 +117,17 @@
 }
 
+
 GlRenderer::~GlRenderer()
 {
   cerr<<"gl renderer destructor..\n";
  
-  //CLEAR_CONTAINER(sQueries);
   CLEAR_CONTAINER(mOcclusionQueries);
 
+  DeleteVbos();
+
+  if (mData) delete [] mData;
+  if (mIndices) delete [] mIndices;
+
+  glDeleteBuffersARB(1, &mVboId);
   cerr<<"done."<<endl;
 }
@@ -338,4 +358,6 @@
   
   OcclusionQuery::GenQueries(mOcclusionQueries, 10);
+
+  CreateVertexArrays();
 }
 
@@ -373,33 +395,50 @@
 GlRenderer::_RenderScene()
 {
-  ObjectContainer::const_iterator oi = mObjects.begin();
-  for (; oi != mObjects.end(); oi++)
-	RenderIntersectable(*oi);
-}
-
-void
-GlRenderer::_RenderSceneTriangles()
-{
-  glBegin(GL_TRIANGLES);
-
-  ObjectContainer::const_iterator oi = mObjects.begin();
-  for (; oi != mObjects.end(); oi++) {
-	
-	if ((*oi)->Type() == Intersectable::TRIANGLE_INTERSECTABLE) {
-	  TriangleIntersectable *object = (TriangleIntersectable *)*oi;
-	  Triangle3 &t = object->GetItem();
-	  
-	  Vector3 normal = t.GetNormal();
-	  glNormal3f(normal.x, normal.y, normal.z);
-	  glVertex3f(t.mVertices[0].x, t.mVertices[0].y, t.mVertices[0].z);
-	  glVertex3f(t.mVertices[1].x, t.mVertices[1].y, t.mVertices[1].z);
-	  glVertex3f(t.mVertices[2].x, t.mVertices[2].y, t.mVertices[2].z);
-	  
-	}
-  }
-
-  glEnd();
-  
-}
+	ObjectContainer::const_iterator oi = mObjects.begin();
+	for (; oi != mObjects.end(); oi++)
+		RenderIntersectable(*oi);
+}
+
+void GlRenderer::_RenderSceneTrianglesWithDrawArrays()
+{
+	EnableDrawArrays();
+	
+	if (mUseVbos)
+		glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVboId);
+
+	int offset = mObjects.size() * 3;
+	char *arrayPtr = mUseVbos ? NULL : (char *)mData;
+	
+	glVertexPointer(3, GL_FLOAT, 0, (char *)arrayPtr);
+	glNormalPointer(GL_FLOAT, 0, (char *)arrayPtr + offset * sizeof(Vector3));
+	
+	glDrawArrays(GL_TRIANGLES, 0, mObjects.size() * 3);
+	//DisableDrawArrays();
+}
+
+
+void GlRenderer::_RenderSceneTriangles()
+{
+	glBegin(GL_TRIANGLES);
+
+	ObjectContainer::const_iterator oi = mObjects.begin();
+	for (; oi != mObjects.end(); oi++) {
+
+		if ((*oi)->Type() == Intersectable::TRIANGLE_INTERSECTABLE) {
+			TriangleIntersectable *object = (TriangleIntersectable *)*oi;
+			Triangle3 &t = object->GetItem();
+
+			Vector3 normal = t.GetNormal();
+			glNormal3f(normal.x, normal.y, normal.z);
+			glVertex3f(t.mVertices[0].x, t.mVertices[0].y, t.mVertices[0].z);
+			glVertex3f(t.mVertices[1].x, t.mVertices[1].y, t.mVertices[1].z);
+			glVertex3f(t.mVertices[2].x, t.mVertices[2].y, t.mVertices[2].z);
+
+		}
+	}
+
+	glEnd();
+}
+
 
 bool
@@ -407,4 +446,10 @@
 {
   Intersectable::NewMail();
+
+#if 1
+  
+  _RenderSceneTrianglesWithDrawArrays();
+
+#else
   static int glList = -1;
   if (mUseGlLists) {
@@ -420,5 +465,5 @@
 	_RenderSceneTriangles();
 	
-  
+#endif
   return true;
 }
@@ -426,7 +471,5 @@
 
 void
-GlRendererBuffer::EvalQueryWithItemBuffer(
-										  //RenderCostSample &sample
-									   )
+GlRendererBuffer::EvalQueryWithItemBuffer()
 {
 	// read back the texture
@@ -466,8 +509,6 @@
 								   KdTree *tree):
 GlRenderer(sceneGraph, viewcells, tree)  
-{
-  
-  mPixelBuffer = NULL;
-  
+{ 
+  mPixelBuffer = NULL; 
   // implement width and height in subclasses
 }
@@ -683,7 +724,4 @@
 	RenderBvhNode(in->GetFront());
   }
-
-  //cout << "leaf obj " << i << endl;
-
 }
 
@@ -691,19 +729,23 @@
 GlRenderer::RenderKdNode(KdNode *node)
 {
-  if (node->IsLeaf()) {
-	KdLeaf *leaf = (KdLeaf *) node;
-	for (int i=0; i < leaf->mObjects.size(); i++) {
-	  RenderIntersectable(leaf->mObjects[i]);
-	}
-  } else {
-	KdInterior *in = (KdInterior *)node;
-	RenderKdNode(in->mBack);
-	RenderKdNode(in->mFront);
-  }
-  
-}
-
-
-
+	if (node->IsLeaf()) 
+	{
+#if 1
+		RenderKdLeaf(static_cast<KdLeaf *>(node));
+#else
+		KdLeaf *leaf = (KdLeaf *)node;
+		for (int i=0; i < leaf->mObjects.size(); i++) 
+		{
+			RenderIntersectable(leaf->mObjects[i]);
+		}
+#endif
+	} 
+	else 
+	{
+		KdInterior *in = (KdInterior *)node;
+		RenderKdNode(in->mBack);
+		RenderKdNode(in->mFront);
+	}
+}
 
 
@@ -814,4 +856,5 @@
 #endif
 #endif
+	
 }
 
@@ -1126,7 +1169,5 @@
 	{
 		mOcclusionQueries[queryIdx ++]->BeginQuery();
-
 		RenderIntersectable(*vit);
-		
 		mOcclusionQueries[queryIdx]->EndQuery();
 
@@ -1519,20 +1560,176 @@
 GlRenderer::RenderViewPoint()
 {
-  mWireFrame = true;
-  glPushMatrix();
-  glTranslatef(mViewPoint.x, mViewPoint.y, mViewPoint.z);
-  glScalef(5.0f,5.0f,5.0f);
-  glPushAttrib(GL_CURRENT_BIT);
-  glColor3f(1.0f, 0.0f, 0.0f);
-  gluSphere((::GLUquadric *)mSphere,
-			1e-3*Magnitude(mViewCellsManager->GetViewSpaceBox().Size()), 6, 6);
-  glPopAttrib();
-  glPopMatrix();
-  mWireFrame = false;
-}
-
-
-
-
-
-}
+	mWireFrame = true;
+	glPushMatrix();
+	glTranslatef(mViewPoint.x, mViewPoint.y, mViewPoint.z);
+	glScalef(5.0f,5.0f,5.0f);
+	glPushAttrib(GL_CURRENT_BIT);
+	glColor3f(1.0f, 0.0f, 0.0f);
+	gluSphere((::GLUquadric *)mSphere,
+		1e-3*Magnitude(mViewCellsManager->GetViewSpaceBox().Size()), 6, 6);
+	glPopAttrib();
+	glPopMatrix();
+	mWireFrame = false;
+}
+
+
+void GlRenderer::EnableDrawArrays()
+{
+	glEnableClientState(GL_VERTEX_ARRAY);
+	glEnableClientState(GL_NORMAL_ARRAY);
+}
+
+
+void GlRenderer::DisableDrawArrays()
+{
+	glDisableClientState(GL_VERTEX_ARRAY);
+	glDisableClientState(GL_NORMAL_ARRAY);
+}
+
+
+#if 0
+
+void GlRenderer::RenderKdLeaf(KdLeaf *leaf)
+{
+	int bufferSize = 0;
+
+	// count #new triangles
+	for (size_t i = 0; i < leaf->mObjects.size(); ++ i)
+	{
+		TriangleIntersectable *obj = static_cast<TriangleIntersectable *>(leaf->mObjects[i]);
+
+		// check if already rendered
+		if (!obj->Mailed())
+			bufferSize += 3;
+		//else cout << obj->mMailbox << " " << obj->sMailId << " ";
+	}
+
+	Vector3 *vertices = new Vector3[bufferSize];
+	Vector3 *normals = new Vector3[bufferSize];
+
+	int j = 0;
+
+	for (size_t i = 0; i < leaf->mObjects.size(); ++ i)
+	{
+		TriangleIntersectable *obj = static_cast<TriangleIntersectable *>(leaf->mObjects[i]);
+
+		// check if already rendered
+		if (obj->Mailed())
+			continue;
+
+		obj->Mail();
+
+		Triangle3 tri = obj->GetItem();
+
+		vertices[j * 3 + 0] = tri.mVertices[0];
+		vertices[j * 3 + 1] = tri.mVertices[1];
+		vertices[j * 3 + 2] = tri.mVertices[2];
+
+		Vector3 n = tri.GetNormal();
+
+		normals[j * 3 + 0] = n;
+		normals[j * 3 + 1] = n;
+		normals[j * 3 + 2] = n;
+
+		++ j;
+	}
+
+	glVertexPointer(3, GL_FLOAT, 0, vertices);
+	glNormalPointer(GL_FLOAT, 0, normals);
+
+	glDrawArrays(GL_TRIANGLES, 0, bufferSize);
+
+	DEL_PTR(vertices);
+	DEL_PTR(normals);
+}
+
+#else
+
+void GlRenderer::RenderKdLeaf(KdLeaf *leaf)
+{
+	if (!leaf->mIndexBufferSize)
+		return;
+
+	unsigned int offset = mObjects.size() * 3;
+	char *arrayPtr = mUseVbos ? NULL : (char *)mData;
+	
+	glVertexPointer(3, GL_FLOAT, 0, (char *)arrayPtr);
+	glNormalPointer(GL_FLOAT, 0, (char *)arrayPtr + offset * sizeof(Vector3));
+	
+	glDrawElements(GL_TRIANGLES, leaf->mIndexBufferSize, GL_UNSIGNED_INT, mIndices + leaf->mIndexBufferStart);
+}
+
+#endif
+
+void GlRenderer::CreateVertexArrays()
+{
+	mData = new Vector3[mObjects.size() * 6];
+	mIndices = new unsigned int[mObjects.size() * 3];
+
+	const int offset = mObjects.size() * 3;
+
+	for (size_t i = 0; i < mObjects.size(); ++ i)
+	{
+		TriangleIntersectable *obj = static_cast<TriangleIntersectable *>(mObjects[i]);
+
+		Triangle3 tri = obj->GetItem();
+		const Vector3 n = tri.GetNormal();
+
+		mData[i * 3 + 0] = tri.mVertices[0];
+		mData[i * 3 + 1] = tri.mVertices[1];
+		mData[i * 3 + 2] = tri.mVertices[2];
+
+		mData[offset + i * 3 + 0] = n;
+		mData[offset + i * 3 + 1] = n;
+		mData[offset + i * 3 + 2] = n;
+	}
+
+	if (mUseVbos)
+	{
+		EnableDrawArrays();
+
+		glGenBuffersARB(1, &mVboId);
+		glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVboId);
+
+		glVertexPointer(3, GL_FLOAT, 0, (char *)NULL);
+		glNormalPointer(GL_FLOAT, 0, (char *)NULL + offset * sizeof(Vector3));
+
+		glBufferDataARB(GL_ARRAY_BUFFER_ARB, mObjects.size() * 6 * sizeof(Vector3), mData, GL_STATIC_DRAW_ARB);
+		glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+
+		DisableDrawArrays();
+
+		delete [] mData;
+	}
+
+	cout << "\n**************\ndraw arrays created\n" << endl;	
+}
+
+
+void GlRenderer::DeleteVbos()
+{
+	glDeleteBuffersARB(1, &mVboId);
+
+/*
+	KdLeafContainer leaves;
+	mKdTree->CollectLeaves(leaves);
+
+	KdLeafContainer::const_iterator kit, kit_end = leaves.end();
+
+	for (kit = leaves.begin(); kit != kit_end; ++ kit)
+	{
+		KdLeaf *leaf = *kit;
+
+		if (leaf->mVboId == -1)
+		{
+			// delete old vbo
+			glDeleteBuffersARB(1, &leaf->mVboId);
+			leaf->mVboId = -1;
+		}
+	}
+*/
+}
+
+
+
+}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.h	(revision 2524)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.h	(revision 2538)
@@ -183,5 +183,5 @@
 public:
   KdLeaf(KdInterior *parent, const int objects):
-	  KdNode(parent), mViewCell(NULL) {
+	  KdNode(parent), mViewCell(NULL), mVboId(-1), mIndexBufferStart(0), mIndexBufferSize(0) {
     mObjects.reserve(objects);
   }
@@ -209,24 +209,20 @@
   /// pointers to occluders contained in this node
   ObjectContainer mObjects;
-
   /// Ray set description of the rays passing through this node
   PassingRaySet mPassingRays;
-	
-  /// PVS consisting of visible KdTree nodes
-  //KdPvs mKdPvs;
-
-  /// pvs of view cells seeing this node.
-  SubdivisionCandidate *mSubdivisionCandidate;
-
   /// pointer to view cell.
   KdViewCell *mViewCell;
-
+  /// rays intersecting this leaf
   VssRayContainer mVssRays;
-
    /// Objects that are referenced in more than one leaf.
   ObjectContainer mMultipleObjects;
-
   /// universal counter
   int mCounter;
+
+  /// hack
+  unsigned int mVboId;
+
+  unsigned int mIndexBufferStart;
+  unsigned int mIndexBufferSize;
 };
 
@@ -342,5 +338,4 @@
 
   /** Returns or creates a new intersectable for use in a kd based pvs.
-	  The OspTree is responsible for destruction of the intersectable.
   */
   KdIntersectable *GetOrCreateKdIntersectable(KdNode *node);
@@ -348,6 +343,5 @@
 
   void
-  SetPvsTerminationNodes(
-						 const float maxArea);
+  SetPvsTerminationNodes(const float maxArea);
   
   KdNode *
Index: GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp	(revision 2452)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp	(revision 2538)
@@ -365,87 +365,93 @@
 #endif
 
-	if (preprocessor->mUseGlRenderer || preprocessor->mUseGlDebugger)
+	  if (preprocessor->mUseGlRenderer || preprocessor->mUseGlDebugger)
 	  {
 #ifdef USE_QT
-		cout << "using gl widget" << endl;
-		// create and run the preprocessor application in a parallel thread
-		
-		pt->InitThread();
-		pt->RunThread();
-
-		// display the render widget
-		if (!rendererWidget) 
-		{
-
-		  if (!QGLFormat::hasOpenGL() || !QGLPixelBuffer::hasOpenGLPbuffers()) {
-			QMessageBox::information(0, "OpenGL pbuffers", 
-									   "This system does not support OpenGL/pbuffers.",
-									   QMessageBox::Ok);
-			  return NULL;
-			}
-
-		  rendererWidget = 
-			new QtGlRendererWidget(preprocessor->mSceneGraph,
-								   preprocessor->mViewCellsManager,
-								   preprocessor->mKdTree);
-		  
-		  rendererWidget->Show();
-		  
-		  QtGlViewer *viewer = 
-			new QtGlViewer(NULL, (QtGlRendererWidget *)rendererWidget);
-		  
-		  viewer->show();
-		  guiSupported = true; 
-		}
-		
-		
-		bool exportRandomViewCells;
-		Environment::GetSingleton()->GetBoolValue("ViewCells.exportRandomViewCells",
-												  exportRandomViewCells);
-
-		if (exportRandomViewCells)
-		{
-			cout << "exporting random view cells" << endl;
-			preprocessor->mViewCellsManager->ExportRandomViewCells(viewCellPointsFile);
-			cout << "finished" << endl;
-		}
-
-		/*bool evaluatePixelError;
-		Environment::GetSingleton()->GetBoolValue("Preprocessor.evaluatePixelError",  evaluatePixelError);
-
-		if (evaluatePixelError)
-		{
-			cout << "evaluating pixel error" << endl;
-			preprocessor->ComputeRenderError();
-		}*/
-		
-		qApp->exec();
-#endif
-	}
-
-	// no gui available
-	if (!guiSupported) 
-	{
-		if (preprocessor->mUseGlRenderer || preprocessor->mUseGlDebugger)
-			cout << "warning: gui not supported!" << endl;
-		
-		preprocessor->mUseGlRenderer = false;
-		preprocessor->mUseGlDebugger = false;
-	}
-
-	if (!(preprocessor->mUseGlRenderer || preprocessor->mUseGlDebugger)) 
-	{
-		cout << "executing main thread" << endl;
-		// just call the mail method -> will be executed in the main thread
-		pt->Main();
-	}	
-#endif
-
-	// release memory
-	Cleanup();
-	
-	delete pt;
-
-	return returnCode;
+
+		  ////////
+		  // create and run the preprocessor application in a parallel thread
+
+		  cout << "using gl widget" << endl;
+
+		  pt->InitThread();
+		  pt->RunThread();
+
+		  // display the render widget
+		  if (!rendererWidget) 
+		  {
+
+			  if (!QGLFormat::hasOpenGL() || !QGLPixelBuffer::hasOpenGLPbuffers()) {
+				  QMessageBox::information(0, "OpenGL pbuffers", 
+					  "This system does not support OpenGL/pbuffers.",
+					  QMessageBox::Ok);
+				  return NULL;
+			  }
+
+			  rendererWidget = 
+				  new QtGlRendererWidget(preprocessor->mSceneGraph,
+				  preprocessor->mViewCellsManager,
+				  preprocessor->mKdTree);
+
+			  rendererWidget->Show();
+
+			  if (0)
+			  {
+				  QtGlViewer *viewer = 
+					  new QtGlViewer(NULL, (QtGlRendererWidget *)rendererWidget);
+				  viewer->show();
+			  }
+
+			  guiSupported = true; 
+		  }
+
+
+		  bool exportRandomViewCells;
+		  Environment::GetSingleton()->GetBoolValue("ViewCells.exportRandomViewCells",
+			  exportRandomViewCells);
+
+		  if (exportRandomViewCells)
+		  {
+			  cout << "exporting random view cells" << endl;
+			  preprocessor->mViewCellsManager->ExportRandomViewCells(viewCellPointsFile);
+			  cout << "finished" << endl;
+		  }
+
+		  /*bool evaluatePixelError;
+		  Environment::GetSingleton()->GetBoolValue("Preprocessor.evaluatePixelError",  evaluatePixelError);
+
+		  if (evaluatePixelError)
+		  {
+		  cout << "evaluating pixel error" << endl;
+		  preprocessor->ComputeRenderError();
+		  }*/
+
+		  qApp->exec();
+#endif
+	  }
+
+	  // no gui available
+	  if (!guiSupported) 
+	  {
+		  if (preprocessor->mUseGlRenderer || preprocessor->mUseGlDebugger)
+			  cout << "warning: gui not supported!" << endl;
+
+		  preprocessor->mUseGlRenderer = false;
+		  preprocessor->mUseGlDebugger = false;
+	  }
+
+	  if (!(preprocessor->mUseGlRenderer || preprocessor->mUseGlDebugger)) 
+	  {
+		  cout << "executing main thread" << endl;
+		  // just call the mail method -> will be executed in the main thread
+		  pt->Main();
+	  }	
+#endif
+
+	  // release memory
+	  Cleanup();
+
+	  delete pt;
+
+	  return returnCode;
 }
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.h	(revision 2176)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.h	(revision 2538)
@@ -59,8 +59,17 @@
 
 	struct PvsCache {
-		PvsCache():mViewCell(NULL) {}
-		void Reset() { mViewCell = NULL; mPvs.Clear(); filteredBoxes.clear(); }
+		
+		PvsCache():mViewCell(NULL), mUnfilteredPvsSize(0) {}
+
+		void Reset()
+		{ 
+			mViewCell = NULL; mPvs.Clear(); 
+			filteredBoxes.clear(); 
+			mUnfilteredPvsSize = 0;
+		}
+		
 		ViewCell *mViewCell;
 		ObjectPvs mPvs;
+		int mUnfilteredPvsSize;
 		vector<AxisAlignedBox3> filteredBoxes;
 	};
@@ -94,4 +103,6 @@
 class GlRenderer: public Renderer
 {
+friend class GlobalLinesRenderer;
+friend class ViewCellsManager;
 
 public:
@@ -141,4 +152,6 @@
   _RenderSceneTriangles();
 
+  void _RenderSceneTrianglesWithDrawArrays();
+
   void
   RenderViewPoint();
@@ -197,6 +210,4 @@
 	  Vector3 mDirection;
   };
-friend class GlobalLinesRenderer;
-friend class ViewCellsManager;
 
   vector<PvsErrorEntry> mPvsErrorBuffer;
@@ -204,36 +215,50 @@
 protected:
 
-  
-
-  PvsCache mPvsCache;
-
-  vector<OcclusionQuery *> mOcclusionQueries;
-
-  ObjectContainer mObjects;
-   
-  Vector3 mViewPoint;
-  Vector3 mViewDirection;
-
-  int timerId;
-  bool mUseFalseColors;
-  bool mUseForcedColors;
-
-  HaltonSequence halton;
-  
-  
-  bool mDetectEmptyViewSpace;
-  bool mSnapErrorFrames;
-
-  bool mRenderBoxes;
-
-  bool mUseGlLists;
-  
-  std::string mSnapPrefix;
-
-  GLUquadric *mSphere;
-  
-  KdTree *mKdTree;
-
-};
+	void CreateVertexArrays();
+	void DeleteVbos();
+	void EnableDrawArrays();
+	void DisableDrawArrays();
+
+	void RenderKdLeaf(KdLeaf *leaf);
+
+
+	//////////////////
+
+	PvsCache mPvsCache;
+
+	unsigned int mVboId;
+	vector<OcclusionQuery *> mOcclusionQueries;
+
+	ObjectContainer mObjects;
+
+	Vector3 mViewPoint;
+	Vector3 mViewDirection;
+
+	int timerId;
+	bool mUseFalseColors;
+	bool mUseForcedColors;
+
+	HaltonSequence halton;
+
+
+	bool mDetectEmptyViewSpace;
+	bool mSnapErrorFrames;
+
+	bool mRenderBoxes;
+
+	bool mUseGlLists;
+
+	std::string mSnapPrefix;
+
+	GLUquadric *mSphere;
+
+	KdTree *mKdTree;
+
+	Vector3 *mData;
+	unsigned int *mIndices;
+
+	bool mUseVbos;
+};
+
 
 /* Class implementing an OpenGl render buffer.
@@ -268,9 +293,7 @@
 	*/
 	virtual void SampleRenderCost(const int numSamples, 
-		vector<RenderCostSample> &samples,
-		const bool useOcclusionQueries,
-		const int threshold = 0);
-
-
+								  vector<RenderCostSample> &samples,
+								  const bool useOcclusionQueries,
+								  const int threshold = 0);
 	/** Implerment in subclasses.
 	*/
@@ -288,21 +311,19 @@
 
 	virtual void SampleBeamContributions(
-		Intersectable *sourceObject,
-		Beam &beam,
-		const int samples,
-		BeamSampleStatistics &stat
-		);
-
-	virtual void
-		SampleViewpointContributions(
-		Intersectable *sourceObject,
-		const Vector3 viewPoint,
-		Beam &beam,
-		const int desiredSamples,
-		BeamSampleStatistics &stat
-		);
+										 Intersectable *sourceObject,
+										 Beam &beam,
+										 const int samples,
+										 BeamSampleStatistics &stat
+										 );
+
+	virtual void SampleViewpointContributions(
+											  Intersectable *sourceObject,
+											  const Vector3 viewPoint,
+											  Beam &beam,
+											  const int desiredSamples,
+											  BeamSampleStatistics &stat
+											  );
 
 	virtual void InitGL();
-
 	/** Computes rays from information gained with hw sampling-
 	*/
@@ -321,20 +342,12 @@
 
 	virtual void SetupProjectionForViewPoint(const Vector3 &viewPoint, 
-		const Beam &beam, 
-
-		Intersectable *sourceObject);
-
+											 const Beam &beam, 
+											 Intersectable *sourceObject);
 	/** Evaluates query for one direction using item buffer.
 	*/
 	virtual void EvalQueryWithItemBuffer();
-
 	/** Evaluates query for one direction using occlusion queries.
 	*/
 	virtual void EvalQueryWithOcclusionQueries();
-
-public:
-	// matt: remove qt dependencies
-	// signals:
-	//	void UpdatePvsErrorItem(int i, GlRendererBuffer::PvsErrorEntry &);
 };
 
@@ -353,18 +366,8 @@
 
 	  virtual ~GlRendererWidget() {}
-
-	  //virtual void Create() {}
+	  
 	  virtual void Show() {}
-
-
-protected:
-
-
-	//	SceneGraph *mSceneGraph;
-	//	ViewCellsManager *mViewCellsManager;
-	//	KdTree *mKdTree;
-};
-
-//extern GlRendererWidget *rendererWidget;
+};
+
 
 };
Index: GTP/trunk/Lib/Vis/Preprocessing/src/IntersectableWrapper.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/IntersectableWrapper.h	(revision 2176)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/IntersectableWrapper.h	(revision 2538)
@@ -160,6 +160,4 @@
 {
 public:
-	AxisAlignedBox3 mBox;
-	
 	KdIntersectable(KdNode *item, const AxisAlignedBox3 &box);
     
@@ -173,4 +171,7 @@
 		return mBox;
 	}
+
+	/// the bounding box of this intersectable
+	AxisAlignedBox3 mBox;
 };
 
