collisionLevelState.cxx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // Filename: collisionLevelState.cxx
  2. // Created by: drose (16Mar02)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) 2001, 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://www.panda3d.org/license.txt .
  13. //
  14. // To contact the maintainers of this program write to
  15. // [email protected] .
  16. //
  17. ////////////////////////////////////////////////////////////////////
  18. #include "collisionLevelState.h"
  19. #include "collisionSolid.h"
  20. #include "dcast.h"
  21. ////////////////////////////////////////////////////////////////////
  22. // Function: CollisionLevelState::clear
  23. // Access: Public
  24. // Description:
  25. ////////////////////////////////////////////////////////////////////
  26. void CollisionLevelState::
  27. clear() {
  28. _colliders.clear();
  29. _local_bounds.clear();
  30. _parent_bounds.clear();
  31. _current = 0;
  32. _colliders_with_geom = 0;
  33. }
  34. ////////////////////////////////////////////////////////////////////
  35. // Function: CollisionLevelState::reserve
  36. // Access: Public
  37. // Description:
  38. ////////////////////////////////////////////////////////////////////
  39. void CollisionLevelState::
  40. reserve(int max_colliders) {
  41. _colliders.reserve(max_colliders);
  42. _local_bounds.reserve(max_colliders);
  43. }
  44. ////////////////////////////////////////////////////////////////////
  45. // Function: CollisionLevelState::prepare_collider
  46. // Access: Public
  47. // Description: Adds the indicated Collider to the set of Colliders
  48. // in the current level state.
  49. ////////////////////////////////////////////////////////////////////
  50. void CollisionLevelState::
  51. prepare_collider(const ColliderDef &def) {
  52. int index = (int)_colliders.size();
  53. _colliders.push_back(def);
  54. CollisionSolid *collider = def._collider;
  55. const BoundingVolume &bv = collider->get_bound();
  56. if (!bv.is_of_type(GeometricBoundingVolume::get_class_type())) {
  57. _local_bounds.push_back((GeometricBoundingVolume *)NULL);
  58. } else {
  59. GeometricBoundingVolume *gbv;
  60. DCAST_INTO_V(gbv, bv.make_copy());
  61. gbv->xform(def._space);
  62. _local_bounds.push_back(gbv);
  63. }
  64. _current |= get_mask(index);
  65. if (def._node->get_collide_geom()) {
  66. _colliders_with_geom |= get_mask(index);
  67. }
  68. _parent_bounds = _local_bounds;
  69. }
  70. ////////////////////////////////////////////////////////////////////
  71. // Function: CollisionLevelState::any_in_bounds
  72. // Access: Public
  73. // Description: Checks the bounding volume of the current node
  74. // against each of our colliders. Eliminates from the
  75. // current collider list any that are outside of the
  76. // bounding volume. Returns true if any colliders
  77. // remain, false if all of them fall outside this node's
  78. // bounding volume.
  79. ////////////////////////////////////////////////////////////////////
  80. bool CollisionLevelState::
  81. any_in_bounds() {
  82. #ifndef NDEBUG
  83. int indent_level = 0;
  84. if (collide_cat.is_spam()) {
  85. indent_level = _node_path.get_num_nodes() * 2;
  86. collide_cat.spam();
  87. indent(collide_cat.spam(false), indent_level)
  88. << "Considering " << _node_path.get_node_path() << "\n";
  89. }
  90. #endif // NDEBUG
  91. const BoundingVolume &node_bv = node()->get_bound();
  92. if (node_bv.is_of_type(GeometricBoundingVolume::get_class_type())) {
  93. const GeometricBoundingVolume *node_gbv;
  94. DCAST_INTO_R(node_gbv, &node_bv, false);
  95. int num_colliders = get_num_colliders();
  96. for (int c = 0; c < num_colliders; c++) {
  97. if (has_collider(c)) {
  98. CollisionNode *collider = get_node(c);
  99. bool is_in = false;
  100. // Don't even bother testing the bounding volume if there are
  101. // no collide bits in common between our collider and this
  102. // node.
  103. CollideMask from_mask = collider->get_from_collide_mask();
  104. if (collider->get_collide_geom() ||
  105. (from_mask & node()->get_net_collide_mask()) != 0) {
  106. // There are bits in common, so go ahead and try the
  107. // bounding volume.
  108. const GeometricBoundingVolume *col_gbv =
  109. get_local_bound(c);
  110. if (col_gbv != (GeometricBoundingVolume *)NULL) {
  111. is_in = (node_gbv->contains(col_gbv) != 0);
  112. #ifndef NDEBUG
  113. if (collide_cat.is_spam()) {
  114. collide_cat.spam();
  115. indent(collide_cat.spam(false), indent_level)
  116. << "Comparing " << c << ": " << *col_gbv
  117. << " to " << *node_gbv << ", is_in = " << is_in << "\n";
  118. }
  119. #endif // NDEBUG
  120. }
  121. }
  122. if (!is_in) {
  123. // This collider cannot intersect with any geometry at
  124. // this node or below.
  125. omit_collider(c);
  126. }
  127. }
  128. }
  129. }
  130. #ifndef NDEBUG
  131. if (collide_cat.is_spam()) {
  132. int num_active_colliders = 0;
  133. int num_colliders = get_num_colliders();
  134. for (int c = 0; c < num_colliders; c++) {
  135. if (has_collider(c)) {
  136. num_active_colliders++;
  137. }
  138. }
  139. collide_cat.spam();
  140. indent(collide_cat.spam(false), indent_level)
  141. << _node_path.get_node_path() << " has " << num_active_colliders
  142. << " interested colliders.\n";
  143. }
  144. #endif // NDEBUG
  145. return has_any_collider();
  146. }
  147. ////////////////////////////////////////////////////////////////////
  148. // Function: CollisionLevelState::apply_transform
  149. // Access: Public
  150. // Description: Applies the inverse transform from the current node,
  151. // if any, onto all the colliders in the level state.
  152. ////////////////////////////////////////////////////////////////////
  153. void CollisionLevelState::
  154. apply_transform() {
  155. // The "parent" bounds list remembers the bounds list of the
  156. // previous node.
  157. _parent_bounds = _local_bounds;
  158. // Recompute the bounds list of this node (if we have a transform).
  159. const TransformState *node_transform = node()->get_transform();
  160. if (!node_transform->is_identity()) {
  161. CPT(TransformState) inv_transform =
  162. node_transform->invert_compose(TransformState::make_identity());
  163. const LMatrix4f &mat = inv_transform->get_mat();
  164. // Now build the new bounding volumes list.
  165. BoundingVolumes new_bounds;
  166. int num_colliders = get_num_colliders();
  167. new_bounds.reserve(num_colliders);
  168. for (int c = 0; c < num_colliders; c++) {
  169. if (!has_collider(c) ||
  170. get_local_bound(c) == (GeometricBoundingVolume *)NULL) {
  171. new_bounds.push_back((GeometricBoundingVolume *)NULL);
  172. } else {
  173. const GeometricBoundingVolume *old_bound = get_local_bound(c);
  174. GeometricBoundingVolume *new_bound =
  175. DCAST(GeometricBoundingVolume, old_bound->make_copy());
  176. new_bound->xform(mat);
  177. new_bounds.push_back(new_bound);
  178. }
  179. }
  180. _local_bounds = new_bounds;
  181. }
  182. }