Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Dice simulation
#1
I saw Petr's dice simulation here not long ago. I really liked it. I was inspired and tried to solve it with rigid-body physics to make the cube's movement realistic. Unfortunately, I couldn't do it with classic rigid-body physics (i.e. 1 center point, angular velocity, linear force, etc.) because it all became chaotic when calculating the angles. Instead, I tried with elastic-body physics. All 8 corners of the cube live an independent life. With their own inertia, direction. Each point is connected by an invisible spring. Therefore, if I apply a force to one point of the cube, it affects the entire system, and a real center-of-mass angular velocity is created. It's like poking one corner of a dice with a pencil, and it will move in a straight line, and it will also turn in the process.

OpenGL, with lights, and the cube will cast a shadow on the ground.

No external file is needed.

   


Code: (Select All)
Dim Shared Gl_ena, mon As Long: mon = _NewImage(800, 800 / 16 * 9, 32): Screen mon: _FullScreen , _Smooth: _DisplayOrder _GLRender , _Software: _MouseHide
Dim Shared Start_values
Dim Shared Dice_size: Dice_size = .8
Const pip180 = 3.141592 / 180

Dim Shared Body(20)





ReDim Shared Points(999, 19), conn(999, 9), Conn_c, Points_c


Dim Shared cam(9)
Dim Shared lamp(3) 'light point XYZ,angle



lookspeed = .3
cam(6) = .5 'start zoom
cam(8) = -25 'start pitch

Cls , 0
Color _RGBA32(255, 255, 255, 200), _RGBA32(0, 0, 0, 200)
Print "Looking with Mouse        New Roll with SPACE key      Zoom with Mousewheel"



Do: _Limit 60

    Select Case InKey$
        Case " ": Start_values = 0
        Case Chr$(27): End
    End Select

    While _MouseInput
        cam(3) = cam(3) + _MouseMovementX * lookspeed
        cam(8) = cam(8) + _MouseMovementY * lookspeed '-80,+80
        cam(6) = cam(6) - _MouseWheel * .03 'zoom
    Wend
    cam(8) = Sgn(cam(8)) * _Min(Abs(cam(8)), 89.5)
    cam(6) = norm(cam(6))
    dis = interpolate(4, 25, cam(6)) * Dice_size
    ang1 = -cam(3) * pip180
    ang2 = -cam(8) * pip180
    cam(0) = Cos(ang2) * Sin(ang1) * dis + Body(0)
    cam(1) = Sin(ang2) * dis + Body(1)
    cam(2) = Cos(ang2) * Cos(ang1) * dis + Body(2)
    cam(1) = _Max(cam(1), .1)

    'cam4 kiszamitasa
    dx = Body(0) - cam(0)
    dy = Body(1) - cam(1)
    dz = Body(2) - cam(2)
    distXZ = Sqr(dx * dx + dz * dz)
    cam(4) = Atn(dy / distXZ) / pip180

    'LAMP
    lamp(3) = Timer * .1: dis = 400
    lamp(0) = Sin(lamp(3)) * dis: lamp(1) = 150: lamp(2) = Cos(lamp(3)) * dis

    Gl_ena = 1
    '_Display
Loop





