/// <summary>Internal use only. Called by CinemachineCore at designated update time /// so the vcam can position itself and track its targets. All 3 child rigs are updated, /// and a blend calculated, depending on the value of the Y axis.</summary> /// <param name="worldUp">Default world Up, set by the CinemachineBrain</param> /// <param name="deltaTime">Delta time for time-based effects (ignore if less than 0)</param> override public void InternalUpdateCameraState(Vector3 worldUp, float deltaTime) { // Initialize the camera state, in case the game object got moved in the editor m_State = PullStateFromVirtualCamera(worldUp, ref m_Lens); m_Rigs[(int)RigID.Top].m_Lens.SnapshotCameraReadOnlyProperties(ref m_Lens); m_Rigs[(int)RigID.Bottom].m_Lens.SnapshotCameraReadOnlyProperties(ref m_Lens); // Update our axes bool activeCam = PreviousStateIsValid || CinemachineCore.Instance.IsLive(this); if (activeCam && deltaTime >= 0) { if (m_VerticalAxis.Update(deltaTime)) { m_VerticalAxis.m_Recentering.CancelRecentering(); } m_RadialAxis.Update(deltaTime); } m_VerticalAxis.m_Recentering.DoRecentering(ref m_VerticalAxis, deltaTime, 0.5f); // Blend the components if (mBlender == null) { mBlender = new ComponentBlender(this); } mBlender.Blend(GetVerticalAxisValue()); // Blend the lens if (m_Rigs[mBlender.OtherRig].m_CustomLens) { m_State.Lens = LensSettings.Lerp( m_State.Lens, m_Rigs[mBlender.OtherRig].m_Lens, mBlender.BlendAmount); } // Do our stuff SetReferenceLookAtTargetInState(ref m_State); InvokeComponentPipeline(ref m_State, worldUp, deltaTime); ApplyPositionBlendMethod(ref m_State, m_Transitions.m_BlendHint); // Restore the components mBlender.Restore(); // Push the raw position back to the game object's transform, so it // moves along with the camera. if (!UserIsDragging) { if (Follow != null) { transform.position = State.RawPosition; } if (LookAt != null) { transform.rotation = State.RawOrientation; } } // Signal that it's all done InvokePostPipelineStageCallback(this, CinemachineCore.Stage.Finalize, ref m_State, deltaTime); PreviousStateIsValid = true; }
/// <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); }
/// <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">PHow 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(); state.Lens = LensSettings.Lerp(stateA.Lens, stateB.Lens, t); state.ReferenceUp = Vector3.Slerp(stateA.ReferenceUp, stateB.ReferenceUp, t); state.RawPosition = Vector3.Lerp(stateA.RawPosition, stateB.RawPosition, t); Vector3 dirTarget = Vector3.zero; if (!stateA.HasLookAt || !stateB.HasLookAt) { state.ReferenceLookAt = kNoPoint; // can't interpolate if undefined } else { // Re-interpolate FOV to preserve target composition, if possible float fovA = stateA.Lens.FieldOfView; float fovB = stateB.Lens.FieldOfView; if (!Mathf.Approximately(fovA, fovB)) { LensSettings lens = state.Lens; lens.FieldOfView = state.InterpolateFOV( fovA, fovB, (stateA.ReferenceLookAt - stateA.RawPosition).magnitude, (stateB.ReferenceLookAt - stateB.RawPosition).magnitude, t); state.Lens = lens; // Make sure we preserve the screen composition through FOV changes adjustedT = Mathf.Abs((lens.FieldOfView - fovA) / (fovB - fovA)); } // Spherical linear interpolation about RawPosition state.ReferenceLookAt = state.RawPosition + Vector3.Slerp( stateA.ReferenceLookAt - state.RawPosition, stateB.ReferenceLookAt - state.RawPosition, adjustedT); dirTarget = state.ReferenceLookAt - state.RawPosition; } // Clever orientation interpolation if (dirTarget.AlmostZero()) { // Don't know what we're looking at - can only slerp state.RawOrientation = 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 state.RawOrientation = UnityQuaternionExtensions.SlerpWithReferenceUp( stateA.RawOrientation, stateB.RawOrientation, t, state.ReferenceUp); } else { // Put the target in the center state.RawOrientation = Quaternion.LookRotation(dirTarget, state.ReferenceUp); // Blend the desired offsets from center Vector2 deltaA = -stateA.RawOrientation.GetCameraRotationToTarget( stateA.ReferenceLookAt - stateA.RawPosition, stateA.ReferenceUp); Vector2 deltaB = -stateB.RawOrientation.GetCameraRotationToTarget( stateB.ReferenceLookAt - stateB.RawPosition, stateB.ReferenceUp); state.RawOrientation = state.RawOrientation.ApplyCameraRotation( Vector2.Lerp(deltaA, deltaB, adjustedT), state.ReferenceUp); } } state.ShotQuality = Mathf.Lerp(stateA.ShotQuality, stateB.ShotQuality, t); state.PositionCorrection = Vector3.Lerp( stateA.PositionCorrection, stateB.PositionCorrection, t); // GML todo: is this right? Can it introduce a roll? state.OrientationCorrection = Quaternion.Slerp( stateA.OrientationCorrection, stateB.OrientationCorrection, t); return(state); }
public static CameraState Lerp(CameraState stateA, CameraState stateB, float t) { t = Mathf.Clamp01(t); float t2 = t; CameraState result = default(CameraState); result.Lens = LensSettings.Lerp(stateA.Lens, stateB.Lens, t); result.ReferenceUp = Vector3.Slerp(stateA.ReferenceUp, stateB.ReferenceUp, t); result.RawPosition = Vector3.Lerp(stateA.RawPosition, stateB.RawPosition, t); result.ShotQuality = Mathf.Lerp(stateA.ShotQuality, stateB.ShotQuality, t); result.PositionCorrection = Vector3.Lerp(stateA.PositionCorrection, stateB.PositionCorrection, t); result.OrientationCorrection = Quaternion.Slerp(stateA.OrientationCorrection, stateB.OrientationCorrection, t); Vector3 vector = Vector3.zero; if (!stateA.HasLookAt || !stateB.HasLookAt) { result.ReferenceLookAt = CameraState.kNoPoint; } else { float fieldOfView = stateA.Lens.FieldOfView; float fieldOfView2 = stateB.Lens.FieldOfView; if (!result.Lens.Orthographic && !Mathf.Approximately(fieldOfView, fieldOfView2)) { LensSettings lens = result.Lens; lens.FieldOfView = result.InterpolateFOV(fieldOfView, fieldOfView2, Mathf.Max((stateA.ReferenceLookAt - stateA.CorrectedPosition).magnitude, stateA.Lens.NearClipPlane), Mathf.Max((stateB.ReferenceLookAt - stateB.CorrectedPosition).magnitude, stateB.Lens.NearClipPlane), t); result.Lens = lens; t2 = Mathf.Abs((lens.FieldOfView - fieldOfView) / (fieldOfView2 - fieldOfView)); } result.ReferenceLookAt = Vector3.Lerp(stateA.ReferenceLookAt, stateB.ReferenceLookAt, t2); float num = Quaternion.Angle(stateA.RawOrientation, stateB.RawOrientation); if (num > 0.0001f) { vector = result.ReferenceLookAt - result.CorrectedPosition; } } if (vector.AlmostZero()) { result.RawOrientation = UnityQuaternionExtensions.SlerpWithReferenceUp(stateA.RawOrientation, stateB.RawOrientation, t, result.ReferenceUp); } else { vector = vector.normalized; if ((vector - result.ReferenceUp).AlmostZero() || (vector + result.ReferenceUp).AlmostZero()) { result.RawOrientation = UnityQuaternionExtensions.SlerpWithReferenceUp(stateA.RawOrientation, stateB.RawOrientation, t, result.ReferenceUp); } else { result.RawOrientation = Quaternion.LookRotation(vector, result.ReferenceUp); Vector2 a = -stateA.RawOrientation.GetCameraRotationToTarget(stateA.ReferenceLookAt - stateA.CorrectedPosition, stateA.ReferenceUp); Vector2 b = -stateB.RawOrientation.GetCameraRotationToTarget(stateB.ReferenceLookAt - stateB.CorrectedPosition, stateB.ReferenceUp); result.RawOrientation = result.RawOrientation.ApplyCameraRotation(Vector2.Lerp(a, b, t2), result.ReferenceUp); } } for (int i = 0; i < stateA.NumCustomBlendables; i++) { CameraState.CustomBlendable customBlendable = stateA.GetCustomBlendable(i); customBlendable.m_Weight *= 1f - t; if (customBlendable.m_Weight > 0.0001f) { result.AddCustomBlendable(customBlendable); } } for (int j = 0; j < stateB.NumCustomBlendables; j++) { CameraState.CustomBlendable customBlendable2 = stateB.GetCustomBlendable(j); customBlendable2.m_Weight *= t; if (customBlendable2.m_Weight > 0.0001f) { result.AddCustomBlendable(customBlendable2); } } return(result); }
/// <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(); state.Lens = LensSettings.Lerp(stateA.Lens, stateB.Lens, t); state.ReferenceUp = Vector3.Slerp(stateA.ReferenceUp, stateB.ReferenceUp, t); state.RawPosition = Vector3.Lerp(stateA.RawPosition, stateB.RawPosition, t); state.ShotQuality = Mathf.Lerp(stateA.ShotQuality, stateB.ShotQuality, t); state.PositionCorrection = Vector3.Lerp( stateA.PositionCorrection, stateB.PositionCorrection, t); // GML todo: is this right? Can it introduce a roll? state.OrientationCorrection = Quaternion.Slerp( stateA.OrientationCorrection, stateB.OrientationCorrection, t); Vector3 dirTarget = Vector3.zero; if (!stateA.HasLookAt || !stateB.HasLookAt) { state.ReferenceLookAt = kNoPoint; // can't interpolate if undefined } else { // Re-interpolate FOV to preserve target composition, if possible float fovA = stateA.Lens.FieldOfView; float fovB = stateB.Lens.FieldOfView; if (!state.Lens.Orthographic && !Mathf.Approximately(fovA, fovB)) { LensSettings lens = state.Lens; lens.FieldOfView = state.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); // 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; } } // Clever orientation interpolation if (dirTarget.AlmostZero()) { // Don't know what we're looking at - can only slerp state.RawOrientation = 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 state.RawOrientation = UnityQuaternionExtensions.SlerpWithReferenceUp( stateA.RawOrientation, stateB.RawOrientation, t, state.ReferenceUp); } else { // Put the target in the center state.RawOrientation = 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); state.RawOrientation = state.RawOrientation.ApplyCameraRotation( Vector2.Lerp(deltaA, deltaB, adjustedT), state.ReferenceUp); } } // 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); }