protected Quaternion GetCounterRotationDelta(Quaternion deltaRot) { Vector3 ea = new Angle3(deltaRot.eulerAngles).eulerAcute; ea.x *= counterRotationPerAxis.x; ea.y *= counterRotationPerAxis.y; ea.z *= counterRotationPerAxis.z; ea *= counterRotationStrength; return(Quaternion.Euler(ea)); }
protected float CalculateMotion(float dT) { dT = Mathf.Max(dT, 0.000001f); float fx = 0; // Total effect strength from all motion types #if UNITY_EDITOR // Debug motion calculations // Cache current settings bool wasUsingAv = useAngularVelocity; bool wasUsingLa = useAcceleration; bool wasUsingLv = useVelocity; float prevAvStr = angularVelocityStrength; float prevLaStr = accelerationStrength; float prevLvStr = velocityStrength; // Turn on all motion calculations if (_debugMotionCalculations) { // Disable contributions of unused motion types if (!useAngularVelocity) { angularVelocityStrength = 0; } if (!useAcceleration) { accelerationStrength = 0; } if (!useVelocity) { velocityStrength = 0; } useAngularVelocity = useAcceleration = useVelocity = true; } #endif // Rotation Vector3 fwd = motionTarget.forward; if (useAngularVelocity) { float av = Vector3.Angle(_lastFwd, fwd) / dT; #if UNITY_EDITOR _debugAv = av; #endif av = Mathf.InverseLerp(angularVelocityMin, angularVelocityMax, av); _avSmoothed = Mathf.SmoothDamp(_avSmoothed, av, ref _avSlew, angularVelocitySmoothing); fx += _avSmoothed * angularVelocityStrength; } // Velocity float speed = 0; Vector3 dPos = motionTarget.position - _lastPos; Vector3 vel = dPos / dT; if (useVelocity || useAcceleration) { speed = vel.magnitude; #if UNITY_EDITOR _debugLv = speed; #endif } if (useVelocity) { _speedSmoothed = Mathf.SmoothDamp(_speedSmoothed, speed, ref _speedSlew, velocitySmoothing); float lm = 0; // Check for divide-by-zero if (!Mathf.Approximately(velocityMax, velocityMin)) { lm = Mathf.Clamp01((_speedSmoothed - velocityMin) / (velocityMax - velocityMin)); } fx += lm * velocityStrength; } // Acceleration if (useAcceleration) { // Use unsmoothed vel to keep smoothing independent float accel = Mathf.Abs(speed - _lastSpeed) / dT; #if UNITY_EDITOR _debugLa = accel; #endif // Check for divide-by-zero if (!Mathf.Approximately(accelerationMax, accelerationMin)) { accel = Mathf.Clamp01((accel - accelerationMin) / (accelerationMax - accelerationMin)); } _accelSmoothed = Mathf.SmoothDamp(_accelSmoothed, accel, ref _accelSlew, accelerationSmoothing); fx += _accelSmoothed * accelerationStrength; } ; // Clamp and scale final effect strength fx = RemapRadius(fx) * RemapRadius(effectCoverage); #region Motion Effects #region Artificial Tilt // Check if target has changed or bool has been toggled if ((useArtificialTilt != _prevUseTilt) || (motionEffectTarget != _prevMotionEffectTarget)) { // Reset smoothing params _prevUseTilt = useArtificialTilt; _tiltAccelSlew = _tiltAccelSmoothed = Vector3.zero; // Ensure previous tilt target gets its rotation reset if (_prevMotionEffectTarget != null) { _prevMotionEffectTarget.localEulerAngles = _tiltInit.eulerAcute; } // Reset tilt offset if (motionEffectTarget != null) { _tiltInit = new Angle3(motionEffectTarget.localEulerAngles); _mfxTgtLocalPosInit = motionEffectTarget.localPosition; _mfxTgtLocalRotInit = motionEffectTarget.localRotation; } else { _tiltInit = Vector3.zero; } // Cache new target _prevMotionEffectTarget = motionEffectTarget; } // Apply tilt if (useArtificialTilt && motionEffectTarget != null) { Vector3 accTgt = motionTarget.InverseTransformDirection(vel - _lastVel) / dT; // Convert to log_e for (int i = 0; i < 3; ++i) { float acc = accTgt[i]; float sign = Mathf.Sign(acc); acc = Mathf.Abs(acc); acc = Mathf.Log(acc + 1); accTgt[i] = acc * sign; } _tiltAccelSmoothed = Vector3.SmoothDamp(_tiltAccelSmoothed, accTgt, ref _tiltAccelSlew, tiltSmoothTime, 1000, dT); Vector3 tilt = new Angle3(_tiltAccelSmoothed.z * tiltStrength, 0, _tiltAccelSmoothed.x * tiltStrength).eulerAcute; if (tiltMaxAngles.sqrMagnitude > 0) { tilt = new Vector3( Mathf.Clamp(tilt.x, -tiltMaxAngles.x, tiltMaxAngles.x), 0, Mathf.Clamp(tilt.z, -tiltMaxAngles.y, tiltMaxAngles.y) ); } motionEffectTarget.localEulerAngles = (_tiltInit + tilt).eulerAcute; } #endregion #region Framerate Division bool updateFps = false; if (framerateDivision > 1 && (divideTranslation || divideRotation)) { if (Time.frameCount % framerateDivision == 0) { updateFps = true; } else { motionEffectTarget.position = _fpsPosition; motionEffectTarget.rotation = _fpsRotation; } } // Check for settings change if (_lastFpsDivision != framerateDivision) { updateFps = true; _lastFpsDivision = framerateDivision; } if (updateFps) { if (divideTranslation) { motionEffectTarget.localPosition = _mfxTgtLocalPosInit; _fpsPosition = motionEffectTarget.position; } if (divideRotation) { motionEffectTarget.localRotation = _mfxTgtLocalRotInit; _fpsRotation = motionEffectTarget.rotation; } } #endregion if (useCounterMotion) { UpdateCounterMotion(dPos, Quaternion.Inverse(motionTarget.rotation) * _lastRot); } #endregion // Cache current motion params for next frame _lastFwd = fwd; _lastPos = motionTarget.position; _lastSpeed = speed; _lastVel = vel; _lastRot = motionTarget.rotation; #if UNITY_EDITOR // Restore motion settings if (_debugMotionCalculations) { useAngularVelocity = wasUsingAv; useAcceleration = wasUsingLa; useVelocity = wasUsingLv; angularVelocityStrength = prevAvStr; accelerationStrength = prevLaStr; velocityStrength = prevLvStr; } // Use forced value if (_debugForceOn) { return(Mathf.Clamp01(RemapRadius(_debugForceValue) * RemapRadius(effectCoverage))); } #endif return(Mathf.Clamp01(fx)); }