Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Matrix4x4.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Matrix4x4.h	(revision 2782)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Matrix4x4.h	(revision 2913)
@@ -9,4 +9,5 @@
 
 class Vector3;
+class AxisAlignedBox3;
 
 
@@ -108,4 +109,6 @@
 	friend Vector3 GetTranslation(const Matrix4x4 &M);
 
+	friend Matrix4x4 GetFittingProjectionMatrix(const AxisAlignedBox3 &box);
+
 	// Overloaded output operator.
 	friend std::ostream& operator<< (std::ostream &s, const Matrix4x4 &M);
@@ -148,4 +151,5 @@
 Vector3 TransformNormal(const Matrix4x4 &M, const Vector3 &v);
 Vector3 GetTranslation(const Matrix4x4 &M);
+Matrix4x4 GetFittingProjectionMatrix(const AxisAlignedBox3 &box);
 
 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polygon3.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polygon3.h	(revision 2912)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polygon3.h	(revision 2913)
@@ -18,7 +18,4 @@
 struct Triangle3;
 
-
-
-typedef std::vector<Vector3> VertexArray;
 
 
@@ -70,5 +67,5 @@
 		@returns true if polygon is valid.
 	*/
-	bool Valid(const float epsilon) const; 
+	bool Valid(float epsilon) const; 
 	/** Returns the surface normal.
 	*/
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Plane3.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Plane3.cpp	(revision 2782)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Plane3.cpp	(revision 2913)
@@ -12,10 +12,4 @@
     mD = -DotProd(b, mNormal);
 }
-
-
-/*Plane3::Plane3(const Vector3 &normal, float dist): 
-mNormal(normal), mD(dist)
-{
-}*/
 
 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polyhedron.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polyhedron.h	(revision 2912)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polyhedron.h	(revision 2913)
@@ -73,6 +73,4 @@
 	inline friend std::ostream &operator<<(std::ostream &s, const Polyhedron &a);
 
-
-
 protected:
 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/AxisAlignedBox3.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/AxisAlignedBox3.h	(revision 2911)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/AxisAlignedBox3.h	(revision 2913)
@@ -6,5 +6,4 @@
 #include "Vector3.h"
 #include "common.h"
-#
 
 
@@ -16,4 +15,20 @@
 class Polygon3;
 class Polyhedron;
+
+
+struct SimpleRay
+{
+	SimpleRay() {}
+
+	SimpleRay(const Vector3 &o, const Vector3 &d): mOrigin(o), mDirection(d) {}
+
+	Vector3 mOrigin;
+	Vector3 mDirection;
+
+	Vector3 Extrap(const float t) const 
+	{
+		return mOrigin + mDirection * t;
+	}
+};
 
 
@@ -178,8 +193,8 @@
 	/** Returns cross section of the plane as a polygon.
 	*/
-	Polygon3 *AxisAlignedBox3::CrossSection(const Plane3 &plane) const;
+	Polygon3 *CrossSection(const Plane3 &plane) const;
 	/** Returns the supporting plane of this face.
 	*/
-	Plane3 AxisAlignedBox3::GetPlane(const int face) const;
+	Plane3 GetPlane(const int face) const;
 	/** Returns 
 		0 if box intersects plane
@@ -190,6 +205,8 @@
 	/**  Calculates the intersection of the polyhedron with the box.
 	*/
-	Polyhedron *CalcIntersection(Polyhedron *polyhedron) const;
-
+	Polyhedron *CalcIntersection(const Polyhedron &polyhedron) const;
+
+
+	bool Intersects(const SimpleRay &ray, float &tnear, float &tfar) const;
 
 	////////////
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.h	(revision 2911)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.h	(revision 2913)
@@ -109,10 +109,4 @@
 	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;
-
-
 protected:
 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polyhedron.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polyhedron.cpp	(revision 2912)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polyhedron.cpp	(revision 2913)
