Index: GTP/trunk/App/Demos/Vis/CHC_revisited/SceneEntity.h
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/SceneEntity.h	(revision 2764)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/SceneEntity.h	(revision 2764)
@@ -0,0 +1,75 @@
+#ifndef __SCENEENTITY_H
+#define __SCENEENTITY_H
+
+#include "common.h"
+#include "AxisAlignedBox3.h"
+#include "Triangle3.h"
+
+
+namespace CHCDemo 
+{
+
+class Material;
+class Geometry;
+class RenderState;
+
+/** The current render state.
+*/
+class RenderState
+{
+public:
+	bool mTexturesEnabled;
+};
+
+
+/** Class representing a scene entity.
+    A scene entity basicly consists of geometry, transformation, and a material
+*/
+class SceneEntity
+{
+public:
+int id;
+	/** Creates a scene entity.
+	*/
+	SceneEntity(Geometry *geometry, Material *mat, Matrix4x4 *trafo);
+	/** Renders this node.
+	*/
+	void Render(RenderState *state);	
+	/** Set pointer to the geometry
+	*/
+	void SetGeometry(Geometry *geom);
+	/** See set
+	*/
+	Geometry *GetGeometry() const { return mGeometry; }
+	/** Set pointer to the geometry
+	*/
+	void SetTransformation(Matrix4x4 *trafo);
+	/** Set pointer to the material
+	*/
+	void SetMaterial(Material *mat);
+	/** Returns the transformed bounding box.
+	*/
+	AxisAlignedBox3 GetBoundingBox() const;
+	/** set frame where we last rendered this node
+	*/
+	void SetLastRendered(int lastRendered);
+	/** returns frame where we last visited this node
+	*/
+	int GetLastRendered() const;
+	
+
+protected:
+
+	/// transform matrix 
+	Matrix4x4 *mTransform;
+	Geometry *mGeometry;
+	Material *mMaterial;
+
+	//AxisAlignedBox3 mBoundingBox;
+	
+	int mLastRendered;
+};
+
+}
+
+#endif // __SCENEENTITY_H
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/Texture.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/Texture.cpp	(revision 2758)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/Texture.cpp	(revision 2764)
@@ -60,4 +60,5 @@
 	glBindTexture(GL_TEXTURE_2D, mTexId);
 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/RenderTraverser.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/RenderTraverser.cpp	(revision 2763)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/RenderTraverser.cpp	(revision 2764)
@@ -7,4 +7,25 @@
 namespace CHCDemo
 {
+
+	
+void TraversalStatistics::Reset()
+{
+	// reset statistics
+	mNumTraversedNodes = 0;
+	mNumQueryCulledNodes = 0;
+	mNumFrustumCulledNodes = 0;
+	mNumRenderedGeometry = 0;
+	mNumRenderedTriangles = 0;
+
+	mNumIssuedQueries = 0;
+	mRenderTime = 0;
+}
+
+
+
+/******************************************************/
+/*           RenderTraverser implementation           */
+/******************************************************/
+
 
 RenderTraverser::RenderTraverser(): 
@@ -13,6 +34,5 @@
 mBvh(NULL), 
 mIsQueryMode(false),
-mUseOptimization(true),
-mCurrentQueryIdx(0)
+mUseOptimization(true)
 {
 }
@@ -21,40 +41,7 @@
 RenderTraverser::~RenderTraverser()
 {
-	//DelQueries();
-}
-
-
-/*void RenderTraverser::Render(int mode)
-{
-	mDistanceQueue.push(mHierarchyRoot);
-
-	long startTime = getTime();
-
-	Preprocess();
-
-	switch(mode)
-	{
-		case RENDER_CULL_FRUSTUM:
-			RenderCullFrustum();
-            break;
-		case RENDER_STOP_AND_WAIT:
-			RenderStopAndWait();
-			break;
-		case RENDER_COHERENT:
-			RenderCoherentWithQueue();
-			break;
-		default:
-			RenderCullFrustum();
-			break;
-	}
-
-	mFrameID ++;
-	
-
-	long endTime = getTime();
-	mRenderTime = endTime - startTime;
-
-	finishTiming();
-}*/
+	mQueryHandler.DestroyQueries();
+}
+
 
 void RenderTraverser::EnqueueNode(BvhNode *node)
