# how use Math for create 3D games?

## Recommended Posts

i need 1 correction: the screen only use 2D(X, Y) and not 3D(X, Y, Z)... so how can i create the perspective?

is these math correct:

PosX2D = PosX3D /(FocalDistance+PosZ3D);

PosY2D = PosY3D /(FocalDistance+PosZ3D)

?

i have seen several tutorials and seems that they have their own Perspective.
understand these, i can create my own polygon and move front-back, and left-right.

##### Share on other sites

Those are good to start with. Sort your points by depth (z) and draw from back to front.

##### Share on other sites

Is always best the window center be the point 0,0?

And using float positions?

Then i must trunc() or round() to convert to integer?

Edited by Joaquim
##### Share on other sites

Experiment. Don't be afraid to try a bunch of variations. It's only software.

##### Share on other sites

I'm asking because of results. But i need add a correction for dont draw behind the player.

##### Share on other sites

done code:

```#include <windows.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <math.h>

using namespace std;

HDC HDCConsole = GetWindowDC(GetConsoleWindow());

struct position
{
float Pos3DX;
float Pos3DY;
float Pos3DZ;
float PosX;
float PosY;
POINT Perspective(int FocalDistance, POINT Center={0,0})
{
float PosX2D = Pos3DX /(FocalDistance+Pos3DZ)+ Center.x;
float PosY2D = Pos3DY /(FocalDistance+Pos3DZ)+Center.y;
POINT pos;
pos.x=round(PosX2D);
pos.y=round(PosY2D);
return pos;
}
};

void DrawPolygon(HDC HDCDestination, vector<position> Points, HPEN &LineColor, HBRUSH &PlaneColor)
{
HPEN hOldPen = (HPEN)SelectObject(HDCDestination, LineColor);
HBRUSH hOldBrush = (HBRUSH)SelectObject(HDCDestination, PlaneColor);
POINT pos[Points.size()];
for(unsigned int index=0; index<Points.size(); index++)
{
pos[index]=Points[index].Perspective(300,{0,0});
}
if(Polygon(HDCDestination,pos,4)==FALSE) MessageBox(NULL,"error","error", MB_OK);

SelectObject(HDCDestination, hOldPen);
SelectObject(HDCDestination, hOldBrush);
}

int main()
{
vector<position> Rec;
Rec.push_back({0,0,0});
Rec.push_back({10,0,0});
/*Rec.push_back({10,10,0});
Rec.push_back({0,10,0});
Rec.push_back({0,0,0});*/
HPEN hPen1 = CreatePen(PS_SOLID, 1, RGB(0, 255, 0));
HBRUSH hPlane = CreateSolidBrush(RGB(0,255,0));
do
{
DrawPolygon(HDCConsole,Rec,hPen1,hPlane);

}while(!(GetKeyState(VK_ESCAPE) & 0x8000));
DeleteObject(hPen1);
DeleteObject(hPlane);
return 0;
}```

see the perspetive():

```POINT Perspective(int FocalDistance, POINT Center={0,0})
{
float PosX2D = Pos3DX /(FocalDistance+Pos3DZ)+ Center.x;
float PosY2D = Pos3DY /(FocalDistance+Pos3DZ)+Center.y;
POINT pos;
pos.x=round(PosX2D);
pos.y=round(PosY2D);
return pos;
}```

see on the Polygon():

```POINT pos[Points.size()];
for(unsigned int index=0; index<Points.size(); index++)
{
pos[index]=Points[index].Perspective(300,{0,0});
}
if(Polygon(HDCDestination,pos,4)==FALSE) MessageBox(NULL,"error","error", MB_OK);```

if the center is {0,0} the line isn't showed.

if the center is {100,100}... the line is showed. The X seems ok... but Y ins't... the line seems drawed much more than window.

```int main()
{
vector<position> Rec;
Rec.push_back({0,0,0});
Rec.push_back({10,0,0});
/*Rec.push_back({10,10,0});
Rec.push_back({0,10,0});
Rec.push_back({0,0,0});*/```

so what is wrong with my perspective code?

##### Share on other sites

heres my perspective function:

```POINT Perspective(int FocalDistance, POINT Center={0,0})
{
float PosX2D = Pos3DX /(FocalDistance+Pos3DZ)+ Center.x;
float PosY2D = Pos3DY /(FocalDistance+Pos3DZ)+Center.y;
POINT pos;
pos.x=round(PosX2D);
pos.y=round(PosY2D);
return pos;
}```

these function is wrong...
how the perspective function works:
1 - we must calculate  the perspective(please use float or double types on divisions):

`float Perspective = FocalLenght / (FocalLenght + PolygonPosZ);`

2 - using the Perspective, we can change the shape scale or position(scale too):

```float PosX2D = Pos3DX * Perspective;
float PosY2D = Pos3DY * Perspective;```

