Index: /GTP/trunk/App/Demos/Vis/CHC_revisited/RenderTraverser.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/CHC_revisited/RenderTraverser.cpp	(revision 2769)
+++ /GTP/trunk/App/Demos/Vis/CHC_revisited/RenderTraverser.cpp	(revision 2770)
@@ -19,7 +19,8 @@
 	mNumRenderedGeometry = 0;
 	mNumRenderedTriangles = 0;
-
+	mNumPreviouslyVisibleNodeQueries = 0;
 	mNumIssuedQueries = 0;
 	mRenderTime = 0;
+	mNumStateChanges = 0;
 }
 
@@ -35,7 +36,8 @@
 mBvh(NULL), 
 mIsQueryMode(false),
-mUseOptimization(true),
+mUseOptimization(false),
 mFrameId(-1),
-mUseRenderQueue(false)
+mUseRenderQueue(false),
+mAssumedVisibleFrames(10)
 {
 }
@@ -61,16 +63,5 @@
 	if (node->IsVirtualLeaf())
 	{
-		if (mUseRenderQueue)
-		{
-			int geometrySize;
-			SceneEntity **geom = mBvh->GetGeometry(node, geometrySize);
-			mRenderQueue.Enqueue(geom, geometrySize);
-			mStats.mNumRenderedGeometry += geometrySize;
-		}
-		else
-		{
-			// RenderBox(node->GetBox());
-			mStats.mNumRenderedGeometry += mBvh->Render(node, mRenderState);
-		}		
+		RenderNode(node);
 	}
 	else 
