Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

camera.cpp

Go to the documentation of this file.
00001 /*
00002     toxic - A Global Illumination Renderer
00003     Copyright (C) 2003-2004 Francois Beaune
00004     Contact: http://toxicengine.sourceforge.net/
00005 
00006     This file is part of toxic.
00007 
00008     toxic is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012 
00013     toxic is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License
00019     along with toxic; if not, write to the Free Software
00020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 */
00022 
00023 #include "camera.h" // include first
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 /*= DEFAULT_CAMERA_FOV*/,
00037                Real aspect_ratio /*= DEFAULT_CAMERA_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         // Create a ray with origin at the lens center and directed toward the
00064         // specified location on the film plane.
00065         Ray ray(Ray::AUTOFOCUS_RAY);
00066         ray.m_origin = m_location;
00067         ray.m_direction =
00068             m_autofocus_target.m_x * m_u +  // m_u = m_ex * m_aspect_ratio
00069             m_autofocus_target.m_y * m_ey +
00070             m_w;            // m_w = m_ez * (-m_focal_length)
00071         ray.m_direction.Normalize();
00072 
00073         // Cast a ray through the scene to compute focal distance. If the ray
00074         // don't hit any object, focal distance is not altered.
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     // Compute lens radius.
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 { //!< Returned ray is expressed in world space.
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     // Create a ray starting at the lens center and directed toward the specified location
00108     // on the film plane.
00109     Ray ray(Ray::PRIMARY_RAY);
00110     ray.m_origin = m_location;
00111     ray.m_direction =
00112         p.m_x * m_u +   // m_u = m_ex * m_aspect_ratio
00113         p.m_y * m_ey +
00114         m_w;            // m_w = m_ez * (-m_focal_length)
00115     ray.m_direction.Normalize();
00116 
00117     if(m_is_dof_enabled) {
00118         // Intersect the ray with the focal plane (the plane of focus).
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         // Randomly choose a location on the lens surface (note: we're under the thin lens approximation).
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         // Update ray's origin.
00129         ray.m_origin +=
00130             lens_sample.m_x * m_ex +
00131             lens_sample.m_y * m_ey;
00132 
00133         // Update ray's direction.
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 }

Generated on Tue May 11 01:31:49 2004 for toxic by doxygen 1.3.6