Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 2703)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 2707)
@@ -25,4 +25,5 @@
 #include "GlobalLinesRenderer.h"
 #include "ObjectsParser.h"
+#include "SepPlanesBox3.h"
 
 
@@ -1658,71 +1659,51 @@
 /** Object has moved - must dynamically update all affected PVSs */
 void
-Preprocessor::ObjectMoved(SceneGraphLeaf *object)
+Preprocessor::ObjectMoved(SceneGraphLeaf *leaf)
 {
   // first invalidate all PVS from which this object is visible
   ViewCellContainer::const_iterator vit, vit_end = mViewCellsManager->GetViewCells().end();
-
-  AxisAlignedBox3 box = object->GetBox();
-
-  ObjectContainer objects;
-
-  if (0) 
-	{
-	  // simplified computation taking only the objects intersecting the box
-		KdNode::NewMail();
-
-		// first mail all kDObjects which are intersected by the object
-		preprocessor->mKdTree->CollectKdObjects(box, objects);
-
-	} 
-	else 
-	{
-		ViewCellContainer viewCells;
-		mViewCellsManager->ComputeBoxIntersections(box, viewCells);
-
-		// add object to all viewcells that intersect the bounding box
-		ObjectPvs pvs;
-
-		ViewCellContainer::const_iterator it = viewCells.begin(), it_end = viewCells.end();
-
-		for (int i = 0; it != it_end; ++ it, ++ i) 
-		{
-			//cout<<"v"<<i<<" pvs="<<(*it)->GetPvs().mEntries.size()<<endl;
-			pvs.MergeInPlace((*it)->GetPvs());
-		}
-
-		ObjectPvsIterator pit = pvs.GetIterator();
-		while (pit.HasMoreEntries())  
-		{		
-			PvsData pvsData;
-			Intersectable *object = pit.Next(pvsData);
-			objects.push_back(object);
-		}
-	}
-
-	int pvsCounter = 0;
-
-	// now search for pvss which contained any mailed node
-	for (vit = mViewCellsManager->GetViewCells().begin(); vit != vit_end; ++ vit) 
-	{
-		ObjectPvs &pvs = (*vit)->GetPvs();
-
-		for (int i=0; i < objects.size(); i++) 
-		{
-			vector<PvsEntry<Intersectable *,PvsData> >::iterator v;
+  
+  AxisAlignedBox3 box = leaf->GetBox();
+  Intersectable *inter = leaf->GetIntersectable();
+  int removedEntries = 0;
+  
+  // now search for pvss which contained any mailed node
+  for (vit = mViewCellsManager->GetViewCells().begin(); vit != vit_end; ++ vit) {
+	ObjectPvs &pvs = (*vit)->GetPvs();
+	if (Overlap(box, (*vit)->GetBox())) {
+	  pvs.Clear();
+	  removedEntries += pvs.GetSize();
+	} else {
+	  CSeparatingAxisTester shadowVolume;
+	  
+	  //	cout<<(*vit)->GetBox()<<" "<<box<<endl;
+	  shadowVolume.Init((*vit)->GetBox(), box);
+	  
+	  int j = 0;
+	  for (int i=0; i < pvs.mEntries.size(); i++) {
+		Intersectable *o = pvs.mEntries[i].mObject;
 		
-			if (pvs.Find(objects[i], v)) {
-				// clear the pvs
-				pvs.Clear();
-				pvsCounter++;
-				break;
-			}
-		}
-	}
-
-	cout<<"Number of affected objects "<<objects.size()<<endl;
-	cout<<"Cleared "<<pvsCounter<<" PVSs ("<<mViewCellsManager->GetViewCells().size()/
-		(float)pvsCounter*100.0f<<"%) "<<endl;
-
+		if (!shadowVolume.TestIsInsideShaft(o->GetBox())) {
+		  if (j != i)
+			pvs.mEntries[j] = pvs.mEntries[i];
+		  j++;
+		} else {
+		  removedEntries++;
+		}
+	  }
+	  pvs.mLastSorted = 0;
+	  if (j==0)
+		pvs.mEntries.clear();
+	  else {
+		pvs.mEntries.resize(j);
+		pvs.SimpleSort();
+	  }
+	}
+  }
+  
+  cerr<<"Number of removed pvs entries = "<<removedEntries<<endl;
+  //	cout<<"Cleared "<<pvsCounter<<" PVSs ("<<mViewCellsManager->GetViewCells().size()/
+  //	  (float)pvsCounter*100.0f<<"%) "<<endl;
+  
 }
 
