Index: trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env	(revision 361)
+++ trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env	(revision 362)
@@ -9,7 +9,7 @@
 #	filename vienna.x3d
 #	filename ../data/vienna/vienna-simple.x3d
-	filename ../data/vienna/vienna-buildings.x3d
+#	filename ../data/vienna/vienna-buildings.x3d
 #	filename ../data/vienna/viewcells-25-sel.x3d
-#	filename ../data/atlanta/atlanta2.x3d
+	filename ../data/atlanta/atlanta2.x3d
 #	filename ../data/soda/soda.dat
 #	filename ../data/soda/soda5.dat
@@ -56,6 +56,6 @@
 
 Sampling {
-	totalSamples	20000
-	samplesPerPass  2
+	totalSamples	200000
+	samplesPerPass  3
 }
 
@@ -68,4 +68,6 @@
 	maxViewCells 0
 	
+	minPvsDif 10
+	
 #	filename ../data/atlanta/atlanta_viewcells_large.x3d
 	filename ../data/vienna/viewcells-25-sel.x3d
@@ -76,8 +78,8 @@
 BspTree {
 	Construction {
-	#	input fromRays
-		input fromViewCells
+		input fromRays
+	#	input fromViewCells
 	#	input fromSceneGeometry
-		samples 15000
+		samples 100000
 		sideTolerance 0.005
 	}
@@ -116,5 +118,5 @@
 	#splitPlaneStrategy 130
 	
-	splitPlaneStrategy 66
+	splitPlaneStrategy 130
 	
 	maxCandidates 80
@@ -122,17 +124,22 @@
 	Termination {
 		# autopartition
-		maxRays -1
+		maxRays 80
 		maxPolygons 0
 		maxDepth 100
 		
 		# axis aligned splits
-		maxPolysForAxisAligned 400
-		maxCostRatio 0.9
-		ct_div_ci 0.5
+		AxisAligned {
+			maxPolys 500
+			maxRays 300
+			maxObjects 20
+			maxCostRatio 0.9
+			ct_div_ci 0.5
+		}
 	}
 	
-	#axis aligned split
-	splitBorder 0.01
-	
+	AxisAligned {
+		splitBorder 0.01
+	}
+		
 	# if split polys are stored for visualization
 	storeSplitPolys false
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.cpp	(revision 359)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.cpp	(revision 362)
@@ -81,49 +81,20 @@
 }
 
-ViewCell *ViewCell::MergeViewCells(const ViewCell &front, const ViewCell &back)
+ViewCell *ViewCell::Merge(ViewCell &front, ViewCell &back)
 {
-	/*stable_sort(front.mPiercingRays.begin(), front.mPiercingRays.end());
+	ViewCell *vc = new ViewCell();
+	// merge pvs
+	vc->mPvs.Merge(front.mPvs, back.mPvs);
+
+	// merge ray sets
+	stable_sort(front.mPiercingRays.begin(), front.mPiercingRays.end());
 	stable_sort(back.mPiercingRays.begin(), back.mPiercingRays.end());
 
-	ViewCell *vc = front.Merge(back);
+	std::merge(front.mPiercingRays.begin(), front.mPiercingRays.end(),
+			   back.mPiercingRays.begin(), back.mPiercingRays.end(), 
+			   vc->mPiercingRays.begin());
 
-	if (vc)
-		return vc;
-
-	return back.Merge(front);*/return NULL;
+	return vc;
 }
-
-ViewCell *ViewCell::Merge(const ViewCell &other) const
-{
-	//-- compute set differences
-	const float minDif = 10;
-
-	RayContainer diff;
-
-	set_difference(mPiercingRays.begin(), mPiercingRays.end(), 
-				   other.mPiercingRays.begin(), other.mPiercingRays.end(),
-				   diff.begin());
-
-	if (diff.size() < minDif)
-	{
-		ViewCell *vc = new ViewCell();
-
-		RayContainer::const_iterator it, it_end = other.mPiercingRays.end();
-
-		for (it = other.mPiercingRays.begin(); it != it_end; ++ it)
-			vc->mPiercingRays.push_back(*it);
-
-		while (!diff.empty())
-		{
-			vc->mPiercingRays.push_back(diff.back());
-			diff.pop_back();
-		}
-
-		return vc;
-	}
-
-	return NULL;
-}
-
 
 void ViewCell::AddPassingRay(const Ray &ray, const int contributions)
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Pvs.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Pvs.h	(revision 350)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Pvs.h	(revision 362)
@@ -37,21 +37,57 @@
 	int GetSize() {return (int)mEntries.size();}
 	bool Empty() {return mEntries.size() == 0;}
+	/** Merges pvs of a and pvs of b into this pvs.
+	*/
 	void Merge(const Pvs<T> &a, const Pvs<T> &b);
+    /** Difference of pvs to pvs b.
+		@returns number of different entries.
+	*/
+	int Diff(const Pvs<T> &b);
 
 	PvsData<T> *Find(T sample);
 	int AddSample(T sample);
 
-	void GetData(const int index,
-	       T &entry,
-	       PvsData<T> &data);
+	void GetData(const int index, T &entry, PvsData<T> &data);
 	std::map<T, PvsData<T>, LtSample<T> > mEntries;
 };
 
 template <typename T>
+int Pvs<T>::Diff(const Pvs<T> &b)
+{
+	int dif = 0;
+
+	std::map<T, PvsData<T>, LtSample<T> >::const_iterator it;
+
+	for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
+	{
+		PvsData<T> *data = Find((*it).first);		
+		if (!data) ++ dif;
+	}
+
+	return dif;
+}
+
+template <typename T>
 void Pvs<T>::Merge(const Pvs<T> &a, const Pvs<T> &b)
 {
-	//std::merge(a.mEntries.begin(), a.mEntries.end(), 
-	//	       b.mEntries.begin(), b.mEntries.end(), mEntries.begin());
+	std::map<T, PvsData<T>, LtSample<T> >::const_iterator it;
+
+	// todo: copy all elements instead of inserting
+	for (it = a.mEntries.begin(); it != a.mEntries.end(); ++ it)
+	{
+		mEntries.insert(*it);
+	}
+
+	for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
+	{
+		PvsData<T> *data = Find((*it).first);
+		
+		if (data)
+			data->mVisibleSamples += (*it).second.mVisibleSamples;
+		else
+			mEntries.insert(*it);
+	}
 }
+
 
 template <typename T>
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.h	(revision 360)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.h	(revision 362)
@@ -118,4 +118,9 @@
 	void InheritRays(Polygon3 &front_piece, 
 					 Polygon3 &back_piece) const;
+
+
+	/** Counts the number of different intersectables associated with the polygons.
+	*/
+	static int CountIntersectables(const PolygonContainer &polys);
 };
 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 361)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 362)
@@ -14,4 +14,6 @@
 class Ray;
 
+/** Data structure used for optimized ray casting.
+*/
 struct BspRayTraversalData 
 {
@@ -26,4 +28,21 @@
 	{}
 };
+
+/** Data used for passing ray data down the tree.
+*/
+struct BoundedRay
+{
+	Ray *mRay;
+	float mMinT;
+	float mMaxT;
+		
+	BoundedRay(): mMinT(0), mMaxT(1e6), mRay(NULL)
+	{}
+	BoundedRay(Ray *r, float minT, float maxT):
+	mRay(r), mMinT(minT), mMaxT(maxT)
+	{}
+};
+
+typedef vector<BoundedRay *> BoundedRayContainer;
 
 class BspTreeStatistics
@@ -230,8 +249,8 @@
 		@param storeRays if ray set should be stored in view cell
 	*/
-	void BspLeaf::GenerateViewCell(const RayContainer &rays, 
-							   int &sampleContributions,
-							   int &contributingSamples,
-							   const bool storeRays = false);
+	void GenerateViewCell(const BoundedRayContainer &rays, 
+					      int &sampleContributions,
+						  int &contributingSamples,
+						  const bool storeRays = false);
 
 protected:
@@ -246,5 +265,5 @@
 {
 public:
-	 	
+	
 	/** Additional data which is passed down the BSP tree during traversal.
 	*/
@@ -260,5 +279,5 @@
 		ViewCell *mViewCell;
 		/// rays piercing this node
-		RayContainer *mRays;
+		BoundedRayContainer *mRays;
 
 		BspTraversalData():
@@ -274,5 +293,5 @@
 						 const int depth, 
 						 ViewCell *viewCell,
-						 RayContainer *rays): 
+						 BoundedRayContainer *rays): 
 		mNode(node), 
 		mPolygons(polys), 
@@ -344,31 +363,54 @@
 	int CastRay(Ray &ray);
 
