better system for combining nodes in flattenStrong

This commit is contained in:
David Rose 2001-06-14 01:25:10 +00:00
parent e161452942
commit 25ba7f73a8
8 changed files with 103 additions and 27 deletions

View File

@ -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);
}
////////////////////////////////////////////////////////////////////

View File

@ -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

View File

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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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);
}