@@ -1745,7 +1726,7 @@
 			cout<<"done."<<endl;
 			
-			cout<<"Updating affected PVSs..."<<endl;
+			cerr<<"Updating affected PVSs..."<<endl;
 			preprocessor->ObjectMoved(l);
-			cout<<"done."<<endl;	  
+			cerr<<"done."<<endl;	  
 		}
         
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/QtInterface/QtGlRenderer.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/QtInterface/QtGlRenderer.cpp	(revision 2706)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/QtInterface/QtGlRenderer.cpp	(revision 2707)
@@ -333,5 +333,5 @@
 			char filename[256];
 			//sprintf(filename, "error-frame-%04d-%0.5f.png", mFrame, pErrorPixels);
-			sprintf_s(filename, "error-frame-%04d-%04d-%08d.png", mFrame, viewcell->GetId(), pixelCount);
+			sprintf(filename, "error-frame-%04d-%04d-%08d.png", mFrame, viewcell->GetId(), pixelCount);
 			QImage im = toImage();
 			string str = mSnapPrefix + filename;
@@ -367,5 +367,5 @@
 
 				im = toImage();
-				sprintf_s(filename, "error-frame-%04d-%04d-%08d-pvs.png", mFrame, viewcell->GetId(), pixelCount);
+				sprintf(filename, "error-frame-%04d-%04d-%08d-pvs.png", mFrame, viewcell->GetId(), pixelCount);
 				str = mSnapPrefix + filename;
 				qstr = str.c_str();
@@ -1043,5 +1043,5 @@
 			break;
 
