Source Code World2Screen - DIrect3D and OpenGL WorldToScreen Functions

Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,164
78,998
2,399
Game Name
N/A
Anticheat
N/A
Tutorial Link
N/A
How long you been coding/hacking?
4 Years
Coding Language
C++ / C#
What is a view matrix?
Matrices are used to define the location of things inside a coordinate system as well as how these things are projected onto your screen. There are actually several matrices used in 3D game programming they are:
  • Model Matrix
  • World Matrix
  • View Matrix
  • Projection Matrix
These are often all multiplied together and stored as another matrix named the Model-View-Projection Matrix. By using this matrix, you can do one transformation to move 3D coordinate into screen space. This transformation is done by using a World To Screen function.

A view matrix is 4 Vector3 structures that represents the camera position, it's viewport and frustrum. 3 of these vectors are the rotation matrix, representing the Right, Up & Forward (Look) axes. The other vector encodes the position. It can also be looked at as an array of 16 float values.

3D Game Programming uses view matrices to "transform" vertices of objects. The view matrix is used in our WorldToScreen() function to convert 3D world positions of entities to 2D screen space.

If you want to learn more about View Matrices checkout:

Guide - How to get started with learning ViewMatrix

Top 3 Best GH Resources for View Matrix & World2Screen (read them!)

How does WorldToScreen work?
You take the 3D world coordinates and do a series of transformations. A transformation is performed by using matrix multiplication. You multiply the vec3 coordinates by a specific matrix and the result is called a transform. The series of transformations is called the transformation pipeline

You go from model vertex data -> eye coordinates -> clip coordinates -> normalized device coordinates -> window coordinates

1574279422380.png



The Functions

For most games, the function is basically identical. We have several variation depending what you need:
  • Direct3D World To Screen
  • OpenGL WorldToScreen
  • Quake / Call of Duty / IdTech engine World2Screen
  • Build your own View Matrix
  • C++ & C# Versions of these functions
These functions all do the same thing, they transform 3D world coordinates into 2D screen / window coordinates. If your game uses DirectX, use the Direct3D version, if your game uses OpenGL, use that version. If you're doing a Quake Engine, Call of Duty or IdTech Engine game, against use the correct version. If your game does not have a view matrix or you're having a really hard time finding it, build your own. If the game has a traditional 16 float viewmatrix then just use the Direct3D or OpenGL function as needed.

The Direct3D and OpenGL versions are different because each store their rows/columns differently, this is referred to as being row major or column major.

Necessary functions that you may not already have:
C++:
#define PI 3.1415927f

vec3_t Subtract(vec3_t src, vec3_t dst)
{
    vec3_t diff;
    diff.x = src.x - dst.x;
    diff.y = src.y - dst.y;
    diff.z = src.z - dst.z;
    return diff;
}

vec3_t Divide(vec3_t src, float num)
{
    vec3_t vec;
    vec.x = src.x / num;
    vec.y = src.y / num;
    vec.z = src.z / num;

    return vec;
}

float Magnitude(vec3_t vec)
{
    return sqrtf(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z);
}

float DotProduct(vec3_t src, vec3_t dst)
{
    return src.x * dst.x + src.y * dst.y + src.z * dst.z;
}

Direct3D World to Screen
Does not matter if it's D3D9, D3D11, D3D12 they all use the same function. In DirectX the MVP matrix is row major and not column major.