Sub movedice


    'POINTS array
    '0,1,2 : XYZ
    '3,4,5 : XYZ vector
    '6:active 7:identifier
    '8,9,10 :XYZ calculated to maptriangle
    '11,12,13 :XYZ moving temporary calculating
    '14: 0:FIX 1:MOVING
    '15,16,17 2D-X,Y, greyscale


    'CONN array
    '0:point#1
    '1:point#2
    '2:distance
    '3:active
    '4:disX
    '5:disY
    '6:disZ



    If Start_values = 0 Then
        Gl_ena = 0
        Points_c = 0
        Conn_c = 0
        Randomize Timer
        x = 0
        y = 10
        z = 0
        For t = 0 To 7: l = Points_c + t
            Points(l, 0) = ((t And 1) * 2 - 1) * Dice_size / 2 + x
            Points(l, 1) = ((t And 2) - 1) * Dice_size / 2 + y
            Points(l, 2) = ((t And 4) / 2 - 1) * Dice_size / 2 + z
            Points(l, 6) = 1
            Points(l, 7) = acc
            Points(l, 14) = 1
        Next t
        Points_c = Points_c + 8

        For t1 = 0 To 7
            For t2 = 0 To 7
                conn_add t1, t2, 1
        Next t2, t1
        Start_values = 1

        'Points(0, 14) = 0
        'Points(0, 5) = .5
        speed = interpolate(.02, .06, Rnd)
        For t = 0 To 7
            Points(t, 3) = speed
        Next t
        Points(0, 3) = speed - Rnd * .008
        Points(0, 5) = -(speed - Rnd * .008)


    End If
    tightness = 1
    gravity = .0001 '005
    lass = .9995
    lass = .9996
    power = -.3


    ReDim vec(2)
    For cyc = 0 To 30
        For a = 0 To Points_c - 1: For t = 0 To 2: Points(a, 11 + t) = Points(a, t): Next t
            If (Points(a, 14) = 0 Or Points(a, 6) = 0) Then _Continue

            'connections vector
            vec(0) = 0: vec(1) = 0: vec(2) = 0: vec_c = 0
            For t = 0 To Conn_c - 1: If conn(t, 3) = 0 Then _Continue
                x = -1: For t2 = 0 To 1: If conn(t, t2) = a Then x = conn(t, t2 Xor 1)
                Next t2
                If x <> -1 Then

                    dx = Points(a, 0) - Points(x, 0)
                    dy = Points(a, 1) - Points(x, 1)
                    dz = Points(a, 2) - Points(x, 2)

                    dis = Sqr(dx * dx + dy * dy + dz * dz)
                    If dis > 0.00001 Then
                        diff = dis - conn(t, 2) ' REST LENGTH (nem X/Y/Z!)
                        f = diff * power

                        nx = dx / dis
                        ny = dy / dis
                        nz = dz / dis

                        vec(0) = vec(0) + nx * f
                        vec(1) = vec(1) + ny * f
                        vec(2) = vec(2) + nz * f
                    End If

                    vec_c = vec_c + 1

                    '  For av = 0 To 2: disv = points(a, av) - points(x, av): vec(av) = vec(av) + ((Abs(disv) - conn(t, 4 + av))) * Sgn(disv) * power
                    ' Next av: vec_c = vec_c + 1
                End If
            Next t

            For av = 0 To 2: Points(a, 3 + av) = (Points(a, 3 + av) + vec(av) / vec_c) * lass: Next av
            For av = 0 To 2: Points(a, 11 + av) = Points(a, av) + Points(a, 3 + av): Next av

            'utkozes
            If Points(a, 12) < 0 Then
                Points(a, 12) = 0
                Points(a, 4) = Abs(Points(a, 4)) * .95
                Points(a, 3) = Points(a, 3) / 2
                Points(a, 5) = Points(a, 5) / 2
            Else If cyc = 0 Then Points(a, 4) = Points(a, 4) - gravity

            End If

        Next a

        For a = 0 To Points_c - 1: For t = 0 To 2: Points(a, t) = Points(a, 11 + t): Next t, a
    Next cyc

    Body(0) = 0: Body(1) = 0: Body(2) = 0 'kozeppont
    For t = 0 To 7
        Body(0) = Body(0) + Points(t, 0)
        Body(1) = Body(1) + Points(t, 1)
        Body(2) = Body(2) + Points(t, 2)
    Next t
    Body(0) = Body(0) / 8
    Body(1) = Body(1) / 8
    Body(2) = Body(2) / 8

End Sub



Sub conn_add (p1, p2, tightness): If p1 = p2 Then Exit Sub
    For t = 0 To Conn_c - 1: If (conn(t, 0) = p1 And conn(t, 1) = p2) Or (conn(t, 0) = p2 And conn(t, 1) = p1) Then Exit Sub
    Next t
    conn(Conn_c, 0) = p1: conn(Conn_c, 1) = p2
    For t = 0 To 2: conn(Conn_c, 4 + t) = (Abs(Points(p1, t) - Points(p2, t))) * tightness: Next t
    conn(Conn_c, 2) = dist(conn(Conn_c, 4), conn(Conn_c, 5), conn(Conn_c, 6)): conn(Conn_c, 3) = 1
    'For t = 0 To 2: conn(conn_c, 4 + t) = 0: Next t

    Conn_c = Conn_c + 1