@@ -83,4 +83,5 @@
 
 
+
 float Polyhedron::GetVolume() const
 {
@@ -124,4 +125,5 @@
 {
 	int boxSide = mBox.Side(plane);
+
 	// plane does not intersect bounding box
 	if (boxSide != 0) return boxSide;
@@ -135,5 +137,7 @@
         const int side = (*it)->Side(plane, epsilon);
 
-		if (side != 0)
+		if (side == 0) // intersects polygon => intersects
+			return 0;
+		else if (side != 0)
 		{
 			if (side == -s)
@@ -178,6 +182,20 @@
 	if (mPolygons.size() < 3)
 		return false;
-	else
-		return true;
+	
+	const Vector3 center = CenterOfMass();
+
+	PolygonContainer::const_iterator pit, pit_end = mPolygons.end();
+
+	for (pit = mPolygons.begin(); pit != pit_end; ++ pit)
+	{
+		Polygon3 *poly = *pit;
+		Plane3 plane = poly->GetSupportingPlane();
+
+		float dist = plane.Distance(center);
+		//cout << "dist: " << dist<< endl;
+		if (dist > 0) 
+			return false;
+	}
+	return true;
 }
 
@@ -189,14 +207,20 @@
 	
 	if (intersect == 1)
+	{
 		// on the other side of the plane, the intersection is empty
-		return NULL; 
+		return NULL;
+	}
 	else if (intersect == -1)
-		return NULL;
+	{
 		// does not intersect, just return a copy
-		//return new Polyhedron(*this);
+		return new Polyhedron(*this);
+	}
+
+	// polyhedron is intersected: create new polyhedron
+	Polyhedron *clippedPolyhedron = new Polyhedron();
 
 
 	//////////
-	//-- finally, create and add new polygon to close polyhedron
+	//-- create and add new polygon to close polyhedron
 
 	// get cross section of new polygon
@@ -206,12 +230,10 @@
 	planePoly = SplitPolygon(planePoly);
 
-	// something is wrong, probably some numerical error: just bail out
+	// something is wrong, probably some numerical error
 	if (!planePoly) 
 	{ 
 		cerr << "should not happen" << endl; 
-		return NULL;//new Polyhedron(*this); 
-	}
-
-	Polyhedron *clippedPolyhedron = new Polyhedron();
+		return new Polyhedron(*this); 
+	}
 
 	// add the new polygon to the polyhedron
@@ -221,5 +243,5 @@
 
 	/////////////
-	//-- plane splits all polygons
+	//-- clip polyhedron: plane splits all polygons
 
 	for (int i = 0; i < (int)mPolygons.size(); ++ i)
@@ -260,5 +282,4 @@
 		}
 	}
-	
 
 	return clippedPolyhedron;
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Visualization.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Visualization.cpp	(revision 2911)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Visualization.cpp	(revision 2913)
@@ -151,5 +151,5 @@
 	glDisable(GL_DEPTH_TEST);
 
-	//RenderFrustum();
+	RenderFrustum();
 
 	ShadowMap::DrawPolys();
@@ -183,5 +183,4 @@
 	mCamera->ComputePoints(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr);
 
-	//mCamera->SetF
 	glLineWidth(2);
 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.h	(revision 2911)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.h	(revision 2913)
@@ -6,4 +6,5 @@
 #include "AxisAlignedBox3.h"
 #include "Matrix4x4.h"
+
 #include <Cg/cg.h>
 #include <Cg/cgGL.h>
@@ -58,8 +59,19 @@
 protected:
 
-	void CalcFocussedFrustum(const Matrix4x4 &camProjView, 
-							 const Matrix4x4 &lightProjView, 
-							 Matrix4x4 &focussed);
+	/** Calculates the intersection of the frustum with the box,
+		returns resultin polyhedron as array of polygons.
+	*/
+	Polyhedron *CalcClippedFrustum(const AxisAlignedBox3 &box) const;
 
