// Normally we'd use double.Epsilon public static void Main (String[] args, ILog ilog) { int n = 0; if (args.Length > 0) n = Int32.Parse (args [0]); Scene scene = Scene.SphereScene (levels, new Vector (0.0, -1.0, 0.0), 1.0); ilog.InfoFormat ("P5"); ilog.InfoFormat ("{0} {1}", n, n); ilog.InfoFormat ("255"); Stream stream = Stream.Null; byte[] temp = new byte[1]; for (int y = n - 1; y >= 0; --y) { for (int x = 0; x < n; ++x) { double greyscale = 0.0; for (int dx = 0; dx < ss; ++dx) { for (int dy = 0; dy < ss; ++dy) { Vector v = new Vector ( x + dx / (double)ss - n / 2.0 , y + dy / (double)ss - n / 2.0 , n); Ray ray = new Ray (new Vector (0.0, 0.0, -4.0), v.Normalized ()); greyscale += scene.TraceRay (ray, new Vector (-1.0, -3.0, 2.0).Normalized ()); } } temp [0] = (byte)(0.5 + 255.0 * greyscale / (ss * ss)); stream.Write (temp, 0, 1); } } }
internal double TraceRay (Ray ray, Vector light) { IntersectionPoint p = Intersect (ray, new IntersectionPoint ( double.PositiveInfinity, new Vector (0.0, 0.0, 0.0))); if (double.IsInfinity (p.distance)) return 0.0; double greyscale = -(p.normal * light); if (greyscale <= 0.0) return 0.0; Vector o = ray.origin + (p.distance * ray.direction) + (Epsilon * p.normal); Ray shadowRay = new Ray (o, new Vector (0.0, 0.0, 0.0) - light); IntersectionPoint shadowp = Intersect (shadowRay, new IntersectionPoint (double.PositiveInfinity, p.normal)); return double.IsInfinity (shadowp.distance) ? greyscale : 0.0; }
abstract internal IntersectionPoint Intersect (Ray ray, IntersectionPoint p);
override internal IntersectionPoint Intersect (Ray r, IntersectionPoint p) { if (bound.Distance (r) < p.distance) { foreach (Scene each in scenes) p = each.Intersect (r, p); } return p; }
override internal IntersectionPoint Intersect (Ray r, IntersectionPoint p) { double d = Distance (r); if (d < p.distance) { Vector v = r.origin + ((d * r.direction) - center); p = new IntersectionPoint (d, v.Normalized ()); } return p; }
internal double Distance (Ray ray) { Vector v = center - ray.origin; double b = v * ray.direction; double disc = b * b - v * v + radius * radius; if (disc < 0) return double.PositiveInfinity; // No intersection double d = Math.Sqrt (disc); double t1 = b + d; if (t1 < 0) return double.PositiveInfinity; double t2 = b - d; return t2 > 0 ? t2 : t1; }