Index: trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h	(revision 437)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h	(revision 440)
@@ -441,8 +441,4 @@
 	int CastRay(Ray &ray);
 
-	/** Set to true if new view cells shall be generated in each leaf.
-	*/
-	void SetGenerateViewCells(int generateViewCells);
-
 	/// bsp tree construction types
 	enum {FROM_INPUT_VIEW_CELLS, FROM_SCENE_GEOMETRY, FROM_SAMPLES};
Index: trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp	(revision 433)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp	(revision 440)
@@ -444,5 +444,5 @@
 
 void
-VspKdTree::Construct(VssRayContainer &rays,
+VspKdTree::Construct(const VssRayContainer &rays,
 					 AxisAlignedBox3 *forcedBoundingBox)
 {
Index: trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.h	(revision 439)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.h	(revision 440)
@@ -84,4 +84,6 @@
 {
 public:
+	BspRenderSimulator(BspTree *bspTree);
+
 	BspRenderSimulator(float objRenderCost, 
 							   float vcOverhead, 
@@ -104,4 +106,6 @@
 {
 public:
+	KdRenderSimulator(KdTree *kdTree);
+
 	KdRenderSimulator(float objRenderCost, 
 							  float vcOverhead, 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 437)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 440)
@@ -526,7 +526,4 @@
 	static void ParseEnvironment();
 
-	/// BSP tree construction method
-	static int sConstructionMethod;
-
 
 protected:
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h	(revision 440)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h	(revision 440)
@@ -0,0 +1,295 @@
+#ifndef _ViewCellsManager_H__
+#define _ViewCellsManager_H__
+
+#include "Ray.h"
+#include "VssRay.h"
+#include "Containers.h"
+
+class ViewCell;
+class Intersectable;
+class RenderSimulator;
+class Mesh;
+struct Triangle3;
+class SimulationStatistics;
+class BspTree;
+class KdTree;
+class VspKdTree;
+class VspBspTree;
+class KdNode;
+class KdLeaf;
+class VspKdTree;
+class AxisAlignedBox3;
+/**
+	Manages different higher order operations on the view cells.
+*/
+class ViewCellsManager
+{
+
+public:
+	
+	/// view cell container types
+	enum {BSP, KD, VSP_KD, VSP_BSP};
+
+	/** Constructor taking the maximal number of samples used for construction
+	*/
+	ViewCellsManager(const int constructionSamples);
+
+	ViewCellsManager();
+
+	~ViewCellsManager();
+
+	/** Constructs view cell container with a given number of samples.
+	*/
+	virtual int Construct(const ObjectContainer &objects, 
+						  const VssRayContainer &rays,
+						  AxisAlignedBox3 *sceneBbox = NULL) = 0;
+
+	/** Casts bundle of rays to the view cells and stores contributions in PVS.
+	*/
+	int CastRays(const RayContainer &rays);
+
+	/** Casts ray to the view cells and stores contributions in PVS.
+	*/
+	virtual int CastRay(const Ray &ray) = 0;
+
+	/** Post processes view cells givemŽa number of rays.
+	*/
+	virtual int PostProcess(const ObjectContainer &objects, 
+							const RayContainer &rays) = 0;
+
+	/** Show visualization of the view cells.
+	*/
+	virtual void Visualize(const ObjectContainer &objects,
+						   const RayContainer &sampleRays) = 0;
+
+	/** type of the view cell container.
+	*/
+	virtual int GetType() const = 0;
+
+	/** Simulates rendering with the given view cell partition.
+		@returns render time statistics
+	*/
+	SimulationStatistics SimulateRendering() const;
+
+	/** Load the input viewcells. The input viewcells should be given as a collection
+		of meshes. Each mesh is assume to form a bounded polyhedron defining the interior of
+		the viewcell. The method then builds a BSP tree of these view cells.
+		
+		@param filename file to load
+		@return true on success
+    */
+    bool LoadViewCells(const string filename);
+
+	/** Constructs view cell from base triangle. The ViewCell is extruded along the normal vector.
+		@param the base triangle
+		@param the height of the newly created view cell
+	*/
+	ViewCell *ExtrudeViewCell(const Triangle3 &baseTri, const float height) const;
+
+	/** Merges two view cells.
+		@note the piercing rays of the front and back will be ordered	
+		@returns new view cell based on the merging.
+	*/
+	ViewCell *Merge(ViewCell &front, ViewCell &back) const;
+	
+	/** Generates view cell of type specified by this manager
+	*/
+	virtual ViewCell *GenerateViewCell(Mesh *mesh = NULL) const;
+
+	/** Adds a new view cell to the list of predefined view cells.
+	*/
+	void AddViewCell(ViewCell *viewCell);
+
+	/** Derive view cells from objects.
+	*/
+	void DeriveViewCells(const ObjectContainer &objects, 
+						 ViewCellContainer &viewCells, 
+						 const int maxViewCells) const;
+
+	/** Sets maximal number of samples used for the 
+		construction of the view cells.
+	*/
+	void SetVisualizationSamples(const int visSamples);
+
+	/** Sets maximal number of samples used for the visualization of the view cells.
+	*/
+	void SetConstructionSamples(const int constructionSamples);
+
+	/** Sets maximal number of samples used for the post processing of the view cells.
+	*/
+	void SetPostProcessSamples(const int postProcessingSamples);
+
+	/** See set.
+	*/
+	int GetVisualizationSamples() const;
+
+	/** See set.
+	*/
+	int GetConstructionSamples() const;
+
+	/** See set.
+	*/
+	int GetPostProcessSamples() const;
+
+	/** Returns true if view cells wer already constructed.
+	*/
+	virtual bool ViewCellsConstructed() const = 0;
+	
+protected:
+	/** Adds sample constributions to the view cell PVS.
+		@returns number of sample contributions
+	*/
+	virtual int AddSampleContributions(const Ray &ray,
+									   Intersectable *sObject,
+									   Intersectable *tObject) = 0;
+
+	/** Initialises the render time simulator.
+	*/
+	void InitRenderSimulator();
+	/////////////////////
+
+	
+	/// the view cell corresponding to unbounded space
+	ViewCell *mUnbounded;
+
+	/// Simulates rendering
+	RenderSimulator *mRenderSimulator;
+
+	/// Loaded view cells
+	ViewCellContainer mViewCells;
+
+	/// maximum number of samples taken for construction of the view cells
+	int mConstructionSamples;
+	int mPostProcessSamples;
+	int mVisualizationSamples;
+};
+
+/**
+	Manages different higher order operations on the view cells.
+*/
+class BspViewCellsManager: public ViewCellsManager
+{
+
+public:
+
+	BspViewCellsManager(BspTree *tree, int constructionSamples);
+
+	int Construct(const ObjectContainer &objects, 
+				  const VssRayContainer &rays,
+				  AxisAlignedBox3 *sceneBbox);
+
+	int CastRay(const Ray &rays);
+
+	int PostProcess(const ObjectContainer &objects, 
+					const RayContainer &rays);
+
+	void Visualize(const ObjectContainer &objects,
+				   const RayContainer &sampleRays);
+
+	int GetType() const;
+	
+	/** Generates view cell of type specified by this manager
+	*/
+	ViewCell *GenerateViewCell(Mesh *mesh = NULL) const;
+
+	bool ViewCellsConstructed() const;
+
+protected:
+
+	int	AddSampleContributions(const Ray &ray, Intersectable *sObject, Intersectable *tObject);
+
+	/// the BSP tree.
+	BspTree *mBspTree;
+
+
+private:
+
+
+	/** Exports visualization of the BSP splits.
+	*/
+	void ExportSplits(const ObjectContainer &objects, const RayContainer &sampleRays);
+
+	/** Exports visualization of the BSP PVS.
+	*/
+	void ExportBspPvs(const ObjectContainer &objects, const RayContainer &sampleRays);
+
+};
+
+/**
+	Manages different higher order operations on the KD type view cells.
+*/
+class KdViewCellsManager: public ViewCellsManager
+{
+
+public:
+
+	KdViewCellsManager(KdTree *tree);
+
+	int Construct(const ObjectContainer &objects, 
+				  const VssRayContainer &rays,
+				  AxisAlignedBox3 *sceneBbox);
+
+	int CastRay(const Ray &ray);
+
+	int PostProcess(const ObjectContainer &objects, 
+					const RayContainer &rays);
+
+	void Visualize(const ObjectContainer &objects,
+				   const RayContainer &sampleRays);
+
+	int GetType() const;
+
+	bool ViewCellsConstructed() const;
+
+
+protected:
+
+	 KdNode *GetNodeForPvs(KdLeaf *leaf);
+
+	 int AddSampleContributions(const Ray &ray, Intersectable *sObject, Intersectable *tObject);
+
+	/// the BSP tree.
+	KdTree *mKdTree;
+
+	/// depth of the KD tree nodes with represent the view cells
+	int mKdPvsDepth;
+};
+
+/**
+	Manages different higher order operations on the view cells 
+	for vsp kd tree view cells.
+*/
+class VspKdViewCellsManager: public ViewCellsManager
+{
+
+public:
+
+	VspKdViewCellsManager(VspKdTree *vspKdTree, int constructionSamples);
+
+	int Construct(const ObjectContainer &objects, 
+				  const VssRayContainer &rays,
+				  AxisAlignedBox3 *sceneBbox);
+
+	int CastRay(const Ray &rays);
+
+	int PostProcess(const ObjectContainer &objects, 
+					const RayContainer &rays);
+
+	void Visualize(const ObjectContainer &objects,
+				   const RayContainer &sampleRays);
+
+	int GetType() const;
+	
+	bool ViewCellsConstructed() const;
+
+
+protected:
+
+	int	AddSampleContributions(const Ray &ray, Intersectable *sObject, Intersectable *tObject);
+
+	/// the BSP tree.
+	VspKdTree *mVspKdTree;
+};
+
+
+#endif
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h	(revision 438)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h	(revision 440)
@@ -103,4 +103,7 @@
   ExportBspLeaves(const BspTree &tree, const int maxPvs = 0) = 0;
 
+  virtual void
+  ExportGeometry(const ObjectContainer &objects) = 0;
+
   void SetExportRayDensity(const bool d) { mExportRayDensity = d; }
   
Index: trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.cpp	(revision 439)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.cpp	(revision 440)
@@ -53,4 +53,8 @@
 /*     class BspRenderSimulator implementation          */
 /********************************************************/
+BspRenderSimulator::BspRenderSimulator(BspTree *bspTree):
+mBspTree(bspTree)
+{
+}
 
 BspRenderSimulator::BspRenderSimulator(float objRenderCost, 
@@ -149,4 +153,9 @@
 											 KdTree *kdTree):
 RenderSimulator(objRenderCost, vcOverhead, moveSpeed), mKdTree(kdTree)
+{
+}
+
+KdRenderSimulator::KdRenderSimulator(KdTree *kdTree):
+mKdTree(kdTree)
 {
 }
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 439)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 440)
@@ -35,6 +35,4 @@
 */
 const float BspTree::sBalancedRaysTable[] = {1, -1, 0, 0, 0};
-
-int BspTree::sConstructionMethod = FROM_INPUT_VIEW_CELLS;
 
 int BspTree::sFrontId = 0; 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 439)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 440)
