void ModelPreviewCanvas::AddjustCameraPos() { _Assert(mCamera != NULL); _Assert(mModel != NULL); AABBox bound; mModel->CalcDynamicAABBox(IDENTITY_MATRIX, &bound); float width = bound.GetSize().x; float height = bound.GetSize().y; float length = bound.GetSize().z; float aspect = 0; float fov = 0; mCamera->GetCameraParams(NULL, NULL, &fov, &aspect); float distY = (height / 2.0f) / tan(fov / 2.0f); float distX = (height / 2.0f) / (aspect * tan(fov / 2.0f)); float dist = Max(distX, distY); mCamera->SetWorldPosition(bound.GetCenter()); mCamera->Translate(0, 0, -dist - length); mCamera->LookAt(bound.GetCenter()); HoverCameraController* hoverCameraController = New HoverCameraController(5.0f, 20.0f, -4*PI/9, 4*PI/9, 2.0f, 1000.0f, bound.GetCenter(), dist + length); mCamera->SetCameraController(hoverCameraController); }
void ShadowMapRenderer::setupVirtualLightCamera(Camera* camera, DirectionalLightNode* lightNode, int cascadeIndex) { const float BOUND_EXPAND_FACTOR = 0.8f; _Assert(camera != NULL); _Assert(cascadeIndex >= 0 && cascadeIndex < CASCADE_COUNTS); DirectionalLight* dirLight = lightNode->GetDirLight(); Vector3 lightDir = dirLight->GetDirection(); lightDir.Normalize(); Vector3 frustumPos[5]; { float farZ = 0; float aspect = 0; float fov = 0; camera->GetCameraParams(NULL, &farZ, &fov, &aspect); farZ *= calcCascadeDist(cascadeIndex); float fy = farZ * tanf(fov / 2.0f); float fx = aspect * fy; frustumPos[0] = Vector3::Zero; frustumPos[1] = Vector3(-fx, fy, farZ); frustumPos[2] = Vector3( fx, fy, farZ); frustumPos[3] = Vector3(-fx, -fy, farZ); frustumPos[4] = Vector3( fx, -fy, farZ); } D3DXMATRIX matCameraViewInv; D3DXMatrixInverse(&matCameraViewInv, 0, &camera->ViewMatrix()); D3DXMATRIX matLightView; { Vector3 lightPos = lightNode->GetWorldPosition(); D3DXMATRIX matRotTranspose, matTransInverse; D3DXMatrixTranspose(&matRotTranspose, &(lightNode->GetWorldOrient().Matrix())); D3DXMatrixTranslation(&matTransInverse, -lightPos.x, -lightPos.y, -lightPos.z); matLightView = matTransInverse * matRotTranspose; } AABBox lightSpaceBound; for(int i = 0; i < 5; ++i) { Vector3 posW = PosVecTransform(frustumPos[i], matCameraViewInv); Vector3 posL = PosVecTransform(posW, matLightView); lightSpaceBound = AABBox::CombinePoint(lightSpaceBound, posL); } float nearZ = 0.1f; float farZ = 0; float width = 0; float height = 0; { Vector3 lookDir = camera->GetWorldForward(); lookDir.Normalize(); float adjustFactor = lookDir.Dot(lightDir); // lookDir与lightDir贴近时, 向后扩展virtualCamera范围 float expandDist = adjustFactor * BOUND_EXPAND_FACTOR * fabsf(lightSpaceBound.mMax.z - lightSpaceBound.mMin.z); Vector3 centerL = lightSpaceBound.GetCenter(); D3DXMATRIX matLightViewInv; D3DXMatrixInverse(&matLightViewInv, 0, &matLightView); Vector3 centerW = PosVecTransform(centerL, matLightViewInv); float lightDist = fabsf(lightSpaceBound.mMax.z - lightSpaceBound.mMin.z) / 2.0f; width = fabsf(lightSpaceBound.mMax.x - lightSpaceBound.mMin.x); height = fabsf(lightSpaceBound.mMax.y - lightSpaceBound.mMin.y); farZ = 2.0f * lightDist + expandDist; mVirtualCamera[cascadeIndex].pos = centerW - (lightDist + expandDist) * lightDir; } D3DXMATRIX matLightProj; D3DXMatrixOrthoLH(&matLightProj, width, height, nearZ, farZ); D3DXMATRIX matVirtualCameraView; { Vector3 virtualCameraPos = mVirtualCamera[cascadeIndex].pos; D3DXMATRIX matRotTranspose, matTransInverse; D3DXMatrixTranspose(&matRotTranspose, &(lightNode->GetWorldOrient().Matrix())); D3DXMatrixTranslation(&matTransInverse, -virtualCameraPos.x, -virtualCameraPos.y, -virtualCameraPos.z); matVirtualCameraView = matTransInverse * matRotTranspose; mVirtualCamera[cascadeIndex].bound = AABBox::MatTransform(AABBox(Vector3(0, 0, farZ/2.0f), width, height, farZ), InversedMatrix(matVirtualCameraView)); } mVirtualCamera[cascadeIndex].matVP = matVirtualCameraView * matLightProj; }