diff options
Diffstat (limited to 'src/tile.h')
-rw-r--r-- | src/tile.h | 219 |
1 files changed, 214 insertions, 5 deletions
diff --git a/src/tile.h b/src/tile.h index a68731f55..b846b467b 100644 --- a/src/tile.h +++ b/src/tile.h @@ -21,10 +21,208 @@ with this program; if not, write to the Free Software Foundation, Inc., #define TILE_HEADER #include "common_irrlicht.h" -//#include "utility.h" -#include "texture.h" +#include "threads.h" +#include "utility.h" #include <string> +/* + Specifies a texture in an atlas. + + This is used to specify single textures also. + + This has been designed to be small enough to be thrown around a lot. +*/ +struct AtlasPointer +{ + u32 id; // Texture id + video::ITexture *atlas; // Atlas in where the texture is + v2f pos; // Position in atlas + v2f size; // Size in atlas + u16 tiled; // X-wise tiling count. If 0, width of atlas is width of image. + + AtlasPointer( + u16 id_, + video::ITexture *atlas_=NULL, + v2f pos_=v2f(0,0), + v2f size_=v2f(1,1), + u16 tiled_=1 + ): + id(id_), + atlas(atlas_), + pos(pos_), + size(size_), + tiled(tiled_) + { + } + + bool operator==(const AtlasPointer &other) + { + return ( + id == other.id + ); + /*return ( + id == other.id && + atlas == other.atlas && + pos == other.pos && + size == other.size && + tiled == other.tiled + );*/ + } + + float x0(){ return pos.X; } + float x1(){ return pos.X + size.X; } + float y0(){ return pos.Y; } + float y1(){ return pos.Y + size.Y; } +}; + +/* + An internal variant of the former with more data. +*/ +struct SourceAtlasPointer +{ + std::string name; + AtlasPointer a; + video::IImage *atlas_img; // The source image of the atlas + // Integer variants of position and size + v2s32 intpos; + v2u32 intsize; + + SourceAtlasPointer( + const std::string &name_, + AtlasPointer a_=AtlasPointer(0, NULL), + video::IImage *atlas_img_=NULL, + v2s32 intpos_=v2s32(0,0), + v2u32 intsize_=v2u32(0,0) + ): + name(name_), + a(a_), + atlas_img(atlas_img_), + intpos(intpos_), + intsize(intsize_) + { + } +}; + +/* + Creates and caches textures. +*/ +class TextureSource +{ +public: + TextureSource(IrrlichtDevice *device); + ~TextureSource(); + + /* + Processes queued texture requests from other threads. + + Shall be called from the main thread. + */ + void processQueue(); + + /* + Example case: + Now, assume a texture with the id 1 exists, and has the name + "stone.png^mineral1". + Then a random thread calls getTextureId for a texture called + "stone.png^mineral1^crack0". + ...Now, WTF should happen? Well: + - getTextureId strips off stuff recursively from the end until + the remaining part is found, or nothing is left when + something is stripped out + + But it is slow to search for textures by names and modify them + like that? + - ContentFeatures is made to contain ids for the basic plain + textures + - Crack textures can be slow by themselves, but the framework + must be fast. + + Example case #2: + - Assume a texture with the id 1 exists, and has the name + "stone.png^mineral1" and is specified as a part of some atlas. + - Now MapBlock::getNodeTile() stumbles upon a node which uses + texture id 1, and finds out that NODEMOD_CRACK must be applied + with progression=0 + - It finds out the name of the texture with getTextureName(1), + appends "^crack0" to it and gets a new texture id with + getTextureId("stone.png^mineral1^crack0") + + */ + + /* + Gets a texture id from cache or + - if main thread, from getTextureIdDirect + - if other thread, adds to request queue and waits for main thread + */ + u32 getTextureId(const std::string &name); + + /* + Example names: + "stone.png" + "stone.png^crack2" + "stone.png^blit:mineral_coal.png" + "stone.png^blit:mineral_coal.png^crack1" + + - If texture specified by name is found from cache, return the + cached id. + - Otherwise generate the texture, add to cache and return id. + Recursion is used to find out the largest found part of the + texture and continue based on it. + + The id 0 points to a NULL texture. It is returned in case of error. + */ + u32 getTextureIdDirect(const std::string &name); + + /* + Finds out the name of a cached texture. + */ + std::string getTextureName(u32 id); + + /* + If texture specified by the name pointed by the id doesn't + exist, create it, then return the cached texture. + + Can be called from any thread. If called from some other thread + and not found in cache, the call is queued to the main thread + for processing. + */ + AtlasPointer getTexture(u32 id); + + AtlasPointer getTexture(const std::string &name) + { + return getTexture(getTextureId(name)); + } + +private: + /* + Build the main texture atlas which contains most of the + textures. + + This is called by the constructor. + */ + void buildMainAtlas(); + + // The id of the thread that is allowed to use irrlicht directly + threadid_t m_main_thread; + // The irrlicht device + IrrlichtDevice *m_device; + + // A texture id is index in this array. + // The first position contains a NULL texture. + core::array<SourceAtlasPointer> m_atlaspointer_cache; + // Maps a texture name to an index in the former. + core::map<std::string, u32> m_name_to_id; + // The two former containers are behind this mutex + JMutex m_atlaspointer_cache_mutex; + + // Main texture atlas. This is filled at startup and is then not touched. + video::IImage *m_main_atlas_image; + video::ITexture *m_main_atlas_texture; + + // Queued texture fetches (to be processed by the main thread) + RequestQueue<std::string, u32, u8, u8> m_get_texture_queue; +}; + enum MaterialType{ MATERIAL_ALPHA_NONE, MATERIAL_ALPHA_VERTEX, @@ -38,12 +236,17 @@ enum MaterialType{ /* This fully defines the looks of a tile. The SMaterial of a tile is constructed according to this. + + TODO: Change this to use an AtlasPointer */ struct TileSpec { TileSpec(): + texture(0), alpha(255), material_type(MATERIAL_ALPHA_NONE), + // Use this so that leaves don't need a separate material + //material_type(MATERIAL_ALPHA_SIMPLE), material_flags( MATERIAL_FLAG_BACKFACE_CULLING ) @@ -53,7 +256,7 @@ struct TileSpec bool operator==(TileSpec &other) { return ( - spec == other.spec && + texture == other.texture && alpha == other.alpha && material_type == other.material_type && material_flags == other.material_flags @@ -80,8 +283,14 @@ struct TileSpec material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) ? true : false; } - // Specification of texture - TextureSpec spec; + // NOTE: Deprecated, i guess? + void setTexturePos(u8 tx_, u8 ty_, u8 tw_, u8 th_) + { + texture.pos = v2f((float)tx_/256.0, (float)ty_/256.0); + texture.size = v2f(((float)tw_ + 1.0)/256.0, ((float)th_ + 1.0)/256.0); + } + + AtlasPointer texture; // Vertex alpha u8 alpha; // Material type |