]> git.lizzy.rs Git - minetest.git/blob - src/client/tile.h
Prevent SIGFPE on entity tile loading issue. (#5178)
[minetest.git] / src / client / tile.h
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 #ifndef TILE_HEADER
21 #define TILE_HEADER
22
23 #include "irrlichttypes.h"
24 #include "irr_v3d.h"
25 #include <ITexture.h>
26 #include <IrrlichtDevice.h>
27 #include "threads.h"
28 #include <string>
29 #include <vector>
30 #include "util/numeric.h"
31
32 class IGameDef;
33 struct TileSpec;
34 struct TileDef;
35
36 /*
37         tile.{h,cpp}: Texture handling stuff.
38 */
39
40 /*
41         Find out the full path of an image by trying different filename
42         extensions.
43
44         If failed, return "".
45
46         TODO: Should probably be moved out from here, because things needing
47               this function do not need anything else from this header
48 */
49 std::string getImagePath(std::string path);
50
51 /*
52         Gets the path to a texture by first checking if the texture exists
53         in texture_path and if not, using the data path.
54
55         Checks all supported extensions by replacing the original extension.
56
57         If not found, returns "".
58
59         Utilizes a thread-safe cache.
60 */
61 std::string getTexturePath(const std::string &filename);
62
63 void clearTextureNameCache();
64
65 /*
66         ITextureSource::generateTextureFromMesh parameters
67 */
68 namespace irr {namespace scene {class IMesh;}}
69 struct TextureFromMeshParams
70 {
71         scene::IMesh *mesh;
72         core::dimension2d<u32> dim;
73         std::string rtt_texture_name;
74         bool delete_texture_on_shutdown;
75         v3f camera_position;
76         v3f camera_lookat;
77         core::CMatrix4<f32> camera_projection_matrix;
78         video::SColorf ambient_light;
79         v3f light_position;
80         video::SColorf light_color;
81         f32 light_radius;
82 };
83
84 /*
85         TextureSource creates and caches textures.
86 */
87
88 class ISimpleTextureSource
89 {
90 public:
91         ISimpleTextureSource(){}
92         virtual ~ISimpleTextureSource(){}
93         virtual video::ITexture* getTexture(
94                         const std::string &name, u32 *id = NULL) = 0;
95 };
96
97 class ITextureSource : public ISimpleTextureSource
98 {
99 public:
100         ITextureSource(){}
101         virtual ~ITextureSource(){}
102         virtual u32 getTextureId(const std::string &name)=0;
103         virtual std::string getTextureName(u32 id)=0;
104         virtual video::ITexture* getTexture(u32 id)=0;
105         virtual video::ITexture* getTexture(
106                         const std::string &name, u32 *id = NULL)=0;
107         virtual video::ITexture* getTextureForMesh(
108                         const std::string &name, u32 *id = NULL) = 0;
109         virtual IrrlichtDevice* getDevice()=0;
110         virtual bool isKnownSourceImage(const std::string &name)=0;
111         /*! Generates an image from a full string like
112          * "stone.png^mineral_coal.png^[crack:1:0".
113          * Shall be called from the main thread.
114          * The returned Image should be dropped.
115          */
116         virtual video::IImage* generateImage(const std::string &name)=0;
117         virtual video::ITexture* generateTextureFromMesh(
118                         const TextureFromMeshParams &params)=0;
119         virtual video::ITexture* getNormalTexture(const std::string &name)=0;
120         virtual video::SColor getTextureAverageColor(const std::string &name)=0;
121         virtual video::ITexture *getShaderFlagsTexture(bool normalmap_present)=0;
122 };
123
124 class IWritableTextureSource : public ITextureSource
125 {
126 public:
127         IWritableTextureSource(){}
128         virtual ~IWritableTextureSource(){}
129         virtual u32 getTextureId(const std::string &name)=0;
130         virtual std::string getTextureName(u32 id)=0;
131         virtual video::ITexture* getTexture(u32 id)=0;
132         virtual video::ITexture* getTexture(
133                         const std::string &name, u32 *id = NULL)=0;
134         virtual IrrlichtDevice* getDevice()=0;
135         virtual bool isKnownSourceImage(const std::string &name)=0;
136         virtual video::ITexture* generateTextureFromMesh(
137                         const TextureFromMeshParams &params)=0;
138
139         virtual void processQueue()=0;
140         virtual void insertSourceImage(const std::string &name, video::IImage *img)=0;
141         virtual void rebuildImagesAndTextures()=0;
142         virtual video::ITexture* getNormalTexture(const std::string &name)=0;
143         virtual video::SColor getTextureAverageColor(const std::string &name)=0;
144         virtual video::ITexture *getShaderFlagsTexture(bool normalmap_present)=0;
145 };
146
147 IWritableTextureSource* createTextureSource(IrrlichtDevice *device);
148
149 #ifdef __ANDROID__
150 video::IImage * Align2Npot2(video::IImage * image, video::IVideoDriver* driver);
151 #endif
152
153 enum MaterialType{
154         TILE_MATERIAL_BASIC,
155         TILE_MATERIAL_ALPHA,
156         TILE_MATERIAL_LIQUID_TRANSPARENT,
157         TILE_MATERIAL_LIQUID_OPAQUE,
158         TILE_MATERIAL_WAVING_LEAVES,
159         TILE_MATERIAL_WAVING_PLANTS
160 };
161
162 // Material flags
163 // Should backface culling be enabled?
164 #define MATERIAL_FLAG_BACKFACE_CULLING 0x01
165 // Should a crack be drawn?
166 #define MATERIAL_FLAG_CRACK 0x02
167 // Should the crack be drawn on transparent pixels (unset) or not (set)?
168 // Ignored if MATERIAL_FLAG_CRACK is not set.
169 #define MATERIAL_FLAG_CRACK_OVERLAY 0x04
170 #define MATERIAL_FLAG_ANIMATION 0x08
171 #define MATERIAL_FLAG_HIGHLIGHTED 0x10
172 #define MATERIAL_FLAG_TILEABLE_HORIZONTAL 0x20
173 #define MATERIAL_FLAG_TILEABLE_VERTICAL 0x40
174
175 /*
176         This fully defines the looks of a tile.
177         The SMaterial of a tile is constructed according to this.
178 */
179 struct FrameSpec
180 {
181         FrameSpec():
182                 texture_id(0),
183                 texture(NULL),
184                 normal_texture(NULL),
185                 flags_texture(NULL)
186         {
187         }
188         u32 texture_id;
189         video::ITexture *texture;
190         video::ITexture *normal_texture;
191         video::ITexture *flags_texture;
192 };
193
194 struct TileSpec
195 {
196         TileSpec():
197                 texture_id(0),
198                 texture(NULL),
199                 normal_texture(NULL),
200                 flags_texture(NULL),
201                 material_type(TILE_MATERIAL_BASIC),
202                 material_flags(
203                         //0 // <- DEBUG, Use the one below
204                         MATERIAL_FLAG_BACKFACE_CULLING
205                 ),
206                 shader_id(0),
207                 animation_frame_count(1),
208                 animation_frame_length_ms(0),
209                 rotation(0),
210                 has_color(false),
211                 color(),
212                 emissive_light(0)
213         {
214         }
215
216         /*!
217          * Two tiles are equal if they can be appended to
218          * the same mesh buffer.
219          */
220         bool operator==(const TileSpec &other) const
221         {
222                 return (
223                         texture_id == other.texture_id &&
224                         material_type == other.material_type &&
225                         material_flags == other.material_flags &&
226                         rotation == other.rotation
227                 );
228         }
229
230         /*!
231          * Two tiles are not equal if they must be in different mesh buffers.
232          */
233         bool operator!=(const TileSpec &other) const
234         {
235                 return !(*this == other);
236         }
237         
238         // Sets everything else except the texture in the material
239         void applyMaterialOptions(video::SMaterial &material) const
240         {
241                 switch (material_type) {
242                 case TILE_MATERIAL_BASIC:
243                         material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
244                         break;
245                 case TILE_MATERIAL_ALPHA:
246                         material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
247                         break;
248                 case TILE_MATERIAL_LIQUID_TRANSPARENT:
249                         material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
250                         break;
251                 case TILE_MATERIAL_LIQUID_OPAQUE:
252                         material.MaterialType = video::EMT_SOLID;
253                         break;
254                 case TILE_MATERIAL_WAVING_LEAVES:
255                         material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
256                         break;
257                 case TILE_MATERIAL_WAVING_PLANTS:
258                         material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
259                         break;
260                 }
261                 material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING)
262                         ? true : false;
263                 if (!(material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL)) {
264                         material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
265                 }
266                 if (!(material_flags & MATERIAL_FLAG_TILEABLE_VERTICAL)) {
267                         material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
268                 }
269         }
270
271         void applyMaterialOptionsWithShaders(video::SMaterial &material) const
272         {
273                 material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING)
274                         ? true : false;
275                 if (!(material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL)) {
276                         material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
277                         material.TextureLayer[1].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
278                 }
279                 if (!(material_flags & MATERIAL_FLAG_TILEABLE_VERTICAL)) {
280                         material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
281                         material.TextureLayer[1].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
282                 }
283         }
284         
285         u32 texture_id;
286         video::ITexture *texture;
287         video::ITexture *normal_texture;
288         video::ITexture *flags_texture;
289         
290         // Material parameters
291         u8 material_type;
292         u8 material_flags;
293         u32 shader_id;
294         // Animation parameters
295         u8 animation_frame_count;
296         u16 animation_frame_length_ms;
297         std::vector<FrameSpec> frames;
298
299         u8 rotation;
300         //! If true, the tile has its own color.
301         bool has_color;
302         /*!
303          * The color of the tile, or if the tile does not own
304          * a color then the color of the node owning this tile.
305          */
306         video::SColor color;
307         //! This much light does the tile emit.
308         u8 emissive_light;
309 };
310 #endif