Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/src/FrustumCullingManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/src/FrustumCullingManager.cpp	(revision 2292)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/src/FrustumCullingManager.cpp	(revision 2555)
@@ -31,7 +31,8 @@
 		{
 			mHierarchyInterface->SetNodeVisible(node, true);
-			mHierarchyInterface->TraverseNode(node);
+			mHierarchyInterface->TraverseNode2(node);
 		}
 	}
+	mHierarchyInterface->RenderQueue();
 }
 } // namespace GtpVisibility
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/src/CoherentHierarchicalCullingManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/src/CoherentHierarchicalCullingManager.cpp	(revision 2455)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/src/CoherentHierarchicalCullingManager.cpp	(revision 2555)
@@ -9,5 +9,4 @@
 
 
-static int batchSize = 5;
 
 //-----------------------------------------------------------------------
@@ -36,5 +35,4 @@
 {
 	if (0) CullingLogManager::GetSingleton()->LogMessage("chc");
-	QueryQueue queryQueue;
 	unsigned int visiblePixels = 0;
 	
@@ -42,16 +40,16 @@
 	//-- PART 1: process finished occlusion queries
 
-	while (!mHierarchyInterface->GetQueue()->empty() || !queryQueue.empty())
+	while (!mHierarchyInterface->GetQueue()->empty() || !mQueryQueue.empty())
 	{
 		//////////
 		//-- only wait for result if there are no nodes to process
 
-		while (!queryQueue.empty() && 
-			   (NodeInvalid(queryQueue.front().first) ||
-			    queryQueue.front().second->GetQueryResult(
+		while (!mQueryQueue.empty() && 
+			   (NodeInvalid(mQueryQueue.front().first) ||
+			    mQueryQueue.front().second->GetQueryResult(
 				             visiblePixels, mHierarchyInterface->GetQueue()->empty())))
 		{
-			HierarchyNode *node = queryQueue.front().first;
-			queryQueue.pop();
+			HierarchyNode *node = mQueryQueue.front().first;
+			mQueryQueue.pop();
 
 			// "invalid nodes" happen for hierarchies that have geometry
@@ -145,7 +143,8 @@
 					++ mNumQueriesIssued;
 					
-					const bool testGeometry = wasVisible && mHierarchyInterface->IsLeaf(node) && mTestGeometryForVisibleLeaves;
-
-					queryQueue.push(QueryPair(node, mHierarchyInterface->
+					const bool testGeometry = 
+						wasVisible && mHierarchyInterface->IsLeaf(node) && mTestGeometryForVisibleLeaves;
+
+					mQueryQueue.push(QueryPair(node, mHierarchyInterface->
 						IssueNodeOcclusionQuery(node, testGeometry)));
 				}
@@ -192,9 +191,9 @@
 {
 	// parent was tested invisible in this frame
-	HierarchyNode *parent = mHierarchyInterface->GetParent(node);
-    return 
-		parent && 
-		(mHierarchyInterface->LastVisited(node) == mHierarchyInterface->GetFrameId()) && 
-		!mHierarchyInterface->IsNodeVisible(parent);
+    return ( 
+		    mHierarchyInterface->GetParent(node) && 
+		    (mHierarchyInterface->LastVisited(node) == mHierarchyInterface->GetFrameId()) && 
+		    !mHierarchyInterface->IsNodeVisible(mHierarchyInterface->GetParent(node))
+           );
 }
 //-----------------------------------------------------------------------
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/src/VisibilityManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/src/VisibilityManager.cpp	(revision 2455)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/src/VisibilityManager.cpp	(revision 2555)
@@ -5,4 +5,5 @@
 #include "DummyPreprocessingManager.h"
 #include "RandomUpdateCullingManager.h"
+#include "CoherentHierarchicalCullingPlusPlusManager.h"
 #include "CullingLogManager.h"
 
@@ -19,13 +20,5 @@
 mAssumedVisibilityForChc(0)
 {
-#if 1
 	SetCullingManager(VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING);
-#endif
-#if 0	
-	SetCullingManager(VisibilityEnvironment::STOP_AND_WAIT_CULLING);
-#endif
-#if 0
-	SetCullingManager(VisibilityEnvironment::FRUSTUM_CULLING);
-#endif
 }
 //-----------------------------------------------------------------------
@@ -61,9 +54,9 @@
 			mCullingManager = new FrustumCullingManager();
 			break;
-		case VisibilityEnvironment::RANDOM_UPDATE_CULLING:
+		case VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING_PLUSPLUS:
 			{
-				RandomUpdateCullingManager *rum = new RandomUpdateCullingManager(mRandomCandidatesForRuc);
-				rum->SetTestGeometryForVisibleLeaves(mTestGeometryForVisibleLeaves);
-				mCullingManager = rum;
+				CoherentHierarchicalCullingPlusPlusManager *chcm = 
+					new CoherentHierarchicalCullingPlusPlusManager(mAssumedVisibilityForChc);
+				mCullingManager = chcm;
 			}
 			break;
@@ -118,8 +111,14 @@
 	mAssumedVisibilityForChc = assumedVisibility;
 
-	if (mCullingManagerType == VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING)
+	switch (mCullingManagerType)
 	{
+	case VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING:
 		static_cast<CoherentHierarchicalCullingManager *>(mCullingManager)->
 				SetAssumedVisibility(mAssumedVisibilityForChc);
+		break;
+	case VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING_PLUSPLUS:
+		static_cast<CoherentHierarchicalCullingPlusPlusManager *>(mCullingManager)->
+				SetAssumedVisibility(mAssumedVisibilityForChc);
+		break;
 	}
 }
@@ -129,5 +128,5 @@
 	mRandomCandidatesForRuc = randomCandidates;
 
-	if (mCullingManagerType == VisibilityEnvironment::RANDOM_UPDATE_CULLING)
+	if (mCullingManagerType == VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING_PLUSPLUS)
 	{
 		static_cast<RandomUpdateCullingManager *>(mCullingManager)->
@@ -160,9 +159,9 @@
 				SetTestGeometryForVisibleLeaves(mTestGeometryForVisibleLeaves);
 	}
-	else if (mCullingManagerType == VisibilityEnvironment::RANDOM_UPDATE_CULLING)
+	/*else if (mCullingManagerType == VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING_PLUSPLUS)
 	{
 		static_cast<RandomUpdateCullingManager *>(mCullingManager)->
 				SetTestGeometryForVisibleLeaves(mTestGeometryForVisibleLeaves);
-	}
+	}*/
 }
 //-----------------------------------------------------------------------
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/src/GtpVisibility.vcproj
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/src/GtpVisibility.vcproj	(revision 2542)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/src/GtpVisibility.vcproj	(revision 2555)
@@ -253,8 +253,8 @@
 			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
 			<File
-				RelativePath="..\src\BatchedQueriesCullingManager.cpp">
-			</File>
-			<File
 				RelativePath="..\src\CoherentHierarchicalCullingManager.cpp">
+			</File>
+			<File
+				RelativePath=".\CoherentHierarchicalCullingPlusPlusManager.cpp">
 			</File>
 			<File
@@ -297,11 +297,8 @@
 			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
 			<File
-				RelativePath="..\include\BatchedQueriesCullingManager.h">
-			</File>
-			<File
 				RelativePath="..\include\CoherentHierarchicalCullingManager.h">
 			</File>
 			<File
-				RelativePath="..\include\CoherentHierarchicalCullingManager2.h">
+				RelativePath="..\include\CoherentHierarchicalCullingPlusPlusManager.h">
 			</File>
 			<File
Index: GTP/trunk/Lib/Vis/OnlineCullingCHC/src/CoherentHierarchicalCullingPlusPlusManager.cpp
===================================================================
--- GTP/trunk/Lib/Vis/OnlineCullingCHC/src/CoherentHierarchicalCullingPlusPlusManager.cpp	(revision 2553)
+++ GTP/trunk/Lib/Vis/OnlineCullingCHC/src/CoherentHierarchicalCullingPlusPlusManager.cpp	(revision 2555)
@@ -1,43 +1,94 @@
-#include "BatchedQueriesCullingManager.h"
+#include "CoherentHierarchicalCullingPlusPlusManager.h"
+#include "CullingLogManager.h"
+
+#include <time.h>
+#include <sstream>
+
 
 
 namespace GtpVisibility {
 
-//-----------------------------------------------------------------------
-BatchedQueriesCullingManager::BatchedQueriesCullingManager():
-mMaxPending(5)
-{
-}
-//-----------------------------------------------------------------------
-BatchedQueriesCullingManager::BatchedQueriesCullingManager(const unsigned int 
-														   assumedVisibility):
-CoherentHierarchicalCullingManager(assumedVisibility), mMaxPending(5)
-{
-}
-
-//-----------------------------------------------------------------------
-void BatchedQueriesCullingManager::RenderScene()
-{
-	QueryQueue queryQueue;
+
+static const bool CULL_INVALID_NODES = false;
+
+//-----------------------------------------------------------------------
+CoherentHierarchicalCullingPlusPlusManager::CoherentHierarchicalCullingPlusPlusManager():
+mAssumedVisibility(0), mMaxInvisibleNodesSize(50)
+{
+}
+//-----------------------------------------------------------------------
+CoherentHierarchicalCullingPlusPlusManager::CoherentHierarchicalCullingPlusPlusManager(
+														const unsigned int assumedVisibility):
+mAssumedVisibility(assumedVisibility), mMaxInvisibleNodesSize(50)
+{
+}
+//-----------------------------------------------------------------------
+void CoherentHierarchicalCullingPlusPlusManager::AssignAssumedVisibility(GtpVisibility::HierarchyNode *node)
+{
+	if (!mHierarchyInterface->IsNodeVisible(node))
+		// previously invisible nodes: give random offset just for the first test after
+		// becoming visible to avoid that all nodes are tested in the same frame
+		mHierarchyInterface->SetNodeAssumedVisible(node, rand() * mAssumedVisibility / RAND_MAX);
+	else
+		mHierarchyInterface->SetNodeAssumedVisible(node, mAssumedVisibility);
+}
+//-----------------------------------------------------------------------
+void CoherentHierarchicalCullingPlusPlusManager::RenderScene()
+{
+	if (0) CullingLogManager::GetSingleton()->LogMessage("chc++");
+	
 	unsigned int visiblePixels = 0;
 
-	PendingQueue pendingQueue;
-
+	/////////////
 	//-- PART 1: process finished occlusion queries
-	while (!mHierarchyInterface->GetQueue()->empty() || !queryQueue.empty() ||!pendingQueue.empty())
+
+	while (!mHierarchyInterface->GetQueue()->empty() || !mQueryQueue.empty() ||
+		   !mInvisibleNodes.empty() || !mVisibleNodes.empty())
 	{
-		while (!queryQueue.empty() && 
-			   queryQueue.front().second->GetQueryResult(visiblePixels, 
-									mHierarchyInterface->GetQueue()->empty()))
+		//////////
+		//-- only wait for result if there are no nodes to process
+
+		bool resultAvailable = false;
+		while (
+			   !mQueryQueue.empty() && 
+			   (NodeInvalid(mQueryQueue.front().first) ||
+			   mHierarchyInterface->GetQueue()->empty() ||
+			   (resultAvailable = mQueryQueue.front().second->GetQueryResult(visiblePixels, false)))
+			   )
 		{
-           	HierarchyNode *node = queryQueue.front().first;
-			
-			queryQueue.pop();
-
+			HierarchyNode *node = mQueryQueue.front().first;
+
+			// "invalid nodes" happen for hierarchies that store geometry in the interiors
+			// parent was tested invisible => remove children from queue
+			if (NodeInvalid(node)) {mQueryQueue.pop(); continue;}
+
+			// during the wait time issue nodes from visible queue
+			while (!mVisibleNodes.empty() && !resultAvailable)
+			{
+				HierarchyNode *vn = mVisibleNodes.front();
+				mVisibleNodes.pop();
+				IssueQuery(vn, false);
+
+				// check if result is already availalbe
+				resultAvailable = mQueryQueue.front().second->GetQueryResult(visiblePixels, false);
+			}
+
+			if (!resultAvailable)
+				mQueryQueue.front().second->GetQueryResult(visiblePixels, true);
+
+			resultAvailable = false;
+           	mQueryQueue.pop();
+
+			// tested visible
 			if (visiblePixels > mVisibilityThreshold)
 			{
-				// ensure that we only traverse once if geometry in node
+				// assing the #frames the node is assumed to stay visible
+				AssignAssumedVisibility(node);
+
+				// for previously visible interior node which contains geometry: 
+				// ensure that we did not already traverse this node 
+				// (which means that the visibility flag is set)
 				if (!mHierarchyInterface->IsNodeVisible(node))
-					mHierarchyInterface->TraverseNode(node);
+					mHierarchyInterface->TraverseNode2(node);
 
 				mHierarchyInterface->PullUpVisibility(node);
@@ -50,11 +101,14 @@
 				
 				if (mVisualizeCulledNodes)
-				{
 					mHierarchyInterface->VisualizeCulledNode(node, QUERY_CULLED);
 				}
-			}
+			
+			// update node's visited flag
+			mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId());	
 		}
 		
+		////////////////
 		//-- PART 2: hierarchical traversal
+
 		if (!mHierarchyInterface->GetQueue()->empty())
 		{
@@ -62,4 +116,7 @@
 			mHierarchyInterface->GetQueue()->pop();
 				
+			// parent was tested invisible => remove children from queue
+			if (NodeInvalid(node)) continue;
+
 			bool intersects = false;
 
@@ -69,11 +126,9 @@
 				
 				if (mVisualizeCulledNodes)
-				{
 					mHierarchyInterface->VisualizeCulledNode(node, FRUSTUM_CULLED);
-				}
-			}
-			// -- if node intersects near plane, skip query because wrong results possible
+			}
 			else if (intersects)
 			{
+				//-- if node intersects near plane, skip query because wrong results possible
 				SkipQuery(node);
 			}
@@ -85,6 +140,7 @@
 				
 				// if we assume node to be visible in this frame => skip query 
-				bool skipQuery = wasVisible && (mAssumedVisibility > 0) && 
-					DecideVisible(node) && mHierarchyInterface->HasGeometry(node);
+				const bool skipQuery = wasVisible &&
+									   DecideVisible(node) && 
+									   mHierarchyInterface->HasGeometry(node);
 
 				if (skipQuery)
@@ -96,24 +152,36 @@
                 // identify nodes that we cannot skip queries for
 				// geometry not only in leaves => test for renderable geometry
-				bool issueQuery = !wasVisible || mHierarchyInterface->HasGeometry(node);
+				const bool issueQuery = !wasVisible || mHierarchyInterface->HasGeometry(node);
 							
-				// reset node's visibility classification
-				// set visible if geometry in node so we only traverse once
+				// set node's visibility classification
+				// we identify previously visible / invisible nodes in the query queue
 				mHierarchyInterface->SetNodeVisible(node, wasVisible && issueQuery);
 
-				// update node's visited flag
-				mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId());
-
-				// skip testing previously visible nodes without geometry
 				if (issueQuery)
 				{
 					++ mNumQueriesIssued;
-					// add to the pending queue instead of immediate query
-					if ((int)pendingQueue.size() < mMaxPending)
-						pendingQueue.push(PendingQuery(node, wasVisible));
+
+					if (!wasVisible)
+					{
+						mInvisibleNodes.push_back(node);
+
+						if ((int)mInvisibleNodes.size() >= mMaxInvisibleNodesSize)
+						{
+							mHierarchyInterface->RenderQueue();
+							// issue the batched queries
+							IssueBatchedQuery(mInvisibleNodes);
+						}
+					}
 					else
 					{
-						IssueMultipleQueries(pendingQueue, queryQueue);	
+						mVisibleNodes.push(node);
+						//IssueQuery(node, false);
 					}
+				}
+				else
+				{
+					// skip testing previously visible nodes without geometry
+                    // just update node's visited flag
+					mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId());
 				}
 				
@@ -121,33 +189,113 @@
 				if (wasVisible)
 				{
-					mHierarchyInterface->TraverseNode(node);
+					mHierarchyInterface->TraverseNode2(node);
 				}
 			}
 		}
 
-		// issue rest of queries
-		IssueMultipleQueries(pendingQueue, queryQueue);
+		
+		if (mHierarchyInterface->GetQueue()->empty() && !mInvisibleNodes.empty())
+		{
+			if (0)
+			{
+				std::stringstream d;
+				d << "inv nodes: " << (int)mInvisibleNodes.size();
+				CullingLogManager::GetSingleton()->LogMessage(d.str());
+			}
+			
+			mHierarchyInterface->RenderQueue();
+			IssueBatchedQuery(mInvisibleNodes);
+		}
+
+        // issue rest of nodes from nodes from visible queue
+		if (mHierarchyInterface->GetQueue()->empty() && mQueryQueue.empty() && !mVisibleNodes.empty())
+		{
+			if (0)
+			{
+				std::stringstream d;
+				d << "vis nodes: " << (int)mVisibleNodes.size();
+				CullingLogManager::GetSingleton()->LogMessage(d.str());
+			}
+
+			while (!mVisibleNodes.empty())
+			{
+				IssueQuery(mVisibleNodes.front(), false);
+				mVisibleNodes.pop();
+			}
+		}
 	}
-}
-
-void BatchedQueriesCullingManager::IssueMultipleQueries(PendingQueue &pendingQueue, 
-														QueryQueue &queryQueue)
-{
-	while (!pendingQueue.empty())
+
+
+	if (0)
 	{
-		HierarchyNode *node = pendingQueue.front().first;
-		const bool wasVisible = pendingQueue.front().second;
-
-		pendingQueue.pop();
-
-		queryQueue.push(QueryPair(node, mHierarchyInterface->
-					IssueNodeOcclusionQuery(node, wasVisible)));
+		std::stringstream d;
+		d << "queries: " << (int)mQueryQueue.size() << " vis: " << (int)mVisibleNodes.size() << " inv: " << (int)mInvisibleNodes.size();
+		CullingLogManager::GetSingleton()->LogMessage(d.str());
 	}
-}
-
-void BatchedQueriesCullingManager::SetMaxPending(int maxPending)
-{
-	mMaxPending = maxPending;
-}
-
-} // namespace GtpVisibility
+	
+	// render rest
+	mHierarchyInterface->RenderQueue();
+}
+//-----------------------------------------------------------------------
+void CoherentHierarchicalCullingPlusPlusManager::SetAssumedVisibility(const unsigned int assumedVisibility)
+{
+	mAssumedVisibility = assumedVisibility;
+}
+//-----------------------------------------------------------------------
+inline bool CoherentHierarchicalCullingPlusPlusManager::DecideVisible(HierarchyNode *node) const
+{
+	mHierarchyInterface->DecNodeAssumedVisible(node);
+	//std::stringstream d; d << "node visible: " << mHierarchyInterface->GetNodeAssumedVisible(node);
+	//CullingLogManager::GetSingleton()->LogMessage(d.str());
+	return mHierarchyInterface->GetNodeAssumedVisible(node) > 0;
+}
+//-----------------------------------------------------------------------
+inline void CoherentHierarchicalCullingPlusPlusManager::SkipQuery(HierarchyNode *node) const
+{
+	//-- set node to be visible in this frame, then traverse it
+	mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId());
+
+	mHierarchyInterface->PullUpVisibility(node);			
+	mHierarchyInterface->TraverseNode2(node);
+}
+//-----------------------------------------------------------------------
+inline bool CoherentHierarchicalCullingPlusPlusManager::NodeInvalid(HierarchyNode *node) const
+{
+	if (!CULL_INVALID_NODES) return false;
+
+	// parent was tested invisible in this frame
+    return ( 
+		    mHierarchyInterface->GetParent(node) && 
+		    (mHierarchyInterface->LastVisited(node) == mHierarchyInterface->GetFrameId()) && 
+		    !mHierarchyInterface->IsNodeVisible(mHierarchyInterface->GetParent(node))
+           );
+}
+//-----------------------------------------------------------------------
+void CoherentHierarchicalCullingPlusPlusManager::SetTestGeometryForVisibleLeaves(const bool testGeometry)
+{
+	mTestGeometryForVisibleLeaves = testGeometry;
+}
+//-----------------------------------------------------------------------
+bool CoherentHierarchicalCullingPlusPlusManager::GetTestGeometryForVisibleLeaves()
+{
+	return mTestGeometryForVisibleLeaves;
+}
+//-----------------------------------------------------------------------
+inline void CoherentHierarchicalCullingPlusPlusManager::IssueQuery(HierarchyNode *node, 
+																   const bool queryGeometry)
+{
+	mQueryQueue.push(QueryPair(node, mHierarchyInterface->
+		IssueNodeOcclusionQuery(node, queryGeometry)));
+}
+//-----------------------------------------------------------------------
+void CoherentHierarchicalCullingPlusPlusManager::IssueBatchedQuery(HierarchyNodeContainer &nodes)
+{
+	HierarchyNodeContainer::const_iterator nit, nit_end = nodes.end();
+
+	for (nit = nodes.begin(); nit != nit_end; ++ nit)
+		IssueQuery(*nit, false);
+
+	nodes.clear();
+}
+		
+}
