Index: /trunk/VUT/GtpVisibilityPreprocessor/scripts/Preprocessor.vcproj
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/scripts/Preprocessor.vcproj	(revision 498)
+++ /trunk/VUT/GtpVisibilityPreprocessor/scripts/Preprocessor.vcproj	(revision 508)
@@ -156,5 +156,6 @@
 						Name="VCCustomBuildTool"
 						Description="Performing moc on $(InputName).h"
-						CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp"
+						CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp
+"
 						Outputs="$(InputDir)moc_$(InputName).cpp"/>
 				</FileConfiguration>
@@ -225,4 +226,7 @@
 			<File
 				RelativePath="..\src\Parser.h">
+			</File>
+			<File
+				RelativePath="..\src\Plane3.cpp">
 			</File>
 			<File
@@ -251,5 +255,6 @@
 						Name="VCCustomBuildTool"
 						Description="Performing moc on $(InputName).h"
-						CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp"
+						CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp
+"
 						Outputs="$(InputDir)moc_$(InputName).cpp"/>
 				</FileConfiguration>
@@ -265,5 +270,6 @@
 						Name="VCCustomBuildTool"
 						Description="Performing moc on $(InputName).h"
-						CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp"
+						CommandLine="%qtdir%\bin\moc.exe $(InputDir)$(InputName).h -o $(InputDir)moc_$(InputName).cpp
+"
 						Outputs="$(InputDir)moc_$(InputName).cpp"/>
 				</FileConfiguration>
@@ -367,4 +373,13 @@
 			<File
 				RelativePath="..\src\ViewCellsManager.h">
+			</File>
+			<File
+				RelativePath="..\src\ViewCellsParser.cpp">
+			</File>
+			<File
+				RelativePath="..\src\ViewCellsParser.h">
+			</File>
+			<File
+				RelativePath="..\src\ViewCellsParserXerces.h">
 			</File>
 			<File
Index: /trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env	(revision 503)
+++ /trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env	(revision 508)
@@ -15,5 +15,5 @@
 	filename ../data/atlanta/atlanta2.x3d
 #	filename ../data/soda/soda.dat
-#	filename ../data/soda/soda5.dat
+	filename ../data/soda/soda5.dat
 }
 
@@ -21,5 +21,5 @@
 	# stored sample rays
 	samplesFilename rays.out
-	useGlRenderer true
+	useGlRenderer false
 #	type sampling
 	type vss
@@ -28,11 +28,18 @@
 
 VssPreprocessor {
-	samplesPerPass  100000
-	initialSamples 500000
-	vssSamples 2000000
+	samplesPerPass  500000
+	initialSamples 200000
+	vssSamples 200000
 	vssSamplesPerPass 100000
 	useImportanceSampling true
 	loadInitialSamples  false
 	storeInitialSamples false
+	useViewSpaceBox true
+}
+
+
+SamplingPreprocessor {
+	totalSamples 500000
+	samplesPerPass  3
 }
 
@@ -160,11 +167,8 @@
 
 
-Sampling {
-	totalSamples 300000
-	samplesPerPass  3
-}
 
 ViewCells {
 	loadFromFile false
+	exportToFile true
 	#type kdTree
 	#type vspKdTree
@@ -176,7 +180,6 @@
 	height 5.0
 	maxViewCells 500
-	maxPvs 200
-	
-	
+	maxPvs 500
+		
 	PostProcess {
 		# how much samples are used for post processing
@@ -192,5 +195,5 @@
 		colorCode Random
 		exportRays false
-		exportGeometry false
+		exportGeometry true
 	}
 	
@@ -199,4 +202,5 @@
 #	filename ../data/vienna/viewcells-25.x3d
 #	filename ../data/vienna/viewcells-large-sel.x3d
+	filename ../scripts/viewcells.xml
 }
 
@@ -220,9 +224,9 @@
 		maxDepth	 	40
 		minPvs			50
-		minRays			300
+		minRays			700
 		minSize			0.001
 		maxCostRatio		0.9
 		missTolerance		4
-		maxRayContribution 	0.5
+		maxRayContribution 	0.05
 	}
 	
@@ -260,6 +264,6 @@
 	# balanced rays        = 512
 	# pvs                  = 1024
-
-	splitPlaneStrategy 1024
+	
+	splitPlaneStrategy 1026
 	
 	# maximal candidates for split planes
@@ -268,5 +272,5 @@
 	
 	# maximal tested rays for split cost heuristics
-	maxTests 2000
+	maxTests 10000
 	
 	# factors for evaluating split plane costs
@@ -279,19 +283,24 @@
 	Termination {
 		# parameters used for autopartition
-		minRays 		200
+		minRays 		500
 		minPolygons 		-1
 		maxDepth		30
 		minPvs 			20
-		#minArea 		0.0001
-		minArea 		0.000
-		maxRayContribution	0.05
-		maxCostRatio		0.9
+		minArea 		0.0001
+		#minArea 		0.000
+		maxRayContribution	0.5
+		maxCostRatio		0.95
 		missTolerance		5
 		#maxAccRayLength	100
 		
-		maxViewCells		20000
+		maxViewCells		200000
 		
 		# used for pvs criterium
 		ct_div_ci 0.0
+		
+		AxisAligned {
+			minRays 		2000
+			maxRayContribution	0.5
+		}
 	}
 	
@@ -305,5 +314,5 @@
 	PostProcess {
 		maxCostRatio 0.1
-		minViewCells 500
+		minViewCells 200
 		maxPvsSize   1000
 		useRaysForMerge true
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h	(revision 503)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h	(revision 508)
@@ -34,4 +34,6 @@
 class VspBspTree 
 {
+	friend class ViewCellsParseHandlers;
+
 public:
 	
@@ -180,8 +182,4 @@
 	BspNode *GetRoot() const;
 
-	/** Exports VspBsp tree to file.
-	*/
-	bool Export(const string filename);
-
 	/** Collects the leaf view cells of the tree
 		@param viewCells returns the view cells 
@@ -279,16 +277,12 @@
 	bool ViewPointValid(const Vector3 &viewPoint) const;
 
-	/** Returns the view cell corresponding to 
-		the space outside the valid view space.
-	*/
-	BspViewCell *GetOutOfBoundsCell() const;
-
-	/** Writes tree to disc.
-	*/
-	bool WriteVspBspTree();
-
-	/** Loads tree from disc.
-	*/
-	bool LoadVspBspTree();
+	/** Returns view cell corresponding to 
+		the invalid view space.
+	*/
+	BspViewCell *GetOutOfBoundsCell();
+
+	/** Writes tree to output stream
+	*/
+	bool Export(ofstream &stream);
 
 protected:
@@ -321,4 +315,9 @@
 	};
 
+	/** Returns view cell corresponding to 
+		the invalid view space. If it does not exist, it is created.
+	*/
+	BspViewCell *GetOrCreateOutOfBoundsCell();
+
 	/** Collapses the tree with respect to the view cell partition,
 		i.e. leaves having the same view cell are collapsed.
@@ -329,4 +328,5 @@
 	*/
 	BspNode *CollapseTree(BspNode *node, int &collapsed);
+
 	/** Shuffles the leaves, i.e., tests if exchanging
 		the leaves helps in improving the view cells.
@@ -367,5 +367,7 @@
 	bool SelectPlane(Plane3 &plane, 
 					 BspLeaf *leaf, 
-					 VspBspTraversalData &data);
+					 VspBspTraversalData &data,
+					 VspBspTraversalData &frontData,
+					 VspBspTraversalData &backData);
 	
 	/** Strategies where the effect of the split plane is tested
@@ -375,6 +377,9 @@
 	*/
 	float SplitPlaneCost(const Plane3 &candidatePlane, 
-						 const VspBspTraversalData &data) const;
-
+						 const VspBspTraversalData &data,
+						 BspNodeGeometry &geomFront,
+						 BspNodeGeometry &geomBack,
+						 float &areaFront,
+						 float &areaBack) const;
 
 	/** Subdivide leaf.
@@ -397,17 +402,4 @@
 						   PolygonContainer &coincident);
 
-	/** Selects the split plane in order to construct a tree with
-		certain characteristics (e.g., balanced tree, least splits, 
-		2.5d aligned)
-		@param bestPlane returns the split plane
-		@param polygons container of polygons
-		@param rays bundle of rays on which the split can be based
-
-		@returns true if the overall cost is under maxCostRatio
-	*/
-	bool SelectPlaneHeuristics(Plane3 &bestPlane, 
-							   BspLeaf *leaf, 
-							   VspBspTraversalData &data);
-
 	/** Extracts the meshes of the objects and adds them to polygons. 
 		Adds object aabb to the aabb of the tree.
@@ -441,9 +433,8 @@
 								 const VspBspTraversalData &tData,
 								 int &axis,
-								 float &position,
-								 int &raysBack,
-								 int &raysFront,
-								 int &pvsBack,
-								 int &pvsFront);
+								 BspNodeGeometry **frontGeom,
+								 BspNodeGeometry **backGeom,
+								 float &frontArea,
+								 float &backArea);
 
 	/** Sorts split candidates for surface area heuristics for axis aligned splits.
@@ -506,5 +497,9 @@
 	
 	*/
-	void AddObjToPvs(Intersectable *obj, const int cf, int &frontPvs, int &backPvs) const;
+	void AddObjToPvs(Intersectable *obj, 
+					 const int cf, 
+					 int &frontPvs, 
+					 int &backPvs, 
+					 int &totalPvs) const;
 	
 	/** Computes PVS size induced by the rays.
@@ -591,8 +586,12 @@
 	void PropagateUpValidity(BspNode *node);
 
-	/** Creates or returns view cell corresponding to 
-		the space outside the valid view space.
-	*/
-	BspViewCell *GetOrCreateOutOfBoundsCell();
+	/** Writes the node to disk
+		@note: should be implemented as visitor
+	*/
+	void ExportNode(BspNode *node, ofstream &stream);
+
+	/** Returns memory usage of tree.
+	*/
+	float GetMemUsage() const;
 
 	/// Pointer to the root of the tree
@@ -621,13 +620,15 @@
 	/// mininum PVS
 	int mTermMinPvs;
-
-	/// minimal number of rays for axis aligned split
-	int mTermMinRaysForAxisAligned;
-	/// minimal number of objects for axis aligned split
-	int mTermMinObjectsForAxisAligned;
 	/// maximal contribution per ray
 	float mTermMaxRayContribution;
 	/// minimal accumulated ray length
 	float mTermMinAccRayLength;
+
+	//-- termination criteria for axis aligned split
+
+	/// minimal number of rays for axis aligned split
+	int mTermMinRaysForAxisAligned;
+	// max ray contribution
+	float mTermMaxRayContriForAxisAligned;
 
 	/// strategy to get the best split plane
@@ -684,6 +685,8 @@
 
 	MergeQueue mMergeQueue;
+
 	/// if rays should be used to collect merge candidates
 	bool mUseRaysForMerge;
+	
 	/// maximal allowed pvs so that view cell is valid
 	int mMaxPvs;
@@ -695,4 +698,10 @@
 	bool mShowInvalidSpace;
 
+	int mCurrentViewCellsId;
+
+	/// maximal tree memory
+	float mMaxMemory;
+
+	bool mOutOfMemory;
 private:
 	
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/X3dParser.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/X3dParser.cpp	(revision 490)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/X3dParser.cpp	(revision 508)
@@ -134,5 +134,5 @@
 	}
 	ptr = endptr;
-      }
+	  }
     }
   }
@@ -380,7 +380,7 @@
 
 
-/***********************************************************
- *         class X3dViewCellsParseHandlers implemenation   *
- ***********************************************************/
+/************************************************************************/
+/*             class X3dViewCellsParseHandlers implementation           */
+/************************************************************************/
 
 
@@ -534,15 +534,14 @@
   }
 	
-  // do nothing
-  //if (element == "Shape") {}
-  
   if (element == "Coordinate") {
 	  // add coordinates to the triangles
       StartCoordinate(attributes);
   }
+  // do nothing
+  //if (element == "Shape") {}
   // ignore material
   //if (element == "Material") {}
 
-  mElementCount++;
+  ++ mElementCount;
   mAttrCount += attributes.getLength();
 }
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsParser.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsParser.h	(revision 508)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsParser.h	(revision 508)
@@ -0,0 +1,23 @@
+#ifndef __VIEWCELLSDPARSER_H
+#define __VIEWCELLSDPARSER_H
+
+#include "Parser.h"
+#include "Containers.h"
+
+class ViewCellsManager;
+class VspBspTree;
+
+class ViewCellsParser : public Parser
+{
+public:
+  ViewCellsParser():Parser() {}
+  
+  //bool ParseFile(const string filename, ViewCellsManager &viewCells);
+  bool ParseFile(const string filename, 
+				 VspBspTree *tree, 
+				 ViewCellsManager *viewCells,
+				 ObjectContainer *objects);
+};
+
+
+#endif
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.h	(revision 503)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.h	(revision 508)
@@ -98,8 +98,16 @@
 	int CastRay(const Ray &ray, float &t, const float nearestT);
 
-	/** The polygon is triangulated.
+	/** The polygon is converted to triangles.
 	*/
 	void Triangulate(vector<Triangle3> &triangles);
-
+	/**
+		Adds polygon to mesh
+	*/
+	void AddToMesh(Mesh &mesh);
+	/** 
+		Triangle strip indices are created from this polgon.
+	*/
+	void Triangulate(VertexIndexContainer &indices);
+	
 	/** The piercing rays of the polygon are inherited by the child fragments
 		@parm front_piece the front fragment inheriting the front rays
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 503)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 508)
@@ -25,4 +25,7 @@
 	BspNodeGeometry()
 	{};  
+
+	// copy constructor copying the polygon array
+	BspNodeGeometry(const BspNodeGeometry &rhs);
 
 	~BspNodeGeometry();
@@ -330,4 +333,5 @@
 	/// leaf pvs
 	ObjectPvs *mPvs;
+
 	/// leaf area
 	float mArea;
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h	(revision 503)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h	(revision 508)
@@ -104,5 +104,5 @@
 		@return true on success
     */
-    bool LoadViewCells(const string filename);
+    virtual bool LoadViewCells(const string filename, ObjectContainer *objects);
 
 	/** Constructs view cell from base triangle. The ViewCell is extruded along the normal vector.
@@ -237,8 +237,15 @@
 	virtual void CreateMesh(ViewCell *vc) = NULL;
 
+	/** Writes view cells to disc.
+	*/
+	virtual bool ExportViewCells(const string filename);
+
 protected:
 
 	void ParseEnvironment();
 
+	/** Creates unique view cell ids.
+	*/
+	void CreateUniqueViewCellIds();
 	/** Recollects view cells and resets statistics.
 	*/
