Skip to content

Commit

Permalink
Merge pull request #13 from Tornado-Technology/transform-implementation
Browse files Browse the repository at this point in the history
Transform implementation
  • Loading branch information
Tornado-Technology authored Jul 12, 2024
2 parents 5b72ca4 + c89569d commit 5a38cb5
Show file tree
Hide file tree
Showing 22 changed files with 862 additions and 69 deletions.
44 changes: 18 additions & 26 deletions Hypercube.Client/Graphics/Viewports/Camera2D.cs
Original file line number Diff line number Diff line change
@@ -1,64 +1,56 @@
using Hypercube.Shared.Math.Matrix;
using Hypercube.Shared.Math;
using Hypercube.Shared.Math.Matrix;
using Hypercube.Shared.Math.Transform;
using Hypercube.Shared.Math.Vector;

namespace Hypercube.Client.Graphics.Viewports;

public class Camera2D : ICamera
public sealed class Camera2D : ICamera
{
public Vector3 Position { get; private set; }
public Vector3 Rotation { get; private set; }
public Vector3 Scale { get; private set; } = Vector3.One;
public Matrix4X4 Projection { get; private set; }

public Vector3 Position => _transform.Position;
public Vector3 Rotation => _transform.Rotation.ToEuler();
public Vector3 Scale => _transform.Scale;
public Vector2Int Size { get; private set; }

private readonly float _zFar;
private readonly float _zNear;
private Vector2Int Size { get; set; }


private Vector2 HalfSize => Size / 2f;
public Matrix4X4 Projection { get; private set; }
private Transform3 _transform = new();

public Camera2D(Vector2Int size, Vector2 position, float zNear, float zFar)
{
Size = size;
Position = new Vector3(position);
_zNear = zNear;
_zFar = zFar;

SetPosition(new Vector3(position));

UpdateProjection();
}

public void SetSize(Vector2Int size)
{
Size = size;
UpdateProjection();
}

public void SetPosition(Vector3 position)
{
Position = position;
_transform.SetPosition(position);
UpdateProjection();
}

public void SetRotation(Vector3 rotation)
{
Rotation = Rotation.WithZ(rotation.Z);
_transform.SetRotation(Quaternion.FromEuler(0, 0, rotation.Z));
UpdateProjection();
}

public void SetScale(Vector3 scale)
{
Scale = scale;
_transform.SetScale(scale);
UpdateProjection();
}

private void UpdateProjection()
{
var projection = Matrix4X4.CreateOrthographic(Size, _zNear, _zFar);

var translate = Matrix4X4.CreateTranslation(Position);
var rotation = Matrix4X4.CreateRotationZ(Rotation.Z);
var scale = Matrix4X4.CreateScale(Scale);

Projection = projection * translate * rotation * scale;
Projection = projection * _transform.Matrix;
}
}
1 change: 1 addition & 0 deletions Hypercube.Client/Graphics/Viewports/ICamera.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public interface ICamera
Vector3 Position { get; }
Vector3 Rotation { get; }
Vector3 Scale { get; }
Vector2Int Size { get; }

void SetPosition(Vector3 position);
void SetRotation(Vector3 rotation);
Expand Down
112 changes: 108 additions & 4 deletions Hypercube.Shared.Math/Angle.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,120 @@
using System.Runtime.CompilerServices;
using Hypercube.Shared.Math.Extensions;
using Hypercube.Shared.Math.Vector;

namespace Hypercube.Shared.Math;

public readonly struct Angle(double theta)
public readonly struct Angle : IEquatable<Angle>, IEquatable<double>
{
public static readonly Angle Zero = new(0);

public readonly double Theta;

public double Degrees
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => Theta * HyperMath.RadiansToDegrees;
}

public Vector2 Vector
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new((float)System.Math.Cos(Theta), (float)System.Math.Sin(Theta));
}

public Angle(double theta)
{
Theta = theta;
}

