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);
        }
Example #2
0
        /// <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;
        }
Example #5
0
        /// <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();
        }