@@ -254,10 +261,9 @@
 	void EvaluateViewCellsStats();
 
-
 	//-- helper functions for view cell visualization
 
 	/** Exports the view cell partition.
 	*/
-	void ExportViewCells(Exporter *exporter) const;
+	void ExportViewCellsForViz(Exporter *exporter) const;
 
 	/** Sets exporter color.
@@ -272,4 +278,10 @@
 	*/
 	void CreateViewCellsMeshes();
+
+	/**
+		Exports single view cell.
+		NOTE: should be in exporter!!
+	*/
+	void ExportViewCell(ViewCell *viewCell, ofstream &stream);
 
 	/// the view cell corresponding to space ouside the valid view space
@@ -298,7 +310,8 @@
 	/// the scene bounding box
 	AxisAlignedBox3 mSceneBox;
-
+	/// holds the view cell meshes
 	MeshContainer mMeshContainer;
-
+	/// if view cells should be exported
+	bool mExportViewCells;
 	//-- visualization options
 	
@@ -551,9 +564,13 @@
 	void CreateMesh(ViewCell *vc);
 
+	bool LoadViewCells(const string filename, ObjectContainer *objects);
+	bool ExportViewCells(const string filename);
+
 protected:
 
 	/** Merges the view cells.
 	*/
-	void MergeViewCells(const VssRayContainer &rays, const ObjectContainer &objects);
+	void MergeViewCells(const VssRayContainer &rays, 
+						const ObjectContainer &objects);
 	
 	void RefineViewCells(const VssRayContainer &rays);
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp	(revision 503)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp	(revision 508)
@@ -19,4 +19,5 @@
 
 //-- static members
+
 /** Evaluates split plane classification with respect to the plane's
 	contribution for a minimum number of ray splits.
@@ -35,7 +36,7 @@
 float BspMergeCandidate::sOverallCost = 0;
 
-/****************************************************************/
-/*                  class VspBspTree implementation             */
-/****************************************************************/
+/********************************************************************/
+/*                  class VspBspTree implementation                 */
+/********************************************************************/
 
 VspBspTree::VspBspTree():
@@ -44,7 +45,7 @@
 mCostNormalizer(Limits::Small),
 mViewCellsManager(NULL),
-mStoreRays(false),
 mOutOfBoundsCell(NULL),
-mShowInvalidSpace(false)
+mShowInvalidSpace(false),
+mStoreRays(false)
 {
 	bool randomize = false;
@@ -88,4 +89,12 @@
 	environment->GetIntValue("ViewCells.maxPvs", mMaxPvs);
 
+	//-- termination criteria for axis aligned split
+	environment->GetFloatValue("VspBspTree.Termination.AxisAligned.maxRayContribution", 
+		mTermMaxRayContriForAxisAligned);
+	environment->GetIntValue("VspBspTree.Termination.AxisAligned.minRays",
+		mTermMinRaysForAxisAligned);
+
+	//environment->GetFloatValue("VspBspTree.maxTotalMemory", mMaxTotalMemory);
+	environment->GetFloatValue("VspBspTree.maxStaticMemory", mMaxMemory);
 
 	//-- debug output
@@ -135,10 +144,17 @@
 }
 
+BspViewCell *VspBspTree::GetOutOfBoundsCell()
+{
+	return mOutOfBoundsCell;
+}
+
 
 BspViewCell *VspBspTree::GetOrCreateOutOfBoundsCell()
 {
 	if (!mOutOfBoundsCell)
+	{
 		mOutOfBoundsCell = new BspViewCell();
-
+		mOutOfBoundsCell->SetId(-1);
+	}
 	return mOutOfBoundsCell;
 }
@@ -326,4 +342,17 @@
 }
 
+
+// return memory usage in MB
+float VspBspTree::GetMemUsage() const
+{
+	return
+		(sizeof(VspBspTree) +
+		 mStat.Leaves() * sizeof(BspLeaf) +
+		 mStat.Interior() * sizeof(BspInterior) +
+		 mStat.accumRays * sizeof(RayInfo)) / (1024.0f * 1024.0f);
+}
+
+
+
 void VspBspTree::Construct(const PolygonContainer &polys, RayInfoContainer *rays)
 {
@@ -350,10 +379,22 @@
 
 	long startTime = GetTime();
+	
+	bool mOutOfMemory = false;
 
 	while (!tStack.empty())
 	{
 		tData = tStack.top();
-
-	    tStack.pop();
+	    tStack.pop();		
+
+		if (0 && !mOutOfMemory)
+		{
+			float mem = GetMemUsage();
+
+			if (mem > mMaxMemory)
+			{
+				mOutOfMemory = true;
+				Debug << "memory limit reached: " << mem << endl;
+			}
+		}
 
 		// subdivide leaf node
@@ -365,8 +406,10 @@
 	}
 
+	Debug << "Used Memory: " << GetMemUsage() << " MB" << endl;
 	cout << "finished\n";
 
 	mStat.Stop();
 }
+
 
 bool VspBspTree::TerminationCriteriaMet(const VspBspTraversalData &data) const
@@ -377,7 +420,8 @@
 		 (data.mArea <= mTermMinArea) ||
 		 (mStat.Leaves() >= mMaxViewCells) ||
-		// (data.GetAvgRayContribution() >= mTermMaxRayContribution) ||
+		 (data.GetAvgRayContribution() >= mTermMaxRayContribution) ||
 		 (data.mDepth >= mTermMaxDepth));
 }
