OK, grabbed the latest copy of OSG out of SVN (latest as of about 2PM
today) and ran my test app again. With the latest OSG the app doesn't
crash, but there are still major issues. So, the multi-threading issue
is still there. The database pager simply stops working, I get all
manner of errors in the console window, etc.

I've attached the test app. Should compile in linux, windows, etc.

If you run this app, you will need a paged database to really stress
things. I have one (about 148MB compressed) that I can provide if
anyone is interested. Just email me and I'll provide a link to
download. Oh, and be sure to pass the app an argument of --mt 5, where
5 is the number of test threads to launch, can be any reasonable
number.


On Dec 12, 2007 10:21 PM, sherman wilcox <[EMAIL PROTECTED]> wrote:
> I spent a bit of time this evening digging up the the code that
> reproduces the crash. I'll update to the SVN snapshot of OSG and give
> it a try. I was able to reproduce the crash on 2.2.0.
>
>
> On Dec 12, 2007 4:22 AM, Robert Osfield <[EMAIL PROTECTED]> wrote:
> > Hi Sherman,
> >
> > On Dec 11, 2007 11:31 PM, sherman wilcox <[EMAIL PROTECTED]> wrote:
> > > I can still reliably reproduce the multithreaded osgText /
> > > databasepager crash issue   :)
> >
> > Could you explain how your recreate the crash, and the circumstances
> > of the crash.  It may be exactly the same problem as Serge has, but
> > also just as easily could be another weakness that needs solving.
> >
> > Aaa you gotta love debugging multi-threaded apps remotely :-)
> >
> > Robert.
> >
> > _______________________________________________
> > osg-users mailing list
> > osg-users@lists.openscenegraph.org
> > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
> >
>
/* OpenSceneGraph example, osgtext.
*
*  Permission is hereby granted, free of charge, to any person obtaining a copy
*  of this software and associated documentation files (the "Software"), to deal
*  in the Software without restriction, including without limitation the rights
*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*  copies of the Software, and to permit persons to whom the Software is
*  furnished to do so, subject to the following conditions:
*
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
*  THE SOFTWARE.
*/

#include <osgUtil/Optimizer>

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgDB/Registry>

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>

#include <osg/Geode>
#include <osg/Camera>
#include <osg/ShapeDrawable>
#include <osg/Sequence>
#include <osg/PolygonMode>
#include <osg/io_utils>

#include <osgText/Font>
#include <osgText/Text>