@@ -85,4 +76,23 @@
 
 
+void RenderTraverser::RenderNode(BvhNode *node)
+{
+	if (mUseRenderQueue)
+	{
+		int geometrySize;
+		SceneEntity **geom = mBvh->GetGeometry(node, geometrySize);
+		mRenderQueue.Enqueue(geom, geometrySize);
+		mStats.mNumRenderedGeometry += geometrySize;
+	}
+	else
+	{
+		if (mRenderState->SetState(RenderState::RENDER))
+			++ mStats.mNumStateChanges;
+
+		mStats.mNumRenderedGeometry += mBvh->Render(node, mRenderState);
+	}		
+}
+
+
 void RenderTraverser::SetHierarchy(Bvh *bvh)
 {
@@ -101,4 +111,10 @@
 {
 	++ mStats.mNumIssuedQueries;
+
+	if (mUseRenderQueue && (mRenderState->GetMode() == RenderState::RENDER))
+	{
+		mRenderQueue.Render();
+		mRenderQueue.Clear();
+	}
 
 	OcclusionQuery *query = mQueryHandler.RequestQuery();
@@ -107,18 +123,25 @@
 
 	query->BeginQuery();
-	
-	// if leaf and was visible => will be rendered anyway, thus we
+
+	if (wasVisible)
+	{
+		node->SetAssumedVisibleFrameId(mFrameId + 10);
+		++ mStats.mNumPreviouslyVisibleNodeQueries;
+	}
+
+	// if this node is a previous visible leaf => will be rendered anyway, thus we
 	// can also test with the real geometry 
-	/*if(node->IsLeaf() && wasVisible && mUseOptimization)
-	{
-		mNumRenderedGeometry += node->Render();
+	if (wasVisible && mUseOptimization)
+	{
+		mStats.mNumRenderedGeometry += mBvh->Render(node, mRenderState);
 	}
 	else
-	{*/
-
-	// change to query mode
-	mRenderState->SetState(RenderState::QUERY);
-	mBvh->RenderBoundingBox(node);
-	mRenderState->SetState(RenderState::RENDER);
+	{
+		// change to query mode and render box
+		if (mRenderState->SetState(RenderState::QUERY))
+			++ mStats.mNumStateChanges;
+
+		mBvh->RenderBoundingBox(node);
+	}
 
 	query->EndQuery();
@@ -172,9 +195,19 @@
 	Traverse();
 
+	// render the rest of the objects
+	if (mUseRenderQueue)
+	{
+		if (mRenderState->SetState(RenderState::RENDER))
+			++ mStats.mNumStateChanges;
+
+		mRenderQueue.Render();
+		mRenderQueue.Clear();
+	}
+
+	mRenderState->Reset();
+
 	glDisableClientState(GL_VERTEX_ARRAY);
 	glDisableClientState(GL_NORMAL_ARRAY);
 
-	mRenderState->Reset();
-
 	t2 = GetTime();
 	mStats.mRenderTime = TimeDiff(t1, t2);
Index: /GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.h
===================================================================
--- /GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.h	(revision 2767)
+++ /GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.h	(revision 2770)
@@ -42,6 +42,6 @@
 		/// if the node is visible
 		bool mIsVisible;
-		/// #frames this node is assumed to stay visible
-		int mAssumedVisibleFrames;
+		/// frame id until this node is assumed to stay visible
+		int mAssumedVisibleFrameId;
 		/// the frame when this node was last touched during traversal
 		int mLastVisitedFrame;
@@ -96,16 +96,10 @@
 	*/
 	inline void SetVisible(bool visible);
-	/** The assumed visible time span of this node.
-	*/
-	inline void SetAssumedVisibleFrames(int t);
+	/** The frame id until this node is assumed visible
+	*/
+	inline void SetAssumedVisibleFrameId(int t);
 	/** See set.
 	*/
-	inline int GetAssumedVisibleFrames() const;
-	/** The time span this node remains visible.
-	*/
-	inline void SetRemainingVisibleFrames(const int t);
-	/** Decrease the time this node is considered visible.
-	*/
-	inline void DecAssumedVisibleFrames();
+	inline int GetAssumedVisibleFrameId() const;
 	/** Increases the #times this node was
 		successfully tested invisible.
@@ -318,18 +312,13 @@
 
 
-void BvhNode::SetAssumedVisibleFrames(const int t) 
-{ 
-	mVisibility.mAssumedVisibleFrames = t; 
-}
-
-
-int BvhNode::GetAssumedVisibleFrames() const 
-{ 
-	return mVisibility.mAssumedVisibleFrames;
-}
-
-void BvhNode::DecAssumedVisibleFrames() 
-{
-	-- mVisibility.mAssumedVisibleFrames; 
+void BvhNode::SetAssumedVisibleFrameId(int t) 
+{ 
+	mVisibility.mAssumedVisibleFrameId = t; 
+}
+
+
+int BvhNode::GetAssumedVisibleFrameId() const 
+{ 
+	return mVisibility.mAssumedVisibleFrameId;
 }
 
Index: /GTP/trunk/App/Demos/Vis/CHC_revisited/CHCPlusPlusTraverser.h
===================================================================
--- /GTP/trunk/App/Demos/Vis/CHC_revisited/CHCPlusPlusTraverser.h	(revision 2767)
+++ /GTP/trunk/App/Demos/Vis/CHC_revisited/CHCPlusPlusTraverser.h	(revision 2770)
@@ -21,4 +21,13 @@
 	*/
 	virtual void Traverse();
+
+	void QueryPreviouslyInvisibleNodes(BvhNode *node);
+
+	void IssueMultiQueries();
+
+	//////////////
+
+	BvhNodeQueue mIQueue;
+	BvhNodeQueue mVQueue;
 };
 
Index: /GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.cpp	(revision 2764)
+++ /GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.cpp	(revision 2770)
@@ -104,12 +104,8 @@
 {
 	mIsVisible = false;
-	
-	mAssumedVisibleFrames = 0;
-
+	mAssumedVisibleFrameId = 0;
 	mLastVisitedFrame = -1;
-	
 	mTimesInvisible = 0;
 	mIsFrustumCulled = false;
-
 	mIsNew = true;
 }
Index: /GTP/trunk/App/Demos/Vis/CHC_revisited/CHCTraverser.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/CHC_revisited/CHCTraverser.cpp	(revision 2767)
+++ /GTP/trunk/App/Demos/Vis/CHC_revisited/CHCTraverser.cpp	(revision 2770)
@@ -28,4 +28,5 @@
 				BvhNode *node = query->GetFrontNode();
 
+				node->SetVisible(true);
 				mBvh->MakeParentsVisible(node);
 				TraverseNode(node);
@@ -62,6 +63,5 @@
 					
 					// identify nodes that we cannot skip queries for
-					const bool leafOrWasInvisible = 
-						(node->GetLastVisitedFrame() != mFrameId) && (!wasVisible || node->IsVirtualLeaf());
+					const bool leafOrWasInvisible = (!wasVisible || node->IsVirtualLeaf());
 
 					// reset node's visibility classification 
Index: /GTP/trunk/App/Demos/Vis/CHC_revisited/chcdemo.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/CHC_revisited/chcdemo.cpp	(revision 2769)
+++ /GTP/trunk/App/Demos/Vis/CHC_revisited/chcdemo.cpp	(revision 2770)
@@ -57,4 +57,14 @@
 float visZoomFactor = 1.5f;
 
+long accumulatedTime = 1000;
+float fps = 1e3f;
+
+int renderedObjects = 0;
+int issuedQueries = 0;
+int traversedNodes = 0;
+int frustumCulledNodes = 0;
+int queryCulledNodes = 0;
+int stateChanges = 0;
+
 bool showHelp = false;
 bool showStatistics = true;
@@ -69,5 +79,5 @@
 int xEyeBegin, yEyeBegin, yMotionBegin, verticalMotionBegin, horizontalMotionBegin = 0;
 
-bool useOptimization = true;
+bool useOptimization = false;
 
 
@@ -296,4 +306,7 @@
 	traverser->SetHierarchy(bvh);
 	traverser->SetRenderState(&state);
+	traverser->SetUseOptimization(useOptimization);
+	traverser->SetUseRenderQueue(useRenderQueue);
+	traverser->SetVisibilityThreshold(threshold);
 }
 
