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; }