osg::Group* createHUDText()
{

  osg::Group* rootNode = new osg::Group;

  osgText::Font* font = osgText::readFontFile("fonts/arial.ttf");

  osg::Geode* geode  = new osg::Geode;
  rootNode->addChild(geode);

  float windowHeight = 1024.0f;
  float windowWidth = 1280.0f;
  float margin = 50.0f;


  
////////////////////////////////////////////////////////////////////////////////////////////////////////
  //    
  // Examples of how to set up different text layout
  //

  osg::Vec4 layoutColor(1.0f,1.0f,0.0f,1.0f);
  float layoutCharacterSize = 20.0f;    

  {
    osgText::Text* text = new osgText::Text;
    text->setFont(font);
    text->setColor(layoutColor);
    text->setCharacterSize(layoutCharacterSize);
    text->setPosition(osg::Vec3(margin,windowHeight-margin,0.0f));

    // the default layout is left to right, typically used in languages
    // originating from europe such as English, French, German, Spanish etc..
    text->setLayout(osgText::Text::LEFT_TO_RIGHT);

    text->setText("text->setLayout(osgText::Text::LEFT_TO_RIGHT);");
    geode->addDrawable(text);
  }

  {
    osgText::Text* text = new osgText::Text;
    text->setFont(font);
    text->setColor(layoutColor);
    text->setCharacterSize(layoutCharacterSize);
    text->setPosition(osg::Vec3(windowWidth-margin,windowHeight-margin,0.0f));

    // right to left layouts would be used for hebrew or arabic fonts.
    text->setLayout(osgText::Text::RIGHT_TO_LEFT);
    text->setAlignment(osgText::Text::RIGHT_BASE_LINE);

    text->setText("text->setLayout(osgText::Text::RIGHT_TO_LEFT);");
    geode->addDrawable(text);
  }

  {
    osgText::Text* text = new osgText::Text;
    text->setFont(font);
    text->setColor(layoutColor);
    text->setPosition(osg::Vec3(margin,windowHeight-margin,0.0f));
    text->setCharacterSize(layoutCharacterSize);

    // vertical font layout would be used for asian fonts.
    text->setLayout(osgText::Text::VERTICAL);

    text->setText("text->setLayout(osgText::Text::VERTICAL);");
    geode->addDrawable(text);
  }


  
////////////////////////////////////////////////////////////////////////////////////////////////////////
  //    
  // Examples of how to set up different font resolution
  //

  osg::Vec4 fontSizeColor(0.0f,1.0f,1.0f,1.0f);
  float fontSizeCharacterSize = 30;

  osg::Vec3 cursor = osg::Vec3(margin*2,windowHeight-margin*2,0.0f);

  {
    osgText::Text* text = new osgText::Text;
    text->setFont(font);
    text->setColor(fontSizeColor);
    text->setCharacterSize(fontSizeCharacterSize);
    text->setPosition(cursor);

    // use text that uses 10 by 10 texels as a target resolution for fonts.
    text->setFontResolution(10,10); // blocky but small texture memory usage

    text->setText("text->setFontResolution(10,10); // blocky but small texture 
memory usage");
    geode->addDrawable(text);
  }

  cursor.y() -= fontSizeCharacterSize;
  {
    osgText::Text* text = new osgText::Text;
    text->setFont(font);
    text->setColor(fontSizeColor);
    text->setCharacterSize(fontSizeCharacterSize);
    text->setPosition(cursor);

    // use text that uses 20 by 20 texels as a target resolution for fonts.
    text->setFontResolution(20,20); // smoother but higher texture memory usage 
(but still quite low).

    text->setText("text->setFontResolution(20,20); // smoother but higher 
texture memory usage (but still quite low).");
    geode->addDrawable(text);
  }

  cursor.y() -= fontSizeCharacterSize;
  {
    osgText::Text* text = new osgText::Text;
    text->setFont(font);
    text->setColor(fontSizeColor);
    text->setCharacterSize(fontSizeCharacterSize);
    text->setPosition(cursor);

    // use text that uses 40 by 40 texels as a target resolution for fonts.
    text->setFontResolution(40,40); // even smoother but again higher texture 
memory usage.

    text->setText("text->setFontResolution(40,40); // even smoother but again 
higher texture memory usage.");
    geode->addDrawable(text);
  }


  
////////////////////////////////////////////////////////////////////////////////////////////////////////
  //    
  // Examples of how to set up different sized text
  //

  osg::Vec4 characterSizeColor(1.0f,0.0f,1.0f,1.0f);

  cursor.y() -= fontSizeCharacterSize*2.0f;

  {
    osgText::Text* text = new osgText::Text;
    text->setFont(font);
    text->setColor(characterSizeColor);
    text->setFontResolution(20,20);
    text->setPosition(cursor);

    // use text that is 20 units high.
    text->setCharacterSize(20); // small

    text->setText("text->setCharacterSize(20.0f); // small");
    geode->addDrawable(text);
  }

  cursor.y() -= 30.0f;
  {
    osgText::Text* text = new osgText::Text;
    text->setFont(font);
    text->setColor(characterSizeColor);
    text->setFontResolution(30,30);
    text->setPosition(cursor);

    // use text that is 30 units high.
    text->setCharacterSize(30.0f); // medium

    text->setText("text->setCharacterSize(30.0f); // medium");
    geode->addDrawable(text);
  }

  cursor.y() -= 50.0f;
  {
    osgText::Text* text = new osgText::Text;
    text->setFont(font);
    text->setColor(characterSizeColor);
    text->setFontResolution(40,40);
    text->setPosition(cursor);

    // use text that is 60 units high.
    text->setCharacterSize(60.0f); // large

    text->setText("text->setCharacterSize(60.0f); // large");
    geode->addDrawable(text);
  }


  
////////////////////////////////////////////////////////////////////////////////////////////////////////
  //    
  // Examples of how to set up different alignments
  //

  osg::Vec4 alignmentSizeColor(0.0f,1.0f,0.0f,1.0f);
  float alignmentCharacterSize = 25.0f;
  cursor.x() = 640;
  cursor.y() = margin*4.0f;

  typedef std::pair<osgText::Text::AlignmentType,std::string> AlignmentPair;
  typedef std::vector<AlignmentPair> AlignmentList;
  AlignmentList alignmentList;
  
alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_TOP,"text->setAlignment(\nosgText::Text::LEFT_TOP);"));
  
alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_CENTER,"text->setAlignment(\nosgText::Text::LEFT_CENTER);"));
  
alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_BOTTOM,"text->setAlignment(\nosgText::Text::LEFT_BOTTOM);"));
  
alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_TOP,"text->setAlignment(\nosgText::Text::CENTER_TOP);"));
  
alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_CENTER,"text->setAlignment(\nosgText::Text::CENTER_CENTER);"));
  
alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_BOTTOM,"text->setAlignment(\nosgText::Text::CENTER_BOTTOM);"));
  
alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_TOP,"text->setAlignment(\nosgText::Text::RIGHT_TOP);"));
  
alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_CENTER,"text->setAlignment(\nosgText::Text::RIGHT_CENTER);"));
  
alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_BOTTOM,"text->setAlignment(\nosgText::Text::RIGHT_BOTTOM);"));
  
alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_BASE_LINE,"text->setAlignment(\nosgText::Text::LEFT_BASE_LINE);"));
  
alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_BASE_LINE,"text->setAlignment(\nosgText::Text::CENTER_BASE_LINE);"));
  
alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_BASE_LINE,"text->setAlignment(\nosgText::Text::RIGHT_BASE_LINE);"));
  
alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_BOTTOM_BASE_LINE,"text->setAlignment(\nosgText::Text::LEFT_BOTTOM_BASE_LINE);"));
  
alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_BOTTOM_BASE_LINE,"text->setAlignment(\nosgText::Text::CENTER_BOTTOM_BASE_LINE);"));
  
alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_BOTTOM_BASE_LINE,"text->setAlignment(\nosgText::Text::RIGHT_BOTTOM_BASE_LINE);"));


  osg::Sequence* sequence = new osg::Sequence;
  {
    for(AlignmentList::iterator itr=alignmentList.begin();
      itr!=alignmentList.end();
      ++itr)
    {
      osg::Geode* alignmentGeode = new osg::Geode;
      sequence->addChild(alignmentGeode);
      sequence->setTime(sequence->getNumChildren(), 1.0f);

      osgText::Text* text = new osgText::Text;
      text->setFont(font);
      text->setColor(alignmentSizeColor);
      text->setCharacterSize(alignmentCharacterSize);
      text->setPosition(cursor);
      
text->setDrawMode(osgText::Text::TEXT|osgText::Text::ALIGNMENT|osgText::Text::BOUNDINGBOX);

      text->setAlignment(itr->first);
      text->setText(itr->second);

      alignmentGeode->addDrawable(text);


    }

  }

  sequence->setMode(osg::Sequence::START);
  sequence->setInterval(osg::Sequence::LOOP, 0, -1);
  sequence->setDuration(1.0f, -1);

  rootNode->addChild(sequence);


  