@@ -843,18 +856,24 @@
 
 
-	sprintf_s(msg2, "traversed: %4d, frustum culled: %4d, query culled: %4d (of %d nodes)",
-			  traverser->GetStats().mNumTraversedNodes, traverser->GetStats().mNumFrustumCulledNodes,
-			  traverser->GetStats().mNumQueryCulledNodes, bvh->GetNumVirtualNodes());
-
 	char *optstr[2] = {"", ", using optimization"};
 	
-	float fps = 1e3f;
 	static long renderTime = traverser->GetStats().mRenderTime;
-
 	const float expFactor = 0.5f;
-
 	renderTime = traverser->GetStats().mRenderTime * expFactor + (1.0f - expFactor) * renderTime;
 
-	if (renderTime) fps = 1e3f / (float)renderTime;
+	accumulatedTime += renderTime;
+
+	if (accumulatedTime > 200) // update every fraction of a second
+	{	
+		accumulatedTime = 0;
+		if (renderTime) fps = 1e3f / (float)renderTime;
+
+		renderedObjects = traverser->GetStats().mNumRenderedGeometry;
+		traversedNodes = traverser->GetStats().mNumTraversedNodes;
+		frustumCulledNodes = traverser->GetStats().mNumFrustumCulledNodes;
+		queryCulledNodes = traverser->GetStats().mNumQueryCulledNodes;
+		issuedQueries = traverser->GetStats().mNumIssuedQueries;
+		stateChanges = traverser->GetStats().mNumStateChanges;
+	}
 
 	sprintf_s(msg2, "threshold: %4d%s", 
@@ -869,10 +888,13 @@
 
 	sprintf_s(msg3, "rendered objects: %6d (of %6d), rendered triangles: %s (of %s)", 
-			  traverser->GetStats().mNumRenderedGeometry, sceneEntities.size(), str.c_str(), str2.c_str()); 
-
-	sprintf_s(msg4, "issued queries: %5d", traverser->GetStats().mNumIssuedQueries);
+			  renderedObjects, sceneEntities.size(), str.c_str(), str2.c_str()); 
+
+	sprintf_s(msg4, "nodes: %5d, traversed: %5d, frustum culled: %5d, query culled: %5d, issued queries: %5d, state changes: %5d",
+			  bvh->GetNumVirtualNodes(), traversedNodes, frustumCulledNodes,
+			  queryCulledNodes, issuedQueries, stateChanges);
 
 	sprintf_s(msg5, "fps: %6.1f", fps);
 
