Index: trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env	(revision 479)
+++ trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env	(revision 480)
@@ -177,7 +177,7 @@
 Simulation {
 	objRenderCost 1.0
-	vcOverhead 2.0
+	vcOverhead 1.0
 	# always between 0 and 1
-	moveSpeed 0.00002
+	moveSpeed 0.0001
 }
 
@@ -223,5 +223,5 @@
 VspBspTree {
 	Construction {
-		samples 100000
+		samples 500000
 		epsilon 0.005
 	}
@@ -241,5 +241,5 @@
 	
 	# maximal tested rays for split cost heuristics
-	maxTests 500
+	maxTests 2000
 	
 	# factors for evaluating split plane costs
@@ -258,9 +258,9 @@
 		minArea 		0.0001
 		maxRayContribution	0.005
-		maxCostRatio		0.9
+		maxCostRatio		0.8
 		missTolerance		2
 		#maxAccRayLength	100
 		
-		maxViewCells		1000
+		maxViewCells		5000
 		
 		# used for pvs criterium
@@ -289,5 +289,5 @@
 	
 	PostProcess {
-		maxCostRatio 0.05
+		maxCostRatio 0.005
 		minViewCells 700
 		maxPvsSize   500
Index: trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h	(revision 479)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h	(revision 480)
@@ -263,17 +263,24 @@
 	struct SortableEntry
 	{
-		enum {POLY_MIN, POLY_MAX};
-    
+		enum EType 
+		{
+			ERayMin,
+			ERayMax
+		};
+
 		int type;
 		float value;
-		Polygon3 *poly;
+		void *data;
+  
 		SortableEntry() {}
-		SortableEntry(const int t, const float v, Polygon3 *poly): 
-		type(t), value(v), poly(poly) {}
-		
-		bool operator<(const SortableEntry &b) const 
+		SortableEntry(const int t, const float v, void *d):type(t),
+					  value(v), data(d) 
 		{
-			return value < b.value;
-		}  
+		}
+		
+		friend bool operator<(const SortableEntry &a, const SortableEntry &b) 
+		{
+			return a.value < b.value;
+		}
 	};
 
@@ -315,5 +322,5 @@
 	*/
 	float SplitPlaneCost(const Plane3 &candidatePlane, 
-						 const VspBspTraversalData &data);
+						 const VspBspTraversalData &data) const;
 
 
@@ -375,20 +382,9 @@
 	int AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent);
 
-	/** Computes best cost ratio for the suface area heuristics for axis aligned
-		splits. This heuristics minimizes the cost for ray traversal.
-		@param polys the polygons guiding the ratio computation
-		@param box the bounding box of the leaf
-		@param axis the current split axis
-		@param position returns the split position
-		@param objectsBack the number of objects in the back of the split plane
-		@param objectsFront the number of objects in the front of the split plane
-	*/
-	float BestCostRatio(const PolygonContainer &polys,
-						const AxisAlignedBox3 &box,
-						const int axis,
-						float &position,
-						int &objectsBack,
-						int &objectsFront) const;
-	
+	/** Selects a plane axis aligned.
+	*/
+	float SelectAxisAlignedPlane(Plane3 &plane, 
+								 const VspBspTraversalData &tData);
+
 	/** Sorts split candidates for surface area heuristics for axis aligned splits.
 		@param polys the input for choosing split candidates
@@ -396,7 +392,13 @@
 		@param splitCandidates returns sorted list of split candidates
 	*/
