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