End Sub


Function dist (a, b, c): dist = Sqr(a * a + b * b + c * c): End Function

Sub _GL
    If Gl_ena Then
        movedice
        _glMatrixMode _GL_PROJECTION
        _glLoadIdentity
        _gluPerspective 50, _Width(mon) / _Height(mon), .2, 500
        _glMatrixMode _GL_MODELVIEW
        _glClear _GL_COLOR_BUFFER_BIT Or _GL_DEPTH_BUFFER_BIT

        multi = interpolate(1, 5, 1 / 180 * Abs(Dif_Ang(-cam(3), lamp(3) / pip180)))
        _glClearColor .2 * multi, .6 * multi, .8 * multi, 1
        _glEnable _GL_DEPTH_TEST
        _glEnable _GL_LIGHTING
        _glEnable _GL_LIGHT0

        set_camera1
        _glLightfv _GL_LIGHT0, _GL_POSITION, glVec4(lamp(0), lamp(1), lamp(2), 1) 'ha tolem vilagit
        multi = .1: _glLightfv _GL_LIGHT0, _GL_AMBIENT, glVec3(multi, multi, multi)
        multi = 1: _glLightfv _GL_LIGHT0, _GL_DIFFUSE, glVec3(multi, multi, multi)
        draw_field
        draw_diceshadow
        draw_cube
        _glFlush
    End If
End Sub

Sub set_camera1: _glLoadIdentity: _glRotatef -cam(4), 1, 0, 0: _glRotatef cam(3), 0, 1, 0: End Sub
Sub set_camera2: set_camera1: _glTranslatef -cam(0), -cam(1), -cam(2): End Sub



Sub draw_field
    Static install As Integer, GLlist As Long


    If install = 0 Then
        field_size = 500
        field_res = 140
        half_size = field_size / 2
        cell_size = field_size / field_res

        Dim col(1, 2) As Single
        col(0, 0) = 0.82: col(0, 1) = 0.71: col(0, 2) = 0.55 ' RGB1
        col(1, 0) = 0.55: col(1, 1) = 0.42: col(1, 2) = 0.26 ' RGB2

        GLlist = _glGenLists(1)
        _glNewList GLlist, _GL_COMPILE
        _glDisable _GL_TEXTURE_2D

        For i = 0 To field_res - 1
            For j = 0 To field_res - 1
                Actcol = Abs((i + j) Mod 2 = 0)
                multi = .1: _glMaterialfv _GL_FRONT_AND_BACK, _GL_AMBIENT, glVec4(col(Actcol, 0), col(Actcol, 1), col(Actcol, 2), 1)
                multi = 2: _glMaterialfv _GL_FRONT_AND_BACK, _GL_DIFFUSE, glVec4(col(Actcol, 0), col(Actcol, 1), col(Actcol, 2), 1)
                x0 = -half_size + i * cell_size
                x1 = x0 + cell_size
                z0 = -half_size + j * cell_size
                z1 = z0 + cell_size
                _glBegin _GL_QUADS
                _glNormal3f 0, 1, 0
                _glVertex3f x0, 0, z0
                _glVertex3f x1, 0, z0
                _glVertex3f x1, 0, z1
                _glVertex3f x0, 0, z1
                _glEnd
        Next j, i
        _glEndList
        install = 1

    End If
    set_camera2
    _glCallList GLlist
End Sub

