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

Revision 1927, 15.0 kB (checked in by robert, 12 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#include <osg/Geode>
2#include <osg/ShapeDrawable>
3#include <osg/Material>
4#include <osg/Texture2D>
5#include <osg/Geometry>
6#include <osg/MatrixTransform>
7#include <osg/PositionAttitudeTransform>
8#include <osg/BlendFunc>
9#include <osg/ClearNode>
10
11#include <osgUtil/Tesselator>
12#include <osgUtil/TransformCallback>
13#include <osgUtil/CullVisitor>
14
15#include <osgText/Text>
16
17#include <osgGA/TrackballManipulator>
18
19#include <osgProducer/Viewer>
20
21#include <osgDB/ReadFile>
22
23static bool s_ProfessionalServices = false;
24
25class MyBillboardTransform : public osg::PositionAttitudeTransform
26{
27    public:
28   
29        MyBillboardTransform():
30            _axis(0.0f,0.0f,1.0f),
31            _normal(0.0f,-1.0f,0.0f)
32        {
33        }
34       
35        bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const
36        {
37            osg::Quat billboardRotation;
38            osgUtil::CullVisitor* cullvisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
39            if (cullvisitor)
40            {
41                osg::Vec3 eyevector = cullvisitor->getEyeLocal()-_position;
42                eyevector.normalize();
43
44                osg::Vec3 side = _axis^_normal;
45                side.normalize();
46
47                float angle = atan2(eyevector*_normal,eyevector*side);
48                billboardRotation.makeRotate(osg::PI_2-angle,_axis);
49
50            }
51
52
53            matrix.preMult(osg::Matrix::translate(-_pivotPoint)*
54                           osg::Matrix::rotate(_attitude)*
55                           osg::Matrix::rotate(billboardRotation)*
56                           osg::Matrix::translate(_position));
57            return true;
58        }
59
60
61       
62        void setAxis(const osg::Vec3& axis) { _axis = axis; }
63
64        void setNormal(const osg::Vec3& normal) { _normal = normal; }
65       
66    protected:
67   
68        virtual ~MyBillboardTransform() {}
69       
70        osg::Vec3 _axis;
71        osg::Vec3 _normal;
72};
73
74
75osg::Geometry* createWing(const osg::Vec3& left, const osg::Vec3& nose, const osg::Vec3& right,float chordRatio,const osg::Vec4& color)
76{
77    osg::Geometry* geom = new osg::Geometry;
78
79    osg::Vec3 normal = (nose-right)^(left-nose);
80    normal.normalize();
81
82    osg::Vec3 left_to_right = right-left;
83    osg::Vec3 mid = (right+left)*0.5f;
84    osg::Vec3 mid_to_nose = (nose-mid)*chordRatio*0.5f;
85   
86    osg::Vec3Array* vertices = new osg::Vec3Array;
87    vertices->push_back(left);
88    //vertices->push_back(mid+mid_to_nose);
89   
90    unsigned int noSteps = 40;
91    for(unsigned int i=1;i<noSteps;++i)
92    {
93        float ratio = (float)i/(float)noSteps;
94        vertices->push_back(left + left_to_right*ratio + mid_to_nose* (cosf((ratio-0.5f)*osg::PI*2.0f)+1.0f));
95    }
96   
97    vertices->push_back(right);
98    vertices->push_back(nose);
99
100    geom->setVertexArray(vertices);
101
102
103    osg::Vec3Array* normals = new osg::Vec3Array;
104    normals->push_back(normal);
105    geom->setNormalArray(normals);
106    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
107   
108   
109    osg::Vec4Array* colors = new osg::Vec4Array;
110    colors->push_back(color);
111    geom->setColorArray(colors);
112    geom->setColorBinding(osg::Geometry::BIND_OVERALL);
113   
114
115    geom->addPrimitiveSet(new osg::DrawArrays(GL_POLYGON,0,vertices->getNumElements()));
116   
117    osgUtil::Tesselator tesselator;
118    tesselator.retesselatePolygons(*geom);
119
120    return geom;
121   
122}
123
124osg:: Node* createTextBelow(const osg::BoundingBox& bb)
125{
126    osg::Geode* geode = new osg::Geode();
127
128    std::string font("fonts/arial.ttf");
129
130    osgText::Text* text = new  osgText::Text;
131
132    text->setFont(font);
133    text->setFontResolution(64,64);
134    text->setAlignment(osgText::Text::CENTER_CENTER);
135    text->setAxisAlignment(osgText::Text::XZ_PLANE);
136    text->setPosition(bb.center()-osg::Vec3(0.0f,0.0f,(bb.zMax()-bb.zMin())));
137    text->setColor(osg::Vec4(0.37f,0.48f,0.67f,1.0f));
138    text->setText("OpenSceneGraph");
139
140    geode->addDrawable( text );
141
142    return geode;
143}
144
145osg:: Node* createTextLeft(const osg::BoundingBox& bb)
146{
147    osg::Geode* geode = new osg::Geode();
148
149
150    osg::StateSet* stateset = geode->getOrCreateStateSet();
151    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
152
153
154    //std::string font("fonts/times.ttf");
155    std::string font("fonts/arial.ttf");
156
157    osgText::Text* text = new  osgText::Text;
158 
159    text->setFont(font);
160    text->setFontResolution(110,120);
161    text->setAlignment(osgText::Text::RIGHT_CENTER);
162    text->setAxisAlignment(osgText::Text::XZ_PLANE);
163    text->setCharacterSize((bb.zMax()-bb.zMin())*1.0f);
164    text->setPosition(bb.center()-osg::Vec3((bb.xMax()-bb.xMin()),-(bb.yMax()-bb.yMin())*0.5f,(bb.zMax()-bb.zMin())*0.1f));
165    //text->setColor(osg::Vec4(0.37f,0.48f,0.67f,1.0f)); // Neil's orignal OSG colour
166    text->setColor(osg::Vec4(0.20f,0.45f,0.60f,1.0f)); // OGL logo colour
167    text->setText("OpenSceneGraph");
168
169    geode->addDrawable( text );
170
171
172    if (s_ProfessionalServices)
173    {
174        //osgText::Text* subscript = new  osgText::Text(new osgText::TextureFont(font,45));
175
176        osgText::Text* subscript = new osgText::Text;
177        subscript->setFont(font);
178        subscript->setText("Professional Services");
179        subscript->setAlignment(osgText::Text::RIGHT_CENTER);
180        subscript->setAxisAlignment(osgText::Text::XZ_PLANE);
181        subscript->setPosition(bb.center()-osg::Vec3((bb.xMax()-bb.xMin())*4.3f,-(bb.yMax()-bb.yMin())*0.5f,(bb.zMax()-bb.zMin())*0.6f));
182        subscript->setColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); // black
183
184        geode->addDrawable( subscript );
185    }
186       
187    return geode;
188}
189
190osg:: Node* createGlobe(const osg::BoundingBox& bb,float ratio)
191{
192    osg::Geode* geode = new osg::Geode();
193
194    osg::StateSet* stateset = geode->getOrCreateStateSet();
195
196    osg::Image* image = osgDB::readImageFile("Images/land_shallow_topo_2048.jpg");
197    if (image)
198    {
199        osg::Texture2D* texture = new osg::Texture2D;
200        texture->setImage(image);
201        texture->setMaxAnisotropy(8);
202        stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
203    }
204   
205    osg::Material* material = new osg::Material;
206    stateset->setAttribute(material);   
207   
208   
209    // the globe
210    geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(bb.center(),bb.radius()*ratio)));
211   
212   
213    osg::MatrixTransform* xform = new osg::MatrixTransform;
214    xform->setUpdateCallback(new osgUtil::TransformCallback(bb.center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(30.0f)));
215    xform->addChild(geode);
216       
217    return xform;
218}
219
220osg:: Node* createBox(const osg::BoundingBox& bb,float chordRatio)
221{
222    osg::Geode* geode = new osg::Geode();
223
224    osg::Vec4 white(1.0f,1.0f,1.0f,1.0f);
225
226    // front faces.
227    geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,white));
228    geode->addDrawable(createWing(bb.corner(7),bb.corner(5),bb.corner(4),chordRatio,white));
229
230    geode->addDrawable(createWing(bb.corner(4),bb.corner(5),bb.corner(1),chordRatio,white));
231    geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,white));
232   
233    geode->addDrawable(createWing(bb.corner(1),bb.corner(5),bb.corner(7),chordRatio,white));
234    geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,white));
235
236    // back faces
237    geode->addDrawable(createWing(bb.corner(2),bb.corner(0),bb.corner(1),chordRatio,white));
238    geode->addDrawable(createWing(bb.corner(1),bb.corner(3),bb.corner(2),chordRatio,white));
239
240    geode->addDrawable(createWing(bb.corner(2),bb.corner(3),bb.corner(7),chordRatio,white));
241    geode->addDrawable(createWing(bb.corner(7),bb.corner(6),bb.corner(2),chordRatio,white));
242
243    geode->addDrawable(createWing(bb.corner(2),bb.corner(6),bb.corner(4),chordRatio,white));
244    geode->addDrawable(createWing(bb.corner(4),bb.corner(0),bb.corner(2),chordRatio,white));
245
246    return geode;
247}
248
249osg:: Node* createBoxNo5(const osg::BoundingBox& bb,float chordRatio)
250{
251    osg::Geode* geode = new osg::Geode();
252
253    osg::Vec4 white(1.0f,1.0f,1.0f,1.0f);
254
255    // front faces.
256    geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,white));
257
258    geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,white));
259   
260    geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,white));
261
262    // back faces
263    geode->addDrawable(createWing(bb.corner(2),bb.corner(0),bb.corner(1),chordRatio,white));
264    geode->addDrawable(createWing(bb.corner(1),bb.corner(3),bb.corner(2),chordRatio,white));
265
266    geode->addDrawable(createWing(bb.corner(2),bb.corner(3),bb.corner(7),chordRatio,white));
267    geode->addDrawable(createWing(bb.corner(7),bb.corner(6),bb.corner(2),chordRatio,white));
268
269    geode->addDrawable(createWing(bb.corner(2),bb.corner(6),bb.corner(4),chordRatio,white));
270    geode->addDrawable(createWing(bb.corner(4),bb.corner(0),bb.corner(2),chordRatio,white));
271
272    return geode;
273}
274
275osg:: Node* createBoxNo5No2(const osg::BoundingBox& bb,float chordRatio)
276{
277    osg::Geode* geode = new osg::Geode();
278
279//    osg::Vec4 red(1.0f,0.0f,0.0f,1.0f);
280//    osg::Vec4 green(0.0f,1.0f,0.0f,1.0f);
281//    osg::Vec4 blue(0.0f,0.0f,1.0f,1.0f);
282
283    osg::Vec4 red(1.0f,0.12f,0.06f,1.0f);
284    osg::Vec4 green(0.21f,0.48f,0.03f,1.0f);
285    osg::Vec4 blue(0.20f,0.45f,0.60f,1.0f);
286
287    // front faces.
288    geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,red));
289
290    geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,green));
291   
292    geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,blue));
293
294    return geode;
295}
296
297osg:: Node* createBackdrop(const osg::Vec3& corner,const osg::Vec3& top,const osg::Vec3& right)
298{
299
300
301
302    osg::Geometry* geom = new osg::Geometry;
303
304    osg::Vec3 normal = (corner-top)^(right-corner);
305    normal.normalize();
306
307    osg::Vec3Array* vertices = new osg::Vec3Array;
308    vertices->push_back(top);
309    vertices->push_back(corner);
310
311    vertices->push_back(right);
312    vertices->push_back(right+(top-corner));
313
314    geom->setVertexArray(vertices);
315
316    osg::Vec3Array* normals = new osg::Vec3Array;
317    normals->push_back(normal);
318    geom->setNormalArray(normals);
319    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
320
321    osg::Vec4Array* colors = new osg::Vec4Array;
322    colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
323    geom->setColorArray(colors);
324    geom->setColorBinding(osg::Geometry::BIND_OVERALL);
325
326    geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,vertices->getNumElements()));
327
328    osg::Geode* geode = new osg::Geode();
329    geode->addDrawable(geom);
330   
331    return geode;   
332}
333
334osg::Node* createLogo()
335{
336    osg::BoundingBox bb(osg::Vec3(0.0f,0.0f,0.0f),osg::Vec3(100.0f,100.0f,100.0f));
337    float chordRatio = 0.5f;
338    float sphereRatio = 0.6f;
339
340    // create a group to hold the whole model.
341    osg::Group* logo_group = new osg::Group;
342
343    osg::Quat r1,r2;
344    r1.makeRotate(-osg::inDegrees(45.0f),0.0f,0.0f,1.0f);
345    r2.makeRotate(osg::inDegrees(45.0f),1.0f,0.0f,0.0f);
346
347
348    MyBillboardTransform* xform = new MyBillboardTransform;
349    xform->setPivotPoint(bb.center());
350    xform->setPosition(bb.center());
351    xform->setAttitude(r1*r2);
352
353
354//     // create a transform to orientate the box and globe.
355//     osg::MatrixTransform* xform = new osg::MatrixTransform;
356//     xform->setDataVariance(osg::Object::STATIC);
357//     xform->setMatrix(osg::Matrix::translate(-bb.center())*
358//                      osg::Matrix::rotate(-osg::inDegrees(45.0f),0.0f,0.0f,1.0f)*
359//                      osg::Matrix::rotate(osg::inDegrees(45.0f),1.0f,0.0f,0.0f)*
360//                      osg::Matrix::translate(bb.center()));
361
362    // add the box and globe to it.
363    //xform->addChild(createBox(bb,chordRatio));
364    //xform->addChild(createBoxNo5(bb,chordRatio));
365    xform->addChild(createBoxNo5No2(bb,chordRatio));
366    // add the transform to the group.
367    logo_group->addChild(xform);
368
369    logo_group->addChild(createGlobe(bb,sphereRatio));
370
371    // add the text to the group.
372    //group->addChild(createTextBelow(bb));
373    logo_group->addChild(createTextLeft(bb));
374   
375   
376    // create the backdrop to render the shadow to.
377    osg::Vec3 corner(-900.0f,150.0f,-100.0f);
378    osg::Vec3 top(0.0f,0.0f,300.0f); top += corner;
379    osg::Vec3 right(1100.0f,0.0f,0.0f); right += corner;
380   
381   
382//     osg::Group* backdrop = new osg::Group;
383//     backdrop->addChild(createBackdrop(corner,top,right));
384
385    osg::ClearNode* backdrop = new osg::ClearNode;
386    backdrop->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
387
388    //osg::Vec3 lightPosition(-500.0f,-2500.0f,500.0f);
389    //osg::Node* scene = createShadowedScene(logo_group,backdrop,lightPosition,0.0f,0);
390
391    osg::Group* scene = new osg::Group;
392
393    osg::StateSet* stateset = scene->getOrCreateStateSet();
394    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
395
396
397    scene->addChild(logo_group);
398    scene->addChild(backdrop);
399
400    return scene;
401}
402
403int main( int argc, char **argv )
404{
405
406    // use an ArgumentParser object to manage the program arguments.
407    osg::ArgumentParser arguments(&argc,argv);
408
409    // set up the usage document, in case we need to print out how to use this program.
410    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates both text, animation and billboard via custom transform to create the OpenSceneGraph logo..");
411    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
412    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
413    arguments.getApplicationUsage()->addCommandLineOption("ps","Render the Professional Services logo");
414   
415    // construct the viewer.
416    osgProducer::Viewer viewer(arguments);
417
418    // set up the value with sensible default event handlers.
419    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
420
421    // get details on keyboard and mouse bindings used by the viewer.
422    viewer.getUsage(*arguments.getApplicationUsage());
423
424    // if user request help write it out to cout.
425    if (arguments.read("-h") || arguments.read("--help"))
426    {
427        arguments.getApplicationUsage()->write(std::cout);
428        return 1;
429    }
430   
431    while (arguments.read("ps")) s_ProfessionalServices = true;
432
433        // any option left unread are converted into errors to write out later.
434    arguments.reportRemainingOptionsAsUnrecognized();
435
436    // report any errors if they have occured when parsing the program aguments.
437    if (arguments.errors())
438    {
439        arguments.writeErrorMessages(std::cout);
440        return 1;
441    }
442   
443    osg::Node* node = createLogo();
444
445    // add model to viewer.
446    viewer.setSceneData( node );
447
448    // create the windows and run the threads.
449    viewer.realize();
450
451    while( !viewer.done() )
452    {
453        // wait for all cull and draw threads to complete.
454        viewer.sync();
455
456        // update the scene by traversing it with the the update visitor which will
457        // call all node update callbacks and animations.
458        viewer.update();
459         
460        // fire off the cull and draw traversals of the scene.
461        viewer.frame();
462       
463    }
464   
465    // wait for all cull and draw threads to complete before exit.
466    viewer.sync();
467
468    return 0;
469}
Note: See TracBrowser for help on using the browser.