internal static void DrawVirtualCameraBaseGizmos(CinemachineVirtualCameraBase vcam, GizmoType selectionType) { // Don't draw gizmos on hidden stuff if ((vcam.VirtualCameraGameObject.hideFlags & (HideFlags.HideInHierarchy | HideFlags.HideInInspector)) != 0) { return; } if (vcam.ParentCamera != null && (selectionType & GizmoType.Active) == 0) { return; } CameraState state = vcam.State; Gizmos.DrawIcon(state.FinalPosition, kGizmoFileName, true); DrawCameraFrustumGizmo( CinemachineCore.Instance.FindPotentialTargetBrain(vcam), state.Lens, Matrix4x4.TRS( state.FinalPosition, UnityQuaternionExtensions.Normalized(state.FinalOrientation), Vector3.one), CinemachineCore.Instance.IsLive(vcam) ? CinemachineSettings.CinemachineCoreSettings.ActiveGizmoColour : CinemachineSettings.CinemachineCoreSettings.InactiveGizmoColour); }
/// <summary>Applies the composer rules and orients the camera accordingly</summary> /// <param name="curState">The current camera state</param> /// <param name="statePrevFrame">The camera state on the previous frame (unused)</param> /// <param name="deltaTime">Used for calculating damping. If less than /// or equal to zero, then target will snap to the center of the dead zone.</param> /// <returns>curState with RawOrientation applied</returns> public virtual CameraState MutateCameraState( CameraState curState, CameraState statePrevFrame, float deltaTime) { if (!IsValid || !curState.HasLookAt) { return(curState); } CameraState newState = curState; newState.ReferenceLookAt = GetTrackedPoint(ref newState); float targetDistance = (newState.ReferenceLookAt - newState.CorrectedPosition).magnitude; if (targetDistance < UnityVectorExtensions.Epsilon) { return(newState); // navel-gazing, get outa here } // Calculate effective fov - fake it for ortho based on target distance float fov, fovH; if (newState.Lens.Orthographic) { fov = Mathf.Rad2Deg * 2 * Mathf.Atan(newState.Lens.OrthographicSize / targetDistance); fovH = Mathf.Rad2Deg * 2 * Mathf.Atan(newState.Lens.Aspect * newState.Lens.OrthographicSize / targetDistance); } else { fov = newState.Lens.FieldOfView; double radHFOV = 2 * Math.Atan(Math.Tan(fov * Mathf.Deg2Rad / 2) * newState.Lens.Aspect); fovH = (float)(Mathf.Rad2Deg * radHFOV); } Rect softGuideFOV = ScreenToFOV(SoftGuideRect, fov, fovH, newState.Lens.Aspect); if (deltaTime <= 0) { // No damping, just snap to central bounds, skipping the soft zone Rect rect = new Rect(softGuideFOV.center, Vector2.zero); // Force to center newState.RawOrientation = PlaceWithinScreenBounds( ref newState, rect, newState.RawOrientation, fov, fovH, 0); } else { // Start with previous frame's orientation (but with current up) Quaternion rigOrientation = Quaternion.LookRotation( statePrevFrame.RawOrientation * Vector3.forward, newState.ReferenceUp); // First force the previous rotation into the hard bounds, no damping Rect hardGuideFOV = ScreenToFOV(HardGuideRect, fov, fovH, newState.Lens.Aspect); newState.RawOrientation = PlaceWithinScreenBounds( ref newState, hardGuideFOV, rigOrientation, fov, fovH, 0); // Now move it through the soft zone, with damping newState.RawOrientation = PlaceWithinScreenBounds( ref newState, softGuideFOV, newState.RawOrientation, fov, fovH, deltaTime); } newState.RawOrientation = UnityQuaternionExtensions.Normalized(newState.RawOrientation); return(newState); }
/// <summary>Applies the composer rules and orients the camera accordingly</summary> /// <param name="curState">The current camera state</param> /// <param name="statePrevFrame">The camera state on the previous frame (unused)</param> /// <param name="deltaTime">Used for calculating damping. If less than /// or equal to zero, then target will snap to the center of the dead zone.</param> /// <returns>curState with RawOrientation applied</returns> public CameraState MutateCameraState( CameraState curState, CameraState statePrevFrame, float deltaTime) { if (!IsValid || !curState.HasLookAt) { return(curState); } CameraState newState = curState; newState.ReferenceLookAt = GetTrackedPoint(newState.ReferenceLookAt); if ((newState.ReferenceLookAt - newState.CorrectedPosition).AlmostZero()) { return(newState); // navel-gazing, get outa here } CinemachineBrain brain = CinemachineCore.Instance.FindPotentialTargetBrain(VirtualCamera); float aspect = brain != null ? brain.OutputCamera.aspect : 1; float fovH = CameraUtilities.CalculateHorizontalFOV(newState.Lens.FieldOfView, aspect); Rect softGuideFOV = ScreenToFOV(SoftGuideRect, newState.Lens.FieldOfView, fovH, aspect); if (deltaTime <= 0) { // No damping, just snap to central bounds, skipping the soft zone Rect rect = new Rect(softGuideFOV.center, Vector2.zero); // Force to center newState.RawOrientation = PlaceWithinScreenBounds( ref newState, rect, newState.RawOrientation, fovH, 0); } else { // Start with previous frame's orientation (but with current up) Quaternion rigOrientation = Quaternion.LookRotation( statePrevFrame.RawOrientation * Vector3.forward, newState.ReferenceUp); // First force the previous rotation into the hard bounds, no damping Rect hardGuideFOV = ScreenToFOV(HardGuideRect, newState.Lens.FieldOfView, fovH, aspect); newState.RawOrientation = PlaceWithinScreenBounds( ref newState, hardGuideFOV, rigOrientation, fovH, 0); // Now move it through the soft zone, with damping newState.RawOrientation = PlaceWithinScreenBounds( ref newState, softGuideFOV, newState.RawOrientation, fovH, deltaTime); } newState.RawOrientation = UnityQuaternionExtensions.Normalized(newState.RawOrientation); return(newState); }
internal static void DrawVirtualCameraGizmos(CinemachineVirtualCameraBase vcam, GizmoType selectionType) { // Don't draw gizmos on hidden stuff if ((vcam.VirtualCameraGameObject.hideFlags & (HideFlags.HideInHierarchy | HideFlags.HideInInspector)) != 0) { return; } Color originalGizmoColour = Gizmos.color; Gizmos.color = CinemachineCore.Instance.IsLive(vcam) ? CinemachineSettings.CinemachineCoreSettings.ActiveGizmoColour : CinemachineSettings.CinemachineCoreSettings.InactiveGizmoColour; CameraState state = vcam.State; Gizmos.DrawIcon(state.FinalPosition, "Cinemachine/cm_logo_lg.png", true); float aspect = 1; CinemachineBrain brain = CinemachineCore.Instance.FindPotentialTargetBrain(vcam); if (brain != null) { aspect = brain.OutputCamera.aspect; } Matrix4x4 originalMatrix = Gizmos.matrix; Gizmos.matrix = Matrix4x4.TRS( state.FinalPosition, UnityQuaternionExtensions.Normalized(state.FinalOrientation), Vector3.one); Gizmos.DrawFrustum( Vector3.zero, state.Lens.FieldOfView, state.Lens.FarClipPlane, state.Lens.NearClipPlane, aspect); Gizmos.matrix = originalMatrix; Gizmos.color = originalGizmoColour; }
/// <summary>Applies the composer rules and orients the camera accordingly</summary> /// <param name="curState">The current camera state</param> /// <param name="deltaTime">Used for calculating damping. If less than /// zero, then target will snap to the center of the dead zone.</param> public override void MutateCameraState(ref CameraState curState, float deltaTime) { if (!IsValid || !curState.HasLookAt) { return; } // Correct the tracked point in the event that it's behind the camera // while the real target is in front if (!(TrackedPoint - curState.ReferenceLookAt).AlmostZero()) { Vector3 mid = Vector3.Lerp(curState.CorrectedPosition, curState.ReferenceLookAt, 0.5f); Vector3 toLookAt = curState.ReferenceLookAt - mid; Vector3 toTracked = TrackedPoint - mid; if (Vector3.Dot(toLookAt, toTracked) < 0) { float t = Vector3.Distance(curState.ReferenceLookAt, mid) / Vector3.Distance(curState.ReferenceLookAt, TrackedPoint); TrackedPoint = Vector3.Lerp(curState.ReferenceLookAt, TrackedPoint, t); } } float targetDistance = (TrackedPoint - curState.CorrectedPosition).magnitude; if (targetDistance < Epsilon) { if (deltaTime >= 0 && VirtualCamera.PreviousStateIsValid) { curState.RawOrientation = m_CameraOrientationPrevFrame; } return; // navel-gazing, get outa here } // Expensive FOV calculations mCache.UpdateCache(curState.Lens, SoftGuideRect, HardGuideRect, targetDistance); Quaternion rigOrientation = curState.RawOrientation; if (deltaTime < 0 || !VirtualCamera.PreviousStateIsValid) { // No damping, just snap to central bounds, skipping the soft zone rigOrientation = Quaternion.LookRotation( rigOrientation * Vector3.forward, curState.ReferenceUp); Rect rect = mCache.mFovSoftGuideRect; if (m_CenterOnActivate) { rect = new Rect(rect.center, Vector2.zero); // Force to center } RotateToScreenBounds( ref curState, rect, curState.ReferenceLookAt, ref rigOrientation, mCache.mFov, mCache.mFovH, -1); } else { // Start with previous frame's orientation (but with current up) Vector3 dir = m_LookAtPrevFrame - m_CameraPosPrevFrame; if (dir.AlmostZero()) { rigOrientation = Quaternion.LookRotation( m_CameraOrientationPrevFrame * Vector3.forward, curState.ReferenceUp); } else { dir = Quaternion.Euler(curState.PositionDampingBypass) * dir; rigOrientation = Quaternion.LookRotation(dir, curState.ReferenceUp); rigOrientation = rigOrientation.ApplyCameraRotation( -m_ScreenOffsetPrevFrame, curState.ReferenceUp); } // Move target through the soft zone, with damping RotateToScreenBounds( ref curState, mCache.mFovSoftGuideRect, TrackedPoint, ref rigOrientation, mCache.mFov, mCache.mFovH, deltaTime); // Force the actual target (not the lookahead one) into the hard bounds, no damping if (deltaTime < 0 || VirtualCamera.LookAtTargetAttachment > 1 - Epsilon) { RotateToScreenBounds( ref curState, mCache.mFovHardGuideRect, curState.ReferenceLookAt, ref rigOrientation, mCache.mFov, mCache.mFovH, -1); } } m_CameraPosPrevFrame = curState.CorrectedPosition; m_LookAtPrevFrame = TrackedPoint; m_CameraOrientationPrevFrame = UnityQuaternionExtensions.Normalized(rigOrientation); m_ScreenOffsetPrevFrame = m_CameraOrientationPrevFrame.GetCameraRotationToTarget( m_LookAtPrevFrame - curState.CorrectedPosition, curState.ReferenceUp); curState.RawOrientation = m_CameraOrientationPrevFrame; }
/// <summary>Applies the composer rules and orients the camera accordingly</summary> /// <param name="curState">The current camera state</param> /// <param name="deltaTime">Used for calculating damping. If less than /// zero, then target will snap to the center of the dead zone.</param> public override void MutateCameraState(ref CameraState curState, float deltaTime) { // Initialize the state for previous frame if appropriate if (deltaTime < 0) { m_Predictor.Reset(); } if (!IsValid || !curState.HasLookAt) { return; } float targetDistance = (TrackedPoint - curState.CorrectedPosition).magnitude; if (targetDistance < Epsilon) { if (deltaTime >= 0) { curState.RawOrientation = m_CameraOrientationPrevFrame; } return; // navel-gazing, get outa here } float fov, fovH; if (curState.Lens.Orthographic) { // Calculate effective fov - fake it for ortho based on target distance fov = Mathf.Rad2Deg * 2 * Mathf.Atan(curState.Lens.OrthographicSize / targetDistance); fovH = Mathf.Rad2Deg * 2 * Mathf.Atan( curState.Lens.Aspect * curState.Lens.OrthographicSize / targetDistance); } else { fov = curState.Lens.FieldOfView; double radHFOV = 2 * Math.Atan(Math.Tan(fov * Mathf.Deg2Rad / 2) * curState.Lens.Aspect); fovH = (float)(Mathf.Rad2Deg * radHFOV); } Quaternion rigOrientation = curState.RawOrientation; Rect softGuideFOV = ScreenToFOV(SoftGuideRect, fov, fovH, curState.Lens.Aspect); if (deltaTime < 0) { // No damping, just snap to central bounds, skipping the soft zone Rect rect = new Rect(softGuideFOV.center, Vector2.zero); // Force to center RotateToScreenBounds(ref curState, rect, ref rigOrientation, fov, fovH, -1); } else { // Start with previous frame's orientation (but with current up) Vector3 dir = m_LookAtPrevFrame - (m_CameraPosPrevFrame + curState.PositionDampingBypass); if (dir.AlmostZero()) { rigOrientation = Quaternion.LookRotation( m_CameraOrientationPrevFrame * Vector3.forward, curState.ReferenceUp); } else { rigOrientation = Quaternion.LookRotation(dir, curState.ReferenceUp); rigOrientation = rigOrientation.ApplyCameraRotation( -m_ScreenOffsetPrevFrame, curState.ReferenceUp); } // First force the previous rotation into the hard bounds, no damping, // then Now move it through the soft zone, with damping Rect hardGuideFOV = ScreenToFOV(HardGuideRect, fov, fovH, curState.Lens.Aspect); if (!RotateToScreenBounds(ref curState, hardGuideFOV, ref rigOrientation, fov, fovH, -1)) { RotateToScreenBounds(ref curState, softGuideFOV, ref rigOrientation, fov, fovH, deltaTime); } } m_CameraPosPrevFrame = curState.CorrectedPosition; m_LookAtPrevFrame = TrackedPoint; m_CameraOrientationPrevFrame = UnityQuaternionExtensions.Normalized(rigOrientation); m_ScreenOffsetPrevFrame = m_CameraOrientationPrevFrame.GetCameraRotationToTarget( m_LookAtPrevFrame - curState.CorrectedPosition, curState.ReferenceUp); curState.RawOrientation = m_CameraOrientationPrevFrame; }
/// <summary>Applies the composer rules and orients the camera accordingly</summary> /// <param name="curState">The current camera state</param> /// <param name="deltaTime">Used for calculating damping. If less than /// zero, then target will snap to the center of the dead zone.</param> public override void MutateCameraState(ref CameraState curState, float deltaTime) { // Initialize the state for previous frame if appropriate if (deltaTime < 0) { m_Predictor.Reset(); } if (!IsValid || !curState.HasLookAt) { return; } float targetDistance = (TrackedPoint - curState.CorrectedPosition).magnitude; if (targetDistance < Epsilon) { if (deltaTime >= 0) { curState.RawOrientation = m_CameraOrientationPrevFrame; } return; // navel-gazing, get outa here } // Expensive FOV calculations mCache.UpdateCache(curState.Lens, SoftGuideRect, HardGuideRect, targetDistance); Quaternion rigOrientation = curState.RawOrientation; if (deltaTime < 0) { // No damping, just snap to central bounds, skipping the soft zone Rect rect = mCache.mFovSoftGuideRect; if (m_CenterOnActivate) { rect = new Rect(rect.center, Vector2.zero); // Force to center } RotateToScreenBounds(ref curState, rect, ref rigOrientation, mCache.mFov, mCache.mFovH, -1); } else { // Start with previous frame's orientation (but with current up) Vector3 dir = m_LookAtPrevFrame - (m_CameraPosPrevFrame + curState.PositionDampingBypass); if (dir.AlmostZero()) { rigOrientation = Quaternion.LookRotation( m_CameraOrientationPrevFrame * Vector3.forward, curState.ReferenceUp); } else { rigOrientation = Quaternion.LookRotation(dir, curState.ReferenceUp); rigOrientation = rigOrientation.ApplyCameraRotation( -m_ScreenOffsetPrevFrame, curState.ReferenceUp); } // First force the previous rotation into the hard bounds, no damping, // then Now move it through the soft zone, with damping if (!RotateToScreenBounds(ref curState, mCache.mFovHardGuideRect, ref rigOrientation, mCache.mFov, mCache.mFovH, -1)) { RotateToScreenBounds(ref curState, mCache.mFovSoftGuideRect, ref rigOrientation, mCache.mFov, mCache.mFovH, deltaTime); } } m_CameraPosPrevFrame = curState.CorrectedPosition; m_LookAtPrevFrame = TrackedPoint; m_CameraOrientationPrevFrame = UnityQuaternionExtensions.Normalized(rigOrientation); m_ScreenOffsetPrevFrame = m_CameraOrientationPrevFrame.GetCameraRotationToTarget( m_LookAtPrevFrame - curState.CorrectedPosition, curState.ReferenceUp); curState.RawOrientation = m_CameraOrientationPrevFrame; }
/// <summary>Applies the composer rules and orients the camera accordingly</summary> /// <param name="curState">The current camera state</param> /// <param name="deltaTime">Used for calculating damping. If less than /// or equal to zero, then target will snap to the center of the dead zone.</param> public virtual void MutateCameraState(ref CameraState curState, float deltaTime) { // Initialize the state for previous frame if appropriate if (deltaTime <= 0) { m_CameraOrientationPrevFrame = curState.RawOrientation; } if (!IsValid || !curState.HasLookAt) { return; } curState.ReferenceLookAt = GetTrackedPoint(curState.ReferenceLookAt); float targetDistance = (curState.ReferenceLookAt - curState.CorrectedPosition).magnitude; if (targetDistance < UnityVectorExtensions.Epsilon) { return; // navel-gazing, get outa here } //UnityEngine.Profiling.Profiler.BeginSample("CinemachineComposer.MutateCameraState"); float fov, fovH; if (curState.Lens.Orthographic) { // Calculate effective fov - fake it for ortho based on target distance fov = Mathf.Rad2Deg * 2 * Mathf.Atan(curState.Lens.OrthographicSize / targetDistance); fovH = Mathf.Rad2Deg * 2 * Mathf.Atan( curState.Lens.Aspect * curState.Lens.OrthographicSize / targetDistance); } else { fov = curState.Lens.FieldOfView; double radHFOV = 2 * Math.Atan(Math.Tan(fov * Mathf.Deg2Rad / 2) * curState.Lens.Aspect); fovH = (float)(Mathf.Rad2Deg * radHFOV); } Rect softGuideFOV = ScreenToFOV(SoftGuideRect, fov, fovH, curState.Lens.Aspect); if (deltaTime <= 0) { // No damping, just snap to central bounds, skipping the soft zone Rect rect = new Rect(softGuideFOV.center, Vector2.zero); // Force to center curState.RawOrientation = RotateToScreenBounds( ref curState, rect, curState.RawOrientation, fov, fovH, 0); } else { // Start with previous frame's orientation (but with current up) Quaternion rigOrientation = Quaternion.LookRotation( m_CameraOrientationPrevFrame * Vector3.forward, curState.ReferenceUp); // First force the previous rotation into the hard bounds, no damping Rect hardGuideFOV = ScreenToFOV(HardGuideRect, fov, fovH, curState.Lens.Aspect); curState.RawOrientation = RotateToScreenBounds( ref curState, hardGuideFOV, rigOrientation, fov, fovH, 0); // Now move it through the soft zone, with damping curState.RawOrientation = RotateToScreenBounds( ref curState, softGuideFOV, curState.RawOrientation, fov, fovH, deltaTime); } curState.RawOrientation = m_CameraOrientationPrevFrame = UnityQuaternionExtensions.Normalized(curState.RawOrientation); //UnityEngine.Profiling.Profiler.EndSample(); }