Speedup mapblock_mesh
authorRealBadAngel <maciej.kasatkin@o2.pl>
Tue, 15 Jul 2014 07:07:52 +0000 (09:07 +0200)
committersapier <Sapier at GMX dot net>
Thu, 17 Jul 2014 20:28:14 +0000 (22:28 +0200)
src/mapblock_mesh.cpp
src/nodedef.cpp
src/tile.cpp
src/tile.h

index 080131a6f4ee20dd1edf5118eb249c57d8034b9e..b29d07319f44b09282152603412e980752642c5d 100644 (file)
@@ -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<<tsrc->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<video::S3DVertex>
                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<<tsrc->getTextureName(tile.texture_id);
-               os<<"^[verticalframe:"<<(int)tile.animation_frame_count<<":"<<frame;
-               // Set the texture
-               buf->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<<fname_normal<<"^[verticalframe:"<<(int)tile.animation_frame_count<<":"<<frame;
-                                               buf->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"));
                        }
                }
        }
index f62c9e82ceb320b27a31f5f17f2635bd50c82175..e972ab927b28605e84e4b4333187a70388c73e96 100644 (file)
@@ -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; i<m_content_features.size(); i++)
                {
@@ -716,6 +719,9 @@ public:
                                f->tiles[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<<tiledef[j].name<<"^[verticalframe:"<<frame_count<<":"<<i;
+                                               frame.texture = tsrc->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<<f->tiledef_special[j].name<<"^[verticalframe:"<<frame_count<<":"<<i;
+                                               frame.texture = tsrc->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;
                                        }
                                }
                        }
index 17ec51614fe1265eaf8f2cf72762c875d6060004..7cb39eabfbf39cbb99a033b55482e0617c8aa22f 100644 (file)
@@ -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;
+}
index 29c6b69f2e293bb20f7c1f160f772d2d4c498886..f3250669e2b45d751f52513858a49359ce05ddd1 100644 (file)
@@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <IrrlichtDevice.h>
 #include "threads.h"
 #include <string>
+#include <map>
 
 class IGameDef;
 
@@ -106,6 +107,7 @@ public:
        virtual bool isKnownSourceImage(const std::string &name)=0;
        virtual video::ITexture* generateTextureFromMesh(
                        const TextureFromMeshParams &params)=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<u32, FrameSpec> frames;
+
        u8 rotation;
 };