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

Revision 12912, 11.1 kB (checked in by robert, 2 years ago)

Added support for using GL_UNPACK_ROW_LENGTH in conjunction with texture's + osg::Image via new RowLength?
parameter in osg::Image. To support this Image::setData(..) now has a new optional rowLength parameter which
defaults to 0, which provides the original behaviour, Image::setRowLength(int) and int Image::getRowLength() are also provided.

With the introduction of RowLength? support in osg::Image it is now possible to create a sub image where
the t size of the image are smaller than the row length, useful for when you have a large image on the CPU
and which to use a small portion of it on the GPU. However, when these sub images are created the data
within the image is no longer contiguous so data access can no longer assume that all the data is in
one block. The new method Image::isDataContiguous() enables the user to check whether the data is contiguous,
and if not one can either access the data row by row using Image::data(column,row,image) accessor, or use the
new Image::DataIterator? for stepping through each block on memory assocatied with the image.

To support the possibility of non contiguous osg::Image usage of image objects has had to be updated to
check DataContiguous? and handle the case or use access via the DataIerator? or by row by row. To achieve
this a relatively large number of files has had to be modified, in particular the texture classes and
image plugins that doing writing.

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