Browse Source

better system for combining nodes in flattenStrong

David Rose 24 years ago
parent
commit
25ba7f73a8

+ 1 - 16
panda/src/graph/graphReducer.cxx

@@ -417,22 +417,7 @@ collapse_nodes(Node *node1, Node *node2, bool) {
     return NULL;
   }
 
-  // We get to choose whether to remove node1 or node2.
-  if (node2->is_exact_type(Node::get_class_type()) ||
-      node2->is_exact_type(NamedNode::get_class_type())) {
-    // Node2 isn't anything special, so preserve node1.
-    return node1;
-
-  } else if (node1->is_exact_type(Node::get_class_type()) ||
-             node1->is_exact_type(NamedNode::get_class_type())) {
-    // Node1 isn't anything special, so preserve node2.
-    return node2;
-
-  } else {
-    // Both node1 and node2 are some special kind of node.  Don't
-    // want to risk removing either of them.
-    return NULL;
-  }
+  return node2->combine_with(node1);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 35 - 0
panda/src/graph/namedNode.cxx

@@ -46,6 +46,41 @@ make_copy() const {
   return new NamedNode(*this);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: NamedNode::combine_with
+//       Access: Public, Virtual
+//  Description: Collapses this node with the other node, if possible,
+//               and returns a pointer to the combined node, or NULL
+//               if the two nodes cannot safely be combined.
+//
+//               The return value may be this, other, or a new node
+//               altogether.
+//
+//               This function is called from GraphReducer::flatten(),
+//               and need not deal with children; its job is just to
+//               decide whether to collapse the two nodes and what the
+//               collapsed node should look like.
+////////////////////////////////////////////////////////////////////
+Node *NamedNode::
+combine_with(Node *other) {
+  // An unadorned NamedNode combines with other Nodes by yielding
+  // completely.  However, if we are actually some fancy Node type
+  // that derives from NamedNode but didn't redefine this function, we
+  // should refuse to combine.
+  if (is_exact_type(get_class_type())) {
+    // No, we're an ordinary NamedNode.
+    if (other->is_exact_type(Node::get_class_type())) {
+      // And the other node isn't even named, so we override.
+      return this;
+    }
+    // The other node is also a NamedNode, or better, so it wins.
+    return other;
+  }
+
+  // We're something other than an ordinary NamedNode.  Don't combine.
+  return (Node *)NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: NamedNode::preserve_name
 //       Access: Public, Virtual

+ 1 - 0
panda/src/graph/namedNode.h

@@ -39,6 +39,7 @@ public:
   virtual ~NamedNode();
 
   virtual Node *make_copy() const;
+  virtual Node *combine_with(Node *other); 
 
   virtual bool preserve_name() const;
 

+ 30 - 0
panda/src/graph/node.cxx

@@ -184,6 +184,36 @@ void Node::
 xform(const LMatrix4f &) {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Node::combine_with
+//       Access: Public, Virtual
+//  Description: Collapses this node with the other node, if possible,
+//               and returns a pointer to the combined node, or NULL
+//               if the two nodes cannot safely be combined.
+//
+//               The return value may be this, other, or a new node
+//               altogether.
+//
+//               This function is called from GraphReducer::flatten(),
+//               and need not deal with children; its job is just to
+//               decide whether to collapse the two nodes and what the
+//               collapsed node should look like.
+////////////////////////////////////////////////////////////////////
+Node *Node::
+combine_with(Node *other) {
+  // An unadorned Node always combines with any other Nodes by
+  // yielding completely.  However, if we are actually some fancy Node
+  // type that derives from Node but didn't redefine this function, we
+  // should refuse to combine.
+  if (is_exact_type(get_class_type())) {
+    // No, we're an ordinary Node.
+    return other;
+  }
+
+  // We're something other than an ordinary Node.  Don't combine.
+  return (Node *)NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Node::transform_changed
 //       Access: Public, Virtual

+ 1 - 0
panda/src/graph/node.h

@@ -70,6 +70,7 @@ public:
   virtual bool safe_to_transform() const;
   virtual bool safe_to_combine() const;
   virtual void xform(const LMatrix4f &mat);
+  virtual Node *combine_with(Node *other); 
 
   virtual void transform_changed(NodeRelation *arc);
 

+ 28 - 0
panda/src/sgraph/geomNode.cxx

@@ -111,6 +111,34 @@ xform(const LMatrix4f &mat) {
   transformer.transform_vertices(this, mat);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GeomNode::combine_with
+//       Access: Public, Virtual
+//  Description: Collapses this node with the other node, if possible,
+//               and returns a pointer to the combined node, or NULL
+//               if the two nodes cannot safely be combined.
+//
+//               The return value may be this, other, or a new node
+//               altogether.
+//
+//               This function is called from GraphReducer::flatten(),
+//               and need not deal with children; its job is just to
+//               decide whether to collapse the two nodes and what the
+//               collapsed node should look like.
+////////////////////////////////////////////////////////////////////
+Node *GeomNode::
+combine_with(Node *other) {
+  if (is_exact_type(get_class_type()) &&
+      other->is_exact_type(get_class_type())) {
+    // Two GeomNodes can combine by moving Geoms from one to the other.
+    GeomNode *gother = DCAST(GeomNode, other);
+    add_geoms_from(gother);
+    return this;
+  }
+
+  return (Node *)NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomNode::write
 //       Access: Public

+ 1 - 0
panda/src/sgraph/geomNode.h

@@ -48,6 +48,7 @@ public:
 
   virtual Node *make_copy() const;
   virtual void xform(const LMatrix4f &mat);
+  virtual Node *combine_with(Node *other); 
 
   virtual void write(ostream &out, int indent_level = 0) const;
 

+ 6 - 11
panda/src/sgraphutil/sceneGraphReducer.cxx

@@ -304,17 +304,12 @@ collapse_nodes(Node *node1, Node *node2, bool siblings) {
   // We can collapse two GeomNodes easily, if they're siblings.  If
   // they're parent-child, we'd probably better not (it might
   // interfere with decaling).
-  if (siblings &&
-      node1->is_exact_type(GeomNode::get_class_type()) &&
+  if (node1->is_exact_type(GeomNode::get_class_type()) &&
       node2->is_exact_type(GeomNode::get_class_type())) {
-    GeomNode *gnode1;
-    DCAST_INTO_R(gnode1, node1, NULL);
-    GeomNode *gnode2;
-    DCAST_INTO_R(gnode2, node2, NULL);
-    gnode1->add_geoms_from(gnode2);
-    return gnode1;
-
-  } else {
-    return GraphReducer::collapse_nodes(node1, node2, siblings);
+    if (!siblings) {
+      return (Node *)NULL;
+    }
   }
+
+  return GraphReducer::collapse_nodes(node1, node2, siblings);
 }