43PStatCollector CollisionTraverser::_collisions_pcollector(
"App:Collisions");
45PStatCollector CollisionTraverser::_cnode_volume_pcollector(
"Collision Volumes:CollisionNode");
46PStatCollector CollisionTraverser::_gnode_volume_pcollector(
"Collision Volumes:GeomNode");
47PStatCollector CollisionTraverser::_geom_volume_pcollector(
"Collision Volumes:Geom");
52class SortByColliderSort {
54 SortByColliderSort(
const CollisionTraverser &trav) :
59 inline bool operator () (
int a,
int b)
const {
60 const CollisionTraverser::OrderedColliderDef &ocd_a = _trav._ordered_colliders[a];
61 const CollisionTraverser::OrderedColliderDef &ocd_b = _trav._ordered_colliders[b];
62 return ((
const CollisionNode *)ocd_a._node_path.
node())->get_collider_sort() < ((
const CollisionNode *)ocd_b._node_path.
node())->get_collider_sort();
65 const CollisionTraverser &_trav;
72CollisionTraverser(
const std::string &name) :
74 _this_pcollector(_collisions_pcollector, name)
76 _respect_prev_transform = respect_prev_transform;
77 #ifdef DO_COLLISION_RECORDING
86~CollisionTraverser() {
87 #ifdef DO_COLLISION_RECORDING
103 nassertv(_ordered_colliders.size() == _colliders.size());
105 nassertv(handler !=
nullptr);
107 Colliders::iterator ci = _colliders.find(collider);
108 if (ci != _colliders.end()) {
110 if ((*ci).second != handler) {
113 (*ci).second = handler;
116 Handlers::iterator hi = _handlers.find(old_handler);
117 nassertv(hi != _handlers.end());
119 nassertv((*hi).second >= 0);
120 if ((*hi).second == 0) {
124 hi = _handlers.find(handler);
125 if (hi == _handlers.end()) {
126 _handlers.insert(Handlers::value_type(handler, 1));
134 _colliders.insert(Colliders::value_type(collider, handler));
135 OrderedColliderDef ocdef;
136 ocdef._node_path = collider;
137 ocdef._in_graph =
true;
138 _ordered_colliders.push_back(ocdef);
140 Handlers::iterator hi = _handlers.find(handler);
141 if (hi == _handlers.end()) {
142 _handlers.insert(Handlers::value_type(handler, 1));
148 nassertv(_ordered_colliders.size() == _colliders.size());
159 nassertr(_ordered_colliders.size() == _colliders.size(),
false);
161 Colliders::iterator ci = _colliders.find(collider);
162 if (ci == _colliders.end()) {
170 Handlers::iterator hi = _handlers.find(handler);
171 nassertr(hi != _handlers.end(),
false);
173 nassertr((*hi).second >= 0,
false);
174 if ((*hi).second == 0) {
178 _colliders.erase(ci);
180 OrderedColliders::iterator oci;
181 oci = _ordered_colliders.begin();
182 while (oci != _ordered_colliders.end() &&
183 (*oci)._node_path != collider) {
187 nassertr(oci != _ordered_colliders.end(),
false);
188 _ordered_colliders.erase(oci);
190 nassertr(_ordered_colliders.size() == _colliders.size(),
false);
200 Colliders::const_iterator ci = _colliders.find(collider);
201 return (ci != _colliders.end());
210 nassertr(_ordered_colliders.size() == _colliders.size(), 0);
211 return _ordered_colliders.size();
220 nassertr(_ordered_colliders.size() == _colliders.size(), NodePath());
221 nassertr(n >= 0 && n < (
int)_ordered_colliders.size(), NodePath());
222 return _ordered_colliders[n]._node_path;
232 Colliders::const_iterator ci = _colliders.find(collider);
233 if (ci != _colliders.end()) {
246 _ordered_colliders.clear();
260 #ifdef DO_COLLISION_RECORDING
261 if (has_recorder()) {
262 get_recorder()->begin_traversal();
266 Handlers::iterator hi;
267 for (hi = _handlers.begin(); hi != _handlers.end(); ++hi) {
268 if ((*hi).first->wants_all_potential_collidees()) {
269 (*hi).first->set_root(root);
271 (*hi).first->begin_group();
274 bool traversal_done =
false;
276 !allow_collider_multiple) {
279 LevelStatesSingle level_states;
280 prepare_colliders_single(level_states, root);
282 if (level_states.size() == 1 || !allow_collider_multiple) {
283 traversal_done =
true;
287 for (
size_t pass = 0; pass < level_states.size(); ++pass) {
289 PStatTimer pass_timer(get_pass_collector(pass));
291 r_traverse_single(level_states[pass], pass);
296 if (!traversal_done &&
299 LevelStatesDouble level_states;
300 prepare_colliders_double(level_states, root);
302 if (level_states.size() == 1) {
303 traversal_done =
true;
305 for (
size_t pass = 0; pass < level_states.size(); ++pass) {
307 PStatTimer pass_timer(get_pass_collector(pass));
309 r_traverse_double(level_states[pass], pass);
314 if (!traversal_done) {
316 LevelStatesQuad level_states;
317 prepare_colliders_quad(level_states, root);
319 traversal_done =
true;
321 for (
size_t pass = 0; pass < level_states.size(); ++pass) {
323 PStatTimer pass_timer(get_pass_collector(pass));
325 r_traverse_quad(level_states[pass], pass);
329 hi = _handlers.begin();
330 while (hi != _handlers.end()) {
331 if (!(*hi).first->end_group()) {
333 hi = remove_handler(hi);
339 #ifdef DO_COLLISION_RECORDING
340 if (has_recorder()) {
341 get_recorder()->end_traversal();
345 CollisionLevelStateBase::_node_volume_pcollector.flush_level();
346 _cnode_volume_pcollector.flush_level();
347 _gnode_volume_pcollector.flush_level();
348 _geom_volume_pcollector.flush_level();
357#if defined(DO_COLLISION_RECORDING) || !defined(CPPPARSER)
376#ifdef DO_COLLISION_RECORDING
377 if (recorder != _recorder) {
379 if (_recorder !=
nullptr) {
380 nassertv(_recorder->_trav ==
this);
381 _recorder->_trav =
nullptr;
384 _recorder = recorder;
387 if (_recorder !=
nullptr) {
388 nassertv(_recorder->_trav !=
this);
389 if (_recorder->_trav !=
nullptr) {
390 _recorder->_trav->clear_recorder();
392 nassertv(_recorder->_trav ==
nullptr);
393 _recorder->_trav =
this;
407#ifdef DO_COLLISION_RECORDING
409 CollisionVisualizer *viz =
new CollisionVisualizer(
"show_collisions");
423#ifdef DO_COLLISION_RECORDING
424 if (!_collision_visualizer_np.is_empty()) {
425 _collision_visualizer_np.remove_node();
436void CollisionTraverser::
437output(std::ostream &out)
const {
438 out <<
"CollisionTraverser, " << _colliders.size()
439 <<
" colliders and " << _handlers.size() <<
" handlers.\n";
445void CollisionTraverser::
446write(std::ostream &out,
int indent_level)
const {
448 <<
"CollisionTraverser, " << _colliders.size()
449 <<
" colliders and " << _handlers.size() <<
" handlers:\n";
451 OrderedColliders::const_iterator oci;
452 for (oci = _ordered_colliders.begin();
453 oci != _ordered_colliders.end();
455 NodePath cnode_path = (*oci)._node_path;
456 bool in_graph = (*oci)._in_graph;
458 Colliders::const_iterator ci;
459 ci = _colliders.find(cnode_path);
460 nassertv(ci != _colliders.end());
462 CollisionHandler *handler = (*ci).second;
463 nassertv(handler !=
nullptr);
465 indent(out, indent_level + 2)
468 out <<
" handled by " << handler->get_type() <<
"\n";
474 CollisionNode *cnode = DCAST(CollisionNode, cnode_path.
node());
476 int num_solids = cnode->get_num_solids();
477 for (
int i = 0; i < num_solids; ++i) {
478 cnode->get_solid(i)->write(out, indent_level + 4);
491void CollisionTraverser::
492prepare_colliders_single(CollisionTraverser::LevelStatesSingle &level_states,
494 int num_colliders = _colliders.size();
497 CollisionLevelStateSingle level_state(root);
502 level_state.reserve(min(num_colliders, max_colliders));
506 int *indirect = (
int *)alloca(
sizeof(
int) * num_colliders);
508 for (i = 0; i < num_colliders; ++i) {
511 std::sort(indirect, indirect + num_colliders, SortByColliderSort(*
this));
513 int num_remaining_colliders = num_colliders;
514 for (i = 0; i < num_colliders; ++i) {
515 OrderedColliderDef &ocd = _ordered_colliders[indirect[i]];
516 NodePath cnode_path = ocd._node_path;
522 <<
"Collider " << cnode_path
523 <<
" is not in scene graph. Ignoring.\n";
524 ocd._in_graph =
false;
528 ocd._in_graph =
true;
529 CollisionNode *cnode = DCAST(CollisionNode, cnode_path.
node());
533 def._node_path = cnode_path;
535 int num_solids = cnode->get_num_solids();
536 for (
int s = 0; s < num_solids; ++s) {
537 CPT(CollisionSolid) collider = cnode->get_solid(s);
538 def._collider = collider;
539 level_state.prepare_collider(def, root);
541 if (level_state.get_num_colliders() == max_colliders) {
543 level_states.push_back(level_state);
545 level_state.reserve(min(num_remaining_colliders, max_colliders));
550 --num_remaining_colliders;
551 nassertv(num_remaining_colliders >= 0);
554 if (level_state.get_num_colliders() != 0) {
555 level_states.push_back(level_state);
557 nassertv(num_remaining_colliders == 0);
563void CollisionTraverser::
564r_traverse_single(CollisionLevelStateSingle &level_state,
size_t pass) {
572 PandaNode *node = level_state.
node();
574 CollisionNode *cnode;
575 DCAST_INTO_V(cnode, node);
576 CPT(BoundingVolume) node_bv = cnode->
get_bounds();
577 const GeometricBoundingVolume *node_gbv =
nullptr;
578 if (node_bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
579 DCAST_INTO_V(node_gbv, node_bv);
582 CollisionEntry entry;
583 entry._into_node = cnode;
585 if (_respect_prev_transform) {
586 entry._flags |= CollisionEntry::F_respect_prev_transform;
589 int num_colliders = level_state.get_num_colliders();
590 for (
int c = 0; c < num_colliders; ++c) {
592 entry._from_node = level_state.get_collider_node(c);
594 if ((entry._from_node->get_from_collide_mask() &
599 entry._from_node_path = level_state.get_collider_node_path(c);
600 entry._from = level_state.get_collider(c);
602 compare_collider_to_node(
613 if (collide_cat.is_spam()) {
615 <<
"Reached " << *node <<
"\n";
620 DCAST_INTO_V(gnode, node);
621 CPT(BoundingVolume) node_bv = gnode->
get_bounds();
622 const GeometricBoundingVolume *node_gbv =
nullptr;
623 if (node_bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
624 DCAST_INTO_V(node_gbv, node_bv);
627 CollisionEntry entry;
628 entry._into_node = gnode;
630 if (_respect_prev_transform) {
631 entry._flags |= CollisionEntry::F_respect_prev_transform;
634 int num_colliders = level_state.get_num_colliders();
635 for (
int c = 0; c < num_colliders; ++c) {
637 entry._from_node = level_state.get_collider_node(c);
639 if ((entry._from_node->get_from_collide_mask() &
644 entry._from_node_path = level_state.get_collider_node_path(c);
645 entry._from = level_state.get_collider(c);
647 compare_collider_to_geom_node(
661 if (index >= 0 && index < node->get_num_children()) {
662 CollisionLevelStateSingle next_state(level_state, node->
get_child(index));
663 r_traverse_single(next_state, pass);
672 int index = DCAST(LODNode, node)->get_lowest_switch();
675 for (
int i = 0; i < num_children; ++i) {
676 CollisionLevelStateSingle next_state(level_state, children.
get_child(i));
678 next_state.set_include_mask(next_state.get_include_mask() &
681 r_traverse_single(next_state, pass);
688 for (
int i = 0; i < num_children; ++i) {
689 CollisionLevelStateSingle next_state(level_state, children.
get_child(i));
690 r_traverse_single(next_state, pass);
702void CollisionTraverser::
703prepare_colliders_double(CollisionTraverser::LevelStatesDouble &level_states,
705 int num_colliders = _colliders.size();
708 CollisionLevelStateDouble level_state(root);
713 level_state.
reserve(min(num_colliders, max_colliders));
717 int *indirect = (
int *)alloca(
sizeof(
int) * num_colliders);
719 for (i = 0; i < num_colliders; ++i) {
722 std::sort(indirect, indirect + num_colliders, SortByColliderSort(*
this));
724 int num_remaining_colliders = num_colliders;
725 for (i = 0; i < num_colliders; ++i) {
726 OrderedColliderDef &ocd = _ordered_colliders[indirect[i]];
727 NodePath cnode_path = ocd._node_path;
733 <<
"Collider " << cnode_path
734 <<
" is not in scene graph. Ignoring.\n";
735 ocd._in_graph =
false;
739 ocd._in_graph =
true;
740 CollisionNode *cnode = DCAST(CollisionNode, cnode_path.
node());
744 def._node_path = cnode_path;
746 int num_solids = cnode->get_num_solids();
747 for (
int s = 0; s < num_solids; ++s) {
748 CPT(CollisionSolid) collider = cnode->get_solid(s);
749 def._collider = collider;
752 if (level_state.get_num_colliders() == max_colliders) {
754 level_states.push_back(level_state);
756 level_state.
reserve(min(num_remaining_colliders, max_colliders));
761 --num_remaining_colliders;
762 nassertv(num_remaining_colliders >= 0);
765 if (level_state.get_num_colliders() != 0) {
766 level_states.push_back(level_state);
768 nassertv(num_remaining_colliders == 0);
774void CollisionTraverser::
775r_traverse_double(CollisionLevelStateDouble &level_state,
size_t pass) {
783 PandaNode *node = level_state.
node();
785 CollisionNode *cnode;
786 DCAST_INTO_V(cnode, node);
787 CPT(BoundingVolume) node_bv = cnode->
get_bounds();
788 const GeometricBoundingVolume *node_gbv =
nullptr;
789 if (node_bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
790 DCAST_INTO_V(node_gbv, node_bv);
793 CollisionEntry entry;
794 entry._into_node = cnode;
796 if (_respect_prev_transform) {
797 entry._flags |= CollisionEntry::F_respect_prev_transform;
800 int num_colliders = level_state.get_num_colliders();
801 for (
int c = 0; c < num_colliders; ++c) {
803 entry._from_node = level_state.get_collider_node(c);
805 if ((entry._from_node->get_from_collide_mask() &
810 entry._from_node_path = level_state.get_collider_node_path(c);
811 entry._from = level_state.get_collider(c);
813 compare_collider_to_node(
824 if (collide_cat.is_spam()) {
826 <<
"Reached " << *node <<
"\n";
831 DCAST_INTO_V(gnode, node);
832 CPT(BoundingVolume) node_bv = gnode->
get_bounds();
833 const GeometricBoundingVolume *node_gbv =
nullptr;
834 if (node_bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
835 DCAST_INTO_V(node_gbv, node_bv);
838 CollisionEntry entry;
839 entry._into_node = gnode;
841 if (_respect_prev_transform) {
842 entry._flags |= CollisionEntry::F_respect_prev_transform;
845 int num_colliders = level_state.get_num_colliders();
846 for (
int c = 0; c < num_colliders; ++c) {
848 entry._from_node = level_state.get_collider_node(c);
850 if ((entry._from_node->get_from_collide_mask() &
855 entry._from_node_path = level_state.get_collider_node_path(c);
856 entry._from = level_state.get_collider(c);
858 compare_collider_to_geom_node(
872 if (index >= 0 && index < node->get_num_children()) {
873 CollisionLevelStateDouble next_state(level_state, node->
get_child(index));
874 r_traverse_double(next_state, pass);
883 int index = DCAST(LODNode, node)->get_lowest_switch();
886 for (
int i = 0; i < num_children; ++i) {
887 CollisionLevelStateDouble next_state(level_state, children.
get_child(i));
889 next_state.set_include_mask(next_state.get_include_mask() &
892 r_traverse_double(next_state, pass);
899 for (
int i = 0; i < num_children; ++i) {
900 CollisionLevelStateDouble next_state(level_state, children.
get_child(i));
901 r_traverse_double(next_state, pass);
913void CollisionTraverser::
914prepare_colliders_quad(CollisionTraverser::LevelStatesQuad &level_states,
916 int num_colliders = _colliders.size();
919 CollisionLevelStateQuad level_state(root);
924 level_state.
reserve(min(num_colliders, max_colliders));
928 int *indirect = (
int *)alloca(
sizeof(
int) * num_colliders);
930 for (i = 0; i < num_colliders; ++i) {
933 std::sort(indirect, indirect + num_colliders, SortByColliderSort(*
this));
935 int num_remaining_colliders = num_colliders;
936 for (i = 0; i < num_colliders; ++i) {
937 OrderedColliderDef &ocd = _ordered_colliders[indirect[i]];
938 NodePath cnode_path = ocd._node_path;
944 <<
"Collider " << cnode_path
945 <<
" is not in scene graph. Ignoring.\n";
946 ocd._in_graph =
false;
950 ocd._in_graph =
true;
951 CollisionNode *cnode = DCAST(CollisionNode, cnode_path.
node());
955 def._node_path = cnode_path;
957 int num_solids = cnode->get_num_solids();
958 for (
int s = 0; s < num_solids; ++s) {
959 CPT(CollisionSolid) collider = cnode->get_solid(s);
960 def._collider = collider;
963 if (level_state.get_num_colliders() == max_colliders) {
965 level_states.push_back(level_state);
967 level_state.
reserve(min(num_remaining_colliders, max_colliders));
972 --num_remaining_colliders;
973 nassertv(num_remaining_colliders >= 0);
976 if (level_state.get_num_colliders() != 0) {
977 level_states.push_back(level_state);
979 nassertv(num_remaining_colliders == 0);
985void CollisionTraverser::
986r_traverse_quad(CollisionLevelStateQuad &level_state,
size_t pass) {
994 PandaNode *node = level_state.
node();
996 CollisionNode *cnode;
997 DCAST_INTO_V(cnode, node);
998 CPT(BoundingVolume) node_bv = cnode->
get_bounds();
999 const GeometricBoundingVolume *node_gbv =
nullptr;
1000 if (node_bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
1001 DCAST_INTO_V(node_gbv, node_bv);
1004 CollisionEntry entry;
1005 entry._into_node = cnode;
1007 if (_respect_prev_transform) {
1008 entry._flags |= CollisionEntry::F_respect_prev_transform;
1011 int num_colliders = level_state.get_num_colliders();
1012 for (
int c = 0; c < num_colliders; ++c) {
1014 entry._from_node = level_state.get_collider_node(c);
1016 if ((entry._from_node->get_from_collide_mask() &
1021 entry._from_node_path = level_state.get_collider_node_path(c);
1022 entry._from = level_state.get_collider(c);
1024 compare_collider_to_node(
1035 if (collide_cat.is_spam()) {
1037 <<
"Reached " << *node <<
"\n";
1042 DCAST_INTO_V(gnode, node);
1043 CPT(BoundingVolume) node_bv = gnode->
get_bounds();
1044 const GeometricBoundingVolume *node_gbv =
nullptr;
1045 if (node_bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
1046 DCAST_INTO_V(node_gbv, node_bv);
1049 CollisionEntry entry;
1050 entry._into_node = gnode;
1052 if (_respect_prev_transform) {
1053 entry._flags |= CollisionEntry::F_respect_prev_transform;
1056 int num_colliders = level_state.get_num_colliders();
1057 for (
int c = 0; c < num_colliders; ++c) {
1059 entry._from_node = level_state.get_collider_node(c);
1061 if ((entry._from_node->get_from_collide_mask() &
1066 entry._from_node_path = level_state.get_collider_node_path(c);
1067 entry._from = level_state.get_collider(c);
1069 compare_collider_to_geom_node(
1083 if (index >= 0 && index < node->get_num_children()) {
1084 CollisionLevelStateQuad next_state(level_state, node->
get_child(index));
1085 r_traverse_quad(next_state, pass);
1094 int index = DCAST(LODNode, node)->get_lowest_switch();
1097 for (
int i = 0; i < num_children; ++i) {
1098 CollisionLevelStateQuad next_state(level_state, children.
get_child(i));
1100 next_state.set_include_mask(next_state.get_include_mask() &
1103 r_traverse_quad(next_state, pass);
1110 for (
int i = 0; i < num_children; ++i) {
1111 CollisionLevelStateQuad next_state(level_state, children.
get_child(i));
1112 r_traverse_quad(next_state, pass);
1120void CollisionTraverser::
1125 bool within_node_bounds =
true;
1126 if (from_parent_gbv !=
nullptr &&
1127 into_node_gbv !=
nullptr) {
1128 within_node_bounds = (into_node_gbv->
contains(from_parent_gbv) != 0);
1129 _cnode_volume_pcollector.add_level(1);
1132 if (within_node_bounds) {
1135 CollisionNode *cnode;
1136 DCAST_INTO_V(cnode, entry._into_node);
1138 int num_solids = cnode->get_num_solids();
1139 if (collide_cat.is_spam()) {
1141 <<
"Colliding against CollisionNode " << entry._into_node
1142 <<
" which has " << num_solids <<
" collision solids.\n";
1149 if (num_solids == 1) {
1150 entry._into = cnode->_solids[0].get_read_pointer(current_thread);
1151 Colliders::const_iterator ci;
1153 nassertv(ci != _colliders.end());
1154 entry.test_intersection((*ci).second,
this);
1156 CollisionNode::Solids::const_iterator si;
1157 for (si = cnode->_solids.begin(); si != cnode->_solids.end(); ++si) {
1158 entry._into = (*si).get_read_pointer(current_thread);
1164 CPT(BoundingVolume) solid_bv = entry._into->get_bounds();
1165 const GeometricBoundingVolume *solid_gbv =
nullptr;
1166 if (solid_bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
1167 solid_gbv = (
const GeometricBoundingVolume *)solid_bv.p();
1170 compare_collider_to_solid(entry, from_node_gbv, solid_gbv);
1179void CollisionTraverser::
1184 bool within_node_bounds =
true;
1185 if (from_parent_gbv !=
nullptr &&
1186 into_node_gbv !=
nullptr) {
1187 within_node_bounds = (into_node_gbv->
contains(from_parent_gbv) != 0);
1188 _gnode_volume_pcollector.add_level(1);
1191 if (within_node_bounds) {
1193 DCAST_INTO_V(gnode, entry._into_node);
1195 for (
int s = 0; s < num_geoms; ++s) {
1196 entry._into =
nullptr;
1197 const Geom *geom = DCAST(Geom, gnode->get_geom(s));
1198 if (geom !=
nullptr) {
1199 CPT(BoundingVolume) geom_bv = geom->
get_bounds();
1200 const GeometricBoundingVolume *geom_gbv =
nullptr;
1201 if (num_geoms > 1 &&
1202 geom_bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
1208 DCAST_INTO_V(geom_gbv, geom_bv);
1211 compare_collider_to_geom(entry, geom, from_node_gbv, geom_gbv);
1220void CollisionTraverser::
1224 bool within_solid_bounds =
true;
1225 if (from_node_gbv !=
nullptr &&
1226 solid_gbv !=
nullptr) {
1227 within_solid_bounds = (solid_gbv->
contains(from_node_gbv) != 0);
1229 ((CollisionSolid *)entry.
get_into())->get_volume_pcollector().add_level(1);
1232 if (collide_cat.is_spam()) {
1233 collide_cat.spam(
false)
1234 <<
"Comparing to solid: " << *from_node_gbv
1235 <<
" to " << *solid_gbv <<
", within_solid_bounds = "
1236 << within_solid_bounds <<
"\n";
1240 if (within_solid_bounds) {
1241 Colliders::const_iterator ci;
1243 nassertv(ci != _colliders.end());
1244 entry.test_intersection((*ci).second,
this);
1251void CollisionTraverser::
1255 bool within_geom_bounds =
true;
1256 if (from_node_gbv !=
nullptr &&
1257 geom_gbv !=
nullptr) {
1258 within_geom_bounds = (geom_gbv->
contains(from_node_gbv) != 0);
1259 _geom_volume_pcollector.add_level(1);
1261 if (within_geom_bounds) {
1262 Colliders::const_iterator ci;
1264 nassertv(ci != _colliders.end());
1269 GeomVertexReader vertex(data, InternalName::get_vertex());
1271 int num_primitives = geom->get_num_primitives();
1272 for (
int i = 0; i < num_primitives; ++i) {
1273 const GeomPrimitive *primitive = geom->get_primitive(i);
1274 CPT(GeomPrimitive) tris = primitive->
decompose();
1275 nassertv(tris->is_of_type(GeomTriangles::get_class_type()));
1277 if (tris->is_indexed()) {
1279 GeomVertexReader index(tris->get_vertices(), 0);
1280 while (!index.is_at_end()) {
1283 vertex.set_row_unsafe(index.get_data1i());
1284 v[0] = vertex.get_data3();
1285 vertex.set_row_unsafe(index.get_data1i());
1286 v[1] = vertex.get_data3();
1287 vertex.set_row_unsafe(index.get_data1i());
1288 v[2] = vertex.get_data3();
1293 bool within_solid_bounds =
true;
1294 if (from_node_gbv !=
nullptr) {
1295 PT(BoundingSphere) sphere =
new BoundingSphere;
1296 sphere->around(v, v + 3);
1297 within_solid_bounds = (sphere->contains(from_node_gbv) != 0);
1299 CollisionGeom::_volume_pcollector.add_level(1);
1302 if (within_solid_bounds) {
1303 PT(CollisionGeom) cgeom =
new CollisionGeom(LVecBase3(v[0]), LVecBase3(v[1]), LVecBase3(v[2]));
1304 entry._into = cgeom;
1305 entry.test_intersection((*ci).second,
this);
1313 for (
int i = 0; i < num_vertices; i += 3) {
1316 v[0] = vertex.get_data3();
1317 v[1] = vertex.get_data3();
1318 v[2] = vertex.get_data3();
1323 bool within_solid_bounds =
true;
1324 if (from_node_gbv !=
nullptr) {
1325 PT(BoundingSphere) sphere =
new BoundingSphere;
1326 sphere->around(v, v + 3);
1327 within_solid_bounds = (sphere->contains(from_node_gbv) != 0);
1329 CollisionGeom::_volume_pcollector.add_level(1);
1332 if (within_solid_bounds) {
1333 PT(CollisionGeom) cgeom =
new CollisionGeom(LVecBase3(v[0]), LVecBase3(v[1]), LVecBase3(v[2]));
1334 entry._into = cgeom;
1335 entry.test_intersection((*ci).second,
this);
1354CollisionTraverser::Handlers::iterator CollisionTraverser::
1355remove_handler(CollisionTraverser::Handlers::iterator hi) {
1356 nassertr(hi != _handlers.end(), hi);
1358 CollisionHandler *handler = (*hi).first;
1359 Handlers::iterator hnext = hi;
1361 _handlers.erase(hi);
1365 Colliders::iterator ci;
1366 ci = _colliders.begin();
1367 while (ci != _colliders.end()) {
1368 if ((*ci).second == handler) {
1370 NodePath node_path = (*ci).first;
1372 Colliders::iterator cnext = ci;
1374 _colliders.erase(ci);
1378 OrderedColliders::iterator oci;
1379 oci = _ordered_colliders.begin();
1380 while (oci != _ordered_colliders.end() &&
1381 (*oci)._node_path != node_path) {
1384 nassertr(oci != _ordered_colliders.end(), hi);
1385 _ordered_colliders.erase(oci);
1387 nassertr(_ordered_colliders.size() == _colliders.size(), hi);
1402get_pass_collector(
int pass) {
1403 nassertr(pass >= 0, _this_pcollector);
1404 while ((
int)_pass_collectors.size() <= pass) {
1405 std::ostringstream name;
1406 name <<
"pass" << (_pass_collectors.size() + 1);
1407 PStatCollector col(_this_pcollector, name.str());
1408 _pass_collectors.push_back(col);
1409 PStatCollector sc_col(col,
"solid_collide");
1410 _solid_collide_collectors.push_back(sc_col);
1413 return _pass_collectors[pass];
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void flush_level()
Flushes the PStatCollectors used during traversal.
static void flush_level()
Flushes the PStatCollectors used during traversal.
Defines a single collision event.
get_into
Returns the CollisionSolid pointer for the particular solid was collided into.
get_from_node_path
Returns the NodePath that represents the CollisionNode that contains the CollisionSolid that triggere...
The abstract interface to a number of classes that decide what to do when a collision is detected.
void reserve(int num_colliders)
Indicates an intention to add the indicated number of colliders to the level state.
const GeometricBoundingVolume * get_parent_bound(int n) const
Returns the bounding volume of the indicated collider, transformed into the previous node's transform...
PandaNode * node() const
Returns the PandaNode pointer of the node we have traversed to.
const GeometricBoundingVolume * get_local_bound(int n) const
Returns the bounding volume of the indicated collider, transformed into the current node's transform ...
NodePath get_node_path() const
Returns the NodePath representing the node instance we have traversed to.
bool any_in_bounds()
Checks the bounding volume of the current node against each of our colliders.
bool has_collider(int n) const
Returns true if the nth collider in the LevelState is still part of the level.
void prepare_collider(const ColliderDef &def, const NodePath &root)
Adds the indicated Collider to the set of Colliders in the current level state.
bool apply_transform()
Applies the inverse transform from the current node, if any, onto all the colliders in the level stat...
static int get_max_colliders()
get_into_collide_mask
Returns the current "into" CollideMask.
static void flush_level()
Flushes the PStatCollectors used during traversal.
static bool verify_points(const LPoint3 *begin, const LPoint3 *end)
Verifies that the indicated set of points will define a valid CollisionPolygon: that is,...
static void flush_level()
Flushes the PStatCollectors used during traversal.
static void flush_level()
Flushes the PStatCollectors used during traversal.
CollisionHandler * get_handler(const NodePath &collider) const
Returns the handler that is currently assigned to serve the indicated collision node,...
get_collider
Returns the nth CollisionNode that has been added to the traverser via add_collider().
bool remove_collider(const NodePath &collider)
Removes the collider (and its associated handler) from the set of CollisionNodes that will be tested ...
bool has_collider(const NodePath &collider) const
Returns true if the indicated node is current in the set of nodes that will be tested each frame for ...
set_recorder
Uses the indicated CollisionRecorder object to start recording the intersection tests made by each su...
void clear_colliders()
Completely empties the set of collision nodes and their associated handlers.
CollisionVisualizer * show_collisions(const NodePath &root)
This is a high-level function to create a CollisionVisualizer object to render the collision tests pe...
void add_collider(const NodePath &collider, CollisionHandler *handler)
Adds a new CollisionNode, representing an object that will be tested for collisions into other object...
get_num_colliders
Returns the number of CollisionNodes that have been added to the traverser via add_collider().
void hide_collisions()
Undoes the effect of a previous call to show_collisions().
void traverse(const NodePath &root)
Perform the traversal.
get_num_geoms
Returns the number of geoms in the node.
get_default_collide_mask
Returns the default into_collide_mask assigned to new GeomNodes.
get_num_vertices
Returns the number of indices used by all the primitives in this object.
int get_first_vertex() const
Returns the first vertex number referenced by the primitive.
ConstPointerTo< GeomPrimitive > decompose() const
Decomposes a complex primitive type into a simpler primitive type, for instance triangle strips to tr...
A container for geometry primitives.
ConstPointerTo< GeomVertexData > get_animated_vertex_data(bool force, Thread *current_thread=Thread::get_current_thread()) const
Returns a GeomVertexData that represents the results of computing the vertex animation on the CPU for...
get_primitive_type
Returns the fundamental primitive type that is common to all GeomPrimitives added within the Geom.
ConstPointerTo< BoundingVolume > get_bounds(Thread *current_thread=Thread::get_current_thread()) const
Returns the bounding volume for the Geom.
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
int contains(const GeometricBoundingVolume *vol) const
Returns the appropriate set of IntersectionFlags to indicate the amount of intersection with the indi...
A base class for all things which can have a name.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
bool is_same_graph(const NodePath &other, Thread *current_thread=Thread::get_current_thread()) const
Returns true if the node represented by this NodePath is parented within the same graph as that of th...
bool is_empty() const
Returns true if the NodePath contains no nodes.
PandaNode * node() const
Returns the referenced node of the path.
NodePath attach_new_node(PandaNode *node, int sort=0, Thread *current_thread=Thread::get_current_thread()) const
Attaches a new node, with or without existing parents, to the scene graph below the referenced node o...
A lightweight class that represents a single element that may be timed and/or counted via stats.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
PandaNode * get_child(size_t n) const
Returns the nth child of the node.
size_t get_num_children() const
Returns the number of children of the node.
virtual bool is_geom_node() const
A simple downcast check.
virtual bool has_single_child_visibility() const
Should be overridden by derived classes to return true if this kind of node has the special property ...
virtual int get_visible_child() const
Returns the index number of the currently visible child of this node.
get_into_collide_mask
Returns the "into" collide mask for this node.
get_child
Returns the nth child node of this node.
ConstPointerTo< BoundingVolume > get_bounds(Thread *current_thread=Thread::get_current_thread()) const
Returns the external bounding volume of this node: a bounding volume that contains the user bounding ...
virtual bool is_lod_node() const
A simple downcast check.
virtual bool is_collision_node() const
A simple downcast check.
get_children
Returns an object that can be used to walk through the list of children of the node.
get_current_thread
Returns a pointer to the currently-executing Thread object.
TypeHandle is the identifier used to differentiate C++ class types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.