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