00001 // Filename: collisionHandlerQueue.cxx 00002 // Created by: drose (16Mar02) 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 "collisionHandlerQueue.h" 00016 #include "config_collide.h" 00017 #include "indent.h" 00018 00019 TypeHandle CollisionHandlerQueue::_type_handle; 00020 00021 // This class is used in sort_entries(), below. 00022 class CollisionEntrySorter { 00023 public: 00024 CollisionEntrySorter(CollisionEntry *entry) { 00025 _entry = entry; 00026 LVector3 vec = 00027 entry->get_surface_point(entry->get_from_node_path()) - 00028 entry->get_from()->get_collision_origin(); 00029 _dist2 = vec.length_squared(); 00030 } 00031 bool operator < (const CollisionEntrySorter &other) const { 00032 return _dist2 < other._dist2; 00033 } 00034 00035 CollisionEntry *_entry; 00036 PN_stdfloat _dist2; 00037 }; 00038 00039 //////////////////////////////////////////////////////////////////// 00040 // Function: CollisionHandlerQueue::Constructor 00041 // Access: Published 00042 // Description: 00043 //////////////////////////////////////////////////////////////////// 00044 CollisionHandlerQueue:: 00045 CollisionHandlerQueue() { 00046 } 00047 00048 //////////////////////////////////////////////////////////////////// 00049 // Function: CollisionHandlerQueue::begin_group 00050 // Access: Published, Virtual 00051 // Description: Will be called by the CollisionTraverser before a new 00052 // traversal is begun. It instructs the handler to 00053 // reset itself in preparation for a number of 00054 // CollisionEntries to be sent. 00055 //////////////////////////////////////////////////////////////////// 00056 void CollisionHandlerQueue:: 00057 begin_group() { 00058 _entries.clear(); 00059 } 00060 00061 //////////////////////////////////////////////////////////////////// 00062 // Function: CollisionHandlerQueue::add_entry 00063 // Access: Published, Virtual 00064 // Description: Called between a begin_group() .. end_group() 00065 // sequence for each collision that is detected. 00066 //////////////////////////////////////////////////////////////////// 00067 void CollisionHandlerQueue:: 00068 add_entry(CollisionEntry *entry) { 00069 nassertv(entry != (CollisionEntry *)NULL); 00070 _entries.push_back(entry); 00071 } 00072 00073 //////////////////////////////////////////////////////////////////// 00074 // Function: CollisionHandlerQueue::sort_entries 00075 // Access: Published 00076 // Description: Sorts all the detected collisions front-to-back by 00077 // from_intersection_point() so that those intersection 00078 // points closest to the collider's origin (e.g., the 00079 // center of the CollisionSphere, or the point_a of a 00080 // CollisionSegment) appear first. 00081 //////////////////////////////////////////////////////////////////// 00082 void CollisionHandlerQueue:: 00083 sort_entries() { 00084 // Build up a temporary vector of entries so we can sort the 00085 // pointers. This uses the class defined above. 00086 typedef pvector<CollisionEntrySorter> Sorter; 00087 Sorter sorter; 00088 sorter.reserve(_entries.size()); 00089 00090 Entries::const_iterator ei; 00091 for (ei = _entries.begin(); ei != _entries.end(); ++ei) { 00092 sorter.push_back(CollisionEntrySorter(*ei)); 00093 } 00094 00095 sort(sorter.begin(), sorter.end()); 00096 nassertv(sorter.size() == _entries.size()); 00097 00098 // Now that they're sorted, get them back. We do this in two steps, 00099 // building up a temporary vector first, so we don't accidentally 00100 // delete all the entries when the pointers go away. 00101 Entries sorted_entries; 00102 sorted_entries.reserve(sorter.size()); 00103 Sorter::const_iterator si; 00104 for (si = sorter.begin(); si != sorter.end(); ++si) { 00105 sorted_entries.push_back((*si)._entry); 00106 } 00107 00108 _entries.swap(sorted_entries); 00109 } 00110 00111 //////////////////////////////////////////////////////////////////// 00112 // Function: CollisionHandlerQueue::clear_entries 00113 // Access: Published 00114 // Description: Removes all the entries from the queue. 00115 //////////////////////////////////////////////////////////////////// 00116 void CollisionHandlerQueue:: 00117 clear_entries() { 00118 _entries.clear(); 00119 } 00120 00121 //////////////////////////////////////////////////////////////////// 00122 // Function: CollisionHandlerQueue::get_num_entries 00123 // Access: Published 00124 // Description: Returns the number of CollisionEntries detected last 00125 // pass. 00126 //////////////////////////////////////////////////////////////////// 00127 int CollisionHandlerQueue:: 00128 get_num_entries() const { 00129 return _entries.size(); 00130 } 00131 00132 //////////////////////////////////////////////////////////////////// 00133 // Function: CollisionHandlerQueue::get_entry 00134 // Access: Published 00135 // Description: Returns the nth CollisionEntry detected last pass. 00136 //////////////////////////////////////////////////////////////////// 00137 CollisionEntry *CollisionHandlerQueue:: 00138 get_entry(int n) const { 00139 nassertr(n >= 0 && n < (int)_entries.size(), NULL); 00140 return _entries[n]; 00141 } 00142 00143 //////////////////////////////////////////////////////////////////// 00144 // Function: CollisionHandlerQueue::output 00145 // Access: Published 00146 // Description: 00147 //////////////////////////////////////////////////////////////////// 00148 void CollisionHandlerQueue:: 00149 output(ostream &out) const { 00150 out << "CollisionHandlerQueue, " << _entries.size() << " entries"; 00151 } 00152 00153 //////////////////////////////////////////////////////////////////// 00154 // Function: CollisionHandlerQueue::write 00155 // Access: Published 00156 // Description: 00157 //////////////////////////////////////////////////////////////////// 00158 void CollisionHandlerQueue:: 00159 write(ostream &out, int indent_level) const { 00160 indent(out, indent_level) 00161 << "CollisionHandlerQueue, " << _entries.size() << " entries:\n"; 00162 00163 Entries::const_iterator ei; 00164 for (ei = _entries.begin(); ei != _entries.end(); ++ei) { 00165 (*ei)->write(out, indent_level + 2); 00166 } 00167 }