Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/pgraph/billboardEffect.cxx

Go to the documentation of this file.
00001 // Filename: billboardEffect.cxx
00002 // Created by:  drose (14Mar02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "billboardEffect.h"
00020 #include "nodePath.h"
00021 #include "look_at.h"
00022 #include "bamReader.h"
00023 #include "bamWriter.h"
00024 #include "datagram.h"
00025 #include "datagramIterator.h"
00026 
00027 TypeHandle BillboardEffect::_type_handle;
00028 
00029 ////////////////////////////////////////////////////////////////////
00030 //     Function: BillboardEffect::make
00031 //       Access: Published, Static
00032 //  Description: Constructs a new BillboardEffect object with the
00033 //               indicated properties.
00034 ////////////////////////////////////////////////////////////////////
00035 CPT(RenderEffect) BillboardEffect::
00036 make(const LVector3f &up_vector, bool eye_relative,
00037      bool axial_rotate, float offset, const NodePath &look_at,
00038      const LPoint3f &look_at_point) {
00039   BillboardEffect *effect = new BillboardEffect;
00040   effect->_up_vector = up_vector;
00041   effect->_eye_relative = eye_relative;
00042   effect->_axial_rotate = axial_rotate;
00043   effect->_offset = offset;
00044   effect->_look_at = look_at;
00045   effect->_look_at_point = look_at_point;
00046   effect->_off = false;
00047   return return_new(effect);
00048 }
00049 
00050 ////////////////////////////////////////////////////////////////////
00051 //     Function: BillboardEffect::safe_to_transform
00052 //       Access: Public, Virtual
00053 //  Description: Returns true if it is generally safe to transform
00054 //               this particular kind of RenderEffect by calling the
00055 //               xform() method, false otherwise.
00056 ////////////////////////////////////////////////////////////////////
00057 bool BillboardEffect::
00058 safe_to_transform() const {
00059   return false;
00060 }
00061 
00062 ////////////////////////////////////////////////////////////////////
00063 //     Function: BillboardEffect::output
00064 //       Access: Public, Virtual
00065 //  Description: 
00066 ////////////////////////////////////////////////////////////////////
00067 void BillboardEffect::
00068 output(ostream &out) const {
00069   out << get_type() << ":";
00070   if (is_off()) {
00071     out << "(off)";
00072   } else {
00073     if (_axial_rotate) {
00074       out << "(axis";
00075     } else {
00076       out << "(point";
00077     }
00078     if (!_up_vector.almost_equal(LVector3f::up())) {
00079       out << " up " << _up_vector;
00080     }
00081     if (_eye_relative) {
00082       out << " eye";
00083     }
00084     if (_offset != 0.0f) {
00085       out << " offset " << _offset;
00086     }
00087     if (!_look_at.is_empty()) {
00088       out << " look at " << _look_at;
00089     }
00090     if (!_look_at_point.almost_equal(LPoint3f(0.0f, 0.0f, 0.0f))) {
00091       out << " look at point " << _look_at_point;
00092     }
00093     out << ")";
00094   }
00095 }
00096 
00097 ////////////////////////////////////////////////////////////////////
00098 //     Function: BillboardEffect::do_billboard
00099 //       Access: Public
00100 //  Description: Computes the appropriate transform to apply to the
00101 //               billboarded geometry, given its current net
00102 //               transform, and the camera's inverse net transform.
00103 ////////////////////////////////////////////////////////////////////
00104 CPT(TransformState) BillboardEffect::
00105 do_billboard(const TransformState *net_transform,
00106              const TransformState *camera_transform) const {
00107   // Determine the relative transform to our camera (or other look_at
00108   // coordinate space).
00109   if (!_look_at.is_empty()) {
00110     camera_transform = _look_at.get_net_transform();
00111   }
00112 
00113   CPT(TransformState) rel_transform =
00114     net_transform->invert_compose(camera_transform);
00115   const LMatrix4f &rel_mat = rel_transform->get_mat();
00116 
00117   // Determine the look_at point in the camera space.
00118   LVector3f camera_pos, up;
00119 
00120   // If this is an eye-relative Billboard, then (a) the up vector is
00121   // relative to the camera, not to the world, and (b) the look
00122   // direction is towards the plane that contains the camera,
00123   // perpendicular to the forward direction, not directly to the
00124   // camera.
00125 
00126   if (_eye_relative) {
00127     up = _up_vector * rel_mat;
00128     camera_pos = LVector3f::forward() * rel_mat;
00129 
00130   } else {
00131     up = _up_vector;
00132     camera_pos = -(_look_at_point * rel_mat);
00133   }
00134 
00135   // Now determine the rotation matrix for the Billboard.
00136   LMatrix4f rotate;
00137   if (_axial_rotate) {
00138     heads_up(rotate, camera_pos, up);
00139   } else {
00140     look_at(rotate, camera_pos, up);
00141   }
00142 
00143   // Also slide the billboard geometry towards the camera according to
00144   // the offset factor.
00145   if (_offset != 0.0f) {
00146     LVector3f translate(rel_mat(3, 0), rel_mat(3, 1), rel_mat(3, 2));
00147     translate.normalize();
00148     translate *= _offset;
00149     rotate.set_row(3, translate);
00150   }
00151 
00152   return TransformState::make_mat(rotate);
00153 }
00154 
00155 ////////////////////////////////////////////////////////////////////
00156 //     Function: BillboardEffect::compare_to_impl
00157 //       Access: Protected, Virtual
00158 //  Description: Intended to be overridden by derived BillboardEffect
00159 //               types to return a unique number indicating whether
00160 //               this BillboardEffect is equivalent to the other one.
00161 //
00162 //               This should return 0 if the two BillboardEffect objects
00163 //               are equivalent, a number less than zero if this one
00164 //               should be sorted before the other one, and a number
00165 //               greater than zero otherwise.
00166 //
00167 //               This will only be called with two BillboardEffect
00168 //               objects whose get_type() functions return the same.
00169 ////////////////////////////////////////////////////////////////////
00170 int BillboardEffect::
00171 compare_to_impl(const RenderEffect *other) const {
00172   const BillboardEffect *ta;
00173   DCAST_INTO_R(ta, other, 0);
00174 
00175   if (_axial_rotate != ta->_axial_rotate) {
00176     return _axial_rotate - ta->_axial_rotate;
00177   }
00178   if (_eye_relative != ta->_eye_relative) {
00179     return _eye_relative - ta->_eye_relative;
00180   }
00181   if (_offset != ta->_offset) {
00182     return _offset < ta->_offset ? -1 : 1;
00183   }
00184   int compare = _up_vector.compare_to(ta->_up_vector);
00185   if (compare != 0) {
00186     return compare;
00187   }
00188   compare = _look_at.compare_to(ta->_look_at);
00189   if (compare != 0) {
00190     return compare;
00191   }
00192   compare = _look_at_point.compare_to(ta->_look_at_point);
00193   if (compare != 0) {
00194     return compare;
00195   }
00196   return 0;
00197 }
00198 
00199 ////////////////////////////////////////////////////////////////////
00200 //     Function: BillboardEffect::register_with_read_factory
00201 //       Access: Public, Static
00202 //  Description: Tells the BamReader how to create objects of type
00203 //               BillboardEffect.
00204 ////////////////////////////////////////////////////////////////////
00205 void BillboardEffect::
00206 register_with_read_factory() {
00207   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00208 }
00209 
00210 ////////////////////////////////////////////////////////////////////
00211 //     Function: BillboardEffect::write_datagram
00212 //       Access: Public, Virtual
00213 //  Description: Writes the contents of this object to the datagram
00214 //               for shipping out to a Bam file.
00215 ////////////////////////////////////////////////////////////////////
00216 void BillboardEffect::
00217 write_datagram(BamWriter *manager, Datagram &dg) {
00218   RenderEffect::write_datagram(manager, dg);
00219 
00220   dg.add_bool(_off);
00221   _up_vector.write_datagram(dg);
00222   dg.add_bool(_eye_relative);
00223   dg.add_bool(_axial_rotate);
00224   dg.add_float32(_offset);
00225   _look_at_point.write_datagram(dg);
00226 
00227   // *** We don't write out the _look_at NodePath right now.  Maybe
00228   // we should.
00229 }
00230 
00231 ////////////////////////////////////////////////////////////////////
00232 //     Function: BillboardEffect::make_from_bam
00233 //       Access: Protected, Static
00234 //  Description: This function is called by the BamReader's factory
00235 //               when a new object of type BillboardEffect is encountered
00236 //               in the Bam file.  It should create the BillboardEffect
00237 //               and extract its information from the file.
00238 ////////////////////////////////////////////////////////////////////
00239 TypedWritable *BillboardEffect::
00240 make_from_bam(const FactoryParams &params) {
00241   BillboardEffect *effect = new BillboardEffect;
00242   DatagramIterator scan;
00243   BamReader *manager;
00244 
00245   parse_params(params, scan, manager);
00246   effect->fillin(scan, manager);
00247 
00248   return effect;
00249 }
00250 
00251 ////////////////////////////////////////////////////////////////////
00252 //     Function: BillboardEffect::fillin
00253 //       Access: Protected
00254 //  Description: This internal function is called by make_from_bam to
00255 //               read in all of the relevant data from the BamFile for
00256 //               the new BillboardEffect.
00257 ////////////////////////////////////////////////////////////////////
00258 void BillboardEffect::
00259 fillin(DatagramIterator &scan, BamReader *manager) {
00260   RenderEffect::fillin(scan, manager);
00261 
00262   _off = scan.get_bool();
00263   _up_vector.read_datagram(scan);
00264   _eye_relative = scan.get_bool();
00265   _axial_rotate = scan.get_bool();
00266   _offset = scan.get_float32();
00267   _look_at_point.read_datagram(scan);
00268 }

Generated on Fri May 2 00:41:06 2003 for Panda by doxygen1.3