Index: GTP/trunk/Lib/Vis/Preprocessing/src/SubdivisionCandidate.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/SubdivisionCandidate.h	(revision 1684)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/SubdivisionCandidate.h	(revision 1695)
@@ -22,5 +22,5 @@
 	enum {OBJECT_SPACE, VIEW_SPACE};
 
-	SubdivisionCandidate(): mRenderCostDecrease(0) {};
+	SubdivisionCandidate(): mRenderCostDecrease(0), mDirty(true) {};
 
 	virtual ~SubdivisionCandidate() {};
@@ -130,4 +130,6 @@
 
 	int mMailbox;
+
+	bool mDirty;
 };
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 1684)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Environment.cpp	(revision 1695)
@@ -1392,4 +1392,9 @@
 					"300000");
 
+	RegisterOption("ViewCells.Evaluation.samplesForStats",
+					optInt,
+					"view_cells_evaluation_samples_for_stats=",
+					"300000");
+
 	RegisterOption("ViewCells.exportToFile",
 					optBool,
@@ -1804,5 +1809,10 @@
 					"preprocessor_kd_tree_filename=",
 					"vienna_kdtree.bin.gz");
-	
+
+	RegisterOption("Preprocessor.exportObj", 
+					optBool,
+					"preprocessor_export_obj=",
+					"false");
+
 
 	/*************************************************************************/
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 1664)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp	(revision 1695)
@@ -158,9 +158,14 @@
 	Environment::GetSingleton()->GetBoolValue("Preprocessor.applyVisibilityFilter", mApplyVisibilityFilter );
 	Environment::GetSingleton()->GetBoolValue("Preprocessor.applyVisibilitySpatialFilter",
-							  mApplyVisibilitySpatialFilter );
+											  mApplyVisibilitySpatialFilter );
 	Environment::GetSingleton()->GetFloatValue("Preprocessor.visibilityFilterWidth", mVisibilityFilterWidth);
 
+	Environment::GetSingleton()->GetBoolValue("Preprocessor.exportObj", mExportObj);
+	
+	Debug << "******* Preprocessor Options **********" << endl;
 	Debug << "detect empty view space=" << mDetectEmptyViewSpace << endl;
 	Debug << "load meshes: " << mLoadMeshes << endl;
+	Debug << "load meshes: " << mLoadMeshes << endl;
+	Debug << "export obj: " << mExportObj << endl;
 }
 
@@ -298,4 +303,52 @@
 
 	return true;
+}
+
+
+bool Preprocessor::ExportObj(const string filename, const ObjectContainer &objects)
+{
+	ofstream samplesOut(filename.c_str());
+
+	if (!samplesOut.is_open())
+		return false;
+
+	ObjectContainer::const_iterator oit, oit_end = objects.end();
+
+	for (oit = objects.begin(); oit != oit_end; ++ oit)
+	{
+		Intersectable *obj = *oit;
+
+		if (obj->Type() == Intersectable::TRIANGLE_INTERSECTABLE)
+		{
+			Triangle3 tri = dynamic_cast<TriangleIntersectable *>(obj)->GetItem();
+
+			samplesOut << "v " << tri.mVertices[0].x << " " << tri.mVertices[0].y << " " << tri.mVertices[0].z << endl;
+			samplesOut << "v " << tri.mVertices[1].x << " " << tri.mVertices[1].y << " " << tri.mVertices[1].z << endl;
+			samplesOut << "v " << tri.mVertices[2].x << " " << tri.mVertices[2].y << " " << tri.mVertices[2].z << endl;
+		}
+		else
+		{
+			cout << "not implemented intersectable type " << obj->Type() << endl;
+		}
+	}
+
+	// write faces
+	int i = 1;
+	for (oit = objects.begin(); oit != oit_end; ++ oit, i += 3)
+	{
+		Intersectable *obj = *oit;
+		if (obj->Type() == Intersectable::TRIANGLE_INTERSECTABLE)
+		{
+			Triangle3 tri = dynamic_cast<TriangleIntersectable *>(obj)->GetItem();
+			samplesOut << "f " << i << " " << i + 1 << " " << i + 2 << endl;
+		}
+		else
+		{
+			cout << "not implemented intersectable type " << obj->Type() << endl;
+		}
+	}
+
+	return true;
+
 }
 