@@ -40,5 +40,5 @@
 	
 	filenames.push_back(string(str, pos, str.size() - pos));
-	return filenames.size();
+	return (int)filenames.size();
 }
 
@@ -161,271 +161,4 @@
 }
 
-
-void Preprocessor::ExportSplits(const ObjectContainer &objects,
-								const RayContainer &sampleRays,
-								const int visSamples)
-{
-	Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
-
-	if (exporter) 
-	{	
-		Material m; 
-		m.mDiffuseColor = RgbColor(1, 0, 0);
-		exporter->SetForcedMaterial(m);
-		exporter->SetWireframe();
-		exporter->ExportBspSplits(*mBspTree, true);
-
-		// take forced material, else big scenes cannot be viewed
-		m.mDiffuseColor = RgbColor(0, 1, 0);
-		exporter->SetForcedMaterial(m);
-		exporter->SetFilled();
-
-		exporter->ResetForcedMaterial();
-		
-		// export rays
-		if (0)
-		{
-			RayContainer outRays;
-		
-			for (int i = 0; i < sampleRays.size(); ++ i)
-			{
-				// only rays piercing geometry
-				if (!sampleRays[i]->intersections.empty())
-					outRays.push_back(sampleRays[i]);
-			}
-			if (BspTree::sConstructionMethod == BspTree::FROM_SAMPLES)
-			{
-				// export rays 
-				exporter->ExportRays(outRays, 1000, RgbColor(1, 1, 0));
-			}
-		}
-
-		if (1)
-			ExportSceneGeometry(exporter, objects);
-
-		delete exporter;
-	}
-}
-
-inline bool vc_gt(ViewCell *a, ViewCell *b) 
-{ 
-	return a->GetPvs().GetSize() > b->GetPvs().GetSize();
-}
-
-void Preprocessor::ExportBspPvs(const ObjectContainer &objects,
-								const RayContainer &sampleRays,
-								const int visSamples)
-{
-	const int leafOut = 10;
-	
-	ViewCell::NewMail();
-
-	//-- some rays for output
-	const int raysOut = min((int)sampleRays.size(), visSamples);
-	cout << "visualization using " << visSamples << " samples" << endl;
-	vector<Ray *> vcRays[leafOut];
-
-	if (0)
-	{
-		//-- some random view cells and rays for output
-		vector<BspLeaf *> bspLeaves;
-
-		for (int i = 0; i < leafOut; ++ i)
-			bspLeaves.push_back(mBspTree->GetRandomLeaf());	
-		
-		for (int i = 0; i < bspLeaves.size(); ++ i)
-		{
-			cout << "creating output for view cell " << i << " ... ";
-			// check whether we can add the current ray to the output rays
-			for (int k = 0; k < raysOut; ++ k) 
-			{
-				Ray *ray = sampleRays[k];
-
-				for	(int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
-				{
-					BspLeaf *leaf = ray->bspIntersections[j].mLeaf;
-
-					if (bspLeaves[i]->GetViewCell() == leaf->GetViewCell()) 
-					{
-						vcRays[i].push_back(ray);
-					}
-				}
-			}
-
-			Intersectable::NewMail();
-
-			BspViewCell *vc = dynamic_cast<BspViewCell *>(bspLeaves[i]->GetViewCell());
-
-			//bspLeaves[j]->Mail();
-			char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
-
-			Exporter *exporter = Exporter::GetExporter(s);
-			exporter->SetFilled();
-
-			ViewCellPvsMap::iterator it = vc->GetPvs().mEntries.begin();
-
-			exporter->SetWireframe();
-			//exporter->SetFilled();
-
-			Material m;//= RandomMaterial();
-			m.mDiffuseColor = RgbColor(0, 1, 0);
-			exporter->SetForcedMaterial(m);
-
-			if (vc->GetMesh())
-				exporter->ExportViewCell(vc);
-			else
-			{
-				PolygonContainer cell;
-				// export view cell geometry
-				mBspTree->ConstructGeometry(vc, cell);
-				exporter->ExportPolygons(cell);
-				CLEAR_CONTAINER(cell);
-			}
-
-			Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize() 
-					<< ", piercing rays=" << (int)vcRays[i].size() << endl;
-
-			// export rays piercing this view cell
-			exporter->ExportRays(vcRays[i], 1000, RgbColor(0, 1, 0));
-
-			m.mDiffuseColor = RgbColor(1, 0, 0);
-			exporter->SetForcedMaterial(m);
-
-			// exporter->SetWireframe();
-			exporter->SetFilled();
-
-			// output PVS of view cell
-			for (; it != vc->GetPvs().mEntries.end(); ++ it) 
-			{
-				Intersectable *intersect = (*it).first;
-				if (!intersect->Mailed())
-				{
-					exporter->ExportIntersectable(intersect);
-					intersect->Mail();
-				}			
-			}
-				
-			// output rest of the objects
-			if (0)
-			{
-				Material m;//= RandomMaterial();
-				m.mDiffuseColor = RgbColor(0, 0, 1);
-				exporter->SetForcedMaterial(m);
-
-				for (int j = 0; j < objects.size(); ++ j)
-					if (!objects[j]->Mailed())
-					{
-						exporter->SetForcedMaterial(m);
-						exporter->ExportIntersectable(objects[j]);
-						objects[j]->Mail();
-					}
-			}
-			DEL_PTR(exporter);
-			cout << "finished" << endl;
-		}
-	}
-	else
-	{
-		ViewCellContainer viewCells;
-
-		mBspTree->CollectViewCells(viewCells);
-		stable_sort(viewCells.begin(), viewCells.end(), vc_gt);
-
-		int limit = min(leafOut, (int)viewCells.size()); 
-		
-		for (int i = 0; i < limit; ++ i)
-		{
-			cout << "creating output for view cell " << i << " ... ";
-			
-            Intersectable::NewMail();
-			BspViewCell *vc = dynamic_cast<BspViewCell *>(viewCells[i]);
-
-			cout << "creating output for view cell " << i << " ... ";
-			// check whether we can add the current ray to the output rays
-			for (int k = 0; k < raysOut; ++ k) 
-			{
-				Ray *ray = sampleRays[k];
-
-				for	(int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
-				{
-					BspLeaf *leaf = ray->bspIntersections[j].mLeaf;
-
-					if (vc == leaf->GetViewCell()) 
-					{
-						vcRays[i].push_back(ray);
-					}
-				}
-			}
-
-			//bspLeaves[j]->Mail();
-			char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
-
-			Exporter *exporter = Exporter::GetExporter(s);
-			
-			exporter->SetWireframe();
-
-			Material m;//= RandomMaterial();
-			m.mDiffuseColor = RgbColor(0, 1, 0);
-			exporter->SetForcedMaterial(m);
-
-			if (vc->GetMesh())
-				exporter->ExportViewCell(vc);
-			else
-			{
-				PolygonContainer cell;
-				// export view cell
-				mBspTree->ConstructGeometry(vc, cell);
-				exporter->ExportPolygons(cell);
-				CLEAR_CONTAINER(cell);
-			}
-
-			
-			Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize() 
-					<< ", piercing rays=" << (int)vcRays[i].size() << endl;
-
-			
-			// export rays piercing this view cell
-			exporter->ExportRays(vcRays[i], 1000, RgbColor(0, 1, 0));
-	
-			m.mDiffuseColor = RgbColor(1, 0, 0);
-			exporter->SetForcedMaterial(m);
-
-			ViewCellPvsMap::const_iterator it,
-				it_end = vc->GetPvs().mEntries.end();
-
-			// output PVS of view cell
-			for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it) 
-			{
-				Intersectable *intersect = (*it).first;
-				if (!intersect->Mailed())
-				{
-					Material m = RandomMaterial();
-			
-					exporter->SetForcedMaterial(m);
-
-					exporter->ExportIntersectable(intersect);
-					intersect->Mail();
-				}			
-			}
-				
-			DEL_PTR(exporter);
-			cout << "finished" << endl;
-		}
-	}
-}
-
-
-void Preprocessor::ExportSceneGeometry(Exporter *exporter, 
-									   const ObjectContainer &objects)
-{
-	Material m;//= RandomMaterial();
-	m.mDiffuseColor = RgbColor(0, 1, 0);
-	exporter->SetForcedMaterial(m);
-	exporter->SetWireframe();
-
-	for (int j = 0; j < objects.size(); ++ j)
-		exporter->ExportIntersectable(objects[j]);
-}
-
 bool Preprocessor::PrepareViewCells()
 {
@@ -436,18 +169,27 @@
 	if (strcmp(viewCellsStr, "kdTree") == 0)
 	{
-		//mViewCellsManager = new KdViewCellsManager(mKdTree);
+		mViewCellsManager = new KdViewCellsManager(mKdTree);
 	}
 	if (strcmp(viewCellsStr, "bspTree") == 0)
 	{
-		//mViewCellsManager = new BspViewCellsManager(mBspTree, mBspConstructionSamples);
+		int bspConstructionSamples = 0;
+
+		environment->GetIntValue("BspTree.Construction.samples", bspConstructionSamples);
+		mViewCellsManager = new BspViewCellsManager(mBspTree, bspConstructionSamples);
 	}
 	else if (strcmp(viewCellsStr, "vspTree") == 0)
 	{
-		//mViewCellsManager = new VspKdViewCellContaienr(mVspKdTree, mVspKdConstructionSamples);
+		int vspKdConstructionSamples = 0;
+		
+		environment->GetIntValue("VspKdTree.Construction.samples", vspKdConstructionSamples);
+        mViewCellsManager = new VspKdViewCellsManager(mVspKdTree, vspKdConstructionSamples);
 	}
 	else if (strcmp(viewCellsStr, "sceneDependent") == 0)
 	{
 		//TODO
-		//mViewCellsManager = new BspViewCellContainer(mBspTree);
+		int bspConstructionSamples = 0;
+
+		environment->GetIntValue("BspTree.Construction.samples", bspConstructionSamples);
+		mViewCellsManager = new BspViewCellsManager(mBspTree, bspConstructionSamples);
 	}
 	else
@@ -457,5 +199,16 @@
 	}
 
+	int postProcessSamples = 0;
+	int visSamples = 0;
+
+	environment->GetIntValue("ViewCells.PostProcessing.samples", postProcessSamples);
+ 	environment->GetIntValue("BspTree.Visualization.samples", visSamples);
+
+	mViewCellsManager->SetPostProcessSamples(postProcessSamples);
+	mViewCellsManager->SetVisualizationSamples(visSamples);
+
+
 	//-- parse view cells construction method
+
 	bool loadViewCells = false;
 	environment->GetBoolValue("ViewCell.Construction.loadFromFile", loadViewCells);
Index: trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h	(revision 438)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h	(revision 440)
@@ -84,4 +84,7 @@
 
   virtual void 
+  ExportGeometry(const ObjectContainer &objects);
+
+  virtual void 
   ExportBspSplitPlanes(const BspTree &tree);
   
Index: trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.h	(revision 439)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.h	(revision 440)
@@ -22,33 +22,38 @@
 
 protected:
+	/** Sets up ray for sampling.
+	*/
   void
   SetupRay(Ray &ray, 
 		   const Vector3 &point, 
 		   const Vector3 &direction,
-		   const int type);
+			 const int type,
+			 const Ray::Intersection &source);
 
