Panda3D

cylindricalLens.cxx

00001 // Filename: cylindricalLens.cxx
00002 // Created by:  drose (12Dec01)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "cylindricalLens.h"
00016 #include "deg_2_rad.h"
00017 
00018 TypeHandle CylindricalLens::_type_handle;
00019 
00020 // This is the focal-length constant for fisheye lenses.  See
00021 // fisheyeLens.cxx.
00022 static const float cylindrical_k = 60.0f;
00023 // focal_length = film_size * cylindrical_k / fov;
00024 
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //     Function: CylindricalLens::make_copy
00028 //       Access: Public, Virtual
00029 //  Description: Allocates a new Lens just like this one.
00030 ////////////////////////////////////////////////////////////////////
00031 PT(Lens) CylindricalLens::
00032 make_copy() const {
00033   return new CylindricalLens(*this);
00034 }
00035 
00036 ////////////////////////////////////////////////////////////////////
00037 //     Function: CylindricalLens::extrude_impl
00038 //       Access: Protected, Virtual
00039 //  Description: Given a 2-d point in the range (-1,1) in both
00040 //               dimensions, where (0,0) is the center of the
00041 //               lens and (-1,-1) is the lower-left corner,
00042 //               compute the corresponding vector in space that maps
00043 //               to this point, if such a vector can be determined.
00044 //               The vector is returned by indicating the points on
00045 //               the near plane and far plane that both map to the
00046 //               indicated 2-d point.
00047 //
00048 //               The z coordinate of the 2-d point is ignored.
00049 //
00050 //               Returns true if the vector is defined, or false
00051 //               otherwise.
00052 ////////////////////////////////////////////////////////////////////
00053 bool CylindricalLens::
00054 extrude_impl(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) const {
00055   // Undo the shifting from film offsets, etc.  This puts the point
00056   // into the range [-film_size/2, film_size/2] in x and y.
00057   LPoint3f f = point2d * get_film_mat_inv();
00058 
00059   float focal_length = get_focal_length();
00060   float angle = f[0] * cylindrical_k / focal_length;
00061   float sinAngle, cosAngle;
00062   csincos(deg_2_rad(angle), &sinAngle, &cosAngle);
00063 
00064   // Define a unit vector (well, a unit vector in the XY plane, at
00065   // least) that represents the vector corresponding to this point.
00066   LPoint3f v(sinAngle, cosAngle, f[1] / focal_length);
00067 
00068   // And we'll need to account for the lens's rotations, etc. at the
00069   // end of the day.
00070   const LMatrix4f &lens_mat = get_lens_mat();
00071 
00072   near_point = (v * get_near()) * lens_mat;
00073   far_point = (v * get_far()) * lens_mat;
00074   return true;
00075 }
00076 
00077 ////////////////////////////////////////////////////////////////////
00078 //     Function: CylindricalLens::extrude_vec_impl
00079 //       Access: Protected, Virtual
00080 //  Description: Given a 2-d point in the range (-1,1) in both
00081 //               dimensions, where (0,0) is the center of the
00082 //               lens and (-1,-1) is the lower-left corner,
00083 //               compute the vector that corresponds to the view
00084 //               direction.  This will be parallel to the normal on
00085 //               the surface (the far plane) corresponding to the lens
00086 //               shape at this point.
00087 //
00088 //               See the comment block on Lens::extrude_vec_impl() for
00089 //               a more in-depth comment on the meaning of this
00090 //               vector.
00091 //
00092 //               The z coordinate of the 2-d point is ignored.
00093 //
00094 //               Returns true if the vector is defined, or false
00095 //               otherwise.
00096 ////////////////////////////////////////////////////////////////////
00097 bool CylindricalLens::
00098 extrude_vec_impl(const LPoint3f &point2d, LVector3f &vec) const {
00099   // Undo the shifting from film offsets, etc.  This puts the point
00100   // into the range [-film_size/2, film_size/2] in x and y.
00101   LPoint3f f = point2d * get_film_mat_inv();
00102 
00103   float focal_length = get_focal_length();
00104   float angle = f[0] * cylindrical_k / focal_length;
00105   float sinAngle, cosAngle;
00106   csincos(deg_2_rad(angle), &sinAngle, &cosAngle);
00107 
00108   vec = LVector3f(sinAngle, cosAngle, 0.0f) * get_lens_mat();
00109 
00110   return true;
00111 }
00112 
00113 ////////////////////////////////////////////////////////////////////
00114 //     Function: CylindricalLens::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 CylindricalLens::
00131 project_impl(const LPoint3f &point3d, LPoint3f &point2d) const {
00132   // First, account for any rotations, etc. on the lens.
00133   LPoint3f p = point3d * get_lens_mat_inv();
00134 
00135   // To compute the x position on the frame, we only need to consider
00136   // the angle of the vector about the Z axis.  Project the vector
00137   // into the XY plane to do this.
00138   LVector2f xy(p[0], p[1]);
00139 
00140   // The perspective distance is the length of this vector in the XY
00141   // plane.
00142   float pdist = xy.length();
00143   if (pdist == 0.0f) {
00144     point2d.set(0.0f, 0.0f, 0.0f);
00145     return false;
00146   }
00147 
00148   float focal_length = get_focal_length();
00149 
00150   point2d.set
00151     (
00152      // The x position is the angle about the Z axis.
00153      rad_2_deg(catan2(xy[0], xy[1])) * focal_length / cylindrical_k,
00154      // The y position is the Z height divided by the perspective
00155      // distance.
00156      p[2] * focal_length / pdist,
00157      // Z is the perspective distance scaled into the range (1, -1).
00158      (get_near() - pdist) / (get_far() - get_near())
00159      );
00160 
00161   // Now we have to transform the point according to the film
00162   // adjustments.
00163   point2d = point2d * get_film_mat();
00164 
00165   return
00166     point2d[0] >= -1.0f && point2d[0] <= 1.0f && 
00167     point2d[1] >= -1.0f && point2d[1] <= 1.0f;
00168 }
00169 
00170 ////////////////////////////////////////////////////////////////////
00171 //     Function: CylindricalLens::fov_to_film
00172 //       Access: Protected, Virtual
00173 //  Description: Given a field of view in degrees and a focal length,
00174 //               compute the correspdonding width (or height) on the
00175 //               film.  If horiz is true, this is in the horizontal
00176 //               direction; otherwise, it is in the vertical direction
00177 //               (some lenses behave differently in each direction).
00178 ////////////////////////////////////////////////////////////////////
00179 float CylindricalLens::
00180 fov_to_film(float fov, float focal_length, bool horiz) const {
00181   if (horiz) {
00182     return focal_length * fov / cylindrical_k;
00183   } else {
00184     return (ctan(deg_2_rad(fov * 0.5f)) * focal_length) * 2.0f;
00185   }
00186 }
00187 
00188 ////////////////////////////////////////////////////////////////////
00189 //     Function: CylindricalLens::fov_to_focal_length
00190 //       Access: Protected, Virtual
00191 //  Description: Given a field of view in degrees and a width (or
00192 //               height) on the film, compute the focal length of the
00193 //               lens.  If horiz is true, this is in the horizontal
00194 //               direction; otherwise, it is in the vertical direction
00195 //               (some lenses behave differently in each direction).
00196 ////////////////////////////////////////////////////////////////////
00197 float CylindricalLens::
00198 fov_to_focal_length(float fov, float film_size, bool horiz) const {
00199   if (horiz) {
00200     return film_size * cylindrical_k / fov;
00201   } else {
00202     return film_size * 0.5f / ctan(deg_2_rad(fov * 0.5f));
00203   }
00204 }
00205 
00206 ////////////////////////////////////////////////////////////////////
00207 //     Function: CylindricalLens::film_to_fov
00208 //       Access: Protected, Virtual
00209 //  Description: Given a width (or height) on the film and a focal
00210 //               length, compute the field of view in degrees.  If
00211 //               horiz is true, this is in the horizontal direction;
00212 //               otherwise, it is in the vertical direction (some
00213 //               lenses behave differently in each direction).
00214 ////////////////////////////////////////////////////////////////////
00215 float CylindricalLens::
00216 film_to_fov(float film_size, float focal_length, bool horiz) const {
00217   if (horiz) {
00218     return film_size * cylindrical_k / focal_length;
00219   } else {
00220     return rad_2_deg(catan(film_size * 0.5f / focal_length)) * 2.0f;
00221   }
00222 }
 All Classes Functions Variables Enumerations