Index: GTP/trunk/Lib/Vis/Preprocessing/src/X3dParser.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/X3dParser.cpp	(revision 1627)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/X3dParser.cpp	(revision 1789)
@@ -243,5 +243,4 @@
 		for (fit = fit_begin; fit != fit_end; ++ fit)
 		{
-			//cout << "f";
 			// triangulate the faces
 			Face *face = *fit;
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 1773)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.cpp	(revision 1789)
@@ -1357,9 +1357,9 @@
 	// C = ct_div_ci  + (ql*rl + qr*rr)/queries
 
-	int pvsl = 0;
-	int pvsr = pvsSize;
-
-	int pvsBack = pvsl;
-	int pvsFront = pvsr;
+	float pvsl = 0;
+	float pvsr = (float)pvsSize;
+
+	float pvsBack = pvsl;
+	float pvsFront = pvsr;
 
 	float sum = (float)pvsSize * sizeBox;
@@ -1504,5 +1504,5 @@
 	const float pFront = maxBox - position;
 	
-	const float penaltyOld = EvalPvsPenalty(pvsSize, lowerPvsLimit, upperPvsLimit);
+	const float penaltyOld = EvalPvsPenalty((float)pvsSize, lowerPvsLimit, upperPvsLimit);
     const float penaltyFront = EvalPvsPenalty(pvsFront, lowerPvsLimit, upperPvsLimit);
 	const float penaltyBack = EvalPvsPenalty(pvsBack, lowerPvsLimit, upperPvsLimit);
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h	(revision 1787)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.h	(revision 1789)
@@ -131,5 +131,5 @@
 	/** Add sample contributions to the viewcells they intersect 
 	*/
-	void AddSampleContributions(const VssRayContainer &rays);
+	//void AddSampleContributions(const VssRayContainer &rays);
   
 
@@ -144,5 +144,5 @@
 											const bool storeViewCells);
 
