Index: GTP/trunk/App/Demos/Vis/CHC_revisited/RenderTraverser.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/RenderTraverser.cpp	(revision 2760)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/RenderTraverser.cpp	(revision 2761)
@@ -66,5 +66,5 @@
 void RenderTraverser::TraverseNode(BvhNode *node)
 {
-	if (node->IsLeaf())
+	if (node->IsVirtualLeaf()||node->IsLeaf())
 	{
 		//mNumRenderedGeometry +=
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.cpp	(revision 2760)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.cpp	(revision 2761)
@@ -81,5 +81,12 @@
 mIndicesPtr(-1),
 mIndices(NULL),
-mId(0)
+mId(0),
+mIsMaxDepthForVirtualLeaf(false),
+mIsVirtualLeaf(false)
+{
+}
+
+
+BvhNode::~BvhNode() 
 {
 }
@@ -91,9 +98,4 @@
 
 	mLastRenderedFrame = -999;
-}
-
-
-BvhNode::~BvhNode() 
-{
 }
 
@@ -838,3 +840,113 @@
 
 
-}
+void Bvh::CollectVirtualLeaves(BvhNode *node, BvhNodeContainer &leaves)
+{
+	stack<BvhNode *> tStack;
+	tStack.push(node);
+
+	while (!tStack.empty())
+	{
+		BvhNode *node = tStack.top();
+		tStack.pop();
+
+		if (node->mIsVirtualLeaf)
+		{
+			leaves.push_back(node);
+		}
+		else if (!node->IsLeaf())
+		{
+			BvhInterior *interior = static_cast<BvhInterior *>(node);
+
+			tStack.push(interior->mFront);
+			tStack.push(interior->mBack);
+		}
+	}
+}
+
+
+void Bvh::SetVirtualLeaves(int numTriangles) 
+{
+	// first invalidate old leaves
+	BvhNodeContainer leaves;
+
+	CollectVirtualLeaves(mRoot, leaves);
+
+	BvhNodeContainer::const_iterator bit, bit_end = leaves.end();
+
+	for (bit = leaves.begin(); bit != bit_end; ++ bit)
+	{
+		(*bit)->mIsVirtualLeaf = false;
+	}
+
+	// assign new virtual leaves based on specified number of triangles per leaf
+	std::stack<BvhNode *> nodeStack;
+	nodeStack.push(mRoot);
+
+	while (!nodeStack.empty()) 
+	{
+		BvhNode *node = nodeStack.top();
+		nodeStack.pop();
+
+		if (node->IsLeaf()) 
+		{
+			BvhLeaf *leaf = static_cast<BvhLeaf *>(node);
+			leaf->mIsVirtualLeaf = true;
+		} 
+		else 
+		{
+			BvhInterior *interior = static_cast<BvhInterior *>(node);
+
+			BvhNode *f = interior->mFront;
+			BvhNode *b = interior->mBack;
+
+			if (node->mIsMaxDepthForVirtualLeaf || (CountTriangles(node) <= numTriangles))
+			{
+				 node->mIsVirtualLeaf = true;
+			}
+			else
+			{
+				nodeStack.push(interior->mBack);
+				nodeStack.push(interior->mFront);
+			}
+		}
+	}
+}
+
+
+void Bvh::PostProcess() 
+{
+	std::stack<BvhNode *> nodeStack;
+	nodeStack.push(mRoot);
+
+	while (!nodeStack.empty()) 
+	{
+		BvhNode *node = nodeStack.top();
+		nodeStack.pop();
+
+		if (node->IsLeaf()) 
+		{
+			node->mIsMaxDepthForVirtualLeaf = true;
+		} 
+		else 
+		{
+			BvhInterior *interior = static_cast<BvhInterior *>(node);
+
+			BvhNode *f = interior->mFront;
+			BvhNode *b = interior->mBack;
+
+			// point reached where we cannot subdivide further on object level
+			if ((f->mFirst == b->mFirst) && (f->mLast == b->mLast))
+			{
+				node->mIsMaxDepthForVirtualLeaf = true;
+			}
+			else
+			{
+				nodeStack.push(f);
+				nodeStack.push(b);
+			}
+		}
+	}
+}
+
+
+}
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/BvhLoader.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/BvhLoader.cpp	(revision 2760)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/BvhLoader.cpp	(revision 2761)
@@ -62,6 +62,5 @@
 					 const SceneEntityContainer &entities)
 {
-	// export binary version of mesh
-	queue<BvhNode *> tStack;
+	queue<BvhNode *> tQueue;
 	ifstream stream(filename.c_str(), ifstream::binary);
 
@@ -73,11 +72,11 @@
 	bvh->mRoot = LoadNextNode(stream, NULL);
 
-	tStack.push(bvh->mRoot);
+	tQueue.push(bvh->mRoot);
 	bvh->mNumNodes = 1;
 
-	while(!tStack.empty())
+	while(!tQueue.empty())
 	{
-		BvhNode *node = tStack.front();
-		tStack.pop();
+		BvhNode *node = tQueue.front();
+		tQueue.pop();
 
 		if (!node->IsLeaf())
@@ -87,7 +86,7 @@
 			BvhInterior *interior = static_cast<BvhInterior *>(node);
 
-            BvhNode *front = LoadNextNode(stream, interior);
+			BvhNode *front = LoadNextNode(stream, interior);
 			BvhNode *back = LoadNextNode(stream, interior);
-	
+
 			interior->mFront = front;
 			interior->mBack = back;
@@ -96,6 +95,6 @@
 			back->mDepth = interior->mDepth + 1;
 
-			tStack.push(front);			
-			tStack.push(back);
+			tQueue.push(front);			
+			tQueue.push(back);
 		}
 	}
