Panda3D
|
00001 // Filename: occluderEffect.cxx 00002 // Created by: drose (17Mar11) 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 "occluderEffect.h" 00016 #include "pandaNode.h" 00017 #include "graphicsStateGuardianBase.h" 00018 #include "bamReader.h" 00019 #include "bamWriter.h" 00020 #include "datagram.h" 00021 #include "datagramIterator.h" 00022 #include "config_pgraph.h" 00023 #include "attribNodeRegistry.h" 00024 00025 CPT(RenderEffect) OccluderEffect::_empty_effect; 00026 TypeHandle OccluderEffect::_type_handle; 00027 00028 //////////////////////////////////////////////////////////////////// 00029 // Function: OccluderEffect::make 00030 // Access: Published, Static 00031 // Description: Constructs a new OccluderEffect object that does 00032 // nothing. 00033 //////////////////////////////////////////////////////////////////// 00034 CPT(RenderEffect) OccluderEffect:: 00035 make() { 00036 // We make it a special case and store a pointer to the empty effect 00037 // forever once we find it the first time, as an optimization. 00038 if (_empty_effect == (RenderEffect *)NULL) { 00039 _empty_effect = return_new(new OccluderEffect); 00040 } 00041 00042 return _empty_effect; 00043 } 00044 00045 //////////////////////////////////////////////////////////////////// 00046 // Function: OccluderEffect::add_on_occluder 00047 // Access: Published 00048 // Description: Returns a new OccluderEffect, just like this one, but 00049 // with the indicated occluder added to the list of occluders 00050 // enabled by this effect. 00051 //////////////////////////////////////////////////////////////////// 00052 CPT(RenderEffect) OccluderEffect:: 00053 add_on_occluder(const NodePath &occluder) const { 00054 nassertr(!occluder.is_empty() && occluder.node()->is_of_type(OccluderNode::get_class_type()), this); 00055 OccluderEffect *effect = new OccluderEffect(*this); 00056 effect->_on_occluders.insert(occluder); 00057 00058 pair<Occluders::iterator, bool> insert_result = 00059 effect->_on_occluders.insert(Occluders::value_type(occluder)); 00060 00061 return return_new(effect); 00062 } 00063 00064 //////////////////////////////////////////////////////////////////// 00065 // Function: OccluderEffect::remove_on_occluder 00066 // Access: Published 00067 // Description: Returns a new OccluderEffect, just like this one, but 00068 // with the indicated occluder removed from the list of 00069 // occluders enabled by this effect. 00070 //////////////////////////////////////////////////////////////////// 00071 CPT(RenderEffect) OccluderEffect:: 00072 remove_on_occluder(const NodePath &occluder) const { 00073 nassertr(!occluder.is_empty() && occluder.node()->is_of_type(OccluderNode::get_class_type()), this); 00074 OccluderEffect *effect = new OccluderEffect(*this); 00075 effect->_on_occluders.erase(occluder); 00076 return return_new(effect); 00077 } 00078 00079 //////////////////////////////////////////////////////////////////// 00080 // Function: OccluderEffect::output 00081 // Access: Public, Virtual 00082 // Description: 00083 //////////////////////////////////////////////////////////////////// 00084 void OccluderEffect:: 00085 output(ostream &out) const { 00086 out << get_type() << ":"; 00087 if (_on_occluders.empty()) { 00088 out << "identity"; 00089 } else { 00090 out << "on"; 00091 00092 Occluders::const_iterator li; 00093 for (li = _on_occluders.begin(); li != _on_occluders.end(); ++li) { 00094 NodePath occluder = (*li); 00095 out << " " << occluder; 00096 } 00097 } 00098 } 00099 00100 //////////////////////////////////////////////////////////////////// 00101 // Function: OccluderEffect::compare_to_impl 00102 // Access: Protected, Virtual 00103 // Description: Intended to be overridden by derived OccluderEffect 00104 // types to return a unique number indicating whether 00105 // this OccluderEffect is equivalent to the other one. 00106 // 00107 // This should return 0 if the two OccluderEffect 00108 // objects are equivalent, a number less than zero if 00109 // this one should be sorted before the other one, and a 00110 // number greater than zero otherwise. 00111 // 00112 // This will only be called with two OccluderEffect 00113 // objects whose get_type() functions return the same. 00114 //////////////////////////////////////////////////////////////////// 00115 int OccluderEffect:: 00116 compare_to_impl(const RenderEffect *other) const { 00117 const OccluderEffect *ta; 00118 DCAST_INTO_R(ta, other, 0); 00119 00120 Occluders::const_iterator li = _on_occluders.begin(); 00121 Occluders::const_iterator oli = ta->_on_occluders.begin(); 00122 00123 while (li != _on_occluders.end() && oli != ta->_on_occluders.end()) { 00124 NodePath occluder = (*li); 00125 NodePath other_occluder = (*oli); 00126 00127 int compare = occluder.compare_to(other_occluder); 00128 if (compare != 0) { 00129 return compare; 00130 } 00131 00132 ++li; 00133 ++oli; 00134 } 00135 00136 if (li != _on_occluders.end()) { 00137 return 1; 00138 } 00139 if (oli != ta->_on_occluders.end()) { 00140 return -1; 00141 } 00142 00143 return 0; 00144 } 00145 00146 //////////////////////////////////////////////////////////////////// 00147 // Function: OccluderEffect::register_with_read_factory 00148 // Access: Public, Static 00149 // Description: Tells the BamReader how to create objects of type 00150 // OccluderEffect. 00151 //////////////////////////////////////////////////////////////////// 00152 void OccluderEffect:: 00153 register_with_read_factory() { 00154 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 00155 } 00156 00157 //////////////////////////////////////////////////////////////////// 00158 // Function: OccluderEffect::write_datagram 00159 // Access: Public, Virtual 00160 // Description: Writes the contents of this object to the datagram 00161 // for shipping out to a Bam file. 00162 //////////////////////////////////////////////////////////////////// 00163 void OccluderEffect:: 00164 write_datagram(BamWriter *manager, Datagram &dg) { 00165 RenderEffect::write_datagram(manager, dg); 00166 00167 // write the number of on occluders 00168 dg.add_uint16(get_num_on_occluders()); 00169 // write the on occluders pointers if any 00170 Occluders::const_iterator nti; 00171 for (nti = _on_occluders.begin(); nti != _on_occluders.end(); ++nti) { 00172 NodePath occluder = (*nti); 00173 manager->write_pointer(dg, occluder.node()); 00174 } 00175 } 00176 00177 //////////////////////////////////////////////////////////////////// 00178 // Function: OccluderEffect::complete_pointers 00179 // Access: Public, Virtual 00180 // Description: Receives an array of pointers, one for each time 00181 // manager->read_pointer() was called in fillin(). 00182 // Returns the number of pointers processed. 00183 //////////////////////////////////////////////////////////////////// 00184 int OccluderEffect:: 00185 complete_pointers(TypedWritable **p_list, BamReader *manager) { 00186 int pi = RenderEffect::complete_pointers(p_list, manager); 00187 AttribNodeRegistry *areg = AttribNodeRegistry::get_global_ptr(); 00188 00189 Occluders::iterator ci; 00190 ci = _on_occluders.begin(); 00191 while (ci != _on_occluders.end()) { 00192 PandaNode *node; 00193 DCAST_INTO_R(node, p_list[pi++], pi); 00194 00195 int ni = areg->find_node(node->get_type(), node->get_name()); 00196 if (ni != -1) { 00197 (*ci) = areg->get_node(ni); 00198 } else { 00199 (*ci) = NodePath(node); 00200 } 00201 ++ci; 00202 } 00203 _on_occluders.sort(); 00204 00205 return pi; 00206 } 00207 00208 //////////////////////////////////////////////////////////////////// 00209 // Function: OccluderEffect::require_fully_complete 00210 // Access: Public, Virtual 00211 // Description: Some objects require all of their nested pointers to 00212 // have been completed before the objects themselves can 00213 // be completed. If this is the case, override this 00214 // method to return true, and be careful with circular 00215 // references (which would make the object unreadable 00216 // from a bam file). 00217 //////////////////////////////////////////////////////////////////// 00218 bool OccluderEffect:: 00219 require_fully_complete() const { 00220 return true; 00221 } 00222 00223 //////////////////////////////////////////////////////////////////// 00224 // Function: OccluderEffect::make_from_bam 00225 // Access: Protected, Static 00226 // Description: This function is called by the BamReader's factory 00227 // when a new object of type OccluderEffect is encountered 00228 // in the Bam file. It should create the OccluderEffect 00229 // and extract its information from the file. 00230 //////////////////////////////////////////////////////////////////// 00231 TypedWritable *OccluderEffect:: 00232 make_from_bam(const FactoryParams ¶ms) { 00233 OccluderEffect *effect = new OccluderEffect; 00234 DatagramIterator scan; 00235 BamReader *manager; 00236 00237 parse_params(params, scan, manager); 00238 effect->fillin(scan, manager); 00239 00240 return effect; 00241 } 00242 00243 //////////////////////////////////////////////////////////////////// 00244 // Function: OccluderEffect::fillin 00245 // Access: Protected 00246 // Description: This internal function is called by make_from_bam to 00247 // read in all of the relevant data from the BamFile for 00248 // the new OccluderEffect. 00249 //////////////////////////////////////////////////////////////////// 00250 void OccluderEffect:: 00251 fillin(DatagramIterator &scan, BamReader *manager) { 00252 RenderEffect::fillin(scan, manager); 00253 00254 // Push back an empty NodePath for each Occluder for now, until we 00255 // get the actual list of pointers later in complete_pointers(). 00256 int num_on_occluders = scan.get_uint16(); 00257 _on_occluders.reserve(num_on_occluders); 00258 for (int i = 0; i < num_on_occluders; i++) { 00259 manager->read_pointer(scan); 00260 _on_occluders.push_back(NodePath()); 00261 } 00262 }