Index: trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env	(revision 481)
+++ trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env	(revision 482)
@@ -146,7 +146,7 @@
 	loadFromFile false
 	#type kdTree
-	#type vspKdTree
+	type vspKdTree
 	#type bspTree
-	type vspBspTree
+	#type vspBspTree
 	
 	#type sceneDependent
@@ -166,4 +166,8 @@
 		# how much samples are be used for visualization
 		samples 90000
+		#colorCode PVS
+		#colorCode MergedLeaves
+		#colorCode MergedTreeDiff
+		colorCode Random
 	}
 	
@@ -192,10 +196,10 @@
 	Termination {
 		maxDepth	 	40
-		minPvs			5
-		minRays			500
+		minPvs			50
+		minRays			300
 		minSize			0.1
-		maxCostRatio		0.9
-		missTolerance		4
-		maxRayContribution 	0.2
+		maxCostRatio		1.8
+		missTolerance		2
+		maxRayContribution 	0.5
 	}
 	
@@ -209,6 +213,6 @@
 	# maximal cost for merging a view cell
 	PostProcess {
-		maxCostRatio 1.4
-		minViewCells 100
+		maxCostRatio 0.005
+		minViewCells 300
 		maxPvsSize   50000
 	}
@@ -216,5 +220,5 @@
 	
 	Visualization {
-		exportRays true
+		exportRays false
 		exportGeometry false
 	}
@@ -223,5 +227,5 @@
 VspBspTree {
 	Construction {
-		samples 500000
+		samples 300000
 		epsilon 0.005
 	}
@@ -258,13 +262,13 @@
 		minArea 		0.0001
 		maxRayContribution	0.005
-		maxCostRatio		0.8
+		maxCostRatio		0.9
 		missTolerance		2
 		#maxAccRayLength	100
 		
-		maxViewCells		5000
+		maxViewCells		1000
 		
 		# used for pvs criterium
 		ct_div_ci 0.0
-	
+	}
 	
 	Visualization {
@@ -277,5 +281,5 @@
 	PostProcess {
 		maxCostRatio 0.005
-		minViewCells 700
+		minViewCells 100
 		maxPvsSize   500
 	}
Index: trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h	(revision 481)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h	(revision 482)
@@ -191,8 +191,4 @@
 	enum {FROM_INPUT_VIEW_CELLS, FROM_SCENE_GEOMETRY, FROM_SAMPLES};
 
-	/** Returns statistics.
-	*/
-	BspTreeStatistics &GetStat();
-
 	/** finds neighbouring leaves of this tree node.
 	*/
@@ -255,4 +251,8 @@
 	BspNode *CollapseTree(BspNode *node);
 	
+
+	/** Returns distance from node 1 to node 2.
+	*/
+	int TreeDistance(BspNode *n1, BspNode *n2);
 
 protected:
@@ -271,9 +271,9 @@
 		int type;
 		float value;
-		void *data;
+		VssRay *ray;
   
 		SortableEntry() {}
-		SortableEntry(const int t, const float v, void *d):type(t),
-					  value(v), data(d) 
+		SortableEntry(const int t, const float v, VssRay *r):type(t),
+					  value(v), ray(r) 
 		{
 		}
@@ -580,4 +580,7 @@
 	vector<SortableEntry> *mSplitCandidates;
 
+	bool mOnlyDrivingAxis;
+
+
 private:
 	
Index: trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp	(revision 480)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp	(revision 482)
@@ -343,6 +343,5 @@
 
 
-
-VspKdTree::VspKdTree(): mOnlyDrivingAxis(true)
+VspKdTree::VspKdTree(): mOnlyDrivingAxis(false)
 {
 	environment->GetIntValue("VspKdTree.Termination.maxDepth", mTermMaxDepth);
@@ -431,8 +430,8 @@
 	app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n";
 
-	app << "#N_SPLITS ( Number of splits in axes x y z dx dy dz \n";
-
-	for (int i=0; i<7; i++)
-		app << splits[i] <<" ";
+	app << "#N_SPLITS ( Number of splits in axes x y z\n";
+
+	for (int i = 0; i < 3; ++ i)
+		app << splits[i] << " ";
 	app << endl;
 
@@ -466,4 +465,7 @@
 		maxRayContribNodes * 100 / (double)Leaves() << endl;
 
+	app << "#N_PMAXRCOSTLEAVES  ( Percentage of leaves with maximal cost ratio )\n" <<
+		maxCostNodes * 100 / (double)Leaves() << endl;
+
 	app << "#N_ADDED_RAYREFS  ( Number of dynamically added ray references )\n"<<
 		addedRayRefs << endl;
@@ -476,4 +478,7 @@
 	app << "#N_( Maximal PVS size / leaf)\n"
 		<< maxPvsSize << endl;
+
+	app << "#N_( Average PVS size / leaf)\n"
+		<< (double) accPvsSize / (double)Leaves() << endl;
 
 	app << "#N_CTIME  ( Construction time [s] )\n"
@@ -550,8 +555,7 @@
 		//leaf->AddRay(RayInfo(*ri));
 		VssRay *ray = *ri;
-
 		float minT, maxT;
-
-		// TODO: not very efficient to implictly cast between rays types ...
+		
+		// TODO: not very efficient to implictly cast between rays types!
 		if (mBox.GetRaySegment(*ray, minT, maxT))
 		{
@@ -692,6 +696,11 @@
 	if (costRatio > mTermMaxCostRatio)
 	{
-		Debug << "Too big cost ratio " << costRatio << endl;
-		return -1;
+		//Debug << "Too big cost ratio " << costRatio << endl;
+		++ leaf->mMaxCostMisses;
+		if (leaf->mMaxCostMisses > mTermMissTolerance)
+		{
+			++ mStat.maxCostNodes;
+			return -1;
+		}
 	}
 
@@ -721,10 +730,8 @@
 	pvsBack = 0;
 
-	float newCost;
-
 	Intersectable::NewMail(3);
 
 	// eval pvs size
-	int pvsSize = leaf->GetPvsSize();
+	const int pvsSize = leaf->GetPvsSize();
 
 	// this is the main ray classification loop!
@@ -748,37 +755,75 @@
 	}
 
+	//-- only one of these options should be one
+
+	if (0) //-- only pvs
+	{
+		const float sum = float(pvsBack + pvsFront);
+		const float oldCost = (float)pvsSize;
+
+		return sum / oldCost;
+	}
+
+	//-- pvs + probability heuristics
+	float pBack, pFront, pOverall;
+
 	if (0)
 	{
-		const float sum = float(pvsBack + pvsFront);
-		const float oldCost = (float)pvsSize * 2;
-
-		return sum / oldCost;
-	}
-	else
-	{
-#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);
-		const float sum = pvsBack * (position - minBox) + pvsFront * (maxBox - position);
-
-		newCost = mCtDivCi + sum  / sizeBox;
-
-		//Debug << axis << " " << pvsSize << " " << pvsBack << " " << pvsFront << endl;
-		//  float oldCost = leaf->mRays.size();
-		const float oldCost = (float)pvsSize;
-
-		return newCost / oldCost;
-	}
+		// box length substitute for probability
+		const float minBox = box.Min(axis);
+		const float maxBox = box.Max(axis);
+
+		pBack = position - minBox;
+		pFront = maxBox - position;
+		pOverall = maxBox - minBox;
+	}
+
+	if (1) //-- area substitute for probability
+	{
+		
+		const bool useMidSplit = true;
+		//const bool useMidSplit = false;
+			
+		pOverall = box.SurfaceArea();
+			
+		if (!useMidSplit)
+		{
+			Vector3 pos = box.Max(); pos[axis] = position;
+			pBack = AxisAlignedBox3(box.Min(), pos).SurfaceArea();
+
+			pos = box.Min(); pos[axis] = position;
+			pFront = AxisAlignedBox3(pos, box.Max()).SurfaceArea();
+		}
+		else
+		{
+			//-- simplified computation for mid split
+			const int axis2 = (axis + 1) % 3;
+			const int axis3 = (axis + 2) % 3;
+
+			const float faceArea = 
+				(box.Max(axis2) - box.Min(axis2)) *
+				(box.Max(axis3) - box.Min(axis3));
+
+			pBack = pFront = pOverall * 0.5f + faceArea;
+		}
+	}
+
+	//-- ray density substitute for probability
+	if (1)
+	{
+		pBack = (float)raysBack;
+		pFront = (float)raysFront;
+		pOverall = (float)leaf->mRays.size();
+	}
+
+	//Debug << axis << " " << pvsSize << " " << pvsBack << " " << pvsFront << endl;
+	//Debug << pFront << " " << pBack << " " << pOverall << endl;
+
+	// float sum = raysBack*(position - minBox) + raysFront*(maxBox - position);
+	const float newCost = pvsBack * pBack + pvsFront * pFront;
+	//  float oldCost = leaf->mRays.size();
+	const float oldCost = (float)pvsSize * pOverall;
+
+	return  (mCtDivCi + newCost) / oldCost;
 }
 
@@ -800,5 +845,4 @@
 
 	//AxisAlignedBox3 sBox = GetBBox(leaf);
-
 	const int sAxis = box.Size().DrivingAxis();
 
@@ -912,5 +956,5 @@
 				{
 					++ rl;
-					ray = (VssRay *) (*ci).data;
+					ray = (*ci).ray;
 					Intersectable *object = ray->mTerminationObject;
 					if (object && !object->Mailed())
@@ -925,5 +969,5 @@
 					-- rr;
 
-					ray = (VssRay *) (*ci).data;
+					ray = (*ci).ray;
 					Intersectable *object = ray->mTerminationObject;
 
@@ -992,8 +1036,8 @@
 		bool positive = (*ri).mRay->HasPosDir(axis);
 		mSplitCandidates->push_back(SortableEntry(positive ? SortableEntry::ERayMin : SortableEntry::ERayMax,
-												  (*ri).ExtrapOrigin(axis), (void *)&*ri));
+												  (*ri).ExtrapOrigin(axis), (*ri).mRay));
 
 		mSplitCandidates->push_back(SortableEntry(positive ? SortableEntry::ERayMax : SortableEntry::ERayMin,
-												  (*ri).ExtrapTermination(axis), (void *)&*ri));
+												  (*ri).ExtrapTermination(axis), (*ri).mRay));
 	}
 
@@ -1013,4 +1057,5 @@
 		mStat.maxRayRefs = (int)leaf->mRays.size();
 
+	mStat.rays += (int)leaf->mRays.size();
 
 	if (data.mDepth >= mTermMaxDepth)
@@ -1020,4 +1065,6 @@
 		++ mStat.minPvsNodes;
 
+	mStat.accPvsSize += leaf->GetPvsSize();
+
 	if ((int)leaf->GetRays().size() < mTermMinRays)
 		++ mStat.minRaysNodes;
@@ -1036,5 +1083,5 @@
 	return ((leaf->GetPvsSize() < mTermMinPvs) ||
 		    (leaf->mRays.size() < mTermMinRays) ||
-			//(leaf->GetAvgRayContribution() > mTermMaxRayContribution ) ||
+			(leaf->GetAvgRayContribution() > mTermMaxRayContribution ) ||
 			(leaf->mDepth >= mTermMaxDepth) ||
 			(SqrMagnitude(box.Size()) <= mTermMinSize));
@@ -1068,19 +1115,11 @@
 	// select subdivision axis
 	const int axis = SelectPlane(leaf, box, position, raysBack, raysFront, pvsBack, pvsFront);
-
 	//Debug << "rays back=" << raysBack << " rays front=" << raysFront << " pvs back=" << pvsBack << " pvs front=" <<	pvsFront << endl;
 
-	int maxCostMisses = leaf->GetMaxCostMisses();
-
 	if (axis == -1)
-	{
-		// cost ratio missed
-		++ maxCostMisses;
-		if (maxCostMisses > mTermMissTolerance)
-			return leaf;
-	}
-
+		return leaf;
+	
 	mStat.nodes += 2;
-	//++ mStat.splits[axis];
+	++ mStat.splits[axis];
 
 	// add the new nodes to the tree
@@ -1094,7 +1133,7 @@
 	frontBBox = box;
 
-	VspKdLeaf *back = new VspKdLeaf(node, raysBack, maxCostMisses);
+	VspKdLeaf *back = new VspKdLeaf(node, raysBack, leaf->GetMaxCostMisses());
 	back->SetPvsSize(pvsBack);
-	VspKdLeaf *front = new VspKdLeaf(node, raysFront, maxCostMisses);
+	VspKdLeaf *front = new VspKdLeaf(node, raysFront, leaf->GetMaxCostMisses());
 	front->SetPvsSize(pvsFront);
 
