Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.h	(revision 2954)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.h	(revision 3053)
@@ -7,5 +7,5 @@
 #include "Vector3.h"
 #include "AxisAlignedBox3.h"
-//#include "SceneEntity.h"
+
 
 
@@ -343,5 +343,5 @@
 bool BvhNode::Empty() const 
 { 
-	return mFirst == -1; 
+	return (mFirst == -1); 
 }
 
@@ -637,4 +637,25 @@
 
 
+	/////////////////////////////
+
+	int SortTriangles(BvhLeaf *leaf, 
+		              int axis, 
+					  float position,
+					  SceneEntityContainer &entities);
+
+	int SortTrianglesSpatialMedian(BvhLeaf *leaf, 
+		                           int axis,
+								   SceneEntityContainer &entities);
+
+	BvhNode *SubdivideLeaf(BvhLeaf *leaf, 
+		                   int parentAxis, 
+						   SceneEntityContainer &entities);
+
+	/** Recompute the dynamic branch of the hierarchy.
+	*/
+	void UpdateDynamicBranch();
+
+	inline bool TerminationCriteriaMet(BvhLeaf *leaf) const;
+
 
 	////////////////////////
@@ -686,4 +707,12 @@
 	/// indices used for draw array rendering
 	unsigned int *mIndices;
+
+
+	///////////
+	//-- termination criteria for dynamic branch
+
+	int mMaxDepthForDynamicBranch;
+
+	SceneEntityContainer mDynamicEntities;
 };
 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/RenderQueue.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/RenderQueue.cpp	(revision 3051)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/RenderQueue.cpp	(revision 3053)
@@ -55,24 +55,23 @@
 	// test if entity belongs to this bucket
 	// note: rather slows down the application for some reason!!
-	if (tech->IsAlphaTestEnabled() != mBuckets[idx]->mAlphaTestEnabled) return false;
-	if (tech->IsCullFaceEnabled() != mBuckets[idx]->mCullFaceEnabled) return false;
-	if (tech->IsColorWriteEnabled() != mBuckets[idx]->mColorWriteEnabled) return false;
-	if (tech->IsLightingEnabled() != mBuckets[idx]->mLightingEnabled) return false;
-	if (tech->IsDepthWriteEnabled() != mBuckets[idx]->mDepthWriteEnabled) return false;
+	if (tech->IsAlphaTestEnabled() != mBuckets[idx]->mAlphaTestEnabled) { cout << "a"; return false; }
+	if (tech->IsCullFaceEnabled() != mBuckets[idx]->mCullFaceEnabled) { cout << "b"; return false; }
+	if (tech->IsColorWriteEnabled() != mBuckets[idx]->mColorWriteEnabled) { cout << "c"; return false; }
+	if (tech->IsLightingEnabled() != mBuckets[idx]->mLightingEnabled) { cout << "d"; return false; }
+	if (tech->IsDepthWriteEnabled() != mBuckets[idx]->mDepthWriteEnabled) { cout << "e"; return false; }
 
 	const bool hasTexture = (tech->GetTexture() != NULL);
 
-	if (hasTexture != mBuckets[idx]->mHasTexture)
-		return false;
+	if (hasTexture != mBuckets[idx]->mHasTexture) { cout << "f"; return false; }
 
 	if (hasTexture)
 	{
-		if (tech->GetTexture()->GetWidth() != mBuckets[idx]->mTexWidth) return false;
-		if (tech->GetTexture()->GetHeight() != mBuckets[idx]->mTexHeight) return false;
-		if (tech->GetTexture()->GetFormat() != mBuckets[idx]->mTexFormat) return false;
-	}
-
-	if ((tech->GetFragmentProgram() != NULL) && mBuckets[idx]->mHasFragmentProgram) return false;
-	if ((tech->GetVertexProgram() != NULL) && mBuckets[idx]->mHasVertexProgram) return false;
+		if (tech->GetTexture()->GetWidth() != mBuckets[idx]->mTexWidth) { cout << "g"; return false; }
+		if (tech->GetTexture()->GetHeight() != mBuckets[idx]->mTexHeight) { cout << "h"; return false; }
+		if (tech->GetTexture()->GetFormat() != mBuckets[idx]->mTexFormat) { cout << "i"; return false; }
+	}
+
+	if (!tech->GetFragmentProgram() && mBuckets[idx]->mHasFragmentProgram) { cout << "j"; return false; }
+	if (!tech->GetVertexProgram() && mBuckets[idx]->mHasVertexProgram) { cout << "h"; return false; }
 
 
@@ -156,5 +155,5 @@
 			mBuckets.push_back(bucket);
 
-			//cout << "num buckets: " << (int)mBuckets.size() << endl;
+			cout << "num buckets: " << (int)mBuckets.size() << endl;
 		}
 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.cpp	(revision 3052)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.cpp	(revision 3053)