-	void SortSplitCandidates(const PolygonContainer &polys, 
-							 const int axis, 
-							 vector<SortableEntry> &splitCandidates) const;
+	void SortSplitCandidates(const RayInfoContainer &rays, const int axis);
+
+	/** Computes best cost for axis aligned planes.
+	*/
+	float BestCostRatioHeuristics(const RayInfoContainer &rays,
+								  const AxisAlignedBox3 &box,
+								  const int pvsSize,
+								  int &axis,
+								  float &position);
 
 	/** Selects an axis aligned split plane.
@@ -569,5 +571,5 @@
 	int mMergeMinViewCells;
 	/// maximal cost ratio for the merge
-	int mMergeMaxCostRatio;
+	float mMergeMaxCostRatio;
 
 	ViewCellsManager *mViewCellsManager;
@@ -575,4 +577,6 @@
 	// if rays should be stored in leaves
 	bool mStoreRays;
+
+	vector<SortableEntry> *mSplitCandidates;
 
 private:
Index: trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp	(revision 479)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp	(revision 480)
@@ -80,5 +80,6 @@
 
 VspKdNode::~VspKdNode()
-{};
+{
+};
 
 inline VspKdInterior *VspKdNode::GetParent() const
@@ -658,5 +659,4 @@
 						   int &pvsFront)
 {
-	int minDirDepth = 6;
 	int axis = 0;
 	float costRatio = 0;
@@ -665,4 +665,5 @@
 	{
 		costRatio = BestCostRatioRegular(leaf,
+										 box,
 										 axis,
 										 position,
@@ -675,4 +676,5 @@
 	{
 		costRatio = BestCostRatioHeuristic(leaf,
+										   box,
 										   axis,
 										   position,
@@ -706,4 +708,5 @@
 
 float VspKdTree::EvalCostRatio(VspKdLeaf *leaf,
+							   const AxisAlignedBox3 &box,
 							   const int axis,
 							   const float position,
@@ -725,18 +728,15 @@
 	int pvsSize = leaf->GetPvsSize();
 
-	Intersectable::NewMail(3);
-
 	// this is the main ray classification loop!
-	  for(RayInfoContainer::iterator ri = leaf->mRays.begin();
+	for(RayInfoContainer::iterator ri = leaf->mRays.begin();
 			ri != leaf->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);
-		//				(*ri).mRay->mSide = side;
-
+	{
+		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;
@@ -757,9 +757,16 @@
 	else
 	{
-		AxisAlignedBox3 box = GetBBox(leaf);
-
+#if 0
 		float minBox = box.Min(axis);
 		float maxBox = box.Max(axis);
+
 		float sizeBox = maxBox - minBox;
+#else
+
+		float minBox = AxisAlignedBox3(box.Min(), position).SurfaceArea();
+		float maxBox = AxisAlignedBox3(position, box.Max()).SurfaceArea();
+
+		float sizeBox = box.SurfaceArea();
+#endif
 
 		// float sum = raysBack*(position - minBox) + raysFront*(maxBox - position);
@@ -777,4 +784,5 @@
 
 float VspKdTree::BestCostRatioRegular(VspKdLeaf *leaf,
+									  const AxisAlignedBox3 &box,
 									  int &axis,
 									  float &position,
@@ -791,7 +799,7 @@
 	int bestAxis = -1;
 
-	AxisAlignedBox3 sBox = GetBBox(leaf);
-
-	const int sAxis = sBox.Size().DrivingAxis();
+	//AxisAlignedBox3 sBox = GetBBox(leaf);
+
+	const int sAxis = box.Size().DrivingAxis();
 
 	for (axis = 0; axis < 3; ++ axis)
@@ -800,7 +808,8 @@
 		{
 
-			nPosition[axis] = (sBox.Min()[axis] + sBox.Max()[axis]) * 0.5f;
+			nPosition[axis] = (box.Min()[axis] + box.Max()[axis]) * 0.5f;
 
 			nCostRatio[axis] = EvalCostRatio(leaf,
+											 box,
 											 axis,
 											 nPosition[axis],
@@ -838,4 +847,5 @@
 
 float VspKdTree::BestCostRatioHeuristic(VspKdLeaf *leaf,
+										const AxisAlignedBox3 &box,
 										int &axis,
 										float &position,
@@ -845,5 +855,5 @@
 										int &pvsFront)
 {
-	AxisAlignedBox3 box = GetBBox(leaf);
+	//AxisAlignedBox3 box = GetBBox(leaf);
 	//	AxisAlignedBox3 dirBox = GetDirBBox(node);
 
@@ -1065,7 +1075,7 @@
 	if (axis == -1)
 	{
+		// cost ratio missed
 		++ maxCostMisses;
-
-		if (maxCostMisses >= mTermMissTolerance)
+		if (maxCostMisses > mTermMissTolerance)
 			return leaf;
 	}
@@ -2171,7 +2181,7 @@
 
 	// collapse siblings belonging to the same view cell
-	CollapseTree(mRoot);
+	//CollapseTree(mRoot);
 	// revalidate leaves
-	RepairVcLeafLists();
+	//RepairVcLeafLists();
 
 	//Debug << "merged " << merged << " of " << savedVcSize << " leaves" << endl;
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 479)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 480)
@@ -28,4 +28,6 @@
 	~BspNodeGeometry();
 
+	/** Returns accumulated area of all polygons.
+	*/
 	float GetArea() const;
 	
@@ -39,4 +41,9 @@
 					   const float epsilon) const;
 
+	/** Computes bounding box of the node.
+	*/
+	void ComputeBoundingBox(AxisAlignedBox3 &box);
+	/** Splits the polygon and returns the part of the polygon inside of the node geometry.
+	*/
 	Polygon3 *SplitPolygon(Polygon3 *poly, const float epsilon) const;
 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h	(revision 479)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h	(revision 480)
@@ -10,4 +10,5 @@
 class Intersectable;
 class RenderSimulator;
+class Renderer;
 class Mesh;
 struct Triangle3;
@@ -192,19 +193,32 @@
 					VssRayContainer &savedRays) const;
 
