Panda3D
|
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 }