-	virtual void AddSampleContributions(VssRay &ray);
+	//virtual void AddSampleContributions(VssRay &ray);
 
 	/** Prints out statistics of the view cells.
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.cpp	(revision 1715)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.cpp	(revision 1789)
@@ -2699,11 +2699,11 @@
 		if (!ray->intersections.empty())
 		  contribution += vc->GetPvs().AddSample(ray->intersections[0].mObject,
-												 1.0f,
-												 relContribution);
+												 1.0f);
+												 //relContribution);
 		
 		if (ray->sourceObject.mObject)
 			contribution += vc->GetPvs().AddSample(ray->sourceObject.mObject,
-												   1.0f,
-												   relContribution);
+												   1.0f);
+												   //relContribution);
 		
 		if (contribution)
Index: GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp	(revision 1787)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.cpp	(revision 1789)
@@ -304,5 +304,5 @@
 	Environment::GetSingleton()->GetIntValue("BvHierarchy.minRaysForVisibility", mMinRaysForVisibility);
 	Environment::GetSingleton()->GetIntValue("BvHierarchy.maxTests", mMaxTests);
-	//	Environment::GetSingleton()->GetBoolValue("BvHierarchy.Construction.useInitialSubdivision", mApplyInitialPartition);
+	Environment::GetSingleton()->GetBoolValue("BvHierarchy.Construction.useInitialSubdivision", mApplyInitialPartition);
 	Environment::GetSingleton()->GetIntValue("BvHierarchy.Construction.Initial.minObjects", mInitialMinObjects);
 	Environment::GetSingleton()->GetFloatValue("BvHierarchy.Construction.Initial.maxAreaRatio", mInitialMaxAreaRatio);
@@ -957,5 +957,5 @@
 
 		const bool noValidSplit = ((objectsLeft <= Limits::Small) || (objectsRight <= Limits::Small));
-		const float sum =  noValidSplit ? 1e25 : objectsLeft * al + objectsRight * ar;
+		const float sum = noValidSplit ? 1e25 : objectsLeft * al + objectsRight * ar;
       
 		/*cout << "pos=" << (*cit).mPos << "\t q=(" << objectsLeft << "," << objectsRight <<")\t r=(" 
@@ -1553,4 +1553,8 @@
 			}
 
+			// no good results for degenerate axis split
+			if (0 && tData.mNode->GetBoundingBox().Size(axis) < Limits::Small)
+					nCostRatio[axis] += 9999;
+
 			if ((bestAxis == -1) || (nCostRatio[axis] < nCostRatio[bestAxis]))
 			{
@@ -2149,6 +2153,4 @@
 		new BvhSubdivisionCandidate(oData);
 
-	// evaluate priority
-	EvalSubdivisionCandidate(*oSubdivisionCandidate);
 	bvhLeaf->SetSubdivisionCandidate(oSubdivisionCandidate);
 
@@ -2156,14 +2158,36 @@
 	mPvsEntries = CountViewCells(objects);
 
-	PrintSubdivisionStats(*oSubdivisionCandidate);
-	
 	if (mApplyInitialPartition)
 	{
-		ApplyInitialSubdivision(oSubdivisionCandidate, tQueue);		
+		vector<SubdivisionCandidate *> candidateContainer;
+
+		mIsInitialSubdivision = true;
+		
+		// evaluate priority
+		EvalSubdivisionCandidate(*oSubdivisionCandidate);
+		PrintSubdivisionStats(*oSubdivisionCandidate);
+
+		ApplyInitialSubdivision(oSubdivisionCandidate, candidateContainer);		
+
+		mIsInitialSubdivision = false;
+
+		vector<SubdivisionCandidate *>::const_iterator cit, cit_end = candidateContainer.end();
+
+		for (cit = candidateContainer.begin(); cit != cit_end; ++ cit)
+		{
+			// reevaluate priority
+			EvalSubdivisionCandidate(*oSubdivisionCandidate);
+			tQueue.Push(*cit);
+		}
 	}
 	else
 	{
+		// evaluate priority
+		EvalSubdivisionCandidate(*oSubdivisionCandidate);
+		PrintSubdivisionStats(*oSubdivisionCandidate);
+
 		tQueue.Push(oSubdivisionCandidate);
 	}
+		
 	cout << "!!size: " << GetStatistics().Leaves() << endl;
 }
@@ -2510,8 +2534,6 @@
 
 void BvHierarchy::ApplyInitialSubdivision(SubdivisionCandidate *firstCandidate,
-										  SplitQueue &tQueue)
-{
-	mIsInitialSubdivision = true;
-
+										  vector<SubdivisionCandidate *> &candidateContainer)
+{
 	SplitQueue tempQueue;
 	tempQueue.Push(firstCandidate);
@@ -2523,11 +2545,9 @@
 		BvhSubdivisionCandidate *bsc = 
 			dynamic_cast<BvhSubdivisionCandidate *>(candidate);
-		cout << "§§§§§§§§here49 "<< bsc->mParentData.mSortedObjects[3]->size() << " " << mInitialMinObjects << endl;
 
 		const bool globalCriteriaMet = GlobalTerminationCriteriaMet(bsc->mParentData);
 
 		if (!InitialTerminationCriteriaMet(bsc->mParentData))
-		{
-			cout << "here9"<<bsc->mParentData.mNode->mObjects.size()<<endl;
+		{cout << "here9"<<endl;
 			BvhNode *node = Subdivide(tempQueue, bsc, globalCriteriaMet);
 
@@ -2536,11 +2556,9 @@
 		}
 		else // initial preprocessing  finished for this candidate
-		{cout << "here14"<<endl;
+		{cout << "here19"<<endl;
 			// add to "real" traversal queue
-			tQueue.Push(bsc);
-		}
-	}
-
-	mIsInitialSubdivision = false;
+			candidateContainer.push_back(bsc);
+		}
+	}
 }
 
@@ -2550,5 +2568,4 @@
 									ObjectContainer &backObjects)
 {
-	cout << "*******here54 "<<tData.mSortedObjects[3]->size()<<endl;
 	ObjectContainer *objects = tData.mSortedObjects[3];
 
@@ -2563,6 +2580,6 @@
 
 	ObjectContainer::const_iterator backObjectsStart = objects->begin();
-
-    for (oit = objects->begin(); oit != (objects->end() - 1); ++ oit)
+int dummy = 0;
+    for (oit = objects->begin(); oit != (objects->end() - 1); ++ oit, ++ dummy)
 	{
 		Intersectable *objS = *oit;
@@ -2574,6 +2591,6 @@
 		if (areaDiff > maxAreaDiff)
 		{
-			//cout << "here5 " << areaDiff << " " << maxAreaDiff << endl;
 			maxAreaDiff = areaDiff;
+			//cout << "maxAreaDiff : " << maxAreaDiff << " " << dummy << " " << objects->size() - dummy <<  endl;
 			backObjectsStart = oit + 1;
 		}
@@ -2583,5 +2600,5 @@
 	for (oit = objects->begin(); oit != backObjectsStart; ++ oit)
 	{
-		backObjects.push_back(*oit);
+		frontObjects.push_back(*oit);
 	}
 
@@ -2589,6 +2606,16 @@
 	for (oit = backObjectsStart; oit != oit_end; ++ oit)
 	{
-		frontObjects.push_back(*oit);
-	}
+		backObjects.push_back(*oit);
+	}
+	TriangleIntersectable *tObj1 = (TriangleIntersectable *)frontObjects.back();
+	TriangleIntersectable *tObj2 = (TriangleIntersectable *)backObjects.front();
+
+	cout << "here4 " << tObj1->GetItem().GetArea() << " " << tObj2->GetItem().GetArea() << endl;
+
+
+if (maxAreaDiff < 0.0001)
+cout << "big error!!!! " << maxAreaDiff << endl;
+
+	cout << "front: " << (int)frontObjects.size() << " back " << (int)backObjects.size() << " " << backObjects.front()->GetBox().SurfaceArea() - frontObjects.back()->GetBox().SurfaceArea() << endl;
 }
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1787)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1789)
@@ -1956,5 +1956,5 @@
 }
 
-
+/*
 void
 ViewCellsManager::AddSampleContributions(const VssRayContainer &rays)
@@ -1964,10 +1964,10 @@
 
   VssRayContainer::const_iterator it, it_end = rays.end();
-
+cout <<"here60"<<endl;
   for (it = rays.begin(); it != it_end; ++ it) {
 	AddSampleContributions(*(*it));
   }
 }
-
+*/
 
 int ViewCellsManager::GetMinPvsSize() const
