00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 # include <simgear_config.h>
00021 #endif
00022
00023 #include "SGInteractionAnimation.hxx"
00024
00025 #include <osg/Geode>
00026 #include <osg/NodeVisitor>
00027 #include <osg/TemplatePrimitiveFunctor>
00028
00029 #include <simgear/scene/util/SGSceneUserData.hxx>
00030 #include <simgear/scene/bvh/BVHGroup.hxx>
00031 #include <simgear/scene/bvh/BVHLineGeometry.hxx>
00032
00033 class SGInteractionAnimation::LineCollector : public osg::NodeVisitor {
00034 struct LinePrimitiveFunctor {
00035 LinePrimitiveFunctor() : _lineCollector(0)
00036 { }
00037 void operator() (const osg::Vec3&, bool)
00038 { }
00039 void operator() (const osg::Vec3& v1, const osg::Vec3& v2, bool)
00040 { if (_lineCollector) _lineCollector->addLine(v1, v2); }
00041 void operator() (const osg::Vec3&, const osg::Vec3&, const osg::Vec3&,
00042 bool)
00043 { }
00044 void operator() (const osg::Vec3&, const osg::Vec3&, const osg::Vec3&,
00045 const osg::Vec3&, bool)
00046 { }
00047 LineCollector* _lineCollector;
00048 };
00049
00050 public:
00051 LineCollector() :
00052 osg::NodeVisitor(osg::NodeVisitor::NODE_VISITOR,
00053 osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
00054 { }
00055 virtual void apply(osg::Geode& geode)
00056 {
00057 osg::TemplatePrimitiveFunctor<LinePrimitiveFunctor> pf;
00058 pf._lineCollector = this;
00059 for (unsigned i = 0; i < geode.getNumDrawables(); ++i) {
00060 geode.getDrawable(i)->accept(pf);
00061 }
00062 }
00063 virtual void apply(osg::Node& node)
00064 {
00065 traverse(node);
00066 }
00067 virtual void apply(osg::Transform& transform)
00068 {
00069 osg::Matrix matrix = _matrix;
00070 if (transform.computeLocalToWorldMatrix(_matrix, this))
00071 traverse(transform);
00072 _matrix = matrix;
00073 }
00074
00075 const std::vector<SGLineSegmentf>& getLineSegments() const
00076 { return _lineSegments; }
00077
00078 void addLine(const osg::Vec3& v1, const osg::Vec3& v2)
00079 {
00080
00081
00082
00083 SGVec3f tv1(toSG(_matrix.preMult(v1)));
00084 SGVec3f tv2(toSG(_matrix.preMult(v2)));
00085 if (tv1[0] > tv2[0])
00086 _lineSegments.push_back(SGLineSegmentf(tv1, tv2));
00087 else
00088 _lineSegments.push_back(SGLineSegmentf(tv2, tv1));
00089 }
00090
00091 void addBVHElements(osg::Node& node, simgear::BVHLineGeometry::Type type)
00092 {
00093 if (_lineSegments.empty())
00094 return;
00095
00096 SGSceneUserData* userData;
00097 userData = SGSceneUserData::getOrCreateSceneUserData(&node);
00098
00099 simgear::BVHNode* bvNode = userData->getBVHNode();
00100 if (!bvNode && _lineSegments.size() == 1) {
00101 simgear::BVHLineGeometry* bvLine;
00102 bvLine = new simgear::BVHLineGeometry(_lineSegments.front(), type);
00103 userData->setBVHNode(bvLine);
00104 return;
00105 }
00106
00107 simgear::BVHGroup* group = new simgear::BVHGroup;
00108 if (bvNode)
00109 group->addChild(bvNode);
00110
00111 for (unsigned i = 0; i < _lineSegments.size(); ++i) {
00112 simgear::BVHLineGeometry* bvLine;
00113 bvLine = new simgear::BVHLineGeometry(_lineSegments[i], type);
00114 group->addChild(bvLine);
00115 }
00116 userData->setBVHNode(group);
00117 }
00118
00119 private:
00120 osg::Matrix _matrix;
00121 std::vector<SGLineSegmentf> _lineSegments;
00122 };
00123
00124 SGInteractionAnimation::SGInteractionAnimation(const SGPropertyNode* configNode,
00125 SGPropertyNode* modelRoot) :
00126 SGAnimation(configNode, modelRoot)
00127 {
00128 }
00129
00130 void
00131 SGInteractionAnimation::install(osg::Node& node)
00132 {
00133 SGAnimation::install(node);
00134
00135 if (!getConfig()->hasChild("type"))
00136 return;
00137 std::string interactionType;
00138 interactionType = getConfig()->getStringValue("interaction-type", "");
00139
00140 LineCollector lineCollector;
00141 node.accept(lineCollector);
00142
00143 if (interactionType == "carrier-catapult") {
00144 lineCollector.addBVHElements(node,
00145 simgear::BVHLineGeometry::CarrierCatapult);
00146 } else if (interactionType == "carrier-wire") {
00147 lineCollector.addBVHElements(node,
00148 simgear::BVHLineGeometry::CarrierWire);
00149 } else {
00150 SG_LOG(SG_IO, SG_ALERT, "Unknown interaction animation "
00151 "interaction-type \"" << interactionType << "\". Ignoring!");
00152 }
00153 }
00154
00155