////////////////////////////////////////////////////////////////////////////////////////////////////////
  //    
  // Examples of how to set up different fonts...
  //

  cursor.x() = margin*2.0f;
  cursor.y() = margin*2.0f;

  osg::Vec4 fontColor(1.0f,0.5f,0.0f,1.0f);
  float fontCharacterSize = 20.0f;
  float spacing = 40.0f;

  {
    osgText::Text* text = new osgText::Text;
    text->setColor(fontColor);
    text->setPosition(cursor);
    text->setCharacterSize(fontCharacterSize);

    text->setFont(0);
    text->setText("text->setFont(0); // inbuilt font.");
    geode->addDrawable(text);

    cursor.x() = text->getBound().xMax() + spacing ;
  }

  {
    osgText::Font* arial = osgText::readFontFile("fonts/arial.ttf");

    osgText::Text* text = new osgText::Text;
    text->setColor(fontColor);
    text->setPosition(cursor);
    text->setCharacterSize(fontCharacterSize);

    text->setFont(arial);
    text->setText(arial!=0?
      "text->setFont(\"fonts/arial.ttf\");":
    "unable to load \"fonts/arial.ttf\"");
    geode->addDrawable(text);

    cursor.x() = text->getBound().xMax() + spacing ;
  }

  {
    osgText::Font* times = osgText::readFontFile("fonts/times.ttf");

    osgText::Text* text = new osgText::Text;
    text->setColor(fontColor);
    text->setPosition(cursor);
    text->setCharacterSize(fontCharacterSize);

    geode->addDrawable(text);
    text->setFont(times);
    text->setText(times!=0?
      "text->setFont(\"fonts/times.ttf\");":
    "unable to load \"fonts/times.ttf\"");

    cursor.x() = text->getBound().xMax() + spacing ;
  }

  cursor.x() = margin*2.0f;
  cursor.y() = margin;

  {
    osgText::Font* dirtydoz = osgText::readFontFile("fonts/dirtydoz.ttf");

    osgText::Text* text = new osgText::Text;
    text->setColor(fontColor);
    text->setPosition(cursor);
    text->setCharacterSize(fontCharacterSize);

    text->setFont(dirtydoz);
    text->setText(dirtydoz!=0?
      "text->setFont(\"fonts/dirtydoz.ttf\");":
    "unable to load \"fonts/dirtydoz.ttf\"");
    geode->addDrawable(text);

    cursor.x() = text->getBound().xMax() + spacing ;
  }

  {
    osgText::Font* fudd = osgText::readFontFile("fonts/fudd.ttf");

    osgText::Text* text = new osgText::Text;
    text->setColor(fontColor);
    text->setPosition(cursor);
    text->setCharacterSize(fontCharacterSize);

    text->setFont(fudd);
    text->setText(fudd!=0?
      "text->setFont(\"fonts/fudd.ttf\");":
    "unable to load \"fonts/fudd.ttf\"");
    geode->addDrawable(text);

    cursor.x() = text->getBound().xMax() + spacing ;
  }

  return rootNode;    
}




// create text which sits in 3D space such as would be inserted into a normal 
model
osg::Group* create3DText(const osg::Vec3& center,float radius)
{

  osg::Geode* geode  = new osg::Geode;

  
////////////////////////////////////////////////////////////////////////////////////////////////////////
  //    
  // Examples of how to set up axis/orientation alignments
  //

  float characterSize=radius*0.2f;

  osg::Vec3 
pos(center.x()-radius*.5f,center.y()-radius*.5f,center.z()-radius*.5f);

  osgText::Text* text1 = new osgText::Text;
  text1->setFont("fonts/times.ttf");
  text1->setCharacterSize(characterSize);
  text1->setPosition(pos);
  text1->setAxisAlignment(osgText::Text::XY_PLANE);
  text1->setText("XY_PLANE");
  geode->addDrawable(text1);

  osgText::Text* text2 = new osgText::Text;
  text2->setFont("fonts/times.ttf");
  text2->setCharacterSize(characterSize);
  text2->setPosition(pos);
  text2->setAxisAlignment(osgText::Text::YZ_PLANE);
  text2->setText("YZ_PLANE");
  geode->addDrawable(text2);

  osgText::Text* text3 = new osgText::Text;
  text3->setFont("fonts/times.ttf");
  text3->setCharacterSize(characterSize);
  text3->setPosition(pos);
  text3->setAxisAlignment(osgText::Text::XZ_PLANE);
  text3->setText("XZ_PLANE");
  geode->addDrawable(text3);


  osgText::Text* text4 = new osgText::Text;
  text4->setFont("fonts/times.ttf");
  text4->setCharacterSize(characterSize);
  text4->setPosition(center);
  text4->setAxisAlignment(osgText::Text::SCREEN);

  osg::Vec4 characterSizeModeColor(1.0f,0.0f,0.5f,1.0f);

  osgText::Text* text5 = new osgText::Text;
  text5->setColor(characterSizeModeColor);
  text5->setFont("fonts/times.ttf");
  //text5->setCharacterSize(characterSize);
  text5->setCharacterSize(32.0f); // medium
  text5->setPosition(center - osg::Vec3(0.0, 0.0, 0.2));
  text5->setAxisAlignment(osgText::Text::SCREEN);
  text5->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
  text5->setText("CharacterSizeMode SCREEN_COORDS(size 32.0)");
  geode->addDrawable(text5);

  osgText::Text* text6 = new osgText::Text;
  text6->setColor(characterSizeModeColor);
  text6->setFont("fonts/times.ttf");
  text6->setCharacterSize(characterSize);
  text6->setPosition(center - osg::Vec3(0.0, 0.0, 0.4));
  text6->setAxisAlignment(osgText::Text::SCREEN);
  
text6->setCharacterSizeMode(osgText::Text::OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT);
  text6->setText("CharacterSizeMode 
OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT");
  geode->addDrawable(text6);

  osgText::Text* text7 = new osgText::Text;
  text7->setColor(characterSizeModeColor);
  text7->setFont("fonts/times.ttf");
  text7->setCharacterSize(characterSize);
  text7->setPosition(center - osg::Vec3(0.0, 0.0, 0.6));
  text7->setAxisAlignment(osgText::Text::SCREEN);
  text7->setCharacterSizeMode(osgText::Text::OBJECT_COORDS);
  text7->setText("CharacterSizeMode OBJECT_COORDS (default)");
  geode->addDrawable(text7);

#if 1
  // reproduce outline bounding box compute problem with backdrop on.
  text4->setBackdropType(osgText::Text::OUTLINE);
  text4->setDrawMode(osgText::Text::TEXT | osgText::Text::BOUNDINGBOX);
#endif

  text4->setText("SCREEN");
  geode->addDrawable(text4);

  osg::ShapeDrawable* shape = new osg::ShapeDrawable(new 
osg::Sphere(center,characterSize*0.2f));
  shape->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::ON);
  geode->addDrawable(shape);

  osg::Group* rootNode = new osg::Group;
  rootNode->addChild(geode);

  return rootNode;    
}

