Index: trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp	(revision 574)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp	(revision 576)
@@ -2303,17 +2303,17 @@
 			if (entSide < 0) 
 			{
-				node = in->GetBack();
-				// plane does not split ray => no far child
-				if (extSide <= 0) 
-					continue;
-
-				farChild = in->GetFront(); // plane splits ray
+			  node = in->GetBack();
+			  // plane does not split ray => no far child
+			  if (extSide <= 0) 
+				continue;
+			  
+			  farChild = in->GetFront(); // plane splits ray
 			} 
 			else if (entSide > 0)
 			{
-				node = in->GetFront();
-
-				if (extSide >= 0) // plane does not split ray => no far child
-					continue;
+			  node = in->GetFront();
+
+			  if (extSide >= 0) // plane does not split ray => no far child
+				continue;
 
 				farChild = in->GetBack(); // plane splits ray
@@ -2364,4 +2364,7 @@
 	return hits;
 }
+
+
+
 
 int VspBspTree::TreeDistance(BspNode *n1, BspNode *n2) const
Index: trunk/VUT/GtpVisibilityPreprocessor/src/SceneGraph.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/SceneGraph.cpp	(revision 492)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/SceneGraph.cpp	(revision 576)
@@ -65,7 +65,15 @@
     nodeStack.pop();
 		
-    ObjectContainer::const_iterator mi = node->mGeometry.begin();
-    for (; mi != node->mGeometry.end(); mi++) 
-      (*mi)->SetId(id++);
+    ObjectContainer::iterator mi = node->mGeometry.begin();
+    for (; mi != node->mGeometry.end(); mi++) {
+	  // $$ JB remove object id=2601 (for debugging purposes in atlanta scene)
+	  if (1) //id != 2601)
+		(*mi)->SetId(id++);
+	  else {
+		node->mGeometry.erase(mi);
+		--mi;
+		id++;
+	  }
+	}
     
     SceneGraphNodeContainer::iterator ni = node->mChildren.begin();
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 575)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 576)
@@ -435,11 +435,10 @@
 {
   Vector3 origin, direction; 
-
-  for (int i=0; rays.size() < number; i++) {
-	mViewCellsManager->GetViewPoint(origin);
-	
+  int startSize = rays.size();
+  for (int i=0; rays.size() - startSize  < number; i++) {
 	// now get the direction
 	switch (sampleType) {
 	case OBJECT_BASED_DISTRIBUTION: {
+	  mViewCellsManager->GetViewPoint(origin);
 	  Vector3 point;
 	  Vector3 normal;
@@ -450,8 +449,19 @@
 	}
 	  break;
+	case OBJECT_DIRECTION_BASED_DISTRIBUTION: {
+	  int i = RandomValue(0, mObjects.size() - 1);
+	  Intersectable *object = mObjects[i];
+	  Vector3 normal;
+	  object->GetRandomSurfacePoint(origin, normal);
+	  direction = UniformRandomVector(normal);
+	  origin += 0.1f*direction;
+	}
+	  break;
 	case DIRECTION_BASED_DISTRIBUTION:
+	  mViewCellsManager->GetViewPoint(origin);
 	  direction = UniformRandomVector();
 	  break;
 	case DIRECTION_BOX_BASED_DISTRIBUTION: {
+	  mViewCellsManager->GetViewPoint(origin);
 	  float alpha = RandomValue(0.0f, 2*M_PI);
 	  float beta = RandomValue(-M_PI/2, M_PI/2);
@@ -460,4 +470,5 @@
 	}
 	case SPATIAL_BOX_BASED_DISTRIBUTION:
+	  mViewCellsManager->GetViewPoint(origin);
 	  direction = mKdTree->GetBox().GetRandomPoint() - origin;
 	  break;
Index: trunk/VUT/GtpVisibilityPreprocessor/src/RssPreprocessor.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/RssPreprocessor.cpp	(revision 574)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/RssPreprocessor.cpp	(revision 576)
@@ -195,4 +195,5 @@
 	  vssRays.push_back(vssRay);
 	  hits ++;
+
 	}
 	
@@ -209,9 +210,45 @@
 	}
   }
-	
+  
   return hits;
 }
 
 
+void
+RssPreprocessor::ExportObjectRays(VssRayContainer &rays,
+								  const int objectId)
+{
+  ObjectContainer::const_iterator oi;
+
+  Intersectable *object = NULL;
+  for (oi = mObjects.begin(); oi != mObjects.end(); ++oi)
+	if (objectId == (*oi)->GetId()) {
+	  object = *oi;
+	  break;
+	}
+
+  if (object == NULL)
+	return;
+  
+  VssRayContainer selectedRays;
+  VssRayContainer::const_iterator it= rays.begin(), it_end = rays.end();
+
+  
+  for (; it != it_end; ++it) {
+	if ((*it)->mTerminationObject == object)
+	  selectedRays.push_back(*it);
+  }
+  
+
+  Exporter *exporter = Exporter::GetExporter("object-rays.x3d");
+  //	exporter->SetWireframe();
+  //	exporter->ExportKdTree(*mKdTree);
+  exporter->SetFilled();
+  exporter->ExportIntersectable(object);
+  exporter->ExportRays(selectedRays, RgbColor(1, 0, 0));
+  
+  delete exporter;
+  
+}
 
 
@@ -461,7 +498,12 @@
 	SimpleRayContainer rays;
 
