From 86f85c95acddfb1063aed4fd8f8552e29d6c31ac Mon Sep 17 00:00:00 2001 From: pohky Date: Wed, 3 Jul 2024 01:17:26 +0200 Subject: [PATCH] fix WorldToScreen and ScreenToWorld (#1885) * fix WorldToScreen and ScreenToWorld * Update FFXIVClientStructs --- Dalamud/Game/Gui/GameGui.cs | 88 +++++++--------------- Dalamud/Game/Gui/GameGuiAddressResolver.cs | 9 --- lib/FFXIVClientStructs | 2 +- 3 files changed, 27 insertions(+), 72 deletions(-) diff --git a/Dalamud/Game/Gui/GameGui.cs b/Dalamud/Game/Gui/GameGui.cs index 98f6ef0f87..a79a840ddd 100644 --- a/Dalamud/Game/Gui/GameGui.cs +++ b/Dalamud/Game/Gui/GameGui.cs @@ -9,6 +9,8 @@ using Dalamud.Logging.Internal; using Dalamud.Plugin.Services; using Dalamud.Utility; + +using FFXIVClientStructs.FFXIV.Client.Game.Control; using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel; using FFXIVClientStructs.FFXIV.Client.System.String; using FFXIVClientStructs.FFXIV.Client.UI; @@ -20,6 +22,7 @@ using Vector2 = System.Numerics.Vector2; using Vector3 = System.Numerics.Vector3; +using Vector4 = System.Numerics.Vector4; namespace Dalamud.Game.Gui; @@ -33,8 +36,6 @@ internal sealed unsafe class GameGui : IInternalDisposableService, IGameGui private readonly GameGuiAddressResolver address; - private readonly GetMatrixSingletonDelegate getMatrixSingleton; - private readonly Hook setGlobalBgmHook; private readonly Hook handleItemHoverHook; private readonly Hook handleItemOutHook; @@ -70,8 +71,6 @@ private GameGui(TargetSigScanner sigScanner) this.handleImmHook = Hook.FromAddress(this.address.HandleImm, this.HandleImmDetour); - this.getMatrixSingleton = Marshal.GetDelegateForFunctionPointer(this.address.GetMatrixSingleton); - this.toggleUiHideHook = Hook.FromAddress(this.address.ToggleUiHide, this.ToggleUiHideDetour); this.utf8StringFromSequenceHook = Hook.FromAddress(this.address.Utf8StringFromSequence, this.Utf8StringFromSequenceDetour); @@ -86,11 +85,6 @@ private GameGui(TargetSigScanner sigScanner) this.utf8StringFromSequenceHook.Enable(); } - // Marshaled delegates - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate IntPtr GetMatrixSingletonDelegate(); - // Hooked delegates [UnmanagedFunctionPointer(CallingConvention.ThisCall)] @@ -178,23 +172,29 @@ public bool WorldToScreen(Vector3 worldPos, out Vector2 screenPos) /// public bool WorldToScreen(Vector3 worldPos, out Vector2 screenPos, out bool inView) { - // Get base object with matrices - var matrixSingleton = this.getMatrixSingleton(); - // Read current ViewProjectionMatrix plus game window size var windowPos = ImGuiHelpers.MainViewport.Pos; - var viewProjectionMatrix = *(Matrix4x4*)(matrixSingleton + 0x1b4); + var viewProjectionMatrix = Control.Instance()->ViewProjectionMatrix; var device = Device.Instance(); float width = device->Width; float height = device->Height; - var pCoords = Vector3.Transform(worldPos, viewProjectionMatrix); - screenPos = new Vector2(pCoords.X / MathF.Abs(pCoords.Z), pCoords.Y / MathF.Abs(pCoords.Z)); + var pCoords = Vector4.Transform(new Vector4(worldPos, 1.0f), viewProjectionMatrix); + var inFront = pCoords.W > 0.0f; + + if (Math.Abs(pCoords.W) < float.Epsilon) + { + screenPos = Vector2.Zero; + inView = false; + return false; + } + + pCoords *= MathF.Abs(1.0f / pCoords.W); + screenPos = new Vector2(pCoords.X, pCoords.Y); screenPos.X = (0.5f * width * (screenPos.X + 1f)) + windowPos.X; screenPos.Y = (0.5f * height * (1f - screenPos.Y)) + windowPos.Y; - var inFront = pCoords.Z > 0; inView = inFront && screenPos.X > windowPos.X && screenPos.X < windowPos.X + width && screenPos.Y > windowPos.Y && screenPos.Y < windowPos.Y + height; @@ -216,53 +216,17 @@ public bool ScreenToWorld(Vector2 screenPos, out Vector3 worldPos, float rayDist worldPos = default; return false; } - - // Get base object with matrices - var matrixSingleton = this.getMatrixSingleton(); - - // Read current ViewProjectionMatrix plus game window size - var viewProjectionMatrix = default(Matrix); - var rawMatrix = (float*)(matrixSingleton + 0x1b4).ToPointer(); - - for (var i = 0; i < 16; i++, rawMatrix++) - viewProjectionMatrix[i] = *rawMatrix; - - var width = *rawMatrix; - var height = *(rawMatrix + 1); - - viewProjectionMatrix.Invert(); - - var localScreenPos = new SharpDX.Vector2(screenPos.X - windowPos.X, screenPos.Y - windowPos.Y); - var screenPos3D = new SharpDX.Vector3 - { - X = (localScreenPos.X / width * 2.0f) - 1.0f, - Y = -((localScreenPos.Y / height * 2.0f) - 1.0f), - Z = 0, - }; - - SharpDX.Vector3.TransformCoordinate(ref screenPos3D, ref viewProjectionMatrix, out var camPos); - - screenPos3D.Z = 1; - SharpDX.Vector3.TransformCoordinate(ref screenPos3D, ref viewProjectionMatrix, out var camPosOne); - - var clipPos = camPosOne - camPos; - clipPos.Normalize(); - - // This array is larger than necessary because it contains more info than we currently use - var worldPosArray = default(RaycastHit); - - // Theory: this is some kind of flag on what type of things the ray collides with - var unknown = stackalloc int[3] + + var camera = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.CameraManager.Instance()->CurrentCamera; + if (camera == null) { - 0x4000, - 0x4000, - 0x0, - }; - - var isSuccess = BGCollisionModule.Raycast2(camPos.ToSystem(), clipPos.ToSystem(), rayDistance, &worldPosArray, unknown); - worldPos = worldPosArray.Point; - - return isSuccess; + worldPos = Vector3.Zero; + return false; + } + var ray = camera->ScreenPointToRay(screenPos); + var result = BGCollisionModule.RaycastMaterialFilter(ray.Origin, ray.Direction, out var hit); + worldPos = hit.Point; + return result; } /// diff --git a/Dalamud/Game/Gui/GameGuiAddressResolver.cs b/Dalamud/Game/Gui/GameGuiAddressResolver.cs index c389491f0e..e0ffe41dd6 100644 --- a/Dalamud/Game/Gui/GameGuiAddressResolver.cs +++ b/Dalamud/Game/Gui/GameGuiAddressResolver.cs @@ -39,12 +39,6 @@ internal sealed class GameGuiAddressResolver : BaseAddressResolver /// Gets the address of the native HandleImm method. /// public IntPtr HandleImm { get; private set; } - - /// - /// Gets the address of the native GetMatrixSingleton method. - /// - public IntPtr GetMatrixSingleton { get; private set; } - /// /// Gets the address of the native ToggleUiHide method. /// @@ -65,9 +59,6 @@ protected override void Setup64Bit(ISigScanner sig) this.HandleActionOut = sig.ScanText("48 89 5C 24 ?? 57 48 83 EC 20 48 8B DA 48 8B F9 4D 85 C0 74 1F"); this.HandleImm = sig.ScanText("E8 ?? ?? ?? ?? 84 C0 75 10 48 83 FF 09"); - // Client::Graphics::JobSystem.GetSingleton() - this.GetMatrixSingleton = sig.ScanText("E8 ?? ?? ?? ?? 48 8D 4C 24 ?? 48 89 4c 24 ?? 4C 8D 4D ?? 4C 8D 44 24 ??"); - this.ToggleUiHide = sig.ScanText("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC ?? 44 0F B6 81"); this.Utf8StringFromSequence = sig.ScanText("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8D 41 22 66 C7 41 ?? ?? ?? 48 89 01 49 8B D8"); } diff --git a/lib/FFXIVClientStructs b/lib/FFXIVClientStructs index d39475f818..dd4bbedad0 160000 --- a/lib/FFXIVClientStructs +++ b/lib/FFXIVClientStructs @@ -1 +1 @@ -Subproject commit d39475f81899cb35e874cbde7a50028667eb95c9 +Subproject commit dd4bbedad018777d590af8c7d285504d0ee02eee