#region License /* Copyright (C) <2009-2011> * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #endregion namespace Sog { /// /// Provides constants and static methods for trigonometric, logarithmic, and other common mathematical functions. /// public sealed class FixedMath { /// /// PI constant. /// public static Fixed64 Pi = Fixed64.Pi; public static Fixed64 PI = Fixed64.Pi; /// /// PI over 2 constant. /// public static Fixed64 PiOver2 = Fixed64.PiOver2; /// /// A small value often used to decide if numeric results are zero. /// public static Fixed64 Epsilon = Fixed64.Epsilon; /// /// Degree to radians constant. /// public static Fixed64 Deg2Rad = Fixed64.Deg2Rad; /// /// Radians to degree constant. /// public static Fixed64 Rad2Deg = Fixed64.Rad2Deg; /// /// Gets the square root. /// /// The number to get the square root from. /// public static Fixed64 Sqrt(Fixed64 number) { return Fixed64.Sqrt(number); } public static Fixed64 Square(Fixed64 value) { return value * value; } /// /// Gets the maximum number of two values. /// /// The first value. /// The second value. /// Returns the largest value. public static Fixed64 Max(Fixed64 val1, Fixed64 val2) { return (val1 > val2) ? val1 : val2; } /// /// Gets the minimum number of two values. /// /// The first value. /// The second value. /// Returns the smallest value. public static Fixed64 Min(Fixed64 val1, Fixed64 val2) { return (val1 < val2) ? val1 : val2; } /// /// Gets the maximum number of three values. /// /// The first value. /// The second value. /// The third value. /// Returns the largest value. public static Fixed64 Max(Fixed64 val1, Fixed64 val2, Fixed64 val3) { Fixed64 max12 = (val1 > val2) ? val1 : val2; return (max12 > val3) ? max12 : val3; } /// /// Returns a number which is within [min,max] /// /// The value to clamp. /// The minimum value. /// The maximum value. /// The clamped value. public static Fixed64 Clamp(Fixed64 value, Fixed64 min, Fixed64 max) { value = (value > max) ? max : value; value = (value < min) ? min : value; return value; } public static Fixed64 Clamp01(Fixed64 value) { if (value < Fixed64.Zero) return Fixed64.Zero; if (value > Fixed64.One) return Fixed64.One; return value; } /// /// Returns the sine of value. /// public static Fixed64 Sin(Fixed64 value) { return Fixed64.Sin(value); } /// /// Returns the cosine of value. /// public static Fixed64 Cos(Fixed64 value) { return Fixed64.Cos(value); } /// /// Returns the tan of value. /// public static Fixed64 Tan(Fixed64 value) { return Fixed64.Tan(value); } /// /// Returns the arc sine of value. /// public static Fixed64 Asin(Fixed64 value) { return Fixed64.Asin(value); } /// /// Returns the arc cosine of value. /// public static Fixed64 Acos(Fixed64 value) { return Fixed64.Acos(value); } /// /// Returns the arc tan of value. /// public static Fixed64 Atan(Fixed64 value) { return Fixed64.Atan(value); } /// /// Returns the arc tan of coordinates x-y. /// public static Fixed64 Atan2(Fixed64 y, Fixed64 x) { return Fixed64.Atan2(y, x); } /// /// Returns the largest integer less than or equal to the specified number. /// public static Fixed64 Floor(Fixed64 value) { return Fixed64.Floor(value); } public static int FloorToInt(Fixed64 value) { return (int)Fixed64.Floor(value); } /// /// Returns the smallest integral value that is greater than or equal to the specified number. /// public static Fixed64 Ceiling(Fixed64 value) { return value; } public static int CeilToInt(Fixed64 value) { return (int)value; } /// /// Rounds a value to the nearest integral value. /// If the value is halfway between an even and an uneven value, returns the even value. /// public static Fixed64 Round(Fixed64 value) { return Fixed64.Round(value); } public static int RoundToInt(Fixed64 value) { return (int)Fixed64.Round(value); } /// /// Returns a number indicating the sign of a Fix64 number. /// Returns 1 if the value is positive, 0 if is 0, and -1 if it is negative. /// public static int Sign(Fixed64 value) { return Fixed64.Sign(value); } /// /// Returns the absolute value of a Fix64 number. /// Note: Abs(Fix64.MinValue) == Fix64.MaxValue. /// public static Fixed64 Abs(Fixed64 value) { return Fixed64.Abs(value); } public static Fixed64 Barycentric(Fixed64 value1, Fixed64 value2, Fixed64 value3, Fixed64 amount1, Fixed64 amount2) { return value1 + (value2 - value1) * amount1 + (value3 - value1) * amount2; } public static Fixed64 CatmullRom(Fixed64 value1, Fixed64 value2, Fixed64 value3, Fixed64 value4, Fixed64 amount) { // Using formula from http://www.mvps.org/directx/articles/catmull/ // Internally using FPs not to lose precission Fixed64 amountSquared = amount * amount; Fixed64 amountCubed = amountSquared * amount; return (0.5 * (2.0 * value2 + (value3 - value1) * amount + (2.0 * value1 - 5.0 * value2 + 4.0 * value3 - value4) * amountSquared + (3.0 * value2 - value1 - 3.0 * value3 + value4) * amountCubed)); } public static Fixed64 Distance(Fixed64 value1, Fixed64 value2) { return Fixed64.Abs(value1 - value2); } public static Fixed64 Hermite(Fixed64 value1, Fixed64 tangent1, Fixed64 value2, Fixed64 tangent2, Fixed64 amount) { // All transformed to FP not to lose precission // Otherwise, for high numbers of param:amount the result is NaN instead of Infinity Fixed64 v1 = value1, v2 = value2, t1 = tangent1, t2 = tangent2, s = amount, result; Fixed64 sCubed = s * s * s; Fixed64 sSquared = s * s; if (amount == 0f) result = value1; else if (amount == 1f) result = value2; else result = (2 * v1 - 2 * v2 + t2 + t1) * sCubed + (3 * v2 - 3 * v1 - 2 * t1 - t2) * sSquared + t1 * s + v1; return result; } public static Fixed64 Lerp(Fixed64 value1, Fixed64 value2, Fixed64 amount) { return value1 + (value2 - value1) * amount; } public static Fixed64 InverseLerp(Fixed64 a, Fixed64 b, Fixed64 value) { if (a != b) return Clamp01((value - a) / (b - a)); return Fixed64.Zero; } public static Fixed64 SmoothStep(Fixed64 value1, Fixed64 value2, Fixed64 amount) { // It is expected that 0 < amount < 1 // If amount < 0, return value1 // If amount > 1, return value2 Fixed64 result = Clamp(amount, 0f, 1f); result = Hermite(value1, 0f, value2, 0f, result); return result; } public static Fixed64 Repeat(Fixed64 t, Fixed64 length) { return Clamp(t - Floor(t / length) * length, 0.0f, length); } public static Fixed64 DeltaAngle(Fixed64 current, Fixed64 target) { Fixed64 num = Repeat(target - current, 360f); if (num > 180.0) num -= 360f; return num; } public static int DivideRoundingUp(int numerator, int divisor) { return (numerator + divisor - 1) / divisor; } public static int DivideRoundingUp(int numerator, double divisor) { double num = (double)numerator / divisor; int num2 = (int)System.Math.Truncate(num); if (num - (double)num2 > 0.0) { num2++; } return num2; } public static int DivideRoundingUp(double numerator, double divisor) { double num = numerator / divisor; int num2 = (int)System.Math.Truncate(num); if (num - (double)num2 > 0.0) { num2++; } return num2; } public static Fixed64Vector2 Mix(Fixed64Vector2 v1, Fixed64Vector2 v2, Fixed64 a) { return (v1 + (v2 - v1) * a); } } }