engine2.bas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. 'Engine 2. Started Saturday 1 August 2020
  2. #include "file.bi"
  3. #define SWIDTH 800
  4. #define SHEIGHT 600
  5. #define PPM (76800 / 23) 'Pixels per meter
  6. #define MAX_VERTICES 1000
  7. #define MAX_TRIANGLES 1000
  8. #define MAX_TRACK_OBJECTS 256
  9. #define MAX_MATERIALS 100
  10. #define MAX_ACTIVE_OBJECTS 100
  11. #define PI 3.14159
  12. Type Vector3D
  13. x As Double
  14. y As Double
  15. z As Double
  16. End Type
  17. Type Camera
  18. x As Double
  19. y As Double
  20. z As Double
  21. azm As Double 'Azimuth, Z rotation, first
  22. alt As Double 'Altitude, X rotation, second
  23. bank As Double 'Bank, Y rotation, last
  24. End Type
  25. Type TrackObject
  26. fvertex As Short
  27. vertices As Short
  28. ftriangle As Short
  29. triangles As Short
  30. End Type
  31. Type Triangle
  32. p(1 To 3) As Short
  33. col As ULong
  34. twosided As Byte
  35. textured As Byte
  36. priority As Byte
  37. End Type
  38. Type Material
  39. mname As String
  40. col As ULong
  41. twosided As Byte
  42. textured As Byte
  43. priority As Byte
  44. End Type
  45. Type ActiveObject
  46. x As Double 'Centre X, Y and Z
  47. y As Double
  48. z As Double
  49. d As Double 'Distance to camera: used during rendering
  50. rot As Double 'Rotation in Z
  51. kind As Short 'Object type
  52. End Type
  53. 'Pool of vertices, triangles, objects and materials
  54. Dim Shared pv(1 To MAX_VERTICES) As Vector3D, pvs As Short
  55. Dim Shared pt(1 To MAX_TRIANGLES) As Triangle, pts As Short
  56. Dim Shared tob(1 To MAX_TRACK_OBJECTS) As TrackObject, tobs As Short
  57. Dim Shared mat(1 To MAX_MATERIALS) As Material, mats As Short
  58. Dim Shared aob(1 To MAX_ACTIVE_OBJECTS) As ActiveObject, aobs As Short
  59. 'Working vertices and triangles (currently working object)
  60. Dim Shared wv(1 To 500) As Vector3D, wvs As Short
  61. Dim Shared wt(1 To 500) As Triangle, wts As Short
  62. Dim Shared cam As Camera, visibility As Short = 1200
  63. Dim Shared As Double SMWIDTH, SMHEIGHT, DTS = .6, CLIP_DISTANCE = .6
  64. 'Convert to screen/window coordinates
  65. Sub Screenise
  66. For i As Short = 1 To wvs
  67. wv(i).x = wv(i).x * PPM + SWIDTH / 2
  68. wv(i).z = SHEIGHT / 2 - wv(i).z * PPM
  69. Swap wv(i).y, wv(i).z
  70. Next i
  71. End Sub
  72. 'Load an object from the object pool as the working object
  73. Sub TakeObject (n As Short)
  74. Dim i As Short
  75. wvs = tob(n).vertices
  76. For i = tob(n).fvertex To tob(n).fvertex + tob(n).vertices - 1
  77. wv(i - tob(n).fvertex + 1) = pv(i)
  78. Next i
  79. wts = tob(n).triangles
  80. For i = tob(n).ftriangle To tob(n).ftriangle + tob(n).triangles - 1
  81. wt(i - tob(n).ftriangle + 1) = pt(i)
  82. Next i
  83. End Sub
  84. 'Move working object
  85. Sub MoveObject (dx As Double, dy As Double, dz As Double)
  86. For i As Short = 1 To wvs
  87. wv(i).x += dx
  88. wv(i).y += dy
  89. wv(i).z += dz
  90. Next i
  91. End Sub
  92. Sub RotateX (angle As Double)
  93. Dim v As Vector3D
  94. For i As Short = 1 To wvs
  95. v = wv(i)
  96. wv(i).y = v.y * Cos(angle) - v.z * Sin(angle)
  97. wv(i).z = v.y * Sin(angle) + v.z * Cos(angle)
  98. Next i
  99. End Sub
  100. Sub RotateY (angle As Double)
  101. Dim v As Vector3D
  102. For i As Short = 1 To wvs
  103. v = wv(i)
  104. wv(i).x = v.x * Cos(angle) + v.z * Sin(angle)
  105. wv(i).z = -v.x * Sin(angle) + v.z * Cos(angle)
  106. Next i
  107. End Sub
  108. Sub RotateZ (angle As Double)
  109. Dim v As Vector3D
  110. For i As Short = 1 To wvs
  111. v = wv(i)
  112. wv(i).x = v.x * Cos(angle) + v.y * Sin(angle)
  113. wv(i).y = -v.x * Sin(angle) + v.y * Cos(angle)
  114. Next i
  115. End Sub
  116. 'Apply perspective to working object's X and Z coordinates over Y
  117. Sub ApplyPerspective
  118. For i As Short = 1 To wvs
  119. If wv(i).y > .05 Then
  120. wv(i).x = DTS * wv(i).x / wv(i).y
  121. wv(i).z = DTS * wv(i).z / wv(i).y
  122. End If
  123. Next i
  124. End Sub
  125. Sub LoadMaterials (mlib As String)
  126. Dim f As Integer, s As String, n As Short, c As String
  127. f = FreeFile
  128. Open mlib + ".mtl" For Input As f
  129. While Not EoF(f)
  130. Line Input #f, s
  131. n = InStr(s, " ")
  132. If n Then
  133. c = Left(s, n - 1)
  134. s = Trim(Mid(s, n + 1))
  135. Else
  136. c = s
  137. s = ""
  138. End If
  139. Select Case c
  140. Case "newmtl"
  141. mats += 1
  142. mat(mats).mname = s
  143. mat(mats).priority = 0
  144. mat(mats).twosided = 0
  145. Case "Kd"
  146. Dim As ULong r, g, b
  147. r = 255 * Val(s)
  148. s = Mid(s, InStr(s, " ") + 1)
  149. g = 255 * Val(s)
  150. s = Mid(s, InStr(s, " ") + 1)
  151. b = 255 * Val(s)
  152. mat(mats).col = RGB(r, g, b)
  153. Case "d"
  154. If Val(s) = 1 Then
  155. mat(mats).textured = 0
  156. Else
  157. mat(mats).textured = -1
  158. End If
  159. Case "#p" 'Priority is a made-up property
  160. mat(mats).priority = -1
  161. Case "#2s" 'Two-sided is a made-up property
  162. mat(mats).twosided = -1
  163. End Select
  164. Wend
  165. Close f
  166. End Sub
  167. Sub LoadObj (oname As String)
  168. Dim f As Integer, s As String, n As Short, c As String
  169. Dim curmat As Short = 1
  170. f = FreeFile
  171. Open oname + ".obj" For Input As f
  172. tobs += 1
  173. tob(tobs).fvertex = pvs + 1
  174. tob(tobs).vertices = 0
  175. tob(tobs).ftriangle = pts + 1
  176. tob(tobs).triangles = 0
  177. While Not EoF(f)
  178. Line Input #f, s
  179. n = InStr(s, " ")
  180. If n Then
  181. c = Left(s, n - 1)
  182. s = Trim(Mid(s, n + 1))
  183. Else
  184. c = s
  185. s = ""
  186. End If
  187. Select Case c
  188. Case "v" 'Add vertex to the pool
  189. pvs += 1
  190. tob(tobs).vertices += 1
  191. 'For some weird reason, Blender saves Y and Z swapped
  192. 'when exporting OBJ. So we're undoing that here
  193. pv(pvs).x = Val(s)
  194. s = Mid(s, InStr(s, " ") + 1)
  195. pv(pvs).z = Val(s)
  196. s = Mid(s, InStr(s, " ") + 1)
  197. pv(pvs).y = Val(s)
  198. Case "f"
  199. Dim As Short a, b, c
  200. a = ValInt(s)
  201. s = Mid(s, InStr(s, " ") + 1)
  202. b = ValInt(s)
  203. s = Mid(s, InStr(s, " ") + 1)
  204. c = ValInt(s)
  205. 'If the polygon is not a triangle, decompose
  206. 'in triangles using first vertex as pivot. This
  207. 'will only work if the polygon is convex!
  208. Do
  209. pts += 1
  210. tob(tobs).triangles += 1
  211. pt(pts).col = mat(curmat).col
  212. pt(pts).priority = mat(curmat).priority
  213. pt(pts).textured = mat(curmat).textured
  214. pt(pts).p(1) = a '+ tob(tobs).ftriangle - 1
  215. pt(pts).p(2) = b '+ tob(tobs).ftriangle - 1
  216. pt(pts).p(3) = c '+ tob(tobs).ftriangle - 1
  217. If InStr(s, " ") = 0 Then Exit Do
  218. b = c
  219. s = Mid(s, InStr(s, " ") + 1)
  220. c = ValInt(s)
  221. Loop
  222. Case "usemtl"
  223. For i As Short = 1 To mats
  224. If mat(i).mname = s Then
  225. curmat = i
  226. Exit For
  227. End If
  228. Next i
  229. End Select
  230. Wend
  231. Close f
  232. End Sub
  233. Sub drawtriangle(ByVal x1 As Short, ByVal y1 As Short, _
  234. ByVal x2 As Short, ByVal y2 As Short, _
  235. ByVal x3 As Short, ByVal y3 As Short, col As ULong)
  236. 'STEPS TO FOLLOW:
  237. 'Step 1: Sort point by Y
  238. 'Step 2: Drop all triangles out of Y bounds
  239. 'Step 3: Classify as top, bottom or mixed
  240. 'Step 4: If mixed, split the triangle and call the sub twice and exit
  241. 'Step 5: Obtain initial Y and X1 and X2 for first line, plus deltas
  242. 'Step 6: Apply deltas till Y is onscreen
  243. 'Step 7: Draw lines till triangle is complete or out of screen
  244. Dim currenty As Long
  245. Dim As Long deltaxi, deltaxf, currentxi, currentxf
  246. 'Step 1: Sort point by Y
  247. If y1 > y2 Then Swap y1, y2 : Swap x1, x2
  248. If y2 > y3 Then Swap y2, y3 : Swap x2, x3
  249. If y1 > y2 Then Swap y1, y2 : Swap x1, x2
  250. 'Step 2: Drop all triangles out of Y bounds
  251. If y3 < 0 Or y1 >= SHEIGHT Then Exit Sub
  252. 'Step 3: Classify as top, bottom or mixed
  253. If y1 = y2 AndAlso y2 = y3 Then
  254. 'Just a horizontal line
  255. '... not drawing anything so far
  256. ElseIf y2 = y3 Then 'Top
  257. 'Step 5: Obtain initial Y and X1 and X2 for first line, plus deltas
  258. If x2 > x3 Then Swap x2, x3 : Swap y2, y3 'Sort by X
  259. currenty = y1
  260. currentxi = x1 ShL 8 : currentxf = x1 ShL 8
  261. deltaxi = ((x2 - x1) ShL 8) \ (y2 - y1) 'Add some precision
  262. deltaxf = ((x3 - x1) ShL 8) \ (y3 - y1)
  263. ElseIf y1 = y2 Then 'Bottom
  264. 'Step 5: Obtain initial Y and X1 and X2 for first line, plus deltas
  265. If x1 > x2 Then Swap x1, x2 : Swap y1, y2 'Sort by X
  266. currenty = y1
  267. currentxi = x1 ShL 8 : currentxf = x2 ShL 8
  268. deltaxi = ((x3 - x1) ShL 8) \ (y3 - y1) 'Add some precision
  269. deltaxf = ((x3 - x2) ShL 8) \ (y3 - y2)
  270. Else 'Mixed
  271. 'Step 4: If mixed, split the triangle and call the sub twice and exit
  272. Dim otherx As Short
  273. otherx = (y2 - y1) * (x3 - x1) \ (y3 - y1) + x1
  274. drawtriangle x1, y1, x2, y2, otherx, y2, col
  275. drawtriangle x2, y2, otherx, y2, x3, y3, col
  276. Exit Sub
  277. End If
  278. 'Step 6: Apply deltas till Y is onscreen
  279. If currenty < 0 Then
  280. currentxi += Abs(currenty) * deltaxi
  281. currentxf += Abs(currenty) * deltaxf
  282. currenty = 0
  283. End If
  284. 'Step 7: Draw lines till triangle is complete or out of screen
  285. Dim As Short tempxi, tempxf
  286. Do
  287. 'Only draw if onscreen
  288. If currentxf >= 0 And (currentxi ShR 8) < SWIDTH Then
  289. 'Clip the line
  290. If currentxi >= 0 Then tempxi = currentxi ShR 8 Else tempxi = 0
  291. If (currentxf ShR 8) < SWIDTH Then tempxf = currentxf ShR 8 Else tempxf = SWIDTH - 1
  292. 'Draw it
  293. If tempxi <> 0 Or tempxf <> 0 Then _ 'Don't know why this IF is necessary to avoid a horrible vertical line
  294. Line (tempxi, currenty)-(tempxf, currenty), col
  295. End If
  296. 'If triangle is done or we go offscreen, then exit
  297. If currenty >= y3 OrElse currenty >= SHEIGHT - 1 Then Exit Do
  298. 'Update coordinates
  299. currentxi += deltaxi
  300. currentxf += deltaxf
  301. currenty += 1
  302. Loop
  303. End Sub
  304. Sub SortTriangles
  305. Dim As Short i, j
  306. Dim tz(1 To wts) As Double
  307. For i = 1 To wts
  308. tz(i) = wv(wt(i).p(1)).z + wv(wt(i).p(2)).z + wv(wt(i).p(3)).z
  309. Next i
  310. Dim farthest As Short, fdistance As Double
  311. For i = 1 To wts - 1
  312. fdistance = 0
  313. For j = i To wts
  314. If tz(j) > fdistance Then
  315. fdistance = tz(j)
  316. farthest = j
  317. End If
  318. Next j
  319. If farthest <> i Then
  320. Swap wt(farthest), wt(i)
  321. Swap tz(farthest), tz(i)
  322. End If
  323. Next i
  324. End Sub
  325. Function TFront(t As Triangle) As Boolean
  326. Dim As Double r, r2
  327. 'This works fine, but unless the operation is performed
  328. 'AFTER perspective was applied, the result will look
  329. 'awkward.
  330. r = wv(t.p(1)).x * wv(t.p(2)).y
  331. r += wv(t.p(2)).x * wv(t.p(3)).y
  332. r += wv(t.p(3)).x * wv(t.p(1)).y
  333. r2 = wv(t.p(2)).x * wv(t.p(1)).y
  334. r2 += wv(t.p(3)).x * wv(t.p(2)).y
  335. r2 += wv(t.p(1)).x * wv(t.p(3)).y
  336. Return r > r2
  337. End Function
  338. Sub DrawObject
  339. For i As Short = 1 To wts
  340. If TFront(wt(i)) Then
  341. drawtriangle wv(wt(i).p(1)).x, wv(wt(i).p(1)).y, _
  342. wv(wt(i).p(2)).x, wv(wt(i).p(2)).y, _
  343. wv(wt(i).p(3)).x, wv(wt(i).p(3)).y, wt(i).col
  344. End If
  345. Next i
  346. End Sub
  347. Sub ClipTriangles
  348. Dim As Short i, n
  349. Dim isok(1 To 3) As Byte, areok As Byte
  350. n = 1
  351. Do
  352. areok = 0
  353. For i = 1 To 3
  354. isok(i) = (wv(wt(n).p(i)).y >= CLIP_DISTANCE)
  355. If isok(i) Then areok += 1
  356. Next i
  357. Select Case areok
  358. Case 3
  359. 'Good boy! Keep this triangle as is. Next triangle
  360. n += 1
  361. Case 0
  362. 'Don't draw this triangle. It's behind the fustrum
  363. Swap wt(n), wt(wts)
  364. wts -= 1
  365. Case 1
  366. 'Only one good vertex. Transform the other two
  367. Dim temp As Short
  368. 'First, reorder so that point 1 is the good one
  369. If isok(2) Then
  370. temp = wt(n).p(1)
  371. wt(n).p(1) = wt(n).p(2)
  372. wt(n).p(2) = wt(n).p(3)
  373. wt(n).p(3) = temp
  374. ElseIf isok(3) Then
  375. temp = wt(n).p(1)
  376. wt(n).p(1) = wt(n).p(3)
  377. wt(n).p(3) = wt(n).p(2)
  378. wt(n).p(2) = temp
  379. End If
  380. Dim a As Double
  381. 'Create the two new points
  382. a = (CLIP_DISTANCE - wv(wt(n).p(1)).y) / (wv(wt(n).p(2)).y - wv(wt(n).p(1)).y)
  383. wvs += 1
  384. wv(wvs).x = a * (wv(wt(n).p(2)).x - wv(wt(n).p(1)).x) + wv(wt(n).p(1)).x
  385. wv(wvs).y = CLIP_DISTANCE
  386. wv(wvs).z = a * (wv(wt(n).p(2)).z - wv(wt(n).p(1)).z) + wv(wt(n).p(1)).z
  387. a = (CLIP_DISTANCE - wv(wt(n).p(1)).y) / (wv(wt(n).p(3)).y - wv(wt(n).p(1)).y)
  388. wvs += 1
  389. wv(wvs).x = a * (wv(wt(n).p(3)).x - wv(wt(n).p(1)).x) + wv(wt(n).p(1)).x
  390. wv(wvs).y = CLIP_DISTANCE
  391. wv(wvs).z = a * (wv(wt(n).p(3)).z - wv(wt(n).p(1)).z) + wv(wt(n).p(1)).z
  392. 'Replace points 2 and 3
  393. wt(n).p(2) = wvs - 1
  394. wt(n).p(3) = wvs
  395. n += 1
  396. Case 2
  397. 'Two vertices are OK. We need to split the triangle
  398. Dim temp As Short
  399. 'First, reorder so that point 1 is the bad one
  400. If Not isok(2) Then
  401. temp = wt(n).p(1)
  402. wt(n).p(1) = wt(n).p(2)
  403. wt(n).p(2) = wt(n).p(3)
  404. wt(n).p(3) = temp
  405. ElseIf Not isok(3) Then
  406. temp = wt(n).p(1)
  407. wt(n).p(1) = wt(n).p(3)
  408. wt(n).p(3) = wt(n).p(2)
  409. wt(n).p(2) = temp
  410. End If
  411. Dim a As Double
  412. 'Create the two new points
  413. a = (CLIP_DISTANCE - wv(wt(n).p(1)).y) / (wv(wt(n).p(2)).y - wv(wt(n).p(1)).y)
  414. wvs += 1
  415. wv(wvs).x = a * (wv(wt(n).p(2)).x - wv(wt(n).p(1)).x) + wv(wt(n).p(1)).x
  416. wv(wvs).y = CLIP_DISTANCE
  417. wv(wvs).z = a * (wv(wt(n).p(2)).z - wv(wt(n).p(1)).z) + wv(wt(n).p(1)).z
  418. a = (CLIP_DISTANCE - wv(wt(n).p(1)).y) / (wv(wt(n).p(3)).y - wv(wt(n).p(1)).y)
  419. wvs += 1
  420. wv(wvs).x = a * (wv(wt(n).p(3)).x - wv(wt(n).p(1)).x) + wv(wt(n).p(1)).x
  421. wv(wvs).y = CLIP_DISTANCE
  422. wv(wvs).z = a * (wv(wt(n).p(3)).z - wv(wt(n).p(1)).z) + wv(wt(n).p(1)).z
  423. 'Update point 1 of current triangle
  424. wt(n).p(1) = wvs - 1
  425. 'Create new triangle and assign the points
  426. wts += 1
  427. wt(wts).p(1) = wvs
  428. wt(wts).p(2) = wvs - 1
  429. wt(wts).p(3) = wt(n).p(3)
  430. 'Skip the newly created triangle
  431. Swap wt(n + 1), wt(wts)
  432. n += 2
  433. End Select
  434. Loop Until n > wts
  435. End Sub
  436. Sub ParseConfig
  437. Dim f As Integer, s As String, c As String, n As Short
  438. Dim ar(1 To 10) As String
  439. If Not FileExists("engine2.cfg") Then Exit Sub
  440. f = FreeFile
  441. Open "engine2.cfg" For Input As f
  442. While Not EoF(f)
  443. Line Input #f, s
  444. n = InStr(s, "#")
  445. If n Then s = Left(s, n - 1)
  446. s = Trim(s)
  447. n = InStr(s, " ")
  448. If n Then
  449. c = RTrim(Left(s, n - 1))
  450. s = LTrim(Mid(s, n + 1))
  451. Else
  452. c = s
  453. s = ""
  454. End If
  455. For i As Short = 1 To 10
  456. n = InStr(s, ",")
  457. If n Then
  458. ar(i) = RTrim(Left(s, n - 1))
  459. s = LTrim(Mid(s, n + 1))
  460. Else
  461. ar(i) = s
  462. Exit For
  463. End If
  464. Next i
  465. Select Case LCase(c)
  466. Case "lm", "mat", "m" : LoadMaterials ar(1)
  467. Case "lo", "obj", "o" : LoadObj ar(1)
  468. Case "place", "+" 'place numobj,x,y,z,rot
  469. aobs += 1
  470. aob(aobs).kind = ValInt(ar(1))
  471. aob(aobs).x = Val(ar(2))
  472. aob(aobs).y = Val(ar(3))
  473. aob(aobs).z = Val(ar(4))
  474. aob(aobs).rot = Val(ar(5))
  475. Case "camera", "cam", "c" 'camera x,y,z,azimuth,altitude,bank
  476. cam.x = Val(ar(1))
  477. cam.y = Val(ar(2))
  478. cam.z = Val(ar(3))
  479. cam.azm = Val(ar(4))
  480. cam.alt = Val(ar(5))
  481. cam.bank = Val(ar(6))
  482. End Select
  483. Wend
  484. Close f
  485. End Sub
  486. Sub SortActiveObjects
  487. 'Calculate taxicab distances
  488. For i As Short = 1 To aobs
  489. aob(i).d = Abs(aob(i).x - cam.x) + Abs(aob(i).y - cam.y) + Abs(aob(i).z - cam.z)
  490. Next i
  491. 'Sort
  492. For i As Short = 1 To aobs
  493. Dim max As Double, who As Short
  494. max = 0 : who = i
  495. For j As Short = i To aobs
  496. If aob(j).d > max Then
  497. max = aob(j).d
  498. who = j
  499. End If
  500. Next j
  501. If who <> i Then Swap aob(i), aob(who)
  502. Next i
  503. End Sub
  504. Sub Render
  505. SortActiveObjects
  506. ScreenLock
  507. CLS
  508. For i As Short = 1 To aobs
  509. If aob(i).d <= visibility Then
  510. TakeObject aob(i).kind
  511. RotateZ aob(i).rot
  512. MoveObject aob(i).x - cam.x, aob(i).y - cam.y, aob(i).z - cam.z
  513. 'These three can be packed in one matrix multiplication
  514. RotateZ -cam.azm
  515. RotateX -cam.alt
  516. RotateY -cam.bank
  517. ClipTriangles
  518. ApplyPerspective
  519. Screenise
  520. SortTriangles
  521. DrawObject
  522. End If
  523. Next i
  524. ScreenUnlock
  525. End Sub
  526. SMWIDTH = SWIDTH / PPM
  527. SMHEIGHT = SHEIGHT / PPM
  528. ScreenRes SWIDTH, SHEIGHT, 32
  529. WindowTitle "StuntsLegacyEngine v0.2"
  530. ParseConfig
  531. Dim t As Double, theta As Double, phi As Double
  532. Dim akey As String, dist As Double, debug As Byte
  533. Dim speed As Short
  534. t = Timer
  535. Do
  536. Render
  537. If debug Then
  538. Locate 1, 1
  539. Print Using "(####.###_, ####.###_, ####.###)"; cam.x; cam.y; cam.z
  540. Print Using "az=#### pt=#### bk=####"; cam.azm * 180 / PI; cam.alt * 180 / PI; cam.bank * 180 / PI
  541. Print "Dist. to screen: "; DTS;
  542. End If
  543. Do : Loop Until Timer >= t + .01
  544. t = Timer
  545. If MultiKey(&H2A) Then 'Shift
  546. speed = 1
  547. Else
  548. speed = 3
  549. End If
  550. If MultiKey(&H11) Then 'W
  551. cam.x += 2 * Sin(cam.azm) * speed
  552. cam.y += 2 * Cos(cam.azm) * speed
  553. End If
  554. If MultiKey(&H1F) Then 'S
  555. cam.x -= 2 * Sin(cam.azm) * speed
  556. cam.y -= 2 * Cos(cam.azm) * speed
  557. End If
  558. If MultiKey(&H1E) Then 'A
  559. cam.x -= 1 * Cos(cam.azm) * speed
  560. cam.y += 1 * Sin(cam.azm) * speed
  561. End If
  562. If MultiKey(&H20) Then 'D
  563. cam.x += 1 * Cos(cam.azm) * speed
  564. cam.y -= 1 * Sin(cam.azm) * speed
  565. End If
  566. If MultiKey(72) Then 'Up
  567. cam.alt -= .002 * speed
  568. If cam.alt <= -PI Then cam.alt += 2 * PI
  569. End If
  570. If MultiKey(80) Then 'Down
  571. cam.alt += .002 * speed
  572. If cam.alt >= PI Then cam.alt -= 2 * PI
  573. End If
  574. If MultiKey(77) Then 'Right
  575. cam.azm += .002 * speed
  576. If cam.azm >= PI Then cam.azm -= 2 * PI
  577. End If
  578. If MultiKey(75) Then 'Left
  579. cam.azm -= .002 * speed
  580. If cam.azm <= -PI Then cam.azm += 2 * PI
  581. End If
  582. If MultiKey(73) Then 'PgUp
  583. cam.z += .4 * speed
  584. End If
  585. If MultiKey(81) Then 'PgDn
  586. cam.z -= .4 * speed
  587. End If
  588. akey = InKey
  589. Select Case akey
  590. Case "["
  591. If DTS > .1 Then DTS /= 1.4142
  592. Case "]"
  593. If DTS < 20 Then DTS *= 1.4142
  594. Case Chr(4) 'CTRL+D - Debug
  595. debug = Not debug
  596. Case Chr(27) : Exit Do
  597. End Select
  598. Loop