admin 发表于 2023-9-24 22:47:03

UE4,UE5 世界坐标转屏幕坐标






#include "pch.h"
#include "世界坐标转屏幕坐标.h"
#include"TGame.h"


//-----------项目代码-------------------
#pragma once

ULONG64 offset_OwningGameInstance = 0x290;
ULONG64 offset_ULocalPlayer = 0x38;//本地角色
ULONG64 offset_UPlayerController = 0x30;//角色控制器

bool WorldToScreenEx(IN FVector3 WorldLocation, OUT FVector3* Screenlocation);


//
//UINT_PTR TGame::GetGWorld()
//{
//        return RP(GetPByPdbName("GWorld") + 0);
//}

UINT_PTR TGame::GetGameInstance()
{
        //[+0x290]
        return RP(GetGWorld() + offset_OwningGameInstance);
}
UINT_PTR TGame::GetLocalPlayer()
{
        // [[[[+0x290]+38]+30]+0*8]
        returnRP(RP(GetGameInstance() + offset_ULocalPlayer) + 0x00);
}




// 函数类型指针 type_ProjectWorldLocationToScreen
typedef bool(__thiscall* type_ProjectWorldLocationToScreen)(
        UINT_PTR vrcx_this, // PlayerController*
        FVector3* WorldLocation,   // IN 待转换的世界坐标
        FVector3* ScreenLocation, // OUT 返回转换后的屏幕坐标
        bool bPlayerViewportRelative //IN是否相对玩家视口 false
        );


//需要主线程 里调用 bool WorldToScreenEx(IN FVector3 WorldLocation, OUT FVector3& Screenlocation)
//void TGame::WorldToScreen(IN float* worldpos3, OUT float* screenpos2, bool bPlayerViewportRelative,BOOL isEx)
void TGame::WorldToScreen(IN FVector3* worldpos3, OUT FVector3* screenpos2, bool bPlayerViewportRelative, BOOL isEx)
{
        if (isEx)
        {
                WorldToScreenEx(*worldpos3, screenpos2);
                return;
        }

        printf("内置 pcall_worldtoScreen line=%d \r\n", __LINE__);

        type_ProjectWorldLocationToScreen pcall_worldtoScreen = (type_ProjectWorldLocationToScreen)GetPByPdbName("APlayerController::ProjectWorldLocationToScreen");
        //获取 PlayerController
        UINT_PTR vrcx_PlayerController = TGame::GetPlayerController();

        //printf("pcall_worldtoScreen=%p,GetPlayerController()=%zX \r\n", pcall_worldtoScreen, vrcx_PlayerController);
        //LogFileW("c:\\log\\遍历怪物数组draw.txt", L"pcall_worldtoScreen=%zX,GetAPlayerController()=%zX \r\n", pcall_worldtoScreen, vrcx_PlayerController);
        if (pcall_worldtoScreen && vrcx_PlayerController)
        {
               
                //需要主线程调用
                pcall_worldtoScreen(
                        vrcx_PlayerController, // PlayerController指针
                        worldpos3,// IN 待转换的世界坐标
                        screenpos2,// OUT 返回转换后的屏幕坐标
                        bPlayerViewportRelative);//=false);
        }
        else
        {

                //MessageBoxA(0, __FILE__, "世界坐标转屏幕坐标 错误", MB_OK);
                printf("错误 pcall_worldtoScreen=%p,GetAPlayerController()=%zX \r\n", pcall_worldtoScreen, vrcx_PlayerController);
        }
}