+	cout << "previously visible node queries: " << traverser->GetStats().mNumPreviouslyVisibleNodeQueries << endl;
 
 	begin2D();
Index: /GTP/trunk/App/Demos/Vis/CHC_revisited/CHCPlusPlusTraverser.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/CHC_revisited/CHCPlusPlusTraverser.cpp	(revision 2767)
+++ /GTP/trunk/App/Demos/Vis/CHC_revisited/CHCPlusPlusTraverser.cpp	(revision 2770)
@@ -1,3 +1,5 @@
 #include "CHCPlusPlusTraverser.h"
+#include "RenderState.h"
+
 
 namespace CHCDemo
@@ -17,20 +19,32 @@
 			   (mQueryQueue.front()->ResultAvailable() || mDistanceQueue.empty()))
 		{
-			OcclusionQuery *query = mQueryQueue.front();
-			mQueryQueue.pop();
-			
-			// wait until result available
-			int visiblePixels = query->GetQueryResult();
+			if (mQueryQueue.front()->ResultAvailable())
+			{
+				OcclusionQuery *query = mQueryQueue.front();
+				mQueryQueue.pop();
 
-			if (visiblePixels > mVisibilityThreshold)
+				// wait until result available
+				int visiblePixels = query->GetQueryResult();
+
+				if (visiblePixels > mVisibilityThreshold)
+				{
+					BvhNode *node = query->GetFrontNode();
+
+					node->SetVisible(true);
+					mBvh->MakeParentsVisible(node);
+					TraverseNode(node);
+				}
+				else
+				{
+					++ mStats.mNumQueryCulledNodes;
+				}
+			}
+			else if (!mVQueue.empty())
 			{
-				BvhNode *node = query->GetFrontNode();
+				BvhNode *node = mVQueue.front();
+				mVQueue.pop();
 
-				mBvh->MakeParentsVisible(node);
-				TraverseNode(node);
-			}
-			else
-			{
-				++ mStats.mNumQueryCulledNodes;
+				OcclusionQuery *query = IssueOcclusionQuery(node, true);
+				mQueryQueue.push(query);
 			}
 		}	
@@ -61,9 +75,6 @@
 					
 					// identify nodes that we cannot skip queries for
-					const bool leafOrWasInvisible = 
-						(node->GetLastVisitedFrame() != mFrameId) && (!wasVisible || node->IsVirtualLeaf());
-
-					// reset node's visibility classification 
-					node->SetVisible(false);
+					const bool testFeasible = (!wasVisible || (node->IsVirtualLeaf() /*&& (node->GetAssumedVisibleFrameId() <= mFrameId)*/));
+						 
 
 					// update node's visited flag
@@ -71,11 +82,20 @@
 					
 					// skip testing previously visible interior nodes
-					if (leafOrWasInvisible)
+					if (testFeasible)
 					{
-						OcclusionQuery *query = IssueOcclusionQuery(node, wasVisible);
-						mQueryQueue.push(query);
+						// reset node's visibility classification 
+						node->SetVisible(false);
+
+						if (!wasVisible)
+						{
+							QueryPreviouslyInvisibleNodes(node);
+						}
+						else
+						{
+							mVQueue.push(node);
+						}
 					}
 					
-					// always traverse a node if it was visible
+					// always traverse a node if it was previously visible
 					if (wasVisible)
 						TraverseNode(node);
@@ -88,6 +108,80 @@
 			}
 		}
