• Print

Author Topic: 3D Bouncing Balls  (Read 168 times)

Richard Notley

  • Sr. Member
  • ****
  • Posts: 349
  • QwerKey
3D Bouncing Balls
« on: April 21, 2018, 05:38:58 am »
This program simulates coloured balls moving and colliding.  It is a derivative of my previous program.

http://www.qb64.net/forum/index.php?topic=13321.0

In the previous version, the perspective mathematics was calculated within the program from my own equations.  In this version, the perspective is handled by the QB64 function _MAPTRIANGLE (3D).  When I coded the original program, I was not aware of the QB64's in-built function, which amazingly handles the 3-dimensional x_, y- and Z- co-ordinates, and presents the image within the 3D space.

I have further added to the 3D full perspective visualisation by making the actual balls 3D shapes.  The 2D ball image is mapped via _MAPTRIANGLE to an actual spherical shape.  You will notice that this method has the effect of distorting the ball shape, especially at distances from the centre of the screen.   This arises because of the vanishing-point perspective used in _MAPTRIANGLE(3D).

I have created this program as a half-way house towards a stereoscopic 3D program I wish to create: in that program, the balls will be seen to move in and out of the screen.

Esc to quit the program.

Code: [Select]
' 3D Bouncing Balls Using _MAPTRIANGLE by QWERKEY 21/04/18

' Cyperium method for sphere image

CONST True = -1`, False = 0`
_TITLE "3D Bouncing Balls"
RANDOMIZE (TIMER)

CONST NoBalls%% = 10, Uscreen% = 1000, Vscreen% = 800, NoPhis%% = 16, NoAlphas%% = 6, XBright! = 0.5
CONST Pi! = 4 * ATN(1), Rad1%% = 25, PerspDist% = 550, DeltaSepn! = 0.25 'small offset to stop balls sticking
CONST Alpha! = Pi! / (2 * NoAlphas%%), Phi! = 2 * Pi! / NoPhis%%
DIM BallStats!(NoBalls%% - 1, 9), ViewOrder%%(NoBalls%% - 1), Cyperium&(NoBalls%% - 1)
DIM MapConv%(NoPhis%%, NoAlphas%%, 1, 2)

'Conversion from 2D
FOR N%% = 0 TO NoPhis%%
    FOR M%% = 0 TO NoAlphas%%
        MapConv%(N%%, M%%, 0, 0) = 128 + CINT(127 * SIN((Pi! / 2) - M%% * Alpha!) * COS(N%% * Phi!))
        MapConv%(N%%, M%%, 0, 1) = 128 + CINT(127 * SIN((Pi! / 2) - M%% * Alpha!) * SIN(N%% * Phi!))
        MapConv%(N%%, M%%, 1, 0) = CINT(Rad1%% * SIN((Pi! / 2) - M%% * Alpha!) * COS(N%% * Phi!))
        MapConv%(N%%, M%%, 1, 1) = CINT(Rad1%% * SIN((Pi! / 2) - M%% * Alpha!) * SIN(N%% * Phi!))
        MapConv%(N%%, M%%, 1, 2) = CINT(Rad1%% * COS((Pi! / 2) - M%% * Alpha!))
    NEXT M%%
NEXT N%%

'Screen Background
TempImage& = _NEWIMAGE(Uscreen%, Vscreen%, 32)
_DEST TempImage&
COLOR _RGB(255, 255, 255), _RGB(10, 60, 60)
CLS
FOR UCol% = 0 TO Uscreen% - 1
    FOR VCol% = 0 TO Vscreen% - 1
        PSET (UCol%, VCol%), _RGB(100, INT(180 * UCol% / Uscreen%), INT(180 * VCol% / Vscreen%))
    NEXT VCol%
NEXT UCol%
Background& = MakeHardware&(TempImage&)

'Set array for depth order
JumpStart%% = 1
WHILE JumpStart%% <= NoBalls%%: JumpStart%% = JumpStart%% * 2: WEND
FOR N%% = 0 TO NoBalls%% - 1
    ViewOrder%%(N%%) = N%%
NEXT N%%