/*

PlayerController.h

typedef bool (__thiscall* type_ProjectWorldLocationToScreen)(
        UINT_PTR vrcx_this,
        float* WorldLocation,   // IN 待转换的世界坐标
        float* ScreenLocation, // OUT 返回转换后的屏幕坐标
        bool bPlayerViewportRelative //IN是否相对玩家视口
        );

        bool PlayerController::ProjectWorldLocationToScreen(FVector WorldLocation, FVector2D& ScreenLocation, bool bPlayerViewportRelative = false) const;

UGameInstance::GetFirstLocalPlayerController

00007FF649ADDA60 | 48:895C24 08             | mov qword ptr ss:,rbx                                                          | gameinstance.cpp:555,
00007FF649ADDA65 | 48:897424 10             | mov qword ptr ss:,rsi                                                         |
00007FF649ADDA6A | 57                     | push rdi                                                                              |
00007FF649ADDA6B | 48:83EC 30               | sub rsp,30                                                                            |
00007FF649ADDA6F | 8B71 40                  | mov esi,dword ptr ds:                                                         | gameinstance.cpp:556
00007FF649ADDA72 | 48:8BF9                  | mov rdi,rcx                                                                           |[+0x290]
00007FF649ADDA75 | 33DB                     | xor ebx,ebx                                                                           | gameinstance.cpp:556
00007FF649ADDA77 | 3BDE                     | cmp ebx,esi                                                                           |
00007FF649ADDA79 | 74 6C                  | je shootergame.7FF649ADDAE7                                                         |
00007FF649ADDA7B | 8B57 40                  | mov edx,dword ptr ds:                                                         |
00007FF649ADDA7E | 33C9                     | xor ecx,ecx                                                                           |
00007FF649ADDA80 | 3BDA                     | cmp ebx,edx                                                                           |
00007FF649ADDA82 | 0F9CC1                   | setl cl                                                                               |
00007FF649ADDA85 | 33C0                     | xor eax,eax                                                                           |
00007FF649ADDA87 | 85DB                     | test ebx,ebx                                                                        |
00007FF649ADDA89 | 0F99C0                   | setns al                                                                              |
00007FF649ADDA8C | 85C8                     | test eax,ecx                                                                        |
00007FF649ADDA8E | 75 28                  | jne shootergame.7FF649ADDAB8                                                          |
00007FF649ADDA90 | 895424 28                | mov dword ptr ss:,edx                                                         |
00007FF649ADDA94 | 4C:8D0D 65C61201         | lea r9,qword ptr ds:[<L"Array index out of bounds: %i fr"...>]                        | 00007FF64AC0A100:L"Array index out of bounds: %i from an array of size %i"
00007FF649ADDA9B | 48:8D0D CEC61201         | lea rcx,qword ptr ds:[<"(Index >= 0) & (Index < ArrayNum"...>]                        | 00007FF64AC0A170:"(Index >= 0) & (Index < ArrayNum)"
00007FF649ADDAA2 | 48:8D15 D7BF1201         | lea rdx,qword ptr ds:[<"F:\\build\\LostIsland\\Engine\\Sourc"...>]                  | 00007FF64AC09A80:"F:\\build\\LostIsland\\Engine\\Source\\Runtime\\Core\\Public\\Containers\\Array.h"
00007FF649ADDAA9 | 41:B8 3C020000         | mov r8d,23C                                                                           |
00007FF649ADDAAF | 895C24 20                | mov dword ptr ss:,ebx                                                         |
00007FF649ADDAB3 | E8 A8DE84FF            | call <shootergame.public: static void __cdecl FDebug::AssertFailed(char const *, char |
00007FF649ADDAB8 | 48:8B47 38               | mov rax,qword ptr ds:                                                         | [[+0x290]+38]
00007FF649ADDABC | 48:63CB                  | movsxd rcx,ebx                                                                        |
00007FF649ADDABF | 48:8B04C8                | mov rax,qword ptr ds:    //player 数组? [[[+0x290]+38]+0*8]
00007FF649ADDAC3 | 48:85C0                  | test rax,rax                                                                        | gameinstance.cpp:558
00007FF649ADDAC6 | 74 07                  | je shootergame.7FF649ADDACF                                                         |
00007FF649ADDAC8 | 48:8378 30 00            | cmp qword ptr ds:,0                                                         |
00007FF649ADDACD | 75 04                  | jne shootergame.7FF649ADDAD3                                                          |
00007FF649ADDACF | FFC3                     | inc ebx                                                                               | gameinstance.cpp:556
00007FF649ADDAD1 | EB A4                  | jmp shootergame.7FF649ADDA77                                                          |
00007FF649ADDAD3 | 48:8B40 30               | mov rax,qword ptr ds:                                                         | rax = [[[[+0x290]+38]+0*8]+30]
00007FF649ADDAD7 | 48:8B5C24 40             | mov rbx,qword ptr ss:                                                         | gameinstance.cpp:567
00007FF649ADDADC | 48:8B7424 48             | mov rsi,qword ptr ss:                                                         |
00007FF649ADDAE1 | 48:83C4 30               | add rsp,30                                                                            |
00007FF649ADDAE5 | 5F                     | pop rdi                                                                               |
00007FF649ADDAE6 | C3                     | ret                                                                                 |
00007FF649ADDAE7 | 48:8B5C24 40             | mov rbx,qword ptr ss:                                                         |
00007FF649ADDAEC | 48:8B7424 48             | mov rsi,qword ptr ss:                                                         |
00007FF649ADDAF1 | 33C0                     | xor eax,eax                                                                           |
00007FF649ADDAF3 | 48:83C4 30               | add rsp,30                                                                            |
00007FF649ADDAF7 | 5F                     | pop rdi                                                                               |
00007FF649ADDAF8 | C3                     | ret                                                                                 |




APlayerController* UGameInstance::GetFirstLocalPlayerController(const UWorld* World) const
{
        if (World == nullptr)
        {
                for (ULocalPlayer* Player : LocalPlayers)
                {
                        // Returns the first non-null UPlayer::PlayerController without filtering by UWorld.
                        if (Player && Player->PlayerController)
                        {
                                // return first non-null entry
                                return Player->PlayerController;
                        }
                }
        }
        else
        {
                // Only return a local PlayerController from the given World.
                for (FConstPlayerControllerIterator Iterator = World->GetPlayerControllerIterator(); Iterator; ++Iterator)
                {
                        APlayerController* PC = Iterator->Get();
                        if (PC && PC->IsLocalController())
                        {
                                return PC;
                        }
                }
        }

        // didn't find one
        return nullptr;
}

*/