@@ -1983,8 +1983,8 @@
 }
 
-
+/*
 void
 ViewCellsManager::AddSampleContributions(VssRay &ray)
-{
+{cout << "here12" << endl;
 	// assumes viewcells have been stored...
 	ViewCellContainer *viewcells = &ray.mViewCells;
@@ -2008,10 +2008,10 @@
 	}
 }
-
+*/
 
 float ViewCellsManager::ComputeSampleContribution(VssRay &ray,
 												  const bool addRays,
 												  const bool storeViewCells)
-{
+{cout << "$$$$$$$$$$$$$4here10" << endl;
 	ViewCellContainer viewcells;
 
@@ -3470,5 +3470,5 @@
 	if (sortViewCells)
 	{	// sort view cells to visualize the largest view cells
-		stable_sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
+		sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
 	}
 
@@ -4824,5 +4824,5 @@
 	{
 		// sort view cells to visualize the largest view cells
-		stable_sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
+		sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
 	}
 
@@ -5278,5 +5278,6 @@
 
 
-VspOspViewCellsManager::VspOspViewCellsManager(ViewCellsTree *vcTree, const string &hierarchyType)
+VspOspViewCellsManager::VspOspViewCellsManager(ViewCellsTree *vcTree, 
+											   const string &hierarchyType)
 : ViewCellsManager(vcTree)
 {
@@ -5297,4 +5298,5 @@
 	mHierarchyManager->SetViewCellsTree(mViewCellsTree);
 }
+
 
 Intersectable *
@@ -5307,4 +5309,5 @@
 #endif
 }
+
 
 HierarchyManager *VspOspViewCellsManager::CreateHierarchyManager(const string &hierarchyType)
@@ -5675,5 +5678,7 @@
 	Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
 
-	Vector3 scale(0.9f, 0.9f, 0.9f);
+	//Vector3 scale(0.9f, 0.9f, 0.9f);
+	Vector3 scale(1.0f, 1.0f, 1.0f);
+
 	if (exporter)
 	{
@@ -5773,5 +5778,5 @@
 	{
 		// sort view cells to visualize the view cells with highest render cost
-		stable_sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
+		sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
 	}
 
@@ -6055,5 +6060,4 @@
 	float tmin = 0, tmax = 1.0;
 
-	
 	if (!GetViewSpaceBox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax))
 		return 0;
@@ -6069,7 +6073,7 @@
 	if (storeViewCells)
 	{	
-	  // copy viewcells memory efficiently
-	  ray.mViewCells.reserve(viewcells.size());
-	  ray.mViewCells = viewcells;
+		// copy viewcells memory efficiently
+		ray.mViewCells.reserve(viewcells.size());
+		ray.mViewCells = viewcells;
 	}
 
@@ -6078,43 +6082,43 @@
 	Intersectable *terminationObj = GetIntersectable(ray, true);
 	Intersectable *originObj = GetIntersectable(ray, false);
-	  
-	for (; it != viewcells.end(); ++ it) {
-	  ViewCell *viewcell = *it;
-	  
-	  if (viewcell->GetValid())
+
+	for (; it != viewcells.end(); ++ it) 
+	{
+		ViewCell *viewcell = *it;
+
+		if (viewcell->GetValid())
 		{	// if ray not outside of view space
-		  float contribution;
-		  
-		  if (terminationObj) 
+			float contribution;
+
+			if (terminationObj) 
 			{
-			  // todo: maybe not correct for kd node pvs
-			  if (viewcell->GetPvs().GetSampleContribution(
-														   terminationObj, ray.mPdf, contribution))
+				// todo: maybe not correct for kd node pvs
+			/*	if (viewcell->GetPvs().GetSampleContribution(
+					terminationObj, ray.mPdf, contribution))
 				{
-				  ++ ray.mPvsContribution;
+					++ ray.mPvsContribution;
 				}
-			  
-			  ray.mRelativePvsContribution += contribution;
+				ray.mRelativePvsContribution += contribution;*/
 			}
-			
-		  ////////////////
-		  //-- for directional sampling it is important to count 
-		  //-- only contributions made in one direction!
-		  //-- the other contributions of this sample will be counted for the opposite ray!
-		  
+
+			////////////////
+			//-- for directional sampling it is important to count 
+			//-- only contributions made in one direction!
+			//-- the other contributions of this sample will be counted for the opposite ray!
+
 #if SAMPLE_ORIGIN_OBJECTS
-		  
-		  if (originObj && 
-			  viewcell->GetPvs().GetSampleContribution(originObj,
-													   ray.mPdf,
-													   contribution))
+
+		/*	if (originObj && 
+				viewcell->GetPvs().GetSampleContribution(originObj,
+														 ray.mPdf,
+														 contribution))
 			{
-			  ++ ray.mPvsContribution;
-			  ray.mRelativePvsContribution += contribution;
-			}
+				++ ray.mPvsContribution;
+				ray.mRelativePvsContribution += contribution;
+			}*/
 #endif
 		}
 	}
-	
+
 	if (!addRays)
 	{
@@ -6131,13 +6135,48 @@
 
 		//$$JB hack
-		viewCell->GetPvs().AddSample(terminationObj, ray.mPdf);
-		
+		float contrib;
+		//viewCell->GetPvs().AddSampleDirtyCheck(terminationObj, ray.mPdf, contrib);
+		viewCell->GetPvs().AddSample(terminationObj, ray.mPdf);//, contrib);
+
+		if (viewCell->GetPvs().GetSize() == 50)
+		//if (viewCell->GetPvs().RequiresResort())
+		{Intersectable::NewMail();
+		cout << "\nbefore sort: " << viewCell->GetPvs().GetLastSorted() << " \n";
+			ObjectPvsIterator pit = viewCell->GetPvs().GetIterator(); int i = 0;
+			while (pit.HasMoreEntries())
+			{		
+				ObjectPvsEntry entry = pit.Next();
+                Intersectable *object = entry.mObject;
+
+				if ((i ++) == viewCell->GetPvs().GetLastSorted())
+					cout << "| ";
+				
+				//if (object->Mailed())	cout << "error!!"<<endl;
+				object->Mail();
+				cout << (int)object << " ";
+			}
+
+			//viewCell->GetPvs().Sort();
+			
+			/*cout << "\nafter sort\n";
+			pit = viewCell->GetPvs().GetIterator(); i = 0;
+			while (pit.HasMoreEntries())
+			{		
+				ObjectPvsEntry entry = pit.Next();
+                Intersectable *object = entry.mObject;
+
+				if ((i ++) == viewCell->GetPvs().GetLastSorted())
+					cout << "| ";	
+				cout << (int)object << " ";
+			}*/
+		}
+		//else cout << "b";
 #if SAMPLE_ORIGIN_OBJECTS
-		viewCell->GetPvs().AddSample(originObj, ray.mPdf);
-#endif			
-	}
-	
+		//viewCell->GetPvs().AddSample(originObj, ray.mPdf);
+#endif
+	}
+
 	return ABS_CONTRIBUTION_WEIGHT*ray.mPvsContribution +
-	  (1.0f - ABS_CONTRIBUTION_WEIGHT)*ray.mRelativePvsContribution;
+		(1.0f - ABS_CONTRIBUTION_WEIGHT)*ray.mRelativePvsContribution;
 }
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp	(revision 1786)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp	(revision 1789)
@@ -263,5 +263,5 @@
 							float &contribution)
 { 
-	const bool result = mPvs.AddSample(sample, pdf, contribution);
+	const bool result = mPvs.AddSample(sample, pdf);//, contribution);
 	// have to recompute pvs size
 	mPvsSizeValid = false;
Index: GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 1786)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 1789)
@@ -887,5 +887,5 @@
 	*/
 	void ApplyInitialSubdivision(SubdivisionCandidate *firstCandidate,
-								 SplitQueue &tQueue);
+								 vector<SubdivisionCandidate *> &candidateContainer);
 
 	void ApplyInitialSplit(const BvhTraversalData &tData,
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h	(revision 1786)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h	(revision 1789)
@@ -32,4 +32,6 @@
 	template<typename T, typename S>
 	friend int operator< (const PvsEntry<T, S> &a, const PvsEntry<T, S> &b);
+	template<typename T, typename S>
+	friend int operator== (const PvsEntry<T, S> &a, const PvsEntry<T, S> &b);
 };
 
