Panda3D
cylindricalLens.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file cylindricalLens.cxx
10  * @author drose
11  * @date 2001-12-12
12  */
13 
14 #include "cylindricalLens.h"
15 #include "deg_2_rad.h"
16 
17 TypeHandle CylindricalLens::_type_handle;
18 
19 // This is the focal-length constant for fisheye lenses. See fisheyeLens.cxx.
20 static const PN_stdfloat cylindrical_k = 60.0f;
21 // focal_length = film_size * cylindrical_k fov;
22 
23 
24 /**
25  * Allocates a new Lens just like this one.
26  */
27 PT(Lens) CylindricalLens::
28 make_copy() const {
29  return new CylindricalLens(*this);
30 }
31 
32 /**
33  * Given a 2-d point in the range (-1,1) in both dimensions, where (0,0) is
34  * the center of the lens and (-1,-1) is the lower-left corner, compute the
35  * corresponding vector in space that maps to this point, if such a vector can
36  * be determined. The vector is returned by indicating the points on the near
37  * plane and far plane that both map to the indicated 2-d point.
38  *
39  * The z coordinate of the 2-d point is ignored.
40  *
41  * Returns true if the vector is defined, or false otherwise.
42  */
43 bool CylindricalLens::
44 do_extrude(const Lens::CData *lens_cdata,
45  const LPoint3 &point2d, LPoint3 &near_point, LPoint3 &far_point) const {
46  // Undo the shifting from film offsets, etc. This puts the point into the
47  // range [-film_size2, film_size2] in x and y.
48  LPoint3 f = point2d * do_get_film_mat_inv(lens_cdata);
49 
50  PN_stdfloat focal_length = do_get_focal_length(lens_cdata);
51  PN_stdfloat angle = f[0] * cylindrical_k / focal_length;
52  PN_stdfloat sinAngle, cosAngle;
53  csincos(deg_2_rad(angle), &sinAngle, &cosAngle);
54 
55  // Define a unit vector (well, a unit vector in the XY plane, at least) that
56  // represents the vector corresponding to this point.
57  LPoint3 v(sinAngle, cosAngle, f[1] / focal_length);
58 
59  // And we'll need to account for the lens's rotations, etc. at the end of
60  // the day.
61  const LMatrix4 &lens_mat = do_get_lens_mat(lens_cdata);
62  const LMatrix4 &proj_inv_mat = do_get_projection_mat_inv(lens_cdata);
63 
64  near_point = (v * do_get_near(lens_cdata)) * proj_inv_mat * lens_mat;
65  far_point = (v * do_get_far(lens_cdata)) * proj_inv_mat * lens_mat;
66  return true;
67 }
68 
69 /**
70  * Given a 2-d point in the range (-1,1) in both dimensions, where (0,0) is
71  * the center of the lens and (-1,-1) is the lower-left corner, compute the
72  * vector that corresponds to the view direction. This will be parallel to
73  * the normal on the surface (the far plane) corresponding to the lens shape
74  * at this point.
75  *
76  * See the comment block on Lens::extrude_vec_impl() for a more in-depth
77  * comment on the meaning of this vector.
78  *
79  * The z coordinate of the 2-d point is ignored.
80  *
81  * Returns true if the vector is defined, or false otherwise.
82  */
83 bool CylindricalLens::
84 do_extrude_vec(const Lens::CData *lens_cdata, const LPoint3 &point2d, LVector3 &vec) const {
85  // Undo the shifting from film offsets, etc. This puts the point into the
86  // range [-film_size2, film_size2] in x and y.
87  LPoint3 f = point2d * do_get_film_mat_inv(lens_cdata);
88 
89  PN_stdfloat focal_length = do_get_focal_length(lens_cdata);
90  PN_stdfloat angle = f[0] * cylindrical_k / focal_length;
91  PN_stdfloat sinAngle, cosAngle;
92  csincos(deg_2_rad(angle), &sinAngle, &cosAngle);
93 
94  vec = LVector3(sinAngle, cosAngle, 0.0f) * do_get_projection_mat_inv(lens_cdata) * do_get_lens_mat(lens_cdata);
95 
96  return true;
97 }
98 
99 /**
100  * Given a 3-d point in space, determine the 2-d point this maps to, in the
101  * range (-1,1) in both dimensions, where (0,0) is the center of the lens and
102  * (-1,-1) is the lower-left corner.
103  *
104  * Some lens types also set the z coordinate of the 2-d point to a value in
105  * the range (-1, 1), where -1 represents a point on the near plane, and 1
106  * represents a point on the far plane.
107  *
108  * Returns true if the 3-d point is in front of the lens and within the
109  * viewing frustum (in which case point2d is filled in), or false otherwise.
110  */
111 bool CylindricalLens::
112 do_project(const Lens::CData *lens_cdata, const LPoint3 &point3d, LPoint3 &point2d) const {
113  // First, account for any rotations, etc. on the lens.
114  LPoint3 p = point3d * do_get_lens_mat_inv(lens_cdata) * do_get_projection_mat(lens_cdata);
115 
116  // To compute the x position on the frame, we only need to consider the
117  // angle of the vector about the Z axis. Project the vector into the XY
118  // plane to do this.
119  LVector2 xy(p[0], p[1]);
120 
121  // The perspective distance is the length of this vector in the XY plane.
122  PN_stdfloat pdist = xy.length();
123  if (pdist == 0.0f) {
124  point2d.set(0.0f, 0.0f, 0.0f);
125  return false;
126  }
127 
128  PN_stdfloat focal_length = do_get_focal_length(lens_cdata);
129 
130  // Compute the depth as a linear distance in the range 0 .. 1.
131  PN_stdfloat z = (pdist - do_get_near(lens_cdata)) / (do_get_far(lens_cdata) - do_get_near(lens_cdata));
132 
133  point2d.set
134  (
135  // The x position is the angle about the Z axis.
136  rad_2_deg(catan2(xy[0], xy[1])) * focal_length / cylindrical_k,
137  // The y position is the Z height divided by the perspective distance.
138  p[2] * focal_length / pdist,
139  // Z is the distance scaled into the range -1 .. 1.
140  2.0 * z - 1.0
141  );
142 
143  // Now we have to transform the point according to the film adjustments.
144  point2d = point2d * do_get_film_mat(lens_cdata);
145 
146  return
147  point2d[0] >= -1.0f && point2d[0] <= 1.0f &&
148  point2d[1] >= -1.0f && point2d[1] <= 1.0f;
149 }
150 
151 /**
152  * Given a field of view in degrees and a focal length, compute the
153  * correspdonding width (or height) on the film. If horiz is true, this is in
154  * the horizontal direction; otherwise, it is in the vertical direction (some
155  * lenses behave differently in each direction).
156  */
157 PN_stdfloat CylindricalLens::
158 fov_to_film(PN_stdfloat fov, PN_stdfloat focal_length, bool horiz) const {
159  if (horiz) {
160  return focal_length * fov / cylindrical_k;
161  } else {
162  return (ctan(deg_2_rad(fov * 0.5f)) * focal_length) * 2.0f;
163  }
164 }
165 
166 /**
167  * Given a field of view in degrees and a width (or height) on the film,
168  * compute the focal length of the lens. If horiz is true, this is in the
169  * horizontal direction; otherwise, it is in the vertical direction (some
170  * lenses behave differently in each direction).
171  */
172 PN_stdfloat CylindricalLens::
173 fov_to_focal_length(PN_stdfloat fov, PN_stdfloat film_size, bool horiz) const {
174  if (horiz) {
175  return film_size * cylindrical_k / fov;
176  } else {
177  return film_size * 0.5f / ctan(deg_2_rad(fov * 0.5f));
178  }
179 }
180 
181 /**
182  * Given a width (or height) on the film and a focal length, compute the field
183  * of view in degrees. If horiz is true, this is in the horizontal direction;
184  * otherwise, it is in the vertical direction (some lenses behave differently
185  * in each direction).
186  */
187 PN_stdfloat CylindricalLens::
188 film_to_fov(PN_stdfloat film_size, PN_stdfloat focal_length, bool horiz) const {
189  if (horiz) {
190  return film_size * cylindrical_k / focal_length;
191  } else {
192  return rad_2_deg(catan(film_size * 0.5f / focal_length)) * 2.0f;
193  }
194 }
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:41
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A cylindrical lens.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81