Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.h
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.h	(revision 2913)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.h	(revision 2931)
@@ -108,4 +108,7 @@
 	*/
 	void SetDirection(const Vector3 &direction);
+	/** Returns frustum as polyhedron.
+	*/
+	Polyhedron *Camera::ComputeFrustum() const;
 
 protected:
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polyhedron.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polyhedron.cpp	(revision 2929)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Polyhedron.cpp	(revision 2931)
@@ -15,7 +15,7 @@
 
 
-/**********************************************************/
-/*             class Polyhedron Implementation             */
-/**********************************************************/
+/************************************************************/
+/*              class Polyhedron Implementation             */
+/************************************************************/
 
 
@@ -57,6 +57,4 @@
 
 	if (!oldPolyhedron->Valid()) cerr << "******************* not valid!! ************* " << endl;
-
-	//oldPolyhedron->mBox = sceneBox;
 
 	vector<Plane3>::const_iterator it, it_end = planes.end();
@@ -77,7 +75,4 @@
 		}
 
-		// hack: set bounding box temporarily to scene bounding box
-		//newPolyhedron->mBox = sceneBox;
-
 		DEL_PTR(oldPolyhedron);
 		oldPolyhedron = newPolyhedron;
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Visualization.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Visualization.cpp	(revision 2929)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Visualization.cpp	(revision 2931)
@@ -174,5 +174,4 @@
 
 	glDepthMask(GL_TRUE);
-
 	glPopAttrib();
 }
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.h
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.h	(revision 2929)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.h	(revision 2931)
@@ -56,4 +56,6 @@
 	Camera *GetShadowCamera() const { return mShadowCam; }
 
+	void RenderShadowView(RenderTraverser *renderer, const Matrix4x4 &projView);
+
 
 	static void DrawPolys();
@@ -61,4 +63,5 @@
 
 protected:
