annotate demos/ray.cpp @ 650:aa6a0b7968f7

Added test case for bug #100 Removed dubious check for not emitting static private global in other modules without access. This should be handled properly somewhere else, it's causing unresolved global errors for stuff that should work (in MiniD)
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Sun, 05 Oct 2008 17:28:15 +0200
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 }