Panda3D
|
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 }