+
+	bool CalcLightProjection(Matrix4x4 &lightProj);
+
+	void IncludeLightVolume(const Polyhedron &polyhedron, 
+		                    VertexArray &frustumPoints, 
+							const Vector3 lightDir,
+							const AxisAlignedBox3 &sceneBox);
+
+
+	//////////////
 
 	/// the scene bounding box
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.cpp	(revision 2911)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.cpp	(revision 2913)
@@ -108,6 +108,4 @@
 	if (!polyhedron) return;
 
-	cout << "here3" << endl;
-
 	for (size_t i = 0; i < polyhedron->NumPolygons(); ++ i)
 	{
@@ -133,32 +131,165 @@
 
 
-void ShadowMap::CalcFocussedFrustum(const Matrix4x4 &camProjView, 
-									const Matrix4x4 &lightProjView, 
-									Matrix4x4 &focussed)
-{
+void ShadowMap::IncludeLightVolume(const Polyhedron &polyhedron, 
+								   VertexArray &frustumPoints, 
+								   const Vector3 lightDir,
+								   const AxisAlignedBox3 &sceneBox
+								   ) 
+{
+	// we don't need closed form anymore => just store vertices
+	VertexArray vertices;
+	polyhedron.CollectVertices(vertices);
+
+	// we 'look' at each point and calculate intersections of rays with scene bounding box
+	VertexArray::const_iterator it, it_end = vertices.end();
+
+	cout << "=================" << endl;
+
+	for (it = vertices.begin(); it != it_end; ++ it)
+	{
+		Vector3 v  = *it;
+
+		frustumPoints.push_back(v);
+		
+		// hack: get point surely outside of box
+		v -= Magnitude(mSceneBox.Diagonal()) * lightDir;
+
+		//cout << "pt: " << v << endl;
+		SimpleRay ray(v, lightDir);
+
+		float tNear, tFar;
+
+		if (sceneBox.Intersects(ray, tNear, tFar))
+		{
+			Vector3 newpt = ray.Extrap(tNear);
+			Vector3 newpt2 = ray.Extrap(tFar);
+
+			frustumPoints.push_back(newpt);
+
+			if (newpt.z < 220)
+			cout << "ipt: " << newpt << " " << *it << endl;
+		}
+	}
+}
+
+
+bool ShadowMap::CalcLightProjection(Matrix4x4 &lightProj)
+{
+	DEL_PTR(polyhedron);
+
+
 	///////////////////
-	//-- 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);
-	}
+	//-- First step: calc frustum clipped by scene box
+
+	polyhedron = CalcClippedFrustum(mSceneBox);
+
+	if (!polyhedron) return false; // something is wrong
+
+	// include the part of the light volume that "sees" the frustum
+	// we only require frustum vertices
+
+	VertexArray frustumPoints;
+	IncludeLightVolume(*polyhedron, frustumPoints, mShadowCam->GetDirection(), mSceneBox);
+
+
+	///////////////
+	//-- transform points from world view to light view and calculate extremal points
+
+	AxisAlignedBox3 extremalPoints;
+	extremalPoints.Initialize();
+
+	Matrix4x4 lightView;
+	mShadowCam->GetModelViewMatrix(lightView);
+
+	//Matrix4x4 inverseCamView;
+	//mCamera->GetModelViewMatrix(inverseCamView);
+	//Invert(inverseCamView);
+
+	//Matrix4x4 m = inverseCamView * lightView;
+
+	VertexArray::const_iterator it, it_end = frustumPoints.end();
+		
+	for (it = frustumPoints.begin(); it != it_end; ++ it)
+	{
+		Vector3 pt = *it;
+
+		//pt = inverseCamView * pt;
+		pt = lightView * pt;
+		//v = m * v;
+
+		extremalPoints.Include(pt);
+		//cout << "pt: " << pt << endl;
+	}
+
+	// focus projection matrix on the extremal points
+	lightProj = GetFittingProjectionMatrix(extremalPoints);
+
+	/*Vector3 pmax = extremalPoints.Max();
+	Vector3 pmin = extremalPoints.Min();
+
+	cout << "min: " << lightProj * pmin << endl;
+	cout << "max: " << lightProj * pmax << endl;
+	
+	for (it = frustumPoints.begin(); it != it_end; ++ it)
+	{
+		Vector3 pt = *it;
+		
+		pt = lightView * pt;
+		pt = lightProj * pt;
+
+		cout << "pt: " << pt << endl;
+	}*/
+
+	return true;
+}
+
+
+Polyhedron *ShadowMap::CalcClippedFrustum(const AxisAlignedBox3 &box) const
+{
+	Vector3 ftl, ftr, fbl, fbr;
+	Vector3 ntl, ntr, nbl, nbr;
+
+	VertexArray sides[6];
+
+	mCamera->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] = ftl; sides[0][1] = fbl; sides[0][2] = nbl; sides[0][3] = ntl;
+	sides[1][0] = fbr; sides[1][1] = ftr; sides[1][2] = ntr; sides[1][3] = nbr;
+	// bottom, top
+	sides[2][0] = fbl; sides[2][1] = fbr; sides[2][2] = nbr; sides[2][3] = nbl;
+	sides[3][0] = ftr; sides[3][1] = ftl; sides[3][2] = ntl; sides[3][3] = ntr;
+	// near, far
+	sides[4][0] = ntr; sides[4][1] = ntl; sides[4][2] = nbl; sides[4][3] = nbr; 
+	sides[5][0] = ftl; sides[5][1] = ftr; sides[5][2] = fbr; sides[5][3] = fbl; 
+
+	//sides[4][0] = ntl; sides[4][1] = ntr; sides[4][2] = nbr; sides[4][3] = nbl; 
+	//sides[5][0] = ftr; sides[5][1] = ftl; sides[5][2] = fbl; sides[5][3] = fbr;
+
+
+
+	//////////
+	//-- 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);
+	//return p;
+	
+	Polyhedron *clippedPolyhedron = box.CalcIntersection(*p);
+	
+	DEL_PTR(p);
+	
+
+	return clippedPolyhedron;
 }
 