-  /** Returns accumulated area of all view cells.
-  */
-  float GetAccVcArea();
-
-  /** Returns area of one view cell.
-  */
-  virtual float GetArea(ViewCell *viewCell) const;
-
-  /** Returns volume of view cells.
-  */
-  virtual float GetVolume(ViewCell *viewCell) const;
-
-  virtual AxisAlignedBox3 GetSceneBbox() const = 0;
-
+	/** Returns accumulated area of all view cells.
+	*/
+	float GetAccVcArea();
+
+	/** Returns area of one view cell.
+	*/
+	virtual float GetArea(ViewCell *viewCell) const;
+
+	/** Returns volume of view cells.
+	*/
+	virtual float GetVolume(ViewCell *viewCell) const;
+
+	virtual AxisAlignedBox3 GetSceneBbox() const = 0;
+
+	/** Sets the current renderer mainly for view cells statistics.
+	*/
+	void SetRenderer(Renderer *renderer);
+
+	
 protected:
+
+	/** Recollects view cells and resets statistics.
+	*/
+	void ResetViewCells();
+	/** Collects the view cells in the view cell container.
+	*/
+	virtual void CollectViewCells() = 0;
+
 	/** Evaluates view cells statistics and stores it in
 		mViewCellsStatistics.
@@ -215,6 +229,6 @@
 	ViewCell *mUnbounded;
 
-	/// Simulates rendering
-	RenderSimulator *mRenderSimulator;
+	/// Renders the view cells.
+	Renderer *mRenderer;
 
 	/// Loaded view cells
@@ -281,4 +295,6 @@
 protected:
 
+	void CollectViewCells();
+
 	/** Merges view cells front and back leaf view cell.
 	*/
@@ -348,12 +364,13 @@
 protected:
 
-	 KdNode *GetNodeForPvs(KdLeaf *leaf);
-
-
-	 /// the BSP tree.
-	 KdTree *mKdTree;
-
-	 /// depth of the KD tree nodes with represent the view cells
-	 int mKdPvsDepth;
+	void CollectViewCells();
+	KdNode *GetNodeForPvs(KdLeaf *leaf);
+
+
+	/// the BSP tree.
+	KdTree *mKdTree;
+
+	/// depth of the KD tree nodes with represent the view cells
+	int mKdPvsDepth;
 };
 
@@ -400,4 +417,6 @@
 protected:
 
+	void CollectViewCells();
+
 	/// the BSP tree.
 	VspKdTree *mVspKdTree;
@@ -459,4 +478,6 @@
 	bool ShouldMerge(BspLeaf *front, BspLeaf *back) const;
 
+	void CollectViewCells();
+
 	/// the view space partition BSP tree.
 	VspBspTree *mVspBspTree;
Index: trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp	(revision 479)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp	(revision 480)
@@ -84,5 +84,5 @@
 	environment->GetIntValue("VspBspTree.Termination.maxViewCells", mMaxViewCells);
 	environment->GetIntValue("VspBspTree.PostProcess.minViewCells", mMergeMinViewCells);
-	environment->GetIntValue("VspBspTree.PostProcess.maxCostRatio", mMergeMaxCostRatio);
+	environment->GetFloatValue("VspBspTree.PostProcess.maxCostRatio", mMergeMaxCostRatio);
 
 
@@ -125,4 +125,6 @@
 		Debug << "pvs";
 	}
+	
+	mSplitCandidates = new vector<SortableEntry>;
 
 	Debug << endl;
@@ -140,4 +142,5 @@
 	DEL_PTR(mRoot);
 	DEL_PTR(mRootCell);
+	DEL_PTR(mSplitCandidates);
 }
 
@@ -236,5 +239,5 @@
 	long startTime = GetTime();
 
-	cout << "Extracting polygons from rays ...";
+	cout << "Extracting polygons from rays ... ";
 
 	Intersectable::NewMail();
@@ -430,5 +433,5 @@
 		++ maxCostMisses;
 
-		if (maxCostMisses >= mTermMissTolerance)
+		if (maxCostMisses > mTermMissTolerance)
 		{
 			// terminate branch because of max cost
@@ -555,110 +558,160 @@
 }
 
