Browse Source

*** empty log message ***

David Rose 25 years ago
parent
commit
b2a26b267d

+ 3 - 2
panda/src/egg2sg/computedVerticesMaker.cxx

@@ -195,8 +195,9 @@ add_normal(const Normald &normal, const EggMorphNormalList &morphs,
   // call to begin_new_space().
   // call to begin_new_space().
   assert(_current_vc != NULL);
   assert(_current_vc != NULL);
 
 
-  Normalf tn = LCAST(float, normal * transform);
-  int index = _current_vc->_nmap.add_value(tn, morphs, _norms);
+  Normald norm = normal * transform;
+  norm.normalize();
+  int index = _current_vc->_nmap.add_value(LCAST(float, norm), morphs, _norms);
   _current_vc->_nindex.insert(index);
   _current_vc->_nindex.insert(index);
 
 
   // Now create any morph sliders.
   // Now create any morph sliders.

+ 6 - 2
panda/src/egg2sg/eggLoader.cxx

@@ -286,7 +286,9 @@ make_nonindexed_primitive(EggPrimitive *egg_prim, NamedNode *parent,
   }
   }
   
   
   if (egg_prim->has_normal()) {
   if (egg_prim->has_normal()) {
-    bprim.set_normal(LCAST(float, egg_prim->get_normal() * mat));
+    Normald norm = egg_prim->get_normal() * mat;
+    norm.normalize();
+    bprim.set_normal(LCAST(float, norm));
   }
   }
   if (egg_prim->has_color() && !egg_false_color) {
   if (egg_prim->has_color() && !egg_false_color) {
     bprim.set_color(egg_prim->get_color());
     bprim.set_color(egg_prim->get_color());
@@ -299,7 +301,9 @@ make_nonindexed_primitive(EggPrimitive *egg_prim, NamedNode *parent,
     BuilderVertex bvert(LCAST(float, egg_vert->get_pos3() * mat));
     BuilderVertex bvert(LCAST(float, egg_vert->get_pos3() * mat));
     
     
     if (egg_vert->has_normal()) {
     if (egg_vert->has_normal()) {
-      bvert.set_normal(LCAST(float, egg_vert->get_normal() * mat));
+      Normald norm = egg_vert->get_normal() * mat;
+      norm.normalize();
+      bvert.set_normal(LCAST(float, norm));
     }
     }
     if (egg_vert->has_color() && !egg_false_color) {
     if (egg_vert->has_color() && !egg_false_color) {
       bvert.set_color(egg_vert->get_color());
       bvert.set_color(egg_vert->get_color());

+ 252 - 11
panda/src/graph/arcChain.I

@@ -6,13 +6,179 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ArcChain::ArcComponent::Constructor
 //     Function: ArcChain::ArcComponent::Constructor
 //       Access: Public
 //       Access: Public
-//  Description: 
+//  Description: Constructs an ArcComponent that references a node.
+//               This kind of ArcComponent may *only* be at the head
+//               of the chain; i.e. _next must always be NULL.
+////////////////////////////////////////////////////////////////////
+INLINE ArcChain::ArcComponent::
+ArcComponent(Node *node) :
+  _next(NULL)
+{
+  nassertv(node != (Node *)NULL);
+  _p._node = node;
+  _p._node->ref();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::ArcComponent::Constructor
+//       Access: Public
+//  Description: Constructs an ArcComponent that references an arc.
+//               This kind of ArcComponent must be in the middle or
+//               tail of the chain; it may not be at the head of the
+//               chain; i.e. _next must never be NULL.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE ArcChain::ArcComponent::
 INLINE ArcChain::ArcComponent::
 ArcComponent(NodeRelation *arc, ArcComponent *next) :
 ArcComponent(NodeRelation *arc, ArcComponent *next) :
-  _arc(arc),
   _next(next)
   _next(next)
 {
 {
+  nassertv(_next != (ArcComponent *)NULL);
+  nassertv(arc != (NodeRelation *)NULL);
+  _p._arc = arc;
+  _p._arc->ref();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::ArcComponent::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE ArcChain::ArcComponent::
+ArcComponent(const ArcComponent &copy) :
+  _next(copy._next)
+{
+  if (has_arc()) {
+    _p._arc = copy._p._arc;
+    _p._arc->ref();
+  } else {
+    _p._node = copy._p._node;
+    _p._node->ref();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::ArcComponent::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void ArcChain::ArcComponent::
+operator = (const ArcComponent &copy) {
+  _next = copy._next;
+
+  if (has_arc()) {
+    _p._arc = copy._p._arc;
+    _p._arc->ref();
+  } else {
+    _p._node = copy._p._node;
+    _p._node->ref();
+  }
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::ArcComponent::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE ArcChain::ArcComponent::
+~ArcComponent() {
+  if (has_arc()) {
+    _p._arc->unref();
+  } else {
+    _p._node->unref();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::ArcComponent::has_arc
+//       Access: Public
+//  Description: Returns true if this component stores an arc, false
+//               if it stores a node.
+////////////////////////////////////////////////////////////////////
+INLINE bool ArcChain::ArcComponent::
+has_arc() const {
+  return (_next != (ArcComponent *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::ArcComponent::get_arc
+//       Access: Public
+//  Description: Returns the arc referenced by this component.  It is
+//               an error to call this unless has_arc() has already
+//               returned true.
+////////////////////////////////////////////////////////////////////
+INLINE NodeRelation *ArcChain::ArcComponent::
+get_arc() const {
+  nassertr(has_arc(), (NodeRelation *)NULL);
+  return _p._arc;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::ArcComponent::get_node
+//       Access: Public
+//  Description: Returns the node referenced by this component.  If
+//               this component references a node (i.e. has_arc() is
+//               false), this will return that node; if the component
+//               references an arc (has_arc() is true), this will
+//               return the child node of the arc.
+////////////////////////////////////////////////////////////////////
+INLINE Node *ArcChain::ArcComponent::
+get_node() const {
+  if (has_arc()) {
+    return _p._arc->get_child();
+  } else {
+    return _p._node;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::ArcComponent::is_top_node
+//       Access: Public
+//  Description: Returns true if this component represents the top
+//               node in the chain.  This is the one component at the
+//               top of the chain that represents a node; the rest of
+//               the chain represents arcs.
+////////////////////////////////////////////////////////////////////
+INLINE bool ArcChain::ArcComponent::
+is_top_node() const {
+  return (_next == (ArcComponent *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::ArcComponent::is_top_arc
+//       Access: Public
+//  Description: Returns true if this component represents the top arc
+//               in the chain.  This is the component just below the
+//               top of the chain; the highest component in the chain
+//               that still represents an arc.
+////////////////////////////////////////////////////////////////////
+INLINE bool ArcChain::ArcComponent::
+is_top_arc() const {
+  return (_next != (ArcComponent *)NULL && _next->is_top_node());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::ArcComponent::get_next
+//       Access: Public
+//  Description: Returns the next component in the chain.
+////////////////////////////////////////////////////////////////////
+INLINE ArcChain::ArcComponent *ArcChain::ArcComponent::
+get_next() const {
+  return _next;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::ArcComponent::set_next
+//       Access: Public
+//  Description: Changes the next component in the chain.  This breaks
+//               the chain at this component and relinks it to another
+//               chain.
+////////////////////////////////////////////////////////////////////
+INLINE void ArcChain::ArcComponent::
+set_next(ArcComponent *next) {
+  nassertv(next != (ArcComponent *)NULL);
+  nassertv(_next != (ArcComponent *)NULL);
+
+  _next = next;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -37,7 +203,7 @@ ForwardIterator(ArcChain::ArcComponent *comp) : _comp(comp) {
 INLINE NodeRelation *ArcChain::ForwardIterator::
 INLINE NodeRelation *ArcChain::ForwardIterator::
 operator * () const {
 operator * () const {
   nassertr(_comp != (ArcComponent *)NULL, NULL);
   nassertr(_comp != (ArcComponent *)NULL, NULL);
-  return _comp->_arc;
+  return _comp->get_arc();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -48,7 +214,13 @@ operator * () const {
 INLINE void ArcChain::ForwardIterator::
 INLINE void ArcChain::ForwardIterator::
 operator ++() {
 operator ++() {
   nassertv(_comp != (ArcComponent *)NULL);
   nassertv(_comp != (ArcComponent *)NULL);
-  _comp = _comp->_next;
+  if (_comp->is_top_arc()) {
+    // We only visit arcs, not nodes.  When we reach the end of the
+    // list of arcs (i.e. the "top" arc), we stop.
+    _comp = (ArcComponent *)NULL;
+  } else {
+    _comp = _comp->get_next();
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -74,12 +246,29 @@ operator != (const ArcChain::ForwardIterator &other) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ArcChain::Default Constructor
 //     Function: ArcChain::Default Constructor
 //       Access: Public
 //       Access: Public
-//  Description: 
+//  Description: This constructs an empty ArcChain with no nodes.  It
+//               cannot be extended, since you cannot add arcs without
+//               first specifying the top node.  Use the constructor
+//               that receives a node if you ever want to do anything
+//               with this chain.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE ArcChain::
 INLINE ArcChain::
 ArcChain() {
 ArcChain() {
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::Constructor
+//       Access: Public
+//  Description: This constructs an empty ArcChain with a single node.
+//               This chain may now be extended by repeatedly calling
+//               push_back() with each arc below that node in
+//               sequence.
+////////////////////////////////////////////////////////////////////
+INLINE ArcChain::
+ArcChain(Node *top_node) {
+  _head = new ArcComponent(top_node);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ArcChain::Copy Constructor
 //     Function: ArcChain::Copy Constructor
 //       Access: Public
 //       Access: Public
@@ -101,6 +290,28 @@ operator = (const ArcChain &copy) {
   _head = copy._head;
   _head = copy._head;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::has_node
+//       Access: Public
+//  Description: Returns true if there is at least a top node in the
+//               chain, or false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool ArcChain::
+has_node() const {
+  return (_head != (ArcComponent *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::has_arcs
+//       Access: Public
+//  Description: Returns true if there are any arcs in the chain, or
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool ArcChain::
+has_arcs() const {
+  return (_head != (ArcComponent *)NULL && !_head->is_top_node());
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ArcChain::begin
 //     Function: ArcChain::begin
 //       Access: Public
 //       Access: Public
@@ -109,7 +320,11 @@ operator = (const ArcChain &copy) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE ArcChain::const_iterator ArcChain::
 INLINE ArcChain::const_iterator ArcChain::
 begin() const {
 begin() const {
-  return ForwardIterator(_head);
+  if (empty()) {
+    return ForwardIterator();
+  } else {
+    return ForwardIterator(_head);
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -128,11 +343,11 @@ end() const {
 //       Access: Public
 //       Access: Public
 //  Description: Returns true if the list of arcs returned by begin()
 //  Description: Returns true if the list of arcs returned by begin()
 //               .. end() is empty (i.e. begin() == end()), false
 //               .. end() is empty (i.e. begin() == end()), false
-//               otherwise.
+//               otherwise.  This is the same as !has_arcs().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool ArcChain::
 INLINE bool ArcChain::
 empty() const {
 empty() const {
-  return (_head == (ArcComponent *)NULL);
+  return (_head == (ArcComponent *)NULL || _head->is_top_node());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -142,6 +357,9 @@ empty() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void ArcChain::
 INLINE void ArcChain::
 push_back(NodeRelation *arc) {
 push_back(NodeRelation *arc) {
+  // It is invalid to push an arc onto a chain that does not already
+  // have at least a top node.
+  nassertv(_head != (ArcComponent *)NULL);
   _head = new ArcComponent(arc, _head);
   _head = new ArcComponent(arc, _head);
 }
 }
 
 
@@ -153,7 +371,10 @@ push_back(NodeRelation *arc) {
 INLINE void ArcChain::
 INLINE void ArcChain::
 pop_back() {
 pop_back() {
   nassertv(_head != (ArcComponent *)NULL);
   nassertv(_head != (ArcComponent *)NULL);
-  _head = _head->_next;
+  _head = _head->get_next();
+
+  // It is invalid to pop off the top node of the chain.
+  nassertv(_head != (ArcComponent *)NULL);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -164,7 +385,7 @@ pop_back() {
 INLINE NodeRelation *ArcChain::
 INLINE NodeRelation *ArcChain::
 back() const {
 back() const {
   nassertr(_head != (ArcComponent *)NULL, (NodeRelation *)NULL);
   nassertr(_head != (ArcComponent *)NULL, (NodeRelation *)NULL);
-  return _head->_arc;
+  return _head->get_arc();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -203,6 +424,26 @@ operator < (const ArcChain &other) const {
   return (compare_to(other) < 0);
   return (compare_to(other) < 0);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::compare_to
+//       Access: Public
+//  Description: Returns a number less than zero if this ArcChain
+//               sorts before the other one, greater than zero if it
+//               sorts after, or zero if they are equivalent.
+//
+//               Two ArcChains are considered equivalent if they
+//               consist of exactly the same list of arcs in the same
+//               order.  Otherwise, they are different; different
+//               ArcChains will be ranked in a consistent but
+//               undefined ordering; the ordering is useful only for
+//               placing the ArcChains in a sorted container like an
+//               STL set.
+////////////////////////////////////////////////////////////////////
+INLINE int ArcChain::
+compare_to(const ArcChain &other) const {
+  return r_compare_to(_head, other._head);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ArcChain::output
 //     Function: ArcChain::output
 //       Access: Public
 //       Access: Public
@@ -211,7 +452,7 @@ operator < (const ArcChain &other) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void ArcChain::
 INLINE void ArcChain::
 output(ostream &out) const {
 output(ostream &out) const {
-  if (empty()) {
+  if (_head == (ArcComponent *)NULL) {
     out << "(empty)";
     out << "(empty)";
   } else {
   } else {
     r_output(out, _head);
     r_output(out, _head);

+ 34 - 42
panda/src/graph/arcChain.cxx

@@ -7,46 +7,6 @@
 #include "node.h"
 #include "node.h"
 #include "namedNode.h"
 #include "namedNode.h"
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: ArcChain::compare_to
-//       Access: Public
-//  Description: Returns a number less than zero if this ArcChain
-//               sorts before the other one, greater than zero if it
-//               sorts after, or zero if they are equivalent.
-//
-//               Two ArcChains are considered equivalent if they
-//               consist of exactly the same list of arcs in the same
-//               order.  Otherwise, they are different; different
-//               ArcChains will be ranked in a consistent but
-//               undefined ordering; the ordering is useful only for
-//               placing the ArcChains in a sorted container like an
-//               STL set.
-////////////////////////////////////////////////////////////////////
-int ArcChain::
-compare_to(const ArcChain &other) const {
-  ArcComponent *a = _head;
-  ArcComponent *b = other._head;
-
-  while (a != (ArcComponent *)NULL && b != (ArcComponent *)NULL) {
-    if (a < b) {
-      return -1;
-    } else if (a > b) {
-      return 1;
-    }
-
-    a = a->_next;
-    b = b->_next;
-  }
-
-  if (a < b) {
-    return -1;
-  } else if (a > b) {
-    return 1;
-  }
-
-  return 0;
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ArcChain::r_output
 //     Function: ArcChain::r_output
 //       Access: Private
 //       Access: Private
@@ -57,7 +17,7 @@ compare_to(const ArcChain &other) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ArcChain::
 void ArcChain::
 r_output(ostream &out, ArcComponent *comp) const {
 r_output(ostream &out, ArcComponent *comp) const {
-  ArcComponent *next = comp->_next;
+  ArcComponent *next = comp->get_next();
   if (next != (ArcComponent *)NULL) {
   if (next != (ArcComponent *)NULL) {
     // This is not the head of the list; keep going up.
     // This is not the head of the list; keep going up.
     r_output(out, next);
     r_output(out, next);
@@ -65,7 +25,7 @@ r_output(ostream &out, ArcComponent *comp) const {
   }
   }
 
 
   // Now output this component.
   // Now output this component.
-  Node *node = comp->_arc->get_child();
+  Node *node = comp->get_node();
   if (node->is_of_type(NamedNode::get_class_type())) {
   if (node->is_of_type(NamedNode::get_class_type())) {
     NamedNode *named_node = DCAST(NamedNode, node);
     NamedNode *named_node = DCAST(NamedNode, node);
     if (named_node->has_name()) {
     if (named_node->has_name()) {
@@ -77,3 +37,35 @@ r_output(ostream &out, ArcComponent *comp) const {
     out << node->get_type();
     out << node->get_type();
   }
   }
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::r_compare_to
+//       Access: Private, Static
+//  Description: The recursive implementation of compare_to().  Returns
+//               < 0 if a sorts before b, > 0 if b sorts before a, or
+//               == 0 if they are equivalent.
+////////////////////////////////////////////////////////////////////
+int ArcChain::
+r_compare_to(const ArcComponent *a, const ArcComponent *b) {
+  if (a == b) {
+    return 0;
+
+  } else if (a == (const ArcComponent *)NULL) {
+    return -1;
+
+  } else if (b == (const ArcComponent *)NULL) {
+    return 1;
+
+  } else if (a->has_arc() != b->has_arc()) {
+    return a->has_arc() - b->has_arc();
+
+  } else if (a->has_arc() && (a->get_arc() != b->get_arc())) {
+    return a->get_arc() - b->get_arc();
+
+  } else if (!a->has_arc() && (a->get_node() != b->get_node())) {
+    return a->get_node() - b->get_node();
+
+  } else {
+    return r_compare_to(a->get_next(), b->get_next());
+  }
+}

+ 43 - 1
panda/src/graph/arcChain.h

@@ -9,6 +9,7 @@
 #include <pandabase.h>
 #include <pandabase.h>
 
 
 #include "nodeRelation.h"
 #include "nodeRelation.h"
+#include "node.h"
 
 
 #include <pointerTo.h>
 #include <pointerTo.h>
 #include <referenceCount.h>
 #include <referenceCount.h>
@@ -45,10 +46,46 @@ protected:
   // copy the entire path by simply copying the head pointer, and we
   // copy the entire path by simply copying the head pointer, and we
   // can then append to or shorten our own path without affecting the
   // can then append to or shorten our own path without affecting the
   // paths we're sharing ArcComponents with.  Very LISPy.
   // paths we're sharing ArcComponents with.  Very LISPy.
+
+  // Normally, an ArcChain represents a list of arcs from the root of
+  // some graph down to a leaf.  This kind of structure works pretty
+  // well because the ArcChain keeps a reference count to each arc,
+  // which in turn keeps a reference count to each child node.  This
+  // means each node in the chain is reference counted, *except* the
+  // top node.
+
+  // To ensure that we also reference count the top node, we allow
+  // each ArcComponent to store either a pointer to an arc or, if it
+  // is the last node in the chain (and *only* if it is the last node
+  // in the chain), a pointer to a node.  Thus, the last ArcComponent
+  // in the chain will store a reference-counting pointer to the
+  // chain's top node.
+
   class ArcComponent : public ReferenceCount {
   class ArcComponent : public ReferenceCount {
   public:
   public:
+    INLINE ArcComponent(Node *node);
     INLINE ArcComponent(NodeRelation *arc, ArcComponent *next);
     INLINE ArcComponent(NodeRelation *arc, ArcComponent *next);
-    PT(NodeRelation) _arc;
+    INLINE ArcComponent(const ArcComponent &copy);
+    INLINE void operator = (const ArcComponent &copy);
+    INLINE ~ArcComponent();
+
+    INLINE bool has_arc() const;
+    INLINE NodeRelation *get_arc() const;
+    INLINE Node *get_node() const;
+    INLINE bool is_top_node() const;
+    INLINE bool is_top_arc() const;
+
+    INLINE ArcComponent *get_next() const;
+    INLINE void set_next(ArcComponent *next);
+
+  private:
+    union {
+      // These are plain pointers instead of PT's, because they are
+      // stored in a union.  We manage the reference counts by hand in
+      // the constructors and destructor.
+      NodeRelation *_arc;
+      Node *_node;
+    } _p;
     PT(ArcComponent) _next;
     PT(ArcComponent) _next;
   };
   };
 
 
@@ -73,9 +110,13 @@ public:
   typedef ForwardIterator const_iterator;
   typedef ForwardIterator const_iterator;
 
 
   INLINE ArcChain();
   INLINE ArcChain();
+  INLINE ArcChain(Node *top_node);
   INLINE ArcChain(const ArcChain &copy);
   INLINE ArcChain(const ArcChain &copy);
   INLINE void operator = (const ArcChain &copy);
   INLINE void operator = (const ArcChain &copy);
 
 
+  INLINE bool has_node() const;
+  INLINE bool has_arcs() const;
+
   INLINE const_iterator begin() const;
   INLINE const_iterator begin() const;
   INLINE const_iterator end() const;
   INLINE const_iterator end() const;
   INLINE bool empty() const;
   INLINE bool empty() const;
@@ -93,6 +134,7 @@ public:
 
 
 private:
 private:
   void r_output(ostream &out, ArcComponent *comp) const;
   void r_output(ostream &out, ArcComponent *comp) const;
+  static int r_compare_to(const ArcComponent *a, const ArcComponent *v);
 };
 };
 
 
 INLINE ostream &operator << (ostream &out, const ArcChain &arc_chain) {
 INLINE ostream &operator << (ostream &out, const ArcChain &arc_chain) {

+ 1 - 1
panda/src/graph/nodeRelation.h

@@ -72,11 +72,11 @@ public:
   // instead, you should call remove_arc().
   // instead, you should call remove_arc().
   virtual ~NodeRelation();
   virtual ~NodeRelation();
 
 
+PUBLISHED:
   void output(ostream &out) const;
   void output(ostream &out) const;
   INLINE void output_transitions(ostream &out) const;
   INLINE void output_transitions(ostream &out) const;
   INLINE void write_transitions(ostream &out, int indent = 0) const;
   INLINE void write_transitions(ostream &out, int indent = 0) const;
 
 
-PUBLISHED:
   INLINE Node *get_parent() const;
   INLINE Node *get_parent() const;
   INLINE Node *get_child() const;
   INLINE Node *get_child() const;
   INLINE int get_sort() const;
   INLINE int get_sort() const;

+ 27 - 0
panda/src/putil/factoryBase.cxx

@@ -5,6 +5,7 @@
 
 
 #include "factoryBase.h"
 #include "factoryBase.h"
 #include "indent.h"
 #include "indent.h"
+#include "config_util.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: FactoryBase::Constructor
 //     Function: FactoryBase::Constructor
@@ -42,6 +43,19 @@ make_instance(TypeHandle handle, const FactoryParams &params) {
     // Can't create an exact instance; try for a derived type.
     // Can't create an exact instance; try for a derived type.
     instance = make_instance_more_specific(handle, params);
     instance = make_instance_more_specific(handle, params);
   }
   }
+
+#ifndef NDEBUG
+  if (util_cat.is_debug()) {
+    util_cat.debug()
+      << "make_instance(" << handle << ", params) returns "
+      << (void *)instance;
+    if (instance != (TypedObject *)NULL) {
+      util_cat.debug(false)
+	<< ", of type " << instance->get_type();
+    }
+    util_cat.debug(false) << "\n";
+  }
+#endif
   return instance;
   return instance;
 }
 }
 
 
@@ -66,6 +80,19 @@ make_instance_more_general(TypeHandle handle, const FactoryParams &params) {
     object = make_instance_exact(handle, params);
     object = make_instance_exact(handle, params);
   }
   }
 
 
+#ifndef NDEBUG
+  if (util_cat.is_debug()) {
+    util_cat.debug()
+      << "make_instance(" << handle << ", params) returns "
+      << (void *)object;
+    if (object != (TypedObject *)NULL) {
+      util_cat.debug(false)
+	<< ", of type " << object->get_type();
+    }
+    util_cat.debug(false) << "\n";
+  }
+#endif
+
   return object;
   return object;
 }
 }
 
 

+ 3 - 2
panda/src/sgmanip/findApproxPath.cxx

@@ -127,8 +127,9 @@ add_component(string str_component) {
 
 
   } else if (str_component == "**") {
   } else if (str_component == "**") {
     if ((flags & CF_stashed) != 0) {
     if ((flags & CF_stashed) != 0) {
-      sgmanip_cat.warning()
-	<< "@@** is ambiguous; use @@*/** or **/@@* instead.\n";
+      sgmanip_cat.error()
+	<< "@@** is undefined; use @@*/** or **/@@* instead.\n";
+      return false;
     }
     }
     add_match_many(flags);
     add_match_many(flags);
 
 

+ 59 - 151
panda/src/sgmanip/nodePath.I

@@ -4,61 +4,6 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::ForwardIterator::Constructor
-//       Access: Public
-//  Description: This is an STL-style iterator that can be used to
-//               traverse the full list of arcs in the NodePath.  Its
-//               primary purpose is as a parameter to wrt() so we can
-//               compute a correct relative wrt to the particular
-//               instance referenced by the NodePath.
-////////////////////////////////////////////////////////////////////
-INLINE NodePath::ForwardIterator::
-ForwardIterator(NodePath::ArcComponent *comp) : _comp(comp) {
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::ForwardIterator::Dereference Operator
-//       Access: Public
-//  Description: 
-////////////////////////////////////////////////////////////////////
-INLINE NodeRelation *NodePath::ForwardIterator::
-operator * () const {
-  nassertr(_comp != (ArcComponent *)NULL, NULL);
-  return _comp->_arc;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::ForwardIterator::Increment Operator
-//       Access: Public
-//  Description: 
-////////////////////////////////////////////////////////////////////
-INLINE void NodePath::ForwardIterator::
-operator ++() {
-  nassertv(_comp != (ArcComponent *)NULL);
-  _comp = _comp->_next;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::ForwardIterator::Equality Operator
-//       Access: Public
-//  Description: 
-////////////////////////////////////////////////////////////////////
-INLINE bool NodePath::ForwardIterator::
-operator == (const NodePath::ForwardIterator &other) const {
-  return _comp == other._comp;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::ForwardIterator::Inequality Operator
-//       Access: Public
-//  Description: 
-////////////////////////////////////////////////////////////////////
-INLINE bool NodePath::ForwardIterator::
-operator != (const NodePath::ForwardIterator &other) const {
-  return _comp != other._comp;
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::Default Constructor
 //     Function: NodePath::Default Constructor
 //       Access: Public
 //       Access: Public
@@ -80,8 +25,7 @@ NodePath(TypeHandle graph_type) : NodePathBase(graph_type) {
 //               ordinary node pointer.
 //               ordinary node pointer.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE NodePath::
 INLINE NodePath::
-NodePath(Node *top_node, TypeHandle graph_type) : NodePathBase(graph_type) {
-  _top_node = top_node;
+NodePath(Node *top_node, TypeHandle graph_type) : NodePathBase(top_node, graph_type) {
   nassertv(verify_connectivity());
   nassertv(verify_connectivity());
 }
 }
 
 
@@ -98,7 +42,6 @@ INLINE NodePath::
 NodePath(const ArcChain &chain, TypeHandle graph_type) :
 NodePath(const ArcChain &chain, TypeHandle graph_type) :
   NodePathBase(chain, graph_type)
   NodePathBase(chain, graph_type)
 {
 {
-  reset_top_node();
   nassertv(verify_connectivity());
   nassertv(verify_connectivity());
 }
 }
 
 
@@ -150,6 +93,20 @@ operator != (const NodePath &other) const {
   return !operator == (other);
   return !operator == (other);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::compare_to
+//       Access: Public
+//  Description: Returns a number less than zero if this NodePath
+//               sorts before the indicated NodePath in an arbitrary
+//               lexicographical comparision, greater than zero if
+//               this one sorts after the other one, or zero if the
+//               two NodePaths are equivalent.
+////////////////////////////////////////////////////////////////////
+INLINE int NodePath::
+compare_to(const NodePath &other) const {
+  return NodePathBase::compare_to(other);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::set_graph_type
 //     Function: NodePath::set_graph_type
 //       Access: Public
 //       Access: Public
@@ -222,7 +179,7 @@ get_max_search_depth() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool NodePath::
 INLINE bool NodePath::
 is_empty() const {
 is_empty() const {
-  return (_head == (ArcComponent *)NULL && _top_node == (Node *)NULL);
+  return !ArcChain::has_node();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -233,7 +190,7 @@ is_empty() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool NodePath::
 INLINE bool NodePath::
 is_singleton() const {
 is_singleton() const {
-  return (_head == (ArcComponent *)NULL && _top_node != (Node *)NULL);
+  return ArcChain::has_node() && !ArcChain::has_arcs();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -246,33 +203,20 @@ is_singleton() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool NodePath::
 INLINE bool NodePath::
 has_arcs() const {
 has_arcs() const {
-  return (_head != (ArcComponent *)NULL);
+  return ArcChain::has_arcs();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: NodePath::get_num_nodes
+//     Function: NodePath::get_num_arcs
 //       Access: Public
 //       Access: Public
-//  Description: Returns the number of nodes in the path, including
-//               the top node.
+//  Description: Returns the number of arcs in the path.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int NodePath::
 INLINE int NodePath::
-get_num_nodes() const {
-  if (is_empty()) {
+get_num_arcs() const {
+  if (!has_arcs()) {
     return 0;
     return 0;
   }
   }
-  return get_num_arcs() + 1;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::get_top_node
-//       Access: Public
-//  Description: Returns the top node of the path, or NULL if the path
-//               is empty.
-////////////////////////////////////////////////////////////////////
-INLINE Node *NodePath::
-get_top_node() {
-  reset_top_node();
-  return _top_node;
+  return get_num_nodes() - 1;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -283,11 +227,10 @@ get_top_node() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE Node *NodePath::
 INLINE Node *NodePath::
 node() const {
 node() const {
-  if (_head == (ArcComponent *)NULL) {
-    // A singleton or empty list.
-    return _top_node;
+  if (is_empty()) {
+    return (Node *)NULL;
   }
   }
-  return _head->_arc->get_child();
+  return _head->get_node();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -298,11 +241,11 @@ node() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE NodeRelation *NodePath::
 INLINE NodeRelation *NodePath::
 arc() const {
 arc() const {
-  if (_head == (ArcComponent *)NULL) {
+  if (!has_arcs()) {
     // A singleton or empty list.
     // A singleton or empty list.
     return (NodeRelation *)NULL;
     return (NodeRelation *)NULL;
   }
   }
-  return _head->_arc;
+  return _head->get_arc();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -676,9 +619,9 @@ get_sa() const {
 INLINE void NodePath::
 INLINE void NodePath::
 clear_color_scale() {
 clear_color_scale() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-  _head->_arc->clear_transition(ColorMatrixTransition::get_class_type());
-  _head->_arc->clear_transition(AlphaTransformTransition::get_class_type());
+  NodeRelation *darc = arc();
+  darc->clear_transition(ColorMatrixTransition::get_class_type());
+  darc->clear_transition(AlphaTransformTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -694,9 +637,9 @@ clear_color_scale() {
 INLINE bool NodePath::
 INLINE bool NodePath::
 has_color_scale() const {
 has_color_scale() const {
   nassertr(has_arcs(), false);
   nassertr(has_arcs(), false);
-  nassertr(_head != (ArcComponent *)NULL, false);
-  return _head->_arc->has_transition(ColorMatrixTransition::get_class_type()) ||
-         _head->_arc->has_transition(AlphaTransformTransition::get_class_type());
+  NodeRelation *darc = arc();
+  return darc->has_transition(ColorMatrixTransition::get_class_type()) ||
+         darc->has_transition(AlphaTransformTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -734,8 +677,7 @@ set_pos_hpr_scale(float x, float y, float z, float h, float p, float r,
 INLINE void NodePath::
 INLINE void NodePath::
 clear_mat() {
 clear_mat() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-  _head->_arc->clear_transition(TransformTransition::get_class_type());
+  arc()->clear_transition(TransformTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -747,8 +689,7 @@ clear_mat() {
 INLINE bool NodePath::
 INLINE bool NodePath::
 has_mat() const {
 has_mat() const {
   nassertr(has_arcs(), false);
   nassertr(has_arcs(), false);
-  nassertr(_head != (ArcComponent *)NULL, false);
-  return _head->_arc->has_transition(TransformTransition::get_class_type());
+  return arc()->has_transition(TransformTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -761,10 +702,9 @@ has_mat() const {
 INLINE LMatrix4f NodePath::
 INLINE LMatrix4f NodePath::
 get_mat() const {
 get_mat() const {
   nassertr(has_arcs(), LMatrix4f::ident_mat());
   nassertr(has_arcs(), LMatrix4f::ident_mat());
-  nassertr(_head != (ArcComponent *)NULL, LMatrix4f::ident_mat());
 
 
   const TransformTransition *tt;
   const TransformTransition *tt;
-  if (!get_transition_into(tt, _head->_arc)) {
+  if (!get_transition_into(tt, arc())) {
     // No relative transform.
     // No relative transform.
     return LMatrix4f::ident_mat();
     return LMatrix4f::ident_mat();
   }
   }
@@ -1135,8 +1075,7 @@ set_color(float r, float g, float b, float a,
 INLINE void NodePath::
 INLINE void NodePath::
 clear_color() {
 clear_color() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-  _head->_arc->clear_transition(ColorTransition::get_class_type());
+  arc()->clear_transition(ColorTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1148,8 +1087,7 @@ clear_color() {
 INLINE bool NodePath::
 INLINE bool NodePath::
 has_color() const {
 has_color() const {
   nassertr(has_arcs(), false);
   nassertr(has_arcs(), false);
-  nassertr(_head != (ArcComponent *)NULL, false);
-  return _head->_arc->has_transition(ColorTransition::get_class_type());
+  return arc()->has_transition(ColorTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1161,8 +1099,7 @@ has_color() const {
 INLINE void NodePath::
 INLINE void NodePath::
 clear_bin() {
 clear_bin() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-  _head->_arc->clear_transition(TextureTransition::get_class_type());
+  arc()->clear_transition(TextureTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1175,8 +1112,7 @@ clear_bin() {
 INLINE bool NodePath::
 INLINE bool NodePath::
 has_bin() const {
 has_bin() const {
   nassertr(has_arcs(), false);
   nassertr(has_arcs(), false);
-  nassertr(_head != (ArcComponent *)NULL, false);
-  return _head->_arc->has_transition(GeomBinTransition::get_class_type());
+  return arc()->has_transition(GeomBinTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1191,8 +1127,7 @@ has_bin() const {
 INLINE void NodePath::
 INLINE void NodePath::
 clear_texture() {
 clear_texture() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-  _head->_arc->clear_transition(TextureTransition::get_class_type());
+  arc()->clear_transition(TextureTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1207,8 +1142,7 @@ clear_texture() {
 INLINE void NodePath::
 INLINE void NodePath::
 clear_fog() {
 clear_fog() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-  _head->_arc->clear_transition(FogTransition::get_class_type());
+  arc()->clear_transition(FogTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1222,8 +1156,7 @@ clear_fog() {
 INLINE void NodePath::
 INLINE void NodePath::
 clear_render_mode() {
 clear_render_mode() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-  _head->_arc->clear_transition(RenderModeTransition::get_class_type());
+  arc()->clear_transition(RenderModeTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1237,8 +1170,7 @@ clear_render_mode() {
 INLINE bool NodePath::
 INLINE bool NodePath::
 has_render_mode() const {
 has_render_mode() const {
   nassertr(has_arcs(), false);
   nassertr(has_arcs(), false);
-  nassertr(_head != (ArcComponent *)NULL, false);
-  return _head->_arc->has_transition(RenderModeTransition::get_class_type());
+  return arc()->has_transition(RenderModeTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1255,8 +1187,7 @@ has_render_mode() const {
 INLINE void NodePath::
 INLINE void NodePath::
 clear_two_sided() {
 clear_two_sided() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-  _head->_arc->clear_transition(CullFaceTransition::get_class_type());
+  arc()->clear_transition(CullFaceTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1271,8 +1202,7 @@ clear_two_sided() {
 INLINE bool NodePath::
 INLINE bool NodePath::
 has_two_sided() const {
 has_two_sided() const {
   nassertr(has_arcs(), false);
   nassertr(has_arcs(), false);
-  nassertr(_head != (ArcComponent *)NULL, false);
-  return _head->_arc->has_transition(CullFaceTransition::get_class_type());
+  return arc()->has_transition(CullFaceTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1284,9 +1214,7 @@ has_two_sided() const {
 INLINE void NodePath::
 INLINE void NodePath::
 set_billboard_axis() {
 set_billboard_axis() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-
-  _head->_arc->set_transition(new BillboardTransition(BillboardTransition::axis()));
+  arc()->set_transition(new BillboardTransition(BillboardTransition::axis()));
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1300,9 +1228,7 @@ set_billboard_axis() {
 INLINE void NodePath::
 INLINE void NodePath::
 set_billboard_point_eye() {
 set_billboard_point_eye() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-
-  _head->_arc->set_transition(new BillboardTransition(BillboardTransition::point_eye()));
+  arc()->set_transition(new BillboardTransition(BillboardTransition::point_eye()));
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1315,9 +1241,7 @@ set_billboard_point_eye() {
 INLINE void NodePath::
 INLINE void NodePath::
 set_billboard_point_world() {
 set_billboard_point_world() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-
-  _head->_arc->set_transition(new BillboardTransition(BillboardTransition::point_world()));
+  arc()->set_transition(new BillboardTransition(BillboardTransition::point_world()));
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1328,9 +1252,7 @@ set_billboard_point_world() {
 INLINE void NodePath::
 INLINE void NodePath::
 clear_billboard() {
 clear_billboard() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-
-  _head->_arc->clear_transition(BillboardTransition::get_class_type());
+  arc()->clear_transition(BillboardTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1342,9 +1264,7 @@ clear_billboard() {
 INLINE bool NodePath::
 INLINE bool NodePath::
 has_billboard() const {
 has_billboard() const {
   nassertr(has_arcs(), false);
   nassertr(has_arcs(), false);
-  nassertr(_head != (ArcComponent *)NULL, false);
-
-  return _head->_arc->has_transition(BillboardTransition::get_class_type());
+  return arc()->has_transition(BillboardTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1361,8 +1281,7 @@ has_billboard() const {
 INLINE void NodePath::
 INLINE void NodePath::
 clear_transparency() {
 clear_transparency() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-  _head->_arc->clear_transition(TransparencyTransition::get_class_type());
+  arc()->clear_transition(TransparencyTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1378,8 +1297,7 @@ clear_transparency() {
 INLINE bool NodePath::
 INLINE bool NodePath::
 has_transparency() const {
 has_transparency() const {
   nassertr(has_arcs(), false);
   nassertr(has_arcs(), false);
-  nassertr(_head != (ArcComponent *)NULL, false);
-  return _head->_arc->has_transition(TransparencyTransition::get_class_type());
+  return arc()->has_transition(TransparencyTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1396,9 +1314,7 @@ has_transparency() const {
 INLINE void NodePath::
 INLINE void NodePath::
 adjust_all_priorities(int adjustment) {
 adjust_all_priorities(int adjustment) {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-
-  r_adjust_all_priorities(_head->_arc, adjustment);
+  r_adjust_all_priorities(arc(), adjustment);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1412,9 +1328,7 @@ adjust_all_priorities(int adjustment) {
 INLINE void NodePath::
 INLINE void NodePath::
 show() {
 show() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-
-  _head->_arc->clear_transition(PruneTransition::get_class_type());
+  arc()->clear_transition(PruneTransition::get_class_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1433,9 +1347,7 @@ show() {
 INLINE void NodePath::
 INLINE void NodePath::
 hide() {
 hide() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-
-  _head->_arc->set_transition(new PruneTransition);
+  arc()->set_transition(new PruneTransition);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1489,9 +1401,7 @@ is_hidden() const {
 INLINE void NodePath::
 INLINE void NodePath::
 stash() {
 stash() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-
-  _head->_arc->set_graph_type(NodeRelation::get_stashed_type());
+  arc()->set_graph_type(NodeRelation::get_stashed_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1502,9 +1412,7 @@ stash() {
 INLINE void NodePath::
 INLINE void NodePath::
 unstash() {
 unstash() {
   nassertv(has_arcs());
   nassertv(has_arcs());
-  nassertv(_head != (ArcComponent *)NULL);
-
-  _head->_arc->set_graph_type(_head->_arc->get_type());
+  arc()->set_graph_type(arc()->get_type());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

File diff suppressed because it is too large
+ 151 - 210
panda/src/sgmanip/nodePath.cxx


+ 5 - 19
panda/src/sgmanip/nodePath.h

@@ -122,7 +122,7 @@ PUBLISHED:
 
 
   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;
-  int compare_to(const NodePath &other) const;
+  INLINE int compare_to(const NodePath &other) const;
 
 
   INLINE void set_graph_type(TypeHandle graph_type);
   INLINE void set_graph_type(TypeHandle graph_type);
   INLINE TypeHandle get_graph_type() const;
   INLINE TypeHandle get_graph_type() const;
@@ -134,7 +134,7 @@ PUBLISHED:
   // Methods to extend or shorten a NodePath.
   // Methods to extend or shorten a NodePath.
 
 
   bool extend_by(Node *dnode);
   bool extend_by(Node *dnode);
-  bool extend_by(NodeRelation *arc);
+  bool extend_by(NodeRelation *darc);
   bool extend_by(const NodePath &other);
   bool extend_by(const NodePath &other);
   bool extend_by(const string &path);
   bool extend_by(const string &path);
   bool extend_down_to(Node *dnode);
   bool extend_down_to(Node *dnode);
@@ -148,13 +148,13 @@ PUBLISHED:
   INLINE bool is_empty() const;
   INLINE bool is_empty() const;
   INLINE bool is_singleton() const;
   INLINE bool is_singleton() const;
   INLINE bool has_arcs() const;
   INLINE bool has_arcs() const;
-  INLINE int get_num_nodes() const;
+  int get_num_nodes() const;
   Node *get_node(int index) const;
   Node *get_node(int index) const;
 
 
-  int get_num_arcs() const;
+  INLINE int get_num_arcs() const;
   NodeRelation *get_arc(int index) const;
   NodeRelation *get_arc(int index) const;
 
 
-  INLINE Node *get_top_node();
+  Node *get_top_node() const;
   INLINE Node *node() const;
   INLINE Node *node() const;
   INLINE NodeRelation *arc() const;
   INLINE NodeRelation *arc() const;
 
 
@@ -458,21 +458,7 @@ PUBLISHED:
   void write_bounds(ostream &out) const;
   void write_bounds(ostream &out) const;
 
 
 
 
-public:
-  // This is a supporting class for passing the list of arcs to wrt().
-  class ForwardIterator {
-  public:
-    INLINE ForwardIterator(ArcComponent *comp = NULL);
-    INLINE NodeRelation *operator * () const;
-    INLINE void operator ++();
-    INLINE bool operator == (const ForwardIterator &other) const;
-    INLINE bool operator != (const ForwardIterator &other) const;
-    ArcComponent *_comp;
-  };
-
 private:
 private:
-  void reset_top_node();
-  static int r_compare_to(const ArcComponent *a, const ArcComponent *v);
   bool r_extend_by(const ArcComponent *other);
   bool r_extend_by(const ArcComponent *other);
   int r_as_string(const ArcComponent *comp, string &result, 
   int r_as_string(const ArcComponent *comp, string &result, 
 		  int skip_nodes) const;
 		  int skip_nodes) const;

+ 12 - 2
panda/src/sgmanip/nodePathBase.I

@@ -15,6 +15,18 @@ NodePathBase(TypeHandle graph_type) :
 {
 {
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodePathBase::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE NodePathBase::
+NodePathBase(Node *top_node, TypeHandle graph_type) :
+  ArcChain(top_node),
+  _graph_type(graph_type)
+{
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePathBase::Constructor
 //     Function: NodePathBase::Constructor
 //       Access: Public
 //       Access: Public
@@ -39,7 +51,6 @@ NodePathBase(const ArcChain &chain, TypeHandle graph_type) :
 INLINE NodePathBase::
 INLINE NodePathBase::
 NodePathBase(const NodePathBase &copy) :
 NodePathBase(const NodePathBase &copy) :
   ArcChain(copy),
   ArcChain(copy),
-  _top_node(copy._top_node),
   _graph_type(copy._graph_type)
   _graph_type(copy._graph_type)
 {
 {
 }
 }
@@ -52,6 +63,5 @@ NodePathBase(const NodePathBase &copy) :
 INLINE void NodePathBase::
 INLINE void NodePathBase::
 operator = (const NodePathBase &copy) {
 operator = (const NodePathBase &copy) {
   ArcChain::operator = (copy);
   ArcChain::operator = (copy);
-  _top_node = copy._top_node;
   _graph_type = copy._graph_type;
   _graph_type = copy._graph_type;
 }
 }

+ 3 - 11
panda/src/sgmanip/nodePathBase.h

@@ -24,23 +24,15 @@
 class EXPCL_PANDA NodePathBase : public ArcChain {
 class EXPCL_PANDA NodePathBase : public ArcChain {
 public:
 public:
   INLINE NodePathBase(TypeHandle graph_type = RenderRelation::get_class_type());
   INLINE NodePathBase(TypeHandle graph_type = RenderRelation::get_class_type());
+  INLINE NodePathBase(Node *top_node, TypeHandle graph_type = RenderRelation::get_class_type());
   INLINE NodePathBase(const ArcChain &chain, TypeHandle graph_type);
   INLINE NodePathBase(const ArcChain &chain, TypeHandle graph_type);
   INLINE NodePathBase(const NodePathBase &copy);
   INLINE NodePathBase(const NodePathBase &copy);
   INLINE void operator = (const NodePathBase &copy);
   INLINE void operator = (const NodePathBase &copy);
 
 
 protected:
 protected:
   // Most of the interesting part of NodePathBase is inherited from
   // Most of the interesting part of NodePathBase is inherited from
-  // ArcChain.  This gives us a sharable linked list of arcs.
-
-  // We also add an explicit pointer to the top node in the chain,
-  // mainly to allow us to define a NodePath containing a single node,
-  // even if the chain of arcs is empty.
-
-  // If the chain is nonempty, this might still be useful (int that it
-  // keeps a reference count to the top node), but this is problematic
-  // since it will not automatically update if our parent is changed
-  // without our knowledge.
-  PT_Node _top_node;
+  // ArcChain.  This gives us a sharable linked list of arcs, with a
+  // single node on top.
 
 
   TypeHandle _graph_type;
   TypeHandle _graph_type;
   static int _max_search_depth;
   static int _max_search_depth;

+ 3 - 1
panda/src/sgraph/geomTransformer.cxx

@@ -84,7 +84,9 @@ transform_vertices(Geom *geom, const LMatrix4f &mat) {
       new_norms.reserve(norms.size());
       new_norms.reserve(norms.size());
       PTA_Normalf::const_iterator ni;
       PTA_Normalf::const_iterator ni;
       for (ni = norms.begin(); ni != norms.end(); ++ni) {
       for (ni = norms.begin(); ni != norms.end(); ++ni) {
-	new_norms.push_back((*ni) * mat);
+	Normalf new_norm = (*ni) * mat;
+	new_norm.normalize();
+	new_norms.push_back(new_norm);
       }
       }
       nassertr(new_norms.size() == norms.size(), false);
       nassertr(new_norms.size() == norms.size(), false);
     }
     }

+ 13 - 0
panda/src/sgraphutil/frustumCullTraverser.I

@@ -54,10 +54,23 @@ FrustumCullTraverser(ArcChain &arc_chain, Node *root,
     }
     }
   }
   }
 
 
+  bool needs_top_node = !_arc_chain.has_node();
+  if (needs_top_node) {
+    // If the ArcChain supplied in is initially empty, put the root
+    // node in it.
+    _arc_chain = ArcChain(root);
+  }
+
   LevelState level_state(initial_level_state);
   LevelState level_state(initial_level_state);
   traverse(root, _initial_render_state, level_state, local_frustum, false);
   traverse(root, _initial_render_state, level_state, local_frustum, false);
 
 
   _view_frustum = NULL;
   _view_frustum = NULL;
+
+  if (needs_top_node) {
+    // Restore the ArcChain to its initial empty state (if that's what
+    // it was).
+    _arc_chain = ArcChain();
+  }
 }
 }
 
 
 
 

+ 60 - 5
panda/src/sgraphutil/sceneGraphAnalyzer.cxx

@@ -71,6 +71,10 @@ clear() {
   _num_triangles_in_fans = 0;
   _num_triangles_in_fans = 0;
 
 
   _texture_bytes = 0;
   _texture_bytes = 0;
+
+  _num_long_normals = 0;
+  _num_short_normals = 0;
+  _total_normal_length = 0.0;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -118,6 +122,13 @@ write(ostream &out, int indent_level) const {
     << _num_vertices << " vertices, " << _num_normals << " normals, "
     << _num_vertices << " vertices, " << _num_normals << " normals, "
     << _num_texcoords << " texture coordinates.\n";
     << _num_texcoords << " texture coordinates.\n";
 
 
+  if (_num_normals != 0) {
+    indent(out, indent_level)
+      << _num_long_normals << " normals are too long, " 
+      << _num_short_normals << " are too short.  Average normal length is "
+      << _total_normal_length / (float)_num_normals << "\n";
+  }
+
   indent(out, indent_level)
   indent(out, indent_level)
     << _num_tris << " triangles:\n";
     << _num_tris << " triangles:\n";
   indent(out, indent_level + 2)
   indent(out, indent_level + 2)
@@ -268,21 +279,26 @@ collect_statistics(Geom *geom) {
 
 
   _num_vertices += num_verts;
   _num_vertices += num_verts;
 
 
-  switch (geom->get_binding(G_NORMAL)) {
+  PTA_Normalf norms;
+  GeomBindType nbind;
+  PTA_ushort nindex;
+  geom->get_normals(norms, nbind, nindex);
+
+  switch (nbind) {
   case G_OVERALL:
   case G_OVERALL:
-    _num_normals++;
+    consider_normals(norms, nindex, 1);
     break;
     break;
 
 
   case G_PER_PRIM:
   case G_PER_PRIM:
-    _num_normals += num_prims;
+    consider_normals(norms, nindex, num_prims);
     break;
     break;
 
 
   case G_PER_COMPONENT:
   case G_PER_COMPONENT:
-    _num_normals += num_components;
+    consider_normals(norms, nindex, num_components);
     break;
     break;
 
 
   case G_PER_VERTEX:
   case G_PER_VERTEX:
-    _num_normals += num_verts;
+    consider_normals(norms, nindex, num_verts);
     break;
     break;
 
 
   case G_OFF:
   case G_OFF:
@@ -381,3 +397,42 @@ collect_statistics(Texture *texture) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: SceneGraphAnalyzer::consider_normals
+//       Access: Private
+//  Description: Examines the indicated set of normals.
+////////////////////////////////////////////////////////////////////
+void SceneGraphAnalyzer::
+consider_normals(const Normalf *norms, const ushort *nindex, int num) {
+  _num_normals += num;
+
+  if (nindex != (const ushort *)NULL) {
+    // An indexed array.
+    for (int i = 0; i < num; i++) {
+      const Normalf &norm = norms[nindex[i]];
+      float l = norm.length();
+      if (IS_THRESHOLD_EQUAL(l, 1.0, 0.01)) {
+	// This normal is close enough to unit length to be ok.
+      } else if (l > 1.0) {
+	_num_long_normals++;
+      } else { // l < 1.0
+	_num_short_normals++;
+      }
+      _total_normal_length += l;
+    }
+  } else {
+    // A nonindexed array.
+    for (int i = 0; i < num; i++) {
+      const Normalf &norm = norms[i];
+      float l = norm.length();
+      if (IS_THRESHOLD_EQUAL(l, 1.0, 0.01)) {
+	// This normal is close enough to unit length to be ok.
+      } else if (l > 1.0) {
+	_num_long_normals++;
+      } else { // l < 1.0
+	_num_short_normals++;
+      }
+      _total_normal_length += l;
+    }
+  }
+}

+ 6 - 0
panda/src/sgraphutil/sceneGraphAnalyzer.h

@@ -40,6 +40,8 @@ private:
   void collect_statistics(Geom *geom);
   void collect_statistics(Geom *geom);
   void collect_statistics(Texture *texture);
   void collect_statistics(Texture *texture);
 
 
+  void consider_normals(const Normalf *norms, const ushort *nindex, int num);
+
   typedef map<Node *, int> Nodes;
   typedef map<Node *, int> Nodes;
   typedef map<Texture *, int> Textures;
   typedef map<Texture *, int> Textures;
 
 
@@ -74,6 +76,10 @@ public:
 
 
   int _texture_bytes;
   int _texture_bytes;
 
 
+  int _num_long_normals;
+  int _num_short_normals;
+  float _total_normal_length;
+
   TypeHandle _graph_type;
   TypeHandle _graph_type;
 };
 };
 
 

Some files were not shown because too many files changed in this diff