예제 #1
0
        /// <summary>
        /// Adjust the rigOrientation to put the camera within the screen bounds.
        /// If deltaTime >= 0 then damping will be applied.
        /// Assumes that currentOrientation fwd is such that input rigOrientation's
        /// local up is NEVER NEVER NEVER pointing downwards, relative to
        /// state.ReferenceUp.  If this condition is violated
        /// then you will see crazy spinning.  That's the symptom.
        /// </summary>
        private bool RotateToScreenBounds(
            ref CameraState state, Rect screenRect,
            ref Quaternion rigOrientation, float fov, float fovH, float deltaTime)
        {
            Vector3 targetDir = TrackedPoint - state.CorrectedPosition;
            Vector2 rotToRect = rigOrientation.GetCameraRotationToTarget(targetDir, state.ReferenceUp);

            // Bring it to the edge of screenRect, if outside.  Leave it alone if inside.
            ClampVerticalBounds(ref screenRect, targetDir, state.ReferenceUp, fov);
            float min = (screenRect.yMin - 0.5f) * fov;
            float max = (screenRect.yMax - 0.5f) * fov;

            if (rotToRect.x < min)
            {
                rotToRect.x -= min;
            }
            else if (rotToRect.x > max)
            {
                rotToRect.x -= max;
            }
            else
            {
                rotToRect.x = 0;
            }

            min = (screenRect.xMin - 0.5f) * fovH;
            max = (screenRect.xMax - 0.5f) * fovH;
            if (rotToRect.y < min)
            {
                rotToRect.y -= min;
            }
            else if (rotToRect.y > max)
            {
                rotToRect.y -= max;
            }
            else
            {
                rotToRect.y = 0;
            }

            // Apply damping
            if (deltaTime >= 0)
            {
                rotToRect.x = Damper.Damp(rotToRect.x, m_VerticalDamping, deltaTime);
                rotToRect.y = Damper.Damp(rotToRect.y, m_HorizontalDamping, deltaTime);
            }

            // Rotate
            rigOrientation = rigOrientation.ApplyCameraRotation(rotToRect, state.ReferenceUp);
#if false
            // GML this gives false positives when the camera is moving.
            // The way to address this would be to grow the hard rect by the amount
            // that it would be damped
            return(Mathf.Abs(rotToRect.x) > Epsilon || Mathf.Abs(rotToRect.y) > Epsilon);
#else
            return(false);
#endif
        }
예제 #2
0
        /// <summary>
        /// Adjust the rigOrientation to put the camera within the screen bounds.
        /// If deltaTime >= 0 then damping will be applied.
        /// Assumes that currentOrientation fwd is such that input rigOrientation's
        /// local up is NEVER NEVER NEVER pointing downwards, relative to
        /// state.ReferenceUp.  If this condition is violated
        /// then you will see crazy spinning.  That's the symptom.
        /// </summary>
        private Quaternion RotateToScreenBounds(
            ref CameraState state, Rect screenRect,
            Quaternion rigOrientation, float fov, float fovH, float deltaTime)
        {
            Vector3 targetDir = state.ReferenceLookAt - state.CorrectedPosition;
            Vector2 rotToRect = rigOrientation.GetCameraRotationToTarget(targetDir, state.ReferenceUp);

            // Bring it to the edge of screenRect, if outside.  Leave it alone if inside.
            ClampVerticalBounds(ref screenRect, targetDir, state.ReferenceUp, fov);
            float min = (screenRect.yMin - 0.5f) * fov;
            float max = (screenRect.yMax - 0.5f) * fov;

            if (rotToRect.x < min)
            {
                rotToRect.x -= min;
            }
            else if (rotToRect.x > max)
            {
                rotToRect.x -= max;
            }
            else
            {
                rotToRect.x = 0;
            }

            min = (screenRect.xMin - 0.5f) * fovH;
            max = (screenRect.xMax - 0.5f) * fovH;
            if (rotToRect.y < min)
            {
                rotToRect.y -= min;
            }
            else if (rotToRect.y > max)
            {
                rotToRect.y -= max;
            }
            else
            {
                rotToRect.y = 0;
            }

            // Apply damping
            if (deltaTime > 0)
            {
                if (Mathf.Abs(rotToRect.x) > UnityVectorExtensions.Epsilon)
                {
                    rotToRect.x *= deltaTime / Mathf.Max(m_VerticalDamping * kDampingScale, deltaTime);
                }
                if (Mathf.Abs(rotToRect.y) > UnityVectorExtensions.Epsilon)
                {
                    rotToRect.y *= deltaTime / Mathf.Max(m_HorizontalDamping * kDampingScale, deltaTime);
                }
            }

            // Rotate
            return(rigOrientation.ApplyCameraRotation(rotToRect, state.ReferenceUp));
        }