@@ -169,14 +300,19 @@
 	const float ylen = Magnitude(mSceneBox.Diagonal() * 0.5f);
 	
-	mShadowCam->SetDirection(mLight->GetDirection());
-	
+	const Vector3 dir = mLight->GetDirection();
+	//const Vector3 dir(0, 0, 1);
+
+	mShadowCam->SetDirection(dir);
+	
+	//cout << "lightdir: " << mShadowCam->GetDirection() << endl;
+
 	// set position so that we can see the whole scene
 	Vector3 pos = mSceneBox.Center();
 
-	Matrix4x4 camView;
-	mCamera->GetModelViewMatrix(camView);
-
-	pos -= mLight->GetDirection() * Magnitude(mSceneBox.Diagonal() * 0.5f);
-	//mShadowCam->SetPosition(pos);
+	//Matrix4x4 camView;
+	//mCamera->GetModelViewMatrix(camView);
+
+	pos -= dir * Magnitude(mSceneBox.Diagonal() * 0.5f);
+	mShadowCam->SetPosition(pos);
 
 	mFbo->Bind();
@@ -199,11 +335,25 @@
 	glEnable(GL_DEPTH_TEST);
 
+	
+	// setup projection
+	/*glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+	glOrtho(+xlen, -xlen, +ylen, -ylen, 0.0f, Magnitude(mSceneBox.Diagonal())); 
+
+	Matrix4x4 dummyMat;
+	glGetFloatv(GL_PROJECTION_MATRIX, (float *)dummyMat.x);
+	cout << "old:\n" << dummyMat << endl;
+	*/
+	Matrix4x4 lightView, lightProj;
+
+	mShadowCam->GetModelViewMatrix(lightView);
+
+	CalcLightProjection(lightProj);
+
 	glMatrixMode(GL_PROJECTION);
 	glPushMatrix();
