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

panda/src/pgraph/compassEffect.cxx

Go to the documentation of this file.
00001 // Filename: compassEffect.cxx
00002 // Created by:  drose (16Jul02)
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 "compassEffect.h"
00020 #include "config_pgraph.h"
00021 #include "nodePath.h"
00022 #include "bamReader.h"
00023 #include "bamWriter.h"
00024 #include "datagram.h"
00025 #include "datagramIterator.h"
00026 
00027 TypeHandle CompassEffect::_type_handle;
00028 
00029 ////////////////////////////////////////////////////////////////////
00030 //     Function: CompassEffect::make
00031 //       Access: Published, Static
00032 //  Description: Constructs a new CompassEffect object.  If the
00033 //               reference is an empty NodePath, it means the
00034 //               CompassEffect is relative to the root of the scene
00035 //               graph; otherwise, it's relative to the indicated
00036 //               node.  The properties bitmask specifies the set of
00037 //               properties that the compass node inherits from the
00038 //               reference instead of from its parent.
00039 ////////////////////////////////////////////////////////////////////
00040 CPT(RenderEffect) CompassEffect::
00041 make(const NodePath &reference, int properties) {
00042   CompassEffect *effect = new CompassEffect;
00043   effect->_reference = reference;
00044   effect->_properties = (properties & P_all);
00045   return return_new(effect);
00046 }
00047 
00048 ////////////////////////////////////////////////////////////////////
00049 //     Function: CompassEffect::safe_to_transform
00050 //       Access: Public, Virtual
00051 //  Description: Returns true if it is generally safe to transform
00052 //               this particular kind of RenderEffect by calling the
00053 //               xform() method, false otherwise.
00054 ////////////////////////////////////////////////////////////////////
00055 bool CompassEffect::
00056 safe_to_transform() const {
00057   return false;
00058 }
00059 
00060 ////////////////////////////////////////////////////////////////////
00061 //     Function: CompassEffect::output
00062 //       Access: Public, Virtual
00063 //  Description: 
00064 ////////////////////////////////////////////////////////////////////
00065 void CompassEffect::
00066 output(ostream &out) const {
00067   out << get_type() << ":";
00068   if (_properties == 0) {
00069     out << " none";
00070   }
00071   if ((_properties & P_pos) == P_pos) {
00072     out << " xyz";
00073   } else {
00074     if ((_properties & P_x) != 0) {
00075       out << " x";
00076     }
00077     if ((_properties & P_y) != 0) {
00078       out << " y";
00079     }
00080     if ((_properties & P_z) != 0) {
00081       out << " z";
00082     }
00083   }
00084   if ((_properties & P_rot) != 0) {
00085     out << " rot";
00086   }
00087   if ((_properties & P_scale) == P_scale) {
00088     out << " scale";
00089   } else {
00090     if ((_properties & P_sx) != 0) {
00091       out << " sx";
00092     }
00093     if ((_properties & P_sy) != 0) {
00094       out << " sy";
00095     }
00096     if ((_properties & P_sz) != 0) {
00097       out << " sz";
00098     }
00099   }
00100   if (!_reference.is_empty()) {
00101     out << " reference " << _reference;
00102   }
00103 }
00104 
00105 ////////////////////////////////////////////////////////////////////
00106 //     Function: CompassEffect::do_compass
00107 //       Access: Public
00108 //  Description: Computes the appropriate transform to rotate the node
00109 //               according to the reference node, or to the root
00110 //               transform if there is no reference node.
00111 ////////////////////////////////////////////////////////////////////
00112 CPT(TransformState) CompassEffect::
00113 do_compass(const TransformState *net_transform,
00114            const TransformState *node_transform) const {
00115   if (_properties == 0) {
00116     // Nothing to do.
00117     return TransformState::make_identity();
00118   }
00119 
00120   // Compute the reference transform: our transform, as applied to the
00121   // reference node.
00122   CPT(TransformState) ref_transform;
00123   if (_reference.is_empty()) {
00124     ref_transform = node_transform;
00125   } else {
00126     ref_transform = _reference.get_net_transform()->compose(node_transform);
00127   }
00128 
00129   // Now compute the transform we actually want to achieve.  This is
00130   // all of the components from the net transform we want to inherit
00131   // normally from our parent, with all of the components from the ref
00132   // transform we want to inherit from our reference.
00133   CPT(TransformState) want_transform;
00134   if (_properties == P_all) {
00135     // If we want to steal the whole transform, that's easy.
00136     want_transform = ref_transform;
00137 
00138   } else {
00139     // How much of the pos do we want to steal?  We can always
00140     // determine a transform's pos, even if it's nondecomposable.
00141     LVecBase3f want_pos = net_transform->get_pos();
00142     const LVecBase3f &ref_pos = ref_transform->get_pos();
00143     if ((_properties & P_x) != 0) {
00144       want_pos[0] = ref_pos[0];
00145     }
00146     if ((_properties & P_y) != 0) {
00147       want_pos[1] = ref_pos[1];
00148     }
00149     if ((_properties & P_z) != 0) {
00150       want_pos[2] = ref_pos[2];
00151     }
00152 
00153     if ((_properties & ~P_pos) == 0) {
00154       // If we only want to steal the pos, that's pretty easy.
00155       want_transform = net_transform->set_pos(want_pos);
00156   
00157     } else if ((_properties & (P_rot | P_scale)) == (P_rot | P_scale)) {
00158       // If we want to steal everything *but* the pos, also easy.
00159       want_transform = ref_transform->set_pos(want_pos);
00160       
00161     } else {
00162       // For any other combination, we have to be able to decompose both
00163       // transforms.
00164       if (!net_transform->has_components() || 
00165           !ref_transform->has_components()) {
00166         // If we can't decompose, just do the best we can: steal
00167         // everything but the pos.
00168         want_transform = ref_transform->set_pos(want_pos);
00169 
00170       } else {
00171         // If we can decompose, then take only the components we want.
00172         LQuaternionf want_quat = net_transform->get_quat();
00173         if ((_properties & P_rot) != 0) {
00174           want_quat = ref_transform->get_quat();
00175         }
00176 
00177         LVecBase3f want_scale = net_transform->get_scale();
00178         const LVecBase3f &ref_scale = ref_transform->get_scale();
00179         if ((_properties & P_sx) != 0) {
00180           want_scale[0] = ref_scale[0];
00181         }
00182         if ((_properties & P_sy) != 0) {
00183           want_scale[1] = ref_scale[1];
00184         }
00185         if ((_properties & P_sz) != 0) {
00186           want_scale[2] = ref_scale[2];
00187         }
00188 
00189         want_transform =
00190           TransformState::make_pos_quat_scale(want_pos, want_quat, want_scale);
00191       }
00192     }
00193   }
00194 
00195   // Now compute the transform that will convert net_transform to
00196   // want_transform.  This is inv(net_transform) * want_transform.
00197   return net_transform->invert_compose(want_transform);
00198 }
00199 
00200 ////////////////////////////////////////////////////////////////////
00201 //     Function: CompassEffect::compare_to_impl
00202 //       Access: Protected, Virtual
00203 //  Description: Intended to be overridden by derived CompassEffect
00204 //               types to return a unique number indicating whether
00205 //               this CompassEffect is equivalent to the other one.
00206 //
00207 //               This should return 0 if the two CompassEffect objects
00208 //               are equivalent, a number less than zero if this one
00209 //               should be sorted before the other one, and a number
00210 //               greater than zero otherwise.
00211 //
00212 //               This will only be called with two CompassEffect
00213 //               objects whose get_type() functions return the same.
00214 ////////////////////////////////////////////////////////////////////
00215 int CompassEffect::
00216 compare_to_impl(const RenderEffect *other) const {
00217   const CompassEffect *ta;
00218   DCAST_INTO_R(ta, other, 0);
00219 
00220   if (_properties != ta->_properties) {
00221     return _properties - ta->_properties;
00222   }
00223   int compare = _reference.compare_to(ta->_reference);
00224   if (compare != 0) {
00225     return compare;
00226   }
00227   return 0;
00228 }
00229 
00230 ////////////////////////////////////////////////////////////////////
00231 //     Function: CompassEffect::register_with_read_factory
00232 //       Access: Public, Static
00233 //  Description: Tells the BamReader how to create objects of type
00234 //               CompassEffect.
00235 ////////////////////////////////////////////////////////////////////
00236 void CompassEffect::
00237 register_with_read_factory() {
00238   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00239 }
00240 
00241 ////////////////////////////////////////////////////////////////////
00242 //     Function: CompassEffect::write_datagram
00243 //       Access: Public, Virtual
00244 //  Description: Writes the contents of this object to the datagram
00245 //               for shipping out to a Bam file.
00246 ////////////////////////////////////////////////////////////////////
00247 void CompassEffect::
00248 write_datagram(BamWriter *manager, Datagram &dg) {
00249   RenderEffect::write_datagram(manager, dg);
00250   dg.add_uint16(_properties);
00251   // *** We don't write out the _reference NodePath right now.  Maybe
00252   // we should.
00253 }
00254 
00255 ////////////////////////////////////////////////////////////////////
00256 //     Function: CompassEffect::make_from_bam
00257 //       Access: Protected, Static
00258 //  Description: This function is called by the BamReader's factory
00259 //               when a new object of type CompassEffect is encountered
00260 //               in the Bam file.  It should create the CompassEffect
00261 //               and extract its information from the file.
00262 ////////////////////////////////////////////////////////////////////
00263 TypedWritable *CompassEffect::
00264 make_from_bam(const FactoryParams &params) {
00265   CompassEffect *effect = new CompassEffect;
00266   DatagramIterator scan;
00267   BamReader *manager;
00268 
00269   parse_params(params, scan, manager);
00270   effect->fillin(scan, manager);
00271 
00272   return effect;
00273 }
00274 
00275 ////////////////////////////////////////////////////////////////////
00276 //     Function: CompassEffect::fillin
00277 //       Access: Protected
00278 //  Description: This internal function is called by make_from_bam to
00279 //               read in all of the relevant data from the BamFile for
00280 //               the new CompassEffect.
00281 ////////////////////////////////////////////////////////////////////
00282 void CompassEffect::
00283 fillin(DatagramIterator &scan, BamReader *manager) {
00284   RenderEffect::fillin(scan, manager);
00285   _properties = scan.get_uint16();
00286 }

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