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