-  KdNode *
-  GetNodeForPvs(KdLeaf *leaf);
-
-	int
-	AddNodeSamples(const Ray &ray,
-								 Intersectable *sObject,
-								 Intersectable *tObject
-								 );
-
+	/** Refined sampling for finding "holes", i.e., difficult visibility.
+	*/
   void
   HoleSamplingPass();
 
+	/** Casts a bundle of sample rays into the scene.
+	*/
+	int CastRays(const RayContainer &rays,
+				 int &sampleContribtion, 
+				 int &contributingSamples);
+	
+	/** Casts a ray into the scene.
+	*/
 	int
-	CastRay(Intersectable *object,
-					Ray &ray);
+	CastRay(const Ray &ray);
 	
-	KdNode *
-	GetNodeToSample(Intersectable *object);
+	/** Verify if the exact visibility for this object was established.
+	*/
 	void
 	VerifyVisibility(Intersectable *object);
 
-	int
-	CastEdgeSamples(
+	/** Sample the shiluette of objects in order to find visibility changes
+		along the visibility skeleton.
+	*/
+	int CastEdgeSamples(
 									Intersectable *object,
 									const Vector3 &point,
@@ -57,27 +62,14 @@
 									);
 
-	/** Processes the BSP based view cells during a pass.
-		
+	/** Processes the view cells during a pass.
 		@param ray the current ray
-		@param object the currently processed object
-		@param faceIndex the sampled face of the object
-		@param contributingSamples samples contributing to pvs
-		@param sampleContributions contribution of the samples
-	*/
-	/*void ProcessBspViewCells(const Ray &ray,
-							 Intersectable *object,
-							 const int faceIndex,
-							 int &contributingSamples,
-							 int &sampleContributions);
 
-	void ProcessVspViewCells(Ray &ray,
-							 Intersectable *object,
-							 const int faceIndex,
-							 int &contributingSamples,
-							 int &sampleContributions);
+		@param contributingSamples returns the samples contributing to pvs
+		@param sampleContributions returns the accumulated 
+		contribution of the samples
 */
+	
 	void ProcessViewCells(const Ray &ray,
-						  Intersectable *object,
-						  const int faceIndex,
+						  const ObjectContainer &objects,
 						  int &contributingSamples,
 						  int &sampleContributions);
@@ -87,11 +79,9 @@
 	int AddObjectSamples(Intersectable *obj, const Ray &ray);
 
-	/** Post processes view cells (i.e., merges or subdivides view cells based
-		on the PVS and the ray sets.
-		@param rays a set of rays which carries the visibility information 
-		the merging / subdivision is based on.
-		@returns number of merged view cells.
+	/**
+		Returns random node as target for the current sample ray.
 	*/
-	int PostprocessViewCells(const RayContainer &rays);
+	KdNode *GetNodeToSample(Intersectable *object);
+
 
 protected:
@@ -101,16 +91,10 @@
 	int mSamplesPerPass;
 	int mTotalSamples;
-	int mKdPvsDepth;
+	
 	ofstream mStats;
 	ObjectContainer mObjects;
 
 	RayContainer mSampleRays;
-	VssRayContainer mVspSampleRays;
-	
-	int mVspConstructionSamples;
-
-    int mPostProcessSamples;
-	int mVisualizationSamples;
-
+	VssRayContainer mVssSampleRays;
 };
 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp	(revision 438)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp	(revision 440)
@@ -1148,2 +1148,11 @@
 	CLEAR_CONTAINER(polys);
 }
+
+
+void X3dExporter::ExportGeometry(const ObjectContainer &objects)
+{
+	for (int j = 0; j < objects.size(); ++ j)
+		ExportIntersectable(objects[j]);
+}
+
+
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.h	(revision 439)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.h	(revision 440)
@@ -100,17 +100,11 @@
 
 protected:
-  void ExportBspPvs(const ObjectContainer &objects,
-					const RayContainer &sampleRays,
-					const int visSamples);
 
-  void ExportSplits(const ObjectContainer &objects,
-					const RayContainer &sampleRays,
-					const int visSamples);
+  /////////////////////////
 
-  /** Export scene geometry.
-  */
-  void ExportSceneGeometry(Exporter *exporter, const ObjectContainer &objects);
-
+  /// samples used for construction of the BSP view cells tree.
   int mBspConstructionSamples;
+   /// samples used for construction of the VSP KD tree.
+  int mVspKdConstructionSamples;
 };
 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.h	(revision 428)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.h	(revision 440)
@@ -426,5 +426,5 @@
 	virtual ~VspKdTree();
 
-	virtual void Construct(VssRayContainer &rays,
+	virtual void Construct(const VssRayContainer &rays,
 						   AxisAlignedBox3 *forcedBoundingBox = NULL);
 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp	(revision 439)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp	(revision 440)
@@ -15,10 +15,5 @@
   environment->GetIntValue("Sampling.samplesPerPass", mSamplesPerPass);
   environment->GetIntValue("Sampling.totalSamples", mTotalSamples);
-  environment->GetIntValue("BspTree.Construction.samples", mBspConstructionSamples);
-  environment->GetIntValue("VspKdTree.Construction.samples", mVspConstructionSamples);
-  environment->GetIntValue("ViewCells.PostProcessing.samples", mPostProcessSamples);
-  environment->GetIntValue("BspTree.Visualization.samples", mVisualizationSamples);
  
-  mKdPvsDepth = 100;
   mStats.open("stats.log");
 }
@@ -27,5 +22,5 @@
 {
 	CLEAR_CONTAINER(mSampleRays);
-	CLEAR_CONTAINER(mVspSampleRays);
+	CLEAR_CONTAINER(mVssSampleRays);
 }
 
@@ -34,5 +29,6 @@
 															 const Vector3 &point, 
 															 const Vector3 &direction,
-															 const int type)
+							   const int type,
+							   const Ray::Intersection &origin)
 {
   ray.intersections.clear();
@@ -40,52 +36,10 @@
   ray.testedObjects.clear();
   ray.bspIntersections.clear();
+  
 	ray.mFlags |= Ray::STORE_KDLEAVES | Ray::STORE_BSP_INTERSECTIONS;
   //  cout<<point<<" "<<direction<<endl;
   ray.Init(point, direction, type);
-}
-
-KdNode *
-SamplingPreprocessor::GetNodeForPvs(KdLeaf *leaf)
-{
-  KdNode *node = leaf;
-  while (node->mParent && node->mDepth > mKdPvsDepth)
-    node = node->mParent;
-  return node;
-}
-
-int
-SamplingPreprocessor::AddNodeSamples(const Ray &ray,
-									 Intersectable *sObject,
-									 Intersectable *tObject
-									 )
-{
-  int contributingSamples = 0;
-  int j;
-	int objects = 0;
-	if (sObject)
-		objects++;
-	if (tObject)
-		objects++;
-
-	if (objects) {
-		for (j=0; j < ray.kdLeaves.size(); j++) {
-			KdNode *node = GetNodeForPvs( ray.kdLeaves[j] );
-			if (sObject)
-				contributingSamples += sObject->mKdPvs.AddSample(node);
-			if (tObject)
-				contributingSamples += tObject->mKdPvs.AddSample(node);
-		}
-	}
-	
-	for (j=1; j < ((int)ray.kdLeaves.size() - 1); j++) {
-		ray.kdLeaves[j]->AddPassingRay2(ray,
-										objects,
-										ray.kdLeaves.size()
-										);
-  }
-  
-  return contributingSamples;
-}
-
+	ray.sourceObject = origin;
+}
 
 void
@@ -102,88 +56,26 @@
 }
 
-int SamplingPreprocessor::AddObjectSamples(Intersectable *obj, const Ray &ray)
-{
-	int contributingSamples = 0;
-	int j;
  
-	// object can be seen from the view cell => add to view cell pvs
-	/*for (j=0; j < ray.bspIntersections.size(); ++ j)
+int
+SamplingPreprocessor::CastRays(const RayContainer &rays, 
+							   int &sampleContributions, 
+							   int &contributingSamples)
 	{ 	
-		BspLeaf *leaf = ray.bspIntersections[j].mLeaf;
-		// if ray not in unbounded space
-		if (leaf->GetViewCell() != &mUnbounded)
-			contributingSamples += 
-				leaf->GetViewCell()->GetPvs().AddSample(obj);
-	}*/
+	// cast ray to KD tree to find intersection with other objects
+	RayContainer::const_iterator it, it_end = rays.end();
  
-	// rays passing through this viewcell
-	/*if (mPass > 1)
-		for (j=1; j < ((int)ray.bspIntersections.size() - 1); ++ j) 
-		{
-			BspLeaf *leaf = ray.bspIntersections[j].mLeaf;
-
-			if (leaf->GetViewCell() != &mUnbounded)
-				leaf->GetViewCell()->
-					AddPassingRay(ray, contributingSamples ? 1 : 0);
-		}
- */
-	return contributingSamples;
-}
-
+	for (it = rays.begin(); it != it_end; ++it)
+        mKdTree->CastRay((*it));
+
+	sampleContributions = mViewCellsManager->CastRays(rays);
+}
 
 int