+
 
 BspNode *VspBspTree::Subdivide(VspBspTraversalStack &tStack,
@@ -386,5 +430,5 @@
 	BspNode *newNode = tData.mNode;
 
-	if (!TerminationCriteriaMet(tData))
+	if (!mOutOfMemory || !TerminationCriteriaMet(tData))
 	{
 		PolygonContainer coincident;
@@ -423,6 +467,5 @@
 		}
 		else
-		{
-			// create new view cell for this leaf
+		{	// create new view cell for this leaf			
 			viewCell = new BspViewCell();
 		}
@@ -465,10 +508,14 @@
 {
 	BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode);
-
-	int maxCostMisses = tData.mMaxCostMisses;
-
+	
 	// select subdivision plane
 	Plane3 splitPlane;
-	if (!SelectPlane(splitPlane, leaf, tData))
+	int maxCostMisses = tData.mMaxCostMisses;
+	bool success = SelectPlane(splitPlane, 
+							   leaf, 
+							   tData,
+							   frontData,
+							   backData);
+	if (!success)
 	{
 		++ maxCostMisses;
@@ -492,14 +539,12 @@
 
 	//-- the front and back traversal data is filled with the new values
+	frontData.mDepth = tData.mDepth + 1;
 	frontData.mPolygons = new PolygonContainer();
-	frontData.mDepth = tData.mDepth + 1;
 	frontData.mRays = new RayInfoContainer();
-	frontData.mGeometry = new BspNodeGeometry();
-
+	
+	backData.mDepth = tData.mDepth + 1;
 	backData.mPolygons = new PolygonContainer();
-	backData.mDepth = tData.mDepth + 1;
 	backData.mRays = new RayInfoContainer();
-	backData.mGeometry = new BspNodeGeometry();
-
+	
 	// subdivide rays
 	SplitRays(interior->GetPlane(),
@@ -524,20 +569,28 @@
 	backData.mPvs = ComputePvsSize(*backData.mRays);
 
-	// split geometry and compute area
-	if (1)
-	{
-		tData.mGeometry->SplitGeometry(*frontData.mGeometry,
-									   *backData.mGeometry,
-									   interior->GetPlane(),
-									   mBox,
-									   mEpsilon);
-
-		frontData.mArea = frontData.mGeometry->GetArea();
-		backData.mArea = backData.mGeometry->GetArea();
-	}
-
-	// compute accumulated ray length
-	//frontData.mAccRayLength = AccumulatedRayLength(*frontData.mRays);
-	//backData.mAccRayLength = AccumulatedRayLength(*backData.mRays);
+	// split front and back node geometry and compute area
+	if (mPvsUseArea)
+	{
+		// if not already computed
+		if (!frontData.mGeometry && !backData.mGeometry)
+		{
+			frontData.mGeometry = new BspNodeGeometry();
+			backData.mGeometry = new BspNodeGeometry();
+
+			tData.mGeometry->SplitGeometry(*frontData.mGeometry,
+										   *backData.mGeometry,
+										   interior->GetPlane(),
+										   mBox,
+										   mEpsilon);
+		
+			frontData.mArea = frontData.mGeometry->GetArea();
+			backData.mArea = backData.mGeometry->GetArea();
+		}
+	}
+	else
+	{
+		frontData.mArea = (float)frontData.mRays->size();
+		backData.mArea = (float)backData.mRays->size();
+	}
 
 	//-- create front and back leaf
@@ -565,4 +618,5 @@
 	return interior;
 }
+
 
 void VspBspTree::AddToPvs(BspLeaf *leaf,
@@ -757,19 +811,9 @@
 										 const VspBspTraversalData &tData,
 										 int &axis,
-										 float &position,
-										 int &raysBack,
-										 int &raysFront,
-										 int &pvsBack,
-										 int &pvsFront)
-{
-	AxisAlignedBox3 box;
-	box.Initialize();
-
-	// create bounding box of region
-	RayInfoContainer::const_iterator ri, ri_end = tData.mRays->end();
-
-	for(ri = tData.mRays->begin(); ri < ri_end; ++ ri)
-		box.Include((*ri).ExtrapTermination());
-
+										 BspNodeGeometry **frontGeom,
+										 BspNodeGeometry **backGeom,
+										 float &frontArea,
+										 float &backArea)
+{
 	const bool useCostHeuristics = false;
 
@@ -777,10 +821,35 @@
 	float nPosition[3];
 	float nCostRatio[3];
+	float nFrontArea[3];
+	float nBackArea[3];
+
+	BspNodeGeometry *nFrontGeom[3];
+	BspNodeGeometry *nBackGeom[3];
+
 	int bestAxis = -1;
 
-	const int sAxis = box.Size().DrivingAxis();
+	// create bounding box of node extent
+	AxisAlignedBox3 box;
+	box.Initialize();
+	
+#if 0
+	RayInfoContainer::const_iterator ri, ri_end = tData.mRays->end();
+
+	for(ri = tData.mRays->begin(); ri < ri_end; ++ ri)
+		box.Include((*ri).ExtrapTermination());
+#else
+	PolygonContainer::const_iterator it, it_end = tData.mGeometry->mPolys.end();
+
+	for(it = tData.mGeometry->mPolys.begin(); it < it_end; ++ it)
+		box.Include(*(*it));
+
+#endif
+	int sAxis = box.Size().DrivingAxis();
 
 	for (axis = 0; axis < 3; ++ axis)
 	{
+		nFrontGeom[axis] = new BspNodeGeometry();
+		nBackGeom[axis] = new BspNodeGeometry();
+
 		if (!mOnlyDrivingAxis || axis == sAxis)
 		{
@@ -789,6 +858,8 @@
 				nPosition[axis] = (box.Min()[axis] + box.Max()[axis]) * 0.5f;
 				Vector3 normal(0,0,0); normal[axis] = 1;
-
-				nCostRatio[axis] = SplitPlaneCost(Plane3(normal, nPosition[axis]), tData);
+				
+				nCostRatio[axis] = SplitPlaneCost(Plane3(normal, nPosition[axis]), 
+												  tData, *nFrontGeom[axis], *nBackGeom[axis],
+												  nFrontArea[axis], nBackArea[axis]);
 			}
 			else
@@ -809,7 +880,4 @@
 			else if (nCostRatio[axis] < nCostRatio[bestAxis])
 			{
-				/*Debug << "pvs front " << nPvsBack[axis]
-					  << " pvs back " << nPvsFront[axis]
-					  << " overall pvs " << leaf->GetPvsSize() << endl;*/
 				bestAxis = axis;
 			}
@@ -820,140 +888,27 @@
 	//-- assign values
 	axis = bestAxis;
-	position = nPosition[bestAxis];
-
-	raysBack = 0;//nRaysBack[bestAxis];
-	raysFront = 0;//nRaysFront[bestAxis];
-
-	pvsBack = 0;//nPvsBack[bestAxis];
-	pvsFront = 0;//nPvsFront[bestAxis];
-
-	Vector3 normal(0,0,0); normal[bestAxis] = 1;
+	frontArea = nFrontArea[bestAxis];
+	backArea = nBackArea[bestAxis];
+
+	// assign best split nodes geometry 
+	*frontGeom = nFrontGeom[bestAxis];
+	*backGeom = nBackGeom[bestAxis];
+	// and delete other geometry
+	delete nFrontGeom[(bestAxis + 1) % 3];
+	delete nBackGeom[(bestAxis + 2) % 3];
+
+	//-- split plane
+    Vector3 normal(0,0,0); normal[bestAxis] = 1;
 	plane = Plane3(normal, nPosition[bestAxis]);
-	
+
 	return nCostRatio[bestAxis];
 }
 
 
-/*
-float VspBspTree::EvalCostRatio(const VspBspTraversalData &tData,
-								const AxisAlignedBox3 &box,
-								const int axis,
-								const float position,
-								int &raysBack,
-								int &raysFront,
-								int &pvsBack,
-								int &pvsFront)
-{
-	raysBack = 0;
-	raysFront = 0;
-	pvsFront = 0;
-	pvsBack = 0;
-
-	Intersectable::NewMail(3);
-
-	// eval pvs size
-	const int pvsSize = tData.mPvs;
-
-	// create unique ids for pvs heuristics
-	GenerateUniqueIdsForPvs();
-
-	// this is the main ray classification loop!
-	for(RayInfoContainer::iterator ri = tData.mRays->begin();
-			ri != tData.mRays->end(); ++ ri)
-	{
-		if (!(*ri).mRay->IsActive())
-			continue;
-
-		// determine the side of this ray with respect to the plane
-		float t;
-		int side = (*ri).ComputeRayIntersection(axis, position, t);
-			
-		if (side <= 0)
-			++ raysBack;
-
-		if (side >= 0)
-			++ raysFront;
-
-		AddObjToPvs((*ri).mRay->mTerminationObject, side, pvsBack, pvsFront);
-	}
-
-	//-- only one of these options should be one
-
-	if (0) //-- only pvs
-	{
-		const float sum = float(pvsBack + pvsFront);
-		const float oldCost = (float)pvsSize;
-
-		return sum / oldCost;
-	}
-
-	//-- pvs + probability heuristics
-	float pBack, pFront, pOverall;
-
-	if (0)
-	{
-		// box length substitute for probability
-		const float minBox = box.Min(axis);
-		const float maxBox = box.Max(axis);
-
-		pBack = position - minBox;
-		pFront = maxBox - position;
-		pOverall = maxBox - minBox;
-	}
-
-	if (1) //-- area substitute for probability
-	{
-		
-		const bool useMidSplit = true;
-		//const bool useMidSplit = false;
-			
-		pOverall = box.SurfaceArea();
-			
-		if (!useMidSplit)
-		{
-			Vector3 pos = box.Max(); pos[axis] = position;
-			pBack = AxisAlignedBox3(box.Min(), pos).SurfaceArea();
-
-			pos = box.Min(); pos[axis] = position;
-			pFront = AxisAlignedBox3(pos, box.Max()).SurfaceArea();
-		}
-		else
-		{
-			//-- simplified computation for mid split
-			const int axis2 = (axis + 1) % 3;
-			const int axis3 = (axis + 2) % 3;
-
-			const float faceArea = 
-				(box.Max(axis2) - box.Min(axis2)) *
-				(box.Max(axis3) - box.Min(axis3));
-
-			pBack = pFront = pOverall * 0.5f + faceArea;
-		}
-	}
-
-	//-- ray density substitute for probability
-	if (0)
-	{
-		pBack = (float)raysBack;
-		pFront = (float)raysFront;
-		pOverall = (float)tData.mRays->size();
-	}
-
-	//Debug << axis << " " << pvsSize << " " << pvsBack << " " << pvsFront << endl;
-	//Debug << pFront << " " << pBack << " " << pOverall << endl;
-
-	// float sum = raysBack*(position - minBox) + raysFront*(maxBox - position);
-	const float newCost = pvsBack * pBack + pvsFront * pFront;
-	//  float oldCost = leaf->mRays.size();
-	const float oldCost = (float)pvsSize * pOverall;
-
-	return  (mCtDivCi + newCost) / oldCost;
-}
-*/
-
-
-bool VspBspTree::SelectPlane(Plane3 &plane,
+bool VspBspTree::SelectPlane(Plane3 &bestPlane,
 							 BspLeaf *leaf,
-							 VspBspTraversalData &data)
+							 VspBspTraversalData &data,
+							 VspBspTraversalData &frontData,
+							 VspBspTraversalData &backData)
 {
 	// simplest strategy: just take next polygon
@@ -962,14 +917,93 @@
         if (!data.mPolygons->empty())
 		{
-			const int randIdx = (int)RandomValue(0, (Real)((int)data.mPolygons->size() - 1));
+			const int randIdx = 
+				(int)RandomValue(0, (Real)((int)data.mPolygons->size() - 1));
 			Polygon3 *nextPoly = (*data.mPolygons)[randIdx];
 
-			plane = nextPoly->GetSupportingPlane();
+			bestPlane = nextPoly->GetSupportingPlane();
 			return true;
 		}
 	}
 
-	// use heuristics to find appropriate plane
-	return SelectPlaneHeuristics(plane, leaf, data);
+	//-- use heuristics to find appropriate plane
+
+	// intermediate plane
+	Plane3 plane;
+	float lowestCost = MAX_FLOAT;
+		
+	const bool onlyAxisAligned  = 
+		(mSplitPlaneStrategy & AXIS_ALIGNED) &&
+		((int)data.mRays->size() > mTermMinRaysForAxisAligned) &&
+		((int)data.GetAvgRayContribution() < mTermMaxRayContriForAxisAligned);
+	
+	// split polygons if no axis aligned splits
+	const int limit = onlyAxisAligned ? 0 : 
+		Min((int)data.mPolygons->size(), mMaxPolyCandidates);
+
+	float candidateCost;
+
+	int maxIdx = (int)data.mPolygons->size();
+
+	for (int i = 0; i < limit; ++ i)
+	{
+		//-- assure that no index is taken twice
+		const int candidateIdx = (int)RandomValue(0, (Real)(-- maxIdx));
+		Polygon3 *poly = (*data.mPolygons)[candidateIdx];
+
+		// swap candidate to the end to avoid testing same plane
+		std::swap((*data.mPolygons)[maxIdx], (*data.mPolygons)[candidateIdx]);
+		//Polygon3 *poly = (*data.mPolygons)[(int)RandomValue(0, (int)polys.size() - 1)];
+
+		// evaluate current candidate
+		BspNodeGeometry fGeom, bGeom;
+		float fArea, bArea;
+		plane = poly->GetSupportingPlane();
+		candidateCost = SplitPlaneCost(plane, data, fGeom, bGeom, fArea, bArea);
+		
+		if (candidateCost < lowestCost)
+		{
+			bestPlane = plane;
+			lowestCost = candidateCost;
+		}
+	}
+
+	//-- evaluate axis aligned splits
+	int axis;
+	BspNodeGeometry *fGeom, *bGeom;
+	float fArea, bArea;
+
+	candidateCost = SelectAxisAlignedPlane(plane, data, axis,
+										   &fGeom, &bGeom, 
+										   fArea, bArea);						 
+
+	if (candidateCost < lowestCost)
+	{	
+		bestPlane = plane;
+		lowestCost = candidateCost;
+
+		//-- assign already computed values
+		frontData.mGeometry = fGeom;
+		backData.mGeometry = bGeom;
+		frontData.mArea = fArea;
+		backData.mArea = bArea;
+
+		//! error also computed if cost ratio is missed
+		++ mStat.splits[axis];
+	}
+	else
+	{
+		DEL_PTR(fGeom);
+		DEL_PTR(bGeom);
+	}
+
+#ifdef _DEBUG
+	Debug << "plane lowest cost: " << lowestCost << endl;
+#endif
+
+	// cost ratio miss
+	if (lowestCost > mTermMaxCostRatio)
+		return false;
+
+	return true;
 }
 
@@ -1048,83 +1082,4 @@
 
 
-bool VspBspTree::SelectPlaneHeuristics(Plane3 &bestPlane,
-									   BspLeaf *leaf,
-									   VspBspTraversalData &data)
-{
-	float lowestCost = MAX_FLOAT;
-	// intermediate plane
-	Plane3 plane;
-	bool useAxisAlignedPlane = false;
-
-	const int limit = Min((int)data.mPolygons->size(), mMaxPolyCandidates);
-	int maxIdx = (int)data.mPolygons->size();
-
-	float candidateCost;
-
-	for (int i = 0; i < limit; ++ i)
-	{
-		//-- assure that no index is taken twice
-		const int candidateIdx = (int)RandomValue(0, (Real)(-- maxIdx));
-		Polygon3 *poly = (*data.mPolygons)[candidateIdx];
-
-		// swap candidate to the end to avoid testing same plane
-		std::swap((*data.mPolygons)[maxIdx], (*data.mPolygons)[candidateIdx]);
-
-		//Polygon3 *poly = (*data.mPolygons)[(int)RandomValue(0, (int)polys.size() - 1)];
-
-		// evaluate current candidate
-		candidateCost = SplitPlaneCost(poly->GetSupportingPlane(), data);
-
-		if (candidateCost < lowestCost)
-		{
-			bestPlane = poly->GetSupportingPlane();
-			lowestCost = candidateCost;
-		}
-	}
-
-	//-- axis aligned splits
-	int axis;
-	float position;
-	int raysBack;
-	int raysFront;
-	int pvsFront;
-	int pvsBack;
-
-	candidateCost = SelectAxisAlignedPlane(plane, 
-										   data, 
-										   axis,
-										   position,
-										   raysBack,
-										   raysFront,
-										   pvsFront,
-										   pvsBack);
-
-	if (candidateCost < lowestCost)
-	{	
-		if (!useAxisAlignedPlane)
-		{
-			useAxisAlignedPlane = true;
-			//if (data.mPolygons->size() > 0)
-			//	Debug << "haha" << endl;
-			//! error also computed if cost ratio is missed
-			++ mStat.splits[axis];
-		}
-
-		bestPlane = plane;
-		lowestCost = candidateCost;
-	}
-
-#ifdef _DEBUG
-	Debug << "plane lowest cost: " << lowestCost << endl;
-#endif
-
-	// cost ratio miss
-	if (lowestCost > mTermMaxCostRatio)
-		return false;
-
-	return true;
-}
-
-
 inline void VspBspTree::GenerateUniqueIdsForPvs()
 {
@@ -1136,5 +1091,9 @@
 
 float VspBspTree::SplitPlaneCost(const Plane3 &candidatePlane,
-								 const VspBspTraversalData &data) const
+								 const VspBspTraversalData &data,
+								 BspNodeGeometry &geomFront,
+								 BspNodeGeometry &geomBack,
+								 float &areaFront,
+								 float &areaBack) const
 {
 	float cost = 0;
@@ -1143,12 +1102,16 @@
 	float sumRaySplits = 0;
 
-	int frontPvs = 0;
-	int backPvs = 0;
-
-	// probability that view point lies in child
+	int pvsFront = 0;
+	int pvsBack = 0;
+
+	// probability that view point lies in back / front node
 	float pOverall = 0;
 	float pFront = 0;
 	float pBack = 0;
 
+	int raysFront = 0;
+	int raysBack = 0;
+	int totalPvs = 0;
+
 	if (mSplitPlaneStrategy & PVS)
 	{
@@ -1159,17 +1122,22 @@
 		{
 			// construct child geometry with regard to the candidate split plane
-			BspNodeGeometry frontCell;
-			BspNodeGeometry backCell;
-
-			data.mGeometry->SplitGeometry(frontCell,
-										  backCell,
+			data.mGeometry->SplitGeometry(geomFront,
+										  geomBack,
 										  candidatePlane,
 										  mBox,
 										  mEpsilon);
 
-			pFront = frontCell.GetArea();
-			pBack = backCell.GetArea();
-
+			areaFront = geomFront.GetArea();
+			areaBack = geomBack.GetArea();
+
+			pBack = areaBack;
+			pFront = areaFront;
 			pOverall = data.mArea;
+		}
+		else // use number of rays to approximate volume
+		{
+			pOverall = (float)data.mRays->size();
+			pFront = (float)raysFront;
+			pBack = (float)raysBack;
 		}
 	}
@@ -1189,13 +1157,19 @@
 		limit = (int)data.mRays->size();
 	}
-
+	
 	for (int i = 0; i < limit; ++ i)
 	{
-		const int testIdx = useRand ? (int)RandomValue(0, (Real)(limit - 1)) : i;
+		const int testIdx = useRand ? 
+			(int)RandomValue(0, (Real)((int)data.mRays->size() - 1)) : i;
 		RayInfo rayInf = (*data.mRays)[testIdx];
 
+		float t;
 		VssRay *ray = rayInf.mRay;
-		float t;
 		const int cf = rayInf.ComputeRayIntersection(candidatePlane, t);
+
+        if (cf >= 0)
+			++ raysFront;
+		if (cf <= 0)
+			++ raysBack;
 
 		if (mSplitPlaneStrategy & LEAST_RAY_SPLITS)
@@ -1212,20 +1186,7 @@
 		if (mSplitPlaneStrategy & PVS)
 		{
-			// in case the ray intersects an object
-			// assure that we only count the object
-			// once for the front and once for the back side of the plane
-			AddObjToPvs(ray->mTerminationObject, cf, frontPvs, backPvs);
-			AddObjToPvs(ray->mOriginObject, cf, frontPvs, backPvs);
-
-			// use number of rays to approximate volume
-			if (!mPvsUseArea)
-			{
-				pOverall = (float)data.mRays->size();
-
-				if (cf >= 0)
-					++ pFront;
-				if (cf <= 0)
-					++ pBack;
-			}
+			// find front and back pvs for origing and termination object
+			AddObjToPvs(ray->mTerminationObject, cf, pvsFront, pvsBack, totalPvs);
+			AddObjToPvs(ray->mOriginObject, cf, pvsFront, pvsBack, totalPvs);
 		}
 	}
@@ -1242,20 +1203,12 @@
 	if (mSplitPlaneStrategy & PVS)
 	{
-		const float oldCost = pOverall * (float)data.mPvs + Limits::Small;
-		cost += mPvsFactor * (frontPvs * pFront + backPvs * pBack) / oldCost;
-
-		//cost += mPvsFactor * 0.5 * (frontPvs * pFront + backPvs * pBack) / oldCost;
-		//Debug << "new cost: " << cost << " over" << frontPvs * pFront + backPvs * pBack << " old cost " << oldCost << endl;
-
-		if (0) // give penalty to unbalanced split
-			if (((pFront * 0.2 + Limits::Small) > pBack) ||
-				(pFront < (pBack * 0.2 + Limits::Small)))
-					cost += 0.5;
+		const float oldCost = pOverall * (float)totalPvs + Limits::Small;
+		cost += mPvsFactor * (pvsFront * pFront + pvsBack * pBack) / oldCost;
 	}
 
 #ifdef _DEBUG
   	Debug << "totalpvs: " << data.mPvs << " ptotal: " << pOverall
-  		  << " frontpvs: " << frontPvs << " pFront: " << pFront
-  		  << " backpvs: " << backPvs << " pBack: " << pBack << endl << endl;
+  		  << " frontpvs: " << pvsFront << " pFront: " << pFront
+  		  << " backpvs: " << pvsBack << " pBack: " << pBack << endl << endl;
 #endif
 
@@ -1263,12 +1216,22 @@
 	return cost / (float)mCostNormalizer;
 }
+
 
 void VspBspTree::AddObjToPvs(Intersectable *obj,
 							 const int cf,
 							 int &frontPvs,
-							 int &backPvs) const
+							 int &backPvs,
+							 int &totalPvs) const
 {
 	if (!obj)
 		return;
+	
+	if ((obj->mMailbox != sFrontId) &&
+		(obj->mMailbox != sBackId) &&
+		(obj->mMailbox != sFrontAndBackId))
+	{
+		++ totalPvs;
+	}
+
 	// TODO: does this really belong to no pvs?
 	//if (cf == Ray::COINCIDENT) return;
@@ -1281,5 +1244,5 @@
 		{
 			++ frontPvs;
-
+		
 			if (obj->mMailbox == sBackId)
 				obj->mMailbox = sFrontAndBackId;
@@ -1295,5 +1258,5 @@
 		{
 			++ backPvs;
-
+		
 			if (obj->mMailbox == sFrontId)
 				obj->mMailbox = sFrontAndBackId;
@@ -1322,5 +1285,5 @@
 			BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
 			if (leaf->TreeValid() && 
-				(!onlyUnmailed || leaf->Mailed()) &&
+				(!onlyUnmailed || !leaf->Mailed()) &&
 				((maxPvsSize < 0) || (leaf->GetViewCell()->GetPvs().GetSize() <= maxPvsSize)))
 			{
@@ -1351,10 +1314,4 @@
 
 
-BspViewCell *VspBspTree::GetOutOfBoundsCell() const
-{
-	return mOutOfBoundsCell;
-}
-
-
 void VspBspTree::EvaluateLeafStats(const VspBspTraversalData &data)
 {
@@ -1368,8 +1325,12 @@
 	if (data.mPvs > mStat.maxPvs)
 		mStat.maxPvs = data.mPvs;
+	
 	if (data.mDepth < mStat.minDepth)
 		mStat.minDepth = data.mDepth;
+
 	if (data.mDepth >= mTermMaxDepth)
 		++ mStat.maxDepthNodes;
+	// accumulate rays to compute rays /  leaf
+	mStat.accumRays += (int)data.mRays->size();
 
 	if (data.mPvs < mTermMinPvs)
@@ -1383,8 +1344,6 @@
 
 	if (data.mArea <= mTermMinArea)
-	{
-		//Debug << "area: " << data.mArea / mBox.SurfaceArea() << " min area: " << mTermMinArea / mBox.SurfaceArea() << endl;
 		++ mStat.minAreaNodes;
-	}
+	
 	// accumulate depth to compute average depth
 	mStat.accumDepth += data.mDepth;
@@ -1498,17 +1457,4 @@
 }
 
-bool VspBspTree::Export(const string filename)
-{
-	Exporter *exporter = Exporter::GetExporter(filename);
-
-	if (exporter)
-	{
-		//exporter->ExportVspBspTree(*this);
-		return true;
-	}
-
-	return false;
-}
-
 void VspBspTree::CollectViewCells(ViewCellContainer &viewCells) const
 {
@@ -1516,5 +1462,5 @@
 
 	if (!mRoot)
-	return;
+		return;
 
 	nodeStack.push(mRoot);
@@ -1543,5 +1489,5 @@
 		{
 			BspInterior *interior = dynamic_cast<BspInterior *>(node);
-			
+		
 			nodeStack.push(interior->GetFront());
 			nodeStack.push(interior->GetBack());
@@ -2245,7 +2191,8 @@
 {
 	BspLeaf::NewMail();
-
+	
 	vector<BspLeaf *>::const_iterator it, it_end = leaves.end();
 
+	Debug << "mergequeue size: " << mMergeQueue.size() << endl;
 	// find merge candidates and push them into queue
 	for (it = leaves.begin(); it != it_end; ++ it)
@@ -2268,8 +2215,11 @@
 		// TODO: test if at least one ray goes from one leaf to the other
 		for (nit = neighbors.begin(); nit != nit_end; ++ nit)
-		{			
-			mMergeQueue.push(BspMergeCandidate(leaf, *nit));
-		}
-	}
+		{
+			if ((*nit)->GetViewCell() != leaf->GetViewCell())
+				mMergeQueue.push(BspMergeCandidate(leaf, *nit));
+		}
+	}
+
+	Debug << "new mergequeue size: " << mMergeQueue.size() << endl;
 
 	return (int)leaves.size();
@@ -2283,5 +2233,6 @@
 	long startTime = GetTime();
 	ConstructBspRays(bspRays, rays);
-	Debug << (int)bspRays.size() << " bsp rays constructed in " << TimeDiff(startTime, GetTime()) * 1e-3f << " secs" << endl;
+	Debug << (int)bspRays.size() << " bsp rays constructed in " 
+		  << TimeDiff(startTime, GetTime()) * 1e-3f << " secs" << endl;
 
 	map<BspLeaf *, vector<BspLeaf*> > neighborMap;
@@ -2324,6 +2275,7 @@
             leaf = (*iit).mLeaf;
 
-			// view space not valid
-			if (!leaf->TreeValid() || !prevLeaf->TreeValid())
+			// view space not valid or same view cell
+			if (!leaf->TreeValid() || !prevLeaf->TreeValid() ||
+				(leaf->GetViewCell() == prevLeaf->GetViewCell()))
 				continue;
 
@@ -2379,6 +2331,7 @@
 	vector<BspLeaf *> leaves;
 	CollectLeaves(leaves, true, mMaxPvs);
-	Debug << "found " << (int)leaves.size() << " new leaves" << endl;
-	//CollectMergeCandidates(leaves);
+	Debug << "found " << (int)leaves.size() << " new leaves" << endl << endl;
+	// TODO
+	CollectMergeCandidates(leaves);
 
 	return numLeaves;
@@ -2508,6 +2461,5 @@
 
 
-ViewCell *
-VspBspTree::GetViewCell(const Vector3 &point)
+ViewCell *VspBspTree::GetViewCell(const Vector3 &point)
 {
   if (mRoot == NULL)
@@ -2737,138 +2689,40 @@
 }
 
-#define USE_ASCII 0
-bool VspBspTree::WriteVspBspTree()
-{
-	char fileName[100];
-	environment->GetStringValue("VspBspTree.viewCellsFilename", fileName);
+
+bool VspBspTree::Export(ofstream &stream)
+{
+	ExportNode(mRoot, stream);
+
+	return true;
+}
+
+
+void VspBspTree::ExportNode(BspNode *node, ofstream &stream)
+{
+	if (node->IsLeaf())
+	{
+		BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
+			
+		int id = -1;
+		if (leaf->GetViewCell() != mOutOfBoundsCell)
+			id = leaf->GetViewCell()->GetId();
+
+		stream << "<Leaf viewCellId=\"" << id << "\" />" << endl;
+	}
+	else
+	{
+		BspInterior *interior = dynamic_cast<BspInterior *>(node);
 	
-	/*VssRayContainer::const_iterator it, it_end = samples.end();
-	
-#if USE_ASCII
-	ofstream samplesOut(fileName);
-	if (!samplesOut.is_open())
-		return false;
-
-	for (it = samples.begin(); it != it_end; ++ it)
-	{
-		VssRay *ray = *it;
-		int sourceid = ray->mOriginObject ? ray->mOriginObject->mId : -1;		
-		int termid = ray->mTerminationObject ? ray->mTerminationObject->mId : -1;	
-
-		samplesOut << ray->GetOrigin().x << " " << ray->GetOrigin().y << " " << ray->GetOrigin().z << " " 
-				   << ray->GetTermination().x << " " << ray->GetTermination().y << " " << ray->GetTermination().z << " " 
-				   << sourceid << " " << termid << "\n";
-	}
-#else
-	ofstream samplesOut(fileName, ios::binary);
-	if (!samplesOut.is_open())
-		return false;
-
-	for (it = samples.begin(); it != it_end; ++ it)
-	{	
-		VssRay *ray = *it;
-		Vector3 origin(ray->GetOrigin());
-		Vector3 termination(ray->GetTermination());
-		
-		int sourceid = ray->mOriginObject ? ray->mOriginObject->mId : -1;		
-		int termid = ray->mTerminationObject ? ray->mTerminationObject->mId : -1;		
-
-		samplesOut.write(reinterpret_cast<char *>(&origin), sizeof(Vector3));
-		samplesOut.write(reinterpret_cast<char *>(&termination), sizeof(Vector3));
-		samplesOut.write(reinterpret_cast<char *>(&sourceid), sizeof(int));
-		samplesOut.write(reinterpret_cast<char *>(&termid), sizeof(int));
-    }
-#endif
-
-	samplesOut.close();
-	*/
-	return true;
-}
-
-bool VspBspTree::LoadVspBspTree()
-{
-	/*std::stable_sort(objects.begin(), objects.end(), ilt);
-	char fileName[100];
-	environment->GetStringValue("Preprocessor.samplesFilename", fileName);
-	
-    Vector3 origin, termination;
-	// HACK: needed only for lower_bound algorithm to find the 
-	// intersected objects
-	MeshInstance sObj(NULL);
-	MeshInstance tObj(NULL);
-
-#if USE_ASCII
-	ifstream samplesIn(fileName, ios::binary);
-	if (!samplesIn.is_open())
-		return false;
-
-	string buf;
-	while (!(getline(samplesIn, buf)).eof())
-	{
-		sscanf(buf.c_str(), "%f %f %f %f %f %f %d %d", 
-			   &origin.x, &origin.y, &origin.z,
-			   &termination.x, &termination.y, &termination.z, 
-			   &(sObj.mId), &(tObj.mId));
-		
-		Intersectable *sourceObj = NULL;
-		Intersectable *termObj = NULL;
-		
-		if (sObj.mId >= 0)
-		{
-			ObjectContainer::iterator oit =
-				lower_bound(objects.begin(), objects.end(), &sObj, ilt);
-			sourceObj = *oit;
-		}
-		
-		if (tObj.mId >= 0)
-		{
-			ObjectContainer::iterator oit =
-				lower_bound(objects.begin(), objects.end(), &tObj, ilt);
-			termObj = *oit;
-		}
-
-		samples.push_back(new VssRay(origin, termination, sourceObj, termObj));
-	}
-#else
-	ifstream samplesIn(fileName, ios::binary);
-	if (!samplesIn.is_open())
-		return false;
-
-	while (1)
-	{
-		 samplesIn.read(reinterpret_cast<char *>(&origin), sizeof(Vector3));
-		 samplesIn.read(reinterpret_cast<char *>(&termination), sizeof(Vector3));
-		 samplesIn.read(reinterpret_cast<char *>(&(sObj.mId)), sizeof(int));
-		 samplesIn.read(reinterpret_cast<char *>(&(tObj.mId)), sizeof(int));
-		
-		 if (samplesIn.eof())
-			break;
-
-		Intersectable *sourceObj = NULL;
-		Intersectable *termObj = NULL;
-		
-		if (sObj.mId >= 0)
-		{
-			ObjectContainer::iterator oit =
-				lower_bound(objects.begin(), objects.end(), &sObj, ilt);
-			sourceObj = *oit;
-		}
-		
-		if (tObj.mId >= 0)
-		{
-			ObjectContainer::iterator oit =
-				lower_bound(objects.begin(), objects.end(), &tObj, ilt);
-			termObj = *oit;
-		}
-
-		samples.push_back(new VssRay(origin, termination, sourceObj, termObj));
-	}
-
-#endif
-	samplesIn.close();
-*/
-	return true;
-}
-
+		Plane3 plane = interior->GetPlane();
+		stream << "<Interior plane=\"" << plane.mNormal.x << " " 
+			   << plane.mNormal.y << " " << plane.mNormal.z << " " 
+			   << plane.mD << "\">" << endl;
+
+		ExportNode(interior->GetBack(), stream);
+		ExportNode(interior->GetFront(), stream);
+
+		stream << "</Interior>" << endl;
+	}
+}
 
 /************************************************************************/
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Parser.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Parser.h	(revision 339)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Parser.h	(revision 508)
@@ -14,5 +14,5 @@
   Parser() {}
 
-	virtual bool ParseFile(const string filename, SceneGraphNode **root) = 0;
+  virtual bool ParseFile(const string filename, SceneGraphNode **root) {return false;};
 	
 };
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp	(revision 503)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp	(revision 508)
@@ -1140,10 +1140,10 @@
 		 "0.1");
 
-  RegisterOption("Sampling.totalSamples",
+  RegisterOption("SamplingPreprocessor.totalSamples",
 		 optInt,
 		 "total_samples=",
 		 "1000000");
 
-  RegisterOption("Sampling.samplesPerPass",
+  RegisterOption("SamplingPreprocessor.samplesPerPass",
 		 optInt,
 		 "samples_per_pass=",
@@ -1191,5 +1191,5 @@
 	  optBool,
 	  "-vss_use_viewspace_box=",
-	  "true");
+	  "false");
    
 
@@ -1199,288 +1199,293 @@
 
 
-  RegisterOption("ViewCells.type",
-		 optString,
-		 "view_cells_type",
-		 "bspTree");
-
-  RegisterOption("ViewCells.PostProcess.samples",
-				 optInt,
-				 "view_cells_postprocess_samples=",
-				 "200000");
-  
-  RegisterOption("ViewCells.Visualization.samples",
-				 optInt,
-				 "view_cells_visualization_samples=",
-				 "20000");
-  
-   RegisterOption("ViewCells.loadFromFile",
-				  optBool,
-				  "view_cells_load_from_file",
-				  "false");
-   
-  RegisterOption("ViewCells.maxViewCells",
-		 optInt,
-		 "view_cells_max_view_cells=",
-		 "0");
-
-  
-  RegisterOption("ViewCells.maxPvs",
-				 optInt,
-				 "view_cells_max_pvs=",
-				 "300");
- 
-  RegisterOption("ViewCells.filename",
-		 optString,
-		 "view_cells_filename=",
-		 "atlanta_viewcells_large.x3d");
-
-   RegisterOption("ViewCells.height",
-		 optFloat,
-		 "view_cells_height=",
-		 "5.0");
-
-   RegisterOption("ViewCells.Visualization.colorCode",
+	RegisterOption("ViewCells.type",
+			optString,
+			"view_cells_type",
+			"bspTree");
+
+	RegisterOption("ViewCells.PostProcess.samples",
+					optInt,
+					"view_cells_postprocess_samples=",
+					"200000");
+
+	RegisterOption("ViewCells.Visualization.samples",
+					optInt,
+					"view_cells_visualization_samples=",
+					"20000");
+
+	RegisterOption("ViewCells.loadFromFile",
+					optBool,
+					"view_cells_load_from_file",
+					"false");
+
+	RegisterOption("ViewCells.exportToFile",
+					optBool,
+					"view_cells_export_to_file",
+					"false");
+
+	RegisterOption("ViewCells.maxViewCells",
+			optInt,
+			"view_cells_max_view_cells=",
+			"0");
+
+	RegisterOption("ViewCells.maxPvs",
+					optInt,
+					"view_cells_max_pvs=",
+					"300");
+
+	RegisterOption("ViewCells.filename",
+			optString,
+			"view_cells_filename=",
+			"atlanta_viewcells_large.x3d");
+
+	RegisterOption("ViewCells.height",
+			optFloat,
+			"view_cells_height=",
+			"5.0");
+
+	RegisterOption("ViewCells.Visualization.colorCode",
 		optString,
 		"-view_cells_visualization.color_code",
 		"PVS");
 
-   RegisterOption("ViewCells.Visualization.exportRays",
-	  optBool,
-	  "-bsp_visualization.export_rays",
-	  "false");
-   
-   RegisterOption("ViewCells.Visualization.exportGeometry",
-	  optBool,
-	  "-bsp_visualization.export_geometry",
-	  "false");
-
-  /************************************************************************************/
-  /*                         Render simulation related options                        */
-  /************************************************************************************/
-
-
-  RegisterOption("Simulation.objRenderCost",
-		 optFloat,
-		 "simulation_obj_render_cost",
-		 "1.0");
-
-  RegisterOption("Simulation.vcOverhead",
-		 optFloat,
-		 "simulation_vc_overhead",
-		 "0.05");
-
-  RegisterOption("Simulation.moveSpeed",
-		 optFloat,
-		 "simulation_moveSpeed",
-		 "1.0");
-
-
-
-
-  /************************************************************************************/
-  /*                         Bsp tree related options                                 */
-  /************************************************************************************/
-
-
-  RegisterOption("BspTree.Construction.input",
-	  optString,
-	  "bsp_construction_input=",
-	  "fromViewCells");
-  
-  RegisterOption("BspTree.Construction.samples",
-	  optInt,
-	  "bsp_construction_samples=",
-	  "100000");
-
-  RegisterOption("BspTree.Construction.epsilon",
-	  optFloat,
-	  "bsp_construction_side_tolerance=",
-	  "0.002");
-
-  RegisterOption("BspTree.Termination.minPolygons",
-		 optInt,
-		 "bsp_term_min_polygons=",
-		 "5");
-
-  RegisterOption("BspTree.Termination.minPvs",
-		 optInt,
-		 "bsp_term_min_pvs=",
-		 "20");
-
-  RegisterOption("BspTree.Termination.minArea",
-		 optFloat,
-		 "bsp_term_min_area=",
-		 "0.001");
-  
-  RegisterOption("BspTree.Termination.maxRayContribution",
-		 optFloat,
-		 "bsp_term_ray_contribution=",
-		 "0.005");
-
-  RegisterOption("BspTree.Termination.minAccRayLenght",
-		 optFloat,
-		 "bsp_term_min_acc_ray_length=",
-		 "50");
-
-   RegisterOption("BspTree.Termination.minRays",
-		 optInt,
-		 "bsp_term_min_rays=",
-		 "-1");
-
-   RegisterOption("BspTree.Termination.ct_div_ci",
-		 optFloat,
-		 "bsp_term_ct_div_ci=",
-		 "0.0");
-  
-  RegisterOption("BspTree.Termination.maxDepth",
-		 optInt,
-		 "bsp_term_max_depth=",
-		 "100");
-
-  RegisterOption("BspTree.Termination.maxCostRatio",
-		 optFloat,
-		 "bsp_term_axis_aligned_max_cost_ratio=",
-		 "1.5");
-
-  RegisterOption("BspTree.Termination.AxisAligned.ct_div_ci",
-		 optFloat,
-		 "bsp_term_axis_aligned_ct_div_ci=",
-		 "0.5");
-
-  RegisterOption("BspTree.AxisAligned.splitBorder",
-		 optFloat,
-		 "bsp__axis_aligned_split_border=",
-		 "0.1");
-
-  RegisterOption("BspTree.Termination.AxisAligned.minPolys",
-		 optInt,
-		 "bsp_term_axis_aligned_max_polygons=",
-		 "50");
-
-   RegisterOption("BspTree.Termination.AxisAligned.minObjects",
-		 optInt,
-		 "bsp_term_min_objects=",
-		 "3");
-
-  RegisterOption("BspTree.Termination.AxisAligned.minRays",
-		 optInt,
-		 "bsp_term_axis_aligned_min_rays=",
-		 "-1");
-
-  RegisterOption("BspTree.splitPlaneStrategy",
-		 optString,
-		 "bsp_split_method=",
-		 "leastSplits");
-
-  RegisterOption("BspTree.maxPolyCandidates",
-	  optInt,
-	  "bsp_max_poly_candidates=",
-	  "20");
-
-  RegisterOption("BspTree.maxRayCandidates",
-	  optInt,
-	  "bsp_max_plane_candidates=",
-	  "20");
-
-  RegisterOption("BspTree.maxTests",
-	  optInt,
-	  "bsp_max_tests=",
-	  "5000");
-
-  RegisterOption("BspTree.Visualization.exportSplits",
-	  optBool,
-	  "bsp_visualization.export_splits",
-	  "false");
-
-  RegisterOption("BspTree.Factor.verticalSplits", optFloat, "bsp_factor_vertical=", "1.0");
-   RegisterOption("BspTree.Factor.largestPolyArea", optFloat, "bsp_factor_largest_poly=", "1.0");
-   RegisterOption("BspTree.Factor.blockedRays", optFloat, "bsp_factor_blocked=", "1.0");
-   RegisterOption("BspTree.Factor.leastSplits", optFloat, "bsp_factor_least_splits=", "1.0");
-   RegisterOption("BspTree.Factor.balancedPolys", optFloat, "bsp_factor_balanced_polys=", "1.0");
-   RegisterOption("BspTree.Factor.balancedViewCells", optFloat, "bsp_factor_balanced_view_cells=", "1.0");
-   RegisterOption("BspTree.Factor.leastRaySplits", optFloat, "bsp_factor_least_ray_splits=", "1.0");
-   RegisterOption("BspTree.Factor.balancedRays", optFloat, "bsp_factor_balanced_rays=", "1.0");
-   RegisterOption("BspTree.Factor.pvs", optFloat, "bsp_factor_pvs=", "1.0");
-
-   /************************************************************************************/
-   /*                         Preprocessor related options                             */
-   /************************************************************************************/
-
-   RegisterOption("Preprocessor.type",
-				 optString,
-				 "preprocessor=",
-				 "sampling");
-
-   RegisterOption("Preprocessor.samplesFilename",
-				  optString,
-				  "-preprocessor_samples_filename=",
-				  "rays.out");
-
-  RegisterOption("Preprocessor.useGlRenderer",
-				 optBool,
-				 "useGlRenderer",
-				 "false");
-  
-  /**************************************************************************************/
-  /*                  View space partition KD tree related options                      */
-  /**************************************************************************************/
-
-   RegisterOption("VspKdTree.Construction.samples",
-				  optInt,
-				  "vsp_kd_construction_samples=",
-				  "100000");
-
-   RegisterOption("VspKdTree.Termination.maxDepth", 
-	   optInt, 
-	   "vsp_term_maxdepth=", "30");
-
-   RegisterOption("VspKdTree.Termination.minPvs", 
-	   optInt, 
-	   "vsp_minpvs=", 
-	   "1");
-
-   RegisterOption("VspKdTree.Termination.minRays", 
-	   optInt, 
-	   "vsp_term_minrays=", 
-	   "10");
-
-   RegisterOption("VspKdTree.Termination.minSize", 
-	   optFloat, 
-	   "vsp_term_minsize=", 
-	   "0.001");
-
-   RegisterOption("VspKdTree.Termination.maxCostRatio", 
-	   optFloat, 
-	   "vsp_term_maxcost=",
-	   "0.95");
-
-   RegisterOption("VspKdTree.Termination.maxRayContribution", 
-	   optFloat, 
-	   "vsp_term_max_ray_contrib=", 
-	   "0.5");
-
-   RegisterOption("VspKdTree.epsilon", 
-	   optFloat, 
-	   "kd_eps=", 
-	   "1e-6");
-
-   RegisterOption("VspKdTree.ct_div_ci", 
-	   optFloat, 
-	   "vsp_ctdivci=", "1.0");
-   
-   RegisterOption("VspKdTree.splitType", 
-	   optString, 
-	   "split=", 
-	   "queries");
-
-  RegisterOption("VspKdTree.splitAxis", 
-	   optString, 
-	   "split=", 
-	   "drivingAxis");
-
-  RegisterOption("VspKdTree.splitUseOnlyDrivingAxis", 
-	  optBool, 
-	  "vsp_kd_splitdriving=", 
-	  "false");
+	RegisterOption("ViewCells.Visualization.exportRays",
+		optBool,
+		"-bsp_visualization.export_rays",
+		"false");
+
+	RegisterOption("ViewCells.Visualization.exportGeometry",
+		optBool,
+		"-bsp_visualization.export_geometry",
+		"false");
+
+
+	/************************************************************************************/
+	/*                         Render simulation related options                        */
+	/************************************************************************************/
+
+
+	RegisterOption("Simulation.objRenderCost",
+			optFloat,
+			"simulation_obj_render_cost",
+			"1.0");
+
+	RegisterOption("Simulation.vcOverhead",
+			optFloat,
+			"simulation_vc_overhead",
+			"0.05");
+
+	RegisterOption("Simulation.moveSpeed",
+			optFloat,
+			"simulation_moveSpeed",
+			"1.0");
+
+
+
+
+	/************************************************************************************/
+	/*                         Bsp tree related options                                 */
+	/************************************************************************************/
+
+
+	RegisterOption("BspTree.Construction.input",
+		optString,
+		"bsp_construction_input=",
+		"fromViewCells");
+
+	RegisterOption("BspTree.Construction.samples",
+		optInt,
+		"bsp_construction_samples=",
+		"100000");
+
+	RegisterOption("BspTree.Construction.epsilon",
+		optFloat,
+		"bsp_construction_side_tolerance=",
+		"0.002");
+
+	RegisterOption("BspTree.Termination.minPolygons",
+			optInt,
+			"bsp_term_min_polygons=",
+			"5");
+
+	RegisterOption("BspTree.Termination.minPvs",
+			optInt,
+			"bsp_term_min_pvs=",
+			"20");
+
+	RegisterOption("BspTree.Termination.minArea",
+			optFloat,
+			"bsp_term_min_area=",
+			"0.001");
+
+	RegisterOption("BspTree.Termination.maxRayContribution",
+			optFloat,
+			"bsp_term_ray_contribution=",
+			"0.005");
+
+	RegisterOption("BspTree.Termination.minAccRayLenght",
+			optFloat,
+			"bsp_term_min_acc_ray_length=",
+			"50");
+
+	RegisterOption("BspTree.Termination.minRays",
+			optInt,
+			"bsp_term_min_rays=",
+			"-1");
+
+	RegisterOption("BspTree.Termination.ct_div_ci",
+			optFloat,
+			"bsp_term_ct_div_ci=",
+			"0.0");
+
+	RegisterOption("BspTree.Termination.maxDepth",
+			optInt,
+			"bsp_term_max_depth=",
+			"100");
+
+	RegisterOption("BspTree.Termination.maxCostRatio",
+			optFloat,
+			"bsp_term_axis_aligned_max_cost_ratio=",
+			"1.5");
+
+	RegisterOption("BspTree.Termination.AxisAligned.ct_div_ci",
+			optFloat,
+			"bsp_term_axis_aligned_ct_div_ci=",
+			"0.5");
+
+	RegisterOption("BspTree.AxisAligned.splitBorder",
+			optFloat,
+			"bsp__axis_aligned_split_border=",
+			"0.1");
+
+	RegisterOption("BspTree.Termination.AxisAligned.minPolys",
+			optInt,
+			"bsp_term_axis_aligned_max_polygons=",
+			"50");
+
+	RegisterOption("BspTree.Termination.AxisAligned.minObjects",
+			optInt,
+			"bsp_term_min_objects=",
+			"3");
+
+	RegisterOption("BspTree.Termination.AxisAligned.minRays",
+			optInt,
+			"bsp_term_axis_aligned_min_rays=",
+			"-1");
+
+	RegisterOption("BspTree.splitPlaneStrategy",
+			optString,
+			"bsp_split_method=",
+			"leastSplits");
+
+	RegisterOption("BspTree.maxPolyCandidates",
+		optInt,
+		"bsp_max_poly_candidates=",
+		"20");
+
+	RegisterOption("BspTree.maxRayCandidates",
+		optInt,
+		"bsp_max_plane_candidates=",
+		"20");
+
+	RegisterOption("BspTree.maxTests",
+		optInt,
+		"bsp_max_tests=",
+		"5000");
+
+	RegisterOption("BspTree.Visualization.exportSplits",
+		optBool,
+		"bsp_visualization.export_splits",
+		"false");
+
+	RegisterOption("BspTree.Factor.verticalSplits", optFloat, "bsp_factor_vertical=", "1.0");
+	RegisterOption("BspTree.Factor.largestPolyArea", optFloat, "bsp_factor_largest_poly=", "1.0");
+	RegisterOption("BspTree.Factor.blockedRays", optFloat, "bsp_factor_blocked=", "1.0");
+	RegisterOption("BspTree.Factor.leastSplits", optFloat, "bsp_factor_least_splits=", "1.0");
+	RegisterOption("BspTree.Factor.balancedPolys", optFloat, "bsp_factor_balanced_polys=", "1.0");
+	RegisterOption("BspTree.Factor.balancedViewCells", optFloat, "bsp_factor_balanced_view_cells=", "1.0");
+	RegisterOption("BspTree.Factor.leastRaySplits", optFloat, "bsp_factor_least_ray_splits=", "1.0");
+	RegisterOption("BspTree.Factor.balancedRays", optFloat, "bsp_factor_balanced_rays=", "1.0");
+	RegisterOption("BspTree.Factor.pvs", optFloat, "bsp_factor_pvs=", "1.0");
+
+	/************************************************************************************/
+	/*                         Preprocessor related options                             */
+	/************************************************************************************/
+
+	RegisterOption("Preprocessor.type",
+					optString,
+					"preprocessor=",
+					"sampling");
+
+	RegisterOption("Preprocessor.samplesFilename",
+					optString,
+					"-preprocessor_samples_filename=",
+					"rays.out");
+
+	RegisterOption("Preprocessor.useGlRenderer",
+					optBool,
+					"useGlRenderer",
+					"false");
+
+	/**************************************************************************************/
+	/*                  View space partition KD tree related options                      */
+	/**************************************************************************************/
+
+	RegisterOption("VspKdTree.Construction.samples",
+					optInt,
+					"vsp_kd_construction_samples=",
+					"100000");
+
+	RegisterOption("VspKdTree.Termination.maxDepth", 
+		optInt, 
+		"vsp_term_maxdepth=", "30");
+
+	RegisterOption("VspKdTree.Termination.minPvs", 
+		optInt, 
+		"vsp_minpvs=", 
+		"1");
+
+	RegisterOption("VspKdTree.Termination.minRays", 
+		optInt, 
+		"vsp_term_minrays=", 
+		"10");
+
+	RegisterOption("VspKdTree.Termination.minSize", 
+		optFloat, 
+		"vsp_term_minsize=", 
+		"0.001");
+
+	RegisterOption("VspKdTree.Termination.maxCostRatio", 
+		optFloat, 
+		"vsp_term_maxcost=",
+		"0.95");
+
+	RegisterOption("VspKdTree.Termination.maxRayContribution", 
+		optFloat, 
+		"vsp_term_max_ray_contrib=", 
+		"0.5");
+
+	RegisterOption("VspKdTree.epsilon", 
+		optFloat, 
+		"kd_eps=", 
+		"1e-6");
+
+	RegisterOption("VspKdTree.ct_div_ci", 
+		optFloat, 
+		"vsp_ctdivci=", "1.0");
+
+	RegisterOption("VspKdTree.splitType", 
+		optString, 
+		"split=", 
+		"queries");
+
+	RegisterOption("VspKdTree.splitAxis", 
+		optString, 
+		"split=", 
+		"drivingAxis");
+
+	RegisterOption("VspKdTree.splitUseOnlyDrivingAxis", 
+		optBool, 
+		"vsp_kd_splitdriving=", 
+		"false");
 
 	RegisterOption("VspKdTree.numberOfEndPointDomains", 
@@ -1535,7 +1540,7 @@
 
 	RegisterOption("VspKdTree.Termination.missTolerance",
-		 optInt,
-		 "-vsp_kd_term_miss_tolerance=",
-		 "4");
+			optInt,
+			"-vsp_kd_term_miss_tolerance=",
+			"4");
 
 	/************************************************************************************/
@@ -1582,33 +1587,33 @@
 
 	RegisterOption("RssPreprocessor.vssSamples",
-				   optInt,
-				   "rss_vss_samples=",
-				   "1000000");
-	
+					optInt,
+					"rss_vss_samples=",
+					"1000000");
+
 	RegisterOption("RssPreprocessor.vssSamplesPerPass",
-				   optInt,
-				   "rss_vss_samples_per_pass=",
-				   "1000");
-	
+					optInt,
+					"rss_vss_samples_per_pass=",
+					"1000");
+
 	RegisterOption("RssPreprocessor.samplesPerPass",
-				   optInt,
-				   "rss_samples_per_pass=",
-				   "100000");
-	
+					optInt,
+					"rss_samples_per_pass=",
+					"100000");
+
 	RegisterOption("RssPreprocessor.useImportanceSampling",
-				   optBool,
-				   "rss_use_importance",
-				   "true");
-	
+					optBool,
+					"rss_use_importance",
+					"true");
+
 	RegisterOption("RssPreprocessor.objectBasedSampling",
-				   optBool,
-				   "rss_object_based_sampling",
-				   "true");
-	
+					optBool,
+					"rss_object_based_sampling",
+					"true");
+
 	RegisterOption("RssPreprocessor.directionalSampling",
-				   optBool,
-				   "rss_directional_sampling",
-				   "false");
-	
+					optBool,
+					"rss_directional_sampling",
+					"false");
+
 	RegisterOption("RssTree.maxDepth", optInt, "kd_depth=", "12");
 	RegisterOption("RssTree.minPvs", optInt, "kd_minpvs=", "1");
@@ -1616,5 +1621,5 @@
 	RegisterOption("RssTree.maxCostRatio", optFloat, "maxcost=", "0.95");
 	RegisterOption("RssTree.maxRayContribution", optFloat, "maxraycontrib=", "0.5");
-	
+
 	RegisterOption("RssTree.epsilon", optFloat, "kd_eps=", "1e-6");
 	RegisterOption("RssTree.ct_div_ci", optFloat, "kd_ctdivci=", "1.0");
@@ -1622,14 +1627,14 @@
 	RegisterOption("RssTree.splitType", optString, "split=", "queries");
 	RegisterOption("RssTree.splitUseOnlyDrivingAxis", optBool, "splitdriving=", "false");
-	
+
 	RegisterOption("RssTree.numberOfEndPointDomains", optInt, "endpoints=", "10000");
-	
+
 	RegisterOption("RssTree.minSize", optFloat, "minsize=", "0.001");
-	
+
 	RegisterOption("RssTree.maxTotalMemory", optFloat, "mem=", "60.0");
 	RegisterOption("RssTree.maxStaticMemory", optFloat, "statmem=", "8.0");
-	
+
 	RegisterOption("RssTree.queryType", optString, "qtype=", "static");
-	
+
 	RegisterOption("RssTree.queryPosWeight", optFloat, "qposweight=", "0.0");
 	RegisterOption("RssTree.useRefDirSplits", optBool, "refdir", "false");
@@ -1638,10 +1643,10 @@
 	RegisterOption("RssTree.accessTimeThreshold", optInt, "accesstime=", "1000");
 	RegisterOption("RssTree.minCollapseDepth", optInt, "colldepth=", "4");
-	
+
 	RegisterOption("RssTree.interleaveDirSplits", optBool, "interleavedirsplits", "true");
 	RegisterOption("RssTree.dirSplitDepth", optInt, "dirsplidepth=", "10");
 	RegisterOption("RssTree.importanceBasedCost", optBool, "importance_based_cost", "true");
 	RegisterOption("RssTree.maxRays", optInt, "rss_max_rays=", "2000000");
-	
+
 	RegisterOption("RssPreprocessor.Export.pvs", optBool, "rss_export_pvs", "false");
 	RegisterOption("RssPreprocessor.Export.rssTree", optBool, "rss_export_rss_tree", "false");
@@ -1650,62 +1655,65 @@
 	RegisterOption("RssPreprocessor.useViewcells", optBool, "rss_use_viewcells", "false");
 	RegisterOption("RssPreprocessor.updateSubdivision", optBool, "rss_update_subdivision", "false");
-	
-	
-  /************************************************************************************/
-  /*               View space partition BSP tree related options                      */
-  /************************************************************************************/
+
+
+/************************************************************************************/
+/*               View space partition BSP tree related options                      */
+/************************************************************************************/
 
 
 	RegisterOption("RssPreprocessor.loadInitialSamples",
-				   optBool,
-				   "vss_load_loadInitialSamples=",
-				   "false");
+					optBool,
+					"vss_load_loadInitialSamples=",
+					"false");
 
 	RegisterOption("RssPreprocessor.storeInitialSamples",
-				   optBool,
-				   "vss_store_storeInitialSamples=",
-				   "false");
-
-	/************************************************************************************/
-	/*               View space partition BSP tree related options                      */
-	/************************************************************************************/
+					optBool,
+					"vss_store_storeInitialSamples=",
+					"false");
+
+
+/************************************************************************************/
+/*               View space partition BSP tree related options                      */
+/************************************************************************************/
+
+
 	RegisterOption("VspBspTree.Termination.minPolygons",
-				   optInt,
-				   "vsp_bsp_term_min_polygons=",
-				   "5");
+					optInt,
+					"vsp_bsp_term_min_polygons=",
+					"5");
 
 	RegisterOption("VspBspTree.Termination.minPvs",
-				   optInt,
-				   "vsp_bsp_term_min_pvs=",
-				   "20");
+					optInt,
+					"vsp_bsp_term_min_pvs=",
+					"20");
 	RegisterOption("VspBspTree.Termination.minArea",
-				   optFloat,
-				   "vsp_bsp_term_min_area=",
-				   "0.001");
+					optFloat,
+					"vsp_bsp_term_min_area=",
+					"0.001");
 
 	RegisterOption("VspBspTree.Termination.maxRayContribution",
-				   optFloat,
-				   "vsp_bsp_term_ray_contribution=",
-				   "0.005");
+					optFloat,
+					"vsp_bsp_term_ray_contribution=",
+					"0.005");
 
 	RegisterOption("VspBspTree.Termination.minAccRayLenght",
-				   optFloat,
-				   "vsp_bsp_term_min_acc_ray_length=",
-				   "50");
+					optFloat,
+					"vsp_bsp_term_min_acc_ray_length=",
+					"50");
 
 	RegisterOption("VspBspTree.Termination.minRays",
-				   optInt,
-				   "vsp_bsp_term_min_rays=",
-				   "-1");
+					optInt,
+					"vsp_bsp_term_min_rays=",
+					"-1");
 
 	RegisterOption("VspBspTree.Termination.ct_div_ci",
-				   optFloat,
-				   "vsp_bsp_term_ct_div_ci=",
-				   "0.0");
+					optFloat,
+					"vsp_bsp_term_ct_div_ci=",
+					"0.0");
 
 	RegisterOption("VspBspTree.Termination.maxDepth",
-				   optInt,
-				   "vsp_bsp_term_max_depth=",
-				   "100");
+					optInt,
+					"vsp_bsp_term_max_depth=",
+					"100");
 
 	RegisterOption("VspBspTree.Termination.AxisAligned.maxCostRatio",
@@ -1725,46 +1733,56 @@
 
 	RegisterOption("VspBspTree.Termination.missTolerance",
-				   optInt,
-				   "vsp_bsp_term_miss_tolerance=",
-				   "4");
+					optInt,
+					"vsp_bsp_term_miss_tolerance=",
+					"4");
 	RegisterOption("VspBspTree.splitPlaneStrategy",
-				   optString,
-				   "vsp_bsp_split_method=",
-				   "leastSplits");
+					optString,
+					"vsp_bsp_split_method=",
+					"leastSplits");
 
 	RegisterOption("VspBspTree.maxPolyCandidates",
-				   optInt,
-				   "vsp_bsp_max_poly_candidates=",
-				   "20");
+					optInt,
+					"vsp_bsp_max_poly_candidates=",
+					"20");
 	RegisterOption("VspBspTree.maxRayCandidates",
-				   optInt,
-				   "vsp_bsp_max_plane_candidates=",
-				   "20");
+					optInt,
+					"vsp_bsp_max_plane_candidates=",
+					"20");
 
 	RegisterOption("VspBspTree.maxTests",
-				   optInt,
-				   "vsp_bsp_max_tests=",
-				   "5000");
+					optInt,
+					"vsp_bsp_max_tests=",
+					"5000");
 
 	RegisterOption("VspBspTree.Construction.samples",
-				   optInt,
-				   "bsp_construction_samples=",
-				   "100000");
+					optInt,
+					"bsp_construction_samples=",
+					"100000");
 
 	RegisterOption("VspBspTree.Construction.epsilon",
-				   optFloat,
-				   "vsp_bsp_construction_side_tolerance=",
-				   "0.002");
+					optFloat,
+					"vsp_bsp_construction_side_tolerance=",
+					"0.002");
 
 	RegisterOption("VspBspTree.Visualization.exportSplits",
-				   optBool,
-				   "vsp_bsp_visualization.export_splits",
-				   "false");
+					optBool,
+					"vsp_bsp_visualization.export_splits",
+					"false");
+
+	RegisterOption("VspBspTree.splitUseOnlyDrivingAxis", 
+					optBool, 
+					"vsp_bsp_splitdriving=", 
+					"false");
+
+	RegisterOption("VspBspTree.Termination.AxisAligned.minRays",
+			optInt,
+			"bsp_term_axis_aligned_min_rays=",
+			"100");
 	
