Panda3D

compassEffect.cxx

00001 // Filename: compassEffect.cxx
00002 // Created by:  drose (16Jul02)
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 "compassEffect.h"
00016 #include "cullTraverserData.h"
00017 #include "config_pgraph.h"
00018 #include "nodePath.h"
00019 #include "bamReader.h"
00020 #include "bamWriter.h"
00021 #include "datagram.h"
00022 #include "datagramIterator.h"
00023 
00024 TypeHandle CompassEffect::_type_handle;
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //     Function: CompassEffect::make
00028 //       Access: Published, Static
00029 //  Description: Constructs a new CompassEffect object.  If the
00030 //               reference is an empty NodePath, it means the
00031 //               CompassEffect is relative to the root of the scene
00032 //               graph; otherwise, it's relative to the indicated
00033 //               node.  The properties bitmask specifies the set of
00034 //               properties that the compass node inherits from the
00035 //               reference instead of from its parent.
00036 ////////////////////////////////////////////////////////////////////
00037 CPT(RenderEffect) CompassEffect::
00038 make(const NodePath &reference, int properties) {
00039   CompassEffect *effect = new CompassEffect;
00040   effect->_reference = reference;
00041   effect->_properties = (properties & P_all);
00042   return return_new(effect);
00043 }
00044 
00045 ////////////////////////////////////////////////////////////////////
00046 //     Function: CompassEffect::safe_to_transform
00047 //       Access: Public, Virtual
00048 //  Description: Returns true if it is generally safe to transform
00049 //               this particular kind of RenderEffect by calling the
00050 //               xform() method, false otherwise.
00051 ////////////////////////////////////////////////////////////////////
00052 bool CompassEffect::
00053 safe_to_transform() const {
00054   return false;
00055 }
00056 
00057 ////////////////////////////////////////////////////////////////////
00058 //     Function: CompassEffect::output
00059 //       Access: Public, Virtual
00060 //  Description: 
00061 ////////////////////////////////////////////////////////////////////
00062 void CompassEffect::
00063 output(ostream &out) const {
00064   out << get_type() << ":";
00065   if (_properties == 0) {
00066     out << " none";
00067   }
00068   if ((_properties & P_pos) == P_pos) {
00069     out << " xyz";
00070   } else {
00071     if ((_properties & P_x) != 0) {
00072       out << " x";
00073     }
00074     if ((_properties & P_y) != 0) {
00075       out << " y";
00076     }
00077     if ((_properties & P_z) != 0) {
00078       out << " z";
00079     }
00080   }
00081   if ((_properties & P_rot) != 0) {
00082     out << " rot";
00083   }
00084   if ((_properties & P_scale) == P_scale) {
00085     out << " scale";
00086   } else {
00087     if ((_properties & P_sx) != 0) {
00088       out << " sx";
00089     }
00090     if ((_properties & P_sy) != 0) {
00091       out << " sy";
00092     }
00093     if ((_properties & P_sz) != 0) {
00094       out << " sz";
00095     }
00096   }
00097   if (!_reference.is_empty()) {
00098     out << " reference " << _reference;
00099   }
00100 }
00101 
00102 ////////////////////////////////////////////////////////////////////
00103 //     Function: CompassEffect::has_cull_callback
00104 //       Access: Public, Virtual
00105 //  Description: Should be overridden by derived classes to return
00106 //               true if cull_callback() has been defined.  Otherwise,
00107 //               returns false to indicate cull_callback() does not
00108 //               need to be called for this effect during the cull
00109 //               traversal.
00110 ////////////////////////////////////////////////////////////////////
00111 bool CompassEffect::
00112 has_cull_callback() const {
00113   return true;
00114 }
00115 
00116 ////////////////////////////////////////////////////////////////////
00117 //     Function: CompassEffect::cull_callback
00118 //       Access: Public, Virtual
00119 //  Description: If has_cull_callback() returns true, this function
00120 //               will be called during the cull traversal to perform
00121 //               any additional operations that should be performed at
00122 //               cull time.  This may include additional manipulation
00123 //               of render state or additional visible/invisible
00124 //               decisions, or any other arbitrary operation.
00125 //
00126 //               At the time this function is called, the current
00127 //               node's transform and state have not yet been applied
00128 //               to the net_transform and net_state.  This callback
00129 //               may modify the node_transform and node_state to apply
00130 //               an effective change to the render state at this
00131 //               level.
00132 ////////////////////////////////////////////////////////////////////
00133 void CompassEffect::
00134 cull_callback(CullTraverser *trav, CullTraverserData &data,
00135               CPT(TransformState) &node_transform,
00136               CPT(RenderState) &) const {
00137   if (_properties == 0) {
00138     // Nothing to do.
00139     return;
00140   }
00141 
00142   CPT(TransformState) true_net_transform = data.get_net_transform(trav);
00143   CPT(TransformState) want_net_transform = true_net_transform;
00144   adjust_transform(want_net_transform, node_transform, data.node());
00145 
00146   // Now compute the transform that will convert true_net_transform to
00147   // want_transform.  This is inv(true_net_transform) * want_transform.
00148   CPT(TransformState) compass_transform =
00149     true_net_transform->invert_compose(want_net_transform);
00150 
00151   // And modify our local node's apparent transform so that
00152   // true_net_transform->compose(new_node_transform) produces the same
00153   // result we would have gotten had we actually computed
00154   // want_transform->compose(orig_node_transform).
00155   node_transform = compass_transform->compose(node_transform);
00156 }
00157 
00158 ////////////////////////////////////////////////////////////////////
00159 //     Function: CompassEffect::has_adjust_transform
00160 //       Access: Public, Virtual
00161 //  Description: Should be overridden by derived classes to return
00162 //               true if adjust_transform() has been defined, and
00163 //               therefore the RenderEffect has some effect on the
00164 //               node's apparent local and net transforms.
00165 ////////////////////////////////////////////////////////////////////
00166 bool CompassEffect::
00167 has_adjust_transform() const {
00168   return (_properties != 0);
00169 }
00170 
00171 ////////////////////////////////////////////////////////////////////
00172 //     Function: CompassEffect::adjust_transform
00173 //       Access: Public, Virtual
00174 //  Description: Performs some operation on the node's apparent net
00175 //               and/or local transforms.  This will only be called if
00176 //               has_adjust_transform() is redefined to return true.
00177 //
00178 //               Both parameters are in/out.  The original transforms
00179 //               will be passed in, and they may (or may not) be
00180 //               modified in-place by the RenderEffect.
00181 ////////////////////////////////////////////////////////////////////
00182 void CompassEffect::
00183 adjust_transform(CPT(TransformState) &net_transform,
00184                  CPT(TransformState) &node_transform,
00185                  PandaNode *) const {
00186   if (_properties == 0) {
00187     // Nothing to do.
00188     return;
00189   }
00190 
00191   // The reference transform: where we are acting as if we inherit
00192   // from.  Either the root node (identity) or the specified reference
00193   // node.
00194   CPT(TransformState) ref_transform;
00195   if (_reference.is_empty()) {
00196     ref_transform = TransformState::make_identity();
00197   } else {
00198     ref_transform = _reference.get_net_transform();
00199   }
00200 
00201   // Now compute the net transform we actually want to achieve.  This
00202   // is all of the components from the net transform we want to
00203   // inherit normally from our parent, with all of the components from
00204   // the ref transform we want to inherit from our reference.
00205   CPT(TransformState) want_net_transform;
00206   if (_properties == P_all) {
00207     // If we want to steal the whole transform, that's easy.
00208     want_net_transform = ref_transform;
00209 
00210   } else {
00211     // How much of the pos do we want to steal?  We can always
00212     // determine a transform's pos, even if it's nondecomposable.
00213     LVecBase3 want_pos = net_transform->get_pos();
00214     const LVecBase3 &ref_pos = ref_transform->get_pos();
00215     if ((_properties & P_x) != 0) {
00216       want_pos[0] = ref_pos[0];
00217     }
00218     if ((_properties & P_y) != 0) {
00219       want_pos[1] = ref_pos[1];
00220     }
00221     if ((_properties & P_z) != 0) {
00222       want_pos[2] = ref_pos[2];
00223     }
00224 
00225     if ((_properties & ~P_pos) == 0) {
00226       // If we only want to steal the pos, that's pretty easy.
00227       want_net_transform = net_transform->set_pos(want_pos);
00228   
00229     } else if ((_properties & (P_rot | P_scale)) == (P_rot | P_scale)) {
00230       // If we want to steal everything *but* the pos, also easy.
00231       want_net_transform = ref_transform->set_pos(want_pos);
00232       
00233     } else {
00234       // For any other combination, we have to be able to decompose both
00235       // transforms.
00236       if (!net_transform->has_components() || 
00237           !ref_transform->has_components()) {
00238         // If we can't decompose, just do the best we can: steal
00239         // everything but the pos.
00240         want_net_transform = ref_transform->set_pos(want_pos);
00241 
00242       } else {
00243         // If we can decompose, then take only the components we want.
00244         LQuaternion want_quat = net_transform->get_quat();
00245         if ((_properties & P_rot) != 0) {
00246           want_quat = ref_transform->get_quat();
00247         }
00248 
00249         LVecBase3 want_scale = net_transform->get_scale();
00250         const LVecBase3 &ref_scale = ref_transform->get_scale();
00251         if ((_properties & P_sx) != 0) {
00252           want_scale[0] = ref_scale[0];
00253         }
00254         if ((_properties & P_sy) != 0) {
00255           want_scale[1] = ref_scale[1];
00256         }
00257         if ((_properties & P_sz) != 0) {
00258           want_scale[2] = ref_scale[2];
00259         }
00260 
00261         want_net_transform =
00262           TransformState::make_pos_quat_scale(want_pos, want_quat, want_scale);
00263       }
00264     }
00265   }
00266 
00267   net_transform = want_net_transform;
00268 }
00269 
00270 ////////////////////////////////////////////////////////////////////
00271 //     Function: CompassEffect::compare_to_impl
00272 //       Access: Protected, Virtual
00273 //  Description: Intended to be overridden by derived CompassEffect
00274 //               types to return a unique number indicating whether
00275 //               this CompassEffect is equivalent to the other one.
00276 //
00277 //               This should return 0 if the two CompassEffect objects
00278 //               are equivalent, a number less than zero if this one
00279 //               should be sorted before the other one, and a number
00280 //               greater than zero otherwise.
00281 //
00282 //               This will only be called with two CompassEffect
00283 //               objects whose get_type() functions return the same.
00284 ////////////////////////////////////////////////////////////////////
00285 int CompassEffect::
00286 compare_to_impl(const RenderEffect *other) const {
00287   const CompassEffect *ta;
00288   DCAST_INTO_R(ta, other, 0);
00289 
00290   if (_properties != ta->_properties) {
00291     return _properties - ta->_properties;
00292   }
00293   int compare = _reference.compare_to(ta->_reference);
00294   if (compare != 0) {
00295     return compare;
00296   }
00297   return 0;
00298 }
00299 
00300 ////////////////////////////////////////////////////////////////////
00301 //     Function: CompassEffect::register_with_read_factory
00302 //       Access: Public, Static
00303 //  Description: Tells the BamReader how to create objects of type
00304 //               CompassEffect.
00305 ////////////////////////////////////////////////////////////////////
00306 void CompassEffect::
00307 register_with_read_factory() {
00308   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00309 }
00310 
00311 ////////////////////////////////////////////////////////////////////
00312 //     Function: CompassEffect::write_datagram
00313 //       Access: Public, Virtual
00314 //  Description: Writes the contents of this object to the datagram
00315 //               for shipping out to a Bam file.
00316 ////////////////////////////////////////////////////////////////////
00317 void CompassEffect::
00318 write_datagram(BamWriter *manager, Datagram &dg) {
00319   RenderEffect::write_datagram(manager, dg);
00320   dg.add_uint16(_properties);
00321   // *** We don't write out the _reference NodePath right now.  Maybe
00322   // we should.
00323 }
00324 
00325 ////////////////////////////////////////////////////////////////////
00326 //     Function: CompassEffect::make_from_bam
00327 //       Access: Protected, Static
00328 //  Description: This function is called by the BamReader's factory
00329 //               when a new object of type CompassEffect is encountered
00330 //               in the Bam file.  It should create the CompassEffect
00331 //               and extract its information from the file.
00332 ////////////////////////////////////////////////////////////////////
00333 TypedWritable *CompassEffect::
00334 make_from_bam(const FactoryParams &params) {
00335   CompassEffect *effect = new CompassEffect;
00336   DatagramIterator scan;
00337   BamReader *manager;
00338 
00339   parse_params(params, scan, manager);
00340   effect->fillin(scan, manager);
00341 
00342   return effect;
00343 }
00344 
00345 ////////////////////////////////////////////////////////////////////
00346 //     Function: CompassEffect::fillin
00347 //       Access: Protected
00348 //  Description: This internal function is called by make_from_bam to
00349 //               read in all of the relevant data from the BamFile for
00350 //               the new CompassEffect.
00351 ////////////////////////////////////////////////////////////////////
00352 void CompassEffect::
00353 fillin(DatagramIterator &scan, BamReader *manager) {
00354   RenderEffect::fillin(scan, manager);
00355   _properties = scan.get_uint16();
00356 }
 All Classes Functions Variables Enumerations