VcamExtraState GetExtraState(ICinemachineCamera vcam)
        {
            if (mExtraState == null)
            {
                mExtraState = new Dictionary <ICinemachineCamera, VcamExtraState>();
            }
            VcamExtraState extra = null;

            if (!mExtraState.TryGetValue(vcam, out extra))
            {
                extra = mExtraState[vcam] = new VcamExtraState();
            }
            if (extra.filter == null || extra.filter.Sigma != m_PositionSmoothing)
            {
                extra.filter = new GaussianWindow1D_Vector3(m_PositionSmoothing);
            }
            if (!m_UseCurbFeelers)
            {
                extra.curbFeelers = null;
            }
            else if (extra.curbFeelers == null || extra.curbFeelers.Length != 9 ||
                     extra.curbResistance != m_CurbResistance ||
                     extra.feelerDistance != m_CurbFeelerDistance)
            {
                extra.RebuildCurbFeelers(m_CurbResistance, m_CurbFeelerDistance);
            }
            return(extra);
        }
Exemplo n.º 2
0
        /// <summary>Callback to to the camera confining</summary>
        protected override void PostPipelineStageCallback(
            CinemachineVirtualCameraBase vcam,
            CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
        {
            if (IsValid)
            {
                // Move the body before the Aim is calculated
                if (stage == CinemachineCore.Stage.Body)
                {
                    Vector3 displacement;
                    if (m_ConfineScreenEdges && state.Lens.Orthographic)
                    {
                        displacement = ConfineScreenEdges(vcam, ref state);
                    }
                    else
                    {
                        displacement = ConfinePoint(state.CorrectedPosition);
                    }

                    VcamExtraState extra = GetExtraState <VcamExtraState>(vcam);
                    if (m_Damping > 0 && deltaTime >= 0)
                    {
                        Vector3 delta = displacement - extra.m_previousDisplacement;
                        delta        = Damper.Damp(delta, m_Damping, deltaTime);
                        displacement = extra.m_previousDisplacement + delta;
                    }
                    extra.m_previousDisplacement = displacement;
                    state.PositionCorrection    += displacement;
                    extra.confinerDisplacement   = displacement.magnitude;
                }
            }
        }
        Vector3 PreserveLineOfSight(ref CameraState state, ref VcamExtraState extra)
        {
            Vector3 displacement = Vector3.zero;

            if (state.HasLookAt && m_CollideAgainst != 0 &&
                m_CollideAgainst != m_TransparentLayers)
            {
                Vector3    cameraPos = state.CorrectedPosition;
                Vector3    lookAtPos = state.ReferenceLookAt;
                RaycastHit hitInfo   = new RaycastHit();
                displacement = PullCameraInFrontOfNearestObstacle(
                    cameraPos, lookAtPos, m_CollideAgainst & ~m_TransparentLayers, ref hitInfo);
                Vector3 pos = cameraPos + displacement;
                if (hitInfo.collider != null)
                {
                    extra.AddPointToDebugPath(pos);
                    if (m_Strategy != ResolutionStrategy.PullCameraForward)
                    {
                        Vector3 targetToCamera = cameraPos - lookAtPos;
                        pos = PushCameraBack(
                            pos, targetToCamera, hitInfo, lookAtPos,
                            new Plane(state.ReferenceUp, cameraPos),
                            targetToCamera.magnitude, m_MaximumEffort, ref extra);
                    }
                }
                displacement = pos - cameraPos;
            }
            return(displacement);
        }
Exemplo n.º 4
0
        private void PostPipelineStageCallback(
            CinemachineVirtualCameraBase vcam,
            CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
        {
            if (enabled && m_BoundingVolume != null)
            {
                // Move the body before the Aim is calculated
                if (stage == CinemachineCore.Stage.Body)
                {
                    Vector3 camPos   = state.CorrectedPosition;
                    Vector3 closest  = m_BoundingVolume.ClosestPoint(camPos);
                    Vector3 dir      = closest - camPos;
                    float   distance = dir.magnitude;
                    if (distance > Epsilon)
                    {
                        dir /= distance;
                    }
                    Vector3 displacement = distance * dir;

                    VcamExtraState extra = GetExtraState(vcam);
                    if (m_Damping > 0 && deltaTime > 0)
                    {
                        Vector3 delta = displacement - extra.m_previousDisplacement;
                        if (Mathf.Abs(delta.magnitude) > Epsilon)
                        {
                            delta *= deltaTime / Mathf.Max(m_Damping * kDampingScale, deltaTime);
                        }
                        displacement = extra.m_previousDisplacement + delta;
                    }
                    extra.m_previousDisplacement = displacement;
                    state.PositionCorrection    += displacement;
                    extra.confinerDisplacement   = displacement.magnitude;
                }
            }
        }
        private Vector3 PreserveLignOfSight(ref CameraState state, ref VcamExtraState extra)
        {
            var displacement = Vector3.zero;

            if (state.HasLookAt)
            {
                var cameraPos             = state.CorrectedPosition;
                var lookAtPos             = state.ReferenceLookAt;
                var pos                   = cameraPos;
                var dir                   = pos - lookAtPos;
                var targetDistance        = dir.magnitude;
                var minDistanceFromTarget = Mathf.Max(m_MinimumDistanceFromTarget, Epsilon);
                if (targetDistance > minDistanceFromTarget)
                {
                    dir.Normalize();
                    var rayLength = targetDistance - minDistanceFromTarget;
                    if (m_DistanceLimit > Epsilon)
                    {
                        rayLength = Mathf.Min(m_DistanceLimit, rayLength);
                    }

                    // Make a ray that looks towards the camera, to get the most distant obstruction
                    var ray = new Ray(pos - rayLength * dir, dir);
                    rayLength += PrecisionSlush;
                    if (rayLength > Epsilon)
                    {
                        RaycastHit hitInfo;
                        if (RaycastIgnoreTag(ray, out hitInfo, rayLength))
                        {
                            // Pull camera forward in front of obstacle
                            var adjustment = Mathf.Max(0, hitInfo.distance - PrecisionSlush);
                            pos = ray.GetPoint(adjustment);
                            extra.AddPointToDebugPath(pos);
                            if (m_Strategy != ResolutionStrategy.PullCameraForward)
                            {
                                pos = PushCameraBack(
                                    pos, dir, hitInfo, lookAtPos,
                                    new Plane(state.ReferenceUp, cameraPos),
                                    targetDistance, m_MaximumEffort, ref extra);
                            }
                        }
                    }
                }

                if (m_CameraRadius > Epsilon)
                {
                    pos += RespectCameraRadius(pos, state.ReferenceLookAt);
                }
                else if (mCameraColliderGameObject != null)
                {
                    CleanupCameraCollider();
                }
                displacement = pos - cameraPos;
            }

            return(displacement);
        }
Exemplo n.º 6
0
        VcamExtraState GetExtraState(ICinemachineCamera vcam)
        {
            if (mExtraState == null)
            {
                mExtraState = new Dictionary <ICinemachineCamera, VcamExtraState>();
            }
            VcamExtraState extra = null;

            if (!mExtraState.TryGetValue(vcam, out extra))
            {
                extra = mExtraState[vcam] = new VcamExtraState();
            }
            return(extra);
        }
Exemplo n.º 7
0
        private Vector3 PreserveLignOfSight(ref CameraState state, ref VcamExtraState extra)
        {
            Vector3 displacement = Vector3.zero;

            if (state.HasLookAt && m_CollideAgainst != 0 &&
                m_CollideAgainst != m_TransparentLayers)
            {
                Vector3    cameraPos = state.CorrectedPosition;
                Vector3    lookAtPos = state.ReferenceLookAt;
                RaycastHit hitInfo   = new RaycastHit();
                displacement = PullCameraInFrontOfNearestObstacle(
                    cameraPos, lookAtPos, m_CollideAgainst & ~m_TransparentLayers, ref hitInfo);
                Vector3 pos = cameraPos + displacement;
                if (hitInfo.collider != null)
                {
                    extra.AddPointToDebugPath(pos);
                    if (m_Strategy != ResolutionStrategy.PullCameraForward)
                    {
                        Vector3 targetToCamera = cameraPos - lookAtPos;
                        pos = PushCameraBack(
                            pos, targetToCamera, hitInfo, lookAtPos,
                            new Plane(state.ReferenceUp, cameraPos),
                            targetToCamera.magnitude, m_MaximumEffort, ref extra);
                    }
                }
                displacement = pos - cameraPos;

                // Apply distance smoothing
                if (m_SmoothingTime > Epsilon)
                {
                    Vector3 dir      = pos - lookAtPos;
                    float   distance = dir.magnitude;
                    if (distance > Epsilon)
                    {
                        dir /= distance;
                        if (!displacement.AlmostZero())
                        {
                            extra.UpdateDistanceSmoothing(distance, m_SmoothingTime);
                        }
                        distance      = extra.ApplyDistanceSmoothing(distance, m_SmoothingTime);
                        displacement += (state.ReferenceLookAt + dir * distance) - pos;
                    }
                }
            }
            return(displacement);
        }
        private bool PreserveLignOfSight(ref CameraState state, VcamExtraState extra)
        {
            bool displaced = false;

            if (state.HasLookAt)
            {
                Vector3 lookAtPos             = state.ReferenceLookAt;
                Vector3 pos                   = state.CorrectedPosition;
                Vector3 dir                   = lookAtPos - pos;
                float   targetDistance        = dir.magnitude;
                float   minDistanceFromTarget = Mathf.Max(m_MinimumDistanceFromTarget, UnityVectorExtensions.Epsilon);
                if (targetDistance > minDistanceFromTarget)
                {
                    dir.Normalize();
                    float rayFar = targetDistance - minDistanceFromTarget;
                    if (m_LineOfSightFeelerDistance > UnityVectorExtensions.Epsilon)
                    {
                        rayFar = Mathf.Min(m_LineOfSightFeelerDistance, rayFar);
                    }

                    // Make a ray that looks towards the camera, to get the most distant obstruction
                    Ray   ray = new Ray(pos + rayFar * dir, -dir);
                    int   raycastLayerMask = m_CollideAgainst.value;
                    float rayLength        = rayFar - Mathf.Max(0, m_MinimumDistanceFromCamera);
                    if (rayLength > Mathf.Epsilon)
                    {
                        RaycastHit hitInfo;
                        if (Physics.Raycast(ray, out hitInfo, rayLength, raycastLayerMask))
                        {
                            float adjustment = hitInfo.distance;
                            if (m_UseCurbFeelers)
                            {
                                adjustment -= MinCurbDistance;
                            }
                            pos = ray.GetPoint(adjustment);
                            Vector3 displacement = pos - state.CorrectedPosition;
                            state.PositionCorrection   += displacement;
                            extra.colliderDisplacement += displacement.magnitude;
                            displaced = true;
                        }
                    }
                }
            }
            return(displaced);
        }
Exemplo n.º 9
0
        VcamExtraState GetExtraState(ICinemachineCamera vcam)
        {
            if (mExtraState == null)
            {
                mExtraState = new Dictionary <ICinemachineCamera, VcamExtraState>();
            }
            VcamExtraState extra = null;

            if (!mExtraState.TryGetValue(vcam, out extra))
            {
                extra = mExtraState[vcam] = new VcamExtraState();
            }
            if (extra.filter == null || extra.filter.Sigma != m_Smoothing)
            {
                extra.filter = new GaussianWindow1D_Vector3(m_Smoothing);
            }
            return(extra);
        }
        private bool ApplyCurbFeelers(ref CameraState state, VcamExtraState extra)
        {
            bool       displaced   = false;
            Vector3    pos         = state.CorrectedPosition;
            Quaternion orientation = state.CorrectedOrientation;
            RaycastHit hitInfo;
            int        raycastLayerMask = m_CollideAgainst.value;

            Ray     feelerRay         = new Ray();
            int     numHits           = 0;
            Vector3 resultingPosition = Vector3.zero;

            for (int i = 0; i < extra.curbFeelers.Length; ++i)
            {
                CompiledCurbFeeler feeler = extra.curbFeelers[i];
                feelerRay.origin    = pos;
                feelerRay.direction = orientation * feeler.LocalVector;
                if (Physics.Raycast(feelerRay, out hitInfo, feeler.RayDistance, raycastLayerMask))
                {
                    float compressionPercent = Mathf.Clamp01((feeler.RayDistance - hitInfo.distance) / feeler.RayDistance);
                    compressionPercent = 1f - Mathf.Pow(compressionPercent, feeler.DampingConstant);
                    resultingPosition += hitInfo.point - feelerRay.direction * (compressionPercent * feeler.RayDistance);
                    feeler.IsHit       = true;
                    feeler.HitDistance = hitInfo.distance;
                    numHits++;
                }
                else
                {
                    feeler.IsHit       = false;
                    feeler.HitDistance = float.MaxValue;
                }
                extra.curbFeelers[i] = feeler;
            }

            // Average the resulting positions if feelers hit anything
            if (numHits > 0)
            {
                Vector3 displacement = (resultingPosition / (float)numHits) - state.CorrectedPosition;
                extra.colliderDisplacement += displacement.magnitude;
                state.PositionCorrection   += displacement;
                displaced = true;
            }
            return(displaced);
        }
 protected override void PostPipelineStageCallback(
     CinemachineVirtualCameraBase vcam,
     CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
 {
     if (enabled)
     {
         if (stage == CinemachineCore.Stage.Body)
         {
             VcamExtraState extra = GetExtraState <VcamExtraState>(vcam);
             if (m_PositionSmoothing > 0)
             {
                 if (deltaTime < 0)
                 {
                     extra.mSmoothingFilter = null; // reset the filter
                 }
                 state.PositionCorrection
                     += ApplySmoothing(vcam, state.CorrectedPosition, extra) - state.CorrectedPosition;
             }
             if (m_LookAtSmoothing > 0 && state.HasLookAt)
             {
                 if (deltaTime < 0)
                 {
                     extra.mSmoothingFilterLookAt = null; // reset the filter
                 }
                 state.ReferenceLookAt = ApplySmoothingLookAt(vcam, state.ReferenceLookAt, extra);
             }
         }
         if (stage == CinemachineCore.Stage.Aim)
         {
             if (m_RotationSmoothing > 0)
             {
                 VcamExtraState extra = GetExtraState <VcamExtraState>(vcam);
                 if (deltaTime < 0)
                 {
                     extra.mSmoothingFilterRotation = null; // reset the filter
                 }
                 Quaternion q = Quaternion.Inverse(state.CorrectedOrientation)
                                * ApplySmoothing(vcam, state.CorrectedOrientation, state.ReferenceUp, extra);
                 state.OrientationCorrection = state.OrientationCorrection * q;
             }
         }
     }
 }
        protected override void PostPipelineStageCallback(
            CinemachineVirtualCameraBase vcam,
            CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
        {
            VcamExtraState extra = GetExtraState <VcamExtraState>(vcam);

            if (!enabled || deltaTime < 0)
            {
                extra.m_previousFrameZoom = state.Lens.FieldOfView;
            }
            if (enabled)
            {
                // Set the zoom after the body has been positioned, but before the aim,
                // so that composer can compose using the updated fov.
                if (stage == CinemachineCore.Stage.Body)
                {
                    // Try to reproduce the target width
                    float targetWidth = Mathf.Max(m_Width, 0);
                    float fov         = 179f;
                    float d           = Vector3.Distance(state.CorrectedPosition, state.ReferenceLookAt);
                    if (d > UnityVectorExtensions.Epsilon)
                    {
                        // Clamp targetWidth to FOV min/max
                        float minW = d * 2f * Mathf.Tan(m_MinFOV * Mathf.Deg2Rad / 2f);
                        float maxW = d * 2f * Mathf.Tan(m_MaxFOV * Mathf.Deg2Rad / 2f);
                        targetWidth = Mathf.Clamp(targetWidth, minW, maxW);

                        // Apply damping
                        if (deltaTime >= 0 && m_Damping > 0)
                        {
                            float currentWidth = d * 2f * Mathf.Tan(extra.m_previousFrameZoom * Mathf.Deg2Rad / 2f);
                            float delta        = targetWidth - currentWidth;
                            delta       = Damper.Damp(delta, m_Damping, deltaTime);
                            targetWidth = currentWidth + delta;
                        }
                        fov = 2f * Mathf.Atan(targetWidth / (2 * d)) * Mathf.Rad2Deg;
                    }
                    LensSettings lens = state.Lens;
                    lens.FieldOfView = extra.m_previousFrameZoom = Mathf.Clamp(fov, m_MinFOV, m_MaxFOV);
                    state.Lens       = lens;
                }
            }
        }
        Vector3 PushCameraBack(
            Vector3 currentPos, Vector3 pushDir, RaycastHit obstacle,
            Vector3 lookAtPos, Plane startPlane, float targetDistance, int iterations,
            ref VcamExtraState extra)
        {
            // Take a step along the wall.
            Vector3 pos = currentPos;
            Vector3 dir = Vector3.zero;

            if (!GetWalkingDirection(pos, pushDir, obstacle, ref dir))
            {
                return(pos);
            }

            Ray   ray      = new Ray(pos, dir);
            float distance = GetPushBackDistance(ray, startPlane, targetDistance, lookAtPos);

            if (distance <= Epsilon)
            {
                return(pos);
            }

            // Check only as far as the obstacle bounds
            float clampedDistance = ClampRayToBounds(ray, distance, obstacle.collider.bounds);

            distance = Mathf.Min(distance, clampedDistance + k_PrecisionSlush);

            if (RuntimeUtility.RaycastIgnoreTag(ray, out var hitInfo, distance,
                                                m_CollideAgainst & ~m_TransparentLayers, m_IgnoreTag))
            {
                // We hit something.  Stop there and take a step along that wall.
                float adjustment = hitInfo.distance - k_PrecisionSlush;
                pos = ray.GetPoint(adjustment);
                extra.AddPointToDebugPath(pos);
                if (iterations > 1)
                {
                    pos = PushCameraBack(
                        pos, dir, hitInfo,
                        lookAtPos, startPlane,
                        targetDistance, iterations - 1, ref extra);
                }

                return(pos);
            }

            // Didn't hit anything.  Can we push back all the way now?
            pos = ray.GetPoint(distance);

            // First check if we can still see the target.  If not, abort
            dir = pos - lookAtPos;
            float d = dir.magnitude;

            if (d < Epsilon || RuntimeUtility.RaycastIgnoreTag(
                    new Ray(lookAtPos, dir), out _, d - k_PrecisionSlush,
                    m_CollideAgainst & ~m_TransparentLayers, m_IgnoreTag))
            {
                return(currentPos);
            }

            // All clear
            ray = new Ray(pos, dir);
            extra.AddPointToDebugPath(pos);
            distance = GetPushBackDistance(ray, startPlane, targetDistance, lookAtPos);
            if (distance > Epsilon)
            {
                if (!RuntimeUtility.RaycastIgnoreTag(ray, out hitInfo, distance,
                                                     m_CollideAgainst & ~m_TransparentLayers, m_IgnoreTag))
                {
                    pos = ray.GetPoint(distance); // no obstacles - all good
                    extra.AddPointToDebugPath(pos);
                }
                else
                {
                    // We hit something.  Stop there and maybe take a step along that wall
                    float adjustment = hitInfo.distance - k_PrecisionSlush;
                    pos = ray.GetPoint(adjustment);
                    extra.AddPointToDebugPath(pos);
                    if (iterations > 1)
                    {
                        pos = PushCameraBack(
                            pos, dir, hitInfo, lookAtPos, startPlane,
                            targetDistance, iterations - 1, ref extra);
                    }
                }
            }
            return(pos);
        }
Exemplo n.º 14
0
        private void PostPipelineStageCallback(
            CinemachineVirtualCameraBase vcam,
            CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
        {
            VcamExtraState extra = null;

            if (stage == CinemachineCore.Stage.Body)
            {
                extra = GetExtraState(vcam);
                extra.targetObscured       = false;
                extra.colliderDisplacement = 0;
            }
            if (enabled)
            {
                // Move the body before the Aim is calculated
                if (stage == CinemachineCore.Stage.Body)
                {
                    if (m_PreserveLineOfSight)
                    {
                        Vector3 displacement = PreserveLignOfSight(ref state);
                        if (m_Smoothing > 0)
                        {
                            if (deltaTime > 0)
                            {
                                displacement = extra.filter.Filter(displacement);
                            }
                            else
                            {
                                extra.filter.Reset();
                            }
                        }
                        state.PositionCorrection   += displacement;
                        extra.colliderDisplacement += displacement.magnitude;
                    }
                }
                // Rate the shot after the aim was set
                if (stage == CinemachineCore.Stage.Aim)
                {
                    extra = GetExtraState(vcam);
                    extra.targetObscured = CheckForTargetObstructions(state);

                    // GML these values are an initial arbitrary attempt at rating quality
                    if (extra.targetObscured)
                    {
                        state.ShotQuality *= 0.2f;
                    }
                    if (extra.colliderDisplacement > 0)
                    {
                        state.ShotQuality *= 0.8f;
                    }

                    float       nearnessBoost = 0;
                    const float kMaxNearBoost = 0.2f;
                    if (m_OptimalTargetDistance > 0 && state.HasLookAt)
                    {
                        float distance = Vector3.Magnitude(state.ReferenceLookAt - state.FinalPosition);
                        if (distance <= m_OptimalTargetDistance)
                        {
                            float threshold = m_OptimalTargetDistance / 2;
                            if (distance >= threshold)
                            {
                                nearnessBoost = kMaxNearBoost * (distance - threshold)
                                                / (m_OptimalTargetDistance - threshold);
                            }
                        }
                        else
                        {
                            distance -= m_OptimalTargetDistance;
                            float threshold = m_OptimalTargetDistance * 3;
                            if (distance < threshold)
                            {
                                nearnessBoost = kMaxNearBoost * (1f - (distance / threshold));
                            }
                        }
                        state.ShotQuality *= (1f + nearnessBoost);
                    }
                }
            }
        }
Exemplo n.º 15
0
        /// <summary>Callback to do the collision resolution and shot evaluation</summary>
        protected override void PostPipelineStageCallback(
            CinemachineVirtualCameraBase vcam,
            CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
        {
            VcamExtraState extra = null;

            if (stage == CinemachineCore.Stage.Body)
            {
                extra = GetExtraState <VcamExtraState>(vcam);
                extra.targetObscured       = false;
                extra.colliderDisplacement = 0;
                if (extra.debugResolutionPath != null)
                {
                    extra.debugResolutionPath.RemoveRange(0, extra.debugResolutionPath.Count);
                }
            }

            // Move the body before the Aim is calculated
            if (stage == CinemachineCore.Stage.Body)
            {
                if (m_AvoidObstacles)
                {
                    Vector3 displacement = Vector3.zero;
                    displacement = PreserveLignOfSight(ref state, ref extra);
                    if (m_MinimumOcclusionTime > Epsilon)
                    {
                        float now = Time.timeSinceLevelLoad;
                        if (displacement.sqrMagnitude < Epsilon)
                        {
                            extra.occlusionStartTime = 0;
                        }
                        else
                        {
                            if (extra.occlusionStartTime <= 0)
                            {
                                extra.occlusionStartTime = now;
                            }
                            if (now - extra.occlusionStartTime < m_MinimumOcclusionTime)
                            {
                                displacement = extra.m_previousDisplacement;
                            }
                        }
                    }

                    float damping = m_Damping;
                    if (displacement.AlmostZero())
                    {
                        extra.ResetDistanceSmoothing(m_SmoothingTime);
                    }
                    else
                    {
                        damping = m_DampingWhenOccluded;
                    }
                    if (damping > 0 && deltaTime >= 0)
                    {
                        Vector3 delta = displacement - extra.m_previousDisplacement;
                        delta        = Damper.Damp(delta, damping, deltaTime);
                        displacement = extra.m_previousDisplacement + delta;
                    }
                    extra.m_previousDisplacement = displacement;
                    Vector3 correction = RespectCameraRadius(state.CorrectedPosition + displacement, ref state);
                    if (damping > 0 && deltaTime >= 0)
                    {
                        Vector3 delta = correction - extra.m_previousDisplacementCorrection;
                        delta      = Damper.Damp(delta, damping, deltaTime);
                        correction = extra.m_previousDisplacementCorrection + delta;
                    }
                    displacement += correction;
                    extra.m_previousDisplacementCorrection = correction;
                    state.PositionCorrection   += displacement;
                    extra.colliderDisplacement += displacement.magnitude;
                }
            }
            // Rate the shot after the aim was set
            if (stage == CinemachineCore.Stage.Aim)
            {
                extra = GetExtraState <VcamExtraState>(vcam);
                extra.targetObscured = IsTargetOffscreen(state) || CheckForTargetObstructions(state);

                // GML these values are an initial arbitrary attempt at rating quality
                if (extra.targetObscured)
                {
                    state.ShotQuality *= 0.2f;
                }
                if (extra.colliderDisplacement > 0)
                {
                    state.ShotQuality *= 0.8f;
                }

                float       nearnessBoost = 0;
                const float kMaxNearBoost = 0.2f;
                if (m_OptimalTargetDistance > 0 && state.HasLookAt)
                {
                    float distance = Vector3.Magnitude(state.ReferenceLookAt - state.FinalPosition);
                    if (distance <= m_OptimalTargetDistance)
                    {
                        float threshold = m_OptimalTargetDistance / 2;
                        if (distance >= threshold)
                        {
                            nearnessBoost = kMaxNearBoost * (distance - threshold)
                                            / (m_OptimalTargetDistance - threshold);
                        }
                    }
                    else
                    {
                        distance -= m_OptimalTargetDistance;
                        float threshold = m_OptimalTargetDistance * 3;
                        if (distance < threshold)
                        {
                            nearnessBoost = kMaxNearBoost * (1f - (distance / threshold));
                        }
                    }
                    state.ShotQuality *= (1f + nearnessBoost);
                }
            }
        }
        private void PostPipelineStageCallback(
            CinemachineVirtualCameraBase vcam,
            CinemachineCore.Stage stage, ref CameraState state, CameraState previousState, float deltaTime)
        {
            VcamExtraState extra = null;

            if (stage == CinemachineCore.Stage.Body)
            {
                extra = GetExtraState(vcam);
                extra.targetObscured       = false;
                extra.colliderDisplacement = 0;
                if (extra.colliderDisplacementDecay > 0)
                {
                    --extra.colliderDisplacementDecay; // decay the displacement to accommodate the filter
                }
            }
            if (enabled)
            {
                // Move the body before the Aim is calculated
                if (stage == CinemachineCore.Stage.Body)
                {
                    if (m_PreserveLineOfSight)
                    {
                        PreserveLignOfSight(ref state, extra);
                    }
                    if (m_UseCurbFeelers && m_CurbFeelerDistance > UnityVectorExtensions.Epsilon)
                    {
                        ApplyCurbFeelers(ref state, extra);
                    }
                    if (extra.colliderDisplacement > 0.1f)
                    {
                        extra.colliderDisplacementDecay = extra.filter.KernelSize + 1;
                    }

                    // Apply the smoothing filter
                    Vector3 pos = state.CorrectedPosition;
                    if (m_PositionSmoothing > 0)
                    {
                        state.PositionCorrection += extra.filter.Filter(pos) - pos;
                    }
                }
                // Rate the shot after the aim was set
                if (stage == CinemachineCore.Stage.Aim)
                {
                    extra = GetExtraState(vcam);
                    extra.targetObscured = CheckForTargetObstructions(state);

                    // GML these values are an initial arbitrary attempt at rating quality
                    if (extra.targetObscured)
                    {
                        state.ShotQuality *= 0.2f;
                    }
                    if (extra.colliderDisplacementDecay > 0)
                    {
                        state.ShotQuality *= 0.8f;
                    }

                    float       nearnessBoost = 0;
                    const float kMaxNearBoost = 0.2f;
                    if (m_OptimalTargetDistance > 0 && state.HasLookAt)
                    {
                        float distance = Vector3.Magnitude(state.ReferenceLookAt - state.FinalPosition);
                        if (distance <= m_OptimalTargetDistance)
                        {
                            float threshold = m_OptimalTargetDistance / 2;
                            if (distance >= threshold)
                            {
                                nearnessBoost = kMaxNearBoost * (distance - threshold)
                                                / (m_OptimalTargetDistance - threshold);
                            }
                        }
                        else
                        {
                            distance -= m_OptimalTargetDistance;
                            float threshold = m_OptimalTargetDistance * 3;
                            if (distance < threshold)
                            {
                                nearnessBoost = kMaxNearBoost * (1f - (distance / threshold));
                            }
                        }
                        state.ShotQuality *= (1f + nearnessBoost);
                    }
                }
            }
        }
Exemplo n.º 17
0
        private Vector3 PushCameraBack(
            Vector3 currentPos, Vector3 pushDir, RaycastHit obstacle,
            Vector3 lookAtPos, Plane startPlane, float targetDistance, int iterations,
            ref VcamExtraState extra)
        {
            // Take a step along the wall.
            Vector3 pos = currentPos;
            Vector3 dir = Vector3.zero;

            if (!GetWalkingDirection(pos, pushDir, obstacle, ref dir))
            {
                return(pos);
            }

            Ray   ray      = new Ray(pos, dir);
            float distance = GetPushBackDistance(ray, startPlane, targetDistance, lookAtPos);

            if (distance <= Epsilon)
            {
                return(pos);
            }

            // Check only as far as the obstacle bounds
            float clampedDistance = ClampRayToBounds(ray, distance, obstacle.collider.bounds);

            distance = Mathf.Min(distance, clampedDistance + PrecisionSlush);

            RaycastHit hitInfo;

            if (RaycastIgnoreTag(ray, out hitInfo, distance,
                                 m_CollideAgainst & ~m_TransparentLayers))
            {
                // We hit something.  Stop there and take a step along that wall.
                float adjustment = hitInfo.distance - PrecisionSlush;
                pos = ray.GetPoint(adjustment);
                extra.AddPointToDebugPath(pos);
                if (iterations > 1)
                {
                    pos = PushCameraBack(
                        pos, dir, hitInfo,
                        lookAtPos, startPlane,
                        targetDistance, iterations - 1, ref extra);
                }

                return(pos);
            }

            // Didn't hit anything.  Can we push back all the way now?
            pos = ray.GetPoint(distance);

            // First check if we can still see the target.  If not, abort
            dir = pos - lookAtPos;
            float d = dir.magnitude;

            //if (m_MinDistanceNearTarget != 0  && distance != 0 && d < m_MinDistanceNearTarget)
            //{
            //    Vector3 hitToTarget = lookAtPos - currentPos;
            //    float hd = hitToTarget.magnitude;
            //    Vector3 planeDir = Vector3.ProjectOnPlane(hitToTarget, obstacle.normal);
            //    float pd = planeDir.magnitude;
            //    distance = Mathf.Sqrt(m_MinimumDistanceFromTarget * m_MinimumDistanceFromTarget - (hd * hd - pd * pd)) - pd;
            //    pos = ray.GetPoint(distance);
            //    dir = pos - lookAtPos;
            //    d = dir.magnitude;
            //}

            RaycastHit hitInfo2;

            if (d < Epsilon || RaycastIgnoreTag(
                    new Ray(lookAtPos, dir), out hitInfo2, d - PrecisionSlush,
                    m_CollideAgainst & ~m_TransparentLayers))
            {
                return(currentPos);
            }

            // All clear
            ray = new Ray(pos, dir);
            extra.AddPointToDebugPath(pos);
            distance = GetPushBackDistance(ray, startPlane, targetDistance, lookAtPos);
            if (distance > Epsilon)
            {
                if (!RaycastIgnoreTag(ray, out hitInfo, distance,
                                      m_CollideAgainst & ~m_TransparentLayers))
                {
                    pos = ray.GetPoint(distance); // no obstacles - all good
                    extra.AddPointToDebugPath(pos);
                }
                else
                {
                    // We hit something.  Stop there and maybe take a step along that wall
                    float adjustment = hitInfo.distance - PrecisionSlush;
                    pos = ray.GetPoint(adjustment);
                    extra.AddPointToDebugPath(pos);
                    if (iterations > 1)
                    {
                        pos = PushCameraBack(
                            pos, dir, hitInfo, lookAtPos, startPlane,
                            targetDistance, iterations - 1, ref extra);
                    }
                }
            }
            return(pos);
        }
        /// <summary>Callcack to to the collision resolution and shot evaluation</summary>
        protected override void PostPipelineStageCallback(
            CinemachineVirtualCameraBase vcam,
            CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
        {
            VcamExtraState extra = null;

            if (stage == CinemachineCore.Stage.Body)
            {
                extra = GetExtraState <VcamExtraState>(vcam);
                extra.targetObscured       = false;
                extra.colliderDisplacement = 0;
                extra.debugResolutionPath  = null;
            }

            // Move the body before the Aim is calculated
            if (stage == CinemachineCore.Stage.Body)
            {
                if (m_AvoidObstacles)
                {
                    var displacement = PreserveLignOfSight(ref state, ref extra);
                    if (m_Damping > 0 && deltaTime >= 0)
                    {
                        var delta = displacement - extra.m_previousDisplacement;
                        delta        = Damper.Damp(delta, m_Damping, deltaTime);
                        displacement = extra.m_previousDisplacement + delta;
                    }

                    extra.m_previousDisplacement = displacement;
                    state.PositionCorrection    += displacement;
                    extra.colliderDisplacement  += displacement.magnitude;
                }
            }

            // Rate the shot after the aim was set
            if (stage == CinemachineCore.Stage.Aim)
            {
                extra = GetExtraState <VcamExtraState>(vcam);
                extra.targetObscured = CheckForTargetObstructions(state);

                // GML these values are an initial arbitrary attempt at rating quality
                if (extra.targetObscured)
                {
                    state.ShotQuality *= 0.2f;
                }
                if (extra.colliderDisplacement > 0)
                {
                    state.ShotQuality *= 0.8f;
                }

                float       nearnessBoost = 0;
                const float kMaxNearBoost = 0.2f;
                if (m_OptimalTargetDistance > 0 && state.HasLookAt)
                {
                    var distance = Vector3.Magnitude(state.ReferenceLookAt - state.FinalPosition);
                    if (distance <= m_OptimalTargetDistance)
                    {
                        var threshold = m_OptimalTargetDistance / 2;
                        if (distance >= threshold)
                        {
                            nearnessBoost = kMaxNearBoost * (distance - threshold)
                                            / (m_OptimalTargetDistance - threshold);
                        }
                    }
                    else
                    {
                        distance -= m_OptimalTargetDistance;
                        var threshold = m_OptimalTargetDistance * 3;
                        if (distance < threshold)
                        {
                            nearnessBoost = kMaxNearBoost * (1f - distance / threshold);
                        }
                    }

                    state.ShotQuality *= 1f + nearnessBoost;
                }
            }
        }
Exemplo n.º 19
0
 private Vector3 ApplySmoothingLookAt(CinemachineVirtualCameraBase vcam, Vector3 pos, VcamExtraState extra)
 {
     if (extra.mSmoothingFilterLookAt == null || extra.mSmoothingFilterLookAt.Sigma != m_LookAtSmoothing)
     {
         extra.mSmoothingFilterLookAt = new GaussianWindow1D_Vector3(m_LookAtSmoothing);
     }
     return(extra.mSmoothingFilterLookAt.Filter(pos));
 }
Exemplo n.º 20
0
        private Quaternion ApplySmoothing(CinemachineVirtualCameraBase vcam, Quaternion rot, Vector3 up, VcamExtraState extra)
        {
            if (extra.mSmoothingFilterRotation == null || extra.mSmoothingFilterRotation.Sigma != m_RotationSmoothing)
            {
                extra.mSmoothingFilterRotation = new GaussianWindow1D_CameraRotation(m_RotationSmoothing);
            }
            Vector3 camRot = Quaternion.identity.GetCameraRotationToTarget(rot * Vector3.forward, up);

            return(Quaternion.identity.ApplyCameraRotation(extra.mSmoothingFilterRotation.Filter(camRot), up));
        }
        private Vector3 PushCameraBack(
            Vector3 currentPos, Vector3 pushDir, RaycastHit obstacle,
            Vector3 lookAtPos, Plane startPlane, float targetDistance, int iterations,
            ref VcamExtraState extra)
        {
            // Take a step along the wall.
            Vector3 pos = currentPos;
            Vector3 dir = Vector3.zero;

            if (!GetWalkingDirection(pos, pushDir, obstacle, ref dir))
            {
                return(pos);
            }

            Ray   ray      = new Ray(pos, dir);
            float distance = GetPushBackDistance(ray, startPlane, targetDistance, lookAtPos);

            if (distance <= Epsilon)
            {
                return(pos);
            }

            // Check only as far as the obstacle bounds
            float clampedDistance = ClampRayToBounds(ray, distance, obstacle.collider.bounds);

            distance = Mathf.Min(distance, clampedDistance + PrecisionSlush);

            RaycastHit hitInfo;

            if (Physics.Raycast(ray, out hitInfo, distance, m_CollideAgainst.value))
            {
                // We hit something.  Stop there and take a step along that wall.
                float adjustment = hitInfo.distance - PrecisionSlush;
                pos = ray.GetPoint(adjustment);
                extra.AddPointToDebugPath(pos);
                if (iterations > 1)
                {
                    pos = PushCameraBack(
                        pos, dir, hitInfo,
                        lookAtPos, startPlane,
                        targetDistance, iterations - 1, ref extra);
                }

                return(pos);
            }

            // Didn't hit anything.  Can we push back all the way now?
            pos = ray.GetPoint(distance);

            // First check if we can still see the target.  If not, abort
            dir = lookAtPos - pos;
            float      d = dir.magnitude - m_MinimumDistanceFromTarget;
            RaycastHit hitInfo2;

            if (d < Epsilon || Physics.Raycast(
                    new Ray(pos, dir), out hitInfo2, d, m_CollideAgainst.value,
                    QueryTriggerInteraction.Ignore))
            {
                return(currentPos);
            }

            // All clear
            extra.AddPointToDebugPath(pos);
            dir      = pos - lookAtPos;
            ray      = new Ray(pos, dir);
            distance = GetPushBackDistance(ray, startPlane, targetDistance, lookAtPos);
            if (distance > Epsilon)
            {
                if (!Physics.Raycast(
                        ray, out hitInfo, distance, m_CollideAgainst.value,
                        QueryTriggerInteraction.Ignore))
                {
                    pos = ray.GetPoint(distance); // no obstacles - all good
                    extra.AddPointToDebugPath(pos);
                }
                else
                {
                    // We hit something.  Stop there and maybe take a step along that wall
                    float adjustment = hitInfo.distance - PrecisionSlush;
                    pos = ray.GetPoint(adjustment);
                    extra.AddPointToDebugPath(pos);
                    if (iterations > 1)
                    {
                        pos = PushCameraBack(
                            pos, dir, hitInfo, lookAtPos, startPlane,
                            targetDistance, iterations - 1, ref extra);
                    }
                }
            }
            return(pos);
        }