C++:
bool WorldToScreen(vec3_t pos, vec2 &screen, float matrix[16], int windowWidth, int windowHeight)
{
//Matrix-vector Product, multiplying world(eye) coordinates by projection matrix = clipCoords
vec4 clipCoords;
clipCoords.x = pos.x*matrix[0] + pos.y*matrix[1] + pos.z*matrix[2] + matrix[3];
clipCoords.y = pos.x*matrix[4] + pos.y*matrix[5] + pos.z*matrix[6] + matrix[7];
clipCoords.z = pos.x*matrix[8] + pos.y*matrix[9] + pos.z*matrix[10] + matrix[11];
clipCoords.w = pos.x*matrix[12] + pos.y*matrix[13] + pos.z*matrix[14] + matrix[15];

if (clipCoords.w < 0.1f)
return false;

//perspective division, dividing by clip.W = Normalized Device Coordinates
vec3_t NDC;
NDC.x = clipCoords.x / clipCoords.w;
NDC.y = clipCoords.y / clipCoords.w;
NDC.z = clipCoords.z / clipCoords.w;

screen.x = (windowWidth / 2 * NDC.x) + (NDC.x + windowWidth / 2);
screen.y = -(windowHeight / 2 * NDC.y) + (NDC.y + windowHeight / 2);
return true;
}
Using Direct3D API for W2S
This assumes you have a hooked directx9 device. DOES NOT WORK ON ALL GAMES

function:
bool WorldToScreen(LPDIRECT3DDEVICE9 pDevice, D3DXVECTOR3* pos, D3DXVECTOR3* out) {
    D3DVIEWPORT9 viewPort;
    D3DXMATRIX view, projection, world;

    pDevice->GetViewport(&viewPort);
    pDevice->GetTransform(D3DTS_VIEW, &view);
    pDevice->GetTransform(D3DTS_PROJECTION, &projection);
    D3DXMatrixIdentity(&world);

    D3DXVec3Project(out, pos, &viewPort, &projection, &view, &world);
     if (out->z < 1) {
         return true;
     }
     return false;
}

calling the function:
calling function:
D3DXVECTOR3 pos = { 0.0f,0.0f,0.0f }; //world position to project to screen {x,y,z}
D3DXVECTOR3 screenPos;
if (WorldToScreen(pDevice, &pos, &screenPos)) {
    //do stuff here
    //screenPos.x , screenPos.y
}

OpenGL WorldToScreen
The matrix is column major in OpenGL games.

C++:
bool WorldToScreen(vec3_t pos, vec3_t &screen, float matrix[16], int windowWidth, int windowHeight)
{
    //Matrix-vector Product, multiplying world(eye) coordinates by projection matrix = clipCoords
    vec4 clipCoords;
    clipCoords.x = pos.x*matrix[0] + pos.y*matrix[4] + pos.z*matrix[8] + matrix[12];
    clipCoords.y = pos.x*matrix[1] + pos.y*matrix[5] + pos.z*matrix[9] + matrix[13];
    clipCoords.z = pos.x*matrix[2] + pos.y*matrix[6] + pos.z*matrix[10] + matrix[14];
    clipCoords.w = pos.x*matrix[3] + pos.y*matrix[7] + pos.z*matrix[11] + matrix[15];

    if (clipCoords.w < 0.1f)
        return false;

    //perspective division, dividing by clip.W = Normalized Device Coordinates
    vec3_t NDC;
    NDC.x = clipCoords.x / clipCoords.w;
    NDC.y = clipCoords.y / clipCoords.w;
    NDC.z = clipCoords.z / clipCoords.w;

        //Transform to window coordinates
    screen.x = (windowWidth / 2 * NDC.x) + (NDC.x + windowWidth / 2);
    screen.y = -(windowHeight / 2 * NDC.y) + (NDC.y + windowHeight / 2);
    return true;
}

