Index: GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.h	(revision 1695)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.h	(revision 1763)
@@ -109,4 +109,14 @@
 
 
+class ViewCellBorderBasedDistribution: public SamplingStrategy
+{
+ public:
+	 ViewCellBorderBasedDistribution(const Preprocessor &preprocessor):
+	 SamplingStrategy(preprocessor) {}
+	 
+	 virtual bool GenerateSample(SimpleRay &ray) const;
+};
+
+
 /** This strategy generates samples inside of the objects, e.g.,
 	for sampling the inside of a colon.
Index: GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp	(revision 1761)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp	(revision 1763)
@@ -84,4 +84,20 @@
 }
 
+
+int BvhNode::GetRandomEdgePoint(Vector3 &point,
+								Vector3 &normal)
+{
+	// get random edge
+	const int idx = Random(12); 
+	Vector3 a, b;
+	mBoundingBox.GetEdge(idx, &a, &b);
+	
+	const float factor = RandomValue(0.0f, 1.0f);
+
+	point = a * factor + b * (1 - factor);
+	//normal = mBoundingBox.GetNormal();
+
+	return idx;
+}
 
 
@@ -415,5 +431,5 @@
 	
 	// set the time stamp so the order of traversal can be reconstructed
-	node->mTimeStamp = mHierarchyManager->mTimeStamp ++;
+	node->SetTimeStamp(mHierarchyManager->mTimeStamp ++);
 		
 	// assign the objects in sorted order
@@ -1699,5 +1715,4 @@
 		numRays += CollectViewCells(*oit, viewCells, true, setCounter, onlyMailedRays);
 	}
-	//cout << "here4 " << numRays << " boj: " << objects.size() << " " << onlyMailedRays << endl;
 
 	return numRays;
@@ -1818,5 +1833,4 @@
 	int numRays = CollectViewCells(node->mObjects, viewCells, false, false);
 
-	//cout << "here6 " << numRays << endl;
 	if (0) cout << "collected " << (int)viewCells.size() << " dirty candidates" << endl;
 	
@@ -2353,6 +2367,6 @@
 		BvhSubdivisionCandidate *backCandidate = new BvhSubdivisionCandidate(tBackData);
 
-		frontCandidate->SetPriority((float)-oldInterior->GetFront()->mTimeStamp);
-		backCandidate->SetPriority((float)-oldInterior->GetBack()->mTimeStamp);
+		frontCandidate->SetPriority((float)-oldInterior->GetFront()->GetTimeStamp());
+		backCandidate->SetPriority((float)-oldInterior->GetBack()->GetTimeStamp());
 
 		frontCandidate->mEvaluationHack = oldInterior->GetFront();
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1761)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1763)
@@ -1579,5 +1579,4 @@
 		mViewCellsTree->UpdateViewCellsStats(*it, mCurrentViewCellsStats);
 	}
-	cout << "here44 " << mCurrentViewCellsStats.maxPvs << endl;
 }
 
@@ -2214,9 +2213,9 @@
 {
 	ViewCellContainer::const_iterator it, it_end = mViewCells.end();
-cout << "here2" << endl;
+
 	for (it = mViewCells.begin(); it != it_end; ++ it)
-	{cout << "here4 " << mOnlyValidViewCells << " " << (*it)->GetValid() <<  endl;
+	{
 		if (!mOnlyValidViewCells || (*it)->GetValid())
-		{cout << "here5 " << mColorCode << endl;
+		{
 			ExportColor(exporter, *it, colorCode);	
 			ExportViewCellGeometry(exporter, *it, sceneBox, clipPlane);
@@ -2789,13 +2788,9 @@
 		
 	case 1: // pvs
-		{ //cout << "here22 " << mCurrentViewCellsStats.maxPvs << endl;
+		{
 			if (mCurrentViewCellsStats.maxPvs)
 			{
-				//cout << "pvscost : " << (float)mViewCellsTree->GetPvsCost(vc) << endl;
-				//cout << "maxPvs : " << (float)mCurrentViewCellsStats.maxPvs << endl;
-
-				importance = 
-					(float)mViewCellsTree->GetPvsCost(vc) / 
-					(float)mCurrentViewCellsStats.maxPvs;
+				importance = (float)mViewCellsTree->GetPvsCost(vc) / 
+							 (float)mCurrentViewCellsStats.maxPvs;
 			}
 		}
@@ -2817,5 +2812,4 @@
 #endif
 	default:
-		cout << "here10" << endl;
 		break;
 	}
@@ -3057,8 +3051,11 @@
 	const int savedColorCode = mColorCode;
 
+	Exporter *exporter;
+
+#if 0
 	// export merged view cells
 	mColorCode = 0; // use random colors
 
-	Exporter *exporter = Exporter::GetExporter("merged_view_cells.wrl");
+	exporter = Exporter::GetExporter("merged_view_cells.wrl");
 
 	cout << "exporting view cells after merge ... ";
@@ -3077,7 +3074,7 @@
 	}
 	cout << "finished" << endl;
+#endif
 
 	// export merged view cells using pvs color coding
-	
 	exporter = Exporter::GetExporter("merged_view_cells_pvs.wrl");
 	cout << "exporting view cells after merge (pvs size) ... ";	
@@ -3092,5 +3089,5 @@
 		exporter->SetFilled();
 		mColorCode = 1;
-cout << "here49 " << mColorCode << endl;
+
 		ExportViewCellsForViz(exporter, NULL,  mColorCode, GetClipPlane());
 
@@ -3183,5 +3180,5 @@
 
 	//  visualization of the view cells
-	if (0) ExportMergedViewCells(objects);
+	if (1) ExportMergedViewCells(objects);
 
 	// compute final meshes and volume / area
@@ -5504,9 +5501,12 @@
 	Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
 
+	Vector3 scale(1.0f, 0.9f, 1.0f);
 	if (exporter)
 	{
+		EvaluateViewCellsStats();
+
 		// hack color code (show pvs size)
 		const int savedColorCode = mColorCode;
-		mColorCode = 0;
+		mColorCode = 1; // export pvs
 
 		const long starttime = GetTime();
@@ -5515,5 +5515,5 @@
 		// matt: hack for clamping scene
 		AxisAlignedBox3 bbox = mViewSpaceBox;
-		bbox.Scale(Vector3(0.5, 1, 0.5));
+		bbox.Scale(scale);
 
 		if (CLAMP_TO_BOX)
@@ -5536,5 +5536,7 @@
 		mHierarchyManager->ExportObjectSpaceHierarchy(exporter, objects, 
 													  CLAMP_TO_BOX ? &bbox : NULL, false);
-		ExportViewCellsForViz(exporter, CLAMP_TO_BOX ? &bbox : NULL, mColorCode, GetClipPlane());
+		
+		//ExportViewCellsForViz(exporter, CLAMP_TO_BOX ? &bbox : NULL, mColorCode, GetClipPlane());
+		ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
 
 		delete exporter;
@@ -5553,5 +5555,5 @@
 		// matt: hack for making visualization smaller in size
 		AxisAlignedBox3 bbox = mHierarchyManager->GetObjectSpaceBox();
-		bbox.Scale(Vector3(0.5, 1, 0.5));
+		bbox.Scale(scale);
 
 		cout << "exporting object space hierarchy ... ";
@@ -5562,10 +5564,7 @@
 	}
 	
-	cout << "here92 " << mHierarchyManager->GetVspTree()->GetStatistics().maxPvs << endl;
-
 	// visualization of the view cells
-    if (1) 
+    if (0) 
 	{	
-		EvaluateViewCellsStats();
 		ExportMergedViewCells(objects);
 	}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp	(revision 1758)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp	(revision 1763)
@@ -1785,5 +1785,4 @@
 	ViewCellContainer::const_iterator it, it_end = leaves.end();
 
-	Intersectable::NewMail();
 	ObjectPvs newPvs;
 
@@ -1791,17 +1790,5 @@
 	for (it = leaves.begin(); it != it_end; ++ it)
 	{
-		ObjectPvsIterator oit = (*it)->GetPvs().GetIterator();
-
-		while (oit.HasMoreEntries())
-		{
-			ObjectPvsEntry entry = oit.Next();
-			Intersectable *intersect = entry.mObject;
-
-			if (!intersect->Mailed())
-			{
-				intersect->Mail();
-				newPvs.AddSample(intersect, entry.mData.mSumPdf);
-			}
-		}
+		newPvs.MergeInPlace((*it)->GetPvs());
 	}
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 1761)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 1763)
@@ -63,5 +63,5 @@
 	{ return rayRefs / (double)Leaves(); } 
 
-
+	
 	void Reset() 
 	{
@@ -201,5 +201,9 @@
 	float GetMergeCost() {return (float)-mTimeStamp; }
 
-	int mTimeStamp;
+	virtual int GetRandomEdgePoint(Vector3 &point,
+								 Vector3 &normal);
+
+	inline int GetTimeStamp() const { return mTimeStamp; }
+	inline void SetTimeStamp(const int timeStamp) { mTimeStamp = timeStamp; };
 
 	/////////////////////////////////////
@@ -269,4 +273,5 @@
 	/// parent of this node
 	BvhInterior *mParent;
+	int mTimeStamp;
 };
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/IntersectableWrapper.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/IntersectableWrapper.cpp	(revision 1758)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/IntersectableWrapper.cpp	(revision 1763)
@@ -92,4 +92,21 @@
 
 
+int TriangleIntersectable::GetRandomEdgePoint(Vector3 &point,
+											  Vector3 &normal)
+{
+	int edge = Random(3);
+
+	Vector3 a = mItem.mVertices[edge];
+	Vector3 b = mItem.mVertices[(edge + 1) % 3];
+
+	const float factor = RandomValue(0.0f, 1.0f);
+
+	point = a * factor + b * factor;
+	normal = mItem.GetNormal();
+
+	return edge;
+}
+
+
 KdIntersectable::KdIntersectable(KdNode *item, const AxisAlignedBox3 &box)  :
   IntersectableWrapper<KdNode *>(item)
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.h	(revision 1419)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.h	(revision 1763)
@@ -245,39 +245,41 @@
 
 public:
-  MeshInstance(Mesh *mesh):Intersectable(), mMesh(mesh), mMaterial(NULL)
-  {
-  }
-
-  int GetRandomSurfacePoint(Vector3 &point, Vector3 &normal);
-
-	int
-	GetRandomVisibleSurfacePoint(Vector3 &point,
-															 Vector3 &normal,
-															 const Vector3 &viewpoint,
-															 const int maxTries
-															 );
-
-
-  Mesh *GetMesh() { return mMesh; }
-
-  virtual AxisAlignedBox3 GetBox() const {
-    return mMesh->mBox;
-  }
-
-  virtual int CastRay(Ray &ray);
-
-  virtual bool IsConvex() const { return mMesh->mIsConvex; }
-  virtual bool IsWatertight() const { return mMesh->mIsWatertight; }
-  virtual float IntersectionComplexity() {  return (float)mMesh->mFaces.size(); }
-
-  virtual int NumberOfFaces() const {  return (int)mMesh->mFaces.size(); }
-
-  virtual int Type() const { return MESH_INSTANCE; }
-
-  virtual int
-  CastRay(
-	  Ray &ray,
-	  const vector<int> &faces
-	  );
+	MeshInstance(Mesh *mesh):Intersectable(), mMesh(mesh), mMaterial(NULL)
+	{
+	}
+
+	int GetRandomSurfacePoint(Vector3 &point, Vector3 &normal);
+
+	int	GetRandomVisibleSurfacePoint(Vector3 &point,
+		Vector3 &normal,
+		const Vector3 &viewpoint,
+		const int maxTries
+		);
+
+
+	virtual int GetRandomEdgePoint(Vector3 &point,
+								 Vector3 &normal);
+
+	Mesh *GetMesh() { return mMesh; }
+
+	virtual AxisAlignedBox3 GetBox() const {
+		return mMesh->mBox;
+	}
+
+	virtual int CastRay(Ray &ray);
+
+	virtual bool IsConvex() const { return mMesh->mIsConvex; }
+	virtual bool IsWatertight() const { return mMesh->mIsWatertight; }
+	virtual float IntersectionComplexity() {  return (float)mMesh->mFaces.size(); }
+
+	virtual int NumberOfFaces() const {  return (int)mMesh->mFaces.size(); }
+
+	virtual int Type() const { return MESH_INSTANCE; }
+
+	virtual int
+		CastRay(
+		Ray &ray,
+		const vector<int> &faces
+		);
 
 
@@ -286,12 +288,12 @@
 		return mMesh->Describe(s);
 	}
-	
+
 	/** Sets the material. this overrides the material from 
-		the mesh itself.
+	the mesh itself.
 	*/
 	void SetMaterial(Material *mat);
 
 	/** Returns the material of this mesh instance.
-		if not defined, returns the material of the mesh itself.
+	if not defined, returns the material of the mesh itself.
 	*/
 	Material *GetMaterial() const;
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.cpp	(revision 1760)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.cpp	(revision 1763)
@@ -505,4 +505,6 @@
 	Debug << "vsp mem const: " << mMemoryConst << endl;
 
