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

Revision 4391, 19.3 kB (checked in by robert, 9 years ago)

From Yuri Vilmanis, improved multi-line justifaction support and new alignment modes

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