@@ -323,4 +376,5 @@
 	cout << "number of input files: " << files << endl;
 	bool result = false;
+	bool isObj = false;
 
 	// root for different files
@@ -357,4 +411,6 @@
 		else if (strstr(filename.c_str(), ".obj"))
 		{
+			isObj = true;
+
 			// hack: load binary dump
 			string binFile = ReplaceSuffix(filename, ".obj", ".bin");
@@ -417,9 +473,6 @@
 
 			SceneGraphNode *node = new SceneGraphNode();
-			const bool success = parser->ParseFile(
-				filename, 
-				node,
-				mLoadMeshes,
-				fi);
+			const bool success = 
+				parser->ParseFile(filename, node, mLoadMeshes, fi);
 
 			if (success) 
@@ -943,4 +996,6 @@
 	case SamplingStrategy::SPATIAL_BOX_BASED_DISTRIBUTION:
 		return new SpatialBoxBasedDistribution(*this);
+	case SamplingStrategy::REVERSE_OBJECT_BASED_DISTRIBUTION:
+		return new ReverseObjectBasedDistribution(*this);
 	//case OBJECTS_INTERIOR_DISTRIBUTION:
 	//	return new ObjectsInteriorDistribution(*this);
Index: GTP/trunk/Lib/Vis/Preprocessing/src/OspTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/OspTree.h	(revision 1667)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/OspTree.h	(revision 1695)
@@ -254,5 +254,6 @@
 		void EvalCandidate(bool computeSplitplane = true)
 		{
-			//if (computeSplitplane) TODO
+			mDirty = false;
+			// todo: avoid computing split plane
 			sOspTree->EvalSubdivisionCandidate(*this);	
 		}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h	(revision 1658)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.h	(revision 1695)
@@ -100,8 +100,5 @@
 	/** Export preprocessor data.
 	*/
-	bool Export(
-		const string filename, 
-		const bool scene, 
-		const bool kdtree);  
+	bool Export(const string filename, const bool scene, const bool kdtree);  
 
 	virtual void KdTreeStatistics(ostream &s);
@@ -114,5 +111,5 @@
 	*/
 	bool LoadSamples(VssRayContainer &samples,
-		ObjectContainer &objects) const;
+					 ObjectContainer &objects) const;
 
 	/** Exports samples to file.
@@ -124,21 +121,17 @@
 	bool ExportKdTree(const string filename);
 
-	virtual bool
-		GenerateRays(
-		const int number,
-		const int raysType,
-		SimpleRayContainer &rays
-		);
-
-	bool GenerateRayBundle(
-		SimpleRayContainer &rayBundle,
-		const SimpleRay &mainRay,
-		const int number,
-		const int shuffleType) const;
+	virtual bool GenerateRays(const int number,
+							  const int raysType,
+							  SimpleRayContainer &rays);
+
+	bool GenerateRayBundle(SimpleRayContainer &rayBundle,
+						   const SimpleRay &mainRay,
+						   const int number,
+						   const int shuffleType) const;
 
 	virtual void CastRays(SimpleRayContainer &rays,
-		VssRayContainer &vssRays,
-		const bool castDoubleRays,
-		const bool pruneInvalidRays = true);
+						  VssRayContainer &vssRays,
+						  const bool castDoubleRays,
+						  const bool pruneInvalidRays = true);
 
 	/** Returns a view cells manager of the given name.
@@ -153,4 +146,5 @@
 	bool InitRayCast(const string externKdTree, const string internKdTree);
 
+bool ExportObj(const string filename, const ObjectContainer &objects);
 
 	////////////////////////////////////////////////
@@ -206,4 +200,7 @@
   bool mStopComputation;
   
+	bool mExportObj;
+
+
 protected:
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.h	(revision 1686)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.h	(revision 1695)
@@ -480,4 +480,5 @@
 		void EvalCandidate(bool computeSplitplane = true)
 		{
+			mDirty = false;
 			sVspTree->EvalSubdivisionCandidate(*this, computeSplitplane);
 		}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.h	(revision 1520)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.h	(revision 1695)
@@ -27,5 +27,6 @@
 		 VSS_BASED_DISTRIBUTION,
 		 OBJECT_DIRECTION_BASED_DISTRIBUTION,
-		 OBJECTS_INTERIOR_DISTRIBUTION
+		 OBJECTS_INTERIOR_DISTRIBUTION,
+		 REVERSE_OBJECT_BASED_DISTRIBUTION
 	 };
 
@@ -53,4 +54,15 @@
 	
 	 ObjectBasedDistribution(const Preprocessor &preprocessor):
+	 SamplingStrategy(preprocessor) {}
+
+	 virtual bool GenerateSample(SimpleRay &ray) const;
+};
+
+
+class ReverseObjectBasedDistribution: public SamplingStrategy
+{
+ public:
+	
+	 ReverseObjectBasedDistribution(const Preprocessor &preprocessor):
 	 SamplingStrategy(preprocessor) {}
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1694)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp	(revision 1695)
@@ -38,5 +38,5 @@
 // HACK
 const static bool SAMPLE_AFTER_SUBDIVISION = true;
-const static bool CLAMP_TO_BOX = false;
+const static bool CLAMP_TO_BOX = true;
 
 template <typename T> class myless
@@ -72,5 +72,4 @@
 
 	mViewCellsTree->SetViewCellsManager(this);
-	//mViewCellsTree = new ViewCellsTree(this);
 }
 
@@ -112,5 +111,9 @@
 	
 	// sampling type for view cells construction samples
-	if (strcmp(buf, "box") == 0)
+	if (strcmp(buf, "object") == 0)
+	{
+		mSamplingType = SamplingStrategy::OBJECT_BASED_DISTRIBUTION;
+	}
+	else if (strcmp(buf, "box") == 0)
 	{
 		mSamplingType = SamplingStrategy::SPATIAL_BOX_BASED_DISTRIBUTION;
@@ -123,4 +126,8 @@
 	{
 		mSamplingType = SamplingStrategy::OBJECT_DIRECTION_BASED_DISTRIBUTION;
+	}
+	else if (strcmp(buf, "reverse_object") == 0)
+	{
+		mSamplingType = SamplingStrategy::REVERSE_OBJECT_BASED_DISTRIBUTION;
 	}
 	/*else if (strcmp(buf, "interior") == 0)
@@ -137,5 +144,9 @@
 	Environment::GetSingleton()->GetStringValue("ViewCells.Evaluation.samplingType", buf);
 	
-	if (strcmp(buf, "box") == 0)
+	if (strcmp(buf, "object") == 0)
+	{
+		mEvaluationSamplingType = SamplingStrategy::OBJECT_BASED_DISTRIBUTION;
+	}
+	else if (strcmp(buf, "box") == 0)
 	{
 		mEvaluationSamplingType = SamplingStrategy::SPATIAL_BOX_BASED_DISTRIBUTION;
@@ -148,4 +159,8 @@
 	{
 		mEvaluationSamplingType = SamplingStrategy::OBJECT_DIRECTION_BASED_DISTRIBUTION;
+	}
+	else if (strcmp(buf, "reverse_object") == 0)
+	{
+		mEvaluationSamplingType = SamplingStrategy::REVERSE_OBJECT_BASED_DISTRIBUTION;
 	}
 	/*else if (strcmp(buf, "interior") == 0)
@@ -155,4 +170,5 @@
 	else
 	{
+		mEvaluationSamplingType = -1;
 		Debug << "error! wrong sampling type" << endl;
 		exit(0);
@@ -868,6 +884,10 @@
 	int castSamples = 0;
 	char str[64]; 
+	int oldSamples = 0;
+
+	int samplesForStats;
 
 	Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samplesPerPass", samplesPerPass);
+	Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samplesForStats", samplesForStats);
 	Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samples", numSamples);
 
@@ -924,8 +944,9 @@
 
 		Real timeDiff = TimeDiff(startTime, GetTime());
-		Debug << "finished in " << timeDiff * 1e-3 << " secs" << endl;
-		cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
-
+		
+		cout << "finished in " << timeDiff * 1e-3f << " secs" << endl;
 		cout << "computing sample contributions of " << (int)evaluationSamples.size()  << " samples ... ";
+		
+		Debug << "finished in " << timeDiff * 1e-3f << " secs" << endl;
 		Debug << "computing sample contributions of " << (int)evaluationSamples.size()  << " samples ... ";
 
@@ -938,25 +959,38 @@
 		Debug << "finished in " << timeDiff * 1e-3 << " secs" << endl;
 
-		startTime = GetTime();
-		cout << "compute new statistics ... " << endl;
-
-		///////////
-		//-- output stats
-
-		sprintf(str, "-%09d-eval.log", castSamples);
-		string fileName = string(statsPrefix) + string(str);
-
-		///////////////
-		//-- propagate pvs or pvs size information
-
-		ObjectPvs pvs;
-		UpdatePvsForEvaluation(mViewCellsTree->GetRoot(), pvs);
-
-		ExportStats(fileName);
-
-		timeDiff = TimeDiff(startTime, GetTime());
-		cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
-		Debug << "statistis compted in " << timeDiff * 1e-3 << " secs" << endl;
-	
+		if ((castSamples >= samplesForStats + oldSamples) || (castSamples >= numSamples))
+		{
+			oldSamples += samplesForStats;
+
+			///////////
+			//-- output stats
+
+			sprintf(str, "-%09d-eval.log", castSamples);
+			string fileName = string(statsPrefix) + string(str);
+
+			///////////////
+			//-- propagate pvs or pvs size information
+
+			startTime = GetTime();
+			ObjectPvs pvs;
+
+			cout << "updating pvs for contribution ... " << endl;
+
+			UpdatePvsForEvaluation(mViewCellsTree->GetRoot(), pvs);
+
+			timeDiff = TimeDiff(startTime, GetTime());
+			cout << "finished updating the pvs in " << timeDiff * 1e-3 << " secs" << endl;
+			Debug << "pvs evaluated in " << timeDiff * 1e-3 << " secs" << endl;
+		
+			startTime = GetTime();
+			cout << "compute new statistics ... " << endl;
+
+			ExportStats(fileName);
+
+			timeDiff = TimeDiff(startTime, GetTime());
+			cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
+			Debug << "statistis computed in " << timeDiff * 1e-3 << " secs" << endl;
+		}
+
 		disposeRays(evaluationSamples, NULL);
 	}
@@ -966,4 +1000,5 @@
 	//-- histogram
 
+	const int numLeaves = mViewCellsTree->GetNumInitialViewCells(mViewCellsTree->GetRoot());
 	bool useHisto;
 	int histoStepSize;
@@ -971,7 +1006,4 @@
 	Environment::GetSingleton()->GetBoolValue("ViewCells.Evaluation.histogram", useHisto);
 	Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.histoStepSize", histoStepSize);
-
-	const int numLeaves = mViewCellsTree->GetNumInitialViewCells(mViewCellsTree->GetRoot());
-
 
 	if (useHisto)
@@ -2529,19 +2561,22 @@
 	// reset recursive pvs
 	pvs.Clear();
+
+	// pvss of child nodes
 	vector<ObjectPvs> pvsList;
 
 	ViewCellContainer::const_iterator vit, vit_end = interior->mChildren.end();
-
-	for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit)
-	{
-		ObjectPvs objPvs;
+	pvsList.resize((int)interior->mChildren.size());
+	int i = 0;
+	for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit, ++ i)
+	{
+		//ObjectPvs objPvs;
 		
 		//////////////////
 		//-- recursivly compute child pvss
 
-		UpdatePvsForEvaluation(*vit, objPvs);
+		UpdatePvsForEvaluation(*vit, pvsList[i]/*objPvs*/);
 
 		// store pvs in vector
