1 #ifndef DEPTHOFFIELDCAMERA_HXX
2 #define DEPTHOFFIELDCAMERA_HXX
3
4 #include "Camera.hxx"
5 #include "Randomizer.hxx"
6
7 // The basic idea of this camera is the same as for the PerspectiveCamera.
8 // Only the InitRay method differs: Here, Rays are not initialized correctly,
9 // but rays from a randomized point on the lens to the intersection point
10 // of the "clean" ray with the focal plane are set up. This method implies
11 // a greater number of samples (which should be applied anyway).
12
13 // As this camera constitutes a lens camera, i.e. the opening angle is independent
14 // from the viewing frustrum, our implementation considers this as well.
15 // However, if no parameter is given, we behave as if we were a PerspectiveCam
16 // (with real focus calculations though, not with the approximation we do in our
17 // PerspectiveCamera).
18
19 class DepthOfFieldCamera : public Camera
20 {
21 // input values
22 Vec3f pos,dir,up;
23 float angle;
24 float focus;
25
26 // preprocessed values
27 float radius;
28 Vec3f xAxis,yAxis,zAxis;
29 float aspect;
30
31 // a working randomizer...
32 Randomizer randomizer;
33 public:
34 DepthOfFieldCamera(Vec3f pos, Vec3f dir, Vec3f up,
35 float angle, float radius,
36 int resX, int resY, float focus = -1.0f
37 )
38 : Camera(resX,resY),pos(pos),dir(dir),up(up),angle(angle),focus(focus),radius(radius)
39 {
40 // Optional fallback solution (see above)
41 if (this->focus < 0.0f)
42 this->focus = 1.0f / tan(angle * M_PI / 360.0f);
43
44 // usual stuff as in PerspectiveCam
45 aspect = static_cast<float>(resX) / static_cast<float>(resY);
46
47 Normalize(this->up);
48 Normalize(this->dir);
49
50 // Axis precomputation. Z contains all further precomputations,
51 // including that rays are shot through the middle of the pixels
52 // ("+1")
53 xAxis = Cross(-this->up, this->dir);
54 yAxis = Cross(xAxis, this->dir);
55 zAxis = static_cast<float>(resY) / (tan(angle * M_PI / 360.0f) * 2.0f) * this->dir - (xAxis * (resX - 1.0f) + yAxis * (resY - 1.0f)) / 2.0f;
56 }
57
58 virtual ~DepthOfFieldCamera(){};
59
60 // Returns random points on the lens disc of the cam
61 Vec3f GetSurfacePoint()
62 {
63 Vec3f point = pos;
64 float x = randomizer.drand(),
65 y = randomizer.drand();
66
67 point += (x * xAxis + y * sqrt(1 - x * x) * yAxis) * radius;
68
69 return point;
70 }
71
72 virtual bool InitRay(float x, float y, Ray &ray)
73 {
74 ray.org = GetSurfacePoint();
75
76 // Get the "clean" ray (for intersection point
77 // with the focal plane)
78 ray.dir = xAxis * x + yAxis * y + zAxis;
79 Normalize(ray.dir);
80
81 // Now calculate the new ray direction
82 ray.dir = (pos + ray.dir * focus) - ray.org;
83 Normalize(ray.dir);
84
85 // The usual crap (as with every camera)
86 ray.t = Infinity;
87 ray.hit = NULL;
88
89 return true;
90 };
91
92 #ifdef STEREOVIEW
93 virtual bool InitRay(float x, float y, Ray &ray, float eyedistance)
94 {
95 ray.org = GetSurfacePoint() + xAxis * eyedistance;
96
97 // Get the "clean" ray (for intersection point
98 // with the focal plane)
99 ray.dir = xAxis * x + yAxis * y + zAxis;
100 Normalize(ray.dir);
101
102 // Now calculate the new ray direction
103 ray.dir = (pos + xAxis * eyedistance + ray.dir * focus) - ray.org;
104 Normalize(ray.dir);
105
106 // The usual crap (as with every camera)
107 ray.t = Infinity;
108 ray.hit = NULL;
109
110 return true;
111 };
112 #endif
113
114 };
115 #endif
syntax highlighted by Code2HTML, v. 0.9.1