Sub draw_cube
    Static install As Integer, GLlist As Long, text(5) As Long
    If install = 0 Then

        'textures
        Dim Dice_bg As Long: Dice_bg = _RGB32(220, 220, 220)
        Dim Dice_pt As Long: Dice_pt = _RGB32(30, 30, 30)

        size = 600 'kep meret
        dis = size * .25 'tavolsag
        rad = size * .09 'potty sugara
        For t = 0 To 5
            pic = _NewImage(size, size, 32)
            _Dest pic
            Cls , Dice_bg
            For ty = 0 To 2: For tx = 0 To 2
                    If Mid$("....*...." + "..*...*.." + "..*.*.*.." + "*.*...*.*" + "*.*.*.*.*" + "***...***", t * 9 + ty * 3 + tx + 1, 1) = "*" Then
                        py = size / 2 + (ty - 1) * dis: px = size / 2 + (tx - 1) * dis
                        Circle (px, py), rad, Dice_pt: Paint (px, py), Dice_pt, Dice_pt
                    End If
            Next tx, ty
            text(t) = GenerateGLTexture&(pic): _Dest 0: _FreeImage pic
        Next t
        install = 1
    End If

    'draw
    set_camera2
    _glEnable _GL_TEXTURE_2D
    Dim col(2): col(0) = .8: col(1) = .8: col(2) = 1 'light color

    multi = .1: _glMaterialfv _GL_FRONT_AND_BACK, _GL_AMBIENT, glVec4(col(0), col(1), col(2), 1)
    multi = 2: _glMaterialfv _GL_FRONT_AND_BACK, _GL_DIFFUSE, glVec4(col(0), col(1), col(2), 1)

    ReDim p(2) As Integer, Q(2, 2) As Single
    cs$ = "2376 4510 2640 6754 7315 3201": ct$ = "031 132": ctx$ = "00101101" ': cn$ = "11 10 00 21 01 20"
    _glEnable _GL_NORMALIZE
    For t = 0 To 5: sq$ = Mid$(cs$, t * 5 + 1, 4) ' négyszög oldalai
        _glBindTexture _GL_TEXTURE_2D, text(t)
        For t2 = 0 To 1: tr$ = Mid$(ct$, t2 * 4 + 1, 3) ' 1 háromszög 3 vertexe

            For t3 = 0 To 2: Ap = Val(Mid$(sq$, Val(Mid$(tr$, t3 + 1, 1)) + 1, 1))
                For t4 = 0 To 2: Q(t3, t4) = Points(Ap, t4)
            Next t4, t3

            UX = Q(1, 0) - Q(0, 0): UY = Q(1, 1) - Q(0, 1): UZ = Q(1, 2) - Q(0, 2)
            VX = Q(2, 0) - Q(0, 0): VY = Q(2, 1) - Q(0, 1): VZ = Q(2, 2) - Q(0, 2)

            NormX = UY * VZ - UZ * VY: NormY = UZ * VX - UX * VZ: NormZ = UX * VY - UY * VX 'cross multi
            _glBegin _GL_TRIANGLES
            For t3 = 0 To 2
                Ap = Val(Mid$(tr$, t3 + 1, 1))
                _glTexCoord2f Val(Mid$(ctx$, Ap * 2 + 1, 1)), Val(Mid$(ctx$, Ap * 2 + 2, 1))
                _glNormal3f NormX, NormY, NormZ
                Ap2 = Val(Mid$(sq$, Ap + 1, 1))
                _glVertex3f Points(Ap2, 0), Points(Ap2, 1), Points(Ap2, 2)
            Next t3
            _glEnd

    Next t2, t

End Sub

