Panda3D
|
00001 // Filename: clipPlaneAttrib.cxx 00002 // Created by: drose (11Jul02) 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 "clipPlaneAttrib.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 #include <iterator> 00025 00026 CPT(RenderAttrib) ClipPlaneAttrib::_empty_attrib; 00027 CPT(RenderAttrib) ClipPlaneAttrib::_all_off_attrib; 00028 TypeHandle ClipPlaneAttrib::_type_handle; 00029 int ClipPlaneAttrib::_attrib_slot; 00030 00031 // This STL Function object is used in filter_to_max(), below, to sort 00032 // a list of PlaneNodes in reverse order by priority. 00033 class ComparePlaneNodePriorities { 00034 public: 00035 bool operator ()(const NodePath &a, const NodePath &b) const { 00036 nassertr(!a.is_empty() && !b.is_empty(), a < b); 00037 PlaneNode *pa = DCAST(PlaneNode, a.node()); 00038 PlaneNode *pb = DCAST(PlaneNode, b.node()); 00039 nassertr(pa != (PlaneNode *)NULL && pb != (PlaneNode *)NULL, a < b); 00040 00041 return pa->get_priority() > pb->get_priority(); 00042 } 00043 }; 00044 00045 //////////////////////////////////////////////////////////////////// 00046 // Function: ClipPlaneAttrib::make 00047 // Access: Published, Static 00048 // Description: Constructs a new ClipPlaneAttrib object that enables (or 00049 // disables, according to op) the indicated plane(s). 00050 // 00051 // This method is now deprecated. Use add_on_plane() or 00052 // add_off_plane() instead. 00053 //////////////////////////////////////////////////////////////////// 00054 CPT(RenderAttrib) ClipPlaneAttrib:: 00055 make(ClipPlaneAttrib::Operation op, PlaneNode *plane) { 00056 pgraph_cat.warning() 00057 << "Using deprecated ClipPlaneAttrib interface.\n"; 00058 00059 CPT(RenderAttrib) attrib; 00060 00061 switch (op) { 00062 case O_set: 00063 attrib = make_all_off(); 00064 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane)); 00065 return attrib; 00066 00067 case O_add: 00068 attrib = make(); 00069 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane)); 00070 return attrib; 00071 00072 case O_remove: 00073 attrib = make(); 00074 attrib = DCAST(ClipPlaneAttrib, attrib)->add_off_plane(NodePath(plane)); 00075 return attrib; 00076 } 00077 00078 nassertr(false, make()); 00079 return make(); 00080 } 00081 00082 //////////////////////////////////////////////////////////////////// 00083 // Function: ClipPlaneAttrib::make 00084 // Access: Published, Static 00085 // Description: Constructs a new ClipPlaneAttrib object that turns on (or 00086 // off, according to op) the indicate plane(s). 00087 // 00088 // This method is now deprecated. Use add_on_plane() or 00089 // add_off_plane() instead. 00090 //////////////////////////////////////////////////////////////////// 00091 CPT(RenderAttrib) ClipPlaneAttrib:: 00092 make(ClipPlaneAttrib::Operation op, PlaneNode *plane1, PlaneNode *plane2) { 00093 pgraph_cat.warning() 00094 << "Using deprecated ClipPlaneAttrib interface.\n"; 00095 00096 CPT(RenderAttrib) attrib; 00097 00098 switch (op) { 00099 case O_set: 00100 attrib = make_all_off(); 00101 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane1)); 00102 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane2)); 00103 return attrib; 00104 00105 case O_add: 00106 attrib = make(); 00107 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane1)); 00108 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane2)); 00109 return attrib; 00110 00111 case O_remove: 00112 attrib = make(); 00113 attrib = DCAST(ClipPlaneAttrib, attrib)->add_off_plane(NodePath(plane1)); 00114 attrib = DCAST(ClipPlaneAttrib, attrib)->add_off_plane(NodePath(plane2)); 00115 return attrib; 00116 } 00117 00118 nassertr(false, make()); 00119 return make(); 00120 } 00121 00122 //////////////////////////////////////////////////////////////////// 00123 // Function: ClipPlaneAttrib::make 00124 // Access: Published, Static 00125 // Description: Constructs a new ClipPlaneAttrib object that turns on (or 00126 // off, according to op) the indicate plane(s). 00127 // 00128 // This method is now deprecated. Use add_on_plane() or 00129 // add_off_plane() instead. 00130 //////////////////////////////////////////////////////////////////// 00131 CPT(RenderAttrib) ClipPlaneAttrib:: 00132 make(ClipPlaneAttrib::Operation op, PlaneNode *plane1, PlaneNode *plane2, 00133 PlaneNode *plane3) { 00134 pgraph_cat.warning() 00135 << "Using deprecated ClipPlaneAttrib interface.\n"; 00136 00137 CPT(RenderAttrib) attrib; 00138 00139 switch (op) { 00140 case O_set: 00141 attrib = make_all_off(); 00142 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane1)); 00143 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane2)); 00144 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane3)); 00145 return attrib; 00146 00147 case O_add: 00148 attrib = make(); 00149 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane1)); 00150 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane2)); 00151 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane3)); 00152 return attrib; 00153 00154 case O_remove: 00155 attrib = make(); 00156 attrib = DCAST(ClipPlaneAttrib, attrib)->add_off_plane(NodePath(plane1)); 00157 attrib = DCAST(ClipPlaneAttrib, attrib)->add_off_plane(NodePath(plane2)); 00158 attrib = DCAST(ClipPlaneAttrib, attrib)->add_off_plane(NodePath(plane3)); 00159 return attrib; 00160 } 00161 00162 nassertr(false, make()); 00163 return make(); 00164 } 00165 00166 //////////////////////////////////////////////////////////////////// 00167 // Function: ClipPlaneAttrib::make 00168 // Access: Published, Static 00169 // Description: Constructs a new ClipPlaneAttrib object that turns on (or 00170 // off, according to op) the indicate plane(s). 00171 // 00172 // This method is now deprecated. Use add_on_plane() or 00173 // add_off_plane() instead. 00174 //////////////////////////////////////////////////////////////////// 00175 CPT(RenderAttrib) ClipPlaneAttrib:: 00176 make(ClipPlaneAttrib::Operation op, PlaneNode *plane1, PlaneNode *plane2, 00177 PlaneNode *plane3, PlaneNode *plane4) { 00178 pgraph_cat.warning() 00179 << "Using deprecated ClipPlaneAttrib interface.\n"; 00180 00181 CPT(RenderAttrib) attrib; 00182 00183 switch (op) { 00184 case O_set: 00185 attrib = make_all_off(); 00186 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane1)); 00187 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane2)); 00188 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane3)); 00189 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane4)); 00190 return attrib; 00191 00192 case O_add: 00193 attrib = make(); 00194 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane1)); 00195 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane2)); 00196 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane3)); 00197 attrib = DCAST(ClipPlaneAttrib, attrib)->add_on_plane(NodePath(plane4)); 00198 return attrib; 00199 00200 case O_remove: 00201 attrib = make(); 00202 attrib = DCAST(ClipPlaneAttrib, attrib)->add_off_plane(NodePath(plane1)); 00203 attrib = DCAST(ClipPlaneAttrib, attrib)->add_off_plane(NodePath(plane2)); 00204 attrib = DCAST(ClipPlaneAttrib, attrib)->add_off_plane(NodePath(plane3)); 00205 attrib = DCAST(ClipPlaneAttrib, attrib)->add_off_plane(NodePath(plane4)); 00206 return attrib; 00207 } 00208 00209 nassertr(false, make()); 00210 return make(); 00211 } 00212 00213 //////////////////////////////////////////////////////////////////// 00214 // Function: ClipPlaneAttrib::make_default 00215 // Access: Published, Static 00216 // Description: Returns a RenderAttrib that corresponds to whatever 00217 // the standard default properties for render attributes 00218 // of this type ought to be. 00219 //////////////////////////////////////////////////////////////////// 00220 CPT(RenderAttrib) ClipPlaneAttrib:: 00221 make_default() { 00222 return return_new(new ClipPlaneAttrib); 00223 } 00224 00225 //////////////////////////////////////////////////////////////////// 00226 // Function: ClipPlaneAttrib::get_operation 00227 // Access: Published 00228 // Description: Returns the basic operation type of the ClipPlaneAttrib. 00229 // If this is O_set, the planes listed here completely 00230 // replace any planes that were already on. If this is 00231 // O_add, the planes here are added to the set of of 00232 // planes that were already on, and if O_remove, the 00233 // planes here are removed from the set of planes that 00234 // were on. 00235 // 00236 // This method is now deprecated. ClipPlaneAttribs 00237 // nowadays have a separate list of on_planes and 00238 // off_planes, so this method doesn't make sense. Query 00239 // the lists independently. 00240 //////////////////////////////////////////////////////////////////// 00241 ClipPlaneAttrib::Operation ClipPlaneAttrib:: 00242 get_operation() const { 00243 pgraph_cat.warning() 00244 << "Using deprecated ClipPlaneAttrib interface.\n"; 00245 00246 if (has_all_off()) { 00247 return O_set; 00248 00249 } else if (get_num_off_planes() == 0) { 00250 return O_add; 00251 00252 } else { 00253 return O_remove; 00254 } 00255 } 00256 00257 //////////////////////////////////////////////////////////////////// 00258 // Function: ClipPlaneAttrib::get_num_planes 00259 // Access: Published 00260 // Description: Returns the number of planes listed in the attribute. 00261 // 00262 // This method is now deprecated. ClipPlaneAttribs 00263 // nowadays have a separate list of on_planes and 00264 // off_planes, so this method doesn't make sense. Query 00265 // the lists independently. 00266 //////////////////////////////////////////////////////////////////// 00267 int ClipPlaneAttrib:: 00268 get_num_planes() const { 00269 pgraph_cat.warning() 00270 << "Using deprecated ClipPlaneAttrib interface.\n"; 00271 00272 if (get_num_off_planes() == 0) { 00273 return get_num_on_planes(); 00274 } else { 00275 return get_num_off_planes(); 00276 } 00277 } 00278 00279 //////////////////////////////////////////////////////////////////// 00280 // Function: ClipPlaneAttrib::get_plane 00281 // Access: Published 00282 // Description: Returns the nth plane listed in the attribute. 00283 // 00284 // This method is now deprecated. ClipPlaneAttribs 00285 // nowadays have a separate list of on_planes and 00286 // off_planes, so this method doesn't make sense. Query 00287 // the lists independently. 00288 //////////////////////////////////////////////////////////////////// 00289 PlaneNode *ClipPlaneAttrib:: 00290 get_plane(int n) const { 00291 pgraph_cat.warning() 00292 << "Using deprecated ClipPlaneAttrib interface.\n"; 00293 00294 if (get_num_off_planes() == 0) { 00295 return DCAST(PlaneNode, get_on_plane(n).node()); 00296 } else { 00297 return DCAST(PlaneNode, get_off_plane(n).node()); 00298 } 00299 } 00300 00301 //////////////////////////////////////////////////////////////////// 00302 // Function: ClipPlaneAttrib::has_plane 00303 // Access: Published 00304 // Description: Returns true if the indicated plane is listed in the 00305 // attrib, false otherwise. 00306 // 00307 // This method is now deprecated. ClipPlaneAttribs 00308 // nowadays have a separate list of on_planes and 00309 // off_planes, so this method doesn't make sense. Query 00310 // the lists independently. 00311 //////////////////////////////////////////////////////////////////// 00312 bool ClipPlaneAttrib:: 00313 has_plane(PlaneNode *plane) const { 00314 pgraph_cat.warning() 00315 << "Using deprecated ClipPlaneAttrib interface.\n"; 00316 00317 if (get_num_off_planes() == 0) { 00318 return has_on_plane(NodePath(plane)); 00319 } else { 00320 return has_off_plane(NodePath(plane)); 00321 } 00322 } 00323 00324 //////////////////////////////////////////////////////////////////// 00325 // Function: ClipPlaneAttrib::add_plane 00326 // Access: Published 00327 // Description: Returns a new ClipPlaneAttrib, just like this one, but 00328 // with the indicated plane added to the list of planes. 00329 // 00330 // This method is now deprecated. Use add_on_plane() or 00331 // add_off_plane() instead. 00332 //////////////////////////////////////////////////////////////////// 00333 CPT(RenderAttrib) ClipPlaneAttrib:: 00334 add_plane(PlaneNode *plane) const { 00335 pgraph_cat.warning() 00336 << "Using deprecated ClipPlaneAttrib interface.\n"; 00337 00338 if (get_num_off_planes() == 0) { 00339 return add_on_plane(NodePath(plane)); 00340 } else { 00341 return add_off_plane(NodePath(plane)); 00342 } 00343 } 00344 00345 //////////////////////////////////////////////////////////////////// 00346 // Function: ClipPlaneAttrib::remove_plane 00347 // Access: Published 00348 // Description: Returns a new ClipPlaneAttrib, just like this one, but 00349 // with the indicated plane removed from the list of 00350 // planes. 00351 // 00352 // This method is now deprecated. Use remove_on_plane() 00353 // or remove_off_plane() instead. 00354 //////////////////////////////////////////////////////////////////// 00355 CPT(RenderAttrib) ClipPlaneAttrib:: 00356 remove_plane(PlaneNode *plane) const { 00357 pgraph_cat.warning() 00358 << "Using deprecated ClipPlaneAttrib interface.\n"; 00359 00360 if (get_num_off_planes() == 0) { 00361 return remove_on_plane(NodePath(plane)); 00362 } else { 00363 return remove_off_plane(NodePath(plane)); 00364 } 00365 } 00366 00367 //////////////////////////////////////////////////////////////////// 00368 // Function: ClipPlaneAttrib::make 00369 // Access: Published, Static 00370 // Description: Constructs a new ClipPlaneAttrib object that does 00371 // nothing. 00372 //////////////////////////////////////////////////////////////////// 00373 CPT(RenderAttrib) ClipPlaneAttrib:: 00374 make() { 00375 // We make it a special case and store a pointer to the empty attrib 00376 // forever once we find it the first time, as an optimization. 00377 if (_empty_attrib == (RenderAttrib *)NULL) { 00378 _empty_attrib = return_new(new ClipPlaneAttrib); 00379 } 00380 00381 return _empty_attrib; 00382 } 00383 00384 //////////////////////////////////////////////////////////////////// 00385 // Function: ClipPlaneAttrib::make_all_off 00386 // Access: Published, Static 00387 // Description: Constructs a new ClipPlaneAttrib object that disables 00388 // all planes (and hence disables clipping). 00389 //////////////////////////////////////////////////////////////////// 00390 CPT(RenderAttrib) ClipPlaneAttrib:: 00391 make_all_off() { 00392 // We make it a special case and store a pointer to the off attrib 00393 // forever once we find it the first time, as an optimization. 00394 if (_all_off_attrib == (RenderAttrib *)NULL) { 00395 ClipPlaneAttrib *attrib = new ClipPlaneAttrib; 00396 attrib->_off_all_planes = true; 00397 _all_off_attrib = return_new(attrib); 00398 } 00399 00400 return _all_off_attrib; 00401 } 00402 00403 //////////////////////////////////////////////////////////////////// 00404 // Function: ClipPlaneAttrib::add_on_plane 00405 // Access: Published 00406 // Description: Returns a new ClipPlaneAttrib, just like this one, but 00407 // with the indicated plane added to the list of planes 00408 // enabled by this attrib. 00409 //////////////////////////////////////////////////////////////////// 00410 CPT(RenderAttrib) ClipPlaneAttrib:: 00411 add_on_plane(const NodePath &plane) const { 00412 nassertr(!plane.is_empty() && plane.node()->is_of_type(PlaneNode::get_class_type()), this); 00413 ClipPlaneAttrib *attrib = new ClipPlaneAttrib(*this); 00414 attrib->_on_planes.insert(plane); 00415 attrib->_off_planes.erase(plane); 00416 00417 pair<Planes::iterator, bool> insert_result = 00418 attrib->_on_planes.insert(Planes::value_type(plane)); 00419 if (insert_result.second) { 00420 // Also ensure it is removed from the off_planes list. 00421 attrib->_off_planes.erase(plane); 00422 } 00423 00424 return return_new(attrib); 00425 } 00426 00427 //////////////////////////////////////////////////////////////////// 00428 // Function: ClipPlaneAttrib::remove_on_plane 00429 // Access: Published 00430 // Description: Returns a new ClipPlaneAttrib, just like this one, but 00431 // with the indicated plane removed from the list of 00432 // planes enabled by this attrib. 00433 //////////////////////////////////////////////////////////////////// 00434 CPT(RenderAttrib) ClipPlaneAttrib:: 00435 remove_on_plane(const NodePath &plane) const { 00436 nassertr(!plane.is_empty() && plane.node()->is_of_type(PlaneNode::get_class_type()), this); 00437 ClipPlaneAttrib *attrib = new ClipPlaneAttrib(*this); 00438 attrib->_on_planes.erase(plane); 00439 return return_new(attrib); 00440 } 00441 00442 //////////////////////////////////////////////////////////////////// 00443 // Function: ClipPlaneAttrib::add_off_plane 00444 // Access: Published 00445 // Description: Returns a new ClipPlaneAttrib, just like this one, but 00446 // with the indicated plane added to the list of planes 00447 // disabled by this attrib. 00448 //////////////////////////////////////////////////////////////////// 00449 CPT(RenderAttrib) ClipPlaneAttrib:: 00450 add_off_plane(const NodePath &plane) const { 00451 nassertr(!plane.is_empty() && plane.node()->is_of_type(PlaneNode::get_class_type()), this); 00452 ClipPlaneAttrib *attrib = new ClipPlaneAttrib(*this); 00453 if (!_off_all_planes) { 00454 attrib->_off_planes.insert(plane); 00455 } 00456 attrib->_on_planes.erase(plane); 00457 return return_new(attrib); 00458 } 00459 00460 //////////////////////////////////////////////////////////////////// 00461 // Function: ClipPlaneAttrib::remove_off_plane 00462 // Access: Published 00463 // Description: Returns a new ClipPlaneAttrib, just like this one, but 00464 // with the indicated plane removed from the list of 00465 // planes disabled by this attrib. 00466 //////////////////////////////////////////////////////////////////// 00467 CPT(RenderAttrib) ClipPlaneAttrib:: 00468 remove_off_plane(const NodePath &plane) const { 00469 nassertr(!plane.is_empty() && plane.node()->is_of_type(PlaneNode::get_class_type()), this); 00470 ClipPlaneAttrib *attrib = new ClipPlaneAttrib(*this); 00471 attrib->_off_planes.erase(plane); 00472 return return_new(attrib); 00473 } 00474 00475 //////////////////////////////////////////////////////////////////// 00476 // Function: ClipPlaneAttrib::filter_to_max 00477 // Access: Public 00478 // Description: Returns a new ClipPlaneAttrib, very much like this one, 00479 // but with the number of on_planes reduced to be no 00480 // more than max_clip_planes. The number of off_planes in 00481 // the new ClipPlaneAttrib is undefined. 00482 //////////////////////////////////////////////////////////////////// 00483 CPT(ClipPlaneAttrib) ClipPlaneAttrib:: 00484 filter_to_max(int max_clip_planes) const { 00485 if (max_clip_planes < 0 || (int)_on_planes.size() <= max_clip_planes) { 00486 // Trivial case: this ClipPlaneAttrib qualifies. 00487 return this; 00488 } 00489 00490 // Since check_filtered() will clear the _filtered list if we are out 00491 // of date, we should call it first. 00492 check_filtered(); 00493 00494 Filtered::const_iterator fi; 00495 fi = _filtered.find(max_clip_planes); 00496 if (fi != _filtered.end()) { 00497 // Easy case: we have already computed this for this particular 00498 // ClipPlaneAttrib. 00499 return (*fi).second; 00500 } 00501 00502 // Harder case: we have to compute it now. We must choose the n 00503 // planeNodes with the highest priority in our list of planeNodes. 00504 Planes priority_planes = _on_planes; 00505 00506 // This sort function uses the STL function object defined above. 00507 sort(priority_planes.begin(), priority_planes.end(), 00508 ComparePlaneNodePriorities()); 00509 00510 // Now lop off all of the planeNodes after the first max_clip_planes. 00511 priority_planes.erase(priority_planes.begin() + max_clip_planes, 00512 priority_planes.end()); 00513 00514 // And re-sort the ov_set into its proper order. 00515 priority_planes.sort(); 00516 00517 // Now create a new attrib reflecting these planeNodes. 00518 PT(ClipPlaneAttrib) attrib = new ClipPlaneAttrib; 00519 attrib->_on_planes.swap(priority_planes); 00520 00521 CPT(RenderAttrib) new_attrib = return_new(attrib); 00522 00523 // Finally, record this newly-created attrib in the map for next 00524 // time. 00525 CPT(ClipPlaneAttrib) planeNode_attrib = (const ClipPlaneAttrib *)new_attrib.p(); 00526 ((ClipPlaneAttrib *)this)->_filtered[max_clip_planes] = planeNode_attrib; 00527 return planeNode_attrib; 00528 } 00529 00530 //////////////////////////////////////////////////////////////////// 00531 // Function: ClipPlaneAttrib::compose_off 00532 // Access: Public 00533 // Description: This is a special method which composes two 00534 // ClipPlaneAttribs with regard only to their set of 00535 // "off" clip planes, for the purposes of deriving 00536 // PandaNode::get_off_clip_planes(). 00537 // 00538 // The result will be a ClipPlaneAttrib that represents 00539 // the union of all of the clip planes turned off in 00540 // either attrib. The set of on planes in the result is 00541 // undefined and should be ignored. 00542 //////////////////////////////////////////////////////////////////// 00543 CPT(RenderAttrib) ClipPlaneAttrib:: 00544 compose_off(const RenderAttrib *other) const { 00545 const ClipPlaneAttrib *ta; 00546 DCAST_INTO_R(ta, other, 0); 00547 00548 if (_off_all_planes || (!ta->_off_all_planes && ta->_off_planes.empty())) { 00549 // If we turn off all planes, or the other turns none off, the 00550 // result is the same as this one. 00551 return this; 00552 } 00553 00554 if (ta->_off_all_planes || _off_planes.empty()) { 00555 // And contrariwise. 00556 return ta; 00557 } 00558 00559 Planes::const_iterator ai = _off_planes.begin(); 00560 Planes::const_iterator bi = ta->_off_planes.begin(); 00561 00562 // Create a new ClipPlaneAttrib that will hold the result. 00563 ClipPlaneAttrib *new_attrib = new ClipPlaneAttrib; 00564 back_insert_iterator<Planes> result = 00565 back_inserter(new_attrib->_on_planes); 00566 00567 while (ai != _off_planes.end() && 00568 bi != ta->_off_planes.end()) { 00569 if ((*ai) < (*bi)) { 00570 // Here is a plane that we have in the original, which is not 00571 // present in the secondary. 00572 *result = *ai; 00573 ++ai; 00574 ++result; 00575 00576 } else if ((*bi) < (*ai)) { 00577 // Here is a new plane we have in the secondary, that was not 00578 // present in the original. 00579 *result = *bi; 00580 ++bi; 00581 ++result; 00582 00583 } else { // (*bi) == (*ai) 00584 // Here is a plane we have in both. 00585 *result = *bi; 00586 ++ai; 00587 ++bi; 00588 ++result; 00589 } 00590 } 00591 00592 while (ai != _off_planes.end()) { 00593 *result = *ai; 00594 ++ai; 00595 ++result; 00596 } 00597 00598 while (bi != ta->_off_planes.end()) { 00599 *result = *bi; 00600 ++bi; 00601 ++result; 00602 } 00603 00604 return return_new(new_attrib); 00605 } 00606 00607 //////////////////////////////////////////////////////////////////// 00608 // Function: ClipPlaneAttrib::output 00609 // Access: Public, Virtual 00610 // Description: 00611 //////////////////////////////////////////////////////////////////// 00612 void ClipPlaneAttrib:: 00613 output(ostream &out) const { 00614 out << get_type() << ":"; 00615 if (_off_planes.empty()) { 00616 if (_on_planes.empty()) { 00617 if (_off_all_planes) { 00618 out << "all off"; 00619 } else { 00620 out << "identity"; 00621 } 00622 } else { 00623 if (_off_all_planes) { 00624 out << "set"; 00625 } else { 00626 out << "on"; 00627 } 00628 } 00629 00630 } else { 00631 out << "off"; 00632 Planes::const_iterator fi; 00633 for (fi = _off_planes.begin(); fi != _off_planes.end(); ++fi) { 00634 NodePath plane = (*fi); 00635 out << " " << plane; 00636 } 00637 00638 if (!_on_planes.empty()) { 00639 out << " on"; 00640 } 00641 } 00642 00643 Planes::const_iterator li; 00644 for (li = _on_planes.begin(); li != _on_planes.end(); ++li) { 00645 NodePath plane = (*li); 00646 out << " " << plane; 00647 } 00648 } 00649 00650 //////////////////////////////////////////////////////////////////// 00651 // Function: ClipPlaneAttrib::compare_to_impl 00652 // Access: Protected, Virtual 00653 // Description: Intended to be overridden by derived ClipPlaneAttrib 00654 // types to return a unique number indicating whether 00655 // this ClipPlaneAttrib is equivalent to the other one. 00656 // 00657 // This should return 0 if the two ClipPlaneAttrib 00658 // objects are equivalent, a number less than zero if 00659 // this one should be sorted before the other one, and a 00660 // number greater than zero otherwise. 00661 // 00662 // This will only be called with two ClipPlaneAttrib 00663 // objects whose get_type() functions return the same. 00664 //////////////////////////////////////////////////////////////////// 00665 int ClipPlaneAttrib:: 00666 compare_to_impl(const RenderAttrib *other) const { 00667 const ClipPlaneAttrib *ta; 00668 DCAST_INTO_R(ta, other, 0); 00669 00670 if (_off_all_planes != ta->_off_all_planes) { 00671 return (int)_off_all_planes - (int)ta->_off_all_planes; 00672 } 00673 00674 Planes::const_iterator li = _on_planes.begin(); 00675 Planes::const_iterator oli = ta->_on_planes.begin(); 00676 00677 while (li != _on_planes.end() && oli != ta->_on_planes.end()) { 00678 NodePath plane = (*li); 00679 NodePath other_plane = (*oli); 00680 00681 int compare = plane.compare_to(other_plane); 00682 if (compare != 0) { 00683 return compare; 00684 } 00685 00686 ++li; 00687 ++oli; 00688 } 00689 00690 if (li != _on_planes.end()) { 00691 return 1; 00692 } 00693 if (oli != ta->_on_planes.end()) { 00694 return -1; 00695 } 00696 00697 Planes::const_iterator fi = _off_planes.begin(); 00698 Planes::const_iterator ofi = ta->_off_planes.begin(); 00699 00700 while (fi != _off_planes.end() && ofi != ta->_off_planes.end()) { 00701 NodePath plane = (*fi); 00702 NodePath other_plane = (*ofi); 00703 00704 int compare = plane.compare_to(other_plane); 00705 if (compare != 0) { 00706 return compare; 00707 } 00708 00709 ++fi; 00710 ++ofi; 00711 } 00712 00713 if (fi != _off_planes.end()) { 00714 return 1; 00715 } 00716 if (ofi != ta->_off_planes.end()) { 00717 return -1; 00718 } 00719 00720 return 0; 00721 } 00722 00723 //////////////////////////////////////////////////////////////////// 00724 // Function: ClipPlaneAttrib::get_hash_impl 00725 // Access: Protected, Virtual 00726 // Description: Intended to be overridden by derived RenderAttrib 00727 // types to return a unique hash for these particular 00728 // properties. RenderAttribs that compare the same with 00729 // compare_to_impl(), above, should return the same 00730 // hash; RenderAttribs that compare differently should 00731 // return a different hash. 00732 //////////////////////////////////////////////////////////////////// 00733 size_t ClipPlaneAttrib:: 00734 get_hash_impl() const { 00735 size_t hash = 0; 00736 00737 Planes::const_iterator li; 00738 for (li = _on_planes.begin(); li != _on_planes.end(); ++li) { 00739 NodePath plane = (*li); 00740 hash = plane.add_hash(hash); 00741 } 00742 00743 // This bool value goes here, between the two lists, to 00744 // differentiate between the two. 00745 hash = int_hash::add_hash(hash, (int)_off_all_planes); 00746 00747 for (li = _off_planes.begin(); li != _off_planes.end(); ++li) { 00748 NodePath plane = (*li); 00749 hash = plane.add_hash(hash); 00750 } 00751 00752 return hash; 00753 } 00754 00755 //////////////////////////////////////////////////////////////////// 00756 // Function: ClipPlaneAttrib::compose_impl 00757 // Access: Protected, Virtual 00758 // Description: Intended to be overridden by derived RenderAttrib 00759 // types to specify how two consecutive RenderAttrib 00760 // objects of the same type interact. 00761 // 00762 // This should return the result of applying the other 00763 // RenderAttrib to a node in the scene graph below this 00764 // RenderAttrib, which was already applied. In most 00765 // cases, the result is the same as the other 00766 // RenderAttrib (that is, a subsequent RenderAttrib 00767 // completely replaces the preceding one). On the other 00768 // hand, some kinds of RenderAttrib (for instance, 00769 // ColorTransformAttrib) might combine in meaningful 00770 // ways. 00771 //////////////////////////////////////////////////////////////////// 00772 CPT(RenderAttrib) ClipPlaneAttrib:: 00773 compose_impl(const RenderAttrib *other) const { 00774 const ClipPlaneAttrib *ta; 00775 DCAST_INTO_R(ta, other, 0); 00776 00777 if (ta->_off_all_planes) { 00778 // If the other type turns off all planes, it doesn't matter what 00779 // we are. 00780 return ta; 00781 } 00782 00783 // This is a three-way merge between ai, bi, and ci, except that bi 00784 // and ci should have no intersection and therefore needn't be 00785 // compared to each other. 00786 Planes::const_iterator ai = _on_planes.begin(); 00787 Planes::const_iterator bi = ta->_on_planes.begin(); 00788 Planes::const_iterator ci = ta->_off_planes.begin(); 00789 00790 // Create a new ClipPlaneAttrib that will hold the result. 00791 ClipPlaneAttrib *new_attrib = new ClipPlaneAttrib; 00792 back_insert_iterator<Planes> result = 00793 back_inserter(new_attrib->_on_planes); 00794 00795 while (ai != _on_planes.end() && 00796 bi != ta->_on_planes.end() && 00797 ci != ta->_off_planes.end()) { 00798 if ((*ai) < (*bi)) { 00799 if ((*ai) < (*ci)) { 00800 // Here is a plane that we have in the original, which is not 00801 // present in the secondary. 00802 *result = *ai; 00803 ++ai; 00804 ++result; 00805 00806 } else if ((*ci) < (*ai)) { 00807 // Here is a plane that is disabled in the secondary, but 00808 // was not present in the original. 00809 ++ci; 00810 00811 } else { // (*ci) == (*ai) 00812 // Here is a plane that is disabled in the secondary, and 00813 // was present in the original. 00814 ++ai; 00815 ++ci; 00816 } 00817 00818 } else if ((*bi) < (*ai)) { 00819 // Here is a new plane we have in the secondary, that was not 00820 // present in the original. 00821 *result = *bi; 00822 ++bi; 00823 ++result; 00824 00825 } else { // (*bi) == (*ai) 00826 // Here is a plane we have in both. 00827 *result = *bi; 00828 ++ai; 00829 ++bi; 00830 ++result; 00831 } 00832 } 00833 00834 while (ai != _on_planes.end() && bi != ta->_on_planes.end()) { 00835 if ((*ai) < (*bi)) { 00836 // Here is a plane that we have in the original, which is not 00837 // present in the secondary. 00838 *result = *ai; 00839 ++ai; 00840 ++result; 00841 00842 } else if ((*bi) < (*ai)) { 00843 // Here is a new plane we have in the secondary, that was not 00844 // present in the original. 00845 *result = *bi; 00846 ++bi; 00847 ++result; 00848 00849 } else { 00850 // Here is a plane we have in both. 00851 *result = *bi; 00852 ++ai; 00853 ++bi; 00854 ++result; 00855 } 00856 } 00857 00858 while (ai != _on_planes.end() && ci != ta->_off_planes.end()) { 00859 if ((*ai) < (*ci)) { 00860 // Here is a plane that we have in the original, which is not 00861 // present in the secondary. 00862 *result = *ai; 00863 ++ai; 00864 ++result; 00865 00866 } else if ((*ci) < (*ai)) { 00867 // Here is a plane that is disabled in the secondary, but 00868 // was not present in the original. 00869 ++ci; 00870 00871 } else { // (*ci) == (*ai) 00872 // Here is a plane that is disabled in the secondary, and 00873 // was present in the original. 00874 ++ai; 00875 ++ci; 00876 } 00877 } 00878 00879 while (ai != _on_planes.end()) { 00880 *result = *ai; 00881 ++ai; 00882 ++result; 00883 } 00884 00885 while (bi != ta->_on_planes.end()) { 00886 *result = *bi; 00887 ++bi; 00888 ++result; 00889 } 00890 00891 return return_new(new_attrib); 00892 } 00893 00894 //////////////////////////////////////////////////////////////////// 00895 // Function: ClipPlaneAttrib::invert_compose_impl 00896 // Access: Protected, Virtual 00897 // Description: Intended to be overridden by derived RenderAttrib 00898 // types to specify how two consecutive RenderAttrib 00899 // objects of the same type interact. 00900 // 00901 // See invert_compose() and compose_impl(). 00902 //////////////////////////////////////////////////////////////////// 00903 CPT(RenderAttrib) ClipPlaneAttrib:: 00904 invert_compose_impl(const RenderAttrib *other) const { 00905 // I think in this case the other attrib always wins. Maybe this 00906 // needs a bit more thought. It's hard to imagine that it's even 00907 // important to compute this properly. 00908 return other; 00909 } 00910 00911 //////////////////////////////////////////////////////////////////// 00912 // Function: ClipPlaneAttrib::get_auto_shader_attrib_impl 00913 // Access: Protected, Virtual 00914 // Description: 00915 //////////////////////////////////////////////////////////////////// 00916 CPT(RenderAttrib) ClipPlaneAttrib:: 00917 get_auto_shader_attrib_impl(const RenderState *state) const { 00918 return this; 00919 } 00920 00921 //////////////////////////////////////////////////////////////////// 00922 // Function: ClipPlaneAttrib::sort_on_planes 00923 // Access: Private 00924 // Description: This is patterned after 00925 // TextureAttrib::sort_on_stages(), but since planeNodes 00926 // don't actually require sorting, this only empties the 00927 // _filtered map. 00928 //////////////////////////////////////////////////////////////////// 00929 void ClipPlaneAttrib:: 00930 sort_on_planes() { 00931 _sort_seq = PlaneNode::get_sort_seq(); 00932 _filtered.clear(); 00933 } 00934 00935 //////////////////////////////////////////////////////////////////// 00936 // Function: ClipPlaneAttrib::register_with_read_factory 00937 // Access: Public, Static 00938 // Description: Tells the BamReader how to create objects of type 00939 // ClipPlaneAttrib. 00940 //////////////////////////////////////////////////////////////////// 00941 void ClipPlaneAttrib:: 00942 register_with_read_factory() { 00943 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 00944 } 00945 00946 //////////////////////////////////////////////////////////////////// 00947 // Function: ClipPlaneAttrib::write_datagram 00948 // Access: Public, Virtual 00949 // Description: Writes the contents of this object to the datagram 00950 // for shipping out to a Bam file. 00951 //////////////////////////////////////////////////////////////////// 00952 void ClipPlaneAttrib:: 00953 write_datagram(BamWriter *manager, Datagram &dg) { 00954 RenderAttrib::write_datagram(manager, dg); 00955 00956 dg.add_bool(_off_all_planes); 00957 00958 // write the number of off_planes 00959 dg.add_uint16(get_num_off_planes()); 00960 // write the off planes pointers if any 00961 Planes::const_iterator fi; 00962 for (fi = _off_planes.begin(); fi != _off_planes.end(); ++fi) { 00963 NodePath plane = (*fi); 00964 00965 // Since we can't write out a NodePath, we write out just the 00966 // plain PandaNode. The user can use the AttribNodeRegistry on 00967 // re-read if there is any ambiguity that needs to be resolved. 00968 manager->write_pointer(dg, plane.node()); 00969 } 00970 00971 // write the number of on planes 00972 dg.add_uint16(get_num_on_planes()); 00973 // write the on planes pointers if any 00974 Planes::const_iterator nti; 00975 for (nti = _on_planes.begin(); nti != _on_planes.end(); ++nti) { 00976 NodePath plane = (*nti); 00977 manager->write_pointer(dg, plane.node()); 00978 } 00979 } 00980 00981 //////////////////////////////////////////////////////////////////// 00982 // Function: ClipPlaneAttrib::complete_pointers 00983 // Access: Public, Virtual 00984 // Description: Receives an array of pointers, one for each time 00985 // manager->read_pointer() was called in fillin(). 00986 // Returns the number of pointers processed. 00987 //////////////////////////////////////////////////////////////////// 00988 int ClipPlaneAttrib:: 00989 complete_pointers(TypedWritable **p_list, BamReader *manager) { 00990 int pi = RenderAttrib::complete_pointers(p_list, manager); 00991 AttribNodeRegistry *areg = AttribNodeRegistry::get_global_ptr(); 00992 00993 Planes::iterator ci = _off_planes.begin(); 00994 while (ci != _off_planes.end()) { 00995 PandaNode *node; 00996 DCAST_INTO_R(node, p_list[pi++], pi); 00997 00998 // We go through some effort to look up the node in the registry 00999 // without creating a NodePath around it first (which would up, 01000 // and then down, the reference count, possibly deleting the 01001 // node). 01002 int ni = areg->find_node(node->get_type(), node->get_name()); 01003 if (ni != -1) { 01004 (*ci) = areg->get_node(ni); 01005 } else { 01006 (*ci) = NodePath(node); 01007 } 01008 ++ci; 01009 } 01010 _off_planes.sort(); 01011 01012 ci = _on_planes.begin(); 01013 while (ci != _on_planes.end()) { 01014 PandaNode *node; 01015 DCAST_INTO_R(node, p_list[pi++], pi); 01016 01017 int ni = areg->find_node(node->get_type(), node->get_name()); 01018 if (ni != -1) { 01019 (*ci) = areg->get_node(ni); 01020 } else { 01021 (*ci) = NodePath(node); 01022 } 01023 ++ci; 01024 } 01025 _on_planes.sort(); 01026 01027 return pi; 01028 } 01029 01030 //////////////////////////////////////////////////////////////////// 01031 // Function: ClipPlaneAttrib::require_fully_complete 01032 // Access: Public, Virtual 01033 // Description: Some objects require all of their nested pointers to 01034 // have been completed before the objects themselves can 01035 // be completed. If this is the case, override this 01036 // method to return true, and be careful with circular 01037 // references (which would make the object unreadable 01038 // from a bam file). 01039 //////////////////////////////////////////////////////////////////// 01040 bool ClipPlaneAttrib:: 01041 require_fully_complete() const { 01042 return true; 01043 } 01044 01045 //////////////////////////////////////////////////////////////////// 01046 // Function: ClipPlaneAttrib::make_from_bam 01047 // Access: Protected, Static 01048 // Description: This function is called by the BamReader's factory 01049 // when a new object of type ClipPlaneAttrib is encountered 01050 // in the Bam file. It should create the ClipPlaneAttrib 01051 // and extract its information from the file. 01052 //////////////////////////////////////////////////////////////////// 01053 TypedWritable *ClipPlaneAttrib:: 01054 make_from_bam(const FactoryParams ¶ms) { 01055 ClipPlaneAttrib *attrib = new ClipPlaneAttrib; 01056 DatagramIterator scan; 01057 BamReader *manager; 01058 01059 parse_params(params, scan, manager); 01060 attrib->fillin(scan, manager); 01061 01062 return attrib; 01063 } 01064 01065 //////////////////////////////////////////////////////////////////// 01066 // Function: ClipPlaneAttrib::fillin 01067 // Access: Protected 01068 // Description: This internal function is called by make_from_bam to 01069 // read in all of the relevant data from the BamFile for 01070 // the new ClipPlaneAttrib. 01071 //////////////////////////////////////////////////////////////////// 01072 void ClipPlaneAttrib:: 01073 fillin(DatagramIterator &scan, BamReader *manager) { 01074 RenderAttrib::fillin(scan, manager); 01075 01076 // We cheat a little bit here. In the middle of bam version 4.10, 01077 // we completely redefined the bam storage definition for 01078 // ClipPlaneAttribs, without bothering to up the bam version or even to 01079 // attempt to read the old definition. We get away with this, 01080 // knowing that the egg loader doesn't create ClipPlaneAttribs, and 01081 // hence no old bam files have the old definition for ClipPlaneAttrib 01082 // within them. 01083 01084 _off_all_planes = scan.get_bool(); 01085 01086 int num_off_planes = scan.get_uint16(); 01087 01088 // Push back an empty NodePath for each off Plane for now, until we 01089 // get the actual list of pointers later in complete_pointers(). 01090 _off_planes.reserve(num_off_planes); 01091 int i; 01092 for (i = 0; i < num_off_planes; i++) { 01093 manager->read_pointer(scan); 01094 _off_planes.push_back(NodePath()); 01095 } 01096 01097 int num_on_planes = scan.get_uint16(); 01098 _on_planes.reserve(num_on_planes); 01099 for (i = 0; i < num_on_planes; i++) { 01100 manager->read_pointer(scan); 01101 _on_planes.push_back(NodePath()); 01102 } 01103 }