@@ -104,5 +103,9 @@
 
 	///////////
-	//-- post process
+	//-- post process nodes
+
+	bvh->PostProcess();
+	// set virtual leaves for 500 triangles
+	bvh->SetVirtualLeaves(500);
 
 	bvh->UpdateNumLeaves(bvh->mRoot);
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/FrustumCullingTraverser.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/FrustumCullingTraverser.cpp	(revision 2760)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/FrustumCullingTraverser.cpp	(revision 2761)
@@ -16,4 +16,5 @@
 	mDistanceQueue.push(mBvh->GetRoot());
 
+	int traversed = 0;
 	while (!mDistanceQueue.empty())
 	{
@@ -27,5 +28,5 @@
 		//bool intersects;
 	
-		if (1)//mBvh->InsideViewFrustum(node, intersects))
+		if (mBvh->IsWithinViewFrustum(node))
 		{
 			// update node's visited flag => needed for rendering
@@ -33,5 +34,5 @@
 			//node->SetLastVisited(mFrameID);
 			//node->SetVisible(true);
-
+			++ traversed;
 			TraverseNode(node);
 		}
@@ -41,4 +42,6 @@
 		}
 	}
+
+	std::cout << "traversed: " << traversed << std::endl;
 }
 
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.h
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.h	(revision 2760)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.h	(revision 2761)
@@ -79,5 +79,7 @@
 	virtual void ResetVisibility();
 
-	virtual bool IsLeaf() = 0; //{ return BVH_NODE; }
+	virtual bool IsLeaf() const = 0;
+
+	bool IsVirtualLeaf() const { return mIsVirtualLeaf; }
 
 
@@ -211,4 +213,13 @@
 	/// the bounding box
 	AxisAlignedBox3 mBox;
+	/// if this node is a virtual leaf
+	bool mIsVirtualLeaf;
+	/** This marks the maximal depth where a virtual leaf can be defined.
+	    From this point on it makes no sense to traverse down further, as all
+		nodes below contain the same geometry, so no further refinement of visibility 
+		can be archieved. All nodes below this point can merely used to define the 
+		tighter bounds.
+	*/
+	bool mIsMaxDepthForVirtualLeaf;
 };
 
@@ -335,11 +346,11 @@
 	BvhInterior(BvhNode *parent): mBack(NULL), mFront(NULL), BvhNode(parent)
 	{}
-	virtual bool IsLeaf() {return false;}
+	virtual bool IsLeaf() const { return false; }
 	/** Back child.
 	*/
-	inline BvhNode *GetBack() { return mBack;}
+	inline BvhNode *GetBack() { return mBack; }
 	/** Front child.
 	*/
-	inline BvhNode *GetFront() { return mFront;}
+	inline BvhNode *GetFront() { return mFront; }
 	/** recursivly delete tree.
 	*/
@@ -375,5 +386,5 @@
 	~BvhLeaf();
 
-	virtual bool IsLeaf() { return true; }
+	virtual bool IsLeaf() const { return true; }
 };
 
@@ -450,4 +461,7 @@
 	void CollectNodes(BvhNode *node, BvhNodeContainer &nodes);
 	void CollectLeaves(BvhNode *node, BvhLeafContainer &leaves);
+	/** Collect only the virtual leaves.
+	*/
+	void CollectVirtualLeaves(BvhNode *node, BvhNodeContainer &leaves);
 
 
@@ -511,5 +525,7 @@
 	*/
 	void ComputeIds();
-
+	/** Assign virtual leaves based on specified number of triangles per leaf.
+	*/
+	void SetVirtualLeaves(int numTriangles);
 
 	////////
@@ -576,5 +592,5 @@
 	/** Does some postprocessing on the nodes.
 	*/
-	//void PostProcess();
+	void PostProcess();
 	/** Helper method that updates the number of leaves in the subtree under
 		this node.
