/// <summary>Internal use only.  Called by CinemachineCore at designated update time
        /// so the vcam can position itself and track its targets.  All 3 child rigs are updated,
        /// and a blend calculated, depending on the value of the Y axis.</summary>
        /// <param name="worldUp">Default world Up, set by the CinemachineBrain</param>
        /// <param name="deltaTime">Delta time for time-based effects (ignore if less than 0)</param>
        override public void InternalUpdateCameraState(Vector3 worldUp, float deltaTime)
        {
            // Initialize the camera state, in case the game object got moved in the editor
            m_State = PullStateFromVirtualCamera(worldUp, ref m_Lens);
            m_Rigs[(int)RigID.Top].m_Lens.SnapshotCameraReadOnlyProperties(ref m_Lens);
            m_Rigs[(int)RigID.Bottom].m_Lens.SnapshotCameraReadOnlyProperties(ref m_Lens);

            // Update our axes
            bool activeCam = PreviousStateIsValid || CinemachineCore.Instance.IsLive(this);

            if (activeCam && deltaTime >= 0)
            {
                if (m_VerticalAxis.Update(deltaTime))
                {
                    m_VerticalAxis.m_Recentering.CancelRecentering();
                }
                m_RadialAxis.Update(deltaTime);
            }
            m_VerticalAxis.m_Recentering.DoRecentering(ref m_VerticalAxis, deltaTime, 0.5f);

            // Blend the components
            if (mBlender == null)
            {
                mBlender = new ComponentBlender(this);
            }
            mBlender.Blend(GetVerticalAxisValue());

            // Blend the lens
            if (m_Rigs[mBlender.OtherRig].m_CustomLens)
            {
                m_State.Lens = LensSettings.Lerp(
                    m_State.Lens, m_Rigs[mBlender.OtherRig].m_Lens, mBlender.BlendAmount);
            }

            // Do our stuff
            SetReferenceLookAtTargetInState(ref m_State);
            InvokeComponentPipeline(ref m_State, worldUp, deltaTime);
            ApplyPositionBlendMethod(ref m_State, m_Transitions.m_BlendHint);

            // Restore the components
            mBlender.Restore();

            // Push the raw position back to the game object's transform, so it
            // moves along with the camera.
            if (!UserIsDragging)
            {
                if (Follow != null)
                {
                    transform.position = State.RawPosition;
                }
                if (LookAt != null)
                {
                    transform.rotation = State.RawOrientation;
                }
            }
            // Signal that it's all done
            InvokePostPipelineStageCallback(this, CinemachineCore.Stage.Finalize, ref m_State, deltaTime);
            PreviousStateIsValid = true;
        }
