//----------------------------------------------------------------------- void LiSPSMShadowCameraSetup::getShadowCamera (const SceneManager *sm, const Camera *cam, const Viewport *vp, const Light *light, Camera *texCam) const { // check availability - viewport not needed OgreAssert(sm != NULL, "SceneManager is NULL"); OgreAssert(cam != NULL, "Camera (viewer) is NULL"); OgreAssert(light != NULL, "Light is NULL"); OgreAssert(texCam != NULL, "Camera (texture) is NULL"); mLightFrustumCameraCalculated = false; // calculate standard shadow mapping matrix Matrix4 LView, LProj; calculateShadowMappingMatrix(*sm, *cam, *light, &LView, &LProj, NULL); // build scene bounding box const VisibleObjectsBoundsInfo& visInfo = sm->getShadowCasterBoundsInfo(light); AxisAlignedBox sceneBB = visInfo.aabb; sceneBB.merge(sm->getVisibleObjectsBoundsInfo(cam).aabb); sceneBB.merge(cam->getDerivedPosition()); // in case the sceneBB is empty (e.g. nothing visible to the cam) simply // return the standard shadow mapping matrix if (sceneBB.isNull()) { texCam->setCustomViewMatrix(true, LView); texCam->setCustomProjectionMatrix(true, LProj); return; } // calculate the intersection body B mPointListBodyB.reset(); calculateB(*sm, *cam, *light, sceneBB, &mPointListBodyB); // in case the bodyB is empty (e.g. nothing visible to the light or the cam) // simply return the standard shadow mapping matrix if (mPointListBodyB.getPointCount() == 0) { texCam->setCustomViewMatrix(true, LView); texCam->setCustomProjectionMatrix(true, LProj); return; } // transform to light space: y -> -z, z -> y LProj = msNormalToLightSpace * LProj; // calculate LVS so it does not need to be calculated twice // calculate the body L \cap V \cap S to make sure all returned points are in // front of the camera calculateLVS(*sm, *cam, *light, sceneBB, &mPointListBodyLVS); // fetch the viewing direction const Vector3 viewDir = getLSProjViewDir(LProj * LView, *cam, mPointListBodyLVS); // The light space will be rotated in such a way, that the projected light view // always points upwards, so the up-vector is the y-axis (we already prepared the // light space for this usage).The transformation matrix is set up with the // following parameters: // - position is the origin // - the view direction is the calculated viewDir // - the up vector is the y-axis LProj = buildViewMatrix(Vector3::ZERO, viewDir, Vector3::UNIT_Y) * LProj; // calculate LiSPSM projection LProj = calculateLiSPSM(LProj * LView, mPointListBodyB, mPointListBodyLVS, *sm, *cam, *light) * LProj; // map bodyB to unit cube LProj = transformToUnitCube(LProj * LView, mPointListBodyB) * LProj; // transform from light space to normal space: y -> z, z -> -y LProj = msLightSpaceToNormal * LProj; // LView = Lv^-1 // LProj = Switch_{-ls} * FocusBody * P * L_r * Switch_{ls} * L_p texCam->setCustomViewMatrix(true, LView); texCam->setCustomProjectionMatrix(true, LProj); }
void DiFocusedShadowPolicy::getShadowCamera (const DiSceneManager *sm, const DiCamera *cam, const DiViewport *vp, const DiLight *light, DiCamera *texCam, size_t iteration) const { // check availability - viewport not needed DI_ASSERT_MESSAGE(sm != NULL, "SceneManager is NULL"); DI_ASSERT_MESSAGE(cam != NULL, "Camera (viewer) is NULL"); DI_ASSERT_MESSAGE(light != NULL, "Light is NULL"); DI_ASSERT_MESSAGE(texCam != NULL, "Camera (texture) is NULL"); mLightFrustumCameraCalculated = false; texCam->SetNearClipDistance(light->DeriveShadowNearClipDistance(cam)); texCam->SetFarClipDistance(light->DeriveShadowFarClipDistance(cam)); // calculate standard shadow mapping matrix DiMat4 LView, LProj; calculateShadowMappingMatrix(*sm, *cam, *light, &LView, &LProj, NULL); // build scene bounding box auto& visInfo = texCam->GetVisBoundsInfo(); DiAABB sceneBB = visInfo.aabb; DiAABB receiverAABB = cam->GetVisBoundsInfo().receiverAabb; sceneBB.Merge(receiverAABB); sceneBB.Merge(cam->GetDerivedPosition()); // in case the sceneBB is empty (e.g. nothing visible to the cam) simply // return the standard shadow mapping matrix if (sceneBB.IsNull()) { texCam->SetCustomViewMatrix(true, LView); texCam->SetCustomProjectionMatrix(true, LProj); return; } // calculate the intersection body B mPointListBodyB.reset(); calculateB(*sm, *cam, *light, sceneBB, receiverAABB, &mPointListBodyB); // in case the bodyB is empty (e.g. nothing visible to the light or the cam) // simply return the standard shadow mapping matrix if (mPointListBodyB.getPointCount() == 0) { texCam->SetCustomViewMatrix(true, LView); texCam->SetCustomProjectionMatrix(true, LProj); return; } // transform to light space: y -> -z, z -> y LProj = msNormalToLightSpace * LProj; // calculate LVS so it does not need to be calculated twice // calculate the body L \cap V \cap S to make sure all returned points are in // front of the camera mPointListBodyLVS.reset(); calculateLVS(*sm, *cam, *light, sceneBB, &mPointListBodyLVS); // fetch the viewing direction const DiVec3 viewDir = getLSProjViewDir(LProj * LView, *cam, mPointListBodyLVS); // The light space will be rotated in such a way, that the projected light view // always points upwards, so the up-vector is the y-axis (we already prepared the // light space for this usage).The transformation matrix is set up with the // following parameters: // - position is the origin // - the view direction is the calculated viewDir // - the up vector is the y-axis LProj = buildViewMatrix(DiVec3::ZERO, viewDir, DiVec3::UNIT_Y) * LProj; // map bodyB to unit cube LProj = transformToUnitCube(LProj * LView, mPointListBodyB) * LProj; // transform from light space to normal space: y -> z, z -> -y LProj = msLightSpaceToNormal * LProj; // set the two custom matrices texCam->SetCustomViewMatrix(true, LView); texCam->SetCustomProjectionMatrix(true, LProj); }