-		if (sscanf_s(text.toAscii(), "%f %f %f", &mViewPoint.x, &mViewPoint.y, &mViewPoint.z) == 3) {
+		if (sscanf(text.toAscii(), "%f %f %f", &mViewPoint.x, &mViewPoint.y, &mViewPoint.z) == 3) {
 			text.sprintf("%f %f %f", mViewDirection.x, mViewDirection.y, mViewDirection.z);
 			text = QInputDialog::getText(this,
@@ -1053,5 +1053,5 @@
 			if (!ok)
 				break;
-			if (sscanf_s(text.toAscii(), "%f %f %f", &mViewDirection.x,
+			if (sscanf(text.toAscii(), "%f %f %f", &mViewDirection.x,
 				&mViewDirection.y, &mViewDirection.z) == 3) {
 					updateGL();
@@ -2194,5 +2194,5 @@
 #endif
 
-#if 0
+#if 1
 	QGroupBox *groupBox4 = CreateTrafoPanel(hbox);
 	vh->addWidget(groupBox4, 0, 0);
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h	(revision 2636)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h	(revision 2707)
@@ -442,4 +442,14 @@
 }
 
+template <typename T, typename S>
+void VerbosePvs<T, S>::Remove(typename vector<PvsEntry<T, S> >::iterator &it)
+{
+
+  mEntries.erase(it);
+  -- mLastSorted; // wrong if sample was in tail!!
+  // $$JB decrement only if the sample found
+  -- mSamples;
+  
+}
 
 template <typename T, typename S>
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/Makefile
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/Makefile	(revision 2701)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/Makefile	(revision 2707)
@@ -1,5 +1,5 @@
 #############################################################################
 # Makefile for building: preprocessor
-# Generated by qmake (2.00a) (Qt 4.1.2) on: pá 23. V 15:20:40 2008
+# Generated by qmake (2.00a) (Qt 4.1.2) on: so 24. V 22:09:30 2008
 # Project:  preprocessor.pro
 # Template: app
@@ -63,5 +63,5 @@
 	$(MAKE) -f $(MAKEFILE).Debug uninstall
 
-Makefile: preprocessor.pro  C:/Qt/4.1.2/mkspecs/win32-msvc2005\qmake.conf C:/Qt/4.1.2/mkspecs/qconfig.pri \
+Makefile: preprocessor.pro  C:/Qt/4.1.2/mkspecs/win32-msvc.net\qmake.conf C:/Qt/4.1.2/mkspecs/qconfig.pri \
 		C:\Qt\4.1.2\mkspecs\features\qt_config.prf \
 		C:\Qt\4.1.2\mkspecs\features\exclusive_builds.prf \
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/PvsBase.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/PvsBase.h	(revision 2696)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/PvsBase.h	(revision 2707)
@@ -4,5 +4,5 @@
 #include "common.h"
 #include "Containers.h"
-
+#include <vector>
 
 namespace GtpVisibilityPreprocessor {
@@ -145,11 +145,16 @@
 	}
 
+  
 	inline T Next() { return (*(mItCurrent ++)).mObject; }
 
-
-private:
-	
-	typename vector<PvsEntry<T, S> >::const_iterator mItCurrent;
-	typename vector<PvsEntry<T, S> >::const_iterator mItEnd;
+  inline T Current(S &pdf) {
+	pdf = (*mItCurrent).mData;
+	return (*(mItCurrent)).mObject;
+  }
+
+  //private:
+	
+  typename vector<PvsEntry<T, S> >::const_iterator mItCurrent;
+  typename vector<PvsEntry<T, S> >::const_iterator mItEnd;
 };
 
@@ -261,5 +266,7 @@
 	@param visibleSamples number of references to be removed
 	*/
-	bool RemoveSample(T sample, const float pdf);
+  bool RemoveSample(T sample, const float pdf);
+
+  void Remove(typename vector<PvsEntry<T, S> >::iterator &it);
 
 	/** Compute continuous PVS difference 
@@ -334,5 +341,5 @@
 	VerbosePvsStats mStats;
 
-protected:
+  //protected:
 
 	/** Merge pvs 1 from begin iterator to end iterator with
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/SepPlanesBox3.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/SepPlanesBox3.cpp	(revision 2707)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/SepPlanesBox3.cpp	(revision 2707)
@@ -0,0 +1,254 @@
+#include <iostream>
+#include "AxisAlignedBox3.h"
+#include "SepPlanesBox3.h"
+
+#include <cassert>
+using namespace std;
+
+namespace GtpVisibilityPreprocessor {
+
+int
+Side(const Plane3 &pl, const AxisAlignedBox3 &box)
+{
+  // Better implementation than below, takes the
+  // problem as computing the extrema of the function
+  // Written by V.H. in November 2001.
+  float sumMin = pl.mD;
+  float sumMax = pl.mD;
+  const Vector3 &min = box.Min();
+  const Vector3 &max = box.Max();
+
+  // maximize and minimize the value for the function
+  // normal * vertex + d
+  
+  // for x-axis
+  if (pl.mNormal.x >= 0.0) {
+    sumMax += pl.mNormal.x * max.x;
+    sumMin += pl.mNormal.x * min.x;
+  }
+  else {
+    sumMin += pl.mNormal.x * max.x;
+    sumMax += pl.mNormal.x * min.x;
+  }
+  
+  // for y-axis
+  if (pl.mNormal.y >= 0.0) {
+    sumMax += pl.mNormal.y * max.y;
+    sumMin += pl.mNormal.y * min.y;
+  }
+  else {
+    sumMin += pl.mNormal.y * max.y;
+    sumMax += pl.mNormal.y * min.y;
+  }
+  
+  // for z-axis
+  if (pl.mNormal.z >= 0.0) {
+    sumMax += pl.mNormal.z * max.z;
+    sumMin += pl.mNormal.z * min.z;
+  }
+  else {
+    sumMin += pl.mNormal.z * max.z;
+    sumMax += pl.mNormal.z * min.z;
+  }
+  
+  if (sumMax >= 0.0) {
+    if (sumMin >= 0.0)
+      return 1; // box only in positive halfspace
+    return 0; // box is intersected by the plane
+  }
+
+  // sumMax < 0.0
+  assert(sumMin < 0.0);
+  
+  return -1; // box only in the negative halfspace
+}
+
+  
+  // constructor, no planes
+CSeparatingAxisTester::CSeparatingAxisTester()
+{
+  cntPlanes = 0;
+}
+
+void
+CSeparatingAxisTester::InsertPlane(const Plane3 &pl)
+{
+  assert(cntPlanes < 16);
+  planes[cntPlanes].mNormal = pl.mNormal;
+  planes[cntPlanes].mD = pl.mD;
+  cntPlanes++;
+}
+
+void
+CSeparatingAxisTester::OnePhase(const AxisAlignedBox3 &origBox,
+				const AxisAlignedBox3 &shadBox,
+				const Vector3 &pointBACKSIDE)
+{
+  Vector3 centerOrig = origBox.Center();
+  Vector3 centerShad = shadBox.Center();
+  const float eps = 1e-3;
+  int cnt = 0;
+  
+  // We check first for all edges of the 'origBox' and one
+  // vertex of the 'shadBox' existence of the plane.
+  for (int i = 0; i < 12; i++) {
+    Vector3 a,b;
+    // You get one edge from the orig box
+    origBox.GetEdge(i, &a, &b);
+    // Move the vertices a bit outside the box
+    a += eps * (a-centerOrig);
+    b += eps * (b-centerOrig);
+
+    // Now you take all the vertices from the 'shadBox',
+    // which contains a new position of the moved object
+    for (int j = 0; j < 8; j++) {
+      Vector3 c;
+      shadBox.GetVertex(j, c);
+      c += eps * (c-centerShad);
+      Plane3 pl(a, b, c);
+
+      cnt++;
+      // if (cnt == 17) { cout << "Problem " << endl; }
+      
+      int centerFlag = pl.Side(pointBACKSIDE, 1e-6);
+      if (centerFlag == Plane3:: INTERSECTS)
+	continue; // plane crosses the center of the box!
+      
+      if (centerFlag == Plane3::FRONT_SIDE) {
+	// we have to change the plane orientation
+	pl.mNormal = -pl.mNormal;
+	pl.mD = -pl.mD;
+	centerFlag = Plane3::BACK_SIDE;
+	assert(pl.Side(pointBACKSIDE, 1e-6) == Plane3::BACK_SIDE);
+      } 
+
+      // Check if the shad box is on one side of the plane
+      if ((Side(pl, origBox) == Plane3::FRONT_SIDE) &&
+	  (Side(pl, shadBox) == Plane3::BACK_SIDE)) {
+	//cout << "Inserting plane normal=" << pl.mNormal
+	//     << " mD=" << pl.mD << endl;
+	InsertPlane(pl);
+      }
+    } // for j
+  } // for i
+}
+
+// brute force separating planes construction algorithm
+void
+CSeparatingAxisTester::Init(const AxisAlignedBox3 &origBox,
+							const AxisAlignedBox3 &shadBox)
+{
+  // test all edges of the axis aligned box
+  Vector3 a,b;
+  const float eps = 1e-3;
+  Vector3 centerShad = shadBox.Center();
+
+  cntPlanes = 0;
+
+  // First, we check for all edges of the 'origBox' and one
+  // vertex of the 'shadBox' existence of the plane.
+  OnePhase(origBox, shadBox, centerShad);
+
+  // Second, we check for all edges of the 'shadBox' and one
+  // vertex of the 'origBox' existence of the plane.
+  OnePhase(shadBox, origBox, centerShad);
+  
+  // Finally, we add the separating plane, which touches the
+  // 'shadBox', lies between 'origBox' and 'shadBox',
+  // 'origBox' lies in the FRONT_SIDE of this plane, and
+  // 'shadBox' lies in the BACK_SIDE of this plane.
+  
+  Vector3 centerOrig = origBox.Center();
+  Vector3 normal = Normalize(centerOrig - centerShad);
+  // Now we check all the vertices of the shadBox and find the
+  // one closest to the box
+  bool f = false;
+  for (int i = 0; i < 8; i++) {
+    Vector3 c;
+    shadBox.GetVertex(i, c);
+    c += eps * (c-centerShad);
+    Plane3 pl(normal, c);
+    if (Side(pl, shadBox) == -1) {
+      assert(pl.Side(centerShad, 1e-6) == Plane3::BACK_SIDE);
+      //assert(pl.Side(centerOrig, 1e-6) == Plane3::FRONT_SIDE);
+      InsertPlane(pl);
+      f = true;
+      break;
+    }
+  } // for all vertices
+
+  if (!f) {
+    cout << "Problem finding last separating plane" << endl;
+    abort();
+  }
+  
+  return;
+}
+  
+// This function returns true if a ray starting
+// in the 'origBox' and intersecting 'shadBox'
+// can intersect the box as input of this function
+bool
+CSeparatingAxisTester::TestIsInsideShaft(const AxisAlignedBox3 &testBox)
+{
+  for (int i = 0; i < cntPlanes; i++) {
+    if (Side(planes[i], testBox) == Plane3::FRONT_SIDE)
+      // there is such a plane which separates 'origBox' and 'shadBox'
+      // that no ray can intersect all three boxes, starting in 'origBox'
+      return false; 
+  }
+
+  // there is a ray intersecting 'origBox', 'shadBox', and 'testBox'
+  // at the same time
+  return true; 
+}
+  
+// Testing code
+void
+TestSepAxis()
+{
+  CSeparatingAxisTester st;
+#if 0
+  Vector3 vo1(0, 0, 0);
+  Vector3 vo2(1, 1, 1);
+
+  Vector3 vs1(10, -1, -1);
+  Vector3 vs2(11, 1, 1);
+#else
+  // JB test
+  Vector3 vo1(1279.08, 211.942, -76.4611);
+  Vector3 vo2(1395.34, 215.833, 37.5);
+  Vector3 vs1(-2446.14, 1381.31, -2621.98);
+  Vector3 vs2(-2426.14, 1391.57, -2608.9);
+#endif
+  
+  st.Init(AxisAlignedBox3(vo1, vo2),
+	  AxisAlignedBox3(vs1, vs2));
+
+  // Box that should return true
+  Vector3 vt1(10, -1, 1);
+  Vector3 vt2(11, -1, 1);
+  int res = st.TestIsInsideShaft(AxisAlignedBox3(vt1, vt2));
+  cout << "Res1 = " << res << endl;
+
+  // Box that should return true
+  vt1.SetValue(11, 1, 1);
+  vt2.SetValue(12, 2, 2);
+  res = st.TestIsInsideShaft(AxisAlignedBox3(vt1, vt2));
+  cout << "Res2 = " << res << endl;
+  
+  // Box that should return false
+  vt1.SetValue(-1, -1, -1);
+  vt2.SetValue(1, 1, 1);
+  res = st.TestIsInsideShaft(AxisAlignedBox3(vt1, vt2));
+  cout << "Res3 = " << res << endl;
+
+  // Box that should also return false
+  vt1.SetValue(12, 12, 12);
+  vt2.SetValue(13, 13, 13);
+  res = st.TestIsInsideShaft(AxisAlignedBox3(vt1, vt2));
+  cout << "Res4 = " << res << endl;
+}
+
+}
+
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp	(revision 2706)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp	(revision 2707)
@@ -27,4 +27,5 @@
 #include "RayCaster.h"
 #include "ViewCellsManager.h"
+#include "SepPlanesBox3.h"
 
 
@@ -169,4 +170,7 @@
 	Debug.open("debug.log");
 
+	
+	TestSepAxis();
+	
 	Environment::GetSingleton()->Parse(argc, argv, USE_EXE_PATH);
 	MeshKdTree::ParseEnvironment();
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/SepPlanesBox3.h
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/SepPlanesBox3.h	(revision 2707)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/SepPlanesBox3.h	(revision 2707)
@@ -0,0 +1,60 @@
+#ifndef _SeparatingPlanesBox3_H__
+#define _SeparatingPlanesBox3_H__
+
+#include "AxisAlignedBox3.h"
+#include "Matrix4x4.h"
+#include "Vector3.h"
+#include "Plane3.h"
+#include "Containers.h"
+
+namespace GtpVisibilityPreprocessor {
+
+
+// Written by Vlastimil Havran, May 2008, in the scope
+// of Progressive Visibility Sampling project.
+  
+// This class given two axis aligned boxes can construct all the
+// separating planes between two boxes. It gets the boxes as 'origBox'
+// containing ray origin, and 'shadBox', containing shadowing object,
+// to which the ray is aimed at. The constructed planes can found if a
+// 'testBox' cannot be intersected by a ray starting from the origBox
+// and intersecting the 'shadBox'.
+
+class CSeparatingAxisTester
+{
+  // the number of separating planes
+  int cntPlanes;
+  Plane3 planes[18];
+  AxisAlignedBox3 origBox;
+  AxisAlignedBox3 shadBox;
+
+  void InsertPlane(const Plane3 &pl);
+
+  void OnePhase(const AxisAlignedBox3 &origBox,
+				const AxisAlignedBox3 &shadBox,
+				const Vector3 &pointBACKSIDE);
+  
+public:
+  CSeparatingAxisTester();
+
+  // Initialize with two boxe, the 'origBox' contains
+  // origin of the ray, 'shadBox' is the shadowing
+  // box, which contains new position of the object
+  // and to which a ray aims at.
+  void Init(const AxisAlignedBox3 &origBox,
+			const AxisAlignedBox3 &shadBox);
+
+  // This function returns true if a ray starting
+  // in the 'origBox' and intersecting 'shadBox'
+  // can intersect the box as input of this function
+  bool TestIsInsideShaft(const AxisAlignedBox3 &testBox);
+  
+  // returns number of separating planes
+  int CntPlanes() const { return cntPlanes;}
+};
+
+// Testing code 
+void  TestSepAxis();
+  
+}
+#endif
Index: /GTP/trunk/Lib/Vis/Preprocessing/src/preprocessor.pro
===================================================================
--- /GTP/trunk/Lib/Vis/Preprocessing/src/preprocessor.pro	(revision 2701)
+++ /GTP/trunk/Lib/Vis/Preprocessing/src/preprocessor.pro	(revision 2707)
@@ -125,5 +125,6 @@
 Intersectable.cpp TraversalTree.cpp ObjectPvs.cpp ObjectsParser.cpp \
 FilterBasedDistribution.cpp DifferenceSampling.cpp HavranRayCaster.cpp \
-HavranDynRayCaster.cpp OcclusionQuery.cpp RandomViewCellsHandler.cpp
+HavranDynRayCaster.cpp OcclusionQuery.cpp RandomViewCellsHandler.cpp \
+SepPlanesBox3.cpp
 
 