-		pvsList.push_back(objPvs);
+		//pvsList.push_back(objPvs);
 	}
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp	(revision 1667)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp	(revision 1695)
@@ -1527,4 +1527,5 @@
 	tqueue.push(mRoot);
 
+	//cout << "exporting stats ... " << endl;
 	int numViewCells = 1;
 	
@@ -1534,7 +1535,4 @@
 	const int rootPvs = GetPvsSize(mRoot);
 	const int rootEntries = GetPvsEntries(mRoot);
-
-	cout << "exporting stats ... " << endl;
-	
 	float totalRenderCost, avgRenderCost, expectedCost;
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 1686)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h	(revision 1695)
@@ -421,4 +421,5 @@
 		void EvalCandidate(bool computeSplitplane = true)
 		{
+			mDirty = false;
 			sBvHierarchy->EvalSubdivisionCandidate(*this, computeSplitplane);
 		}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.cpp	(revision 1694)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.cpp	(revision 1695)
@@ -1328,5 +1328,4 @@
 	ObjectContainer::const_iterator oit, oit_end = objects.end();
 
-
 	///////////////////////////
 	//-- compute bounding box of object space
Index: GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp	(revision 1694)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/main.cpp	(revision 1695)
@@ -94,5 +94,5 @@
 
 
-static string GetInternKdTreeName(const string &filename)
+static string GetInternFilename(const string &filename, const string newSuffix)
 {
 	vector<string> filenames;
@@ -118,5 +118,5 @@
 			strippedFilename = string(str);
 
-			delete []str;
+			delete [] str;
 		}
 		
