Index: trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env	(revision 264)
+++ trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env	(revision 265)
@@ -13,6 +13,6 @@
 #	viewcells ../data/atlanta/atlanta_viewcells_large.x3d
 #viewcells ../data/atlanta/atlanta_viewcells_large2.x3d
-#	viewcells ../data/vienna/viewcells-25-sel.x3d
-	viewcells ../data/vienna/viewcells-25.x3d
+	viewcells ../data/vienna/viewcells-25-sel.x3d
+#	viewcells ../data/vienna/viewcells-25.x3d
 #	viewcells ../data/vienna/viewcells-large-sel.x3d
 }
@@ -63,6 +63,6 @@
 
 BspTree {
-	splitPlaneStrategy leastSplits
-#	splitPlaneStrategy balancedTree
+#	splitPlaneStrategy leastSplits
+	splitPlaneStrategy balancedTree
 #	splitPlaneStrategy nextPolygon
 #	splitPlaneStrategy combined
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.cpp	(revision 264)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.cpp	(revision 265)
@@ -4,4 +4,7 @@
 #include "Triangle3.h"
 
+ViewCell::ViewCell(): mMesh(NULL)
+{
+}
 
 ViewCell::ViewCell(Mesh *mesh): mMesh(mesh), mPvs(NULL) 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Pvs.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Pvs.h	(revision 260)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Pvs.h	(revision 265)
@@ -48,5 +48,5 @@
   int AddNodeSample(KdNode *node);
   int Compress() {return 0;}
-  int GetSize() { return mEntries.size(); }
+  int GetSize() { return (int)mEntries.size(); }
   void GetData(const int index,
 	       KdNode *&node,
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 264)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 265)
@@ -46,4 +46,6 @@
   // maximal reached depth
   int maxDepth;
+  // minimal depth
+  int minDepth;
   // total number of query domains
   int queryDomains;
@@ -64,5 +66,11 @@
   // number of dynamically removed ray refs
   int removedRayRefs;
-  
+  // accumulated depth (used to compute average)
+  int accumDepth;
+  // number of initial polygons
+  int polys;
+  /// number of view cells in leaf
+  int viewCellLeaves;
+
   // Constructor
   BspTreeStatistics() 
@@ -74,5 +82,6 @@
   int Interior() const { return nodes / 2; }
   int Leaves() const { return (nodes / 2) + 1; }
-
+  int AvgDepth() const { return accumDepth / Leaves();};
+  
   void Reset() 
   {
@@ -83,7 +92,12 @@
 	  zeroQueryNodes = 0;
       maxDepthNodes = 0;
-      //minCostNodes = 0;
+
 	  maxObjectRefs = 0;
 	  addedRayRefs = removedRayRefs = 0;
+	  maxDepth = 0;
+	  minDepth = 99999;
+	  polys = 0;
+	  accumDepth = 0;
+	  viewCellLeaves = 0;
   }
 
@@ -316,6 +330,8 @@
 
 	/** Constructs the tree from the given list of polygons.
-	*/
-	void Construct(PolygonContainer *polys);
+		@param viewCells if not NULL, new view cells are 
+		created in the leafs and stored in the conatainer
+	*/
+	void Construct(PolygonContainer *polys, ViewCellContainer *viewCells = NULL);
 
 	/** Evaluates the contribution of the candidate split plane.
@@ -376,15 +392,18 @@
 		Adds object aabb to the aabb of the tree.
 		@param maxPolys the maximal number of objects to be stored as polygons
-	*/
-	void Copy2PolygonSoup(const ObjectContainer &objects, PolygonContainer &polys, int maxObjects);
+		@returns the number of polygons
+	*/
+	int Copy2PolygonSoup(const ObjectContainer &objects, PolygonContainer &polys, int maxObjects);
 	/** Extracts the meshes of the view cells and copies them into the mesh. 
 		Adds view cell aabb to the aabb of the tree.
 		@param maxPolys the maximal number of objects to be stored as polygons
-	*/
-	void Copy2PolygonSoup(const ViewCellContainer &viewCells, PolygonContainer &polys, int maxObjects);
-
-	/** Add this mesh as polygons to polygon container.
-	*/
-	void AddMesh2Polygons(Mesh *mesh, PolygonContainer &polys);
+		@returns the number of polygons
+	*/
+	int Copy2PolygonSoup(const ViewCellContainer &viewCells, PolygonContainer &polys, int maxObjects);
+
+	/** Extract polygons of this mesh and add to polygon container.
+		@returns number of polygons
+	*/
+	int AddMesh2Polygons(Mesh *mesh, PolygonContainer &polys);
 
 	/** A ray is cast possible intersecting the tree.
@@ -393,6 +412,4 @@
 	*/
 	int CastRay(Ray &ray);
