@@ 0,0 1,65 @@
+require 'files'
+
+magnitude=: +/ &.: *:
+normalize=: * %@magnitude NB. scale by reciprocal of magnitude
+dotproduct=: +/ . *
+toRGB=: ([: <.&255 >.&0) @ ([: <. 255&*)
+reflect=: [ - ] * +:@dotproduct NB. (vector normal)
+coordinates=: [: ,"0/~ i.
+hit=: <./ @: #~ 0&< NB. smallest positive intersection
+
+intersect=: dyad define NB. (origin direction)
+a=. y dotproduct y
+b=. 2 * y dotproduct x
+c=. (x dotproduct x) - 1
+discriminant=. (*: b) - (4 * a * c)
+if. discriminant >: 0 do.
+ i1=. ((- b) - (%: discriminant)) % +: a
+ i2=. ((- b) + (%: discriminant)) % +: a
+ i1 ; i2
+else.
+ 0 NB. lest we return the last calculated value...
+end.
+)
+
+lighting=: monad define
+'light material position eye normal'=. y
+'lPosition lIntensity'=. light
+'mAmbient mDiffuse mSpecular mShiny mColor'=. material
+effectiveColor=. (1,1,1) * lIntensity
+ambient=. effectiveColor * mAmbient
+lightv=. normalize lPosition - position
+l=. lightv dotproduct normal
+r=. ((- lightv) reflect normal) dotproduct eye
+diffuse=. (l>:0) { > (0 0 0) ; l * effectiveColor * mDiffuse
+specular=. (r>:0) { > (0 0 0) ; lIntensity * mSpecular * r ^ mShiny
+ambient + diffuse + specular
+)
+
+trace=: dyad define NB. (width (x y)) e.g. 300 trace"1 (coordinates 300)
+'xcoord ycoord'=. y
+rOrigin=. 0 0 _5
+wallZ=. 10
+wallSize=. 7.0
+pixelSize=. wallSize % x
+position=. ((- -: wallSize) + pixelSize * xcoord) , ((-: wallSize) - pixelSize * ycoord) , wallZ
+rDirection=. normalize position - rOrigin
+contactTime=. hit >rOrigin intersect rDirection
+if. contactTime do.
+ pos=. rOrigin + rDirection * contactTime
+ normal=. normalize pos
+ eye=. -rDirection
+ light=. (_10 _10 _10); (0.7 0.7 0.7) NB. position intensity
+ material=. 0.1 ; 0.9 ; 0.9 ; 300 ; 1 1 1 NB. ambient diffuse specular shiny color
+ lighting light; material ; pos; eye; normal
+else.
+ 0 0 0
+end.
+)
+
+writePPM=: dyad define NB. (array filename) TODO wrap at 70 characters
+header=. 'P3', LF, (": 0 1 { $x), LF, '255', LF
+(header, (": toRGB ,,/x), LF) fwrite y
+)
+
+NB. (300 trace"1 (coordinates 300)) writePPM '/tmp/test.ppm'
No newline at end of file