1 /* -*-c++-*- */
2 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
3 * Copyright 2008-2013 Pelican Mapping
4 * http://osgearth.org
5 *
6 * osgEarth is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
18 */
19 #include "ParallelKeyNodeFactory"
20 #include <osgEarth/Registry>
21 #include <osg/PagedLOD>
22
23 using namespace osgEarth_engine_osgterrain;
24 using namespace osgEarth;
25 using namespace OpenThreads;
26
27 #define LC "[ParallelKeyNodeFactory] "
28
29 //--------------------------------------------------------------------------
30
ParallelKeyNodeFactory(TileBuilder * builder,const OSGTerrainOptions & options,const MapInfo & mapInfo,TerrainNode * terrain,UID engineUID)31 ParallelKeyNodeFactory::ParallelKeyNodeFactory(TileBuilder* builder,
32 const OSGTerrainOptions& options,
33 const MapInfo& mapInfo,
34 TerrainNode* terrain,
35 UID engineUID ) :
36
37 SerialKeyNodeFactory( builder, options, mapInfo, terrain, engineUID )
38 {
39 //NOP
40 }
41
42 osg::Node*
createRootNode(const TileKey & key)43 ParallelKeyNodeFactory::createRootNode( const TileKey& key )
44 {
45 // NYI
46 return 0L;
47 }
48
49 osg::Node*
createNode(const TileKey & key)50 ParallelKeyNodeFactory::createNode( const TileKey& key )
51 {
52 // An event for synchronizing the completion of all requests:
53 Threading::MultiEvent semaphore;
54
55 // Collect all the jobs that can run in parallel (from all 4 subtiles)
56 osg::ref_ptr<TileBuilder::Job> jobs[4];
57 unsigned numTasks = 0;
58 for( unsigned i=0; i<4; ++i )
59 {
60 jobs[i] = _builder->createJob( key.createChildKey(i), semaphore );
61 if ( jobs[i].valid() )
62 numTasks += jobs[i]->_tasks.size();
63 }
64
65 // Set up the sempahore to block for the correct number of tasks:
66 semaphore.reset( numTasks );
67
68 // Run all the tasks in parallel:
69 for( unsigned i=0; i<4; ++i )
70 if ( jobs[i].valid() )
71 _builder->runJob( jobs[i].get() );
72
73 // Wait for them to complete:
74 semaphore.wait();
75
76 // Now postprocess them and assemble into a tile group.
77 osg::Group* root = new osg::Group();
78
79 for( unsigned i=0; i<4; ++i )
80 {
81 if ( jobs[i].valid() )
82 {
83 osg::ref_ptr<Tile> tile;
84 bool hasRealData;
85 bool hasLodBlending;
86 _builder->finalizeJob( jobs[i].get(), tile, hasRealData, hasLodBlending );
87 if ( tile.valid() )
88 addTile( tile.get(), hasRealData, hasLodBlending, root );
89 }
90 }
91
92 //TODO: need to check to see if the group is empty, and do something different.
93 return root;
94 }
95