-void VspBspTree::SortSplitCandidates(const PolygonContainer &polys, 
-									 const int axis, 
-									 vector<SortableEntry> &splitCandidates) const
-{
-	splitCandidates.clear();
-  
-	const int requestedSize = 2 * (int)polys.size();
-	
-	// creates a sorted split candidates array  
-	splitCandidates.reserve(requestedSize);
-  
-	PolygonContainer::const_iterator it, it_end = polys.end();
-
-	AxisAlignedBox3 box;
-
-	// insert all queries 
-	for(it = polys.begin(); it != it_end; ++ it)
-	{
-		box.Initialize();
-		box.Include(*(*it));
-	  
-		splitCandidates.push_back(SortableEntry(SortableEntry::POLY_MIN, box.Min(axis), *it));
-		splitCandidates.push_back(SortableEntry(SortableEntry::POLY_MAX, box.Max(axis), *it));
-	}
-  
-	stable_sort(splitCandidates.begin(), splitCandidates.end());
-}
-
-
-float VspBspTree::BestCostRatio(const PolygonContainer &polys,
-								const AxisAlignedBox3 &box,
-								const int axis,
-								float &position,
-								int &objectsBack,
-                                int &objectsFront) const
-{
-	vector<SortableEntry> splitCandidates;
-
-	SortSplitCandidates(polys, axis, splitCandidates);
-	
+void VspBspTree::SortSplitCandidates(const RayInfoContainer &rays, const int axis)
+{
+	mSplitCandidates->clear();
+
+	int requestedSize = 2 * (int)(rays.size());
+	// creates a sorted split candidates array
+	if (mSplitCandidates->capacity() > 500000 &&
+		requestedSize < (int)(mSplitCandidates->capacity()/10) )
+	{
+    	DEL_PTR(mSplitCandidates);
+   		mSplitCandidates = new vector<SortableEntry>;
+	}
+
+	mSplitCandidates->reserve(requestedSize);
+
+	// insert all queries
+	for(RayInfoContainer::const_iterator ri = rays.begin();	ri < rays.end(); ++ ri)
+	{
+		bool positive = (*ri).mRay->HasPosDir(axis);
+		mSplitCandidates->push_back(SortableEntry(positive ? SortableEntry::ERayMin : SortableEntry::ERayMax,
+												  (*ri).ExtrapOrigin(axis), (void *)&*ri));
+
+		mSplitCandidates->push_back(SortableEntry(positive ? SortableEntry::ERayMax : SortableEntry::ERayMin,
+												  (*ri).ExtrapTermination(axis), (void *)&*ri));
+	}
+
+	stable_sort(mSplitCandidates->begin(), mSplitCandidates->end());
+}
+
+float VspBspTree::BestCostRatioHeuristics(const RayInfoContainer &rays,
+										  const AxisAlignedBox3 &box,
+										  const int pvsSize,
+										  int &axis,
+                                          float &position)
+{
+	//	AxisAlignedBox3 dirBox = GetDirBBox(node);
+	int raysBack;
+	int raysFront;
+	int pvsBack;
+	int pvsFront;
+
+	axis = box.Size().DrivingAxis();
+
+	SortSplitCandidates(rays, axis);
+
 	// go through the lists, count the number of objects left and right
 	// and evaluate the following cost funcion:
-	// C = ct_div_ci  + (ol + or)/queries
-	
-	int objectsLeft = 0, objectsRight = (int)polys.size();
-	
+	// C = ct_div_ci  + (ql*rl + qr*rr)/queries
+
+	int rl = 0, rr = (int)rays.size();
+	int pl = 0, pr = pvsSize;
+
 	float minBox = box.Min(axis);
 	float maxBox = box.Max(axis);
-	float boxArea = box.SurfaceArea();
-  
-	float minBand = minBox + mAxisAlignedSplitBorder * (maxBox - minBox);
-	float maxBand = minBox + (1.0f - mAxisAlignedSplitBorder) * (maxBox - minBox);
-	
+	float sizeBox = maxBox - minBox;
+
+	float minBand = minBox + 0.1f*(maxBox - minBox);
+	float maxBand = minBox + 0.9f*(maxBox - minBox);
+
+	float sum = rr*sizeBox;
 	float minSum = 1e20f;
-	vector<SortableEntry>::const_iterator ci, ci_end = splitCandidates.end();
-
-	for(ci = splitCandidates.begin(); ci != ci_end; ++ ci) 
-	{
-		switch ((*ci).type) 
-		{
-			case SortableEntry::POLY_MIN:
-				++ objectsLeft;
-				break;
-			case SortableEntry::POLY_MAX:
-			    -- objectsRight;
-				break;
-			default:
-				break;
-		}
-		
-		if ((*ci).value > minBand && (*ci).value < maxBand) 
-		{
-			AxisAlignedBox3 lbox = box;
-			AxisAlignedBox3 rbox = box;
-			lbox.SetMax(axis, (*ci).value);
-			rbox.SetMin(axis, (*ci).value);
-
-			float sum = objectsLeft * lbox.SurfaceArea() + 
-						objectsRight * rbox.SurfaceArea();
-      
-			if (sum < minSum) 
+
+	Intersectable::NewMail();
+
+	// set all object as belonging to the fron pvs
+	for(RayInfoContainer::const_iterator ri = rays.begin(); ri != rays.end(); ++ ri)
+	{
+		if ((*ri).mRay->IsActive())
+		{
+			Intersectable *object = (*ri).mRay->mTerminationObject;
+
+			if (object)
+				if (!object->Mailed())
+				{
+					object->Mail();
+					object->mCounter = 1;
+				}
+				else
+					++ object->mCounter;
+		}
+	}
+
+	Intersectable::NewMail();
+
+	for (vector<SortableEntry>::const_iterator ci = mSplitCandidates->begin();
+		ci < mSplitCandidates->end(); ++ ci)
+	{
+		VssRay *ray;
+
+		switch ((*ci).type)
+		{
+			case SortableEntry::ERayMin:
+				{
+					++ rl;
+					ray = (VssRay *) (*ci).data;
+					Intersectable *object = ray->mTerminationObject;
+					if (object && !object->Mailed())
+					{
+						object->Mail();
+						++ pl;
+					}
+					break;
+				}
+			case SortableEntry::ERayMax:
+				{
+					-- rr;
+
+					ray = (VssRay *) (*ci).data;
+					Intersectable *object = ray->mTerminationObject;
+
+					if (object)
+					{
+						if (-- object->mCounter == 0)
+						-- pr;
+					}
+
+					break;
+				}
+		}
+
+		// Note: sufficient to compare size of bounding boxes of front and back side?
+		if ((*ci).value > minBand && (*ci).value < maxBand)
+		{
+			sum = pl*((*ci).value - minBox) + pr*(maxBox - (*ci).value);
+
+			//  cout<<"pos="<<(*ci).value<<"\t q=("<<ql<<","<<qr<<")\t r=("<<rl<<","<<rr<<")"<<endl;
+			// cout<<"cost= "<<sum<<endl;
+
+			if (sum < minSum)
 			{
 				minSum = sum;
 				position = (*ci).value;
 
-				objectsBack = objectsLeft;
-				objectsFront = objectsRight;
+				raysBack = rl;
+				raysFront = rr;
+
+				pvsBack = pl;
+				pvsFront = pr;
+
 			}
 		}
 	}
-  
-	const float oldCost = (float)polys.size();
-	const float newCost = mAxisAlignedCtDivCi + minSum / boxArea;
-	const float ratio = newCost / oldCost;
-
-
-#if 0
-  Debug << "====================" << endl;
-  Debug << "costRatio=" << ratio << " pos=" << position<<" t=" << (position - minBox)/(maxBox - minBox)
-      << "\t o=(" << objectsBack << "," << objectsFront << ")" << endl;
-#endif
-  return ratio;
-}
-
-bool VspBspTree::SelectAxisAlignedPlane(Plane3 &plane,
-                                        const PolygonContainer &polys) const
+
+	float oldCost = (float)pvsSize;
+	float newCost = mCtDivCi + minSum / sizeBox;
+	float ratio = newCost / oldCost;
+
+	//Debug << "costRatio=" << ratio << " pos=" << position << " t=" << (position - minBox) / (maxBox - minBox)
+	//     <<"\t q=(" << queriesBack << "," << queriesFront << ")\t r=(" << raysBack << "," << raysFront << ")" << endl;
+
+	return ratio;
+}
+
+
+float VspBspTree::SelectAxisAlignedPlane(Plane3 &plane, 
+										 const VspBspTraversalData &tData)
 {
 	AxisAlignedBox3 box;
@@ -666,33 +719,73 @@
 	
 	// create bounding box of region
-	Polygon3::IncludeInBox(polys, box);
-        
-	int objectsBack = 0, objectsFront = 0;
+	RayInfoContainer::const_iterator ri, ri_end = tData.mRays->end();
+
+	for(ri = tData.mRays->begin(); ri < ri_end; ++ ri)
+		box.Include((*ri).ExtrapTermination());
+
 	int axis = 0;
-	float costRatio = MAX_FLOAT;
-	Vector3 position;
-
-	//-- area subdivision
-	for (int i = 0; i < 3; ++ i) 
-	{
-		float p = 0;
-		const float r = BestCostRatio(polys, box, i, p, objectsBack, objectsFront);
+	const bool useCostHeuristics = false;
+
+	if (useCostHeuristics)
+	{
+		float position;
+
+		const float ratio = 
+			BestCostRatioHeuristics(*tData.mRays,
+								    box,
+									tData.mPvs,
+									axis,
+									position);
+
+		Vector3 normal(0,0,0); normal[axis] = 1;
+		plane = Plane3(normal, position);
+
+		return ratio;
+	}
+
+	//-- regular split
+	float nPosition[3];
+	float nCostRatio[3];
+	int bestAxis = -1;
+
+	bool mOnlyDrivingAxis = false;
+
+	const int sAxis = box.Size().DrivingAxis();
 		
-		if (r < costRatio)
-		{
-			costRatio = r;
-			axis = i;
-			position = p;
-		}
-	}
-	
-	if (costRatio >= mTermMaxCostRatio)
-		return false;
-
-	Vector3 norm(0,0,0); norm[axis] = 1.0f;
-	plane = Plane3(norm, position);
-
-	return true;
-}
+	for (axis = 0; axis < 3; ++ axis)
+	{
+		if (!mOnlyDrivingAxis || axis == sAxis)
+		{
+			if (!useCostHeuristics)
+			{
+				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);
+			}
+			
+			if (bestAxis == -1)
+			{
+				bestAxis = axis;
+			}
+
+			else if (nCostRatio[axis] < nCostRatio[bestAxis])
+			{
+				/*Debug << "pvs front " << nPvsBack[axis]
+					  << " pvs back " << nPvsFront[axis]
+					  << " overall pvs " << leaf->GetPvsSize() << endl;*/
+				bestAxis = axis;
+			}
+
+		}
+	}
+
+	//-- assign best axis
+	Vector3 normal(0,0,0); normal[bestAxis] = 1;
+	plane = Plane3(normal, nPosition[bestAxis]);
+
+	return nCostRatio[bestAxis];
+}
+
 
 bool VspBspTree::SelectPlane(Plane3 &plane, 
@@ -700,10 +793,4 @@
 							 VspBspTraversalData &data)
 {
-	if ((mSplitPlaneStrategy & AXIS_ALIGNED) &&
-		((int)data.mRays->size() > mTermMinRaysForAxisAligned))
-	{	// TODO: candidates should be rays
-		return SelectAxisAlignedPlane(plane, *data.mPolygons); 
-	}
-
 	// simplest strategy: just take next polygon
 	if (mSplitPlaneStrategy & RANDOM_POLYGON)
@@ -740,4 +827,5 @@
 }
 
