Page 2 of 4 FirstFirst 1234 LastLast
Results 41 to 80 of 125

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

  1. #41
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,379

    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.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  2. #42

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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.
    VB6 2D Sprite control

    To live is difficult, but we do it.

  3. #43
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,379

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

    Quote Originally Posted by joaquim View Post
    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.
    Last edited by passel; Apr 9th, 2020 at 01:35 PM.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  4. #44
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,379

    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.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  5. #45

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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
    VB6 2D Sprite control

    To live is difficult, but we do it.

  6. #46
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,379

    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.
    Last edited by passel; Apr 11th, 2020 at 11:09 PM.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  7. #47

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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
    VB6 2D Sprite control

    To live is difficult, but we do it.

  8. #48

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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)
    VB6 2D Sprite control

    To live is difficult, but we do it.

  9. #49

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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...
    i can add an 'if' here, but what i can add instead 'FloorZ + MeDistance'(for exemple)?
    VB6 2D Sprite control

    To live is difficult, but we do it.

  10. #50
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,379

    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.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  11. #51

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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
    VB6 2D Sprite control

    To live is difficult, but we do it.

  12. #52
    Junior Member
    Join Date
    Jun 2018
    Location
    New Orleans, Austin, Santa Monica
    Posts
    24

    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
    Attached Files Attached Files

  13. #53

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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
    VB6 2D Sprite control

    To live is difficult, but we do it.

  14. #54
    Lively Member Mikle's Avatar
    Join Date
    Oct 2009
    Location
    Tuapse, Russia
    Posts
    111

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

    Deleted double of post

  15. #55
    Lively Member Mikle's Avatar
    Join Date
    Oct 2009
    Location
    Tuapse, Russia
    Posts
    111

    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. #56

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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
    VB6 2D Sprite control

    To live is difficult, but we do it.

  17. #57
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,379

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

    Quote Originally Posted by joaquim View Post
    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.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  18. #58

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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
    VB6 2D Sprite control

    To live is difficult, but we do it.

  19. #59
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,379

    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.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  20. #60

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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)
    VB6 2D Sprite control

    To live is difficult, but we do it.

  21. #61
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,379

    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));
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  22. #62

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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
    Last edited by joaquim; Apr 18th, 2020 at 03:42 PM.
    VB6 2D Sprite control

    To live is difficult, but we do it.

  23. #63
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,379

    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.
    Last edited by passel; Apr 20th, 2020 at 09:04 AM.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  24. #64

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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..
    VB6 2D Sprite control

    To live is difficult, but we do it.

  25. #65
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,379

    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.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  26. #66

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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
    i need ask 2 things:
    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
    VB6 2D Sprite control

    To live is difficult, but we do it.

  27. #67
    Lively Member Mikle's Avatar
    Join Date
    Oct 2009
    Location
    Tuapse, Russia
    Posts
    111

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

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

  28. #68

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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
    VB6 2D Sprite control

    To live is difficult, but we do it.

  29. #69
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,379

    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.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  30. #70
    Lively Member Mikle's Avatar
    Join Date
    Oct 2009
    Location
    Tuapse, Russia
    Posts
    111

    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. #71

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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
        ConvertRadiansToDegrees = Rotation
    End Function
    
    Private Function Rotate(Position As Position3D, Rotation As Angle3D, PositionRotated As Position3D) As Position3D
        Dim ConvertedPosition As Position3D
        Rotation = ConvertRadiansToDegrees(Rotation)
        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
    
    
    Private Sub Form_Load()
        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?
    VB6 2D Sprite control

    To live is difficult, but we do it.

  32. #72
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,379

    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
        Dim deg2Rad As Double
        deg2Rad = Pi / 180
        
        ConvertDegreesToRadians.X = Rotation.X * deg2Rad
        ConvertDegreesToRadians.Y = Rotation.Y * deg2Rad
        ConvertDegreesToRadians.Z = Rotation.Z * deg2Rad
      '  ConvertRadiansToDegrees = Rotation
    End Function
    
    Private Function Rotate(Position As Position3D, Rotation As Angle3D, PositionRotated As Position3D) As Position3D
        Dim ConvertedPosition As Position3D
        Dim RotationInRads As Angle3D
        
        RotationInRads = ConvertDegreesToRadians(Rotation)
        Debug.Print RotationInRads.Y
        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.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  33. #73

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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
        Dim deg2Rad As Double
        deg2Rad = Pi / 180
        
        ConvertDegreesToRadians.X = Rotation.X * deg2Rad
        ConvertDegreesToRadians.Y = Rotation.Y * deg2Rad
        ConvertDegreesToRadians.Z = Rotation.Z * deg2Rad
      '  ConvertRadiansToDegrees = Rotation
    End Function
    
    Private Function Rotate(Position As Position3D, Rotation As Angle3D, PositionRotated As Position3D) As Position3D
        Dim ConvertedPosition As Position3D
        Dim RotationInRads As Angle3D
        
        RotationInRads = ConvertDegreesToRadians(Rotation)
        Debug.Print RotationInRads.Y
        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
    
    
    Private Sub Form_Load()
        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
    VB6 2D Sprite control

    To live is difficult, but we do it.

  34. #74
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,379

    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
        Dim deg2Rad As Double
        deg2Rad = Pi / 180
        
        ConvertDegreesToRadians.X = Rotation.X * deg2Rad
        ConvertDegreesToRadians.Y = Rotation.Y * deg2Rad
        ConvertDegreesToRadians.Z = Rotation.Z * deg2Rad
      '  ConvertRadiansToDegrees = Rotation
    End Function
    
    Private Function Rotate(Position As Position3D, Rotation As Angle3D, PositionRotated As Position3D) As Position3D
        Dim ConvertedPosition As Position3D
        Dim RotationInRads As Angle3D
        
        RotationInRads = ConvertDegreesToRadians(Rotation)
        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
    
    Private Sub Form_Load()
        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.
    Last edited by passel; Apr 23rd, 2020 at 10:57 PM.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  35. #75

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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
        Dim RotationInRads As Angle3D
        
        RotationInRads = ConvertDegreesToRadians(Rotation)
        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
    VB6 2D Sprite control

    To live is difficult, but we do it.

  36. #76
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,379

    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
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  37. #77

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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
    VB6 2D Sprite control

    To live is difficult, but we do it.

  38. #78
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,379

    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.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  39. #79

    Thread Starter
    PowerPoster joaquim's Avatar
    Join Date
    Apr 2007
    Posts
    3,535

    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
        Dim RotationInRads As Angle3D
        
        RotationInRads = ConvertDegreesToRadians(Rotation)
        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
    VB6 2D Sprite control

    To live is difficult, but we do it.

  40. #80
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,379

    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.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

Page 2 of 4 FirstFirst 1234 LastLast

Posting Permissions

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



Click Here to Expand Forum to Full Width