1 /* 2 Minetest 3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU Lesser General Public License as published by 7 the Free Software Foundation; either version 2.1 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public License along 16 with this program; if not, write to the Free Software Foundation, Inc., 17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 20 #pragma once 21 22 #include "irrlichttypes.h" 23 #include "irr_v3d.h" 24 #include <ITexture.h> 25 #include <string> 26 #include <vector> 27 #include <SMaterial.h> 28 #include "util/numeric.h" 29 #include "config.h" 30 31 #if ENABLE_GLES 32 #include <IVideoDriver.h> 33 #endif 34 35 class IGameDef; 36 struct TileSpec; 37 struct TileDef; 38 39 typedef std::vector<video::SColor> Palette; 40 41 /* 42 tile.{h,cpp}: Texture handling stuff. 43 */ 44 45 /* 46 Find out the full path of an image by trying different filename 47 extensions. 48 49 If failed, return "". 50 51 TODO: Should probably be moved out from here, because things needing 52 this function do not need anything else from this header 53 */ 54 std::string getImagePath(std::string path); 55 56 /* 57 Gets the path to a texture by first checking if the texture exists 58 in texture_path and if not, using the data path. 59 60 Checks all supported extensions by replacing the original extension. 61 62 If not found, returns "". 63 64 Utilizes a thread-safe cache. 65 */ 66 std::string getTexturePath(const std::string &filename, bool *is_base_pack = nullptr); 67 68 void clearTextureNameCache(); 69 70 /* 71 TextureSource creates and caches textures. 72 */ 73 74 class ISimpleTextureSource 75 { 76 public: 77 ISimpleTextureSource() = default; 78 79 virtual ~ISimpleTextureSource() = default; 80 81 virtual video::ITexture* getTexture( 82 const std::string &name, u32 *id = nullptr) = 0; 83 }; 84 85 class ITextureSource : public ISimpleTextureSource 86 { 87 public: 88 ITextureSource() = default; 89 90 virtual ~ITextureSource() = default; 91 92 virtual u32 getTextureId(const std::string &name)=0; 93 virtual std::string getTextureName(u32 id)=0; 94 virtual video::ITexture* getTexture(u32 id)=0; 95 virtual video::ITexture* getTexture( 96 const std::string &name, u32 *id = nullptr)=0; 97 virtual video::ITexture* getTextureForMesh( 98 const std::string &name, u32 *id = nullptr) = 0; 99 /*! 100 * Returns a palette from the given texture name. 101 * The pointer is valid until the texture source is 102 * destructed. 103 * Should be called from the main thread. 104 */ 105 virtual Palette* getPalette(const std::string &name) = 0; 106 virtual bool isKnownSourceImage(const std::string &name)=0; 107 virtual video::ITexture* getNormalTexture(const std::string &name)=0; 108 virtual video::SColor getTextureAverageColor(const std::string &name)=0; 109 virtual video::ITexture *getShaderFlagsTexture(bool normalmap_present)=0; 110 }; 111 112 class IWritableTextureSource : public ITextureSource 113 { 114 public: 115 IWritableTextureSource() = default; 116 117 virtual ~IWritableTextureSource() = default; 118 119 virtual u32 getTextureId(const std::string &name)=0; 120 virtual std::string getTextureName(u32 id)=0; 121 virtual video::ITexture* getTexture(u32 id)=0; 122 virtual video::ITexture* getTexture( 123 const std::string &name, u32 *id = nullptr)=0; 124 virtual bool isKnownSourceImage(const std::string &name)=0; 125 126 virtual void processQueue()=0; 127 virtual void insertSourceImage(const std::string &name, video::IImage *img)=0; 128 virtual void rebuildImagesAndTextures()=0; 129 virtual video::ITexture* getNormalTexture(const std::string &name)=0; 130 virtual video::SColor getTextureAverageColor(const std::string &name)=0; 131 virtual video::ITexture *getShaderFlagsTexture(bool normalmap_present)=0; 132 }; 133 134 IWritableTextureSource *createTextureSource(); 135 136 #if ENABLE_GLES 137 bool hasNPotSupport(); 138 video::IImage * Align2Npot2(video::IImage * image, irr::video::IVideoDriver* driver); 139 #endif 140 141 enum MaterialType{ 142 TILE_MATERIAL_BASIC, 143 TILE_MATERIAL_ALPHA, 144 TILE_MATERIAL_LIQUID_TRANSPARENT, 145 TILE_MATERIAL_LIQUID_OPAQUE, 146 TILE_MATERIAL_WAVING_LEAVES, 147 TILE_MATERIAL_WAVING_PLANTS, 148 TILE_MATERIAL_OPAQUE, 149 TILE_MATERIAL_WAVING_LIQUID_BASIC, 150 TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT, 151 TILE_MATERIAL_WAVING_LIQUID_OPAQUE, 152 TILE_MATERIAL_PLAIN, 153 TILE_MATERIAL_PLAIN_ALPHA 154 }; 155 156 // Material flags 157 // Should backface culling be enabled? 158 #define MATERIAL_FLAG_BACKFACE_CULLING 0x01 159 // Should a crack be drawn? 160 #define MATERIAL_FLAG_CRACK 0x02 161 // Should the crack be drawn on transparent pixels (unset) or not (set)? 162 // Ignored if MATERIAL_FLAG_CRACK is not set. 163 #define MATERIAL_FLAG_CRACK_OVERLAY 0x04 164 #define MATERIAL_FLAG_ANIMATION 0x08 165 //#define MATERIAL_FLAG_HIGHLIGHTED 0x10 166 #define MATERIAL_FLAG_TILEABLE_HORIZONTAL 0x20 167 #define MATERIAL_FLAG_TILEABLE_VERTICAL 0x40 168 169 /* 170 This fully defines the looks of a tile. 171 The SMaterial of a tile is constructed according to this. 172 */ 173 struct FrameSpec 174 { 175 FrameSpec() = default; 176 177 u32 texture_id = 0; 178 video::ITexture *texture = nullptr; 179 video::ITexture *normal_texture = nullptr; 180 video::ITexture *flags_texture = nullptr; 181 }; 182 183 #define MAX_TILE_LAYERS 2 184 185 //! Defines a layer of a tile. 186 struct TileLayer 187 { 188 TileLayer() = default; 189 190 /*! 191 * Two layers are equal if they can be merged. 192 */ 193 bool operator==(const TileLayer &other) const 194 { 195 return 196 texture_id == other.texture_id && 197 material_type == other.material_type && 198 material_flags == other.material_flags && 199 color == other.color && 200 scale == other.scale; 201 } 202 203 /*! 204 * Two tiles are not equal if they must have different vertices. 205 */ 206 bool operator!=(const TileLayer &other) const 207 { 208 return !(*this == other); 209 } 210 211 // Sets everything else except the texture in the material applyMaterialOptionsTileLayer212 void applyMaterialOptions(video::SMaterial &material) const 213 { 214 switch (material_type) { 215 case TILE_MATERIAL_OPAQUE: 216 case TILE_MATERIAL_LIQUID_OPAQUE: 217 case TILE_MATERIAL_WAVING_LIQUID_OPAQUE: 218 material.MaterialType = video::EMT_SOLID; 219 break; 220 case TILE_MATERIAL_BASIC: 221 case TILE_MATERIAL_WAVING_LEAVES: 222 case TILE_MATERIAL_WAVING_PLANTS: 223 case TILE_MATERIAL_WAVING_LIQUID_BASIC: 224 material.MaterialTypeParam = 0.5; 225 material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; 226 break; 227 case TILE_MATERIAL_ALPHA: 228 case TILE_MATERIAL_LIQUID_TRANSPARENT: 229 case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT: 230 material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; 231 break; 232 default: 233 break; 234 } 235 material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) != 0; 236 if (!(material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL)) { 237 material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; 238 } 239 if (!(material_flags & MATERIAL_FLAG_TILEABLE_VERTICAL)) { 240 material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE; 241 } 242 } 243 applyMaterialOptionsWithShadersTileLayer244 void applyMaterialOptionsWithShaders(video::SMaterial &material) const 245 { 246 material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) != 0; 247 if (!(material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL)) { 248 material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; 249 material.TextureLayer[1].TextureWrapU = video::ETC_CLAMP_TO_EDGE; 250 } 251 if (!(material_flags & MATERIAL_FLAG_TILEABLE_VERTICAL)) { 252 material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE; 253 material.TextureLayer[1].TextureWrapV = video::ETC_CLAMP_TO_EDGE; 254 } 255 } 256 isTileableTileLayer257 bool isTileable() const 258 { 259 return (material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL) 260 && (material_flags & MATERIAL_FLAG_TILEABLE_VERTICAL); 261 } 262 263 // Ordered for size, please do not reorder 264 265 video::ITexture *texture = nullptr; 266 video::ITexture *normal_texture = nullptr; 267 video::ITexture *flags_texture = nullptr; 268 269 u32 shader_id = 0; 270 271 u32 texture_id = 0; 272 273 u16 animation_frame_length_ms = 0; 274 u16 animation_frame_count = 1; 275 276 u8 material_type = TILE_MATERIAL_BASIC; 277 u8 material_flags = 278 //0 // <- DEBUG, Use the one below 279 MATERIAL_FLAG_BACKFACE_CULLING | 280 MATERIAL_FLAG_TILEABLE_HORIZONTAL| 281 MATERIAL_FLAG_TILEABLE_VERTICAL; 282 283 //! If true, the tile has its own color. 284 bool has_color = false; 285 286 std::vector<FrameSpec> *frames = nullptr; 287 288 /*! 289 * The color of the tile, or if the tile does not own 290 * a color then the color of the node owning this tile. 291 */ 292 video::SColor color; 293 294 u8 scale; 295 }; 296 297 /*! 298 * Defines a face of a node. May have up to two layers. 299 */ 300 struct TileSpec 301 { 302 TileSpec() = default; 303 304 /*! 305 * Returns true if this tile can be merged with the other tile. 306 */ isTileableTileSpec307 bool isTileable(const TileSpec &other) const { 308 for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) { 309 if (layers[layer] != other.layers[layer]) 310 return false; 311 if (!layers[layer].isTileable()) 312 return false; 313 } 314 return rotation == 0 315 && rotation == other.rotation 316 && emissive_light == other.emissive_light; 317 } 318 319 //! If true, the tile rotation is ignored. 320 bool world_aligned = false; 321 //! Tile rotation. 322 u8 rotation = 0; 323 //! This much light does the tile emit. 324 u8 emissive_light = 0; 325 //! The first is base texture, the second is overlay. 326 TileLayer layers[MAX_TILE_LAYERS]; 327 }; 328 329 std::vector<std::string> getTextureDirs(); 330