From efa4da43988c8ab3eda2b9da5347ef200331d391 Mon Sep 17 00:00:00 2001 From: Syntriax Date: Wed, 28 Jan 2026 11:06:15 +0300 Subject: [PATCH] fix: ScreenToWorldPosition & vice versa methods on MonoGameCamera2D fixed --- .../Behaviours/MonoGameCamera2D.cs | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/Engine.Integration/Engine.Integration.MonoGame/Behaviours/MonoGameCamera2D.cs b/Engine.Integration/Engine.Integration.MonoGame/Behaviours/MonoGameCamera2D.cs index 1dcd651..f28deb5 100644 --- a/Engine.Integration/Engine.Integration.MonoGame/Behaviours/MonoGameCamera2D.cs +++ b/Engine.Integration/Engine.Integration.MonoGame/Behaviours/MonoGameCamera2D.cs @@ -1,12 +1,11 @@ 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, IUpdate +public class MonoGameCamera2D : Behaviour, ICamera2D, IFirstFrameUpdate, ILastFrameUpdate, IPreDraw { public Event OnViewMatrixChanged { get; } = new(); public Event OnProjectionMatrixChanged { get; } = new(); @@ -73,13 +72,34 @@ public class MonoGameCamera2D : Behaviour, ICamera2D, IFirstFrameUpdate, ILastFr // TODO This causes delay since OnPreDraw calls assuming this is called in in Update public Vector2D ScreenToWorldPosition(Vector2D screenPosition) { - Vector2D worldPosition = Vector2.Transform(screenPosition.ToVector2(), ViewMatrix.Inverse.ToXnaMatrix()).ToVector2D(); - return worldPosition.Scale(EngineConverterExtensions.screenScale); + float x = 2f * screenPosition.X / Viewport.Width - 1f; + float y = 2f * screenPosition.Y / Viewport.Height - 1f; + Vector4D normalizedCoordinates = new(x, y, 0f, 1f); + + Matrix4x4 invertedViewProjectionMatrix = (ProjectionMatrix * ViewMatrix).Inverse; + + Vector4D worldPosition = invertedViewProjectionMatrix * normalizedCoordinates; + + if (worldPosition.W != 0f) + worldPosition /= worldPosition.W; + + return new(worldPosition.X, worldPosition.Y); } + public Vector2D WorldToScreenPosition(Vector2D worldPosition) { - Vector2D screenPosition = Vector2.Transform(worldPosition.ToVector2(), ViewMatrix.ToXnaMatrix()).ToVector2D(); - return screenPosition.Scale(EngineConverterExtensions.screenScale); + Vector4D worldPosition4D = new(worldPosition.X, worldPosition.Y, 0f, 1f); + + Matrix4x4 viewProjection = ProjectionMatrix * ViewMatrix; + Vector4D clip = viewProjection * worldPosition4D; + + if (clip.W != 0f) + clip /= clip.W; + + float screenX = (clip.X + 1f) * .5f * Viewport.Width; + float screenY = (clip.Y + 1f) * .5f * Viewport.Height; + + return new(screenX, screenY); } public void LastActiveFrame() => Transform = null!; @@ -99,13 +119,4 @@ public class MonoGameCamera2D : Behaviour, ICamera2D, IFirstFrameUpdate, ILastFr .ApplyScale(Transform.Scale.X.Max(Transform.Scale.Y)) .ApplyScale(Zoom); } - - public void Update() - { - KeyboardInputs keyboardInputs = Universe.FindRequiredBehaviour(); - 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; - } }