SkinResource* ResourceLibrary::getSkin( const SkinSymbol* symbol, Random& prng, const osgDB::Options* dbOptions ) const { const_cast<ResourceLibrary*>(this)->initialize( dbOptions ); if (symbol->name().isSet()) { return getSkin(symbol->name()->eval(), dbOptions); } SkinResourceVector candidates; getSkins( symbol, candidates ); unsigned size = candidates.size(); if ( size == 0 ) { return 0L; } else if ( size == 1 ) { return candidates[0].get(); } else { return candidates[ prng.next(size) ].get(); } }
void ResourceLibrary::getSkins( SkinResourceVector& output ) const { Threading::ScopedReadLock shared( const_cast<ResourceLibrary*>(this)->_mutex ); output.reserve( _skins.size() ); for( SkinResourceMap::const_iterator i = _skins.begin(); i != _skins.end(); ++i ) output.push_back( i->second.get() ); }
void ResourceLibrary::getSkins( SkinResourceVector& output, const osgDB::Options* dbOptions ) const { const_cast<ResourceLibrary*>(this)->initialize( dbOptions ); Threading::ScopedReadLock shared( _mutex ); output.reserve( _skins.size() ); for( ResourceMap<SkinResource>::const_iterator i = _skins.begin(); i != _skins.end(); ++i ) output.push_back( i->second.get() ); }
void SkinTextureArray::build(SkinResourceVector& skins, const osgDB::Options* dbOptions) { _texture = 0; _layerIndex.clear(); unsigned int maxWidth = 0; unsigned int maxHeight = 0; std::vector< osg::ref_ptr< osg::Image > > images; for (unsigned int i = 0; i < skins.size(); i++) { osg::ref_ptr< osg::Image > image = skins[i]->createImage( dbOptions ); if (image.valid()) { if (maxWidth < image->s()) maxWidth = image->s(); if (maxHeight < image->t()) maxHeight = image->t(); _layerIndex[ skins[i]->name() ] = i; images.push_back( image.get() ); } } // Now resize all the images to the largest size. for (unsigned int i = 0; i < images.size(); i++) { osg::ref_ptr< osg::Image> resized; if (images[i]->s() != maxWidth || images[i]->t() != maxHeight) { OE_DEBUG << "resizing image to " << maxWidth << "x" << maxHeight << std::endl; ImageUtils::resizeImage( images[i].get(), maxWidth, maxHeight, resized, 0, true); } else { resized = images[i].get(); } resized = ImageUtils::convertToRGBA8( resized.get() ); images[i] = resized.get(); } osg::Texture2DArray* texture = new osg::Texture2DArray(); texture->setTextureDepth( images.size() ); texture->setTextureWidth( maxWidth ); texture->setTextureHeight( maxHeight ); texture->setSourceFormat( GL_RGBA ); texture->setInternalFormat( GL_RGBA8 ); texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR_MIPMAP_LINEAR); texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR); texture->setWrap(osg::Texture::WRAP_S,osg::Texture::REPEAT); texture->setWrap(osg::Texture::WRAP_T,osg::Texture::REPEAT); texture->setResizeNonPowerOfTwoHint(false); for (unsigned int i = 0; i < images.size(); i++) { texture->setImage(i, images[i].get() ); } _texture = texture; }
SkinResource* ResourceLibrary::getSkin( const SkinSymbol* symbol, Random& prng ) const { SkinResourceVector candidates; getSkins( symbol, candidates ); unsigned size = candidates.size(); if ( size == 0 ) { return 0L; } else if ( size == 1 ) { return candidates[0].get(); } else { return candidates[ prng.next(size) ].get(); } }
void ResourceLibrary::getSkins( const SkinSymbol* symbol, SkinResourceVector& output ) const { Threading::ScopedReadLock shared( const_cast<ResourceLibrary*>(this)->_mutex ); for( SkinResourceMap::const_iterator i = _skins.begin(); i != _skins.end(); ++i ) { SkinResource* skin = i->second.get(); if ( matches(symbol, skin) ) { output.push_back( skin ); } } }
void ResourceLibrary::getSkins( const SkinSymbol* symbol, SkinResourceVector& output, const osgDB::Options* dbOptions ) const { const_cast<ResourceLibrary*>(this)->initialize( dbOptions ); Threading::ScopedReadLock shared( _mutex ); for( ResourceMap<SkinResource>::const_iterator i = _skins.begin(); i != _skins.end(); ++i ) { SkinResource* skin = i->second.get(); if ( matches(symbol, skin) ) { output.push_back( skin ); } } }
bool AtlasBuilder::build(const ResourceLibrary* inputLib, const std::string& newAtlasURI, Atlas& out ) const { if ( !inputLib ) return false; // prepare an atlaser: TextureAtlasBuilderEx tab; // maximum size of the texture (x,y) tab.setMaximumAtlasSize( (int)_width, (int)_height ); // texels between atlased images tab.setMargin( 1 ); // clone the Resource library so we can re-write the URIs and add // texture matrix information. out._lib = new ResourceLibrary( inputLib->getConfig() ); out._lib->initialize( _options ); out._lib->uri().unset(); // store a mapping from atlasbuilder source to skin. typedef std::map<TextureAtlasBuilderEx::SourceEx*, SkinResource*> SourceSkinMap; SourceSkinMap sourceSkins; // fetch all the skins from the catalog: SkinResourceVector skins; out._lib->getSkins( skins ); for(SkinResourceVector::iterator i = skins.begin(); i != skins.end(); ++i) { SkinResource* skin = i->get(); osg::Image* image = skin->createImage( _options ); if ( image ) { // ensure we're not trying to atlas an atlas. if ( image->r() > 1 ) { OE_WARN << LC << "Found an image with more than one layer. You cannot create an " "altas from another atlas. Stopping." << std::endl; return false; } tab.addSource( image ); // re-write the URI to point at our new atlas: skin->imageURI() = newAtlasURI; // save the associate so we can come back later: sourceSkins[tab.getSourceList().back().get()] = skin; OE_INFO << LC << "Added skin: \"" << skin->name() << "\"" << std::endl; } else { OE_WARN << LC << "Failed to load image from catalog: \"" << skin->name() << "\" ... skipped" << std::endl; } } unsigned numSources = tab.getNumSources(); OE_INFO << LC << "Added " << numSources << " images ... building atlas ..." << std::endl; // build the atlas images. tab.buildAtlas(); const TextureAtlasBuilderEx::AtlasListEx& atlasList = tab.getAtlasList(); // create the target multi-layer image. out._image = new osg::Image(); out._image->allocateImage( _width, _height, atlasList.size(), GL_RGBA, GL_UNSIGNED_BYTE); // initialize to all zeros memset(out._image->data(), 0, out._image->getTotalSizeInBytesIncludingMipmaps()); // combine each of the atlas images into the corresponding "r" slot of the composed image: for(int r=0; r<(int)atlasList.size(); ++r) { // copy the atlas image into the image array: osg::Image* atlasImage = atlasList[r]->_image.get(); ImageUtils::PixelReader read (atlasImage); ImageUtils::PixelWriter write(out._image.get()); for(int s=0; s<atlasImage->s(); ++s) for(int t=0; t<atlasImage->t(); ++t) write(read(s, t, 0), s, t, r); // for each source in this atlas layer, apply its texture matrix info // to the new catalog. for(int k=0; k<atlasList[r]->_sourceList.size(); ++k) { TextureAtlasBuilderEx::SourceEx* source = atlasList[r]->_sourceList[k].get(); SourceSkinMap::iterator n = sourceSkins.find(source); if ( n != sourceSkins.end() ) { SkinResource* skin = n->second; skin->imageLayer() = r; skin->imageBiasS() = (float)source->_x/(float)atlasImage->s(); //(float)trans.x(); skin->imageBiasT() = (float)source->_y/(float)atlasImage->t(); //(float)trans.y(); skin->imageScaleS() = (float)source->_image->s()/(float)atlasImage->s(); skin->imageScaleT() = (float)source->_image->t()/(float)atlasImage->t(); } } } return true; }