class UpdateTextOperation : public osg::Operation
{
public:

  UpdateTextOperation(osg::Group* group):        
      Operation("UpdateTextOperation", true),
        _group(group),
        _maxNumChildren(200),
        _maxNumTextPerGeode(10)
      {
      }

      virtual void operator () (osg::Object* callingObject)
      {
        // decided which method to call according to whole has called me.
        osgViewer::Viewer* viewer = 
dynamic_cast<osgViewer::Viewer*>(callingObject);

        if (viewer) update();
        else load();
      }

      void update()
      {
        // osg::notify(osg::NOTICE)<<"*** Doing update"<<std::endl;

        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);

        if (_mergeSubgraph.valid())
        {
          _group->addChild(_mergeSubgraph.get());

          _mergeSubgraph = 0;

          if (_group->getNumChildren()>_maxNumChildren)
          {
            osg::Geode* geode = dynamic_cast<osg::Geode*>(_group->getChild(0));
            if (geode)
            {
              _availableSubgraph.push_back(geode);
              geode->removeDrawables(0,geode->getNumDrawables());
            }
            _group->removeChild(0,1);
          }

          _waitOnMergeBlock.release();
        }        
      }

      void load()
      {

        // osg::notify(osg::NOTICE)<<"Doing load"<<std::endl;

        osg::ref_ptr<osg::Geode> geode;
        {
          OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
          if (!_availableSubgraph.empty())
          {
            geode = _availableSubgraph.front();
            _availableSubgraph.pop_front();
          }
        }

        if (!geode) geode = new osg::Geode;

        for(unsigned int i=0; i<_maxNumTextPerGeode; ++i)
        {
          osg::Vec3 position(float(rand()) / float(RAND_MAX), float(rand()) / 
float(RAND_MAX), float(i)/float(_maxNumTextPerGeode));

          std::string str;
          unsigned int _numCharacters = 5;
          for(unsigned int ni=0; ni<_numCharacters;++ni)
          {
            str.push_back(char(32.0 + (float(rand())/float(RAND_MAX))*128.0f));
          }

          osgText::Text* text = new osgText::Text;
          text->setDataVariance(osg::Object::DYNAMIC);
          text->setPosition(position);
          text->setFont("times.ttf");
          text->setText(str);
          text->setCharacterSize(0.025f);
          text->setAxisAlignment(osgText::Text::SCREEN);

          geode->addDrawable(text);
        }


        {        
          OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
          _mergeSubgraph = geode;
        }

        // osg::notify(osg::NOTICE)<<"Waiting on merge"<<std::endl;

        _waitOnMergeBlock.block();

      }

      virtual void release()
      {
        _waitOnMergeBlock.release();
      }

      typedef std::list< osg::ref_ptr<osg::Geode> > AvailableList;

      unsigned int                _maxNumChildren;
      unsigned int                _maxNumTextPerGeode;

      OpenThreads::Mutex          _mutex;
      osg::ref_ptr<osg::Group>    _group;
      osg::ref_ptr<osg::Geode>    _mergeSubgraph;
      AvailableList               _availableSubgraph;
      OpenThreads::Block          _waitOnMergeBlock;

      unsigned int                _counter;

};