@@ -1686,7 +1725,8 @@
 
 		}
-		else {
+		else
+		{
 			VspKdInterior *in = (VspKdInterior *)node;
-			// both nodes for directional splits
+			
 			tstack.push(in->GetFront());
 			tstack.push(in->GetBack());
@@ -1733,5 +1773,5 @@
 			VspKdInterior *in =
 				dynamic_cast<VspKdInterior *>(node);
-			// both nodes for directional splits
+		
 			tstack.push(in->GetFront());
 			tstack.push(in->GetBack());
@@ -1767,5 +1807,5 @@
 		{
 			VspKdInterior *in = (VspKdInterior *)node;
-			// both nodes for directional splits
+			
 			tstack.push(in->GetFront());
 			tstack.push(in->GetBack());
@@ -1832,4 +1872,5 @@
 }
 
+
 int VspKdTree::ComputePvsSize(VspKdNode *node,
 							  const RayInfoContainer &globalRays) const
@@ -1840,4 +1881,6 @@
 
 	RayInfoContainer::const_iterator it, it_end = globalRays.end();
+
+	// TODO
 
 	// warning: implicit conversion from VssRay to Ray
@@ -1847,4 +1890,5 @@
 	return pvsSize;
 }
+
 
 void VspKdTree::CollectLeaves(vector<VspKdLeaf *> &leaves) const
@@ -2065,4 +2109,6 @@
 	// set new size of view cell
 	vc->SetVolume(fVc->GetVolume() + bVc->GetVolume());
+	// new area
+	vc->SetArea(fVc->GetArea() + bVc->GetArea());
 
 	vector<VspKdLeaf *> fLeaves = fVc->mLeaves;
@@ -2143,13 +2189,10 @@
 	int merged = 0;
 
-	//Debug << mMinViewCells << " " << mMaxCostRatio << endl;
-
 	// use priority queue to merge leaves
-	while (!mergeQueue.empty() &&
-		   (vcSize > mMergeMinViewCells) &&
+	while (!mergeQueue.empty() && (vcSize > mMergeMinViewCells) &&
 		   (mergeQueue.top().GetMergeCost() < 
-		    mMergeMaxCostRatio / MergeCandidate::sOverallCost))
-	{
-		//Debug << mergeQueue.top().GetMergeCost() << " " << mMaxCostRatio << endl;
+		    mMergeMaxCostRatio * MergeCandidate::sOverallCost))
+	{
+		//Debug << "mergecost: " << mergeQueue.top().GetMergeCost() / MergeCandidate::sOverallCost << " " << mMergeMaxCostRatio << endl;
 		MergeCandidate mc = mergeQueue.top();
 		mergeQueue.pop();
@@ -2181,9 +2224,9 @@
 
 	// collapse siblings belonging to the same view cell
-	//CollapseTree(mRoot);
+	CollapseTree(mRoot);
 	// revalidate leaves
-	//RepairVcLeafLists();
-
-	//Debug << "merged " << merged << " of " << savedVcSize << " leaves" << endl;
+	RepairVcLeafLists();
+
+	Debug << "merged " << merged << " of " << savedVcSize << " leaves" << endl;
 
 	//TODO: should return sample contributions
@@ -2332,4 +2375,5 @@
 }
 
+
 VspKdLeaf *MergeCandidate::GetLeaf1()
 {
@@ -2337,8 +2381,10 @@
 }
 
+
 VspKdLeaf *MergeCandidate::GetLeaf2()
 {
 	return mLeaf2;
 }
+
 
 bool MergeCandidate::Valid() const
@@ -2349,8 +2395,10 @@
 }
 
+
 float MergeCandidate::GetMergeCost() const
 {
 	return mMergeCost;
 }
+
 
 void MergeCandidate::SetValid()
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 480)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 482)
@@ -198,5 +198,11 @@
 	void SetParent(BspInterior *parent);
 
-	
+	/** Returns true if this node is a sibling of node n.
+	*/
+	bool IsSibling(BspNode *n) const;
+
+	/** returns depth of the node.
+	*/
+	int GetDepth() const;
 	static int sMailId;
 	int mMailbox;
Index: trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.h	(revision 459)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.h	(revision 482)
@@ -321,4 +321,12 @@
 				float &maxT) const;
 
+  /** If the boxes are intersecting on a common face, this function 
+	  returns the face intersection, false otherwise.
+    
+	  @param neighbour the neighbouring box intersecting with this box.
+  */
+  bool GetIntersectionFace(Rectangle3 &face,
+						   const AxisAlignedBox3 &neighbour) const;
+
 #define __EXTENT_HACK
   // get the extent of face
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h	(revision 480)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.h	(revision 482)
@@ -24,5 +24,5 @@
 class BspLeaf;
 class ViewCellsStatistics;
-
+class Exporter;
 struct BspRay;
 
@@ -214,16 +214,34 @@
 protected:
 
+	void ParseEnvironment();
+
 	/** 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.
 	*/
 	void EvaluateViewCellsStats();
-		
+
+
+	//-- helper functions for view cell visualization
+
+	/** Exports the view cell partition.
+	*/
+	void ExportViewCells(Exporter *exporter) const;
+
+	/** Sets exporter color.
+	*/
+	virtual void ExportColor(Exporter *exporter, ViewCell *vc) const = 0;
+
+	/** Exports view cell geometry.
+	*/
+	virtual void ExportGeometry(Exporter *exporter, ViewCell *vc) const = 0;
+
 	/// the view cell corresponding to unbounded space
 	ViewCell *mUnbounded;
@@ -247,4 +265,7 @@
 	float mTotalAreaValid;
 	float mTotalArea;
+
+	// visualization color code
+	int mColorCode;
 
 	ViewCellsStatistics mViewCellsStats;
@@ -307,4 +328,8 @@
 	void ConstructBspRays(const VssRayContainer &rays,
 						  const int numSamples);
+
+	void ExportColor(Exporter *exporter, ViewCell *vc) const;
+	void ExportGeometry(Exporter *exporter, ViewCell *vc) const;
+
 	/// the BSP tree.
 	BspTree *mBspTree;
@@ -367,4 +392,6 @@
 	KdNode *GetNodeForPvs(KdLeaf *leaf);
 
+	void ExportColor(Exporter *exporter, ViewCell *vc) const;
+	void ExportGeometry(Exporter *exporter, ViewCell *vc) const;
 
 	/// the BSP tree.
@@ -417,5 +444,12 @@
 protected:
 
+	void ExportLeaves(const ObjectContainer &objects,
+					  const VssRayContainer &sampleRays);
+
 	void CollectViewCells();
+
+	void ExportColor(Exporter *exporter, ViewCell *vc) const;
+	void ExportGeometry(Exporter *exporter, ViewCell *vc) const;
+
 
 	/// the BSP tree.
@@ -480,12 +514,20 @@
 	void CollectViewCells();
 
+	void ExportColor(Exporter *exporter, ViewCell *vc) const;
+	void ExportGeometry(Exporter *exporter, ViewCell *vc) const;
+
+	/** Returns maximal depth difference of view cell 
+		leaves in tree.
+	*/
+	int GetMaxTreeDiff(ViewCell *vc) const;
+
 	/// the view space partition BSP tree.
 	VspBspTree *mVspBspTree;
 
+	/// helper array of rays
 	vector<BspRay *> mBspRays;
 
 private:
 
-
 	/** Exports visualization of the BSP splits.
 	*/
Index: trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp	(revision 481)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.cpp	(revision 482)
@@ -19,9 +19,9 @@
 
 //-- static members
-/** Evaluates split plane classification with respect to the plane's 
+/** Evaluates split plane classification with respect to the plane's
 	contribution for a minimum number of ray splits.
 */
 const float VspBspTree::sLeastRaySplitsTable[] = {0, 0, 1, 1, 0};
-/** Evaluates split plane classification with respect to the plane's 
+/** Evaluates split plane classification with respect to the plane's
 	contribution for balanced rays.
 */
@@ -29,5 +29,5 @@
 
 
-int VspBspTree::sFrontId = 0; 
+int VspBspTree::sFrontId = 0;
 int VspBspTree::sBackId = 0;
 int VspBspTree::sFrontAndBackId = 0;
@@ -39,10 +39,11 @@
 /****************************************************************/
 
-VspBspTree::VspBspTree(): 
+VspBspTree::VspBspTree():
 mRoot(NULL),
 mPvsUseArea(true),
 mCostNormalizer(Limits::Small),
 mViewCellsManager(NULL),
-mStoreRays(true)
+mStoreRays(true),
+mOnlyDrivingAxis(false)
 {
 	mRootCell = new BspViewCell();
@@ -54,5 +55,5 @@
 	environment->GetIntValue("VspBspTree.Termination.minPvs", mTermMinPvs);
 	environment->GetIntValue("VspBspTree.Termination.minRays", mTermMinRays);
-	environment->GetFloatValue("VspBspTree.Termination.minArea", mTermMinArea);	
+	environment->GetFloatValue("VspBspTree.Termination.minArea", mTermMinArea);
 	environment->GetFloatValue("VspBspTree.Termination.maxRayContribution", mTermMaxRayContribution);
 	environment->GetFloatValue("VspBspTree.Termination.minAccRayLenght", mTermMinAccRayLength);
@@ -65,16 +66,11 @@
 	environment->GetFloatValue("VspBspTree.Termination.ct_div_ci", mCtDivCi);
 
-	//-- termination criteria for axis aligned split
-	environment->GetFloatValue("VspBspTree.Termination.AxisAligned.ct_div_ci", mAxisAlignedCtDivCi);
+	//-- max cost ratio for early tree termination
 	environment->GetFloatValue("VspBspTree.Termination.maxCostRatio", mTermMaxCostRatio);
-	
-	environment->GetIntValue("VspBspTree.Termination.AxisAligned.minRays", 
-							 mTermMinRaysForAxisAligned);
-	
+
 	//-- partition criteria
 	environment->GetIntValue("VspBspTree.maxPolyCandidates", mMaxPolyCandidates);
 	environment->GetIntValue("VspBspTree.maxRayCandidates", mMaxRayCandidates);
 	environment->GetIntValue("VspBspTree.splitPlaneStrategy", mSplitPlaneStrategy);
-	environment->GetFloatValue("VspBspTree.AxisAligned.splitBorder", mAxisAlignedSplitBorder);
 
 	environment->GetFloatValue("VspBspTree.Construction.epsilon", mEpsilon);
@@ -100,5 +96,5 @@
 	Debug << "max polygon candidates: " << mMaxPolyCandidates << endl;
 	Debug << "max plane candidates: " << mMaxRayCandidates << endl;
-	
+
 	Debug << "Split plane strategy: ";
 	if (mSplitPlaneStrategy & RANDOM_POLYGON)
@@ -125,5 +121,5 @@
 		Debug << "pvs";
 	}
-	
+
 	mSplitCandidates = new vector<SortableEntry>;
 
@@ -132,5 +128,5 @@
 
 
-const BspTreeStatistics &VspBspTree::GetStatistics() const 
+const BspTreeStatistics &VspBspTree::GetStatistics() const
 {
 	return mStat;
@@ -145,15 +141,15 @@
 }
 