-	GenerateRays(mInitialSamples, SPATIAL_BOX_BASED_DISTRIBUTION, rays);
+	GenerateRays(mInitialSamples/4, SPATIAL_BOX_BASED_DISTRIBUTION, rays);
+	GenerateRays(mInitialSamples/4, OBJECT_BASED_DISTRIBUTION, rays);
+	GenerateRays(mInitialSamples/4, DIRECTION_BASED_DISTRIBUTION, rays);
+	GenerateRays(mInitialSamples/4, OBJECT_DIRECTION_BASED_DISTRIBUTION, rays);
 	
 	CastRays(rays, mVssRays);
+
+	ExportObjectRays(mVssRays, 1546);
   }
   
@@ -551,5 +593,5 @@
 	  VssRayContainer tmpVssRays;
 
-	  float ratios[] = {1.0f,0,0};
+	  float ratios[] = {0.8f,0.1f,0.1f};
 
 	  
@@ -633,5 +675,13 @@
 	  mViewCellsManager->PrintPvsStatistics(mStats);
 	}
-	
+
+	if (0 && mPass > 0) {
+	  if (mUseImportanceSampling)
+		renderer->mSnapPrefix.sprintf("snap/i-%02d-", mPass);
+	  else
+		renderer->mSnapPrefix.sprintf("snap/r-%02d-", mPass);
+	  renderer->mSnapErrorFrames = true;
+	}
+
 	ComputeRenderError();
 	
Index: trunk/VUT/GtpVisibilityPreprocessor/src/default.env
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/default.env	(revision 569)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/default.env	(revision 576)
@@ -27,5 +27,4 @@
 	detectEmptyViewSpace false
 	pvsRenderErrorSamples 10000
-
 }
 
@@ -73,6 +72,6 @@
 RssPreprocessor {
 	samplesPerPass 500000
-	initialSamples 1000000
-	vssSamples 15000000
+	initialSamples 2000000
+	vssSamples 20000000
 	vssSamplesPerPass 1000000
 	useImportanceSampling true
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.h	(revision 575)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.h	(revision 576)
@@ -108,5 +108,6 @@
 	RSS_BASED_DISTRIBUTION,
 	RSS_SILHOUETTE_BASED_DISTRIBUTION,
-	VSS_BASED_DISTRIBUTION
+	VSS_BASED_DISTRIBUTION,
+	OBJECT_DIRECTION_BASED_DISTRIBUTION
   };
   
Index: trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.h	(revision 572)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.h	(revision 576)
@@ -72,4 +72,6 @@
   
 bool mDetectEmptyViewSpace;
+  bool mSnapErrorFrames;
+  QString mSnapPrefix;
 
   KdTree *mKdTree;
@@ -96,4 +98,5 @@
   RenderScene();
 
+
   void
   SetupProjection(const int w, const int h);
@@ -101,6 +104,4 @@
   
   
-  float
-  GetPixelError();
 
   void InitGL();
@@ -159,4 +160,6 @@
   int ComputePvs() const;
 
+  float
+  GetPixelError();
 
   int ComputePvs(ObjectContainer &objects, ObjectContainer &pvs) const;
@@ -217,4 +220,7 @@
   RenderErrors();
 
+  void
+  RenderInfo();
+
   virtual int GetWidth() const { return width(); }
   virtual int GetHeight() const { return height(); }
Index: trunk/VUT/GtpVisibilityPreprocessor/src/PreprocessorThread.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/PreprocessorThread.cpp	(revision 556)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/PreprocessorThread.cpp	(revision 576)
@@ -28,7 +28,8 @@
 
   if (0) {
-    camera.LookAtBox(mPreprocessor->mKdTree->GetBox());
+    // camera.LookAtBox(mPreprocessor->mKdTree->GetBox());
 	//	camera.LookInBox(mPreprocessor->mKdTree->GetBox());
-	//	camera.SetPosition(camera.mPosition + Vector3(0,300,0));
+	camera.SetPosition(Vector3(3473, 6.778, -1699));
+	camera.SetDirection(Vector3(-0.2432, 0, 0.97));
     camera.SnapImage("camera.jpg", mPreprocessor->mKdTree, mPreprocessor->mSceneGraph);
   }
