00001 // Filename: cylindricalLens.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 "cylindricalLens.h" 00020 #include "deg_2_rad.h" 00021 00022 TypeHandle CylindricalLens::_type_handle; 00023 00024 // This is the focal-length constant for fisheye lenses. See 00025 // fisheyeLens.cxx. 00026 static const float cylindrical_k = 60.0f; 00027 // focal_length = film_size * cylindrical_k / fov; 00028 00029 00030 //////////////////////////////////////////////////////////////////// 00031 // Function: CylindricalLens::make_copy 00032 // Access: Public, Virtual 00033 // Description: Allocates a new Lens just like this one. 00034 //////////////////////////////////////////////////////////////////// 00035 PT(Lens) CylindricalLens:: 00036 make_copy() const { 00037 return new CylindricalLens(*this); 00038 } 00039 00040 //////////////////////////////////////////////////////////////////// 00041 // Function: CylindricalLens::extrude_impl 00042 // Access: Protected, Virtual 00043 // Description: Given a 2-d point in the range (-1,1) in both 00044 // dimensions, where (0,0) is the center of the 00045 // lens and (-1,-1) is the lower-left corner, 00046 // compute the corresponding vector in space that maps 00047 // to this point, if such a vector can be determined. 00048 // The vector is returned by indicating the points on 00049 // the near plane and far plane that both map to the 00050 // indicated 2-d point. 00051 // 00052 // The z coordinate of the 2-d point is ignored. 00053 // 00054 // Returns true if the vector is defined, or false 00055 // otherwise. 00056 //////////////////////////////////////////////////////////////////// 00057 bool CylindricalLens:: 00058 extrude_impl(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) const { 00059 // Undo the shifting from film offsets, etc. This puts the point 00060 // into the range [-film_size/2, film_size/2] in x and y. 00061 LPoint3f f = point2d * get_film_mat_inv(); 00062 00063 float focal_length = get_focal_length(); 00064 float angle = f[0] * cylindrical_k / focal_length; 00065 float sinAngle, cosAngle; 00066 csincos(deg_2_rad(angle), &sinAngle, &cosAngle); 00067 00068 // Define a unit vector (well, a unit vector in the XY plane, at 00069 // least) that reprents the vector corresponding to this point. 00070 LPoint3f v(sinAngle, cosAngle, f[1] / focal_length); 00071 00072 // And we'll need to account for the lens's rotations, etc. at the 00073 // end of the day. 00074 const LMatrix4f &lens_mat = get_lens_mat(); 00075 00076 near_point = (v * get_near()) * lens_mat; 00077 far_point = (v * get_far()) * lens_mat; 00078 return true; 00079 } 00080 00081 //////////////////////////////////////////////////////////////////// 00082 // Function: CylindricalLens::project_impl 00083 // Access: Protected, Virtual 00084 // Description: Given a 3-d point in space, determine the 2-d point 00085 // this maps to, in the range (-1,1) in both dimensions, 00086 // where (0,0) is the center of the lens and 00087 // (-1,-1) is the lower-left corner. 00088 // 00089 // Some lens types also set the z coordinate of the 2-d 00090 // point to a value in the range (-1, 1), where 1 00091 // represents a point on the near plane, and -1 00092 // represents a point on the far plane. 00093 // 00094 // Returns true if the 3-d point is in front of the lens 00095 // and within the viewing frustum (in which case point2d 00096 // is filled in), or false otherwise. 00097 //////////////////////////////////////////////////////////////////// 00098 bool CylindricalLens:: 00099 project_impl(const LPoint3f &point3d, LPoint3f &point2d) const { 00100 // First, account for any rotations, etc. on the lens. 00101 LPoint3f p = point3d * get_lens_mat_inv(); 00102 00103 // To compute the x position on the frame, we only need to consider 00104 // the angle of the vector about the Z axis. Project the vector 00105 // into the XY plane to do this. 00106 LVector2f xy(p[0], p[1]); 00107 00108 // The perspective distance is the length of this vector in the XY 00109 // plane. 00110 float pdist = xy.length(); 00111 if (pdist == 0.0f) { 00112 point2d.set(0.0f, 0.0f, 0.0f); 00113 return false; 00114 } 00115 00116 float focal_length = get_focal_length(); 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 / cylindrical_k, 00122 // The y position is the Z height divided by the perspective 00123 // distance. 00124 p[2] * focal_length / pdist, 00125 // Z is the perspective distance scaled into the range (1, -1). 00126 (get_near() - pdist) / (get_far() - get_near()) 00127 ); 00128 00129 // Now we have to transform the point according to the film 00130 // adjustments. 00131 point2d = point2d * get_film_mat(); 00132 00133 return 00134 point2d[0] >= -1.0f && point2d[0] <= 1.0f && 00135 point2d[1] >= -1.0f && point2d[1] <= 1.0f; 00136 } 00137 00138 //////////////////////////////////////////////////////////////////// 00139 // Function: CylindricalLens::fov_to_film 00140 // Access: Protected, Virtual 00141 // Description: Given a field of view in degrees and a focal length, 00142 // compute the correspdonding width (or height) on the 00143 // film. If horiz is true, this is in the horizontal 00144 // direction; otherwise, it is in the vertical direction 00145 // (some lenses behave differently in each direction). 00146 //////////////////////////////////////////////////////////////////// 00147 float CylindricalLens:: 00148 fov_to_film(float fov, float focal_length, bool horiz) const { 00149 if (horiz) { 00150 return focal_length * fov / cylindrical_k; 00151 } else { 00152 return (ctan(deg_2_rad(fov * 0.5f)) * focal_length) * 2.0f; 00153 } 00154 } 00155 00156 //////////////////////////////////////////////////////////////////// 00157 // Function: CylindricalLens::fov_to_focal_length 00158 // Access: Protected, Virtual 00159 // Description: Given a field of view in degrees and a width (or 00160 // height) on the film, compute the focal length of the 00161 // lens. If horiz is true, this is in the horizontal 00162 // direction; otherwise, it is in the vertical direction 00163 // (some lenses behave differently in each direction). 00164 //////////////////////////////////////////////////////////////////// 00165 float CylindricalLens:: 00166 fov_to_focal_length(float fov, float film_size, bool horiz) const { 00167 if (horiz) { 00168 return film_size * cylindrical_k / fov; 00169 } else { 00170 return film_size * 0.5f / ctan(deg_2_rad(fov * 0.5f)); 00171 } 00172 } 00173 00174 //////////////////////////////////////////////////////////////////// 00175 // Function: CylindricalLens::film_to_fov 00176 // Access: Protected, Virtual 00177 // Description: Given a width (or height) on the film and a focal 00178 // length, compute the field of view in degrees. If 00179 // horiz is true, this is in the horizontal direction; 00180 // otherwise, it is in the vertical direction (some 00181 // lenses behave differently in each direction). 00182 //////////////////////////////////////////////////////////////////// 00183 float CylindricalLens:: 00184 film_to_fov(float film_size, float focal_length, bool horiz) const { 00185 if (horiz) { 00186 return film_size * cylindrical_k / focal_length; 00187 } else { 00188 return rad_2_deg(catan(film_size * 0.5f / focal_length)) * 2.0f; 00189 } 00190 }