3 - now we can add the center of screen to the  position:

```PosX2D = PosX2D + ViewCenter.x;
PosY2D = PosY2D + ViewCenter.y;```

4 - the Polygon()(for example) use the POINT pointer.. the POINT structer use LONG type(integers)... so we need use the trunc() function for convert them:

```POINT pos;
pos.x=trunc(PosX2D);
pos.y=trunc(PosY2D);```

now i can draw a polygon:

```vector<position> Polygon3D={ {30, 145,0}, {85, 165,0}, {105,
110,10}, {65, 125,10}, {30, 105,0} };

vector<POINT> polygon;

for(int index=0; index<Polygon3D.size(); index++)
{
polygon.push_back(Polygon3D[index].Perspective(300,{WindowSize.right/2, WindowSize.bottom/2 }));
}

//...
DrawPolygon(HDCConsole,polygon,hPen1,hPlane);

void DrawPolygon(HDC HDCDestination, vector<POINT> points, HPEN LineColor, HBRUSH PlaneColor)
{
HPEN hOldPen = (HPEN)SelectObject(HDCDestination, LineColor);
HBRUSH hOldBrush = (HBRUSH)SelectObject(HDCDestination, PlaneColor);
Polygon(HDCDestination,points.data(),points.size());
SelectObject(HDCDestination, hOldPen);
SelectObject(HDCDestination, hOldBrush);
}```

yes the 'data()' give us in right vector type type.

see the result:
https://imgur.com/DcU5Aov

thank you so much for all.

in time i will create a wall shape for test.

##### Share on other sites

'DrawPolygon()' draw a wall... but how can i control the draw position?

i can't draw something less than zero Z(behind the player\window\view)... so how can i control it?

##### Share on other sites

Model in 3D. Use your transforms to convert to a 2D viewport (window). Scale to screen coordinates.

If you are already clipping in 2D to the viewport, then you only need to clip the polygons in 3D to the viewplane (plane perpendicular to the direction the viewer is looking).

Harder but potentially more efficient is clipping polygons in 3D to the planes from the viewpoint to each of the four viewport sides.

Actually, 3D clipping is too advanced for now. Just keep all your models in positive z space until you have everything else working. And use triangles, not polygons, to simplify rendering. Later you can support rectangles and arbitrary polygons by breaking them down into triangles.

##### Share on other sites

Yes i'm trying clipping the 3D shape. I try avoid the Z negative. But the wrong coordenates continue happen... so what you advice more?

Anotherthing is best create my own function for draw a line?

##### Share on other sites

i think i know the problem: the polygon is a serie of lines\dots. but some can be from right to left(normaly the Destination is more far and not more close  ).

heres the position structure:

```struct position
{
float Pos3DX;
float Pos3DY;
float Pos3DZ;
float PosX;
float PosY;

//Convert 3D to 2D:
POINT Perspective(int FocalDistance=300, POINT Center={0,0})
{
if(Pos3DZ==0) Pos3DZ=1;
float perspect=FocalDistance/(FocalDistance+Pos3DZ);

float PosX2D = Pos3DX*perspect + Center.x;
float PosY2D = Pos3DY*perspect + Center.y;
POINT pos;
pos.x=trunc(PosX2D);
pos.y=trunc(PosY2D);
return pos;
}
};```

`position GetLineZZero(position Origin, position Destination)`

imagine if the 'Destination' is a Left point and the Origin is the Right point.... how can i compare the values?
is just like:

`if(Destination.Pos3DX < Origin.Pos3DX || Destination.Pos3DY < Origin.Pos3DY || Destination.Pos3DZ < Origin.Pos3DZ) SwapPosition(Origin,Destination);//Swap function not created`

i'm I right?

Edited by Joaquim
##### Share on other sites

and worst.. i tested just with 1 line, and seems not working lol
i must retest the GetLineZZero() and DrawPolygon().

##### Share on other sites

• 10 months later...
On 8/7/2022 at 3:45 PM, Joaquim said:

i need 1 correction: the screen only use 2D(X, Y) and not 3D(X, Y, Z)... so how can i create the perspective?

is these math correct:

PosX2D = PosX3D /(FocalDistance+PosZ3D);

PosY2D = PosY3D /(FocalDistance+PosZ3D)

?

i have seen several tutorials and seems that they have their own Perspective.
understand these, i can create my own polygon and move front-back, and left-right.

Sure, let's simplify it:

Your formulas are a type of 3D to 2D perspective projection. However, it's more common to divide by Z alone, not the sum of focal distance and Z:

PosX2D = (FocalDistance * PosX3D) / PosZ3D; PosY2D = (FocalDistance * PosY3D) / PosZ3D;

This provides a "camera" view, with objects appearing smaller the further they are. Note, this won't handle viewport transformations, and objects at Z=0 or negative Z may cause issues.

## Create an account

Register a new account