/// <summary>Positions the virtual camera according to the transposer rules.</summary>
        /// <param name="curState">The current camera state</param>
        /// <param name="deltaTime">Used for damping.  If less than 0, no damping is done.</param>
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            InitPrevFrameStateInfo(ref curState, deltaTime);

            // Update the heading
            if (FollowTarget != PreviousTarget)
            {
                PreviousTarget      = FollowTarget;
                mTargetRigidBody    = (PreviousTarget == null) ? null : PreviousTarget.GetComponent <Rigidbody>();
                mLastTargetPosition = (PreviousTarget == null) ? Vector3.zero : PreviousTarget.position;
                mHeadingTracker     = null;
            }
            LastHeading = HeadingUpdater(this, deltaTime, curState.ReferenceUp);
            float heading = LastHeading;

            if (IsValid)
            {
                // Calculate the heading
                if (m_BindingMode != BindingMode.SimpleFollowWithWorldUp)
                {
                    heading += m_Heading.m_Bias;
                }
                Quaternion headingRot = Quaternion.AngleAxis(heading, Vector3.up);

                Vector3 rawOffset = EffectiveOffset;
                Vector3 offset    = headingRot * rawOffset;

                // Track the target, with damping
                TrackTarget(deltaTime, curState.ReferenceUp, offset, out Vector3 pos, out Quaternion orient);

                // Place the camera
                offset = orient * offset;
                curState.ReferenceUp = orient * Vector3.up;

                // Respect minimum target distance on XZ plane
                var targetPosition = FollowTargetPosition;
                pos += GetOffsetForMinimumTargetDistance(
                    pos, offset, curState.RawOrientation * Vector3.forward,
                    curState.ReferenceUp, targetPosition);
                curState.RawPosition = pos + offset;

                if (deltaTime >= 0 && VirtualCamera.PreviousStateIsValid)
                {
                    var lookAt = targetPosition;
                    if (LookAtTarget != null)
                    {
                        lookAt = LookAtTargetPosition;
                    }
                    var dir0 = mLastCameraPosition - lookAt;
                    var dir1 = curState.RawPosition - lookAt;
                    if (dir0.sqrMagnitude > 0.01f && dir1.sqrMagnitude > 0.01f)
                    {
                        curState.PositionDampingBypass = UnityVectorExtensions.SafeFromToRotation(
                            dir0, dir1, curState.ReferenceUp).eulerAngles;
                    }
                }
                mLastTargetPosition = targetPosition;
                mLastCameraPosition = curState.RawPosition;
            }
        }