예제 #3
0
        /// <summary>
        /// Adjust the rigOrientation to put the camera within the screen bounds.
        /// If deltaTime >= 0 then damping will be applied.
        /// Assumes that currentOrientation fwd is such that input rigOrientation's
        /// local up is NEVER NEVER NEVER pointing downwards, relative to
        /// state.ReferenceUp.  If this condition is violated
        /// then you will see crazy spinning.  That's the symptom.
        /// </summary>
        private void RotateToScreenBounds(
            ref CameraState state, Rect screenRect, Vector3 trackedPoint,
            ref Quaternion rigOrientation, float fov, float fovH, float deltaTime)
        {
            Vector3 targetDir = trackedPoint - state.CorrectedPosition;
            Vector2 rotToRect = rigOrientation.GetCameraRotationToTarget(targetDir, state.ReferenceUp);

            // Bring it to the edge of screenRect, if outside.  Leave it alone if inside.
            ClampVerticalBounds(ref screenRect, targetDir, state.ReferenceUp, fov);
            float min = (screenRect.yMin - 0.5f) * fov;
            float max = (screenRect.yMax - 0.5f) * fov;

            if (rotToRect.x < min)
            {
                rotToRect.x -= min;
            }
            else if (rotToRect.x > max)
            {
                rotToRect.x -= max;
            }
            else
            {
                rotToRect.x = 0;
            }

            min = (screenRect.xMin - 0.5f) * fovH;
            max = (screenRect.xMax - 0.5f) * fovH;
            if (rotToRect.y < min)
            {
                rotToRect.y -= min;
            }
            else if (rotToRect.y > max)
            {
                rotToRect.y -= max;
            }
            else
            {
                rotToRect.y = 0;
            }

            // Apply damping
            if (deltaTime >= 0 && VirtualCamera.PreviousStateIsValid)
            {
                rotToRect.x = VirtualCamera.DetachedLookAtTargetDamp(
                    rotToRect.x, m_VerticalDamping, deltaTime);
                rotToRect.y = VirtualCamera.DetachedLookAtTargetDamp(
                    rotToRect.y, m_HorizontalDamping, deltaTime);
            }

            // Rotate
            rigOrientation = rigOrientation.ApplyCameraRotation(rotToRect, state.ReferenceUp);
        }
예제 #4
0
        /// <summary>
        /// Adjust the rigOrientation to put the camera within the screen bounds.
        /// If deltaTime >= 0 then damping will be applied.
        /// Assumes that currentOrientation fwd is such that input rigOrientation's
        /// local up is NEVER NEVER NEVER pointing downwards, relative to
        /// state.ReferenceUp.  If this condition is violated
        /// then you will see crazy spinning.  That's the symptom.
        /// </summary>
        private Quaternion PlaceWithinScreenBounds(
            ref CameraState state, Rect screenRect,
            Quaternion rigOrientation, float fovH, float deltaTime)
        {
            Vector3 targetDir = state.ReferenceLookAt - state.CorrectedPosition;
            Vector2 rotToRect = rigOrientation.GetCameraRotationToTarget(targetDir, state.ReferenceUp);

            // Bring it to the edge of screenRect, if outside.  Leave it alone if inside.
            ClampVerticalBounds(ref screenRect, targetDir, state.ReferenceUp, state.Lens.FieldOfView);
            float min = (screenRect.yMin - 0.5f) * state.Lens.FieldOfView;
            float max = (screenRect.yMax - 0.5f) * state.Lens.FieldOfView;

            if (rotToRect.x < min)
            {
                rotToRect.x -= min;
            }
            else if (rotToRect.x > max)
            {
                rotToRect.x -= max;
            }
            else
            {
                rotToRect.x = 0;
            }

            min = (screenRect.xMin - 0.5f) * fovH;
            max = (screenRect.xMax - 0.5f) * fovH;
            if (rotToRect.y < min)
            {
                rotToRect.y -= min;
            }
            else if (rotToRect.y > max)
            {
                rotToRect.y -= max;
            }
            else
            {
                rotToRect.y = 0;
            }

            // Apply damping
            if (deltaTime > 0)
            {
                rotToRect.x *= deltaTime / Mathf.Max(VerticalSoftTrackingSpeed, deltaTime);
                rotToRect.y *= deltaTime / Mathf.Max(HorizontalSoftTrackingSpeed, deltaTime);
            }

            // Rotate
            return(rigOrientation.ApplyCameraRotation(rotToRect, state.ReferenceUp));
        }
