]> git.mxchange.org Git - simgear.git/blob - simgear/scene/util/SplicingVisitor.cxx
Work around apparent OSG 3.2.0 normal binding bug.
[simgear.git] / simgear / scene / util / SplicingVisitor.cxx
1 #include "SplicingVisitor.hxx"
2
3 namespace simgear
4 {
5 using namespace osg;
6
7 SplicingVisitor::SplicingVisitor()
8     : NodeVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN)
9 {
10     _childStack.push_back(NodeList());
11 }
12
13 void SplicingVisitor::reset()
14 {
15     _childStack.clear();
16     NodeVisitor::reset();
17 }
18
19 NodeList SplicingVisitor::traverse(Node& node)
20 {
21     NodeList result;
22     _childStack.push_back(NodeList());
23     NodeVisitor::traverse(node);
24     result = _childStack.back();
25     _childStack.pop_back();
26     return result;
27 }
28 void SplicingVisitor::apply(Node& node)
29 {
30     NodeVisitor::traverse(node);
31     pushNode(&node);
32 }
33
34 void SplicingVisitor::apply(Group& node)
35 {
36     if (pushNode(getNewNode(node)))
37         return;
38     pushResultNode(&node, &node, traverse(node));
39 }
40
41 Group* SplicingVisitor::pushResultNode(Group* node, Group* newNode,
42                                        const NodeList& children)
43 {
44     ref_ptr<Group> result;
45     if (node == newNode) {
46         result = copyIfNeeded(*node, children);
47     } else {
48         result = newNode;
49         for (NodeList::const_iterator itr = children.begin(), end = children.end();
50              itr != end;
51              ++itr)
52             result->addChild(itr->get());
53     }
54     _childStack.back().push_back(result);
55     recordNewNode(node, result.get());
56     return result.get();
57 }
58
59 Node* SplicingVisitor::pushResultNode(Node* node, Node* newNode)
60 {
61     _childStack.back().push_back(newNode);
62     recordNewNode(node, newNode);
63     return newNode;
64 }
65
66 Node* SplicingVisitor::pushNode(Node* node)
67 {
68     if (node)
69         _childStack.back().push_back(node);
70     return node;
71 }
72
73 Node* SplicingVisitor::getResult()
74 {
75     NodeList& top = _childStack.at(0);
76     if (top.empty()) {
77         return 0;
78     } else if (top.size() == 1) {
79         return top[0].get();
80     } else {
81         Group* result = new Group;
82         for (NodeList::iterator itr = top.begin(), end = top.end();
83              itr != end;
84              ++itr)
85             result->addChild(itr->get());
86         return result;
87     }
88 }
89
90 Node* SplicingVisitor::getNewNode(osg::Node* node)
91 {
92     ref_ptr<Node> tmpPtr(node);
93     NodeMap::iterator itr;
94     try {
95         itr = _visited.find(tmpPtr);
96     }
97     catch (...) {
98         tmpPtr.release();
99         throw;
100     }
101     if (itr == _visited.end())
102         return 0;
103     else
104         return itr->second.get();
105 }
106
107 bool SplicingVisitor::recordNewNode(osg::Node* oldNode, osg::Node* newNode)
108 {
109     ref_ptr<Node> oldTmp(oldNode);
110     ref_ptr<Node> newTmp(newNode);
111     return _visited.insert(std::make_pair(oldTmp, newTmp)).second;
112 }
113 }