dcsimg
Page 3 of 3 FirstFirst 123
Results 81 to 116 of 116

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

  1. #81

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

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

    but like you see i'm using the rectangle center:
    Code:
    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, Size.Width / 2, Size.Height / 2, Size.ZDepth / 2
        
        'Vector1
        FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(0) = NewPoint
    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
    but i don't understand why isn't using the rectangle center
    i'm still confused... sorry
    VB6 2D Sprite control

    To live is difficult, but we do it.

  2. #82
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,907

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

    Step through the code and look at what values your are rotating.
    If you want to rotate around the center of the rectangle, then the center of the rectangle has to be 0,0,0 at the time of the rotation. Rotation is always around 0,0,0, so your points have to be translated so that they are relative to 0,0,0.

    If you have a position.X of 10, your current code says the X values are 10 - 5 (i.e. 5) and (10 + 5) (i.e. 15).

    So, you will be rotating the points at X = 5 and X = 15 around 0, when what you want them to rotate around is 10 (10 is your position, so is your world center for the rectangle).

    Since the equation rotates around 0, you need to move your points mathematically to rotate around 0. You do that by subtracting the world position from the points.
    X = 5 - 10 (X = -5)
    X = 15 - 10 (X = 5)

    Now, if you rotate, the -5 and +5 points will rotate around 0, which now is the mathematical center of the rectangle.
    Once you've rotated, lets say you have the resulting values in RotatedPoint.
    Now, you can move the rotated points of the rectangle back out to the position where they originally were.
    RotatedPoint.X = RotatedPoint.X + Position.X

    So, in summary.
    1. Subtract the position from the coordinates to make the coordinates relative to 0,0,0
    2. Rotate the resulting coordinates.
    3. Add the position to the rotated coordinates to put them back to the place they came from.
    "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. #83

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

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

    - so i must re position the rectangle center on position (0, 0, 0);
    - rotate it;
    - and then re position on right place?
    VB6 2D Sprite control

    To live is difficult, but we do it.

  4. #84

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

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

    finally i put it to work:
    Code:
    FillPosition3D RotatedPosition, Position.X + Size.Width / 2, Position.Y + Size.Height / 2, Position.Z + Size.ZDepth / 2
    and now the rotation:
    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)
        'rotate from center rectangle from 0,0,0 position:
        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)
        'postion the rectangle on right position:
        ConvertedPosition.X = ConvertedPosition.X + Position.X
        ConvertedPosition.Y = ConvertedPosition.Y + Position.Y
        ConvertedPosition.Z = ConvertedPosition.Z + Position.Z
        Rotate = ConvertedPosition
    End Function
    big problem from what i see: the rectangle size is more big
    another problem: the Z rotation don't works

    heres the entire project:
    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
    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)
        ConvertedPosition.X = ConvertedPosition.X + Position.X
        ConvertedPosition.Y = ConvertedPosition.Y + Position.Y
        ConvertedPosition.Z = ConvertedPosition.Z + Position.Z
        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
        HScrollChanged
    
    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, 1
        
        Dim RecSize As Size3D
        FillSize3D RecSize, 10, 10, 1
        DrawRectangle RecPosition, RecSize, Angletest, World3D
        VScrollChanged
        ZScrollChanged
    End Sub
    
    Sub VScrollChanged()
        Angletest.Y = VScroll1.Value
        Me.Caption = CStr(VScroll1.Value)
        Dim RecPosition As Position3D
        FillPosition3D RecPosition, 10, 50, 1
        
        Dim RecSize As Size3D
        FillSize3D RecSize, 10, 10, 1
        DrawRectangle RecPosition, RecSize, Angletest, World3D
    End Sub
    
    Sub ZScrollChanged()
        Angletest.Z = HScroll2.Value
        Me.Caption = CStr(HScroll2.Value)
        Dim RecPosition As Position3D
        FillPosition3D RecPosition, 10, 50, 1
        
        Dim RecSize As Size3D
        FillSize3D RecSize, 10, 10, 1
        DrawRectangle RecPosition, RecSize, Angletest, World3D
        Me.Refresh
    End Sub
    
    Private Sub HScroll2_Change()
        HScrollChanged
    End Sub
    
    Private Sub HScroll2_Scroll()
        HScrollChanged
    End Sub
    
    Private Sub VScroll1_Change()
        HScrollChanged
        
    End Sub
    
    Private Sub VScroll1_Scroll()
        HScrollChanged
    End Sub
    Last edited by joaquim; Apr 26th, 2020 at 04:15 AM. Reason: add more code
    VB6 2D Sprite control

    To live is difficult, but we do it.

  5. #85
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,907

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

    Quote Originally Posted by joaquim View Post
    ...
    big problem from what i see: the rectangle size is more big
    another problem: the Z rotation don't works
    ...
    Well the rectangle may be bigger than the size you gave because you're doing a 3d perspective projection. If you were doing a raw 3d projection, i.e. an ISO projection where you didn't modify the 3D points for Z depth, then the size of the rectangle would be fixed regardless of depth.

    But since you're doing a perspective projection, then the size depends on your viewing frustum, which depends on the eye distance from the viewing plane. For a give size of rectangle, the rectangle will be larger if it is closer to the eye, and smaller if it is further from the eye (i.e. viewpoint).

    I haven't looked at all the values to try to figure what your frustum is, and how your Z value affects the perceived size of the rectangle.

    As far as the Z rotation not working, that is because you aren't doing any Z rotation.
    The fact is you aren't doing X rotation and Y rotation either.
    For 2d rotation, there is only one rotation, which is around the "missing" Z axis. The screen represents the Z plane which is a single level, i.e. 0, so your X,Y values rotate around on that plane.
    For 3d rotation, there are three rotations needed because you have three planes to rotate around, the X,Y plane (Z plane), the X,Z plane (Y plane) and the Y,Z plane (X plane).

    You only have one rotation, which is a mixture of both X and Y. I don't know that it is properly rotating the points around X and Y planes, but it appears to be. But since it is a mixture, it may actually be rotating around a plane that is a combination of the two and is not technically orthogonal to the Z axis.

    If you want to be able to rotate around the Z axis, then you need to fix the rotation sub so that it rotates around all three axis, that is three rotations, not one.
    I don't have time to investigate it right now, but various of the articles that I've linked to explain this from various sources, so if you read them, you can probably play with different ones and decide which method of rotation code you want to use, but in the end, it will involve three rotations, not one.
    "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. #86

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

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

    now the Z rotation works:
    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 = Position
        
        If (Rotation.X <> 0) Then
            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)
        End If
        
        If (Rotation.Y <> 0) Then
            ConvertedPosition.X = (Position.Z - PositionRotated.Z) * Sin(RotationInRads.Y) + (Position.Z - PositionRotated.Z) * Cos(RotationInRads.Y)
            ConvertedPosition.Z = (Position.Z - PositionRotated.Z) * Cos(RotationInRads.Y) - (Position.Z - PositionRotated.Z) * Sin(RotationInRads.Y)
        End If
        
        
        If (Rotation.Z <> 0) Then
            ConvertedPosition.X = (Position.X - PositionRotated.X) * Cos(RotationInRads.Z) - (Position.Y - PositionRotated.Y) * Sin(RotationInRads.Z)
            ConvertedPosition.Y = (Position.X - PositionRotated.X) * Sin(RotationInRads.Z) + (Position.Y - PositionRotated.Y) * Cos(RotationInRads.Z)
        End If
        
        
        ConvertedPosition.X = ConvertedPosition.X + Position.X
        ConvertedPosition.Y = ConvertedPosition.Y + Position.Y
        ConvertedPosition.Z = ConvertedPosition.Z + Position.Z
        Rotate = ConvertedPosition
    End Function
    but i see 2 things:
    - the Z rotation change the scale too;
    - the X and Y, now, don't center the rotation
    VB6 2D Sprite control

    To live is difficult, but we do it.

  7. #87

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

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

    after several times and more thinking, the rotation works fine...
    but see these function:
    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 = Position
        
        If (Rotation.X <> 0) Then
            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)
        End If
        
        If (Rotation.Y <> 0) Then
            ConvertedPosition.X = (Position.Z - PositionRotated.Z) * Sin(RotationInRads.Y) + (Position.X - PositionRotated.X) * Cos(RotationInRads.Y)
            ConvertedPosition.Z = (Position.Z - PositionRotated.Z) * Cos(RotationInRads.Y) - (Position.X - PositionRotated.X) * Sin(RotationInRads.Y)
        End If
        
        
        If (Rotation.Z <> 0) Then
            ConvertedPosition.X = (Position.X - PositionRotated.X) * Cos(RotationInRads.Z) - (Position.Y - PositionRotated.Y) * Sin(RotationInRads.Z)
            ConvertedPosition.Y = (Position.X - PositionRotated.X) * Sin(RotationInRads.Z) + (Position.Y - PositionRotated.Y) * Cos(RotationInRads.Z)
        End If
        
        If (Rotation.X <> 0 Or Rotation.Y <> 0 Or Rotation.Z <> 0) Then
            ConvertedPosition.X = ConvertedPosition.X + PositionRotated.X
            ConvertedPosition.Y = ConvertedPosition.Y + PositionRotated.Y
            ConvertedPosition.Z = ConvertedPosition.Z + PositionRotated.Z
        End If
        Rotate = ConvertedPosition
    End Function
    these function works... but if the angle is Zero, i get 1 different position... but above zero i get the same position... why?
    VB6 2D Sprite control

    To live is difficult, but we do it.

  8. #88
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,907

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

    Are you not able to step through the code?

    If you change the X angle what happens?
    You compute a new Y and Z value, but you don't change X.

    But at the end of the function you add the positions to all three coordinates, even the one you didn't change, so the X position jumps to a new position because you're adding a position to an axis that you didn't subtract a position from.

    The code skips subtracting off the position if the rotation is 0, but never skips adding the position when the rotation value is 0, so you get an offset on the axis that is set to 0.
    If you set both X and Y to non-zero values, then you will see the rectangle jump back to the original position.

    However, the rotations are still not done correctly.
    If you move the Z slider so that you rotate around the Z axis some amount, then you can slide the X and Y sliders and nothing will happen. The Z rotation, being the last one done is the only one that has an effect on your rotation.

    But that isn't the way it should be done. You should always do all three rotations, and each rotation should feed the next, not be three independent rotations, each done on the original values of X,Y,Z.

    I don't know that doing them in X, Y, Z order is the "correct" order, but assuming it is a chosen order, even though perhaps not a conventional one, you should do the steps in sequence.

    1. Subtract the position from your X,Y,Z coordinates so the rotation will rotate around the position (now relative to the object's position), not around the world center. Let's call the results X1, Y1, Z1.
    2. Rotate X1,Y1,Z1 around the X axis, so you have a new coordinates, lets call them X2, Y2, and Z2.
    3. Rotate X2,Y2 and Z2 values around the Y axis, so now you have X3, Y3 and Z3
    4. Rotate X3, Y3, and Z3 values around the Z axis, so now you have your final coordinates, X4, Y4 and Z4
    5. Add the position offsets back to X4, Y4 and Z4 and return them as the fully rotate coordinate, relative to the world position.

    Even though your X and Y rotation might sort of look correct to you, and both sliders seems to be working independent of each other, unlike the Z which stops the X and Y sliders completely, the X and Y are not working correctly.

    If you set the X to 45, the rectangle will get thinner, as it would appear if you're looking at it straight on. But if you then rotate around Y, the rectangle should not look like a rectangle any longer, it should look like a parallelogram type shape, because the rectangle should be "leaning back" or "leaning forward", with the Z depth of the upper and lower edges being at different depths in Z.

    When you rotate in Y, that difference in Z depth of lower and upper lines should cause the side lines to draw at a slant as the rectangle rotates around the Y.

    Since you clobber the Z value computed in the X rotation with the value computed in the Y rotation (rather than using the Z value from the X rotation in the Y rotation), Your Z values all end up being two dimensional so the rectangle remains a rectangle when projected since the Z depth is essentially not affected by the rotation around the X axis.

    If you rotate around the X axis to 90 degrees you should see a line, along the X axis, which will be the bottom or top edge of the rectangle, depending on which way you rotated.
    If you then start rotating around the Y axis, the Line should increase in size, as you see both the (bottom or top) edge of the rectangle, and one of the sides. The maximum length of the line should be when the Y reaches 45, as the size of the (top/bottom) and the side should each look to be around 70% of their length. The line should then appear to shorten as yo increase the angle, and when you reach 90 degrees in Y, it should be a line the length of the side.

    Assuming you have a square rectangle, the line should never be shorter than the length of an edge, but will be longer if you can see two edges in the same plane at the same time.

    Since you are not doing the rotation correctly, if you rotate around the X axis to 90 degrees, and then rotate around the Y axis to 90 degrees, the line edges reduces to a point.
    Last edited by passel; May 3rd, 2020 at 01:43 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

  9. #89
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,907

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

    I went ahead and made the changes I mentioned above to your existing code.
    I also cleaned up the vscroll1 and hscroll2 code, where you were doing additional rectangle drawings, that were in addition to the rectangle you were drawing in the hscrollChanged sub.
    I changed the name of the hscrollChanged sub to just scrollChanged, as it is less confusing since it is called when any scroll changes, not just horizontal scroll control.

    I changed the size and placement of the rectangle to make it easier to see. A 10x10 pixel square was a bit small, so I made it 50x50 and positioned it out at 100,100.
    That seemed to be working fine.

    I then decided to copy your five coordinates in the DrawRectangle sub, and added 50 to the Z value for second five coordinates. This should draw another rectangle 50 pixels behind the first in Z, to give you more sense of what the rotations are doing, since you have two rectangles rotating together, but 50 pixels apart in depth.

    You're still using 0,0 upper left corner of the window as your camera center field of view, so your drawing reflects that, i.e. the deeper Z values are drawn toward the upper left, i.e. your vanishing point is the upper left corner.

    So, full code:
    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
    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 = Position
        ConvertedPosition.X = PositionRotated.X - Position.X
        ConvertedPosition.Y = PositionRotated.Y - Position.Y
        ConvertedPosition.Z = PositionRotated.Z - Position.Z
        Dim T As Position3D
        
        T = ConvertedPosition
            ConvertedPosition.Y = T.Y * Cos(RotationInRads.X) - T.Z * Sin(RotationInRads.X)
            ConvertedPosition.Z = T.Y * Sin(RotationInRads.X) + T.Z * Cos(RotationInRads.X)
      
        T = ConvertedPosition
            ConvertedPosition.X = T.Z * Sin(RotationInRads.Y) + T.X * Cos(RotationInRads.Y)
            ConvertedPosition.Z = T.Z * Cos(RotationInRads.Y) - T.X * Sin(RotationInRads.Y)
        
        T = ConvertedPosition
            ConvertedPosition.X = T.X * Cos(RotationInRads.Z) - T.Y * Sin(RotationInRads.Z)
            ConvertedPosition.Y = T.X * Sin(RotationInRads.Z) + T.Y * Cos(RotationInRads.Z)
        
            ConvertedPosition.X = ConvertedPosition.X + PositionRotated.X
            ConvertedPosition.Y = ConvertedPosition.Y + PositionRotated.Y
            ConvertedPosition.Z = ConvertedPosition.Z + PositionRotated.Z
        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
        
            'Vector1
        FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z + 50
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(0) = NewPoint
        
        
        'Vector2
        FillPosition3D NewPosition3D, Position.X + Size.Width, Position.Y, Position.Z + 50
        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 + 50
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(2) = NewPoint
        
        'Vector4
        FillPosition3D NewPosition3D, Position.X, Position.Y + Size.Height, Position.Z + 50
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(3) = NewPoint
        
        'Vector5
        FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z + 50
        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
        ScrollChanged
    End Sub
    
    Private Sub HScroll1_Change()
      ScrollChanged
    End Sub
    Private Sub HScroll1_Scroll()
      ScrollChanged
    End Sub
    
    Sub ScrollChanged()
        Me.Cls
        Angletest.X = HScroll1.Value
        Angletest.Y = VScroll1.Value
        Angletest.Z = HScroll2.Value
        
        Me.Caption = Angletest.X & ", " & Angletest.Y & ", " & Angletest.Z
        
        Dim RecPosition As Position3D
        FillPosition3D RecPosition, 100, 100, 1
        
        Dim RecSize As Size3D
        FillSize3D RecSize, 50, 50, 1
        DrawRectangle RecPosition, RecSize, Angletest, World3D
        Me.Refresh
    End Sub
    
    Sub VScrollChanged()
      ScrollChanged
    End Sub
    
    Sub ZScrollChanged()
      ScrollChanged
    End Sub
    
    Private Sub HScroll2_Change()
        ScrollChanged
    End Sub
    
    Private Sub HScroll2_Scroll()
        ScrollChanged
    End Sub
    
    Private Sub VScroll1_Change()
        ScrollChanged
    End Sub
    
    Private Sub VScroll1_Scroll()
        ScrollChanged
    End Sub
    Last edited by passel; May 3rd, 2020 at 01:45 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

  10. #90
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,907

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

    Decided to change the Draw Rectangle sub again. Doubled the size of the vertices array so that we can have both rectangles in the array at the same time. Then moved the drawing of the rectangles to the end of the sub, and added to variables to track the updated Z depth of the two rectangles, so we can chose to draw the one further away first, and the closer one second.

    Also, changed the FillStyle so the polygons are filled, and fill each with a different color.
    That way it is more obvious when one moves behind the other during rotations.
    The Z rotation didn't look like what I would expect, and I think that is because the rotations weren't done in the order that I'm use to.

    The order that seems correct to me is Roll (around Z axis), Pitch(around X axis), Yaw(around Y axis), for body rotation.

    So, this is the modified Rotate function, with the Z rotation moved so it is done first, and then the DrawRectangle function that fills the polygons with different colors and changes which is drawn first depending on Z depth.
    I think this looks like it is working much better.
    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 = Position
        ConvertedPosition.X = PositionRotated.X - Position.X
        ConvertedPosition.Y = PositionRotated.Y - Position.Y
        ConvertedPosition.Z = PositionRotated.Z - Position.Z
        Dim T As Position3D
        
        'Z axis  (Roll)
        T = ConvertedPosition
            ConvertedPosition.X = T.X * Cos(RotationInRads.Z) - T.Y * Sin(RotationInRads.Z)
            ConvertedPosition.Y = T.X * Sin(RotationInRads.Z) + T.Y * Cos(RotationInRads.Z)
        
        'X axis  (Pitch)
        T = ConvertedPosition
            ConvertedPosition.Y = T.Y * Cos(RotationInRads.X) - T.Z * Sin(RotationInRads.X)
            ConvertedPosition.Z = T.Y * Sin(RotationInRads.X) + T.Z * Cos(RotationInRads.X)
      
        'Y axis  (Yaw)
        T = ConvertedPosition
            ConvertedPosition.X = T.Z * Sin(RotationInRads.Y) + T.X * Cos(RotationInRads.Y)
            ConvertedPosition.Z = T.Z * Cos(RotationInRads.Y) - T.X * Sin(RotationInRads.Y)
        
            ConvertedPosition.X = ConvertedPosition.X + PositionRotated.X
            ConvertedPosition.Y = ConvertedPosition.Y + PositionRotated.Y
            ConvertedPosition.Z = ConvertedPosition.Z + PositionRotated.Z
        Rotate = ConvertedPosition
    End Function
    
    Private Sub DrawRectangle(Position As Position3D, Size As Size3D, Rotation As Angle3D, WorldSize As Size3D)
        Dim Vertices(9) As POINTAPI
        
        Dim NewPoint As POINTAPI
        
        Dim Z1 As Long, Z2 As Long
        
        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
        Z1 = NewPosition3D.Z
        
        
        '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
        
        
            'Vector1
        FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z + 50
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(5) = NewPoint
        Z2 = NewPosition3D.Z
        
        
        'Vector2
        FillPosition3D NewPosition3D, Position.X + Size.Width, Position.Y, Position.Z + 50
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(6) = NewPoint
        
        'Vector3
        FillPosition3D NewPosition3D, Position.X + Size.Width, Position.Y + Size.Height, Position.Z + 50
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(7) = NewPoint
        
        'Vector4
        FillPosition3D NewPosition3D, Position.X, Position.Y + Size.Height, Position.Z + 50
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(8) = NewPoint
        
        'Vector5
        FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z + 50
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(9) = NewPoint
        
        FillStyle = vbFSSolid
        If Z2 < Z1 Then
          FillColor = vbRed
          Polygon Me.hdc, Vertices(0), 5
          FillColor = vbBlue
          Polygon Me.hdc, Vertices(5), 5
        Else
          FillColor = vbBlue
          Polygon Me.hdc, Vertices(5), 5
          FillColor = vbRed
          Polygon Me.hdc, Vertices(0), 5
        End If
    End Sub
    "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. #91

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

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

    passel: on rotation i see 1 strange thing see that 1 rectangle go above the other.... something about z order or something...
    move the rotation and see more carefully... unless you tell me that's normal.

    correct me anotherthing: on DrawRectangle() i only get once the rotation position... is these correct or i must change for all vertices?

    anotherthing: the 2D rotation must use the same method:
    1 - center of shape position to 0,0;
    2 - rotate;
    3- go to normal position.
    VB6 2D Sprite control

    To live is difficult, but we do it.

  12. #92
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,907

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

    As for z order, yes that is an issue.
    If you go back to my example in post #5, in that program I take the average Z depth of the four points that make up a rectangle (square actually) and sort the squares by that value, and then draw the squares in that order, which will draw all the squares from back to front so that those that closer to the eye should cover those that are further from the eye.

    I would have to look back at the code, but I also may filter out the polygons that make up the sides you can't see (you can only see at maximum, three sides of the overall big collection of sides), so rather than sort all 54 polygons that make up the big cube, only sort the 27 polygons that are possibly visible of the three large faces.

    This is a very "simple" z-ordering, and it will still have overlapped areas where the polygon Z order conflicts, when a level of cubes start revolving independent of the other levels.

    For a more complete z-ordering solution, and more in line with what the 3d-engines have to do, is a Z-buffer value, where each pixel in the scene z-depth is compared to a buffer that is maintained when drawing. For every pixels on the screen, you have the color of the pixel that is being drawn there, and in a parallel buffer you have the z-depth of the pixel being drawn. If the zbuffer pixel is empty, then you draw the pixel's color in the pixel buffer and draw the depth of the pixel in the zbuffer. Before you draw a pixel's color in the pixel buffer, you always check to the zbuffer first and if a pixel has already been drawn there, if the depth of the current pixel being drawn is shallower (closer to the eye), then you put its color in the pixel buffer, and its depth in the zbuffer.

    That way all the pixels that you see in the end are the pixels that are closest to the eye, and the ones "behind" are clobbered (unless you have transparency, in which case the behind pixels will change the color of the fore pixels in some way depending on translucency calculations (not to mention lighting calculations and reflection calculations and surface material type (bump mapping) type calculations being done in a "real" 3D engine).

    Mikle's example in post #55 demonstrates the use of the Zbuffer to handle the overlapping and intersection conflicts of the order that pixels should be drawn in to avoid discontinuities in the drawing order.

    Another approach to handling the z-order issue is a tessellation process of the polygons. The polygons used are not rectangles as we are using here, primarily because using four points for a polygon, there is no guarantee that the four points will be in the same plane so can't be depended on to always represent a flat surface.
    Triangles are used, because the three points of a triangle have to be in a plane, i.e. the three points of a triangle will define the orientation of a plane that contains the three points. You can thus calculate the 90 degree (orthogonal) vector of that plane for lighting and reflection calculations and 3D graphic hardware is designed to fill triangles with a texture very quickly as the mapping of the texture to the plane of the triangle is straight forward.

    In that case, a rectangle would be made up of two triangles with a common diagonal along one side edge of the triangle (i.e. diagonally bisecting the rectangle). When two triangular polygons that make up all the surfaces of all the objects in a scene end up intersecting or overlapping in z-order, the triangles are divided into two smaller triangles at the line of intersection where the two planes cross. That is the tessellation process, subdividing triangular planes into smaller triangular planes before rendering, so you can properly render the smaller triangles in the proper order to maintain z-ordering of the pixels use to fill the triangles.

    So, z-ordering is a complexity, that will have to be addressed in some manner if you want to have good looking graphic interactions in 3D.

    I'm not sure I understand the second question about the "get once the rotation position".
    I think if I'm understanding you, your asking if you need to only calculate the rotation values (essentially the rotation matrix) for the rectangle once, rather than for each point in the rectangle.

    That is true. For a given object, which could be made up of many rectangles, as long as all the points of all the rectangles belong together, so have a common position that is the center of rotation for that object, then yes, you determine what the rotation matrix values are once, then loop through all the points and apply it to get the new positions for all the points that are part of the overall object.

    Third, yes 2D rotation is the same principle. 3D rotation is just 2D rotation done three times.
    "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

  13. #93

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

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

    seems that using a cube, i must get the rotated position from all vertices... is what i see from an error drawing here.
    correct me anotherthing: when the player direction(Y angle) is changed all the world must be rotated without the rotated position(center of the plane)?
    i must update the World Center.... using the form size, i get the CX and CY... but from Z, i only know ZDepth/2.... what you can tell me more about Z? the Z positive is for me or far of me?
    VB6 2D Sprite control

    To live is difficult, but we do it.

  14. #94
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,907

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

    I believe the code you're using has Z increasing as it goes into the screen.

    There are multiple ways to go about it, but in my case, there is a 0,0,0 reference that is the center of your world.
    Then you have objects in that world, so they have position in that world. For objects that move around, it is usual for their position reference to be the center of gravity of the object. That makes it easy to spin the object around its center of gravity.
    Another popular reference for vehicles would be at the center of the vehicle, between the wheels, and the plane at at bottom of the wheels.

    In any case, you are currently using a corner of your rectangle as the position of the rectangle, which is why it tends to rotate off center.

    So you would also have a position in this world, and where your eye is (the eye point also know as the camera position especially when not associated with a player).

    You can also have a lot of fixed objects in the world, so the world position of those points never change.

    Now, if you want to render a scene, you have a lot of things to do.

    First would be to determine where you are in the world, and the direction you're looking and what objects are within the frustum so you know what objects will need to be included in your calculations.

    Second are all the moving objects that are in the scene. For each of objects you have to do what we've been doing lately in this program. If the object has moved or turned since the last time you calculated the vertices (assuming you hang on to the 3D verticies for each object), you have to recalculate them so they reflect their current position in the 3D world. If you don't hang on to the calculated 3D vertices, you'll have to calculate them now.

    Once the moving objects have been updated so their vertices reflect where they are in the 3D world, you have to convert the world coordinates for the things you're going to draw into camera relative coordinates. because where everything appears is relative to where you view them from.
    That calculation is pretty simple, you just subtract the X,Y,Z position of the camera (eye point) from the vertices of the objects you're going to draw.

    Next, you do the 3D rotation of all the vertices around the eyepoint.
    After you have all the relative points for you given view, now would be when you would to z-ordering sorting to figure the order things should be drawn in, unless you will do pixel z-buffer processing when drawing. The z-buffering approach requires you are doing your drawing at the pixel level, rather than using API polygon or other larger area drawing methods.

    The last step is the perspective projection of the 3D points to the 2D screen and doing the actual 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

  15. #95

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

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

    "That calculation is pretty simple, you just subtract the X,Y,Z position of the camera (eye point) from the vertices of the objects you're going to draw."
    and better after the rotation calculation
    thank you so much for all.. thank you
    VB6 2D Sprite control

    To live is difficult, but we do it.

  16. #96

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

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

    i'm sorry Passel, but i need understand more 2 things(again):
    1 - when we draw the plane(floor, the sky or other), normally we use only(besides position) width and ZDepth or we must use, too, Height? if i must use the Height, isn't depend or calculated from ZDepth?(yah i'm confused on something here, like you had seen on previous post)
    when i think on floor, the Height seems to be zero... but my thot may be wrong... here i need a correction... sorry

    2 - when the player changes the direction, the entire world(items, walls, enemies and more) rotates the X... but the rotation position\center is the player position, right?
    VB6 2D Sprite control

    To live is difficult, but we do it.

  17. #97

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

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

    from '1': can you explain more how you calculated the floor?
    i did the same on VB6 but isn't drawed
    Code:
    Private Sub DrawPlane(Position As Position3D, Size As Size3D, Rotation As Angle3D, WorldSize As Size3D, Optional blnRotatedPositionX As Long = 0, Optional blnRotatedPositionY As Long = 0, Optional blnRotatedPositionZ As Long = 0)
        Dim Vertices(5) As POINTAPI
        
        Dim NewPoint As POINTAPI
        
        Dim NewPosition3D As Position3D
        Dim RotatedPosition As Position3D
        Dim FloorZDepthWorldSize As Long
        FloorZDepthWorldSize = Size.ZDepth * WorldSize.ZDepth
        If (FloorZDepthWorldSize = 0) Then FloorZDepthWorldSize = 1
        
        Dim FloorZWorldSize As Long
        FloorZWorldSize = Position.Z + WorldSize.ZDepth
        If (FloorZWorldSize = 0) Then FloorZWorldSize = 1
        
        Dim Z1 As Long, Z2 As Long
        
        If (blnRotatedPositionX = 0) Then
            FillPosition3D RotatedPosition, Position.X + Size.Width / 2, Position.Y + Size.Height / 2, Position.Z + Size.ZDepth / 2
        Else
            FillPosition3D RotatedPosition, Me.ScaleWidth / 2, Me.ScaleHeight / 2, WorldSize.ZDepth / 2
        End If
        
        
        'Back Plane:
        
        'Vector1
        
        NewPosition3D = Rotate(Position, Rotation, RotatedPosition)
        FillPosition2D NewPoint, (NewPosition3D.X) * WorldSize.ZDepth / FloorZWorldSize, (NewPosition3D.Y) * WorldSize.ZDepth / FloorZDepthWorldSize
        
        Vertices(0) = NewPoint
        
        
        'Vector2
        'FillPosition3D NewPosition3D, Position.X + Size.Width, Position.Y, Position.Z - Size.ZDepth
        'NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        'NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        
        NewPosition3D = Rotate(Position, Rotation, RotatedPosition)
        FillPosition2D NewPoint, (NewPosition3D.X + Size.Width) * WorldSize.ZDepth / FloorZWorldSize, NewPosition3D.Y * WorldSize.ZDepth / FloorZDepthWorldSize
        
        Vertices(1) = NewPoint
        
        'Vector3
        'FillPosition3D NewPosition3D, Position.X + Size.Width, Position.Y + Size.Height, Position.Z - Size.ZDepth
        'NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        'NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        NewPosition3D = Rotate(Position, Rotation, RotatedPosition)
        FillPosition2D NewPoint, (NewPosition3D.X + Size.Width) * WorldSize.ZDepth / FloorZWorldSize, (NewPosition3D.Y + Size.Height) * WorldSize.ZDepth / FloorZWorldSize
        Vertices(2) = NewPoint
        
        'Vector4
        'FillPosition3D NewPosition3D, Position.X, Position.Y + Size.Height, Position.Z - Size.ZDepth
        'NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        'NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        NewPosition3D = Rotate(Position, Rotation, RotatedPosition)
        FillPosition2D NewPoint, (NewPosition3D.X + Size.Width) * WorldSize.ZDepth / FloorZWorldSize, (NewPosition3D.Y + Size.Height) * WorldSize.ZDepth / FloorZWorldSize
        Vertices(3) = NewPoint
        
        'Vector5
        'FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z - Size.ZDepth
        'NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        'NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        
        NewPosition3D = Rotate(Position, Rotation, RotatedPosition)
        FillPosition2D NewPoint, (NewPosition3D.X) * WorldSize.ZDepth / FloorZWorldSize, (NewPosition3D.Y) * WorldSize.ZDepth / FloorZWorldSize
        
        Vertices(4) = NewPoint
        
        FillColor = vbRed
        Polygon Me.hdc, Vertices(0), 5
    End Sub
    VB6 2D Sprite control

    To live is difficult, but we do it.

  18. #98
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,907

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

    Well, I think the main problem is that you are trying to define a simple figure like a Rectangle as a modified 2D object, which makes it hard to orient it in 3D space, because you are defining it in terms of Height, width and depth, which by definition means the rectangle has to be aligned with two of the X,Y or Z axis. In order to have it not align, you have to define the correct rotation values for the three axis so the corners end up in 3D space where you want them.

    That is a hard way to define the four points of an arbitrary rectangle.

    It would be much easier to define the four corners of the rectangle in 3D coordinates and be done with it.

    Assume your eyepoint is looking down the Z axis, into the screen and you want a wall in front of you.
    And it would probably make sense to say the floor is at Y = 0, so we will use that.

    (Note: although the height of the ceiling is 6000 pixels, remember that the Y axis is reversed so ceiling will -6000 above the floor
    Ok, say we decided the eye distance to the screen is 1000 pixels.
    And lets assume if you're standing, your eye point is -3000 pixels above the floor.
    Now, we already said the floor's level will be 0, so it is 3000 pixels below our eye.
    And, lets say the room if fairly tall, so the height of the ceiling we will make 6000 pixels.

    So, any wall that goes from Floor to ceiling will be -6000 pixels tall.
    And lets say the room or hallway is 10000 pixels wide.
    In camera coordinates, lets define a wall that is 24000 pixels in front of us.
    Lets say our eyepoint in world coordinates is {100000, -3000, 200000}

    Lets define a wall that would be 24000 pixels in front of us (camera coordinates) at our currently location.

    By the way, you've been defining 5 coordinates for your rectangles, the last being the same as the first, but you don't have to do that to close the polygon. The polygon will automatically be closed from the last point, to the first point, so that is extra work on your part, and probably extra work for the polygon function.


    {left, floor, Z},{left,ceiling,Z},{right,ceiling,Z},{right,floor, Z}
    Front wall = {95000, 0, 224000}, {95000, -6000, 224000}, {105000, -6000, 224000}, {105000, 0, 224000}

    When you convert that to camera coordinates, it will become:
    Front wall = {-5000, 3000, 24000}, -5000, -3000, 24000}, {5000, -3000, 24000}, {5000, 3000, 24000]

    So, in our world, we're defining a rectangle that is 6000 pixels in height, 10000 pixels wide, and is aligned with the Z axis at 224000.
    If you want to use the bottom left corner of the rectangle as your position, then the position is our first coordinate, {95000, 0, 224000}.

    Lets assume the side walls, ceiling and floor will all start at our current eyepoint Z location + 4000 ( 204000), and end at the wall in front of us (Z = 224000}

    Floor
    {95000, 0, 204000}, {95000, 0, 224000}, {105000, 0, 224000}, {105000, 0, 204000}

    Ceiling (same as floor, except y is at ceiling height)
    {95000, 6000, 204000}, {95000, 6000, 224000}, {105000, 6000, 224000}, {105000, 6000, 204000}

    Left Wall
    {95000, 0, 204000}, {95000, 6000, 204000}, {95000, 6000, 224000}, 95000, 0, 224000}

    Right wall (same as left wall, but X is aligned with right side)
    {105000, 0, 204000}, {105000, 6000, 204000}, {105000, 6000, 224000}, 105000, 0, 224000}

    Its late, so I didn't try to change all your code to work with coordinates like this, but I did do a quick test based on the above coordinates, so you could see the projection of a floor, ceiling and the left wall.

    First, a fix to the ConvertPosition3DTo2D Function.
    You had PosZZDepth defined as an Integer, but all your positions are Longs, so that needed to be changed to a long to not overflow with the above world coordinates.
    Also, since we don't want the eyepoint to be located in the upper left corner when projecting the view, added the half height and width values to the coordinates so the eye point is centered in the window.
    Code:
    Private Function ConvertPositon3DTo2D(Position As Position3D, World3DSize As Size3D) As POINTAPI
        Dim ConvertedPosition As POINTAPI
        Dim PosZZDepth As Long
        
        PosZZDepth = Position.Z + World3DSize.ZDepth
        
        If (PosZZDepth = 0) Then PosZZDepth = 1 'avoiding division by zero
        
        ConvertedPosition.X = (Position.X * World3DSize.ZDepth / PosZZDepth) + World3DSize.Width / 2
        ConvertedPosition.Y = (Position.Y * World3DSize.ZDepth / PosZZDepth) + World3DSize.Height / 2
        ConvertPositon3DTo2D = ConvertedPosition
    End Function
    Then for testing the above values, I just patched the values for the three wall into the vertices array in the DrawRectangle Sub.
    I did some minor fixes in the Rotate sub to get the Y values moving in the right direction (+ moves down the screen).
    I also used an instance of the Player UDT to serve as the Camera Position, and change the rotated coordinates to camera coordinates as the last step of the Rotate Sub.

    You can't rotate very far left or right, or up and down, because there is no protection in the code for clipping the 3d line vectors properly when the rotation takes points behind the camera. If you draw things that are behind the camera, you get inverted drawing in both axis, so your polygons get twisted. They shouldn't be drawn when in that condition. I haven't worked out that fix in the past, so handling that would be new territory for me, and I don't know if I will have the time to try to work that. I shouldn't even be doing this post, as I have a busy day tomorrow, and its getting extremely late.

    Since I made a number of changes, and may miss something if I just try to post updated code, I'll post the complete code again.
    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 Double
        Y As Double
        Z As Double
    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
    
    Dim Player1 As Player
    
    
    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 Double, Y As Double, Z As Double)
        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 Long
        
        PosZZDepth = Position.Z + World3DSize.ZDepth
        
        If (PosZZDepth = 0) Then PosZZDepth = 1 'avoiding division by zero
        
        ConvertedPosition.X = (Position.X * World3DSize.ZDepth / PosZZDepth) + World3DSize.Width / 2
        ConvertedPosition.Y = (Position.Y * World3DSize.ZDepth / PosZZDepth) + World3DSize.Height / 2
        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
    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 = Position
        ConvertedPosition.X = Position.X - PositionRotated.X
        ConvertedPosition.Y = -(PositionRotated.Y - Position.Y)  'reversed because Y increments down
        ConvertedPosition.Z = Position.Z - PositionRotated.Z
        Dim T As Position3D
        
        'Z axis  (Roll)
        T = ConvertedPosition
            ConvertedPosition.X = T.X * Cos(RotationInRads.Z) - T.Y * Sin(RotationInRads.Z)
            ConvertedPosition.Y = T.X * Sin(RotationInRads.Z) + T.Y * Cos(RotationInRads.Z)
        
        'X axis  (Pitch)
        T = ConvertedPosition
            ConvertedPosition.Y = T.Y * Cos(RotationInRads.X) - T.Z * Sin(RotationInRads.X)
            ConvertedPosition.Z = T.Y * Sin(RotationInRads.X) + T.Z * Cos(RotationInRads.X)
      
        'Y axis  (Yaw)
        T = ConvertedPosition
            ConvertedPosition.X = T.Z * Sin(RotationInRads.Y) + T.X * Cos(RotationInRads.Y)
            ConvertedPosition.Z = T.Z * Cos(RotationInRads.Y) - T.X * Sin(RotationInRads.Y)
        
            ConvertedPosition.X = ConvertedPosition.X + PositionRotated.X
            ConvertedPosition.Y = ConvertedPosition.Y + PositionRotated.Y
            ConvertedPosition.Z = ConvertedPosition.Z + PositionRotated.Z
            
            'Convert to Camera Coordinates
            ConvertedPosition.X = ConvertedPosition.X - Player1.Position.X
            ConvertedPosition.Y = ConvertedPosition.Y - Player1.Position.Y
            ConvertedPosition.Z = ConvertedPosition.Z - Player1.Position.Z
            
        Rotate = ConvertedPosition
    End Function
    
    Private Sub DrawRectangle(Position As Position3D, Size As Size3D, Rotation As Angle3D, WorldSize As Size3D)
        Dim Vertices(11) 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
         With Player1.Position
           FillPosition3D RotatedPosition, .X, .Y, .Z  'Camera Position
         End With
         
        'Vector1
       ' FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z
        FillPosition3D NewPosition3D, 95000, 0, 204000
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(0) = NewPoint
        
        'Vector2
        FillPosition3D NewPosition3D, 95000, 0, 224000
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(1) = NewPoint
        
        'Vector3
        FillPosition3D NewPosition3D, 105000, 0, 224000
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(2) = NewPoint
        
        'Vector4
        FillPosition3D NewPosition3D, 105000, 0, 204000
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(3) = NewPoint
        
            'Vector1
        FillPosition3D NewPosition3D, 95000, -6000, 204000
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(4) = NewPoint
        
        'Vector2
        FillPosition3D NewPosition3D, 95000, -6000, 224000
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(5) = NewPoint
        
        'Vector3
        FillPosition3D NewPosition3D, 105000, -6000, 224000
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(6) = NewPoint
        
        'Vector4
        FillPosition3D NewPosition3D, 105000, -6000, 204000
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(7) = NewPoint
        
        'Vector1
        FillPosition3D NewPosition3D, 95000, 0, 204000
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(8) = NewPoint
        
        'Vector2
        FillPosition3D NewPosition3D, 95000, -6000, 204000
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(9) = NewPoint
        
        'Vector3
        FillPosition3D NewPosition3D, 95000, -6000, 224000
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(10) = NewPoint
        
        'Vector4
        FillPosition3D NewPosition3D, 95000, 0, 224000
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(11) = NewPoint
        
        FillStyle = vbFSSolid
        
        FillColor = vbRed
        Polygon Me.hdc, Vertices(0), 4
          
        FillColor = vbBlue
        Polygon Me.hdc, Vertices(4), 4
    
        FillColor = vbGreen
        Polygon Me.hdc, Vertices(8), 4
    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
        
        FillPosition3D Player1.Position, 100000, -3000, 200000   'Camera Position
    
        World3D.Width = Me.ScaleWidth
        World3D.Height = Me.ScaleHeight
        World3D.ZDepth = 1000
        ScrollChanged
    End Sub
    
    Private Sub HScroll1_Change()
      ScrollChanged
    End Sub
    Private Sub HScroll1_Scroll()
      ScrollChanged
    End Sub
    
    Sub ScrollChanged()
        Me.Cls
        Angletest.X = HScroll1.Value
        Angletest.Y = VScroll1.Value
        Angletest.Z = HScroll2.Value
        
        Me.Caption = Angletest.X & ", " & Angletest.Y & ", " & Angletest.Z
        
        Dim RecPosition As Position3D
        FillPosition3D RecPosition, 100, 100, 1
        
        Dim RecSize As Size3D
        FillSize3D RecSize, 50, 50, 1
        DrawRectangle RecPosition, RecSize, Angletest, World3D
        Me.Refresh
    End Sub
    
    Sub VScrollChanged()
      ScrollChanged
    End Sub
    
    Sub ZScrollChanged()
      ScrollChanged
    End Sub
    
    Private Sub HScroll2_Change()
        ScrollChanged
    End Sub
    
    Private Sub HScroll2_Scroll()
        ScrollChanged
    End Sub
    
    Private Sub VScroll1_Change()
        ScrollChanged
    End Sub
    
    Private Sub VScroll1_Scroll()
        ScrollChanged
    End Sub
    "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

  19. #99

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

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

    Thanks so much. Yesterday I couldn't login on pc. I did now using the mobile phone. Maybe after some time I can login again on pc.
    Correct me 1 thing: using the new convert3Dto2D function we can create rectangles without using Z and Zdepth?
    I must retest the code, but yesterday was hard reload the page. For that I used another page for load the page. Thanks for all
    VB6 2D Sprite control

    To live is difficult, but we do it.

  20. #100
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,907

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

    Quote Originally Posted by joaquim View Post
    ...
    Correct me 1 thing: using the new convert3Dto2D function we can create rectangles without using Z and Zdepth?
    ...
    The ConvertPositon3DTo2D function isn't really New, it works the same as it did before. I just fixed a Type on the local variable (changing from Integer to Long), and added the center of the window offsets to the returned X,Y values, so the projection's center (0,0) was in the center of the form, rather than in the upper left corner of the form.

    You've been leaving the center of the projection in its default position, i.e. the Upper-Left corner of the form, so you could never see things that were to the left of your eye/camera or above your eye/camera.

    Those fixes or additions have no impact on how you define objects in your world, so have nothing to do with using Z and Zdepth in your rectangle definitions.
    Using Z and Zdepth in your rectangle definitions is a standalone design decision, which I didn't fully understand and just added confusion for me.
    Bottom line, however you choose to define an object, in the end the points that make up the object have to be converted to 3D world coordinates.

    So, if you want to use a 3D position, and 3D dimension, and 3D angles to define your object, and use those to convert to 3D world coordinates before calling the Rotate function, that is up to you, but I find that hard to work with.

    Since you need the objects to end up in 3D world coordinates, then I find it easier to either define the object in 3D world coordinates to begin with, in the case where the object is a permanent part of the 3D world, or define them using local (body reference coordinates), i.e. the center of a figure of a character that is moving in your 3D world may be a point in the center of the character, near the waist, so the position of the head would normally be a negative value (because of the way the Y axis is defined) some distance above the center, and the feet would be a positive value some distance below the center.

    If you want to rotate the character around the three axis, then you just use the local body coordinates to do the rotation since they are already relative to the center of the body, you don't need to subtract the position, do the rotation, and then add the position back.
    You only need to add the position to the local coordinates to "move" the object to where it is located in your 3D world, i.e. you add the object's position to the object's local rotated body coordinates to convert the vertices to 3D world coordinates.

    Which is why I think you have two much code in the Rotate function. Ideally, the Rotate function should just rotate the points it is given, it shouldn't be responsible for converting 3D world coordinates into local body coordinates, doing the rotation and converting them back to 3D world coordinates. The World to local and local to World conversions should be done outside that function.

    Because you are doing those conversions inside the function, then in the case where we want to rotate the world, so the world is essentially our local coordinates, we have to do the extra work of undoing the local to World conversion done in the Rotation. That is why I had to add this second set of translations
    Code:
            'Convert to Camera Coordinates
            ConvertedPosition.X = ConvertedPosition.X - Player1.Position.X
            ConvertedPosition.Y = ConvertedPosition.Y - Player1.Position.Y
            ConvertedPosition.Z = ConvertedPosition.Z - Player1.Position.Z
    to the end of the rotate function, essentially undoing the previous local to World translation that was done in front of it.

    Bottom line, the Rotate function should just Rotate, and any Translations of coordinates that need to be done should be their own function or done directly in the code that calls the rotate function, so you don't have all these extra parameters and hacks in the rotate function to deal with coordinate translations.

    p.s. I do believe the ConvertPositon3DTo2D function will have to be modified to truncate points, i.e. modify points that lie behind the eyepoint to values that are in front of the eyepoint (but most likely still outside the viewing frustum, or perhaps all points that end up outside the viewing frustum could be truncated to the edge of the frustum), so that you don't get the twisted/inverted view of things behind you showing up in front of you in the window.
    You can't simple just limit the X and/or Y value to the frustum, the X and/or Y value has to be calculated to end where the line they are a part of intersect the plane of the frustum, otherwise the angle of the line is changed.

    That is something I haven't worked out before, but SeabrookStan's example in post #52 says it does it, so it would be worth checking out that code as a possible reference, in addition to any web searches on the subject.
    You didn't have VB6 installed previously, apparently, so you may not have looked at his Demo. You should probably look at it now, since it is an interesting demo.
    Last edited by passel; May 7th, 2020 at 08:22 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

  21. #101

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

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

    i'm sorry... but i need understand more 1 thing: please see these line:
    Code:
    FillPosition3D Player1.Position, 100000, -3000, 200000   'Camera Position
    how do you know that coordinates are the form center? how do you get that values?

    on DrawRectangle() function: why you use a number positions instead the variables?
    Code:
    Private Sub DrawRectangle(Position As Position3D, Size As Size3D, Rotation As Angle3D, WorldSize As Size3D)
        Dim Vertices(11) 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
         With Player1.Position
           FillPosition3D RotatedPosition, .X, .Y, .Z  'Camera Position
         End With
         
        'Vector1
       ' FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z
        FillPosition3D NewPosition3D, 95000, 0, 204000 'why numbers instead variables?
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
    PS: finally i login normally....
    VB6 2D Sprite control

    To live is difficult, but we do it.

  22. #102
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,907

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

    Quote Originally Posted by joaquim View Post
    i'm sorry... but i need understand more 1 thing: please see these line:
    Code:
    FillPosition3D Player1.Position, 100000, -3000, 200000   'Camera Position
    how do you know that coordinates are the form center? how do you get that values?
    Those numbers aren't the form center, they are arbitrary values chosen for the example.
    Wherever the player is, in this case, is where the camera is, at the players eye level. This is what is known as a First Person View (FPV), as in FPS (First Person Shooter) type game. You are seeing the world as you would see the world through your eyes as a character in the game.

    I could have chosen any values, but since your Z Depth calculations are based on Pixel coordinates (i.e. the eye is 1000 pixels from the screen), then I was using pixel coordinates for everything else, in the world, as I explain.
    For instance, as I said, I chose the eye level to be 3000 pixels above the floor, so that is why the Y value is -3000.

    For the other numbers (X and Z), I figured the player should be in the 3D World someplace, and since pixels are a very small unit of measurement (in the Simulation world, we usually use meters as our coordinate units, not pixels), I chose relative large numbers, but 100000 pixels would only be a 30 to 40 meters into the real 3D world at normal scale. Of course, if you had a miniature world where people and cars for instance were only 100 pixels tall, and could only move 100s of pixels per second instead of 50 meters per second, for instance, then the world would appear much larger to the small objects that occupied it.

    So, the X and Z values were arbitrary, just giving a current reference point for where the character is in the 3D world. In a FPV, the character is always the center of the view, no mater where they go. So, for projection on the screen, all world coordinates will be converted to character eyepoint (camera) coordinates to produce the scene.
    Quote Originally Posted by joaquim View Post
    ...

    DrawRectangle() function: why you use a number positions instead the variables?
    Simple answer, because this was an example, and the numbers were already explained as being world coordinates and were defined to be in front of the world position of the First Person View, it was easier to patch the literal numbers into a series of vertices calculations so you could see them all in one set of steps.

    The longer answer:
    Because this was just patched in numbers to illustrate what I was talking about, i.e. simple World coordinates for the Floor, Ceiling and Wall.
    You have multiple structucture that have to be passed as parameters, i.e. Position, Size, Rotation and WorldSize, and that is for one rectangle.
    You then create the points of the rectangle based on combinations of values from those various structures.

    If I was to use those structures and variables, I would have to figure out how to simple world coordinates for a vertex (e.g. 95000, 0, 204000), and figure out how to break it apart and create values in Position and size structures that would convert back to the proper values I wanted at that point.
    And since the example was creating three rectangles, that would be a lot of additional setup and calling code outside the function to make that happen.
    I didn't want to spend that much time working that out, especially since I had just said that is expressing simple 3D things in a complicated modified 2D manner of defining objects.

    So, rather than use the function to draw a rectangle and generate the misshaped structures needed to use the function, I just in-lined the code to draw the three rectangles within the function. The steps taken to convert the numbers from world coordinates to projected coordinates is thus right there to step through.

    I figured once you see the process steps in line, you can decide if you want to change your structure, or calls, or simply take the literal numbers used in the example, and create the initialization of whatever variables you see fit to hold those values outside the function, and pass them in as three separate calls to create the three rectangles. If you wanted them in variables, I assumed you could put them in variables. That would give you the opportunity to decide if you wanted to restructure the way you managed storing the rectangles as well, to make things easier to work with.

    You were defining a plane function, and a rectangle function. What is the real difference between a plane and a rectangle. It seems like you were started down a rabbit hole, and I didn't want to follow.
    "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

  23. #103

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

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

    now i understand much more about it.
    but correct me anotherthing: the World3D.ZDepth is 1000, but the camera Z position is 200000... what these means? the ZDepth don't must be more big that the camera Z position?
    the same happens with World3D size.
    VB6 2D Sprite control

    To live is difficult, but we do it.

  24. #104
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,907

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

    You called it World3d.ZDepth, but it doesn't have anything to do with the world's 3D depth.
    It is the distance from your eye to the screen.

    So, as you sit at the computer, we're saying your eye is about 1000 pixels distance from the screen.
    It doesn't matter where you move in the world that is projected on the screen, the distance from your eye to the screen should be the same, in theory.

    If you take the code from the bottom of post #98 in a new project, so you don't disturb anything you have been doing, you can add a couple of thin pictureboxes (like scrollbar shaped) to the form to use as "touchpads" to change the player's X and Z position in the world, i.e. you're moving the eyepoint, aka the camera viewpoint. That way you can back away from the initial starting position, 100000, -3000, 200000, and see the walls move away from the screen, and if you move left and right, you see the walls move and change perspective. If you're careful, you can back away, move to one side, spin the view slightly to keep the walls in the middle, and continue moving to the side, and once the walls are far enough to the right of your position, you can start moving up in Z and make your way to the other side of the walls, and then continue turning around and, moving in X and Z and eventually be on the other side from where you started, and looking south instead of north, and the green wall will be on your right, instead of on your left.

    Eventually you could add controls that would be easier to manipulate the position and view direction, but adding two pictureboxes to use as "touchpads", and a little bit of code will be the quickest and easiest to give you a little bit of rudimentary movement.

    The first picturebox should be oriented like a vertical scrollbar, so tall and skinny. The second picturebox should be oriented like a horizontal picturebox, so short and wide. You don't need to change the scalemode, as moving 12 to 15 pixels at a time (or whatever your twips conversion values are) is not too slow. Moving only 1 pixel at a time would be extremely slow.

    So, if you add the two pictureboxes, this is the code to go with them.
    Code:
    Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
      Static lx As Single, ly As Single
      If Button = vbLeftButton Then
        Player1.Position.Z = Player1.Position.Z + (ly - Y)
        ScrollChanged
      End If
      lx = X: ly = Y
    End Sub
    
    Private Sub Picture2_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
      Static lx As Single, ly As Single
      If Button = vbLeftButton Then
        Player1.Position.X = Player1.Position.X + (X - lx)
        ScrollChanged
      End If
      lx = X: ly = Y
    End Sub
    Dragging the mouse on the pictureboxes will player's X or Z position, and the view will be updated because of the call to the ScrollChanged sub.
    "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

  25. #105

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

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

    i'm using the timer without success
    Code:
    Private Sub Timer1_Timer()
         Const Speed As Integer = 1
         If GetKeyState(vbKeyA) And KEY_DOWN Then
            Angletest.Y = Angletest.Y + 1
            ScrollChanged
        ElseIf GetKeyState(vbKeyD) And KEY_DOWN Then
            Angletest.Y = Angletest.Y - 1
            ScrollChanged
        
        
        ElseIf GetKeyState(vbKeyLeft) And KEY_DOWN Then
            Player1.Position.X = Player1.Position.X - 1
            Player1.Movement.X = Player1.Movement.X - 1
            ScrollChanged
        ElseIf GetKeyState(vbKeyRight) And KEY_DOWN Then
            Player1.Position.X = Player1.Position.X + 1
            Player1.Movement.X = Player1.Movement.X + 1
            ScrollChanged
        ElseIf GetKeyState(vbKeyUp) And KEY_DOWN Then
            Player1.Position.Z = Player1.Position.Z - Speed
            ScrollChanged
        ElseIf GetKeyState(vbKeyDown) And KEY_DOWN Then
            Player1.Position.Z = Player1.Position.Z + Speed
            ScrollChanged
        End If
    End Sub
    lets see the keydown and keyup...
    Code:
    Sub ScrollChanged()
        Me.Cls
        'Angletest.X = HScroll1.Value
        'Angletest.Y = VScroll1.Value
        'Angletest.Z = HScroll2.Value
        
        Label1.Caption = Angletest.X & ", " & Angletest.Y & ", " & Angletest.Z
        Label1.Caption = Label1.Caption & vbNewLine & Player1.Movement.X & ", " & Player1.Movement.Y & ", " & Player1.Movement.Z
        
        Dim RecPosition As Position3D
        FillPosition3D RecPosition, 95000, 0, 204000
        Dim RecSize As Size3D
        FillSize3D RecSize, 10000, -6000, 20000
        DrawCube RecPosition, RecSize, Angletest, World3D
        Me.Refresh
    End Sub
    and i updated the drawrectangle to drawcube and using variabels names:
    Code:
    Private Sub DrawCube(Position As Position3D, Size As Size3D, Rotation As Angle3D, WorldSize As Size3D)
        Dim Vertices(11) 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
        With Player1.Position
           FillPosition3D RotatedPosition, .X, .Y, .Z  'Camera Position
        End With
         
        'Floor:
        'Vector1
        FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z
        'FillPosition3D NewPosition3D, 95000, 0, 204000
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(0) = NewPoint
        
        'Vector2
        'FillPosition3D NewPosition3D, 95000, 0, 224000
        FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z + Size.ZDepth
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(1) = NewPoint
        
        'Vector3
        'FillPosition3D NewPosition3D, 105000, 0, 224000
        FillPosition3D NewPosition3D, Position.X + Size.Width, Position.Y, Position.Z + Size.ZDepth
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(2) = NewPoint
        
        'Vector4
        'FillPosition3D NewPosition3D, 105000, 0, 204000
        FillPosition3D NewPosition3D, Position.X + Size.Width, Position.Y, Position.Z
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(3) = NewPoint
        
        
        'Roof:
        'Vector1
        'FillPosition3D NewPosition3D, 95000, -6000, 204000
        FillPosition3D NewPosition3D, Position.X, Position.Y + Size.Height, Position.Z
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(4) = NewPoint
        
        'Vector2
        'FillPosition3D NewPosition3D, 95000, -6000, 224000
        FillPosition3D NewPosition3D, Position.X, Position.Y + Size.Height, Position.Z + Size.ZDepth
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(5) = NewPoint
        
        'Vector3
        'FillPosition3D NewPosition3D, 105000, -6000, 224000
        FillPosition3D NewPosition3D, Position.X + Size.Width, Position.Y + Size.Height, Position.Z + Size.ZDepth
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(6) = NewPoint
        
        'Vector4
        'FillPosition3D NewPosition3D, 105000, -6000, 204000
        FillPosition3D NewPosition3D, Position.X + Size.Width, Position.Y + Size.Height, Position.Z
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(7) = NewPoint
        
        'Left:
        'Vector1
        'FillPosition3D NewPosition3D, 95000, 0, 204000
        FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(8) = NewPoint
        
        'Vector2
        'FillPosition3D NewPosition3D, 95000, -6000, 204000
        FillPosition3D NewPosition3D, Position.X, Position.Y + Size.Height, Position.Z
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(9) = NewPoint
        
        'Vector3
        'FillPosition3D NewPosition3D, 95000, -6000, 224000
        FillPosition3D NewPosition3D, Position.X, Position.Y + Size.Height, Position.Z + Size.ZDepth
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(10) = NewPoint
        
        'Vector4
        'FillPosition3D NewPosition3D, 95000, 0, 224000
        FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z + Size.ZDepth
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Vertices(11) = NewPoint
        
        FillStyle = vbFSSolid
        
        FillColor = vbRed
        Polygon Me.hdc, Vertices(0), 4
          
        FillColor = vbBlue
        Polygon Me.hdc, Vertices(4), 4
    
        FillColor = vbGreen
        Polygon Me.hdc, Vertices(8), 4
    End Sub
    for now i'm trying the Z and X movement without success
    VB6 2D Sprite control

    To live is difficult, but we do it.

  26. #106
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,907

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

    Perhaps add some Debug.Print statements in the timer code to see if you're getting into any of the If conditions, and to make sure the timer code is running.
    "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

  27. #107

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

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

    you don't belive: now works... i just change the speed:
    Code:
    Private Sub Timer1_Timer()
         Const Speed As Integer = 20
         If KeyState(vbKeyA) = True Then
            Angletest.Y = Angletest.Y + 1
            ScrollChanged
        ElseIf GetKeyState(vbKeyD) And KEY_DOWN Then
            Angletest.Y = Angletest.Y - 1
            ScrollChanged
        
        
        ElseIf GetKeyState(vbKeyLeft) And KEY_DOWN Then
            Player1.Position.X = Player1.Position.X - Speed
            
            ScrollChanged
        ElseIf GetKeyState(vbKeyRight) And KEY_DOWN Then
            Player1.Position.X = Player1.Position.X + Speed
            ScrollChanged
        ElseIf GetKeyState(vbKeyUp) And KEY_DOWN Then
            Player1.Position.Z = Player1.Position.Z + Speed
            ScrollChanged
        ElseIf GetKeyState(vbKeyDown) And KEY_DOWN Then
            Player1.Position.Z = Player1.Position.Z - Speed
            ScrollChanged
        End If
    End Sub
    now i need understand how i can change how can i calculate for draw the visible vertices
    VB6 2D Sprite control

    To live is difficult, but we do it.

  28. #108
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,907

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

    Yeah, I was about to say it worked for me. I changed the timer interval to 1, so the timer would fire as fast as possible, and I changed the speed to 20 (which you did also), so the movement would happen faster.
    As I said, using pixels as the world units is pretty small units to use, so things move very little when you only move 1 pixel in world space.
    And since you are looking at the world from 1000 pixels away, i.e. the screen, and then the walls themselves are even further away, more than 4000 pixels in z, up to 24000 pixels in z, then moving your view point by 1 pixel, moves the world view in subpixel steps, i.e. the farther something is from your eye, the slower it appears to move in the scene compared to your eye.

    I don't know if you had the experience when you were a small child of looking out the side window of a moving car and thinking that the moon was following your car because you could see the trees and other things outside the car whizzing past the window, but the moon looked like it was keeping pace with the car. Because it is so far away, it looks when you change your position (i.e. you're moving with the car and the window is moving with the car, and you are seeing the world through the frame of the window), the moon does not appear to be moving across the window as you move.

    Figuring out how to clip the polygons as they reach the edge of your view, or not drawing them at all if they are completely out of view, is the next big challenge, and is much more complicated than anything done so far.
    "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

  29. #109

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

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

    maybe thinking on these way:
    1 - testing the 3D collision between the vertice and the camera view;
    2 - testing if the next vertice is inside de view for we change the distance between the 2 vertices;
    3 - we now get the new vertice...
    maybe is these the best for don't show hidded vertices... but items and the NPC's in back wall are more difficulty to think... unless i drawed them any way thinking on Z order
    VB6 2D Sprite control

    To live is difficult, but we do it.

  30. #110

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

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

    now i have seen how you work with camera... on rotation, you use:
    1 - the rotation camera position;
    2 - you add the camera position after rotate the vertice.

    i need ask more 2 things:
    1 - is my thot, about don't draw the camera outside vertices right?
    2 - even using the ZOrder, the items after a wall(what we don't see because another object is on front) must be drawed(even thinking on a window or a door)?
    Last edited by joaquim; May 10th, 2020 at 04:00 PM.
    VB6 2D Sprite control

    To live is difficult, but we do it.

  31. #111
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,907

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

    1. You don't draw things that are completely outside the camera view, but you may need to draw things that are in view, but extend outside the view. In that case, you'll need to truncate the object going out of view.

    The way you currently draw that may be difficult. If you look at SeabrookStan's code, all his objects and things he draws are made up of lines.
    So as each line is drawn, it can determine if the line will exceed the frame, and the line shortened to stop at that frame.

    Since you are filling a polygon, you may have to shorten two lines, and you can't eliminate the line that may be completely off screen, because you still need it to close the polygon.

    2. Yes, a simple approach is to draw everything, back to front. If you don't have a hole in a foreground object, then perhaps you could skip drawing some things, but of course, you have to know that what is in front does fully block something behind it. When you're rotating around and seeing things from different angles, that may be hard to determine.

    There is a mode of Ray Tracing that is suppose to be pretty quick, where you scan pixels horizontally looking for the first object hit in z-depth, and then draw the vertical line associated with that object for that horizontal position. Don't think that will work for you since you aren't mapping a texture to an object, but filling with a polygon call, so you don't really have a vertical line of pixels to transfer.
    I may not be remembering the details correctly, haven't tried the method myself.

    I've just drawn everything from back to the front. But, for individual objects, like a cube, you can of course not draw the backside of the cube.
    The standard way of doing backface culling is to always define your polygons in a clockwise direction, from the perspective of facing the polygon.
    So the polygons on the back of the cube would be define in a counter-clockwise direction. When you rotate a view, and get the new coordinates, a test to see if the coordinates are clockwise or not determines whether you draw it or not. For instance, if the cube is rotated so that the back is facing the camera, the counter-clockwise coordinates of the back face, will become clockwise after the rotation, so you draw it.

    With that method, if you want to see both sides of a wall, as we are currently seeing if we rotate, you have to define the rectangle twice, one clockwise, and one counter-clockwise, so one of them will be drawn depending on which side of the wall you're looking at.
    "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

  32. #112

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

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

    i have the 3D collision function:
    Code:
    Private Function IsCollission3D(ObjectPosition1 As Position3D, ObjectSize1 As Size3D, ObjectPosition2 As Position3D, ObjectSize2 As Size3D)
      IsCollission3D = ((ObjectPosition1.X <= (ObjectPosition2.X + ObjectSize2.Width)) And ((ObjectPosition1.X + ObjectSize1.Width) >= ObjectPosition2.X) And (ObjectPosition1.Y <= (ObjectPosition2.Y + ObjectSize2.Height)) And ((ObjectPosition1.Y + ObjectSize1.Height) >= ObjectPosition2.Y) And (ObjectPosition1.Z <= (ObjectPosition2.Z + ObjectSize2.ZDepth)) And ((ObjectPosition1.Z + ObjectSize1.ZDepth) >= ObjectPosition2.Z))
    End Function
    
    
    Private Function IsVerticeCollission3D(Vertice1 As Position3D, Vertice2 As Position3D)
      IsVerticeCollission3D = ((Vertice1.X <= (Vertice2.X)) And ((Vertice1.X) >= Vertice2.X) And (Vertice1.Y <= (Vertice2.Y)) And ((Vertice1.Y) >= Vertice2.Y) And (Vertice1.Z <= (Vertice2.Z)) And ((Vertice1.Z) >= Vertice2.Z))
    End Function
    now i need ask(speaking on same line): how can i add\sub X,Y,Z camera view to the vertice?
    VB6 2D Sprite control

    To live is difficult, but we do it.

  33. #113
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,907

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

    I don't know.
    If you are doing the collisions in cameraview coordinates, then you would convert the coordinates to cameraview coordinates and pass those to the function.
    The function should only be doing collision testing on a set of coordinates, not be concerned what the reference for the coordinates are.

    Just looking at it the IsVerticeCollission3D function.
    (Vertice1.X <= (Vertice2.X)) And ((Vertice1.X) >= Vertice2.X)

    That will only be True if Vertice1.X equals Vertice2.X, so why not just have (Vertice1.X = Vertice2.X), i.e. a single comparison rather than two comparisons and a logical operation.
    "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. #114

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

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

    i still confused with 1 thing: i think the avoid draw everything is for don't use severy the CPU... that i understand... so what i'm asking!?!
    that code works fine but something don't make sence to me...
    see these normal draw when i start:

    https://imgur.com/yHN339L

    now see these bug draw after some move to front(player\camera Z):

    https://imgur.com/dRq42TD

    i know the draw is more big than window size, but is these normal?

    edit: the X and Y calculations seems correct, but not the Z calculation
    edit2: the problem have to do with 'World3D.ZDepth = 1000': the more less number will get more quickly that second image...
    Last edited by joaquim; May 14th, 2020 at 05:20 PM.
    VB6 2D Sprite control

    To live is difficult, but we do it.

  35. #115
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,907

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

    Post #50
    Quote Originally Posted by passel View Post
    ...
    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.
    Post #98
    Quote Originally Posted by passel View Post
    ...
    You can't rotate very far left or right, or up and down, because there is no protection in the code for clipping the 3d line vectors properly when the rotation takes points behind the camera. If you draw things that are behind the camera, you get inverted drawing in both axis, so your polygons get twisted. They shouldn't be drawn when in that condition. I haven't worked out that fix in the past, so handling that would be new territory for me, and I don't know if I will have the time to try to work that.
    ...
    Post #100
    Quote Originally Posted by passel View Post
    ...
    p.s. I do believe the ConvertPositon3DTo2D function will have to be modified to truncate points, i.e. modify points that lie behind the eyepoint to values that are in front of the eyepoint (but most likely still outside the viewing frustum, or perhaps all points that end up outside the viewing frustum could be truncated to the edge of the frustum), so that you don't get the twisted/inverted view of things behind you showing up in front of you in the window.
    You can't simple just limit the X and/or Y value to the frustum, the X and/or Y value has to be calculated to end where the line they are a part of intersect the plane of the frustum, otherwise the angle of the line is changed.

    That is something I haven't worked out before, but SeabrookStan's example in post #52 says it does it, so it would be worth checking out that code as a possible reference, in addition to any web searches on the subject.
    ...
    Post #108
    Quote Originally Posted by passel View Post
    ...
    Figuring out how to clip the polygons as they reach the edge of your view, or not drawing them at all if they are completely out of view, is the next big challenge, and is much more complicated than anything done so far.
    "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

  36. #116

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

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

    finally i'm doing something:
    Code:
    Private Function IsCollision3D(ObjectPosition1 As Position3D, ObjectSize1 As Size3D, ObjectPosition2 As Position3D, ObjectSize2 As Size3D)
      IsCollision3D = ((ObjectPosition1.X <= (ObjectPosition2.X + ObjectSize2.Width)) And ((ObjectPosition1.X + ObjectSize1.Width) >= ObjectPosition2.X) And (ObjectPosition1.Y <= (ObjectPosition2.Y + ObjectSize2.Height)) And ((ObjectPosition1.Y + ObjectSize1.Height) >= ObjectPosition2.Y) And (ObjectPosition1.Z <= (ObjectPosition2.Z + ObjectSize2.ZDepth)) And ((ObjectPosition1.Z + ObjectSize1.ZDepth) >= ObjectPosition2.Z))
    End Function
    
    Private Function IsCollisionVertice3D(Vertice1 As Position3D, ObjectPosition2 As Position3D, ObjectSize2 As Size3D)
      IsCollisionVertice3D = ((Vertice1.X <= (ObjectPosition2.X + ObjectSize2.Width)) And ((Vertice1.X) >= ObjectPosition2.X) And (Vertice1.Y <= (ObjectPosition2.Y + ObjectSize2.Height)) And ((Vertice1.Y) >= ObjectPosition2.Y) And (Vertice1.Z <= (ObjectPosition2.Z + ObjectSize2.ZDepth)) And ((Vertice1.Z) >= ObjectPosition2.Z))
    End Function
    
    Private Sub DrawPlane(Position As Position3D, Size As Size3D, Rotation As Angle3D, WorldSize As Size3D)
        Dim Points(4) 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
        With Player1.Position
           FillPosition3D RotatedPosition, .X, .Y, .Z  'Camera Position
        End With
        
        If (IsCollision3D(Player1.Position, World3D, Position, Size) = False) Then Exit Sub
        
        'Floor:
        'Vector1
        FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        If (IsCollisionVertice3D(NewPosition3D, Player1.Position, World3D) = False) Then
               NewPosition3D.Z = Player1.Position.Z
        End If
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Points(0) = NewPoint
        
        'Vector2
        FillPosition3D NewPosition3D, Position.X, Position.Y, Position.Z + Size.ZDepth
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        If (IsCollisionVertice3D(NewPosition3D, Player1.Position, World3D) = False) Then
            NewPosition3D.Z = Player1.Position.Z
        End If
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Points(1) = NewPoint
        
        'Vector3
        FillPosition3D NewPosition3D, Position.X + Size.Width, Position.Y, Position.Z + Size.ZDepth
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        If (IsCollisionVertice3D(NewPosition3D, Player1.Position, World3D) = False) Then
            NewPosition3D.Z = Player1.Position.Z
        End If
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Points(2) = NewPoint
        
        'Vector4
        FillPosition3D NewPosition3D, Position.X + Size.Width, Position.Y, Position.Z
        NewPosition3D = Rotate(NewPosition3D, Rotation, RotatedPosition)
        If (IsCollisionVertice3D(NewPosition3D, Player1.Position, World3D) = False) Then
            NewPosition3D.Z = Player1.Position.Z
        End If
        NewPoint = ConvertPositon3DTo2D(NewPosition3D, WorldSize)
        Points(3) = NewPoint
        
        
        FillStyle = vbFSSolid
        
        FillColor = vbRed
        Polygon Me.hdc, Points(0), 4
    End Sub
    these code draw 1 line... the 1st 'if' seems working:
    Code:
    If (IsCollision3D(Player1.Position, World3D, Position, Size) = False) Then Exit Sub
    but i'm doing 1 thing wrong: i don't test it with rotated positions...
    but i have another error: i'm testing if the point\vertice is on player front:
    Code:
    If (IsCollisionVertice3D(NewPosition3D, Player1.Position, World3D) = False) Then
               NewPosition3D.Z = Player1.Position.Z
        End If
    is my 'if' thinking wrong or the IsCollisionVertice3D() function is wrong?
    Code:
    Private Function IsCollisionVertice3D(Vertice1 As Position3D, ObjectPosition2 As Position3D, ObjectSize2 As Size3D)
      IsCollisionVertice3D = ((Vertice1.X <= (ObjectPosition2.X + ObjectSize2.Width)) And ((Vertice1.X) >= ObjectPosition2.X) And (Vertice1.Y <= (ObjectPosition2.Y + ObjectSize2.Height)) And ((Vertice1.Y) >= ObjectPosition2.Y) And (Vertice1.Z <= (ObjectPosition2.Z + ObjectSize2.ZDepth)) And ((Vertice1.Z) >= ObjectPosition2.Z))
    End Function
    sometimes isn't showed correctly... can you please see these 2 functions?
    VB6 2D Sprite control

    To live is difficult, but we do it.

Page 3 of 3 FirstFirst 123

Posting Permissions

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



Featured


Click Here to Expand Forum to Full Width