Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Material.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Material.h	(revision 386)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Material.h	(revision 608)
@@ -18,5 +18,8 @@
   {
   }
-  
+
+  friend RgbColor
+  RandomColor(const float a=0.0f, const float b=1.0f);
+
 };
 
@@ -32,11 +35,11 @@
   {
   }
-
-	Material(const RgbColor &color):mDiffuseColor(color),
-																	mAmbientColor(color),
-																	mSpecularColor(0,0,0)
-	{
-	}
-
+  
+  Material(const RgbColor &color):mDiffuseColor(color),
+								  mAmbientColor(color),
+								  mSpecularColor(0,0,0)
+  {
+  }
+  
   friend Material RandomMaterial();
   
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.cpp	(revision 607)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.cpp	(revision 608)
@@ -606,4 +606,5 @@
 			if (mViewCellsManager->EqualToSpatialNode(mergedVc))
 				++ mergeStats.siblings;
+			mergedVc->SetCost(realExpectedCost);
 
 			if (((mergeStats.merged % statsOut) == 0) || 
@@ -664,4 +665,7 @@
 		ViewCellInterior *root = mViewCellsManager->MergeViewCells(activeViewCells);
 		root->SetMergeCost(totalRenderCost);
+		// $$JB keep this 0 temporarilly
+		root->SetCost(0.0f);
+		
 		mRoot = root;
 	}
@@ -693,5 +697,6 @@
 	Debug << mergeStats << endl << endl;
 
-
+	// assign colors for the view cells so that at least one is always consistent
+	AssignRandomColors();
 	//TODO: should return sample contributions?
 	return mergeStats.merged;
@@ -1533,4 +1538,68 @@
 
 
+void
+ViewCellsTree::AssignRandomColors()
+{
+  TraversalQueue tqueue;
+  tqueue.push(mRoot);
+  mRoot->SetColor(RandomColor(0.3f, 1.0f));
+  while (!tqueue.empty())
+	{
+	  ViewCell *vc = tqueue.top();
+	  
+	  // save the view cells if it is a leaf or if enough view cells have already been traversed
+	  // because of the priority queue, this will be the optimal set of v
+	  if (!vc->IsLeaf()) {	
+		ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
+		
+		ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
+		float maxProbability = -1.0f;
+		ViewCell *maxViewCell = NULL;
+		for (it = interior->mChildren.begin(); it != it_end; ++ it) {
+		  ViewCell *v = *it;
+		  // set random color
+		  v->SetColor(RandomColor(0.3f, 1.0f));
+		  if (v->GetVolume() > maxProbability) {
+			maxProbability = v->GetVolume();
+			maxViewCell = v;
+		  }
+		  maxViewCell->SetColor(vc->GetColor());
+		  tqueue.push(v);
+		}
+		
+	  }
+	  
+	  tqueue.pop();
+	}
+}
+
+/** Get costs resulting from each merge step. */
+void
+ViewCellsTree::GetCostFunction(vector<float> &costFunction)
+{
+  TraversalQueue tqueue;
+  tqueue.push(mRoot);
+  while (!tqueue.empty()) {
+	ViewCell *vc = tqueue.top();
+	
+	// save the view cells if it is a leaf or if enough view cells have already been traversed
+	// because of the priority queue, this will be the optimal set of v
+	if (!vc->IsLeaf()) {	
+	  ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
+	  costFunction.push_back(interior->GetCost());
+	  
+	  ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
+	  
+	  for (it = interior->mChildren.begin(); it != it_end; ++ it) {
+		tqueue.push(*it);
+	  }
+	  
+	}
+	
+	tqueue.pop();
+  }
+}
+
+
 void  ViewCellsTree::UpdateViewCellsStats(ViewCell *vc, ViewCellsStatistics &vcStat)
 {
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.h	(revision 605)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.h	(revision 608)
@@ -6,4 +6,5 @@
 #include "Ray.h"
 #include "Statistics.h"
+#include "Material.h"
 //namespace GtpVisibilityPreprocessor {
 
@@ -107,5 +108,5 @@
 	int Type() const;
 
-	void SetParent(ViewCellInterior *parent);
+  void SetParent(ViewCellInterior *parent);
 
 	/** Adds a passing ray to the passing ray container.
@@ -147,6 +148,15 @@
 
 
-
-
+  /** set color for visiualizations */
+  void SetColor(const RgbColor &color) {
+	mColor = color;
+  }
+
+  /** get color for visualuzations */
+  RgbColor GetColor() const {
+	return mColor;
+  }
+
+  
 	/// parent view cell in the view cell hierarchy
 	ViewCellInterior *mParent;
@@ -201,4 +211,7 @@
 
 	bool mValid;
+
+  /** color used for consistent visualization */
+  RgbColor mColor;
 };
 