-	RegisterOption("VspBspTree.splitUseOnlyDrivingAxis", 
-				   optBool, 
-				   "vsp_bsp_splitdriving=", 
-				   "false");
-	
+	RegisterOption("VspBspTree.Termination.AxisAligned.maxRayContribution",
+			optFloat,
+			"bsp_term_axis_aligned_min_rays=",
+			"0.1");
+
 	RegisterOption("VspBspTree.Factor.leastRaySplits", optFloat, "-vsp_bsp_factor_least_ray_splits=", "1.0");
 	RegisterOption("VspBspTree.Factor.balancedRays", optFloat, "-vsp_bsp_factor_balanced_rays=", "1.0");
@@ -1785,5 +1803,5 @@
 		"vsp_bsp_term_post_process_max_pvs_size=", 
 		"100");
-	
+
 	RegisterOption("VspBspTree.PostProcess.useRaysForMerge", 
 		optBool, 
@@ -1795,4 +1813,15 @@
 		"vsp_bsp_construction_randomize=", 
 		"false");
+
+	
+	RegisterOption("VspBspTree.maxTotalMemory", 
+		optFloat, 
+		"vsp_bsp_max_total_mem=", 
+		"60.0");
+
+	RegisterOption("VspBspTree.maxStaticMemory", 
+		optFloat, 
+		"vsp_bsp_max_static_mem=", 
+		"8.0");
 	//////////////////////////////////////////////////////////////////////////////////
 }
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 503)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 508)
@@ -2527,4 +2527,14 @@
 
 
+BspNodeGeometry::BspNodeGeometry(const BspNodeGeometry &rhs)
+{
+	PolygonContainer::const_iterator it, it_end = rhs.mPolys.end();
+	for (it = rhs.mPolys.begin(); it != it_end; ++ it)
+	{
+		Polygon3 *poly = *it;
+		mPolys.push_back(new Polygon3(*poly));
+	}
+}
+
 BspNodeGeometry::~BspNodeGeometry()
 {
@@ -2542,23 +2552,8 @@
 {
 	PolygonContainer::const_iterator it, it_end = mPolys.end();
-	int vcount = 0;
-
+	
 	for (it = mPolys.begin(); it != mPolys.end(); ++ it)
 	{
-		Polygon3 *poly = *it;
-		
-		vector<Triangle3> triangles;
-		poly->Triangulate(triangles);
-		vector<Triangle3>::const_iterator tit, tit_end = triangles.end();
-	
-		for (tit = triangles.begin(); tit != tit_end; ++ tit)
-		{
-			mesh.mVertices.push_back((*tit).mVertices[0]);
-			mesh.mVertices.push_back((*tit).mVertices[1]);
-			mesh.mVertices.push_back((*tit).mVertices[2]);
-
-			Face *face = new Face(vcount ++, vcount ++, vcount ++);
-			mesh.AddFace(face);
-		}
+		(*it)->AddToMesh(mesh);
 	}
 }
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 496)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 508)
@@ -59,9 +59,8 @@
 Preprocessor::LoadScene(const string filename)
 {
-  // use leaf nodes of the original spatial hiearrchy as occludees
-
-  mSceneGraph = new SceneGraph;
+	// use leaf nodes of the original spatial hiearrchy as occludees
+	mSceneGraph = new SceneGraph;
   
-  Parser *parser;
+	Parser *parser;
 	vector<string> filenames;
 	int files = SplitFilenames(filename, filenames);
@@ -176,4 +175,5 @@
 }
 