@@ -67,11 +54,10 @@
 void RenderTraverser::TraverseNode(BvhNode *node)
 {
+	++ mStats.mNumTraversedNodes;
 
 	if (node->IsVirtualLeaf())
 	{
 		//RenderBox(node->GetBox());
-
-		//mNumRenderedGeometry +=
-		mBvh->Render(node, mRenderState);
+		mStats.mNumRenderedGeometry +=	mBvh->Render(node, mRenderState);
 	}
 	else 
@@ -117,5 +103,9 @@
 OcclusionQuery *RenderTraverser::IssueOcclusionQuery(BvhNode *node, bool wasVisible)
 {
+	++ mStats.mNumIssuedQueries;
+
 	OcclusionQuery *query = mQueryHandler.RequestQuery();
+	query->Reset();
+	query->AddNode(node);
 
 	query->BeginQuery();
@@ -131,7 +121,7 @@
 
 	// change state so the bounding box gets not actually rendered on the screen
-	//Switch2GLQueryState();
+	Switch2GLQueryState();
 	mBvh->RenderBoundingBox(node);
-	//Switch2GLRenderState();
+	Switch2GLRenderState();
 
 	query->EndQuery();
@@ -155,12 +145,27 @@
 
 
-#if 0
-
-Bvh *RenderTraverser::GetHierarchy()
-{
-	return mBvh;
-}
-
-
+void RenderTraverser::PullUpVisibility(BvhNode *node)
+{
+	while(node && ! node->IsVisible())
+	{
+		node->SetVisible(true);
+		node = node->GetParent();
+	}
+}
+
+
+void RenderTraverser::SetVisibilityThreshold(int threshold)
+{
+	mVisibilityThreshold = threshold;
+}
+
+
+int RenderTraverser::GetVisibilityThreshold() const
+{
+	return mVisibilityThreshold;
+}
+
+
+/*
 void RenderTraverser::RenderVisualization()
 {
@@ -184,180 +189,5 @@
 		}
 	}
-}
-
-
-void RenderTraverser::PullUpVisibility(HierarchyNode *node)
-{
-	while(node && !node->Visible())
-	{
-		node->SetVisible(true);
-		node = node->GetParent();
-	}
-}
-
-bool RenderTraverser::ResultAvailable(HierarchyNode *node) const
-{
-	unsigned int result;
-	if (mUseArbQueries)
-	{
-		glGetQueryObjectuivARB(node->GetOcclusionQuery(),
-							   GL_QUERY_RESULT_AVAILABLE_ARB, &result);
-	}
-	else
-	{
-		
-		glGetOcclusionQueryuivNV(node->GetOcclusionQuery(), 
-								 GL_PIXEL_COUNT_AVAILABLE_NV, &result);
-
-	}
-	
-	return (result == GL_TRUE);
-}
-
-
-void RenderTraverser::Preprocess()
-{
-	if (!mOcclusionQueries)
-	{
-		mOcclusionQueries = new unsigned int[mHierarchyRoot->GetNumHierarchyNodes()];
-
-		// generate ids for occlusion test
-		if (mUseArbQueries)
-		{
-			glGenQueriesARB(mHierarchyRoot->GetNumHierarchyNodes(), mOcclusionQueries);
-		}
-		else
-		{
-			glGenOcclusionQueriesNV(mHierarchyRoot->GetNumHierarchyNodes(), mOcclusionQueries);
-		}
-	}
-
-	// view frustum planes for view frustum culling
-	calcViewFrustumPlanes(&mClipPlanes, mProjViewMatrix);
-	calcAABNPVertexIndices(mNPVertexIndices, mClipPlanes);
-
-	mCurrentQueryIdx = 0;
-
-	// reset statistics
-	mNumTraversedNodes = 0;
-	mNumQueryCulledNodes = 0;
-	mNumFrustumCulledNodes = 0;
-	mNumRenderedGeometry = 0;
-}
-
-
-void RenderTraverser::DelQueries()
-{
-	if (!mOcclusionQueries)
-		return;
-
-	// tell the driver that the occlusion queries won't be needed any more
-	if (mUseArbQueries)
-	{
-		glDeleteQueriesARB(mHierarchyRoot->GetNumHierarchyNodes(), mOcclusionQueries);
-	}
-	else
-	{
-		glDeleteOcclusionQueriesNV(mHierarchyRoot->GetNumHierarchyNodes(), mOcclusionQueries);
-	}
-
-	delete [] mOcclusionQueries;
-
-	mOcclusionQueries = NULL;
-}
-
-
-void RenderTraverser::SetViewpoint(Vector3 const &viewpoint)
-{
-	copyVector3(mViewpoint, viewpoint);
-}
-	
-
-void RenderTraverser::SetProjViewMatrix(Matrix4x4 const &projViewMatrix)
-{
-	copyMatrix(mProjViewMatrix, projViewMatrix);
-}
-
-
-bool RenderTraverser::InsideViewFrustum(HierarchyNode *node, bool &intersects)
-{
-	Vector3x8 vertices;
-	
-	bool intersect = false;
-
-	calcAABoxPoints(vertices, node->GetBoundingVolume());
-
-	// simply test all 6 vertices
-	for (int i = 0; i < 6; i++)
-	{		
-		// test the n-vertex
-		// note: the calcAABNearestVertexId should be preprocessed
-		if(!pointBeforePlane(mClipPlanes.plane[i], vertices[mNPVertexIndices[i * 2]]))
-		{
-			// outside
-			return false;
-		}
-	}
-
-	// test if bounding box is intersected by nearplane (using the p-vertex)
-	intersects = (!pointBeforePlane(mClipPlanes.plane[5], vertices[mNPVertexIndices[11]]));
-
-	// -- get vector from viewpoint to center of bounding volume
-	Vector3 vec;
-	calcAABoxCenter(vec, node->GetBoundingVolume());
-	diffVector3(vec, vec, mViewpoint);
-
-	// compute distance from nearest point to viewpoint
-	diffVector3(vec, vertices[calcAABNearestVertexIdx(vec)], mViewpoint);
-	node->SetDistance(squaredLength(vec));
-	
-	return true;
-}
-
-
-void RenderTraverser::SetVisibilityThreshold(int threshold)
-{
-	mVisibilityThreshold = threshold;
-}
-
-void RenderTraverser::SetUseArbQueries(const bool useArbQueries)
-{
-	DelQueries();
-	mUseArbQueries = useArbQueries;
-}
-
-bool RenderTraverser::GetUseArbQueries() const
-{
-	return mUseArbQueries;
-}
-
-long RenderTraverser::GetRenderTime()
-{
-	return mRenderTime;
-}
-
-int RenderTraverser::GetNumTraversedNodes()
-{
-	return mNumTraversedNodes;
-}
-
-int RenderTraverser::GetNumQueryCulledNodes()
-{
-	return mNumQueryCulledNodes;
-}
-
-int RenderTraverser::GetNumFrustumCulledNodes()
-{
-	return mNumFrustumCulledNodes;
-}
-
-
-int RenderTraverser::GetNumRenderedGeometry()
-{
-	return mNumRenderedGeometry;
-}
-
-
-#endif
+}*/
 
 
@@ -474,3 +304,4 @@
 
 
-}
+
+}
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.cpp	(revision 2763)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.cpp	(revision 2764)
@@ -366,12 +366,10 @@
 	// store near plane
 	sNearPlane = Plane3(mCamera->GetDirection(), mCamera->GetPosition());
-//	Debug << "near: " << sNearPlane << " d " << mCamera->GetDirection() << " " << mCamera->GetPosition() << std::endl;
-//	for (int i = 0; i < 6; ++ i) Debug << "plane: " << sFrustum.mClipPlanes[i] << std::endl;
-}
-
-
-float Bvh::CalcDistance(BvhNode *node) const
-{
-	return node->GetBox().GetMinVisibleDistance(sNearPlane);
+}
+
+
+void Bvh::CalcDistance(BvhNode *node) const
+{
+	node->mDistance = node->GetBox().GetMinVisibleDistance(sNearPlane);
 }
 
@@ -872,4 +870,6 @@
 	}
 
+	mNumVirtualNodes = 0;
+
 	// assign new virtual leaves based on specified number of triangles per leaf
 	std::stack<BvhNode *> nodeStack;
@@ -880,4 +880,6 @@
 		BvhNode *node = nodeStack.top();
 		nodeStack.pop();
+
+		++ mNumVirtualNodes;
 
 		if (node->IsLeaf()) 
@@ -948,30 +950,32 @@
 	const Vector3 u = box.Max();
 