+
 Plane3 VspBspTree::ChooseCandidatePlane(const RayInfoContainer &rays) const
 {	
@@ -752,4 +840,5 @@
 	return Plane3(normal, pt);
 }
+
 
 Plane3 VspBspTree::ChooseCandidatePlane2(const RayInfoContainer &rays) const
@@ -822,4 +911,6 @@
 	int maxIdx = (int)data.mPolygons->size();
 	
+	float candidateCost;
+
 	for (int i = 0; i < limit; ++ i)
 	{
@@ -836,6 +927,5 @@
 
 		// evaluate current candidate
-		const float candidateCost = 
-			SplitPlaneCost(poly->GetSupportingPlane(), data);
+		candidateCost = SplitPlaneCost(poly->GetSupportingPlane(), data);
 
 		if (candidateCost < lowestCost)
@@ -846,4 +936,5 @@
 	}
 	
+#if 0
 	//-- choose candidate planes extracted from rays
 	//-- different methods are available
@@ -851,5 +942,5 @@
 	{
 		plane = ChooseCandidatePlane3(*data.mRays);
-		const float candidateCost = SplitPlaneCost(plane, data);
+		candidateCost = SplitPlaneCost(plane, data);
 
 		if (candidateCost < lowestCost)
@@ -858,4 +949,14 @@
 			lowestCost = candidateCost;
 		}