예제 #5
0
        private bool RotateToScreenBounds(ref CameraState state, Rect screenRect, ref Quaternion rigOrientation, float fov, float fovH, float deltaTime)
        {
            Vector3 vector = this.TrackedPoint - state.CorrectedPosition;
            Vector2 cameraRotationToTarget = rigOrientation.GetCameraRotationToTarget(vector, state.ReferenceUp);

            this.ClampVerticalBounds(ref screenRect, vector, state.ReferenceUp, fov);
            float num  = (screenRect.yMin - 0.5f) * fov;
            float num2 = (screenRect.yMax - 0.5f) * fov;

            if (cameraRotationToTarget.x < num)
            {
                cameraRotationToTarget.x -= num;
            }
            else if (cameraRotationToTarget.x > num2)
            {
                cameraRotationToTarget.x -= num2;
            }
            else
            {
                cameraRotationToTarget.x = 0f;
            }
            num  = (screenRect.xMin - 0.5f) * fovH;
            num2 = (screenRect.xMax - 0.5f) * fovH;
            if (cameraRotationToTarget.y < num)
            {
                cameraRotationToTarget.y -= num;
            }
            else if (cameraRotationToTarget.y > num2)
            {
                cameraRotationToTarget.y -= num2;
            }
            else
            {
                cameraRotationToTarget.y = 0f;
            }
            if (deltaTime >= 0f)
            {
                cameraRotationToTarget.x = Damper.Damp(cameraRotationToTarget.x, this.m_VerticalDamping, deltaTime);
                cameraRotationToTarget.y = Damper.Damp(cameraRotationToTarget.y, this.m_HorizontalDamping, deltaTime);
            }
            rigOrientation = rigOrientation.ApplyCameraRotation(cameraRotationToTarget, state.ReferenceUp);
            return(false);
        }
예제 #6
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);
        }
