'\r
' Changelog:\r
' 2003.08, Initial version\r
-' 2024, Improved program readability using AI\r
-\r
-\r
-DECLARE SUB chlin (x1!, y1!, z1!, q1!, x2!, y2!, z2!, q2!)\r
-DECLARE SUB rot (x1!, y1!, z1!, q1!, x4!, y4!, z4!, q4!)\r
-DECLARE SUB setpal ()\r
-DECLARE SUB getp (x1!, y1!, z1!, q1!, x2!, y2!, z2!, q2!, n!, rx!, ry!, rz!, rq!)\r
-DECLARE SUB qpyra (x1!, y1!, z1!, q1!, x2!, y2!, z2!, q2!, x3!, y3!, z3!, q3!, x4!, y4!, z4!, q4!, x5!, y5!, z5!, q5!)\r
-DECLARE FUNCTION vahe! (x1!, y1!, z1!, q1!, x2!, y2!, z2!, q2!)\r
-DIM SHARED siz\r
-DIM SHARED an1, an2, an3, an4, an5, an6\r
-DIM SHARED myx, myy, myz, myq\r
+' 2024 - 2025, Improved program readability\r
+\r
+' Declare subroutines and functions that will be used in the program\r
+DECLARE SUB CalculateInterpolatedLine (originalX1!, originalY1!, originalZ1!, originalQ1!, originalX2!, originalY2!, originalZ2!, originalQ2!)\r
+DECLARE SUB RotatePoint (x1!, y1!, z1!, q1!, x4!, y4!, z4!, q4!)\r
+DECLARE SUB SetupPalette ()\r
+DECLARE SUB GetPointAtDistance (x1!, y1!, z1!, q1!, x2!, y2!, z2!, q2!, distanceFactor!, rx!, ry!, rz!, rq!)\r
+DECLARE SUB RenderPentachoron (ox1!, oy1!, oz1!, oq1!, ox2!, oy2!, oz2!, oq2!, ox3!, oy3!, oz3!, oq3!, ox4!, oy4!, oz4!, oq4!, ox5!, oy5!, oz5!, oq5!)\r
+DECLARE FUNCTION CalculateDistance (x1!, y1!, z1!, q1!, x2!, y2!, z2!, q2!)\r
+\r
+' Shared variables that can be accessed from any subroutine\r
+DIM SHARED screenSize\r
+DIM SHARED angleXZ, angleYZ, angleXY, angleQX, angleQY, angleQZ\r
+DIM SHARED cameraX, cameraY, cameraZ, cameraQ\r
DIM SHARED pi\r
-DIM SHARED s1, s2, s3, s4, s5, s6\r
-DIM SHARED c1, c2, c3, c4, c5, c6\r
+DIM SHARED sineXZ, sineYZ, sineXY, sineQX, sineQY, sineQZ\r
+DIM SHARED cosineXZ, cosineYZ, cosineXY, cosineQX, cosineQY, cosineQZ\r
\r
-DIM SHARED px(1 TO 10)\r
-DIM SHARED py(1 TO 10)\r
-DIM SHARED pm\r
-DIM SHARED frm\r
+' Arrays to store projected points and other drawing information\r
+DIM SHARED projectedX(1 TO 10)\r
+DIM SHARED projectedY(1 TO 10)\r
+DIM SHARED pointCount\r
+DIM SHARED frame\r
\r
+' Display control instructions to the user\r
PRINT ""\r
PRINT " Use keys:"\r
PRINT " Rotate:"\r
PRINT " ESC - to quit program"\r
PRINT\r
PRINT " Press any key to continue..."\r
-a$ = INPUT$(1)\r
+in$ = INPUT$(1)\r
\r
+' Initialize pi value for rotation calculations\r
pi = 3.1415\r
\r
-' Angles for rotation along different axes\r
-an1 = pi * .5\r
-an2 = an1\r
-an3 = an1\r
-an4 = an1\r
-an5 = an1\r
-an6 = an1\r
-\r
-' Current position in the 4D space\r
-myx = 0\r
-myy = 0\r
-myz = 0\r
-myq = .5\r
-\r
+' Initialize rotation angles for each axis\r
+angleXZ = pi * .5\r
+angleYZ = angleXZ\r
+angleXY = angleXZ\r
+angleQX = angleXZ\r
+angleQY = angleXZ\r
+angleQZ = angleXZ\r
+\r
+' Set initial camera position in 4D space\r
+cameraX = 0\r
+cameraY = 0\r
+cameraZ = 0\r
+cameraQ = .5\r
+\r
+' Set graphics mode to 640x480 with 16 colors\r
SCREEN 12\r
-setpal\r
+' Setup the color palette for rendering\r
+SetupPalette\r
\r
-1\r
+MainLoop:\r
+' Clear screen for new frame\r
CLS\r
\r
-' Calculate sine and cosine for each rotation angle\r
-s1 = SIN(an1): c1 = COS(an1)\r
-s2 = SIN(an2): c2 = COS(an2)\r
-s3 = SIN(an3): c3 = COS(an3)\r
-s4 = SIN(an4): c4 = COS(an4)\r
-s5 = SIN(an5): c5 = COS(an5)\r
-s6 = SIN(an6): c6 = COS(an6)\r
+' Calculate sine and cosine values for each rotation angle\r
+sineXZ = SIN(angleXZ): cosineXZ = COS(angleXZ)\r
+sineYZ = SIN(angleYZ): cosineYZ = COS(angleYZ)\r
+sineXY = SIN(angleXY): cosineXY = COS(angleXY)\r
+sineQX = SIN(angleQX): cosineQX = COS(angleQX)\r
+sineQY = SIN(angleQY): cosineQY = COS(angleQY)\r
+sineQZ = SIN(angleQZ): cosineQZ = COS(angleQZ)\r
\r
-' Render the 3D tetrahedrons with varying brightness\r
-FOR frm = 1 TO 15 STEP 3\r
- qpyra -10, -10, -10, 0, 10, -10, -10, 0, 0, -10, 10, 0, 0, 10, 0, 0, 0, 0, 0, 10\r
-NEXT frm\r
+' Render multiple frames of the pentachoron with varying depth\r
+FOR frame = 1 TO 15 STEP 3\r
+ ' Render a pentachoron (5-cell) with the current camera position and rotation\r
+ RenderPentachoron -10, -10, -10, 0, 10, -10, -10, 0, 0, -10, 10, 0, 0, 10, 0, 0, 0, 0, 0, 10\r
+NEXT frame\r
\r
-a$ = INPUT$(1)\r
+' Get user input for camera control\r
+in$ = INPUT$(1)\r
\r
' Handle user input for rotation and movement\r
-SELECT CASE a$\r
+SELECT CASE in$\r
CASE CHR$(27)\r
+ ' ESC key pressed - exit program\r
SYSTEM\r
CASE "q"\r
- an1 = an1 + .1\r
+ ' Increase rotation angle along XZ axis\r
+ angleXZ = angleXZ + .1\r
CASE "w"\r
- an1 = an1 - .1\r
+ ' Decrease rotation angle along XZ axis\r
+ angleXZ = angleXZ - .1\r
CASE "a"\r
- an2 = an2 + .1\r
+ ' Increase rotation angle along YZ axis\r
+ angleYZ = angleYZ + .1\r
CASE "s"\r
- an2 = an2 - .1\r
+ ' Decrease rotation angle along YZ axis\r
+ angleYZ = angleYZ - .1\r
CASE "z"\r
- an3 = an3 + .1\r
+ ' Increase rotation angle along XY axis\r
+ angleXY = angleXY + .1\r
CASE "x"\r
- an3 = an3 - .1\r
+ ' Decrease rotation angle along XY axis\r
+ angleXY = angleXY - .1\r
CASE "e"\r
- an4 = an4 + .1\r
+ ' Increase rotation angle along QX axis\r
+ angleQX = angleQX + .1\r
CASE "r"\r
- an4 = an4 - .1\r
+ ' Decrease rotation angle along QX axis\r
+ angleQX = angleQX - .1\r
CASE "d"\r
- an5 = an5 + .1\r
+ ' Increase rotation angle along QY axis\r
+ angleQY = angleQY + .1\r
CASE "f"\r
- an5 = an5 - .1\r
+ ' Decrease rotation angle along QY axis\r
+ angleQY = angleQY - .1\r
CASE "c"\r
- an6 = an6 + .1\r
+ ' Increase rotation angle along QZ axis\r
+ angleQZ = angleQZ + .1\r
CASE "v"\r
- an6 = an6 - .1\r
+ ' Decrease rotation angle along QZ axis\r
+ angleQZ = angleQZ - .1\r
\r
' Handle user input for movement in the 4D space\r
CASE "4"\r
- myx = myx - 3\r
+ ' Move camera left along X axis\r
+ cameraX = cameraX - 3\r
CASE "6"\r
- myx = myx + 3\r
+ ' Move camera right along X axis\r
+ cameraX = cameraX + 3\r
CASE "8"\r
- myz = myz + 3\r
+ ' Move camera forward along Z axis\r
+ cameraZ = cameraZ + 3\r
CASE "2"\r
- myz = myz - 3\r
+ ' Move camera backward along Z axis\r
+ cameraZ = cameraZ - 3\r
CASE "7"\r
- myy = myy + 3\r
+ ' Move camera up along Y axis\r
+ cameraY = cameraY + 3\r
CASE "1"\r
- myy = myy - 3\r
+ ' Move camera down along Y axis\r
+ cameraY = cameraY - 3\r
CASE "+"\r
- myq = myq + .3\r
+ ' Move camera forward along Q axis (4th dimension)\r
+ cameraQ = cameraQ + .3\r
CASE "-"\r
- myq = myq - .3\r
+ ' Move camera backward along Q axis (4th dimension)\r
+ cameraQ = cameraQ - .3\r
\r
END SELECT\r
\r
-GOTO 1\r
+' Loop back to render next frame\r
+GOTO MainLoop\r
\r
-' Subroutine to calculate the linear interpolation between two points\r
-SUB chlin (ox1, oy1, oz1, oq1, ox2, oy2, oz2, oq2)\r
- x1 = ox1: y1 = oy1: z1 = oz1: q1 = oq1\r
- x2 = ox2: y2 = oy2: z2 = oz2: q2 = oq2\r
+' Function to calculate the distance between two points in 4D space\r
+FUNCTION CalculateDistance (x1, y1, z1, q1, x2, y2, z2, q2)\r
+ ' Calculate Euclidean distance in 4D space\r
+ CalculateDistance = SQR((x1 - x2) ^ 2 + (y1 - y2) ^ 2 + (z1 - z2) ^ 2 + (q1 - q2) ^ 2)\r
+END FUNCTION\r
\r
- ' Swap points if the first point is behind the current position in the fourth dimension\r
- IF (q1 > myq) AND (q2 < myq) THEN\r
+' Subroutine to calculate the linear interpolation between two points\r
+SUB CalculateInterpolatedLine (originalX1, originalY1, originalZ1, originalQ1, originalX2, originalY2, originalZ2, originalQ2)\r
+ ' Local variables to store coordinates of the two points\r
+ x1 = originalX1: y1 = originalY1: z1 = originalZ1: q1 = originalQ1\r
+ x2 = originalX2: y2 = originalY2: z2 = originalZ2: q2 = originalQ2\r
+\r
+ ' If the first point is in front of the camera and the second is behind,\r
+ ' swap them to ensure proper rendering order\r
+ IF (q1 > cameraQ) AND (q2 < cameraQ) THEN\r
SWAP x1, x2\r
SWAP y1, y2\r
SWAP z1, z2\r
SWAP q1, q2\r
END IF\r
\r
- ' Calculate the interpolated point if the first point is in front of the current position\r
- ' and the second point is behind it\r
- IF (q1 < myq) AND (q2 > myq) THEN\r
- vq = q2 - q1\r
- vmq = myq - q1\r
- jt = vmq / vq\r
- pm = pm + 1\r
- rx = (x2 - x1) * jt + x1\r
- ry = (y2 - y1) * jt + y1\r
- rz = (z2 - z1) * jt + z1 + 50\r
- px(pm) = rx / rz * 700 + 320\r
- py(pm) = ry / rz * 700 + 240\r
+ ' If the first point is in front of the camera and the second is behind,\r
+ ' calculate the intersection point where the line segment crosses the camera plane\r
+ IF (q1 < cameraQ) AND (q2 > cameraQ) THEN\r
+ ' Calculate the difference in Q coordinates\r
+ qDifference = q2 - q1\r
+ ' Calculate how far along the line segment we need to go to reach the camera plane\r
+ qToCamera = cameraQ - q1\r
+ ' Calculate the interpolation factor\r
+ interpolationFactor = qToCamera / qDifference\r
+ ' Increment point counter\r
+ pointCount = pointCount + 1\r
+ ' Calculate interpolated coordinates\r
+ interpolatedX = (x2 - x1) * interpolationFactor + x1\r
+ interpolatedY = (y2 - y1) * interpolationFactor + y1\r
+ interpolatedZ = (z2 - z1) * interpolationFactor + z1 + 50\r
+ ' Project 3D coordinates to 2D screen coordinates and store them\r
+ projectedX(pointCount) = interpolatedX / interpolatedZ * 700 + 320\r
+ projectedY(pointCount) = interpolatedY / interpolatedZ * 700 + 240\r
END IF\r
END SUB\r
\r
' Subroutine to get a point at a specific distance along the line segment\r
-SUB getp (x1, y1, z1, q1, x2, y2, z2, q2, n, rx, ry, rz, rq)\r
+SUB GetPointAtDistance (x1, y1, z1, q1, x2, y2, z2, q2, distanceFactor, rx, ry, rz, rq)\r
' Calculate the vector between the two points\r
- xv = x2 - x1\r
- yv = y2 - y1\r
- zv = z2 - z1\r
- qv = q2 - q1\r
-\r
- ' Calculate the interpolated point at the specified distance along the line segment\r
- rx = x1 + (xv * n)\r
- ry = y1 + (yv * n)\r
- rz = z1 + (zv * n)\r
- rq = q1 + (qv * n)\r
+ xVector = x2 - x1\r
+ yVector = y2 - y1\r
+ zVector = z2 - z1\r
+ qVector = q2 - q1\r
+\r
+ ' Calculate the coordinates of the point at the specified distance along the line segment\r
+ rx = x1 + (xVector * distanceFactor)\r
+ ry = y1 + (yVector * distanceFactor)\r
+ rz = z1 + (zVector * distanceFactor)\r
+ rq = q1 + (qVector * distanceFactor)\r
END SUB\r
\r
' Subroutine to render a 3D tetrahedron with varying brightness\r
-SUB qpyra (ox1, oy1, oz1, oq1, ox2, oy2, oz2, oq2, ox3, oy3, oz3, oq3, ox4, oy4, oz4, oq4, ox5, oy5, oz5, oq5)\r
-\r
- ' Adjust the coordinates for the current position in the 4D space\r
- ox1 = ox1 - myx\r
- oy1 = oy1 - myy\r
- oz1 = oz1 - myz\r
- oq1 = oq1 - myq - frm\r
-\r
- ox2 = ox2 - myx\r
- oy2 = oy2 - myy\r
- oz2 = oz2 - myz\r
- oq2 = oq2 - myq - frm\r
-\r
- ox3 = ox3 - myx\r
- oy3 = oy3 - myy\r
- oz3 = oz3 - myz\r
- oq3 = oq3 - myq - frm\r
-\r
- ox4 = ox4 - myx\r
- oy4 = oy4 - myy\r
- oz4 = oz4 - myz\r
- oq4 = oq4 - myq - frm\r
-\r
- ox5 = ox5 - myx\r
- oy5 = oy5 - myy\r
- oz5 = oz5 - myz\r
- oq5 = oq5 - myq - frm\r
-\r
- ' Rotate the points along the specified axes\r
- rot ox1, oy1, oz1, oq1, x1, y1, z1, q1\r
- rot ox2, oy2, oz2, oq2, x2, y2, z2, q2\r
- rot ox3, oy3, oz3, oq3, x3, y3, z3, q3\r
- rot ox4, oy4, oz4, oq4, x4, y4, z4, q4\r
- rot ox5, oy5, oz5, oq5, x5, y5, z5, q5\r
-\r
- ' Initialize the list of points to be drawn\r
- pm = 0\r
-\r
- ' Calculate the linear interpolation between each pair of points\r
- chlin x1, y1, z1, q1, x2, y2, z2, q2\r
- chlin x1, y1, z1, q1, x3, y3, z3, q3\r
- chlin x1, y1, z1, q1, x4, y4, z4, q4\r
- chlin x1, y1, z1, q1, x5, y5, z5, q5\r
-\r
- chlin x2, y2, z2, q2, x3, y3, z3, q3\r
- chlin x2, y2, z2, q2, x4, y4, z4, q4\r
- chlin x2, y2, z2, q2, x5, y5, z5, q5\r
-\r
- chlin x3, y3, z3, q3, x4, y4, z4, q4\r
- chlin x3, y3, z3, q3, x5, y5, z5, q5\r
-\r
- chlin x4, y4, z4, q4, x5, y5, z5, q5\r
-\r
- ' Draw lines between each pair of points\r
- FOR a = 1 TO pm\r
- FOR b = a + 1 TO pm\r
- LINE (px(a), py(a))-(px(b), py(b)), 15 - frm\r
- NEXT b\r
- NEXT a\r
+SUB RenderPentachoron (originalX1, originalY1, originalZ1, originalQ1, originalX2, originalY2, originalZ2, originalQ2, originalX3, originalY3, originalZ3, originalQ3, originalX4, originalY4, originalZ4, originalQ4, originalX5, originalY5, originalZ5 _\r
+, originalQ5)\r
+\r
+ ' Adjust coordinates based on camera position and frame depth\r
+ originalX1 = originalX1 - cameraX\r
+ originalY1 = originalY1 - cameraY\r
+ originalZ1 = originalZ1 - cameraZ\r
+ originalQ1 = originalQ1 - cameraQ - frame\r
+\r
+ originalX2 = originalX2 - cameraX\r
+ originalY2 = originalY2 - cameraY\r
+ originalZ2 = originalZ2 - cameraZ\r
+ originalQ2 = originalQ2 - cameraQ - frame\r
+\r
+ originalX3 = originalX3 - cameraX\r
+ originalY3 = originalY3 - cameraY\r
+ originalZ3 = originalZ3 - cameraZ\r
+ originalQ3 = originalQ3 - cameraQ - frame\r
+\r
+ originalX4 = originalX4 - cameraX\r
+ originalY4 = originalY4 - cameraY\r
+ originalZ4 = originalZ4 - cameraZ\r
+ originalQ4 = originalQ4 - cameraQ - frame\r
+\r
+ originalX5 = originalX5 - cameraX\r
+ originalY5 = originalY5 - cameraY\r
+ originalZ5 = originalZ5 - cameraZ\r
+ originalQ5 = originalQ5 - cameraQ - frame\r
+\r
+ ' Rotate all points based on current rotation angles\r
+ RotatePoint originalX1, originalY1, originalZ1, originalQ1, x1, y1, z1, q1\r
+ RotatePoint originalX2, originalY2, originalZ2, originalQ2, x2, y2, z2, q2\r
+ RotatePoint originalX3, originalY3, originalZ3, originalQ3, x3, y3, z3, q3\r
+ RotatePoint originalX4, originalY4, originalZ4, originalQ4, x4, y4, z4, q4\r
+ RotatePoint originalX5, originalY5, originalZ5, originalQ5, x5, y5, z5, q5\r
+\r
+ ' Initialize point counter\r
+ pointCount = 0\r
+\r
+ ' Calculate interpolated points for all edges of the pentachoron\r
+ CalculateInterpolatedLine x1, y1, z1, q1, x2, y2, z2, q2\r
+ CalculateInterpolatedLine x1, y1, z1, q1, x3, y3, z3, q3\r
+ CalculateInterpolatedLine x1, y1, z1, q1, x4, y4, z4, q4\r
+ CalculateInterpolatedLine x1, y1, z1, q1, x5, y5, z5, q5\r
+\r
+ CalculateInterpolatedLine x2, y2, z2, q2, x3, y3, z3, q3\r
+ CalculateInterpolatedLine x2, y2, z2, q2, x4, y4, z4, q4\r
+ CalculateInterpolatedLine x2, y2, z2, q2, x5, y5, z5, q5\r
+\r
+ CalculateInterpolatedLine x3, y3, z3, q3, x4, y4, z4, q4\r
+ CalculateInterpolatedLine x3, y3, z3, q3, x5, y5, z5, q5\r
+\r
+ CalculateInterpolatedLine x4, y4, z4, q4, x5, y5, z5, q5\r
+\r
+ ' Draw lines between each pair of interpolated points\r
+ FOR pointA = 1 TO pointCount\r
+ FOR pointB = pointA + 1 TO pointCount\r
+ ' Draw line with color based on frame depth (for varying brightness)\r
+ LINE (projectedX(pointA), projectedY(pointA))-(projectedX(pointB), projectedY(pointB)), 15 - frame\r
+ NEXT pointB\r
+ NEXT pointA\r
\r
END SUB\r
\r
' Subroutine to rotate a point along the specified axes\r
-SUB rot (x1, y1, z1, q1, x4, y4, z4, q4)\r
+SUB RotatePoint (x1, y1, z1, q1, x4, y4, z4, q4)\r
\r
' Rotate the point along the QX axis\r
- q2 = q1 * s4 - x1 * c4\r
- x2 = q1 * c4 + x1 * s4\r
+ q2 = q1 * sineQX - x1 * cosineQX\r
+ x2 = q1 * cosineQX + x1 * sineQX\r
\r
' Rotate the point along the QY axis\r
- q3 = q2 * s5 - y1 * c5\r
- y2 = q2 * c5 + y1 * s5\r
+ q3 = q2 * sineQY - y1 * cosineQY\r
+ y2 = q2 * cosineQY + y1 * sineQY\r
\r
' Rotate the point along the QZ axis\r
- q4 = q3 * s6 - z1 * c6\r
- z2 = q3 * c6 + z1 * s6\r
+ q4 = q3 * sineQZ - z1 * cosineQZ\r
+ z2 = q3 * cosineQZ + z1 * sineQZ\r
\r
' Rotate the point along the XZ axis\r
- x3 = x2 * s1 - z2 * c1\r
- z3 = x2 * c1 + z2 * s1\r
+ x3 = x2 * sineXZ - z2 * cosineXZ\r
+ z3 = x2 * cosineXZ + z2 * sineXZ\r
\r
' Rotate the point along the YZ axis\r
- y3 = y2 * s2 - z3 * c2\r
- z4 = y2 * c2 + z3 * s2\r
+ y3 = y2 * sineYZ - z3 * cosineYZ\r
+ z4 = y2 * cosineYZ + z3 * sineYZ\r
\r
' Rotate the point along the XY axis\r
- y4 = y3 * s3 - x3 * c3\r
- x4 = y3 * c3 + x3 * s3\r
+ y4 = y3 * sineXY - x3 * cosineXY\r
+ x4 = y3 * cosineXY + x3 * sineXY\r
\r
END SUB\r
\r
' Subroutine to set up the color palette\r
-SUB setpal\r
-\r
- ' Set up the color palette for the 4D rendering\r
- FOR a = 0 TO 15\r
- OUT &H3C8, a\r
- OUT &H3C9, a * 4\r
- OUT &H3C9, a * 4\r
- OUT &H3C9, a * 4\r
- LINE (a, 0)-(a, 400), a\r
- NEXT a\r
+SUB SetupPalette\r
+\r
+ ' Set up a grayscale color palette\r
+ FOR colorIndex = 0 TO 15\r
+ ' Set palette register\r
+ OUT &H3C8, colorIndex\r
+ ' Set RGB values (all equal for grayscale)\r
+ OUT &H3C9, colorIndex * 4\r
+ OUT &H3C9, colorIndex * 4\r
+ OUT &H3C9, colorIndex * 4\r
+ ' Draw a vertical line with this color to visualize the palette\r
+ LINE (colorIndex, 0)-(colorIndex, 400), colorIndex\r
+ NEXT colorIndex\r
\r
END SUB\r
\r
-' Function to calculate the distance between two points in 4D space\r
-FUNCTION vahe (x1, y1, z1, q1, x2, y2, z2, q2)\r
- vahe = SQR((x1 - x2) ^ 2 + (y1 - y2) ^ 2 + (z1 - z2) ^ 2 + (q1 - q2) ^ 2)\r
-END FUNCTION\r
-\r