Panda3D
 All Classes Functions Variables Enumerations
renderEffect.cxx
00001 // Filename: renderEffect.cxx
00002 // Created by:  drose (14Mar02)
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 "renderEffect.h"
00016 #include "bamReader.h"
00017 #include "indent.h"
00018 #include "config_pgraph.h"
00019 
00020 RenderEffect::Effects *RenderEffect::_effects = NULL;
00021 TypeHandle RenderEffect::_type_handle;
00022 
00023 ////////////////////////////////////////////////////////////////////
00024 //     Function: RenderEffect::Constructor
00025 //       Access: Protected
00026 //  Description:
00027 ////////////////////////////////////////////////////////////////////
00028 RenderEffect::
00029 RenderEffect() {
00030   if (_effects == (Effects *)NULL) {
00031     // Make sure the global _effects map is allocated.  This only has
00032     // to be done once.  We could make this map static, but then we
00033     // run into problems if anyone creates a RenderState object at
00034     // static init time; it also seems to cause problems when the
00035     // Panda shared library is unloaded at application exit time.
00036     _effects = new Effects;
00037   }
00038   _saved_entry = _effects->end();
00039 }
00040 
00041 ////////////////////////////////////////////////////////////////////
00042 //     Function: RenderEffect::Copy Constructor
00043 //       Access: Private
00044 //  Description: RenderEffects are not meant to be copied.
00045 ////////////////////////////////////////////////////////////////////
00046 RenderEffect::
00047 RenderEffect(const RenderEffect &) {
00048   nassertv(false);
00049 }
00050 
00051 ////////////////////////////////////////////////////////////////////
00052 //     Function: RenderEffect::Copy Assignment Operator
00053 //       Access: Private
00054 //  Description: RenderEffects are not meant to be copied.
00055 ////////////////////////////////////////////////////////////////////
00056 void RenderEffect::
00057 operator = (const RenderEffect &) {
00058   nassertv(false);
00059 }
00060 
00061 ////////////////////////////////////////////////////////////////////
00062 //     Function: RenderEffect::Destructor
00063 //       Access: Public, Virtual
00064 //  Description: The destructor is responsible for removing the
00065 //               RenderEffect from the global set if it is there.
00066 ////////////////////////////////////////////////////////////////////
00067 RenderEffect::
00068 ~RenderEffect() {
00069   if (_saved_entry != _effects->end()) {
00070     // We cannot make this assertion, because the RenderEffect has
00071     // already partially destructed--this means we cannot look up the
00072     // object in the map.  In fact, the map is temporarily invalid
00073     // until we finish destructing, since we screwed up the ordering
00074     // when we changed the return value of get_type().
00075     //    nassertv(_effects->find(this) == _saved_entry);
00076 
00077     // Note: this isn't thread-safe, because once the derived class
00078     // destructor exits and before this destructor completes, the map
00079     // is invalid, and other threads may inadvertently attempt to read
00080     // the invalid map.  To make it thread-safe, we need to move this
00081     // functionality to a separate method, that is to be called from
00082     // *each* derived class's destructor (and then we can put the
00083     // above assert back in).
00084     _effects->erase(_saved_entry);
00085     _saved_entry = _effects->end();
00086   }
00087 }
00088 
00089 ////////////////////////////////////////////////////////////////////
00090 //     Function: RenderEffect::safe_to_transform
00091 //       Access: Public, Virtual
00092 //  Description: Returns true if it is generally safe to transform
00093 //               this particular kind of RenderEffect by calling the
00094 //               xform() method, false otherwise.
00095 ////////////////////////////////////////////////////////////////////
00096 bool RenderEffect::
00097 safe_to_transform() const {
00098   return true;
00099 }
00100 
00101 ////////////////////////////////////////////////////////////////////
00102 //     Function: RenderEffect::prepare_flatten_transform
00103 //       Access: Public, Virtual
00104 //  Description: Preprocesses the accumulated transform that is about
00105 //               to be applied to (or through) this node due to a
00106 //               flatten operation.  The returned value will be used
00107 //               instead.
00108 ////////////////////////////////////////////////////////////////////
00109 CPT(TransformState) RenderEffect::
00110 prepare_flatten_transform(const TransformState *net_transform) const {
00111   return net_transform;
00112 }
00113 
00114 ////////////////////////////////////////////////////////////////////
00115 //     Function: RenderEffect::safe_to_combine
00116 //       Access: Public, Virtual
00117 //  Description: Returns true if this kind of effect can safely be
00118 //               combined with sibling nodes that share the exact same
00119 //               effect, or false if this is not a good idea.
00120 ////////////////////////////////////////////////////////////////////
00121 bool RenderEffect::
00122 safe_to_combine() const {
00123   return true;
00124 }
00125 
00126 ////////////////////////////////////////////////////////////////////
00127 //     Function: RenderEffect::xform
00128 //       Access: Public, Virtual
00129 //  Description: Returns a new RenderEffect transformed by the
00130 //               indicated matrix.
00131 ////////////////////////////////////////////////////////////////////
00132 CPT(RenderEffect) RenderEffect::
00133 xform(const LMatrix4 &) const {
00134   return this;
00135 }
00136 
00137 ////////////////////////////////////////////////////////////////////
00138 //     Function: RenderEffect::has_cull_callback
00139 //       Access: Public, Virtual
00140 //  Description: Should be overridden by derived classes to return
00141 //               true if cull_callback() has been defined.  Otherwise,
00142 //               returns false to indicate cull_callback() does not
00143 //               need to be called for this effect during the cull
00144 //               traversal.
00145 ////////////////////////////////////////////////////////////////////
00146 bool RenderEffect::
00147 has_cull_callback() const {
00148   return false;
00149 }
00150 
00151 ////////////////////////////////////////////////////////////////////
00152 //     Function: RenderEffect::cull_callback
00153 //       Access: Public, Virtual
00154 //  Description: If has_cull_callback() returns true, this function
00155 //               will be called during the cull traversal to perform
00156 //               any additional operations that should be performed at
00157 //               cull time.  This may include additional manipulation
00158 //               of render state or additional visible/invisible
00159 //               decisions, or any other arbitrary operation.
00160 //
00161 //               At the time this function is called, the current
00162 //               node's transform and state have not yet been applied
00163 //               to the net_transform and net_state.  This callback
00164 //               may modify the node_transform and node_state to apply
00165 //               an effective change to the render state at this
00166 //               level.
00167 ////////////////////////////////////////////////////////////////////
00168 void RenderEffect::
00169 cull_callback(CullTraverser *, CullTraverserData &,
00170               CPT(TransformState) &, CPT(RenderState) &) const {
00171 }
00172 
00173 ////////////////////////////////////////////////////////////////////
00174 //     Function: RenderEffect::has_adjust_transform
00175 //       Access: Public, Virtual
00176 //  Description: Should be overridden by derived classes to return
00177 //               true if adjust_transform() has been defined, and
00178 //               therefore the RenderEffect has some effect on the
00179 //               node's apparent local and net transforms.
00180 ////////////////////////////////////////////////////////////////////
00181 bool RenderEffect::
00182 has_adjust_transform() const {
00183   return false;
00184 }
00185 
00186 ////////////////////////////////////////////////////////////////////
00187 //     Function: RenderEffect::adjust_transform
00188 //       Access: Public, Virtual
00189 //  Description: Performs some operation on the node's apparent net
00190 //               and/or local transforms.  This will only be called if
00191 //               has_adjust_transform() is redefined to return true.
00192 //
00193 //               Both parameters are in/out.  The original transforms
00194 //               will be passed in, and they may (or may not) be
00195 //               modified in-place by the RenderEffect.
00196 ////////////////////////////////////////////////////////////////////
00197 void RenderEffect::
00198 adjust_transform(CPT(TransformState) &, CPT(TransformState) &,
00199                  PandaNode *) const {
00200 }
00201 
00202 ////////////////////////////////////////////////////////////////////
00203 //     Function: RenderEffect::output
00204 //       Access: Published, Virtual
00205 //  Description: 
00206 ////////////////////////////////////////////////////////////////////
00207 void RenderEffect::
00208 output(ostream &out) const {
00209   out << get_type();
00210 }
00211 
00212 ////////////////////////////////////////////////////////////////////
00213 //     Function: RenderEffect::write
00214 //       Access: Published, Virtual
00215 //  Description: 
00216 ////////////////////////////////////////////////////////////////////
00217 void RenderEffect::
00218 write(ostream &out, int indent_level) const {
00219   indent(out, indent_level) << *this << "\n";
00220 }
00221 
00222 ////////////////////////////////////////////////////////////////////
00223 //     Function: RenderEffect::get_num_effects
00224 //       Access: Published, Static
00225 //  Description: Returns the total number of unique RenderEffect
00226 //               objects allocated in the world.  This will go up and
00227 //               down during normal operations.
00228 ////////////////////////////////////////////////////////////////////
00229 int RenderEffect::
00230 get_num_effects() {
00231   if (_effects == (Effects *)NULL) {
00232     return 0;
00233   }
00234   return _effects->size();
00235 }
00236 
00237 ////////////////////////////////////////////////////////////////////
00238 //     Function: RenderEffect::list_effects
00239 //       Access: Published, Static
00240 //  Description: Lists all of the RenderEffects in the cache to the
00241 //               output stream, one per line.  This can be quite a lot
00242 //               of output if the cache is large, so be prepared.
00243 ////////////////////////////////////////////////////////////////////
00244 void RenderEffect::
00245 list_effects(ostream &out) {
00246   out << _effects->size() << " effects:\n";
00247   Effects::const_iterator si;
00248   for (si = _effects->begin(); si != _effects->end(); ++si) {
00249     const RenderEffect *effect = (*si);
00250     effect->write(out, 2);
00251   }
00252 }
00253 
00254 ////////////////////////////////////////////////////////////////////
00255 //     Function: RenderEffect::validate_effects
00256 //       Access: Published, Static
00257 //  Description: Ensures that the cache is still stored in sorted
00258 //               order.  Returns true if so, false if there is a
00259 //               problem (which implies someone has modified one of
00260 //               the supposedly-const RenderEffect objects).
00261 ////////////////////////////////////////////////////////////////////
00262 bool RenderEffect::
00263 validate_effects() {
00264   if (_effects->empty()) {
00265     return true;
00266   }
00267 
00268   Effects::const_iterator si = _effects->begin();
00269   Effects::const_iterator snext = si;
00270   ++snext;
00271   while (snext != _effects->end()) {
00272     if ((*si)->compare_to(*(*snext)) >= 0) {
00273       pgraph_cat.error()
00274         << "RenderEffects out of order!\n";
00275       (*si)->write(pgraph_cat.error(false), 2);
00276       (*snext)->write(pgraph_cat.error(false), 2);
00277       return false;
00278     }
00279     si = snext;
00280     ++snext;
00281   }
00282 
00283   return true;
00284 }
00285 
00286 ////////////////////////////////////////////////////////////////////
00287 //     Function: RenderEffect::return_new
00288 //       Access: Protected, Static
00289 //  Description: This function is used by derived RenderEffect types
00290 //               to share a common RenderEffect pointer for all
00291 //               equivalent RenderEffect objects.
00292 //
00293 //               The make() function of the derived type should create
00294 //               a new RenderEffect and pass it through return_new(),
00295 //               which will either save the pointer and return it
00296 //               unchanged (if this is the first similar such object)
00297 //               or delete it and return an equivalent pointer (if
00298 //               there was already a similar object saved).
00299 ////////////////////////////////////////////////////////////////////
00300 CPT(RenderEffect) RenderEffect::
00301 return_new(RenderEffect *effect) {
00302   nassertr(effect != (RenderEffect *)NULL, effect);
00303 
00304   // This should be a newly allocated pointer, not one that was used
00305   // for anything else.
00306   nassertr(effect->_saved_entry == _effects->end(), effect);
00307 
00308 #ifndef NDEBUG
00309   if (paranoid_const) {
00310     nassertr(validate_effects(), effect);
00311   }
00312 #endif
00313 
00314   // Save the effect in a local PointerTo so that it will be freed at
00315   // the end of this function if no one else uses it.
00316   CPT(RenderEffect) pt_effect = effect;
00317 
00318   pair<Effects::iterator, bool> result = _effects->insert(effect);
00319   if (result.second) {
00320     // The effect was inserted; save the iterator and return the
00321     // input effect.
00322     effect->_saved_entry = result.first;
00323     return pt_effect;
00324   }
00325 
00326   // The effect was not inserted; there must be an equivalent one
00327   // already in the set.  Return that one.
00328   return *(result.first);
00329 }
00330 
00331 ////////////////////////////////////////////////////////////////////
00332 //     Function: RenderEffect::compare_to_impl
00333 //       Access: Protected, Virtual
00334 //  Description: Intended to be overridden by derived RenderEffect
00335 //               types to return a unique number indicating whether
00336 //               this RenderEffect is equivalent to the other one.
00337 //
00338 //               This should return 0 if the two RenderEffect objects
00339 //               are equivalent, a number less than zero if this one
00340 //               should be sorted before the other one, and a number
00341 //               greater than zero otherwise.
00342 //
00343 //               This will only be called with two RenderEffect
00344 //               objects whose get_type() functions return the same.
00345 ////////////////////////////////////////////////////////////////////
00346 int RenderEffect::
00347 compare_to_impl(const RenderEffect *other) const {
00348   return 0;
00349 }
00350 
00351 ////////////////////////////////////////////////////////////////////
00352 //     Function: RenderEffect::write_datagram
00353 //       Access: Public, Virtual
00354 //  Description: Writes the contents of this object to the datagram
00355 //               for shipping out to a Bam file.
00356 ////////////////////////////////////////////////////////////////////
00357 void RenderEffect::
00358 write_datagram(BamWriter *manager, Datagram &dg) {
00359   TypedWritable::write_datagram(manager, dg);
00360 }
00361 
00362 ////////////////////////////////////////////////////////////////////
00363 //     Function: RenderEffect::change_this
00364 //       Access: Public, Static
00365 //  Description: Called immediately after complete_pointers(), this
00366 //               gives the object a chance to adjust its own pointer
00367 //               if desired.  Most objects don't change pointers after
00368 //               completion, but some need to.
00369 //
00370 //               Once this function has been called, the old pointer
00371 //               will no longer be accessed.
00372 ////////////////////////////////////////////////////////////////////
00373 TypedWritable *RenderEffect::
00374 change_this(TypedWritable *old_ptr, BamReader *manager) {
00375   // First, uniquify the pointer.
00376   RenderEffect *effect = DCAST(RenderEffect, old_ptr);
00377   CPT(RenderEffect) pointer = return_new(effect);
00378 
00379   // But now we have a problem, since we have to hold the reference
00380   // count and there's no way to return a TypedWritable while still
00381   // holding the reference count!  We work around this by explicitly
00382   // upping the count, and also setting a finalize() callback to down
00383   // it later.
00384   if (pointer == effect) {
00385     pointer->ref();
00386     manager->register_finalize(effect);
00387   }
00388   
00389   // We have to cast the pointer back to non-const, because the bam
00390   // reader expects that.
00391   return (RenderEffect *)pointer.p();
00392 }
00393 
00394 ////////////////////////////////////////////////////////////////////
00395 //     Function: RenderEffect::finalize
00396 //       Access: Public, Virtual
00397 //  Description: Called by the BamReader to perform any final actions
00398 //               needed for setting up the object after all objects
00399 //               have been read and all pointers have been completed.
00400 ////////////////////////////////////////////////////////////////////
00401 void RenderEffect::
00402 finalize(BamReader *) {
00403   // Unref the pointer that we explicitly reffed in change_this().
00404   unref();
00405 
00406   // We should never get back to zero after unreffing our own count,
00407   // because we expect to have been stored in a pointer somewhere.  If
00408   // we do get to zero, it's a memory leak; the way to avoid this is
00409   // to call unref_delete() above instead of unref(), but this is
00410   // dangerous to do from within a virtual function.
00411   nassertv(get_ref_count() != 0);
00412 }
00413 
00414 ////////////////////////////////////////////////////////////////////
00415 //     Function: RenderEffect::fillin
00416 //       Access: Protected
00417 //  Description: This internal function is called by make_from_bam to
00418 //               read in all of the relevant data from the BamFile for
00419 //               the new RenderEffect.
00420 ////////////////////////////////////////////////////////////////////
00421 void RenderEffect::
00422 fillin(DatagramIterator &scan, BamReader *manager) {
00423   TypedWritable::fillin(scan, manager);
00424 }
 All Classes Functions Variables Enumerations