예제 #7
0
        /// <summary>Applies the composer rules and orients the camera accordingly</summary>
        /// <param name="curState">The current camera state</param>
        /// <param name="deltaTime">Used for calculating damping.  If less than
        /// zero, then target will snap to the center of the dead zone.</param>
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            if (!IsValid || !curState.HasLookAt)
            {
                return;
            }

            // Correct the tracked point in the event that it's behind the camera
            // while the real target is in front
            if (!(TrackedPoint - curState.ReferenceLookAt).AlmostZero())
            {
                Vector3 mid       = Vector3.Lerp(curState.CorrectedPosition, curState.ReferenceLookAt, 0.5f);
                Vector3 toLookAt  = curState.ReferenceLookAt - mid;
                Vector3 toTracked = TrackedPoint - mid;
                if (Vector3.Dot(toLookAt, toTracked) < 0)
                {
                    float t = Vector3.Distance(curState.ReferenceLookAt, mid)
                              / Vector3.Distance(curState.ReferenceLookAt, TrackedPoint);
                    TrackedPoint = Vector3.Lerp(curState.ReferenceLookAt, TrackedPoint, t);
                }
            }

            float targetDistance = (TrackedPoint - curState.CorrectedPosition).magnitude;

            if (targetDistance < Epsilon)
            {
                if (deltaTime >= 0 && VirtualCamera.PreviousStateIsValid)
                {
                    curState.RawOrientation = m_CameraOrientationPrevFrame;
                }
                return;  // navel-gazing, get outa here
            }

            // Expensive FOV calculations
            mCache.UpdateCache(curState.Lens, SoftGuideRect, HardGuideRect, targetDistance);

            Quaternion rigOrientation = curState.RawOrientation;

            if (deltaTime < 0 || !VirtualCamera.PreviousStateIsValid)
            {
                // No damping, just snap to central bounds, skipping the soft zone
                rigOrientation = Quaternion.LookRotation(
                    rigOrientation * Vector3.forward, curState.ReferenceUp);
                Rect rect = mCache.mFovSoftGuideRect;
                if (m_CenterOnActivate)
                {
                    rect = new Rect(rect.center, Vector2.zero); // Force to center
                }
                RotateToScreenBounds(
                    ref curState, rect, curState.ReferenceLookAt,
                    ref rigOrientation, mCache.mFov, mCache.mFovH, -1);
            }
            else
            {
                // Start with previous frame's orientation (but with current up)
                Vector3 dir = m_LookAtPrevFrame - m_CameraPosPrevFrame;
                if (dir.AlmostZero())
                {
                    rigOrientation = Quaternion.LookRotation(
                        m_CameraOrientationPrevFrame * Vector3.forward, curState.ReferenceUp);
                }
                else
                {
                    dir            = Quaternion.Euler(curState.PositionDampingBypass) * dir;
                    rigOrientation = Quaternion.LookRotation(dir, curState.ReferenceUp);
                    rigOrientation = rigOrientation.ApplyCameraRotation(
                        -m_ScreenOffsetPrevFrame, curState.ReferenceUp);
                }

                // Move target through the soft zone, with damping
                RotateToScreenBounds(
                    ref curState, mCache.mFovSoftGuideRect, TrackedPoint,
                    ref rigOrientation, mCache.mFov, mCache.mFovH, deltaTime);

                // Force the actual target (not the lookahead one) into the hard bounds, no damping
                if (deltaTime < 0 || VirtualCamera.LookAtTargetAttachment > 1 - Epsilon)
                {
                    RotateToScreenBounds(
                        ref curState, mCache.mFovHardGuideRect, curState.ReferenceLookAt,
                        ref rigOrientation, mCache.mFov, mCache.mFovH, -1);
                }
            }

            m_CameraPosPrevFrame         = curState.CorrectedPosition;
            m_LookAtPrevFrame            = TrackedPoint;
            m_CameraOrientationPrevFrame = UnityQuaternionExtensions.Normalized(rigOrientation);
            m_ScreenOffsetPrevFrame      = m_CameraOrientationPrevFrame.GetCameraRotationToTarget(
                m_LookAtPrevFrame - curState.CorrectedPosition, curState.ReferenceUp);

            curState.RawOrientation = m_CameraOrientationPrevFrame;
        }
