1 // Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de 2 // 3 // This library is free software; you can redistribute it and/or 4 // modify it under the terms of the GNU Library General Public 5 // License as published by the Free Software Foundation; either 6 // version 2 of the License, or (at your option) any later version. 7 // 8 // This library is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 // Library General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with this program; if not, write to the Free Software 15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 // 17 18 #ifndef BVHDebugCollectVisitor_hxx 19 #define BVHDebugCollectVisitor_hxx 20 21 #include <osg/ref_ptr> 22 #include <osg/Geode> 23 #include <osg/Geometry> 24 #include <osg/Group> 25 #include <osg/PolygonOffset> 26 #include <osg/PrimitiveSet> 27 #include <osg/MatrixTransform> 28 #include <osg/ShapeDrawable> 29 #include <osg/Shape> 30 #include <osg/Depth> 31 #include <osg/BlendFunc> 32 #include <osg/StateSet> 33 34 #include <simgear/math/SGGeometry.hxx> 35 #include <simgear/scene/util/OsgMath.hxx> 36 37 #include <simgear/bvh/BVHVisitor.hxx> 38 #include <simgear/bvh/BVHNode.hxx> 39 #include <simgear/bvh/BVHGroup.hxx> 40 #include <simgear/bvh/BVHTransform.hxx> 41 #include <simgear/bvh/BVHMotionTransform.hxx> 42 #include <simgear/bvh/BVHStaticGeometry.hxx> 43 44 #include <simgear/bvh/BVHStaticData.hxx> 45 46 #include <simgear/bvh/BVHStaticNode.hxx> 47 #include <simgear/bvh/BVHStaticTriangle.hxx> 48 #include <simgear/bvh/BVHStaticBinary.hxx> 49 50 #include <simgear/bvh/BVHBoundingBoxVisitor.hxx> 51 52 namespace simgear { 53 54 class BVHNode; 55 class BVHStaticNode; 56 57 class BVHDebugCollectVisitor : public BVHVisitor { 58 public: BVHDebugCollectVisitor(const double & time,unsigned level=~0u)59 BVHDebugCollectVisitor(const double& time, unsigned level = ~0u) : 60 _group(new osg::Group), 61 _time(time), 62 _level(level), 63 _currentLevel(0) 64 { 65 osg::StateSet* stateSet = _group->getOrCreateStateSet(); 66 stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); 67 stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF); 68 stateSet->setAttribute(new osg::Depth(osg::Depth::LESS, 0, 1, false)); 69 osg::BlendFunc *blendFunc; 70 blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, 71 osg::BlendFunc::DST_ALPHA); 72 stateSet->setAttributeAndModes(blendFunc); 73 osg::PolygonOffset* polygonOffset = new osg::PolygonOffset(-1, -1); 74 stateSet->setAttributeAndModes(polygonOffset); 75 } ~BVHDebugCollectVisitor()76 virtual ~BVHDebugCollectVisitor() 77 { } 78 apply(BVHGroup & node)79 virtual void apply(BVHGroup& node) 80 { 81 addNodeSphere(node); 82 ++_currentLevel; 83 node.traverse(*this); 84 --_currentLevel; 85 } apply(BVHTransform & node)86 virtual void apply(BVHTransform& node) 87 { 88 addNodeSphere(node); 89 osg::ref_ptr<osg::Group> oldGroup = _group; 90 osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform; 91 transform->setMatrix(osg::Matrix(node.getToWorldTransform().data())); 92 _group = transform; 93 ++_currentLevel; 94 node.traverse(*this); 95 --_currentLevel; 96 _group = oldGroup; 97 if (transform->getNumChildren()) 98 _group->addChild(transform.get()); 99 } apply(BVHMotionTransform & node)100 virtual void apply(BVHMotionTransform& node) 101 { 102 addNodeSphere(node); 103 osg::ref_ptr<osg::Group> oldGroup = _group; 104 osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform; 105 transform->setMatrix(osg::Matrix(node.getToWorldTransform(_time).data())); 106 _group = transform; 107 ++_currentLevel; 108 node.traverse(*this); 109 --_currentLevel; 110 _group = oldGroup; 111 if (transform->getNumChildren()) 112 _group->addChild(transform.get()); 113 } apply(BVHPageNode & leaf)114 virtual void apply(BVHPageNode& leaf) 115 { 116 leaf.traverse(*this); 117 } 118 apply(BVHLineGeometry &)119 virtual void apply(BVHLineGeometry&) 120 { 121 } apply(BVHStaticGeometry & node)122 virtual void apply(BVHStaticGeometry& node) 123 { 124 addNodeSphere(node); 125 ++_currentLevel; 126 node.traverse(*this); 127 --_currentLevel; 128 } 129 apply(const BVHStaticBinary & node,const BVHStaticData & data)130 virtual void apply(const BVHStaticBinary& node, const BVHStaticData& data) 131 { 132 addNodeBox(node, data); 133 ++_currentLevel; 134 node.traverse(*this, data); 135 --_currentLevel; 136 } apply(const BVHStaticTriangle & node,const BVHStaticData & data)137 virtual void apply(const BVHStaticTriangle& node, const BVHStaticData& data) 138 { 139 addNodeBox(node, data); 140 addTriangle(node.getTriangle(data), osg::Vec4(0.5, 0, 0.5, 0.2)); 141 } 142 getNode() const143 osg::Node* getNode() const { return _group.get(); } 144 allLevels()145 static unsigned allLevels() { return ~0u; } triangles()146 static unsigned triangles() { return ~0u - 1; } 147 148 private: addTriangle(const SGTrianglef & triangle,const osg::Vec4 & color)149 void addTriangle(const SGTrianglef& triangle, const osg::Vec4& color) 150 { 151 if (_level != triangles()) 152 return; 153 154 osg::Geometry* geometry = new osg::Geometry; 155 156 osg::Vec3Array* vertices = new osg::Vec3Array; 157 vertices->push_back(toOsg(triangle.getVertex(0))); 158 vertices->push_back(toOsg(triangle.getVertex(1))); 159 vertices->push_back(toOsg(triangle.getVertex(2))); 160 161 osg::Vec4Array* colors = new osg::Vec4Array; 162 colors->push_back(color); 163 164 geometry->setVertexArray(vertices); 165 geometry->setColorArray(colors); 166 geometry->setColorBinding(osg::Geometry::BIND_OVERALL); 167 168 geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, 3)); 169 170 osg::Geode* geode = new osg::Geode; 171 geode->addDrawable(geometry); 172 _group->addChild(geode); 173 } 174 addNodeSphere(const BVHNode & node)175 void addNodeSphere(const BVHNode& node) 176 { 177 if (_level != ~0u && _level != _currentLevel) 178 return; 179 SGSphered sphere = node.getBoundingSphere(); 180 osg::Sphere* shape = new osg::Sphere; 181 shape->setCenter(toOsg(sphere.getCenter())); 182 shape->setRadius(sphere.getRadius()); 183 addShape(shape, osg::Vec4(0.5f, 0.5f, 0.5f, 0.1f)); 184 } 185 addNodeBox(const BVHStaticNode & node,const BVHStaticData & data)186 void addNodeBox(const BVHStaticNode& node, const BVHStaticData& data) 187 { 188 if (_level != ~0u && _level != _currentLevel) 189 return; 190 BVHBoundingBoxVisitor bbv; 191 node.accept(bbv, data); 192 osg::Box* shape = new osg::Box; 193 shape->setCenter(toOsg(bbv.getBox().getCenter())); 194 shape->setHalfLengths(toOsg((0.5*bbv.getBox().getSize()))); 195 addShape(shape, osg::Vec4(0.5f, 0, 0, 0.1f)); 196 } 197 addShape(osg::Shape * shape,const osg::Vec4 & color)198 void addShape(osg::Shape* shape, const osg::Vec4& color) 199 { 200 osg::ShapeDrawable* shapeDrawable = new osg::ShapeDrawable; 201 shapeDrawable->setColor(color); 202 shapeDrawable->setShape(shape); 203 osg::Geode* geode = new osg::Geode; 204 geode->addDrawable(shapeDrawable); 205 _group->addChild(geode); 206 } 207 208 osg::ref_ptr<osg::Group> _group; 209 const double _time; 210 const unsigned _level; 211 unsigned _currentLevel; 212 }; 213 214 } 215 216 #endif 217