@@ -125,12 +125,5 @@
 		if (i == (int)filenames.size() - 1)
 		{
-			if (preprocessor->mLoadMeshes)
-			{
-				suffix = ".kdm";	
-			}
-			else
-			{
-				suffix = ".kdt";
-			}
+			suffix = newSuffix;
 		}
 
@@ -200,5 +193,5 @@
 	Environment::GetSingleton()->GetStringValue("Scene.filename", buff);
 	string filename(buff);
-	const string dummyname = GetInternKdTreeName(filename);
+	
 
 	if (!preprocessor->LoadScene(filename))
@@ -218,7 +211,8 @@
 	
 	const string externKdTree = ReplaceSuffix(filename, ".obj", ".kdf");
-	const string internKdTree = GetInternKdTreeName(filename);
+	const string internKdTree = GetInternFilename(filename, preprocessor->mLoadMeshes ? ".kdm" : ".kdt");
 
 	//-- initialize external ray casters
+	
 	if (preprocessor->InitRayCast(externKdTree, internKdTree))
 	{
@@ -230,4 +224,32 @@
 		Cleanup();
 		exit(1);
+	}
+
+	
+	// export objects as obj
+	if (preprocessor->mExportObj)
+	{
+		if (strstr(filename.c_str(), ".obj"))
+		{
+			cerr << "already in obj format" << endl;
+			if (1)
+			preprocessor->ExportObj("test.obj", preprocessor->mObjects);
+		}
+		else
+		{
+			const string objname = GetInternFilename(filename, ".obj");
+
+			//cout << "exporting scene to " << objname << endl;
+			bool success = preprocessor->ExportObj(objname, preprocessor->mObjects);
+
+			if (success)
+			{
+				cout << "finished exporting obj" << endl;
+			}
+			else
+			{
+				cerr << "error exporting " << objname << endl;
+			}
+		}
 	}
 
