Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/AxisAlignedBox3.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/AxisAlignedBox3.h	(revision 2802)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/AxisAlignedBox3.h	(revision 2911)
@@ -5,4 +5,6 @@
 #include "Matrix4x4.h"
 #include "Vector3.h"
+#include "common.h"
+#
 
 
@@ -12,4 +14,7 @@
 struct Triangle3;
 class Plane3;
+class Polygon3;
+class Polyhedron;
+
 
 /** Axis alignedd box class.
@@ -79,4 +84,7 @@
 	void Include(const Vector3 &newpt);
 	void Include(const AxisAlignedBox3 &bbox);
+	void Include(const Polygon3 &newpoly);
+	void Include(const PolygonContainer &polys);
+	
 	/** Expand the axis-aligned box to include given values in particular axis.
 	*/
@@ -85,4 +93,5 @@
 	*/
 	bool Includes(const AxisAlignedBox3 &b) const;
+
 	/** Returns true if this point is inside box.
 	*/
@@ -167,4 +176,19 @@
 	*/
 	float GetMinVisibleDistance(const Plane3 &near) const;
+	/** Returns cross section of the plane as a polygon.
+	*/
+	Polygon3 *AxisAlignedBox3::CrossSection(const Plane3 &plane) const;
+	/** Returns the supporting plane of this face.
+	*/
+	Plane3 AxisAlignedBox3::GetPlane(const int face) const;
+	/** Returns 
+		0 if box intersects plane
+		1 if box in front of plane
+		-1 if box behind plane
+	*/
+	int Side(const Plane3 &plane) const;
+	/**  Calculates the intersection of the polyhedron with the box.
+	*/
+	Polyhedron *CalcIntersection(Polyhedron *polyhedron) const;
 
 
@@ -178,6 +202,6 @@
 	friend inline bool OverlapS(const AxisAlignedBox3 &,const AxisAlignedBox3 &);
 
-	/** Overlap returns 1 if the two axis-aligned boxes overlap for a given
-	epsilon. If eps > 0.0, then the boxes has to have the real intersection
+	/** Overlap returns 1 if the two axis-aligned boxes overlap for a given epsilon. 
+	If eps > 0.0, then the boxes has to have the real intersection
 	box, if eps < 0.0, then the boxes need not intersect really, they
 	can be at eps distance in the projection.
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Vector3.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Vector3.h	(revision 2844)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Vector3.h	(revision 2911)
@@ -2,5 +2,5 @@
 #define _Vector3_h__
 
-#include <iostream>
+
 #include "common.h"
 #include <math.h>
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.h	(revision 2838)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.h	(revision 2911)
@@ -10,18 +10,35 @@
 {
 
+class Matrix4x4;
+class Polyhedron;
+
+/** Class representing a frustum.
+*/
+class Frustum
+{
+	friend class Camera;
+
+public:
+
+	Frustum() {};
+
+	Frustum(const Matrix4x4 &trafo);
+
+	enum { RIGHT_PLANE, LEFT_PLANE, BOTTOM_PLANE, TOP_PLANE, FAR_PLANE, NEAR_PLANE};
+	/** Resizes the current frustum so that it fully encloses the given polyhedron
+	*/
+	void EnclosePolyhedron(const Polyhedron &polyhedron);
+
+	void ExtractTransformation(Matrix4x4 &m) const;
+
+
+	/// the 6 clip planes
+	Plane3 mClipPlanes[6];
+};
+
 
 class Camera
 {
 public:
-	
-	/** Small struct representing a frustum.
-	*/
-	struct Frustum
-	{
-		/// the 6 clip planes
-		Plane3 mClipPlanes[6];
-
-		void CalcNPVertexIndices(int *indices);
-	};
 	
 	Camera();
@@ -33,7 +50,12 @@
 
 	inline Vector3 GetPosition() const { return mPosition; }
+	
 	Vector3 GetDirection() const;
 	Vector3 GetUpVector() const;
 	Vector3 GetRightVector() const;
+
+	Vector3 GetBaseDirection() const;
+	Vector3 GetBaseUpVector() const;
+	Vector3 GetBaseRightVector() const;
 
 	inline float GetFov() const { return mFovy; }
@@ -51,11 +73,15 @@
 	*/
 	void GetModelViewMatrix(Matrix4x4 &mat);
-
+	/** Calculates a frustum from the projection and the modelview matrix.
+	*/
 	void CalcFrustum(Frustum &frustum);
 	/** Computes the extremal points of this frustum.
 	*/
 	void ComputePoints(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
-		               Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr);
-	
+		               Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr) const;
+	/** Computes the extremal points of the base frustum.
+	*/
+	void ComputeBasePoints(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
+						   Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr) const;
 	/** Returns the near plane.
 	*/