+	cout << "use cost heuristics: " << mUseCostHeuristics << endl;
+
 	Debug << endl;
 }
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.h	(revision 1743)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Intersectable.h	(revision 1763)
@@ -113,4 +113,7 @@
   virtual int GetRandomSurfacePoint(Vector3 &point, Vector3 &normal) = 0;
 
+  virtual int GetRandomEdgePoint(Vector3 &point,
+								 Vector3 &normal) = 0;
+
   virtual int GetRandomVisibleSurfacePoint(Vector3 &point,
 										   Vector3 &normal,
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.cpp	(revision 1758)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.cpp	(revision 1763)
@@ -143,5 +143,5 @@
 	Intersectable::NewMail();
 	KdLeaf::NewMail();
-	BvhLeaf::NewMail();
+	BvhNode::NewMail();
 
 	ObjectPvsEntries::const_iterator it, it_end = mEntries.end();
Index: GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp	(revision 1760)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp	(revision 1763)
@@ -741,4 +741,5 @@
 	if (!success) // split was not taken
 	{
+		cout << "x";
 		return false;
 	}
@@ -1731,5 +1732,5 @@
 	int Type()  const { return BVH_NODE; }
 
-	float GetMergeCost() const { return (float)-mNode->mTimeStamp; };
+	float GetMergeCost() const { return (float)-mNode->GetTimeStamp(); };
 
 	bool IsLeaf() const { return mNode->IsLeaf(); }
@@ -1856,5 +1857,4 @@
 			++ pvsEntries;
 			rc += mBvHierarchy->EvalAbsCost(objects);
-			//cout << " pvs: " << mBvHierarchy->EvalAbsCost(leaf->mObjects);
 		}
 	}
