diff --git a/Engine.Integration/Engine.Integration.MonoGame/Behaviours/MonoGameCamera3D.cs b/Engine.Integration/Engine.Integration.MonoGame/Behaviours/MonoGameCamera3D.cs index b43d873..640ad4b 100644 --- a/Engine.Integration/Engine.Integration.MonoGame/Behaviours/MonoGameCamera3D.cs +++ b/Engine.Integration/Engine.Integration.MonoGame/Behaviours/MonoGameCamera3D.cs @@ -154,17 +154,42 @@ public class MonoGameCamera3D : Behaviour, ICamera3D, IFirstFrameUpdate, ILastFr if (!isRecalculationNeeded) return; - Vector3 cameraPosition = Position.ToVector3(); - View = Matrix.CreateLookAt( - cameraPosition, - Transform.Forward.ToVector3() + cameraPosition, - Transform.Up.ToVector3() - ); - Projection = Matrix.CreatePerspectiveFieldOfView(_fieldOfView, Viewport.AspectRatio, 0.1f, 100f); - + CalculateView(); + CalculateProjection(); isRecalculationNeeded = false; } + private void CalculateView() + { + Vector3 forward = Vector3.Normalize(Transform.Forward.ToVector3()); + Vector3 up = Vector3.Normalize(Transform.Up.ToVector3()); + Vector3 right = Vector3.Normalize(Transform.Right.ToVector3()); + Vector3 position = Position.ToVector3(); + + View = new Matrix( + right.X, up.X, forward.X, 0, + right.Y, up.Y, forward.Y, 0, + right.Z, up.Z, forward.Z, 0, + -Vector3.Dot(right, position), + -Vector3.Dot(up, position), + -Vector3.Dot(forward, position), + 1 + ); + } + + private void CalculateProjection() + { + float yScale = 1f / (float)Math.Tan(_fieldOfView / 2f); + float xScale = yScale / Viewport.AspectRatio; + + Projection = new Matrix( + xScale, 0, 0, 0, + 0, yScale, 0, 0, + 0, 0, _farPlane / (_farPlane - _nearPlane), 1, + 0, 0, -_nearPlane * _farPlane / (_farPlane - _nearPlane), 0 + ); + } + public readonly record struct ViewChangedArguments(Matrix PreviousView); public readonly record struct ProjectionChangedArguments(Matrix PreviousProjection); public readonly record struct ViewportChangedArguments(Viewport PreviousViewport);