root/OpenSceneGraph/trunk/examples/osgtext/osgtext.cpp @ 7329

Revision 7329, 23.5 kB (checked in by robert, 7 years ago)

Added support for running multiple text generation threads

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* OpenSceneGraph example, osgtext.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18
19#include <osgUtil/Optimizer>
20
21#include <osgDB/ReadFile>
22#include <osgDB/WriteFile>
23#include <osgDB/Registry>
24
25#include <osgViewer/Viewer>
26#include <osgViewer/ViewerEventHandlers>
27
28#include <osg/Geode>
29#include <osg/Camera>
30#include <osg/ShapeDrawable>
31#include <osg/Sequence>
32#include <osg/PolygonMode>
33#include <osg/io_utils>
34
35#include <osgText/Font>
36#include <osgText/Text>
37
38
39osg::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
383osg::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}
479
480class UpdateTextOperation : public osg::Operation
481{
482public:
483
484    UpdateTextOperation(osg::Group* group):       
485        Operation("UpdateTextOperation", true),
486        _group(group),
487        _maxNumChildren(200),
488        _maxNumTextPerGeode(10)
489    {
490    }
491
492    virtual void operator () (osg::Object* callingObject)
493    {
494        // decided which method to call according to whole has called me.
495        osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(callingObject);
496
497        if (viewer) update();
498        else load();
499    }
500   
501    void update()
502    {
503        // osg::notify(osg::NOTICE)<<"*** Doing update"<<std::endl;
504       
505        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
506       
507        if (_mergeSubgraph.valid())
508        {
509            _group->addChild(_mergeSubgraph.get());
510
511            _mergeSubgraph = 0;
512
513            if (_group->getNumChildren()>_maxNumChildren)
514            {
515                osg::Geode* geode = dynamic_cast<osg::Geode*>(_group->getChild(0));
516                if (geode)
517                {
518                    _availableSubgraph.push_back(geode);
519                    geode->removeDrawables(0,geode->getNumDrawables());
520                }
521                _group->removeChild(0,1);
522            }
523           
524            _waitOnMergeBlock.release();
525        }       
526    }
527   
528    void load()
529    {
530   
531        // osg::notify(osg::NOTICE)<<"Doing load"<<std::endl;
532
533        osg::ref_ptr<osg::Geode> geode;
534        {
535            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
536            if (!_availableSubgraph.empty())
537            {
538                geode = _availableSubgraph.front();
539                _availableSubgraph.pop_front();
540            }
541        }
542       
543        if (!geode) geode = new osg::Geode;
544
545        for(unsigned int i=0; i<_maxNumTextPerGeode; ++i)
546        {
547            osg::Vec3 position(float(rand()) / float(RAND_MAX), float(rand()) / float(RAND_MAX), float(i)/float(_maxNumTextPerGeode));
548
549            std::string str;
550            unsigned int _numCharacters = 5;
551            for(unsigned int ni=0; ni<_numCharacters;++ni)
552            {
553                str.push_back(char(32.0 + (float(rand())/float(RAND_MAX))*128.0f));
554            }
555                       
556            osgText::Text* text = new osgText::Text;
557            text->setDataVariance(osg::Object::DYNAMIC);
558            text->setPosition(position);
559            text->setFont("times.ttf");
560            text->setText(str);
561            text->setCharacterSize(0.025f);
562            text->setAxisAlignment(osgText::Text::SCREEN);
563           
564            geode->addDrawable(text);
565        }
566
567
568        {       
569            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
570            _mergeSubgraph = geode;
571        }
572       
573        // osg::notify(osg::NOTICE)<<"Waiting on merge"<<std::endl;
574
575        _waitOnMergeBlock.block();
576
577    }
578   
579    virtual void release()
580    {
581        _waitOnMergeBlock.release();
582    }
583
584    typedef std::list< osg::ref_ptr<osg::Geode> > AvailableList;
585
586    unsigned int                _maxNumChildren;
587    unsigned int                _maxNumTextPerGeode;
588   
589    OpenThreads::Mutex          _mutex;
590    osg::ref_ptr<osg::Group>    _group;
591    osg::ref_ptr<osg::Geode>    _mergeSubgraph;
592    AvailableList               _availableSubgraph;
593    OpenThreads::Block          _waitOnMergeBlock;
594   
595    unsigned int                _counter;
596
597};
598
599
600int main(int argc, char** argv)
601{
602    osg::ArgumentParser arguments(&argc, argv);
603
604    // construct the viewer.
605    osgViewer::Viewer viewer(arguments);
606   
607    typedef std::list< osg::ref_ptr<osg::OperationThread> > Threads;
608
609    Threads operationThreads;
610    osg::ref_ptr<UpdateTextOperation> updateOperation;
611
612    unsigned int numThreads = 0;
613    if (arguments.read("--mt", numThreads) || arguments.read("--mt"))
614    {
615        // construct a multi-threaded text updating test.
616        if (numThreads==0) numThreads = 1;
617       
618        // create a group to add everything into.
619        osg::Group* mainGroup = new osg::Group;
620       
621        for(unsigned int i=0; i<numThreads; ++i)
622        {
623            osg::Group* textGroup = new osg::Group;
624            mainGroup->addChild(textGroup);
625
626            // create the background thread
627            osg::OperationThread* operationThread = new osg::OperationThread;
628           
629            operationThreads.push_back(operationThread);
630
631            // create the operation that will run in the background and
632            // sync once per frame with the main viewer loop.
633            updateOperation = new UpdateTextOperation(textGroup);
634
635            // add the operation to the operation thread and start it.
636            operationThread->add(updateOperation.get());
637            operationThread->startThread();
638
639            // add the operation to the viewer to sync once per frame.
640            viewer.addUpdateOperation(updateOperation.get());
641
642
643            // add a unit cube for the text to appear within.
644            osg::Geode* geode = new osg::Geode;
645            geode->getOrCreateStateSet()->setAttribute(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE));
646            geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.5f,0.5f,0.5f),1.0)));
647
648            mainGroup->addChild(geode);
649        }
650               
651        viewer.setSceneData(mainGroup);       
652    }
653    else
654    {
655        // prepare scene.
656        osg::Vec3 center(0.0f,0.0f,0.0f);
657        float radius = 1.0f;
658       
659        // make sure the root node is group so we can add extra nodes to it.
660        osg::Group* group = new osg::Group;
661       
662        {
663            // create the hud.
664            osg::Camera* camera = new osg::Camera;
665            camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
666            camera->setProjectionMatrixAsOrtho2D(0,1280,0,1024);
667            camera->setViewMatrix(osg::Matrix::identity());
668            camera->setClearMask(GL_DEPTH_BUFFER_BIT);
669            camera->addChild(createHUDText());
670            camera->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
671
672            group->addChild(camera);
673        }
674
675        group->addChild(create3DText(center,radius));
676
677        // set the scene to render
678        viewer.setSceneData(group);
679    }
680
681#if 0
682    osgDB::writeNodeFile(*viewer.getSceneData(),"text.osg");
683#endif
684
685    viewer.addEventHandler(new osgViewer::StatsHandler());
686
687    viewer.run();
688   
689    if (!operationThreads.empty())
690    {
691        for(Threads::iterator itr = operationThreads.begin();
692            itr != operationThreads.begin();
693            ++itr)
694        {
695            (*itr)->cancel();
696        }
697    }
698}
Note: See TracBrowser for help on using the browser.