+	/** Set to true if new view cells shall be generated in each leaf.
+	*/
+	void SetGenerateViewCells(int generateViewCells);
+
+	/// bsp tree construction types
+	enum {FROM_INPUT_VIEW_CELLS, FROM_SCENE_GEOMETRY, FROM_RAYS};
+
+	/** Returns statistics.
+	*/
+	BspTreeStatistics &GetStat();
+
+	/** finds neighbouring leaves of this tree node.
+	*/
+	int FindNeighbors(BspNode *n, vector<BspLeaf *> &neighbors, 
+					  const bool onlyUnmailed) const;
+
+	/** Extracts geometry associated with the split plane leading to this node.
+	*/
+	void ConstructGeometry(BspNode *n, PolygonContainer &polys) const;
+	
+	/** Returns random leaf of BSP tree.
+		@param halfspace defines the halfspace from which the leaf is taken.
+	*/
+	BspLeaf *GetRandomLeaf(const Plane3 &halfspace);
+
+	/** Returns random leaf of BSP tree.
+		@param onlyUnmailed if only unmailed leaves should be returned.
+	*/
+	BspLeaf *GetRandomLeaf(const bool onlyUnmailed = false);
+
+	/** Adds halfspace to cell definition.
+		@param side indicates which side of halfspace is added
+	*/
+	void AddHalfspace(PolygonContainer &cell, 
+					  vector<Plane3> &planes,
+					  vector<bool> &sides,
+					  const Plane3 &halfspace, 
+					  const bool side) const;
+
+	/** Returns true if merge criteria are reached.
+	*/
+    bool ShouldMerge(BspLeaf *front, BspLeaf *back) const;
+
 	/** Merges view cells based on some criteria
 	    E.g., empty view cells can pe purged, view cells which have 
-		a very similar PVS can be merged to one larger view cell farther up 
-		in the BSP tree.
-		@returns the number of merged view cells
-	*/
-	int MergeViewCells();
-
-	/** Set to true if new view cells shall be generated in each leaf.
-	*/
-	void SetGenerateViewCells(int generateViewCells);
-
-	/// bsp tree construction types
-	enum {FROM_INPUT_VIEW_CELLS, FROM_SCENE_GEOMETRY, FROM_RAYS};
-
-	/** Returns statistics.
-	*/
-	BspTreeStatistics &GetStat();
-
-	/** finds neighbouring leaves of this tree node.
-	*/
-	int FindNeighbors(BspNode *n, vector<BspLeaf *> &neighbors, 
-					  const bool onlyUnmailed) const;
-
-	/** Extracts geometry associated with the split plane leading to this node.
-	*/
-	void ConstructGeometry(BspNode *n, PolygonContainer &polys) const;
+		a very similar PVS can be merged to one larger view cell.
+
+		@returns true if merge was successful.
+	*/
+	bool MergeViewCells(BspLeaf *front, BspLeaf *back) const;
 
 protected:
@@ -394,8 +436,4 @@
 	};
 
-	/** Merges view cells of leafs.
-	*/
-	void MergeLeafs(BspLeaf *front, BspLeaf *back) const;
-
 	/** Evaluates tree stats in the BSP tree leafs.
 	*/
@@ -413,5 +451,5 @@
 		@param rays storesset of rays on which subdivision may be based
 	*/
-	void Construct(PolygonContainer *polys, RayContainer *rays);
+	void Construct(PolygonContainer *polys, BoundedRayContainer *rays);
 
 	/** Selects the best possible splitting plane. 
@@ -424,5 +462,5 @@
 	Plane3 SelectPlane(BspLeaf *leaf, 
 					   PolygonContainer &polys,
-					   const RayContainer &ray);
+					   const BoundedRayContainer &ray);
 
 	/** Evaluates the contribution of the candidate split plane.
@@ -435,5 +473,5 @@
 	float SplitPlaneCost(const Plane3 &candidatePlane,
 						 const PolygonContainer &polys, 						 
-						 const RayContainer &rays) const;
+						 const BoundedRayContainer &rays) const;
 
 	/** Strategies where the effect of the split plane is tested
@@ -449,5 +487,5 @@
 	*/
 	float SplitPlaneCost(const Plane3 &candidatePlane,
-						 const RayContainer &polys) const;
+						 const BoundedRayContainer &polys) const;
 
 	/** Filters next view cell down the tree and inserts it into the appropriate leaves
@@ -478,7 +516,7 @@
 							   PolygonContainer &backPolys,
 							   PolygonContainer &coincident,
-							   RayContainer &rays,
-							   RayContainer &frontRays,
-							    RayContainer &backRays);
+							   BoundedRayContainer &rays,
+							   BoundedRayContainer &frontRays,
+							   BoundedRayContainer &backRays);
 
 	/** Filters polygons down the tree.
@@ -501,5 +539,5 @@
 	*/
 	Plane3 SelectPlaneHeuristics(PolygonContainer &polys, 
-								 const RayContainer &rays,
+								 const BoundedRayContainer &rays,
 								 const int maxTests);
 
@@ -597,7 +635,7 @@
 	*/
 	int SplitRays(const Plane3 &plane,
-				  RayContainer &rays, 
-			      RayContainer &frontRays, 
-				  RayContainer &backRays);
+				  BoundedRayContainer &rays, 
+			      BoundedRayContainer &frontRays, 
+				  BoundedRayContainer &backRays);
 
 
@@ -656,6 +694,10 @@
 	/// BSP tree construction method
 	static int sConstructionMethod;
-	/// maximal number of polygons where we do axis aligned splits
+	/// maximal number of polygons for axis aligned split
 	static int sTermMaxPolysForAxisAligned;
+	/// maximal number of rays for axis aligned split
+	static int sTermMaxRaysForAxisAligned;
+	/// maximal number of objects for axis aligned split
+	static int sTermMaxObjectsForAxisAligned;
 
 	/// axis aligned split criteria
@@ -677,4 +719,7 @@
 	static bool sStoreSplitPolys;
 
