Skip to content

Commit

Permalink
fix WorldToScreen and ScreenToWorld (#1885)
Browse files Browse the repository at this point in the history
* fix WorldToScreen and ScreenToWorld

* Update FFXIVClientStructs
  • Loading branch information
pohky authored Jul 2, 2024
1 parent cf515cb commit 86f85c9
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 72 deletions.
88 changes: 26 additions & 62 deletions Dalamud/Game/Gui/GameGui.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -20,6 +22,7 @@

using Vector2 = System.Numerics.Vector2;
using Vector3 = System.Numerics.Vector3;
using Vector4 = System.Numerics.Vector4;

namespace Dalamud.Game.Gui;

Expand All @@ -33,8 +36,6 @@ internal sealed unsafe class GameGui : IInternalDisposableService, IGameGui

private readonly GameGuiAddressResolver address;

private readonly GetMatrixSingletonDelegate getMatrixSingleton;

private readonly Hook<SetGlobalBgmDelegate> setGlobalBgmHook;
private readonly Hook<HandleItemHoverDelegate> handleItemHoverHook;
private readonly Hook<HandleItemOutDelegate> handleItemOutHook;
Expand Down Expand Up @@ -70,8 +71,6 @@ private GameGui(TargetSigScanner sigScanner)

this.handleImmHook = Hook<HandleImmDelegate>.FromAddress(this.address.HandleImm, this.HandleImmDetour);

this.getMatrixSingleton = Marshal.GetDelegateForFunctionPointer<GetMatrixSingletonDelegate>(this.address.GetMatrixSingleton);

this.toggleUiHideHook = Hook<ToggleUiHideDelegate>.FromAddress(this.address.ToggleUiHide, this.ToggleUiHideDetour);

this.utf8StringFromSequenceHook = Hook<Utf8StringFromSequenceDelegate>.FromAddress(this.address.Utf8StringFromSequence, this.Utf8StringFromSequenceDetour);
Expand All @@ -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)]
Expand Down Expand Up @@ -178,23 +172,29 @@ public bool WorldToScreen(Vector3 worldPos, out Vector2 screenPos)
/// <inheritdoc/>
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;
Expand All @@ -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;
}

/// <inheritdoc/>
Expand Down
9 changes: 0 additions & 9 deletions Dalamud/Game/Gui/GameGuiAddressResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,6 @@ internal sealed class GameGuiAddressResolver : BaseAddressResolver
/// Gets the address of the native HandleImm method.
/// </summary>
public IntPtr HandleImm { get; private set; }

/// <summary>
/// Gets the address of the native GetMatrixSingleton method.
/// </summary>
public IntPtr GetMatrixSingleton { get; private set; }

/// <summary>
/// Gets the address of the native ToggleUiHide method.
/// </summary>
Expand All @@ -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<Apricot::Engine::Core>.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");
}
Expand Down

0 comments on commit 86f85c9

Please sign in to comment.