From 0369f07074e1f21c73937d709c2b991a34b52f66 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 23 Sep 2004 19:51:54 +0000 Subject: [PATCH] all nodes now have a CollideMask --- panda/src/collide/collisionLevelState.I | 39 ------- panda/src/collide/collisionLevelState.cxx | 4 - panda/src/collide/collisionLevelState.h | 5 - panda/src/collide/collisionNode.I | 71 +++--------- panda/src/collide/collisionNode.cxx | 129 ++++++++++++++++++---- panda/src/collide/collisionNode.h | 18 ++- panda/src/collide/collisionTraverser.cxx | 22 ++-- panda/src/pgraph/geomNode.I | 11 ++ panda/src/pgraph/geomNode.cxx | 18 +++ panda/src/pgraph/geomNode.h | 3 + panda/src/pgraph/nodePath.I | 36 ++++++ panda/src/pgraph/nodePath.cxx | 20 ++++ panda/src/pgraph/nodePath.h | 6 + panda/src/pgraph/pandaNode.I | 54 ++++++--- panda/src/pgraph/pandaNode.cxx | 23 +++- panda/src/pgraph/pandaNode.h | 22 +++- panda/src/putil/bam.h | 3 +- panda/src/putil/collideMask.h | 22 ++++ 18 files changed, 338 insertions(+), 168 deletions(-) diff --git a/panda/src/collide/collisionLevelState.I b/panda/src/collide/collisionLevelState.I index c903889edb..0a576919d9 100644 --- a/panda/src/collide/collisionLevelState.I +++ b/panda/src/collide/collisionLevelState.I @@ -39,7 +39,6 @@ CollisionLevelState(const CollisionLevelState &parent, PandaNode *child) : _node_path(parent._node_path, child), _colliders(parent._colliders), _current(parent._current), - _colliders_with_geom(parent._colliders_with_geom), _local_bounds(parent._local_bounds) { } @@ -88,19 +87,6 @@ has_collider(int n) const { 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 // Access: Public @@ -111,31 +97,6 @@ has_any_collider() const { 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 // Access: Public diff --git a/panda/src/collide/collisionLevelState.cxx b/panda/src/collide/collisionLevelState.cxx index 4a1d88d955..164d7df5fd 100644 --- a/panda/src/collide/collisionLevelState.cxx +++ b/panda/src/collide/collisionLevelState.cxx @@ -31,7 +31,6 @@ clear() { _local_bounds.clear(); _parent_bounds.clear(); _current = 0; - _colliders_with_geom = 0; } //////////////////////////////////////////////////////////////////// @@ -89,9 +88,6 @@ prepare_collider(const ColliderDef &def) { _current |= get_mask(index); - if (def._node->get_collide_geom()) { - _colliders_with_geom |= get_mask(index); - } _parent_bounds = _local_bounds; } diff --git a/panda/src/collide/collisionLevelState.h b/panda/src/collide/collisionLevelState.h index ba7131f418..c6743cfb11 100644 --- a/panda/src/collide/collisionLevelState.h +++ b/panda/src/collide/collisionLevelState.h @@ -63,11 +63,7 @@ public: INLINE int get_num_colliders() 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_collide_geom() const; - - INLINE void reached_collision_node(); INLINE CollisionSolid *get_collider(int n) const; INLINE CollisionNode *get_collider_node(int n) const; @@ -92,7 +88,6 @@ private: typedef PTA(ColliderDef) Colliders; Colliders _colliders; ColliderMask _current; - ColliderMask _colliders_with_geom; typedef PTA(CPT(GeometricBoundingVolume)) BoundingVolumes; BoundingVolumes _local_bounds; diff --git a/panda/src/collide/collisionNode.I b/panda/src/collide/collisionNode.I index f091747bd5..88d0e257c2 100644 --- a/panda/src/collide/collisionNode.I +++ b/panda/src/collide/collisionNode.I @@ -29,20 +29,6 @@ set_collide_mask(CollideMask 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 // Access: Published @@ -54,12 +40,8 @@ set_from_collide_mask(CollideMask mask) { //////////////////////////////////////////////////////////////////// INLINE void CollisionNode:: 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:: 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(); 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; +} diff --git a/panda/src/collide/collisionNode.cxx b/panda/src/collide/collisionNode.cxx index 2c85fa8a08..11388c2ba5 100644 --- a/panda/src/collide/collisionNode.cxx +++ b/panda/src/collide/collisionNode.cxx @@ -30,6 +30,7 @@ #include "datagramIterator.h" #include "bamReader.h" #include "bamWriter.h" +#include "clockObject.h" TypeHandle CollisionNode::_type_handle; @@ -42,12 +43,14 @@ TypeHandle CollisionNode::_type_handle; CollisionNode:: CollisionNode(const string &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. 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 ©) : PandaNode(copy), _from_collide_mask(copy._from_collide_mask), - _into_collide_mask(copy._into_collide_mask), - _flags(copy._flags), _solids(copy._solids) { } @@ -167,6 +168,22 @@ combine_with(PandaNode *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 // Access: Public, Virtual @@ -260,22 +277,74 @@ output(ostream &out) const { 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(_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()); - _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(); + } } diff --git a/panda/src/collide/collisionNode.h b/panda/src/collide/collisionNode.h index 454f7d3555..c3604f073a 100644 --- a/panda/src/collide/collisionNode.h +++ b/panda/src/collide/collisionNode.h @@ -47,6 +47,7 @@ public: virtual bool preserve_name() const; virtual void xform(const LMatrix4f &mat); virtual PandaNode *combine_with(PandaNode *other); + virtual CollideMask get_legal_collide_mask() const; virtual bool has_cull_callback() const; virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data); @@ -55,13 +56,13 @@ public: PUBLISHED: 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 CollideMask get_from_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 int get_num_solids() const; @@ -70,8 +71,9 @@ PUBLISHED: INLINE void remove_solid(int n); INLINE int add_solid(CollisionSolid *solid); + INLINE static CollideMask get_default_collide_mask(); + protected: - virtual BoundingVolume *recompute_bound(); virtual BoundingVolume *recompute_internal_bound(); private: @@ -81,13 +83,7 @@ private: // traversal will take place in App only. Perhaps we will revisit // this later. 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; Solids _solids; diff --git a/panda/src/collide/collisionTraverser.cxx b/panda/src/collide/collisionTraverser.cxx index 030ed6f25f..45a57bb9bc 100644 --- a/panda/src/collide/collisionTraverser.cxx +++ b/panda/src/collide/collisionTraverser.cxx @@ -513,8 +513,6 @@ r_traverse(CollisionLevelState &level_state) { PandaNode *node = level_state.node(); if (node->is_exact_type(CollisionNode::get_class_type())) { - level_state.reached_collision_node(); - CollisionNode *cnode; DCAST_INTO_V(cnode, node); 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 if (collide_cat.is_spam()) { collide_cat.spam() @@ -573,15 +571,19 @@ r_traverse(CollisionLevelState &level_state) { int num_colliders = level_state.get_num_colliders(); 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_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); + } } } } diff --git a/panda/src/pgraph/geomNode.I b/panda/src/pgraph/geomNode.I index b080ff7ffb..99d16c775e 100644 --- a/panda/src/pgraph/geomNode.I +++ b/panda/src/pgraph/geomNode.I @@ -167,3 +167,14 @@ remove_all_geoms() { cdata->_geoms.clear(); 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; +} diff --git a/panda/src/pgraph/geomNode.cxx b/panda/src/pgraph/geomNode.cxx index 9f2de7791a..25da833c2a 100644 --- a/panda/src/pgraph/geomNode.cxx +++ b/panda/src/pgraph/geomNode.cxx @@ -124,6 +124,8 @@ GeomNode:: GeomNode(const string &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; } +//////////////////////////////////////////////////////////////////// +// 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 // Access: Published diff --git a/panda/src/pgraph/geomNode.h b/panda/src/pgraph/geomNode.h index fca3afcb44..35260997ea 100644 --- a/panda/src/pgraph/geomNode.h +++ b/panda/src/pgraph/geomNode.h @@ -53,6 +53,7 @@ public: calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any, const TransformState *transform) const; + virtual CollideMask get_legal_collide_mask() const; PUBLISHED: INLINE int get_num_geoms() const; @@ -69,6 +70,8 @@ PUBLISHED: void write_geoms(ostream &out, int indent_level) const; void write_verbose(ostream &out, int indent_level) const; + INLINE static CollideMask get_default_collide_mask(); + public: virtual void output(ostream &out) const; diff --git a/panda/src/pgraph/nodePath.I b/panda/src/pgraph/nodePath.I index 4235b183cd..c8b382e5c7 100644 --- a/panda/src/pgraph/nodePath.I +++ b/panda/src/pgraph/nodePath.I @@ -1453,6 +1453,42 @@ is_stashed() const { 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 == // Access: Published diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 1641d6df71..4a5e907212 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/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 // Access: Private diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index ae71695f1a..1414106ff5 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -647,6 +647,9 @@ PUBLISHED: INLINE bool is_stashed() 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 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_set_collide_mask(PandaNode *node, + CollideMask and_mask, CollideMask or_mask); + typedef pset Textures; Texture *r_find_texture(PandaNode *node, const RenderState *state, const GlobPattern &glob) const; diff --git a/panda/src/pgraph/pandaNode.I b/panda/src/pgraph/pandaNode.I index 5236646a5c..769f0d0edd 100644 --- a/panda/src/pgraph/pandaNode.I +++ b/panda/src/pgraph/pandaNode.I @@ -120,6 +120,7 @@ CData() { _transform = TransformState::make_identity(); _prev_transform = TransformState::make_identity(); _draw_mask = DrawMask::all_on(); + _into_collide_mask = CollideMask::all_off(); _net_collide_mask = CollideMask::all_off(); _fixed_internal_bound = false; } @@ -141,6 +142,7 @@ CData(const PandaNode::CData ©) : _prev_transform(copy._prev_transform), _tag_data(copy._tag_data), _draw_mask(copy._draw_mask), + _into_collide_mask(copy._into_collide_mask), _fixed_internal_bound(copy._fixed_internal_bound) { _net_collide_mask = CollideMask::all_off(); @@ -812,6 +814,45 @@ get_draw_mask() const { 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 // Access: Published @@ -897,19 +938,6 @@ changed_internal_bound() { 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 // Access: Public diff --git a/panda/src/pgraph/pandaNode.cxx b/panda/src/pgraph/pandaNode.cxx index df6402e3f9..3168e93199 100644 --- a/panda/src/pgraph/pandaNode.cxx +++ b/panda/src/pgraph/pandaNode.cxx @@ -77,6 +77,7 @@ write_datagram(BamWriter *manager, Datagram &dg) const { manager->write_pointer(dg, _transform); dg.add_uint32(_draw_mask.get_word()); + dg.add_uint32(_into_collide_mask.get_word()); write_up_list(_up, manager, dg); write_down_list(_down, manager, dg); @@ -142,6 +143,9 @@ fillin(DatagramIterator &scan, BamReader *manager) { manager->read_pointer(scan); _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. fillin_up_list(_up, scan, manager); @@ -383,6 +387,7 @@ PandaNode(const PandaNode ©) : cdata->_prev_transform = copy_cdata->_prev_transform; cdata->_tag_data = copy_cdata->_tag_data; 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; } @@ -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 // Access: Published, Virtual @@ -1382,7 +1403,7 @@ recompute_bound() { // Also, recompute the net_collide_mask bits while we do this. 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 // of our child bounding volumes. diff --git a/panda/src/pgraph/pandaNode.h b/panda/src/pgraph/pandaNode.h index 4bfcf81896..fe792a8792 100644 --- a/panda/src/pgraph/pandaNode.h +++ b/panda/src/pgraph/pandaNode.h @@ -164,6 +164,10 @@ PUBLISHED: INLINE void set_draw_mask(DrawMask mask); 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; virtual void output(ostream &out) const; @@ -320,12 +324,18 @@ private: // This is the draw_mask of this particular node. 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; bool _fixed_internal_bound; diff --git a/panda/src/putil/bam.h b/panda/src/putil/bam.h index 185710d07e..e710abb721 100644 --- a/panda/src/putil/bam.h +++ b/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 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 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 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 12 on 09/22/04 to add PandaNode::into_collide_mask. #endif diff --git a/panda/src/putil/collideMask.h b/panda/src/putil/collideMask.h index 458be24bb9..585390f411 100644 --- a/panda/src/putil/collideMask.h +++ b/panda/src/putil/collideMask.h @@ -34,5 +34,27 @@ 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