Sub draw_diceshadow

    Dim sp(7, 1) As Single ' 8 pont vetítve XZ síkra
    Dim t As Integer
    Dim x1, y1, z1, x2, y2, z2, t2 As Single
    Dim hull(7) As Integer ' konvex hull indexei
    Dim hullCount As Integer

    '8 point vetulet
    l0 = lamp(0) + cam(0): l2 = lamp(2) + cam(2)
    For t = 0 To 7
        t2 = -lamp(1) / (Points(t, 1) - lamp(1))
        sp(t, 0) = l0 + t2 * (Points(t, 0) - l0) ' X vetulet
        sp(t, 1) = l2 + t2 * (Points(t, 2) - l2) ' Z vetulet
    Next t

    'gift-wrapping
    hullCount = 0
    minX = sp(0, 0): minIdx = 0
    For t = 1 To 7: If sp(t, 0) < minX Then minX = sp(t, 0): minIdx = t
    Next t

    p0 = minIdx
    Do
        hull(hullCount) = p0
        hullCount = hullCount + 1
        p1 = -1
        For t = 0 To 7
            If t <> p0 Then
                If p1 = -1 Then
                    p1 = t
                Else
                    dx1 = sp(p1, 0) - sp(p0, 0)
                    dz1 = sp(p1, 1) - sp(p0, 1)
                    dx2 = sp(t, 0) - sp(p0, 0)
                    dz2 = sp(t, 1) - sp(p0, 1)
                    If dx1 * dz2 - dz1 * dx2 < 0 Then p1 = t
                End If
            End If
        Next t
        p0 = p1
    Loop While p0 <> hull(0) And hullCount < 8 ' maximum 8 pont

    '--------------------------------------
    set_camera2
    _glDisable _GL_DEPTH_TEST
    _glEnable _GL_BLEND
    _glBlendFunc _GL_SRC_ALPHA, _GL_ONE_MINUS_SRC_ALPHA
    _glDisable _GL_TEXTURE_2D
    _glDisable _GL_LIGHTING
    _glColor4f 0, 0, 0, 0.7
    _glBegin _GL_TRIANGLE_FAN
    _glNormal3f 0, 1, 0

    cx = 0: cz = 0
    For t = 0 To hullCount - 1
        cx = cx + sp(hull(t), 0)
        cz = cz + sp(hull(t), 1)
    Next t
    cx = cx / hullCount: cz = cz / hullCount
    _glVertex3f cx, 0, cz

    For t = 0 To hullCount - 1: _glVertex3f sp(hull(t), 0), 0, sp(hull(t), 1): Next t
    _glVertex3f sp(hull(0), 0), 0, sp(hull(0), 1)
    _glEnd
    _glEnable _GL_DEPTH_TEST
    _glEnable _GL_TEXTURE_2D
    _glEnable _GL_LIGHTING

End Sub



Function GenerateGLTexture& (imgHandle)

    Dim texID&, level&, w&, h&, tmpImg&, m As _MEM
    _glGenTextures 1, _Offset(texID&)
    _glBindTexture _GL_TEXTURE_2D, texID&
    w& = _Width(imgHandle): h& = _Height(imgHandle)
    tmpImg& = _CopyImage(imgHandle, 32) ' 32-bites másolat
    level& = 0
    Do
        m = _MemImage(tmpImg&)
        _glTexImage2D _GL_TEXTURE_2D, level&, _GL_RGBA, w&, h&, 0, _GL_BGRA_EXT, _GL_UNSIGNED_BYTE, m.OFFSET
        _MemFree m
        If w& <= 1 Or h& <= 1 Then Exit Do
        w& = Int(w& * .5): h& = Int(h& * .5): level& = level& + 1
        nextImg& = _NewImage(w&, h&, 32)
        _Dest nextImg&
        _PutImage (0, 0)-(w& - 1, h& - 1), tmpImg&
        _Dest 0
        _FreeImage tmpImg&
        tmpImg& = nextImg&
    Loop

    _FreeImage tmpImg&
    _glTexParameteri 3553, 10242, 33071 ''_glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_WRAP_S, _GL_CLAMP_TO_EDGE
    _glTexParameteri 3553, 10243, 33071 ''_glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_WRAP_T, _GL_CLAMP_TO_EDGE
    _glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MIN_FILTER, _GL_LINEAR_MIPMAP_LINEAR
    _glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MAG_FILTER, _GL_LINEAR
    GenerateGLTexture& = texID&
End Function



Function interpolate (a, b, c): interpolate = a + (b - a) * c: End Function
Function norm (x): norm = _Max(_Min(x, 1), 0): End Function
Function glVec3%& (x, y, z): Static internal_vec3(2): internal_vec3(0) = x: internal_vec3(1) = y: internal_vec3(2) = z: glVec3%& = _Offset(internal_vec3()): End Function
Function glVec4%& (x, y, z, w): Static internal_vec4(3): internal_vec4(0) = x: internal_vec4(1) = y: internal_vec4(2) = z: internal_vec4(3) = w: glVec4%& = _Offset(internal_vec4()): End Function
Function Dif_Ang (angle1, angle2): diff = angle2 - angle1: Do While diff > 180: diff = diff - 360: Loop: Do While diff < -180: diff = diff + 360: Loop: Dif_Ang = diff: End Function
Reply
#2
This is really great work! This is just great! Really very nice! Add the pieces and the game cube and you can have a Ludo 3D game Smile  Cool


