void CameraZoom(FbxScene* pScene, int pZoomDepth, int pZoomMode) { FbxCamera* lCamera = GetCurrentCamera(pScene); if( lCamera == NULL) return; if( pZoomMode == SceneContext::ZOOM_FOCAL_LENGTH) { if (lCamera->ProjectionType.Get() == FbxCamera::ePerspective) { double lTransform = 0 - pZoomDepth / 100.0; double lApertureW = lCamera->GetApertureWidth(); lApertureW = TransformAperture( lApertureW, lTransform); double lApertureH = lCamera->GetApertureHeight(); lApertureH = TransformAperture( lApertureH, lTransform); UpdatePerspCameraAttributes( lCamera, lApertureW, lApertureH); } else { if( pZoomDepth > 0) gsOrthoCameraScale *= 0.8; else gsOrthoCameraScale *= 1.25; } } else { FbxNode* lCameraNode = lCamera ? lCamera->GetNode() : NULL; // Compute the camera position and direction. FbxVector4 lEye(0,0,1); FbxVector4 lCenter(0,0,0); FbxVector4 lForward(0,0,0); if (lCamera) { lEye = lCamera->Position.Get(); } if (lCameraNode && lCameraNode->GetTarget()) { lCenter = lCameraNode->GetTarget()->LclTranslation.Get(); lForward = lCenter - lEye; } else { if (!lCameraNode || IsProducerCamera(pScene, lCamera)) { if (lCamera) { lCenter = lCamera->InterestPosition.Get(); lForward = lCenter - lEye; } } else { // Get the direction FbxAMatrix lGlobalRotation; FbxVector4 lRotationVector( lCameraNode->LclRotation.Get()); lGlobalRotation.SetR(lRotationVector); // Set the center. // A camera with rotation = {0,0,0} points to the X direction. So create a // vector in the X direction, rotate that vector by the global rotation amount // and then position the center by scaling and translating the resulting vector lRotationVector = FbxVector4(1.0,0,0); lForward = lGlobalRotation.MultT(lRotationVector); } } lForward.Normalize(); lEye += lForward * pZoomDepth; FbxDouble3 lPosition(lEye[0], lEye[1], lEye[2]); lCamera->Position.Set(lPosition); } }
// Set the view to the current camera settings. void SetCamera(KFbxScene* pScene, KTime& pTime, KFbxAnimLayer* pAnimLayer, KArrayTemplate<KFbxNode*>& pCameraArray) { KFbxCamera* lCamera = GetCurrentCamera(pScene, pTime, pCameraArray); KFbxNode* lCameraNode = lCamera ? lCamera->GetNode() : NULL; KFbxVector4 lEye(0,0,1); KFbxVector4 lCenter(0,0,0); KFbxVector4 lUp(0,1,0); KFbxVector4 lForward, lRight; if (lCamera) { lEye = lCamera->Position.Get(); lUp = lCamera->UpVector.Get(); } if (lCameraNode && lCameraNode->GetTarget()) { lCenter = GetGlobalPosition(lCameraNode->GetTarget(), pTime).GetT(); } else { if (!lCameraNode || IsProducerCamera(pScene, lCamera)) { if (lCamera) lCenter = lCamera->InterestPosition.Get(); } else { KFbxXMatrix lGlobalRotation; KFbxVector4 lRotationVector(GetGlobalPosition(lCameraNode, pTime).GetR()); lGlobalRotation.SetR(lRotationVector); KFbxVector4 lInterestPosition(lCamera->InterestPosition.Get()); KFbxVector4 lCameraGlobalPosition(GetGlobalPosition(lCameraNode, pTime).GetT()); double lLength = (KFbxVector4(lInterestPosition - lCameraGlobalPosition).Length()); lRotationVector = KFbxVector4(1.0,0,0); lCenter = lGlobalRotation.MultT(lRotationVector); lCenter *= lLength; lCenter += lEye; lRotationVector = KFbxVector4(0,1.0,0); lUp = lGlobalRotation.MultT(lRotationVector); } } lForward = lCenter - lEye; lForward.Normalize(); lRight = lForward.CrossProduct(lUp); lRight.Normalize(); lUp = lRight.CrossProduct(lForward); lUp.Normalize(); double lRadians = 0; if (lCamera) lRadians = 3.1416 * lCamera->Roll.Get() / 180.0; lUp *= cos(lRadians); lRight *= sin(lRadians); lUp = lUp + lRight; double lNearPlane = 0.01; if (lCamera) lNearPlane = lCamera->GetNearPlane(); double lFarPlane = 1000.0; if (lCamera) lFarPlane = lCamera->GetFarPlane(); if (lCamera && lCamera->ProjectionType.Get() == KFbxCamera::ePERSPECTIVE) { double lFieldOfViewY=0.0; double lAspect = lCamera->GetApertureWidth() * lCamera->GetSqueezeRatio() / lCamera->GetApertureHeight(); if (lCamera->GetApertureMode() == KFbxCamera::eHORIZONTAL || lCamera->GetApertureMode() == KFbxCamera::eVERTICAL) { lFieldOfViewY = lCamera->FieldOfView.Get(); if (lCamera->GetApertureMode() == KFbxCamera::eHORIZONTAL) lFieldOfViewY /= lAspect; } else if (lCamera->GetApertureMode() == KFbxCamera::eFOCAL_LENGTH) { lFieldOfViewY = lCamera->ComputeFieldOfView(lCamera->FocalLength.Get()); lFieldOfViewY /= lAspect; } else if (lCamera->GetApertureMode() == KFbxCamera::eHORIZONTAL_AND_VERTICAL) { lFieldOfViewY = lCamera->FieldOfViewY.Get(); } GlSetCameraPerspective(lFieldOfViewY, lAspect, lNearPlane, lFarPlane, lEye, lCenter, lUp); } else { double lPixelRatio = 1.0; if (lCamera) lPixelRatio = lCamera->GetPixelRatio(); int lWidth, lHeight; double lLeftPlane, lRightPlane, lBottomPlane, lTopPlane; GlGetWindowSize(lWidth, lHeight); if(lWidth < lHeight) { lLeftPlane = -gsOrthoCameraScale * lPixelRatio; lRightPlane = gsOrthoCameraScale * lPixelRatio; lBottomPlane = -gsOrthoCameraScale * lHeight / lWidth; lTopPlane = gsOrthoCameraScale * lHeight / lWidth; } else { lWidth *= (int) lPixelRatio; lLeftPlane = -gsOrthoCameraScale * lWidth / lHeight; lRightPlane = gsOrthoCameraScale * lWidth / lHeight; lBottomPlane = -gsOrthoCameraScale; lTopPlane = gsOrthoCameraScale; } GlSetCameraOrthogonal(lLeftPlane, lRightPlane, lBottomPlane, lTopPlane, lNearPlane, lFarPlane, lEye, lCenter, lUp); } }
// Set the view to the current camera settings. void SetCamera(FbxScene* pScene, FbxTime& pTime, FbxAnimLayer* pAnimLayer, const FbxArray<FbxNode*>& pCameraArray, int pWindowWidth, int pWindowHeight) { // Find the current camera at the given time. FbxCamera* lCamera = GetCurrentCamera(pScene, pTime, pAnimLayer, pCameraArray); if( lCamera == NULL) return; FbxNode* lCameraNode = lCamera ? lCamera->GetNode() : NULL; // Compute the camera position and direction. FbxVector4 lEye(0,0,1); FbxVector4 lCenter(0,0,0); FbxVector4 lUp(0,1,0); FbxVector4 lForward, lRight; if (lCamera) { lEye = lCamera->Position.Get(); lUp = lCamera->UpVector.Get(); } if (lCameraNode && lCameraNode->GetTarget()) { lCenter = GetGlobalPosition(lCameraNode->GetTarget(), pTime).GetT(); } else { if (!lCameraNode || IsProducerCamera(pScene, lCamera)) { if (lCamera) lCenter = lCamera->InterestPosition.Get(); } else { // Get the direction FbxAMatrix lGlobalRotation; FbxVector4 lRotationVector(GetGlobalPosition(lCameraNode, pTime).GetR()); lGlobalRotation.SetR(lRotationVector); // Get the length FbxVector4 lInterestPosition(lCamera->InterestPosition.Get()); FbxVector4 lCameraGlobalPosition(GetGlobalPosition(lCameraNode, pTime).GetT()); double lLength = (FbxVector4(lInterestPosition - lCameraGlobalPosition).Length()); // Set the center. // A camera with rotation = {0,0,0} points to the X direction. So create a // vector in the X direction, rotate that vector by the global rotation amount // and then position the center by scaling and translating the resulting vector lRotationVector = FbxVector4(1.0,0,0); lCenter = lGlobalRotation.MultT(lRotationVector); lCenter *= lLength; lCenter += lEye; // Update the default up vector with the camera rotation. lRotationVector = FbxVector4(0,1.0,0); lUp = lGlobalRotation.MultT(lRotationVector); } } // Align the up vector. lForward = lCenter - lEye; lForward.Normalize(); lRight = lForward.CrossProduct(lUp); lRight.Normalize(); lUp = lRight.CrossProduct(lForward); lUp.Normalize(); // Rotate the up vector with the roll value. double lRadians = 0; if (lCamera) lRadians = lCamera->Roll.Get() * FBXSDK_PI_DIV_180; lUp = lUp * cos( lRadians) + lRight * sin(lRadians); double lNearPlane = 0.01; if (lCamera) lNearPlane = lCamera->GetNearPlane(); double lFarPlane = 4000.0; if (lCamera) lFarPlane = lCamera->GetFarPlane(); //Get global scaling. FbxVector4 lCameraScaling = GetGlobalPosition(lCameraNode, pTime).GetS(); static const int FORWARD_SCALE = 2; //scaling near plane and far plane lNearPlane *= lCameraScaling[ FORWARD_SCALE]; lFarPlane *= lCameraScaling[ FORWARD_SCALE]; // Get the relevant camera settings for a perspective view. if (lCamera && lCamera->ProjectionType.Get() == FbxCamera::ePerspective) { //get the aspect ratio FbxCamera::EAspectRatioMode lCamAspectRatioMode = lCamera->GetAspectRatioMode(); double lAspectX = lCamera->AspectWidth.Get(); //ºñÀ² double lAspectY = lCamera->AspectHeight.Get(); double lAspectRatio = 1.333333; switch( lCamAspectRatioMode) { case FbxCamera::eWindowSize: lAspectRatio = lAspectX / lAspectY; break; case FbxCamera::eFixedRatio: lAspectRatio = lAspectX; break; case FbxCamera::eFixedResolution: lAspectRatio = lAspectX / lAspectY * lCamera->GetPixelRatio(); break; case FbxCamera::eFixedWidth: lAspectRatio = lCamera->GetPixelRatio() / lAspectY; break; case FbxCamera::eFixedHeight: lAspectRatio = lCamera->GetPixelRatio() * lAspectX; break; default: break; } //get the aperture ratio double lFilmHeight = lCamera->GetApertureHeight(); double lFilmWidth = lCamera->GetApertureWidth() * lCamera->GetSqueezeRatio(); //here we use Height : Width double lApertureRatio = lFilmHeight / lFilmWidth; //change the aspect ratio to Height : Width lAspectRatio = 1 / lAspectRatio; //revise the aspect ratio and aperture ratio FbxCamera::EGateFit lCameraGateFit = lCamera->GateFit.Get(); switch( lCameraGateFit ) { case FbxCamera::eFitFill: if( lApertureRatio > lAspectRatio) // the same as eHORIZONTAL_FIT { lFilmHeight = lFilmWidth * lAspectRatio; lCamera->SetApertureHeight( lFilmHeight); lApertureRatio = lFilmHeight / lFilmWidth; } else if( lApertureRatio < lAspectRatio) //the same as eVERTICAL_FIT { lFilmWidth = lFilmHeight / lAspectRatio; lCamera->SetApertureWidth( lFilmWidth); lApertureRatio = lFilmHeight / lFilmWidth; } break; case FbxCamera::eFitVertical: lFilmWidth = lFilmHeight / lAspectRatio; lCamera->SetApertureWidth( lFilmWidth); lApertureRatio = lFilmHeight / lFilmWidth; break; case FbxCamera::eFitHorizontal: lFilmHeight = lFilmWidth * lAspectRatio; lCamera->SetApertureHeight( lFilmHeight); lApertureRatio = lFilmHeight / lFilmWidth; break; case FbxCamera::eFitStretch: lAspectRatio = lApertureRatio; break; case FbxCamera::eFitOverscan: if( lFilmWidth > lFilmHeight) { lFilmHeight = lFilmWidth * lAspectRatio; } else { lFilmWidth = lFilmHeight / lAspectRatio; } lApertureRatio = lFilmHeight / lFilmWidth; break; case FbxCamera::eFitNone: default: break; } //change the aspect ratio to Width : Height lAspectRatio = 1 / lAspectRatio; double lFieldOfViewX = 0.0; double lFieldOfViewY = 0.0; if ( lCamera->GetApertureMode() == FbxCamera::eVertical) { lFieldOfViewY = lCamera->FieldOfView.Get(); lFieldOfViewX = VFOV2HFOV( lFieldOfViewY, 1 / lApertureRatio); } else if (lCamera->GetApertureMode() == FbxCamera::eHorizontal) { lFieldOfViewX = lCamera->FieldOfView.Get(); //get HFOV lFieldOfViewY = HFOV2VFOV( lFieldOfViewX, lApertureRatio); } else if (lCamera->GetApertureMode() == FbxCamera::eFocalLength) { lFieldOfViewX = lCamera->ComputeFieldOfView(lCamera->FocalLength.Get()); //get HFOV lFieldOfViewY = HFOV2VFOV( lFieldOfViewX, lApertureRatio); } else if (lCamera->GetApertureMode() == FbxCamera::eHorizAndVert) { lFieldOfViewX = lCamera->FieldOfViewX.Get(); lFieldOfViewY = lCamera->FieldOfViewY.Get(); } double lRealScreenRatio = (double)pWindowWidth / (double)pWindowHeight; int lViewPortPosX = 0, lViewPortPosY = 0, lViewPortSizeX = pWindowWidth, lViewPortSizeY = pWindowHeight; //compute the view port if( lRealScreenRatio > lAspectRatio) { lViewPortSizeY = pWindowHeight; lViewPortSizeX = (int)( lViewPortSizeY * lAspectRatio); lViewPortPosY = 0; lViewPortPosX = (int)((pWindowWidth - lViewPortSizeX) * 0.5); } else { lViewPortSizeX = pWindowWidth; lViewPortSizeY = (int)(lViewPortSizeX / lAspectRatio); lViewPortPosX = 0; lViewPortPosY = (int)((pWindowHeight - lViewPortSizeY) * 0.5); } //revise the Perspective since we have film offset double lFilmOffsetX = lCamera->FilmOffsetX.Get(); double lFilmOffsetY = lCamera->FilmOffsetY.Get(); lFilmOffsetX = 0 - lFilmOffsetX / lFilmWidth * 2.0; lFilmOffsetY = 0 - lFilmOffsetY / lFilmHeight * 2.0; GlSetCameraPerspective( lFieldOfViewY, lAspectRatio, lNearPlane, lFarPlane, lEye, lCenter, lUp, lFilmOffsetX, lFilmOffsetY); //glMatrixMode(GL_PROJECTION); //double lTestPerpMatrix[ 16]; //glGetDoublev( GL_PROJECTION_MATRIX, lTestPerpMatrix); //lTestPerpMatrix[ 8] -= lFilmOffsetX; //lTestPerpMatrix[ 9] -= lFilmOffsetY; // //glLoadMatrixd( lTestPerpMatrix); //glMatrixMode(GL_MODELVIEW); glViewport( lViewPortPosX, lViewPortPosY, lViewPortSizeX, lViewPortSizeY); } // Get the relevant camera settings for an orthogonal view. else { double lPixelRatio = 1.0; if (lCamera) lPixelRatio = lCamera->GetPixelRatio(); double lLeftPlane, lRightPlane, lBottomPlane, lTopPlane; if(pWindowWidth < pWindowHeight) { lLeftPlane = -gsOrthoCameraScale * lPixelRatio; lRightPlane = gsOrthoCameraScale * lPixelRatio; lBottomPlane = -gsOrthoCameraScale * pWindowHeight / pWindowWidth; lTopPlane = gsOrthoCameraScale * pWindowHeight / pWindowWidth; } else { pWindowWidth *= (int) lPixelRatio; lLeftPlane = -gsOrthoCameraScale * pWindowWidth / pWindowHeight; lRightPlane = gsOrthoCameraScale * pWindowWidth / pWindowHeight; lBottomPlane = -gsOrthoCameraScale; lTopPlane = gsOrthoCameraScale; } GlSetCameraOrthogonal(lLeftPlane, lRightPlane, lBottomPlane, lTopPlane, lNearPlane, lFarPlane, lEye, lCenter, lUp); } }