Author Topic: On trigless starfields: remember Sanctum?  (Read 363 times)

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 692
  • Savage.
    • Domum
On trigless starfields: remember Sanctum?
« on: August 11, 2019, 11:26:58 AM »
Hey all,

As a mere coincidence, I was working on streamlining the 3D world explorer from a few months ago when the starfield subject came up. For those not familiar with this work, below is a full-fledged 3D vector engine that, due to a cool breakthrough involving linked lists, has the flexibility to backbone any 3D engine. For now it stays (almost) strictly in the QB45 domain - no textures, GL commands, libraries - basically no cheating whatsoever. The math is done (as you may have guessed) with vectors, and avoids trig completely. (The 3D calculations involve zero trig, but some objects in the world are best made using trig functions and these are completely nonessential.)

I'm still deciding what the endgame of this project will be, but I figure a refresher post wouldn't hurt. The mouse is disabled for now. Suggested hand placement is left hand on "WSAD", and right hand on numeric keypad (hybrid gamer setup)... But you can do some stuff with the arrow keys too...

For an instant starfield feeling, load the world and press "e" to rise steadily. Once you break through the sky, press "w" to zoom through the stars. Use the keypad etc to move around in any direction. Discover heaven's bottom layer, discover hell, find the pyramid, the megalith, and so on.

Kinda like minecraft, call it pixelcraft, you can press "b" to create blocks. Press "n" to destroy the nearest group. Press "k" to make it vanish.

You only need one extra file, a list of colors (attached).