-	glLoadIdentity();
-	
-	// setup projection
-	glOrtho(+xlen, -xlen, +ylen, -ylen, 0.0f, Magnitude(mSceneBox.Diagonal())); 
-	
+	glLoadMatrixf((float *)lightProj.x);
+
+	//cout << "new:\n" << lightProj << endl;
 
 	glMatrixMode(GL_MODELVIEW);
@@ -211,47 +361,11 @@
 	glLoadIdentity();
 
-	// setup shadow camera
 	mShadowCam->SetupCameraView();
+
+	mLightProjView = lightView * lightProj;
 
 
 	//////////////
 	//-- compute texture matrix
-
-	Matrix4x4 lightView, lightProj;
-
-	mShadowCam->GetModelViewMatrix(lightView);
-	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,
@@ -260,5 +374,4 @@
 
 	mTextureMatrix = mLightProjView * biasMatrix; 
-	//mTextureMatrix = oldLightProjView * biasMatrix; 
 
 
@@ -279,5 +392,5 @@
 
 	glPopAttrib();
-	/*
+#if 0
 	float *data = new float[mSize * mSize];
 
@@ -288,5 +401,5 @@
 	
 	PrintGLerror("shadow map");
-*/
+#endif
 	FrameBufferObject::Release();
 }
@@ -305,3 +418,4 @@
 
 
+
 } // namespace
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp	(revision 2911)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp	(revision 2913)
@@ -334,10 +334,9 @@
 	///////////////////////////
 
-	camera = new Camera(winWidth, winHeight, fov);
+	camera = new Camera(winWidth, winHeight, 60);//fov);
 	camera->SetNear(nearDist);
-	camera->SetFar(100000);
+	camera->SetFar(1000);
 
 	camera->SetDirection(camDir);
-
 	camera->SetPosition(camPos);
 
@@ -432,5 +431,5 @@
 	bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
 
-	//bvh->SetCamera(camera);
+	camera->SetFar(Magnitude(bvh->GetBox().Diagonal()));
 	
 	InitCg();
@@ -1546,5 +1545,5 @@
 	// hack: set far plane for viz
 	//camera->SetFar(0.35f * Magnitude(box.Diagonal()));
-	camera->SetFar(1);
+	//camera->SetFar(1000);
 
 	const float offs = box.Size().x * 0.3f;
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Matrix4x4.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Matrix4x4.cpp	(revision 2782)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Matrix4x4.cpp	(revision 2913)
@@ -3,5 +3,7 @@
 
 // standard headers
+#include "AxisAlignedBox3.h"
 #include <iomanip>
+
 using namespace std;
 
@@ -648,3 +650,52 @@
 }
 
-}
+
+Matrix4x4 GetFittingProjectionMatrix(const AxisAlignedBox3 &box)
+{
+	Matrix4x4 m;
+
+/*	m.x[0][0] = 2.0f / (box.Max()[0] - box.Min()[0]);
+	m.x[1][0] = .0f;
+	m.x[2][0] = .0f;
+	m.x[3][0] = -(box.Max()[0] + box.Min()[0]) / (box.Max()[0] - box.Min()[0]);
+
+	m.x[0][1] = .0f;
+	m.x[1][1] = 2.0f / (box.Max()[1] - box.Min()[1]);
+	m.x[2][1] = .0f;
+	m.x[3][1] = -(box.Max()[1] + box.Min()[1]) / (box.Max()[1] - box.Min()[1]);
+
+	m.x[0][2] = .0f;
+	m.x[1][2] = .0f;
+	m.x[2][2] = 2.0f / (box.Max()[2] - box.Min()[2]);
+	m.x[3][2] = -(box.Max()[2] + box.Min()[2]) / (box.Max()[2] - box.Min()[2]);
+
+	m.x[0][3] = .0f;
+	m.x[1][3] = .0f;
+	m.x[2][3] = .0f;
+	m.x[3][3] = 1.0f;*/
+
+	m.x[0][0] = -2.0f / (box.Max()[0] - box.Min()[0]);
+	m.x[1][0] = .0f;
+	m.x[2][0] = .0f;
+	m.x[3][0] = (box.Max()[0] + box.Min()[0]) / (box.Max()[0] - box.Min()[0]);
+
+	m.x[0][1] = .0f;
+	m.x[1][1] = -2.0f / (box.Max()[1] - box.Min()[1]);
+	m.x[2][1] = .0f;
+	m.x[3][1] = (box.Max()[1] + box.Min()[1]) / (box.Max()[1] - box.Min()[1]);
+
+	m.x[0][2] = .0f;
+	m.x[1][2] = .0f;
+	m.x[2][2] = -2.0f / (box.Max()[2] - box.Min()[2]);
+	m.x[3][2] = (box.Max()[2] + box.Min()[2]) / (box.Max()[2] - box.Min()[2]);
+
+	m.x[0][3] = .0f;
+	m.x[1][3] = .0f;
+	m.x[2][3] = .0f;
+	m.x[3][3] = 1.0f;
+
+	return m;
+}
+
+
+}
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polygon3.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polygon3.cpp	(revision 2912)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polygon3.cpp	(revision 2913)
@@ -135,5 +135,6 @@
 	else if (classification == FRONT_SIDE)
 		return 1;