Reply
#3
(01-13-2026, 08:45 PM)Petr Wrote: This is really great work! This is just great! Really very nice! Add the pieces and the game cube and you can have a Ludo 3D game Smile  Cool
Thanks Petr! Smile

I have other plans. Actually, any spatial shape can be created. The cube was good for testing. First, I would like to solve the problem so that it works not only on flat ground, but also on terrain and terrain. If this works, then 5 bodies. 1 car body + 4 wheels. The fit of the 4 wheels to the body requires different spring strengths. Both wheel-wheel and body-body points. But in theory...very in theory....if everything was calibrated correctly, then the car would roll over, the chassis would work realistically, and the lower half of the wheel would flatten if it was hit by force....like in reality...but I'm just imagining this. I don't know if it's worth it or if it will come to anything. But I'll try.
I did this about 5 years ago:  https://www.youtube.com/watch?v=ZdxWAw-a...VsYQ%3D%3D
This is 'maptriangle' and not realistic car dynamics. It can't roll over. Now that this elastic-body physics works and I've managed to understand opengl a bit, I plan to rewrite the game with realistic physics and nice opengl lighting effects, and not run at 25fps, but at least 60.
Reply
#4
Beautiful! Amazed by the "bounce" shadow, and the rotating light source - these are effects that could go unnoticed when using the dice, but great attention to detail.
Just for the record, the opposite sides of a "real" cubic die add up to 7:  4 opposite 3 etc. but not important I guess.
Great work!
Of all the places on Earth, and all the planets in the Universe, I'd rather live here (Perth, Western Australia.) Big Grin
Please visit my Website at: http://oldendayskids.blogspot.com/
Reply
#5
In the words of Kate Bush: Wow! Wow! Wow! Wow! Wow! Wow! Unbelievable!

This would be just the sort of thing that would be great on the QB64PE YouTube site (@bplus).

As bplus mentioned that Windows Key +G does video capture, I tried it (I usually use proprietary screen capture & edit software), I did this:


The program stutters a bit at the beginning (is that my laptop - it's a Core i5 so shouldn't be slow?).  But all the correct physics is there.  Marvellous!

Almost makes one want to learn Open GL - almost!

Phil is right, the die spots add to 7 on opposite sides.  And as there is one cube it's a die (dice is plural - Steve McN will tell me that dice singular is perfectly acceptable).  This pedantic member can only find trivial things to criticise.
Reply
#6
I managed to move on the terrain. I'm happy. The dice react well to the terrain conditions. Now it's a car. Here we need more complicated flexible connections, and since there are so many points, so many calculations. In principle, it works, but I'm afraid that the program won't be able to process the physics in real time (60fps). Here's a dice. 8 points. But a monster truck-like car with big wheels, a minimum score of around 200. (low-poly body, but high-resolution wheels, and chassis parts) I want the idea to work, so that the wheel presses in, the springs work... I'm curious, we'll find out.
I removed the shadow because it works with little calculation on flat ground (simple projection), but it is complicated on terrain.



Attached Files
.zip   dice_terrain.zip (Size: 1.01 MB / Downloads: 3)
Reply
#7
Thats just freaking sweet! NICE JOB SIR!

+1 

q. Can multiple dice bounce of each other?

An amazed Unseen!
Reply
#8
(01-16-2026, 05:32 PM)Unseen Machine Wrote: Thats just freaking sweet! NICE JOB SIR!

+1 

q. Can multiple dice bounce of each other?

An amazed Unseen!

