Index: GTP/trunk/Lib/Vis/Preprocessing/src/default.env
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/default.env	(revision 1942)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/default.env	(revision 1952)
@@ -73,5 +73,5 @@
 	}
 	Export {
-		rays true
+		rays false
 		numRays 5000
 	}
@@ -104,5 +104,5 @@
 	samplesPerPass 1000000
 	initialSamples 2000000
-	vssSamples 20000000
+	vssSamples 500000000
 	vssSamplesPerPass 5000000
 	useImportanceSampling true
@@ -137,5 +137,5 @@
  	maxCostRatio 1.0
 	maxRayContribution 1.0
-	maxRays		2000000
+	maxRays		1000000
 	maxTotalMemory	400
 	maxStaticMemory	200
Index: GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.h	(revision 1949)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.h	(revision 1952)
@@ -9,5 +9,5 @@
 namespace GtpVisibilityPreprocessor {
 
-
+  class VssRay;
 class Preprocessor;
 struct SimpleRay;
@@ -40,5 +40,7 @@
 		REVERSE_VIEWSPACE_BORDER_BASED_DISTRIBUTION,
 	  GLOBAL_LINES_DISTRIBUTION,
-	  GVS
+	  GVS,
+	  MUTATION_BASED_DISTRIBUTION
+
 	};
 
@@ -146,4 +148,5 @@
 private:
   virtual bool GenerateSample(SimpleRay &ray);
+  static HaltonSequence sHalton;
 };
 
@@ -216,4 +219,29 @@
 private:
   virtual bool GenerateSample(SimpleRay &ray);
+};
+
+class MutationBasedDistribution: public SamplingStrategy
+{
+public:
+  MutationBasedDistribution(Preprocessor &preprocessor);
+  virtual void Update(VssRayContainer &vssRays);
+
+  virtual bool RequiresRays() { return true; }
+
+private:
+  virtual bool GenerateSample(SimpleRay &ray);
+  static HaltonSequence sHalton;
+  struct RayEntry {
+	VssRay *mRay;
+	int mSamples;
+	RayEntry();
+	RayEntry(VssRay *r):mRay(r), mSamples(0) {}
+  };
+  
+  vector<RayEntry> mRays;
+  int mMaxRays;
+  float mOriginMutationSize;
+  int mBufferStart;
+  int mLastIndex;
 };
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1949)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1952)
@@ -2039,5 +2039,5 @@
 		  PvsFilterStatistics fstat = ApplyFilter2(viewcell,
 												   false,
-												   2.0f,
+												   4.0f,
 												   filteredPvs);
 		  
Index: GTP/trunk/Lib/Vis/Preprocessing/src/IntelRayCaster.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/IntelRayCaster.cpp	(revision 1942)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/IntelRayCaster.cpp	(revision 1952)
@@ -7,5 +7,5 @@
 #include "ArchModeler2MLRT.hxx"
 
-#define DEBUG_RAYCAST 0 
+#define DEBUG_RAYCAST 0
 
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Makefile
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Makefile	(revision 1946)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Makefile	(revision 1952)
@@ -1,5 +1,5 @@
 #############################################################################
 # Makefile for building: preprocessor
-# Generated by qmake (2.00a) (Qt 4.1.2) on: pá 5. I 19:57:11 2007
+# Generated by qmake (2.00a) (Qt 4.1.2) on: ne 7. I 23:22:46 2007
 # Project:  preprocessor.pro
 # Template: app
@@ -63,5 +63,5 @@
 	$(MAKE) -f $(MAKEFILE).Debug uninstall
 
-Makefile: preprocessor.pro  C:/Qt/4.1.2/mkspecs/win32-msvc.net\qmake.conf C:/Qt/4.1.2/mkspecs/qconfig.pri \
+Makefile: preprocessor.pro  C:/Qt/4.1.2/mkspecs/win32-msvc2005\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/RayCaster.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/RayCaster.cpp	(revision 1942)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/RayCaster.cpp	(revision 1952)
@@ -45,4 +45,5 @@
 							  Vector3 &clippedTermination)
 {
+  
   Ray ray(origin, termination - origin, Ray::LINE_SEGMENT);	
   ray.Precompute();
@@ -132,25 +133,23 @@
 
 #if DEBUG_RAYCAST
-	Debug<<"PRA"<<flush;
-#endif
-
-	// regardless of the pruneInvalidRays setting reject rays whic degenerate to a point
-	//	if (EpsilonEqualV3(hitA.mPoint, hitB.mPoint, Limits::Small))
-	//	  return 0;
+	static int id=0;
+	Debug<<"PRA "<<id++<<endl<<flush;
+#endif
 	
 	if (pruneInvalidRays) 
 	{
-		if (!hitA.mObject && !hitB.mObject) 
-		{
-			return 0;
-		}
-	}
-	
-	const bool validA = 
-	  ValidateRay(simpleRay.mOrigin, simpleRay.mDirection, box, hitA);
-	
-	// note: should we check for backward valitidy also for single rays?
+	  if (!hitA.mObject && !hitB.mObject) {
+		return 0;
+	  }
+	  if (EpsilonEqualV3(hitA.mPoint, hitB.mPoint, Limits::Small)) {
+		return 0;
+	  }
+	}
+	
+	// regardless of the pruneInvalidRays setting reject rays whic degenerate to a point
+	const bool validA = ValidateRay(simpleRay.mOrigin, simpleRay.mDirection, box, hitA);
 	const bool validB = //castDoubleRay && 