OPENGL C# WorldToScreen
C#:
public static float[] WorldToScreen(byte[] matrix, PlayerEntity entity, int width, int height, POINTS gameWindow, bool foot = true)
{

    float m11 = BitConverter.ToSingle(matrix, 0), m12 = BitConverter.ToSingle(matrix, 4), m13 = BitConverter.ToSingle(matrix, 8), m14 = BitConverter.ToSingle(matrix, 12);
    float m21 = BitConverter.ToSingle(matrix, 16), m22 = BitConverter.ToSingle(matrix, 20), m23 = BitConverter.ToSingle(matrix, 24), m24 = BitConverter.ToSingle(matrix, 28);
    float m31 = BitConverter.ToSingle(matrix, 32), m32 = BitConverter.ToSingle(matrix, 36), m33 = BitConverter.ToSingle(matrix, 40), m34 = BitConverter.ToSingle(matrix, 44);
    float m41 = BitConverter.ToSingle(matrix, 48), m42 = BitConverter.ToSingle(matrix, 52), m43 = BitConverter.ToSingle(matrix, 56), m44 = BitConverter.ToSingle(matrix, 60);

    float zPos = entity.getZPos(foot);

    //multiply vector against matrix
    float screenX = (m11 * entity.xPos) + (m21 * entity.yPos) + (m31 * zPos) + m41;
    float screenY = (m12 * entity.xPos) + (m22 * entity.yPos) + (m32 * zPos) + m42;
    float screenW = (m14 * entity.xPos) + (m24 * entity.yPos) + (m34 * zPos) + m44;


    //camera position (eye level/middle of screen)
    float camX = width / 2f;
    float camY = height / 2f;

    //convert to homogeneous position
    float x = camX + (camX * screenX / screenW);
    float y = camY - (camY * screenY / screenW);
    float[] screenPos = { x, y };

    //check it is in the bounds to draw
    if (screenW > 0.001f  //not behind us
        && gameWindow.Left + x > gameWindow.Left && gameWindow.Left + x < gameWindow.Right //not off the left or right of the window
        && gameWindow.Top + y > gameWindow.Top && gameWindow.Top + y < gameWindow.Bottom) //not off the top of bottom of the window
    {
        return screenPos;
    }
    return null;
}
Direct3D C# W2S
C#:
public static float[] WorldToScreen(byte[] matrix, PlayerEntity entity, int width, int height, POINTS gameWindow, bool foot = true)
{
    float m11 = BitConverter.ToSingle(matrix, 0), m12 = BitConverter.ToSingle(matrix, 16), m13 = BitConverter.ToSingle(matrix, 32), m14 = BitConverter.ToSingle(matrix, 48);
    float m21 = BitConverter.ToSingle(matrix, 4), m22 = BitConverter.ToSingle(matrix, 20), m23 = BitConverter.ToSingle(matrix, 36), m24 = BitConverter.ToSingle(matrix, 25);
    float m31 = BitConverter.ToSingle(matrix, 8), m32 = BitConverter.ToSingle(matrix, 24), m33 = BitConverter.ToSingle(matrix, 40), m34 = BitConverter.ToSingle(matrix, 56);
    float m41 = BitConverter.ToSingle(matrix, 12), m42 = BitConverter.ToSingle(matrix, 28), m43 = BitConverter.ToSingle(matrix, 44), m44 = BitConverter.ToSingle(matrix, 60);

    float zPos = entity.getZPos(foot);

    //multiply vector against matrix
    float screenX = (m11 * entity.xPos) + (m21 * entity.yPos) + (m31 * zPos) + m41;
    float screenY = (m12 * entity.xPos) + (m22 * entity.yPos) + (m32 * zPos) + m42;
    float screenW = (m14 * entity.xPos) + (m24 * entity.yPos) + (m34 * zPos) + m44;


    //camera position (eye level/middle of screen)
    float camX = width / 2f;
    float camY = height / 2f;

    //convert to homogeneous position
    float x = camX + (camX * screenX / screenW);
    float y = camY - (camY * screenY / screenW);
    float[] screenPos = { x, y };

    //check it is in the bounds to draw
    if (screenW > 0.001f  //not behind us
        && gameWindow.Left + x > gameWindow.Left && gameWindow.Left + x < gameWindow.Right //not off the left or right of the window
        && gameWindow.Top + y > gameWindow.Top && gameWindow.Top + y < gameWindow.Bottom) //not off the top of bottom of the window
    {
        return screenPos;
    }
    return null;
}