-SamplingPreprocessor::CastRay(Intersectable *object, Ray &ray)
-{
-	int sampleContributions = 0;
-
-/*	long t1 = GetRealTime();
+SamplingPreprocessor::CastRay(const Ray &ray)
+{
 	// cast ray to KD tree to find intersection with other objects
 	mKdTree->CastRay(ray);
-	long t2 = GetRealTime();
-
-	if (0 && object && object->GetId() > 2197) {
-		object->Describe(cout)<<endl;
-		cout<<ray<<endl;
-	}
-
-	switch(ViewCell::sHierarchy)
-	{
-	case ViewCell::BSP:
-		
-		//-- cast ray to BSP tree to get intersection with view cells
-		if (!mBspTree)
-			break;
-		
-		mBspTree->CastRay(ray);
-			
-		if (object)
-			sampleContributions += AddObjectSamples(object, ray);
-			
-		if (!ray.intersections.empty()) // second intersection found
-		{
-			sampleContributions += 
-				AddObjectSamples(ray.intersections[0].mObject, ray);
-		}
-		break;
-	case ViewCell::KD:
-		if (ray.kdLeaves.size()) 
-		{
-			Intersectable *terminator =
-				ray.intersections.size() ? ray.intersections[0].mObject: NULL;
-
-			sampleContributions += AddNodeSamples(ray,
-																					object,
-																					terminator);
-		}
-		break;
-	case ViewCell::VSP:
-		// TODO:
-		break;
-	default:
-		Debug << "Should never come here" << endl;
-		break;
-	}
-*/
-	return sampleContributions;
+
+	return mViewCellsManager->CastRay(ray);
 }
 
@@ -265,10 +157,10 @@
 		Vector3 target = t*poly.mVertices[edge] + (1.0f-t)*poly.mVertices[(edge + 1)%
 																																		 poly.mVertices.size()];
-		SetupRay(ray, point, target - point, Ray::LOCAL_RAY);
+		SetupRay(ray, point, target - point, Ray::LOCAL_RAY, Ray::Intersection(0, object, 0));
 		if (!mesh->CastRay(ray, mi)) {
 			// the rays which intersect the mesh have been discarded since they are not tangent
 			// to the mesh
 			rays++;
-			edgeSamplesContributions += CastRay(object, ray);
+			edgeSamplesContributions += CastRay(ray);
 		}
 	}
