00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "thinlenscamera.h"
00024 #include "common/math/sampling.h"
00025 #include "context.h"
00026 #include "ray.h"
00027 #include "scene.h"
00028
00029 #include <cassert>
00030 #include <cmath>
00031
00032 using namespace sheep;
00033 using namespace toxic;
00034
00035 ThinLensCamera::ThinLensCamera(const Matrix4 &m,
00036 Real hfov,
00037 Real aspect_ratio,
00038 Real fstop,
00039 Real focal_length,
00040 Real focal_distance) :
00041 ICamera(m, hfov, aspect_ratio)
00042 {
00043
00044 assert(fstop > 0.0);
00045 assert(focal_length >= 0.0);
00046 m_lens_radius = 0.5 * focal_length / fstop;
00047
00048
00049 m_af_enabled = false;
00050 assert(focal_distance >= 0.0);
00051 m_focal_distance = focal_distance;
00052 }
00053
00054 ThinLensCamera::ThinLensCamera(const Matrix4 &m,
00055 Real hfov,
00056 Real aspect_ratio,
00057 Real fstop,
00058 Real focal_length,
00059 const Point2 &af_target) :
00060 ICamera(m, hfov, aspect_ratio)
00061 {
00062
00063 assert(fstop > 0.0);
00064 assert(focal_length >= 0.0);
00065 m_lens_radius = 0.5 * focal_length / fstop;
00066
00067
00068
00069 assert(af_target.m_x >= -0.5 && af_target.m_x <= 0.5);
00070 assert(af_target.m_y >= -0.5 && af_target.m_y <= 0.5);
00071 m_af_enabled = true;
00072 m_af_target = af_target;
00073 }
00074
00075 void ThinLensCamera::Finalize(const Context &context,
00076 const Scene *scene)
00077 {
00078 if(m_af_enabled) {
00079
00080
00081 Ray ray(Ray::AUTOFOCUS_RAY);
00082 ray.m_origin = m_location;
00083 ray.m_direction =
00084 m_af_target.m_x * m_u +
00085 m_af_target.m_y * m_ey +
00086 m_w;
00087 ray.m_direction.Normalize();
00088
00089
00090
00091 Hit hit;
00092 if(scene->Trace(context, ray, &hit))
00093 m_focal_distance = hit.m_abscissa;
00094 else {
00095 assert(!"Could not compute focal distance.");
00096 throw "Could not compute focal distance.";
00097 }
00098 }
00099 }
00100
00101 Ray ThinLensCamera::ComputeRay(const Context &context,
00102 const Point2 &p) const
00103 {
00104 assert(p.m_x >= -0.5 && p.m_x <= 0.5);
00105 assert(p.m_y >= -0.5 && p.m_y <= 0.5);
00106
00107
00108
00109 Ray ray(Ray::PRIMARY_RAY);
00110 ray.m_origin = m_location;
00111 ray.m_direction =
00112 p.m_x * m_u +
00113 p.m_y * m_ey +
00114 m_w;
00115 ray.m_direction.Normalize();
00116
00117
00118 const Real t = -m_focal_distance / (ray.m_direction * m_ez);
00119 assert(t >= 0.0);
00120 const Point3 pt_on_fp = ray.GetPointAt(t);
00121
00122
00123
00124 const Real xi1 = context.m_rng->RandomReal1();
00125 const Real xi2 = context.m_rng->RandomReal1();
00126 const Vector2 lens_sample = m_lens_radius * UniformDiskSampling(xi1, xi2);
00127
00128
00129 ray.m_origin +=
00130 lens_sample.m_x * m_ex +
00131 lens_sample.m_y * m_ey;
00132
00133
00134 ray.m_direction = (pt_on_fp - ray.m_origin).Normalized();
00135
00136 return ray;
00137 }
00138
00139 Point2 ThinLensCamera::Project(const Point3 &p) const {
00140 Vector3 xi = p - m_location;
00141 assert(xi * m_ez != 0.0);
00142
00143 xi *= -m_focal_length / (xi * m_ez);
00144
00145 return Point2(xi * m_ex / m_aspect_ratio, xi * m_ey);
00146 }