#include"pch.h"
#include<Windows.h>
#include"世界坐标转屏幕坐标.h"

#define PI        3.14159265358979323846264338327950288419716939937510



//矩阵
D3DXMATRIX Matrix(FVector3 rot, FVector3 origin = FVector3(0, 0, 0))
{
        float radPitch = (rot.x * float(PI) / 180.f);
        float radYaw = (rot.y * float(PI) / 180.f);
        float radRoll = (rot.z * float(PI) / 180.f);

        float SP = sinf(radPitch);
        float CP = cosf(radPitch);
        float SY = sinf(radYaw);
        float CY = cosf(radYaw);
        float SR = sinf(radRoll);
        float CR = cosf(radRoll);

        D3DMATRIX matrix;
        matrix.m = CP * CY;
        matrix.m = CP * SY;
        matrix.m = SP;
        matrix.m = 0.f;

        matrix.m = SR * SP * CY - CR * SY;
        matrix.m = SR * SP * SY + CR * CY;
        matrix.m = -SR * CP;
        matrix.m = 0.f;

        matrix.m = -(CR * SP * CY + SR * SY);
        matrix.m = CY * SR - CR * SP * SY;
        matrix.m = CR * CP;
        matrix.m = 0.f;

        matrix.m = origin.x;
        matrix.m = origin.y;
        matrix.m = origin.z;
        matrix.m = 1.f;

        return matrix;
}

