root/OpenSceneGraph/trunk/examples/osgkdtree/osgkdtree.cpp @ 8410

Revision 8410, 13.9 kB (checked in by robert, 6 years ago)

Basic implementation of kdtree generation based on vertices

Line 
1/* OpenSceneGraph example, osgintersection.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18
19 
20#include <osgDB/ReadFile>
21
22#define _GLIBCXX_DEBUG
23
24#include <osg/ArgumentParser>
25#include <osg/ApplicationUsage>
26#include <osg/Timer>
27#include <osg/CoordinateSystemNode>
28#include <osg/Notify>
29#include <osg/io_utils>
30#include <osg/Geometry>
31
32
33#include <osgUtil/IntersectionVisitor>
34#include <osgUtil/LineSegmentIntersector>
35
36#include <osgSim/LineOfSight>
37#include <osgSim/HeightAboveTerrain>
38#include <osgSim/ElevationSlice>
39
40#include <iostream>
41
42
43namespace osg
44{
45
46class KDNode
47{
48    public:
49   
50        KDNode():
51            _leftChild(0),
52            _rightChild(0) {}
53   
54        KDNode(const KDNode& rhs):
55            _leftChild(rhs._leftChild),
56            _rightChild(rhs._rightChild) {}
57
58        KDNode& operator = (const KDNode& rhs)
59        {
60            _leftChild = rhs._leftChild;
61            _rightChild = rhs._rightChild;
62            return *this;
63        }
64
65        typedef int value_type;
66
67        value_type _leftChild;
68        value_type _rightChild;
69};
70
71class KDLeaf : public osg::Referenced
72{
73    public:
74   
75        KDLeaf() {}
76   
77        typedef unsigned int index_type;
78        typedef std::vector< index_type > Indices;
79
80        Indices _vertexIndices;       
81   
82    protected:
83   
84        virtual ~KDLeaf() {}
85};
86
87class KDTree : public osg::Shape
88{
89    public:
90   
91   
92        KDTree() {}
93       
94        KDTree(const KDTree& rhs, const CopyOp& copyop=CopyOp::SHALLOW_COPY):
95            Shape(rhs,copyop) {}
96
97        META_Shape(osg, KDTree)
98   
99        typedef std::vector< unsigned int > AxisStack;
100        typedef std::vector< KDNode > KDNodeList;
101        typedef std::vector< osg::ref_ptr<KDLeaf> > KDLeafList;
102       
103       
104        /// note, leafNum is negative to distinguish from nodeNum
105        int addLeaf(KDLeaf* leaf) { int num = _kdLeaves.size(); _kdLeaves.push_back(leaf); return -(num+1); }
106
107        int replaceLeaf(int leafNum, KDLeaf* leaf)
108        {
109            int num = -leafNum-1;
110           
111            if (num>_kdLeaves.size()-1)
112            {
113                osg::notify(osg::NOTICE)<<"Warning: replaceChild("<<leafNum<<", leaf), num = "<<num<<" _kdLeaves.size()="<<_kdLeaves.size()<<std::endl;
114                return leafNum;
115            }
116           
117            _kdLeaves[num] = leaf; return leafNum;
118        }
119
120        /// note, leafNum is negative to distinguish from nodeNum
121        KDLeaf* getLeaf(int leafNum)
122        {
123            int num = -leafNum-1;
124            if (num<0 || num>_kdLeaves.size()-1)
125            {
126                osg::notify(osg::NOTICE)<<"Warning: getLeaf("<<leafNum<<", num = "<<num<<") _kdLeaves.size()="<<_kdLeaves.size()<<std::endl;
127                return 0;
128            }
129
130            return _kdLeaves[num].get();
131        }
132       
133        int addNode(const KDNode& node)
134        {
135            int num = _kdNodes.size();
136            _kdNodes.push_back(node);
137            return num;
138        }
139
140        /// note, nodeNum is positive to distinguish from leftNum
141        KDNode& getNode(int nodeNum)
142        {
143            if (nodeNum<0 || nodeNum>_kdNodes.size()-1)
144            {
145                osg::notify(osg::NOTICE)<<"Warning: getNode("<<nodeNum<<") _kdNodes.size()="<<_kdNodes.size()<<std::endl;
146            }
147            return _kdNodes[nodeNum];
148        }
149
150
151        osg::observer_ptr<osg::Geometry> _geometry;
152
153        osg::BoundingBox                _bb;
154
155        AxisStack                       _axisStack;
156        KDNodeList                      _kdNodes;
157        KDLeafList                      _kdLeaves;
158};
159
160class KDTreeTraverser
161{
162    public:
163   
164   
165        std::ostream& output(unsigned int level)
166        {
167            for(unsigned int i=0; i<level; ++i)
168            {
169                osg::notify(osg::NOTICE)<<"  ";
170            }
171            return osg::notify(osg::NOTICE);
172        }
173   
174
175        void traverse(KDLeaf& leaf, unsigned int level)
176        {
177            output(level)<<"leaf("<<level<<") { ";
178
179            for(unsigned int i=0; i<leaf._vertexIndices.size(); ++i)
180            {
181                if (i==0) osg::notify(osg::NOTICE)<<leaf._vertexIndices[i];
182                else osg::notify(osg::NOTICE)<<", "<<leaf._vertexIndices[i];               
183            }
184
185            osg::notify(osg::NOTICE)<<"}"<<std::endl;;
186           
187        }
188
189        void traverse(KDTree& tree, KDNode::value_type nodeIndex, unsigned int level)
190        {
191            output(level)<<"traverse("<<nodeIndex<<", "<< level<<") { "<<std::endl;
192           
193            if (nodeIndex>=0)
194            {       
195                KDNode& node = tree._kdNodes[nodeIndex];
196                if (node._leftChild) traverse(tree,node._leftChild,level+1);
197                else output(level+1)<<"empty left child()"<<std::endl;
198               
199                if (node._rightChild) traverse(tree,node._rightChild,level+1);
200                else output(level+1)<<"empty right child()"<<std::endl;
201            }
202            else 
203            {
204                KDNode::value_type leafIndex = -nodeIndex-1;
205                KDLeaf& leaf = *(tree._kdLeaves[leafIndex]);
206                traverse(leaf, level);
207            }
208
209            output(level)<<"}"<<std::endl;;
210        }
211
212
213        void traverse(KDTree& tree)
214        {
215            osg::notify(osg::NOTICE)<<"traverse(tree)"<<std::endl;
216            if (!tree._kdNodes.empty())
217            {
218                traverse(tree,0,0);
219            }
220            else if (!tree._kdLeaves.empty())
221            {
222                traverse(*tree._kdLeaves.front(), 0);
223            }
224        }
225   
226};
227
228
229class KDTreeBuilder : public osg::NodeVisitor
230{
231    public:
232   
233        KDTreeBuilder():
234            osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
235            _maxNumLevels(24),
236            _targetNumVerticesPerLeaf(8)           
237        {           
238        }
239   
240   
241        void apply(osg::Geode& geode)
242        {
243            for(unsigned int i=0; i<geode.getNumDrawables(); ++i)
244            {
245                osg::Geometry* geom = geode.getDrawable(i)->asGeometry();
246                if (geom)
247                {
248                    geom->setShape(createKDTree(geom));
249                }   
250            }
251        }
252   
253        KDTree* createKDTree(osg::Geometry* geometry);
254       
255        void computeDivisions(KDTree& kdTree);
256       
257        int divide(KDTree& kdTree, osg::BoundingBox& bb, int nodeIndex, unsigned int level);
258
259        unsigned int _maxNumLevels;
260        unsigned int _targetNumVerticesPerLeaf;       
261
262};
263
264
265KDTree* KDTreeBuilder::createKDTree(osg::Geometry* geometry)
266{
267    osg::notify(osg::NOTICE)<<"osg::KDTreeBuilder::createKDTree()"<<std::endl;
268
269    osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
270    if (!vertices) return 0;
271
272    osg::ref_ptr<KDTree> kdTree = new KDTree;
273    kdTree->_geometry = geometry;
274    kdTree->_bb = kdTree->_geometry->getBound();
275   
276   
277    unsigned int estimatedSize = (unsigned int)(float(vertices->size())/float(_targetNumVerticesPerLeaf)*1.5);
278
279    osg::notify(osg::NOTICE)<<"kdTree->_kdNodes.reserve()="<<estimatedSize<<std::endl<<std::endl;
280
281    kdTree->_kdNodes.reserve(estimatedSize);
282    kdTree->_kdLeaves.reserve(estimatedSize);
283   
284    computeDivisions(*kdTree);
285
286    // create initial leaf list   
287    osg::ref_ptr<KDLeaf> leaf = new KDLeaf;
288    leaf->_vertexIndices.reserve(vertices->size());
289    for(unsigned int i=0; i<vertices->size(); ++i)
290    {
291        leaf->_vertexIndices.push_back(i);
292    }
293
294    osg::BoundingBox bb = kdTree->_bb;
295   
296    int leafNum = kdTree->addLeaf(leaf.get());
297    int nodeNum = divide(*kdTree, bb, leafNum, 0);
298   
299    osg::notify(osg::NOTICE)<<"Root nodeNum="<<nodeNum<<std::endl;
300   
301   
302    KDTreeTraverser traverser;
303    traverser.traverse(*kdTree);
304   
305    osg::notify(osg::NOTICE)<<"Final kdTree->_kdNodes.size()="<<kdTree->_kdNodes.size()<<std::endl;
306    osg::notify(osg::NOTICE)<<"Final kdTree->_kdLeaves.size()="<<kdTree->_kdLeaves.size()<<std::endl;
307
308    osg::notify(osg::NOTICE)<<"osg::KDTreeBuilder::createKDTree() completed"<<std::endl<<std::endl;
309
310    return kdTree.release();
311}   
312
313void KDTreeBuilder::computeDivisions(KDTree& kdTree)
314{
315
316
317    osg::Vec3 dimensions(kdTree._bb.xMax()-kdTree._bb.xMin(),
318                         kdTree._bb.yMax()-kdTree._bb.yMin(),
319                         kdTree._bb.zMax()-kdTree._bb.zMin());
320
321    osg::notify(osg::NOTICE)<<"computeDivisions("<<_maxNumLevels<<") "<<dimensions<< " { "<<std::endl;
322
323    kdTree._axisStack.reserve(_maxNumLevels);
324 
325    int level = 0;
326    for(unsigned int level=0; level<_maxNumLevels; ++level)
327    {
328        int axis = 0;
329        if (dimensions[0]>=dimensions[1])
330        {
331            if (dimensions[0]>=dimensions[2]) axis = 0;
332            else axis = 2;
333        }
334        else if (dimensions[1]>=dimensions[2]) axis = 1;
335        else axis = 2;
336
337        kdTree._axisStack.push_back(axis);
338        dimensions[axis] /= 2.0f;
339
340        osg::notify(osg::NOTICE)<<"  "<<level<<", "<<dimensions<<", "<<axis<<std::endl;
341    }
342
343    osg::notify(osg::NOTICE)<<"}"<<std::endl;
344}
345
346int KDTreeBuilder::divide(KDTree& kdTree, osg::BoundingBox& bb, int nodeIndex, unsigned int level)
347{
348    if (kdTree._axisStack.size()<=level) return nodeIndex;
349
350
351    int axis = kdTree._axisStack[level];
352
353    osg::notify(osg::NOTICE)<<"divide("<<nodeIndex<<", "<<level<< "), axis="<<axis<<std::endl;
354
355    if (nodeIndex>=0)
356    {
357        osg::notify(osg::NOTICE)<<"  divide node"<<std::endl;
358        KDNode& node = kdTree.getNode(nodeIndex);
359        return nodeIndex;
360    }
361    else
362    {   
363        if (kdTree.getLeaf(nodeIndex)->_vertexIndices.size()<=_targetNumVerticesPerLeaf) return nodeIndex;
364   
365        osg::notify(osg::NOTICE)<<"  divide leaf"<<std::endl;
366       
367        int nodeNum = kdTree.addNode(KDNode());
368
369        float original_min = bb._min[axis];
370        float original_max = bb._max[axis];
371
372        float mid = (original_min+original_max)*0.5f;
373
374        {
375            osg::ref_ptr<KDLeaf> leaf = kdTree.getLeaf(nodeIndex);
376
377            // create new node, and add two leaves to it.
378            osg::ref_ptr<KDLeaf> leftLeaf = new KDLeaf;
379            osg::ref_ptr<KDLeaf> rightLeaf = new KDLeaf;
380
381
382            osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(kdTree._geometry->getVertexArray());
383
384            osg::notify(osg::NOTICE)<<"  divide leaf->_vertexIndices.size()="<<leaf->_vertexIndices.size()<<std::endl;
385
386            unsigned int estimatedSize = leaf->_vertexIndices.size();
387            leftLeaf->_vertexIndices.reserve(estimatedSize);
388            rightLeaf->_vertexIndices.reserve(estimatedSize);
389
390            for(unsigned int i=0; i<leaf->_vertexIndices.size(); ++i)
391            {
392                unsigned int vi = leaf->_vertexIndices[i];
393                osg::Vec3& v = (*vertices)[vi];
394                if (v[axis] <= mid) leftLeaf->_vertexIndices.push_back(vi);
395                else rightLeaf->_vertexIndices.push_back(vi);
396            }
397
398            if (leftLeaf->_vertexIndices.empty())
399            {
400                osg::notify(osg::NOTICE)<<"LeftLeaf empty"<<std::endl;
401                kdTree.getNode(nodeNum)._leftChild = 0;
402                kdTree.getNode(nodeNum)._rightChild = kdTree.replaceLeaf(nodeIndex, rightLeaf.get());
403            }
404            else if (rightLeaf->_vertexIndices.empty())
405            {
406                osg::notify(osg::NOTICE)<<"RightLeaf empty"<<std::endl;
407                kdTree.getNode(nodeNum)._leftChild = kdTree.replaceLeaf(nodeIndex, leftLeaf.get());
408                kdTree.getNode(nodeNum)._rightChild = 0;
409            }
410            else
411            {
412                kdTree.getNode(nodeNum)._leftChild = kdTree.replaceLeaf(nodeIndex, leftLeaf.get());
413                kdTree.getNode(nodeNum)._rightChild = kdTree.addLeaf(rightLeaf.get());
414            }
415
416
417        }
418       
419        int originalLeftChildIndex = kdTree.getNode(nodeNum)._leftChild;
420        int originalRightChildIndex = kdTree.getNode(nodeNum)._rightChild;
421
422
423        float restore = bb._max[axis];
424        bb._max[axis] = mid;
425
426        osg::notify(osg::NOTICE)<<"  divide leftLeaf "<<kdTree.getNode(nodeNum)._leftChild<<std::endl;
427        int leftChildIndex = divide(kdTree, bb, originalLeftChildIndex, level+1);
428
429        bb._max[axis] = restore;
430       
431        restore = bb._min[axis];
432        bb._min[axis] = mid;
433
434        osg::notify(osg::NOTICE)<<"  divide rightLeaf "<<kdTree.getNode(nodeNum)._rightChild<<std::endl;
435        int rightChildIndex = divide(kdTree, bb, originalRightChildIndex, level+1);
436       
437        bb._min[axis] = restore;
438       
439        kdTree.getNode(nodeNum)._leftChild = leftChildIndex;
440        kdTree.getNode(nodeNum)._rightChild = rightChildIndex;
441       
442        return nodeNum;       
443    }
444
445
446}
447
448}
449
450int main(int argc, char **argv)
451{
452    // use an ArgumentParser object to manage the program arguments.
453    osg::ArgumentParser arguments(&argc,argv);
454   
455    osg::ref_ptr<osg::Node> scene = osgDB::readNodeFiles(arguments);
456   
457    if (!scene)
458    {
459        std::cout<<"No model loaded, please specify a valid model on the command line."<<std::endl;
460        return 0;
461    }
462   
463    osg::KDTreeBuilder builder;
464    scene->accept(builder);
465   
466   
467   
468    return 0;
469}
Note: See TracBrowser for help on using the browser.