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

thinlenscamera.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 "thinlenscamera.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 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     // Compute camera lens radius.
00044     assert(fstop > 0.0);
00045     assert(focal_length >= 0.0);
00046     m_lens_radius = 0.5 * focal_length / fstop;
00047 
00048     // Set camera focal distance.
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     // Compute camera lens radius.
00063     assert(fstop > 0.0);
00064     assert(focal_length >= 0.0);
00065     m_lens_radius = 0.5 * focal_length / fstop;
00066 
00067     // Camera focal distance will be computed by the autofocus
00068     // mechanism in the Finalize() method.
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         // Create a ray with origin at the lens center and directed toward the
00080         // specified location on the film plane.
00081         Ray ray(Ray::AUTOFOCUS_RAY);
00082         ray.m_origin = m_location;
00083         ray.m_direction =
00084             m_af_target.m_x * m_u +     // m_u = m_ex * m_aspect_ratio
00085             m_af_target.m_y * m_ey +
00086             m_w;                        // m_w = m_ez * (-m_focal_length)
00087         ray.m_direction.Normalize();
00088 
00089         // Cast a ray through the scene to compute focal distance. If the ray
00090         // don't hit any object, throw an exception.
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     // Create a ray with origin at the lens center and directed toward
00108     // the specified location 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     // Intersect the ray with the focal plane (the plane of focus).
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     // Randomly choose a location on the lens surface (the lens surface
00123     // is approximated by a disk: this is 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_lens_radius * UniformDiskSampling(xi1, xi2);
00127 
00128     // Shift origin of the ray.
00129     ray.m_origin +=
00130         lens_sample.m_x * m_ex +
00131         lens_sample.m_y * m_ey;
00132 
00133     // Compute new direction of the ray.
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 }

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