Index: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.cpp
===================================================================
--- GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.cpp	(revision 2943)
+++ GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.cpp	(revision 2944)
@@ -187,7 +187,75 @@
 
 
+// z0 is the point that lies on the parallel plane to the near plane through e (A)
+//and on the near plane of the C frustum (the plane z = bZmax) and on the line x = e.x
+Vector3 ShadowMap::GetLightSpaceZ0(const Matrix4x4 &lightSpace, 
+								   const Vector3 &e, 
+								   const float maxZ, 
+								   const Vector3 &eyeDir) const 
+{
+	// to calculate the parallel plane to the near plane through e we 
+	// calculate the plane A with the three points
+	Plane3 planeA(e, eyeDir);
+
+	planeA.Transform(lightSpace);
+	
+	// get the parameters of A from the plane equation n dot d = 0
+	const float d = planeA.mD;
+	const Vector3 n = planeA.mNormal;
+	
+	// transform to light space
+	const Vector3 e_ls = lightSpace * e;
+
+	Vector3 z0;
+
+	z0.x = e_ls.x;
+	z0.y = (d - n.z * maxZ - n.x * e_ls.x) / n.y;
+	z0.z = maxZ;
+
+	return z0;
+	//return V3(e_ls.x(),(d-n.z()*b_lsZmax-n.x()*e_ls.x())/n.y(),b_lsZmax);
+}
+
+
+float ShadowMap::ComputeNOpt(const Matrix4x4 &lightSpace, 
+							 const AxisAlignedBox3 &extremalPoints,
+							 const VertexArray &body) const
+{
+	const Vector3 nearPt = GetNearCameraPointE(body);
+	const Vector3 eyeDir = mCamera->GetDirection();
+
+	Matrix4x4 eyeView;
+	mCamera->GetModelViewMatrix(eyeView);
+
+	const Matrix4x4 invLightSpace = Invert(lightSpace);
+
+	const Vector3 z0_ls = GetLightSpaceZ0(lightSpace, nearPt, extremalPoints.Max().z, eyeDir);
+	const Vector3 z1_ls = Vector3(z0_ls.x, z0_ls.y, extremalPoints.Min().z);
+	
+	// transform back to world space
+	const Vector3 z0_ws = invLightSpace * z0_ls;
+	const Vector3 z1_ws = invLightSpace * z1_ls;
+
+	// transform to eye space
+	const Vector3 z0_es = eyeView * z0_ws;
+	const Vector3 z1_es = eyeView * z1_ws;
+
+	const float z0 = z0_es.z;
+	const float z1 = z1_es.z;
+
+	cout << "z0 ls: " << z0_ls << " z1 ls: " << z1_ls << endl;
+	cout << "z0: " << z0_es << " z1: " << z1_es << endl;
+
+	const float d = fabs(extremalPoints.Max()[2] - extremalPoints.Min()[2]); 
+
+	const float n = d / (sqrt(z1 / z0) - 1.0f);
+
+	return n;
+}
+
+
 float ShadowMap::ComputeN(const AxisAlignedBox3 &extremalPoints) const 
 {
-	const float n = mCamera->GetNear();
+	const float nearPlane = mCamera->GetNear();
 	
 	const float d = fabs(extremalPoints.Max()[2] - extremalPoints.Min()[2]); 
@@ -196,5 +264,8 @@
 	const float sinGamma = sin(fabs(acos(dotProd)));
 
-	return (n + sqrt(n * (n + d * sinGamma))) /  sinGamma;
+	// test for values close to zero
+	if (sinGamma < 1e-6f) return 1e6f;
+	
+	return (nearPlane + sqrt(nearPlane * (nearPlane + d * sinGamma))) /  sinGamma;
 }
 
@@ -205,6 +276,4 @@
 										 )
 {
-	//return IdentityMatrix();
-
 	AxisAlignedBox3 bounds_ls = GetExtremalPoints(lightSpace, body);
 
@@ -213,7 +282,11 @@
 	//-- first find the free parameter values n, and P (the projection center), and the projection depth
 
-	const float n = ComputeN(bounds_ls);
-
-	//cout << "n: " << n << endl;
+	//const float n = ComputeN(bounds_ls);
+	const float n = ComputeNOpt(lightSpace, extremalPoints, body);
+
+	cout << "n: " << n << endl;
+
+	if (n >= 1e6f) // light direction nearly parallel to view => switch to uniform
+		return IdentityMatrix();
 
 	const Vector3 nearPt = GetNearCameraPointE(body);
@@ -358,5 +431,4 @@
 
 	VertexArray frustumPoints;
-	//Vector3 lightDir = Vector3(0, 0, -1);
 	IncludeLightVolume(*polyhedron, frustumPoints, mLight->GetDirection(), mSceneBox);
 
@@ -392,5 +464,5 @@
 	//look(from position, into the direction of the projected direction, with unchanged up-vector)
 	//const Matrix4x4 frame = MyLookAt2(Vector3::ZERO(), projViewDir, Vector3::UNIT_Y());
-	const Matrix4x4 frame = MyLookAt(Vector3::ZERO(), projViewDir, Vector3::UNIT_Y());
+	const Matrix4x4 frame = LookAt(Vector3::ZERO(), projViewDir, Vector3::UNIT_Y());
 
 	lightProj *= frame;
@@ -600,5 +672,5 @@
 
 	Vector3 upVec = CalcUpVec(mCamera->GetDirection(), dir);
-	Matrix4x4 lightView = MyLookAt(mShadowCam->GetPosition(), dir, upVec);
+	Matrix4x4 lightView = LookAt(mShadowCam->GetPosition(), dir, upVec);
 
 	mShadowCam->mViewOrientation = lightView;
@@ -606,5 +678,5 @@
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
-	glPolygonOffset(1.0f, 2000.0f);
+	glPolygonOffset(5.0f, 100.0f);
 	glEnable(GL_POLYGON_OFFSET_FILL);
 	
