Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SceneEntity.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SceneEntity.h	(revision 3251)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SceneEntity.h	(revision 3259)
@@ -44,5 +44,5 @@
 	/** Returns number of shapes in vector.
 	*/
-	inline int GetNumShapes();
+	inline int GetNumShapes() const;
 	/** Set pointer to the geometry
 	*/
@@ -118,7 +118,8 @@
 		this id is -1 or their id matches this id.
 	*/
-	static void SetGlobalVisibleId(int id);
-
-	static int GetGlobalVisibleId();
+	static void SetCurrentVisibleId(int id);
+
+	static int GetCurrentVisibleId();
+
 
 protected:
@@ -151,12 +152,12 @@
 	/// the center of gravity of this entity
 	Vector3 mCenter;
-	
+	/// generic id
 	int mId;
-
+	/// used to find out if this scene entity is in the current pvs
+	int mVisibleId;
+	static int sCurrentVisibleId;
+	/// if LODs are used for rendering: otherwise we always take the highest lod
 	static bool sUseLODs;
-	static int sCurrentId;
-
-	int mVisibleId;
-	static int sVisibleId;
+
 };
 
@@ -198,5 +199,5 @@
 
 
-inline int SceneEntity::GetNumShapes()
+inline int SceneEntity::GetNumShapes() const
 {
 	return (int)mShapes.size(); 
@@ -216,13 +217,13 @@
 
 
-inline void SceneEntity::SetGlobalVisibleId(int id)
-{
-	sVisibleId = id;
-}
-
-
-inline int SceneEntity::GetGlobalVisibleId()
-{
-	return sVisibleId;
+inline void SceneEntity::SetCurrentVisibleId(int id)
+{
+	sCurrentVisibleId = id;
+}
+
+
+inline int SceneEntity::GetCurrentVisibleId()
+{
+	return sCurrentVisibleId;
 }
 
@@ -236,5 +237,5 @@
 inline bool SceneEntity::IsVisible() const
 {
-	return (sVisibleId == -1) || (mVisibleId == sVisibleId);
+	return (sCurrentVisibleId == -1) || (mVisibleId == sCurrentVisibleId);
 }
 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Geometry.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Geometry.h	(revision 3126)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Geometry.h	(revision 3259)
@@ -18,5 +18,4 @@
 {
 	friend class ResourceManager;
-	friend class EntityMerger;
 
 public:
@@ -30,5 +29,5 @@
 			 Texcoord2 *texcoords, 
 			 int numVertices, 
-			 bool delData,
+			 bool deleteData,
 			 Vector3 *tangents);
 	/** Detructor destroying the opengl resources.
@@ -48,4 +47,17 @@
 	inline bool HasTexture() const { return mHasTexture; }
 	
+
+	//////////////
+	//-- these functions return the specified data
+	//-- only if deleteData has not been switched on in the consruction
+
+	Vector3 *GetVertices(int &numVertices) const;
+
+	Vector3 *GetNormals(int &numNormals) const;
+
+	Vector3 *GetTangents(int &numTangents) const;
+
+	Texcoord2 *GetTexCoords(int &numTexCoords) const;
+
 
 protected:
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/BvhExporter.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/BvhExporter.h	(revision 3259)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/BvhExporter.h	(revision 3259)
@@ -0,0 +1,36 @@
+#ifndef __PVS_H
+#define __PVS_H
+
+#include "common.h"
+#include "Bvh.h"
+#include <map>
+
+
+namespace CHCDemoEngine
+{
+
+/** Class for exporting bvh to Jiris format
+*/
+class BvhExporter
+{
+public:
+
+	bool ExportToFile(const std::string &filename, Bvh *bvh);
+
+
+protected:
+
+	void ConstructTriangleRangeMap(Bvh *bvh, BvhNode *node, int &first, int &last);
+
+	void SaveNode(BvhNode *node, FILE *fw);
+
+
+	//////////////
+
+	std::map<BvhNode *, std::pair<int, int> > mTriangleRangeMap;
+};
+
+
+}
+
+#endif
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Pvs.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Pvs.h	(revision 3243)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Pvs.h	(revision 3259)
@@ -3,11 +3,14 @@
 
 #include "common.h"
-
+#include "Bvh.h"
 
 namespace CHCDemoEngine
 {
 
-/** Template class representing the Potentially Visible Set (PVS) 
-	mainly from a view cell, but also e.g., from objects.
+class BvhNode;
+class Bvh;
+
+
+/** Class representing the Potentially Visible Set (PVS) from a view cell.
 */
 class Pvs
@@ -16,15 +19,17 @@
 public:
 
-	Pvs() {};
+	//Pvs() {}
 
-	void Clear() { mEntries.clear(); }
+	void Clear();
 
-	bool Empty() const { return mEntries.empty(); }
+	bool Empty() const;
 
-	SceneEntity *GetEntry(int i) const { return mEntries[i]; }
+	void AddEntry(Bvh *bvh, BvhNode *node);
 
-	int Size() { return (int)mEntries.size(); }
+	int GetSize() const;
 
-	void AddEntry(SceneEntity *ent) { mEntries.push_back(ent); }
+	inline SceneEntity *GetEntry(int i) const;
+
+	inline void AddEntry(SceneEntity *ent);
 
 
@@ -35,4 +40,36 @@
 };
 
+
+inline SceneEntity *Pvs::GetEntry(int i) const 
+{
+	return mEntries[i]; 
+}
+
+
+inline void Pvs::AddEntry(SceneEntity *ent) 
+{
+	mEntries.push_back(ent); 
+}
+
+
+inline int Pvs::GetSize() const
+{ 
+	return (int)mEntries.size(); 
+}
+
+
+inline void Pvs::AddEntry(Bvh *bvh, BvhNode *node) 
+{
+	int geometrySize;
+	SceneEntity **entities;
+	entities = bvh->GetGeometry(node, geometrySize);
+
+	for (int i = 0; i < geometrySize; ++ i)
+	{
+		AddEntry(entities[i]);
+	}
+}
+
+
 }
 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/RenderTraverser.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/RenderTraverser.cpp	(revision 3258)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/RenderTraverser.cpp	(revision 3259)