+	}
+#endif
+
+	// axis aligned splits
+	candidateCost = SelectAxisAlignedPlane(plane, data); 
+
+	if (candidateCost < lowestCost)
+	{
+		bestPlane = plane;	
+		lowestCost = candidateCost;
 	}
 
@@ -880,5 +981,5 @@
 
 float VspBspTree::SplitPlaneCost(const Plane3 &candidatePlane, 
-								 const VspBspTraversalData &data)
+								 const VspBspTraversalData &data) const
 {
 	float cost = 0;
@@ -1957,13 +2058,10 @@
 	int merged = 0;
 
-	Debug << "mergecost: " << mergeQueue.top().GetMergeCost() / BspMergeCandidate::sOverallCost << " " << mMergeMaxCostRatio << endl;
-	Debug << "overall cost: " << BspMergeCandidate::sOverallCost << endl;
-
-	// use priority queue to merge leaves
+	//-- use priority queue to merge leaf pairs
 	while (!mergeQueue.empty() && (vcSize > mMergeMinViewCells) &&
 		   (mergeQueue.top().GetMergeCost() < 
 		    mMergeMaxCostRatio * BspMergeCandidate::sOverallCost))
 	{
-		Debug << "mergecost: " << mergeQueue.top().GetMergeCost() / BspMergeCandidate::sOverallCost << " " << mMergeMaxCostRatio << endl;
+		//Debug << "mergecost: " << mergeQueue.top().GetMergeCost() / BspMergeCandidate::sOverallCost << " " << mMergeMaxCostRatio << endl;
 		BspMergeCandidate mc = mergeQueue.top();
 		mergeQueue.pop();
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp	(revision 478)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp	(revision 480)
@@ -1490,5 +1490,5 @@
 			optFloat,
 			"-vsp_kd_post_process_max_cost_ratio=",
-			"1.5");
+			"0.9");
 
 	RegisterOption("VspKdTree.PostProcess.minViewCells", 
@@ -1758,5 +1758,5 @@
 			optFloat,
 			"-vsp_bsp_post_process_max_cost_ratio=",
-			"1.5");
+			"0.9");
 
 	RegisterOption("VspBspTree.PostProcess.minViewCells", 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 479)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 480)