-
-
 
 	/// Pointer to the root of the tree
Index: trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.h	(revision 191)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/AxisAlignedBox3.h	(revision 265)
@@ -45,5 +45,5 @@
 
   float Center(const int axis) const {
-    return  0.5 * (mMin[axis] + mMax[axis]);
+    return  0.5f * (mMin[axis] + mMax[axis]);
   }
 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.h	(revision 209)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.h	(revision 265)
@@ -167,5 +167,5 @@
   virtual bool IsConvex() { return mMesh->mIsConvex; }
   virtual bool IsWatertight() { return mMesh->mIsWatertight; }
-  virtual float IntersectionComplexity() {  return mMesh->mFaces.size(); }
+  virtual float IntersectionComplexity() {  return (int)mMesh->mFaces.size(); }
 
   virtual int Type() const { return MESH_INSTANCE; }
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 264)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 265)
@@ -17,6 +17,6 @@
 int BspTree::sTermMaxPolygons = 10;
 int BspTree::sTermMaxDepth = 20;
+int BspTree::sMaxCandidates = 10;
 int BspTree::sSplitPlaneStrategy = NEXT_POLYGON; 
-int BspTree::sMaxCandidates = 10;
 int BspTree::sConstructionMethod = VIEW_CELLS;
 
@@ -30,5 +30,4 @@
 int BspTree::sBalancedTreeTable[4] = {-1, 1, 0, 0};
 
-int counter = 0;
 /****************************************************************/
 /*                  class BspNode implementation                */
@@ -36,6 +35,5 @@
 
 BspNode::BspNode(): mParent(NULL), mPolygons(NULL)
-{
-}
+{}
 
 BspNode::BspNode(BspInterior *parent): mParent(parent), mPolygons(NULL)
@@ -50,4 +48,5 @@
 	}
 }
