renderEffect.cxx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. // Filename: renderEffect.cxx
  2. // Created by: drose (14Mar02)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
  8. //
  9. // All use of this software is subject to the terms of the Panda 3d
  10. // Software license. You should have received a copy of this license
  11. // along with this source code; you will also find a current copy of
  12. // the license at http://etc.cmu.edu/panda3d/docs/license/ .
  13. //
  14. // To contact the maintainers of this program write to
  15. // [email protected] .
  16. //
  17. ////////////////////////////////////////////////////////////////////
  18. #include "renderEffect.h"
  19. #include "bamReader.h"
  20. #include "indent.h"
  21. #include "config_pgraph.h"
  22. RenderEffect::Effects *RenderEffect::_effects = NULL;
  23. TypeHandle RenderEffect::_type_handle;
  24. ////////////////////////////////////////////////////////////////////
  25. // Function: RenderEffect::Constructor
  26. // Access: Protected
  27. // Description:
  28. ////////////////////////////////////////////////////////////////////
  29. RenderEffect::
  30. RenderEffect() {
  31. if (_effects == (Effects *)NULL) {
  32. // Make sure the global _effects map is allocated. This only has
  33. // to be done once. We could make this map static, but then we
  34. // run into problems if anyone creates a RenderState object at
  35. // static init time; it also seems to cause problems when the
  36. // Panda shared library is unloaded at application exit time.
  37. _effects = new Effects;
  38. }
  39. _saved_entry = _effects->end();
  40. }
  41. ////////////////////////////////////////////////////////////////////
  42. // Function: RenderEffect::Copy Constructor
  43. // Access: Private
  44. // Description: RenderEffects are not meant to be copied.
  45. ////////////////////////////////////////////////////////////////////
  46. RenderEffect::
  47. RenderEffect(const RenderEffect &) {
  48. nassertv(false);
  49. }
  50. ////////////////////////////////////////////////////////////////////
  51. // Function: RenderEffect::Copy Assignment Operator
  52. // Access: Private
  53. // Description: RenderEffects are not meant to be copied.
  54. ////////////////////////////////////////////////////////////////////
  55. void RenderEffect::
  56. operator = (const RenderEffect &) {
  57. nassertv(false);
  58. }
  59. ////////////////////////////////////////////////////////////////////
  60. // Function: RenderEffect::Destructor
  61. // Access: Public, Virtual
  62. // Description: The destructor is responsible for removing the
  63. // RenderEffect from the global set if it is there.
  64. ////////////////////////////////////////////////////////////////////
  65. RenderEffect::
  66. ~RenderEffect() {
  67. if (_saved_entry != _effects->end()) {
  68. // We cannot make this assertion, because the RenderEffect has
  69. // already partially destructed--this means we cannot look up the
  70. // object in the map. In fact, the map is temporarily invalid
  71. // until we finish destructing, since we screwed up the ordering
  72. // when we changed the return value of get_type().
  73. // nassertv(_effects->find(this) == _saved_entry);
  74. // Note: this isn't thread-safe, because once the derived class
  75. // destructor exits and before this destructor completes, the map
  76. // is invalid, and other threads may inadvertently attempt to read
  77. // the invalid map. To make it thread-safe, we need to move this
  78. // functionality to a separate method, that is to be called from
  79. // *each* derived class's destructor (and then we can put the
  80. // above assert back in).
  81. _effects->erase(_saved_entry);
  82. _saved_entry = _effects->end();
  83. }
  84. }
  85. ////////////////////////////////////////////////////////////////////
  86. // Function: RenderEffect::safe_to_transform
  87. // Access: Public, Virtual
  88. // Description: Returns true if it is generally safe to transform
  89. // this particular kind of RenderEffect by calling the
  90. // xform() method, false otherwise.
  91. ////////////////////////////////////////////////////////////////////
  92. bool RenderEffect::
  93. safe_to_transform() const {
  94. return true;
  95. }
  96. ////////////////////////////////////////////////////////////////////
  97. // Function: RenderEffect::safe_to_combine
  98. // Access: Public, Virtual
  99. // Description: Returns true if this kind of effect can safely be
  100. // combined with sibling nodes that share the exact same
  101. // effect, or false if this is not a good idea.
  102. ////////////////////////////////////////////////////////////////////
  103. bool RenderEffect::
  104. safe_to_combine() const {
  105. return true;
  106. }
  107. ////////////////////////////////////////////////////////////////////
  108. // Function: RenderEffect::xform
  109. // Access: Public, Virtual
  110. // Description: Returns a new RenderEffect transformed by the
  111. // indicated matrix.
  112. ////////////////////////////////////////////////////////////////////
  113. CPT(RenderEffect) RenderEffect::
  114. xform(const LMatrix4f &) const {
  115. return this;
  116. }
  117. ////////////////////////////////////////////////////////////////////
  118. // Function: RenderEffect::has_cull_callback
  119. // Access: Public, Virtual
  120. // Description: Should be overridden by derived classes to return
  121. // true if cull_callback() has been defined. Otherwise,
  122. // returns false to indicate cull_callback() does not
  123. // need to be called for this effect during the cull
  124. // traversal.
  125. ////////////////////////////////////////////////////////////////////
  126. bool RenderEffect::
  127. has_cull_callback() const {
  128. return false;
  129. }
  130. ////////////////////////////////////////////////////////////////////
  131. // Function: RenderEffect::cull_callback
  132. // Access: Public, Virtual
  133. // Description: If has_cull_callback() returns true, this function
  134. // will be called during the cull traversal to perform
  135. // any additional operations that should be performed at
  136. // cull time. This may include additional manipulation
  137. // of render state or additional visible/invisible
  138. // decisions, or any other arbitrary operation.
  139. //
  140. // At the time this function is called, the current
  141. // node's transform and state have not yet been applied
  142. // to the net_transform and net_state. This callback
  143. // may modify the node_transform and node_state to apply
  144. // an effective change to the render state at this
  145. // level.
  146. ////////////////////////////////////////////////////////////////////
  147. void RenderEffect::
  148. cull_callback(CullTraverser *, CullTraverserData &,
  149. CPT(TransformState) &, CPT(RenderState) &) const {
  150. }
  151. ////////////////////////////////////////////////////////////////////
  152. // Function: RenderEffect::has_net_transform
  153. // Access: Public, Virtual
  154. // Description: Should be overridden by derived classes to return
  155. // true if net_transform() has been defined, and
  156. // therefore the RenderEffect has some effect on the
  157. // node's apparent net transform.
  158. ////////////////////////////////////////////////////////////////////
  159. bool RenderEffect::
  160. has_net_transform() const {
  161. return false;
  162. }
  163. ////////////////////////////////////////////////////////////////////
  164. // Function: RenderEffect::net_transform
  165. // Access: Public, Virtual
  166. // Description: Given the node's parent's net transform, compute its
  167. // parent's new net transform after application of the
  168. // RenderEffect. Presumably this interposes some
  169. // special transform derived from the RenderEffect.
  170. // This may only be called if has_net_transform(),
  171. // above, has been defined to return true.
  172. ////////////////////////////////////////////////////////////////////
  173. CPT(TransformState) RenderEffect::
  174. net_transform(CPT(TransformState) &orig_net_transform) const {
  175. return orig_net_transform;
  176. }
  177. ////////////////////////////////////////////////////////////////////
  178. // Function: RenderEffect::output
  179. // Access: Published, Virtual
  180. // Description:
  181. ////////////////////////////////////////////////////////////////////
  182. void RenderEffect::
  183. output(ostream &out) const {
  184. out << get_type();
  185. }
  186. ////////////////////////////////////////////////////////////////////
  187. // Function: RenderEffect::write
  188. // Access: Published, Virtual
  189. // Description:
  190. ////////////////////////////////////////////////////////////////////
  191. void RenderEffect::
  192. write(ostream &out, int indent_level) const {
  193. indent(out, indent_level) << *this << "\n";
  194. }
  195. ////////////////////////////////////////////////////////////////////
  196. // Function: RenderEffect::get_num_effects
  197. // Access: Published, Static
  198. // Description: Returns the total number of unique RenderEffect
  199. // objects allocated in the world. This will go up and
  200. // down during normal operations.
  201. ////////////////////////////////////////////////////////////////////
  202. int RenderEffect::
  203. get_num_effects() {
  204. if (_effects == (Effects *)NULL) {
  205. return 0;
  206. }
  207. return _effects->size();
  208. }
  209. ////////////////////////////////////////////////////////////////////
  210. // Function: RenderEffect::list_effects
  211. // Access: Published, Static
  212. // Description: Lists all of the RenderEffects in the cache to the
  213. // output stream, one per line. This can be quite a lot
  214. // of output if the cache is large, so be prepared.
  215. ////////////////////////////////////////////////////////////////////
  216. void RenderEffect::
  217. list_effects(ostream &out) {
  218. out << _effects->size() << " effects:\n";
  219. Effects::const_iterator si;
  220. for (si = _effects->begin(); si != _effects->end(); ++si) {
  221. const RenderEffect *effect = (*si);
  222. effect->write(out, 2);
  223. }
  224. }
  225. ////////////////////////////////////////////////////////////////////
  226. // Function: RenderEffect::validate_effects
  227. // Access: Published, Static
  228. // Description: Ensures that the cache is still stored in sorted
  229. // order. Returns true if so, false if there is a
  230. // problem (which implies someone has modified one of
  231. // the supposedly-const RenderEffect objects).
  232. ////////////////////////////////////////////////////////////////////
  233. bool RenderEffect::
  234. validate_effects() {
  235. if (_effects->empty()) {
  236. return true;
  237. }
  238. Effects::const_iterator si = _effects->begin();
  239. Effects::const_iterator snext = si;
  240. ++snext;
  241. while (snext != _effects->end()) {
  242. if ((*si)->compare_to(*(*snext)) >= 0) {
  243. pgraph_cat.error()
  244. << "RenderEffects out of order!\n";
  245. (*si)->write(pgraph_cat.error(false), 2);
  246. (*snext)->write(pgraph_cat.error(false), 2);
  247. return false;
  248. }
  249. si = snext;
  250. ++snext;
  251. }
  252. return true;
  253. }
  254. ////////////////////////////////////////////////////////////////////
  255. // Function: RenderEffect::return_new
  256. // Access: Protected, Static
  257. // Description: This function is used by derived RenderEffect types
  258. // to share a common RenderEffect pointer for all
  259. // equivalent RenderEffect objects.
  260. //
  261. // The make() function of the derived type should create
  262. // a new RenderEffect and pass it through return_new(),
  263. // which will either save the pointer and return it
  264. // unchanged (if this is the first similar such object)
  265. // or delete it and return an equivalent pointer (if
  266. // there was already a similar object saved).
  267. ////////////////////////////////////////////////////////////////////
  268. CPT(RenderEffect) RenderEffect::
  269. return_new(RenderEffect *effect) {
  270. nassertr(effect != (RenderEffect *)NULL, effect);
  271. // This should be a newly allocated pointer, not one that was used
  272. // for anything else.
  273. nassertr(effect->_saved_entry == _effects->end(), effect);
  274. #ifndef NDEBUG
  275. if (paranoid_const) {
  276. nassertr(validate_effects(), effect);
  277. }
  278. #endif
  279. // Save the effect in a local PointerTo so that it will be freed at
  280. // the end of this function if no one else uses it.
  281. CPT(RenderEffect) pt_effect = effect;
  282. pair<Effects::iterator, bool> result = _effects->insert(effect);
  283. if (result.second) {
  284. // The effect was inserted; save the iterator and return the
  285. // input effect.
  286. effect->_saved_entry = result.first;
  287. return pt_effect;
  288. }
  289. // The effect was not inserted; there must be an equivalent one
  290. // already in the set. Return that one.
  291. return *(result.first);
  292. }
  293. ////////////////////////////////////////////////////////////////////
  294. // Function: RenderEffect::compare_to_impl
  295. // Access: Protected, Virtual
  296. // Description: Intended to be overridden by derived RenderEffect
  297. // types to return a unique number indicating whether
  298. // this RenderEffect is equivalent to the other one.
  299. //
  300. // This should return 0 if the two RenderEffect objects
  301. // are equivalent, a number less than zero if this one
  302. // should be sorted before the other one, and a number
  303. // greater than zero otherwise.
  304. //
  305. // This will only be called with two RenderEffect
  306. // objects whose get_type() functions return the same.
  307. ////////////////////////////////////////////////////////////////////
  308. int RenderEffect::
  309. compare_to_impl(const RenderEffect *other) const {
  310. return 0;
  311. }
  312. ////////////////////////////////////////////////////////////////////
  313. // Function: RenderEffect::write_datagram
  314. // Access: Public, Virtual
  315. // Description: Writes the contents of this object to the datagram
  316. // for shipping out to a Bam file.
  317. ////////////////////////////////////////////////////////////////////
  318. void RenderEffect::
  319. write_datagram(BamWriter *manager, Datagram &dg) {
  320. TypedWritable::write_datagram(manager, dg);
  321. }
  322. ////////////////////////////////////////////////////////////////////
  323. // Function: RenderEffect::change_this
  324. // Access: Public, Static
  325. // Description: Called immediately after complete_pointers(), this
  326. // gives the object a chance to adjust its own pointer
  327. // if desired. Most objects don't change pointers after
  328. // completion, but some need to.
  329. //
  330. // Once this function has been called, the old pointer
  331. // will no longer be accessed.
  332. ////////////////////////////////////////////////////////////////////
  333. TypedWritable *RenderEffect::
  334. change_this(TypedWritable *old_ptr, BamReader *manager) {
  335. // First, uniquify the pointer.
  336. RenderEffect *effect = DCAST(RenderEffect, old_ptr);
  337. CPT(RenderEffect) pointer = return_new(effect);
  338. // But now we have a problem, since we have to hold the reference
  339. // count and there's no way to return a TypedWritable while still
  340. // holding the reference count! We work around this by explicitly
  341. // upping the count, and also setting a finalize() callback to down
  342. // it later.
  343. if (pointer == effect) {
  344. pointer->ref();
  345. manager->register_finalize(effect);
  346. }
  347. // We have to cast the pointer back to non-const, because the bam
  348. // reader expects that.
  349. return (RenderEffect *)pointer.p();
  350. }
  351. ////////////////////////////////////////////////////////////////////
  352. // Function: RenderEffect::finalize
  353. // Access: Public, Virtual
  354. // Description: Method to ensure that any necessary clean up tasks
  355. // that have to be performed by this object are performed
  356. ////////////////////////////////////////////////////////////////////
  357. void RenderEffect::
  358. finalize() {
  359. // Unref the pointer that we explicitly reffed in make_from_bam().
  360. unref();
  361. // We should never get back to zero after unreffing our own count,
  362. // because we expect to have been stored in a pointer somewhere. If
  363. // we do get to zero, it's a memory leak; the way to avoid this is
  364. // to call unref_delete() above instead of unref(), but this is
  365. // dangerous to do from within a virtual function.
  366. nassertv(get_ref_count() != 0);
  367. }
  368. ////////////////////////////////////////////////////////////////////
  369. // Function: RenderEffect::fillin
  370. // Access: Protected
  371. // Description: This internal function is called by make_from_bam to
  372. // read in all of the relevant data from the BamFile for
  373. // the new RenderEffect.
  374. ////////////////////////////////////////////////////////////////////
  375. void RenderEffect::
  376. fillin(DatagramIterator &scan, BamReader *manager) {
  377. TypedWritable::fillin(scan, manager);
  378. }