-int VspBspTree::AddMeshToPolygons(Mesh *mesh, 
-								  PolygonContainer &polys, 
+int VspBspTree::AddMeshToPolygons(Mesh *mesh,
+								  PolygonContainer &polys,
 								  MeshInstance *parent)
 {
 	FaceContainer::const_iterator fi;
-	
+
 	// copy the face data to polygons
 	for (fi = mesh->mFaces.begin(); fi != mesh->mFaces.end(); ++ fi)
 	{
 		Polygon3 *poly = new Polygon3((*fi), mesh);
-		
+
 		if (poly->Valid(mEpsilon))
 		{
@@ -167,11 +163,11 @@
 }
 
-int VspBspTree::AddToPolygonSoup(const ViewCellContainer &viewCells, 
-							  PolygonContainer &polys, 
+int VspBspTree::AddToPolygonSoup(const ViewCellContainer &viewCells,
+							  PolygonContainer &polys,
 							  int maxObjects)
 {
-	int limit = (maxObjects > 0) ? 
+	int limit = (maxObjects > 0) ?
 		Min((int)viewCells.size(), maxObjects) : (int)viewCells.size();
-  
+
 	int polysSize = 0;
 
@@ -181,7 +177,7 @@
 		{
 			mBox.Include(viewCells[i]->GetBox()); // add to BSP tree aabb
-			polysSize += 
-				AddMeshToPolygons(viewCells[i]->GetMesh(), 
-								  polys, 
+			polysSize +=
+				AddMeshToPolygons(viewCells[i]->GetMesh(),
+								  polys,
 								  viewCells[i]);
 		}
@@ -191,11 +187,11 @@
 }
 
-int VspBspTree::AddToPolygonSoup(const ObjectContainer &objects, 
-								 PolygonContainer &polys, 
+int VspBspTree::AddToPolygonSoup(const ObjectContainer &objects,
+								 PolygonContainer &polys,
 								 int maxObjects)
 {
-	int limit = (maxObjects > 0) ? 
+	int limit = (maxObjects > 0) ?
 		Min((int)objects.size(), maxObjects) : (int)objects.size();
-  
+
 	for (int i = 0; i < limit; ++i)
 	{
@@ -216,5 +212,5 @@
 			break;
 		}
-		
+
         if (mesh) // copy the mesh data to polygons
 		{
@@ -231,5 +227,5 @@
     mStat.nodes = 1;
 	mBox.Initialize(); 	// initialise BSP tree bounding box
-	
+
 	PolygonContainer polys;
 	RayInfoContainer *rays = new RayInfoContainer();
@@ -247,5 +243,5 @@
 	{
 		VssRay *ray = *rit;
-	
+
 		if (ray->mTerminationObject && !ray->mTerminationObject->Mailed())
 		{
@@ -270,5 +266,5 @@
 	{
 		VssRay *ray = *rit;
-		
+
 		float minT, maxT;
 
@@ -277,8 +273,8 @@
 		{
 			float len = ray->Length();
-			
-			if (!len) 
+
+			if (!len)
 				len = Limits::Small;
-			
+
 			rays->push_back(RayInfo(ray, minT / len, maxT / len));
 		}
@@ -290,5 +286,5 @@
 	cout << "finished" << endl;
 
-	Debug << "\nPolygon extraction: " << (int)polys.size() << " polys extracted from " 
+	Debug << "\nPolygon extraction: " << (int)polys.size() << " polys extracted from "
 		  << (int)sampleRays.size() << " rays in "
 		  << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl << endl;
@@ -310,10 +306,10 @@
 	ConstructGeometry(mRoot, *geom);
 
-	VspBspTraversalData tData(mRoot, 
-							  new PolygonContainer(polys), 
+	VspBspTraversalData tData(mRoot,
+							  new PolygonContainer(polys),
 							  0,
-							  rays, 
-                              ComputePvsSize(*rays), 
-							  geom->GetArea(), 
+							  rays,
+                              ComputePvsSize(*rays),
+							  geom->GetArea(),
 							  geom);
 
@@ -324,5 +320,5 @@
 
 	long startTime = GetTime();
-	
+
 	while (!tStack.empty())
 	{
@@ -335,5 +331,5 @@
 
 		if (r == mRoot)
-			Debug << "VSP BSP tree construction time spent at root: " 
+			Debug << "VSP BSP tree construction time spent at root: "
 				  << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl << endl;
 	}
@@ -346,5 +342,5 @@
 bool VspBspTree::TerminationCriteriaMet(const VspBspTraversalData &data) const
 {
-	return 
+	return
 		(((int)data.mRays->size() <= mTermMinRays) ||
 		 (data.mPvs <= mTermMinPvs)   ||
@@ -355,5 +351,5 @@
 }
 
-BspNode *VspBspTree::Subdivide(VspBspTraversalStack &tStack, 
+BspNode *VspBspTree::Subdivide(VspBspTraversalStack &tStack,
 							   VspBspTraversalData &tData)
 {
@@ -363,5 +359,5 @@
 	{
 		PolygonContainer coincident;
-	
+
 		VspBspTraversalData tFrontData;
 		VspBspTraversalData tBackData;
@@ -378,17 +374,17 @@
 
 			// delete old leaf node
-			DEL_PTR(tData.mNode);	
-		}
-	}
-	
+			DEL_PTR(tData.mNode);
+		}
+	}
+
 	//-- terminate traversal and create new view cell
 	if (newNode->IsLeaf())
 	{
 		BspLeaf *leaf = dynamic_cast<BspLeaf *>(newNode);
-	
+
 		// create new view cell for this leaf
 		BspViewCell *viewCell = new BspViewCell();
 		leaf->SetViewCell(viewCell);
-		
+
 		if (mStoreRays)
 		{
@@ -404,12 +400,12 @@
 		int conSamp = 0, sampCon = 0;
 		AddToPvs(leaf, *tData.mRays, conSamp, sampCon);
-			
+
 		mStat.contributingSamples += conSamp;
 		mStat.sampleContributions += sampCon;
-		
+
 		EvaluateLeafStats(tData);
 	}
-	
-		
+
+
 	//-- cleanup
 	tData.Clear();
@@ -436,5 +432,5 @@
 		{
 			// terminate branch because of max cost
-			++ mStat.maxCostNodes; 
+			++ mStat.maxCostNodes;
             return leaf;
 		}
@@ -444,10 +440,10 @@
 
 	//-- subdivide further
-	BspInterior *interior = new BspInterior(splitPlane); 
+	BspInterior *interior = new BspInterior(splitPlane);
 
 #ifdef _DEBUG
 	Debug << interior << endl;
 #endif
-	
+
 	//-- the front and back traversal data is filled with the new values
 	frontData.mPolygons = new PolygonContainer();
@@ -462,17 +458,17 @@
 
 	// subdivide rays
-	SplitRays(interior->GetPlane(), 
-			  *tData.mRays, 
-			  *frontData.mRays, 
+	SplitRays(interior->GetPlane(),
+			  *tData.mRays,
+			  *frontData.mRays,
 			  *backData.mRays);
-	
+
 	// subdivide polygons
 	mStat.splits += SplitPolygons(interior->GetPlane(),
-								  *tData.mPolygons, 
-		                          *frontData.mPolygons, 
+								  *tData.mPolygons,
+		                          *frontData.mPolygons,
 								  *backData.mPolygons,
 								  coincident);
 
-	
+
 	// how often was max cost ratio missed in this branch?
 	frontData.mMaxCostMisses = maxCostMisses;
@@ -486,10 +482,10 @@
 	if (1)
 	{
-		tData.mGeometry->SplitGeometry(*frontData.mGeometry, 
-									   *backData.mGeometry, 
+		tData.mGeometry->SplitGeometry(*frontData.mGeometry,
+									   *backData.mGeometry,
 									   interior->GetPlane(),
 									   mBox,
 									   mEpsilon);
-	
+
 		frontData.mArea = frontData.mGeometry->GetArea();
 		backData.mArea = backData.mGeometry->GetArea();
@@ -517,5 +513,5 @@
 	// and setup child links
 	interior->SetupChildLinks(new BspLeaf(interior), new BspLeaf(interior));
-	
+
 	frontData.mNode = interior->GetFront();
 	backData.mNode = interior->GetBack();
@@ -526,5 +522,5 @@
 
 void VspBspTree::AddToPvs(BspLeaf *leaf,
-						  const RayInfoContainer &rays, 
+						  const RayInfoContainer &rays,
 						  int &sampleContributions,
 						  int &contributingSamples)
@@ -542,8 +538,8 @@
 		int contribution = 0;
 		VssRay *ray = (*it).mRay;
-			
+
 		if (ray->mTerminationObject)
 			contribution += vc->GetPvs().AddSample(ray->mTerminationObject);
-		
+
 		if (ray->mOriginObject)
 			contribution += vc->GetPvs().AddSample(ray->mOriginObject);
@@ -567,5 +563,5 @@
 		requestedSize < (int)(mSplitCandidates->capacity()/10) )
 	{
-    	DEL_PTR(mSplitCandidates);
+    	delete mSplitCandidates;
    		mSplitCandidates = new vector<SortableEntry>;
 	}
@@ -578,8 +574,8 @@
 		bool positive = (*ri).mRay->HasPosDir(axis);
 		mSplitCandidates->push_back(SortableEntry(positive ? SortableEntry::ERayMin : SortableEntry::ERayMax,
-												  (*ri).ExtrapOrigin(axis), (void *)&*ri));
+												  (*ri).ExtrapOrigin(axis), (*ri).mRay));
 
 		mSplitCandidates->push_back(SortableEntry(positive ? SortableEntry::ERayMax : SortableEntry::ERayMin,
-												  (*ri).ExtrapTermination(axis), (void *)&*ri));
+												  (*ri).ExtrapTermination(axis), (*ri).mRay));
 	}
 
@@ -593,5 +589,4 @@
                                           float &position)
 {
-	//	AxisAlignedBox3 dirBox = GetDirBBox(node);
 	int raysBack;
 	int raysFront;
@@ -599,6 +594,4 @@
 	int pvsFront;
 
-	//axis = box.Size().DrivingAxis();
-
 	SortSplitCandidates(rays, axis);
 
@@ -630,4 +623,5 @@
 
 			if (object)
+			{
 				if (!object->Mailed())
 				{
@@ -637,4 +631,5 @@
 				else
 					++ object->mCounter;
+			}
 		}
 	}
@@ -652,6 +647,8 @@
 				{
 					++ rl;
-					ray = (VssRay *) (*ci).data;
+					ray = (VssRay *) (*ci).ray;
+
 					Intersectable *object = ray->mTerminationObject;
+
 					if (object && !object->Mailed())
 					{
@@ -664,6 +661,6 @@
 				{
 					-- rr;
-
-					ray = (VssRay *) (*ci).data;
+					ray = (VssRay *) (*ci).ray;
+
 					Intersectable *object = ray->mTerminationObject;
 
@@ -671,5 +668,5 @@
 					{
 						if (-- object->mCounter == 0)
-						-- pr;
+							-- pr;
 					}
 
@@ -712,10 +709,10 @@
 
 
-float VspBspTree::SelectAxisAlignedPlane(Plane3 &plane, 
+float VspBspTree::SelectAxisAlignedPlane(Plane3 &plane,
 										 const VspBspTraversalData &tData)
 {
 	AxisAlignedBox3 box;
 	box.Initialize();
-	
+
 	// create bounding box of region
 	RayInfoContainer::const_iterator ri, ri_end = tData.mRays->end();
@@ -731,8 +728,6 @@
 	int bestAxis = -1;
 
-	bool mOnlyDrivingAxis = false;
-
 	const int sAxis = box.Size().DrivingAxis();
-		
+
 	for (int axis = 0; axis < 3; ++ axis)
 	{
@@ -748,5 +743,5 @@
 			else
 			{
-				nCostRatio[axis] = 
+				nCostRatio[axis] =
 					BestCostRatioHeuristics(*tData.mRays,
 										    box,
@@ -780,6 +775,6 @@
 
 
-bool VspBspTree::SelectPlane(Plane3 &plane, 
-							 BspLeaf *leaf, 
+bool VspBspTree::SelectPlane(Plane3 &plane,
+							 BspLeaf *leaf,
 							 VspBspTraversalData &data)
 {
@@ -799,5 +794,5 @@
 			//-- choose plane on midpoint of a ray
 			const int candidateIdx = (int)RandomValue(0, (Real)((int)data.mRays->size() - 1));
-									
+
 			const Vector3 minPt = (*data.mRays)[candidateIdx].ExtrapOrigin();
 			const Vector3 maxPt = (*data.mRays)[candidateIdx].ExtrapTermination();
@@ -806,5 +801,5 @@
 
 			const Vector3 normal = (*data.mRays)[candidateIdx].mRay->GetDir();
-			
+
 			plane = Plane3(normal, pt);
 			return true;
@@ -815,12 +810,12 @@
 
 	// use heuristics to find appropriate plane
-	return SelectPlaneHeuristics(plane, leaf, data); 
+	return SelectPlaneHeuristics(plane, leaf, data);
 }
 
 
 Plane3 VspBspTree::ChooseCandidatePlane(const RayInfoContainer &rays) const
-{	
+{
 	const int candidateIdx = (int)RandomValue(0, (Real)((int)rays.size() - 1));
-	
+
 	const Vector3 minPt = rays[candidateIdx].ExtrapOrigin();
 	const Vector3 maxPt = rays[candidateIdx].ExtrapTermination();
@@ -834,7 +829,7 @@
 
 Plane3 VspBspTree::ChooseCandidatePlane2(const RayInfoContainer &rays) const
-{	
+{
 	Vector3 pt[3];
-	
+
 	int idx[3];
 	int cmaxT = 0;
@@ -845,9 +840,9 @@
 	{
 		idx[j] = (int)RandomValue(0, (Real)((int)rays.size() * 2 - 1));
-			
+
 		if (idx[j] >= (int)rays.size())
 		{
 			idx[j] -= (int)rays.size();
-				
+
 			chooseMin = (cminT < 2);
 		}
@@ -857,5 +852,5 @@
 		RayInfo rayInf = rays[idx[j]];
 		pt[j] = chooseMin ? rayInf.ExtrapOrigin() : rayInf.ExtrapTermination();
-	}	
+	}
 
 	return Plane3(pt[0], pt[1], pt[2]);
@@ -863,7 +858,7 @@
 
 Plane3 VspBspTree::ChooseCandidatePlane3(const RayInfoContainer &rays) const
-{	
+{
 	Vector3 pt[3];
-	
+
 	int idx1 = (int)RandomValue(0, (Real)((int)rays.size() - 1));
 	int idx2 = (int)RandomValue(0, (Real)((int)rays.size() - 1));
@@ -881,5 +876,5 @@
 	// vector from line 1 to line 2
 	const Vector3 vd = ray2.ExtrapOrigin() - ray1.ExtrapOrigin();
-	
+
 	// project vector on normal to get distance
 	const float dist = DotProd(vd, norm);
@@ -891,6 +886,6 @@
 }
 
-bool VspBspTree::SelectPlaneHeuristics(Plane3 &bestPlane, 
-									   BspLeaf *leaf, 
+bool VspBspTree::SelectPlaneHeuristics(Plane3 &bestPlane,
+									   BspLeaf *leaf,
 									   VspBspTraversalData &data)
 {
@@ -901,5 +896,5 @@
 	const int limit = Min((int)data.mPolygons->size(), mMaxPolyCandidates);
 	int maxIdx = (int)data.mPolygons->size();
-	
+
 	float candidateCost;
 
@@ -909,10 +904,10 @@
 		const int candidateIdx = (int)RandomValue(0, (Real)(-- maxIdx));
 		//Debug << "current Idx: " << maxIdx << " cand idx " << candidateIdx << endl;
-		
+
 		Polygon3 *poly = (*data.mPolygons)[candidateIdx];
 
 		// swap candidate to the end to avoid testing same plane
 		std::swap((*data.mPolygons)[maxIdx], (*data.mPolygons)[candidateIdx]);
-	
+
 		//Polygon3 *poly = (*data.mPolygons)[(int)RandomValue(0, (int)polys.size() - 1)];
 
@@ -926,5 +921,5 @@
 		}
 	}
-	
+
 #if 0
 	//-- choose candidate planes extracted from rays
@@ -937,5 +932,5 @@
 		if (candidateCost < lowestCost)
 		{
-			bestPlane = plane;	
+			bestPlane = plane;
 			lowestCost = candidateCost;
 		}
@@ -944,9 +939,9 @@
 
 	// axis aligned splits
-	candidateCost = SelectAxisAlignedPlane(plane, data); 
+	candidateCost = SelectAxisAlignedPlane(plane, data);
 
 	if (candidateCost < lowestCost)
 	{
-		bestPlane = plane;	
+		bestPlane = plane;
 		lowestCost = candidateCost;
 	}
@@ -971,5 +966,5 @@
 }
 
-float VspBspTree::SplitPlaneCost(const Plane3 &candidatePlane, 
+float VspBspTree::SplitPlaneCost(const Plane3 &candidatePlane,
 								 const VspBspTraversalData &data) const
 {
@@ -978,5 +973,5 @@
 	float sumBalancedRays = 0;
 	float sumRaySplits = 0;
-	
+
 	int frontPvs = 0;
 	int backPvs = 0;
@@ -993,17 +988,17 @@
 		// create unique ids for pvs heuristics
 		GenerateUniqueIdsForPvs();
-	
+
 		if (mPvsUseArea) // use front and back cell areas to approximate volume
-		{	
+		{
 			// construct child geometry with regard to the candidate split plane
 			BspNodeGeometry frontCell;
 			BspNodeGeometry backCell;
-		
-			data.mGeometry->SplitGeometry(frontCell, 
-										  backCell, 
+
+			data.mGeometry->SplitGeometry(frontCell,
+										  backCell,
 										  candidatePlane,
 										  mBox,
 										  mEpsilon);
-		
+
 			pFront = frontCell.GetArea();
 			pBack = backCell.GetArea();
@@ -1012,5 +1007,5 @@
 		}
 	}
-		
+
 	int limit;
 	bool useRand;
@@ -1041,5 +1036,5 @@
 			sumBalancedRays += cf;
 		}
-		
+
 		if (mSplitPlaneStrategy & BALANCED_RAYS)
 		{
@@ -1051,13 +1046,13 @@
 		{
 			// in case the ray intersects an object
-			// assure that we only count the object 
+			// assure that we only count the object
 			// once for the front and once for the back side of the plane
-			
+
 			// add the termination object
 			AddObjToPvs(ray->mTerminationObject, cf, frontPvs, backPvs);
-			
+
 			// add the source object
 			AddObjToPvs(ray->mOriginObject, cf, frontPvs, backPvs);
-			
+
 			// use number or length of rays to approximate volume
 			if (!mPvsUseArea)
@@ -1067,5 +1062,5 @@
 				if (pvsUseLen) // use length of rays
 					len = rayInf.SqrSegmentLength();
-			
+
 				pOverall += len;
 
@@ -1077,10 +1072,10 @@
 				{
 					// use length of rays to approximate volume
-					if (pvsUseLen) 
+					if (pvsUseLen)
 					{
-						float newLen = len * 
-							(rayInf.GetMaxT() - t) / 
+						float newLen = len *
+							(rayInf.GetMaxT() - t) /
 							(rayInf.GetMaxT() - rayInf.GetMinT());
-		
+
 						if (candidatePlane.Side(rayInf.ExtrapOrigin()) <= 0)
 						{
@@ -1105,5 +1100,5 @@
 
 	const float raysSize = (float)data.mRays->size() + Limits::Small;
-	
+
 	if (mSplitPlaneStrategy & LEAST_RAY_SPLITS)
 		cost += mLeastRaySplitsFactor * sumRaySplits / raysSize;
@@ -1111,5 +1106,5 @@
 	if (mSplitPlaneStrategy & BALANCED_RAYS)
 		cost += mBalancedRaysFactor * fabs(sumBalancedRays) /  raysSize;
-	
+
 	// pvs criterium
 	if (mSplitPlaneStrategy & PVS)
@@ -1120,7 +1115,7 @@
 		//cost += mPvsFactor * 0.5 * (frontPvs * pFront + backPvs * pBack) / oldCost;
 		//Debug << "new cost: " << cost << " over" << frontPvs * pFront + backPvs * pBack << " old cost " << oldCost << endl;
-	
+
 		if (0) // give penalty to unbalanced split
-			if (((pFront * 0.2 + Limits::Small) > pBack) || 
+			if (((pFront * 0.2 + Limits::Small) > pBack) ||
 				(pFront < (pBack * 0.2 + Limits::Small)))
 					cost += 0.5;
@@ -1129,8 +1124,8 @@
 #ifdef _DEBUG
   	Debug << "totalpvs: " << data.mPvs << " ptotal: " << pOverall
-  		  << " frontpvs: " << frontPvs << " pFront: " << pFront 
+  		  << " frontpvs: " << frontPvs << " pFront: " << pFront
   		  << " backpvs: " << backPvs << " pBack: " << pBack << endl << endl;
 #endif
-	
+
 	// normalize cost by sum of linear factors
 	return cost / (float)mCostNormalizer;
@@ -1150,5 +1145,5 @@
 	if (cf >= 0)
 	{
-		if ((obj->mMailbox != sFrontId) && 
+		if ((obj->mMailbox != sFrontId) &&
 			(obj->mMailbox != sFrontAndBackId))
 		{
@@ -1156,10 +1151,10 @@
 
 			if (obj->mMailbox == sBackId)
-				obj->mMailbox = sFrontAndBackId;	
+				obj->mMailbox = sFrontAndBackId;
 			else
-				obj->mMailbox = sFrontId;								
-		}
-	}
-	
+				obj->mMailbox = sFrontId;
+		}
+	}
+
 	if (cf <= 0)
 	{
@@ -1170,7 +1165,7 @@
 
 			if (obj->mMailbox == sFrontId)
-				obj->mMailbox = sFrontAndBackId; 
+				obj->mMailbox = sFrontAndBackId;
 			else
-				obj->mMailbox = sBackId;				
+				obj->mMailbox = sBackId;
 		}
 	}
@@ -1181,17 +1176,17 @@
 	stack<BspNode *> nodeStack;
 	nodeStack.push(mRoot);
- 
-	while (!nodeStack.empty()) 
+
+	while (!nodeStack.empty())
 	{
 		BspNode *node = nodeStack.top();
-    
+
 		nodeStack.pop();
-    
-		if (node->IsLeaf()) 
-		{
-			BspLeaf *leaf = (BspLeaf *)node;		
+
+		if (node->IsLeaf())
+		{
+			BspLeaf *leaf = (BspLeaf *)node;
 			leaves.push_back(leaf);
-		} 
-		else 
+		}
+		else
 		{
 			BspInterior *interior = dynamic_cast<BspInterior *>(node);
@@ -1224,5 +1219,5 @@
 	if (data.mDepth < mStat.minDepth)
 		mStat.minDepth = data.mDepth;
-	
+
 	if (data.mDepth >= mTermMaxDepth)
 		++ mStat.maxDepthNodes;
@@ -1236,6 +1231,6 @@
 	if (data.GetAvgRayContribution() > mTermMaxRayContribution)
 		++ mStat.maxRayContribNodes;
-	
-	if (data.mArea <= mTermMinArea) 
+
+	if (data.mArea <= mTermMinArea)
 	{
 		//Debug << "area: " << data.mArea / mBox.SurfaceArea() << " min area: " << mTermMinArea / mBox.SurfaceArea() << endl;
@@ -1250,5 +1245,5 @@
 		  << "PVS: " << data.mPvs << " (min: " << mTermMinPvs << "), "
 		  << "Area: " << data.mArea << " (min: " << mTermMinArea << "), "
-		  << "#rays: " << (int)data.mRays->size() << " (max: " << mTermMinRays << "), " 
+		  << "#rays: " << (int)data.mRays->size() << " (max: " << mTermMinRays << "), "
 		  << "#pvs: " << leaf->GetViewCell()->GetPvs().GetSize() << "=, "
 		  << "#avg ray contrib (pvs): " << (float)data.mPvs / (float)data.mRays->size() << endl;
@@ -1259,7 +1254,7 @@
 {
 	int hits = 0;
-  
+
 	stack<BspRayTraversalData> tStack;
-  
+
 	float maxt, mint;
 
@@ -1271,11 +1266,11 @@
 	Vector3 entp = ray.Extrap(mint);
 	Vector3 extp = ray.Extrap(maxt);
-  
+
 	BspNode *node = mRoot;
 	BspNode *farChild = NULL;
-	
+
 	while (1)
 	{
-		if (!node->IsLeaf()) 
+		if (!node->IsLeaf())
 		{
 			BspInterior *in = dynamic_cast<BspInterior *>(node);
@@ -1291,5 +1286,5 @@
 				if(extSide <= 0) // plane does not split ray => no far child
 					continue;
-					
+
 				farChild = in->GetFront(); // plane splits ray
 
@@ -1301,5 +1296,5 @@
 					continue;
 
-				farChild = in->GetBack(); // plane splits ray			
+				farChild = in->GetBack(); // plane splits ray
 			}
 			else // ray and plane are coincident
@@ -1318,9 +1313,9 @@
 			extp = splitPlane.FindIntersection(ray.GetLoc(), extp, &t);
 			maxt *= t;
-			
+
 		} else // reached leaf => intersection with view cell
 		{
 			BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
-      
+
 			if (!leaf->GetViewCell()->Mailed())
 			{
@@ -1329,9 +1324,9 @@
 				++ hits;
 			}
-			
+
    			//-- fetch the next far child from the stack
 			if (tStack.empty())
 				break;
-      
+
 			entp = extp;
 			mint = maxt; // NOTE: need this?
@@ -1357,9 +1352,9 @@
 	Exporter *exporter = Exporter::GetExporter(filename);
 
-	if (exporter) 
+	if (exporter)
 	{
 		//exporter->ExportVspBspTree(*this);
 		return true;
-	}	
+	}
 
 	return false;
@@ -1373,14 +1368,14 @@
 	ViewCell::NewMail();
 
-	while (!nodeStack.empty()) 
+	while (!nodeStack.empty())
 	{
 		BspNode *node = nodeStack.top();
 		nodeStack.pop();
 
-		if (node->IsLeaf()) 
+		if (node->IsLeaf())
 		{
 			ViewCell *viewCell = dynamic_cast<BspLeaf *>(node)->GetViewCell();
 
-			if (!viewCell->Mailed()) 
+			if (!viewCell->Mailed())
 			{
 				viewCell->Mail();
@@ -1388,5 +1383,5 @@
 			}
 		}
-		else 
+		else
 		{
 			BspInterior *interior = dynamic_cast<BspInterior *>(node);
@@ -1399,10 +1394,4 @@
 
 
-BspTreeStatistics &VspBspTree::GetStat()
-{
-	return mStat;
-}
-
-
 float VspBspTree::AccumulatedRayLength(const RayInfoContainer &rays) const
 {
@@ -1419,6 +1408,6 @@
 
 int VspBspTree::SplitRays(const Plane3 &plane,
-						  RayInfoContainer &rays, 
-						  RayInfoContainer &frontRays, 
+						  RayInfoContainer &rays,
+						  RayInfoContainer &frontRays,
 						  RayInfoContainer &backRays)
 {
@@ -1435,5 +1424,5 @@
 			// get classification and receive new t
 		const int cf = bRay.ComputeRayIntersection(plane, t);
-	
+
 		switch (cf)
 		{
@@ -1444,9 +1433,9 @@
 			frontRays.push_back(bRay);
 			break;
-		case 0: 
+		case 0:
 			//-- split ray
 			//--  look if start point behind or in front of plane
 			if (plane.Side(bRay.ExtrapOrigin()) <= 0)
-			{	
+			{
 				backRays.push_back(RayInfo(ray, bRay.GetMinT(), t));
 				frontRays.push_back(RayInfo(ray, t, bRay.GetMaxT()));
@@ -1479,5 +1468,5 @@
 		// split plane of node itself
 		n = n->GetParent();
-		
+
 		if (n)
 		{
@@ -1494,5 +1483,5 @@
 }
 
-void VspBspTree::ConstructGeometry(BspNode *n, 
+void VspBspTree::ConstructGeometry(BspNode *n,
 								   BspNodeGeometry &cell) const
 {
@@ -1502,5 +1491,5 @@
 }
 
-void VspBspTree::ConstructGeometry(BspNode *n, 
+void VspBspTree::ConstructGeometry(BspNode *n,
 								   PolygonContainer &cell) const
 {
@@ -1515,5 +1504,5 @@
 	{
 		Polygon3 *p = GetBoundingBox().CrossSection(halfSpaces[i]);
-		
+
 		if (p->Valid(mEpsilon))
 		{
@@ -1527,5 +1516,5 @@
 	{
 		VertexContainer vertices;
-	
+
 		for (int j = 0; j < 4; ++ j)
 			vertices.push_back(mBox.GetFace(i).mVertices[j]);
@@ -1545,8 +1534,8 @@
 			Polygon3 *frontPoly, *backPoly;
 
-			const int cf = 
+			const int cf =
 				candidatePolys[i]->ClassifyPlane(halfSpaces[j],
 												 mEpsilon);
-			
+
 			switch (cf)
 			{
@@ -1555,6 +1544,6 @@
 					backPoly = new Polygon3();
 
-					candidatePolys[i]->Split(halfSpaces[j], 
-											 *frontPoly, 
+					candidatePolys[i]->Split(halfSpaces[j],
+											 *frontPoly,
 											 *backPoly,
 											 mEpsilon);
@@ -1579,5 +1568,5 @@
 			}
 		}
-		
+
 		if (candidatePolys[i])
 			cell.push_back(candidatePolys[i]);
@@ -1595,5 +1584,5 @@
 }
 
-int VspBspTree::FindNeighbors(BspNode *n, vector<BspLeaf *> &neighbors, 
+int VspBspTree::FindNeighbors(BspNode *n, vector<BspLeaf *> &neighbors,
 						   const bool onlyUnmailed) const
 {
@@ -1604,10 +1593,10 @@
 	stack<BspNode *> nodeStack;
 	nodeStack.push(mRoot);
-		
+
 	// planes needed to verify that we found neighbor leaf.
 	vector<Plane3> halfSpaces;
 	ExtractHalfSpaces(n, halfSpaces);
 
-	while (!nodeStack.empty()) 
+	while (!nodeStack.empty())
 	{
 		BspNode *node = nodeStack.top();
@@ -1622,10 +1611,10 @@
 				PolygonContainer neighborCandidate;
 				ConstructGeometry(node, neighborCandidate);
-				
+
 				bool isAdjacent = true;
 				for (int i = 0; (i < halfSpaces.size()) && isAdjacent; ++ i)
 				{
-					const int cf = 
-						Polygon3::ClassifyPlane(neighborCandidate, 
+					const int cf =
+						Polygon3::ClassifyPlane(neighborCandidate,
 												halfSpaces[i],
 												mEpsilon);
@@ -1641,10 +1630,10 @@
 			}
 		}
-		else 
+		else
 		{
 			BspInterior *interior = dynamic_cast<BspInterior *>(node);
-	
-			const int cf = Polygon3::ClassifyPlane(cell, 
-												   interior->GetPlane(), 
+
+			const int cf = Polygon3::ClassifyPlane(cell,
+												   interior->GetPlane(),
 												   mEpsilon);
 
@@ -1654,5 +1643,5 @@
 				if (cf == Polygon3::BACK_SIDE)
 					nodeStack.push(interior->GetBack());
-				else 
+				else
 				{
 					// random decision
@@ -1662,5 +1651,5 @@
 		}
 	}
-	
+
 	CLEAR_CONTAINER(cell);
 	return (int)neighbors.size();
@@ -1671,22 +1660,22 @@
     stack<BspNode *> nodeStack;
   	nodeStack.push(mRoot);
-	
+
 	int mask = rand();
-  
-	while (!nodeStack.empty()) 
+
+	while (!nodeStack.empty())
 	{
 		BspNode *node = nodeStack.top();
 		nodeStack.pop();
-	  
-		if (node->IsLeaf()) 
+
+		if (node->IsLeaf())
 		{
 			return dynamic_cast<BspLeaf *>(node);
-		} 
-		else 
+		}
+		else
 		{
 			BspInterior *interior = dynamic_cast<BspInterior *>(node);
-			
+
 			BspNode *next;
-	
+
 			PolygonContainer cell;
 
@@ -1701,5 +1690,5 @@
 				if (cf == Polygon3::FRONT_SIDE)
 					next = interior->GetFront();
-			else 
+			else
 			{
 				// random decision
@@ -1714,5 +1703,5 @@
 		}
 	}
-	
+
 	return NULL;
 }
@@ -1721,20 +1710,20 @@
 {
 	stack<BspNode *> nodeStack;
-	
+
 	nodeStack.push(mRoot);
 
 	int mask = rand();
-	
-	while (!nodeStack.empty()) 
+
+	while (!nodeStack.empty())
 	{
 		BspNode *node = nodeStack.top();
 		nodeStack.pop();
-		
-		if (node->IsLeaf()) 
+
+		if (node->IsLeaf())
 		{
 			if ( (!onlyUnmailed || !node->Mailed()) )
 				return dynamic_cast<BspLeaf *>(node);
 		}
-		else 
+		else
 		{
 			BspInterior *interior = dynamic_cast<BspInterior *>(node);
@@ -1749,5 +1738,5 @@
 		}
 	}
-	
+
 	return NULL;
 }
@@ -1764,5 +1753,5 @@
 	{
 		VssRay *ray = (*rit).mRay;
-		
+
 		if (ray->mOriginObject)
 		{
@@ -1797,7 +1786,7 @@
 
 int VspBspTree::SplitPolygons(const Plane3 &plane,
-							  PolygonContainer &polys, 
-							  PolygonContainer &frontPolys, 
-							  PolygonContainer &backPolys, 
+							  PolygonContainer &polys,
+							  PolygonContainer &frontPolys,
+							  PolygonContainer &backPolys,
 							  PolygonContainer &coincident) const
 {
@@ -1816,6 +1805,6 @@
 			case Polygon3::COINCIDENT:
 				coincident.push_back(poly);
-				break;			
-			case Polygon3::FRONT_SIDE:	
+				break;
+			case Polygon3::FRONT_SIDE:
 				frontPolys.push_back(poly);
 				break;
@@ -1844,41 +1833,41 @@
 	int hits = 0;
 	stack<BspRayTraversalData> tStack;
-  
+
 	float mint = 0.0f, maxt = 1.0f;
-  
+
 	Intersectable::NewMail();
-  
+
 	Vector3 entp = origin;
 	Vector3 extp = termination;
-  
+
 	BspNode *node = mRoot;
 	BspNode *farChild = NULL;
-  
-	while (1) 
-	{
-		if (!node->IsLeaf())  
+
+	while (1)
+	{
+		if (!node->IsLeaf())
 		{
 			BspInterior *in = dynamic_cast<BspInterior *>(node);
-	  
+
 			Plane3 splitPlane = in->GetPlane();
 			const int entSide = splitPlane.Side(entp);
 			const int extSide = splitPlane.Side(extp);
-	  
-			if (entSide < 0) 
+
+			if (entSide < 0)
 			{
 				node = in->GetBack();
-		
+
 				if(extSide <= 0) // plane does not split ray => no far child
 					continue;
-		
+
 				farChild = in->GetFront(); // plane splits ray
-			} else if (entSide > 0) 
+			} else if (entSide > 0)
 			{
 				node = in->GetFront();
-		  
+
 				if (extSide >= 0) // plane does not split ray => no far child
 					continue;
-		  
-				farChild = in->GetBack(); // plane splits ray			
+
+				farChild = in->GetBack(); // plane splits ray
 			}
 			else // ray and plane are coincident
@@ -1889,19 +1878,19 @@
 				continue;
 			}
-	  
+
 			// push data for far child
 			tStack.push(BspRayTraversalData(farChild, extp, maxt));
-	  
+
 			// find intersection of ray segment with plane
 			float t;
 			extp = splitPlane.FindIntersection(origin, extp, &t);
 			maxt *= t;
-	  
-		} else 
+
+		} else
 		{
 			// reached leaf => intersection with view cell
 			BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
-	  
-			if (!leaf->GetViewCell()->Mailed()) 
+
+			if (!leaf->GetViewCell()->Mailed())
 			{
 				viewcells.push_back(leaf->GetViewCell());
@@ -1909,19 +1898,19 @@
 				++ hits;
 			}
-	  
+
 			//-- fetch the next far child from the stack
 			if (tStack.empty())
 				break;
-      
+
 			entp = extp;
 			mint = maxt; // NOTE: need this?
-	  
-			
+
+
 			BspRayTraversalData &s = tStack.top();
-            
+
 			node = s.mNode;
 			extp = s.mExitPoint;
 			maxt = s.mMaxT;
-	  
+
 			tStack.pop();
 		}
@@ -1930,4 +1919,36 @@
 }
 
+int VspBspTree::TreeDistance(BspNode *n1, BspNode *n2)
+{
+	std::deque<BspNode *> path1;
+	BspNode *p1 = n1;
+
+	// create path from node 1 to root
+	while (p1)
+	{
+		if (p1 == n2) // second node on path
+			return (int)path1.size();
+
+		path1.push_front(p1);
+		p1 = p1->GetParent();
+	}
+
+	int depth = n2->GetDepth();
+	int d = depth;
+
+	BspNode *p2 = n2;
+
+	// compare with same depth
+	while (1)
+	{
+		if ((d < (int)path1.size()) && (p2 == path1[d]))
+			return (depth - d) + ((int)path1.size() - 1 - d);
+
+		-- d;
+		p2 = p2->GetParent();
+	}
+
+	return 0; // never come here
+}
 
 BspNode *VspBspTree::CollapseTree(BspNode *node)
@@ -1952,5 +1973,5 @@
 
 			BspLeaf *leaf = new BspLeaf(interior->GetParent(), vc);
-			
+
 			// replace a link from node's parent
 			if (leaf->GetParent())
@@ -2048,8 +2069,13 @@
 
 	int merged = 0;
+	int mergedSiblings = 0;
+	int accTreeDist = 0;
+	int maxTreeDist = 0;
+	const bool mergeStats = true;
+
 
 	//-- use priority queue to merge leaf pairs
 	while (!mergeQueue.empty() && (vcSize > mMergeMinViewCells) &&
-		   (mergeQueue.top().GetMergeCost() < 
+		   (mergeQueue.top().GetMergeCost() <
 		    mMergeMaxCostRatio * BspMergeCandidate::sOverallCost))
 	{
@@ -2066,9 +2092,23 @@
 			ViewCell::NewMail();
 			MergeViewCells(mc.GetLeaf1(), mc.GetLeaf2());
-
-			++ merged;
 			-- vcSize;
 			// increase absolute merge cost
 			BspMergeCandidate::sOverallCost += mc.GetMergeCost();
+
+			//-- stats
+			++ merged;
+
+			if (mc.GetLeaf1()->IsSibling(mc.GetLeaf2()))
+				++ mergedSiblings;
+
+			if (mergeStats)
+			{
+				const int dist = TreeDistance(mc.GetLeaf1(), mc.GetLeaf2());
+
+				if (dist > maxTreeDist)
+					maxTreeDist = dist;
+
+				accTreeDist += dist;
+			}
 		}
 		// merge candidate not valid, because one of the leaves was already
@@ -2088,5 +2128,12 @@
 	RepairVcLeafLists();
 
-	//Debug << "merged " << merged << " of " << savedVcSize << " leaves" << endl;
+	Debug << "Merged " << merged << " nodes of " << savedVcSize
+		  << " (merged " << mergedSiblings << " siblings)" << endl;
+
+	if (mergeStats)
+	{
+		Debug << "maximal tree distance: " << maxTreeDist << endl;
+		Debug << "Avg tree distance: " << (float)accTreeDist / (float)merged << endl;
+	}
 
 	//TODO: should return sample contributions
@@ -2097,5 +2144,5 @@
 bool VspBspTree::MergeViewCells(BspLeaf *l1, BspLeaf *l2)
 {
-	//-- change pointer to view cells of all leaves associated 
+	//-- change pointer to view cells of all leaves associated
 	//-- with the previous view cells
 	BspViewCell *fVc = l1->GetViewCell();
@@ -2184,5 +2231,5 @@
 	//-- to new rendering cost (size of merged view cell times pvs size)
 	const float oldCost = GetLeaf1Cost() + GetLeaf2Cost();
-	
+
 	const float newCost =
 		(float)vcPvs * (vc1->GetArea() + vc2->GetArea());
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp	(revision 481)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp	(revision 482)
@@ -1231,5 +1231,9 @@
 		 "-view_cells_height=",
 		 "5.0");
-   
+   RegisterOption("ViewCells.Visualization.colorCode",
+		optString,
+		"-view_cells_visualization.color_code",
+		"PVS");
+
   /************************************************************************************/
   /*                         Render simulation related options                        */
@@ -1621,54 +1625,53 @@
 	/************************************************************************************/
 
-
 	RegisterOption("VspBspTree.Termination.minPolygons",
-			optInt,
-			"-vsp_bsp_term_min_polygons=",
-			"5");
+		optInt,
+		"-vsp_bsp_term_min_polygons=",
+		"5");
 
 	RegisterOption("VspBspTree.Termination.minPvs",
-			optInt,
-			"-vsp_bsp_term_min_pvs=",
-			"20");
+		optInt,
+		"-vsp_bsp_term_min_pvs=",
+		"20");
 
 	RegisterOption("VspBspTree.Termination.minArea",
-			optFloat,
-			"-vsp_bsp_term_min_area=",
-			"0.001");
+		optFloat,
+		"-vsp_bsp_term_min_area=",
+		"0.001");
 
 	RegisterOption("VspBspTree.Termination.maxRayContribution",
-			optFloat,
-			"-vsp_bsp_term_ray_contribution=",
-			"0.005");
+		optFloat,
+		"-vsp_bsp_term_ray_contribution=",
+		"0.005");
 
 	RegisterOption("VspBspTree.Termination.minAccRayLenght",
-			optFloat,
-			"-vsp_bsp_term_min_acc_ray_length=",
-			"50");
+		optFloat,
+		"-vsp_bsp_term_min_acc_ray_length=",
+		"50");
 
 	RegisterOption("VspBspTree.Termination.minRays",
-			optInt,
-			"-vsp_bsp_term_min_rays=",
-			"-1");
+		optInt,
+		"-vsp_bsp_term_min_rays=",
+		"-1");
 
 	RegisterOption("VspBspTree.Termination.ct_div_ci",
-			optFloat,
-			"-vsp_bsp_term_ct_div_ci=",
-			"0.0");
+		optFloat,
+		"-vsp_bsp_term_ct_div_ci=",
+		"0.0");
 
 	RegisterOption("VspBspTree.Termination.maxDepth",
-			optInt,
-			"-vsp_bsp_term_max_depth=",
-			"100");
+		optInt,
+		"-vsp_bsp_term_max_depth=",
+		"100");
 
 	RegisterOption("VspBspTree.Termination.AxisAligned.maxCostRatio",
-			optFloat,
-			"-vsp_bsp_term_axis_aligned_max_cost_ratio=",
-			"1.5");
+		optFloat,
+		"-vsp_bsp_term_axis_aligned_max_cost_ratio=",
+		"1.5");
 
 	RegisterOption("VspBspTree.Termination.maxViewCells",
-			optInt,
-			"-vsp_bsp_term_axis_aligned_max_view_cells=",
-			"1000");
+		optInt,
+		"-vsp_bsp_term_axis_aligned_max_view_cells=",
+		"1000");
 
 	RegisterOption("VspBspTree.Termination.maxCostRatio",
@@ -1716,4 +1719,5 @@
 		"-vsp_bsp_visualization.export_splits",
 		"false");
+
 	RegisterOption("VspBspTree.Visualization.exportRays",
 		optBool,
@@ -1726,4 +1730,5 @@
 		"false");
 
+	
 	RegisterOption("VspBspTree.Factor.leastRaySplits", optFloat, "-vsp_bsp_factor_least_ray_splits=", "1.0");
 	RegisterOption("VspBspTree.Factor.balancedRays", optFloat, "-vsp_bsp_factor_balanced_rays=", "1.0");
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h	(revision 466)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Exporter.h	(revision 482)
@@ -100,12 +100,6 @@
   ExportBspSplits(const VspBspTree &tree, const bool exportDepth = false) = 0;
 
-  virtual void
-  ExportBspViewCellPartition(const VspBspTree &tree, const int maxPvs = 0) = 0;
-
   virtual void 
   ExportPolygons(const PolygonContainer &polys) = 0;
-
-  virtual void
-  ExportBspViewCellPartition(const BspTree &tree, const int maxPvs = 0) = 0;
 
   virtual void 
@@ -118,7 +112,4 @@
   ExportRssTree2(const RssTree &tree,
 				 const Vector3 direction) = 0;
-
-  virtual bool 
-  ExportVspKdTreeViewCells(const VspKdTree &tree, const int maxPvs = 0) = 0;
 
   void SetExportRayDensity(const bool d) { mExportRayDensity = d; }
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 480)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 482)
@@ -57,4 +57,5 @@
 }
 
+
 BspInterior *BspNode::GetParent() 
 { 
@@ -62,7 +63,29 @@
 }
 
+
 void BspNode::SetParent(BspInterior *parent)
 {
 	mParent = parent;
+}
+
+
+bool BspNode::IsSibling(BspNode *n) const
+{
+	return  ((this != n) && mParent && 
+			 (mParent->GetFront() == n) || (mParent->GetBack() == n));
+}
+
+int BspNode::GetDepth() const
+{
+	int depth = 0;
+	BspNode *p = mParent;
+	
+	while (p)
+	{
+		p = p->mParent;
+		++ depth;
+	}
+
+	return depth;
 }
 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.cpp	(revision 480)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/RenderSimulator.cpp	(revision 482)
@@ -77,11 +77,16 @@
 		// probability of view cell
 		const float pInVc = mViewCellsManager->GetProbability(vc);
-		// compute render time of PVS times probability that view point is in view cell
-		const float vcCost = pInVc * mViewCellsManager->GetRendercost(vc, mObjRenderCost);
+		// compute render time of PVS times probability
+		// that view point is in view cell
+		const float vcCost = pInVc * 
+			mViewCellsManager->GetRendercost(vc, mObjRenderCost);
 	
 		// crossing the border of a view cell is depending on the move speed
 		// and the probability that a view cell border is crossed
 		loadPvsOverhead += GetCrossVcProbability() * mVcOverhead;
-		//Debug << "vccost: " << vcCost << " p in vc " << pInVc << " cross vc " << GetCrossVcProbability() << endl;
+
+		//Debug << "vccost: " << vcCost << " p in vc " << pInVc
+		//<< " cross vc " << GetCrossVcProbability() << endl;
+
 		//-- update statistics
 		renderTime += vcCost;
Index: trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h	(revision 469)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.h	(revision 482)
@@ -115,7 +115,4 @@
 
   virtual void
-  ExportBspViewCellPartition(const BspTree &tree, const int maxPvs = 0);
-
-  virtual void
   ExportBspLeaves(const BspTree &tree, const int maxPvs = 0);
 
@@ -123,10 +120,4 @@
   virtual void
   ExportBspSplits(const VspBspTree &tree, const bool exportDepth);
-
-  virtual void
-  ExportBspViewCellPartition(const VspBspTree &tree, const int maxPvs = 0);
-
-  virtual bool
-  ExportVspKdTreeViewCells(const VspKdTree &tree, const int maxPvs = 0);
 
 protected:
@@ -151,6 +142,4 @@
 						   const bool epsilon);
 
-  bool ExportVspKdTreeViewCell(const VspKdTree &tree, const VspKdViewCell &vc);
-
 
   void ExportViewpoint(const Vector3 &point, const Vector3 &direction);
Index: trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp	(revision 469)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp	(revision 482)
@@ -224,38 +224,4 @@
 	for (it = viewCells.begin(); it != it_end; ++ it)
 		ExportViewCell(*it);
-}
-
-void 
-X3dExporter::ExportBspViewCellPartition(const BspTree &tree, const int maxPvs)
-{
-	ViewCellContainer viewCells;
-	tree.CollectViewCells(viewCells);
-
-	ViewCellContainer::const_iterator it, it_end = viewCells.end();
-
-	if (maxPvs > 0)
-		mUseForcedMaterial = true;
-
-	for (it = viewCells.begin(); it != it_end; ++ it)
-	{
-		if (maxPvs > 0)
-		{
-			mForcedMaterial.mDiffuseColor.b = 1.0f;
-  			float importance = (float)(*it)->GetPvs().GetSize() / (float)maxPvs;
-
-			mForcedMaterial.mDiffuseColor.r = importance;
-			mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r;
-		}
-
-		if ((*it)->GetMesh())
-			ExportViewCell(*it);
-		else
-		{
-			PolygonContainer cell;
-			tree.ConstructGeometry(dynamic_cast<BspViewCell *>(*it), cell);
-
-			ExportPolygons(cell);
-		}
-	}
 }
 
@@ -588,5 +554,5 @@
 
 	// export view cells
-	ExportBspViewCellPartition(tree);	
+	ExportBspLeaves(tree);	
 
 	return true;
@@ -664,45 +630,4 @@
 }
 
-bool X3dExporter::ExportVspKdTreeViewCells(const VspKdTree &tree, const int maxPvs)
-{
-	ViewCellContainer vc;
-
-	//if (maxPvs > 0)
-	mUseForcedMaterial = true;
-
-	tree.CollectViewCells(vc);
-
-	ViewCellContainer::const_iterator it, it_end = vc.end();
-
-	for (it = vc.begin(); it != it_end; ++ it)
-	{
-		VspKdViewCell *viewCell = dynamic_cast<VspKdViewCell *>(*it);
-
-		if (maxPvs > 0)
-		{			
-			mForcedMaterial.mDiffuseColor.b = 1.0f;
-			
-			const float importance = (float)viewCell->GetPvs().GetSize() / (float)maxPvs;
-			mForcedMaterial.mDiffuseColor.r = importance;
-			mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r;
-		}
-		else 
-			mForcedMaterial = RandomMaterial();
-
-		ExportVspKdTreeViewCell(tree, *viewCell);
-	}
-
-	return true;
-}
-
-bool X3dExporter::ExportVspKdTreeViewCell(const VspKdTree &tree, const VspKdViewCell &vc)
-{
-	vector<VspKdLeaf *>::const_iterator it, it_end = vc.mLeaves.end();
-
-	for (it = vc.mLeaves.begin(); it != it_end; ++ it)
-		ExportBox(tree.GetBBox(*it));
-
-	return true;
-}
 
 bool X3dExporter::ExportKdTree(const KdTree &tree)
@@ -1232,38 +1157,4 @@
 }
 
-void X3dExporter::ExportBspViewCellPartition(const VspBspTree &tree, 
-											 const int maxPvs)
-{
-	ViewCellContainer viewCells;
-	tree.CollectViewCells(viewCells);
-
-	ViewCellContainer::const_iterator it, it_end = viewCells.end();
-
-	if (maxPvs > 0)
-		mUseForcedMaterial = true;
-
-	for (it = viewCells.begin(); it != it_end; ++ it)
-	{
-		if (maxPvs > 0)
-		{
-			mForcedMaterial.mDiffuseColor.b = 1.0f;
-  			float importance = (float)(*it)->GetPvs().GetSize() / (float)maxPvs;
-
-			mForcedMaterial.mDiffuseColor.r = importance;
-			mForcedMaterial.mDiffuseColor.g = 1.0f - mForcedMaterial.mDiffuseColor.r;
-		}
-
-		if ((*it)->GetMesh())
-			ExportViewCell(*it);
-		else
-		{
-			PolygonContainer cell;
-			tree.ConstructGeometry(dynamic_cast<BspViewCell *>(*it), cell);
-
-			ExportPolygons(cell);
-		}
-	}
-}
-
 
 bool
Index: trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.h	(revision 480)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.h	(revision 482)
@@ -140,4 +140,7 @@
 	int maxPvsSize;
 
+	// max cost ratio
+	int maxCostNodes;
+
 	// number of dynamically added ray refs
 	int addedRayRefs;
@@ -145,4 +148,7 @@
 	int removedRayRefs;
   
+	/// for average pvs
+	int accPvsSize;
+
 	/** Default constructor.
 	*/
@@ -167,4 +173,5 @@
 		maxRayContribNodes = 0;
 		minSizeNodes = 0;
+		maxCostNodes = 0;
 
 		maxRayRefs = 0;
@@ -173,4 +180,5 @@
 		initialPvsSize = 0;
 		maxPvsSize = 0;
+		accPvsSize = 0;
 	}
 
@@ -236,5 +244,5 @@
 	VspKdInterior *mParent;
 
-	enum {SPLIT_X = 0, SPLIT_Y, SPLIT_Z, SPLIT_DIRX, SPLIT_DIRY, SPLIT_DIRZ};
+	enum {SPLIT_X = 0, SPLIT_Y, SPLIT_Z};
   
 	/// splitting axis
@@ -431,9 +439,9 @@
 		int type;
 		float value;
-		void *data;
+		VssRay *ray;
   
 		SortableEntry() {}
-		SortableEntry(const int t, const float v, void *d):type(t),
-					  value(v), data(d) 
+		SortableEntry(const int t, const float v, VssRay *r): type(t),
+					  value(v), ray(r) 
 		{
 		}
Index: trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.cpp	(revision 469)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.cpp	(revision 482)
@@ -1771,2 +1771,96 @@
 	return true;
 }
+
+
+bool AxisAlignedBox3::GetIntersectionFace(Rectangle3 &face, 
+										  const AxisAlignedBox3 &neighbour) const
+										   
+{ 
+	if (EpsilonEqual(mMin[0], neighbour.Max(0)))
+	{
+		float maxy = min(mMax.y, neighbour.mMax.y);
+		float maxz = min(mMax.z, neighbour.mMax.z);
+		float miny = max(mMin.y, neighbour.mMin.y);
+		float minz = max(mMin.z, neighbour.mMin.z);
+
+		face.mVertices[3].SetValue(mMin.x, miny, minz);
+		face.mVertices[2].SetValue(mMin.x, maxy, minz);
+		face.mVertices[1].SetValue(mMin.x, maxy, maxz);
+		face.mVertices[0].SetValue(mMin.x, miny, maxz);
+
+        return true;
+	}
+    if (EpsilonEqual(mMax[0], neighbour.Min(0)))
+	{
+		float maxy = min(mMax.y, neighbour.mMax.y);
+		float maxz = min(mMax.z, neighbour.mMax.z);
+		float miny = max(mMin.y, neighbour.mMin.y);
+		float minz = max(mMin.z, neighbour.mMin.z);
+
+		face.mVertices[0].SetValue(mMax.x, miny, minz);
+		face.mVertices[1].SetValue(mMax.x, maxy, minz);
+		face.mVertices[2].SetValue(mMax.x, maxy, maxz);
+		face.mVertices[3].SetValue(mMax.x, miny, maxz);
+
+		return true;
+	}
+    if (EpsilonEqual(mMin[1], neighbour.Max(1)))
+	{
+		float maxx = min(mMax.x, neighbour.mMax.x);
+		float maxz = min(mMax.z, neighbour.mMax.z);
+		float minx = max(mMin.x, neighbour.mMin.x);
+		float minz = max(mMin.z, neighbour.mMin.z);
+
+		face.mVertices[3].SetValue(minx, mMin.y, minz);
+		face.mVertices[2].SetValue(minx, mMin.y, maxz);
+		face.mVertices[1].SetValue(maxx, mMin.y, maxz);
+		face.mVertices[0].SetValue(maxx, mMin.y, minz);
+		
+		return true;
+	}
+	if (EpsilonEqual(mMax[1], neighbour.Min(1)))
+	{		
+		float maxx = min(mMax.x, neighbour.mMax.x);
+		float maxz = min(mMax.z, neighbour.mMax.z);
+		float minx = max(mMin.x, neighbour.mMin.x);
+		float minz = max(mMin.z, neighbour.mMin.z);
+
+		face.mVertices[0].SetValue(minx, mMax.y, minz);
+		face.mVertices[1].SetValue(minx, mMax.y, maxz);
+		face.mVertices[2].SetValue(maxx, mMax.y, maxz);
+		face.mVertices[3].SetValue(maxx, mMax.y, minz);
+
+		return true;
+	}
+	if (EpsilonEqual(mMin[2], neighbour.Max(2)))
+	{
+		float maxx = min(mMax.x, neighbour.mMax.x);
+		float maxy = min(mMax.y, neighbour.mMax.y);
+		float minx = max(mMin.x, neighbour.mMin.x);
+		float miny = max(mMin.y, neighbour.mMin.y);
+
+		face.mVertices[3].SetValue(minx, miny, mMin.z);
+		face.mVertices[2].SetValue(maxx, miny, mMin.z);
+		face.mVertices[1].SetValue(maxx, maxy, mMin.z);
+		face.mVertices[0].SetValue(minx, maxy, mMin.z);
+	
+		return true;
+	}
+	if (EpsilonEqual(mMax[2], neighbour.Min(2)))
+	{
+		float maxx = min(mMax.x, neighbour.mMax.x);
+		float maxy = min(mMax.y, neighbour.mMax.y);
+		float minx = max(mMin.x, neighbour.mMin.x);
+		float miny = max(mMin.y, neighbour.mMin.y);
+
+		face.mVertices[0].SetValue(minx, miny, mMax.z);
+		face.mVertices[1].SetValue(maxx, miny, mMax.z);
+		face.mVertices[2].SetValue(maxx, maxy, mMax.z);
+		face.mVertices[3].SetValue(minx, maxy, mMax.z);
+
+		return true;
+	}
+
+	return false;
+}
+
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp	(revision 480)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp	(revision 482)
@@ -21,8 +21,5 @@
 mTotalArea(0.0f)
 {
-	// post processing stuff
-	environment->GetIntValue("ViewCells.PostProcess.minPvsDif", mMinPvsDif);
-	environment->GetIntValue("ViewCells.PostProcess.minPvs", mMinPvs);
-	environment->GetIntValue("ViewCells.PostProcess.maxPvs", mMaxPvs);
+	ParseEnvironment();
 }
 
@@ -33,8 +30,28 @@
 mVisualizationSamples(0)
 {
+	ParseEnvironment();
+}
+
+void ViewCellsManager::ParseEnvironment()
+{
 	// post processing stuff
 	environment->GetIntValue("ViewCells.PostProcess.minPvsDif", mMinPvsDif);
 	environment->GetIntValue("ViewCells.PostProcess.minPvs", mMinPvs);
 	environment->GetIntValue("ViewCells.PostProcess.maxPvs", mMaxPvs);
+
+	char buf[50];
+	
+	environment->GetStringValue("ViewCells.Visualization.colorCode", buf);
+	
+	if (strcmp(buf, "PVS") == 0)
+		mColorCode = 1;
+	else if (strcmp(buf, "MergedLeaves") == 0)
+		mColorCode = 2;
+	else if (strcmp(buf, "MergedTreeDiff") == 0)
+		mColorCode = 3;
+	else
+		mColorCode = 0;
+
+	Debug << "colorCode: " << mColorCode << endl;
 }
 
@@ -336,7 +353,20 @@
 }
 
+
 void ViewCellsManager::PrintStatistics(ostream &s) const
 {
 	s << mViewCellsStats << endl;
+}
+
+
+void ViewCellsManager::ExportViewCells(Exporter *exporter) const
+{
+	ViewCellContainer::const_iterator it, it_end = mViewCells.end();
+
+	for (it = mViewCells.begin(); it != it_end; ++ it)
+	{
+		ExportColor(exporter, *it);
+		ExportGeometry(exporter, *it);
+	}
 }
 
@@ -345,4 +375,5 @@
 /*                   BspViewCellsManager implementation               */
 /**********************************************************************/
+
 
 BspViewCellsManager::BspViewCellsManager(BspTree *bspTree, 
@@ -490,6 +521,5 @@
 			//exporter->SetWireframe();
 			exporter->SetFilled();
-			exporter->ExportBspViewCellPartition(*mBspTree, 
-				mViewCellsStats.maxPvs);
+			ExportViewCells(exporter);
 				
 			if (0)
@@ -593,6 +623,5 @@
 		if (exporter)
 		{
-			exporter->ExportBspViewCellPartition(*mBspTree, 
-				mViewCellsStats.maxPvs);
+			ExportViewCells(exporter);
 			delete exporter;
 		}
@@ -635,11 +664,11 @@
 		exporter->ExportBspSplits(*mBspTree, true);
 
-		// take forced material, else big scenes cannot be viewed
+		//NOTE: take forced material, else big scenes cannot be viewed
 		m.mDiffuseColor = RgbColor(0, 1, 0);
 		exporter->SetForcedMaterial(m);
+		//exporter->ResetForcedMaterial();
+
 		exporter->SetFilled();
-
-		exporter->ResetForcedMaterial();
-		
+				
 		// export rays
 		if (0)
@@ -671,5 +700,5 @@
 
 	environment->GetBoolValue("VspBspTree.Visualization.exportRays", exportRays);
-	environment->GetBoolValue("VspBspTree.Visualization.exportGeometry", exportGeometry);
+	environment->GetBoolValue("VspBspTree.Visualization.exportRays", exportRays);
 
 	const int leafOut = 10;
@@ -866,4 +895,62 @@
 }
 
+
+void BspViewCellsManager::ExportColor(Exporter *exporter, 
+									  ViewCell *vc) const
+{
+	if (mColorCode == 0) // Random color
+	{
+		exporter->ResetForcedMaterial();
+		return;
+	}
+
+	float importance = 0;
+
+	switch (mColorCode)
+	{
+	case 1: // pvs
+		{
+			importance = (float)vc->GetPvs().GetSize() / 
+				(float)mViewCellsStats.maxPvs;
+		}
+		break;
+	case 2: // merges
+		{
+			BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
+
+			importance = (float)bspVc->mLeaves.size() / 
+				(float)mViewCellsStats.maxLeaves;
+		}
+		break;
+	case 3: // merge tree differene
+		{
+			// TODO
+		}
+		break;
+	default:
+		break;
+	}
+
+	Material m;
+	m.mDiffuseColor.b = 1.0f;
+	m.mDiffuseColor.r = importance;
+	m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
+	
+	exporter->SetForcedMaterial(m);
+}
+
+void BspViewCellsManager::ExportGeometry(Exporter *exporter, 
+										 ViewCell *vc) const
+{
+	if (vc->GetMesh())
+		exporter->ExportViewCell(vc);
+	else
+	{
+		PolygonContainer cell;
+		mBspTree->ConstructGeometry(dynamic_cast<BspViewCell *>(vc), cell);
+
+		exporter->ExportPolygons(cell);
+	}
+}
 
 /**********************************************************************/
@@ -1116,4 +1203,18 @@
 
 
+void KdViewCellsManager::ExportColor(Exporter *exporter,
+									 ViewCell *vc) const
+{
+	// TODO
+}
+
+
+void KdViewCellsManager::ExportGeometry(Exporter *exporter, 
+										ViewCell *vc) const
+{
+	// TODO
+}
+
+
 int KdViewCellsManager::GetType() const
 {
@@ -1143,4 +1244,5 @@
 /*                   VspKdViewCellsManager implementation             */
 /**********************************************************************/
+
 
 VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree, 
@@ -1192,9 +1294,13 @@
 	Debug << mVspKdTree->GetStatistics() << endl;
 
-	ResetViewCells();
-	Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
+	// export leaf building blocks
+	ExportLeaves(objects, rays);
 
 	// finally merge kd leaf building blocks to view cells
 	const int merged = mVspKdTree->MergeLeaves();
+	// evaluale view cell stats
+	ResetViewCells();
+
+	Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
 
 	// recast rest of rays
@@ -1221,10 +1327,60 @@
 		return 0;
 
+	// recalculate stats
+	EvaluateViewCellsStats();
+
 	return 0;
 }
 
+
 AxisAlignedBox3 VspKdViewCellsManager::GetSceneBbox() const
 {
 	return mVspKdTree->GetBBox(mVspKdTree->GetRoot());
+}
+
+
+void VspKdViewCellsManager::ExportLeaves(const ObjectContainer &objects,
+										 const VssRayContainer &sampleRays)
+{
+	bool exportRays = false;
+	bool exportGeometry = false;
+
+	environment->GetBoolValue("VspKdTree.Visualization.exportRays", exportRays);
+	environment->GetBoolValue("VspKdTree.Visualization.exportGeometry", exportGeometry);
+
+	if (!ViewCellsConstructed())
+		return;
+
+	//-- export leaf building blocks
+	Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d"); 
+	if (!exporter)
+		return;
+
+	//exporter->SetWireframe();
+	//exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
+	exporter->ExportVspKdTree(*mVspKdTree);
+
+	if (exportGeometry) 
+		exporter->ExportGeometry(objects);
+
+	if (exportRays) 
+	{
+		const float prob = (float)mVisualizationSamples 
+			/ ((float)sampleRays.size() + Limits::Small);
+
+		exporter->SetWireframe();
+
+		//-- collect uniformly distributed rays
+		VssRayContainer rays;
+
+		for (int i = 0; i < sampleRays.size(); ++ i)
+		{
+			if (RandomValue(0,1) < prob)
+				rays.push_back(sampleRays[i]);
+		}
+		exporter->ExportRays(rays, RgbColor(1, 0, 0));
+	}
+
+	delete exporter;
 }
 
@@ -1240,88 +1396,81 @@
 	if (!ViewCellsConstructed())
 		return;
-
-	//-- export tree leaves
-	if (1)
-	{
-		Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d"); 
-		//exporter->SetWireframe();
-		//exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
-		exporter->ExportVspKdTree(*mVspKdTree);
-
-		if (1) 
-			exporter->ExportGeometry(objects);
-
-		if (exportRays) 
-		  {
-			int raysSize = 2000;
-			float prob = raysSize / (float)sampleRays.size();
-		
-			exporter->SetWireframe();
-			
-			VssRayContainer rays;
-		
-			for (int i = 0; i < sampleRays.size(); ++ i)
+	
+	//-- export single view cells
+	for (int i = 0; i < 10; ++ i)
+	{
+		char s[64];
+		sprintf(s, "vsp_viewcell%04d.x3d", i);
+		Exporter *exporter = Exporter::GetExporter(s);
+		const int idx = 
+			(int)RandomValue(0.0, (Real)((int)mViewCells.size() - 1));
+
+		VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(mViewCells[idx]); 
+
+		//-- export geometry
+		Material m;
+		m.mDiffuseColor = RgbColor(0, 1, 1);
+				
+		exporter->SetForcedMaterial(m);
+		exporter->SetWireframe();
+
+		ExportGeometry(exporter, vc);
+
+		//-- export stored rays
+		if (exportRays)
+		{
+			vector<VspKdLeaf *>::const_iterator it, 
+				it_end = vc->mLeaves.end();
+
+			for (it = vc->mLeaves.begin(); it != it_end; ++ it)
 			{
-				if (RandomValue(0,1) < prob)
-					rays.push_back(sampleRays[i]);
+				VspKdLeaf *leaf = *it;
+				AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
+
+				VssRayContainer vssRays;
+				leaf->GetRays(vssRays);
+
+				VssRayContainer rays;
+				VssRayContainer::const_iterator it, it_end = vssRays.end();
+
+				for (it = vssRays.begin(); it != it_end; ++ it)
+					rays.push_back(*it);
+			
+				exporter->ExportRays(rays, RgbColor(1, 0, 0));
 			}
-
-			exporter->ExportRays(rays, RgbColor(1, 0, 0));
+		}
+
+		//-- output PVS of view cell
+		m.mDiffuseColor = RgbColor(1, 0, 0);
+		exporter->SetForcedMaterial(m);
+
+		ObjectPvsMap::const_iterator it,
+			it_end = vc->GetPvs().mEntries.end();
+
+		exporter->SetFilled();
+
+		for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it) 
+		{
+			Intersectable *intersect = (*it).first;
+
+			if (!intersect->Mailed())
+			{
+				Material m = RandomMaterial();
+				exporter->SetForcedMaterial(m);
+
+				exporter->ExportIntersectable(intersect);
+				intersect->Mail();
+			}			
 		}
 
 		delete exporter;
-	}
-
-	//-- export single leaves
-	if (1)
-	{
-		vector<VspKdLeaf *> leafContainer;
-		mVspKdTree->CollectLeaves(leafContainer);
-
-		for (int i = 0; i < 10; ++ i)
-		{
-			char s[64];
-			sprintf(s, "vsp_leaves%04d.x3d", i);
-			Exporter *exporter = Exporter::GetExporter(s);
-
-			// export geometry
-			VspKdLeaf *leaf = leafContainer[(int)RandomValue(0.0, (Real)((int)leafContainer.size() - 1))]; 
-			AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
-
-			Material m;
-			m.mDiffuseColor = RgbColor(0, 1, 1);
-			exporter->SetForcedMaterial(m);
-			exporter->SetWireframe();
-			exporter->ExportBox(box);
-
-			//-- export stored rays
-			VssRayContainer vssRays;
-			leaf->GetRays(vssRays);
-
-			VssRayContainer rays;
-			VssRayContainer::const_iterator it, it_end = vssRays.end();
-
-			for (it = vssRays.begin(); it != it_end; ++ it)
-				rays.push_back(*it);
-			
-			exporter->ExportRays(rays, RgbColor(1, 0, 0));
-
-			//-- export stored PVS
-			ObjectContainer pvsObj;
-			leaf->ExtractPvs(pvsObj);
-				
-			exporter->ExportGeometry(pvsObj);
-
-			delete exporter;
-		}			
 	}
 
 	//-- export final view cells
 	Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d"); 
-	exporter->SetWireframe();
-	//exporter->ExportVspKdTreeViewCells(*mVspKdTree, vcStats.maxPvs);
-	exporter->ExportVspKdTreeViewCells(*mVspKdTree);
-
-	if (1) 
+	exporter->SetFilled();
+	ExportViewCells(exporter);
+
+	if (exportGeometry) 
 	{
 		exporter->SetFilled();
@@ -1331,6 +1480,6 @@
 	if (exportRays) 
 	{
-		int raysSize = 2000;
-		float prob = raysSize / (float)sampleRays.size();
+		const float prob = (float)mVisualizationSamples 
+			/ ((float)sampleRays.size() + Limits::Small);
 		
 		exporter->SetWireframe();
@@ -1363,8 +1512,65 @@
 
 
+void VspKdViewCellsManager::ExportColor(Exporter *exporter,
+										ViewCell *vc) const
+{
+	if (mColorCode == 0) // Random color
+		return;
+	
+	float importance = 0;
+
+	switch (mColorCode)
+	{
+	case 1: // pvs
+		{
+			importance = (float)vc->GetPvs().GetSize() / 
+				(float)mViewCellsStats.maxPvs;
+		}
+		break;
+	case 2: // merges
+		{
+            VspKdViewCell *vspKdVc = dynamic_cast<VspKdViewCell *>(vc);
+
+			importance = (float)vspKdVc->mLeaves.size() / 
+				(float)mViewCellsStats.maxLeaves;
+		}
+		break;
+	case 3: // merge tree differene
+		{
+			//importance = (float)GetMaxTreeDiff(vc) / 
+			//	(float)(mVspBspTree->GetStatistics().maxDepth * 2);
+		}
+		break;
+	default:
+		break;
+	}
+
+	Material m;
+	m.mDiffuseColor.b = 1.0f;
+	m.mDiffuseColor.r = importance;
+	m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
+	//Debug << "importance: " << importance << endl;
+	exporter->SetForcedMaterial(m);
+}
+
+
+void VspKdViewCellsManager::ExportGeometry(Exporter *exporter, 
+										   ViewCell *vc) const
+{
+	VspKdViewCell *kdVc = dynamic_cast<VspKdViewCell *>(vc);
+
+	vector<VspKdLeaf *>::const_iterator it, it_end = kdVc->mLeaves.end();
+
+	for (it = kdVc->mLeaves.begin(); it != it_end; ++ it)
+	{
+		exporter->ExportBox(mVspKdTree->GetBBox(*it));
+	}
+}
+
 
 /**********************************************************************/
 /*                 VspBspViewCellsManager implementation              */
 /**********************************************************************/
+
 
 VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree, 
@@ -1511,6 +1717,6 @@
 			//exporter->SetWireframe();
 			exporter->SetFilled();
-			//exporter->ExportBspViewCellPartition(*mVspBspTree, mViewCellsStats.maxPvs);
-			exporter->ExportBspViewCellPartition(*mVspBspTree);
+			
+			ExportViewCells(exporter);
 
 			if (0)
@@ -1612,6 +1818,5 @@
 		if (exporter)
 		{
-			//exporter->ExportBspViewCellPartition(*mVspBspTree, mViewCellsStats.maxPvs);
-			exporter->ExportBspViewCellPartition(*mVspBspTree);
+			ExportViewCells(exporter);
 			delete exporter;
 		}
@@ -1633,9 +1838,15 @@
 	ExportBspPvs(objects);
 }
-
+	
 
 void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects)
 {
 	Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
+
+	bool exportRays = false;
+	bool exportGeometry = false;
+
+	environment->GetBoolValue("VspBspTree.Visualization.exportRays", exportRays);
+	environment->GetBoolValue("VspBspTree.Visualization.exportGeometry", exportGeometry);
 
 	if (exporter) 
@@ -1656,5 +1867,5 @@
 		
 		// export rays
-		if (0)
+		if (exportRays)
 		{
 			VssRayContainer outRays;
@@ -1670,5 +1881,5 @@
 		}
 
-		if (0)
+		if (exportGeometry)
 			exporter->ExportGeometry(objects);
 
@@ -1861,2 +2072,85 @@
 	return mVspBspTree->CastLineSegment(origin, termination, viewcells);
 }
+
+
+void VspBspViewCellsManager::ExportColor(Exporter *exporter, 
+										 ViewCell *vc) const
+{
+	if (mColorCode == 0) // Random color
+		return;
+	
+	float importance = 0;
+
+	switch (mColorCode)
+	{
+	case 1: // pvs
+		{
+			importance = (float)vc->GetPvs().GetSize() / 
+				(float)mViewCellsStats.maxPvs;
+		}
+		break;
+	case 2: // merges
+		{
+            BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
+
+			importance = (float)bspVc->mLeaves.size() / 
+				(float)mViewCellsStats.maxLeaves;
+		}
+		break;
+	case 3: // merge tree differene
+		{
+			importance = (float)GetMaxTreeDiff(vc) / 
+				(float)(mVspBspTree->GetStatistics().maxDepth * 2);
+		}
+		break;
+	default:
+		break;
+	}
+
+	Material m;
+	m.mDiffuseColor.b = 1.0f;
+	m.mDiffuseColor.r = importance;
+	m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
+	//Debug << "importance: " << importance << endl;
+	exporter->SetForcedMaterial(m);
+}
+
+
+void VspBspViewCellsManager::ExportGeometry(Exporter *exporter, 
+											ViewCell *vc) const
+{
+	if (vc->GetMesh())
+		exporter->ExportViewCell(vc);
+	else
+	{
+		PolygonContainer cell;
+		mVspBspTree->
+			ConstructGeometry(dynamic_cast<BspViewCell *>(vc), cell);
+
+		exporter->ExportPolygons(cell);
+	}
+}
+
+
+int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
+{
+	BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
+
+	int maxDist = 0;
+	// compute max height difference
+	for (int i = 0; i < (int)bspVc->mLeaves.size(); ++ i)
+		for (int j = 0; j < (int)bspVc->mLeaves.size(); ++ j)
+	{
+		BspLeaf *leaf = bspVc->mLeaves[i];
+
+		if (i != j)
+		{
+			BspLeaf *leaf2 = bspVc->mLeaves[j];
+			int dist = mVspBspTree->TreeDistance(leaf, leaf2);
+			if (dist > maxDist)
+				maxDist = dist;
+		}
+	}
+
+	return maxDist;
+}
