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

Revision 1927, 18.8 kB (checked in by robert, 11 years ago)

Added support for automatic scaling of text to screen coords. Optimized
the text implementation to provide better speed, especially by using the
alignement to screen option.

Deprecated the Text::setFontSize(,) method, which is now being replaced
by setFontResolution(,)

Fixed typos in Texture*.cpp.

Removed old deprecated methods from osg headers.

  • 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
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 10 by 10 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 10 by 10 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 20 units high.
171        text->setCharacterSize(20); // small
172       
173        text->setText("text->setCharacterSize(15.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 20 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 uses 10 by 10 texels as a target resolution for fonts.
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(osgText::Text::LEFT_TOP);"));
222    alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_CENTER,"text->setAlignment(osgText::Text::LEFT_CENTER);"));
223    alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_BOTTOM,"text->setAlignment(osgText::Text::LEFT_BOTTOM);"));
224    alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_TOP,"text->setAlignment(osgText::Text::CENTER_TOP);"));
225    alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_CENTER,"text->setAlignment(osgText::Text::CENTER_CENTER);"));
226    alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_BOTTOM,"text->setAlignment(osgText::Text::CENTER_BOTTOM);"));
227    alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_TOP,"text->setAlignment(osgText::Text::RIGHT_TOP);"));
228    alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_CENTER,"text->setAlignment(osgText::Text::RIGHT_CENTER);"));
229    alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_BOTTOM,"text->setAlignment(osgText::Text::RIGHT_BOTTOM);"));
230    alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_BASE_LINE,"text->setAlignment(osgText::Text::BASE_LINE);"));
231    alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_BASE_LINE,"text->setAlignment(osgText::Text::CENTER_BASE_LINE);"));
232    alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_BASE_LINE,"text->setAlignment(osgText::Text::RIGHT_BASE_LINE);"));
233
234    osg::Sequence* sequence = new osg::Sequence;
235    {
236        for(AlignmentList::iterator itr=alignmentList.begin();
237            itr!=alignmentList.end();
238            ++itr)
239        {
240            osg::Geode* alignmentGeode = new osg::Geode;
241            sequence->addChild(alignmentGeode);
242            sequence->setTime(sequence->getNumChildren(), 1.0f);
243
244            osgText::Text* text = new osgText::Text;
245            text->setFont(font);
246            text->setColor(alignmentSizeColor);
247            text->setCharacterSize(alignmentCharacterSize);
248            text->setPosition(cursor);
249            text->setDrawMode(osgText::Text::TEXT|osgText::Text::ALIGNMENT|osgText::Text::BOUNDINGBOX);
250           
251            text->setAlignment(itr->first);
252            text->setText(itr->second);
253           
254            alignmentGeode->addDrawable(text);
255
256
257        }
258       
259    }
260
261    sequence->setMode(osg::Sequence::START);
262    sequence->setInterval(osg::Sequence::LOOP, 0, -1);
263    sequence->setDuration(1.0f, -1);
264   
265    rootNode->addChild(sequence);
266
267
268////////////////////////////////////////////////////////////////////////////////////////////////////////
269//   
270// Examples of how to set up different fonts...
271//
272
273    cursor.x() = margin*2.0f;
274    cursor.y() = margin*2.0f;
275   
276    osg::Vec4 fontColor(1.0f,0.5f,0.0f,1.0f);
277    float fontCharacterSize = 20.0f;
278    float spacing = 40.0f;
279   
280    {
281        osgText::Text* text = new osgText::Text;
282        text->setColor(fontColor);
283        text->setPosition(cursor);
284        text->setCharacterSize(fontCharacterSize);
285       
286        text->setFont(0);
287        text->setText("text->setFont(0); // inbuilt font.");
288        geode->addDrawable(text);
289
290        cursor.x() = text->getBound().xMax() + spacing ;
291    }
292   
293    {
294        osgText::Font* arial = osgText::readFontFile("fonts/arial.ttf");
295
296        osgText::Text* text = new osgText::Text;
297        text->setColor(fontColor);
298        text->setPosition(cursor);
299        text->setCharacterSize(fontCharacterSize);
300       
301        text->setFont(arial);
302        text->setText(arial!=0?
303                      "text->setFont(\"fonts/arial.ttf\");":
304                      "unable to load \"fonts/arial.ttf\"");
305        geode->addDrawable(text);
306
307        cursor.x() = text->getBound().xMax() + spacing ;
308    }
309   
310    {
311        osgText::Font* times = osgText::readFontFile("fonts/times.ttf");
312
313        osgText::Text* text = new osgText::Text;
314        text->setColor(fontColor);
315        text->setPosition(cursor);
316        text->setCharacterSize(fontCharacterSize);
317       
318        geode->addDrawable(text);
319        text->setFont(times);
320        text->setText(times!=0?
321                      "text->setFont(\"fonts/times.ttf\");":
322                      "unable to load \"fonts/times.ttf\"");
323
324        cursor.x() = text->getBound().xMax() + spacing ;
325    }
326   
327    cursor.x() = margin*2.0f;
328    cursor.y() = margin;
329
330    {
331        osgText::Font* dirtydoz = osgText::readFontFile("fonts/dirtydoz.ttf");
332
333        osgText::Text* text = new osgText::Text;
334        text->setColor(fontColor);
335        text->setPosition(cursor);
336        text->setCharacterSize(fontCharacterSize);
337       
338        text->setFont(dirtydoz);
339        text->setText(dirtydoz!=0?
340                      "text->setFont(\"fonts/dirtydoz.ttf\");":
341                      "unable to load \"fonts/dirtydoz.ttf\"");
342        geode->addDrawable(text);
343
344        cursor.x() = text->getBound().xMax() + spacing ;
345    }
346   
347    {
348        osgText::Font* fudd = osgText::readFontFile("fonts/fudd.ttf");
349   
350        osgText::Text* text = new osgText::Text;
351        text->setColor(fontColor);
352        text->setPosition(cursor);
353        text->setCharacterSize(fontCharacterSize);
354       
355        text->setFont(fudd);
356        text->setText(fudd!=0?
357                      "text->setFont(\"fonts/fudd.ttf\");":
358                      "unable to load \"fonts/fudd.ttf\"");
359        geode->addDrawable(text);
360
361        cursor.x() = text->getBound().xMax() + spacing ;
362    }
363           
364    return rootNode;   
365}
366
367
368
369
370// create text which sits in 3D space such as would be inserted into a normal model
371osg::Group* create3DText(const osg::Vec3& center,float radius)
372{
373
374    osg::Geode* geode  = new osg::Geode;
375
376////////////////////////////////////////////////////////////////////////////////////////////////////////
377//   
378// Examples of how to set up axis/orientation alignments
379//
380
381    float characterSize=radius*0.2f;
382   
383    osg::Vec3 pos(center.x()-radius*.5f,center.y()-radius*.5f,center.z()-radius*.5f);
384
385    osgText::Text* text1 = new osgText::Text;
386    text1->setFont("fonts/times.ttf");
387    text1->setCharacterSize(characterSize);
388    text1->setPosition(pos);
389    text1->setAxisAlignment(osgText::Text::XY_PLANE);
390    text1->setText("XY_PLANE");
391    geode->addDrawable(text1);
392
393    osgText::Text* text2 = new osgText::Text;
394    text2->setFont("fonts/times.ttf");
395    text2->setCharacterSize(characterSize);
396    text2->setPosition(pos);
397    text2->setAxisAlignment(osgText::Text::YZ_PLANE);
398    text2->setText("YZ_PLANE");
399    geode->addDrawable(text2);
400
401    osgText::Text* text3 = new osgText::Text;
402    text3->setFont("fonts/times.ttf");
403    text3->setCharacterSize(characterSize);
404    text3->setPosition(pos);
405    text3->setAxisAlignment(osgText::Text::XZ_PLANE);
406    text3->setText("XZ_PLANE");
407    geode->addDrawable(text3);
408
409
410    osgText::Text* text4 = new osgText::Text;
411    text4->setFont("fonts/times.ttf");
412    text4->setCharacterSize(characterSize);
413    text4->setPosition(center);
414    text4->setAxisAlignment(osgText::Text::SCREEN);
415    text4->setText("SCREEN");
416    geode->addDrawable(text4);
417
418    osg::ShapeDrawable* shape = new osg::ShapeDrawable(new osg::Sphere(center,characterSize*0.2f));
419    shape->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::ON);
420    geode->addDrawable(shape);
421
422
423    osg::Group* rootNode = new osg::Group;
424    rootNode->addChild(geode);
425
426    return rootNode;   
427}
428
429int main( int argc, char **argv )
430{
431    // use an ArgumentParser object to manage the program arguments.
432    osg::ArgumentParser arguments(&argc,argv);
433   
434    // set up the usage document, in case we need to print out how to use this program.
435    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use of text.");
436    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] [filename] ...");
437    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
438   
439
440    // construct the viewer.
441    osgProducer::Viewer viewer(arguments);
442
443    // set up the value with sensible default event handlers.
444    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
445
446    // get details on keyboard and mouse bindings used by the viewer.
447    viewer.getUsage(*arguments.getApplicationUsage());
448
449    // if user request help write it out to cout.
450    if (arguments.read("-h") || arguments.read("--help"))
451    {
452        arguments.getApplicationUsage()->write(std::cout);
453        return 1;
454    }
455
456    // any option left unread are converted into errors to write out later.
457    arguments.reportRemainingOptionsAsUnrecognized();
458
459    // report any errors if they have occured when parsing the program aguments.
460    if (arguments.errors())
461    {
462        arguments.writeErrorMessages(std::cout);
463        return 1;
464    }
465   
466
467    // read the scene from the list of file specified commandline args.
468    osg::ref_ptr<osg::Node> rootNode = osgDB::readNodeFiles(arguments);
469
470    // prepare scene.
471    {
472
473        osg::Vec3 center(0.0f,0.0f,0.0f);
474        float radius = 1.0f;
475       
476        if (rootNode.valid())
477        {
478            // optimize the scene graph, remove rendundent nodes and state etc.
479            osgUtil::Optimizer optimizer;
480            optimizer.optimize(rootNode.get());
481           
482            const osg::BoundingSphere& bs = rootNode->getBound();
483            center = bs.center();
484            radius = bs.radius();
485        }
486
487        // make sure the root node is group so we can add extra nodes to it.
488        osg::Group* group = dynamic_cast<osg::Group*>(rootNode.get());
489        if (!group)
490        {
491            group = new osg::Group;
492           
493            if (rootNode.valid()) group->addChild(rootNode.get());
494           
495            rootNode = group;
496        }
497
498        {
499            // create the hud.
500            osg::Projection* projection = new osg::Projection;
501            projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024));
502
503            osg::MatrixTransform* modelview_abs = new osg::MatrixTransform;
504            modelview_abs->setReferenceFrame(osg::Transform::RELATIVE_TO_ABSOLUTE);
505            modelview_abs->setMatrix(osg::Matrix::identity());
506
507            modelview_abs->addChild(createHUDText());
508
509            projection->addChild(modelview_abs);
510
511            group->addChild(projection);
512        }
513
514        group->addChild(create3DText(center,radius));
515
516    }
517
518    // set the scene to render
519    viewer.setSceneData(rootNode.get());
520
521
522    // create the windows and run the threads.
523    viewer.realize();
524
525#if 0
526    // this optional compile block is done as a test against graphics
527    // drivers that claim support for generate mip map, but the actual
528    // implementation is flacky.  It is not compiled by default.
529
530    // go through each graphics context and switch off the generate mip map extension.
531    // note, this must be done after the realize so that init of texture state and as
532    // result extension structures have been iniatilized.
533    for(unsigned int contextID = 0;
534        contextID<viewer.getDisplaySettings()->getMaxNumberOfGraphicsContexts();
535        ++contextID)
536    {
537        osg::Texture::Extensions* textureExt = osg::Texture::getExtensions(contextID,false);
538        if (textureExt) textureExt->setGenerateMipMapSupported(false);
539    }
540#endif
541   
542    while( !viewer.done() )
543    {
544        // wait for all cull and draw threads to complete.
545        viewer.sync();
546
547        // update the scene by traversing it with the the update visitor which will
548        // call all node update callbacks and animations.
549        viewer.update();
550         
551        // fire off the cull and draw traversals of the scene.
552        viewer.frame();
553       
554    }
555   
556    // wait for all cull and draw threads to complete before exit.
557    viewer.sync();
558
559    return 0;
560}
Note: See TracBrowser for help on using the browser.