+
 bool BspNode::IsRoot() const 
 {
@@ -145,7 +144,7 @@
 								int &splits, bool storePolys)
 {
-#ifdef _Debug
+//#ifdef _Debug
 	Debug << "Splitting polygons of node " << this << " with plane " << mPlane << endl;
-#endif
+//#endif
 	bool inside = false;
 
@@ -156,10 +155,11 @@
 
 		// test if split is neccessary
-		int result = poly->ClassifyPlane(mPlane);
-
+		int classification = poly->ClassifyPlane(mPlane);
+
+		//Debug << "polygon plane: " << poly->GetSupportingPlane() << endl;
 		Polygon3 *front_piece = NULL;
 		Polygon3 *back_piece = NULL;
 		
-		switch (result)
+		switch (classification)
 		{
 			case Polygon3::COINCIDENT:
@@ -169,20 +169,20 @@
 					inside = (DotProd(mPlane.mNormal, poly->GetSupportingPlane().mNormal) > 0);
 					
-				//Debug << "coincident" << endl;
+				Debug << "coincident" << endl;
 				// discard polygons or saves them in node
 				ProcessPolygon(poly, storePolys);
 				break;
 			case Polygon3::FRONT_SIDE:
-				//Debug << "front" << endl;
+				Debug << "front" << endl;
 				frontPolys->push_back(poly);
 				break;
 			case Polygon3::BACK_SIDE:
 				inside = true;
-				//Debug << "back" << endl;
+				Debug << "back" << endl;
 				backPolys->push_back(poly);
 				break;
 			case Polygon3::SPLIT:
 				inside = true;
-				//Debug << "split" << endl;
+				Debug << "split " << poly << endl;
 
 				front_piece = new Polygon3();
@@ -279,7 +279,9 @@
 	app << "#N_NODES ( Number of nodes )\n" << nodes << "\n";
 
+	app << "#N_LEAVES ( Number of interior nodes )\n" << Interior() << "\n";
+
 	app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n";
 
-	app << "#N_SPLITS ( Number of splits)\n" << splits << "\n";
+	app << "#N_SPLITS ( Number of splits )\n" << splits << "\n";
 
 	app << "#N_RAYREFS ( Number of rayRefs )\n" <<
@@ -307,17 +309,22 @@
 	maxDepthNodes * 100 / (double)Leaves() << endl;
 
-	app << "#N_PMAXDEPTH ( Maximal reached depth )\n" << maxDepth <<endl;
-
-	app << "#N_ADDED_RAYREFS  (Number of dynamically added ray references )\n"<<
-	addedRayRefs<<endl;
-
-	app << "#N_REMOVED_RAYREFS  (Number of dynamically removed ray references )\n"<<
-	removedRayRefs<<endl;
-
-	//  app << setprecision(4);
-
-	//  app << "#N_CTIME  ( Construction time [s] )\n"
-	//      << Time() << " \n";
-
+	app << "#N_PMAXDEPTH ( Maximal reached depth )\n" << maxDepth << endl;
+
+	app << "#N_PMINDEPTH ( Minimal reached depth )\n" << minDepth << endl;
+
+	app << "#AVGEPTH ( average depth )\n" << AvgDepth() << endl;
+
+	app << "#N_ADDED_RAYREFS  ( Number of dynamically added ray references )\n"<<
+	addedRayRefs << endl;
+
+	app << "#N_REMOVED_RAYREFS  ( Number of dynamically removed ray references )\n" <<
+	removedRayRefs << endl;
+
+	app << "#N_INPUT_POLYGONS (number of input polygons )\n" <<
+		polys << endl;
+
+	app << "#N_ROUTPUT_INPUT_POLYGONS ( ratio polygons after subdivision / input polygons )\n" <<
+		 (polys + splits) / (double)polys << endl;
+	
 	app << "===== END OF BspTree statistics ==========\n";
 }
@@ -356,5 +363,5 @@
 
 	// extract polygons that guide the split process
-	AddMesh2Polygons(viewCell->GetMesh(), *polys);
+	mStat.polys += AddMesh2Polygons(viewCell->GetMesh(), *polys);
 	mBox.Include(viewCell->GetBox()); // add to BSP aabb
 
@@ -382,4 +389,5 @@
 				int splits = 0;
 		
+				Debug << "Splitting poly, YEAHH\n";
 				// split viecell polygons with respect to split plane
 				bool inside = interior->SplitPolygons(tData.mPolygons, frontPolys, backPolys, splits, mStorePolys);
@@ -399,12 +407,16 @@
 		else // reached leaf => subdivide current viewcell
 		{
+			if (tData.mPolygons->size() > 0)
+				Debug << "WARNING (should not come here): polygon size: " << tData.mPolygons->size() << " inside: " << tData.mIsInside  << endl;
+
 			BspNode *root = Subdivide(tStack, tData, viewCell);		
 
-            // tree empty => new root
-			if (!mRoot)
+			//if (!root->IsLeaf())
+			//	Debug << "WARNING should NOT have subdivided further\n";
+         
+			if (!mRoot) // tree empty => new root
 				mRoot = root;
 		}
 	}
-	Debug << "ended traversal" << endl; Debug.flush();
 }
 