Пример #2
0
        /// <summary>Intelligently blend the contents of two states.</summary>
        /// <param name="stateA">The first state, corresponding to t=0</param>
        /// <param name="stateB">The second state, corresponding to t=1</param>
        /// <param name="t">How much to interpolate.  Internally clamped to 0..1</param>
        /// <returns>Linearly interpolated CameraState</returns>
        public static CameraState Lerp(CameraState stateA, CameraState stateB, float t)
        {
            t = Mathf.Clamp01(t);
            float adjustedT = t;

            CameraState state = new CameraState();

            // Combine the blend hints intelligently
            if (((stateA.BlendHint & stateB.BlendHint) & BlendHintValue.NoPosition) != 0)
            {
                state.BlendHint |= BlendHintValue.NoPosition;
            }
            if (((stateA.BlendHint & stateB.BlendHint) & BlendHintValue.NoOrientation) != 0)
            {
                state.BlendHint |= BlendHintValue.NoOrientation;
            }
            if (((stateA.BlendHint & stateB.BlendHint) & BlendHintValue.NoLens) != 0)
            {
                state.BlendHint |= BlendHintValue.NoLens;
            }
            if (((stateA.BlendHint | stateB.BlendHint) & BlendHintValue.SphericalPositionBlend) != 0)
            {
                state.BlendHint |= BlendHintValue.SphericalPositionBlend;
            }
            if (((stateA.BlendHint | stateB.BlendHint) & BlendHintValue.CylindricalPositionBlend) != 0)
            {
                state.BlendHint |= BlendHintValue.CylindricalPositionBlend;
            }

            if (((stateA.BlendHint | stateB.BlendHint) & BlendHintValue.NoLens) == 0)
            {
                state.Lens = LensSettings.Lerp(stateA.Lens, stateB.Lens, t);
            }
            else if (((stateA.BlendHint & stateB.BlendHint) & BlendHintValue.NoLens) == 0)
            {
                if ((stateA.BlendHint & BlendHintValue.NoLens) != 0)
                {
                    state.Lens = stateB.Lens;
                }
                else
                {
                    state.Lens = stateA.Lens;
                }
            }
            state.ReferenceUp = Vector3.Slerp(stateA.ReferenceUp, stateB.ReferenceUp, t);
            state.ShotQuality = Mathf.Lerp(stateA.ShotQuality, stateB.ShotQuality, t);

            state.PositionCorrection = ApplyPosBlendHint(
                stateA.PositionCorrection, stateA.BlendHint,
                stateB.PositionCorrection, stateB.BlendHint,
                state.PositionCorrection,
                Vector3.Lerp(stateA.PositionCorrection, stateB.PositionCorrection, t));

            state.OrientationCorrection = ApplyRotBlendHint(
                stateA.OrientationCorrection, stateA.BlendHint,
                stateB.OrientationCorrection, stateB.BlendHint,
                state.OrientationCorrection,
                Quaternion.Slerp(stateA.OrientationCorrection, stateB.OrientationCorrection, t));

            // LookAt target
            if (!stateA.HasLookAt || !stateB.HasLookAt)
            {
                state.ReferenceLookAt = kNoPoint;
            }
            else
            {
                // Re-interpolate FOV to preserve target composition, if possible
                float fovA = stateA.Lens.FieldOfView;
                float fovB = stateB.Lens.FieldOfView;
                if (((stateA.BlendHint | stateB.BlendHint) & BlendHintValue.NoLens) == 0 &&
                    !state.Lens.Orthographic && !Mathf.Approximately(fovA, fovB))
                {
                    LensSettings lens = state.Lens;
                    lens.FieldOfView = InterpolateFOV(
                        fovA, fovB,
                        Mathf.Max((stateA.ReferenceLookAt - stateA.CorrectedPosition).magnitude, stateA.Lens.NearClipPlane),
                        Mathf.Max((stateB.ReferenceLookAt - stateB.CorrectedPosition).magnitude, stateB.Lens.NearClipPlane), t);
                    state.Lens = lens;

                    // Make sure we preserve the screen composition through FOV changes
                    adjustedT = Mathf.Abs((lens.FieldOfView - fovA) / (fovB - fovA));
                }

                // Linear interpolation of lookAt target point
                state.ReferenceLookAt = Vector3.Lerp(
                    stateA.ReferenceLookAt, stateB.ReferenceLookAt, adjustedT);
            }

            // Raw position
            state.RawPosition = ApplyPosBlendHint(
                stateA.RawPosition, stateA.BlendHint,
                stateB.RawPosition, stateB.BlendHint,
                state.RawPosition, state.InterpolatePosition(
                    stateA.RawPosition, stateA.ReferenceLookAt,
                    stateB.RawPosition, stateB.ReferenceLookAt,
                    t));


            // Interpolate the LookAt in Screen Space if requested
            if (state.HasLookAt &&
                ((stateA.BlendHint | stateB.BlendHint) & BlendHintValue.RadialAimBlend) != 0)
            {
                state.ReferenceLookAt = state.RawPosition + Vector3.Slerp(
                    stateA.ReferenceLookAt - state.RawPosition,
                    stateB.ReferenceLookAt - state.RawPosition, adjustedT);
            }

            // Clever orientation interpolation
            Quaternion newOrient = state.RawOrientation;

            if (((stateA.BlendHint | stateB.BlendHint) & BlendHintValue.NoOrientation) == 0)
            {
                Vector3 dirTarget = Vector3.zero;
                if (state.HasLookAt)//&& ((stateA.BlendHint | stateB.BlendHint) & BlendHintValue.RadialAimBlend) == 0)
                {
                    // If orientations are different, use LookAt to blend them
                    float angle = Quaternion.Angle(stateA.RawOrientation, stateB.RawOrientation);
                    if (angle > UnityVectorExtensions.Epsilon)
                    {
                        dirTarget = state.ReferenceLookAt - state.CorrectedPosition;
                    }
                }
                if (dirTarget.AlmostZero() ||
                    ((stateA.BlendHint | stateB.BlendHint) & BlendHintValue.IgnoreLookAtTarget) != 0)
                {
                    // Don't know what we're looking at - can only slerp
                    newOrient = UnityQuaternionExtensions.SlerpWithReferenceUp(
                        stateA.RawOrientation, stateB.RawOrientation, t, state.ReferenceUp);
                }
                else
                {
                    // Rotate while preserving our lookAt target
                    dirTarget = dirTarget.normalized;
                    if ((dirTarget - state.ReferenceUp).AlmostZero() ||
                        (dirTarget + state.ReferenceUp).AlmostZero())
                    {
                        // Looking up or down at the pole
                        newOrient = UnityQuaternionExtensions.SlerpWithReferenceUp(
                            stateA.RawOrientation, stateB.RawOrientation, t, state.ReferenceUp);
                    }
                    else
                    {
                        // Put the target in the center
                        newOrient = Quaternion.LookRotation(dirTarget, state.ReferenceUp);

                        // Blend the desired offsets from center
                        Vector2 deltaA = -stateA.RawOrientation.GetCameraRotationToTarget(
                            stateA.ReferenceLookAt - stateA.CorrectedPosition, stateA.ReferenceUp);
                        Vector2 deltaB = -stateB.RawOrientation.GetCameraRotationToTarget(
                            stateB.ReferenceLookAt - stateB.CorrectedPosition, stateB.ReferenceUp);
                        newOrient = newOrient.ApplyCameraRotation(
                            Vector2.Lerp(deltaA, deltaB, adjustedT), state.ReferenceUp);
                    }
                }
            }
            state.RawOrientation = ApplyRotBlendHint(
                stateA.RawOrientation, stateA.BlendHint,
                stateB.RawOrientation, stateB.BlendHint,
                state.RawOrientation, newOrient);

            // Accumulate the custom blendables and apply the weights
            for (int i = 0; i < stateA.NumCustomBlendables; ++i)
            {
                CustomBlendable b = stateA.GetCustomBlendable(i);
                b.m_Weight *= (1 - t);
                if (b.m_Weight > UnityVectorExtensions.Epsilon)
                {
                    state.AddCustomBlendable(b);
                }
            }
            for (int i = 0; i < stateB.NumCustomBlendables; ++i)
            {
                CustomBlendable b = stateB.GetCustomBlendable(i);
                b.m_Weight *= t;
                if (b.m_Weight > UnityVectorExtensions.Epsilon)
                {
                    state.AddCustomBlendable(b);
                }
            }
            return(state);
        }
