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