Retro Programming Nostalgia VI: Exploring the Hyperspace

Henk Rogers: Um, I like Pascal. Assembler is my go-to. But never underestimate…
Alexey Pajitnov: …the power of BASIC.

From the movie Tetris (2023).

It has been a long while that I wanted to write this article. The usual motivation is to propose another of my BASIC programming explorations performed in the 80s on my Philips MSX VG-8010 and Amiga 500 microcomputer. The exploration was encouraged by the reading of another of the brilliant articles by A. K. Dewdney in his column “Ricreazioni al Calcolatore” (Computer Recreation) of Le Scienze, the edition in Italian of Scientific American [1]. Dewdney’s article was inspired by the beautiful book by Thomas F. Banchoff [2] who pioneered in the early 1990s the study using computer graphics of hyperdimensional objects.

The exploration of multidimensional space is a recurring theme in many excellent popular science books. It has inspired generations of science fiction writers, artists, and cinema directors in producing fascinating stories. Starting from the earlier Banchoff ‘ experimentation [3] to the recent Hollywood movie such as “Interstellar,” the graphical 3D representation of multidimensional objects has evolved thanks to the progress of computer graphics that has given a huge help to our fantasy in figuring out how these objects project in our tridimensional world.

A four-dimensional hypercube or tesseract, can be expressed using coordinates in four-dimensional space. Let’s denote a point in four-dimensional space by four coordinates (x, y, z, w), where each coordinate represents a position along a different axis. For simplicity, we’ll assume each coordinate can take on values from -1 to 1, although the range can be adjusted as needed. To construct a tesseract, we can start with the eight vertices of a 3D cube, which are given by the combinations of ±1 for each coordinate:

  1. (-1, -1, -1, -1)
  2. (-1, -1, -1, 1)
  3. (-1, -1, 1, -1)
  4. (-1, -1, 1, 1)
  5. (-1, 1, -1, -1)
  6. (-1, 1, -1, 1)
  7. (-1, 1, 1, -1)
  8. (-1, 1, 1, 1)

Now, to construct the tesseract, we connect these vertices in such a way that each vertex is connected to four other vertices, representing the edges of the tesseract. This results in a total of 16 edges.

The rotation of the hypercube along one of the axes of the reference frame involves using transformation matrices to represent the rotation operation. Let’s consider rotating the tesseract along one of its axes, say the (x)-axis, for example:

  1. Choose the rotation axis: Let’s say we’re rotating the tesseract along the (x)-axis. In a four-dimensional Cartesian coordinate system, the (x)-axis corresponds to the axis where the (x) coordinate is the only non-zero value.
  2. Define the rotation angle: As before, let (\theta ) represent the rotation angle.
  3. Construct the rotation matrix: The rotation matrix for rotating a point ( (x, y, z, w) ) about the (x)-axis by an angle ( \theta ) is simplified because it only involves rotations in the (yzw)-plane (the plane perpendicular to the (x)-axis). The rotation matrix in this case is:

\mathbf{R} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos \theta & -\sin \theta & 0 \\ 0 & \sin \theta & \cos \theta & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}

  1. Perform the rotation: Multiply each vertex of the tesseract by the rotation matrix ( \mathbf{R} ) to obtain the rotated vertices.

This rotation matrix performs a rotation about the (x)-axis while leaving the (x)-coordinate unchanged. It rotates the (yzw)-plane around the (x)-axis by an angle ( \theta ).

By similarly defining rotation matrices for rotations about the (y)-axis and (z)-axis, you can achieve rotations along those axes as well. This simplified approach should make it easier to understand and implement rotations of the hypercube along the axes of the reference frame.

Now we look to the BASIC program to plot the hypercube as a projection in the 3D space (to be correct, the program projects these 3D projections onto a 2D space). The source code reported in the appendix is an adaptation of my source code. In the following Figure, a screenshot of the program is shown.

By using the key indicated on the top menu, it is possible to modify the rotation plane, zoom in and out, and change the representation from perspective to orthonormal.

I hope you can enjoy diving in the Tesseract!

REFERENCES

[1] Dewdney, A. K. “Computer Recreations: A Program for Rotating Hypercubes Induces Four-Dimensional Dementia.” Sci. Amer. 254, 14-23, Mar. 1986.

[2] Banchoff TF.. “Beyond the third dimension.” 1990. Scientific American Library.

APPENDIX

This is the current version of the program. The comments are left in Italian as in the original version of the code. It is also very likely to contain a bug. This means that if some of you decide to try and improve I would love to see the improved version of the code!

'======================================================================
' IPERCUBO: RUOTA UN IPERCUBO
'
' PROGRAMMA  : IPERCUBO.BAS
' DESCRIZIONE: QUESTO PROGRAMMA PERMETTE DI DISEGNARE E RUOTARE
'              UN IPERCUBO INTORNO AGLI ASSI PERPENDICOLARE ALLE SUE
'              FACCE. IL PROGRAMMA SI BASA SUL ALGORITMO DESCRITTO
'              DA DEWDENEY NELLA RUBRICA
'              "RICREAZIONI AL CALCOLATORE" NEL NUMERO 162 (Febbraio 1982)
'              DI LE SCIENZE.
' AUTORE     : D. ROCCATANO
' CREATO NEL : 1985
'================================================================
'

