00001 // Filename: renderEffects.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 "renderEffects.h" 00020 #include "billboardEffect.h" 00021 #include "decalEffect.h" 00022 #include "compassEffect.h" 00023 #include "showBoundsEffect.h" 00024 #include "config_pgraph.h" 00025 #include "bamReader.h" 00026 #include "bamWriter.h" 00027 #include "datagramIterator.h" 00028 #include "indent.h" 00029 #include "compareTo.h" 00030 00031 RenderEffects::States RenderEffects::_states; 00032 CPT(RenderEffects) RenderEffects::_empty_state; 00033 TypeHandle RenderEffects::_type_handle; 00034 00035 //////////////////////////////////////////////////////////////////// 00036 // Function: RenderEffects::Constructor 00037 // Access: Protected 00038 // Description: Actually, this could be a private constructor, since 00039 // no one inherits from RenderEffects, but gcc gives us a 00040 // spurious warning if all constructors are private. 00041 //////////////////////////////////////////////////////////////////// 00042 RenderEffects:: 00043 RenderEffects() { 00044 _saved_entry = _states.end(); 00045 _flags = 0; 00046 } 00047 00048 //////////////////////////////////////////////////////////////////// 00049 // Function: RenderEffects::Copy Constructor 00050 // Access: Private 00051 // Description: RenderEffectss are not meant to be copied. 00052 //////////////////////////////////////////////////////////////////// 00053 RenderEffects:: 00054 RenderEffects(const RenderEffects &) { 00055 nassertv(false); 00056 } 00057 00058 //////////////////////////////////////////////////////////////////// 00059 // Function: RenderEffects::Copy Assignment Operator 00060 // Access: Private 00061 // Description: RenderEffectss are not meant to be copied. 00062 //////////////////////////////////////////////////////////////////// 00063 void RenderEffects:: 00064 operator = (const RenderEffects &) { 00065 nassertv(false); 00066 } 00067 00068 //////////////////////////////////////////////////////////////////// 00069 // Function: RenderEffects::Destructor 00070 // Access: Public, Virtual 00071 // Description: The destructor is responsible for removing the 00072 // RenderEffects from the global set if it is there. 00073 //////////////////////////////////////////////////////////////////// 00074 RenderEffects:: 00075 ~RenderEffects() { 00076 // Remove the deleted RenderEffects object from the global pool. 00077 if (_saved_entry != _states.end()) { 00078 _states.erase(_saved_entry); 00079 _saved_entry = _states.end(); 00080 } 00081 } 00082 00083 //////////////////////////////////////////////////////////////////// 00084 // Function: RenderEffects::operator < 00085 // Access: Public 00086 // Description: Provides an arbitrary ordering among all unique 00087 // RenderEffectss, so we can store the essentially 00088 // different ones in a big set and throw away the rest. 00089 // 00090 // This method is not needed outside of the RenderEffects 00091 // class because all equivalent RenderEffects objects are 00092 // guaranteed to share the same pointer; thus, a pointer 00093 // comparison is always sufficient. 00094 //////////////////////////////////////////////////////////////////// 00095 bool RenderEffects:: 00096 operator < (const RenderEffects &other) const { 00097 // We must compare all the properties of the effects, not just 00098 // the type; thus, we compare them one at a time using compare_to(). 00099 return lexicographical_compare(_effects.begin(), _effects.end(), 00100 other._effects.begin(), other._effects.end(), 00101 CompareTo<Effect>()); 00102 } 00103 00104 //////////////////////////////////////////////////////////////////// 00105 // Function: RenderEffects::safe_to_transform 00106 // Access: Public 00107 // Description: Returns true if all of the effects in this set can 00108 // safely be transformed, and therefore the complete set 00109 // can be transformed, by calling xform(). 00110 //////////////////////////////////////////////////////////////////// 00111 bool RenderEffects:: 00112 safe_to_transform() const { 00113 Effects::const_iterator ai; 00114 for (ai = _effects.begin(); ai != _effects.end(); ++ai) { 00115 const Effect &effect = (*ai); 00116 if (!effect._effect->safe_to_transform()) { 00117 return false; 00118 } 00119 } 00120 00121 return true; 00122 } 00123 00124 //////////////////////////////////////////////////////////////////// 00125 // Function: RenderEffects::safe_to_combine 00126 // Access: Public 00127 // Description: Returns true if all of the effects in this set can 00128 // safely be shared with a sibling node that has the 00129 // exact same set of effects, or false if this would be 00130 // bad for any of the effects. 00131 //////////////////////////////////////////////////////////////////// 00132 bool RenderEffects:: 00133 safe_to_combine() const { 00134 Effects::const_iterator ai; 00135 for (ai = _effects.begin(); ai != _effects.end(); ++ai) { 00136 const Effect &effect = (*ai); 00137 if (!effect._effect->safe_to_combine()) { 00138 return false; 00139 } 00140 } 00141 00142 return true; 00143 } 00144 00145 //////////////////////////////////////////////////////////////////// 00146 // Function: RenderEffects::xform 00147 // Access: Public, Virtual 00148 // Description: Returns a new RenderEffects transformed by the 00149 // indicated matrix. 00150 //////////////////////////////////////////////////////////////////// 00151 CPT(RenderEffects) RenderEffects:: 00152 xform(const LMatrix4f &mat) const { 00153 if (is_empty()) { 00154 return this; 00155 } 00156 00157 RenderEffects *new_state = new RenderEffects; 00158 back_insert_iterator<Effects> result = 00159 back_inserter(new_state->_effects); 00160 00161 Effects::const_iterator ai; 00162 for (ai = _effects.begin(); ai != _effects.end(); ++ai) { 00163 const Effect &effect = (*ai); 00164 Effect new_effect(effect); 00165 new_effect._effect = effect._effect->xform(mat); 00166 *result = new_effect; 00167 ++result; 00168 } 00169 00170 return return_new(new_state); 00171 } 00172 00173 00174 //////////////////////////////////////////////////////////////////// 00175 // Function: RenderEffects::find_effect 00176 // Access: Published 00177 // Description: Searches for an effect with the indicated type in 00178 // the state, and returns its index if it is found, or 00179 // -1 if it is not. 00180 //////////////////////////////////////////////////////////////////// 00181 int RenderEffects:: 00182 find_effect(TypeHandle type) const { 00183 Effects::const_iterator ai = _effects.find(Effect(type)); 00184 if (ai == _effects.end()) { 00185 return -1; 00186 } 00187 return ai - _effects.begin(); 00188 } 00189 00190 //////////////////////////////////////////////////////////////////// 00191 // Function: RenderEffects::make_empty 00192 // Access: Published, Static 00193 // Description: Returns a RenderEffects with no effects set. 00194 //////////////////////////////////////////////////////////////////// 00195 CPT(RenderEffects) RenderEffects:: 00196 make_empty() { 00197 // The empty state is asked for so often, we make it a special case 00198 // and store a pointer forever once we find it the first time. 00199 if (_empty_state == (RenderEffects *)NULL) { 00200 RenderEffects *state = new RenderEffects; 00201 _empty_state = return_new(state); 00202 } 00203 00204 return _empty_state; 00205 } 00206 00207 //////////////////////////////////////////////////////////////////// 00208 // Function: RenderEffects::make 00209 // Access: Published, Static 00210 // Description: Returns a RenderEffects with one effect set. 00211 //////////////////////////////////////////////////////////////////// 00212 CPT(RenderEffects) RenderEffects:: 00213 make(const RenderEffect *effect) { 00214 RenderEffects *state = new RenderEffects; 00215 state->_effects.reserve(1); 00216 state->_effects.insert(Effect(effect)); 00217 return return_new(state); 00218 } 00219 00220 //////////////////////////////////////////////////////////////////// 00221 // Function: RenderEffects::make 00222 // Access: Published, Static 00223 // Description: Returns a RenderEffects with two effects set. 00224 //////////////////////////////////////////////////////////////////// 00225 CPT(RenderEffects) RenderEffects:: 00226 make(const RenderEffect *effect1, 00227 const RenderEffect *effect2) { 00228 RenderEffects *state = new RenderEffects; 00229 state->_effects.reserve(2); 00230 state->_effects.push_back(Effect(effect1)); 00231 state->_effects.push_back(Effect(effect2)); 00232 state->_effects.sort(); 00233 return return_new(state); 00234 } 00235 00236 //////////////////////////////////////////////////////////////////// 00237 // Function: RenderEffects::make 00238 // Access: Published, Static 00239 // Description: Returns a RenderEffects with three effects set. 00240 //////////////////////////////////////////////////////////////////// 00241 CPT(RenderEffects) RenderEffects:: 00242 make(const RenderEffect *effect1, 00243 const RenderEffect *effect2, 00244 const RenderEffect *effect3) { 00245 RenderEffects *state = new RenderEffects; 00246 state->_effects.reserve(2); 00247 state->_effects.push_back(Effect(effect1)); 00248 state->_effects.push_back(Effect(effect2)); 00249 state->_effects.push_back(Effect(effect3)); 00250 state->_effects.sort(); 00251 return return_new(state); 00252 } 00253 00254 //////////////////////////////////////////////////////////////////// 00255 // Function: RenderEffects::make 00256 // Access: Published, Static 00257 // Description: Returns a RenderEffects with four effects set. 00258 //////////////////////////////////////////////////////////////////// 00259 CPT(RenderEffects) RenderEffects:: 00260 make(const RenderEffect *effect1, 00261 const RenderEffect *effect2, 00262 const RenderEffect *effect3, 00263 const RenderEffect *effect4) { 00264 RenderEffects *state = new RenderEffects; 00265 state->_effects.reserve(2); 00266 state->_effects.push_back(Effect(effect1)); 00267 state->_effects.push_back(Effect(effect2)); 00268 state->_effects.push_back(Effect(effect3)); 00269 state->_effects.push_back(Effect(effect4)); 00270 state->_effects.sort(); 00271 return return_new(state); 00272 } 00273 00274 //////////////////////////////////////////////////////////////////// 00275 // Function: RenderEffects::add_effect 00276 // Access: Published 00277 // Description: Returns a new RenderEffects object that represents the 00278 // same as the source state, with the new RenderEffect 00279 // added. If there is already a RenderEffect with the 00280 // same type, it is replaced. 00281 //////////////////////////////////////////////////////////////////// 00282 CPT(RenderEffects) RenderEffects:: 00283 add_effect(const RenderEffect *effect) const { 00284 RenderEffects *new_state = new RenderEffects; 00285 back_insert_iterator<Effects> result = 00286 back_inserter(new_state->_effects); 00287 00288 Effect new_effect(effect); 00289 Effects::const_iterator ai = _effects.begin(); 00290 00291 while (ai != _effects.end() && (*ai) < new_effect) { 00292 *result = *ai; 00293 ++ai; 00294 ++result; 00295 } 00296 *result = new_effect; 00297 ++result; 00298 00299 if (ai != _effects.end() && !(new_effect < (*ai))) { 00300 // At this point we know: 00301 // !((*ai) < new_effect) && !(new_effect < (*ai)) 00302 // which means (*ai) == new_effect--so we should leave it out, 00303 // to avoid duplicating effects in the set. 00304 ++ai; 00305 } 00306 00307 while (ai != _effects.end()) { 00308 *result = *ai; 00309 ++ai; 00310 ++result; 00311 } 00312 00313 return return_new(new_state); 00314 } 00315 00316 //////////////////////////////////////////////////////////////////// 00317 // Function: RenderEffects::remove_effect 00318 // Access: Published 00319 // Description: Returns a new RenderEffects object that represents the 00320 // same as the source state, with the indicated 00321 // RenderEffect removed. 00322 //////////////////////////////////////////////////////////////////// 00323 CPT(RenderEffects) RenderEffects:: 00324 remove_effect(TypeHandle type) const { 00325 RenderEffects *new_state = new RenderEffects; 00326 back_insert_iterator<Effects> result = 00327 back_inserter(new_state->_effects); 00328 00329 Effects::const_iterator ai = _effects.begin(); 00330 00331 while (ai != _effects.end()) { 00332 if ((*ai)._type != type) { 00333 *result = *ai; 00334 ++result; 00335 } 00336 ++ai; 00337 } 00338 00339 return return_new(new_state); 00340 } 00341 00342 //////////////////////////////////////////////////////////////////// 00343 // Function: RenderEffects::get_effect 00344 // Access: Published, Virtual 00345 // Description: Looks for a RenderEffect of the indicated type in the 00346 // state, and returns it if it is found, or NULL if it 00347 // is not. 00348 //////////////////////////////////////////////////////////////////// 00349 const RenderEffect *RenderEffects:: 00350 get_effect(TypeHandle type) const { 00351 Effects::const_iterator ai; 00352 ai = _effects.find(Effect(type)); 00353 if (ai != _effects.end()) { 00354 return (*ai)._effect; 00355 } 00356 return NULL; 00357 } 00358 00359 //////////////////////////////////////////////////////////////////// 00360 // Function: RenderEffects::output 00361 // Access: Published, Virtual 00362 // Description: 00363 //////////////////////////////////////////////////////////////////// 00364 void RenderEffects:: 00365 output(ostream &out) const { 00366 out << "E:"; 00367 if (_effects.empty()) { 00368 out << "(empty)"; 00369 00370 } else { 00371 Effects::const_iterator ai = _effects.begin(); 00372 out << "(" << (*ai)._type; 00373 ++ai; 00374 while (ai != _effects.end()) { 00375 out << " " << (*ai)._type; 00376 ++ai; 00377 } 00378 out << ")"; 00379 } 00380 } 00381 00382 //////////////////////////////////////////////////////////////////// 00383 // Function: RenderEffects::write 00384 // Access: Published, Virtual 00385 // Description: 00386 //////////////////////////////////////////////////////////////////// 00387 void RenderEffects:: 00388 write(ostream &out, int indent_level) const { 00389 indent(out, indent_level) << _effects.size() << " effects:\n"; 00390 Effects::const_iterator ai; 00391 for (ai = _effects.begin(); ai != _effects.end(); ++ai) { 00392 const Effect &effect = (*ai); 00393 effect._effect->write(out, indent_level + 2); 00394 } 00395 } 00396 00397 //////////////////////////////////////////////////////////////////// 00398 // Function: RenderEffects::return_new 00399 // Access: Private, Static 00400 // Description: This function is used to share a common RenderEffects 00401 // pointer for all equivalent RenderEffects objects. 00402 // 00403 // See the similar logic in RenderEffect. The idea is 00404 // to create a new RenderEffects object and pass it 00405 // through this function, which will share the pointer 00406 // with a previously-created RenderEffects object if it is 00407 // equivalent. 00408 //////////////////////////////////////////////////////////////////// 00409 CPT(RenderEffects) RenderEffects:: 00410 return_new(RenderEffects *state) { 00411 nassertr(state != (RenderEffects *)NULL, state); 00412 00413 // This should be a newly allocated pointer, not one that was used 00414 // for anything else. 00415 nassertr(state->_saved_entry == _states.end(), state); 00416 00417 // Save the state in a local PointerTo so that it will be freed at 00418 // the end of this function if no one else uses it. 00419 CPT(RenderEffects) pt_state = state; 00420 00421 pair<States::iterator, bool> result = _states.insert(state); 00422 if (result.second) { 00423 // The state was inserted; save the iterator and return the 00424 // input state. 00425 state->_saved_entry = result.first; 00426 return pt_state; 00427 } 00428 00429 // The state was not inserted; there must be an equivalent one 00430 // already in the set. Return that one. 00431 return *(result.first); 00432 } 00433 00434 //////////////////////////////////////////////////////////////////// 00435 // Function: RenderEffects::determine_billboard 00436 // Access: Private 00437 // Description: This is the private implementation of 00438 // get_billboard(). 00439 //////////////////////////////////////////////////////////////////// 00440 void RenderEffects:: 00441 determine_billboard() { 00442 const RenderEffect *effect = get_effect(BillboardEffect::get_class_type()); 00443 _billboard = (const BillboardEffect *)NULL; 00444 if (effect != (const RenderEffect *)NULL) { 00445 _billboard = DCAST(BillboardEffect, effect); 00446 } 00447 _flags |= F_checked_billboard; 00448 } 00449 00450 //////////////////////////////////////////////////////////////////// 00451 // Function: RenderEffects::determine_decal 00452 // Access: Private 00453 // Description: This is the private implementation of has_decal(). 00454 //////////////////////////////////////////////////////////////////// 00455 void RenderEffects:: 00456 determine_decal() { 00457 const RenderEffect *effect = get_effect(DecalEffect::get_class_type()); 00458 if (effect != (const RenderEffect *)NULL) { 00459 _flags |= F_has_decal; 00460 } 00461 _flags |= F_checked_decal; 00462 } 00463 00464 //////////////////////////////////////////////////////////////////// 00465 // Function: RenderEffects::determine_compass 00466 // Access: Private 00467 // Description: This is the private implementation of has_compass(). 00468 //////////////////////////////////////////////////////////////////// 00469 void RenderEffects:: 00470 determine_compass() { 00471 const RenderEffect *effect = get_effect(CompassEffect::get_class_type()); 00472 _compass = (const CompassEffect *)NULL; 00473 if (effect != (const RenderEffect *)NULL) { 00474 _compass = DCAST(CompassEffect, effect); 00475 } 00476 _flags |= F_checked_compass; 00477 } 00478 00479 //////////////////////////////////////////////////////////////////// 00480 // Function: RenderEffects::determine_show_bounds 00481 // Access: Private 00482 // Description: This is the private implementation of has_show_bounds(). 00483 //////////////////////////////////////////////////////////////////// 00484 void RenderEffects:: 00485 determine_show_bounds() { 00486 const RenderEffect *effect = get_effect(ShowBoundsEffect::get_class_type()); 00487 if (effect != (const RenderEffect *)NULL) { 00488 _flags |= F_has_show_bounds; 00489 } 00490 _flags |= F_checked_show_bounds; 00491 } 00492 00493 //////////////////////////////////////////////////////////////////// 00494 // Function: RenderEffects::register_with_read_factory 00495 // Access: Public, Static 00496 // Description: Tells the BamReader how to create objects of type 00497 // RenderEffects. 00498 //////////////////////////////////////////////////////////////////// 00499 void RenderEffects:: 00500 register_with_read_factory() { 00501 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 00502 } 00503 00504 //////////////////////////////////////////////////////////////////// 00505 // Function: RenderEffects::write_datagram 00506 // Access: Public, Virtual 00507 // Description: Writes the contents of this object to the datagram 00508 // for shipping out to a Bam file. 00509 //////////////////////////////////////////////////////////////////// 00510 void RenderEffects:: 00511 write_datagram(BamWriter *manager, Datagram &dg) { 00512 TypedWritable::write_datagram(manager, dg); 00513 00514 int num_effects = _effects.size(); 00515 nassertv(num_effects == (int)(PN_uint16)num_effects); 00516 dg.add_uint16(num_effects); 00517 00518 Effects::const_iterator ai; 00519 for (ai = _effects.begin(); ai != _effects.end(); ++ai) { 00520 const Effect &effect = (*ai); 00521 00522 manager->write_pointer(dg, effect._effect); 00523 } 00524 } 00525 00526 //////////////////////////////////////////////////////////////////// 00527 // Function: RenderEffects::complete_pointers 00528 // Access: Public, Virtual 00529 // Description: Receives an array of pointers, one for each time 00530 // manager->read_pointer() was called in fillin(). 00531 // Returns the number of pointers processed. 00532 //////////////////////////////////////////////////////////////////// 00533 int RenderEffects:: 00534 complete_pointers(TypedWritable **p_list, BamReader *manager) { 00535 int pi = TypedWritable::complete_pointers(p_list, manager); 00536 00537 // Get the effect pointers. 00538 Effects::iterator ai; 00539 for (ai = _effects.begin(); ai != _effects.end(); ++ai) { 00540 Effect &effect = (*ai); 00541 00542 effect._effect = DCAST(RenderEffect, p_list[pi++]); 00543 nassertr(effect._effect != (RenderEffect *)NULL, pi); 00544 effect._type = effect._effect->get_type(); 00545 } 00546 00547 // Now make sure the array is properly sorted. (It won't 00548 // necessarily preserve its correct sort after being read from bam, 00549 // because the sort is based on TypeHandle indices, which can change 00550 // from session to session.) 00551 _effects.sort(); 00552 00553 return pi; 00554 } 00555 00556 //////////////////////////////////////////////////////////////////// 00557 // Function: RenderEffects::change_this 00558 // Access: Public, Static 00559 // Description: Called immediately after complete_pointers(), this 00560 // gives the object a chance to adjust its own pointer 00561 // if desired. Most objects don't change pointers after 00562 // completion, but some need to. 00563 // 00564 // Once this function has been called, the old pointer 00565 // will no longer be accessed. 00566 //////////////////////////////////////////////////////////////////// 00567 TypedWritable *RenderEffects:: 00568 change_this(TypedWritable *old_ptr, BamReader *manager) { 00569 // First, uniquify the pointer. 00570 RenderEffects *state = DCAST(RenderEffects, old_ptr); 00571 CPT(RenderEffects) pointer = return_new(state); 00572 00573 // But now we have a problem, since we have to hold the reference 00574 // count and there's no way to return a TypedWritable while still 00575 // holding the reference count! We work around this by explicitly 00576 // upping the count, and also setting a finalize() callback to down 00577 // it later. 00578 if (pointer == state) { 00579 pointer->ref(); 00580 manager->register_finalize(state); 00581 } 00582 00583 // We have to cast the pointer back to non-const, because the bam 00584 // reader expects that. 00585 return (RenderEffects *)pointer.p(); 00586 } 00587 00588 //////////////////////////////////////////////////////////////////// 00589 // Function: RenderEffects::finalize 00590 // Access: Public, Virtual 00591 // Description: Called by the BamReader to perform any final actions 00592 // needed for setting up the object after all objects 00593 // have been read and all pointers have been completed. 00594 //////////////////////////////////////////////////////////////////// 00595 void RenderEffects:: 00596 finalize() { 00597 // Unref the pointer that we explicitly reffed in make_from_bam(). 00598 unref(); 00599 00600 // We should never get back to zero after unreffing our own count, 00601 // because we expect to have been stored in a pointer somewhere. If 00602 // we do get to zero, it's a memory leak; the way to avoid this is 00603 // to call unref_delete() above instead of unref(), but this is 00604 // dangerous to do from within a virtual function. 00605 nassertv(get_ref_count() != 0); 00606 } 00607 00608 //////////////////////////////////////////////////////////////////// 00609 // Function: RenderEffects::make_from_bam 00610 // Access: Protected, Static 00611 // Description: This function is called by the BamReader's factory 00612 // when a new object of type RenderEffects is encountered 00613 // in the Bam file. It should create the RenderEffects 00614 // and extract its information from the file. 00615 //////////////////////////////////////////////////////////////////// 00616 TypedWritable *RenderEffects:: 00617 make_from_bam(const FactoryParams ¶ms) { 00618 RenderEffects *state = new RenderEffects; 00619 DatagramIterator scan; 00620 BamReader *manager; 00621 00622 parse_params(params, scan, manager); 00623 state->fillin(scan, manager); 00624 manager->register_change_this(change_this, state); 00625 00626 return state; 00627 } 00628 00629 //////////////////////////////////////////////////////////////////// 00630 // Function: RenderEffects::fillin 00631 // Access: Protected 00632 // Description: This internal function is called by make_from_bam to 00633 // read in all of the relevant data from the BamFile for 00634 // the new RenderEffects. 00635 //////////////////////////////////////////////////////////////////// 00636 void RenderEffects:: 00637 fillin(DatagramIterator &scan, BamReader *manager) { 00638 TypedWritable::fillin(scan, manager); 00639 00640 int num_effects = scan.get_uint16(); 00641 00642 // Push back a NULL pointer for each effect for now, until we get 00643 // the actual list of pointers later in complete_pointers(). 00644 _effects.reserve(num_effects); 00645 for (int i = 0; i < num_effects; i++) { 00646 manager->read_pointer(scan); 00647 _effects.push_back(Effect()); 00648 } 00649 }