+
 bool Preprocessor::PrepareViewCells()
 {
@@ -257,5 +257,5 @@
 		environment->GetStringValue("ViewCells.filename", buff);
 		string vcFilename(buff);
-		mViewCellsManager->LoadViewCells(vcFilename);
+		mViewCellsManager->LoadViewCells(vcFilename, &mObjects);
 	}
 
@@ -364,5 +364,6 @@
 }
 
-bool Preprocessor::WriteSamples(const VssRayContainer &samples) const
+
+bool Preprocessor::ExportSamples(const VssRayContainer &samples) const
 {
 	char fileName[100];
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/RssPreprocessor.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/RssPreprocessor.cpp	(revision 504)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/RssPreprocessor.cpp	(revision 508)
@@ -580,5 +580,5 @@
 	cout << "#totalRayStackSize=" << (int)mVssRays.size() << endl <<flush;
 	
-	rssSamples += mVssRays.size();
+	rssSamples += (int)mVssRays.size();
 	
 	
@@ -592,5 +592,5 @@
 	  {
 		cout << "Writing samples to file ... ";
-		WriteSamples(mVssRays);
+		ExportSamples(mVssRays);
 		cout << "finished\n" << endl;
 	  }
@@ -731,5 +731,5 @@
 	  VssRayContainer contributingRays;
 	  vssRays.GetContributingRays(contributingRays, mPass);
-	  mStats<<"#NUM_CONTRIBUTING_RAYS\n"<<contributingRays.size()<<endl;
+	  mStats<<"#NUM_CONTRIBUTING_RAYS\n"<<(int)contributingRays.size()<<endl;
 	  sprintf(filename, "rss-crays-%04d.x3d", rssPass);
 	  ExportRays(filename, contributingRays, mExportNumRays);
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/VssPreprocessor.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/VssPreprocessor.cpp	(revision 501)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/VssPreprocessor.cpp	(revision 508)
@@ -29,4 +29,5 @@
   environment->GetBoolValue("VssPreprocessor.storeInitialSamples", mStoreInitialSamples);
   environment->GetBoolValue("VssPreprocessor.useViewSpaceBox", mUseViewSpaceBox);
+  useViewspacePlane = mUseViewSpaceBox; //hack
 
   mStats.open("stats.log");
@@ -473,5 +474,5 @@
   {
 	  cout << "Writing " << (int)mVssRays.size() << " samples to file ... ";
-	  WriteSamples(mVssRays);
+	  ExportSamples(mVssRays);
 	  cout << "finished\n" << endl;
 
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsParserXerces.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsParserXerces.h	(revision 508)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsParserXerces.h	(revision 508)
@@ -0,0 +1,148 @@
+#ifndef _X3D_PARSER_XERCES__H
+#define _X3D_PARSER_XERCES__H
+
+// ---------------------------------------------------------------------------
+//  Includes
+// ---------------------------------------------------------------------------
+#include <xercesc/sax/HandlerBase.hpp>
+#include "Mesh.h"
+
+XERCES_CPP_NAMESPACE_USE
+XERCES_CPP_NAMESPACE_BEGIN
+class AttributeList;
+XERCES_CPP_NAMESPACE_END
+
+class VspBspTree;
+class ViewCellsManager;
+
+class ViewCellsParseHandlers: public HandlerBase
+{
+public:
+  // -----------------------------------------------------------------------
+  //  Constructors and Destructor
+  // -----------------------------------------------------------------------
+  ViewCellsParseHandlers(VspBspTree *tree, 
+						 ViewCellsManager *viewCellsManager,
+						 ObjectContainer *objects);
+  ~ViewCellsParseHandlers();
+  
+  
+  // -----------------------------------------------------------------------
+  //  Getter methods
+  // -----------------------------------------------------------------------
+  unsigned int GetElementCount()
+  {
+    return mElementCount;
+  }
+  
+  unsigned int GetAttrCount()
+  {
+    return mAttrCount;
+  }
+  
+  unsigned int GetCharacterCount()
+  {
+    return mCharacterCount;
+  }
+  
+  unsigned int GetSpaceCount()
+  {
+    return mSpaceCount;
+  }
+
+
+  // -----------------------------------------------------------------------
+  //  Handlers for the SAX DocumentHandler interface
+  // -----------------------------------------------------------------------
+  void endElement(const XMLCh* const name);
+  void startElement(const XMLCh* const name, AttributeList& attributes);
+  void characters(const XMLCh* const chars, const unsigned int length);
+  void ignorableWhitespace(const XMLCh* const chars, const unsigned int length);
+  void resetDocument();
+
+  VspBspTree *mVspBspTree;
+  BspNode *mCurrentNode;
+  ViewCellContainer mViewCells;
+  ViewCellsManager *mViewCellsManager;
+  ObjectContainer *mObjects;
+
+  // Handlers for X3D
+  void StartLeaf(AttributeList& attributes);
+  void StartInterior(AttributeList& attributes);
+  void EndInterior();
+ 
+  void StartViewCell(AttributeList&  attributes);
+  void EndViewCells();
+
+  // -----------------------------------------------------------------------
+  //  Handlers for the SAX ErrorHandler interface
+  // -----------------------------------------------------------------------
+  void warning(const SAXParseException& exc);
+  void error(const SAXParseException& exc);
+  void fatalError(const SAXParseException& exc);
+  
+  
+private:
+  // -----------------------------------------------------------------------
+  //  Private data members
+  //
+  //  fAttrCount
+  //  fCharacterCount
+  //  fElementCount
+  //  fSpaceCount
+  //      These are just counters that are run upwards based on the input
+  //      from the document handlers.
+  // -----------------------------------------------------------------------
+  unsigned int    mAttrCount;
+  unsigned int    mCharacterCount;
+  unsigned int    mElementCount;
+  unsigned int    mSpaceCount;
+};
+
+// ---------------------------------------------------------------------------
+//  This is a simple class that lets us do easy (though not terribly efficient)
+//  trancoding of XMLCh data to local code page for display.
+// ---------------------------------------------------------------------------
+class StrX
+{
+public :
+  // -----------------------------------------------------------------------
+  //  Constructors and Destructor
+  // -----------------------------------------------------------------------
+  StrX(const XMLCh* const toTranscode)
+  {
+	  // Call the private transcoding method
+	  mLocalForm = XMLString::transcode(toTranscode);
+  }
+  
+  ~StrX()
+  {
+	  XMLString::release(&mLocalForm);
+  }
+  
+  // -----------------------------------------------------------------------
+  //  Getter methods
+  // -----------------------------------------------------------------------
+  const char* LocalForm() const
+  {
+    return mLocalForm;
+  }
+  
+private :
+  // -----------------------------------------------------------------------
+  //  Private data members
+  //
+  //  fLocalForm
+  //      This is the local code page form of the string.
+  // -----------------------------------------------------------------------
+  char*   mLocalForm;
+};
+
+inline XERCES_STD_QUALIFIER ostream&
+operator<<(XERCES_STD_QUALIFIER ostream& target, const StrX& toDump)
+{
+  target << toDump.LocalForm();
+  return target;
+}
+
+#endif
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.h	(revision 496)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.h	(revision 508)
@@ -96,5 +96,6 @@
 	  @returns true if samples were written successfully
   */
-  bool WriteSamples(const VssRayContainer &samples) const;
+  bool ExportSamples(const VssRayContainer &samples) const;
+
   /// scene graph loaded from file
   SceneGraph *mSceneGraph;
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/RayInfo.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/RayInfo.cpp	(revision 485)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/RayInfo.cpp	(revision 508)
@@ -139,12 +139,15 @@
 	// non-intersecting, otherwise polygon-plane intersections of bsp tree
 	// approaches are not eliminating any rays intersecting the polygon!
-
-	//if (t > GetMaxT())
+#if 1
 	if (t >= GetMaxT() - 1e-20)
 		return splitPlane.Side(ExtrapOrigin());
-	//if (t < GetMinT())
 	if (t <= GetMinT() + 1e-20)
 		return splitPlane.Side(ExtrapTermination());
-
+#else
+	if (t > GetMaxT())
+		return splitPlane.Side(ExtrapOrigin());
+	else if (t < GetMinT())
+		return splitPlane.Side(ExtrapTermination());
+#endif
 	return 0;
 }
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.cpp	(revision 503)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.cpp	(revision 508)
@@ -477,5 +477,5 @@
 	int i = 1;
 	int j = 0;
-	int k = mVertices.size() - 1;
+	int k = (int)mVertices.size() - 1;
 	int count = 0;
 
@@ -490,2 +490,57 @@
 	}
 }