Beispiel #2
0
        /// <summary>Positions the virtual camera according to the transposer rules.</summary>
        /// <param name="curState">The current camera state</param>
        /// <param name="deltaTime">Used for damping.  If 0 or less, no damping is done.</param>
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            //UnityEngine.Profiling.Profiler.BeginSample("CinemachineOrbitalTransposer.MutateCameraState");
            InitPrevFrameStateInfo(ref curState, deltaTime);

            // Update the heading
            if (VirtualCamera.Follow != PreviousTarget)
            {
                PreviousTarget      = VirtualCamera.Follow;
                mTargetRigidBody    = (PreviousTarget == null) ? null : PreviousTarget.GetComponent <Rigidbody>();
                mLastTargetPosition = (PreviousTarget == null) ? Vector3.zero : PreviousTarget.position;
                mHeadingTracker     = null;
            }
            if (!m_HeadingIsSlave)
            {
                UpdateHeading(deltaTime, curState.ReferenceUp);
            }

            if (IsValid)
            {
                mLastTargetPosition = VirtualCamera.Follow.position;

                // Place the camera
                Quaternion targetOrientation = GetReferenceOrientation(curState.ReferenceUp);
                float      heading           = m_XAxis.Value + m_Heading.m_HeadingBias;
                targetOrientation = targetOrientation * Quaternion.AngleAxis(heading, Vector3.up);
                DoTracking(ref curState, deltaTime, targetOrientation, EffectiveOffset);
            }
            //UnityEngine.Profiling.Profiler.EndSample();
        }
        // Make sure this is calld only once per frame
        private float GetTargetHeading(
            float currentHeading, Quaternion targetOrientation, float deltaTime)
        {
            if (VirtualCamera.Follow == null)
            {
                return(currentHeading);
            }

            if (m_Heading.m_HeadingDefinition == Heading.HeadingDefinition.Velocity &&
                mTargetRigidBody == null)
            {
                Debug.Log(string.Format(
                              "Attempted to use HeadingDerivationMode.Velocity to calculate heading for {0}. No RigidBody was present on '{1}'. Defaulting to position delta",
                              GetFullName(VirtualCamera.VirtualCameraGameObject), VirtualCamera.Follow));
                m_Heading.m_HeadingDefinition = Heading.HeadingDefinition.PositionDelta;
            }

            Vector3 velocity = Vector3.zero;

            switch (m_Heading.m_HeadingDefinition)
            {
            case Heading.HeadingDefinition.PositionDelta:
                velocity = VirtualCamera.Follow.position - mLastTargetPosition;
                break;

            case Heading.HeadingDefinition.Velocity:
                velocity = mTargetRigidBody.velocity;
                break;

            default:
            case Heading.HeadingDefinition.TargetForward:
            case Heading.HeadingDefinition.WorldForward:
                return(0);
            }

            // Process the velocity and derive the heading from it.
            int filterSize = m_Heading.m_VelocityFilterStrength * 5;

            if (mHeadingTracker == null || mHeadingTracker.FilterSize != filterSize)
            {
                mHeadingTracker = new HeadingTracker(filterSize);
            }
            mHeadingTracker.DecayHistory();
            Vector3 up = targetOrientation * Vector3.up;

            velocity = velocity.ProjectOntoPlane(up);
            if (!velocity.AlmostZero())
            {
                mHeadingTracker.Add(velocity);
            }

            velocity = mHeadingTracker.GetReliableHeading();
            if (!velocity.AlmostZero())
            {
                return(UnityVectorExtensions.SignedAngle(targetOrientation * Vector3.forward, velocity, up));
            }

            // If no reliable heading, then stay where we are.
            return(currentHeading);
        }
        /// <summary>Positions the virtual camera according to the transposer rules.</summary>
        /// <param name="curState">The current camera state</param>
        /// <param name="deltaTime">Used for damping.  If less than 0, no damping is done.</param>
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            //UnityEngine.Profiling.Profiler.BeginSample("CinemachineOrbitalTransposer.MutateCameraState");
            InitPrevFrameStateInfo(ref curState, deltaTime);

            // Update the heading
            if (FollowTarget != PreviousTarget)
            {
                PreviousTarget      = FollowTarget;
                mTargetRigidBody    = (PreviousTarget == null) ? null : PreviousTarget.GetComponent <Rigidbody>();
                mLastTargetPosition = (PreviousTarget == null) ? Vector3.zero : PreviousTarget.position;
                mHeadingTracker     = null;
            }
            if (!m_HeadingIsSlave)
            {
                UpdateHeading(deltaTime, curState.ReferenceUp);
            }

            if (IsValid)
            {
                mLastTargetPosition = FollowTarget.position;

                // Track the target, with damping
                Vector3    pos;
                Quaternion orient;
                TrackTarget(deltaTime, curState.ReferenceUp, out pos, out orient);

                // Place the camera
                curState.ReferenceUp = orient * Vector3.up;

                float heading = m_XAxis.Value;
                if (m_BindingMode == BindingMode.SimpleFollow)
                {
                    m_XAxis.Value = 0;
                }
                else
                {
                    heading += m_Heading.m_HeadingBias;
                }
                Quaternion headingRot = Quaternion.AngleAxis(heading, curState.ReferenceUp);

                Vector3 offset = EffectiveOffset;
                if (deltaTime >= 0)
                {
                    Vector3 bypass = (headingRot * offset) - mHeadingPrevFrame * mOffsetPrevFrame;
                    bypass = orient * bypass;
                    curState.PositionDampingBypass = bypass;
                }
                orient = orient * headingRot;
                curState.RawPosition = pos + orient * offset;

                mHeadingPrevFrame = (m_BindingMode == BindingMode.SimpleFollow) ? Quaternion.identity : headingRot;
                mOffsetPrevFrame  = offset;
            }
            //UnityEngine.Profiling.Profiler.EndSample();
        }
        /// <summary>Positions the virtual camera according to the transposer rules.</summary>
        /// <param name="curState">The current camera state</param>
        /// <param name="deltaTime">Used for damping.  If less than 0, no damping is done.</param>
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            //UnityEngine.Profiling.Profiler.BeginSample("CinemachineOrbitalTransposer.MutateCameraState");
            InitPrevFrameStateInfo(ref curState, deltaTime);

            // Update the heading
            if (FollowTarget != PreviousTarget)
            {
                PreviousTarget      = FollowTarget;
                mTargetRigidBody    = PreviousTarget == null ? null : PreviousTarget.GetComponent <Rigidbody>();
                mLastTargetPosition = PreviousTarget == null ? Vector3.zero : PreviousTarget.position;
                mHeadingTracker     = null;
            }

            var heading = HeadingUpdater(this, deltaTime, curState.ReferenceUp);

            if (IsValid)
            {
                mLastTargetPosition = FollowTarget.position;

                // Calculate the heading
                if (m_BindingMode != BindingMode.SimpleFollowWithWorldUp)
                {
                    heading += m_Heading.m_HeadingBias;
                }
                var headingRot = Quaternion.AngleAxis(heading, curState.ReferenceUp);

                // Track the target, with damping
                var        offset = EffectiveOffset;
                Vector3    pos;
                Quaternion orient;
                TrackTarget(deltaTime, curState.ReferenceUp, headingRot * offset, out pos, out orient);

                // Place the camera
                curState.ReferenceUp = orient * Vector3.up;
                if (deltaTime >= 0)
                {
                    var bypass = headingRot * offset - mHeadingPrevFrame * mOffsetPrevFrame;
                    bypass = orient * bypass;
                    curState.PositionDampingBypass = bypass;
                }

                orient = orient * headingRot;
                curState.RawPosition = pos + orient * offset;

                mHeadingPrevFrame = m_BindingMode == BindingMode.SimpleFollowWithWorldUp
                    ? Quaternion.identity
                    : headingRot;
                mOffsetPrevFrame = offset;
            }

            //UnityEngine.Profiling.Profiler.EndSample();
        }