@@ -235,5 +235,4 @@
 {
 	mUseTightBounds = useTightBounds;
-	//cout << "using tight bounds: " << useTightBounds << endl;
 }
 
@@ -296,5 +295,5 @@
 {
 	// no invisible objects
-	if (SceneEntity::GetGlobalVisibleId() == -1) return true;
+	if (SceneEntity::GetCurrentVisibleId() == -1) return true;
 
 	int geometrySize;
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Geometry.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Geometry.cpp	(revision 3154)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Geometry.cpp	(revision 3259)
@@ -218,3 +218,31 @@
 
 
-}
+Vector3 *Geometry::GetVertices(int &numVertices) const
+{
+	numVertices = mNumVertices;
+	return mVertices;
+}
+
+
+Vector3 *Geometry::GetNormals(int &numNormals) const
+{
+	numNormals = mNumVertices;
+	return mNormals;
+}
+
+
+Vector3 *Geometry::GetTangents(int &numTangents) const
+{
+	numTangents = mHasTangents ? mNumVertices : 0;;
+	return mTangents;
+}
+
+
+Texcoord2 *Geometry::GetTexCoords(int &numTexCoords) const
+{
+	numTexCoords = mHasTangents ? mNumVertices : 0;;
+	return mTexCoords;
+}
+
+
+}
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/VisibilitySolutionLoader.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/VisibilitySolutionLoader.cpp	(revision 3258)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/VisibilitySolutionLoader.cpp	(revision 3259)
@@ -151,12 +151,5 @@
 			BvhNode *node = nodes[objectId];
 
-			int geometrySize;
-			SceneEntity **entities;
-			entities = bvh->GetGeometry(node, geometrySize);
-
-			for (int k = 0; k < geometrySize; ++ k)
-			{
-				mViewCells[i]->mPvs.AddEntry(entities[k]);
-			}
+			mViewCells[i]->mPvs.AddEntry(bvh, node);
 		}
 	}
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SceneEntityConverter.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SceneEntityConverter.cpp	(revision 3245)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SceneEntityConverter.cpp	(revision 3259)
@@ -39,5 +39,5 @@
 	}
 
-	Geometry *geom = new Geometry(vertices, normals, NULL, 36, false, NULL);
+	Geometry *geom = new Geometry(vertices, normals, NULL, 36, true, NULL);
 
 	Shape *shape = new Shape(geom, mat);
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ResourceManager.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ResourceManager.cpp	(revision 3238)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ResourceManager.cpp	(revision 3259)
@@ -383,5 +383,5 @@
 	}
 