@@ -420,8 +432,9 @@
 
 
-void BspTree::AddMesh2Polygons(Mesh *mesh, PolygonContainer &polys)
+int BspTree::AddMesh2Polygons(Mesh *mesh, PolygonContainer &polys)
 {
 	FaceContainer::const_iterator fi;
-	
+	int polysNum = 0;
+
 	// copy the face data to polygons
 	for (fi = mesh->mFaces.begin(); fi != mesh->mFaces.end(); ++ fi)
@@ -429,8 +442,10 @@
 		Polygon3 *poly = new Polygon3((*fi), mesh);
 		polys.push_back(poly);
-	}
-}
-
-void BspTree::Copy2PolygonSoup(const ViewCellContainer &viewCells, PolygonContainer &polys, int maxObjects)
+		polysNum ++;
+	}
+	return polysNum;
+}
+
+int BspTree::Copy2PolygonSoup(const ViewCellContainer &viewCells, PolygonContainer &polys, int maxObjects)
 {
 	int limit = (maxObjects > 0) ? Min((int)viewCells.size(), maxObjects) : (int)viewCells.size();
@@ -444,7 +459,9 @@
 		}
 	}
-}
-
-void BspTree::Copy2PolygonSoup(const ObjectContainer &objects, PolygonContainer &polys, int maxObjects)
+
+	return (int)polys.size();
+}
+
+int BspTree::Copy2PolygonSoup(const ObjectContainer &objects, PolygonContainer &polys, int maxObjects)
 {
 	int limit = (maxObjects > 0) ? Min((int)objects.size(), maxObjects) : (int)objects.size();
@@ -475,5 +492,5 @@
 	}
 
-	Debug << "Number of polygons: " << (int)polys.size() << ", BSP root box: " << mBox << endl;
+	return (int)polys.size();
 }
 
@@ -511,15 +528,17 @@
 
 	mStorePolys = savedStorePolys;
-
-	counter = 0;
-
-	Debug << "\n**** Started view cells insertion ****\n\n";
+	mStat.polys = 0;
+	mStat.splits = 0;
+	//int counter = 0;
+	
+	long startTime = GetTime();
+	Debug << "**** Starting view cell insertion ****" << endl;
 	for (it = viewCells.begin(); it != viewCells.end(); ++ it)
 	{
-		Debug << "*** Inserting view cell " << counter << " ***" << endl;
+		//Debug << "*** Inserting view cell " << counter ++ << " ***" << endl;
 		InsertViewCell(*it);
-		counter ++;
-	}
-	Debug << "**** finished view cells insertion ****" << endl; Debug.flush();
+	}
+	Debug << "**** Finished view cell insertion ****" << endl;
+	Debug << "insertion time: "<< TimeDiff(startTime, GetTime())*1e-3 << "s" << endl;
 }
 
@@ -533,5 +552,5 @@
 	
 	// copy mesh instance polygons into one big polygon soup
-	Copy2PolygonSoup(objects, *polys, sMaxCandidates);
+	mStat.polys = Copy2PolygonSoup(objects, *polys, sMaxCandidates);
 
 	// construct tree from polygon soup
@@ -546,5 +565,5 @@
 }
 
-void BspTree::Construct(PolygonContainer *polys)
+void BspTree::Construct(PolygonContainer *polys, ViewCellContainer *viewCells)
 {
 	std::stack<BspTraversalData> tStack;
@@ -554,4 +573,5 @@
 	tStack.push(tData);
 
+	long startTime = GetTime();
 	Debug << "**** Contructing tree using objects ****\n";
 	while (!tStack.empty()) 
@@ -559,7 +579,15 @@
 		tData = tStack.top();
 	    tStack.pop();
-	
+
+		ViewCell *viewCell = NULL;
+
+        if (viewCells) // generate new view cell in leaf
+		{
+			viewCell = new ViewCell();
+			viewCells->push_back(viewCell);
+		}
+
 		// subdivide leaf node
-		BspNode *root = Subdivide(tStack, tData);
+		BspNode *root = Subdivide(tStack, tData, viewCell);
 
 		// empty tree => new root corresponding to unbounded space
@@ -568,5 +596,6 @@
 	}
 
-	Debug << "**** tree construction finished ****\n";
+	Debug << "**** Finished tree construction ****\n";
+	Debug << "BSP tree contruction time: "<< TimeDiff(startTime, GetTime())*1e-3 << "s" << endl;
 }
 
