2007-06-12 22:20:16 +08:00
|
|
|
/* 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.
|
2003-02-21 22:05:39 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <osgUtil/Optimizer>
|
2003-03-05 17:08:11 +08:00
|
|
|
|
2003-02-21 22:05:39 +08:00
|
|
|
#include <osgDB/ReadFile>
|
2003-03-05 17:08:11 +08:00
|
|
|
#include <osgDB/WriteFile>
|
2003-03-07 01:11:24 +08:00
|
|
|
#include <osgDB/Registry>
|
2003-03-05 17:08:11 +08:00
|
|
|
|
2007-01-11 23:19:59 +08:00
|
|
|
#include <osgViewer/Viewer>
|
2007-08-28 22:02:16 +08:00
|
|
|
#include <osgViewer/ViewerEventHandlers>
|
2003-02-21 22:05:39 +08:00
|
|
|
|
|
|
|
#include <osg/Geode>
|
2006-11-27 22:52:07 +08:00
|
|
|
#include <osg/Camera>
|
2003-03-05 17:08:11 +08:00
|
|
|
#include <osg/ShapeDrawable>
|
|
|
|
#include <osg/Sequence>
|
2007-08-28 22:02:16 +08:00
|
|
|
#include <osg/PolygonMode>
|
|
|
|
#include <osg/io_utils>
|
2003-02-21 22:05:39 +08:00
|
|
|
|
2003-03-05 01:14:42 +08:00
|
|
|
#include <osgText/Font>
|
2003-03-03 05:05:05 +08:00
|
|
|
#include <osgText/Text>
|
2003-02-21 22:05:39 +08:00
|
|
|
|
|
|
|
|
2003-03-05 01:14:42 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
2003-03-05 20:28:42 +08:00
|
|
|
|
2003-02-21 22:05:39 +08:00
|
|
|
|
2007-08-28 22:02:16 +08:00
|
|
|
class UpdateTextOperation : public osg::Operation
|
2003-02-21 22:05:39 +08:00
|
|
|
{
|
2007-08-28 22:02:16 +08:00
|
|
|
public:
|
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
UpdateTextOperation(osg::Group* group):
|
|
|
|
Operation("UpdateTextOperation", true),
|
|
|
|
_group(group),
|
2007-08-28 23:31:43 +08:00
|
|
|
_maxNumChildren(200),
|
2008-02-25 20:54:54 +08:00
|
|
|
_maxNumTextPerGeode(10)
|
|
|
|
{
|
|
|
|
}
|
2007-08-28 22:02:16 +08:00
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
virtual void operator () (osg::Object* callingObject)
|
|
|
|
{
|
2007-08-28 22:02:16 +08:00
|
|
|
// decided which method to call according to whole has called me.
|
|
|
|
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(callingObject);
|
|
|
|
|
|
|
|
if (viewer) update();
|
|
|
|
else load();
|
2008-02-25 20:54:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void update()
|
|
|
|
{
|
2007-08-28 22:02:16 +08:00
|
|
|
// osg::notify(osg::NOTICE)<<"*** Doing update"<<std::endl;
|
2008-02-25 20:54:54 +08:00
|
|
|
|
2007-08-28 22:02:16 +08:00
|
|
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
2008-02-25 20:54:54 +08:00
|
|
|
|
2007-08-28 22:02:16 +08:00
|
|
|
if (_mergeSubgraph.valid())
|
|
|
|
{
|
2008-02-25 20:54:54 +08:00
|
|
|
_group->addChild(_mergeSubgraph.get());
|
2007-08-28 22:02:16 +08:00
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
_mergeSubgraph = 0;
|
2007-08-28 22:02:16 +08:00
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
if (_group->getNumChildren()>_maxNumChildren)
|
|
|
|
{
|
|
|
|
osg::Geode* geode = dynamic_cast<osg::Geode*>(_group->getChild(0));
|
|
|
|
if (geode)
|
2007-08-28 22:02:16 +08:00
|
|
|
{
|
2008-02-25 20:54:54 +08:00
|
|
|
_availableSubgraph.push_back(geode);
|
|
|
|
geode->removeDrawables(0,geode->getNumDrawables());
|
2007-08-28 22:02:16 +08:00
|
|
|
}
|
2008-02-25 20:54:54 +08:00
|
|
|
_group->removeChild(0,1);
|
|
|
|
}
|
|
|
|
|
|
|
|
_waitOnMergeBlock.release();
|
2007-08-28 22:02:16 +08:00
|
|
|
}
|
2008-02-25 20:54:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void load()
|
|
|
|
{
|
|
|
|
|
2007-08-28 22:02:16 +08:00
|
|
|
// osg::notify(osg::NOTICE)<<"Doing load"<<std::endl;
|
|
|
|
|
|
|
|
osg::ref_ptr<osg::Geode> geode;
|
|
|
|
{
|
2008-02-25 20:54:54 +08:00
|
|
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
|
|
|
if (!_availableSubgraph.empty())
|
|
|
|
{
|
|
|
|
geode = _availableSubgraph.front();
|
|
|
|
_availableSubgraph.pop_front();
|
|
|
|
}
|
2007-08-28 22:02:16 +08:00
|
|
|
}
|
2008-02-25 20:54:54 +08:00
|
|
|
|
2007-08-28 22:02:16 +08:00
|
|
|
if (!geode) geode = new osg::Geode;
|
|
|
|
|
|
|
|
for(unsigned int i=0; i<_maxNumTextPerGeode; ++i)
|
|
|
|
{
|
2008-02-25 20:54:54 +08:00
|
|
|
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);
|
2007-08-28 22:02:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{
|
2008-02-25 20:54:54 +08:00
|
|
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
|
|
|
_mergeSubgraph = geode;
|
2007-08-28 22:02:16 +08:00
|
|
|
}
|
2008-02-25 20:54:54 +08:00
|
|
|
|
2007-08-28 22:02:16 +08:00
|
|
|
// osg::notify(osg::NOTICE)<<"Waiting on merge"<<std::endl;
|
|
|
|
|
|
|
|
_waitOnMergeBlock.block();
|
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void release()
|
|
|
|
{
|
2007-08-28 22:02:16 +08:00
|
|
|
_waitOnMergeBlock.release();
|
2008-02-25 20:54:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
typedef std::list< osg::ref_ptr<osg::Geode> > AvailableList;
|
2007-08-28 22:02:16 +08:00
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
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;
|
2007-08-28 22:02:16 +08:00
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char** argv)
|
|
|
|
{
|
2008-02-25 20:54:54 +08:00
|
|
|
osg::ArgumentParser arguments(&argc, argv);
|
2007-08-28 22:02:16 +08:00
|
|
|
|
2003-02-21 22:05:39 +08:00
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
osg::Referenced::setThreadSafeReferenceCounting(true);
|
2007-08-28 22:02:16 +08:00
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
// construct the viewer.
|
|
|
|
osgViewer::Viewer viewer(arguments);
|
2007-08-28 22:02:16 +08:00
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
typedef std::list< osg::ref_ptr<osg::OperationThread> > Threads;
|
2007-08-28 22:02:16 +08:00
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
Threads operationThreads;
|
|
|
|
osg::ref_ptr<UpdateTextOperation> updateOperation;
|
2007-08-28 22:02:16 +08:00
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
unsigned int numThreads = 0;
|
|
|
|
if (arguments.read("--mt", numThreads) || arguments.read("--mt"))
|
|
|
|
{
|
|
|
|
// construct a multi-threaded text updating test.
|
|
|
|
if (numThreads==0) numThreads = 1;
|
2007-08-28 22:02:16 +08:00
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
// create a group to add everything into.
|
|
|
|
osg::Group* mainGroup = new osg::Group;
|
2007-09-01 00:59:32 +08:00
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
|
|
|
|
mainGroup->addChild(loadedModel.get());
|
2007-09-01 00:59:32 +08:00
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
for(unsigned int i=0; i<numThreads; ++i)
|
2007-08-28 22:02:16 +08:00
|
|
|
{
|
2008-02-25 20:54:54 +08:00
|
|
|
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());
|
|
|
|
|
2003-02-21 22:05:39 +08:00
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
// 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)));
|
2003-02-21 22:05:39 +08:00
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
mainGroup->addChild(geode);
|
2003-02-21 22:05:39 +08:00
|
|
|
}
|
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
viewer.setSceneData(mainGroup);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-08-28 22:02:16 +08:00
|
|
|
#if 0
|
2008-02-25 20:54:54 +08:00
|
|
|
osgDB::writeNodeFile(*viewer.getSceneData(),"text.osg");
|
2007-08-28 22:02:16 +08:00
|
|
|
#endif
|
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
viewer.addEventHandler(new osgViewer::StatsHandler());
|
|
|
|
viewer.addEventHandler( new osgViewer::ThreadingHandler );
|
|
|
|
viewer.addEventHandler( new osgViewer::WindowSizeHandler );
|
|
|
|
|
|
|
|
|
|
|
|
viewer.run();
|
2007-02-03 00:51:59 +08:00
|
|
|
|
2008-02-25 20:54:54 +08:00
|
|
|
if (!operationThreads.empty())
|
|
|
|
{
|
|
|
|
for(Threads::iterator itr = operationThreads.begin();
|
|
|
|
itr != operationThreads.begin();
|
|
|
|
++itr)
|
2007-08-28 22:02:16 +08:00
|
|
|
{
|
2008-02-25 20:54:54 +08:00
|
|
|
(*itr)->cancel();
|
2007-08-28 22:02:16 +08:00
|
|
|
}
|
2008-02-25 20:54:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2003-02-21 22:05:39 +08:00
|
|
|
}
|
2005-07-16 00:22:53 +08:00
|
|
|
|