Example #1
0
        float AdjustCameraDepthAndLensForGroupFraming(
            CinemachineTargetGroup group, float targetZ,
            ref CameraState curState, float deltaTime)
        {
            float cameraOffset = 0;

            // Get the bounding box from that POV in view space, and find its height
            Bounds  bounds = group.BoundingBox;
            Vector3 fwd    = curState.RawOrientation * Vector3.forward;

            m_lastBoundsMatrix = Matrix4x4.TRS(
                bounds.center - (fwd * bounds.extents.magnitude),
                curState.RawOrientation, Vector3.one);
            m_LastBounds = group.GetViewSpaceBoundingBox(m_lastBoundsMatrix);
            float targetHeight = GetTargetHeight(m_LastBounds);

            // Apply damping
            if (deltaTime >= 0)
            {
                float delta = targetHeight - m_prevTargetHeight;
                delta        = Damper.Damp(delta, m_ZDamping, deltaTime);
                targetHeight = m_prevTargetHeight + delta;
            }
            m_prevTargetHeight = targetHeight;

            // Move the camera
            if (!curState.Lens.Orthographic && m_AdjustmentMode != AdjustmentMode.ZoomOnly)
            {
                // What distance would be needed to get the target height, at the current FOV
                float desiredDistance
                    = targetHeight / (2f * Mathf.Tan(curState.Lens.FieldOfView * Mathf.Deg2Rad / 2f));

                // target the near surface of the bounding box
                desiredDistance += m_LastBounds.extents.z;

                // Clamp to respect min/max distance settings
                desiredDistance = Mathf.Clamp(
                    desiredDistance, targetZ - m_MaxDollyIn, targetZ + m_MaxDollyOut);
                desiredDistance = Mathf.Clamp(desiredDistance, m_MinimumDistance, m_MaximumDistance);

                // Apply
                cameraOffset += desiredDistance - targetZ;
            }

            // Apply zoom
            if (curState.Lens.Orthographic || m_AdjustmentMode != AdjustmentMode.DollyOnly)
            {
                float nearBoundsDistance = (targetZ + cameraOffset) - m_LastBounds.extents.z;
                float currentFOV         = 179;
                if (nearBoundsDistance > Epsilon)
                {
                    currentFOV = 2f * Mathf.Atan(targetHeight / (2 * nearBoundsDistance)) * Mathf.Rad2Deg;
                }

                LensSettings lens = curState.Lens;
                lens.FieldOfView      = Mathf.Clamp(currentFOV, m_MinimumFOV, m_MaximumFOV);
                lens.OrthographicSize = Mathf.Clamp(targetHeight / 2, m_MinimumOrthoSize, m_MaximumOrthoSize);
                curState.Lens         = lens;
            }
            return(-cameraOffset);
        }
        /// <summary>Applies the composer rules and orients the camera accordingly</summary>
        /// <param name="state">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)
        {
            // Can't do anything without a group to look at
            CinemachineTargetGroup group = TargetGroup;

            if (group == null)
            {
                base.MutateCameraState(ref curState, deltaTime);
                return;
            }

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

            curState.ReferenceLookAt = GetLookAtPointAndSetTrackedPoint(group.transform.position);
            Vector3 currentOffset   = TrackedPoint - curState.RawPosition;
            float   currentDistance = currentOffset.magnitude;

            if (currentDistance < Epsilon)
            {
                return;  // navel-gazing, get outa here
            }
            //UnityEngine.Profiling.Profiler.BeginSample("CinemachineGroupComposer.MutateCameraState");

            // Get the camera axis
            Vector3 fwd = currentOffset.AlmostZero() ? Vector3.forward : currentOffset.normalized;

            // Get the bounding box from that POV in view space, and find its width
            Bounds bounds = group.BoundingBox;

            m_lastBoundsMatrix = Matrix4x4.TRS(
                bounds.center - (fwd * bounds.extents.magnitude),
                Quaternion.LookRotation(fwd, curState.ReferenceUp), Vector3.one);
            m_LastBounds = group.GetViewSpaceBoundingBox(m_lastBoundsMatrix);
            float   targetHeight = GetTargetHeight(m_LastBounds);
            Vector3 targetPos    = m_lastBoundsMatrix.MultiplyPoint3x4(m_LastBounds.center);

            // Apply damping
            if (deltaTime >= 0)
            {
                float delta = targetHeight - m_prevTargetHeight;
                delta        = Damper.Damp(delta, m_FrameDamping, deltaTime);
                targetHeight = m_prevTargetHeight + delta;
            }
            m_prevTargetHeight = targetHeight;

            // Move the camera
            if (!curState.Lens.Orthographic && m_AdjustmentMode != AdjustmentMode.ZoomOnly)
            {
                // What distance would be needed to get the target height, at the current FOV
                float currentFOV     = curState.Lens.FieldOfView;
                float targetDistance = targetHeight / (2f * Mathf.Tan(currentFOV * Mathf.Deg2Rad / 2f));

                // target the near surface of the bounding box
                float cameraDistance = targetDistance + m_LastBounds.extents.z;

                // Clamp to respect min/max distance settings
                cameraDistance = Mathf.Clamp(
                    cameraDistance, currentDistance - m_MaxDollyIn, currentDistance + m_MaxDollyOut);
                cameraDistance = Mathf.Clamp(cameraDistance, m_MinimumDistance, m_MaximumDistance);

                // Apply
                curState.PositionCorrection += targetPos - fwd * cameraDistance - curState.RawPosition;
            }

            // Apply zoom
            if (curState.Lens.Orthographic || m_AdjustmentMode != AdjustmentMode.DollyOnly)
            {
                float nearBoundsDistance = (TrackedPoint - curState.CorrectedPosition).magnitude
                                           - m_LastBounds.extents.z;
                float currentFOV = 179;
                if (nearBoundsDistance > Epsilon)
                {
                    currentFOV = 2f * Mathf.Atan(targetHeight / (2 * nearBoundsDistance)) * Mathf.Rad2Deg;
                }

                LensSettings lens = curState.Lens;
                lens.FieldOfView      = Mathf.Clamp(currentFOV, m_MinimumFOV, m_MaximumFOV);
                lens.OrthographicSize = Mathf.Clamp(targetHeight / 2, m_MinimumOrthoSize, m_MaximumOrthoSize);
                curState.Lens         = lens;
            }

            // Now compose normally
            base.MutateCameraState(ref curState, deltaTime);
            //UnityEngine.Profiling.Profiler.EndSample();
        }