+
+		if (mDistanceQueue.empty())
+		{
+			// issue remaining multiqueries
+			IssueMultiQueries();
+		}
+	}
+
+	//////////////
+	//-- issue remaining previously visible node queries
+
+	while (!mVQueue.empty())
+	{
+		BvhNode *node = mVQueue.front();
+		mVQueue.pop();
+
+		OcclusionQuery *query = IssueOcclusionQuery(node, true);
+		mQueryQueue.push(query);
+	}
+
+	while (!mQueryQueue.empty())
+	{
+		OcclusionQuery *query = mQueryQueue.front();
+		mQueryQueue.pop();
+
+		// wait until result available
+		int visiblePixels = query->GetQueryResult();
+
+		if (visiblePixels > mVisibilityThreshold)
+		{
+			BvhNode *node = query->GetFrontNode();
+
+			node->SetVisible(true);
+			mBvh->MakeParentsVisible(node);
+		}
+		else
+		{
+			++ mStats.mNumQueryCulledNodes;
+		}
 	}
 }
 
+
+
+void CHCPlusPlusTraverser::QueryPreviouslyInvisibleNodes(BvhNode *node)
+{
+	mIQueue.push(node);
+
+	if (mIQueue.size() > 50)
+	{
+		IssueMultiQueries();
+	}
 }
+
+
+void CHCPlusPlusTraverser::IssueMultiQueries()
+{
+	if (0 && mUseRenderQueue)
+	{
+		if (mRenderState->SetState(RenderState::RENDER))
+			++ mStats.mNumStateChanges;
+	
+		mRenderQueue.Render();
+		mRenderQueue.Clear();
+	}
+
+	while (!mIQueue.empty())
+	{
+		BvhNode *node = mIQueue.front();
+		mIQueue.pop();
+
+		OcclusionQuery *query = IssueOcclusionQuery(node, false);
+		mQueryQueue.push(query);
+	}
+}
+
+
+}
Index: /GTP/trunk/App/Demos/Vis/CHC_revisited/FrustumCullingTraverser.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/CHC_revisited/FrustumCullingTraverser.cpp	(revision 2767)
+++ /GTP/trunk/App/Demos/Vis/CHC_revisited/FrustumCullingTraverser.cpp	(revision 2770)
@@ -36,7 +36,4 @@
 		}
 	}
-
-	mRenderQueue.Render();
-	mRenderQueue.Clear();
 }
 
Index: /GTP/trunk/App/Demos/Vis/CHC_revisited/RenderTraverser.h
===================================================================
--- /GTP/trunk/App/Demos/Vis/CHC_revisited/RenderTraverser.h	(revision 2769)
+++ /GTP/trunk/App/Demos/Vis/CHC_revisited/RenderTraverser.h	(revision 2770)
@@ -33,4 +33,6 @@
 	int mNumRenderedTriangles;
 	int mNumIssuedQueries;
+	int mNumStateChanges;
+	int mNumPreviouslyVisibleNodeQueries;
 
 	long mRenderTime;
@@ -99,8 +101,10 @@
 	*/
 	inline bool IntersectsNearPlane(BvhNode *node) const; 
-	/** Enqueues a bvh node.
+	/** Enqueues a bvh node for distance traversal
 	*/
 	void EnqueueNode(BvhNode *node);
-
+	/** Renders the bvh node.
+	*/
+	void RenderNode(BvhNode *node);
 
 
@@ -134,4 +138,6 @@
 
 	bool mUseRenderQueue;
+
+	int mAssumedVisibleFrames;
 };
 
Index: /GTP/trunk/App/Demos/Vis/CHC_revisited/common.h
===================================================================
--- /GTP/trunk/App/Demos/Vis/CHC_revisited/common.h	(revision 2763)
+++ /GTP/trunk/App/Demos/Vis/CHC_revisited/common.h	(revision 2770)
@@ -472,4 +472,5 @@
 
 typedef std::queue<OcclusionQuery *> QueryQueue;
+typedef std::queue<BvhNode *> BvhNodeQueue;
 
 static std::ofstream Debug("debug.log");
