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

Revision 8868, 16.5 kB (checked in by robert, 6 years ago)

From Mathias Froehlich, "This is a generic optimization that does not depend on any cpu or instruction
set.

The optimization is based on the observation that matrix matrix multiplication
with a dense matrix 4x4 is 43 Operations whereas multiplication with a
transform, or scale matrix is only 4
2 operations. Which is a gain of a
*FACTOR*4* for these special cases.
The change implements these special cases, provides a unit test for these
implementation and converts uses of the expensiver dense matrix matrix
routine with the specialized versions.

Depending on the transform nodes in the scenegraph this change gives a
noticable improovement.
For example the osgforest code using the MatrixTransform? is about 20% slower
than the same codepath using the PositionAttitudeTransform? instead of the
MatrixTransform? with this patch applied.

If I remember right, the sse type optimizations did *not* provide a factor 4
improovement. Also these changes are totally independent of any cpu or
instruction set architecture. So I would prefer to have this current kind of
change instead of some hand coded and cpu dependent assembly stuff. If we
need that hand tuned stuff, these can go on top of this changes which must
provide than hand optimized additional variants for the specialized versions
to give a even better result in the end.

An other change included here is a change to rotation matrix from quaterion
code. There is a sqrt call which couold be optimized away. Since we divide in
effect by sqrt(length)*sqrt(length) which is just length ...
"

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* OpenSceneGraph example, osglogo.
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 <osg/Geode>
20#include <osg/ShapeDrawable>
21#include <osg/Material>
22#include <osg/Texture2D>
23#include <osg/Geometry>
24#include <osg/MatrixTransform>
25#include <osg/PositionAttitudeTransform>
26#include <osg/BlendFunc>
27#include <osg/ClearNode>
28#include <osg/Version>
29
30#include <osgUtil/Tessellator>
31#include <osgUtil/CullVisitor>
32
33#include <osgText/Text>
34
35#include <osgGA/TrackballManipulator>
36
37#include <osgViewer/Viewer>
38
39#include <osgDB/ReadFile>
40
41#include <iostream>
42
43class MyBillboardTransform : public osg::PositionAttitudeTransform
44{
45    public:
46   
47        MyBillboardTransform():
48            _axis(0.0f,0.0f,1.0f),
49            _normal(0.0f,-1.0f,0.0f)
50        {
51        }
52       
53        bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const
54        {
55            osg::Quat billboardRotation;
56            osgUtil::CullVisitor* cullvisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
57            if (cullvisitor)
58            {
59                osg::Vec3 eyevector = cullvisitor->getEyeLocal()-_position;
60                eyevector.normalize();
61
62                osg::Vec3 side = _axis^_normal;
63                side.normalize();
64
65                float angle = atan2(eyevector*_normal,eyevector*side);
66                billboardRotation.makeRotate(osg::PI_2-angle,_axis);
67
68            }
69
70            matrix.preMultTranslate(_position);
71            matrix.preMultRotate(billboardRotation);
72            matrix.preMultRotate(_attitude);
73            matrix.preMultTranslate(_pivotPoint);
74            return true;
75        }
76
77
78       
79        void setAxis(const osg::Vec3& axis) { _axis = axis; }
80
81        void setNormal(const osg::Vec3& normal) { _normal = normal; }
82       
83    protected:
84   
85        virtual ~MyBillboardTransform() {}
86       
87        osg::Vec3 _axis;
88        osg::Vec3 _normal;
89};
90
91
92osg::Geometry* createWing(const osg::Vec3& left, const osg::Vec3& nose, const osg::Vec3& right,float chordRatio,const osg::Vec4& color)
93{
94    osg::Geometry* geom = new osg::Geometry;
95
96    osg::Vec3 normal = (nose-right)^(left-nose);
97    normal.normalize();
98
99    osg::Vec3 left_to_right = right-left;
100    osg::Vec3 mid = (right+left)*0.5f;
101    osg::Vec3 mid_to_nose = (nose-mid)*chordRatio*0.5f;
102   
103    osg::Vec3Array* vertices = new osg::Vec3Array;
104    vertices->push_back(left);
105    //vertices->push_back(mid+mid_to_nose);
106   
107    unsigned int noSteps = 40;
108    for(unsigned int i=1;i<noSteps;++i)
109    {
110        float ratio = (float)i/(float)noSteps;
111        vertices->push_back(left + left_to_right*ratio + mid_to_nose* (cosf((ratio-0.5f)*osg::PI*2.0f)+1.0f));
112    }
113   
114    vertices->push_back(right);
115    vertices->push_back(nose);
116
117    geom->setVertexArray(vertices);
118
119
120    osg::Vec3Array* normals = new osg::Vec3Array;
121    normals->push_back(normal);
122    geom->setNormalArray(normals);
123    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
124   
125   
126    osg::Vec4Array* colors = new osg::Vec4Array;
127    colors->push_back(color);
128    geom->setColorArray(colors);
129    geom->setColorBinding(osg::Geometry::BIND_OVERALL);
130   
131
132    geom->addPrimitiveSet(new osg::DrawArrays(GL_POLYGON,0,vertices->getNumElements()));
133   
134    osgUtil::Tessellator tessellator;
135    tessellator.retessellatePolygons(*geom);
136
137    return geom;
138   
139}
140
141osg:: Node* createTextBelow(const osg::BoundingBox& bb, const std::string& label, const std::string&)
142{
143    osg::Geode* geode = new osg::Geode();
144
145    std::string font("fonts/arial.ttf");
146
147    osgText::Text* text = new  osgText::Text;
148
149    text->setFont(font);
150    text->setFontResolution(64,64);
151    text->setAlignment(osgText::Text::CENTER_CENTER);
152    text->setAxisAlignment(osgText::Text::XZ_PLANE);
153    text->setPosition(bb.center()-osg::Vec3(0.0f,0.0f,(bb.zMax()-bb.zMin())));
154    text->setColor(osg::Vec4(0.37f,0.48f,0.67f,1.0f));
155    text->setText(label);
156
157    geode->addDrawable( text );
158
159    return geode;
160}
161
162osg:: Node* createTextLeft(const osg::BoundingBox& bb, const std::string& label, const std::string& subscript)
163{
164    osg::Geode* geode = new osg::Geode();
165
166
167    osg::StateSet* stateset = geode->getOrCreateStateSet();
168    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
169
170
171    //std::string font("fonts/times.ttf");
172    std::string font("fonts/arial.ttf");
173
174    osgText::Text* text = new  osgText::Text;
175 
176    text->setFont(font);
177    text->setFontResolution(110,120);
178    text->setAlignment(osgText::Text::RIGHT_CENTER);
179    text->setAxisAlignment(osgText::Text::XZ_PLANE);
180    text->setCharacterSize((bb.zMax()-bb.zMin())*1.0f);
181    text->setPosition(bb.center()-osg::Vec3((bb.xMax()-bb.xMin()),-(bb.yMax()-bb.yMin())*0.5f,(bb.zMax()-bb.zMin())*0.1f));
182    //text->setColor(osg::Vec4(0.37f,0.48f,0.67f,1.0f)); // Neil's original OSG colour
183    text->setColor(osg::Vec4(0.20f,0.45f,0.60f,1.0f)); // OGL logo colour
184    text->setText(label);
185
186#if 1
187    text->setBackdropType(osgText::Text::OUTLINE);
188//   text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT);
189
190    text->setBackdropImplementation(osgText::Text::POLYGON_OFFSET);
191//    text->setBackdropImplementation(osgText::Text::NO_DEPTH_BUFFER);
192//    text->setBackdropImplementation(osgText::Text::DEPTH_RANGE);
193//    text->setBackdropImplementation(osgText::Text::STENCIL_BUFFER);
194   
195    text->setBackdropOffset(0.05f);
196    text->setBackdropColor(osg::Vec4(0.0f, 0.0f, 0.5f, 1.0f));
197#endif
198
199
200#if 1
201    text->setColorGradientMode(osgText::Text::OVERALL);
202    osg::Vec4 lightblue(0.30f,0.6f,0.90f,1.0f);
203    osg::Vec4 blue(0.10f,0.30f,0.40f,1.0f);
204    text->setColorGradientCorners(lightblue, blue, blue, lightblue);
205#else
206    text->setColorGradientMode(osgText::Text::OVERALL);
207    osg::Vec4 light = osg::Vec4(0.0f, 1.0f, 1.0f, 1.0f);
208    osg::Vec4 dark = osg::Vec4(0.0f, 0.0f, 0.5f, 1.0f);
209    text->setColorGradientCorners(light, dark, dark, light);
210//    text->setColorGradientCorners(dark, light, light, dark);
211#endif
212
213    geode->addDrawable( text );
214
215
216    if (!subscript.empty())
217    {
218        //osgText::Text* subscript = new  osgText::Text(new osgText::TextureFont(font,45));
219
220        osgText::Text* subscriptText = new osgText::Text;
221        subscriptText->setFont(font);
222        subscriptText->setText(subscript);
223        subscriptText->setAlignment(osgText::Text::RIGHT_CENTER);
224        subscriptText->setAxisAlignment(osgText::Text::XZ_PLANE);
225        subscriptText->setPosition(bb.center()-osg::Vec3((bb.xMax()-bb.xMin())*4.3f,-(bb.yMax()-bb.yMin())*0.5f,(bb.zMax()-bb.zMin())*0.6f));
226        subscriptText->setColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); // black
227
228        geode->addDrawable( subscriptText );
229    }
230       
231    return geode;
232}
233
234osg:: Node* createGlobe(const osg::BoundingBox& bb,float ratio, const std::string& filename)
235{
236    osg::MatrixTransform* xform = new osg::MatrixTransform;
237    xform->setUpdateCallback(new osg::AnimationPathCallback(bb.center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(10.0f)));
238
239    osg::Node* bluemarble = filename.empty() ? 0 : osgDB::readNodeFile(filename.c_str());
240    if (bluemarble)
241    {
242        const osg::BoundingSphere& bs = bluemarble->getBound();
243        float s = 1.2*bb.radius()/bs.radius();
244        osg::MatrixTransform* positioner = new osg::MatrixTransform;
245        positioner->setMatrix(osg::Matrix::translate(-bs.center())*osg::Matrix::scale(s,s,s)*osg::Matrix::translate(bb.center()));
246        positioner->addChild(bluemarble);
247   
248        xform->addChild(positioner);
249    }
250    else
251    {
252
253        osg::Geode* geode = new osg::Geode();
254
255        osg::StateSet* stateset = geode->getOrCreateStateSet();
256
257        osg::Image* image = osgDB::readImageFile("Images/land_shallow_topo_2048.jpg");
258        if (image)
259        {
260            osg::Texture2D* texture = new osg::Texture2D;
261            texture->setImage(image);
262            texture->setMaxAnisotropy(8);
263            stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
264        }
265
266        osg::Material* material = new osg::Material;
267        stateset->setAttribute(material);   
268
269        // the globe
270        geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(bb.center(),bb.radius()*ratio)));
271
272        xform->addChild(geode);
273    }
274           
275    return xform;
276}
277
278osg:: Node* createBox(const osg::BoundingBox& bb,float chordRatio)
279{
280    osg::Geode* geode = new osg::Geode();
281
282    osg::Vec4 white(1.0f,1.0f,1.0f,1.0f);
283
284    // front faces.
285    geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,white));
286    geode->addDrawable(createWing(bb.corner(7),bb.corner(5),bb.corner(4),chordRatio,white));
287
288    geode->addDrawable(createWing(bb.corner(4),bb.corner(5),bb.corner(1),chordRatio,white));
289    geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,white));
290   
291    geode->addDrawable(createWing(bb.corner(1),bb.corner(5),bb.corner(7),chordRatio,white));
292    geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,white));
293
294    // back faces
295    geode->addDrawable(createWing(bb.corner(2),bb.corner(0),bb.corner(1),chordRatio,white));
296    geode->addDrawable(createWing(bb.corner(1),bb.corner(3),bb.corner(2),chordRatio,white));
297
298    geode->addDrawable(createWing(bb.corner(2),bb.corner(3),bb.corner(7),chordRatio,white));
299    geode->addDrawable(createWing(bb.corner(7),bb.corner(6),bb.corner(2),chordRatio,white));
300
301    geode->addDrawable(createWing(bb.corner(2),bb.corner(6),bb.corner(4),chordRatio,white));
302    geode->addDrawable(createWing(bb.corner(4),bb.corner(0),bb.corner(2),chordRatio,white));
303
304    return geode;
305}
306
307osg:: Node* createBoxNo5(const osg::BoundingBox& bb,float chordRatio)
308{
309    osg::Geode* geode = new osg::Geode();
310
311    osg::Vec4 white(1.0f,1.0f,1.0f,1.0f);
312
313    // front faces.
314    geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,white));
315
316    geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,white));
317   
318    geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,white));
319
320    // back faces
321    geode->addDrawable(createWing(bb.corner(2),bb.corner(0),bb.corner(1),chordRatio,white));
322    geode->addDrawable(createWing(bb.corner(1),bb.corner(3),bb.corner(2),chordRatio,white));
323
324    geode->addDrawable(createWing(bb.corner(2),bb.corner(3),bb.corner(7),chordRatio,white));
325    geode->addDrawable(createWing(bb.corner(7),bb.corner(6),bb.corner(2),chordRatio,white));
326
327    geode->addDrawable(createWing(bb.corner(2),bb.corner(6),bb.corner(4),chordRatio,white));
328    geode->addDrawable(createWing(bb.corner(4),bb.corner(0),bb.corner(2),chordRatio,white));
329
330    return geode;
331}
332
333osg:: Node* createBoxNo5No2(const osg::BoundingBox& bb,float chordRatio)
334{
335    osg::Geode* geode = new osg::Geode();
336
337//    osg::Vec4 red(1.0f,0.0f,0.0f,1.0f);
338//    osg::Vec4 green(0.0f,1.0f,0.0f,1.0f);
339//    osg::Vec4 blue(0.0f,0.0f,1.0f,1.0f);
340
341    osg::Vec4 red(1.0f,0.12f,0.06f,1.0f);
342    osg::Vec4 green(0.21f,0.48f,0.03f,1.0f);
343    osg::Vec4 blue(0.20f,0.45f,0.60f,1.0f);
344
345    // front faces.
346    geode->addDrawable(createWing(bb.corner(4),bb.corner(6),bb.corner(7),chordRatio,red));
347
348    geode->addDrawable(createWing(bb.corner(1),bb.corner(0),bb.corner(4),chordRatio,green));
349   
350    geode->addDrawable(createWing(bb.corner(7),bb.corner(3),bb.corner(1),chordRatio,blue));
351
352    return geode;
353}
354
355osg:: Node* createBackdrop(const osg::Vec3& corner,const osg::Vec3& top,const osg::Vec3& right)
356{
357
358
359
360    osg::Geometry* geom = new osg::Geometry;
361
362    osg::Vec3 normal = (corner-top)^(right-corner);
363    normal.normalize();
364
365    osg::Vec3Array* vertices = new osg::Vec3Array;
366    vertices->push_back(top);
367    vertices->push_back(corner);
368
369    vertices->push_back(right);
370    vertices->push_back(right+(top-corner));
371
372    geom->setVertexArray(vertices);
373
374    osg::Vec3Array* normals = new osg::Vec3Array;
375    normals->push_back(normal);
376    geom->setNormalArray(normals);
377    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
378
379    osg::Vec4Array* colors = new osg::Vec4Array;
380    colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
381    geom->setColorArray(colors);
382    geom->setColorBinding(osg::Geometry::BIND_OVERALL);
383
384    geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,vertices->getNumElements()));
385
386    osg::Geode* geode = new osg::Geode();
387    geode->addDrawable(geom);
388   
389    return geode;   
390}
391
392osg::Node* createLogo(const std::string& filename, const std::string& label, const std::string& subscript)
393{
394    osg::BoundingBox bb(osg::Vec3(0.0f,0.0f,0.0f),osg::Vec3(100.0f,100.0f,100.0f));
395    float chordRatio = 0.5f;
396    float sphereRatio = 0.6f;
397
398    // create a group to hold the whole model.
399    osg::Group* logo_group = new osg::Group;
400
401    osg::Quat r1,r2;
402    r1.makeRotate(-osg::inDegrees(45.0f),0.0f,0.0f,1.0f);
403    r2.makeRotate(osg::inDegrees(45.0f),1.0f,0.0f,0.0f);
404
405
406    MyBillboardTransform* xform = new MyBillboardTransform;
407    xform->setPivotPoint(bb.center());
408    xform->setPosition(bb.center());
409    xform->setAttitude(r1*r2);
410
411
412//     // create a transform to orientate the box and globe.
413//     osg::MatrixTransform* xform = new osg::MatrixTransform;
414//     xform->setDataVariance(osg::Object::STATIC);
415//     xform->setMatrix(osg::Matrix::translate(-bb.center())*
416//                      osg::Matrix::rotate(-osg::inDegrees(45.0f),0.0f,0.0f,1.0f)*
417//                      osg::Matrix::rotate(osg::inDegrees(45.0f),1.0f,0.0f,0.0f)*
418//                      osg::Matrix::translate(bb.center()));
419
420    // add the box and globe to it.
421    //xform->addChild(createBox(bb,chordRatio));
422    //xform->addChild(createBoxNo5(bb,chordRatio));
423    xform->addChild(createBoxNo5No2(bb,chordRatio));
424    // add the transform to the group.
425    logo_group->addChild(xform);
426
427    logo_group->addChild(createGlobe(bb,sphereRatio,filename));
428
429    // add the text to the group.
430    //group->addChild(createTextBelow(bb));
431    logo_group->addChild(createTextLeft(bb, label, subscript));
432   
433   
434    // create the backdrop to render the shadow to.
435    osg::Vec3 corner(-900.0f,150.0f,-100.0f);
436    osg::Vec3 top(0.0f,0.0f,300.0f); top += corner;
437    osg::Vec3 right(1100.0f,0.0f,0.0f); right += corner;
438   
439   
440//     osg::Group* backdrop = new osg::Group;
441//     backdrop->addChild(createBackdrop(corner,top,right));
442
443    osg::ClearNode* backdrop = new osg::ClearNode;
444    backdrop->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,0.0f));
445
446    //osg::Vec3 lightPosition(-500.0f,-2500.0f,500.0f);
447    //osg::Node* scene = createShadowedScene(logo_group,backdrop,lightPosition,0.0f,0);
448
449    osg::Group* scene = new osg::Group;
450
451    osg::StateSet* stateset = scene->getOrCreateStateSet();
452    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
453
454
455    scene->addChild(logo_group);
456    scene->addChild(backdrop);
457
458    return scene;
459}
460
461int main( int argc, char **argv )
462{
463    // use an ArgumentParser object to manage the program arguments.
464    osg::ArgumentParser arguments(&argc,argv);
465   
466    osg::DisplaySettings::instance()->setMinimumNumAlphaBits(8);
467   
468    // construct the viewer.
469    osgViewer::Viewer viewer;
470
471    // if user request help write it out to cout.
472    if (arguments.read("-h") || arguments.read("--help"))
473    {
474        arguments.getApplicationUsage()->write(std::cout);
475        return 1;
476    }
477   
478    std::string label = "OpenSceneGraph";
479    std::string subscript = "";
480
481    bool showVersion = false;
482    while (arguments.read("--version")) { showVersion = true; }
483    if( showVersion )
484    {
485        label += " ";
486        label += osgGetVersion();
487    }
488
489    while (arguments.read("--label", label)) {}
490    while (arguments.read("--subscript", subscript)) {}
491   
492    osg::ref_ptr<osg::Node> node;
493   
494    if (arguments.argc()>1) node = createLogo(arguments[1], label, subscript);
495    else node = createLogo("", label, subscript);
496
497    // add model to viewer.
498    viewer.setSceneData( node.get() );
499
500    return viewer.run();
501}
Note: See TracBrowser for help on using the browser.