diff --git a/.idea/.idea.Hypercube/.idea/indexLayout.xml b/.idea/.idea.Hypercube/.idea/indexLayout.xml
index 7b08163..2a75c2c 100644
--- a/.idea/.idea.Hypercube/.idea/indexLayout.xml
+++ b/.idea/.idea.Hypercube/.idea/indexLayout.xml
@@ -1,7 +1,9 @@
-
+
+ Resources
+
diff --git a/Hypercube.Client/Dependencies.cs b/Hypercube.Client/Dependencies.cs
index 2e75cf9..29e4fc1 100644
--- a/Hypercube.Client/Dependencies.cs
+++ b/Hypercube.Client/Dependencies.cs
@@ -1,6 +1,7 @@
using Hypercube.Client.Graphics;
using Hypercube.Client.Graphics.Rendering;
using Hypercube.Client.Graphics.Texturing;
+using Hypercube.Client.Graphics.Viewports;
using Hypercube.Client.Input.Handler;
using Hypercube.Client.Input.Manager;
using Hypercube.Client.Runtimes;
@@ -38,6 +39,9 @@ public static void Register(DependenciesContainer rootContainer)
// Texturing
rootContainer.Register();
+ // Camera
+ rootContainer.Register();
+
// Rendering
rootContainer.Register();
diff --git a/Hypercube.Client/Graphics/Rendering/Renderer.Render.cs b/Hypercube.Client/Graphics/Rendering/Renderer.Render.cs
index 215ada9..dc5a1c6 100644
--- a/Hypercube.Client/Graphics/Rendering/Renderer.Render.cs
+++ b/Hypercube.Client/Graphics/Rendering/Renderer.Render.cs
@@ -3,6 +3,8 @@
using Hypercube.Client.Graphics.Viewports;
using Hypercube.Shared.Math;
using Hypercube.Shared.Math.Box;
+using Hypercube.Shared.Math.Matrix;
+using Hypercube.Shared.Math.Vector;
using Hypercube.Shared.Runtimes.Loop.Event;
using OpenToolkit.Graphics.OpenGL4;
@@ -40,6 +42,8 @@ private void OnLoad()
_baseTexture = _textureManager.CreateHandler("/icon.png");
_baseTexture.Bind();
+ _cameraManager.SetMainCamera(_cameraManager.CreateCamera2D(MainWindow.Size));
+
_vbo = new BufferObject(BufferTarget.ArrayBuffer);
_ebo = new BufferObject(BufferTarget.ElementArrayBuffer);
_vao = new ArrayObject();
@@ -64,9 +68,10 @@ private void OnLoad()
private void OnFrameUpdate(UpdateFrameEvent args)
{
#if DEBUG
- _windowManager.WindowSetTitle(MainWindow, $"FPS: {_timing.Fps} | RealTime: {_timing.RealTime}");
+ _windowManager.WindowSetTitle(MainWindow, $"FPS: {_timing.Fps} | RealTime: {_timing.RealTime} | cPos: {_cameraManager.MainCamera?.Position ?? null} | cRot: {_cameraManager.MainCamera?.Rotation ?? null}");
#endif
_windowManager.PollEvents();
+ _cameraManager.UpdateInput(_cameraManager.MainCamera, args.DeltaSeconds);
}
private void OnFrameRender(RenderFrameEvent args)
@@ -83,14 +88,20 @@ private void OnFrameRender(RenderFrameEvent args)
var colorG = new Color(0f, sin, 0f);
var colorB = new Color(0f, 0f, sin);
- DrawTexture(_baseTexture, new Box2(-1.0f, 1.0f, 0.0f, 0.0f), new Box2(0.0f, 1.0f, 1.0f, 0.0f), Color.White);
- DrawTexture(_baseTexture, new Box2(0.0f, 1.0f, 1.0f, 0.0f), new Box2(0.0f, 1.0f, 1.0f, 0.0f), colorR);
- DrawTexture(_baseTexture, new Box2(-1.0f, 0.0f, 0.0f, -1.0f), new Box2(0.0f, 1.0f, 1.0f, 0.0f), colorG);
- DrawTexture(_baseTexture, new Box2(0.0f, 0.0f, 1.0f, -1.0f), new Box2(0.0f, 1.0f, 1.0f, 0.0f), colorB);
+ DrawTexture(_baseTexture, _baseTexture.Texture.QuadCrateTranslated(-Vector2.UnitY * 60f), new Box2(0.0f, 1.0f, 1.0f, 0.0f), Color.White);
+ DrawTexture(_baseTexture, _baseTexture.Texture.QuadCrateTranslated(Vector2.UnitX * 60f), new Box2(0.0f, 1.0f, 1.0f, 0.0f), colorR);
+ DrawTexture(_baseTexture, _baseTexture.Texture.QuadCrateTranslated(-Vector2.UnitX * 60f), new Box2(0.0f, 1.0f, 1.0f, 0.0f), colorG);
+ DrawTexture(_baseTexture, _baseTexture.Texture.QuadCrateTranslated(Vector2.UnitY * 60f), new Box2(0.0f, 1.0f, 1.0f, 0.0f), colorB);
BatchUpdate();
+
+ var model = Matrix4X4.CreateTranslation(Vector2.Zero) * Matrix4X4.CreateRotationZ(0) * Matrix4X4.CreateScale(Vector2.One);
+ var view = Matrix4X4.CreateTranslation(0.0f, 0.0f, -3.0f);
_baseShader.Use();
+ _baseShader.SetUniform("model", model);
+ _baseShader.SetUniform("view", view);
+ _baseShader.SetUniform("projection", _cameraManager.Projection);
_vao.Bind();
GL.DrawElements(BeginMode.Triangles, (int) _batchIndexIndex, DrawElementsType.UnsignedInt, 0);
diff --git a/Hypercube.Client/Graphics/Rendering/Renderer.cs b/Hypercube.Client/Graphics/Rendering/Renderer.cs
index 3e58e29..a350fa7 100644
--- a/Hypercube.Client/Graphics/Rendering/Renderer.cs
+++ b/Hypercube.Client/Graphics/Rendering/Renderer.cs
@@ -1,7 +1,7 @@
-using System.Collections.Frozen;
-using Hypercube.Client.Graphics.Event;
+using System.Collections.Frozen;
using Hypercube.Client.Graphics.OpenGL;
using Hypercube.Client.Graphics.Texturing;
+using Hypercube.Client.Graphics.Viewports;
using Hypercube.Client.Graphics.Windows;
using Hypercube.Client.Graphics.Windows.Manager;
using Hypercube.Shared.Dependency;
@@ -22,6 +22,7 @@ public sealed partial class Renderer : IRenderer, IPostInject
[Dependency] private readonly IEventBus _eventBus = default!;
[Dependency] private readonly ITextureManager _textureManager = default!;
[Dependency] private readonly ITiming _timing = default!;
+ [Dependency] private readonly ICameraManager _cameraManager = default!;
[Dependency] private readonly IResourceManager _resourceManager = default!;
private readonly ILogger _logger = LoggingManager.GetLogger("renderer");
diff --git a/Hypercube.Client/Graphics/Shading/IShader.cs b/Hypercube.Client/Graphics/Shading/IShader.cs
index 4838e90..8881364 100644
--- a/Hypercube.Client/Graphics/Shading/IShader.cs
+++ b/Hypercube.Client/Graphics/Shading/IShader.cs
@@ -1,7 +1,12 @@
-namespace Hypercube.Client.Graphics.Shading;
+using Hypercube.Shared.Math.Matrix;
+
+namespace Hypercube.Client.Graphics.Shading;
public interface IShader
{
void Use();
+ int GetUniformLocation(string name);
void SetUniform(string name, int value);
+ void SetUniform(string name, Matrix4X4 value, bool transpose = false);
+ void SetUniform(int index, Matrix4X4 value, bool transpose = false);
}
\ No newline at end of file
diff --git a/Hypercube.Client/Graphics/Shading/Shader.cs b/Hypercube.Client/Graphics/Shading/Shader.cs
index 9ed479c..7e77782 100644
--- a/Hypercube.Client/Graphics/Shading/Shader.cs
+++ b/Hypercube.Client/Graphics/Shading/Shader.cs
@@ -1,8 +1,8 @@
-using Hypercube.Shared.Math.Vector;
+using Hypercube.Shared.Math.Matrix;
+using Hypercube.Shared.Math.Vector;
using Hypercube.Shared.Resources;
using Hypercube.Shared.Resources.Manager;
using OpenToolkit.Graphics.OpenGL4;
-using Vector2 = Hypercube.Shared.Math.Vector.Vector2;
namespace Hypercube.Client.Graphics.Shading;
@@ -57,12 +57,17 @@ public void Use()
GL.UseProgram(_handle);
}
+ public int GetUniformLocation(string name)
+ {
+ return GL.GetUniformLocation(_handle, name);
+ }
+
public void SetUniform(string name, int value)
{
GL.UseProgram(_handle);
GL.Uniform1(_uniformLocations[name], value);
}
-
+
public void SetUniform(string name, Vector2Int value)
{
GL.UseProgram(_handle);
@@ -80,6 +85,18 @@ public void SetUniform(string name, Vector2 value)
GL.UseProgram(_handle);
GL.Uniform2(_uniformLocations[name], value.X, value.Y);
}
+
+ public void SetUniform(string name, Matrix4X4 value, bool transpose = false)
+ {
+ SetUniform(GL.GetUniformLocation(_handle, name), value, transpose);
+ }
+
+ public void SetUniform(int index, Matrix4X4 value, bool transpose = false)
+ {
+ var matrix = transpose ? Matrix4X4.Transpose(value) : new Matrix4X4(value);
+ GL.UseProgram(_handle);
+ GL.UniformMatrix4(index, 1, false, matrix.ToArray());
+ }
private int CreateShader(string source, ShaderType type)
{
diff --git a/Hypercube.Client/Graphics/Vertex.cs b/Hypercube.Client/Graphics/Vertex.cs
index 62523b4..9ba010f 100644
--- a/Hypercube.Client/Graphics/Vertex.cs
+++ b/Hypercube.Client/Graphics/Vertex.cs
@@ -12,8 +12,8 @@ public readonly struct Vertex
private static readonly Color DefaultColor = Color.White;
public readonly Vector3 Position;
- public readonly Vector2 UVCoords;
public readonly Color Color;
+ public readonly Vector2 UVCoords;
public Vertex(Vector3 position, Vector2 uvCoords, Color color)
{
diff --git a/Hypercube.Client/Graphics/Viewports/Camera2D.cs b/Hypercube.Client/Graphics/Viewports/Camera2D.cs
index 11689cc..fde8ce8 100644
--- a/Hypercube.Client/Graphics/Viewports/Camera2D.cs
+++ b/Hypercube.Client/Graphics/Viewports/Camera2D.cs
@@ -1,37 +1,64 @@
-using Hypercube.Shared.Math.Box;
-using Hypercube.Shared.Math.Matrix;
+using Hypercube.Shared.Math.Matrix;
using Hypercube.Shared.Math.Vector;
namespace Hypercube.Client.Graphics.Viewports;
public class Camera2D : ICamera
{
- public float ZFar { get; private set; }
- public float ZNear { get; private set; }
- public Vector2 Position { get; private set; }
- public float Zoom { get; private set; }
+ public Vector3 Position { get; private set; }
+ public Vector3 Rotation { get; private set; }
+ public Vector3 Scale { get; private set; } = Vector3.One;
+
+ private readonly float _zFar;
+ private readonly float _zNear;
+ private Vector2Int Size { get; set; }
- public Matrix4X4 Projection;
+
+ private Vector2 HalfSize => Size / 2f;
+ public Matrix4X4 Projection { get; private set; }
- public void SetPosition(Vector2 position)
+ public Camera2D(Vector2Int size, Vector2 position, float zNear, float zFar)
+ {
+ Size = size;
+ Position = new Vector3(position);
+ _zNear = zNear;
+ _zFar = zFar;
+
+ UpdateProjection();
+ }
+
+ public void SetSize(Vector2Int size)
+ {
+ Size = size;
+ UpdateProjection();
+ }
+
+ public void SetPosition(Vector3 position)
{
Position = position;
UpdateProjection();
}
- public void SetZoom(float zoom)
+ public void SetRotation(Vector3 rotation)
+ {
+ Rotation = Rotation.WithZ(rotation.Z);
+ UpdateProjection();
+ }
+
+ public void SetScale(Vector3 scale)
{
- Zoom = zoom;
+ Scale = scale;
UpdateProjection();
}
private void UpdateProjection()
{
- var size = new Box2();
+ var projection = Matrix4X4.CreateOrthographic(Size, _zNear, _zFar);
- var projection = Matrix4X4.CreateOrthographic(size, ZNear, ZFar);
- var scale = Matrix4X4.CreateScale(Zoom);
-
- Projection = projection * scale;
+ var translate = Matrix4X4.CreateTranslation(Position);
+ var rotation = Matrix4X4.CreateRotationZ(Rotation.Z);
+ var scale = Matrix4X4.CreateScale(Scale);
+
+ Projection = projection * translate * rotation * scale;
}
}
\ No newline at end of file
diff --git a/Hypercube.Client/Graphics/Viewports/CameraManager.cs b/Hypercube.Client/Graphics/Viewports/CameraManager.cs
index 0213d02..6b8cdba 100644
--- a/Hypercube.Client/Graphics/Viewports/CameraManager.cs
+++ b/Hypercube.Client/Graphics/Viewports/CameraManager.cs
@@ -1,20 +1,71 @@
-using Hypercube.Shared.Dependency;
-using Hypercube.Shared.EventBus;
-using Hypercube.Shared.Runtimes.Loop.Event;
+using Hypercube.Client.Input;
+using Hypercube.Client.Input.Handler;
+using Hypercube.Shared.Dependency;
+using Hypercube.Shared.Math.Matrix;
+using Hypercube.Shared.Math.Vector;
namespace Hypercube.Client.Graphics.Viewports;
-public class CameraManager : ICameraManager, IPostInject
+public class CameraManager : ICameraManager
{
- [Dependency] private readonly IEventBus _eventBus = default!;
+ [Dependency] private readonly IInputHandler _inputHandler = default!;
- public void PostInject()
+ public ICamera? MainCamera { get; private set; }
+ public Matrix4X4 Projection => MainCamera?.Projection ?? Matrix4X4.Identity;
+
+ public void UpdateInput(ICamera? camera, float delta)
{
- _eventBus.Subscribe(OnUpdate);
+ if (camera is null)
+ return;
+
+ // Debug camera controls
+ var position = camera.Position;
+ var rotation = camera.Rotation;
+ var scale = camera.Scale;
+
+ var speed = 20f;
+
+ if (_inputHandler.IsKeyDown(Key.W))
+ position -= Vector3.UnitY * speed * delta;
+
+ if (_inputHandler.IsKeyDown(Key.S))
+ position += Vector3.UnitY * speed * delta;
+
+ if (_inputHandler.IsKeyDown(Key.A))
+ position += Vector3.UnitX * speed * delta;
+
+ if (_inputHandler.IsKeyDown(Key.D))
+ position -= Vector3.UnitX * speed * delta;
+
+ if (_inputHandler.IsKeyDown(Key.Q))
+ rotation -= Vector3.UnitZ * delta;
+
+ if (_inputHandler.IsKeyDown(Key.E))
+ rotation += Vector3.UnitZ * delta;
+
+ if (_inputHandler.IsKeyDown(Key.T))
+ scale -= Vector3.One * delta;
+
+ if (_inputHandler.IsKeyDown(Key.Y))
+ scale += Vector3.One * delta;
+
+ camera.SetPosition(position);
+ camera.SetRotation(rotation);
+ camera.SetScale(scale);
}
- private void OnUpdate(UpdateFrameEvent args)
+ public void SetMainCamera(ICamera camera)
{
-
+ MainCamera = camera;
+ }
+
+ public ICamera CreateCamera2D(Vector2Int size)
+ {
+ return CreateCamera2D(size, Vector2.Zero);
+ }
+
+ public ICamera CreateCamera2D(Vector2Int size, Vector2 position, float zNear = 0.1f, float zFar = 100f)
+ {
+ return new Camera2D(size, position, zNear, zFar);
}
}
\ No newline at end of file
diff --git a/Hypercube.Client/Graphics/Viewports/ICamera.cs b/Hypercube.Client/Graphics/Viewports/ICamera.cs
index 0c26f15..fd8d030 100644
--- a/Hypercube.Client/Graphics/Viewports/ICamera.cs
+++ b/Hypercube.Client/Graphics/Viewports/ICamera.cs
@@ -1,6 +1,17 @@
-namespace Hypercube.Client.Graphics.Viewports;
+using Hypercube.Shared.Math.Matrix;
+using Hypercube.Shared.Math.Vector;
+
+namespace Hypercube.Client.Graphics.Viewports;
public interface ICamera
{
+ Matrix4X4 Projection { get; }
+
+ Vector3 Position { get; }
+ Vector3 Rotation { get; }
+ Vector3 Scale { get; }
+ void SetPosition(Vector3 position);
+ void SetRotation(Vector3 rotation);
+ void SetScale(Vector3 scale);
}
\ No newline at end of file
diff --git a/Hypercube.Client/Graphics/Viewports/ICameraManager.cs b/Hypercube.Client/Graphics/Viewports/ICameraManager.cs
index 88db334..035fc39 100644
--- a/Hypercube.Client/Graphics/Viewports/ICameraManager.cs
+++ b/Hypercube.Client/Graphics/Viewports/ICameraManager.cs
@@ -1,6 +1,13 @@
-namespace Hypercube.Client.Graphics.Viewports;
+using Hypercube.Shared.Math.Matrix;
+using Hypercube.Shared.Math.Vector;
+
+namespace Hypercube.Client.Graphics.Viewports;
public interface ICameraManager
{
-
+ ICamera? MainCamera { get; }
+ Matrix4X4 Projection { get; }
+ void SetMainCamera(ICamera camera);
+ ICamera CreateCamera2D(Vector2Int size);
+ void UpdateInput(ICamera? camera, float delta);
}
\ No newline at end of file
diff --git a/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.Callbacks.cs b/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.Callbacks.cs
index 3eb4225..22e20f1 100644
--- a/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.Callbacks.cs
+++ b/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.Callbacks.cs
@@ -1,22 +1,43 @@
-using Hypercube.Client.Graphics.Event;
-using Hypercube.Client.Input;
+using Hypercube.Client.Input;
using Hypercube.Client.Utilities;
using OpenTK.Windowing.GraphicsLibraryFramework;
using GlfwKeyModifiers = OpenTK.Windowing.GraphicsLibraryFramework.KeyModifiers;
using KeyModifiers = Hypercube.Client.Input.KeyModifiers;
+using static OpenTK.Windowing.GraphicsLibraryFramework.GLFWCallbacks;
namespace Hypercube.Client.Graphics.Windows.Manager;
public sealed unsafe partial class GlfwWindowManager
{
- private void OnWindowClosed(Window* window)
+ private ErrorCallback? _errorCallback;
+
+ private KeyCallback? _keyCallback;
+
+ private WindowCloseCallback? _windowCloseCallback;
+ private WindowSizeCallback? _windowSizeCallback;
+ private WindowFocusCallback? _windowFocusCallback;
+
+ ///
+ /// GC doesn't think our callbacks are stored anywhere,
+ /// so it cleans them up,
+ /// we need to indicate that there is a link to them so they don't get lost.
+ ///
+ private void HandleCallbacks()
{
- if (!TryGetWindow(window, out var registration))
- return;
+ _errorCallback = OnErrorHandled;
+
+ _keyCallback = OnWindowKeyHandled;
- _renderer.CloseWindow(registration);
+ _windowCloseCallback = OnWindowClosed;
+ _windowSizeCallback = OnWindowResized;
+ _windowFocusCallback = OnWindowFocusChanged;
}
-
+
+ private void OnErrorHandled(ErrorCode error, string description)
+ {
+ _logger.Error(GLFWHelper.FormatError(error, description));
+ }
+
private void OnWindowKeyHandled(Window* window, Keys glfwKey, int scanCode, InputAction action, GlfwKeyModifiers mods)
{
var key = (Key)glfwKey;
@@ -49,6 +70,14 @@ private void OnWindowKeyHandled(Window* window, Keys glfwKey, int scanCode, Inpu
(KeyModifiers)mods,
scanCode));
}
+
+ private void OnWindowClosed(Window* window)
+ {
+ if (!TryGetWindow(window, out var registration))
+ return;
+
+ _renderer.CloseWindow(registration);
+ }
private void OnWindowResized(Window* window, int width, int height)
{
diff --git a/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.Init.cs b/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.Init.cs
index 6509d6c..46c21fc 100644
--- a/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.Init.cs
+++ b/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.Init.cs
@@ -14,7 +14,7 @@ private bool GlfwInit()
}
// Set callback to handle errors
- GLFW.SetErrorCallback(OnErrorHandled);
+ GLFW.SetErrorCallback(_errorCallback);
_initialized = true;
@@ -22,9 +22,4 @@ private bool GlfwInit()
_logger.EngineInfo($"Initialize, version: {version}");
return true;
}
-
- private void OnErrorHandled(ErrorCode error, string description)
- {
- _logger.Error(GLFWHelper.FormatError(error, description));
- }
}
\ No newline at end of file
diff --git a/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.Window.cs b/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.Window.cs
index 5215b72..a7df78a 100644
--- a/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.Window.cs
+++ b/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.Window.cs
@@ -120,7 +120,7 @@ private GlfwWindowRegistration WindowSetup(Window* window, WindowCreateSettings
Pointer = window,
Id = new WindowId(_nextWindowId++),
- Ratio = framebufferSize.Ratio,
+ Ratio = framebufferSize.AspectRatio,
Size = size,
FramebufferSize = framebufferSize
};
@@ -132,10 +132,10 @@ private GlfwWindowRegistration WindowSetup(Window* window, WindowCreateSettings
SetWindowIcons(registration, settings.WindowImages.ToList());
// Setting callbacks
- GLFW.SetKeyCallback(window, OnWindowKeyHandled);
- GLFW.SetWindowCloseCallback(window, OnWindowClosed);
- GLFW.SetWindowSizeCallback(window, OnWindowResized);
- GLFW.SetWindowFocusCallback(window, OnWindowFocusChanged);
+ GLFW.SetKeyCallback(window, _keyCallback);
+ GLFW.SetWindowCloseCallback(window, _windowCloseCallback);
+ GLFW.SetWindowSizeCallback(window, _windowSizeCallback);
+ GLFW.SetWindowFocusCallback(window, _windowFocusCallback);
return registration;
}
diff --git a/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.cs b/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.cs
index 8f38686..65d3a4e 100644
--- a/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.cs
+++ b/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.cs
@@ -26,6 +26,9 @@ public bool Init()
{
DependencyManager.Inject(this);
+ // We don't let GC take our callbacks
+ HandleCallbacks();
+
if (!GlfwInit())
return false;
diff --git a/Hypercube.Client/Input/Handler/IInputHandler.cs b/Hypercube.Client/Input/Handler/IInputHandler.cs
index 635e552..f0ff620 100644
--- a/Hypercube.Client/Input/Handler/IInputHandler.cs
+++ b/Hypercube.Client/Input/Handler/IInputHandler.cs
@@ -13,4 +13,5 @@ public interface IInputHandler
// TODO: Create Analyzer to allow access only for IWindowManager implementation
void SendKeyState(KeyStateChangedArgs changedArgs);
+ bool IsKeyDown(Key key);
}
\ No newline at end of file
diff --git a/Hypercube.Client/Input/Handler/InputHandler.cs b/Hypercube.Client/Input/Handler/InputHandler.cs
index f2666fc..a11d733 100644
--- a/Hypercube.Client/Input/Handler/InputHandler.cs
+++ b/Hypercube.Client/Input/Handler/InputHandler.cs
@@ -6,7 +6,8 @@ public sealed class InputHandler : IInputHandler
{
public event Action? KeyUp;
public event Action? KeyDown;
-
+
+ private readonly HashSet _keysDown = new();
private readonly ILogger _logger = LoggingManager.GetLogger("input_handler");
public void SendKeyState(KeyStateChangedArgs changedArgs)
@@ -23,10 +24,17 @@ public void SendKeyState(KeyStateChangedArgs changedArgs)
if (changedArgs.Pressed)
{
- KeyUp?.Invoke(changedArgs);
+ KeyDown?.Invoke(changedArgs);
+ _keysDown.Add(changedArgs.Key);
return;
}
- KeyDown?.Invoke(changedArgs);
+ _keysDown.Remove(changedArgs.Key);
+ KeyUp?.Invoke(changedArgs);
+ }
+
+ public bool IsKeyDown(Key key)
+ {
+ return _keysDown.Contains(key);
}
}
\ No newline at end of file
diff --git a/Hypercube.Shared.Math/Angle.cs b/Hypercube.Shared.Math/Angle.cs
index 47f6552..e52a056 100644
--- a/Hypercube.Shared.Math/Angle.cs
+++ b/Hypercube.Shared.Math/Angle.cs
@@ -1,8 +1,16 @@
-namespace Hypercube.Shared.Math;
+using System.Runtime.CompilerServices;
+
+namespace Hypercube.Shared.Math;
public readonly struct Angle(double theta)
{
public static readonly Angle Zero = new(0);
public readonly double Theta = theta;
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator float(Angle angle)
+ {
+ return (float)angle.Theta;
+ }
}
\ No newline at end of file
diff --git a/Hypercube.Shared.Math/Color.cs b/Hypercube.Shared.Math/Color.cs
index a926016..6ecd9ee 100644
--- a/Hypercube.Shared.Math/Color.cs
+++ b/Hypercube.Shared.Math/Color.cs
@@ -1,8 +1,10 @@
using System.Globalization;
+using System.Runtime.InteropServices;
using Hypercube.Shared.Math.Vector;
namespace Hypercube.Shared.Math;
+[StructLayout(LayoutKind.Sequential)]
public readonly struct Color
{
public static readonly Color White = new(1f, 1f, 1f);
diff --git a/Hypercube.Shared.Math/Hypercube.Shared.Math.csproj b/Hypercube.Shared.Math/Hypercube.Shared.Math.csproj
index 8f59722..b60e9ec 100644
--- a/Hypercube.Shared.Math/Hypercube.Shared.Math.csproj
+++ b/Hypercube.Shared.Math/Hypercube.Shared.Math.csproj
@@ -9,6 +9,7 @@
+
diff --git a/Hypercube.Shared.Math/Matrix/Matrix3X3.Compatibility.cs b/Hypercube.Shared.Math/Matrix/Matrix3X3.Compatibility.cs
new file mode 100644
index 0000000..1d6affa
--- /dev/null
+++ b/Hypercube.Shared.Math/Matrix/Matrix3X3.Compatibility.cs
@@ -0,0 +1,39 @@
+using System.Runtime.CompilerServices;
+using OpenTK.Mathematics;
+
+namespace Hypercube.Shared.Math.Matrix;
+
+public partial struct Matrix3X3
+{
+ /*
+ * OpenTK Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Matrix3(Matrix3X3 matrix3)
+ {
+ return new Matrix3(matrix3.Row0, matrix3.Row1, matrix3.Row2);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Matrix3X3(Matrix3 matrix3)
+ {
+ return new Matrix3X3(matrix3.Row0, matrix3.Row1, matrix3.Row2);
+ }
+
+ /*
+ * OpenToolkit Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator OpenToolkit.Mathematics.Matrix3(Matrix3X3 matrix3)
+ {
+ return new OpenToolkit.Mathematics.Matrix3(matrix3.Row0, matrix3.Row1, matrix3.Row2);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Matrix3X3(OpenToolkit.Mathematics.Matrix3 matrix3)
+ {
+ return new Matrix3X3(matrix3.Row0, matrix3.Row1, matrix3.Row2);
+ }
+}
\ No newline at end of file
diff --git a/Hypercube.Shared.Math/Matrix/Matrix3X3.cs b/Hypercube.Shared.Math/Matrix/Matrix3X3.cs
index f5b1394..ddf205f 100644
--- a/Hypercube.Shared.Math/Matrix/Matrix3X3.cs
+++ b/Hypercube.Shared.Math/Matrix/Matrix3X3.cs
@@ -1,25 +1,28 @@
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using Hypercube.Shared.Math.Vector;
namespace Hypercube.Shared.Math.Matrix;
-public struct Matrix3X3(Vector3 x, Vector3 y, Vector3 z)
+// TODO: May be it's can be immutable, and also layout broken
+[StructLayout(LayoutKind.Sequential)]
+public partial struct Matrix3X3
{
- private const int IndexRaw0 = 0;
- private const int IndexRaw1 = 1;
- private const int IndexRaw2 = 2;
+ private const int IndexRow0 = 0;
+ private const int IndexRow1 = 1;
+ private const int IndexRow2 = 2;
- private const int IndexColum0 = 0;
- private const int IndexColum1 = 1;
- private const int IndexColum2 = 2;
+ private const int IndexColumn0 = 0;
+ private const int IndexColumn1 = 1;
+ private const int IndexColumn2 = 2;
public static Matrix3X3 Zero => new(Vector3.Zero);
public static Matrix3X3 One => new(Vector3.One);
- public static Matrix3X3 Identity => new(Vector3.Right, Vector3.Up, Vector3.Forward);
+ public static Matrix3X3 Identity => new(Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ);
- public Vector3 Raw0 = x;
- public Vector3 Raw1 = y;
- public Vector3 Raw2 = z;
+ public Vector3 Row0;
+ public Vector3 Row1;
+ public Vector3 Row2;
///
/// Matrix x: 0, y: 0 element.
@@ -27,9 +30,9 @@ public struct Matrix3X3(Vector3 x, Vector3 y, Vector3 z)
public float M00
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw0.X;
+ get => Row0.X;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw0 = Raw0.WithX(value);
+ set => Row0 = Row0.WithX(value);
}
///
@@ -38,9 +41,9 @@ public float M00
public float M01
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw0.Y;
+ get => Row0.Y;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw0 = Raw0.WithY(value);
+ set => Row0 = Row0.WithY(value);
}
///
@@ -49,9 +52,9 @@ public float M01
public float M02
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw0.Z;
+ get => Row0.Z;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw0 = Raw0.WithZ(value);
+ set => Row0 = Row0.WithZ(value);
}
///
@@ -60,9 +63,9 @@ public float M02
public float M10
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw1.X;
+ get => Row1.X;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw1 = Raw1.WithX(value);
+ set => Row1 = Row1.WithX(value);
}
///
@@ -71,9 +74,9 @@ public float M10
public float M11
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw1.Y;
+ get => Row1.Y;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw1 = Raw1.WithY(value);
+ set => Row1 = Row1.WithY(value);
}
///
@@ -82,9 +85,9 @@ public float M11
public float M12
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw1.Z;
+ get => Row1.Z;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw1 = Raw1.WithZ(value);
+ set => Row1 = Row1.WithZ(value);
}
///
@@ -93,9 +96,9 @@ public float M12
public float M20
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw2.X;
+ get => Row2.X;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw2 = Raw2.WithX(value);
+ set => Row2 = Row2.WithX(value);
}
///
@@ -104,9 +107,9 @@ public float M20
public float M21
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw2.Y;
+ get => Row2.Y;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw2 = Raw2.WithY(value);
+ set => Row2 = Row2.WithY(value);
}
///
@@ -115,34 +118,34 @@ public float M21
public float M22
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw2.Z;
+ get => Row2.Z;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw2 = Raw2.WithZ(value);
+ set => Row2 = Row2.WithZ(value);
}
public float this[int raw, int colum]
{
get => raw switch
{
- IndexRaw0 => colum switch
+ IndexRow0 => colum switch
{
- IndexColum0 => M00,
- IndexColum1 => M01,
- IndexColum2 => M02,
+ IndexColumn0 => M00,
+ IndexColumn1 => M01,
+ IndexColumn2 => M02,
_ => throw new ArgumentOutOfRangeException(nameof(colum), colum, null)
},
- IndexRaw1 => colum switch
+ IndexRow1 => colum switch
{
- IndexColum0 => M10,
- IndexColum1 => M11,
- IndexColum2 => M12,
+ IndexColumn0 => M10,
+ IndexColumn1 => M11,
+ IndexColumn2 => M12,
_ => throw new ArgumentOutOfRangeException(nameof(colum), colum, null)
},
- IndexRaw2 => colum switch
+ IndexRow2 => colum switch
{
- IndexColum0 => M20,
- IndexColum1 => M21,
- IndexColum2 => M22,
+ IndexColumn0 => M20,
+ IndexColumn1 => M21,
+ IndexColumn2 => M22,
_ => throw new ArgumentOutOfRangeException(nameof(colum), colum, null)
},
_ => throw new ArgumentOutOfRangeException(nameof(raw), raw, null)
@@ -151,18 +154,18 @@ public float M22
{
switch (raw)
{
- case IndexRaw0:
+ case IndexRow0:
switch (colum)
{
- case IndexColum0:
+ case IndexColumn0:
M00 = value;
break;
- case IndexColum1:
+ case IndexColumn1:
M01 = value;
break;
- case IndexColum2:
+ case IndexColumn2:
M02 = value;
break;
@@ -171,18 +174,18 @@ public float M22
}
break;
- case IndexRaw1:
+ case IndexRow1:
switch (colum)
{
- case IndexColum0:
+ case IndexColumn0:
M10 = value;
break;
- case IndexColum1:
+ case IndexColumn1:
M11 = value;
break;
- case IndexColum2:
+ case IndexColumn2:
M12 = value;
break;
@@ -191,18 +194,18 @@ public float M22
}
break;
- case IndexRaw2:
+ case IndexRow2:
switch (colum)
{
- case IndexColum0:
+ case IndexColumn0:
M20 = value;
break;
- case IndexColum1:
+ case IndexColumn1:
M21 = value;
break;
- case IndexColum2:
+ case IndexColumn2:
M22 = value;
break;
@@ -216,11 +219,33 @@ public float M22
}
}
}
+ ///
+ /// Creates 3x3 matrix
+ ///
+ /// x.X | x.Y | x.Z
+ /// y.X | y.Y | y.Z
+ /// z.X | z.Y | z.Z
+ ///
+ ///
+ public Matrix3X3(Vector3 x, Vector3 y, Vector3 z)
+ {
+ Row0 = x;
+ Row1 = y;
+ Row2 = z;
+ }
public Matrix3X3(Vector3 value) : this(value, value, value)
{
}
+ ///
+ /// Creates 3x3 matrix
+ ///
+ /// m00 | m01 | m02
+ /// m10 | m11 | m12
+ /// m20 | m21 | m22
+ ///
+ ///
public Matrix3X3(float m00, float m01, float m02,
float m10, float m11, float m12,
float m20, float m21, float m22) : this(new Vector3(m00, m01, m02),
@@ -377,6 +402,6 @@ public static Matrix3X3 CreateTransform(Vector2 position, Angle angle, Vector2 s
public static Vector3 operator *(Matrix3X3 a, Vector3 b)
{
- return a.Raw0 * b.X + a.Raw1 * b.Y + a.Raw2 * b.Z;
+ return a.Row0 * b.X + a.Row1 * b.Y + a.Row2 * b.Z;
}
}
\ No newline at end of file
diff --git a/Hypercube.Shared.Math/Matrix/Matrix4X4.Compatibility.cs b/Hypercube.Shared.Math/Matrix/Matrix4X4.Compatibility.cs
new file mode 100644
index 0000000..d626311
--- /dev/null
+++ b/Hypercube.Shared.Math/Matrix/Matrix4X4.Compatibility.cs
@@ -0,0 +1,38 @@
+using System.Runtime.CompilerServices;
+using OpenTK.Mathematics;
+
+namespace Hypercube.Shared.Math.Matrix;
+
+public partial struct Matrix4X4
+{
+ /*
+ * OpenTK Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ 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(Matrix4 matrix4)
+ {
+ return new Matrix4X4(matrix4.Row0, matrix4.Row1, matrix4.Row2, matrix4.Row3);
+ }
+
+ /*
+ * Open Toolkit Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator OpenToolkit.Mathematics.Matrix4(Matrix4X4 matrix4X4)
+ {
+ return new OpenToolkit.Mathematics.Matrix4(matrix4X4.Row0, matrix4X4.Row1, matrix4X4.Row2, matrix4X4.Row3);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Matrix4X4(OpenToolkit.Mathematics.Matrix4 matrix4)
+ {
+ return new Matrix4X4(matrix4.Row0, matrix4.Row1, matrix4.Row2, matrix4.Row3);
+ }
+}
\ No newline at end of file
diff --git a/Hypercube.Shared.Math/Matrix/Matrix4X4.cs b/Hypercube.Shared.Math/Matrix/Matrix4X4.cs
index b2d466b..17cef3d 100644
--- a/Hypercube.Shared.Math/Matrix/Matrix4X4.cs
+++ b/Hypercube.Shared.Math/Matrix/Matrix4X4.cs
@@ -1,49 +1,47 @@
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using Hypercube.Shared.Math.Box;
using Hypercube.Shared.Math.Vector;
namespace Hypercube.Shared.Math.Matrix;
-public struct Matrix4X4(Vector4 x, Vector4 y, Vector4 z, Vector4 w) : IEquatable
+[StructLayout(LayoutKind.Sequential)]
+public partial struct Matrix4X4 : IEquatable
{
public static Matrix4X4 Zero => new(Vector4.Zero);
public static Matrix4X4 One => new(Vector4.One);
- public static Matrix4X4 Identity => new(
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1);
-
- public Vector4 Raw0 = x;
- public Vector4 Raw1 = y;
- public Vector4 Raw2 = z;
- public Vector4 Raw3 = w;
-
- public Vector4 Colum0 => new(M00, M10, M20, M30);
- public Vector4 Colum1 => new(M01, M11, M21, M31);
- public Vector4 Colum2 => new(M02, M12, M22, M32);
- public Vector4 Colum3 => new(M03, M13, M23, M33);
-
+ public static Matrix4X4 Identity => new(Vector4.UnitX, Vector4.UnitY, Vector4.UnitZ, Vector4.UnitW);
+
+ public Vector4 Row0;
+ public Vector4 Row1;
+ public Vector4 Row2;
+ public Vector4 Row3;
+
+ public Vector4 Column0 => new(M00, M10, M20, M30);
+ public Vector4 Column1 => new(M01, M11, M21, M31);
+ public Vector4 Column2 => new(M02, M12, M22, M32);
+ public Vector4 Column3 => new(M03, M13, M23, M33);
+
///
/// Matrix x: 0, y: 0 element.
///
public float M00
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw0.X;
+ get => Row0.X;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw0 = Raw0.WithX(value);
+ set => Row0 = Row0.WithX(value);
}
-
+
///
/// Matrix x: 1, y: 0 element.
///
public float M01
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw0.Y;
+ get => Row0.Y;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw0 = Raw0.WithY(value);
+ set => Row0 = Row0.WithY(value);
}
///
@@ -52,9 +50,9 @@ public float M01
public float M02
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw0.Z;
+ get => Row0.Z;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw0 = Raw0.WithZ(value);
+ set => Row0 = Row0.WithZ(value);
}
///
@@ -63,147 +61,170 @@ public float M02
public float M03
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw0.W;
+ get => Row0.W;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw0 = Raw0.WithW(value);
+ set => Row0 = Row0.WithW(value);
}
-
+
///
/// Matrix x: 0, y: 1 element.
///
public float M10
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw1.X;
+ get => Row1.X;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw1 = Raw1.WithX(value);
+ set => Row1 = Row1.WithX(value);
}
-
+
///
/// Matrix x: 1, y: 1 element.
///
public float M11
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw1.Y;
+ get => Row1.Y;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw1 = Raw1.WithY(value);
+ set => Row1 = Row1.WithY(value);
}
-
+
///
/// Matrix x: 2, y: 1 element.
///
public float M12
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw1.Z;
+ get => Row1.Z;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw1 = Raw1.WithZ(value);
+ set => Row1 = Row1.WithZ(value);
}
-
+
///
/// Matrix x: 3, y: 1 element.
///
public float M13
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw1.W;
+ get => Row1.W;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw1 = Raw1.WithW(value);
+ set => Row1 = Row1.WithW(value);
}
-
+
///
/// Matrix x: 0, y: 2 element.
///
public float M20
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw2.X;
+ get => Row2.X;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw2 = Raw2.WithX(value);
+ set => Row2 = Row2.WithX(value);
}
-
+
///
/// Matrix x: 1, y: 2 element.
///
public float M21
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw2.Y;
+ get => Row2.Y;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw2 = Raw2.WithY(value);
+ set => Row2 = Row2.WithY(value);
}
-
+
///
/// Matrix x: 2, y: 2 element.
///
public float M22
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw2.Z;
+ get => Row2.Z;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw2 = Raw2.WithZ(value);
+ set => Row2 = Row2.WithZ(value);
}
-
+
///
/// Matrix x: 3, y: 2 element.
///
public float M23
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw2.W;
+ get => Row2.W;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw2 = Raw2.WithW(value);
+ set => Row2 = Row2.WithW(value);
}
-
+
///
/// Matrix x: 0, y: 3 element.
///
public float M30
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw3.X;
+ get => Row3.X;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw3 = Raw3.WithX(value);
+ set => Row3 = Row3.WithX(value);
}
-
+
///
/// Matrix x: 1, y: 3 element.
///
public float M31
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw3.Y;
+ get => Row3.Y;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw3 = Raw3.WithY(value);
+ set => Row3 = Row3.WithY(value);
}
-
+
///
/// Matrix x: 2, y: 3 element.
///
- public float M32
+ public float M32
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw3.Z;
+ get => Row3.Z;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw3 = Raw3.WithZ(value);
+ set => Row3 = Row3.WithZ(value);
}
-
+
///
/// Matrix x: 3, y: 3 element.
///
public float M33
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Raw3.W;
+ get => Row3.W;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => Raw3 = Raw3.WithW(value);
+ set => Row3 = Row3.WithW(value);
}
-
+ ///
+ /// Creates new matrix 4x4
+ ///
+ /// Row0.X | Row0.Y | Row0.Z | Row0.W
+ /// Row1.X | Row1.Y | Row1.Z | Row1.W
+ /// Row2.X | Row2.Y | Row2.Z | Row2.W
+ /// Row2.X | Row2.Y | Row2.Z | Row2.W
+ ///
+ ///
+ /// Row 0
+ /// Row 1
+ /// Row 2
+ /// Row 3
+ public Matrix4X4(Vector4 x, Vector4 y, Vector4 z, Vector4 w)
+ {
+ Row0 = x;
+ Row1 = y;
+ Row2 = z;
+ Row3 = w;
+ }
+ ///
+ /// Creates new matrix with all rows is ""
+ ///
+ /// Vector4 to make rows out of
public Matrix4X4(Vector4 value) : this(value, value, value, value)
{
}
-
+
///
/// Creating matrix
///
@@ -223,16 +244,27 @@ public Matrix4X4(float m00, float m01, float m02, float m03,
{
}
- public Matrix4X4(Matrix4X4 matrix4X4) : this(matrix4X4.Raw0, matrix4X4.Raw1, matrix4X4.Raw2, matrix4X4.Raw3)
+ public Matrix4X4(Matrix4X4 matrix4X4) : this(matrix4X4.Row0, matrix4X4.Row1, matrix4X4.Row2, matrix4X4.Row3)
{
}
-
+
public bool Equals(Matrix4X4 other)
{
- return Raw0.Equals(other.Raw0) &&
- Raw1.Equals(other.Raw1) &&
- Raw2.Equals(other.Raw2) &&
- Raw3.Equals(other.Raw3);
+ return Row0.Equals(other.Row0) &&
+ Row1.Equals(other.Row1) &&
+ Row2.Equals(other.Row2) &&
+ Row3.Equals(other.Row3);
+ }
+
+ public float[] ToArray()
+ {
+ return new float[]
+ {
+ M00, M01, M02, M03,
+ M10, M11, M12, M13,
+ M20, M21, M22, M23,
+ M30, M31, M32, M33
+ };
}
public override bool Equals(object? obj)
@@ -242,48 +274,48 @@ public override bool Equals(object? obj)
public override int GetHashCode()
{
- return HashCode.Combine(Raw0, Raw1, Raw2, Raw3);
+ return HashCode.Combine(Row0, Row1, Row2, Row3);
}
-
+
public override string ToString()
{
- return $"{Raw0}\n{Raw1}\n{Raw2}\n{Raw3}";
+ return $"{Row0}\n{Row1}\n{Row2}\n{Row3}";
}
public static Matrix4X4 operator *(Matrix4X4 a, Matrix4X4 b)
{
var result = Zero;
- result.M00 = (a.Raw0 * b.Colum0).Sum();
- result.M01 = (a.Raw0 * b.Colum1).Sum();
- result.M02 = (a.Raw0 * b.Colum2).Sum();
- result.M03 = (a.Raw0 * b.Colum3).Sum();
+ result.M00 = (a.Row0 * b.Column0).Sum();
+ result.M01 = (a.Row0 * b.Column1).Sum();
+ result.M02 = (a.Row0 * b.Column2).Sum();
+ result.M03 = (a.Row0 * b.Column3).Sum();
+
+ result.M10 = (a.Row1 * b.Column0).Sum();
+ result.M11 = (a.Row1 * b.Column1).Sum();
+ result.M12 = (a.Row1 * b.Column2).Sum();
+ result.M13 = (a.Row1 * b.Column3).Sum();
+
+ result.M20 = (a.Row2 * b.Column0).Sum();
+ result.M21 = (a.Row2 * b.Column1).Sum();
+ result.M22 = (a.Row2 * b.Column2).Sum();
+ result.M23 = (a.Row2 * b.Column3).Sum();
+
+ result.M30 = (a.Row3 * b.Column0).Sum();
+ result.M31 = (a.Row3 * b.Column1).Sum();
+ result.M32 = (a.Row3 * b.Column2).Sum();
+ result.M33 = (a.Row3 * b.Column3).Sum();
- result.M10 = (a.Raw1 * b.Colum0).Sum();
- result.M11 = (a.Raw1 * b.Colum1).Sum();
- result.M12 = (a.Raw1 * b.Colum2).Sum();
- result.M13 = (a.Raw1 * b.Colum3).Sum();
-
- result.M20 = (a.Raw2 * b.Colum0).Sum();
- result.M21 = (a.Raw2 * b.Colum1).Sum();
- result.M22 = (a.Raw2 * b.Colum2).Sum();
- result.M23 = (a.Raw2 * b.Colum3).Sum();
-
- result.M30 = (a.Raw3 * b.Colum0).Sum();
- result.M31 = (a.Raw3 * b.Colum1).Sum();
- result.M32 = (a.Raw3 * b.Colum2).Sum();
- result.M33 = (a.Raw3 * b.Colum3).Sum();
-
return result;
}
-
+
public static Vector4 operator *(Matrix4X4 a, Vector4 b)
{
return new Vector4(
- (a.Raw0 * b).Sum(),
- (a.Raw1 * b).Sum(),
- (a.Raw2 * b).Sum(),
- (a.Raw3 * b).Sum());
+ (a.Row0 * b).Sum(),
+ (a.Row1 * b).Sum(),
+ (a.Row2 * b).Sum(),
+ (a.Row3 * b).Sum());
}
public static bool operator ==(Matrix4X4 a, Matrix4X4 b)
@@ -296,20 +328,26 @@ public override string ToString()
return !a.Equals(b);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Matrix4X4 Transpose(Matrix4X4 matrix4X4)
+ {
+ return new Matrix4X4(matrix4X4.Column0, matrix4X4.Column1, matrix4X4.Column2, matrix4X4.Column3);
+ }
+
///
/// Creating scale matrix
///
/// v | 0 | 0 | 0
/// 0 | v | 0 | 0
/// 0 | 0 | v | 0
- /// 0 | 0 | 0 | v
+ /// 0 | 0 | 0 | 1
///
///
public static Matrix4X4 CreateScale(float value)
{
- return CreateScale(value, value, value, value);
+ return CreateScale(value, value, value);
}
-
+
///
/// Creating scale matrix
///
@@ -321,9 +359,9 @@ public static Matrix4X4 CreateScale(float value)
///
public static Matrix4X4 CreateScale(Vector2 scale)
{
- return CreateScale(scale.X, scale.Y, 1f, 1f);
+ return CreateScale(scale.X, scale.Y, 1f);
}
-
+
///
/// Creating scale matrix
///
@@ -335,9 +373,9 @@ public static Matrix4X4 CreateScale(Vector2 scale)
///
public static Matrix4X4 CreateScale(Vector3 scale)
{
- return CreateScale(scale.X, scale.Y, scale.Z, 1f);
+ return CreateScale(scale.X, scale.Y, scale.Z);
}
-
+
///
/// Creating scale matrix
///
@@ -347,42 +385,200 @@ public static Matrix4X4 CreateScale(Vector3 scale)
/// 0 | 0 | 0 | 1
///
///
- public static Matrix4X4 CreateScale(float x, float y, float z, float w)
+ public static Matrix4X4 CreateScale(float x, float y, float z)
{
var result = Identity;
result.M00 = x;
result.M11 = y;
result.M22 = z;
- result.M33 = w;
return result;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Matrix4X4 CreateRotation(Vector3 direction, float angle)
+ {
+ var cos = MathF.Cos(-angle);
+ var sin = MathF.Sin(-angle);
+ var t = 1.0f - cos;
+
+ direction = direction.Normalized;
+
+ return new Matrix4X4(
+ t * direction.X * direction.X + cos,
+ t * direction.X * direction.Y - sin * direction.Z,
+ t * direction.X * direction.Z + sin * direction.Y,
+ 0,
+ t * direction.X * direction.Y + sin * direction.Z,
+ t * direction.Y * direction.Y + cos,
+ t * direction.Y * direction.Z - sin * direction.X,
+ 0,
+ t * direction.X * direction.Z - sin * direction.Y,
+ t * direction.Y * direction.Z + sin * direction.X,
+ t * direction.Z * direction.Z + cos,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1
+ );
+ }
+
+ ///
+ /// Creating rotation axis X matrix
+ ///
+ /// 1 | 0 | 0 | 0
+ /// 0 | cos | sin | 0
+ /// 0 | -sin | cos | 0
+ /// 0 | 0 | 0 | 1
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Matrix4X4 CreateRotationX(float angle)
+ {
+ var cos = MathF.Cos(angle);
+ var sin = MathF.Sin(angle);
+
+ return new Matrix4X4(
+ Vector4.UnitX,
+ new Vector4(0, cos, sin, 0),
+ new Vector4(0, -sin, cos, 0),
+ Vector4.UnitW
+ );
+ }
+
///
- /// Creating orthographic matrix
+ /// Creating rotation axis Y matrix
///
- /// 2 / (r - l) | 0 | 0 | -(r + l) / (r - l)
- /// 0 | 2 / (t - b) | 0 | -(t + b) / (t - b)
- /// 0 | 0 | -2 / (zF - zN) | -(zF + zN) / (zF - zN)
- /// 0 | 0 | 0 | 1
+ /// cos | 0 | -sin | 0
+ /// 0 | 1 | 0 | 0
+ /// sin | 0 | cos | 0
+ /// 0 | 0 | 0 | 1
///
///
- public static Matrix4X4 CreateOrthographic(Box2 box2, float zNear, float zFar)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Matrix4X4 CreateRotationY(float angle)
+ {
+ var cos = MathF.Cos(angle);
+ var sin = MathF.Sin(angle);
+
+ return new Matrix4X4(
+ new Vector4(cos, 0, -sin, 0),
+ Vector4.UnitY,
+ new Vector4(sin, 0, cos, 0),
+ Vector4.UnitW
+ );
+ }
+
+ ///
+ /// Creating rotation axis Z matrix
+ ///
+ /// cos | sin | 0 | 0
+ /// -sin | cos | 0 | 0
+ /// 0 | 0 | 1 | 0
+ /// 0 | 0 | 0 | 1
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Matrix4X4 CreateRotationZ(float angle)
+ {
+ var cos = MathF.Cos(angle);
+ var sin = MathF.Sin(angle);
+
+ return new Matrix4X4(
+ new Vector4(cos, sin, 0, 0),
+ new Vector4(-sin, cos, 0, 0),
+ Vector4.UnitZ,
+ Vector4.UnitW
+ );
+ }
+
+ ///
+ /// Creating translate matrix
+ ///
+ /// 1 | 0 | 0 | v
+ /// 0 | 1 | 0 | v
+ /// 0 | 0 | 1 | v
+ /// 0 | 0 | 0 | 1
+ ///
+ ///
+ public static Matrix4X4 CreateTranslation(float value)
+ {
+ return CreateTranslation(value, value, value);
+ }
+
+ ///
+ /// Creating translate matrix
+ ///
+ /// 1 | 0 | 0 | x
+ /// 0 | 1 | 0 | y
+ /// 0 | 0 | 1 | 0
+ /// 0 | 0 | 0 | 1
+ ///
+ ///
+ public static Matrix4X4 CreateTranslation(Vector2 vector2)
+ {
+ return CreateTranslation(vector2.X, vector2.Y, 0f);
+ }
+
+ ///
+ /// Creating translate matrix
+ ///
+ /// 1 | 0 | 0 | x
+ /// 0 | 1 | 0 | y
+ /// 0 | 0 | 1 | z
+ /// 0 | 0 | 0 | 1
+ ///
+ ///
+ public static Matrix4X4 CreateTranslation(Vector3 vector3)
+ {
+ return CreateTranslation(vector3.X, vector3.Y, vector3.Z);
+ }
+
+ ///
+ /// Creating translate matrix
+ ///
+ /// 1 | 0 | 0 | x
+ /// 0 | 1 | 0 | y
+ /// 0 | 0 | 1 | z
+ /// 0 | 0 | 0 | 1
+ ///
+ ///
+ public static Matrix4X4 CreateTranslation(float x, float y, float z)
{
var result = Identity;
- result.M00 = 2 / (box2.Right - box2.Left);
- result.M11 = 2 / (box2.Top - box2.Bottom);
- result.M22 = -2 / (zFar - zNear);
+ result.M03 = x;
+ result.M13 = y;
+ result.M23 = z;
- result.M03 = -(box2.Right + box2.Left) / (box2.Right - box2.Left);
- result.M13 = -(box2.Top + box2.Bottom) / (box2.Top - box2.Bottom);
- result.M23 = -(zFar + zNear) / (zFar - zNear);
-
return result;
}
+
+ public static Matrix4X4 CreateOrthographic(Box2 box2, float zNear, float zFar)
+ {
+ return CreateOrthographic(box2.Width, box2.Height, zNear, zFar);
+ }
+ public static Matrix4X4 CreateOrthographic(Vector2 size, float zNear, float zFar)
+ {
+ return CreateOrthographic(size.X, size.Y, zNear, zFar);
+ }
+
+ public static Matrix4X4 CreateOrthographic(float width, float height, float zNear, float zFar)
+ {
+ var result = Identity;
+ var range = 1.0f / (zNear - zFar);
+
+ result.Row0 = new Vector4(2.0f / width, 0, 0, 0);
+ result.Row1 = new Vector4(0, 2.0f / height, 0, 0);
+ result.Row2 = new Vector4(0, 0, range, 0);
+ result.Row3 = new Vector4(0, 0, range * zNear, 1);
+
+ return result;
+ }
+
///
/// Creating perspective matrix
///
@@ -404,16 +600,15 @@ public static Matrix4X4 CreatePerspective(float fov, float aspect, float zNear,
{
var result = Zero;
- var halfFov = fov / 2;
- var tanHalfFov = (float)System.Math.Tan(halfFov);
- var zDelta = zFar - zNear;
-
- result.M00 = 1 / (aspect * tanHalfFov);
- result.M11 = 1 / tanHalfFov;
- result.M22 = zFar / zDelta;
- result.M23 = 1;
- result.M32 = zFar * zNear / zDelta;
+ var height = 1.0f / MathF.Tan(fov * 0.5f);
+ var width = height / aspect;
+ var range = float.IsPositiveInfinity(zFar) ? -1.0f : zFar / (zNear - zFar);
+ result.Row0 = new Vector4(width, 0, 0, 0);
+ result.Row1 = new Vector4(0, height, 0, 0);
+ result.Row2 = new Vector4(0, 0, range, -1.0f);
+ result.Row3 = new Vector4(0, 0, range * zNear, 0);
+
return result;
}
-}
\ No newline at end of file
+}
diff --git a/Hypercube.Shared.Math/Vector/Vector2.Compability.cs b/Hypercube.Shared.Math/Vector/Vector2.Compability.cs
deleted file mode 100644
index 5462fa9..0000000
--- a/Hypercube.Shared.Math/Vector/Vector2.Compability.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System.Runtime.CompilerServices;
-
-namespace Hypercube.Shared.Math.Vector;
-
-public readonly partial struct Vector2
-{
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator Vector2(System.Numerics.Vector2 vector)
- {
- return new Vector2(vector.X, vector.Y);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator System.Numerics.Vector2(Vector2 vector)
- {
- return new System.Numerics.Vector2(vector.X, vector.Y);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator Vector2(OpenTK.Mathematics.Vector2 vector)
- {
- return new Vector2(vector.X, vector.Y);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator OpenTK.Mathematics.Vector2(Vector2 vector)
- {
- return new OpenTK.Mathematics.Vector2(vector.X, vector.Y);
- }
-}
\ No newline at end of file
diff --git a/Hypercube.Shared.Math/Vector/Vector2.Compatibility.cs b/Hypercube.Shared.Math/Vector/Vector2.Compatibility.cs
new file mode 100644
index 0000000..b79f9eb
--- /dev/null
+++ b/Hypercube.Shared.Math/Vector/Vector2.Compatibility.cs
@@ -0,0 +1,86 @@
+using System.Runtime.CompilerServices;
+
+namespace Hypercube.Shared.Math.Vector;
+
+public readonly partial struct Vector2
+{
+ /*
+ * Self Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector2Int(Vector2 vector)
+ {
+ return new Vector2Int((int)vector.X, (int)vector.Y);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector3(Vector2 vector)
+ {
+ return new Vector3(vector.X, vector.Y, 0f);
+ }
+
+ /*
+ * Tuple Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector2((float x, float y) a)
+ {
+ return new Vector2(a.x, a.y);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator (float x, float y)(Vector2 a)
+ {
+ return (a.X, a.Y);
+ }
+
+ /*
+ * System.Numerics Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector2(System.Numerics.Vector2 vector)
+ {
+ return new Vector2(vector.X, vector.Y);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator System.Numerics.Vector2(Vector2 vector)
+ {
+ return new System.Numerics.Vector2(vector.X, vector.Y);
+ }
+
+ /*
+ * OpenTK Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector2(OpenTK.Mathematics.Vector2 vector)
+ {
+ return new Vector2(vector.X, vector.Y);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator OpenTK.Mathematics.Vector2(Vector2 vector)
+ {
+ return new OpenTK.Mathematics.Vector2(vector.X, vector.Y);
+ }
+
+ /*
+ * OpenToolkit Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector2(OpenToolkit.Mathematics.Vector2 vector)
+ {
+ return new Vector2(vector.X, vector.Y);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator OpenToolkit.Mathematics.Vector2(Vector2 vector)
+ {
+ return new OpenToolkit.Mathematics.Vector2(vector.X, vector.Y);
+ }
+}
\ No newline at end of file
diff --git a/Hypercube.Shared.Math/Vector/Vector2.cs b/Hypercube.Shared.Math/Vector/Vector2.cs
index 61b3cf9..4742380 100644
--- a/Hypercube.Shared.Math/Vector/Vector2.cs
+++ b/Hypercube.Shared.Math/Vector/Vector2.cs
@@ -1,25 +1,36 @@
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
namespace Hypercube.Shared.Math.Vector;
-public readonly partial struct Vector2(float x, float y) : IEquatable
+[StructLayout(LayoutKind.Sequential)]
+public readonly partial struct Vector2 : IEquatable
{
public static readonly Vector2 Zero = new(0, 0);
public static readonly Vector2 One = new(1, 1);
- public static readonly Vector2 Up = new(0, 1);
- public static readonly Vector2 Down = new(0, -1);
- public static readonly Vector2 Right = new(1, 0);
- public static readonly Vector2 Left = new(-1, 0);
+
public static readonly Vector2 UnitX = new(1, 0);
public static readonly Vector2 UnitY = new(0, 1);
- public readonly float X = x;
- public readonly float Y = y;
+ public readonly float X;
+ public readonly float Y;
+ public float AspectRatio
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => X / Y;
+ }
+
public float Length
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => MathF.Sqrt(x * x + y * y);
+ get => MathF.Sqrt(X * X + Y * Y);
+ }
+
+ public Vector2(float x, float y)
+ {
+ X = x;
+ Y = y;
}
public Vector2(float value) : this(value, value)
@@ -63,7 +74,7 @@ public override int GetHashCode()
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string ToString()
{
- return $"{x}, {y}";
+ return $"{X}, {Y}";
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/Hypercube.Shared.Math/Vector/Vector2Int.Compability.cs b/Hypercube.Shared.Math/Vector/Vector2Int.Compability.cs
deleted file mode 100644
index f1df15b..0000000
--- a/Hypercube.Shared.Math/Vector/Vector2Int.Compability.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System.Runtime.CompilerServices;
-
-namespace Hypercube.Shared.Math.Vector;
-
-public readonly partial struct Vector2Int
-{
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator Vector2Int(System.Drawing.Size size)
- {
- return new Vector2Int(size.Width, size.Height);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator System.Drawing.Size(Vector2Int vector2)
- {
- return new System.Drawing.Size(vector2.X, vector2.Y);
- }
-}
\ No newline at end of file
diff --git a/Hypercube.Shared.Math/Vector/Vector2Int.Compatibility.cs b/Hypercube.Shared.Math/Vector/Vector2Int.Compatibility.cs
new file mode 100644
index 0000000..fc6d717
--- /dev/null
+++ b/Hypercube.Shared.Math/Vector/Vector2Int.Compatibility.cs
@@ -0,0 +1,86 @@
+using System.Runtime.CompilerServices;
+
+namespace Hypercube.Shared.Math.Vector;
+
+public readonly partial struct Vector2Int
+{
+ /*
+ * Self Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector2(Vector2Int vector)
+ {
+ return new Vector2(vector.X, vector.Y);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector3(Vector2Int vector)
+ {
+ return new Vector3(vector.X, vector.Y, 0f);
+ }
+
+ /*
+ * Tuple Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector2Int((int x, int y) a)
+ {
+ return new Vector2Int(a.x, a.y);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator (int x, int y)(Vector2Int a)
+ {
+ return (a.X, a.Y);
+ }
+
+ /*
+ * System.Drawing Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector2Int(System.Drawing.Size size)
+ {
+ return new Vector2Int(size.Width, size.Height);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator System.Drawing.Size(Vector2Int vector2)
+ {
+ return new System.Drawing.Size(vector2.X, vector2.Y);
+ }
+
+ /*
+ * OpenTK Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector2Int(OpenTK.Mathematics.Vector2i vector)
+ {
+ return new Vector2Int(vector.X, vector.Y);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator OpenTK.Mathematics.Vector2i(Vector2Int vector)
+ {
+ return new OpenTK.Mathematics.Vector2i(vector.X, vector.Y);
+ }
+
+ /*
+ * OpenToolkit Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector2Int(OpenToolkit.Mathematics.Vector2i vector)
+ {
+ return new Vector2Int(vector.X, vector.Y);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator OpenToolkit.Mathematics.Vector2i(Vector2Int vector)
+ {
+ return new OpenToolkit.Mathematics.Vector2i(vector.X, vector.Y);
+ }
+}
\ No newline at end of file
diff --git a/Hypercube.Shared.Math/Vector/Vector2Int.cs b/Hypercube.Shared.Math/Vector/Vector2Int.cs
index 63aaf8e..554e67f 100644
--- a/Hypercube.Shared.Math/Vector/Vector2Int.cs
+++ b/Hypercube.Shared.Math/Vector/Vector2Int.cs
@@ -1,110 +1,158 @@
-namespace Hypercube.Shared.Math.Vector;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
-public readonly partial struct Vector2Int(int x, int y)
+namespace Hypercube.Shared.Math.Vector;
+
+[StructLayout(LayoutKind.Sequential)]
+public readonly partial struct Vector2Int : IEquatable
{
public static readonly Vector2Int Zero = new(0, 0);
public static readonly Vector2Int One = new(1, 1);
- public static readonly Vector2Int Up = new(0, 1);
- public static readonly Vector2Int Down = new(0, -1);
- public static readonly Vector2Int Right = new(1, 0);
- public static readonly Vector2Int Left = new(-1, 0);
+
+ public static readonly Vector2Int UnitX = new(1, 0);
+ public static readonly Vector2Int UnitY = new(0, 1);
+
+ public readonly int X;
+ public readonly int Y;
- public readonly int X = x;
- public readonly int Y = y;
- public readonly float Ratio = x / (float)y;
+ public float AspectRatio
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => X / (float)Y;
+ }
+
+ public float Length
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => MathF.Sqrt(X * X + Y * Y);
+ }
+ public Vector2Int(int x, int y)
+ {
+ X = x;
+ Y = y;
+ }
+
+ public Vector2Int(int value) : this(value, value)
+ {
+ }
+
+ public Vector2Int(Vector2Int vector2Int) : this(vector2Int.X, vector2Int.Y)
+ {
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector2Int WithX(int value)
+ {
+ return new Vector2Int(value, Y);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector2Int WithY(int value)
+ {
+ return new Vector2Int(X, value);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool Equals(Vector2Int other)
+ {
+ return X == other.X &&
+ Y == other.Y;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override bool Equals(object? obj)
+ {
+ return obj is Vector2Int vector && Equals(vector);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(X, Y);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override string ToString()
+ {
+ return $"{X}, {Y}";
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2Int operator +(Vector2Int a, Vector2Int b)
{
return new Vector2Int(a.X + b.X, a.Y + b.Y);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2Int operator +(Vector2Int a, int b)
{
return new Vector2Int(a.X + b, a.Y + b);
}
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector2Int operator -(Vector2Int a)
+ {
+ return new Vector2Int(-a.X, -a.Y);
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2Int operator -(Vector2Int a, Vector2Int b)
{
return new Vector2Int(a.X - b.X, a.Y - b.Y);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2Int operator -(Vector2Int a, int b)
{
return new Vector2Int(a.X - b, a.Y - b);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2Int operator *(Vector2Int a, Vector2Int b)
{
return new Vector2Int(a.X * b.X, a.Y * b.Y);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2Int operator *(Vector2Int a, int b)
{
return new Vector2Int(a.X * b, a.Y * b);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 operator *(Vector2Int a, float b)
{
return new Vector2(a.X * b, a.Y * b);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2Int operator /(Vector2Int a, Vector2Int b)
{
return new Vector2Int(a.X / b.X, a.Y / b.Y);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2Int operator /(Vector2Int a, int b)
{
return new Vector2Int(a.X / b, a.Y / b);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 operator /(Vector2Int a, float b)
{
return new Vector2(a.X / b, a.Y / b);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Vector2Int a, Vector2Int b)
{
return a.Equals(b);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Vector2Int a, Vector2Int b)
{
return !a.Equals(b);
}
-
- public static implicit operator Vector2(Vector2Int a)
- {
- return new Vector2(a.X, a.Y);
- }
-
- public static implicit operator Vector2Int(Vector2 a)
- {
- return new Vector2Int((int)a.X, (int)a.Y);
- }
-
- public static implicit operator Vector2Int((int x, int y) a)
- {
- return new Vector2Int(a.x, a.y);
- }
-
- public readonly bool Equals(Vector2Int other)
- {
- return X == other.X && Y == other.Y;
- }
-
- public readonly override bool Equals(object? obj)
- {
- return obj is Vector2Int vector && Equals(vector);
- }
-
- public override int GetHashCode()
- {
- return x + y;
- }
-
- public override string ToString()
- {
- return $"{x}, {y}";
- }
}
\ No newline at end of file
diff --git a/Hypercube.Shared.Math/Vector/Vector3.Compatibility.cs b/Hypercube.Shared.Math/Vector/Vector3.Compatibility.cs
new file mode 100644
index 0000000..5236e58
--- /dev/null
+++ b/Hypercube.Shared.Math/Vector/Vector3.Compatibility.cs
@@ -0,0 +1,86 @@
+using System.Runtime.CompilerServices;
+
+namespace Hypercube.Shared.Math.Vector;
+
+public readonly partial struct Vector3
+{
+ /*
+ * Self Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector2(Vector3 vector)
+ {
+ return new Vector2(vector.X, vector.Y);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector2Int(Vector3 vector)
+ {
+ return new Vector2Int((int)vector.X, (int)vector.Y);
+ }
+
+ /*
+ * Tuple Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector3((float x, float y, float z) a)
+ {
+ return new Vector3(a.x, a.y, a.z);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator (float x, float y, float z)(Vector3 a)
+ {
+ return (a.X, a.Y, a.Z);
+ }
+
+ /*
+ * System.Numerics Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator System.Numerics.Vector3(Vector3 vector3)
+ {
+ return new System.Numerics.Vector3(vector3.X, vector3.Y, vector3.Z);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector3(System.Numerics.Vector3 vector3)
+ {
+ return new Vector3(vector3.X, vector3.Y, vector3.Z);
+ }
+
+ /*
+ * OpenTK Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator OpenTK.Mathematics.Vector3(Vector3 vector)
+ {
+ return new OpenTK.Mathematics.Vector3(vector.X, vector.Y, vector.Z);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector3(OpenTK.Mathematics.Vector3 vector)
+ {
+ return new Vector3(vector.X, vector.Y, vector.Z);
+ }
+
+ /*
+ * OpenToolkit Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator OpenToolkit.Mathematics.Vector3(Vector3 vector)
+ {
+ return new OpenToolkit.Mathematics.Vector3(vector.X, vector.Y, vector.Z);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector3(OpenToolkit.Mathematics.Vector3 vector)
+ {
+ return new Vector3(vector.X, vector.Y, vector.Z);
+ }
+}
\ No newline at end of file
diff --git a/Hypercube.Shared.Math/Vector/Vector3.cs b/Hypercube.Shared.Math/Vector/Vector3.cs
index 6bc7cd8..e9f8463 100644
--- a/Hypercube.Shared.Math/Vector/Vector3.cs
+++ b/Hypercube.Shared.Math/Vector/Vector3.cs
@@ -1,17 +1,15 @@
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Hypercube.Shared.Math.Extensions;
namespace Hypercube.Shared.Math.Vector;
-public readonly struct Vector3(float x, float y, float z)
+[StructLayout(LayoutKind.Sequential)]
+public readonly partial struct Vector3(float x, float y, float z) : IEquatable
{
public static readonly Vector3 Zero = new(0, 0, 0);
public static readonly Vector3 One = new(1, 1, 1);
- public static readonly Vector3 Forward = new(0, 0, 1);
- public static readonly Vector3 Back = new(0, 0, -1);
- public static readonly Vector3 Up = new(0, 1, 0);
- public static readonly Vector3 Down = new(0, -1, 0);
- public static readonly Vector3 Right = new(1, 0, 0);
- public static readonly Vector3 Left = new(-1, 0, 0);
+
public static readonly Vector3 UnitX = new(1, 0, 0);
public static readonly Vector3 UnitY = new(0, 1, 0);
public static readonly Vector3 UnitZ = new(0, 0, 1);
@@ -20,10 +18,26 @@ public readonly struct Vector3(float x, float y, float z)
public readonly float Y = y;
public readonly float Z = z;
+ public float Length
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => MathF.Sqrt(X * X + Y * Y + Z * Z);
+ }
+
+ public Vector3 Normalized
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => this / Length;
+ }
+
public Vector3(float value) : this(value, value, value)
{
}
+ public Vector3(Vector2 vector2) : this(vector2.X, vector2.Y, 0)
+ {
+ }
+
public Vector3(Vector2 vector2, float z) : this(vector2.X, vector2.Y, z)
{
}
@@ -56,6 +70,38 @@ public Vector3 WithZ(float value)
return new Vector3(X, Y, value);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector3 Cross(Vector3 other)
+ {
+ return Vector3.Cross(this, other);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool Equals(Vector3 other)
+ {
+ return X.AboutEquals(other.X) &&
+ Y.AboutEquals(other.Y) &&
+ Z.AboutEquals(other.Z);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override bool Equals(object? obj)
+ {
+ return obj is Vector3 other && Equals(other);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(X, Y, Z);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override string ToString()
+ {
+ return $"{x}, {y}, {z}";
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 operator +(Vector3 a, Vector3 b)
{
@@ -135,8 +181,23 @@ public Vector3 WithZ(float value)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public override string ToString()
+ public static bool operator ==(Vector3 a, Vector3 b)
{
- return $"{x}, {y}, {z}";
+ return a.Equals(b);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator !=(Vector3 a, Vector3 b)
+ {
+ return !a.Equals(b);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector3 Cross(Vector3 left, Vector3 right)
+ {
+ return new Vector3(
+ left.Y * right.Z - left.Z * right.Y,
+ left.Z * right.X - left.X * right.Z,
+ left.X * right.Y - left.Y * right.X);
}
}
\ No newline at end of file
diff --git a/Hypercube.Shared.Math/Vector/Vector4.Compatibility.cs b/Hypercube.Shared.Math/Vector/Vector4.Compatibility.cs
new file mode 100644
index 0000000..61adf86
--- /dev/null
+++ b/Hypercube.Shared.Math/Vector/Vector4.Compatibility.cs
@@ -0,0 +1,54 @@
+using System.Runtime.CompilerServices;
+
+namespace Hypercube.Shared.Math.Vector;
+
+public readonly partial struct Vector4
+{
+ /*
+ * System.Numerics Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector4(System.Numerics.Vector4 vector4)
+ {
+ return new Vector4(vector4.X, vector4.Y, vector4.Z, vector4.W);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator System.Numerics.Vector4(Vector4 vector4)
+ {
+ return new System.Numerics.Vector4(vector4.X, vector4.Y, vector4.Z, vector4.W);
+ }
+
+ /*
+ * OpenTK Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector4(OpenTK.Mathematics.Vector4 vector4)
+ {
+ return new Vector4(vector4.X, vector4.Y, vector4.Z, vector4.W);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator OpenTK.Mathematics.Vector4(Vector4 vector4)
+ {
+ return new OpenTK.Mathematics.Vector4(vector4.X, vector4.Y, vector4.Z, vector4.W);
+ }
+
+ /*
+ * OpenToolkit Compatibility
+ */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator OpenToolkit.Mathematics.Vector4(Vector4 vector4)
+ {
+ return new OpenToolkit.Mathematics.Vector4(vector4.X, vector4.Y, vector4.Z, vector4.W);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Vector4(OpenToolkit.Mathematics.Vector4 vector4)
+ {
+ return new Vector4(vector4.X, vector4.Y, vector4.Z, vector4.W);
+ }
+}
\ No newline at end of file
diff --git a/Hypercube.Shared.Math/Vector/Vector4.cs b/Hypercube.Shared.Math/Vector/Vector4.cs
index d1e9486..224dcb1 100644
--- a/Hypercube.Shared.Math/Vector/Vector4.cs
+++ b/Hypercube.Shared.Math/Vector/Vector4.cs
@@ -1,22 +1,33 @@
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using Hypercube.Shared.Math.Extensions;
namespace Hypercube.Shared.Math.Vector;
-public readonly struct Vector4(float x, float y, float z, float w) : IEquatable
+[StructLayout(LayoutKind.Sequential)]
+public readonly partial struct Vector4 : IEquatable
{
public static readonly Vector4 Zero = new(0, 0, 0, 0);
public static readonly Vector4 One = new(1, 1, 1, 1);
+
public static readonly Vector4 UnitX = new(1, 0, 0, 0);
public static readonly Vector4 UnitY = new(0, 1, 0, 0);
public static readonly Vector4 UnitZ = new(0, 0, 1, 0);
public static readonly Vector4 UnitW = new(0, 0, 0, 1);
- public readonly float X = x;
- public readonly float Y = y;
- public readonly float Z = z;
- public readonly float W = w;
+ public readonly float X;
+ public readonly float Y;
+ public readonly float Z;
+ public readonly float W;
+ public Vector4(float x, float y, float z, float w)
+ {
+ X = x;
+ Y = y;
+ Z = z;
+ W = w;
+ }
+
public Vector4(float value) : this(value, value, value, value)
{
}
@@ -25,7 +36,7 @@ public Vector4(Vector2 vector2, float z, float w) : this(vector2.X, vector2.Y, z
{
}
- public Vector4(Vector4 Vector4, float w) : this(Vector4.X, Vector4.Y, Vector4.Z, w)
+ public Vector4(Vector4 vector4, float w) : this(vector4.X, vector4.Y, vector4.Z, w)
{
}
@@ -79,7 +90,7 @@ public override bool Equals(object? obj)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string ToString()
{
- return $"{x}, {y}, {z}, {w}";
+ return $"{X}, {Y}, {Z}, {W}";
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/Resources/Shaders/base.frag b/Resources/Shaders/base.frag
index e58fb8f..88f9e22 100644
--- a/Resources/Shaders/base.frag
+++ b/Resources/Shaders/base.frag
@@ -8,6 +8,6 @@ in vec2 TexCoord;
uniform sampler2D texture0;
void main()
-{
- FragColor = texture(texture0, TexCoord) * Color;
+{
+ FragColor = texture(texture0, TexCoord) * Color;
}
\ No newline at end of file
diff --git a/Resources/Shaders/base.vert b/Resources/Shaders/base.vert
index 9a5affb..b663ed1 100644
--- a/Resources/Shaders/base.vert
+++ b/Resources/Shaders/base.vert
@@ -7,10 +7,14 @@ layout (location = 2) in vec2 aTexCoord;
out vec4 Color;
out vec2 TexCoord;
+uniform mat4 projection;
+uniform mat4 model;
+uniform mat4 view;
+
void main()
{
- gl_Position = vec4(aPos, 1.0);
+ gl_Position = vec4(aPos, 1.0) * model * view * projection;
- Color = aColor;
- TexCoord = aTexCoord;
+ Color = aColor;
+ TexCoord = aTexCoord;
}
\ No newline at end of file