Example #1
0
	AABB3::operator OBB3() const {
		Vector3 siz = max - min;
		return OBB3(Matrix4(siz.x, 0, 0, 0,
							0, siz.y, 0, 0,
							0, 0, siz.z, 0,
							min.x, min.y, min.z, 1));
	}
		void GLBasicShadowMapRenderer::BuildMatrix(float near, float far){
			// TODO: variable light direction?
			Vector3 lightDir = MakeVector3(0, -1, -1).Normalize();
			// set better up dir?
			Vector3 up = MakeVector3(0, 0, 1);
			Vector3 side = Vector3::Cross(up, lightDir).Normalize();
			up = Vector3::Cross(lightDir, side).Normalize();
			
			// build frustrum
			client::SceneDefinition def = GetRenderer()->GetSceneDef();
			Vector3 frustrum[8];
			float tanX = tanf(def.fovX * .5f);
			float tanY = tanf(def.fovY * .5f);
			
			frustrum[0] = FrustrumCoord(def, tanX, tanY, near);
			frustrum[1] = FrustrumCoord(def, tanX, -tanY, near);
			frustrum[2] = FrustrumCoord(def, -tanX, tanY, near);
			frustrum[3] = FrustrumCoord(def, -tanX, -tanY, near);
			frustrum[4] = FrustrumCoord(def, tanX, tanY, far);
			frustrum[5] = FrustrumCoord(def, tanX, -tanY, far);
			frustrum[6] = FrustrumCoord(def, -tanX, tanY, far);
			frustrum[7] = FrustrumCoord(def, -tanX, -tanY, far);
			
			// compute frustrum's x,y boundary
			float minX, maxX, minY, maxY;
			minX = maxX = Vector3::Dot(frustrum[0], side);
			minY = maxY = Vector3::Dot(frustrum[0], up);
			for(int i = 1; i < 8; i++){
				float x = Vector3::Dot(frustrum[i], side);
				float y = Vector3::Dot(frustrum[i], up);
				if(x < minX) minX = x;
				if(x > maxX) maxX = x;
				if(y < minY) minY = y;
				if(y > maxY) maxY = y;
			}
			
			// compute frustrum's z boundary
			Segment seg;
			Plane3 plane1(0,0,1,-4.f);
			Plane3 plane2(0,0,1,64.f);
			seg += ZRange(side * minX + up * minY,
						  lightDir, plane1, plane2);
			seg += ZRange(side * minX + up * maxY,
						  lightDir, plane1, plane2);
			seg += ZRange(side * maxX + up * minY,
						  lightDir, plane1, plane2);
			seg += ZRange(side * maxX + up * maxY,
						  lightDir, plane1, plane2);
			
			
			for(int i = 1; i < 8; i++){
				seg += Vector3::Dot(frustrum[i], lightDir);
			}
			
			
			// build frustrum obb
			Vector3 origin = side * minX + up * minY + lightDir * seg.low;
			Vector3 axis1 = side * (maxX - minX);
			Vector3 axis2 = up * (maxY - minY);
			Vector3 axis3 = lightDir * (seg.high - seg.low);
			
			obb = OBB3(Matrix4::FromAxis(axis1, axis2, axis3,
										 origin));
			vpWidth = 2.f / axis1.GetLength();
			vpHeight = 2.f / axis2.GetLength();
		
			// convert to projectionview matrix
			matrix = obb.m.InversedFast();
			
			matrix = Matrix4::Scale(2.f) * matrix;
			matrix = Matrix4::Translate(-1, -1, -1) * matrix;
			
			// scale a little big for padding
			matrix = Matrix4::Scale(.98f) * matrix;
			//
			matrix = Matrix4::Scale(1,1,-1) * matrix;
			
			// make sure frustrums in range
#ifndef NDEBUG
			for(int i = 0; i < 8; i++){
				Vector4 v = matrix * frustrum[i];
				SPAssert(v.x >= -1.f);
				SPAssert(v.y >= -1.f);
				//SPAssert(v.z >= -1.f);
				SPAssert(v.x < 1.f);
				SPAssert(v.y < 1.f);
				//SPAssert(v.z < 1.f);
			}
#endif
		}