Browse Source

all nodes now have a CollideMask

David Rose 21 years ago
parent
commit
0369f07074

+ 0 - 39
panda/src/collide/collisionLevelState.I

@@ -39,7 +39,6 @@ CollisionLevelState(const CollisionLevelState &parent, PandaNode *child) :
   _node_path(parent._node_path, child),
   _node_path(parent._node_path, child),
   _colliders(parent._colliders),
   _colliders(parent._colliders),
   _current(parent._current),
   _current(parent._current),
-  _colliders_with_geom(parent._colliders_with_geom),
   _local_bounds(parent._local_bounds)
   _local_bounds(parent._local_bounds)
 {
 {
 }
 }
@@ -88,19 +87,6 @@ has_collider(int n) const {
   return (_current & get_mask(n)) != 0;
   return (_current & get_mask(n)) != 0;
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionLevelState::has_collider_with_geom
-//       Access: Public
-//  Description: Returns true if the nth collider in the LevelState is
-//               still part of the level, and it has the
-//               "collide_geom" flag set.
-////////////////////////////////////////////////////////////////////
-INLINE bool CollisionLevelState::
-has_collider_with_geom(int n) const {
-  nassertr(n >= 0 && n < (int)_colliders.size(), false);
-  return (_current & _colliders_with_geom & get_mask(n)) != 0;
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionLevelState::has_any_collider
 //     Function: CollisionLevelState::has_any_collider
 //       Access: Public
 //       Access: Public
@@ -111,31 +97,6 @@ has_any_collider() const {
   return _current != 0;
   return _current != 0;
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionLevelState::has_any_collide_geom
-//       Access: Public
-//  Description: Returns true if any Collider in the level state has
-//               the "collide_geom" flag set, false otherwise.
-////////////////////////////////////////////////////////////////////
-INLINE bool CollisionLevelState::
-has_any_collide_geom() const {
-  return (_current & _colliders_with_geom) != 0;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionLevelState::reached_collision_node
-//       Access: Public
-//  Description: Called by the traverser when we reach a CollisionNode
-//               in the traversal.  At this point, we zero out our set
-//               of colliders with the "collide_geom" flag set,
-//               because no colliders will test against geometry
-//               parented beneath a CollisionNode.
-////////////////////////////////////////////////////////////////////
-INLINE void CollisionLevelState::
-reached_collision_node() {
-  _colliders_with_geom = 0;
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionLevelState::get_collider
 //     Function: CollisionLevelState::get_collider
 //       Access: Public
 //       Access: Public

+ 0 - 4
panda/src/collide/collisionLevelState.cxx

@@ -31,7 +31,6 @@ clear() {
   _local_bounds.clear();
   _local_bounds.clear();
   _parent_bounds.clear();
   _parent_bounds.clear();
   _current = 0;
   _current = 0;
-  _colliders_with_geom = 0;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -89,9 +88,6 @@ prepare_collider(const ColliderDef &def) {
 
 
   _current |= get_mask(index);
   _current |= get_mask(index);
 
 
-  if (def._node->get_collide_geom()) {
-    _colliders_with_geom |= get_mask(index);
-  }
   _parent_bounds = _local_bounds;
   _parent_bounds = _local_bounds;
 }
 }
 
 

+ 0 - 5
panda/src/collide/collisionLevelState.h

@@ -63,11 +63,7 @@ public:
 
 
   INLINE int get_num_colliders() const;
   INLINE int get_num_colliders() const;
   INLINE bool has_collider(int n) const;
   INLINE bool has_collider(int n) const;
-  INLINE bool has_collider_with_geom(int n) const;
   INLINE bool has_any_collider() const;
   INLINE bool has_any_collider() const;
-  INLINE bool has_any_collide_geom() const;
-
-  INLINE void reached_collision_node();
 
 
   INLINE CollisionSolid *get_collider(int n) const;
   INLINE CollisionSolid *get_collider(int n) const;
   INLINE CollisionNode *get_collider_node(int n) const;
   INLINE CollisionNode *get_collider_node(int n) const;
@@ -92,7 +88,6 @@ private:
   typedef PTA(ColliderDef) Colliders;
   typedef PTA(ColliderDef) Colliders;
   Colliders _colliders;
   Colliders _colliders;
   ColliderMask _current;
   ColliderMask _current;
-  ColliderMask _colliders_with_geom;
 
 
   typedef PTA(CPT(GeometricBoundingVolume)) BoundingVolumes;
   typedef PTA(CPT(GeometricBoundingVolume)) BoundingVolumes;
   BoundingVolumes _local_bounds;
   BoundingVolumes _local_bounds;

+ 15 - 56
panda/src/collide/collisionNode.I

@@ -29,20 +29,6 @@ set_collide_mask(CollideMask mask) {
   set_into_collide_mask(mask);
   set_into_collide_mask(mask);
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionNode::set_from_collide_mask
-//       Access: Published
-//  Description: Sets the "from" CollideMask.  In order for a
-//               collision to be detected from this object into
-//               another object, the intersection of this object's
-//               "from" mask and the other object's "into" mask must
-//               be nonzero.
-////////////////////////////////////////////////////////////////////
-INLINE void CollisionNode::
-set_from_collide_mask(CollideMask mask) {
-  _from_collide_mask = mask;
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionNode::set_into_collide_mask
 //     Function: CollisionNode::set_into_collide_mask
 //       Access: Published
 //       Access: Published
@@ -54,12 +40,8 @@ set_from_collide_mask(CollideMask mask) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void CollisionNode::
 INLINE void CollisionNode::
 set_into_collide_mask(CollideMask mask) {
 set_into_collide_mask(CollideMask mask) {
-  _into_collide_mask = mask;
-
-  // We mark the bound stale when this changes, not because the actual
-  // bounding volume changes, but rather because we piggyback the
-  // computing of the _net_collide_mask on the bounding volume.
-  mark_bound_stale();
+  // This is now inherited from the PandaNode base class.
+  PandaNode::set_into_collide_mask(mask);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -87,42 +69,8 @@ get_from_collide_mask() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CollideMask CollisionNode::
 INLINE CollideMask CollisionNode::
 get_into_collide_mask() const {
 get_into_collide_mask() const {
-  return _into_collide_mask;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionNode::set_collide_geom
-//       Access: Published
-//  Description: Sets the state of the "collide geom" flag for this
-//               CollisionNode.  Normally, this is false; when this is
-//               set true, the CollisionSolids in this node will test
-//               for collisions with actual renderable geometry, in
-//               addition to whatever CollisionSolids may be indicated
-//               by the from_collide_mask.
-//
-//               Setting this to true causes this to test *all*
-//               GeomNodes for collisions.  It is an all-or-none
-//               thing; there is no way to collide with only some
-//               GeomNodes, as GeomNodes have no into_collide_mask.
-////////////////////////////////////////////////////////////////////
-INLINE void CollisionNode::
-set_collide_geom(bool flag) {
-  if (flag) {
-    _flags |= F_collide_geom;
-  } else {
-    _flags &= ~F_collide_geom;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionNode::get_collide_geom
-//       Access: Published
-//  Description: Returns the current state of the collide_geom flag.
-//               See set_collide_geom().
-////////////////////////////////////////////////////////////////////
-INLINE bool CollisionNode::
-get_collide_geom() const {
-  return (_flags & F_collide_geom) != 0;
+  // This is now inherited from the PandaNode base class.
+  return PandaNode::get_into_collide_mask();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -195,3 +143,14 @@ add_solid(CollisionSolid *solid) {
   mark_bound_stale();
   mark_bound_stale();
   return _solids.size() - 1;
   return _solids.size() - 1;
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionNode::get_default_collide_mask
+//       Access: Published, Static
+//  Description: Returns the default into_collide_mask assigned to new
+//               CollisionNodes.
+////////////////////////////////////////////////////////////////////
+INLINE CollideMask CollisionNode::
+get_default_collide_mask() {
+  return default_collision_node_collide_mask;
+}

+ 107 - 22
panda/src/collide/collisionNode.cxx

@@ -30,6 +30,7 @@
 #include "datagramIterator.h"
 #include "datagramIterator.h"
 #include "bamReader.h"
 #include "bamReader.h"
 #include "bamWriter.h"
 #include "bamWriter.h"
+#include "clockObject.h"
 
 
 TypeHandle CollisionNode::_type_handle;
 TypeHandle CollisionNode::_type_handle;
 
 
@@ -42,12 +43,14 @@ TypeHandle CollisionNode::_type_handle;
 CollisionNode::
 CollisionNode::
 CollisionNode(const string &name) :
 CollisionNode(const string &name) :
   PandaNode(name),
   PandaNode(name),
-  _from_collide_mask(CollideMask::all_on()),
-  _into_collide_mask(CollideMask::all_on()),
-  _flags(0)
+  _from_collide_mask(get_default_collide_mask()),
+  _collide_geom(false)
 {
 {
   // CollisionNodes are hidden by default.
   // CollisionNodes are hidden by default.
   set_draw_mask(DrawMask::all_off());
   set_draw_mask(DrawMask::all_off());
+
+  // CollisionNodes have a certain set of bits on by default.
+  set_into_collide_mask(get_default_collide_mask());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -59,8 +62,6 @@ CollisionNode::
 CollisionNode(const CollisionNode &copy) :
 CollisionNode(const CollisionNode &copy) :
   PandaNode(copy),
   PandaNode(copy),
   _from_collide_mask(copy._from_collide_mask),
   _from_collide_mask(copy._from_collide_mask),
-  _into_collide_mask(copy._into_collide_mask),
-  _flags(copy._flags),
   _solids(copy._solids)
   _solids(copy._solids)
 {
 {
 }
 }
@@ -167,6 +168,22 @@ combine_with(PandaNode *other) {
   return PandaNode::combine_with(other);
   return PandaNode::combine_with(other);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionNode::get_legal_collide_mask
+//       Access: Published, Virtual
+//  Description: Returns the subset of CollideMask bits that may be
+//               set for this particular type of PandaNode.  For most
+//               nodes, this is 0; it doesn't make sense to set a
+//               CollideMask for most kinds of nodes.
+//
+//               For nodes that can be collided with, such as GeomNode
+//               and CollisionNode, this returns all bits on.
+////////////////////////////////////////////////////////////////////
+CollideMask CollisionNode::
+get_legal_collide_mask() const {
+  return CollideMask::all_on();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionNode::has_cull_callback
 //     Function: CollisionNode::has_cull_callback
 //       Access: Public, Virtual
 //       Access: Public, Virtual
@@ -260,22 +277,74 @@ output(ostream &out) const {
   out << " (" << _solids.size() << " solids)";
   out << " (" << _solids.size() << " solids)";
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionNode::set_from_collide_mask
+//       Access: Published
+//  Description: Sets the "from" CollideMask.  In order for a
+//               collision to be detected from this object into
+//               another object, the intersection of this object's
+//               "from" mask and the other object's "into" mask must
+//               be nonzero.
+////////////////////////////////////////////////////////////////////
+void CollisionNode::
+set_from_collide_mask(CollideMask mask) {
+  _from_collide_mask = mask;
+
+  if (_collide_geom) {
+    _from_collide_mask |= GeomNode::get_default_collide_mask();
+  }
+}
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: CollisionNode::recompute_bound
-//       Access: Protected, Virtual
-//  Description: Recomputes the dynamic bounding volume for this
-//               object.  This is the bounding volume for the node and
-//               all of its children, and normally does not need to be
-//               specialized beyond PandaNode; we specialize this
-//               function just so we can piggyback on it the
-//               setting the _net_collide_mask bits.
+//     Function: CollisionNode::set_collide_geom
+//       Access: Published
+//  Description: Sets the state of the "collide geom" flag for this
+//               CollisionNode.  
+//
+//               This flag is now deprecated, now that GeomNodes have
+//               their own into_collide_mask, just like CollisionNodes
+//               do.  Instead of using set_collide_geom(), you should
+//               use the from_collide_mask to control which GeomNodes
+//               each CollisionNode will intersect with.  
+//
+//               In particular, you may be interested in setting
+//               from_collide_mask to the value returned by
+//               GeomNode::get_default_collide_mask(), which is the
+//               default into_collide_mask that all GeomNodes will be
+//               given (unless they are explicitly given some other
+//               mask).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-BoundingVolume *CollisionNode::
-recompute_bound() {
-  BoundingVolume *result = PandaNode::recompute_bound();
-  add_net_collide_mask(get_into_collide_mask());
-  return result;
+void CollisionNode::
+set_collide_geom(bool flag) {
+  // Only repeat this warning every five seconds or so--no need to be
+  // completely spammy.
+  static double last_warning = -10.0;
+  double now = ClockObject::get_global_clock()->get_frame_time();
+  double elapsed = now - last_warning;
+  if (elapsed > 5.0) {
+    last_warning = now;
+    collide_cat.warning()
+      << "Using deprecated set_collide_geom().  Replace this with an appropriate call to set_from_collide_mask(), e.g. set_from_collide_mask(GeomNode::get_default_collide_mask()).\n";
+  }
+    
+  _collide_geom = flag;
+
+  if (_collide_geom) {
+    _from_collide_mask |= GeomNode::get_default_collide_mask();
+  } else {
+    _from_collide_mask &= ~GeomNode::get_default_collide_mask();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionNode::get_collide_geom
+//       Access: Published
+//  Description: Returns the current state of the collide_geom flag.
+//               See set_collide_geom().
+////////////////////////////////////////////////////////////////////
+bool CollisionNode::
+get_collide_geom() const {
+  return _collide_geom;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -373,8 +442,6 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   }
   }
 
 
   dg.add_uint32(_from_collide_mask.get_word());
   dg.add_uint32(_from_collide_mask.get_word());
-  dg.add_uint32(_into_collide_mask.get_word());
-  dg.add_uint8(_flags);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -438,6 +505,24 @@ fillin(DatagramIterator &scan, BamReader *manager) {
   }
   }
 
 
   _from_collide_mask.set_word(scan.get_uint32());
   _from_collide_mask.set_word(scan.get_uint32());
-  _into_collide_mask.set_word(scan.get_uint32());
-  _flags = scan.get_uint8();
+  if (manager->get_file_minor_ver() < 12) {
+    // Bam files prior to 4.12 stored the into_collide_mask here.
+    // (4.12 and later store this in the PandaNode base class
+    // instead.)
+    CollideMask into_collide_mask;
+    into_collide_mask.set_word(scan.get_uint32());
+
+    // We also introduced the concept of the CollisionNode-reserved
+    // bits and the GeomNode-reserved bits with version 4.12.  Prior
+    // to that, CollisionNodes tended to have all bits set.  Assume
+    // they only meant to have the CollisionNode bits set.
+    into_collide_mask &= get_default_collide_mask();
+    _from_collide_mask &= get_default_collide_mask();
+
+    set_into_collide_mask(into_collide_mask);
+
+    // Bam files prior to 4.12 also had a _flags member, which is no
+    // longer supported.
+    scan.get_uint8();
+  }
 }
 }

+ 7 - 11
panda/src/collide/collisionNode.h

@@ -47,6 +47,7 @@ public:
   virtual bool preserve_name() const;
   virtual bool preserve_name() const;
   virtual void xform(const LMatrix4f &mat);
   virtual void xform(const LMatrix4f &mat);
   virtual PandaNode *combine_with(PandaNode *other); 
   virtual PandaNode *combine_with(PandaNode *other); 
+  virtual CollideMask get_legal_collide_mask() const;
 
 
   virtual bool has_cull_callback() const;
   virtual bool has_cull_callback() const;
   virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
   virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
@@ -55,13 +56,13 @@ public:
 
 
 PUBLISHED:
 PUBLISHED:
   INLINE void set_collide_mask(CollideMask mask);
   INLINE void set_collide_mask(CollideMask mask);
-  INLINE void set_from_collide_mask(CollideMask mask);
+  void set_from_collide_mask(CollideMask mask);
   INLINE void set_into_collide_mask(CollideMask mask);
   INLINE void set_into_collide_mask(CollideMask mask);
   INLINE CollideMask get_from_collide_mask() const;
   INLINE CollideMask get_from_collide_mask() const;
   INLINE CollideMask get_into_collide_mask() const;
   INLINE CollideMask get_into_collide_mask() const;
 
 
-  INLINE void set_collide_geom(bool flag);
-  INLINE bool get_collide_geom() const;
+  void set_collide_geom(bool flag);
+  bool get_collide_geom() const;
 
 
   INLINE void clear_solids();
   INLINE void clear_solids();
   INLINE int get_num_solids() const;
   INLINE int get_num_solids() const;
@@ -70,8 +71,9 @@ PUBLISHED:
   INLINE void remove_solid(int n);
   INLINE void remove_solid(int n);
   INLINE int add_solid(CollisionSolid *solid);
   INLINE int add_solid(CollisionSolid *solid);
 
 
+  INLINE static CollideMask get_default_collide_mask();
+
 protected:
 protected:
-  virtual BoundingVolume *recompute_bound();
   virtual BoundingVolume *recompute_internal_bound();
   virtual BoundingVolume *recompute_internal_bound();
 
 
 private:
 private:
@@ -81,13 +83,7 @@ private:
   // traversal will take place in App only.  Perhaps we will revisit
   // traversal will take place in App only.  Perhaps we will revisit
   // this later.
   // this later.
   CollideMask _from_collide_mask;
   CollideMask _from_collide_mask;
-  CollideMask _into_collide_mask;
-
-  enum Flags {
-    F_collide_geom = 0x0001,
-    // Presently only 8 bits are written to the bam file.
-  };
-  int _flags;
+  bool _collide_geom;
 
 
   typedef pvector< PT(CollisionSolid) > Solids;
   typedef pvector< PT(CollisionSolid) > Solids;
   Solids _solids;
   Solids _solids;

+ 12 - 10
panda/src/collide/collisionTraverser.cxx

@@ -513,8 +513,6 @@ r_traverse(CollisionLevelState &level_state) {
 
 
   PandaNode *node = level_state.node();
   PandaNode *node = level_state.node();
   if (node->is_exact_type(CollisionNode::get_class_type())) {
   if (node->is_exact_type(CollisionNode::get_class_type())) {
-    level_state.reached_collision_node();
-
     CollisionNode *cnode;
     CollisionNode *cnode;
     DCAST_INTO_V(cnode, node);
     DCAST_INTO_V(cnode, node);
     const BoundingVolume &node_bv = cnode->get_bound();
     const BoundingVolume &node_bv = cnode->get_bound();
@@ -548,7 +546,7 @@ r_traverse(CollisionLevelState &level_state) {
       }
       }
     }
     }
 
 
-  } else if (node->is_geom_node() && level_state.has_any_collide_geom()) {
+  } else if (node->is_geom_node()) {
 #ifndef NDEBUG
 #ifndef NDEBUG
     if (collide_cat.is_spam()) {
     if (collide_cat.is_spam()) {
       collide_cat.spam()
       collide_cat.spam()
@@ -573,15 +571,19 @@ r_traverse(CollisionLevelState &level_state) {
 
 
     int num_colliders = level_state.get_num_colliders();
     int num_colliders = level_state.get_num_colliders();
     for (int c = 0; c < num_colliders; c++) {
     for (int c = 0; c < num_colliders; c++) {
-      if (level_state.has_collider_with_geom(c)) {
+      if (level_state.has_collider(c)) {
         entry._from_node = level_state.get_collider_node(c);
         entry._from_node = level_state.get_collider_node(c);
-        entry._from_node_path = level_state.get_collider_node_path(c);
-        entry._from = level_state.get_collider(c);
 
 
-        compare_collider_to_geom_node(entry, 
-                                      level_state.get_parent_bound(c),
-                                      level_state.get_local_bound(c),
-                                      node_gbv);
+        if ((entry._from_node->get_from_collide_mask() &
+             gnode->get_into_collide_mask()) != 0) {
+          entry._from_node_path = level_state.get_collider_node_path(c);
+          entry._from = level_state.get_collider(c);
+
+          compare_collider_to_geom_node(entry, 
+                                        level_state.get_parent_bound(c),
+                                        level_state.get_local_bound(c),
+                                        node_gbv);
+        }
       }
       }
     }
     }
   }
   }

+ 11 - 0
panda/src/pgraph/geomNode.I

@@ -167,3 +167,14 @@ remove_all_geoms() {
   cdata->_geoms.clear();
   cdata->_geoms.clear();
   mark_bound_stale();
   mark_bound_stale();
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: GeomNode::get_default_collide_mask
+//       Access: Published, Static
+//  Description: Returns the default into_collide_mask assigned to new
+//               GeomNodes.
+////////////////////////////////////////////////////////////////////
+INLINE CollideMask GeomNode::
+get_default_collide_mask() {
+  return default_geom_node_collide_mask;
+}

+ 18 - 0
panda/src/pgraph/geomNode.cxx

@@ -124,6 +124,8 @@ GeomNode::
 GeomNode(const string &name) :
 GeomNode(const string &name) :
   PandaNode(name)
   PandaNode(name)
 {
 {
+  // GeomNodes have a certain set of bits on by default.
+  set_into_collide_mask(get_default_collide_mask());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -316,6 +318,22 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any,
   return next_transform;
   return next_transform;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GeomNode::get_legal_collide_mask
+//       Access: Published, Virtual
+//  Description: Returns the subset of CollideMask bits that may be
+//               set for this particular type of PandaNode.  For most
+//               nodes, this is 0; it doesn't make sense to set a
+//               CollideMask for most kinds of nodes.
+//
+//               For nodes that can be collided with, such as GeomNode
+//               and CollisionNode, this returns all bits on.
+////////////////////////////////////////////////////////////////////
+CollideMask GeomNode::
+get_legal_collide_mask() const {
+  return CollideMask::all_on();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomNode::add_geoms_from
 //     Function: GeomNode::add_geoms_from
 //       Access: Published
 //       Access: Published

+ 3 - 0
panda/src/pgraph/geomNode.h

@@ -53,6 +53,7 @@ public:
     calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
     calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
                       bool &found_any,
                       bool &found_any,
                       const TransformState *transform) const;
                       const TransformState *transform) const;
+  virtual CollideMask get_legal_collide_mask() const;
 
 
 PUBLISHED:
 PUBLISHED:
   INLINE int get_num_geoms() const;
   INLINE int get_num_geoms() const;
@@ -69,6 +70,8 @@ PUBLISHED:
   void write_geoms(ostream &out, int indent_level) const;
   void write_geoms(ostream &out, int indent_level) const;
   void write_verbose(ostream &out, int indent_level) const;
   void write_verbose(ostream &out, int indent_level) const;
 
 
+  INLINE static CollideMask get_default_collide_mask();
+
 public:
 public:
   virtual void output(ostream &out) const;
   virtual void output(ostream &out) const;
 
 

+ 36 - 0
panda/src/pgraph/nodePath.I

@@ -1453,6 +1453,42 @@ is_stashed() const {
   return !get_stashed_ancestor().is_empty();
   return !get_stashed_ancestor().is_empty();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::get_collide_mask
+//       Access: Published
+//  Description: Returns the union of all of the into_collide_masks
+//               for nodes at this level and below.  This is the same
+//               thing as node()->get_net_collide_mask().
+//
+//               If you want to return what the into_collide_mask of
+//               this node itself is, without regard to its children,
+//               use node()->get_into_collide_mask().
+////////////////////////////////////////////////////////////////////
+INLINE CollideMask NodePath::
+get_collide_mask() const {
+  nassertr_always(!is_empty(), CollideMask::all_off());
+  return node()->get_net_collide_mask();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::set_collide_mask
+//       Access: Published
+//  Description: Recursively applies the indicated CollideMask to the
+//               into_collide_masks for all nodes at this level and
+//               below.
+//
+//               The default is to change all bits, but if
+//               bits_to_change is not all bits on, then only the bits
+//               that are set in bits_to_change are modified, allowing
+//               this call to change only a subset of the bits in the
+//               subgraph.
+////////////////////////////////////////////////////////////////////
+INLINE void NodePath::
+set_collide_mask(CollideMask new_mask, CollideMask bits_to_change) {
+  nassertv_always(!is_empty());
+  r_set_collide_mask(node(), ~bits_to_change, new_mask & bits_to_change);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::operator ==
 //     Function: NodePath::operator ==
 //       Access: Published
 //       Access: Published

+ 20 - 0
panda/src/pgraph/nodePath.cxx

@@ -4944,6 +4944,26 @@ r_force_recompute_bounds(PandaNode *node) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::r_set_collide_mask
+//       Access: Private
+//  Description: Recursively applies the indicated collide mask to the
+//               nodes at and below this node.
+////////////////////////////////////////////////////////////////////
+void NodePath::
+r_set_collide_mask(PandaNode *node, 
+                   CollideMask and_mask, CollideMask or_mask) {
+  CollideMask into_collide_mask = node->get_into_collide_mask();
+  into_collide_mask = (into_collide_mask & and_mask) | or_mask;
+  node->set_into_collide_mask(into_collide_mask);
+
+  PandaNode::Children cr = node->get_children();
+  int num_children = cr.get_num_children();
+  for (int i = 0; i < num_children; i++) {
+    r_set_collide_mask(cr.get_child(i), and_mask, or_mask);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::r_find_texture
 //     Function: NodePath::r_find_texture
 //       Access: Private
 //       Access: Private

+ 6 - 0
panda/src/pgraph/nodePath.h

@@ -647,6 +647,9 @@ PUBLISHED:
   INLINE bool is_stashed() const;
   INLINE bool is_stashed() const;
   NodePath get_stashed_ancestor() const;
   NodePath get_stashed_ancestor() const;
 
 
+  INLINE CollideMask get_collide_mask() const;
+  INLINE void set_collide_mask(CollideMask new_mask, CollideMask bits_to_change = CollideMask::all_on());
+
   // Comparison methods
   // Comparison methods
   INLINE bool operator == (const NodePath &other) const;
   INLINE bool operator == (const NodePath &other) const;
   INLINE bool operator != (const NodePath &other) const;
   INLINE bool operator != (const NodePath &other) const;
@@ -708,6 +711,9 @@ private:
 
 
   void r_force_recompute_bounds(PandaNode *node);
   void r_force_recompute_bounds(PandaNode *node);
 
 
+  void r_set_collide_mask(PandaNode *node, 
+                          CollideMask and_mask, CollideMask or_mask);
+
   typedef pset<Texture *> Textures;
   typedef pset<Texture *> Textures;
   Texture *r_find_texture(PandaNode *node, const RenderState *state,
   Texture *r_find_texture(PandaNode *node, const RenderState *state,
                           const GlobPattern &glob) const;
                           const GlobPattern &glob) const;

+ 41 - 13
panda/src/pgraph/pandaNode.I

@@ -120,6 +120,7 @@ CData() {
   _transform = TransformState::make_identity();
   _transform = TransformState::make_identity();
   _prev_transform = TransformState::make_identity();
   _prev_transform = TransformState::make_identity();
   _draw_mask = DrawMask::all_on();
   _draw_mask = DrawMask::all_on();
+  _into_collide_mask = CollideMask::all_off();
   _net_collide_mask = CollideMask::all_off();
   _net_collide_mask = CollideMask::all_off();
   _fixed_internal_bound = false;
   _fixed_internal_bound = false;
 }
 }
@@ -141,6 +142,7 @@ CData(const PandaNode::CData &copy) :
   _prev_transform(copy._prev_transform),
   _prev_transform(copy._prev_transform),
   _tag_data(copy._tag_data),
   _tag_data(copy._tag_data),
   _draw_mask(copy._draw_mask),
   _draw_mask(copy._draw_mask),
+  _into_collide_mask(copy._into_collide_mask),
   _fixed_internal_bound(copy._fixed_internal_bound)
   _fixed_internal_bound(copy._fixed_internal_bound)
 {
 {
   _net_collide_mask = CollideMask::all_off();
   _net_collide_mask = CollideMask::all_off();
@@ -812,6 +814,45 @@ get_draw_mask() const {
   return cdata->_draw_mask;
   return cdata->_draw_mask;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PandaNode::set_into_collide_mask
+//       Access: Published
+//  Description: Sets the "into" CollideMask.  
+//
+//               This specifies the set of bits that must be shared
+//               with a CollisionNode's "from" CollideMask in order
+//               for the CollisionNode to detect a collision with this
+//               particular node.
+//
+//               The actual CollideMask that will be set is masked by
+//               the return value from get_legal_collide_mask().
+//               Thus, the into_collide_mask cannot be set to anything
+//               other than nonzero except for those types of nodes
+//               that can be collided into, such as CollisionNodes and
+//               GeomNodes.
+////////////////////////////////////////////////////////////////////
+INLINE void PandaNode::
+set_into_collide_mask(CollideMask mask) {
+  CDWriter cdata(_cycler);
+  cdata->_into_collide_mask = mask & get_legal_collide_mask();
+
+  // We mark the bound stale when this changes, not because the actual
+  // bounding volume changes, but rather because we piggyback the
+  // computing of the _net_collide_mask on the bounding volume.
+  mark_bound_stale();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PandaNode::get_into_collide_mask
+//       Access: Published
+//  Description: Returns the "into" collide mask for this node.
+////////////////////////////////////////////////////////////////////
+INLINE CollideMask PandaNode::
+get_into_collide_mask() const {
+  CDReader cdata(_cycler);
+  return cdata->_into_collide_mask;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PandaNode::get_net_collide_mask
 //     Function: PandaNode::get_net_collide_mask
 //       Access: Published
 //       Access: Published
@@ -897,19 +938,6 @@ changed_internal_bound() {
   BoundedObject::mark_bound_stale();
   BoundedObject::mark_bound_stale();
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: PandaNode::add_net_collide_mask
-//       Access: Protected
-//  Description: Adds the indicated bits into the net_collide_mask for
-//               this node.  This is normally called only by
-//               CollisionNode::recompute_bound().
-////////////////////////////////////////////////////////////////////
-INLINE void PandaNode::
-add_net_collide_mask(CollideMask mask) {
-  CDWriter cdata(_cycler);
-  cdata->_net_collide_mask |= mask;
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PandaNode::get_children
 //     Function: PandaNode::get_children
 //       Access: Public
 //       Access: Public

+ 22 - 1
panda/src/pgraph/pandaNode.cxx

@@ -77,6 +77,7 @@ write_datagram(BamWriter *manager, Datagram &dg) const {
   manager->write_pointer(dg, _transform);
   manager->write_pointer(dg, _transform);
 
 
   dg.add_uint32(_draw_mask.get_word());
   dg.add_uint32(_draw_mask.get_word());
+  dg.add_uint32(_into_collide_mask.get_word());
 
 
   write_up_list(_up, manager, dg);
   write_up_list(_up, manager, dg);
   write_down_list(_down, manager, dg);
   write_down_list(_down, manager, dg);
@@ -142,6 +143,9 @@ fillin(DatagramIterator &scan, BamReader *manager) {
   manager->read_pointer(scan);
   manager->read_pointer(scan);
 
 
   _draw_mask.set_word(scan.get_uint32());
   _draw_mask.set_word(scan.get_uint32());
+  if (manager->get_file_minor_ver() >= 12) {
+    _into_collide_mask.set_word(scan.get_uint32());
+  }
 
 
   // Read the parent and child pointers.
   // Read the parent and child pointers.
   fillin_up_list(_up, scan, manager);
   fillin_up_list(_up, scan, manager);
@@ -383,6 +387,7 @@ PandaNode(const PandaNode &copy) :
   cdata->_prev_transform = copy_cdata->_prev_transform;
   cdata->_prev_transform = copy_cdata->_prev_transform;
   cdata->_tag_data = copy_cdata->_tag_data;
   cdata->_tag_data = copy_cdata->_tag_data;
   cdata->_draw_mask = copy_cdata->_draw_mask;
   cdata->_draw_mask = copy_cdata->_draw_mask;
+  cdata->_into_collide_mask = copy_cdata->_into_collide_mask;
   cdata->_fixed_internal_bound = copy_cdata->_fixed_internal_bound;
   cdata->_fixed_internal_bound = copy_cdata->_fixed_internal_bound;
 }
 }
 
 
@@ -1275,6 +1280,22 @@ list_tags(ostream &out, const string &separator) const {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PandaNode::get_legal_collide_mask
+//       Access: Published, Virtual
+//  Description: Returns the subset of CollideMask bits that may be
+//               set for this particular type of PandaNode.  For most
+//               nodes, this is 0; it doesn't make sense to set a
+//               CollideMask for most kinds of nodes.
+//
+//               For nodes that can be collided with, such as GeomNode
+//               and CollisionNode, this returns all bits on.
+////////////////////////////////////////////////////////////////////
+CollideMask PandaNode::
+get_legal_collide_mask() const {
+  return CollideMask::all_off();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PandaNode::output
 //     Function: PandaNode::output
 //       Access: Published, Virtual
 //       Access: Published, Virtual
@@ -1382,7 +1403,7 @@ recompute_bound() {
 
 
   // Also, recompute the net_collide_mask bits while we do this.
   // Also, recompute the net_collide_mask bits while we do this.
   CDWriter cdata(_cycler);
   CDWriter cdata(_cycler);
-  cdata->_net_collide_mask = CollideMask::all_off();
+  cdata->_net_collide_mask = cdata->_into_collide_mask;
 
 
   // Now actually compute the bounding volume by putting it around all
   // Now actually compute the bounding volume by putting it around all
   // of our child bounding volumes.
   // of our child bounding volumes.

+ 16 - 6
panda/src/pgraph/pandaNode.h

@@ -164,6 +164,10 @@ PUBLISHED:
   INLINE void set_draw_mask(DrawMask mask);
   INLINE void set_draw_mask(DrawMask mask);
   INLINE DrawMask get_draw_mask() const;
   INLINE DrawMask get_draw_mask() const;
 
 
+  INLINE void set_into_collide_mask(CollideMask mask);
+  INLINE CollideMask get_into_collide_mask() const;
+  virtual CollideMask get_legal_collide_mask() const;
+
   INLINE CollideMask get_net_collide_mask() const;
   INLINE CollideMask get_net_collide_mask() const;
 
 
   virtual void output(ostream &out) const;
   virtual void output(ostream &out) const;
@@ -320,12 +324,18 @@ private:
     // This is the draw_mask of this particular node.
     // This is the draw_mask of this particular node.
     DrawMask _draw_mask;
     DrawMask _draw_mask;
 
 
-    // This is the union of all into_collide_mask bits for any
-    // CollisionNodes at and below this level.  It's conceptually
-    // similar to a bounding volume--it represents the bounding volume
-    // of this node in the space of collision bits--and it needs to be
-    // updated for the same reasons the bounding volume needs to be
-    // updated.  So we update them together.
+    // This is the mask that indicates which CollisionNodes may detect
+    // a collision with this particular node.  By default it is zero
+    // for an ordinary PandaNode, and all bits on for a CollisionNode
+    // or GeomNode.
+    CollideMask _into_collide_mask;
+
+    // This is the union of all into_collide_mask bits for any nodes
+    // at and below this level.  It's conceptually similar to a
+    // bounding volume--it represents the bounding volume of this node
+    // in the space of collision bits--and it needs to be updated for
+    // the same reasons the bounding volume needs to be updated.  So
+    // we update them together.
     CollideMask _net_collide_mask;
     CollideMask _net_collide_mask;
 
 
     bool _fixed_internal_bound;
     bool _fixed_internal_bound;

+ 2 - 1
panda/src/putil/bam.h

@@ -34,7 +34,7 @@ static const unsigned short _bam_major_ver = 4;
 // Bumped to major version 3 on 12/8/00 to change float64's to float32's.
 // Bumped to major version 3 on 12/8/00 to change float64's to float32's.
 // Bumped to major version 4 on 4/10/02 to store new scene graph.
 // Bumped to major version 4 on 4/10/02 to store new scene graph.
 
 
-static const unsigned short _bam_minor_ver = 11;
+static const unsigned short _bam_minor_ver = 12;
 // Bumped to minor version 1 on 4/10/03 to add CullFaceAttrib::reverse.
 // Bumped to minor version 1 on 4/10/03 to add CullFaceAttrib::reverse.
 // Bumped to minor version 1 on 4/10/03 to add CullFaceAttrib::reverse.
 // Bumped to minor version 1 on 4/10/03 to add CullFaceAttrib::reverse.
 // Bumped to minor version 2 on 4/12/03 to add num_components to texture.
 // Bumped to minor version 2 on 4/12/03 to add num_components to texture.
@@ -47,6 +47,7 @@ static const unsigned short _bam_minor_ver = 11;
 // Bumped to minor version 9 on 12/02/03 to change CollisionPolygon internals.
 // Bumped to minor version 9 on 12/02/03 to change CollisionPolygon internals.
 // Bumped to minor version 10 on 04/23/04 to make ComputedVertices use uint32's.
 // Bumped to minor version 10 on 04/23/04 to make ComputedVertices use uint32's.
 // Bumped to minor version 11 on 07/26/04 to add multitexture pointers.
 // Bumped to minor version 11 on 07/26/04 to add multitexture pointers.
+// Bumped to minor version 12 on 09/22/04 to add PandaNode::into_collide_mask.
 
 
 
 
 #endif
 #endif

+ 22 - 0
panda/src/putil/collideMask.h

@@ -34,5 +34,27 @@
 
 
 typedef BitMask32 CollideMask;
 typedef BitMask32 CollideMask;
 
 
+// We need some conventions for initial bits for GeomNodes and
+// CollideNodes.  These are primarily advisory, since the application
+// programmer is free to define each bit as he or she chooses, but
+// they also control the initial default values that are assigned to
+// new nodes.
+
+// By established convention, the lower 20 bits are reserved for
+// CollisionNodes.  Each CollisionNode has all these bits set on by
+// default (and no others).  You can (and probably should) change this
+// on a per-node basis to specialize CollisionNodes for different
+// purposes.
+static const CollideMask default_collision_node_collide_mask = CollideMask::lower_on(20);
+
+// The next bit is reserved for generic GeomNodes.  Each GeomNode has
+// this bit on by default (and no others).  You can, of course, set
+// any mask you want on a particular GeomNode; this is just the
+// default bit if you choose not to do anything.
+static const CollideMask default_geom_node_collide_mask = CollideMask::bit(20);
+
+// The remaining 11 bits are presently unassigned.  No nodes will have
+// these bits on by default.
+
 #endif
 #endif