@@ -1910,5 +1910,4 @@
 	// collect best set of view cells for this #splits
     CollectBestSet(maxSplits, maxMemoryCost, viewCells, bvhNodes);
-	//cout << "here5 " << bvhNodes.size() << endl;
 	vector<BvhNode *>::const_iterator bit, bit_end = bvhNodes.end();
 	
@@ -2111,5 +2110,5 @@
 
 	firstVsp->SetPriority((float)-oldVspRoot->mTimeStamp);
-	firstBvh->SetPriority((float)-oldBvhRoot->mTimeStamp);
+	firstBvh->SetPriority((float)-oldBvhRoot->GetTimeStamp());
 
 	tQueue.Push(firstVsp);
@@ -2214,4 +2213,16 @@
 	mOldViewCells.clear();
 
+	// reset active nodes
+	vector<BvhLeaf *> bvhLeaves;
+
+	mBvHierarchy->CollectLeaves(mBvHierarchy->GetRoot(), bvhLeaves);
+
+	vector<BvhLeaf *>::const_iterator bit, bit_end = bvhLeaves.end();
+
+	for (bit = bvhLeaves.begin(); bit != bit_end; ++ bit)
+	{
+		(*bit)->SetActiveNode(*bit);
+	}
+
 	cout << endl;
 }