+	/// threshold where view cells are merged
+	static int sMinPvsDif;
+
 private:
 	/** Evaluates split plane classification with respect to the plane's 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Ray.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Ray.h	(revision 350)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Ray.h	(revision 362)
@@ -12,4 +12,5 @@
 class MeshInstance;
 class ViewCell;
+class BspLeaf;
 
 // -------------------------------------------------------------------
@@ -61,7 +62,7 @@
   
   vector<Intersection> intersections;
-  vector<KdLeaf *> leaves;
+  vector<KdLeaf *> kdLeaves;
   vector<MeshInstance *> meshes;
-  vector<ViewCell *> viewCells;
+  vector<BspLeaf *> bspLeaves;
   
   // constructors
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp	(revision 332)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp	(revision 362)
@@ -1147,5 +1147,5 @@
   RegisterOption("Sampling.samplesPerPass",
 		 optInt,
-		 "-total_samples=",
+		 "-samples_per_pass=",
 		 "10");
 
@@ -1155,4 +1155,9 @@
 		 "bspTree");
 
+  RegisterOption("ViewCells.minPvsDif",
+		 optString,
+		 "-view_cells_min_pvs_dif",
+		 "10");
+
   RegisterOption("ViewCells.filename",
 		 optString,
@@ -1190,8 +1195,33 @@
 		 "-1");
 
-  RegisterOption("BspTree.Termination.maxPolysForAxisAligned",
+  RegisterOption("BspTree.Termination.AxisAligned.maxCostRatio",
+		 optFloat,
+		 "-bsp_term_max_cost_ratio=",
+		 "1.5");
+
+  RegisterOption("BspTree.Termination.AxisAligned.ct_div_ci",
+		 optFloat,
+		 "-bsp_term_ct_div_ci=",
+		 "1.0");
+
+  RegisterOption("BspTree.AxisAligned.splitBorder",
+		 optFloat,
+		 "-bsp_split_border=",
+		 "0.1");
+
+  RegisterOption("BspTree.Termination.AxisAligned.maxPolys",
 		 optInt,
 		 "-bsp_term_max_polygons=",
 		 "50");
+
+   RegisterOption("BspTree.Termination.AxisAligned.maxObjects",
+		 optInt,
+		 "-bsp_term_max_objects=",
+		 "3");
+
+  RegisterOption("BspTree.Termination.AxisAligned.maxRays",
+		 optInt,
+		 "-bsp_term_max_rays=",
+		 "-1");
 
   RegisterOption("BspTree.Termination.maxDepth",
@@ -1199,19 +1229,4 @@
 		 "-bsp_term_max_depth=",
 		 "100");
-  
-  RegisterOption("BspTree.Termination.maxCostRatio",
-		 optFloat,
-		 "-bsp_term_max_cost_ratio=",
-		 "1.5");
-
-  RegisterOption("BspTree.Termination.ct_div_ci",
-		 optFloat,
-		 "-bsp_term_ct_div_ci=",
-		 "1.0");
-
-  RegisterOption("BspTree.splitBorder",
-		 optFloat,
-		 "-bsp_split_border=",
-		 "0.1");
 
   RegisterOption("BspTree.storeSplitPolys",
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h	(revision 360)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h	(revision 362)
@@ -16,4 +16,5 @@
 class Intersectable;
 class BspLeaf;
+class Polygon3;
 
 class Exporter
@@ -74,4 +75,7 @@
   ExportLeavesGeometry(const BspTree &tree, const vector<BspLeaf *> &leaves) = 0;
 	
+  virtual void 
+  ExportPolygons(const PolygonContainer &polys) = 0;
+
   void SetExportRayDensity(const bool d) { mExportRayDensity = d; }
   
Index: trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.cpp	(revision 354)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.cpp	(revision 362)
@@ -572,5 +572,5 @@
       // compute intersection with all objects in this leaf
       KdLeaf *leaf = (KdLeaf *) node;
-      ray.leaves.push_back(leaf);
+      ray.kdLeaves.push_back(leaf);
       
       ObjectContainer::const_iterator mi;
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 361)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 362)
@@ -20,5 +20,8 @@
 int BspTree::sConstructionMethod = FROM_INPUT_VIEW_CELLS;
 int BspTree::sTermMaxPolysForAxisAligned = 50;
+int BspTree::sTermMaxObjectsForAxisAligned = 50;
+int BspTree::sTermMaxRaysForAxisAligned = -1;
 int BspTree::sTermMaxRays = -1;
+int BspTree::sMinPvsDif = 10;
 
 float BspTree::sCt_div_ci = 1.0f;
@@ -31,4 +34,5 @@
 float BspTree::sBalancedPolysFactor = 1.0f;
 float BspTree::sBalancedViewCellsFactor = 1.0f;
+
 // NOTE:  very important criterium for 2.5d scenes
 float BspTree::sVerticalSplitsFactor = 1.0f;
@@ -285,5 +289,5 @@
 }
 
-void BspLeaf::GenerateViewCell(const RayContainer &rays, 
+void BspLeaf::GenerateViewCell(const BoundedRayContainer &rays, 
 							   int &sampleContributions,
 							   int &contributingSamples,
@@ -295,5 +299,5 @@
 	mViewCell = new ViewCell();
 
-    RayContainer::const_iterator it, it_end = rays.end();
+    BoundedRayContainer::const_iterator it, it_end = rays.end();
 
 	// add contributions from samples to the PVS
@@ -301,11 +305,12 @@
 	{
 		int contribution = 0;
-
-		if (!(*it)->intersections.empty())
+		Ray *ray = (*it)->mRay;
+			
+		if (!ray->intersections.empty())
 		{	
-            contribution +=  mViewCell->GetPvs().AddSample((*it)->intersections[0].mObject);
-		}
-
-		contribution +=  mViewCell->GetPvs().AddSample((*it)->sourceObject.mObject);
+            contribution += mViewCell->GetPvs().AddSample(ray->intersections[0].mObject);
+		}
+
+		contribution += mViewCell->GetPvs().AddSample(ray->sourceObject.mObject);
 
 		if (contribution > 0)
@@ -315,6 +320,8 @@
 		}
 
+		ray->bspLeaves.push_back(this);
+
 		if (storeRays)
-			mViewCell->mPiercingRays.push_back(*it);
+			mViewCell->mPiercingRays.push_back(ray);
 	}
 }
@@ -414,5 +421,5 @@
 		mRoot = new BspLeaf();
 
-	tStack.push(BspTraversalData(mRoot, polys, 0, mRootCell, new RayContainer()));
+	tStack.push(BspTraversalData(mRoot, polys, 0, mRootCell, new BoundedRayContainer()));
 
 	while (!tStack.empty())
@@ -472,5 +479,5 @@
 											 tData.mDepth + 1, 
 											 backViewCell,
-											 new RayContainer()));
+											 new BoundedRayContainer()));
 			}
 
@@ -570,5 +577,5 @@
 
 	// construct tree from the view cell polygons
-	Construct(polys, new RayContainer());
+	Construct(polys, new BoundedRayContainer());
 }
 
@@ -585,5 +592,5 @@
 
 	// construct tree from polygon soup
-	Construct(polys, new RayContainer());
+	Construct(polys, new BoundedRayContainer());
 }
 
@@ -591,8 +598,8 @@
 {
 	mStat.nodes = 1;
-	mBox.Initialize(); 	// initialise bsp tree bounding box
+	mBox.Initialize(); 	// initialise BSP tree bounding box
 	
 	PolygonContainer *polys = new PolygonContainer();
-	RayContainer *rays = new RayContainer();
+	BoundedRayContainer *rays = new BoundedRayContainer();
 
 	RayContainer::const_iterator rit, rit_end = sampleRays.end();
@@ -608,9 +615,5 @@
 	{
 		Ray *ray = *rit;
-		ray->SetId(-1); // reset id
-		rays->push_back(ray);
-
-		//Debug << "extracting ray with intersections" << ray->intersections.size() << endl;
-
+	
 		// get ray-face intersection. Store polygon representing the rays together
 		// with rays intersecting the face.
@@ -629,4 +632,5 @@
 			{
 				Polygon3 *poly = new Polygon3(face, obj->GetMesh());
+				poly->mParent = obj;
 				polys->push_back(poly);
 				poly->mPiercingRays.push_back(ray);
@@ -638,4 +642,16 @@
 	
 	Polygon3::IncludeInBox(*polys, mBox);
+
+	//-- store rays
+	for (rit = sampleRays.begin(); rit != rit_end; ++ rit)
+	{
+		Ray *ray = *rit;
+        ray->SetId(-1); // reset id
+
+		float minT, maxT;
+		if (BoundRay(*ray, minT, maxT))
+			rays->push_back(new BoundedRay(ray, minT, maxT));
+	}
+
 	mStat.polys = (int)polys->size();
 
@@ -647,5 +663,5 @@
 }
 
-void BspTree::Construct(PolygonContainer *polys, RayContainer *rays)
+void BspTree::Construct(PolygonContainer *polys, BoundedRayContainer *rays)
 {
 	std::stack<BspTraversalData> tStack;
@@ -705,4 +721,6 @@
 		leaf->ProcessPolygons(tData.mPolygons, sStoreSplitPolys);
 		DEL_PTR(tData.mPolygons);
+		// discard rays
+		CLEAR_CONTAINER(*tData.mRays);
 		DEL_PTR(tData.mRays);
 
@@ -717,6 +735,6 @@
 	PolygonContainer *backPolys = new PolygonContainer();
 
-	RayContainer *frontRays = new RayContainer();
-	RayContainer *backRays = new RayContainer();
+	BoundedRayContainer *frontRays = new BoundedRayContainer();
+	BoundedRayContainer *backRays = new BoundedRayContainer();
 	
 	// create new interior node and two leaf nodes
@@ -810,7 +828,7 @@
 									PolygonContainer &backPolys,
 									PolygonContainer &coincident,
-									RayContainer &rays,
-									RayContainer &frontRays,
-									RayContainer &backRays)
+									BoundedRayContainer &rays,
+									BoundedRayContainer &frontRays,
+									BoundedRayContainer &backRays)
 {
 	mStat.nodes += 2;
@@ -827,10 +845,8 @@
 	SplitRays(interior->mPlane, rays, frontRays, backRays);
 	
-	// split polygons with split plane
-	mStat.splits +=interior->SplitPolygons(polys, 
-									       frontPolys, 
-							               backPolys, 
-							               coincident, 
-							               sStoreSplitPolys);
+	// subdivide polygons with plane
+	mStat.splits += 
+		interior->SplitPolygons(polys, frontPolys, backPolys, 
+								coincident, sStoreSplitPolys);
 
 	BspInterior *parent = leaf->GetParent();
@@ -995,5 +1011,5 @@
 Plane3 BspTree::SelectPlane(BspLeaf *leaf, 
 							PolygonContainer &polys, 
-							const RayContainer &rays)
+							const BoundedRayContainer &rays)
 {
 	if (polys.empty())
@@ -1014,7 +1030,10 @@
 		return Plane3(norm, position);
 	}
-
+	
 	if ((sSplitPlaneStrategy & AXIS_ALIGNED) &&
-		((int)polys.size() > sTermMaxPolysForAxisAligned))
+		((int)polys.size() > sTermMaxPolysForAxisAligned) &&
+		((int)rays.size() > sTermMaxRaysForAxisAligned) &&
+		((sTermMaxObjectsForAxisAligned < 0) || 
+		  (Polygon3::CountIntersectables(polys) > sTermMaxObjectsForAxisAligned)))
 	{
 		Plane3 plane;
@@ -1034,5 +1053,5 @@
 
 Plane3 BspTree::SelectPlaneHeuristics(PolygonContainer &polys,
-									  const RayContainer &rays,
+									  const BoundedRayContainer &rays,
 									  const int maxTests)
 {
@@ -1093,5 +1112,6 @@
 	int totalViewCells = 0;
 
-	// needed for balanced view cells criterium
+	// need three unique ids for each type of view cell
+	// for balanced view cells criterium
 	ViewCell::NewMail();
 	const int backId = ViewCell::sMailId;
@@ -1206,5 +1226,4 @@
 		minT = 0;
 
-	//Debug << "ray intersections " << ray.intersections.size() << endl;
 	// bound ray or line segment
 	if ((ray.GetType() == Ray::LOCAL_RAY) && 
@@ -1219,5 +1238,5 @@
 
 float BspTree::SplitPlaneCost(const Plane3 &candidatePlane, 
-							  const RayContainer &rays) const
+							  const BoundedRayContainer &rays) const
 {
 	float val = 0;
@@ -1226,13 +1245,11 @@
 	float sumRaySplits = 0;
 
-	RayContainer::const_iterator rit, rit_end = rays.end();
+	BoundedRayContainer::const_iterator rit, rit_end = rays.end();
 
 	for (rit = rays.begin(); rit != rays.end(); ++ rit)
 	{
-		Ray *ray = *rit;
-
-		float minT, maxT;
-		if (!BoundRay(*ray, minT, maxT))
-			continue;
+		Ray *ray = (*rit)->mRay;
+		const float minT = (*rit)->mMinT;
+		const float maxT = (*rit)->mMaxT;
 
 		const int classification = 
@@ -1263,5 +1280,5 @@
 float BspTree::SplitPlaneCost(const Plane3 &candidatePlane, 
 							  const PolygonContainer &polys, 							  
-							  const RayContainer &rays) const
+							  const BoundedRayContainer &rays) const
 {
 	float val = 0;
@@ -1326,13 +1343,16 @@
 
 	//-- termination criteria for axis aligned split
-	environment->GetFloatValue("BspTree.Termination.ct_div_ci", sCt_div_ci);
-	environment->GetFloatValue("BspTree.Termination.maxCostRatio", sMaxCostRatio);
-	environment->GetIntValue("BspTree.Termination.maxPolysForAxisAligned", 
+	environment->GetFloatValue("BspTree.Termination.AxisAligned.ct_div_ci", sCt_div_ci);
+	environment->GetFloatValue("BspTree.Termination.AxisAligned.maxCostRatio", sMaxCostRatio);
+	environment->GetIntValue("BspTree.Termination.AxisAligned.maxPolys", 
 							 sTermMaxPolysForAxisAligned);
-	
+	environment->GetIntValue("BspTree.Termination.AxisAligned.maxRays", 
+							 sTermMaxRaysForAxisAligned);
+	environment->GetIntValue("BspTree.Termination.AxisAligned.maxObjects", 
+							 sTermMaxObjectsForAxisAligned);
 	//-- partition criteria
 	environment->GetIntValue("BspTree.maxCandidates", sMaxCandidates);
 	environment->GetIntValue("BspTree.splitPlaneStrategy", sSplitPlaneStrategy);
-	environment->GetFloatValue("BspTree.splitBorder", sSplitBorder);
+	environment->GetFloatValue("BspTree.AxisAligned.splitBorder", sSplitBorder);
 	
 	environment->GetBoolValue("BspTree.storeSplitPolys", sStoreSplitPolys);
@@ -1340,4 +1360,6 @@
 	environment->GetFloatValue("BspTree.Construction.sideTolerance", Vector3::sDistTolerance);
 	Vector3::sDistToleranceSqrt = Vector3::sDistTolerance * Vector3::sDistTolerance;
+
+	environment->GetIntValue("ViewCells.minPvsDif", sMinPvsDif);
 
     Debug << "BSP max depth: " << sTermMaxDepth << endl;
@@ -1440,8 +1462,9 @@
 	float maxt, mint;
 
+	if (!BoundRay(ray, mint, maxt))
+		return 0;
+
 	Intersectable::NewMail();
 
-	BoundRay(ray, mint, maxt);
-	
 	Vector3 entp = ray.Extrap(mint);
 	Vector3 extp = ray.Extrap(maxt);
@@ -1458,7 +1481,4 @@
 			Plane3 *splitPlane = in->GetPlane();
 
-			float t = 0;
-			bool coplanar = false;
-		
 			int entSide = splitPlane->Side(entp);
 			int extSide = splitPlane->Side(extp);
@@ -1494,5 +1514,7 @@
 
 			// find intersection of ray segment with plane
-			extp = splitPlane->FindIntersection(ray.GetLoc(), extp, &maxt);
+			float t;
+			extp = splitPlane->FindIntersection(ray.GetLoc(), extp, &t);
+			maxt *= t;
 			
 		} else // reached leaf => intersection with view cell
@@ -1502,5 +1524,5 @@
 			if (!leaf->mViewCell->Mailed())
 			{
-				ray.viewCells.push_back(leaf->mViewCell);
+				ray.bspLeaves.push_back(leaf);
 				leaf->mViewCell->Mail();
 				++ hits;
@@ -1514,5 +1536,5 @@
 			mint = maxt; // NOTE: need this?
 
-			 if (ray.GetType() == Ray::LINE_SEGMENT && mint > 1.0f)
+			if (ray.GetType() == Ray::LINE_SEGMENT && mint > 1.0f)
 				break;
 
@@ -1522,6 +1544,4 @@
 			extp = s.mExitPoint;
 			maxt = s.mMaxT;
-
-			//Debug << "leaf: new entrypt: " << entp << " new extp: " << extp << endl;
 
 			tStack.pop();
@@ -1577,51 +1597,32 @@
 }
 
-int BspTree::MergeViewCells()
-{
-	stack<BspNode *> nodeStack;
-	nodeStack.push(mRoot);
-
-	BspLeaf *storedLeaf = NULL;
-
-	while (!nodeStack.empty()) 
-	{
-		BspNode *node = nodeStack.top();
-		nodeStack.pop();
-
-		if (node->IsLeaf()) 
-		{
-			BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
-
-			if (storedLeaf)
-				MergeLeafs(leaf, storedLeaf);
-
-			// store current leaf
-			storedLeaf = leaf;
-		}
-		else 
-		{
-			BspInterior *interior = dynamic_cast<BspInterior *>(node);
-
-			nodeStack.push(interior->mFront);
-			nodeStack.push(interior->mBack);
-		}
-	}
-	return 0;
-}
-
-void BspTree::MergeLeafs(BspLeaf *front, BspLeaf *back) const
-{
-	//std::merge(front->mPvs.mEntries.begin(), back->mPvs.mEntries.begin());
-	ViewCell *viewCell = ViewCell::MergeViewCells(*front->mViewCell, *back->mViewCell);
-	//viewCell->GetPvs().Merge(front->mViewCell->GetPvs(), back->mViewCell->GetPvs());
-
-	if (viewCell)
-	{
-		DEL_PTR(front->mViewCell);
-		DEL_PTR(back->mViewCell);
-
-		front->SetViewCell(viewCell);
-		back->SetViewCell(viewCell);
-	}
+
+bool BspTree::MergeViewCells(BspLeaf *front, BspLeaf *back) const
+{
+	ViewCell *viewCell = ViewCell::Merge(*front->mViewCell, *back->mViewCell);
+	
+	if (!viewCell)
+		return false;
+
+	DEL_PTR(front->mViewCell);
+	DEL_PTR(back->mViewCell);
+
+	front->SetViewCell(viewCell);
+	back->SetViewCell(viewCell);
+
+	return true;
+}
+
+bool BspTree::ShouldMerge(BspLeaf *front, BspLeaf *back) const
+{
+	if (front->mViewCell->GetPvs().Diff(back->mViewCell->GetPvs()) < 
+		sMinPvsDif)
+		return true;
+	
+	if (back->mViewCell->GetPvs().Diff(front->mViewCell->GetPvs()) < 
+		sMinPvsDif)
+		return true;
+
+	return false;
 }
 
@@ -1637,7 +1638,7 @@
 
 int BspTree::SplitRays(const Plane3 &plane,
-					   RayContainer &rays, 
-					   RayContainer &frontRays, 
-					   RayContainer &backRays)
+					   BoundedRayContainer &rays, 
+					   BoundedRayContainer &frontRays, 
+					   BoundedRayContainer &backRays)
 {
 	int splits = 0;
@@ -1645,35 +1646,54 @@
 	while (!rays.empty())
 	{
-		Ray *ray = rays.back();
+		BoundedRay *bRay = rays.back();
+		Ray *ray = bRay->mRay;
 		rays.pop_back();
-
-		//-- ray-plane intersection
-		float maxT, minT;
-	
-		if (!BoundRay(*ray, minT, maxT))
-			continue;
-				
-		const int classification = ray->ClassifyPlane(plane, minT, maxT);
 		
-		ray->SetId(classification);
-
-		switch (classification)
+		const int cf = 
+			ray->ClassifyPlane(plane, bRay->mMinT, bRay->mMaxT);
+		
+		ray->SetId(cf);
+
+		switch (cf)
 		{
 		case Ray::COINCIDENT:
+			frontRays.push_back(bRay);
 			break;
 		case Ray::BACK:
-			backRays.push_back(ray);
+			backRays.push_back(bRay);
 			break;
 		case Ray::FRONT:
-			frontRays.push_back(ray);
+			frontRays.push_back(bRay);
 			break;
 		case Ray::FRONT_BACK:
-			ray->SetId(Ray::FRONT_BACK);
-			backRays.push_back(ray);
-			++ splits;			
+			{
+				// find intersection of ray segment with plane
+				const Vector3 extp = ray->Extrap(bRay->mMaxT);
+				const float t = plane.FindT(ray->GetLoc(), extp);
+				
+				const float newT = t * bRay->mMaxT;
+
+				frontRays.push_back(new BoundedRay(ray, bRay->mMinT, newT));
+				backRays.push_back(new BoundedRay(ray, newT, bRay->mMaxT));
+
+				DEL_PTR(bRay);
+
+				++ splits;
+			}
 			break;
 		case Ray::BACK_FRONT:
-			frontRays.push_back(ray);
-			++ splits;
+			{
+				// find intersection of ray segment with plane
+				const Vector3 extp = ray->Extrap(bRay->mMaxT);
+				const float t = plane.FindT(ray->GetLoc(), extp);
+				const float newT = t * bRay->mMaxT;
+
+				backRays.push_back(new BoundedRay(ray, bRay->mMinT, newT));
+				frontRays.push_back(new BoundedRay(ray, newT, bRay->mMaxT));
+				
+				DEL_PTR(bRay);
+
+				++ splits;
+			}
 			break;
 		default:
@@ -1686,5 +1706,7 @@
 }
 
-void BspTree::ExtractSplitPlanes(BspNode *n, vector<Plane3 *> &planes, vector<bool> &sides) const
+void BspTree::ExtractSplitPlanes(BspNode *n, 
+								 vector<Plane3 *> &planes, 
+								 vector<bool> &sides) const
 {
 	BspNode *lastNode;
@@ -1692,4 +1714,7 @@
 	{
 		lastNode = n;
+
+		// want to get planes defining geometry of this node => don't take
+		// split plane of node itself
 		n = n->GetParent();
 		
@@ -1705,4 +1730,151 @@
 }
 
+struct Candidate
+{
+	Polygon3 *mPoly;
+	Plane3 mPlane;
+	bool mSide;
+
+	Candidate(Polygon3 *poly, const Plane3 &plane, const bool &side):
+	mPoly(poly), mPlane(plane), mSide(side)
+	{}
+};
+
+void BspTree::AddHalfspace(PolygonContainer &cell, 
+						   vector<Plane3> &planes,
+						   vector<bool> &sides,
+						   const Plane3 &halfspace, 
+						   const bool side) const
+{
+	Polygon3 *poly = GetBoundingBox().CrossSection(halfspace);
+
+	bool inside = true;
+
+	// polygon is split by all other planes
+	for (int i = 0; (i < planes.size()) && inside; ++ i)
+	{
+		VertexContainer splitPts;
+		Polygon3 *frontPoly, *backPoly;
+
+		const int cf = poly->ClassifyPlane(planes[i]);
+			
+		// split new polygon with all previous planes
+		switch (cf)
+		{
+			case Polygon3::SPLIT:
+				frontPoly = new Polygon3();
+				backPoly = new Polygon3();
+
+				poly->Split(planes[i], *frontPoly, *backPoly, splitPts);
+				DEL_PTR(poly);
+
+				if(sides[i] == true)
+				{
+					poly = frontPoly;
+					DEL_PTR(backPoly);
+				}
+					else
+					{
+						poly = backPoly;
+						DEL_PTR(frontPoly);
+					}
+					inside = true;
+					break;
+			case Polygon3::BACK_SIDE:
+				if (sides[i]) 
+					inside = false;
+				break;
+			case Polygon3::FRONT_SIDE:
+				if (!sides[i])
+					inside = false;
+				break;
+			default:
+				break;
+		}
+	}
+
+	//-- plane poly splits all other candidates
+
+    // some polygons may fall out => rebuild cell
+	vector<Candidate> candidates;
+
+	for (int i = 0; i < (int)cell.size(); ++ i)
+	{
+		candidates.push_back(Candidate(cell[i], planes[i], sides[i]));
+	}
+
+	cell.clear();
+	planes.clear();
+	sides.clear();
+
+	for (int i = 0; i < (int)candidates.size(); ++ i)
+	{
+		bool candidateInside = true;
+
+		VertexContainer splitPts;
+		Polygon3 *frontPoly, *backPoly;
+
+		const int cf = poly->ClassifyPlane(halfspace);
+			
+		// split new polygon with all previous planes
+		switch (cf)
+		{
+			case Polygon3::SPLIT:
+				frontPoly = new Polygon3();
+				backPoly = new Polygon3();
+
+				poly->Split(halfspace, *frontPoly, *backPoly, splitPts);
+				DEL_PTR(candidates[i].mPoly);
+
+				if (sides[i] == true)
+				{
+					candidates[i].mPoly = frontPoly;
+					DEL_PTR(backPoly);
+				}
+				else
+				{
+					candidates[i].mPoly = backPoly;
+					DEL_PTR(frontPoly);
+				}
+				inside = true;
+				break;
+			case Polygon3::BACK_SIDE:
+				if (candidates[i].mSide) 
+					candidateInside = false;
+				break;
+			case Polygon3::FRONT_SIDE:
+				if (!candidates[i].mSide)
+					candidateInside = false;
+				break;
+			default:
+				break;
+		}
+		
+		if (candidateInside)
+		{
+			cell.push_back(candidates[i].mPoly);
+			sides.push_back(candidates[i].mSide);
+			planes.push_back(candidates[i].mPlane);
+		}
+		else
+		{
+			DEL_PTR(candidates[i].mPoly);
+		}
+	}
+
+	//-- finally add polygon
+	if (inside)
+	{
+		cell.push_back(poly);
+		planes.push_back(halfspace);
+		sides.push_back(side);
+	}
+	else
+	{
+		DEL_PTR(poly);
+	}
+}
+
+
 void BspTree::ConstructGeometry(BspNode *n, PolygonContainer &cell) const
 {
@@ -1716,5 +1888,5 @@
 	PolygonContainer candidatePolys;
 
-	// bounded plane is added to the polygons
+	// bounded planes are added to the polygons
 	for (int i = 0; i < (int)planes.size(); ++ i)
 	{
@@ -1722,4 +1894,5 @@
 	}
 
+	// add faces of bounding box (also could be faces of the cell)
 	for (int i = 0; i < 6; ++ i)
 	{
@@ -1736,5 +1909,5 @@
 		bool inside = true;
 
-		// polygon is split with all other planes
+		// polygon is split by all other planes
 		for (int j = 0; (j < planes.size()) && inside; ++ j)
 		{
@@ -1747,8 +1920,7 @@
 			Polygon3 *frontPoly, *backPoly;
 
-			int cf = candidatePolys[i]->ClassifyPlane(*plane);
+			const int cf = candidatePolys[i]->ClassifyPlane(*plane);
 			
-			// split new polygon with all previous planes
-			switch(cf)
+			switch (cf)
 			{
 				case Polygon3::SPLIT:
@@ -1756,5 +1928,6 @@
 					backPoly = new Polygon3();
 
-					candidatePolys[i]->Split(*plane, *frontPoly, *backPoly, splitPts);
+					candidatePolys[i]->Split(*plane, *frontPoly, 
+											 *backPoly, splitPts);
 					DEL_PTR(candidatePolys[i]);
 
@@ -1835,4 +2008,6 @@
 				if (isAdjacent)
 					neighbors.push_back(dynamic_cast<BspLeaf *>(node));
+
+				CLEAR_CONTAINER(neighborCandidate);
 			}
 		}
@@ -1857,4 +2032,91 @@
 	}
 	
+	CLEAR_CONTAINER(cell);
 	return (int)neighbors.size();
 }
+
+BspLeaf *BspTree::GetRandomLeaf(const Plane3 &halfspace)
+{
+    stack<BspNode *> nodeStack;
+  	nodeStack.push(mRoot);
+	
+	int mask = rand();
+  
+	while (!nodeStack.empty()) 
+	{
+		BspNode *node = nodeStack.top();
+		nodeStack.pop();
+	  
+		if (node->IsLeaf()) 
+		{
+			return dynamic_cast<BspLeaf *>(node);
+		} 
+		else 
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+			
+			BspNode *next;
+	
+			PolygonContainer cell;
+
+			// todo: not very efficient: constructs full cell everytime
+			ConstructGeometry(interior, cell);
+
+			const int cf = Polygon3::ClassifyPlane(cell, halfspace);
+
+			if (cf == Polygon3::BACK_SIDE)
+				next = interior->mFront;
+			else
+				if (cf == Polygon3::FRONT_SIDE)
+					next = interior->mFront;
+			else 
+			{
+				// random decision
+				if (mask & 1)
+					next = interior->mBack;
+				else
+					next = interior->mFront;
+				mask = mask >> 1;
+			}
+
+			nodeStack.push(next);
+		}
+	}
+	
+	return NULL;
+}
+
+BspLeaf *BspTree::GetRandomLeaf(const bool onlyUnmailed)
+{
+	stack<BspNode *> nodeStack;
+	
+	nodeStack.push(mRoot);
+
+	int mask = rand();
+	
+	while (!nodeStack.empty()) 
+	{
+		BspNode *node = nodeStack.top();
+		nodeStack.pop();
+		
+		if (node->IsLeaf()) 
+		{
+			if ( (!onlyUnmailed || !node->Mailed()) )
+				return dynamic_cast<BspLeaf *>(node);
+		}
+		else 
+		{
+			BspInterior *interior = dynamic_cast<BspInterior *>(node);
+
+			// random decision
+			if (mask & 1)
+				nodeStack.push(interior->mBack);
+			else
+				nodeStack.push(interior->mFront);
+
+			mask = mask >> 1;
+		}
+	}
+	
+	return NULL;
+}
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.h	(revision 352)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.h	(revision 362)
@@ -48,8 +48,9 @@
 	static ViewCell *ExtrudeViewCell(const Triangle3 &baseTri, const float height);
 
-	/** Merges two view cells based on some criteria
-		@returns new view cell if merge was success. NULL if merge failed.
+	/** Merges two view cells.
+		@note the piercing rays of the front and back will be ordered	
+		@returns new view cell based on the merging.
 	*/