+
+
+void Polygon3::Triangulate(VertexIndexContainer &indices)
+{
+	int i = 1;
+	int j = 0;
+	int k = (int)mVertices.size() - 1;
+
+	int count = 0;
+
+	while (i < k)
+	{
+		indices.push_back(k);
+		indices.push_back(j);
+		indices.push_back(i);
+
+		if ((count ++) % 2)
+			j = i ++;
+		else
+			j = k --;
+	}
+}
+
+
+void Polygon3::AddToMesh(Mesh &mesh)
+{
+	const int n = (int)mesh.mVertices.size();
+
+    //-- add the vertices
+    VertexContainer::const_iterator vit, vit_end = mVertices.end();
+	for (vit = mVertices.begin(); vit != vit_end; ++ vit)
+	{
+		mesh.mVertices.push_back(*vit);
+	}
+
+	// one quad => no triangulation necessary
+	if ((int)mVertices.size() == 4)
+	{
+		mesh.AddFace(new Face(n, n + 1, n + 2, n + 3));
+	}
+	else
+	{
+		VertexIndexContainer indices;
+		Triangulate(indices);
+
+		// add indices of triangle strip
+		for (int i = 0; i < (int)indices.size(); i += 3)
+		{
+			Face *face = new Face(n + indices[i], 
+								  n + indices[i + 1], 
+								  n + indices[i + 2]);
+			mesh.AddFace(face);
+		}
+	}
+}
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsParser.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsParser.cpp	(revision 508)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsParser.cpp	(revision 508)
@@ -0,0 +1,472 @@
+// ---------------------------------------------------------------------------
+//  Includes for all the program files to see
+// ---------------------------------------------------------------------------
+#include <string.h>
+#include <stdlib.h>
+#include <iostream>
+using namespace std;
+#include <xercesc/util/PlatformUtils.hpp>
+
+// ---------------------------------------------------------------------------
+//  Includes
+// ---------------------------------------------------------------------------
+#include <xercesc/framework/StdInInputSource.hpp>
+#include <xercesc/parsers/SAXParser.hpp>
+#include <xercesc/util/OutOfMemoryException.hpp>
+
+// ---------------------------------------------------------------------------
+//  Includes
+// ---------------------------------------------------------------------------
+#include <xercesc/sax/AttributeList.hpp>
+#include <xercesc/sax/SAXParseException.hpp>
+#include <xercesc/sax/SAXException.hpp>
+
+#include "ViewCellsParser.h"
+
+#include "ViewCellsParserXerces.h"
+#include "Mesh.h"
+#include "VspBspTree.h"
+#include "ViewCellBsp.h"
+#include "ViewCellsManager.h"
+
+// ---------------------------------------------------------------------------
+//  Local data
+//
+//  doNamespaces
+//      Indicates whether namespace processing should be enabled or not.
+//      The default is no, but -n overrides that.
+//
+//  doSchema
+//      Indicates whether schema processing should be enabled or not.
+//      The default is no, but -s overrides that.
+//
+//  schemaFullChecking
+//      Indicates whether full schema constraint checking should be enabled or not.
+//      The default is no, but -s overrides that.
+//
+//  valScheme
+//      Indicates what validation scheme to use. It defaults to 'auto', but
+//      can be set via the -v= command.
+// ---------------------------------------------------------------------------
+static bool     doNamespaces       = false;
+static bool     doSchema           = false;
+static bool     schemaFullChecking = false;
+static SAXParser::ValSchemes    valScheme       = SAXParser::Val_Auto;
+
+
+
+
+
+// ---------------------------------------------------------------------------
+//  StdInParseHandlers: Constructors and Destructor
+// ---------------------------------------------------------------------------
+ViewCellsParseHandlers::ViewCellsParseHandlers(VspBspTree *tree,
+											   ViewCellsManager *viewCells,
+											   ObjectContainer *objects):
+  mElementCount(0)
+  , mAttrCount(0)
+  , mCharacterCount(0)
+  , mSpaceCount(0)
+{
+	mVspBspTree = tree;
+	mCurrentNode = tree->GetRoot();
+	mViewCellsManager = viewCells;
+	mObjects = objects;
+}
+
+ViewCellsParseHandlers::~ViewCellsParseHandlers()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+//  StdInParseHandlers: Implementation of the SAX DocumentHandler interface
+// ---------------------------------------------------------------------------
+
+
+void ViewCellsParseHandlers::endElement(const XMLCh* const name)
+{
+  StrX lname(name);
+  string element(lname.LocalForm());
+  if (element == "Interior")
+	  EndInterior();
+  if (element == "ViewCells")
+	  EndViewCells();
+}
+
+
+void ViewCellsParseHandlers::EndInterior()
+{
+	// go one up in the tree
+	if (mCurrentNode->GetParent())
+	{	cout << "]";
+		mCurrentNode = mCurrentNode->GetParent();
+	}
+}
+
+
+inline bool vlt(ViewCell *v1, ViewCell *v2)
+{
+	return v1->mId < v2->mId;
+}
+
+
+void ViewCellsParseHandlers::EndViewCells()
+{
+	// sort view cells for easily finding id
+	stable_sort(mViewCells.begin(), mViewCells.end(), vlt);
+}
+
+
+void ViewCellsParseHandlers::startElement(const XMLCh* const name,
+										  AttributeList& attributes)
+{
+	StrX lname(name);
+	string element(lname.LocalForm());
+	
+	if (element == "ViewCell")
+	{
+		cout << "v";
+		StartViewCell(attributes);
+	}
+
+	if (element == "Interior") 
+	{
+		cout << "[";
+		StartInterior(attributes);
+	}
+
+	if (element == "Leaf") 
+	{
+		StartLeaf(attributes);
+	}
+
+	++ mElementCount;
+	mAttrCount += attributes.getLength();
+}
+
+
+inline bool ilt(Intersectable *obj1, Intersectable *obj2)
+{
+	return obj1->mId < obj2->mId;
+}
+
+
+void ViewCellsParseHandlers::StartViewCell(AttributeList&  attributes)
+{
+	int len = attributes.getLength();
+	vector<int> objIndices;
+  
+	ViewCell *viewCell = mViewCellsManager->GenerateViewCell();
+	mViewCells.push_back(viewCell);
+
+	for (int i = 0; i < len; ++ i) 
+	{
+		string attrName(StrX(attributes.getName(i)).LocalForm());
+		
+		if (attrName == "pvs") 
+		{
+			StrX attrValue(attributes.getValue(i));
+			
+			// handle coordIndex
+			objIndices.clear();
+			const char *ptr = attrValue.LocalForm();
+			char *endptr;
+			
+			while (1)
+			{
+				int index = strtol(ptr, &endptr, 10);
+
+				if (ptr == endptr)
+					break;
+
+				objIndices.push_back(index);
+
+				ptr = endptr;
+			}
+
+			//TODO: find objects and add them to pvs
+			// TODO: get view cell with specified id
+			MeshInstance dummyInst(NULL);
+
+			vector<int>::const_iterator it, it_end = objIndices.end();
+			for (it = objIndices.begin(); it != it_end; ++ it)
+			{
+				const int objId = *it;	
+				dummyInst.SetId(objId);
+
+				ObjectContainer::iterator oit =
+					lower_bound(mObjects->begin(), mObjects->end(), &dummyInst, ilt);
+			
+				Intersectable *obj = *oit;
+				
+				if (obj->GetId() == objId)
+				{
+					viewCell->GetPvs().AddSample(obj);
+				}
+				else
+				{
+					Debug << "error: object does not exist" << endl;
+				}
+			}
+		}
+		else if (attrName == "id") 
+		{
+			StrX attrValue(attributes.getValue(i));
+			
+			const char *ptr = attrValue.LocalForm();
+			char *endptr = NULL;
+			const int id = strtol(ptr, &endptr, 10);
+
+			viewCell->SetId(id);
+		}
+	}
+}
+
+
+void ViewCellsParseHandlers::StartLeaf(AttributeList& attributes)
+{
+	BspLeaf * leaf = 
+		new BspLeaf(dynamic_cast<BspInterior *>(mCurrentNode), NULL);
+
+	if (mCurrentNode) // replace front or (if not NULL) back child
+	{
+		dynamic_cast<BspInterior *>(mCurrentNode)->ReplaceChildLink(NULL, leaf);
+	}
+	else
+	{
+		mVspBspTree->mRoot = leaf;
+	}
+
+	//-- find associated view cell
+	int viewCellId;
+	
+	int len = attributes.getLength();
+	  
+	for (int i = 0; i < len; ++ i) 
+	{
+		string attrName(StrX(attributes.getName(i)).LocalForm());
+		StrX attrValue(attributes.getValue(i));
+
+		const char *ptr = attrValue.LocalForm();
+		char *endptr = NULL;
+
+		if (attrName == "viewCellId") 
+		{
+			viewCellId = strtol(ptr, &endptr, 10);
+		}
+	}
+
+	if (viewCellId >= 0) // valid view cell
+	{
+		// TODO: get view cell with specified id
+		ViewCell dummyVc;
+		dummyVc.SetId(viewCellId);
+
+		ViewCellContainer::iterator vit =
+			lower_bound(mViewCells.begin(), mViewCells.end(), &dummyVc, vlt);
+			
+		BspViewCell *viewCell = dynamic_cast<BspViewCell *>(*vit);
+		if (viewCell->GetId() == viewCellId)
+		{
+			leaf->SetViewCell(viewCell);
+		}
+		else
+		{
+			Debug << "error: view cell does not exist" << endl;
+		}
+	}
+	else
+	{
+		leaf->SetViewCell(mVspBspTree->GetOrCreateOutOfBoundsCell());
+		leaf->SetTreeValid(false);
+		mVspBspTree->PropagateUpValidity(leaf);
+	}
+}
+
+
+void ViewCellsParseHandlers::StartInterior(AttributeList& attributes)
+{
+	Plane3 plane;
+	int len = attributes.getLength();
+
+	for (int i = 0; i < len; ++ i) 
+	{
+		string attrName(StrX(attributes.getName(i)).LocalForm());
+		StrX attrValue(attributes.getValue(i));
+		const char *ptr = attrValue.LocalForm();
+
+		if (attrName == "plane") 
+		{
+			sscanf(ptr, "%f %f %f %f",
+				   &plane.mNormal.x, &plane.mNormal.y, &plane.mNormal.z, &plane.mD);
+		}
+	}
+
+	BspInterior* interior = new BspInterior(plane);
+	
+	if (mCurrentNode) // replace NULL child of parent with current node
+	{
+		BspInterior *current = dynamic_cast<BspInterior *>(mCurrentNode);
+
+		current->ReplaceChildLink(NULL, interior);
+		interior->SetParent(current);
+	}
+	else
+	{
+		mVspBspTree->mRoot = interior;
+	}
+
+	mCurrentNode = interior;
+}
+
+
+void ViewCellsParseHandlers::characters(const XMLCh* const chars,
+										const unsigned int length)
+{
+	mCharacterCount += length;
+}
+
+
+void ViewCellsParseHandlers::ignorableWhitespace(const XMLCh* const chars,
+												 const unsigned int length)
+{
+	mSpaceCount += length;
+}
+
+
+void ViewCellsParseHandlers::resetDocument()
+{
+	mAttrCount = 0;
+	mCharacterCount = 0;
+	mElementCount = 0;
+	mSpaceCount = 0;
+}
+
+
+// ---------------------------------------------------------------------------
+//  StdInParseHandlers: Overrides of the SAX ErrorHandler interface
+// ---------------------------------------------------------------------------
+void
+ViewCellsParseHandlers::error(const SAXParseException& e)
+{
+  XERCES_STD_QUALIFIER cerr << "\nError at (file " << StrX(e.getSystemId())
+			    << ", line " << e.getLineNumber()
+			    << ", char " << e.getColumnNumber()
+			    << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
+}
+
+void
+ViewCellsParseHandlers::fatalError(const SAXParseException& e)
+{
+  XERCES_STD_QUALIFIER cerr << "\nFatal Error at (file " << StrX(e.getSystemId())
+			    << ", line " << e.getLineNumber()
+			    << ", char " << e.getColumnNumber()
+			    << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
+}
+
+void
+ViewCellsParseHandlers::warning(const SAXParseException& e)
+{
+  XERCES_STD_QUALIFIER cerr << "\nWarning at (file " << StrX(e.getSystemId())
+			    << ", line " << e.getLineNumber()
+			    << ", char " << e.getColumnNumber()
+			    << "): " << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
+}
+
+
+bool ViewCellsParser::ParseFile(const string filename, 
+								VspBspTree *tree,
+								ViewCellsManager *viewCells,
+								ObjectContainer *objects)
+{
+  // Initialize the XML4C system
+  try {
+    XMLPlatformUtils::Initialize();
+  }
+  
+  catch (const XMLException& toCatch)
+    {
+      XERCES_STD_QUALIFIER cerr << "Error during initialization! Message:\n"
+				<< StrX(toCatch.getMessage()) << XERCES_STD_QUALIFIER endl;
+      return false;
+    }
+  
+  
+  //
+  //  Create a SAX parser object. Then, according to what we were told on
+  //  the command line, set the options.
+  //
+  SAXParser* parser = new SAXParser;
+  parser->setValidationScheme(valScheme);
+  parser->setDoNamespaces(doNamespaces);
+  parser->setDoSchema(doSchema);
+  parser->setValidationSchemaFullChecking(schemaFullChecking);
+  
+
+  //
+  //  Create our SAX handler object and install it on the parser, as the
+  //  document and error handler. We are responsible for cleaning them
+  //  up, but since its just stack based here, there's nothing special
+  //  to do.
+  //
+  ViewCellsParseHandlers handler(tree, viewCells, objects);
+  parser->setDocumentHandler(&handler);
+  parser->setErrorHandler(&handler);
+  
+  unsigned long duration;
+  int errorCount = 0;
+  // create a faux scope so that 'src' destructor is called before
+  // XMLPlatformUtils::Terminate
+  {
+    //
+    //  Kick off the parse and catch any exceptions. Create a standard
+    //  input input source and tell the parser to parse from that.
+    //
+    //    StdInInputSource src;
+    try
+      {
+	const unsigned long startMillis = XMLPlatformUtils::getCurrentMillis();
+	parser->parse(filename.c_str());
+	const unsigned long endMillis = XMLPlatformUtils::getCurrentMillis();
+	duration = endMillis - startMillis;
+	errorCount = parser->getErrorCount();
+      }
+    catch (const OutOfMemoryException&)
+      {
+	XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" << XERCES_STD_QUALIFIER endl;
+	errorCount = 2;
+	return false;
+      }
+    catch (const XMLException& e)
+      {
+	XERCES_STD_QUALIFIER cerr << "\nError during parsing: \n"
+				  << StrX(e.getMessage())
+				  << "\n" << XERCES_STD_QUALIFIER endl;
+	errorCount = 1;
+	return false;
+      }
+
+    
+    // Print out the stats that we collected and time taken
+    if (!errorCount) {
+      XERCES_STD_QUALIFIER cout << filename << ": " << duration << " ms ("
+				<< handler.GetElementCount() << " elems, "
+				<< handler.GetAttrCount() << " attrs, "
+				<< handler.GetSpaceCount() << " spaces, "
+				<< handler.GetCharacterCount() << " chars)" << XERCES_STD_QUALIFIER endl;
+    }
+  }
+  
+  //
+  //  Delete the parser itself.  Must be done prior to calling Terminate, below.
+  //
+  delete parser;
+  
+  XMLPlatformUtils::Terminate();
+  
+  if (errorCount > 0)
+    return false;
+  else
+    return true;
+}
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp	(revision 503)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp	(revision 508)
@@ -11,5 +11,5 @@
 #include "Exporter.h"
 #include "VspBspTree.h"
