mixedreality/com.microsoft.mixedreality..../SDK/Features/Utilities/Solvers/Momentum.cs

149 lines
5.1 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Utilities.Solvers
{
/// <summary>
/// Applies acceleration/velocity/friction to simulate momentum for an object being moved by other solvers/components
/// </summary>
[AddComponentMenu("Scripts/MRTK/SDK/Momentum")]
public class Momentum : Solver
{
#region Momentum Parameters
[SerializeField]
[Tooltip("Friction to slow down the current velocity")]
private float resistance = 0.99f;
/// <summary>
/// Friction to slow down the current velocity
/// </summary>
public float Resistance
{
get { return resistance; }
set { resistance = value; }
}
[SerializeField]
[Tooltip("Apply more resistance when going faster- applied resistance is resistance * (velocity ^ resistanceVelocityPower)")]
private float resistanceVelocityPower = 1.5f;
/// <summary>
/// Apply more resistance when going faster- applied resistance is resistance * (velocity ^ resistanceVelocityPower)
/// </summary>
public float ResistanceVelocityPower
{
get { return resistanceVelocityPower; }
set { resistanceVelocityPower = value; }
}
[SerializeField]
[Tooltip("Accelerate to goal position at this rate")]
private float accelerationRate = 10f;
/// <summary>
/// Accelerate to goal position at this rate
/// </summary>
public float AccelerationRate
{
get { return accelerationRate; }
set { accelerationRate = value; }
}
[SerializeField]
[Tooltip("Apply more acceleration if farther from target- applied acceleration is accelerationRate + springiness * distance")]
private float springiness = 0;
/// <summary>
/// Apply more acceleration if farther from target- applied acceleration is accelerationRate + springiness * distance
/// </summary>
public float Springiness
{
get { return springiness; }
set { springiness = value; }
}
[SerializeField]
[Tooltip("Instantly maintain a constant depth from the view point instead of simulating Z-velocity")]
private bool snapZ = true;
/// <summary>
/// Instantly maintain a constant depth from the view point instead of simulating Z-velocity
/// </summary>
public bool SnapZ
{
get { return snapZ; }
set { snapZ = value; }
}
#endregion
private Vector3 velocity;
private Vector3 ReferencePosition => SolverHandler.TransformTarget == null ? Vector3.zero : SolverHandler.TransformTarget.position;
protected override void OnEnable()
{
base.OnEnable();
velocity = Vector3.zero;
}
/// <inheritdoc />
public override void SolverUpdate()
{
// Start with snapZ
if (SnapZ)
{
// Snap the current depth to the goal depth
var referencePosition = ReferencePosition;
float goalDepth = (SolverHandler.GoalPosition - referencePosition).magnitude;
Vector3 currentDelta = transform.position - referencePosition;
float currentDeltaMagnitude = currentDelta.magnitude;
if (!Mathf.Approximately(currentDeltaMagnitude, 0))
{
Vector3 currentDeltaNorm = currentDelta / currentDeltaMagnitude;
transform.position += currentDeltaNorm * (goalDepth - currentDeltaMagnitude);
}
}
// Determine and apply acceleration
Vector3 delta = SolverHandler.GoalPosition - transform.position;
float deltaMagnitude = delta.magnitude;
if (deltaMagnitude > 0.01f)
{
Vector3 deltaNorm = delta / deltaMagnitude;
velocity += deltaNorm * (SolverHandler.DeltaTime * (AccelerationRate + Springiness * deltaMagnitude));
}
// Resistance
float velocityMagnitude = velocity.magnitude;
if (!Mathf.Approximately(velocityMagnitude, 0))
{
Vector3 velocityNormal = velocity / velocityMagnitude;
float powFactor = velocityMagnitude > 1f ? Mathf.Pow(velocityMagnitude, ResistanceVelocityPower) : velocityMagnitude;
velocity -= velocityNormal * (powFactor * Resistance * SolverHandler.DeltaTime);
}
if (velocity.sqrMagnitude < 0.001f)
{
velocity = Vector3.zero;
}
// Apply velocity to the solver... no wait, the actual transform
transform.position += velocity * SolverHandler.DeltaTime;
}
/// <inheritdoc />
public override void SnapTo(Vector3 position, Quaternion rotation, Vector3 scale)
{
base.SnapTo(position, rotation, scale);
velocity = Vector3.zero;
}
}
}