Dim Shared VERT(16, 4), CUBO(16, 4), TRAC(33)
Dim Shared ROTE(4, 4), ROTM(4, 4)
Dim Shared AN, f, f1, FAC, TA, ZL, ORTO

TA = 25
ZL = -40
PI = Atn(1) * 4
FAC = 2 * PI / 360.
ORTO = 0

' CARICA LE COORDINATE DEI VERTICI
For I = 0 To 15
    For J = 1 To 4
        Read S
        VERT(I, J) = S
    Next J
Next I

Data -1,-1,-1,-1
Data -1,-1,-1,1
Data -1,-1,1,-1
Data -1,-1,1,1
Data -1,1,-1,-1
Data -1,1,-1,1
Data -1,1,1,-1
Data -1,1,1,1
Data 1,-1,-1,-1
Data 1,-1,-1,1
Data 1,-1,1,-1
Data 1,-1,1,1
Data 1,1,-1,-1
Data 1,1,-1,1
Data 1,1,1,-1
Data 1,1,1,1


' CARICA LA SEQUENZA DI TRACCIAMENTO DEI LATI
For I = 0 To 32
    Read S
    TRAC(I) = S
Next I
' FACCE
Data 0,1,3,2,6,14,10,8,9,11,3,7,15
Data 14,12,13,9,1,5,7,6,4,12,8,0,4,5,13,15,11,10,2,0

' PREPARA GLI ARRAYS
' DUPLICA LA MATRICE DEI VERTICI
For I = 1 To 4
    For J = 1 To 4
        Read S
        ROTM(I, J) = S
    Next J
Next I
Data 1,0,0,0
Data 0,1,0,0
Data 0,0,1,0
Data 0,0,0,1

'======================================================
' PROGRAMMA PRINCIPALE
'
Screen _NewImage(800, 725, 256), 1, 0

Cls
Color 1, 15
Out &H3C8, 0
Out &H3C9, 63
Out &H3C9, 63
Out &H3C9, 63
stp = 0
Do
    MENU
    AN = 0

    ' COORDINATE INIZIALI DEL CUBO EXPANSE DEL FATTORE TA
Loop Until stp <> 0
End

Sub SCALA_IPERCUBO
    Shared CUBO, VERT
    Shared TA

    For I = 0 To 15
        For J = 1 To 4
            CUBO(I, J) = VERT(I, J) * TA
        Next J
    Next I

End Sub


Sub STEPROT
    Shared CUBO, VERT, TRAC
    Shared ROTE, ROTM
    Shared AN, f, f1, FAC, TA, ZL, ORTO

    Dim TEMP(16, 4)
    SCALA_IPERCUBO
    PREPARA_ROT

    Do
        _Limit 1000
        Cls
        Locate 1, 2: Print "TASTI DI CONTROLLO ('ESC' PER USCIRE)"
        Locate 2, 2: Print "Piani selezionati (X=1,Y=2,Z=3,W=4): ", f, f1
        Locate 3, 2: Print "1:X x Y | 2:X x Z | 3;X x W | 4:Y x Z | 5:Y x W | 6: Z x W "
        Locate 4, 2: Print "Fattore di scala: ", TA, "(+/-: Ingrandisce/Riduce l'ipercubo)"
        Locate 5, 2: Print "Distanza prospettica: ", ZL, "(V/v: Aumenta/Riduce la distanza)"
        Locate 6, 2: Print "Proiezione Ortografica(1)/Prospettica(0): ", ORTO, "(P/p Cambia proiezione)"
        For I = 0 To 15
            For J = 1 To 4
                D = 0
                For K = 1 To 4
                    D = D + (CUBO(I, K) * ROTE(K, J))
                Next K
                TEMP(I, J) = D
            Next J
        Next I
        For I = 0 To 15
            For J = 1 To 4
                CUBO(I, J) = TEMP(I, J)
            Next J
        Next I

        For I = 0 To 32
            M = TRAC(I)
            N = TRAC(I + 1)
            If (ORTO = 0) Then
                Z = ZL - CUBO(M, 3)
                Z1 = ZL - CUBO(N, 3)
                FACT = ZL / Z
                FACT1 = ZL / Z1
            Else
                FACT = 1
                FACT1 = 1
            End If

            Line (400 + FACT * CUBO(M, 1), 350 - FACT * CUBO(M, 2))-(400 + FACT1 * CUBO(N, 1), 350 - FACT1 * CUBO(N, 2)), 4

            '         Line (400 + ZL * CUBO(M, 1) / Z, 350 - ZL * CUBO(M, 2) / Z)-(400 + ZL * CUBO(N, 1) / Z1, 350 - ZL * CUBO(N, 2) / Z1), 4
        Next I
        K$ = InKey$
        Locate 9, 2: Print K$
        If (K$ <> "") Then CONTROLLO K$
        _Display
    Loop While K$ <> Chr$(27)

