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