@@ -976,25 +976,25 @@
 								  vector<SortableEntry> &splitCandidates) const
 {
-  splitCandidates.clear();
-  
-  int requestedSize = 2 * (int)polys.size();
-  // creates a sorted split candidates array  
-  splitCandidates.reserve(requestedSize);
-  
-  PolygonContainer::const_iterator it, it_end = polys.end();
-
-  AxisAlignedBox3 box;
-
-  // insert all queries 
-  for(it = polys.begin(); it != it_end; ++ it)
-  {
-	  box.Initialize();
-	  box.Include(*(*it));
-	  
-	  splitCandidates.push_back(SortableEntry(SortableEntry::POLY_MIN, box.Min(axis), *it));
-      splitCandidates.push_back(SortableEntry(SortableEntry::POLY_MAX, box.Max(axis), *it));
-  }
-  
-  stable_sort(splitCandidates.begin(), splitCandidates.end());
+	splitCandidates.clear();
+
+	int requestedSize = 2 * (int)polys.size();
+	// creates a sorted split candidates array  
+	splitCandidates.reserve(requestedSize);
+
+	PolygonContainer::const_iterator it, it_end = polys.end();
+
+	AxisAlignedBox3 box;
+
+	// insert all queries 
+	for(it = polys.begin(); it != it_end; ++ it)
+	{
+		box.Initialize();
+		box.Include(*(*it));
+		
+		splitCandidates.push_back(SortableEntry(SortableEntry::POLY_MIN, box.Min(axis), *it));
+		splitCandidates.push_back(SortableEntry(SortableEntry::POLY_MAX, box.Max(axis), *it));
+	}
+
+	stable_sort(splitCandidates.begin(), splitCandidates.end());
 }
 
@@ -2612,2 +2612,7 @@
 	return planePoly;
 }
+
+void BspNodeGeometry::ComputeBoundingBox(AxisAlignedBox3 &box)
+{
+	Polygon3::IncludeInBox(mPolys, box);
+}
Index: trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.cpp	(revision 479)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.cpp	(revision 480)
@@ -83,5 +83,5 @@
 		// and the probability that a view cell border is crossed
 		loadPvsOverhead += GetCrossVcProbability() * mVcOverhead;
-
+		//Debug << "vccost: " << vcCost << " p in vc " << pInVc << " cross vc " << GetCrossVcProbability() << endl;
 		//-- update statistics
 		renderTime += vcCost;
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 478)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 480)
@@ -236,4 +236,5 @@
 	mViewCellsManager->SetPostProcessSamples(postProcessSamples);
 	mViewCellsManager->SetVisualizationSamples(visSamples);
+	mViewCellsManager->SetRenderer(mRenderSimulator);
 
 	//Debug << "Visualization samples: " << mViewCellsManager->GetVisualizationSamples() << endl;
Index: trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.h	(revision 479)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.h	(revision 480)
@@ -629,4 +629,5 @@
   
 	float BestCostRatioHeuristic(VspKdLeaf *node,
+								 const AxisAlignedBox3 &box,
 								 int &axis,
 								 float &position,
@@ -636,5 +637,6 @@
 								 int &pvsFront);
 
