# Thread: 3D Math: how draw a 3D cube?

1. ## Re: 3D Math: how draw a 3D cube?

You have floor width, floor height and floor ZWidth.
That would make the floor 3 dimensional, i.e. the Floor would be a block, rather than a plane.
The floor should be a plane.
I would call Z depth instead of width.

So, the floor's X value should change depending on the width of the floor.
The floor's Z value should change depending on the depth of the floor (i.e how close to your eye it is and how far into the distance does it go (into the screen))
The floor's Y value should not be changing, unless the floor is going up a hill, or down a hill, or is for some reason not flat.

2. ## Re: 3D Math: how draw a 3D cube?

qvb6: from the code, i see 2 things that make me confuse(on line 64):
- the X1,Y1, and Z1 are zero... but the X2 is 'CubeSize'... i'm confused here.

can you draw the floor and the sky, on your project, please?

now i'm preparing the Installer for install VS6 on Windows 10.

3. ## Re: 3D Math: how draw a 3D cube?

Originally Posted by joaquim
qvb6: from the code, i see 2 things that make me confuse(on line 64):
- the X1,Y1, and Z1 are zero... but the X2 is 'CubeSize'... i'm confused here.
...
CubeSize is 100, so all the edges of the cube will be 100 in length

The front, upper, left corner of the cube is (0, 0, 0).
The front, upper, right corner of the cube is (100, 0, 0)
The front, lower, right corner of the cube is (100, 100, 0)
The front, lower, left corner of the cube is (0, 100, 0)

That is the order that is given in the code, and the order drawn, from top left corner, to the top right corner, down to the right lower corner, left to the lower left corner, then up to the upper right corner.

So, line 64 is drawing the upper front edge of the cube, from (0, 0, 0) to (100, 0, 0)
The next line is drawing the front right edge edge of the cube (right side of the front face). That would be from (100, 0, 0) to (100, 100, 0).

For all the front face corners, the Z value would be the same, i.e. 0.
For all the back face corners, the Z value would be the same, i.e. 100.
The X,Y values for the front face and the back face would be the same, for the corresponding corners, only the Z value would be different.

So, compare the backface below with the frontface above, just the Z values are changed.
The front, upper, left corner of the cube is (0, 0, 100).
The front, upper, right corner of the cube is (100, 0, 100)
The front, lower, right corner of the cube is (100, 100, 100)
The front, lower, left corner of the cube is (0, 100, 100)

Z is positive, going "into" the screen. X is positive to the right, and Y is positive down the screen.

4. ## Re: 3D Math: how draw a 3D cube?

The DrawCube subroutine draws the cube with relative 3d coordinates, i.e. the coordinates of the Model of the cube.
It callss Draw3DLine, which will place the cube somewhere in 3D space, by adding the Origin3D.X and .Y values, So, Origin3D defines where in space the cube is located.

After Draw3DLine converts the 3D coordinates into 2D projection coordinates, then the Line is drawn, and the center of the coordinate system, i.e. the center of the eyepoint on the screen, is defined by Origin2D. So, that gets added to the 2D coordinates to determine where the lines end up on the screen.

This essentially moves the (0,0) point of the picturebox to the center of the picturebox.
Of course, with VB6, you could have just changed the Scale of the picturebox to put 0,0 at the center of the Picturebox and you wouldn't have to Add Origin2D.x and .y to every point when drawing. But you might not have that option with other drawing tools, so this type of code would work on any bitmap, where (0,0) was in the upper left corner, and you couldn't change the scale of the drawing surface before drawing.

5. ## Re: 3D Math: how draw a 3D cube?

thanks i tested the code and i have seen the cube rotating.
on previous post you speaked about isometrics figures with floors\sky, right?

Passel: you said that the floor be flat i can't change the Y. ok i must use the X as Y positions, but i can't use the Height... until here i agree with you.
but even with these values:
Code:
```//Position and Size Floor:
int FloorX=100, FloorY=300, FloorZ=1,FloorWidth=1000, FloorHeight=1, FloorZDepth=500;

//floor vectors:
POINT FloorPoints[5];

FloorPoints[0] = {(FloorX * MeDistance) / (FloorZ + MeDistance), (FloorY * MeDistance) / (FloorZ + MeDistance)   };
FloorPoints[1] = { (FloorX *MeDistance) / (FloorZ +MeDistance), (FloorHeight)*MeDistance/(FloorZDepth+MeDistance) };
FloorPoints[2] = { (FloorWidth *MeDistance) / (FloorZ +MeDistance), (FloorHeight)*MeDistance/(FloorZDepth+MeDistance)};
FloorPoints[3] = { (FloorWidth *MeDistance) / (FloorZ +MeDistance), (FloorY)*MeDistance/(FloorZDepth+MeDistance) };
FloorPoints[4] = {(FloorX * MeDistance) / (FloorZ + MeDistance), (FloorY * MeDistance) / (FloorZ + MeDistance)   };

HBRUSH hBrush1 = CreateSolidBrush(RGB(0, 0, 255));
HBRUSH holdBrush = (HBRUSH)SelectObject(Console, hBrush1);
Polygon(Console, FloorPoints, 5);

SelectObject(Console, holdBrush );
DeleteObject(hBrush1);```
the floor is drawed incorrectly.
i'm doing correctly with FloorPoints? maybe here is my mistake without notice

6. ## Re: 3D Math: how draw a 3D cube?

You're still changing Y, i.e. your using Floory and FloorHeight.
You're mixing your Z values incorrectly.

If you're model your world as X,Y,Z with X and Y being the planes you walk on (X is Left and right, Y is ahead and behind) and Z being Altitude, you need to realize that when using the projection formula provided, the Y and Z values are swapped, as I stated "Z is positive, going "into" the screen. X is positive to the right, and Y is positive down the screen.".

To draw your floor, the X and Z values should be changing (If you were drawing a wall in front of you then X and Y would be changing, and if you were drawing a wall beside you, then Y and Z would be changing).