Index: GTP/trunk/Lib/Vis/Preprocessing/src/ObjParser.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/ObjParser.cpp	(revision 1655)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/ObjParser.cpp	(revision 1695)
@@ -204,5 +204,5 @@
 				sscanf(str + 1, "%f %f %f", &x, &y, &z);
 				vertices.push_back(Vector3(x,y,z));
-				//Debug << "vertex: " << vertices.back() << endl;
+				//cout << "vertex: " << vertices.back() << endl;
 				break;
 			}
Index: GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.cpp
===================================================================
--- GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.cpp	(revision 1692)
+++ GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.cpp	(revision 1695)
@@ -151,4 +151,36 @@
 }
 
+
+bool ReverseObjectBasedDistribution::GenerateSample(SimpleRay &ray) const
+{
+	Vector3 origin, direction; 
+
+	mPreprocessor.mViewCellsManager->GetViewPoint(origin);
+
+	Vector3 point;
+	Vector3 normal;
+	//cout << "y";
+	const int i = (int)RandomValue(0, (float)mPreprocessor.mObjects.size() - 0.5f);
+
+	Intersectable *object = mPreprocessor.mObjects[i];
+
+	object->GetRandomSurfacePoint(point, normal);
+	direction = origin - point;
+
+	// $$ 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(point, direction, pdf);
+	
+	return true;
+}
+
 #if 0
 bool ObjectsInteriorDistribution::GenerateSample(SimpleRay &ray) const
