Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/distort/fisheyeLens.cxx

Go to the documentation of this file.
00001 // Filename: fisheyeLens.cxx
00002 // Created by:  drose (12Dec01)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "fisheyeLens.h"
00020 #include "deg_2_rad.h"
00021 
00022 TypeHandle FisheyeLens::_type_handle;
00023 
00024 // This is the focal-length constant for fisheye lenses.  The focal
00025 // length of a fisheye lens relates to its fov by the equation:
00026 
00027 //   w = Fd/k
00028 
00029 // Where w is the width of the negative, F is the focal length, and d
00030 // is the total field of view in degrees.
00031 
00032 // k is chosen to make the focal lengths for a fisheye lens roughly
00033 // correspond to the equivalent field of view for a conventional,
00034 // perspective lens.  It was determined empirically by simple
00035 // examination of a couple of actual lenses for 35mm film.  I don't
00036 // know how well this extends to other lenses and other negative
00037 // sizes.
00038 
00039 static const float fisheye_k = 60.0f;
00040 // focal_length = film_size * fisheye_k / fov;
00041 
00042 
00043 ////////////////////////////////////////////////////////////////////
00044 //     Function: FisheyeLens::make_copy
00045 //       Access: Public, Virtual
00046 //  Description: Allocates a new Lens just like this one.
00047 ////////////////////////////////////////////////////////////////////
00048 PT(Lens) FisheyeLens::
00049 make_copy() const {
00050   return new FisheyeLens(*this);
00051 }
00052 
00053 ////////////////////////////////////////////////////////////////////
00054 //     Function: FisheyeLens::extrude_impl
00055 //       Access: Protected, Virtual
00056 //  Description: Given a 2-d point in the range (-1,1) in both
00057 //               dimensions, where (0,0) is the center of the
00058 //               lens and (-1,-1) is the lower-left corner,
00059 //               compute the corresponding vector in space that maps
00060 //               to this point, if such a vector can be determined.
00061 //               The vector is returned by indicating the points on
00062 //               the near plane and far plane that both map to the
00063 //               indicated 2-d point.
00064 //
00065 //               The z coordinate of the 2-d point is ignored.
00066 //
00067 //               Returns true if the vector is defined, or false
00068 //               otherwise.
00069 ////////////////////////////////////////////////////////////////////
00070 bool FisheyeLens::
00071 extrude_impl(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) const {
00072   // Undo the shifting from film offsets, etc.  This puts the point
00073   // into the range [-film_size/2, film_size/2] in x and y.
00074   LPoint3f f = point2d * get_film_mat_inv();
00075 
00076   // First, get the vector from the center of the film to the point,
00077   // and normalize it.
00078   LVector2f v2(f[0], f[1]);
00079 
00080   LPoint3f v;
00081 
00082   float r = v2.length();
00083   if (r == 0.0f) {
00084     // Special case: directly forward.
00085     v.set(0.0f, 1.0f, 0.0f);
00086 
00087   } else {
00088     v2 /= r;
00089 
00090     // Now get the point r units around the circle in the YZ plane.
00091     float focal_length = get_focal_length();
00092     float angle = r * fisheye_k / focal_length;
00093     float sinAngle, cosAngle;
00094     csincos(deg_2_rad(angle), &sinAngle, &cosAngle);
00095 
00096     LVector3f p(0.0, cosAngle, sinAngle);
00097 
00098     // And rotate this point around the Y axis.
00099     v.set(p[0]*v2[1] + p[2]*v2[0],
00100           p[1],
00101           p[2]*v2[1] - p[0]*v2[0]);
00102   }
00103 
00104   // And we'll need to account for the lens's rotations, etc. at the
00105   // end of the day.
00106   const LMatrix4f &lens_mat = get_lens_mat();
00107 
00108   near_point = (v * get_near()) * lens_mat;
00109   far_point = (v * get_far()) * lens_mat;
00110   return true;
00111 }
00112 
00113 ////////////////////////////////////////////////////////////////////
00114 //     Function: FisheyeLens::project_impl
00115 //       Access: Protected, Virtual
00116 //  Description: Given a 3-d point in space, determine the 2-d point
00117 //               this maps to, in the range (-1,1) in both dimensions,
00118 //               where (0,0) is the center of the lens and
00119 //               (-1,-1) is the lower-left corner.
00120 //
00121 //               Some lens types also set the z coordinate of the 2-d
00122 //               point to a value in the range (-1, 1), where 1
00123 //               represents a point on the near plane, and -1
00124 //               represents a point on the far plane.
00125 //
00126 //               Returns true if the 3-d point is in front of the lens
00127 //               and within the viewing frustum (in which case point2d
00128 //               is filled in), or false otherwise.
00129 ////////////////////////////////////////////////////////////////////
00130 bool FisheyeLens::
00131 project_impl(const LPoint3f &point3d, LPoint3f &point2d) const {
00132   // First, account for any rotations, etc. on the lens.
00133   LVector3f v2 = point3d * get_lens_mat_inv();
00134 
00135   // A fisheye lens projection has the property that the distance from
00136   // the center point to any other point on the projection is
00137   // proportional to the actual distance on the sphere along the great
00138   // circle.  Also, the angle to the point on the projection is equal
00139   // to the angle to the point on the sphere.
00140 
00141   // First, get the straight-line distance from the lens, and use it
00142   // to normalize the vector.
00143   float dist = v2.length();
00144   v2 /= dist;
00145 
00146   // Now, project the point into the XZ plane and measure its angle
00147   // to the Z axis.  This is the same angle it will have to the
00148   // vertical axis on the film.
00149   LVector2f y(v2[0], v2[2]);
00150   y.normalize();
00151 
00152   if (y == LVector2f(0.0f, 0.0f)) {
00153     // Special case.  This point is either directly ahead or directly
00154     // behind.
00155     point2d.set(0.0f, 0.0f, 
00156                 (get_near() - dist) / (get_far() - get_near()));
00157     return v2[1] >= 0.0f;
00158   }
00159 
00160   // Now bring the vector into the YZ plane by rotating about the Y
00161   // axis.
00162   LVector2f x(v2[1], v2[0]*y[0]+v2[2]*y[1]);
00163 
00164   // Now the angle of x to the forward vector represents the distance
00165   // along the great circle to the point.
00166   float r = 90.0f - rad_2_deg(catan2(x[0], x[1]));
00167 
00168   float focal_length = get_focal_length();
00169   float factor = r * focal_length / fisheye_k;
00170 
00171   point2d.set
00172     (y[0] * factor,
00173      y[1] * factor,
00174      // Z is the distance scaled into the range (1, -1).
00175      (get_near() - dist) / (get_far() - get_near())
00176      );
00177 
00178   // Now we have to transform the point according to the film
00179   // adjustments.
00180   point2d = point2d * get_film_mat();
00181 
00182   return
00183     point2d[0] >= -1.0f && point2d[0] <= 1.0f && 
00184     point2d[1] >= -1.0f && point2d[1] <= 1.0f;
00185 }
00186 
00187 ////////////////////////////////////////////////////////////////////
00188 //     Function: FisheyeLens::fov_to_film
00189 //       Access: Protected, Virtual
00190 //  Description: Given a field of view in degrees and a focal length,
00191 //               compute the correspdonding width (or height) on the
00192 //               film.  If horiz is true, this is in the horizontal
00193 //               direction; otherwise, it is in the vertical direction
00194 //               (some lenses behave differently in each direction).
00195 ////////////////////////////////////////////////////////////////////
00196 float FisheyeLens::
00197 fov_to_film(float fov, float focal_length, bool) const {
00198   return focal_length * fov / fisheye_k;
00199 }
00200 
00201 ////////////////////////////////////////////////////////////////////
00202 //     Function: FisheyeLens::fov_to_focal_length
00203 //       Access: Protected, Virtual
00204 //  Description: Given a field of view in degrees and a width (or
00205 //               height) on the film, compute the focal length of the
00206 //               lens.  If horiz is true, this is in the horizontal
00207 //               direction; otherwise, it is in the vertical direction
00208 //               (some lenses behave differently in each direction).
00209 ////////////////////////////////////////////////////////////////////
00210 float FisheyeLens::
00211 fov_to_focal_length(float fov, float film_size, bool) const {
00212   return film_size * fisheye_k / fov;
00213 }
00214 
00215 ////////////////////////////////////////////////////////////////////
00216 //     Function: FisheyeLens::film_to_fov
00217 //       Access: Protected, Virtual
00218 //  Description: Given a width (or height) on the film and a focal
00219 //               length, compute the field of view in degrees.  If
00220 //               horiz is true, this is in the horizontal direction;
00221 //               otherwise, it is in the vertical direction (some
00222 //               lenses behave differently in each direction).
00223 ////////////////////////////////////////////////////////////////////
00224 float FisheyeLens::
00225 film_to_fov(float film_size, float focal_length, bool) const {
00226   return film_size * fisheye_k / focal_length;
00227 }
00228 

Generated on Fri May 2 00:36:38 2003 for Panda by doxygen1.3