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