Index: GTP/trunk/Lib/Vis/Preprocessing/src/IntersectableWrapper.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/IntersectableWrapper.h	(revision 1758)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/IntersectableWrapper.h	(revision 1763)
@@ -62,5 +62,5 @@
 	ostream &Describe(ostream &s);
 	
-
+	int GetRandomEdgePoint(Vector3 &point, Vector3 &normal);
 protected:
 	
@@ -111,4 +111,5 @@
 }
 
+
 template<typename T>
 float IntersectableWrapper<T>::IntersectionComplexity()
@@ -117,4 +118,5 @@
 }
 
+
 template<typename T>
 int IntersectableWrapper<T>::NumberOfFaces() const
@@ -122,4 +124,5 @@
 	return 0;
 }
+
 
 template<typename T>
@@ -129,4 +132,13 @@
 	return 0;
 }
+
+
+template<typename T>
+int IntersectableWrapper<T>::GetRandomEdgePoint(Vector3 &point,
+												Vector3 &normal)
+{
+	return 0;
+}
+
 
 template<typename T>
@@ -193,4 +205,7 @@
 									 const Vector3 &viewpoint,
 									 const int maxTries);
+
+	int GetRandomEdgePoint(Vector3 &point, Vector3 &normal);
+
 };
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.cpp	(revision 1587)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.cpp	(revision 1763)
@@ -795,4 +795,10 @@
 
 
+int MeshInstance::GetRandomEdgePoint(Vector3 &point, Vector3 &normal)
+{
+	// TODO
+	return mMesh->GetRandomSurfacePoint(point, normal);
+}
+
 
 /*************************************************************/