-	float BestCostRatioRegular(VspKdLeaf *node, 
+	float BestCostRatioRegular(VspKdLeaf *node,
+							   const AxisAlignedBox3 &box,
 							   int &axis,
 							   float &position,
@@ -645,4 +647,5 @@
 	
 	float EvalCostRatio(VspKdLeaf *node,
+						const AxisAlignedBox3 &box,
 						const int axis,
 						const float position,
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp	(revision 479)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp	(revision 480)
@@ -14,5 +14,5 @@
 
 ViewCellsManager::ViewCellsManager():
-mRenderSimulator(NULL),
+mRenderer(NULL),
 mConstructionSamples(0),
 mPostProcessSamples(0),
@@ -29,5 +29,5 @@
 ViewCellsManager::ViewCellsManager(int constructionSamples):
 mConstructionSamples(constructionSamples),
-mRenderSimulator(NULL),
+mRenderer(NULL),
 mPostProcessSamples(0),
 mVisualizationSamples(0)
@@ -41,5 +41,5 @@
 ViewCellsManager::~ViewCellsManager()
 {
-	DEL_PTR(mRenderSimulator);
+	DEL_PTR(mRenderer);
 
 	CLEAR_CONTAINER(mViewCells);
@@ -176,4 +176,8 @@
 }
 
+void ViewCellsManager::SetRenderer(Renderer *renderer)
+{
+	mRenderer = renderer;
+}
 
 ViewCell *ViewCellsManager::GenerateViewCell(Mesh *mesh) const
@@ -236,6 +240,5 @@
 }
 
-void
-ViewCellsManager::PrintPvsStatistics(ostream &s)
+void ViewCellsManager::PrintPvsStatistics(ostream &s)
 {
   s<<"############# Viewcell PVS STAT ##################\n";
@@ -252,4 +255,14 @@
 }
 
+void ViewCellsManager::ResetViewCells()
+{
+	mViewCells.clear();
+	CollectViewCells();
+	mViewCellsStats.Reset();
+	EvaluateViewCellsStats();
+
+	mTotalAreaValid = false;
+}
+
 void ViewCellsManager::ComputeSampleContributions(VssRay &ray)
 {
@@ -313,6 +326,9 @@
 
 	for (it = mViewCells.begin(); it != it_end; ++ it)
+	{
+		//Debug << "area: " << GetArea(*it);
         mTotalArea += GetArea(*it);
-	
+	}
+
 	mTotalAreaValid = true;
 
@@ -343,8 +359,10 @@
 }
 
+
 ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
 {
 	return new BspViewCell(mesh);
 }
+
 
 int BspViewCellsManager::Construct(const ObjectContainer &objects, 
@@ -388,6 +406,4 @@
 	}
 
-	EvaluateViewCellsStats();
-
 	// destroy rays created only for construction
 	CLEAR_CONTAINER(constructionRays);
@@ -395,4 +411,7 @@
 	Debug << mBspTree->GetStatistics() << endl;
 	
+	EvaluateViewCellsStats();
+	Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
+
 	// recast rest of the rays
 	ComputeSampleContributions(savedRays);
@@ -401,4 +420,8 @@
 }
 
+void BspViewCellsManager::CollectViewCells()
+{
+	mBspTree->CollectViewCells(mViewCells);
+}
 
 float BspViewCellsManager::GetProbability(ViewCell *viewCell)
@@ -449,6 +472,13 @@
 	int pvsSize = 0;
 
+	EvaluateViewCellsStats();
 	Debug << "original view cell partition:\n" << mViewCellsStats << endl;
-		
+
+	mRenderer->RenderScene();
+	SimulationStatistics ss;
+	dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
+
+    Debug << ss << endl;
+
 	if (1) // export view cells
 	{
@@ -529,9 +559,5 @@
 	
 	// reset view cells and stats
-	mViewCells.clear();
-	mTotalAreaValid = false;
-	mBspTree->CollectViewCells(mViewCells);
-	mViewCellsStats.Reset();
-	EvaluateViewCellsStats();
+	ResetViewCells();
 
 	return merged;
@@ -876,4 +902,8 @@
 }
 
+void KdViewCellsManager::CollectViewCells()
+{
+	//mKdTree->CollectViewCells(mViewCells); TODO
+}
 
 int KdViewCellsManager::Construct(const ObjectContainer &objects, 
@@ -887,7 +917,13 @@
 	mKdTree->Construct();
 
+	mTotalAreaValid = false;
 	// create the view cells
 	mKdTree->CreateAndCollectViewCells(mViewCells);
+	
+	// cast rays
+	ComputeSampleContributions(rays);
+
 	EvaluateViewCellsStats();
+	Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
 
 	return 0;
@@ -1119,8 +1155,9 @@
 {
 	// volume or area substitutes for view point probability
-	AxisAlignedBox3 box = mVspKdTree->GetBBox(mVspKdTree->GetRoot());
-
-	return GetArea(viewCell) / box.SurfaceArea();
-	//return GetArea(viewCell) / GetAccVcArea();
+#if 0
+	return GetArea(viewCell) / GetSceneBbox().SurfaceArea();
+#else
+	return GetArea(viewCell) / GetAccVcArea();
+#endif
 }
 
@@ -1131,4 +1168,8 @@
 }
 
+void VspKdViewCellsManager::CollectViewCells()
+{
+	mVspKdTree->CollectViewCells(mViewCells);
+}
 
 int VspKdViewCellsManager::Construct(const ObjectContainer &objects, 
@@ -1149,8 +1190,8 @@
 
 	mVspKdTree->Construct(constructionRays, sceneBbox);
-	mVspKdTree->CollectViewCells(mViewCells);
-	EvaluateViewCellsStats();
-
 	Debug << mVspKdTree->GetStatistics() << endl;
+
+	ResetViewCells();
+	Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
 
 	// finally merge kd leaf building blocks to view cells
@@ -1352,4 +1393,10 @@
 
 
+void VspBspViewCellsManager::CollectViewCells()
+{
+	mVspBspTree->CollectViewCells(mViewCells);
+}
+
+
 float VspBspViewCellsManager::GetRendercost(ViewCell *viewCell, 
 											float objRendercost) const
@@ -1392,9 +1439,9 @@
 	
 	mVspBspTree->Construct(constructionRays);
-	mVspBspTree->CollectViewCells(mViewCells);
-	EvaluateViewCellsStats();
-
 	Debug << mVspBspTree->GetStatistics() << endl;
-	
+
+	ResetViewCells();
+
+	Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
 	// recast rest of rays
 	ComputeSampleContributions(savedRays);
@@ -1447,6 +1494,12 @@
 	int pvsSize = 0;
 
+	EvaluateViewCellsStats();
 	Debug << "original view cell partition:\n" << mViewCellsStats << endl;
-		
+
+	mRenderer->RenderScene();
+	SimulationStatistics ss;
+	dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
+    Debug << ss << endl;
+
 	if (1) // export view cells
 	{
@@ -1532,9 +1585,5 @@
 	
 	// reset view cells and stats
-	mViewCells.clear();
-	mTotalAreaValid = false;
-	mVspBspTree->CollectViewCells(mViewCells);
-	mViewCellsStats.Reset();
-	EvaluateViewCellsStats();
+	ResetViewCells();
 
 	return merged;
