]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/SGInteractionAnimation.cxx
Merge branch 'timoore/aptsign' into next
[simgear.git] / simgear / scene / model / SGInteractionAnimation.cxx
1 // Copyright (C) 2004-2007  Vivian Meazza
2 // Copyright (C) 2004-2009  Mathias Froehlich - Mathias.Froehlich@web.de
3 //
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Library General Public
6 // License as published by the Free Software Foundation; either
7 // version 2 of the License, or (at your option) any later version.
8 //
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // Library General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 //
18
19 #ifdef HAVE_CONFIG_H
20 #  include <simgear_config.h>
21 #endif
22
23 #include "SGInteractionAnimation.hxx"
24
25 #include <osg/Geode>
26 #include <osg/NodeVisitor>
27 #include <osg/TemplatePrimitiveFunctor>
28
29 #include <simgear/scene/util/SGSceneUserData.hxx>
30 #include <simgear/scene/bvh/BVHGroup.hxx>
31 #include <simgear/scene/bvh/BVHLineGeometry.hxx>
32
33 class SGInteractionAnimation::LineCollector : public osg::NodeVisitor {
34     struct LinePrimitiveFunctor {
35         LinePrimitiveFunctor() : _lineCollector(0)
36         { }
37         void operator() (const osg::Vec3&, bool)
38         { }
39         void operator() (const osg::Vec3& v1, const osg::Vec3& v2, bool)
40         { if (_lineCollector) _lineCollector->addLine(v1, v2); }
41         void operator() (const osg::Vec3&, const osg::Vec3&, const osg::Vec3&,
42                          bool)
43         { }
44         void operator() (const osg::Vec3&, const osg::Vec3&, const osg::Vec3&,
45                          const osg::Vec3&, bool)
46         { }
47         LineCollector* _lineCollector;
48     };
49     
50 public:
51     LineCollector() :
52         osg::NodeVisitor(osg::NodeVisitor::NODE_VISITOR,
53                          osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
54     { }
55     virtual void apply(osg::Geode& geode)
56     {
57         osg::TemplatePrimitiveFunctor<LinePrimitiveFunctor> pf;
58         pf._lineCollector = this;
59         for (unsigned i = 0; i < geode.getNumDrawables(); ++i) {
60             geode.getDrawable(i)->accept(pf);
61         }
62     }
63     virtual void apply(osg::Node& node)
64     {
65         traverse(node);
66     }
67     virtual void apply(osg::Transform& transform)
68     {
69         osg::Matrix matrix = _matrix;
70         if (transform.computeLocalToWorldMatrix(_matrix, this))
71             traverse(transform);
72         _matrix = matrix;
73     }
74     
75     const std::vector<SGLineSegmentf>& getLineSegments() const
76     { return _lineSegments; }
77     
78     void addLine(const osg::Vec3& v1, const osg::Vec3& v2)
79     {
80         // Trick to get the ends in the right order.
81         // Use the x axis in the original coordinate system. Choose the
82         // most negative x-axis as the one pointing forward
83         SGVec3f tv1(toSG(_matrix.preMult(v1)));
84         SGVec3f tv2(toSG(_matrix.preMult(v2)));
85         if (tv1[0] > tv2[0])
86             _lineSegments.push_back(SGLineSegmentf(tv1, tv2));
87         else
88             _lineSegments.push_back(SGLineSegmentf(tv2, tv1));
89     }
90
91     void addBVHElements(osg::Node& node, simgear::BVHLineGeometry::Type type)
92     {
93         if (_lineSegments.empty())
94             return;
95
96         SGSceneUserData* userData;
97         userData = SGSceneUserData::getOrCreateSceneUserData(&node);
98
99         simgear::BVHNode* bvNode = userData->getBVHNode();
100         if (!bvNode && _lineSegments.size() == 1) {
101             simgear::BVHLineGeometry* bvLine;
102             bvLine = new simgear::BVHLineGeometry(_lineSegments.front(), type);
103             userData->setBVHNode(bvLine);
104             return;
105         }
106
107         simgear::BVHGroup* group = new simgear::BVHGroup;
108         if (bvNode)
109             group->addChild(bvNode);
110
111         for (unsigned i = 0; i < _lineSegments.size(); ++i) {
112             simgear::BVHLineGeometry* bvLine;
113             bvLine = new simgear::BVHLineGeometry(_lineSegments[i], type);
114             group->addChild(bvLine);
115         }
116         userData->setBVHNode(group);
117     }
118     
119 private:
120     osg::Matrix _matrix;
121     std::vector<SGLineSegmentf> _lineSegments;
122 };
123
124 SGInteractionAnimation::SGInteractionAnimation(const SGPropertyNode* configNode,
125                                                SGPropertyNode* modelRoot) :
126   SGAnimation(configNode, modelRoot)
127 {
128 }
129
130 void
131 SGInteractionAnimation::install(osg::Node& node)
132 {
133   SGAnimation::install(node);
134
135   if (!getConfig()->hasChild("type"))
136       return;
137   std::string interactionType;
138   interactionType = getConfig()->getStringValue("interaction-type", "");
139
140   LineCollector lineCollector;
141   node.accept(lineCollector);
142
143   if (interactionType == "carrier-catapult") {
144       lineCollector.addBVHElements(node,
145                                    simgear::BVHLineGeometry::CarrierCatapult);
146   } else if (interactionType == "carrier-wire") {
147       lineCollector.addBVHElements(node,
148                                    simgear::BVHLineGeometry::CarrierWire);
149   } else {
150       SG_LOG(SG_IO, SG_ALERT, "Unknown interaction animation "
151              "interaction-type \"" << interactionType << "\". Ignoring!");
152   }
153 }
154
155