-	const bool delGeometry = false;
+	const bool delGeometry = true;
 	return new Geometry(vertices, normals, texcoords, vertexCount, delGeometry, NULL);//tangents);
 }
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.h	(revision 3243)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.h	(revision 3259)
@@ -30,4 +30,5 @@
 	friend class Bvh;
 	friend class BvhLoader;
+	friend class BvhExporter;
 	friend class mygreaterdistance;
 
@@ -422,4 +423,5 @@
 	friend class Bvh;
 	friend class BvhLoader;
+	friend class BvhExporter;
 
 public:
@@ -474,4 +476,5 @@
 };
 
+
 typedef std::priority_queue<BvhNode *, std::vector<BvhNode *>, GtDistance> TraversalQueue;
 
@@ -482,4 +485,5 @@
 {
 	friend class BvhLoader;
+	friend class BvhExporter;
 
 	/** Bvh properties
@@ -524,4 +528,7 @@
 	*/
 	inline int GetNumNodes() const;
+	/** Counts the number of bvh nodes under this node
+	*/
+	int CountNumNodes(BvhNode *node) const;
 	/** Returns number of bvh leaves.
 	*/
@@ -557,4 +564,6 @@
 	*/
 	void CollectNodes(BvhNode *node, BvhNodeContainer &nodes, int depth);
+	/** Collect all child nodes.
+	*/
 	void CollectNodes(BvhNode *node, BvhNodeContainer &nodes);
 	/** Collect the "physical" leaves of the hierarchy
@@ -614,5 +623,5 @@
 	*/
 	void ResetNodeClassifications();
-	/** Count triangles the node contains.
+	/** Counts the number of triangles contained in this node.
 	*/
 	int CountTriangles(BvhNode *node) const;
@@ -654,5 +663,5 @@
 	////////////////////////////
 
-	/** Returns stats.
+	/** Returns statistics.
 	*/
 	const BvhStats &GetBvhStats() const { return mBvhStats; }
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/PvsCollectionRenderer.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/PvsCollectionRenderer.cpp	(revision 3258)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/PvsCollectionRenderer.cpp	(revision 3259)
@@ -23,4 +23,6 @@
 void PvsCollectionRenderer::Traverse()
 {
+	mPIS.clear();
+
 	////////////
 	//-- part1: do frustum culling + pvs
@@ -49,4 +51,7 @@
 	}
 
+	int pisSize = (int)mPIS.size();
+
+
 	////////////
 	//-- part2: test the potentially invisible nodes
@@ -57,5 +62,6 @@
 
 	OcclusionQuery *query = mQueryHandler.RequestQuery();
-	
+	query->Reset();
+
 	int querySize = 50;
 
@@ -87,5 +93,7 @@
 	probablyVisibleNodes.clear();
 	
-	
+	int qsize = (int)queries.size();
+	int fqueries = 0;
+
 	// get query results: collect probably visible nodes
 	while (!queries.empty())
@@ -98,4 +106,6 @@
 		if (visiblePixels > 0)
 		{
+			++ fqueries;
+
 			BvhNodeContainer::const_iterator bit, bit_end = q->GetNodes().end();
 
@@ -109,10 +119,12 @@
 	}
 
+	//cout << "probably visible: " << fqueries << " of " << qsize << " (" << (int)probablyVisibleNodes.size() << " of " << pisSize << " nodes)" << endl;
+
+
 
 	//////////////
 	//-- part4: test probably visible nodes individually, update pvs of current view cell
 
-	return;
-	//if (!mViewCell) return;
+	if (!mViewCell) return;
 	
 	// query all nodes individually
@@ -122,5 +134,15 @@
 	{
 		BvhNode *n = *bit;
-		queries.push(IssueOcclusionQuery(n));
+
+		// node intersects near plane => 
+		// add immediately because testing the bb could fail
+		if (mBvh->IntersectsNearPlane(n))
+		{
+			mViewCell->mPvs.AddEntry(mBvh, n);
+		}
+		else
+		{
+			queries.push(IssueOcclusionQuery(n));
+		}
 	}
 
@@ -132,16 +154,8 @@
 	
 		const int visiblePixels = q->GetQueryResult();
-
+		
 		if (visiblePixels > 0)
 		{
-			// add node to pvs
-			int geometrySize;
-			SceneEntity **entities;
-			entities = mBvh->GetGeometry(q->GetFrontNode(), geometrySize);
-
-			for (int i = 0; i < geometrySize; ++ i)
-			{
-				mViewCell->mPvs.AddEntry(entities[i]);
-			}
+			mViewCell->mPvs.AddEntry(mBvh, q->GetFrontNode());
 		}
 	}
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.cpp	(revision 3245)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.cpp	(revision 3259)
@@ -327,4 +327,32 @@
 
 
+int Bvh::CountNumNodes(BvhNode *node) const
+{
+	int numNodes = 0;
+
+	stack<BvhNode *> tStack;
+
+	tStack.push(node);
+
+	while (!tStack.empty())
+	{
+		BvhNode *node = tStack.top();
+		tStack.pop();
+
+		++ numNodes;
+
+		if (!node->IsLeaf())
+		{
+			BvhInterior *interior = static_cast<BvhInterior *>(node);
+
+			tStack.push(interior->mFront);
+			tStack.push(interior->mBack);
+		}
+	}
+
+	return numNodes;
+}
+
+
 void Bvh::CollectNodes(BvhNode *node, BvhNodeContainer &nodes)
 {
@@ -770,5 +798,5 @@
 	static BvhNodeContainer nodes;
 	nodes.clear();
-	//nodes.reserve(GetNumNodes());
+
 	CollectNodes(mDynamicRoot, nodes);
 
@@ -1528,5 +1556,5 @@
 	mDynamicRoot->mParent = mRoot;
 }