Beispiel #6
0
        /// <summary>Positions the virtual camera according to the transposer rules.</summary>
        /// <param name="curState">The current camera state</param>
        /// <param name="deltaTime">Used for damping.  If less than 0, no damping is done.</param>
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            InitPrevFrameStateInfo(ref curState, deltaTime);

            // Update the heading
            if (FollowTarget != PreviousTarget)
            {
                PreviousTarget      = FollowTarget;
                mTargetRigidBody    = (PreviousTarget == null) ? null : PreviousTarget.GetComponent <Rigidbody>();
                mLastTargetPosition = (PreviousTarget == null) ? Vector3.zero : PreviousTarget.position;
                mHeadingTracker     = null;
            }
            LastHeading = HeadingUpdater(this, deltaTime, curState.ReferenceUp);
            float heading = LastHeading;

            if (IsValid)
            {
                mLastTargetPosition = FollowTargetPosition;

                // Calculate the heading
                if (m_BindingMode != BindingMode.SimpleFollowWithWorldUp)
                {
                    heading += m_Heading.m_Bias;
                }
                Quaternion headingRot = Quaternion.AngleAxis(heading, Vector3.up);

                // Track the target, with damping
                Vector3    offset = EffectiveOffset;
                Vector3    pos;
                Quaternion orient;
                TrackTarget(deltaTime, curState.ReferenceUp, headingRot * offset, out pos, out orient);

                // Place the camera
                curState.ReferenceUp = orient * Vector3.up;
                if (deltaTime >= 0)
                {
                    Vector3 bypass = (headingRot * offset) - mHeadingPrevFrame * mOffsetPrevFrame;
                    bypass = orient * bypass;
                    curState.PositionDampingBypass = bypass;
                }
                orient = orient * headingRot;
                curState.RawPosition = pos + orient * offset;

                mHeadingPrevFrame = (m_BindingMode == BindingMode.SimpleFollowWithWorldUp)
                    ? Quaternion.identity : headingRot;
                mOffsetPrevFrame = offset;
            }
        }
        // Make sure this is calld only once per frame
        private float GetTargetHeading(float currentHeading, Quaternion targetOrientation)
        {
            if (m_BindingMode == BindingMode.SimpleFollowWithWorldUp)
            {
                return(0);
            }
            if (FollowTarget == null)
            {
                return(currentHeading);
            }

            var headingDef = m_Heading.m_Definition;

            if (headingDef == Heading.HeadingDefinition.Velocity && mTargetRigidBody == null)
            {
                headingDef = Heading.HeadingDefinition.PositionDelta;
            }

            Vector3 velocity = Vector3.zero;

            switch (headingDef)
            {
            case Heading.HeadingDefinition.PositionDelta:
                velocity = FollowTargetPosition - mLastTargetPosition;
                break;

            case Heading.HeadingDefinition.Velocity:
                velocity = mTargetRigidBody.velocity;
                break;

            case Heading.HeadingDefinition.TargetForward:
                velocity = FollowTargetRotation * Vector3.forward;
                break;

            default:
            case Heading.HeadingDefinition.WorldForward:
                return(0);
            }

            // Process the velocity and derive the heading from it.
            Vector3 up = targetOrientation * Vector3.up;

            velocity = velocity.ProjectOntoPlane(up);
            if (headingDef != Heading.HeadingDefinition.TargetForward)
            {
                int filterSize = m_Heading.m_VelocityFilterStrength * 5;
                if (mHeadingTracker == null || mHeadingTracker.FilterSize != filterSize)
                {
                    mHeadingTracker = new HeadingTracker(filterSize);
                }
                mHeadingTracker.DecayHistory();
                if (!velocity.AlmostZero())
                {
                    mHeadingTracker.Add(velocity);
                }
                velocity = mHeadingTracker.GetReliableHeading();
            }
            if (!velocity.AlmostZero())
            {
                return(UnityVectorExtensions.SignedAngle(
                           targetOrientation * Vector3.forward, velocity, up));
            }

            // If no reliable heading, then stay where we are.
            return(currentHeading);
        }