-		ValidateRay(simpleRay.mOrigin, -simpleRay.mDirection, box, hitB);
+	  ValidateRay(simpleRay.mOrigin, -simpleRay.mDirection, box, hitB);
+	
 	
 #if DEBUG_RAYCAST
@@ -159,14 +158,13 @@
 	
 	// reset both contributions
-	if (!validA || !validB)
-	{
-		if (pruneInvalidRays)
-			return 0;
-		
-		// reset both contributions of this ray
-		hitA.mObject = NULL;
-		hitB.mObject = NULL;
-	}
+	if (!validA || !validB) {
+	  if (pruneInvalidRays)
+		return 0;
 	  
+	  // reset both contributions of this ray
+	  hitA.mObject = NULL;
+	  hitB.mObject = NULL;
+	}
+	
 	// 8.11. 2007 JB
 	// degenerate rays checked by geometrical constraint...
@@ -185,4 +183,5 @@
 							  clipB))
 		return 0;
+
 	  if (!pruneInvalidRays || hitA.mObject) {
 		VssRay *vssRay = new VssRay(
Index: GTP/trunk/Lib/Vis/Preprocessing/src/preprocessor.pro
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/preprocessor.pro	(revision 1942)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/preprocessor.pro	(revision 1952)
@@ -116,7 +116,7 @@
 
 CONFIG(qt) {
-HEADERS += QtPreprocessorThread.h QtInterface/QtGlRenderer.h \
+HEADERS += QtInterface/QtPreprocessorThread.h QtInterface/QtGlRenderer.h \
 QtInterface/QtGlViewer.h
-SOURCES += OcclusionQuery.cpp QtPreprocessorThread.cpp \
+SOURCES += OcclusionQuery.cpp QtInterface/QtPreprocessorThread.cpp \
 QtInterface/QtGlRenderer.cpp QtInterface/QtGlViewer.cpp 
 } else {
Index: GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.cpp	(revision 1942)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.cpp	(revision 1952)
@@ -17,4 +17,6 @@
 HaltonSequence SpatialBoxBasedDistribution::sHalton;
 HaltonSequence ObjectDirectionBasedDistribution::sHalton;
+HaltonSequence DirectionBasedDistribution::sHalton;
+HaltonSequence MutationBasedDistribution::sHalton;
 
 
@@ -153,19 +155,25 @@
 bool DirectionBasedDistribution::GenerateSample(SimpleRay &ray)
 {	
-	Vector3 origin, direction; 
-	mPreprocessor.mViewCellsManager->GetViewPoint(origin);
-	 
-	direction = UniformRandomVector();
-	const float c = Magnitude(direction);
-
-	if (c <= Limits::Small) 
-		return false;
-
-	const float pdf = 1.0f;
-
-	direction *= 1.0f / c;
-	ray = SimpleRay(origin, direction, DIRECTION_BASED_DISTRIBUTION, pdf);
-
-	return true;
+
+  float r[5];
+  sHalton.GetNext(5, r);
+
+  Vector3 origin, direction; 
+  mPreprocessor.mViewCellsManager->GetViewPoint(origin,
+												Vector3(r[2],r[3],r[4])
+												);
+  
+  direction = UniformRandomVector(r[0], r[1]);
+  const float c = Magnitude(direction);
+  
+  if (c <= Limits::Small) 
+	return false;
+  
+  const float pdf = 1.0f;
+  
+  direction *= 1.0f / c;
+  ray = SimpleRay(origin, direction, DIRECTION_BASED_DISTRIBUTION, pdf);
+  
+  return true;
 }
 
@@ -630,5 +638,9 @@
 				  if (strcmp(curr, "reverse_viewspace_border")==0) {
 					mDistributions.push_back(new ReverseViewSpaceBorderBasedDistribution(mPreprocessor));
-				  } 
+				  } else
+					if (strcmp(curr, "mutation")==0) {
+					  mDistributions.push_back(new MutationBasedDistribution(mPreprocessor));
+					} 
+	
 	
 	if (e==NULL)
@@ -641,5 +653,152 @@
 }
 
-}
-
-
+
+
+void
+MutationBasedDistribution::Update(VssRayContainer &vssRays)
+{
+  //  for (int i=0; i < mRays.size(); i++)
+  //	cout<<mRays[i].mSamples<<" ";
+  //  cout<<endl;
+  
+  for (int i=0; i < vssRays.size(); i++) {
+	VssRay *newRay = vssRays[i];
+	if (newRay->mPvsContribution) {
+	  // add this ray
+	  newRay->Ref();
+	  if (mRays.size() < mMaxRays)
+		mRays.push_back(RayEntry(newRay));
+	  else {
+		// unref the old ray
+		VssRay *oldRay = mRays[mBufferStart].mRay;
+		oldRay->Unref();
+		if (oldRay->RefCount() == 0)
+		  delete oldRay;
+		mRays[mBufferStart] = RayEntry(newRay);
+		mBufferStart++;
+		if (mBufferStart >= mMaxRays)
+		  mBufferStart = 0;
+	  }
+	}
+  }
+}
+
+bool
+MutationBasedDistribution::GenerateSample(SimpleRay &sray)
+{
+  float r[5];
+  sHalton.GetNext(5, r);
+
+  if (mRays.size() == 0) {
+	// use direction based distribution
+	Vector3 origin, direction;
+	mPreprocessor.mViewCellsManager->GetViewPoint(origin,
+												  Vector3(r[0], r[1], r[2]));
+	
+	direction = UniformRandomVector(r[3], r[4]);
+	
+	const float pdf = 1.0f;
+	sray = SimpleRay(origin, direction, MUTATION_BASED_DISTRIBUTION, pdf);
+
+	return true;
+  } 
+  
+  //  int index = (int) (r[0]*mRays.size());
+  //  if (index >= mRays.size()) {
+  //	cerr<<"mutation: index out of bounds\n";
+  //	exit(1);
+  //  }
+
+  // get tail of the buffer
+  int index = (mLastIndex+1)%mRays.size();
+  if (mRays[index].mSamples > mRays[mLastIndex].mSamples) {
+	// search back for index where this is valid
+	index = (mLastIndex - 1 + mRays.size())%mRays.size();
+	for (int i=0; i < mRays.size(); i++) {
+	  if (mRays[index].mSamples > mRays[mLastIndex].mSamples)
+		break;
+	  index = (index - 1 + mRays.size())%mRays.size();
+	}
+	// go one step back
+	index = (index+1)%mRays.size();
+  }
+  
+  VssRay *ray = mRays[index].mRay;
+  mRays[index].mSamples++;
+  mLastIndex = index;
+  
+  Vector3 v;
+  // mutate the origin
+  Vector3 d = ray->GetDir();
+  if (d.DrivingAxis() == 0)
+	v = Vector3(0, r[1]-0.5f, r[2]-0.5f);
+  else
+	if (d.DrivingAxis() == 1)
+	  v = Vector3(r[1]-0.5f, 0, r[2]-0.5f);
+	else
+	  v = Vector3(r[1]-0.5f, r[2]-0.5f, 0);
+
+  v=v*mOriginMutationSize;
+
+  Vector3 origin = ray->mOrigin + v;
+  
+  // mutate the termination
+  if (d.DrivingAxis() == 0)
+	v = Vector3(0, r[3]-0.5f, r[4]-0.5f);
+  else
+	if (d.DrivingAxis() == 1)
+	  v = Vector3(r[3]-0.5f, 0, r[4]-0.5f);
+	else
+	  v = Vector3(r[3]-0.5f, r[4]-0.5f, 0);
+
+  float size = 1.5f*Magnitude(ray->mTerminationObject->GetBox().Diagonal());
+  if (size < Limits::Small)
+	return false;
+  
+//   Vector3 nv;
+  
+//   if (Magnitude(v) > Limits::Small)
+// 	nv = Normalize(v);
+//   else
+// 	nv = v;
+  
+//  v = nv*size + v*size;
+
+  v = v*size;
+
+  Vector3 termination = ray->mTermination + v;
+  
+  Vector3 direction = termination - origin;
+
+  if (Magnitude(direction) < Limits::Small)
+	return false;
+
+  // shift the origin a little bit
+  origin += direction*0.05f;
+
+  direction.Normalize();
+  
+  // $$ jb the pdf is yet not correct for all sampling methods!
+  const float pdf = 1.0f;
+  
+  sray = SimpleRay(origin, direction, MUTATION_BASED_DISTRIBUTION, pdf);
+  return true;
+}
+
+MutationBasedDistribution::MutationBasedDistribution(Preprocessor &preprocessor) :
+  SamplingStrategy(preprocessor)
+{
+  mType = MUTATION_BASED_DISTRIBUTION;
+  mBufferStart = 0;
+  mMaxRays = 1000000;
+
+  mOriginMutationSize = 2.0f;
+  mLastIndex = 0;
+  //  mOriginMutationSize = Magnitude(preprocessor.mViewCellsManager->
+  //								  GetViewSpaceBox().Diagonal())*1e-3;
+  
+}
+
+}
+
+
