Browse Source

*** empty log message ***

David Rose 24 years ago
parent
commit
96fb0b9335

+ 10 - 9
panda/src/cull/cullTraverser.cxx

@@ -19,20 +19,18 @@
 #include <pruneTransition.h>
 #include <pruneTransition.h>
 #include <transformTransition.h>
 #include <transformTransition.h>
 #include <nodeTransitionWrapper.h>
 #include <nodeTransitionWrapper.h>
+#include <switchNode.h>
 #include <indent.h>
 #include <indent.h>
 #include <config_sgraphutil.h>  // for implicit_app_traversal
 #include <config_sgraphutil.h>  // for implicit_app_traversal
 #include <config_sgattrib.h>    // for support_decals
 #include <config_sgattrib.h>    // for support_decals
 #include <string_utils.h>
 #include <string_utils.h>
+#include <pStatTimer.h>
 
 
 TypeHandle CullTraverser::_type_handle;
 TypeHandle CullTraverser::_type_handle;
 
 
-#ifdef DO_PSTATS
-#include <pStatTimer.h>
-
-PStatCollector CullTraverser::_cull_pcollector =
-  PStatCollector("Cull", RGBColorf(0,1,0), 10);
-PStatCollector CullTraverser::_draw_pcollector =
-  PStatCollector("Draw", RGBColorf(1,0,0), 20);
+#ifndef CPPPARSER
+PStatCollector CullTraverser::_cull_pcollector("Cull", RGBColorf(0,1,0), 10);
+PStatCollector CullTraverser::_draw_pcollector("Draw", RGBColorf(1,0,0), 20);
 #endif
 #endif
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -173,10 +171,8 @@ void CullTraverser::
 traverse(Node *root, 
 traverse(Node *root, 
 	 const AllAttributesWrapper &initial_state,
 	 const AllAttributesWrapper &initial_state,
 	 const AllTransitionsWrapper &net_trans) {
 	 const AllTransitionsWrapper &net_trans) {
-#ifdef DO_PSTATS
   // Statistics
   // Statistics
   PStatTimer timer(_cull_pcollector);
   PStatTimer timer(_cull_pcollector);
-#endif
 
 
   if (cull_cat.is_debug()) {
   if (cull_cat.is_debug()) {
     cull_cat.debug()
     cull_cat.debug()
@@ -667,6 +663,11 @@ forward_arc(NodeRelation *arc, NullTransitionWrapper &,
   }
   }
 #endif
 #endif
 
 
+  if (node->is_of_type(SwitchNode::get_class_type())) {
+    SwitchNode *swnode = DCAST(SwitchNode, node);
+    swnode->compute_switch(this);
+  }
+
   return true;
   return true;
 }
 }
 
 

+ 3 - 8
panda/src/cull/cullTraverser.h

@@ -16,10 +16,7 @@
 #include <traverserVisitor.h>
 #include <traverserVisitor.h>
 #include <nullTransitionWrapper.h>
 #include <nullTransitionWrapper.h>
 #include <nullAttributeWrapper.h>
 #include <nullAttributeWrapper.h>
-
-#ifdef DO_PSTATS
 #include <pStatCollector.h>
 #include <pStatCollector.h>
-#endif
 
 
 #include <list>
 #include <list>
 #include <set>
 #include <set>
@@ -122,11 +119,9 @@ private:
   UpdateSeq _now;
   UpdateSeq _now;
 
 
 public:
 public:
-  #ifdef DO_PSTATS
-	  // Statistics
-	  static PStatCollector _cull_pcollector;
-	  static PStatCollector _draw_pcollector;
-  #endif
+  // Statistics
+  static PStatCollector _cull_pcollector;
+  static PStatCollector _draw_pcollector;
   
   
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 4 - 2
panda/src/sgraph/Sources.pp

@@ -13,14 +13,16 @@
     modelNode.h modelRoot.I modelRoot.cxx modelRoot.h \
     modelNode.h modelRoot.I modelRoot.cxx modelRoot.h \
     planeNode.I planeNode.cxx \
     planeNode.I planeNode.cxx \
     planeNode.h projectionNode.I projectionNode.cxx projectionNode.h \
     planeNode.h projectionNode.I projectionNode.cxx projectionNode.h \
-    renderTraverser.I renderTraverser.cxx renderTraverser.h
+    renderTraverser.I renderTraverser.cxx renderTraverser.h \
+    switchNode.I switchNode.cxx switchNode.h
 
 
   #define INSTALL_HEADERS \
   #define INSTALL_HEADERS \
     camera.I camera.h config_sgraph.h \
     camera.I camera.h config_sgraph.h \
     geomNode.I geomNode.h geomTransformer.I \
     geomNode.I geomNode.h geomTransformer.I \
     geomTransformer.h modelNode.I modelNode.h modelRoot.I \
     geomTransformer.h modelNode.I modelNode.h modelRoot.I \
     modelRoot.h planeNode.I planeNode.h projectionNode.I \
     modelRoot.h planeNode.I planeNode.h projectionNode.I \
-    projectionNode.h renderTraverser.I renderTraverser.h
+    projectionNode.h renderTraverser.I renderTraverser.h \
+    switchNode.I switchNode.h
 
 
   #define IGATESCAN all
   #define IGATESCAN all
 
 

+ 2 - 0
panda/src/sgraph/config_sgraph.cxx

@@ -11,6 +11,7 @@
 #include "modelNode.h"
 #include "modelNode.h"
 #include "modelRoot.h"
 #include "modelRoot.h"
 #include "projectionNode.h"
 #include "projectionNode.h"
+#include "switchNode.h"
 
 
 #include <dconfig.h>
 #include <dconfig.h>
 #include <config_graph.h>
 #include <config_graph.h>
@@ -47,6 +48,7 @@ init_libsgraph() {
   ModelNode::init_type();
   ModelNode::init_type();
   ModelRoot::init_type();
   ModelRoot::init_type();
   ProjectionNode::init_type();
   ProjectionNode::init_type();
+  SwitchNode::init_type();
 
 
   //Registration of writeable object's creation
   //Registration of writeable object's creation
   //functions with BamReader's factory
   //functions with BamReader's factory

+ 37 - 0
panda/src/sgraph/switchNode.I

@@ -0,0 +1,37 @@
+// Filename: switchNode.I
+// Created by:  drose (15May01)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: SwitchNode::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE SwitchNode::
+SwitchNode(const string &name) : 
+  NamedNode(name) 
+{ 
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SwitchNode::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE SwitchNode::
+SwitchNode(const SwitchNode &copy) :
+  NamedNode(copy)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SwitchNode::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void SwitchNode::
+operator = (const SwitchNode &copy) {
+  NamedNode::operator = (copy);
+}

+ 8 - 0
panda/src/sgraph/switchNode.cxx

@@ -0,0 +1,8 @@
+// Filename: switchNode.cxx
+// Created by:  drose (15May01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "switchNode.h"
+
+TypeHandle SwitchNode::_type_handle;

+ 58 - 0
panda/src/sgraph/switchNode.h

@@ -0,0 +1,58 @@
+// Filename: switchNode.h
+// Created by:  drose (15May01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef SWITCHNODE_H
+#define SWITCHNODE_H
+
+#include <pandabase.h>
+
+#include <namedNode.h>
+
+class RenderTraverser;
+
+////////////////////////////////////////////////////////////////////
+//       Class : SwitchNode
+// Description : A base class for nodes that may choose to render only
+//               some subset of their children, based on some internal
+//               criteria.
+//
+//               This is an abstract base class, and is only
+//               interface; it is defined in this directory so that
+//               FrustumCullTraverser can access it.  All of the
+//               implementations of this class are defined in the
+//               switchnode directory.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA SwitchNode : public NamedNode {
+PUBLISHED:
+  INLINE SwitchNode(const string &name = "");
+  INLINE SwitchNode(const SwitchNode &copy);
+  INLINE void operator = (const SwitchNode &copy);
+
+public:
+  virtual void compute_switch(RenderTraverser *trav)=0;
+
+  virtual bool is_child_visible(TypeHandle type, int index)=0;
+
+public:
+  static TypeHandle get_class_type() {
+      return _type_handle;
+  }
+  static void init_type() {
+    NamedNode::init_type();
+    register_type( _type_handle, "SwitchNode",
+                NamedNode::get_class_type() );
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle		_type_handle;
+};
+
+#include "switchNode.I"
+
+#endif

+ 8 - 6
panda/src/sgraphutil/directRenderTraverser.cxx

@@ -21,16 +21,16 @@
 #include <allTransitionsWrapper.h>
 #include <allTransitionsWrapper.h>
 #include <transformTransition.h>
 #include <transformTransition.h>
 #include <nodeTransitionWrapper.h>
 #include <nodeTransitionWrapper.h>
+#include <switchNode.h>
 #include <decalTransition.h>
 #include <decalTransition.h>
 #include <decalAttribute.h>
 #include <decalAttribute.h>
 #include <config_sgattrib.h>   // for support_decals
 #include <config_sgattrib.h>   // for support_decals
+#include <pStatTimer.h>
 
 
 TypeHandle DirectRenderTraverser::_type_handle;
 TypeHandle DirectRenderTraverser::_type_handle;
 
 
-#ifdef DO_PSTATS
-#include <pStatTimer.h>
-PStatCollector DirectRenderTraverser::_draw_pcollector =
-  PStatCollector("Draw", RGBColorf(1,0,0), 20);
+#ifndef CPPPARSER
+PStatCollector DirectRenderTraverser::_draw_pcollector("Draw", RGBColorf(1,0,0), 20);
 #endif
 #endif
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -66,10 +66,8 @@ void DirectRenderTraverser::
 traverse(Node *root, 
 traverse(Node *root, 
 	 const AllAttributesWrapper &initial_state,
 	 const AllAttributesWrapper &initial_state,
 	 const AllTransitionsWrapper &net_trans) {
 	 const AllTransitionsWrapper &net_trans) {
-#ifdef DO_PSTATS
   // Statistics
   // Statistics
   PStatTimer timer(_draw_pcollector);
   PStatTimer timer(_draw_pcollector);
-#endif
 
 
   AllAttributesWrapper render_state;
   AllAttributesWrapper render_state;
   render_state.apply_from(initial_state, net_trans);
   render_state.apply_from(initial_state, net_trans);
@@ -177,6 +175,10 @@ reached_node(Node *node, AllAttributesWrapper &render_state,
     } else {
     } else {
       geom->draw(_gsg);
       geom->draw(_gsg);
     }
     }
+
+  } else if (node->is_of_type(SwitchNode::get_class_type())) {
+    SwitchNode *swnode = DCAST(SwitchNode, node);
+    swnode->compute_switch(this);
   }
   }
   
   
   return true;
   return true;

+ 2 - 7
panda/src/sgraphutil/directRenderTraverser.h

@@ -18,10 +18,7 @@
 #include <geometricBoundingVolume.h>
 #include <geometricBoundingVolume.h>
 #include <lmatrix.h>
 #include <lmatrix.h>
 #include <pointerTo.h>
 #include <pointerTo.h>
-
-#ifdef DO_PSTATS
 #include <pStatCollector.h>
 #include <pStatCollector.h>
-#endif
 
 
 class Node;
 class Node;
 class GraphicsStateGuardian;
 class GraphicsStateGuardian;
@@ -63,10 +60,8 @@ public:
 		    const DirectRenderLevelState &level_state);
 		    const DirectRenderLevelState &level_state);
 
 
 private:
 private:
