[svn] r5974: nemerle/trunk/snippets/raytracer/ray-compressed.n
malekith
svnadmin at nemerle.org
Sun Nov 27 19:08:03 CET 2005
Log:
Add compressed version (like the one in OCaml). It's only 2 lines longer than the OCaml one.
Author: malekith
Date: Sun Nov 27 19:08:03 2005
New Revision: 5974
Added:
nemerle/trunk/snippets/raytracer/ray-compressed.n
Added: nemerle/trunk/snippets/raytracer/ray-compressed.n
==============================================================================
--- (empty file)
+++ nemerle/trunk/snippets/raytracer/ray-compressed.n Sun Nov 27 19:08:03 2005
@@ -0,0 +1,61 @@
+#pragma indent
+[Record] struct Vec
+ x : double; y : double; z : double
+ public static @*(s:double, r:Vec) :Vec { Vec(s*r.x, s*r.y, s*r.z) }
+ public static @+(s:Vec, r:Vec) :Vec { Vec(s.x+r.x, s.y+r.y, s.z+r.z) }
+ public static @-(s:Vec, r:Vec) :Vec { Vec (s.x-r.x, s.y-r.y, s.z-r.z) }
+ public static @**(s:Vec, r:Vec) :double { s.x*r.x + s.y*r.y + s.z*r.z }
+ public Unitise () : Vec { (1 / System.Math.Sqrt (this ** this)) * this }
+variant Scene
+ | Sphere { m : Vec; r : double; }
+ | Group { m : Vec; r : double; l : list [Scene]; }
+def delta = 1.49011611938476562e-08; def inf = double.PositiveInfinity
+def ray_sphere (orig, dir, center, radius : double)
+ def v = center - orig; def b = v ** dir
+ def disc = b * b - (v ** v) + radius * radius
+ if (disc < 0) inf else
+ def disc = System.Math.Sqrt (disc)
+ def t2 = b + disc; def t1 = b - disc
+ if (t2 < 0) inf else if (t1 > 0) t1 else t2
+def intersect (orig, dir : Vec, scene)
+ def aux (elt, first)
+ def l = first [0]
+ match (elt)
+ | Scene.Sphere (center, radius) =>
+ def l' = ray_sphere (orig, dir, center, radius)
+ if (l' >= l) first else (l', (orig + l' * dir - center).Unitise ())
+ | Scene.Group (center, radius, scenes) =>
+ def l' = ray_sphere (orig, dir, center, radius)
+ if (l' >= l) first else scenes.FoldLeft (first, aux)
+ aux (scene, (inf, Vec ()))
+def ray_trace (light, orig, dir, scene)
+ def (lambda, normal) = intersect (orig, dir, scene)
+ if (lambda == inf) 0.0 else
+ def g = normal ** light
+ if (g >= 0) 0.0 else
+ def p = orig + lambda * dir + delta * normal
+ if ((intersect (p, -1 * light, scene)) [0] < inf) 0.0 else -g
+def create (level, c, r)
+ def obj = Scene.Sphere (c, r)
+ if (level == 1) obj else
+ def a = 3 * r / System.Math.Sqrt (12)
+ def aux (x', z') { create (level - 1, c + Vec (x', a, z'), 0.5 * r) }
+ Scene.Group (c, 3*r, [obj, aux (-a,-a), aux (a,-a), aux (-a,a), aux (a,a)])
+def main (level, n)
+ def scene = create (level, Vec (0, -1, 0), 1)
+ def light = Vec (-1, -3, 2).Unitise (); def ss = 4
+ System.Console.Write ($ "P5\n$n $n\n255\n")
+ def s = System.Console.OpenStandardOutput ()
+ for (mutable y = n - 1; y >= 0; y--)
+ for (mutable x = 0; x < n; x++)
+ mutable g = 0.0
+ for (mutable dx = 0; dx < ss; dx++)
+ for (mutable dy = 0; dy < ss; dy++)
+ def aux (x, d) { x - n / 2.0 + d / (ss :> double) }
+ def dir = Vec (aux (x, dx), aux (y, dy), n).Unitise ()
+ g += ray_trace (light, Vec (0,0,-4), dir, scene)
+ s.WriteByte ((0.5 + 255 * g / (ss*ss)) :> byte)
+match (Nemerle.Collections.List.FromArray (
+ System.Environment.GetCommandLineArgs()))
+ | [_, level, n] => main (int.Parse (level), int.Parse (n))
+ | _ => main (9, 512)
More information about the svn
mailing list