Added screencasts for 3D graphics applications master
authorSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Sat, 30 Nov 2024 23:05:35 +0000 (01:05 +0200)
committerSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Sat, 30 Nov 2024 23:05:35 +0000 (01:05 +0200)
20 files changed:
Graphics/3D/3D game of life/3d life.bas [deleted file]
Graphics/3D/3D game of life/3dlife.dat [deleted file]
Graphics/3D/3D life.bas [new file with mode: 0755]
Graphics/3D/3D life.webm [new file with mode: 0644]
Graphics/3D/3dlife.dat [new file with mode: 0644]
Graphics/3D/bouncing cubes.webm [new file with mode: 0644]
Graphics/3D/gravi.bas [deleted file]
Graphics/3D/gravity particles.bas [new file with mode: 0755]
Graphics/3D/gravity particles.webm [new file with mode: 0644]
Graphics/3D/matrix math.bas [new file with mode: 0755]
Graphics/3D/matrix math.webm [new file with mode: 0644]
Graphics/3D/mtrxmath.bas [deleted file]
Graphics/3D/rocket simulator.bas [new file with mode: 0755]
Graphics/3D/rocket simulator.webm [new file with mode: 0644]
Graphics/3D/rocket.bas [deleted file]
Graphics/3D/stars.webm [new file with mode: 0644]
Graphics/3D/tank on the bridge.bas [new file with mode: 0755]
Graphics/3D/tank on the bridge.webm [new file with mode: 0644]
Graphics/3D/tank1.bas [deleted file]
Graphics/3D/tiled room.webm [new file with mode: 0644]