Index: GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.cpp	(revision 1695)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.cpp	(revision 1763)
@@ -183,4 +183,41 @@
 }
 
+
+bool ViewCellBorderBasedDistribution::GenerateSample(SimpleRay &ray) const
+{
+	Vector3 origin, direction; 
+
+	ViewCellContainer &viewCells = mPreprocessor.mViewCellsManager->GetViewCells();
+
+	Vector3 point;
+	Vector3 normal, normal2;
+	
+	//cout << "y";
+	const int vcIdx = (int)RandomValue(0, (float)viewCells.size() - 0.5f);
+	const int objIdx = (int)RandomValue(0, (float)mPreprocessor.mObjects.size() - 0.5f);
+
+	Intersectable *object = mPreprocessor.mObjects[objIdx];
+	ViewCell *viewCell = viewCells[vcIdx];
+
+	object->GetRandomSurfacePoint(point, normal);
+	viewCell->GetRandomEdgePoint(origin, normal2);
+
+	direction = point - origin;
+
+	// $$ jb the pdf is yet not correct for all sampling methods!
+	const float c = Magnitude(direction);
+
+	if (c <= Limits::Small) 
+		return false;
+
+	// $$ jb the pdf is yet not correct for all sampling methods!
+	const float pdf = 1.0f;
+	//cout << "p: " << point << " ";
+	direction *= 1.0f / c;
+	ray = SimpleRay(origin, direction, pdf);
+	
+	return true;
+}
+
 #if 0
 bool ObjectsInteriorDistribution::GenerateSample(SimpleRay &ray) const