@@ -83,4 +109,8 @@
 	void SetDirection(const Vector3 &direction);
 
+	/** Calculates the intersection of the frustum with the box,
+		returns resultin polyhedron as array of polygons.
+	*/
+	Polyhedron *CalcClippedFrustum(const AxisAlignedBox3 &box) const;
 
 
@@ -91,4 +121,8 @@
 	void CalculateFromPitchAndYaw();
 
+	void ComputePointsInternal(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
+							   Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr,
+							   const Vector3 &view, const Vector3 &right, const Vector3 &up,
+							   const Vector3 &pos) const;
 
 	////////////////
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/deferred.cg
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/deferred.cg	(revision 2895)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/deferred.cg	(revision 2911)
@@ -102,4 +102,5 @@
 	
 	float4 lightSpacePos = mul(shadowMatrix, position);
+	lightSpacePos /= lightSpacePos.w;
 
 	float shadowDepth[9];
@@ -123,5 +124,5 @@
 	OUT.color = col;
 	
-	float depth = lightSpacePos.z / lightSpacePos.w;
+	float depth = lightSpacePos.z;
 
 	float d = 0.0f;
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/ssao.cg
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/ssao.cg	(revision 2904)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/ssao.cg	(revision 2911)
@@ -88,12 +88,11 @@
 			(SAMPLE_INTENSITY * DISTANCE_SCALE) / (DISTANCE_SCALE + length_to_sample * length_to_sample);
 
+#if 0
 		// if surface normal perpenticular to view dir, approx. half of the samples will not count
 		// => compensate for this (on the other hand, projected sampling area could be larger!)
-		//const float view_correction = 1.0f + VIEW_CORRECTION_SCALE * (1.0f - dot(currentViewDir, currentNormal));
-		//total_ao += cos_angle * distance_intensity * view_correction;
-
+		const float view_correction = 1.0f + VIEW_CORRECTION_SCALE * (1.0f - dot(currentViewDir, currentNormal));
+		total_ao += cos_angle * distance_intensity * view_correction;
+#endif
 		total_ao += cos_angle * distance_intensity;
-
-		//total_ao /= j;
 	}
 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Plane3.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Plane3.h	(revision 2853)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Plane3.h	(revision 2911)
@@ -8,5 +8,5 @@
 {
 
-/** 3D Plane.
+/** Class describing a 3D Plane.
 */
 class Plane3 
@@ -35,5 +35,5 @@
 	/** Returns 1 if v is on front side, -1 if on back side, 0 if on plane.
 	*/
-	int Side(const Vector3 &v, const float threshold = 1e-6) const;
+	int Side(const Vector3 &v, float threshold = 1e-6) const;
 	/** Finds intersection of line segment between points a and b with plane.
 	    @param a start point
@@ -52,4 +52,18 @@
 	float FindT(const Vector3 &a, const Vector3 &b) const;
 
+	operator const float*() const 
+	{ 
+		return (const float*) this; 
+	}
+
+	float& operator[] (const int inx) 
+	{
+		return (&mNormal.x)[inx];
+	}
+
+	const float &operator[] (const int inx) const 
+	{
+		return *(&mNormal.x + inx);
+	}
 
 	///////////
@@ -59,4 +73,5 @@
 
 	friend bool PlaneIntersection(const Plane3 &p1, const Plane3 &p2);
+	
 
 	friend std::ostream &operator<<(std::ostream &s, const Plane3 &p) 
@@ -73,4 +88,5 @@
 };
 
+
 }
 #endif
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Visualization.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Visualization.cpp	(revision 2891)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Visualization.cpp	(revision 2911)
@@ -5,4 +5,5 @@
 #include "Bvh.h"
 #include "RenderState.h"
+#include "ShadowMapping.h"
 
 #include <stack>
@@ -150,5 +151,7 @@
 	glDisable(GL_DEPTH_TEST);
 
-	RenderFrustum();
+	//RenderFrustum();
+
+	ShadowMap::DrawPolys();
 
 	Vector3 pos = mCamera->GetPosition();
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.h	(revision 2897)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.h	(revision 2911)
@@ -34,5 +34,5 @@
 	/** Computes the shadow map
 	*/
-	void ComputeShadowMap(RenderTraverser *traverser);
+	void ComputeShadowMap(RenderTraverser *traverser, const Matrix4x4 &projView);
 	/** Returns computed shadow texture.
 	*/
@@ -53,5 +53,13 @@
 
 
+	static void DrawPolys();
+
+
 protected:
+
+	void CalcFocussedFrustum(const Matrix4x4 &camProjView, 
+							 const Matrix4x4 &lightProjView, 
+							 Matrix4x4 &focussed);
+
 
 	/// the scene bounding box
@@ -69,4 +77,6 @@
 	/// the scene camera
 	Camera *mCamera;
+
+	Matrix4x4 mLightProjView;
 };
 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.cpp	(revision 2897)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.cpp	(revision 2911)