End Sub

Sub CONTROT
    Dim TEMP(16, 4)

    Shared CUBO, VERT, TRAC
    Shared ROTE, ROTM
    Shared AN, f, f1, FAC, TA, ZL

    For I = 0 To 15
        For J = 1 To 4
            CUBO(I, J) = VERT(I, J) * TA
        Next J
    Next I
    PREPARA_ROT

    Do
        _Limit 1000
        Cls
        Locate 2, 2: Print "PREMI IL TASTO 'ESC' PER USCIRE"

        For I = 0 To 15
            For J = 1 To 4
                D = 0
                For K = 1 To 4
                    D = D + (CUBO(I, K) * ROTE(K, J))
                Next K
                TEMP(I, J) = D
            Next J
        Next I
        For I = 0 To 15
            For J = 1 To 4
                CUBO(I, J) = TEMP(I, J)
            Next J
        Next I

        For I = 0 To 32
            M = TRAC(I)
            N = TRAC(I + 1)
            Z = ZL - CUBO(M, 3)
            Z1 = ZL - CUBO(N, 3)
            Line (400 + ZL * CUBO(M, 1) / Z, 350 - ZL * CUBO(M, 2) / Z)-(400 + ZL * CUBO(N, 1) / Z1, 350 - ZL * CUBO(N, 2) / Z1), 4
        Next I
        _Display
    Loop While InKey$ <> Chr$(27)
End Sub

Sub CONTROLLO (Key$)
    Shared f, f1
    If (Key$ = "1") Then f = 1: f1 = 2
    If (Key$ = "2") Then f = 1: f1 = 3
    If (Key$ = "3") Then f = 1: f1 = 4
    If (Key$ = "4") Then f = 2: f1 = 3
    If (Key$ = "5") Then f = 2: f1 = 4
    If (Key$ = "6") Then f = 3: f1 = 4
    If (Key$ = "+") Then
        TA = TA + 5
        SCALA_IPERCUBO
    End If
    If (Key$ = "-") Then
        TA = TA - 5
        If TA < 5 Then TA = 5
        SCALA_IPERCUBO
    End If
    If (Key$ = "V") Then
        ZL = ZL + 5
        SCALA_IPERCUBO
    End If
    If (Key$ = "v") Then
        ZL = ZL - 5
        SCALA_IPERCUBO
    End If
    If (Key$ = "P") Then ORTO = 0
    If (Key$ = "p") Then ORTO = 1
    PREPARA_ROT

End Sub

Sub MENU
    Shared CUBO, VERT
    Shared ROTE, ROTM
    Shared AN, f, f1, FAC, TA, ZL

    '
    '***** MENU I *****
    '
    f = 1
    f1 = 4
    Cls
    HH = 0
    Do
        Locate 15, 30: Print "SCEGLI IL PIANIO DI ROTAZIONE"
        Locate 16, 30: Print "1: ROTAZIONE CONTINUA"
        Locate 17, 30: Print "2: ROTAZIONE CONTROLLATA"
        Locate 18, 30: Print "3: QUIT"
        Locate 20, 30: Input "Scegli:     "; HH
    Loop Until HH > 0 And HH < 4
    If (HH = 1) Then
        Cls
        IP = 0
        Do
            Locate 15, 30: Print "PIANI DI ROTAZIONE"
            Locate 16, 30: Print "1: X x Y "
            Locate 17, 30: Print "2: X x Z "
            Locate 18, 30: Print "3; X x W "
            Locate 19, 30: Print "4: Y x Z "
            Locate 20, 30: Print "5: Y x W "
            Locate 21, 30: Print "6: Z x W "
            Locate 25, 30: Input "Scegli:     "; IP
            'Locate 19, 30: Input "Fattore di scala        "; TA
            'Locate 20, 30: Input "Distanza della sorgente "; ZL
        Loop Until IP > 0 And IP < 8

        If (IP = 1) Then f = 1: f1 = 2
        If (IP = 2) Then f = 1: f1 = 3
        If (IP = 3) Then f = 1: f1 = 4
        If (IP = 4) Then f = 2: f1 = 3
        If (IP = 5) Then f = 2: f1 = 4
        If (IP = 6) Then f = 3: f1 = 4
        CONTROT
    End If
    If (HH = 2) Then STEPROT
    If (HH = 3) Then End
End Sub

Sub PREPARA_ROT
    Shared ROTE, ROTM
    Shared AN, f, f1, FAC, TA, ZL
    ' PREPARA LA MATRICE DI ROTAZIONE

    AN = AN + 0.036
    ANG = AN * FAC

    A = Cos(ANG)
    B = Sin(ANG)

    For I = 1 To 4
        For J = 1 To 4
            ROTE(I, J) = ROTM(I, J)
        Next J
    Next I

    ROTE(f, f) = A
    ROTE(f1, f1) = A
    ROTE(f, f1) = -B
    ROTE(f1, f) = B
End Sub

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.