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

Revision 3305, 18.8 kB (checked in by robert, 10 years ago)

From Don Tidrow, fixes to comments.

  • 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 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(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 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(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.