FOV WorldToScreen for Quake / Call of Duty / IdTech engine and more

C++:
//Thanks to c5 for this knowledge
bool WorldToScreen(vec3_t src, vec3_t dst, vec3_t &screen, float fovx, float fovy, float windowWidth, float windowHeight, vec3_t left, vec3_t up, vec3_t forward)
{
        vec3_t transform;
        float xc, yc;
        float px, py;
        float z;

        px = tan(fovx * PI / 360.0);
        py = tan(fovy * PI / 360.0);

        transform = Subtract(dst, src);

        xc = windowWidth / 2.0;
        yc = windowHeight / 2.0;

        z = DotProduct(transform, left);

        if (z <= 0.1)
    {
      return false;
    }

        screen.x = xc - DotProduct(transform, up) *xc / (z*px);
        screen.y = yc - DotProduct(transform, forward) *yc / (z*py);

        return true;
}
Using this FOV World2Screen for Quake / COD / idTech is easy peazy becuz of this struct that replaces a matrix[16]
C++:
struct refdef_t
{
    int            x, y, width, height;
    float        fov_x, fov_y;
    vec3_t        vieworg;
    vec3_t        viewaxis[3];        // transformation matrix
};
Build your own View Matrix
Tutorial - Calculate your own ViewProjection matrix

Additional GH Resources
Guide - How to get started with learning ViewMatrix
Tutorial - So what is a viewmatrix anyway and how does a W2S work????
Tutorial - Calculate your own ViewProjection matrix
Tutorial - How to Find view Matrix Counter Strike Source setang



Offsite Resources
 
Last edited:

Garang