Code: QB64: [Select]
  1. '$EXEICON:'sanctum.ico'
  2. REM $INCLUDE:'Color32.BI'
  3.  
  4. ' Constants.
  5. pi = 3.1415926536
  6. ee = 2.7182818285
  7.  
  8. ' Scale.
  9. DIM bignumber AS LONG
  10. bignumber = 3000000
  11.  
  12. ' Video.
  13. 'SCREEN _NEWIMAGE(640, 480, 32)
  14. SCREEN _NEWIMAGE(800, 600, 32)
  15. 'SCREEN _NEWIMAGE(1024, 768, 32)
  16. screenwidth = _WIDTH
  17. screenheight = _HEIGHT
  18.  
  19. ' Camera orientation vectors.
  20. DIM uhat(3), vhat(3), nhat(3)
  21.  
  22. ' Basis vectors defined in three-space.
  23. DIM xhat(3), yhat(3), zhat(3)
  24. xhat(1) = 1: xhat(2) = 0: xhat(3) = 0
  25. yhat(1) = 0: yhat(2) = 1: yhat(3) = 0
  26. zhat(1) = 0: zhat(2) = 0: zhat(3) = 1
  27.  
  28. ' Group structure.
  29. TYPE VectorGroupElement
  30.     Identity AS LONG
  31.     Pointer AS LONG
  32.     Lagger AS LONG
  33.     FirstVector AS LONG
  34.     LastVector AS LONG
  35.     GroupName AS STRING * 50
  36.     Visible AS INTEGER
  37.     ForceAnimate AS INTEGER
  38.     COMFixed AS INTEGER
  39.     COMx AS SINGLE ' Center of mass
  40.     COMy AS SINGLE
  41.     COMz AS SINGLE
  42.     ROTx AS SINGLE ' Center of rotation
  43.     ROTy AS SINGLE
  44.     ROTz AS SINGLE
  45.     REVx AS SINGLE ' Revolution speed
  46.     REVy AS SINGLE
  47.     REVz AS SINGLE
  48.     DIMx AS SINGLE ' Maximum volume
  49.     DIMy AS SINGLE
  50.     DIMz AS SINGLE
  51. DIM VectorGroup(bignumber) AS VectorGroupElement
  52.  
  53. ' World vectors.
  54. DIM vec(bignumber, 3) ' Relative Position
  55. DIM vec3Dpos(bignumber, 3) ' Position
  56. DIM vec3Dvel(bignumber, 3) ' Linear velocity
  57. DIM vec3Dacc(bignumber, 3) ' Linear acceleration
  58. DIM vec3Danv(bignumber, 3) ' Angular velocity
  59. DIM vec3Dvis(bignumber) ' Visible toggle
  60. DIM vec2D(bignumber, 2) ' Projection onto 2D plane
  61. DIM vec3Dcolor(bignumber) AS LONG ' Original color
  62. DIM vec2Dcolor(bignumber) AS LONG ' Projected color
  63.  
  64. ' Clipping planes.
  65. DIM nearplane(4), farplane(4), rightplane(4), leftplane(4), topplane(4), bottomplane(4)
  66.  
  67. ' State.
  68. nearplane(4) = 1
  69. farplane(4) = -100
  70. rightplane(4) = 0 '*' fovd * (nhat(1) * rightplane(1) + nhat(2) * rightplane(2) + nhat(3) * rightplane(3))
  71. leftplane(4) = 0
  72. topplane(4) = 0
  73. bottomplane(4) = 0
  74. midscreenx = screenwidth / 2
  75. midscreeny = screenheight / 2
  76. fovd = -256
  77. numgroupvisible = 0
  78. numvectorvisible = 0
  79. groupidticker = 0
  80. vecgroupid = 0
  81. vectorindex = 0
  82. rotspeed = 1 / 33
  83. linspeed = 3 / 2
  84. timestep = .001
  85. camx = -40
  86. camy = 30
  87. camz = 40
  88. uhat(1) = -.2078192: uhat(2) = -.9781672: uhat(3) = 0
  89. vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  90. toggletimeanimate = 1
  91. toggleinvertmouse = -1
  92. togglehud = 1
  93.  
  94. ' Prime main loop.
  95. GOSUB initialize.objects
  96. GOSUB redraw
  97.  
  98. ' Begin main loop.
  99. fpstimer = INT(TIMER)
  100. fps = 0
  101.     GOSUB redraw
  102.     GOSUB mouseprocess
  103.     GOSUB keyprocess
  104.  
  105.     fps = fps + 1
  106.     tt = INT(TIMER)
  107.     IF tt = fpstimer + 1 THEN
  108.         fpstimer = tt
  109.         fpsreport = fps
  110.         fps = 0
  111.     END IF
  112.  
  113.     _DISPLAY
  114.     _KEYCLEAR
  115.     _LIMIT 30
  116.  
  117.  
  118. ' Gosubs.
  119.  
  120. redraw:
  121. GOSUB normalize.SCREEN.vectors
  122. GOSUB calculate.clippingplanes
  123. GOSUB compute.visible.groups
  124. GOSUB plot.visible.vectors
  125.  
  126. mouseprocess:
  127. 'mx = 0
  128. 'my = 0
  129. 'DO WHILE _MOUSEINPUT
  130. '    mx = mx + _MOUSEMOVEMENTX
  131. '    my = my + _MOUSEMOVEMENTY
  132. '    IF _MOUSEWHEEL > 0 THEN GOSUB rotate.clockwise
  133. '    IF _MOUSEWHEEL < 0 THEN GOSUB rotate.counterclockwise
  134. '    IF mx > 0 THEN
  135. '        GOSUB rotate.uhat.plus: GOSUB normalize.screen.vectors
  136. '    END IF
  137. '    IF mx < 0 THEN
  138. '        GOSUB rotate.uhat.minus: GOSUB normalize.screen.vectors
  139. '    END IF
  140. '    IF my > 0 THEN
  141. '        IF toggleinvertmouse = -1 THEN
  142. '            GOSUB rotate.vhat.plus: GOSUB normalize.screen.vectors
  143. '        ELSE
  144. '            GOSUB rotate.vhat.minus: GOSUB normalize.screen.vectors
  145. '        END IF
  146. '    END IF
  147. '    IF my < 0 THEN
  148. '        IF toggleinvertmouse = -1 THEN
  149. '            GOSUB rotate.vhat.minus: GOSUB normalize.screen.vectors
  150. '        ELSE
  151. '            GOSUB rotate.vhat.plus: GOSUB normalize.screen.vectors
  152. '        END IF
  153. '    END IF
  154. '    mx = 0
  155. '    my = 0
  156. 'LOOP
  157.  
  158. keyprocess:
  159. IF _KEYDOWN(119) = -1 OR _KEYDOWN(18432) = -1 THEN GOSUB strafe.camera.nhat.minus ' w or uparrow
  160. IF _KEYDOWN(115) = -1 OR _KEYDOWN(20480) = -1 THEN GOSUB strafe.camera.nhat.plus ' s or downarrow
  161. IF _KEYDOWN(97) = -1 THEN GOSUB strafe.camera.uhat.minus ' a
  162. IF _KEYDOWN(100) = -1 THEN GOSUB strafe.camera.uhat.plus ' d
  163. IF _KEYDOWN(56) = -1 THEN GOSUB rotate.vhat.plus: GOSUB normalize.SCREEN.vectors ' 8
  164. IF _KEYDOWN(50) = -1 THEN GOSUB rotate.vhat.minus: GOSUB normalize.SCREEN.vectors ' 2
  165. IF _KEYDOWN(19200) = -1 OR _KEYDOWN(52) = -1 THEN GOSUB rotate.uhat.minus: GOSUB normalize.SCREEN.vectors ' 4
  166. IF _KEYDOWN(19712) = -1 OR _KEYDOWN(54) = -1 THEN GOSUB rotate.uhat.plus: GOSUB normalize.SCREEN.vectors ' 6
  167. IF _KEYDOWN(55) = -1 THEN GOSUB rotate.clockwise ' 7
  168. IF _KEYDOWN(57) = -1 THEN GOSUB rotate.counterclockwise ' 9
  169. IF _KEYDOWN(49) = -1 THEN GOSUB rotate.uhat.minus: GOSUB normalize.SCREEN.vectors: GOSUB rotate.clockwise ' 1
  170. IF _KEYDOWN(51) = -1 THEN GOSUB rotate.uhat.plus: GOSUB normalize.SCREEN.vectors: GOSUB rotate.counterclockwise ' 3
  171. IF _KEYDOWN(113) = -1 THEN GOSUB strafe.camera.vhat.minus ' q
  172. IF _KEYDOWN(101) = -1 THEN GOSUB strafe.camera.vhat.plus ' e
  173.  
  174. IF (KEY$ <> "") THEN
  175.     SELECT CASE KEY$
  176.         CASE "x"
  177.             uhat(1) = 0: uhat(2) = 1: uhat(3) = 0
  178.             vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  179.         CASE "X"
  180.             uhat(1) = 0: uhat(2) = -1: uhat(3) = 0
  181.             vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  182.         CASE "y"
  183.             uhat(1) = -1: uhat(2) = 0: uhat(3) = 0
  184.             vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  185.         CASE "Y"
  186.             uhat(1) = 1: uhat(2) = 0: uhat(3) = 0
  187.             vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  188.         CASE "z"
  189.             uhat(1) = 1: uhat(2) = 0: uhat(3) = 0
  190.             vhat(1) = 0: vhat(2) = 1: vhat(3) = 0
  191.             GOSUB normalize.SCREEN.vectors
  192.         CASE "Z"
  193.             uhat(1) = 0: uhat(2) = 1: uhat(3) = 0
  194.             vhat(1) = 1: vhat(2) = 0: vhat(3) = 0
  195.         CASE "]"
  196.             farplane(4) = farplane(4) - 1
  197.         CASE "["
  198.             farplane(4) = farplane(4) + 1
  199.         CASE " "
  200.             togglehud = -togglehud
  201.         CASE "t"
  202.             toggletimeanimate = -toggletimeanimate
  203.         CASE "i"
  204.             toggleinvertmouse = -toggleinvertmouse
  205.         CASE "v"
  206.             OPEN "snapshot-camera.txt" FOR OUTPUT AS #1
  207.             PRINT #1, camx, camy, camz
  208.             PRINT #1, uhat(1), uhat(2), uhat(3)
  209.             PRINT #1, vhat(1), vhat(2), vhat(3)
  210.             CLOSE #1
  211.         CASE CHR$(27)
  212.             SYSTEM
  213.         CASE "n"
  214.             VectorGroup(closestgroup).COMFixed = 1
  215.             FOR vectorindex = VectorGroup(closestgroup).FirstVector TO VectorGroup(closestgroup).LastVector
  216.                 vec3Dvel(vectorindex, 1) = (RND - .5) * 200
  217.                 vec3Dvel(vectorindex, 2) = (RND - .5) * 200
  218.                 vec3Dvel(vectorindex, 3) = (RND - .5) * 200
  219.             NEXT
  220.         CASE "k"
  221.             p = VectorGroup(closestgroup).Pointer
  222.             l = VectorGroup(closestgroup).Lagger
  223.             VectorGroup(l).Pointer = p
  224.             IF (p <> -999) THEN
  225.                 VectorGroup(p).Lagger = l
  226.             END IF
  227.         CASE "b"
  228.             tilesize = 5
  229.             ' Determine last object id.
  230.             p = 1
  231.             DO
  232.                 k = VectorGroup(p).Identity
  233.                 p = VectorGroup(k).Pointer
  234.                 IF (p = -999) THEN EXIT DO
  235.             LOOP
  236.             lastobjectid = k
  237.             vectorindex = VectorGroup(lastobjectid).LastVector
  238.             ' Create new group.
  239.             groupidticker = groupidticker + 1
  240.             vecgroupid = groupidticker
  241.             VectorGroup(vecgroupid).Identity = vecgroupid
  242.             VectorGroup(vecgroupid).Pointer = -999
  243.             VectorGroup(vecgroupid).Lagger = lastobjectid
  244.             VectorGroup(vecgroupid).GroupName = "Block"
  245.             VectorGroup(vecgroupid).Visible = 0
  246.             VectorGroup(vecgroupid).COMFixed = 1
  247.             VectorGroup(vecgroupid).DIMx = tilesize / 2
  248.             VectorGroup(vecgroupid).DIMy = tilesize / 2
  249.             VectorGroup(vecgroupid).DIMz = tilesize / 2
  250.             VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  251.             FOR r = 1 TO 400
  252.                 vectorindex = vectorindex + 1
  253.                 vec3Dpos(vectorindex, 1) = camx + -20 * nhat(1) + (RND - .5) * tilesize
  254.                 vec3Dpos(vectorindex, 2) = camy + -20 * nhat(2) + (RND - .5) * tilesize
  255.                 vec3Dpos(vectorindex, 3) = camz + -20 * nhat(3) + (RND - .5) * tilesize
  256.                 vec3Dvis(vectorindex) = 0
  257.                 IF RND > .5 THEN
  258.                     vec3Dcolor(vectorindex) = Lime
  259.                 ELSE
  260.                     vec3Dcolor(vectorindex) = Purple
  261.                 END IF
  262.                 GOSUB integratecom
  263.             NEXT
  264.             VectorGroup(vecgroupid).LastVector = vectorindex
  265.             GOSUB calculatecom
  266.             VectorGroup(lastobjectid).Pointer = vecgroupid
  267.     END SELECT
  268.  
  269. convert:
  270. ' Convert graphics from uv-cartesian coordinates to monitor coordinates.
  271. x0 = x: y0 = y
  272. x = x0 + midscreenx
  273. y = -y0 + midscreeny
  274.  
  275. rotate.uhat.plus:
  276. uhat(1) = uhat(1) + nhat(1) * rotspeed
  277. uhat(2) = uhat(2) + nhat(2) * rotspeed
  278. uhat(3) = uhat(3) + nhat(3) * rotspeed
  279.  
  280. rotate.uhat.minus:
  281. uhat(1) = uhat(1) - nhat(1) * rotspeed
  282. uhat(2) = uhat(2) - nhat(2) * rotspeed
  283. uhat(3) = uhat(3) - nhat(3) * rotspeed
  284.  
  285. rotate.vhat.plus:
  286. vhat(1) = vhat(1) + nhat(1) * rotspeed
  287. vhat(2) = vhat(2) + nhat(2) * rotspeed
  288. vhat(3) = vhat(3) + nhat(3) * rotspeed
  289.  
  290. rotate.vhat.minus:
  291. vhat(1) = vhat(1) - nhat(1) * rotspeed
  292. vhat(2) = vhat(2) - nhat(2) * rotspeed
  293. vhat(3) = vhat(3) - nhat(3) * rotspeed
  294.  
  295. rotate.counterclockwise:
  296. v1 = vhat(1)
  297. v2 = vhat(2)
  298. v3 = vhat(3)
  299. vhat(1) = vhat(1) + uhat(1) * rotspeed
  300. vhat(2) = vhat(2) + uhat(2) * rotspeed
  301. vhat(3) = vhat(3) + uhat(3) * rotspeed
  302. uhat(1) = uhat(1) - v1 * rotspeed
  303. uhat(2) = uhat(2) - v2 * rotspeed
  304. uhat(3) = uhat(3) - v3 * rotspeed
  305.  
  306. rotate.clockwise:
  307. v1 = vhat(1)
  308. v2 = vhat(2)
  309. v3 = vhat(3)
  310. vhat(1) = vhat(1) - uhat(1) * rotspeed
  311. vhat(2) = vhat(2) - uhat(2) * rotspeed
  312. vhat(3) = vhat(3) - uhat(3) * rotspeed
  313. uhat(1) = uhat(1) + v1 * rotspeed
  314. uhat(2) = uhat(2) + v2 * rotspeed
  315. uhat(3) = uhat(3) + v3 * rotspeed
  316.  
  317. strafe.camera.uhat.plus:
  318. camx = camx + uhat(1) * linspeed
  319. camy = camy + uhat(2) * linspeed
  320. camz = camz + uhat(3) * linspeed
  321.  
  322. strafe.camera.uhat.minus:
  323. camx = camx - uhat(1) * linspeed
  324. camy = camy - uhat(2) * linspeed
  325. camz = camz - uhat(3) * linspeed
  326.  
  327. strafe.camera.vhat.plus:
  328. camx = camx + vhat(1) * linspeed
  329. camy = camy + vhat(2) * linspeed
  330. camz = camz + vhat(3) * linspeed
  331.  
  332. strafe.camera.vhat.minus:
  333. camx = camx - vhat(1) * linspeed
  334. camy = camy - vhat(2) * linspeed
  335. camz = camz - vhat(3) * linspeed
  336.  
  337. strafe.camera.nhat.plus:
  338. camx = camx + nhat(1) * linspeed
  339. camy = camy + nhat(2) * linspeed
  340. camz = camz + nhat(3) * linspeed
  341.  
  342. strafe.camera.nhat.minus:
  343. camx = camx - nhat(1) * linspeed
  344. camy = camy - nhat(2) * linspeed
  345. camz = camz - nhat(3) * linspeed
  346.  
  347. normalize.SCREEN.vectors:
  348. uhatmag = SQR(uhat(1) * uhat(1) + uhat(2) * uhat(2) + uhat(3) * uhat(3))
  349. uhat(1) = uhat(1) / uhatmag: uhat(2) = uhat(2) / uhatmag: uhat(3) = uhat(3) / uhatmag
  350. vhatmag = SQR(vhat(1) * vhat(1) + vhat(2) * vhat(2) + vhat(3) * vhat(3))
  351. vhat(1) = vhat(1) / vhatmag: vhat(2) = vhat(2) / vhatmag: vhat(3) = vhat(3) / vhatmag
  352. uhatdotvhat = uhat(1) * vhat(1) + uhat(2) * vhat(2) + uhat(3) * vhat(3)
  353. ' The normal vector points toward the eye.
  354. nhat(1) = uhat(2) * vhat(3) - uhat(3) * vhat(2)
  355. nhat(2) = uhat(3) * vhat(1) - uhat(1) * vhat(3)
  356. nhat(3) = uhat(1) * vhat(2) - uhat(2) * vhat(1)
  357. nhatmag = SQR(nhat(1) * nhat(1) + nhat(2) * nhat(2) + nhat(3) * nhat(3))
  358. nhat(1) = nhat(1) / nhatmag: nhat(2) = nhat(2) / nhatmag: nhat(3) = nhat(3) / nhatmag
  359.  
  360. calculate.clippingplanes:
  361. ' Calculate normal vectors to all clipping planes.
  362. h2 = screenheight / 2
  363. w2 = screenwidth / 2
  364. nearplane(1) = -nhat(1)
  365. nearplane(2) = -nhat(2)
  366. nearplane(3) = -nhat(3)
  367. farplane(1) = nhat(1)
  368. farplane(2) = nhat(2)
  369. farplane(3) = nhat(3)
  370. rightplane(1) = h2 * fovd * uhat(1) - h2 * w2 * nhat(1)
  371. rightplane(2) = h2 * fovd * uhat(2) - h2 * w2 * nhat(2)
  372. rightplane(3) = h2 * fovd * uhat(3) - h2 * w2 * nhat(3)
  373. mag = SQR(rightplane(1) * rightplane(1) + rightplane(2) * rightplane(2) + rightplane(3) * rightplane(3))
  374. rightplane(1) = rightplane(1) / mag
  375. rightplane(2) = rightplane(2) / mag
  376. rightplane(3) = rightplane(3) / mag
  377. leftplane(1) = -h2 * fovd * uhat(1) - h2 * w2 * nhat(1)
  378. leftplane(2) = -h2 * fovd * uhat(2) - h2 * w2 * nhat(2)
  379. leftplane(3) = -h2 * fovd * uhat(3) - h2 * w2 * nhat(3)
  380. mag = SQR(leftplane(1) * leftplane(1) + leftplane(2) * leftplane(2) + leftplane(3) * leftplane(3))
  381. leftplane(1) = leftplane(1) / mag
  382. leftplane(2) = leftplane(2) / mag
  383. leftplane(3) = leftplane(3) / mag
  384. topplane(1) = w2 * fovd * vhat(1) - h2 * w2 * nhat(1)
  385. topplane(2) = w2 * fovd * vhat(2) - h2 * w2 * nhat(2)
  386. topplane(3) = w2 * fovd * vhat(3) - h2 * w2 * nhat(3)
  387. mag = SQR(topplane(1) * topplane(1) + topplane(2) * topplane(2) + topplane(3) * topplane(3))
  388. topplane(1) = topplane(1) / mag
  389. topplane(2) = topplane(2) / mag
  390. topplane(3) = topplane(3) / mag
  391. bottomplane(1) = -w2 * fovd * vhat(1) - h2 * w2 * nhat(1)
  392. bottomplane(2) = -w2 * fovd * vhat(2) - h2 * w2 * nhat(2)
  393. bottomplane(3) = -w2 * fovd * vhat(3) - h2 * w2 * nhat(3)
  394. mag = SQR(bottomplane(1) * bottomplane(1) + bottomplane(2) * bottomplane(2) + bottomplane(3) * bottomplane(3))
  395. bottomplane(1) = bottomplane(1) / mag
  396. bottomplane(2) = bottomplane(2) / mag
  397. bottomplane(3) = bottomplane(3) / mag
  398.  
  399. compute.visible.groups:
  400. closestdist2 = 10000000
  401. closestgroup = 1
  402. fp42 = farplane(4) * farplane(4)
  403.  
  404. k = 1
  405. k = VectorGroup(k).Identity
  406. DO ' iterates k
  407.  
  408.     VectorGroup(k).Visible = 0
  409.  
  410.     dx = VectorGroup(k).COMx - camx
  411.     dy = VectorGroup(k).COMy - camy
  412.     dz = VectorGroup(k).COMz - camz
  413.  
  414.     dist2 = dx * dx + dy * dy + dz * dz
  415.  
  416.     IF dist2 < fp42 THEN
  417.  
  418.         groupinview = 1
  419.         IF dx * nearplane(1) + dy * nearplane(2) + dz * nearplane(3) - nearplane(4) < 0 THEN groupinview = 0
  420.         'IF dx * farplane(1) + dy * farplane(2) + dz * farplane(3) - farplane(4) < 0 THEN groupinview = 0
  421.         IF dx * rightplane(1) + dy * rightplane(2) + dz * rightplane(3) - rightplane(4) < 0 THEN groupinview = 0
  422.         IF dx * leftplane(1) + dy * leftplane(2) + dz * leftplane(3) - leftplane(4) < 0 THEN groupinview = 0
  423.         IF dx * topplane(1) + dy * topplane(2) + dz * topplane(3) - topplane(4) < 0 THEN groupinview = 0
  424.         IF dx * bottomplane(1) + dy * bottomplane(2) + dz * bottomplane(3) - bottomplane(4) < 0 THEN groupinview = 0
  425.         IF groupinview = 1 THEN
  426.  
  427.             IF (dist2 < closestdist2) THEN
  428.                 closestdist2 = dist2
  429.                 closestgroup = k
  430.             END IF
  431.  
  432.             VectorGroup(k).Visible = 1
  433.  
  434.             IF (toggletimeanimate = 1) THEN
  435.                 vecgroupid = k
  436.                 GOSUB timeanimate
  437.             END IF
  438.  
  439.             FOR i = VectorGroup(k).FirstVector TO VectorGroup(k).LastVector
  440.                 GOSUB clip.project.vectors
  441.             NEXT
  442.  
  443.         ELSE
  444.             ' Force animation regardless of clipping.
  445.             IF (VectorGroup(k).ForceAnimate = 1) THEN
  446.                 vecgroupid = k
  447.                 GOSUB timeanimate
  448.             END IF
  449.         END IF
  450.     ELSE
  451.         ' Force animation regardless of distance from camera.
  452.         IF (VectorGroup(k).ForceAnimate = 1) THEN
  453.             vecgroupid = k
  454.             GOSUB timeanimate
  455.         END IF
  456.     END IF
  457.     k = VectorGroup(k).Pointer
  458.     IF k = -999 THEN EXIT DO
  459.     k = VectorGroup(k).Identity
  460.  
  461. clip.project.vectors: ' requires i
  462. vec(i, 1) = vec3Dpos(i, 1) - camx
  463. vec(i, 2) = vec3Dpos(i, 2) - camy
  464. vec(i, 3) = vec3Dpos(i, 3) - camz
  465. fogswitch = -1
  466. vec3Dvis(i) = 0
  467. vectorinview = 1
  468. ' Perform view plane clipping.
  469. IF vec(i, 1) * nearplane(1) + vec(i, 2) * nearplane(2) + vec(i, 3) * nearplane(3) - nearplane(4) < 0 THEN vectorinview = 0
  470. IF vec(i, 1) * farplane(1) + vec(i, 2) * farplane(2) + vec(i, 3) * farplane(3) - farplane(4) < 0 THEN vectorinview = 0
  471. IF vec(i, 1) * farplane(1) + vec(i, 2) * farplane(2) + vec(i, 3) * farplane(3) - farplane(4) * .85 < 0 THEN fogswitch = 1
  472. IF vec(i, 1) * rightplane(1) + vec(i, 2) * rightplane(2) + vec(i, 3) * rightplane(3) - rightplane(4) < 0 THEN vectorinview = 0
  473. IF vec(i, 1) * leftplane(1) + vec(i, 2) * leftplane(2) + vec(i, 3) * leftplane(3) - leftplane(4) < 0 THEN vectorinview = 0
  474. IF vec(i, 1) * topplane(1) + vec(i, 2) * topplane(2) + vec(i, 3) * topplane(3) - topplane(4) < 0 THEN vectorinview = 0
  475. IF vec(i, 1) * bottomplane(1) + vec(i, 2) * bottomplane(2) + vec(i, 3) * bottomplane(3) - bottomplane(4) < 0 THEN vectorinview = 0
  476. IF vectorinview = 1 THEN
  477.     vec3Dvis(i) = 1
  478.     ' Project vectors onto the screen plane.
  479.     vec3Ddotnhat = vec(i, 1) * nhat(1) + vec(i, 2) * nhat(2) + vec(i, 3) * nhat(3)
  480.     vec2D(i, 1) = (vec(i, 1) * uhat(1) + vec(i, 2) * uhat(2) + vec(i, 3) * uhat(3)) * fovd / vec3Ddotnhat
  481.     vec2D(i, 2) = (vec(i, 1) * vhat(1) + vec(i, 2) * vhat(2) + vec(i, 3) * vhat(3)) * fovd / vec3Ddotnhat
  482.     IF fogswitch = 1 THEN vec2Dcolor(i) = Gray ELSE vec2Dcolor(i) = vec3Dcolor(i)
  483.  
  484. timeanimate: ' requires vecgroupid
  485. dt = timestep
  486.  
  487. xcom = VectorGroup(vecgroupid).COMx
  488. ycom = VectorGroup(vecgroupid).COMy
  489. zcom = VectorGroup(vecgroupid).COMz
  490. xrot = VectorGroup(vecgroupid).ROTx
  491. yrot = VectorGroup(vecgroupid).ROTy
  492. zrot = VectorGroup(vecgroupid).ROTz
  493. xrev = VectorGroup(vecgroupid).ROTx
  494. yrev = VectorGroup(vecgroupid).ROTy
  495. zrev = VectorGroup(vecgroupid).ROTz
  496. xdim = VectorGroup(vecgroupid).DIMx
  497. ydim = VectorGroup(vecgroupid).DIMy
  498. zdim = VectorGroup(vecgroupid).DIMz
  499.  
  500. IF (VectorGroup(vecgroupid).COMFixed = 0) THEN GOSUB resetcom
  501.  
  502. FOR vectorindex = VectorGroup(vecgroupid).FirstVector TO VectorGroup(vecgroupid).LastVector
  503.  
  504.     ' Linear velocity update
  505.     ax = vec3Dacc(vectorindex, 1)
  506.     ay = vec3Dacc(vectorindex, 2)
  507.     az = vec3Dacc(vectorindex, 3)
  508.     IF (ax <> 0) THEN vec3Dvel(vectorindex, 1) = vec3Dvel(vectorindex, 1) + ax * dt
  509.     IF (ay <> 0) THEN vec3Dvel(vectorindex, 2) = vec3Dvel(vectorindex, 2) + ay * dt
  510.     IF (az <> 0) THEN vec3Dvel(vectorindex, 3) = vec3Dvel(vectorindex, 3) + az * dt
  511.  
  512.     ' Linear position update with periodic boundaries inside group dimension
  513.     vx = vec3Dvel(vectorindex, 1)
  514.     vy = vec3Dvel(vectorindex, 2)
  515.     vz = vec3Dvel(vectorindex, 3)
  516.     IF (vx <> 0) THEN
  517.         px = vec3Dpos(vectorindex, 1) + vx * dt
  518.         IF ABS(px - xcom) > xdim THEN
  519.             IF (px > xcom) THEN
  520.                 px = xcom - xdim
  521.             ELSE
  522.                 px = xcom + xdim
  523.             END IF
  524.         END IF
  525.         vec3Dpos(vectorindex, 1) = px
  526.     END IF
  527.     IF (vy <> 0) THEN
  528.         py = vec3Dpos(vectorindex, 2) + vy * dt
  529.         IF ABS(py - ycom) > ydim THEN
  530.             IF (py > ycom) THEN
  531.                 py = ycom - ydim
  532.             ELSE
  533.                 py = ycom + ydim
  534.             END IF
  535.         END IF
  536.         vec3Dpos(vectorindex, 2) = py
  537.     END IF
  538.     IF (vz <> 0) THEN
  539.         pz = vec3Dpos(vectorindex, 3) + vz * dt
  540.         IF ABS(pz - zcom) > zdim THEN
  541.             IF (pz > zcom) THEN
  542.                 pz = zcom - zdim
  543.             ELSE
  544.                 pz = zcom + zdim
  545.             END IF
  546.         END IF
  547.         vec3Dpos(vectorindex, 3) = pz
  548.     END IF
  549.  
  550.     ' Rotation update
  551.     IF (xrot <> 0) THEN
  552.         anv = vec3Danv(vectorindex, 1)
  553.         yy = vec3Dpos(vectorindex, 2) - yrot
  554.         zz = vec3Dpos(vectorindex, 3) - zrot
  555.         y = yy * COS(timestep * anv) - zz * SIN(timestep * anv)
  556.         z = yy * SIN(timestep * anv) + zz * COS(timestep * anv)
  557.         vec3Dpos(vectorindex, 2) = y + yrot
  558.         vec3Dpos(vectorindex, 3) = z + zrot
  559.     END IF
  560.     IF (yrot <> 0) THEN
  561.         anv = vec3Danv(vectorindex, 2)
  562.         xx = vec3Dpos(vectorindex, 1) - xrot
  563.         zz = vec3Dpos(vectorindex, 3) - zrot
  564.         x = xx * COS(timestep * anv) + zz * SIN(timestep * anv)
  565.         z = -xx * SIN(timestep * anv) + zz * COS(timestep * anv)
  566.         vec3Dpos(vectorindex, 1) = x + xrot
  567.         vec3Dpos(vectorindex, 3) = z + zrot
  568.     END IF
  569.     IF (zrot <> 0) THEN
  570.         anv = vec3Danv(vectorindex, 3)
  571.         xx = vec3Dpos(vectorindex, 1) - xrot
  572.         yy = vec3Dpos(vectorindex, 2) - yrot
  573.         x = xx * COS(timestep * anv) - yy * SIN(timestep * anv)
  574.         y = xx * SIN(timestep * anv) + yy * COS(timestep * anv)
  575.         vec3Dpos(vectorindex, 1) = x + xrot
  576.         vec3Dpos(vectorindex, 2) = y + yrot
  577.     END IF
  578.  
  579.     ' Revolution update
  580.     IF (xrev <> 0) THEN
  581.         anv = xrev
  582.         yy = vec3Dpos(vectorindex, 2) - ycom
  583.         zz = vec3Dpos(vectorindex, 3) - zcom
  584.         y = yy * COS(timestep * anv) - zz * SIN(timestep * anv)
  585.         z = yy * SIN(timestep * anv) + zz * COS(timestep * anv)
  586.         vec3Dpos(vectorindex, 2) = y + ycom
  587.         vec3Dpos(vectorindex, 3) = z + zcom
  588.     END IF
  589.     IF (yrev <> 0) THEN
  590.         anv = yrev
  591.         xx = vec3Dpos(vectorindex, 1) - xcom
  592.         zz = vec3Dpos(vectorindex, 3) - zcom
  593.         x = xx * COS(timestep * anv) + zz * SIN(timestep * anv)
  594.         z = -xx * SIN(timestep * anv) + zz * COS(timestep * anv)
  595.         vec3Dpos(vectorindex, 1) = x + xcom
  596.         vec3Dpos(vectorindex, 3) = z + zcom
  597.     END IF
  598.     IF (zrev <> 0) THEN
  599.         anv = zrev
  600.         xx = vec3Dpos(vectorindex, 1) - xcom
  601.         yy = vec3Dpos(vectorindex, 2) - ycom
  602.         x = xx * COS(timestep * anv) - yy * SIN(timestep * anv)
  603.         y = xx * SIN(timestep * anv) + yy * COS(timestep * anv)
  604.         vec3Dpos(vectorindex, 1) = x + xcom
  605.         vec3Dpos(vectorindex, 2) = y + ycom
  606.     END IF
  607.  
  608.     IF (VectorGroup(vecgroupid).COMFixed = 0) THEN GOSUB integratecom
  609. IF (VectorGroup(vecgroupid).COMFixed = 0) THEN GOSUB calculatecom
  610.  
  611. integratecom: ' requires vecgroupid
  612. VectorGroup(vecgroupid).COMx = vec3Dpos(vectorindex, 1) + VectorGroup(vecgroupid).COMx
  613. VectorGroup(vecgroupid).COMy = vec3Dpos(vectorindex, 2) + VectorGroup(vecgroupid).COMy
  614. VectorGroup(vecgroupid).COMz = vec3Dpos(vectorindex, 3) + VectorGroup(vecgroupid).COMz
  615.  
  616. calculatecom: ' requires vecgroupid
  617. f = 1 + VectorGroup(vecgroupid).LastVector - VectorGroup(vecgroupid).FirstVector
  618. VectorGroup(vecgroupid).COMx = VectorGroup(vecgroupid).COMx / f
  619. VectorGroup(vecgroupid).COMy = VectorGroup(vecgroupid).COMy / f
  620. VectorGroup(vecgroupid).COMz = VectorGroup(vecgroupid).COMz / f
  621.  
  622. resetcom: ' requires vecgroupid
  623. VectorGroup(vecgroupid).COMx = 0
  624. VectorGroup(vecgroupid).COMy = 0
  625. VectorGroup(vecgroupid).COMz = 0
  626.  
  627. plot.visible.vectors:
  628. GOSUB plot.vectors
  629. GOSUB plot.hud
  630.  
  631. plot.vectors:
  632. numgroupvisible = 0
  633. numvectorvisible = 0
  634. k = 1
  635. k = VectorGroup(k).Identity
  636.     IF (VectorGroup(k).Visible = 1) THEN
  637.         numgroupvisible = numgroupvisible + 1
  638.         FOR i = VectorGroup(k).FirstVector TO VectorGroup(k).LastVector - 1
  639.             IF (vec3Dvis(i) = 1) THEN
  640.                 numvectorvisible = numvectorvisible + 1
  641.                 IF k = closestgroup THEN col = Yellow ELSE col = vec2Dcolor(i)
  642.                 x = vec2D(i, 1): y = vec2D(i, 2): GOSUB convert: x1 = x: y1 = y
  643.                 x = vec2D(i + 1, 1): y = vec2D(i + 1, 2): GOSUB convert: x2 = x: y2 = y
  644.                 IF ((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) < 225 THEN
  645.                     LINE (x1, y1)-(x2, y2), col
  646.                 ELSE
  647.                     CIRCLE (x1, y1), 1, col
  648.                 END IF
  649.             END IF
  650.         NEXT
  651.     END IF
  652.     k = VectorGroup(k).Pointer
  653.     IF k = -999 THEN EXIT DO
  654.     k = VectorGroup(k).Identity
  655.  
  656. plot.hud:
  657. ' Redraw compass.
  658. x = 30 * (xhat(1) * uhat(1) + xhat(2) * uhat(2) + xhat(3) * uhat(3)): y = 30 * (xhat(1) * vhat(1) + xhat(2) * vhat(2) + xhat(3) * vhat(3)): GOSUB convert
  659. LINE (midscreenx, midscreeny)-(x, y), Red
  660. x = 30 * (yhat(1) * uhat(1) + yhat(2) * uhat(2) + yhat(3) * uhat(3)): y = 30 * (yhat(1) * vhat(1) + yhat(2) * vhat(2) + yhat(3) * vhat(3)): GOSUB convert
  661. LINE (midscreenx, midscreeny)-(x, y), Green
  662. x = 30 * (zhat(1) * uhat(1) + zhat(2) * uhat(2) + zhat(3) * uhat(3)): y = 30 * (zhat(1) * vhat(1) + zhat(2) * vhat(2) + zhat(3) * vhat(3)): GOSUB convert
  663. LINE (midscreenx, midscreeny)-(x, y), Blue
  664. IF togglehud = 1 THEN
  665.     COLOR LimeGreen
  666.     LOCATE 2, 2: PRINT "- View Info -"
  667.     COLOR DarkKhaki
  668.     LOCATE 3, 2: PRINT "FPS:"; fpsreport
  669.     LOCATE 4, 2: PRINT "Vectors:"; numvectorvisible
  670.     LOCATE 5, 2: PRINT "Groups:"; numgroupvisible
  671.     LOCATE 6, 2: PRINT "Depth:"; -farplane(4)
  672.     LOCATE 7, 2: PRINT "Adjust via [ ]"
  673.     COLOR LimeGreen
  674.     LOCATE 9, 2: PRINT "- Camera -"
  675.     COLOR DarkKhaki
  676.     LOCATE 10, 2: PRINT INT(camx); INT(camy); INT(camz)
  677.     COLOR LimeGreen
  678.     LOCATE 12, 2: PRINT "- Closest: -"
  679.     COLOR DarkKhaki
  680.     LOCATE 13, 2: PRINT LTRIM$(RTRIM$(VectorGroup(closestgroup).GroupName))
  681.     COLOR LimeGreen
  682.     a$ = "MOVE - ALIGN": LOCATE 2, screenwidth / 8 - LEN(a$): PRINT a$
  683.     COLOR DarkKhaki
  684.     a$ = "q w e - x y z": LOCATE 3, screenwidth / 8 - LEN(a$): PRINT a$
  685.     a$ = "a s d - X Y Z": LOCATE 4, screenwidth / 8 - LEN(a$): PRINT a$
  686.     a$ = "i = invert ms": LOCATE 5, screenwidth / 8 - LEN(a$): PRINT a$
  687.     COLOR LimeGreen
  688.     a$ = "- ROTATE -": LOCATE 7, screenwidth / 8 - LEN(a$): PRINT a$
  689.     COLOR DarkKhaki
  690.     a$ = "7 8 9 Mouse": LOCATE 8, screenwidth / 8 - LEN(a$): PRINT a$
  691.     a$ = "4 5 6   +  ": LOCATE 9, screenwidth / 8 - LEN(a$): PRINT a$
  692.     a$ = "1 2 3 Wheel": LOCATE 10, screenwidth / 8 - LEN(a$): PRINT a$
  693.     COLOR LimeGreen
  694.     a$ = "- CONTROL -": LOCATE 12, screenwidth / 8 - LEN(a$): PRINT a$
  695.     COLOR DarkKhaki
  696.     a$ = "t = Stop time": LOCATE 13, screenwidth / 8 - LEN(a$): PRINT a$
  697.     a$ = "b = Create": LOCATE 14, screenwidth / 8 - LEN(a$): PRINT a$
  698.     a$ = "n = Destroy": LOCATE 15, screenwidth / 8 - LEN(a$): PRINT a$
  699.     a$ = "k = Delete": LOCATE 16, screenwidth / 8 - LEN(a$): PRINT a$
  700.     COLOR LimeGreen
  701.     a$ = "SPACE = Hide Info": LOCATE (screenheight / 16) - 3, (screenwidth / 8) / 2 - LEN(a$) / 2: PRINT a$
  702.     COLOR LimeGreen
  703.     a$ = "You See: " + LTRIM$(RTRIM$(VectorGroup(closestgroup).GroupName)): LOCATE (screenheight / 16) - 3, (screenwidth / 8) / 2 - LEN(a$) / 2: PRINT a$
  704.  
  705. 'groupidfromname: ' requires n$, returns k
  706. 'k = 1
  707. 'k = VectorGroup(k).Identity
  708. 'DO ' iterates k
  709. '    IF n$ = LTRIM$(RTRIM$(VectorGroup(k).GroupName)) THEN EXIT DO
  710. '    k = VectorGroup(k).Pointer
  711. '    IF k = -999 THEN EXIT DO
  712. '    k = VectorGroup(k).Identity
  713. 'LOOP
  714. 'RETURN
  715.  
  716. ' Data.
  717.  
  718. initialize.objects:
  719. vectorindex = 0
  720. groupidticker = 0
  721. gridsize = 550
  722. tilesize = 15
  723.  
  724. '__AAA
  725. groupidticker = groupidticker + 1
  726. vecgroupid = groupidticker
  727. VectorGroup(vecgroupid).Identity = vecgroupid
  728. VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  729. VectorGroup(vecgroupid).Lagger = vecgroupid - 1 ' Fancy way to say 0.
  730. VectorGroup(vecgroupid).GroupName = "__AAA"
  731. VectorGroup(vecgroupid).Visible = 0
  732. VectorGroup(vecgroupid).COMFixed = 1
  733. VectorGroup(vecgroupid).DIMx = 5
  734. VectorGroup(vecgroupid).DIMy = 5
  735. VectorGroup(vecgroupid).DIMz = 5
  736. VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  737. FOR r = 1 TO 1
  738.     vectorindex = vectorindex + 1
  739.     vec3Dpos(vectorindex, 1) = 0
  740.     vec3Dpos(vectorindex, 2) = 0
  741.     vec3Dpos(vectorindex, 3) = -1000
  742.     vec3Dcolor(vectorindex) = White
  743.     GOSUB integratecom
  744. VectorGroup(vecgroupid).LastVector = vectorindex
  745. GOSUB calculatecom
  746.  
  747. 'Dirt
  748. h = 5
  749. FOR w = 1 TO 5
  750.     FOR u = -gridsize TO gridsize STEP tilesize
  751.         FOR v = -gridsize TO gridsize STEP tilesize
  752.             groupidticker = groupidticker + 1
  753.             vecgroupid = groupidticker
  754.             VectorGroup(vecgroupid).Identity = vecgroupid
  755.             VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  756.             VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  757.             VectorGroup(vecgroupid).GroupName = "Dirt"
  758.             VectorGroup(vecgroupid).Visible = 0
  759.             VectorGroup(vecgroupid).COMFixed = 1
  760.             VectorGroup(vecgroupid).DIMx = 35
  761.             VectorGroup(vecgroupid).DIMy = 35
  762.             VectorGroup(vecgroupid).DIMz = 35
  763.             VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  764.             FOR i = u TO u + tilesize STEP h
  765.                 FOR j = v TO v + tilesize STEP h
  766.                     IF RND > 1 - w / 5 THEN
  767.                         vectorindex = vectorindex + 1
  768.                         vec3Dpos(vectorindex, 1) = i + RND * h - RND * h
  769.                         vec3Dpos(vectorindex, 2) = j + RND * h - RND * h
  770.                         vec3Dpos(vectorindex, 3) = -(w - 1) * 70 - RND * 70
  771.                         vec3Dvis(vectorindex) = 0
  772.                         IF RND > .5 THEN
  773.                             vec3Dcolor(vectorindex) = DarkGoldenRod
  774.                         ELSE
  775.                             IF RND > .5 THEN
  776.                                 vec3Dcolor(vectorindex) = SaddleBrown
  777.                             ELSE
  778.                                 vec3Dcolor(vectorindex) = Sienna
  779.                             END IF
  780.                         END IF
  781.                         GOSUB integratecom
  782.                     END IF
  783.                 NEXT
  784.             NEXT
  785.             VectorGroup(vecgroupid).LastVector = vectorindex
  786.             GOSUB calculatecom
  787.         NEXT
  788.     NEXT
  789.  
  790. 'Grass and Puddles
  791. h = 2
  792. FOR u = -gridsize TO gridsize STEP tilesize
  793.     FOR v = -gridsize TO gridsize STEP tilesize
  794.         groupidticker = groupidticker + 1
  795.         vecgroupid = groupidticker
  796.         VectorGroup(vecgroupid).Identity = vecgroupid
  797.         VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  798.         VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  799.         VectorGroup(vecgroupid).GroupName = "Grass and Puddles"
  800.         VectorGroup(vecgroupid).Visible = 0
  801.         VectorGroup(vecgroupid).COMFixed = 1
  802.         VectorGroup(vecgroupid).DIMx = tilesize / 2
  803.         VectorGroup(vecgroupid).DIMy = tilesize / 2
  804.         VectorGroup(vecgroupid).DIMz = 3
  805.         VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  806.         FOR i = u TO u + tilesize STEP h
  807.             FOR j = v TO v + tilesize STEP h
  808.                 vectorindex = vectorindex + 1
  809.                 vec3Dpos(vectorindex, 1) = i + RND * h - RND * h
  810.                 vec3Dpos(vectorindex, 2) = j + RND * h - RND * h
  811.                 vec3Dpos(vectorindex, 3) = .5 + 1 * COS((i - 15) * .08) - 1 * COS((j - 6) * .12)
  812.                 vec3Dvis(vectorindex) = 0
  813.                 IF vec3Dpos(vectorindex, 3) > 0 THEN
  814.                     IF RND > .5 THEN
  815.                         vec3Dcolor(vectorindex) = Green
  816.                     ELSE
  817.                         vec3Dcolor(vectorindex) = ForestGreen
  818.                     END IF
  819.                 ELSE
  820.                     vec3Dvel(vectorindex, 1) = (RND - .5) * 20
  821.                     vec3Dvel(vectorindex, 2) = (RND - .5) * 20
  822.                     vec3Dvel(vectorindex, 3) = (RND - .5) * 20
  823.                     IF RND > .2 THEN
  824.                         vec3Dcolor(vectorindex) = LightSeaGreen
  825.                     ELSE
  826.                         vec3Dcolor(vectorindex) = Blue
  827.                     END IF
  828.                 END IF
  829.                 GOSUB integratecom
  830.             NEXT
  831.         NEXT
  832.         VectorGroup(vecgroupid).LastVector = vectorindex
  833.         GOSUB calculatecom
  834.     NEXT
  835.  
  836. 'Grave
  837. thickness = 2.5
  838. span = 20
  839. height = 30
  840. crux = 22
  841. FOR xloc = -90 TO -290 STEP -60
  842.     FOR yloc = 0 TO 180 STEP 45
  843.         FOR k = 0 TO height
  844.             groupidticker = groupidticker + 1
  845.             vecgroupid = groupidticker
  846.             VectorGroup(vecgroupid).Identity = vecgroupid
  847.             VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  848.             VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  849.             VectorGroup(vecgroupid).GroupName = "Grave"
  850.             VectorGroup(vecgroupid).Visible = 0
  851.             VectorGroup(vecgroupid).COMFixed = 1
  852.             VectorGroup(vecgroupid).DIMx = thickness
  853.             VectorGroup(vecgroupid).DIMy = thickness
  854.             VectorGroup(vecgroupid).DIMz = thickness
  855.             VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  856.             FOR i = -thickness TO thickness STEP thickness / 2
  857.                 FOR j = -thickness TO thickness STEP thickness / 2
  858.                     vectorindex = vectorindex + 1
  859.                     vec3Dpos(vectorindex, 1) = xloc + i + (RND - .5) * 2
  860.                     vec3Dpos(vectorindex, 2) = yloc + j + (RND - .5) * 2
  861.                     vec3Dpos(vectorindex, 3) = k + (RND - .5) * 2
  862.                     vec3Dvis(vectorindex) = 0
  863.                     IF RND > .5 THEN
  864.                         vec3Dcolor(vectorindex) = SlateGray
  865.                     ELSE
  866.                         vec3Dcolor(vectorindex) = DarkGray
  867.                     END IF
  868.                     GOSUB integratecom
  869.                 NEXT
  870.             NEXT
  871.             VectorGroup(vecgroupid).LastVector = vectorindex
  872.             GOSUB calculatecom
  873.         NEXT
  874.         FOR j = -span / 2 TO -thickness
  875.             groupidticker = groupidticker + 1
  876.             vecgroupid = groupidticker
  877.             VectorGroup(vecgroupid).Identity = vecgroupid
  878.             VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  879.             VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  880.             VectorGroup(vecgroupid).GroupName = "Grave"
  881.             VectorGroup(vecgroupid).Visible = 0
  882.             VectorGroup(vecgroupid).COMFixed = 1
  883.             VectorGroup(vecgroupid).DIMx = thickness
  884.             VectorGroup(vecgroupid).DIMy = thickness
  885.             VectorGroup(vecgroupid).DIMz = thickness
  886.             VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  887.             FOR k = -thickness TO thickness STEP thickness / 2
  888.                 FOR i = -thickness TO thickness STEP thickness / 2
  889.                     vectorindex = vectorindex + 1
  890.                     vec3Dpos(vectorindex, 1) = xloc + i + (RND - .5) * 2
  891.                     vec3Dpos(vectorindex, 2) = yloc + j + (RND - .5) * 2
  892.                     vec3Dpos(vectorindex, 3) = crux + k + (RND - .5) * 2
  893.                     vec3Dvis(vectorindex) = 0
  894.                     IF RND > .5 THEN
  895.                         vec3Dcolor(vectorindex) = SlateGray
  896.                     ELSE
  897.                         vec3Dcolor(vectorindex) = DarkGray
  898.                     END IF
  899.                     GOSUB integratecom
  900.                 NEXT
  901.             NEXT
  902.             VectorGroup(vecgroupid).LastVector = vectorindex
  903.             GOSUB calculatecom
  904.         NEXT
  905.         FOR j = thickness TO span / 2
  906.             groupidticker = groupidticker + 1
  907.             vecgroupid = groupidticker
  908.             VectorGroup(vecgroupid).Identity = vecgroupid
  909.             VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  910.             VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  911.             VectorGroup(vecgroupid).GroupName = "Grave"
  912.             VectorGroup(vecgroupid).Visible = 0
  913.             VectorGroup(vecgroupid).COMFixed = 1
  914.             VectorGroup(vecgroupid).DIMx = thickness
  915.             VectorGroup(vecgroupid).DIMy = thickness
  916.             VectorGroup(vecgroupid).DIMz = thickness
  917.             VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  918.             FOR k = -thickness TO thickness STEP thickness / 2
  919.                 FOR i = -thickness TO thickness STEP thickness / 2
  920.                     vectorindex = vectorindex + 1
  921.                     vec3Dpos(vectorindex, 1) = xloc + i + (RND - .5) * 2
  922.                     vec3Dpos(vectorindex, 2) = yloc + j + (RND - .5) * 2
  923.                     vec3Dpos(vectorindex, 3) = crux + k + (RND - .5) * 2
  924.                     vec3Dvis(vectorindex) = 0
  925.                     IF RND > .5 THEN
  926.                         vec3Dcolor(vectorindex) = SlateGray
  927.                     ELSE
  928.                         vec3Dcolor(vectorindex) = DarkGray
  929.                     END IF
  930.                     GOSUB integratecom
  931.                 NEXT
  932.             NEXT
  933.             VectorGroup(vecgroupid).LastVector = vectorindex
  934.             GOSUB calculatecom
  935.         NEXT
  936.     NEXT
  937.  
  938. 'Heaven's Bottom Layer
  939. h = 2
  940. FOR u = -gridsize TO gridsize STEP tilesize
  941.     FOR v = -gridsize TO gridsize STEP tilesize
  942.         groupidticker = groupidticker + 1
  943.         vecgroupid = groupidticker
  944.         VectorGroup(vecgroupid).Identity = vecgroupid
  945.         VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  946.         VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  947.         VectorGroup(vecgroupid).GroupName = "Heaven's Bottom Layer"
  948.         VectorGroup(vecgroupid).Visible = 0
  949.         VectorGroup(vecgroupid).COMFixed = 1
  950.         VectorGroup(vecgroupid).DIMx = tilesize / 2
  951.         VectorGroup(vecgroupid).DIMy = tilesize / 2
  952.         VectorGroup(vecgroupid).DIMz = 3
  953.         VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  954.         FOR i = u TO u + tilesize STEP h
  955.             FOR j = v TO v + tilesize STEP h
  956.                 vectorindex = vectorindex + 1
  957.                 vec3Dpos(vectorindex, 1) = i + RND * h - RND * h
  958.                 vec3Dpos(vectorindex, 2) = j + RND * h - RND * h
  959.                 vec3Dpos(vectorindex, 3) = 420 - RND
  960.                 vec3Dvis(vectorindex) = 0
  961.                 IF RND > .5 THEN
  962.                     vec3Dcolor(vectorindex) = BlueViolet
  963.                 ELSE
  964.                     vec3Dcolor(vectorindex) = Cyan
  965.                 END IF
  966.                 GOSUB integratecom
  967.             NEXT
  968.         NEXT
  969.         VectorGroup(vecgroupid).LastVector = vectorindex
  970.         GOSUB calculatecom
  971.     NEXT
  972.  
  973. 'Hell Spawn
  974. FOR u = -gridsize TO gridsize STEP tilesize
  975.     FOR v = -gridsize TO gridsize STEP tilesize
  976.         groupidticker = groupidticker + 1
  977.         vecgroupid = groupidticker
  978.         VectorGroup(vecgroupid).Identity = vecgroupid
  979.         VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  980.         VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  981.         VectorGroup(vecgroupid).GroupName = "Hell Spawn"
  982.         VectorGroup(vecgroupid).Visible = 0
  983.         VectorGroup(vecgroupid).COMFixed = 1
  984.         VectorGroup(vecgroupid).DIMx = tilesize / 2
  985.         VectorGroup(vecgroupid).DIMy = tilesize / 2
  986.         VectorGroup(vecgroupid).DIMz = 35
  987.         VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  988.         FOR i = u TO u + tilesize STEP tilesize / 5
  989.             FOR j = v TO v + tilesize STEP tilesize / 5
  990.                 vectorindex = vectorindex + 1
  991.                 vec3Dpos(vectorindex, 1) = i + (RND - .5) * tilesize
  992.                 vec3Dpos(vectorindex, 2) = j + (RND - .5) * tilesize
  993.                 vec3Dpos(vectorindex, 3) = -350 - RND * 70
  994.                 vec3Dvel(vectorindex, 1) = 0
  995.                 vec3Dvel(vectorindex, 2) = 0
  996.                 vec3Dvel(vectorindex, 3) = 400 * RND
  997.                 vec3Dvis(vectorindex) = 0
  998.                 IF RND > .2 THEN
  999.                     vec3Dcolor(vectorindex) = Red
  1000.                 ELSE
  1001.                     vec3Dcolor(vectorindex) = DarkGoldenRod
  1002.                 END IF
  1003.                 GOSUB integratecom
  1004.             NEXT
  1005.         NEXT
  1006.         VectorGroup(vecgroupid).LastVector = vectorindex
  1007.         GOSUB calculatecom
  1008.         VectorGroup(vecgroupid).COMz = -350 - 35
  1009.     NEXT
  1010.  
  1011. 'Icewall East
  1012. h = 2
  1013. FOR u = -gridsize TO gridsize STEP tilesize
  1014.     FOR v = 0 TO 70 STEP tilesize
  1015.         groupidticker = groupidticker + 1
  1016.         vecgroupid = groupidticker
  1017.         VectorGroup(vecgroupid).Identity = vecgroupid
  1018.         VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  1019.         VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  1020.         VectorGroup(vecgroupid).GroupName = "Icewall East"
  1021.         VectorGroup(vecgroupid).Visible = 0
  1022.         VectorGroup(vecgroupid).COMFixed = 1
  1023.         VectorGroup(vecgroupid).DIMx = tilesize / 2
  1024.         VectorGroup(vecgroupid).DIMy = tilesize / 2
  1025.         VectorGroup(vecgroupid).DIMz = tilesize / 2
  1026.         VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  1027.         FOR i = u TO u + tilesize STEP h
  1028.             FOR j = v TO v + tilesize STEP h
  1029.                 vectorindex = vectorindex + 1
  1030.                 vec3Dpos(vectorindex, 1) = gridsize + tilesize / 2
  1031.                 vec3Dpos(vectorindex, 2) = i + RND * h - RND * h
  1032.                 vec3Dpos(vectorindex, 3) = j + RND * h - RND * h
  1033.                 vec3Dvis(vectorindex) = 0
  1034.                 IF RND > .5 THEN
  1035.                     vec3Dcolor(vectorindex) = White
  1036.                 ELSE
  1037.                     vec3Dcolor(vectorindex) = Ivory
  1038.                 END IF
  1039.                 GOSUB integratecom
  1040.             NEXT
  1041.         NEXT
  1042.         VectorGroup(vecgroupid).LastVector = vectorindex
  1043.         GOSUB calculatecom
  1044.     NEXT
  1045.  
  1046. 'Icewall South
  1047. h = 2
  1048. FOR u = -gridsize TO gridsize STEP tilesize
  1049.     FOR v = 0 TO 70 STEP tilesize
  1050.         groupidticker = groupidticker + 1
  1051.         vecgroupid = groupidticker
  1052.         VectorGroup(vecgroupid).Identity = vecgroupid
  1053.         VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  1054.         VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  1055.         VectorGroup(vecgroupid).GroupName = "Icewall South"
  1056.         VectorGroup(vecgroupid).Visible = 0
  1057.         VectorGroup(vecgroupid).COMFixed = 1
  1058.         VectorGroup(vecgroupid).DIMx = tilesize / 2
  1059.         VectorGroup(vecgroupid).DIMy = tilesize / 2
  1060.         VectorGroup(vecgroupid).DIMz = tilesize / 2
  1061.         VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  1062.         FOR i = u TO u + tilesize STEP h
  1063.             FOR j = v TO v + tilesize STEP h
  1064.                 vectorindex = vectorindex + 1
  1065.                 vec3Dpos(vectorindex, 1) = -gridsize
  1066.                 vec3Dpos(vectorindex, 2) = i + RND * h - RND * h
  1067.                 vec3Dpos(vectorindex, 3) = j + RND * h - RND * h
  1068.                 vec3Dvis(vectorindex) = 0
  1069.                 IF RND > .5 THEN
  1070.                     vec3Dcolor(vectorindex) = White
  1071.                 ELSE
  1072.                     vec3Dcolor(vectorindex) = Ivory
  1073.                 END IF
  1074.                 GOSUB integratecom
  1075.             NEXT
  1076.         NEXT
  1077.         VectorGroup(vecgroupid).LastVector = vectorindex
  1078.         GOSUB calculatecom
  1079.     NEXT
  1080.  
  1081. 'Icewall North
  1082. h = 2
  1083. FOR u = -gridsize TO gridsize STEP tilesize
  1084.     FOR v = 0 TO 70 STEP tilesize
  1085.         groupidticker = groupidticker + 1
  1086.         vecgroupid = groupidticker
  1087.         VectorGroup(vecgroupid).Identity = vecgroupid
  1088.         VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  1089.         VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  1090.         VectorGroup(vecgroupid).GroupName = "Icewall North"
  1091.         VectorGroup(vecgroupid).Visible = 0
  1092.         VectorGroup(vecgroupid).COMFixed = 1
  1093.         VectorGroup(vecgroupid).DIMx = tilesize / 2
  1094.         VectorGroup(vecgroupid).DIMy = tilesize / 2
  1095.         VectorGroup(vecgroupid).DIMz = tilesize / 2
  1096.         VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  1097.         FOR i = u TO u + tilesize STEP h
  1098.             FOR j = v TO v + tilesize STEP h
  1099.                 vectorindex = vectorindex + 1
  1100.                 vec3Dpos(vectorindex, 1) = i + RND * h - RND * h
  1101.                 vec3Dpos(vectorindex, 2) = gridsize + tilesize / 2
  1102.                 vec3Dpos(vectorindex, 3) = j + RND * h - RND * h
  1103.                 vec3Dvis(vectorindex) = 0
  1104.                 IF RND > .5 THEN
  1105.                     vec3Dcolor(vectorindex) = White
  1106.                 ELSE
  1107.                     vec3Dcolor(vectorindex) = Ivory
  1108.                 END IF
  1109.                 GOSUB integratecom
  1110.             NEXT
  1111.         NEXT
  1112.         VectorGroup(vecgroupid).LastVector = vectorindex
  1113.         GOSUB calculatecom
  1114.     NEXT
  1115.  
  1116. 'Icewall West
  1117. h = 2
  1118. FOR u = -gridsize TO gridsize STEP tilesize
  1119.     FOR v = 0 TO 70 STEP tilesize
  1120.         groupidticker = groupidticker + 1
  1121.         vecgroupid = groupidticker
  1122.         VectorGroup(vecgroupid).Identity = vecgroupid
  1123.         VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  1124.         VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  1125.         VectorGroup(vecgroupid).GroupName = "Icewall West"
  1126.         VectorGroup(vecgroupid).Visible = 0
  1127.         VectorGroup(vecgroupid).COMFixed = 1
  1128.         VectorGroup(vecgroupid).DIMx = tilesize / 2
  1129.         VectorGroup(vecgroupid).DIMy = tilesize / 2
  1130.         VectorGroup(vecgroupid).DIMz = tilesize / 2
  1131.         VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  1132.         FOR i = u TO u + tilesize STEP h
  1133.             FOR j = v TO v + tilesize STEP h
  1134.                 vectorindex = vectorindex + 1
  1135.                 vec3Dpos(vectorindex, 1) = i + RND * h - RND * h
  1136.                 vec3Dpos(vectorindex, 2) = -gridsize
  1137.                 vec3Dpos(vectorindex, 3) = j + RND * h - RND * h
  1138.                 vec3Dvis(vectorindex) = 0
  1139.                 IF RND > .5 THEN
  1140.                     vec3Dcolor(vectorindex) = White
  1141.                 ELSE
  1142.                     vec3Dcolor(vectorindex) = Ivory
  1143.                 END IF
  1144.                 GOSUB integratecom
  1145.             NEXT
  1146.         NEXT
  1147.         VectorGroup(vecgroupid).LastVector = vectorindex
  1148.         GOSUB calculatecom
  1149.     NEXT
  1150.  
  1151. 'Lake of Fire
  1152. h = 2
  1153. FOR u = -gridsize TO gridsize STEP tilesize
  1154.     FOR v = -gridsize TO gridsize STEP tilesize
  1155.         groupidticker = groupidticker + 1
  1156.         vecgroupid = groupidticker
  1157.         VectorGroup(vecgroupid).Identity = vecgroupid
  1158.         VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  1159.         VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  1160.         VectorGroup(vecgroupid).GroupName = "Lake of Fire"
  1161.         VectorGroup(vecgroupid).Visible = 0
  1162.         VectorGroup(vecgroupid).COMFixed = 1
  1163.         VectorGroup(vecgroupid).DIMx = tilesize / 2
  1164.         VectorGroup(vecgroupid).DIMy = tilesize / 2
  1165.         VectorGroup(vecgroupid).DIMz = tilesize / 2
  1166.         VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  1167.         FOR i = u TO u + tilesize STEP h
  1168.             FOR j = v TO v + tilesize STEP h
  1169.                 vectorindex = vectorindex + 1
  1170.                 vec3Dpos(vectorindex, 1) = i + RND * h - RND * h
  1171.                 vec3Dpos(vectorindex, 2) = j + RND * h - RND * h
  1172.                 vec3Dpos(vectorindex, 3) = -350 - 70 - RND
  1173.                 vec3Dvis(vectorindex) = 0
  1174.                 IF RND > .2 THEN
  1175.                     vec3Dcolor(vectorindex) = Red
  1176.                 ELSE
  1177.                     vec3Dcolor(vectorindex) = Indigo
  1178.                 END IF
  1179.                 GOSUB integratecom
  1180.             NEXT
  1181.         NEXT
  1182.         VectorGroup(vecgroupid).LastVector = vectorindex
  1183.         GOSUB calculatecom
  1184.     NEXT
  1185.  
  1186. 'Megalith
  1187. ctrx = -90
  1188. ctry = -320
  1189. ctrz = 4
  1190. w = 8
  1191. h = 256
  1192. dens = 100
  1193. FOR k = 1 TO h STEP w
  1194.     FOR i = -h / 20 + k / 20 TO h / 20 - k / 20 STEP w
  1195.         FOR j = -h / 20 + k / 20 TO h / 20 - k / 20 STEP w
  1196.             groupidticker = groupidticker + 1
  1197.             vecgroupid = groupidticker
  1198.             VectorGroup(vecgroupid).Identity = vecgroupid
  1199.             VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  1200.             VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  1201.             VectorGroup(vecgroupid).GroupName = "Megalith"
  1202.             VectorGroup(vecgroupid).Visible = 0
  1203.             VectorGroup(vecgroupid).COMFixed = 1
  1204.             VectorGroup(vecgroupid).DIMx = w / 2
  1205.             VectorGroup(vecgroupid).DIMy = w / 2
  1206.             VectorGroup(vecgroupid).DIMz = w / 2
  1207.             VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  1208.             FOR q = 1 TO dens
  1209.                 vectorindex = vectorindex + 1
  1210.                 vec3Dpos(vectorindex, 1) = ctrx + i + (RND - .5) * w
  1211.                 vec3Dpos(vectorindex, 2) = ctry + j + (RND - .5) * w
  1212.                 vec3Dpos(vectorindex, 3) = ctrz + k + (RND - .5) * w
  1213.                 vec3Dvis(vectorindex) = 0
  1214.                 IF RND > .5 THEN
  1215.                     vec3Dcolor(vectorindex) = Cyan
  1216.                 ELSE
  1217.                     vec3Dcolor(vectorindex) = Teal
  1218.                 END IF
  1219.                 GOSUB integratecom
  1220.             NEXT
  1221.             VectorGroup(vecgroupid).LastVector = vectorindex
  1222.             GOSUB calculatecom
  1223.         NEXT
  1224.     NEXT
  1225.  
  1226. 'Pyramid
  1227. ctrx = -90
  1228. ctry = -120
  1229. ctrz = 4
  1230. w = 8
  1231. h = 56
  1232. dens = 50
  1233. FOR k = 1 TO h STEP w
  1234.     FOR i = -h / 2 + k / 2 TO h / 2 - k / 2 STEP w
  1235.         FOR j = -h / 2 + k / 2 TO h / 2 - k / 2 STEP w
  1236.             groupidticker = groupidticker + 1
  1237.             vecgroupid = groupidticker
  1238.             VectorGroup(vecgroupid).Identity = vecgroupid
  1239.             VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  1240.             VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  1241.             VectorGroup(vecgroupid).GroupName = "Pyramid"
  1242.             VectorGroup(vecgroupid).Visible = 0
  1243.             VectorGroup(vecgroupid).COMFixed = 1
  1244.             VectorGroup(vecgroupid).DIMx = tilesize / 2
  1245.             VectorGroup(vecgroupid).DIMy = tilesize / 2
  1246.             VectorGroup(vecgroupid).DIMz = tilesize / 2
  1247.             VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  1248.             FOR q = 1 TO dens
  1249.                 vectorindex = vectorindex + 1
  1250.                 vec3Dpos(vectorindex, 1) = ctrx + i + (RND - .5) * w
  1251.                 vec3Dpos(vectorindex, 2) = ctry + j + (RND - .5) * w
  1252.                 vec3Dpos(vectorindex, 3) = ctrz + k + (RND - .5) * w
  1253.                 vec3Dvis(vectorindex) = 0
  1254.                 IF RND > .5 THEN
  1255.                     vec3Dcolor(vectorindex) = DarkGoldenRod
  1256.                 ELSE
  1257.                     vec3Dcolor(vectorindex) = GoldenRod
  1258.                 END IF
  1259.                 GOSUB integratecom
  1260.             NEXT
  1261.             VectorGroup(vecgroupid).LastVector = vectorindex
  1262.             GOSUB calculatecom
  1263.         NEXT
  1264.     NEXT
  1265.  
  1266. 'Rain
  1267. FOR u = -gridsize TO gridsize STEP tilesize
  1268.     FOR v = -gridsize TO gridsize STEP tilesize
  1269.         groupidticker = groupidticker + 1
  1270.         vecgroupid = groupidticker
  1271.         VectorGroup(vecgroupid).Identity = vecgroupid
  1272.         VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  1273.         VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  1274.         VectorGroup(vecgroupid).GroupName = "Rain"
  1275.         VectorGroup(vecgroupid).Visible = 0
  1276.         VectorGroup(vecgroupid).COMFixed = 1
  1277.         VectorGroup(vecgroupid).DIMx = tilesize / 2
  1278.         VectorGroup(vecgroupid).DIMy = tilesize / 2
  1279.         VectorGroup(vecgroupid).DIMz = 35
  1280.         VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  1281.         FOR i = u TO u + tilesize STEP tilesize '/ 3
  1282.             FOR j = v TO v + tilesize STEP tilesize '/ 3
  1283.                 vectorindex = vectorindex + 1
  1284.                 vec3Dpos(vectorindex, 1) = i + (RND - .5) * tilesize
  1285.                 vec3Dpos(vectorindex, 2) = j + (RND - .5) * tilesize
  1286.                 vec3Dpos(vectorindex, 3) = RND * 70
  1287.                 vec3Dvel(vectorindex, 1) = 0
  1288.                 vec3Dvel(vectorindex, 2) = 0
  1289.                 vec3Dvel(vectorindex, 3) = -400 * RND
  1290.                 vec3Dvis(vectorindex) = 0
  1291.                 IF RND > 5 THEN
  1292.                     vec3Dcolor(vectorindex) = Aquamarine
  1293.                 ELSE
  1294.                     vec3Dcolor(vectorindex) = DodgerBlue
  1295.                 END IF
  1296.                 GOSUB integratecom
  1297.             NEXT
  1298.         NEXT
  1299.         VectorGroup(vecgroupid).LastVector = vectorindex
  1300.         GOSUB calculatecom
  1301.         VectorGroup(vecgroupid).COMz = 35
  1302.     NEXT
  1303.  
  1304. 'Sky
  1305. h = 2
  1306. FOR u = -gridsize TO gridsize STEP tilesize
  1307.     FOR v = -gridsize TO gridsize STEP tilesize
  1308.         groupidticker = groupidticker + 1
  1309.         vecgroupid = groupidticker
  1310.         VectorGroup(vecgroupid).Identity = vecgroupid
  1311.         VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  1312.         VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  1313.         VectorGroup(vecgroupid).GroupName = "Sky"
  1314.         VectorGroup(vecgroupid).Visible = 0
  1315.         VectorGroup(vecgroupid).COMFixed = 1
  1316.         VectorGroup(vecgroupid).DIMx = tilesize / 2
  1317.         VectorGroup(vecgroupid).DIMy = tilesize / 2
  1318.         VectorGroup(vecgroupid).DIMz = 3
  1319.         VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  1320.         FOR i = u TO u + tilesize STEP h
  1321.             FOR j = v TO v + tilesize STEP h
  1322.                 vectorindex = vectorindex + 1
  1323.                 vec3Dpos(vectorindex, 1) = i + (RND - RND) * h
  1324.                 vec3Dpos(vectorindex, 2) = j + (RND - RND) * h
  1325.                 vec3Dpos(vectorindex, 3) = 70 + (RND - RND) * h
  1326.                 vec3Dvel(vectorindex, 1) = (RND - RND) * 2
  1327.                 vec3Dvel(vectorindex, 2) = (RND - RND) * 2
  1328.                 vec3Dvel(vectorindex, 3) = (RND - RND) * 2
  1329.                 vec3Danv(vectorindex, 1) = 0
  1330.                 vec3Danv(vectorindex, 2) = 0
  1331.                 vec3Danv(vectorindex, 3) = 0
  1332.                 vec3Dvis(vectorindex) = 0
  1333.                 IF RND > .5 THEN
  1334.                     vec3Dcolor(vectorindex) = Snow
  1335.                 ELSE
  1336.                     vec3Dcolor(vectorindex) = RoyalBlue
  1337.                 END IF
  1338.                 GOSUB integratecom
  1339.             NEXT
  1340.         NEXT
  1341.         VectorGroup(vecgroupid).LastVector = vectorindex
  1342.         GOSUB calculatecom
  1343.     NEXT
  1344.  
  1345. 'Stars
  1346. h = 5
  1347. FOR w = 1 TO 5
  1348.     FOR u = -gridsize TO gridsize STEP tilesize
  1349.         FOR v = -gridsize TO gridsize STEP tilesize
  1350.             groupidticker = groupidticker + 1
  1351.             vecgroupid = groupidticker
  1352.             VectorGroup(vecgroupid).Identity = vecgroupid
  1353.             VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  1354.             VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  1355.             VectorGroup(vecgroupid).GroupName = "Stars"
  1356.             VectorGroup(vecgroupid).Visible = 0
  1357.             VectorGroup(vecgroupid).COMFixed = 1
  1358.             VectorGroup(vecgroupid).DIMx = tilesize / 2
  1359.             VectorGroup(vecgroupid).DIMy = tilesize / 2
  1360.             VectorGroup(vecgroupid).DIMz = tilesize / 2
  1361.             VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  1362.             FOR i = u TO u + tilesize STEP h
  1363.                 FOR j = v TO v + tilesize STEP h
  1364.                     IF RND > 1 - w / 5 THEN
  1365.                         vectorindex = vectorindex + 1
  1366.                         vec3Dpos(vectorindex, 1) = i + RND * h - RND * h
  1367.                         vec3Dpos(vectorindex, 2) = j + RND * h - RND * h
  1368.                         vec3Dpos(vectorindex, 3) = w * 70 + RND * 70
  1369.                         vec3Dvis(vectorindex) = 0
  1370.                         IF RND > .5 THEN
  1371.                             vec3Dcolor(vectorindex) = GhostWhite
  1372.                         ELSE
  1373.                             IF RND > .5 THEN
  1374.                                 vec3Dcolor(vectorindex) = White
  1375.                             ELSE
  1376.                                 vec3Dcolor(vectorindex) = DarkGray
  1377.                             END IF
  1378.                         END IF
  1379.                         GOSUB integratecom
  1380.                     END IF
  1381.                 NEXT
  1382.             NEXT
  1383.             VectorGroup(vecgroupid).LastVector = vectorindex
  1384.             GOSUB calculatecom
  1385.         NEXT
  1386.     NEXT
  1387.  
  1388. 'Sun
  1389. radius = 10
  1390. dx = .0628
  1391. dy = .0628
  1392. xl = 0: xr = 2 * pi
  1393. yl = 0: yr = pi
  1394. xrange = 1 + INT((-xl + xr) / dx)
  1395. yrange = 1 + INT((-yl + yr) / dy)
  1396. FOR i = 1 TO xrange STEP 10
  1397.     FOR j = 1 TO yrange STEP 10
  1398.         groupidticker = groupidticker + 1
  1399.         vecgroupid = groupidticker
  1400.         VectorGroup(vecgroupid).Identity = vecgroupid
  1401.         VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  1402.         VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  1403.         VectorGroup(vecgroupid).GroupName = "Sun"
  1404.         VectorGroup(vecgroupid).Visible = 0
  1405.         VectorGroup(vecgroupid).COMFixed = 1
  1406.         VectorGroup(vecgroupid).DIMx = radius
  1407.         VectorGroup(vecgroupid).DIMy = radius
  1408.         VectorGroup(vecgroupid).DIMz = radius
  1409.         VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  1410.         FOR u = i TO i + 10 STEP 1
  1411.             FOR v = j TO j + 10 STEP 1
  1412.                 vectorindex = vectorindex + 1
  1413.                 theta = u * dx - dx
  1414.                 phi = v * dy - dy
  1415.                 vec3Dpos(vectorindex, 1) = radius * SIN(phi) * COS(theta)
  1416.                 vec3Dpos(vectorindex, 2) = radius * SIN(phi) * SIN(theta)
  1417.                 vec3Dpos(vectorindex, 3) = 90 + radius * COS(phi)
  1418.                 vec3Dvis(vectorindex) = 0
  1419.                 IF RND > .5 THEN
  1420.                     vec3Dcolor(vectorindex) = Sunglow
  1421.                 ELSE
  1422.                     vec3Dcolor(vectorindex) = SunsetOrange
  1423.                 END IF
  1424.                 GOSUB integratecom
  1425.             NEXT
  1426.         NEXT
  1427.         GOSUB integratecom
  1428.         VectorGroup(vecgroupid).LastVector = vectorindex
  1429.         GOSUB calculatecom
  1430.     NEXT
  1431.  
  1432. 'Moon
  1433. radius = 4
  1434. au = 60
  1435. dx = (2 * pi / radius) * .05
  1436. dy = (2 * pi / radius) * .05
  1437. xl = 0: xr = 2 * pi
  1438. yl = 0: yr = pi
  1439. xrange = 1 + INT((-xl + xr) / dx)
  1440. yrange = 1 + INT((-yl + yr) / dy)
  1441. groupidticker = groupidticker + 1
  1442. vecgroupid = groupidticker
  1443. VectorGroup(vecgroupid).Identity = vecgroupid
  1444. VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  1445. VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  1446. VectorGroup(vecgroupid).GroupName = "Moon"
  1447. VectorGroup(vecgroupid).Visible = 0
  1448. VectorGroup(vecgroupid).ForceAnimate = 1
  1449. VectorGroup(vecgroupid).COMFixed = 0
  1450. VectorGroup(vecgroupid).ROTx = 0
  1451. VectorGroup(vecgroupid).ROTy = 0
  1452. VectorGroup(vecgroupid).ROTz = 90
  1453. VectorGroup(vecgroupid).REVx = 1.5
  1454. VectorGroup(vecgroupid).REVy = 0
  1455. VectorGroup(vecgroupid).REVz = 0
  1456. VectorGroup(vecgroupid).DIMx = 2 * radius + 1
  1457. VectorGroup(vecgroupid).DIMy = 2 * radius + 1
  1458. VectorGroup(vecgroupid).DIMz = 2 * radius + 1
  1459. VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  1460. FOR i = 1 TO xrange
  1461.     FOR j = 1 TO yrange
  1462.         vectorindex = vectorindex + 1
  1463.         theta = i * dx - dx
  1464.         phi = j * dy - dy
  1465.         vec3Dpos(vectorindex, 1) = au + radius * SIN(phi) * COS(theta)
  1466.         vec3Dpos(vectorindex, 2) = radius * SIN(phi) * SIN(theta)
  1467.         vec3Dpos(vectorindex, 3) = 90 + radius * COS(phi)
  1468.         vec3Danv(vectorindex, 1) = 0
  1469.         vec3Danv(vectorindex, 2) = 0
  1470.         vec3Danv(vectorindex, 3) = 1.5
  1471.         vec3Dvis(vectorindex) = 0
  1472.         IF RND > .5 THEN
  1473.             vec3Dcolor(vectorindex) = Gray
  1474.         ELSE
  1475.             vec3Dcolor(vectorindex) = PaleGoldenRod
  1476.         END IF
  1477.         GOSUB integratecom
  1478.         VectorGroup(vecgroupid).LastVector = vectorindex
  1479.         GOSUB calculatecom
  1480.     NEXT
  1481.  
  1482. 'Waves or Particles? (1)
  1483. FOR i = 1 TO 5 STEP 1
  1484.     FOR k = 1 TO 5 STEP 1
  1485.         groupidticker = groupidticker + 1
  1486.         vecgroupid = groupidticker
  1487.         VectorGroup(vecgroupid).Identity = vecgroupid
  1488.         VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  1489.         VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  1490.         VectorGroup(vecgroupid).GroupName = "Waves or Particles?"
  1491.         VectorGroup(vecgroupid).Visible = 0
  1492.         VectorGroup(vecgroupid).COMFixed = 1
  1493.         VectorGroup(vecgroupid).DIMx = 4
  1494.         VectorGroup(vecgroupid).DIMy = 1
  1495.         VectorGroup(vecgroupid).DIMz = 4
  1496.         VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  1497.         FOR u = i TO i + 1 STEP .05
  1498.             FOR v = k TO k + 1 STEP .05
  1499.                 vectorindex = vectorindex + 1
  1500.                 vec3Dpos(vectorindex, 1) = 70 + 7 * u
  1501.                 vec3Dpos(vectorindex, 2) = 80 + 1 * COS((u ^ 2 - v ^ 2))
  1502.                 vec3Dpos(vectorindex, 3) = 10 + 7 * v
  1503.                 vec3Dvis(vectorindex) = 0
  1504.                 IF vec3Dpos(vectorindex, 2) < 80 THEN
  1505.                     vec3Dcolor(vectorindex) = DarkBlue
  1506.                 ELSE
  1507.                     vec3Dcolor(vectorindex) = DeepPink
  1508.                 END IF
  1509.                 GOSUB integratecom
  1510.             NEXT
  1511.         NEXT
  1512.         VectorGroup(vecgroupid).LastVector = vectorindex
  1513.         GOSUB calculatecom
  1514.     NEXT
  1515.  
  1516. 'Waves or Particles? (2)
  1517. FOR i = 1 TO 5 STEP 1
  1518.     FOR k = 1 TO 5 STEP 1
  1519.         groupidticker = groupidticker + 1
  1520.         vecgroupid = groupidticker
  1521.         VectorGroup(vecgroupid).Identity = vecgroupid
  1522.         VectorGroup(vecgroupid).Pointer = vecgroupid + 1
  1523.         VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  1524.         VectorGroup(vecgroupid).GroupName = "Particles or Waves?"
  1525.         VectorGroup(vecgroupid).Visible = 0
  1526.         VectorGroup(vecgroupid).COMFixed = 1
  1527.         VectorGroup(vecgroupid).DIMx = 4
  1528.         VectorGroup(vecgroupid).DIMy = 1
  1529.         VectorGroup(vecgroupid).DIMz = 4
  1530.         VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  1531.         FOR u = i TO i + 1 STEP .05
  1532.             FOR v = k TO k + 1 STEP .05
  1533.                 vectorindex = vectorindex + 1
  1534.                 vec3Dpos(vectorindex, 1) = -7 * u
  1535.                 vec3Dpos(vectorindex, 2) = 80 + 1 * COS(2 * ((u - 7) ^ 2 - (v - 5) ^ 2))
  1536.                 vec3Dpos(vectorindex, 3) = 10 + 7 * v
  1537.                 vec3Dvis(vectorindex) = 0
  1538.                 IF vec3Dpos(vectorindex, 2) < 80 THEN
  1539.                     vec3Dcolor(vectorindex) = Magenta
  1540.                 ELSE
  1541.                     vec3Dcolor(vectorindex) = Chocolate
  1542.                 END IF
  1543.                 GOSUB integratecom
  1544.             NEXT
  1545.         NEXT
  1546.         VectorGroup(vecgroupid).LastVector = vectorindex
  1547.         GOSUB calculatecom
  1548.     NEXT
  1549.  
  1550. '__ZZZ
  1551. groupidticker = groupidticker + 1
  1552. vecgroupid = groupidticker
  1553. VectorGroup(vecgroupid).Identity = vecgroupid
  1554. VectorGroup(vecgroupid).Pointer = -999
  1555. VectorGroup(vecgroupid).Lagger = vecgroupid - 1
  1556. VectorGroup(vecgroupid).GroupName = "__ZZZ"
  1557. VectorGroup(vecgroupid).COMFixed = 1
  1558. VectorGroup(vecgroupid).FirstVector = vectorindex + 1
  1559. FOR r = 1 TO 1
  1560.     vectorindex = vectorindex + 1
  1561.     vec3Dpos(vectorindex, 1) = 0
  1562.     vec3Dpos(vectorindex, 2) = 0
  1563.     vec3Dpos(vectorindex, 3) = -1000
  1564.     vec3Dcolor(vectorindex) = White
  1565.     GOSUB integratecom
  1566. VectorGroup(vecgroupid).LastVector = vectorindex
  1567. GOSUB calculatecom
« Last Edit: August 12, 2019, 07:43:50 AM by STxAxTIC »
An ounce of theory outweighs a pound of code.

Offline TempodiBasic

  • Forum Resident
  • Posts: 1176
Re: On trigless starfields: remember Sanctum?
« Reply #1 on: August 11, 2019, 12:55:23 PM »
pixelcraft!?!
 https://img.youtube.com/vi/X6P9M8IX7qc/hqdefault.jpg
https://i.ytimg.com/vi/BbS5blDdrMI/hqdefault.jpg
It is so intriguing...
well let's build up a daycycle, an AI and Mobs :-))

Does Who follow STxAxTIC steps?
Programming isn't difficult, only it's  consuming time and coffee

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 692
  • Savage.
    • Domum
Re: On trigless starfields: remember Sanctum?
« Reply #2 on: August 11, 2019, 01:42:15 PM »
Thanks TempodiBasic, I shouldn't have been so loose with an obviously-taken name!
An ounce of theory outweighs a pound of code.

Offline SierraKen

  • Forum Resident
  • Posts: 641
    • Ken's Programs
Re: On trigless starfields: remember Sanctum?
« Reply #3 on: August 11, 2019, 04:53:04 PM »
This program is incredible! I made some blocks all around me to make a circle and flew up and down. I think Q or W is down. Thanks for posting this!
Check out my QB64 programs and games I've made here: http://www.KensPrograms.com/

Offline TempodiBasic

  • Forum Resident
  • Posts: 1176
Re: On trigless starfields: remember Sanctum?
« Reply #4 on: August 11, 2019, 06:12:08 PM »
Hi STxAxTIC
if I could suggest and alternative name I guess ExSTxAxTICxCraft  a fusion of Ectasy plus STxATxIC  plus Craft.

PS (please no affirmation about drugs!)
Programming isn't difficult, only it's  consuming time and coffee

Offline Petr

  • Forum Resident
  • Posts: 1190
  • The best code is the DNA of the hops.
Hi StXaXtic,
« Reply #5 on: August 12, 2019, 04:15:59 AM »
Of course I did not give up and I did not end my efforts. I have a finished level editor for my version of the 3D maze, which we talked about with Steve in the 3D MAPTRIANGLE thread. Currently, I have a very primitive 3D object editor that will be inserted into the map through the 3D maze editor before I finish. I have 2 to 3 months left to finish because I don't have much time to do this. Then I will improve my own program for browsing 3D rooms. They are basically currently written three large programs, which cooperate with each other and whose size of the source code already greatly exceeds 100 KB.

This is all based on MAPTRINGLE3D, because OpenGL is not stable with some statements (and this caused 14 days of futile attempts and delays).

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 692
  • Savage.
    • Domum
Re: On trigless starfields: remember Sanctum?
« Reply #6 on: August 12, 2019, 07:42:20 AM »
Morning Petr,

I surely didn't forget that you broke the 3D barrier as well! I once went down the path of textures, maptriangle, underscore commands, and so on - but pulled back for a handful of reasons, including the ones you allude to. I've had more satisfaction staying close to the QB45 core in all my projects, a habit that is fueled by the existential dread that surrounds QB64 - will the next Windows update kill it entirely? etc. - so when the day comes, my code is already that much tighter and closer to being ready for the next language, but I digress.

Do you know where you want to go with your 3D work? Make a Quake clone maybe? Flight simulator? Finish with mazes and call it done?

I'm still deciding what in the world I want this code to do. It's a perfect skeleton for textures if I want, but on the other hand it seems "playable" just as particles. I'm the last person in the world who's going to write a formal "game", so maybe it'll be just an engine forever... iiiiiiddddkkkk man. Ya'll tell me.
« Last Edit: August 12, 2019, 07:50:11 AM by STxAxTIC »
An ounce of theory outweighs a pound of code.