예제 #8
0
        /// <summary>Applies the composer rules and orients the camera accordingly</summary>
        /// <param name="curState">The current camera state</param>
        /// <param name="deltaTime">Used for calculating damping.  If less than
        /// zero, then target will snap to the center of the dead zone.</param>
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            // Initialize the state for previous frame if appropriate
            if (deltaTime < 0)
            {
                m_Predictor.Reset();
            }

            if (!IsValid || !curState.HasLookAt)
            {
                return;
            }

            float targetDistance = (TrackedPoint - curState.CorrectedPosition).magnitude;

            if (targetDistance < Epsilon)
            {
                if (deltaTime >= 0)
                {
                    curState.RawOrientation = m_CameraOrientationPrevFrame;
                }
                return;  // navel-gazing, get outa here
            }

            float fov, fovH;

            if (curState.Lens.Orthographic)
            {
                // Calculate effective fov - fake it for ortho based on target distance
                fov  = Mathf.Rad2Deg * 2 * Mathf.Atan(curState.Lens.OrthographicSize / targetDistance);
                fovH = Mathf.Rad2Deg * 2 * Mathf.Atan(
                    curState.Lens.Aspect * curState.Lens.OrthographicSize / targetDistance);
            }
            else
            {
                fov = curState.Lens.FieldOfView;
                double radHFOV = 2 * Math.Atan(Math.Tan(fov * Mathf.Deg2Rad / 2) * curState.Lens.Aspect);
                fovH = (float)(Mathf.Rad2Deg * radHFOV);
            }

            Quaternion rigOrientation = curState.RawOrientation;
            Rect       softGuideFOV   = ScreenToFOV(SoftGuideRect, fov, fovH, curState.Lens.Aspect);

            if (deltaTime < 0)
            {
                // No damping, just snap to central bounds, skipping the soft zone
                Rect rect = new Rect(softGuideFOV.center, Vector2.zero); // Force to center
                RotateToScreenBounds(ref curState, rect, ref rigOrientation, fov, fovH, -1);
            }
            else
            {
                // Start with previous frame's orientation (but with current up)
                Vector3 dir = m_LookAtPrevFrame - (m_CameraPosPrevFrame + curState.PositionDampingBypass);
                if (dir.AlmostZero())
                {
                    rigOrientation = Quaternion.LookRotation(
                        m_CameraOrientationPrevFrame * Vector3.forward, curState.ReferenceUp);
                }
                else
                {
                    rigOrientation = Quaternion.LookRotation(dir, curState.ReferenceUp);
                    rigOrientation = rigOrientation.ApplyCameraRotation(
                        -m_ScreenOffsetPrevFrame, curState.ReferenceUp);
                }

                // First force the previous rotation into the hard bounds, no damping,
                // then Now move it through the soft zone, with damping
                Rect hardGuideFOV = ScreenToFOV(HardGuideRect, fov, fovH, curState.Lens.Aspect);
                if (!RotateToScreenBounds(ref curState, hardGuideFOV, ref rigOrientation, fov, fovH, -1))
                {
                    RotateToScreenBounds(ref curState, softGuideFOV, ref rigOrientation, fov, fovH, deltaTime);
                }
            }
            m_CameraPosPrevFrame         = curState.CorrectedPosition;
            m_LookAtPrevFrame            = TrackedPoint;
            m_CameraOrientationPrevFrame = UnityQuaternionExtensions.Normalized(rigOrientation);
            m_ScreenOffsetPrevFrame      = m_CameraOrientationPrevFrame.GetCameraRotationToTarget(
                m_LookAtPrevFrame - curState.CorrectedPosition, curState.ReferenceUp);

            curState.RawOrientation = m_CameraOrientationPrevFrame;
        }
예제 #9
0
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            if (deltaTime < 0f)
            {
                this.m_Predictor.Reset();
            }
            if (!this.IsValid || !curState.HasLookAt)
            {
                return;
            }
            float magnitude = (this.TrackedPoint - curState.CorrectedPosition).magnitude;

            if (magnitude < 0.0001f)
            {
                if (deltaTime >= 0f)
                {
                    curState.RawOrientation = this.m_CameraOrientationPrevFrame;
                }
                return;
            }
            float num;
            float fovH;

            if (curState.Lens.Orthographic)
            {
                num  = 114.59156f * Mathf.Atan(curState.Lens.OrthographicSize / magnitude);
                fovH = 114.59156f * Mathf.Atan(curState.Lens.Aspect * curState.Lens.OrthographicSize / magnitude);
            }
            else
            {
                num = curState.Lens.FieldOfView;
                double num2 = 2.0 * Math.Atan(Math.Tan((double)(num * 0.0174532924f / 2f)) * (double)curState.Lens.Aspect);
                fovH = (float)(57.295780181884766 * num2);
            }
            Quaternion quaternion = curState.RawOrientation;
            Rect       screenRect = this.ScreenToFOV(this.SoftGuideRect, num, fovH, curState.Lens.Aspect);

            if (deltaTime < 0f)
            {
                Rect screenRect2 = new Rect(screenRect.center, Vector2.zero);
                this.RotateToScreenBounds(ref curState, screenRect2, ref quaternion, num, fovH, -1f);
            }
            else
            {
                Vector3 vector = this.m_LookAtPrevFrame - (this.m_CameraPosPrevFrame + curState.PositionDampingBypass);
                if (vector.AlmostZero())
                {
                    quaternion = Quaternion.LookRotation(this.m_CameraOrientationPrevFrame * Vector3.forward, curState.ReferenceUp);
                }
                else
                {
                    quaternion = Quaternion.LookRotation(vector, curState.ReferenceUp);
                    quaternion = quaternion.ApplyCameraRotation(-this.m_ScreenOffsetPrevFrame, curState.ReferenceUp);
                }
                Rect screenRect3 = this.ScreenToFOV(this.HardGuideRect, num, fovH, curState.Lens.Aspect);
                if (!this.RotateToScreenBounds(ref curState, screenRect3, ref quaternion, num, fovH, -1f))
                {
                    this.RotateToScreenBounds(ref curState, screenRect, ref quaternion, num, fovH, deltaTime);
                }
            }
            this.m_CameraPosPrevFrame         = curState.CorrectedPosition;
            this.m_LookAtPrevFrame            = this.TrackedPoint;
            this.m_CameraOrientationPrevFrame = quaternion.Normalized();
            this.m_ScreenOffsetPrevFrame      = this.m_CameraOrientationPrevFrame.GetCameraRotationToTarget(this.m_LookAtPrevFrame - curState.CorrectedPosition, curState.ReferenceUp);
            curState.RawOrientation           = this.m_CameraOrientationPrevFrame;
        }