@@ -39,4 +41,10 @@
 {
 	return a.mObject < b.mObject;
+} 
+
+template<typename T, typename S>
+int operator== (const PvsEntry<T, S> &a, const PvsEntry<T, S> &b)
+{
+	return a.mObject == b.mObject;
 } 
 
@@ -51,4 +59,9 @@
 };
 
+template<typename T, typename S>
+int equalSample (const PvsEntry<T, S> &a, const PvsEntry<T, S> &b)
+{
+	return a.mObject == b.mObject;
+} 
 
 /** Information stored with a PVS entry. Consists of the number
@@ -189,7 +202,9 @@
 
 	/** Finds sample in PVS.
+		@param checkDirty if dirty part of the pvs should be checked for entry 
+			(warning: linear runtime in dirty part)
 		@returns iterator on the sample.
 	*/
-	typename vector<PvsEntry<T, S> >::iterator Find(T sample);
+	typename vector<PvsEntry<T, S> >::iterator Find(T sample, const bool checkDirty = true);
 
 	bool GetSampleContribution(T sample, const float pdf, float &contribution);
@@ -199,5 +214,5 @@
 		@returns true if sample was not already in PVS.
 	*/
-	bool AddSample(T sample, const float pdf, float &contribution);
+	//bool AddSample(T sample, const float pdf, float &contribution);
 
 	/** Adds sample to PVS.
@@ -206,13 +221,19 @@
 	float AddSample(T sample, const float pdf);
 
-  /** Adds sample to PVS without checking for presence of the sample
-	  pvs remians unsorted!
-  */
-  void AddSampleDirty(T sample, const float pdf);
-
-  /** Sort pvs entries - this should always be called after a
-	  sequence of AddSampleDirty calls */
-  void Sort();
-  
+	/** Adds sample to PVS without checking for presence of the sample
+		pvs remains unsorted!
+	*/
+	void AddSampleDirty(T sample, const float pdf);
+
+	/** Adds sample dirty (on the end of the vector) but
+		first checks if sample is already in clean part of the pvs.
+	*/
+	bool AddSampleDirtyCheck(T sample, const float pdf);//, float &contribution);
+
+	/** Sort pvs entries - this should always be called after a
+		sequence of AddSampleDirty calls 
+	*/
+	void Sort();
+
 	/** Adds sample to PVS. Assumes that the pvs is sorted
 		@returns contribution of sample (0 or 1)
@@ -266,7 +287,35 @@
 	static void Merge(Pvs<T, S> &mergedPvs, const Pvs<T, S> &a, const Pvs<T, S> &b);
 
+	static void Merge(Pvs<T, S> &mergedPvs, 
+					  const typename std::vector<PvsEntry<T, S> >::const_iterator &aBegin,
+					  const typename std::vector<PvsEntry<T, S> >::const_iterator &aEnd,
+					  const typename std::vector<PvsEntry<T, S> >::const_iterator &bBegin,
+					  const typename std::vector<PvsEntry<T, S> >::const_iterator &bEnd,
+					  const int aSamples, 
+					  const int bSamples);
+
 	int GetSamples() const
 	{
 		return mSamples;
+	}
+
+
+	bool IsDirty() const
+	{
+		return mLastSorted < mEntries.size();
+	}
+
+	bool RequiresResort() const
+	{
+		// the last part should not be more than log of the sorted part. this
+		// way we can achieve logarithmic behaviour for insertion and find
+		const int dirtySize = (int)mEntries.size() - mLastSorted;
+		return dirtySize > (int)(log((double)mEntries.size()) / log(2.0));
+	}
+
+
+	int GetLastSorted() const
+	{
+		return mLastSorted;
 	}
 
@@ -281,7 +330,6 @@
 	int mSamples;
   
-  /// Last sorted entry in the pvs (important for find and merge
-  int mLastSorted;
-  
+	/// Last sorted entry in the pvs (important for find and merge)
+	int mLastSorted;  
 };
 
@@ -293,14 +341,31 @@
 	mEntries = samples;
 	mLastSorted = 0;
-}
+	mSamples = samples.size();
+}
+
 
 template <typename T, typename S>
 void Pvs<T, S>::Sort()
 {
-  std::vector<PvsEntry<T, S> >::iterator it = mEntries.begin();
-  it.inc(mLastSorted);
-  sort(it, mEntries.end());
-  mLastSorted = mEntries.size() - 1;
-}
+	std::vector<PvsEntry<T, S> >::iterator it = mEntries.begin() + mLastSorted;
+	//std::vector<PvsEntry<T, S> >::const_iterator it = mEntries.begin() + mLastSorted;
+	std::vector<PvsEntry<T, S> >::iterator it_end = mEntries.end();
+
+	// throw out double entries
+	std::vector<PvsEntry<T, S> >::iterator newEnd = unique(it, it_end);
+	sort(it, newEnd);
+	//sort(mEntries.begin(), mEntries.end());
+
+	// now merge sorted ranges
+	ObjectPvs newPvs;
+	Merge(newPvs, 
+		  mEntries.begin(), it, 
+		  it, newEnd, 
+		  mSamples, 0);
+	
+	mEntries = newPvs.mEntries;
+	mLastSorted = (int)mEntries.size();
+}
+
 
 /**
@@ -436,11 +501,33 @@
 	std::vector<PvsEntry<T, S> >::const_iterator bit = b.mEntries.begin(), bit_end = b.mEntries.end();
 	
-	for (; (ait != ait_end); ++ ait)
+	Merge(mergedPvs, 
+		  ait, ait_end,
+		  bit, bit_end,
+		  a.mSamples,
+		  b.mSamples);
+}
+
+
+template <typename T, typename S>
+void Pvs<T, S>::Merge(Pvs<T, S> &mergedPvs, 
+					  const typename std::vector<PvsEntry<T, S> >::const_iterator &aBegin,
+					  const typename std::vector<PvsEntry<T, S> >::const_iterator &aEnd,
+					  const typename std::vector<PvsEntry<T, S> >::const_iterator &bBegin,
+					  const typename std::vector<PvsEntry<T, S> >::const_iterator &bEnd,
+					  const int aSamples, 
+					  const int bSamples)
+{
+	std::vector<PvsEntry<T, S> >::const_iterator ait = aBegin;
+	std::vector<PvsEntry<T, S> >::const_iterator bit = bBegin;
+	
+	for (; (ait != aEnd); ++ ait)
 	{
 		Intersectable *aObj = (*ait).mObject;
 		Intersectable *bObj = NULL;
-		PvsEntry<T, S> aEntry = (*ait);
-
-		for (; (bit != bit_end) && ((*bit).mObject <= (*ait).mObject); ++ bit)
+		//Intersectable *bObjOld = NULL;
+	
+		const PvsEntry<T, S> &aEntry = (*ait);
+
+		for (; (bit != bEnd) && ((*bit).mObject <= (*ait).mObject); ++ bit)
 		{
 			bObj = (*bit).mObject;
@@ -457,4 +544,6 @@
 				mergedPvs.mEntries.push_back(*bit);
 			}
+			
+			//bObjOld = bObj;
 		}
 
@@ -468,9 +557,10 @@
 
 	// add the rest
-	for (; (bit != bit_end); ++ bit)
+	for (; (bit != bEnd); ++ bit)
 	{
 		mergedPvs.mEntries.push_back(*bit);
 	}
-	mergedPvs.mSamples = a.mSamples + b.mSamples;
+
+	mergedPvs.mSamples = aSamples + bSamples;
 }
 
@@ -480,4 +570,5 @@
 	mEntries.clear();
 	mSamples = 0;
+	mLastSorted = 0;
 
 	if (trim)
@@ -495,9 +586,24 @@
 
 template <typename T, typename S> 
-typename std::vector<PvsEntry<T, S> >::iterator Pvs<T, S>::Find(T sample)
+typename std::vector<PvsEntry<T, S> >::iterator Pvs<T, S>::Find(T sample, const bool checkDirty)
 {
 	PvsEntry<T, S> dummy(sample, PvsData());
-	vector<PvsEntry<T, S> >::iterator it = lower_bound(mEntries.begin(), mEntries.end(), dummy);
-				
+
+	// only check clean part
+	//mLastSorted = 0;
+	vector<PvsEntry<T, S> >::iterator sorted_end = mEntries.begin() + mLastSorted;
+if (sorted_end != mEntries.end())
+cout << "not entries end!! " << endl;
+	// binary search
+	vector<PvsEntry<T, S> >::iterator it = lower_bound(mEntries.begin(), sorted_end, dummy);
+
+	// sample not found yet => search further in the unsorted part
+	if (checkDirty &&
+		((it == mEntries.end()) || ((*it).mObject != sample)))
+	{
+		vector<PvsEntry<T, S> >::const_iterator it_end = mEntries.end();
+		for (it = sorted_end; (it != it_end) && ((*it).mObject != sample); ++ it);
+	}
+	else cout << "f ";
 	return it;
 }
@@ -519,8 +625,9 @@
 {
 	++ mSamples;
+	cout << "! ";
 	std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
 
 	if ((it != mEntries.end()) && ((*it).mObject == sample))
-	{
+	{	cout << "g";
 		S &data = (*it).mData;
 		data.mSumPdf += pdf;
@@ -528,9 +635,11 @@
 	}
 	else 
-	{
+	{cout << "t";
 		PvsEntry<T, S> entry(sample, pdf);
 		mEntries.insert(it, entry);
+		++ mLastSorted;
 		return pdf;
 	}
+	cout << " $";
 }
 
@@ -539,6 +648,6 @@
 void Pvs<T, S>::AddSampleDirty(T sample, const float pdf)
 {
-  ++ mSamples;
-  mEntries.push_back(PvsEntry<T, S>(sample, pdf));
+	++ mSamples;
+	mEntries.push_back(PvsEntry<T, S>(sample, pdf));
 }
 					 
@@ -548,4 +657,5 @@
 {
 	++ mSamples;
+	
 	std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
 
@@ -559,4 +669,5 @@
 		PvsEntry<T, S> entry(sample, pdf);
 		mEntries.insert(it, entry);
+		++ mLastSorted;
 	}
 
@@ -565,5 +676,5 @@
 
 
-template <typename T, typename S> 
+/*template <typename T, typename S> 
 bool Pvs<T, S>::AddSample(T sample,
 						  const float pdf,
@@ -589,4 +700,36 @@
 		mEntries.insert(it, entry);
 		contribution = 1.0f;
+		++ mLastSorted;
+
+		return true;
+	}
+}*/
+
+
+/** Adds sample dirty (on the end of the vector) but
+	first checks if sample is already in clean part of the pvs.
+*/
+template <typename T, typename S> 
+bool Pvs<T, S>::AddSampleDirtyCheck(T sample,
+									const float pdf)
+									//,float &contribution)
+{
+	++ mSamples;
+
+	std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
+
+	if ((it != mEntries.end()) && ((*it).mObject == sample))
+	{
+		S &data = (*it).mData;
+
+		data.mSumPdf += pdf;
+		//contribution = pdf / data.mSumPdf;
+
+		return false;
+	}
+	else 
+	{
+		AddSampleDirty(sample, pdf);
+		//contribution = 1.0f;
 
 		return true;
@@ -620,5 +763,5 @@
 {
 	-- mSamples;
-
+	
 	std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
 
@@ -633,4 +776,5 @@
 	{
 		mEntries.erase(it);
+		-- mLastSorted; // wrong if sample was in tail!!
 	}
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp	(revision 1787)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp	(revision 1789)
@@ -2020,11 +2020,10 @@
 	
 		ObjectPvs pvs;
-		//GetPvsRecursive(vc, pvs);
-		
-		// uses mailing
-		// warning: pvs not sorted!!
+				
 		if (vc->GetPvs().Empty())
 		{
+			// warning: uses mailing, pvs not sorted!!
 			GetPvsEfficiently(vc, pvs);
+			//GetPvsRecursive(vc, pvs);
 			vc->SetPvs(pvs);
 			//cout << "q";
@@ -2105,5 +2104,5 @@
 	//-- or the reverse order of subdivision for subdivision-only 
 	//-- view cell hierarchies.
-	
+
 	while (!tQueue.Empty())
 	{
@@ -2114,5 +2113,5 @@
 		int entriesIncr; 
 
-        if (nextCandidate->Type() == SubdivisionCandidate::VIEW_SPACE)
+		if (nextCandidate->Type() == SubdivisionCandidate::VIEW_SPACE)
 		{
 			timeStamp = (int)-nextCandidate->GetPriority();
@@ -2120,5 +2119,5 @@
 			VspNode *newNode = mVspTree->SubdivideAndCopy(tQueue, nextCandidate);
 			VspNode *oldNode = (VspNode *)nextCandidate->mEvaluationHack;
-			
+
 			isLeaf = newNode->IsLeaf();
 			//subStats.mRenderCostDecrease = oldNode->mRenderCostDecr;
@@ -2128,13 +2127,13 @@
 		{
 			timeStamp = (int)-nextCandidate->GetPriority();
-			
+
 			BvhNode *newNode = mBvHierarchy->SubdivideAndCopy(tQueue, nextCandidate);
 			BvhNode *oldNode = (BvhNode *)nextCandidate->mEvaluationHack;
-			
+
 			isLeaf = newNode->IsLeaf();
 			//subStats.mRenderCostDecrease = oldNode->mRenderCostDecr;
 			//entriesIncr = oldNode->mPvsEntriesIncr;
 		}		
-				
+
 		if (!isLeaf)
 		{
@@ -2164,5 +2163,5 @@
 
 			subStats.Print(stats);
-			
+
 		}
 
