Panda3D
pSphereLens.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 pSphereLens.cxx
10  * @author drose
11  * @date 2001-12-12
12  */
13 
14 #include "pSphereLens.h"
15 #include "deg_2_rad.h"
16 
17 TypeHandle PSphereLens::_type_handle;
18 
19 // This is the focal-length constant for fisheye lenses. See fisheyeLens.cxx.
20 static const PN_stdfloat pspherical_k = 60.0f;
21 
22 
23 /**
24  * Allocates a new Lens just like this one.
25  */
26 PT(Lens) PSphereLens::
27 make_copy() const {
28  return new PSphereLens(*this);
29 }
30 
31 /**
32  * Given a 2-d point in the range (-1,1) in both dimensions, where (0,0) is
33  * the center of the lens and (-1,-1) is the lower-left corner, compute the
34  * corresponding vector in space that maps to this point, if such a vector can
35  * be determined. The vector is returned by indicating the points on the near
36  * plane and far plane that both map to the indicated 2-d point.
37  *
38  * The z coordinate of the 2-d point is ignored.
39  *
40  * Returns true if the vector is defined, or false otherwise.
41  */
42 bool PSphereLens::
43 do_extrude(const Lens::CData *lens_cdata,
44  const LPoint3 &point2d, LPoint3 &near_point, LPoint3 &far_point) const {
45  // Undo the shifting from film offsets, etc. This puts the point into the
46  // range [-film_size2, film_size2] in x and y.
47  LPoint3 f = point2d * do_get_film_mat_inv(lens_cdata);
48 
49  PN_stdfloat focal_length = do_get_focal_length(lens_cdata);
50 
51  // Rotate the forward vector through the rotation angles corresponding to
52  // this point.
53  LPoint3 v = LPoint3(0.0f, 1.0f, 0.0f) *
54  LMatrix3::rotate_mat(f[1] * pspherical_k / focal_length, LVector3(1.0f, 0.0f, 0.0f)) *
55  LMatrix3::rotate_mat(f[0] * pspherical_k / focal_length, LVector3(0.0f, 0.0f, -1.0f));
56 
57  // And we'll need to account for the lens's rotations, etc. at the end of
58  // the day.
59  const LMatrix4 &lens_mat = do_get_lens_mat(lens_cdata);
60  const LMatrix4 &proj_inv_mat = do_get_projection_mat_inv(lens_cdata);
61 
62  near_point = (v * do_get_near(lens_cdata)) * proj_inv_mat * lens_mat;
63  far_point = (v * do_get_far(lens_cdata)) * proj_inv_mat * lens_mat;
64  return true;
65 }
66 
67 /**
68  * Given a 3-d point in space, determine the 2-d point this maps to, in the
69  * range (-1,1) in both dimensions, where (0,0) is the center of the lens and
70  * (-1,-1) is the lower-left corner.
71  *
72  * Some lens types also set the z coordinate of the 2-d point to a value in
73  * the range (-1, 1), where -1 represents a point on the near plane, and 1
74  * represents a point on the far plane.
75  *
76  * Returns true if the 3-d point is in front of the lens and within the
77  * viewing frustum (in which case point2d is filled in), or false otherwise.
78  */
79 bool PSphereLens::
80 do_project(const Lens::CData *lens_cdata, const LPoint3 &point3d, LPoint3 &point2d) const {
81  // First, account for any rotations, etc. on the lens.
82  LVector3 v3 = point3d * do_get_lens_mat_inv(lens_cdata) * do_get_projection_mat(lens_cdata);
83  PN_stdfloat dist = v3.length();
84  if (dist == 0.0f) {
85  point2d.set(0.0f, 0.0f, 0.0f);
86  return false;
87  }
88 
89  v3 /= dist;
90 
91  PN_stdfloat focal_length = do_get_focal_length(lens_cdata);
92 
93  // To compute the x position on the frame, we only need to consider the
94  // angle of the vector about the Z axis. Project the vector into the XY
95  // plane to do this.
96  LVector2 xy(v3[0], v3[1]);
97 
98  // Unroll the Z angle, and the y position is the angle about the X axis.
99  xy.normalize();
100  LVector2d yz(v3[0]*xy[0] + v3[1]*xy[1], v3[2]);
101 
102  // Compute the depth as a linear distance in the range 0 .. 1.
103  PN_stdfloat z = (dist - do_get_near(lens_cdata)) / (do_get_far(lens_cdata) - do_get_near(lens_cdata));
104 
105  point2d.set
106  (
107  // The x position is the angle about the Z axis.
108  rad_2_deg(catan2(xy[0], xy[1])) * focal_length / pspherical_k,
109  // The y position is the angle about the X axis.
110  rad_2_deg(catan2(yz[1], yz[0])) * focal_length / pspherical_k,
111  // Z is the distance scaled into the range -1 .. 1.
112  2.0 * z - 1.0
113  );
114 
115  // Now we have to transform the point according to the film adjustments.
116  point2d = point2d * do_get_film_mat(lens_cdata);
117 
118  return
119  point2d[0] >= -1.0f && point2d[0] <= 1.0f &&
120  point2d[1] >= -1.0f && point2d[1] <= 1.0f;
121 }
122 
123 /**
124  * Given a field of view in degrees and a focal length, compute the
125  * correspdonding width (or height) on the film. If horiz is true, this is in
126  * the horizontal direction; otherwise, it is in the vertical direction (some
127  * lenses behave differently in each direction).
128  */
129 PN_stdfloat PSphereLens::
130 fov_to_film(PN_stdfloat fov, PN_stdfloat focal_length, bool) const {
131  return focal_length * fov / pspherical_k;
132 }
133 
134 /**
135  * Given a field of view in degrees and a width (or height) on the film,
136  * compute the focal length of the lens. If horiz is true, this is in the
137  * horizontal direction; otherwise, it is in the vertical direction (some
138  * lenses behave differently in each direction).
139  */
140 PN_stdfloat PSphereLens::
141 fov_to_focal_length(PN_stdfloat fov, PN_stdfloat film_size, bool) const {
142  return film_size * pspherical_k / fov;
143 }
144 
145 /**
146  * Given a width (or height) on the film and a focal length, compute the field
147  * of view in degrees. If horiz is true, this is in the horizontal direction;
148  * otherwise, it is in the vertical direction (some lenses behave differently
149  * in each direction).
150  */
151 PN_stdfloat PSphereLens::
152 film_to_fov(PN_stdfloat film_size, PN_stdfloat focal_length, bool) const {
153  return film_size * pspherical_k / focal_length;
154 }
A PSphereLens is a special nonlinear lens that doesn't correspond to any real physical lenses.
Definition: pSphereLens.h:33
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81