Author Topic: Ray-Tracing Engine by Zom-B  (Read 2347 times)

Offline The Librarian

  • Moderator
Ray-Tracing Engine by Zom-B
« on: March 06, 2018, 09:17:41 PM »
Ray-Tracing Engine

Author: Zom-B
Source: qb64.net Forum
URL: http://www.qb64.net/forum/index.php?topic=1145.0
Version: 2010
Tags: [3d], [raytrace]

Description:
This is a ray tracer I've been working on for the past 6 years. Well, on and off of course :) It's still a beta version. 43Kb. Bet this won't run in QB45.

Source Code:
Code: QB64 [Select]
  1. '> Merged with Zom-B's smart $include merger 0.51
  2.  
  3. ' Best viewed with 120 or more columns
  4.  
  5. DEFDBL A-Z
  6.  
  7. '####################################################################################################################
  8. '# Math Library V1.0 (include)
  9. '# By Zom-B
  10. '####################################################################################################################
  11.  
  12. CONST sqrt2 = 1.41421356237309504880168872420969807856967187537695 ' Knuth01
  13. CONST sqrt3 = 1.73205080756887729352744634150587236694280525381038 ' Knuth02
  14. CONST sqrt5 = 2.23606797749978969640917366873127623544061835961153 ' Knuth03
  15. CONST sqrt10 = 3.16227766016837933199889354443271853371955513932522 ' Knuth04
  16. CONST cubert2 = 1.25992104989487316476721060727822835057025146470151 ' Knuth05
  17. CONST cubert3 = 1.44224957030740838232163831078010958839186925349935 ' Knuth06
  18. CONST q2pow025 = 1.18920711500272106671749997056047591529297209246382 ' Knuth07
  19. CONST phi = 1.61803398874989484820458683436563811772030917980576 ' Knuth08
  20. CONST log2 = 0.69314718055994530941723212145817656807550013436026 ' Knuth09
  21. CONST log3 = 1.09861228866810969139524523692252570464749055782275 ' Knuth10
  22. CONST log10 = 2.30258509299404568401799145468436420760110148862877 ' Knuth11
  23. CONST logpi = 1.14472988584940017414342735135305871164729481291531 ' Knuth12
  24. CONST logphi = 0.48121182505960344749775891342436842313518433438566 ' Knuth13
  25. CONST q1log2 = 1.44269504088896340735992468100189213742664595415299 ' Knuth14
  26. CONST q1log10 = 0.43429448190325182765112891891660508229439700580367 ' Knuth15
  27. CONST q1logphi = 2.07808692123502753760132260611779576774219226778328 ' Knuth16
  28. CONST pi = 3.14159265358979323846264338327950288419716939937511 ' Knuth17
  29. CONST deg2rad = 0.01745329251994329576923690768488612713442871888542 ' Knuth18
  30. CONST q1pi = 0.31830988618379067153776752674502872406891929148091 ' Knuth19
  31. CONST pisqr = 9.86960440108935861883449099987615113531369940724079 ' Knuth20
  32. CONST gamma05 = 1.7724538509055160272981674833411451827975494561224 '  Knuth21
  33. CONST gamma033 = 2.6789385347077476336556929409746776441286893779573 '  Knuth22
  34. CONST gamma067 = 1.3541179394264004169452880281545137855193272660568 '  Knuth23
  35. CONST e = 2.71828182845904523536028747135266249775724709369996 ' Knuth24
  36. CONST q1e = 0.36787944117144232159552377016146086744581113103177 ' Knuth25
  37. CONST esqr = 7.38905609893065022723042746057500781318031557055185 ' Knuth26
  38. CONST eulergamma = 0.57721566490153286060651209008240243104215933593992 ' Knuth27
  39. CONST expeulergamma = 1.7810724179901979852365041031071795491696452143034 '  Knuth28
  40. CONST exppi025 = 2.19328005073801545655976965927873822346163764199427 ' Knuth29
  41. CONST sin1 = 0.84147098480789650665250232163029899962256306079837 ' Knuth30
  42. CONST cos1 = 0.54030230586813971740093660744297660373231042061792 ' Knuth31
  43. CONST zeta3 = 1.2020569031595942853997381615114499907649862923405 '  Knuth32
  44. CONST nloglog2 = 0.36651292058166432701243915823266946945426344783711 ' Knuth33
  45.  
  46. CONST logr10 = 0.43429448190325182765112891891660508229439700580367
  47. CONST logr2 = 1.44269504088896340735992468100189213742664595415299
  48. CONST pi05 = 1.57079632679489661923132169163975144209858469968755
  49. CONST pi2 = 6.28318530717958647692528676655900576839433879875021
  50. CONST q05log10 = 0.21714724095162591382556445945830254114719850290183
  51. CONST q05log2 = 0.72134752044448170367996234050094606871332297707649
  52. CONST q05pi = 0.15915494309189533576888376337251436203445964574046
  53. CONST q13 = 0.33333333333333333333333333333333333333333333333333
  54. CONST q16 = 0.16666666666666666666666666666666666666666666666667
  55. CONST q2pi = 0.63661977236758134307553505349005744813783858296183
  56. CONST q2sqrt5 = 0.89442719099991587856366946749251049417624734384461
  57. CONST rad2deg = 57.2957795130823208767981548141051703324054724665643
  58. CONST sqrt02 = 0.44721359549995793928183473374625524708812367192231
  59. CONST sqrt05 = 0.70710678118654752440084436210484903928483593768847
  60. CONST sqrt075 = 0.86602540378443864676372317075293618347140262690519
  61. CONST y2q112 = 1.05946309435929526456182529494634170077920431749419 ' Chromatic base
  62.  
  63. '####################################################################################################################
  64. '# Vector math library v0.1 (include part)
  65. '# By Zom-B
  66. '####################################################################################################################
  67.  
  68. TYPE VECTOR
  69.     x AS DOUBLE
  70.     y AS DOUBLE
  71.     z AS DOUBLE
  72.  
  73. '####################################################################################################################
  74. '# Screen mode selector v1.0 (include)
  75. '# By Zom-B
  76. '####################################################################################################################
  77.  
  78. videoaspect:
  79. DATA "all aspect",15
  80. DATA "4:3",11
  81. DATA "16:10",10
  82. DATA "16:9",14
  83. DATA "5:4",13
  84. DATA "3:2",12
  85. DATA "5:3",9
  86. DATA "1:1",7
  87. DATA "other",8
  88.  
  89. videomodes:
  90. DATA 256,256,7
  91. DATA 320,240,1
  92. DATA 400,300,1
  93. DATA 512,384,1
  94. DATA 512,512,7
  95. DATA 640,480,1
  96. DATA 720,540,1
  97. DATA 768,576,1
  98. DATA 800,480,2
  99. DATA 800,600,1
  100. DATA 854,480,3
  101. DATA 1024,600,8
  102. DATA 1024,640,2
  103. DATA 1024,768,1
  104. DATA 1024,1024,7
  105. DATA 1152,768,5
  106. DATA 1152,864,1
  107. DATA 1280,720,3
  108. DATA 1280,768,6
  109. DATA 1280,800,2
  110. DATA 1280,854,5
  111. DATA 1280,960,1
  112. DATA 1280,1024,4
  113. DATA 1366,768,3
  114. DATA 1400,1050,1
  115. DATA 1440,900,2
  116. DATA 1440,960,5
  117. DATA 1600,900,3
  118. DATA 1600,1200,1
  119. DATA 1680,1050,2
  120. DATA 1920,1080,3
  121. DATA 1920,1200,2
  122. DATA 2048,1152,3
  123. DATA 2048,1536,1
  124. DATA 2048,2048,7
  125. DATA ,,
  126.  
  127.  
  128. '####################################################################################################################
  129. '# Ray Tracer (Beta version)
  130. '# By Zom-B
  131. '####################################################################################################################
  132.  
  133. CONST Doantialias = -1
  134. CONST Usegaussian = 0
  135.  
  136. CONST FLOOR = 1
  137. CONST SPHERE = 2
  138.  
  139. TYPE TEXTURE
  140.     image AS LONG
  141.     w AS INTEGER
  142.     h AS INTEGER
  143.     scaleU AS SINGLE
  144.     scaleV AS SINGLE
  145.     offsetU AS SINGLE
  146.     offsetV AS SINGLE
  147.     bumpfactor AS SINGLE
  148.  
  149. DIM SHARED sizeX%, sizeY%
  150. DIM SHARED maxX%, maxY%
  151. DIM SHARED halfX%, halfY%
  152.  
  153. DIM SHARED texture&(4)
  154.  
  155. DIM SHARED camPos AS VECTOR
  156. DIM SHARED camDir AS VECTOR
  157. DIM SHARED camUp AS VECTOR
  158. DIM SHARED camRight AS VECTOR
  159.  
  160. 'Speed required with these variables, so not using TYPEs here
  161. DIM SHARED objectType%(7) '                                 Object type
  162. DIM SHARED positionX(7), positionY(7), positionZ(7) '       Object position
  163. DIM SHARED size(7) '                                        Radius (in case of a sphere)
  164. DIM SHARED colorR!(7), colorG!(7), colorB!(7), colorA!(7) ' RGBA color
  165. DIM SHARED specular!(7), highlight!(7) '                    Phong parameters
  166. DIM SHARED reflection!(7) '                                 Ray reflection amount
  167. DIM SHARED textures(7) AS TEXTURE, bumpmap(7) AS TEXTURE '  image handle
  168. DIM SHARED numObjects%
  169.  
  170. DIM SHARED lightX(4), lightY(4), lightZ(4) '                Light position
  171. DIM SHARED lightR!(4), lightG!(4), lightB!(4) '             Light color
  172. DIM SHARED numLights%
  173.  
  174. init
  175. main
  176.  
  177. worldMap:
  178. DATA "!~#!~#!~#!-#(.69AEGFC@5.224;DJMORQND:)(*$!:#'#$!e#+.+1WX\_`ab\MCOZ!/baaQ5&!)#'<;CB=,&!&#$06,8@6/$!%#&&##$8NL"
  179. DATA ":1%!P#-=@@D25CGHIKJYZ]A)=^b`!0b]:!+#$0M?80!.#*-6.!&#%#%#/6?VR=6)!*#'%!B#,DDID?>>/LLPRINQE,!%#$#'F!.bZ0!;#=P="
  180. DATA "-%$'$%)7GV^!)bA/)&6.##-BL/0+!,#/!'#$/80)&!'#$)5NA\]^]W3EQZ,[]baaN>0!&#J_!+bZ2!%#$$!+#$/3-!)#8V*##+R]PUV\!/ba"
  181. DATA "bb8CBN[XRF26/!(#(=*##&B`!'b_YQPYaaVVMTVVX]YJY]YFMaZ_!%b9$##/Q!(b]TJ6$!-#%>V`ba`UJ<),2;<DCSTL[`O]!%ba!:baSTVT"
  182. DATA "[XOOWT06OZ!.b_PNa!+b`WH._a]aOP%#&[!%baP@%##1@CF&!*#Dab\Mba\FFLQ`!*b\_!Gb##*--VS!1baa^ab_`abN0?E.=8GVT'!%#1_bb"
  183. DATA "<!(#8=/##&!%#$9RbbN=Ya^aV\!,baY]`!@b^!%b]G##$#CUab`WXGKQ^!)b__a]!%abA!&#%ObZ3.,!&#-@I!0#&#/aa`b=6TLUQ[a!,b!%a"
  184. DATA "!9ba^]Xa:)RNGF1!*#+AJ>!&#$@Y!+baZbb^=.##%Cbb^][)!4#2T+##9>Q^,3Q`!%b_!EbO*##$$1U\(!+#),3+!*#6Qa_a!&ba_abb`bbU"
  185. DATA "G,Taab``U8!2#/LJK$#-ZO;>T!>babTa!'babbN1'!&#L`=#&!&#')'%&!-#$)L`baa!*b_!%bGa`baabaX-!1#;?KaGJ!@babbabZ\!-bT$"
  186. DATA "!%#;6!&#&#'!4#*FYaa!)b`bQZ!'b[L7,PI%!2#9DZ!Rb[<*!%#'!=#+a!,bYPAU[!&b_@4(2)!2#%N!&b^!'bZMZWbbaW!@b^/5#'&!?#/a"
  187. DATA "!-bYPQVXb_84-!4#)C@PbMEER=[bb`-$(.Sb`(T!*b`!4b\R.(Q;%!@#,a!-baa^`bY9%!6#-!%bA($:2N3aNWJW[KPbbG3!9b]``X)##08!C#"
  188. DATA "N!1ba1!2#$!'#/[aP&*,3.;$B>D!%abbabM-!9b[7?U##)K2!C#)X!0bW&!9#4KJ`bbX!&#+('19!?bU&,Q.HQI$!E#K]!-bD!:#5a!(bQ:$"
  189. DATA "HA/)/M!@b@$%J-$!G#*B^!&b`GJ<8Q/!7#$%(N!+b]!&b`a!&bL`!:bC##%!J#;=_!%bA!J5!7#+Z!2b=!&bW:KV!7bX&#'!L#:0]bb6!&#"
  190. DATA "4BU,!6#I!3bLB!&b]\E(',\!2bU>3%!<#'*!3#Dbb@#-L)79Q4/!4#%a!4b5]!'b])##/V!&b_A?!&b`FL-#%!?#(!3#(H``HYX!%#/)E3,$"
  191. DATA "!/#$##V!4bJ5!&b\2!&#(!%bU(##G!%bV1-##*6!R#';;^ZM8$!(#(!.#*#&_!5b?YbZ=!)#TbP'!%#0<!%bK!%#6;!U#&7\8##$4-$#%!1#"
  192. DATA "a!6bJ3)'&!(#:bC!%#&'.PWbZ!%#)A5!V#5E31[^^QU:!1#2^!5b\[b+!*#ZF!%#$#,A)S-##&+9>!W#(0N!(b>0!0#8]!%bZX!1bJ!)#%#&"
  193. DATA "E&!%#'$G-!    $3Q##$!V#F!*bQ!0#*;/0#&@W!.b[)!)#%%!(#&L?U$%%C_0!?#$!<#1a!+bG!6#J!)b`!%bS*!3#0[_,/Wb_/2*4!1#%!C#"
  194. DATA "(!%#P!-bS4'!3#Q!(baB_bW&!5#=bR0`bK@<'*6F35$#%%!*#$!F#T!0bI+!1#)\!'b^bba-!6#$Da/05-=B%0+<Mb]C$,+!N#A!1bL!2#B!'b"
  195. DATA "Xbba(!8#8EH:!&'$)/,\b\C.#0)!M#X!/ba7!2#3!'b`b^b3!;#&-5-6$(%%&U,?2%#'+!*#%!C#7!/bA!3#8!)bXb?$#;!<#'&U_K#R,##%"
  196. DATA "!&#$!1#$!:#$Ia_!,b/!3#R!+b;)EY!;#1W`bbW4^T!)#.!%#)!,#$!=#1!-b)!3#Qa!(b]3#:bF!;#R!*b.!(#$$##0!I#`!+bJ!4#/a!(b"
  197. DATA "F##@b2#%%!5#,M^!+b`:!?*!L#(!*bJ1$!5#X!(bE##A\!9#L!.bY*!Q#/!)bT!8#K!'bO!&#%!9#J!/bC!Q#=!)b:!8#(_!%ba0!>#/!/b"
  198. DATA "C!Q#@!(bF!:#Hbb^6!@#]bbM=4I!'b^/!Q#R!&b^:!;#*3*$!@#$=0'!&#?[bb`D!)#/&!H#*a!%b]C!g#-NP@)!)#%Q1!G#/_b_K&!j#1:!*#"
  199. DATA "=C##%!E#1^bZ*!k#'1!(#)K>!I#Cbb;!t#8;!J#Wb`3!Q#-!n#G_W##0*!P#$!l#%AO5$!*#'&!~#!H#(!~#!;#$##%!(#%!~#!8#)8;'!W#"
  200. DATA "&!f#+>\O!G#&/EH3&!)#5?@:>[NLA7BD52;ONCDA92/!'#$$!F#$!'#.@>`bM%!5#+,)*+-41-'+8CD1GWa!(b_ZH8BY!9bTNOA8&!B#$6BA"
  201. DATA "30.%#'4E`!%bM!0#.6DX^a!,babb`!,b^_!Cb^W7!0#'/37>DIQZVUPOIB>K!'b`X`!(bL*!,#)IT!@b]`!BbaK2&!%#21!%./7?JHTa!Bb_"
  202. DATA "RG:7?;:GT`!db_;DDC?7!~b!=ba_!Uba!%baa!hbaabaa!%b`^!%bab]a`ba!?b_a!qba\_!~b!Ib"
  203.  
  204. '####################################################################################################################
  205. '####################################################################################################################
  206. '####################################################################################################################
  207.  
  208. SUB init ()
  209. WIDTH , 40
  210. PRINT TAB(27); "Ray Tracer (Beta version)"
  211. PRINT TAB(36); "By Zom-B"
  212.  
  213. scrn& = selectScreenMode&(4, 32)
  214.  
  215. makeTextures
  216. 'texture&(1) = _LOADIMAGE("d:\0synced\software\qb64\wTex.png", 32)
  217. 'texture&(2) = _LOADIMAGE("d:\0synced\software\qb64\wBump.png", 32)
  218. 'texture&(3) = _LOADIMAGE("d:\0synced\software\qb64\fTex.png", 32)
  219. 'texture&(4) = _LOADIMAGE("d:\0synced\software\qb64\fBump.png", 32)
  220.  
  221. makeScene
  222.  
  223. SCREEN scrn&
  224. _DEST scrn&
  225. 'SCREEN _NEWIMAGE(640, 480, 32)
  226.  
  227. sizeX% = _WIDTH
  228. sizeY% = _HEIGHT
  229. maxX% = sizeX% - 1
  230. maxY% = sizeY% - 1
  231. halfX% = sizeX% \ 2
  232. halfY% = sizeY% \ 2
  233.  
  234. cameraPrepare 150, -250, 200, 0, 0, 66, 0, 0, 1, 60, maxX% / maxY%
  235. 'cameraPrepare 0, 0, 400, 0, 0, 132, 0, -1, 0, 45, maxX% / maxY%
  236.  
  237. '####################################################################################################################
  238.  
  239. SUB main ()
  240. 'FOR i% = 0 TO 360 STEP 30
  241. '  x = 100 * COS(i% * _deg2rad)
  242. '  y = 100 * SIN(i% * _deg2rad)
  243. '  cameraPrepare x, y, 400, 0, 0, 200, 0, 0, 1, 60, maxX% / maxY%
  244.  
  245. renderProgressive 256, 4
  246.  
  247. CIRCLE (maxX% \ 2, maxY% \ 2), 3, _RGB32(255, 255, 255), , , 1
  248. 'NEXT
  249.  
  250. '####################################################################################################################
  251. '####################################################################################################################
  252. '####################################################################################################################
  253.  
  254. SUB cameraPrepare (posX, posY, posZ, lookAtX, lookAtY, lookAtZ, upX, upY, upZ, fov, aspect)
  255. camPos.x = posX
  256. camPos.y = posY
  257. camPos.z = posZ
  258.  
  259. camDir.x = lookAtX - posX
  260. camDir.y = lookAtY - posY
  261. camDir.z = lookAtZ - posZ
  262. vectorNormalize camDir
  263. 'PRINT camDir.x, camDir.y, camDir.z
  264.  
  265. camUp.x = upX
  266. camUp.y = upY
  267. camUp.z = upZ
  268. 'vectorNormalize camUp
  269. 'PRINT camUp.x, camUp.y, camUp.z
  270.  
  271. 'Right vec
  272. vectorCross camUp, camDir, camRight
  273. vectorNormalize camRight
  274. 'PRINT camRight.x, camRight.y, camRight.z
  275.  
  276. vectorCross camDir, camRight, camUp
  277. vectorNormalize camUp
  278. 'PRINT camUp.x, camUp.y, camUp.z
  279. 'END
  280.  
  281. scaleY = TAN(fov * (_PI / 360)) * 0.75
  282. scaleX = scaleY * aspect
  283.  
  284. vectorScale camRight, scaleX
  285. vectorScale camUp, scaleY
  286.  
  287. 'PRINT fov, scaleX, scaleY
  288. 'END
  289.  
  290. '####################################################################################################################
  291.  
  292. SUB renderProgressive (startSize%, endSize%)
  293. pixStep% = startSize%
  294.  
  295. pixWidth% = pixStep% - 1
  296. FOR y% = 0 TO maxY% STEP pixStep%
  297.     FOR x% = 0 TO maxX% STEP pixStep%
  298.         tracePoint x%, y%, r!, g!, b!
  299.         LINE (x%, y%)-STEP(pixWidth%, pixWidth%), _RGB(r! * 255, g! * 255, b! * 255), BF
  300.     NEXT
  301.     IF INKEY$ = CHR$(27) THEN SYSTEM
  302.  
  303. WHILE pixStep% > 2
  304.     pixSize% = pixStep% \ 2
  305.     pixWidth% = pixSize% - 1
  306.     FOR y% = 0 TO maxY% STEP pixStep%
  307.         y1% = y% + pixSize%
  308.         FOR x% = 0 TO maxX% STEP pixStep%
  309.             x1% = x% + pixSize%
  310.  
  311.             IF x1% < sizeX% THEN
  312.                 tracePoint x1%, y%, r!, g!, b!
  313.                 LINE (x1%, y%)-STEP(pixWidth%, pixWidth%), _RGB(r! * 255, g! * 255, b! * 255), BF
  314.             END IF
  315.             IF y1% < sizeY% THEN
  316.                 tracePoint x%, y1%, r!, g!, b!
  317.                 LINE (x%, y1%)-STEP(pixWidth%, pixWidth%), _RGB(r! * 255, g! * 255, b! * 255), BF
  318.                 IF x1% < sizeX% THEN
  319.                     tracePoint x1%, y1%, r!, g!, b!
  320.                     LINE (x1%, y1%)-STEP(pixWidth%, pixWidth%), _RGB(r! * 255, g! * 255, b! * 255), BF
  321.                 END IF
  322.             END IF
  323.         NEXT
  324.         IF INKEY$ = CHR$(27) THEN SYSTEM
  325.     NEXT
  326.     pixStep% = pixStep% \ 2
  327.  
  328. FOR y% = 0 TO maxY%
  329.     y1% = y% + 1
  330.     FOR x% = 0 TO maxX%
  331.         x1% = x% + 1
  332.  
  333.         IF x1% < sizeX% THEN
  334.             tracePoint x1%, y%, r!, g!, b!
  335.             PSET (x1%, y%), _RGB(r! * 255, g! * 255, b! * 255)
  336.         END IF
  337.         IF y1% < sizeY% THEN
  338.             tracePoint x%, y1%, r!, g!, b!
  339.             PSET (x%, y1%), _RGB(r! * 255, g! * 255, b! * 255)
  340.             IF x1% < sizeX% THEN
  341.                 tracePoint x1%, y1%, r!, g!, b!
  342.                 PSET (x1%, y1%), _RGB(r! * 255, g! * 255, b! * 255)
  343.             END IF
  344.         END IF
  345.     NEXT
  346.     IF INKEY$ = CHR$(27) THEN SYSTEM
  347.  
  348. IF NOT Doantialias THEN EXIT SUB
  349.  
  350. factor! = 255 / (endSize% * endSize%)
  351.  
  352. IF Usegaussian THEN
  353.     FOR y% = 0 TO maxY%
  354.         FOR x% = 0 TO maxX%
  355.             c& = POINT(x%, y%)
  356.             r! = _RED(c&)
  357.             g! = _GREEN(c&)
  358.             b! = _BLUE(c&)
  359.             FOR i% = 2 TO endArea%
  360.                 DO 'Marsaglia polar method for random gaussian
  361.                     u! = RND * 2 - 1
  362.                     v! = RND * 2 - 1
  363.                     s! = u! * u! + v! * v!
  364.                 LOOP WHILE s! >= 1 OR s! = 0
  365.                 s! = SQR(-2 * LOG(s!) / s!) * 0.5
  366.                 u! = u! * s!
  367.                 v! = v! * s!
  368.  
  369.                 tracePoint x% + u!, y% + v!, r1!, g1!, b1!
  370.  
  371.                 r! = r! + r1!
  372.                 g! = g! + g1!
  373.                 b! = b! + b1!
  374.             NEXT
  375.  
  376.             PSET (x%, y%), _RGB(r! * factor!, g! * factor!, b! * factor!)
  377.             IF INKEY$ = CHR$(27) THEN SYSTEM
  378.         NEXT
  379.     NEXT
  380.     FOR y% = 0 TO maxY%
  381.         FOR x% = 0 TO maxX%
  382.             r! = 0
  383.             g! = 0
  384.             b! = 0
  385.             FOR v% = 0 TO endSize% - 1
  386.                 y1! = y% + v% / endSize%
  387.                 FOR u% = 0 TO endSize% - 1
  388.                     IF u% = 0 AND v& = 0 THEN
  389.                         c& = POINT(x%, y%)
  390.                     ELSE
  391.                         x1! = x% + u% / endSize%
  392.                         tracePoint x1!, y1!, r1!, g1!, b1!
  393.                     END IF
  394.                     r! = r! + r1!
  395.                     g! = g! + g1!
  396.                     b! = b! + b1!
  397.                 NEXT
  398.             NEXT
  399.  
  400.             PSET (x%, y%), _RGB(r! * factor!, g! * factor!, b! * factor!)
  401.             IF INKEY$ = CHR$(27) THEN SYSTEM
  402.         NEXT
  403.     NEXT
  404.  
  405. '####################################################################################################################
  406.  
  407. SUB tracePoint (x!, y!, r!, g!, b!)
  408. x0! = (x! - halfX%) / halfX%
  409. y0! = (halfY% - y!) / halfY%
  410.  
  411. rayX = camDir.x + x0! * camRight.x + y0! * camUp.x
  412. rayY = camDir.y + x0! * camRight.y + y0! * camUp.y
  413. rayZ = camDir.z + x0! * camRight.z + y0! * camUp.z
  414.  
  415. 'normalize to a vector length of 1
  416. d = 1 / SQR(rayX * rayX + rayY * rayY + rayZ * rayZ)
  417. traceRay camPos.x, camPos.y, camPos.z, rayX * d, rayY * d, rayZ * d, 3, -1, r!, g!, b!
  418.  
  419. '####################################################################################################################
  420.  
  421. SUB traceRay (startX, startY, startZ, rayX, rayY, rayZ, depth%, lastObj%, lightR!, lightG!, lightB!)
  422. findMinObj startX, startY, startZ, rayX, rayY, rayZ, lastObj%, minobj%, minDepth
  423.  
  424. IF minobj% = 0 THEN '                        Infinity
  425.     lightR! = 0
  426.     lightG! = 0
  427.     lightB! = 0
  428. ELSE '                                       An object was found
  429.     intersectX = startX + rayX * minDepth
  430.     intersectY = startY + rayY * minDepth
  431.     intersectZ = startZ + rayZ * minDepth
  432.  
  433.     'Calculate normal vector
  434.     SELECT CASE objectType%(minobj%)
  435.         CASE FLOOR:
  436.             normalX = 0
  437.             normalY = 0
  438.             normalZ = 1
  439.         CASE SPHERE:
  440.             normalX = (intersectX - positionX(minobj%)) / size(minobj%)
  441.             normalY = (intersectY - positionY(minobj%)) / size(minobj%)
  442.             normalZ = (intersectZ - positionZ(minobj%)) / size(minobj%)
  443.     END SELECT
  444.  
  445.     'Calculate UV coordinates
  446.     IF textures(minobj%).image <> -1 OR bumpmap(minobj%).image <> -1 THEN
  447.         SELECT CASE objectType%(minobj%)
  448.             CASE FLOOR:
  449.                 texcoordU! = intersectX
  450.                 texcoordV! = intersectY
  451.             CASE SPHERE:
  452.                 IF normalX = 0 THEN
  453.                     IF normalY <= 0 THEN texcoordU! = 0 ELSE texcoordU! = 0.5
  454.                 ELSE
  455.                     texcoordU! = atan2(normalX, normalY) / pi2 + 0.5
  456.                 END IF
  457.  
  458.                 texcoordV! = acos(normalZ) / _PI
  459.         END SELECT
  460.     END IF
  461.  
  462.     'Bumpmapping
  463.     IF bumpmap(minobj%).image <> -1 THEN
  464.         IF minobj% < 3 THEN
  465.             texdirxx = 1
  466.             texdirxy = 0
  467.             texdirxz = 0
  468.  
  469.             texdiryx = 0
  470.             texdiryy = 1
  471.             texdiryz = 0
  472.         ELSE
  473.             texdirxx = normalY
  474.             texdirxy = -normalX
  475.             texdirxz = 0
  476.  
  477.             texdiryx = normalZ * normalX
  478.             texdiryy = normalZ * normalY
  479.             texdiryz = -(normalX * normalX + normalY * normalY)
  480.         END IF
  481.  
  482.         x! = texcoordU! * bumpmap(minobj%).scaleU - bumpmap(minobj%).offsetU
  483.         y! = texcoordV! * bumpmap(minobj%).scaleV - bumpmap(minobj%).offsetV
  484.         x1% = INT(x!)
  485.         y1% = INT(y!)
  486.  
  487.         dx1! = x! - x1%
  488.         dy1! = y! - y1%
  489.         dx2! = 1 - dx1!
  490.         dy2! = 1 - dy1!
  491.         dx1dy1! = dx1! * dy1!
  492.         dx1dy2! = dx1! * dy2!
  493.         dx2dy1! = dx2! * dy1!
  494.         dx2dy2! = dx2! * dy2!
  495.  
  496.         x0% = remainder%(x1%, bumpmap(minobj%).w)
  497.         y0% = remainder%(y1%, bumpmap(minobj%).h)
  498.         x1% = remainder%(x1% + 1, bumpmap(minobj%).w)
  499.         y1% = remainder%(y1% + 1, bumpmap(minobj%).h)
  500.  
  501.         _SOURCE bumpmap(minobj%).image
  502.         c0& = POINT(x0%, y0%)
  503.         c1& = POINT(x1%, y0%)
  504.         c2& = POINT(x0%, y1%)
  505.         c3& = POINT(x1%, y1%)
  506.  
  507.         sx! = ((_RED(c0&) - 127) * dx2dy2! + (_RED(c1&) - 127) * dx1dy2! + (_RED(c2&) - 127) * dx2dy1! + (_RED(c3&) - 127) * dx1dy1!) * bumpmap(minobj%).bumpfactor / 127
  508.         sy! = ((_GREEN(c0&) - 127) * dx2dy2! + (_GREEN(c1&) - 127) * dx1dy2! + (_GREEN(c2&) - 127) * dx2dy1! + (_GREEN(c3&) - 127) * dx1dy1!) * bumpmap(minobj%).bumpfactor / 127
  509.  
  510.         normalX = normalX - (texdirxx * sx! + texdiryx * sy)
  511.         normalY = normalY - (texdirxy * sx! + texdiryy * sy)
  512.         normalZ = normalZ - (texdirxz * sx! + texdiryz * sy)
  513.  
  514.         r = SQR(normalX * normalX + normalY * normalY + normalZ * normalZ)
  515.         normalX = normalX / r
  516.         normalY = normalY / r
  517.         normalZ = normalZ / r
  518.     END IF
  519.  
  520.     'lighting
  521.     r = 2 * (rayX * normalX + rayY * normalY + rayZ * normalZ)
  522.     rayX = rayX - normalX * r
  523.     rayY = rayY - normalY * r
  524.     rayZ = rayZ - normalZ * r
  525.  
  526.     diffuseR! = 0
  527.     diffuseG! = 0
  528.     diffuseB! = 0
  529.     specularR! = 0
  530.     specularG! = 0
  531.     specularB! = 0
  532.  
  533.     FOR a% = numLights% TO 1 STEP -1
  534.         dirX = lightX(a%) - intersectX
  535.         dirY = lightY(a%) - intersectY
  536.         dirZ = lightZ(a%) - intersectZ
  537.  
  538.         r = 1 / SQR(dirX * dirX + dirY * dirY + dirZ * dirZ)
  539.         dirX = dirX * r
  540.         dirY = dirY * r
  541.         dirZ = dirZ * r
  542.  
  543.         'Shadows testing
  544.         findShadow intersectX, intersectY, intersectZ, dirX, dirY, dirZ, minobj%, noShadows%
  545.  
  546.         IF noShadows% THEN
  547.             'Diffuse lighting
  548.             r = normalX * dirX + normalY * dirY + normalZ * dirZ
  549.             IF r > 0 THEN
  550.                 diffuseR! = diffuseR! + colorR!(minobj%) * lightR!(a%) * r
  551.                 diffuseG! = diffuseG! + colorG!(minobj%) * lightG!(a%) * r
  552.                 diffuseB! = diffuseB! + colorB!(minobj%) * lightB!(a%) * r
  553.             END IF
  554.  
  555.             'Specular lighting
  556.             r = rayX * dirX + rayY * dirY + rayZ * dirZ
  557.             IF r > 0 THEN
  558.                 c! = r ^ (1 / highlight!(minobj%)) * specular!(minobj%)
  559.  
  560.                 specularR! = specularR! + lightR!(a%) * c!
  561.                 specularG! = specularG! + lightG!(a%) * c!
  562.                 specularB! = specularB! + lightB!(a%) * c!
  563.             END IF
  564.         END IF
  565.     NEXT
  566.  
  567.     lightR! = diffuseR! + specularR!
  568.     lightG! = diffuseG! + specularG!
  569.     lightB! = diffuseB! + specularB!
  570.  
  571.     'texturing
  572.     IF textures(minobj%).image <> -1 THEN
  573.         x! = texcoordU! * textures(minobj%).scaleU - textures(minobj%).offsetU
  574.         y! = texcoordV! * textures(minobj%).scaleV - textures(minobj%).offsetV
  575.         x0% = INT(x!)
  576.         y0% = INT(y!)
  577.  
  578.         dx1! = x! - x0%
  579.         dy1! = y! - y0%
  580.         dx2! = 1 - dx1!
  581.         dy2! = 1 - dy1!
  582.         dx1dy1! = dx1! * dy1!
  583.         dx1dy2! = dx1! * dy2!
  584.         dx2dy1! = dx2! * dy1!
  585.         dx2dy2! = dx2! * dy2!
  586.  
  587.         x1% = remainder%(x0% + 1, textures(minobj%).w) ' returns positive value only, in contrast to MOD
  588.         y1% = remainder%(y0% + 1, textures(minobj%).h)
  589.         x0% = remainder%(x0%, textures(minobj%).w)
  590.         y0% = remainder%(y0%, textures(minobj%).h)
  591.  
  592.         _SOURCE textures(minobj%).image
  593.         c0& = POINT(x0%, y0%)
  594.         c1& = POINT(x1%, y0%)
  595.         c2& = POINT(x0%, y1%)
  596.         c3& = POINT(x1%, y1%)
  597.  
  598.         materialr! = _RED(c0&) * dx2dy2! + _RED(c1&) * dx1dy2! + _RED(c2&) * dx2dy1! + _RED(c3&) * dx1dy1!
  599.         materialg! = _GREEN(c0&) * dx2dy2! + _GREEN(c1&) * dx1dy2! + _GREEN(c2&) * dx2dy1! + _GREEN(c3&) * dx1dy1!
  600.         materialb! = _BLUE(c0&) * dx2dy2! + _BLUE(c1&) * dx1dy2! + _BLUE(c2&) * dx2dy1! + _BLUE(c3&) * dx1dy1!
  601.  
  602.         lightR! = lightR! * materialr! / 255F
  603.         lightG! = lightG! * materialg! / 255F
  604.         lightB! = lightB! * materialb! / 255F
  605.     END IF
  606.  
  607.     'Reflection
  608.     IF reflection!(minobj%) > 0 AND depth% > 0 THEN
  609.         traceRay intersectX, intersectY, intersectZ, rayX, rayY, rayZ, depth% - 1, minobj%, reflectR!, reflectG!, reflectB!
  610.         lightR! = lightR! + (reflectR! - lightR!) * reflection!(minobj%)
  611.         lightG! = lightG! + (reflectG! - lightG!) * reflection!(minobj%)
  612.         lightB! = lightB! + (reflectB! - lightB!) * reflection!(minobj%)
  613.     END IF
  614.  
  615.     ' Global intensity
  616.     r = EXP(-minDepth / 1000.0)
  617.  
  618.     lightR! = lightR! * r
  619.     lightG! = lightG! * r
  620.     lightB! = lightB! * r
  621.  
  622. '####################################################################################################################
  623.  
  624. SUB findMinObj (startX, startY, startZ, rayX, rayY, rayZ, lastObj%, minObj%, minDepth)
  625. minObj% = 0
  626. minDepth = 1E+308
  627. FOR a% = numObjects% TO 1 STEP -1
  628.     IF a% <> lastObj% THEN
  629.         SELECT CASE objectType%(a%)
  630.             CASE FLOOR:
  631.                 depth = -startZ / rayZ
  632.             CASE SPHERE:
  633.                 posX = positionX(a%) - startX
  634.                 posY = positionY(a%) - startY
  635.                 posZ = positionZ(a%) - startZ
  636.  
  637.                 r = rayX * posX + rayY * posY + rayZ * posZ
  638.                 d = r * r - posX * posX - posY * posY - posZ * posZ + size(a%) * size(a%)
  639.                 IF d >= 0 THEN depth = r - SQR(d) ELSE depth = -1
  640.         END SELECT
  641.  
  642.         IF depth >= 0 THEN
  643.             IF minDepth > depth THEN minDepth = depth: minObj% = a%
  644.         END IF
  645.     END IF
  646.  
  647. '####################################################################################################################
  648.  
  649. SUB findShadow (startX, startY, startZ, rayX, rayY, rayZ, lastObj%, noShadows%)
  650. noShadows% = -1
  651. FOR a% = numObjects% TO 1 STEP -1
  652.     IF a% <> lastObj% THEN
  653.         SELECT CASE objectType%(a%)
  654.             CASE FLOOR:
  655.                 depth = -startZ / rayZ
  656.             CASE SPHERE:
  657.                 posX = positionX(a%) - startX
  658.                 posY = positionY(a%) - startY
  659.                 posZ = positionZ(a%) - startZ
  660.  
  661.                 r = rayX * posX + rayY * posY + rayZ * posZ
  662.                 d = r * r - posX * posX - posY * posY - posZ * posZ + size(a%) * size(a%)
  663.                 IF d >= 0 THEN depth = r - SQR(d) ELSE depth = -1
  664.         END SELECT
  665.  
  666.         IF depth >= 0 THEN
  667.             noShadows% = 0
  668.             EXIT SUB
  669.         END IF
  670.     END IF
  671.  
  672. '####################################################################################################################
  673. '####################################################################################################################
  674. '####################################################################################################################
  675.  
  676. SUB makeTextures
  677. PRINT "Generating textures. Press any key to see them generating."
  678. showing = 0
  679.  
  680. world& = _NEWIMAGE(128, 64, 32)
  681. texture&(1) = _NEWIMAGE(1024, 512, 32)
  682. texture&(2) = _NEWIMAGE(1024, 512, 32)
  683. texture&(3) = _NEWIMAGE(512, 512, 32)
  684. texture&(4) = _NEWIMAGE(512, 512, 32)
  685.  
  686. IF showing THEN SCREEN world& ELSE _DEST 0: PRINT: PRINT "(1/5) Decompressing world template (RLE)";
  687.  
  688. x% = 0: y% = 0
  689. FOR a% = 1 TO 25
  690.     _DEST world&
  691.     READ a$
  692.     FOR b! = 1 TO LEN(a$)
  693.         c% = (ASC(MID$(a$, b!, 1)) - 35) * 4
  694.         IF c% < 0 THEN n% = ASC(MID$(a$, b! + 1, 1)) - 34: b! = b! + 2: c% = (ASC(MID$(a$, b!, 1)) - 35) * 4 ELSE n% = 1
  695.         FOR n% = n% TO 1 STEP -1
  696.             PSET (x%, y%), _RGB(c%, c%, c%)
  697.             x% = x% + 1: IF x% = 128 THEN x% = 0: y% = y% + 1
  698.         NEXT
  699.     NEXT
  700.     IF LEN(INKEY$) THEN showing = -1: SCREEN world& ELSE IF NOT showing THEN _DEST 0: PRINT ".";
  701.  
  702. IF showing THEN SCREEN texture&(1) ELSE _DEST 0: PRINT: PRINT "(2/5) World bump map";
  703.  
  704. FOR y% = 0 TO 511
  705.     _SOURCE world&
  706.     _DEST texture&(1)
  707.     FOR x% = 0 TO 1023
  708.         getWorldBump x% / 3000, y% / 2000, a!
  709.         a! = (a! - 0.387) / 0.502: a! = a! * a!
  710.         getWorldPixel x% / 8 - 0.5, y% / 8 - 0.50, c!
  711.         c! = c! / 255: IF c! > 1 THEN c! = 1
  712.  
  713.         r! = 11 + (24 + 231 * a! - 11) * c!
  714.         g! = 10 + (49 + 198 * a! - 10) * c!
  715.         b! = 50 + (8 + 181 * a! - 50) * c!
  716.  
  717.         PSET (x%, y%), _RGB32(r!, g!, b!)
  718.     NEXT
  719.     IF LEN(INKEY$) THEN showing = -1: SCREEN texture&(1) ELSE IF NOT showing THEN _DEST 0: PRINT ".";
  720.  
  721. IF showing THEN SCREEN texture&(2) ELSE _DEST 0: PRINT: PRINT "(3/5) World bump map";
  722.  
  723. FOR y% = 0 TO 511
  724.     _SOURCE world&
  725.     _DEST texture&(2)
  726.     FOR x% = 0 TO 1023
  727.         getWorldPixel x% / 8 - 0.46, y% / 8 - 0.50, c0!: getWorldBump x% / 300 + 0.001, y% / 300, a0!: a0! = a0! * c0!
  728.         getWorldPixel x% / 8 - 0.54, y% / 8 - 0.50, c1!: getWorldBump x% / 300 - 0.001, y% / 300, a1!: a1! = a1! * c1!
  729.         getWorldPixel x% / 8 - 0.50, y% / 8 - 0.46, c2!: getWorldBump x% / 300, y% / 300 + 0.001, a2!: a2! = a2! * c2!
  730.         getWorldPixel x% / 8 - 0.50, y% / 8 - 0.54, c3!: getWorldBump x% / 300, y% / 300 - 0.001, a3!: a3! = a3! * c3!
  731.  
  732.         r! = (a1! - a0!) * 7
  733.         g! = (a2! - a3!) * 7
  734.         PSET (x%, y%), _RGB32(r! + 127, g! + 127, 127)
  735.     NEXT
  736.     IF LEN(INKEY$) THEN showing = -1: SCREEN texture&(2) ELSE IF NOT showing THEN _DEST 0: PRINT ".";
  737.  
  738. IF showing THEN SCREEN texture&(3) ELSE _DEST 0: PRINT: PRINT "(4/5) Floor texture";
  739.  
  740. FOR y% = 0 TO 511
  741.     _DEST texture&(3)
  742.     FOR x% = 0 TO 511
  743.         getFloorTexture x% / 256, y% / 256, r!, g!, b!
  744.         PSET (x%, y%), _RGB32(r! * 255, g! * 255, b! * 255)
  745.     NEXT
  746.     IF LEN(INKEY$) THEN showing = -1: SCREEN texture&(2) ELSE IF NOT showing THEN _DEST 0: PRINT ".";
  747.  
  748. IF showing THEN SCREEN texture&(4) ELSE _DEST 0: PRINT: PRINT "(5/5) Floor bump map";
  749.  
  750. FOR y% = 0 TO 511
  751.     _DEST texture&(4)
  752.     FOR x% = 0 TO 511
  753.         getFloorBump x% / 256 - 0.002, y% / 256, a0!
  754.         getFloorBump x% / 256 + 0.002, y% / 256, a1!
  755.         getFloorBump x% / 256, y% / 256 + 0.002, a2!
  756.         getFloorBump x% / 256, y% / 256 - 0.002, a3!
  757.  
  758.         r! = (a1! - a0!) * 1400
  759.         g! = (a2! - a3!) * 1400
  760.  
  761.         PSET (x%, y%), _RGB32(r! + 127, g! + 127, 127)
  762.     NEXT
  763.     IF LEN(INKEY$) THEN showing = -1: SCREEN texture&(4) ELSE IF NOT showing THEN _DEST 0: PRINT ".";
  764.  
  765. '####################################################################################################################
  766.  
  767. SUB getWorldPixel (x!, y!, c0!)
  768. x% = INT(x!) AND &H7F
  769. y% = INT(y!) AND &H3F
  770. dx! = x! - x%: IF dx! < 0 THEN dx! = dx! + 128
  771. dy! = y! - y%
  772.  
  773.  
  774. c0! = POINT(x%, y%) AND &HFF
  775. c1! = POINT((x% + 1) AND &H7F, y%) AND &HFF
  776. c2! = POINT(x%, y% + 1) AND &HFF
  777. c3! = POINT((x% + 1) AND &H7F, y% + 1) AND &HFF
  778.  
  779. c0! = c0! + (c1! - c0!) * dx!
  780. c2! = c2! + (c3! - c2!) * dx!
  781. c0! = c0! + (c2! - c0!) * dy!
  782.  
  783. c0! = c0! - 72: IF c0! < 0 THEN c0! = 0
  784.  
  785.  
  786. SUB getWorldBump (u!, v!, a!)
  787. l! = 0
  788. fbm u!, v!, 1, l!
  789. a! = 0.3 * l! + 0.2
  790.  
  791.  
  792. SUB getFloorTexture (u!, v!, r!, g!, b!)
  793. v1% = v! - INT(v!) < 0.5: u1% = u! - INT(u!) < 0.5
  794.  
  795. IF u1% = v1% THEN
  796.     l! = 0
  797.     fbm u!, v!, 3, l!
  798.     l! = l! * 0.7
  799.     fbm u!, v!, 2, l!
  800.     r! = 0.054 * l! + 0.61
  801.     g! = 0.054 * l! + 0.42
  802.     b! = 0.054 * l! + 0.25
  803.     l! = 0
  804.     fbm u!, v!, 1, l!
  805.     l! = l! * 0.6
  806.     fbm u!, v!, 0, l!
  807.     r! = 0.10 * l! + 0.05
  808.     g! = 0.08 * l! - 0.04
  809.     b! = 0.07 * l! - 0.06
  810.  
  811.  
  812. SUB getFloorBump (u!, v!, a!)
  813. v1% = v! - INT(v!) < 0.5: u1% = u! - INT(u!) < 0.5
  814. v2! = v! * 2 - INT(v! * 2): v2! = 1 - v2! * (1 - v2!) * 4: v2! = v2! * v2!: v2! = 1 - v2! * v2!
  815. u2! = u! * 2 - INT(u! * 2): u2! = 1 - u2! * (1 - u2!) * 4: u2! = u2! * u2!: u2! = 1 - u2! * u2!
  816.  
  817. IF u1% = v1% THEN
  818.     l! = 0
  819.     fbm u!, v!, 3, l!
  820.     l! = l! * 0.7
  821.     fbm u!, v!, 2, l!
  822.     a! = 0.02 * l! + 0.7
  823.     l! = 0
  824.     fbm u!, v!, 1, l!
  825.     l! = l! * 0.6
  826.     fbm u!, v!, 0, l!
  827.     a! = 0.05 * l! + 0.6
  828.  
  829. a! = a! * u2! * v2!
  830.  
  831. 'a! = a! + (u2! * v2! - 1) ' * 0.88
  832. 'IF a! < 0.06 THEN a = RND * 0.02
  833.  
  834. '####################################################################################################################
  835.  
  836. SUB fbm (x!, y!, a%, o!)
  837.     CASE 0:
  838.         zx! = x! * 40 - y! * 2
  839.         zy! = y!
  840.         i% = -5
  841.     CASE 1:
  842.         zx! = x! * 50
  843.         zy! = y! * 50
  844.         i% = -2
  845.     CASE 2:
  846.         zx! = x! * 80
  847.         zy! = y! * 80
  848.         i% = -2
  849.     CASE 3:
  850.         zx! = x! * 30 + y! * 0.5
  851.         zy! = y! * 2
  852.         i% = -2
  853.  
  854. scale! = 1
  855. FOR i% = i% TO 0
  856.     zcx! = zx!: zx! = zcx! * 0.6 - zy! * 0.8: zy! = zcx! * 0.8 + zy! * 0.6
  857.     zcx! = CINT(zx! / scale!) * scale!: zcy! = CINT(zy! / scale!) * scale!
  858.  
  859.     rx1! = zcx! + 0.5 * scale! + 14: ry1! = zcy! + 0.5 * scale!: r! = 123094 / (rx1! * rx1! + ry1! * ry1!)
  860.     rx1! = rx1! * r!: ry1! = ry1! * r!: rx1! = rx1! - INT(rx1!): ry1! = ry1! - INT(ry1!)
  861.     rx2! = zcx! - 0.5 * scale! + 14: ry2! = zcy! + 0.5 * scale!: r! = 123094 / (rx2! * rx2! + ry2! * ry2!)
  862.     rx2! = rx2! * r!: ry2! = ry2! * r!: rx2! = rx2! - INT(rx2!): ry2! = ry2! - INT(ry2!)
  863.     rx3! = zcx! + 0.5 * scale! + 14: ry3! = zcy! - 0.5 * scale!: r! = 123094 / (rx3! * rx3! + ry3! * ry3!)
  864.     rx3! = rx3! * r!: ry3! = ry3! * r!: rx3! = rx3! - INT(rx3!): ry3! = ry3! - INT(ry3!)
  865.     rx4! = zcx! - 0.5 * scale! + 14: ry4! = zcy! - 0.5 * scale!: r! = 123094 / (rx4! * rx4! + ry4! * ry4!)
  866.     rx4! = rx4! * r!: ry4! = ry4! * r!: rx4! = rx4! - INT(rx4!): ry4! = ry4! - INT(ry4!)
  867.     x0! = (zx! - zcx!) / scale! + 0.5: x0! = (3 - 2 * x0!) * x0! * x0!: x1! = 1 - x0!
  868.     y0! = (zy! - zcy!) / scale! + 0.5: y0! = (3 - 2 * y0!) * y0! * y0!: y1! = 1 - y0!
  869.     pixcompx! = rx1! * x0! * y0! + rx3! * x0! * y1! + rx2! * x1! * y0! + rx4! * x1! * y1!
  870.     pixcompy! = ry1! * x0! * y0! + ry3! * x0! * y1! + ry2! * x1! * y0! + ry4! * x1! * y1!
  871.     o! = o! + SQR(pixcompx! * pixcompx! + pixcompy! * pixcompy!) * scale! * scale!: scale! = scale! * 0.8
  872.  
  873. '####################################################################################################################
  874. '####################################################################################################################
  875. '####################################################################################################################
  876.  
  877. SUB makeScene
  878. objectType%(1) = FLOOR
  879. colorR!(1) = 1
  880. colorG!(1) = 1
  881. colorB!(1) = 1
  882. colorA!(1) = 1
  883. specular!(1) = 2
  884. highlight!(1) = 0.002
  885. reflection!(1) = 0.5
  886. texturePrepare textures(1), texture&(3), .005, .005, 0, 0, 0
  887. texturePrepare bumpmap(1), texture&(4), .005, .005, 0, 0, 1
  888.  
  889. objectType%(2) = SPHERE
  890. positionX(2) = 0
  891. positionY(2) = 57.735
  892. positionZ(2) = 50
  893. size(2) = 50
  894. colorR!(2) = 1
  895. colorG!(2) = 0
  896. colorB!(2) = 0
  897. colorA!(2) = 1
  898. specular!(2) = 1
  899. highlight!(2) = 0.1
  900. reflection!(2) = 0.1
  901. texturePrepare textures(2), -1, 1, 1, 0, 0, 0
  902. texturePrepare bumpmap(2), -1, 1, 1, 0, 0, 1
  903.  
  904. objectType%(3) = SPHERE
  905. positionX(3) = -50
  906. positionY(3) = -28.8675
  907. positionZ(3) = 50
  908. size(3) = 50
  909. colorR!(3) = 0
  910. colorG!(3) = 0
  911. colorB!(3) = 1
  912. colorA!(3) = 1
  913. specular!(3) = 1
  914. highlight!(3) = 0.04
  915. reflection!(3) = 0.4
  916. texturePrepare textures(3), -1, 1, 1, 0, 0, 0
  917. texturePrepare bumpmap(3), -1, 1, 1, 0, 0, 1
  918.  
  919. objectType%(4) = SPHERE
  920. positionX(4) = 50
  921. positionY(4) = -28.8675
  922. positionZ(4) = 50
  923. size(4) = 50
  924. colorR!(4) = 0
  925. colorG!(4) = 1
  926. colorB!(4) = 0
  927. colorA!(4) = 1
  928. specular!(4) = 10
  929. highlight!(4) = 0.01
  930. reflection!(4) = 0.2
  931. texturePrepare textures(4), -1, 1, 1, 0, 0, 0
  932. texturePrepare bumpmap(4), -1, 1, 1, 0, 0, 1
  933.  
  934. objectType%(5) = SPHERE
  935. positionX(5) = 0
  936. positionY(5) = 0
  937. positionZ(5) = 132
  938. size(5) = 50
  939. colorR!(5) = 1
  940. colorG!(5) = 1
  941. colorB!(5) = 1
  942. colorA!(5) = 1
  943. specular!(5) = 5
  944. highlight!(5) = 0.002
  945. reflection!(5) = 0.15
  946. texturePrepare textures(5), texture&(1), 1, 1, 0.35, 0, 0
  947. texturePrepare bumpmap(5), texture&(2), 1, 1, 0.35, 0, 1
  948.  
  949. numObjects% = 5
  950.  
  951. lightX(1) = 460
  952. lightY(1) = -460
  953. lightZ(1) = 460
  954. lightR!(1) = 1
  955. lightG!(1) = 0.25
  956. lightB!(1) = 0.25
  957.  
  958. lightX(2) = -640
  959. lightY(2) = -180
  960. lightZ(2) = 460
  961. lightR!(2) = 0.25
  962. lightG!(2) = 1
  963. lightB!(2) = 0.25
  964.  
  965. lightX(3) = 80
  966. lightY(3) = 260
  967. lightZ(3) = 760
  968. lightR!(3) = 0.25
  969. lightG!(3) = 0.25
  970. lightB!(3) = 1
  971.  
  972. lightX(4) = 0
  973. lightY(4) = 0
  974. lightZ(4) = 400
  975. lightR!(4) = 1
  976. lightG!(4) = 1
  977. lightB!(4) = 1
  978.  
  979. numLights% = 4
  980.  
  981. '####################################################################################################################
  982.  
  983. SUB texturePrepare (tex AS TEXTURE, handle&, sU!, sV!, oU!, oV!, bumpfactor!)
  984. tex.image = handle&
  985. IF handle& <> -1 THEN
  986.     tex.w = _WIDTH(tex.image)
  987.     tex.h = _HEIGHT(tex.image)
  988.     tex.scaleU = sU! * tex.w
  989.     tex.scaleV = sV! * tex.h
  990.     tex.offsetU = oU! * tex.w
  991.     tex.offsetV = oV! * tex.h
  992.     tex.bumpfactor = bumpfactor!
  993.  
  994. '####################################################################################################################
  995. '# Math Library V0.11 (routines)
  996. '# By Zom-B
  997. '####################################################################################################################
  998.  
  999. FUNCTION remainder% (a%, b%)
  1000. remainder% = a% - INT(a% / b%) * b%
  1001.  
  1002. '> merger: Skipping unused FUNCTION fRemainder (a, b)
  1003.  
  1004. '####################################################################################################################
  1005.  
  1006. '> merger: Skipping unused FUNCTION safeLog (x)
  1007.  
  1008. '####################################################################################################################
  1009.  
  1010. '> merger: Skipping unused FUNCTION asin (y)
  1011.  
  1012. FUNCTION acos (y)
  1013. IF y <= -0.99999999999999# THEN acos = _PI: EXIT FUNCTION
  1014. IF y >= 0.99999999999999# THEN acos = 0: EXIT FUNCTION
  1015. acos = pi05 - ATN(y / SQR(1 - y * y))
  1016.  
  1017. '> merger: Skipping unused FUNCTION safeAcos (y)
  1018.  
  1019. FUNCTION atan2 (y, x)
  1020. IF x > 0 THEN
  1021.     atan2 = ATN(y / x)
  1022. ELSEIF x < 0 THEN
  1023.     IF y > 0 THEN
  1024.         atan2 = ATN(y / x) + _PI
  1025.     ELSE
  1026.         atan2 = ATN(y / x) - _PI
  1027.     END IF
  1028. ELSEIF y > 0 THEN
  1029.     atan2 = _PI / 2
  1030.     atan2 = -_PI / 2
  1031.  
  1032. '####################################################################################################################
  1033. '# Vector math library v0.1 (module part)
  1034. '# By Zom-B
  1035. '####################################################################################################################
  1036.  
  1037. SUB vectorScale (a AS VECTOR, scale)
  1038. a.x = a.x * scale
  1039. a.y = a.y * scale
  1040. a.z = a.z * scale
  1041.  
  1042. SUB vectorNormalize (a AS VECTOR)
  1043. r = 1 / SQR(a.x * a.x + a.y * a.y + a.z * a.z)
  1044. a.x = a.x * r
  1045. a.y = a.y * r
  1046. a.z = a.z * r
  1047.  
  1048. '####################################################################################################################
  1049.  
  1050. SUB vectorCross (a AS VECTOR, b AS VECTOR, o AS VECTOR)
  1051. o.x = a.y * b.z - a.z * b.y
  1052. o.y = a.z * b.x - a.x * b.z
  1053. o.z = a.x * b.y - a.y * b.x
  1054.  
  1055. '####################################################################################################################
  1056. '# Screen mode selector v1.1 (routines)
  1057. '# By Zom-B
  1058. '####################################################################################################################
  1059.  
  1060. FUNCTION selectScreenMode& (yOffset%, colors%)
  1061. DIM aspectName$(0 TO 9), aspectCol%(0 TO 9)
  1062. RESTORE videoaspect
  1063. FOR y% = 0 TO 10
  1064.     READ aspectName$(y%), aspectCol%(y%)
  1065.     IF aspectCol%(y%) = 0 THEN numAspect% = y% - 1: EXIT FOR
  1066.  
  1067. DIM vidX%(1 TO 100), vidY%(1 TO 100), vidA%(1 TO 100)
  1068. RESTORE videomodes
  1069. FOR y% = 1 TO 100
  1070.     READ vidX%(y%), vidY%(y%), vidA%(y%)
  1071.     IF (vidX%(y%) <= 0) THEN numModes% = y% - 1: EXIT FOR
  1072.  
  1073. IF numModes% > _HEIGHT - yOffset% - 1 THEN numModes% = _HEIGHT - yOffset% - 1
  1074.  
  1075. DEF SEG = &HB800
  1076. LOCATE yOffset% + 1, 1
  1077. PRINT "Select video mode:"; TAB(61); "Click "
  1078. POKE yOffset% * 160 + 132, 31
  1079.  
  1080. y% = 0
  1081. lastY% = 0
  1082. selectedAspect% = 0
  1083. reprint% = 1
  1084. lastButton% = 0
  1085.     IF INKEY$ = CHR$(27) THEN CLS: SYSTEM
  1086.     IF reprint% THEN
  1087.         reprint% = 0
  1088.  
  1089.         FOR x% = 1 TO numModes%
  1090.             LOCATE yOffset% + x% + 1, 1
  1091.             COLOR 7, 0
  1092.             PRINT USING "##:"; x%;
  1093.             IF selectedAspect% = 0 THEN
  1094.                 COLOR aspectCol%(vidA%(x%))
  1095.             ELSEIF selectedAspect% = vidA%(x%) THEN
  1096.                 COLOR 15
  1097.             ELSE
  1098.                 COLOR 8
  1099.             END IF
  1100.             PRINT STR$(vidX%(x%)); ","; vidY%(x%);
  1101.         NEXT
  1102.  
  1103.         FOR x% = 0 TO numAspect%
  1104.             IF x% > 0 AND selectedAspect% = x% THEN
  1105.                 COLOR aspectCol%(x%), 3
  1106.             ELSE
  1107.                 COLOR aspectCol%(x%), 0
  1108.             END IF
  1109.             LOCATE yOffset% + x% + 2, 64
  1110.             PRINT "<"; aspectName$(x%); ">"
  1111.         NEXT
  1112.     END IF
  1113.         IF lastY% > 0 THEN
  1114.             FOR x% = 0 TO 159 STEP 2
  1115.                 POKE lastY% + x%, PEEK(lastY% + x%) AND &HEF
  1116.             NEXT
  1117.         END IF
  1118.  
  1119.         x% = _MOUSEX
  1120.         y% = _MOUSEY - yOffset% - 1
  1121.  
  1122.         IF x% <= 60 THEN
  1123.             IF y% > 0 AND y% <= numModes% THEN
  1124.                 IF _MOUSEBUTTON(1) = 0 AND lastButton% THEN EXIT DO
  1125.                 y% = (yOffset% + y%) * 160 + 1
  1126.                 FOR x% = 0 TO 119 STEP 2
  1127.                     POKE y% + x%, PEEK(y% + x%) OR &H10
  1128.                 NEXT
  1129.             ELSE
  1130.                 y% = 0
  1131.             END IF
  1132.         ELSE
  1133.             IF y% > 0 AND y% - 1 <= numAspect% THEN
  1134.                 IF _MOUSEBUTTON(1) THEN
  1135.                     selectedAspect% = y% - 1
  1136.                     reprint% = 1
  1137.                 END IF
  1138.                 y% = (yOffset% + y%) * 160 + 1
  1139.                 FOR x% = 120 TO 159 STEP 2
  1140.                     POKE y% + x%, PEEK(y% + x%) OR &H10
  1141.                 NEXT
  1142.             ELSE
  1143.                 y% = 0
  1144.             END IF
  1145.         END IF
  1146.         lastY% = y%
  1147.         lastButton% = _MOUSEBUTTON(1)
  1148.     END IF
  1149.  
  1150. selectScreenMode& = _NEWIMAGE(vidX%(y%), vidY%(y%), colors%)
  1151.  
  1152.  

« Last Edit: August 08, 2018, 11:19:42 PM by odin »