Panda3D
 All Classes Functions Variables Enumerations
perspectiveLens.cxx
1 // Filename: perspectiveLens.cxx
2 // Created by: drose (18Feb99)
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 "perspectiveLens.h"
16 #include "bamReader.h"
17 
18 TypeHandle PerspectiveLens::_type_handle;
19 
20 
21 ////////////////////////////////////////////////////////////////////
22 // Function: PerspectiveLens::make_copy
23 // Access: Public, Virtual
24 // Description: Allocates a new Lens just like this one.
25 ////////////////////////////////////////////////////////////////////
27 make_copy() const {
28  return new PerspectiveLens(*this);
29 }
30 
31 ////////////////////////////////////////////////////////////////////
32 // Function: PerspectiveLens::is_linear
33 // Access: Published, Virtual
34 // Description: Returns true if the lens represents a linear
35 // projection (e.g. PerspectiveLens, OrthographicLens),
36 // and therefore there is a valid matrix returned by
37 // get_projection_mat(), or false otherwise.
38 ////////////////////////////////////////////////////////////////////
40 is_linear() const {
41  return true;
42 }
43 
44 ////////////////////////////////////////////////////////////////////
45 // Function: PerspectiveLens::is_perspective
46 // Access: Published, Virtual
47 // Description: Returns true if the lens represents a perspective
48 // projection (i.e. it is a PerspectiveLens), false
49 // otherwise.
50 ////////////////////////////////////////////////////////////////////
52 is_perspective() const {
53  return true;
54 }
55 
56 ////////////////////////////////////////////////////////////////////
57 // Function: PerspectiveLens::do_extrude_depth
58 // Access: Protected, Virtual
59 // Description: This is the generic implementation, which is based on
60 // do_extrude() and assumes a linear distribution of
61 // depth values between the near and far points.
62 ////////////////////////////////////////////////////////////////////
63 bool PerspectiveLens::
64 do_extrude_depth(const CData *cdata,
65  const LPoint3 &point2d, LPoint3 &point3d) const {
66  return do_extrude_depth_with_mat(cdata, point2d, point3d);
67 }
68 
69 ////////////////////////////////////////////////////////////////////
70 // Function: PerspectiveLens::do_compute_projection_mat
71 // Access: Protected, Virtual
72 // Description: Computes the complete transformation matrix from 3-d
73 // point to 2-d point, if the lens is linear.
74 ////////////////////////////////////////////////////////////////////
75 void PerspectiveLens::
76 do_compute_projection_mat(Lens::CData *lens_cdata) {
77  CoordinateSystem cs = lens_cdata->_cs;
78  if (cs == CS_default) {
79  cs = get_default_coordinate_system();
80  }
81 
82  PN_stdfloat fl = do_get_focal_length(lens_cdata);
83  PN_stdfloat fFar = do_get_far(lens_cdata);
84  PN_stdfloat fNear = do_get_near(lens_cdata);
85  PN_stdfloat a, b;
86 
87  if (cinf(fFar)) {
88  a = 1;
89  b = -2 * fNear;
90  } else {
91  PN_stdfloat far_minus_near = fFar-fNear;
92  a = (fFar + fNear);
93  b = -2 * fFar * fNear;
94  a /= far_minus_near;
95  b /= far_minus_near;
96  }
97 
98  LMatrix4 canonical;
99  switch (cs) {
100  case CS_zup_right:
101  canonical.set( fl, 0.0f, 0.0f, 0.0f,
102  0.0f, 0.0f, a, 1.0f,
103  0.0f, fl, 0.0f, 0.0f,
104  0.0f, 0.0f, b, 0.0f);
105  break;
106 
107  case CS_yup_right:
108  canonical.set( fl, 0.0f, 0.0f, 0.0f,
109  0.0f, fl, 0.0f, 0.0f,
110  0.0f, 0.0f, -a, -1.0f,
111  0.0f, 0.0f, b, 0.0f);
112  break;
113 
114  case CS_zup_left:
115  canonical.set( fl, 0.0f, 0.0f, 0.0f,
116  0.0f, 0.0f, -a, -1.0f,
117  0.0f, fl, 0.0f, 0.0f,
118  0.0f, 0.0f, b, 0.0f);
119  break;
120 
121  case CS_yup_left:
122  canonical.set( fl, 0.0f, 0.0f, 0.0f,
123  0.0f, fl, 0.0f, 0.0f,
124  0.0f, 0.0f, a, 1.0f,
125  0.0f, 0.0f, b, 0.0f);
126  break;
127 
128  default:
129  gobj_cat.error()
130  << "Invalid coordinate system " << (int)cs << " in PerspectiveLens!\n";
131  canonical = LMatrix4::ident_mat();
132  }
133 
134  lens_cdata->_projection_mat = do_get_lens_mat_inv(lens_cdata) * canonical * do_get_film_mat(lens_cdata);
135 
136  if ((lens_cdata->_user_flags & UF_interocular_distance) == 0) {
137  lens_cdata->_projection_mat_left = lens_cdata->_projection_mat_right = lens_cdata->_projection_mat;
138 
139  } else {
140  // Compute the left and right projection matrices in case this
141  // lens is assigned to a stereo DisplayRegion.
142 
143  LVector3 iod = lens_cdata->_interocular_distance * 0.5f * LVector3::left(lens_cdata->_cs);
144  lens_cdata->_projection_mat_left = do_get_lens_mat_inv(lens_cdata) * LMatrix4::translate_mat(-iod) * canonical * do_get_film_mat(lens_cdata);
145  lens_cdata->_projection_mat_right = do_get_lens_mat_inv(lens_cdata) * LMatrix4::translate_mat(iod) * canonical * do_get_film_mat(lens_cdata);
146 
147  if ((lens_cdata->_user_flags & UF_convergence_distance) != 0 &&
148  !cinf(lens_cdata->_convergence_distance)) {
149  nassertv(lens_cdata->_convergence_distance != 0.0f);
150  LVector3 cd;
151  if (stereo_lens_old_convergence) { // The old, incorrect calculation was requested.
152  cd = (0.25f / lens_cdata->_convergence_distance) * LVector3::left(lens_cdata->_cs);
153  } else {
154  const LVecBase2 &fov = do_get_fov(lens_cdata);
155  cd = (2.0f / fov_to_film(fov[0], lens_cdata->_convergence_distance, true)) * iod;
156  }
157  lens_cdata->_projection_mat_left *= LMatrix4::translate_mat(cd);
158  lens_cdata->_projection_mat_right *= LMatrix4::translate_mat(-cd);
159  }
160  }
161 
162  do_adjust_comp_flags(lens_cdata,
163  CF_projection_mat_inv | CF_projection_mat_left_inv | CF_projection_mat_right_inv,
164  CF_projection_mat);
165 }
166 
167 ////////////////////////////////////////////////////////////////////
168 // Function: PerspectiveLens::fov_to_film
169 // Access: Protected, Virtual
170 // Description: Given a field of view in degrees and a focal length,
171 // compute the correspdonding width (or height) on the
172 // film. If horiz is true, this is in the horizontal
173 // direction; otherwise, it is in the vertical direction
174 // (some lenses behave differently in each direction).
175 ////////////////////////////////////////////////////////////////////
176 PN_stdfloat PerspectiveLens::
177 fov_to_film(PN_stdfloat fov, PN_stdfloat focal_length, bool) const {
178  return (ctan(deg_2_rad(fov * 0.5f)) * focal_length) * 2.0f;
179 }
180 
181 ////////////////////////////////////////////////////////////////////
182 // Function: PerspectiveLens::fov_to_focal_length
183 // Access: Protected, Virtual
184 // Description: Given a field of view in degrees and a width (or
185 // height) on the film, compute the focal length of the
186 // lens. If horiz is true, this is in the horizontal
187 // direction; otherwise, it is in the vertical direction
188 // (some lenses behave differently in each direction).
189 ////////////////////////////////////////////////////////////////////
190 PN_stdfloat PerspectiveLens::
191 fov_to_focal_length(PN_stdfloat fov, PN_stdfloat film_size, bool) const {
192  return film_size * 0.5f / ctan(deg_2_rad(fov * 0.5f));
193 }
194 
195 ////////////////////////////////////////////////////////////////////
196 // Function: PerspectiveLens::film_to_fov
197 // Access: Protected, Virtual
198 // Description: Given a width (or height) on the film and a focal
199 // length, compute the field of view in degrees. If
200 // horiz is true, this is in the horizontal direction;
201 // otherwise, it is in the vertical direction (some
202 // lenses behave differently in each direction).
203 ////////////////////////////////////////////////////////////////////
204 PN_stdfloat PerspectiveLens::
205 film_to_fov(PN_stdfloat film_size, PN_stdfloat focal_length, bool) const {
206  return rad_2_deg(catan(film_size * 0.5f / focal_length)) * 2.0f;
207 }
208 
209 ////////////////////////////////////////////////////////////////////
210 // Function: PerspectiveLens::register_with_read_factory
211 // Access: Public, Static
212 // Description: Tells the BamReader how to create objects of type
213 // Lens.
214 ////////////////////////////////////////////////////////////////////
217  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
218 }
219 
220 ////////////////////////////////////////////////////////////////////
221 // Function: PerspectiveLens::make_from_bam
222 // Access: Protected, Static
223 // Description: This function is called by the BamReader's factory
224 // when a new object of type Lens is encountered
225 // in the Bam file. It should create the Lens
226 // and extract its information from the file.
227 ////////////////////////////////////////////////////////////////////
228 TypedWritable *PerspectiveLens::
229 make_from_bam(const FactoryParams &params) {
230  PerspectiveLens *lens = new PerspectiveLens;
231  DatagramIterator scan;
232  BamReader *manager;
233 
234  parse_params(params, scan, manager);
235  lens->fillin(scan, manager);
236 
237  return lens;
238 }
static const LMatrix4f & ident_mat()
Returns an identity matrix.
Definition: lmatrix.h:903
virtual bool is_linear() const
Returns true if the lens represents a linear projection (e.g.
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:45
static LMatrix4f translate_mat(const LVecBase3f &trans)
Returns a matrix that applies the indicated translation.
Definition: lmatrix.h:2397
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:37
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
virtual bool is_perspective() const
Returns true if the lens represents a perspective projection (i.e.
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:451
A perspective-type lens: a normal camera.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:40
static LVector3f left(CoordinateSystem cs=CS_default)
Returns the left vector for the given coordinate system.
Definition: lvector3.h:607
This is the base class for all two-component vectors and points.
Definition: lvecBase2.h:105
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:90
static void register_with_read_factory()
Tells the BamReader how to create objects of type Lens.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:213
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85