' Define characteristics of balls
DATA 255,0,0
DATA 219,80,0
DATA 150,100,0
DATA 138,117,0
DATA 80,155,20
DATA 0,255,0
DATA 20,135,100
DATA 0,105,150
DATA 0,60,150
DATA 0,0,255
FOR N%% = 0 TO NoBalls%% - 1
    'Ball mass
    BallStats!(N%%, 0) = 0.1 + (0.8 * N%% / (NoBalls%% - 1))
    IF BallStats!(N%%, 0) = 0 THEN BallStats!(N%%, 0) = 0.000001
    'Ball colours (temporarily use (N%%,1,2,3)
    FOR P%% = 1 TO 3
        READ BallStats!(N%%, P%%)
    NEXT P%%
    TempImage& = _NEWIMAGE(256, 256, 32)
    _DEST TempImage&
    COLOR _RGB(BallStats!(N%%, 1), BallStats!(N%%, 2), BallStats!(N%%, 3)), _RGBA(0, 0, 0, 0)
    'Image data goes from 1 to 255 (not 0 to 255)
    FOR Z% = 128 TO 255
        FOR X% = 1 TO 255
            FOR Y% = 1 TO 255
                DeltaX% = X% - 127
                DeltaY% = Y% - 127
                DeltaZ% = Z% - 127
                Dist! = SQR((DeltaX% * DeltaX%) + (DeltaY% * DeltaY%) + (DeltaZ% * DeltaZ%))
                IF Dist! > 125 AND Dist! < 127 THEN PSET (X%, Y%), _RGB(CINT(Z% * BallStats!(N%%, 1) * (1 - (XBright! * X% / 255)) / 255), CINT(Z% * BallStats!(N%%, 2) * (1 - (XBright! * X% / 255)) / 255), CINT(Z% * BallStats!(N%%, 3) * (1 - (XBright! * X% / 255)) / 255))
            NEXT
        NEXT
    NEXT
    Cyperium&(N%%) = MakeHardware&(TempImage&)
    'Ball positions/velocities
    FOR P%% = 4 TO 6
        BallStats!(N%%, P%%) = (0.5 - RND) * 1000
    NEXT P%%
    FOR P%% = 7 TO 9
        Velocity! = 0.5 - RND
        IF Velocity! < 0 THEN
            Velocity! = Velocity! - 0.5
        ELSE
            Velocity! = Velocity! + 0.5
        END IF
        BallStats!(N%%, P%%) = Velocity! * 3
    NEXT P%%
NEXT N%%

'Create screen
SCREEN _NEWIMAGE(Uscreen%, Vscreen%, 32)
_SCREENMOVE 50, 13
_DEST 0
_DISPLAYORDER _HARDWARE 'do not even render the software layer, just the hardware one.

