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 }