2019-05-08 20:28:04 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
2019-05-26 14:56:23 +00:00
|
|
|
|
using OpenTK;
|
2019-05-08 20:28:04 +00:00
|
|
|
|
|
2019-07-16 21:35:21 +00:00
|
|
|
|
namespace Toolbox.Library
|
2019-05-08 20:28:04 +00:00
|
|
|
|
{
|
|
|
|
|
public static class STMath
|
|
|
|
|
{
|
2023-05-27 23:33:14 +00:00
|
|
|
|
public const float Deg2Rad = (float)System.Math.PI / 180.0f;
|
|
|
|
|
public const float Rad2Deg = 180.0f / (float)System.Math.PI;
|
|
|
|
|
|
2019-05-08 20:28:04 +00:00
|
|
|
|
private const long SizeOfKb = 1024;
|
|
|
|
|
private const long SizeOfMb = SizeOfKb * 1024;
|
|
|
|
|
private const long SizeOfGb = SizeOfMb * 1024;
|
|
|
|
|
private const long SizeOfTb = SizeOfGb * 1024;
|
|
|
|
|
|
|
|
|
|
public static double ConvertBytesToMegabytes(long bytes)
|
|
|
|
|
{
|
|
|
|
|
return (bytes / SizeOfKb) / SizeOfKb;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static double ConvertKilobytesToMegabytes(long kilobytes)
|
|
|
|
|
{
|
|
|
|
|
return kilobytes / SizeOfKb;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static string GetFileSize(this long value, int decimalPlaces = 0)
|
|
|
|
|
{
|
|
|
|
|
var asTb = Math.Round((double)value / SizeOfTb, decimalPlaces);
|
|
|
|
|
var asGb = Math.Round((double)value / SizeOfGb, decimalPlaces);
|
|
|
|
|
var asMb = Math.Round((double)value / SizeOfMb, decimalPlaces);
|
|
|
|
|
var asKb = Math.Round((double)value / SizeOfKb, decimalPlaces);
|
2019-06-18 20:27:36 +00:00
|
|
|
|
string chosenValue = asTb > 1 ? string.Format("{0} TB", asTb)
|
|
|
|
|
: asGb > 1 ? string.Format("{0} GB", asGb)
|
|
|
|
|
: asMb > 1 ? string.Format("{0} MB", asMb)
|
|
|
|
|
: asKb > 1 ? string.Format("{0} KB", asKb)
|
|
|
|
|
: string.Format("{0} bytes", Math.Round((double)value, decimalPlaces));
|
2019-05-08 20:28:04 +00:00
|
|
|
|
return chosenValue;
|
|
|
|
|
}
|
2019-05-26 14:56:23 +00:00
|
|
|
|
|
|
|
|
|
//From https://github.com/Ploaj/SSBHLib/blob/e37b0d83cd088090f7802be19b1d05ec998f2b6a/CrossMod/Tools/CrossMath.cs#L42
|
|
|
|
|
//Seems to give good results
|
2023-05-27 23:33:14 +00:00
|
|
|
|
public static Vector3 ToEulerAngles(double X, double Y, double Z, double W)
|
|
|
|
|
{
|
2019-05-26 15:32:12 +00:00
|
|
|
|
return ToEulerAngles(new Quaternion((float)X, (float)Y, (float)Z, (float)W));
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-27 23:33:14 +00:00
|
|
|
|
public static Vector3 ToEulerAngles(float X, float Y, float Z, float W)
|
|
|
|
|
{
|
2019-05-26 15:32:12 +00:00
|
|
|
|
return ToEulerAngles(new Quaternion(X, Y, Z, W));
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-26 14:56:23 +00:00
|
|
|
|
public static Vector3 ToEulerAngles(Quaternion q)
|
|
|
|
|
{
|
|
|
|
|
Matrix4 mat = Matrix4.CreateFromQuaternion(q);
|
|
|
|
|
float x, y, z;
|
|
|
|
|
y = (float)Math.Asin(Clamp(mat.M13, -1, 1));
|
|
|
|
|
|
|
|
|
|
if (Math.Abs(mat.M13) < 0.99999)
|
|
|
|
|
{
|
|
|
|
|
x = (float)Math.Atan2(-mat.M23, mat.M33);
|
|
|
|
|
z = (float)Math.Atan2(-mat.M12, mat.M11);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
x = (float)Math.Atan2(mat.M32, mat.M22);
|
|
|
|
|
z = 0;
|
|
|
|
|
}
|
|
|
|
|
return new Vector3(x, y, z) * -1;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-06 23:20:42 +00:00
|
|
|
|
public static Quaternion FromEulerAngles(Vector3 rotation)
|
|
|
|
|
{
|
|
|
|
|
Quaternion xRotation = Quaternion.FromAxisAngle(Vector3.UnitX, rotation.X);
|
|
|
|
|
Quaternion yRotation = Quaternion.FromAxisAngle(Vector3.UnitY, rotation.Y);
|
|
|
|
|
Quaternion zRotation = Quaternion.FromAxisAngle(Vector3.UnitZ, rotation.Z);
|
|
|
|
|
Quaternion q = (zRotation * yRotation * xRotation);
|
|
|
|
|
|
|
|
|
|
if (q.W < 0)
|
|
|
|
|
q *= -1;
|
|
|
|
|
|
|
|
|
|
return q;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-27 23:33:14 +00:00
|
|
|
|
public static Matrix4 RotationFromTo(Vector3 start, Vector3 end)
|
|
|
|
|
{
|
|
|
|
|
var axis = Vector3.Cross(start, end).Normalized();
|
|
|
|
|
var angle = (float)Math.Acos(Vector3.Dot(start, end));
|
|
|
|
|
return Matrix4.CreateFromAxisAngle(axis, angle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Quaternion QuatRotationFromTo(Vector3 start, Vector3 end)
|
|
|
|
|
{
|
|
|
|
|
var axis = Vector3.Cross(start, end).Normalized();
|
|
|
|
|
var angle = (float)Math.Acos(Vector3.Dot(start, end));
|
|
|
|
|
return Quaternion.FromAxisAngle(axis, angle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Vector3 GetEulerAngle(Matrix4 m)
|
|
|
|
|
{
|
|
|
|
|
float pitch, yaw, roll; // 3 angles
|
|
|
|
|
yaw = Rad2Deg * (float)Math.Asin(GetValue(m, 8));
|
|
|
|
|
if (GetValue(m, 10) < 0)
|
|
|
|
|
{
|
|
|
|
|
if (yaw >= 0) yaw = 180.0f - yaw;
|
|
|
|
|
else yaw = -180.0f - yaw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// find roll (around z-axis) and pitch (around x-axis)
|
|
|
|
|
// if forward vector is (1,0,0) or (-1,0,0), then m[0]=m[4]=m[9]=m[10]=0
|
|
|
|
|
if (m.M11 > -double.Epsilon && m.M11 < double.Epsilon)
|
|
|
|
|
{
|
|
|
|
|
roll = 0; //@@ assume roll=0
|
|
|
|
|
pitch = Rad2Deg * (float)Math.Atan2(GetValue(m, 1), GetValue(m, 5));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
roll = Rad2Deg * (float)Math.Atan2(-GetValue(m, 4), GetValue(m, 0));
|
|
|
|
|
pitch = Rad2Deg * (float)Math.Atan2(-GetValue(m, 9), GetValue(m, 10));
|
|
|
|
|
}
|
|
|
|
|
return new Vector3(pitch, yaw, roll) * Deg2Rad;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static float GetValue(Matrix4 mat, int index)
|
|
|
|
|
{
|
|
|
|
|
switch (index)
|
|
|
|
|
{
|
|
|
|
|
case 0: return mat.M11;
|
|
|
|
|
case 1: return mat.M12;
|
|
|
|
|
case 2: return mat.M13;
|
|
|
|
|
case 3: return mat.M14;
|
|
|
|
|
case 4: return mat.M21;
|
|
|
|
|
case 5: return mat.M22;
|
|
|
|
|
case 6: return mat.M23;
|
|
|
|
|
case 7: return mat.M24;
|
|
|
|
|
case 8: return mat.M31;
|
|
|
|
|
case 9: return mat.M32;
|
|
|
|
|
case 10: return mat.M33;
|
|
|
|
|
case 11: return mat.M34;
|
|
|
|
|
case 12: return mat.M41;
|
|
|
|
|
case 13: return mat.M42;
|
|
|
|
|
case 14: return mat.M43;
|
|
|
|
|
case 15: return mat.M44;
|
|
|
|
|
default:
|
|
|
|
|
throw new Exception("Invalid index for 4x4 matrix!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-26 14:56:23 +00:00
|
|
|
|
public static float Clamp(float v, float min, float max)
|
|
|
|
|
{
|
|
|
|
|
if (v < min) return min;
|
|
|
|
|
if (v > max) return max;
|
|
|
|
|
return v;
|
|
|
|
|
}
|
2019-05-08 20:28:04 +00:00
|
|
|
|
}
|
|
|
|
|
}
|