Пример #3
0
        /// <summary>Intelligently blend the contents of two states.</summary>
        /// <param name="stateA">The first state, corresponding to t=0</param>
        /// <param name="stateB">The second state, corresponding to t=1</param>
        /// <param name="t">PHow much to interpolate.  Internally clamped to 0..1</param>
        /// <returns>Linearly interpolated CameraState</returns>
        public static CameraState Lerp(CameraState stateA, CameraState stateB, float t)
        {
            t = Mathf.Clamp01(t);
            float adjustedT = t;

            CameraState state = new CameraState();

            state.Lens        = LensSettings.Lerp(stateA.Lens, stateB.Lens, t);
            state.ReferenceUp = Vector3.Slerp(stateA.ReferenceUp, stateB.ReferenceUp, t);
            state.RawPosition = Vector3.Lerp(stateA.RawPosition, stateB.RawPosition, t);

            Vector3 dirTarget = Vector3.zero;

            if (!stateA.HasLookAt || !stateB.HasLookAt)
            {
                state.ReferenceLookAt = kNoPoint;   // can't interpolate if undefined
            }
            else
            {
                // Re-interpolate FOV to preserve target composition, if possible
                float fovA = stateA.Lens.FieldOfView;
                float fovB = stateB.Lens.FieldOfView;
                if (!Mathf.Approximately(fovA, fovB))
                {
                    LensSettings lens = state.Lens;
                    lens.FieldOfView = state.InterpolateFOV(
                        fovA, fovB,
                        (stateA.ReferenceLookAt - stateA.RawPosition).magnitude,
                        (stateB.ReferenceLookAt - stateB.RawPosition).magnitude, t);
                    state.Lens = lens;

                    // Make sure we preserve the screen composition through FOV changes
                    adjustedT = Mathf.Abs((lens.FieldOfView - fovA) / (fovB - fovA));
                }

                // Spherical linear interpolation about RawPosition
                state.ReferenceLookAt = state.RawPosition + Vector3.Slerp(
                    stateA.ReferenceLookAt - state.RawPosition,
                    stateB.ReferenceLookAt - state.RawPosition, adjustedT);
                dirTarget = state.ReferenceLookAt - state.RawPosition;
            }

            // Clever orientation interpolation
            if (dirTarget.AlmostZero())
            {
                // Don't know what we're looking at - can only slerp
                state.RawOrientation = UnityQuaternionExtensions.SlerpWithReferenceUp(
                    stateA.RawOrientation, stateB.RawOrientation, t, state.ReferenceUp);
            }
            else
            {
                // Rotate while preserving our lookAt target
                dirTarget = dirTarget.normalized;
                if ((dirTarget - state.ReferenceUp).AlmostZero() ||
                    (dirTarget + state.ReferenceUp).AlmostZero())
                {
                    // Looking up or down at the pole
                    state.RawOrientation = UnityQuaternionExtensions.SlerpWithReferenceUp(
                        stateA.RawOrientation, stateB.RawOrientation, t, state.ReferenceUp);
                }
                else
                {
                    // Put the target in the center
                    state.RawOrientation = Quaternion.LookRotation(dirTarget, state.ReferenceUp);

                    // Blend the desired offsets from center
                    Vector2 deltaA = -stateA.RawOrientation.GetCameraRotationToTarget(
                        stateA.ReferenceLookAt - stateA.RawPosition, stateA.ReferenceUp);
                    Vector2 deltaB = -stateB.RawOrientation.GetCameraRotationToTarget(
                        stateB.ReferenceLookAt - stateB.RawPosition, stateB.ReferenceUp);
                    state.RawOrientation = state.RawOrientation.ApplyCameraRotation(
                        Vector2.Lerp(deltaA, deltaB, adjustedT), state.ReferenceUp);
                }
            }

            state.ShotQuality        = Mathf.Lerp(stateA.ShotQuality, stateB.ShotQuality, t);
            state.PositionCorrection = Vector3.Lerp(
                stateA.PositionCorrection, stateB.PositionCorrection, t);
            // GML todo: is this right?  Can it introduce a roll?
            state.OrientationCorrection = Quaternion.Slerp(
                stateA.OrientationCorrection, stateB.OrientationCorrection, t);
            return(state);
        }