/*
        //相机坐标
        AShooterPlayerController=[[[[+290]+38]+0]+30]
        PlayerCameraManager =
        // [[[[+290]+38]+0]+30]+4F0

        +480 //3、FOV视角 float   [[[[[+290]+38]+0]+30]+4F0]+480 真实视角 修改有效
        +4D8 //1、相机坐标float pos3 FVector3   [[[[[+290]+38]+0]+30]+4F0]+4D0+8
        +4E4 //2、相机旋转坐标 float pos      [[[[[+290]+38]+0]+30]+4F0]+4D0+8+C
        +500 //2、相机旋转坐标 float pos
        +500 //3、FOV视角 float                  [[[[[+290]+38]+0]+30]+4F0]+4D0+8+28 可读
        +C40 //3、FOV视角 float   [[[[[+290]+38]+0]+30]+4F0]+C40 可读
        +FE8 //3、FOV视角 float   [[[[[+290]+38]+0]+30]+4F0]+FE8 可读

*/


// UGameInstance::GetFirstLocalPlayerController//PlayerController::ProjectWorldLocationToScreen
UINT_PTR TGame::GetPlayerController()
{
        UINT_PTR ULocalPlayer = GetLocalPlayer();
        //[[[[+0x290]+38]+0*8]+30]
        return RP(ULocalPlayer + offset_UPlayerController);
}



UINT_PTR TGame::GetPlayerCameraManager()
{// [[[[[+290]+38]+0]+30]+4F0]
        //return RP(RP(RP(RP(RP(GetGWorld() + 0x290) + 0x38) + 0x00) + 0x30) + 0x4F0);
        return RP(GetPlayerController() + 0x4F0);
}

FVector3 TGame::GetCameraRotation()
{
        //[[[[[+290]+38]+0]+30]+4F0]+4D8

        UINT_PTR pbase = GetPlayerCameraManager() + 0x4D8;
        FVector3 Rotation = RP<FVector3>(pbase);
        return Rotation;
}

FVector3 TGame::GetCameraLocation()
{
        //[[[[[+290]+38]+0]+30]+4F0]+4E4       
        UINT_PTR pbase = GetPlayerCameraManager() + 0x4E4;
        FVector3 Rotation = RP<FVector3>(pbase);
        return Rotation;
}

float TGame::GetFov()
{        //FOV弧度
        //+500 //3、FOV视角 float       [[[[[+290]+38]+0]+30]+4F0]+4D0+8+28 可读
        float Fov = 0;
        UINT_PTR pbase = GetPlayerCameraManager() + 0x500;
        Fov = RP<float>(pbase);
        return Fov;
}

/*
GSystemResolution
+00 分辩率宽度 x int
+04 分辩率高度 y int
*/

INT64 GetResolution(OUT int& x, int& y)
{
        UINT_PTR pbase_GetResolution = GetPByPdbName("GSystemResolution");
        INT64 pos = RP<INT64>(pbase_GetResolution + 0x00);
        //y = RP<int>(pbase_GetResolution+0x04);
        x = pos && 0xFFFFFFFF;
        y = pos >> 32;
        return pos;
}

INT64 TGame::GetResolution(OUT int& x, int& y)
{
        UINT_PTR pbase_GetResolution = GetPByPdbName("GSystemResolution");
        INT64 pos = RP<INT64>(pbase_GetResolution + 0x00);
        //y = RP<int>(pbase_GetResolution+0x04);
        x = GetResolutionWidth();
        y = GetResolutionHeight();
        return pos;
}

//判断坐标是否在屏幕内
INT64 TGame::在屏幕内(int x, int y)
{
        int w, h;
        GetResolution(w, h);


        if((abs(x) <= w) && (abs(y) <= h))
        {
          return true;
        }else
        {
                return false;
        }

}



int TGame::GetResolutionWidth()
{
        UINT_PTR pbase_GetResolution = GetPByPdbName("GSystemResolution");
        int pos = RP<int>(pbase_GetResolution + 0x00);

        return pos;
}

