Panda3D
 All Classes Functions Variables Enumerations
perspectiveLens.cxx
00001 // Filename: perspectiveLens.cxx
00002 // Created by:  drose (18Feb99)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "perspectiveLens.h"
00016 #include "bamReader.h"
00017 
00018 TypeHandle PerspectiveLens::_type_handle;
00019 
00020 
00021 ////////////////////////////////////////////////////////////////////
00022 //     Function: PerspectiveLens::make_copy
00023 //       Access: Public, Virtual
00024 //  Description: Allocates a new Lens just like this one.
00025 ////////////////////////////////////////////////////////////////////
00026 PT(Lens) PerspectiveLens::
00027 make_copy() const {
00028   return new PerspectiveLens(*this);
00029 }
00030 
00031 ////////////////////////////////////////////////////////////////////
00032 //     Function: PerspectiveLens::is_linear
00033 //       Access: Published, Virtual
00034 //  Description: Returns true if the lens represents a linear
00035 //               projection (e.g. PerspectiveLens, OrthographicLens),
00036 //               and therefore there is a valid matrix returned by
00037 //               get_projection_mat(), or false otherwise.
00038 ////////////////////////////////////////////////////////////////////
00039 bool PerspectiveLens::
00040 is_linear() const {
00041   return true;
00042 }
00043 
00044 ////////////////////////////////////////////////////////////////////
00045 //     Function: PerspectiveLens::is_perspective
00046 //       Access: Published, Virtual
00047 //  Description: Returns true if the lens represents a perspective
00048 //               projection (i.e. it is a PerspectiveLens), false
00049 //               otherwise.
00050 ////////////////////////////////////////////////////////////////////
00051 bool PerspectiveLens::
00052 is_perspective() const {
00053   return true;
00054 }
00055 
00056 ////////////////////////////////////////////////////////////////////
00057 //     Function: PerspectiveLens::do_compute_projection_mat
00058 //       Access: Protected, Virtual
00059 //  Description: Computes the complete transformation matrix from 3-d
00060 //               point to 2-d point, if the lens is linear.
00061 ////////////////////////////////////////////////////////////////////
00062 void PerspectiveLens::
00063 do_compute_projection_mat(Lens::CData *lens_cdata) {
00064   CoordinateSystem cs = lens_cdata->_cs;
00065   if (cs == CS_default) {
00066     cs = get_default_coordinate_system();
00067   }
00068 
00069   PN_stdfloat fl = do_get_focal_length(lens_cdata);
00070   PN_stdfloat fFar = do_get_far(lens_cdata);
00071   PN_stdfloat fNear = do_get_near(lens_cdata);
00072   PN_stdfloat far_minus_near = fFar-fNear;
00073   PN_stdfloat a = (fFar + fNear);
00074   PN_stdfloat b = -2.0f * fFar * fNear;
00075 
00076   a /= far_minus_near;
00077   b /= far_minus_near;
00078 
00079   LMatrix4 canonical;
00080   switch (cs) {
00081   case CS_zup_right:
00082     canonical.set(  fl,  0.0f,  0.0f,  0.0f,
00083                   0.0f,  0.0f,     a,  1.0f,
00084                   0.0f,    fl,  0.0f,  0.0f,
00085                   0.0f,  0.0f,     b,  0.0f);
00086     break;
00087 
00088   case CS_yup_right:
00089     canonical.set(  fl,  0.0f,  0.0f,  0.0f,
00090                   0.0f,    fl,  0.0f,  0.0f,
00091                   0.0f,  0.0f,    -a, -1.0f,
00092                   0.0f,  0.0f,     b,  0.0f);
00093     break;
00094 
00095   case CS_zup_left:
00096     canonical.set(  fl,  0.0f,  0.0f,  0.0f,
00097                   0.0f,  0.0f,    -a, -1.0f,
00098                   0.0f,    fl,  0.0f,  0.0f,
00099                   0.0f,  0.0f,     b,  0.0f);
00100     break;
00101 
00102   case CS_yup_left:
00103     canonical.set(  fl,  0.0f,  0.0f,  0.0f,
00104                   0.0f,    fl,  0.0f,  0.0f,
00105                   0.0f,  0.0f,     a,  1.0f,
00106                   0.0f,  0.0f,     b,  0.0f);
00107     break;
00108 
00109   default:
00110     gobj_cat.error()
00111       << "Invalid coordinate system " << (int)cs << " in PerspectiveLens!\n";
00112     canonical = LMatrix4::ident_mat();
00113   }
00114 
00115   lens_cdata->_projection_mat = do_get_lens_mat_inv(lens_cdata) * canonical * do_get_film_mat(lens_cdata);
00116 
00117   if ((lens_cdata->_user_flags & UF_interocular_distance) == 0) {
00118     lens_cdata->_projection_mat_left = lens_cdata->_projection_mat_right = lens_cdata->_projection_mat;
00119 
00120   } else {
00121     // Compute the left and right projection matrices in case this
00122     // lens is assigned to a stereo DisplayRegion.
00123 
00124     LVector3 iod = lens_cdata->_interocular_distance * 0.5f * LVector3::left(lens_cdata->_cs);
00125     lens_cdata->_projection_mat_left = do_get_lens_mat_inv(lens_cdata) * LMatrix4::translate_mat(-iod) * canonical * do_get_film_mat(lens_cdata);
00126     lens_cdata->_projection_mat_right = do_get_lens_mat_inv(lens_cdata) * LMatrix4::translate_mat(iod) * canonical * do_get_film_mat(lens_cdata);
00127     
00128     if (lens_cdata->_user_flags & UF_convergence_distance) {
00129       nassertv(lens_cdata->_convergence_distance != 0.0f);
00130       LVector3 cd = (0.25f / lens_cdata->_convergence_distance) * LVector3::left(lens_cdata->_cs);
00131       lens_cdata->_projection_mat_left *= LMatrix4::translate_mat(cd);
00132       lens_cdata->_projection_mat_right *= LMatrix4::translate_mat(-cd);
00133     }
00134   }
00135 
00136   do_adjust_comp_flags(lens_cdata,
00137                        CF_projection_mat_inv | CF_projection_mat_left_inv | CF_projection_mat_right_inv,
00138                        CF_projection_mat);
00139 }
00140 
00141 ////////////////////////////////////////////////////////////////////
00142 //     Function: PerspectiveLens::fov_to_film
00143 //       Access: Protected, Virtual
00144 //  Description: Given a field of view in degrees and a focal length,
00145 //               compute the correspdonding width (or height) on the
00146 //               film.  If horiz is true, this is in the horizontal
00147 //               direction; otherwise, it is in the vertical direction
00148 //               (some lenses behave differently in each direction).
00149 ////////////////////////////////////////////////////////////////////
00150 PN_stdfloat PerspectiveLens::
00151 fov_to_film(PN_stdfloat fov, PN_stdfloat focal_length, bool) const {
00152   return (ctan(deg_2_rad(fov * 0.5f)) * focal_length) * 2.0f;
00153 }
00154 
00155 ////////////////////////////////////////////////////////////////////
00156 //     Function: PerspectiveLens::fov_to_focal_length
00157 //       Access: Protected, Virtual
00158 //  Description: Given a field of view in degrees and a width (or
00159 //               height) on the film, compute the focal length of the
00160 //               lens.  If horiz is true, this is in the horizontal
00161 //               direction; otherwise, it is in the vertical direction
00162 //               (some lenses behave differently in each direction).
00163 ////////////////////////////////////////////////////////////////////
00164 PN_stdfloat PerspectiveLens::
00165 fov_to_focal_length(PN_stdfloat fov, PN_stdfloat film_size, bool) const {
00166   return film_size * 0.5f / ctan(deg_2_rad(fov * 0.5f));
00167 }
00168 
00169 ////////////////////////////////////////////////////////////////////
00170 //     Function: PerspectiveLens::film_to_fov
00171 //       Access: Protected, Virtual
00172 //  Description: Given a width (or height) on the film and a focal
00173 //               length, compute the field of view in degrees.  If
00174 //               horiz is true, this is in the horizontal direction;
00175 //               otherwise, it is in the vertical direction (some
00176 //               lenses behave differently in each direction).
00177 ////////////////////////////////////////////////////////////////////
00178 PN_stdfloat PerspectiveLens::
00179 film_to_fov(PN_stdfloat film_size, PN_stdfloat focal_length, bool) const {
00180   return rad_2_deg(catan(film_size * 0.5f / focal_length)) * 2.0f;
00181 }
00182 
00183 ////////////////////////////////////////////////////////////////////
00184 //     Function: PerspectiveLens::register_with_read_factory
00185 //       Access: Public, Static
00186 //  Description: Tells the BamReader how to create objects of type
00187 //               Lens.
00188 ////////////////////////////////////////////////////////////////////
00189 void PerspectiveLens::
00190 register_with_read_factory() {
00191   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00192 }
00193 
00194 ////////////////////////////////////////////////////////////////////
00195 //     Function: PerspectiveLens::make_from_bam
00196 //       Access: Protected, Static
00197 //  Description: This function is called by the BamReader's factory
00198 //               when a new object of type Lens is encountered
00199 //               in the Bam file.  It should create the Lens
00200 //               and extract its information from the file.
00201 ////////////////////////////////////////////////////////////////////
00202 TypedWritable *PerspectiveLens::
00203 make_from_bam(const FactoryParams &params) {
00204   PerspectiveLens *lens = new PerspectiveLens;
00205   DatagramIterator scan;
00206   BamReader *manager;
00207 
00208   parse_params(params, scan, manager);
00209   lens->fillin(scan, manager);
00210 
00211   return lens;
00212 }
 All Classes Functions Variables Enumerations