Given the code above, you are drawing the floor like this:
0 = x, y, z
1 = x, y2, z and z2 (You mix your Z's here using FloorZ for X and FloorZDepth for Y, so you have a fourth dimension? X,Y,Z,Z2
2 = x2, y2, z and z2 (mixing Z's again)
3 = x2, y, z and z2 (mixing Z's again)
4 = x, y, z Same as first point.

What you should have is
0 = x, y, z
1 = x, y, z2
2 = x2, y, z2
3 = x2, y, z
4 = x, y, z Same as first point.

The floor doesn't go up or down, so y shouldn't change.
Fixed Code:
Code:
```        FloorPoints[0] = {(FloorX * MeDistance) / (FloorZ + MeDistance), (FloorY * MeDistance) / (FloorZ + MeDistance)   };
FloorPoints[1] = { (FloorX * MeDistance) / (FloorZDepth + MeDistance), (FloorY) * MeDistance / (FloorZDepth + MeDistance) };
FloorPoints[2] = { (FloorWidth * MeDistance) / (FloorZDepth + MeDistance), (FloorY) * MeDistance / (FloorZDepth + MeDistance)};
FloorPoints[3] = { (FloorWidth * MeDistance) / (FloorZ + MeDistance), (FloorY) * MeDistance / (FloorZ + MeDistance) };
FloorPoints[4] = {(FloorX * MeDistance) / (FloorZ + MeDistance), (FloorY * MeDistance) / (FloorZ + MeDistance)   };```
Of course you should have a function that you can pass the x,y,z values to and get the projected x,y values back which would prevent the error of applying different Z values to the X and Y calculation.

If you do the above then your given "eye point" would be the upper left corner of the window and the floor would be below that and to the right, so should be roughly trapezoid in shape, but both the left and right sides would slant from North to South East at different angles because you're defining the coordinates as being to the right and below from where you're viewing.
Tried to upload an image, but having problems, tried two different browsers, and no joy. Could be something with this computer won't allow uploads, so giving up for now.

7. ## Re: 3D Math: how draw a 3D cube?

great it's working now
thank you so much
inside the loop i did now:
Code:
`int FloorX=100, FloorY=300, FloorZ=1+MoveFrontBack,FloorWidth=1000, FloorHeight=1, FloorZDepth=500+MoveFrontBack;`
the 'MoveFrontBack' make the floor move(changing the Z), when i move...
isn't easy to understand correctly the positions\size values for the points, but with some time i will understand better.
thank you so much.
https://imgur.com/a/lUchqLV

8. ## Re: 3D Math: how draw a 3D cube?

Passel i will create a new topic, because is more different, but it's for 3D and 2D(Collisions)

9. ## Re: 3D Math: how draw a 3D cube?

passel the code works fine. but i need more 1 correction:
Code:
`FloorPoints[0] =  {(FloorX * MeDistance) / (FloorZ + MeDistance), (FloorY * MeDistance) / (FloorZ + MeDistance)   }`
seems, i think, the FloorZ + MeDistance can get zero... and we can't devide it by zero.
what i can see is the program been closed automatic... so i think the error is here...

10. ## Re: 3D Math: how draw a 3D cube?

That is another reason to have a Function, so you can calculate a value for (FloorZ + MeDistance) and if the value is > than 0, use it, and if it is 0 or less than 0, then perhaps clip the vector in some manner.
That is an issue as you move through an environment, eventually, some of the points are going to be outside your field of view, or behind your eyepoint. You have to accommodate those situations, because in some cases, the calculation will wrap in a way so instead of a trapezoidal type shape, the edges may cross each other and you end up with a twisted, hourglass shaped polygon.

I haven't really worked out how to truncate the shape when it goes out of bounds, so you'll have to do some research on an approach.
Since the original DOOM engine code is online, perhaps examining that code could be instructive, but I haven't the time myself.

11. ## Re: 3D Math: how draw a 3D cube?

"That is another reason to have a Function, so you can calculate a value for (FloorZ + MeDistance) and if the value is > than 0, use it, and if it is 0 or less than 0, then perhaps clip the vector in some manner."
that i have notice... but i'm confused: if (FloorZ + MeDistance) ==0, what i must return? 1?
and you have right i must calculate for draw what i can see and more close... the more far, i can left black

12. ## Re: 3D Math: how draw a 3D cube?

Hi joaquim - here is another code sample for you to consider if you are still exploring cubes in 3D. I wrote it using intrinsic VB6 (before I took that painful plunge into DirectX and APIs) and there is a routine which truncates lines when the line extends beyond whatever world boundary you declare. I'm sure you could improve and adapt it for your purposes. Sometimes a different 'perspective' can be illuminating

13. ## Re: 3D Math: how draw a 3D cube?

i need more corrections that i don't understand correctly
1 - the 'L', now i call it 'Medistance', is the max screen size? if the player movement is more big than 'L', the program close it.. i need to understand why the program exits (yes i fixed the division by zero)
2 - Passel you fixed my floor coordinates... but now i'm trying do the same for the roof\sky... but i can't move between the the floor and roof and the roof seems that don't have the right angle
Code:
```class Floor
{
public:
struct Position3D
{
LONG X = 0;
LONG Y = 0;
LONG Z = 0;
};

struct Size3D
{
LONG Width = 0;
LONG Height = 0;
LONG ZDepht = 0 ;
};
Position3D Position;
Size3D Size;

Floor(Position3D position, Size3D size3d)
{
Position=position;
Size=size3d;
}

void Draw(HDC Destination, LONG PlayerMoveX, LONG PlayerMoveY,LONG MeDistance)
{
int FloorZMeDistance=Position.Z+PlayerMoveY + MeDistance;
if(FloorZMeDistance==0)
FloorZMeDistance=1;
int FloorZDepthMeDistance=Size.ZDepht+PlayerMoveY + MeDistance;
if(FloorZDepthMeDistance==0)
FloorZDepthMeDistance=1;

//floor vectors:
POINT FloorPoints[5];

FloorPoints[0] = {((Position.X+PlayerMoveX) * MeDistance) / (FloorZMeDistance), (Position.Y * MeDistance) / (FloorZMeDistance)   };
FloorPoints[1] = { ((Position.X+PlayerMoveX) * MeDistance) / (FloorZDepthMeDistance), Position.Y * MeDistance / (FloorZDepthMeDistance) };
FloorPoints[2] = { ((Size.Width+Position.X+PlayerMoveX) * MeDistance) / (FloorZDepthMeDistance), Position.Y * MeDistance / (FloorZDepthMeDistance)};
FloorPoints[3] = { ((Size.Width+Position.X+PlayerMoveX) * MeDistance) / (FloorZMeDistance), Position.Y * MeDistance / (FloorZMeDistance) };
FloorPoints[4] = {((Position.X+PlayerMoveX+PlayerMoveX) * MeDistance) / (FloorZMeDistance), (Position.Y * MeDistance) / (FloorZMeDistance)   };

HBRUSH hBrush1 = CreateSolidBrush(RGB(0, 0, 255));
HBRUSH holdBrush = (HBRUSH)SelectObject(Console, hBrush1);
Polygon(Console, FloorPoints, 5);

SelectObject(Console, holdBrush );
DeleteObject(hBrush1);
}
};

//............
//Position and Size for Sky:
Floor Sky({100, 5, -1},{700, 1, 800});
Sky.Draw(Console,MoveLeftRight,MoveFrontBack, MeDistance);```
result(sky green and floor blue):
https://imgur.com/3CS4Kr5

14. ## Re: 3D Math: how draw a 3D cube?

Deleted double of post

15. ## Re: 3D Math: how draw a 3D cube?

My example of a softrender for cubes on vb6 may also be useful: https://yadi.sk/d/pFM1V8kA8ab5hg
Not only lines are drawn here, but faces are colored in different colors, and there is a zBuffer here.

16. ## Re: 3D Math: how draw a 3D cube?

Mikle: on a project, never compact it with an exe... my Windows Defender, thot it was a virus hehehehe
to be honest i need my questions answers for i understand better... sorry

17. ## Re: 3D Math: how draw a 3D cube?

Originally Posted by joaquim
i need more corrections that i don't understand correctly
1 - the 'L', now i call it 'Medistance', is the max screen size? if the player movement is more big than 'L', the program close it.. i need to understand why the program exits (yes i fixed the division by zero)
2 - Passel you fixed my floor coordinates... but now i'm trying do the same for the roof\sky... but i can't move between the the floor and roof and the roof seems that don't have the right angle
[CODE]class Floor
{
...
FloorPoints[0] = {((Position.X+PlayerMoveX) * MeDistance) / (FloorZMeDistance), (Position.Y * MeDistance) / (FloorZMeDistance) };
...
FloorPoints[4] = {((Position.X+PlayerMoveX+PlayerMoveX) * MeDistance) / (FloorZMeDistance), (Position.Y * MeDistance) / (FloorZMeDistance) };

...
1. You can't draw a polygon if the coordinates are invalid, so your program is probably exiting because of an error in the Polygon api call parameters.You will either have to make the polygon correct, by creating a modified polygon when the coordinates go out of bounds, or don't draw the polygon.
That is what SeabrookStan and Mikle were trying to show, i.e. where they had to truncate a lines coordinates, to a point partway along the line when it goes out of bounds. Mikle's is a bit more complex because it is tessellating the surface into triangles, which is the way 3D graphics is normally done, so when you have different surfaces meet, you have to subdivide the original plane (normally two triangles), into sub triangles along the edge where the planes intersect. Mikles code also is just doing straight 3D coordinate drawing, i.e. Isometric, rather than perspective.

Since you're working in C++, I don't really have a test bed to try your code, and I don't really have the time to play with translating your methods into VB to test things out.

As for 2, Point[0] and Point[4] should be the same, but as you can see in your code, they are not the same point. Since they should be the same, I don't manually type in the statement for [4], I just copy the line setting [0] and change the 0 to a 4.
It looks like you obviously modified the code manually rather than copy the line, so inadvertently added PlayerMoveX twice. I didn't test the code, but I would guess that is probably the reason you see what you see.

18. ## Re: 3D Math: how draw a 3D cube?

Passel: please answer these question, because i still confused: if i use coordinates more big than 'L'(from previous\original formula), i will get invalid values that can close the program?(i did several tests, but i continues a little confused... the floor size\position can't be more big than

ok.... i fixed about Point[0] and Point[4](something that i missed or always change it ).
but correct me more 1 thing that i'm still confused... how can i give a correct position size too the sky\roof?
i must see what is on my front, but not on my top. so what i think is the bottom position must be more little than the front:
Code:
```class Floor
{
public:
struct Position3D
{
LONG X = 0;
LONG Y = 0;
LONG Z = 0;
};

struct Size3D
{
LONG Width = 0;
LONG Height = 0;
LONG ZDepht = 0 ;
};
Position3D Position;
Size3D Size;

Floor(Position3D position, Size3D size3d)
{
Position=position;
Size=size3d;
}

void Draw(HDC Destination, LONG PlayerMoveX, LONG PlayerMoveY,LONG MeDistance, COLORREF color)
{
int FloorZMeDistance=Position.Z+PlayerMoveY + MeDistance;
if(FloorZMeDistance==0)
FloorZMeDistance=1;
int FloorZDepthMeDistance=Size.ZDepht+PlayerMoveY + MeDistance;
if(FloorZDepthMeDistance==0)
FloorZDepthMeDistance=1;

//floor vectors:
POINT FloorPoints[5];

FloorPoints[0] = {((Position.X+PlayerMoveX) * MeDistance) / (FloorZMeDistance), (Position.Y * MeDistance) / (FloorZMeDistance)   };
FloorPoints[1] = { ((Position.X+PlayerMoveX) * MeDistance) / (FloorZDepthMeDistance), Position.Y * MeDistance / (FloorZDepthMeDistance) };
FloorPoints[2] = { ((Size.Width+Position.X+PlayerMoveX) * MeDistance) / (FloorZDepthMeDistance), Position.Y * MeDistance / (FloorZDepthMeDistance)};
FloorPoints[3] = { ((Size.Width+Position.X+PlayerMoveX) * MeDistance) / (FloorZMeDistance), Position.Y * MeDistance / (FloorZMeDistance) };
FloorPoints[4] = {((Position.X+PlayerMoveX) * MeDistance) / (FloorZMeDistance), (Position.Y * MeDistance) / (FloorZMeDistance)   };

HBRUSH hBrush1 = CreateSolidBrush(color);
HBRUSH holdBrush = (HBRUSH)SelectObject(Console, hBrush1);
Polygon(Console, FloorPoints, 5);

SelectObject(Console, holdBrush );
DeleteObject(hBrush1);
}
};

Floor Sky({100, 50, -1000},{700, -100, 800});//yes using the Floor class```
result:
https://imgur.com/y8chgQT

in these case, do i must change the Z angle?
because seems parallel to the floor

19. ## Re: 3D Math: how draw a 3D cube?

It was discussed a couple of times in previous posts.
For the projection, all the points are relative to the position of the eyepoint.
You are not offsetting (0,0) to the center of the screen, you are leaving it at the upper, left corner, and your Y coordinates are all positive, likewise your X coordinates are positive.
So, everything you look at is down and to the right of the eyepoint, so you can only see the top of the floor and the top of the ceiling.

What you want to do is to treat the eyepoint as being in the center of the screen, so the left side of the floor and ceiling should be negative, and the right side positive.
Likewise, the Y value for the floor should be positive (the floor is below the eye) and the Y value for the ceiling should be negative (the ceiling is above the eye).

If you use negative and positive values so that the points are to the left and right, and above and below the eye, you will be projecting the coordinates the way you should be.
You just have to add an X,Y offset when drawing, so that the (0,0) point of the drawing is in the center of the window, or at least near it, instead of being at the upper-left corner.

20. ## Re: 3D Math: how draw a 3D cube?

Code:
```Floor(Position3D position, Size3D size3d, Angle3D Ang={0,0,0})
{
Position=position;
Size=size3d;
Angle =Ang;
if(Angle.X!=0)
{
Position.Y =Position.Y*cos(Ang.X) - Position.Z*sin(Ang.X);
Position.Z=Position.Y*sin(Ang.X) + Position.Z*cos(Ang.X);
}

if(Angle.Y!=0)
{
Position.X =Position.Z*sin(Ang.Y) + Position.X*cos(Ang.Y);
Position.Z=Position.Z*cos(Ang.Y) - Position.X*sin(Ang.Y);
}

if(Angle.Z!=0)
{
Position.X = (Position.X + Position.X*cos(Ang.Z)) - (Position.X + Position.Y*sin(Ang.Z));
Position.Y= (Position.Y + Position.X*sin(Ang.Z)) + (Position.Y + Position.Y*cos(Ang.Z));
}
}```
is the AngleZ correctly calculated?
yes i added the X and Y position for use the same point... i think it's the right way...
the problem, from drawed sky, is the Width more big on left(position X is less than i wanted, but the size is added to that position.. so the size point is the floor size point)

21. ## Re: 3D Math: how draw a 3D cube?

I didn't say anything about using an angle and rotating Z for the issue you were having in post #58.

I said you have to move where the eye point was, so that your 0,0 reference is somewhere near the middle of your window.
That way you can draw things below and above the eye, and also to the left and right of the eye.

Right now you have the eye point in the upper left corner of the window, so everything is below and to the right of your eye perspective.
You can never see the bottom or right side of anything.

Given the code you had in post #58, in order to move the eye point to somewhere inside your window, you need to add a center X and center Y offset to all the points to translate them before drawing (after your perspective calculations).
And you have to change the coordinates of your polygons, so that the X values are negative if the point is to the left of the eye and Y values are negative if the point is above your eye (e.g. the sky).

So, the existing code in post #58 I expected to be modified something along these lines so you have a full four quadrant perspective view, not a one quadrant perspective view.
Code:
```class Floor
{
public:
struct Position3D
{
LONG X = 0;
LONG Y = 0;
LONG Z = 0;
};

struct Size3D
{
LONG Width = 0;
LONG Height = 0;
LONG ZDepht = 0 ;
};
Position3D Position;
Size3D Size;

Floor(Position3D position, Size3D size3d)
{
Position=position;
Size=size3d;
}

//eye point in window
int cx = 500;
int cy = 500;

void Draw(HDC Destination, LONG PlayerMoveX, LONG PlayerMoveY,LONG MeDistance, COLORREF color)
{
int FloorZMeDistance=Position.Z+PlayerMoveY + MeDistance;
if(FloorZMeDistance==0)
FloorZMeDistance=1;
int FloorZDepthMeDistance=Size.ZDepht+PlayerMoveY + MeDistance;
if(FloorZDepthMeDistance==0)
FloorZDepthMeDistance=1;

//floor vectors:
POINT FloorPoints[5];

FloorPoints[0] = {(((Position.X+PlayerMoveX) * MeDistance) + cx)/ (FloorZMeDistance), (Position.Y * MeDistance) / FloorZMeDistance + cy  };
FloorPoints[1] = {(((Position.X+PlayerMoveX) * MeDistance) + cx) / (FloorZDepthMeDistance), (Position.Y * MeDistance) / FloorZDepthMeDistance + cy};
FloorPoints[2] = {(((Size.Width+Position.X+PlayerMoveX) * MeDistance) + cx) / (FloorZDepthMeDistance), (Position.Y * MeDistance) / FloorZDepthMeDistance + cy};
FloorPoints[3] = {(((Size.Width+Position.X+PlayerMoveX) * MeDistance) + cx) / (FloorZMeDistance), (Position.Y * MeDistance) / FloorZMeDistance + cy};
FloorPoints[4] = {(((Position.X+PlayerMoveX) * MeDistance) + cx) / (FloorZMeDistance), (Position.Y * MeDistance) / FloorZMeDistance + cy };

HBRUSH hBrush1 = CreateSolidBrush(color);
HBRUSH holdBrush = (HBRUSH)SelectObject(Console, hBrush1);
Polygon(Console, FloorPoints, 5);

SelectObject(Console, holdBrush );
DeleteObject(hBrush1);
}
};

//Draw sky above (-300) the eye Y (500)
Floor Sky({-350, -300, 0},{700, 1, 800});//yes using the Floor class
Sky.Draw(Console,MoveLeftRight,MoveFrontBack, MeDistance, RGB(0, 255, 0));

//Draw floor below (300) the eye Y (500)
Floor floor({-350, 300, 0},{700, 1, 800});
floor.Draw(Console,MoveLeftRight,MoveFrontBack, MeDistance, RGB(0, 0, 255));```

22. ## Re: 3D Math: how draw a 3D cube?

so i did these:
Code:
```int cx = (Console.GetWindowSize().right-Console.GetWindowSize().left)/2;
int cy = (Console.GetWindowSize().bottom-Console.GetWindowSize().top)/2;```
cy and cx are the center of window view.
but i continues with sky plane problems
- i can move between floor and the sky;
- when i move until the floor end, the sky Height is automatic grow.. and the Z angle seems like floor.. but, i think, it must be inverted.... the back sky must be down and the front must be up... right?
for now the rotation calculations aren't working

23. ## Re: 3D Math: how draw a 3D cube?

Since we don't have a common code base we can work against, it makes it hard to know what you are doing.
Since you want to do this 3D programing the "old fashion" way, where you do the math and drawing in a primitive fashion, then perhaps referring to tutorials from a time where doing this type of coding was necessary would help to get a handle on things.
In particular, back in the old QBasic days with the limited type of graphics that was available, there were multiple tutorials on just the type of thing you are trying to do now.

This site has a bunch of old QBasic and QB based graphic tutorial and example code.
There is a section of 3D graphics, and later other 3D tutorials by various people. Some of the links may be broken, but a couple I looked at were good.
In particular "Why Divide by Z?" is probably a very good article for you to try to work through to see if you can "Unravel the geometry behind perspective projection".

There are likely a number of other good articles in that list of links, but I've mostly only read that "Why Divede by Z?" thoroughly at this point. Hopefully, once the method behind the projection is understood, then there will be other articles that cover moving through an environment and rotating your view.

p.s. Further down the list from the collected 3D graphics section, are some Series link, and probably "RelSoft's 3D Series", would also be a good one to work through since it should be a set of tutorials that build on one another to take you from the Basics of 3D projection, on to Rotation, Vectors and Matrices.

p.p.s. And, if for some reason you would like to try out some of this old QBasic or QB code, a good way would likely be to Install QB64 which is a QB 4.6 IDE emulation, which behind the scene generates C++ code and compiles it, so will run on 64-bit machines. It has much more capability than the old QB compiler by the use of an extended syntax, but the main benefit is that it can usually run old QBasic and QB code without modification, so if you have old QBasic or QB code hanging around, you have a way to run it in 64-bit without having to resort to running DOS in a virtual machine.

24. ## Re: 3D Math: how draw a 3D cube?

Code:
```#include<windows.h>
#include<iostream>
#include <fstream>
#include <math.h>

using namespace std;

class Console
{

private:
HWND myconsole;
HDC mydc;

public:

Console()
{
myconsole = GetConsoleWindow();
//Get a handle to device context
mydc = GetDC(myconsole);
}

~Console()
{
ReleaseDC(myconsole, mydc);
}

operator HDC()
{
return mydc;
}

operator HWND()
{
return myconsole;
}

RECT GetWindowSize()
{
RECT RectWindow;
GetWindowRect(myconsole,&RectWindow);
return RectWindow;
}

void Clear(COLORREF Color=RGB(0,0,0))
{
//Clear:
RECT RectWindow;
GetWindowRect(myconsole,&RectWindow);
RectWindow.top=0;
RectWindow.left=0;
HBRUSH clean=CreateSolidBrush(Color);
HBRUSH oldbrush= (HBRUSH)SelectObject(mydc,clean);
FillRect(mydc,&RectWindow,clean);
SelectObject(mydc, oldbrush);
DeleteObject(clean);
}

}Console;

struct Position3D
{
int X = 0;
int Y = 0;
int Z = 0;
};

struct Size3D
{
int Width = 0;
int Height = 0;
int ZDepht = 0 ;
};

struct Angle3D
{
int X=0;
int Y =0;
int Z =0;
};

struct Player
{
LONG MoveFrontBack=0;
LONG MoveLeftRight=0;
LONG RotationX=0;
LONG RotationY =0;
LONG RotationZ=0;
};

class Object3D
{
public:

POINT Vectors[5];
double Scale=1.0;
Position3D Position={0};
Size3D Size={0};
Angle3D RotationObject={0};
LONG ScreenView=0;

POINT To2D(LONG X, LONG Y, LONG Z, LONG ViewSize)
{
POINT p2d;
LONG ZViewSize=Z+ViewSize;
if(ZViewSize==0)
ZViewSize=1;
p2d.x = X * ViewSize / (ZViewSize);
p2d.y = Y * ViewSize / (ZViewSize);
return p2d;
}

Object3D(Position3D Position3D, Size3D Size3D, LONG View)
{
ScreenView=View;
Position=Position3D;
Size=Size3D;
POINT Size2D=To2D(Size.Width,Size.Height, Size.ZDepht, ScreenView);
POINT Point2D=To2D(Position.X,Position.Y, Position.Z, ScreenView);

Vectors[0] = { (LONG)Point2D.x, (LONG)Point2D.y};
Vectors[1] = { (LONG)Size2D.x + Point2D.x, (LONG)Point2D.y};
Vectors[2] = { (LONG)Size2D.x + Point2D.x, (LONG)Size2D.y+Point2D.y };
Vectors[3] = { (LONG)Point2D.x , (LONG)Size2D.y+Point2D.y };
Vectors[4] = { (LONG)Point2D.x, (LONG)Point2D.y};
}

void Draw(HDC Destination, double Scale,POINT Move, Angle3D RotationObject)
{
POINT Size2D=To2D(Size.Width-Move.y,Size.Height, Size.ZDepht-Move.y, ScreenView);
POINT Point2D=To2D(Position.X-Move.y,Position.Y, Position.Z-Move.y, ScreenView);
Vectors[0] = { (LONG)Point2D.x, (LONG)Point2D.y};
Vectors[1] = { (LONG)Size2D.x + Point2D.x , (LONG)Point2D.y};
Vectors[2] = { (LONG)Size2D.x + Point2D.x, (LONG)Size2D.y+Point2D.y };
Vectors[3] = { (LONG)Point2D.x , (LONG)Size2D.y+Point2D.y };
Vectors[4] = { (LONG)Point2D.x, (LONG)Point2D.y};

//draw a rectangle
HPEN hWhitePen = (HPEN)GetStockObject(WHITE_PEN);
HPEN hOldPen = (HPEN)SelectObject(Destination, hWhitePen);
HBRUSH hBrush1 = CreateSolidBrush(RGB(121, 90, 0));
HBRUSH holdBrush = (HBRUSH)SelectObject(Destination, hBrush1);
Polygon(Destination, Vectors, 5);
SelectObject(Destination, hOldPen);
SelectObject(Destination, holdBrush );
DeleteObject(hBrush1);
DeleteObject(hWhitePen);
}
};

class Plane
{
public:

Angle3D Angle;
Position3D Position;
Size3D Size;

Plane(Position3D position, Size3D size3d, Angle3D Ang={0,0,0})
{
Position=position;
Size=size3d;
Angle =Ang;
if(Angle.X!=0)
{
Position.Y =Position.Y*cos(Ang.X) - Position.Z*sin(Ang.X);
Position.Z=Position.Y*sin(Ang.X) + Position.Z*cos(Ang.X);
}

if(Angle.Y!=0)
{
Position.X =Position.Z*sin(Ang.Y) + Position.X*cos(Ang.Y);
Position.Z=Position.Z*cos(Ang.Y) - Position.X*sin(Ang.Y);
}

if(Angle.Z!=0)
{
Position.X =Position.X*cos(Ang.Z) - Position.Y*sin(Ang.Z);
Position.Y=Position.X*sin(Ang.Z) + Position.Y*cos(Ang.Z);
}

}

void Draw(HDC Destination, LONG PlayerMoveX, LONG PlayerMoveY,LONG WorldSize, COLORREF color,Angle3D PlayerAngle={0,0,0 })
{
int cx = (Console.GetWindowSize().right-Console.GetWindowSize().left)/2;
int cy = (Console.GetWindowSize().bottom-Console.GetWindowSize().top)/2;
int cz = WorldSize/2;
int PosX=Position.X+cx+PlayerMoveX;
int PosY=Position.Y+cy;
int PosZ = Position.Z+cz+PlayerMoveY;

int FloorZWorldSize=PosZ + WorldSize;
if(FloorZWorldSize==0)
FloorZWorldSize=1;
int FloorZDepthWorldSize=Size.ZDepht + WorldSize;
if(FloorZDepthWorldSize==0)
FloorZDepthWorldSize=1;

//floor vectors:
POINT FloorPoints[5];

FloorPoints[0] = {((PosX) * WorldSize) / (FloorZWorldSize), (PosY * WorldSize) / (FloorZWorldSize)   };
FloorPoints[1] = { ((PosX) * WorldSize) / (FloorZDepthWorldSize), PosY * WorldSize / (FloorZDepthWorldSize) };
FloorPoints[2] = { ((Size.Width+PosX) * WorldSize) / (FloorZDepthWorldSize), PosY * WorldSize / (FloorZDepthWorldSize)};
FloorPoints[3] = { ((Size.Width+PosX) * WorldSize) / (FloorZWorldSize), PosY * WorldSize / (FloorZWorldSize) };
FloorPoints[4] = {((PosX) * WorldSize) / (FloorZWorldSize), (PosY * WorldSize) / (FloorZWorldSize)   };

HBRUSH hBrush1 = CreateSolidBrush(color);
HBRUSH holdBrush = (HBRUSH)SelectObject(Console, hBrush1);
Polygon(Console, FloorPoints, 5);

SelectObject(Console, holdBrush );
DeleteObject(hBrush1);
}
};

class World
{
public:
Size3D WorldSize={0};

Player PlayerMovement;

World(int ZDepht=0, int WolrdWidth=Console.GetWindowSize().right-Console.GetWindowSize().left, int WorldHeight=Console.GetWindowSize().bottom-Console.GetWindowSize().top)
{
WorldSize.ZDepht=ZDepht;
WorldSize.Height=WorldHeight;
WorldSize.Width=WolrdWidth;
}
}World;

int main()
{
World.WorldSize.ZDepht=2700;
World.PlayerMovement.MoveFrontBack=0;

//Position and Size for Floor:
Plane Floor({-600, 200, -1000},{1200, 0, 1000});

//Position and Size for Sky:
Plane Sky({-600, -250, -1000},{1200, 0, 1000});
do
{
Console.Clear();

//Draw Text:
string text="Distance: " + to_string(World.PlayerMovement.MoveFrontBack);
SIZE textsize;
GetTextExtentPoint32A(Console, text.c_str(),text.length(), &textsize);
RECT test;
test.top=0;
test.left=0;
test.right=textsize.cx;
test.bottom=textsize.cy;
DrawTextA(Console,text.c_str(),100,&test,0);

Floor.Draw(Console,World.PlayerMovement.MoveLeftRight,World.PlayerMovement.MoveFrontBack, World.WorldSize.ZDepht,RGB(0,0,255));
Sky.Draw(Console,World.PlayerMovement.MoveLeftRight,World.PlayerMovement.MoveFrontBack, World.WorldSize.ZDepht,RGB(0,255,0));

if(GetKeyState(VK_UP)& 0x8000)
{

if(World.PlayerMovement.MoveFrontBack<=-(Floor.Size.ZDepht+abs(Floor.Position.Z)))
World.PlayerMovement.MoveFrontBack=-(Floor.Size.ZDepht+abs(Floor.Position.Z));
else
World.PlayerMovement.MoveFrontBack-=1;
}
else if(GetKeyState(VK_DOWN)& 0x8000)
{

if(World.PlayerMovement.MoveFrontBack==0)
World.PlayerMovement.MoveFrontBack=0;
else
World.PlayerMovement.MoveFrontBack+=1;

}

if(GetKeyState(VK_LEFT)& 0x8000)
{
World.PlayerMovement.MoveLeftRight+=1;
}
else if(GetKeyState(VK_RIGHT)& 0x8000)
{
World.PlayerMovement.MoveLeftRight-=1;
}

if(GetKeyState(VK_ESCAPE)& 0x8000)
{
break;
}

if(GetKeyState('A')& 0x8000)
{
World.PlayerMovement.RotationZ-=1;
}
else if(GetKeyState('D')& 0x8000)
{
World.PlayerMovement.RotationZ+=1;
}

Sleep(5);
}while(1);
return 0;
}```
but before i continue and maybe i can resolve some problems... see these angles math:
Code:
```Plane(Position3D position, Size3D size3d, Angle3D Ang={0,0,0})
{
Position=position;
Size=size3d;
Angle =Ang;
if(Angle.X!=0)
{
Position.Y =Position.Y*cos(Ang.X) - Position.Z*sin(Ang.X);
Position.Z=Position.Y*sin(Ang.X) + Position.Z*cos(Ang.X);
}

if(Angle.Y!=0)
{
Position.X =Position.Z*sin(Ang.Y) + Position.X*cos(Ang.Y);
Position.Z=Position.Z*cos(Ang.Y) - Position.X*sin(Ang.Y);
}

if(Angle.Z!=0)
{
Position.X =Position.X*cos(Ang.Z) - Position.Y*sin(Ang.Z);
Position.Y=Position.X*sin(Ang.Z) + Position.Y*cos(Ang.Z);
}
}```
is these calculation correct?
doing these i can change the roof inclination... i think it's the Z angle( or the Y), but you can correct me...
i see another problem on code, but i must test it more... the roof can win more height, when i'm to close to the Z Depth.
these is the actual 2 problems that i must fix..

25. ## Re: 3D Math: how draw a 3D cube?

But if you're doing it wrong, even if you can make it look right by rendering the sky a different way from the floor, you end up with some sort of skewed environment.

The angle calculation is for rotating the view around the eye point, i.e. it is for simulating you turning to look a different direction. Depending on which way you are looking, you rotate the coordinates in 3D space (which haven't change, i.e. the walls, floor and ceiling don't move in your 3D world, you move and turn (the camera moves and turns), so the view changes.
The calculations should change the world coordinates into view coordinates. You don't rotate some parts of the world to fix problems with perspective.

So, rather than continue down a misguided path of throwing various math functions at coordinates to hopefully find something the may look correct, but in only one place, looking one direction, which then falls apart if you move, you need to understand the basic math, or at least get the basic functions in correct form and using them where they apply.
You may have the rotation functions correct, but if they don't apply to this situation, applying them at this point is erroneous.

The "Why divide by Z" article is a very basic tutorial and explanation for what perspective projection is and how it works, and gives the simplest code to do it, which is essentially the code you are using. But working through the article may allow you to use your code properly and more effectively.

If you've installed VB6 now, and you've done a lot of VB6 before, then perhaps working in VB6 for the purpose of learning 3D would be more productive as both you and the person that is trying to help you can work in the same environment. You don't have to use one of the more complete versions of code that you've already been given, you could just post what you're trying to do in C++ in a VB6 version of the code. That way we can work on and fix your VB6 version of the code, and you can apply that back to your C++ code on your own.

If you can do it in VB6, then you should be able to translate the code to C++ pretty easily.

If you don't want to work through the QB article, that would be my suggestion. Take the code you have in C++ and write a VB6 version of it, so you should see the same problem you are seeing in C++. Then post that VB6 code, and others can more easily evaluate the code and suggest changes, which you can use to update your C++ version as you go.

If you keep the VB6 version and the C++ version in sync, I'm assuming you will make faster progress than just working in C++ alone. And once you have both, maintaining both on your side should not be that big of a chore.

26. ## Re: 3D Math: how draw a 3D cube?

heres my actual functions and types:
Code:
```Private Type POINTAPI
x As Long
y As Long
End Type

Private Declare Function Polygon Lib "gdi32" (ByVal hdc As Long, lpPoint As POINTAPI, ByVal nCount As Long) As Long

Private Type Position2D
x As Integer
y As Integer
End Type

Private Type Position3D
x As Integer
y As Integer
Z As Integer
End Type

Private Type Angle3D
x As Integer
y As Integer
Z As Integer
End Type

Private Type Size3D
Width As Integer
Height As Integer
ZDepth As Integer
End Type

Private Type Player
Position As Position3D
Angle As Angle3D
End Type

Private Function ConvertPositon3DTo2D(Position As Position3D, World3DSize As Size3D) As Position2D
Dim ConvertedPosition As Position2D

PosZZDepth = Position.Z + World3DSize.ZDepth

If (PosZZDepth = 0) Then PosZZDepth = 1 'avoiding division by zero

ConvertedPosition.x = Position.x * World3DSize.ZDepth / PosZZDepth
ConvertedPosition.y = Position.y * World3DSize.ZDepth / PosZZDepth
ConvertPositon3DTo2D = ConvertedPosition
End Function

Private Function Rotate(Position As Position3D, Rotation As Angle3D, PositionRotated As Position3D) As Position3D
Dim ConvertedPosition As Position3D
ConvertedPosition.x = (Position.Z + PositionRotated.Z) * Sin(Angle.y) + (Position.x + PositionRotated.x) * Cos(Angle.y)
ConvertedPosition.y = (Position.y + PositionRotated.y) * Cos(Angle.x) - (Position.Z + PositionRotated.Z) * Sin(Angle.x)
ConvertedPosition.Z = (Position.y + PositionRotated.y) * Sin(Angle.x) + (Position.Z + PositionRotated.Z) * Cos(Angle.x)
Rotate = ConvertedPosition
End Function```
1 - is the Rotate() function correct?
2 - the ConvertPositon3DTo2D() function seems right... but i accept more ideas

now i'm trying draw a rectangle... i did these code in minutes: just translate de code from C++ to VB6.. too much quickly and less time... on the moment

27. ## Re: 3D Math: how draw a 3D cube?

Why are the angles and coordinates set as integers instead of fractions?

28. ## Re: 3D Math: how draw a 3D cube?

Mikle because i use the Polygon() API function for draw the lines... and the:
Code:
```Private Type POINTAPI
X As Long
Y As Long
End Type```
long structure... that's why

29. ## Re: 3D Math: how draw a 3D cube?

You have to convert the values to Long types (i.e. pixel values) for the polygon api call, but the math for rotation and angles needs to be in a floating point type for accuracy, otherwise your coordinates can end up being distorted as your true value is truncated or rounded to an Integer value, giving you some amount of error and then any multiplication will magnify those errors which can result in a point being many pixels away from where it should be.

If you convert the computed values to Longs when you draw, you can only be off by 1/2 a pixel from the ideal.
If you round to an integer during the calculations, and you're off by .5 at some point in calculation and you multiply by 10 for instance, you are now off by 5.
Converting to Longs for the polygon method should be about the only place you would use an Integer type.

30. ## Re: 3D Math: how draw a 3D cube?

Right.
But in other places, even bigger errors may occur, for example, do not forget that the angle is measured in radians, meaning we lose values between 0 degrees and 57 degrees.

31. ## Re: 3D Math: how draw a 3D cube?

so i did that changes... but i can't get the line rotating
Code:
```Option Explicit

Private Type POINTAPI
X As Long
Y As Long
End Type

Private Declare Function Polygon Lib "gdi32" (ByVal hdc As Long, lpPoint As POINTAPI, ByVal nCount As Long) As Long

Private Type Position3D
X As Long
Y As Long
Z As Long
End Type

Private Type Angle3D
X As Double
Y As Double
Z As Double
End Type

Private Type Size3D
Width As Long
Height As Long
ZDepth As Long
End Type

Private Type Player
Position As Position3D
Angle As Angle3D
End Type

Private Const Pi As Double = 3.14159265358979
Dim World3D As Size3D
Dim Angletest As Angle3D

Private Sub FillPosition2D(Position As POINTAPI, X As Long, Y As Long)
Position.X = X
Position.Y = Y
End Sub

Private Sub FillPosition3D(Position As Position3D, X As Long, Y As Long, Z As Long)
Position.X = X
Position.Y = Y
Position.Z = Z
End Sub

Private Sub FillSize3D(Size As Size3D, Width As Long, Height As Long, ZDepth As Long)
Size.Width = Width
Size.Height = Height
Size.ZDepth = ZDepth
End Sub

Private Function ConvertPositon3DTo2D(Position As Position3D, World3DSize As Size3D) As POINTAPI
Dim ConvertedPosition As POINTAPI
Dim PosZZDepth As Integer

PosZZDepth = Position.Z + World3DSize.ZDepth

If (PosZZDepth = 0) Then PosZZDepth = 1 'avoiding division by zero

ConvertedPosition.X = Position.X * World3DSize.ZDepth / PosZZDepth
ConvertedPosition.Y = Position.Y * World3DSize.ZDepth / PosZZDepth
ConvertPositon3DTo2D = ConvertedPosition
End Function

Private Function ConvertRadiansToDegrees(Rotation As Angle3D) As Angle3D
Rotation.X = Rotation.X * 180 / Pi
End Function

Private Function Rotate(Position As Position3D, Rotation As Angle3D, PositionRotated As Position3D) As Position3D
Dim ConvertedPosition As Position3D
ConvertedPosition.X = (Position.Z + PositionRotated.Z) * Sin(Rotation.Y) + (Position.X + PositionRotated.X) * Cos(Rotation.Y)
ConvertedPosition.Y = (Position.Y + PositionRotated.Y) * Cos(Rotation.X) - (Position.Z + PositionRotated.Z) * Sin(Rotation.X)
ConvertedPosition.Z = (Position.Y + PositionRotated.Y) * Sin(Rotation.X) + (Position.Z + PositionRotated.Z) * Cos(Rotation.X)
Rotate = ConvertedPosition
End Function

Private Sub DrawRectangle(Position As Position3D, Size As Size3D, Rotation As Angle3D, WorldSize As Size3D)
Dim Vertices(5) As POINTAPI

Dim NewPoint As POINTAPI

Dim NewPosition3D As Position3D
Dim RotatedPosition As Position3D
FillPosition3D RotatedPosition, Position.X + Size.Width / 2, Position.Y + Size.Height / 2, Position.Z + Size.ZDepth / 2

'Vector1
FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z
NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
Vertices(0) = NewPoint

'Vector2
FillPosition3D NewPosition3D, Position.X + Size.Width, Position.Y, Position.Z
NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
Vertices(1) = NewPoint

Polygon Me.hdc, Vertices(0), 2
End Sub

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If (KeyCode = vbKeyEscape) Then End
End Sub

World3D.Width = Me.Width
World3D.Height = Me.Height
World3D.ZDepth = 1000
Angletest.X = 0
Angletest.Y = 0
Angletest.Z = 0
Dim RecPosition As Position3D
FillPosition3D RecPosition, 10, 10, 20

Dim RecSize As Size3D
FillSize3D RecSize, 10, 10, 20
DrawRectangle RecPosition, RecSize, Angletest, World3D
End Sub

Private Sub Timer1_Timer()
Angletest.Y = Angletest.Y + 1
Me.Cls
Dim RecPosition As Position3D
FillPosition3D RecPosition, 10, 10, 20

Dim RecSize As Size3D
FillSize3D RecSize, 10, 10, 20

DrawRectangle RecPosition, RecSize, Angletest, World3D
Me.Refresh
End Sub```
but why the rotation isn't working correctly?

32. ## Re: 3D Math: how draw a 3D cube?

Because the code is very wrong.

Since you are using the Polygon API call, you want the form to be in scalemode= vbPixels.
Perhaps you've set the scalemode to pixels in the IDE, I don't know. Anyway, I added it to the Form_Load sub.

Next, since you want to use the scalemode's pixels to draw with, you need the ScaleWidth and ScaleHeight to know the size of the drawing area. Your code is using Width and Height, which is the size of the whole form in twips, not the size of the drawing area. So, that needs to be changed.

Also, perhaps you set the Timer interval in the IDE as well. Since I didn't, I just added it to the Form_Load as well.
Code:
```Private Sub Form_Load()
ScaleMode = vbPixels

World3D.Width = Me.ScaleWidth
World3D.Height = Me.ScaleHeight
World3D.ZDepth = 1000
Angletest.X = 0
Angletest.Y = 0
Angletest.Z = 0
Dim RecPosition As Position3D
FillPosition3D RecPosition, 10, 10, 20

Dim RecSize As Size3D
FillSize3D RecSize, 10, 10, 20
DrawRectangle RecPosition, RecSize, Angletest, World3D

Timer1.Interval = 100
End Sub```
Next, you're incrementing the Y rotation value by 1, so I assume that means the rotation values are in degrees.
But it looks like you try to clobber the values in your Rotate function with a call to ConvertRadiansToDegrees. But if the values are degrees, then you shouldn't be converting them to degrees, you should be converting them to Radians.
And if you want to use degrees in your code, then you shouldn't clobber the values with radians in the function.
Also, your conversion routine only changed the X value, and not the Y and Z values.

So, I added the correct function, and converted the degrees to Radians to a local instance of the Angle3D type (RotationInRads), and used that Type in place of Rotation in the Rotate Function so it doesn't clobber the version using degrees.
Code:
```Private Function ConvertDegreesToRadians(Rotation As Angle3D) As Angle3D

End Function

Private Function Rotate(Position As Position3D, Rotation As Angle3D, PositionRotated As Position3D) As Position3D
Dim ConvertedPosition As Position3D

ConvertedPosition.X = (Position.Z + PositionRotated.Z) * Sin(RotationInRads.Y) + (Position.X + PositionRotated.X) * Cos(RotationInRads.Y)
ConvertedPosition.Y = (Position.Y + PositionRotated.Y) * Cos(RotationInRads.X) - (Position.Z + PositionRotated.Z) * Sin(RotationInRads.X)
ConvertedPosition.Z = (Position.Y + PositionRotated.Y) * Sin(RotationInRads.X) + (Position.Z + PositionRotated.Z) * Cos(RotationInRads.X)
Rotate = ConvertedPosition
End Function```
I think that is all I changed. You are only drawing a short line, and the line is not offset to the center of the screen, so if you look in the upperleft corner of the window when you run (and assuming your timer is ticking), you should see a short horizontal line that circles around the Y axis, so it is off screen through part of the rotation.

33. ## Re: 3D Math: how draw a 3D cube?

i did all the fixes... but still not rotating
Code:
```Option Explicit

Private Type POINTAPI
X As Long
Y As Long
End Type

Private Declare Function Polygon Lib "gdi32" (ByVal hdc As Long, lpPoint As POINTAPI, ByVal nCount As Long) As Long

Private Type Position3D
X As Long
Y As Long
Z As Long
End Type

Private Type Angle3D
X As Double
Y As Double
Z As Double
End Type

Private Type Size3D
Width As Long
Height As Long
ZDepth As Long
End Type

Private Type Player
Position As Position3D
Angle As Angle3D
End Type

Private Const Pi As Double = 3.14159265358979
Dim World3D As Size3D
Dim Angletest As Angle3D

Private Sub LetPoint3dArray(la() As Position3D, ParamArray va() As Variant)
' No error trapping, so use with caution.
Dim i       As Long
Dim j       As Long
Dim k      As Long

k = (UBound(va) + 1) \ 3 - 1
ReDim la(k)
For i = 0& To k
la(i).X = va(j): j = j + 1
la(i).Y = va(j): j = j + 1
la(i).Z = va(j): j = j + 1
Next
End Sub

Private Sub FillPosition2D(Position As POINTAPI, X As Long, Y As Long)
Position.X = X
Position.Y = Y
End Sub

Private Sub FillPosition3D(Position As Position3D, X As Long, Y As Long, Z As Long)
Position.X = X
Position.Y = Y
Position.Z = Z
End Sub

Private Sub FillSize3D(Size As Size3D, Width As Long, Height As Long, ZDepth As Long)
Size.Width = Width
Size.Height = Height
Size.ZDepth = ZDepth
End Sub

Private Function ConvertPositon3DTo2D(Position As Position3D, World3DSize As Size3D) As POINTAPI
Dim ConvertedPosition As POINTAPI
Dim PosZZDepth As Integer

PosZZDepth = Position.Z + World3DSize.ZDepth

If (PosZZDepth = 0) Then PosZZDepth = 1 'avoiding division by zero

ConvertedPosition.X = Position.X * World3DSize.ZDepth / PosZZDepth
ConvertedPosition.Y = Position.Y * World3DSize.ZDepth / PosZZDepth
ConvertPositon3DTo2D = ConvertedPosition
End Function

Private Function ConvertDegreesToRadians(Rotation As Angle3D) As Angle3D

End Function

Private Function Rotate(Position As Position3D, Rotation As Angle3D, PositionRotated As Position3D) As Position3D
Dim ConvertedPosition As Position3D

ConvertedPosition.X = (Position.Z + PositionRotated.Z) * Sin(RotationInRads.Y) + (Position.X + PositionRotated.X) * Cos(RotationInRads.Y)
ConvertedPosition.Y = (Position.Y + PositionRotated.Y) * Cos(RotationInRads.X) - (Position.Z + PositionRotated.Z) * Sin(RotationInRads.X)
ConvertedPosition.Z = (Position.Y + PositionRotated.Y) * Sin(RotationInRads.X) + (Position.Z + PositionRotated.Z) * Cos(RotationInRads.X)
Rotate = ConvertedPosition
End Function

Private Sub DrawRectangle(Position As Position3D, Size As Size3D, Rotation As Angle3D, WorldSize As Size3D)
Dim Vertices(5) As POINTAPI

Dim NewPoint As POINTAPI

Dim NewPosition3D As Position3D
Dim RotatedPosition As Position3D
'FillPosition3D RotatedPosition, Position.X + Size.Width / 2, Position.Y + Size.Height / 2, Position.Z + Size.ZDepth / 2

'Vector1
FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z
NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
Vertices(0) = NewPoint

'Vector2
FillPosition3D NewPosition3D, Position.X + Size.Width, Position.Y, Position.Z
NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
Vertices(1) = NewPoint

'Vector3
FillPosition3D NewPosition3D, Position.X + Size.Width, Position.Y + Size.Height, Position.Z
NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
Vertices(2) = NewPoint

'Vector4
FillPosition3D NewPosition3D, Position.X, Position.Y + Size.Height, Position.Z
NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
Vertices(3) = NewPoint

'Vector5
FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z
NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
Vertices(4) = NewPoint

Polygon Me.hdc, Vertices(0), 5
End Sub

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If (KeyCode = vbKeyEscape) Then End
End Sub

World3D.Width = Me.ScaleWidth
World3D.Height = Me.ScaleHeight
World3D.ZDepth = 1000
Dim RecPosition As Position3D
FillPosition3D RecPosition, 10, 10, 0

Dim RecSize As Size3D
FillSize3D RecSize, 10, 10, 0
DrawRectangle RecPosition, RecSize, Angletest, World3D
End Sub

Private Sub HScroll1_Change()
Me.Cls
Angletest.X = HScroll1.Value
Me.Caption = CStr(HScroll1.Value)
Dim RecPosition As Position3D
FillPosition3D RecPosition, 10, 10, 0

Dim RecSize As Size3D
FillSize3D RecSize, 10, 10, 0
DrawRectangle RecPosition, RecSize, Angletest, World3D
Me.Refresh
End Sub```

34. ## Re: 3D Math: how draw a 3D cube?

Well, I'm on another machine now, without access to the previous project, so I guess I'll try your latest code from scratch on this machine.
I see you've gone with a scrollbar instead of a timer, the better to control and look at specific angles.
Also, you're now rotating around the X axis instead of the Y axis, so the rotation will take the rectangle up and outside the form for a good portion of its rotation.

Perhaps the problem is you don't have AutoRedraw set to True.
When using an API call to do drawing, you either have AutoRedraw set to False, so the API call will draw on the form you see (i.e. in the screen context of the form), so you don't call Refresh because Refresh will wipe out the drawing done on the screen in preparation for you to "Refresh" the drawing from code in the Paint Event.

Or you set AutoRedraw to True, in which case you're drawing is done in a memory backbuffer, and VB will draw in that memory buffer and update the screen from that buffer automatically, so it does not generate a Paint Event.
But, if you only draw using API calls, VB is not aware of that drawing, so won't update the screen automatically, so you have to call Refresh when you're done drawing.

So, to fix your issue, either set AutoRedraw to True, and the code you have should work.
Or, leave AutoRedraw False, and don't call Me.Refresh, because the API will be drawing directly on the screen area of the form, so you'll see it draw.

Since I started a new project, I don't know how you have the properties set in the IDE, so I just added setting the Scalemode to Pixels and setting AutoRedraw to True in the Form_Load sub, and I see the small little rectangle rotating around the X axis.

I'll post the full code I tested with, just to make sure there isn't any other thing I changed.
That reminds me, I did change one other thing. I like to see what happens when you scroll the scrollbar with the thumb, which doesn't trigger the "Change" event until you release the thumb. So, you need to respond to the Scroll Event also.
Rather than duplicate the code, I just put the scroll Change code in another sub (HScrollChanged), and then call HScrollChanged from the HScroll1_Change and HScroll1_Scroll event subs.
Code:
```Option Explicit

Private Type POINTAPI
X As Long
Y As Long
End Type

Private Declare Function Polygon Lib "gdi32" (ByVal hdc As Long, lpPoint As POINTAPI, ByVal nCount As Long) As Long

Private Type Position3D
X As Long
Y As Long
Z As Long
End Type

Private Type Angle3D
X As Double
Y As Double
Z As Double
End Type

Private Type Size3D
Width As Long
Height As Long
ZDepth As Long
End Type

Private Type Player
Position As Position3D
Angle As Angle3D
End Type

Private Const Pi As Double = 3.14159265358979
Dim World3D As Size3D
Dim Angletest As Angle3D

Private Sub LetPoint3dArray(la() As Position3D, ParamArray va() As Variant)
' No error trapping, so use with caution.
Dim i       As Long
Dim j       As Long
Dim k      As Long

k = (UBound(va) + 1) \ 3 - 1
ReDim la(k)
For i = 0& To k
la(i).X = va(j): j = j + 1
la(i).Y = va(j): j = j + 1
la(i).Z = va(j): j = j + 1
Next
End Sub

Private Sub FillPosition2D(Position As POINTAPI, X As Long, Y As Long)
Position.X = X
Position.Y = Y
End Sub

Private Sub FillPosition3D(Position As Position3D, X As Long, Y As Long, Z As Long)
Position.X = X
Position.Y = Y
Position.Z = Z
End Sub

Private Sub FillSize3D(Size As Size3D, Width As Long, Height As Long, ZDepth As Long)
Size.Width = Width
Size.Height = Height
Size.ZDepth = ZDepth
End Sub

Private Function ConvertPositon3DTo2D(Position As Position3D, World3DSize As Size3D) As POINTAPI
Dim ConvertedPosition As POINTAPI
Dim PosZZDepth As Integer

PosZZDepth = Position.Z + World3DSize.ZDepth

If (PosZZDepth = 0) Then PosZZDepth = 1 'avoiding division by zero

ConvertedPosition.X = Position.X * World3DSize.ZDepth / PosZZDepth
ConvertedPosition.Y = Position.Y * World3DSize.ZDepth / PosZZDepth
ConvertPositon3DTo2D = ConvertedPosition
End Function

Private Function ConvertDegreesToRadians(Rotation As Angle3D) As Angle3D

End Function

Private Function Rotate(Position As Position3D, Rotation As Angle3D, PositionRotated As Position3D) As Position3D
Dim ConvertedPosition As Position3D

ConvertedPosition.X = (Position.Z + PositionRotated.Z) * Sin(RotationInRads.Y) + (Position.X + PositionRotated.X) * Cos(RotationInRads.Y)
ConvertedPosition.Y = (Position.Y + PositionRotated.Y) * Cos(RotationInRads.X) - (Position.Z + PositionRotated.Z) * Sin(RotationInRads.X)
ConvertedPosition.Z = (Position.Y + PositionRotated.Y) * Sin(RotationInRads.X) + (Position.Z + PositionRotated.Z) * Cos(RotationInRads.X)
Rotate = ConvertedPosition
End Function

Private Sub DrawRectangle(Position As Position3D, Size As Size3D, Rotation As Angle3D, WorldSize As Size3D)
Dim Vertices(5) As POINTAPI

Dim NewPoint As POINTAPI

Dim NewPosition3D As Position3D
Dim RotatedPosition As Position3D
'FillPosition3D RotatedPosition, Position.X + Size.Width / 2, Position.Y + Size.Height / 2, Position.Z + Size.ZDepth / 2

'Vector1
FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z
NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
Vertices(0) = NewPoint

'Vector2
FillPosition3D NewPosition3D, Position.X + Size.Width, Position.Y, Position.Z
NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
Vertices(1) = NewPoint

'Vector3
FillPosition3D NewPosition3D, Position.X + Size.Width, Position.Y + Size.Height, Position.Z
NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
Vertices(2) = NewPoint

'Vector4
FillPosition3D NewPosition3D, Position.X, Position.Y + Size.Height, Position.Z
NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
Vertices(3) = NewPoint

'Vector5
FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z
NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
Vertices(4) = NewPoint

Polygon Me.hdc, Vertices(0), 5
End Sub

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If (KeyCode = vbKeyEscape) Then End
End Sub

ScaleMode = vbPixels
AutoRedraw = True

World3D.Width = Me.ScaleWidth
World3D.Height = Me.ScaleHeight
World3D.ZDepth = 1000
Dim RecPosition As Position3D
FillPosition3D RecPosition, 10, 10, 0

Dim RecSize As Size3D
FillSize3D RecSize, 10, 10, 0
DrawRectangle RecPosition, RecSize, Angletest, World3D

End Sub

Private Sub HScroll1_Change()
HScrollChanged
End Sub
Private Sub HScroll1_Scroll()
HScrollChanged
End Sub

Sub HScrollChanged()
Me.Cls
Angletest.X = HScroll1.Value
Me.Caption = CStr(HScroll1.Value)
Dim RecPosition As Position3D
FillPosition3D RecPosition, 10, 10, 0

Dim RecSize As Size3D
FillSize3D RecSize, 10, 10, 0
DrawRectangle RecPosition, RecSize, Angletest, World3D
Me.Refresh

End Sub```
p.s. After posting, I modified the application to add another scrollbar to change the Y rotation. I then saw a lot of debug prints because of the Debug.Print added to the Rotate function from several posts back. That didn't need to be in there. It was added when I was checking the values of the Angle, which is why I noticed you were converting degrees to "degrees", so the value was jumping from 0 to 57.xxx to numbers quickly in the thousands before. So, I've removed that debug.Print statement from the above code as well.

p.p.s.
While, the above appears to be rotating around the X axis when you change the X angle, and around the Y axis when you change the Y angle, I'm not sure that the rotation calculations are actually working properly or not.
You're mixing the angles in the equations, so that you're using angles for two different axis in the same calculation for the transformation of a point.

I don't know if those combinations of angles and positions done simultaneously in one calculation is a valid combination of two calculations when are normally done separately.

I added a third scrollbar and changing the Z angle which had no effect that I could see on the drawing.

Normally, to rotate a 3d point involves three rotations of X,Y,Z, accounting for the 3 dimensions. You have only one rotation of X,Y,Z, with X and Y being a mixture of two rotations, i.e rotating X around Y and Y around X and nothing rotating around Z.

Perhaps it can work out, if you're moving through a world where you can pitch up and down, and yaw left or right, but you will never roll. I can't tell. I not sure of how the Position inputs and PositionRotated inputs relate to your world and will be manipulated in your world.

35. ## Re: 3D Math: how draw a 3D cube?

testing what you changed, i see 2 problems:
1 - seems that the rotation point isn't correct:
Code:
`FillPosition3D RotatedPosition, Position.X + Size.Width / 2, Position.Y + Size.Height / 2, Position.Z + Size.ZDepth / 2`
the 'Size' it's the rectangle size.
Code:
```Private Function Rotate(Position As Position3D, Rotation As Angle3D, PositionRotated As Position3D) As Position3D
Dim ConvertedPosition As Position3D

ConvertedPosition.X = (Position.Z + PositionRotated.Z) * Sin(RotationInRads.Y) + (Position.X + PositionRotated.X) * Cos(RotationInRads.Y)
ConvertedPosition.Y = (Position.Y + PositionRotated.Y) * Cos(RotationInRads.X) - (Position.Z + PositionRotated.Z) * Sin(RotationInRads.X)
ConvertedPosition.Z = (Position.Y + PositionRotated.Y) * Sin(RotationInRads.X) + (Position.Z + PositionRotated.Z) * Cos(RotationInRads.X)
Rotate = ConvertedPosition
End Function```
the PositionRotated is right calculated for the rotation center?
2 - the Y angle have the same effect

36. ## Re: 3D Math: how draw a 3D cube?

I guess that is related to the last statement in my post. I didn't understand why you had a Position and PositionRotated structure in your rotation input. You're not doing much of anything in a standard way.

The rotation center is always going to be around (0,0,0). That is the way it works.
Your camera position is going to be somewhere, and what you do is convert the world coordinates into camera coordinates.
That puts the world coordinates relative to the camera, so essentially the camera is at (0,0,0) and the world rotates around it as it rotates.

Where you draw the center of the field of view of the camera on the screen is another matter. In your last code, you don't change where you draw, so the rotation will be around the (0,0) 2D coordinate, which is the upper left corner of the window.
The rectangle appears, to me, to be doing what it is suppose to do, based on the code, but perhaps isn't doing what you meant it to do.
When you change the X angle, the rectangle appears to rotate around the X axis, so moves up and off the window because the X axis is at the top of the window.

Likewise, the Y axis is along the left edge of the window, so the rectangle rotates out of the window whenever the Y values end up on the negative side of the axis.

I would like you to try to read these two articles to see if they make sense to you.
http://www.petesqbsite.com/sections/...qbcm/3-3d.html
http://www.petesqbsite.com/sections/...qbcm/4-3d.html

37. ## Re: 3D Math: how draw a 3D cube?

i'm sorry passel, but the rotated rectangle isn't from the center of rectangle?
i mean that i need rotate the rectangle in same position

38. ## Re: 3D Math: how draw a 3D cube?

If you want to rotate an object around its center, then for the rotation, (0,0,0) needs to be the coordinates of the center of the object. Rotation is always around (0,0,0).

So, the X,Y,Z value need to be relative to the center of the object for the rotation.
So, rather than end up with X = 20 and Y = 20 and Z = 40 or some other set of relatively large values (compared to the rectangle's size), if the rectangle is 10 pixels wide, then X should be in the range of -5 to 5, likewise with Y and Z.

The points you want to rotate, need to be translated to be relative to the (0,0,0) point of rotation, rotated, then translated back to their world coordinates.

39. ## Re: 3D Math: how draw a 3D cube?

that's why i did PositionX + Width/2.. and these is correct.. that's why i did:
Code:
```Private Function Rotate(Position As Position3D, Rotation As Angle3D, PositionRotated As Position3D) As Position3D
Dim ConvertedPosition As Position3D

ConvertedPosition.X = (Position.Z + PositionRotated.Z) * Sin(RotationInRads.Y) + (Position.X + PositionRotated.X) * Cos(RotationInRads.Y)
ConvertedPosition.Y = (Position.Y + PositionRotated.Y) * Cos(RotationInRads.X) - (Position.Z + PositionRotated.Z) * Sin(RotationInRads.X)
ConvertedPosition.Z = (Position.Y + PositionRotated.Y) * Sin(RotationInRads.X) + (Position.Z + PositionRotated.Z) * Cos(RotationInRads.X)
Rotate = ConvertedPosition
End Function```
Code:
`FillPosition3D RotatedPosition, Size.Width / 2, Size.Height / 2, Size.ZDepth / 2`
the 'Size' is the rectangle size... but i don't understand why the center is incorrect

40. ## Re: 3D Math: how draw a 3D cube?

Because you're not making the point relative to the center of the rectangle. You are defining the corners in world coordinate relative to where the rectangle is located.

The points of the object to be rotated, relative to the center of the object will never change (assuming a fixed shaped object, i.e. no joints or moving parts).

So, the X to be rotated wouldn't be Position.X + Width/2.
It would be +/- Width/2, and it will always be Width/2.
The relation of the point to its center never changes.
After you rotated the point around the object center, you would add Position.X to place it to where it is in 3d space, but you don't want to rotate the point in space.

The way you're doing it is like a satellite orbiting the earth. The Position.X rotates around the earth as the satellite moves, so you rotate it around the earth center.
But if you want to spin the satellite, you don't spin it around the earth, you spin it around the center of itself.

If you just define the model of the cube with points relative to 0,0,0 being at its center, then you can rotate the object simply using those coordinates, they will never change. You then add its position to those rotated coordinates to place it where it is in space.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•