@@ -65,5 +65,5 @@
 
 static Plane3 sNearPlane;
-static Camera::Frustum sFrustum;
+static Frustum sFrustum;
 
 /// these values are valid for all nodes
@@ -364,4 +364,16 @@
 
 
+static void CalcNPVertexIndices(const Frustum &frustum, int *indices)
+{
+	for (int i = 0; i < 6; ++ i)
+	{
+		// n-vertex
+		indices[i * 2 + 0] = AxisAlignedBox3::GetIndexNearestVertex(frustum.mClipPlanes[i].mNormal);
+		// p-vertex
+		indices[i * 2 + 1] = AxisAlignedBox3::GetIndexFarthestVertex(frustum.mClipPlanes[i].mNormal);	
+	}
+}
+
+
 void Bvh::InitFrame(Camera *cam)
 {
@@ -370,5 +382,5 @@
 
 	cam->CalcFrustum(sFrustum);
-	sFrustum.CalcNPVertexIndices(sClipPlaneAABBVertexIndices);
+	CalcNPVertexIndices(sFrustum, sClipPlaneAABBVertexIndices);
 
 	// store near plane
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SampleGenerator.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SampleGenerator.h	(revision 2903)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SampleGenerator.h	(revision 2911)
@@ -28,5 +28,5 @@
 };
 
-/** Class generating random samples on a disc or a sphere, respectively.
+/** Class generating random samples on a disc or in a sphere, respectively.
 */
 class SampleGenerator
@@ -61,4 +61,8 @@
 
 
+/** This class generates random samples on a disc respecting
+	the poisson disc condition (all samples at least distance d apart)
+	according to some d related to the number of samples.
+*/
 class PoissonDiscSampleGenerator: public SampleGenerator
 {
@@ -74,5 +78,6 @@
 };
 
