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 }