annotate demos/ray.cpp @ 1638:0de4525a9ed6

Apply workaround for #395 by klickverbot.
author Christian Kamm <kamm incasoftware de>
date Mon, 08 Mar 2010 20:06:08 +0100
parents 90522b72128a
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
180
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
1 #include <list>
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
2 #include <iostream>
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
3 #include <limits>
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
4 #include <cmath>
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
5 #include <cstdlib>
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
6
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
7 using namespace std;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
8
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
9 numeric_limits<double> real;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
10 double delta = sqrt(real.epsilon()), infinity = real.infinity();
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
11
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
12 struct Vec {
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
13 double x, y, z;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
14 Vec(double x2, double y2, double z2) : x(x2), y(y2), z(z2) {}
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
15 };
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
16 Vec operator+(const Vec &a, const Vec &b)
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
17 { return Vec(a.x+b.x, a.y+b.y, a.z+b.z); }
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
18 Vec operator-(const Vec &a, const Vec &b)
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
19 { return Vec(a.x-b.x, a.y-b.y, a.z-b.z); }
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
20 Vec operator*(double a, const Vec &b) { return Vec(a*b.x, a*b.y, a*b.z); }
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
21 double dot(const Vec &a, const Vec &b) { return a.x*b.x + a.y*b.y + a.z*b.z; }
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
22 Vec unitise(const Vec &a) { return (1 / sqrt(dot(a, a))) * a; }
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
23
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
24 typedef pair<double, Vec> Hit;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
25
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
26 struct Ray {
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
27 Vec orig, dir;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
28 Ray(const Vec &o, const Vec &d) : orig(o), dir(d) {}
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
29 };
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
30
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
31 struct Scene {
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
32 virtual ~Scene() {};
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
33 virtual void intersect(Hit &, const Ray &) const = 0;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
34 };
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
35
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
36 struct Sphere : public Scene {
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
37 Vec center;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
38 double radius;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
39
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
40 Sphere(Vec c, double r) : center(c), radius(r) {}
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
41 ~Sphere() {}
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
42
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
43 double ray_sphere(const Ray &ray) const {
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
44 Vec v = center - ray.orig;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
45 double b = dot(v, ray.dir), disc = b*b - dot(v, v) + radius * radius;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
46 if (disc < 0) return infinity;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
47 double d = sqrt(disc), t2 = b + d;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
48 if (t2 < 0) return infinity;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
49 double t1 = b - d;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
50 return (t1 > 0 ? t1 : t2);
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
51 }
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
52
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
53 void intersect(Hit &hit, const Ray &ray) const {
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
54 double lambda = ray_sphere(ray);
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
55 if (lambda >= hit.first) return;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
56 hit = Hit(lambda, unitise(ray.orig + lambda*ray.dir - center));
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
57 }
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
58 };
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
59
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
60 typedef list<Scene *> Scenes;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
61 struct Group : public Scene {
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
62 Sphere bound;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
63 Scenes child;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
64
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
65 Group(Sphere b, Scenes c) : bound(b), child(c) {}
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
66 ~Group() {
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
67 for (Scenes::const_iterator it=child.begin(); it!=child.end(); ++it)
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
68 delete *it;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
69 }
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
70
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
71 void intersect(Hit &hit, const Ray &ray) const {
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
72 double l = bound.ray_sphere(ray);
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
73 if (l < hit.first)
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
74 for (Scenes::const_iterator it=child.begin(); it!=child.end(); ++it)
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
75 (*it)->intersect(hit, ray);
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
76 }
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
77 };
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
78
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
79 Hit intersect(const Ray &ray, const Scene &s) {
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
80 Hit res = Hit(infinity, Vec(0, 0, 0));
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
81 s.intersect(res, ray);
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
82 return res;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
83 }
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
84
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
85 double ray_trace(const Vec &light, const Ray &ray, const Scene &s) {
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
86 Hit hit = intersect(ray, s);
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
87 if (hit.first == infinity) return 0;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
88 double g = dot(hit.second, light);
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
89 if (g >= 0) return 0.;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
90 Vec p = ray.orig + hit.first*ray.dir + delta*hit.second;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
91 return (intersect(Ray(p, -1. * light), s).first < infinity ? 0 : -g);
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
92 }
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
93
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
94 Scene *create(int level, const Vec &c, double r) {
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
95 Scene *s = new Sphere(c, r);
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
96 if (level == 1) return s;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
97 Scenes child;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
98 child.push_back(s);
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
99 double rn = 3*r/sqrt(12.);
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
100 for (int dz=-1; dz<=1; dz+=2)
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
101 for (int dx=-1; dx<=1; dx+=2)
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
102 child.push_back(create(level-1, c + rn*Vec(dx, 1, dz), r/2));
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
103 return new Group(Sphere(c, 3*r), child);
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
104 }
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
105
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
106 int main(int argc, char *argv[]) {
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
107 int level = 6, n = 512, ss = 4;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
108 if (argc == 2) level = atoi(argv[1]);
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
109 Vec light = unitise(Vec(-1, -3, 2));
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
110 Scene *s(create(level, Vec(0, -1, 0), 1));
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
111 cout << "P5\n" << n << " " << n << "\n255\n";
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
112 for (int y=n-1; y>=0; --y)
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
113 for (int x=0; x<n; ++x) {
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
114 double g=0;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
115 for (int dx=0; dx<ss; ++dx)
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
116 for (int dy=0; dy<ss; ++dy) {
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
117 Vec dir(unitise(Vec(x+dx*1./ss-n/2., y+dy*1./ss-n/2., n)));
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
118 g += ray_trace(light, Ray(Vec(0, 0, -4), dir), *s);
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
119 }
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
120 cout << char(int(.5 + 255. * g / (ss*ss)));
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
121 }
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
122 delete s;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
123 return 0;
90522b72128a [svn r196] Added C++ version of the ray demo for comparing.
lindquist
parents:
diff changeset
124 }