-
+/** This class generates random spherical samples.
+*/
 class SphericalSampleGenerator: public SampleGenerator
 {
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.cpp	(revision 2899)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.cpp	(revision 2911)
@@ -4,7 +4,11 @@
 #include "RenderTraverser.h"
 #include "Light.h"
+#include "Polygon3.h"
+#include "Polyhedron.h"
+
 #include <IL/il.h>
 #include <assert.h>
 
+
 using namespace std;
 
@@ -12,4 +16,7 @@
 namespace CHCDemoEngine
 {
+
+
+static Polyhedron *polyhedron = NULL;
 
 
@@ -97,5 +104,65 @@
 
 
-void ShadowMap::ComputeShadowMap(RenderTraverser *renderer)
+void ShadowMap::DrawPolys()
+{
+	if (!polyhedron) return;
+
+	cout << "here3" << endl;
+
+	for (size_t i = 0; i < polyhedron->NumPolygons(); ++ i)
+	{
+		float r = (float)i / polyhedron->NumPolygons();
+		float g = 1;
+		float b = 1;
+
+		glColor3f(r, g, b);
+
+		glBegin(GL_LINE_LOOP);
+
+		Polygon3 *poly = polyhedron->GetPolygons()[i];
+
+		for (size_t j = 0; j < poly->mVertices.size(); ++ j)
+		{
+			Vector3 v = poly->mVertices[j];
+			glVertex3d(v.x, v.y, v.z);
+		}
+
+		glEnd();
+	}
+}
+
+
+void ShadowMap::CalcFocussedFrustum(const Matrix4x4 &camProjView, 
+									const Matrix4x4 &lightProjView, 
+									Matrix4x4 &focussed)
+{
+	///////////////////
+	//-- First step: calc clipped frustum
+
+	DEL_PTR(polyhedron);
+	polyhedron = mCamera->CalcClippedFrustum(mSceneBox);
+
+	if (polyhedron)
+	{
+		// second step: focus light frustum on clipped frustum
+		Frustum lightFrustum(lightProjView);
+
+		for (int i = 0; i < 6; ++ i)
+		{
+			// the clipping planes look outward the frustum,
+			// so distances > 0 mean that a point is outside
+			const float invLength = 1.0f / Magnitude(lightFrustum.mClipPlanes[i].mNormal);
+
+			lightFrustum.mClipPlanes[i].mD *= invLength;
+			lightFrustum.mClipPlanes[i].mNormal *= invLength;
+		}
+
+		//lightFrustum.EnclosePolyhedron(*polyhedron);
+		lightFrustum.ExtractTransformation(focussed);
+	}
+}
+
+
+void ShadowMap::ComputeShadowMap(RenderTraverser *renderer, const Matrix4x4 &projView)
 {
 	const float xlen = Magnitude(mSceneBox.Diagonal() * 0.5f);
@@ -107,6 +174,9 @@
 	Vector3 pos = mSceneBox.Center();
 
+	Matrix4x4 camView;
+	mCamera->GetModelViewMatrix(camView);
+
 	pos -= mLight->GetDirection() * Magnitude(mSceneBox.Diagonal() * 0.5f);
-	mShadowCam->SetPosition(pos);
+	//mShadowCam->SetPosition(pos);
 
 	mFbo->Bind();
@@ -153,11 +223,44 @@
 	mShadowCam->GetProjectionMatrix(lightProj);
 
+	Matrix4x4 oldLightProjView = lightView * lightProj;
+	Matrix4x4 newLightProj;
+
+	CalcFocussedFrustum(projView, lightProj, newLightProj);
+	//CalcFocussedFrustum(projView, oldLightProjView, newLightProj);
+
+	Matrix4x4 dummyMat;
+	glGetFloatv(GL_PROJECTION_MATRIX, (float *)dummyMat.x);
+
+
+	cout << "old:\n" << dummyMat << endl;
+
+
+	glMatrixMode(GL_PROJECTION);
+	glLoadMatrixf((float *)newLightProj.x);
+	
+	glMatrixMode(GL_MODELVIEW);
+	//glLoadIdentity();
+
+	Matrix4x4 dummyMat3;
+	glGetFloatv(GL_PROJECTION_MATRIX, (float *)dummyMat3.x);
+
+	cout << "new:\n" << newLightProj << endl;
+
+	lightView = camView;
+	mLightProjView = lightView * newLightProj;
+	//mLightProjView = newLightProj;
+
+	//cout << "old: \n" << oldLightProjView << " new: \n " << mLightProjView << endl;
+	
+
 	static Matrix4x4 biasMatrix(0.5f, 0.0f, 0.0f, 0.5f,
 								0.0f, 0.5f, 0.0f, 0.5f,
 								0.0f, 0.0f, 0.5f, 0.5f,
-								0.0f, 0.0f, 0.0f, 1.0f); //bias from [-1, 1] to [0, 1]
-
-	Matrix4x4 lightProjView = lightView * lightProj;
-	mTextureMatrix = lightProjView * biasMatrix; 
+								0.0f, 0.0f, 0.0f, 1.0f);
+
+	mTextureMatrix = mLightProjView * biasMatrix; 
+	//mTextureMatrix = oldLightProjView * biasMatrix; 
+
+
 
 
@@ -176,6 +279,6 @@
 
 	glPopAttrib();
-	
-	/*float *data = new float[mSize * mSize];
+	/*
+	float *data = new float[mSize * mSize];
 
 	GrabDepthBuffer(data, mFbo->GetDepthTex());
@@ -183,7 +286,7 @@
 
 	delete [] data;
-	*/
+	
 	PrintGLerror("shadow map");
-
+*/
 	FrameBufferObject::Release();
 }
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp	(revision 2905)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp	(revision 2911)
@@ -44,5 +44,5 @@
 static Environment env;
 
-#define MAX_DEPTH_CONST myfar //10.0f;
+#define MAX_DEPTH_CONST 10.0f
 
 // fbo
@@ -336,5 +336,5 @@
 	camera = new Camera(winWidth, winHeight, fov);
 	camera->SetNear(nearDist);
-	camera->SetFar(1000);
+	camera->SetFar(100000);
 
 	camera->SetDirection(camDir);
@@ -933,5 +933,5 @@
 
 			// the scene is rendered withouth any shading	
-			shadowMap->ComputeShadowMap(shadowTraverser);
+			shadowMap->ComputeShadowMap(shadowTraverser, matProjectionView);
 
 			// change back state
@@ -1545,5 +1545,6 @@
 
 	// hack: set far plane for viz
-	camera->SetFar(0.35f * Magnitude(box.Diagonal()));
+	//camera->SetFar(0.35f * Magnitude(box.Diagonal()));
+	camera->SetFar(1);
 
 	const float offs = box.Size().x * 0.3f;
@@ -1593,5 +1594,4 @@
 	visualization->Render();
 
-	
 	
 	// reset previous settings
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/AxisAlignedBox3.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/AxisAlignedBox3.cpp	(revision 2802)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/AxisAlignedBox3.cpp	(revision 2911)
@@ -1,7 +1,9 @@
+#include "AxisAlignedBox3.h"
+#include "Plane3.h"
+#include "Polygon3.h"
+#include "Polyhedron.h"
+
 #include <cassert>
 #include <iostream>
-#include "AxisAlignedBox3.h"
-#include "Plane3.h"
-
 
 using namespace std;
@@ -50,4 +52,22 @@
 	Minimize(mMin, newpt);
 	Maximize(mMax, newpt);
+}
+
+
+void AxisAlignedBox3::Include(const Polygon3 &newpoly)
+{
+	VertexArray::const_iterator it, it_end = newpoly.mVertices.end();
+
+	for (it = newpoly.mVertices.begin(); it != it_end; ++ it)
+		Include(*it);
+}
+
+
+void AxisAlignedBox3::Include(const PolygonContainer &polys)
+{
+	PolygonContainer::const_iterator it, it_end = polys.end();
+
+	for (it = polys.begin(); it != it_end; ++ it)
+		Include(*(*it));
 }
 
