For the coppypasta happy people, Kynox's 3d to 2d projection made easy. For the real implementation, keep just the comments, for the easy copy/paste one, keep it as it is. 3.0.8 compatible ofc. No need to blindly hoover around the screen searching for stuff anymore. Works out of process for easy testing, returns false when the mouse can be moved there (behind the camera, etc).
Code:
/////////////////////
#define WOW_CAMERA_PTR1 0x10A5DAC
#define WOW_CAMERA_OFFSET 0x000782C
#define M_DEG2RAD 0.01745329251f
struct SCameraInfo
{
DWORD dwFoo1[2];
//CVec3 vPos;
float fPos[3];
//CMat3 matView;
float fViewMat[3][3];
DWORD dwFoo2[2];
float fFov;
};
BOOL MoveMouseToWoWCoords( float x, float y, float z /* CVec3 vWoWPos*/, HWND hwndWoW, HANDLE hWoWProc )
{
SCameraInfo camera;
LPBYTE pAddr1;
LPBYTE pAddr2;
DWORD dwFoo;
if( !ReadProcessMemory( hWoWProc, (LPDWORD)WOW_CAMERA_PTR1, &pAddr1, 4, &dwFoo ) || dwFoo != 4 )
return FALSE;
if( !ReadProcessMemory( hWoWProc, pAddr1+WOW_CAMERA_OFFSET, &pAddr2, 4, &dwFoo ) || dwFoo != 4 )
return FALSE;
if( !ReadProcessMemory( hWoWProc, pAddr2, &camera, sizeof(SCameraInfo), &dwFoo ) || dwFoo != sizeof(SCameraInfo) )
return FALSE;
RECT rc;
if( !::GetClientRect( hwndWoW,&rc ) )
return FALSE;
//CVec3 vDiff = vWoWPos - camera.vPos;
float fDiff[3];
fDiff[0] = x-camera.fPos[0];
fDiff[1] = y-camera.fPos[1];
fDiff[2] = z-camera.fPos[2];
//float fProd = vDiff*camera.matView[0];
float fProd =
fDiff[0]*camera.fViewMat[0][0] +
fDiff[1]*camera.fViewMat[0][1] +
fDiff[2]*camera.fViewMat[0][2];
if( fProd < 0 )
return FALSE;
//CVec3 vView = vDiff*!camera.matView;
float fInv[3][3];
fInv[0][0] = camera.fViewMat[1][1]*camera.fViewMat[2][2]-camera.fViewMat[1][2]*camera.fViewMat[2][1];
fInv[1][0] = camera.fViewMat[1][2]*camera.fViewMat[2][0]-camera.fViewMat[1][0]*camera.fViewMat[2][2];
fInv[2][0] = camera.fViewMat[1][0]*camera.fViewMat[2][1]-camera.fViewMat[1][1]*camera.fViewMat[2][0];
float fDet = camera.fViewMat[0][0]*fInv[0][0]+camera.fViewMat[0][1]*fInv[1][0]+camera.fViewMat[0][2]*fInv[2][0];
float fInvDet = 1.0f / fDet;
fInv[0][1] = camera.fViewMat[0][2]*camera.fViewMat[2][1]-camera.fViewMat[0][1]*camera.fViewMat[2][2];
fInv[0][2] = camera.fViewMat[0][1]*camera.fViewMat[1][2]-camera.fViewMat[0][2]*camera.fViewMat[1][1];
fInv[1][1] = camera.fViewMat[0][0]*camera.fViewMat[2][2]-camera.fViewMat[0][2]*camera.fViewMat[2][0];
fInv[1][2] = camera.fViewMat[0][2]*camera.fViewMat[1][0]-camera.fViewMat[0][0]*camera.fViewMat[1][2];
fInv[2][1] = camera.fViewMat[0][1]*camera.fViewMat[2][0]-camera.fViewMat[0][0]*camera.fViewMat[2][1];
fInv[2][2] = camera.fViewMat[0][0]*camera.fViewMat[1][1]-camera.fViewMat[0][1]*camera.fViewMat[1][0];
camera.fViewMat[0][0] = fInv[0][0]*fInvDet;
camera.fViewMat[0][1] = fInv[0][1]*fInvDet;
camera.fViewMat[0][2] = fInv[0][2]*fInvDet;
camera.fViewMat[1][0] = fInv[1][0]*fInvDet;
camera.fViewMat[1][1] = fInv[1][1]*fInvDet;
camera.fViewMat[1][2] = fInv[1][2]*fInvDet;
camera.fViewMat[2][0] = fInv[2][0]*fInvDet;
camera.fViewMat[2][1] = fInv[2][1]*fInvDet;
camera.fViewMat[2][2] = fInv[2][2]*fInvDet;
float fView[3];
fView[0] = fInv[0][0]*fDiff[0]+fInv[1][0]*fDiff[1]+fInv[2][0]*fDiff[2];
fView[1] = fInv[0][1]*fDiff[0]+fInv[1][1]*fDiff[1]+fInv[2][1]*fDiff[2];
fView[2] = fInv[0][2]*fDiff[0]+fInv[1][2]*fDiff[1]+fInv[2][2]*fDiff[2];
//CVec3 vCam( -vView.fY,-vView.fZ,vView.fX );
float fCam[3];
fCam[0] = -fView[1];
fCam[1] = -fView[2];
fCam[2] = fView[0];
float fScreenX = (rc.right-rc.left)/2.0f;
float fScreenY = (rc.bottom-rc.top)/2.0f;
// Thanks pat0! Aspect ratio fix
float fTmpX = fScreenX/tan(((camera.fFov*44.0f)/2.0f)*M_DEG2RAD);
float fTmpY = fScreenY/tan(((camera.fFov*35.0f)/2.0f)*M_DEG2RAD);
POINT pctMouse;
//pctMouse.x = fScreenX + vCam.fX*fTmpX/vCam.fZ;
pctMouse.x = fScreenX + fCam[0]*fTmpX/fCam[2];
//pctMouse.y = fScreenY + vCam.fY*fTmpY/vCam.fZ;
pctMouse.y = fScreenY + fCam[1]*fTmpY/fCam[2];
if( pctMouse.x < 0 || pctMouse.y < 0 || pctMouse.x > rc.right || pctMouse.y > rc.bottom )
return FALSE;
if( !::ClientToScreen(hwndWoW,&pctMouse) )
return FALSE;
if( !::SetCursorPos(pctMouse.x,pctMouse.y) )
return FALSE;
return TRUE;
}
///////////////////////////////////////
0x004B4B20 -> GetCamera()