-
+#include "ViewCellsParser.h"
 
 ViewCellsManager::ViewCellsManager():
@@ -66,5 +66,5 @@
 
 
-bool ViewCellsManager::LoadViewCells(const string filename)
+bool ViewCellsManager::LoadViewCells(const string filename, ObjectContainer *objects)
 {
 	X3dParser parser;
@@ -317,6 +317,7 @@
 {
 	mViewCells.clear();
-
+	
 	CollectViewCells();
+	
 	mViewCellsStats.Reset();
 	EvaluateViewCellsStats();
@@ -328,7 +329,4 @@
 void ViewCellsManager::ComputeSampleContributions(VssRay &ray)
 {
-
-
-
   ViewCellContainer viewcells;
 
@@ -445,5 +443,12 @@
 
 
-void ViewCellsManager::ExportViewCells(Exporter *exporter) const
+void ViewCellsManager::CreateUniqueViewCellIds()
+{
+	for (int i = 0; i < (int)mViewCells.size(); ++ i)
+		mViewCells[i]->SetId(i);
+}
+
+
+void ViewCellsManager::ExportViewCellsForViz(Exporter *exporter) const
 {
 	ViewCellContainer::const_iterator it, it_end = mViewCells.end();
@@ -457,5 +462,4 @@
 
 
-
 void ViewCellsManager::CreateViewCellsMeshes()
 {
@@ -468,4 +472,27 @@
 	}
 }
+
+
+bool ViewCellsManager::ExportViewCells(const string filename) 
+{ 
+	return false;
+}
+
+
+void ViewCellsManager::ExportViewCell(ViewCell *viewCell, ofstream &stream)
+{
+	stream << "<ViewCell id=\"" << viewCell->GetId() << "\" ";
+	stream << "pvs=\"";
+
+	ObjectPvsMap::iterator it, it_end = viewCell->GetPvs().mEntries.end();
+	if(0) // test with empty pvs
+	for (it = viewCell->GetPvs().mEntries.begin(); it != it_end; ++ it)
+	{
+		stream << (*it).first->GetId() << " ";
+	}
+
+	stream << "\" />" << endl;
+}
+
 
 /**********************************************************************/
@@ -617,5 +644,5 @@
 			//exporter->SetWireframe();
 			exporter->SetFilled();
-			ExportViewCells(exporter);
+			ExportViewCellsForViz(exporter);
 
 			if (mExportGeometry)
@@ -723,5 +750,5 @@
 		if (exporter)
 		{
-			ExportViewCells(exporter);
+			ExportViewCellsForViz(exporter);
 			delete exporter;
 		}
@@ -1605,5 +1632,5 @@
 	//else exporter->SetFilled();
 
-	ExportViewCells(exporter);
+	ExportViewCellsForViz(exporter);
 
 	if (mExportGeometry)
@@ -1789,6 +1816,6 @@
 	GetRaySets(rays, mConstructionSamples, constructionRays, &savedRays);
 
-	Debug << "construction rays: " << (int)savedRays.size() << endl;
-	Debug << "saved rays: " << (int)constructionRays.size() << endl;
+	Debug << "construction rays: " << (int)constructionRays.size() << endl;
+	Debug << "saved rays: " << (int)savedRays.size() << endl;
 
 	mVspBspTree->Construct(constructionRays, &mSceneBox);
@@ -1818,5 +1845,5 @@
 			//exporter->SetWireframe();
 			exporter->SetFilled();
-			ExportViewCells(exporter);
+			ExportViewCellsForViz(exporter);
 
 			if (0 && mExportRays)
@@ -1909,5 +1936,5 @@
 			//exporter->SetWireframe();
 			exporter->SetFilled();
-			ExportViewCells(exporter);
+			ExportViewCellsForViz(exporter);
 
 			if (mExportGeometry)
@@ -1960,5 +1987,11 @@
 	}
 
+	// real meshes are only contructed only at this stage
 	CreateViewCellsMeshes();
+	// write view cells to disc
+	if (mExportViewCells)
+	{
+		ExportViewCells("viewcells.xml");
+	}
 
 	return 0;
@@ -2025,5 +2058,5 @@
 			}
 
-			ExportViewCells(exporter);
+			ExportViewCellsForViz(exporter);
 			delete exporter;
 		}
