1 // 2 // SuperTuxKart - a fun racing game with go-kart 3 // Copyright (C) 2004-2015 Steve Baker <sjbaker1@airmail.net> 4 // Copyright (C) 2010-2015 Steve Baker, Joerg Henrichs 5 // 6 // This program is free software; you can redistribute it and/or 7 // modify it under the terms of the GNU General Public License 8 // as published by the Free Software Foundation; either version 3 9 // of the License, or (at your option) any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program; if not, write to the Free Software 18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 20 #ifndef HEADER_MATERIAL_HPP 21 #define HEADER_MATERIAL_HPP 22 23 #include "utils/no_copy.hpp" 24 #include "utils/random_generator.hpp" 25 26 #include <array> 27 #include <assert.h> 28 #include <map> 29 #include <string> 30 #include <vector> 31 32 namespace irr 33 { 34 namespace video { class ITexture; class SMaterial; } 35 namespace scene { class ISceneNode; class IMeshBuffer; } 36 } 37 using namespace irr; 38 39 class XMLNode; 40 class SFXBase; 41 class ParticleKind; 42 43 /** 44 * \ingroup graphics 45 */ 46 class Material : public NoCopy 47 { 48 public: 49 enum ParticleConditions 50 { 51 EMIT_ON_DRIVE = 0, 52 EMIT_ON_SKID, 53 54 EMIT_KINDS_COUNT 55 }; 56 57 enum CollisionReaction 58 { 59 NORMAL, 60 RESCUE, 61 PUSH_BACK, 62 PUSH_SOCCER_BALL 63 }; 64 65 private: 66 67 /** Pointer to the texture. */ 68 video::ITexture *m_texture; 69 70 /** Name of the texture. */ 71 std::string m_texname; 72 73 std::string m_full_path; 74 75 /** Name of a special sfx to play when a kart is on this terrain, or 76 * "" if no special sfx exists. */ 77 std::string m_sfx_name; 78 79 /** Either ' ' (no mirroring), 'U' or 'V' if a texture needs to be 80 * mirrored when driving in reverse. Typically used for arrows indicating 81 * the direction. */ 82 char m_mirror_axis_when_reverse; 83 84 /** Set if being on this surface means being under some other mesh. 85 * This is used to simulate that a kart is in water: the ground under 86 * the water is marked as 'm_below_surface', which will then trigger a raycast 87 * up to find the position of the actual water surface. */ 88 bool m_below_surface; 89 90 /** If a kart is falling over a material with this flag set, it 91 * will trigger the special camera fall effect. */ 92 bool m_falling_effect; 93 /** A material that is a surface only, i.e. the karts can fall through 94 * but the information is still needed (for GFX mostly). An example is 95 * a water surface: karts can drive while partly in water (so the water 96 * surface is not a physical object), but the location of the water 97 * effect is on the surface. */ 98 bool m_surface; 99 100 /** If the material is a zipper, i.e. gives a speed boost. */ 101 bool m_zipper; 102 103 /** If a kart is rescued when driving on this surface. */ 104 bool m_drive_reset; 105 106 /** True if this is a texture that will start the jump animation when 107 * leaving it and being in the air. */ 108 bool m_is_jump_texture; 109 110 /** True if driving on this texture should adjust the gravity of the kart 111 * to be along the normal of the triangle. This allows karts to drive e.g 112 * upside down. */ 113 bool m_has_gravity; 114 115 /** If the property should be ignored in the physics. Example would be 116 * plants that a kart can just drive through. */ 117 bool m_ignore; 118 119 /** True if the material shouldn't be "slippy" at an angle */ 120 bool m_high_tire_adhesion; 121 122 bool m_complain_if_not_found; 123 124 bool m_deprecated; 125 126 bool m_installed; 127 128 /** True if this material can be colorized (like red/blue in team game). */ 129 bool m_colorizable; 130 131 /** True if this material should use texture compression. */ 132 bool m_tex_compression; 133 134 /** Minimum resulting saturation when colorized (from 0 to 1) */ 135 float m_colorization_factor; 136 137 /** If a kart is rescued when crashing into this surface. */ 138 CollisionReaction m_collision_reaction; 139 140 /** Particles to show on touch */ 141 std::string m_collision_particles; 142 143 /** 144 * Associated with m_mirror_axis_when_reverse, to avoid mirroring the same material twice 145 * (setAllMaterialFlags can be called multiple times on the same mesh buffer) 146 */ 147 std::map<void*, bool> m_mirrorred_mesh_buffers; 148 149 ParticleKind* m_particles_effects[EMIT_KINDS_COUNT]; 150 151 /** Texture clamp bitmask */ 152 unsigned int m_clamp_tex; 153 154 /** List of hue pre-defined for colorization (from 0 to 1) */ 155 std::vector<float> m_hue_settings; 156 157 /** Random generator for getting pre-defined hue */ 158 RandomGenerator m_random_hue; 159 160 /** How much the top speed is reduced per second. */ 161 int m_slowdown_ticks; 162 163 /** Maximum speed at which no more slow down occurs. */ 164 float m_max_speed_fraction; 165 166 /** Minimum speed on this terrain. This is used for zippers on a ramp to 167 * guarantee the right jump distance. A negative value indicates no 168 * minimum speed. */ 169 float m_zipper_min_speed; 170 /** The minimum speed at which a special sfx is started to be played. */ 171 float m_sfx_min_speed; 172 /** The speed at which the maximum pitch is used. */ 173 float m_sfx_max_speed; 174 /** The minimum pitch to be used (at minimum speed). */ 175 float m_sfx_min_pitch; 176 /** The maximum pitch to be used (at maximum speed). */ 177 float m_sfx_max_pitch; 178 /** (max_pitch-min_pitch) / (max_speed - min_speed). Used to adjust 179 * the pitch of a sfx depending on speed of the kart. 180 */ 181 float m_sfx_pitch_per_speed; 182 /** Additional speed allowed on top of the kart-specific maximum kart speed 183 * if a zipper is used. If this value is <0 the kart specific value will 184 * be used. */ 185 float m_zipper_max_speed_increase; 186 /** Time a zipper stays activated. If this value is <0 the kart specific 187 * value will be used. */ 188 float m_zipper_duration; 189 /** A one time additional speed gain - the kart will instantly add this 190 * amount of speed to its current speed. If this value is <0 the kart 191 * specific value will be used. */ 192 float m_zipper_speed_gain; 193 /** Time it takes for the zipper advantage to fade out. If this value 194 * is <0 the kart specific value will be used. */ 195 float m_zipper_fade_out_time; 196 /** Additional engine force. */ 197 float m_zipper_engine_force; 198 199 std::string m_mask; 200 201 std::string m_colorization_mask; 202 203 void init (); 204 void install (bool srgb = false, bool premul_alpha = false); 205 void initCustomSFX(const XMLNode *sfx); 206 void initParticlesEffect(const XMLNode *node); 207 208 // SP usage 209 std::string m_shader_name; 210 std::string m_uv_two_tex; 211 // Full path for textures in sp shader 212 std::string m_sampler_path[6]; 213 std::string m_container_id; 214 void loadContainerId(); 215 216 public: 217 Material(const XMLNode *node, bool deprecated); 218 Material(const std::string& fname, 219 bool is_full_path=false, 220 bool complain_if_not_found=true, 221 bool load_texture = true, 222 const std::string& shader_name = "solid"); 223 ~Material (); 224 225 void unloadTexture(); 226 227 void setSFXSpeed(SFXBase *sfx, float speed, bool should_be_paused) const; 228 void setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* mb); 229 230 /** Returns the ITexture associated with this material. */ 231 video::ITexture *getTexture(bool srgb = true, bool premul_alpha = false); 232 // ------------------------------------------------------------------------ isIgnore() const233 bool isIgnore () const { return m_ignore; } 234 // ------------------------------------------------------------------------ 235 /** Returns true if this material is a zipper. */ isZipper() const236 bool isZipper () const { return m_zipper; } 237 // ------------------------------------------------------------------------ 238 /** Returns if this material should trigger a rescue if a kart 239 * is driving on it. */ isDriveReset() const240 bool isDriveReset () const { return m_drive_reset; } 241 // ------------------------------------------------------------------------ 242 /** Returns if this material can be colorized. 243 */ isColorizable() const244 bool isColorizable () const { return m_colorizable; } 245 // ------------------------------------------------------------------------ 246 /** Returns the minimum resulting saturation when colorized. 247 */ getColorizationFactor() const248 float getColorizationFactor () const { return m_colorization_factor; } 249 // ------------------------------------------------------------------------ hasRandomHue() const250 bool hasRandomHue() const { return !m_hue_settings.empty(); } 251 // ------------------------------------------------------------------------ 252 /** Returns a random hue when colorized. 253 */ getRandomHue()254 float getRandomHue() 255 { 256 if (m_hue_settings.empty()) 257 return 0.0f; 258 const unsigned int hue = m_random_hue.get((int)m_hue_settings.size()); 259 assert(hue < m_hue_settings.size()); 260 return m_hue_settings[hue]; 261 } 262 // ------------------------------------------------------------------------ 263 /** Returns if this material should trigger a rescue if a kart 264 * crashes against it. */ getCollisionReaction() const265 CollisionReaction getCollisionReaction() const { return m_collision_reaction; } 266 267 // ------------------------------------------------------------------------ getCrashResetParticles() const268 std::string getCrashResetParticles() const { return m_collision_particles; } 269 270 // ------------------------------------------------------------------------ highTireAdhesion() const271 bool highTireAdhesion () const { return m_high_tire_adhesion; } 272 // ------------------------------------------------------------------------ 273 const std::string& getTexFname() const274 getTexFname () const { return m_texname; } 275 // ------------------------------------------------------------------------ 276 const std::string& getTexFullPath() const277 getTexFullPath () const { return m_full_path; } 278 279 // ------------------------------------------------------------------------ isTransparent() const280 bool isTransparent () const 281 { 282 return m_shader_name == "additive" || m_shader_name == "alphablend" || 283 m_shader_name == "displace"; 284 } 285 286 // ------------------------------------------------------------------------ 287 /** Returns the fraction of maximum speed on this material. */ getMaxSpeedFraction() const288 float getMaxSpeedFraction() const { return m_max_speed_fraction; } 289 // ------------------------------------------------------------------------ 290 /** Returns how long it will take for a slowdown to take effect. 291 * It is the time it takes till the full slowdown applies to 292 * karts. So a short time will slowdown a kart much faster. */ getSlowDownTicks() const293 int getSlowDownTicks() const { return m_slowdown_ticks; } 294 // ------------------------------------------------------------------------ 295 /** Returns true if this material is under some other mesh and therefore 296 * requires another raycast to find the surface it is under (used for 297 * gfx, e.g. driving under water to find where the water splash should 298 * be shown at. */ isBelowSurface() const299 bool isBelowSurface () const { return m_below_surface; } 300 // ------------------------------------------------------------------------ 301 /** Returns true if this material is a surface, i.e. it is going to be 302 * ignored for the physics, but the information is needed e.g. for 303 * gfx. See m_below_surface for more details. */ isSurface() const304 bool isSurface () const { return m_surface; } 305 // ------------------------------------------------------------------------ 306 /** Returns the name of a special sfx to play while a kart is on this 307 * terrain. The string will be "" if no special sfx exists. */ getSFXName() const308 const std::string &getSFXName() const { return m_sfx_name; } 309 // ------------------------------------------------------------------------ 310 /** \brief Get the kind of particles that are to be used on this material, 311 * in the given conditions. 312 * \return The particles to use, or NULL if none. */ getParticlesWhen(ParticleConditions cond) const313 const ParticleKind* getParticlesWhen(ParticleConditions cond) const 314 { 315 return m_particles_effects[cond]; 316 } // getParticlesWhen 317 // ------------------------------------------------------------------------ 318 /** Returns true if a kart falling over this kind of material triggers 319 * the special falling camera. */ hasFallingEffect() const320 bool hasFallingEffect() const {return m_falling_effect; } 321 // ------------------------------------------------------------------------ 322 /** Returns if being in the air after this texture should start the 323 * jump animation. */ isJumpTexture() const324 bool isJumpTexture() const { return m_is_jump_texture; } 325 // ------------------------------------------------------------------------ 326 /** Returns true if this texture adjusts the gravity vector of the kart 327 * to be parallel to the normal of the triangle - which allows karts to 328 * e.g. drive upside down. */ hasGravity() const329 bool hasGravity() const { return m_has_gravity; } 330 // ------------------------------------------------------------------------ 331 /** Returns the zipper parametersfor the current material. */ getZipperParameter(float * zipper_max_speed_increase,float * zipper_duration,float * zipper_speed_gain,float * zipper_fade_out_time,float * zipper_engine_force) const332 void getZipperParameter(float *zipper_max_speed_increase, 333 float *zipper_duration, 334 float *zipper_speed_gain, 335 float *zipper_fade_out_time, 336 float *zipper_engine_force) const 337 { 338 *zipper_max_speed_increase = m_zipper_max_speed_increase; 339 *zipper_duration = m_zipper_duration; 340 *zipper_speed_gain = m_zipper_speed_gain; 341 *zipper_fade_out_time = m_zipper_fade_out_time; 342 *zipper_engine_force = m_zipper_engine_force; 343 } // getZipperParameter 344 // ------------------------------------------------------------------------ 345 /** Returns the minimum speed of a kart on this material. This is used 346 * for zippers on a ramp to guarantee the right jump distance even 347 * on lower speeds. A negative value indicates no minimum speed. */ getZipperMinSpeed() const348 float getZipperMinSpeed() const { return m_zipper_min_speed; } 349 // ------------------------------------------------------------------------ 350 /** True if this texture should have the U coordinates mirrored. */ getMirrorAxisInReverse() const351 char getMirrorAxisInReverse() const { return m_mirror_axis_when_reverse; } 352 // ------------------------------------------------------------------------ getAlphaMask() const353 const std::string& getAlphaMask() const { return m_mask; } 354 // ------------------------------------------------------------------------ getColorizationMask() const355 const std::string& getColorizationMask() const 356 { return m_colorization_mask; } 357 // ------------------------------------------------------------------------ setShaderName(const std::string & name)358 void setShaderName(const std::string& name) { m_shader_name = name; } 359 // ------------------------------------------------------------------------ getShaderName() const360 const std::string& getShaderName() const { return m_shader_name; } 361 // ------------------------------------------------------------------------ 362 /* This is used for finding correct material for spm*/ getUVTwoTexture() const363 const std::string& getUVTwoTexture() const 364 { return m_uv_two_tex; } 365 // ------------------------------------------------------------------------ use2UV() const366 bool use2UV() const { return !m_uv_two_tex.empty(); } 367 // ------------------------------------------------------------------------ getSamplerPath(unsigned layer) const368 const std::string& getSamplerPath(unsigned layer) const 369 { 370 assert(layer < 6); 371 return m_sampler_path[layer]; 372 } 373 // ------------------------------------------------------------------------ 374 /* Return the container id used by texture compression to cache texture in 375 * cache folder with unique name, if no texture compression is used for 376 * this material, then it will always return empty. */ getContainerId() const377 const std::string& getContainerId() const 378 { 379 static std::string empty; 380 if (!m_tex_compression) 381 return empty; 382 return m_container_id; 383 } 384 }; 385 386 387 #endif 388 389 /* EOF */ 390 391