@@ -1026,4 +1046,180 @@
 }
 
-}
-
+
+struct VertexData
+{
+	Vector3 mVertex;
+	float mAngle;
+	
+	VertexData(Vector3 vtx, float angle): mVertex(vtx), mAngle(angle)
+	{}
+
+	bool operator<(const VertexData &b) const 
+	{
+		return mAngle > b.mAngle;
+	}
+};
+
+// TODO: use a table to avoid normal and distance computations
+Polygon3 *AxisAlignedBox3::CrossSection(const Plane3 &plane) const
+{
+	Polygon3 *planePoly = new Polygon3();
+	
+	int side[8];
+	bool onFrontSide = false, onBackSide = false;
+	
+	Vector3 vtx;
+	
+	//////////////
+	//-- compute classification of vertices
+
+	for (int i = 0; i < 8; ++i)
+	{
+		GetVertex(i, vtx);
+		side[i] = plane.Side(vtx);
+		if (side[i] > 0)
+			onFrontSide = true;
+		else if (side[i] < 0)
+			onBackSide = true;
+		else // vertex coincident => push_back
+			planePoly->mVertices.push_back(vtx);
+	}
+
+	///////////
+	//-- find intersections
+
+	if (onFrontSide && onBackSide)
+	{
+		Vector3 ptA, ptB;
+		for (int i = 0; i < 12; ++ i)
+		{
+			int aIdx, bIdx;
+			GetEdge(i, aIdx, bIdx);
+
+			ptA = GetVertex(aIdx);
+			ptB = GetVertex(bIdx);
+
+			int sideA = side[aIdx];
+			int sideB = side[bIdx];
+
+			if (((sideA > 0) && (sideB < 0)) || (sideA < 0) && (sideB > 0))
+				planePoly->mVertices.push_back(plane.FindIntersection(ptA, ptB));	
+		}
+	}
+
+	// order intersections	
+	if (planePoly->mVertices.size() > 3)
+	{
+		Vector3 centerOfMass(0);
+
+		int i;
+		// compute center of mass
+		for (i = 0; i < (int)planePoly->mVertices.size(); ++ i)
+			centerOfMass += planePoly->mVertices[i];
+		
+		centerOfMass /= (float)planePoly->mVertices.size();
+
+		vector<VertexData> vertexData;
+		Vector3 refVec = Normalize(centerOfMass - planePoly->mVertices[0]);
+
+		// compute angle to reference point
+		for (i = 1; i < (int)planePoly->mVertices.size(); ++ i)
+		{
+		    float angle = 
+		      Angle(refVec, centerOfMass - planePoly->mVertices[i], plane.mNormal);
+		    
+		    vertexData.push_back(VertexData(planePoly->mVertices[i], angle));
+		}
+		
+		std::stable_sort(vertexData.begin(), vertexData.end());
+
+		// update vertices
+		for (i = 1; i < (int)planePoly->mVertices.size(); ++ i)
+			planePoly->mVertices[i] = vertexData[i - 1].mVertex;
+	}
+	else if (planePoly->mVertices.size() == 3)
+	{
+		// fix orientation if needed
+		if (DotProd(planePoly->GetNormal(), plane.mNormal) < 0)
+		{
+			Vector3 v = planePoly->mVertices[1];
+			planePoly->mVertices[1] = planePoly->mVertices[2];
+			planePoly->mVertices[2] = v;
+		}
+	}
+	
+	return planePoly;
+}
+
+
+Plane3 AxisAlignedBox3::GetPlane(const int face) const
+{
+	switch (face) 
+	{
+        
+	case 0:
+		return Plane3(Vector3(-1, 0, 0), mMin);
+	case 1: 
+		return Plane3(Vector3(1, 0, 0), mMax);
+	case 2:
+		return Plane3(Vector3(0, -1, 0), mMin);
+	case 3:
+		return Plane3(Vector3(0, 1, 0), mMax);
+	case 4:
+		return Plane3(Vector3(0, 0, -1), mMin);
+	case 5:
+		return Plane3(Vector3(0, 0, 1), mMax);
+	}
+
+	// should not come here
+	return Plane3();
+}
+
+
+int AxisAlignedBox3::Side(const Plane3 &plane) const
+{
+	int s = 0;
+	// if exactly one of the vertices lies on the plane 
+	// and the others are on the same side, the plane is tangent
+	// to the box on either side and not intersecting
+	for (int i = 0; i < 8; ++ i)
+	{
+		Vector3 pt;
+		GetVertex(i, pt);
+
+		int side = plane.Side(pt);
+
+		if (side != 0)
+		{
+			if (side == -s)
+				return 0; // sign changed => intersects
+
+			s = side;
+		}
+	}
+
+	return s;
+}
+
+
+Polyhedron *AxisAlignedBox3::CalcIntersection(Polyhedron *polyhedron) const
+{
+	Polyhedron *oldPolyhedron = new Polyhedron(*polyhedron);
+
+	Polyhedron *newPolyhedron = NULL;
+
+	for (int i = 0; i < 6; ++ i)
+	{
+		Polyhedron *newPolyhedron = oldPolyhedron->CalcIntersection(GetPlane(i));
+		DEL_PTR(oldPolyhedron);
+
+		if (!newPolyhedron)
+			return NULL;
+	}
+
+	return newPolyhedron;
+}
+
+
+}
+
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.cpp	(revision 2893)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.cpp	(revision 2911)
@@ -2,5 +2,7 @@
 #include "Camera.h"
 #include "glInterface.h"
