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

Revision 2419, 15.7 kB (checked in by robert, 10 years ago)

Added code to load the bluemarble.ive database instead of the texture mapped
sphere for the earth model in the logo.

  • 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, const std::string& filename)
191{
192    osg::MatrixTransform* xform = new osg::MatrixTransform;
193    xform->setUpdateCallback(new osgUtil::TransformCallback(bb.center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(10.0f)));
194
195    osg::Node* bluemarble = osgDB::readNodeFile(filename.c_str());
196    if (bluemarble)
197    {
198        const osg::BoundingSphere& bs = bluemarble->getBound();
199        float s = 1.2*bb.radius()/bs.radius();
200        osg::MatrixTransform* positioner = new osg::MatrixTransform;
201        positioner->setMatrix(osg::Matrix::translate(-bs.center())*osg::Matrix::scale(s,s,s)*osg::Matrix::translate(bb.center()));
202        positioner->addChild(bluemarble);
203   
204        xform->addChild(positioner);
205    }
206    else
207    {
208
209        osg::Geode* geode = new osg::Geode();
210
211        osg::StateSet* stateset = geode->getOrCreateStateSet();
212
213        osg::Image* image = osgDB::readImageFile("Images/land_shallow_topo_2048.jpg");
214        if (image)
215        {
216            osg::Texture2D* texture = new osg::Texture2D;
217            texture->setImage(image);
218            texture->setMaxAnisotropy(8);
219            stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
220        }
221
222        osg::Material* material = new osg::Material;
223        stateset->setAttribute(material);   
224
225        // the globe
226        geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(bb.center(),bb.radius()*ratio)));
227
228        xform->addChild(geode);
229    }
230           
231    return xform;
232}
233
234osg:: Node* createBox(const osg::BoundingBox& bb,float chordRatio)
235{
236    osg::Geode* geode = new osg::Geode();
237
238    osg::Vec4 white(1.0f,1.0f,1.0f,1.0f);
239
240    // front faces.
241    geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,white));
242    geode->addDrawable(createWing(bb.corner(7),bb.corner(5),bb.corner(4),chordRatio,white));
243
244    geode->addDrawable(createWing(bb.corner(4),bb.corner(5),bb.corner(1),chordRatio,white));
245    geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,white));
246   
247    geode->addDrawable(createWing(bb.corner(1),bb.corner(5),bb.corner(7),chordRatio,white));
248    geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,white));
249
250    // back faces
251    geode->addDrawable(createWing(bb.corner(2),bb.corner(0),bb.corner(1),chordRatio,white));
252    geode->addDrawable(createWing(bb.corner(1),bb.corner(3),bb.corner(2),chordRatio,white));
253
254    geode->addDrawable(createWing(bb.corner(2),bb.corner(3),bb.corner(7),chordRatio,white));
255    geode->addDrawable(createWing(bb.corner(7),bb.corner(6),bb.corner(2),chordRatio,white));
256
257    geode->addDrawable(createWing(bb.corner(2),bb.corner(6),bb.corner(4),chordRatio,white));
258    geode->addDrawable(createWing(bb.corner(4),bb.corner(0),bb.corner(2),chordRatio,white));
259
260    return geode;
261}
262
263osg:: Node* createBoxNo5(const osg::BoundingBox& bb,float chordRatio)
264{
265    osg::Geode* geode = new osg::Geode();
266
267    osg::Vec4 white(1.0f,1.0f,1.0f,1.0f);
268
269    // front faces.
270    geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,white));
271
272    geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,white));
273   
274    geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,white));
275
276    // back faces
277    geode->addDrawable(createWing(bb.corner(2),bb.corner(0),bb.corner(1),chordRatio,white));
278    geode->addDrawable(createWing(bb.corner(1),bb.corner(3),bb.corner(2),chordRatio,white));
279
280    geode->addDrawable(createWing(bb.corner(2),bb.corner(3),bb.corner(7),chordRatio,white));
281    geode->addDrawable(createWing(bb.corner(7),bb.corner(6),bb.corner(2),chordRatio,white));
282
283    geode->addDrawable(createWing(bb.corner(2),bb.corner(6),bb.corner(4),chordRatio,white));
284    geode->addDrawable(createWing(bb.corner(4),bb.corner(0),bb.corner(2),chordRatio,white));
285
286    return geode;
287}
288
289osg:: Node* createBoxNo5No2(const osg::BoundingBox& bb,float chordRatio)
290{
291    osg::Geode* geode = new osg::Geode();
292
293//    osg::Vec4 red(1.0f,0.0f,0.0f,1.0f);
294//    osg::Vec4 green(0.0f,1.0f,0.0f,1.0f);
295//    osg::Vec4 blue(0.0f,0.0f,1.0f,1.0f);
296
297    osg::Vec4 red(1.0f,0.12f,0.06f,1.0f);
298    osg::Vec4 green(0.21f,0.48f,0.03f,1.0f);
299    osg::Vec4 blue(0.20f,0.45f,0.60f,1.0f);
300
301    // front faces.
302    geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,red));
303
304    geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,green));
305   
306    geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,blue));
307
308    return geode;
309}
310
311osg:: Node* createBackdrop(const osg::Vec3& corner,const osg::Vec3& top,const osg::Vec3& right)
312{
313
314
315
316    osg::Geometry* geom = new osg::Geometry;
317
318    osg::Vec3 normal = (corner-top)^(right-corner);
319    normal.normalize();
320
321    osg::Vec3Array* vertices = new osg::Vec3Array;
322    vertices->push_back(top);
323    vertices->push_back(corner);
324
325    vertices->push_back(right);
326    vertices->push_back(right+(top-corner));
327
328    geom->setVertexArray(vertices);
329
330    osg::Vec3Array* normals = new osg::Vec3Array;
331    normals->push_back(normal);
332    geom->setNormalArray(normals);
333    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
334
335    osg::Vec4Array* colors = new osg::Vec4Array;
336    colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
337    geom->setColorArray(colors);
338    geom->setColorBinding(osg::Geometry::BIND_OVERALL);
339
340    geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,vertices->getNumElements()));
341
342    osg::Geode* geode = new osg::Geode();
343    geode->addDrawable(geom);
344   
345    return geode;   
346}
347
348osg::Node* createLogo(const std::string& filename)
349{
350    osg::BoundingBox bb(osg::Vec3(0.0f,0.0f,0.0f),osg::Vec3(100.0f,100.0f,100.0f));
351    float chordRatio = 0.5f;
352    float sphereRatio = 0.6f;
353
354    // create a group to hold the whole model.
355    osg::Group* logo_group = new osg::Group;
356
357    osg::Quat r1,r2;
358    r1.makeRotate(-osg::inDegrees(45.0f),0.0f,0.0f,1.0f);
359    r2.makeRotate(osg::inDegrees(45.0f),1.0f,0.0f,0.0f);
360
361
362    MyBillboardTransform* xform = new MyBillboardTransform;
363    xform->setPivotPoint(bb.center());
364    xform->setPosition(bb.center());
365    xform->setAttitude(r1*r2);
366
367
368//     // create a transform to orientate the box and globe.
369//     osg::MatrixTransform* xform = new osg::MatrixTransform;
370//     xform->setDataVariance(osg::Object::STATIC);
371//     xform->setMatrix(osg::Matrix::translate(-bb.center())*
372//                      osg::Matrix::rotate(-osg::inDegrees(45.0f),0.0f,0.0f,1.0f)*
373//                      osg::Matrix::rotate(osg::inDegrees(45.0f),1.0f,0.0f,0.0f)*
374//                      osg::Matrix::translate(bb.center()));
375
376    // add the box and globe to it.
377    //xform->addChild(createBox(bb,chordRatio));
378    //xform->addChild(createBoxNo5(bb,chordRatio));
379    xform->addChild(createBoxNo5No2(bb,chordRatio));
380    // add the transform to the group.
381    logo_group->addChild(xform);
382
383    logo_group->addChild(createGlobe(bb,sphereRatio,filename));
384
385    // add the text to the group.
386    //group->addChild(createTextBelow(bb));
387    logo_group->addChild(createTextLeft(bb));
388   
389   
390    // create the backdrop to render the shadow to.
391    osg::Vec3 corner(-900.0f,150.0f,-100.0f);
392    osg::Vec3 top(0.0f,0.0f,300.0f); top += corner;
393    osg::Vec3 right(1100.0f,0.0f,0.0f); right += corner;
394   
395   
396//     osg::Group* backdrop = new osg::Group;
397//     backdrop->addChild(createBackdrop(corner,top,right));
398
399    osg::ClearNode* backdrop = new osg::ClearNode;
400    backdrop->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
401
402    //osg::Vec3 lightPosition(-500.0f,-2500.0f,500.0f);
403    //osg::Node* scene = createShadowedScene(logo_group,backdrop,lightPosition,0.0f,0);
404
405    osg::Group* scene = new osg::Group;
406
407    osg::StateSet* stateset = scene->getOrCreateStateSet();
408    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
409
410
411    scene->addChild(logo_group);
412    scene->addChild(backdrop);
413
414    return scene;
415}
416
417int main( int argc, char **argv )
418{
419
420    // use an ArgumentParser object to manage the program arguments.
421    osg::ArgumentParser arguments(&argc,argv);
422
423    // set up the usage document, in case we need to print out how to use this program.
424    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates both text, animation and billboard via custom transform to create the OpenSceneGraph logo..");
425   
426arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+"[options] [filename] ...");
427    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
428    arguments.getApplicationUsage()->addCommandLineOption("ps","Render the Professional Services logo");
429   
430    // construct the viewer.
431    osgProducer::Viewer viewer(arguments);
432
433    // set up the value with sensible default event handlers.
434    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
435
436    // get details on keyboard and mouse bindings used by the viewer.
437    viewer.getUsage(*arguments.getApplicationUsage());
438
439    // if user request help write it out to cout.
440    if (arguments.read("-h") || arguments.read("--help"))
441    {
442        arguments.getApplicationUsage()->write(std::cout);
443        return 1;
444    }
445   
446    while (arguments.read("ps")) s_ProfessionalServices = true;
447
448        // any option left unread are converted into errors to write out later.
449    arguments.reportRemainingOptionsAsUnrecognized();
450
451    // report any errors if they have occured when parsing the program aguments.
452    if (arguments.errors())
453    {
454        arguments.writeErrorMessages(std::cout);
455        return 1;
456    }
457   
458    osg::Node* node = 0;
459   
460    if (arguments.argc()>1) createLogo(arguments[1]);
461    else node = createLogo("bluemarble.ive");
462
463    // add model to viewer.
464    viewer.setSceneData( node );
465
466    // create the windows and run the threads.
467    viewer.realize();
468
469    while( !viewer.done() )
470    {
471        // wait for all cull and draw threads to complete.
472        viewer.sync();
473
474        // update the scene by traversing it with the the update visitor which will
475        // call all node update callbacks and animations.
476        viewer.update();
477         
478        // fire off the cull and draw traversals of the scene.
479        viewer.frame();
480       
481    }
482   
483    // wait for all cull and draw threads to complete before exit.
484    viewer.sync();
485
486    return 0;
487}
Note: See TracBrowser for help on using the browser.