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.
20 # include <simgear_config.h>
23 #include "SGInteractionAnimation.hxx"
26 #include <osg/NodeVisitor>
27 #include <osg/TemplatePrimitiveFunctor>
29 #include <simgear/scene/util/SGSceneUserData.hxx>
30 #include <simgear/scene/bvh/BVHGroup.hxx>
31 #include <simgear/scene/bvh/BVHLineGeometry.hxx>
33 class SGInteractionAnimation::LineCollector : public osg::NodeVisitor {
34 struct LinePrimitiveFunctor {
35 LinePrimitiveFunctor() : _lineCollector(0)
37 void operator() (const osg::Vec3&, bool)
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&,
44 void operator() (const osg::Vec3&, const osg::Vec3&, const osg::Vec3&,
45 const osg::Vec3&, bool)
47 LineCollector* _lineCollector;
52 osg::NodeVisitor(osg::NodeVisitor::NODE_VISITOR,
53 osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
55 virtual void apply(osg::Geode& geode)
57 osg::TemplatePrimitiveFunctor<LinePrimitiveFunctor> pf;
58 pf._lineCollector = this;
59 for (unsigned i = 0; i < geode.getNumDrawables(); ++i) {
60 geode.getDrawable(i)->accept(pf);
63 virtual void apply(osg::Node& node)
67 virtual void apply(osg::Transform& transform)
69 osg::Matrix matrix = _matrix;
70 if (transform.computeLocalToWorldMatrix(_matrix, this))
75 const std::vector<SGLineSegmentf>& getLineSegments() const
76 { return _lineSegments; }
78 void addLine(const osg::Vec3& v1, const osg::Vec3& v2)
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)));
86 _lineSegments.push_back(SGLineSegmentf(tv1, tv2));
88 _lineSegments.push_back(SGLineSegmentf(tv2, tv1));
91 void addBVHElements(osg::Node& node, simgear::BVHLineGeometry::Type type)
93 if (_lineSegments.empty())
96 SGSceneUserData* userData;
97 userData = SGSceneUserData::getOrCreateSceneUserData(&node);
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);
107 simgear::BVHGroup* group = new simgear::BVHGroup;
109 group->addChild(bvNode);
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);
116 userData->setBVHNode(group);
121 std::vector<SGLineSegmentf> _lineSegments;
124 SGInteractionAnimation::SGInteractionAnimation(const SGPropertyNode* configNode,
125 SGPropertyNode* modelRoot) :
126 SGAnimation(configNode, modelRoot)
131 SGInteractionAnimation::install(osg::Node& node)
133 SGAnimation::install(node);
135 if (!getConfig()->hasChild("type"))
137 std::string interactionType;
138 interactionType = getConfig()->getStringValue("interaction-type", "");
140 LineCollector lineCollector;
141 node.accept(lineCollector);
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);
150 SG_LOG(SG_IO, SG_ALERT, "Unknown interaction animation "
151 "interaction-type \"" << interactionType << "\". Ignoring!");