@@ -576,10 +605,10 @@
 {
 	//-- terminate traversal  
-	if (((tData.mPolygons->size() <= mTermMaxPolygons) || (tData.mDepth >= mTermMaxDepth))
+	if ((tData.mPolygons->size() <= mTermMaxPolygons) || (tData.mDepth >= mTermMaxDepth))
 		// if there is another view cell associated with this leaf => subdivide further
-		&& !(viewCell && tData.mIsInside && dynamic_cast<BspLeaf *>(tData.mNode)->GetViewCell()))
+		//&& !(viewCell && tData.mIsInside && dynamic_cast<BspLeaf *>(tData.mNode)->GetViewCell()))  
 	{
 #ifdef _DEBUG
-        Debug << "terminate subdivision, size " << (int)tData.mPolygons->size() << ", depth " << tData.mDepth << endl;
+		Debug << "subdivision terminated at depth " << tData.mDepth << ", #polys: " << (int)tData.mPolygons->size() << endl;
 #endif
 
@@ -587,15 +616,11 @@
 
 	    // add view cell if inside object) 
-		if (viewCell && tData.mIsInside) 
-			// || (tData.mGeometry->size() > 0) // or if there is still geometry left 
+		if (viewCell && tData.mIsInside) // || (tData.mGeometry->size() > 0) // or if there is still geometry left 
 		{
 			BspLeaf *leaf = dynamic_cast<BspLeaf *>(tData.mNode);
 
-#ifdef _DEBUG
 			if (leaf->GetViewCell())
 				Debug << "ERROR: leaf already has view cell" << endl;
 
-			Debug << "**** Inserted view cell ****" << endl;
-#endif
 			leaf->SetViewCell(viewCell);
 		}
@@ -613,4 +638,5 @@
 	bool inside = false;
 
+	Debug << "Subdividing node at depth " << tData.mDepth << endl;
 	BspInterior *interior = SubdivideNode(dynamic_cast<BspLeaf *>(tData.mNode),
 										  tData.mPolygons,
@@ -618,5 +644,6 @@
 										  backPolys, inside);
 
-	// push the children on the stack (there are always two children)
+	// push the children on the stack
+	// inside information is only propagated with the back leaf
 	tStack.push(BspTraversalData(interior->GetBack(), backPolys, tData.mDepth + 1, inside));
 	tStack.push(BspTraversalData(interior->GetFront(), frontPolys, tData.mDepth + 1, false));
@@ -657,5 +684,6 @@
 
 	// and setup child links
-	interior->SetupChildLinks(new BspLeaf(interior, leaf->mViewCell), new BspLeaf(interior));
+	//interior->SetupChildLinks(new BspLeaf(interior), new BspLeaf(interior, leaf->mViewCell));
+	interior->SetupChildLinks(new BspLeaf(interior), new BspLeaf(interior));
 	
 	delete leaf; // leaf not member of tree anymore
@@ -685,11 +713,11 @@
 {
 	int lowestCost = INITIAL_COST;
-	Plane3 *bestPlane = NULL;
+	int bestPlaneIdx = 0;
 	
 	int limit = Min((int)polygons->size(), maxTests);
 
-	for (int i = 0; i < limit; ++i)
-	{
-		int candidateIdx = Random((int)polygons->size());
+	for (int i = 0; i < limit; ++ i)
+	{
+		int candidateIdx = Random((int)polygons->size()); // TODO:  avoid testing same plane 2 times
 		Plane3 candidatePlane = (*polygons)[candidateIdx]->GetSupportingPlane();
 		
@@ -699,11 +727,15 @@
 		if (candidateCost < lowestCost)
 		{
-			bestPlane = &candidatePlane;
+			bestPlaneIdx = candidateIdx;
 			lowestCost = candidateCost;
 			//Debug << "new plane cost " << lowestCost << endl;
 		}
 	}
-		
-	return *bestPlane;
+	
+	if (lowestCost > 0)
+		Debug << "Split plane cost: " << lowestCost << " plane: " << (*polygons)[bestPlaneIdx]->GetSupportingPlane() << endl;
+	else
+		Debug << "no splits for plane: " << (*polygons)[bestPlaneIdx]->GetSupportingPlane() << endl;
+	return (*polygons)[bestPlaneIdx]->GetSupportingPlane();
 }
 
@@ -712,7 +744,7 @@
 	PolygonContainer::const_iterator it;
 
-	int sum = 0, sum2 = 0;
-
-	for (it = polygons->begin(); it < polygons->end(); ++ it)
+	int sumBalanced = 0, sumLeastSplits = 0;
+
+	for (it = polygons->begin(); it != polygons->end(); ++ it)
 	{
 		int classification = (*it)->ClassifyPlane(candidatePlane);
@@ -720,15 +752,18 @@
 		if ((sSplitPlaneStrategy == COMBINED) || (sSplitPlaneStrategy == BALANCED_TREE))
 		{
-			sum += sBalancedTreeTable[classification];
+			sumBalanced += sBalancedTreeTable[classification];
 		}
 		
-		if ((sSplitPlaneStrategy == COMBINED) ||(sSplitPlaneStrategy == LEAST_SPLITS))
-		{
-			sum2 += sLeastSplitsTable[classification];
-		}
-	}
+		if ((sSplitPlaneStrategy == COMBINED) || (sSplitPlaneStrategy == LEAST_SPLITS))
+		{
+			sumLeastSplits += sLeastSplitsTable[classification];
+			Debug << "Adding " <<  sLeastSplitsTable[classification] << " for poly " << *it << "!";
+		}
+	}
+
+	Debug << "\n" << candidatePlane << " evaluation: " << abs(sumBalanced) + abs(sumLeastSplits) << endl;
 
 	// return linear combination of both sums
-	return abs(sum) + abs(sum2);
+	return abs(sumBalanced) + abs(sumLeastSplits);
 }
 
@@ -738,4 +773,8 @@
 	environment->GetIntValue("BspTree.Termination.maxPolygons", sTermMaxPolygons);
 	environment->GetIntValue("BspTree.maxCandidates", sMaxCandidates);
+
+	Debug << "BSP max depth: " << sTermMaxDepth << endl;
+	Debug << "BSP max polys: " << sTermMaxPolygons << endl;
+	Debug << "BSP max candidates: " << sMaxCandidates << endl;
 
 	//-- extract strategy to choose the next split plane
@@ -758,6 +797,8 @@
     }
 
