1 /* OpenSceneGraph example, osgtext.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16 * THE SOFTWARE.
17 */
18
19 #include <QApplication>
20 #include <QGridLayout>
21 #include <QWidget>
22
23 #include <osgQt/GraphicsWindowQt>
24 #include <osgQt/QFontImplementation>
25
26 #include <osgDB/ReadFile>
27 #include <osgDB/WriteFile>
28 #include <osgDB/Registry>
29
30 #include <osgGA/StateSetManipulator>
31 #include <osgGA/TrackballManipulator>
32 #include <osgViewer/CompositeViewer>
33 #include <osgViewer/ViewerEventHandlers>
34
35 #include <osg/Geode>
36 #include <osg/Camera>
37 #include <osg/ShapeDrawable>
38 #include <osg/Sequence>
39 #include <osg/PolygonMode>
40
41 #include <osgText/Font>
42 #include <osgText/Text>
43
createHUDText()44 osg::Group* createHUDText()
45 {
46
47 osg::Group* rootNode = new osg::Group;
48
49 osgText::Font* font = new osgText::Font(new osgQt::QFontImplementation(QFont("Arial")));
50
51 osg::Geode* geode = new osg::Geode;
52 rootNode->addChild(geode);
53
54 float windowHeight = 1024.0f;
55 float windowWidth = 1280.0f;
56 float margin = 50.0f;
57
58
59 ////////////////////////////////////////////////////////////////////////////////////////////////////////
60 //
61 // Examples of how to set up different text layout
62 //
63
64 osg::Vec4 layoutColor(1.0f,1.0f,0.0f,1.0f);
65 float layoutCharacterSize = 20.0f;
66
67 {
68 osgText::Text* text = new osgText::Text;
69 text->setFont(font);
70 text->setColor(layoutColor);
71 text->setCharacterSize(layoutCharacterSize);
72 text->setPosition(osg::Vec3(margin,windowHeight-margin,0.0f));
73
74 // the default layout is left to right, typically used in languages
75 // originating from europe such as English, French, German, Spanish etc..
76 text->setLayout(osgText::Text::LEFT_TO_RIGHT);
77
78 text->setText("text->setLayout(osgText::Text::LEFT_TO_RIGHT);");
79 geode->addDrawable(text);
80 }
81
82 {
83 osgText::Text* text = new osgText::Text;
84 text->setFont(font);
85 text->setColor(layoutColor);
86 text->setCharacterSize(layoutCharacterSize);
87 text->setPosition(osg::Vec3(windowWidth-margin,windowHeight-margin,0.0f));
88
89 // right to left layouts would be used for hebrew or arabic fonts.
90 text->setLayout(osgText::Text::RIGHT_TO_LEFT);
91 text->setAlignment(osgText::Text::RIGHT_BASE_LINE);
92
93 text->setText("text->setLayout(osgText::Text::RIGHT_TO_LEFT);");
94 geode->addDrawable(text);
95 }
96
97 {
98 osgText::Text* text = new osgText::Text;
99 text->setFont(font);
100 text->setColor(layoutColor);
101 text->setPosition(osg::Vec3(margin,windowHeight-margin,0.0f));
102 text->setCharacterSize(layoutCharacterSize);
103
104 // vertical font layout would be used for asian fonts.
105 text->setLayout(osgText::Text::VERTICAL);
106
107 text->setText("text->setLayout(osgText::Text::VERTICAL);");
108 geode->addDrawable(text);
109 }
110
111
112 ////////////////////////////////////////////////////////////////////////////////////////////////////////
113 //
114 // Examples of how to set up different font resolution
115 //
116
117 osg::Vec4 fontSizeColor(0.0f,1.0f,1.0f,1.0f);
118 float fontSizeCharacterSize = 30;
119
120 osg::Vec3 cursor = osg::Vec3(margin*2,windowHeight-margin*2,0.0f);
121
122 {
123 osgText::Text* text = new osgText::Text;
124 text->setFont(font);
125 text->setColor(fontSizeColor);
126 text->setCharacterSize(fontSizeCharacterSize);
127 text->setPosition(cursor);
128
129 // use text that uses 10 by 10 texels as a target resolution for fonts.
130 text->setFontResolution(10,10); // blocky but small texture memory usage
131
132 text->setText("text->setFontResolution(10,10); // blocky but small texture memory usage");
133 geode->addDrawable(text);
134 }
135
136 cursor.y() -= fontSizeCharacterSize;
137 {
138 osgText::Text* text = new osgText::Text;
139 text->setFont(font);
140 text->setColor(fontSizeColor);
141 text->setCharacterSize(fontSizeCharacterSize);
142 text->setPosition(cursor);
143
144 // use text that uses 20 by 20 texels as a target resolution for fonts.
145 text->setFontResolution(20,20); // smoother but higher texture memory usage (but still quite low).
146
147 text->setText("text->setFontResolution(20,20); // smoother but higher texture memory usage (but still quite low).");
148 geode->addDrawable(text);
149 }
150
151 cursor.y() -= fontSizeCharacterSize;
152 {
153 osgText::Text* text = new osgText::Text;
154 text->setFont(font);
155 text->setColor(fontSizeColor);
156 text->setCharacterSize(fontSizeCharacterSize);
157 text->setPosition(cursor);
158
159 // use text that uses 40 by 40 texels as a target resolution for fonts.
160 text->setFontResolution(40,40); // even smoother but again higher texture memory usage.
161
162 text->setText("text->setFontResolution(40,40); // even smoother but again higher texture memory usage.");
163 geode->addDrawable(text);
164 }
165
166
167 ////////////////////////////////////////////////////////////////////////////////////////////////////////
168 //
169 // Examples of how to set up different sized text
170 //
171
172 osg::Vec4 characterSizeColor(1.0f,0.0f,1.0f,1.0f);
173
174 cursor.y() -= fontSizeCharacterSize*2.0f;
175
176 {
177 osgText::Text* text = new osgText::Text;
178 text->setFont(font);
179 text->setColor(characterSizeColor);
180 text->setFontResolution(20,20);
181 text->setPosition(cursor);
182
183 // use text that is 20 units high.
184 text->setCharacterSize(20); // small
185
186 text->setText("text->setCharacterSize(20.0f); // small");
187 geode->addDrawable(text);
188 }
189
190 cursor.y() -= 30.0f;
191 {
192 osgText::Text* text = new osgText::Text;
193 text->setFont(font);
194 text->setColor(characterSizeColor);
195 text->setFontResolution(30,30);
196 text->setPosition(cursor);
197
198 // use text that is 30 units high.
199 text->setCharacterSize(30.0f); // medium
200
201 text->setText("text->setCharacterSize(30.0f); // medium");
202 geode->addDrawable(text);
203 }
204
205 cursor.y() -= 50.0f;
206 {
207 osgText::Text* text = new osgText::Text;
208 text->setFont(font);
209 text->setColor(characterSizeColor);
210 text->setFontResolution(40,40);
211 text->setPosition(cursor);
212
213 // use text that is 60 units high.
214 text->setCharacterSize(60.0f); // large
215
216 text->setText("text->setCharacterSize(60.0f); // large");
217 geode->addDrawable(text);
218 }
219
220
221 ////////////////////////////////////////////////////////////////////////////////////////////////////////
222 //
223 // Examples of how to set up different alignments
224 //
225
226 osg::Vec4 alignmentSizeColor(0.0f,1.0f,0.0f,1.0f);
227 float alignmentCharacterSize = 25.0f;
228 cursor.x() = 640;
229 cursor.y() = margin*4.0f;
230
231 typedef std::pair<osgText::Text::AlignmentType,std::string> AlignmentPair;
232 typedef std::vector<AlignmentPair> AlignmentList;
233 AlignmentList alignmentList;
234 alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_TOP,"text->setAlignment(\nosgText::Text::LEFT_TOP);"));
235 alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_CENTER,"text->setAlignment(\nosgText::Text::LEFT_CENTER);"));
236 alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_BOTTOM,"text->setAlignment(\nosgText::Text::LEFT_BOTTOM);"));
237 alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_TOP,"text->setAlignment(\nosgText::Text::CENTER_TOP);"));
238 alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_CENTER,"text->setAlignment(\nosgText::Text::CENTER_CENTER);"));
239 alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_BOTTOM,"text->setAlignment(\nosgText::Text::CENTER_BOTTOM);"));
240 alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_TOP,"text->setAlignment(\nosgText::Text::RIGHT_TOP);"));
241 alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_CENTER,"text->setAlignment(\nosgText::Text::RIGHT_CENTER);"));
242 alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_BOTTOM,"text->setAlignment(\nosgText::Text::RIGHT_BOTTOM);"));
243 alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_BASE_LINE,"text->setAlignment(\nosgText::Text::LEFT_BASE_LINE);"));
244 alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_BASE_LINE,"text->setAlignment(\nosgText::Text::CENTER_BASE_LINE);"));
245 alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_BASE_LINE,"text->setAlignment(\nosgText::Text::RIGHT_BASE_LINE);"));
246 alignmentList.push_back(AlignmentPair(osgText::Text::LEFT_BOTTOM_BASE_LINE,"text->setAlignment(\nosgText::Text::LEFT_BOTTOM_BASE_LINE);"));
247 alignmentList.push_back(AlignmentPair(osgText::Text::CENTER_BOTTOM_BASE_LINE,"text->setAlignment(\nosgText::Text::CENTER_BOTTOM_BASE_LINE);"));
248 alignmentList.push_back(AlignmentPair(osgText::Text::RIGHT_BOTTOM_BASE_LINE,"text->setAlignment(\nosgText::Text::RIGHT_BOTTOM_BASE_LINE);"));
249
250
251 osg::Sequence* sequence = new osg::Sequence;
252 {
253 for(AlignmentList::iterator itr=alignmentList.begin();
254 itr!=alignmentList.end();
255 ++itr)
256 {
257 osg::Geode* alignmentGeode = new osg::Geode;
258 sequence->addChild(alignmentGeode);
259 sequence->setTime(sequence->getNumChildren(), 1.0f);
260
261 osgText::Text* text = new osgText::Text;
262 text->setFont(font);
263 text->setColor(alignmentSizeColor);
264 text->setCharacterSize(alignmentCharacterSize);
265 text->setPosition(cursor);
266 text->setDrawMode(osgText::Text::TEXT|osgText::Text::ALIGNMENT|osgText::Text::BOUNDINGBOX);
267
268 text->setAlignment(itr->first);
269 text->setText(itr->second);
270
271 alignmentGeode->addDrawable(text);
272
273
274 }
275
276 }
277
278 sequence->setMode(osg::Sequence::START);
279 sequence->setInterval(osg::Sequence::LOOP, 0, -1);
280 sequence->setDuration(1.0f, -1);
281
282 rootNode->addChild(sequence);
283
284
285 ////////////////////////////////////////////////////////////////////////////////////////////////////////
286 //
287 // Examples of how to set up different fonts...
288 //
289
290 cursor.x() = margin*2.0f;
291 cursor.y() = margin*2.0f;
292
293 osg::Vec4 fontColor(1.0f,0.5f,0.0f,1.0f);
294 float fontCharacterSize = 20.0f;
295 float spacing = 40.0f;
296
297 {
298 osgText::Text* text = new osgText::Text;
299 text->setColor(fontColor);
300 text->setPosition(cursor);
301 text->setCharacterSize(fontCharacterSize);
302
303 text->setFont(0);
304 text->setText("text->setFont(0); // inbuilt font.");
305 geode->addDrawable(text);
306
307 cursor.x() = text->getBoundingBox().xMax() + spacing ;
308 }
309
310 {
311 osgText::Font* arial = new osgText::Font(new osgQt::QFontImplementation(QFont("Arial")));
312
313 osgText::Text* text = new osgText::Text;
314 text->setColor(fontColor);
315 text->setPosition(cursor);
316 text->setCharacterSize(fontCharacterSize);
317
318 text->setFont(arial);
319 text->setText(arial!=0?
320 "text->setFont(\"fonts/arial.ttf\");":
321 "unable to load \"fonts/arial.ttf\"");
322 geode->addDrawable(text);
323
324 cursor.x() = text->getBoundingBox().xMax() + spacing ;
325 }
326
327 {
328 osgText::Font* times = new osgText::Font(new osgQt::QFontImplementation(QFont("Times")));
329
330 osgText::Text* text = new osgText::Text;
331 text->setColor(fontColor);
332 text->setPosition(cursor);
333 text->setCharacterSize(fontCharacterSize);
334
335 geode->addDrawable(text);
336 text->setFont(times);
337 text->setText(times!=0?
338 "text->setFont(\"fonts/times.ttf\");":
339 "unable to load \"fonts/times.ttf\"");
340
341 cursor.x() = text->getBoundingBox().xMax() + spacing ;
342 }
343
344 cursor.x() = margin*2.0f;
345 cursor.y() = margin;
346
347 {
348 osgText::Font* dirtydoz = new osgText::Font(new osgQt::QFontImplementation(QFont("Times")));
349
350 osgText::Text* text = new osgText::Text;
351 text->setColor(fontColor);
352 text->setPosition(cursor);
353 text->setCharacterSize(fontCharacterSize);
354
355 text->setFont(dirtydoz);
356 text->setText(dirtydoz!=0?
357 "text->setFont(\"fonts/dirtydoz.ttf\");":
358 "unable to load \"fonts/dirtydoz.ttf\"");
359 geode->addDrawable(text);
360
361 cursor.x() = text->getBoundingBox().xMax() + spacing ;
362 }
363
364 {
365 osgText::Font* fudd = new osgText::Font(new osgQt::QFontImplementation(QFont("Times")));
366
367 osgText::Text* text = new osgText::Text;
368 text->setColor(fontColor);
369 text->setPosition(cursor);
370 text->setCharacterSize(fontCharacterSize);
371
372 text->setFont(fudd);
373 text->setText(fudd!=0?
374 "text->setFont(\"fonts/fudd.ttf\");":
375 "unable to load \"fonts/fudd.ttf\"");
376 geode->addDrawable(text);
377
378 cursor.x() = text->getBoundingBox().xMax() + spacing ;
379 }
380
381 return rootNode;
382 }
383
384
385
386
387 // create text which sits in 3D space such as would be inserted into a normal model
create3DText(const osg::Vec3 & center,float radius)388 osg::Group* create3DText(const osg::Vec3& center,float radius)
389 {
390
391 osg::Geode* geode = new osg::Geode;
392
393 ////////////////////////////////////////////////////////////////////////////////////////////////////////
394 //
395 // Examples of how to set up axis/orientation alignments
396 //
397
398 float characterSize=radius*0.2f;
399
400 osg::Vec3 pos(center.x()-radius*.5f,center.y()-radius*.5f,center.z()-radius*.5f);
401
402 osgText::Text* text1 = new osgText::Text;
403 text1->setFont(new osgText::Font(new osgQt::QFontImplementation(QFont("Times"))));
404 text1->setCharacterSize(characterSize);
405 text1->setPosition(pos);
406 text1->setAxisAlignment(osgText::Text::XY_PLANE);
407 text1->setText("XY_PLANE");
408 geode->addDrawable(text1);
409
410 osgText::Text* text2 = new osgText::Text;
411 text2->setFont(new osgText::Font(new osgQt::QFontImplementation(QFont("Times"))));
412 text2->setCharacterSize(characterSize);
413 text2->setPosition(pos);
414 text2->setAxisAlignment(osgText::Text::YZ_PLANE);
415 text2->setText("YZ_PLANE");
416 geode->addDrawable(text2);
417
418 osgText::Text* text3 = new osgText::Text;
419 text3->setFont(new osgText::Font(new osgQt::QFontImplementation(QFont("Times"))));
420 text3->setCharacterSize(characterSize);
421 text3->setPosition(pos);
422 text3->setAxisAlignment(osgText::Text::XZ_PLANE);
423 text3->setText("XZ_PLANE");
424 geode->addDrawable(text3);
425
426
427 osgText::Text* text4 = new osgText::Text;
428 text4->setFont(new osgText::Font(new osgQt::QFontImplementation(QFont("Times"))));
429 text4->setCharacterSize(characterSize);
430 text4->setPosition(center);
431 text4->setAxisAlignment(osgText::Text::SCREEN);
432
433 osg::Vec4 characterSizeModeColor(1.0f,0.0f,0.5f,1.0f);
434
435 osgText::Text* text5 = new osgText::Text;
436 text5->setColor(characterSizeModeColor);
437 text5->setFont(new osgText::Font(new osgQt::QFontImplementation(QFont("Times"))));
438 //text5->setCharacterSize(characterSize);
439 text5->setCharacterSize(32.0f); // medium
440 text5->setPosition(center - osg::Vec3(0.0, 0.0, 0.2));
441 text5->setAxisAlignment(osgText::Text::SCREEN);
442 text5->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
443 text5->setText("CharacterSizeMode SCREEN_COORDS(size 32.0)");
444 geode->addDrawable(text5);
445
446 osgText::Text* text6 = new osgText::Text;
447 text6->setColor(characterSizeModeColor);
448 text6->setFont(new osgText::Font(new osgQt::QFontImplementation(QFont("Times"))));
449 text6->setCharacterSize(characterSize);
450 text6->setPosition(center - osg::Vec3(0.0, 0.0, 0.4));
451 text6->setAxisAlignment(osgText::Text::SCREEN);
452 text6->setCharacterSizeMode(osgText::Text::OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT);
453 text6->setText("CharacterSizeMode OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT");
454 geode->addDrawable(text6);
455
456 osgText::Text* text7 = new osgText::Text;
457 text7->setColor(characterSizeModeColor);
458 text7->setFont(new osgText::Font(new osgQt::QFontImplementation(QFont("Times"))));
459 text7->setCharacterSize(characterSize);
460 text7->setPosition(center - osg::Vec3(0.0, 0.0, 0.6));
461 text7->setAxisAlignment(osgText::Text::SCREEN);
462 text7->setCharacterSizeMode(osgText::Text::OBJECT_COORDS);
463 text7->setText("CharacterSizeMode OBJECT_COORDS (default)");
464 geode->addDrawable(text7);
465
466 #if 1
467 // reproduce outline bounding box compute problem with backdrop on.
468 text4->setBackdropType(osgText::Text::OUTLINE);
469 text4->setDrawMode(osgText::Text::TEXT | osgText::Text::BOUNDINGBOX);
470 #endif
471
472 text4->setText("SCREEN");
473 geode->addDrawable(text4);
474
475 osg::ShapeDrawable* shape = new osg::ShapeDrawable(new osg::Sphere(center,characterSize*0.2f));
476 shape->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::ON);
477 geode->addDrawable(shape);
478
479 osg::Group* rootNode = new osg::Group;
480 rootNode->addChild(geode);
481
482 return rootNode;
483 }
484
485 class MainWindow : public QWidget {
486 public:
MainWindow()487 MainWindow()
488 {
489 osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits(osg::DisplaySettings::instance().get());
490 traits->width = width();
491 traits->height = height();
492 traits->doubleBuffer = true;
493 osgQt::GraphicsWindowQt* graphicsWindow = new osgQt::GraphicsWindowQt(traits.get());
494
495 QGridLayout* grid = new QGridLayout;
496 grid->setMargin(0);
497 grid->addWidget(graphicsWindow->getGLWidget(), 0, 0);
498 setLayout(grid);
499
500 _viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);
501
502 osg::Camera* camera = _viewer.getCamera();
503 camera->setGraphicsContext(graphicsWindow);
504 camera->setViewport(new osg::Viewport(0, 0, width(), height()));
505
506 startTimer(10);
507 }
508
paintEvent(QPaintEvent * event)509 virtual void paintEvent(QPaintEvent* event)
510 {
511 _viewer.frame();
512 }
timerEvent(QTimerEvent * event)513 virtual void timerEvent(QTimerEvent* event)
514 {
515 _viewer.frame();
516 }
517
setSceneData(osg::Node * node)518 void setSceneData(osg::Node* node)
519 {
520 _viewer.setSceneData(node);
521 }
setCameraManipulator(osgGA::CameraManipulator * manipulator,bool resetPosition=true)522 void setCameraManipulator(osgGA::CameraManipulator* manipulator, bool resetPosition = true)
523 {
524 _viewer.setCameraManipulator(manipulator, resetPosition);
525 }
526
527 private:
528 osgViewer::Viewer _viewer;
529 };
530
main(int argc,char ** argv)531 int main(int argc, char** argv)
532 {
533 QApplication app(argc, argv);
534
535 // prepare scene.
536 osg::Vec3 center(0.0f,0.0f,0.0f);
537 float radius = 1.0f;
538
539 // create the hud.
540 osg::ref_ptr<osg::Camera> camera = new osg::Camera;
541 camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
542 camera->setProjectionMatrixAsOrtho2D(0,1280,0,1024);
543 camera->setViewMatrix(osg::Matrix::identity());
544 camera->setClearMask(GL_DEPTH_BUFFER_BIT);
545 camera->addChild(createHUDText());
546 camera->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
547
548 // make sure the root node is group so we can add extra nodes to it.
549 osg::ref_ptr<osg::Group> group = new osg::Group;
550 group->addChild(camera.get());
551 group->addChild(create3DText(center, radius));
552
553 // The qt window
554 MainWindow widget;
555
556 // set the scene to render
557 widget.setSceneData(group.get());
558 widget.setCameraManipulator(new osgGA::TrackballManipulator);
559
560 widget.setGeometry(100, 100, 800, 600);
561 widget.show();
562
563 return app.exec();
564 }
565