-
-
-}
+  
+
+}
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SceneEntity.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SceneEntity.cpp	(revision 3245)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SceneEntity.cpp	(revision 3259)
@@ -15,7 +15,7 @@
 {
 
-int SceneEntity::sCurrentId = 0;
+int sCurrentId = 0;
 bool SceneEntity::sUseLODs = true;
-int SceneEntity::sVisibleId = -1;
+int SceneEntity::sCurrentVisibleId = -1;
 
 SceneEntity::SceneEntity(Transform3 *trafo): 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/StopAndWaitTraverser.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/StopAndWaitTraverser.cpp	(revision 3065)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/StopAndWaitTraverser.cpp	(revision 3259)
@@ -22,4 +22,10 @@
 		mDistanceQueue.pop();
 	
+		if (1 && !IsNodeGeometryVisible(node, 10))
+		{
+			node->SetVisible(false);
+			continue;
+		}
+
 		if (mBvh->IsWithinViewFrustum(node))
 		{
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp	(revision 3258)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp	(revision 3259)
@@ -1613,5 +1613,5 @@
 		// enable / disable view cells
 		usePvs = !usePvs;
-		if (!usePvs) SceneEntity::SetGlobalVisibleId(-1);
+		if (!usePvs) SceneEntity::SetCurrentVisibleId(-1);
 		break;
 	default:
@@ -2598,7 +2598,7 @@
 	int numTriangles = 0;
 
-	SceneEntity::SetGlobalVisibleId(globalVisibleId);
-
-	for (int i = 0; i < viewCell->mPvs.Size(); ++ i)
+	SceneEntity::SetCurrentVisibleId(globalVisibleId);
+
+	for (int i = 0; i < viewCell->mPvs.GetSize(); ++ i)
 	{
 		SceneEntity *ent = viewCell->mPvs.GetEntry(i);
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/CHCPlusPlusTraverser.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/CHCPlusPlusTraverser.cpp	(revision 3258)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/CHCPlusPlusTraverser.cpp	(revision 3259)
@@ -119,7 +119,11 @@
 			mDistanceQueue.pop();
 	
-			if (1 && !IsNodeGeometryVisible(node, 10))
-			{
+			if (!IsNodeGeometryVisible(node, 10))
+			{
+				node->SetLastVisitedFrame(mFrameId);
 				node->SetVisible(false);
+
+				mBvh->MakeParentsVisible(node);
+
 				continue;
 			}
@@ -148,5 +152,5 @@
 
 					// node was not recently tested => reset flag 
-					if (node->GetLastVisitedFrame() != mFrameId - 1)
+					if (node->GetLastVisitedFrame() != (mFrameId - 1))
 					{
 						node->SetTimesTestedInvisible(0);
@@ -259,7 +263,11 @@
 		// node was already part of a mulitquery => avoid recursion
 		if (node->GetLastQueriedFrame() == mFrameId)
+		{
 			newPBatch = 0;
+		}
 		else
+		{
 			newPBatch *= mVisibilityPredictor.GetProbability(node);
+		}
 
 		if (query->GetNodes().empty())
@@ -274,6 +282,5 @@
 		}
 
-		if (newBatchVal <= maxBatchVal)
-			break;
+		if (newBatchVal <= maxBatchVal)	break;
 
 		iqueue.pop_back();
@@ -304,5 +311,7 @@
 
 		while (!mIQueue.empty())
+		{
 			mQueryQueue.push(GetNextMultiQuery(mIQueue));
+		}
 	}
 	else
@@ -311,5 +320,7 @@
 
 		for (it = mIQueue.begin(); it != it_end; ++ it)
+		{
 			mQueryQueue.push(IssueOcclusionQuery(*it));
+		}
 
 		mIQueue.clear();
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Pvs.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Pvs.cpp	(revision 3242)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Pvs.cpp	(revision 3259)
@@ -1,5 +1,4 @@
 #include "Pvs.h"
 #include "Timer/PerfTimer.h"
-#include "common.h"
 #include <iostream>
 
@@ -8,57 +7,16 @@
 {
 
-void TestPvsPerformance()
-{
-	//  Pvs pvs(15000);
-	const int prange=10000;
-	Pvs pvs[prange+1];
-	// test PVS performance
-	const int num = 100000000;
-	const int range = 50000;
-	PerfTimer timer;
-	timer.Entry();
-
-	for (int i=0; i < num; i++)
-	{
-		int id = (int)Random(range);
-		int pid = (5*num)%prange;
-		pvs[pid].Insert(id, (float)i);
-		if (i%1000000 == 0) {
-			cout<<i/1000000<<" M"<<endl;
-			cout<<"size = "<<pvs[pid].GetSize()/(1000*1000)<<"M"<<endl;
-			//	  cout << "bucket_count: " << pvs.entries.bucket_count() << endl;
-		}
-	}
-	timer.Exit();
+void Pvs::Clear() 
+{ 
+	mEntries.clear(); 
+}
 
 
-	cout<<"Pvs insert speed = "<<num/float(1000*1000*timer.TotalTime())<<
-		"M entries/s\n";
-	cout<<"Memory usage "<<pvs[0].GetMemoryUsage()<<" bytes"<<endl;
-
-	int counter = 0;
-	timer.Entry();
-	PvsIterator it(pvs[0]);
-	for (; it.HasMoreEntries(); it.Next()) 
-	{
-		++ counter;
-	}
-	timer.Exit();
-
-	cout<<"Pvs count = "<<counter<<endl;
-	cout<<"Pvs iteration speed = "<<pvs[0].GetSize()/float(1000*1000*timer.TotalTime())<<
-		"M entries/s\n";
-
-	counter = 0;
-	timer.Entry();
-	PvsTimeIterator tit(pvs[0], 400);
-	for (; tit.HasMoreEntries(); tit.Next()) {
-		counter++;
-	}
-	timer.Exit();
-	cout<<"Pvs time count = "<<counter<<endl;
-	cout<<"Pvs iteration speed = "<<pvs[0].GetSize()/(1024*1024*timer.TotalTime())<<
-		"M entries/s\n";
+bool Pvs::Empty() const 
+{ 
+	return mEntries.empty(); 
 }
 
+
+
 }
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/BvhExporter.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/BvhExporter.cpp	(revision 3259)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/BvhExporter.cpp	(revision 3259)
@@ -0,0 +1,138 @@
+#include "BvhExporter.h"
+
+using namespace std;
+
+// MAGIC of all bin exports
+#ifndef MAGIC 
+#define MAGIC 0x827923
+#endif
+
+#define BVH_VERSION 2.1
+
+namespace CHCDemoEngine
+{
+
+static int currentIdx = 0;
+
+
+void BvhExporter::SaveNode(BvhNode *node, FILE *fw) 
+{
+	if (!node) return;
+	
+	int buffer[4];
+
+	if (node->IsLeaf()) 
+	{
+		BvhLeaf *leaf = (BvhLeaf*)node;
+		
+		buffer[0] = mTriangleRangeMap[leaf].first;
+		buffer[1] = mTriangleRangeMap[leaf].second;
+		buffer[2] = -1;//leaf->GetAxis();
+		buffer[3] = currentIdx ++;
+
+		fwrite(buffer, sizeof(int), 4, fw);
+	}
+	else
+	{
+		BvhInterior *interior = (BvhInterior *)node;
+		
+		buffer[0] = interior->mFirst;
+		buffer[1] = interior->mLast;
+		buffer[2] = 0;//interior->mAxis;
+		buffer[3] = currentIdx ++;
+
+		fwrite(buffer, sizeof(int), 4, fw);
+		
+		SaveNode(interior->GetFront(), fw);
+		SaveNode(interior->GetBack(), fw);
+	}
+}
+
+
+void BvhExporter::ConstructTriangleRangeMap(Bvh *bvh, 
+											BvhNode *node,
+											int &first, 
+											int &last)
+{
+	if (!node->IsLeaf())
+	{
+		int m;
+		BvhInterior *interior = static_cast<BvhInterior *>(node);
+
+		ConstructTriangleRangeMap(bvh, interior->GetFront(), first, m);
+		ConstructTriangleRangeMap(bvh, interior->GetBack(), m, last);
+
+		mTriangleRangeMap[node] = pair<int, int>(first, last);
+	}
+	else
+	{
+		//first = currentIdx;
+		last = first + bvh->CountTriangles(node);
+		//currentIdx = last;
+
+		mTriangleRangeMap[node] = pair<int, int>(first, last);
+	}
+}
+
+
+bool BvhExporter::ExportToFile(const string &filename, Bvh *bvh)
+{
+	 cout << "Info: Exporting to file '" << filename.c_str() << "'" << endl;
+  
+	 FILE *fw = fopen(filename.c_str(), "wb");
+
+	 if (fw == NULL) 
+	 {
+		 cerr << "Error: Cannot open file for writing" << endl;
+		 return false;
+	 }
+
+	 int buffer[6];
+	 buffer[0] = MAGIC;
+	 buffer[1] = BVH_VERSION * 1000;
+	 //buffer[2] = triangles.size();
+	 buffer[3] = 0; // construction method
+	 buffer[4] = 1; // termination leaves
+	 buffer[5] = bvh->CountNumNodes(bvh->GetStaticRoot());
+
+	 fwrite(buffer, sizeof(int), 6, fw);
+
+	 int first, last;
+	 ConstructTriangleRangeMap(bvh, bvh->GetStaticRoot(), first, last);
+
+	 BvhNodeContainer nodes;
+	 bvh->CollectNodes(bvh->GetStaticRoot(), nodes);
+
+	 vector<int> triangles;
+
+	 BvhNodeContainer::const_iterator it, it_end = nodes.end();
+
+	 for (it = nodes.begin(); it != it_end; ++ it)
+	 {
+		 BvhNode *node = *it;
+
+		 int f = mTriangleRangeMap[node].first;
+		 int b = mTriangleRangeMap[node].second;
+
+		 for (int i = f; i < b; ++ i)
+		 {
+			 triangles.push_back(i);
+		 }
+	 }
+
+	 // export sorted triangle IDs
+	 for (int i = 0; i < triangles.size(); ++i) 
+	 {
+		 fwrite(&triangles[i], sizeof(int), 1, fw);
+	 }
+
+	 SaveNode(bvh->GetStaticRoot(), fw);
+	 
+	 cout << "successfully exported bvh" << endl;
+	 fclose(fw);
+
+	 return true;
+}
+
+
+}
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/FriendlyCulling.vcproj
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/FriendlyCulling.vcproj	(revision 3258)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/FriendlyCulling.vcproj	(revision 3259)
@@ -160,4 +160,12 @@
 			>
 			<File
+				RelativePath=".\src\BvhExporter.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\BvhExporter.h"
+				>
+			</File>
+			<File
 				RelativePath=".\src\BvhLoader.cpp"
 				>
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/default.env
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/default.env	(revision 3258)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/default.env	(revision 3259)
@@ -99,5 +99,5 @@
 
 # use full resolution ssao (vs. half resoltion)
-ssaoUseFullResolution=1
+ssaoUseFullResolution=0
 # ssao kernel radius
 #ssaoKernelRadius=8e-1f
@@ -115,10 +115,9 @@
 ## powerplant options
 
-#filename=PowerPlantM
-
-#keyForwardMotion=500.0f
-#mouseMotion=3.0f
-#visibilitySolution=power-plant-2c-xx-1000b-pgv2
-#camPosition=-1320.57 -6306.34 3603
-#camDirection=0.292156 0.9556 0.0383878
-#viewCellsScaleFactor=0.05f
+filename=PowerPlantM
+keyForwardMotion=500.0f
+mouseMotion=3.0f
+visibilitySolution=power-plant-2c-xx-1000b-pgv2
+camPosition=-1320.57 -6306.34 3603
+camDirection=0.292156 0.9556 0.0383878
+viewCellsScaleFactor=0.05f