+	Debug << "Split plane heuristic: " << splitPlaneStrategyStr << endl;
+
 	//-- parse BSP tree construction method
-	char constructionMethodStr[64];
+	char constructionMethodStr[60];
 	
 	environment->GetStringValue("BspTree.constructionMethod", constructionMethodStr);
@@ -777,4 +818,5 @@
     }
 
+	Debug << "Construction method: " << constructionMethodStr << endl;
 }
 
@@ -879,10 +921,17 @@
 	}
 
-	// store maximal depth
+	// store maximal and minimal depth
 	if (data.mDepth > mStat.maxDepth)
 		mStat.maxDepth = data.mDepth;
+	if (data.mDepth < mStat.minDepth)
+		mStat.minDepth = data.mDepth;
+
+	mStat.accumDepth += data.mDepth;
+
+	if (leaf->mViewCell)
+		++ mStat.viewCellLeaves;
 
 #ifdef _DEBUG
-	Debug << "BSP Traversal data. Depth: " << data.mDepth << " (max: " << mTermMaxDepth<< "), #polygons: " << 
+	Debug << "BSP Traversal data. Depth: " << data.mDepth << " (max: " << mTermMaxDepth << "), #polygons: " << 
 	  data.mPolygons->size() << " (max: " << mTermMaxPolygons << ")" << endl;
 #endif
