]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/mapblock_mesh.cpp
Add dtime_s to entity activation
[dragonfireclient.git] / src / mapblock_mesh.cpp
index abe23855f247ea71513296b130753a066b766f90..9ae9b21c07058d7be6cce5ba33cc27edeeab807e 100644 (file)
@@ -3,16 +3,16 @@ Minetest-c55
 Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
 
 This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License along
+You should have received a copy of the GNU Lesser General Public License along
 with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
@@ -27,6 +27,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "gamedef.h"
 #include "mesh.h"
 #include "content_mapblock.h"
+#include "noise.h"
+#include "settings.h"
+#include "util/directiontables.h"
 
 /*
        MeshMakeData
@@ -183,6 +186,15 @@ static u8 getFaceLight(enum LightBank bank, MapNode n, MapNode n2,
        else
                light = l2;
 
+       // Boost light level for light sources
+       u8 light_source = MYMAX(ndef->get(n).light_source,
+                       ndef->get(n2).light_source);
+       //if(light_source >= light)
+               //return decode_light(undiminish_light(light_source));
+       if(light_source > light)
+               //return decode_light(light_source);
+               light = light_source;
+
        // Make some nice difference to different sides
 
        // This makes light come from a corner
@@ -233,10 +245,13 @@ static u8 getSmoothLight(enum LightBank bank, v3s16 p, MeshMakeData *data)
        u16 ambient_occlusion = 0;
        u16 light = 0;
        u16 light_count = 0;
+       u8 light_source_max = 0;
        for(u32 i=0; i<8; i++)
        {
                MapNode n = data->m_vmanip.getNodeNoEx(p - dirs8[i]);
                const ContentFeatures &f = ndef->get(n);
+               if(f.light_source > light_source_max)
+                       light_source_max = f.light_source;
                // Check f.solidness because fast-style leaves look
                // better this way
                if(f.param_type == CPT_LIGHT && f.solidness != 2)
@@ -255,10 +270,23 @@ static u8 getSmoothLight(enum LightBank bank, v3s16 p, MeshMakeData *data)
        
        light /= light_count;
 
+       // Boost brightness around light sources
+       if(decode_light(light_source_max) >= light)
+               //return decode_light(undiminish_light(light_source_max));
+               return decode_light(light_source_max);
+
        if(ambient_occlusion > 4)
        {
-               ambient_occlusion -= 4;
-               light = (float)light / ((float)ambient_occlusion * 0.5 + 1.0);
+               //ambient_occlusion -= 4;
+               //light = (float)light / ((float)ambient_occlusion * 0.5 + 1.0);
+               float light_amount = (8 - ambient_occlusion) / 4.0;
+               float light_f = (float)light / 255.0;
+               light_f = pow(light_f, 2.2f); // gamma -> linear space
+               light_f = light_f * light_amount;
+               light_f = pow(light_f, 1.0f/2.2f); // linear -> gamma space
+               if(light_f > 1.0)
+                       light_f = 1.0;
+               light = 255.0 * light_f + 0.5;
        }
 
        return light;
@@ -534,6 +562,11 @@ TileSpec getNodeTileN(MapNode mn, v3s16 p, u8 tileindex, MeshMakeData *data)
                spec.material_flags |= MATERIAL_FLAG_CRACK;
                spec.texture = data->m_gamedef->tsrc()->getTextureRawAP(spec.texture);
        }
+       // If animated, replace tile texture with one without texture atlas
+       if(spec.material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES)
+       {
+               spec.texture = data->m_gamedef->tsrc()->getTextureRawAP(spec.texture);
+       }
        return spec;
 }
 
@@ -572,7 +605,46 @@ TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 dir, MeshMakeData *data)
                   0,  5,  0,  2,  0,  3,  1,  4,  // facedir = 3
        };
        u8 tileindex = dir_to_tile[facedir*8 + dir_i];
-       return getNodeTileN(mn, p, tileindex, data);
+
+       // If not rotated or is side tile, we're done
+       if(facedir == 0 || (tileindex != 0 && tileindex != 1))
+               return getNodeTileN(mn, p, tileindex, data);
+
+       // This is the top or bottom tile, and it shall be rotated; thus rotate it
+       TileSpec spec = getNodeTileN(mn, p, tileindex, data);
+       if(tileindex == 0){
+               if(facedir == 1){ // -90
+                       std::string name = data->m_gamedef->tsrc()->getTextureName(spec.texture.id);
+                       name += "^[transformR270";
+                       spec.texture = data->m_gamedef->tsrc()->getTexture(name);
+               }
+               else if(facedir == 2){ // 180
+                       spec.texture.pos += spec.texture.size;
+                       spec.texture.size *= -1;
+               }
+               else if(facedir == 3){ // 90
+                       std::string name = data->m_gamedef->tsrc()->getTextureName(spec.texture.id);
+                       name += "^[transformR90";
+                       spec.texture = data->m_gamedef->tsrc()->getTexture(name);
+               }
+       }
+       else if(tileindex == 1){
+               if(facedir == 1){ // -90
+                       std::string name = data->m_gamedef->tsrc()->getTextureName(spec.texture.id);
+                       name += "^[transformR90";
+                       spec.texture = data->m_gamedef->tsrc()->getTexture(name);
+               }
+               else if(facedir == 2){ // 180
+                       spec.texture.pos += spec.texture.size;
+                       spec.texture.size *= -1;
+               }
+               else if(facedir == 3){ // 90
+                       std::string name = data->m_gamedef->tsrc()->getTextureName(spec.texture.id);
+                       name += "^[transformR270";
+                       spec.texture = data->m_gamedef->tsrc()->getTexture(name);
+               }
+       }
+       return spec;
 }
 
 static void getTileInfo(
@@ -958,6 +1030,28 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
                                crack_basename += "^[crack";
                        m_crack_materials.insert(std::make_pair(i, crack_basename));
                }
+               // - Texture animation
+               if(p.tile.material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES)
+               {
+                       ITextureSource *tsrc = data->m_gamedef->tsrc();
+                       // Add to MapBlockMesh in order to animate these tiles
+                       m_animation_tiles[i] = p.tile;
+                       m_animation_frames[i] = 0;
+                       if(g_settings->getBool("desynchronize_mapblock_texture_animation")){
+                               // Get starting position from noise
+                               m_animation_frame_offsets[i] = 100000 * (2.0 + noise3d(
+                                               data->m_blockpos.X, data->m_blockpos.Y,
+                                               data->m_blockpos.Z, 0));
+                       } else {
+                               // Play all synchronized
+                               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());
+               }
                // - Lighting
                for(u32 j = 0; j < p.vertices.size(); j++)
                {
@@ -1030,7 +1124,8 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
        // Check if animation is required for this mesh
        m_has_animation =
                !m_crack_materials.empty() ||
-               !m_daynight_diffs.empty();
+               !m_daynight_diffs.empty() ||
+               !m_animation_tiles.empty();
 }
 
 MapBlockMesh::~MapBlockMesh()
@@ -1069,6 +1164,34 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
 
                m_last_crack = crack;
        }
+       
+       // Texture animation
+       for(std::map<u32, TileSpec>::iterator
+                       i = m_animation_tiles.begin();
+                       i != m_animation_tiles.end(); i++)
+       {
+               const TileSpec &tile = i->second;
+               // Figure out current frame
+               int frameoffset = m_animation_frame_offsets[i->first];
+               int frame = (int)(time * 1000 / tile.animation_frame_length_ms
+                               + frameoffset) % tile.animation_frame_count;
+               // If frame doesn't change, skip
+               if(frame == m_animation_frames[i->first])
+                       continue;
+
+               m_animation_frames[i->first] = frame;
+
+               scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first);
+               ITextureSource *tsrc = m_gamedef->getTextureSource();
+
+               // 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
+               AtlasPointer ap = tsrc->getTexture(os.str());
+               buf->getMaterial().setTexture(0, ap.atlas);
+       }
 
        // Day-night transition
        if(daynight_ratio != m_last_daynight_ratio)