-	static ViewCell *MergeViewCells(const ViewCell &front, const ViewCell &back);
+	static ViewCell *Merge(ViewCell &front, ViewCell &back);
 
 
@@ -61,9 +62,4 @@
 
 protected:
-	
-	/** Merges view cell with other view cell if certain criteria are met.
-		@note because of performance issues the precondition is that the piercing rays are ordered.
-	*/
-	ViewCell *Merge(const ViewCell &other) const;
 
 	/// the potentially visible objects
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Plane3.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Plane3.h	(revision 349)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Plane3.h	(revision 362)
@@ -55,14 +55,24 @@
 	}
 	
+	if (coplanar) (*coplanar) = false;
     float u = - Distance(a) / dv; // TODO: could be done more efficiently
     
-	if (coplanar) (*coplanar) = false;
 	if (t) (*t) = u;
 	
-	//Debug << "t: " << u << ", b - a: " << v << ", norm: " << mNormal << ", dist(a): " << - Distance(a) << ", dv: " << dv << endl;
-    //return a - Distance(a) * b / dv + Distance(a) * a / dv; // NOTE: gives better precision than calclulating a + u * v
     return a + u * v;
   }
   
+  float FindT(const Vector3 &a,
+			  const Vector3 &b) const 
+  {	  
+	  const Vector3 v = b - a; // line from A to B
+	  const float dv = DotProd(v, mNormal);
+    
+	  if (signum(dv) == 0)
+		  return 1;
+	
+	  return - Distance(a) / dv; // TODO: could be done more efficiently
+  }
+
   friend bool
   PlaneIntersection(const Plane3 &a, const Plane3 &b, const Plane3 &c, Vector3 &result);
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Ray.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Ray.cpp	(revision 349)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Ray.cpp	(revision 362)
@@ -168,20 +168,28 @@
 	const int extSide = plane.Side(extp);
 
