예제 #1
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 that 0, no damping is done.</param>
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            // Init previous frame state info
            if (deltaTime < 0)
            {
                m_PreviousPathPosition   = m_PathPosition;
                m_PreviousCameraPosition = curState.RawPosition;
            }

            if (!IsValid)
            {
                return;
            }

            //UnityEngine.Profiling.Profiler.BeginSample("CinemachineTrackedDolly.MutateCameraState");
            // Get the new ideal path base position
            if (m_AutoDolly.m_Enabled && FollowTarget != null)
            {
                float prevPos = m_Path.ToNativePathUnits(m_PreviousPathPosition, m_PositionUnits);
                // This works in path units
                m_PathPosition = m_Path.FindClosestPoint(
                    FollowTargetPosition,
                    Mathf.FloorToInt(prevPos),
                    (deltaTime < 0 || m_AutoDolly.m_SearchRadius <= 0)
                        ? -1 : m_AutoDolly.m_SearchRadius,
                    m_AutoDolly.m_SearchResolution);
                m_PathPosition = m_Path.FromPathNativeUnits(m_PathPosition, m_PositionUnits);

                // Apply the path position offset
                m_PathPosition += m_AutoDolly.m_PositionOffset;
            }
            float newPathPosition = m_PathPosition;

            if (deltaTime >= 0)
            {
                // Normalize previous position to find the shortest path
                float maxUnit = m_Path.MaxUnit(m_PositionUnits);
                if (maxUnit > 0)
                {
                    float prev = m_Path.StandardizeUnit(m_PreviousPathPosition, m_PositionUnits);
                    float next = m_Path.StandardizeUnit(newPathPosition, m_PositionUnits);
                    if (m_Path.Looped && Mathf.Abs(next - prev) > maxUnit / 2)
                    {
                        if (next > prev)
                        {
                            prev += maxUnit;
                        }
                        else
                        {
                            prev -= maxUnit;
                        }
                    }
                    m_PreviousPathPosition = prev;
                    newPathPosition        = next;
                }

                // Apply damping along the path direction
                float offset = m_PreviousPathPosition - newPathPosition;
                offset          = Damper.Damp(offset, m_ZDamping, deltaTime);
                newPathPosition = m_PreviousPathPosition - offset;
            }
            m_PreviousPathPosition = newPathPosition;
            Quaternion newPathOrientation = m_Path.EvaluateOrientationAtUnit(newPathPosition, m_PositionUnits);

            // Apply the offset to get the new camera position
            Vector3 newCameraPos = m_Path.EvaluatePositionAtUnit(newPathPosition, m_PositionUnits);
            Vector3 offsetX      = newPathOrientation * Vector3.right;
            Vector3 offsetY      = newPathOrientation * Vector3.up;
            Vector3 offsetZ      = newPathOrientation * Vector3.forward;

            newCameraPos += m_PathOffset.x * offsetX;
            newCameraPos += m_PathOffset.y * offsetY;
            newCameraPos += m_PathOffset.z * offsetZ;

            // Apply damping to the remaining directions
            if (deltaTime >= 0)
            {
                Vector3 currentCameraPos = m_PreviousCameraPosition;
                Vector3 delta            = (currentCameraPos - newCameraPos);
                Vector3 delta1           = Vector3.Dot(delta, offsetY) * offsetY;
                Vector3 delta0           = delta - delta1;
                delta0       = Damper.Damp(delta0, m_XDamping, deltaTime);
                delta1       = Damper.Damp(delta1, m_YDamping, deltaTime);
                newCameraPos = currentCameraPos - (delta0 + delta1);
            }
            curState.RawPosition = m_PreviousCameraPosition = newCameraPos;

            // Set the orientation and up
            Quaternion newOrientation
                = GetCameraOrientationAtPathPoint(newPathOrientation, curState.ReferenceUp);

            if (deltaTime < 0)
            {
                m_PreviousOrientation = newOrientation;
            }
            else
            {
                if (deltaTime >= 0)
                {
                    Vector3 relative = (Quaternion.Inverse(m_PreviousOrientation)
                                        * newOrientation).eulerAngles;
                    for (int i = 0; i < 3; ++i)
                    {
                        if (relative[i] > 180)
                        {
                            relative[i] -= 360;
                        }
                    }
                    relative       = Damper.Damp(relative, AngularDamping, deltaTime);
                    newOrientation = m_PreviousOrientation * Quaternion.Euler(relative);
                }
                m_PreviousOrientation = newOrientation;
            }

            curState.RawOrientation = newOrientation;
            if (m_CameraUp != CameraUpMode.Default)
            {
                curState.ReferenceUp = curState.RawOrientation * Vector3.up;
            }
            //UnityEngine.Profiling.Profiler.EndSample();
        }