Index: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.h	(revision 262)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.h	(revision 265)
@@ -18,4 +18,5 @@
 {
 public:
+	ViewCell();
 	/** Default constructor taking a mesh which represents the shape of
 		the viewcell.
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 264)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 265)
@@ -95,12 +95,8 @@
 	{
 	case BspTree::VIEW_CELLS:
-		Debug << "Construction method: view cells\n";
-		
 		mBspTree->Construct(mViewCells);
 		break;
 	case BspTree::SCENE_GEOMETRY:
-		Debug << "Construction method: geometry\n";
-
-        CLEAR_CONTAINER(mViewCells); // we generate new view cells
+		CLEAR_CONTAINER(mViewCells); // we generate new view cells
 
 		mSceneGraph->CollectObjects(&objects);
@@ -108,6 +104,4 @@
 		break;
 	case BspTree::RAYS:
-		Debug << "Construction method: rays\n";
-
 		CLEAR_CONTAINER(mViewCells); // we generate new view cells	
 		mBspTree->Construct(rays, &mViewCells);
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Plane3.h
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Plane3.h	(revision 245)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Plane3.h	(revision 265)
@@ -47,10 +47,10 @@
     
     if (signum(dv) == 0)
-      {
-	if (coplanar) 
-	  (*coplanar) = true;	
+	{
+		if (coplanar) 
+			(*coplanar) = true;	
 	
-	return a;
-      }
+		return a;
+	}
     
     float u = - Distance(a) / dv; // TODO: could be done more efficiently
Index: trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp	(revision 264)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/main.cpp	(revision 265)
@@ -44,13 +44,15 @@
 	  {
           p->LoadViewCells(vcFilename);
-		  Exporter *exporter = Exporter::GetExporter("viewcells.x3d");
+		  
+		  /*Exporter *exporter = Exporter::GetExporter("viewcells.x3d");
 		  if (exporter) 
-		  {
-			  exporter->ExportViewCells(&p->mViewCells);
-			  delete exporter;
-		  }
+		  {	  exporter->ExportViewCells(&p->mViewCells);
+			  delete exporter;  
+		  }*/
 	  }
 	  else
 		  p->GenerateViewCells();
+
+	  Debug << "Number of view cells: " << p->mViewCells.size() << endl;
   }
 
Index: trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp	(revision 264)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/X3dExporter.cpp	(revision 265)
@@ -395,4 +395,6 @@
 		SetFilled();
 
+	ViewCellContainer mFoundViewCells;
+
 	while (!tStack.empty()) 
 	{
@@ -422,9 +424,18 @@
 			ViewCell *viewCell = dynamic_cast<BspLeaf *>(node)->GetViewCell();
 			
-			if (viewCell) // export view cell geometry
-				ExportViewCell(viewCell);	
+			if (viewCell)
+				mFoundViewCells.push_back(viewCell);
 		}
 	}
 	
+	if (!tree.StorePolys())
+	{
+		//move consecutive duplicates past the end; store new end
+		ViewCellContainer::iterator new_end = unique(mFoundViewCells.begin(), mFoundViewCells.end());
+		// delete all elements past new_end 
+		mFoundViewCells.erase(new_end, mFoundViewCells.end());
+		ExportViewCells(&mFoundViewCells);
+	}
+
 	return true;
 }
Index: trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.cpp
===================================================================
--- trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.cpp	(revision 264)
+++ trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.cpp	(revision 265)
@@ -109,17 +109,16 @@
 	bool onBackSide = false;
 
+	int count = 0;
 	// find possible line-plane intersections
 	for (it = mVertices.begin(); it != mVertices.end(); ++ it)
 	{
 		int side = plane.Side(*it, SIDE_TOLERANCE);
+		//Debug << "side: " << side << " " << plane.Distance(*it) << endl;
+
+		if (side > 0)
+			onFrontSide = true;
+		else if (side < 0)
+			onBackSide = true;
 		
-		if (side > 0)
-		{
-			onFrontSide = true;
-		}
-		else if (side < 0)
-		{
-			onBackSide = true;
-		}
 		//TODO: check if split goes through vertex
 		if (onFrontSide && onBackSide) // split 
@@ -127,4 +126,7 @@
 			return SPLIT;
 		}
+		// 3 vertices enough to decide coincident
+		else if (((++ count) >= 3) && !onFrontSide && !onBackSide) 
+			return COINCIDENT;
 	}
 
