Author Topic: Sanctum: Open world 3D engine using CIRCLE and LINE  (Read 8467 times)

0 Members and 1 Guest are viewing this topic.

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Sanctum: Open world 3D engine using CIRCLE and LINE
« on: February 01, 2019, 04:45:34 pm »
Compile to an EXE. Drag+drop the file below (level.txt) onto the EXE for a bonus.

You can do all kinds of things in this alpha version: ponder the big questions, discover heaven and hell, explore the fabric of digital spacetime itself...

Code: QB64: [Select]
  1. $EXEICON:'sanctum.ico'
  2. REM $include:'Color32.BI'
  3.  
  4. ' Video.
  5. 'SCREEN _NEWIMAGE(640, 480, 32)
  6. SCREEN _NEWIMAGE(800, 600, 32)
  7. 'SCREEN _NEWIMAGE(1024, 768, 32)
  8. screenwidth = _WIDTH
  9. screenheight = _HEIGHT
  10. plotmode = 1
  11.  
  12. ' Memory.
  13. DIM bignumber AS LONG
  14. bignumber = 3000000
  15. DIM numparticleorig AS LONG
  16. numparticleorig = bignumber
  17. numparticlevisible = bignumber
  18. numgroupvisible = 0
  19.  
  20. ' Structure to store groups of particles.
  21. TYPE GroupElement
  22.     Identity AS LONG
  23.     Pointer AS LONG
  24.     Lagger AS LONG
  25.     ContentName AS STRING * 50
  26.     ContentType AS INTEGER
  27.     ' 0 Static
  28.     ' 1 Standard Newtonian
  29.     ' 2 Standard Rotor
  30.     ' 3 Standard Hardcode
  31.     ' 11 Forced Newtonian
  32.     ' 12 Forced Rotor
  33.     ' 31 Scatter
  34.     ' 32 Sparks
  35.     FirstParticle AS LONG
  36.     LastParticle AS LONG
  37.     EventTimer AS LONG
  38.     COMx AS SINGLE
  39.     COMy AS SINGLE
  40.     COMz AS SINGLE
  41.     CORx AS SINGLE
  42.     CORy AS SINGLE
  43.     CORz AS SINGLE
  44. DIM VectorGroup(bignumber / 10) AS GroupElement
  45.  
  46. ' Constant(s).
  47. pi = 3.1415926536
  48. ee = 2.7182818285
  49.  
  50. ' Camera orientation vectors.
  51. DIM uhat(1 TO 3), vhat(1 TO 3), nhat(1 TO 3)
  52.  
  53. ' Clipping planes.
  54. DIM nearplane(1 TO 4), farplane(1 TO 4), rightplane(1 TO 4), leftplane(1 TO 4), topplane(1 TO 4), bottomplane(1 TO 4)
  55.  
  56. ' Basis vectors defined in xyz three-space.
  57. DIM xhat(1 TO 3), yhat(1 TO 3), zhat(1 TO 3)
  58. xhat(1) = 1: xhat(2) = 0: xhat(3) = 0
  59. yhat(1) = 0: yhat(2) = 1: yhat(3) = 0
  60. zhat(1) = 0: zhat(2) = 0: zhat(3) = 1
  61.  
  62. ' Basis vectors projected in uv two-space.
  63. DIM xhatp(1 TO 2), yhatp(1 TO 2), zhatp(1 TO 2)
  64.  
  65. ' Particle vectors defined in xyz three-space.
  66. DIM vecgroupname(bignumber / 10) AS STRING
  67. DIM vecorig(numparticleorig, 3)
  68. DIM vecorigvel(numparticleorig, 3)
  69. DIM vecorigrot(numparticleorig, 3)
  70. DIM vecorigacc(numparticleorig, 3)
  71. DIM veccolor(numparticleorig) AS LONG
  72. DIM vec(numparticleorig, 3)
  73. DIM vecvisible(numparticlevisible, 3)
  74. DIM vecvisiblecolor(numparticlevisible) AS LONG
  75.  
  76. ' Particle vectors projected in uv two-space.
  77. DIM vecpuv(numparticleorig, 1 TO 2)
  78. DIM vecvisiblepuv(numparticlevisible, 1 TO 2)
  79.  
  80. ' Particle projections adjusted for screen uv two-space.
  81. DIM vecpuvs(numparticleorig, 1 TO 2)
  82. DIM vecvisiblepuvs(numparticlevisible, 1 TO 2)
  83.  
  84. ' State.
  85. nearplane(4) = 1
  86. farplane(4) = -100
  87. rightplane(4) = 0 '*' fovd * (nhat(1) * rightplane(1) + nhat(2) * rightplane(2) + nhat(3) * rightplane(3))
  88. leftplane(4) = 0
  89. topplane(4) = 0
  90. bottomplane(4) = 0
  91. centerx = screenwidth / 2
  92. centery = screenheight / 2
  93. fovd = -256
  94. numparticleorig = 0
  95. numparticlevisible = 0
  96. particleindex = 0
  97. vecgroupcounter = 0
  98. vecgroupindex = 0
  99. speeddamp = 1 / 66 ' Rotation damper.
  100. speedboost = 1.5 ' Linear boost.
  101. timevar = 0
  102. timestep = .001
  103. camx = -40
  104. camy = 30
  105. camz = 40
  106. uhat(1) = -.2078192: uhat(2) = -.9781672: uhat(3) = 0
  107. vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  108. toggletimeanimate = 1
  109. toggleinvertmouse = -1
  110. togglehud = -1
  111.  
  112. ' Prime main loop.
  113. GOSUB initialize.objects
  114. GOSUB redraw
  115.  
  116. ' Begin main loop.
  117. fpstimer = INT(TIMER)
  118. fps = 0
  119.     IF toggletimeanimate = 1 THEN
  120.         timevar = timevar + timestep
  121.         IF timevar > 10 ^ 6 THEN timevar = 0
  122.         flagredraw = 1
  123.     END IF
  124.     IF flagredraw = 1 THEN
  125.         GOSUB redraw
  126.         fps = fps + 1
  127.         flagredraw = -1
  128.     END IF
  129.     GOSUB mouseprocess
  130.     GOSUB keyprocess
  131.  
  132.     tt = INT(TIMER)
  133.     IF tt = fpstimer + 1 THEN
  134.         fpstimer = tt
  135.         fpsreport = fps
  136.         fps = 0
  137.     END IF
  138.  
  139.     _DISPLAY
  140.     _KEYCLEAR
  141.     _LIMIT 60
  142.  
  143.  
  144. ' Gosubs.
  145.  
  146. mouseprocess:
  147. mx = 0
  148. my = 0
  149.     mx = mx + _MOUSEMOVEMENTX
  150.     my = my + _MOUSEMOVEMENTY
  151.     IF _MOUSEWHEEL > 0 THEN GOSUB rotate.clockwise
  152.     IF _MOUSEWHEEL < 0 THEN GOSUB rotate.counterclockwise
  153.     IF mx > 0 THEN
  154.         GOSUB rotate.uhat.plus: GOSUB normalize.screen.vectors
  155.     END IF
  156.     IF mx < 0 THEN
  157.         GOSUB rotate.uhat.minus: GOSUB normalize.screen.vectors
  158.     END IF
  159.     IF my > 0 THEN
  160.         IF toggleinvertmouse = -1 THEN
  161.             GOSUB rotate.vhat.plus: GOSUB normalize.screen.vectors
  162.         ELSE
  163.             GOSUB rotate.vhat.minus: GOSUB normalize.screen.vectors
  164.         END IF
  165.     END IF
  166.     IF my < 0 THEN
  167.         IF toggleinvertmouse = -1 THEN
  168.             GOSUB rotate.vhat.minus: GOSUB normalize.screen.vectors
  169.         ELSE
  170.             GOSUB rotate.vhat.plus: GOSUB normalize.screen.vectors
  171.         END IF
  172.     END IF
  173.     mx = 0
  174.     my = 0
  175.  
  176. 'MouseLB = _MOUSEBUTTON(1)
  177. 'MouseRB = _MOUSEBUTTON(2)
  178. flagredraw = 1
  179.  
  180. '_keydown
  181.  
  182. keyprocess:
  183. IF _KEYDOWN(119) = -1 OR _KEYDOWN(18432) = -1 THEN GOSUB strafe.camera.nhat.minus ' w or uparrow
  184. IF _KEYDOWN(115) = -1 OR _KEYDOWN(20480) = -1 THEN GOSUB strafe.camera.nhat.plus ' s or downarrow
  185. IF _KEYDOWN(97) = -1 THEN GOSUB strafe.camera.uhat.minus ' a
  186. IF _KEYDOWN(100) = -1 THEN GOSUB strafe.camera.uhat.plus ' d
  187. IF _KEYDOWN(56) = -1 THEN GOSUB rotate.vhat.plus: GOSUB normalize.screen.vectors ' 8
  188. IF _KEYDOWN(50) = -1 THEN GOSUB rotate.vhat.minus: GOSUB normalize.screen.vectors ' 2
  189. IF _KEYDOWN(19200) = -1 OR _KEYDOWN(52) = -1 THEN GOSUB rotate.uhat.minus: GOSUB normalize.screen.vectors ' 4
  190. IF _KEYDOWN(19712) = -1 OR _KEYDOWN(54) = -1 THEN GOSUB rotate.uhat.plus: GOSUB normalize.screen.vectors ' 6
  191. IF _KEYDOWN(55) = -1 THEN GOSUB rotate.clockwise ' 7
  192. IF _KEYDOWN(57) = -1 THEN GOSUB rotate.counterclockwise ' 9
  193. IF _KEYDOWN(49) = -1 THEN GOSUB rotate.uhat.minus: GOSUB normalize.screen.vectors: GOSUB rotate.clockwise ' 1
  194. IF _KEYDOWN(51) = -1 THEN GOSUB rotate.uhat.plus: GOSUB normalize.screen.vectors: GOSUB rotate.counterclockwise ' 3
  195. IF _KEYDOWN(113) = -1 THEN GOSUB strafe.camera.vhat.minus ' q
  196. IF _KEYDOWN(101) = -1 THEN GOSUB strafe.camera.vhat.plus ' e
  197.  
  198. ''': GOSUB normalize.screen.vectors
  199.  
  200. IF key$ <> "" THEN
  201.     flagredraw = 1
  202.     SELECT CASE key$
  203.         CASE "x"
  204.             uhat(1) = 0: uhat(2) = 1: uhat(3) = 0
  205.             vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  206.         CASE "X"
  207.             uhat(1) = 0: uhat(2) = -1: uhat(3) = 0
  208.             vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  209.         CASE "y"
  210.             uhat(1) = -1: uhat(2) = 0: uhat(3) = 0
  211.             vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  212.         CASE "Y"
  213.             uhat(1) = 1: uhat(2) = 0: uhat(3) = 0
  214.             vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  215.         CASE "z"
  216.             uhat(1) = 1: uhat(2) = 0: uhat(3) = 0
  217.             vhat(1) = 0: vhat(2) = 1: vhat(3) = 0
  218.             GOSUB normalize.screen.vectors
  219.         CASE "Z"
  220.             uhat(1) = 0: uhat(2) = 1: uhat(3) = 0
  221.             vhat(1) = 1: vhat(2) = 0: vhat(3) = 0
  222.         CASE "]"
  223.             farplane(4) = farplane(4) - 1
  224.         CASE "["
  225.             farplane(4) = farplane(4) + 1
  226.         CASE " "
  227.             togglehud = -togglehud
  228.         CASE "t"
  229.             toggletimeanimate = -toggletimeanimate
  230.         CASE "i"
  231.             toggleinvertmouse = -toggleinvertmouse
  232.         CASE "p"
  233.             plotmode = -plotmode
  234.         CASE "v"
  235.             OPEN "snapshot-camera.txt" FOR OUTPUT AS #1
  236.             PRINT #1, camx, camy, camz
  237.             PRINT #1, uhat(1), uhat(2), uhat(3)
  238.             PRINT #1, vhat(1), vhat(2), vhat(3)
  239.             CLOSE #1
  240.         CASE CHR$(27)
  241.             SYSTEM
  242.         CASE "f"
  243.             explodex = camx - nhat(1) * (1 - .1 * RND) * 60
  244.             explodey = camy - nhat(2) * (1 - .1 * RND) * 60
  245.             explodez = camz - nhat(3) * (1 - .1 * RND) * 60
  246.             GOSUB explode
  247.         CASE "n"
  248.             VectorGroup(closestgroup).ContentType = 31
  249.             FOR particleindex = VectorGroup(closestgroup).FirstParticle TO VectorGroup(closestgroup).LastParticle
  250.                 vecorigvel(particleindex, 1) = (RND - .5) * 20
  251.                 vecorigvel(particleindex, 2) = (RND - .5) * 20
  252.                 vecorigvel(particleindex, 3) = (RND - .5) * 20
  253.                 vecorigacc(particleindex, 3) = -30
  254.             NEXT
  255.             VectorGroup(closestgroup).EventTimer = TIMER
  256.         CASE "k"
  257.             explodex = VectorGroup(closestgroup).COMx
  258.             explodey = VectorGroup(closestgroup).COMy
  259.             explodez = VectorGroup(closestgroup).COMz
  260.             GOSUB explode
  261.             p = VectorGroup(closestgroup).Pointer
  262.             l = VectorGroup(closestgroup).Lagger
  263.             VectorGroup(l).Pointer = p
  264.             IF p <> -999 THEN
  265.                 VectorGroup(p).Lagger = l
  266.             ELSE
  267.                 'determine last object id
  268.                 p = 1
  269.                 DO
  270.                     k = VectorGroup(p).Identity
  271.                     p = VectorGroup(k).Pointer
  272.                     IF p = -999 THEN EXIT DO
  273.                 LOOP
  274.                 lastobjectid = k
  275.                 VectorGroup(lastobjectid).Pointer = -999
  276.             END IF
  277.         CASE "b"
  278.             'determine last object id
  279.             p = 1
  280.             DO
  281.                 k = VectorGroup(p).Identity
  282.                 p = VectorGroup(k).Pointer
  283.                 IF p = -999 THEN EXIT DO
  284.             LOOP
  285.             lastobjectid = k
  286.             particleindex = VectorGroup(lastobjectid).LastParticle
  287.             'create new group
  288.             vecgroupcounter = vecgroupcounter + 1
  289.             vecgroupindex = vecgroupcounter
  290.             VectorGroup(vecgroupindex).Identity = vecgroupindex
  291.             VectorGroup(vecgroupindex).Pointer = -999
  292.             VectorGroup(vecgroupindex).Lagger = lastobjectid
  293.             VectorGroup(vecgroupindex).ContentName = "Block"
  294.             VectorGroup(vecgroupindex).ContentType = 0
  295.             VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  296.             FOR r = 1 TO 400
  297.                 particleindex = particleindex + 1
  298.                 vecorig(particleindex, 1) = camx + -40 * nhat(1) + RND * tilesize / 2
  299.                 vecorig(particleindex, 2) = camy + -40 * nhat(2) + RND * tilesize / 2
  300.                 vecorig(particleindex, 3) = camz + -40 * nhat(3) + RND * tilesize / 2
  301.                 IF RND > .5 THEN
  302.                     veccolor(particleindex) = Lime
  303.                 ELSE
  304.                     veccolor(particleindex) = Purple
  305.                 END IF
  306.                 GOSUB calccom
  307.             NEXT
  308.             VectorGroup(vecgroupindex).LastParticle = particleindex
  309.             GOSUB adjustcom
  310.             'connect new group to last group
  311.             VectorGroup(lastobjectid).Pointer = vecgroupindex
  312.     END SELECT
  313.  
  314. convert:
  315. ' Convert graphics from uv-cartesian coordinates to monitor coordinates.
  316. x0 = x: y0 = y
  317. x = x0 + centerx
  318. y = -y0 + centery
  319.  
  320. rotate.uhat.plus:
  321. uhat(1) = uhat(1) + nhat(1) * speeddamp
  322. uhat(2) = uhat(2) + nhat(2) * speeddamp
  323. uhat(3) = uhat(3) + nhat(3) * speeddamp
  324.  
  325. rotate.uhat.minus:
  326. uhat(1) = uhat(1) - nhat(1) * speeddamp
  327. uhat(2) = uhat(2) - nhat(2) * speeddamp
  328. uhat(3) = uhat(3) - nhat(3) * speeddamp
  329.  
  330. rotate.vhat.plus:
  331. vhat(1) = vhat(1) + nhat(1) * speeddamp
  332. vhat(2) = vhat(2) + nhat(2) * speeddamp
  333. vhat(3) = vhat(3) + nhat(3) * speeddamp
  334.  
  335. rotate.vhat.minus:
  336. vhat(1) = vhat(1) - nhat(1) * speeddamp
  337. vhat(2) = vhat(2) - nhat(2) * speeddamp
  338. vhat(3) = vhat(3) - nhat(3) * speeddamp
  339.  
  340. rotate.counterclockwise:
  341. v1 = vhat(1)
  342. v2 = vhat(2)
  343. v3 = vhat(3)
  344. vhat(1) = vhat(1) + uhat(1) * speeddamp
  345. vhat(2) = vhat(2) + uhat(2) * speeddamp
  346. vhat(3) = vhat(3) + uhat(3) * speeddamp
  347. uhat(1) = uhat(1) - v1 * speeddamp
  348. uhat(2) = uhat(2) - v2 * speeddamp
  349. uhat(3) = uhat(3) - v3 * speeddamp
  350.  
  351. rotate.clockwise:
  352. v1 = vhat(1)
  353. v2 = vhat(2)
  354. v3 = vhat(3)
  355. vhat(1) = vhat(1) - uhat(1) * speeddamp
  356. vhat(2) = vhat(2) - uhat(2) * speeddamp
  357. vhat(3) = vhat(3) - uhat(3) * speeddamp
  358. uhat(1) = uhat(1) + v1 * speeddamp
  359. uhat(2) = uhat(2) + v2 * speeddamp
  360. uhat(3) = uhat(3) + v3 * speeddamp
  361.  
  362. strafe.camera.uhat.plus:
  363. camx = camx + uhat(1) * speedboost
  364. camy = camy + uhat(2) * speedboost
  365. camz = camz + uhat(3) * speedboost
  366.  
  367. strafe.camera.uhat.minus:
  368. camx = camx - uhat(1) * speedboost
  369. camy = camy - uhat(2) * speedboost
  370. camz = camz - uhat(3) * speedboost
  371.  
  372. strafe.camera.vhat.plus:
  373. camx = camx + vhat(1) * speedboost
  374. camy = camy + vhat(2) * speedboost
  375. camz = camz + vhat(3) * speedboost
  376.  
  377. strafe.camera.vhat.minus:
  378. camx = camx - vhat(1) * speedboost
  379. camy = camy - vhat(2) * speedboost
  380. camz = camz - vhat(3) * speedboost
  381.  
  382. strafe.camera.nhat.plus:
  383. camx = camx + nhat(1) * speedboost
  384. camy = camy + nhat(2) * speedboost
  385. camz = camz + nhat(3) * speedboost
  386.  
  387. strafe.camera.nhat.minus:
  388. camx = camx - nhat(1) * speedboost
  389. camy = camy - nhat(2) * speedboost
  390. camz = camz - nhat(3) * speedboost
  391.  
  392. normalize.screen.vectors:
  393. uhatmag = SQR(uhat(1) ^ 2 + uhat(2) ^ 2 + uhat(3) ^ 2)
  394. uhat(1) = uhat(1) / uhatmag: uhat(2) = uhat(2) / uhatmag: uhat(3) = uhat(3) / uhatmag
  395. vhatmag = SQR(vhat(1) ^ 2 + vhat(2) ^ 2 + vhat(3) ^ 2)
  396. vhat(1) = vhat(1) / vhatmag: vhat(2) = vhat(2) / vhatmag: vhat(3) = vhat(3) / vhatmag
  397. uhatdotvhat = uhat(1) * vhat(1) + uhat(2) * vhat(2) + uhat(3) * vhat(3)
  398. IF SQR(uhatdotvhat ^ 2) > .0005 THEN
  399.     BEEP ' ... if vectors are somenow not normalized. This has never happened.
  400.     uhat(1) = 0.8251367: uhat(2) = -0.564903: uhat(3) = -0.005829525
  401.     vhat(1) = 0.065519: vhat(2) = 0.08544215: vhat(3) = 0.9941866
  402. ' The normal vector points toward the eye.
  403. nhat(1) = uhat(2) * vhat(3) - uhat(3) * vhat(2)
  404. nhat(2) = uhat(3) * vhat(1) - uhat(1) * vhat(3)
  405. nhat(3) = uhat(1) * vhat(2) - uhat(2) * vhat(1)
  406. nhatmag = SQR(nhat(1) ^ 2 + nhat(2) ^ 2 + nhat(3) ^ 2)
  407. nhat(1) = nhat(1) / nhatmag: nhat(2) = nhat(2) / nhatmag: nhat(3) = nhat(3) / nhatmag
  408.  
  409. redraw:
  410. GOSUB normalize.screen.vectors
  411. GOSUB calculate.clippingplanes
  412. ' Project the three-space basis vectors onto the screen plane.
  413. xhatp(1) = xhat(1) * uhat(1) + xhat(2) * uhat(2) + xhat(3) * uhat(3)
  414. xhatp(2) = xhat(1) * vhat(1) + xhat(2) * vhat(2) + xhat(3) * vhat(3)
  415. yhatp(1) = yhat(1) * uhat(1) + yhat(2) * uhat(2) + yhat(3) * uhat(3)
  416. yhatp(2) = yhat(1) * vhat(1) + yhat(2) * vhat(2) + yhat(3) * vhat(3)
  417. zhatp(1) = zhat(1) * uhat(1) + zhat(2) * uhat(2) + zhat(3) * uhat(3)
  418. zhatp(2) = zhat(1) * vhat(1) + zhat(2) * vhat(2) + zhat(3) * vhat(3)
  419. GOSUB compute.visible.groups
  420. GOSUB project.particles
  421. GOSUB draw.all.objects
  422.  
  423. compute.visible.groups:
  424. numparticlevisible = 0
  425. numgroupvisible = 0
  426. closestdist2 = 10000 ^ 2
  427. closestgroup = 1
  428. ci = -1
  429. cf = -1
  430.  
  431. k = 1
  432. k = VectorGroup(k).Identity
  433.  
  434.     xcom = VectorGroup(k).COMx
  435.     ycom = VectorGroup(k).COMy
  436.     zcom = VectorGroup(k).COMz
  437.  
  438.     thetype = VectorGroup(k).ContentType
  439.  
  440.     dist2 = (camx - xcom) ^ 2 + (camy - ycom) ^ 2 + (camz - zcom) ^ 2
  441.  
  442.     IF dist2 < farplane(4) ^ 2 THEN
  443.  
  444.         groupinview = 1
  445.         IF (xcom - camx) * nearplane(1) + (ycom - camy) * nearplane(2) + (zcom - camz) * nearplane(3) - nearplane(4) < 0 THEN groupinview = 0
  446.         'IF (xcom - camx) * farplane(1) + (ycom - camy) * farplane(2) + (zcom - camz) * farplane(3) - farplane(4) < 0 THEN groupinview = 0
  447.         IF (xcom - camx) * rightplane(1) + (ycom - camy) * rightplane(2) + (zcom - camz) * rightplane(3) - rightplane(4) < 0 THEN groupinview = 0
  448.         IF (xcom - camx) * leftplane(1) + (ycom - camy) * leftplane(2) + (zcom - camz) * leftplane(3) - leftplane(4) < 0 THEN groupinview = 0
  449.         IF (xcom - camx) * topplane(1) + (ycom - camy) * topplane(2) + (zcom - camz) * topplane(3) - topplane(4) < 0 THEN groupinview = 0
  450.         IF (xcom - camx) * bottomplane(1) + (ycom - camy) * bottomplane(2) + (zcom - camz) * bottomplane(3) - bottomplane(4) < 0 THEN groupinview = 0
  451.         IF groupinview = 1 THEN
  452.  
  453.             numgroupvisible = numgroupvisible + 1
  454.  
  455.             IF toggletimeanimate = 1 THEN
  456.                 vecgroupindex = k
  457.                 GOSUB timeanimate
  458.             END IF
  459.  
  460.             IF dist2 < closestdist2 AND thetype < 30 THEN
  461.                 closestdist2 = dist2
  462.                 closestgroup = k
  463.             END IF
  464.  
  465.             IF k = closestgroup THEN ci = numparticlevisible
  466.  
  467.             FOR i = VectorGroup(k).FirstParticle TO VectorGroup(k).LastParticle
  468.                 vec(i, 1) = vecorig(i, 1) - camx
  469.                 vec(i, 2) = vecorig(i, 2) - camy
  470.                 vec(i, 3) = vecorig(i, 3) - camz
  471.                 GOSUB clip.particle.viewplanes
  472.             NEXT
  473.  
  474.             IF k = closestgroup THEN cf = numparticlevisible
  475.  
  476.         ELSE
  477.             ' Force animation regardless of distance from camera.
  478.             IF thetype >= 10 THEN
  479.                 vecgroupindex = k
  480.                 GOSUB timeanimate
  481.             END IF
  482.  
  483.         END IF
  484.  
  485.     ELSE
  486.  
  487.         ' Force animation regardless of distance from camera.
  488.         IF thetype >= 10 THEN
  489.             vecgroupindex = k
  490.             GOSUB timeanimate
  491.         END IF
  492.  
  493.     END IF
  494.  
  495.     k = VectorGroup(k).Pointer
  496.     IF k = -999 THEN EXIT DO
  497.     k = VectorGroup(k).Identity
  498.  
  499.  
  500. IF ci <> -1 AND cf <> -1 THEN
  501.     FOR i = ci TO cf
  502.         vecvisiblecolor(i) = Yellow
  503.     NEXT
  504.  
  505.  
  506. clip.particle.viewplanes:
  507. ' requires i
  508. particleinview = 1
  509. fogswitch = -1
  510. ' Perform standard view plane clipping and implement fog effect.
  511. IF vec(i, 1) * nearplane(1) + vec(i, 2) * nearplane(2) + vec(i, 3) * nearplane(3) - nearplane(4) < 0 THEN particleinview = 0
  512. IF vec(i, 1) * farplane(1) + vec(i, 2) * farplane(2) + vec(i, 3) * farplane(3) - farplane(4) < 0 THEN particleinview = 0
  513. IF vec(i, 1) * farplane(1) + vec(i, 2) * farplane(2) + vec(i, 3) * farplane(3) - farplane(4) * .9 < 0 THEN fogswitch = 1
  514. IF vec(i, 1) * rightplane(1) + vec(i, 2) * rightplane(2) + vec(i, 3) * rightplane(3) - rightplane(4) < 0 THEN particleinview = 0
  515. IF vec(i, 1) * leftplane(1) + vec(i, 2) * leftplane(2) + vec(i, 3) * leftplane(3) - leftplane(4) < 0 THEN particleinview = 0
  516. IF vec(i, 1) * topplane(1) + vec(i, 2) * topplane(2) + vec(i, 3) * topplane(3) - topplane(4) < 0 THEN particleinview = 0
  517. IF vec(i, 1) * bottomplane(1) + vec(i, 2) * bottomplane(2) + vec(i, 3) * bottomplane(3) - bottomplane(4) < 0 THEN particleinview = 0
  518. IF particleinview = 1 THEN
  519.     numparticlevisible = numparticlevisible + 1
  520.     vecvisible(numparticlevisible, 1) = vec(i, 1)
  521.     vecvisible(numparticlevisible, 2) = vec(i, 2)
  522.     vecvisible(numparticlevisible, 3) = vec(i, 3)
  523.     vecvisiblecolor(numparticlevisible) = veccolor(i)
  524.     IF fogswitch = 1 THEN vecvisiblecolor(numparticlevisible) = Gray
  525.  
  526. project.particles:
  527. ' Project vectors onto the screen plane.
  528. FOR i = 1 TO numparticlevisible
  529.     vecvisibledotnhat = vecvisible(i, 1) * nhat(1) + vecvisible(i, 2) * nhat(2) + vecvisible(i, 3) * nhat(3)
  530.     vecvisiblepuv(i, 1) = vecvisible(i, 1) * uhat(1) + vecvisible(i, 2) * uhat(2) + vecvisible(i, 3) * uhat(3)
  531.     vecvisiblepuv(i, 2) = vecvisible(i, 1) * vhat(1) + vecvisible(i, 2) * vhat(2) + vecvisible(i, 3) * vhat(3)
  532.     vecvisiblepuvs(i, 1) = vecvisiblepuv(i, 1) * fovd / vecvisibledotnhat
  533.     vecvisiblepuvs(i, 2) = vecvisiblepuv(i, 2) * fovd / vecvisibledotnhat
  534.  
  535. draw.all.objects:
  536. GOSUB plot.particles
  537. ' Redraw compass.
  538. x = 30 * xhatp(1): y = 30 * xhatp(2): GOSUB convert
  539. LINE (centerx, centery)-(x, y), Red
  540. x = 30 * yhatp(1): y = 30 * yhatp(2): GOSUB convert
  541. LINE (centerx, centery)-(x, y), Green
  542. x = 30 * zhatp(1): y = 30 * zhatp(2): GOSUB convert
  543. LINE (centerx, centery)-(x, y), Blue
  544. IF togglehud = 1 THEN
  545.     COLOR LimeGreen
  546.     LOCATE 2, 2: PRINT "- View Info -"
  547.     COLOR DarkKhaki
  548.     LOCATE 3, 2: PRINT "FPS:"; fpsreport
  549.     LOCATE 4, 2: PRINT "Particles:"; numparticlevisible
  550.     LOCATE 5, 2: PRINT "Groups:"; numgroupvisible
  551.     LOCATE 6, 2: PRINT "Depth:"; -farplane(4)
  552.     LOCATE 7, 2: PRINT "Adjust via [ ]"
  553.     COLOR LimeGreen
  554.     LOCATE 9, 2: PRINT "- Camera -"
  555.     COLOR DarkKhaki
  556.     LOCATE 10, 2: PRINT INT(camx); INT(camy); INT(camz)
  557.     COLOR LimeGreen
  558.     LOCATE 12, 2: PRINT "- Closest: -"
  559.     COLOR DarkKhaki
  560.     LOCATE 13, 2: PRINT LTRIM$(RTRIM$(VectorGroup(closestgroup).ContentName))
  561.     COLOR LimeGreen
  562.     a$ = "MOVE - ALIGN": LOCATE 2, screenwidth / 8 - LEN(a$): PRINT a$
  563.     COLOR DarkKhaki
  564.     a$ = "q w e - x y z": LOCATE 3, screenwidth / 8 - LEN(a$): PRINT a$
  565.     a$ = "a s d - X Y Z": LOCATE 4, screenwidth / 8 - LEN(a$): PRINT a$
  566.     a$ = "i = invert ms": LOCATE 5, screenwidth / 8 - LEN(a$): PRINT a$
  567.     COLOR LimeGreen
  568.     a$ = "- ROTATE -": LOCATE 7, screenwidth / 8 - LEN(a$): PRINT a$
  569.     COLOR DarkKhaki
  570.     a$ = "7 8 9 Mouse": LOCATE 8, screenwidth / 8 - LEN(a$): PRINT a$
  571.     a$ = "4 5 6   +  ": LOCATE 9, screenwidth / 8 - LEN(a$): PRINT a$
  572.     a$ = "1 2 3 Wheel": LOCATE 10, screenwidth / 8 - LEN(a$): PRINT a$
  573.     COLOR LimeGreen
  574.     a$ = "- CONTROL -": LOCATE 12, screenwidth / 8 - LEN(a$): PRINT a$
  575.     COLOR DarkKhaki
  576.     a$ = "t = Stop time": LOCATE 13, screenwidth / 8 - LEN(a$): PRINT a$
  577.     a$ = "f = Fireworks": LOCATE 14, screenwidth / 8 - LEN(a$): PRINT a$
  578.     a$ = "b = Create": LOCATE 15, screenwidth / 8 - LEN(a$): PRINT a$
  579.     a$ = "n = Destroy": LOCATE 16, screenwidth / 8 - LEN(a$): PRINT a$
  580.     a$ = "k = Delete": LOCATE 17, screenwidth / 8 - LEN(a$): PRINT a$
  581.     COLOR LimeGreen
  582.     a$ = "SPACE = Hide Info": LOCATE (screenheight / 16) - 3, (screenwidth / 8) / 2 - LEN(a$) / 2: PRINT a$
  583.     COLOR LimeGreen
  584.     a$ = "You See: " + LTRIM$(RTRIM$(VectorGroup(closestgroup).ContentName)): LOCATE (screenheight / 16) - 3, (screenwidth / 8) / 2 - LEN(a$) / 2: PRINT a$
  585.  
  586. calculate.clippingplanes:
  587. ' Calculate normal vectors to all clipping planes.
  588. nearplane(1) = -nhat(1)
  589. nearplane(2) = -nhat(2)
  590. nearplane(3) = -nhat(3)
  591. farplane(1) = nhat(1)
  592. farplane(2) = nhat(2)
  593. farplane(3) = nhat(3)
  594. rightplane(1) = (screenheight / 2) * fovd * uhat(1) - (screenheight / 2) * (screenwidth / 2) * nhat(1)
  595. rightplane(2) = (screenheight / 2) * fovd * uhat(2) - (screenheight / 2) * (screenwidth / 2) * nhat(2)
  596. rightplane(3) = (screenheight / 2) * fovd * uhat(3) - (screenheight / 2) * (screenwidth / 2) * nhat(3)
  597. mag = SQR((rightplane(1)) ^ 2 + (rightplane(2)) ^ 2 + (rightplane(3)) ^ 2)
  598. rightplane(1) = rightplane(1) / mag
  599. rightplane(2) = rightplane(2) / mag
  600. rightplane(3) = rightplane(3) / mag
  601. leftplane(1) = -(screenheight / 2) * fovd * uhat(1) - (screenheight / 2) * (screenwidth / 2) * nhat(1)
  602. leftplane(2) = -(screenheight / 2) * fovd * uhat(2) - (screenheight / 2) * (screenwidth / 2) * nhat(2)
  603. leftplane(3) = -(screenheight / 2) * fovd * uhat(3) - (screenheight / 2) * (screenwidth / 2) * nhat(3)
  604. mag = SQR((leftplane(1)) ^ 2 + (leftplane(2)) ^ 2 + (leftplane(3)) ^ 2)
  605. leftplane(1) = leftplane(1) / mag
  606. leftplane(2) = leftplane(2) / mag
  607. leftplane(3) = leftplane(3) / mag
  608. topplane(1) = (screenwidth / 2) * fovd * vhat(1) - (screenheight / 2) * (screenwidth / 2) * nhat(1)
  609. topplane(2) = (screenwidth / 2) * fovd * vhat(2) - (screenheight / 2) * (screenwidth / 2) * nhat(2)
  610. topplane(3) = (screenwidth / 2) * fovd * vhat(3) - (screenheight / 2) * (screenwidth / 2) * nhat(3)
  611. mag = SQR((topplane(1)) ^ 2 + (topplane(2)) ^ 2 + (topplane(3)) ^ 2)
  612. topplane(1) = topplane(1) / mag
  613. topplane(2) = topplane(2) / mag
  614. topplane(3) = topplane(3) / mag
  615. bottomplane(1) = -(screenwidth / 2) * fovd * vhat(1) - (screenheight / 2) * (screenwidth / 2) * nhat(1)
  616. bottomplane(2) = -(screenwidth / 2) * fovd * vhat(2) - (screenheight / 2) * (screenwidth / 2) * nhat(2)
  617. bottomplane(3) = -(screenwidth / 2) * fovd * vhat(3) - (screenheight / 2) * (screenwidth / 2) * nhat(3)
  618. mag = SQR((bottomplane(1)) ^ 2 + (bottomplane(2)) ^ 2 + (bottomplane(3)) ^ 2)
  619. bottomplane(1) = bottomplane(1) / mag
  620. bottomplane(2) = bottomplane(2) / mag
  621. bottomplane(3) = bottomplane(3) / mag
  622.  
  623. plot.particles:
  624. FOR i = 1 TO numparticlevisible - 1
  625.     x = vecvisiblepuvs(i, 1): y = vecvisiblepuvs(i, 2): GOSUB convert: x1 = x: y1 = y
  626.     x = vecvisiblepuvs(i + 1, 1): y = vecvisiblepuvs(i + 1, 2): GOSUB convert: x2 = x: y2 = y
  627.     IF ((x2 - x1) ^ 2 + (y2 - y1) ^ 2) < 225 THEN
  628.         IF plotmode = 1 THEN
  629.             LINE (x1, y1)-(x2, y2), vecvisiblecolor(i)
  630.         ELSE
  631.             LINE (x1, y1)-(x2, y2), vecvisiblecolor(i), B
  632.         END IF
  633.     ELSE
  634.         CIRCLE (x1, y1), 1, vecvisiblecolor(i)
  635.     END IF
  636.  
  637. ' Data.
  638.  
  639. initialize.objects:
  640. particleindex = 0
  641. vecgroupcounter = 0
  642. gridsize = 550
  643. tilesize = 15
  644.  
  645. '__AAA
  646. vecgroupcounter = vecgroupcounter + 1
  647. vecgroupindex = vecgroupcounter
  648. VectorGroup(vecgroupindex).Identity = vecgroupindex
  649. VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  650. VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  651. VectorGroup(vecgroupindex).ContentName = "__AAA"
  652. VectorGroup(vecgroupindex).ContentType = 0
  653. VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  654. FOR r = 1 TO 5
  655.     particleindex = particleindex + 1
  656.     vecorig(particleindex, 1) = -1000
  657.     vecorig(particleindex, 2) = -1000
  658.     vecorig(particleindex, 3) = -1000
  659.     veccolor(particleindex) = White
  660.     GOSUB calccom
  661. VectorGroup(vecgroupindex).LastParticle = particleindex
  662. GOSUB adjustcom
  663.  
  664. 'Clock Face (Rolex)
  665. vecgroupcounter = vecgroupcounter + 1
  666. vecgroupindex = vecgroupcounter
  667. VectorGroup(vecgroupindex).Identity = vecgroupindex
  668. VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  669. VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  670. VectorGroup(vecgroupindex).ContentName = "Clock Face (Rolex)"
  671. VectorGroup(vecgroupindex).ContentType = 0
  672. VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  673. FOR q = 0 TO 2 * pi STEP (2 * pi / 12) / 25
  674.     FOR r = 10 TO 12 STEP .5
  675.         particleindex = particleindex + 1
  676.         vecorig(particleindex, 1) = 40 + r * COS(q)
  677.         vecorig(particleindex, 2) = -20 + r
  678.         vecorig(particleindex, 3) = 40 + r * SIN(q)
  679.         veccolor(particleindex) = DarkSlateGray
  680.         GOSUB calccom
  681.     NEXT
  682. VectorGroup(vecgroupindex).LastParticle = particleindex
  683. GOSUB adjustcom
  684.  
  685. 'Clock Hands
  686. vecgroupcounter = vecgroupcounter + 1
  687. vecgroupindex = vecgroupcounter
  688. VectorGroup(vecgroupindex).Identity = vecgroupindex
  689. VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  690. VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  691. VectorGroup(vecgroupindex).ContentName = "Clock Hands"
  692. VectorGroup(vecgroupindex).ContentType = 3
  693. VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  694. DIM hand(3)
  695. DIM hcol(3) AS LONG
  696. hand(1) = VAL(LEFT$(TIME$, 2)) * (2 * pi / 12)
  697. hand(2) = VAL(MID$(TIME$, 4, 2)) * (2 * pi / 60)
  698. hand(3) = VAL(RIGHT$(TIME$, 2)) * (2 * pi / 60)
  699. phase = pi / 2
  700. hcol(1) = Gold
  701. hcol(2) = Lime
  702. hcol(3) = OrangeRed
  703. FOR q = 1 TO 3
  704.     FOR r = 0 TO 5 + q STEP .1
  705.         particleindex = particleindex + 1
  706.         vecorig(particleindex, 1) = 40 + r * COS(hand(q) + phase)
  707.         vecorig(particleindex, 2) = -10
  708.         vecorig(particleindex, 3) = 40 + r * SIN(hand(q) + phase)
  709.         veccolor(particleindex) = hcol(q)
  710.         GOSUB calccom
  711.     NEXT
  712. VectorGroup(vecgroupindex).LastParticle = particleindex
  713. GOSUB adjustcom
  714.  
  715. 'Dirt
  716. h = 5
  717. FOR w = 1 TO 5
  718.     FOR u = -gridsize TO gridsize STEP tilesize
  719.         FOR v = -gridsize TO gridsize STEP tilesize
  720.             vecgroupcounter = vecgroupcounter + 1
  721.             vecgroupindex = vecgroupcounter
  722.             VectorGroup(vecgroupindex).Identity = vecgroupindex
  723.             VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  724.             VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  725.             VectorGroup(vecgroupindex).ContentName = "Dirt"
  726.             VectorGroup(vecgroupindex).ContentType = 0
  727.             VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  728.             FOR i = u TO u + tilesize STEP h
  729.                 FOR j = v TO v + tilesize STEP h
  730.                     IF RND > 1 - w / 5 THEN
  731.                         particleindex = particleindex + 1
  732.                         vecorig(particleindex, 1) = i + RND * h - RND * h
  733.                         vecorig(particleindex, 2) = j + RND * h - RND * h
  734.                         vecorig(particleindex, 3) = -(w - 1) * 70 - RND * 70
  735.                         IF RND > .5 THEN
  736.                             veccolor(particleindex) = DarkGoldenRod
  737.                         ELSE
  738.                             IF RND > .5 THEN
  739.                                 veccolor(particleindex) = SaddleBrown
  740.                             ELSE
  741.                                 veccolor(particleindex) = Sienna
  742.                             END IF
  743.                         END IF
  744.                         GOSUB calccom
  745.                     END IF
  746.                 NEXT
  747.             NEXT
  748.             VectorGroup(vecgroupindex).LastParticle = particleindex
  749.             GOSUB adjustcom
  750.         NEXT
  751.     NEXT
  752.  
  753. 'Grass and Puddles
  754. h = 2
  755. FOR u = -gridsize TO gridsize STEP tilesize
  756.     FOR v = -gridsize TO gridsize STEP tilesize
  757.         vecgroupcounter = vecgroupcounter + 1
  758.         vecgroupindex = vecgroupcounter
  759.         VectorGroup(vecgroupindex).Identity = vecgroupindex
  760.         VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  761.         VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  762.         VectorGroup(vecgroupindex).ContentName = "Grass and Puddles"
  763.         VectorGroup(vecgroupindex).ContentType = 0
  764.         VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  765.         FOR i = u TO u + tilesize STEP h
  766.             FOR j = v TO v + tilesize STEP h
  767.                 particleindex = particleindex + 1
  768.                 vecorig(particleindex, 1) = i + RND * h - RND * h
  769.                 vecorig(particleindex, 2) = j + RND * h - RND * h
  770.                 vecorig(particleindex, 3) = .5 + 1 * COS((i - 15) * .08) - 1 * COS((j - 6) * .12)
  771.                 IF vecorig(particleindex, 3) > 0 THEN
  772.                     IF RND > .5 THEN
  773.                         veccolor(particleindex) = Green
  774.                     ELSE
  775.                         veccolor(particleindex) = ForestGreen
  776.                     END IF
  777.                 ELSE
  778.                     IF RND > .2 THEN
  779.                         veccolor(particleindex) = LightSeaGreen
  780.                     ELSE
  781.                         veccolor(particleindex) = Blue
  782.                     END IF
  783.                 END IF
  784.                 GOSUB calccom
  785.             NEXT
  786.         NEXT
  787.         VectorGroup(vecgroupindex).LastParticle = particleindex
  788.         GOSUB adjustcom
  789.     NEXT
  790.  
  791. 'Grave
  792. thickness = 2.5
  793. span = 20
  794. height = 30
  795. crux = 22
  796. FOR xloc = -90 TO -290 STEP -60
  797.     FOR yloc = 0 TO 180 STEP 45
  798.         FOR k = 0 TO height
  799.             vecgroupcounter = vecgroupcounter + 1
  800.             vecgroupindex = vecgroupcounter
  801.             VectorGroup(vecgroupindex).Identity = vecgroupindex
  802.             VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  803.             VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  804.             VectorGroup(vecgroupindex).ContentName = "Grave"
  805.             VectorGroup(vecgroupindex).ContentType = 0
  806.             VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  807.             FOR i = -thickness TO thickness STEP thickness / 2
  808.                 FOR j = -thickness TO thickness STEP thickness / 2
  809.                     particleindex = particleindex + 1
  810.                     vecorig(particleindex, 1) = xloc + i + (RND - .5) * 2
  811.                     vecorig(particleindex, 2) = yloc + j + (RND - .5) * 2
  812.                     vecorig(particleindex, 3) = k + (RND - .5) * 2
  813.                     IF RND > .5 THEN
  814.                         veccolor(particleindex) = SlateGray
  815.                     ELSE
  816.                         veccolor(particleindex) = DarkGray
  817.                     END IF
  818.                     GOSUB calccom
  819.                 NEXT
  820.             NEXT
  821.             VectorGroup(vecgroupindex).LastParticle = particleindex
  822.             GOSUB adjustcom
  823.         NEXT
  824.         FOR j = -span / 2 TO -thickness
  825.             vecgroupcounter = vecgroupcounter + 1
  826.             vecgroupindex = vecgroupcounter
  827.             VectorGroup(vecgroupindex).Identity = vecgroupindex
  828.             VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  829.             VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  830.             VectorGroup(vecgroupindex).ContentName = "Grave"
  831.             VectorGroup(vecgroupindex).ContentType = 0
  832.             VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  833.             FOR k = -thickness TO thickness STEP thickness / 2
  834.                 FOR i = -thickness TO thickness STEP thickness / 2
  835.                     particleindex = particleindex + 1
  836.                     vecorig(particleindex, 1) = xloc + i + (RND - .5) * 2
  837.                     vecorig(particleindex, 2) = yloc + j + (RND - .5) * 2
  838.                     vecorig(particleindex, 3) = crux + k + (RND - .5) * 2
  839.                     IF RND > .5 THEN
  840.                         veccolor(particleindex) = SlateGray
  841.                     ELSE
  842.                         veccolor(particleindex) = DarkGray
  843.                     END IF
  844.                     GOSUB calccom
  845.                 NEXT
  846.             NEXT
  847.             VectorGroup(vecgroupindex).LastParticle = particleindex
  848.             GOSUB adjustcom
  849.         NEXT
  850.         FOR j = thickness TO span / 2
  851.             vecgroupcounter = vecgroupcounter + 1
  852.             vecgroupindex = vecgroupcounter
  853.             VectorGroup(vecgroupindex).Identity = vecgroupindex
  854.             VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  855.             VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  856.             VectorGroup(vecgroupindex).ContentName = "Grave"
  857.             VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  858.             FOR k = -thickness TO thickness STEP thickness / 2
  859.                 FOR i = -thickness TO thickness STEP thickness / 2
  860.                     particleindex = particleindex + 1
  861.                     vecorig(particleindex, 1) = xloc + i + (RND - .5) * 2
  862.                     vecorig(particleindex, 2) = yloc + j + (RND - .5) * 2
  863.                     vecorig(particleindex, 3) = crux + k + (RND - .5) * 2
  864.                     IF RND > .5 THEN
  865.                         veccolor(particleindex) = SlateGray
  866.                     ELSE
  867.                         veccolor(particleindex) = DarkGray
  868.                     END IF
  869.                     GOSUB calccom
  870.                 NEXT
  871.             NEXT
  872.             VectorGroup(vecgroupindex).LastParticle = particleindex
  873.             GOSUB adjustcom
  874.         NEXT
  875.     NEXT
  876.  
  877. 'Heaven's Bottom Layer
  878. h = 2
  879. FOR u = -gridsize TO gridsize STEP tilesize
  880.     FOR v = -gridsize TO gridsize STEP tilesize
  881.         vecgroupcounter = vecgroupcounter + 1
  882.         vecgroupindex = vecgroupcounter
  883.         VectorGroup(vecgroupindex).Identity = vecgroupindex
  884.         VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  885.         VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  886.         VectorGroup(vecgroupindex).ContentName = "Heaven's Bottom Layer"
  887.         VectorGroup(vecgroupindex).ContentType = 0
  888.         VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  889.         FOR i = u TO u + tilesize STEP h
  890.             FOR j = v TO v + tilesize STEP h
  891.                 particleindex = particleindex + 1
  892.                 vecorig(particleindex, 1) = i + RND * h - RND * h
  893.                 vecorig(particleindex, 2) = j + RND * h - RND * h
  894.                 vecorig(particleindex, 3) = 420 - RND
  895.                 IF RND > .5 THEN
  896.                     veccolor(particleindex) = BlueViolet
  897.                 ELSE
  898.                     veccolor(particleindex) = Cyan
  899.                 END IF
  900.                 GOSUB calccom
  901.             NEXT
  902.         NEXT
  903.         VectorGroup(vecgroupindex).LastParticle = particleindex
  904.         GOSUB adjustcom
  905.     NEXT
  906.  
  907. 'Hell Spawn
  908. FOR u = -gridsize TO gridsize STEP tilesize
  909.     FOR v = -gridsize TO gridsize STEP tilesize
  910.         vecgroupcounter = vecgroupcounter + 1
  911.         vecgroupindex = vecgroupcounter
  912.         VectorGroup(vecgroupindex).Identity = vecgroupindex
  913.         VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  914.         VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  915.         VectorGroup(vecgroupindex).ContentName = "Hell Spawn"
  916.         VectorGroup(vecgroupindex).ContentType = 3
  917.         VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  918.         FOR i = u TO u + tilesize STEP tilesize / 5
  919.             FOR j = v TO v + tilesize STEP tilesize / 5
  920.                 particleindex = particleindex + 1
  921.                 vecorig(particleindex, 1) = i + RND * tilesize / 5
  922.                 vecorig(particleindex, 2) = j + RND * tilesize / 5
  923.                 vecorig(particleindex, 3) = -350 - RND * 70
  924.                 IF RND > .2 THEN
  925.                     veccolor(particleindex) = Red
  926.                 ELSE
  927.                     veccolor(particleindex) = DarkGoldenRod
  928.                 END IF
  929.                 GOSUB calccom
  930.             NEXT
  931.         NEXT
  932.         VectorGroup(vecgroupindex).LastParticle = particleindex
  933.         GOSUB adjustcom
  934.     NEXT
  935.  
  936. 'Icewall East
  937. h = 2
  938. FOR u = -gridsize TO gridsize STEP tilesize
  939.     FOR v = 0 TO 70 STEP tilesize
  940.         vecgroupcounter = vecgroupcounter + 1
  941.         vecgroupindex = vecgroupcounter
  942.         VectorGroup(vecgroupindex).Identity = vecgroupindex
  943.         VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  944.         VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  945.         VectorGroup(vecgroupindex).ContentName = "Icewall East"
  946.         VectorGroup(vecgroupindex).ContentType = 0
  947.         VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  948.         FOR i = u TO u + tilesize STEP h
  949.             FOR j = v TO v + tilesize STEP h
  950.                 particleindex = particleindex + 1
  951.                 vecorig(particleindex, 1) = gridsize
  952.                 vecorig(particleindex, 2) = i + RND * h - RND * h
  953.                 vecorig(particleindex, 3) = j + RND * h - RND * h
  954.                 IF RND > .5 THEN
  955.                     veccolor(particleindex) = White
  956.                 ELSE
  957.                     veccolor(particleindex) = Ivory
  958.                 END IF
  959.                 GOSUB calccom
  960.             NEXT
  961.         NEXT
  962.         VectorGroup(vecgroupindex).LastParticle = particleindex
  963.         GOSUB adjustcom
  964.     NEXT
  965.  
  966. 'Icewall South
  967. h = 2
  968. FOR u = -gridsize TO gridsize STEP tilesize
  969.     FOR v = 0 TO 70 STEP tilesize
  970.         vecgroupcounter = vecgroupcounter + 1
  971.         vecgroupindex = vecgroupcounter
  972.         VectorGroup(vecgroupindex).Identity = vecgroupindex
  973.         VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  974.         VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  975.         VectorGroup(vecgroupindex).ContentName = "Icewall South"
  976.         VectorGroup(vecgroupindex).ContentType = 0
  977.         VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  978.         FOR i = u TO u + tilesize STEP h
  979.             FOR j = v TO v + tilesize STEP h
  980.                 particleindex = particleindex + 1
  981.                 vecorig(particleindex, 1) = -gridsize
  982.                 vecorig(particleindex, 2) = i + RND * h - RND * h
  983.                 vecorig(particleindex, 3) = j + RND * h - RND * h
  984.                 IF RND > .5 THEN
  985.                     veccolor(particleindex) = White
  986.                 ELSE
  987.                     veccolor(particleindex) = Ivory
  988.                 END IF
  989.                 GOSUB calccom
  990.             NEXT
  991.         NEXT
  992.         VectorGroup(vecgroupindex).LastParticle = particleindex
  993.         GOSUB adjustcom
  994.     NEXT
  995.  
  996. 'Icewall North
  997. h = 2
  998. FOR u = -gridsize TO gridsize STEP tilesize
  999.     FOR v = 0 TO 70 STEP tilesize
  1000.         vecgroupcounter = vecgroupcounter + 1
  1001.         vecgroupindex = vecgroupcounter
  1002.         VectorGroup(vecgroupindex).Identity = vecgroupindex
  1003.         VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  1004.         VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1005.         VectorGroup(vecgroupindex).ContentName = "Icewall North"
  1006.         VectorGroup(vecgroupindex).ContentType = 0
  1007.         VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1008.         FOR i = u TO u + tilesize STEP h
  1009.             FOR j = v TO v + tilesize STEP h
  1010.                 particleindex = particleindex + 1
  1011.                 vecorig(particleindex, 1) = i + RND * h - RND * h
  1012.                 vecorig(particleindex, 2) = gridsize
  1013.                 vecorig(particleindex, 3) = j + RND * h - RND * h
  1014.                 IF RND > .5 THEN
  1015.                     veccolor(particleindex) = White
  1016.                 ELSE
  1017.                     veccolor(particleindex) = Ivory
  1018.                 END IF
  1019.                 GOSUB calccom
  1020.             NEXT
  1021.         NEXT
  1022.         VectorGroup(vecgroupindex).LastParticle = particleindex
  1023.         GOSUB adjustcom
  1024.     NEXT
  1025.  
  1026. 'Icewall West
  1027. h = 2
  1028. FOR u = -gridsize TO gridsize STEP tilesize
  1029.     FOR v = 0 TO 70 STEP tilesize
  1030.         vecgroupcounter = vecgroupcounter + 1
  1031.         vecgroupindex = vecgroupcounter
  1032.         VectorGroup(vecgroupindex).Identity = vecgroupindex
  1033.         VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  1034.         VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1035.         VectorGroup(vecgroupindex).ContentName = "Icewall West"
  1036.         VectorGroup(vecgroupindex).ContentType = 0
  1037.         VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1038.         FOR i = u TO u + tilesize STEP h
  1039.             FOR j = v TO v + tilesize STEP h
  1040.                 particleindex = particleindex + 1
  1041.                 vecorig(particleindex, 1) = i + RND * h - RND * h
  1042.                 vecorig(particleindex, 2) = -gridsize
  1043.                 vecorig(particleindex, 3) = j + RND * h - RND * h
  1044.                 IF RND > .5 THEN
  1045.                     veccolor(particleindex) = White
  1046.                 ELSE
  1047.                     veccolor(particleindex) = Ivory
  1048.                 END IF
  1049.                 GOSUB calccom
  1050.             NEXT
  1051.         NEXT
  1052.         VectorGroup(vecgroupindex).LastParticle = particleindex
  1053.         GOSUB adjustcom
  1054.     NEXT
  1055.  
  1056. 'Lake of Fire
  1057. h = 2
  1058. FOR u = -gridsize TO gridsize STEP tilesize
  1059.     FOR v = -gridsize TO gridsize STEP tilesize
  1060.         vecgroupcounter = vecgroupcounter + 1
  1061.         vecgroupindex = vecgroupcounter
  1062.         VectorGroup(vecgroupindex).Identity = vecgroupindex
  1063.         VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  1064.         VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1065.         VectorGroup(vecgroupindex).ContentName = "Lake of Fire"
  1066.         VectorGroup(vecgroupindex).ContentType = 0
  1067.         VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1068.         FOR i = u TO u + tilesize STEP h
  1069.             FOR j = v TO v + tilesize STEP h
  1070.                 particleindex = particleindex + 1
  1071.                 vecorig(particleindex, 1) = i + RND * h - RND * h
  1072.                 vecorig(particleindex, 2) = j + RND * h - RND * h
  1073.                 vecorig(particleindex, 3) = -350 - 70 - RND
  1074.                 IF RND > .2 THEN
  1075.                     veccolor(particleindex) = Red
  1076.                 ELSE
  1077.                     veccolor(particleindex) = Indigo
  1078.                 END IF
  1079.                 GOSUB calccom
  1080.             NEXT
  1081.         NEXT
  1082.         VectorGroup(vecgroupindex).LastParticle = particleindex
  1083.         GOSUB adjustcom
  1084.     NEXT
  1085.  
  1086. 'Megalith
  1087. ctrx = -90
  1088. ctry = -320
  1089. ctrz = 4
  1090. w = 8
  1091. h = 256
  1092. dens = 100
  1093. FOR k = 1 TO h STEP w
  1094.     FOR i = -h / 20 + k / 20 TO h / 20 - k / 20 STEP w
  1095.         FOR j = -h / 20 + k / 20 TO h / 20 - k / 20 STEP w
  1096.             vecgroupcounter = vecgroupcounter + 1
  1097.             vecgroupindex = vecgroupcounter
  1098.             VectorGroup(vecgroupindex).Identity = vecgroupindex
  1099.             VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  1100.             VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1101.             VectorGroup(vecgroupindex).ContentName = "Megalith"
  1102.             VectorGroup(vecgroupindex).ContentType = 0
  1103.             VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1104.             FOR q = 1 TO dens
  1105.                 particleindex = particleindex + 1
  1106.                 vecorig(particleindex, 1) = ctrx + i + (RND - .5) * w
  1107.                 vecorig(particleindex, 2) = ctry + j + (RND - .5) * w
  1108.                 vecorig(particleindex, 3) = ctrz + k + (RND - .5) * w
  1109.                 IF RND > .5 THEN
  1110.                     veccolor(particleindex) = Cyan
  1111.                 ELSE
  1112.                     veccolor(particleindex) = Teal
  1113.                 END IF
  1114.                 GOSUB calccom
  1115.             NEXT
  1116.             VectorGroup(vecgroupindex).LastParticle = particleindex
  1117.             GOSUB adjustcom
  1118.         NEXT
  1119.     NEXT
  1120.  
  1121. 'Moon
  1122. vecgroupcounter = vecgroupcounter + 1
  1123. vecgroupindex = vecgroupcounter
  1124. VectorGroup(vecgroupindex).Identity = vecgroupindex
  1125. VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  1126. VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1127. VectorGroup(vecgroupindex).ContentName = "Moon"
  1128. VectorGroup(vecgroupindex).ContentType = 2
  1129. VectorGroup(vecgroupindex).CORx = 0
  1130. VectorGroup(vecgroupindex).CORy = 0
  1131. VectorGroup(vecgroupindex).CORz = 90
  1132. VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1133. radius = 4
  1134. au = 60
  1135. dx = (2 * pi / radius) * .05
  1136. dy = (2 * pi / radius) * .05
  1137. xl = 0: xr = 2 * pi
  1138. yl = 0: yr = pi
  1139. xrange = 1 + INT((-xl + xr) / dx)
  1140. yrange = 1 + INT((-yl + yr) / dy)
  1141. FOR i = 1 TO xrange
  1142.     FOR j = 1 TO yrange
  1143.         particleindex = particleindex + 1
  1144.         theta = i * dx - dx
  1145.         phi = j * dy - dy
  1146.         vecorig(particleindex, 1) = au + radius * SIN(phi) * COS(theta)
  1147.         vecorig(particleindex, 2) = radius * SIN(phi) * SIN(theta)
  1148.         vecorig(particleindex, 3) = 90 + radius * COS(phi)
  1149.         vecorigrot(particleindex, 1) = 0
  1150.         vecorigrot(particleindex, 2) = 0
  1151.         vecorigrot(particleindex, 3) = 1
  1152.  
  1153.         IF RND > .5 THEN
  1154.             veccolor(particleindex) = Gray
  1155.         ELSE
  1156.             veccolor(particleindex) = PaleGoldenRod
  1157.         END IF
  1158.         GOSUB calccom
  1159.     NEXT
  1160. VectorGroup(vecgroupindex).LastParticle = particleindex
  1161. GOSUB adjustcom
  1162.  
  1163. 'Pyramid
  1164. ctrx = -90
  1165. ctry = -120
  1166. ctrz = 4
  1167. w = 8
  1168. h = 56
  1169. dens = 50
  1170. FOR k = 1 TO h STEP w
  1171.     FOR i = -h / 2 + k / 2 TO h / 2 - k / 2 STEP w
  1172.         FOR j = -h / 2 + k / 2 TO h / 2 - k / 2 STEP w
  1173.             vecgroupcounter = vecgroupcounter + 1
  1174.             vecgroupindex = vecgroupcounter
  1175.             VectorGroup(vecgroupindex).Identity = vecgroupindex
  1176.             VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  1177.             VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1178.             VectorGroup(vecgroupindex).ContentName = "Pyramid"
  1179.             VectorGroup(vecgroupindex).ContentType = 0
  1180.             VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1181.             FOR q = 1 TO dens
  1182.                 particleindex = particleindex + 1
  1183.                 vecorig(particleindex, 1) = ctrx + i + (RND - .5) * w
  1184.                 vecorig(particleindex, 2) = ctry + j + (RND - .5) * w
  1185.                 vecorig(particleindex, 3) = ctrz + k + (RND - .5) * w
  1186.                 IF RND > .5 THEN
  1187.                     veccolor(particleindex) = DarkGoldenRod
  1188.                 ELSE
  1189.                     veccolor(particleindex) = GoldenRod
  1190.                 END IF
  1191.                 GOSUB calccom
  1192.             NEXT
  1193.             VectorGroup(vecgroupindex).LastParticle = particleindex
  1194.             GOSUB adjustcom
  1195.         NEXT
  1196.     NEXT
  1197.  
  1198. 'Rain
  1199. FOR u = -gridsize TO gridsize STEP tilesize
  1200.     FOR v = -gridsize TO gridsize STEP tilesize
  1201.         vecgroupcounter = vecgroupcounter + 1
  1202.         vecgroupindex = vecgroupcounter
  1203.         VectorGroup(vecgroupindex).Identity = vecgroupindex
  1204.         VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  1205.         VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1206.         VectorGroup(vecgroupindex).ContentName = "Rain"
  1207.         VectorGroup(vecgroupindex).ContentType = 3
  1208.         VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1209.         FOR i = u TO u + tilesize STEP tilesize '/ 3
  1210.             FOR j = v TO v + tilesize STEP tilesize '/ 3
  1211.                 particleindex = particleindex + 1
  1212.                 vecorig(particleindex, 1) = i + RND * tilesize
  1213.                 vecorig(particleindex, 2) = j + RND * tilesize
  1214.                 vecorig(particleindex, 3) = RND * 70
  1215.                 IF RND > 5 THEN
  1216.                     veccolor(particleindex) = Aquamarine
  1217.                 ELSE
  1218.                     veccolor(particleindex) = DodgerBlue
  1219.                 END IF
  1220.                 GOSUB calccom
  1221.             NEXT
  1222.         NEXT
  1223.         VectorGroup(vecgroupindex).LastParticle = particleindex
  1224.         GOSUB adjustcom
  1225.     NEXT
  1226.  
  1227. 'Sky
  1228. h = 2
  1229. FOR u = -gridsize TO gridsize STEP tilesize
  1230.     FOR v = -gridsize TO gridsize STEP tilesize
  1231.         vecgroupcounter = vecgroupcounter + 1
  1232.         vecgroupindex = vecgroupcounter
  1233.         VectorGroup(vecgroupindex).Identity = vecgroupindex
  1234.         VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  1235.         VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1236.         VectorGroup(vecgroupindex).ContentName = "Sky"
  1237.         VectorGroup(vecgroupindex).ContentType = 0
  1238.         VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1239.         FOR i = u TO u + tilesize STEP h
  1240.             FOR j = v TO v + tilesize STEP h
  1241.                 particleindex = particleindex + 1
  1242.                 vecorig(particleindex, 1) = i + RND * h - RND * h
  1243.                 vecorig(particleindex, 2) = j + RND * h - RND * h
  1244.                 vecorig(particleindex, 3) = 70 + RND * h - RND * h
  1245.                 IF RND > .5 THEN
  1246.                     veccolor(particleindex) = Snow
  1247.                 ELSE
  1248.                     veccolor(particleindex) = RoyalBlue
  1249.                 END IF
  1250.                 GOSUB calccom
  1251.             NEXT
  1252.         NEXT
  1253.         VectorGroup(vecgroupindex).LastParticle = particleindex
  1254.         GOSUB adjustcom
  1255.     NEXT
  1256.  
  1257. 'Snake?
  1258. vecgroupcounter = vecgroupcounter + 1
  1259. vecgroupindex = vecgroupcounter
  1260. VectorGroup(vecgroupindex).Identity = vecgroupindex
  1261. VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  1262. VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1263. VectorGroup(vecgroupindex).ContentName = "Snake?"
  1264. VectorGroup(vecgroupindex).ContentType = 3
  1265. VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1266. FOR i = -pi TO pi STEP .005
  1267.     particleindex = particleindex + 1
  1268.     vecorig(particleindex, 1) = -10 + 5 * COS(i)
  1269.     vecorig(particleindex, 2) = -20 + 5 * SIN(i)
  1270.     vecorig(particleindex, 3) = 25 - 3 * COS(6 * i) * SIN(3 * i)
  1271.     veccolor(particleindex) = Coral
  1272.     GOSUB calccom
  1273. VectorGroup(vecgroupindex).LastParticle = particleindex
  1274. GOSUB adjustcom
  1275.  
  1276. 'Sparks
  1277. vecgroupcounter = vecgroupcounter + 1
  1278. vecgroupindex = vecgroupcounter
  1279. VectorGroup(vecgroupindex).Identity = vecgroupindex
  1280. VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  1281. VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1282. VectorGroup(vecgroupindex).ContentName = "Sparks"
  1283. VectorGroup(vecgroupindex).ContentType = 32
  1284. VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1285. u = 0
  1286. v = 0
  1287. FOR i = 1 TO 300
  1288.     particleindex = particleindex + 1
  1289.     vecorig(particleindex, 1) = RND - .5
  1290.     vecorig(particleindex, 2) = RND - .5
  1291.     vecorig(particleindex, 3) = 20 + RND - .5
  1292.     vecorigvel(particleindex, 1) = 8 * (RND - .5)
  1293.     vecorigvel(particleindex, 2) = 8 * (RND - .5)
  1294.     vecorigvel(particleindex, 3) = 20 * RND
  1295.     vecorigacc(particleindex, 1) = 0
  1296.     vecorigacc(particleindex, 2) = 0
  1297.     vecorigacc(particleindex, 3) = -40
  1298.     veccolor(particleindex) = _RGB(INT(RND * 255), INT(RND * 255), INT(RND * 255))
  1299.     GOSUB calccom
  1300. VectorGroup(vecgroupindex).LastParticle = particleindex
  1301. GOSUB adjustcom
  1302.  
  1303. 'Stars
  1304. h = 5
  1305. FOR w = 1 TO 5
  1306.     FOR u = -gridsize TO gridsize STEP tilesize
  1307.         FOR v = -gridsize TO gridsize STEP tilesize
  1308.             vecgroupcounter = vecgroupcounter + 1
  1309.             vecgroupindex = vecgroupcounter
  1310.             VectorGroup(vecgroupindex).Identity = vecgroupindex
  1311.             VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  1312.             VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1313.             VectorGroup(vecgroupindex).ContentName = "Stars"
  1314.             VectorGroup(vecgroupindex).ContentType = 0
  1315.             VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1316.             FOR i = u TO u + tilesize STEP h
  1317.                 FOR j = v TO v + tilesize STEP h
  1318.                     IF RND > 1 - w / 5 THEN
  1319.                         particleindex = particleindex + 1
  1320.                         vecorig(particleindex, 1) = i + RND * h - RND * h
  1321.                         vecorig(particleindex, 2) = j + RND * h - RND * h
  1322.                         vecorig(particleindex, 3) = w * 70 + RND * 70
  1323.                         IF RND > .5 THEN
  1324.                             veccolor(particleindex) = GhostWhite
  1325.                         ELSE
  1326.                             IF RND > .5 THEN
  1327.                                 veccolor(particleindex) = White
  1328.                             ELSE
  1329.                                 veccolor(particleindex) = DarkGray
  1330.                             END IF
  1331.                         END IF
  1332.                         GOSUB calccom
  1333.                     END IF
  1334.                 NEXT
  1335.             NEXT
  1336.             VectorGroup(vecgroupindex).LastParticle = particleindex
  1337.             GOSUB adjustcom
  1338.         NEXT
  1339.     NEXT
  1340.  
  1341. 'Sun
  1342. radius = 10
  1343. dx = .0628
  1344. dy = .0628
  1345. xl = 0: xr = 2 * pi
  1346. yl = 0: yr = pi
  1347. xrange = 1 + INT((-xl + xr) / dx)
  1348. yrange = 1 + INT((-yl + yr) / dy)
  1349. FOR i = 1 TO xrange STEP 10
  1350.     FOR j = 1 TO yrange STEP 10
  1351.         vecgroupcounter = vecgroupcounter + 1
  1352.         vecgroupindex = vecgroupcounter
  1353.         VectorGroup(vecgroupindex).Identity = vecgroupindex
  1354.         VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  1355.         VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1356.         VectorGroup(vecgroupindex).ContentName = "Sun"
  1357.         VectorGroup(vecgroupindex).ContentType = 0
  1358.         VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1359.         FOR u = i TO i + 10 STEP 1
  1360.             FOR v = j TO j + 10 STEP 1
  1361.                 particleindex = particleindex + 1
  1362.                 theta = u * dx - dx
  1363.                 phi = v * dy - dy
  1364.                 vecorig(particleindex, 1) = radius * SIN(phi) * COS(theta)
  1365.                 vecorig(particleindex, 2) = radius * SIN(phi) * SIN(theta)
  1366.                 vecorig(particleindex, 3) = 90 + radius * COS(phi)
  1367.                 IF RND > .5 THEN
  1368.                     veccolor(particleindex) = Sunglow
  1369.                 ELSE
  1370.                     veccolor(particleindex) = SunsetOrange
  1371.                 END IF
  1372.                 GOSUB calccom
  1373.             NEXT
  1374.         NEXT
  1375.         VectorGroup(vecgroupindex).LastParticle = particleindex
  1376.         GOSUB adjustcom
  1377.     NEXT
  1378.  
  1379. 'UFO!!!
  1380. vecgroupcounter = vecgroupcounter + 1
  1381. vecgroupindex = vecgroupcounter
  1382. VectorGroup(vecgroupindex).Identity = vecgroupindex
  1383. VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  1384. VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1385. VectorGroup(vecgroupindex).ContentName = "UFO!!!"
  1386. VectorGroup(vecgroupindex).ContentType = 12
  1387. VectorGroup(vecgroupindex).CORx = 0
  1388. VectorGroup(vecgroupindex).CORy = 0
  1389. VectorGroup(vecgroupindex).CORz = 0
  1390. VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1391. FOR q = 0 TO 2 * pi STEP (2 * pi / 12) / 25
  1392.     FOR r = 10 TO 12 STEP .5
  1393.         particleindex = particleindex + 1
  1394.         vecorig(particleindex, 1) = -90 + r * COS(q)
  1395.         vecorig(particleindex, 2) = -120 + r * SIN(q)
  1396.         vecorig(particleindex, 3) = 100 + r - 12
  1397.         vecorigrot(particleindex, 1) = 0
  1398.         vecorigrot(particleindex, 2) = 0
  1399.         vecorigrot(particleindex, 3) = 1
  1400.         veccolor(particleindex) = HotPink
  1401.         GOSUB calccom
  1402.     NEXT
  1403.     FOR r = 12 TO 10 STEP -.5
  1404.         particleindex = particleindex + 1
  1405.         vecorig(particleindex, 1) = -90 + r * COS(q)
  1406.         vecorig(particleindex, 2) = -120 + r * SIN(q)
  1407.         vecorig(particleindex, 3) = 100 - r + 12
  1408.         vecorigrot(particleindex, 1) = 0
  1409.         vecorigrot(particleindex, 2) = 0
  1410.         vecorigrot(particleindex, 3) = 1
  1411.         veccolor(particleindex) = Red
  1412.         GOSUB calccom
  1413.     NEXT
  1414. r = 5
  1415. h = 30
  1416. FOR w = 1 TO 400
  1417.     xx = (RND - .5) * 2 * r
  1418.     yy = (RND - .5) * 2 * r
  1419.     IF xx ^ 2 + yy ^ 2 < r ^ 2 THEN
  1420.         particleindex = particleindex + 1
  1421.         vecorig(particleindex, 1) = -90 + xx
  1422.         vecorig(particleindex, 2) = -120 + yy
  1423.         vecorig(particleindex, 3) = 100 - RND * h
  1424.         vecorigrot(particleindex, 1) = 0
  1425.         vecorigrot(particleindex, 2) = 0
  1426.         vecorigrot(particleindex, 3) = 1
  1427.         IF RND > .5 THEN
  1428.             veccolor(particleindex) = Aquamarine
  1429.         ELSE
  1430.             veccolor(particleindex) = Lime
  1431.         END IF
  1432.         GOSUB calccom
  1433.     END IF
  1434. VectorGroup(vecgroupindex).LastParticle = particleindex
  1435. GOSUB adjustcom
  1436.  
  1437. 'Waves or Particles? (1)
  1438. FOR i = 1 TO 5 STEP 1
  1439.     FOR k = 1 TO 5 STEP 1
  1440.         vecgroupcounter = vecgroupcounter + 1
  1441.         vecgroupindex = vecgroupcounter
  1442.         VectorGroup(vecgroupindex).Identity = vecgroupindex
  1443.         VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  1444.         VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1445.         VectorGroup(vecgroupindex).ContentName = "Waves or Particles?"
  1446.         VectorGroup(vecgroupindex).ContentType = 0
  1447.         VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1448.         FOR u = i TO i + 1 STEP .05
  1449.             FOR v = k TO k + 1 STEP .05
  1450.                 particleindex = particleindex + 1
  1451.                 vecorig(particleindex, 1) = 70 + 7 * u
  1452.                 vecorig(particleindex, 2) = 80 + 1 * COS((u ^ 2 - v ^ 2))
  1453.                 vecorig(particleindex, 3) = 10 + 7 * v
  1454.                 IF vecorig(particleindex, 2) < 80 THEN
  1455.                     veccolor(particleindex) = DarkBlue
  1456.                 ELSE
  1457.                     veccolor(particleindex) = DeepPink
  1458.                 END IF
  1459.                 GOSUB calccom
  1460.             NEXT
  1461.         NEXT
  1462.         VectorGroup(vecgroupindex).LastParticle = particleindex
  1463.         GOSUB adjustcom
  1464.     NEXT
  1465.  
  1466. 'Waves or Particles? (2)
  1467. FOR i = 1 TO 5 STEP 1
  1468.     FOR k = 1 TO 5 STEP 1
  1469.         vecgroupcounter = vecgroupcounter + 1
  1470.         vecgroupindex = vecgroupcounter
  1471.         VectorGroup(vecgroupindex).Identity = vecgroupindex
  1472.         VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  1473.         VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1474.         VectorGroup(vecgroupindex).ContentName = "Waves or Particles?"
  1475.         VectorGroup(vecgroupindex).ContentType = 0
  1476.         VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1477.         FOR u = i TO i + 1 STEP .05
  1478.             FOR v = k TO k + 1 STEP .05
  1479.                 particleindex = particleindex + 1
  1480.                 vecorig(particleindex, 1) = -7 * u
  1481.                 vecorig(particleindex, 2) = 80 + 1 * COS(2 * ((u - 7) ^ 2 - (v - 5) ^ 2))
  1482.                 vecorig(particleindex, 3) = 10 + 7 * v
  1483.                 IF vecorig(particleindex, 2) < 80 THEN
  1484.                     veccolor(particleindex) = Magenta
  1485.                 ELSE
  1486.                     veccolor(particleindex) = Chocolate
  1487.                 END IF
  1488.                 GOSUB calccom
  1489.             NEXT
  1490.         NEXT
  1491.         VectorGroup(vecgroupindex).LastParticle = particleindex
  1492.         GOSUB adjustcom
  1493.     NEXT
  1494.  
  1495. 'File
  1496.     DO WHILE NOT EOF(1)
  1497.         INPUT #1, xx, yy, zz, co
  1498.         recordtype = 0
  1499.         IF xx = -111111 AND yy = -111111 AND zz = -111111 AND co = -111111 THEN ' Next record begins a group.
  1500.             recordtype = 111111
  1501.             INPUT #1, n$, m
  1502.             vecgroupcounter = vecgroupcounter + 1
  1503.             vecgroupindex = vecgroupcounter
  1504.             VectorGroup(vecgroupindex).Identity = vecgroupindex
  1505.             VectorGroup(vecgroupindex).Pointer = vecgroupindex + 1
  1506.             VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1507.             VectorGroup(vecgroupindex).ContentName = n$
  1508.             VectorGroup(vecgroupindex).ContentType = m
  1509.             VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1510.         END IF
  1511.         IF xx = -222222 AND yy = -222222 AND zz = -222222 AND co = -222222 THEN ' Next record is position offset for entire group.
  1512.             recordtype = 222222
  1513.             INPUT #1, xx, yy, zz
  1514.             vecorigvel(particleindex, 1) = 0 'xx
  1515.             vecorigvel(particleindex, 2) = 0 'yy
  1516.             vecorigvel(particleindex, 3) = 0 'zz
  1517.         END IF
  1518.         IF xx = -333333 AND yy = -333333 AND zz = -333333 AND co = -333333 THEN ' Next record is previous particle's linear velocity vector.
  1519.             recordtype = 333333
  1520.             INPUT #1, xx, yy, zz
  1521.             vecorigvel(particleindex, 1) = xx
  1522.             vecorigvel(particleindex, 2) = yy
  1523.             vecorigvel(particleindex, 3) = zz
  1524.         END IF
  1525.         IF xx = -444444 AND yy = -444444 AND zz = -444444 AND co = -444444 THEN ' Next record is previous particle's linear acceleration vector.
  1526.             recordtype = 444444
  1527.             INPUT #1, xx, yy, zz
  1528.             vecorigacc(particleindex, 1) = xx
  1529.             vecorigacc(particleindex, 2) = yy
  1530.             vecorigacc(particleindex, 3) = zz
  1531.         END IF
  1532.         IF xx = -555555 AND yy = -555555 AND zz = -555555 AND co = -555555 THEN ' Next record is rotation point for entire group.
  1533.             recordtype = 555555
  1534.             INPUT #1, xx, yy, zz
  1535.             VectorGroup(vecgroupindex).CORx = xx
  1536.             VectorGroup(vecgroupindex).CORy = yy
  1537.             VectorGroup(vecgroupindex).CORz = zz
  1538.         END IF
  1539.         IF xx = -666666 AND yy = -666666 AND zz = -666666 AND co = -666666 THEN ' Next record is previous particle's angular velocity vector.
  1540.             recordtype = 666666
  1541.             INPUT #1, xx, yy, zz
  1542.             vecorigrot(particleindex, 1) = xx
  1543.             vecorigrot(particleindex, 2) = yy
  1544.             vecorigrot(particleindex, 3) = zz
  1545.         END IF
  1546.         IF xx = -999999 AND yy = -999999 AND zz = -999999 AND co = -999999 THEN ' Previous record was last in group.
  1547.             recordtype = 999999
  1548.             VectorGroup(vecgroupindex).LastParticle = particleindex
  1549.             GOSUB adjustcom
  1550.         END IF
  1551.         IF xx = -123123 AND yy = -123123 AND zz = -123123 AND co = -123123 THEN ' Next record sets camera position.
  1552.             recordtype = 123123
  1553.             INPUT #1, xx, yy, zz
  1554.             camx = xx
  1555.             camy = yy
  1556.             camz = zz
  1557.         END IF
  1558.         IF xx = -234234 AND yy = -234234 AND zz = -234234 AND co = -234234 THEN ' Next two records set camera orientation.
  1559.             recordtype = 23434
  1560.             INPUT #1, xx, yy, zz
  1561.             uhat(1) = xx
  1562.             uhat(2) = yy
  1563.             uhat(3) = zz
  1564.             INPUT #1, xx, yy, zz
  1565.             vhat(1) = xx
  1566.             vhat(2) = yy
  1567.             vhat(3) = zz
  1568.         END IF
  1569.         IF recordtype = 0 THEN ' Not a special record. Store position and color.
  1570.             particleindex = particleindex + 1
  1571.             vecorig(particleindex, 1) = xx
  1572.             vecorig(particleindex, 2) = yy
  1573.             vecorig(particleindex, 3) = zz
  1574.             SELECT CASE co
  1575.                 CASE 0
  1576.                     veccolor(particleindex) = Black
  1577.                 CASE 1
  1578.                     veccolor(particleindex) = Blue
  1579.                 CASE 2
  1580.                     veccolor(particleindex) = Green
  1581.                 CASE 3
  1582.                     veccolor(particleindex) = Cyan
  1583.                 CASE 4
  1584.                     veccolor(particleindex) = Red
  1585.                 CASE 5
  1586.                     veccolor(particleindex) = Purple
  1587.                 CASE 6
  1588.                     veccolor(particleindex) = Orange
  1589.                 CASE 7
  1590.                     veccolor(particleindex) = LightGray
  1591.                 CASE 8
  1592.                     veccolor(particleindex) = DarkGray
  1593.                 CASE 9
  1594.                     veccolor(particleindex) = LightBlue
  1595.                 CASE 10
  1596.                     veccolor(particleindex) = LightGreen
  1597.                 CASE 11
  1598.                     veccolor(particleindex) = LightCyan
  1599.                 CASE 12
  1600.                     veccolor(particleindex) = OrangeRed 'lightred
  1601.                 CASE 13
  1602.                     veccolor(particleindex) = Violet 'lightpurple
  1603.                 CASE 14
  1604.                     veccolor(particleindex) = Yellow
  1605.                 CASE 15
  1606.                     veccolor(particleindex) = White
  1607.                 CASE ELSE
  1608.                     veccolor(particleindex) = White
  1609.             END SELECT
  1610.             GOSUB calccom
  1611.         END IF
  1612.     LOOP
  1613.     CLOSE #1
  1614.  
  1615. '__ZZZ
  1616. vecgroupcounter = vecgroupcounter + 1
  1617. vecgroupindex = vecgroupcounter
  1618. VectorGroup(vecgroupindex).Identity = vecgroupindex
  1619. VectorGroup(vecgroupindex).Pointer = -999
  1620. VectorGroup(vecgroupindex).Lagger = vecgroupindex - 1
  1621. VectorGroup(vecgroupindex).ContentName = "__ZZZ"
  1622. VectorGroup(vecgroupindex).ContentType = 0
  1623. VectorGroup(vecgroupindex).FirstParticle = particleindex + 1
  1624. FOR r = 1 TO 5
  1625.     particleindex = particleindex + 1
  1626.     vecorig(particleindex, 1) = -1000
  1627.     vecorig(particleindex, 2) = -1000
  1628.     vecorig(particleindex, 3) = -1000
  1629.     veccolor(particleindex) = White
  1630.     GOSUB calccom
  1631. VectorGroup(vecgroupindex).LastParticle = particleindex
  1632. GOSUB adjustcom
  1633.  
  1634. numparticleorig = particleindex
  1635.  
  1636. timeanimate:
  1637. thename$ = LTRIM$(RTRIM$(VectorGroup(vecgroupindex).ContentName))
  1638. IF thetype = 31 THEN ' Scatter
  1639.     dt = timestep * 100
  1640.     GOSUB resetcom
  1641.     FOR particleindex = VectorGroup(vecgroupindex).FirstParticle TO VectorGroup(vecgroupindex).LastParticle
  1642.         vecorigvel(particleindex, 1) = vecorigvel(particleindex, 1) + vecorigacc(particleindex, 1) * dt
  1643.         vecorigvel(particleindex, 2) = vecorigvel(particleindex, 2) + vecorigacc(particleindex, 2) * dt
  1644.         vecorigvel(particleindex, 3) = vecorigvel(particleindex, 3) + vecorigacc(particleindex, 3) * dt
  1645.         vecorig(particleindex, 1) = vecorig(particleindex, 1) + vecorigvel(particleindex, 1) * dt
  1646.         vecorig(particleindex, 2) = vecorig(particleindex, 2) + vecorigvel(particleindex, 2) * dt
  1647.         vecorig(particleindex, 3) = vecorig(particleindex, 3) + vecorigvel(particleindex, 3) * dt
  1648.         IF vecorig(particleindex, 3) < 0 THEN
  1649.             vecorig(particleindex, 3) = 0
  1650.             vecorigvel(particleindex, 1) = vecorigvel(particleindex, 1) * .75
  1651.             vecorigvel(particleindex, 2) = vecorigvel(particleindex, 2) * .75
  1652.             vecorigvel(particleindex, 3) = -vecorigvel(particleindex, 3) * .5
  1653.         END IF
  1654.         GOSUB calccom
  1655.     NEXT
  1656.     GOSUB adjustcom
  1657.     IF INT(TIMER) - VectorGroup(vecgroupindex).EventTimer > 6 THEN
  1658.         VectorGroup(vecgroupindex).ContentName = "Destroyed " + VectorGroup(vecgroupindex).ContentName
  1659.         VectorGroup(vecgroupindex).ContentType = 0
  1660.     END IF
  1661. IF thetype = 2 OR thetype = 12 THEN ' Standard Rotor, Forced Rotor
  1662.     GOSUB resetcom
  1663.     FOR particleindex = VectorGroup(vecgroupindex).FirstParticle TO VectorGroup(vecgroupindex).LastParticle
  1664.         x = vecorig(particleindex, 1) - VectorGroup(vecgroupindex).CORx
  1665.         y = vecorig(particleindex, 2) - VectorGroup(vecgroupindex).CORy
  1666.         z = vecorig(particleindex, 3) - VectorGroup(vecgroupindex).CORz
  1667.         ax = vecorigrot(particleindex, 1)
  1668.         ay = vecorigrot(particleindex, 2)
  1669.         az = vecorigrot(particleindex, 3)
  1670.         IF az <> 0 THEN
  1671.             da = timestep * az
  1672.             xx = x
  1673.             yy = y
  1674.             x = xx * COS(da) - yy * SIN(da)
  1675.             y = xx * SIN(da) + yy * COS(da)
  1676.         END IF
  1677.         IF ay <> 0 THEN
  1678.             da = timestep * ay
  1679.             xx = x
  1680.             zz = z
  1681.             x = xx * COS(da) + zz * SIN(da)
  1682.             z = -xx * SIN(da) + zz * COS(da)
  1683.         END IF
  1684.         IF ax <> 0 THEN
  1685.             da = timestep * ax
  1686.             yy = y
  1687.             zz = z
  1688.             y = yy * COS(da) - zz * SIN(da)
  1689.             z = yy * SIN(da) + zz * COS(da)
  1690.         END IF
  1691.         vecorig(particleindex, 1) = x + VectorGroup(vecgroupindex).CORx
  1692.         vecorig(particleindex, 2) = y + VectorGroup(vecgroupindex).CORy
  1693.         vecorig(particleindex, 3) = z + VectorGroup(vecgroupindex).CORz
  1694.         GOSUB calccom
  1695.     NEXT
  1696.     GOSUB adjustcom
  1697. IF thename$ = "Clock Hands" THEN
  1698.     pin = VectorGroup(vecgroupindex).FirstParticle
  1699.     hands(1, 1) = VAL(LEFT$(TIME$, 2)) * (2 * pi / 12)
  1700.     hands(2, 1) = VAL(MID$(TIME$, 4, 2)) * (2 * pi / 60)
  1701.     hands(3, 1) = VAL(RIGHT$(TIME$, 2)) * (2 * pi / 60)
  1702.     FOR q = 1 TO 3
  1703.         FOR r = 0 TO 5 + q STEP .1
  1704.             pin = pin + 1
  1705.             vecorig(pin, 1) = 40 + r * COS(hands(q, 1) + pi / 2)
  1706.             vecorig(pin, 2) = -10
  1707.             vecorig(pin, 3) = 40 + r * SIN(hands(q, 1) + pi / 2)
  1708.         NEXT
  1709.     NEXT
  1710. IF thename$ = "Hell Spawn" THEN
  1711.     FOR i = VectorGroup(vecgroupindex).FirstParticle TO VectorGroup(vecgroupindex).LastParticle
  1712.         vecorig(i, 3) = vecorig(i, 3) + .3
  1713.         IF vecorig(i, 3) > -350 THEN vecorig(i, 3) = -350 - 70
  1714.     NEXT
  1715. IF thename$ = "Rain" THEN
  1716.     FOR i = VectorGroup(vecgroupindex).FirstParticle TO VectorGroup(vecgroupindex).LastParticle
  1717.         vecorig(i, 3) = vecorig(i, 3) - .3
  1718.         IF vecorig(i, 3) < 0 THEN vecorig(i, 3) = 70
  1719.     NEXT
  1720. IF thename$ = "Snake?" AND thetype = 3 THEN
  1721.     pin = VectorGroup(vecgroupindex).FirstParticle
  1722.     t = timevar
  1723.     FOR i = -pi TO pi STEP .005
  1724.         vecorig(pin, 1) = -10 + 5 * COS(i + t)
  1725.         vecorig(pin, 2) = -20 + 5 * SIN(i + t)
  1726.         vecorig(pin, 3) = 25 - 3 * COS(6 * i + t) * SIN(3 * i + t)
  1727.         pin = pin + 1
  1728.     NEXT
  1729. IF thename$ = "Sparks" THEN
  1730.     GOSUB resetcom
  1731.     dt = timestep * 100
  1732.     FOR particleindex = VectorGroup(vecgroupindex).FirstParticle TO VectorGroup(vecgroupindex).LastParticle
  1733.         vecorigvel(particleindex, 1) = vecorigvel(particleindex, 1) + vecorigacc(particleindex, 1) * dt
  1734.         vecorigvel(particleindex, 2) = vecorigvel(particleindex, 2) + vecorigacc(particleindex, 2) * dt
  1735.         vecorigvel(particleindex, 3) = vecorigvel(particleindex, 3) + vecorigacc(particleindex, 3) * dt
  1736.         vecorig(particleindex, 1) = vecorig(particleindex, 1) + vecorigvel(particleindex, 1) * dt
  1737.         vecorig(particleindex, 2) = vecorig(particleindex, 2) + vecorigvel(particleindex, 2) * dt
  1738.         vecorig(particleindex, 3) = vecorig(particleindex, 3) + vecorigvel(particleindex, 3) * dt
  1739.         IF vecorig(particleindex, 3) < 0 THEN
  1740.             vecorig(particleindex, 3) = 0
  1741.             vecorigvel(particleindex, 1) = vecorigvel(particleindex, 1) * .75
  1742.             vecorigvel(particleindex, 2) = vecorigvel(particleindex, 2) * .75
  1743.             vecorigvel(particleindex, 3) = -vecorigvel(particleindex, 3) * .5
  1744.         END IF
  1745.         GOSUB calccom
  1746.     NEXT
  1747.     GOSUB adjustcom
  1748.  
  1749. explode:
  1750. vecgroupindex = VectorGroup(1).Identity
  1751.     IF LTRIM$(RTRIM$(VectorGroup(vecgroupindex).ContentName)) = "Sparks" THEN
  1752.         GOSUB resetcom
  1753.         FOR particleindex = VectorGroup(vecgroupindex).FirstParticle TO VectorGroup(vecgroupindex).LastParticle
  1754.             vecorig(particleindex, 1) = explodex
  1755.             vecorig(particleindex, 2) = explodey
  1756.             vecorig(particleindex, 3) = explodez
  1757.             vecorigvel(particleindex, 1) = (RND - .5) * 20
  1758.             vecorigvel(particleindex, 2) = (RND - .5) * 20
  1759.             vecorigvel(particleindex, 3) = (RND - .2) * 40
  1760.             vecorigacc(particleindex, 3) = -30
  1761.             GOSUB calccom
  1762.         NEXT
  1763.         GOSUB adjustcom
  1764.         EXIT DO
  1765.     END IF
  1766.     vecgroupindex = VectorGroup(vecgroupindex).Pointer
  1767.     IF vecgroupindex = -999 THEN EXIT DO
  1768.     vecgroupindex = VectorGroup(vecgroupindex).Identity
  1769.  
  1770. calccom:
  1771. VectorGroup(vecgroupindex).COMx = vecorig(particleindex, 1) + VectorGroup(vecgroupindex).COMx
  1772. VectorGroup(vecgroupindex).COMy = vecorig(particleindex, 2) + VectorGroup(vecgroupindex).COMy
  1773. VectorGroup(vecgroupindex).COMz = vecorig(particleindex, 3) + VectorGroup(vecgroupindex).COMz
  1774.  
  1775. adjustcom:
  1776. f = 1 + VectorGroup(vecgroupindex).LastParticle - VectorGroup(vecgroupindex).FirstParticle
  1777. VectorGroup(vecgroupindex).COMx = VectorGroup(vecgroupindex).COMx / f
  1778. VectorGroup(vecgroupindex).COMy = VectorGroup(vecgroupindex).COMy / f
  1779. VectorGroup(vecgroupindex).COMz = VectorGroup(vecgroupindex).COMz / f
  1780.  
  1781. resetcom:
  1782. VectorGroup(vecgroupindex).COMx = 0
  1783. VectorGroup(vecgroupindex).COMy = 0
  1784. VectorGroup(vecgroupindex).COMz = 0
* Color32.BI (Filesize: 10.92 KB, Downloads: 192)
* level.txt (Filesize: 18.58 KB, Downloads: 194)
« Last Edit: February 12, 2019, 09:31:32 pm by STxAxTIC »
You're not done when it works, you're done when it's right.

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Sanctum: Open world 3D engine using CIRCLE and LINE
« Reply #1 on: February 02, 2019, 12:51:43 am »
... And something tells me those members in our 60+ club who grew up without FPS games might need a hand... and so might the lazy people too.

Here is a three minute video of me flying around. My first youtube post btw.

https://youtu.be/Jgw4TX0f8NE
« Last Edit: February 02, 2019, 05:30:13 pm by STxAxTIC »
You're not done when it works, you're done when it's right.

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Sanctum: Open world 3D engine using CIRCLE and LINE
« Reply #2 on: February 02, 2019, 11:07:50 am »
60+ Club? A hand, no, a liver... maybe. :D

I tried it, but it triggers my trip. I miss the days when the saying made more sense the other way around. Anyways, thanks the posting the 3-D effect in our 2-D universe, but since we are living in a Second-D World, and I'm a SCREEN 0 girl, I'll stick with the text stuff.

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Sigh.

Just for Pete, here is the same program in SCREEN 0. (Where's Fluffrabbit by the way?)

Code: QB64: [Select]
  1. '#lang "qb"
  2.  
  3. ' Video.
  4. screenwidth = 640
  5. screenheight = 480
  6.  
  7. ' Memory.
  8. DIM bignumber AS LONG
  9. bignumber = 3000000
  10. DIM numparticleorig AS LONG
  11. numparticleorig = bignumber
  12. numparticlevisible = bignumber
  13.  
  14. ' Constant(s).
  15. pi = 3.1415926536
  16. ee = 2.7182818285
  17.  
  18. ' Camera orientation vectors.
  19. DIM uhat(1 TO 3), vhat(1 TO 3), nhat(1 TO 3)
  20.  
  21. ' Clipping planes.
  22. DIM nearplane(1 TO 4), farplane(1 TO 4), rightplane(1 TO 4), leftplane(1 TO 4), topplane(1 TO 4), bottomplane(1 TO 4)
  23.  
  24. ' Basis vectors defined in xyz three-space.
  25. DIM xhat(1 TO 4), yhat(1 TO 4), zhat(1 TO 4)
  26. xhat(1) = 1: xhat(2) = 0: xhat(3) = 0: xhat(4) = 4
  27. yhat(1) = 0: yhat(2) = 1: yhat(3) = 0: yhat(4) = 2
  28. zhat(1) = 0: zhat(2) = 0: zhat(3) = 1: zhat(4) = 1
  29.  
  30. ' Basis vectors projected in uv two-space.
  31. DIM xhatp(1 TO 2), yhatp(1 TO 2), zhatp(1 TO 2)
  32.  
  33. ' Particle vectors defined in xyz three-space.
  34. DIM vecgroupname(bignumber / 10) AS STRING
  35. DIM vecaddress(bignumber / 10, 2) AS LONG
  36. DIM veccom(bignumber / 10, 3)
  37. DIM vecorig(numparticleorig, 3)
  38. DIM vecorigvel(numparticleorig, 3)
  39. DIM vecorigacc(numparticleorig, 3)
  40. DIM veccolor(numparticleorig)
  41. DIM vec(numparticleorig, 3)
  42. DIM vecvisible(numparticlevisible, 4)
  43.  
  44. ' Particle vectors projected in uv two-space.
  45. DIM vecpuv(numparticleorig, 1 TO 2)
  46. DIM vecvisiblepuv(numparticlevisible, 1 TO 2)
  47.  
  48. ' Particle projections adjusted for screen uv two-space.
  49. DIM vecpuvs(numparticleorig, 1 TO 2)
  50. DIM vecvisiblepuvs(numparticlevisible, 1 TO 2)
  51.  
  52. ' State.
  53. vecgroupcounter = 0
  54. numparticleorig = 0
  55. numparticlevisible = 0
  56. pcountparticleorig = 0
  57. fovd = -256 ' Field-of-view constant.
  58. nearplane(4) = 1
  59. farplane(4) = -100
  60. rightplane(4) = 0 '*' fovd * (nhat(1) * rightplane(1) + nhat(2) * rightplane(2) + nhat(3) * rightplane(3))
  61. leftplane(4) = 0
  62. topplane(4) = 0
  63. bottomplane(4) = 0
  64. centerx = screenwidth / 2
  65. centery = screenheight / 2
  66. speeddamp = 1 / 66 ' Rotation damper.
  67. speedboost = 1.5 ' Linear boost.
  68. timevar = 0
  69. uhat(1) = -.2078192: uhat(2) = -.9781672: uhat(3) = 0
  70. vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  71. camx = -42
  72. camy = 28
  73. camz = 40
  74. toggletimeanimate = 1
  75. toggleinvertmouse = -1
  76. togglehud = 1
  77.  
  78. ' Prime main loop.
  79. GOSUB initialize.objects
  80. numparticleorig = pcountparticleorig
  81. GOSUB redraw
  82.  
  83. ' Begin main loop.
  84.     IF toggletimeanimate = 1 THEN flagredraw = 1
  85.     IF flagredraw = 1 THEN
  86.         GOSUB redraw
  87.         flagredraw = -1
  88.     END IF
  89.     GOSUB mouseprocess
  90.     GOSUB keyprocess
  91.  
  92.     _DISPLAY
  93.     _KEYCLEAR
  94.     _LIMIT 30
  95.  
  96.  
  97. ' Gosubs.
  98.  
  99. mouseprocess:
  100.         GOSUB rotate.uhat.plus: GOSUB normalize.screen.vectors
  101.     END IF
  102.         GOSUB rotate.uhat.minus: GOSUB normalize.screen.vectors
  103.     END IF
  104.         IF toggleinvertmouse = -1 THEN
  105.             GOSUB rotate.vhat.plus: GOSUB normalize.screen.vectors
  106.         ELSE
  107.             GOSUB rotate.vhat.minus: GOSUB normalize.screen.vectors
  108.         END IF
  109.     END IF
  110.         IF toggleinvertmouse = -1 THEN
  111.             GOSUB rotate.vhat.minus: GOSUB normalize.screen.vectors
  112.         ELSE
  113.             GOSUB rotate.vhat.plus: GOSUB normalize.screen.vectors
  114.         END IF
  115.     END IF
  116.     IF _MOUSEWHEEL > 0 THEN GOSUB rotate.clockwise
  117.     IF _MOUSEWHEEL < 0 THEN GOSUB rotate.counterclockwise
  118.     'MouseLB = _MOUSEBUTTON(1)
  119.     'MouseRB = _MOUSEBUTTON(2)
  120.     flagredraw = 1
  121.  
  122. keyprocess:
  123. IF key$ <> "" THEN flagredraw = 1
  124.     CASE "8":
  125.         GOSUB rotate.vhat.plus
  126.     CASE "2":
  127.         GOSUB rotate.vhat.minus
  128.     CASE "4":
  129.         GOSUB rotate.uhat.minus
  130.     CASE "6":
  131.         GOSUB rotate.uhat.plus
  132.     CASE "7":
  133.         GOSUB rotate.clockwise
  134.     CASE "9":
  135.         GOSUB rotate.counterclockwise
  136.     CASE "1":
  137.         GOSUB rotate.uhat.minus: GOSUB normalize.screen.vectors: GOSUB rotate.clockwise
  138.     CASE "3":
  139.         GOSUB rotate.uhat.plus: GOSUB normalize.screen.vectors: GOSUB rotate.counterclockwise
  140.     CASE "s"
  141.         GOSUB strafe.camera.nhat.plus
  142.     CASE "w"
  143.         GOSUB strafe.camera.nhat.minus
  144.     CASE "d"
  145.         GOSUB strafe.camera.uhat.plus
  146.     CASE "a"
  147.         GOSUB strafe.camera.uhat.minus
  148.     CASE "e"
  149.         GOSUB strafe.camera.vhat.plus
  150.     CASE "q"
  151.         GOSUB strafe.camera.vhat.minus
  152.     CASE "x"
  153.         uhat(1) = 0: uhat(2) = 1: uhat(3) = 0
  154.         vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  155.     CASE "X"
  156.         uhat(1) = 0: uhat(2) = -1: uhat(3) = 0
  157.         vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  158.     CASE "y"
  159.         uhat(1) = -1: uhat(2) = 0: uhat(3) = 0
  160.         vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  161.     CASE "Y"
  162.         uhat(1) = 1: uhat(2) = 0: uhat(3) = 0
  163.         vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  164.     CASE "z"
  165.         uhat(1) = 1: uhat(2) = 0: uhat(3) = 0
  166.         vhat(1) = 0: vhat(2) = 1: vhat(3) = 0
  167.         GOSUB normalize.screen.vectors
  168.     CASE "Z"
  169.         uhat(1) = 0: uhat(2) = 1: uhat(3) = 0
  170.         vhat(1) = 1: vhat(2) = 0: vhat(3) = 0
  171.     CASE "]"
  172.         farplane(4) = farplane(4) - 1
  173.     CASE "["
  174.         farplane(4) = farplane(4) + 1
  175.     CASE " "
  176.         togglehud = -togglehud
  177.     CASE "t"
  178.         toggletimeanimate = -toggletimeanimate
  179.     CASE "i"
  180.         toggleinvertmouse = -toggleinvertmouse
  181.     CASE CHR$(27)
  182.         SYSTEM
  183.     CASE "f"
  184.         FOR k = 1 TO vecgroupcounter
  185.             IF vecgroupname(k) = "Sparks" THEN
  186.                 vgc = k
  187.                 FOR i = vecaddress(vgc, 1) TO vecaddress(vgc, 2)
  188.                     vecorig(i, 1) = camx + -nhat(1) * (1 - .1 * RND) * 60
  189.                     vecorig(i, 2) = camy + -nhat(2) * (1 - .1 * RND) * 60
  190.                     vecorig(i, 3) = camz + -nhat(3) * (1 - .1 * RND) * 60
  191.                     vecorigvel(i, 1) = (RND - .5) * 20
  192.                     vecorigvel(i, 2) = (RND - .5) * 20
  193.                     vecorigvel(i, 3) = (RND - .2) * 40
  194.                     vecorigacc(i, 3) = -30
  195.                     GOSUB calccom
  196.                 NEXT
  197.                 GOSUB adjustcom
  198.             END IF
  199.         NEXT
  200.  
  201. convert:
  202. ' Convert graphics from uv-cartesian coordinates to monitor coordinates.
  203. x0 = x: y0 = y
  204. x = x0 + centerx
  205. y = -y0 + centery
  206.  
  207. rotate.uhat.plus:
  208. uhat(1) = uhat(1) + nhat(1) * speeddamp
  209. uhat(2) = uhat(2) + nhat(2) * speeddamp
  210. uhat(3) = uhat(3) + nhat(3) * speeddamp
  211.  
  212. rotate.uhat.minus:
  213. uhat(1) = uhat(1) - nhat(1) * speeddamp
  214. uhat(2) = uhat(2) - nhat(2) * speeddamp
  215. uhat(3) = uhat(3) - nhat(3) * speeddamp
  216.  
  217. rotate.vhat.plus:
  218. vhat(1) = vhat(1) + nhat(1) * speeddamp
  219. vhat(2) = vhat(2) + nhat(2) * speeddamp
  220. vhat(3) = vhat(3) + nhat(3) * speeddamp
  221.  
  222. rotate.vhat.minus:
  223. vhat(1) = vhat(1) - nhat(1) * speeddamp
  224. vhat(2) = vhat(2) - nhat(2) * speeddamp
  225. vhat(3) = vhat(3) - nhat(3) * speeddamp
  226.  
  227. rotate.counterclockwise:
  228. v1 = vhat(1)
  229. v2 = vhat(2)
  230. v3 = vhat(3)
  231. vhat(1) = vhat(1) + uhat(1) * speeddamp
  232. vhat(2) = vhat(2) + uhat(2) * speeddamp
  233. vhat(3) = vhat(3) + uhat(3) * speeddamp
  234. uhat(1) = uhat(1) - v1 * speeddamp
  235. uhat(2) = uhat(2) - v2 * speeddamp
  236. uhat(3) = uhat(3) - v3 * speeddamp
  237.  
  238. rotate.clockwise:
  239. v1 = vhat(1)
  240. v2 = vhat(2)
  241. v3 = vhat(3)
  242. vhat(1) = vhat(1) - uhat(1) * speeddamp
  243. vhat(2) = vhat(2) - uhat(2) * speeddamp
  244. vhat(3) = vhat(3) - uhat(3) * speeddamp
  245. uhat(1) = uhat(1) + v1 * speeddamp
  246. uhat(2) = uhat(2) + v2 * speeddamp
  247. uhat(3) = uhat(3) + v3 * speeddamp
  248.  
  249. strafe.camera.uhat.plus:
  250. camx = camx + uhat(1) * speedboost
  251. camy = camy + uhat(2) * speedboost
  252. camz = camz + uhat(3) * speedboost
  253.  
  254. strafe.camera.uhat.minus:
  255. camx = camx - uhat(1) * speedboost
  256. camy = camy - uhat(2) * speedboost
  257. camz = camz - uhat(3) * speedboost
  258.  
  259. strafe.camera.vhat.plus:
  260. camx = camx + vhat(1) * speedboost
  261. camy = camy + vhat(2) * speedboost
  262. camz = camz + vhat(3) * speedboost
  263.  
  264. strafe.camera.vhat.minus:
  265. camx = camx - vhat(1) * speedboost
  266. camy = camy - vhat(2) * speedboost
  267. camz = camz - vhat(3) * speedboost
  268.  
  269. strafe.camera.nhat.plus:
  270. camx = camx + nhat(1) * speedboost
  271. camy = camy + nhat(2) * speedboost
  272. camz = camz + nhat(3) * speedboost
  273.  
  274. strafe.camera.nhat.minus:
  275. camx = camx - nhat(1) * speedboost
  276. camy = camy - nhat(2) * speedboost
  277. camz = camz - nhat(3) * speedboost
  278.  
  279. normalize.screen.vectors:
  280. uhatmag = SQR(uhat(1) ^ 2 + uhat(2) ^ 2 + uhat(3) ^ 2)
  281. uhat(1) = uhat(1) / uhatmag: uhat(2) = uhat(2) / uhatmag: uhat(3) = uhat(3) / uhatmag
  282. vhatmag = SQR(vhat(1) ^ 2 + vhat(2) ^ 2 + vhat(3) ^ 2)
  283. vhat(1) = vhat(1) / vhatmag: vhat(2) = vhat(2) / vhatmag: vhat(3) = vhat(3) / vhatmag
  284. uhatdotvhat = uhat(1) * vhat(1) + uhat(2) * vhat(2) + uhat(3) * vhat(3)
  285. IF SQR(uhatdotvhat ^ 2) > .0005 THEN
  286.     BEEP ' ... if vectors are somenow not normalized. This has never happened.
  287.     uhat(1) = 0.8251367: uhat(2) = -0.564903: uhat(3) = -0.005829525
  288.     vhat(1) = 0.065519: vhat(2) = 0.08544215: vhat(3) = 0.9941866
  289. ' The normal vector points toward the eye.
  290. nhat(1) = uhat(2) * vhat(3) - uhat(3) * vhat(2)
  291. nhat(2) = uhat(3) * vhat(1) - uhat(1) * vhat(3)
  292. nhat(3) = uhat(1) * vhat(2) - uhat(2) * vhat(1)
  293. nhatmag = SQR(nhat(1) ^ 2 + nhat(2) ^ 2 + nhat(3) ^ 2)
  294. nhat(1) = nhat(1) / nhatmag: nhat(2) = nhat(2) / nhatmag: nhat(3) = nhat(3) / nhatmag
  295.  
  296. redraw:
  297. GOSUB normalize.screen.vectors
  298. GOSUB calculate.clippingplanes
  299. ' Project the three-space basis vectors onto the screen plane.
  300. xhatp(1) = xhat(1) * uhat(1) + xhat(2) * uhat(2) + xhat(3) * uhat(3)
  301. xhatp(2) = xhat(1) * vhat(1) + xhat(2) * vhat(2) + xhat(3) * vhat(3)
  302. yhatp(1) = yhat(1) * uhat(1) + yhat(2) * uhat(2) + yhat(3) * uhat(3)
  303. yhatp(2) = yhat(1) * vhat(1) + yhat(2) * vhat(2) + yhat(3) * vhat(3)
  304. zhatp(1) = zhat(1) * uhat(1) + zhat(2) * uhat(2) + zhat(3) * uhat(3)
  305. zhatp(2) = zhat(1) * vhat(1) + zhat(2) * vhat(2) + zhat(3) * vhat(3)
  306. GOSUB compute.visible.particles
  307. GOSUB project.particles
  308. GOSUB draw.all.objects
  309.  
  310. compute.visible.particles:
  311. numparticlevisible = 0
  312. closestdist2 = 10000 ^ 2
  313. closestgroup = -1
  314. FOR k = 1 TO vecgroupcounter
  315.     dist2 = (camx - veccom(k, 1)) ^ 2 + (camy - veccom(k, 2)) ^ 2 + (camz - veccom(k, 3)) ^ 2
  316.  
  317.     IF dist2 < farplane(4) ^ 2 THEN
  318.  
  319.         groupinview = 1 ' Dsiable near plane group clipping to make things more interesting at zero distance.
  320.         IF (veccom(k, 1) - camx) * nearplane(1) + (veccom(k, 2) - camy) * nearplane(2) + (veccom(k, 3) - camz) * nearplane(3) - nearplane(4) < 0 THEN groupinview = 0
  321.         'IF (veccom(k, 1) - camx) * farplane(1) + (veccom(k, 2) - camy) * farplane(2) + (veccom(k, 3) - camz) * farplane(3) - farplane(4) < 0 THEN groupinview = 0
  322.         IF (veccom(k, 1) - camx) * rightplane(1) + (veccom(k, 2) - camy) * rightplane(2) + (veccom(k, 3) - camz) * rightplane(3) - rightplane(4) < 0 THEN groupinview = 0
  323.         IF (veccom(k, 1) - camx) * leftplane(1) + (veccom(k, 2) - camy) * leftplane(2) + (veccom(k, 3) - camz) * leftplane(3) - leftplane(4) < 0 THEN groupinview = 0
  324.         IF (veccom(k, 1) - camx) * topplane(1) + (veccom(k, 2) - camy) * topplane(2) + (veccom(k, 3) - camz) * topplane(3) - topplane(4) < 0 THEN groupinview = 0
  325.         IF (veccom(k, 1) - camx) * bottomplane(1) + (veccom(k, 2) - camy) * bottomplane(2) + (veccom(k, 3) - camz) * bottomplane(3) - bottomplane(4) < 0 THEN groupinview = 0
  326.         IF groupinview = 1 THEN
  327.  
  328.             FOR i = vecaddress(k, 1) TO vecaddress(k, 2)
  329.                 vec(i, 1) = vecorig(i, 1) - camx
  330.                 vec(i, 2) = vecorig(i, 2) - camy
  331.                 vec(i, 3) = vecorig(i, 3) - camz
  332.             NEXT
  333.  
  334.             IF toggletimeanimate = 1 THEN GOSUB timeanimate
  335.  
  336.             FOR i = vecaddress(k, 1) TO vecaddress(k, 2)
  337.                 GOSUB clip.particle.viewplanes
  338.             NEXT
  339.  
  340.         END IF
  341.  
  342.         IF dist2 < closestdist2 THEN
  343.             closestdist2 = dist2
  344.             closestgroup = k
  345.         END IF
  346.  
  347.     END IF
  348.  
  349. clip.particle.viewplanes:
  350. particleinview = 1
  351. fogswitch = -1
  352. ' Perform standard view plane clipping and implement fog effect.
  353. IF vec(i, 1) * nearplane(1) + vec(i, 2) * nearplane(2) + vec(i, 3) * nearplane(3) - nearplane(4) < 0 THEN particleinview = 0
  354. IF vec(i, 1) * farplane(1) + vec(i, 2) * farplane(2) + vec(i, 3) * farplane(3) - farplane(4) < 0 THEN particleinview = 0
  355. IF vec(i, 1) * farplane(1) + vec(i, 2) * farplane(2) + vec(i, 3) * farplane(3) - farplane(4) * .9 < 0 THEN fogswitch = 1
  356. IF vec(i, 1) * rightplane(1) + vec(i, 2) * rightplane(2) + vec(i, 3) * rightplane(3) - rightplane(4) < 0 THEN particleinview = 0
  357. IF vec(i, 1) * leftplane(1) + vec(i, 2) * leftplane(2) + vec(i, 3) * leftplane(3) - leftplane(4) < 0 THEN particleinview = 0
  358. IF vec(i, 1) * topplane(1) + vec(i, 2) * topplane(2) + vec(i, 3) * topplane(3) - topplane(4) < 0 THEN particleinview = 0
  359. IF vec(i, 1) * bottomplane(1) + vec(i, 2) * bottomplane(2) + vec(i, 3) * bottomplane(3) - bottomplane(4) < 0 THEN particleinview = 0
  360. IF particleinview = 1 THEN
  361.     numparticlevisible = numparticlevisible + 1
  362.     vecvisible(numparticlevisible, 1) = vec(i, 1)
  363.     vecvisible(numparticlevisible, 2) = vec(i, 2)
  364.     vecvisible(numparticlevisible, 3) = vec(i, 3)
  365.     vecvisible(numparticlevisible, 4) = veccolor(i)
  366.     IF fogswitch = 1 THEN vecvisible(numparticlevisible, 4) = 8
  367.  
  368. project.particles:
  369. ' Project vectors onto the screen plane.
  370. FOR i = 1 TO numparticlevisible
  371.     vecvisibledotnhat = vecvisible(i, 1) * nhat(1) + vecvisible(i, 2) * nhat(2) + vecvisible(i, 3) * nhat(3)
  372.     vecvisiblepuv(i, 1) = vecvisible(i, 1) * uhat(1) + vecvisible(i, 2) * uhat(2) + vecvisible(i, 3) * uhat(3)
  373.     vecvisiblepuv(i, 2) = vecvisible(i, 1) * vhat(1) + vecvisible(i, 2) * vhat(2) + vecvisible(i, 3) * vhat(3)
  374.     vecvisiblepuvs(i, 1) = vecvisiblepuv(i, 1) * fovd / vecvisibledotnhat
  375.     vecvisiblepuvs(i, 2) = vecvisiblepuv(i, 2) * fovd / vecvisibledotnhat
  376.  
  377. draw.all.objects:
  378. GOSUB plot.particles
  379. ' Redraw compass.
  380. x = 30 * xhatp(1): y = 30 * xhatp(2): GOSUB convert
  381. 'LINE (centerx, centery)-(x, y), xhat(4)
  382. x = 30 * yhatp(1): y = 30 * yhatp(2): GOSUB convert
  383. 'LINE (centerx, centery)-(x, y), yhat(4)
  384. x = 30 * zhatp(1): y = 30 * zhatp(2): GOSUB convert
  385. 'LINE (centerx, centery)-(x, y), zhat(4)
  386. IF togglehud = 1 THEN
  387.     COLOR 7
  388.     LOCATE 28, 26: PRINT "SPACE = toggle Info,  ESC = quit."
  389.     COLOR 14
  390.     LOCATE 26, 2: PRINT "- MOVE - ALIGN -"
  391.     COLOR 15
  392.     LOCATE 27, 2: PRINT " q w e - x y z"
  393.     LOCATE 28, 2: PRINT " a s d - X Y Z"
  394.     COLOR 14
  395.     LOCATE 25, 68: PRINT "-  ROTATE  -"
  396.     COLOR 7
  397.     LOCATE 26, 68: PRINT "7 8 9"
  398.     LOCATE 27, 68: PRINT "4 5 6"
  399.     LOCATE 28, 68: PRINT "1 2 3"
  400.     COLOR 7
  401.     LOCATE 26, 75: PRINT "Mouse"
  402.     LOCATE 27, 75: PRINT "  +  "
  403.     LOCATE 28, 75: PRINT "Wheel"
  404.     COLOR 7
  405.     LOCATE 1, 2: PRINT "- World Info -"
  406.     LOCATE 2, 2: PRINT "Particles:"; numparticleorig
  407.     LOCATE 3, 2: PRINT "Visible:"; numparticlevisible
  408.     LOCATE 5, 2: PRINT "- Player -"
  409.     LOCATE 6, 2: PRINT INT(camx); INT(camy); INT(camz)
  410.     LOCATE 8, 2: PRINT "- You see: -"
  411.     LOCATE 9, 2: PRINT vecgroupname(closestgroup)
  412.     'FOR k = 1 TO vecgroupcounter
  413.     '    IF vecgroupname(k) = "Sparks" THEN
  414.     '        LOCATE 10, 1: PRINT veccom(k, 1); veccom(k, 2); veccom(k, 3)
  415.     '        LOCATE 12, 1: PRINT SQR((camx - veccom(k, 1)) ^ 2 + (camy - veccom(k, 2)) ^ 2 + (camz - veccom(k, 3)) ^ 2)
  416.     '    END IF
  417.     'NEXT
  418.     LOCATE 1, 63: PRINT "- View Distance -"
  419.     LOCATE 2, 65: PRINT "Depth:"; -farplane(4)
  420.     LOCATE 3, 65: PRINT "Adjust via [ ]"
  421.     LOCATE 5, 63: PRINT "- Invert Mouse -"
  422.     LOCATE 6, 65: PRINT "Toggle via `i'"
  423.     LOCATE 1, 25: PRINT "Press `T' to toggle animation."
  424.     COLOR 7
  425.     LOCATE 28, 32: PRINT "You See: "; vecgroupname(closestgroup)
  426.  
  427. calculate.clippingplanes:
  428. ' Calculate normal vectors to all clipping planes.
  429. nearplane(1) = -nhat(1)
  430. nearplane(2) = -nhat(2)
  431. nearplane(3) = -nhat(3)
  432. farplane(1) = nhat(1)
  433. farplane(2) = nhat(2)
  434. farplane(3) = nhat(3)
  435. rightplane(1) = (screenheight / 2) * fovd * uhat(1) - (screenheight / 2) * (screenwidth / 2) * nhat(1)
  436. rightplane(2) = (screenheight / 2) * fovd * uhat(2) - (screenheight / 2) * (screenwidth / 2) * nhat(2)
  437. rightplane(3) = (screenheight / 2) * fovd * uhat(3) - (screenheight / 2) * (screenwidth / 2) * nhat(3)
  438. mag = SQR((rightplane(1)) ^ 2 + (rightplane(2)) ^ 2 + (rightplane(3)) ^ 2)
  439. rightplane(1) = rightplane(1) / mag
  440. rightplane(2) = rightplane(2) / mag
  441. rightplane(3) = rightplane(3) / mag
  442. leftplane(1) = -(screenheight / 2) * fovd * uhat(1) - (screenheight / 2) * (screenwidth / 2) * nhat(1)
  443. leftplane(2) = -(screenheight / 2) * fovd * uhat(2) - (screenheight / 2) * (screenwidth / 2) * nhat(2)
  444. leftplane(3) = -(screenheight / 2) * fovd * uhat(3) - (screenheight / 2) * (screenwidth / 2) * nhat(3)
  445. mag = SQR((leftplane(1)) ^ 2 + (leftplane(2)) ^ 2 + (leftplane(3)) ^ 2)
  446. leftplane(1) = leftplane(1) / mag
  447. leftplane(2) = leftplane(2) / mag
  448. leftplane(3) = leftplane(3) / mag
  449. topplane(1) = (screenwidth / 2) * fovd * vhat(1) - (screenheight / 2) * (screenwidth / 2) * nhat(1)
  450. topplane(2) = (screenwidth / 2) * fovd * vhat(2) - (screenheight / 2) * (screenwidth / 2) * nhat(2)
  451. topplane(3) = (screenwidth / 2) * fovd * vhat(3) - (screenheight / 2) * (screenwidth / 2) * nhat(3)
  452. mag = SQR((topplane(1)) ^ 2 + (topplane(2)) ^ 2 + (topplane(3)) ^ 2)
  453. topplane(1) = topplane(1) / mag
  454. topplane(2) = topplane(2) / mag
  455. topplane(3) = topplane(3) / mag
  456. bottomplane(1) = -(screenwidth / 2) * fovd * vhat(1) - (screenheight / 2) * (screenwidth / 2) * nhat(1)
  457. bottomplane(2) = -(screenwidth / 2) * fovd * vhat(2) - (screenheight / 2) * (screenwidth / 2) * nhat(2)
  458. bottomplane(3) = -(screenwidth / 2) * fovd * vhat(3) - (screenheight / 2) * (screenwidth / 2) * nhat(3)
  459. mag = SQR((bottomplane(1)) ^ 2 + (bottomplane(2)) ^ 2 + (bottomplane(3)) ^ 2)
  460. bottomplane(1) = bottomplane(1) / mag
  461. bottomplane(2) = bottomplane(2) / mag
  462. bottomplane(3) = bottomplane(3) / mag
  463.  
  464. plot.particles:
  465. FOR i = 1 TO numparticlevisible - 1
  466.     x = vecvisiblepuvs(i, 1): y = vecvisiblepuvs(i, 2) ': GOSUB convert
  467.     x1 = x: y1 = y
  468.     x = vecvisiblepuvs(i + 1, 1): y = vecvisiblepuvs(i + 1, 2) ': GOSUB convert
  469.     x2 = x: y2 = y
  470.     'IF ((x2 - x1) ^ 2 + (y2 - y1) ^ 2) < 15 ^ 2 THEN
  471.     '    LINE (x1, y1)-(x2, y2), vecvisible(i, 4) ', B
  472.     '    'PSET (x1, y1), vecvisible(i, 4)
  473.     'ELSE
  474.     '    CIRCLE (x1, y1), 1, vecvisible(i, 4)
  475.     '    'PSET (x1, y1), vecvisible(i, 4)
  476.     'END IF
  477.     xtext = (x1 + screenwidth / 2) * (80 / screenwidth)
  478.     ytext = (screenheight / 2 - y1) * (48 / screenheight) + 1
  479.     IF xtext < 1 THEN xtext = 1
  480.     IF xtext > 80 THEN xtext = 80
  481.     IF ytext < 1 THEN ytext = 1
  482.     IF ytext > 48 THEN ytext = 48
  483.     COLOR vecvisible(i, 4)
  484.     LOCATE ytext, xtext: PRINT "*"
  485.  
  486.  
  487. ' Data.
  488.  
  489. initialize.objects:
  490. pcountparticleorig = 0
  491.  
  492. gridsize = 550
  493. tilesize = 15
  494.  
  495. 'Waving Banner
  496. vecgroupcounter = vecgroupcounter + 1
  497. vgc = vecgroupcounter
  498. vecgroupname(vgc) = "Waving Banner"
  499. vecaddress(vgc, 1) = pcountparticleorig
  500. xl = -1.9: xr = 1.9: dx = .32
  501. yl = -1: yr = 1: dy = .32
  502. xl = xl * 4: xr = xr * 4: yl = yl * 4: yr = yr * 4
  503. xrange = 1 + INT((-xl + xr) / dx)
  504. yrange = 1 + INT((-yl + yr) / dy)
  505. t = 0
  506. FOR i = xl TO xr STEP dx
  507.     FOR j = yl TO yr STEP dy
  508.         pcountparticleorig = pcountparticleorig + 1
  509.         pn = pcountparticleorig
  510.         vecorig(pn, 1) = 70 + 1.25 * COS(i - 2 * t) ^ 2 - 1.25 * SIN(j - t) ^ 2
  511.         vecorig(pn, 2) = 30 + i
  512.         vecorig(pn, 3) = 40 + j
  513.         IF vecorig(pn, 1) < 70 THEN
  514.             veccolor(pn) = 11
  515.         ELSE
  516.             veccolor(pn) = 6
  517.         END IF
  518.         GOSUB calccom
  519.     NEXT
  520. vecaddress(vgc, 2) = pn
  521. GOSUB adjustcom
  522.  
  523. 'Clock Face (Rolex)
  524. vecgroupcounter = vecgroupcounter + 1
  525. vgc = vecgroupcounter
  526. vecgroupname(vgc) = "Clock Face (Rolex)"
  527. vecaddress(vgc, 1) = pcountparticleorig
  528. FOR q = 0 TO 2 * pi STEP (2 * pi / 12) / 25
  529.     FOR r = 10 TO 12 STEP .5
  530.         pcountparticleorig = pcountparticleorig + 1
  531.         pn = pcountparticleorig
  532.         vecorig(pn, 1) = 40 + r * COS(q)
  533.         vecorig(pn, 2) = -20 + r
  534.         vecorig(pn, 3) = 40 + r * SIN(q)
  535.         veccolor(pn) = 15
  536.         GOSUB calccom
  537.     NEXT
  538. vecaddress(vgc, 2) = pn
  539. GOSUB adjustcom
  540.  
  541. 'Clock Hands
  542. vecgroupcounter = vecgroupcounter + 1
  543. vgc = vecgroupcounter
  544. vecgroupname(vgc) = "Clock Hands"
  545. vecaddress(vgc, 1) = pcountparticleorig
  546. DIM hands(3, 2)
  547. hands(1, 1) = VAL(LEFT$(TIME$, 2)) * (2 * pi / 12)
  548. hands(2, 1) = VAL(MID$(TIME$, 4, 2)) * (2 * pi / 60)
  549. hands(3, 1) = VAL(RIGHT$(TIME$, 2)) * (2 * pi / 60)
  550. phase = pi / 2
  551. hands(1, 2) = 3
  552. hands(2, 2) = 5
  553. hands(3, 2) = 9
  554. FOR q = 1 TO 3
  555.     FOR r = 0 TO 5 + q STEP .1
  556.         pcountparticleorig = pcountparticleorig + 1
  557.         pn = pcountparticleorig
  558.         vecorig(pn, 1) = 40 + r * COS(hands(q, 1) + phase)
  559.         vecorig(pn, 2) = -10
  560.         vecorig(pn, 3) = 40 + r * SIN(hands(q, 1) + phase)
  561.         veccolor(pn) = hands(q, 2)
  562.         GOSUB calccom
  563.     NEXT
  564. vecaddress(vgc, 2) = pn
  565. GOSUB adjustcom
  566.  
  567. 'Dirt
  568. h = 5
  569. FOR w = 1 TO 5
  570.     FOR u = -gridsize TO gridsize STEP tilesize
  571.         FOR v = -gridsize TO gridsize STEP tilesize
  572.             vecgroupcounter = vecgroupcounter + 1
  573.             vgc = vecgroupcounter
  574.             vecgroupname(vgc) = "Dirt"
  575.             vecaddress(vgc, 1) = pcountparticleorig
  576.             FOR i = u TO u + tilesize STEP h
  577.                 FOR j = v TO v + tilesize STEP h
  578.                     IF RND > 1 - w / 5 THEN
  579.                         pcountparticleorig = pcountparticleorig + 1
  580.                         pn = pcountparticleorig
  581.                         vecorig(pn, 1) = i + RND * h - RND * h
  582.                         vecorig(pn, 2) = j + RND * h - RND * h
  583.                         vecorig(pn, 3) = -(w - 1) * 70 - RND * 70
  584.                         IF RND > .5 THEN
  585.                             veccolor(pn) = 6
  586.                         ELSE
  587.                             IF RND > .5 THEN
  588.                                 veccolor(pn) = 7
  589.                             ELSE
  590.                                 veccolor(pn) = 8
  591.                             END IF
  592.                         END IF
  593.                         GOSUB calccom
  594.                     END IF
  595.                 NEXT
  596.             NEXT
  597.             vecaddress(vgc, 2) = pn
  598.             GOSUB adjustcom
  599.         NEXT
  600.     NEXT
  601.  
  602. 'Grass and Puddles
  603. h = 2
  604. FOR u = -gridsize TO gridsize STEP tilesize
  605.     FOR v = -gridsize TO gridsize STEP tilesize
  606.         vecgroupcounter = vecgroupcounter + 1
  607.         vgc = vecgroupcounter
  608.         vecgroupname(vgc) = "Grass and Puddles"
  609.         vecaddress(vgc, 1) = pcountparticleorig
  610.         FOR i = u TO u + tilesize STEP h
  611.             FOR j = v TO v + tilesize STEP h
  612.                 pcountparticleorig = pcountparticleorig + 1
  613.                 pn = pcountparticleorig
  614.                 vecorig(pn, 1) = i + RND * h - RND * h
  615.                 vecorig(pn, 2) = j + RND * h - RND * h
  616.                 vecorig(pn, 3) = .5 + 1 * COS((i - 15) * .08) - 1 * COS((j - 6) * .12)
  617.                 IF vecorig(pn, 3) > 0 THEN
  618.                     veccolor(pn) = 2
  619.                 ELSE
  620.                     IF RND > .2 THEN
  621.                         veccolor(pn) = 9
  622.                     ELSE
  623.                         veccolor(pn) = 1
  624.                     END IF
  625.                 END IF
  626.                 GOSUB calccom
  627.             NEXT
  628.         NEXT
  629.         vecaddress(vgc, 2) = pn
  630.         GOSUB adjustcom
  631.     NEXT
  632.  
  633. 'Grave
  634. 'xloc = -90
  635. 'yloc = 0
  636. thickness = 2.5
  637. span = 20
  638. height = 30
  639. crux = 22
  640. FOR xloc = -90 TO -290 STEP -60
  641.     FOR yloc = 0 TO 180 STEP 45
  642.         FOR k = 0 TO height
  643.             vecgroupcounter = vecgroupcounter + 1
  644.             vgc = vecgroupcounter
  645.             vecgroupname(vgc) = "Grave"
  646.             vecaddress(vgc, 1) = pcountparticleorig
  647.             FOR i = -thickness TO thickness STEP thickness / 2
  648.                 FOR j = -thickness TO thickness STEP thickness / 2
  649.                     pcountparticleorig = pcountparticleorig + 1
  650.                     pn = pcountparticleorig
  651.                     vecorig(pn, 1) = xloc + i + (RND - .5) * 2
  652.                     vecorig(pn, 2) = yloc + j + (RND - .5) * 2
  653.                     vecorig(pn, 3) = k + (RND - .5) * 2
  654.                     IF RND > .5 THEN
  655.                         veccolor(pn) = 7
  656.                     ELSE
  657.                         veccolor(pn) = 8
  658.                     END IF
  659.                     GOSUB calccom
  660.                 NEXT
  661.             NEXT
  662.             vecaddress(vgc, 2) = pn
  663.             GOSUB adjustcom
  664.         NEXT
  665.         FOR j = -span / 2 TO -thickness
  666.             vecgroupcounter = vecgroupcounter + 1
  667.             vgc = vecgroupcounter
  668.             vecgroupname(vgc) = "Grave"
  669.             vecaddress(vgc, 1) = pcountparticleorig
  670.             FOR k = -thickness TO thickness STEP thickness / 2
  671.                 FOR i = -thickness TO thickness STEP thickness / 2
  672.                     pcountparticleorig = pcountparticleorig + 1
  673.                     pn = pcountparticleorig
  674.                     vecorig(pn, 1) = xloc + i + (RND - .5) * 2
  675.                     vecorig(pn, 2) = yloc + j + (RND - .5) * 2
  676.                     vecorig(pn, 3) = crux + k + (RND - .5) * 2
  677.                     IF RND > .5 THEN
  678.                         veccolor(pn) = 7
  679.                     ELSE
  680.                         veccolor(pn) = 8
  681.                     END IF
  682.                     GOSUB calccom
  683.                 NEXT
  684.             NEXT
  685.             vecaddress(vgc, 2) = pn
  686.             GOSUB adjustcom
  687.         NEXT
  688.         FOR j = thickness TO span / 2
  689.             vecgroupcounter = vecgroupcounter + 1
  690.             vgc = vecgroupcounter
  691.             vecgroupname(vgc) = "Grave"
  692.             vecaddress(vgc, 1) = pcountparticleorig
  693.             FOR k = -thickness TO thickness STEP thickness / 2
  694.                 FOR i = -thickness TO thickness STEP thickness / 2
  695.                     pcountparticleorig = pcountparticleorig + 1
  696.                     pn = pcountparticleorig
  697.                     vecorig(pn, 1) = xloc + i + (RND - .5) * 2
  698.                     vecorig(pn, 2) = yloc + j + (RND - .5) * 2
  699.                     vecorig(pn, 3) = crux + k + (RND - .5) * 2
  700.                     IF RND > .5 THEN
  701.                         veccolor(pn) = 7
  702.                     ELSE
  703.                         veccolor(pn) = 8
  704.                     END IF
  705.                     GOSUB calccom
  706.                 NEXT
  707.             NEXT
  708.             vecaddress(vgc, 2) = pn
  709.             GOSUB adjustcom
  710.         NEXT
  711.     NEXT
  712.  
  713. 'Heaven's Bottom Layer
  714. h = 2
  715. FOR u = -gridsize TO gridsize STEP tilesize
  716.     FOR v = -gridsize TO gridsize STEP tilesize
  717.         vecgroupcounter = vecgroupcounter + 1
  718.         vgc = vecgroupcounter
  719.         vecgroupname(vgc) = "Heaven's Bottom Layer"
  720.         vecaddress(vgc, 1) = pcountparticleorig
  721.         FOR i = u TO u + tilesize STEP h
  722.             FOR j = v TO v + tilesize STEP h
  723.                 pcountparticleorig = pcountparticleorig + 1
  724.                 pn = pcountparticleorig
  725.                 vecorig(pn, 1) = i + RND * h - RND * h
  726.                 vecorig(pn, 2) = j + RND * h - RND * h
  727.                 vecorig(pn, 3) = 420 - RND
  728.                 IF RND > .5 THEN
  729.                     veccolor(pn) = 3
  730.                 ELSE
  731.                     veccolor(pn) = 5
  732.                 END IF
  733.                 GOSUB calccom
  734.             NEXT
  735.         NEXT
  736.         vecaddress(vgc, 2) = pn
  737.         GOSUB adjustcom
  738.     NEXT
  739.  
  740. 'Hell Spawn
  741. FOR u = -gridsize TO gridsize STEP tilesize
  742.     FOR v = -gridsize TO gridsize STEP tilesize
  743.         vecgroupcounter = vecgroupcounter + 1
  744.         vgc = vecgroupcounter
  745.         vecgroupname(vgc) = "Hell Spawn"
  746.         vecaddress(vgc, 1) = pcountparticleorig
  747.         FOR i = u TO u + tilesize STEP tilesize / 5
  748.             FOR j = v TO v + tilesize STEP tilesize / 5
  749.                 pcountparticleorig = pcountparticleorig + 1
  750.                 pn = pcountparticleorig
  751.                 vecorig(pn, 1) = i + RND * tilesize / 5
  752.                 vecorig(pn, 2) = j + RND * tilesize / 5
  753.                 vecorig(pn, 3) = -350 - RND * 70
  754.                 IF RND > .2 THEN
  755.                     veccolor(pn) = 4
  756.                 ELSE
  757.                     veccolor(pn) = 10
  758.                 END IF
  759.                 GOSUB calccom
  760.             NEXT
  761.         NEXT
  762.         vecaddress(vgc, 2) = pn
  763.         GOSUB adjustcom
  764.     NEXT
  765.  
  766. 'Icewall East
  767. h = 2
  768. FOR u = -gridsize TO gridsize STEP tilesize
  769.     FOR v = 0 TO 70 STEP tilesize
  770.         vecgroupcounter = vecgroupcounter + 1
  771.         vgc = vecgroupcounter
  772.         vecgroupname(vgc) = "Icewall East"
  773.         vecaddress(vgc, 1) = pcountparticleorig
  774.         FOR i = u TO u + tilesize STEP h
  775.             FOR j = v TO v + tilesize STEP h
  776.                 pcountparticleorig = pcountparticleorig + 1
  777.                 pn = pcountparticleorig
  778.                 vecorig(pn, 1) = gridsize
  779.                 vecorig(pn, 2) = i + RND * h - RND * h
  780.                 vecorig(pn, 3) = j + RND * h - RND * h
  781.                 IF RND > .5 THEN
  782.                     veccolor(pn) = 15
  783.                 ELSE
  784.                     veccolor(pn) = 7
  785.                 END IF
  786.                 GOSUB calccom
  787.             NEXT
  788.         NEXT
  789.         vecaddress(vgc, 2) = pn
  790.         GOSUB adjustcom
  791.     NEXT
  792.  
  793. 'Icewall South
  794. h = 2
  795. FOR u = -gridsize TO gridsize STEP tilesize
  796.     FOR v = 0 TO 70 STEP tilesize
  797.         vecgroupcounter = vecgroupcounter + 1
  798.         vgc = vecgroupcounter
  799.         vecgroupname(vgc) = "Icewall South"
  800.         vecaddress(vgc, 1) = pcountparticleorig
  801.         FOR i = u TO u + tilesize STEP h
  802.             FOR j = v TO v + tilesize STEP h
  803.                 pcountparticleorig = pcountparticleorig + 1
  804.                 pn = pcountparticleorig
  805.                 vecorig(pn, 1) = -gridsize
  806.                 vecorig(pn, 2) = i + RND * h - RND * h
  807.                 vecorig(pn, 3) = j + RND * h - RND * h
  808.                 IF RND > .5 THEN
  809.                     veccolor(pn) = 15
  810.                 ELSE
  811.                     veccolor(pn) = 7
  812.                 END IF
  813.                 GOSUB calccom
  814.             NEXT
  815.         NEXT
  816.         vecaddress(vgc, 2) = pn
  817.         GOSUB adjustcom
  818.     NEXT
  819.  
  820. 'Icewall North
  821. h = 2
  822. FOR u = -gridsize TO gridsize STEP tilesize
  823.     FOR v = 0 TO 70 STEP tilesize
  824.         vecgroupcounter = vecgroupcounter + 1
  825.         vgc = vecgroupcounter
  826.         vecgroupname(vgc) = "Icewall North"
  827.         vecaddress(vgc, 1) = pcountparticleorig
  828.         FOR i = u TO u + tilesize STEP h
  829.             FOR j = v TO v + tilesize STEP h
  830.                 pcountparticleorig = pcountparticleorig + 1
  831.                 pn = pcountparticleorig
  832.                 vecorig(pn, 1) = i + RND * h - RND * h
  833.                 vecorig(pn, 2) = gridsize
  834.                 vecorig(pn, 3) = j + RND * h - RND * h
  835.                 IF RND > .5 THEN
  836.                     veccolor(pn) = 15
  837.                 ELSE
  838.                     veccolor(pn) = 7
  839.                 END IF
  840.                 GOSUB calccom
  841.             NEXT
  842.         NEXT
  843.         vecaddress(vgc, 2) = pn
  844.         GOSUB adjustcom
  845.     NEXT
  846.  
  847. 'Icewall West
  848. h = 2
  849. FOR u = -gridsize TO gridsize STEP tilesize
  850.     FOR v = 0 TO 70 STEP tilesize
  851.         vecgroupcounter = vecgroupcounter + 1
  852.         vgc = vecgroupcounter
  853.         vecgroupname(vgc) = "Icewall West"
  854.         vecaddress(vgc, 1) = pcountparticleorig
  855.         FOR i = u TO u + tilesize STEP h
  856.             FOR j = v TO v + tilesize STEP h
  857.                 pcountparticleorig = pcountparticleorig + 1
  858.                 pn = pcountparticleorig
  859.                 vecorig(pn, 1) = i + RND * h - RND * h
  860.                 vecorig(pn, 2) = -gridsize
  861.                 vecorig(pn, 3) = j + RND * h - RND * h
  862.                 IF RND > .5 THEN
  863.                     veccolor(pn) = 15
  864.                 ELSE
  865.                     veccolor(pn) = 7
  866.                 END IF
  867.                 GOSUB calccom
  868.             NEXT
  869.         NEXT
  870.         vecaddress(vgc, 2) = pn
  871.         GOSUB adjustcom
  872.     NEXT
  873.  
  874. 'Lake of Fire
  875. h = 2
  876. FOR u = -gridsize TO gridsize STEP tilesize
  877.     FOR v = -gridsize TO gridsize STEP tilesize
  878.         vecgroupcounter = vecgroupcounter + 1
  879.         vgc = vecgroupcounter
  880.         vecgroupname(vgc) = "Lake of Fire"
  881.         vecaddress(vgc, 1) = pcountparticleorig
  882.         FOR i = u TO u + tilesize STEP h
  883.             FOR j = v TO v + tilesize STEP h
  884.                 pcountparticleorig = pcountparticleorig + 1
  885.                 pn = pcountparticleorig
  886.                 vecorig(pn, 1) = i + RND * h - RND * h
  887.                 vecorig(pn, 2) = j + RND * h - RND * h
  888.                 vecorig(pn, 3) = -350 - 70 - RND
  889.                 IF RND > .2 THEN
  890.                     veccolor(pn) = 4
  891.                 ELSE
  892.                     veccolor(pn) = 11
  893.                 END IF
  894.                 GOSUB calccom
  895.             NEXT
  896.         NEXT
  897.         vecaddress(vgc, 2) = pn
  898.         GOSUB adjustcom
  899.     NEXT
  900.  
  901. 'Megalith
  902. ctrx = -90
  903. ctry = -320
  904. ctrz = 4
  905. w = 8
  906. h = 256
  907. dens = 100
  908. FOR k = 1 TO h STEP w
  909.     FOR i = -h / 20 + k / 20 TO h / 20 - k / 20 STEP w
  910.         FOR j = -h / 20 + k / 20 TO h / 20 - k / 20 STEP w
  911.             vecgroupcounter = vecgroupcounter + 1
  912.             vgc = vecgroupcounter
  913.             vecgroupname(vgc) = "Megalith"
  914.             vecaddress(vgc, 1) = pcountparticleorig
  915.             FOR q = 1 TO dens
  916.                 pcountparticleorig = pcountparticleorig + 1
  917.                 pn = pcountparticleorig
  918.                 vecorig(pn, 1) = ctrx + i + (RND - .5) * w
  919.                 vecorig(pn, 2) = ctry + j + (RND - .5) * w
  920.                 vecorig(pn, 3) = ctrz + k + (RND - .5) * w
  921.                 IF RND > .5 THEN
  922.                     veccolor(pn) = 11
  923.                 ELSE
  924.                     veccolor(pn) = 7
  925.                 END IF
  926.                 GOSUB calccom
  927.             NEXT
  928.             vecaddress(vgc, 2) = pn
  929.             GOSUB adjustcom
  930.         NEXT
  931.     NEXT
  932.  
  933. 'Moon
  934. vecgroupcounter = vecgroupcounter + 1
  935. vgc = vecgroupcounter
  936. vecgroupname(vgc) = "Moon"
  937. vecaddress(vgc, 1) = pcountparticleorig
  938. radius = 4
  939. au = 60
  940. dx = (2 * pi / radius) * .05
  941. dy = (2 * pi / radius) * .05
  942. xl = 0: xr = 2 * pi
  943. yl = 0: yr = pi
  944. xrange = 1 + INT((-xl + xr) / dx)
  945. yrange = 1 + INT((-yl + yr) / dy)
  946. FOR i = 1 TO xrange
  947.     FOR j = 1 TO yrange
  948.         pcountparticleorig = pcountparticleorig + 1
  949.         pn = pcountparticleorig
  950.         theta = i * dx - dx
  951.         phi = j * dy - dy
  952.         vecorig(pn, 1) = au + radius * SIN(phi) * COS(theta)
  953.         vecorig(pn, 2) = radius * SIN(phi) * SIN(theta)
  954.         vecorig(pn, 3) = 90 + radius * COS(phi)
  955.         IF RND > .5 THEN
  956.             veccolor(pn) = 7
  957.         ELSE
  958.             veccolor(pn) = 8
  959.         END IF
  960.         GOSUB calccom
  961.     NEXT
  962. vecaddress(vgc, 2) = pn
  963. GOSUB adjustcom
  964.  
  965. 'Rain
  966. FOR u = -gridsize TO gridsize STEP tilesize
  967.     FOR v = -gridsize TO gridsize STEP tilesize
  968.         vecgroupcounter = vecgroupcounter + 1
  969.         vgc = vecgroupcounter
  970.         vecgroupname(vgc) = "Rain"
  971.         vecaddress(vgc, 1) = pcountparticleorig
  972.         FOR i = u TO u + tilesize STEP tilesize '/ 3
  973.             FOR j = v TO v + tilesize STEP tilesize '/ 3
  974.                 pcountparticleorig = pcountparticleorig + 1
  975.                 pn = pcountparticleorig
  976.                 vecorig(pn, 1) = i + RND * tilesize
  977.                 vecorig(pn, 2) = j + RND * tilesize
  978.                 vecorig(pn, 3) = RND * 70
  979.                 IF RND > .66 THEN
  980.                     veccolor(pn) = 9
  981.                 ELSE
  982.                     veccolor(pn) = 7
  983.                 END IF
  984.                 GOSUB calccom
  985.             NEXT
  986.         NEXT
  987.         vecaddress(vgc, 2) = pn
  988.         GOSUB adjustcom
  989.     NEXT
  990.  
  991. 'Pyramid
  992. ctrx = -90
  993. ctry = -120
  994. ctrz = 4
  995. w = 8
  996. h = 56
  997. dens = 50
  998. FOR k = 1 TO h STEP w
  999.     FOR i = -h / 2 + k / 2 TO h / 2 - k / 2 STEP w
  1000.         FOR j = -h / 2 + k / 2 TO h / 2 - k / 2 STEP w
  1001.             vecgroupcounter = vecgroupcounter + 1
  1002.             vgc = vecgroupcounter
  1003.             vecgroupname(vgc) = "Pyramid"
  1004.             vecaddress(vgc, 1) = pcountparticleorig
  1005.             FOR q = 1 TO dens
  1006.                 pcountparticleorig = pcountparticleorig + 1
  1007.                 pn = pcountparticleorig
  1008.                 vecorig(pn, 1) = ctrx + i + (RND - .5) * w
  1009.                 vecorig(pn, 2) = ctry + j + (RND - .5) * w
  1010.                 vecorig(pn, 3) = ctrz + k + (RND - .5) * w
  1011.                 IF RND > .5 THEN
  1012.                     veccolor(pn) = 6
  1013.                 ELSE
  1014.                     veccolor(pn) = 12
  1015.                 END IF
  1016.                 GOSUB calccom
  1017.             NEXT
  1018.             vecaddress(vgc, 2) = pn
  1019.             GOSUB adjustcom
  1020.         NEXT
  1021.     NEXT
  1022.  
  1023. 'Sky
  1024. h = 2
  1025. FOR u = -gridsize TO gridsize STEP tilesize
  1026.     FOR v = -gridsize TO gridsize STEP tilesize
  1027.         vecgroupcounter = vecgroupcounter + 1
  1028.         vgc = vecgroupcounter
  1029.         vecgroupname(vgc) = "Sky"
  1030.         vecaddress(vgc, 1) = pcountparticleorig
  1031.         FOR i = u TO u + tilesize STEP h
  1032.             FOR j = v TO v + tilesize STEP h
  1033.                 pcountparticleorig = pcountparticleorig + 1
  1034.                 pn = pcountparticleorig
  1035.                 vecorig(pn, 1) = i + RND * h - RND * h
  1036.                 vecorig(pn, 2) = j + RND * h - RND * h
  1037.                 vecorig(pn, 3) = 70 + RND * h - RND * h
  1038.                 IF RND > .5 THEN
  1039.                     veccolor(pn) = 9
  1040.                 ELSE
  1041.                     veccolor(pn) = 15
  1042.                 END IF
  1043.                 GOSUB calccom
  1044.             NEXT
  1045.         NEXT
  1046.         vecaddress(vgc, 2) = pn
  1047.         GOSUB adjustcom
  1048.     NEXT
  1049.  
  1050. 'Snake?
  1051. vecgroupcounter = vecgroupcounter + 1
  1052. vgc = vecgroupcounter
  1053. vecgroupname(vgc) = "Snake?"
  1054. vecaddress(vgc, 1) = pcountparticleorig
  1055. FOR i = -pi TO pi STEP .005
  1056.     pcountparticleorig = pcountparticleorig + 1
  1057.     pn = pcountparticleorig
  1058.     vecorig(pn, 1) = -10 + 5 * COS(i)
  1059.     vecorig(pn, 2) = -20 + 5 * SIN(i)
  1060.     vecorig(pn, 3) = 25 - 3 * COS(6 * i) * SIN(3 * i)
  1061.     veccolor(pn) = 12
  1062.     GOSUB calccom
  1063. vecaddress(vgc, 2) = pn
  1064. GOSUB adjustcom
  1065.  
  1066. 'Sparks
  1067. u = 0
  1068. v = 0
  1069. vecgroupcounter = vecgroupcounter + 1
  1070. vgc = vecgroupcounter
  1071. vecgroupname(vgc) = "Sparks"
  1072. vecaddress(vgc, 1) = pcountparticleorig
  1073. FOR i = 1 TO 300
  1074.     pcountparticleorig = pcountparticleorig + 1
  1075.     pn = pcountparticleorig
  1076.     vecorig(pn, 1) = RND - .5
  1077.     vecorig(pn, 2) = RND - .5
  1078.     vecorig(pn, 3) = 20 + RND - .5
  1079.     vecorigvel(pn, 1) = 8 * (RND - .5)
  1080.     vecorigvel(pn, 2) = 8 * (RND - .5)
  1081.     vecorigvel(pn, 3) = 20 * RND
  1082.     vecorigacc(pn, 1) = 0
  1083.     vecorigacc(pn, 2) = 0
  1084.     vecorigacc(pn, 3) = -40
  1085.     veccolor(pn) = INT(RND * 14) + 1
  1086.     GOSUB calccom
  1087. vecaddress(vgc, 2) = pn
  1088. GOSUB adjustcom
  1089.  
  1090. 'Stars
  1091. h = 5
  1092. FOR w = 1 TO 5
  1093.     FOR u = -gridsize TO gridsize STEP tilesize
  1094.         FOR v = -gridsize TO gridsize STEP tilesize
  1095.             vecgroupcounter = vecgroupcounter + 1
  1096.             vgc = vecgroupcounter
  1097.             vecgroupname(vgc) = "Stars"
  1098.             vecaddress(vgc, 1) = pcountparticleorig
  1099.             FOR i = u TO u + tilesize STEP h
  1100.                 FOR j = v TO v + tilesize STEP h
  1101.                     IF RND > 1 - w / 5 THEN
  1102.                         pcountparticleorig = pcountparticleorig + 1
  1103.                         pn = pcountparticleorig
  1104.                         vecorig(pn, 1) = i + RND * h - RND * h
  1105.                         vecorig(pn, 2) = j + RND * h - RND * h
  1106.                         vecorig(pn, 3) = w * 70 + RND * 70
  1107.                         IF RND > .5 THEN
  1108.                             veccolor(pn) = 15
  1109.                         ELSE
  1110.                             IF RND > .5 THEN
  1111.                                 veccolor(pn) = 7
  1112.                             ELSE
  1113.                                 veccolor(pn) = 8
  1114.                             END IF
  1115.                         END IF
  1116.                         GOSUB calccom
  1117.                     END IF
  1118.                 NEXT
  1119.             NEXT
  1120.             vecaddress(vgc, 2) = pn
  1121.             GOSUB adjustcom
  1122.         NEXT
  1123.     NEXT
  1124.  
  1125. 'Sun
  1126. radius = 10
  1127. dx = .0628
  1128. dy = .0628
  1129. xl = 0: xr = 2 * pi
  1130. yl = 0: yr = pi
  1131. xrange = 1 + INT((-xl + xr) / dx)
  1132. yrange = 1 + INT((-yl + yr) / dy)
  1133. FOR i = 1 TO xrange STEP 10
  1134.     FOR j = 1 TO yrange STEP 10
  1135.         vecgroupcounter = vecgroupcounter + 1
  1136.         vgc = vecgroupcounter
  1137.         vecgroupname(vgc) = "Sun"
  1138.         vecaddress(vgc, 1) = pcountparticleorig
  1139.         FOR u = i TO i + 10 STEP 1
  1140.             FOR v = j TO j + 10 STEP 1
  1141.                 pcountparticleorig = pcountparticleorig + 1
  1142.                 pn = pcountparticleorig
  1143.                 theta = u * dx - dx
  1144.                 phi = v * dy - dy
  1145.                 vecorig(pn, 1) = radius * SIN(phi) * COS(theta)
  1146.                 vecorig(pn, 2) = radius * SIN(phi) * SIN(theta)
  1147.                 vecorig(pn, 3) = 90 + radius * COS(phi)
  1148.                 veccolor(pn) = 14
  1149.                 GOSUB calccom
  1150.             NEXT
  1151.         NEXT
  1152.         vecaddress(vgc, 2) = pn
  1153.         GOSUB adjustcom
  1154.     NEXT
  1155.  
  1156. 'UFO!!!
  1157. vecgroupcounter = vecgroupcounter + 1
  1158. vgc = vecgroupcounter
  1159. vecgroupname(vgc) = "UFO!!!"
  1160. vecaddress(vgc, 1) = pcountparticleorig
  1161. FOR q = 0 TO 2 * pi STEP (2 * pi / 12) / 25
  1162.     FOR r = 10 TO 12 STEP .5
  1163.         pcountparticleorig = pcountparticleorig + 1
  1164.         pn = pcountparticleorig
  1165.         vecorig(pn, 1) = -90 + r * COS(q)
  1166.         vecorig(pn, 2) = -120 + r * SIN(q)
  1167.         vecorig(pn, 3) = 100 + r - 12
  1168.         veccolor(pn) = 13
  1169.         GOSUB calccom
  1170.     NEXT
  1171.     FOR r = 12 TO 10 STEP -.5
  1172.         pcountparticleorig = pcountparticleorig + 1
  1173.         pn = pcountparticleorig
  1174.         vecorig(pn, 1) = -90 + r * COS(q)
  1175.         vecorig(pn, 2) = -120 + r * SIN(q)
  1176.         vecorig(pn, 3) = 100 - r + 12
  1177.         veccolor(pn) = 12
  1178.         GOSUB calccom
  1179.     NEXT
  1180. r = 5
  1181. h = 30
  1182. FOR w = 1 TO 400
  1183.     xx = (RND - .5) * 2 * r
  1184.     yy = (RND - .5) * 2 * r
  1185.     IF xx ^ 2 + yy ^ 2 < r ^ 2 THEN
  1186.         pcountparticleorig = pcountparticleorig + 1
  1187.         pn = pcountparticleorig
  1188.         vecorig(pn, 1) = -90 + xx
  1189.         vecorig(pn, 2) = -120 + yy
  1190.         vecorig(pn, 3) = 100 - RND * h
  1191.         IF RND > .5 THEN
  1192.             veccolor(pn) = 3
  1193.         ELSE
  1194.             veccolor(pn) = 11
  1195.         END IF
  1196.         GOSUB calccom
  1197.     END IF
  1198. vecaddress(vgc, 2) = pn
  1199. GOSUB adjustcom
  1200.  
  1201. 'Waves or Particles? (1)
  1202. FOR i = 1 TO 5 STEP 1
  1203.     FOR k = 1 TO 5 STEP 1
  1204.         vecgroupcounter = vecgroupcounter + 1
  1205.         vgc = vecgroupcounter
  1206.         vecgroupname(vgc) = "Particles or Waves?"
  1207.         vecaddress(vgc, 1) = pcountparticleorig
  1208.         FOR u = i TO i + 1 STEP .05
  1209.             FOR v = k TO k + 1 STEP .05
  1210.                 pcountparticleorig = pcountparticleorig + 1
  1211.                 pn = pcountparticleorig
  1212.                 vecorig(pn, 1) = 70 + 7 * u
  1213.                 vecorig(pn, 2) = 80 + 1 * COS((u ^ 2 - v ^ 2))
  1214.                 vecorig(pn, 3) = 10 + 7 * v
  1215.                 IF vecorig(pn, 2) < 80 THEN
  1216.                     veccolor(pn) = 2
  1217.                 ELSE
  1218.                     veccolor(pn) = 1
  1219.                 END IF
  1220.                 GOSUB calccom
  1221.             NEXT
  1222.         NEXT
  1223.         vecaddress(vgc, 2) = pn
  1224.         GOSUB adjustcom
  1225.     NEXT
  1226.  
  1227. 'Waves or Particles? (2)
  1228. FOR i = 1 TO 5 STEP 1
  1229.     FOR k = 1 TO 5 STEP 1
  1230.         vecgroupcounter = vecgroupcounter + 1
  1231.         vgc = vecgroupcounter
  1232.         vecgroupname(vgc) = "Waves or Particles?"
  1233.         vecaddress(vgc, 1) = pcountparticleorig
  1234.         FOR u = i TO i + 1 STEP .05
  1235.             FOR v = k TO k + 1 STEP .05
  1236.                 pcountparticleorig = pcountparticleorig + 1
  1237.                 pn = pcountparticleorig
  1238.                 vecorig(pn, 1) = -7 * u
  1239.                 vecorig(pn, 2) = 80 + 1 * COS(2 * ((u - 7) ^ 2 - (v - 5) ^ 2))
  1240.                 vecorig(pn, 3) = 10 + 7 * v
  1241.                 IF vecorig(pn, 2) < 80 THEN
  1242.                     veccolor(pn) = 13
  1243.                 ELSE
  1244.                     veccolor(pn) = 4
  1245.                 END IF
  1246.                 GOSUB calccom
  1247.             NEXT
  1248.         NEXT
  1249.         vecaddress(vgc, 2) = pn
  1250.         GOSUB adjustcom
  1251.     NEXT
  1252.  
  1253.  
  1254. 'File
  1255.     DO WHILE NOT EOF(1)
  1256.         INPUT #1, xx, yy, zz, co
  1257.         regularpoint = 1
  1258.         IF xx = -999999 AND yy = -999999 AND zz = -999999 AND co = -999999 THEN
  1259.             regularpoint = 0
  1260.             INPUT #1, n$
  1261.             vecgroupcounter = vecgroupcounter + 1
  1262.             vgc = vecgroupcounter
  1263.             vecgroupname(vgc) = n$
  1264.             vecaddress(vgc, 1) = pcountparticleorig
  1265.         END IF
  1266.         IF xx = -888888 AND yy = -888888 AND zz = -888888 AND co = -888888 THEN
  1267.             regularpoint = 0
  1268.             vecaddress(vgc, 2) = pn
  1269.             GOSUB adjustcom
  1270.         END IF
  1271.         IF regularpoint = 1 THEN
  1272.             pcountparticleorig = pcountparticleorig + 1
  1273.             pn = pcountparticleorig
  1274.             vecorig(pn, 1) = xx
  1275.             vecorig(pn, 2) = yy
  1276.             vecorig(pn, 3) = zz
  1277.             veccolor(pn) = co
  1278.             GOSUB calccom
  1279.         END IF
  1280.     LOOP
  1281.  
  1282.  
  1283. timeanimate:
  1284. timestep = .001
  1285. timevar = timevar + timestep
  1286. IF timevar > 10 ^ 6 THEN timevar = 0
  1287.  
  1288. IF vecgroupname(k) = "Clock Hands" THEN
  1289.     pn = vecaddress(k, 1)
  1290.     hands(1, 1) = VAL(LEFT$(TIME$, 2)) * (2 * pi / 12)
  1291.     hands(2, 1) = VAL(MID$(TIME$, 4, 2)) * (2 * pi / 60)
  1292.     hands(3, 1) = VAL(RIGHT$(TIME$, 2)) * (2 * pi / 60)
  1293.     phase = pi / 2
  1294.     FOR q = 1 TO 3
  1295.         FOR r = 0 TO 5 + q STEP .1
  1296.             pn = pn + 1
  1297.             vecorig(pn, 1) = 40 + r * COS(hands(q, 1) + phase)
  1298.             vecorig(pn, 2) = -10
  1299.             vecorig(pn, 3) = 40 + r * SIN(hands(q, 1) + phase)
  1300.         NEXT
  1301.     NEXT
  1302. IF vecgroupname(k) = "Waving Banner" THEN
  1303.     pn = vecaddress(k, 1)
  1304.     t = timevar / 50
  1305.     xl = -1.9: xr = 1.9: dx = .32
  1306.     yl = -1: yr = 1: dy = .32
  1307.     xl = xl * 4: xr = xr * 4: yl = yl * 4: yr = yr * 4
  1308.     FOR i = xl TO xr STEP dx
  1309.         FOR j = yl TO yr STEP dy
  1310.             pn = pn + 1
  1311.             vecorig(pn, 1) = 70 + 1.25 * COS(i - 2 * t) ^ 2 - 1.25 * SIN(j - t) ^ 2
  1312.             vecorig(pn, 2) = 30 + i
  1313.             vecorig(pn, 3) = 40 + j
  1314.             IF vecorig(pn, 1) < 70 THEN
  1315.                 veccolor(pn) = 11
  1316.             ELSE
  1317.                 veccolor(pn) = 6
  1318.             END IF
  1319.         NEXT
  1320.     NEXT
  1321. IF vecgroupname(k) = "Hell Spawn" THEN
  1322.     FOR i = vecaddress(k, 1) + 1 TO vecaddress(k, 2)
  1323.         vecorig(i, 3) = vecorig(i, 3) + .3
  1324.         IF vecorig(i, 3) > -350 THEN vecorig(i, 3) = -350 - 70
  1325.     NEXT
  1326. IF vecgroupname(k) = "Moon" THEN
  1327.     t = timevar * .000001
  1328.     FOR i = vecaddress(k, 1) + 1 TO vecaddress(k, 2)
  1329.         xx = vecorig(i, 1)
  1330.         yy = vecorig(i, 2)
  1331.         vecorig(i, 1) = xx * COS(t) - yy * SIN(t)
  1332.         vecorig(i, 2) = xx * SIN(t) + yy * COS(t)
  1333.         GOSUB calccom
  1334.     NEXT
  1335.     GOSUB adjustcom
  1336. IF vecgroupname(k) = "Rain" THEN
  1337.     FOR i = vecaddress(k, 1) + 1 TO vecaddress(k, 2)
  1338.         vecorig(i, 3) = vecorig(i, 3) - .3
  1339.         IF vecorig(i, 3) < 0 THEN vecorig(i, 3) = 70
  1340.     NEXT
  1341. IF vecgroupname(k) = "Snake?" THEN
  1342.     pn = vecaddress(k, 1) + 1
  1343.     t = timevar * .1
  1344.     FOR i = -pi TO pi STEP .005
  1345.         vecorig(pn, 1) = -10 + 5 * COS(i + t)
  1346.         vecorig(pn, 2) = -20 + 5 * SIN(i + t)
  1347.         vecorig(pn, 3) = 25 - 3 * COS(6 * i + t) * SIN(3 * i + t)
  1348.         pn = pn + 1
  1349.     NEXT
  1350. IF vecgroupname(k) = "Sparks" THEN
  1351.     vgc = k
  1352.     dt = timestep * 100
  1353.     FOR pn = vecaddress(vgc, 1) + 1 TO vecaddress(vgc, 2)
  1354.         vecorigvel(pn, 1) = vecorigvel(pn, 1) + vecorigacc(pn, 1) * timestep
  1355.         vecorigvel(pn, 2) = vecorigvel(pn, 2) + vecorigacc(pn, 2) * dt
  1356.         vecorigvel(pn, 3) = vecorigvel(pn, 3) + vecorigacc(pn, 3) * dt
  1357.         vecorig(pn, 1) = vecorig(pn, 1) + vecorigvel(pn, 1) * dt
  1358.         vecorig(pn, 2) = vecorig(pn, 2) + vecorigvel(pn, 2) * dt
  1359.         vecorig(pn, 3) = vecorig(pn, 3) + vecorigvel(pn, 3) * dt
  1360.         IF vecorig(pn, 3) < 0 THEN
  1361.             vecorig(pn, 3) = 0
  1362.             vecorigvel(pn, 1) = vecorigvel(pn, 1) * .75
  1363.             vecorigvel(pn, 2) = vecorigvel(pn, 2) * .75
  1364.             vecorigvel(pn, 3) = -vecorigvel(pn, 3) * .5
  1365.         END IF
  1366.         GOSUB calccom
  1367.     NEXT
  1368.     GOSUB adjustcom
  1369. IF vecgroupname(k) = "UFO!!!" THEN
  1370.     vgc = k
  1371.     dt = timestep
  1372.     FOR pn = vecaddress(vgc, 1) + 1 TO vecaddress(vgc, 2)
  1373.         xx = vecorig(pn, 1) - 150
  1374.         yy = vecorig(pn, 2) - 150
  1375.         vecorig(pn, 1) = xx * COS(dt) - yy * SIN(dt) + 150
  1376.         vecorig(pn, 2) = xx * SIN(dt) + yy * COS(dt) + 150
  1377.         GOSUB calccom
  1378.     NEXT
  1379.     GOSUB adjustcom
  1380.  
  1381. calccom:
  1382. veccom(vgc, 1) = vecorig(pn, 1) + veccom(vgc, 1)
  1383. veccom(vgc, 2) = vecorig(pn, 2) + veccom(vgc, 2)
  1384. veccom(vgc, 3) = vecorig(pn, 3) + veccom(vgc, 3)
  1385.  
  1386. adjustcom:
  1387. veccom(vgc, 1) = veccom(vgc, 1) / (vecaddress(vgc, 2) - vecaddress(vgc, 1))
  1388. veccom(vgc, 2) = veccom(vgc, 2) / (vecaddress(vgc, 2) - vecaddress(vgc, 1))
  1389. veccom(vgc, 3) = veccom(vgc, 3) / (vecaddress(vgc, 2) - vecaddress(vgc, 1))
  1390.  

EDIT

Decided to attach a sketch of what's going on mathematically. Don't mind the sloppy handwriting.
main idea picture.jpg
* main idea picture.jpg (Filesize: 836.94 KB, Dimensions: 3507x2550, Views: 202)
« Last Edit: February 02, 2019, 08:30:31 pm by STxAxTIC »
You're not done when it works, you're done when it's right.

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Sanctum: Open world 3D engine using CIRCLE and LINE
« Reply #4 on: February 02, 2019, 12:58:16 pm »
This is the strangest word processor I've ever tried.

Pete :D
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline Richard Frost

  • Seasoned Forum Regular
  • Posts: 316
  • Needle nardle noo. - Peter Sellers
    • View Profile
Re: Sanctum: Open world 3D engine using CIRCLE and LINE
« Reply #5 on: February 02, 2019, 04:39:59 pm »
Your long variable names - do you actually type them in, or use short ones and do a mass search/replace
once the program is done? 

p.s. I am a zombie.  I will eat your brain to acquire 3D skills.  Beware of man with salt shaker.

It works better if you plug it in.

Offline Richard Frost

  • Seasoned Forum Regular
  • Posts: 316
  • Needle nardle noo. - Peter Sellers
    • View Profile
Re: Sanctum: Open world 3D engine using CIRCLE and LINE
« Reply #6 on: February 02, 2019, 04:49:35 pm »
Hardware for the 3D graphics engine...
circuit_diagram.png
* circuit_diagram.png (Filesize: 133.69 KB, Dimensions: 740x952, Views: 185)
It works better if you plug it in.

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Sanctum: Open world 3D engine using CIRCLE and LINE
« Reply #7 on: February 02, 2019, 05:02:20 pm »
Sup Richard -

I type the long variable names typically. I'm all about code that doesn't need many comments - the code *is* the commentary when you name things right. Programmers convince themselves that they power-type all day and need all kinds of "++" esque shortcuts, but that's a myth. Clear code is better than unnecessarily tight code 100% of the time.

Nice hardware pic, haha. Now this site has 3 xkcd readers that I know about...
You're not done when it works, you're done when it's right.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Sanctum: Open world 3D engine using CIRCLE and LINE
« Reply #8 on: February 03, 2019, 04:21:34 am »
Richard Frost,

The beautiful connection of the MAA 555, which has Satanic designation MAA 666 :-D, that bat in the circuit and those coils and diodes, chachacha, yeah, that's a really good scheme. The transistor with two emitters :-D, that's fine. Thanks for this beautiful scheme :-D On one side cooled by water, on the other side powered by the sun :-D That's really great!

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Sanctum: Open world 3D engine using CIRCLE and LINE
« Reply #9 on: February 03, 2019, 04:43:35 pm »
I got burned with that circuit many times, but then I discovered the secret... stop using Holy Water.

Hey Bill, check out what this guy posted! https://www.tapatalk.com/groups/qbasic/viewtopic.php?f=648955&t=39427

Pete :D
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Sanctum: Open world 3D engine using CIRCLE and LINE
« Reply #10 on: February 03, 2019, 08:19:22 pm »
Aw, publicity! Where are my star-shaped sunglasses?

In exchange for this lovely cross-pollination of ideas, I will start hitting that forum way more often! (It's actually really encouraging to know that not *all* QB64 discussion happens exclusively here. That would be sad.)
You're not done when it works, you're done when it's right.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Sanctum: Open world 3D engine using CIRCLE and LINE
« Reply #11 on: February 03, 2019, 09:17:57 pm »
I have to say the video clip demo of this is much better than my little exploration.

Following Richard Frost idea to include music with Sierpinski Circled, I found all sorts of stuff that would go with the clip for Sanctum.

It would be cool if you could change the music according to the directions you go in space travel.

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Sanctum: Open world 3D engine using CIRCLE and LINE
« Reply #12 on: February 04, 2019, 02:11:46 am »
Aw, publicity! Where are my star-shaped sunglasses?

In exchange for this lovely cross-pollination of ideas, I will start hitting that forum way more often! (It's actually really encouraging to know that not *all* QB64 discussion happens exclusively here. That would be sad.)

I added user name from the old N54 QB Forum: STxAxTIK, in the posting group. You should be able to post when you want by logging in with your old Network54 password. If you forgot that password, just re-register and I will add your new user name to the posting group. I miss the old boards but the video embedding and some other features are a nice addition.

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Sanctum: Open world 3D engine using CIRCLE and LINE
« Reply #13 on: February 04, 2019, 06:20:25 am »
Hello all, made a major update to the mechanism (data-wise, not the geometry) behind the Sanctum engine. For those who follow this...

The question that motivated the update is: How do you make changes to any element in the 3D world while the program is running? Thinking about this for a second, certain elements in games tend be immutable. You can try blowing up the walls in Doom, CounterStrike, or Tetris all day long, and it'll never happen - the engine just treats the environment differently than the stuff you can move around... but then along came Minecraft, which broke that barrier. So in that same spirit, I introduce a new direction for this project, and at this point I realize I should have waited and named this "PixelCraft". You can now create and destroy little blocks to build stuff. Very primitive for now, but it works.

The "major update" is how the particles are stored. When you boot the program as of now, the world is made of several million particles. How then, do we create and delete select chunks of the environment without befuddling arrays? With so many millions, we can't waste any time... So it is Linked List to the rescue. (That's what all the "pointer/lagger" stuff in there means.)

The code is updated at the top post. The "level.txt" attachment has also been replaced. Be sure to grab it too.

Instructions for creating and destroying blocks will be on screen. Its still rudimentary.
« Last Edit: February 04, 2019, 06:33:46 am by STxAxTIC »
You're not done when it works, you're done when it's right.

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Sanctum: Open world 3D engine using CIRCLE and LINE
« Reply #14 on: February 04, 2019, 10:29:11 am »
Destroying blocks? As in we can blow stuff up? Now you've got my attention.

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/