int TGame::GetResolutionHeight()
{
        UINT_PTR pbase_GetResolution = GetPByPdbName("GSystemResolution");
        int pos = RP<int>(pbase_GetResolution + 0x04);

        return pos;
}

int TGame::窗口客户端中心X()
{
        int pos = GetResolutionWidth();
        return pos / 2;
}
int TGame::窗口客户端中心Y()
{
       
        int pos = GetResolutionHeight();
        return pos / 2;
}

/*
//本地角色   APlayerController*   UShooterLocalPlayer= [[[+290]+38]+0]
//这个接口   可以重点关注
bool APlayerController::ProjectWorldLocationToScreen(
FVector WorldLocation,   // IN 待转换的世界坐标
FVector2D& ScreenLocation, // OUT 返回转换后的屏幕坐标
bool bPlayerViewportRelative //IN是否相对玩家视口
)
{
        return UGameplayStatics::ProjectWorldToScreen(this, WorldLocation, ScreenLocation, bPlayerViewportRelative);
}

*/

//世界坐标转屏幕坐标

bool TGame::WorldToScreenEx(IN FVector3 WorldLocation, OUT FVector3* Screenlocation)
{
        //获取相机旋转坐标
        FVector3 Rotation = GetCameraRotation();

        D3DMATRIX tempMatrix = Matrix(Rotation);

        FVector3 vAxisX, vAxisY, vAxisZ;

        vAxisX = FVector3(tempMatrix.m, tempMatrix.m, tempMatrix.m);
        vAxisY = FVector3(tempMatrix.m, tempMatrix.m, tempMatrix.m);
        vAxisZ = FVector3(tempMatrix.m, tempMatrix.m, tempMatrix.m);
        //世界矩阵-相机矩阵
        FVector3 vDelta = WorldLocation - GetCameraLocation();
        FVector3 vTransformed = FVector3(vDelta.Dot(vAxisY), vDelta.Dot(vAxisZ), vDelta.Dot(vAxisX));

        if (vTransformed.z < 1.f)
                return 0;

        float FovAngle = GetFov();

        //Screenlocation.x = g_Game->窗口客户端中心X + vTransformed.x * (g_Game->窗口客户端中心X / tanf(FovAngle * (float)PI / 360.f)) / vTransformed.z;
        //Screenlocation.y = 窗口客户端中心Y() - vTransformed.y * (g_Game->窗口客户端中心X / tanf(FovAngle * (float)PI / 360.f)) / vTransformed.z;
        int 窗口客户端中心X = TGame::窗口客户端中心X();
        int 窗口客户端中心Y = TGame::窗口客户端中心Y();
        Screenlocation->x = 窗口客户端中心X + vTransformed.x * (窗口客户端中心X / tanf(FovAngle * (float)PI / 360.f)) / vTransformed.z;
        Screenlocation->y = 窗口客户端中心Y - vTransformed.y * (窗口客户端中心X / tanf(FovAngle * (float)PI / 360.f)) / vTransformed.z;

        Screenlocation->z = 0.0f;
        return 1;
}

UINT_PTR TGame::Get_UMatrix()
{
        /*

        */
        ULONG64offset_UMatrixXbase = GetPByPdbName("GetCanvasByName") + 0x21;
        UINT_PTR offset_UMatrix = offset_UMatrixXbase + 7 + RP<DWORD>(offset_UMatrixXbase + 3);
       
        return offset_UMatrix;
}

//Rm(Rm(Rm(g_Game->GameBase + g_Game->offset_UMatrix) + 0x20) + 0xB0, tempMatrix, 64);



