diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp index 080131a6f..b29d07319 100644 --- a/src/mapblock_mesh.cpp +++ b/src/mapblock_mesh.cpp @@ -32,14 +32,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "util/directiontables.h" -void applyContrast(video::SColor& color, float Factor) +static void applyContrast(video::SColor& color, float factor) { - float r = color.getRed(); - float g = color.getGreen(); - float b = color.getBlue(); - color.setRed(irr::core::clamp((int)sqrt(r * r * Factor), 0, 255)); - color.setGreen(irr::core::clamp((int)sqrt(g * g * Factor), 0, 255)); - color.setBlue(irr::core::clamp((int)sqrt(b * b * Factor), 0, 255)); + color.setRed(core::clamp(core::round32(color.getRed()*factor), 0, 255)); + color.setGreen(core::clamp(core::round32(color.getGreen()*factor), 0, 255)); + color.setBlue(core::clamp(core::round32(color.getBlue()*factor), 0, 255)); } /* @@ -1099,8 +1096,6 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): IShaderSource *shdrsrc = m_gamedef->getShaderSource(); bool enable_shaders = g_settings->getBool("enable_shaders"); - bool enable_bumpmapping = g_settings->getBool("enable_bumpmapping"); - bool enable_parallax_occlusion = g_settings->getBool("enable_parallax_occlusion"); for(u32 i = 0; i < collector.prebuffers.size(); i++) { @@ -1141,33 +1136,31 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): m_animation_frame_offsets[i] = 0; } // Replace tile texture with the first animation frame - std::ostringstream os(std::ios::binary); - os<getTextureName(p.tile.texture_id); - os<<"^[verticalframe:"<<(int)p.tile.animation_frame_count<<":0"; - p.tile.texture = tsrc->getTexture( - os.str(), - &p.tile.texture_id); + FrameSpec animation_frame = p.tile.frames.find(0)->second; + p.tile.texture = animation_frame.texture; } for(u32 j = 0; j < p.vertices.size(); j++) { + // Note applyContrast second parameter is precalculated sqrt from original + // values for speed improvement video::SColor &vc = p.vertices[j].Color; if(p.vertices[j].Normal.Y > 0.5) { - applyContrast (vc, 1.2); + applyContrast (vc, 1.095445); } else if (p.vertices[j].Normal.Y < -0.5) { - applyContrast (vc, 0.3); + applyContrast (vc, 0.547723); } else if (p.vertices[j].Normal.X > 0.5) { - applyContrast (vc, 0.5); + applyContrast (vc, 0.707107); } else if (p.vertices[j].Normal.X < -0.5) { - applyContrast (vc, 0.5); + applyContrast (vc, 0.707107); } else if (p.vertices[j].Normal.Z > 0.5) { - applyContrast (vc, 0.8); + applyContrast (vc, 0.894427); } else if (p.vertices[j].Normal.Z < -0.5) { - applyContrast (vc, 0.8); + applyContrast (vc, 0.894427); } if(!enable_shaders) { - // - Classic lighting (shaders handle this by themselves) + // - Classic lighting (shaders handle this by themselves) // Set initial real color and store for later updates u8 day = vc.getRed(); u8 night = vc.getGreen(); @@ -1191,34 +1184,17 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): if (enable_shaders) { material.MaterialType = shdrsrc->getShaderInfo(p.tile.shader_id).material; p.tile.applyMaterialOptionsWithShaders(material); - material.setTexture(2, tsrc->getTexture("disable_img.png")); - if (enable_bumpmapping || enable_parallax_occlusion) { - if (tsrc->isKnownSourceImage("override_normal.png")){ - material.setTexture(1, tsrc->getTexture("override_normal.png")); - material.setTexture(2, tsrc->getTexture("enable_img.png")); - } else { - std::string fname_base = tsrc->getTextureName(p.tile.texture_id); - std::string normal_ext = "_normal.png"; - size_t pos = fname_base.find("."); - std::string fname_normal = fname_base.substr(0, pos) + normal_ext; - - if (tsrc->isKnownSourceImage(fname_normal)) { - // look for image extension and replace it - size_t i = 0; - while ((i = fname_base.find(".", i)) != std::string::npos) { - fname_base.replace(i, 4, normal_ext); - i += normal_ext.length(); - } - material.setTexture(1, tsrc->getTexture(fname_base)); - material.setTexture(2, tsrc->getTexture("enable_img.png")); - } - } + if (p.tile.normal_texture) { + material.setTexture(1, p.tile.normal_texture); + material.setTexture(2, tsrc->getTexture("enable_img.png")); + } else { + material.setTexture(2, tsrc->getTexture("disable_img.png")); } } else { p.tile.applyMaterialOptions(material); } - // Create meshbuffer + // Create meshbuffer // This is a "Standard MeshBuffer", // it's a typedeffed CMeshBuffer scene::SMeshBuffer *buf = new scene::SMeshBuffer(); @@ -1278,8 +1254,6 @@ MapBlockMesh::~MapBlockMesh() bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_ratio) { bool enable_shaders = g_settings->getBool("enable_shaders"); - bool enable_bumpmapping = g_settings->getBool("enable_bumpmapping"); - bool enable_parallax_occlusion = g_settings->getBool("enable_parallax_occlusion"); if(!m_has_animation) { @@ -1342,35 +1316,15 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first); ITextureSource *tsrc = m_gamedef->getTextureSource(); - IShaderSource *shdrsrc = m_gamedef->getShaderSource(); - // Create new texture name from original - std::ostringstream os(std::ios::binary); - os<getTextureName(tile.texture_id); - os<<"^[verticalframe:"<<(int)tile.animation_frame_count<<":"<getMaterial().setTexture(0, tsrc->getTexture(os.str())); - if (enable_shaders){ - buf->getMaterial().setTexture(2, tsrc->getTexture("disable_img.png")); - buf->getMaterial().MaterialType = shdrsrc->getShaderInfo(tile.shader_id).material; - if (enable_bumpmapping || enable_parallax_occlusion){ - if (tsrc->isKnownSourceImage("override_normal.png")){ - buf->getMaterial().setTexture(1, tsrc->getTexture("override_normal.png")); - buf->getMaterial().setTexture(2, tsrc->getTexture("enable_img.png")); - } else { - std::string fname_base,fname_normal; - fname_base = tsrc->getTextureName(tile.texture_id); - unsigned pos; - pos = fname_base.find("."); - fname_normal = fname_base.substr (0, pos); - fname_normal += "_normal.png"; - if (tsrc->isKnownSourceImage(fname_normal)){ - os.str(""); - os<getMaterial().setTexture(1, tsrc->getTexture(os.str())); - buf->getMaterial().setTexture(2, tsrc->getTexture("enable_img.png")); - } - } + FrameSpec animation_frame = tile.frames.find(frame)->second; + buf->getMaterial().setTexture(0, animation_frame.texture); + if (enable_shaders) { + if (animation_frame.normal_texture) { + buf->getMaterial().setTexture(1, animation_frame.normal_texture); + buf->getMaterial().setTexture(2, tsrc->getTexture("enable_img.png")); + } else { + buf->getMaterial().setTexture(2, tsrc->getTexture("disable_img.png")); } } } diff --git a/src/nodedef.cpp b/src/nodedef.cpp index f62c9e82c..e972ab927 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -607,6 +607,9 @@ public: bool new_style_water = g_settings->getBool("new_style_water"); bool new_style_leaves = g_settings->getBool("new_style_leaves"); bool opaque_water = g_settings->getBool("opaque_water"); + bool enable_shaders = g_settings->getBool("enable_shaders"); + bool enable_bumpmapping = g_settings->getBool("enable_bumpmapping"); + bool enable_parallax_occlusion = g_settings->getBool("enable_parallax_occlusion"); for(u32 i=0; itiles[j].texture = tsrc->getTexture( tiledef[j].name, &f->tiles[j].texture_id); + // Normal texture + if (enable_shaders && (enable_bumpmapping || enable_parallax_occlusion)) + f->tiles[j].normal_texture = tsrc->getNormalTexture(tiledef[j].name); // Alpha f->tiles[j].alpha = f->alpha; // Material type @@ -727,28 +733,32 @@ public: if(tiledef[j].animation.type == TAT_VERTICAL_FRAMES) f->tiles[j].material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; // Animation parameters - if(f->tiles[j].material_flags & - MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) - { + int frame_count = 1; + if(f->tiles[j].material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) { // Get texture size to determine frame count by // aspect ratio v2u32 size = f->tiles[j].texture->getOriginalSize(); int frame_height = (float)size.X / (float)tiledef[j].animation.aspect_w * (float)tiledef[j].animation.aspect_h; - int frame_count = size.Y / frame_height; + frame_count = size.Y / frame_height; int frame_length_ms = 1000.0 * tiledef[j].animation.length / frame_count; f->tiles[j].animation_frame_count = frame_count; f->tiles[j].animation_frame_length_ms = frame_length_ms; - - // If there are no frames for an animation, switch - // animation off (so that having specified an animation - // for something but not using it in the texture pack - // gives no overhead) - if(frame_count == 1){ - f->tiles[j].material_flags &= - ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; + } + if(frame_count == 1) { + f->tiles[j].material_flags &= ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; + } else { + std::ostringstream os(std::ios::binary); + for (int i = 0; i < frame_count; i++) { + FrameSpec frame; + os.str(""); + os<getTexture(os.str(), &frame.texture_id); + if (f->tiles[j].normal_texture) + frame.normal_texture = tsrc->getNormalTexture(os.str()); + f->tiles[j].frames[i]=frame; } } } @@ -760,6 +770,9 @@ public: f->special_tiles[j].texture = tsrc->getTexture( f->tiledef_special[j].name, &f->special_tiles[j].texture_id); + // Normal texture + if (enable_shaders && (enable_bumpmapping || enable_parallax_occlusion)) + f->special_tiles[j].normal_texture = tsrc->getNormalTexture(f->tiledef_special[j].name); // Alpha f->special_tiles[j].alpha = f->alpha; // Material type @@ -771,28 +784,32 @@ public: if(f->tiledef_special[j].animation.type == TAT_VERTICAL_FRAMES) f->special_tiles[j].material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; // Animation parameters - if(f->special_tiles[j].material_flags & - MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) - { + int frame_count = 1; + if(f->special_tiles[j].material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) { // Get texture size to determine frame count by // aspect ratio v2u32 size = f->special_tiles[j].texture->getOriginalSize(); int frame_height = (float)size.X / (float)f->tiledef_special[j].animation.aspect_w * (float)f->tiledef_special[j].animation.aspect_h; - int frame_count = size.Y / frame_height; + frame_count = size.Y / frame_height; int frame_length_ms = 1000.0 * f->tiledef_special[j].animation.length / frame_count; f->special_tiles[j].animation_frame_count = frame_count; f->special_tiles[j].animation_frame_length_ms = frame_length_ms; - - // If there are no frames for an animation, switch - // animation off (so that having specified an animation - // for something but not using it in the texture pack - // gives no overhead) - if(frame_count == 1){ - f->special_tiles[j].material_flags &= - ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; + } + if(frame_count == 1) { + f->special_tiles[j].material_flags &= ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES; + } else { + std::ostringstream os(std::ios::binary); + for (int i = 0; i < frame_count; i++) { + FrameSpec frame; + os.str(""); + os<tiledef_special[j].name<<"^[verticalframe:"<getTexture(os.str(), &frame.texture_id); + if (f->special_tiles[j].normal_texture) + frame.normal_texture = tsrc->getNormalTexture(os.str()); + f->special_tiles[j].frames[i]=frame; } } } diff --git a/src/tile.cpp b/src/tile.cpp index 17ec51614..7cb39eabf 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -389,6 +389,7 @@ public: // Shall be called from the main thread. bool generateImage(std::string part_of_name, video::IImage *& baseimg); + video::ITexture* getNormalTexture(const std::string &name); private: // The id of the thread that is allowed to use irrlicht directly @@ -1872,3 +1873,24 @@ void imageTransform(u32 transform, video::IImage *src, video::IImage *dst) dst->setPixel(dx,dy,c); } } + +video::ITexture* TextureSource::getNormalTexture(const std::string &name) +{ + u32 id; + if (isKnownSourceImage("override_normal.png")) + return getTexture("override_normal.png", &id); + std::string fname_base = name; + std::string normal_ext = "_normal.png"; + size_t pos = fname_base.find("."); + std::string fname_normal = fname_base.substr(0, pos) + normal_ext; + if (isKnownSourceImage(fname_normal)) { + // look for image extension and replace it + size_t i = 0; + while ((i = fname_base.find(".", i)) != std::string::npos) { + fname_base.replace(i, 4, normal_ext); + i += normal_ext.length(); + } + return getTexture(fname_base, &id); + } + return NULL; +} diff --git a/src/tile.h b/src/tile.h index 29c6b69f2..f3250669e 100644 --- a/src/tile.h +++ b/src/tile.h @@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "threads.h" #include +#include class IGameDef; @@ -106,6 +107,7 @@ public: virtual bool isKnownSourceImage(const std::string &name)=0; virtual video::ITexture* generateTextureFromMesh( const TextureFromMeshParams ¶ms)=0; + virtual video::ITexture* getNormalTexture(const std::string &name)=0; }; class IWritableTextureSource : public ITextureSource @@ -127,6 +129,7 @@ public: virtual void processQueue()=0; virtual void insertSourceImage(const std::string &name, video::IImage *img)=0; virtual void rebuildImagesAndTextures()=0; + virtual video::ITexture* getNormalTexture(const std::string &name)=0; }; IWritableTextureSource* createTextureSource(IrrlichtDevice *device); @@ -175,11 +178,25 @@ enum MaterialType{ This fully defines the looks of a tile. The SMaterial of a tile is constructed according to this. */ +struct FrameSpec +{ + FrameSpec(): + texture_id(0), + texture(NULL), + normal_texture(NULL) + { + } + u32 texture_id; + video::ITexture *texture; + video::ITexture *normal_texture; +}; + struct TileSpec { TileSpec(): texture_id(0), texture(NULL), + normal_texture(NULL), alpha(255), material_type(TILE_MATERIAL_BASIC), material_flags( @@ -243,6 +260,8 @@ struct TileSpec u32 texture_id; video::ITexture *texture; + video::ITexture *normal_texture; + // Vertex alpha (when MATERIAL_ALPHA_VERTEX is used) u8 alpha; // Material parameters @@ -252,6 +271,8 @@ struct TileSpec // Animation parameters u8 animation_frame_count; u16 animation_frame_length_ms; + std::map frames; + u8 rotation; };