// https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Math/Vector3.cs
pc.Vec3.SmoothDamp = function (current, target, currentVelocity, smoothTime, maxSpeed, deltaTime) {
var output_x = 0;
var output_y = 0;
var output_z = 0;
smoothTime = Math.max(0.0001, smoothTime);
var omega = 2 / smoothTime;
var x = omega * deltaTime;
var exp = 1 / (1 + x + 0.48 * x * x + 0.235 * x * x * x);
var change_x = current.x - target.x;
var change_y = current.y - target.y;
var change_z = current.z - target.z;
var originalTo = target;
var maxChange = maxSpeed * smoothTime;
var maxChangeSq = Math.pow(maxSpeed, 2);
var sqrmag = change_x + change_x + change_y + change_y + change_z + change_z;
if (sqrmag > maxChangeSq) {
var mag = Math.sqrt(sqrmag);
change_x = change_x / mag * maxChange;
change_y = change_y / mag * maxChange;
change_z = change_z / mag * maxChange;
}
target.x = current.x - change_x;
target.y = current.y - change_y;
target.z = current.z - change_z;
var temp_x = (currentVelocity.x + omega * change_x) * deltaTime;
var temp_y = (currentVelocity.y + omega * change_y) * deltaTime;
var temp_z = (currentVelocity.z + omega * change_z) * deltaTime;
currentVelocity.x = (currentVelocity.x - omega * temp_x) * exp;
currentVelocity.y = (currentVelocity.y - omega * temp_y) * exp;
currentVelocity.z = (currentVelocity.z - omega * temp_z) * exp;
output_x = target.x + (change_x + temp_x) * exp;
output_y = target.y + (change_y + temp_y) * exp;
output_z = target.z + (change_z + temp_z) * exp;
var origMinusCurrent_x = originalTo.x - current.x;
var origMinusCurrent_y = originalTo.y - current.y;
var origMinusCurrent_z = originalTo.z - current.z;
var outMinusOrig_x = output_x - originalTo.x;
var outMinusOrig_y = output_y - originalTo.y;
var outMinusOrig_z = output_z - originalTo.z;
if (origMinusCurrent_x * outMinusOrig_x + origMinusCurrent_y * outMinusOrig_y + origMinusCurrent_z * outMinusOrig_z > 0) {
output_x = originalTo.x;
output_y = originalTo.y;
output_z = originalTo.z;
currentVelocity.x = (output_x - originalTo.x) / deltaTime;
currentVelocity.y = (output_y - originalTo.y) / deltaTime;
currentVelocity.z = (output_z - originalTo.z) / deltaTime;
}
return new pc.Vec3(output_x, output_y, output_z);
/*
public static Vector3 SmoothDamp(Vector3 current, Vector3 target, ref Vector3 currentVelocity, float smoothTime, float maxSpeed)
{
float deltaTime = Time.deltaTime;
return SmoothDamp(current, target, ref currentVelocity, smoothTime, maxSpeed, deltaTime);
}
[uei.ExcludeFromDocs]
[MethodImpl(MethodImplOptionsEx.AggressiveInlining)]
public static Vector3 SmoothDamp(Vector3 current, Vector3 target, ref Vector3 currentVelocity, float smoothTime)
{
float deltaTime = Time.deltaTime;
float maxSpeed = Mathf.Infinity;
return SmoothDamp(current, target, ref currentVelocity, smoothTime, maxSpeed, deltaTime);
}
// Gradually changes a vector towards a desired goal over time.
public static Vector3 SmoothDamp(Vector3 current, Vector3 target, ref Vector3 currentVelocity, float smoothTime, [uei.DefaultValue("Mathf.Infinity")] float maxSpeed, [uei.DefaultValue("Time.deltaTime")] float deltaTime)
{
float output_x = 0f;
float output_y = 0f;
float output_z = 0f;
// Based on Game Programming Gems 4 Chapter 1.10
smoothTime = Mathf.Max(0.0001F, smoothTime);
float omega = 2F / smoothTime;
float x = omega * deltaTime;
float exp = 1F / (1F + x + 0.48F * x * x + 0.235F * x * x * x);
float change_x = current.x - target.x;
float change_y = current.y - target.y;
float change_z = current.z - target.z;
Vector3 originalTo = target;
// Clamp maximum speed
float maxChange = maxSpeed * smoothTime;
float maxChangeSq = maxChange * maxChange;
float sqrmag = change_x * change_x + change_y * change_y + change_z * change_z;
if (sqrmag > maxChangeSq)
{
var mag = (float)Math.Sqrt(sqrmag);
change_x = change_x / mag * maxChange;
change_y = change_y / mag * maxChange;
change_z = change_z / mag * maxChange;
}
target.x = current.x - change_x;
target.y = current.y - change_y;
target.z = current.z - change_z;
float temp_x = (currentVelocity.x + omega * change_x) * deltaTime;
float temp_y = (currentVelocity.y + omega * change_y) * deltaTime;
float temp_z = (currentVelocity.z + omega * change_z) * deltaTime;
currentVelocity.x = (currentVelocity.x - omega * temp_x) * exp;
currentVelocity.y = (currentVelocity.y - omega * temp_y) * exp;
currentVelocity.z = (currentVelocity.z - omega * temp_z) * exp;
output_x = target.x + (change_x + temp_x) * exp;
output_y = target.y + (change_y + temp_y) * exp;
output_z = target.z + (change_z + temp_z) * exp;
// Prevent overshooting
float origMinusCurrent_x = originalTo.x - current.x;
float origMinusCurrent_y = originalTo.y - current.y;
float origMinusCurrent_z = originalTo.z - current.z;
float outMinusOrig_x = output_x - originalTo.x;
float outMinusOrig_y = output_y - originalTo.y;
float outMinusOrig_z = output_z - originalTo.z;
if (origMinusCurrent_x * outMinusOrig_x + origMinusCurrent_y * outMinusOrig_y + origMinusCurrent_z * outMinusOrig_z > 0)
{
output_x = originalTo.x;
output_y = originalTo.y;
output_z = originalTo.z;
currentVelocity.x = (output_x - originalTo.x) / deltaTime;
currentVelocity.y = (output_y - originalTo.y) / deltaTime;
currentVelocity.z = (output_z - originalTo.z) / deltaTime;
}
return new Vector3(output_x, output_y, output_z);
}
*/
}
3 Likes
Hi @Fus_ion,
Thanks for sharing! The Unity math library has tons of useful methods like this.
1 Like
Yep, I’ve been meaning to port MoveTowards and RotateTowards from Unity for a while
2 Likes