1 // Copyright (C) 2004-2007 Vivian Meazza
2 // Copyright (C) 2004-2009 Mathias Froehlich - Mathias.Froehlich@web.de
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.
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.
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.
19 #include "SGInteractionAnimation.hxx"
22 #include <osg/NodeVisitor>
23 #include <osg/TemplatePrimitiveFunctor>
25 #include <simgear/scene/util/SGSceneUserData.hxx>
26 #include <simgear/scene/bvh/BVHGroup.hxx>
27 #include <simgear/scene/bvh/BVHLineGeometry.hxx>
29 class SGInteractionAnimation::LineCollector : public osg::NodeVisitor {
30 struct LinePrimitiveFunctor {
31 LinePrimitiveFunctor() : _lineCollector(0)
33 void operator() (const osg::Vec3&, bool)
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&,
40 void operator() (const osg::Vec3&, const osg::Vec3&, const osg::Vec3&,
41 const osg::Vec3&, bool)
43 LineCollector* _lineCollector;
48 osg::NodeVisitor(osg::NodeVisitor::NODE_VISITOR,
49 osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
51 virtual void apply(osg::Geode& geode)
53 osg::TemplatePrimitiveFunctor<LinePrimitiveFunctor> pf;
54 pf._lineCollector = this;
55 for (unsigned i = 0; i < geode.getNumDrawables(); ++i) {
56 geode.getDrawable(i)->accept(pf);
59 virtual void apply(osg::Node& node)
63 virtual void apply(osg::Transform& transform)
65 osg::Matrix matrix = _matrix;
66 if (transform.computeLocalToWorldMatrix(_matrix, this))
71 const std::vector<SGLineSegmentf>& getLineSegments() const
72 { return _lineSegments; }
74 void addLine(const osg::Vec3& v1, const osg::Vec3& v2)
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));
82 _lineSegments.push_back(SGLineSegmentf(tv1, tv2));
84 _lineSegments.push_back(SGLineSegmentf(tv2, tv1));
87 void addBVHElements(osg::Node& node, simgear::BVHLineGeometry::Type type)
89 if (_lineSegments.empty())
92 SGSceneUserData* userData;
93 userData = SGSceneUserData::getOrCreateSceneUserData(&node);
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);
103 simgear::BVHGroup* group = new simgear::BVHGroup;
105 group->addChild(bvNode);
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);
112 userData->setBVHNode(group);
117 std::vector<SGLineSegmentf> _lineSegments;
120 SGInteractionAnimation::SGInteractionAnimation(const SGPropertyNode* configNode,
121 SGPropertyNode* modelRoot) :
122 SGAnimation(configNode, modelRoot)
127 SGInteractionAnimation::install(osg::Node& node)
129 SGAnimation::install(node);
131 if (!getConfig()->hasChild("type"))
133 std::string interactionType;
134 interactionType = getConfig()->getStringValue("interaction-type", "");
136 LineCollector lineCollector;
137 node.accept(lineCollector);
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);
146 SG_LOG(SG_IO, SG_ALERT, "Unknown interaction animation "
147 "interaction-type \"" << interactionType << "\". Ignoring!");