OpenGL SpriteSheet
-
Moin.
Hab das Dingens hier geschrieben, vielleicht hat ja jemand interesse daran, daher poste ich das mal hier.1.) Lade das Tool hier:
http://spritesheetpacker.codeplex.com/Damit kann man SpriteSheets erstellen, sprich viele kleine Texturen auf einer großen. Das steigert die Performance eines Programmes deutlich. Das Programm erzeugt 2 Dateien: Eine .txt Datei und eine .png. Die .png ist die Textur. Die müsst ihr aber selber laden :p. Die .txt Datei bechreibt die Dateien per Name und Rect.
2.) Meinen Code einbinden. Ihr braucht erstmal Boost. Es werden 2 Argumente benötigt für das Template:
a) TVector2 was eine Klasse sein sollte welche x und y zur Verfügung stellt, was die Breite und Höhe der Textur darstellt. Ich verwende hier glm::vec2 (http://glm.g-truc.net/).
b) TTextureCoords, das stellt ein struct oder eine Klasse dar, welche 2 öffentliche Mitglieder hat: s und t als Texturkoordinaten. Man kann hier ebenfalls glm::vec2 nehmen.
Das Programm erwartet dass ihr eure Sprites entgegen dem Uhrzeigersinn mit Hilfe von 2 Polygonen oder GL_QUADS zeichnet. Falls die Bilder falsch herum sind, sind eure Vertex-Daten unterschiedlich. Einfach den Code entsprechend anpassen. Es soll ja auch nur ein Snippet sein :p.
Der Code wird die Datei parsen und der Name, der ganz vorne steht dient als ID für getTexCoordsByName(). Das liefert nen Zeiger auf die TexCoords, den könnt ihr an OpenGL oder eure SpriteKlasse oder wie auch immer ihr eure Daten habt weiterleiten.
Ich erwarte weder Lob, noch Bier, noch sonst irgendwas, wenns euch was nutzt fein, wenns euch nicht gefällt, mir scheiss egal :p.
Für Anregungen bzw Optimierungen bin ich jedoch offen.
#include <boost/noncopyable> #include <boost/lexical_cast.hpp> #include <boost/tokenizer.hpp> #include <string> #include <map> #include <vector> namespace OpenGL { template <typename TTextureCoords, typename TVector2> class SpriteSheet : public boost::noncopyable { protected: typedef std::map<std::string, TTextureCoords*> TSpriteSheetMap; public: SpriteSheet() {} // Delete allocated data virtual ~SpriteSheet() { TSpriteSheetMap::iterator& it = m_map.begin(); for ( it; it != m_map.end(); it++ ) { TTextureCoords* t = it->second; delete t; } m_map.clear(); } // param file: The text file from SpriteSheetPacker // param tex_size: Size of the generated Texture bool loadSpriteSheet(const std::string& file, const TVector2& tex_size) { std::ifstream stream; stream.open(file.c_str()); if ( stream.is_open() ) { std::string line; while ( !stream.eof() ) { // Read line std::getline(stream, line); if ( !line.empty() ) { // Tokenize string const boost::char_delimiters_separator<char> sep(" ", "="); boost::tokenizer<> tokenizer(line, sep); boost::tokenizer<>::iterator it = tokenizer.begin(); // Vector for the tokens std::vector<std::string> tokens; // Walk tokens for ( it; it != tokenizer.end(); it++ ) { tokens.push_back(*it); } // Now read tokens std::string name = tokens[0]; // 1 is skipped because it contains '=' try { int pos_x = boost::lexical_cast<int>(tokens[2]); int pos_y = boost::lexical_cast<int>(tokens[3]); int width = boost::lexical_cast<int>(tokens[4]); int height = boost::lexical_cast<int>(tokens[5]); TTextureCoords* coords = new TTextureCoords[4]; coords[0].s = pos_x / tex_size.x; coords[0].t = pos_y / tex_size.y; coords[1].s = pos_x / tex_size.x; coords[1].t = (pos_y + height ) / tex_size.y; coords[2].s = ( pos_x + width ) / tex_size.x; coords[2].t = pos_y / tex_size.y; coords[3].s = ( pos_x + width ) / tex_size.x; coords[3].t = ( pos_y + height ) / tex_size.y; m_map.insert(std::make_pair(name, coords)); } catch (boost::bad_lexical_cast& e) { throw std::exception(e.what()); } } } stream.close(); return true; } return false; } // param Name = Name of the texture in the generated .txt file from SpriteSheetPacker TTextureCoords* getTexCoordsByName(const std::string& name) { TTextureCoords* coords = m_map[name]; return coords; } protected: TSpriteSheetMap m_map; }; }