int main(int argc, char** argv)
{
  osg::ArgumentParser arguments(&argc, argv);


  osg::Referenced::setThreadSafeReferenceCounting(true);

  // construct the viewer.
  osgViewer::Viewer viewer(arguments);

  typedef std::list< osg::ref_ptr<osg::OperationThread> > Threads;

  Threads operationThreads;
  osg::ref_ptr<UpdateTextOperation> updateOperation;

  unsigned int numThreads = 0;
  if (arguments.read("--mt", numThreads) || arguments.read("--mt"))
  {
    // construct a multi-threaded text updating test.
    if (numThreads==0) numThreads = 1;

    // create a group to add everything into.
    osg::Group* mainGroup = new osg::Group;

    osg::ref_ptr<osg::Node> loadedModel = 
osgDB::readNodeFile("earth.ive");//osgDB::readNodeFiles(arguments);
    mainGroup->addChild(loadedModel.get());

    for(unsigned int i=0; i<numThreads; ++i)
    {
      osg::Group* textGroup = new osg::Group;
      mainGroup->addChild(textGroup);

      // create the background thread
      osg::OperationThread* operationThread = new osg::OperationThread;

      operationThreads.push_back(operationThread);

      // create the operation that will run in the background and
      // sync once per frame with the main viewer loop.
      updateOperation = new UpdateTextOperation(textGroup);

      // add the operation to the operation thread and start it.
      operationThread->add(updateOperation.get());
      operationThread->startThread();

      // add the operation to the viewer to sync once per frame.
      viewer.addUpdateOperation(updateOperation.get());


      // add a unit cube for the text to appear within.
      osg::Geode* geode = new osg::Geode;
      geode->getOrCreateStateSet()->setAttribute(new 
osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE));
      geode->addDrawable(new osg::ShapeDrawable(new 
osg::Box(osg::Vec3(0.5f,0.5f,0.5f),1.0)));

      mainGroup->addChild(geode);
    }

    viewer.setSceneData(mainGroup);        
  }
  else
  {
    // prepare scene.
    osg::Vec3 center(0.0f,0.0f,0.0f);
    float radius = 1.0f;

    // make sure the root node is group so we can add extra nodes to it.
    osg::Group* group = new osg::Group;

    {
      // create the hud.
      osg::Camera* camera = new osg::Camera;
      camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
      camera->setProjectionMatrixAsOrtho2D(0,1280,0,1024);
      camera->setViewMatrix(osg::Matrix::identity());
      camera->setClearMask(GL_DEPTH_BUFFER_BIT);
      camera->addChild(createHUDText());
      
camera->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);

      group->addChild(camera);
    }

    group->addChild(create3DText(center,radius));

    // set the scene to render
    viewer.setSceneData(group);
  }

#if 0
  osgDB::writeNodeFile(*viewer.getSceneData(),"text.osg");
#endif

  viewer.addEventHandler(new osgViewer::StatsHandler());
  viewer.addEventHandler( new osgViewer::ThreadingHandler );
  viewer.addEventHandler( new osgViewer::WindowSizeHandler );


  viewer.run();

  if (!operationThreads.empty())
  {
    for(Threads::iterator itr = operationThreads.begin();
      itr != operationThreads.begin();
      ++itr)
    {
      (*itr)->cancel();
    }
  }
}

_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to