Thanks! Smile No, for now it only counts collisions with the ground. I've stopped for now because I'd have to come up with a system for the car, because that would be much more complicated. The collision test between body and body will not be based on flexible points, but on orientation-collision. But that would break the previous system. For now, I'm happy if the car can't drive, but at least it bounces and rolls over as it should. Then I'll add things little by little.. steering, acceleration, deceleration, handbrake, and if that works, then 2 or more cars. The problem is that there's a level above which I can't see whether the idea is good or not. and I don't want too much time to go by with unnecessary trials.
Reply
#9
I'm writing this here, hoping someone has an idea for rigid-body physics. As the code shows, it works beautifully. I'm naive, I thought that if I add 1 dimension to this short code, it won't be a square, but a cube, and it will bounce nicely in space. It seems simple. But adding another dimension makes the whole thing chaotic. Then come the Euler problems (I can't explain it well, search for it). Solution, using quanternios instead of angles. But this is a level I can't see through. Then the never-ending impulses. But still, the best thing would be if the cube were calculated using rigid-body physics. Hopefully someone has an idea, code, in any language. Chatgpt is a huge help, but unfortunately at this level it already says nonsense.
If I can't find a way, I'll continue with elastic physics. Which uses simple mathematics, but a lot of calculations. So it's transparent, but a performance killer. In the case of the cube, 8 points. every point is connected to every other point in a flexible way. that means 28 connections, that's not a lot. not a lot. 28 times a lot of multiplications, additive operations, and SQR. The number of connections increases exponentially with the number of points. to have high-resolution wheels, and a minimalist body, I estimated about 200 points. That's a lot, because 200 points have about 20,000 connections to each other. 20,000 SQRs, multiplications, etc. will not be able to be performed at 60fps by QB64.

So does anyone have an idea, code in any language, for rigid-body physics calculations? If not, then I'll continue like this, I'm just afraid that the result will work, but it will be unusable in real time due to the many calculations.

here is the code working in 2d, using rigid-body physics:

Code: (Select All)
Screen 12


Const g = 1200
Const dt = 0.016
Const restitution = 0.6
Const friction = 0.9
Const cubeSize = 40

Dim Shared x, y, vx, vy
Dim Shared angle, omega
Dim Shared groundY

groundY = 400

x = 200
y = 100
vx = 160
vy = 0
angle = .3
omega = 3

Do
    _Limit 60
    Cls

    ' ===== FIZIKA =====
    vy = vy + g * dt
    x = x + vx * dt
    y = y + vy * dt
    angle = angle + omega * dt

    ' ===== CSÚCSOK SZÁMÍTÁSA =====
    Dim px(3), py(3)
    Call GetVertices(x, y, cubeSize, angle, px(), py())

    ' ===== ÜTKÖZÉSVIZSGÁLAT =====
    deepest = 0
    hit = 0
    hitIndex = -1

    For i = 0 To 3
        penetration = py(i) - groundY
        If penetration > deepest Then
            deepest = penetration
            hitIndex = i
            hit = -1
        End If
    Next

    If hit Then
        ' pozíció korrekció
        y = y - deepest

        ' normál irányú sebesség
        If vy > 0 Then
            vy = -vy * restitution
        End If

        ' érintkezési pont karja
        rx = px(hitIndex) - x
        ry = py(hitIndex) - y

        ' forgatónyomaték
        omega = omega + rx * vy * 0.0005

        ' súrlódás
        vx = vx * friction
        omega = omega * friction
    End If

    ' ===== RAJZOLÁS =====
    Line (0, groundY)-(640, groundY), 7

    For i = 0 To 3
        j = (i + 1) Mod 4
        Line (px(i), py(i))-(px(j), py(j)), 15
    Next

    Locate 1, 1
    Print "omega="; omega

    If InKey$ = Chr$(27) Then End
Loop

'==============================
Sub GetVertices (cx, cy, size, ang, px(), py())
    Dim localX(3), localY(3)
    half = size / 2

    localX(0) = -half: localY(0) = -half
    localX(1) = half: localY(1) = -half
    localX(2) = half: localY(2) = half
    localX(3) = -half: localY(3) = half

    For i = 0 To 3
        rx = localX(i) * Cos(ang) - localY(i) * Sin(ang)
        ry = localX(i) * Sin(ang) + localY(i) * Cos(ang)
        px(i) = rx + cx
        py(i) = ry + cy
    Next
End Sub
Reply
#10
Hello!

I'm so happy, I finally managed to create a 'base'. I can now build on this. I need to solve steering, braking, acceleration. The size of the front/rear wheels, their distance, wheelbase, suspension will all be adjustable in real time. The plasticine behavior of the car will also be improved. I'm happy with this for now, because it took a lot of time, not only the programming part, but also the implementation of a stable chassis, the location of point sets, and creating connections in a way that doesn't require too many calculations. So in general, something meaningful will finally happen on the screen. I had a lot of trouble with the physics part before I managed to create a base.



Attached Files
.zip   v7_01.zip (Size: 1.74 MB / Downloads: 3)
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)