BREAKING CHANGE: 4x4 matrices are now column major

This commit is contained in:
2026-01-27 23:45:50 +03:00
parent 9294df8a19
commit 08f32f96e4
3 changed files with 54 additions and 52 deletions

View File

@@ -6,7 +6,7 @@ namespace Engine.Core;
// TODO Comments
/// <summary>
/// Represents a 4D left handed space matrix.
/// Represents a 4D left handed space matrix in a Column Major convention.
/// </summary>
/// <remarks>
/// Initializes a new instance of the <see cref="Matrix4x4"/> struct with the specified values.
@@ -220,10 +220,10 @@ public readonly struct Matrix4x4(
);
public static Matrix4x4 CreateTranslation(Vector3D position) => new(
1f, 0f, 0f, 0f,
0f, 1f, 0f, 0f,
0f, 0f, 1f, 0f,
position.X, position.Y, position.Z, 1
1f, 0f, 0f, position.X,
0f, 1f, 0f, position.Y,
0f, 0f, 1f, position.Z,
0f, 0f, 0f, 1f
);
public static Matrix4x4 CreateScale(float scale) => new(
@@ -245,10 +245,10 @@ public readonly struct Matrix4x4(
float c = Math.Cos(radians);
float s = Math.Sin(radians);
return new Matrix4x4(
return new(
1f, 0f, 0f, 0f,
0f, c, s, 0f,
0f, -s, c, 0f,
0f, c, -s, 0f,
0f, s, c, 0f,
0f, 0f, 0f, 1f
);
}
@@ -258,10 +258,10 @@ public readonly struct Matrix4x4(
float c = Math.Cos(radians);
float s = Math.Sin(radians);
return new Matrix4x4(
c, 0f, -s, 0f,
return new(
c, 0f, s, 0f,
0f, 1f, 0f, 0f,
s, 0f, c, 0f,
-s, 0f, c, 0f,
0f, 0f, 0f, 1f
);
}
@@ -271,9 +271,9 @@ public readonly struct Matrix4x4(
float c = Math.Cos(radians);
float s = Math.Sin(radians);
return new Matrix4x4(
c, s, 0f, 0f,
-s, c, 0f, 0f,
return new(
c, -s, 0f, 0f,
s, c, 0f, 0f,
0f, 0f, 1f, 0f,
0f, 0f, 0f, 1f
);
@@ -292,7 +292,7 @@ public readonly struct Matrix4x4(
Vector3D x = up.Cross(z).Normalized;
Vector3D y = z.Cross(x);
return new Matrix4x4(
return new(
x.X, y.X, z.X, 0f,
x.Y, y.Y, z.Y, 0f,
x.Z, y.Z, z.Z, 0f,
@@ -302,15 +302,15 @@ public readonly struct Matrix4x4(
public static Matrix4x4 CreateLookMatrix(Vector3D position, Vector3D target, Vector3D up)
{
Vector3D z = position.FromTo(target).Normalized;
Vector3D x = up.Cross(z).Normalized;
Vector3D y = z.Cross(x);
Vector3D f = (target - position).Normalized;
Vector3D s = f.Cross(up).Normalized;
Vector3D u = s.Cross(f);
return new Matrix4x4(
x.X, y.X, z.X, 0f,
x.Y, y.Y, z.Y, 0f,
x.Z, y.Z, z.Z, 0f,
-x.Dot(position), -y.Dot(position), -z.Dot(position), 1f
return new(
s.X, u.X, -f.X, 0f,
s.Y, u.Y, -f.Y, 0f,
s.Z, u.Z, -f.Z, 0f,
-s.Dot(position), -u.Dot(position), f.Dot(position), 1f
);
}
@@ -318,10 +318,10 @@ public readonly struct Matrix4x4(
{
float invDepth = 1f / (farPlane - nearPlane);
return new Matrix4x4(
return new(
2f / width, 0f, 0f, 0f,
0f, -2f / height, 0f, 0f,
0f, 0f, invDepth, 0f,
0f, 0f, 1f * invDepth, 0f,
-1f, 1f, -nearPlane * invDepth, 1f
);
}
@@ -330,24 +330,25 @@ public readonly struct Matrix4x4(
{
float invDepth = 1f / (farPlane - nearPlane);
return new Matrix4x4(
return new(
2f / width, 0f, 0f, 0f,
0f, 2f / height, 0f, 0f,
0f, 0f, invDepth, 0f,
0f, 0f, 1f * invDepth, 0f,
0f, 0f, -nearPlane * invDepth, 1f
);
}
public static Matrix4x4 CreatePerspectiveFieldOfView(float fieldOfViewInRadians, float aspectRatio, float nearPlane, float farPlane)
public static Matrix4x4 CreatePerspectiveFieldOfView(float fovRadians, float aspectRatio, float nearPlane, float farPlane)
{
float yScale = 1f / Math.Tan(fieldOfViewInRadians / 2f);
float yScale = 1f / Math.Tan(fovRadians / 2f);
float xScale = yScale / aspectRatio;
float zRange = farPlane - nearPlane;
return new Matrix4x4(
return new(
xScale, 0f, 0f, 0f,
0f, yScale, 0f, 0f,
0f, 0f, farPlane / (farPlane - nearPlane), 1f,
0f, 0f, -nearPlane * farPlane / (farPlane - nearPlane), 0f
0f, 0f, -(farPlane + nearPlane) / zRange, -1f,
0f, 0f, -(2f * nearPlane * farPlane) / zRange, 0f
);
}

View File

@@ -1,11 +1,12 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Engine.Core;
namespace Engine.Integration.MonoGame;
public class MonoGameCamera2D : Behaviour, ICamera2D, IFirstFrameUpdate, ILastFrameUpdate, IPreDraw
public class MonoGameCamera2D : Behaviour, ICamera2D, IFirstFrameUpdate, ILastFrameUpdate, IPreDraw, IUpdate
{
public Event<MonoGameCamera2D> OnViewMatrixChanged { get; } = new();
public Event<MonoGameCamera2D> OnProjectionMatrixChanged { get; } = new();
@@ -91,12 +92,20 @@ public class MonoGameCamera2D : Behaviour, ICamera2D, IFirstFrameUpdate, ILastFr
public void PreDraw()
{
ProjectionMatrix = Matrix.CreateOrthographicOffCenter(Viewport.X, Viewport.Width, Viewport.Height, Viewport.Y, 0, 1).FromXnaMatrix();
ProjectionMatrix = Matrix4x4.CreateOrthographicViewCentered(Viewport.Width, -Viewport.Height);
ViewMatrix =
Matrix4x4.CreateTranslation(new Vector3D(-Transform.Position.X, Transform.Position.Y, 0f)) *
Matrix4x4.CreateRotationZ(Transform.Rotation * Math.DegreeToRadian) *
Matrix4x4.CreateScale(Transform.Scale.X.Max(Transform.Scale.Y)) *
Matrix4x4.CreateScale(Zoom) *
Matrix4x4.CreateTranslation(new Vector3D(Viewport.Width * .5f, Viewport.Height * .5f, 0f));
Matrix4x4.CreateTranslation(new Vector3D(-Transform.Position.X, Transform.Position.Y, 0f))
.ApplyRotationZ(Transform.Rotation * Math.DegreeToRadian)
.ApplyScale(Transform.Scale.X.Max(Transform.Scale.Y))
.ApplyScale(Zoom);
}
public void Update()
{
KeyboardInputs keyboardInputs = Universe.FindRequiredBehaviour<KeyboardInputs>();
if (keyboardInputs.IsPressed(Keys.Right)) Transform.Position += Transform.Right * Universe.Time.DeltaTime * 100;
if (keyboardInputs.IsPressed(Keys.Up)) Transform.Position += Transform.Up * Universe.Time.DeltaTime * 100;
if (keyboardInputs.IsPressed(Keys.Down)) Transform.Position += Transform.Down * Universe.Time.DeltaTime * 100;
if (keyboardInputs.IsPressed(Keys.Left)) Transform.Position += Transform.Left * Universe.Time.DeltaTime * 100;
}
}

View File

@@ -44,19 +44,11 @@ public class MonoGameTriangleBatch : Behaviour, ITriangleBatch, IFirstFrameUpdat
}
public void Begin(Matrix4x4? view = null, Matrix4x4? projection = null)
{
if (view != null)
this.view = view.Value.ToXnaMatrix();
else
this.view = Matrix.Identity;
if (projection != null)
this.projection = projection.Value.ToXnaMatrix();
else
{
Viewport viewport = graphicsDevice.Viewport;
this.projection = Matrix.CreateOrthographicOffCenter(viewport.X, viewport.Width, viewport.Height, viewport.Y, 0, 1);
}
this.view = (view ?? Matrix4x4.Identity).Transposed.ToXnaMatrix();
this.projection = (projection ?? Matrix4x4.CreateOrthographicViewCentered(viewport.Width, viewport.Height)).Transposed.ToXnaMatrix();
}
public void End() => Flush();