-
+#include "Polygon3.h"
+#include "Matrix4x4.h"
+#include "Polyhedron.h"
 
 namespace CHCDemoEngine 
@@ -107,21 +109,6 @@
 
 	matProjectionView = matViewing * matProjectionView;
-		
-	float planes[6][4];
-
-
-	//////////
-	//-- extract the plane equations
-
-	for (int i = 0; i < 4; ++ i)
-	{
-		planes[0][i] = matProjectionView.x[i][3] - matProjectionView.x[i][0]; // right plane
-		planes[1][i] = matProjectionView.x[i][3] + matProjectionView.x[i][0]; // left plane
-		planes[2][i] = matProjectionView.x[i][3] + matProjectionView.x[i][1]; // bottom plane
-		planes[3][i] = matProjectionView.x[i][3] - matProjectionView.x[i][1]; // top plane
-		planes[4][i] = matProjectionView.x[i][3] - matProjectionView.x[i][2]; // far plane
-		planes[5][i] = matProjectionView.x[i][3] + matProjectionView.x[i][2]; // near plane
-	}
-
+
+	frustum = Frustum(matProjectionView);
 
 	////////////
@@ -132,28 +119,8 @@
 		// the clipping planes look outward the frustum,
 		// so distances > 0 mean that a point is outside
-		float fInvLength = -1.0f / 
-			sqrt(planes[i][0] * planes[i][0] +	
-			     planes[i][1] * planes[i][1] +	
-				 planes[i][2] * planes[i][2]);
-
-		planes[i][0] *= fInvLength;
-		planes[i][1] *= fInvLength;
-		planes[i][2] *= fInvLength;
-		planes[i][3] *= fInvLength;
-
-		frustum.mClipPlanes[i].mNormal = Vector3(planes[i][0], planes[i][1], planes[i][2]);
-		frustum.mClipPlanes[i].mD = planes[i][3];
-	}
-}
-
-
-void Camera::Frustum::CalcNPVertexIndices(int *indices)
-{
-	for (int i = 0; i < 6; ++ i)
-	{
-		// n-vertex
-		indices[i * 2 + 0] = AxisAlignedBox3::GetIndexNearestVertex(mClipPlanes[i].mNormal);
-		// p-vertex
-		indices[i * 2 + 1] = AxisAlignedBox3::GetIndexFarthestVertex(mClipPlanes[i].mNormal);	
+		const float invLength = -1.0f / Magnitude(frustum.mClipPlanes[i].mNormal);
+	
+		frustum.mClipPlanes[i].mD *= invLength;
+		frustum.mClipPlanes[i].mNormal *= invLength;
 	}
 }
