mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
Remove redundant custom math types (#6078)
Vector3, Vector4, Matrix4, and Quaternion are now gone. Use System.Numerics instead. This commit is just replacing usages, cleaning up using declarations, and moving over the (couple) helpers that are actually important.
This commit is contained in:
committed by
GitHub
parent
fee67b648c
commit
cdd3afaa4c
@@ -3,8 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Animations;
|
||||
using Robust.Shared.Maths;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Client.Animations
|
||||
{
|
||||
@@ -122,9 +120,9 @@ namespace Robust.Client.Animations
|
||||
case Vector2 vector2:
|
||||
return Vector2Helpers.InterpolateCubic((Vector2) preA, vector2, (Vector2) b, (Vector2) postB, t);
|
||||
case Vector3 vector3:
|
||||
return Vector3.InterpolateCubic((Vector3) preA, vector3, (Vector3) b, (Vector3) postB, t);
|
||||
return VectorHelpers.InterpolateCubic((Vector3) preA, vector3, (Vector3) b, (Vector3) postB, t);
|
||||
case Vector4 vector4:
|
||||
return Vector4.InterpolateCubic((Vector4) preA, vector4, (Vector4) b, (Vector4) postB, t);
|
||||
return VectorHelpers.InterpolateCubic((Vector4) preA, vector4, (Vector4) b, (Vector4) postB, t);
|
||||
case float f:
|
||||
return MathHelper.InterpolateCubic((float) preA, f, (float) b, (float) postB, t);
|
||||
case double d:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using OpenTK.Audio.OpenAL.Extensions.Creative.EFX;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Effects;
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace Robust.Client.Console
|
||||
MouseFilter = MouseFilterMode.Stop;
|
||||
Result = result;
|
||||
var compl = new FormattedMessage();
|
||||
var dim = Color.FromHsl((0f, 0f, 0.8f, 1f));
|
||||
var dim = Color.FromHsl(new Vector4(0f, 0f, 0.8f, 1f));
|
||||
|
||||
// warning: ew ahead
|
||||
string basen = "default";
|
||||
|
||||
@@ -30,8 +30,6 @@ using Robust.Shared.ViewVariables;
|
||||
using DrawDepthTag = Robust.Shared.GameObjects.DrawDepth;
|
||||
using static Robust.Shared.Serialization.TypeSerializers.Implementations.SpriteSpecifierSerializer;
|
||||
using Direction = Robust.Shared.Maths.Direction;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
using SysVec4 = System.Numerics.Vector4;
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
|
||||
@@ -7,8 +7,6 @@ using Robust.Shared.Graphics.RSI;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
using static Robust.Client.GameObjects.SpriteComponent;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
using SysVec4 = System.Numerics.Vector4;
|
||||
|
||||
namespace Robust.Client.GameObjects;
|
||||
|
||||
@@ -157,7 +155,7 @@ public sealed partial class SpriteSystem
|
||||
// Negative color modulation values are by the default shader to disable light shading.
|
||||
// Specifically we set colour = - 1 - colour
|
||||
// This is good enough to ensure that non-negative values become negative & is trivially invertible.
|
||||
layerColor = new(new SysVec4(-1) - layerColor.RGBA);
|
||||
layerColor = new(new Vector4(-1) - layerColor.RGBA);
|
||||
}
|
||||
|
||||
drawingHandle.DrawTextureRectRegion(texture, quad, layerColor);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using OpenToolkit.Graphics.OpenGL4;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.Enums;
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Maths;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
|
||||
namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
|
||||
@@ -18,7 +18,6 @@ using Robust.Shared.Graphics;
|
||||
using static Robust.Shared.GameObjects.OccluderComponent;
|
||||
using Robust.Shared.Utility;
|
||||
using TextureWrapMode = Robust.Shared.Graphics.TextureWrapMode;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
|
||||
@@ -11,8 +11,6 @@ using Robust.Shared.Graphics;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
using TKStencilOp = OpenToolkit.Graphics.OpenGL4.StencilOp;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
@@ -541,7 +539,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
case Matrix3x2 matrix3:
|
||||
program.SetUniform(name, matrix3);
|
||||
break;
|
||||
case Matrix4 matrix4:
|
||||
case Matrix4x4 matrix4:
|
||||
program.SetUniform(name, matrix4);
|
||||
break;
|
||||
case ClydeTexture clydeTexture:
|
||||
|
||||
@@ -10,8 +10,6 @@ using Robust.Shared.Graphics;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
@@ -528,7 +526,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
data.Parameters[name] = value;
|
||||
}
|
||||
|
||||
private protected override void SetParameterImpl(string name, in Matrix4 value)
|
||||
private protected override void SetParameterImpl(string name, in Matrix4x4 value)
|
||||
{
|
||||
var data = Parent._shaderInstances[Handle];
|
||||
data.ParametersDirty = true;
|
||||
|
||||
@@ -17,8 +17,6 @@ using Robust.Shared.Timing;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using Color = Robust.Shared.Maths.Color;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
@@ -398,7 +396,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
}
|
||||
|
||||
private protected override void SetParameterImpl(string name, in Matrix4 value)
|
||||
private protected override void SetParameterImpl(string name, in Matrix4x4 value)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@ using System.Runtime.CompilerServices;
|
||||
using OpenToolkit.Graphics.OpenGL4;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
@@ -277,20 +275,20 @@ namespace Robust.Client.Graphics.Clyde
|
||||
_clyde.CheckGlError();
|
||||
}
|
||||
|
||||
public void SetUniform(string uniformName, in Matrix4 matrix, bool transpose=true)
|
||||
public void SetUniform(string uniformName, in Matrix4x4 matrix, bool transpose=true)
|
||||
{
|
||||
var uniformId = GetUniform(uniformName);
|
||||
SetUniformDirect(uniformId, matrix, transpose);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private unsafe void SetUniformDirect(int uniformId, in Matrix4 value, bool transpose=true)
|
||||
private unsafe void SetUniformDirect(int uniformId, in Matrix4x4 value, bool transpose=true)
|
||||
{
|
||||
Matrix4 tmpTranspose = value;
|
||||
Matrix4x4 tmpTranspose = value;
|
||||
if (transpose)
|
||||
{
|
||||
// transposition not supported on GLES2, & no access to _hasGLES
|
||||
tmpTranspose.Transpose();
|
||||
tmpTranspose = Matrix4x4.Transpose(value);
|
||||
}
|
||||
GL.UniformMatrix4(uniformId, 1, false, (float*) &tmpTranspose);
|
||||
_clyde.CheckGlError();
|
||||
@@ -551,7 +549,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
}
|
||||
}
|
||||
|
||||
public void SetUniformMaybe(string uniformName, in Matrix4 value, bool transpose=true)
|
||||
public void SetUniformMaybe(string uniformName, in Matrix4x4 value, bool transpose=true)
|
||||
{
|
||||
if (TryGetUniform(uniformName, out var slot))
|
||||
{
|
||||
|
||||
@@ -4,8 +4,6 @@ using Robust.Shared.Graphics;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Client.Graphics
|
||||
{
|
||||
@@ -169,7 +167,7 @@ namespace Robust.Client.Graphics
|
||||
SetParameterImpl(name, value);
|
||||
}
|
||||
|
||||
public void SetParameter(string name, in Matrix4 value)
|
||||
public void SetParameter(string name, in Matrix4x4 value)
|
||||
{
|
||||
EnsureAlive();
|
||||
EnsureMutable();
|
||||
@@ -236,7 +234,7 @@ namespace Robust.Client.Graphics
|
||||
private protected abstract void SetParameterImpl(string name, bool value);
|
||||
private protected abstract void SetParameterImpl(string name, bool[] value);
|
||||
private protected abstract void SetParameterImpl(string name, in Matrix3x2 value);
|
||||
private protected abstract void SetParameterImpl(string name, in Matrix4 value);
|
||||
private protected abstract void SetParameterImpl(string name, in Matrix4x4 value);
|
||||
private protected abstract void SetParameterImpl(string name, Texture value);
|
||||
private protected abstract void SetStencilImpl(StencilParameters value);
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@ using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Client.Graphics
|
||||
{
|
||||
@@ -222,7 +220,7 @@ namespace Robust.Client.Graphics
|
||||
case Matrix3x2 i:
|
||||
instance.SetParameter(key, i);
|
||||
break;
|
||||
case Matrix4 i:
|
||||
case Matrix4x4 i:
|
||||
instance.SetParameter(key, i);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Map;
|
||||
using Vector2 = System.Numerics.Vector2;
|
||||
|
||||
namespace Robust.Client.Placement.Modes
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Map;
|
||||
using Vector2 = System.Numerics.Vector2;
|
||||
|
||||
namespace Robust.Client.Placement.Modes
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.ColorNaming;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
|
||||
@@ -21,19 +21,19 @@ public sealed class ColorSelectorStyleBox : StyleBoxTexture
|
||||
/// <summary>
|
||||
/// Base background colour.
|
||||
/// </summary>
|
||||
public Robust.Shared.Maths.Vector4 BaseColor;
|
||||
public Vector4 BaseColor;
|
||||
|
||||
/// <summary>
|
||||
/// Colour to add to the background colour along the X-axis.
|
||||
/// I.e., from left to right the background colour will vary from (BaseColour) to (BaseColour + XAxis)
|
||||
/// </summary>
|
||||
public Robust.Shared.Maths.Vector4 XAxis;
|
||||
public Vector4 XAxis;
|
||||
|
||||
/// <summary>
|
||||
/// Colour to add to the background colour along the y-axis.
|
||||
/// I.e., from left to right the background colour will vary from (BaseColour) to (BaseColour + XAxis)
|
||||
/// </summary>
|
||||
public Robust.Shared.Maths.Vector4 YAxis;
|
||||
public Vector4 YAxis;
|
||||
|
||||
/// <summary>
|
||||
/// If true, then <see cref="BaseColor"/>, <see cref="XAxis"/>, and <see cref="YAxis"/> will be interpreted as HSVa
|
||||
@@ -93,14 +93,14 @@ public sealed class ColorSelectorStyleBox : StyleBoxTexture
|
||||
{
|
||||
var colorData = Hsv
|
||||
? Color.ToHsv(color)
|
||||
: new Robust.Shared.Maths.Vector4(color.R, color.G, color.B, color.A);
|
||||
: new Vector4(color.R, color.G, color.B, color.A);
|
||||
SetBaseColor(colorData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method that sets the base color by taking in some color and removing the components that are controlled by the x and y axes.
|
||||
/// </summary>
|
||||
public void SetBaseColor(Robust.Shared.Maths.Vector4 colorData)
|
||||
public void SetBaseColor(Vector4 colorData)
|
||||
{
|
||||
BaseColor = colorData - colorData * XAxis - colorData * YAxis;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ using Robust.Shared.Maths;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using Vector2 = System.Numerics.Vector2;
|
||||
|
||||
namespace Robust.Client.UserInterface.Controls;
|
||||
|
||||
|
||||
@@ -29,12 +29,11 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Utility;
|
||||
using SysVector3 = System.Numerics.Vector3;
|
||||
using SysVector4 = System.Numerics.Vector4;
|
||||
|
||||
namespace Robust.Shared.Maths
|
||||
{
|
||||
@@ -69,7 +68,7 @@ namespace Robust.Shared.Maths
|
||||
/// Vector representation, for easy SIMD operations.
|
||||
/// </summary>
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public readonly SysVector4 RGBA => Unsafe.BitCast<Color, SysVector4>(this);
|
||||
public readonly Vector4 RGBA => Unsafe.BitCast<Color, Vector4>(this);
|
||||
|
||||
public readonly byte RByte => (byte) (R * byte.MaxValue);
|
||||
public readonly byte GByte => (byte) (G * byte.MaxValue);
|
||||
@@ -94,9 +93,9 @@ namespace Robust.Shared.Maths
|
||||
/// <summary>
|
||||
/// Constructs a new Color structure from the components in a <see cref="SysVector4"/>.
|
||||
/// </summary>
|
||||
public Color(in SysVector4 vec)
|
||||
public Color(in Vector4 vec)
|
||||
{
|
||||
this = Unsafe.BitCast<SysVector4, Color>(vec);
|
||||
this = Unsafe.BitCast<Vector4, Color>(vec);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -905,7 +904,7 @@ namespace Robust.Shared.Maths
|
||||
var m = (1 - g - k) / (1 - k);
|
||||
var y = (1 - b - k) / (1 - k);
|
||||
|
||||
return (c, m, y, k);
|
||||
return new Vector4(c, m, y, k);
|
||||
}
|
||||
|
||||
public static Color FromCmyk(Vector4 cmyk)
|
||||
@@ -932,7 +931,7 @@ namespace Robust.Shared.Maths
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Color InterpolateBetween(Color α, Color β, float λ)
|
||||
{
|
||||
return new(SysVector4.Lerp(α.RGBA, β.RGBA, λ));
|
||||
return new(Vector4.Lerp(α.RGBA, β.RGBA, λ));
|
||||
}
|
||||
|
||||
public static Color? TryFromHex(ReadOnlySpan<char> hexColor)
|
||||
@@ -1007,10 +1006,10 @@ namespace Robust.Shared.Maths
|
||||
|
||||
public static Color Blend(Color dstColor, Color srcColor, BlendFactor dstFactor, BlendFactor srcFactor)
|
||||
{
|
||||
var dst = new SysVector3(dstColor.R, dstColor.G, dstColor.B);
|
||||
var src = new SysVector3(srcColor.R, srcColor.G, srcColor.B);
|
||||
var dst = new Vector3(dstColor.R, dstColor.G, dstColor.B);
|
||||
var src = new Vector3(srcColor.R, srcColor.G, srcColor.B);
|
||||
|
||||
var ret = new SysVector3();
|
||||
var ret = new Vector3();
|
||||
|
||||
switch (dstFactor)
|
||||
{
|
||||
@@ -1023,13 +1022,13 @@ namespace Robust.Shared.Maths
|
||||
ret = dst * src;
|
||||
break;
|
||||
case BlendFactor.OneMinusSrcColor:
|
||||
ret = dst * (SysVector3.One - src);
|
||||
ret = dst * (Vector3.One - src);
|
||||
break;
|
||||
case BlendFactor.DstColor:
|
||||
ret = dst * dst;
|
||||
break;
|
||||
case BlendFactor.OneMinusDstColor:
|
||||
ret = dst * (SysVector3.One - dst);
|
||||
ret = dst * (Vector3.One - dst);
|
||||
break;
|
||||
case BlendFactor.SrcAlpha:
|
||||
ret = dst * srcColor.A;
|
||||
@@ -1058,13 +1057,13 @@ namespace Robust.Shared.Maths
|
||||
ret += src * src;
|
||||
break;
|
||||
case BlendFactor.OneMinusSrcColor:
|
||||
ret += src * (SysVector3.One - src);
|
||||
ret += src * (Vector3.One - src);
|
||||
break;
|
||||
case BlendFactor.DstColor:
|
||||
ret += src * dst;
|
||||
break;
|
||||
case BlendFactor.OneMinusDstColor:
|
||||
ret += src * (SysVector3.One - dst);
|
||||
ret += src * (Vector3.One - dst);
|
||||
break;
|
||||
case BlendFactor.SrcAlpha:
|
||||
ret += src * srcColor.A;
|
||||
|
||||
@@ -15,7 +15,6 @@ using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Vec4 = System.Numerics.Vector4;
|
||||
|
||||
namespace Robust.Shared.Maths
|
||||
{
|
||||
@@ -530,13 +529,13 @@ namespace Robust.Shared.Maths
|
||||
/// Returns whether two vectors are within <paramref name="percentage"/> of each other
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool CloseToPercent(Vec4 a, Vec4 b, float percentage = .00001f)
|
||||
public static bool CloseToPercent(Vector4 a, Vector4 b, float percentage = .00001f)
|
||||
{
|
||||
a = Vec4.Abs(a);
|
||||
b = Vec4.Abs(b);
|
||||
var p = new Vec4(percentage);
|
||||
var epsilon = Vec4.Max(Vec4.Max(a, b) * p, p);
|
||||
var delta = Vec4.Abs(a - b);
|
||||
a = Vector4.Abs(a);
|
||||
b = Vector4.Abs(b);
|
||||
var p = new Vector4(percentage);
|
||||
var epsilon = Vector4.Max(Vector4.Max(a, b) * p, p);
|
||||
var delta = Vector4.Abs(a - b);
|
||||
return delta.X <= epsilon.X && delta.Y <= epsilon.Y && delta.Z <= epsilon.Z && delta.W <= epsilon.W;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,978 +0,0 @@
|
||||
#region --- License ---
|
||||
|
||||
/*
|
||||
Copyright (c) 2006 - 2008 The Open Toolkit library.
|
||||
Copyright 2013 Xamarin Inc
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#endregion --- License ---
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Xml.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Shared.Maths
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a Quaternion.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Quaternion : IEquatable<Quaternion>, ISpanFormattable
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private Vector3 xyz;
|
||||
private float w;
|
||||
|
||||
#endregion Fields
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Quaternion from vector and w components
|
||||
/// </summary>
|
||||
/// <param name="v">The vector part</param>
|
||||
/// <param name="w">The w part</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Quaternion(Vector3 v, float w)
|
||||
{
|
||||
xyz = v;
|
||||
this.w = w;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Quaternion
|
||||
/// </summary>
|
||||
/// <param name="x">The x component</param>
|
||||
/// <param name="y">The y component</param>
|
||||
/// <param name="z">The z component</param>
|
||||
/// <param name="w">The w component</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Quaternion(float x, float y, float z, float w)
|
||||
: this(new Vector3(x, y, z), w) { }
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Quaternion(ref Matrix3x2 matrix)
|
||||
{
|
||||
var scale = Math.Pow(matrix.GetDeterminant(), 1.0d / 3.0d);
|
||||
float x, y, z;
|
||||
|
||||
w = (float) (Math.Sqrt(Math.Max(0, scale + matrix[0, 0] + matrix[1, 1] + matrix[2, 2])) / 2);
|
||||
x = (float) (Math.Sqrt(Math.Max(0, scale + matrix[0, 0] - matrix[1, 1] - matrix[2, 2])) / 2);
|
||||
y = (float) (Math.Sqrt(Math.Max(0, scale - matrix[0, 0] + matrix[1, 1] - matrix[2, 2])) / 2);
|
||||
z = (float) (Math.Sqrt(Math.Max(0, scale - matrix[0, 0] - matrix[1, 1] + matrix[2, 2])) / 2);
|
||||
|
||||
xyz = new Vector3(x, y, z);
|
||||
|
||||
if (matrix[2, 1] - matrix[1, 2] < 0) X = -X;
|
||||
if (matrix[0, 2] - matrix[2, 0] < 0) Y = -Y;
|
||||
if (matrix[1, 0] - matrix[0, 1] < 0) Z = -Z;
|
||||
}
|
||||
|
||||
#endregion Constructors
|
||||
|
||||
#region Public Members
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an OpenTK.Vector3 with the X, Y and Z components of this instance.
|
||||
/// </summary>
|
||||
public Vector3 Xyz
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => xyz;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
set => xyz = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the X component of this instance.
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public float X
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => xyz.X;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
set => xyz.X = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Y component of this instance.
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public float Y
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => xyz.Y;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
set => xyz.Y = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Z component of this instance.
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public float Z
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => xyz.Z;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
set => xyz.Z = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the W component of this instance.
|
||||
/// </summary>
|
||||
public float W
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => w;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
set => w = value;
|
||||
}
|
||||
|
||||
public float x
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => xyz.X;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
set => xyz.X = value;
|
||||
}
|
||||
|
||||
public float y
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => xyz.Y;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
set => xyz.Y = value;
|
||||
}
|
||||
|
||||
public float z
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => xyz.Z;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
set => xyz.Z = value;
|
||||
}
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Instance
|
||||
|
||||
#region ToAxisAngle
|
||||
|
||||
/// <summary>
|
||||
/// Convert the current quaternion to axis angle representation
|
||||
/// </summary>
|
||||
/// <param name="axis">The resultant axis</param>
|
||||
/// <param name="angle">The resultant angle</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ToAxisAngle(out Vector3 axis, out float angle)
|
||||
{
|
||||
var result = ToAxisAngle();
|
||||
axis = result.Xyz;
|
||||
angle = result.W;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert this instance to an axis-angle representation.
|
||||
/// </summary>
|
||||
/// <returns>A Vector4 that is the axis-angle representation of this quaternion.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Vector4 ToAxisAngle()
|
||||
{
|
||||
var q = this;
|
||||
if (Math.Abs(q.W) > 1.0f)
|
||||
q.Normalize();
|
||||
|
||||
var result = new Vector4();
|
||||
|
||||
result.W = 2.0f * (float) Math.Acos(q.W); // angle
|
||||
var den = (float) Math.Sqrt(1.0 - q.W * q.W);
|
||||
if (den > 0.0001f)
|
||||
{
|
||||
result.Xyz = q.Xyz / den;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This occurs when the angle is zero.
|
||||
// Not a problem: just set an arbitrary normalized axis.
|
||||
result.Xyz = Vector3.UnitX;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion ToAxisAngle
|
||||
|
||||
#region public float Length
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length (magnitude) of the quaternion.
|
||||
/// </summary>
|
||||
/// <seealso cref="LengthSquared"/>
|
||||
public float Length
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => (float) Math.Sqrt(W * W + Xyz.LengthSquared);
|
||||
}
|
||||
|
||||
#endregion public float Length
|
||||
|
||||
#region public float LengthSquared
|
||||
|
||||
/// <summary>
|
||||
/// Gets the square of the quaternion length (magnitude).
|
||||
/// </summary>
|
||||
public float LengthSquared
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => W * W + Xyz.LengthSquared;
|
||||
}
|
||||
|
||||
#endregion public float LengthSquared
|
||||
|
||||
#region public void Normalize()
|
||||
|
||||
/// <summary>
|
||||
/// Scales the Quaternion to unit length.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Normalize()
|
||||
{
|
||||
var scale = 1.0f / Length;
|
||||
Xyz *= scale;
|
||||
W *= scale;
|
||||
}
|
||||
|
||||
#endregion public void Normalize()
|
||||
|
||||
#region public void Conjugate()
|
||||
|
||||
/// <summary>
|
||||
/// Convert this quaternion to its conjugate
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Conjugate()
|
||||
{
|
||||
Xyz = -Xyz;
|
||||
}
|
||||
|
||||
#endregion public void Conjugate()
|
||||
|
||||
#endregion Instance
|
||||
|
||||
#region Static
|
||||
|
||||
#region Fields
|
||||
|
||||
private const float RadToDeg = (float) (180.0 / Math.PI);
|
||||
private const float DegToRad = (float) (Math.PI / 180.0);
|
||||
|
||||
/// <summary>
|
||||
/// Defines the identity quaternion.
|
||||
/// </summary>
|
||||
public static readonly Quaternion Identity = new(0, 0, 0, 1);
|
||||
|
||||
#endregion Fields
|
||||
|
||||
#region Add
|
||||
|
||||
/// <summary>
|
||||
/// Add two quaternions
|
||||
/// </summary>
|
||||
/// <param name="left">The first operand</param>
|
||||
/// <param name="right">The second operand</param>
|
||||
/// <returns>The result of the addition</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion Add(Quaternion left, Quaternion right)
|
||||
{
|
||||
return new(
|
||||
left.Xyz + right.Xyz,
|
||||
left.W + right.W);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add two quaternions
|
||||
/// </summary>
|
||||
/// <param name="left">The first operand</param>
|
||||
/// <param name="right">The second operand</param>
|
||||
/// <param name="result">The result of the addition</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Add(ref Quaternion left, ref Quaternion right, out Quaternion result)
|
||||
{
|
||||
result = new Quaternion(
|
||||
left.Xyz + right.Xyz,
|
||||
left.W + right.W);
|
||||
}
|
||||
|
||||
#endregion Add
|
||||
|
||||
#region Sub
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts two instances.
|
||||
/// </summary>
|
||||
/// <param name="left">The left instance.</param>
|
||||
/// <param name="right">The right instance.</param>
|
||||
/// <returns>The result of the operation.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion Sub(Quaternion left, Quaternion right)
|
||||
{
|
||||
return new(
|
||||
left.Xyz - right.Xyz,
|
||||
left.W - right.W);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts two instances.
|
||||
/// </summary>
|
||||
/// <param name="left">The left instance.</param>
|
||||
/// <param name="right">The right instance.</param>
|
||||
/// <param name="result">The result of the operation.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Sub(ref Quaternion left, ref Quaternion right, out Quaternion result)
|
||||
{
|
||||
result = new Quaternion(
|
||||
left.Xyz - right.Xyz,
|
||||
left.W - right.W);
|
||||
}
|
||||
|
||||
#endregion Sub
|
||||
|
||||
#region Mult
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies two instances.
|
||||
/// </summary>
|
||||
/// <param name="left">The first instance.</param>
|
||||
/// <param name="right">The second instance.</param>
|
||||
/// <returns>A new instance containing the result of the calculation.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion Multiply(Quaternion left, Quaternion right)
|
||||
{
|
||||
Multiply(ref left, ref right, out var result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies two instances.
|
||||
/// </summary>
|
||||
/// <param name="left">The first instance.</param>
|
||||
/// <param name="right">The second instance.</param>
|
||||
/// <param name="result">A new instance containing the result of the calculation.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Multiply(ref Quaternion left, ref Quaternion right, out Quaternion result)
|
||||
{
|
||||
result = new Quaternion(
|
||||
right.W * left.Xyz + left.W * right.Xyz + Vector3.Cross(left.Xyz, right.Xyz),
|
||||
left.W * right.W - Vector3.Dot(left.Xyz, right.Xyz));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies an instance by a scalar.
|
||||
/// </summary>
|
||||
/// <param name="quaternion">The instance.</param>
|
||||
/// <param name="scale">The scalar.</param>
|
||||
/// <param name="result">A new instance containing the result of the calculation.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Multiply(ref Quaternion quaternion, float scale, out Quaternion result)
|
||||
{
|
||||
result = new Quaternion(quaternion.X * scale, quaternion.Y * scale, quaternion.Z * scale, quaternion.W * scale);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies an instance by a scalar.
|
||||
/// </summary>
|
||||
/// <param name="quaternion">The instance.</param>
|
||||
/// <param name="scale">The scalar.</param>
|
||||
/// <returns>A new instance containing the result of the calculation.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion Multiply(Quaternion quaternion, float scale)
|
||||
{
|
||||
return new(quaternion.X * scale, quaternion.Y * scale, quaternion.Z * scale, quaternion.W * scale);
|
||||
}
|
||||
|
||||
#endregion Mult
|
||||
|
||||
#region Dot
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the dot product between two Quaternions.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float Dot(Quaternion a, Quaternion b)
|
||||
{
|
||||
return a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W;
|
||||
}
|
||||
|
||||
#endregion Dot
|
||||
|
||||
#region Conjugate
|
||||
|
||||
/// <summary>
|
||||
/// Get the conjugate of the given quaternion
|
||||
/// </summary>
|
||||
/// <param name="q">The quaternion</param>
|
||||
/// <returns>The conjugate of the given quaternion</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion Conjugate(Quaternion q)
|
||||
{
|
||||
return new(-q.Xyz, q.W);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the conjugate of the given quaternion
|
||||
/// </summary>
|
||||
/// <param name="q">The quaternion</param>
|
||||
/// <param name="result">The conjugate of the given quaternion</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Conjugate(ref Quaternion q, out Quaternion result)
|
||||
{
|
||||
result = new Quaternion(-q.Xyz, q.W);
|
||||
}
|
||||
|
||||
#endregion Conjugate
|
||||
|
||||
#region Invert
|
||||
|
||||
/// <summary>
|
||||
/// Get the inverse of the given quaternion
|
||||
/// </summary>
|
||||
/// <param name="q">The quaternion to invert</param>
|
||||
/// <returns>The inverse of the given quaternion</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion Invert(Quaternion q)
|
||||
{
|
||||
Invert(ref q, out var result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the inverse of the given quaternion
|
||||
/// </summary>
|
||||
/// <param name="q">The quaternion to invert</param>
|
||||
/// <param name="result">The inverse of the given quaternion</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Invert(ref Quaternion q, out Quaternion result)
|
||||
{
|
||||
var lengthSq = q.LengthSquared;
|
||||
if (lengthSq != 0.0)
|
||||
{
|
||||
var i = 1.0f / lengthSq;
|
||||
result = new Quaternion(q.Xyz * -i, q.W * i);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = q;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Invert
|
||||
|
||||
#region Normalize
|
||||
|
||||
/// <summary>
|
||||
/// Scale the given quaternion to unit length
|
||||
/// </summary>
|
||||
/// <param name="q">The quaternion to normalize</param>
|
||||
/// <returns>The normalized quaternion</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion Normalize(Quaternion q)
|
||||
{
|
||||
Normalize(ref q, out var result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scale the given quaternion to unit length
|
||||
/// </summary>
|
||||
/// <param name="q">The quaternion to normalize</param>
|
||||
/// <param name="result">The normalized quaternion</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Normalize(ref Quaternion q, out Quaternion result)
|
||||
{
|
||||
var scale = 1.0f / q.Length;
|
||||
result = new Quaternion(q.Xyz * scale, q.W * scale);
|
||||
}
|
||||
|
||||
#endregion Normalize
|
||||
|
||||
#region FromAxisAngle
|
||||
|
||||
/// <summary>
|
||||
/// Build a quaternion from the given axis and angle
|
||||
/// </summary>
|
||||
/// <param name="axis">The axis to rotate about</param>
|
||||
/// <param name="angle">The rotation angle in radians</param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion FromAxisAngle(Vector3 axis, float angle)
|
||||
{
|
||||
if (axis.LengthSquared == 0.0f)
|
||||
return Identity;
|
||||
|
||||
var result = Identity;
|
||||
|
||||
angle *= 0.5f;
|
||||
axis.Normalize();
|
||||
result.Xyz = axis * (float) Math.Sin(angle);
|
||||
result.W = (float) Math.Cos(angle);
|
||||
|
||||
return Normalize(result);
|
||||
}
|
||||
|
||||
#endregion FromAxisAngle
|
||||
|
||||
#region Slerp
|
||||
|
||||
/// <summary>
|
||||
/// Do Spherical linear interpolation between two quaternions
|
||||
/// </summary>
|
||||
/// <param name="q1">The first quaternion</param>
|
||||
/// <param name="q2">The second quaternion</param>
|
||||
/// <param name="blend">The blend factor</param>
|
||||
/// <returns>A smooth blend between the given quaternions</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion Slerp(Quaternion q1, Quaternion q2, float blend)
|
||||
{
|
||||
// if either input is zero, return the other.
|
||||
if (q1.LengthSquared == 0.0f)
|
||||
{
|
||||
if (q2.LengthSquared == 0.0f)
|
||||
{
|
||||
return Identity;
|
||||
}
|
||||
|
||||
return q2;
|
||||
}
|
||||
|
||||
if (q2.LengthSquared == 0.0f)
|
||||
{
|
||||
return q1;
|
||||
}
|
||||
|
||||
var cosHalfAngle = q1.W * q2.W + Vector3.Dot(q1.Xyz, q2.Xyz);
|
||||
|
||||
if (cosHalfAngle >= 1.0f || cosHalfAngle <= -1.0f)
|
||||
{
|
||||
// angle = 0.0f, so just return one input.
|
||||
return q1;
|
||||
}
|
||||
|
||||
if (cosHalfAngle < 0.0f)
|
||||
{
|
||||
q2.Xyz = -q2.Xyz;
|
||||
q2.W = -q2.W;
|
||||
cosHalfAngle = -cosHalfAngle;
|
||||
}
|
||||
|
||||
float blendA;
|
||||
float blendB;
|
||||
if (cosHalfAngle < 0.99f)
|
||||
{
|
||||
// do proper slerp for big angles
|
||||
var halfAngle = (float) Math.Acos(cosHalfAngle);
|
||||
var sinHalfAngle = (float) Math.Sin(halfAngle);
|
||||
var oneOverSinHalfAngle = 1.0f / sinHalfAngle;
|
||||
blendA = (float) Math.Sin(halfAngle * (1.0f - blend)) * oneOverSinHalfAngle;
|
||||
blendB = (float) Math.Sin(halfAngle * blend) * oneOverSinHalfAngle;
|
||||
}
|
||||
else
|
||||
{
|
||||
// do lerp if angle is really small.
|
||||
blendA = 1.0f - blend;
|
||||
blendB = blend;
|
||||
}
|
||||
|
||||
var result = new Quaternion(blendA * q1.Xyz + blendB * q2.Xyz, blendA * q1.W + blendB * q2.W);
|
||||
if (result.LengthSquared > 0.0f)
|
||||
return Normalize(result);
|
||||
return Identity;
|
||||
}
|
||||
|
||||
#endregion Slerp
|
||||
|
||||
#region RotateTowards
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta)
|
||||
{
|
||||
var num = Angle(from, to);
|
||||
if (num == 0f)
|
||||
{
|
||||
return to;
|
||||
}
|
||||
|
||||
var t = MathF.Min(1f, maxDegreesDelta / num);
|
||||
return Slerp(from, to, t);
|
||||
}
|
||||
|
||||
#endregion RotateTowards
|
||||
|
||||
#region Angle
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float Angle(Quaternion a, Quaternion b)
|
||||
{
|
||||
var f = Dot(a, b);
|
||||
return (float) (Math.Acos(Math.Min(Math.Abs(f), 1f)) * 2f * RadToDeg);
|
||||
}
|
||||
|
||||
#endregion Angle
|
||||
|
||||
#region LookRotation
|
||||
|
||||
// from http://answers.unity3d.com/questions/467614/what-is-the-source-code-of-quaternionlookrotation.html
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion LookRotation(ref Vector3 forward, ref Vector3 up)
|
||||
{
|
||||
forward = Vector3.Normalize(forward);
|
||||
var right = Vector3.Normalize(Vector3.Cross(up, forward));
|
||||
up = Vector3.Cross(forward, right);
|
||||
var m00 = right.X;
|
||||
var m01 = right.Y;
|
||||
var m02 = right.Z;
|
||||
var m10 = up.X;
|
||||
var m11 = up.Y;
|
||||
var m12 = up.Z;
|
||||
var m20 = forward.X;
|
||||
var m21 = forward.Y;
|
||||
var m22 = forward.Z;
|
||||
|
||||
var num8 = m00 + m11 + m22;
|
||||
var quaternion = new Quaternion();
|
||||
if (num8 > 0f)
|
||||
{
|
||||
var num = MathF.Sqrt(num8 + 1f);
|
||||
quaternion.w = num * 0.5f;
|
||||
num = 0.5f / num;
|
||||
quaternion.X = (m12 - m21) * num;
|
||||
quaternion.Y = (m20 - m02) * num;
|
||||
quaternion.Z = (m01 - m10) * num;
|
||||
return quaternion;
|
||||
}
|
||||
|
||||
if (m00 >= m11 && m00 >= m22)
|
||||
{
|
||||
var num7 = MathF.Sqrt(1f + m00 - m11 - m22);
|
||||
var num4 = 0.5f / num7;
|
||||
quaternion.X = 0.5f * num7;
|
||||
quaternion.Y = (m01 + m10) * num4;
|
||||
quaternion.Z = (m02 + m20) * num4;
|
||||
quaternion.W = (m12 - m21) * num4;
|
||||
return quaternion;
|
||||
}
|
||||
|
||||
if (m11 > m22)
|
||||
{
|
||||
var num6 = MathF.Sqrt(1f + m11 - m00 - m22);
|
||||
var num3 = 0.5f / num6;
|
||||
quaternion.X = (m10 + m01) * num3;
|
||||
quaternion.Y = 0.5f * num6;
|
||||
quaternion.Z = (m21 + m12) * num3;
|
||||
quaternion.W = (m20 - m02) * num3;
|
||||
return quaternion;
|
||||
}
|
||||
|
||||
var num5 = MathF.Sqrt(1f + m22 - m00 - m11);
|
||||
var num2 = 0.5f / num5;
|
||||
quaternion.X = (m20 + m02) * num2;
|
||||
quaternion.Y = (m21 + m12) * num2;
|
||||
quaternion.Z = 0.5f * num5;
|
||||
quaternion.W = (m01 - m10) * num2;
|
||||
return quaternion;
|
||||
}
|
||||
|
||||
#endregion LookRotation
|
||||
|
||||
#region Euler Angles
|
||||
|
||||
// from http://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vector3 ToEulerRad(Quaternion rotation)
|
||||
{
|
||||
var sqw = rotation.w * rotation.w;
|
||||
var sqx = rotation.x * rotation.x;
|
||||
var sqy = rotation.y * rotation.y;
|
||||
var sqz = rotation.z * rotation.z;
|
||||
var unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
|
||||
var test = rotation.x * rotation.w - rotation.y * rotation.z;
|
||||
Vector3 v;
|
||||
|
||||
if (test > 0.4995f * unit)
|
||||
{
|
||||
// singularity at north pole
|
||||
v.Y = 2f * MathF.Atan2(rotation.y, rotation.x);
|
||||
v.X = (float) (Math.PI / 2);
|
||||
v.Z = 0;
|
||||
return NormalizeAngles(v * RadToDeg);
|
||||
}
|
||||
|
||||
if (test < -0.4995f * unit)
|
||||
{
|
||||
// singularity at south pole
|
||||
v.Y = -2f * MathF.Atan2(rotation.y, rotation.x);
|
||||
v.X = (float) (-Math.PI / 2);
|
||||
v.Z = 0;
|
||||
return NormalizeAngles(v * RadToDeg);
|
||||
}
|
||||
|
||||
var q = new Quaternion(rotation.w, rotation.z, rotation.x, rotation.y);
|
||||
v.Y = MathF.Atan2(2f * q.x * q.w + 2f * q.y * q.z, 1 - 2f * (q.z * q.z + q.w * q.w)); // Yaw
|
||||
v.X = MathF.Asin(2f * (q.x * q.z - q.w * q.y)); // Pitch
|
||||
v.Z = MathF.Atan2(2f * q.x * q.y + 2f * q.z * q.w, 1 - 2f * (q.y * q.y + q.z * q.z)); // Roll
|
||||
return NormalizeAngles(v * RadToDeg);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vector3 NormalizeAngles(Vector3 angles)
|
||||
{
|
||||
angles.X = NormalizeAngle(angles.X);
|
||||
angles.Y = NormalizeAngle(angles.Y);
|
||||
angles.Z = NormalizeAngle(angles.Z);
|
||||
return angles;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static float NormalizeAngle(float angle)
|
||||
{
|
||||
/*
|
||||
while (angle > 360)
|
||||
angle -= 360;
|
||||
while (angle < 0)
|
||||
angle += 360;
|
||||
return angle;
|
||||
|
||||
asm:
|
||||
|
||||
L0000: vzeroupper
|
||||
L0003: vucomiss xmm0, [fld 360f]
|
||||
L000b: jbe short L001f
|
||||
L000d: vsubss xmm0, xmm0, [fld 360f]
|
||||
L0015: vucomiss xmm0, [fld 0]
|
||||
L001d: ja short L000d
|
||||
L001f: vxorps xmm1, xmm1, xmm1
|
||||
L0023: vucomiss xmm1, xmm0
|
||||
L0027: jbe short L003b
|
||||
L0029: vaddss xmm0, xmm0, [fld 360f]
|
||||
L0031: vxorps xmm1, xmm1, xmm1
|
||||
L0035: vucomiss xmm1, xmm0
|
||||
L0039: ja short L0029
|
||||
L003b: ret
|
||||
|
||||
*/
|
||||
|
||||
return angle - MathF.Floor(angle * (1/360f)) * 360f;
|
||||
/* asm:
|
||||
L0000: vzeroupper
|
||||
L0003: vmovaps xmm1, xmm0
|
||||
L0007: vmulss xmm1, xmm1, [fld 1/360f]
|
||||
L000f: vroundss xmm1, xmm1, xmm1, 9
|
||||
L0015: vmulss xmm1, xmm1, [fld 360f]
|
||||
L001d: vsubss xmm0, xmm0, xmm1
|
||||
L0021: ret
|
||||
*/
|
||||
}
|
||||
|
||||
#endregion Euler Angles
|
||||
|
||||
#endregion Static
|
||||
|
||||
#region Operators
|
||||
|
||||
/// <summary>
|
||||
/// Adds two instances.
|
||||
/// </summary>
|
||||
/// <param name="left">The first instance.</param>
|
||||
/// <param name="right">The second instance.</param>
|
||||
/// <returns>The result of the calculation.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion operator +(Quaternion left, Quaternion right)
|
||||
{
|
||||
left.Xyz += right.Xyz;
|
||||
left.W += right.W;
|
||||
return left;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts two instances.
|
||||
/// </summary>
|
||||
/// <param name="left">The first instance.</param>
|
||||
/// <param name="right">The second instance.</param>
|
||||
/// <returns>The result of the calculation.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion operator -(Quaternion left, Quaternion right)
|
||||
{
|
||||
left.Xyz -= right.Xyz;
|
||||
left.W -= right.W;
|
||||
return left;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies two instances.
|
||||
/// </summary>
|
||||
/// <param name="left">The first instance.</param>
|
||||
/// <param name="right">The second instance.</param>
|
||||
/// <returns>The result of the calculation.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion operator *(Quaternion left, Quaternion right)
|
||||
{
|
||||
Multiply(ref left, ref right, out left);
|
||||
return left;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies an instance by a scalar.
|
||||
/// </summary>
|
||||
/// <param name="quaternion">The instance.</param>
|
||||
/// <param name="scale">The scalar.</param>
|
||||
/// <returns>A new instance containing the result of the calculation.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion operator *(Quaternion quaternion, float scale)
|
||||
{
|
||||
Multiply(ref quaternion, scale, out quaternion);
|
||||
return quaternion;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies an instance by a scalar.
|
||||
/// </summary>
|
||||
/// <param name="quaternion">The instance.</param>
|
||||
/// <param name="scale">The scalar.</param>
|
||||
/// <returns>A new instance containing the result of the calculation.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion operator *(float scale, Quaternion quaternion)
|
||||
{
|
||||
return new(quaternion.X * scale, quaternion.Y * scale, quaternion.Z * scale, quaternion.W * scale);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares two instances for equality.
|
||||
/// </summary>
|
||||
/// <param name="left">The first instance.</param>
|
||||
/// <param name="right">The second instance.</param>
|
||||
/// <returns>True, if left equals right; false otherwise.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator ==(Quaternion left, Quaternion right)
|
||||
{
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares two instances for inequality.
|
||||
/// </summary>
|
||||
/// <param name="left">The first instance.</param>
|
||||
/// <param name="right">The second instance.</param>
|
||||
/// <returns>True, if left does not equal right; false otherwise.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator !=(Quaternion left, Quaternion right)
|
||||
{
|
||||
return !left.Equals(right);
|
||||
}
|
||||
|
||||
#endregion Operators
|
||||
|
||||
#region Overrides
|
||||
|
||||
#region public override string ToString()
|
||||
|
||||
/// <summary>
|
||||
/// Returns a System.String that represents the current Quaternion.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public readonly override string ToString()
|
||||
{
|
||||
return $"V: {xyz}, W: {w}";
|
||||
}
|
||||
|
||||
public readonly string ToString(string? format, IFormatProvider? formatProvider)
|
||||
{
|
||||
return ToString();
|
||||
}
|
||||
|
||||
public readonly bool TryFormat(
|
||||
Span<char> destination,
|
||||
out int charsWritten,
|
||||
ReadOnlySpan<char> format,
|
||||
IFormatProvider? provider)
|
||||
{
|
||||
return FormatHelpers.TryFormatInto(
|
||||
destination,
|
||||
out charsWritten,
|
||||
$"V: {xyz}, W: {w}");
|
||||
}
|
||||
|
||||
#endregion public override string ToString()
|
||||
|
||||
#region public override bool Equals (object o)
|
||||
|
||||
/// <summary>
|
||||
/// Compares this object instance to another object for equality.
|
||||
/// </summary>
|
||||
/// <param name="obj">The other object to be used in the comparison.</param>
|
||||
/// <returns>True if both objects are Quaternions of equal value. Otherwise it returns false.</returns>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj is Quaternion quaternion) return this == quaternion;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion public override bool Equals (object o)
|
||||
|
||||
#region public override int GetHashCode ()
|
||||
|
||||
/// <summary>
|
||||
/// Provides the hash code for this object.
|
||||
/// </summary>
|
||||
/// <returns>A hash code formed from the bitwise XOR of this objects members.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Xyz.GetHashCode() ^ W.GetHashCode();
|
||||
}
|
||||
|
||||
#endregion public override int GetHashCode ()
|
||||
|
||||
#endregion Overrides
|
||||
|
||||
#endregion Public Members
|
||||
|
||||
#region IEquatable<Quaternion> Members
|
||||
|
||||
/// <summary>
|
||||
/// Compares this Quaternion instance to another Quaternion for equality.
|
||||
/// </summary>
|
||||
/// <param name="other">The other Quaternion to be used in the comparison.</param>
|
||||
/// <returns>True if both instances are equal; false otherwise.</returns>
|
||||
public bool Equals(Quaternion other)
|
||||
{
|
||||
return Xyz == other.Xyz && W == other.W;
|
||||
}
|
||||
|
||||
#endregion IEquatable<Quaternion> Members
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Robust.Shared.Maths
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Robust.Shared.Maths
|
||||
|
||||
31
Robust.Shared.Maths/VectorHelpers.cs
Normal file
31
Robust.Shared.Maths/VectorHelpers.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System.Numerics;
|
||||
|
||||
namespace Robust.Shared.Maths;
|
||||
|
||||
public static class VectorHelpers
|
||||
{
|
||||
public static Vector3 InterpolateCubic(Vector3 preA, Vector3 a, Vector3 b, Vector3 postB, float t)
|
||||
{
|
||||
return a + (b - preA + (preA * 2.0f - a * 5.0f + b * 4.0f - postB + ((a - b) * 3.0f + postB - preA) * t) * t) * t * 0.5f;
|
||||
}
|
||||
|
||||
public static Vector4 InterpolateCubic(Vector4 preA, Vector4 a, Vector4 b, Vector4 postB, float t)
|
||||
{
|
||||
return a + (b - preA + (preA * 2.0f - a * 5.0f + b * 4.0f - postB + ((a - b) * 3.0f + postB - preA) * t) * t) * t * 0.5f;
|
||||
}
|
||||
|
||||
public static void Deconstruct(this Vector3 vector, out float x, out float y, out float z)
|
||||
{
|
||||
x = vector.X;
|
||||
y = vector.Y;
|
||||
z = vector.Z;
|
||||
}
|
||||
|
||||
public static void Deconstruct(this Vector4 vector, out float x, out float y, out float z, out float w)
|
||||
{
|
||||
x = vector.X;
|
||||
y = vector.Y;
|
||||
z = vector.Z;
|
||||
w = vector.W;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Audio.Effects;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Audio.Components;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.Shared.Audio.Effects;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
//
|
||||
|
||||
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.Shared.Audio.Effects;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// of the MIT license. See the LICENSE file for details.
|
||||
//
|
||||
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.Shared.Audio.Effects;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ using Robust.Shared.Maths;
|
||||
using Robust.Shared.Serialization.Markdown;
|
||||
using Robust.Shared.Serialization.Markdown.Mapping;
|
||||
using Robust.Shared.Utility;
|
||||
using Vector2 = System.Numerics.Vector2;
|
||||
|
||||
namespace Robust.Shared.EntitySerialization.Systems;
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
using Vector2 = System.Numerics.Vector2;
|
||||
|
||||
namespace Robust.Shared.EntitySerialization.Systems;
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using JetBrains.Annotations;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Shared.Noise
|
||||
{
|
||||
|
||||
@@ -30,7 +30,6 @@ using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
|
||||
namespace Robust.Shared.Physics.Dynamics.Joints;
|
||||
// Linear constraint (point-to-line)
|
||||
|
||||
@@ -6,7 +6,6 @@ using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
|
||||
namespace Robust.Shared.Physics.Dynamics.Joints;
|
||||
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using NetSerializer;
|
||||
|
||||
namespace Robust.Shared.Serialization;
|
||||
|
||||
internal sealed class Matrix3x2Serializer : IStaticTypeSerializer
|
||||
{
|
||||
public bool Handles(Type type)
|
||||
{
|
||||
return type == typeof(Matrix3x2);
|
||||
}
|
||||
|
||||
public IEnumerable<Type> GetSubtypes(Type type)
|
||||
{
|
||||
return Type.EmptyTypes;
|
||||
}
|
||||
|
||||
public MethodInfo GetStaticWriter(Type type)
|
||||
{
|
||||
return typeof(Matrix3x2Serializer).GetMethod("WritePrimitive",
|
||||
BindingFlags.Static | BindingFlags.Public | BindingFlags.ExactBinding, null,
|
||||
new Type[] { typeof(Stream), type }, null)!;
|
||||
}
|
||||
|
||||
public MethodInfo GetStaticReader(Type type)
|
||||
{
|
||||
return typeof(Matrix3x2Serializer).GetMethod("ReadPrimitive",
|
||||
BindingFlags.Static | BindingFlags.Public | BindingFlags.ExactBinding, null,
|
||||
new Type[] { typeof(Stream), type.MakeByRefType() }, null)!;
|
||||
}
|
||||
|
||||
public static void WritePrimitive(Stream stream, Matrix3x2 value)
|
||||
{
|
||||
Primitives.WritePrimitive(stream, value.M11);
|
||||
Primitives.WritePrimitive(stream, value.M12);
|
||||
Primitives.WritePrimitive(stream, value.M21);
|
||||
Primitives.WritePrimitive(stream, value.M22);
|
||||
Primitives.WritePrimitive(stream, value.M31);
|
||||
Primitives.WritePrimitive(stream, value.M32);
|
||||
}
|
||||
|
||||
public static void ReadPrimitive(Stream stream, out Matrix3x2 value)
|
||||
{
|
||||
Span<float> buf = stackalloc float[6];
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
Primitives.ReadPrimitive(stream, out buf[i]);
|
||||
}
|
||||
value = new Matrix3x2(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
|
||||
}
|
||||
}
|
||||
61
Robust.Shared/Serialization/NetMathSerializers.cs
Normal file
61
Robust.Shared/Serialization/NetMathSerializers.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using NetSerializer;
|
||||
|
||||
namespace Robust.Shared.Serialization;
|
||||
|
||||
internal sealed class NetMathSerializer : IStaticTypeSerializer
|
||||
{
|
||||
public bool Handles(Type type)
|
||||
{
|
||||
return type == typeof(Vector2)
|
||||
|| type == typeof(Vector3)
|
||||
|| type == typeof(Vector4)
|
||||
|| type == typeof(Quaternion)
|
||||
|| type == typeof(Matrix4x4)
|
||||
|| type == typeof(Matrix3x2);
|
||||
}
|
||||
|
||||
public IEnumerable<Type> GetSubtypes(Type type)
|
||||
{
|
||||
return Type.EmptyTypes;
|
||||
}
|
||||
|
||||
public MethodInfo GetStaticWriter(Type type)
|
||||
{
|
||||
return typeof(NetMathSerializer)
|
||||
.GetMethod(nameof(WriteFloatObject), BindingFlags.Static | BindingFlags.Public)!
|
||||
.MakeGenericMethod(type);
|
||||
}
|
||||
|
||||
public MethodInfo GetStaticReader(Type type)
|
||||
{
|
||||
return typeof(NetMathSerializer)
|
||||
.GetMethod(nameof(ReadFloatObject), BindingFlags.Static | BindingFlags.Public)!
|
||||
.MakeGenericMethod(type);
|
||||
}
|
||||
|
||||
public static void WriteFloatObject<T>(Stream stream, T value) where T : unmanaged
|
||||
{
|
||||
var floatSpan = MemoryMarshal.Cast<T, float>(new Span<T>(ref value));
|
||||
foreach (var f in floatSpan)
|
||||
{
|
||||
Primitives.WritePrimitive(stream, f);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReadFloatObject<T>(Stream stream, out T value) where T : unmanaged
|
||||
{
|
||||
Unsafe.SkipInit(out value);
|
||||
var floatSpan = MemoryMarshal.Cast<T, float>(new Span<T>(ref value));
|
||||
for (var i = 0; i < floatSpan.Length; i++)
|
||||
{
|
||||
Primitives.ReadPrimitive(stream, out floatSpan[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,8 +89,7 @@ namespace Robust.Shared.Serialization
|
||||
CustomTypeSerializers = new[]
|
||||
{
|
||||
MappedStringSerializer.TypeSerializer,
|
||||
new Vector2Serializer(),
|
||||
new Matrix3x2Serializer(),
|
||||
new NetMathSerializer()
|
||||
}
|
||||
};
|
||||
_serializer = new Serializer(types, settings);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Globalization;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
@@ -59,7 +60,7 @@ namespace Robust.Shared.Serialization.TypeSerializers.Implementations
|
||||
public Vector3 CreateCopy(ISerializationManager serializationManager, Vector3 source,
|
||||
IDependencyCollection dependencies, SerializationHookContext hookCtx, ISerializationContext? context = null)
|
||||
{
|
||||
return new(source);
|
||||
return source;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Globalization;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
@@ -63,7 +64,7 @@ namespace Robust.Shared.Serialization.TypeSerializers.Implementations
|
||||
public Vector4 CreateCopy(ISerializationManager serializationManager, Vector4 source,
|
||||
IDependencyCollection dependencies, SerializationHookContext hookCtx, ISerializationContext? context = null)
|
||||
{
|
||||
return new(source);
|
||||
return source;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using NetSerializer;
|
||||
|
||||
namespace Robust.Shared.Serialization;
|
||||
|
||||
internal sealed class Vector2Serializer : IStaticTypeSerializer
|
||||
{
|
||||
public bool Handles(Type type)
|
||||
{
|
||||
return type == typeof(Vector2);
|
||||
}
|
||||
|
||||
public IEnumerable<Type> GetSubtypes(Type type)
|
||||
{
|
||||
return Type.EmptyTypes;
|
||||
}
|
||||
|
||||
public MethodInfo GetStaticWriter(Type type)
|
||||
{
|
||||
return typeof(Vector2Serializer).GetMethod("WritePrimitive",
|
||||
BindingFlags.Static | BindingFlags.Public | BindingFlags.ExactBinding, null,
|
||||
new Type[] { typeof(Stream), type }, null)!;
|
||||
}
|
||||
|
||||
public MethodInfo GetStaticReader(Type type)
|
||||
{
|
||||
return typeof(Vector2Serializer).GetMethod("ReadPrimitive",
|
||||
BindingFlags.Static | BindingFlags.Public | BindingFlags.ExactBinding, null,
|
||||
new Type[] { typeof(Stream), type.MakeByRefType() }, null)!;
|
||||
}
|
||||
|
||||
public static void WritePrimitive(Stream stream, Vector2 value)
|
||||
{
|
||||
Primitives.WritePrimitive(stream, value.X);
|
||||
Primitives.WritePrimitive(stream, value.Y);
|
||||
}
|
||||
|
||||
public static void ReadPrimitive(Stream stream, out Vector2 value)
|
||||
{
|
||||
Primitives.ReadPrimitive(stream, out float x);
|
||||
Primitives.ReadPrimitive(stream, out float y);
|
||||
value = new Vector2(x, y);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Robust.Shared.Toolshed.TypeParsers.Math;
|
||||
|
||||
internal sealed class Vector3TypeParser : SpanLikeTypeParser<Maths.Vector3, float>
|
||||
internal sealed class Vector3TypeParser : SpanLikeTypeParser<Vector3, float>
|
||||
{
|
||||
public override int Elements => 3;
|
||||
public override Maths.Vector3 Create(Span<float> elements)
|
||||
public override Vector3 Create(Span<float> elements)
|
||||
{
|
||||
return new Maths.Vector3(elements[0], elements[1], elements[2]);
|
||||
return new Vector3(elements[0], elements[1], elements[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Robust.Shared.Toolshed.TypeParsers.Math;
|
||||
|
||||
internal sealed class Vector4TypeParser : SpanLikeTypeParser<Maths.Vector4, float>
|
||||
internal sealed class Vector4TypeParser : SpanLikeTypeParser<Vector4, float>
|
||||
{
|
||||
public override int Elements => 4;
|
||||
public override Maths.Vector4 Create(Span<float> elements)
|
||||
public override Vector4 Create(Span<float> elements)
|
||||
{
|
||||
return new Maths.Vector4(elements[0], elements[1], elements[2], elements[4]);
|
||||
return new Vector4(elements[0], elements[1], elements[2], elements[4]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@ using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Threading;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Shared.Utility
|
||||
{
|
||||
@@ -123,25 +121,35 @@ namespace Robust.Shared.Utility
|
||||
}
|
||||
|
||||
[Pure]
|
||||
public static Matrix4 AsMatrix4(this YamlNode node)
|
||||
public static Matrix4x4 AsMatrix4(this YamlNode node)
|
||||
{
|
||||
string raw = AsString(node);
|
||||
string[] args = raw.Split(',');
|
||||
if (args.Length != 16)
|
||||
{
|
||||
throw new ArgumentException(string.Format("Could not parse {0}: '{1}'", nameof(Matrix4), raw));
|
||||
}
|
||||
Vector4[] vectorBlocks = new Vector4[4];
|
||||
for(var i = 0; i < 16; i += 4) {
|
||||
vectorBlocks.Append(new Vector4(
|
||||
float.Parse(args[0 + i], CultureInfo.InvariantCulture),
|
||||
float.Parse(args[1 + i], CultureInfo.InvariantCulture),
|
||||
float.Parse(args[2 + i], CultureInfo.InvariantCulture),
|
||||
float.Parse(args[3 + i], CultureInfo.InvariantCulture)
|
||||
));
|
||||
throw new ArgumentException(string.Format("Could not parse {0}: '{1}'", nameof(Matrix4x4), raw));
|
||||
}
|
||||
|
||||
return new Matrix4(vectorBlocks[0],vectorBlocks[1],vectorBlocks[2],vectorBlocks[3]);
|
||||
// What, you know a better way to do this?
|
||||
|
||||
var m11 = Parse.Float(args[0]);
|
||||
var m12 = Parse.Float(args[1]);
|
||||
var m13 = Parse.Float(args[2]);
|
||||
var m14 = Parse.Float(args[3]);
|
||||
var m21 = Parse.Float(args[4]);
|
||||
var m22 = Parse.Float(args[5]);
|
||||
var m23 = Parse.Float(args[6]);
|
||||
var m24 = Parse.Float(args[7]);
|
||||
var m31 = Parse.Float(args[8]);
|
||||
var m32 = Parse.Float(args[9]);
|
||||
var m33 = Parse.Float(args[10]);
|
||||
var m34 = Parse.Float(args[11]);
|
||||
var m41 = Parse.Float(args[12]);
|
||||
var m42 = Parse.Float(args[13]);
|
||||
var m43 = Parse.Float(args[14]);
|
||||
var m44 = Parse.Float(args[15]);
|
||||
|
||||
return new Matrix4x4(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44);
|
||||
}
|
||||
|
||||
[Pure]
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.Maths;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
|
||||
namespace Robust.UnitTesting.Shared.Maths
|
||||
{
|
||||
|
||||
@@ -10,8 +10,6 @@ using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.UnitTesting.Shared.Prototypes
|
||||
{
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace Robust.UnitTesting.Shared.Serialization
|
||||
{
|
||||
CustomTypeSerializers = new ITypeSerializer[]
|
||||
{
|
||||
new Vector2Serializer(),
|
||||
new NetMathSerializer(),
|
||||
}
|
||||
});
|
||||
var stream = new MemoryStream();
|
||||
|
||||
@@ -44,8 +44,8 @@ public sealed partial class ToolshedParserTest
|
||||
// maff
|
||||
AssertParseable<Vector2>();
|
||||
AssertParseable<Vector2i>();
|
||||
AssertParseable<Robust.Shared.Maths.Vector3>();
|
||||
AssertParseable<Robust.Shared.Maths.Vector4>();
|
||||
AssertParseable<Vector3>();
|
||||
AssertParseable<Vector4>();
|
||||
AssertParseable<Box2>();
|
||||
AssertParseable<Box2i>();
|
||||
AssertParseable<Angle>();
|
||||
|
||||
Reference in New Issue
Block a user