Page 1 of 4 1234 LastLast
Results 1 to 40 of 125

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

  1. #1

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

    3D Math: how draw a 3D cube?

    ok.. i'm trying learn much more about 3D... but i don't find a nice tutorial about it
    for start i need understand how can i draw: X,Y,Z to X' and Y'... yes the screen don't have the Z coordinate.
    can anyone explain to me or just give me a tutorial for i learn it?
    Last edited by joaquim; Mar 30th, 2020 at 09:36 AM.
    VB6 2D Sprite control

    To live is difficult, but we do it.

  2. #2
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

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

    If you do a search like "3d coordinate to screen", are you saying the first few hits are not "nice" enough tutorials or explanations for what you need?

    I would think that if one of those is not sufficient, I'm not sure what you might be looking for, and I presume I certainly wouldn't provide any better explanation.
    "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

  3. #3

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

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

    thanks i wasn't using the right words.
    before i start more: let me ask you... the screen uses X and Y.... so how can i convert 3D(X,Y,Z) to 2D(X,Y)?
    for i start something
    VB6 2D Sprite control

    To live is difficult, but we do it.

  4. #4

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

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

    or is an 'illusion' and we just draw the objects by order(1 after another)?
    VB6 2D Sprite control

    To live is difficult, but we do it.

  5. #5
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

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

    Well, that is what the first link that was presented when I did the search was explaining.
    Of course there are a lot of illustrations and math discussion involved in the subject, so it is easy to be overwhelmed. I don't think I can make it any easier.

    Many years ago, I was a bit interested in investigating some simple 3D projections myself, so the examples I was looking at at the time were written in plain old GWBasic or QBasic, and would draw simple wireframe versions of a collection of points, and you could spin those points around the three axis.

    I later reused those same calculations in a VB3 program to draw a Rubic's Cube type cube, and was experimenting with rotating some of the layers to possible allow a full rotational model of all the layers allowing replication of rotating the cube as a whole and the various layers to emulate the manipulation of the cube as you would a Rubic's cube, but I lost interest in that before getting very far.
    I added other things to the program to test things like rotating a sphere of dots in addition to the points that made up the junctions of the cube pieces. Also, changing the color of the dot with the resulting Z value so that the dot faded as it was further from the eyepoint.

    I added various checkboxes to enable or disable various portions of the drawing process, so you could see various things without the others, e.g. the cube by itself without the cloud of dots around it, or the cloud of dots without the cube, or drawing a circle inside the cloud of dots, so that it looked like dots were passing in front and behind the circle that was in the center of the sphere.

    It was just a mishmash of various experimental pieces of code, so there is a lot of commented out code in it, as well as unlabeled buttons and other GUI elements.
    The functions that rotate the points to calculate the new X,Y and Z points from the original X,Y and Z points after rotation, are essentially unrolled versions of what happens when you run the points through a matrix transformation. The preferred method would be to use a Matrix because a number of rotations or other transforms could be applied to the matrix, and then the final matrix would be used to transform the points once, moving them from their original definition, to their new position in one shot since the matrix would be a combination of all the transforms needed to go from original position to current position.

    Once you have the points all transformed, then the rendering needs to convert the resulting 3D points into 2D points for display, and that is projection part of the process. And there is more than just determining where the point on the screen is. There is the matter of determining which points should be drawn and which should not, and in the case of surfaces, which should be drawn and which shouldn't. And with a better drawing algorithm, depending on how the surfaces may overlap because of the Z depth of the surface changing across the polygon being filled, the existing polygon should be broken into smaller polygons at the point of overlap.

    The code I used in my tests were quite simplistic compared to what should really be done to draw things correctly.
    I ported the VB3 code to VB6 long ago, and I have a several versions of it hanging around on various computers.
    I guess I can post one of the VB6 versions, as is, and you can play around with it. I can't really afford the time to get back into what it does and how it does it, but maybe you can pull something from it.
    Attached Files Attached Files
    "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

  6. #6

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

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

    please see these 2 lines that draws 2 same images(front and left):
    Code:
    readimagefile("C:\\New\\bkgBox.bmp",PosX,PosY,PosX+bmp.Width,PosY+bmp.Height);
            readimagefile("C:\\New\\bkgBox.bmp",PosX-Z,PosY,PosX,PosY+bmp.Height);
    draw result: https://imgur.com/2ipUJRY
    the front image don't use the Z, but the left use it.... is these the right way?
    Last edited by joaquim; Mar 29th, 2020 at 11:51 AM. Reason: correct some text
    VB6 2D Sprite control

    To live is difficult, but we do it.

  7. #7
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

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

    Not really.
    To draw the left side properly, two things would need to happen.
    The first is Y scale needs to have fore-shortening, which means you have less Y scale the closer the object gets to you.
    So, the Y scale should increase as the left side goes further away from you, which means the bitmap should shrink as it goes away from you.

    If you're looking at the box with the front face being perpendicular to your view, and you're viewing the box with the eye level centered on the front face, then the left side should end up being a trapazoid shape.
    Since you don't have fore-shortening, then the left side looks like it is increasing in size, if your mind can accept that the left side of the image is further back, then the fact that it didn't shrink in size on the screen is interpreted as increasing in size in 3D.

    The second point, is that while you squeeze the texture into a narrower space, this is done linearly across the narrow space, where in "reality", the squeezing should be less closer to the eye and more as the texture gets further from the eye.

    To do this properly, you either should use a 3D library that can apply a texture to a surfaces with perspective, or if you want to do it yourself, you will have to do a lot more work.

    The regular drawing capabilities of VB6 (GDI) and .Net (GDI+) don't support doing 3D texture mapping with perspective. .Net does support some perspective drawing in a limited fashion, but not with textures.

    I did do some other experiments with mapping a texture to a trapazoid in the limited case where the eyepoint was always perpendicular to the vertical, i.e. think of running around in a Maze game, where you don't look up or down, and you are always moving around the maze with the walls perpendicular to your view.

    What you have to do for the side walls in that situation is determine for each vertical line of pixels in the side wall, which vertical line of pixels from the texture maps to it, and then squeeze that line of pixels and draw it vertically where it should be drawn.

    So instead of one transfer of the texture to a shape, you have to do a series of transfers of vertical slices of the texture to match the perspective at that pixel location. It is a lot of work if you want to do the primitives involved yourself.

    So, the question is what is your desired purpose for the post? Are you interested in the math involved, which is explained in the various posts you can find by searching. Are you trying to manually draw some 3D objects using the available drawing primitives within VB6 or .Net?

    You can do an isometric (not perspective) type of 3D using plgblt type operations in either VB6 or VB.Net, but isometric does suffer from not fore-shortening with depth, so generally only looks relatively good when looking down at perhaps a 30 degree angle, which a lot of simple games depend on. This is sometimes referred to as 2.5D as it is a look that is between 2D and true 3D.

    There is no simple answer or trick if you want to do this yourself. There are probably a number of different libraries to make this type of thing easier, but even then it is still a fair amount of work to become competent with those tools.
    "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

  8. #8

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

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

    i want draw the image\cube using Geometric Math for learn it. i know that theres several libraries for it... but i want to learn draw the cube, camera and the move.
    the fog and the atmosphere\effects isn't the goal now
    VB6 2D Sprite control

    To live is difficult, but we do it.

  9. #9
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

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

    Have you looked at this post.
    I haven't looked at it in detail, and it won't help with texturing the cube because that is a whole other level of complication, but it will probably give you another look at the math involved in transforming points from 3D space to a projection on a 2D plane.
    "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

  10. #10

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

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

    that is for rotate the cube... but lets go back a little...
    i'm trying work with scale... from i have seen i must multiply the positions and sizes by scale:
    Code:
    readimagefile("C:\\New\\bkgBox.bmp",PosX*Scale,PosY*Scale,(PosX+bmp.Width)*Scale,(PosY+bmp.Height)*Scale);
            readimagefile("C:\\New\\bkgBox.bmp",(PosX-Z)*Scale,PosY*Scale,PosX*Scale,(PosY+bmp.Height)*Scale);
    but i'm doing something wrong, because sometimes the image isn't showed.
    can you tell me what i'm doing wrong?
    Last edited by joaquim; Mar 30th, 2020 at 09:53 AM.
    VB6 2D Sprite control

    To live is difficult, but we do it.

  11. #11
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

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

    I certainly can't tell what you're doing wrong.
    If it works sometime, and not other times, then the basic function call is likely syntactically correct and the problem is with the parameters passed to the function.
    If the only thing you are changing is scale, then the value for Scale must be incorrect in some situations.
    That is something you will have to test.

    I am not going to try to create a test project to test anything, that is for sure.
    I don't have your bitmap, and from the little bit of code posted, I can't tell if the language being used is C#, C++ or something else.
    I can guess that the readimagefile function may be from the old Borland port of the BGI library to Windows, but I don't even know that for sure.

    If I wanted to test this, then I probably would use four variables to hold the X, Y , Width and Height values and set them before the function call.
    That way you can examine then or print out their values as you change scale, to see if the values make sense for passing to the function.
    At the very least, you can see at what limits of scale the function manages to draw something. I'm pretty sure if the width or height end up being less than a pixel in size, probably nothing ends up getting drawn.

    You could easily verify that the function is working on some basic standard cases, e.g. like:
    a Scale of 1.0 should create an image the size of the original
    2.0 should be twice the size
    0.5 should be half the size
    0.25 should be 1/4 the size.

    If you declared Size as an Integer, then that obviously would be a problem.

    I don't really see how this will help with drawing a cube. The function readimagefile can resize the image, but it will always be a resized rectangle, and to draw a cube, most of the sides would not be rectangles on the screen.
    "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

  12. #12

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

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

    thanks for that.
    yes when the scale is 1, it will give the original size
    Code:
    double Scale=1.0;
    else if( GetKeyState('S') <0)
            {
    
                if(Scale<=0.1)
                    Scale =2.0;
                else
                    Scale-=0.1;
            }
            else if( GetKeyState('W')<0)
            {
                Scale+=0.1;
                if(Scale>=2.0) Scale =1.0;
            }
    until here fine.
    but i need another correction: the scale affect the position too?
    VB6 2D Sprite control

    To live is difficult, but we do it.

  13. #13

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

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

    "I don't really see how this will help with drawing a cube. The function readimagefile can resize the image, but it will always be a resized rectangle, and to draw a cube, most of the sides would not be rectangles on the screen."
    that you have right!!!!
    on win32 theres 1 function that can draw an image on that way?
    VB6 2D Sprite control

    To live is difficult, but we do it.

  14. #14
    Fanatic Member
    Join Date
    Feb 2019
    Posts
    706

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

    First, you are better of using something like DirectX or another game engine rather than reinventing the wheel, because they do other tasks that you might find that you get to do latter. With that in mind, here is a quick simple formula I used in the past:

    x2D = (x * L) / (z + L)
    y2D = (y * L) / (z + L)

    L is a constant representing the distance from the user to the screen in pixels, typically set to 1024 or 2048, which makes the above formula very fast as VB6 uses shifts when you use a number that is multiple of the power of two.

    Here is a function that return x, y when supplied with xyz. I have used Long data type, but if you have trouble, use Double:

    VB Code:
    1. Public Type My2DPoint
    2.     x As Long
    3.     y As Long
    4. End Type
    5.  
    6. Public Function To2D(ByVal x As Long, ByVal y As Long, ByVal z As Long) As My2DPoint
    7.     ' L = Distance from screen to the user in pixels.
    8.     '       It's not necessary to turn this into a variable, just use a typical value.
    9.     Const L As Long = 2048 ' User is at 2048 pixels away from monitor
    10.  
    11.     Dim p2d As My2DPoint
    12.     Dim temp As Long
    13.  
    14.     temp = z + L
    15.     p2d.x = x * L / temp
    16.     p2d.y = y * L / temp
    17.  
    18.     To2D = p2d
    19. End Function

  15. #15

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

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

    thank you so much for the formula.. thank you...
    now i can work more easy...
    thinking on 2D to 3D or Z is more like:
    Z=(x*L-Lx2D)/x2D
    right?

    and yes the passel has right some objects, even the cube, isn't all faces rectangles but polygons.
    can i use brushes on polygons?
    VB6 2D Sprite control

    To live is difficult, but we do it.

  16. #16
    Fanatic Member
    Join Date
    Feb 2019
    Posts
    706

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

    Quote Originally Posted by joaquim View Post
    thank you so much for the formula.. thank you...
    now i can work more easy...
    thinking on 2D to 3D or Z is more like:
    Z=(x*L-Lx2D)/x2D
    right?
    Correct, but you are missing "*":

    z = (x*L-L*x2D) / x2D

    Or:

    z = L * (x-x2D) / x2D

    Quote Originally Posted by joaquim View Post
    can i use brushes on polygons?
    You have to do that on your own, and I am sure that you will have many other questions in the future as you move forward. A game engine saves you development time. These simple solutions are for limited use case scenarios.

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

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

    Quote Originally Posted by joaquim View Post
    ...
    but i need another correction: the scale affect the position too?
    If you don't want to scale the whole view, just the object, then don't multiply the X,Y position by the Scale, just the size, i.e. width and height.

    Quote Originally Posted by joaquim View Post
    "I don't really see how this will help with drawing a cube. The function readimagefile can resize the image, but it will always be a resized rectangle, and to draw a cube, most of the sides would not be rectangles on the screen."
    ...
    on win32 theres 1 function that can draw an image on that way?
    Quote Originally Posted by joaquim View Post
    ..., even the cube, isn't all faces rectangles but polygons.
    can i use brushes on polygons?
    No. There is nothing in the windows (GDI or GDI+) APIs that would draw a perspective image using a texture brush, or to fill a polygon with such a brush that would look correct.
    You didn't mention what language you're using, or what libraries you're using to draw with.

    On the surface, it looks like you may be using C++ and the "Ported to Windows" version of the Borland Graphics Interface. I don't think that WinBGIm even supports texture brushes, or brushes in general, if that is what you are using. WinBGIm is pretty primitive stuff.

    If you were using GDI+, then you could have a texture brush, and you could transpose the brush to rotate, skew, and translate the brush when it is used to fill a polygon, but that would never look right with polygons that represent a 3D polygon projected to a 2D surface. It would always be a parallelogram shaped pattern filling an arbitrary shaped figure.

    The best you could do with a texturebrush is, as I mentioned before, doing an Isometric type drawing, where the shape to be filled would always be a parallelogram so a parallelogram shaped texture would fit the shape more realistically. The texture would still not be variably distributed along the perceived Z-Axis as would be needed for "true" 3D texture mapping. It would be linearly distributed across the perceived Z-Axis. This would be along the same lines as what could be done using GDI with the parallel blit (plgblt) function.

    For an example of what this isometric 3D texture looks like, I played around with plgblt in a VB6 project at least 12 years ago (found a zip file with the project in it from 2008).
    Again, it is just code used to experiment with plgblt and textures, so is a mishmash of code and commented out code.

    I went ahead and made a couple of changes to it today, so that it starts up with the plgblt checkbox enabled, (used flat color fills if that option is not selected), and it starts with the view already rotated and tilted so that you see three sides of the visible blocks when you start up the program.
    I also added a Sleep API declaration and do a "Sleep 1" in the loop so the program isn't using 100% of the core it runs on. On my machine, with the Sleep 1 in place, the executable uses 0% CPU when you aren't moving, and generally less than 8%, when the scene is in motion.

    The Orange Circle, which would represent the object moving through the space, really never moves in the window. Everything else in the environment moves to show relative motion.

    There are various controls that were part of the experiment, but to start with, you really only need to know three things to see the basic drawing in action.
    1. Use the Up Arrow to move "forward" and the Down Arrow to move "backward" and the Left and Right arrows to rotate the heading.
    2. Use the "a" and "z" keys to tilt the view up and down. The tilt will rotate continuously through a full circle in either direction. I don't know if it would eventually crash if you rotated in one direction too long.
    3. If you move away from the drawing environment area (i.e. you get lost), hit the button to reset the view back to the beginning view.
    Attached Files Attached Files
    Last edited by passel; Mar 31st, 2020 at 11:12 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

  18. #18

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

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

    ok.. now i know convert the 3D to 2D and using the camera\me distance(Z).
    but thinking on my position... how can i compare with my position(left-right and up-down)?
    VB6 2D Sprite control

    To live is difficult, but we do it.

  19. #19

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

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

    heres my actual code:
    Code:
    #include<windows.h>
    #include<iostream>
    #include <fstream>
    #include <cmath>
    
    using namespace std;
    
    class Console
    {
    public:
        HWND myconsole;
        HDC mydc;
        Console()
        {
            myconsole = GetConsoleWindow();
            //Get a handle to device context
            mydc = GetDC(myconsole);
        }
    
        ~Console()
        {
            ReleaseDC(myconsole, mydc);
        }
    
        operator HDC()
        {
            return mydc;
        }
    
        operator HWND()
        {
            return myconsole;
        }
    
    
    }Console;
    
    
    #define PI 3.14
    int main()
    {
        LONG X=200, Y=200, Z =10, Width=10, Height = 10, ZWidth=50, MeDistance=50;
    
    
        RECT RectWindow;
        GetWindowRect(Console,&RectWindow);
        RectWindow.left=0;
        RectWindow.top=0;
    
        do
        {
    
            FillRect(Console,&RectWindow,CreateSolidBrush(RGB(0,0,0)));
            HPEN hWhitePen = (HPEN)GetStockObject(WHITE_PEN);
            HPEN hOldPen = (HPEN)SelectObject(Console, hWhitePen);
            POINT points[5] =
            {
                { (X * MeDistance) / (Z + MeDistance), (Y * MeDistance) / (Z + MeDistance) },
                { Width+X, (Y * MeDistance) / (Z + MeDistance) },
                { Width+X, Height+Y },
                { (X * MeDistance) / (Z + MeDistance), Height+Y },
                { (X * MeDistance) / (Z + MeDistance), (Y * MeDistance) / (Z + MeDistance) },
            };
    //draw the rectangle if is on my front:
            if(MeDistance-Z>=0)
            {
                HBRUSH hBrush1 = CreateSolidBrush(RGB(121, 90, 0));
                HBRUSH holdBrush = (HBRUSH)SelectObject(Console, hBrush1);
                Polygon(Console, points, 5);
                SelectObject(Console, hOldPen);
                SelectObject(Console, holdBrush );
                DeleteObject(hBrush1);
                DeleteObject(hWhitePen);
            }
    //for i move to front and back:
            if(GetKeyState(VK_UP)& 0x8000)
            {
                MeDistance-=1;
            }
            else if(GetKeyState(VK_DOWN)& 0x8000)
            {
                MeDistance+=1;
            }
            else if(GetKeyState(VK_ESCAPE)& 0x8000)
            {
                break;
            }
            Sleep(50);
        }while(1);
        return 0;
    }
    when i move for left or right, the scale and rotation changes too?
    VB6 2D Sprite control

    To live is difficult, but we do it.

  20. #20
    Fanatic Member
    Join Date
    Feb 2019
    Posts
    706

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

    Quote Originally Posted by joaquim View Post
    ok.. now i know convert the 3D to 2D and using the camera\me distance(Z).
    but thinking on my position... how can i compare with my position(left-right and up-down)?
    Who are you addressing?

    The formula I posted is not accurate, but it's good enough for games. The limitation is that objects don't become smaller as they go right or left, but become smaller and larger as they go backward or forward. For example, if you are looking at a wall 100 Meters away, and a person walks right or left along the wall, he will not become smaller.

    Here is an accurate formula, but it's slower(VB6 Code, Sqr=Square root):

    x2D = x * L / Sqr((z + L) ^ 2 + y ^ 2)
    y2D = y * L / Sqr((z + L) ^ 2 + x ^ 2)

  21. #21

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

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

    Quote Originally Posted by qvb6 View Post
    Who are you addressing?

    The formula I posted is not accurate, but it's good enough for games. The limitation is that objects don't become smaller as they go right or left, but become smaller and larger as they go backward or forward. For example, if you are looking at a wall 100 Meters away, and a person walks right or left along the wall, he will not become smaller.

    Here is an accurate formula, but it's slower(VB6 Code, Sqr=Square root):

    x2D = x * L / Sqr((z + L) ^ 2 + y ^ 2)
    y2D = y * L / Sqr((z + L) ^ 2 + x ^ 2)
    i need ask more 2 things:
    - we use the angle directly on 'x' or after we get the 'x2D'?
    - these formula is used, too, for make the floor?
    yes i'm trying creating, now, the floor without success
    Code:
    //Position and Size Floor:
            int FloorX=0, FloorY=1000, FloorZ=1,FloorWidth=1000, FloorHeight=10, FloorZWidth=100;
    
            //floor vectors:
            POINT FloorPoints[5] =
            {
                { FloorWidth+FloorX, (FloorY) / (Z) },
                { FloorWidth+FloorX, FloorHeight-FloorY },
                { (FloorX *MeDistance) / (Z +MeDistance), FloorHeight-FloorY },
                { (FloorX * MeDistance) / (Z + MeDistance), (FloorY * MeDistance) / (Z + MeDistance) }
            };
    i'm totally new and i can't get a nice tutorial for learn much more about it
    (these code isn't updated with sqr(), but the C\C++ have it)
    thanks for all
    VB6 2D Sprite control

    To live is difficult, but we do it.

  22. #22
    Fanatic Member
    Join Date
    Feb 2019
    Posts
    706

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

    Quote Originally Posted by joaquim View Post
    i need ask more 2 things:
    - we use the angle directly on 'x' or after we get the 'x2D'?
    - these formula is used, too, for make the floor?
    Yes, you need to do rotation/moving on x, y, z before calculating x2D, y2D. This also apply to the floor, but there maybe some situations where you don't have to do that, I am not sure. I haven't made a game before, but I plan to make one using Unreal game engine(free, but they take 5% after you make a lot of money). You can use C++, or a visual programming language called Blueprint. There are many YouTube tutorials on how to use it.

  23. #23

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

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

    to be honest i didn't found tutorials about these.
    thanks to you, i can start with something, because you give me the key formula.
    and maybe tomorrow i can draw the floor
    i love when works and i hates when fails hehehehehe
    VB6 2D Sprite control

    To live is difficult, but we do it.

  24. #24
    Fanatic Member
    Join Date
    Feb 2019
    Posts
    706

  25. #25

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

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

    i'm sorry i was mean the math for the 3D games
    VB6 2D Sprite control

    To live is difficult, but we do it.

  26. #26
    Fanatic Member
    Join Date
    Feb 2019
    Posts
    706

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

    Quote Originally Posted by joaquim View Post
    i'm sorry i was mean the math for the 3D games
    It's called 3D Projection:

    https://en.wikipedia.org/wiki/3D_projection

    The fast formula that I posted, is something I developed myself, but others may have come up with the same formula. I am not sure about the accurate formula. It might be me or someone else. These are meant for apps that want to display 3D shapes, like engineering apps.

    For games, and even engineering apps; a game engine is a better choice. Game engines do textures, object collision, physics, lighting, shadows, audio, and more. Are you planning to spend months(more like a year or two) in duplicating these futures? If you don't like the main two(Unreal/Unity), here is a list:

    https://en.wikipedia.org/wiki/List_of_game_engines

  27. #27

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

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

    correct me 1 thing: the Polygon() function uses the POINT arrays for the vectors, but uses LONG type instead float... that's why i get a warning.
    theres is another function for get several dots\vectors for create the lines using a float type?
    (is only for i don't get these warnings)
    VB6 2D Sprite control

    To live is difficult, but we do it.

  28. #28

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

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

    Code:
    POINT to2D
            {
                (LONG)Width * CameraDistance / sqrt(pow((ObjectZWidth + CameraDistance) , 2)) + pow(Height , 2), //all variables are 'float'
                (LONG)Height * CameraDistance / sqrt(pow((ObjectZWidth + CameraDistance) , 2)) + pow(Width , 2)
            };
    warning: "narrowing conversion of '((((float)(LONG)((Point3D*)this)->Point3D::PositionX * ((Point3D*)this)->Point3D::CameraDistance) / std::sqrt(std:ow((((Point3D*)this)->Point3D::PositionZ + ((Point3D*)this)->Point3D::CameraDistance), 2.0e+0f))) + std:ow(((Point3D*)this)->Point3D::PositionY, 2.0e+0f))' from 'float' to 'LONG' {aka 'long int'} inside { } [-Wnarrowing]"

    Code:
    class Object3D: public SizePosition3D
    {
    public:
        POINT Vectors[6];
        Object3D(Point3D Position3D=0, Size3D Size3D=0)
        {
            Position=Position3D;
            Size=Size3D;
            Vectors=
            {
                { (Position.To2D().x * Position.CameraDistance) / (Position.PositionZ + Position.CameraDistance), (Position.To2D().y * Position.CameraDistance) / (Position.PositionZ + Position.CameraDistance) },
                { Size.To2D().x+Position.To2D().x, (Position.To2D().y * Position.CameraDistance) / (Position.PositionZ + Position.CameraDistance) },
                { Size.To2D().x+Position.To2D().x, Size.To2D().y+Position.To2D().y },
                { (Position.To2D().x * Position.CameraDistance) / (Position.PositionZ + Position.CameraDistance), Size.To2D().y+Position.To2D().y },
                { (Position.To2D().x * Position.CameraDistance) / (Position.PositionZ + Position.CameraDistance), (Position.To2D().y * Position.CameraDistance) / (Position.PositionZ + Position.CameraDistance) }
            };
        }
    
    };
    "error: assigning to an array from an initializer list|"
    now i get an error confused
    VB6 2D Sprite control

    To live is difficult, but we do it.

  29. #29
    Fanatic Member
    Join Date
    Feb 2019
    Posts
    706

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

    Quote Originally Posted by joaquim View Post
    Code:
    POINT to2D
            {
                (LONG)Width * CameraDistance / sqrt(pow((ObjectZWidth + CameraDistance) , 2)) + pow(Height , 2), //all variables are 'float'
                (LONG)Height * CameraDistance / sqrt(pow((ObjectZWidth + CameraDistance) , 2)) + pow(Width , 2)
            };
    You can't use type casting to convert data. That just tells the compiler to treat the binary data as LONG. Use "double" data type instead of "long", and remove "(LONG)".
    Last edited by qvb6; Apr 5th, 2020 at 03:06 PM.

  30. #30

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

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

    Quote Originally Posted by qvb6 View Post
    You can't use type casting to convert data. That just tells the compiler to treat the binary data as LONG. Use "double" data type instead of "long", and remove "(LONG)".
    maybe i didn't understand what you said.
    i changed from 'float' to 'double' and i delete the "(LONG)"... but the warning remains
    VB6 2D Sprite control

    To live is difficult, but we do it.

  31. #31

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

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

    the casting have, too, an operator precedence and i never knew.
    i must test more 1 thing abut drawing and the distance... then i will be back
    thanks for all
    VB6 2D Sprite control

    To live is difficult, but we do it.

  32. #32

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

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

    theres 1 thing that i'm notice with these formula:
    Code:
    x2D = (x * L) / (z + L)
    y2D = (y * L) / (z + L)
    if the 'L' is more big, the object\rectangle is more big too..
    to be honest: the more big the 'L', the rectangle is more little?
    VB6 2D Sprite control

    To live is difficult, but we do it.

  33. #33
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

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

    Quote Originally Posted by joaquim View Post
    ...if the 'L' is more big, the object\rectangle is more big too..
    to be honest: the more big the 'L', the rectangle is more little?
    L is the distance from you to the screen.
    Imagine if you had an empty picture frame that represented the screen, and you sat at one end of the table with the frame 400cm in front of you, and I was at the other end of the table and you were looking at me through the frame.
    Picture how much of me you might see in the frame.
    Now move the frame further from you, and thus closer to me.
    Would I look smaller in the frame now, or larger?
    "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

  34. #34

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

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

    i'm sorry, but i continue confused: if the 'L' is less than 50, the object will be more far\small... but if is more than 50, the object will be more close\big.
    VB6 2D Sprite control

    To live is difficult, but we do it.

  35. #35

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

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

    when we have FloorZ and the FloorZWidth, the formula only uses FloorZ or must use FloorZ+ FloorZWidth on size vector?
    VB6 2D Sprite control

    To live is difficult, but we do it.

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

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

    Quote Originally Posted by joaquim View Post
    i'm sorry, but i continue confused: if the 'L' is less than 50, the object will be more far\small... but if is more than 50, the object will be more close\big.
    Yes, that is true. If you understand that you are not confused.
    If you don't understand that, then I'm not sure I can make it clearer.

    L is the distance from your eyepoint to the screen. The screen is a window, i.e. a viewport into your 3D world. The closer your eye is to the window, the more of the world you see, if you see more of the world in your window, the world objects have to appear smaller compared to the window.

    If your eye is at the window, you can see 180 degrees of your world, so all the objects you see have to fit in that window, so they have to be small compared to the window.

    If your window is 60 cm wide, and your eye is 60 cm from the window, you can only see 90 degrees of your world, so you see much less of your world. Since you see less things in your window, those things you see appear larger compared to the frame of the window.

    Once you choose a value for L, you should not be changing it. It decides what your field of view is, i.e. how many degrees vertically and horizontally you can see. As you move around, your field of view doesn't change, just the angle of direction that you are looking.
    You would only change L if for instance, you looked through Binoculars, or some other device, that changed your field of view.
    "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. #37

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

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

    passel, to be honest, i was using 'L' like the scale... thanks for correct me.
    so now i understand what i can do for scale...
    i need ask more 1 thing that is kill me now.
    see these sample code:
    Code:
    //Position and Size Floor:
            int FloorX=0, FloorY=1000, FloorZ=100,FloorWidth=1000, FloorHeight=10, FloorZWidth=100;
    
            //floor vectors:
            POINT FloorPoints[5] =
            {
                { (FloorWidth+FloorX)*MeDistance/(FloorZWidth+MeDistance), (FloorY*MeDistance) / (FloorZ*MeDistance) },
                { (FloorWidth+FloorX)*MeDistance/( FloorZWidth+MeDistance), (FloorHeight+FloorY)*MeDistance/( FloorZWidth+MeDistance) },
                { (FloorX *MeDistance) / (FloorZ +MeDistance), (FloorHeight+FloorY)*MeDistance/(FloorZ+ FloorZWidth+MeDistance) },
                { (FloorX * MeDistance) / (FloorZ + MeDistance), (FloorY * MeDistance) / (FloorZ + MeDistance) },
                { (FloorWidth+FloorX)*MeDistance/(FloorZWidth+MeDistance), (FloorY*MeDistance) / (FloorZ*MeDistance) }
            };
    is drawed, but not correctly.. i'm trying creating just a rectangle like a floor... can you explain to me what i'm doing wrong?
    VB6 2D Sprite control

    To live is difficult, but we do it.

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

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

    What is FloorZWidth ?

    It is a little hard to follow what you're doing. You should probably create a function like qvb6 gave you and pass the 3D value in and get the 2d Value back.
    If you store those in variables or arrays of structure, then it would be easier to see the values going in and the resulting X,Y values coming back so you can analyze the values.

    The X,Y,Z values being passed in have to be relative to your eye point.
    So, the first step is to transform your world coordinates into local relative points to where you are looking from in the world.
    Once you've translated the world coordinates into eye point relative coordinates, then those coordinates are what you convert from 3d to 2d for projection.

    It looks like you are using values that are off to one side from the eye point, e.g. ranging from 0 to 1000, rather than -500 to 500.

    Then, if you are not going to use graphics commands to offset the drawing on the screen, you would want to add the center offset when you draw.
    You're not showing what you do with the points after you create them, so I don't know if you're taking care of that or not.

    For an example, I don't have VB6 on this machine, so fell back to using VB.Net in VS2010 which is on this machine.
    I just took qvb6 function and changed the Longs to Integers since they are the 32-bit type in .Net, and changed the Type declaration to a Structure declaration.

    So, treat the your eyepoint as always being (0,0,0) and the points of what you're drawing being relative to that.
    I originally just did the four points with Y as a positive value which I figured would put the rectangle below the eye point (i.e. the floor).
    That looked OK, so I copied the four presets and just changed the Y value to a negative number, so they should be above the eye point (i.e. the ceiling). And that also drew the four points the way I would have expected them to.

    So, the basic function works to the degree that it does, and gives results that you would expect.
    Your primary problem is most likely that your 3d points are not relative to your eye point, but there may be other issues as your example reference variables that are not defined in the snippet you posted.

    Here is the test code I tested with (VB.Net)
    Code:
    Public Class Form1
    
      Private Structure My2DPoint
        Public x As Integer
        Public y As Integer
      End Structure
    
      Private Structure my3DPoint
        Public x As Integer
        Public y As Integer
        Public z As Integer
      End Structure
    
      Dim my2dArray(7) As My2DPoint
      Dim my3dArray(7) As my3DPoint
    
      Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        With my3dArray(0)
          .x = -200
          .y = 100
          .z = 0
        End With
        With my3dArray(1)
          .x = -200
          .y = 100
          .z = 400
        End With
        With my3dArray(2)
          .x = 200
          .y = 100
          .z = 400
        End With
        With my3dArray(3)
          .x = 200
          .y = 100
          .z = 0
        End With
    
        With my3dArray(4)
          .x = -200
          .y = -100
          .z = 0
        End With
        With my3dArray(5)
          .x = -200
          .y = -100
          .z = 400
        End With
        With my3dArray(6)
          .x = 200
          .y = -100
          .z = 400
        End With
        With my3dArray(7)
          .x = 200
          .y = -100
          .z = 0
        End With
    
        For i As Integer = 0 To 7
          With my3dArray(i)
            my2dArray(i) = To2D(.x, .y, .z)
          End With
        Next
    
      End Sub
    
      Private Function To2D(ByVal x As Integer, ByVal y As Integer, ByVal z As Integer) As My2DPoint
        ' L = Distance from screen to the user in pixels.
        '       It's not necessary to turn this into a variable, just use a typical value.
        Const L As Long = 1024 ' User is at 2048 pixels away from monitor
    
        Dim p2d As My2DPoint
        Dim temp As Long
    
        temp = z + L
        p2d.x = x * L / temp
        p2d.y = y * L / temp
    
        To2D = p2d
      End Function
    
      Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        Dim g As Graphics = e.Graphics
        Dim cx As Integer = 300, cy As Integer = 300
    
        For i As Integer = 0 To 7
          With my2dArray(i)
            g.FillEllipse(Brushes.Black, cx + .x, cy + .y, 8, 8)
          End With
        Next
      End Sub
    End Class
    "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. #39

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

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

    "What is FloorZWidth ?"

    - on X, we have Width;
    - on Y, we have Height;
    - so on Z we have ZWidth(it's what i call, unless theres a technical name that i don't know it).
    for now i'm trying draw a rectangle for the floor and then the sky.....

    Code:
    double const MeDistance=500.0f;
    //Position and Size Floor:
            int FloorX=0, FloorY=0, FloorZ=-100,FloorWidth=500, FloorHeight=500, FloorZWidth=500;
    
            //floor vectors:
            POINT FloorPoints[5] =
            {
                {(FloorX * MeDistance) / (FloorZ + MeDistance), (FloorY * MeDistance) / (FloorZ + MeDistance)   },
                {  (FloorX *MeDistance) / (FloorZ +MeDistance), (FloorHeight)*MeDistance/(FloorZWidth+MeDistance) },
                { (FloorWidth *MeDistance) / (FloorZ +MeDistance), (FloorHeight)*MeDistance/(FloorZWidth+MeDistance)},
                { (FloorWidth *MeDistance) / (FloorZ +MeDistance), (FloorY)*MeDistance/(FloorZWidth+MeDistance) },
                { (FloorX+FloorX)*MeDistance/(FloorZWidth+MeDistance), (FloorY*MeDistance) / (FloorZ*MeDistance) }
            };
    it's a normal blue rectangle but nothing compare to floor on Z way
    result:
    https://imgur.com/zY7O0Z2
    VB6 2D Sprite control

    To live is difficult, but we do it.

  40. #40
    Fanatic Member
    Join Date
    Feb 2019
    Posts
    706

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

    Please see the attached VB6 project for a sample that draws a cube. The 3D Origin constants could have been better, but I didn't have time to make them based on PictureBox size.

    VB Code:
    1. Option Explicit
    2.  
    3. Private Type T2DPoint
    4.     x As Long
    5.     y As Long
    6. End Type
    7. Private Type T3DPoint
    8.     x As Long
    9.     y As Long
    10.     z As Long
    11. End Type
    12. Private Origin2D As T2DPoint
    13. Private Origin3D As T3DPoint
    14.  
    15. Const CubeSize As Long = 100 ' Pixels
    16.  
    17. Private Function To2D(ByVal x As Long, ByVal y As Long, ByVal z As Long) As T2DPoint
    18.     ' L = Distance from screen to the user in pixels.
    19.     '     It's not necessary to turn this into a variable, just use a typical value.
    20.     Const L As Long = 2048 ' User is at 2048 pixels away from monitor
    21.  
    22.     Dim p2d As T2DPoint
    23.     Dim temp As Long
    24.  
    25.     If chkUseFastFormula.Value <> 0 Then
    26.         temp = z + L
    27.         p2d.x = x * L \ temp
    28.         p2d.y = y * L \ temp
    29.     Else
    30.         p2d.x = x * L / Sqr((z + L) ^ 2 + y ^ 2)
    31.         p2d.y = y * L / Sqr((z + L) ^ 2 + x ^ 2)
    32.     End If
    33.    
    34.     To2D = p2d
    35. End Function
    36.  
    37. Private Sub Form_Load()
    38.     Picture1.ScaleMode = vbPixels
    39.     Picture1.AutoRedraw = True
    40.     ' 2D Origin
    41.     Origin2D.x = Picture1.ScaleWidth / 2
    42.     Origin2D.y = Picture1.ScaleHeight / 2
    43.     ' 3D Origin
    44.     Origin3D.x = -300
    45.     Origin3D.y = -300 '-50
    46.     Origin3D.z = 1000
    47.     Timer1.Interval = 100
    48.     DrawCube
    49. End Sub
    50.  
    51. Private Sub Draw3DLine(ByVal x1 As Long, ByVal y1 As Long, ByVal z1 As Long, ByVal x2 As Long, ByVal y2 As Long, ByVal z2 As Long)
    52.     Dim pnt1 As T2DPoint
    53.     Dim pnt2 As T2DPoint
    54.    
    55.     pnt1 = To2D(x1 + Origin3D.x, y1 + Origin3D.y, z1 + Origin3D.z)
    56.     pnt2 = To2D(x2 + Origin3D.x, y2 + Origin3D.y, z2 + Origin3D.z)
    57.    
    58.     Picture1.Line (pnt1.x + Origin2D.x, pnt1.y + Origin2D.y)-(pnt2.x + Origin2D.x, pnt2.y + Origin2D.y)
    59. End Sub
    60.  
    61. Private Sub DrawCube()
    62.     ' Cube has 12 lines
    63.     ' Front face
    64.     Draw3DLine 0, 0, 0, CubeSize, 0, 0
    65.     Draw3DLine CubeSize, 0, 0, CubeSize, CubeSize, 0
    66.     Draw3DLine CubeSize, CubeSize, 0, 0, CubeSize, 0
    67.     Draw3DLine 0, CubeSize, 0, 0, 0, 0
    68.     ' Rear face
    69.     Draw3DLine 0, 0, CubeSize, CubeSize, 0, CubeSize
    70.     Draw3DLine CubeSize, 0, CubeSize, CubeSize, CubeSize, CubeSize
    71.     Draw3DLine CubeSize, CubeSize, CubeSize, 0, CubeSize, CubeSize
    72.     Draw3DLine 0, CubeSize, CubeSize, 0, 0, CubeSize
    73.     ' Front to back
    74.     Draw3DLine 0, 0, 0, 0, 0, CubeSize
    75.     Draw3DLine CubeSize, 0, 0, CubeSize, 0, CubeSize
    76.     Draw3DLine CubeSize, CubeSize, 0, CubeSize, CubeSize, CubeSize
    77.     Draw3DLine 0, CubeSize, 0, 0, CubeSize, CubeSize
    78. End Sub
    79.  
    80. Private Sub Timer1_Timer()
    81.     Picture1.Cls
    82.     Origin3D.x = Origin3D.x + 20: If Origin3D.x > 300 Then Origin3D.x = -300
    83.     ' Comment the following line to make the cube move horizenally
    84.     Origin3D.y = Origin3D.y + 20: If Origin3D.y > 300 Then Origin3D.y = -300
    85.     ' Uncomment the following line to make the cube move horizenally
    86.     'Origin3D.y = -50
    87.     Origin3D.z = 0
    88.     DrawCube
    89. End Sub

    DrawCubeProj.zip

Page 1 of 4 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