/// <summary> /// Interpolate rotator from Current to Target. Scaled by distance to Target, so it has a strong start speed and ease out. /// </summary> public static FRotator RInterpTo(FRotator current, FRotator target, float deltaTime, float interpSpeed) { // if DeltaTime is 0, do not perform any interpolation (Location was already calculated for that frame) if (deltaTime == 0.0f || current == target) { return(current); } // If no interp speed, jump to target value if (interpSpeed <= 0.0f) { return(target); } float deltaInterpSpeed = interpSpeed * deltaTime; FRotator delta = (target - current).GetNormalized(); // If steps are too small, just return Target and assume we have reached our destination. if (delta.IsNearlyZero()) { return(target); } // Delta Move, Clamp so we do not over shoot. FRotator deltaMove = delta * FMath.Clamp(deltaInterpSpeed, 0.0f, 1.0f); return((current + deltaMove).GetNormalized()); }
/// <summary> /// Makes a color red->green with the passed in scalar (e.g. 0 is red, 1 is green) /// </summary> public static FColor MakeRedToGreenColorFromScalar(float scalar) { float redSclr = FMath.Clamp((1.0f - scalar) / 0.5f, 0.0f, 1.0f); float greenSclr = FMath.Clamp((scalar / 0.5f), 0.0f, 1.0f); int r = FMath.TruncToInt(255 * redSclr); int g = FMath.TruncToInt(255 * greenSclr); int b = 0; return(new FColor((byte)r, (byte)g, (byte)b)); }
/// <summary> /// Interpolate float from Current to Target with constant step /// </summary> public static float FInterpConstantTo(float current, float target, float deltaTime, float interpSpeed) { float dist = target - current; // If distance is too small, just set the desired location if (FMath.Square(dist) < SmallNumber) { return(target); } float step = interpSpeed * deltaTime; return(current + FMath.Clamp(dist, -step, step)); }
/// <summary> /// Interpolate quaternion from Current to Target. Scaled by angle to Target, so it has a strong start speed and ease out. /// </summary> public static FQuat QInterpTo(FQuat current, FQuat target, float deltaTime, float interpSpeed) { // If no interp speed, jump to target value if (interpSpeed <= 0.0f) { return(target); } // If the values are nearly equal, just return Target and assume we have reached our destination. if (current.Equals(target)) { return(target); } return(FQuat.Slerp(current, target, FMath.Clamp(interpSpeed * deltaTime, 0.0f, 1.0f))); }
/// <summary> /// Interpolate vector2D from Current to Target. Scaled by distance to Target, so it has a strong start speed and ease out. /// </summary> public static FVector2D Vector2DInterpTo(FVector2D current, FVector2D target, float deltaTime, float interpSpeed) { if (interpSpeed <= 0.0f) { return(target); } FVector2D dist = target - current; if (dist.SizeSquared() < KindaSmallNumber) { return(target); } FVector2D deltaMove = dist * FMath.Clamp(deltaTime * interpSpeed, 0.0f, 1.0f); return(current + deltaMove); }
/// <summary> /// Simpler Slerp that doesn't do any checks for 'shortest distance' etc. /// We need this for the cubic interpolation stuff so that the multiple Slerps dont go in different directions. /// Result is NOT normalized. /// </summary> public static FQuat SlerpFullPath_NotNormalized(FQuat quat1, FQuat quat2, float alpha) { float cosAngle = FMath.Clamp(quat1 | quat2, -1.0f, 1.0f); float angle = FMath.Acos(cosAngle); //UE_LOG(LogUnrealMath, Log, TEXT("CosAngle: %f Angle: %f"), CosAngle, Angle ); if (FMath.Abs(angle) < FMath.KindaSmallNumber) { return(quat1); } float sinAngle = FMath.Sin(angle); float invSinAngle = 1.0f / sinAngle; float scale0 = FMath.Sin((1.0f - alpha) * angle) * invSinAngle; float scale1 = FMath.Sin(alpha * angle) * invSinAngle; return(quat1 * scale0 + quat2 * scale1); }
/// <summary> /// Interpolate quaternion from Current to Target with constant step (in radians) /// </summary> public static FQuat QInterpConstantTo(FQuat current, FQuat target, float deltaTime, float interpSpeed) { // If no interp speed, jump to target value if (interpSpeed <= 0.0f) { return(target); } // If the values are nearly equal, just return Target and assume we have reached our destination. if (current.Equals(target)) { return(target); } float deltaInterpSpeed = FMath.Clamp(deltaTime * interpSpeed, 0.0f, 1.0f); float angularDistance = FMath.Max(SmallNumber, target.AngularDistance(current)); float alpha = FMath.Clamp(deltaInterpSpeed / angularDistance, 0.0f, 1.0f); return(FQuat.Slerp(current, target, alpha)); }
/// <summary> /// Interpolate Linear Color from Current to Target. Scaled by distance to Target, so it has a strong start speed and ease out. /// </summary> public static FLinearColor CInterpTo(FLinearColor current, FLinearColor target, float deltaTime, float interpSpeed) { // If no interp speed, jump to target value if (interpSpeed <= 0.0f) { return(target); } // Difference between colors float dist = FLinearColor.Dist(target, current); // If distance is too small, just set the desired color if (dist < KindaSmallNumber) { return(target); } // Delta change, Clamp so we do not over shoot. FLinearColor deltaMove = (target - current) * FMath.Clamp(deltaTime * interpSpeed, 0.0f, 1.0f); return(current + deltaMove); }
/// <summary> /// Interpolate float from Current to Target. Scaled by distance to Target, so it has a strong start speed and ease out. /// </summary> public static float FInterpTo(float current, float target, float deltaTime, float interpSpeed) { // If no interp speed, jump to target value if (interpSpeed <= 0.0f) { return(target); } // Distance to reach float dist = target - current; // If distance is too small, just set the desired location if (FMath.Square(dist) < SmallNumber) { return(target); } // Delta Move, Clamp so we do not over shoot. float deltaMove = dist * FMath.Clamp(deltaTime * interpSpeed, 0.0f, 1.0f); return(current + deltaMove); }
/// <summary> /// Interpolate vector from Current to Target. Scaled by distance to Target, so it has a strong start speed and ease out. /// </summary> public static FVector VInterpTo(FVector current, FVector target, float deltaTime, float interpSpeed) { // If no interp speed, jump to target value if (interpSpeed <= 0.0f) { return(target); } // Distance to reach FVector dist = target - current; // If distance is too small, just set the desired location if (dist.SizeSquared() < KindaSmallNumber) { return(target); } // Delta Move, Clamp so we do not over shoot. FVector deltaMove = dist * FMath.Clamp(deltaTime * interpSpeed, 0.0f, 1.0f); return(current + deltaMove); }
// Special-case interpolation /// <summary> /// Interpolate a normal vector Current to Target, by interpolating the angle between those vectors with constant step. /// </summary> public static FVector VInterpNormalRotationTo(FVector current, FVector target, float deltaTime, float rotationSpeedDegrees) { // Find delta rotation between both normals. FQuat deltaQuat = FQuat.FindBetween(current, target); // Decompose into an axis and angle for rotation FVector deltaAxis; float deltaAngle; deltaQuat.ToAxisAndAngle(out deltaAxis, out deltaAngle); // Find rotation step for this frame float rotationStepRadians = rotationSpeedDegrees * (PI / 180) * deltaTime; if (FMath.Abs(deltaAngle) > rotationStepRadians) { deltaAngle = FMath.Clamp(deltaAngle, -rotationStepRadians, rotationStepRadians); deltaQuat = new FQuat(deltaAxis, deltaAngle); return(deltaQuat.RotateVector(current)); } return(target); }
/// <summary> /// Interpolate rotator from Current to Target with constant step /// </summary> public static FRotator RInterpConstantTo(FRotator current, FRotator target, float deltaTime, float interpSpeed) { // if DeltaTime is 0, do not perform any interpolation (Location was already calculated for that frame) if (deltaTime == 0.0f || current == target) { return(current); } // If no interp speed, jump to target value if (interpSpeed <= 0.0f) { return(target); } float deltaInterpSpeed = interpSpeed * deltaTime; FRotator deltaMove = (target - current).GetNormalized(); FRotator result = current; result.Pitch += FMath.Clamp(deltaMove.Pitch, -deltaInterpSpeed, deltaInterpSpeed); result.Yaw += FMath.Clamp(deltaMove.Yaw, -deltaInterpSpeed, deltaInterpSpeed); result.Roll += FMath.Clamp(deltaMove.Roll, -deltaInterpSpeed, deltaInterpSpeed); return(result.GetNormalized()); }
/// <summary> /// Creates a copy of this vector with both axes clamped to the given range. /// </summary> /// <param name="minAxisVal"></param> /// <param name="maxAxisVal"></param> /// <returns>New vector with clamped axes.</returns> public FVector2D ClampAxes(float minAxisVal, float maxAxisVal) { return(new FVector2D(FMath.Clamp(X, minAxisVal, maxAxisVal), FMath.Clamp(Y, minAxisVal, maxAxisVal))); }