-	// plane splits polygon
+
+	// plane splits polygon or is coincident
 	return 0;
 }
@@ -203,5 +204,5 @@
 	if (mVertices.size() < 3)
 		return false;
-
+#if 0
 	// matt: removed for performance issues
 	// check if area exceeds certain size
@@ -224,5 +225,5 @@
 		vtx = *it;
 	}
-	
+#endif
 	return true;
 }
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/AxisAlignedBox3.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/AxisAlignedBox3.cpp	(revision 2911)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/AxisAlignedBox3.cpp	(revision 2913)
@@ -1153,17 +1153,16 @@
 
 
-Plane3 AxisAlignedBox3::GetPlane(const int face) const
+Plane3 AxisAlignedBox3::GetPlane(int face) const
 {
 	switch (face) 
 	{
-        
 	case 0:
+		return Plane3(Vector3(0, -1, 0), mMin);
+	case 1:
+		return Plane3(Vector3(0, 1, 0), mMax);
+	case 2:
 		return Plane3(Vector3(-1, 0, 0), mMin);
-	case 1: 
+	case 3: 
 		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);
@@ -1176,4 +1175,22 @@
 }
 
+
+/*int AxisAlignedBox3::Side(const Plane3 &plane) const
+{
+	Vector3 v;
+	int i, m=3, M=-3, s;
+
+	for (i=0;i<8;i++) 
+	{
+		GetVertex(i, v);
+	
+		if((s = plane.Side(v)) < m) m=s;
+		if(s > M) M=s;
+		if (m && m==-M)	return 0;
+	}
+
+	return (m == M) ? m : m + M;
+}
+*/
 
 int AxisAlignedBox3::Side(const Plane3 &plane) const