-  #ifdef DO_PSTATS
-    // Statistics
-    static PStatCollector _draw_pcollector;
-  #endif
+  // Statistics
+  static PStatCollector _draw_pcollector;
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 23 - 4
panda/src/sgraphutil/frustumCullTraverser.I

@@ -46,12 +46,14 @@ FrustumCullTraverser(ArcChain &arc_chain, Node *root,
     local_frustum = DCAST(GeometricBoundingVolume, _view_frustum->make_copy());
     local_frustum = DCAST(GeometricBoundingVolume, _view_frustum->make_copy());
     local_frustum->xform(rel_from_camera);
     local_frustum->xform(rel_from_camera);
 
 
+#ifndef NDEBUG
     if (sgraphutil_cat.is_spam()) {
     if (sgraphutil_cat.is_spam()) {
       sgraphutil_cat.spam()
       sgraphutil_cat.spam()
 	<< "Beginning frustum cull, frustum is: " << *local_frustum << "\n"
 	<< "Beginning frustum cull, frustum is: " << *local_frustum << "\n"
 	<< "Transform is:\n";
 	<< "Transform is:\n";
       rel_from_camera.write(sgraphutil_cat.spam(false), 2);
       rel_from_camera.write(sgraphutil_cat.spam(false), 2);
     }
     }
+#endif
   }
   }
 
 
   bool needs_top_node = !_arc_chain.has_node();
   bool needs_top_node = !_arc_chain.has_node();
