Panda3D
 All Classes Functions Variables Enumerations
pSphereLens.cxx
00001 // Filename: pSphereLens.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 "pSphereLens.h"
00016 #include "deg_2_rad.h"
00017 
00018 TypeHandle PSphereLens::_type_handle;
00019 
00020 // This is the focal-length constant for fisheye lenses.  See
00021 // fisheyeLens.cxx.
00022 static const PN_stdfloat pspherical_k = 60.0f;
00023 
00024 
00025 ////////////////////////////////////////////////////////////////////
00026 //     Function: PSphereLens::make_copy
00027 //       Access: Public, Virtual
00028 //  Description: Allocates a new Lens just like this one.
00029 ////////////////////////////////////////////////////////////////////
00030 PT(Lens) PSphereLens::
00031 make_copy() const {
00032   return new PSphereLens(*this);
00033 }
00034 
00035 ////////////////////////////////////////////////////////////////////
00036 //     Function: PSphereLens::do_extrude
00037 //       Access: Protected, Virtual
00038 //  Description: Given a 2-d point in the range (-1,1) in both
00039 //               dimensions, where (0,0) is the center of the
00040 //               lens and (-1,-1) is the lower-left corner,
00041 //               compute the corresponding vector in space that maps
00042 //               to this point, if such a vector can be determined.
00043 //               The vector is returned by indicating the points on
00044 //               the near plane and far plane that both map to the
00045 //               indicated 2-d point.
00046 //
00047 //               The z coordinate of the 2-d point is ignored.
00048 //
00049 //               Returns true if the vector is defined, or false
00050 //               otherwise.
00051 ////////////////////////////////////////////////////////////////////
00052 bool PSphereLens::
00053 do_extrude(const Lens::CData *lens_cdata, 
00054            const LPoint3 &point2d, LPoint3 &near_point, LPoint3 &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   LPoint3 f = point2d * do_get_film_mat_inv(lens_cdata);
00058 
00059   PN_stdfloat focal_length = do_get_focal_length(lens_cdata);
00060 
00061   // Rotate the forward vector through the rotation angles
00062   // corresponding to this point.
00063   LPoint3 v = LPoint3(0.0f, 1.0f, 0.0f) *
00064     LMatrix3::rotate_mat(f[1] * pspherical_k / focal_length, LVector3(1.0f, 0.0f, 0.0f)) *
00065     LMatrix3::rotate_mat(f[0] * pspherical_k / focal_length, LVector3(0.0f, 0.0f, -1.0f));
00066 
00067   // And we'll need to account for the lens's rotations, etc. at the
00068   // end of the day.
00069   const LMatrix4 &lens_mat = do_get_lens_mat(lens_cdata);
00070   const LMatrix4 &proj_inv_mat = do_get_projection_mat_inv(lens_cdata);
00071 
00072   near_point = (v * do_get_near(lens_cdata)) * proj_inv_mat * lens_mat;
00073   far_point = (v * do_get_far(lens_cdata)) * proj_inv_mat * lens_mat;
00074   return true;
00075 }
00076 
00077 ////////////////////////////////////////////////////////////////////
00078 //     Function: PSphereLens::do_project
00079 //       Access: Protected, Virtual
00080 //  Description: Given a 3-d point in space, determine the 2-d point
00081 //               this maps to, in the range (-1,1) in both dimensions,
00082 //               where (0,0) is the center of the lens and
00083 //               (-1,-1) is the lower-left corner.
00084 //
00085 //               Some lens types also set the z coordinate of the 2-d
00086 //               point to a value in the range (-1, 1), where 1
00087 //               represents a point on the near plane, and -1
00088 //               represents a point on the far plane.
00089 //
00090 //               Returns true if the 3-d point is in front of the lens
00091 //               and within the viewing frustum (in which case point2d
00092 //               is filled in), or false otherwise.
00093 ////////////////////////////////////////////////////////////////////
00094 bool PSphereLens::
00095 do_project(const Lens::CData *lens_cdata, const LPoint3 &point3d, LPoint3 &point2d) const {
00096   // First, account for any rotations, etc. on the lens.
00097   LVector3 v3 = point3d * do_get_lens_mat_inv(lens_cdata) * do_get_projection_mat(lens_cdata);
00098   PN_stdfloat dist = v3.length();
00099   if (dist == 0.0f) {
00100     point2d.set(0.0f, 0.0f, 0.0f);
00101     return false;
00102   }
00103 
00104   v3 /= dist;
00105 
00106   PN_stdfloat focal_length = do_get_focal_length(lens_cdata);
00107 
00108   // To compute the x position on the frame, we only need to consider
00109   // the angle of the vector about the Z axis.  Project the vector
00110   // into the XY plane to do this.
00111   LVector2 xy(v3[0], v3[1]);
00112 
00113   // Unroll the Z angle, and the y position is the angle about the X
00114   // axis.
00115   xy.normalize();
00116   LVector2d yz(v3[0]*xy[0] + v3[1]*xy[1], v3[2]);
00117 
00118   point2d.set
00119     (
00120      // The x position is the angle about the Z axis.
00121      rad_2_deg(catan2(xy[0], xy[1])) * focal_length / pspherical_k,
00122      // The y position is the angle about the X axis.
00123      rad_2_deg(catan2(yz[1], yz[0])) * focal_length / pspherical_k,
00124      // Z is the distance scaled into the range (1, -1).
00125      (do_get_near(lens_cdata) - dist) / (do_get_far(lens_cdata) - do_get_near(lens_cdata))
00126      );
00127 
00128   // Now we have to transform the point according to the film
00129   // adjustments.
00130   point2d = point2d * do_get_film_mat(lens_cdata);
00131 
00132   return
00133     point2d[0] >= -1.0f && point2d[0] <= 1.0f && 
00134     point2d[1] >= -1.0f && point2d[1] <= 1.0f;
00135 }
00136 
00137 ////////////////////////////////////////////////////////////////////
00138 //     Function: PSphereLens::fov_to_film
00139 //       Access: Protected, Virtual
00140 //  Description: Given a field of view in degrees and a focal length,
00141 //               compute the correspdonding width (or height) on the
00142 //               film.  If horiz is true, this is in the horizontal
00143 //               direction; otherwise, it is in the vertical direction
00144 //               (some lenses behave differently in each direction).
00145 ////////////////////////////////////////////////////////////////////
00146 PN_stdfloat PSphereLens::
00147 fov_to_film(PN_stdfloat fov, PN_stdfloat focal_length, bool) const {
00148   return focal_length * fov / pspherical_k;
00149 }
00150 
00151 ////////////////////////////////////////////////////////////////////
00152 //     Function: PSphereLens::fov_to_focal_length
00153 //       Access: Protected, Virtual
00154 //  Description: Given a field of view in degrees and a width (or
00155 //               height) on the film, compute the focal length of the
00156 //               lens.  If horiz is true, this is in the horizontal
00157 //               direction; otherwise, it is in the vertical direction
00158 //               (some lenses behave differently in each direction).
00159 ////////////////////////////////////////////////////////////////////
00160 PN_stdfloat PSphereLens::
00161 fov_to_focal_length(PN_stdfloat fov, PN_stdfloat film_size, bool) const {
00162   return film_size * pspherical_k / fov;
00163 }
00164 
00165 ////////////////////////////////////////////////////////////////////
00166 //     Function: PSphereLens::film_to_fov
00167 //       Access: Protected, Virtual
00168 //  Description: Given a width (or height) on the film and a focal
00169 //               length, compute the field of view in degrees.  If
00170 //               horiz is true, this is in the horizontal direction;
00171 //               otherwise, it is in the vertical direction (some
00172 //               lenses behave differently in each direction).
00173 ////////////////////////////////////////////////////////////////////
00174 PN_stdfloat PSphereLens::
00175 film_to_fov(PN_stdfloat film_size, PN_stdfloat focal_length, bool) const {
00176   return film_size * pspherical_k / focal_length;
00177 }
 All Classes Functions Variables Enumerations