예제 #10
0
        /// <summary>Applies the composer rules and orients the camera accordingly</summary>
        /// <param name="curState">The current camera state</param>
        /// <param name="deltaTime">Used for calculating damping.  If less than
        /// zero, then target will snap to the center of the dead zone.</param>
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            // Initialize the state for previous frame if appropriate
            if (deltaTime < 0)
            {
                m_Predictor.Reset();
            }

            if (!IsValid || !curState.HasLookAt)
            {
                return;
            }

            float targetDistance = (TrackedPoint - curState.CorrectedPosition).magnitude;

            if (targetDistance < Epsilon)
            {
                if (deltaTime >= 0)
                {
                    curState.RawOrientation = m_CameraOrientationPrevFrame;
                }
                return;  // navel-gazing, get outa here
            }

            // Expensive FOV calculations
            mCache.UpdateCache(curState.Lens, SoftGuideRect, HardGuideRect, targetDistance);

            Quaternion rigOrientation = curState.RawOrientation;

            if (deltaTime < 0)
            {
                // No damping, just snap to central bounds, skipping the soft zone
                Rect rect = mCache.mFovSoftGuideRect;
                if (m_CenterOnActivate)
                {
                    rect = new Rect(rect.center, Vector2.zero); // Force to center
                }
                RotateToScreenBounds(ref curState, rect, ref rigOrientation, mCache.mFov, mCache.mFovH, -1);
            }
            else
            {
                // Start with previous frame's orientation (but with current up)
                Vector3 dir = m_LookAtPrevFrame - (m_CameraPosPrevFrame + curState.PositionDampingBypass);
                if (dir.AlmostZero())
                {
                    rigOrientation = Quaternion.LookRotation(
                        m_CameraOrientationPrevFrame * Vector3.forward, curState.ReferenceUp);
                }
                else
                {
                    rigOrientation = Quaternion.LookRotation(dir, curState.ReferenceUp);
                    rigOrientation = rigOrientation.ApplyCameraRotation(
                        -m_ScreenOffsetPrevFrame, curState.ReferenceUp);
                }

                // First force the previous rotation into the hard bounds, no damping,
                // then Now move it through the soft zone, with damping
                if (!RotateToScreenBounds(ref curState, mCache.mFovHardGuideRect, ref rigOrientation, mCache.mFov, mCache.mFovH, -1))
                {
                    RotateToScreenBounds(ref curState, mCache.mFovSoftGuideRect, ref rigOrientation, mCache.mFov, mCache.mFovH, deltaTime);
                }
            }
            m_CameraPosPrevFrame         = curState.CorrectedPosition;
            m_LookAtPrevFrame            = TrackedPoint;
            m_CameraOrientationPrevFrame = UnityQuaternionExtensions.Normalized(rigOrientation);
            m_ScreenOffsetPrevFrame      = m_CameraOrientationPrevFrame.GetCameraRotationToTarget(
                m_LookAtPrevFrame - curState.CorrectedPosition, curState.ReferenceUp);

            curState.RawOrientation = m_CameraOrientationPrevFrame;
        }