@@ -1203,17 +1220,26 @@
 
 
-Polyhedron *AxisAlignedBox3::CalcIntersection(Polyhedron *polyhedron) const
-{
-	Polyhedron *oldPolyhedron = new Polyhedron(*polyhedron);
-
+Polyhedron *AxisAlignedBox3::CalcIntersection(const Polyhedron &polyhedron) const
+{
+	Polyhedron *oldPolyhedron = new Polyhedron(polyhedron);
+
+	if (!oldPolyhedron->Valid()) cerr << "******************* not valid!! ************* " << endl;
+	
 	Polyhedron *newPolyhedron = NULL;
 
 	for (int i = 0; i < 6; ++ i)
 	{
-		Polyhedron *newPolyhedron = oldPolyhedron->CalcIntersection(GetPlane(i));
+		newPolyhedron = oldPolyhedron->CalcIntersection(GetPlane(i));
+
+		if (!newPolyhedron || !newPolyhedron->Valid())
+		{
+			DEL_PTR(newPolyhedron);
+			cerr << "polyhedron not valid or NULL!" << endl; 
+
+			return NULL;	
+		}
+
 		DEL_PTR(oldPolyhedron);
-
-		if (!newPolyhedron)
-			return NULL;
+		oldPolyhedron = newPolyhedron;
 	}
 
@@ -1222,4 +1248,100 @@
 
 
-}
-
+
+bool AxisAlignedBox3::Intersects(const SimpleRay &ray, float &tnear, float &tfar) const
+{
+	tnear = -1e20f;
+	tfar = 1e20f;
+
+	const Vector3 origin = ray.mOrigin;
+	const Vector3 dir = ray.mDirection;
+
+	float t1, t2;
+
+	// ray is parallel to the planes
+	if (dir.x == 0) 
+	{
+		if ((origin.x < mMin.x) || (origin.x > mMax.x)) 
+			return false; // origin not between planes
+	}
+	else
+	{
+		// time at which ray intersects minimum X plane
+		t1 = (mMin.x - origin.x) / dir.x;
+		// time at which ray intersects maximum X plane
+		t2 = (mMax.x - origin.x) / dir.x;
+		
+		if (t1 > t2)
+			swap(t1, t2);
+		
+		if (t1 > tnear)
+			tnear = t1;
+		
+		if (t2 < tfar)
+			tfar = t2;
+		
+		if (tnear > tfar)
+			return false;
+		
+		if (tfar < 0)
+			return false;
+	}
+
+	if (dir.y == 0) // ray is parallel to the planes
+	{
+		if ((origin.y < mMin.y) || (origin.y > mMax.y)) 
+			return false; // origin not between planes)
+	}
+	else
+	{
+		t1 = (mMin.y - origin.y) / dir.y; 
+		t2 = (mMax.y - origin.y) / dir.y; 
+		
+		if (t1 > t2)
+			swap(t1, t2);
+		
+		if (t1 > tnear)
+			tnear = t1;
+		
+		if (t2 < tfar)
+			tfar = t2;
+		
+		if (tnear > tfar)
+			return false;
+		
+		if (tfar < 0)
+			return false;
+	}
+
+	if (dir.z == 0) // ray is parallel to the planes
+	{
+		if ((origin.z < mMin.z) || (origin.z > mMax.z)) 
+			return false; // origin not between planes)
+	}
+	else
+	{
+		t1 = (mMin.z - origin.z) / dir.z; 
+		t2 = (mMax.z - origin.z) / dir.z; 
+		
+		if (t1 > t2)
+			swap(t1, t2);
+		
+		if (t1 > tnear)
+			tnear = t1;
+		
+		if (t2 < tfar)
+			tfar = t2;
+		
+		if (tnear > tfar)
+			return false;
+		
+		if (tfar < 0)
+			return false;
+	}
+
+	return true;
+}
+
+
+}
+
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.cpp	(revision 2911)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.cpp	(revision 2913)
@@ -151,9 +151,11 @@
 	float fov = mFovy;
 
+	const float aspectRatio = GetAspect();
+
 	const float w_near = 2.0f * tan(fov * 0.5f) * z_near;
-	const float h_near = w_near / GetAspect();
+	const float h_near = w_near / aspectRatio;
 
 	const float w_far = 2.0f * tan(fov * 0.5f) * z_far;
-	const float h_far = w_far / GetAspect();
+	const float h_far = w_far / aspectRatio;
 
 	const Vector3 fc = pos + view * z_far; 
@@ -196,48 +198,4 @@
 }
 
-
-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;
-}
 
 
Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/common.h
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/common.h	(revision 2911)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/common.h	(revision 2913)
@@ -30,4 +30,5 @@
 struct LODLevel;
 class Polygon3;
+class Vector3;
 
 
@@ -493,4 +494,7 @@
 typedef std::vector<Polygon3 *> PolygonContainer;
 
+typedef std::vector<Vector3> VertexArray;
+
+
 static std::ofstream Debug("debug.log");
 