-	if ((entSide == 0) && (extSide == 0)) 
+	if (entSide < 0)
 	{
-		return COINCIDENT;
-	}
-	else if ((entSide <= 0) && (extSide <= 0))
-	{
+		if (extSide >= 0)
+		{
+			return BACK_FRONT;
+		}
 		return BACK;
 	}
-	else if ((entSide >= 0) && (extSide >= 0))
+	else if (entSide > 0)
 	{
+		if (extSide <= 0)
+			return FRONT_BACK;
+
 		return FRONT;
 	}
-	else if ((entSide <= 0) && (extSide >= 0))
-		return BACK_FRONT;
+	else if (entSide == 0)
+	{
+		if (extSide > 0)
+			return BACK_FRONT;
+		else if (extSide < 0)
+			return FRONT_BACK;
+	}
 	
-	return FRONT_BACK;
+	return COINCIDENT;
 }
 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h	(revision 360)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h	(revision 362)
@@ -50,5 +50,6 @@
   ExportPolygon(Polygon3 *poly);
 
-  virtual void ExportPolygons(const PolygonContainer &polys);
+  virtual void 
+  ExportPolygons(const PolygonContainer &polys);
 
   virtual bool
Index: trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.h	(revision 354)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.h	(revision 362)
@@ -64,5 +64,23 @@
 									);
 