Beispiel #8
0
        Vector3 DoTracking(Vector3 currentPosition, Vector3 up, float deltaTime)
        {
            if (VirtualCamera.Follow == null)
            {
                return(currentPosition);
            }

            if (VirtualCamera.Follow != PreviousTarget)
            {
                PreviousTarget      = VirtualCamera.Follow;
                mTargetRigidBody    = VirtualCamera.Follow.GetComponent <Rigidbody>();
                mLastTargetPosition = VirtualCamera.Follow.position;
                mHeadingTracker     = null;
            }

            // Heading
            if (!m_HeadingIsSlave)
            {
                UpdateHeading(deltaTime, up, true);
            }
            mLastTargetPosition = VirtualCamera.Follow.position;

            // Where to put the camera
            Vector3 localTarget = EffectiveOffset(up);

            localTarget = Quaternion.AngleAxis(m_XAxis.Value + m_HeadingBias, up) * localTarget;

            // Adjust for damping, which is done in local coords
            if (deltaTime > 0)
            {
                if (m_DampingStyle == DampingStyle.Polar)
                {
                    // Get the offset in polar
                    Vector3 localCurrent     = currentPosition - VirtualCamera.Follow.position;
                    Vector3 currentOnPlane   = localCurrent.ProjectOntoPlane(up);
                    Vector3 currentPerpPlane = localCurrent - currentOnPlane;
                    Vector3 targetOnPlane    = localTarget.ProjectOntoPlane(up);
                    Vector3 targetPerpPlane  = localTarget - targetOnPlane;
                    Vector3 delta            = new Vector3(
                        UnityVectorExtensions.SignedAngle(currentOnPlane, targetOnPlane, up),
                        Vector3.Dot(targetPerpPlane - currentPerpPlane, up),
                        (targetOnPlane.magnitude - currentOnPlane.magnitude));

                    // Apply damping
                    Vector3 trackingSpeeds = TrackingSpeeds;
                    for (int i = 0; i < 3; ++i)
                    {
                        delta[i] *= deltaTime / Mathf.Max(trackingSpeeds[i], deltaTime);
                    }

                    localTarget  = currentOnPlane;
                    localTarget += (localTarget.normalized * delta.z);
                    localTarget += currentPerpPlane + (delta.y * up);
                    localTarget  = Quaternion.AngleAxis(delta.x, up) * localTarget;
                }
                else
                {
                    Vector3    worldOffset           = currentPosition - (VirtualCamera.Follow.position + localTarget);
                    Quaternion localToWorldTransform = Quaternion.LookRotation(
                        VirtualCamera.Follow.rotation * Vector3.forward, up);
                    Vector3 localOffset    = Quaternion.Inverse(localToWorldTransform) * worldOffset;
                    Vector3 trackingSpeeds = TrackingSpeeds;
                    for (int i = 0; i < 3; ++i)
                    {
                        localOffset[i] *= deltaTime / Mathf.Max(trackingSpeeds[i], deltaTime);
                    }
                    return(currentPosition - (localToWorldTransform * localOffset));
                }
            }

            // Return the adjusted rig position
            return(VirtualCamera.Follow.position + localTarget);
        }
        private float GetTargetHeading(float currentHeading, Vector3 up, float deltaTime)
        {
            if (VirtualCamera.Follow == null)
            {
                return(currentHeading);
            }

            if (m_RecenterToTargetHeading.m_HeadingDerivationMode
                == Recentering.HeadingDerivationMode.Velocity &&
                mTargetRigidBody == null)
            {
                CinemachineDebugLogger.LogWarn(
                    "Attempted to use HeadingDerivationMode.Velocity to calculate heading for {0}. No RigidBody was present on '{1}'. Defaulting to position delta",
                    GetFullName(VirtualCamera.VirtualCameraGameObject), VirtualCamera.Follow);
                m_RecenterToTargetHeading.m_HeadingDerivationMode
                    = Recentering.HeadingDerivationMode.PositionDelta;
            }

            Vector3 velocity = Vector3.zero;

            switch (m_RecenterToTargetHeading.m_HeadingDerivationMode)
            {
            case Recentering.HeadingDerivationMode.PositionDelta:
                velocity = VirtualCamera.Follow.position - mLastTargetPosition;
                break;

            case Recentering.HeadingDerivationMode.Velocity:
                velocity = mTargetRigidBody.velocity;
                break;

            default:
            case Recentering.HeadingDerivationMode.EulerYRotation:
                return(VirtualCamera.Follow.rotation.eulerAngles.y);

            case Recentering.HeadingDerivationMode.WorldHeading:
                return(m_RecenterToTargetHeading.m_WorldDefaultHeading);
            }

            // Process the velocity and derive the heading from it.
            int filterSize = m_RecenterToTargetHeading.m_VelocityFilterStrength * 5;

            if (mHeadingTracker == null || mHeadingTracker.FilterSize != filterSize)
            {
                mHeadingTracker = new HeadingTracker(filterSize);
            }
            mHeadingTracker.DecayHistory();
            velocity = velocity.ProjectOntoPlane(up);
            if (!velocity.AlmostZero())
            {
                mHeadingTracker.Add(velocity);
            }

            velocity = mHeadingTracker.GetReliableHeading();
            if (!velocity.AlmostZero())
            {
                Vector3 fwd = (-GetBackVector(up)).ProjectOntoPlane(up);
                return(UnityVectorExtensions.SignedAngle(fwd, velocity, up));
            }

            // If no reliable heading, then stay where we are.
            return(currentHeading);
        }