'Initialise axes and rotations
ZRot! = (RND - 0.5) * 0.0011: YRot! = (RND - 0.5) * 0.0011: XRot! = (RND - 0.5) * 0.0011
ZTime% = 15 + INT(47 * RND): YTime%% = 15 + INT(47 * RND): XTime% = 15 + INT(47 * RND)
ZStart! = TIMER: YStart! = TIMER: XStart! = TIMER
Zaxis! = 0: Yaxis! = 0: Xaxis! = 0
Stereo` = True

WHILE Stereo`
    _LIMIT 120 'Game Frames/Second Rate

    _PUTIMAGE (0, 0), Background&

    'Calculate moves
    FOR N%% = 0 TO NoBalls%% - 1
        FOR P%% = 1 TO 3
            BallStats!(N%%, 3 + P%%) = BallStats!(N%%, 3 + P%%) + BallStats!(N%%, 6 + P%%)
        NEXT P%%
    NEXT N%%

    'Check for collsions
    FOR N%% = 0 TO NoBalls%% - 2
        FOR M%% = N%% + 1 TO NoBalls%% - 1
            SepnSqd! = (BallStats!(N%%, 4) - BallStats!(M%%, 4)) * (BallStats!(N%%, 4) - BallStats!(M%%, 4)) + (BallStats!(N%%, 5) - BallStats!(M%%, 5)) * (BallStats!(N%%, 5) - BallStats!(M%%, 5)) + (BallStats!(N%%, 6) - BallStats!(M%%, 6)) * (BallStats!(N%%, 6) - BallStats!(M%%, 6))
            IF SepnSqd! <= 4 * Rad1%% * Rad1%% THEN
                ' Set new velocities
                Multiplier! = 0: NDist! = 0: MDist! = 0
                FOR P%% = 1 TO 3
                    Multiplier! = Multiplier! + (BallStats!(N%%, 6 + P%%) - BallStats!(M%%, 6 + P%%)) * (BallStats!(N%%, 3 + P%%) - BallStats!(M%%, 3 + P%%))
                    NDist! = NDist! + BallStats!(N%%, 3 + P%%) * BallStats!(N%%, 3 + P%%)
                    MDist! = MDist! + BallStats!(M%%, 3 + P%%) * BallStats!(M%%, 3 + P%%)
                NEXT P%%
                NDist! = SQR(NDist!)
                MDist! = SQR(MDist!)
                Multiplier! = 2 * Multiplier! / (SepnSqd! * (BallStats!(N%%, 0) + BallStats!(M%%, 0)))
                FOR P%% = 1 TO 3
                    SepnVect! = BallStats!(N%%, 3 + P%%) - BallStats!(M%%, 3 + P%%)
                    BallStats!(N%%, 6 + P%%) = BallStats!(N%%, 6 + P%%) - (Multiplier! * BallStats!(M%%, 0) * SepnVect!)
                    BallStats!(M%%, 6 + P%%) = BallStats!(M%%, 6 + P%%) + (Multiplier! * BallStats!(N%%, 0) * SepnVect!)
                    IF NDist! > MDist! THEN
                        BallStats!(M%%, 3 + P%%) = BallStats!(M%%, 3 + P%%) - (DeltaSepn! * (BallStats!(N%%, 3 + P%%) - BallStats!(M%%, 3 + P%%)) / SQR(SepnSqd!))
                    ELSE
                        BallStats!(N%%, 3 + P%%) = BallStats!(N%%, 3 + P%%) + (DeltaSepn! * (BallStats!(N%%, 3 + P%%) - BallStats!(M%%, 3 + P%%)) / SQR(SepnSqd!))
                    END IF
                NEXT P%%
            END IF
        NEXT M%%
    NEXT N%%

    'Look for reflection off sides
    FOR N%% = 0 TO NoBalls%% - 1
        FOR P%% = 1 TO 3
            IF BallStats!(N%%, 3 + P%%) > 500 - Rad1%% THEN
                BallStats!(N%%, 6 + P%%) = -BallStats!(N%%, 6 + P%%)
                IF BallStats!(N%%, 3 + P%%) + BallStats!(N%%, 6 + P%%) > 500 - Rad1%% THEN
                    BallStats!(N%%, 3 + P%%) = BallStats!(N%%, 3 + P%%) - DeltaSepn!
                END IF
            ELSEIF BallStats!(N%%, 3 + P%%) < -500 + Rad1%% THEN
                BallStats!(N%%, 6 + P%%) = -BallStats!(N%%, 6 + P%%)
                IF BallStats!(N%%, 3 + P%%) + BallStats!(N%%, 6 + P%%) < -500 + Rad1%% THEN
                    BallStats!(N%%, 3 + P%%) = BallStats!(N%%, 3 + P%%) + DeltaSepn!
                END IF
            END IF
        NEXT P%%
    NEXT N%%

    'Adjust for angle of rotation
    FOR N%% = 0 TO NoBalls%% - 1
        R2! = SQR(BallStats!(N%%, 4) * BallStats!(N%%, 4) + BallStats!(N%%, 5) * BallStats!(N%%, 5) + BallStats!(N%%, 6) * BallStats!(N%%, 6))
        Theta2! = _ACOS(BallStats!(N%%, 6) / R2!)
        Phi2! = _ATAN2(BallStats!(N%%, 5), BallStats!(N%%, 4)) + Zaxis!
        BallStats!(N%%, 1) = R2! * SIN(Theta2!) * COS(Phi2!)
        BallStats!(N%%, 2) = R2! * SIN(Theta2!) * SIN(Phi2!)
        BallStats!(N%%, 3) = R2! * COS(Theta2!)
        R2! = SQR(BallStats!(N%%, 1) * BallStats!(N%%, 1) + BallStats!(N%%, 2) * BallStats!(N%%, 2) + BallStats!(N%%, 3) * BallStats!(N%%, 3))
        Theta2! = _ACOS(BallStats!(N%%, 1) / R2!)
        Phi2! = _ATAN2(BallStats!(N%%, 3), BallStats!(N%%, 2)) + Xaxis!
        BallStats!(N%%, 2) = R2! * SIN(Theta2!) * COS(Phi2!)
        BallStats!(N%%, 3) = R2! * SIN(Theta2!) * SIN(Phi2!)
        BallStats!(N%%, 1) = R2! * COS(Theta2!)
        R2! = SQR(BallStats!(N%%, 1) * BallStats!(N%%, 1) + BallStats!(N%%, 2) * BallStats!(N%%, 2) + BallStats!(N%%, 3) * BallStats!(N%%, 3))
        Theta2! = _ACOS(BallStats!(N%%, 2) / R2!)
        Phi2! = _ATAN2(BallStats!(N%%, 1), BallStats!(N%%, 3)) + Yaxis!
        BallStats!(N%%, 3) = CINT(R2! * SIN(Theta2!) * COS(Phi2!))
        BallStats!(N%%, 1) = CINT(R2! * SIN(Theta2!) * SIN(Phi2!))
        BallStats!(N%%, 2) = CINT(R2! * COS(Theta2!))
    NEXT N%%

    'Change display order: furthest first
    Jump%% = JumpStart%%
    WHILE Jump%% > 1
        Jump%% = (Jump%% - 1) \ 2
        DoneHere` = False
        WHILE NOT DoneHere`
            DoneHere` = True
            FOR Upper%% = 1 TO NoBalls%% - Jump%%
                Lower%% = Upper%% + Jump%%
                '!!! different BallStats! z-dim
                IF BallStats!(ViewOrder%%(Upper%% - 1), 3) > BallStats!(ViewOrder%%(Lower%% - 1), 3) THEN
                    SWAP ViewOrder%%(Upper%% - 1), ViewOrder%%(Lower%% - 1)
                    DoneHere` = False
                END IF
            NEXT Upper%%
        WEND
    WEND

    'Display balls
    FOR N1%% = NoBalls%% - 1 TO 0 STEP -1
        P%% = ViewOrder%%(N1%%)
        '_PUTIMAGE (BallStats!(P%%, 1) + 500, BallStats!(P%%, 2) + 400), Cyperium&(P%%)
        'Ball views done with _MAPTRIANGLE 3D
        FOR N%% = 0 TO NoPhis%% - 1
            FOR M%% = 0 TO NoAlphas%% - 2
                Ax% = MapConv%(N%%, M%%, 1, 0) + BallStats!(P%%, 1)
                Ay% = MapConv%(N%%, M%%, 1, 1) + BallStats!(P%%, 2)
                Az% = MapConv%(N%%, M%%, 1, 2) + BallStats!(P%%, 3) - PerspDist%
                Bx% = MapConv%(N%%, M%% + 1, 1, 0) + BallStats!(P%%, 1)
                By% = MapConv%(N%%, M%% + 1, 1, 1) + BallStats!(P%%, 2)
                Bz% = MapConv%(N%%, M%% + 1, 1, 2) + BallStats!(P%%, 3) - PerspDist%
                Cx% = MapConv%(N%% + 1, M%% + 1, 1, 0) + BallStats!(P%%, 1)
                Cy% = MapConv%(N%% + 1, M%% + 1, 1, 1) + BallStats!(P%%, 2)
                Cz% = MapConv%(N%% + 1, M%% + 1, 1, 2) + BallStats!(P%%, 3) - PerspDist%
                _MAPTRIANGLE (MapConv%(N%%, M%%, 0, 0), MapConv%(N%%, M%%, 0, 1))-(MapConv%(N%%, M%% + 1, 0, 0), MapConv%(N%%, M%% + 1, 0, 1))-(MapConv%(N%% + 1, M%% + 1, 0, 0), MapConv%(N%% + 1, M%% + 1, 0, 1)), Cyperium&(P%%) TO(Ax%, Ay%, Az%)-(Bx%, By%, Bz%)-(Cx%, Cy%, Cz%)
                _MAPTRIANGLE (MapConv%(N%% + 1, M%% + 1, 0, 0), MapConv%(N%% + 1, M%% + 1, 0, 1))-(MapConv%(N%% + 1, M%%, 0, 0), MapConv%(N%% + 1, M%%, 0, 1))-(MapConv%(N%%, M%%, 0, 0), MapConv%(N%%, M%%, 0, 1)), Cyperium&(P%%) TO(Cx%, Cy%, Cz%)-(MapConv%(N%% + 1, M%%, 1, 0) + BallStats!(P%%, 1), MapConv%(N%% + 1, M%%, 1, 1) + BallStats!(P%%, 2), MapConv%(N%% + 1, M%%, 1, 2) + BallStats!(P%%, 3) - PerspDist%)-(Ax%, Ay%, Az%)
                '_MAPTRIANGLE (MapConv%(N%%, M%%, 0, 0), MapConv%(N%%, M%%, 0, 1))-(MapConv%(N%%, M%% + 1, 0, 0), MapConv%(N%%, M%% + 1, 0, 1))-(MapConv%(N%% + 1, M%% + 1, 0, 0), MapConv%(N%% + 1, M%% + 1, 0, 1)), Cyperium&(P%%) TO(MapConv%(N%%, M%%, 1, 0) + BallStats!(P%%, 1), MapConv%(N%%, M%%, 1, 1) + BallStats!(P%%, 2), MapConv%(N%%, M%%, 1, 2) + BallStats!(P%%, 3) - PerspDist%)-(MapConv%(N%%, M%% + 1, 1, 0) + BallStats!(P%%, 1), MapConv%(N%%, M%% + 1, 1, 1) + BallStats!(P%%, 2), MapConv%(N%%, M%% + 1, 1, 2) + BallStats!(P%%, 3) - PerspDist%)-(MapConv%(N%% + 1, M%% + 1, 1, 0) + BallStats!(P%%, 1), MapConv%(N%% + 1, M%% + 1, 1, 1) + BallStats!(P%%, 2), MapConv%(N%% + 1, M%% + 1, 1, 2) + BallStats!(P%%, 3) - PerspDist%)
                '_MAPTRIANGLE (MapConv%(N%% + 1, M%% + 1, 0, 0), MapConv%(N%% + 1, M%% + 1, 0, 1))-(MapConv%(N%% + 1, M%%, 0, 0), MapConv%(N%% + 1, M%%, 0, 1))-(MapConv%(N%%, M%%, 0, 0), MapConv%(N%%, M%%, 0, 1)), Cyperium&(P%%) TO(MapConv%(N%% + 1, M%% + 1, 1, 0) + BallStats!(P%%, 1), MapConv%(N%% + 1, M%% + 1, 1, 1) + BallStats!(P%%, 2), MapConv%(N%% + 1, M%% + 1, 1, 2) + BallStats!(P%%, 3) - PerspDist%)-(MapConv%(N%% + 1, M%%, 1, 0) + BallStats!(P%%, 1), MapConv%(N%% + 1, M%%, 1, 1) + BallStats!(P%%, 2), MapConv%(N%% + 1, M%%, 1, 2) + BallStats!(P%%, 3) - PerspDist%)-(MapConv%(N%%, M%%, 1, 0) + BallStats!(P%%, 1), MapConv%(N%%, M%%, 1, 1) + BallStats!(P%%, 2), MapConv%(N%%, M%%, 1, 2) + BallStats!(P%%, 3) - PerspDist%)
            NEXT M%%
            _MAPTRIANGLE (MapConv%(N%%, NoAlphas%% - 1, 0, 0), MapConv%(N%%, NoAlphas%% - 1, 0, 1))-(128, 128)-(MapConv%(N%% + 1, NoAlphas%% - 1, 0, 0), MapConv%(N%% + 1, NoAlphas%% - 1, 0, 1)), Cyperium&(P%%) TO(Bx%, By%, Bz%)-(BallStats!(P%%, 1), BallStats!(P%%, 2), BallStats!(P%%, 3) + Rad1%% - PerspDist%)-(Cx%, Cy%, Cz%)
            '_MAPTRIANGLE (MapConv%(N%%, NoAlphas%% - 1, 0, 0), MapConv%(N%%, NoAlphas%% - 1, 0, 1))-(128, 128)-(MapConv%(N%% + 1, NoAlphas%% - 1, 0, 0), MapConv%(N%% + 1, NoAlphas%% - 1, 0, 1)), Cyperium&(P%%) TO(MapConv%(N%%, NoAlphas%% - 1, 1, 0) + BallStats!(P%%, 1), MapConv%(N%%, NoAlphas%% - 1, 1, 1) + BallStats!(P%%, 2), MapConv%(N%%, NoAlphas%% - 1, 1, 2) + BallStats!(P%%, 3) - PerspDist%)-(BallStats!(P%%, 1), BallStats!(P%%, 2), BallStats!(P%%, 3) + Rad1%% - PerspDist%)-(MapConv%(N%% + 1, NoAlphas%% - 1, 1, 0) + BallStats!(P%%, 1), MapConv%(N%% + 1, NoAlphas%% - 1, 1, 1) + BallStats!(P%%, 2), MapConv%(N%% + 1, NoAlphas%% - 1, 1, 2) + BallStats!(P%%, 3) - PerspDist%)
        NEXT N%%
    NEXT N1%%

    'rotate around z- axis
    Zaxis! = Zaxis! + ZRot!
    IF Zaxis! > Pi! THEN
        Zaxis! = Zaxis! - 2 * Pi!
    ELSEIF Zaxis! < -Pi! THEN
        Zaxis! = Zaxis! + 2 * Pi!
    END IF

    'rotate around y- axis
    Yaxis! = Yaxis! + YRot!
    IF Yaxis! > Pi! THEN
        Yaxis! = Yaxis! - 2 * Pi!
    ELSEIF Yaxis! < -Pi! THEN
        Yaxis! = Yaxis! + 2 * Pi!
    END IF

    'rotate around x- axis
    Xaxis! = Xaxis! + XRot!
    IF Xaxis! > Pi! THEN
        Xaxis! = Xaxis! - 2 * Pi!
    ELSEIF Xaxis! < -Pi! THEN
        Xaxis! = Xaxis! + 2 * Pi!
    END IF

    IF TIMER > ZStart! + ZTime% THEN
        ZRot! = (RND - 0.5) * 0.0011
        ZTime% = 15 + INT(47 * RND)
        ZStart! = TIMER
        RANDOMIZE (ZStart!)
    END IF
    IF TIMER > YStart! + YTime%% THEN
        YRot! = (RND - 0.5) * 0.0011
        YTime%% = 15 + INT(47 * RND)
        YStart! = TIMER
    END IF
    IF TIMER > XStart! + XTime% THEN
        XRot! = (RND - 0.5) * 0.0011
        XTime% = 15 + INT(47 * RND)
        XStart! = TIMER
    END IF

    IF _KEYHIT = 27 THEN Stereo` = False 'Esc  to quit

    _DISPLAY

WEND

SYSTEM

FUNCTION MakeHardware& (Imagename&)
    MakeHardware& = _COPYIMAGE(Imagename&, 33)
    _FREEIMAGE Imagename&
END FUNCTION

Richard
« Last Edit: April 22, 2018, 09:48:15 am by Richard Notley »
QB64 Projects: https://www.dropbox.com/s/yzn5uf4dzztao2f/QB64%20Projects.pdf?dl=0

bplus

  • Hero Member
  • *****
  • Posts: 756
  • B = B + _
Re: 3D Bouncing Balls
« Reply #1 on: April 21, 2018, 07:49:28 am »
Hi Richard,

I like seeing how balls are growing as come closer and shrinking as the go away from observer but the balls are taking weird bounces, is that rotating cube (from the other thread) still acting on the balls? If so, how can balls escape out to edge of screen when they grow big?
« Last Edit: April 21, 2018, 07:56:35 am by bplus »
Will you still love me, will you still need me, when I'm (QB) 64?

Richard Notley

  • Sr. Member
  • ****
  • Posts: 349
  • QwerKey
Re: 3D Bouncing Balls
« Reply #2 on: April 21, 2018, 08:52:18 am »
bplus,  yes you are correct about the bounces.  The balls are moving inside an invisible cube and bouncing off the sides (the cube is rotating randomly about the three axes).  In this version, I have not displayed the cube.  The balls will not get displayed if the z- dimension (the direction into/out of the screen) is > -1 :- in _MAPTRIANGLE(3D) the allowed values of z- are -1 to -10000.  This version is about demonstrating the mapping of the surface of a solid 3D object (ball).  In fact the program only maps the front hemisphere of each ball.  I have still to work out whether the distortions of the spheres are just an artefact of the _MAPTRIANGLE perspective maths, or whether I've done something stupid.

Richard
QB64 Projects: https://www.dropbox.com/s/yzn5uf4dzztao2f/QB64%20Projects.pdf?dl=0

FellippeHeitor

  • QB64 Partner Site Owner
  • Hero Member
  • *
  • Posts: 1885
  • LET IT = BE
    • QB64.org
Re: 3D Bouncing Balls
« Reply #3 on: April 21, 2018, 02:41:28 pm »
Nice one, Richard. I do see the sphere distortion at the screen edges, hope you sort it out and let us know soon.
- InForm for QB64 http://qb64.org/inform

- vWATCH64 (debugger for QB64) http://bit.ly/vWATCH64v1-103

- Games: http://bit.ly/2048_qb64 * http://bit.ly/ClonedShades_qb64source * http://bit.ly/2aqK866 * http://bit.ly/SpaceshipQB64 * http://bit.ly/2rD1pPP

Petr

  • Hero Member
  • *****
  • Posts: 656
Re: 3D Bouncing Balls
« Reply #4 on: April 22, 2018, 10:16:29 am »
This is a beautiful code. Again I can something to learn.  :)
Coding is relax.

  • Print