Show
Ignore:
Timestamp:
02/25/08 13:54:54 (6 years ago)
Author:
robert
Message:

Refactored the mutex usage in osgText and freetype plugin to prevent multi-thread crash

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/examples/osgtext/osgtext.cpp

    r7867 r7874  
    3737 
    3838 
    39 osg::Group* createHUDText() 
    40 { 
    41  
    42     osg::Group* rootNode = new osg::Group; 
    43  
    44     osgText::Font* font = osgText::readFontFile("fonts/arial.ttf"); 
    45  
    46     osg::Geode* geode  = new osg::Geode; 
    47     rootNode->addChild(geode); 
    48  
    49     float windowHeight = 1024.0f; 
    50     float windowWidth = 1280.0f; 
    51     float margin = 50.0f; 
    52  
    53  
    54 //////////////////////////////////////////////////////////////////////////////////////////////////////// 
    55 //     
    56 // Examples of how to set up different text layout 
    57 // 
    58  
    59     osg::Vec4 layoutColor(1.0f,1.0f,0.0f,1.0f); 
    60     float layoutCharacterSize = 20.0f;     
    61      
    62     { 
    63         osgText::Text* text = new osgText::Text; 
    64         text->setFont(font); 
    65         text->setColor(layoutColor); 
    66         text->setCharacterSize(layoutCharacterSize); 
    67         text->setPosition(osg::Vec3(margin,windowHeight-margin,0.0f)); 
    68  
    69         // the default layout is left to right, typically used in languages 
    70         // originating from europe such as English, French, German, Spanish etc.. 
    71         text->setLayout(osgText::Text::LEFT_TO_RIGHT); 
    72  
    73         text->setText("text->setLayout(osgText::Text::LEFT_TO_RIGHT);"); 
    74         geode->addDrawable(text); 
    75     } 
    76  
    77     { 
    78         osgText::Text* text = new osgText::Text; 
    79         text->setFont(font); 
    80         text->setColor(layoutColor); 
    81         text->setCharacterSize(layoutCharacterSize); 
    82         text->setPosition(osg::Vec3(windowWidth-margin,windowHeight-margin,0.0f)); 
    83  
    84         // right to left layouts would be used for hebrew or arabic fonts. 
    85         text->setLayout(osgText::Text::RIGHT_TO_LEFT); 
    86         text->setAlignment(osgText::Text::RIGHT_BASE_LINE); 
    87  
    88         text->setText("text->setLayout(osgText::Text::RIGHT_TO_LEFT);"); 
    89         geode->addDrawable(text); 
    90     } 
    91  
    92     { 
    93         osgText::Text* text = new osgText::Text; 
    94         text->setFont(font); 
    95         text->setColor(layoutColor); 
    96         text->setPosition(osg::Vec3(margin,windowHeight-margin,0.0f)); 
    97         text->setCharacterSize(layoutCharacterSize); 
    98  
    99         // vertical font layout would be used for asian fonts. 
    100         text->setLayout(osgText::Text::VERTICAL); 
    101  
    102         text->setText("text->setLayout(osgText::Text::VERTICAL);"); 
    103         geode->addDrawable(text); 
    104     } 
    105      
    106      
    107 //////////////////////////////////////////////////////////////////////////////////////////////////////// 
    108 //     
    109 // Examples of how to set up different font resolution 
    110 // 
    111  
    112     osg::Vec4 fontSizeColor(0.0f,1.0f,1.0f,1.0f); 
    113     float fontSizeCharacterSize = 30; 
    114      
    115     osg::Vec3 cursor = osg::Vec3(margin*2,windowHeight-margin*2,0.0f); 
    116      
    117     { 
    118         osgText::Text* text = new osgText::Text; 
    119         text->setFont(font); 
    120         text->setColor(fontSizeColor); 
    121         text->setCharacterSize(fontSizeCharacterSize); 
    122         text->setPosition(cursor); 
    123          
    124         // use text that uses 10 by 10 texels as a target resolution for fonts. 
    125         text->setFontResolution(10,10); // blocky but small texture memory usage 
    126          
    127         text->setText("text->setFontResolution(10,10); // blocky but small texture memory usage"); 
    128         geode->addDrawable(text); 
    129     } 
    130      
    131     cursor.y() -= fontSizeCharacterSize; 
    132     { 
    133         osgText::Text* text = new osgText::Text; 
    134         text->setFont(font); 
    135         text->setColor(fontSizeColor); 
    136         text->setCharacterSize(fontSizeCharacterSize); 
    137         text->setPosition(cursor); 
    138          
    139         // use text that uses 20 by 20 texels as a target resolution for fonts. 
    140         text->setFontResolution(20,20); // smoother but higher texture memory usage (but still quite low). 
    141          
    142         text->setText("text->setFontResolution(20,20); // smoother but higher texture memory usage (but still quite low)."); 
    143         geode->addDrawable(text); 
    144     } 
    145      
    146     cursor.y() -= fontSizeCharacterSize; 
    147     { 
    148         osgText::Text* text = new osgText::Text; 
    149         text->setFont(font); 
    150         text->setColor(fontSizeColor); 
    151         text->setCharacterSize(fontSizeCharacterSize); 
    152         text->setPosition(cursor); 
    153          
    154         // use text that uses 40 by 40 texels as a target resolution for fonts. 
    155         text->setFontResolution(40,40); // even smoother but again higher texture memory usage. 
    156          
    157         text->setText("text->setFontResolution(40,40); // even smoother but again higher texture memory usage."); 
    158         geode->addDrawable(text); 
    159     } 
    160  
    161  
    162 //////////////////////////////////////////////////////////////////////////////////////////////////////// 
    163 //     
    164 // Examples of how to set up different sized text 
    165 // 
    166  
    167     osg::Vec4 characterSizeColor(1.0f,0.0f,1.0f,1.0f); 
    168      
    169     cursor.y() -= fontSizeCharacterSize*2.0f; 
    170      
    171     { 
    172         osgText::Text* text = new osgText::Text; 
    173         text->setFont(font); 
    174         text->setColor(characterSizeColor); 
    175         text->setFontResolution(20,20); 
    176         text->setPosition(cursor); 
    177          
    178         // use text that is 20 units high. 
    179         text->setCharacterSize(20); // small 
    180          
    181         text->setText("text->setCharacterSize(20.0f); // small"); 
    182         geode->addDrawable(text); 
    183     } 
    184      
    185     cursor.y() -= 30.0f; 
    186     { 
    187         osgText::Text* text = new osgText::Text; 
    188         text->setFont(font); 
    189         text->setColor(characterSizeColor); 
    190         text->setFontResolution(30,30); 
    191         text->setPosition(cursor); 
    192          
    193         // use text that is 30 units high. 
    194         text->setCharacterSize(30.0f); // medium 
    195          
    196         text->setText("text->setCharacterSize(30.0f); // medium"); 
    197         geode->addDrawable(text); 
    198     } 
    199      
    200     cursor.y() -= 50.0f; 
    201     { 
    202         osgText::Text* text = new osgText::Text; 
    203         text->setFont(font); 
    204         text->setColor(characterSizeColor); 
    205         text->setFontResolution(40,40); 
    206         text->setPosition(cursor); 
    207          
    208         // use text that is 60 units high. 
    209         text->setCharacterSize(60.0f); // large 
    210          
    211         text->setText("text->setCharacterSize(60.0f); // large"); 
    212         geode->addDrawable(text); 
    213     } 
    214  
    215  
    216 //////////////////////////////////////////////////////////////////////////////////////////////////////// 
    217 //     
    218 // Examples of how to set up different alignments 
    219 // 
    220  
    221     osg::Vec4 alignmentSizeColor(0.0f,1.0f,0.0f,1.0f); 
    222     float alignmentCharacterSize = 25.0f; 
    223     cursor.x() = 640; 
    224     cursor.y() = margin*4.0f; 
    225      
    226     typedef std::pair<osgText::Text::AlignmentType,std::string> AlignmentPair; 
    227     typedef std::vector<AlignmentPair> AlignmentList; 
    228     AlignmentList alignmentList; 
    229     alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_TOP,"text->setAlignment(\nosgText::Text::LEFT_TOP);")); 
    230     alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_CENTER,"text->setAlignment(\nosgText::Text::LEFT_CENTER);")); 
    231     alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_BOTTOM,"text->setAlignment(\nosgText::Text::LEFT_BOTTOM);")); 
    232     alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_TOP,"text->setAlignment(\nosgText::Text::CENTER_TOP);")); 
    233     alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_CENTER,"text->setAlignment(\nosgText::Text::CENTER_CENTER);")); 
    234     alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_BOTTOM,"text->setAlignment(\nosgText::Text::CENTER_BOTTOM);")); 
    235     alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_TOP,"text->setAlignment(\nosgText::Text::RIGHT_TOP);")); 
    236     alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_CENTER,"text->setAlignment(\nosgText::Text::RIGHT_CENTER);")); 
    237     alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_BOTTOM,"text->setAlignment(\nosgText::Text::RIGHT_BOTTOM);")); 
    238     alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_BASE_LINE,"text->setAlignment(\nosgText::Text::LEFT_BASE_LINE);")); 
    239     alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_BASE_LINE,"text->setAlignment(\nosgText::Text::CENTER_BASE_LINE);")); 
    240     alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_BASE_LINE,"text->setAlignment(\nosgText::Text::RIGHT_BASE_LINE);")); 
    241     alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_BOTTOM_BASE_LINE,"text->setAlignment(\nosgText::Text::LEFT_BOTTOM_BASE_LINE);")); 
    242     alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_BOTTOM_BASE_LINE,"text->setAlignment(\nosgText::Text::CENTER_BOTTOM_BASE_LINE);")); 
    243     alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_BOTTOM_BASE_LINE,"text->setAlignment(\nosgText::Text::RIGHT_BOTTOM_BASE_LINE);")); 
    244  
    245  
    246     osg::Sequence* sequence = new osg::Sequence; 
    247     { 
    248         for(AlignmentList::iterator itr=alignmentList.begin(); 
    249             itr!=alignmentList.end(); 
    250             ++itr) 
    251         { 
    252             osg::Geode* alignmentGeode = new osg::Geode; 
    253             sequence->addChild(alignmentGeode); 
    254             sequence->setTime(sequence->getNumChildren(), 1.0f); 
    255  
    256             osgText::Text* text = new osgText::Text; 
    257             text->setFont(font); 
    258             text->setColor(alignmentSizeColor); 
    259             text->setCharacterSize(alignmentCharacterSize); 
    260             text->setPosition(cursor); 
    261             text->setDrawMode(osgText::Text::TEXT|osgText::Text::ALIGNMENT|osgText::Text::BOUNDINGBOX); 
    262              
    263             text->setAlignment(itr->first); 
    264             text->setText(itr->second); 
    265              
    266             alignmentGeode->addDrawable(text); 
    267  
    268  
    269         } 
    270          
    271     } 
    272  
    273     sequence->setMode(osg::Sequence::START); 
    274     sequence->setInterval(osg::Sequence::LOOP, 0, -1); 
    275     sequence->setDuration(1.0f, -1); 
    276      
    277     rootNode->addChild(sequence); 
    278  
    279  
    280 //////////////////////////////////////////////////////////////////////////////////////////////////////// 
    281 //     
    282 // Examples of how to set up different fonts... 
    283 // 
    284  
    285     cursor.x() = margin*2.0f; 
    286     cursor.y() = margin*2.0f; 
    287      
    288     osg::Vec4 fontColor(1.0f,0.5f,0.0f,1.0f); 
    289     float fontCharacterSize = 20.0f; 
    290     float spacing = 40.0f; 
    291      
    292     { 
    293         osgText::Text* text = new osgText::Text; 
    294         text->setColor(fontColor); 
    295         text->setPosition(cursor); 
    296         text->setCharacterSize(fontCharacterSize); 
    297          
    298         text->setFont(0); 
    299         text->setText("text->setFont(0); // inbuilt font."); 
    300         geode->addDrawable(text); 
    301  
    302         cursor.x() = text->getBound().xMax() + spacing ; 
    303     } 
    304      
    305     { 
    306         osgText::Font* arial = osgText::readFontFile("fonts/arial.ttf"); 
    307  
    308         osgText::Text* text = new osgText::Text; 
    309         text->setColor(fontColor); 
    310         text->setPosition(cursor); 
    311         text->setCharacterSize(fontCharacterSize); 
    312          
    313         text->setFont(arial); 
    314         text->setText(arial!=0? 
    315                       "text->setFont(\"fonts/arial.ttf\");": 
    316                       "unable to load \"fonts/arial.ttf\""); 
    317         geode->addDrawable(text); 
    318  
    319         cursor.x() = text->getBound().xMax() + spacing ; 
    320     } 
    321      
    322     { 
    323         osgText::Font* times = osgText::readFontFile("fonts/times.ttf"); 
    324  
    325         osgText::Text* text = new osgText::Text; 
    326         text->setColor(fontColor); 
    327         text->setPosition(cursor); 
    328         text->setCharacterSize(fontCharacterSize); 
    329          
    330         geode->addDrawable(text); 
    331         text->setFont(times); 
    332         text->setText(times!=0? 
    333                       "text->setFont(\"fonts/times.ttf\");": 
    334                       "unable to load \"fonts/times.ttf\""); 
    335  
    336         cursor.x() = text->getBound().xMax() + spacing ; 
    337     } 
    338      
    339     cursor.x() = margin*2.0f; 
    340     cursor.y() = margin; 
    341  
    342     { 
    343         osgText::Font* dirtydoz = osgText::readFontFile("fonts/dirtydoz.ttf"); 
    344  
    345         osgText::Text* text = new osgText::Text; 
    346         text->setColor(fontColor); 
    347         text->setPosition(cursor); 
    348         text->setCharacterSize(fontCharacterSize); 
    349          
    350         text->setFont(dirtydoz); 
    351         text->setText(dirtydoz!=0? 
    352                       "text->setFont(\"fonts/dirtydoz.ttf\");": 
    353                       "unable to load \"fonts/dirtydoz.ttf\""); 
    354         geode->addDrawable(text); 
    355  
    356         cursor.x() = text->getBound().xMax() + spacing ; 
    357     } 
    358      
    359     { 
    360         osgText::Font* fudd = osgText::readFontFile("fonts/fudd.ttf"); 
    361      
    362         osgText::Text* text = new osgText::Text; 
    363         text->setColor(fontColor); 
    364         text->setPosition(cursor); 
    365         text->setCharacterSize(fontCharacterSize); 
    366          
    367         text->setFont(fudd); 
    368         text->setText(fudd!=0? 
    369                       "text->setFont(\"fonts/fudd.ttf\");": 
    370                       "unable to load \"fonts/fudd.ttf\""); 
    371         geode->addDrawable(text); 
    372  
    373         cursor.x() = text->getBound().xMax() + spacing ; 
    374     } 
    375              
    376     return rootNode;     
    377 } 
    378  
    379  
    380  
    381  
    382 // create text which sits in 3D space such as would be inserted into a normal model 
    383 osg::Group* create3DText(const osg::Vec3& center,float radius) 
    384 { 
    385  
    386     osg::Geode* geode  = new osg::Geode; 
    387  
    388 //////////////////////////////////////////////////////////////////////////////////////////////////////// 
    389 //     
    390 // Examples of how to set up axis/orientation alignments 
    391 // 
    392  
    393     float characterSize=radius*0.2f; 
    394      
    395     osg::Vec3 pos(center.x()-radius*.5f,center.y()-radius*.5f,center.z()-radius*.5f); 
    396  
    397     osgText::Text* text1 = new osgText::Text; 
    398     text1->setFont("fonts/times.ttf"); 
    399     text1->setCharacterSize(characterSize); 
    400     text1->setPosition(pos); 
    401     text1->setAxisAlignment(osgText::Text::XY_PLANE); 
    402     text1->setText("XY_PLANE"); 
    403     geode->addDrawable(text1); 
    404  
    405     osgText::Text* text2 = new osgText::Text; 
    406     text2->setFont("fonts/times.ttf"); 
    407     text2->setCharacterSize(characterSize); 
    408     text2->setPosition(pos); 
    409     text2->setAxisAlignment(osgText::Text::YZ_PLANE); 
    410     text2->setText("YZ_PLANE"); 
    411     geode->addDrawable(text2); 
    412  
    413     osgText::Text* text3 = new osgText::Text; 
    414     text3->setFont("fonts/times.ttf"); 
    415     text3->setCharacterSize(characterSize); 
    416     text3->setPosition(pos); 
    417     text3->setAxisAlignment(osgText::Text::XZ_PLANE); 
    418     text3->setText("XZ_PLANE"); 
    419     geode->addDrawable(text3); 
    420  
    421  
    422     osgText::Text* text4 = new osgText::Text; 
    423     text4->setFont("fonts/times.ttf"); 
    424     text4->setCharacterSize(characterSize); 
    425     text4->setPosition(center); 
    426     text4->setAxisAlignment(osgText::Text::SCREEN); 
    427  
    428     osg::Vec4 characterSizeModeColor(1.0f,0.0f,0.5f,1.0f); 
    429  
    430     osgText::Text* text5 = new osgText::Text; 
    431     text5->setColor(characterSizeModeColor); 
    432     text5->setFont("fonts/times.ttf"); 
    433     //text5->setCharacterSize(characterSize); 
    434     text5->setCharacterSize(32.0f); // medium 
    435     text5->setPosition(center - osg::Vec3(0.0, 0.0, 0.2)); 
    436     text5->setAxisAlignment(osgText::Text::SCREEN); 
    437     text5->setCharacterSizeMode(osgText::Text::SCREEN_COORDS); 
    438     text5->setText("CharacterSizeMode SCREEN_COORDS(size 32.0)"); 
    439     geode->addDrawable(text5); 
    440  
    441     osgText::Text* text6 = new osgText::Text; 
    442     text6->setColor(characterSizeModeColor); 
    443     text6->setFont("fonts/times.ttf"); 
    444     text6->setCharacterSize(characterSize); 
    445     text6->setPosition(center - osg::Vec3(0.0, 0.0, 0.4)); 
    446     text6->setAxisAlignment(osgText::Text::SCREEN); 
    447     text6->setCharacterSizeMode(osgText::Text::OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT); 
    448     text6->setText("CharacterSizeMode OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT"); 
    449     geode->addDrawable(text6); 
    450  
    451     osgText::Text* text7 = new osgText::Text; 
    452     text7->setColor(characterSizeModeColor); 
    453     text7->setFont("fonts/times.ttf"); 
    454     text7->setCharacterSize(characterSize); 
    455     text7->setPosition(center - osg::Vec3(0.0, 0.0, 0.6)); 
    456     text7->setAxisAlignment(osgText::Text::SCREEN); 
    457     text7->setCharacterSizeMode(osgText::Text::OBJECT_COORDS); 
    458     text7->setText("CharacterSizeMode OBJECT_COORDS (default)"); 
    459     geode->addDrawable(text7); 
    460  
    461 #if 1 
    462     // reproduce outline bounding box compute problem with backdrop on. 
    463     text4->setBackdropType(osgText::Text::OUTLINE); 
    464     text4->setDrawMode(osgText::Text::TEXT | osgText::Text::BOUNDINGBOX); 
    465 #endif 
    466  
    467     text4->setText("SCREEN"); 
    468     geode->addDrawable(text4); 
    469  
    470     osg::ShapeDrawable* shape = new osg::ShapeDrawable(new osg::Sphere(center,characterSize*0.2f)); 
    471     shape->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::ON); 
    472     geode->addDrawable(shape); 
    473  
    474     osg::Group* rootNode = new osg::Group; 
    475     rootNode->addChild(geode); 
    476  
    477     return rootNode;     
    478 } 
     39 
     40 
     41 
     42 
    47943 
    48044class UpdateTextOperation : public osg::Operation 
     
    48246public: 
    48347 
    484     UpdateTextOperation(const osg::Vec3& center, float diameter, osg::Group* group):         
    485         Operation("UpdateTextOperation", true), 
    486         _center(center), 
    487         _diameter(diameter), 
     48  UpdateTextOperation(osg::Group* group):         
     49      Operation("UpdateTextOperation", true), 
     50        _group(group), 
    48851        _maxNumChildren(200), 
    489         _maxNumTextPerGeode(10), 
    490         _group(group) 
    491     { 
    492     } 
    493  
    494     virtual void operator () (osg::Object* callingObject) 
    495     { 
     52        _maxNumTextPerGeode(10) 
     53      { 
     54      } 
     55 
     56      virtual void operator () (osg::Object* callingObject) 
     57      { 
    49658        // decided which method to call according to whole has called me. 
    49759        osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(callingObject); 
     
    49961        if (viewer) update(); 
    50062        else load(); 
    501     } 
    502      
    503     void update() 
    504     { 
     63      } 
     64 
     65      void update() 
     66      { 
    50567        // osg::notify(osg::NOTICE)<<"*** Doing update"<<std::endl; 
    506          
     68 
    50769        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); 
    508          
     70 
    50971        if (_mergeSubgraph.valid()) 
    51072        { 
    511             _group->addChild(_mergeSubgraph.get()); 
    512  
    513             _mergeSubgraph = 0; 
    514  
    515             if (_group->getNumChildren()>_maxNumChildren) 
     73          _group->addChild(_mergeSubgraph.get()); 
     74 
     75          _mergeSubgraph = 0; 
     76 
     77          if (_group->getNumChildren()>_maxNumChildren) 
     78          { 
     79            osg::Geode* geode = dynamic_cast<osg::Geode*>(_group->getChild(0)); 
     80            if (geode) 
    51681            { 
    517                 osg::Geode* geode = dynamic_cast<osg::Geode*>(_group->getChild(0)); 
    518                 if (geode) 
    519                 { 
    520                     _availableSubgraph.push_back(geode); 
    521                     geode->removeDrawables(0,geode->getNumDrawables()); 
    522                 } 
    523                 _group->removeChild(0,1); 
     82              _availableSubgraph.push_back(geode); 
     83              geode->removeDrawables(0,geode->getNumDrawables()); 
    52484            } 
    525              
    526             _waitOnMergeBlock.release(); 
     85            _group->removeChild(0,1); 
     86          } 
     87 
     88          _waitOnMergeBlock.release(); 
    52789        }         
    528     } 
    529      
    530     void load() 
    531     { 
    532      
     90      } 
     91 
     92      void load() 
     93      { 
     94 
    53395        // osg::notify(osg::NOTICE)<<"Doing load"<<std::endl; 
    53496 
    53597        osg::ref_ptr<osg::Geode> geode; 
    53698        { 
    537             OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); 
    538             if (!_availableSubgraph.empty()) 
    539             { 
    540                 geode = _availableSubgraph.front(); 
    541                 _availableSubgraph.pop_front(); 
    542             } 
     99          OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); 
     100          if (!_availableSubgraph.empty()) 
     101          { 
     102            geode = _availableSubgraph.front(); 
     103            _availableSubgraph.pop_front(); 
     104          } 
    543105        } 
    544          
     106 
    545107        if (!geode) geode = new osg::Geode; 
    546108 
    547109        for(unsigned int i=0; i<_maxNumTextPerGeode; ++i) 
    548110        { 
    549             float x = float(rand()) / float(RAND_MAX) - 0.5f; 
    550             float y = float(rand()) / float(RAND_MAX) - 0.5f; 
    551             float z = float(i)      / float(_maxNumTextPerGeode) - 0.5f; 
    552             osg::Vec3 position(x, y, z); 
    553  
    554             std::string str; 
    555             unsigned int _numCharacters = 5; 
    556             for(unsigned int ni=0; ni<_numCharacters;++ni) 
    557             { 
    558                 str.push_back(char(32.0 + (float(rand())/float(RAND_MAX))*128.0f)); 
    559             } 
    560                          
    561             osgText::Text* text = new osgText::Text; 
    562             text->setDataVariance(osg::Object::DYNAMIC); 
    563             text->setPosition(_center + position * _diameter); 
    564             text->setFont("times.ttf"); 
    565             text->setText(str); 
    566             text->setCharacterSize(0.025f * _diameter); 
    567             text->setAxisAlignment(osgText::Text::SCREEN); 
    568              
    569             geode->addDrawable(text); 
     111          osg::Vec3 position(float(rand()) / float(RAND_MAX), float(rand()) / float(RAND_MAX), float(i)/float(_maxNumTextPerGeode)); 
     112 
     113          std::string str; 
     114          unsigned int _numCharacters = 5; 
     115          for(unsigned int ni=0; ni<_numCharacters;++ni) 
     116          { 
     117            str.push_back(char(32.0 + (float(rand())/float(RAND_MAX))*128.0f)); 
     118          } 
     119 
     120          osgText::Text* text = new osgText::Text; 
     121          text->setDataVariance(osg::Object::DYNAMIC); 
     122          text->setPosition(position); 
     123          text->setFont("times.ttf"); 
     124          text->setText(str); 
     125          text->setCharacterSize(0.025f); 
     126          text->setAxisAlignment(osgText::Text::SCREEN); 
     127 
     128          geode->addDrawable(text); 
    570129        } 
    571130 
    572131 
    573132        {         
    574             OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); 
    575             _mergeSubgraph = geode; 
     133          OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); 
     134          _mergeSubgraph = geode; 
    576135        } 
    577          
     136 
    578137        // osg::notify(osg::NOTICE)<<"Waiting on merge"<<std::endl; 
    579138 
    580139        _waitOnMergeBlock.block(); 
    581140 
    582     } 
    583      
    584     virtual void release() 
    585     { 
     141      } 
     142 
     143      virtual void release() 
     144      { 
    586145        _waitOnMergeBlock.release(); 
    587     } 
    588  
    589     typedef std::list< osg::ref_ptr<osg::Geode> > AvailableList; 
    590  
    591     osg::Vec3                   _center; 
    592     float                       _diameter; 
    593     unsigned int                _maxNumChildren; 
    594     unsigned int                _maxNumTextPerGeode; 
    595      
    596     OpenThreads::Mutex          _mutex; 
    597     osg::ref_ptr<osg::Group>    _group; 
    598     osg::ref_ptr<osg::Geode>    _mergeSubgraph; 
    599     AvailableList               _availableSubgraph; 
    600     OpenThreads::Block          _waitOnMergeBlock; 
    601      
    602     unsigned int                _counter; 
     146      } 
     147 
     148      typedef std::list< osg::ref_ptr<osg::Geode> > AvailableList; 
     149 
     150      unsigned int                _maxNumChildren; 
     151      unsigned int                _maxNumTextPerGeode; 
     152 
     153      OpenThreads::Mutex          _mutex; 
     154      osg::ref_ptr<osg::Group>    _group; 
     155      osg::ref_ptr<osg::Geode>    _mergeSubgraph; 
     156      AvailableList               _availableSubgraph; 
     157      OpenThreads::Block          _waitOnMergeBlock; 
     158 
     159      unsigned int                _counter; 
    603160 
    604161}; 
     
    607164int main(int argc, char** argv) 
    608165{ 
    609     osg::ArgumentParser arguments(&argc, argv); 
    610  
    611     // construct the viewer. 
    612     osgViewer::Viewer viewer(arguments); 
    613      
    614     typedef std::list< osg::ref_ptr<osg::OperationThread> > Threads; 
    615  
    616     Threads operationThreads; 
    617     osg::ref_ptr<UpdateTextOperation> updateOperation; 
    618  
    619     unsigned int numThreads = 0; 
    620     if (arguments.read("--mt", numThreads) || arguments.read("--mt")) 
     166  osg::ArgumentParser arguments(&argc, argv); 
     167 
     168 
     169  osg::Referenced::setThreadSafeReferenceCounting(true); 
     170 
     171  // construct the viewer. 
     172  osgViewer::Viewer viewer(arguments); 
     173 
     174  typedef std::list< osg::ref_ptr<osg::OperationThread> > Threads; 
     175 
     176  Threads operationThreads; 
     177  osg::ref_ptr<UpdateTextOperation> updateOperation; 
     178 
     179  unsigned int numThreads = 0; 
     180  if (arguments.read("--mt", numThreads) || arguments.read("--mt")) 
     181  { 
     182    // construct a multi-threaded text updating test. 
     183    if (numThreads==0) numThreads = 1; 
     184 
     185    // create a group to add everything into. 
     186    osg::Group* mainGroup = new osg::Group; 
     187 
     188    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments); 
     189    mainGroup->addChild(loadedModel.get()); 
     190 
     191    for(unsigned int i=0; i<numThreads; ++i) 
    621192    { 
    622         // construct a multi-threaded text updating test. 
    623         if (numThreads==0) numThreads = 1; 
    624          
    625         // create a group to add everything into. 
    626         osg::Group* mainGroup = new osg::Group; 
    627          
    628         osg::Vec3 center(0.5f,0.5f,0.5f); 
    629         float diameter = 1.0f; 
    630          
    631         osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments); 
    632         if (loadedModel.valid()) 
    633         { 
    634             mainGroup->addChild(loadedModel.get()); 
    635              
    636             center = loadedModel->getBound().center(); 
    637             diameter = loadedModel->getBound().radius() * 2.0f; 
    638         } 
    639          
    640         for(unsigned int i=0; i<numThreads; ++i) 
    641         { 
    642             osg::Group* textGroup = new osg::Group; 
    643             mainGroup->addChild(textGroup); 
    644  
    645             // create the background thread 
    646             osg::OperationThread* operationThread = new osg::OperationThread; 
    647              
    648             operationThreads.push_back(operationThread); 
    649  
    650             // create the operation that will run in the background and 
    651             // sync once per frame with the main viewer loop. 
    652             updateOperation = new UpdateTextOperation(center, diameter, textGroup); 
    653  
    654             // add the operation to the operation thread and start it. 
    655             operationThread->add(updateOperation.get()); 
    656             operationThread->startThread(); 
    657  
    658             // add the operation to the viewer to sync once per frame. 
    659             viewer.addUpdateOperation(updateOperation.get()); 
    660  
    661  
    662             // add a unit cube for the text to appear within. 
    663             osg::Geode* geode = new osg::Geode; 
    664             geode->getOrCreateStateSet()->setAttribute(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE)); 
    665             geode->addDrawable(new osg::ShapeDrawable(new osg::Box(center,diameter))); 
    666  
    667             mainGroup->addChild(geode); 
    668         } 
    669                  
    670         viewer.setSceneData(mainGroup);         
     193      osg::Group* textGroup = new osg::Group; 
     194      mainGroup->addChild(textGroup); 
     195 
     196      // create the background thread 
     197      osg::OperationThread* operationThread = new osg::OperationThread; 
     198 
     199      operationThreads.push_back(operationThread); 
     200 
     201      // create the operation that will run in the background and 
     202      // sync once per frame with the main viewer loop. 
     203      updateOperation = new UpdateTextOperation(textGroup); 
     204 
     205      // add the operation to the operation thread and start it. 
     206      operationThread->add(updateOperation.get()); 
     207      operationThread->startThread(); 
     208 
     209      // add the operation to the viewer to sync once per frame. 
     210      viewer.addUpdateOperation(updateOperation.get()); 
     211 
     212 
     213      // add a unit cube for the text to appear within. 
     214      osg::Geode* geode = new osg::Geode; 
     215      geode->getOrCreateStateSet()->setAttribute(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE)); 
     216      geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.5f,0.5f,0.5f),1.0))); 
     217 
     218      mainGroup->addChild(geode); 
    671219    } 
    672     else 
     220 
     221    viewer.setSceneData(mainGroup);         
     222  } 
     223   
     224 
     225#if 0 
     226  osgDB::writeNodeFile(*viewer.getSceneData(),"text.osg"); 
     227#endif 
     228 
     229  viewer.addEventHandler(new osgViewer::StatsHandler()); 
     230  viewer.addEventHandler( new osgViewer::ThreadingHandler ); 
     231  viewer.addEventHandler( new osgViewer::WindowSizeHandler ); 
     232 
     233 
     234  viewer.run(); 
     235 
     236  if (!operationThreads.empty()) 
     237  { 
     238    for(Threads::iterator itr = operationThreads.begin(); 
     239      itr != operationThreads.begin(); 
     240      ++itr) 
    673241    { 
    674         // prepare scene. 
    675         osg::Vec3 center(0.0f,0.0f,0.0f); 
    676         float radius = 1.0f; 
    677          
    678         // make sure the root node is group so we can add extra nodes to it. 
    679         osg::Group* group = new osg::Group; 
    680          
    681         { 
    682             // create the hud. 
    683             osg::Camera* camera = new osg::Camera; 
    684             camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); 
    685             camera->setProjectionMatrixAsOrtho2D(0,1280,0,1024); 
    686             camera->setViewMatrix(osg::Matrix::identity()); 
    687             camera->setClearMask(GL_DEPTH_BUFFER_BIT); 
    688             camera->addChild(createHUDText()); 
    689             camera->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); 
    690  
    691             group->addChild(camera); 
    692         } 
    693  
    694         group->addChild(create3DText(center,radius)); 
    695  
    696         // set the scene to render 
    697         viewer.setSceneData(group); 
     242      (*itr)->cancel(); 
    698243    } 
    699  
    700 #if 0 
    701     osgDB::writeNodeFile(*viewer.getSceneData(),"text.osg"); 
    702 #endif 
    703  
    704     viewer.addEventHandler(new osgViewer::StatsHandler()); 
    705  
    706     viewer.run(); 
    707      
    708     if (!operationThreads.empty()) 
    709     { 
    710         for(Threads::iterator itr = operationThreads.begin(); 
    711             itr != operationThreads.end(); 
    712             ++itr) 
    713         { 
    714             (*itr)->cancel(); 
    715         } 
    716     } 
     244  } 
     245 
     246  return 0; 
    717247} 
    718248