@@ -114,11 +116,13 @@ traverse(NodeRelation *arc, AttributeWrapper render_state,
 	int result = local_frustum->contains(arc_gbv);
 	int result = local_frustum->contains(arc_gbv);
 	if (result == BoundingVolume::IF_no_intersection) {
 	if (result == BoundingVolume::IF_no_intersection) {
 	  // No intersection at all.  Cull.
 	  // No intersection at all.  Cull.
+#ifndef NDEBUG	
 	  if (sgraphutil_cat.is_spam() && !arc_volume.is_empty()) {
 	  if (sgraphutil_cat.is_spam() && !arc_volume.is_empty()) {
 	    sgraphutil_cat.spam()
 	    sgraphutil_cat.spam()
 	      << "Culling " << *arc->get_child() << " with volume "
 	      << "Culling " << *arc->get_child() << " with volume "
 	      << arc_volume << "\n";
 	      << arc_volume << "\n";
 	  }
 	  }
+#endif
 
 
 	  /*
 	  /*
 	  if (fake_view_frustum_cull) {
 	  if (fake_view_frustum_cull) {
@@ -183,13 +187,15 @@ traverse(NodeRelation *arc, AttributeWrapper render_state,
 	    // be.
 	    // be.
 	    nassertv(local_frustum != (GeometricBoundingVolume *)NULL);
 	    nassertv(local_frustum != (GeometricBoundingVolume *)NULL);
 	    local_frustum->xform(tt->get_matrix());
 	    local_frustum->xform(tt->get_matrix());
-	    
+
+#ifndef NDEBUG	    
 	    if (sgraphutil_cat.is_spam()) {
 	    if (sgraphutil_cat.is_spam()) {
 	      sgraphutil_cat.spam()
 	      sgraphutil_cat.spam()
 		<< "Transforming frustum into local space of " << *arc << ": " << *local_frustum << "\n"
 		<< "Transforming frustum into local space of " << *arc << ": " << *local_frustum << "\n"
 		<< "Transform is:\n";
 		<< "Transform is:\n";
 	      tt->get_matrix().write(sgraphutil_cat.spam(false), 2);
 	      tt->get_matrix().write(sgraphutil_cat.spam(false), 2);
 	    }
 	    }
+#endif
 	  }
 	  }
 	}
 	}
       }
       }
@@ -237,9 +243,22 @@ traverse(Node *node, AttributeWrapper &render_state, LevelState &level_state,
       node->find_connection(_graph_type).get_down();
       node->find_connection(_graph_type).get_down();
 
 
     // Now visit each of the children in turn.
     // Now visit each of the children in turn.
-    DownRelationPointers::const_iterator drpi;
-    for (drpi = drp.begin(); drpi != drp.end(); ++drpi) {
-      traverse(*drpi, render_state, level_state, local_frustum, all_in);
+    if (node->is_of_type(SwitchNode::get_class_type())) {
+      SwitchNode *swnode = DCAST(SwitchNode, node);
+      // Presumably, the visitor called compute_switch() on the
+      // SwitchNode during the reached_node() call, above.  We can't
+      // call it directly since we don't have enough information.
+      size_t i = 0;
+      for (i = 0; i < drp.size(); i++) {
+	if (swnode->is_child_visible(_graph_type, i)) {
+	  traverse(drp[i], render_state, level_state, local_frustum, all_in);
+	}
+      }
+    } else {
+      DownRelationPointers::const_iterator drpi;
+      for (drpi = drp.begin(); drpi != drp.end(); ++drpi) {
+	traverse(*drpi, render_state, level_state, local_frustum, all_in);
+      }
     }
     }
   }
   }
 }
 }

+ 1 - 0
panda/src/sgraphutil/frustumCullTraverser.h

@@ -9,6 +9,7 @@
 #include <pandabase.h>
 #include <pandabase.h>
 
 
 #include <node.h>
 #include <node.h>
+#include <switchNode.h>
 #include <nodeRelation.h>
 #include <nodeRelation.h>
 #include <typedObject.h>
 #include <typedObject.h>
 #include <geometricBoundingVolume.h>
 #include <geometricBoundingVolume.h>

+ 2 - 2
panda/src/switchnode/LODNode.I

@@ -16,7 +16,7 @@
 //  Description: 
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE LODNode::
 INLINE LODNode::
-LODNode(const string &name) : NamedNode(name) {
+LODNode(const string &name) : SwitchNodeOne(name) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -26,7 +26,7 @@ LODNode(const string &name) : NamedNode(name) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE LODNode::
 INLINE LODNode::
 LODNode(const LODNode &copy) : 
 LODNode(const LODNode &copy) : 
-  NamedNode(copy),
+  SwitchNodeOne(copy),
   _lod(copy._lod)
   _lod(copy._lod)
 {
 {
 }
 }

+ 14 - 53
panda/src/switchnode/LODNode.cxx

@@ -57,20 +57,23 @@ xform(const LMatrix4f &mat) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void LODNode::
 void LODNode::
 output(ostream &out) const {
 output(ostream &out) const {
-  NamedNode::output(out);
+  SwitchNodeOne::output(out);
   out << " ";
   out << " ";
   _lod.output(out);
   _lod.output(out);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: sub_render
-//       Access:
-//  Description:
+//     Function: LODNode::compute_switch
+//       Access: Public, Virtual
+//  Description: Computes the node's switching properties, to decide
+//               what children should be visible in the given
+//               rendering situation.
+//
+//               In the case of an LODNode, this decides which child
+//               is visible based on the distance from the camera.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-bool LODNode::
-sub_render(const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans,
-	   RenderTraverser *trav) {
-
+void LODNode::
+compute_switch(RenderTraverser *trav) {
   GraphicsStateGuardian *gsg = trav->get_gsg();
   GraphicsStateGuardian *gsg = trav->get_gsg();
 
 
   // Get the current camera position from the gsg
   // Get the current camera position from the gsg
@@ -92,49 +95,7 @@ sub_render(const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans,
   
   
   // Determine which child to traverse
   // Determine which child to traverse
   int index = _lod.compute_child(camera_pos, LOD_pos);
   int index = _lod.compute_child(camera_pos, LOD_pos);
-  int num_children = get_num_children(RenderRelation::get_class_type());
-  if (index >= 0 && index < num_children) {
-    NodeRelation *arc = get_child(RenderRelation::get_class_type(), index);
-
-    if (switchnode_cat.is_debug()) {
-      switchnode_cat.debug()
-	<< "Selecting child " << index << " of " << *this << ": "
-	<< *arc->get_child() << "\n";
-    }
-
-    // We have to be sure to pick up any state transitions on the arc
-    // itself.
-    AllTransitionsWrapper arc_trans;
-    arc_trans.extract_from(arc);
-
-    AllTransitionsWrapper new_trans(trans);
-    new_trans.compose_in_place(arc_trans);
-
-    // Now render everything from this node and below.
-    gsg->render_subgraph(trav, arc->get_child(), attrib, new_trans);
-
-  } else {
-    if (switchnode_cat.is_debug()) {
-      switchnode_cat.debug()
-	<< "Cannot select child " << index << " of " << *this << "; only "
-	<< num_children << " children.\n";
-    }
-  }
-
-  // Short circuit the rest of the render pass below this node
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: LODNode::has_sub_render
-//       Access: Public, Virtual
-//  Description: Should be redefined to return true if the function
-//               sub_render(), above, expects to be called during
-//               traversal.
-////////////////////////////////////////////////////////////////////
-bool LODNode::
-has_sub_render() const {
-  return true;
+  select_child(index);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -155,7 +116,7 @@ register_with_read_factory() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void LODNode::
 void LODNode::
 write_datagram(BamWriter *manager, Datagram &me) {
 write_datagram(BamWriter *manager, Datagram &me) {
-  NamedNode::write_datagram(manager, me);
+  SwitchNodeOne::write_datagram(manager, me);
   _lod.write_datagram(me);
   _lod.write_datagram(me);
 }
 }
 
 
@@ -187,6 +148,6 @@ make_LODNode(const FactoryParams &params) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void LODNode::
 void LODNode::
 fillin(DatagramIterator &scan, BamReader *manager) {
 fillin(DatagramIterator &scan, BamReader *manager) {
-  NamedNode::fillin(scan, manager);
+  SwitchNodeOne::fillin(scan, manager);
   _lod.read_datagram(scan);
   _lod.read_datagram(scan);
 }
 }

+ 9 - 19
panda/src/switchnode/LODNode.h

@@ -2,27 +2,21 @@
 // Created by:  mike (09Jan97)
 // Created by:  mike (09Jan97)
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//
+
 #ifndef LODNODE_H
 #ifndef LODNODE_H
 #define LODNODE_H
 #define LODNODE_H
-//
-////////////////////////////////////////////////////////////////////
-// Includes
-////////////////////////////////////////////////////////////////////
+
 #include <pandabase.h>
 #include <pandabase.h>
 
 
-#include <namedNode.h>
-#include <LOD.h>
+#include "switchNodeOne.h"
 
 
-////////////////////////////////////////////////////////////////////
-// Defines
-////////////////////////////////////////////////////////////////////
+#include <LOD.h>
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : LODNode
 //       Class : LODNode
 // Description : A node that implements level of detail
 // Description : A node that implements level of detail
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA LODNode : public NamedNode {
+class EXPCL_PANDA LODNode : public SwitchNodeOne {
 PUBLISHED:
 PUBLISHED:
   INLINE LODNode(const string &name = "");
   INLINE LODNode(const string &name = "");
 
 
@@ -48,11 +42,7 @@ PUBLISHED:
 
 
 public:
 public:
   virtual void output(ostream &out) const;
   virtual void output(ostream &out) const;
-
-  virtual bool sub_render(const AllAttributesWrapper &attrib,
-			  AllTransitionsWrapper &trans,
-			  RenderTraverser *trav);
-  virtual bool has_sub_render() const;
+  virtual void compute_switch(RenderTraverser *trav);
 
 
 public:
 public:
   static void register_with_read_factory();
   static void register_with_read_factory();
@@ -64,16 +54,16 @@ protected:
   void fillin(DatagramIterator &scan, BamReader *manager);
   void fillin(DatagramIterator &scan, BamReader *manager);
 
 
 public:
 public:
-  LOD    			_lod;
+  LOD _lod;
 
 
 public:
 public:
   static TypeHandle get_class_type( void ) {
   static TypeHandle get_class_type( void ) {
       return _type_handle;
       return _type_handle;
   }
   }
   static void init_type( void ) {
   static void init_type( void ) {
-    NamedNode::init_type();
+    SwitchNodeOne::init_type();
     register_type( _type_handle, "LODNode",
     register_type( _type_handle, "LODNode",
-                NamedNode::get_class_type() );
+                SwitchNodeOne::get_class_type() );
   }
   }
   virtual TypeHandle get_type( void ) const {
   virtual TypeHandle get_type( void ) const {
     return get_class_type();
     return get_class_type();

+ 4 - 2
panda/src/switchnode/Sources.pp

@@ -9,10 +9,12 @@
 
 
   #define SOURCES \
   #define SOURCES \
     LODNode.I LODNode.cxx LODNode.h config_switchnode.cxx \
     LODNode.I LODNode.cxx LODNode.h config_switchnode.cxx \
-    config_switchnode.h sequenceNode.cxx sequenceNode.h
+    config_switchnode.h sequenceNode.cxx sequenceNode.h \
+    switchNodeOne.I switchNodeOne.cxx switchNodeOne.h
 
 
   #define INSTALL_HEADERS \
   #define INSTALL_HEADERS \
-    LODNode.I LODNode.h sequenceNode.h
+    config_switchnode.h LODNode.I LODNode.h sequenceNode.h \
+    switchNodeOne.I switchNodeOne.h
 
 
   #define IGATESCAN all
   #define IGATESCAN all
 
 

+ 14 - 54
panda/src/switchnode/sequenceNode.cxx

@@ -30,7 +30,7 @@ TypeHandle SequenceNode::_type_handle;
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 SequenceNode::
 SequenceNode::
 SequenceNode(const string &initial_name) :
 SequenceNode(const string &initial_name) :
-  NamedNode(initial_name), TimedCycle()
+  SwitchNodeOne(initial_name), TimedCycle()
 {
 {
 }
 }
 
 
@@ -41,7 +41,7 @@ SequenceNode(const string &initial_name) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 SequenceNode::
 SequenceNode::
 SequenceNode(float switch_time, const string &initial_name) :
 SequenceNode(float switch_time, const string &initial_name) :
-   NamedNode(initial_name), TimedCycle(switch_time, 0)
+   SwitchNodeOne(initial_name), TimedCycle(switch_time, 0)
 {
 {
 }
 }
 
 
@@ -71,62 +71,22 @@ make_copy() const {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: SequenceNode::sub_render
+//     Function: SequenceNode::compute_switch
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description:
+//  Description: Computes the node's switching properties, to decide
+//               what children should be visible in the given
+//               rendering situation.
+//
+//               In the case of a SequenceNode, this simply selects
+//               the appropriate child based on the elapsed time.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-bool SequenceNode::
-sub_render(const AllAttributesWrapper &attrib, AllTransitionsWrapper &trans,
-	   RenderTraverser *trav) {
-  GraphicsStateGuardian *gsg = trav->get_gsg();
-
+void SequenceNode::
+compute_switch(RenderTraverser *) {
   // Determine which child to traverse
   // Determine which child to traverse
   int num_children = get_num_children(RenderRelation::get_class_type());
   int num_children = get_num_children(RenderRelation::get_class_type());
   set_element_count(num_children);
   set_element_count(num_children);
   int index = next_element();
   int index = next_element();
-  if (index >= 0 && index < num_children) {
-    NodeRelation *arc = get_child(RenderRelation::get_class_type(), index);
-
-    if (switchnode_cat.is_debug()) {
-      switchnode_cat.debug()
-	<< "Selecting child " << index << " of " << *this << ": "
-	<< *arc->get_child() << "\n";
-    }
-
-    // We have to be sure to pick up any state transitions on the arc
-    // itself.
-    AllTransitionsWrapper arc_trans;
-    arc_trans.extract_from(arc);
-
-    AllTransitionsWrapper new_trans(trans);
-    new_trans.compose_in_place(arc_trans);
-
-    // Now render everything from this node and below.
-    gsg->render_subgraph(trav, arc->get_child(), attrib, new_trans);
-
-  } else {
-    if (switchnode_cat.is_debug()) {
-      switchnode_cat.debug()
-	<< "Cannot select child " << index << " of " << *this << "; only "
-	<< num_children << " children.\n";
-    }
-  }
-
-  // Short circuit the rest of the render pass below this node
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: SequenceNode::has_sub_render
-//       Access: Public, Virtual
-//  Description: Should be redefined to return true if the function
-//               sub_render(), above, expects to be called during
-//               traversal.
-////////////////////////////////////////////////////////////////////
-bool SequenceNode::
-has_sub_render() const 
-{
-  return true;
+  select_child(index);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -136,7 +96,7 @@ has_sub_render() const
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void SequenceNode::
 void SequenceNode::
 write_datagram(BamWriter *manager, Datagram &me) {
 write_datagram(BamWriter *manager, Datagram &me) {
-  NamedNode::write_datagram(manager, me);
+  SwitchNodeOne::write_datagram(manager, me);
   TimedCycle::write_datagram(me);
   TimedCycle::write_datagram(me);
 }
 }
 
 
@@ -149,7 +109,7 @@ write_datagram(BamWriter *manager, Datagram &me) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void SequenceNode::
 void SequenceNode::
 fillin(DatagramIterator &scan, BamReader *manager) {
 fillin(DatagramIterator &scan, BamReader *manager) {
-  NamedNode::fillin(scan, manager);
+  SwitchNodeOne::fillin(scan, manager);
   TimedCycle::fillin(scan);
   TimedCycle::fillin(scan);
 }
 }
 
 

+ 7 - 13
panda/src/switchnode/sequenceNode.h

@@ -5,13 +5,11 @@
 
 
 #ifndef SEQUENCENODE_H
 #ifndef SEQUENCENODE_H
 #define SEQUENCENODE_H
 #define SEQUENCENODE_H
-//
-////////////////////////////////////////////////////////////////////
-// Includes
-////////////////////////////////////////////////////////////////////
+
 #include <pandabase.h>
 #include <pandabase.h>
 
 
-#include <namedNode.h>
+#include "switchNodeOne.h"
+
 #include <timedCycle.h>
 #include <timedCycle.h>
 #include <pointerToArray.h>
 #include <pointerToArray.h>
 
 
@@ -21,7 +19,7 @@
 //               what node is rendered based on time
 //               what node is rendered based on time
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
-class EXPCL_PANDA SequenceNode : public NamedNode, public TimedCycle
+class EXPCL_PANDA SequenceNode : public SwitchNodeOne, public TimedCycle
 {
 {
 PUBLISHED:
 PUBLISHED:
   SequenceNode(const string &initial_name = "");
   SequenceNode(const string &initial_name = "");
@@ -31,11 +29,7 @@ PUBLISHED:
 
 
 public:
 public:
   virtual Node *make_copy() const;
   virtual Node *make_copy() const;
-
-  virtual bool sub_render(const AllAttributesWrapper &attrib,
-			  AllTransitionsWrapper &trans,
-			  RenderTraverser *trav);
-  virtual bool has_sub_render() const;
+  virtual void compute_switch(RenderTraverser *trav);
 
 
 public:
 public:
   static void register_with_read_factory();
   static void register_with_read_factory();
@@ -51,9 +45,9 @@ public:
       return _type_handle;
       return _type_handle;
   }
   }
   static void init_type( void ) {
   static void init_type( void ) {
-    NamedNode::init_type();
+    SwitchNodeOne::init_type();
     register_type( _type_handle, "SequenceNode",
     register_type( _type_handle, "SequenceNode",
-                NamedNode::get_class_type() );
+                SwitchNodeOne::get_class_type() );
   }
   }
   virtual TypeHandle get_type( void ) const {
   virtual TypeHandle get_type( void ) const {
     return get_class_type();
     return get_class_type();

+ 57 - 0
panda/src/switchnode/switchNodeOne.I

@@ -0,0 +1,57 @@
+// Filename: switchNodeOne.I
+// Created by:  drose (15May01)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: SwitchNodeOne::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE SwitchNodeOne::
+SwitchNodeOne(const string &name) : 
+  SwitchNode(name) 
+{ 
+  _selected_child_index = 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SwitchNodeOne::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE SwitchNodeOne::
+SwitchNodeOne(const SwitchNodeOne &copy) :
+  SwitchNode(copy),
+  _selected_child_index(copy._selected_child_index)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SwitchNodeOne::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void SwitchNodeOne::
+operator = (const SwitchNodeOne &copy) {
+  SwitchNode::operator = (copy);
+  _selected_child_index = copy._selected_child_index;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SwitchNodeOne::select_child
+//       Access: Public
+//  Description: Indicates the particular child which should be
+//               visible.
+////////////////////////////////////////////////////////////////////
+INLINE void SwitchNodeOne::
+select_child(int index) {
+#ifndef NDEBUG
+  if (_selected_child_index != index && switchnode_cat.is_debug()) {
+    switchnode_cat.debug()
+      << *this << " selecting child " << index << "\n";
+  }
+#endif
+  _selected_child_index = index;
+}

+ 21 - 0
panda/src/switchnode/switchNodeOne.cxx

@@ -0,0 +1,21 @@
+// Filename: switchNodeOne.cxx
+// Created by:  drose (15May01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "switchNodeOne.h"
+
+TypeHandle SwitchNodeOne::_type_handle;
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: SwitchNodeOne::is_child_visible
+//       Access: Public, Virtual
+//  Description: Returns true if the indicated child is one that
+//               should be considered visible (rendered), false if it
+//               should be suppressed.
+////////////////////////////////////////////////////////////////////
+bool SwitchNodeOne::
+is_child_visible(TypeHandle, int index) {
+  return (index == _selected_child_index);
+}

+ 58 - 0
panda/src/switchnode/switchNodeOne.h

@@ -0,0 +1,58 @@
+// Filename: switchNodeOne.h
+// Created by:  drose (15May01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef SWITCHNODEONE_H
+#define SWITCHNODEONE_H
+
+#include <pandabase.h>
+
+#include <switchNode.h>
+#include "config_switchnode.h"
+
+class RenderTraverser;
+class ArcChain;
+
+////////////////////////////////////////////////////////////////////
+//       Class : SwitchNodeOne
+// Description : A specialization on SwitchNode for the common kind of
+//               switching node that will only select one child of its
+//               several available.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA SwitchNodeOne : public SwitchNode {
+PUBLISHED:
+  INLINE SwitchNodeOne(const string &name = "");
+  INLINE SwitchNodeOne(const SwitchNodeOne &copy);
+  INLINE void operator = (const SwitchNodeOne &copy);
+
+public:
+  virtual bool is_child_visible(TypeHandle type, int index);
+
+protected:
+  INLINE void select_child(int index);
+
+private:
+  int _selected_child_index;
+
+public:
+  static TypeHandle get_class_type() {
+      return _type_handle;
+  }
+  static void init_type() {
+    SwitchNode::init_type();
+    register_type( _type_handle, "SwitchNodeOne",
+                SwitchNode::get_class_type() );
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle		_type_handle;
+};
+
+#include "switchNodeOne.I"
+
+#endif