@@ -347,12 +239,14 @@
 SamplingPreprocessor::ComputeVisibility()
 {
-  
   // pickup an object
   ObjectContainer objects;
   
+  /// rays per pass
+  RayContainer passRays;
+
   mSceneGraph->CollectObjects(&objects);
 
   Vector3 point, normal, direction;
-  Ray ray;
+  //Ray ray;
 
   long startTime = GetTime();
@@ -361,8 +255,5 @@
   int totalSamples = 0;
 
-  int pvsOut = Min((int)objects.size(), 10);
   int pvsSize = 0;
-
-  RayContainer rays[10];
 
   while (totalSamples < mTotalSamples) {
@@ -374,7 +265,4 @@
 		int reverseSamples = 0;
 		
-			
-		//cout << "totalSamples: "  << totalSamples << endl;
-
 		for (i = 0; i < objects.size(); i++) {
 						
@@ -383,7 +271,4 @@
 		
 			int pvsSize = 0;
-			//if (ViewCell::sHierarchy == ViewCell::KD)
-			//	pvsSize = object->mKdPvs.GetSize();
-						
 			
 			if (0 && pvsSize && mPass == 1000 ) {
@@ -394,5 +279,5 @@
 			
 			bool viewcellSample = true;
-			int sampleContributions;
+			//int sampleContributions;
 			bool debug = false; //(object->GetId() >= 2199);
 			if (viewcellSample) {
@@ -423,33 +308,23 @@
 					}
 					
+					Ray *ray = new Ray();
+
+					// the source object
+					Ray::Intersection source = 
+						Ray::Intersection(0, reverseSample ? NULL : object, faceIndex);
+					
 					// construct a ray
-					SetupRay(ray, point, direction, Ray::LOCAL_RAY);
-					
-					sampleContributions = CastRay(reverseSample ? NULL : object, ray);
+					SetupRay(*ray, point, direction, Ray::LOCAL_RAY, source);
+					passRays.push_back(ray);
 					
 					//-- CORR matt: put block inside loop
-					if (sampleContributions) {
+					/*if (sampleContributions) {
 						passContributingSamples ++;
 						passSampleContributions += sampleContributions;
-					}
-
-					if ( i < pvsOut ) {
-						Ray *nray = new Ray(ray);
-						rays[i].push_back(nray);
-					}
-		
-					if (!ray.intersections.empty()) {
-						// check whether we can add this to the rays
-						for (int j = 0; j < pvsOut; j++) {
-							if (objects[j] == ray.intersections[0].mObject) {
-								Ray *nray = new Ray(ray);
-								rays[j].push_back(nray);
-							}
-						}
-					}
+					}*/
+		
 					//-------------------
 					ProcessViewCells(ray,
-									 reverseSample ? NULL : object,
-									 faceIndex,
+									 objects,
 									 passContributingSamples,
 									 passSampleContributions);
@@ -465,4 +340,8 @@
 		}
 	
+		CastRays(passRays, passSampleContributions, passContributingSamples);
+		CLEAR_CONTAINER(passRays);
+		passRays.clear();
+
 		totalSamples += passSamples; 
 		
@@ -472,17 +351,6 @@
 		mPass++;
         
-		// TODO: move into view cell container
-		/*if (ViewCell::sHierarchy == ViewCell::KD)
-		{
-			pvsSize = 0;
-
-			for (i=0; i < objects.size(); i++) {
-				Intersectable *object = objects[i];
-				pvsSize += object->mKdPvs.GetSize();
-			}
-		}
-		else
 			pvsSize += passSampleContributions;
-		*/
+		
 		float avgRayContrib = (passContributingSamples > 0) ? 
 			passSampleContributions/(float)passContributingSamples : 0;
@@ -506,97 +374,5 @@
 	}
 	
-//	if (ViewCell::sHierarchy == ViewCell::KD)	
-		cout << "#totalKdPvsSize=" << mKdTree->CollectLeafPvs() << endl;
-  
-	//-- render simulation
-	cout << "\nevaluating bsp view cells render time before merge ... ";
-
-	SimulationStatistics ss = mViewCellsManager->SimulateRendering();
-
-	cout << " finished" << endl;
-	cout << ss << endl;
-	Debug << ss << endl;
-
-	if (mBspTree)
-	{
-		//-- post processing of bsp view cells
-        int vcSize = 0;
-		int pvsSize = 0;
-
-		Debug << "overall scene size: " << (int)objects.size() << endl;
-		
-		BspViewCellsStatistics stat;
-		mBspTree->EvaluateViewCellsStats(stat);
-		Debug << "original view cell partition:\n" << stat << endl;
-		
-		if (1) // export view cells
-		{
-			cout << "exporting initial view cells (=leaves) ... ";
-			Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
-			if (exporter)
-			{
-				exporter->SetWireframe();
-				exporter->ExportBspLeaves(*mBspTree, stat.maxPvs);
-				//exporter->ExportBspViewCellPartition(*mBspTree, 0);
-				
-				if (1)
-					ExportSceneGeometry(exporter, objects);
-					
-				delete exporter;
-			}
-			cout << "finished" << endl;
-		}
-
-		cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
-		
-		long startTime = GetTime();
-		int merged = PostprocessViewCells(mSampleRays);
-		
-		cout << "finished" << endl;
-		cout << "merged " << merged << " view cells in "
-			 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
-
-		//-- recount pvs
-		mBspTree->EvaluateViewCellsStats(stat);
-		
-		Debug << "after post processing:\n" << stat << endl;
-
-		//-- render simulation
-		cout << "\nevaluating render time after merge ... ";
-			
-		SimulationStatistics ss = mViewCellsManager->SimulateRendering();
-
-		cout << " finished" << endl;
-
-		cout << ss << endl;
-		Debug << ss << endl;
-
-		if (1) // export view cells
-		{
-			cout << "exporting view cells after merge ... ";
-			Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
-			if (exporter)
-			{
-				exporter->ExportBspViewCellPartition(*mBspTree, stat.maxPvs);
-				//exporter->ExportBspViewCellPartition(*mBspTree, 0);
-				delete exporter;
-			}
-
-			cout << "finished" << endl;
-		}
-
-		//-- visualization of the BSP splits
-		bool exportSplits = false;
-		environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
-		
-		cout << "exporting splits ... ";
-		if (exportSplits)
-	  		ExportSplits(objects, mSampleRays, mVisualizationSamples);
-		cout << "finished" << endl;
-
-		// export the PVS of sample view cells
-		if (1)
-			ExportBspPvs(objects, mSampleRays, mVisualizationSamples);
-	}
+	//cout << "#totalKdPvsSize=" << mKdTree->CollectLeafPvs() << endl;
 	
   //  HoleSamplingPass();
@@ -608,145 +384,20 @@
 	}
 
-	if (mVspKdTree)
-	{
-		if (1)
-		{
-			Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d"); 
-			//exporter->SetWireframe();
-			exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
-
-			Debug << "average PVS size: " << mVspKdTree->GetAvgPvsSize() << endl;
-
-			if (0) ExportSceneGeometry(exporter, objects);
-
-			bool exportRays = true;
-
-			if (exportRays) 
-			{
-				int raysSize = 2000;
-				float prob = raysSize / (float)mVspSampleRays.size();
-		
-				exporter->SetWireframe();
-			
-				VssRayContainer rays;
-				for (int i = 0; i < mVspSampleRays.size(); ++ i)
-				{
-					if (RandomValue(0,1) < prob)
-						rays.push_back(mVspSampleRays[i]);
-				}
-
-				exporter->ExportRays(rays, RgbColor(1, 0, 0));
-			}
-
-			delete exporter;
-		}
-
-		if (1)
-		{
-			vector<VspKdTreeLeaf *> leafContainer;
-
-			mVspKdTree->CollectLeaves(leafContainer);
-
-			for (int i = 0; i < 10; ++ i)
-			{
-				char s[64];
-				sprintf(s, "vsp_leaves%04d.x3d", i);
-				Exporter *exporter = Exporter::GetExporter(s);
-
-				// export geometry
-				VspKdTreeLeaf *leaf = leafContainer[Random((int)leafContainer.size())]; 
-				AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
-
-				Material m;
-				m.mDiffuseColor = RgbColor(0, 1, 1);
-				exporter->SetForcedMaterial(m);
-				exporter->SetWireframe();
-				exporter->ExportBox(box);
-
-				//-- export stored rays
-				VssRayContainer vssRays;
-				leaf->GetRays(vssRays);
-
-				VssRayContainer rays;
-
-				VssRayContainer::const_iterator it, it_end = vssRays.end();
-
-				for (it = vssRays.begin(); it != it_end; ++ it)
-				{
-					//if (!(*it)->mOriginObject && !(*it)->mTerminationObject)
-                        rays.push_back(*it);
-
-					//if (!(*it)->mOriginObject && !(*it)->mTerminationObject)
-					//	Debug << "ERR: " << (*it)->mOrigin << " " << (*it)->mTermination << endl;
-				}
-
-				exporter->ExportRays(rays, RgbColor(1, 0, 0));
-
-				//-- export stored PVS
-				ObjectContainer pvsObj;
-				leaf->ExtractPvs(pvsObj);
-				
-				ExportSceneGeometry(exporter, pvsObj);
-
-				delete exporter;
-			}			
-		}
-	}
-  
-	bool exportRays = false;
-	if (exportRays) {
-		Exporter *exporter = NULL;
-		exporter = Exporter::GetExporter("sample-rays.x3d");
-		exporter->SetWireframe();
-		exporter->ExportKdTree(*mKdTree);
-		exporter->ExportBspTree(*mBspTree);
-
-		for (i=0; i < pvsOut; i++) 
-			exporter->ExportRays(rays[i], 1000, RgbColor(1, 0, 0));
-		exporter->SetFilled();
-		
-		delete exporter;
-	}
+	//-- post process view cells
+	mViewCellsManager->PostProcess(objects, mSampleRays);
+		
 
 	//-- several visualizations and statistics
-	if (1) {
-
-   for (int k=0; k < pvsOut; k++) {
-		 Intersectable *object = objects[k];
-		 char s[64];
-		 sprintf(s, "sample-pvs%04d.x3d", k);
-		 Exporter *exporter = Exporter::GetExporter(s);
-		 exporter->SetWireframe();
 		 
+	//-- render simulation
+	cout << "\nevaluating bsp view cells render time before merge ... ";
 		 
-		 KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
-		 Intersectable::NewMail();
+	SimulationStatistics ss = mViewCellsManager->SimulateRendering();
 		 
-		 // avoid adding the object to the list
-		 object->Mail();
-		 ObjectContainer visibleObjects;
+	cout << " finished" << endl;
+	cout << ss << endl;
+	Debug << ss << endl;
 		 
-		 for (; i != object->mKdPvs.mEntries.end(); i++) 
-			 {
-				 KdNode *node = (*i).first;
-				 exporter->ExportBox(mKdTree->GetBox(node));
-				 mKdTree->CollectObjects(node, visibleObjects);
-			 }
-		 
-		 exporter->ExportRays(rays[k], 1000, RgbColor(0, 1, 0));
-		 exporter->SetFilled();
-		 
-		 for (int j = 0; j < visibleObjects.size(); j++)
-			 exporter->ExportIntersectable(visibleObjects[j]);
-		 
-		 
-		 Material m;
-		 m.mDiffuseColor = RgbColor(1, 0, 0);
-		 exporter->SetForcedMaterial(m);
-		 exporter->ExportIntersectable(object);
-		 
-		 delete exporter;
-	 }
-  }
+	mViewCellsManager->Visualize(objects, mSampleRays);	
   
   return true;
@@ -754,35 +405,18 @@
 
 void SamplingPreprocessor::ProcessViewCells(const Ray &ray,
-                                            Intersectable *object,
-											const int faceIndex,
+											const ObjectContainer &objects,
 											int &contributingSamples,
 											int &sampleContributions)
 {
-}
-/*
-void SamplingPreprocessor::ProcessVspViewCells(Ray &ray,
-                                               Intersectable *object,
-											   const int faceIndex,
-											   int &contributingSamples,
-											   int &sampleContributions)
-{
-	if (!mVspKdTree)
-	{
-		// store samples for vsp kd tree construction
-		if ((int)mVspSampleRays.size() < mVspConstructionSamples)
+	// save rays for view cells construction
+	if (!mViewCellsManager->ViewCellsConstructed())
 		{
-			if (!ray.intersections.empty())
-			{
-				ray.sourceObject = Ray::Intersection(0.0, object, faceIndex);
-				VssRay *sRay = new VssRay(ray);
-				mVspSampleRays.push_back(sRay);
-			}
-		}
+		if ((int)mSampleRays.size() < mViewCellsManager->GetConstructionSamples())
+			mVssSampleRays.push_back(new VssRay(ray));
 		else
 		{
-			// construct VSP tree using the collected samples
-			cout << "building VSP tree from " << (int)mVspSampleRays.size() << " samples " << endl;
-			mVspKdTree = new VspKdTree();
-			mVspKdTree->Construct(mVspSampleRays, &mKdTree->GetBox());
+			mViewCellsManager->Construct(objects, mVssSampleRays);
+			// construct view cells using the collected samples
+			cout << "building view cells from " << (int)mSampleRays.size() << " samples " << endl;
 		
 			// add contributions of saved samples to PVS
@@ -790,99 +424,13 @@
 			//sampleContributions += mBspTree->GetStat().sampleContributions;
 
-			Debug << mVspKdTree->GetStatistics();
-
-			// throw away samples because BSP leaves not stored in order 
-			// Need ordered rays for post processing => collect new rays
-			//CLEAR_CONTAINER(mVspSampleRays);
-		}
-	}
-}
-
-void SamplingPreprocessor::ProcessBspViewCells(const Ray &ray,
-                                               Intersectable *object,
-											   const int faceIndex,
-											   int &contributingSamples,
-											   int &sampleContributions)
-{
-	// save rays for bsp tree construction
-	if (!mBspTree)
-	{
-		if ((BspTree::sConstructionMethod == BspTree::FROM_SAMPLES) &&
-			((int)mSampleRays.size() < mBspConstructionSamples))
-		{
-			MeshInstance *mi = dynamic_cast<MeshInstance *>(object);
-			
-			Ray *sRay = new Ray(ray);
-			mSampleRays.push_back(sRay);
-		
-			// also add origin to sample
-			sRay->sourceObject = Ray::Intersection(0.0, object, faceIndex);
-		}
-		else
-		{
-			// construct BSP tree using the collected samples
-			cout << "building bsp tree from " << (int)mSampleRays.size() << " samples " << endl;
-			BuildBspTree();
-		
-			// add contributions of saved samples to PVS
-			contributingSamples += mBspTree->GetStat().contributingSamples;
-			sampleContributions += mBspTree->GetStat().sampleContributions;
-
-			BspTreeStatistics(Debug);
-
-			if (0) Export("vc_bsptree.x3d", false, false, true);
-
-			// throw away samples because BSP leaves not stored in order 
-			// Need ordered rays for post processing => collect new rays
-			CLEAR_CONTAINER(mSampleRays);
-		}
-	}
-	// save rays for post processing
-	else if (((int)mSampleRays.size() < mPostProcessSamples) ||
-			 ((int)mSampleRays.size() < mVisualizationSamples))
+			// throw away samples 
+			CLEAR_CONTAINER(mVssSampleRays);
+		}
+	}
+	// Need (ordered) rays for post processing => collect new rays
+	else if (((int)mSampleRays.size() < mViewCellsManager->GetPostProcessSamples()) ||
+			 ((int)mSampleRays.size() < mViewCellsManager->GetVisualizationSamples()))
 	{
 		mSampleRays.push_back(new Ray(ray));
 	}
 }
-*/
-// merge or subdivide view cells
-int SamplingPreprocessor::PostprocessViewCells(const RayContainer &rays)
-{
-	int merged = 0;
-
-	RayContainer::const_iterator rit, rit_end = rays.end();
-	vector<Ray::BspIntersection>::const_iterator iit;
-
-	int limit = min((int)mSampleRays.size(), mPostProcessSamples);
-
-	for (int i = 0; i < limit; ++ i)
-	{  
-		Ray *ray = mSampleRays[i];
-
-		// traverse leaves stored in the rays and compare and merge consecutive
-		// leaves (i.e., the neighbors in the tree)
-		if (ray->bspIntersections.size() < 2)
-			continue;
-
-		iit = ray->bspIntersections.begin();
-
-		BspLeaf *previousLeaf = (*iit).mLeaf;
-		++ iit;
-		
-		for (; iit != ray->bspIntersections.end(); ++ iit)
-		{
-			BspLeaf *leaf = (*iit).mLeaf;
-
-			if (mBspTree->ShouldMerge(leaf, previousLeaf))
-			{			
-				mBspTree->MergeViewCells(leaf, previousLeaf);
-
-				++ merged;
-			}
-		
-			previousLeaf = leaf;
-		}
-	}
-
-	return merged;
-}
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp	(revision 440)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp	(revision 440)
@@ -0,0 +1,1052 @@
+#include "ViewCellsManager.h"
+#include "RenderSimulator.h"
+#include "Mesh.h"
+#include "Triangle3.h"
+#include "ViewCell.h"
+#include "Environment.h"
+#include "X3dParser.h"
+#include "ViewCellBsp.h"
+#include "KdTree.h"
+#include "VspKdTree.h"
+#include "Exporter.h"
+
+
+
+
+ViewCellsManager::ViewCellsManager():
+mRenderSimulator(NULL),
+mConstructionSamples(0),
+mPostProcessSamples(0),
+mVisualizationSamples(0)
+{
+    mUnbounded = GenerateViewCell();
+}
+
+ViewCellsManager::ViewCellsManager(int constructionSamples):
+mConstructionSamples(constructionSamples),
+mRenderSimulator(NULL),
+mPostProcessSamples(0),
+mVisualizationSamples(0)
+{
+	mUnbounded = GenerateViewCell();
+}
+
+ViewCellsManager::~ViewCellsManager()
+{
+	DEL_PTR(mUnbounded);
+	DEL_PTR(mRenderSimulator);
+}
+
+void ViewCellsManager::InitRenderSimulator()
+{
+	float objRenderCost = 0, vcOverhead = 0, moveSpeed = 0;
+
+	environment->GetFloatValue("Simulation.objRenderCost",objRenderCost);
+	environment->GetFloatValue("Simulation.vcOverhead", vcOverhead);
+	environment->GetFloatValue("Simulation.moveSpeed", moveSpeed);
+
+	mRenderSimulator->SetObjectRenderCost(objRenderCost);
+	mRenderSimulator->SetVcOverhead(vcOverhead);
+	mRenderSimulator->SetMoveSpeed(moveSpeed);
+}
+
+bool ViewCellsManager::LoadViewCells(const string filename)
+{
+	X3dParser parser;
+	
+	environment->GetFloatValue("ViewCells.height", parser.mViewCellHeight);
+	
+	bool success = parser.ParseFile(filename, *this);
+	Debug << (int)mViewCells.size() << " view cells loaded" << endl;
+
+	return success;
+}
+
+int ViewCellsManager::CastRays(const RayContainer &rays)
+{
+	int sampleContributions = 0;
+
+	RayContainer::const_iterator it, it_end = rays.end();
+
+    for (it = rays.begin(); it != it_end; ++ it)
+		sampleContributions += CastRay(*(*it));
+
+	return sampleContributions;
+}
+
+void ViewCellsManager::AddViewCell(ViewCell *viewCell)
+{
+	mViewCells.push_back(viewCell);
+}
+
+void ViewCellsManager::DeriveViewCells(const ObjectContainer &objects, 
+									   ViewCellContainer &viewCells, 
+									   const int maxViewCells) const
+{
+	// maximal max viewcells
+	int limit = maxViewCells > 0 ? 
+		Min((int)objects.size(), maxViewCells) : (int)objects.size();
+
+	for (int i = 0; i < limit; ++ i)
+	{
+		Intersectable *object = objects[i];
+		
+		// extract the mesh instances
+		if (object->Type() == Intersectable::MESH_INSTANCE)
+		{
+			MeshInstance *inst = dynamic_cast<MeshInstance *>(object);
+
+			ViewCell *viewCell = GenerateViewCell(inst->GetMesh());
+			viewCells.push_back(viewCell);
+		}
+		//TODO: transformed meshes
+	}
+}
+
+ViewCell *ViewCellsManager::ExtrudeViewCell(const Triangle3 &baseTri, 
+											const float height) const
+{
+	// one mesh per view cell
+	Mesh *mesh = new Mesh();
+	
+	//-- construct prism
+
+	// bottom 
+	mesh->mFaces.push_back(new Face(2,1,0));
+	// top
+    mesh->mFaces.push_back(new Face(3,4,5));
+	// sides
+	mesh->mFaces.push_back(new Face(1, 4, 3, 0));
+	mesh->mFaces.push_back(new Face(2, 5, 4, 1));
+	mesh->mFaces.push_back(new Face(3, 5, 2, 0));
+
+	//--- extrude new vertices for top of prism
+	Vector3 triNorm = baseTri.GetNormal();
+
+	Triangle3 topTri;	
+
+	// add base vertices and calculate top vertices
+	for (int i = 0; i < 3; ++ i)
+		mesh->mVertices.push_back(baseTri.mVertices[i]);
+	
+	// add top vertices	
+	for (int i = 0; i < 3; ++ i)
+		mesh->mVertices.push_back(baseTri.mVertices[i] + height * triNorm);
+	
+	mesh->Preprocess();
+
+	return GenerateViewCell(mesh);
+}
+
+ViewCell *ViewCellsManager::Merge(ViewCell &front, ViewCell &back) const
+{
+	ViewCell *vc = GenerateViewCell();
+	// merge pvs
+	vc->GetPvs().Merge(front.GetPvs(), back.GetPvs());
+
+	// merge ray sets
+	stable_sort(front.mPiercingRays.begin(), front.mPiercingRays.end());
+	stable_sort(back.mPiercingRays.begin(), back.mPiercingRays.end());
+
+	std::merge(front.mPiercingRays.begin(), front.mPiercingRays.end(),
+			   back.mPiercingRays.begin(), back.mPiercingRays.end(), 
+			   vc->mPiercingRays.begin());
+
+	return vc;
+}
+
+SimulationStatistics ViewCellsManager::SimulateRendering() const
+{
+	return mRenderSimulator->SimulateRendering();
+}
+
+ViewCell *ViewCellsManager::GenerateViewCell(Mesh *mesh) const
+{
+	return new ViewCell(mesh);
+}
+
+
+void ViewCellsManager::SetVisualizationSamples(const int visSamples)
+{
+	int mVisualizationSamples = visSamples;
+}
+
+void ViewCellsManager::SetConstructionSamples(const int constructionSamples)
+{
+	mConstructionSamples = constructionSamples;
+}
+
+void ViewCellsManager::SetPostProcessSamples(const int postProcessSamples)
+{
+	mPostProcessSamples = postProcessSamples;
+}
+
+int ViewCellsManager::GetVisualizationSamples() const
+{
+	return mVisualizationSamples;
+}
+
+int ViewCellsManager::GetConstructionSamples() const
+{
+	return mConstructionSamples;
+}
+
+int ViewCellsManager::GetPostProcessSamples() const
+{
+	return mPostProcessSamples;
+}
+
+/**********************************************************************/
+/*                   BspViewCellsManager implementation               */
+/**********************************************************************/
+
+BspViewCellsManager::BspViewCellsManager(BspTree *bspTree, int constructionSamples):
+ViewCellsManager(constructionSamples), 
+mBspTree(bspTree)
+{
+   mRenderSimulator = new BspRenderSimulator(bspTree);
+   InitRenderSimulator();
+}
+
+bool BspViewCellsManager::ViewCellsConstructed() const
+{
+	return mBspTree->GetRoot() != NULL;
+}
+
+ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
+{
+	return new BspViewCell(mesh);
+}
+
+int BspViewCellsManager::Construct(const ObjectContainer &objects, 
+								   const VssRayContainer &rays,
+								   AxisAlignedBox3 *sceneBbox)
+{
+	if (ViewCellsConstructed())
+		return 0;
+
+	int sampleContributions = 0;
+	
+	RayContainer sampleRays;
+
+	int limit = min (mConstructionSamples, (int)rays.size());
+
+    for (int i = 0; i < limit; ++ i)
+		sampleRays.push_back(new Ray(*rays[i]));
+
+	mBspTree->Construct(objects, sampleRays);
+	
+	Debug << mBspTree->GetStatistics() << endl;
+	CLEAR_CONTAINER(sampleRays);
+
+	return sampleContributions;
+}
+
+int BspViewCellsManager::CastRay(Ray &ray)
+{
+	mBspTree->CastRay(ray);
+	
+	//if (mBspTree->bspIntersections.empty()) return 0;
+
+	Intersectable *term = 
+		!ray.intersections.empty() ? ray.intersections[0].mObject : NULL;
+
+	return AddSampleContributions(ray, ray.sourceObject.mObject, term);
+}
+
+int BspViewCellsManager::PostProcess(const ObjectContainer &objects, 
+									 const RayContainer &rays)
+{
+	//-- post processing of bsp view cells
+    int vcSize = 0;
+	int pvsSize = 0;
+
+	BspViewCellsStatistics stat;
+	mBspTree->EvaluateViewCellsStats(stat);
+	Debug << "original view cell partition:\n" << stat << endl;
+		
+	if (1) // export view cells
+	{
+		cout << "exporting initial view cells (=leaves) ... ";
+		Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
+	
+		if (exporter)
+		{
+			exporter->SetWireframe();
+			exporter->ExportBspLeaves(*mBspTree, stat.maxPvs);
+			//exporter->ExportBspViewCellPartition(*mBspTree, 0);
+				
+			if (1)
+			{
+				Material m;//= RandomMaterial();
+				m.mDiffuseColor = RgbColor(0, 1, 0);
+				exporter->SetForcedMaterial(m);
+				exporter->SetWireframe();
+
+				exporter->ExportGeometry(objects);
+			}
+
+			delete exporter;
+		}
+		cout << "finished" << endl;
+	}
+
+	cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
+		
+	long startTime = GetTime();
+
+
+	//-- merge or subdivide view cells
+	int merged = 0;
+
+	RayContainer::const_iterator rit, rit_end = rays.end();
+	vector<Ray::BspIntersection>::const_iterator iit;
+
+	int limit = min((int)rays.size(), mPostProcessSamples);
+
+	for (int i = 0; i < limit; ++ i)
+	{  
+		Ray *ray = rays[i];
+
+		// traverse leaves stored in the rays and compare and merge consecutive
+		// leaves (i.e., the neighbors in the tree)
+		if (ray->bspIntersections.size() < 2)
+			continue;
+
+		iit = ray->bspIntersections.begin();
+
+		BspLeaf *previousLeaf = (*iit).mLeaf;
+		++ iit;
+		
+		for (; iit != ray->bspIntersections.end(); ++ iit)
+		{
+			BspLeaf *leaf = (*iit).mLeaf;
+
+			if (mBspTree->ShouldMerge(leaf, previousLeaf))
+			{			
+				mBspTree->MergeViewCells(leaf, previousLeaf);
+
+				++ merged;
+			}
+		
+			previousLeaf = leaf;
+		}
+	}
+
+	//-- stats and visualizations
+	cout << "finished" << endl;
+	cout << "merged " << merged << " view cells in "
+		 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
+
+	return merged;
+}
+
+int BspViewCellsManager::GetType() const
+{
+	return BSP;
+}
+
+int BspViewCellsManager::AddSampleContributions(const Ray &ray,
+												Intersectable *sObject,
+												Intersectable *tObject)
+{
+	int contributingSamples = 0;
+	
+	// rays passing through this viewcell
+	if (0)
+		for (int j = 1; j < ((int)ray.bspIntersections.size() - 1); ++ j) 
+		{
+			BspLeaf *leaf = ray.bspIntersections[j].mLeaf;
+
+			if (leaf->GetViewCell() != mUnbounded)
+				leaf->GetViewCell()->
+					AddPassingRay(ray, contributingSamples ? 1 : 0);
+		}
+
+	if (!sObject && !tObject)
+		return 0;
+
+	// object can be seen from the view cell => add to view cell pvs
+	for (int j = 0; j < (int)ray.bspIntersections.size(); ++ j)
+	{ 	
+		BspLeaf *leaf = ray.bspIntersections[j].mLeaf;
+		
+		// if ray not in unbounded space
+		if (leaf->GetViewCell() != mUnbounded)
+		{
+			if (sObject)
+			{
+				contributingSamples += 
+					leaf->GetViewCell()->GetPvs().AddSample(sObject);
+			}
+
+			if (tObject)
+			{
+				contributingSamples += 
+					leaf->GetViewCell()->GetPvs().AddSample(tObject);
+			}
+		}
+	}
+ 
+	return contributingSamples;
+}
+
+
+void BspViewCellsManager::Visualize(const ObjectContainer &objects,
+									const RayContainer &sampleRays)
+{
+	//-- recount pvs
+	BspViewCellsStatistics vcStats;
+	mBspTree->EvaluateViewCellsStats(vcStats);
+
+	if (1) // export view cells
+	{
+		cout << "exporting view cells after merge ... ";
+		Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
+
+		if (exporter)
+		{
+			exporter->ExportBspViewCellPartition(*mBspTree, vcStats.maxPvs);
+			//exporter->ExportBspViewCellPartition(*mBspTree, 0);
+			delete exporter;
+		}
+
+		cout << "finished" << endl;
+	}	
+
+	//-- visualization of the BSP splits
+	bool exportSplits = false;
+		environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
+	
+	if (exportSplits)
+	{
+		cout << "exporting splits ... ";
+	 	ExportSplits(objects, sampleRays);
+		cout << "finished" << endl;
+	}
+
+	ExportBspPvs(objects, sampleRays);
+}
+
+
+inline bool vc_gt(ViewCell *a, ViewCell *b) 
+{ 
+	return a->GetPvs().GetSize() > b->GetPvs().GetSize();
+}
+
+void BspViewCellsManager::ExportSplits(const ObjectContainer &objects,
+									   const RayContainer &sampleRays)
+{
+	Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
+
+	if (exporter) 
+	{	
+		Material m; 
+		m.mDiffuseColor = RgbColor(1, 0, 0);
+		exporter->SetForcedMaterial(m);
+		exporter->SetWireframe();
+		exporter->ExportBspSplits(*mBspTree, true);
+
+		// take forced material, else big scenes cannot be viewed
+		m.mDiffuseColor = RgbColor(0, 1, 0);
+		exporter->SetForcedMaterial(m);
+		exporter->SetFilled();
+
+		exporter->ResetForcedMaterial();
+		
+		// export rays
+		if (0)
+		{
+			RayContainer outRays;
+		
+			int raysSize = min((int)sampleRays.size(), mVisualizationSamples);
+
+			for (int i = 0; i < raysSize; ++ i)
+			{
+				// only rays piercing geometry
+				if (!sampleRays[i]->intersections.empty())
+					outRays.push_back(sampleRays[i]);
+			}
+			
+			// export rays 
+			exporter->ExportRays(outRays, 1000, RgbColor(1, 1, 0));
+		}
+
+		if (1)
+			exporter->ExportGeometry(objects);
+
+		delete exporter;
+	}
+}
+
+void BspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
+									   const RayContainer &sampleRays)
+{
+	const int leafOut = 10;
+	
+	ViewCell::NewMail();
+
+	//-- some rays for output
+	const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
+	cout << "visualization using " << mVisualizationSamples << " samples" << endl;
+	vector<Ray *> vcRays[leafOut];
+
+	if (0)
+	{
+		//-- some random view cells and rays for output
+		vector<BspLeaf *> bspLeaves;
+
+		for (int i = 0; i < leafOut; ++ i)
+			bspLeaves.push_back(mBspTree->GetRandomLeaf());	
+		
+		for (int i = 0; i < bspLeaves.size(); ++ i)
+		{
+			cout << "creating output for view cell " << i << " ... ";
+			// check whether we can add the current ray to the output rays
+			for (int k = 0; k < raysOut; ++ k) 
+			{
+				Ray *ray = sampleRays[k];
+
+				for	(int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
+				{
+					BspLeaf *leaf = ray->bspIntersections[j].mLeaf;
+
+					if (bspLeaves[i]->GetViewCell() == leaf->GetViewCell()) 
+					{
+						vcRays[i].push_back(ray);
+					}
+				}
+			}
+
+			Intersectable::NewMail();
+
+			BspViewCell *vc = dynamic_cast<BspViewCell *>(bspLeaves[i]->GetViewCell());
+
+			//bspLeaves[j]->Mail();
+			char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
+
+			Exporter *exporter = Exporter::GetExporter(s);
+			exporter->SetFilled();
+
+			ViewCellPvsMap::iterator it = vc->GetPvs().mEntries.begin();
+
+			exporter->SetWireframe();
+			//exporter->SetFilled();
+
+			Material m;//= RandomMaterial();
+			m.mDiffuseColor = RgbColor(0, 1, 0);
+			exporter->SetForcedMaterial(m);
+
+			if (vc->GetMesh())
+				exporter->ExportViewCell(vc);
+			else
+			{
+				PolygonContainer cell;
+				// export view cell geometry
+				mBspTree->ConstructGeometry(vc, cell);
+				exporter->ExportPolygons(cell);
+				CLEAR_CONTAINER(cell);
+			}
+
+			Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize() 
+					<< ", piercing rays=" << (int)vcRays[i].size() << endl;
+
+			// export rays piercing this view cell
+			exporter->ExportRays(vcRays[i], 1000, RgbColor(0, 1, 0));
+
+			m.mDiffuseColor = RgbColor(1, 0, 0);
+			exporter->SetForcedMaterial(m);
+
+			// exporter->SetWireframe();
+			exporter->SetFilled();
+
+			// output PVS of view cell
+			for (; it != vc->GetPvs().mEntries.end(); ++ it) 
+			{
+				Intersectable *intersect = (*it).first;
+				if (!intersect->Mailed())
+				{
+					exporter->ExportIntersectable(intersect);
+					intersect->Mail();
+				}			
+			}
+				
+			// output rest of the objects
+			if (0)
+			{
+				Material m;//= RandomMaterial();
+				m.mDiffuseColor = RgbColor(0, 0, 1);
+				exporter->SetForcedMaterial(m);
+
+				for (int j = 0; j < objects.size(); ++ j)
+					if (!objects[j]->Mailed())
+					{
+						exporter->SetForcedMaterial(m);
+						exporter->ExportIntersectable(objects[j]);
+						objects[j]->Mail();
+					}
+			}
+			DEL_PTR(exporter);
+			cout << "finished" << endl;
+		}
+	}
+	else
+	{
+		ViewCellContainer viewCells;
+
+		mBspTree->CollectViewCells(viewCells);
+		stable_sort(viewCells.begin(), viewCells.end(), vc_gt);
+
+		int limit = min(leafOut, (int)viewCells.size()); 
+		
+		for (int i = 0; i < limit; ++ i)
+		{
+			cout << "creating output for view cell " << i << " ... ";
+			
+            Intersectable::NewMail();
+			BspViewCell *vc = dynamic_cast<BspViewCell *>(viewCells[i]);
+
+			cout << "creating output for view cell " << i << " ... ";
+			// check whether we can add the current ray to the output rays
+			for (int k = 0; k < raysOut; ++ k) 
+			{
+				Ray *ray = sampleRays[k];
+
+				for	(int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
+				{
+					BspLeaf *leaf = ray->bspIntersections[j].mLeaf;
+
+					if (vc == leaf->GetViewCell()) 
+					{
+						vcRays[i].push_back(ray);
+					}
+				}
+			}
+
+			//bspLeaves[j]->Mail();
+			char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
+
+			Exporter *exporter = Exporter::GetExporter(s);
+			
+			exporter->SetWireframe();
+
+			Material m;//= RandomMaterial();
+			m.mDiffuseColor = RgbColor(0, 1, 0);
+			exporter->SetForcedMaterial(m);
+
+			if (vc->GetMesh())
+				exporter->ExportViewCell(vc);
+			else
+			{
+				PolygonContainer cell;
+				// export view cell
+				mBspTree->ConstructGeometry(vc, cell);
+				exporter->ExportPolygons(cell);
+				CLEAR_CONTAINER(cell);
+			}
+
+			
+			Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize() 
+					<< ", piercing rays=" << (int)vcRays[i].size() << endl;
+
+			
+			// export rays piercing this view cell
+			exporter->ExportRays(vcRays[i], 1000, RgbColor(0, 1, 0));
+	
+			m.mDiffuseColor = RgbColor(1, 0, 0);
+			exporter->SetForcedMaterial(m);
+
+			ViewCellPvsMap::const_iterator it,
+				it_end = vc->GetPvs().mEntries.end();
+
+			// output PVS of view cell
+			for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it) 
+			{
+				Intersectable *intersect = (*it).first;
+				if (!intersect->Mailed())
+				{
+					Material m = RandomMaterial();
+			
+					exporter->SetForcedMaterial(m);
+
+					exporter->ExportIntersectable(intersect);
+					intersect->Mail();
+				}			
+			}
+				
+			DEL_PTR(exporter);
+			cout << "finished" << endl;
+		}
+	}
+}
+
+/**********************************************************************/
+/*                   KdViewCellsManager implementation               */
+/**********************************************************************/
+
+KdViewCellsManager::KdViewCellsManager(KdTree *kdTree):
+ViewCellsManager(), 
+mKdTree(kdTree), 
+mKdPvsDepth(100)
+{
+   mRenderSimulator = new KdRenderSimulator(mKdTree);
+   InitRenderSimulator();
+}
+
+int KdViewCellsManager::Construct(const ObjectContainer &objects, 
+								  const VssRayContainer &rays,
+								  AxisAlignedBox3 *sceneBbox)
+{
+	if (ViewCellsConstructed())
+		return 0;
+	
+	mKdTree->Construct();
+
+	return 0;
+}
+
+bool KdViewCellsManager::ViewCellsConstructed() const
+{
+	return mKdTree->GetRoot() != NULL;
+}
+
+int KdViewCellsManager::PostProcess(const ObjectContainer &objects, 
+									const RayContainer &rays)
+{
+	return 0;
+}
+
+void KdViewCellsManager::Visualize(const ObjectContainer &objects,
+								   const RayContainer &sampleRays)
+{
+	const int pvsOut = min((int)objects.size(), 10);
+
+	int limit = min(mVisualizationSamples, (int)sampleRays.size());
+
+	RayContainer *rays = new RayContainer[pvsOut];
+
+	for  (int i = 0; i < limit; ++ i)
+	{
+		Ray *ray = sampleRays[i];
+
+		if (!ray->intersections.empty()) 
+		{
+			// check whether we can add this to the rays
+			for (int j = 0; j < pvsOut; j++) 
+			{
+				if (objects[j] == ray->intersections[0].mObject) 
+				{
+					rays[j].push_back(ray);
+				}
+			}
+		}
+	}
+
+	bool exportRays = false;
+	if (exportRays) {
+		Exporter *exporter = NULL;
+		exporter = Exporter::GetExporter("sample-rays.x3d");
+		exporter->SetWireframe();
+		exporter->ExportKdTree(*mKdTree);
+		
+		for (i=0; i < pvsOut; i++) 
+			exporter->ExportRays(rays[i], 1000, RgbColor(1, 0, 0));
+		exporter->SetFilled();
+		
+		delete exporter;
+	}
+
+	for (int k=0; k < pvsOut; k++) 
+	{
+		Intersectable *object = objects[k];
+		char s[64];	
+		sprintf(s, "sample-pvs%04d.x3d", k);
+
+		Exporter *exporter = Exporter::GetExporter(s);
+		exporter->SetWireframe();
+	 
+        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
+		Intersectable::NewMail();
+			
+		// avoid adding the object to the list
+		object->Mail();
+		ObjectContainer visibleObjects;
+            
+		for (; i != object->mKdPvs.mEntries.end(); i++) 
+		{
+			 KdNode *node = (*i).first;
+			 exporter->ExportBox(mKdTree->GetBox(node));
+			 mKdTree->CollectObjects(node, visibleObjects);
+		}
+
+		exporter->ExportRays(rays[k], 1000, RgbColor(0, 1, 0));
+		exporter->SetFilled();
+		 
+		for (int j = 0; j < visibleObjects.size(); j++)
+			exporter->ExportIntersectable(visibleObjects[j]);
+		 
+		Material m;
+		m.mDiffuseColor = RgbColor(1, 0, 0);
+		exporter->SetForcedMaterial(m);
+		exporter->ExportIntersectable(object);
+	 
+		delete exporter;
+	}
+	DEL_PTR(rays);
+}
+
+int KdViewCellsManager::GetType() const
+{
+	return ViewCellsManager::KD;
+}
+
+int KdViewCellsManager::CastRay(const Ray &ray)
+{
+	if (ray.kdLeaves.empty()) 
+		return 0;
+
+	Intersectable *terminator =
+		!ray.intersections.empty() ? ray.intersections[0].mObject : NULL;
+
+	return AddSampleContributions(ray, ray.sourceObject.mObject, terminator);
+}
+
+int KdViewCellsManager::AddSampleContributions(const Ray &ray,
+											   Intersectable *sObject,
+											   Intersectable *tObject)
+{
+	int contributingSamples = 0;
+	
+	int objects = 0;
+
+	if (sObject)
+		objects++;
+	if (tObject)
+		objects++;
+
+	for (int j = 1; j < ((int)ray.kdLeaves.size() - 1); ++ j) 
+	{
+		ray.kdLeaves[j]->AddPassingRay2(ray, objects,
+										(int)ray.kdLeaves.size());
+	}
+
+	if (!objects)
+		return 0;
+	
+	for (int j=0; j < ray.kdLeaves.size(); j++) 
+	{
+		KdNode *node = GetNodeForPvs(ray.kdLeaves[j]);
+
+		if (sObject)
+			contributingSamples += sObject->mKdPvs.AddSample(node);
+		if (tObject)
+			contributingSamples += tObject->mKdPvs.AddSample(node);
+	}
+		
+	return contributingSamples;
+}
+
+KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
+{
+	KdNode *node = leaf;
+
+	while (node->mParent && node->mDepth > mKdPvsDepth)
+		node = node->mParent;
+	return node;
+}
+
+
+
+/**********************************************************************/
+/*                   VspKdViewCellsManager implementation             */
+/**********************************************************************/
+
+VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree, int constructionSamples):
+ViewCellsManager(constructionSamples), 
+mVspKdTree(vspKdTree)
+{
+   mRenderSimulator = NULL; // TODO: new VspKdRenderSimulator(vspKdTree);
+   InitRenderSimulator();
+}
+
+int VspKdViewCellsManager::Construct(const ObjectContainer &objects, 
+									 const VssRayContainer &rays,
+									 AxisAlignedBox3 *sceneBbox)
+{
+	if (ViewCellsConstructed())
+		return 0;
+
+	mVspKdTree->Construct(rays, sceneBbox);
+	return 0;
+}
+
+bool VspKdViewCellsManager::ViewCellsConstructed() const
+{
+	return mVspKdTree->GetRoot() != NULL;
+}
+
+int VspKdViewCellsManager::CastRay(const Ray &rays)
+{
+	int sampleContributions = 0;
+/*
+    for (int i = 0; i < (int)rays.size(); ++ i)
+	{
+		Ray *ray = rays[i];
+
+		mBspTree->CastRay(*ray);
+			
+		Intersectable *term = 
+			!ray->intersections.empty() ? ray->intersections[0].mObject : NULL
+			;
+		sampleContributions += 
+			AddSampleContributions(*ray, ray->sourceObject.mObject, term);
+			
+	}
+*/
+	return sampleContributions;
+}
+
+int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects, 
+									   const RayContainer &rays)
+{
+	return 0;
+}
+
+void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
+									  const RayContainer &sampleRays)
+{
+	if (1)
+	{
+		Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d"); 
+		//exporter->SetWireframe();
+		exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
+
+		Debug << "average PVS size: " << mVspKdTree->GetAvgPvsSize() << endl;
+
+		if (0) 
+			exporter->ExportGeometry(objects);
+
+		bool exportRays = true;
+
+		if (exportRays) 
+		{
+			int raysSize = 2000;
+			float prob = raysSize / (float)sampleRays.size();
+		
+			exporter->SetWireframe();
+			
+			RayContainer rays;
+		
+			for (int i = 0; i < sampleRays.size(); ++ i)
+			{
+				if (RandomValue(0,1) < prob)
+					rays.push_back(sampleRays[i]);
+			}
+
+			exporter->ExportRays(rays, 1000, RgbColor(1, 0, 0));
+		}
+
+		delete exporter;
+	}
+
+	if (1)
+	{
+		vector<VspKdTreeLeaf *> leafContainer;
+
+		mVspKdTree->CollectLeaves(leafContainer);
+
+		for (int i = 0; i < 10; ++ i)
+		{
+			char s[64];
+			sprintf(s, "vsp_leaves%04d.x3d", i);
+			Exporter *exporter = Exporter::GetExporter(s);
+
+			// export geometry
+			VspKdTreeLeaf *leaf = leafContainer[Random((int)leafContainer.size())]; 
+			AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
+
+			Material m;
+			m.mDiffuseColor = RgbColor(0, 1, 1);
+			exporter->SetForcedMaterial(m);
+			exporter->SetWireframe();
+			exporter->ExportBox(box);
+
+			//-- export stored rays
+			VssRayContainer vssRays;
+			leaf->GetRays(vssRays);
+
+			VssRayContainer rays;
+			VssRayContainer::const_iterator it, it_end = vssRays.end();
+
+			for (it = vssRays.begin(); it != it_end; ++ it)
+			{
+				//if (!(*it)->mOriginObject && !(*it)->mTerminationObject)
+					rays.push_back(*it);
+
+				//if (!(*it)->mOriginObject && !(*it)->mTerminationObject)
+				//	Debug << "ERR: " << (*it)->mOrigin << " " << (*it)->mTermination << endl;
+			}
+
+			exporter->ExportRays(rays, RgbColor(1, 0, 0));
+
+			//-- export stored PVS
+			
+			ObjectContainer pvsObj;
+			leaf->ExtractPvs(pvsObj);
+				
+			exporter->ExportGeometry(pvsObj);
+
+			delete exporter;
+		}			
+	}
+}
+
+int VspKdViewCellsManager::GetType() const
+{
+	return VSP_KD;
+}
+
+int VspKdViewCellsManager::AddSampleContributions(const Ray &ray,
+												Intersectable *sObject,
+												Intersectable *tObject)
+{
+	int contributingSamples = 0;
+	/*
+	// rays passing through this viewcell
+	if (0)
+		for (int j = 1; j < ((int)ray.bspIntersections.size() - 1); ++ j) 
+		{
+			BspLeaf *leaf = ray.bspIntersections[j].mLeaf;
+
+			if (leaf->GetViewCell() != mUnbounded)
+				leaf->GetViewCell()->
+					AddPassingRay(ray, contributingSamples ? 1 : 0);
+		}
+
+	if (!sObject && !tObject)
+		return 0;
+	
+	// object can be seen from the view cell => add to view cell pvs
+	for (j=0; j < (int)ray.bspIntersections.size(); ++ j)
+	{ 	
+		BspLeaf *leaf = ray.bspIntersections[j].mLeaf;
+		
+		// if ray not in unbounded space
+		if (leaf->GetViewCell() != mUnbounded)
+		{
+			if (sObject)
+			{
+				contributingSamples += 
+					leaf->GetViewCell()->GetPvs().AddSample(sObject);
+			}
+
+			if (tObject)
+			{
+				contributingSamples += 
+					leaf->GetViewCell()->GetPvs().AddSample(tObject);
+			}
+		}
+	}
+ */
+	return contributingSamples;
+}