@@ -2310,7 +2343,7 @@
 ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point)
 {
-  if (!mVspBspTree)
-	return NULL;
-  return mVspBspTree->GetViewCell(point);
+	if (!mVspBspTree)
+		return NULL;
+	return mVspBspTree->GetViewCell(point);
 }
 
@@ -2327,2 +2360,58 @@
 	mMeshContainer.push_back(mesh);
 }
+
+
+bool VspBspViewCellsManager::LoadViewCells(const string filename, ObjectContainer *objects)
+{
+	ViewCellsParser parser;
+	
+	DEL_PTR(mVspBspTree);
+	mVspBspTree = new VspBspTree();
+	
+	bool success = parser.ParseFile(filename, mVspBspTree, this, objects);
+	ResetViewCells();
+	
+	Debug << (int)mViewCells.size() << " view cells loaded" << endl;
+
+	return success;
+}
+
+
+inline bool ilt(Intersectable *obj1, Intersectable *obj2)
+{
+	return obj1->mId < obj2->mId;
+}
+
+
+bool VspBspViewCellsManager::ExportViewCells(const string filename)
+{
+	cout << "exporting view cells to xml ... "; 
+	std::ofstream stream;
+
+	// for output we need unique ids
+	CreateUniqueViewCellIds();
+
+	stream.open(filename.c_str());
+	stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
+	stream << "<Visibility_Solution>" << endl;
+	
+	//-- load the view cells itself, i.e., the ids and the pvs
+	stream << "<ViewCells>" << endl;
+	ViewCellContainer::const_iterator it, it_end = mViewCells.end();
+	for (it = mViewCells.begin(); it != it_end; ++ it)
+		ExportViewCell(*it, stream);
+    
+	stream << "</ViewCells>" << endl;
+	
+	//-- load the hierarchy
+	stream << "<BspTree>" << endl;
+	mVspBspTree->Export(stream);
+	stream << endl << "</BspTree>" << endl;
+	
+	stream << "</Visibility_Solution>" << endl;
+	stream.close();
+
+	cout << "finished" << endl;
+
+	return true;
+}
