]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/SGInteractionAnimation.cxx
Propagate the lanel loader through the options.
[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 #include "SGInteractionAnimation.hxx"
20
21 #include <osg/Geode>
22 #include <osg/NodeVisitor>
23 #include <osg/TemplatePrimitiveFunctor>
24
25 #include <simgear/scene/util/SGSceneUserData.hxx>
26 #include <simgear/scene/bvh/BVHGroup.hxx>
27 #include <simgear/scene/bvh/BVHLineGeometry.hxx>
28
29 class SGInteractionAnimation::LineCollector : public osg::NodeVisitor {
30     struct LinePrimitiveFunctor {
31         LinePrimitiveFunctor() : _lineCollector(0)
32         { }
33         void operator() (const osg::Vec3&, bool)
34         { }
35         void operator() (const osg::Vec3& v1, const osg::Vec3& v2, bool)
36         { if (_lineCollector) _lineCollector->addLine(v1, v2); }
37         void operator() (const osg::Vec3&, const osg::Vec3&, const osg::Vec3&,
38                          bool)
39         { }
40         void operator() (const osg::Vec3&, const osg::Vec3&, const osg::Vec3&,
41                          const osg::Vec3&, bool)
42         { }
43         LineCollector* _lineCollector;
44     };
45     
46 public:
47     LineCollector() :
48         osg::NodeVisitor(osg::NodeVisitor::NODE_VISITOR,
49                          osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
50     { }
51     virtual void apply(osg::Geode& geode)
52     {
53         osg::TemplatePrimitiveFunctor<LinePrimitiveFunctor> pf;
54         pf._lineCollector = this;
55         for (unsigned i = 0; i < geode.getNumDrawables(); ++i) {
56             geode.getDrawable(i)->accept(pf);
57         }
58     }
59     virtual void apply(osg::Node& node)
60     {
61         traverse(node);
62     }
63     virtual void apply(osg::Transform& transform)
64     {
65         osg::Matrix matrix = _matrix;
66         if (transform.computeLocalToWorldMatrix(_matrix, this))
67             traverse(transform);
68         _matrix = matrix;
69     }
70     
71     const std::vector<SGLineSegmentf>& getLineSegments() const
72     { return _lineSegments; }
73     
74     void addLine(const osg::Vec3& v1, const osg::Vec3& v2)
75     {
76         // Trick to get the ends in the right order.
77         // Use the x axis in the original coordinate system. Choose the
78         // most negative x-axis as the one pointing forward
79         SGVec3f tv1(_matrix.preMult(v1));
80         SGVec3f tv2(_matrix.preMult(v2));
81         if (tv1[0] > tv2[0])
82             _lineSegments.push_back(SGLineSegmentf(tv1, tv2));
83         else
84             _lineSegments.push_back(SGLineSegmentf(tv2, tv1));
85     }
86
87     void addBVHElements(osg::Node& node, simgear::BVHLineGeometry::Type type)
88     {
89         if (_lineSegments.empty())
90             return;
91
92         SGSceneUserData* userData;
93         userData = SGSceneUserData::getOrCreateSceneUserData(&node);
94
95         simgear::BVHNode* bvNode = userData->getBVHNode();
96         if (!bvNode && _lineSegments.size() == 1) {
97             simgear::BVHLineGeometry* bvLine;
98             bvLine = new simgear::BVHLineGeometry(_lineSegments.front(), type);
99             userData->setBVHNode(bvLine);
100             return;
101         }
102
103         simgear::BVHGroup* group = new simgear::BVHGroup;
104         if (bvNode)
105             group->addChild(bvNode);
106
107         for (unsigned i = 0; i < _lineSegments.size(); ++i) {
108             simgear::BVHLineGeometry* bvLine;
109             bvLine = new simgear::BVHLineGeometry(_lineSegments[i], type);
110             group->addChild(bvLine);
111         }
112         userData->setBVHNode(group);
113     }
114     
115 private:
116     osg::Matrix _matrix;
117     std::vector<SGLineSegmentf> _lineSegments;
118 };
119
120 SGInteractionAnimation::SGInteractionAnimation(const SGPropertyNode* configNode,
121                                                SGPropertyNode* modelRoot) :
122   SGAnimation(configNode, modelRoot)
123 {
124 }
125
126 void
127 SGInteractionAnimation::install(osg::Node& node)
128 {
129   SGAnimation::install(node);
130
131   if (!getConfig()->hasChild("type"))
132       return;
133   std::string interactionType;
134   interactionType = getConfig()->getStringValue("interaction-type", "");
135
136   LineCollector lineCollector;
137   node.accept(lineCollector);
138
139   if (interactionType == "carrier-catapult") {
140       lineCollector.addBVHElements(node,
141                                    simgear::BVHLineGeometry::CarrierCatapult);
142   } else if (interactionType == "carrier-wire") {
143       lineCollector.addBVHElements(node,
144                                    simgear::BVHLineGeometry::CarrierWire);
145   } else {
146       SG_LOG(SG_IO, SG_ALERT, "Unknown interaction animation "
147              "interaction-type \"" << interactionType << "\". Ignoring!");
148   }
149 }
150
151