bool TGame::WorldToScreenRect(IN FVector3 WorldLocation, OUT FVector4& Rect)
{
        float View{}, Top{}, Lift{}, BoxY{}, BoxH{};
        float tempMatrix{};
        // Rm(Rm(Rm(base+offset_UMatrix) + 0x20) + 0xB0, tempMatrix, 64);
        RM(R8(R8(Get_UMatrix()+0) + 0x20) + 0xB0,OUT tempMatrix);

        View =
                tempMatrix * WorldLocation.x +
                tempMatrix * WorldLocation.y +
                tempMatrix * WorldLocation.z +
                tempMatrix;
        if (View < 1.f)
                return false;
        View = 1 / View;
        Top = 窗口客户端中心X() + (
                tempMatrix * WorldLocation.x +
                tempMatrix * WorldLocation.y +
                tempMatrix * WorldLocation.z +
                tempMatrix
                ) * View * 窗口客户端中心X();
        Lift = 窗口客户端中心Y() - (
                tempMatrix * WorldLocation.x +
                tempMatrix * WorldLocation.y +
                tempMatrix * WorldLocation.z +
                tempMatrix
                ) * View * 窗口客户端中心Y();
        BoxY = 窗口客户端中心Y() - (
                tempMatrix * WorldLocation.x +
                tempMatrix * WorldLocation.y +
                tempMatrix * (WorldLocation.z + 75.0f) +
                tempMatrix
                ) * View * 窗口客户端中心Y();
        Rect.h = Lift - BoxY;
        Rect.w = Rect.h * (float)0.6015625;
        Rect.x = Top - Rect.w / 1.4f;
        Rect.y = BoxY;
        Rect.w *= 1.5f;
        Rect.h *= 2.3f;
        return true;
}



admin 发表于 2023-9-24 22:48:19

//"TGame.h"
#pragma once

#include"世界坐标转屏幕坐标.h"

typedef UINT_PTR AActor;
typedef UINT32 SIZE32;

//typedef struct _FVector3
//{
//        float x;
//        float y;
//        float z;
//        float w; //??
//        float h; //??
//}FVector3;

class TGame
{
public:

static                HWND GetHwnd();
static      UINT_PTR GetGameBase();
static      INT64 GetResolution(OUT int& x, int& y); //获取游戏分辩率
static int GetResolutionWidth();
static int GetResolutionHeight();
static int 窗口客户端中心X();
static int 窗口客户端中心Y();

static      INT64 在屏幕内( int x,int y); //判断坐标是否在屏幕内

static                DWORD GetMainThreadID();
static      BOOL IsMainThread();

static        UINT_PTR GetGWorld();
static        UINT_PTR GetUlevel();
static        UINT_PTR GetAActorArray();
static        SIZE32   GetAActorArraySize();   //[+F8]+88+4
static        SIZE32   GetAActorArraySizeMax();//[+F8]+88+4+4 最大容量
static        AActor*GetAActor(UINT32 index); // [[+F8]+88]+8*下标]

static UINT_PTRGetGameInstance();      //[+0x290]
static UINT_PTRGetLocalPlayer();         //[[[[+0x290]+38]+30]+0*8]
static UINT_PTRGetPlayerController();    //[[[[+0x290]+38]+0*8]+30]
static UINT_PTRGetPlayerCameraManager(); //[[[[[+290]+38]+0]+30]+4F0]
static FVector3GetCameraLocation();      //[[[[[+290]+38]+0]+30]+4F0]+4E4       
static FVector3GetCameraRotation();      //[[[[[+290]+38]+0]+30]+4F0]+4D8
static float   GetFov();                  //[[[[[+290]+38]+0]+30]+4F0]+4D0+8+28 可读

//static void      WorldToScreen(IN float* worldpos3, OUT float* screenpos2, bool bPlayerViewportRelative=false);
static UINT_PTR Get_UMatrix();
static void   WorldToScreen(IN FVector3* worldpos3, OUT FVector3* screenpos2, bool bPlayerViewportRelative, BOOL isEx);
static bool   WorldToScreenRect(IN FVector3 WorldLocation,OUT FVector4& Rect);
static bool   WorldToScreenEx(IN FVector3 WorldLocation, OUT FVector3* Screenlocation);


};


页: [1]
查看完整版本: UE4,UE5 世界坐标转屏幕坐标