-
Active Member
[Classic] 1.13.2.32089 - WorldToScreen
Hi, i have been working on the World To Screen function, but facing some problems, and i'm not sure if its the code of the data being used in the function, but hope you guys can help me out
Offsets being used:
pCameraManager: [base + 0x2546398]
pCamera: [pCameraManager + 0x3330]
fov: [pCamera + 0x40]
position: [pCamera + 0x10]
viewMatrix (3x3): [pCamera + 0x1C]
wow.jpg
As you can see on the picture it shows 2 lines from the character to the targeted mob, but both lines are not pointing at the mob, but next to it and i cant figure out why this is happening. - All data from ViewMatrix used to calculate the screen position are shown.
V1:
Code:
public ScreenModel WorldToScreen(Vector3 unitPosition)
{
var diff = unitPosition - Position;
Matrix4x4 invertedMatrix;
Matrix4x4.Invert(ViewMatrix, out invertedMatrix);
var view = Vector3.Transform(diff, invertedMatrix);
var cam = new Vector3(-view.Y, -(view.Z + 0.05f), view.X);
var fovx = Math.Pow((1 / (1 + 1 / Math.Pow(Aspect, 2))), 1);
var fovy = fovx / Aspect;
fovx *= Fov;
fovy *= Fov;
fovx *= 1 / 1.10;
var screen_right_at_unit_depth = Math.Tan(fovx / 2);
var screen_bottom_at_unit_depth = Math.Tan(fovy / 2);
var screen_right_at_point_depth = screen_right_at_unit_depth * cam.Z;
var screen_bottom_at_point_depth = screen_bottom_at_unit_depth * cam.Z;
var screen = new Vector2((float)(cam.X / screen_right_at_point_depth), (float)(cam.Y / screen_bottom_at_point_depth));
var raster = ScreenSize / 2 * (Vector2.One + screen);
var behind = cam.Z < 0;
var infov = Math.Abs(screen.X) <= 1 && Math.Abs(screen.Y) <= 1 && !behind;
var model = new ScreenModel();
model.Point = raster;
model.IsBehind = behind;
model.IsInFov = infov;
return model;
}
V2 (From lazybot i think it was):
Code:
public static Vector2 WorldToScreen(float x, float y, float z, bool realPos)
{
var Result = new Point { X = 0, Y = 0 };
Vector pseudoVec = new Vector(x, y, z);
Vector Pos = new Vector(X, Y, Z);
Vector diff = pseudoVec - Pos;
Vector view = diff * Matrix.Inverse();
Vector cam = new Vector(-view.Y, -view.Z, view.X);
Single WowWidth = Convert.ToSingle((uint)GameModel.Instance.Camera.ScreenSize.X);
Single WowHeight = Convert.ToSingle((uint)GameModel.Instance.Camera.ScreenSize.Y);
Single fHorizontalAdjust = ((WowWidth / WowHeight >= 1.6f) ? 55.0f : 44.0f);
Single fScreenX = WowWidth / 2.0f;
Single fScreenY = WowHeight / 2.0f;
Rect rect = new Rect();
GetClientRect(GameModel.Process.MainWindowHandle, ref rect);
float modifier = 1.0f;
float modifier2 = 1.08f;
if (1.0 * rect.right / rect.bottom > 1.5)
{
modifier *= 1.15f;
modifier2 = 1.0f;
}
Single fTmpX = fScreenX / (Single)Math.Tan((((WowWidth / WowHeight) * fHorizontalAdjust) * modifier2 * modifier / 2.0f) * Deg2Rad);
Single fTmpY = fScreenY / (Single)Math.Tan((((WowWidth / WowHeight) * 35) / 2.0f) * Deg2Rad);
Result.X = (int)(fScreenX + cam.X * fTmpX / cam.Z);
Result.Y = (int)(fScreenY + cam.Y * fTmpY / cam.Z);
return new Vector2(Result.X, Result.Y);
}
-
Contributor
Code:
Vector2 W2S(Vector3 pos)
{
auto pCameraBase = m.read<uintptr_t>(m.m_base + 0x2535398);
auto pCamera = m.read<uintptr_t>(pCameraBase + 0x3330);
auto cam = m.read<CCamera>(pCamera);
RECT rc = { 0,0,1920,1080 };
Vector3 difference{ pos.x - cam.camPos.x, pos.y - cam.camPos.y, pos.z - cam.camPos.z };
float product =
difference.x * cam.mat._00 +
difference.y * cam.mat._01 +
difference.z * cam.mat._02;
if (product < 0)
return Vector2{ 0,0 };
Matrix inverse = Inverse(cam.mat);
Vector3 view{
inverse._00 * difference.x + inverse._10 * difference.y + inverse._20 * difference.z ,
inverse._01 * difference.x + inverse._11 * difference.y + inverse._21 * difference.z,
inverse._02 * difference.x + inverse._12 * difference.y + inverse._22 * difference.z
};
Vector3 camera{ -view.y, -view.z, view.x };
Vector2 gameScreen{ (rc.right - rc.left) / 2.0f , (rc.bottom - rc.top) / 2.0f };
Vector2 aspect{ gameScreen.x / tan(((cam.fov * 55.0f) / 2.0f) * Deg2Rad) ,gameScreen.y / tan(((cam.fov * 35.0f) / 2.0f) * Deg2Rad) };
Vector2 screenPos{ gameScreen.x + camera.x * aspect.x / camera.z,gameScreen.y + camera.y * aspect.y / camera.z };
if (screenPos.x < 0 || screenPos.y < 0 || screenPos.x > rc.right || screenPos.y > rc.bottom)
return Vector2{ 0,0 };
return screenPos;
}
Here's mine, I forget where I got the idea, but it wasn't lazybot
-
Post Thanks / Like - 6 Thanks
-
Active Member
Originally Posted by
ChrisIsMe
Here's mine, I forget where I got the idea, but it wasn't lazybot
Thank you, it's working perfectly with your method
-
Contributor
Originally Posted by
NoxiaZ
Thank you, it's working perfectly with your method
No problem and good job figuring out how to make it work instead of asking for the structures for the matrix and functions that are done on the matrix
-
Contributor
Avid Ailurophile
Originally Posted by
ChrisIsMe
Code:
Vector2 W2S(Vector3 pos)
{
auto pCameraBase = m.read<uintptr_t>(m.m_base + 0x2535398);
auto pCamera = m.read<uintptr_t>(pCameraBase + 0x3330);
auto cam = m.read<CCamera>(pCamera);
RECT rc = { 0,0,1920,1080 };
Vector3 difference{ pos.x - cam.camPos.x, pos.y - cam.camPos.y, pos.z - cam.camPos.z };
float product =
difference.x * cam.mat._00 +
difference.y * cam.mat._01 +
difference.z * cam.mat._02;
if (product < 0)
return Vector2{ 0,0 };
Matrix inverse = Inverse(cam.mat);
Vector3 view{
inverse._00 * difference.x + inverse._10 * difference.y + inverse._20 * difference.z ,
inverse._01 * difference.x + inverse._11 * difference.y + inverse._21 * difference.z,
inverse._02 * difference.x + inverse._12 * difference.y + inverse._22 * difference.z
};
Vector3 camera{ -view.y, -view.z, view.x };
Vector2 gameScreen{ (rc.right - rc.left) / 2.0f , (rc.bottom - rc.top) / 2.0f };
Vector2 aspect{ gameScreen.x / tan(((cam.fov * 55.0f) / 2.0f) * Deg2Rad) ,gameScreen.y / tan(((cam.fov * 35.0f) / 2.0f) * Deg2Rad) };
Vector2 screenPos{ gameScreen.x + camera.x * aspect.x / camera.z,gameScreen.y + camera.y * aspect.y / camera.z };
if (screenPos.x < 0 || screenPos.y < 0 || screenPos.x > rc.right || screenPos.y > rc.bottom)
return Vector2{ 0,0 };
return screenPos;
}
Here's mine, I forget where I got the idea, but it wasn't lazybot
Shameless necro but yeah, Was banging my head against the wall for a couple hours trying to adapt LazyBot W2S, you method however worked perfectly perfectly on the second try (misunderstood View{} layout initially) thanks! Wish I could rep ya more than once for that
-
Post Thanks / Like - 1 Thanks
darheroc (1 members gave Thanks to Razzue for this useful post)
-
I found a DirectX method as well:
Code:
float Cam::WorldToScreen(Vector3 worldPos, Vector2* output)
{
static auto hwnd = FindMainWindow();
RECT rect;
GetWindowRect(hwnd, &rect);
float displaySize_x = rect.right - rect.left;
float displaySize_y = rect.bottom - rect.top;
float nearClip = 1.0f;
float farClip = 10000.0f;
//Get Projection Matrix
float fAspect = displaySize_x / displaySize_y;
DirectX::XMMATRIX Proj = DirectX::XMMatrixPerspectiveFovRH(cam->fov * 0.6, fAspect, nearClip, farClip);
//Get View Matrix
DirectX::XMFLOAT3 vEyePt(cam->pos.x, cam->pos.y, cam->pos.z);
DirectX::XMFLOAT3 vLookatPt(cam->pos.x + cam->mat.M11, cam->pos.y + cam->mat.M12, cam->pos.z + cam->mat.M13);
DirectX::XMFLOAT3 vUpVec(0.0f, 0.0f, 1.0f);
DirectX::XMMATRIX View = DirectX::XMMatrixLookAtRH(DirectX::XMLoadFloat3(&vEyePt), DirectX::XMLoadFloat3(&vLookatPt), DirectX::XMLoadFloat3(&vUpVec));
//Project our position
auto inPos = DirectX::XMFLOAT3(worldPos.x, worldPos.y, worldPos.z);
auto outVect = DirectX::XMVector3Project(DirectX::XMLoadFloat3(&inPos), 0, 0, displaySize_x, displaySize_y, nearClip, farClip, Proj, View, DirectX::XMMatrixIdentity());
output->x = DirectX::XMVectorGetX(outVect);
output->y = DirectX::XMVectorGetY(outVect);
return displaySize_x; // used in calculation for alternate screen ratios. The actual x,y is an out param
}
Usage: there is a function to return the active camera. Once you find the offset of it's position (I don't know how I have this... CE???), the position is followed by a 3x3 matrix (9 floats), so you're fov (field of view) will be located after that when you are making the cam struct from the pointer.
Code:
Vector2 screenPos = Vector2(-1, -1);
auto width = Cam::WorldToScreen(position, &screenPos);
Last edited by GlittPrizes; 07-18-2021 at 09:14 AM.