+
 
 	/** Calculates the intersection of the frustum with the box,
@@ -106,4 +109,6 @@
 
 	Matrix4x4 mLightProjView;
+
+	Matrix4x4 mLightMatrix;
 };
 
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.cpp	(revision 2929)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.cpp	(revision 2931)
@@ -17,4 +17,7 @@
 {
 
+static CGprogram sCgShadowProgram;
+static CGparameter sShadowParam;
+
 
 static Polyhedron *polyhedron = NULL;
@@ -35,7 +38,34 @@
 
 
-
-static CGprogram sCgShadowProgram;
-static CGparameter sShadowParam;
+static Polyhedron *CreatePolyhedron(const Matrix4x4 &lightMatrix, const AxisAlignedBox3 &sceneBox)
+{
+	Frustum frustum(lightMatrix);
+
+	vector<Plane3> clipPlanes;
+
+	for (int i = 0; i < 6; ++ i)
+	{
+		////////////
+		//-- normalize the coefficients
+
+		// the clipping planes look outward the frustum,
+		// so distances > 0 mean that a point is outside
+		const float invLength = -1.0f / Magnitude(frustum.mClipPlanes[i].mNormal);
+
+		frustum.mClipPlanes[i].mD *= invLength;
+		frustum.mClipPlanes[i].mNormal *= invLength;
+
+		//clipPlanes.push_back(frustum.mClipPlanes[i]);
+	}
+
+	clipPlanes.push_back(frustum.mClipPlanes[5]);
+	clipPlanes.push_back(frustum.mClipPlanes[0]);
+	clipPlanes.push_back(frustum.mClipPlanes[1]);
+	clipPlanes.push_back(frustum.mClipPlanes[2]);
+	clipPlanes.push_back(frustum.mClipPlanes[3]);
+	clipPlanes.push_back(frustum.mClipPlanes[4]);
+
+	return Polyhedron::CreatePolyhedron(clipPlanes, sceneBox);
+}
 
 
@@ -182,6 +212,6 @@
 	//-- first find the free parameter values n, and P (the projection center), and the projection depth
 
-	//const float n = 1e6f;
-	const float n = 1e3f;
+	//const float n = 1e2f;
+	const float n = 1e6f;
 	//const float n = ComputeN(bounds_ls) * 100;
 
@@ -431,42 +461,27 @@
 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; 
-
-	//////////
-	//-- 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 *p = mCamera->ComputeFrustum();
+	
 	Polyhedron *clippedPolyhedron = box.CalcIntersection(*p);
-	
+
 	DEL_PTR(p);
 	
-
 	return clippedPolyhedron;
+}
+
+
+//calculates the up vector for the light coordinate frame
+static Vector3 CalcUpVec(const Vector3 viewDir, const Vector3 lightDir) 
+{
+	//we do what gluLookAt does...
+	//left is the normalized vector perpendicular to lightDir and viewDir
+	//this means left is the normalvector of the yz-plane from the paper
+	Vector3 left = CrossProd(lightDir, viewDir);
+	
+	//we now can calculate the rotated(in the yz-plane) viewDir vector
+	//and use it as up vector in further transformations
+	Vector3 up = CrossProd(left, lightDir);
+
+	return Normalize(up);
 }
 
@@ -479,4 +494,7 @@
 	//const Vector3 dir = mLight->GetDirection();
 	const Vector3 dir(0, 0, -1);
+
+	Vector3 upVec = CalcUpVec(mCamera->GetDirection(), dir);
+	mLightMatrix = LookAt(mCamera->GetPosition(), dir, upVec);
 
 	mShadowCam->SetDirection(dir);
@@ -526,5 +544,7 @@
 	Matrix4x4 lightView, lightProj;
 
-	mShadowCam->GetModelViewMatrix(lightView);
+	//mShadowCam->GetModelViewMatrix(lightView);
+	lightView = mLightMatrix;
+
 	CalcLightProjection(lightProj);
 
@@ -535,21 +555,6 @@
 	mLightProjView = lightView * lightProj;
 
-	Frustum frustum(mLightProjView);
-	//Frustum frustum(projView);
-
 	DEL_PTR(lightPoly);
-
-	vector<Plane3> clipPlanes;
-
-	for (int i = 0; i < 6; ++ i)
-	{
-		frustum.mClipPlanes[i].mNormal *= -1;
-		frustum.mClipPlanes[i].mD *= -1;
-
-		clipPlanes.push_back(frustum.mClipPlanes[i]);
-	}
-
-	DEL_PTR(lightPoly);
-	lightPoly = Polyhedron::CreatePolyhedron(clipPlanes, mSceneBox);
+	lightPoly = CreatePolyhedron(mLightProjView, mSceneBox);
 
 	//cout << "new:\n" << lightProj << endl;
@@ -559,6 +564,6 @@
 	glLoadIdentity();
 
-	mShadowCam->SetupCameraView();
-
+	//mShadowCam->SetupCameraView();
+	glLoadMatrixf((float *)mLightMatrix.x);
 
 	//////////////
@@ -606,4 +611,5 @@
 	FrameBufferObject::Release();
 }
+
 
 
@@ -661,3 +667,103 @@
 
 
+void ShadowMap::RenderShadowView(RenderTraverser *renderer, const Matrix4x4 &projView)
+{
+	//const Vector3 dir = mLight->GetDirection();
+	const Vector3 dir(0, 0, -1);
+
+	mShadowCam->SetDirection(dir);
+
+	Vector3 upVec = CalcUpVec(mCamera->GetDirection(), dir);
+	mLightMatrix = LookAt(mCamera->GetPosition(), dir, upVec);
+
+	// set position so that we can see the whole scene
+	Vector3 pos = mSceneBox.Center();
+
+	pos -= dir * Magnitude(mSceneBox.Diagonal() * 0.5f);
+	mShadowCam->SetPosition(pos);
+
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+	glEnable(GL_LIGHTING);
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+	glPolygonOffset(1.0f, 2000.0f);
+	glEnable(GL_POLYGON_OFFSET_FILL);
+glDisable(GL_CULL_FACE);
+	glEnable(GL_DEPTH_TEST);
+
+	Matrix4x4 lightView, lightProj;
+	
+	//mShadowCam->GetModelViewMatrix(lightView);
+	lightView = mLightMatrix;
+	CalcLightProjection(lightProj);
+
+	glMatrixMode(GL_PROJECTION);
+	glPushMatrix();
+	glLoadMatrixf((float *)lightProj.x);
+
+	mLightProjView = lightView * lightProj;
+
+	DEL_PTR(lightPoly);
+	lightPoly = CreatePolyhedron(mLightProjView, mSceneBox);
+
+	//cout << "new:\n" << lightProj << endl;
+
+	glMatrixMode(GL_MODELVIEW);
+	glPushMatrix();
+	glLoadIdentity();
+
+	//mShadowCam->SetupCameraView();
+	glLoadMatrixf((float *)mLightMatrix.x);
+
+
+	/////////////
+	//-- render scene into shadow map
+
+	renderer->RenderScene();
+
+	
+	glDisable(GL_POLYGON_OFFSET_FILL);
+
+	glPushAttrib(GL_CURRENT_BIT);
+	glDisable(GL_LIGHTING);
+	glDisable(GL_DEPTH_TEST);
+	glDepthMask(GL_FALSE);
+	glDisable(GL_CULL_FACE);
+
+	Polyhedron *hpoly = CreatePolyhedron(projView, mSceneBox);
+	//Polyhedron *hpoly = CalcClippedFrustum(mSceneBox);
+	
+	DrawPoly(hpoly, Vector3(1, 1, 1));
+	DEL_PTR(hpoly);
+
+	glEnable(GL_CULL_FACE);
+
+	glEnable(GL_DEPTH_TEST);
+	glDepthMask(GL_TRUE);
+	glPopAttrib();
+
+	glMatrixMode(GL_MODELVIEW);
+	glPopMatrix();
+
+	glMatrixMode(GL_PROJECTION);
+	glPopMatrix();
+
+
+#if 0
+	float *data = new float[mSize * mSize];
+
+	GrabDepthBuffer(data, mFbo->GetDepthTex());
+	ExportDepthBuffer(data, mSize);
+
+	delete [] data;
+	
+	PrintGLerror("shadow map");
+#endif
+	FrameBufferObject::Release();
+}
+
+
+
+
 } // namespace
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp	(revision 2930)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp	(revision 2931)
@@ -100,4 +100,5 @@
 static int winHeight = 768;
 
+const float shadowSize = 4096;
 
 static float winAspectRatio = 1.0f;
@@ -179,4 +180,7 @@
 
 static Matrix4x4 matProjectionView = IdentityMatrix();
+
+bool renderLightView = false;
+
 
 
@@ -873,5 +877,23 @@
 	
 
-	// render without shading
+
+	if ((!shadowMap || !shadowTraverser) && (showShadowMap || renderLightView))
+	{
+		if (!shadowMap)
+			shadowMap = new ShadowMap(light, shadowSize, bvh->GetBox(), camera);
+
+		if (!shadowTraverser)
+			shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
+
+	}
+
+	// hack
+	int oldRenderType = renderType;
+
+	if (renderLightView)
+		renderType = RenderState::FIXED;
+
+
+	// render with the specified method (forward rendering, forward + depth, deferred)
 	switch (renderType)
 	{
@@ -909,35 +931,7 @@
 	case RenderState::DEFERRED:
 
-		if (showShadowMap)// && shadowChanged)
+		if (showShadowMap && !renderLightView)// && shadowChanged)
 		{
-			if (!shadowMap)
-			{
-				const float shadowSize = 4096;
-				//const float shadowSize = 512;
-				shadowMap = new ShadowMap(light, shadowSize, bvh->GetBox(), camera);
-			}
-
-			// change CHC state (must be done for each change of camera)
-			BvhNode::SetCurrentState(1);
-
-			if (!shadowTraverser)
-				shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
-
 			shadowChanged = false;
-
-#if 0
-			state.SetRenderType(RenderState::DEFERRED);
-
-			fbo->Bind();
-
-			glPushAttrib(GL_VIEWPORT_BIT);
-			glViewport(0, 0, texWidth, texHeight);
-
-			cgGLEnableProfile(RenderState::sCgFragmentProfile);
-			cgGLBindProgram(RenderState::sCgMrtFragmentProgram);
-
-			cgGLEnableProfile(RenderState::sCgVertexProfile);
-			cgGLBindProgram(sCgMrtVertexProgram);
-#else
 
 			cgGLDisableProfile(RenderState::sCgFragmentProfile);
@@ -945,5 +939,9 @@
 
 			state.SetRenderType(RenderState::DEPTH_PASS);
-#endif
+			
+			// change CHC++ set of state variables (must be done for each change of camera because
+			// otherwise the temporal coherency is broken
+			BvhNode::SetCurrentState(1);
+
 			// the scene is rendered withouth any shading	
 			shadowMap->ComputeShadowMap(shadowTraverser, matProjectionView);
@@ -1002,6 +1000,16 @@
 	glLightfv(GL_LIGHT1, GL_POSITION, position1);
 
-	// actually render the scene geometry using the specified algorithm
-	traverser->RenderScene();
+
+	if (renderLightView)
+	{
+		// change CHC++ set of state variables (must be done for each change of camera because
+		// otherwise the temporal coherency is broken
+		BvhNode::SetCurrentState(1);
+		shadowMap->RenderShadowView(shadowTraverser, matProjectionView);
+		BvhNode::SetCurrentState(0);
+	}
+	else
+		// actually render the scene geometry using the specified algorithm
+		traverser->RenderScene();
 
 
@@ -1068,5 +1076,6 @@
 	glDisableClientState(GL_VERTEX_ARRAY);
 	glDisableClientState(GL_NORMAL_ARRAY);
-
+	
+	renderType = oldRenderType;
 
 
@@ -1114,8 +1123,8 @@
 		traverser = CreateTraverser(camera);
 
-		if (shadowTraverser && shadowMap) 
+		if (shadowTraverser)
 		{
+			// shadow traverser has to be recomputed (this is done on demand)
 			DEL_PTR(shadowTraverser);
-			//shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
 		}
 
@@ -1202,31 +1211,32 @@
 	case 'a':
 	case 'A':
-			leftKeyPressed = true;
+		leftKeyPressed = true;
 		break;
 	case 'd':
 	case 'D':
-			rightKeyPressed = true;
+		rightKeyPressed = true;
 		break;
 	case 'w':
 	case 'W':
-			upKeyPressed = true;
+		upKeyPressed = true;
 		break;
 	case 's':
 	case 'S':
-			downKeyPressed = true;
+		downKeyPressed = true;
 		break;
 	case 'r':
 	case 'R':
-		{
-			useRenderQueue = !useRenderQueue;
-			traverser->SetUseRenderQueue(useRenderQueue);
-		}
+		useRenderQueue = !useRenderQueue;
+		traverser->SetUseRenderQueue(useRenderQueue);
+		
 		break;
 	case 'b':
 	case 'B':
-		{
-			useTightBounds = !useTightBounds;
-			traverser->SetUseTightBounds(useTightBounds);
-		}
+		useTightBounds = !useTightBounds;
+		traverser->SetUseTightBounds(useTightBounds);
+		break;
+	case 'l':
+	case 'L':
+		renderLightView = !renderLightView;
 		break;
 	default:
Index: /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.cpp
===================================================================
--- /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.cpp	(revision 2928)
+++ /GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.cpp	(revision 2931)
@@ -337,5 +337,41 @@
 
 
-
-}
-
+Polyhedron *Camera::ComputeFrustum() const
+{
+	Vector3 ftl, ftr, fbl, fbr;
+	Vector3 ntl, ntr, nbl, nbr;
+
+	VertexArray sides[6];
+
+	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; 
+
+
+	//////////
+	//-- compute polyhedron
+
+	PolygonContainer polygons;
+
+	for (int i = 0; i < 6; ++ i)
+	{
+		Polygon3 *poly = new Polygon3(sides[i]);
+		polygons.push_back(poly);
+	}
+
+	return new Polyhedron(polygons);
+}
+
+
+}
