root/OpenSceneGraph/trunk/src/osgPlugins/logo/ReaderWriterLOGO.cpp @ 9527

Revision 9527, 10.2 kB (checked in by robert, 6 years ago)

Replaced readImageFile() usage with readRefImageFile() to prevent threading issues with caching of imagery in the osgDB::Registry cache.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <stdio.h>
2#include <osg/Geode>
3#include <osg/Drawable>
4#include <osg/BlendFunc>
5#include <osg/StateSet>
6#include <osg/Notify>
7#include <osg/Viewport>
8
9#include <osgDB/ReadFile>
10#include <osgDB/FileUtils>
11#include <osgDB/FileNameUtils>
12#include <osgDB/Registry>
13#include <osgDB/Input>
14#include <osgDB/Output>
15
16#include <osgUtil/CullVisitor>
17
18using namespace osg;
19using namespace osgDB;
20
21
22class Logos: public osg::Drawable
23{
24    public:
25        enum RelativePosition{
26            Center,
27            UpperLeft,
28            UpperRight,
29            LowerLeft,
30            LowerRight,
31            UpperCenter,
32            LowerCenter,
33            last_position
34        };
35
36        struct logosCullCallback : public osg::Drawable::CullCallback
37        {
38            virtual bool cull(osg::NodeVisitor *visitor, osg::Drawable* drawable, osg::State*) const
39            {
40                Logos *logos = dynamic_cast <Logos *>(drawable);
41                osgUtil::CullVisitor *cv = dynamic_cast<osgUtil::CullVisitor *>(visitor);
42                if( logos != NULL && cv != NULL )
43                {
44                    osg::Viewport *vp = cv->getViewport();
45                    if( vp != NULL )
46                    {
47                        if( vp->width() != logos->getViewport()->width() ||
48                            vp->height() != logos->getViewport()->height() )
49                        {
50                            logos->getViewport()->setViewport( vp->x(), vp->y(), vp->width(), vp->height() );
51                            logos->dirtyDisplayList();
52                        }
53                    }
54                }
55                return false;
56            }
57        };
58
59        Logos()
60        {
61            osg::StateSet *sset = new osg::StateSet;
62            osg::BlendFunc *transp = new osg::BlendFunc;
63            transp->setFunction(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
64            sset->setAttribute( transp );
65            sset->setMode( GL_BLEND, osg::StateAttribute::ON );
66            sset->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
67            sset->setTextureMode( 0, GL_TEXTURE_2D, osg::StateAttribute::OFF );
68#if 1           
69            // for now we'll crudely set the bin number to 100 to force it to draw later and ontop of the scene
70            sset->setRenderBinDetails( 100 , "RenderBin" );
71#else
72            sset->setRenderBinDetails( StateSet::TRANSPARENT_BIN + 1 , "RenderBin" );
73#endif
74            setStateSet( sset );
75            viewport = new osg::Viewport;
76            setCullCallback( new logosCullCallback );
77            _contextID = 0;
78        }
79
80        Logos(const Logos& logo, const CopyOp& copyop=CopyOp::SHALLOW_COPY) :Drawable( logo, copyop ) {}
81
82        virtual Object* cloneType() const { return new Logos(); }
83        virtual Object* clone( const CopyOp& copyop) const { return new Logos(*this, copyop ); }
84        virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const Logos*>(obj)!=NULL; }
85        virtual const char* className() const { return "Logos"; }
86
87        virtual void drawImplementation(osg::RenderInfo& renderInfo) const
88        {
89            if( renderInfo.getContextID() != _contextID )
90                return;
91
92
93            float vx = 0.0;
94            float vy = 0.0;
95            float vw = 1.0;
96            float vh = 1.0;
97            if (viewport)
98            {
99                vx = viewport->x();
100                vy = viewport->y();
101                vw = viewport->width();
102                vh = viewport->height();
103            }
104
105            glMatrixMode( GL_PROJECTION );
106            glPushMatrix();
107            glLoadIdentity();
108            glOrtho( 0.0, vw, 0.0, vh, -1.0, 1.0 );
109
110            glMatrixMode( GL_MODELVIEW );
111            glPushMatrix();
112            glLoadIdentity();
113
114            glColor4f( 1, 1, 1, 1 );
115
116            std::vector <osg::Image *>::const_iterator p;
117            float th = 0.0;
118            for( p = logos[Center].begin(); p != logos[Center].end(); p++ )
119                th += (*p)->t();
120
121            float place[][4] = {
122                { vw*0.5, ((vh*0.5) + th*0.5), -0.5, -1.0 },
123                { vx, vh, 0.0, -1.0 },
124                { vw, vh, -1.0, -1.0 },
125                { vx, vy, 0.0, 1.0 },
126                { vw, vy, -1.0, 1.0 },
127                { vw*0.5, vh , -0.5, -1.0 },
128                { vw*0.5, 0.0 , -0.5, 1.0 },
129            };
130
131            for( int i = Center; i < last_position; i++ )
132            {
133                if( logos[i].size() != 0 )
134                {
135                    float x = place[i][0];
136                    float y = place[i][1];
137                    float xi = place[i][2];
138                    float yi = place[i][3];
139                    for( p = logos[i].begin(); p != logos[i].end(); p++ )
140                    {
141                        osg::Image *img = *p;
142                        x = place[i][0] + xi * img->s();
143                        if( i == Center || i == UpperLeft || i == UpperRight || i == UpperCenter)
144                            y += yi * img->t();
145                        glRasterPos2f( x, y );
146                        glDrawPixels( img->s(), img->t(), img->getPixelFormat(), img->getDataType(), img->data() );
147                        if( i == LowerLeft || i == LowerRight || i == LowerCenter)
148                            y += yi * img->t();
149                    }
150                }
151            }
152
153            glPopMatrix();
154            glMatrixMode( GL_PROJECTION );
155            glPopMatrix();
156            glMatrixMode( GL_MODELVIEW );
157        }
158
159        void addLogo( RelativePosition pos, std::string name )
160        {
161            osg::ref_ptr<osg::Image> image = osgDB::readRefImageFile( name.c_str() );
162            if( image.valid())
163                logos[pos].push_back( image.get() );
164            else
165                osg::notify(osg::WARN)<< "Logos::addLogo image file not found : " << name << ".\n";
166        }
167
168        osg::Viewport *getViewport() { return viewport; }
169        void setContextID( unsigned int id ) { _contextID = id; }
170
171        bool hasLogos()
172        {
173            int n = 0;
174            for( int i = Center; i < last_position; i++ )
175                n += logos[i].size();
176            return (n != 0);
177        }
178
179        virtual osg::BoundingBox computeBound() const 
180        {
181            return osg::BoundingBox( -1, -1, -1, 1, 1, 1);
182        }
183
184    protected:
185        Logos& operator = (const Logos&) { return *this;}
186
187        virtual ~Logos() {}
188    private :
189        std::vector <osg::Image *> logos[last_position];
190        osg::Viewport *viewport;
191        unsigned int _contextID;
192};
193
194
195class LOGOReaderWriter : public osgDB::ReaderWriter
196{
197    public:
198        LOGOReaderWriter()
199        {
200            supportsExtension("logo","Ascii logo placement format");
201        }
202       
203        virtual const char* className() const { return "Logo Database Reader/Writer"; }
204
205        virtual ReadResult readNode(const std::string& file, const osgDB::ReaderWriter::Options* options) const
206        {
207            std::string ext = osgDB::getLowerCaseFileExtension(file);
208            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
209
210            std::string fileName = osgDB::findDataFile( file, options );
211            if (fileName.empty())
212                return ReadResult::FILE_NOT_FOUND;
213
214            osg::notify(osg::INFO)<< "ReaderWriterLOGO::readNode( "<<fileName.c_str()<<" )\n";
215
216            std::string filePath = osgDB::getFilePath(fileName);
217            if (!filePath.empty()) {
218                osg::notify(osg::DEBUG_INFO)<< "Adding : " << filePath << " to the file data path\n";
219                osgDB::getDataFilePathList().push_back(filePath);
220            }
221
222
223            osg::Geode *geode = new osg::Geode;
224
225            unsigned int screen = 0;
226
227            Logos* ld = new Logos;
228            ld->setContextID( screen );
229
230            Logos::RelativePosition pos = Logos::LowerRight;
231
232            FILE *fp;
233            if( (fp = osgDB::fopen( fileName.c_str(), "r")) == NULL )
234                return NULL;
235            while( !feof(fp))
236            {
237                char buff[128];
238
239                if( fscanf( fp, "%s", buff ) != 1 )
240                    break;
241
242                std::string str(buff);
243
244                if( str == "Center" )
245                    pos = Logos::Center;
246                else if( str == "UpperLeft" )
247                    pos = Logos::UpperLeft;
248                else if( str == "UpperRight" )
249                    pos = Logos::UpperRight;
250                else if( str == "LowerLeft" )
251                    pos = Logos::LowerLeft;
252                else if( str == "LowerRight" )
253                    pos = Logos::LowerRight;
254                else if( str == "UpperCenter" )
255                    pos = Logos::UpperCenter;
256                else if( str == "LowerCenter" )
257                    pos = Logos::LowerCenter;
258                else if( str == "Camera" )
259                {
260                    int tn;
261                    if( (fscanf( fp, "%d", &tn )) != 1 )
262                    {
263                        osg::notify(osg::WARN) << "Error... Camera requires an integer argument\n";
264                        break;
265                    }
266                   
267                    if (tn < 0)
268                    {
269                        osg::notify(osg::WARN) << "Error... Camera requires an positive or null value argument\n";
270                        break;
271                    }
272                   
273                    unsigned int n = static_cast<unsigned int>(tn);
274                    if( screen != n )
275                    {
276                        screen = n;
277                        if( ld->hasLogos() )
278                        {
279                        geode->addDrawable( ld );
280                        ld = new Logos;
281                        ld->setContextID( screen );
282                    }
283                    else
284                        ld->setContextID( screen );
285                    }
286                }
287                else
288                {
289                    if( str.length() )
290                    ld->addLogo( pos, str );
291                }
292            }
293            fclose( fp );
294       
295            if( ld->hasLogos() )
296                geode->addDrawable( ld );
297       
298            geode->setCullingActive(false);
299            return geode;
300        }
301};
302
303
304// now register with Registry to instantiate the above
305// reader/writer.
306REGISTER_OSGPLUGIN(logo, LOGOReaderWriter)
Note: See TracBrowser for help on using the browser.