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