@@ -204,4 +204,6 @@
 
 	mVboId = -1;
+
+	mMaxDepthForDynamicBranch = 10;
 }
 
@@ -397,4 +399,10 @@
 	// store near plane
 	sNearPlane = Plane3(cam->GetDirection(), cam->GetPosition());
+
+	// rebuild dynamic part of the hierarchy
+	if (!mDynamicEntities.empty())
+	{
+		UpdateDynamicBranch();
+	}
 }
 
@@ -1110,3 +1118,139 @@
 
 
-}
+////////////////////////
+// construction of the dynamic hierarchy
+
+int Bvh::SortTriangles(BvhLeaf *leaf, 
+					   int axis, 
+					   float position,
+					   SceneEntityContainer &entities)
+{
+	int i = leaf->mFirst;
+	int j = leaf->mLast;
+
+    while (1) 
+	{
+		while (entities[i]->GetCenter()[axis] < position) 
+			++ i;
+	
+		while (position < entities[j]->GetCenter()[axis])
+			-- j;
+
+		if (i < j) 
+		{
+			swap(entities[i], entities[j]);
+			
+			++ i;
+			-- j;
+		}
+		else
+		{
+			break;
+		}
+	}
+
+	return j;
+}
+
+
+int Bvh::SortTrianglesSpatialMedian(BvhLeaf *leaf, 
+									int axis,
+									SceneEntityContainer &entities)
+{
+	// spatial median
+	float m = leaf->mBox.Center()[axis];
+	return SortTriangles(leaf, axis, m, entities);
+}
+
+
+BvhNode *Bvh::SubdivideLeaf(BvhLeaf *leaf, 
+							int parentAxis, 
+							SceneEntityContainer &entities)
+{
+	if (TerminationCriteriaMet(leaf))
+		return leaf;
+	
+	//int axis = leaf->mBox.MajorAxis();
+	int axis = (parentAxis + 1) % 3;
+
+	// position of the split in the partailly sorted array of triangles
+	// corresponding to this leaf
+	int split = -1;
+	const int scale = 20;
+
+	float pos = -1.0f;
+
+	// Spatial median subdivision
+	split = SortTrianglesSpatialMedian(leaf, axis, entities);
+	pos = leaf->mBox.Center()[axis];
+	
+	if (split == leaf->mLast)
+	{
+		// no split could be achieved => just halve number of objects
+		split = (leaf->mLast - leaf->mFirst) / 2;
+		cerr << "no reduction " << leaf->CountPrimitives() << " " << leaf->mFirst << " " << split << " " << leaf->mLast << endl;
+	}
+
+	// create two more nodes
+	mNumNodes += 2;
+	BvhInterior *parent = new BvhInterior(leaf->GetParent());
+	BvhLeaf *front = new BvhLeaf(parent);
+	
+	parent->mAxis = axis;
+	parent->mBox = leaf->mBox;
+	parent->mDepth = leaf->mDepth;
+
+	parent->mBack = leaf;
+	parent->mFront = front;
+	//parent->mPosition = pos;
+	
+	// now assign the triangles to the subnodes
+	front->mFirst = split + 1;
+	front->mLast = leaf->mLast;
+	front->mDepth = leaf->mDepth + 1;
+	leaf->mLast = split;
+	leaf->mDepth = front->mDepth;
+	leaf->mParent = parent;
+	
+	// reset box
+	leaf->mBox.Initialize();
+
+	// recursively continue subdivision
+	parent->mBack = SubdivideLeaf(static_cast<BvhLeaf *>(parent->mBack), axis, entities);
+	parent->mFront = SubdivideLeaf(static_cast<BvhLeaf *>(parent->mFront), axis, entities);
+	
+	return parent;
+}
+
+
+bool Bvh::TerminationCriteriaMet(BvhLeaf *leaf) const
+{
+	const bool criteriaMet = 
+		(leaf->mDepth > mMaxDepthForDynamicBranch) ||
+		(leaf->CountPrimitives() == 1);
+
+	return criteriaMet;
+}
+
+
+void Bvh::UpdateDynamicBranch()
+{
+	BvhNode *dynamicRoot = static_cast<BvhInterior *>(mRoot)->mBack;
+
+	cout << "updating dynamic branch" << endl;
+
+	// delete old branch
+	if (!dynamicRoot->IsLeaf())
+	{
+		cout << "deleting old branch" << endl;
+
+		DEL_PTR(dynamicRoot);
+
+		dynamicRoot = new BvhLeaf(mRoot);
+		dynamicRoot->mBox = mRoot->mBox;
+	}
+
+	dynamicRoot = SubdivideLeaf(static_cast<BvhLeaf *>(dynamicRoot), 0, mDynamicEntities);
+}
+
+}