diff --git a/Graphics/3D/3D game of life/3d life.bas b/Graphics/3D/3D game of life/3d life.bas
deleted file mode 100755 (executable)
index e7f8bef..0000000
+++ /dev/null
@@ -1,360 +0,0 @@
-' Program renders rotating 3D animation from cubes.
-' Cubes appear and disappear according to Conway's Game of Life rules.
-'
-' By Svjatoslav Agejenko.
-' Email: svjatoslav@svjatoslav.eu
-' Homepage: http://www.svjatoslav.eu
-'
-' Changelog:
-' ?, Initial version
-' 2024, Improved program readability using AI
-
-DECLARE SUB PlaceCube (x!, y!, z!)
-DECLARE SUB DrawCube (x!, y!, z!)
-
-DECLARE SUB CreateCollisionData ()
-DECLARE SUB UpdateCollisionData ()
-DECLARE SUB RenderScene ()
-DECLARE SUB InitializeEnvironment ()
-DECLARE SUB StartGame ()
-
-DIM SHARED numPoints, numLines, pointCount, lineCount
-DIM SHARED pointsX(1 TO 3000), pointsY(1 TO 3000), pointsZ(1 TO 3000)
-DIM SHARED renderedPointsX(1 TO 7000), renderedPointsY(1 TO 7000)
-DIM SHARED originalRenderedPointsX(0 TO 9000), originalRenderedPointsY(0 TO 9000)
-DIM SHARED oldPointCount, oldLineCount
-DIM SHARED lineVertices1(1 TO 3800), lineVertices2(1 TO 3800), lineColors(1 TO 3800)
-DIM SHARED originalLineVertices1(1 TO 3800), originalLineVertices2(1 TO 3800)
-DIM SHARED myPositionX, myPositionY, myPositionZ
-DIM SHARED myPreviousPositionX, myPreviousPositionY, myPreviousPositionZ
-DIM SHARED angle1, angle2
-DIM SHARED angle1Str, angle2Str
-DIM SHARED frameCount
-
-DIM SHARED gameOfLifeGrid(1 TO 50, 1 TO 50)
-DIM SHARED nextGameOfLifeGrid(1 TO 50, 1 TO 50)
-
-StartGame
-
-angle1 = 1.5
-10
-frameCount = frameCount + 1
-
-CreateCollisionData
-RenderScene
-
-myPositionX = SIN(frameCount / 20) * 12
-myPositionY = SIN(frameCount / 50) * 10 + 15
-myPositionZ = COS(frameCount / 20) * 12
-
-angle1 = angle1 - .05
-angle2 = 2.2 + SIN(frameCount / 50) / 2
-
-inputKey$ = INKEY$
-IF inputKey$ <> "" THEN SYSTEM
-GOTO 10
-
-SUB CreateCollisionData
-pointCount = numPoints
-lineCount = numLines
-
-FOR y = 1 TO 50
-  FOR x = 1 TO 50
-    IF gameOfLifeGrid(x, y) = 1 THEN
-       v = ABS(x - 26) + ABS(y - 26) + frameCount
-       PlaceCube x - 25, SIN(v / 5) * 5, y - 25
-    END IF
- NEXT x
-NEXT y
-
-IF frameCount \ 10 = frameCount / 10 THEN
-
-FOR y = 2 TO 49
-FOR x = 2 TO 49
-c = gameOfLifeGrid(x - 1, y - 1)
-c = c + gameOfLifeGrid(x, y - 1)
-c = c + gameOfLifeGrid(x + 1, y - 1)
-c = c + gameOfLifeGrid(x - 1, y)
-c = c + gameOfLifeGrid(x + 1, y)
-c = c + gameOfLifeGrid(x - 1, y + 1)
-c = c + gameOfLifeGrid(x, y + 1)
-c = c + gameOfLifeGrid(x + 1, y + 1)
-
-IF gameOfLifeGrid(x, y) = 1 THEN
-  IF (c > 3) OR (c < 2) THEN nextGameOfLifeGrid(x, y) = 0 ELSE nextGameOfLifeGrid(x, y) = 1
-ELSE
-  IF c = 3 THEN nextGameOfLifeGrid(x, y) = 1 ELSE nextGameOfLifeGrid(x, y) = 0
-END IF
-NEXT x
-NEXT y
-
-FOR y = 1 TO 50
-FOR x = 1 TO 50
-  gameOfLifeGrid(x, y) = nextGameOfLifeGrid(x, y)
-NEXT x
-NEXT y
-END IF
-
-END SUB
-
-SUB InitializeEnvironment
-FOR z = -5 TO 5
-FOR x = -5 TO 5
-pointCount = pointCount + 1
-pointsX(pointCount) = x
-pointsY(pointCount) = 0
-pointsZ(pointCount) = z
-IF x > -5 THEN
-lineCount = lineCount + 1
-lineVertices1(lineCount) = pointCount
-lineVertices2(lineCount) = pointCount - 1
-lineColors(lineCount) = 1
-END IF
-IF z > -5 THEN
-lineCount = lineCount + 1
-lineVertices1(lineCount) = pointCount
-lineVertices2(lineCount) = pointCount - 10
-lineColors(lineCount) = 1
-END IF
-NEXT x
-NEXT z
-
-numPoints = pointCount
-numLines = lineCount
-
-END SUB
-
-SUB InitializeEnvironment1
-pointCount = 1
-pointsX(pointCount) = -2
-pointsY(pointCount) = 0
-pointsZ(pointCount) = 0
-pointCount = pointCount + 1
-pointsX(pointCount) = 2
-pointsY(pointCount) = 0
-pointsZ(pointCount) = 0
-
-lineCount = 1
-lineVertices1(lineCount) = 1
-lineVertices2(lineCount) = 2
-lineColors(lineCount) = 14
-
-END SUB
-
-SUB PlaceCube (x, y, z)
-
-v = 3
-
-lineCount = lineCount + 1
-lineVertices1(lineCount) = pointCount + 1
-lineVertices2(lineCount) = pointCount + 2
-lineColors(lineCount) = v
-
-lineCount = lineCount + 1
-lineVertices1(lineCount) = pointCount + 2
-lineVertices2(lineCount) = pointCount + 3
-lineColors(lineCount) = v
-
-lineCount = lineCount + 1
-lineVertices1(lineCount) = pointCount + 3
-lineVertices2(lineCount) = pointCount + 4
-lineColors(lineCount) = v
-
-lineCount = lineCount + 1
-lineVertices1(lineCount) = pointCount + 4
-lineVertices2(lineCount) = pointCount + 1
-lineColors(lineCount) = v
-
-lineCount = lineCount + 1
-lineVertices1(lineCount) = pointCount + 5
-lineVertices2(lineCount) = pointCount + 6
-lineColors(lineCount) = v
-
-lineCount = lineCount + 1
-lineVertices1(lineCount) = pointCount + 6
-lineVertices2(lineCount) = pointCount + 7
-lineColors(lineCount) = v
-
-lineCount = lineCount + 1
-lineVertices1(lineCount) = pointCount + 7
-lineVertices2(lineCount) = pointCount + 8
-lineColors(lineCount) = v
-
-lineCount = lineCount + 1
-lineVertices1(lineCount) = pointCount + 8
-lineVertices2(lineCount) = pointCount + 5
-lineColors(lineCount) = v
-
-lineCount = lineCount + 1
-lineVertices1(lineCount) = pointCount + 1
-lineVertices2(lineCount) = pointCount + 5
-lineColors(lineCount) = v
-
-lineCount = lineCount + 1
-lineVertices1(lineCount) = pointCount + 2
-lineVertices2(lineCount) = pointCount + 6
-lineColors(lineCount) = v
-
-lineCount = lineCount + 1
-lineVertices1(lineCount) = pointCount + 3
-lineVertices2(lineCount) = pointCount + 7
-lineColors(lineCount) = v
-
-lineCount = lineCount + 1
-lineVertices1(lineCount) = pointCount + 4
-lineVertices2(lineCount) = pointCount + 8
-lineColors(lineCount) = v
-
-pointCount = pointCount + 1
-pointsX(pointCount) = x - .5
-pointsY(pointCount) = y
-pointsZ(pointCount) = z - .5
-
-pointCount = pointCount + 1
-pointsX(pointCount) = x + .5
-pointsY(pointCount) = y
-pointsZ(pointCount) = z - .5
-
-pointCount = pointCount + 1
-pointsX(pointCount) = x + .5
-pointsY(pointCount) = y
-pointsZ(pointCount) = z + .5
-
-pointCount = pointCount + 1
-pointsX(pointCount) = x - .5
-pointsY(pointCount) = y
-pointsZ(pointCount) = z + .5
-
-pointCount = pointCount + 1
-pointsX(pointCount) = x - .5
-pointsY(pointCount) = y + 1
-pointsZ(pointCount) = z - .5
-
-pointCount = pointCount + 1
-pointsX(pointCount) = x + .5
-pointsY(pointCount) = y + 1
-pointsZ(pointCount) = z - .5
-
-pointCount = pointCount + 1
-pointsX(pointCount) = x + .5
-pointsY(pointCount) = y + 1
-pointsZ(pointCount) = z + .5
-
-pointCount = pointCount + 1
-pointsX(pointCount) = x - .5
-pointsY(pointCount) = y + 1
-pointsZ(pointCount) = z + .5
-
-END SUB
-
-SUB RenderScene
-
-sineAngle1 = SIN(angle1)
-cosineAngle1 = COS(angle1)
-sineAngle2 = SIN(angle2)
-cosineAngle2 = COS(angle2)
-
-FOR a = 1 TO pointCount
-x = pointsX(a) + myPositionX
-y = pointsY(a) - myPositionY
-z = pointsZ(a) + myPositionZ
-
-x1 = x * sineAngle1 - z * cosineAngle1
-z1 = x * cosineAngle1 + z * sineAngle1
-y1 = y * sineAngle2 - z1 * cosineAngle2
-z2 = y * cosineAngle2 + z1 * sineAngle2
-
-IF z2 < .5 THEN
-renderedPointsX(a) = -1
-ELSE
-renderedPointsX(a) = 320 + (x1 / z2 * 400)
-renderedPointsY(a) = 240 - (y1 / z2 * 400)
-END IF
-NEXT a
-
-FOR a = 1 TO lineCount
-l1 = originalLineVertices1(a)
-l2 = originalLineVertices2(a)
-
-IF originalRenderedPointsX(l1) = -1 OR originalRenderedPointsX(l2) = -1 THEN
-ELSE
-LINE (originalRenderedPointsX(l1), originalRenderedPointsY(l1))-(originalRenderedPointsX(l2), originalRenderedPointsY(l2)), 0
-END IF
-
-l1 = lineVertices1(a)
-l2 = lineVertices2(a)
-IF renderedPointsX(l1) = -1 OR renderedPointsX(l2) = -1 THEN
-ELSE
-LINE (renderedPointsX(l1), renderedPointsY(l1))-(renderedPointsX(l2), renderedPointsY(l2)), lineColors(a)
-END IF
-NEXT a
-
-IF lineCount < oldLineCount THEN
-FOR a = lineCount + 1 TO oldLineCount
-l1 = originalLineVertices1(a)
-l2 = originalLineVertices2(a)
-IF originalRenderedPointsX(l1) = -1 OR originalRenderedPointsX(l2) = -1 THEN
-ELSE
-LINE (originalRenderedPointsX(l1), originalRenderedPointsY(l1))-(originalRenderedPointsX(l2), originalRenderedPointsY(l2)), 0
-END IF
-NEXT a
-END IF
-
-FOR a = 1 TO pointCount
-originalRenderedPointsX(a) = renderedPointsX(a)
-originalRenderedPointsY(a) = renderedPointsY(a)
-NEXT a
-
-oldPointCount = pointCount
-
-FOR a = 1 TO lineCount
-originalLineVertices1(a) = lineVertices1(a)
-originalLineVertices2(a) = lineVertices2(a)
-NEXT a
-
-oldLineCount = lineCount
-
-END SUB
-
-SUB StartGame
-SCREEN 12
-numPoints = 0
-numLines = 0
-pointCount = numPoints
-lineCount = numLines
-gridSize = 50
-
-myPositionX = 4
-myPositionY = 15
-myPositionZ = 17
-angle1 = ATN(1) / 2 - .29
-angle2 = angle1 + 1
-
-FOR a = 1 TO 1000
-lineColors(a) = 4
-NEXT a
-
-FOR a = 1 TO 1000
-originalLineVertices1(a) = 1
-originalLineVertices2(a) = 1
-NEXT a
-
-OPEN "3dlife.dat" FOR INPUT AS #1
-y = 20
-20
-IF EOF(1) <> 0 THEN GOTO 30
-x = 20
-
-LINE INPUT #1, inputLine$
-FOR b = 1 TO LEN(inputLine$)
-  c$ = RIGHT$(LEFT$(inputLine$, b), 1)
-  IF c$ = "#" THEN gameOfLifeGrid(x, y) = 1
-  x = x + 1
-NEXT b
-
-y = y + 1
-GOTO 20
-30
-CLOSE #1
-
-END SUB
diff --git a/Graphics/3D/3D game of life/3dlife.dat b/Graphics/3D/3D game of life/3dlife.dat
deleted file mode 100644 (file)
index 17b0e10..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-.....#.#.....\r
-...##...##...\r
-..#.......#..\r
-.#..##.##..#.\r
-.#.#.....#.#.\r
-#..#.###.#..#\r
-.....#.#.....\r
-#..#.###.#..#\r
-.#.#.....#.#.\r
-.#..##.##..#.\r
-..#.......#..\r
-...##...##...\r
-.....#.#.....\r
diff --git a/Graphics/3D/3D life.bas b/Graphics/3D/3D life.bas
new file mode 100755 (executable)
index 0000000..e7f8bef
--- /dev/null
@@ -0,0 +1,360 @@
+' Program renders rotating 3D animation from cubes.
+' Cubes appear and disappear according to Conway's Game of Life rules.
+'
+' By Svjatoslav Agejenko.
+' Email: svjatoslav@svjatoslav.eu
+' Homepage: http://www.svjatoslav.eu
+'
+' Changelog:
+' ?, Initial version
+' 2024, Improved program readability using AI
+
+DECLARE SUB PlaceCube (x!, y!, z!)
+DECLARE SUB DrawCube (x!, y!, z!)
+
+DECLARE SUB CreateCollisionData ()
+DECLARE SUB UpdateCollisionData ()
+DECLARE SUB RenderScene ()
+DECLARE SUB InitializeEnvironment ()
+DECLARE SUB StartGame ()
+
+DIM SHARED numPoints, numLines, pointCount, lineCount
+DIM SHARED pointsX(1 TO 3000), pointsY(1 TO 3000), pointsZ(1 TO 3000)
+DIM SHARED renderedPointsX(1 TO 7000), renderedPointsY(1 TO 7000)
+DIM SHARED originalRenderedPointsX(0 TO 9000), originalRenderedPointsY(0 TO 9000)
+DIM SHARED oldPointCount, oldLineCount
+DIM SHARED lineVertices1(1 TO 3800), lineVertices2(1 TO 3800), lineColors(1 TO 3800)
+DIM SHARED originalLineVertices1(1 TO 3800), originalLineVertices2(1 TO 3800)
+DIM SHARED myPositionX, myPositionY, myPositionZ
+DIM SHARED myPreviousPositionX, myPreviousPositionY, myPreviousPositionZ
+DIM SHARED angle1, angle2
+DIM SHARED angle1Str, angle2Str
+DIM SHARED frameCount
+
+DIM SHARED gameOfLifeGrid(1 TO 50, 1 TO 50)
+DIM SHARED nextGameOfLifeGrid(1 TO 50, 1 TO 50)
+
+StartGame
+
+angle1 = 1.5
+10
+frameCount = frameCount + 1
+
+CreateCollisionData
+RenderScene
+
+myPositionX = SIN(frameCount / 20) * 12
+myPositionY = SIN(frameCount / 50) * 10 + 15
+myPositionZ = COS(frameCount / 20) * 12
+
+angle1 = angle1 - .05
+angle2 = 2.2 + SIN(frameCount / 50) / 2
+
+inputKey$ = INKEY$
+IF inputKey$ <> "" THEN SYSTEM
+GOTO 10
+
+SUB CreateCollisionData
+pointCount = numPoints
+lineCount = numLines
+
+FOR y = 1 TO 50
+  FOR x = 1 TO 50
+    IF gameOfLifeGrid(x, y) = 1 THEN
+       v = ABS(x - 26) + ABS(y - 26) + frameCount
+       PlaceCube x - 25, SIN(v / 5) * 5, y - 25
+    END IF
+ NEXT x
+NEXT y
+
+IF frameCount \ 10 = frameCount / 10 THEN
+
+FOR y = 2 TO 49
+FOR x = 2 TO 49
+c = gameOfLifeGrid(x - 1, y - 1)
+c = c + gameOfLifeGrid(x, y - 1)
+c = c + gameOfLifeGrid(x + 1, y - 1)
+c = c + gameOfLifeGrid(x - 1, y)
+c = c + gameOfLifeGrid(x + 1, y)
+c = c + gameOfLifeGrid(x - 1, y + 1)
+c = c + gameOfLifeGrid(x, y + 1)
+c = c + gameOfLifeGrid(x + 1, y + 1)
+
+IF gameOfLifeGrid(x, y) = 1 THEN
+  IF (c > 3) OR (c < 2) THEN nextGameOfLifeGrid(x, y) = 0 ELSE nextGameOfLifeGrid(x, y) = 1
+ELSE
+  IF c = 3 THEN nextGameOfLifeGrid(x, y) = 1 ELSE nextGameOfLifeGrid(x, y) = 0
+END IF
+NEXT x
+NEXT y
+
+FOR y = 1 TO 50
+FOR x = 1 TO 50
+  gameOfLifeGrid(x, y) = nextGameOfLifeGrid(x, y)
+NEXT x
+NEXT y
+END IF
+
+END SUB
+
+SUB InitializeEnvironment
+FOR z = -5 TO 5
+FOR x = -5 TO 5
+pointCount = pointCount + 1
+pointsX(pointCount) = x
+pointsY(pointCount) = 0
+pointsZ(pointCount) = z
+IF x > -5 THEN
+lineCount = lineCount + 1
+lineVertices1(lineCount) = pointCount
+lineVertices2(lineCount) = pointCount - 1
+lineColors(lineCount) = 1
+END IF
+IF z > -5 THEN
+lineCount = lineCount + 1
+lineVertices1(lineCount) = pointCount
+lineVertices2(lineCount) = pointCount - 10
+lineColors(lineCount) = 1
+END IF
+NEXT x
+NEXT z
+
+numPoints = pointCount
+numLines = lineCount
+
+END SUB
+
+SUB InitializeEnvironment1
+pointCount = 1
+pointsX(pointCount) = -2
+pointsY(pointCount) = 0
+pointsZ(pointCount) = 0
+pointCount = pointCount + 1
+pointsX(pointCount) = 2
+pointsY(pointCount) = 0
+pointsZ(pointCount) = 0
+
+lineCount = 1
+lineVertices1(lineCount) = 1
+lineVertices2(lineCount) = 2
+lineColors(lineCount) = 14
+
+END SUB
+
+SUB PlaceCube (x, y, z)
+
+v = 3
+
+lineCount = lineCount + 1
+lineVertices1(lineCount) = pointCount + 1
+lineVertices2(lineCount) = pointCount + 2
+lineColors(lineCount) = v
+
+lineCount = lineCount + 1
+lineVertices1(lineCount) = pointCount + 2
+lineVertices2(lineCount) = pointCount + 3
+lineColors(lineCount) = v
+
+lineCount = lineCount + 1
+lineVertices1(lineCount) = pointCount + 3
+lineVertices2(lineCount) = pointCount + 4
+lineColors(lineCount) = v
+
+lineCount = lineCount + 1
+lineVertices1(lineCount) = pointCount + 4
+lineVertices2(lineCount) = pointCount + 1
+lineColors(lineCount) = v
+
+lineCount = lineCount + 1
+lineVertices1(lineCount) = pointCount + 5
+lineVertices2(lineCount) = pointCount + 6
+lineColors(lineCount) = v
+
+lineCount = lineCount + 1
+lineVertices1(lineCount) = pointCount + 6
+lineVertices2(lineCount) = pointCount + 7
+lineColors(lineCount) = v
+
+lineCount = lineCount + 1
+lineVertices1(lineCount) = pointCount + 7
+lineVertices2(lineCount) = pointCount + 8
+lineColors(lineCount) = v
+
+lineCount = lineCount + 1
+lineVertices1(lineCount) = pointCount + 8
+lineVertices2(lineCount) = pointCount + 5
+lineColors(lineCount) = v
+
+lineCount = lineCount + 1
+lineVertices1(lineCount) = pointCount + 1
+lineVertices2(lineCount) = pointCount + 5
+lineColors(lineCount) = v
+
+lineCount = lineCount + 1
+lineVertices1(lineCount) = pointCount + 2
+lineVertices2(lineCount) = pointCount + 6
+lineColors(lineCount) = v
+
+lineCount = lineCount + 1
+lineVertices1(lineCount) = pointCount + 3
+lineVertices2(lineCount) = pointCount + 7
+lineColors(lineCount) = v
+
+lineCount = lineCount + 1
+lineVertices1(lineCount) = pointCount + 4
+lineVertices2(lineCount) = pointCount + 8
+lineColors(lineCount) = v
+
+pointCount = pointCount + 1
+pointsX(pointCount) = x - .5
+pointsY(pointCount) = y
+pointsZ(pointCount) = z - .5
+
+pointCount = pointCount + 1
+pointsX(pointCount) = x + .5
+pointsY(pointCount) = y
+pointsZ(pointCount) = z - .5
+
+pointCount = pointCount + 1
+pointsX(pointCount) = x + .5
+pointsY(pointCount) = y
+pointsZ(pointCount) = z + .5
+
+pointCount = pointCount + 1
+pointsX(pointCount) = x - .5
+pointsY(pointCount) = y
+pointsZ(pointCount) = z + .5
+
+pointCount = pointCount + 1
+pointsX(pointCount) = x - .5
+pointsY(pointCount) = y + 1
+pointsZ(pointCount) = z - .5
+
+pointCount = pointCount + 1
+pointsX(pointCount) = x + .5
+pointsY(pointCount) = y + 1
+pointsZ(pointCount) = z - .5
+
+pointCount = pointCount + 1
+pointsX(pointCount) = x + .5
+pointsY(pointCount) = y + 1
+pointsZ(pointCount) = z + .5
+
+pointCount = pointCount + 1
+pointsX(pointCount) = x - .5
+pointsY(pointCount) = y + 1
+pointsZ(pointCount) = z + .5
+
+END SUB
+
+SUB RenderScene
+
+sineAngle1 = SIN(angle1)
+cosineAngle1 = COS(angle1)
+sineAngle2 = SIN(angle2)
+cosineAngle2 = COS(angle2)
+
+FOR a = 1 TO pointCount
+x = pointsX(a) + myPositionX
+y = pointsY(a) - myPositionY
+z = pointsZ(a) + myPositionZ
+
+x1 = x * sineAngle1 - z * cosineAngle1
+z1 = x * cosineAngle1 + z * sineAngle1
+y1 = y * sineAngle2 - z1 * cosineAngle2
+z2 = y * cosineAngle2 + z1 * sineAngle2
+
+IF z2 < .5 THEN
+renderedPointsX(a) = -1
+ELSE
+renderedPointsX(a) = 320 + (x1 / z2 * 400)
+renderedPointsY(a) = 240 - (y1 / z2 * 400)
+END IF
+NEXT a
+
+FOR a = 1 TO lineCount
+l1 = originalLineVertices1(a)
+l2 = originalLineVertices2(a)
+
+IF originalRenderedPointsX(l1) = -1 OR originalRenderedPointsX(l2) = -1 THEN
+ELSE
+LINE (originalRenderedPointsX(l1), originalRenderedPointsY(l1))-(originalRenderedPointsX(l2), originalRenderedPointsY(l2)), 0
+END IF
+
+l1 = lineVertices1(a)
+l2 = lineVertices2(a)
+IF renderedPointsX(l1) = -1 OR renderedPointsX(l2) = -1 THEN
+ELSE
+LINE (renderedPointsX(l1), renderedPointsY(l1))-(renderedPointsX(l2), renderedPointsY(l2)), lineColors(a)
+END IF
+NEXT a
+
+IF lineCount < oldLineCount THEN
+FOR a = lineCount + 1 TO oldLineCount
+l1 = originalLineVertices1(a)
+l2 = originalLineVertices2(a)
+IF originalRenderedPointsX(l1) = -1 OR originalRenderedPointsX(l2) = -1 THEN
+ELSE
+LINE (originalRenderedPointsX(l1), originalRenderedPointsY(l1))-(originalRenderedPointsX(l2), originalRenderedPointsY(l2)), 0
+END IF
+NEXT a
+END IF
+
+FOR a = 1 TO pointCount
+originalRenderedPointsX(a) = renderedPointsX(a)
+originalRenderedPointsY(a) = renderedPointsY(a)
+NEXT a
+
+oldPointCount = pointCount
+
+FOR a = 1 TO lineCount
+originalLineVertices1(a) = lineVertices1(a)
+originalLineVertices2(a) = lineVertices2(a)
+NEXT a
+
+oldLineCount = lineCount
+
+END SUB
+
+SUB StartGame
+SCREEN 12
+numPoints = 0
+numLines = 0
+pointCount = numPoints
+lineCount = numLines
+gridSize = 50
+
+myPositionX = 4
+myPositionY = 15
+myPositionZ = 17
+angle1 = ATN(1) / 2 - .29
+angle2 = angle1 + 1
+
+FOR a = 1 TO 1000
+lineColors(a) = 4
+NEXT a
+
+FOR a = 1 TO 1000
+originalLineVertices1(a) = 1
+originalLineVertices2(a) = 1
+NEXT a
+
+OPEN "3dlife.dat" FOR INPUT AS #1
+y = 20
+20
+IF EOF(1) <> 0 THEN GOTO 30
+x = 20
+
+LINE INPUT #1, inputLine$
+FOR b = 1 TO LEN(inputLine$)
+  c$ = RIGHT$(LEFT$(inputLine$, b), 1)
+  IF c$ = "#" THEN gameOfLifeGrid(x, y) = 1
+  x = x + 1
+NEXT b
+
+y = y + 1
+GOTO 20
+30
+CLOSE #1
+
+END SUB
diff --git a/Graphics/3D/3D life.webm b/Graphics/3D/3D life.webm
new file mode 100644 (file)
index 0000000..2b7e1ed
Binary files /dev/null and b/Graphics/3D/3D life.webm differ
diff --git a/Graphics/3D/3dlife.dat b/Graphics/3D/3dlife.dat
new file mode 100644 (file)
index 0000000..17b0e10
--- /dev/null
@@ -0,0 +1,13 @@
+.....#.#.....\r
+...##...##...\r
+..#.......#..\r
+.#..##.##..#.\r
+.#.#.....#.#.\r
+#..#.###.#..#\r
+.....#.#.....\r
+#..#.###.#..#\r
+.#.#.....#.#.\r
+.#..##.##..#.\r
+..#.......#..\r
+...##...##...\r
+.....#.#.....\r
diff --git a/Graphics/3D/bouncing cubes.webm b/Graphics/3D/bouncing cubes.webm
new file mode 100644 (file)
index 0000000..2328295
Binary files /dev/null and b/Graphics/3D/bouncing cubes.webm differ
diff --git a/Graphics/3D/gravi.bas b/Graphics/3D/gravi.bas
deleted file mode 100755 (executable)
index e91207a..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-' Program to simulate gravitational forces between atoms.\r
-' By Svjatoslav Agejenko.\r
-' Email: svjatoslav@svjatoslav.eu\r
-' Homepage: http://www.svjatoslav.eu\r
-'\r
-' Changelog:\r
-' 2003.12, Initial version\r
-' 2024.08, Improved program readability using AI\r
-\r
-DECLARE SUB Gravitate ()\r
-DECLARE SUB AddAtom (x AS SINGLE, y AS SINGLE, z AS SINGLE, size AS SINGLE)\r
-DECLARE SUB DisplaySystem ()\r
-\r
-DIM SHARED atomX(1 TO 100)\r
-DIM SHARED atomY(1 TO 100)\r
-DIM SHARED atomZ(1 TO 100)\r
-DIM SHARED atomXSpeed(1 TO 100)\r
-DIM SHARED atomYSpeed(1 TO 100)\r
-DIM SHARED atomZSpeed(1 TO 100)\r
-DIM SHARED atomSize(1 TO 100)\r
-DIM SHARED countOfAtoms\r
-DIM SHARED myX, myY, myZ\r
-DIM SHARED oldAtomX(1 TO 100)\r
-DIM SHARED oldAtomY(1 TO 100)\r
-DIM SHARED oldAtomSize(1 TO 100)\r
-\r
-myX = 0\r
-myY = 0\r
-myZ = -5\r
-countOfAtoms = 0\r
-\r
-SCREEN 13\r
-\r
-' Initialize the system with a random distribution of atoms\r
-FOR a = 1 TO 30\r
-    AddAtom RND * 6 - 3, RND * 6 - 3, RND * 4, 50\r
-NEXT a\r
-\r
-' Main loop to display and update the system\r
-1\r
-    DisplaySystem\r
-    Gravitate\r
-    IF INKEY$ <> "" THEN SYSTEM ' Exit on any key press\r
-GOTO 1\r
-\r
-SUB AddAtom (x, y, z, size)\r
-    ' Increment the atom count\r
-    countOfAtoms = countOfAtoms + 1\r
-\r
-    ' Store the new atom's position and size\r
-    atomX(countOfAtoms) = x\r
-    atomY(countOfAtoms) = y\r
-    atomZ(countOfAtoms) = z\r
-    atomSize(countOfAtoms) = size\r
-\r
-    ' Initialize the speed of the new atom to zero\r
-    atomXSpeed(countOfAtoms) = 0\r
-    atomYSpeed(countOfAtoms) = 0\r
-    atomZSpeed(countOfAtoms) = 0\r
-END SUB\r
-\r
-SUB DisplaySystem\r
-    FOR a = 1 TO countOfAtoms\r
-        ' Calculate the relative position of each atom\r
-        x = atomX(a) - myX\r
-        y = atomY(a) - myY\r
-        z = atomZ(a) - myZ\r
-\r
-        ' Project the 3D positions onto a 2D screen\r
-        x1 = x / z * 100 + 160\r
-        y1 = y / z * 100 + 100\r
-\r
-        ' Erase the old atom position and draw the new one\r
-        CIRCLE (oldAtomX(a), oldAtomY(a)), oldAtomSize(a), 0\r
-        CIRCLE (x1, y1), atomSize(a) / z, 15\r
-\r
-        ' Update the old positions for the next frame\r
-        oldAtomX(a) = x1\r
-        oldAtomY(a) = y1\r
-        oldAtomSize(a) = atomSize(a) / z\r
-    NEXT a\r
-END SUB\r
-\r
-SUB Gravitate\r
-    DIM pxs, pys, pzs\r
-\r
-    FOR a = 1 TO countOfAtoms\r
-        ' Get the current atom's position\r
-        x = atomX(a)\r
-        y = atomY(a)\r
-        z = atomZ(a)\r
-\r
-        ' Initialize gravitational forces to zero\r
-        pxs = 0\r
-        pys = 0\r
-        pzs = 0\r
-\r
-        FOR b = 1 TO countOfAtoms\r
-            IF b = a THEN GOTO 2 ' Skip self-gravitation\r
-\r
-            ' Calculate the distance between atoms\r
-            v = SQR((atomX(b) - x) ^ 2 + (atomY(b) - y) ^ 2 + (atomZ(b) - z) ^ 2)\r
-            v2 = 1 / (v - 1)\r
-\r
-            ' Accumulate gravitational forces from other atoms\r
-            pxs = pxs + (atomX(b) - x) / v2 / 10000\r
-            pys = pys + (atomY(b) - y) / v2 / 10000\r
-            pzs = pzs + (atomZ(b) - z) / v2 / 10000\r
-\r
-2          NEXT b\r
-\r
-        ' Update the atom's velocity with the accumulated forces\r
-        atomXSpeed(a) = atomXSpeed(a) / 1.01 + pxs\r
-        atomYSpeed(a) = atomYSpeed(a) / 1.01 + pys\r
-        atomZSpeed(a) = atomZSpeed(a) / 1.01 + pzs\r
-    NEXT a\r
-\r
-    ' Update the positions of all atoms based on their velocities\r
-    FOR a = 1 TO countOfAtoms\r
-        atomX(a) = atomX(a) + atomXSpeed(a)\r
-        atomY(a) = atomY(a) + atomYSpeed(a)\r
-        atomZ(a) = atomZ(a) + atomZSpeed(a)\r
-    NEXT a\r
-END SUB
\ No newline at end of file
diff --git a/Graphics/3D/gravity particles.bas b/Graphics/3D/gravity particles.bas
new file mode 100755 (executable)
index 0000000..08a239c
--- /dev/null
@@ -0,0 +1,128 @@
+' Program to simulate gravitational forces between atoms.\r
+' By Svjatoslav Agejenko.\r
+' Email: svjatoslav@svjatoslav.eu\r
+' Homepage: http://www.svjatoslav.eu\r
+'\r
+' Changelog:\r
+' 2003.12, Initial version\r
+' 2024.08, Improved program readability using AI\r
+\r
+DECLARE SUB Gravitate ()\r
+DECLARE SUB AddAtom (x AS SINGLE, y AS SINGLE, z AS SINGLE, size AS SINGLE)\r
+DECLARE SUB DisplaySystem ()\r
+\r
+DIM SHARED atomX(1 TO 100)\r
+DIM SHARED atomY(1 TO 100)\r
+DIM SHARED atomZ(1 TO 100)\r
+DIM SHARED atomXSpeed(1 TO 100)\r
+DIM SHARED atomYSpeed(1 TO 100)\r
+DIM SHARED atomZSpeed(1 TO 100)\r
+DIM SHARED atomSize(1 TO 100)\r
+DIM SHARED countOfAtoms\r
+DIM SHARED myX, myY, myZ\r
+DIM SHARED oldAtomX(1 TO 100)\r
+DIM SHARED oldAtomY(1 TO 100)\r
+DIM SHARED oldAtomSize(1 TO 100)\r
+\r
+myX = 0\r
+myY = 0\r
+myZ = -5\r
+countOfAtoms = 0\r
+\r
+SCREEN 13\r
+\r
+' Initialize the system with a random distribution of atoms\r
+FOR a = 1 TO 30\r
+    AddAtom RND * 6 - 3, RND * 6 - 3, RND * 4, 50\r
+NEXT a\r
+\r
+' Main loop to display and update the system\r
+1\r
+    DisplaySystem\r
+    Gravitate\r
+    IF INKEY$ <> "" THEN SYSTEM ' Exit on any key press\r
+   \r
+    ' Delay animation\r
+    SOUND 0, 1\r
+GOTO 1\r
+\r
+SUB AddAtom (x, y, z, size)\r
+    ' Increment the atom count\r
+    countOfAtoms = countOfAtoms + 1\r
+\r
+    ' Store the new atom's position and size\r
+    atomX(countOfAtoms) = x\r
+    atomY(countOfAtoms) = y\r
+    atomZ(countOfAtoms) = z\r
+    atomSize(countOfAtoms) = size\r
+\r
+    ' Initialize the speed of the new atom to zero\r
+    atomXSpeed(countOfAtoms) = 0\r
+    atomYSpeed(countOfAtoms) = 0\r
+    atomZSpeed(countOfAtoms) = 0\r
+END SUB\r
+\r
+SUB DisplaySystem\r
+    FOR a = 1 TO countOfAtoms\r
+        ' Calculate the relative position of each atom\r
+        x = atomX(a) - myX\r
+        y = atomY(a) - myY\r
+        z = atomZ(a) - myZ\r
+\r
+        ' Project the 3D positions onto a 2D screen\r
+        x1 = x / z * 100 + 160\r
+        y1 = y / z * 100 + 100\r
+\r
+        ' Erase the old atom position and draw the new one\r
+        CIRCLE (oldAtomX(a), oldAtomY(a)), oldAtomSize(a), 0\r
+        CIRCLE (x1, y1), atomSize(a) / z, 15\r
+\r
+        ' Update the old positions for the next frame\r
+        oldAtomX(a) = x1\r
+        oldAtomY(a) = y1\r
+        oldAtomSize(a) = atomSize(a) / z\r
+    NEXT a\r
+END SUB\r
+\r
+SUB Gravitate\r
+    DIM pxs, pys, pzs\r
+\r
+    FOR a = 1 TO countOfAtoms\r
+        ' Get the current atom's position\r
+        x = atomX(a)\r
+        y = atomY(a)\r
+        z = atomZ(a)\r
+\r
+        ' Initialize gravitational forces to zero\r
+        pxs = 0\r
+        pys = 0\r
+        pzs = 0\r
+\r
+        FOR b = 1 TO countOfAtoms\r
+            IF b = a THEN GOTO 2 ' Skip self-gravitation\r
+\r
+            ' Calculate the distance between atoms\r
+            v = SQR((atomX(b) - x) ^ 2 + (atomY(b) - y) ^ 2 + (atomZ(b) - z) ^ 2)\r
+            v2 = 1 / (v - 1)\r
+\r
+            ' Accumulate gravitational forces from other atoms\r
+            pxs = pxs + (atomX(b) - x) / v2 / 10000\r
+            pys = pys + (atomY(b) - y) / v2 / 10000\r
+            pzs = pzs + (atomZ(b) - z) / v2 / 10000\r
+\r
+2          NEXT b\r
+\r
+        ' Update the atom's velocity with the accumulated forces\r
+        atomXSpeed(a) = atomXSpeed(a) / 1.01 + pxs\r
+        atomYSpeed(a) = atomYSpeed(a) / 1.01 + pys\r
+        atomZSpeed(a) = atomZSpeed(a) / 1.01 + pzs\r
+    NEXT a\r
+\r
+    ' Update the positions of all atoms based on their velocities\r
+    FOR a = 1 TO countOfAtoms\r
+        atomX(a) = atomX(a) + atomXSpeed(a)\r
+        atomY(a) = atomY(a) + atomYSpeed(a)\r
+        atomZ(a) = atomZ(a) + atomZSpeed(a)\r
+    NEXT a\r
+END SUB\r
+\r
diff --git a/Graphics/3D/gravity particles.webm b/Graphics/3D/gravity particles.webm
new file mode 100644 (file)
index 0000000..c941ab8
Binary files /dev/null and b/Graphics/3D/gravity particles.webm differ
diff --git a/Graphics/3D/matrix math.bas b/Graphics/3D/matrix math.bas
new file mode 100755 (executable)
index 0000000..f625827
--- /dev/null
@@ -0,0 +1,73 @@
+' Program to demonstrate 3x3 matrix math for coordinate rotation in 3D space.\r
+' By Svjatoslav Agejenko.\r
+' Email: svjatoslav@svjatoslav.eu\r
+' Homepage: http://www.svjatoslav.eu\r
+'\r
+' Changelog:\r
+' 2003.03, Initial version\r
+' 2024.08, Improved program readability using AI\r
+\r
+' Use keys:\r
+' 7 9 - change alpha angle\r
+' 4 6 - change beta angle\r
+' 1 3 - change gamma angle\r
+' ESC - quit program\r
+\r
+DECLARE SUB graphicalCoordinates (xVal AS Single, yVal AS Single, zVal AS Single, x1Val AS Single, y1Val AS Single)\r
+DECLARE SUB setAngles (alphaVal AS Single, betaVal AS Single, gammaVal AS Single)\r
+DIM SHARED matrixX1 AS Single, matrixY1 AS Single, matrixZ1 AS Single\r
+DIM SHARED matrixX2 AS Single, matrixY2 AS Single, matrixZ2 AS Single\r
+DIM SHARED matrixX3 AS Single, matrixY3 AS Single, matrixZ3 AS Single\r
+\r
+SCREEN 7, , , 1\r
+\r
+' Main loop starts here\r
+DO\r
+    CALL setAngles(angleAlpha, angleBeta, angleGamma)\r
+\r
+    FOR y = -70 TO 70 STEP 5\r
+        FOR x = -70 TO 70 STEP 5\r
+            CALL graphicalCoordinates(x, y, SIN((ABS(x) + ABS(y)) / 30) * 30, x1Val, y1Val)\r
+            PSET (x1Val, y1Val), 15\r
+        NEXT x\r
+    NEXT y\r
+    PCOPY 0, 1\r
+    CLS\r
+    inputChar$ = INPUT$(1)\r
+\r
+    ' Adjust rotation angles based on user input\r
+    IF inputChar$ = "7" THEN angleAlpha = angleAlpha + 0.1\r
+    IF inputChar$ = "9" THEN angleAlpha = angleAlpha - 0.1\r
+    IF inputChar$ = "4" THEN angleBeta = angleBeta + 0.1\r
+    IF inputChar$ = "6" THEN angleBeta = angleBeta - 0.1\r
+    IF inputChar$ = "1" THEN angleGamma = angleGamma + 0.1\r
+    IF inputChar$ = "3" THEN angleGamma = angleGamma - 0.1\r
+    IF inputChar$ = CHR$(27) THEN SYSTEM ' Exit program if ESC key is pressed\r
+LOOP\r
+\r
+SUB graphicalCoordinates (xVal AS Single, yVal AS Single, zVal AS Single, x1Val AS Single, y1Val AS Single)\r
+    ' Perform matrix transformation to rotate coordinates\r
+    rxVal = xVal * matrixX1 + yVal * matrixY1 + zVal * matrixZ1\r
+    ryVal = xVal * matrixX2 + yVal * matrixY2 + zVal * matrixZ2\r
+    rzVal = xVal * matrixX3 + yVal * matrixY3 + zVal * matrixZ3\r
+\r
+    ' Apply perspective calculation to give the illusion of depth\r
+    rzVal = rzVal + 100\r
+    x1Val = rxVal / rzVal * 120 + 160\r
+    y1Val = ryVal / rzVal * 120 + 100\r
+END SUB\r
+\r
+SUB setAngles (alphaVal AS Single, betaVal AS Single, gammaVal AS Single)\r
+    ' Calculate the elements of the rotation matrix based on the angles\r
+    matrixX1 = SIN(gammaVal) * SIN(betaVal) * SIN(alphaVal) + COS(gammaVal) * COS(alphaVal)\r
+    matrixY1 = COS(betaVal) * SIN(alphaVal)\r
+    matrixZ1 = SIN(gammaVal) * COS(alphaVal) - COS(gammaVal) * SIN(betaVal) * SIN(alphaVal)\r
+\r
+    matrixX2 = SIN(gammaVal) * SIN(betaVal) * COS(alphaVal) - COS(gammaVal) * SIN(alphaVal)\r
+    matrixY2 = COS(betaVal) * COS(alphaVal)\r
+    matrixZ2 = -COS(gammaVal) * SIN(betaVal) * COS(alphaVal) - SIN(gammaVal) * SIN(alphaVal)\r
+\r
+    matrixX3 = -SIN(gammaVal) * COS(betaVal)\r
+    matrixY3 = SIN(betaVal)\r
+    matrixZ3 = COS(gammaVal) * COS(betaVal)\r
+END SUB
\ No newline at end of file
diff --git a/Graphics/3D/matrix math.webm b/Graphics/3D/matrix math.webm
new file mode 100644 (file)
index 0000000..5e6ea9a
Binary files /dev/null and b/Graphics/3D/matrix math.webm differ
diff --git a/Graphics/3D/mtrxmath.bas b/Graphics/3D/mtrxmath.bas
deleted file mode 100755 (executable)
index f625827..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-' Program to demonstrate 3x3 matrix math for coordinate rotation in 3D space.\r
-' By Svjatoslav Agejenko.\r
-' Email: svjatoslav@svjatoslav.eu\r
-' Homepage: http://www.svjatoslav.eu\r
-'\r
-' Changelog:\r
-' 2003.03, Initial version\r
-' 2024.08, Improved program readability using AI\r
-\r
-' Use keys:\r
-' 7 9 - change alpha angle\r
-' 4 6 - change beta angle\r
-' 1 3 - change gamma angle\r
-' ESC - quit program\r
-\r
-DECLARE SUB graphicalCoordinates (xVal AS Single, yVal AS Single, zVal AS Single, x1Val AS Single, y1Val AS Single)\r
-DECLARE SUB setAngles (alphaVal AS Single, betaVal AS Single, gammaVal AS Single)\r
-DIM SHARED matrixX1 AS Single, matrixY1 AS Single, matrixZ1 AS Single\r
-DIM SHARED matrixX2 AS Single, matrixY2 AS Single, matrixZ2 AS Single\r
-DIM SHARED matrixX3 AS Single, matrixY3 AS Single, matrixZ3 AS Single\r
-\r
-SCREEN 7, , , 1\r
-\r
-' Main loop starts here\r
-DO\r
-    CALL setAngles(angleAlpha, angleBeta, angleGamma)\r
-\r
-    FOR y = -70 TO 70 STEP 5\r
-        FOR x = -70 TO 70 STEP 5\r
-            CALL graphicalCoordinates(x, y, SIN((ABS(x) + ABS(y)) / 30) * 30, x1Val, y1Val)\r
-            PSET (x1Val, y1Val), 15\r
-        NEXT x\r
-    NEXT y\r
-    PCOPY 0, 1\r
-    CLS\r
-    inputChar$ = INPUT$(1)\r
-\r
-    ' Adjust rotation angles based on user input\r
-    IF inputChar$ = "7" THEN angleAlpha = angleAlpha + 0.1\r
-    IF inputChar$ = "9" THEN angleAlpha = angleAlpha - 0.1\r
-    IF inputChar$ = "4" THEN angleBeta = angleBeta + 0.1\r
-    IF inputChar$ = "6" THEN angleBeta = angleBeta - 0.1\r
-    IF inputChar$ = "1" THEN angleGamma = angleGamma + 0.1\r
-    IF inputChar$ = "3" THEN angleGamma = angleGamma - 0.1\r
-    IF inputChar$ = CHR$(27) THEN SYSTEM ' Exit program if ESC key is pressed\r
-LOOP\r
-\r
-SUB graphicalCoordinates (xVal AS Single, yVal AS Single, zVal AS Single, x1Val AS Single, y1Val AS Single)\r
-    ' Perform matrix transformation to rotate coordinates\r
-    rxVal = xVal * matrixX1 + yVal * matrixY1 + zVal * matrixZ1\r
-    ryVal = xVal * matrixX2 + yVal * matrixY2 + zVal * matrixZ2\r
-    rzVal = xVal * matrixX3 + yVal * matrixY3 + zVal * matrixZ3\r
-\r
-    ' Apply perspective calculation to give the illusion of depth\r
-    rzVal = rzVal + 100\r
-    x1Val = rxVal / rzVal * 120 + 160\r
-    y1Val = ryVal / rzVal * 120 + 100\r
-END SUB\r
-\r
-SUB setAngles (alphaVal AS Single, betaVal AS Single, gammaVal AS Single)\r
-    ' Calculate the elements of the rotation matrix based on the angles\r
-    matrixX1 = SIN(gammaVal) * SIN(betaVal) * SIN(alphaVal) + COS(gammaVal) * COS(alphaVal)\r
-    matrixY1 = COS(betaVal) * SIN(alphaVal)\r
-    matrixZ1 = SIN(gammaVal) * COS(alphaVal) - COS(gammaVal) * SIN(betaVal) * SIN(alphaVal)\r
-\r
-    matrixX2 = SIN(gammaVal) * SIN(betaVal) * COS(alphaVal) - COS(gammaVal) * SIN(alphaVal)\r
-    matrixY2 = COS(betaVal) * COS(alphaVal)\r
-    matrixZ2 = -COS(gammaVal) * SIN(betaVal) * COS(alphaVal) - SIN(gammaVal) * SIN(alphaVal)\r
-\r
-    matrixX3 = -SIN(gammaVal) * COS(betaVal)\r
-    matrixY3 = SIN(betaVal)\r
-    matrixZ3 = COS(gammaVal) * COS(betaVal)\r
-END SUB
\ No newline at end of file
diff --git a/Graphics/3D/rocket simulator.bas b/Graphics/3D/rocket simulator.bas
new file mode 100755 (executable)
index 0000000..ef6029d
--- /dev/null
@@ -0,0 +1,530 @@
+' 3D rocket simulator. Rocket takes off from the surface of the planet.
+'
+' By Svjatoslav Agejenko.
+' Email: svjatoslav@svjatoslav.eu
+' Homepage: http://www.svjatoslav.eu
+
+' Changelog:
+' 2001, Initial version
+' 2024, Improved program readability using AI
+'
+' Usage:
+' arrow keys - move around
+' 2, 6, 4, 8 - look around
+' -          - fly up
+' +          - fly down
+
+DECLARE SUB addp ()
+DECLARE SUB addl ()
+DEFDBL A-Z
+DECLARE SUB teerock ()
+DECLARE SUB teemaa ()
+DECLARE SUB start ()
+DECLARE SUB n3d ()
+
+DIM SHARED pointX(1 TO 1500)
+DIM SHARED pointY(1 TO 1500)
+DIM SHARED pointZ(1 TO 1500)
+
+DIM SHARED linePoint1(1 TO 3000)
+DIM SHARED linePoint2(1 TO 3000)
+DIM SHARED lc(1 TO 3000)
+
+DIM SHARED onScreenPointX(1 TO 1900)
+DIM SHARED onScreenPointY(1 TO 1900)
+
+DIM SHARED rkx(1 TO 200)
+DIM SHARED rky(1 TO 200)
+DIM SHARED rkz(1 TO 200)
+
+DIM SHARED pointCount, lineCount
+DIM SHARED cameraX, cameraY, cameraZ
+DIM SHARED cameraXSpeed, cameraYSpeed, cameraZSpeed
+DIM SHARED my1, my2
+
+DIM SHARED ox1(1 TO 2500)
+DIM SHARED oy1(1 TO 2500)
+DIM SHARED ox2(1 TO 2500)
+DIM SHARED oy2(1 TO 2500)
+DIM SHARED frm, frm2, frm3
+
+DIM SHARED mk, mks, rs, rst
+DIM SHARED pi
+DIM SHARED rkb, rke, rkm
+DIM SHARED rx, ry, rz, rxp, ryp, rzp
+
+DIM SHARED tmr$, ts
+DIM SHARED ale
+
+start
+my1 = -pi / 2
+
+' Initialize the rocket position and velocity
+rx = 0
+ry = mk / 2 + .009
+rz = 0
+
+cameraX = 0
+cameraY = mk / 2
+cameraZ = -.05
+
+ts = 0
+frm2 = 999999
+tmr$ = TIME$
+1
+frm = frm + 1
+frm2 = frm2 + 1
+
+' Display the current values of some variables
+LOCATE 1, 1
+PRINT pointCount, lineCount, mk, mks
+LOCATE 2, 1
+PRINT rkb, rke, TIMER
+
+' Update rocket position and velocity
+rx = rx + (rxp * ts)
+ry = ry + (ryp * ts)
+rz = rz + (rzp * ts)
+
+' Update the rocket's pitch and roll rates
+ryp = ryp + (.0098 * ts)
+rxp = SIN(frm / 20) / 50
+
+' Update the points that make up the rocket
+FOR a = 1 TO rkm
+    pointX(a + rkb - 1) = rkx(a) + rx
+    pointY(a + rkb - 1) = rky(a) + ry
+    pointZ(a + rkb - 1) = rkz(a) + rz
+NEXT a
+
+' Update the observer position and velocity
+cameraX = cameraX + (cameraXSpeed * ts)
+cameraY = cameraY + (cameraYSpeed * ts)
+cameraZ = cameraZ + (cameraZSpeed * ts)
+
+' Draw the 3D scene
+n3d
+
+' Handle user input
+a$ = INKEY$
+IF a$ <> "" THEN
+    IF a$ = CHR$(0) + "H" THEN
+        ' Move forward
+        cameraZSpeed = cameraZSpeed - SIN(my1) / 100
+        cameraXSpeed = cameraXSpeed + COS(my1) / 100
+    END IF
+    IF a$ = CHR$(0) + "P" THEN
+        ' Move backward
+        cameraZSpeed = cameraZSpeed + SIN(my1) / 100
+        cameraXSpeed = cameraXSpeed - COS(my1) / 100
+    END IF
+    IF a$ = CHR$(0) + "M" THEN
+        ' Move right
+        cameraZSpeed = cameraZSpeed + COS(my1) / 100
+        cameraXSpeed = cameraXSpeed + SIN(my1) / 100
+    END IF
+    IF a$ = CHR$(0) + "K" THEN
+        ' Move left
+        cameraZSpeed = cameraZSpeed - COS(my1) / 100
+        cameraXSpeed = cameraXSpeed - SIN(my1) / 100
+    END IF
+
+    ' Change the viewing angle
+    IF a$ = CHR$(27) THEN SYSTEM
+    IF a$ = "4" THEN my1 = my1 + .1
+    IF a$ = "6" THEN my1 = my1 - .1
+    IF a$ = "2" THEN my2 = my2 + .1
+    IF a$ = "8" THEN my2 = my2 - .1
+    IF a$ = "-" THEN cameraYSpeed = cameraYSpeed + .01
+    IF a$ = "+" THEN cameraYSpeed = cameraYSpeed - .01
+    IF a$ = " " THEN cameraZSpeed = cameraZSpeed / 2: cameraXSpeed = cameraXSpeed / 2
+END IF
+
+' Calculate the speed and distance of the rocket
+v = SQR(rx * rx + ry * ry + rz * rz)
+s = SQR(rxp * rxp + ryp * ryp + rzp * rzp)
+
+' Display the current frame rate and other information
+IF tmr$ <> TIME$ THEN
+    tmr$ = TIME$
+
+    LOCATE 29, 1
+    PRINT "speed"; INT(s * 1000)
+    LOCATE 30, 1
+    PRINT "fps"; frm3; "timeslice"; INT(ts * 1000); "distance"; v;
+
+    ' Update the frame rate and time slice
+    frm3 = frm2
+    ts = 1 / frm3
+    frm2 = 0
+
+    ' Add new points to the scene
+    addp
+    addl
+END IF
+GOTO 1
+
+SUB addl
+pointCount = pointCount + 1
+pointX(pointCount) = rx
+pointY(pointCount) = ry
+pointZ(pointCount) = rz
+
+IF ale > 0 THEN
+    lineCount = lineCount + 1
+    linePoint1(lineCount) = ale
+    linePoint2(lineCount) = pointCount
+    lc(lineCount) = 13
+END IF
+
+ale = pointCount
+END SUB
+
+SUB addp
+' Add new points to the scene
+pointCount = pointCount + 1
+pointX(pointCount) = rx
+pointY(pointCount) = ry
+pointZ(pointCount) = rz
+
+pointCount = pointCount + 1
+pointX(pointCount) = rx - .001
+pointY(pointCount) = ry - .001
+pointZ(pointCount) = rz
+
+pointCount = pointCount + 1
+pointX(pointCount) = rx + .001
+pointY(pointCount) = ry - .001
+pointZ(pointCount) = rz
+
+lineCount = lineCount + 1
+linePoint1(lineCount) = pointCount
+linePoint2(lineCount) = pointCount - 1
+lc(lineCount) = 14
+
+lineCount = lineCount + 1
+linePoint1(lineCount) = pointCount - 2
+linePoint2(lineCount) = pointCount - 1
+lc(lineCount) = 14
+
+lineCount = lineCount + 1
+linePoint1(lineCount) = pointCount
+linePoint2(lineCount) = pointCount - 2
+lc(lineCount) = 14
+
+END SUB
+
+SUB n3d
+' Convert the 3D points to 2D for drawing
+s1 = SIN(my1)
+c1 = COS(my1)
+
+s2 = SIN(my2)
+c2 = COS(my2)
+
+FOR a = 1 TO pointCount
+    x = pointX(a) - cameraX
+    y = pointY(a) - cameraY
+    z = pointZ(a) - cameraZ
+
+    ' Apply the rotation transformations
+    x1 = x * s1 + z * c1
+    z1 = x * c1 - z * s1
+
+    y1 = z1 * s2 + y * c2
+    z2 = z1 * c2 - y * s2
+
+    ' Project the 3D point to 2D
+    IF z2 < .00001 THEN
+        onScreenPointX(a) = -1
+    ELSE
+        onScreenPointX(a) = x1 / z2 * 200 + 320
+        onScreenPointY(a) = 240 - y1 / z2 * 200
+
+        ' Check if the point is within the screen boundaries
+        IF onScreenPointX(a) < -50 OR onScreenPointX(a) > 1000 OR onScreenPointY(a) > 1000 THEN
+            onScreenPointX(a) = -1
+        END IF
+    END IF
+NEXT a
+
+' Draw the lines that make up the rocket
+FOR a = 1 TO lineCount
+    p1 = linePoint1(a)
+    p2 = linePoint2(a)
+    x1 = onScreenPointX(p1)
+    y1 = onScreenPointY(p1)
+    x2 = onScreenPointX(p2)
+    y2 = onScreenPointY(p2)
+
+    ' Check if the line is within the screen boundaries.
+    ' If so, erase line at old locations
+    IF ox1(a) = -1 OR ox2(a) = -1 THEN
+        ELSE
+            LINE (ox1(a), oy1(a))-(ox2(a), oy2(a)), 0
+    END IF
+
+    ' Draw the line if both endpoints are within the screen boundaries
+    IF x1 <> -1 AND x2 <> -1 THEN
+        LINE (x1, y1)-(x2, y2), lc(a)
+    END IF
+
+    ' Update the old endpoints of the line for the next frame
+    ox1(a) = x1
+    oy1(a) = y1
+    ox2(a) = x2
+    oy2(a) = y2
+NEXT a
+
+END SUB
+
+SUB start
+' Initialize the graphics mode and set up the scene
+SCREEN 12
+VIEW PRINT 1 TO 30
+
+mk = 12714
+mks = 500
+rst = 4
+pi = 3.142657
+rs = .00002
+frm2 = 0
+
+ale = -1
+pointX(1) = -.001
+pointY(1) = mk / 2
+pointZ(1) = -.001
+
+pointX(2) = .001
+pointY(2) = mk / 2
+pointZ(2) = -.001
+
+pointX(3) = .001
+pointY(3) = mk / 2
+pointZ(3) = .001
+
+pointX(4) = -.001
+pointY(4) = mk / 2
+pointZ(4) = .001
+
+pointCount = 4
+
+' Set up the initial lines that make up the rocket
+linePoint1(1) = 1
+linePoint2(1) = 2
+lc(1) = 14
+
+linePoint1(2) = 2
+linePoint2(2) = 3
+lc(2) = 14
+
+linePoint1(3) = 3
+linePoint2(3) = 4
+lc(3) = 14
+
+linePoint1(4) = 4
+linePoint2(4) = 1
+lc(4) = 14
+
+lineCount = 4
+
+' Initialize the observer position and velocity
+cameraX = 0
+cameraY = mk * 2
+cameraZ = -35
+
+teemaa
+cameraXSpeed = 0
+cameraYSpeed = 0
+cameraZSpeed = 0
+
+my1 = 0
+
+rkb = pointCount + 1
+teerock
+rke = pointCount
+
+' Calculate the number of points that make up the rocket
+rkm = rke - rkb + 1
+
+' Copy the initial points to the arrays for the rocket
+FOR a = 1 TO rkm
+    p = rkb + a - 1
+    rkx(a) = pointX(p)
+    rky(a) = pointY(p)
+    rkz(a) = pointZ(p)
+NEXT a
+
+END SUB
+
+SUB teemaa
+' Generate the points that make up the earth
+tmpp = pointCount
+le2 = 0
+
+FOR z = -(mk / 3) TO (mk / 3) STEP mks
+    le = 0
+    le2 = le2 + 1
+
+    FOR x = -(mk / 3) TO (mk / 3) STEP mks
+        ' Check if the point is within the rocket's radius
+        IF SQR(x * x + z * z) > (mk / 2.5) THEN GOTO 4
+
+        le = le + 1
+
+        ' Add the first point of the line
+        IF le = 1 THEN
+            xs = x / mks
+        END IF
+
+        pointCount = pointCount + 1
+        pointX(pointCount) = x
+        v = SQR(x * x + z * z)
+        pointY(pointCount) = SQR((v + (mk / 2)) * ((mk / 2) - v))
+        pointZ(pointCount) = z
+
+        ' Add the line to the list of lines
+        IF le > 1 THEN
+            lineCount = lineCount + 1
+            linePoint1(lineCount) = pointCount
+            linePoint2(lineCount) = pointCount - 1
+            lc(lineCount) = 3
+        END IF
+
+        ' Add the line to the list of lines if it is part of a circle
+        IF le2 > 1 THEN
+            IF xso > (x / mks) THEN GOTO 4
+            IF xso + leo <= (x / mks) THEN GOTO 4
+
+            lineCount = lineCount + 1
+            linePoint1(lineCount) = pointCount
+            linePoint2(lineCount) = pointCount - leo - xso + xs
+            lc(lineCount) = 3
+        END IF
+
+    4
+    NEXT x
+
+    ' Update the variables for the next circle
+    leo = le
+    xso = xs
+NEXT z
+
+END SUB
+
+SUB teerock
+' Generate the points that make up the rocket
+s = 50
+
+FOR y = -9 TO 10 STEP rst
+    st = pi * 2 / 6
+
+    IF y > 5 THEN
+        s = s - 3
+    END IF
+
+    IF y > 8 THEN
+        s = s - 6
+    END IF
+
+    FOR a = 0 TO pi * 2 STEP st
+        x1 = SIN(a) * s
+        z1 = COS(a) * s
+
+        pointCount = pointCount + 1
+        pointX(pointCount) = x1 * rs
+        pointY(pointCount) = y * 50 * rs
+        pointZ(pointCount) = z1 * rs
+
+        ' Add the line to the list of lines
+        IF a > 0 THEN
+            lineCount = lineCount + 1
+            linePoint1(lineCount) = pointCount
+            linePoint2(lineCount) = pointCount - 1
+            lc(lineCount) = 10
+        END IF
+
+        ' Add the line to the list of lines if it is part of a circle
+        IF y > -9 THEN
+            lineCount = lineCount + 1
+            linePoint1(lineCount) = pointCount
+            linePoint2(lineCount) = pointCount - 7
+            lc(lineCount) = 10
+        END IF
+
+    NEXT a
+NEXT y
+
+' Add the points that make up the top of the rocket
+pointCount = pointCount + 1
+pointX(pointCount) = 0
+pointY(pointCount) = 11 * 50 * rs
+pointZ(pointCount) = 0
+
+FOR a = 1 TO 6
+    lineCount = lineCount + 1
+    linePoint1(lineCount) = pointCount
+    linePoint2(lineCount) = pointCount - a
+    lc(lineCount) = 10
+NEXT a
+
+' Add the points that make up the bottom of the rocket
+pointCount = pointCount + 1
+pointX(pointCount) = -100 * rs
+pointY(pointCount) = -450 * rs
+pointZ(pointCount) = 0
+
+pointCount = pointCount + 1
+pointX(pointCount) = 100 * rs
+pointY(pointCount) = -450 * rs
+pointZ(pointCount) = 0
+
+pointCount = pointCount + 1
+pointX(pointCount) = 0
+pointY(pointCount) = -200 * rs
+pointZ(pointCount) = 0
+
+lineCount = lineCount + 1
+linePoint1(lineCount) = pointCount
+linePoint2(lineCount) = pointCount - 1
+lc(lineCount) = 12
+
+lineCount = lineCount + 1
+linePoint1(lineCount) = pointCount - 2
+linePoint2(lineCount) = pointCount - 1
+lc(lineCount) = 12
+
+lineCount = lineCount + 1
+linePoint1(lineCount) = pointCount
+linePoint2(lineCount) = pointCount - 2
+lc(lineCount) = 12
+
+
+
+pointCount = pointCount + 1
+pointX(pointCount) = 0
+pointY(pointCount) = -450 * rs
+pointZ(pointCount) = -100 * rs
+
+pointCount = pointCount + 1
+pointX(pointCount) = 0
+pointY(pointCount) = -450 * rs
+pointZ(pointCount) = 100 * rs
+
+
+lineCount = lineCount + 1
+linePoint1(lineCount) = pointCount
+linePoint2(lineCount) = pointCount - 1
+lc(lineCount) = 12
+
+lineCount = lineCount + 1
+linePoint1(lineCount) = pointCount - 2
+linePoint2(lineCount) = pointCount - 1
+lc(lineCount) = 12
+
+lineCount = lineCount + 1
+linePoint1(lineCount) = pointCount
+linePoint2(lineCount) = pointCount - 2
+lc(lineCount) = 12
+
+END SUB
diff --git a/Graphics/3D/rocket simulator.webm b/Graphics/3D/rocket simulator.webm
new file mode 100644 (file)
index 0000000..7e10602
Binary files /dev/null and b/Graphics/3D/rocket simulator.webm differ
diff --git a/Graphics/3D/rocket.bas b/Graphics/3D/rocket.bas
deleted file mode 100755 (executable)
index ef6029d..0000000
+++ /dev/null
@@ -1,530 +0,0 @@
-' 3D rocket simulator. Rocket takes off from the surface of the planet.
-'
-' By Svjatoslav Agejenko.
-' Email: svjatoslav@svjatoslav.eu
-' Homepage: http://www.svjatoslav.eu
-
-' Changelog:
-' 2001, Initial version
-' 2024, Improved program readability using AI
-'
-' Usage:
-' arrow keys - move around
-' 2, 6, 4, 8 - look around
-' -          - fly up
-' +          - fly down
-
-DECLARE SUB addp ()
-DECLARE SUB addl ()
-DEFDBL A-Z
-DECLARE SUB teerock ()
-DECLARE SUB teemaa ()
-DECLARE SUB start ()
-DECLARE SUB n3d ()
-
-DIM SHARED pointX(1 TO 1500)
-DIM SHARED pointY(1 TO 1500)
-DIM SHARED pointZ(1 TO 1500)
-
-DIM SHARED linePoint1(1 TO 3000)
-DIM SHARED linePoint2(1 TO 3000)
-DIM SHARED lc(1 TO 3000)
-
-DIM SHARED onScreenPointX(1 TO 1900)
-DIM SHARED onScreenPointY(1 TO 1900)
-
-DIM SHARED rkx(1 TO 200)
-DIM SHARED rky(1 TO 200)
-DIM SHARED rkz(1 TO 200)
-
-DIM SHARED pointCount, lineCount
-DIM SHARED cameraX, cameraY, cameraZ
-DIM SHARED cameraXSpeed, cameraYSpeed, cameraZSpeed
-DIM SHARED my1, my2
-
-DIM SHARED ox1(1 TO 2500)
-DIM SHARED oy1(1 TO 2500)
-DIM SHARED ox2(1 TO 2500)
-DIM SHARED oy2(1 TO 2500)
-DIM SHARED frm, frm2, frm3
-
-DIM SHARED mk, mks, rs, rst
-DIM SHARED pi
-DIM SHARED rkb, rke, rkm
-DIM SHARED rx, ry, rz, rxp, ryp, rzp
-
-DIM SHARED tmr$, ts
-DIM SHARED ale
-
-start
-my1 = -pi / 2
-
-' Initialize the rocket position and velocity
-rx = 0
-ry = mk / 2 + .009
-rz = 0
-
-cameraX = 0
-cameraY = mk / 2
-cameraZ = -.05
-
-ts = 0
-frm2 = 999999
-tmr$ = TIME$
-1
-frm = frm + 1
-frm2 = frm2 + 1
-
-' Display the current values of some variables
-LOCATE 1, 1
-PRINT pointCount, lineCount, mk, mks
-LOCATE 2, 1
-PRINT rkb, rke, TIMER
-
-' Update rocket position and velocity
-rx = rx + (rxp * ts)
-ry = ry + (ryp * ts)
-rz = rz + (rzp * ts)
-
-' Update the rocket's pitch and roll rates
-ryp = ryp + (.0098 * ts)
-rxp = SIN(frm / 20) / 50
-
-' Update the points that make up the rocket
-FOR a = 1 TO rkm
-    pointX(a + rkb - 1) = rkx(a) + rx
-    pointY(a + rkb - 1) = rky(a) + ry
-    pointZ(a + rkb - 1) = rkz(a) + rz
-NEXT a
-
-' Update the observer position and velocity
-cameraX = cameraX + (cameraXSpeed * ts)
-cameraY = cameraY + (cameraYSpeed * ts)
-cameraZ = cameraZ + (cameraZSpeed * ts)
-
-' Draw the 3D scene
-n3d
-
-' Handle user input
-a$ = INKEY$
-IF a$ <> "" THEN
-    IF a$ = CHR$(0) + "H" THEN
-        ' Move forward
-        cameraZSpeed = cameraZSpeed - SIN(my1) / 100
-        cameraXSpeed = cameraXSpeed + COS(my1) / 100
-    END IF
-    IF a$ = CHR$(0) + "P" THEN
-        ' Move backward
-        cameraZSpeed = cameraZSpeed + SIN(my1) / 100
-        cameraXSpeed = cameraXSpeed - COS(my1) / 100
-    END IF
-    IF a$ = CHR$(0) + "M" THEN
-        ' Move right
-        cameraZSpeed = cameraZSpeed + COS(my1) / 100
-        cameraXSpeed = cameraXSpeed + SIN(my1) / 100
-    END IF
-    IF a$ = CHR$(0) + "K" THEN
-        ' Move left
-        cameraZSpeed = cameraZSpeed - COS(my1) / 100
-        cameraXSpeed = cameraXSpeed - SIN(my1) / 100
-    END IF
-
-    ' Change the viewing angle
-    IF a$ = CHR$(27) THEN SYSTEM
-    IF a$ = "4" THEN my1 = my1 + .1
-    IF a$ = "6" THEN my1 = my1 - .1
-    IF a$ = "2" THEN my2 = my2 + .1
-    IF a$ = "8" THEN my2 = my2 - .1
-    IF a$ = "-" THEN cameraYSpeed = cameraYSpeed + .01
-    IF a$ = "+" THEN cameraYSpeed = cameraYSpeed - .01
-    IF a$ = " " THEN cameraZSpeed = cameraZSpeed / 2: cameraXSpeed = cameraXSpeed / 2
-END IF
-
-' Calculate the speed and distance of the rocket
-v = SQR(rx * rx + ry * ry + rz * rz)
-s = SQR(rxp * rxp + ryp * ryp + rzp * rzp)
-
-' Display the current frame rate and other information
-IF tmr$ <> TIME$ THEN
-    tmr$ = TIME$
-
-    LOCATE 29, 1
-    PRINT "speed"; INT(s * 1000)
-    LOCATE 30, 1
-    PRINT "fps"; frm3; "timeslice"; INT(ts * 1000); "distance"; v;
-
-    ' Update the frame rate and time slice
-    frm3 = frm2
-    ts = 1 / frm3
-    frm2 = 0
-
-    ' Add new points to the scene
-    addp
-    addl
-END IF
-GOTO 1
-
-SUB addl
-pointCount = pointCount + 1
-pointX(pointCount) = rx
-pointY(pointCount) = ry
-pointZ(pointCount) = rz
-
-IF ale > 0 THEN
-    lineCount = lineCount + 1
-    linePoint1(lineCount) = ale
-    linePoint2(lineCount) = pointCount
-    lc(lineCount) = 13
-END IF
-
-ale = pointCount
-END SUB
-
-SUB addp
-' Add new points to the scene
-pointCount = pointCount + 1
-pointX(pointCount) = rx
-pointY(pointCount) = ry
-pointZ(pointCount) = rz
-
-pointCount = pointCount + 1
-pointX(pointCount) = rx - .001
-pointY(pointCount) = ry - .001
-pointZ(pointCount) = rz
-
-pointCount = pointCount + 1
-pointX(pointCount) = rx + .001
-pointY(pointCount) = ry - .001
-pointZ(pointCount) = rz
-
-lineCount = lineCount + 1
-linePoint1(lineCount) = pointCount
-linePoint2(lineCount) = pointCount - 1
-lc(lineCount) = 14
-
-lineCount = lineCount + 1
-linePoint1(lineCount) = pointCount - 2
-linePoint2(lineCount) = pointCount - 1
-lc(lineCount) = 14
-
-lineCount = lineCount + 1
-linePoint1(lineCount) = pointCount
-linePoint2(lineCount) = pointCount - 2
-lc(lineCount) = 14
-
-END SUB
-
-SUB n3d
-' Convert the 3D points to 2D for drawing
-s1 = SIN(my1)
-c1 = COS(my1)
-
-s2 = SIN(my2)
-c2 = COS(my2)
-
-FOR a = 1 TO pointCount
-    x = pointX(a) - cameraX
-    y = pointY(a) - cameraY
-    z = pointZ(a) - cameraZ
-
-    ' Apply the rotation transformations
-    x1 = x * s1 + z * c1
-    z1 = x * c1 - z * s1
-
-    y1 = z1 * s2 + y * c2
-    z2 = z1 * c2 - y * s2
-
-    ' Project the 3D point to 2D
-    IF z2 < .00001 THEN
-        onScreenPointX(a) = -1
-    ELSE
-        onScreenPointX(a) = x1 / z2 * 200 + 320
-        onScreenPointY(a) = 240 - y1 / z2 * 200
-
-        ' Check if the point is within the screen boundaries
-        IF onScreenPointX(a) < -50 OR onScreenPointX(a) > 1000 OR onScreenPointY(a) > 1000 THEN
-            onScreenPointX(a) = -1
-        END IF
-    END IF
-NEXT a
-
-' Draw the lines that make up the rocket
-FOR a = 1 TO lineCount
-    p1 = linePoint1(a)
-    p2 = linePoint2(a)
-    x1 = onScreenPointX(p1)
-    y1 = onScreenPointY(p1)
-    x2 = onScreenPointX(p2)
-    y2 = onScreenPointY(p2)
-
-    ' Check if the line is within the screen boundaries.
-    ' If so, erase line at old locations
-    IF ox1(a) = -1 OR ox2(a) = -1 THEN
-        ELSE
-            LINE (ox1(a), oy1(a))-(ox2(a), oy2(a)), 0
-    END IF
-
-    ' Draw the line if both endpoints are within the screen boundaries
-    IF x1 <> -1 AND x2 <> -1 THEN
-        LINE (x1, y1)-(x2, y2), lc(a)
-    END IF
-
-    ' Update the old endpoints of the line for the next frame
-    ox1(a) = x1
-    oy1(a) = y1
-    ox2(a) = x2
-    oy2(a) = y2
-NEXT a
-
-END SUB
-
-SUB start
-' Initialize the graphics mode and set up the scene
-SCREEN 12
-VIEW PRINT 1 TO 30
-
-mk = 12714
-mks = 500
-rst = 4
-pi = 3.142657
-rs = .00002
-frm2 = 0
-
-ale = -1
-pointX(1) = -.001
-pointY(1) = mk / 2
-pointZ(1) = -.001
-
-pointX(2) = .001
-pointY(2) = mk / 2
-pointZ(2) = -.001
-
-pointX(3) = .001
-pointY(3) = mk / 2
-pointZ(3) = .001
-
-pointX(4) = -.001
-pointY(4) = mk / 2
-pointZ(4) = .001
-
-pointCount = 4
-
-' Set up the initial lines that make up the rocket
-linePoint1(1) = 1
-linePoint2(1) = 2
-lc(1) = 14
-
-linePoint1(2) = 2
-linePoint2(2) = 3
-lc(2) = 14
-
-linePoint1(3) = 3
-linePoint2(3) = 4
-lc(3) = 14
-
-linePoint1(4) = 4
-linePoint2(4) = 1
-lc(4) = 14
-
-lineCount = 4
-
-' Initialize the observer position and velocity
-cameraX = 0
-cameraY = mk * 2
-cameraZ = -35
-
-teemaa
-cameraXSpeed = 0
-cameraYSpeed = 0
-cameraZSpeed = 0
-
-my1 = 0
-
-rkb = pointCount + 1
-teerock
-rke = pointCount
-
-' Calculate the number of points that make up the rocket
-rkm = rke - rkb + 1
-
-' Copy the initial points to the arrays for the rocket
-FOR a = 1 TO rkm
-    p = rkb + a - 1
-    rkx(a) = pointX(p)
-    rky(a) = pointY(p)
-    rkz(a) = pointZ(p)
-NEXT a
-
-END SUB
-
-SUB teemaa
-' Generate the points that make up the earth
-tmpp = pointCount
-le2 = 0
-
-FOR z = -(mk / 3) TO (mk / 3) STEP mks
-    le = 0
-    le2 = le2 + 1
-
-    FOR x = -(mk / 3) TO (mk / 3) STEP mks
-        ' Check if the point is within the rocket's radius
-        IF SQR(x * x + z * z) > (mk / 2.5) THEN GOTO 4
-
-        le = le + 1
-
-        ' Add the first point of the line
-        IF le = 1 THEN
-            xs = x / mks
-        END IF
-
-        pointCount = pointCount + 1
-        pointX(pointCount) = x
-        v = SQR(x * x + z * z)
-        pointY(pointCount) = SQR((v + (mk / 2)) * ((mk / 2) - v))
-        pointZ(pointCount) = z
-
-        ' Add the line to the list of lines
-        IF le > 1 THEN
-            lineCount = lineCount + 1
-            linePoint1(lineCount) = pointCount
-            linePoint2(lineCount) = pointCount - 1
-            lc(lineCount) = 3
-        END IF
-
-        ' Add the line to the list of lines if it is part of a circle
-        IF le2 > 1 THEN
-            IF xso > (x / mks) THEN GOTO 4
-            IF xso + leo <= (x / mks) THEN GOTO 4
-
-            lineCount = lineCount + 1
-            linePoint1(lineCount) = pointCount
-            linePoint2(lineCount) = pointCount - leo - xso + xs
-            lc(lineCount) = 3
-        END IF
-
-    4
-    NEXT x
-
-    ' Update the variables for the next circle
-    leo = le
-    xso = xs
-NEXT z
-
-END SUB
-
-SUB teerock
-' Generate the points that make up the rocket
-s = 50
-
-FOR y = -9 TO 10 STEP rst
-    st = pi * 2 / 6
-
-    IF y > 5 THEN
-        s = s - 3
-    END IF
-
-    IF y > 8 THEN
-        s = s - 6
-    END IF
-
-    FOR a = 0 TO pi * 2 STEP st
-        x1 = SIN(a) * s
-        z1 = COS(a) * s
-
-        pointCount = pointCount + 1
-        pointX(pointCount) = x1 * rs
-        pointY(pointCount) = y * 50 * rs
-        pointZ(pointCount) = z1 * rs
-
-        ' Add the line to the list of lines
-        IF a > 0 THEN
-            lineCount = lineCount + 1
-            linePoint1(lineCount) = pointCount
-            linePoint2(lineCount) = pointCount - 1
-            lc(lineCount) = 10
-        END IF
-
-        ' Add the line to the list of lines if it is part of a circle
-        IF y > -9 THEN
-            lineCount = lineCount + 1
-            linePoint1(lineCount) = pointCount
-            linePoint2(lineCount) = pointCount - 7
-            lc(lineCount) = 10
-        END IF
-
-    NEXT a
-NEXT y
-
-' Add the points that make up the top of the rocket
-pointCount = pointCount + 1
-pointX(pointCount) = 0
-pointY(pointCount) = 11 * 50 * rs
-pointZ(pointCount) = 0
-
-FOR a = 1 TO 6
-    lineCount = lineCount + 1
-    linePoint1(lineCount) = pointCount
-    linePoint2(lineCount) = pointCount - a
-    lc(lineCount) = 10
-NEXT a
-
-' Add the points that make up the bottom of the rocket
-pointCount = pointCount + 1
-pointX(pointCount) = -100 * rs
-pointY(pointCount) = -450 * rs
-pointZ(pointCount) = 0
-
-pointCount = pointCount + 1
-pointX(pointCount) = 100 * rs
-pointY(pointCount) = -450 * rs
-pointZ(pointCount) = 0
-
-pointCount = pointCount + 1
-pointX(pointCount) = 0
-pointY(pointCount) = -200 * rs
-pointZ(pointCount) = 0
-
-lineCount = lineCount + 1
-linePoint1(lineCount) = pointCount
-linePoint2(lineCount) = pointCount - 1
-lc(lineCount) = 12
-
-lineCount = lineCount + 1
-linePoint1(lineCount) = pointCount - 2
-linePoint2(lineCount) = pointCount - 1
-lc(lineCount) = 12
-
-lineCount = lineCount + 1
-linePoint1(lineCount) = pointCount
-linePoint2(lineCount) = pointCount - 2
-lc(lineCount) = 12
-
-
-
-pointCount = pointCount + 1
-pointX(pointCount) = 0
-pointY(pointCount) = -450 * rs
-pointZ(pointCount) = -100 * rs
-
-pointCount = pointCount + 1
-pointX(pointCount) = 0
-pointY(pointCount) = -450 * rs
-pointZ(pointCount) = 100 * rs
-
-
-lineCount = lineCount + 1
-linePoint1(lineCount) = pointCount
-linePoint2(lineCount) = pointCount - 1
-lc(lineCount) = 12
-
-lineCount = lineCount + 1
-linePoint1(lineCount) = pointCount - 2
-linePoint2(lineCount) = pointCount - 1
-lc(lineCount) = 12
-
-lineCount = lineCount + 1
-linePoint1(lineCount) = pointCount
-linePoint2(lineCount) = pointCount - 2
-lc(lineCount) = 12
-
-END SUB
diff --git a/Graphics/3D/stars.webm b/Graphics/3D/stars.webm
new file mode 100644 (file)
index 0000000..39cd97e
Binary files /dev/null and b/Graphics/3D/stars.webm differ
diff --git a/Graphics/3D/tank on the bridge.bas b/Graphics/3D/tank on the bridge.bas
new file mode 100755 (executable)
index 0000000..6b34f9f
--- /dev/null
@@ -0,0 +1,792 @@
+' Program to render animated 3D tank that drives back and forth on the 3D bridge.
+' Notably, tracks on the tank are properly synchronized with the tank movement.
+' User can freely look and fly around in the space.
+'
+' By Svjatoslav Agejenko.
+' Email: svjatoslav@svjatoslav.eu
+' Homepage: http://www.svjatoslav.eu
+'
+' Changelog:
+' 2000, Initial version
+' 2024, Improved program readability using AI
+
+' Use keys to move around:
+' Left, Right, Up, Down   look around
+' + move forward
+' - move back
+' q quit
+' <space> - stop
+
+DECLARE SUB start ()
+DECLARE SUB savepos (x1%, y1%, x2%, y2%)
+DECLARE SUB teemaad ()
+DECLARE SUB setTracks ()
+DECLARE SUB getTracks ()
+DECLARE SUB getTracks1 (x1%, y1%, x2%, y2%)
+DECLARE SUB kiri ()
+DECLARE SUB getcor ()
+DECLARE SUB mulcor ()
+DECLARE SUB nait3d ()
+DECLARE SUB calcsin ()
+DEFINT A-Y
+DIM SHARED xn(1000), yn(1000), czn(1000) ' points transformed to on-screen coordinates
+DIM SHARED pointX(1000), pointY(1000), pointZ(1000) ' points in 3D space
+DIM SHARED Xs1(1000), Ys1(1000), Xe1(1000), Ye1(1000) ' Old rotated points
+DIM SHARED pointers1(1000), pointers2(1000)   ' Connected points
+DIM SHARED cosine&(360), sine&(360)    ' SIN & COS table
+DIM SHARED np, nl
+
+DIM SHARED Tracksx(1 TO 1000)
+DIM SHARED Tracksy(1 TO 1000)
+DIM SHARED mitTracks
+DIM SHARED smes
+
+' Pointers to the beginning of the tank tracks, this is needed to animate tank tracks
+DIM SHARED TracksBeginp ' point index
+DIM SHARED TracksBeginl ' line index
+
+' Pointers to the beginning of the bridge
+DIM SHARED BridgeBeginp    ' point index
+DIM SHARED BridgeBeginl    ' line index  
+
+DIM SHARED Tracksxp
+DIM SHARED myx, myy, myz
+DIM SHARED myxp, myyp, myzp
+
+DIM SHARED deg1, deg2, deg3
+DIM SHARED speed
+
+DIM SHARED ssu
+
+start
+
+nait3d
+
+DATA -10,-30,-20
+DATA 30,-30,-20
+DATA 30,-10,-20
+DATA -10,-10,-20
+
+DATA -10,-30,20
+DATA 30,-30,20
+DATA 30,-10,20
+DATA -10,-10,20
+
+DATA -10,-40,-15
+DATA 30,-40,-15
+DATA -10,-40,15
+DATA 30,-40,15
+
+DATA -20,-30,-15
+DATA -20,-30, 15
+
+DATA -70,-10,-50
+DATA 60,-10, -50
+DATA 70,  0, -50
+DATA 70, 20, -50
+DATA 60, 30, -50
+DATA -70,30, -50
+DATA -80,20, -50
+DATA -80, 0, -50
+
+DATA -70,-10,-30
+DATA 60,-10, -30
+DATA 70,  0, -30
+DATA 70, 20, -30
+DATA 60, 30, -30
+DATA -70,30, -30
+DATA -80,20, -30
+DATA -80, 0, -30
+
+DATA -70,-10, 50
+DATA 60,-10,  50
+DATA 70,  0,  50
+DATA 70, 20,  50
+DATA 60, 30,  50
+DATA -70,30,  50
+DATA -80,20,  50
+DATA -80, 0,  50
+
+DATA -70,-10, 30
+DATA 60,-10,  30
+DATA 70,  0,  30
+DATA 70, 20,  30
+DATA 60, 30,  30
+DATA -70,30,  30
+DATA -80,20,  30
+DATA -80, 0,  30
+
+DATA -50,-7,-30
+DATA  50,-7,-30
+DATA  50, 15,-30
+DATA -50, 15,-30
+
+DATA -50,-7, 30
+DATA  50,-7, 30
+DATA  50, 15,30
+DATA -50, 15,30
+
+DATA -20,-20,-5
+DATA -20,-20, 5
+DATA -20,-30, 5
+DATA -20,-30,-5
+
+DATA -100,-30,-5
+DATA -100,-30, 5
+DATA -100,-40, 5
+DATA -100,-40,-5
+
+DATA 999,999,999
+
+DATA 0,1
+DATA 1,2
+DATA 2,3
+DATA 3,0
+
+DATA 4,5
+DATA 5,6
+DATA 6,7
+DATA 7,4
+
+DATA 0,8
+DATA 1,9
+DATA 4,10
+DATA 5,11
+
+DATA 0,12
+DATA 4,13
+DATA 12,8
+DATA 13,10
+
+DATA 8,9
+DATA 10,11
+DATA 8,10
+DATA 9,11
+
+DATA 12,13
+DATA 12,3
+DATA 13,7
+DATA 3,7
+DATA 1,5
+DATA 2,6
+
+DATA 14,15
+DATA 15,16
+DATA 16,17
+DATA 17,18
+DATA 18,19
+DATA 19,20
+DATA 20,21
+DATA 21,14
+
+DATA 22,23
+DATA 23,24
+DATA 24,25
+DATA 25,26
+DATA 26,27
+DATA 27,28
+DATA 28,29
+DATA 29,22
+
+DATA 30,31
+DATA 31,32
+DATA 32,33
+DATA 33,34
+DATA 34,35
+DATA 35,36
+DATA 36,37
+DATA 37,30
+
+DATA 38,39
+DATA 39,40
+DATA 40,41
+DATA 41,42
+DATA 42,43
+DATA 43,44
+DATA 44,45
+DATA 45,38
+
+DATA 46,47
+DATA 47,48
+DATA 48,49
+DATA 49,46
+
+DATA 50,51
+DATA 51,52
+DATA 52,53
+DATA 53,50
+
+DATA 50,46
+DATA 51,47
+DATA 52,48
+DATA 53,49
+
+DATA 54,55
+DATA 55,56
+DATA 56,57
+DATA 57,54
+
+DATA 54,58
+DATA 55,59
+DATA 56,60
+DATA 57,61
+
+DATA 58,59
+DATA 59,60
+DATA 60,61
+DATA 61,58
+
+DATA 54,3
+DATA 55,7
+
+DATA 999, 999
+'                                                          BRIDGE
+'                                                 right handlebars
+DATA 100,0,100
+DATA 100,50,100
+
+DATA 50,0,100
+DATA 50,50,100
+
+DATA 0,0,100
+DATA 0,50,100
+
+DATA -50,0,100
+DATA -50,50,100
+
+DATA -100,0,100
+DATA -100,50,100
+                       ' 5
+DATA -150,0,100
+DATA -150,50,100
+
+DATA -200,0,100
+DATA -200,50,100
+
+DATA -250,0,100
+DATA -250,50,100
+
+DATA -300,0,100
+DATA -300,50,100
+
+DATA -350,0,100
+DATA -350,50,100
+                           ' 10
+
+DATA -400,0,100
+DATA -400,50,100
+
+DATA -450,0,100
+DATA -450,50,100
+
+DATA -500,0,100
+DATA -500,50,100
+
+DATA -550,0,100
+DATA -550,50,100
+
+DATA -600,0,100
+DATA -600,50,100
+
+DATA -650,0,100
+DATA -650,50,100
+
+                    ' left handlebars
+DATA 100,0,-100
+DATA 100,50,-100
+
+DATA 50,0,-100
+DATA 50,50,-100
+
+DATA 0,0,-100
+DATA 0,50,-100
+
+DATA -50,0,-100
+DATA -50,50,-100
+
+DATA -100,0,-100
+DATA -100,50,-100
+                       ' 5
+DATA -150,0,-100
+DATA -150,50,-100
+
+DATA -200,0,-100
+DATA -200,50,-100
+
+DATA -250,0,-100
+DATA -250,50,-100
+
+DATA -300,0,-100
+DATA -300,50,-100
+
+DATA -350,0,-100
+DATA -350,50,-100
+                           ' 10
+
+DATA -400,0,-100
+DATA -400,50,-100
+
+DATA -450,0,-100
+DATA -450,50,-100
+
+DATA -500,0,-100
+DATA -500,50,-100
+
+DATA -550,0,-100
+DATA -550,50,-100
+
+DATA -600,0,-100
+DATA -600,50,-100
+
+DATA -650,0,-100
+DATA -650,50,-100
+                '   bottom line
+DATA 100,75,-100
+DATA -650,75,-100
+
+DATA 100,75,100
+DATA -650,75,100
+                ' shore
+DATA 75,75,-100
+DATA 75,75,100
+                   'right
+DATA -50,200,-100
+DATA -50,200,100
+
+DATA  75,200,-190
+DATA  75,200, 190
+                   'left
+DATA -525,200,-100
+DATA -525,200, 100
+
+DATA -600,200,-190
+DATA -600,200, 190
+
+'
+
+DATA 999,999,999
+
+                 'right handlebars
+
+DATA 2,3
+DATA 4,5
+DATA 6,7
+DATA 8,9
+
+DATA 10,11
+DATA 12,13
+DATA 14,15
+DATA 16,17
+DATA 18,19
+
+DATA 20,21
+DATA 22,23
+DATA 24,25
+DATA 26,27
+DATA 28,29
+
+
+                   'left handlebars
+DATA 34,35
+DATA 36,37
+DATA 38,39
+DATA 40,41
+
+DATA 42,43
+DATA 44,45
+DATA 46,47
+DATA 48,49
+DATA 50,51
+
+DATA 52,53
+DATA 54,55
+DATA 56,57
+DATA 58,59
+DATA 60,61
+
+'          long features
+DATA 0,4
+DATA 4,8
+DATA 8,12
+DATA 12,16
+DATA 16,20
+DATA 20,24
+DATA 24,28
+DATA 28,30
+
+DATA 1,5
+DATA 5,9
+DATA 9,13
+DATA 13,17
+DATA 17,21
+DATA 21,25
+DATA 25,29
+DATA 29,31
+
+DATA 32,36
+DATA 36,40
+DATA 40,44
+DATA 44,48
+DATA 48,52
+DATA 52,56
+DATA 56,60
+DATA 60,62
+
+DATA 33,37
+DATA 37,41
+DATA 41,45
+DATA 45,49
+DATA 49,53
+DATA 53,57
+DATA 57,61
+DATA 61,63
+
+'
+
+'  end
+
+DATA 1,33
+DATA 31,63
+
+DATA 64,65
+DATA 66,67
+DATA 64,66
+DATA 65,67
+
+DATA 0,66
+DATA 32,64
+DATA 30,67
+DATA 62,65
+            ' shore
+DATA 68,69
+DATA 70,71
+DATA 68,70
+DATA 69,71
+
+DATA 72,70
+DATA 72,68
+
+DATA 73,71
+DATA 73,69
+           'left
+DATA 74,76
+DATA 75,77
+DATA 74,75
+
+DATA 74,65
+DATA 76,65
+
+DATA 75,67
+DATA 77,67
+
+DATA 999, 999
+
+DEFINT Z
+SUB calcsin
+' precalculating sine and cosine tables
+
+FOR a! = 0 TO 359 / 57.29577951# STEP 1 / 57.29577951#
+    cosine&(a) = INT(.5 + COS(a!) * 1024)
+    sine&(a) = INT(.5 + SIN(a!) * 1024)
+    a = a + 1
+NEXT
+CLS
+END SUB
+
+DEFSNG Z
+SUB getcor
+' Loading original points and connected points
+FOR a = 0 TO 10000
+    READ pointX(a), pointY(a), pointZ(a)
+    IF pointX(a) = 999 THEN pointX(a) = 0: pointY(a) = 0: pointZ(a) = 0: GOTO 1
+NEXT
+1
+np = a
+FOR a = 0 TO 10000
+    READ pointers1(a), pointers2(a)
+    IF pointers1(a) = 999 THEN GOTO 2
+NEXT
+2
+nl = a
+
+TracksBeginp = np
+TracksBeginl = nl
+
+' Initializing connected points
+FOR a = 1 TO 48
+pointers1(nl) = np
+np = np + 1
+pointers2(nl) = np
+np = np + 1
+nl = nl + 1
+NEXT a
+
+END SUB
+
+DEFINT Z
+SUB getTracks
+
+' Initialize the number of segments
+mitTracks = 1
+getTracks1 -70, -10, -80, 0
+getTracks1 -80, 0, -80, 20
+getTracks1 -80, 20, -70, 30
+getTracks1 -70, 30, 60, 30
+getTracks1 60, 30, 70, 20
+getTracks1 70, 20, 70, 0
+getTracks1 70, 0, 60, -10
+getTracks1 60, -10, -70, -10
+
+END SUB
+
+DEFSNG Z
+SUB getTracks1 (x1%, y1%, x2%, y2%)
+REM Calculating points for a segment
+z1 = ABS(x1 - x2)
+z2 = ABS(y2 - y1)
+mi = SQR(z1 ^ 2 + z2 ^ 2) * 1.017142857#
+
+' Calculating direction vectors
+zxp = (x1 - x2) / mi
+zyp = (y2 - y1) / mi
+zx = x1
+zy = y1
+
+FOR a = 1 TO mi
+    zx = zx - zxp
+    zy = zy + zyp
+    Tracksx(mitTracks) = zx
+    Tracksy(mitTracks) = zy
+    mitTracks = mitTracks + 1
+NEXT a
+
+END SUB
+
+
+
+DEFSNG Z
+SUB nait3d
+' Main loop to render the scene
+DO
+
+    setTracks
+
+    ' Updating rotation angles
+    deg1 = deg1 + d1
+    deg2 = deg2 + d2
+    deg3 = deg3 + d3
+
+    ' Normalizing angles
+    IF deg1 <= 0 THEN deg1 = deg1 + 360
+    IF deg2 <= 0 THEN deg2 = deg2 + 360
+    IF deg3 <= 0 THEN deg3 = deg3 + 360
+
+    IF deg1 >= 360 THEN deg1 = deg1 - 360
+    IF deg2 >= 360 THEN deg2 = deg2 - 360
+    IF deg3 >= 360 THEN deg3 = deg3 - 360
+
+    ' sine and cosine values lookup
+    c1& = cosine&(deg1)
+    s1& = sine&(deg1)
+    c2& = cosine&(deg2)
+    s2& = sine&(deg2)
+    c3& = cosine&(deg3)
+    S3& = sine&(deg3)
+
+    ' Updating tank position
+    myx = myx - (s1& * speed / 100)
+    myy = myy - (c1& * speed / 100)
+    myz = myz - (s2& * speed / 100)
+
+    ' Rotating points
+    FOR a = 0 TO np - 1
+        x1 = pointX(a) + myx
+        y1 = pointY(a) + myz
+        pz1 = pointZ(a) + myy
+
+        ' Applying rotation matrix
+        x2 = (x1 * c1& - pz1 * s1&) \ 1024
+        pz2 = (x1 * s1& + pz1 * c1&) \ 1024
+
+        y2 = (y1 * c2& - pz2 * s2&) \ 1024
+        pz3 = (y1 * s2& + pz2 * c2&) \ 1024
+
+        x3 = (y2 * c3& - x2 * S3&) \ 1024
+        y3 = (y2 * S3& + x2 * c3&) \ 1024
+
+        ' Checking if point is within view
+        IF pz3 > 10 THEN
+            xn(a) = 320 + (x3 / pz3 * 500)
+            yn(a) = 240 + (y3 / pz3 * 500)
+        ELSE
+            xn(a) = -1
+        END IF
+    NEXT
+
+    ' Drawing lines between connected points
+    FOR a1 = 0 TO nl - 1
+        f1 = pointers1(a1)
+        s1 = pointers2(a1)
+
+        xn = xn(f1)
+        yn = yn(f1)
+
+        x1 = xn(s1)
+        y1 = yn(s1)
+
+        ' Drawing lines
+        IF Xs1(a1) = -1 OR Xe1(a1) = -1 THEN
+            ELSE
+                LINE (Xs1(a1), Ys1(a1))-(Xe1(a1), Ye1(a1)), 0
+        END IF
+
+        IF x1 = -1 OR xn = -1 THEN
+            ELSE
+                LINE (x1, y1)-(xn, yn), 15
+        END IF
+
+        ' Updating old rotated points
+        Xs1(a1) = x1
+        Ys1(a1) = y1
+
+        Xe1(a1) = xn
+        Ye1(a1) = yn
+    NEXT
+
+    ' Handling user input
+    k$ = INKEY$
+    IF k$ <> "" THEN
+
+        SELECT CASE k$
+
+            CASE CHR$(0) + "M"
+                d1 = d1 - 1
+
+            CASE CHR$(0) + "K"
+                d1 = d1 + 1
+
+            CASE CHR$(0) + "P"
+                d2 = d2 + 1
+
+            CASE CHR$(0) + "H"
+                d2 = d2 - 1
+
+            CASE "w"
+                d3 = d3 - 1
+
+            CASE "z"
+                d3 = d3 + 1
+
+            CASE "-"
+                speed = speed - 1
+
+            CASE "+"
+                speed = speed + 1
+
+            CASE " "
+                d1 = 0
+                d2 = 0
+                d3 = 0
+                speed = 0
+
+            CASE CHR$(27)
+                SYSTEM
+
+        END SELECT
+        k$ = ""
+    END IF
+LOOP
+END SUB
+
+SUB setTracks
+' Updating tank position
+Tracksxp = Tracksxp + ssu
+smes = smes + ssu
+IF smes > 15 THEN smes = 1
+IF smes < 1 THEN smes = 15
+b = smes
+
+FOR a = TracksBeginp TO TracksBeginp + 48 STEP 2
+    pointX(a) = Tracksx(b) - Tracksxp
+    pointY(a) = Tracksy(b)
+    pointZ(a) = 50
+    pointX(a + 1) = Tracksx(b) - Tracksxp
+    pointY(a + 1) = Tracksy(b)
+    pointZ(a + 1) = 30
+    b = b + 15
+NEXT a
+
+b = smes
+FOR a = TracksBeginp + 48 TO TracksBeginp + 94 STEP 2
+    pointX(a) = Tracksx(b) - Tracksxp
+    pointY(a) = Tracksy(b)
+    pointZ(a) = -50
+    pointX(a + 1) = Tracksx(b) - Tracksxp
+    pointY(a + 1) = Tracksy(b)
+    pointZ(a + 1) = -30
+    b = b + 15
+NEXT a
+
+REM Moving the tank
+FOR a = 0 TO 84
+    pointX(a) = pointX(a) - ssu
+NEXT a
+
+IF pointX(84) > 0 THEN ssu = 1
+IF pointX(83) < -400 THEN ssu = -1
+
+END SUB
+
+SUB start
+' Initializing the program
+SCREEN 12
+CLS
+speed = 0
+
+deg1 = 210
+deg2 = 20
+deg3 = 90
+
+smes = 1
+Tracksxp = 0
+
+myxp = 0
+myyp = 0
+myzp = 0
+myx = 0
+myy = -300
+myz = 100
+smes = 1
+
+ssu = 1
+
+calcsin
+
+getcor
+teemaad
+getTracks
+
+END SUB
+
+SUB teemaad
+' Adding new points and connected points
+BridgeBeginl = nl
+np = np + 0
+BridgeBeginp = np
+
+5
+READ pointX(np), pointY(np), pointZ(np)
+IF pointX(np) = 999 THEN pointX(np) = 0: pointY(np) = 0: pointZ(np) = 0: GOTO 3
+np = np + 1
+GOTO 5
+
+3
+READ pointers1(nl), pointers2(nl)
+IF pointers1(nl) = 999 THEN GOTO 4
+pointers1(nl) = pointers1(nl) + BridgeBeginp
+pointers2(nl) = pointers2(nl) + BridgeBeginp
+nl = nl + 1
+GOTO 3
+4
+
+END SUB
diff --git a/Graphics/3D/tank on the bridge.webm b/Graphics/3D/tank on the bridge.webm
new file mode 100644 (file)
index 0000000..4d5e603
Binary files /dev/null and b/Graphics/3D/tank on the bridge.webm differ
diff --git a/Graphics/3D/tank1.bas b/Graphics/3D/tank1.bas
deleted file mode 100755 (executable)
index 6b34f9f..0000000
+++ /dev/null
@@ -1,792 +0,0 @@
-' Program to render animated 3D tank that drives back and forth on the 3D bridge.
-' Notably, tracks on the tank are properly synchronized with the tank movement.
-' User can freely look and fly around in the space.
-'
-' By Svjatoslav Agejenko.
-' Email: svjatoslav@svjatoslav.eu
-' Homepage: http://www.svjatoslav.eu
-'
-' Changelog:
-' 2000, Initial version
-' 2024, Improved program readability using AI
-
-' Use keys to move around:
-' Left, Right, Up, Down   look around
-' + move forward
-' - move back
-' q quit
-' <space> - stop
-
-DECLARE SUB start ()
-DECLARE SUB savepos (x1%, y1%, x2%, y2%)
-DECLARE SUB teemaad ()
-DECLARE SUB setTracks ()
-DECLARE SUB getTracks ()
-DECLARE SUB getTracks1 (x1%, y1%, x2%, y2%)
-DECLARE SUB kiri ()
-DECLARE SUB getcor ()
-DECLARE SUB mulcor ()
-DECLARE SUB nait3d ()
-DECLARE SUB calcsin ()
-DEFINT A-Y
-DIM SHARED xn(1000), yn(1000), czn(1000) ' points transformed to on-screen coordinates
-DIM SHARED pointX(1000), pointY(1000), pointZ(1000) ' points in 3D space
-DIM SHARED Xs1(1000), Ys1(1000), Xe1(1000), Ye1(1000) ' Old rotated points
-DIM SHARED pointers1(1000), pointers2(1000)   ' Connected points
-DIM SHARED cosine&(360), sine&(360)    ' SIN & COS table
-DIM SHARED np, nl
-
-DIM SHARED Tracksx(1 TO 1000)
-DIM SHARED Tracksy(1 TO 1000)
-DIM SHARED mitTracks
-DIM SHARED smes
-
-' Pointers to the beginning of the tank tracks, this is needed to animate tank tracks
-DIM SHARED TracksBeginp ' point index
-DIM SHARED TracksBeginl ' line index
-
-' Pointers to the beginning of the bridge
-DIM SHARED BridgeBeginp    ' point index
-DIM SHARED BridgeBeginl    ' line index  
-
-DIM SHARED Tracksxp
-DIM SHARED myx, myy, myz
-DIM SHARED myxp, myyp, myzp
-
-DIM SHARED deg1, deg2, deg3
-DIM SHARED speed
-
-DIM SHARED ssu
-
-start
-
-nait3d
-
-DATA -10,-30,-20
-DATA 30,-30,-20
-DATA 30,-10,-20
-DATA -10,-10,-20
-
-DATA -10,-30,20
-DATA 30,-30,20
-DATA 30,-10,20
-DATA -10,-10,20
-
-DATA -10,-40,-15
-DATA 30,-40,-15
-DATA -10,-40,15
-DATA 30,-40,15
-
-DATA -20,-30,-15
-DATA -20,-30, 15
-
-DATA -70,-10,-50
-DATA 60,-10, -50
-DATA 70,  0, -50
-DATA 70, 20, -50
-DATA 60, 30, -50
-DATA -70,30, -50
-DATA -80,20, -50
-DATA -80, 0, -50
-
-DATA -70,-10,-30
-DATA 60,-10, -30
-DATA 70,  0, -30
-DATA 70, 20, -30
-DATA 60, 30, -30
-DATA -70,30, -30
-DATA -80,20, -30
-DATA -80, 0, -30
-
-DATA -70,-10, 50
-DATA 60,-10,  50
-DATA 70,  0,  50
-DATA 70, 20,  50
-DATA 60, 30,  50
-DATA -70,30,  50
-DATA -80,20,  50
-DATA -80, 0,  50
-
-DATA -70,-10, 30
-DATA 60,-10,  30
-DATA 70,  0,  30
-DATA 70, 20,  30
-DATA 60, 30,  30
-DATA -70,30,  30
-DATA -80,20,  30
-DATA -80, 0,  30
-
-DATA -50,-7,-30
-DATA  50,-7,-30
-DATA  50, 15,-30
-DATA -50, 15,-30
-
-DATA -50,-7, 30
-DATA  50,-7, 30
-DATA  50, 15,30
-DATA -50, 15,30
-
-DATA -20,-20,-5
-DATA -20,-20, 5
-DATA -20,-30, 5
-DATA -20,-30,-5
-
-DATA -100,-30,-5
-DATA -100,-30, 5
-DATA -100,-40, 5
-DATA -100,-40,-5
-
-DATA 999,999,999
-
-DATA 0,1
-DATA 1,2
-DATA 2,3
-DATA 3,0
-
-DATA 4,5
-DATA 5,6
-DATA 6,7
-DATA 7,4
-
-DATA 0,8
-DATA 1,9
-DATA 4,10
-DATA 5,11
-
-DATA 0,12
-DATA 4,13
-DATA 12,8
-DATA 13,10
-
-DATA 8,9
-DATA 10,11
-DATA 8,10
-DATA 9,11
-
-DATA 12,13
-DATA 12,3
-DATA 13,7
-DATA 3,7
-DATA 1,5
-DATA 2,6
-
-DATA 14,15
-DATA 15,16
-DATA 16,17
-DATA 17,18
-DATA 18,19
-DATA 19,20
-DATA 20,21
-DATA 21,14
-
-DATA 22,23
-DATA 23,24
-DATA 24,25
-DATA 25,26
-DATA 26,27
-DATA 27,28
-DATA 28,29
-DATA 29,22
-
-DATA 30,31
-DATA 31,32
-DATA 32,33
-DATA 33,34
-DATA 34,35
-DATA 35,36
-DATA 36,37
-DATA 37,30
-
-DATA 38,39
-DATA 39,40
-DATA 40,41
-DATA 41,42
-DATA 42,43
-DATA 43,44
-DATA 44,45
-DATA 45,38
-
-DATA 46,47
-DATA 47,48
-DATA 48,49
-DATA 49,46
-
-DATA 50,51
-DATA 51,52
-DATA 52,53
-DATA 53,50
-
-DATA 50,46
-DATA 51,47
-DATA 52,48
-DATA 53,49
-
-DATA 54,55
-DATA 55,56
-DATA 56,57
-DATA 57,54
-
-DATA 54,58
-DATA 55,59
-DATA 56,60
-DATA 57,61
-
-DATA 58,59
-DATA 59,60
-DATA 60,61
-DATA 61,58
-
-DATA 54,3
-DATA 55,7
-
-DATA 999, 999
-'                                                          BRIDGE
-'                                                 right handlebars
-DATA 100,0,100
-DATA 100,50,100
-
-DATA 50,0,100
-DATA 50,50,100
-
-DATA 0,0,100
-DATA 0,50,100
-
-DATA -50,0,100
-DATA -50,50,100
-
-DATA -100,0,100
-DATA -100,50,100
-                       ' 5
-DATA -150,0,100
-DATA -150,50,100
-
-DATA -200,0,100
-DATA -200,50,100
-
-DATA -250,0,100
-DATA -250,50,100
-
-DATA -300,0,100
-DATA -300,50,100
-
-DATA -350,0,100
-DATA -350,50,100
-                           ' 10
-
-DATA -400,0,100
-DATA -400,50,100
-
-DATA -450,0,100
-DATA -450,50,100
-
-DATA -500,0,100
-DATA -500,50,100
-
-DATA -550,0,100
-DATA -550,50,100
-
-DATA -600,0,100
-DATA -600,50,100
-
-DATA -650,0,100
-DATA -650,50,100
-
-                    ' left handlebars
-DATA 100,0,-100
-DATA 100,50,-100
-
-DATA 50,0,-100
-DATA 50,50,-100
-
-DATA 0,0,-100
-DATA 0,50,-100
-
-DATA -50,0,-100
-DATA -50,50,-100
-
-DATA -100,0,-100
-DATA -100,50,-100
-                       ' 5
-DATA -150,0,-100
-DATA -150,50,-100
-
-DATA -200,0,-100
-DATA -200,50,-100
-
-DATA -250,0,-100
-DATA -250,50,-100
-
-DATA -300,0,-100
-DATA -300,50,-100
-
-DATA -350,0,-100
-DATA -350,50,-100
-                           ' 10
-
-DATA -400,0,-100
-DATA -400,50,-100
-
-DATA -450,0,-100
-DATA -450,50,-100
-
-DATA -500,0,-100
-DATA -500,50,-100
-
-DATA -550,0,-100
-DATA -550,50,-100
-
-DATA -600,0,-100
-DATA -600,50,-100
-
-DATA -650,0,-100
-DATA -650,50,-100
-                '   bottom line
-DATA 100,75,-100
-DATA -650,75,-100
-
-DATA 100,75,100
-DATA -650,75,100
-                ' shore
-DATA 75,75,-100
-DATA 75,75,100
-                   'right
-DATA -50,200,-100
-DATA -50,200,100
-
-DATA  75,200,-190
-DATA  75,200, 190
-                   'left
-DATA -525,200,-100
-DATA -525,200, 100
-
-DATA -600,200,-190
-DATA -600,200, 190
-
-'
-
-DATA 999,999,999
-
-                 'right handlebars
-
-DATA 2,3
-DATA 4,5
-DATA 6,7
-DATA 8,9
-
-DATA 10,11
-DATA 12,13
-DATA 14,15
-DATA 16,17
-DATA 18,19
-
-DATA 20,21
-DATA 22,23
-DATA 24,25
-DATA 26,27
-DATA 28,29
-
-
-                   'left handlebars
-DATA 34,35
-DATA 36,37
-DATA 38,39
-DATA 40,41
-
-DATA 42,43
-DATA 44,45
-DATA 46,47
-DATA 48,49
-DATA 50,51
-
-DATA 52,53
-DATA 54,55
-DATA 56,57
-DATA 58,59
-DATA 60,61
-
-'          long features
-DATA 0,4
-DATA 4,8
-DATA 8,12
-DATA 12,16
-DATA 16,20
-DATA 20,24
-DATA 24,28
-DATA 28,30
-
-DATA 1,5
-DATA 5,9
-DATA 9,13
-DATA 13,17
-DATA 17,21
-DATA 21,25
-DATA 25,29
-DATA 29,31
-
-DATA 32,36
-DATA 36,40
-DATA 40,44
-DATA 44,48
-DATA 48,52
-DATA 52,56
-DATA 56,60
-DATA 60,62
-
-DATA 33,37
-DATA 37,41
-DATA 41,45
-DATA 45,49
-DATA 49,53
-DATA 53,57
-DATA 57,61
-DATA 61,63
-
-'
-
-'  end
-
-DATA 1,33
-DATA 31,63
-
-DATA 64,65
-DATA 66,67
-DATA 64,66
-DATA 65,67
-
-DATA 0,66
-DATA 32,64
-DATA 30,67
-DATA 62,65
-            ' shore
-DATA 68,69
-DATA 70,71
-DATA 68,70
-DATA 69,71
-
-DATA 72,70
-DATA 72,68
-
-DATA 73,71
-DATA 73,69
-           'left
-DATA 74,76
-DATA 75,77
-DATA 74,75
-
-DATA 74,65
-DATA 76,65
-
-DATA 75,67
-DATA 77,67
-
-DATA 999, 999
-
-DEFINT Z
-SUB calcsin
-' precalculating sine and cosine tables
-
-FOR a! = 0 TO 359 / 57.29577951# STEP 1 / 57.29577951#
-    cosine&(a) = INT(.5 + COS(a!) * 1024)
-    sine&(a) = INT(.5 + SIN(a!) * 1024)
-    a = a + 1
-NEXT
-CLS
-END SUB
-
-DEFSNG Z
-SUB getcor
-' Loading original points and connected points
-FOR a = 0 TO 10000
-    READ pointX(a), pointY(a), pointZ(a)
-    IF pointX(a) = 999 THEN pointX(a) = 0: pointY(a) = 0: pointZ(a) = 0: GOTO 1
-NEXT
-1
-np = a
-FOR a = 0 TO 10000
-    READ pointers1(a), pointers2(a)
-    IF pointers1(a) = 999 THEN GOTO 2
-NEXT
-2
-nl = a
-
-TracksBeginp = np
-TracksBeginl = nl
-
-' Initializing connected points
-FOR a = 1 TO 48
-pointers1(nl) = np
-np = np + 1
-pointers2(nl) = np
-np = np + 1
-nl = nl + 1
-NEXT a
-
-END SUB
-
-DEFINT Z
-SUB getTracks
-
-' Initialize the number of segments
-mitTracks = 1
-getTracks1 -70, -10, -80, 0
-getTracks1 -80, 0, -80, 20
-getTracks1 -80, 20, -70, 30
-getTracks1 -70, 30, 60, 30
-getTracks1 60, 30, 70, 20
-getTracks1 70, 20, 70, 0
-getTracks1 70, 0, 60, -10
-getTracks1 60, -10, -70, -10
-
-END SUB
-
-DEFSNG Z
-SUB getTracks1 (x1%, y1%, x2%, y2%)
-REM Calculating points for a segment
-z1 = ABS(x1 - x2)
-z2 = ABS(y2 - y1)
-mi = SQR(z1 ^ 2 + z2 ^ 2) * 1.017142857#
-
-' Calculating direction vectors
-zxp = (x1 - x2) / mi
-zyp = (y2 - y1) / mi
-zx = x1
-zy = y1
-
-FOR a = 1 TO mi
-    zx = zx - zxp
-    zy = zy + zyp
-    Tracksx(mitTracks) = zx
-    Tracksy(mitTracks) = zy
-    mitTracks = mitTracks + 1
-NEXT a
-
-END SUB
-
-
-
-DEFSNG Z
-SUB nait3d
-' Main loop to render the scene
-DO
-
-    setTracks
-
-    ' Updating rotation angles
-    deg1 = deg1 + d1
-    deg2 = deg2 + d2
-    deg3 = deg3 + d3
-
-    ' Normalizing angles
-    IF deg1 <= 0 THEN deg1 = deg1 + 360
-    IF deg2 <= 0 THEN deg2 = deg2 + 360
-    IF deg3 <= 0 THEN deg3 = deg3 + 360
-
-    IF deg1 >= 360 THEN deg1 = deg1 - 360
-    IF deg2 >= 360 THEN deg2 = deg2 - 360
-    IF deg3 >= 360 THEN deg3 = deg3 - 360
-
-    ' sine and cosine values lookup
-    c1& = cosine&(deg1)
-    s1& = sine&(deg1)
-    c2& = cosine&(deg2)
-    s2& = sine&(deg2)
-    c3& = cosine&(deg3)
-    S3& = sine&(deg3)
-
-    ' Updating tank position
-    myx = myx - (s1& * speed / 100)
-    myy = myy - (c1& * speed / 100)
-    myz = myz - (s2& * speed / 100)
-
-    ' Rotating points
-    FOR a = 0 TO np - 1
-        x1 = pointX(a) + myx
-        y1 = pointY(a) + myz
-        pz1 = pointZ(a) + myy
-
-        ' Applying rotation matrix
-        x2 = (x1 * c1& - pz1 * s1&) \ 1024
-        pz2 = (x1 * s1& + pz1 * c1&) \ 1024
-
-        y2 = (y1 * c2& - pz2 * s2&) \ 1024
-        pz3 = (y1 * s2& + pz2 * c2&) \ 1024
-
-        x3 = (y2 * c3& - x2 * S3&) \ 1024
-        y3 = (y2 * S3& + x2 * c3&) \ 1024
-
-        ' Checking if point is within view
-        IF pz3 > 10 THEN
-            xn(a) = 320 + (x3 / pz3 * 500)
-            yn(a) = 240 + (y3 / pz3 * 500)
-        ELSE
-            xn(a) = -1
-        END IF
-    NEXT
-
-    ' Drawing lines between connected points
-    FOR a1 = 0 TO nl - 1
-        f1 = pointers1(a1)
-        s1 = pointers2(a1)
-
-        xn = xn(f1)
-        yn = yn(f1)
-
-        x1 = xn(s1)
-        y1 = yn(s1)
-
-        ' Drawing lines
-        IF Xs1(a1) = -1 OR Xe1(a1) = -1 THEN
-            ELSE
-                LINE (Xs1(a1), Ys1(a1))-(Xe1(a1), Ye1(a1)), 0
-        END IF
-
-        IF x1 = -1 OR xn = -1 THEN
-            ELSE
-                LINE (x1, y1)-(xn, yn), 15
-        END IF
-
-        ' Updating old rotated points
-        Xs1(a1) = x1
-        Ys1(a1) = y1
-
-        Xe1(a1) = xn
-        Ye1(a1) = yn
-    NEXT
-
-    ' Handling user input
-    k$ = INKEY$
-    IF k$ <> "" THEN
-
-        SELECT CASE k$
-
-            CASE CHR$(0) + "M"
-                d1 = d1 - 1
-
-            CASE CHR$(0) + "K"
-                d1 = d1 + 1
-
-            CASE CHR$(0) + "P"
-                d2 = d2 + 1
-
-            CASE CHR$(0) + "H"
-                d2 = d2 - 1
-
-            CASE "w"
-                d3 = d3 - 1
-
-            CASE "z"
-                d3 = d3 + 1
-
-            CASE "-"
-                speed = speed - 1
-
-            CASE "+"
-                speed = speed + 1
-
-            CASE " "
-                d1 = 0
-                d2 = 0
-                d3 = 0
-                speed = 0
-
-            CASE CHR$(27)
-                SYSTEM
-
-        END SELECT
-        k$ = ""
-    END IF
-LOOP
-END SUB
-
-SUB setTracks
-' Updating tank position
-Tracksxp = Tracksxp + ssu
-smes = smes + ssu
-IF smes > 15 THEN smes = 1
-IF smes < 1 THEN smes = 15
-b = smes
-
-FOR a = TracksBeginp TO TracksBeginp + 48 STEP 2
-    pointX(a) = Tracksx(b) - Tracksxp
-    pointY(a) = Tracksy(b)
-    pointZ(a) = 50
-    pointX(a + 1) = Tracksx(b) - Tracksxp
-    pointY(a + 1) = Tracksy(b)
-    pointZ(a + 1) = 30
-    b = b + 15
-NEXT a
-
-b = smes
-FOR a = TracksBeginp + 48 TO TracksBeginp + 94 STEP 2
-    pointX(a) = Tracksx(b) - Tracksxp
-    pointY(a) = Tracksy(b)
-    pointZ(a) = -50
-    pointX(a + 1) = Tracksx(b) - Tracksxp
-    pointY(a + 1) = Tracksy(b)
-    pointZ(a + 1) = -30
-    b = b + 15
-NEXT a
-
-REM Moving the tank
-FOR a = 0 TO 84
-    pointX(a) = pointX(a) - ssu
-NEXT a
-
-IF pointX(84) > 0 THEN ssu = 1
-IF pointX(83) < -400 THEN ssu = -1
-
-END SUB
-
-SUB start
-' Initializing the program
-SCREEN 12
-CLS
-speed = 0
-
-deg1 = 210
-deg2 = 20
-deg3 = 90
-
-smes = 1
-Tracksxp = 0
-
-myxp = 0
-myyp = 0
-myzp = 0
-myx = 0
-myy = -300
-myz = 100
-smes = 1
-
-ssu = 1
-
-calcsin
-
-getcor
-teemaad
-getTracks
-
-END SUB
-
-SUB teemaad
-' Adding new points and connected points
-BridgeBeginl = nl
-np = np + 0
-BridgeBeginp = np
-
-5
-READ pointX(np), pointY(np), pointZ(np)
-IF pointX(np) = 999 THEN pointX(np) = 0: pointY(np) = 0: pointZ(np) = 0: GOTO 3
-np = np + 1
-GOTO 5
-
-3
-READ pointers1(nl), pointers2(nl)
-IF pointers1(nl) = 999 THEN GOTO 4
-pointers1(nl) = pointers1(nl) + BridgeBeginp
-pointers2(nl) = pointers2(nl) + BridgeBeginp
-nl = nl + 1
-GOTO 3
-4
-
-END SUB
diff --git a/Graphics/3D/tiled room.webm b/Graphics/3D/tiled room.webm
new file mode 100644 (file)
index 0000000..0c4263a
Binary files /dev/null and b/Graphics/3D/tiled room.webm differ