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

Revision 1662, 17.6 kB (checked in by robert, 11 years ago)

Changed the osgText::Font implementation so it used a facade us abstract away
the actual implemention. This has been done so that when a freetype font is
created the implementation can unloaded when the freetype plugin is unloaded
without breaking the main font.

Also add image margin around founds to prevent any image boundaries appearing.

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