Пример #4
0
        public static CameraState Lerp(CameraState stateA, CameraState stateB, float t)
        {
            t = Mathf.Clamp01(t);
            float       t2     = t;
            CameraState result = default(CameraState);

            result.Lens                  = LensSettings.Lerp(stateA.Lens, stateB.Lens, t);
            result.ReferenceUp           = Vector3.Slerp(stateA.ReferenceUp, stateB.ReferenceUp, t);
            result.RawPosition           = Vector3.Lerp(stateA.RawPosition, stateB.RawPosition, t);
            result.ShotQuality           = Mathf.Lerp(stateA.ShotQuality, stateB.ShotQuality, t);
            result.PositionCorrection    = Vector3.Lerp(stateA.PositionCorrection, stateB.PositionCorrection, t);
            result.OrientationCorrection = Quaternion.Slerp(stateA.OrientationCorrection, stateB.OrientationCorrection, t);
            Vector3 vector = Vector3.zero;

            if (!stateA.HasLookAt || !stateB.HasLookAt)
            {
                result.ReferenceLookAt = CameraState.kNoPoint;
            }
            else
            {
                float fieldOfView  = stateA.Lens.FieldOfView;
                float fieldOfView2 = stateB.Lens.FieldOfView;
                if (!result.Lens.Orthographic && !Mathf.Approximately(fieldOfView, fieldOfView2))
                {
                    LensSettings lens = result.Lens;
                    lens.FieldOfView = result.InterpolateFOV(fieldOfView, fieldOfView2, Mathf.Max((stateA.ReferenceLookAt - stateA.CorrectedPosition).magnitude, stateA.Lens.NearClipPlane), Mathf.Max((stateB.ReferenceLookAt - stateB.CorrectedPosition).magnitude, stateB.Lens.NearClipPlane), t);
                    result.Lens      = lens;
                    t2 = Mathf.Abs((lens.FieldOfView - fieldOfView) / (fieldOfView2 - fieldOfView));
                }
                result.ReferenceLookAt = Vector3.Lerp(stateA.ReferenceLookAt, stateB.ReferenceLookAt, t2);
                float num = Quaternion.Angle(stateA.RawOrientation, stateB.RawOrientation);
                if (num > 0.0001f)
                {
                    vector = result.ReferenceLookAt - result.CorrectedPosition;
                }
            }
            if (vector.AlmostZero())
            {
                result.RawOrientation = UnityQuaternionExtensions.SlerpWithReferenceUp(stateA.RawOrientation, stateB.RawOrientation, t, result.ReferenceUp);
            }
            else
            {
                vector = vector.normalized;
                if ((vector - result.ReferenceUp).AlmostZero() || (vector + result.ReferenceUp).AlmostZero())
                {
                    result.RawOrientation = UnityQuaternionExtensions.SlerpWithReferenceUp(stateA.RawOrientation, stateB.RawOrientation, t, result.ReferenceUp);
                }
                else
                {
                    result.RawOrientation = Quaternion.LookRotation(vector, result.ReferenceUp);
                    Vector2 a = -stateA.RawOrientation.GetCameraRotationToTarget(stateA.ReferenceLookAt - stateA.CorrectedPosition, stateA.ReferenceUp);
                    Vector2 b = -stateB.RawOrientation.GetCameraRotationToTarget(stateB.ReferenceLookAt - stateB.CorrectedPosition, stateB.ReferenceUp);
                    result.RawOrientation = result.RawOrientation.ApplyCameraRotation(Vector2.Lerp(a, b, t2), result.ReferenceUp);
                }
            }
            for (int i = 0; i < stateA.NumCustomBlendables; i++)
            {
                CameraState.CustomBlendable customBlendable = stateA.GetCustomBlendable(i);
                customBlendable.m_Weight *= 1f - t;
                if (customBlendable.m_Weight > 0.0001f)
                {
                    result.AddCustomBlendable(customBlendable);
                }
            }
            for (int j = 0; j < stateB.NumCustomBlendables; j++)
            {
                CameraState.CustomBlendable customBlendable2 = stateB.GetCustomBlendable(j);
                customBlendable2.m_Weight *= t;
                if (customBlendable2.m_Weight > 0.0001f)
                {
                    result.AddCustomBlendable(customBlendable2);
                }
            }
            return(result);
        }
