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 
18 using namespace osg;
19 using namespace osgDB;
20 
21 
22 class 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         {
cullLogos::logosCullCallback38             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 appropriate 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 
Logos()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 
Logos(const Logos & logo,const CopyOp & copyop=CopyOp::SHALLOW_COPY)89         Logos(const Logos& logo, const CopyOp& copyop=CopyOp::SHALLOW_COPY) :Drawable( logo, copyop ) {}
90 
cloneType() const91         virtual Object* cloneType() const { return new Logos(); }
clone(const CopyOp & copyop) const92         virtual Object* clone( const CopyOp& copyop) const { return new Logos(*this, copyop ); }
isSameKindAs(const Object * obj) const93         virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const Logos*>(obj)!=NULL; }
className() const94         virtual const char* className() const { return "Logos"; }
95 
drawImplementation(osg::RenderInfo & renderInfo) const96         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.0f;
105             float vy = 0.0f;
106             float vw = 1.0f;
107             float vh = 1.0f;
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.0f, 1.0f, 1.0f, 1.0f );
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.5f, ((vh*0.5f) + th*0.5f), -0.5f, -1.0f },
136                 { vx, vh, 0.0f, -1.0f },
137                 { vw, vh, -1.0f, -1.0f },
138                 { vx, vy, 0.0f, 1.0f },
139                 { vw, vy, -1.0f, 1.0f },
140                 { vw*0.5f, vh , -0.5f, -1.0f },
141                 { vw*0.5f, 0.0f , -0.5f, 1.0f },
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 
addLogo(RelativePosition pos,std::string name)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 
getViewport()190         osg::Viewport *getViewport() { return _viewport.get(); }
191 
setContextID(unsigned int id)192         void setContextID( unsigned int id ) { _contextID = id; }
getContextID()193         unsigned int getContextID() { return _contextID; }
194 
hasLogos()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 
computeBoundingBox() const203         virtual osg::BoundingBox computeBoundingBox() const
204         {
205             return osg::BoundingBox( -1, -1, -1, 1, 1, 1);
206         }
207 
208     protected:
operator =(const Logos &)209         Logos& operator = (const Logos&) { return *this;}
210 
~Logos()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 
221 class LOGOReaderWriter : public osgDB::ReaderWriter
222 {
223     public:
LOGOReaderWriter()224         LOGOReaderWriter()
225         {
226             supportsExtension("logo","Ascii logo placement format");
227         }
228 
className() const229         virtual const char* className() const { return "Logo Database Reader/Writer"; }
230 
readNode(const std::string & file,const osgDB::ReaderWriter::Options * options) const231         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.
332 REGISTER_OSGPLUGIN(logo, LOGOReaderWriter)
333