-	///////////
-	//-- render AABB as triangle strips
-
-	glVertex3f(l.x, l.y, u.z);
-	glVertex3f(u.x, l.y, u.z);
-	glVertex3f(l.x, u.y, u.z);
-	glVertex3f(u.x, u.y, u.z);
-	glVertex3f(l.x, u.y, l.z); 
-	glVertex3f(u.x, u.y, l.z);
-	glVertex3f(l.x, l.y, l.z); 
-	glVertex3f(u.x, l.y, l.z);
-
-	glPrimitiveRestartNV();
-
-	//-- render second half of AABB
-	glVertex3f(l.x, u.y, u.z); 
-	glVertex3f(l.x, u.y, l.z);
-	glVertex3f(l.x, l.y, u.z);
-	glVertex3f(l.x, l.y, l.z);
-	glVertex3f(u.x, l.y, u.z); 
-	glVertex3f(u.x, l.y, l.z);
-	glVertex3f(u.x, u.y, u.z); 
-	glVertex3f(u.x, u.y, l.z);
-}
-
-
-
-}
+	glBegin(GL_TRIANGLE_STRIP);
+	{
+		///////////
+		//-- render AABB as triangle strips
+
+		glVertex3f(l.x, l.y, u.z);
+		glVertex3f(u.x, l.y, u.z);
+		glVertex3f(l.x, u.y, u.z);
+		glVertex3f(u.x, u.y, u.z);
+		glVertex3f(l.x, u.y, l.z); 
+		glVertex3f(u.x, u.y, l.z);
+		glVertex3f(l.x, l.y, l.z); 
+		glVertex3f(u.x, l.y, l.z);
+
+		glPrimitiveRestartNV();
+
+		//-- render second half of AABB
+		glVertex3f(l.x, u.y, u.z); 
+		glVertex3f(l.x, u.y, l.z);
+		glVertex3f(l.x, l.y, u.z);
+		glVertex3f(l.x, l.y, l.z);
+		glVertex3f(u.x, l.y, u.z); 
+		glVertex3f(u.x, l.y, l.z);
+		glVertex3f(u.x, u.y, u.z); 
+		glVertex3f(u.x, u.y, l.z);
+	}
+	glEnd();
+}
+
+}
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/BinaryLoader.h
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/BinaryLoader.h	(revision 2757)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/BinaryLoader.h	(revision 2764)
@@ -30,4 +30,6 @@
 	
 	void LoadTextures(std::ifstream &str);
+	void LoadShapes(std::ifstream &str);
+	void LoadSceneEntities(std::ifstream &str, SceneEntityContainer &entities);
 
 	SceneEntity *LoadSceneEntity(std::ifstream &str);
@@ -35,10 +37,7 @@
 	Geometry *LoadGeometry(std::ifstream &str);
 
-	/*SceneEntity *LoadShape(igzstream &str);
-	Material *LoadMaterial(igzstream &str);
-	Geometry *LoadGeometry(igzstream &str);
-	*/
-
 	std::map<int, Texture *> mTextureTable;
+	std::map<int, Material *> mMaterialTable;
+	std::map<int, Geometry *> mGeometryTable;
 };
 
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/OcclusionQuery.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/OcclusionQuery.cpp	(revision 2763)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/OcclusionQuery.cpp	(revision 2764)
@@ -85,5 +85,9 @@
 	}
 	else
+	{
 		query = mOcclusionQueries[mCurrentQueryIdx];
+	}
+
+	++ mCurrentQueryIdx;
 
 	return query;
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/common.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/common.cpp	(revision 2756)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/common.cpp	(revision 2764)
@@ -194,5 +194,5 @@
 	// get the absolute path
 	size_t c = strlen(name);
-	int i = c - 1;
+	size_t i = c - 1;
 	bool wasDot = false;
 