-	/** Adds objects samples to view cells.
+	/** Processes the BSP based view cells during a pass.
+		@param collectSamplesForBps if still in sample collection phase
+		@param ray the current ray
+		@param object the currently processed object
+		@param faceIndex the sampled face of the object
+		@param contributingSamples samples contributing to pvs
+		@param sampleContributions contribution of the samples
+
+		@returns true if BSP tree has been constructed, false if not yet
+
+	*/
+	bool ProcessBspViewCells(bool collectSamplesForBsp,
+							 Ray &ray,
+							 Intersectable *object,
+							 int faceIndex,
+							 int &contributingSamples,
+							 int &sampleContributions);
+
+	/** Adds objects samples to bsp view cells.
 	*/
 	int AddObjectSamples(Intersectable *obj, const Ray &ray);
@@ -71,4 +89,13 @@
 
 	void ExportSplits(const ObjectContainer &objects);
+
+	void ExportBspPvs(const ObjectContainer &objects);
+
+	/** Post processes view cells (i.e., merges or subdivides view cells based
+		on the PVS and the ray sets.
+		@returns number of merged view cells.
+	*/
+	int PostprocessViewCells(const RayContainer &rays);
+
 };
 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.cpp	(revision 361)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.cpp	(revision 362)
@@ -147,5 +147,5 @@
 	for (it = mVertices.begin(); it != mVertices.end(); ++ it)
 	{
-		int side = plane.Side(*it, Vector3::sDistTolerance);
+		const int side = plane.Side(*it, Vector3::sDistTolerance);
 		
 		if (side > 0)
@@ -395,5 +395,4 @@
 		if ((cf == SPLIT) || (cf == COINCIDENT) || (onFrontSide && onBackSide))
 		{
-			Debug << "here" << endl;
 			return SPLIT;
 		}
@@ -411,2 +410,21 @@
 	return SPLIT;
 }