Newbie
Jul 27, 2015
4
314
0
I have done Unreal Tournament 1999 aimbot with Fleep's code and it works fine.
Then I tried hacking UT'99 ESP .There is a draw of lines, rectangle, and distance string,but still cannot get it project correctly to enemy.
( I am using Fleep's w2s from his "C++ CSS GDI ESP Hack").

My question is what is the right World2Screen function for Unreal Tournament 1999?

Next is Fleep's w2s function which only takes 2 arguments:

bool WorldToScreen(float * from, float * to)
{
float w = 0.0f;

to[0] = MyPlayer.WorldToScreenMatrix.flMatrix[0][0] * from[0] + MyPlayer.WorldToScreenMatrix.flMatrix[0][1] * from[1] + MyPlayer.WorldToScreenMatrix.flMatrix[0][2] * from[2] + MyPlayer.WorldToScreenMatrix.flMatrix[0][3];
to[1] = MyPlayer.WorldToScreenMatrix.flMatrix[1][0] * from[0] + MyPlayer.WorldToScreenMatrix.flMatrix[1][1] * from[1] + MyPlayer.WorldToScreenMatrix.flMatrix[1][2] * from[2] + MyPlayer.WorldToScreenMatrix.flMatrix[1][3];
w = MyPlayer.WorldToScreenMatrix.flMatrix[3][0] * from[0] + MyPlayer.WorldToScreenMatrix.flMatrix[3][1] * from[1] + MyPlayer.WorldToScreenMatrix.flMatrix[3][2] * from[2] + MyPlayer.WorldToScreenMatrix.flMatrix[3][3];

if(w < 0.01f)
return false;

float invw = 1.0f / w;
to[0] *= invw;
to[1] *= invw;

int width = (int)(m_Rect.right - m_Rect.left);
int height = (int)(m_Rect.bottom - m_Rect.top);

float x = width/2;
float y = height/2;

x += 0.5 * to[0] * width + 0.5;
y -= 0.5 * to[1] * height + 0.5;

to[0] = x+ m_Rect.left;
to[1] = y+ m_Rect.top ;

return true;
}
 

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,164
78,998
2,399
I have done Unreal Tournament 1999 aimbot with Fleep's code and it works fine.
Then I tried hacking UT'99 ESP .There is a draw of lines, rectangle, and distance string,but still cannot get it project correctly to enemy.
( I am using Fleep's w2s from his "C++ CSS GDI ESP Hack").

My question is what is the right World2Screen function for Unreal Tournament 1999?

Next is Fleep's w2s function which only takes 2 arguments:
I gave you the conversion for Rotational Unreal Unit to regular angles, just modify the function to include the conversion and it will work, I did it a few years ago but don't have the code anymore
 

Garang

Newbie
Jul 27, 2015
4
314
0
Ok, thank you Rake.
Now I know Fleep's w2s function also works for UT1999 and I will try to modify it.
 

HexMurder

Arcane Hacker
Dank Tier VIP
Dank Tier Donator
Jun 7, 2012
319
7,988
22
How do you suppose you would make a world to screen function for a game like spyro the dragon on PS1? I actually really enjoy hacking this game and have been wondering for some time now. There is no traditional 16 float matrix. The only thing i feel like you could really use would just be camera angles. Any ideas?
 

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,164
78,998
2,399
I elaborated a bit for someone that was asking for help:

I researched this shit for a few weeks before it made any sense to me. It was this guide that finally made sense to me:
OpenGL Transformation

In this function we only need 1 matrix because in most games,
the Product of the ModelView and Project Matrices is already calculated

C++:
bool WorldToScreen(vec3_t pos, vec3_t &screen, float matrix[16], int windowWidth, int windowHeight)
{
    //First, to get ClipCoords perform a Matrix-vector Product calculation
    //This is just the matrix-vector product formula using our variables
    //Clip coordinates

    vec4 clipCoords;
    clipCoords.x = pos.x*matrix[0] + pos.y*matrix[4] + pos.z*matrix[8] + matrix[12];
    clipCoords.y = pos.x*matrix[1] + pos.y*matrix[5] + pos.z*matrix[9] + matrix[13];
    clipCoords.z = pos.x*matrix[2] + pos.y*matrix[6] + pos.z*matrix[10] + matrix[14];
    clipCoords.w = pos.x*matrix[3] + pos.y*matrix[7] + pos.z*matrix[11] + matrix[15];
   
    //A vector describing a coordinate in 3d space has x, y and z.
    //A vector describing a coordinate in a projection includes W which is the depth value
    //If the W value is less than 0 it is behind the camera
    //If it is less than 0.1f it is probably clipping the camera and you don't want to
    //display ESP on this, it will look like shit
   
    if (clipCoords.w < 0.1f)
        return false;

    //dividing by clip.W = Normalized Device Coordinates
    //This is called perspective division and is a simple formula using our variables
    vec3_t NDC;
    NDC.x = clipCoords.x / clipCoords.w;
    NDC.y = clipCoords.y / clipCoords.w;
    NDC.z = clipCoords.z / clipCoords.w;

    //Simple Viewport Transoformation
    screen.x = (windowWidth / 2 * NDC.x) + (NDC.x + windowWidth / 2);
    screen.y = -(windowHeight / 2 * NDC.y) + (NDC.y + windowHeight / 2);
    return true;
}
and here some more good links for learnin':
OpenGL - Transformations
Learn OpenGL, extensive tutorial resource for learning Modern OpenGL
https://www.terathon.com/gdc07_lengyel.pdf
https://www.khanacademy.org/math/pr...ces-by-matrices/v/matrix-multiplication-intro
 
Last edited:

PwndDepot

I has a status
Dank Tier VIP
Trump Tier Donator
Dank Tier Donator
Nov 5, 2014
239
7,748
19
I modified Rake's W2S function to work with DirectX games. In DirectX the MVP matrix is row major and not column major!

C++:
bool WorldToScreen(vec3_t pos, vec2 &screen, float matrix[16], int windowWidth, int windowHeight)
{
	//Matrix-vector Product, multiplying world(eye) coordinates by projection matrix = clipCoords
	vec4 clipCoords;
	clipCoords.x = pos.x*matrix[0] + pos.y*matrix[1] + pos.z*matrix[2] + matrix[3];
	clipCoords.y = pos.x*matrix[4] + pos.y*matrix[5] + pos.z*matrix[6] + matrix[7];
	clipCoords.z = pos.x*matrix[8] + pos.y*matrix[9] + pos.z*matrix[10] + matrix[11];
	clipCoords.w = pos.x*matrix[12] + pos.y*matrix[13] + pos.z*matrix[14] + matrix[15];

	if (clipCoords.w < 0.1f)
		return false;

	//perspective division, dividing by clip.W = Normalized Device Coordinates
	vec3_t NDC;
	NDC.x = clipCoords.x / clipCoords.w;
	NDC.y = clipCoords.y / clipCoords.w;
	NDC.z = clipCoords.z / clipCoords.w;

	screen.x = (windowWidth / 2 * NDC.x) + (NDC.x + windowWidth / 2);
	screen.y = -(windowHeight / 2 * NDC.y) + (NDC.y + windowHeight / 2);
	return true;
}
 

sssky

Newbie
Jul 20, 2017
3
64
0
Rake;42453 said:
function #2 using FOV etc...

C++:
//Thanks to c5 for this knowledge

bool WorldToScreen(vec3_t src, vec3_t dst, vec3_t &screen, float fovx, float fovy, float windowWidth, float windowHeight, vec3_t left, vec3_t up, vec3_t forward)
{
		vec3_t transform;
		float xc, yc;
		float px, py;
		float z;

		px = tan(fovx * PI / 360.0);
		py = tan(fovy * PI / 360.0);

		transform = Subtract(dst, src);

		xc = windowWidth / 2.0;
		yc = windowHeight / 2.0;

		z = DotProduct(transform, left);
  
		if (z <= 0.1) 
    { 
      return false;
    }

		screen.x = xc - DotProduct(transform, up) *xc / (z*px);
		screen.y = yc - DotProduct(transform, forward) *yc / (z*py);
  
		return true;
}
What exactly is vec3_t left, vec3_t up, vec3_t forward?
 

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,164
78,998
2,399
What exactly is vec3_t left, vec3_t up, vec3_t forward?
It's called a rotation matrix, it's the first 3 vectors in a matrix that represent the X Y and Z axis but differently. Rotation can also be described a single vector of X Y Z which is called a eular angle. They are both representation of a rotation. Read more about rotation formalisms If you are serious about hacking, spend as much time as necessary to understand these concepts or you will be lost :) If your game uses eular angles, just use them. If you can't find eular angles but you have a matrix, use that but you also need FOV
 

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,164
78,998
2,399
Here's a C# implementation for you C# peeps

OPENGL C# WorldToScreen:
C#:
public static float[] WorldToScreen(byte[] matrix, PlayerEntity entity, int width, int height, POINTS gameWindow, bool foot = true)
{

    float m11 = BitConverter.ToSingle(matrix, 0), m12 = BitConverter.ToSingle(matrix, 4), m13 = BitConverter.ToSingle(matrix, 8), m14 = BitConverter.ToSingle(matrix, 12);
    float m21 = BitConverter.ToSingle(matrix, 16), m22 = BitConverter.ToSingle(matrix, 20), m23 = BitConverter.ToSingle(matrix, 24), m24 = BitConverter.ToSingle(matrix, 28);
    float m31 = BitConverter.ToSingle(matrix, 32), m32 = BitConverter.ToSingle(matrix, 36), m33 = BitConverter.ToSingle(matrix, 40), m34 = BitConverter.ToSingle(matrix, 44);
    float m41 = BitConverter.ToSingle(matrix, 48), m42 = BitConverter.ToSingle(matrix, 52), m43 = BitConverter.ToSingle(matrix, 56), m44 = BitConverter.ToSingle(matrix, 60);

    float zPos = entity.getZPos(foot);

    //multiply vector against matrix
    float screenX = (m11 * entity.xPos) + (m21 * entity.yPos) + (m31 * zPos) + m41;
    float screenY = (m12 * entity.xPos) + (m22 * entity.yPos) + (m32 * zPos) + m42;
    float screenW = (m14 * entity.xPos) + (m24 * entity.yPos) + (m34 * zPos) + m44;


    //camera position (eye level/middle of screen)
    float camX = width / 2f;
    float camY = height / 2f;

    //convert to homogeneous position
    float x = camX + (camX * screenX / screenW);
    float y = camY - (camY * screenY / screenW);
    float[] screenPos = { x, y };

    //check it is in the bounds to draw
    if (screenW > 0.001f  //not behind us
        && gameWindow.Left + x > gameWindow.Left && gameWindow.Left + x < gameWindow.Right //not off the left or right of the window
        && gameWindow.Top + y > gameWindow.Top && gameWindow.Top + y < gameWindow.Bottom) //not off the top of bottom of the window
    {
        return screenPos;
    }
    return null;
}

Direct3D C# World To Screen:
C#:
public static float[] WorldToScreen(byte[] matrix, PlayerEntity entity, int width, int height, POINTS gameWindow, bool foot = true)
{
    float m11 = BitConverter.ToSingle(matrix, 0), m12 = BitConverter.ToSingle(matrix, 16), m13 = BitConverter.ToSingle(matrix, 32), m14 = BitConverter.ToSingle(matrix, 48);
    float m21 = BitConverter.ToSingle(matrix, 4), m22 = BitConverter.ToSingle(matrix, 20), m23 = BitConverter.ToSingle(matrix, 36), m24 = BitConverter.ToSingle(matrix, 25);
    float m31 = BitConverter.ToSingle(matrix, 8), m32 = BitConverter.ToSingle(matrix, 24), m33 = BitConverter.ToSingle(matrix, 40), m34 = BitConverter.ToSingle(matrix, 56);
    float m41 = BitConverter.ToSingle(matrix, 12), m42 = BitConverter.ToSingle(matrix, 28), m43 = BitConverter.ToSingle(matrix, 44), m44 = BitConverter.ToSingle(matrix, 60);

    float zPos = entity.getZPos(foot);

    //multiply vector against matrix
    float screenX = (m11 * entity.xPos) + (m21 * entity.yPos) + (m31 * zPos) + m41;
    float screenY = (m12 * entity.xPos) + (m22 * entity.yPos) + (m32 * zPos) + m42;
    float screenW = (m14 * entity.xPos) + (m24 * entity.yPos) + (m34 * zPos) + m44;


    //camera position (eye level/middle of screen)
    float camX = width / 2f;
    float camY = height / 2f;

    //convert to homogeneous position
    float x = camX + (camX * screenX / screenW);
    float y = camY - (camY * screenY / screenW);
    float[] screenPos = { x, y };

    //check it is in the bounds to draw
    if (screenW > 0.001f  //not behind us
        && gameWindow.Left + x > gameWindow.Left && gameWindow.Left + x < gameWindow.Right //not off the left or right of the window
        && gameWindow.Top + y > gameWindow.Top && gameWindow.Top + y < gameWindow.Bottom) //not off the top of bottom of the window
    {
        return screenPos;
    }
    return null;
}
 
Last edited:

dropitem

Newbie
Jan 6, 2015
4
64
0
Hello, im new there..
I wanna ask how is worldtoscreen in 2d game world? cam is locked, so is the middle of the screen the cam. (cant zoom or move it)
thanks
 

jai

Sep 22, 2018
3
278
0
The WorldToView implementation described here is (correct me if I'm wrong) transforming the coordinates from world space to clip space And then applying viewport transform so that they can be shown on screen.

But to transform from World space to Clip space we have to transform from World space to View space by multiplying with View matrix, and then from View space to Clip space by multiplying with Projection matrix. But only one multiplication is mentioned here (with the projection matrix).

I also read that some games store multiple transformations as part of a single matrix, which means that to convert from world space to clip space, the view and projection matrices must be merged as one. But the source code for Assault Cube doesn't have a vp only matrix.

matrix definitions:
glmatrixf mvmatrix, projmatrix, mvpmatrix, invmvmatrix, invmvpmatrix;
( Line 968 of rengergl.cpp)

Shouldn't we be converting to View space and then to Clip space? Am I missing something here?
 

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,164
78,998
2,399
@jai

In this function we only need 1 matrix because in most games,
the Product of the ModelView and Project Matrices is already calculated
The "view matrix" you're gonna use in your hacks is the MVPMATRIX = model, view, projection matrix = they're already multiplied together. 99% of matrix calculations will use the MVP matrix to put things on the screen, so they calculate it and store it every frame for efficiency reasons, so that's the one we use
 

jai

Sep 22, 2018
3
278
0
Hi @Rake
Thanks for your answer.

But aren't the coordinates that we use as input for our calculations already in world space (which is local space already multiplied with model matrix)? If we use mvp matrix again, then essentially, won't we be multiplying with model matrix twice?

If we're supposed to multiply with mvp matrix, that should mean that the coordinates we get from player struct are in local space and not in world space, but that doesn't seem right because each object would be at the origin in their respective local spaces.

Also, the sample code mentions that the enemy coordinates are already in view space and we just have to apply the projection matrix. (This also doesn't seem right to me)
C++:
//Matrix-vector Product, multiplying world(eye) coordinates by projection matrix = clipCoords
My understanding is:
Coordinates of enemy player (Vec3) -> World Space (Local Space * Model matrix) -> We already have these from enemy struct
Coordinates to be used by ESP -> Clip space + Viewport transformation (World Space * view matrix * projection matrix)
 
Last edited:

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,164
78,998
2,399
@jai
This is called the world -> screen pipeline:


The entity 3d coordinates are world coordinates in the picture below it's labeled "object coordinates". You multiply them by the model view matrix to get eye coordinates. Then multiply by projection matrix to get the clip coordinates. The MVP has already been calculated so we only do one multiplication.

The MVP matrix is the dot product of the model view matrix and the projection matrix.

If you can't understand it from this thread, read the resources I posted
 
  • Like
Reactions: jai

jai

Sep 22, 2018
3
278
0
Thank you for your help @Rake! :)
Things are clear now.
I was reading a generic 3D programming tutorial which had separate steps for the Model matrix transform and View matrix transform. Then I read about how OpenGL handles it and found that it bundles the Model and View transforms together.
 
  • Like
Reactions: Rake

Bix3

Dank Tier Donator
Dec 5, 2018
4
212
0
Hello, i am wondering what these are
vec3_t left, vec3_t up, vec3_t forward
on function #2,
I understand all other parameters but these dont,
thank you for your answers : )
 

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,164
78,998
2,399
Hello, i am wondering what these are
vec3_t left, vec3_t up, vec3_t forward
on function #2,
I understand all other parameters but these dont,
thank you for your answers : )
learn how to do 3d game programming from tutorials online. They are 3, 3 dimensional vectors that represent a rotational matrix. This is one of the best resources Rotation formalisms in three dimensions - Wikipedia It's confusing AF at first, research for about a month and it'll all start to make sense
 
Attention! Before you post:

Read the How to Ask Questions Guide
99% of questions are answered in the Beginner's Guide, do it before asking a question.

No Hack Requests. Post in the correct section.  Search the forum first. Read the rules.

How to make a good post:

  • Fill out the form correctly
  • Tell us the game name & coding language
  • Post everything we need to know to help you
  • Ask specific questions, be descriptive
  • Post errors, line numbers & screenshots
  • Post code snippets using code tags
  • If it's a large project, zip it up and attach it

If you do not comply, your post may be deleted.  We want to help, please make a good post and we will do our best to help you.

Community Mods