@@ -174,6 +141,8 @@
 
 
-void Camera::ComputePoints(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
-						   Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr)
+void Camera::ComputePointsInternal(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
+								   Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr,
+								   const Vector3 &view, const Vector3 &right, const Vector3 &up,
+								   const Vector3 &pos) const
 {
 	float z_near = mNear;
@@ -188,10 +157,6 @@
 	const float h_far = w_far / GetAspect();
 
-	const Vector3 view = GetDirection();
-	const Vector3 fc = mPosition + view * z_far; 
-	
-	const Vector3 up = GetUpVector();
-	const Vector3 right = GetRightVector();
-
+	const Vector3 fc = pos + view * z_far; 
+	
 	Vector3 t1, t2;
 
@@ -204,5 +169,5 @@
 	fbr = fc - t1 + t2;
 
-	const Vector3 nc = mPosition + view * z_near;
+	const Vector3 nc = pos + view * z_near;
 	
 	t1 = h_near * 0.5f * up;
@@ -216,4 +181,65 @@
 
 
+void Camera::ComputePoints(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
+						   Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr) const
+{
+	ComputePointsInternal(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr, 
+						  GetDirection(), GetRightVector(), GetUpVector(), GetPosition());
+}
+
+
+void Camera::ComputeBasePoints(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
+							   Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr) const
+{
+	ComputePointsInternal(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr, 
+		GetBaseDirection(), GetBaseRightVector(), GetBaseUpVector(), Vector3(0, 0, 0));
+}
+
+
+Polyhedron *Camera::CalcClippedFrustum(const AxisAlignedBox3 &box) const
+{
+	Vector3 ftl, ftr, fbl, fbr;
+	Vector3 ntl, ntr, nbl, nbr;
+
+	VertexArray sides[6];
+
+	ComputeBasePoints(ftl, ftr, fbl, fbr,ntl, ntr, nbl, nbr);
+	//ComputePoints(ftl, ftr, fbl, fbr,ntl, ntr, nbl, nbr);
+
+	for (int i = 0; i < 6; i ++)
+		sides[i].resize(4);
+	
+	// left, right
+	sides[0][0] = ntl; sides[0][1] = ftl; sides[0][2] = fbl; sides[0][3] = nbl;
+	sides[1][0] = ntr; sides[1][1] = ftr; sides[1][2] = fbr; sides[1][3] = nbr;
+	// bottom, top
+	sides[2][0] = ntl; sides[2][1] = ftl; sides[2][2] = ftr; sides[2][3] = ntr;
+	sides[3][0] = nbl; sides[3][1] = fbl; sides[3][2] = fbr; sides[3][3] = nbr;
+	// near, far
+	sides[4][0] = ntl; sides[4][1] = ntr; sides[4][2] = nbr; sides[4][3] = nbl; 
+	sides[5][0] = ntl; sides[5][1] = ntr; sides[5][2] = nbr; sides[5][3] = nbl;
+
+
+	//////////
+	//-- compute polyhedron
+
+	PolygonContainer polygons;
+
+	for (int i = 0; i < 6; ++ i)
+	{
+		Polygon3 *poly = new Polygon3(sides[i]);
+		polygons.push_back(poly);
+	}
+
+	Polyhedron *p = new Polyhedron(polygons);
+
+	//Polyhedron *clippedPolyhedron = box.CalcIntersection(po);
+	//DEL_PTR(p);
+
+	//return clippedPolyhedron;
+	return p;
+}
+
+
 void Camera::SetOrtho(bool ortho)
 {
@@ -240,8 +266,4 @@
 	Vector3 ndir = -Normalize(dir);
 
-	//mPitch = atan2(dir.x, dir.z);
-	//mYaw = atan2(dir.y, sqrt((dir.x * dir.x) + (dir.z * dir.z)));
-
-	//mPitch = atan2(dir.x, dir.y);
 	mPitch = -atan2(ndir.x, ndir.y);
 	mYaw = atan2(ndir.z, sqrt((ndir.x * ndir.x) + (ndir.y * ndir.y)));
@@ -277,9 +299,87 @@
 Vector3 Camera::GetRightVector() const 
 { 
-	return Vector3(mViewOrientation.x[0][0], mViewOrientation.x[1][0], mViewOrientation.x[2][0]);
-		
-}
-
-
-}
-
+	return Vector3(mViewOrientation.x[0][0], mViewOrientation.x[1][0], mViewOrientation.x[2][0]);		
+}
+
+
+Vector3 Camera::GetBaseDirection() const
+{ 
+	return -Vector3(mBaseOrientation.x[0][2], mBaseOrientation.x[1][2], mBaseOrientation.x[2][2]);
+}
+
+
+Vector3 Camera::GetBaseUpVector() const 
+{ 
+	return Vector3(mBaseOrientation.x[0][1], mBaseOrientation.x[1][1], mBaseOrientation.x[2][1]);
+}
+
+
+Vector3 Camera::GetBaseRightVector() const 
+{ 
+	return Vector3(mBaseOrientation.x[0][0], mBaseOrientation.x[1][0], mBaseOrientation.x[2][0]);
+}
+
+
+Frustum::Frustum(const Matrix4x4 &trafo)
+{
+	//////////
+	//-- extract the plane equations
+
+	for (int i = 0; i < 4; ++ i)
+	{
+		mClipPlanes[Frustum::RIGHT_PLANE][i] = trafo.x[i][3] - trafo.x[i][0];
+		mClipPlanes[Frustum::LEFT_PLANE][i] = trafo.x[i][3] + trafo.x[i][0]; 
+		mClipPlanes[Frustum::BOTTOM_PLANE][i] = trafo.x[i][3] + trafo.x[i][1];
+		mClipPlanes[Frustum::TOP_PLANE][i] = trafo.x[i][3] - trafo.x[i][1]; 
+		mClipPlanes[Frustum::FAR_PLANE][i] = trafo.x[i][3] - trafo.x[i][2]; 
+		mClipPlanes[Frustum::NEAR_PLANE][i] = trafo.x[i][3] + trafo.x[i][2];
+	}
+}
+
+
+void Frustum::EnclosePolyhedron(const Polyhedron &polyhedron)
+{
+	VertexArray vertices;
+	polyhedron.CollectVertices(vertices);
+
+	for (int i = 0; i < 6; ++ i)
+	{
+		Plane3 &plane = mClipPlanes[i];
+
+		//cout << "p" << i << " " << plane.mD  << endl;
+
+		VertexArray::const_iterator it, it_end = vertices.end();
+
+		float minDist = 1e20;
+
+		for (it = vertices.begin(); it != it_end; ++ it)
+		{
+			float dist = plane.Distance(*it);
+
+			if (dist < minDist)
+			{
+				cout << "minDist: " << dist << endl;
+				minDist = dist;
+			}
+		}
+
+		plane.mD += minDist;
+	}
+}
+
+
+void Frustum::ExtractTransformation(Matrix4x4 &m) const
+{
+	for (int i = 0; i < 4; ++ i)
+	{
+		m.x[i][0] = (mClipPlanes[LEFT_PLANE][i] - mClipPlanes[RIGHT_PLANE][i]) * 0.5f;
+		m.x[i][1] = (mClipPlanes[BOTTOM_PLANE][i] - mClipPlanes[TOP_PLANE][i]) * 0.5f;
+		m.x[i][2] = (mClipPlanes[NEAR_PLANE][i] - mClipPlanes[FAR_PLANE][i]) * 0.5f;
+		m.x[i][3] = (mClipPlanes[LEFT_PLANE][i] + mClipPlanes[RIGHT_PLANE][i]) * 0.5f;
+	}
+}
+
+
+
+}
+
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/common.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/common.h	(revision 2903)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/common.h	(revision 2911)
@@ -26,4 +26,9 @@
 class OcclusionQuery;
 class SceneEntity;
+
+class Shape;
+struct LODLevel;
+class Polygon3;
+
 
 
@@ -483,4 +488,9 @@
 typedef std::queue<BvhNode *> BvhNodeQueue;
 
+
+typedef std::vector<Shape *> ShapeContainer;
+typedef std::vector<LODLevel *> LODLevelContainer;
+typedef std::vector<Polygon3 *> PolygonContainer;
+
 static std::ofstream Debug("debug.log");
 
@@ -488,19 +498,14 @@
 #define INITIAL_TRIANGLES_PER_VIRTUAL_LEAVES 1000
 
-class Shape;
-typedef std::vector<Shape *> ShapeContainer;
-
-struct LODLevel;
-typedef std::vector<LODLevel *> LODLevelContainer;
-
-}
-
-#endif
-
-
-
-
-
-
-
-
+
+}
+
+#endif
+
+
+
+
+
+
+
+