public Angle(Vector2 vector2)
{
vector2 = vector2.Normalized;
Theta = System.Math.Atan2(vector2.X, vector2.Y);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Angle other)
{
return Theta.AboutEquals(other.Theta);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(double other)
{
return Theta.AboutEquals(other);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object? obj)
{
return (obj is double theta && Equals(theta)) ||
(obj is Angle angle && Equals(angle));
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
return Theta.GetHashCode();
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string ToString()
{
return $"{Degrees} deg";
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Angle a, double b)
{
return a.Equals(b);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Angle a, double b)
{
return !a.Equals(b);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Angle a, Angle b)
{
return a.Equals(b);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Angle a, Angle b)
{
return !a.Equals(b);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator double(Angle angle)
{
return angle.Theta;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Angle(double radians)
{
return new Angle(radians);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Angle(float radians)
{
return new Angle(radians);
}

public readonly double Theta = theta;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Angle FromDegrees(double degrees)
{
return new Angle(degrees * HyperMath.DegreesToRadians);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator float(Angle angle)
public static Angle FromDegrees(float degrees)
{
return (float)angle.Theta;
return new Angle(degrees * HyperMath.DegreesToRadians);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

public static class FloatingPointEqualsExtension
{
public static bool AboutEquals(this double a, double b)
public static bool AboutEquals(this double a, double b, double tolerance = 1E-15d)
{
var epsilon = System.Math.Max(System.Math.Abs(a), System.Math.Abs(b)) * 1E-15d;
return System.Math.Abs(a - b) <= epsilon;
}

public static bool AboutEquals(this float a, float b)
public static bool AboutEquals(this float a, float b, float tolerance = 1E-15f)
{
var epsilon = System.Math.Max(System.Math.Abs(a), System.Math.Abs(b)) * 1E-15f;
var epsilon = System.Math.Max(System.Math.Abs(a), System.Math.Abs(b)) * tolerance ;
return System.Math.Abs(a - b) <= epsilon;
}
}
16 changes: 16 additions & 0 deletions Hypercube.Shared.Math/HyperMath.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Hypercube.Shared.Math;

public static class HyperMath
{
public const double PI = System.Math.PI;

public const double PIOver2 = PI / 2;
public const double PIOver4 = PI / 4;
public const double PIOver6 = PI / 6;

public const double TwoPI = 2 * PI;
public const double ThreePiOver2 = 3 * PI / 2;

public const double RadiansToDegrees = 180 / PI;
public const double DegreesToRadians = PI / 180;
}
16 changes: 16 additions & 0 deletions Hypercube.Shared.Math/HyperMathF.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Hypercube.Shared.Math;

public static class HyperMathF
{
public const float PI = MathF.PI;

public const float PIOver2 = PI / 2;
public const float PIOver4 = PI / 4;
public const float PIOver6 = PI / 6;

public const float TwoPI = 2 * PI;
public const float ThreePiOver2 = 3 * PI / 2;

public const float RadiansToDegrees = 180 / PI;
public const float DegreesToRadians = PI / 180;
}
25 changes: 25 additions & 0 deletions Hypercube.Shared.Math/Matrix/Matrix4X4.Compatibility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,30 @@ namespace Hypercube.Shared.Math.Matrix;

public partial struct Matrix4X4
{
/*
* System.Numerics Compatibility
*/

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator System.Numerics.Matrix4x4(Matrix4X4 matrix4X4)
{
return new System.Numerics.Matrix4x4(
matrix4X4.M00, matrix4X4.M01, matrix4X4.M02, matrix4X4.M03,
matrix4X4.M10, matrix4X4.M11, matrix4X4.M12, matrix4X4.M13,
matrix4X4.M20, matrix4X4.M21, matrix4X4.M22, matrix4X4.M23,
matrix4X4.M30, matrix4X4.M31, matrix4X4.M32, matrix4X4.M33);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Matrix4X4(System.Numerics.Matrix4x4 matrix4X4)
{
return new Matrix4X4(
matrix4X4.M11, matrix4X4.M12, matrix4X4.M13, matrix4X4.M14,
matrix4X4.M21, matrix4X4.M22, matrix4X4.M23, matrix4X4.M24,
matrix4X4.M31, matrix4X4.M32, matrix4X4.M33, matrix4X4.M34,
matrix4X4.M41, matrix4X4.M42, matrix4X4.M43, matrix4X4.M44);
}

/*
* OpenTK Compatibility
*/
Expand All @@ -13,6 +37,7 @@ public static implicit operator OpenTK.Mathematics.Matrix4(Matrix4X4 matrix4X4)
{
return new OpenTK.Mathematics.Matrix4(matrix4X4.Row0, matrix4X4.Row1, matrix4X4.Row2, matrix4X4.Row3);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Matrix4X4(OpenTK.Mathematics.Matrix4 matrix4)
{
Expand Down
Loading

0 comments on commit 5a38cb5

Please sign in to comment.