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