[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