@@ -258,7 +258,7 @@
 StripPath(const char *s)
 {
-	const int len = strlen(s);
-
-	int i = len;
+	const size_t len = strlen(s);
+
+	size_t i = len;
 	for (; i>0; i--) {
 		if (s[i]=='/' || s[i]=='\\')
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/SceneQuery.h
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/SceneQuery.h	(revision 2764)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/SceneQuery.h	(revision 2764)
@@ -0,0 +1,33 @@
+#ifndef _SCENEQUERY_H__
+#define _SCENEQUERY_H__
+
+#include "common.h"
+#include "AxisAlignedBox3.h"
+
+namespace CHCDemo
+{
+
+/** A simple class that computes the first intersection of a horizontal ray with
+	the scene. Can be used to "drop" objects in the scene.
+*/
+class SceneQuery
+{
+public:
+
+	SceneQuery(const AxisAlignedBox3 &sceneBox);
+
+	bool CalcIntersection(Vector3 &pt);
+
+protected:
+
+	void Prepare();
+
+
+	///////////
+
+	AxisAlignedBox3 mSceneBox;
+};
+
+}
+
+#endif
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/StopAndWaitTraverser.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/StopAndWaitTraverser.cpp	(revision 2763)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/StopAndWaitTraverser.cpp	(revision 2764)
@@ -23,8 +23,9 @@
 void StopAndWaitTraverser::Render()
 {
+	mStats.Reset();
 	mRenderState->mTexturesEnabled = false;
-	mDistanceQueue.push(mBvh->GetRoot());
+	EnqueueNode(mBvh->GetRoot());
 
-
+	//cout<<"\n***** starting frame **********\n";
 	int traversed = 0;
 	while (!mDistanceQueue.empty())
@@ -33,12 +34,14 @@
 		mDistanceQueue.pop();
 	
+		//float d = mBvh->GetDistance(node);cout << d << " ";
+
 		// interesting for the visualization, so rest and set
 		node->SetVisible(false);
-		//mNumTraversedNodes ++;
+
 
 		if (mBvh->IsWithinViewFrustum(node))
 		{
 			// if intersects near plane assume visible and don't issue test
-			if (mBvh->CalcDistance(node) < 0.1f)
+			if (IntersectsNearPlane(node))
 			{
 				TraverseNode(node);
@@ -50,13 +53,17 @@
 				int visiblePixels = query->GetQueryResult();
 
-				if (visiblePixels > 0)
+				if (visiblePixels > mVisibilityThreshold)
 				{
-					cout<< "visible: " << visiblePixels << endl;
+					//cout<< "visible: " << visiblePixels << endl;
 					// update node's visited flag => needed for rendering
 					// so set it also here
 					//node->SetLastVisited(mFrameID);
 					//node->SetVisible(true);
-					++ traversed;
+				
 					TraverseNode(node);
+				}
+				else
+				{
+					++ mStats.mNumQueryCulledNodes;
 				}
 			}
@@ -64,5 +71,5 @@
 		else
 		{
-			//mNumFrustumCulledNodes ++;
+			++ mStats.mNumFrustumCulledNodes;
 		}
 		//cout << "intersect: " << intersect << " bx " << node->GetBox() << endl;
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/CHCTraverser.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/CHCTraverser.cpp	(revision 2755)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/CHCTraverser.cpp	(revision 2764)
@@ -1,3 +1,5 @@
 #include "CHCTraverser.h"
+#include "SceneEntity.h"
+
 
 namespace CHCDemo
@@ -17,5 +19,8 @@
 void CHCTraverser::Render()
 {
-#if 0
+	mStats.Reset();
+	mRenderState->mTexturesEnabled = false;
+	EnqueueNode(mBvh->GetRoot());
+
 	QueryQueue queryQueue;
 
@@ -24,20 +29,22 @@
 	{
 		while (!queryQueue.empty() && 
-			   (ResultAvailable(queryQueue.front()) || mDistanceQueue.empty()))
+			   (queryQueue.front()->ResultAvailable() || mDistanceQueue.empty()))
 		{
-			HierarchyNode *node = queryQueue.front();
+			OcclusionQuery *query = queryQueue.front();
 			queryQueue.pop();
 			
 			// wait until result available
-			int visiblePixels = GetOcclusionQueryResult(node);
+			int visiblePixels = query->GetQueryResult();
 
-			if(visiblePixels > mVisibilityThreshold)
+			if (visiblePixels > mVisibilityThreshold)
 			{
-				PullUpVisibility(node);
+				BvhNode *node = query->GetFrontNode();
+
+				mBvh->MakeParentsVisible(node);
 				TraverseNode(node);
 			}
 			else
 			{
-				mNumQueryCulledNodes ++;
+				++ mStats.mNumQueryCulledNodes;
 			}
 		}	
@@ -46,22 +53,18 @@
 		if (!mDistanceQueue.empty())
 		{
-			HierarchyNode *node = mDistanceQueue.top();
-
+			BvhNode *node = mDistanceQueue.top();
 			mDistanceQueue.pop();
 	
-			mNumTraversedNodes ++;
-
-			bool intersects;
-			
-			if (InsideViewFrustum(node, intersects))
+			if (mBvh->IsWithinViewFrustum(node))
 			{
 				// for near plane intersecting bounding box possible 
 				// wrong results => skip occlusion query
-				if(intersects)
+				if (IntersectsNearPlane(node))
 				{
 					// update node's visited flag
-					node->SetLastVisited(mFrameID);
+					node->SetLastVisitedFrame(mFrameID);
 					node->SetVisible(true);
-					PullUpVisibility(node);
+					mBvh->MakeParentsVisible(node);
+
 					TraverseNode(node);
 				}
@@ -69,8 +72,9 @@
 				{		
 					// identify previously visible nodes
-					bool wasVisible = node->Visible() && (node->LastVisited() == mFrameID - 1);
+					const bool wasVisible = node->IsVisible() && (node->GetLastVisitedFrame() == mFrameID - 1);
 					
 					// identify nodes that we cannot skip queries for
-					bool leafOrWasInvisible = (node->LastVisited() != mFrameID) && (!wasVisible || node->IsLeaf());
+					const bool leafOrWasInvisible = 
+						(node->GetLastVisitedFrame() != mFrameID) && (!wasVisible || node->IsVirtualLeaf());
 
 					// reset node's visibility classification 
@@ -78,15 +82,15 @@
 
 					// update node's visited flag
-					node->SetLastVisited(mFrameID);
+					node->SetLastVisitedFrame(mFrameID);
 					
 					// skip testing previously visible interior nodes
-					if(leafOrWasInvisible)
+					if (leafOrWasInvisible)
 					{
-						IssueOcclusionQuery(node, wasVisible);
-						queryQueue.push(node);
+						OcclusionQuery *query = IssueOcclusionQuery(node, wasVisible);
+						queryQueue.push(query);
 					}
 					
 					// always traverse a node if it was visible
-					if(wasVisible)
+					if (wasVisible)
 						TraverseNode(node);
 				}
@@ -95,9 +99,8 @@
 			{
 				// for stats
-				mNumFrustumCulledNodes ++;
+				++ mStats.mNumFrustumCulledNodes;
 			}
 		}
 	}
-#endif
 }
 
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/chc_revisited.vcproj
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/chc_revisited.vcproj	(revision 2756)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/chc_revisited.vcproj	(revision 2764)
@@ -128,5 +128,8 @@
 				AdditionalIncludeDirectories="GL;Devil/include"
 				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				StringPooling="true"
 				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				EnableEnhancedInstructionSet="2"
 				RuntimeTypeInfo="false"
 				UsePrecompiledHeader="0"
@@ -154,4 +157,5 @@
 				OptimizeReferences="2"
 				EnableCOMDATFolding="2"
+				OptimizeForWindows98="1"
 				TargetMachine="1"
 			/>
@@ -241,4 +245,12 @@
 			</File>
 			<File
+				RelativePath=".\SceneQuery.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\SceneQuery.h"
+				>
+			</File>
+			<File
 				RelativePath=".\Timers.cpp"
 				>
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/Camera.h
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/Camera.h	(revision 2762)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/Camera.h	(revision 2764)
@@ -57,4 +57,7 @@
 	void ComputePoints(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
 		               Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr);
+	
+	inline float GetNear() const { return mNear; }
+	void SetNear(float nearDist);
 
 
@@ -74,4 +77,6 @@
 	int mWidth;
 	int mHeight;
+
+	float mNear;
 };
 
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/chcdemo.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/chcdemo.cpp	(revision 2763)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/chcdemo.cpp	(revision 2764)
@@ -16,5 +16,5 @@
 #include "FrustumCullingTraverser.h"
 #include "StopAndWaitTraverser.h"
-
+#include "CHCTraverser.h"
 
 
@@ -36,7 +36,11 @@
 /// the current render state
 RenderState state;
-
+/// the rendering algorithm
+int renderMode = RenderTraverser::CULL_FRUSTUM;
+/// the visibility threshold
+int threshold = 0;
 // eye near plane distance
 float nearDist = 0.1f; 
+
 int winWidth = 1024;
 int winHeight = 768;
@@ -49,5 +53,5 @@
 bool showBoundingVolumes = false;
 bool visMode = false;
-bool showCreateParams = false;
+
 
 int currentFrame = -1;
@@ -58,5 +62,4 @@
 //mouse navigation state
 int xEyeBegin, yEyeBegin, yMotionBegin, verticalMotionBegin, horizontalMotionBegin = 0;
-//int renderMode = RenderTraverser::RENDER_COHERENT;
 
 const int renderTimeSize = 100;
@@ -79,4 +82,5 @@
 void UpdateEyeMtx();
 void SetupLighting();
+void DisplayStats();
 
 void begin2D();
@@ -97,6 +101,6 @@
 long calcRenderTime(void);
 void resetTimer(void);
-void calcDecimalPoint(std::string &str, int d);
-
+void CalcDecimalPoint(std::string &str, int d);
+void ResetTraverser();
 
 
@@ -105,4 +109,5 @@
 {
 	camera = new Camera(winWidth, winHeight);
+	camera->SetNear(nearDist);
 
 	glutInitWindowSize(winWidth, winHeight);
@@ -145,14 +150,8 @@
 	sceneBox = bvh->GetBox();
 
-	//traverser = new FrustumCullingTraverser();
-	traverser = new StopAndWaitTraverser();
-	traverser->SetHierarchy(bvh);
-	traverser->SetRenderState(&state);
-
-	//SetupProjection(800, 600, 60, sceneBox);
+	ResetTraverser();
+
 	//camera->LookAtBox(sceneBox);
 	camera->LookInBox(sceneBox);
-	//camera->SetPosition(Vector3(0, 0, -3));
-	//camera->SetDirection(Vector3(0, 0, 1));
 
 	/// initialise rendertime array
@@ -274,4 +273,28 @@
 
 
+void ResetTraverser()
+{
+	DEL_PTR(traverser);
+
+	switch (renderMode)
+	{
+	case RenderTraverser::CULL_FRUSTUM:
+		traverser = new FrustumCullingTraverser();
+		break;
+	case RenderTraverser::STOP_AND_WAIT:
+		traverser = new StopAndWaitTraverser();
+		break;
+	case RenderTraverser::CHC:
+		traverser = new CHCTraverser();
+		break;
+	default:
+		traverser = new FrustumCullingTraverser();
+	}
+
+	traverser->SetHierarchy(bvh);
+	traverser->SetRenderState(&state);
+}
+
+
 void SetupLighting()
 {
@@ -343,41 +366,4 @@
 void display(void) 
 {
-	char * msg[] = {"Frustum culling only", "Hierarchical stop and wait",
-				    "Coherent hierarchical culling"};
-
-	char msg2[200];
-	char msg3[200];
-	char msg4[100];
-	char msg5[100];
-	char msg6[100];
-	char msg7[100];
-	char msg8[100];
-
-
-	/*sprintf_s(msg2, "Traversed: %4d, frustum culled: %4d, query culled: %4d (of %d nodes)",
-			traverser.GetNumTraversedNodes(), traverser.GetNumFrustumCulledNodes(),
-			traverser.GetNumQueryCulledNodes(), 
-			traverser.GetHierarchy()->GetNumHierarchyNodes());
-*/
-	char *optstr[2] = {"", ", using optimization"};
-	
-	float fps = 1e3f;
-	long renderTime = calcRenderTime();
-	if (renderTime) fps = 1e3f / (float)renderTime;
-
-	//sprintf_s(msg3, "Threshold: %4d, algorithm rendering time: %ld ms (%3.3f fps), queries: %s", 
-	//	traverser.GetVisibilityThreshold(), renderTime / 1000, fps, optstr[useOptimization]);
-	sprintf_s(msg3, "render time: %ld ms (%3.3f fps), queries: %s",  renderTime, fps, optstr[useOptimization]);
-
-	string str;
-	string str2;
-
-	/*calcDecimalPoint(str, Geometry::CountTriangles(objectType) * traverser.GetNumRenderedGeometry());
-	calcDecimalPoint(str2, Geometry::CountTriangles(objectType) * numObjects);
-
-	sprintf_s(msg4, "Rendered objects %d (of %d), rendered triangles: %s (of %s)", 
-			traverser.GetNumRenderedGeometry(), numObjects, str.c_str(), str2.c_str()); 
-*/
-	
 	++ currentFrame;
 
@@ -391,5 +377,4 @@
 
 	InitTiming();
-
 	long t1, t2;
 
@@ -404,29 +389,5 @@
 
 	traverser->Render();
-/*
-	bool usesTextures = false;
-
-	SceneEntityContainer::const_iterator sit, sit_end = sceneEntities.end();
-
-	for (sit = sceneEntities.begin(); sit != sit_end; ++ sit)
-	{
-		SceneEntity *entity = *sit;
-
-		if (!usesTextures && entity->GetGeometry()->HasTexture())
-		{
-			glEnable(GL_TEXTURE_2D);
-			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-			usesTextures = true;
-		}
-		else if (usesTextures && !entity->GetGeometry()->HasTexture())
-		{
-			glDisable(GL_TEXTURE_2D);
-			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-			usesTextures = false;
-		}
-
-		entity->Render();
-	}
-*/
+
 	glDisableClientState(GL_VERTEX_ARRAY);
 	glDisableClientState(GL_NORMAL_ARRAY);
@@ -438,12 +399,5 @@
 	t2 = GetTime();
 	long loop_time = TimeDiff(t1, t2);
-	//cout<<"t: " << loop_time<<endl;
-
-	/*
-	traverser.SetViewpoint(eyePos);
-	traverser.SetProjViewMatrix(eyeProjView);
-	traverser.Render(renderMode);
-	*/
-
+	
 	// cycle through rendertime array
 	renderTimes[renderTimesIdx] = loop_time;// traverser.GetRenderTime();
@@ -455,33 +409,5 @@
 	//if(visMode) displayVisualization();
 	
-
-	begin2D();
-	
-	if(showHelp)
-	{	
-		drawHelpMessage();
-	}
-	else
-	{
-		glColor3f(1.0,1.0,1.0);
-		//output(10, winHeight-10, msg[renderMode]);
-
-		if(showStatistics)
-		{
-			if(showCreateParams)
-			{
-				output(10, winHeight-150, msg8);
-				output(10, winHeight-130, msg7);
-				output(10, winHeight-110, msg6);
-				output(10, winHeight-90,  msg5);
-			}
-
-			output(10, winHeight-70, msg3);
-			//output(10, winHeight-50, msg4);
-			//output(10, winHeight-30, msg2);
-		}
-	}
-	end2D();
-
+	DisplayStats();
 	glutSwapBuffers();
 }
@@ -491,7 +417,4 @@
 void keyboard(const unsigned char c, const int x, const int y) 
 {
-	//int threshold;
-	//HierarchyNode *hierarchy;
-
 	switch(c) 
 	{
@@ -500,7 +423,7 @@
 		break;
 	case 32: //space
-		// renderMode = (renderMode + 1) % RenderTraverser::NUM_RENDERMODES;
+		renderMode = (renderMode + 1) % RenderTraverser::NUM_RENDERMODES;
 		resetTimer();
-		//traverser.Render(renderMode);		// render once so stats are updated
+		ResetTraverser();
 		break;
 	case 'h':
@@ -518,12 +441,12 @@
 		break;
 	case '+':
-		//threshold = traverser.GetVisibilityThreshold() + 10;
-		//traverser.SetVisibilityThreshold(threshold);
+		threshold = traverser->GetVisibilityThreshold() + 10;
+		traverser->SetVisibilityThreshold(threshold);
 		break;
 	case '-':
-		//threshold = traverser.GetVisibilityThreshold() - 10;
-		//if(threshold < 0) threshold = 0;
-
-		//traverser.SetVisibilityThreshold(threshold);		
+		threshold = traverser->GetVisibilityThreshold() - 10;
+		if(threshold < 0) threshold = 0;
+
+		traverser->SetVisibilityThreshold(threshold);		
 		break;
 	case '1':
@@ -541,34 +464,8 @@
 		setupVisView();
 		break;
-	case 'r':
-	case 'R':
-		showCreateParams = !showCreateParams;
-		break;
 	case 'g':
 	case 'G':
 		useOptimization = !useOptimization;
-		//traverser.SetUseOptimization(useOptimization);
-		break;
-		/*
-	case 'c':
-	case 'C':	
-		hierarchy = traverser.GetHierarchy();
-		// delete old hierarchy
-		if (hierarchy) delete hierarchy; 
-		deleteGeometry();
-
-		maxTranslation[2] = -3.0 - zLength;
-		numObjects = numNextObjects;
-		objectType = nextObjectType;
-		
-		hierarchy = generateHierarchy(numObjects);
-		traverser.SetHierarchy(hierarchy);
-
-		showCreateParams = false;
-
-		traverser.Render(renderMode); // render once to update stats
-		resetTimer();
-		break;
-		*/
+		traverser->SetUseOptimization(useOptimization);
 	default:
 		return;
@@ -694,10 +591,12 @@
 
 	// don't move in the vertical direction
-	Vector3 horView(viewDir[0], 0, viewDir[2]);
-	
-	eyeXAngle = -0.2f *  M_PI * (xEyeBegin - x) / 180.0;
+	//Vector3 horView(viewDir[0], 0, viewDir[2]);
+	Vector3 horView(viewDir[0], viewDir[1], 0);
+	
+	eyeXAngle = 0.2f *  M_PI * (xEyeBegin - x) / 180.0;
 
 	// rotate view vector
-	Matrix4x4 rot = RotationYMatrix(eyeXAngle);
+	//Matrix4x4 rot = RotationYMatrix(eyeXAngle);
+	Matrix4x4 rot = RotationZMatrix(eyeXAngle);
 	viewDir = rot * viewDir;
 
@@ -746,11 +645,14 @@
 	// the 90 degree rotated view vector 
 	// y zero so we don't move in the vertical
-	Vector3 rVec(viewDir[0], 0, viewDir[2]);
-	
-	Matrix4x4 rot = RotationYMatrix(M_PI * 0.5f);
+	//Vector3 rVec(viewDir[0], 0, viewDir[2]);
+	Vector3 rVec(viewDir[0], viewDir[1], 0);
+	
+	//Matrix4x4 rot = RotationYMatrix(M_PI * 0.5f);
+	Matrix4x4 rot = RotationZMatrix(M_PI * 0.5f);
 	rVec = rot * rVec;
 	
-	pos += rVec * (x - horizontalMotionBegin) * 0.1f;
-	pos[1] += (verticalMotionBegin - y) * 0.1f;
+	pos -= rVec * (x - horizontalMotionBegin) * 0.1f;
+	//pos[1] += (verticalMotionBegin - y) * 0.1f;
+	pos[2] += (verticalMotionBegin - y) * 0.1f;
 
 	camera->SetPosition(pos);
@@ -902,5 +804,5 @@
 
 // this function inserts a dezimal point after each 1000
-void calcDecimalPoint(string &str, int d)
+void CalcDecimalPoint(string &str, int d)
 {
 	vector<int> numbers;
@@ -920,5 +822,5 @@
 	}
 	
-	for (size_t i = numbers.size() - 2; i >= 0; i--)
+	for (int i = (int)numbers.size() - 2; i >= 0; i--)
 	{
 		sprintf_s(hstr, ",%03d", numbers[i]);
@@ -926,2 +828,59 @@
 	}
 }
+
+
+void DisplayStats()
+{
+	char *msg[] = {"Frustum Culling", "Stop and Wait",
+				    "Coherent Culling"};
+
+	char msg2[200];
+	char msg3[200];
+	char msg4[200];
+
+
+	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;
+	long renderTime = calcRenderTime();
+	if (renderTime) fps /= (float)renderTime;
+
+	sprintf_s(msg3, "Threshold: %4d, render time: %ld ms (%3.3f fps), issued queries: %d%s", 
+		traverser->GetVisibilityThreshold(), renderTime, fps, traverser->GetStats().mNumIssuedQueries, optstr[useOptimization]);
+
+	string str;
+	string str2;
+
+	int dummy = 0;
+	CalcDecimalPoint(str, dummy);
+	CalcDecimalPoint(str2, traverser->GetStats().mNumRenderedTriangles);
+
+	sprintf_s(msg4, "rendered objects %d (of %d), rendered triangles: %s (of %s)", 
+			  traverser->GetStats().mNumRenderedGeometry, sceneEntities.size(), str.c_str(), str2.c_str()); 
+
+
+	begin2D();
+	
+	if(showHelp)
+	{	
+		drawHelpMessage();
+	}
+	else
+	{
+		glColor3f(1.0f ,1.0f ,1.0f );
+		output(20, winHeight - 10, msg[renderMode]);
+
+		if(showStatistics)
+		{
+			output(20, winHeight - 70, msg3);
+			output(20, winHeight - 50, msg4);
+			output(20, winHeight - 30, msg2);
+		}
+	}
+
+	end2D();
+}	
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/BinaryLoader.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/BinaryLoader.cpp	(revision 2763)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/BinaryLoader.cpp	(revision 2764)
@@ -18,7 +18,29 @@
 SceneEntity *BinaryLoader::LoadSceneEntity(ifstream &str)
 {	
-	Geometry *geom = LoadGeometry(str);
-	Material *mat = LoadMaterial(str);
-	Matrix4x4 *trafo = NULL;//IdentityMatrix();
+	// shape
+	int shapeId;
+	str.read(reinterpret_cast<char *>(&shapeId), sizeof(int));
+
+	Geometry *geom = mGeometryTable[shapeId];
+	Material *mat = mMaterialTable[shapeId];
+
+
+	bool hasTrafo;
+	str.read(reinterpret_cast<char *>(&hasTrafo), sizeof(bool));
+
+	Matrix4x4 *trafo;
+	
+	if (!hasTrafo)
+	{
+		trafo = NULL;
+	}
+	else
+	{
+		trafo = new Matrix4x4();
+		//*trafo = IdentityMatrix();
+		str.read(reinterpret_cast<char *>(trafo->x), sizeof(Matrix4x4));
+		//str.read(reinterpret_cast<char *>(trafo), sizeof(Matrix4x4));
+		//cout << "m:\n" << *trafo<<endl;
+	}
 
 	SceneEntity *sceneGeom = new SceneEntity(geom, mat, trafo);
@@ -37,7 +59,6 @@
 		// texture
 		int texnameSize;
-		int id;
-
-		str.read(reinterpret_cast<char *>(&id), sizeof(int));
+
+		//str.read(reinterpret_cast<char *>(&id), sizeof(int));
 		str.read(reinterpret_cast<char *>(&texnameSize), sizeof(int));
 
@@ -48,6 +69,26 @@
 		Texture *tex = new Texture(texname);
 
-		mTextureTable[id] = tex;
-	}
+		mTextureTable[i] = tex;
+	}
+
+	cout << "loaded " << mTextureTable.size() << " textures" << endl;
+}
+
+
+void BinaryLoader::LoadShapes(ifstream &str)
+{
+	int numShapes;
+	str.read(reinterpret_cast<char *>(&numShapes), sizeof(int));
+
+	for (int i = 0; i < numShapes; ++ i)
+	{
+		Geometry *geom = LoadGeometry(str);
+		Material *mat = LoadMaterial(str);
+
+		mGeometryTable[i] = geom;
+		mMaterialTable[i] = mat;
+	}
+
+	cout << "loaded " << mGeometryTable.size() << " shapes" << endl;
 }
 
@@ -61,12 +102,9 @@
 	// texture
 	int texId;
-
 	str.read(reinterpret_cast<char *>(&texId), sizeof(int));
-	//cout << "texid: " << texId << endl;
 
 	if (texId >= 0)
-	{
 		mat->SetTexture(mTextureTable[texId]);
-	}
+	
 
 	// material
@@ -99,5 +137,4 @@
 
 	return app;*/
-
 	return mat;
 }
@@ -156,5 +193,23 @@
 
 
-bool BinaryLoader::Load(const std::string &filename, SceneEntityContainer &geometry)
+void BinaryLoader::LoadSceneEntities(ifstream &str, SceneEntityContainer &entities)
+{
+	int entityCount;
+	str.read(reinterpret_cast<char *>(&entityCount), sizeof(int));
+
+	entities.resize(entityCount);
+
+	for (int i = 0; i < entityCount; ++ i)
+	{
+		SceneEntity *ent = LoadSceneEntity(str);
+		ent->id = i;
+		entities[i] = ent;
+	}
+
+	cout << "loaded " << entityCount << " scene entities" << endl;
+}
+
+
+bool BinaryLoader::Load(const std::string &filename, SceneEntityContainer &entities)
 {
 	//clear_textures(); // clear the texture table
@@ -166,42 +221,17 @@
 		return false;
 
+	cout << "loading textures" << endl;
+	
 	// load the texture table
 	LoadTextures(istr);
 
-	// #shapes
-	int shapeCount;
-	istr.read(reinterpret_cast<char *>(&shapeCount), sizeof(int));
-
-	geometry.resize(shapeCount);
-
-	for (size_t i = 0; i < geometry.size(); ++ i)
-		geometry[i] = NULL;
-	
-
-	int progress = 0;
-
-	for (int i = 0; i < shapeCount; ++ i)
-	{
-		//int id;istr.read(reinterpret_cast<char *>(&id), sizeof(int));
-		SceneEntity *ent = LoadSceneEntity(istr);
-		ent->id = i;
-
-		geometry[i] = ent;
-		
-		int p = (i + 1) * 100 / shapeCount;
-		
-		if (p >= progress)
-		{
-			cout << "% loaded: " << p << endl;
-			progress += 10;
-		}
-	}
-
-	for (size_t i = 0; i < geometry.size(); ++ i)
-	{
-		if (!geometry[i])
-			Debug << "error: index " << i << " missing" << endl;
-	}
-
+	cout << "loading shapes (geometry + materials)" << endl;
+
+	// load the shapees
+	LoadShapes(istr);
+
+	cout << "loading scene entites" << endl;
+	LoadSceneEntities(istr, entities);
+	
 	cout << "bin loading finished" << endl;
 
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/FrustumCullingTraverser.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/FrustumCullingTraverser.cpp	(revision 2763)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/FrustumCullingTraverser.cpp	(revision 2764)
@@ -15,9 +15,8 @@
 void FrustumCullingTraverser::Render()
 {
+	mStats.Reset();
 	mRenderState->mTexturesEnabled = false;
-	mDistanceQueue.push(mBvh->GetRoot());
+	EnqueueNode(mBvh->GetRoot());
 
-
-	int traversed = 0;
 	while (!mDistanceQueue.empty())
 	{
@@ -27,5 +26,4 @@
 		// interesting for the visualization, so rest and set
 		node->SetVisible(false);
-		//mNumTraversedNodes ++;
 
 		if (mBvh->IsWithinViewFrustum(node))
@@ -34,16 +32,12 @@
 			// so set it also here
 			//node->SetLastVisited(mFrameID);
-			//node->SetVisible(true);
-			++ traversed;
+			node->SetVisible(true);
 			TraverseNode(node);
 		}
 		else
 		{
-			//mNumFrustumCulledNodes ++;
+			mStats.mNumFrustumCulledNodes ++;
 		}
-		//cout << "intersect: " << intersect << " bx " << node->GetBox() << endl;
 	}
-	
-	//std::cout << "traversed: " << traversed << std::endl;
 }
 
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/RenderTraverser.h
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/RenderTraverser.h	(revision 2763)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/RenderTraverser.h	(revision 2764)
@@ -7,5 +7,5 @@
 #include "Bvh.h"
 #include "OcclusionQuery.h"
-
+#include "Camera.h"
 
 namespace CHCDemo
@@ -19,24 +19,17 @@
 struct TraversalStatistics
 {
-	friend class RenderTraverser;
+public:
 
-public:
+	void Reset();
 
 	//////////
 	//-- several statistics for a rendering pass
 
-	long GetRenderTime();
-	int GetNumTraversedNodes();
-	int GetNumQueryCulledNodes();
-	int GetNumFrustumCulledNodes();
-	int GetNumRenderedGeometry();
-	
-protected:
-
-	// statistics
 	int mNumTraversedNodes;
 	int mNumQueryCulledNodes;
 	int mNumFrustumCulledNodes;
 	int mNumRenderedGeometry;
+	int mNumRenderedTriangles;
+	int mNumIssuedQueries;
 
 	long mRenderTime;
@@ -52,5 +45,5 @@
 {
 public:
-	//enum {RENDER_CULL_FRUSTUM, RENDER_STOP_AND_WAIT, RENDER_COHERENT, NUM_RENDERMODES};
+	enum {CULL_FRUSTUM, STOP_AND_WAIT, CHC, NUM_RENDERMODES};
 
 	RenderTraverser();
@@ -71,7 +64,4 @@
 	*/
 	void SetCamera(Camera *cam)  {mCamera = cam;}
-	/** sets view projection matrix
-	*/
-	//void SetProjViewMatrix(Matrix4x4 const &projViewMatrix);
 	/** Sets visible pixels threshold for visibility classification
 	*/
@@ -92,4 +82,5 @@
 	void RenderFrustum();
 
+	const TraversalStatistics &GetStats() const { return mStats; }
 
 protected:
@@ -120,4 +111,6 @@
 	void Switch2GLQueryState();
 
+	inline bool IntersectsNearPlane(BvhNode *node) const {return mBvh->GetDistance(node) < mCamera->GetNear();}
+
 	void EnqueueNode(BvhNode *node);
 
@@ -129,12 +122,6 @@
 	//-- members
 
-	// /the current clip planes of the view frustum
-	//VecPlane mClipPlanes;
-	/// the indices of the np-vertices of the bounding box for view frustum culling
-	//int mNPVertexIndices[12];
-
 	/// the current camera
 	Camera *mCamera;
-	//Matrix4x4 mProjViewMatrix;
 	/// the root of the scene hierarchy
 	Bvh *mBvh;
@@ -144,7 +131,5 @@
 	int mFrameID;
 	int mVisibilityThreshold;
-	
-	//unsigned int *mOcclusionQueries;
-	int mCurrentQueryIdx;
+
 	bool mIsQueryMode;
 	
@@ -155,4 +140,6 @@
 
 	QueryHandler mQueryHandler;
+
+	TraversalStatistics mStats;
 };
 
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/SceneQuery.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/SceneQuery.cpp	(revision 2764)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/SceneQuery.cpp	(revision 2764)
@@ -0,0 +1,100 @@
+#include "SceneQuery.h"
+#include "glInterface.h"
+#include "Vector3.h"
+#include "Camera.h"
+
+
+void startil();
+void stopil();
+
+
+namespace CHCDemo
+{
+
+using namespace std;
+
+
+const static int viewport[4] = {0, 0, 512, 512};
+//static DepthComponent<float> *sDepth = NULL;
+
+
+
+SceneQuery::SceneQuery(const AxisAlignedBox3 &sceneBox): 
+mSceneBox(sceneBox)
+{
+	Prepare();
+}
+
+
+bool SceneQuery::CalcIntersection(Vector3 &pt)
+{
+	int px = (pt.x - mSceneBox.Min(0)) * (viewport[2] - 1) / mSceneBox.Size(0);
+	int py = (pt.y - mSceneBox.Min(2)) * (viewport[3] - 1) /  mSceneBox.Size(2);
+
+	const float d = 1.0f;// - sDepth->getPixel(px, py);
+
+	if (d > 0.0f)
+	{
+		pt.z = mSceneBox.Size(2) * d + mSceneBox.Min(2);
+		cout << "new depth " << pt.z << " (" << d << ")" << endl;
+
+		return true;
+	}
+
+	return false;
+}
+
+void SceneQuery::Prepare()
+{
+	cout << "Preparing scene queries" << endl;
+
+	// center camera on "highest" point
+	Vector3 pos;
+
+	pos.x = mSceneBox.Center(0);
+	pos.y = mSceneBox.Max(1);
+	pos.z = mSceneBox.Center(2);
+
+	Camera *orthoCam = new Camera();
+	//orthoCam->SetOrtho(true);
+
+	// contain match scene bounding box;
+
+	// for ortho cam this is the width
+	const Vector3 len = mSceneBox.Size();
+/*
+	orthoCam->SetFov(len.x);
+	orthoCam->SetAspect(len.x / len.y);
+
+	orthoCam->SetNear(0.0f);
+	orthoCam->SetFar(len.z);
+
+	orthoCam->SetPosition(pos);
+
+	OUT1("fov: " << orthoCam->GetFov());
+	OUT1("near: " << orthoCam->GetNear());
+	OUT1("far: " << orthoCam->GetFar());
+	OUT1("aspect: " << orthoCam->GetAspect());
+
+	OUT1("pos: " << orthoCam->GetPosition());
+	OUT1("view: " << orthoCam->GetViewDirection());
+	OUT1("up: " << orthoCam->GetViewUpVector());
+
+	const float pitch = 0;
+	const float yaw = YA_PI * 0.5f;
+	
+	OffscreenRenderArea *of = new OffscreenRenderArea();
+
+	of->Init(viewport[2], viewport[3]);
+	of->SetRenderAction(new GLRenderAction);
+	
+	of->SetCamera(orthoCam);
+	of->SetSceneRoot(mSceneRoot);
+	
+	of->Render();
+
+	sDepth = of->GetDepthFloat();
+	*/
+}
+
+}
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.h
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.h	(revision 2763)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.h	(revision 2764)
@@ -505,5 +505,8 @@
 		note that negative values can appear because culling is done only afterwards
 	*/
-	float CalcDistance(BvhNode *node) const;
+	void CalcDistance(BvhNode *node) const;
+	/** Returns the stored distance.
+	*/
+	float GetDistance(BvhNode *node) const  { return node->mDistance; }
 	/** Pulls up the last visited classification in the bvh.
 	*/
@@ -544,6 +547,11 @@
 	*/
 	const BvhStats &GetBvhStats() const {return mBvhStats;}
-	
+	/** Renders the geometry contained in this node.
+	*/
 	int Render(BvhNode *node, RenderState *state);
+	/** Returns number of 'virtual' nodes in the hierarchy, i.e.
+		the number of nodes actually used for traversal.
+	*/
+	int GetNumVirtualNodes() const  { return mNumVirtualNodes; }
 
 
@@ -602,4 +610,6 @@
 
 	void RenderBoundingBoxImmediate(const AxisAlignedBox3 &box);
+
+
 
 	////////////////////////
@@ -645,4 +655,6 @@
 	AxisAlignedBox3 mBox;
 
+	int mNumVirtualNodes;
+
 	//////////////
 
Index: GTP/trunk/App/Demos/Vis/CHC_revisited/Camera.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/CHC_revisited/Camera.cpp	(revision 2762)
+++ GTP/trunk/App/Demos/Vis/CHC_revisited/Camera.cpp	(revision 2764)
@@ -29,7 +29,10 @@
 	mDirection.Normalize();
 
-	Vector3 side = CrossProd(Vector3(0, 1, 0), mDirection);
+	//Vector3 side = CrossProd(Vector3(0, 1, 0), mDirection);
+	Vector3 side = CrossProd(Vector3(0, 0, 1), mDirection);
+	
 	mUp = -Normalize(CrossProd(side, mDirection));
 	mRight = -Normalize(CrossProd(mDirection, mUp));
+
 
 	float k = tan(mFovy/2);
@@ -53,9 +56,16 @@
 
 
+void Camera::SetNear(float nearDist) 
+{
+	mNear = nearDist;
+}
+
+
 void Camera::LookInBox(const AxisAlignedBox3 &box)
 {
-	mDirection = Vector3(0, 0, 1);
+	//mDirection = Vector3(0, 0, 1);
+	mDirection = Vector3(0, 1, 0);
 	mPosition = box.Center();
-	mPosition.y += 50;
+	mPosition.z = box.Min(2) + 0.9f * box.Size(2);
 
 	Precompute();
@@ -65,5 +75,5 @@
 void Camera::LookAtBox(const AxisAlignedBox3 &box)
 {
-	mDirection = Vector3(0, 0, box.Min().z - box.Max().z);
+	mDirection = Vector3(0, box.Min().y - box.Max().y, 0);
 	mPosition = Vector3(0);//box.Max() - mDirection;
 