Пример #5
0
        /// <summary>Intelligently blend the contents of two states.</summary>
        /// <param name="stateA">The first state, corresponding to t=0</param>
        /// <param name="stateB">The second state, corresponding to t=1</param>
        /// <param name="t">How much to interpolate.  Internally clamped to 0..1</param>
        /// <returns>Linearly interpolated CameraState</returns>
        public static CameraState Lerp(CameraState stateA, CameraState stateB, float t)
        {
            t = Mathf.Clamp01(t);
            float adjustedT = t;

            CameraState state = new CameraState();

            state.Lens        = LensSettings.Lerp(stateA.Lens, stateB.Lens, t);
            state.ReferenceUp = Vector3.Slerp(stateA.ReferenceUp, stateB.ReferenceUp, t);
            state.RawPosition = Vector3.Lerp(stateA.RawPosition, stateB.RawPosition, t);

            state.ShotQuality        = Mathf.Lerp(stateA.ShotQuality, stateB.ShotQuality, t);
            state.PositionCorrection = Vector3.Lerp(
                stateA.PositionCorrection, stateB.PositionCorrection, t);
            // GML todo: is this right?  Can it introduce a roll?
            state.OrientationCorrection = Quaternion.Slerp(
                stateA.OrientationCorrection, stateB.OrientationCorrection, t);

            Vector3 dirTarget = Vector3.zero;

            if (!stateA.HasLookAt || !stateB.HasLookAt)
            {
                state.ReferenceLookAt = kNoPoint;   // can't interpolate if undefined
            }
            else
            {
                // Re-interpolate FOV to preserve target composition, if possible
                float fovA = stateA.Lens.FieldOfView;
                float fovB = stateB.Lens.FieldOfView;
                if (!state.Lens.Orthographic && !Mathf.Approximately(fovA, fovB))
                {
                    LensSettings lens = state.Lens;
                    lens.FieldOfView = state.InterpolateFOV(
                        fovA, fovB,
                        Mathf.Max((stateA.ReferenceLookAt - stateA.CorrectedPosition).magnitude, stateA.Lens.NearClipPlane),
                        Mathf.Max((stateB.ReferenceLookAt - stateB.CorrectedPosition).magnitude, stateB.Lens.NearClipPlane), t);
                    state.Lens = lens;

                    // Make sure we preserve the screen composition through FOV changes
                    adjustedT = Mathf.Abs((lens.FieldOfView - fovA) / (fovB - fovA));
                }

                // Linear interpolation of lookAt target point
                state.ReferenceLookAt = Vector3.Lerp(
                    stateA.ReferenceLookAt, stateB.ReferenceLookAt, adjustedT);

                // If orientations are different, use LookAt to blend them
                float angle = Quaternion.Angle(stateA.RawOrientation, stateB.RawOrientation);
                if (angle > UnityVectorExtensions.Epsilon)
                {
                    dirTarget = state.ReferenceLookAt - state.CorrectedPosition;
                }
            }

            // Clever orientation interpolation
            if (dirTarget.AlmostZero())
            {
                // Don't know what we're looking at - can only slerp
                state.RawOrientation = UnityQuaternionExtensions.SlerpWithReferenceUp(
                    stateA.RawOrientation, stateB.RawOrientation, t, state.ReferenceUp);
            }
            else
            {
                // Rotate while preserving our lookAt target
                dirTarget = dirTarget.normalized;
                if ((dirTarget - state.ReferenceUp).AlmostZero() ||
                    (dirTarget + state.ReferenceUp).AlmostZero())
                {
                    // Looking up or down at the pole
                    state.RawOrientation = UnityQuaternionExtensions.SlerpWithReferenceUp(
                        stateA.RawOrientation, stateB.RawOrientation, t, state.ReferenceUp);
                }
                else
                {
                    // Put the target in the center
                    state.RawOrientation = Quaternion.LookRotation(dirTarget, state.ReferenceUp);

                    // Blend the desired offsets from center
                    Vector2 deltaA = -stateA.RawOrientation.GetCameraRotationToTarget(
                        stateA.ReferenceLookAt - stateA.CorrectedPosition, stateA.ReferenceUp);
                    Vector2 deltaB = -stateB.RawOrientation.GetCameraRotationToTarget(
                        stateB.ReferenceLookAt - stateB.CorrectedPosition, stateB.ReferenceUp);
                    state.RawOrientation = state.RawOrientation.ApplyCameraRotation(
                        Vector2.Lerp(deltaA, deltaB, adjustedT), state.ReferenceUp);
                }
            }

            // Accumulate the custom blendables and apply the weights
            for (int i = 0; i < stateA.NumCustomBlendables; ++i)
            {
                CustomBlendable b = stateA.GetCustomBlendable(i);
                b.m_Weight *= (1 - t);
                if (b.m_Weight > UnityVectorExtensions.Epsilon)
                {
                    state.AddCustomBlendable(b);
                }
            }
            for (int i = 0; i < stateB.NumCustomBlendables; ++i)
            {
                CustomBlendable b = stateB.GetCustomBlendable(i);
                b.m_Weight *= t;
                if (b.m_Weight > UnityVectorExtensions.Epsilon)
                {
                    state.AddCustomBlendable(b);
                }
            }
            return(state);
        }