00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "camera.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 Camera::Camera(const Matrix4 &m,
00036 Real hfov ,
00037 Real aspect_ratio ) :
00038 Basis(m),
00039 m_location(TransformToWorld(Point3(0.0))),
00040 m_ex(TransformToWorld(Vector3(1.0, 0.0, 0.0))),
00041 m_ey(TransformToWorld(Vector3(0.0, 1.0, 0.0))),
00042 m_ez(TransformToWorld(Vector3(0.0, 0.0, 1.0))),
00043 m_hfov(hfov),
00044 m_aspect_ratio(aspect_ratio),
00045 m_is_dof_enabled(false),
00046 m_dof_fstop(0.0),
00047 m_dof_focal_length(0.0),
00048 m_dof_focal_distance(0.0),
00049 m_dof_lens_radius(0.0),
00050 m_is_autofocus_enabled(false),
00051 m_autofocus_target(Point2(0.0))
00052 {
00053 assert(m_hfov > -PI && m_hfov < PI);
00054
00055 m_focal_length = m_aspect_ratio / tan(0.5 * m_hfov);
00056
00057 m_u = m_ex * m_aspect_ratio;
00058 m_w = m_ez * (-m_focal_length);
00059 }
00060
00061 void Camera::Finalize(const Context &context, const Scene *scene) {
00062 if(m_is_autofocus_enabled) {
00063
00064
00065 Ray ray(Ray::AUTOFOCUS_RAY);
00066 ray.m_origin = m_location;
00067 ray.m_direction =
00068 m_autofocus_target.m_x * m_u +
00069 m_autofocus_target.m_y * m_ey +
00070 m_w;
00071 ray.m_direction.Normalize();
00072
00073
00074
00075 Hit hit;
00076 if(scene->Trace(context, ray, &hit))
00077 m_dof_focal_distance = hit.m_abscissa;
00078 }
00079 }
00080
00081 void Camera::EnableDepthOfField(Real fstop, Real focal_length, Real focal_distance) {
00082 assert(fstop > 0.0);
00083 assert(focal_length >= 0.0);
00084 assert(focal_distance >= 0.0);
00085
00086 m_is_dof_enabled = true;
00087 m_dof_fstop = fstop;
00088 m_dof_focal_length = focal_length;
00089 m_dof_focal_distance = focal_distance;
00090
00091
00092 m_dof_lens_radius = 0.5 * m_dof_focal_length / m_dof_fstop;
00093 }
00094
00095 void Camera::EnableAutoFocus(const Point2 &p) {
00096 assert(p.m_x >= -0.5 && p.m_x <= 0.5);
00097 assert(p.m_y >= -0.5 && p.m_y <= 0.5);
00098
00099 m_is_autofocus_enabled = true;
00100 m_autofocus_target = p;
00101 }
00102
00103 Ray Camera::ComputeRay(const Context &context, const Point2 &p) const {
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 if(m_is_dof_enabled) {
00118
00119 const Real t = -m_dof_focal_distance / (ray.m_direction * m_ez);
00120 assert(t >= 0.0);
00121 const Point3 p = ray.GetPointAt(t);
00122
00123
00124 const Real xi1 = context.m_rng->RandomReal1();
00125 const Real xi2 = context.m_rng->RandomReal1();
00126 const Vector2 lens_sample = m_dof_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 = (p - ray.m_origin).Normalized();
00135 }
00136
00137 assert(ray.m_direction.IsUnitLength());
00138
00139 return ray;
00140 }
00141
00142 Point2 Camera::Project(const Point3 &p) const {
00143 Vector3 xi = p - m_location;
00144 assert(xi * m_ez != 0.0);
00145
00146 xi *= -m_focal_length / (xi * m_ez);
00147
00148 return Point2(xi * m_ex / m_aspect_ratio, xi * m_ey);
00149 }