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/OsgMath.hxx>
30 #include <simgear/scene/util/SGSceneUserData.hxx>
31 #include <simgear/scene/bvh/BVHGroup.hxx>
32 #include <simgear/scene/bvh/BVHLineGeometry.hxx>
34 class SGInteractionAnimation::LineCollector : public osg::NodeVisitor {
35 struct LinePrimitiveFunctor {
36 LinePrimitiveFunctor() : _lineCollector(0)
38 void operator() (const osg::Vec3&, bool)
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&,
45 void operator() (const osg::Vec3&, const osg::Vec3&, const osg::Vec3&,
46 const osg::Vec3&, bool)
48 LineCollector* _lineCollector;
53 osg::NodeVisitor(osg::NodeVisitor::NODE_VISITOR,
54 osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
56 virtual void apply(osg::Geode& geode)
58 osg::TemplatePrimitiveFunctor<LinePrimitiveFunctor> pf;
59 pf._lineCollector = this;
60 for (unsigned i = 0; i < geode.getNumDrawables(); ++i) {
61 geode.getDrawable(i)->accept(pf);
64 virtual void apply(osg::Node& node)
68 virtual void apply(osg::Transform& transform)
70 osg::Matrix matrix = _matrix;
71 if (transform.computeLocalToWorldMatrix(_matrix, this))
76 const std::vector<SGLineSegmentf>& getLineSegments() const
77 { return _lineSegments; }
79 void addLine(const osg::Vec3& v1, const osg::Vec3& v2)
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)));
87 _lineSegments.push_back(SGLineSegmentf(tv1, tv2));
89 _lineSegments.push_back(SGLineSegmentf(tv2, tv1));
92 void addBVHElements(osg::Node& node, simgear::BVHLineGeometry::Type type)
94 if (_lineSegments.empty())
97 SGSceneUserData* userData;
98 userData = SGSceneUserData::getOrCreateSceneUserData(&node);
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);
108 simgear::BVHGroup* group = new simgear::BVHGroup;
110 group->addChild(bvNode);
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);
117 userData->setBVHNode(group);
122 std::vector<SGLineSegmentf> _lineSegments;
125 SGInteractionAnimation::SGInteractionAnimation(const SGPropertyNode* configNode,
126 SGPropertyNode* modelRoot) :
127 SGAnimation(configNode, modelRoot)
132 SGInteractionAnimation::install(osg::Node& node)
134 SGAnimation::install(node);
136 if (!getConfig()->hasChild("type"))
138 std::string interactionType;
139 interactionType = getConfig()->getStringValue("interaction-type", "");
141 LineCollector lineCollector;
142 node.accept(lineCollector);
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);
151 SG_LOG(SG_IO, SG_ALERT, "Unknown interaction animation "
152 "interaction-type \"" << interactionType << "\". Ignoring!");