Index: trunk/VUT/GtpVisibilityPreprocessor/src/RssPreprocessor.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/RssPreprocessor.h	(revision 567)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/RssPreprocessor.h	(revision 576)
@@ -87,4 +87,8 @@
 			 );
 
+  void
+  ExportObjectRays(VssRayContainer &rays,
+				   const int objectId);
+	
   int
   GenerateImportanceRays(RssTree *vssTree,
Index: trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.cpp	(revision 572)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.cpp	(revision 576)
@@ -44,7 +44,13 @@
   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);
+  
   mFrame = 0;
   mWireFrame = false;
   environment->GetBoolValue("Preprocessor.detectEmptyViewSpace", mDetectEmptyViewSpace);
+  mSnapErrorFrames = false;
+  mSnapPrefix = "";
 
 }
@@ -177,6 +183,25 @@
   glGetOcclusionQueryuivNV = (PFNGLGETOCCLUSIONQUERYUIVNVPROC)
 	wglGetProcAddress("glGetOcclusionQueryuivNV");
-}
-
+
+	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+
+}
+
+void
+GlRendererWidget::RenderInfo()
+{
+  QString s;
+  s.sprintf("frame:%04d viewpoint:(%4.1f,%4.1f,%4.1f) dir:(%4.1f,%4.1f,%4.1f)",
+			mFrame,
+			mViewPoint.x,
+			mViewPoint.y,
+			mViewPoint.z,
+			mViewDirection.x,
+			mViewDirection.y,
+			mViewDirection.z
+
+			);
+  renderText(0,20,s);
+}
 
 
@@ -245,5 +270,4 @@
 								   KdTree *tree):
 QGLPixelBuffer(QSize(w, h)), GlRenderer(sceneGraph, viewcells, tree) {
- 
  
  environment->GetIntValue("Preprocessor.pvsRenderErrorSamples", mPvsStatFrames);
@@ -256,5 +280,5 @@
 
 float
-GlRenderer::GetPixelError()
+GlRendererBuffer::GetPixelError()
 {
   float pErrorPixels = -1.0f;
@@ -262,6 +286,7 @@
   glReadBuffer(GL_BACK);
   
-  mUseFalseColors = true;
-  
+  //  mUseFalseColors = true;
+  
+  mUseFalseColors = false;
 
   static int query = -1;
@@ -311,4 +336,6 @@
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
+	glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
+
 	// Render PVS
 	std::map<Intersectable *,
@@ -320,4 +347,8 @@
 	  RenderIntersectable(object);
 	}
+
+	//	glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+	mUseFalseColors = true;
 
 	glBeginOcclusionQueryNV(query);
@@ -337,4 +368,50 @@
 	
 	pErrorPixels = ((float)pixelCount)/(GetWidth()*GetHeight());
+	if (mSnapErrorFrames && pErrorPixels > 0.01) {
+	  
+	  char filename[256];
+	  sprintf(filename, "error-frame-%04d-%0.5f.png", mFrame, pErrorPixels);
+	  QImage im = toImage();
+	  im.save(mSnapPrefix + filename, "PNG");
+	  if (1) { //0 && mFrame == 1543) {
+		int x,y;
+		int lastIndex = -1;
+		for (y=0; y < im.height(); y++)
+		  for (x=0; x < im.width(); x++) {
+			QRgb p = im.pixel(x,y);
+			int index = qRed(p) + (qGreen(p)<<8) + (qBlue(p)<<16);
+			if (qGreen(p) != 255 && index!=0) {
+			  if (index != lastIndex) {
+				Debug<<"ei="<<index<<" ";
+				lastIndex = index;
+			  }
+			}
+		  }
+	  }
+
+
+	  mUseFalseColors = false;
+	  glPushAttrib(GL_CURRENT_BIT);
+	  glColor3f(0,1,0);
+	  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+	  SetupCamera();
+	  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	  
+	  // Render PVS
+	  std::map<Intersectable *,
+		PvsData<Intersectable *>,
+		LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
+	  
+	  for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
+		Intersectable *object = (*it).first;
+		RenderIntersectable(object);
+	  }
+
+	  im = toImage();
+	  sprintf(filename, "error-frame-%04d-%0.5f-pvs.png", mFrame, pErrorPixels);
+	  im.save(mSnapPrefix + filename, "PNG");
+	  glPopAttrib();
+	}
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
   }
   
@@ -400,4 +477,5 @@
 		  diff.setPixel(x, y, qRgba(255,128,128,255));
 		  errorPixels++;
+		  
 		}
 	pErrorPixels = ((float)errorPixels)/(im1.height()*im1.width());
@@ -506,5 +584,19 @@
   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] > 0.0f) {
 	  mPvsErrorBuffer[i] = GetPixelError();
@@ -592,7 +684,7 @@
 GlRendererWidget::paintGL()
 {
-	RenderErrors();
-	
-	mFrame++;
+  RenderErrors();
+  RenderInfo();
+  mFrame++;
 }
 