+
+int Polygon3::CountIntersectables(const PolygonContainer &polys)
+{
+	int count = 0;
+
+	PolygonContainer::const_iterator it, it_end = polys.end();
+
+	MeshInstance::NewMail();
+
+	for (it = polys.begin(); it != it_end; ++ it)
+	{
+		if ((*it)->mParent && !(*it)->mParent->Mailed())
+		{
+			++ count;
+			(*it)->mParent->Mail();
+		}
+	}
+	return count;
+}
Index: trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp	(revision 361)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp	(revision 362)
@@ -32,7 +32,7 @@
 {
   ray.intersections.clear();
-  ray.leaves.clear();
+  ray.kdLeaves.clear();
   ray.meshes.clear();
-  ray.viewCells.clear();
+  ray.bspLeaves.clear();
 
   //  cout<<point<<" "<<direction<<endl;
@@ -68,6 +68,4 @@
 		mSceneGraph->CollectObjects(&objects);
 		mBspTree->Construct(objects);
-		
-		mBspTree->CollectViewCells(mViewCells);
 		break;
 	case BspTree::FROM_RAYS:
@@ -75,6 +73,4 @@
 		mBspTree->SetGenerateViewCells(true);
 		mBspTree->Construct(mSampleRays);
-		
-		mBspTree->CollectViewCells(mViewCells);
 		break;
 	default:
@@ -94,12 +90,12 @@
   int contributingSamples = 0;
   int j;
-  for (j=0; j < ray.leaves.size(); j++) {
-    KdNode *node = GetNodeForPvs( ray.leaves[j] );
+  for (j=0; j < ray.kdLeaves.size(); j++) {
+    KdNode *node = GetNodeForPvs( ray.kdLeaves[j] );
     contributingSamples += object->mKdPvs.AddSample(node);
   }
    
   if (mPass > 10)
-    for (j=1; j < ((int)ray.leaves.size() - 1); j++) {
-      ray.leaves[j]->AddPassingRay(ray, contributingSamples ? 1 : 0);
+    for (j=1; j < ((int)ray.kdLeaves.size() - 1); j++) {
+      ray.kdLeaves[j]->AddPassingRay(ray, contributingSamples ? 1 : 0);
   }
   
@@ -114,16 +110,18 @@
  
 	// object can be seen from the view cell => add to view cell pvs
-	for (j=0; j < ray.viewCells.size(); ++ j) 
+	for (j=0; j < ray.bspLeaves.size(); ++ j) 
 	{ 	// if ray not in unbounded space
-		if (ray.viewCells[j] != &mUnbounded)
-			contributingSamples += ray.viewCells[j]->GetPvs().AddSample(obj);
+		if (ray.bspLeaves[j]->GetViewCell() != &mUnbounded)
+			contributingSamples += 
+				ray.bspLeaves[j]->GetViewCell()->GetPvs().AddSample(obj);
 	}
  
 	// rays passing through this viewcell
 	if (mPass > 1)
-		for (j=1; j < ((int)ray.viewCells.size() - 1); ++ j) 
-		{
-			if (ray.viewCells[j] != &mUnbounded)
-				ray.viewCells[j]->AddPassingRay(ray, contributingSamples ? 1 : 0);
+		for (j=1; j < ((int)ray.bspLeaves.size() - 1); ++ j) 
+		{
+			if (ray.bspLeaves[j]->GetViewCell() != &mUnbounded)
+				ray.bspLeaves[j]->GetViewCell()->
+					AddPassingRay(ray, contributingSamples ? 1 : 0);
 		}
  
@@ -183,5 +181,5 @@
 	else
 		{
-			if (ray.leaves.size()) {
+			if (ray.kdLeaves.size()) {
 				if (!reverseRay)
 					sampleContributions += AddNodeSamples(object, ray);
@@ -372,8 +370,4 @@
 
   vector<Ray> rays[10];
-
-  vector<Ray> vcRays[5];
-  ViewCellContainer pvsViewCells;
-  vector<Ray> viewCellRays; // used for BSP tree construction
 
   while (totalSamples < mTotalSamples) {
@@ -462,55 +456,13 @@
 					}
 					//-------------------
-
 					if (mViewCellsType == BSP_VIEW_CELLS) 
 					{
-						// save rays for bsp tree construction
-						if (collectSamplesForBsp)
-						{
-							// also add origin to sample in order to extract it as input polygons
-							MeshInstance *mi = dynamic_cast<MeshInstance *>(object);
-							ray.sourceObject = Ray::Intersection(0.0, mi, faceIndex);
-							
-                            mSampleRays.push_back(new Ray(ray));
-						}
-						else
-						{
-							// construct BSP tree using the samples
-							if (!mBspTree)
-							{
-								BuildBspTree();
-
-								cout << "generated " << (int)mViewCells.size() << " view cells" << endl;
-
-								passContributingSamples += mBspTree->GetStat().contributingSamples;
-								passSampleContributions += mBspTree->GetStat().sampleContributions;
-
-								BspTreeStatistics(Debug);	
-								Export("vc_bsptree.x3d", false, false, true);
-							}
-								
-							// some random view cells for output
-							if (pvsViewCells.empty())
-							{
-								int vcPvsOut = Min((int)mViewCells.size(), 5);
-							
-								for (int j = 0; j < vcPvsOut; ++ j)
-								{
-									int idx = Random((int)mViewCells.size());
-									Debug << "output view cell=" << idx << endl;
-									pvsViewCells.push_back(mViewCells[Random((int)mViewCells.size())]);
-								}
-							}
-							else
-							{	
-								// check whether we can add the current ray to the rays
-								for (int k = 0; k < (int)ray.viewCells.size(); ++ k)
-									for (int j = 0; j < (int)pvsViewCells.size(); ++ j) 
-										if (pvsViewCells[j] == ray.viewCells[k]) 
-											vcRays[j].push_back(ray);							
-							}
-						}
+						ProcessBspViewCells(collectSamplesForBsp,
+											ray,
+											object,
+											faceIndex,
+											passContributingSamples,
+											passSampleContributions);
 					}
-		
 				}
 			} else {
@@ -580,155 +532,63 @@
 		cout << "#totalPvsSize=" << mKdTree->CollectLeafPvs() << endl;
   
+	// merge or subdivide view cells
+	if (mBspTree)
+	{
+		int merged = PostprocessViewCells(mSampleRays);
+		Debug << "merged " << merged << " view cells" << endl;
+
+		ViewCellContainer vc;
+		mBspTree->CollectViewCells(vc);
+
+		ViewCellContainer::const_iterator it, it_end = vc.end();
+
+		int mergedPvs = 0;
+		for (it = vc.begin(); it != it_end; ++ it)
+			mergedPvs += (*it)->GetPvs().GetSize();
+
+		Debug << "merged pvs size: " << mergedPvs << endl;
+
+	}
+	
   //  HoleSamplingPass();
-  if (0) {
-    Exporter *exporter = Exporter::GetExporter("ray-density.x3d");
-    exporter->SetExportRayDensity(true);
-    exporter->ExportKdTree(*mKdTree);
-
+	if (0) {
+		Exporter *exporter = Exporter::GetExporter("ray-density.x3d"); 
+		exporter->SetExportRayDensity(true);
+		exporter->ExportKdTree(*mKdTree);
+
+		if (mBspTree && (mViewCellsType == BSP_VIEW_CELLS))
+			exporter->ExportBspTree(*mBspTree);
+
+		delete exporter;
+	}
+  
+	bool exportRays = false;
+	if (exportRays) {
+		Exporter *exporter = NULL;
+		exporter = Exporter::GetExporter("sample-rays.x3d");
+		exporter->SetWireframe();
+		exporter->ExportKdTree(*mKdTree);
+		exporter->ExportBspTree(*mBspTree);
+
+		for (i=0; i < pvsOut; i++) 
+		exporter->ExportRays(rays[i], 1000, RgbColor(1, 0, 0));
+		exporter->SetFilled();
+		  
+		delete exporter;
+	}
+
+	//-- several visualizations and statistics
+	if (1) {
 	if (mBspTree && (mViewCellsType == BSP_VIEW_CELLS))
-		exporter->ExportBspTree(*mBspTree);
-
-    delete exporter;
-  }
-  
-  bool exportRays = false;
-  if (exportRays) {
-    Exporter *exporter = NULL;
-    exporter = Exporter::GetExporter("sample-rays.x3d");
-    exporter->SetWireframe();
-    exporter->ExportKdTree(*mKdTree);
-	exporter->ExportBspTree(*mBspTree);
-
-    for (i=0; i < pvsOut; i++) 
-      exporter->ExportRays(rays[i], 1000, RgbColor(1, 0, 0));
-    exporter->SetFilled();
-	  
-    delete exporter;
-  }
-
-  //-- several visualizations and statistics
-  if (1) {
-  if (mBspTree && (mViewCellsType == BSP_VIEW_CELLS))
-  {
-	  bool exportSplits = false;
-	  environment->GetBoolValue("BspTree.exportSplits", exportSplits);
-
-	  // export the bsp splits
-	  if (exportSplits)
-	  	  ExportSplits(objects);
-	
-	  Exporter *exporter = Exporter::GetExporter("viewCells.x3d");
-
-	  // export leaves
-	  if (0 && exporter)
-	  {
-		  vector<BspLeaf *> leaves;
-		  mBspTree->CollectLeaves(leaves);
-		  vector<BspLeaf *> randLeaves;
-		  vector<BspLeaf *> neighbors;
-
-		  for (int k = 0; k < 1; ++ k) 
-		  {
-			  BspLeaf *leaf = leaves[Random((int)leaves.size())];
-			  randLeaves.push_back(leaf);
-			  mBspTree->FindNeighbors(leaf, neighbors, false);
-		  }	
-
-		  exporter->ExportLeavesGeometry(*mBspTree, randLeaves);
-		  exporter->SetWireframe();
-          exporter->ExportLeavesGeometry(*mBspTree, neighbors);	
-			
-          delete exporter;
-	  }
-
-	   vector<BspLeaf *> leaves;
-	   mBspTree->CollectLeaves(leaves);
-	   
-	   for (int k = 0; k < 100; ++ k) 
-	   {
-		   vector<BspLeaf *> randLeaves;
-		   vector<BspLeaf *> neighbors;
-		   
-		   char s[64]; sprintf(s, "bsp-vc%04d.x3d", k);
-		   Exporter *exporter = Exporter::GetExporter(s);
-
-		   BspLeaf *leaf = leaves[Random((int)leaves.size())];
-		   Debug << "\noutput leaf " << k << endl;
-		   randLeaves.push_back(leaf);
-		   mBspTree->FindNeighbors(leaf, neighbors, false);
-
-		   exporter->ExportLeavesGeometry(*mBspTree, randLeaves);
-		   exporter->SetWireframe();
-		   exporter->ExportLeavesGeometry(*mBspTree, neighbors);	
-			
-		   delete exporter;
-	   }	
-
-	  for (int j = 0; j < pvsViewCells.size(); ++ j)
-	  {
-		  ViewCell *vc = pvsViewCells[j];
-
-		  Intersectable::NewMail();
-		  char s[64]; sprintf(s, "bsp-pvs%04d.x3d", j);
-
-		  Exporter *exporter = Exporter::GetExporter(s);
-		  exporter->SetFilled();
-
-		  ViewCellPvsMap::iterator it = vc->GetPvs().mEntries.begin();
-
-		  Material m;//= RandomMaterial();
-		  m.mDiffuseColor = RgbColor(0, 1, 0);
-		  exporter->SetForcedMaterial(m);
-
-		  exporter->ExportViewCell(vc);
-
-		  Debug << j << ": pvs size=" << (int)vc->GetPvs().GetSize() 
-			    << ", piercing rays=" << (int)vcRays[j].size() << endl;
-
-		  exporter->SetWireframe();
-
-		  // export view cells
-		  m.mDiffuseColor = RgbColor(1, 0, 1);
-		  exporter->SetForcedMaterial(m);
-		  exporter->ExportViewCells(mViewCells);
-			
-		  // export rays piercing this view cell
-		  exporter->ExportRays(vcRays[j], 1000, RgbColor(0, 1, 0));
-
-		  m.mDiffuseColor = RgbColor(1, 0, 0);
-		  exporter->SetForcedMaterial(m);
-
-		  // output PVS of view cell
-		  for (; it != vc->GetPvs().mEntries.end(); ++ it) 
-		  {
-			  Intersectable *intersect = (*it).first;
-			  if (!intersect->Mailed())
-			  {
-				  exporter->ExportIntersectable(intersect);
-				  intersect->Mail();
-			  }			
-		  }
-		
-		  // output rest of the objects
-		  if (0)
-		  {
-			  Material m;//= RandomMaterial();
-			  m.mDiffuseColor = RgbColor(0, 0, 1);
-			  exporter->SetForcedMaterial(m);
-
-			  for (int j = 0; j < objects.size(); ++ j)
-				  if (!objects[j]->Mailed())
-				  {
-					  //if (j == 2198)m.mDiffuseColor = RgbColor(1, 0, 1);
-					  //else m.mDiffuseColor = RgbColor(1, 1, 0);
-					  exporter->SetForcedMaterial(m);
-					  exporter->ExportIntersectable(objects[j]);
-					  objects[j]->Mail();
-				  }
-		  }
-		  DEL_PTR(exporter);
-		}
-  }  
-
+	{
+		bool exportSplits = false;
+		environment->GetBoolValue("BspTree.exportSplits", exportSplits);
+
+		// export the bsp splits
+		if (exportSplits)
+	  		ExportSplits(objects);
+		
+		ExportBspPvs(objects);
+	}
    for (int k=0; k < pvsOut; k++) {
       Intersectable *object = objects[k];
@@ -772,4 +632,67 @@
 }
 
+bool SamplingPreprocessor::ProcessBspViewCells(bool collectSamplesForBsp,
+											   Ray &ray,
+											   Intersectable *object,
+											   int faceIndex,
+											   int &contributingSamples,
+											   int &sampleContributions)
+{
+	// save rays for bsp tree construction
+	if (collectSamplesForBsp)
+	{
+		// also add origin to sample in order to extract it as input polygons
+		MeshInstance *mi = dynamic_cast<MeshInstance *>(object);
+		ray.sourceObject = Ray::Intersection(0.0, mi, faceIndex);
+							
+        mSampleRays.push_back(new Ray(ray));
+		
+		return false;
+	}
+	
+	// construct BSP tree using the samples
+	if (!mBspTree)
+	{
+		BuildBspTree();
+		
+		contributingSamples += mBspTree->GetStat().contributingSamples;
+		sampleContributions += mBspTree->GetStat().sampleContributions;
+
+		BspTreeStatistics(Debug);	
+		if (0) Export("vc_bsptree.x3d", false, false, true);
+	}
+
+	return true;
+}
+
+// merge or subdivide view cells
+int SamplingPreprocessor::PostprocessViewCells(const RayContainer &rays)
+{
+	int merged = 0;
+	RayContainer::const_iterator rit, rit_end = rays.end();
+	vector<BspLeaf *>::const_iterator lit;
+if (0)
+	for (rit = rays.begin(); rit != rays.end(); ++ rit)
+	{  
+		// traverse leaves stored in the rays and compare and merge consecutive
+		// leaves (i.e., the neighbors in the tree)
+		lit = (*rit)->bspLeaves.begin();
+
+		BspLeaf *previousLeaf = *lit;
+		++ lit;
+		
+		for (; lit != (*rit)->bspLeaves.end(); ++ lit)
+		{
+			BspLeaf *leaf = *lit;
+			if (mBspTree->ShouldMerge(leaf, previousLeaf))
+			{			
+				mBspTree->MergeViewCells(leaf, previousLeaf);
+				++ merged;
+			}
+			previousLeaf = leaf;
+		}
+	}
+	return merged;
+}
 
 void SamplingPreprocessor::ExportSplits(const ObjectContainer &objects)
@@ -829,2 +752,120 @@
 	}
 }
+
+void SamplingPreprocessor::ExportBspPvs(const ObjectContainer &objects)
+{
+	//-- some random view cells and rays for output
+	const int leafOut = 10;
+
+	vector<Ray> vcRays[leafOut];
+	vector<BspLeaf *> bspLeaves;
+			
+	for (int i = 0; i < leafOut; ++ i)
+		bspLeaves.push_back(mBspTree->GetRandomLeaf());
+	
+	const int raysOut = min((int)mSampleRays.size(), 20000);
+
+	// check whether we can add the current ray to the output rays
+	for (int k = 0; k < raysOut; ++ k) 
+	{
+		Ray *ray = mSampleRays[k];
+
+		for (int j = 0; j < (int)ray->bspLeaves.size(); ++ j)
+		{
+			for (int i = 0; i < (int)bspLeaves.size(); ++ i)
+			{
+				if (bspLeaves[i] == ray->bspLeaves[j]) 
+				{
+					vcRays[i].push_back(*ray);
+				}
+			}
+		}
+	}
+
+	ViewCell::NewMail();
+
+	for (int i = 0; i < bspLeaves.size(); ++ i)
+	{
+		Intersectable::NewMail();
+
+		ViewCell *vc = bspLeaves[i]->GetViewCell();
+
+		//bspLeaves[j]->Mail();
+		char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
+
+		Exporter *exporter = Exporter::GetExporter(s);
+		exporter->SetFilled();
+
+		ViewCellPvsMap::iterator it = vc->GetPvs().mEntries.begin();
+
+		Material m;//= RandomMaterial();
+		m.mDiffuseColor = RgbColor(0, 1, 0);
+		exporter->SetForcedMaterial(m);
+
+		exporter->SetWireframe();
+
+		if (vc->GetMesh())
+			exporter->ExportViewCell(vc);
+		else
+		{
+            PolygonContainer cell;
+
+			mBspTree->ConstructGeometry(bspLeaves[i], cell);
+			exporter->ExportPolygons(cell);
+			CLEAR_CONTAINER(cell);
+
+			/*vector<BspLeaf *> neighbors;
+			mBspTree->FindNeighbors(bspLeaves[j], neighbors);
+			for (int j = 0; j < (int)neighbors.size(); ++ j)
+			{	if (neighbors[j]->mViewCell == bspLeaves[j]->mViewCell)
+				{}}*/
+		}
+
+		Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize() 
+				<< ", piercing rays=" << (int)vcRays[i].size() << endl;
+
+		// export view cells
+		if (0)
+		{
+			m.mDiffuseColor = RgbColor(1, 0, 1);
+			exporter->SetForcedMaterial(m);
+			exporter->ExportViewCells(mViewCells);
+		}
+
+		// export rays piercing this view cell
+		exporter->ExportRays(vcRays[i], 1000, RgbColor(0, 1, 0));
+
+		m.mDiffuseColor = RgbColor(1, 0, 0);
+		exporter->SetForcedMaterial(m);
+
+		// output PVS of view cell
+		for (; it != vc->GetPvs().mEntries.end(); ++ it) 
+		{
+			Intersectable *intersect = (*it).first;
+			if (!intersect->Mailed())
+			{
+				exporter->ExportIntersectable(intersect);
+				intersect->Mail();
+			}			
+		}
+			
+		// output rest of the objects
+		if (0)
+		{
+			Material m;//= RandomMaterial();
+			m.mDiffuseColor = RgbColor(0, 0, 1);
+			exporter->SetForcedMaterial(m);
+
+			for (int j = 0; j < objects.size(); ++ j)
+				if (!objects[j]->Mailed())
+				{
+					//if (j == 2198)m.mDiffuseColor = RgbColor(1, 0, 1);
+					//else m.mDiffuseColor = RgbColor(1, 1, 0);
+					exporter->SetForcedMaterial(m);
+					exporter->ExportIntersectable(objects[j]);
+					objects[j]->Mail();
+				}
+		}
+		DEL_PTR(exporter);
+	}
+}
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Camera.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Camera.cpp	(revision 263)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Camera.cpp	(revision 362)
@@ -102,10 +102,10 @@
     int k =0;
     for (int j=0; j < rays.size(); j++)
-      if (rays[j].leaves.size()) {
+      if (rays[j].kdLeaves.size()) {
 	Ray *ray = &(rays[j]);
 	int i;
 	if (1)
-	for (i= 0; i < ray->leaves.size(); i++)
-	  exporter->ExportBox(tree->GetBox(ray->leaves[i]));
+	for (i= 0; i < ray->kdLeaves.size(); i++)
+	  exporter->ExportBox(tree->GetBox(ray->kdLeaves[i]));
 	if (0)
 	for (i= 0; i < ray->meshes.size(); i++)
@@ -130,7 +130,8 @@
 
   ray.intersections.clear();
-  ray.leaves.clear();
+  ray.kdLeaves.clear();
   ray.meshes.clear();
-  
+  ray.bspLeaves.clear();
+
   ray.Init(mPosition, target, Ray::LOCAL_RAY);
   
