Refactored the mutex usage in osgText and freetype plugin to prevent multi-thread crash
This commit is contained in:
@@ -36,683 +36,213 @@
|
||||
#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(const osg::Vec3& center, float diameter, osg::Group* group):
|
||||
Operation("UpdateTextOperation", true),
|
||||
_center(center),
|
||||
_diameter(diameter),
|
||||
UpdateTextOperation(osg::Group* group):
|
||||
Operation("UpdateTextOperation", true),
|
||||
_group(group),
|
||||
_maxNumChildren(200),
|
||||
_maxNumTextPerGeode(10),
|
||||
_group(group)
|
||||
{
|
||||
}
|
||||
_maxNumTextPerGeode(10)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator () (osg::Object* callingObject)
|
||||
{
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
// osg::notify(osg::NOTICE)<<"*** Doing update"<<std::endl;
|
||||
|
||||
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
|
||||
|
||||
if (_mergeSubgraph.valid())
|
||||
{
|
||||
_group->addChild(_mergeSubgraph.get());
|
||||
_group->addChild(_mergeSubgraph.get());
|
||||
|
||||
_mergeSubgraph = 0;
|
||||
_mergeSubgraph = 0;
|
||||
|
||||
if (_group->getNumChildren()>_maxNumChildren)
|
||||
if (_group->getNumChildren()>_maxNumChildren)
|
||||
{
|
||||
osg::Geode* geode = dynamic_cast<osg::Geode*>(_group->getChild(0));
|
||||
if (geode)
|
||||
{
|
||||
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);
|
||||
_availableSubgraph.push_back(geode);
|
||||
geode->removeDrawables(0,geode->getNumDrawables());
|
||||
}
|
||||
|
||||
_waitOnMergeBlock.release();
|
||||
_group->removeChild(0,1);
|
||||
}
|
||||
|
||||
_waitOnMergeBlock.release();
|
||||
}
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
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)
|
||||
{
|
||||
float x = float(rand()) / float(RAND_MAX) - 0.5f;
|
||||
float y = float(rand()) / float(RAND_MAX) - 0.5f;
|
||||
float z = float(i) / float(_maxNumTextPerGeode) - 0.5f;
|
||||
osg::Vec3 position(x, y, z);
|
||||
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(_center + position * _diameter);
|
||||
text->setFont("times.ttf");
|
||||
text->setText(str);
|
||||
text->setCharacterSize(0.025f * _diameter);
|
||||
text->setAxisAlignment(osgText::Text::SCREEN);
|
||||
|
||||
geode->addDrawable(text);
|
||||
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;
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
_mergeSubgraph = geode;
|
||||
}
|
||||
|
||||
|
||||
// osg::notify(osg::NOTICE)<<"Waiting on merge"<<std::endl;
|
||||
|
||||
_waitOnMergeBlock.block();
|
||||
|
||||
}
|
||||
|
||||
virtual void release()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void release()
|
||||
{
|
||||
_waitOnMergeBlock.release();
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::list< osg::ref_ptr<osg::Geode> > AvailableList;
|
||||
typedef std::list< osg::ref_ptr<osg::Geode> > AvailableList;
|
||||
|
||||
osg::Vec3 _center;
|
||||
float _diameter;
|
||||
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;
|
||||
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::ArgumentParser arguments(&argc, argv);
|
||||
|
||||
// construct the viewer.
|
||||
osgViewer::Viewer viewer(arguments);
|
||||
|
||||
typedef std::list< osg::ref_ptr<osg::OperationThread> > Threads;
|
||||
|
||||
Threads operationThreads;
|
||||
osg::ref_ptr<UpdateTextOperation> updateOperation;
|
||||
osg::Referenced::setThreadSafeReferenceCounting(true);
|
||||
|
||||
unsigned int numThreads = 0;
|
||||
if (arguments.read("--mt", numThreads) || arguments.read("--mt"))
|
||||
// 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::readNodeFiles(arguments);
|
||||
mainGroup->addChild(loadedModel.get());
|
||||
|
||||
for(unsigned int i=0; i<numThreads; ++i)
|
||||
{
|
||||
// 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::Vec3 center(0.5f,0.5f,0.5f);
|
||||
float diameter = 1.0f;
|
||||
|
||||
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
|
||||
if (loadedModel.valid())
|
||||
{
|
||||
mainGroup->addChild(loadedModel.get());
|
||||
|
||||
center = loadedModel->getBound().center();
|
||||
diameter = loadedModel->getBound().radius() * 2.0f;
|
||||
}
|
||||
|
||||
for(unsigned int i=0; i<numThreads; ++i)
|
||||
{
|
||||
osg::Group* textGroup = new osg::Group;
|
||||
mainGroup->addChild(textGroup);
|
||||
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 background thread
|
||||
osg::OperationThread* operationThread = new osg::OperationThread;
|
||||
|
||||
// create the operation that will run in the background and
|
||||
// sync once per frame with the main viewer loop.
|
||||
updateOperation = new UpdateTextOperation(center, diameter, textGroup);
|
||||
operationThreads.push_back(operationThread);
|
||||
|
||||
// add the operation to the operation thread and start it.
|
||||
operationThread->add(updateOperation.get());
|
||||
operationThread->startThread();
|
||||
// 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 viewer to sync once per frame.
|
||||
viewer.addUpdateOperation(updateOperation.get());
|
||||
// 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(center,diameter)));
|
||||
// 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);
|
||||
mainGroup->addChild(geode);
|
||||
}
|
||||
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);
|
||||
}
|
||||
viewer.setSceneData(mainGroup);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
osgDB::writeNodeFile(*viewer.getSceneData(),"text.osg");
|
||||
osgDB::writeNodeFile(*viewer.getSceneData(),"text.osg");
|
||||
#endif
|
||||
|
||||
viewer.addEventHandler(new osgViewer::StatsHandler());
|
||||
viewer.addEventHandler(new osgViewer::StatsHandler());
|
||||
viewer.addEventHandler( new osgViewer::ThreadingHandler );
|
||||
viewer.addEventHandler( new osgViewer::WindowSizeHandler );
|
||||
|
||||
viewer.run();
|
||||
|
||||
if (!operationThreads.empty())
|
||||
|
||||
viewer.run();
|
||||
|
||||
if (!operationThreads.empty())
|
||||
{
|
||||
for(Threads::iterator itr = operationThreads.begin();
|
||||
itr != operationThreads.begin();
|
||||
++itr)
|
||||
{
|
||||
for(Threads::iterator itr = operationThreads.begin();
|
||||
itr != operationThreads.end();
|
||||
++itr)
|
||||
{
|
||||
(*itr)->cancel();
|
||||
}
|
||||
(*itr)->cancel();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -158,9 +158,6 @@ public:
|
||||
|
||||
typedef OpenThreads::Mutex FontMutex;
|
||||
|
||||
/** Get the mutex that enables the serialization of calls to this font.*/
|
||||
static FontMutex* getSerializeFontCallsMutex();
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~Font();
|
||||
@@ -173,13 +170,15 @@ protected:
|
||||
|
||||
typedef std::map< FontResolution, GlyphMap > FontSizeGlyphMap;
|
||||
|
||||
mutable OpenThreads::Mutex _glyphMapMutex;
|
||||
|
||||
osg::ref_ptr<osg::TexEnv> _texenv;
|
||||
osg::ref_ptr<osg::StateSet> _stateset;
|
||||
FontSizeGlyphMap _sizeGlyphMap;
|
||||
GlyphTextureList _glyphTextureList;
|
||||
|
||||
// current active size of font
|
||||
FontResolution _fontSize;
|
||||
FontResolution _fontSize;
|
||||
unsigned int _margin;
|
||||
float _marginRatio;
|
||||
|
||||
|
||||
@@ -111,9 +111,6 @@ public:
|
||||
virtual void setThreadSafeRefUnref(bool threadSafe);
|
||||
|
||||
typedef OpenThreads::Mutex Font3DMutex;
|
||||
|
||||
/** Get the mutex that enables the serialization of calls to this font.*/
|
||||
static Font3DMutex* getSerializeFontCallsMutex();
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ void FreeTypeFont::setFontResolution(const osgText::FontResolution& fontSize)
|
||||
|
||||
osgText::Font::Glyph* FreeTypeFont::getGlyph(const osgText::FontResolution& fontRes, unsigned int charcode)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(FreeTypeLibrary::instance()->getMutex());
|
||||
|
||||
setFontResolution(fontRes);
|
||||
|
||||
@@ -201,7 +201,7 @@ osgText::Font::Glyph* FreeTypeFont::getGlyph(const osgText::FontResolution& font
|
||||
|
||||
osg::Vec2 FreeTypeFont::getKerning(const osgText::FontResolution& fontRes, unsigned int leftcharcode,unsigned int rightcharcode, osgText::KerningType kerningType)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(FreeTypeLibrary::instance()->getMutex());
|
||||
|
||||
if (!FT_HAS_KERNING(_face) || (kerningType == osgText::KERNING_NONE)) return osg::Vec2(0.0f,0.0f);
|
||||
|
||||
@@ -233,5 +233,6 @@ osg::Vec2 FreeTypeFont::getKerning(const osgText::FontResolution& fontRes, unsig
|
||||
|
||||
bool FreeTypeFont::hasVertical() const
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(FreeTypeLibrary::instance()->getMutex());
|
||||
return FT_HAS_VERTICAL(_face)!=0;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ protected:
|
||||
|
||||
void setFontResolution(const osgText::FontResolution& fontSize);
|
||||
|
||||
OpenThreads::Mutex _mutex;
|
||||
osgText::FontResolution _currentRes;
|
||||
|
||||
std::string _filename;
|
||||
|
||||
@@ -69,6 +69,8 @@ FreeTypeLibrary* FreeTypeLibrary::instance()
|
||||
|
||||
bool FreeTypeLibrary::getFace(const std::string& fontfile,unsigned int index, FT_Face & face)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(getMutex());
|
||||
|
||||
FT_Error error = FT_New_Face( _ftlibrary, fontfile.c_str(), index, &face );
|
||||
if (error == FT_Err_Unknown_File_Format)
|
||||
{
|
||||
@@ -110,6 +112,8 @@ bool FreeTypeLibrary::getFace(const std::string& fontfile,unsigned int index, FT
|
||||
|
||||
FT_Byte* FreeTypeLibrary::getFace(std::istream& fontstream, unsigned int index, FT_Face & face)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(getMutex());
|
||||
|
||||
FT_Open_Args args;
|
||||
|
||||
std::streampos start = fontstream.tellg();
|
||||
@@ -159,6 +163,7 @@ osgText::Font* FreeTypeLibrary::getFont(const std::string& fontfile, unsigned in
|
||||
FT_Face face;
|
||||
if (getFace(fontfile, index, face) == false) return (0);
|
||||
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(getMutex());
|
||||
|
||||
FreeTypeFont* fontImp = new FreeTypeFont(fontfile,face,flags);
|
||||
osgText::Font* font = new osgText::Font(fontImp);
|
||||
@@ -174,6 +179,8 @@ osgText::Font* FreeTypeLibrary::getFont(std::istream& fontstream, unsigned int i
|
||||
if (face == 0) return (0);
|
||||
|
||||
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(getMutex());
|
||||
|
||||
FreeTypeFont* fontImp = new FreeTypeFont(buffer,face,flags);
|
||||
osgText::Font* font = new osgText::Font(fontImp);
|
||||
|
||||
@@ -187,6 +194,7 @@ osgText::Font3D* FreeTypeLibrary::getFont3D(const std::string& fontfile, unsigne
|
||||
FT_Face face;
|
||||
if (getFace(fontfile, index, face) == false) return (0);
|
||||
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(getMutex());
|
||||
|
||||
FreeTypeFont3D* font3DImp = new FreeTypeFont3D(fontfile,face,flags);
|
||||
osgText::Font3D* font3D = new osgText::Font3D(font3DImp);
|
||||
@@ -197,11 +205,13 @@ osgText::Font3D* FreeTypeLibrary::getFont3D(const std::string& fontfile, unsigne
|
||||
}
|
||||
osgText::Font3D* FreeTypeLibrary::getFont3D(std::istream& fontstream, unsigned int index, unsigned int flags)
|
||||
{
|
||||
|
||||
FT_Face face = 0;
|
||||
FT_Byte * buffer = getFace(fontstream, index, face);
|
||||
if (face == 0) return (0);
|
||||
|
||||
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(getMutex());
|
||||
|
||||
FreeTypeFont3D* font3DImp = new FreeTypeFont3D(buffer,face,flags);
|
||||
osgText::Font3D* font3D = new osgText::Font3D(font3DImp);
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ public:
|
||||
/** get the singleton instance.*/
|
||||
static FreeTypeLibrary* instance();
|
||||
|
||||
OpenThreads::Mutex& getMutex() { return _mutex; }
|
||||
|
||||
osgText::Font* getFont(const std::string& fontfile,unsigned int index=0, unsigned int flags=0);
|
||||
osgText::Font* getFont(std::istream& fontstream, unsigned int index=0, unsigned int flags=0);
|
||||
|
||||
@@ -61,9 +63,10 @@ protected:
|
||||
typedef std::set< FreeTypeFont* > FontImplementationSet;
|
||||
typedef std::set< FreeTypeFont3D* > Font3DImplementationSet;
|
||||
|
||||
FT_Library _ftlibrary;
|
||||
FontImplementationSet _fontImplementationSet;
|
||||
Font3DImplementationSet _font3DImplementationSet;
|
||||
mutable OpenThreads::Mutex _mutex;
|
||||
FT_Library _ftlibrary;
|
||||
FontImplementationSet _fontImplementationSet;
|
||||
Font3DImplementationSet _font3DImplementationSet;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -32,12 +32,6 @@ static osg::ApplicationUsageProxy Font_e0(osg::ApplicationUsage::ENVIRONMENTAL_V
|
||||
|
||||
static OpenThreads::ReentrantMutex s_FontFileMutex;
|
||||
|
||||
Font::FontMutex* osgText::Font::getSerializeFontCallsMutex()
|
||||
{
|
||||
static OpenThreads::Mutex s_serializeFontCallsMutex;
|
||||
return &s_serializeFontCallsMutex;
|
||||
}
|
||||
|
||||
std::string osgText::findFontFile(const std::string& str)
|
||||
{
|
||||
// try looking in OSGFILEPATH etc first for fonts.
|
||||
@@ -330,14 +324,17 @@ osg::Texture::FilterMode Font::getMagFilterHint() const
|
||||
|
||||
Font::Glyph* Font::getGlyph(const FontResolution& fontRes, unsigned int charcode)
|
||||
{
|
||||
FontSizeGlyphMap::iterator itr = _sizeGlyphMap.find(fontRes);
|
||||
if (itr!=_sizeGlyphMap.end())
|
||||
{
|
||||
GlyphMap& glyphmap = itr->second;
|
||||
GlyphMap::iterator gitr = glyphmap.find(charcode);
|
||||
if (gitr!=glyphmap.end()) return gitr->second.get();
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_glyphMapMutex);
|
||||
FontSizeGlyphMap::iterator itr = _sizeGlyphMap.find(fontRes);
|
||||
if (itr!=_sizeGlyphMap.end())
|
||||
{
|
||||
GlyphMap& glyphmap = itr->second;
|
||||
GlyphMap::iterator gitr = glyphmap.find(charcode);
|
||||
if (gitr!=glyphmap.end()) return gitr->second.get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (_implementation.valid()) return _implementation->getGlyph(fontRes, charcode);
|
||||
else return 0;
|
||||
}
|
||||
@@ -400,6 +397,8 @@ bool Font::hasVertical() const
|
||||
|
||||
void Font::addGlyph(const FontResolution& fontRes, unsigned int charcode, Glyph* glyph)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_glyphMapMutex);
|
||||
|
||||
_sizeGlyphMap[fontRes][charcode]=glyph;
|
||||
|
||||
int posX=0,posY=0;
|
||||
|
||||
@@ -37,12 +37,6 @@ static OpenThreads::ReentrantMutex s_Font3DFileMutex;
|
||||
namespace osgText
|
||||
{
|
||||
|
||||
Font::FontMutex* Font3D::getSerializeFontCallsMutex()
|
||||
{
|
||||
static OpenThreads::Mutex s_serializeFontCallsMutex;
|
||||
return &s_serializeFontCallsMutex;
|
||||
}
|
||||
|
||||
std::string findFont3DFile(const std::string& str)
|
||||
{
|
||||
// try looking in OSGFILEPATH etc first for fonts.
|
||||
|
||||
@@ -224,8 +224,6 @@ void Text3D::computeGlyphRepresentation()
|
||||
return;
|
||||
}
|
||||
|
||||
OpenThreads::ScopedLock<Font3D::Font3DMutex> lock(*(_font->getSerializeFontCallsMutex()));
|
||||
|
||||
// initialize bounding box, it will be expanded during glyph position calculation
|
||||
_textBB.init();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user