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

Revision 5415, 21.1 kB (checked in by robert, 8 years ago)

From Martijn Kragtwijk, added example text for showing osgText::Text::CharacterSizeMode? in action.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <osgUtil/Optimizer>
15
16#include <osgDB/ReadFile>
17#include <osgDB/WriteFile>
18#include <osgDB/Registry>
19
20#include <osgProducer/Viewer>
21
22#include <osg/Geode>
23#include <osg/CameraNode>
24#include <osg/ShapeDrawable>
25#include <osg/Sequence>
26
27#include <osgText/Font>
28#include <osgText/Text>
29
30
31osg::Group* createHUDText()
32{
33
34    osg::Group* rootNode = new osg::Group;
35
36    osgText::Font* font = osgText::readFontFile("fonts/arial.ttf");
37
38    osg::Geode* geode  = new osg::Geode;
39    rootNode->addChild(geode);
40
41    float windowHeight = 1024.0f;
42    float windowWidth = 1280.0f;
43    float margin = 50.0f;
44
45
46////////////////////////////////////////////////////////////////////////////////////////////////////////
47//   
48// Examples of how to set up different text layout
49//
50
51    osg::Vec4 layoutColor(1.0f,1.0f,0.0f,1.0f);
52    float layoutCharacterSize = 20.0f;   
53   
54    {
55        osgText::Text* text = new osgText::Text;
56        text->setFont(font);
57        text->setColor(layoutColor);
58        text->setCharacterSize(layoutCharacterSize);
59        text->setPosition(osg::Vec3(margin,windowHeight-margin,0.0f));
60
61        // the default layout is left to right, typically used in languages
62        // originating from europe such as English, French, German, Spanish etc..
63        text->setLayout(osgText::Text::LEFT_TO_RIGHT);
64
65        text->setText("text->setLayout(osgText::Text::LEFT_TO_RIGHT);");
66        geode->addDrawable(text);
67    }
68
69    {
70        osgText::Text* text = new osgText::Text;
71        text->setFont(font);
72        text->setColor(layoutColor);
73        text->setCharacterSize(layoutCharacterSize);
74        text->setPosition(osg::Vec3(windowWidth-margin,windowHeight-margin,0.0f));
75
76        // right to left layouts would be used for hebrew or arabic fonts.
77        text->setLayout(osgText::Text::RIGHT_TO_LEFT);
78        text->setAlignment(osgText::Text::RIGHT_BASE_LINE);
79
80        text->setText("text->setLayout(osgText::Text::RIGHT_TO_LEFT);");
81        geode->addDrawable(text);
82    }
83
84    {
85        osgText::Text* text = new osgText::Text;
86        text->setFont(font);
87        text->setColor(layoutColor);
88        text->setPosition(osg::Vec3(margin,windowHeight-margin,0.0f));
89        text->setCharacterSize(layoutCharacterSize);
90
91        // vertical font layout would be used for asian fonts.
92        text->setLayout(osgText::Text::VERTICAL);
93
94        text->setText("text->setLayout(osgText::Text::VERTICAL);");
95        geode->addDrawable(text);
96    }
97   
98   
99////////////////////////////////////////////////////////////////////////////////////////////////////////
100//   
101// Examples of how to set up different font resolution
102//
103
104    osg::Vec4 fontSizeColor(0.0f,1.0f,1.0f,1.0f);
105    float fontSizeCharacterSize = 30;
106   
107    osg::Vec3 cursor = osg::Vec3(margin*2,windowHeight-margin*2,0.0f);
108   
109    {
110        osgText::Text* text = new osgText::Text;
111        text->setFont(font);
112        text->setColor(fontSizeColor);
113        text->setCharacterSize(fontSizeCharacterSize);
114        text->setPosition(cursor);
115       
116        // use text that uses 10 by 10 texels as a target resolution for fonts.
117        text->setFontResolution(10,10); // blocky but small texture memory usage
118       
119        text->setText("text->setFontResolution(10,10); // blocky but small texture memory usage");
120        geode->addDrawable(text);
121    }
122   
123    cursor.y() -= fontSizeCharacterSize;
124    {
125        osgText::Text* text = new osgText::Text;
126        text->setFont(font);
127        text->setColor(fontSizeColor);
128        text->setCharacterSize(fontSizeCharacterSize);
129        text->setPosition(cursor);
130       
131        // use text that uses 20 by 20 texels as a target resolution for fonts.
132        text->setFontResolution(20,20); // smoother but higher texture memory usage (but still quite low).
133       
134        text->setText("text->setFontResolution(20,20); // smoother but higher texture memory usage (but still quite low).");
135        geode->addDrawable(text);
136    }
137   
138    cursor.y() -= fontSizeCharacterSize;
139    {
140        osgText::Text* text = new osgText::Text;
141        text->setFont(font);
142        text->setColor(fontSizeColor);
143        text->setCharacterSize(fontSizeCharacterSize);
144        text->setPosition(cursor);
145       
146        // use text that uses 40 by 40 texels as a target resolution for fonts.
147        text->setFontResolution(40,40); // even smoother but again higher texture memory usage.
148       
149        text->setText("text->setFontResolution(40,40); // even smoother but again higher texture memory usage.");
150        geode->addDrawable(text);
151    }
152
153
154////////////////////////////////////////////////////////////////////////////////////////////////////////
155//   
156// Examples of how to set up different sized text
157//
158
159    osg::Vec4 characterSizeColor(1.0f,0.0f,1.0f,1.0f);
160   
161    cursor.y() -= fontSizeCharacterSize*2.0f;
162   
163    {
164        osgText::Text* text = new osgText::Text;
165        text->setFont(font);
166        text->setColor(characterSizeColor);
167        text->setFontResolution(20,20);
168        text->setPosition(cursor);
169       
170        // use text that is 20 units high.
171        text->setCharacterSize(20); // small
172       
173        text->setText("text->setCharacterSize(20.0f); // small");
174        geode->addDrawable(text);
175    }
176   
177    cursor.y() -= 30.0f;
178    {
179        osgText::Text* text = new osgText::Text;
180        text->setFont(font);
181        text->setColor(characterSizeColor);
182        text->setFontResolution(30,30);
183        text->setPosition(cursor);
184       
185        // use text that is 30 units high.
186        text->setCharacterSize(30.0f); // medium
187       
188        text->setText("text->setCharacterSize(30.0f); // medium");
189        geode->addDrawable(text);
190    }
191   
192    cursor.y() -= 50.0f;
193    {
194        osgText::Text* text = new osgText::Text;
195        text->setFont(font);
196        text->setColor(characterSizeColor);
197        text->setFontResolution(40,40);
198        text->setPosition(cursor);
199       
200        // use text that is 60 units high.
201        text->setCharacterSize(60.0f); // large
202       
203        text->setText("text->setCharacterSize(60.0f); // large");
204        geode->addDrawable(text);
205    }
206
207
208////////////////////////////////////////////////////////////////////////////////////////////////////////
209//   
210// Examples of how to set up different alignments
211//
212
213    osg::Vec4 alignmentSizeColor(0.0f,1.0f,0.0f,1.0f);
214    float alignmentCharacterSize = 25.0f;
215    cursor.x() = 640;
216    cursor.y() = margin*4.0f;
217   
218    typedef std::pair<osgText::Text::AlignmentType,std::string> AlignmentPair;
219    typedef std::vector<AlignmentPair> AlignmentList;
220    AlignmentList alignmentList;
221    alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_TOP,"text->setAlignment(\nosgText::Text::LEFT_TOP);"));
222    alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_CENTER,"text->setAlignment(\nosgText::Text::LEFT_CENTER);"));
223    alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_BOTTOM,"text->setAlignment(\nosgText::Text::LEFT_BOTTOM);"));
224    alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_TOP,"text->setAlignment(\nosgText::Text::CENTER_TOP);"));
225    alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_CENTER,"text->setAlignment(\nosgText::Text::CENTER_CENTER);"));
226    alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_BOTTOM,"text->setAlignment(\nosgText::Text::CENTER_BOTTOM);"));
227    alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_TOP,"text->setAlignment(\nosgText::Text::RIGHT_TOP);"));
228    alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_CENTER,"text->setAlignment(\nosgText::Text::RIGHT_CENTER);"));
229    alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_BOTTOM,"text->setAlignment(\nosgText::Text::RIGHT_BOTTOM);"));
230    alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_BASE_LINE,"text->setAlignment(\nosgText::Text::LEFT_BASE_LINE);"));
231    alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_BASE_LINE,"text->setAlignment(\nosgText::Text::CENTER_BASE_LINE);"));
232    alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_BASE_LINE,"text->setAlignment(\nosgText::Text::RIGHT_BASE_LINE);"));
233    alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_BOTTOM_BASE_LINE,"text->setAlignment(\nosgText::Text::LEFT_BOTTOM_BASE_LINE);"));
234    alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_BOTTOM_BASE_LINE,"text->setAlignment(\nosgText::Text::CENTER_BOTTOM_BASE_LINE);"));
235    alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_BOTTOM_BASE_LINE,"text->setAlignment(\nosgText::Text::RIGHT_BOTTOM_BASE_LINE);"));
236
237
238    osg::Sequence* sequence = new osg::Sequence;
239    {
240        for(AlignmentList::iterator itr=alignmentList.begin();
241            itr!=alignmentList.end();
242            ++itr)
243        {
244            osg::Geode* alignmentGeode = new osg::Geode;
245            sequence->addChild(alignmentGeode);
246            sequence->setTime(sequence->getNumChildren(), 1.0f);
247
248            osgText::Text* text = new osgText::Text;
249            text->setFont(font);
250            text->setColor(alignmentSizeColor);
251            text->setCharacterSize(alignmentCharacterSize);
252            text->setPosition(cursor);
253            text->setDrawMode(osgText::Text::TEXT|osgText::Text::ALIGNMENT|osgText::Text::BOUNDINGBOX);
254           
255            text->setAlignment(itr->first);
256            text->setText(itr->second);
257           
258            alignmentGeode->addDrawable(text);
259
260
261        }
262       
263    }
264
265    sequence->setMode(osg::Sequence::START);
266    sequence->setInterval(osg::Sequence::LOOP, 0, -1);
267    sequence->setDuration(1.0f, -1);
268   
269    rootNode->addChild(sequence);
270
271
272////////////////////////////////////////////////////////////////////////////////////////////////////////
273//   
274// Examples of how to set up different fonts...
275//
276
277    cursor.x() = margin*2.0f;
278    cursor.y() = margin*2.0f;
279   
280    osg::Vec4 fontColor(1.0f,0.5f,0.0f,1.0f);
281    float fontCharacterSize = 20.0f;
282    float spacing = 40.0f;
283   
284    {
285        osgText::Text* text = new osgText::Text;
286        text->setColor(fontColor);
287        text->setPosition(cursor);
288        text->setCharacterSize(fontCharacterSize);
289       
290        text->setFont(0);
291        text->setText("text->setFont(0); // inbuilt font.");
292        geode->addDrawable(text);
293
294        cursor.x() = text->getBound().xMax() + spacing ;
295    }
296   
297    {
298        osgText::Font* arial = osgText::readFontFile("fonts/arial.ttf");
299
300        osgText::Text* text = new osgText::Text;
301        text->setColor(fontColor);
302        text->setPosition(cursor);
303        text->setCharacterSize(fontCharacterSize);
304       
305        text->setFont(arial);
306        text->setText(arial!=0?
307                      "text->setFont(\"fonts/arial.ttf\");":
308                      "unable to load \"fonts/arial.ttf\"");
309        geode->addDrawable(text);
310
311        cursor.x() = text->getBound().xMax() + spacing ;
312    }
313   
314    {
315        osgText::Font* times = osgText::readFontFile("fonts/times.ttf");
316
317        osgText::Text* text = new osgText::Text;
318        text->setColor(fontColor);
319        text->setPosition(cursor);
320        text->setCharacterSize(fontCharacterSize);
321       
322        geode->addDrawable(text);
323        text->setFont(times);
324        text->setText(times!=0?
325                      "text->setFont(\"fonts/times.ttf\");":
326                      "unable to load \"fonts/times.ttf\"");
327
328        cursor.x() = text->getBound().xMax() + spacing ;
329    }
330   
331    cursor.x() = margin*2.0f;
332    cursor.y() = margin;
333
334    {
335        osgText::Font* dirtydoz = osgText::readFontFile("fonts/dirtydoz.ttf");
336
337        osgText::Text* text = new osgText::Text;
338        text->setColor(fontColor);
339        text->setPosition(cursor);
340        text->setCharacterSize(fontCharacterSize);
341       
342        text->setFont(dirtydoz);
343        text->setText(dirtydoz!=0?
344                      "text->setFont(\"fonts/dirtydoz.ttf\");":
345                      "unable to load \"fonts/dirtydoz.ttf\"");
346        geode->addDrawable(text);
347
348        cursor.x() = text->getBound().xMax() + spacing ;
349    }
350   
351    {
352        osgText::Font* fudd = osgText::readFontFile("fonts/fudd.ttf");
353   
354        osgText::Text* text = new osgText::Text;
355        text->setColor(fontColor);
356        text->setPosition(cursor);
357        text->setCharacterSize(fontCharacterSize);
358       
359        text->setFont(fudd);
360        text->setText(fudd!=0?
361                      "text->setFont(\"fonts/fudd.ttf\");":
362                      "unable to load \"fonts/fudd.ttf\"");
363        geode->addDrawable(text);
364
365        cursor.x() = text->getBound().xMax() + spacing ;
366    }
367           
368    return rootNode;   
369}
370
371
372
373
374// create text which sits in 3D space such as would be inserted into a normal model
375osg::Group* create3DText(const osg::Vec3& center,float radius)
376{
377
378    osg::Geode* geode  = new osg::Geode;
379
380////////////////////////////////////////////////////////////////////////////////////////////////////////
381//   
382// Examples of how to set up axis/orientation alignments
383//
384
385    float characterSize=radius*0.2f;
386   
387    osg::Vec3 pos(center.x()-radius*.5f,center.y()-radius*.5f,center.z()-radius*.5f);
388
389    osgText::Text* text1 = new osgText::Text;
390    text1->setFont("fonts/times.ttf");
391    text1->setCharacterSize(characterSize);
392    text1->setPosition(pos);
393    text1->setAxisAlignment(osgText::Text::XY_PLANE);
394    text1->setText("XY_PLANE");
395    geode->addDrawable(text1);
396
397    osgText::Text* text2 = new osgText::Text;
398    text2->setFont("fonts/times.ttf");
399    text2->setCharacterSize(characterSize);
400    text2->setPosition(pos);
401    text2->setAxisAlignment(osgText::Text::YZ_PLANE);
402    text2->setText("YZ_PLANE");
403    geode->addDrawable(text2);
404
405    osgText::Text* text3 = new osgText::Text;
406    text3->setFont("fonts/times.ttf");
407    text3->setCharacterSize(characterSize);
408    text3->setPosition(pos);
409    text3->setAxisAlignment(osgText::Text::XZ_PLANE);
410    text3->setText("XZ_PLANE");
411    geode->addDrawable(text3);
412
413
414    osgText::Text* text4 = new osgText::Text;
415    text4->setFont("fonts/times.ttf");
416    text4->setCharacterSize(characterSize);
417    text4->setPosition(center);
418    text4->setAxisAlignment(osgText::Text::SCREEN);
419
420    osg::Vec4 characterSizeModeColor(1.0f,0.0f,0.5f,1.0f);
421
422    osgText::Text* text5 = new osgText::Text;
423    text5->setColor(characterSizeModeColor);
424    text5->setFont("fonts/times.ttf");
425    //text5->setCharacterSize(characterSize);
426    text5->setCharacterSize(32.0f); // medium
427    text5->setPosition(center - osg::Vec3(0.0, 0.0, 0.2));
428    text5->setAxisAlignment(osgText::Text::SCREEN);
429    text5->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
430    text5->setText("CharacterSizeMode SCREEN_COORDS(size 32.0)");
431    geode->addDrawable(text5);
432
433    osgText::Text* text6 = new osgText::Text;
434    text6->setColor(characterSizeModeColor);
435    text6->setFont("fonts/times.ttf");
436    text6->setCharacterSize(characterSize);
437    text6->setPosition(center - osg::Vec3(0.0, 0.0, 0.4));
438    text6->setAxisAlignment(osgText::Text::SCREEN);
439    text6->setCharacterSizeMode(osgText::Text::OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT);
440    text6->setText("CharacterSizeMode OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT");
441    geode->addDrawable(text6);
442
443    osgText::Text* text7 = new osgText::Text;
444    text7->setColor(characterSizeModeColor);
445    text7->setFont("fonts/times.ttf");
446    text7->setCharacterSize(characterSize);
447    text7->setPosition(center - osg::Vec3(0.0, 0.0, 0.6));
448    text7->setAxisAlignment(osgText::Text::SCREEN);
449    text7->setCharacterSizeMode(osgText::Text::OBJECT_COORDS);
450    text7->setText("CharacterSizeMode OBJECT_COORDS (default)");
451    geode->addDrawable(text7);
452
453#if 1
454    // reproduce outline bounding box compute problem with backdrop on.
455    text4->setBackdropType(osgText::Text::OUTLINE);
456    text4->setDrawMode(osgText::Text::TEXT | osgText::Text::BOUNDINGBOX);
457#endif
458
459    text4->setText("SCREEN");
460    geode->addDrawable(text4);
461
462    osg::ShapeDrawable* shape = new osg::ShapeDrawable(new osg::Sphere(center,characterSize*0.2f));
463    shape->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::ON);
464    geode->addDrawable(shape);
465
466    osg::Group* rootNode = new osg::Group;
467    rootNode->addChild(geode);
468
469    return rootNode;   
470}
471
472int main( int argc, char **argv )
473{
474    // use an ArgumentParser object to manage the program arguments.
475    osg::ArgumentParser arguments(&argc,argv);
476   
477    // set up the usage document, in case we need to print out how to use this program.
478    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use of text.");
479    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] [filename] ...");
480    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
481   
482
483    // construct the viewer.
484    osgProducer::Viewer viewer(arguments);
485
486    // set up the value with sensible default event handlers.
487    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
488
489    // get details on keyboard and mouse bindings used by the viewer.
490    viewer.getUsage(*arguments.getApplicationUsage());
491
492    // if user request help write it out to cout.
493    if (arguments.read("-h") || arguments.read("--help"))
494    {
495        arguments.getApplicationUsage()->write(std::cout);
496        return 1;
497    }
498
499    // any option left unread are converted into errors to write out later.
500    arguments.reportRemainingOptionsAsUnrecognized();
501
502    // report any errors if they have occured when parsing the program aguments.
503    if (arguments.errors())
504    {
505        arguments.writeErrorMessages(std::cout);
506        return 1;
507    }
508   
509
510    // read the scene from the list of file specified commandline args.
511    osg::ref_ptr<osg::Node> rootNode = osgDB::readNodeFiles(arguments);
512
513    // prepare scene.
514    {
515
516        osg::Vec3 center(0.0f,0.0f,0.0f);
517        float radius = 1.0f;
518       
519        if (rootNode.valid())
520        {
521            // optimize the scene graph, remove rendundent nodes and state etc.
522            osgUtil::Optimizer optimizer;
523            optimizer.optimize(rootNode.get());
524           
525            const osg::BoundingSphere& bs = rootNode->getBound();
526            center = bs.center();
527            radius = bs.radius();
528        }
529
530        // make sure the root node is group so we can add extra nodes to it.
531        osg::Group* group = dynamic_cast<osg::Group*>(rootNode.get());
532        if (!group)
533        {
534            group = new osg::Group;
535           
536            if (rootNode.valid()) group->addChild(rootNode.get());
537           
538            rootNode = group;
539        }
540
541        {
542            // create the hud.
543            osg::CameraNode* camera = new osg::CameraNode;
544            camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
545            camera->setProjectionMatrixAsOrtho2D(0,1280,0,1024);
546            camera->setViewMatrix(osg::Matrix::identity());
547            camera->setClearMask(GL_DEPTH_BUFFER_BIT);
548            camera->addChild(createHUDText());
549            camera->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
550
551            group->addChild(camera);
552        }
553
554        group->addChild(create3DText(center,radius));
555
556    }
557
558    // set the scene to render
559    viewer.setSceneData(rootNode.get());
560
561
562    // create the windows and run the threads.
563    viewer.realize();
564
565#if 0
566    // this optional compile block is done as a test against graphics
567    // drivers that claim support for generate mip map, but the actual
568    // implementation is flacky.  It is not compiled by default.
569
570    // go through each graphics context and switch off the generate mip map extension.
571    // note, this must be done after the realize so that init of texture state and as
572    // result extension structures have been iniatilized.
573    for(unsigned int contextID = 0;
574        contextID<viewer.getDisplaySettings()->getMaxNumberOfGraphicsContexts();
575        ++contextID)
576    {
577        osg::Texture::Extensions* textureExt = osg::Texture::getExtensions(contextID,false);
578        if (textureExt) textureExt->setGenerateMipMapSupported(false);
579    }
580#endif
581   
582    while( !viewer.done() )
583    {
584        // wait for all cull and draw threads to complete.
585        viewer.sync();
586
587        // update the scene by traversing it with the the update visitor which will
588        // call all node update callbacks and animations.
589        viewer.update();
590         
591        // fire off the cull and draw traversals of the scene.
592        viewer.frame();
593       
594    }
595   
596    // wait for all cull and draw threads to complete.
597    viewer.sync();
598
599    // run a clean up frame to delete all OpenGL objects.
600    viewer.cleanup_frame();
601
602    // wait for all the clean up frame to complete.
603    viewer.sync();
604
605    return 0;
606}
Note: See TracBrowser for help on using the browser.