@@ -221,4 +234,14 @@
 	ViewCellContainer mChildren;
 
+  void SetCost(const float c) {
+	mCost = c;
+  }
+  float GetCost() const {
+	return mCost;
+  }
+  
+protected:
+  /** overall cost resulting from the merge */
+  float mCost;
 };
 
@@ -279,8 +302,16 @@
 	int RefineViewCells(const VssRayContainer &rays, const ObjectContainer &objects);
 
+  /** Assign colors to the viewcells so that they can be renderered interactively without
+	  color flickering.
+  */
+  void AssignRandomColors();
 	/** Updates view cell stats for this particular view cell
 	*/
 	void UpdateViewCellsStats(ViewCell *vc, ViewCellsStatistics &vcStat);
 	
+
+  /** Get costs resulting from each merge step. */
+  void GetCostFunction(vector<float> &costFunction);
+  
 
 	/** Returns optimal set of view cells for a given number of view cells.
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/RssPreprocessor.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/RssPreprocessor.cpp	(revision 587)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/RssPreprocessor.cpp	(revision 608)
@@ -298,5 +298,5 @@
   exporter->SetFilled();
   // $$JB temporarily do not export the scene
-  if (0)
+  if (1)
 	exporter->ExportScene(mSceneGraph->mRoot);
   exporter->SetWireframe();
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/default.env
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/default.env	(revision 599)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/default.env	(revision 608)
@@ -25,5 +25,5 @@
 #	type vss
 	type rss
-	detectEmptyViewSpace false
+	detectEmptyViewSpace true
 	pvsRenderErrorSamples 10000
 	quitOnFinish false
@@ -72,8 +72,8 @@
 
 RssPreprocessor {
-	samplesPerPass 500000
+	samplesPerPass 500
 	initialSamples 100
 	vssSamples 100
-	vssSamplesPerPass 1000000
+	vssSamplesPerPass 100
 	useImportanceSampling true
 
@@ -219,6 +219,6 @@
 		exportRays true
 		exportGeometry true
-		exportMergedViewCells true
-		useCuttingPlane true
+		exportMergedViewCells false
+		useCuttingPlane false
 		cuttingPlaneAxis 1
 	}
@@ -283,5 +283,5 @@
 VspBspTree {
 	Construction {
-		samples 300000
+		samples 1000000
 		epsilon 0.005
 		randomize false
@@ -330,5 +330,5 @@
 
 		
-		maxViewCells		10000
+		maxViewCells		50000
 		
 		# used for pvs criterium
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.h	(revision 599)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.h	(revision 608)
@@ -99,5 +99,5 @@
 
 
-  void
+  virtual void
   SetupProjection(const int w, const int h);
 
@@ -179,4 +179,22 @@
 
 
+class RendererControlWidget : public QWidget
+{
+  Q_OBJECT
+public:
+  RendererControlWidget(QWidget * parent = 0, Qt::WFlags f = 0);
+
+  signals:
+  
+  SetViewCellGranularity(int);
+  SetSceneCut(int);
+  SetTopDistance(int);
+
+  SetShowViewCells(bool);
+  SetTopView(bool);
+  SetCutViewCells(bool);
+  SetCutScene(bool);
+
+};
 
 class GlRendererWidget : public QGLWidget, public GlRenderer
@@ -190,4 +208,9 @@
   bool mTopView;
   bool mRenderViewCells;
+  bool mCutViewCells;
+  bool mCutScene;
+  
+  Plane3 mSceneCutPlane;
+  float mTopDistance;
   
   GlRendererWidget(SceneGraph *sceneGraph,
@@ -223,4 +246,6 @@
   virtual int GetHeight() const { return height(); }
 
+  virtual void
+  SetupProjection(const int w, const int h);
 
   void
@@ -229,6 +254,30 @@
  public slots:
  void
- SetViewcellGranularity(int number);
-
+ SetViewCellGranularity(int number);
+
+ void
+ SetSceneCut(int cut);
+
+ void
+ SetTopDistance(int dist);
+
+  void SetShowViewCells(bool b) {
+	mRenderViewCells = b;
+	updateGL();
+  }
+  
+  void SetTopView(bool b) {
+	mTopView = b;
+	updateGL();
+  }
+
+  void SetCutViewCells(bool b) {
+	mCutViewCells = b;
+	updateGL();
+  }
+  void SetCutScene(bool b) {
+	mCutScene = b;
+	updateGL();
+  }
 
 };
@@ -253,4 +302,5 @@
     void initPbuffer();
 
+  
 	 GlRendererBuffer *mRenderBuffer;
 
@@ -258,4 +308,5 @@
 	 int mSamples;
 	 Intersectable *mSourceObject;
+
 private:
     GLuint dynamicTexture;
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Material.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Material.cpp	(revision 162)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Material.cpp	(revision 608)
@@ -10,10 +10,15 @@
 
   Material m;
-  m.mDiffuseColor =
-    RgbColor(a + Random(b),
-	     a + Random(b),
-	     a + Random(b));
+  m.mDiffuseColor = RandomColor(a, b);
 
   return m;
 }
 
+
+RgbColor
+RandomColor(const float a, const float b)
+{
+  return RgbColor(a + Random(b),
+				  a + Random(b),
+				  a + Random(b));
+}
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.cpp	(revision 599)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.cpp	(revision 608)
@@ -13,4 +13,6 @@
 #include <Cg/cgGL.h>
 
+#include <QVBoxLayout>
+
 static CGcontext sCgContext = NULL;
 static CGprogram sCgFragmentProgram = NULL;
@@ -43,8 +45,9 @@
   mViewPoint = mSceneGraph->GetBox().Center();
   mViewDirection = Vector3(0,0,1);
+
   //  timerId = startTimer(10);
   // debug coords for atlanta
-  mViewPoint = Vector3(3473, 6.778, -1699);
-  mViewDirection = Vector3(-0.2432, 0, 0.97);
+  //  mViewPoint = Vector3(3473, 6.778, -1699);
+  //  mViewDirection = Vector3(-0.2432, 0, 0.97);
   
   mFrame = 0;
@@ -205,5 +208,8 @@
 {
   QString s;
-  s.sprintf("frame:%04d viewpoint:(%4.1f,%4.1f,%4.1f) dir:(%4.1f,%4.1f,%4.1f)",
+  int vc = 0;
+  if (mViewCellsManager)
+	vc = mViewCellsManager->GetViewCells().size();
+  s.sprintf("frame:%04d viewpoint:(%4.1f,%4.1f,%4.1f) dir:(%4.1f,%4.1f,%4.1f) viewcells:%04d",
 			mFrame,
 			mViewPoint.x,
@@ -212,6 +218,6 @@
 			mViewDirection.x,
 			mViewDirection.y,
-			mViewDirection.z
-
+			mViewDirection.z,
+			vc
 			);
   renderText(0,20,s);
@@ -433,4 +439,18 @@
 
 
+void
+GlRendererWidget::SetupProjection(const int w, const int h)
+{
+  if (!mTopView)
+	GlRenderer::SetupProjection(w, h);
+  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);
+  }
+}
+
 float
 GlRendererWidget::RenderErrors()
@@ -444,6 +464,16 @@
   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 );
@@ -553,4 +583,6 @@
   }
 
+  glDisable(GL_CLIP_PLANE0);
+
   return pErrorPixels;
 }
@@ -697,11 +729,13 @@
 GlRendererWidget::paintGL()
 {
-  if (mRenderViewCells)
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  
+  RenderErrors();
+  RenderInfo();
+
+    if (mRenderViewCells) 
 	RenderViewCells();
-  else {
-	RenderErrors();
-	RenderInfo();
-  }
-  
+
   mFrame++;
 }
@@ -714,16 +748,32 @@
 	GlRenderer::SetupCamera();
   else {
-	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);
+	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);
+	  
+	}
   }
 
@@ -736,4 +786,5 @@
   case Qt::Key_T:
 	mTopView = !mTopView;
+	SetupProjection(width(), height());
 	updateGL();
 	break;
@@ -746,5 +797,87 @@
 	break;
   }
-  
+}
+
+  
+RendererControlWidget::RendererControlWidget(QWidget * parent, Qt::WFlags f):
+  QWidget(parent, f)
+{
+
+  QVBoxLayout *vl = new QVBoxLayout;
+  setLayout(vl);
+  
+  QWidget *vbox = new QGroupBox("ViewCells", this);
+  layout()->addWidget(vbox);
+  
+  vl = new QVBoxLayout;
+  vbox->setLayout(vl);
+  
+  QSlider *slider = new QSlider(Qt::Horizontal, vbox);
+  vl->addWidget(slider);
+  slider->show();
+  slider->setRange(1, 10000);
+  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+  slider->setValue(500);
+
+  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetViewCellGranularity(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)));
+
+  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("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)));
+  
+
+  adjustSize();
 }
 
@@ -761,14 +894,22 @@
   mTopView = false;
   mRenderViewCells = false;
-
-  QSlider *slider = new QSlider(this);
-  slider->show();
-  slider->setRange(1, 10000);
-
-  connect(slider, SIGNAL(valueChanged(int)), this, SLOT(SetViewcellGranularity(int)));
-}
-
-void
-GlRendererWidget::SetViewcellGranularity(int number)
+  mTopDistance = 1.0f;
+  mCutViewCells = false;
+  mCutScene = false;
+  
+  RendererControlWidget *cw = new RendererControlWidget(NULL);
+  connect(cw, SIGNAL(SetViewCellGranularity(int)), this, SLOT(SetViewCellGranularity(int)));
+  connect(cw, SIGNAL(SetSceneCut(int)), this, SLOT(SetSceneCut(int)));
+  connect(cw, SIGNAL(SetTopDistance(int)), this, SLOT(SetTopDistance(int)));
+  connect(cw, SIGNAL(SetShowViewCells(bool)), this, SLOT(SetShowViewCells(bool)));
+  connect(cw, SIGNAL(SetTopView(bool)), this, SLOT(SetTopView(bool)));
+  connect(cw, SIGNAL(SetCutViewCells(bool)), this, SLOT(SetCutViewCells(bool)));
+  connect(cw, SIGNAL(SetCutScene(bool)), this, SLOT(SetCutScene(bool)));
+  
+  cw->show();
+}
+
+void
+GlRendererWidget::SetViewCellGranularity(int number)
 {
   mViewCellsManager->CollectViewCells(number);
@@ -777,4 +918,26 @@
 
 void
+GlRendererWidget::SetSceneCut(int number)
+{
+  // assume the cut plane can only be aligned with xz plane
+  // shift it along y according to number, which is percentage of the bounding
+  // box position
+  if (mViewCellsManager) {
+	AxisAlignedBox3 box = mViewCellsManager->GetViewSpaceBox();
+	Vector3 p = box.Min() + (number/1000.0f)*box.Max();
+	mSceneCutPlane.mNormal = Vector3(0,-1,0);
+	mSceneCutPlane.mD = -DotProd(mSceneCutPlane.mNormal, p);
+	updateGL();
+  }
+}
+
+void
+GlRendererWidget::SetTopDistance(int number)
+{
+  mTopDistance = number/1000.0f;
+  updateGL();
+}
+
+void
 GlRendererWidget::RenderViewCells()
 {
@@ -782,20 +945,28 @@
 
   SetupCamera();
-  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
+  glEnable(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();
   for (i=0; i < viewcells.size(); i++) {
 	ViewCell *vc = viewcells[i];
-	Mesh *m = vc->GetMesh();
-	float r = RandomValue(0.5, 1.0);
-	float g = RandomValue(0.5, 1.0);
-	float b = RandomValue(0.5, 1.0);
-
-	glColor3f(r, g, b);
-	//SetupMaterial(m->mMaterial);
-
+	//	Mesh *m = vc->GetMesh();
+	RgbColor c = vc->GetColor();
+	glColor3f(c.r, c.g, c.b);
 	RenderViewCell(vc);
   }
+
+  glDisable(GL_CLIP_PLANE0);
 
 }
