ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* /*options*/) const { std::string ext( osgDB::getLowerCaseFileExtension(fileName) ); if( !acceptsExtension(ext) ) return ReadResult::FILE_NOT_HANDLED; osg::notify(osg::INFO) << "ReaderWriterGLOBE( \"" << fileName << "\" )" << std::endl; // strip the ".globe" pseudo-loader extension std::string tmpName( osgDB::getNameLessExtension(fileName) ); // get the next "extension", which actually contains the globe radius parameter std::string params( osgDB::getFileExtension(tmpName) ); if( params.empty() ) { osg::notify(osg::WARN) << "Missing parameters for " EXTENSION_NAME " pseudo-loader" << std::endl; return ReadResult::FILE_NOT_HANDLED; } // strip the "params extension", which must leave an image subfilename. std::string subFileName( osgDB::getNameLessExtension(tmpName) ); if( subFileName.empty() || subFileName == tmpName ) { osg::notify(osg::WARN) << "Missing image subfilename for " EXTENSION_NAME " pseudo-loader" << std::endl; return ReadResult::FILE_NOT_HANDLED; } osg::notify(osg::INFO) << EXTENSION_NAME " params = \"" << params << "\"" << std::endl; int radius; int count( sscanf( params.c_str(), "%d", &radius ) ); if( count != 1 ) { osg::notify(osg::WARN) << "Bad parameters for " EXTENSION_NAME " pseudo-loader: \"" << params << "\"" << std::endl; return ReadResult::FILE_NOT_HANDLED; } // recursively load the image subfile. osg::Image *image( osgDB::readImageFile(subFileName) ); if( !image ) { // propagate the read failure upwards osg::notify(osg::WARN) << "Image file \"" << subFileName << "\" could not be loaded" << std::endl; return ReadResult::FILE_NOT_HANDLED; } // create an osg::Sphere for the globe geometry osg::Geode* geode( new osg::Geode() ); geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0,0,0), radius))); // apply the image as a texture to the globe osg::Texture2D* tex2d( new osg::Texture2D ); tex2d->setImage( image ); tex2d->setWrap( osg::Texture::WRAP_S, osg::Texture::REPEAT ); tex2d->setWrap( osg::Texture::WRAP_T, osg::Texture::REPEAT ); osg::StateSet* stateset( geode->getOrCreateStateSet() ); stateset->setTextureAttributeAndModes( 0, tex2d, osg::StateAttribute::ON ); return geode; }
osg::ref_ptr<osg::Texture> TextureManager::getTexture(size_t idx, int16_t *xoffset, int16_t *yoffset, float *xscale, float *yscale) { auto iter = mTexCache.find(idx); if(iter != mTexCache.end()) { osg::ref_ptr<osg::Texture> tex; if(iter->second.mTexture.lock(tex)) { *xoffset = iter->second.mXOffset; *yoffset = iter->second.mYOffset; *xscale = iter->second.mXScale; *yscale = iter->second.mYScale; return tex; } } int16_t x_offset, y_offset, x_scale, y_scale; std::vector<osg::ref_ptr<osg::Image>> images = DFOSG::TexLoader::get().load( idx, &x_offset, &y_offset, &x_scale, &y_scale, mCurrentPalette ); *xoffset = x_offset; *yoffset = y_offset; *xscale = 1.0f + x_scale/256.0f; *yscale = 1.0f + y_scale/256.0f; if(images.empty()) return osg::ref_ptr<osg::Texture>(); osg::ref_ptr<osg::Texture> tex; if(images.size() == 1) { osg::ref_ptr<osg::Texture2D> tex2d(new osg::Texture2D(images[0])); tex2d->setTextureSize(images[0]->s(), images[0]->t()); tex = tex2d; } else { /* Multiframe textures would ideally be loaded as a Texture2DArray and * animated by offseting the R texture coord. However, they don't work * in the fixed-function pipeline. */ #if 0 osg::ref_ptr<osg::Texture2DArray> tex2darr(new osg::Texture2DArray()); tex2darr->setTextureSize(images[0]->s(), images[0]->t(), images.size()); tex2darr->setResizeNonPowerOfTwoHint(false); for(size_t i = 0;i < images.size();++i) tex2darr->setImage(i, images[i]); tex = tex2darr; #else osg::ref_ptr<osg::Texture2D> tex2d(new osg::Texture2D(images[0])); tex2d->setTextureSize(images[0]->s(), images[0]->t()); tex = tex2d; #endif } tex->setResizeNonPowerOfTwoHint(false); tex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); tex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); tex->setUnRefImageDataAfterApply(true); // Filter should be configurable. Defaults to nearest to retain DF's pixely // look (with linear mipmapping to reduce aliasing). tex->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST_MIPMAP_LINEAR); tex->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST); mTexCache[idx] = TextureInfo{ tex, x_offset, y_offset, 1.0f + x_scale/256.0f, 1.0f + y_scale/256.0f }; return tex; }